From e76b2abd9fa60f5b16e230680432c464f1c8b6d6 Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Tue, 28 Nov 2017 22:49:28 +0100 Subject: [PATCH 0001/2222] some corrections for the german translation --- sonoff/language/de-DE.h | 156 ++++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 1410ee50e..c188df3ae 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -31,9 +31,9 @@ \*********************************************************************/ // "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_YEAR_MONTH_SEPARATOR "." +#define D_MONTH_DAY_SEPARATOR "." +#define D_DATE_TIME_SEPARATOR " " #define D_HOUR_MINUTE_SEPARATOR ":" #define D_MINUTE_SECOND_SEPARATOR ":" @@ -59,17 +59,17 @@ #define D_BLINK "Blinken" #define D_BLINKOFF "BlinkenAus" #define D_BOOTVERSION "Boot" -#define D_BOOT_COUNT "Boot-Zähler" +#define D_BOOT_COUNT "Anzahl Startvorgänge" #define D_BOOTCOUNT "BootZähler" #define D_BRIGHTLIGHT "hell" #define D_BUILDDATETIME "BuildDatumUhrzeit" -#define D_BUTTON "Taste" +#define D_BUTTON "Knopf" #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_COREVERSION "Core" #define D_COUNT "zählen" #define D_COUNTER "Zähler" #define D_CURRENT "Strom" // As in Voltage and Current @@ -82,7 +82,7 @@ #define D_DONE "erledigt" #define D_DST_TIME "DST" #define D_EMPTY "leer" -#define D_EMULATION "Emulierung" +#define D_EMULATION "Emulation" #define D_ENABLED "aktiviert" #define D_ENDDST "EndDST" // End Daylight Savings Time #define D_ERASE "löschen" @@ -97,14 +97,14 @@ #define D_FILE "Datei" #define D_FLASHMODE "FlashMode" #define D_FLASHSIZE "FlashSize" -#define D_FREE_MEMORY "freier Speicher" +#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_HOST "Host" #define D_HOSTNAME "Hostname" #define D_HUMIDITY "Feuchtigkeit" #define D_ID "ID" @@ -115,10 +115,10 @@ #define D_INITIALIZED "initialisiert" #define D_IP_ADDRESS "IP-Addresse" #define D_LIGHT "Licht" -#define D_LOCAL_TIME "örtlich" +#define D_LOCAL_TIME "lokale Zeit" #define D_LOW "niedrig" #define D_LWT "LWT" -#define D_MAC "Mac" +#define D_MAC "MAC" #define D_MASK "Maske" #define D_MODULE "Modul" #define D_MQTT "MQTT" @@ -134,13 +134,13 @@ #define D_OR "oder" #define D_PASSWORD "Passwort" #define D_PERIOD "Punkt" -#define D_PORT "port" +#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_PROGRAM_FLASH_SIZE "Programm Flash Größe" #define D_PROGRAMFLASHSIZE "ProgramFlashSize" #define D_PROGRAM_SIZE "Programmgröße" #define D_PROGRAMSIZE "ProgramSize" @@ -150,16 +150,16 @@ #define D_RESTARTING "starte neu" #define D_RESTART_REASON "Grund für Neustart" #define D_RESTARTREASON "RestartReason" -#define D_RESTORE "wiederherstellen" +#define D_RESTORE "Wiederherstellung" #define D_RETAINED "beibehalten" -#define D_SAVE "speichern" +#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_SERIAL "Seriell" #define D_BYTES "Bytes" #define D_SSID "SSID" #define D_START "Start" @@ -171,7 +171,7 @@ #define D_SUBNETMASK "Subnetmaske" #define D_SUBSCRIBE_TO "subscribe to" #define D_SUCCESSFUL "erfolgreich" -#define D_SWITCH "switch" +#define D_SWITCH "Schalter" #define D_SYNC "sync" #define D_SYS "sys" // Sys log #define D_TEMPERATURE "Temperatur" @@ -179,15 +179,15 @@ #define D_TIME "Zeit" #define D_TO "bis" #define D_TODAY "heute" -#define D_TOGGLE "schalten" +#define D_TOGGLE "An/Aus" #define D_TOPIC "topic" #define D_TOTAL "Total" #define D_TRANSMIT "Übertragen" #define D_TRUE "wahr" -#define D_TYPE "Typ" +#define D_TYPE "Art" #define D_UNKNOWN "unbekannt" -#define D_UPGRADE "upgrade" -#define D_UPLOAD "upload" +#define D_UPGRADE "update" +#define D_UPLOAD "Upload" #define D_UPTIME "Laufzeit" #define D_USER "Benutzer" #define D_UTC_TIME "UTC" @@ -196,26 +196,26 @@ #define D_VERSION "Version" #define D_VOLTAGE "Spannung" #define D_WARMLIGHT "warm" -#define D_WEB "web" // Web log +#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_SAVED_TO_FLASH_AT "in Flash gespeichert am" +#define D_LOADED_FROM_FLASH_AT "aus Flash geladen 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_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_SET_BAUDRATE_TO "Baudrate eingestellt auf" +#define D_RECEIVED_TOPIC "empfangenes topic" #define D_DATA_SIZE "Datengröße" #define D_ANALOG_INPUT "Analog" @@ -229,16 +229,16 @@ // support.ino #define D_OSWATCH "osWatch" #define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig fehlgeschlagen mit Status" +#define D_WPS_FAILED_WITH_STATUS "WPS 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_NO_IP_ADDRESS "Verbindung fehlgeschlagen da keine IP-Adresse zugeteilt 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_CONNECT_FAILED_WRONG_PASSWORD "Verbindung fehlgeschlagen mit AP weil das Passwort falsch ist" +#define D_CONNECT_FAILED_AP_TIMEOUT "Verbindung fehlgeschlagen da der AP nicht antwortet (timeout)" #define D_ATTEMPTING_CONNECTION "Verbindungsversuch..." #define D_CHECKING_CONNECTION "prüfe Verbindung..." #define D_QUERY_DONE "Suchanfrage abgeschlossen. MQTT-Services gefunden" @@ -247,7 +247,7 @@ #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" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nicht gefunden" // webserver.ino #define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMUM-Firmware - bitte upgraden" @@ -262,11 +262,11 @@ #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_DEVICE_WILL_RESTART "Gerät wird jetzt neu gestartet" +#define D_BUTTON_TOGGLE "An/Aus" #define D_CONFIGURATION "Einstellungen" #define D_INFORMATION "Informationen" -#define D_FIRMWARE_UPGRADE "Firmware-Upgrade" +#define D_FIRMWARE_UPGRADE "Firmware Update" #define D_CONSOLE "Konsole" #define D_CONFIRM_RESTART "Neustart bestätigen" @@ -282,16 +282,16 @@ #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_MODULE_PARAMETERS "Modul Einstellungen" +#define D_MODULE_TYPE "Modul 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_WIFI_PARAMETERS "WLAN Einstellungen" +#define D_SCAN_FOR_WIFI_NETWORKS "WLAN-Netzwerk suchen und auswählen" +#define D_SCAN_DONE "Suche 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" @@ -299,42 +299,42 @@ #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_AP1_SSID "WLAN 1 - SSID" +#define D_AP1_PASSWORD "WLAN 1 - Passwort" +#define D_AP2_SSID "WLAN 2 - SSID" +#define D_AP2_PASSWORD "WLAN 2 - Passwort" -#define D_MQTT_PARAMETERS "MQTT-Parameter" +#define D_MQTT_PARAMETERS "MQTT Einstellungen" #define D_CLIENT "client" #define D_FULL_TOPIC "full topic" -#define D_LOGGING_PARAMETERS "Logging-Parameter" -#define D_LOG_LEVEL "log level" +#define D_LOGGING_PARAMETERS "Logging Einstellungen" +#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_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_OTHER_PARAMETERS "Sonstige Einstellungen" +#define D_WEB_ADMIN_PASSWORD "Passwort für Web Oberfläche" #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_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_PROGRAM_VERSION "Tasmota Version" #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_FLASH_WRITE_COUNT "Anz. Flash Schreibzugriffe" #define D_MAC_ADDRESS "MAC-Adresse" -#define D_MQTT_HOST "MQTT host" -#define D_MQTT_PORT "MQTT port" +#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" @@ -344,26 +344,26 @@ #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_FLASH_CHIP_SIZE "Flash Größe" +#define D_FREE_PROGRAM_SPACE "Freier Programm Speicher" -#define D_UPGRADE_BY_WEBSERVER "Upgrade über Web-Server" +#define D_UPGRADE_BY_WEBSERVER "Update ü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_START_UPGRADE "Update starten" +#define D_UPGRADE_BY_FILE_UPLOAD "Update Datei hochladen" #define D_UPLOAD_STARTED "Upload gestartet" -#define D_UPGRADE_STARTED "Upgrade gestartet" +#define D_UPGRADE_STARTED "Update 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_4 "Flash-Größe des Programmes ist größer als der reale Flashspeicher" #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_UPLOAD_ERROR_CODE "Upload Fehler Nummer" #define D_ENTER_COMMAND "Befehl eingeben" #define D_ENABLE_WEBLOG_FOR_RESPONSE "aktivere weblog 2 falls Reaktion erwartet" @@ -396,10 +396,10 @@ #define D_IRHVAC_MODE "MODUS" #define D_IRHVAC_FANSPEED "LÜFTERGESCHWINDIGKEIT" #define D_IRHVAC_TEMP "TEMPERATUR" -#define D_IRRECEIVED "IrReceived" +#define D_IRRECEIVED "IR empfangen" // xdrv_snfbridge.ino -#define D_RFRECEIVED "RfReceived" +#define D_RFRECEIVED "RF empfangen" #define D_START_LEARNING "starte Anlernen" #define D_SET_TO_DEFAULT "auf Standard zurücksetzen" #define D_DEFAULT_SENT "Standard gesendet" @@ -412,7 +412,7 @@ // 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_MULTICAST_JOIN_FAILED "Multicast Verbindung fehlgeschlagen" #define D_FAILED_TO_SEND_RESPONSE "Antwort senden fehlgeschlagen" #define D_WEMO "WeMo" @@ -464,14 +464,14 @@ #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_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_IRRECV "IRRecv" #define D_SENSOR_SPI_CS "SPI CS" #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BLight" @@ -481,12 +481,12 @@ #define D_UNIT_HOUR "h" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" -#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MICROSECOND "µs" #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_SECOND "sek" #define D_UNIT_SECTORS "Sektoren" #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" From d34c51cda32b3408e26da467454071efc8b81e9b Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Tue, 28 Nov 2017 23:04:00 +0100 Subject: [PATCH 0002/2222] fix missing space --- sonoff/language/de-DE.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index c188df3ae..29bd8586d 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -173,7 +173,7 @@ #define D_SUCCESSFUL "erfolgreich" #define D_SWITCH "Schalter" #define D_SYNC "sync" -#define D_SYS "sys" // Sys log +#define D_SYS "Sys " // Sys log #define D_TEMPERATURE "Temperatur" #define D_TEMPERATURE_UNIT "TempUnit" #define D_TIME "Zeit" From 95e6002b51722f8bf1a34ca9ed914cf77ddeebcf Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Wed, 29 Nov 2017 00:08:26 +0100 Subject: [PATCH 0003/2222] fix translate fix --- sonoff/language/de-DE.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 29bd8586d..a236a6472 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -177,7 +177,7 @@ #define D_TEMPERATURE "Temperatur" #define D_TEMPERATURE_UNIT "TempUnit" #define D_TIME "Zeit" -#define D_TO "bis" +#define D_TO "zu" #define D_TODAY "heute" #define D_TOGGLE "An/Aus" #define D_TOPIC "topic" @@ -694,4 +694,4 @@ #define D_CMND_MAXENERGY "MaxEnergy" #define D_CMND_MAXENERGYSTART "MaxEnergyStart" -#endif // _LANGUAGE_DE_DE_H_ \ No newline at end of file +#endif // _LANGUAGE_DE_DE_H_ From 12bbfd962b0529d5d33bec995a15a1a16c0aef9e Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Wed, 13 Dec 2017 23:39:54 +0100 Subject: [PATCH 0004/2222] Add WeMo GetBinaryState --- sonoff/xdrv_wemohue.ino | 93 ++++++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 24 deletions(-) diff --git a/sonoff/xdrv_wemohue.ino b/sonoff/xdrv_wemohue.ino index 9fbb3cd35..ad339a382 100755 --- a/sonoff/xdrv_wemohue.ino +++ b/sonoff/xdrv_wemohue.ino @@ -242,18 +242,18 @@ void PollUdp() const char WEMO_EVENTSERVICE_XML[] PROGMEM = "" - "" - "" - "SetBinaryState" - "" - "" - "" - "BinaryState" - "BinaryState" - "in" - "" - "" - "" + "" + "" + "SetBinaryState" + "" + "" + "" + "BinaryState" + "BinaryState" + "in" + "" + "" + "" "" "BinaryState" "Boolean" @@ -263,14 +263,43 @@ const char WEMO_EVENTSERVICE_XML[] PROGMEM = "level" "string" "0" - "" - "" + "" + "" + "" + "" + "GetBinaryState" + "" + "" + "" + "BinaryState" + "BinaryState" + "out" + "" + "" "" "\r\n" "\r\n"; +const char WEMO_SETSTATE_XML[] PROGMEM = +"" + "" + "" + "{x1" + "" + "" +"\r\n" +"\r\n"; +const char WEMO_GETSTATE_XML[] PROGMEM = +"" + "" + "" + "{x1" + "" + "" +"\r\n" +"\r\n"; const char WEMO_SETUP_XML[] PROGMEM = "" - "" + "" "" "urn:Belkin:device:controllee:1" "{x1" @@ -297,17 +326,34 @@ const char WEMO_SETUP_XML[] PROGMEM = void HandleUpnpEvent() { - 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) { -// ExecuteCommandPower(1, 1); - ExecuteCommandPower(devices_present, 1); + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); + //differentiate get and set state + if (request.indexOf(F("SetBinaryState")) > 0) { + String setstate_xml = FPSTR(WEMO_SETSTATE_XML); + if (request.indexOf(F("State>1 0) { + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT " SET STATE 1")); + ExecuteCommandPower(devices_present, 1); + setstate_xml.replace("{x1", "1"); + } + else if (request.indexOf(F("State>0 0) { + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT " SET STATE 0")); + ExecuteCommandPower(devices_present, 0); + setstate_xml.replace("{x1", "0"); + } + WebServer->send(200, FPSTR(HDR_CTYPE_XML), setstate_xml.c_str()); } - if (request.indexOf(F("State>0 0) { -// ExecuteCommandPower(1, 0); - ExecuteCommandPower(devices_present, 0); + else if(request.indexOf(F("GetBinaryState")) > 0){ + String getstate_xml = FPSTR(WEMO_GETSTATE_XML); + char svalue[80]; + /** TODO: can only return one device status for now in response, + * check how to response multi device status to echo + */ + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, 1 -1)); + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT " GET STATE")); + getstate_xml.replace("{x1", svalue); + WebServer->send(200, FPSTR(HDR_CTYPE_XML), getstate_xml.c_str()); } - WebServer->send(200, FPSTR(HDR_CTYPE_PLAIN), ""); } void HandleUpnpService() @@ -720,4 +766,3 @@ void HandleHueApi(String *path) } #endif // USE_WEBSERVER #endif // USE_EMULATION - From f2362af36f51ccfadbbe971f12dc1983215a51e6 Mon Sep 17 00:00:00 2001 From: Nils Sdun Date: Fri, 15 Dec 2017 13:13:53 +0100 Subject: [PATCH 0005/2222] save some bytes, merge set and get to one pattern --- sonoff/xdrv_wemohue.ino | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/sonoff/xdrv_wemohue.ino b/sonoff/xdrv_wemohue.ino index ad339a382..f8dfb7cc8 100755 --- a/sonoff/xdrv_wemohue.ino +++ b/sonoff/xdrv_wemohue.ino @@ -279,21 +279,12 @@ const char WEMO_EVENTSERVICE_XML[] PROGMEM = "" "\r\n" "\r\n"; -const char WEMO_SETSTATE_XML[] PROGMEM = +const char WEMO_RESPONSE_STATE_XML[] PROGMEM = "" "" - "" - "{x1" - "" - "" -"\r\n" -"\r\n"; -const char WEMO_GETSTATE_XML[] PROGMEM = -"" - "" - "" - "{x1" - "" + "" + "{x2" + "" "" "\r\n" "\r\n"; @@ -326,33 +317,33 @@ const char WEMO_SETUP_XML[] PROGMEM = void HandleUpnpEvent() { - String request = WebServer->arg(0); AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); + String request = WebServer->arg(0); + String state_xml = FPSTR(WEMO_RESPONSE_STATE_XML); //differentiate get and set state if (request.indexOf(F("SetBinaryState")) > 0) { - String setstate_xml = FPSTR(WEMO_SETSTATE_XML); if (request.indexOf(F("State>1 0) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT " SET STATE 1")); ExecuteCommandPower(devices_present, 1); - setstate_xml.replace("{x1", "1"); + state_xml.replace("{x1", "Set"); + state_xml.replace("{x2", "1"); } else if (request.indexOf(F("State>0 0) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT " SET STATE 0")); ExecuteCommandPower(devices_present, 0); - setstate_xml.replace("{x1", "0"); + + state_xml.replace("{x1", "Set"); + state_xml.replace("{x2", "0"); } - WebServer->send(200, FPSTR(HDR_CTYPE_XML), setstate_xml.c_str()); + WebServer->send(200, FPSTR(HDR_CTYPE_XML), state_xml.c_str()); } else if(request.indexOf(F("GetBinaryState")) > 0){ - String getstate_xml = FPSTR(WEMO_GETSTATE_XML); char svalue[80]; - /** TODO: can only return one device status for now in response, - * check how to response multi device status to echo - */ snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, 1 -1)); AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT " GET STATE")); - getstate_xml.replace("{x1", svalue); - WebServer->send(200, FPSTR(HDR_CTYPE_XML), getstate_xml.c_str()); + state_xml.replace("{x1", "Get"); + state_xml.replace("{x2", svalue); + WebServer->send(200, FPSTR(HDR_CTYPE_XML), state_xml.c_str()); } } From 25e3918ce3c0cc74f21d1dcd0ab4a7ac48e80674 Mon Sep 17 00:00:00 2001 From: Nils Sdun Date: Fri, 15 Dec 2017 13:31:38 +0100 Subject: [PATCH 0006/2222] ignore lib/readme --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5dac9f52f..f5681567e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .piolibdeps .clang_complete .gcc-flags.json +lib/readme.txt From a51bb39a5d18c0e5e35cea75d69322cc7e2e0701 Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Thu, 12 Apr 2018 22:56:08 +0200 Subject: [PATCH 0007/2222] igno --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 01bb48119..3ac33def4 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ .clang_complete .gcc-flags.json lib/readme.txt +sonoff/user_config_override.h +sonoff/user_config_my.h From 9c04666a17e11dd4bf8c80f289163e97d785e913 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Sun, 27 May 2018 14:16:51 +0200 Subject: [PATCH 0008/2222] Add SDS0X1 RX and TX gpio pins to sonoff_template.h --- sonoff/sonoff_template.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index f97c32203..315ce4316 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -88,7 +88,8 @@ enum UserSelectablePins { GPIO_SPI_DC, // SPI Data Direction GPIO_BACKLIGHT, // Display backlight control GPIO_PMS5003, // Plantower PMS5003 Serial interface - GPIO_SDS0X1, // Nova Fitness SDS011 Serial interface + GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface + GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface GPIO_SBR_TX, // Serial Bridge Serial interface GPIO_SBR_RX, // Serial Bridge Serial interface GPIO_SR04_TRIG, // SR04 Trigger pin @@ -138,7 +139,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|" D_SENSOR_SAIR_TX "|" D_SENSOR_SAIR_RX "|" D_SENSOR_SPI_CS "|" D_SENSOR_SPI_DC "|" D_SENSOR_BACKLIGHT "|" - D_SENSOR_PMS5003 "|" D_SENSOR_SDS0X1 "|" + D_SENSOR_PMS5003 "|" + D_SENSOR_SDS0X1_TX "|" D_SENSOR_SDS0X1_RX "|" D_SENSOR_SBR_TX "|" D_SENSOR_SBR_RX "|" D_SENSOR_SR04_TRIG "|" D_SENSOR_SR04_ECHO "|" D_SENSOR_SDM120_TX "|" D_SENSOR_SDM120_RX "|" @@ -912,4 +914,4 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { */ -#endif // _SONOFF_TEMPLATE_H_ \ No newline at end of file +#endif // _SONOFF_TEMPLATE_H_ From 91b07f2943c46b1cfee5d3003418d4c74a984053 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Sun, 27 May 2018 14:19:53 +0200 Subject: [PATCH 0009/2222] Add SDS0X1 gpio pins to support.ino --- sonoff/support.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 2bc80c5eb..6449912e8 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -527,7 +527,8 @@ boolean GetUsedInModule(byte val, uint8_t *arr) if (GPIO_PMS5003 == val) { return true; } #endif #ifndef USE_NOVA_SDS - if (GPIO_SDS0X1 == val) { return true; } + if (GPIO_SDS0X1_TX == val) { return true; } + if (GPIO_SDS0X1_RX == val) { return true; } #endif #ifndef USE_SERIAL_BRIDGE if (GPIO_SBR_TX == val) { return true; } From c41a092c7d45b0be5514e577a111a1a332b1a75a Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Sun, 27 May 2018 14:23:25 +0200 Subject: [PATCH 0010/2222] SDS0X1 RX TX pin handling in NovaSdsInit --- sonoff/xsns_20_novasds.ino | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index dc5f0ab66..610e07427 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -83,12 +83,14 @@ void NovaSdsSecond() // Every second void NovaSdsInit() { novasds_type = 0; - if (pin[GPIO_SDS0X1] < 99) { - NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1], -1, 1); + if (pin[GPIO_SDS0X1_RX] < 99 && pin[GPIO_SDS0X1_TX] < 99) { + NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1_RX], pin[GPIO_SDS0X1_TX], 1); + if (NovaSdsSerial->begin(9600)) { - if (NovaSdsSerial->hardwareSerial()) { ClaimSerial(); } + if (NovaSdsSerial->hardwareSerial()) ClaimSerial(); novasds_type = 1; } + } } @@ -154,4 +156,4 @@ boolean Xsns20(byte function) return result; } -#endif // USE_NOVA_SDS \ No newline at end of file +#endif // USE_NOVA_SDS From 7cefc9b76efa762772fbac412df992174cb42b07 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Sun, 27 May 2018 14:24:53 +0200 Subject: [PATCH 0011/2222] SDS0X1 add start and stop functions to idle the sensor --- sonoff/xsns_20_novasds.ino | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 610e07427..c54297911 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -94,6 +94,26 @@ void NovaSdsInit() } } +void NovaSdsStart() +{ + AddLog_P(LOG_LEVEL_DEBUG, "SDS: start"); + const uint8_t novasds_start_cmd[] = {0xAA, 0xB4, 0x06, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x06, 0xAB}; + NovaSdsSerial->write(novasds_start_cmd, sizeof(novasds_start_cmd)); + NovaSdsSerial->flush(); +} + +void NovaSdsStop() +{ + AddLog_P(LOG_LEVEL_DEBUG, "SDS: stop"); + const uint8_t novasds_stop_cmd[] = {0xAA, 0xB4, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x05, 0xAB}; + NovaSdsSerial->write(novasds_stop_cmd, sizeof(novasds_stop_cmd)); + NovaSdsSerial->flush(); + // drain any old data + while (NovaSdsSerial->available()) { + NovaSdsSerial->read(); + } +} + #ifdef USE_WEBSERVER const char HTTP_SDS0X1_SNS[] PROGMEM = "%s" "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" From 4a588581d145837dfd006e06ca932ca3dadd0e23 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Sun, 27 May 2018 14:28:31 +0200 Subject: [PATCH 0012/2222] Allow NovaSdsReadData to read without publishing data --- sonoff/xsns_20_novasds.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index c54297911..03b4965f8 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -37,7 +37,8 @@ struct sds011data { uint16_t pm25; } novasds_data; -bool NovaSdsReadData() + +bool NovaSdsReadData(bool publish) { if (! NovaSdsSerial->available()) return false; @@ -51,7 +52,9 @@ bool NovaSdsReadData() NovaSdsSerial->flush(); AddLogSerial(LOG_LEVEL_DEBUG_MORE, d, 8); - + if (!publish){ + return false; + } if (d[7] == ((d[1] + d[2] + d[3] + d[4] + d[5] + d[6]) & 0xFF)) { novasds_data.pm25 = (d[1] + 256 * d[2]); novasds_data.pm100 = (d[3] + 256 * d[4]); @@ -59,9 +62,6 @@ bool NovaSdsReadData() AddLog_P(LOG_LEVEL_DEBUG, PSTR("SDS: " D_CHECKSUM_FAILURE)); return false; } - - novasds_valid = 10; - return true; } From 87e3dcddb9fde27ed5f057dbe8308a77829c0cd8 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Sun, 27 May 2018 14:29:53 +0200 Subject: [PATCH 0013/2222] SDS0X1 take one stable reading every 3 minutes --- sonoff/xsns_20_novasds.ino | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 03b4965f8..a9dd180b6 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -31,6 +31,10 @@ TasmotaSerial *NovaSdsSerial; uint8_t novasds_type = 1; uint8_t novasds_valid = 0; +uint8_t novasds_running = 1; +uint8_t novasds_read_tick = 30; +uint8_t novasds_wakup_tick = 179; +uint8_t novasds_ticker = 0; struct sds011data { uint16_t pm100; @@ -69,12 +73,35 @@ bool NovaSdsReadData(bool publish) void NovaSdsSecond() // Every second { - if (NovaSdsReadData()) { - novasds_valid = 10; - } else { - if (novasds_valid) { - novasds_valid--; + if (novasds_ticker < novasds_read_tick) { + // wake up the sensor and wait read ticks to stabalize the sensor + if (!novasds_running) { + NovaSdsStart(); + novasds_running = 1; } + + // drain the serial without publishing data + NovaSdsReadData(false); + novasds_ticker++; + + } else if (novasds_ticker == novasds_read_tick) { + + // try to take a single stable reading and sleep the sensor + if (NovaSdsReadData(true)) { + novasds_valid = 1; + NovaSdsStop(); + novasds_running = 0; + novasds_ticker++; + } else { + novasds_valid = 0; + } + + } else if (novasds_ticker >= novasds_wakup_tick) { + // reset the counter + novasds_ticker = 0; + } else { + // sensor is sleeping keep waiting + novasds_ticker++; } } From f11386cfe7da93bedac801747fb093d8498177a8 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Sun, 27 May 2018 14:30:40 +0200 Subject: [PATCH 0014/2222] Update language files for SDS0X1 RX and TX --- sonoff/language/bg-BG.h | 3 ++- sonoff/language/cs-CZ.h | 3 ++- sonoff/language/de-DE.h | 3 ++- sonoff/language/el-GR.h | 3 ++- sonoff/language/en-GB.h | 3 ++- sonoff/language/es-AR.h | 3 ++- sonoff/language/fr-FR.h | 3 ++- sonoff/language/hu-HU.h | 3 ++- sonoff/language/it-IT.h | 3 ++- sonoff/language/nl-NL.h | 3 ++- sonoff/language/pl-PL.h | 3 ++- sonoff/language/pt-BR.h | 3 ++- sonoff/language/pt-PT.h | 3 ++- sonoff/language/ru-RU.h | 3 ++- sonoff/language/zh-CN.h | 3 ++- sonoff/language/zh-TW.h | 3 ++- 16 files changed, 32 insertions(+), 16 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 55482d55c..9981f1902 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "Подсветка" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 9f939534a..6ee0bea8d 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 7d2e7285d..c2fdd0640 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 97eefcd7b..5db01909b 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 9eb8c9d4a..4af5f998e 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index aff7b2665..69737de8c 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index f37d3cfae..a862c54a0 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "RétroÉcl" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 4ebeffbf6..879204ace 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "Háttérvil" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 16c11645b..54868fd2d 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 262daee7b..f9a16a720 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 683d43cb3..d3e753946 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 02bdec2e4..6db472624 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "Luz de fundo" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 4cf9e0da3..398e32a58 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "Luz negra" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 3336484e9..5ea49a669 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 1c3ee0bb7..c97929c32 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index e8505010f..9f79ddb89 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -456,7 +456,8 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" From ff132238077ffd04ac432dcfb0f65c6c49b32eb6 Mon Sep 17 00:00:00 2001 From: Johann Weging Date: Sun, 27 May 2018 14:34:47 +0200 Subject: [PATCH 0015/2222] SDS0X1 minor code cleanup --- sonoff/xsns_20_novasds.ino | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index a9dd180b6..851326f3f 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -114,7 +114,9 @@ void NovaSdsInit() NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1_RX], pin[GPIO_SDS0X1_TX], 1); if (NovaSdsSerial->begin(9600)) { - if (NovaSdsSerial->hardwareSerial()) ClaimSerial(); + if (NovaSdsSerial->hardwareSerial()) { + ClaimSerial(); + } novasds_type = 1; } @@ -137,8 +139,8 @@ void NovaSdsStop() NovaSdsSerial->flush(); // drain any old data while (NovaSdsSerial->available()) { - NovaSdsSerial->read(); - } + NovaSdsSerial->read(); + } } #ifdef USE_WEBSERVER From 5482ac9bfc5e756a09dea94864a8709f50638396 Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Mon, 27 Aug 2018 22:56:26 +0200 Subject: [PATCH 0016/2222] ignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index b6460347b..028a76667 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ build ## Visual Studio Code specific ###### .vscode +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json From 2e8864effd32578cb719c066692f44cca51afcb9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 31 Aug 2018 16:53:40 +0200 Subject: [PATCH 0017/2222] 6.2.0 - Released --- README.md | 2 +- sonoff/_changelog.ino | 163 ++++++++++++++-------------------------- sonoff/sonoff_version.h | 2 +- sonoff/user_config.h | 2 +- 4 files changed, 61 insertions(+), 108 deletions(-) diff --git a/README.md b/README.md index f8f9c92ac..556367ede 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute! [![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/tasmota) ### Development -[![Dev Version](https://img.shields.io/badge/development%20version-6.1.1.13-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-6.2.0.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 6fc8a9fb5..b95a6ce0e 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,114 +1,67 @@ -/* 6.1.1.14 20180830 - * Add boot loop detection and perform some solutions - * Add features to and provide more stable display drivers - * - * 6.1.1.13 20180828 - * Fix 6.1.1.12 regression of Mem and Var default handling (#3618) - * Optimizations - * Change define USE_ALL_SENSORS to USE_SENSORS as it doesn't contain all sensors due to duplicate I2C addresses - * - * 6.1.1.12 20180827 - * Add commands ButtonDebounce 40..1000 and SwitchDebounce 40..1000 to have user control over debounce timing. Default is 50mS (#3594) - * Add rule variables %sunrise%, %sunset%, %uptime% and %time% (#3608) - * Fix handling use of default names when using names starting with shortcut character (#3392, #3600) - * Fix Sonoff Bridge data reception when using Portisch EFM8 firmware and in data buffer length (#3605) - * Add optional MQTT_TELE_RETAIN to Energy Margins message (#3612, 3614) - * Add Individual HSBColorX commands (#3430, #3615) - * Add RuleX debug options 8,9,10 (StopOnError) to control RuleX execution status after an exception restart (#3607) - * - * 6.1.1.11 20180826 - * Change scheduler phase 1/3 - Fixed when sleep is enabled: Uptime, Delay, PulseTime and TelePeriod (#3581) - * Change scheduler phase 2/3 - Fixed when sleep is enabled: Blinktime (#3581) - * Change scheduler phase 3/3 - Some sensor update timings: AdcEvery 200 -> 250, Senseair 300 -> 250, SDM120 300 -> 250, SDM630 300 -> 250 - * - * 6.1.1.10 20180827 +/* 6.2.0 20180901 + * Allow user override of define MAX_RULE_VARS and MAX_RULE_TIMERS (#3561) * Disable wifi sleep for both Esp8266/Arduino core 2.4.1 and 2.4.2 to solve device freeze caused by Espressif SDK bug (#3554) - * Rewrite GPIO options ButtonXn, SwitchXn and CounterXn to select INPUT mode instead of INPUT_PULLUP - * Add command Publish2 for publishing retained MQTT messages (#3593) - * - * 6.1.1.9 20180825 - * Allow user override of define MAX_RULE_TIMERS (#3561) - * Allow user override of define MAX_RULE_VARS - * Add GPIO options ButtonXn, SwitchXn and CounterXn to select INPUT mode instead of INPUT_PULLUP (#2525) - * Fix OtaMagic when file path contains a dash (-) (#3563) - * Fix EnergyReset3 (#2723) - * Change command sleep from restart after change to not restart after change (#3554) - * Add all ruletimer values to command RuleTimer result message (#3571) - * Add RGB support for Domoticz (#3547) - * - * 6.1.1.8 20180825 - * Fix MQTT reconnection detection when using TasmotaMqtt library (#3558) - * Add build time setting of ButtonTopic and SwitchTopic (#3414) - * Add display features and dynamic buffering - * - * 6.1.1.7 20180818 - * Add initial display support for Lcd, Oled, Matrix, Tft and e-paper - Need more docs - * Fix SDM120 reporting wrong negative values to Domoticz (#3521) - * Fix iFan02 power on state (#3412, #3530) - * Add display define USE_DISPLAY_MODES1TO5 to select display modes 1 to 5 - * Add command DisplayRotate 0..3 to select persistent display rotation - * - * 6.1.1.6 20180813 - * Add modulo option to rules like rule1 on Time#Minute|5 do backlog power on;delay 200;power off endon (#3466) - * - * 6.1.1.5 20180812 - * Fix some Pow R2 and S31 checksum errors using optimized re-sync - * - * 6.1.1.4 20180812 - * Change version representation from 1.1.1a to 1.1.1.1 for better change reference - * - * 6.1.1c 20180720 - * Add iFan02 Fanspeed + and Fanspeed - command options (#3415) - * Fix some Pow R2 and S31 checksum errors (#3425) - * Change CounterType 1 from milliseconds to microseconds (#3437) - * Add output support on MCP23008/MCP23017 (#3436) - * Fix LM75AD I2C sensor detection (#3408) - * Add message when JavaScript is not enabled in webbrowser (#3388) - * Fix sonoff-minimal from using default settings - * Add option + to command Rule to concatenate new rule with existing rules (#3365) - * Add initial support for sensor MPU6050 (#3352) - * Add command SerialSend4 to send binary serial data (#3345) - * Add rule triggers Wifi#Connected and Wifi#Disconnected (#3359) - * Fix unsecure main webpage update - * Add Turkish language file (#3332) - * Fix command TimeDst/TimeStd invalid JSON (#3322) - * Fix possible WDT due to long MQTT publish handling (#3313) - * Fix CCS811 temperature and humidity compensation - * Add support for CCS811 sensor (#3309) - * Add command Timers 0/1 to globally disable or enable armed timers (#3270) - * - * 6.1.1b 20180715 - * Add support for MPR121 controller in input mode for touch buttons (#3142) - * Add support for MCP230xx for general purpose input expansion and command Sensor29 (#3188) - * Fix command Scale buffer overflow (#3236) - * Fix rules once regression from v6.1.0 (#3198, #3226) - * Add default Wifi Configuration tool as define WIFI_CONFIG_NO_SSID in user_config.h if no SSID is configured (#3224) - * Add user selection of Wifi Smartconfig as define USE_SMARTCONFIG in user_config.h - * Add user selection of WPS as define USE_WPS in user_config.h in preparation for core v2.4.2 (#3221) - * Change default Wifi config option from WPS to Wifi Manager if WPS is disabled - * or Wifi Smartconfig if webserver is disabled - * or Wifi Serial input if Smartconfig is disabled - * Remove WPS and SmartConfig from sonoff-minimal saving 56k code space - * - * 6.1.1a 20180714 - * Fix TM1638 compile error (#3212) - * Add TM1638 switch support (#2226) - * Fix invalid response using more than 4 switches and domoticz - * Update sensor drivers to provide instant results - * Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21 - * Change SHT1x driver to provide better instant results - * Fix DHT driver mixing values for different sensors (#1797) + * Change DS18B20 driver to provide better instant results + * Change some sensor drivers to provide instant results + * Change define USE_ALL_SENSORS to USE_SENSORS as it doesn't contain all sensors due to duplicate I2C addresses + * Change some sensor update timings: AdcEvery 200 -> 250, Senseair 300 -> 250, SDM120 300 -> 250, SDM630 300 -> 250 + * Change default Wifi config option from WPS to Wifi Manager if WPS is disabled or Wifi Smartconfig if webserver is disabled or Wifi Serial input if Smartconfig is disabled + * Change SHT1x driver to provide better instant results and fix I2C interference * Change DHT driver to provide better instant results and add decimals to DHT11 (#3164) * Change DS18x20 driver to provide better instant results (#3169) - * Change DS18B20 driver to provide better instant results + * Change CounterType 1 from milliseconds to microseconds (#3437) + * Change scheduler for better sleep support using Uptime, Delay, PulseTime and TelePeriod, Blinktime (#3581) + * Remove unused functionality from Sonoff-minimal to save space + * Remove WPS and SmartConfig from sonoff-minimal saving 56k code space * Remove TSL2561 debug message and update library (#2415) - * Change SHT1x sensor initialization from pre-teleperiod to once during restart to fix I2C interference + * Remove forced restart when sleep command is executed (#3554) + * Fix invalid response using more than 4 switches and domoticz + * Fix sonoff-minimal not using default settings + * Fix unsecure main webpage update + * Fix DHT driver mixing values for different sensors (#1797) + * Fix EnergyReset3 regression not clearing total energy (#2723) + * Fix rules once regression from v6.1.0 (#3198, #3226) + * Fix command Scale buffer overflow (#3236) + * Fix possible WDT due to long MQTT publish handling (#3313) + * Fix command TimeDst/TimeStd invalid JSON (#3322) + * Fix handling of default names when using names starting with shortcut character ",0,1 or 2 (#3392, #3600, #3618) + * Fix LM75AD I2C sensor detection (#3408) + * Fix iFan02 power on state (#3412, #3530) + * Fix some Pow R2 and S31 checksum errors using optimized re-sync (#3425) + * Fix SDM120 reporting wrong negative values to Domoticz (#3521) + * Fix MQTT reconnection detection when using TasmotaMqtt library (#3558) + * Fix OtaMagic when file path contains a dash (-) (#3563) + * Fix Sonoff Bridge data reception when using Portisch EFM8 firmware using in data buffer length (#3605) + * Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21 + * Add user selection of Wifi Smartconfig as define USE_SMARTCONFIG in user_config.h + * Add boot loop detection and perform some solutions * Add wifi and mqtt status led blinkyblinky to be disabled by SetOption31 1. Does not work when LedPower is On (deliberate) (#871, #2230, #3114, #3155) - * Add experimental (untested) TM1638 switch support (#2226) + * Add support for TM1638 switch (#2226) + * Add GPIO options ButtonXn, SwitchXn and CounterXn to select INPUT mode instead of INPUT_PULLUP (#2525) * Add support for APDS9960 proximity sensor (#3051) - * Add heap and stack debug information - * Add debug facilities using optional xdrv_99_debug.ino to enable in user_config.h - * Remove not needed functionality from Sonoff-minimal to save space + * Add support for MPR121 controller in input mode for touch buttons (#3142) + * Add support for MCP230xx for general purpose input expansion and command Sensor29 (#3188) + * Add default Wifi Configuration tool as define WIFI_CONFIG_NO_SSID in user_config.h if no SSID is configured (#3224) + * Add command Timers 0/1 to globally disable or enable armed timers (#3270) + * Add support for CCS811 sensor (#3309) + * Add Turkish language file (#3332) + * Add command SerialSend4 to send binary serial data (#3345) + * Add initial support for sensor MPU6050 (#3352) + * Add rule triggers Wifi#Connected and Wifi#Disconnected (#3359) + * Add option + to command Rule to concatenate new rule with existing rules (#3365) + * Add message when JavaScript is not enabled in webbrowser (#3388) + * Add build time setting of ButtonTopic and SwitchTopic (#3414) + * Add iFan02 Fanspeed + and Fanspeed - command options (#3415) + * Add Individual HSBColorX commands (#3430, #3615) + * Add output support on MCP23008/MCP23017 (#3436) + * Add modulo option to rules like rule1 on Time#Minute|5 do backlog power on;delay 200;power off endon (#3466) + * Add RGB support for Domoticz (#3547) + * Add all ruletimer values to command RuleTimer result message (#3571) + * Add command Publish2 for publishing retained MQTT messages (#3593) + * Add commands ButtonDebounce 40..1000 and SwitchDebounce 40..1000 to have user control over debounce timing. Default is 50mS (#3594) + * Add RuleX debug options 8,9,10 (StopOnError) to control RuleX execution status after an exception restart (#3607) + * Add rule variables %sunrise%, %sunset%, %uptime% and %time% (#3608) + * Add optional MQTT_TELE_RETAIN to Energy Margins message (#3612, 3614) * * 6.1.1 20180714 * Revert wifi changes (#3177) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 72634caa1..1bf322288 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0601010E +#define VERSION 0x06020000 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 0471ff768..a8457ff97 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -318,7 +318,7 @@ #endif // USE_I2C // -- SPI sensors --------------------------------- -#define USE_SPI // SPI using library TasmotaTFT +//#define USE_SPI // SPI using library TasmotaTFT #ifdef USE_SPI #ifndef USE_DISPLAY From 17496d002e365138e96f0bbd01c7a5d95b4971fc Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 1 Sep 2018 17:46:45 +0200 Subject: [PATCH 0018/2222] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 556367ede..3ab25ac17 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute! See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development/RELEASENOTES.md) for release information and [sonoff/_changelog.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_changelog.ino) for detailed change information. -The compiled development versions from current codebase are built around 6AM GMT+2 everyday and posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA too). Remember that these are based on the current development codebase and it is not recommended to flash devices in hard to reach places with this firmware. +The development codebase is checked hourly for changes and if new commits have been merged and compile successfuly they will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA too). It is important to note that these are based on the current development codebase and it is not recommended to flash it to devices used in production or which are hard to reach in the event that you need to manually flash the device if OTA failed. The last compiled commit number is also posted on the same page along with the current build status (if a firmware rebuild is in progress). ### Disclaimer :warning: **DANGER OF ELECTROCUTION** :warning: From e5186e602e247117fab0c5109f8ee11409605157 Mon Sep 17 00:00:00 2001 From: alex Date: Sat, 1 Sep 2018 19:57:10 +0200 Subject: [PATCH 0019/2222] Fix ccs811 begin result check --- sonoff/xsns_31_ccs811.ino | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index 482572cdb..8aba4d04f 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -47,13 +47,12 @@ void CCS811Update() // Perform every n second tcnt = 0; CCS811_ready = 0; if (!CCS811_type) { - sint8_t res = ccs.begin(CCS811_ADDRESS); - if (!res) { + if (ccs.begin(CCS811_ADDRESS)) { // ccs.begin returns true in case of success CCS811_type = 1; snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "CCS811", 0x5A); AddLog(LOG_LEVEL_DEBUG); } else { - //snprintf_P(log_data, sizeof(log_data), "CCS811 init failed: %d",res); + //snprintf_P(log_data, sizeof(log_data), "CCS811 init failed"); //AddLog(LOG_LEVEL_DEBUG); } } else { From 6a57882829fe12a0f0c26f4d70389a63197f4002 Mon Sep 17 00:00:00 2001 From: Alexey Kubrinsky Date: Sun, 2 Sep 2018 00:47:35 +0200 Subject: [PATCH 0020/2222] Revert "Fix ccs811 begin result check" --- sonoff/xsns_31_ccs811.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index 8aba4d04f..482572cdb 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -47,12 +47,13 @@ void CCS811Update() // Perform every n second tcnt = 0; CCS811_ready = 0; if (!CCS811_type) { - if (ccs.begin(CCS811_ADDRESS)) { // ccs.begin returns true in case of success + sint8_t res = ccs.begin(CCS811_ADDRESS); + if (!res) { CCS811_type = 1; snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "CCS811", 0x5A); AddLog(LOG_LEVEL_DEBUG); } else { - //snprintf_P(log_data, sizeof(log_data), "CCS811 init failed"); + //snprintf_P(log_data, sizeof(log_data), "CCS811 init failed: %d",res); //AddLog(LOG_LEVEL_DEBUG); } } else { From 48b5f9117ab00d86cb4fac5cc4b4ee0d9621bf96 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 2 Sep 2018 11:11:49 +0200 Subject: [PATCH 0021/2222] 6.2.0.1 - Fix StateText ambiguity Fix possible ambiguity on command parameters if StateText contains numbers only (#3656) --- sonoff/_changelog.ino | 5 ++++- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b95a6ce0e..8b5af65ce 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.2.0 20180901 +/* 6.2.0.1 20180902 + * Fix possible ambiguity on command parameters if StateText contains numbers only (#3656) + * + * 6.2.0 20180901 * Allow user override of define MAX_RULE_VARS and MAX_RULE_TIMERS (#3561) * Disable wifi sleep for both Esp8266/Arduino core 2.4.1 and 2.4.2 to solve device freeze caused by Espressif SDK bug (#3554) * Change DS18B20 driver to provide better instant results diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 1bf322288..c3ea9381e 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020000 +#define VERSION 0x06020001 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index 8cc064fe5..eed4146c2 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -561,13 +561,13 @@ int GetStateNumber(char *state_text) char command[CMDSZ]; int state_number = -1; - if ((GetCommandCode(command, sizeof(command), state_text, kOptionOff) >= 0) || !strcasecmp(state_text, Settings.state_text[0])) { + if (GetCommandCode(command, sizeof(command), state_text, kOptionOff) >= 0) { state_number = 0; } - else if ((GetCommandCode(command, sizeof(command), state_text, kOptionOn) >= 0) || !strcasecmp(state_text, Settings.state_text[1])) { + else if (GetCommandCode(command, sizeof(command), state_text, kOptionOn) >= 0) { state_number = 1; } - else if ((GetCommandCode(command, sizeof(command), state_text, kOptionToggle) >= 0) || !strcasecmp(state_text, Settings.state_text[2])) { + else if (GetCommandCode(command, sizeof(command), state_text, kOptionToggle) >= 0) { state_number = 2; } else if (GetCommandCode(command, sizeof(command), state_text, kOptionBlink) >= 0) { From c6a14c5fe72ead31c3bc869e6cf93ea2e8331121 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 2 Sep 2018 11:52:24 +0200 Subject: [PATCH 0022/2222] Fix possible exception Fix possible exception due to buffer overflow (#3659) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 2 +- sonoff/support.ino | 4 ++-- sonoff/xdrv_02_webserver.ino | 4 ++-- sonoff/xdsp_01_lcd.ino | 2 +- sonoff/xsns_01_counter.ino | 2 +- sonoff/xsns_05_ds18x20_legacy.ino | 2 +- sonoff/xsns_12_ads1115.ino | 2 +- sonoff/xsns_12_ads1115_i2cdev.ino | 2 +- 9 files changed, 11 insertions(+), 10 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 8b5af65ce..c3d1e4c6a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.2.0.1 20180902 * Fix possible ambiguity on command parameters if StateText contains numbers only (#3656) + * Fix possible exception due to buffer overflow (#3659) * * 6.2.0 20180901 * Allow user override of define MAX_RULE_VARS and MAX_RULE_TIMERS (#3561) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 254f88184..93ffbda01 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -442,7 +442,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) ShowFreeMem(PSTR("MqttDataHandler")); - strncpy(topicBuf, topic, sizeof(topicBuf)); + strlcpy(topicBuf, topic, sizeof(topicBuf)); for (i = 0; i < data_len; i++) { if (!isspace(data[i])) break; } diff --git a/sonoff/support.ino b/sonoff/support.ino index eed4146c2..8aaeabf88 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -143,7 +143,7 @@ char* subStr(char* dest, char* str, const char *delim, int index) int i; // Since strtok consumes the first arg, make a copy - strncpy(dest, str, strlen(str)); + strlcpy(dest, str, strlen(str)); for (i = 1, act = dest; i <= index; i++, act = NULL) { sub = strtok_r(act, delim, &ptr); if (sub == NULL) break; @@ -157,7 +157,7 @@ double CharToDouble(char *str) // simple ascii to double, because atof or strtod are too large char strbuf[24]; - strcpy(strbuf, str); + strlcpy(strbuf, str, sizeof(strbuf)); char *pt; double left = atoi(strbuf); double right = 0; diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index c919c8f43..91c01eeae 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -372,8 +372,8 @@ long ajax_token = 1; static void WebGetArg(const char* arg, char* out, size_t max) { String s = WebServer->arg(arg); - strncpy(out, s.c_str(), max); - out[max-1] = '\0'; // Ensure terminating NUL + strlcpy(out, s.c_str(), max); +// out[max-1] = '\0'; // Ensure terminating NUL } void ShowWebSource(int source) diff --git a/sonoff/xdsp_01_lcd.ino b/sonoff/xdsp_01_lcd.ino index 9d4a5d396..bfc0b3536 100644 --- a/sonoff/xdsp_01_lcd.ino +++ b/sonoff/xdsp_01_lcd.ino @@ -107,7 +107,7 @@ void LcdCenter(byte row, char* txt) line[Settings.display_cols[0]] = 0; len = strlen(txt); offset = (len < Settings.display_cols[0]) ? offset = (Settings.display_cols[0] - len) / 2 : 0; - strncpy(line +offset, txt, len); + strlcpy(line +offset, txt, len); lcd->setCursor(0, row); lcd->print(line); } diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index 069d5b3e7..b5822cac7 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -111,7 +111,7 @@ void CounterShow(boolean json) } header++; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"C%d\":%s"), mqtt_data, stemp, i +1, counter); - strcpy(stemp, ","); + strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_DOMOTICZ if ((0 == tele_period) && (1 == dsxflg)) { DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]); diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index 156312104..03754bbe1 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -186,7 +186,7 @@ void Ds18x20Show(boolean json) dsxflg++; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"DS%d\":{\"" D_JSON_TYPE "\":\"%s\",\"" D_JSON_ADDRESS "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, stemp, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), temperature); - strcpy(stemp, ","); + strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_DOMOTICZ if ((0 == tele_period) && (1 == dsxflg)) { DomoticzSensor(DZ_TEMP, temperature); diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index f1279a732..bcfb6dfad 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -191,7 +191,7 @@ void Ads1115Show(boolean json) } dsxflg++; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, stemp, i, adc_value); - strcpy(stemp, ","); + strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_WEBSERVER } else { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value); diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/sonoff/xsns_12_ads1115_i2cdev.ino index d3748ec7a..588a37ac5 100644 --- a/sonoff/xsns_12_ads1115_i2cdev.ino +++ b/sonoff/xsns_12_ads1115_i2cdev.ino @@ -111,7 +111,7 @@ void Ads1115Show(boolean json) } dsxflg++; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, stemp, i, adc_value); - strcpy(stemp, ","); + strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_WEBSERVER } else { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value); From 5623924813f888c25d672f23714a6675b6012c35 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 2 Sep 2018 12:10:22 +0200 Subject: [PATCH 0023/2222] Add Wifi channel number Add Wifi channel number to state message (#3664) --- sonoff/_changelog.ino | 1 + sonoff/i18n.h | 1 + sonoff/sonoff.ino | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index c3d1e4c6a..d8a14e367 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.2.0.1 20180902 * Fix possible ambiguity on command parameters if StateText contains numbers only (#3656) * Fix possible exception due to buffer overflow (#3659) + * Add Wifi channel number to state message (#3664) * * 6.2.0 20180901 * Allow user override of define MAX_RULE_VARS and MAX_RULE_TIMERS (#3561) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 107710678..cfc30e6bc 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -40,6 +40,7 @@ #define D_JSON_BOOTVERSION "Boot" #define D_JSON_BOOTCOUNT "BootCount" #define D_JSON_BUILDDATETIME "BuildDateTime" +#define D_JSON_CHANNEL "Channel" #define D_JSON_CO2 "CarbonDioxide" #define D_JSON_COMMAND "Command" #define D_JSON_CONNECT_FAILED "Connect failed" diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 93ffbda01..9a167eddf 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1532,8 +1532,8 @@ void MqttShowState() MqttShowPWMState(); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_RSSI "\":%d,\"" D_JSON_APMAC_ADDRESS "\":\"%s\"}}"), - mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_APMAC_ADDRESS "\":\"%s\"}}"), + mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str()); } boolean MqttShowSensor() From a60876378f0adc066352eb978ef07d2d54fc83f7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 2 Sep 2018 13:01:08 +0200 Subject: [PATCH 0024/2222] Show AP channel on webpage Show channel number on webpage and wifiscan debug info. Add BSSid to wifiscan debug info --- sonoff/language/bg-BG.h | 2 ++ sonoff/language/cs-CZ.h | 2 ++ sonoff/language/de-DE.h | 2 ++ sonoff/language/el-GR.h | 2 ++ sonoff/language/en-GB.h | 2 ++ sonoff/language/es-AR.h | 2 ++ sonoff/language/fr-FR.h | 2 ++ sonoff/language/hu-HU.h | 2 ++ sonoff/language/it-IT.h | 2 ++ sonoff/language/nl-NL.h | 2 ++ sonoff/language/pl-PL.h | 2 ++ sonoff/language/pt-BR.h | 2 ++ sonoff/language/pt-PT.h | 2 ++ sonoff/language/ru-RU.h | 2 ++ sonoff/language/tr-TR.h | 4 +++- sonoff/language/uk-UK.h | 2 ++ sonoff/language/zh-CN.h | 2 ++ sonoff/language/zh-TW.h | 2 ++ sonoff/xdrv_02_webserver.ino | 5 +++-- 19 files changed, 40 insertions(+), 3 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 6421441b7..e85ab66c3 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "Мигане изкл." #define D_BOOT_COUNT "Брой на стартиранията" #define D_BRIGHTLIGHT "Яркост" +#define D_BSSID "BSSId" #define D_BUTTON "Бутон" #define D_BY "от" // Written by me #define D_BYTES "Байта" #define D_CELSIUS "Целзий" +#define D_CHANNEL "Channel" #define D_CO2 "Въглероден диоксид" #define D_CODE "код" // Button code #define D_COLDLIGHT "Хладна" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index d1905c103..2f51ccc93 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "BlikáníVyp" #define D_BOOT_COUNT "Počítadlo spuštění" #define D_BRIGHTLIGHT "Světlý" +#define D_BSSID "BSSId" #define D_BUTTON "Tlačítko" #define D_BY "by" // Written by me #define D_BYTES "Bytů" #define D_CELSIUS "°C" +#define D_CHANNEL "Channel" #define D_CO2 "CO2" #define D_CODE "kód" // Button code #define D_COLDLIGHT "Studené světlo" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 302c7e55e..888345d8a 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "BlinkenAus" #define D_BOOT_COUNT "Anzahl Startvorgänge" #define D_BRIGHTLIGHT "hell" +#define D_BSSID "BSSId" #define D_BUTTON "Knopf" #define D_BY "von" // Written by me #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" +#define D_CHANNEL "Kanal" #define D_CO2 "CO²" #define D_CODE "code" // Button code #define D_COLDLIGHT "kalt" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 789d88a6f..3187eadf9 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "Δεν αναβοσβήνει" #define D_BOOT_COUNT "Αριθμός εκκινήσεων" #define D_BRIGHTLIGHT "Λαμπερό" +#define D_BSSID "BSSId" #define D_BUTTON "Κουμπί" #define D_BY "από" // Written by me #define D_BYTES "Bytes" #define D_CELSIUS "Κελσίου" +#define D_CHANNEL "Channel" #define D_CO2 "Διοξείδιο του άνθρακα" #define D_CODE "κώδικας" // Button code #define D_COLDLIGHT "Ψυχρός" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index e8af7fab1..558877db2 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "BlinkOff" #define D_BOOT_COUNT "Boot Count" #define D_BRIGHTLIGHT "Bright" +#define D_BSSID "BSSId" #define D_BUTTON "Button" #define D_BY "by" // Written by me #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" +#define D_CHANNEL "Channel" #define D_CO2 "Carbon dioxide" #define D_CODE "code" // Button code #define D_COLDLIGHT "Cold" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 68e9141ea..c1993ffee 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "BlinkOff" #define D_BOOT_COUNT "Conteo Reinicios" #define D_BRIGHTLIGHT "Brillante" +#define D_BSSID "BSSId" #define D_BUTTON "Botón" #define D_BY "por" // Written by me #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" +#define D_CHANNEL "Channel" #define D_CO2 "CO2" #define D_CODE "código" // Button code #define D_COLDLIGHT "Fría" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 1e5c2b9f8..2a46f7b53 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "BlinkOff" #define D_BOOT_COUNT "Nombre de boot" #define D_BRIGHTLIGHT "Luminosité" +#define D_BSSID "BSSId" #define D_BUTTON "Bouton" #define D_BY "par" // Written by me #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" +#define D_CHANNEL "Channel" #define D_CO2 "Dioxyde de carbone" #define D_CODE "code" // Button code #define D_COLDLIGHT "Froid" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 76076427e..c57278176 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "Villogás Ki" #define D_BOOT_COUNT "Bootolások száma" #define D_BRIGHTLIGHT "Max. fényerő" +#define D_BSSID "BSSId" #define D_BUTTON "Gomb" #define D_BY "tőle:" // Written by me #define D_BYTES "Byte-ok" #define D_CELSIUS "Celsius" +#define D_CHANNEL "Channel" #define D_CO2 "Szén-dioxid" #define D_CODE "kód" // Button code #define D_COLDLIGHT "Hideg" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 2beda2e79..d07a33021 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "BlinkOff" #define D_BOOT_COUNT "Numero di boot" #define D_BRIGHTLIGHT "Luminoso" +#define D_BSSID "BSSId" #define D_BUTTON "Pulsante" #define D_BY "da" // Written by me #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" +#define D_CHANNEL "Channel" #define D_CO2 "CO2" #define D_CODE "codice" // Button code #define D_COLDLIGHT "Fredda" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 8ef596448..05ec4666b 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "KnipperUit" #define D_BOOT_COUNT "Herstarts" #define D_BRIGHTLIGHT "Fel" +#define D_BSSID "BSSId" #define D_BUTTON "DrukKnop" #define D_BY "door" // Written by me #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" +#define D_CHANNEL "Kanaal" #define D_CO2 "Koolstofdioxide" #define D_CODE "code" // Button code #define D_COLDLIGHT "Koud" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 06d086c57..faaf8df6d 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "MiganieWył" #define D_BOOT_COUNT "Licznik uruchomienia" #define D_BRIGHTLIGHT "Jasny" +#define D_BSSID "BSSId" #define D_BUTTON "Przycisk" #define D_BY "by" // Written by me #define D_BYTES "Bajtow" #define D_CELSIUS "Celsiusza" +#define D_CHANNEL "Channel" #define D_CO2 "Dwutlenku węgla" #define D_CODE "kod" // Button code #define D_COLDLIGHT "Zimny" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 6c5f3fceb..318f69e45 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "Pulsar desligado" #define D_BOOT_COUNT "Contagem de inicialização" #define D_BRIGHTLIGHT "Brilho" +#define D_BSSID "BSSId" #define D_BUTTON "Botão" #define D_BY "por" // Write by me #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" +#define D_CHANNEL "Channel" #define D_CO2 "Dióxido de carbono" #define D_CODE "Código" // Button code #define D_COLDLIGHT "Luz fria" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 0c93620e8..d39ec6e50 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "Piscar desligado" #define D_BOOT_COUNT "Contagem de Inicialização" #define D_BRIGHTLIGHT "Brilho" +#define D_BSSID "BSSId" #define D_BUTTON "Botão" #define D_BY "por" // Write by me #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" +#define D_CHANNEL "Channel" #define D_CO2 "Dioxido de Carbono" #define D_CODE "Código" // Button code #define D_COLDLIGHT "Luz Fria" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 2fa9d388f..5fea0468e 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "Не Мигать" #define D_BOOT_COUNT "Количество загрузок" #define D_BRIGHTLIGHT "Яркость" +#define D_BSSID "BSSId" #define D_BUTTON "Кнопка" #define D_BY "by" // Written by me #define D_BYTES "Байт" #define D_CELSIUS "Цельсия" +#define D_CHANNEL "Channel" #define D_CO2 "Углекислый газ" #define D_CODE "код" // Button code #define D_COLDLIGHT "Холодный" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 3d88ae1a8..b133d2c80 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "BlinkOff" #define D_BOOT_COUNT "Yeniden başlama sayısı" #define D_BRIGHTLIGHT "Işık" +#define D_BSSID "BSSId" #define D_BUTTON "Buton" #define D_BY "by" // Written by me #define D_BYTES "Bayt" #define D_CELSIUS "Derece" +#define D_CHANNEL "Channel" #define D_CO2 "Karbon dioksit" #define D_CODE "kod" // Button code #define D_COLDLIGHT "Soğuk" @@ -536,4 +538,4 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi -#endif // _LANGUAGE_TR_TR_H_ \ No newline at end of file +#endif // _LANGUAGE_TR_TR_H_ diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index a2fe05843..9cf66773b 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "Не блимати" #define D_BOOT_COUNT "Кіл-сть завант." #define D_BRIGHTLIGHT "Яскравість" +#define D_BSSID "BSSId" #define D_BUTTON "Кнопка" #define D_BY "by" // Written by me #define D_BYTES "Байт" #define D_CELSIUS "Цельсія" +#define D_CHANNEL "Channel" #define D_CO2 "Вуглек. газ" #define D_CODE "код" // Button code #define D_COLDLIGHT "Холодний" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 70186035d..88f680f8e 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "闪烁关" #define D_BOOT_COUNT "启动次数" #define D_BRIGHTLIGHT "亮" +#define D_BSSID "BSSId" #define D_BUTTON "按钮" #define D_BY "汉化: killadm 作者:" // Written by me #define D_BYTES "大小:" #define D_CELSIUS "摄氏" +#define D_CHANNEL "Channel" #define D_CO2 "二氧化碳" #define D_CODE "代码" // Button code #define D_COLDLIGHT "冷" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 16e6961d0..abb92d359 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -60,10 +60,12 @@ #define D_BLINKOFF "閃爍關" #define D_BOOT_COUNT "啟動次數" #define D_BRIGHTLIGHT "亮度" +#define D_BSSID "BSSId" #define D_BUTTON "按鈕" #define D_BY "by" // Written by me #define D_BYTES "大小:" #define D_CELSIUS "攝氏" +#define D_CHANNEL "Channel" #define D_CO2 "二氧化碳" #define D_CODE "代碼" // Button code #define D_COLDLIGHT "冷" diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index 91c01eeae..951c25f9d 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -254,7 +254,7 @@ const char HTTP_FORM_MODULE[] PROGMEM = "" "
" D_MODULE_TYPE " ({mt)

"; const char HTTP_LNK_ITEM[] PROGMEM = - "
{v} {i} {r}%
"; + "
{v} ({w}) {i} {r}%
"; const char HTTP_LNK_SCAN[] PROGMEM = "
"; const char HTTP_FORM_WIFI[] PROGMEM = @@ -882,7 +882,7 @@ void HandleWifi(boolean scan) //display networks in page for (int i = 0; i < n; i++) { if (-1 == indices[i]) { continue; } // skip dups - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_SSID " %s, " D_RSSI " %d"), WiFi.SSID(indices[i]).c_str(), WiFi.RSSI(indices[i])); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i])); AddLog(LOG_LEVEL_DEBUG); int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); @@ -891,6 +891,7 @@ void HandleWifi(boolean scan) String rssiQ; rssiQ += quality; item.replace(F("{v}"), WiFi.SSID(indices[i])); + item.replace(F("{w}"), String(WiFi.channel(indices[i]))); item.replace(F("{r}"), rssiQ); uint8_t auth = WiFi.encryptionType(indices[i]); item.replace(F("{i}"), (ENC_TYPE_WEP == auth) ? F(D_WEP) : (ENC_TYPE_TKIP == auth) ? F(D_WPA_PSK) : (ENC_TYPE_CCMP == auth) ? F(D_WPA2_PSK) : (ENC_TYPE_AUTO == auth) ? F(D_AUTO) : F("")); From 0ac8c73938cff33f0166d86867e33b190f23ded8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 2 Sep 2018 14:26:00 +0200 Subject: [PATCH 0025/2222] Fix Wemo emulation Fix Wemo emulation to select the first relay when more than one relay is present (#3657) --- sonoff/_changelog.ino | 1 + sonoff/xplg_wemohue.ino | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index d8a14e367..d2781b4d4 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Fix possible ambiguity on command parameters if StateText contains numbers only (#3656) * Fix possible exception due to buffer overflow (#3659) * Add Wifi channel number to state message (#3664) + * Fix Wemo emulation to select the first relay when more than one relay is present (#3657) * * 6.2.0 20180901 * Allow user override of define MAX_RULE_VARS and MAX_RULE_TIMERS (#3561) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 9a7cdeec7..9a5fb9467 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -386,12 +386,18 @@ void HandleUpnpEvent() String state_xml = FPSTR(WEMO_RESPONSE_STATE_SOAP); //differentiate get and set state if (request.indexOf(F("SetBinaryState")) > 0) { + uint8_t power = POWER_TOGGLE; if (request.indexOf(F("State>1 0) { - ExecuteCommandPower(devices_present, POWER_ON, SRC_WEMO); + power = POWER_ON } else if (request.indexOf(F("State>0 0) { - ExecuteCommandPower(devices_present, POWER_OFF, SRC_WEMO); + power = POWER_OFF; } + if (power != POWER_TOGGLE) { + uint8_t device = (light_type) ? devices_present : 1; // Select either a configured light or relay1 + ExecuteCommandPower(device, power, SRC_WEMO); + } + } else if(request.indexOf(F("GetBinaryState")) > 0){ state_xml.replace(F("Set"), F("Get")); From 4b4b0dff855a5e9c1bf7a8d272b2a73fa8fbb223 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 2 Sep 2018 14:46:06 +0200 Subject: [PATCH 0026/2222] Fix compile error Fix compile error --- sonoff/xplg_wemohue.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 9a5fb9467..bc579782a 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -388,7 +388,7 @@ void HandleUpnpEvent() if (request.indexOf(F("SetBinaryState")) > 0) { uint8_t power = POWER_TOGGLE; if (request.indexOf(F("State>1 0) { - power = POWER_ON + power = POWER_ON; } else if (request.indexOf(F("State>0 0) { power = POWER_OFF; From 5ff735e4e783a46d68f333ce2a6b1a6618cdc294 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 2 Sep 2018 15:21:58 +0200 Subject: [PATCH 0027/2222] Remove obsolete linker file Remove obsolete linker file as platformio now supports 1m0 out of the box --- esp8266.flash.1m0.ld | 18 ------------------ platformio.ini | 2 +- 2 files changed, 1 insertion(+), 19 deletions(-) delete mode 100644 esp8266.flash.1m0.ld diff --git a/esp8266.flash.1m0.ld b/esp8266.flash.1m0.ld deleted file mode 100644 index 1f9b56a87..000000000 --- a/esp8266.flash.1m0.ld +++ /dev/null @@ -1,18 +0,0 @@ -/* Flash Split for 1M chips */ -/* sketch 999KB */ -/* eeprom 20KB */ - -MEMORY -{ - dport0_0_seg : org = 0x3FF00000, len = 0x10 - dram0_0_seg : org = 0x3FFE8000, len = 0x14000 - iram1_0_seg : org = 0x40100000, len = 0x8000 - irom0_0_seg : org = 0x40201010, len = 0xf9ff0 -} - -PROVIDE ( _SPIFFS_start = 0x402FB000 ); -PROVIDE ( _SPIFFS_end = 0x402FB000 ); -PROVIDE ( _SPIFFS_page = 0 ); -PROVIDE ( _SPIFFS_block = 0 ); - -INCLUDE "esp8266.flash.common.ld" diff --git a/platformio.ini b/platformio.ini index 4cda52b6f..03e61b1dc 100644 --- a/platformio.ini +++ b/platformio.ini @@ -60,7 +60,7 @@ board_build.f_cpu = 80000000L build_unflags = -Wall build_flags = - -Wl,-Tesp8266.flash.1m0.ld + -Wl,-Teagle.flash.1m0.ld ; -DUSE_CONFIG_OVERRIDE ; lwIP 1.4 (Default) ; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH From 9ff3233b9755fd1a1f160af5ace605ff1dab8e4a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 2 Sep 2018 15:23:11 +0200 Subject: [PATCH 0028/2222] Revert "Remove obsolete linker file" This reverts commit 5ff735e4e783a46d68f333ce2a6b1a6618cdc294. --- esp8266.flash.1m0.ld | 18 ++++++++++++++++++ platformio.ini | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 esp8266.flash.1m0.ld diff --git a/esp8266.flash.1m0.ld b/esp8266.flash.1m0.ld new file mode 100644 index 000000000..1f9b56a87 --- /dev/null +++ b/esp8266.flash.1m0.ld @@ -0,0 +1,18 @@ +/* Flash Split for 1M chips */ +/* sketch 999KB */ +/* eeprom 20KB */ + +MEMORY +{ + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40201010, len = 0xf9ff0 +} + +PROVIDE ( _SPIFFS_start = 0x402FB000 ); +PROVIDE ( _SPIFFS_end = 0x402FB000 ); +PROVIDE ( _SPIFFS_page = 0 ); +PROVIDE ( _SPIFFS_block = 0 ); + +INCLUDE "esp8266.flash.common.ld" diff --git a/platformio.ini b/platformio.ini index 03e61b1dc..4cda52b6f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -60,7 +60,7 @@ board_build.f_cpu = 80000000L build_unflags = -Wall build_flags = - -Wl,-Teagle.flash.1m0.ld + -Wl,-Tesp8266.flash.1m0.ld ; -DUSE_CONFIG_OVERRIDE ; lwIP 1.4 (Default) ; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH From 2210bda2e6ff3c0033959cb27014119fed6fea9f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 2 Sep 2018 15:54:26 +0200 Subject: [PATCH 0029/2222] Replace APMac with BSSId Replace APMac with BSSId in state and status 11 --- sonoff/i18n.h | 1 + sonoff/sonoff.ino | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index cfc30e6bc..5559ac6d1 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -39,6 +39,7 @@ #define D_JSON_BLOCKED_LOOP "Blocked Loop" #define D_JSON_BOOTVERSION "Boot" #define D_JSON_BOOTCOUNT "BootCount" +#define D_JSON_BSSID "BSSId" #define D_JSON_BUILDDATETIME "BuildDateTime" #define D_JSON_CHANNEL "Channel" #define D_JSON_CO2 "CarbonDioxide" diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 9a167eddf..8d82efc18 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1532,8 +1532,8 @@ void MqttShowState() MqttShowPWMState(); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_APMAC_ADDRESS "\":\"%s\"}}"), - mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d}}"), + mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI())); } boolean MqttShowSensor() From 44ecdaf952b7e0cf42cf30ffebb996b75e52e1ad Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 2 Sep 2018 16:17:49 +0200 Subject: [PATCH 0030/2222] Add support for Shelly Add support for Shelly 1 and basic support for Shelly 2 - No energy monitoring yet (#2789) --- sonoff/_changelog.ino | 1 + sonoff/sonoff_template.h | 52 ++++++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index d2781b4d4..a59ba99cb 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Fix possible exception due to buffer overflow (#3659) * Add Wifi channel number to state message (#3664) * Fix Wemo emulation to select the first relay when more than one relay is present (#3657) + * Add support for Shelly 1 and basic support for Shelly 2 - No energy monitoring yet (#2789) * * 6.2.0 20180901 * Allow user override of define MAX_RULE_VARS and MAX_RULE_TIMERS (#3561) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 84a0749dc..8d3fac176 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -136,6 +136,9 @@ enum ProgramSelectablePins { GPIO_DI, // my92x1 PWM input GPIO_DCKI, // my92x1 CLK input GPIO_ARIRFRCV, // AliLux RF Receive input + GPIO_MCP39_TX, // MCP39F501 Serial output + GPIO_MCP39_RX, // MCP39F501 Serial input + GPIO_MCP39_RST, // MCP39F501 Serial reset GPIO_USER, // User configurable GPIO_MAX }; @@ -220,6 +223,8 @@ enum SupportedModules { SONOFF_POW_R2, SONOFF_IFAN02, BLITZWOLF_BWSHP2, + SHELLY1, + SHELLY2, MAXMODULE }; /********************************************************************************************/ @@ -271,6 +276,8 @@ const uint8_t kNiceList[MAXMODULE] PROGMEM = { LUANIHVIO, YUNSHAN, WION, + SHELLY1, + SHELLY2, BLITZWOLF_BWSHP2, H801, MAGICHOME, @@ -906,6 +913,27 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_HLW_CF1, // GPIO14 BL0937 or HJL-01 CF1 voltage / current GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) 0, 0 + }, + { "Shelly 1", // Shelly1 Open Source (ESP8266 - 2MB) - https://shelly.cloud/shelly1-open-source/ + 0, 0, 0, 0, + GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) + GPIO_SWT1_NP, // GPIO05 SW pin + 0, 0, 0, 0, 0, 0, // Flash connection + 0, 0, 0, 0, 0, 0 + }, + { "Shelly 2", // Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ + 0, + GPIO_MCP39_RX, // GPIO01 MCP39F501 Serial input + 0, + GPIO_MCP39_TX, // GPIO03 MCP39F501 Serial output + GPIO_REL1, // GPIO04 + GPIO_REL2, // GPIO05 + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_SWT1_NP, // GPIO12 + 0, + GPIO_SWT2_NP, // GPIO14 + GPIO_MCP39_RST, // GPIO15 MCP39F501 Reset + 0, 0 } }; @@ -988,29 +1016,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO15 (D15) GPIO_USER, // GPIO16 (D16) 0 // ADC0 Analog input (A0) - }, - - { "Shelly 1", // Shelly1 Open Source (ESP8266 - 2MB) - https://shelly.cloud/shelly1-open-source/ - GPIO_KEY1, // GPIO00 Button - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - 0, - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) - GPIO_SWT1_NP, // GPIO05 Switch - 0, 0, 0, 0, 0, 0, // Flash connection - 0, 0, 0, 0, 0, 0 - }, - { "Shelly 2", // Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ - // As Gnd is connected to AC no user GPIO allowed - 0, 0, 0, 0, - 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_NP, // GPIO12 Switch 1 - 0, - GPIO_SWT2_NP, // GPIO14 Switch 2 - 0, 0, 0 - }, + } */ #endif // _SONOFF_TEMPLATE_H_ \ No newline at end of file From d557fdbe7b6cee4a5956512fdb632073c7b170ad Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 3 Sep 2018 00:28:03 -0300 Subject: [PATCH 0031/2222] Updated Spanish Translation --- sonoff/language/es-AR.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index c1993ffee..986b9507f 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.1.1c + * Updated until v6.2.0.1 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -65,7 +65,7 @@ #define D_BY "por" // Written by me #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" -#define D_CHANNEL "Channel" +#define D_CHANNEL "Canal" #define D_CO2 "CO2" #define D_CODE "código" // Button code #define D_COLDLIGHT "Fría" @@ -462,7 +462,7 @@ #define D_SENSOR_RELAY "Relé" // 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_COUNTER "Contador" // Suffix "1" #define D_SENSOR_IRRECV "IR RX" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" From 41999a0afcb866c8bc006bc2a7a96fcc74f356ed Mon Sep 17 00:00:00 2001 From: znanev <20048364+znanev@users.noreply.github.com> Date: Mon, 3 Sep 2018 13:49:49 +0100 Subject: [PATCH 0032/2222] Update bg-BG.h --- sonoff/language/bg-BG.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index e85ab66c3..b1ecd6fa6 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.1.1.5 + * Updated until v6.2.0.1 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -65,7 +65,7 @@ #define D_BY "от" // Written by me #define D_BYTES "Байта" #define D_CELSIUS "Целзий" -#define D_CHANNEL "Channel" +#define D_CHANNEL "Канал" #define D_CO2 "Въглероден диоксид" #define D_CODE "код" // Button code #define D_COLDLIGHT "Хладна" @@ -440,12 +440,12 @@ #define D_PARTICALS_BEYOND "Частици" // xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" +#define D_AX_AXIS "Ускорение - ос X" +#define D_AY_AXIS "Ускорение - ос Y" +#define D_AZ_AXIS "Ускорение - ос Z" +#define D_GX_AXIS "Жироскоп - ос X" +#define D_GY_AXIS "Жироскоп - ос Y" +#define D_GZ_AXIS "Жироскоп - ос Z" // sonoff_template.h #define D_SENSOR_NONE "Няма" From ababc351d74b485fa733fdb6b17a7172ab012220 Mon Sep 17 00:00:00 2001 From: MadDoct <32080323+MadDoct@users.noreply.github.com> Date: Tue, 4 Sep 2018 09:45:26 +0100 Subject: [PATCH 0033/2222] prepare to allow h801 tx and rx pins to be gpio_user --- sonoff/sonoff.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 8d82efc18..12aea14e9 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2362,7 +2362,7 @@ void GpioInit() if (mpin) pin[mpin] = i; } - if (2 == pin[GPIO_TXD]) Serial.set_tx(2); + if ((2 == pin[GPIO_TXD]) || (Settings.module == 20)) Serial.set_tx(2); analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) From a8b673487b631a8b2f3ffdd4962dcffe93b9db93 Mon Sep 17 00:00:00 2001 From: MadDoct <32080323+MadDoct@users.noreply.github.com> Date: Tue, 4 Sep 2018 09:56:43 +0100 Subject: [PATCH 0034/2222] h801 tx and rx user selectable --- sonoff/sonoff_template.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 8d3fac176..f2fe93003 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -550,8 +550,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "H801", // Lixada H801 Wifi (ESP8266) GPIO_USER, // GPIO00 E-FW Button 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_USER, // GPIO02 RX and Optional sensor - Pin next to TX on the PCB + GPIO_USER, // GPIO03 TX and Optional sensor - Pin next to GND on the PCB GPIO_PWM5, // GPIO04 W2 - PWM5 GPIO_LED2_INV, // GPIO05 Red LED 0, 0, 0, 0, 0, 0, // Flash connection @@ -1019,4 +1019,4 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { } */ -#endif // _SONOFF_TEMPLATE_H_ \ No newline at end of file +#endif // _SONOFF_TEMPLATE_H_ From 07dafe16312d27e838b42dd6de4a7944bf8927f4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 4 Sep 2018 16:22:34 +0200 Subject: [PATCH 0035/2222] 6.2.0.2 - Energy monitoring 6.2.0.2 20180904 * Rewrite energy monitoring using energy sensor driver modules * Fix lost today and total energy value after power cycle (#3689) --- sonoff/_changelog.ino | 6 +- sonoff/settings.h | 10 +- sonoff/settings.ino | 43 ++- sonoff/sonoff.h | 6 +- sonoff/sonoff.ino | 51 +-- sonoff/sonoff_post.h | 2 + sonoff/sonoff_version.h | 2 +- sonoff/xdrv_03_energy.ino | 638 ++--------------------------------- sonoff/xdrv_06_snfbridge.ino | 3 + sonoff/xdsp_03_matrix.ino | 4 + sonoff/xnrg_01_hlw8012.ino | 283 ++++++++++++++++ sonoff/xnrg_02_cse7766.ino | 248 ++++++++++++++ sonoff/xnrg_03_pzem004t.ino | 248 ++++++++++++++ sonoff/xnrg_interface.ino | 57 ++++ 14 files changed, 949 insertions(+), 652 deletions(-) create mode 100644 sonoff/xnrg_01_hlw8012.ino create mode 100644 sonoff/xnrg_02_cse7766.ino create mode 100644 sonoff/xnrg_03_pzem004t.ino create mode 100644 sonoff/xnrg_interface.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index a59ba99cb..0b3c115cd 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ -/* 6.2.0.1 20180902 +/* 6.2.0.2 20180904 + * Rewrite energy monitoring using energy sensor driver modules + * Fix lost today and total energy value after power cycle (#3689) + * + * 6.2.0.1 20180902 * Fix possible ambiguity on command parameters if StateText contains numbers only (#3656) * Fix possible exception due to buffer overflow (#3659) * Add Wifi channel number to state message (#3664) diff --git a/sonoff/settings.h b/sonoff/settings.h index ded2c140b..3876baf60 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -333,6 +333,12 @@ struct SYSCFG { // E00 - FFF free locations } Settings; +struct RTCRBT { + uint16_t valid; // 000 + uint8_t fast_reboot_count; // 002 + uint8_t free_003[1]; // 003 +} RtcReboot; + struct RTCMEM { uint16_t valid; // 000 byte oswatch_blocked_loop; // 002 @@ -341,9 +347,7 @@ struct RTCMEM { unsigned long energy_kWhtotal; // 008 unsigned long pulse_counter[MAX_COUNTERS]; // 00C power_t power; // 01C - uint16_t extended_valid; // 020 Extended valid flag (v6.1.1.14) - uint8_t fast_reboot_count; // 022 - uint8_t free_023[57]; // 023 + uint8_t free_020[60]; // 020 // 05C next free location (64 (=core) + 100 (=tasmota offset) + 92 (=0x5C RTCMEM struct) = 256 bytes (max = 512)) } RtcSettings; diff --git a/sonoff/settings.ino b/sonoff/settings.ino index cba043696..5626f862b 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -84,7 +84,6 @@ void RtcSettingsSave() { if (GetRtcSettingsCrc() != rtc_settings_crc) { RtcSettings.valid = RTC_MEM_VALID; - RtcSettings.extended_valid = RTC_MEM_VALID; ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); rtc_settings_crc = GetRtcSettingsCrc(); #ifdef DEBUG_THEO @@ -104,14 +103,12 @@ void RtcSettingsLoad() if (RtcSettings.valid != RTC_MEM_VALID) { memset(&RtcSettings, 0, sizeof(RTCMEM)); RtcSettings.valid = RTC_MEM_VALID; - RtcSettings.extended_valid = RTC_MEM_VALID; RtcSettings.energy_kWhtoday = Settings.energy_kWhtoday; RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal; for (byte i = 0; i < MAX_COUNTERS; i++) { RtcSettings.pulse_counter[i] = Settings.pulse_counter[i]; } RtcSettings.power = Settings.power; -// RtcSettings.fast_reboot_count = 0; // Explicit by memset RtcSettingsSave(); } rtc_settings_crc = GetRtcSettingsCrc(); @@ -122,9 +119,45 @@ boolean RtcSettingsValid() return (RTC_MEM_VALID == RtcSettings.valid); } -boolean RtcSettingsExtendedValid() +/********************************************************************************************/ + +uint32_t rtc_reboot_crc = 0; + +uint32_t GetRtcRebootCrc() { - return (RTC_MEM_VALID == RtcSettings.extended_valid); + uint32_t crc = 0; + uint8_t *bytes = (uint8_t*)&RtcReboot; + + for (uint16_t i = 0; i < sizeof(RTCRBT); i++) { + crc += bytes[i]*(i+1); + } + return crc; +} + +void RtcRebootSave() +{ + if (GetRtcRebootCrc() != rtc_reboot_crc) { + RtcReboot.valid = RTC_MEM_VALID; + ESP.rtcUserMemoryWrite(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); + rtc_reboot_crc = GetRtcRebootCrc(); + } +} + +void RtcRebootLoad() +{ + ESP.rtcUserMemoryRead(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); + if (RtcReboot.valid != RTC_MEM_VALID) { + memset(&RtcReboot, 0, sizeof(RTCRBT)); + RtcReboot.valid = RTC_MEM_VALID; +// RtcReboot.fast_reboot_count = 0; // Explicit by memset + RtcRebootSave(); + } + rtc_reboot_crc = GetRtcRebootCrc(); +} + +boolean RtcRebootValid() +{ + return (RTC_MEM_VALID == RtcReboot.valid); } /*********************************************************************************************\ diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 3a1dc14c6..2c5d5cce9 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -202,9 +202,9 @@ enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC}; enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; -enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, - FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, - FUNC_RULES_PROCESS, FUNC_FREE_MEM}; +enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, + FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, + FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 8d82efc18..c92a8db76 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -172,7 +172,7 @@ uint8_t led_inverted = 0; // LED inverted flag (1 = (0 = On, 1 uint8_t pwm_inverted = 0; // PWM inverted flag (1 = inverted) uint8_t counter_no_pullup = 0; // Counter input pullup flag (1 = No pullup) uint8_t dht_flg = 0; // DHT configured -uint8_t energy_flg = 1; // Energy monitor configured +uint8_t energy_flg = 0; // Energy monitor configured uint8_t i2c_flg = 0; // I2C configured uint8_t spi_flg = 0; // SPI configured uint8_t light_type = 0; // Light types @@ -1568,8 +1568,8 @@ void PerformEverySecond() uptime++; if (BOOT_LOOP_TIME == uptime) { - RtcSettings.fast_reboot_count = 0; - RtcSettingsSave(); + RtcReboot.fast_reboot_count = 0; + RtcRebootSave(); } if ((4 == uptime) && (SONOFF_IFAN02 == Settings.module)) { // Microcontroller needs 3 seconds before accepting commands @@ -2193,29 +2193,14 @@ void SerialInput() } } -/*-------------------------------------------------------------------------------------------*\ - * Sonoff bridge 19200 baud serial interface -\*-------------------------------------------------------------------------------------------*/ - if (SONOFF_BRIDGE == Settings.module) { - if (SonoffBridgeSerialInput()) { - serial_in_byte_counter = 0; - Serial.flush(); - return; - } +/*-------------------------------------------------------------------------------------------*/ + + if (XdrvCall(FUNC_SERIAL)) { + serial_in_byte_counter = 0; + Serial.flush(); + return; } -#ifdef USE_ENERGY_SENSOR -/*-------------------------------------------------------------------------------------------*\ - * Sonoff S31 and Sonoff Pow R2 4800 baud serial interface -\*-------------------------------------------------------------------------------------------*/ - if ((SONOFF_S31 == Settings.module) || (SONOFF_POW_R2 == Settings.module)) { - if (CseSerialInput()) { - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - } -#endif // USE_ENERGY_SENSOR /*-------------------------------------------------------------------------------------------*/ if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // binary data... @@ -2491,10 +2476,10 @@ void setup() { byte idx; - RtcSettingsLoad(); - if (!RtcSettingsExtendedValid()) { RtcSettings.fast_reboot_count = 0; } - RtcSettings.fast_reboot_count++; - RtcSettingsSave(); + RtcRebootLoad(); + if (!RtcRebootValid()) { RtcReboot.fast_reboot_count = 0; } + RtcReboot.fast_reboot_count++; + RtcRebootSave(); Serial.begin(baudrate); delay(10); @@ -2528,26 +2513,26 @@ void setup() sleep = Settings.sleep; // Disable functionality as possible cause of fast restart within BOOT_LOOP_TIME seconds (Exception, WDT or restarts) - if (RtcSettings.fast_reboot_count > 1) { // Restart twice + if (RtcReboot.fast_reboot_count > 1) { // Restart twice Settings.flag3.user_esp8285_enable = 0; // Disable ESP8285 Generic GPIOs interfering with flash SPI - if (RtcSettings.fast_reboot_count > 2) { // Restart 3 times + if (RtcReboot.fast_reboot_count > 2) { // Restart 3 times for (byte i = 0; i < MAX_RULE_SETS; i++) { if (bitRead(Settings.rule_stop, i)) { bitWrite(Settings.rule_enabled, i, 0); // Disable rules causing boot loop } } } - if (RtcSettings.fast_reboot_count > 3) { // Restarted 4 times + if (RtcReboot.fast_reboot_count > 3) { // Restarted 4 times Settings.rule_enabled = 0; // Disable all rules } - if (RtcSettings.fast_reboot_count > 4) { // Restarted 5 times + if (RtcReboot.fast_reboot_count > 4) { // Restarted 5 times Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic Settings.last_module = SONOFF_BASIC; for (byte i = 0; i < MAX_GPIO_PIN; i++) { Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors } } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcSettings.fast_reboot_count); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); AddLog(LOG_LEVEL_DEBUG); } diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index b6b8d320c..dc49211d1 100755 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -52,6 +52,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_DHT // Default DHT11 sensor needs no external library #define USE_ENERGY_SENSOR // Use energy sensors +#define USE_HLW8012 // Use energy sensor for Sonoff Pow and WolfBlitz +#define USE_CSE7766 // Use energy sensor for Sonoff S31 and Pow R2 /*********************************************************************************************\ * [sonoff-sensors.bin] diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index c3ea9381e..e9e92cc9d 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020001 +#define VERSION 0x06020002 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 4ea594cdb..5c122c314 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -1,5 +1,5 @@ /* - xdrv_03_energy.ino - HLW8012 (Sonoff Pow) and PZEM004T energy sensor support for Sonoff-Tasmota + xdrv_03_energy.ino - Energy sensor support for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -19,12 +19,12 @@ #ifdef USE_ENERGY_SENSOR /*********************************************************************************************\ - * HLW8012 and PZEM004T - Energy + * Energy \*********************************************************************************************/ -#define FEATURE_POWER_LIMIT true +#define ENERGY_NONE 0 -enum EnergyHardware { ENERGY_NONE, ENERGY_HLW8012, ENERGY_CSE7766, ENERGY_PZEM004T }; +#define FEATURE_POWER_LIMIT true enum EnergyCommands { CMND_POWERDELTA, @@ -76,6 +76,7 @@ uint16_t energy_mplw_counter = 0; byte energy_fifth_second = 0; Ticker ticker_energy; +int energy_command_code = 0; /********************************************************************************************/ void EnergyUpdateToday() @@ -90,543 +91,15 @@ void EnergyUpdateToday() energy_total = (float)(RtcSettings.energy_kWhtotal + energy_kWhtoday) / 100000; } -/*********************************************************************************************\ - * HLW8012, BL0937 or HJL-01 - Energy (Sonoff Pow, HuaFan, KMC70011, BlitzWolf) - * - * Based on Source: Shenzhen Heli Technology Co., Ltd -\*********************************************************************************************/ - -// HLW8012 based (Sonoff Pow, KMC70011, HuaFan) -#define HLW_PREF 10000 // 1000.0W -#define HLW_UREF 2200 // 220.0V -#define HLW_IREF 4545 // 4.545A -#define HLW_SEL_VOLTAGE 1 - -// HJL-01 based (BlitzWolf, Homecube, Gosund) -#define HJL_PREF 1362 -#define HJL_UREF 822 -#define HJL_IREF 3300 -#define HJL_SEL_VOLTAGE 0 - -#define HLW_POWER_PROBE_TIME 10 // Number of seconds to probe for power before deciding none used - -byte hlw_select_ui_flag; -byte hlw_ui_flag = 1; -byte hlw_load_off; -byte hlw_cf1_timer; -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_period_counter; - -unsigned long hlw_power_ratio = 0; -unsigned long hlw_voltage_ratio = 0; -unsigned long hlw_current_ratio = 0; - -unsigned long hlw_cf1_voltage_max_pulse_counter; -unsigned long hlw_cf1_current_max_pulse_counter; - -#ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception -void HlwCfInterrupt() ICACHE_RAM_ATTR; -void HlwCf1Interrupt() ICACHE_RAM_ATTR; -#endif // USE_WS2812_DMA - -void HlwCfInterrupt() // Service Power -{ - unsigned long us = micros(); - - if (hlw_load_off) { // Restart plen measurement - hlw_cf_pulse_last_time = us; - hlw_load_off = 0; - } else { - hlw_cf_pulse_length = us - hlw_cf_pulse_last_time; - hlw_cf_pulse_last_time = us; - hlw_energy_period_counter++; - } -} - -void HlwCf1Interrupt() // Service Voltage and Current -{ - unsigned long us = micros(); - - 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_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) - } - } -} - -void HlwEverySecond() -{ - unsigned long hlw_len; - - if (hlw_energy_period_counter) { - hlw_len = 10000 / hlw_energy_period_counter; - hlw_energy_period_counter = 0; - if (hlw_len) { - energy_kWhtoday_delta += ((hlw_power_ratio * Settings.energy_power_calibration) / hlw_len) / 36; - EnergyUpdateToday(); - } - } -} - -void HlwEvery200ms() -{ - unsigned long hlw_w = 0; - unsigned long hlw_u = 0; - unsigned long hlw_i = 0; - - 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; - } - - if (hlw_cf_pulse_length && energy_power_on && !hlw_load_off) { - hlw_w = (hlw_power_ratio * Settings.energy_power_calibration) / hlw_cf_pulse_length; - energy_power = (float)hlw_w / 10; - } else { - energy_power = 0; - } - - hlw_cf1_timer++; - if (hlw_cf1_timer >= 8) { - hlw_cf1_timer = 0; - hlw_select_ui_flag = (hlw_select_ui_flag) ? 0 : 1; - digitalWrite(pin[GPIO_HLW_SEL], hlw_select_ui_flag); - - if (hlw_cf1_pulse_counter) { - hlw_cf1_pulse_length = hlw_cf1_summed_pulse_length / hlw_cf1_pulse_counter; - } else { - hlw_cf1_pulse_length = 0; - } - if (hlw_select_ui_flag == hlw_ui_flag) { - hlw_cf1_voltage_pulse_length = hlw_cf1_pulse_length; - hlw_cf1_voltage_max_pulse_counter = hlw_cf1_pulse_counter; - - if (hlw_cf1_voltage_pulse_length && energy_power_on) { // If powered on always provide voltage - hlw_u = (hlw_voltage_ratio * Settings.energy_voltage_calibration) / hlw_cf1_voltage_pulse_length; - energy_voltage = (float)hlw_u / 10; - } else { - energy_voltage = 0; - } - - } else { - hlw_cf1_current_pulse_length = hlw_cf1_pulse_length; - hlw_cf1_current_max_pulse_counter = hlw_cf1_pulse_counter; - - if (hlw_cf1_current_pulse_length && energy_power) { // No current if no power being consumed - hlw_i = (hlw_current_ratio * Settings.energy_current_calibration) / hlw_cf1_current_pulse_length; - energy_current = (float)hlw_i / 1000; - } else { - energy_current = 0; - } - - } - hlw_cf1_summed_pulse_length = 0; - hlw_cf1_pulse_counter = 0; - } -} - -void HlwInit() -{ - if (!Settings.energy_power_calibration || (4975 == Settings.energy_power_calibration)) { - Settings.energy_power_calibration = HLW_PREF_PULSE; - Settings.energy_voltage_calibration = HLW_UREF_PULSE; - Settings.energy_current_calibration = HLW_IREF_PULSE; - } - - if (BLITZWOLF_BWSHP2 == Settings.module) { - hlw_power_ratio = HJL_PREF; - hlw_voltage_ratio = HJL_UREF; - hlw_current_ratio = HJL_IREF; - hlw_ui_flag = HJL_SEL_VOLTAGE; - } else { - hlw_power_ratio = HLW_PREF; - hlw_voltage_ratio = HLW_UREF; - hlw_current_ratio = HLW_IREF; - hlw_ui_flag = HLW_SEL_VOLTAGE; - } - - 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_energy_period_counter = 0; - - hlw_select_ui_flag = 0; // Voltage; - - pinMode(pin[GPIO_HLW_SEL], OUTPUT); - digitalWrite(pin[GPIO_HLW_SEL], hlw_select_ui_flag); - pinMode(pin[GPIO_HLW_CF1], INPUT_PULLUP); - attachInterrupt(pin[GPIO_HLW_CF1], HlwCf1Interrupt, FALLING); - pinMode(pin[GPIO_HLW_CF], INPUT_PULLUP); - attachInterrupt(pin[GPIO_HLW_CF], HlwCfInterrupt, FALLING); - - hlw_cf1_timer = 0; -} - -/*********************************************************************************************\ - * CSE7766 - Energy (Sonoff S31 and Sonoff Pow R2) - * - * Based on datasheet from http://www.chipsea.com/UploadFiles/2017/08/11144342F01B5662.pdf -\*********************************************************************************************/ - -#define CSE_NOT_CALIBRATED 0xAA - -#define CSE_PULSES_NOT_INITIALIZED -1 - -#define CSE_PREF 1000 -#define CSE_UREF 100 - -uint8_t cse_receive_flag = 0; - -long voltage_cycle = 0; -long current_cycle = 0; -long power_cycle = 0; -unsigned long power_cycle_first = 0; -long cf_pulses = 0; -long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; - -void CseReceived() -{ - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 - // 55 5A 02 F7 60 00 03 AB 00 40 10 02 60 5D 51 A6 58 03 E9 EF 71 0B 7A 36 - // Hd Id VCal---- Voltage- ICal---- Current- PCal---- Power--- Ad CF--- Ck - - uint8_t header = serial_in_buffer[0]; - if ((header & 0xFC) == 0xFC) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Abnormal hardware")); - return; - } - - // Get chip calibration data (coefficients) and use as initial defaults - if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) { - long voltage_coefficient = 191200; // uSec - if (CSE_NOT_CALIBRATED != header) { - voltage_coefficient = serial_in_buffer[2] << 16 | serial_in_buffer[3] << 8 | serial_in_buffer[4]; - } - Settings.energy_voltage_calibration = voltage_coefficient / CSE_UREF; - } - if (HLW_IREF_PULSE == Settings.energy_current_calibration) { - long current_coefficient = 16140; // uSec - if (CSE_NOT_CALIBRATED != header) { - current_coefficient = serial_in_buffer[8] << 16 | serial_in_buffer[9] << 8 | serial_in_buffer[10]; - } - Settings.energy_current_calibration = current_coefficient; - } - if (HLW_PREF_PULSE == Settings.energy_power_calibration) { - long power_coefficient = 5364000; // uSec - if (CSE_NOT_CALIBRATED != header) { - power_coefficient = serial_in_buffer[14] << 16 | serial_in_buffer[15] << 8 | serial_in_buffer[16]; - } - Settings.energy_power_calibration = power_coefficient / CSE_PREF; - } - - uint8_t adjustement = serial_in_buffer[20]; - voltage_cycle = serial_in_buffer[5] << 16 | serial_in_buffer[6] << 8 | serial_in_buffer[7]; - current_cycle = serial_in_buffer[11] << 16 | serial_in_buffer[12] << 8 | serial_in_buffer[13]; - power_cycle = serial_in_buffer[17] << 16 | serial_in_buffer[18] << 8 | serial_in_buffer[19]; - cf_pulses = serial_in_buffer[21] << 8 | serial_in_buffer[22]; - - if (energy_power_on) { // Powered on - if (adjustement & 0x40) { // Voltage valid - energy_voltage = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)voltage_cycle; - } - if (adjustement & 0x10) { // Power valid - if ((header & 0xF2) == 0xF2) { // Power cycle exceeds range - energy_power = 0; - } else { - if (0 == power_cycle_first) power_cycle_first = power_cycle; // Skip first incomplete power_cycle - if (power_cycle_first != power_cycle) { - power_cycle_first = -1; - energy_power = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)power_cycle; - } else { - energy_power = 0; - } - } - } else { - power_cycle_first = 0; - energy_power = 0; // Powered on but no load - } - if (adjustement & 0x20) { // Current valid - if (0 == energy_power) { - energy_current = 0; - } else { - energy_current = (float)Settings.energy_current_calibration / (float)current_cycle; - } - } - } else { // Powered off - power_cycle_first = 0; - energy_voltage = 0; - energy_power = 0; - energy_current = 0; - } -} - -bool CseSerialInput() -{ - if (cse_receive_flag) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (24 == serial_in_byte_counter) { - - AddLogSerial(LOG_LEVEL_DEBUG_MORE); - - uint8_t checksum = 0; - for (byte i = 2; i < 23; i++) { checksum += serial_in_buffer[i]; } - if (checksum == serial_in_buffer[23]) { - CseReceived(); - cse_receive_flag = 0; - return 1; - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); - do { // Sync buffer with data (issue #1907 and #3425) - memmove(serial_in_buffer, serial_in_buffer +1, 24); - serial_in_byte_counter--; - } while ((serial_in_byte_counter > 2) && (0x5A != serial_in_buffer[1])); - if (0x5A != serial_in_buffer[1]) { - cse_receive_flag = 0; - serial_in_byte_counter = 0; - } - } - } - } else { - if ((0x5A == serial_in_byte) && (1 == serial_in_byte_counter)) { // 0x5A - Packet header 2 - cse_receive_flag = 1; - } else { - serial_in_byte_counter = 0; - } - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - } - serial_in_byte = 0; // Discard - return 0; -} - -void CseEverySecond() -{ - long cf_frequency = 0; - - if (CSE_PULSES_NOT_INITIALIZED == cf_pulses_last_time) { - cf_pulses_last_time = cf_pulses; // Init after restart - } else { - if (cf_pulses < cf_pulses_last_time) { // Rolled over after 65535 pulses - cf_frequency = (65536 - cf_pulses_last_time) + cf_pulses; - } else { - cf_frequency = cf_pulses - cf_pulses_last_time; - } - if (cf_frequency && energy_power) { - cf_pulses_last_time = cf_pulses; - energy_kWhtoday_delta += (cf_frequency * Settings.energy_power_calibration) / 36; - EnergyUpdateToday(); - } - } -} - -#ifdef USE_PZEM004T -/*********************************************************************************************\ - * PZEM004T - Energy - * - * Source: Victor Ferrer https://github.com/vicfergar/Sonoff-MQTT-OTA-Arduino - * Based on: PZEM004T library https://github.com/olehs/PZEM004T - * - * Hardware Serial will be selected if GPIO1 = [PZEM Rx] and [GPIO3 = PZEM Tx] -\*********************************************************************************************/ - -#include - -TasmotaSerial *PzemSerial; - -#define PZEM_VOLTAGE (uint8_t)0xB0 -#define RESP_VOLTAGE (uint8_t)0xA0 - -#define PZEM_CURRENT (uint8_t)0xB1 -#define RESP_CURRENT (uint8_t)0xA1 - -#define PZEM_POWER (uint8_t)0xB2 -#define RESP_POWER (uint8_t)0xA2 - -#define PZEM_ENERGY (uint8_t)0xB3 -#define RESP_ENERGY (uint8_t)0xA3 - -#define PZEM_SET_ADDRESS (uint8_t)0xB4 -#define RESP_SET_ADDRESS (uint8_t)0xA4 - -#define PZEM_POWER_ALARM (uint8_t)0xB5 -#define RESP_POWER_ALARM (uint8_t)0xA5 - -#define PZEM_DEFAULT_READ_TIMEOUT 500 - /*********************************************************************************************/ -struct PZEMCommand { - uint8_t command; - uint8_t addr[4]; - uint8_t data; - uint8_t crc; -}; - -IPAddress pzem_ip(192, 168, 1, 1); - -uint8_t PzemCrc(uint8_t *data) -{ - uint16_t crc = 0; - for (uint8_t i = 0; i < sizeof(PZEMCommand) -1; i++) crc += *data++; - return (uint8_t)(crc & 0xFF); -} - -void PzemSend(uint8_t cmd) -{ - PZEMCommand pzem; - - pzem.command = cmd; - for (uint8_t i = 0; i < sizeof(pzem.addr); i++) pzem.addr[i] = pzem_ip[i]; - pzem.data = 0; - - uint8_t *bytes = (uint8_t*)&pzem; - pzem.crc = PzemCrc(bytes); - - PzemSerial->flush(); - PzemSerial->write(bytes, sizeof(pzem)); -} - -bool PzemReceiveReady() -{ - return PzemSerial->available() >= (int)sizeof(PZEMCommand); -} - -bool PzemRecieve(uint8_t resp, float *data) -{ - // 0 1 2 3 4 5 6 - // A4 00 00 00 00 00 A4 - Set address - // A0 00 D4 07 00 00 7B - Voltage (212.7V) - // A1 00 00 0A 00 00 AB - Current (0.1A) - // A1 00 00 00 00 00 A1 - No current - // A2 00 16 00 00 00 B8 - Power (22W) - // A2 00 00 00 00 00 A2 - No power - // A3 00 08 A4 00 00 4F - Energy (2.212kWh) - // A3 01 86 9F 00 00 C9 - Energy (99.999kWh) - - uint8_t buffer[sizeof(PZEMCommand)] = { 0 }; - - unsigned long start = millis(); - uint8_t len = 0; - while ((len < sizeof(PZEMCommand)) && (millis() - start < PZEM_DEFAULT_READ_TIMEOUT)) { - if (PzemSerial->available() > 0) { - uint8_t c = (uint8_t)PzemSerial->read(); - if (!c && !len) { - continue; // skip 0 at startup - } - if ((1 == len) && (buffer[0] == c)) { - len--; - continue; // fix skewed data - } - buffer[len++] = c; - } - } - - AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, len); - - if (len != sizeof(PZEMCommand)) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Pzem comms timeout")); - return false; - } - if (buffer[6] != PzemCrc(buffer)) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Pzem crc error")); - return false; - } - if (buffer[0] != resp) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Pzem bad response")); - return false; - } - - switch (resp) { - case RESP_VOLTAGE: - *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 10.0); // 65535.x V - break; - case RESP_CURRENT: - *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 100.0); // 65535.xx A - break; - case RESP_POWER: - *data = (float)(buffer[1] << 8) + buffer[2]; // 65535 W - break; - case RESP_ENERGY: - *data = (float)((uint32_t)buffer[1] << 16) + ((uint16_t)buffer[2] << 8) + buffer[3]; // 16777215 Wh - break; - } - return true; -} - -/*********************************************************************************************/ - -const uint8_t pzem_commands[] { PZEM_SET_ADDRESS, PZEM_VOLTAGE, PZEM_CURRENT, PZEM_POWER, PZEM_ENERGY }; -const uint8_t pzem_responses[] { RESP_SET_ADDRESS, RESP_VOLTAGE, RESP_CURRENT, RESP_POWER, RESP_ENERGY }; - -uint8_t pzem_read_state = 0; -uint8_t pzem_sendRetry = 0; - -void PzemEvery200ms() -{ - bool data_ready = PzemReceiveReady(); - - if (data_ready) { - float value = 0; - if (PzemRecieve(pzem_responses[pzem_read_state], &value)) { - switch (pzem_read_state) { - case 1: // Voltage as 230.2V - energy_voltage = value; - break; - case 2: // Current as 17.32A - energy_current = value; - break; - case 3: // Power as 20W - energy_power = value; - break; - case 4: // Total energy as 99999Wh - if (!energy_start || (value < energy_start)) energy_start = value; // Init after restart and hanlde roll-over if any - energy_kWhtoday += (value - energy_start) * 100; - energy_start = value; - EnergyUpdateToday(); - break; - } - pzem_read_state++; - if (5 == pzem_read_state) pzem_read_state = 1; - } - } - - if (0 == pzem_sendRetry || data_ready) { - pzem_sendRetry = 5; - PzemSend(pzem_commands[pzem_read_state]); - } - else { - pzem_sendRetry--; - } -} - -/********************************************************************************************/ -#endif // USE_PZEM004T - void Energy200ms() { energy_fifth_second++; if (5 == energy_fifth_second) { energy_fifth_second = 0; - if (ENERGY_HLW8012 == energy_flg) HlwEverySecond(); - if (ENERGY_CSE7766 == energy_flg) CseEverySecond(); + XnrgCall(FUNC_EVERY_SECOND); if (RtcTime.valid) { if (LocalTime() == Midnight()) { @@ -647,10 +120,7 @@ void Energy200ms() energy_power_on = (power &1) | Settings.flag.no_power_on_check; - if (ENERGY_HLW8012 == energy_flg) HlwEvery200ms(); -#ifdef USE_PZEM004T - if (ENERGY_PZEM004T == energy_flg) PzemEvery200ms(); -#endif // USE_PZEM004T + XnrgCall(FUNC_EVERY_200_MSECOND); float power_factor = 0; if (energy_voltage && energy_current && energy_power) { @@ -721,7 +191,7 @@ void EnergyMarginCheck() energy_voltage_u = (uint16_t)(energy_voltage); energy_current_u = (uint16_t)(energy_current * 1000); -// snprintf_P(log_data, sizeof(log_data), PSTR("HLW: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); +// snprintf_P(log_data, sizeof(log_data), PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); // AddLog(LOG_LEVEL_DEBUG); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); @@ -849,6 +319,7 @@ boolean EnergyCommand() unsigned long nvalue = 0; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kEnergyCommands); + energy_command_code = command_code; if (-1 == command_code) { serviced = false; // Unknown command } @@ -936,63 +407,38 @@ boolean EnergyCommand() command, energy_total_chr, energy_yesterday_chr, energy_daily_chr); status_flag = 1; } - - else if (((ENERGY_HLW8012 == energy_flg) || (ENERGY_CSE7766 == energy_flg)) && (CMND_POWERCAL == command_code)) { + else if ((CMND_POWERCAL == command_code) && XnrgCall(FUNC_COMMAND)) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 32001)) { Settings.energy_power_calibration = (XdrvMailbox.payload > 4000) ? XdrvMailbox.payload : HLW_PREF_PULSE; // HLW = 12530, CSE = 5364 } nvalue = Settings.energy_power_calibration; unit = UNIT_MICROSECOND; } - else if (((ENERGY_HLW8012 == energy_flg) || (ENERGY_CSE7766 == energy_flg)) && (CMND_POWERSET == command_code)) { // Watt - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3601)) { - if ((ENERGY_HLW8012 == energy_flg) && hlw_cf_pulse_length) { - Settings.energy_power_calibration = (XdrvMailbox.payload * 10 * hlw_cf_pulse_length) / hlw_power_ratio; - } - else if ((ENERGY_CSE7766 == energy_flg) && power_cycle) { - Settings.energy_power_calibration = (XdrvMailbox.payload * power_cycle) / CSE_PREF; - } - } - snprintf_P(command, sizeof(command), PSTR(D_CMND_POWERCAL)); - nvalue = Settings.energy_power_calibration; - unit = UNIT_MICROSECOND; - } - else if (((ENERGY_HLW8012 == energy_flg) || (ENERGY_CSE7766 == energy_flg)) && (CMND_VOLTAGECAL == command_code)) { + else if ((CMND_VOLTAGECAL == command_code) && XnrgCall(FUNC_COMMAND)) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 32001)) { Settings.energy_voltage_calibration = (XdrvMailbox.payload > 999) ? XdrvMailbox.payload : HLW_UREF_PULSE; // HLW = 1950, CSE = 1912 } nvalue = Settings.energy_voltage_calibration; unit = UNIT_MICROSECOND; } - else if (((ENERGY_HLW8012 == energy_flg) || (ENERGY_CSE7766 == energy_flg)) && (CMND_VOLTAGESET == command_code)) { // Volt - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 501)) { - if ((ENERGY_HLW8012 == energy_flg) && hlw_cf1_voltage_pulse_length) { - Settings.energy_voltage_calibration = (XdrvMailbox.payload * 10 * hlw_cf1_voltage_pulse_length) / hlw_voltage_ratio; - } - else if ((ENERGY_CSE7766 == energy_flg) && voltage_cycle) { - Settings.energy_voltage_calibration = (XdrvMailbox.payload * voltage_cycle) / CSE_UREF; - } - } - snprintf_P(command, sizeof(command), PSTR(D_CMND_VOLTAGECAL)); - nvalue = Settings.energy_voltage_calibration; - unit = UNIT_MICROSECOND; - } - else if (((ENERGY_HLW8012 == energy_flg) || (ENERGY_CSE7766 == energy_flg)) && (CMND_CURRENTCAL == command_code)) { + else if ((CMND_CURRENTCAL == command_code) && XnrgCall(FUNC_COMMAND)) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 32001)) { Settings.energy_current_calibration = (XdrvMailbox.payload > 1100) ? XdrvMailbox.payload : HLW_IREF_PULSE; // HLW = 3500, CSE = 16140 } nvalue = Settings.energy_current_calibration; unit = UNIT_MICROSECOND; } - else if (((ENERGY_HLW8012 == energy_flg) || (ENERGY_CSE7766 == energy_flg)) && (CMND_CURRENTSET == command_code)) { // milliAmpere - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 16001)) { - if ((ENERGY_HLW8012 == energy_flg) && hlw_cf1_current_pulse_length) { - Settings.energy_current_calibration = (XdrvMailbox.payload * hlw_cf1_current_pulse_length) / hlw_current_ratio; - } - else if ((ENERGY_CSE7766 == energy_flg) && current_cycle) { - Settings.energy_current_calibration = (XdrvMailbox.payload * current_cycle) / 1000; - } - } + else if ((CMND_POWERSET == command_code) && XnrgCall(FUNC_COMMAND)) { // Watt + snprintf_P(command, sizeof(command), PSTR(D_CMND_POWERCAL)); + nvalue = Settings.energy_power_calibration; + unit = UNIT_MICROSECOND; + } + else if ((CMND_VOLTAGESET == command_code) && XnrgCall(FUNC_COMMAND)) { // Volt + snprintf_P(command, sizeof(command), PSTR(D_CMND_VOLTAGECAL)); + nvalue = Settings.energy_voltage_calibration; + unit = UNIT_MICROSECOND; + } + else if ((CMND_CURRENTSET == command_code) && XnrgCall(FUNC_COMMAND)) { // milliAmpere snprintf_P(command, sizeof(command), PSTR(D_CMND_CURRENTCAL)); nvalue = Settings.energy_current_calibration; unit = UNIT_MICROSECOND; @@ -1070,38 +516,15 @@ boolean EnergyCommand() return serviced; } -/********************************************************************************************/ - void EnergyDrvInit() { energy_flg = ENERGY_NONE; - if ((pin[GPIO_HLW_SEL] < 99) && (pin[GPIO_HLW_CF1] < 99) && (pin[GPIO_HLW_CF] < 99)) { // Sonoff Pow or any HLW8012 based device - energy_flg = ENERGY_HLW8012; - } else if ((SONOFF_S31 == Settings.module) || (SONOFF_POW_R2 == Settings.module)) { // Sonoff S31 or Sonoff Pow R2 - baudrate = 4800; - serial_config = SERIAL_8E1; - energy_flg = ENERGY_CSE7766; -#ifdef USE_PZEM004T - } else if ((pin[GPIO_PZEM_RX] < 99) && (pin[GPIO_PZEM_TX] < 99)) { // Any device with a Pzem004T - energy_flg = ENERGY_PZEM004T; -#endif // USE_PZEM004T - } + XnrgCall(FUNC_PRE_INIT); } void EnergySnsInit() { - if (ENERGY_HLW8012 == energy_flg) HlwInit(); - -#ifdef USE_PZEM004T - if (ENERGY_PZEM004T == energy_flg) { // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions - PzemSerial = new TasmotaSerial(pin[GPIO_PZEM_RX], pin[GPIO_PZEM_TX], 1); - if (PzemSerial->begin(9600)) { - if (PzemSerial->hardwareSerial()) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } - } -#endif // USE_PZEM004T + XnrgCall(FUNC_INIT); if (energy_flg) { energy_kWhtoday = (RtcSettingsValid()) ? RtcSettings.energy_kWhtoday : (RtcTime.day_of_year == Settings.energy_kWhdoy) ? Settings.energy_kWhtoday : 0; @@ -1192,17 +615,20 @@ boolean Xdrv03(byte function) { boolean result = false; - if (energy_flg) { + if (FUNC_PRE_INIT == function) { + EnergyDrvInit(); + } + else if (energy_flg) { switch (function) { - case FUNC_PRE_INIT: - EnergyDrvInit(); - break; case FUNC_COMMAND: result = EnergyCommand(); break; case FUNC_SET_POWER: EnergySetPowerSteadyCounter(); break; + case FUNC_SERIAL: + result = XnrgCall(FUNC_SERIAL); + break; } } return result; diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 73c93d374..b0518f133 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -592,6 +592,9 @@ boolean Xdrv06(byte function) case FUNC_COMMAND: result = SonoffBridgeCommand(); break; + case FUNC_SERIAL: + result = SonoffBridgeSerialInput(); + break; } } return result; diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index aef33dbc3..4989ad24b 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -253,6 +253,10 @@ void MatrixPrintLog(uint8_t direction) strncat(mtx_buffer, (const char*)txt +i, 1); } } + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "[%s]"), mtx_buffer); + AddLog(LOG_LEVEL_DEBUG); + mtx_done = 1; } diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino new file mode 100644 index 000000000..440112c15 --- /dev/null +++ b/sonoff/xnrg_01_hlw8012.ino @@ -0,0 +1,283 @@ +/* + xnrg_01_hlw8012.ino - HLW8012 (Sonoff Pow) energy sensor support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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_ENERGY_SENSOR +#ifdef USE_HLW8012 +/*********************************************************************************************\ + * HLW8012, BL0937 or HJL-01 - Energy (Sonoff Pow, HuaFan, KMC70011, BlitzWolf) + * + * Based on Source: Shenzhen Heli Technology Co., Ltd +\*********************************************************************************************/ + +#define XNRG_01 1 + +// HLW8012 based (Sonoff Pow, KMC70011, HuaFan) +#define HLW_PREF 10000 // 1000.0W +#define HLW_UREF 2200 // 220.0V +#define HLW_IREF 4545 // 4.545A +#define HLW_SEL_VOLTAGE 1 + +// HJL-01 based (BlitzWolf, Homecube, Gosund) +#define HJL_PREF 1362 +#define HJL_UREF 822 +#define HJL_IREF 3300 +#define HJL_SEL_VOLTAGE 0 + +#define HLW_POWER_PROBE_TIME 10 // Number of seconds to probe for power before deciding none used + +static byte hlw_select_ui_flag; +static byte hlw_ui_flag = 1; +static byte hlw_load_off; +static byte hlw_cf1_timer; +static unsigned long hlw_cf_pulse_length; +static unsigned long hlw_cf_pulse_last_time; +static unsigned long hlw_cf1_pulse_length; +static unsigned long hlw_cf1_pulse_last_time; +static unsigned long hlw_cf1_summed_pulse_length; +static unsigned long hlw_cf1_pulse_counter; +static unsigned long hlw_cf1_voltage_pulse_length; +static unsigned long hlw_cf1_current_pulse_length; +static unsigned long hlw_energy_period_counter; + +static unsigned long hlw_power_ratio = 0; +static unsigned long hlw_voltage_ratio = 0; +static unsigned long hlw_current_ratio = 0; + +static unsigned long hlw_cf1_voltage_max_pulse_counter; +static unsigned long hlw_cf1_current_max_pulse_counter; + +#ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception +void HlwCfInterrupt() ICACHE_RAM_ATTR; +void HlwCf1Interrupt() ICACHE_RAM_ATTR; +#endif // USE_WS2812_DMA + +void HlwCfInterrupt() // Service Power +{ + unsigned long us = micros(); + + if (hlw_load_off) { // Restart plen measurement + hlw_cf_pulse_last_time = us; + hlw_load_off = 0; + } else { + hlw_cf_pulse_length = us - hlw_cf_pulse_last_time; + hlw_cf_pulse_last_time = us; + hlw_energy_period_counter++; + } +} + +void HlwCf1Interrupt() // Service Voltage and Current +{ + unsigned long us = micros(); + + 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_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) + } + } +} + +/********************************************************************************************/ + +void HlwEvery200ms() +{ + unsigned long hlw_w = 0; + unsigned long hlw_u = 0; + unsigned long hlw_i = 0; + + 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; + } + + if (hlw_cf_pulse_length && energy_power_on && !hlw_load_off) { + hlw_w = (hlw_power_ratio * Settings.energy_power_calibration) / hlw_cf_pulse_length; + energy_power = (float)hlw_w / 10; + } else { + energy_power = 0; + } + + hlw_cf1_timer++; + if (hlw_cf1_timer >= 8) { + hlw_cf1_timer = 0; + hlw_select_ui_flag = (hlw_select_ui_flag) ? 0 : 1; + digitalWrite(pin[GPIO_HLW_SEL], hlw_select_ui_flag); + + if (hlw_cf1_pulse_counter) { + hlw_cf1_pulse_length = hlw_cf1_summed_pulse_length / hlw_cf1_pulse_counter; + } else { + hlw_cf1_pulse_length = 0; + } + if (hlw_select_ui_flag == hlw_ui_flag) { + hlw_cf1_voltage_pulse_length = hlw_cf1_pulse_length; + hlw_cf1_voltage_max_pulse_counter = hlw_cf1_pulse_counter; + + if (hlw_cf1_voltage_pulse_length && energy_power_on) { // If powered on always provide voltage + hlw_u = (hlw_voltage_ratio * Settings.energy_voltage_calibration) / hlw_cf1_voltage_pulse_length; + energy_voltage = (float)hlw_u / 10; + } else { + energy_voltage = 0; + } + + } else { + hlw_cf1_current_pulse_length = hlw_cf1_pulse_length; + hlw_cf1_current_max_pulse_counter = hlw_cf1_pulse_counter; + + if (hlw_cf1_current_pulse_length && energy_power) { // No current if no power being consumed + hlw_i = (hlw_current_ratio * Settings.energy_current_calibration) / hlw_cf1_current_pulse_length; + energy_current = (float)hlw_i / 1000; + } else { + energy_current = 0; + } + + } + hlw_cf1_summed_pulse_length = 0; + hlw_cf1_pulse_counter = 0; + } +} + +void HlwEverySecond() +{ + unsigned long hlw_len; + + if (hlw_energy_period_counter) { + hlw_len = 10000 / hlw_energy_period_counter; + hlw_energy_period_counter = 0; + if (hlw_len) { + energy_kWhtoday_delta += ((hlw_power_ratio * Settings.energy_power_calibration) / hlw_len) / 36; + EnergyUpdateToday(); + } + } +} + +void HlwSnsInit() +{ + if (!Settings.energy_power_calibration || (4975 == Settings.energy_power_calibration)) { + Settings.energy_power_calibration = HLW_PREF_PULSE; + Settings.energy_voltage_calibration = HLW_UREF_PULSE; + Settings.energy_current_calibration = HLW_IREF_PULSE; + } + + if (BLITZWOLF_BWSHP2 == Settings.module) { + hlw_power_ratio = HJL_PREF; + hlw_voltage_ratio = HJL_UREF; + hlw_current_ratio = HJL_IREF; + hlw_ui_flag = HJL_SEL_VOLTAGE; + } else { + hlw_power_ratio = HLW_PREF; + hlw_voltage_ratio = HLW_UREF; + hlw_current_ratio = HLW_IREF; + hlw_ui_flag = HLW_SEL_VOLTAGE; + } + + 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_energy_period_counter = 0; + + hlw_select_ui_flag = 0; // Voltage; + + pinMode(pin[GPIO_HLW_SEL], OUTPUT); + digitalWrite(pin[GPIO_HLW_SEL], hlw_select_ui_flag); + pinMode(pin[GPIO_HLW_CF1], INPUT_PULLUP); + attachInterrupt(pin[GPIO_HLW_CF1], HlwCf1Interrupt, FALLING); + pinMode(pin[GPIO_HLW_CF], INPUT_PULLUP); + attachInterrupt(pin[GPIO_HLW_CF], HlwCfInterrupt, FALLING); + + hlw_cf1_timer = 0; +} + +void HlwDrvInit() +{ + if (!energy_flg) { + if ((pin[GPIO_HLW_SEL] < 99) && (pin[GPIO_HLW_CF1] < 99) && (pin[GPIO_HLW_CF] < 99)) { // Sonoff Pow or any HLW8012 based device + energy_flg = XNRG_01; + } + } +} + +boolean HlwCommand() +{ + boolean serviced = true; + + if ((CMND_POWERCAL == energy_command_code) || (CMND_VOLTAGECAL == energy_command_code) || (CMND_CURRENTCAL == energy_command_code)) { + + } + else if (CMND_POWERSET == energy_command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3601) && hlw_cf_pulse_length) { + Settings.energy_power_calibration = (XdrvMailbox.payload * 10 * hlw_cf_pulse_length) / hlw_power_ratio; + } + } + else if (CMND_VOLTAGESET == energy_command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 501) && hlw_cf1_voltage_pulse_length) { + Settings.energy_voltage_calibration = (XdrvMailbox.payload * 10 * hlw_cf1_voltage_pulse_length) / hlw_voltage_ratio; + } + } + else if (CMND_CURRENTSET == energy_command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 16001) && hlw_cf1_current_pulse_length) { + Settings.energy_current_calibration = (XdrvMailbox.payload * hlw_cf1_current_pulse_length) / hlw_current_ratio; + } + } + else serviced = false; // Unknown command + + return serviced; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +int Xnrg01(byte function) +{ + int result = 0; + + if (FUNC_PRE_INIT == function) { + HlwDrvInit(); + } + else if (XNRG_01 == energy_flg) { + switch (function) { + case FUNC_INIT: + HlwSnsInit(); + break; + case FUNC_EVERY_SECOND: + HlwEverySecond(); + break; + case FUNC_EVERY_200_MSECOND: + HlwEvery200ms(); + break; + case FUNC_COMMAND: + result = HlwCommand(); + break; + } + } + return result; +} + +#endif // USE_HLW8012 +#endif // USE_ENERGY_SENSOR diff --git a/sonoff/xnrg_02_cse7766.ino b/sonoff/xnrg_02_cse7766.ino new file mode 100644 index 000000000..640da704e --- /dev/null +++ b/sonoff/xnrg_02_cse7766.ino @@ -0,0 +1,248 @@ +/* + xnrg_02_cse7766.ino - CSE7766 energy sensor support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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_ENERGY_SENSOR +#ifdef USE_CSE7766 +/*********************************************************************************************\ + * CSE7766 - Energy (Sonoff S31 and Sonoff Pow R2) + * + * Based on datasheet from http://www.chipsea.com/UploadFiles/2017/08/11144342F01B5662.pdf +\*********************************************************************************************/ + +#define XNRG_02 2 + +#define CSE_NOT_CALIBRATED 0xAA + +#define CSE_PULSES_NOT_INITIALIZED -1 + +#define CSE_PREF 1000 +#define CSE_UREF 100 + +uint8_t cse_receive_flag = 0; + +long voltage_cycle = 0; +long current_cycle = 0; +long power_cycle = 0; +unsigned long power_cycle_first = 0; +long cf_pulses = 0; +long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; + +void CseReceived() +{ + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + // 55 5A 02 F7 60 00 03 AB 00 40 10 02 60 5D 51 A6 58 03 E9 EF 71 0B 7A 36 + // Hd Id VCal---- Voltage- ICal---- Current- PCal---- Power--- Ad CF--- Ck + + uint8_t header = serial_in_buffer[0]; + if ((header & 0xFC) == 0xFC) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Abnormal hardware")); + return; + } + + // Get chip calibration data (coefficients) and use as initial defaults + if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) { + long voltage_coefficient = 191200; // uSec + if (CSE_NOT_CALIBRATED != header) { + voltage_coefficient = serial_in_buffer[2] << 16 | serial_in_buffer[3] << 8 | serial_in_buffer[4]; + } + Settings.energy_voltage_calibration = voltage_coefficient / CSE_UREF; + } + if (HLW_IREF_PULSE == Settings.energy_current_calibration) { + long current_coefficient = 16140; // uSec + if (CSE_NOT_CALIBRATED != header) { + current_coefficient = serial_in_buffer[8] << 16 | serial_in_buffer[9] << 8 | serial_in_buffer[10]; + } + Settings.energy_current_calibration = current_coefficient; + } + if (HLW_PREF_PULSE == Settings.energy_power_calibration) { + long power_coefficient = 5364000; // uSec + if (CSE_NOT_CALIBRATED != header) { + power_coefficient = serial_in_buffer[14] << 16 | serial_in_buffer[15] << 8 | serial_in_buffer[16]; + } + Settings.energy_power_calibration = power_coefficient / CSE_PREF; + } + + uint8_t adjustement = serial_in_buffer[20]; + voltage_cycle = serial_in_buffer[5] << 16 | serial_in_buffer[6] << 8 | serial_in_buffer[7]; + current_cycle = serial_in_buffer[11] << 16 | serial_in_buffer[12] << 8 | serial_in_buffer[13]; + power_cycle = serial_in_buffer[17] << 16 | serial_in_buffer[18] << 8 | serial_in_buffer[19]; + cf_pulses = serial_in_buffer[21] << 8 | serial_in_buffer[22]; + + if (energy_power_on) { // Powered on + if (adjustement & 0x40) { // Voltage valid + energy_voltage = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)voltage_cycle; + } + if (adjustement & 0x10) { // Power valid + if ((header & 0xF2) == 0xF2) { // Power cycle exceeds range + energy_power = 0; + } else { + if (0 == power_cycle_first) power_cycle_first = power_cycle; // Skip first incomplete power_cycle + if (power_cycle_first != power_cycle) { + power_cycle_first = -1; + energy_power = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)power_cycle; + } else { + energy_power = 0; + } + } + } else { + power_cycle_first = 0; + energy_power = 0; // Powered on but no load + } + if (adjustement & 0x20) { // Current valid + if (0 == energy_power) { + energy_current = 0; + } else { + energy_current = (float)Settings.energy_current_calibration / (float)current_cycle; + } + } + } else { // Powered off + power_cycle_first = 0; + energy_voltage = 0; + energy_power = 0; + energy_current = 0; + } +} + +bool CseSerialInput() +{ + if (cse_receive_flag) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (24 == serial_in_byte_counter) { + + AddLogSerial(LOG_LEVEL_DEBUG_MORE); + + uint8_t checksum = 0; + for (byte i = 2; i < 23; i++) { checksum += serial_in_buffer[i]; } + if (checksum == serial_in_buffer[23]) { + CseReceived(); + cse_receive_flag = 0; + return 1; + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); + do { // Sync buffer with data (issue #1907 and #3425) + memmove(serial_in_buffer, serial_in_buffer +1, 24); + serial_in_byte_counter--; + } while ((serial_in_byte_counter > 2) && (0x5A != serial_in_buffer[1])); + if (0x5A != serial_in_buffer[1]) { + cse_receive_flag = 0; + serial_in_byte_counter = 0; + } + } + } + } else { + if ((0x5A == serial_in_byte) && (1 == serial_in_byte_counter)) { // 0x5A - Packet header 2 + cse_receive_flag = 1; + } else { + serial_in_byte_counter = 0; + } + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + } + serial_in_byte = 0; // Discard + return 0; +} + +/********************************************************************************************/ + +void CseEverySecond() +{ + long cf_frequency = 0; + + if (CSE_PULSES_NOT_INITIALIZED == cf_pulses_last_time) { + cf_pulses_last_time = cf_pulses; // Init after restart + } else { + if (cf_pulses < cf_pulses_last_time) { // Rolled over after 65535 pulses + cf_frequency = (65536 - cf_pulses_last_time) + cf_pulses; + } else { + cf_frequency = cf_pulses - cf_pulses_last_time; + } + if (cf_frequency && energy_power) { + cf_pulses_last_time = cf_pulses; + energy_kWhtoday_delta += (cf_frequency * Settings.energy_power_calibration) / 36; + EnergyUpdateToday(); + } + } +} + +void CseDrvInit() +{ + if (!energy_flg) { + if ((SONOFF_S31 == Settings.module) || (SONOFF_POW_R2 == Settings.module)) { // Sonoff S31 or Sonoff Pow R2 + baudrate = 4800; + serial_config = SERIAL_8E1; + energy_flg = XNRG_02; + } + } +} + +boolean CseCommand() +{ + boolean serviced = true; + + if ((CMND_POWERCAL == energy_command_code) || (CMND_VOLTAGECAL == energy_command_code) || (CMND_CURRENTCAL == energy_command_code)) { + + } + else if (CMND_POWERSET == energy_command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3601) && power_cycle) { + Settings.energy_power_calibration = (XdrvMailbox.payload * power_cycle) / CSE_PREF; + } + } + else if (CMND_VOLTAGESET == energy_command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 501) && voltage_cycle) { + Settings.energy_voltage_calibration = (XdrvMailbox.payload * voltage_cycle) / CSE_UREF; + } + } + else if (CMND_CURRENTSET == energy_command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 16001) && current_cycle) { + Settings.energy_current_calibration = (XdrvMailbox.payload * current_cycle) / 1000; + } + } + else serviced = false; // Unknown command + + return serviced; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +int Xnrg02(byte function) +{ + int result = 0; + + if (FUNC_PRE_INIT == function) { + CseDrvInit(); + } + else if (XNRG_02 == energy_flg) { + switch (function) { + case FUNC_EVERY_SECOND: + CseEverySecond(); + break; + case FUNC_COMMAND: + result = CseCommand(); + break; + case FUNC_SERIAL: + result = CseSerialInput(); + break; + } + } + return result; +} + +#endif // USE_CSE7766 +#endif // USE_ENERGY_SENSOR diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino new file mode 100644 index 000000000..d009feea4 --- /dev/null +++ b/sonoff/xnrg_03_pzem004t.ino @@ -0,0 +1,248 @@ +/* + xnrg_03_pzem004t.ino - PZEM004T energy sensor support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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_ENERGY_SENSOR +#ifdef USE_PZEM004T +/*********************************************************************************************\ + * PZEM004T - Energy + * + * Source: Victor Ferrer https://github.com/vicfergar/Sonoff-MQTT-OTA-Arduino + * Based on: PZEM004T library https://github.com/olehs/PZEM004T + * + * Hardware Serial will be selected if GPIO1 = [PZEM Rx] and [GPIO3 = PZEM Tx] +\*********************************************************************************************/ + +#define XNRG_03 3 + +#include + +TasmotaSerial *PzemSerial; + +#define PZEM_VOLTAGE (uint8_t)0xB0 +#define RESP_VOLTAGE (uint8_t)0xA0 + +#define PZEM_CURRENT (uint8_t)0xB1 +#define RESP_CURRENT (uint8_t)0xA1 + +#define PZEM_POWER (uint8_t)0xB2 +#define RESP_POWER (uint8_t)0xA2 + +#define PZEM_ENERGY (uint8_t)0xB3 +#define RESP_ENERGY (uint8_t)0xA3 + +#define PZEM_SET_ADDRESS (uint8_t)0xB4 +#define RESP_SET_ADDRESS (uint8_t)0xA4 + +#define PZEM_POWER_ALARM (uint8_t)0xB5 +#define RESP_POWER_ALARM (uint8_t)0xA5 + +#define PZEM_DEFAULT_READ_TIMEOUT 500 + +/*********************************************************************************************/ + +struct PZEMCommand { + uint8_t command; + uint8_t addr[4]; + uint8_t data; + uint8_t crc; +}; + +IPAddress pzem_ip(192, 168, 1, 1); + +uint8_t PzemCrc(uint8_t *data) +{ + uint16_t crc = 0; + for (uint8_t i = 0; i < sizeof(PZEMCommand) -1; i++) crc += *data++; + return (uint8_t)(crc & 0xFF); +} + +void PzemSend(uint8_t cmd) +{ + PZEMCommand pzem; + + pzem.command = cmd; + for (uint8_t i = 0; i < sizeof(pzem.addr); i++) pzem.addr[i] = pzem_ip[i]; + pzem.data = 0; + + uint8_t *bytes = (uint8_t*)&pzem; + pzem.crc = PzemCrc(bytes); + + PzemSerial->flush(); + PzemSerial->write(bytes, sizeof(pzem)); +} + +bool PzemReceiveReady() +{ + return PzemSerial->available() >= (int)sizeof(PZEMCommand); +} + +bool PzemRecieve(uint8_t resp, float *data) +{ + // 0 1 2 3 4 5 6 + // A4 00 00 00 00 00 A4 - Set address + // A0 00 D4 07 00 00 7B - Voltage (212.7V) + // A1 00 00 0A 00 00 AB - Current (0.1A) + // A1 00 00 00 00 00 A1 - No current + // A2 00 16 00 00 00 B8 - Power (22W) + // A2 00 00 00 00 00 A2 - No power + // A3 00 08 A4 00 00 4F - Energy (2.212kWh) + // A3 01 86 9F 00 00 C9 - Energy (99.999kWh) + + uint8_t buffer[sizeof(PZEMCommand)] = { 0 }; + + unsigned long start = millis(); + uint8_t len = 0; + while ((len < sizeof(PZEMCommand)) && (millis() - start < PZEM_DEFAULT_READ_TIMEOUT)) { + if (PzemSerial->available() > 0) { + uint8_t c = (uint8_t)PzemSerial->read(); + if (!c && !len) { + continue; // skip 0 at startup + } + if ((1 == len) && (buffer[0] == c)) { + len--; + continue; // fix skewed data + } + buffer[len++] = c; + } + } + + AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, len); + + if (len != sizeof(PZEMCommand)) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Pzem comms timeout")); + return false; + } + if (buffer[6] != PzemCrc(buffer)) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Pzem crc error")); + return false; + } + if (buffer[0] != resp) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Pzem bad response")); + return false; + } + + switch (resp) { + case RESP_VOLTAGE: + *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 10.0); // 65535.x V + break; + case RESP_CURRENT: + *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 100.0); // 65535.xx A + break; + case RESP_POWER: + *data = (float)(buffer[1] << 8) + buffer[2]; // 65535 W + break; + case RESP_ENERGY: + *data = (float)((uint32_t)buffer[1] << 16) + ((uint16_t)buffer[2] << 8) + buffer[3]; // 16777215 Wh + break; + } + return true; +} + +/*********************************************************************************************/ + +const uint8_t pzem_commands[] { PZEM_SET_ADDRESS, PZEM_VOLTAGE, PZEM_CURRENT, PZEM_POWER, PZEM_ENERGY }; +const uint8_t pzem_responses[] { RESP_SET_ADDRESS, RESP_VOLTAGE, RESP_CURRENT, RESP_POWER, RESP_ENERGY }; + +uint8_t pzem_read_state = 0; +uint8_t pzem_sendRetry = 0; + +void PzemEvery200ms() +{ + bool data_ready = PzemReceiveReady(); + + if (data_ready) { + float value = 0; + if (PzemRecieve(pzem_responses[pzem_read_state], &value)) { + switch (pzem_read_state) { + case 1: // Voltage as 230.2V + energy_voltage = value; + break; + case 2: // Current as 17.32A + energy_current = value; + break; + case 3: // Power as 20W + energy_power = value; + break; + case 4: // Total energy as 99999Wh + if (!energy_start || (value < energy_start)) energy_start = value; // Init after restart and hanlde roll-over if any + energy_kWhtoday += (value - energy_start) * 100; + energy_start = value; + EnergyUpdateToday(); + break; + } + pzem_read_state++; + if (5 == pzem_read_state) pzem_read_state = 1; + } + } + + if (0 == pzem_sendRetry || data_ready) { + pzem_sendRetry = 5; + PzemSend(pzem_commands[pzem_read_state]); + } + else { + pzem_sendRetry--; + } +} + +void PzemSnsInit() +{ + // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions + PzemSerial = new TasmotaSerial(pin[GPIO_PZEM_RX], pin[GPIO_PZEM_TX], 1); + if (PzemSerial->begin(9600)) { + if (PzemSerial->hardwareSerial()) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemDrvInit() +{ + if (!energy_flg) { + if ((pin[GPIO_PZEM_RX] < 99) && (pin[GPIO_PZEM_TX] < 99)) { // Any device with a Pzem004T + energy_flg = XNRG_03; + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +int Xnrg03(byte function) +{ + int result = 0; + + if (FUNC_PRE_INIT == function) { + PzemDrvInit(); + } + else if (XNRG_03 == energy_flg) { + switch (function) { + case FUNC_INIT: + PzemSnsInit(); + break; + case FUNC_EVERY_200_MSECOND: + PzemEvery200ms(); + break; + } + } + return result; +} + +#endif // USE_PZEM004T +#endif // USE_ENERGY_SENSOR diff --git a/sonoff/xnrg_interface.ino b/sonoff/xnrg_interface.ino new file mode 100644 index 000000000..d9726ac05 --- /dev/null +++ b/sonoff/xnrg_interface.ino @@ -0,0 +1,57 @@ +/* + xnrg_interface.ino - Energy driver interface support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends inspired by ESPEasy + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +int (* const xnrg_func_ptr[])(byte) PROGMEM = { // Energy driver Function Pointers +#ifdef XNRG_01 + &Xnrg01, +#endif + +#ifdef XNRG_02 + &Xnrg02, +#endif + +#ifdef XNRG_03 + &Xnrg03, +#endif + +#ifdef XNRG_04 + &Xnrg04, +#endif + +#ifdef XNRG_05 + &Xnrg05, +#endif + +#ifdef XNRG_06 + &Xnrg06 +#endif +}; + +const uint8_t xnrg_present = sizeof(xnrg_func_ptr) / sizeof(xnrg_func_ptr[0]); // Number of drivers found + +int XnrgCall(byte Function) +{ + int result = 0; + + for (byte x = 0; x < xnrg_present; x++) { + result = xnrg_func_ptr[x](Function); + if (result) break; + } + return result; +} From e7ae727c659b5471fbc2713d20e9341dba36560f Mon Sep 17 00:00:00 2001 From: MadDoct <32080323+MadDoct@users.noreply.github.com> Date: Tue, 4 Sep 2018 18:53:44 +0100 Subject: [PATCH 0036/2222] Update sonoff.ino --- sonoff/sonoff.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 12aea14e9..9ada9f656 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2362,7 +2362,7 @@ void GpioInit() if (mpin) pin[mpin] = i; } - if ((2 == pin[GPIO_TXD]) || (Settings.module == 20)) Serial.set_tx(2); + if ((2 == pin[GPIO_TXD]) || (H801 == Settings.module)) Serial.set_tx(2); analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) From bd0323f6f28df037aed04a476798291acaf31cb5 Mon Sep 17 00:00:00 2001 From: gitolicious Date: Tue, 4 Sep 2018 22:43:27 +0200 Subject: [PATCH 0037/2222] Added toggle function for RGBW lights #3695 Proposed fix for #3695 --- sonoff/xdrv_04_light.ino | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 22fce0c33..f8dde0ce6 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -69,6 +69,12 @@ struct LRgbColor { const LRgbColor kFixedColor[MAX_FIXED_COLOR] PROGMEM = { 255,0,0, 0,255,0, 0,0,255, 228,32,0, 0,228,32, 0,32,228, 188,64,0, 0,160,96, 160,32,240, 255,255,0, 255,0,170, 255,255,255 }; +struct LWColor { + uint8_t W; +}; +#define MAX_FIXED_WHITE 3 +const LWColor kFixedWhite[MAX_FIXED_WHITE] PROGMEM = { 0, 255, 128 }; + struct LCwColor { uint8_t C, W; }; @@ -1006,7 +1012,11 @@ boolean LightColorEntry(char *buffer, uint8_t buffer_length) entry_type = 1; // Hexadecimal } else if ((value > 199) && (value <= 199 + MAX_FIXED_COLD_WARM)) { - if (LST_COLDWARM == light_subtype) { + if (LST_RGBW == light_subtype) { + memcpy_P(&light_entry_color[3], &kFixedWhite[value -200], 1); + entry_type = 1; // Hexadecimal + } + else if (LST_COLDWARM == light_subtype) { memcpy_P(&light_entry_color, &kFixedColdWarm[value -200], 2); entry_type = 1; // Hexadecimal } From 170013c1e13860c33da91014ee73beec3cbe5d50 Mon Sep 17 00:00:00 2001 From: gitolicious Date: Tue, 4 Sep 2018 23:03:19 +0200 Subject: [PATCH 0038/2222] Added 4th dimming step It wasn't a good idea to cycle through three dimming steps only, as the 4th would be triggered by the toggle, but nothing happened (`Color 203` got ignored). --- sonoff/xdrv_04_light.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index f8dde0ce6..209fe467a 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -72,8 +72,8 @@ const LRgbColor kFixedColor[MAX_FIXED_COLOR] PROGMEM = struct LWColor { uint8_t W; }; -#define MAX_FIXED_WHITE 3 -const LWColor kFixedWhite[MAX_FIXED_WHITE] PROGMEM = { 0, 255, 128 }; +#define MAX_FIXED_WHITE 4 +const LWColor kFixedWhite[MAX_FIXED_WHITE] PROGMEM = { 0, 255, 128, 32 }; struct LCwColor { uint8_t C, W; From eaff2962624a24d44fd03e9a24d0e9bf9ab7a509 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 5 Sep 2018 11:22:58 +0200 Subject: [PATCH 0039/2222] v6.2.1.1 - Released v6.2.1 Released v6.2.1 to solve important issues --- RELEASENOTES.md | 6 ++++++ sonoff/_changelog.ino | 14 +++++++------- sonoff/sonoff_version.h | 2 +- sonoff/xplg_wemohue.ino | 1 - 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 7cacefa47..8cf1a0022 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -104,6 +104,12 @@ See [Tasmota ESP/Arduino library version related issues](https://github.com/aren | USE_RF_FLASH | - | - | x | x | x | ## Changelog +Version 6.2.1 20180905 + * Fix possible ambiguity on command parameters if StateText contains numbers only (#3656) + * Fix Wemo emulation to select the first relay when more than one relay is present (#3657) + * Fix possible exception due to buffer overflow (#3659) + * Fix lost energy today and total energy value after power cycle (#3689) + Version 6.2.0 20180901 * Allow user override of define MAX_RULE_VARS and MAX_RULE_TIMERS (#3561) * Disable wifi sleep for both Esp8266/Arduino core 2.4.1 and 2.4.2 to solve device freeze caused by Espressif SDK bug (#3554) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0b3c115cd..145e435e3 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,14 +1,14 @@ -/* 6.2.0.2 20180904 +/* 6.2.1.1 20180905 * Rewrite energy monitoring using energy sensor driver modules - * Fix lost today and total energy value after power cycle (#3689) - * - * 6.2.0.1 20180902 - * Fix possible ambiguity on command parameters if StateText contains numbers only (#3656) - * Fix possible exception due to buffer overflow (#3659) * Add Wifi channel number to state message (#3664) - * Fix Wemo emulation to select the first relay when more than one relay is present (#3657) * Add support for Shelly 1 and basic support for Shelly 2 - No energy monitoring yet (#2789) * + * 6.2.1 20180905 + * Fix possible ambiguity on command parameters if StateText contains numbers only (#3656) + * Fix Wemo emulation to select the first relay when more than one relay is present (#3657) + * Fix possible exception due to buffer overflow (#3659) + * Fix lost energy today and total energy value after power cycle (#3689) + * * 6.2.0 20180901 * Allow user override of define MAX_RULE_VARS and MAX_RULE_TIMERS (#3561) * Disable wifi sleep for both Esp8266/Arduino core 2.4.1 and 2.4.2 to solve device freeze caused by Espressif SDK bug (#3554) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index e9e92cc9d..f4df759c8 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020002 +#define VERSION 0x06020101 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index bc579782a..93912bc76 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -397,7 +397,6 @@ void HandleUpnpEvent() uint8_t device = (light_type) ? devices_present : 1; // Select either a configured light or relay1 ExecuteCommandPower(device, power, SRC_WEMO); } - } else if(request.indexOf(F("GetBinaryState")) > 0){ state_xml.replace(F("Set"), F("Get")); From 36242e0e02102e7f6534f53ec519ac304515cac3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 5 Sep 2018 15:38:48 +0200 Subject: [PATCH 0040/2222] Add network information Add network information to display start screen (#3704) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 10 +++++----- sonoff/xdrv_13_display.ino | 22 +++++++++++++++++++--- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 145e435e3..77020540e 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Rewrite energy monitoring using energy sensor driver modules * Add Wifi channel number to state message (#3664) * Add support for Shelly 1 and basic support for Shelly 2 - No energy monitoring yet (#2789) + * Add network information to display start screen (#3704) * * 6.2.1 20180905 * Fix possible ambiguity on command parameters if StateText contains numbers only (#3656) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 2c5d5cce9..a0b65b348 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -204,7 +204,7 @@ enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MA enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, - FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM}; + FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_DISPLAY, FUNC_FREE_MEM}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c92a8db76..8afae580e 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2540,19 +2540,19 @@ void setup() snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); AddLog(LOG_LEVEL_DEBUG); - GpioInit(); - - SetSerialBaudrate(baudrate); - Format(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); Format(mqtt_topic, Settings.mqtt_topic, sizeof(mqtt_topic)); - if (strstr(Settings.hostname, "%")) { strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname, mqtt_topic, ESP.getChipId() & 0x1FFF); } else { snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname); } + + GpioInit(); + + SetSerialBaudrate(baudrate); + WifiConnect(); if (MOTOR == Settings.module) Settings.poweronstate = POWER_ALL_ON; // Needs always on else in limbo! diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 74b4069e1..c8972536a 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -626,11 +626,24 @@ void DisplayLogBufferInit() DisplayReAllocLogBuffer(); - char buffer[20]; + char buffer[40]; snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s"), my_version); DisplayLogBufferAdd(buffer); snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings.display_mode); DisplayLogBufferAdd(buffer); + + snprintf_P(buffer, sizeof(buffer), PSTR(D_CMND_HOSTNAME " %s"), my_hostname); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), Settings.sta_ssid[Settings.sta_active]); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), WiFi.macAddress().c_str()); + DisplayLogBufferAdd(buffer); + if (!global_state.wifi_down && (static_cast(WiFi.localIP()) != 0)) { + snprintf_P(buffer, sizeof(buffer), PSTR("IP %s"), WiFi.localIP().toString().c_str()); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_RSSI " %d%%"), WifiGetRssiAsQuality(WiFi.RSSI())); + DisplayLogBufferAdd(buffer); + } } } @@ -915,8 +928,8 @@ boolean DisplayCommand() if (last_display_mode && !Settings.display_mode) { // Switch to mode 0 DisplayInit(DISPLAY_INIT_MODE); DisplayClear(); - } - if (!last_display_mode && Settings.display_mode) { // Switch to non mode 0 + } else { +// if (!last_display_mode && Settings.display_mode) { // Switch to non mode 0 DisplayLogBufferInit(); DisplayInit(DISPLAY_INIT_MODE); } @@ -1047,6 +1060,9 @@ boolean Xdrv13(byte function) case FUNC_PRE_INIT: DisplayInitDriver(); break; + case FUNC_DISPLAY: + DisplayLogBufferAdd(log_data); + break; case FUNC_EVERY_50_MSECOND: if (Settings.display_model) { XdspCall(FUNC_DISPLAY_EVERY_50_MSECOND); } break; From 35d0e502c46b99d18b5389c9162d399be9e38f04 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 5 Sep 2018 18:01:15 +0200 Subject: [PATCH 0041/2222] Some additions * Add command Display to show all settings at once * Add toggle function RGBW lights (#3695, #3697) * Add user configurable GPIO02 and GPIO03 on H801 devices (#3692) --- sonoff/_changelog.ino | 3 +++ sonoff/sonoff.ino | 2 +- sonoff/sonoff_template.h | 17 +++++++---------- sonoff/xdrv_13_display.ino | 10 ++++++++-- sonoff/xdsp_03_matrix.ino | 4 +++- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 77020540e..910f70bbc 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,9 @@ * Add Wifi channel number to state message (#3664) * Add support for Shelly 1 and basic support for Shelly 2 - No energy monitoring yet (#2789) * Add network information to display start screen (#3704) + * Add command Display to show all settings at once + * Add toggle function RGBW lights (#3695, #3697) + * Add user configurable GPIO02 and GPIO03 on H801 devices (#3692) * * 6.2.1 20180905 * Fix possible ambiguity on command parameters if StateText contains numbers only (#3656) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index fa59bb06d..a7315623d 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2347,7 +2347,7 @@ void GpioInit() if (mpin) pin[mpin] = i; } - if ((2 == pin[GPIO_TXD]) || (H801 == Settings.module)) Serial.set_tx(2); + if ((2 == pin[GPIO_TXD]) || (H801 == Settings.module)) { Serial.set_tx(2); } analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index f2fe93003..b1087da97 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -136,9 +136,6 @@ enum ProgramSelectablePins { GPIO_DI, // my92x1 PWM input GPIO_DCKI, // my92x1 CLK input GPIO_ARIRFRCV, // AliLux RF Receive input - GPIO_MCP39_TX, // MCP39F501 Serial output - GPIO_MCP39_RX, // MCP39F501 Serial input - GPIO_MCP39_RST, // MCP39F501 Serial reset GPIO_USER, // User configurable GPIO_MAX }; @@ -550,8 +547,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "H801", // Lixada H801 Wifi (ESP8266) GPIO_USER, // GPIO00 E-FW Button GPIO_LED1, // GPIO01 Green LED - GPIO_USER, // GPIO02 RX and Optional sensor - Pin next to TX on the PCB - GPIO_USER, // GPIO03 TX and Optional sensor - Pin next to GND on the PCB + GPIO_USER, // GPIO02 TX and Optional sensor - Pin next to TX on the PCB + GPIO_USER, // GPIO03 RX and Optional sensor - Pin next to GND on the PCB GPIO_PWM5, // GPIO04 W2 - PWM5 GPIO_LED2_INV, // GPIO05 Red LED 0, 0, 0, 0, 0, 0, // Flash connection @@ -923,16 +920,16 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { }, { "Shelly 2", // Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ 0, - GPIO_MCP39_RX, // GPIO01 MCP39F501 Serial input + GPIO_TXD, // GPIO01 MCP39F501 Serial input 0, - GPIO_MCP39_TX, // GPIO03 MCP39F501 Serial output + GPIO_RXD, // GPIO03 MCP39F501 Serial output GPIO_REL1, // GPIO04 GPIO_REL2, // GPIO05 0, 0, 0, 0, 0, 0, // Flash connection GPIO_SWT1_NP, // GPIO12 0, GPIO_SWT2_NP, // GPIO14 - GPIO_MCP39_RST, // GPIO15 MCP39F501 Reset + 0, // GPIO15 MCP39F501 Reset 0, 0 } }; @@ -1002,7 +999,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0 } - { "Ledunia", // Ledunia (ESP8266) - http://ledunia.de/ + { "Ledunia", // Ledunia (ESP8266 - 32MB) - http://ledunia.de/ GPIO_USER, // GPIO00 (D0) GPIO_USER, // GPIO01 (D7) Serial RXD GPIO_USER, // GPIO02 (D2) @@ -1019,4 +1016,4 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { } */ -#endif // _SONOFF_TEMPLATE_H_ +#endif // _SONOFF_TEMPLATE_H_ \ No newline at end of file diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index c8972536a..083aae74a 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -49,10 +49,10 @@ enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_E enum DisplayInitModes { DISPLAY_INIT_MODE, DISPLAY_INIT_PARTIAL, DISPLAY_INIT_FULL }; -enum DisplayCommands { CMND_DISP_MODEL, CMND_DISP_MODE, CMND_DISP_REFRESH, CMND_DISP_DIMMER, CMND_DISP_COLS, CMND_DISP_ROWS, +enum DisplayCommands { CMND_DISPLAY, CMND_DISP_MODEL, CMND_DISP_MODE, CMND_DISP_REFRESH, CMND_DISP_DIMMER, CMND_DISP_COLS, CMND_DISP_ROWS, CMND_DISP_SIZE, CMND_DISP_FONT, CMND_DISP_ROTATE, CMND_DISP_TEXT, CMND_DISP_ADDRESS }; const char kDisplayCommands[] PROGMEM = - D_CMND_DISP_MODEL "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|" D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|" + "|" D_CMND_DISP_MODEL "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|" D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|" D_CMND_DISP_SIZE "|" D_CMND_DISP_FONT "|" D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS ; const char S_JSON_DISPLAY_COMMAND_VALUE[] PROGMEM = "{\"" D_CMND_DISPLAY "%s\":\"%s\"}"; @@ -898,6 +898,12 @@ boolean DisplayCommand() if (-1 == command_code) { serviced = false; // Unknown command } + else if (CMND_DISPLAY == command_code) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" + D_CMND_DISP_SIZE "\":%d,\"" D_CMND_DISP_FONT "\":%d,\"" D_CMND_DISP_ROTATE "\":%d,\"" D_CMND_DISP_REFRESH "\":%d,\"" D_CMND_DISP_COLS "\":[%d,%d],\"" D_CMND_DISP_ROWS "\":%d}}"), + Settings.display_model, Settings.display_mode, Settings.display_dimmer, Settings.display_size, Settings.display_font, Settings.display_rotate, Settings.display_refresh, + Settings.display_cols[0], Settings.display_cols[1], Settings.display_rows); + } else if (CMND_DISP_MODEL == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < DISPLAY_MAX_DRIVERS)) { uint8_t last_display_model = Settings.display_model; diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index 4989ad24b..36c5955d6 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -243,7 +243,8 @@ void MatrixPrintLog(uint8_t direction) uint8_t space = 0; uint8_t max_cols = (disp_log_buffer_cols < MTX_MAX_SCREEN_BUFFER) ? disp_log_buffer_cols : MTX_MAX_SCREEN_BUFFER; mtx_buffer[0] = '\0'; - for (byte i = 0; i < max_cols; i++) { + uint8_t i = 0; + while ((txt[i] != '\0') && (i < max_cols)) { if (txt[i] == ' ') { space++; } else { @@ -252,6 +253,7 @@ void MatrixPrintLog(uint8_t direction) if (space < 2) { strncat(mtx_buffer, (const char*)txt +i, 1); } + i++; } snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "[%s]"), mtx_buffer); From 00814c7fc64cb37e8db373e8565fb13e83fffea3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 5 Sep 2018 20:51:17 +0200 Subject: [PATCH 0042/2222] Fix compile error Fix compile error --- sonoff/sonoff.h | 2 +- sonoff/xdrv_13_display.ino | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index a0b65b348..2c5d5cce9 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -204,7 +204,7 @@ enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MA enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, - FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_DISPLAY, FUNC_FREE_MEM}; + FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 083aae74a..4d6ce2e89 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -1066,9 +1066,6 @@ boolean Xdrv13(byte function) case FUNC_PRE_INIT: DisplayInitDriver(); break; - case FUNC_DISPLAY: - DisplayLogBufferAdd(log_data); - break; case FUNC_EVERY_50_MSECOND: if (Settings.display_model) { XdspCall(FUNC_DISPLAY_EVERY_50_MSECOND); } break; From c6507482c4969d452a764c209ebe603265ff7394 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 5 Sep 2018 20:56:43 +0200 Subject: [PATCH 0043/2222] Bump README.md version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ab25ac17..581b38e83 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute! [![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/tasmota) ### Development -[![Dev Version](https://img.shields.io/badge/development%20version-6.2.0.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-6.2.1.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota) From b8e7ee865085370ba53fd1db589420cf5529eb02 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 5 Sep 2018 18:35:02 -0300 Subject: [PATCH 0044/2222] Fixed Exception Issue Solves Bug #3700 --- sonoff/support.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 8aaeabf88..a48156444 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -143,7 +143,7 @@ char* subStr(char* dest, char* str, const char *delim, int index) int i; // Since strtok consumes the first arg, make a copy - strlcpy(dest, str, strlen(str)); + strncpy(dest, str, strlen(str)); for (i = 1, act = dest; i <= index; i++, act = NULL) { sub = strtok_r(act, delim, &ptr); if (sub == NULL) break; From 9413ba9f47386fbd4ade98d8046e10382160382c Mon Sep 17 00:00:00 2001 From: Rodney Gitzel Date: Sun, 2 Sep 2018 01:42:52 -0700 Subject: [PATCH 0045/2222] optionally append timezone to timestamp in JSON messages --- .gitignore | 3 ++ sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 6 ++-- sonoff/support.ino | 68 +++++++++++++++++++----------------- sonoff/user_config.h | 3 ++ sonoff/xdrv_02_webserver.ino | 2 +- 6 files changed, 46 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index b6460347b..028a76667 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ build ## Visual Studio Code specific ###### .vscode +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 3a1dc14c6..b7df1408a 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -170,7 +170,7 @@ enum WeekInMonthOptions {Last, First, Second, Third, Fourth}; enum DayOfTheWeekOptions {Sun=1, Mon, Tue, Wed, Thu, Fri, Sat}; enum MonthNamesOptions {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec}; enum HemisphereOptions {North, South}; -enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_RESTART, DT_UPTIME }; +enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_RESTART }; enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 254f88184..bf12d97eb 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1418,7 +1418,7 @@ void PublishStatus(uint8_t payload) if ((0 == payload) || (1 == payload)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), - baudrate, Settings.mqtt_grptopic, Settings.ota_url, GetResetReason().c_str(), GetDateAndTime(DT_UPTIME).c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.bootcount, Settings.save_flag, GetSettingsAddress()); + baudrate, Settings.mqtt_grptopic, Settings.ota_url, GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.bootcount, Settings.save_flag, GetSettingsAddress()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); } @@ -1509,7 +1509,7 @@ void MqttShowState() { char stemp1[33]; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\""), mqtt_data, GetDateAndTime(DT_LOCAL).c_str(), GetDateAndTime(DT_UPTIME).c_str()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\""), mqtt_data, GetDateAndTime(DT_LOCAL).c_str(), GetUptime().c_str()); #ifdef USE_ADC_VCC dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VCC "\":%s"), mqtt_data, stemp1); @@ -1626,7 +1626,7 @@ void PerformEverySecond() if ((2 == RtcTime.minute) && latest_uptime_flag) { latest_uptime_flag = false; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"}"), GetDateAndTime(DT_LOCAL).c_str(), GetDateAndTime(DT_UPTIME).c_str()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"}"), GetDateAndTime(DT_LOCAL).c_str(), GetUptime().c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_UPTIME)); } if ((3 == RtcTime.minute) && !latest_uptime_flag) latest_uptime_flag = true; diff --git a/sonoff/support.ino b/sonoff/support.ino index 8cc064fe5..290acf231 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1802,44 +1802,46 @@ String GetBuildDateAndTime() return String(bdt); } +/* + * timestamps in https://en.wikipedia.org/wiki/ISO_8601 format + * + * DT_UTC - current data and time in Greenwich, England (aka GMT) + * DT_LOCAL - current date and time taking timezone into account + * DT_RESTART - the date and time this device last started, in local timezone + * + * Format: + * "2017-03-07T11:08:02-07:00" - if DT_LOCAL and TIME_APPEND_TIMEZONE=1 + * "2017-03-07T11:08:02" - otherwise + */ String GetDateAndTime(byte time_type) { - // enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_RESTART, DT_UPTIME }; - // "2017-03-07T11:08:02" - ISO8601:2004 - char dt[21]; + // "2017-03-07T11:08:02-07:00" - ISO8601:2004 + char dt[27]; TIME_T tmpTime; - if (DT_UPTIME == time_type) { - if (restart_time) { - BreakTime(utc_time - restart_time, tmpTime); - } else { - BreakTime(uptime, tmpTime); - } - // "P128DT14H35M44S" - ISO8601:2004 - https://en.wikipedia.org/wiki/ISO_8601 Durations - // snprintf_P(dt, sizeof(dt), PSTR("P%dDT%02dH%02dM%02dS"), ut.days, ut.hour, ut.minute, ut.second); - // "128 14:35:44" - OpenVMS - // "128T14:35:44" - Tasmota - snprintf_P(dt, sizeof(dt), PSTR("%dT%02d:%02d:%02d"), - tmpTime.days, tmpTime.hour, tmpTime.minute, tmpTime.second); - } else { - switch (time_type) { - case DT_UTC: - BreakTime(utc_time, tmpTime); - tmpTime.year += 1970; - break; - case DT_RESTART: - if (restart_time == 0) { - return ""; - } - BreakTime(restart_time, tmpTime); - tmpTime.year += 1970; - break; - default: - tmpTime = RtcTime; - } - snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), - tmpTime.year, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); + switch (time_type) { + case DT_UTC: + BreakTime(utc_time, tmpTime); + tmpTime.year += 1970; + break; + case DT_RESTART: + if (restart_time == 0) { + return ""; + } + BreakTime(restart_time, tmpTime); + tmpTime.year += 1970; + break; + default: + tmpTime = RtcTime; } + + snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), + tmpTime.year, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); + + if (TIME_APPEND_TIMEZONE && (time_type == DT_LOCAL)) { + snprintf_P(dt, sizeof(dt), PSTR("%s%+03d:00"), dt, Settings.timezone); + } + return String(dt); } diff --git a/sonoff/user_config.h b/sonoff/user_config.h index a8457ff97..3dbf9c5b2 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -152,6 +152,9 @@ #define TIME_STD_HOUR 3 // Hour (0 to 23) #define TIME_STD_OFFSET +60 // Offset from UTC in minutes (-780 to +780) +// -- Time - formatting options +#define TIME_APPEND_TIMEZONE 0 // for local timestamps: 0 = no timezone in string, 1 = append numeric timezone (e.g. "+1:00" or "-7:00") + // -- Location ------------------------------------ #define LATITUDE 48.858360 // [Latitude] Your location to be used with sunrise and sunset #define LONGITUDE 2.294442 // [Longitude] Your location to be used with sunrise and sunset diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index c919c8f43..8725bd6f5 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -1291,7 +1291,7 @@ void HandleInformation() func += F(D_PROGRAM_VERSION "}2"); func += my_version; func += F("}1" D_BUILD_DATE_AND_TIME "}2"); func += GetBuildDateAndTime(); func += F("}1" D_CORE_AND_SDK_VERSION "}2" ARDUINO_ESP8266_RELEASE "/"); func += String(ESP.getSdkVersion()); - func += F("}1" D_UPTIME "}2"); func += GetDateAndTime(DT_UPTIME); + func += F("}1" D_UPTIME "}2"); func += GetUptime(); 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); From 359877489d7acba5f19c221a35921bdc83c97017 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 6 Sep 2018 10:42:22 +0200 Subject: [PATCH 0046/2222] 6.2.1.2 - Fix KNX PA exception 6.2.1.2 20180906 * Fix KNX PA exception. Regression from 6.2.1 buffer overflow (#3700, #3710) --- sonoff/_changelog.ino | 5 ++++- sonoff/settings.h | 4 ++-- sonoff/sonoff.ino | 9 ++++++--- sonoff/sonoff_version.h | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 910f70bbc..c34a70697 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.2.1.1 20180905 +/* 6.2.1.2 20180906 + * Fix KNX PA exception. Regression from 6.2.1 buffer overflow (#3700, #3710) + * + * 6.2.1.1 20180905 * Rewrite energy monitoring using energy sensor driver modules * Add Wifi channel number to state message (#3664) * Add support for Shelly 1 and basic support for Shelly 2 - No energy monitoring yet (#2789) diff --git a/sonoff/settings.h b/sonoff/settings.h index 3876baf60..7a44ef9cc 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -64,7 +64,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t data; // Allow bit manipulation using SetOption struct { // SetOption50 .. SetOption81 uint32_t timers_enable : 1; // bit 0 (v6.1.1b) - uint32_t spare01 : 1; + uint32_t user_esp8285_enable : 1; // bit 1 (v6.1.1.14) uint32_t spare02 : 1; uint32_t spare03 : 1; uint32_t spare04 : 1; @@ -94,7 +94,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t spare28 : 1; uint32_t spare29 : 1; uint32_t spare30 : 1; - uint32_t user_esp8285_enable : 1; // bit 31 (v6.1.1.14) + uint32_t spare31 : 1; }; } SysBitfield3; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index a7315623d..b3760faa2 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -843,9 +843,11 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) else if ((CMND_GPIO == command_code) && (index < MAX_GPIO_PIN)) { mytmplt cmodule; memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); - if ((GPIO_USER == cmodule.gp.io[index]) && (payload >= 0) && (payload < GPIO_SENSOR_END)) { +// if ((GPIO_USER == cmodule.gp.io[index]) && (payload >= 0) && (payload < GPIO_SENSOR_END)) { + if ((GPIO_USER == ValidGPIO(index, 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]) && (Settings.my_gp.io[i] == payload)) { +// if ((GPIO_USER == cmodule.gp.io[i]) && (Settings.my_gp.io[i] == payload)) { + if ((GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) && (Settings.my_gp.io[i] == payload)) { Settings.my_gp.io[i] = 0; } } @@ -854,7 +856,8 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (GPIO_USER == cmodule.gp.io[i]) { +// if (GPIO_USER == cmodule.gp.io[i]) { + if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { if (jsflg) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); jsflg = 1; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_GPIO "%d\":\"%d (%s)\""), diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index f4df759c8..178e0af68 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020101 +#define VERSION 0x06020102 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" From dd95bb393e807eb9fa30670df68d9c7c8be722d7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 6 Sep 2018 12:37:50 +0200 Subject: [PATCH 0047/2222] Add command SetOption52 Add command SetOption52 to control display of optional time offset from UTC in JSON messages (#3629, #3711) --- sonoff/_changelog.ino | 1 + sonoff/settings.h | 2 +- sonoff/support.ino | 10 +++++----- sonoff/user_config.h | 27 ++++++++++++--------------- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index c34a70697..7e7bdc520 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.2.1.2 20180906 * Fix KNX PA exception. Regression from 6.2.1 buffer overflow (#3700, #3710) + * Add command SetOption52 to control display of optional time offset from UTC in JSON messages (#3629, #3711) * * 6.2.1.1 20180905 * Rewrite energy monitoring using energy sensor driver modules diff --git a/sonoff/settings.h b/sonoff/settings.h index 7a44ef9cc..32bc80ad0 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -65,7 +65,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu struct { // SetOption50 .. SetOption81 uint32_t timers_enable : 1; // bit 0 (v6.1.1b) uint32_t user_esp8285_enable : 1; // bit 1 (v6.1.1.14) - uint32_t spare02 : 1; + uint32_t time_append_timezone : 1; // bit 2 (v6.2.1.2) uint32_t spare03 : 1; uint32_t spare04 : 1; uint32_t spare05 : 1; diff --git a/sonoff/support.ino b/sonoff/support.ino index ca361d3b3..51b59c554 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1804,13 +1804,13 @@ String GetBuildDateAndTime() /* * timestamps in https://en.wikipedia.org/wiki/ISO_8601 format - * + * * DT_UTC - current data and time in Greenwich, England (aka GMT) * DT_LOCAL - current date and time taking timezone into account * DT_RESTART - the date and time this device last started, in local timezone - * + * * Format: - * "2017-03-07T11:08:02-07:00" - if DT_LOCAL and TIME_APPEND_TIMEZONE=1 + * "2017-03-07T11:08:02-07:00" - if DT_LOCAL and SetOption52 = 1 * "2017-03-07T11:08:02" - otherwise */ String GetDateAndTime(byte time_type) @@ -1838,8 +1838,8 @@ String GetDateAndTime(byte time_type) snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), tmpTime.year, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); - if (TIME_APPEND_TIMEZONE && (time_type == DT_LOCAL)) { - snprintf_P(dt, sizeof(dt), PSTR("%s%+03d:00"), dt, Settings.timezone); + if (Settings.flag3.time_append_timezone && (time_type == DT_LOCAL)) { + snprintf_P(dt, sizeof(dt), PSTR("%s%+03d:%02d"), dt, time_timezone / 10, abs((time_timezone % 10) * 6)); // if timezone = +2:30 then time_timezone = 25 } return String(dt); diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 3dbf9c5b2..ece854530 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -137,23 +137,20 @@ #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_HEMISPHERE North // [TimeDst] Hemisphere (0 or North, 1 or South) -#define TIME_DST_WEEK Last // Week of month (0 or Last, 1 or First, 2 or Second, 3 or Third, 4 or Fourth) -#define TIME_DST_DAY Sun // Day of week (1 or Sun, 2 or Mon, 3 or Tue, 4 or Wed, 5 or Thu, 6 or Fri, 7 or Sat) -#define TIME_DST_MONTH Mar // Month (1 or Jan, 2 or Feb, 3 or Mar, 4 or Apr, 5 or May, 6 or Jun, 7 or Jul, 8 or Aug, 9 or Sep, 10 or Oct, 11 or Nov, 12 or Dec) -#define TIME_DST_HOUR 2 // Hour (0 to 23) -#define TIME_DST_OFFSET +120 // Offset from UTC in minutes (-780 to +780) +#define TIME_DST_HEMISPHERE North // [TimeDst] Hemisphere (0 or North, 1 or South) +#define TIME_DST_WEEK Last // Week of month (0 or Last, 1 or First, 2 or Second, 3 or Third, 4 or Fourth) +#define TIME_DST_DAY Sun // Day of week (1 or Sun, 2 or Mon, 3 or Tue, 4 or Wed, 5 or Thu, 6 or Fri, 7 or Sat) +#define TIME_DST_MONTH Mar // Month (1 or Jan, 2 or Feb, 3 or Mar, 4 or Apr, 5 or May, 6 or Jun, 7 or Jul, 8 or Aug, 9 or Sep, 10 or Oct, 11 or Nov, 12 or Dec) +#define TIME_DST_HOUR 2 // Hour (0 to 23) +#define TIME_DST_OFFSET +120 // Offset from UTC in minutes (-780 to +780) // -- Time - Start Standard Time and timezone offset from UTC in minutes -#define TIME_STD_HEMISPHERE North // [TimeStd] Hemisphere (0 or North, 1 or South) -#define TIME_STD_WEEK Last // Week of month (0 or Last, 1 or First, 2 or Second, 3 or Third, 4 or Fourth) -#define TIME_STD_DAY Sun // Day of week (1 or Sun, 2 or Mon, 3 or Tue, 4 or Wed, 5 or Thu, 6 or Fri, 7 or Sat) -#define TIME_STD_MONTH Oct // Month (1 or Jan, 2 or Feb, 3 or Mar, 4 or Apr, 5 or May, 6 or Jun, 7 or Jul, 8 or Aug, 9 or Sep, 10 or Oct, 11 or Nov, 12 or Dec) -#define TIME_STD_HOUR 3 // Hour (0 to 23) -#define TIME_STD_OFFSET +60 // Offset from UTC in minutes (-780 to +780) - -// -- Time - formatting options -#define TIME_APPEND_TIMEZONE 0 // for local timestamps: 0 = no timezone in string, 1 = append numeric timezone (e.g. "+1:00" or "-7:00") +#define TIME_STD_HEMISPHERE North // [TimeStd] Hemisphere (0 or North, 1 or South) +#define TIME_STD_WEEK Last // Week of month (0 or Last, 1 or First, 2 or Second, 3 or Third, 4 or Fourth) +#define TIME_STD_DAY Sun // Day of week (1 or Sun, 2 or Mon, 3 or Tue, 4 or Wed, 5 or Thu, 6 or Fri, 7 or Sat) +#define TIME_STD_MONTH Oct // Month (1 or Jan, 2 or Feb, 3 or Mar, 4 or Apr, 5 or May, 6 or Jun, 7 or Jul, 8 or Aug, 9 or Sep, 10 or Oct, 11 or Nov, 12 or Dec) +#define TIME_STD_HOUR 3 // Hour (0 to 23) +#define TIME_STD_OFFSET +60 // Offset from UTC in minutes (-780 to +780) // -- Location ------------------------------------ #define LATITUDE 48.858360 // [Latitude] Your location to be used with sunrise and sunset From b441c8577655629e532f299ff69e4a1c3fc5bb34 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 6 Sep 2018 17:35:57 +0200 Subject: [PATCH 0048/2222] Experimental PZEM-003,014,016,017 Add experimental support for PZEM-003,014,016,017 Energy monitoring (#3694) --- sonoff/_changelog.ino | 1 + sonoff/sonoff_template.h | 5 +- sonoff/user_config.h | 5 +- sonoff/xdrv_03_energy.ino | 1 + sonoff/xnrg_05_pzem2.ino | 215 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 sonoff/xnrg_05_pzem2.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 7e7bdc520..49193dfbd 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.2.1.2 20180906 * Fix KNX PA exception. Regression from 6.2.1 buffer overflow (#3700, #3710) * Add command SetOption52 to control display of optional time offset from UTC in JSON messages (#3629, #3711) + * Add experimental support for PZEM-003,014,016,017 Energy monitoring (#3694) * * 6.2.1.1 20180905 * Rewrite energy monitoring using energy sensor driver modules diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index b1087da97..3881f8c3e 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -120,6 +120,8 @@ enum UserSelectablePins { GPIO_CNTR2_NP, GPIO_CNTR3_NP, GPIO_CNTR4_NP, + GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface + GPIO_PZEM2_RX, // PZEM-003,014,016,017 Serial interface GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -169,7 +171,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_TM1638_CLK "|" D_SENSOR_TM1638_DIO "|" D_SENSOR_TM1638_STB "|" D_SENSOR_SWITCH "1n|" D_SENSOR_SWITCH "2n|" D_SENSOR_SWITCH "3n|" D_SENSOR_SWITCH "4n|" D_SENSOR_SWITCH "5n|" D_SENSOR_SWITCH "6n|" D_SENSOR_SWITCH "7n|" D_SENSOR_SWITCH "8n|" D_SENSOR_BUTTON "1n|" D_SENSOR_BUTTON "2n|" D_SENSOR_BUTTON "3n|" D_SENSOR_BUTTON "4n|" - D_SENSOR_COUNTER "1n|" D_SENSOR_COUNTER "2n|" D_SENSOR_COUNTER "3n|" D_SENSOR_COUNTER "4n|"; + D_SENSOR_COUNTER "1n|" D_SENSOR_COUNTER "2n|" D_SENSOR_COUNTER "3n|" D_SENSOR_COUNTER "4n|" + D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|"; /********************************************************************************************/ diff --git a/sonoff/user_config.h b/sonoff/user_config.h index ece854530..b742196a8 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -335,13 +335,16 @@ #define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) #define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) -#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) //#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) #define SDM120_SPEED 9600 // SDM120-Modbus RS485 serial speed (default: 2400 baud) //#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) +// Power monitoring sensors ----------------------- +#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) +#define USE_PZEM2 // Add support for PZEM003,014,016,017 Energy monitor (+2k code) + // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) // #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 5c122c314..d9cfee8cb 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -44,6 +44,7 @@ const char kEnergyCommands[] PROGMEM = float energy_voltage = 0; // 123.1 V float energy_current = 0; // 123.123 A float energy_power = 0; // 123.1 W +float energy_frequency = 0; // 123.1 Hz float energy_power_factor = 0; // 0.12 float energy_daily = 0; // 123.123 kWh float energy_total = 0; // 12345.12345 kWh diff --git a/sonoff/xnrg_05_pzem2.ino b/sonoff/xnrg_05_pzem2.ino new file mode 100644 index 000000000..2b326f216 --- /dev/null +++ b/sonoff/xnrg_05_pzem2.ino @@ -0,0 +1,215 @@ +/* + xnrg_06_pzem2.ino - PZEM-003,017 and PZEM-014,016 Modbus energy sensor support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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_ENERGY_SENSOR +#ifdef USE_PZEM2 +/*********************************************************************************************\ + * PZEM-003 - DC 300V 10A Energy + * PZEM-014 - AC 220V 10A Energy + * PZEM-016 - AC 220V 100A Energy + * PZEM-017 - DC 300V 50A - 300A Energy + * + * Based on: + * PZEM-003,017 docs Https://pan.baidu.com/s/1V9bDWj3RK2u6_fbBJ3GtqQ password rq37 + * PZEM-014,016 docs https://pan.baidu.com/s/1B0MdMgURyjtO1oQa2lavKw password ytkv + * + * Hardware Serial will be selected if GPIO1 = [99 PZEM Rx] and GPIO3 = [98 PZEM Tx] +\*********************************************************************************************/ + +#define XNRG_05 5 + +#define PZEM2_TYPES_003_017 8 // Result 16 bit register count +#define PZEM2_TYPES_014_016 10 // Result 16 bit register count + +#define PZEM2_READ_RESULT 0x04 + +#include + +TasmotaSerial *Pzem2Serial; + +uint8_t pzem2_type = PZEM2_TYPES_014_016; + +/*********************************************************************************************/ + +uint16_t Pzem2ModbusCalculateCRC(uint8_t *frame, uint8_t num) +{ + uint16_t crc = 0xFFFF; + uint16_t flag; + + for (uint8_t i = 0; i < num; i++) { + crc ^= frame[i]; + for (uint8_t j = 8; j; j--) { + if ((crc & 0x0001) != 0) { // If the LSB is set + crc >>= 1; // Shift right and XOR 0xA001 + crc ^= 0xA001; + } else { // Else LSB is not set + crc >>= 1; // Just shift right + } + } + } + return crc; +} + +void Pzem2ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count) +{ + uint8_t frame[8]; + + frame[0] = 0xFE; // Any Address + frame[1] = function_code; + frame[2] = (uint8_t)(start_address >> 8); + frame[3] = (uint8_t)(start_address); + frame[4] = (uint8_t)(register_count >> 8); + frame[5] = (uint8_t)(register_count); + uint16_t crc = Pzem2ModbusCalculateCRC(frame, 6); + frame[6] = (uint8_t)((crc >> 8) & 0xFF); + frame[7] = (uint8_t)(crc & 0xFF); + + Pzem2Serial->flush(); + Pzem2Serial->write(frame, sizeof(frame)); +} + +bool Pzem2ModbusReceiveReady() +{ + return (Pzem2Serial->available() >= 5); // 5 - Error frame, 21 or 25 - Ok frame +} + +uint8_t Pzem2ModbusReceive() +{ + uint8_t buffer[26]; + +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 +// FE 04 14 08 98 03 E8 00 00 08 98 00 00 00 00 00 00 01 F4 00 64 00 00 HH LL = PZEM-014 +// Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc-- +// FE 04 10 27 10 00 64 03 E8 00 00 00 00 00 00 00 00 00 00 HH LL = PZEM-017 +// Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc-- + + uint8_t len = 0; + while (Pzem2Serial->available() > 0) { + buffer[len++] = (uint8_t)Pzem2Serial->read(); + if (3 == len) { + if (buffer[1] & 0x80) { // fe 84 02 f2 f1 + return buffer[2]; // 1 = Illegal Function, 2 = Illegal Address, 3 = Illegal Data, 4 = Slave Error + } + } + if (sizeof(buffer) == len) { break; } + } + + AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, len); + + if (len < 5) { return 8; } // 8 = Not enough data + if (len != buffer[2] + 5) { return 9; } // 9 = Unexpected result + + uint16_t crc = (buffer[len -2] << 8) | buffer[len -1]; + if (Pzem2ModbusCalculateCRC(buffer, len -3) == crc) { + float energy = 0; + if (0x10 == buffer[2]) { // PZEM-003,017 + pzem2_type = PZEM2_TYPES_003_017; + energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 65535.x V + energy_current = (float)((buffer[5] << 8) + buffer[6]); // 65535.xx A + energy_power = (float)((uint32_t)buffer[9] << 24 + (uint32_t)buffer[10] << 16 + (uint32_t)buffer[7] << 8 + buffer[8]); // 65535 W + energy = (float)((uint32_t)buffer[13] << 24 + (uint32_t)buffer[14] << 16 + (uint32_t)buffer[11] << 8 + buffer[12]); // 65535 Wh + if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any + energy_kWhtoday += (energy - energy_start) * 100; + energy_start = energy; + EnergyUpdateToday(); + } + else if (0x14 == buffer[2]) { // PZEM-014,016 + pzem2_type = PZEM2_TYPES_014_016; + energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 65535.x V + energy_current = (float)((uint32_t)buffer[7] << 24 + (uint32_t)buffer[8] << 16 + (uint32_t)buffer[5] << 8 + buffer[6]); // 65535.xx A + energy_power = (float)((uint32_t)buffer[11] << 24 + (uint32_t)buffer[12] << 16 + (uint32_t)buffer[9] << 8 + buffer[10]); // 65535 W + energy_frequency = (float)((buffer[13] << 8) + buffer[14]) / 10.0; // 50.0 Hz + energy = (float)((uint32_t)buffer[15] << 24 + (uint32_t)buffer[16] << 16 + (uint32_t)buffer[13] << 8 + buffer[14]); // 65535 Wh + if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any + energy_kWhtoday += (energy - energy_start) * 100; + energy_start = energy; + EnergyUpdateToday(); + } + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Pzem2 crc error")); + } + + return 0; // 0 = No error +} + +/*********************************************************************************************/ + +uint8_t pzem2_sendRetry = 0; + +void Pzem2EverySecond() +{ + bool data_ready = Pzem2ModbusReceiveReady(); + + if (data_ready) { Pzem2ModbusReceive(); } + + if (0 == pzem2_sendRetry || data_ready) { + pzem2_sendRetry = 5; + Pzem2ModbusSend(PZEM2_READ_RESULT, 0, pzem2_type); + } + else { + pzem2_sendRetry--; + } +} + +void Pzem2SnsInit() +{ + // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions + Pzem2Serial = new TasmotaSerial(pin[GPIO_PZEM2_RX], pin[GPIO_PZEM2_TX], 1); + if (Pzem2Serial->begin(9600)) { + if (Pzem2Serial->hardwareSerial()) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void Pzem2DrvInit() +{ + if (!energy_flg) { + if ((pin[GPIO_PZEM2_RX] < 99) && (pin[GPIO_PZEM2_TX] < 99)) { // Any device with a Pzem-003,014,016,017 + energy_flg = XNRG_05; + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +int Xnrg05(byte function) +{ + int result = 0; + + if (FUNC_PRE_INIT == function) { + Pzem2DrvInit(); + } + else if (XNRG_03 == energy_flg) { + switch (function) { + case FUNC_INIT: + Pzem2SnsInit(); + break; + case FUNC_EVERY_SECOND: + Pzem2EverySecond(); + break; + } + } + return result; +} + +#endif // USE_PZEM2 +#endif // USE_ENERGY_SENSOR From 2fdc91f1b4b671b8d1af45354073e3fed1b66a02 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 6 Sep 2018 18:08:10 +0200 Subject: [PATCH 0049/2222] Housekeeping --- sonoff/support.ino | 19 ++++++++++++++++++- sonoff/user_config.h | 2 +- tools/decode-status.py | 8 +++++--- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 51b59c554..57cb6d9f4 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -609,6 +609,10 @@ boolean GetUsedInModule(byte val, uint8_t *arr) if (GPIO_PZEM_TX == val) { return true; } if (GPIO_PZEM_RX == val) { return true; } #endif +#ifndef USE_PZEM2 + if (GPIO_PZEM2_TX == val) { return true; } + if (GPIO_PZEM2_RX == val) { return true; } +#endif #ifndef USE_SENSEAIR if (GPIO_SAIR_TX == val) { return true; } if (GPIO_SAIR_RX == val) { return true; } @@ -965,7 +969,7 @@ void GetFeatures() feature_sns1 |= 0x00000004; // xdrv_03_energy.ino #endif #ifdef USE_PZEM004T - feature_sns1 |= 0x00000008; // xdrv_03_energy.ino + feature_sns1 |= 0x00000008; // xnrg_03_pzem004t.ino #endif #ifdef USE_DS18B20 feature_sns1 |= 0x00000010; // xsns_05_ds18b20.ino @@ -1074,6 +1078,19 @@ void GetFeatures() #ifdef USE_MCP230xx_DISPLAYOUTPUT feature_sns2 |= 0x00000020; // xsns_29_mcp230xx.ino #endif +#ifdef USE_HLW8012 + feature_sns2 |= 0x00000040; // xnrg_01_hlw8012.ino +#endif +#ifdef USE_CSE7766 + feature_sns2 |= 0x00000080; // xnrg_02_cse7766.ino +#endif +#ifdef USE_MCP39F501 + feature_sns2 |= 0x00000100; // xnrg_04_mcp39f501.ino +#endif +#ifdef USE_PZEM2 + feature_sns2 |= 0x00000200; // xnrg_05_pzem2.ino +#endif + } /*********************************************************************************************\ diff --git a/sonoff/user_config.h b/sonoff/user_config.h index b742196a8..81928f1e7 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -343,7 +343,7 @@ // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) -#define USE_PZEM2 // Add support for PZEM003,014,016,017 Energy monitor (+2k code) +#define USE_PZEM2 // Add support for PZEM003,014,016,017 Energy monitor (+1k1 code) // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) diff --git a/tools/decode-status.py b/tools/decode-status.py index 7f06b674b..b26be9df0 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -83,7 +83,9 @@ a_setoption = [[ "Do not show Wifi and Mqtt state using Led" ],[ "Timers enabled", - "","","", + "Generic ESP8285 GPIO enabled", + "Add UTC time offset to JSON message", + "", "","","","", "","","","", "","","","", @@ -122,8 +124,8 @@ a_features = [[ "USE_SDM630","USE_LM75AD","USE_APDS9960","USE_TM1638" ],[ "USE_MCP230xx","USE_MPR121","USE_CCS811","USE_MPU6050", - "USE_MCP230xx_OUTPUT","USE_MCP230xx_DISPLAYOUTPUT","","", - "","","","", + "USE_MCP230xx_OUTPUT","USE_MCP230xx_DISPLAYOUTPUT","USE_HLW8012","USE_CSE7766", + "USE_MCP39F501","USE_PZEM2","","", "","","","", "","","","", "","","","", From 420be8f4990ec838d51b0f58dad8c814db058461 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 6 Sep 2018 14:21:52 -0300 Subject: [PATCH 0050/2222] Simplified Function Substr --- sonoff/support.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 57cb6d9f4..d00ee009b 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -143,7 +143,7 @@ char* subStr(char* dest, char* str, const char *delim, int index) int i; // Since strtok consumes the first arg, make a copy - strncpy(dest, str, strlen(str)); + strncpy(dest, str, strlen(str)+1); for (i = 1, act = dest; i <= index; i++, act = NULL) { sub = strtok_r(act, delim, &ptr); if (sub == NULL) break; From 96aff63c712f2ec81ae28e1cf207d8fb4ccbe278 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 6 Sep 2018 14:26:26 -0300 Subject: [PATCH 0051/2222] Code Simplification for Substr --- sonoff/xdrv_11_knx.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index ca5e22090..3897caac7 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -1156,7 +1156,7 @@ boolean KnxCommand() else if (CMND_KNX_PA == command_code) { if (XdrvMailbox.data_len) { if (strstr(XdrvMailbox.data, ".")) { // Process parameter entry - char sub_string[XdrvMailbox.data_len +1]; + char sub_string[XdrvMailbox.data_len]; int pa_area = atoi(subStr(sub_string, XdrvMailbox.data, ".", 1)); int pa_line = atoi(subStr(sub_string, XdrvMailbox.data, ".", 2)); @@ -1183,7 +1183,7 @@ boolean KnxCommand() else if ((CMND_KNX_GA == command_code) && (index > 0) && (index <= MAX_KNX_GA)) { if (XdrvMailbox.data_len) { if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry - char sub_string[XdrvMailbox.data_len +1]; + char sub_string[XdrvMailbox.data_len]; int ga_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); int ga_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); @@ -1232,7 +1232,7 @@ boolean KnxCommand() else if ((CMND_KNX_CB == command_code) && (index > 0) && (index <= MAX_KNX_CB)) { if (XdrvMailbox.data_len) { if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry - char sub_string[XdrvMailbox.data_len +1]; + char sub_string[XdrvMailbox.data_len]; int cb_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); int cb_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); From c827270cc2c3e1f3bc315cf5a420c7ba8b65fec2 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Thu, 6 Sep 2018 19:26:52 +0200 Subject: [PATCH 0052/2222] Update MCP230xx to conform to new usage of subStr() --- sonoff/support.ino | 2 +- sonoff/xsns_29_mcp230xx.ino | 27 ++++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 57cb6d9f4..d00ee009b 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -143,7 +143,7 @@ char* subStr(char* dest, char* str, const char *delim, int index) int i; // Since strtok consumes the first arg, make a copy - strncpy(dest, str, strlen(str)); + strncpy(dest, str, strlen(str)+1); for (i = 1, act = dest; i <= index; i++, act = NULL) { sub = strtok_r(act, delim, &ptr); if (sub == NULL) break; diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index f27d68990..d6683da44 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -421,10 +421,11 @@ bool MCP230xx_Command(void) { uint8_t paramcount = 0; if (XdrvMailbox.data_len > 0) { paramcount=1; - sprintf(XdrvMailbox.data,"%s,",XdrvMailbox.data); // need a trailing comma to make substr work properly with last variable - bug? dunno? - XdrvMailbox.data_len++; + } else { + serviced = false; + return serviced; } - char sub_string[XdrvMailbox.data_len +1]; + char sub_string[XdrvMailbox.data_len]; for (uint8_t ca=0;ca 2) { + if (paramcount > 1) { uint8_t intpri = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); if ((intpri >= 0) && (intpri <= 20)) { Settings.mcp230xx_int_prio = intpri; @@ -455,7 +456,7 @@ bool MCP230xx_Command(void) { } if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTTIMER")) { - if (paramcount > 2) { + if (paramcount > 1) { uint8_t inttim = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); if ((inttim >= 0) && (inttim <= 3600)) { Settings.mcp230xx_int_timer = inttim; @@ -470,7 +471,7 @@ bool MCP230xx_Command(void) { } if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTDEF")) { - if (paramcount > 2) { + if (paramcount > 1) { uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); if (pin < mcp230xx_pincount) { if (pin == 0) { @@ -480,7 +481,7 @@ bool MCP230xx_Command(void) { } } if (validpin) { - if (paramcount > 3) { + if (paramcount > 2) { uint8_t intdef = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); if ((intdef >= 0) && (intdef <= 15)) { Settings.mcp230xx_config[pin].int_report_defer=intdef; @@ -510,7 +511,7 @@ bool MCP230xx_Command(void) { } if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTCNT")) { - if (paramcount > 2) { + if (paramcount > 1) { uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); if (pin < mcp230xx_pincount) { if (pin == 0) { @@ -520,7 +521,7 @@ bool MCP230xx_Command(void) { } } if (validpin) { - if (paramcount > 3) { + if (paramcount > 2) { uint8_t intcnt = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); if ((intcnt >= 0) && (intcnt <= 1)) { Settings.mcp230xx_config[pin].int_count_en=intcnt; @@ -567,7 +568,7 @@ bool MCP230xx_Command(void) { validpin=true; } } - if (validpin && (paramcount > 2)) { + if (validpin && (paramcount > 1)) { if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "?")) { uint8_t port = 0; if (pin > 7) { port = 1; } @@ -606,13 +607,13 @@ bool MCP230xx_Command(void) { uint8_t pinmode = 0; uint8_t pullup = 0; uint8_t intmode = 0; - if (paramcount > 2) { + if (paramcount > 1) { pinmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); } - if (paramcount > 3) { + if (paramcount > 2) { pullup = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); } - if (paramcount > 4) { + if (paramcount > 3) { intmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); } #ifdef USE_MCP230xx_OUTPUT From 10bb6b856f8588f43943015124161675c343cae5 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 6 Sep 2018 15:38:10 -0300 Subject: [PATCH 0053/2222] Fix Compilation of Sonoff Classic Version --- sonoff/sonoff_post.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index dc49211d1..7504af3b4 100755 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -137,6 +137,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor #undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor #undef USE_PZEM004T // Disable PZEM004T energy sensor +#undef USE_PZEM2 // Disable PZEM003,014,016,017 Energy monitor #undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter From 7722f5232a4d484b5c2ca862f55a6e727119a26c Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 07:54:29 +0200 Subject: [PATCH 0054/2222] Added DFPlayer Mini MP3 Player (RB-DFR-562) --- sonoff/sonoff_template.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 3881f8c3e..c6e70b98c 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -122,6 +122,7 @@ enum UserSelectablePins { GPIO_CNTR4_NP, GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface GPIO_PZEM2_RX, // PZEM-003,014,016,017 Serial interface + GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -172,7 +173,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SWITCH "1n|" D_SENSOR_SWITCH "2n|" D_SENSOR_SWITCH "3n|" D_SENSOR_SWITCH "4n|" D_SENSOR_SWITCH "5n|" D_SENSOR_SWITCH "6n|" D_SENSOR_SWITCH "7n|" D_SENSOR_SWITCH "8n|" D_SENSOR_BUTTON "1n|" D_SENSOR_BUTTON "2n|" D_SENSOR_BUTTON "3n|" D_SENSOR_BUTTON "4n|" D_SENSOR_COUNTER "1n|" D_SENSOR_COUNTER "2n|" D_SENSOR_COUNTER "3n|" D_SENSOR_COUNTER "4n|" - D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|"; + D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|" + D_SENSOR_MP3_DFR562; /********************************************************************************************/ @@ -1019,4 +1021,4 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { } */ -#endif // _SONOFF_TEMPLATE_H_ \ No newline at end of file +#endif // _SONOFF_TEMPLATE_H_ From a416f0b33487bd5dc37ab2dd1cec6c8e2d55839c Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 07:59:08 +0200 Subject: [PATCH 0055/2222] Add files via upload --- sonoff/xdrv_91_mp3.ino | 117 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 sonoff/xdrv_91_mp3.ino diff --git a/sonoff/xdrv_91_mp3.ino b/sonoff/xdrv_91_mp3.ino new file mode 100644 index 000000000..82c778127 --- /dev/null +++ b/sonoff/xdrv_91_mp3.ino @@ -0,0 +1,117 @@ +/* + xdrv_91_mp3.ino - MP3 Player support for Sonoff-Tasmota + Player type: RB-DFR-562, DFPlayer Mini MP3 Player + Copyright (C) 2018 Theo Arends + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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_MP3_PLAYER + +#include + +TasmotaSerial *MP3Player; + +#define D_CMND_MP3 "MP3" +const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}"; +const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}"; + +enum MP3_Commands { CMND_MP3_PLAY, CMND_MP3_STOP, CMND_MP3_VOLUME}; +const char kMP3_Commands[] PROGMEM = "Play" "|" "Stop" "|" "Volume"; + +#define MP3_CMD_PLAY 3 +#define MP3_CMD_VOLUME 6 +#define MP3_CMD_STOP 0x0e + +uint16_t MP3_Checksum(uint8_t *array) +{ + uint16_t checksum = 0; + for (uint8_t i = 0; i < 6; i++) { + checksum += array[i]; + } + checksum = checksum^0xffff; + return checksum+1; +} + +// init player define serial tx port +void InitMP3Player() { + MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3PLAYER]); + + if (MP3Player->begin(9600)) { + //serial_bridge_active = 1; + MP3Player->flush(); + } +} + +void MP3_CMD(uint8_t mp3cmd,uint16_t val) { + uint8_t cmd[10] = {0x7e,0xff,6,0,0,0,0,0,0,0xef}; + cmd[3] = mp3cmd; + cmd[5] = val>>8; + cmd[6] = val; + uint16_t chks = MP3_Checksum(&cmd[1]); // calculate out + cmd[7] = chks>>8; + cmd[8] = chks; + MP3Player->write(cmd, sizeof(cmd)); +} + +boolean MP3PlayerCmd() { + char command[CMDSZ]; + boolean serviced = true; + uint8_t disp_len = strlen(D_CMND_MP3); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { // Prefix + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMP3_Commands); + + if (CMND_MP3_PLAY == command_code) { + if (XdrvMailbox.data_len > 0) { // play + MP3_CMD(MP3_CMD_PLAY, XdrvMailbox.payload); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); + } + else if (CMND_MP3_VOLUME == command_code) { + if (XdrvMailbox.data_len > 0) { // set volume + MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); + } + else if (CMND_MP3_STOP == command_code) { // stop + MP3_CMD(MP3_CMD_STOP, 0); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); + } else { + serviced = false; // Unknown command + } + } + return serviced; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XDRV_91 + +boolean Xdrv91(byte function) +{ + boolean result = false; + + switch (function) { + case FUNC_PRE_INIT: + InitMP3Player(); + break; + case FUNC_COMMAND: + result = MP3PlayerCmd(); + break; + } + return result; +} + +#endif // USE_MP3_PLAYER From 5582c85b3b36bad9d37bc0d4af9f8c118c0f5573 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:05:58 +0200 Subject: [PATCH 0056/2222] define MP3 Player added //#define USE_MP3_PLAYER --- sonoff/user_config.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 81928f1e7..b7a54408d 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -268,6 +268,9 @@ // -- Internal Analog input ----------------------- #define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices +// -- MP3 player ---------------------------------- +//#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop + // -- One wire sensors ---------------------------- // WARNING: Select none for default one DS18B20 sensor or enable one of the following two options for multiple sensors #define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) From b13c5452a510774019a172a10b031b13639af5fb Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:10:32 +0200 Subject: [PATCH 0057/2222] Added #define D_SENSOR_MP3_DFR562 "MP3 Player" --- sonoff/language/en-GB.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 558877db2..e6ce2eca4 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_MP3_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Switch" // Suffix "1" #define D_SENSOR_BUTTON "Button" // Suffix "1" From 7fd8dcd68dfe77624e7b227208e56e4b4fe78233 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:11:53 +0200 Subject: [PATCH 0058/2222] Update en-GB.h --- sonoff/language/en-GB.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index e6ce2eca4..a622419fa 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -456,7 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_MP3_DFR562 "MP3 Player" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Switch" // Suffix "1" #define D_SENSOR_BUTTON "Button" // Suffix "1" From 96682723d32e400bb37ba00e95c92f5b04c5db2b Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:14:07 +0200 Subject: [PATCH 0059/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/sonoff_template.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index c6e70b98c..2ab43286d 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -174,7 +174,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_BUTTON "1n|" D_SENSOR_BUTTON "2n|" D_SENSOR_BUTTON "3n|" D_SENSOR_BUTTON "4n|" D_SENSOR_COUNTER "1n|" D_SENSOR_COUNTER "2n|" D_SENSOR_COUNTER "3n|" D_SENSOR_COUNTER "4n|" D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|" - D_SENSOR_MP3_DFR562; + D_SENSOR_DFR562; /********************************************************************************************/ From 14ab4b718d2257e2acc350692e0376d0eaaaae67 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:16:03 +0200 Subject: [PATCH 0060/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/bg-BG.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index b1ecd6fa6..bd76cf0be 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Ключ" // Suffix "1" #define D_SENSOR_BUTTON "Бутон" // Suffix "1" From 7722c663a033b1fad68ca9e78aa441ffb8f1c8ff Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:17:26 +0200 Subject: [PATCH 0061/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/cs-CZ.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 2f51ccc93..0a3430e01 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Spínač" // Suffix "1" #define D_SENSOR_BUTTON "Tlačítko" // Suffix "1" From a5c85a6882a4648b1e5e8258be5d07968ef6eac2 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:18:06 +0200 Subject: [PATCH 0062/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/de-DE.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 888345d8a..32d6a8f2b 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRSend" #define D_SENSOR_SWITCH "Switch " // Suffix "1" #define D_SENSOR_BUTTON "Button " // Suffix "1" From 9ce856bb6ee7b7a146354a1fb226b4887c687e48 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:19:41 +0200 Subject: [PATCH 0063/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/el-GR.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 3187eadf9..b2fa8feb6 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Διακόπτης" // Suffix "1" #define D_SENSOR_BUTTON "Κουμπί" // Suffix "1" From f891a8a2e73d172e7368ac5d089ba4a9c017ed2e Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:22:02 +0200 Subject: [PATCH 0064/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/es-AR.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 986b9507f..398d0442f 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IR TX" #define D_SENSOR_SWITCH "Llave" // Suffix "1" #define D_SENSOR_BUTTON "Botón" // Suffix "1" From 1791f8e034ffb1f0fab077592eb4b913e75ef2b8 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:23:00 +0200 Subject: [PATCH 0065/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/fr-FR.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 2a46f7b53..a4b7d2011 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "ÉmetIR" #define D_SENSOR_SWITCH "Inter." // Suffix "1" #define D_SENSOR_BUTTON "Bouton" // Suffix "1" From f3ebfe7c5f3e10f19ed406720b8136070eeba2b7 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:24:03 +0200 Subject: [PATCH 0066/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/it-IT.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index d07a33021..509105eb5 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Switch" // Suffix "1" #define D_SENSOR_BUTTON "Button" // Suffix "1" From efd1b8a1a3643af57ffda75a049288ab83f3ce72 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:24:12 +0200 Subject: [PATCH 0067/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/hu-HU.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index c57278176..79fd88d8e 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRadó" #define D_SENSOR_SWITCH "Kapcsoló" // Suffix "1" #define D_SENSOR_BUTTON "Gomb" // Suffix "1" From 3b22dc7d52b1f7b7761a746389928b1a8a9120c3 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:26:33 +0200 Subject: [PATCH 0068/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/nl-NL.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 05ec4666b..2761e45d3 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Speler" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Switch" // Suffix "1" #define D_SENSOR_BUTTON "Button" // Suffix "1" From d6324a9f44edf58e4fe9d29b66832ba5aa8c3732 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:27:28 +0200 Subject: [PATCH 0069/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/pl-PL.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index faaf8df6d..9fa16ac9f 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Przela" // Suffix "1" #define D_SENSOR_BUTTON "Przyci" // Suffix "1" From 1cf7bc747df792834a412914c5fe7f69ed54e384 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:28:50 +0200 Subject: [PATCH 0070/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/pt-PT.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index d39ec6e50..d4cea0a48 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Interruptor" // Suffix "1" #define D_SENSOR_BUTTON "Botão" // Suffix "1" From f6f69e3b4df2245e739c969e62cd7c1e181c127b Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:29:00 +0200 Subject: [PATCH 0071/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/pt-BR.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 318f69e45..46a21b998 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Interruptor" // Suffix "1" #define D_SENSOR_BUTTON "Botão" // Suffix "1" From 764af507b9df4fa057cc8202f3455404c1d0d1ee Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:30:24 +0200 Subject: [PATCH 0072/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/tr-TR.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index b133d2c80..1f11d4a01 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Switch" // Suffix "1" #define D_SENSOR_BUTTON "Button" // Suffix "1" From 8dfbaf656651cbdc164c2177ae9fd9eef6cdb004 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:30:31 +0200 Subject: [PATCH 0073/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/ru-RU.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 5fea0468e..e782e9409 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Свич" // Suffix "1" #define D_SENSOR_BUTTON "Кнопка" // Suffix "1" From a33566f93e547a6014119b4aa1c41cee2a102a78 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:34:15 +0200 Subject: [PATCH 0074/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/zh-TW.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index abb92d359..c07023268 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Switch" // Suffix "1" #define D_SENSOR_BUTTON "Button" // Suffix "1" From a37f0b397335ff79a558852d4e38d29c322fc845 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:34:22 +0200 Subject: [PATCH 0075/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/zh-CN.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 88f680f8e..24eb38f6f 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Switch" // Suffix "1" #define D_SENSOR_BUTTON "Button" // Suffix "1" From 9bb6c201dfe882a157077d53ac8b21e4f391e8b3 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 7 Sep 2018 08:34:31 +0200 Subject: [PATCH 0076/2222] Added DFPlayer Mini MP3 Player, D_SENSOR_DFR562 --- sonoff/language/uk-UK.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 9cf66773b..90cfb9f4a 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -456,6 +456,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Перемикач" // Suffix "1" #define D_SENSOR_BUTTON "Кнопка" // Suffix "1" From b659444c3abb8fd641ed1eb7eeeaa08034297f4f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 7 Sep 2018 10:54:24 +0200 Subject: [PATCH 0077/2222] Add basic MP3 player * Fix KNX PA exception. Regression from 6.2.1 buffer overflow caused by subStr() (#3700, #3710) * Add basic support for MP3 player using DFRobot RB-DFR-562 (#3723) --- sonoff/_changelog.ino | 3 +- sonoff/user_config.h | 4 +-- sonoff/{xdrv_91_mp3.ino => xdrv_14_mp3.ino} | 36 ++++++++++++--------- 3 files changed, 24 insertions(+), 19 deletions(-) rename sonoff/{xdrv_91_mp3.ino => xdrv_14_mp3.ino} (83%) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 49193dfbd..82d12f28e 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,7 +1,8 @@ /* 6.2.1.2 20180906 - * Fix KNX PA exception. Regression from 6.2.1 buffer overflow (#3700, #3710) + * Fix KNX PA exception. Regression from 6.2.1 buffer overflow caused by subStr() (#3700, #3710) * Add command SetOption52 to control display of optional time offset from UTC in JSON messages (#3629, #3711) * Add experimental support for PZEM-003,014,016,017 Energy monitoring (#3694) + * Add basic support for MP3 player using DFRobot RB-DFR-562 (#3723) * * 6.2.1.1 20180905 * Rewrite energy monitoring using energy sensor driver modules diff --git a/sonoff/user_config.h b/sonoff/user_config.h index b7a54408d..d46a295d7 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -268,9 +268,6 @@ // -- Internal Analog input ----------------------- #define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices -// -- MP3 player ---------------------------------- -//#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop - // -- One wire sensors ---------------------------- // WARNING: Select none for default one DS18B20 sensor or enable one of the following two options for multiple sensors #define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) @@ -343,6 +340,7 @@ #define SDM120_SPEED 9600 // SDM120-Modbus RS485 serial speed (default: 2400 baud) //#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) +//#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) diff --git a/sonoff/xdrv_91_mp3.ino b/sonoff/xdrv_14_mp3.ino similarity index 83% rename from sonoff/xdrv_91_mp3.ino rename to sonoff/xdrv_14_mp3.ino index 82c778127..e4c72cb16 100644 --- a/sonoff/xdrv_91_mp3.ino +++ b/sonoff/xdrv_14_mp3.ino @@ -1,32 +1,39 @@ /* - xdrv_91_mp3.ino - MP3 Player support for Sonoff-Tasmota - Player type: RB-DFR-562, DFPlayer Mini MP3 Player - Copyright (C) 2018 Theo Arends + xdrv_14_mp3.ino - MP3 support for Sonoff-Tasmota + + Copyright (C) 2018 gemu2015, mike2nl 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 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_MP3_PLAYER +/*********************************************************************************************\ + * MP3 control for RB-DFR-562 DFRobot mini MP3 player + * https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299 +\*********************************************************************************************/ #include TasmotaSerial *MP3Player; #define D_CMND_MP3 "MP3" + const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}"; const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}"; enum MP3_Commands { CMND_MP3_PLAY, CMND_MP3_STOP, CMND_MP3_VOLUME}; -const char kMP3_Commands[] PROGMEM = "Play" "|" "Stop" "|" "Volume"; +const char kMP3_Commands[] PROGMEM = "Play|Stop|Volume"; #define MP3_CMD_PLAY 3 #define MP3_CMD_VOLUME 6 @@ -43,11 +50,10 @@ uint16_t MP3_Checksum(uint8_t *array) } // init player define serial tx port -void InitMP3Player() { - MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3PLAYER]); - +void MP3PlayerInit() { + MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3_DFR562]); + if (MP3Player->begin(9600)) { - //serial_bridge_active = 1; MP3Player->flush(); } } @@ -67,7 +73,7 @@ boolean MP3PlayerCmd() { char command[CMDSZ]; boolean serviced = true; uint8_t disp_len = strlen(D_CMND_MP3); - + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { // Prefix int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMP3_Commands); @@ -82,7 +88,7 @@ boolean MP3PlayerCmd() { MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); - } + } else if (CMND_MP3_STOP == command_code) { // stop MP3_CMD(MP3_CMD_STOP, 0); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); @@ -97,15 +103,15 @@ boolean MP3PlayerCmd() { * Interface \*********************************************************************************************/ -#define XDRV_91 +#define XDRV_14 -boolean Xdrv91(byte function) +boolean Xdrv14(byte function) { boolean result = false; switch (function) { case FUNC_PRE_INIT: - InitMP3Player(); + MP3PlayerInit(); break; case FUNC_COMMAND: result = MP3PlayerCmd(); @@ -114,4 +120,4 @@ boolean Xdrv91(byte function) return result; } -#endif // USE_MP3_PLAYER +#endif // USE_MP3_PLAYER From f517755303587f5d5a6b60fb9c75d3dda2dabcde Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 7 Sep 2018 18:15:47 +0200 Subject: [PATCH 0078/2222] Prep for frequency display Prep for energy frequency display and update xnrg_05_pzem2.ino with correct register values --- sonoff/i18n.h | 1 + sonoff/settings.h | 3 +- sonoff/sonoff.ino | 14 +++-- sonoff/xdrv_03_energy.ino | 76 ++++++++++++++++++--------- sonoff/xnrg_01_hlw8012.ino | 37 ++++++------- sonoff/xnrg_02_cse7766.ino | 1 + sonoff/xnrg_03_pzem004t.ino | 1 + sonoff/xnrg_05_pzem2.ino | 101 ++++++++++++++++++++---------------- sonoff/xsns_23_sdm120.ino | 2 +- 9 files changed, 142 insertions(+), 94 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 5559ac6d1..da47371d8 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -181,6 +181,7 @@ #define D_CMND_PRESSURE_RESOLUTION "PressRes" #define D_CMND_POWER_RESOLUTION "WattRes" #define D_CMND_VOLTAGE_RESOLUTION "VoltRes" +#define D_CMND_FREQUENCY_RESOLUTION "FreqRes" #define D_CMND_CURRENT_RESOLUTION "AmpRes" #define D_CMND_ENERGY_RESOLUTION "EnergyRes" #define D_CMND_MODULE "Module" diff --git a/sonoff/settings.h b/sonoff/settings.h index 32bc80ad0..a1fd218ac 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -112,8 +112,7 @@ typedef union { uint32_t spare08 : 1; uint32_t spare09 : 1; uint32_t spare10 : 1; - uint32_t spare11 : 1; - uint32_t spare12 : 1; + uint32_t frequency_resolution : 2; uint32_t axis_resolution : 2; uint32_t current_resolution : 2; uint32_t voltage_resolution : 2; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 6163acfa4..6b2e8422b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -77,8 +77,8 @@ enum TasmotaCommands { CMND_BACKLOG, CMND_DELAY, CMND_POWER, CMND_FANSPEED, CMND_STATUS, CMND_STATE, CMND_POWERONSTATE, CMND_PULSETIME, CMND_BLINKTIME, CMND_BLINKCOUNT, CMND_SENSOR, CMND_SAVEDATA, CMND_SETOPTION, CMND_TEMPERATURE_RESOLUTION, CMND_HUMIDITY_RESOLUTION, - CMND_PRESSURE_RESOLUTION, CMND_POWER_RESOLUTION, CMND_VOLTAGE_RESOLUTION, CMND_CURRENT_RESOLUTION, CMND_ENERGY_RESOLUTION, CMND_MODULE, CMND_MODULES, - CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE, + CMND_PRESSURE_RESOLUTION, CMND_POWER_RESOLUTION, CMND_VOLTAGE_RESOLUTION, CMND_FREQUENCY_RESOLUTION, CMND_CURRENT_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_BUTTONDEBOUNCE, CMND_SWITCHDEBOUNCE, 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, @@ -87,8 +87,8 @@ enum TasmotaCommands { const char kTasmotaCommands[] PROGMEM = D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_FANSPEED "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|" D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SENSOR "|" 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_CURRENT_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_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_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_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" 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 "|" @@ -794,6 +794,12 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.voltage_resolution); } + else if (CMND_FREQUENCY_RESOLUTION == command_code) { + if ((payload >= 0) && (payload <= 3)) { + Settings.flag2.frequency_resolution = payload; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.frequency_resolution); + } else if (CMND_CURRENT_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.current_resolution = payload; diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index d9cfee8cb..081b52d83 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -44,11 +44,13 @@ const char kEnergyCommands[] PROGMEM = float energy_voltage = 0; // 123.1 V float energy_current = 0; // 123.123 A float energy_power = 0; // 123.1 W -float energy_frequency = 0; // 123.1 Hz -float energy_power_factor = 0; // 0.12 +float energy_power_factor = NAN; // 0.12 +int energy_calc_power_factor = 0; // Do not calculate power factor from data +float energy_frequency = NAN; // 123.1 Hz +float energy_start = 0; // 12345.12345 kWh total previous + float energy_daily = 0; // 123.123 kWh float energy_total = 0; // 12345.12345 kWh -float energy_start = 0; // 12345.12345 kWh total previous unsigned long energy_kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to energy_kWhtoday (HLW and CSE only) unsigned long energy_kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = energy_daily unsigned long energy_period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = energy_daily @@ -123,12 +125,14 @@ void Energy200ms() XnrgCall(FUNC_EVERY_200_MSECOND); - float power_factor = 0; - if (energy_voltage && energy_current && energy_power) { - power_factor = energy_power / (energy_voltage * energy_current); - if (power_factor > 1) power_factor = 1; + if (energy_calc_power_factor) { + float power_factor = 0; + if (energy_voltage && energy_current && energy_power) { + power_factor = energy_power / (energy_voltage * energy_current); + if (power_factor > 1) power_factor = 1; + } + energy_power_factor = power_factor; } - energy_power_factor = power_factor; } void EnergySaveState() @@ -537,11 +541,18 @@ void EnergySnsInit() } #ifdef USE_WEBSERVER -const char HTTP_ENERGY_SNS[] PROGMEM = "%s" +const char HTTP_ENERGY_SNS1[] PROGMEM = "%s" "{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" "{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}" - "{s}" D_POWER_FACTOR "{m}%s{e}" + "{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; + +const char HTTP_ENERGY_SNS2[] PROGMEM = "%s" + "{s}" D_POWER_FACTOR "{m}%s{e}"; + +const char HTTP_ENERGY_SNS3[] PROGMEM = "%s" + "{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"; + +const char HTTP_ENERGY_SNS4[] PROGMEM = "%s" "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; // {s} = , {m} = , {e} = @@ -555,31 +566,43 @@ void EnergyShow(boolean json) char energy_power_chr[10]; char energy_voltage_chr[10]; char energy_current_chr[10]; + char energy_frequency_chr[10]; char energy_power_factor_chr[10]; char energy_yesterday_chr[10]; char speriod[20]; + char spfactor[20]; + char sfrequency[20]; bool show_energy_period = (0 == tele_period); + dtostrfd(energy_power, Settings.flag2.wattage_resolution, energy_power_chr); + dtostrfd(energy_voltage, Settings.flag2.voltage_resolution, energy_voltage_chr); + dtostrfd(energy_current, Settings.flag2.current_resolution, energy_current_chr); + dtostrfd(energy_total, Settings.flag2.energy_resolution, energy_total_chr); + dtostrfd(energy_daily, Settings.flag2.energy_resolution, energy_daily_chr); + dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); + float energy = 0; if (show_energy_period) { if (energy_period) energy = (float)(energy_kWhtoday - energy_period) / 100; energy_period = energy_kWhtoday; + dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr); + snprintf_P(speriod, sizeof(speriod), PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr); + } + if (!isnan(energy_frequency)) { + dtostrfd(energy_frequency, Settings.flag2.frequency_resolution, energy_frequency_chr); + snprintf_P(sfrequency, sizeof(sfrequency), PSTR(",\"" D_JSON_FREQUENCY "\":%s"), energy_frequency_chr); + } + if (!isnan(energy_power_factor)) { + dtostrfd(energy_power_factor, 2, energy_power_factor_chr); + snprintf_P(spfactor, sizeof(spfactor), PSTR(",\"" D_JSON_POWERFACTOR "\":%s"), energy_power_factor_chr); } - dtostrfd(energy_total, Settings.flag2.energy_resolution, energy_total_chr); - dtostrfd(energy_daily, Settings.flag2.energy_resolution, energy_daily_chr); - dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr); - dtostrfd(energy_power, Settings.flag2.wattage_resolution, energy_power_chr); - dtostrfd(energy_voltage, Settings.flag2.voltage_resolution, energy_voltage_chr); - dtostrfd(energy_current, Settings.flag2.current_resolution, energy_current_chr); - dtostrfd(energy_power_factor, 2, energy_power_factor_chr); - dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); - if (json) { - snprintf_P(speriod, sizeof(speriod), PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" D_JSON_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), - mqtt_data, energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", energy_power_chr, energy_power_factor_chr, energy_voltage_chr, energy_current_chr); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" + D_JSON_POWERUSAGE "\":%s%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s%s}"), + mqtt_data, energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", + energy_power_chr, (!isnan(energy_power_factor)) ? spfactor : "", energy_voltage_chr, energy_current_chr, (!isnan(energy_frequency)) ? sfrequency : ""); #ifdef USE_DOMOTICZ if (show_energy_period) { // Only send if telemetry dtostrfd(energy_total * 1000, 1, energy_total_chr); @@ -593,7 +616,7 @@ void EnergyShow(boolean json) KnxSensor(KNX_ENERGY_VOLTAGE, energy_voltage); KnxSensor(KNX_ENERGY_CURRENT, energy_current); KnxSensor(KNX_ENERGY_POWER, energy_power); - KnxSensor(KNX_ENERGY_POWERFACTOR, energy_power_factor); + if (!isnan(energy_power_factor)) { KnxSensor(KNX_ENERGY_POWERFACTOR, energy_power_factor); } KnxSensor(KNX_ENERGY_DAILY, energy_daily); KnxSensor(KNX_ENERGY_TOTAL, energy_total); KnxSensor(KNX_ENERGY_START, energy_start); @@ -601,7 +624,10 @@ void EnergyShow(boolean json) #endif // USE_KNX #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS, mqtt_data, energy_voltage_chr, energy_current_chr, energy_power_chr, energy_power_factor_chr, energy_daily_chr, energy_yesterday_chr, energy_total_chr); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS1, mqtt_data, energy_voltage_chr, energy_current_chr, energy_power_chr); + if (!isnan(energy_power_factor)) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS2, mqtt_data, energy_power_factor_chr); } + if (!isnan(energy_frequency)) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS3, mqtt_data, energy_frequency_chr); } + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS4, mqtt_data, energy_daily_chr, energy_yesterday_chr, energy_total_chr); #endif // USE_WEBSERVER } } diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 440112c15..6ef196fb1 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -41,26 +41,26 @@ #define HLW_POWER_PROBE_TIME 10 // Number of seconds to probe for power before deciding none used -static byte hlw_select_ui_flag; -static byte hlw_ui_flag = 1; -static byte hlw_load_off; -static byte hlw_cf1_timer; -static unsigned long hlw_cf_pulse_length; -static unsigned long hlw_cf_pulse_last_time; -static unsigned long hlw_cf1_pulse_length; -static unsigned long hlw_cf1_pulse_last_time; -static unsigned long hlw_cf1_summed_pulse_length; -static unsigned long hlw_cf1_pulse_counter; -static unsigned long hlw_cf1_voltage_pulse_length; -static unsigned long hlw_cf1_current_pulse_length; -static unsigned long hlw_energy_period_counter; +byte hlw_select_ui_flag; +byte hlw_ui_flag = 1; +byte hlw_load_off; +byte hlw_cf1_timer; +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_period_counter; -static unsigned long hlw_power_ratio = 0; -static unsigned long hlw_voltage_ratio = 0; -static unsigned long hlw_current_ratio = 0; +unsigned long hlw_power_ratio = 0; +unsigned long hlw_voltage_ratio = 0; +unsigned long hlw_current_ratio = 0; -static unsigned long hlw_cf1_voltage_max_pulse_counter; -static unsigned long hlw_cf1_current_max_pulse_counter; +unsigned long hlw_cf1_voltage_max_pulse_counter; +unsigned long hlw_cf1_current_max_pulse_counter; #ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception void HlwCfInterrupt() ICACHE_RAM_ATTR; @@ -217,6 +217,7 @@ void HlwDrvInit() { if (!energy_flg) { if ((pin[GPIO_HLW_SEL] < 99) && (pin[GPIO_HLW_CF1] < 99) && (pin[GPIO_HLW_CF] < 99)) { // Sonoff Pow or any HLW8012 based device + energy_calc_power_factor = 1; // Calculate power factor from data energy_flg = XNRG_01; } } diff --git a/sonoff/xnrg_02_cse7766.ino b/sonoff/xnrg_02_cse7766.ino index 640da704e..84535cf96 100644 --- a/sonoff/xnrg_02_cse7766.ino +++ b/sonoff/xnrg_02_cse7766.ino @@ -185,6 +185,7 @@ void CseDrvInit() if ((SONOFF_S31 == Settings.module) || (SONOFF_POW_R2 == Settings.module)) { // Sonoff S31 or Sonoff Pow R2 baudrate = 4800; serial_config = SERIAL_8E1; + energy_calc_power_factor = 1; // Calculate power factor from data energy_flg = XNRG_02; } } diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index d009feea4..03581862c 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -215,6 +215,7 @@ void PzemDrvInit() { if (!energy_flg) { if ((pin[GPIO_PZEM_RX] < 99) && (pin[GPIO_PZEM_TX] < 99)) { // Any device with a Pzem004T + energy_calc_power_factor = 1; // Calculate power factor from data energy_flg = XNRG_03; } } diff --git a/sonoff/xnrg_05_pzem2.ino b/sonoff/xnrg_05_pzem2.ino index 2b326f216..7f9a4f8ba 100644 --- a/sonoff/xnrg_05_pzem2.ino +++ b/sonoff/xnrg_05_pzem2.ino @@ -89,61 +89,29 @@ bool Pzem2ModbusReceiveReady() return (Pzem2Serial->available() >= 5); // 5 - Error frame, 21 or 25 - Ok frame } -uint8_t Pzem2ModbusReceive() +uint8_t Pzem2ModbusReceive(uint8_t *buffer, uint8_t register_count) { - uint8_t buffer[26]; - -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 -// FE 04 14 08 98 03 E8 00 00 08 98 00 00 00 00 00 00 01 F4 00 64 00 00 HH LL = PZEM-014 -// Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc-- -// FE 04 10 27 10 00 64 03 E8 00 00 00 00 00 00 00 00 00 00 HH LL = PZEM-017 -// Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc-- + // 0 1 2 3 4 5 6 + // FE 04 02 08 98 HH LL + // Id Cc Sz Regis Crc-- uint8_t len = 0; - while (Pzem2Serial->available() > 0) { + while ((Pzem2Serial->available() > 0) && (len < (register_count *2) + 5)) { buffer[len++] = (uint8_t)Pzem2Serial->read(); if (3 == len) { if (buffer[1] & 0x80) { // fe 84 02 f2 f1 return buffer[2]; // 1 = Illegal Function, 2 = Illegal Address, 3 = Illegal Data, 4 = Slave Error } } - if (sizeof(buffer) == len) { break; } } AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, len); - if (len < 5) { return 8; } // 8 = Not enough data - if (len != buffer[2] + 5) { return 9; } // 9 = Unexpected result + if (len < 7) { return 7; } // 7 = Not enough data + if (len != buffer[2] + 5) { return 8; } // 8 = Unexpected result uint16_t crc = (buffer[len -2] << 8) | buffer[len -1]; - if (Pzem2ModbusCalculateCRC(buffer, len -3) == crc) { - float energy = 0; - if (0x10 == buffer[2]) { // PZEM-003,017 - pzem2_type = PZEM2_TYPES_003_017; - energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 65535.x V - energy_current = (float)((buffer[5] << 8) + buffer[6]); // 65535.xx A - energy_power = (float)((uint32_t)buffer[9] << 24 + (uint32_t)buffer[10] << 16 + (uint32_t)buffer[7] << 8 + buffer[8]); // 65535 W - energy = (float)((uint32_t)buffer[13] << 24 + (uint32_t)buffer[14] << 16 + (uint32_t)buffer[11] << 8 + buffer[12]); // 65535 Wh - if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any - energy_kWhtoday += (energy - energy_start) * 100; - energy_start = energy; - EnergyUpdateToday(); - } - else if (0x14 == buffer[2]) { // PZEM-014,016 - pzem2_type = PZEM2_TYPES_014_016; - energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 65535.x V - energy_current = (float)((uint32_t)buffer[7] << 24 + (uint32_t)buffer[8] << 16 + (uint32_t)buffer[5] << 8 + buffer[6]); // 65535.xx A - energy_power = (float)((uint32_t)buffer[11] << 24 + (uint32_t)buffer[12] << 16 + (uint32_t)buffer[9] << 8 + buffer[10]); // 65535 W - energy_frequency = (float)((buffer[13] << 8) + buffer[14]) / 10.0; // 50.0 Hz - energy = (float)((uint32_t)buffer[15] << 24 + (uint32_t)buffer[16] << 16 + (uint32_t)buffer[13] << 8 + buffer[14]); // 65535 Wh - if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any - energy_kWhtoday += (energy - energy_start) * 100; - energy_start = energy; - EnergyUpdateToday(); - } - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Pzem2 crc error")); - } + if (Pzem2ModbusCalculateCRC(buffer, len -3) != crc) { return 9; } // 9 = crc error return 0; // 0 = No error } @@ -152,11 +120,56 @@ uint8_t Pzem2ModbusReceive() uint8_t pzem2_sendRetry = 0; -void Pzem2EverySecond() +void Pzem2Every200ms() { bool data_ready = Pzem2ModbusReceiveReady(); - if (data_ready) { Pzem2ModbusReceive(); } + if (data_ready) { + uint8_t buffer[26]; + uint8_t error = Pzem2ModbusReceive(buffer, pzem2_type); + if (error) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PZEM2 response error %d"), error); + AddLog(LOG_LEVEL_DEBUG); +// if (9 == error) { + if (PZEM2_TYPES_014_016 == pzem2_type) { + pzem2_type = PZEM2_TYPES_003_017; + } else { + pzem2_type = PZEM2_TYPES_014_016; + } +// } + } else { + float energy = 0; + + if (PZEM2_TYPES_003_017 == pzem2_type) { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + // FE 04 10 27 10 00 64 03 E8 00 00 00 00 00 00 00 00 00 00 HH LL = PZEM-017 + // Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc-- + energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V + energy_current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A + energy_power = (float)((uint32_t)buffer[9] << 24 + (uint32_t)buffer[10] << 16 + (uint32_t)buffer[7] << 8 + buffer[8]) / 10.0; // 429496729.0 W + energy = (float)((uint32_t)buffer[13] << 24 + (uint32_t)buffer[14] << 16 + (uint32_t)buffer[11] << 8 + buffer[12]); // 4294967295 Wh + if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any + energy_kWhtoday += (energy - energy_start) * 100; + energy_start = energy; + EnergyUpdateToday(); + } + else if (PZEM2_TYPES_014_016 == pzem2_type) { // PZEM-014,016 + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + // FE 04 14 08 98 03 E8 00 00 08 98 00 00 00 00 00 00 01 F4 00 64 00 00 HH LL = PZEM-014 + // Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc-- + energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V + energy_current = (float)((uint32_t)buffer[7] << 24 + (uint32_t)buffer[8] << 16 + (uint32_t)buffer[5] << 8 + buffer[6]) / 1000.0; // 4294967.000 A + energy_power = (float)((uint32_t)buffer[11] << 24 + (uint32_t)buffer[12] << 16 + (uint32_t)buffer[9] << 8 + buffer[10]) / 10.0; // 429496729.0 W + energy_frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz + energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00 + energy = (float)((uint32_t)buffer[15] << 24 + (uint32_t)buffer[16] << 16 + (uint32_t)buffer[13] << 8 + buffer[14]); // 4294967295 Wh + if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any + energy_kWhtoday += (energy - energy_start) * 100; + energy_start = energy; + EnergyUpdateToday(); + } + } + } if (0 == pzem2_sendRetry || data_ready) { pzem2_sendRetry = 5; @@ -203,8 +216,8 @@ int Xnrg05(byte function) case FUNC_INIT: Pzem2SnsInit(); break; - case FUNC_EVERY_SECOND: - Pzem2EverySecond(); + case FUNC_EVERY_200_MSECOND: + Pzem2Every200ms(); break; } } diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino index c22bc28cb..e5cc64418 100644 --- a/sonoff/xsns_23_sdm120.ino +++ b/sonoff/xsns_23_sdm120.ino @@ -246,7 +246,7 @@ void SDM120Show(boolean json) dtostrfd(sdm120_apparent_power, Settings.flag2.wattage_resolution, apparent_power); dtostrfd(sdm120_reactive_power, Settings.flag2.wattage_resolution, reactive_power); dtostrfd(sdm120_power_factor, 2, power_factor); - dtostrfd(sdm120_frequency, 2, frequency); + dtostrfd(sdm120_frequency, Settings.flag2.frequency_resolution, frequency); dtostrfd(sdm120_energy_total, Settings.flag2.energy_resolution, energy_total); if (json) { From b5d7f75647ab656bca132ae8986ad520c30eaf8e Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 8 Sep 2018 08:49:08 +0200 Subject: [PATCH 0079/2222] Fix setting and getting color temperature for Philips Hue emulation - Improve setting and getting color temperature for Philips Hue emulation - Clamp Philips Hue API values - Turn off white LEDs when setting hue+saturation --- sonoff/xdrv_04_light.ino | 26 ++++++++++++++++---------- sonoff/xplg_wemohue.ino | 33 +++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 209fe467a..93c2c522c 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -557,8 +557,8 @@ void LightState(uint8_t append) if (light_subtype > LST_SINGLE) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor)); // Add status for HSB - LightGetHsb(&hsb[0],&hsb[1],&hsb[2]); - // Scale these percentages up to the numbers expected byt he client + LightGetHsb(&hsb[0],&hsb[1],&hsb[2], false); + // Scale these percentages up to the numbers expected by the client h = round(hsb[0] * 360); s = round(hsb[1] * 100); b = round(hsb[2] * 100); @@ -911,13 +911,15 @@ void LightHsbToRgb() 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); + light_current_color[3] = 0; + light_current_color[4] = 0; } /********************************************************************************************/ -void LightGetHsb(float *hue, float *sat, float *bri) +void LightGetHsb(float *hue, float *sat, float *bri, bool gotct) { - if (light_subtype > LST_COLDWARM) { + if (light_subtype > LST_COLDWARM && !gotct) { LightRgbToHsb(); *hue = light_hue; *sat = light_saturation; @@ -925,16 +927,19 @@ void LightGetHsb(float *hue, float *sat, float *bri) } else { *hue = 0; *sat = 0; -// *bri = (2.54f * (float)Settings.light_dimmer); *bri = (0.01f * (float)Settings.light_dimmer); } } -void LightSetHsb(float hue, float sat, float bri, uint16_t ct) +void LightSetHsb(float hue, float sat, float bri, uint16_t ct, bool gotct) { if (light_subtype > LST_COLDWARM) { - if ((LST_RGBWC == light_subtype) && (ct > 0)) { - LightSetColorTemp(ct); + if ((LST_RGBWC == light_subtype) && (gotct)) { + uint8_t tmp = (uint8_t)(bri * 100); + Settings.light_dimmer = tmp; + if (ct > 0) { + LightSetColorTemp(ct); + } } else { light_hue = hue; light_saturation = sat; @@ -1114,7 +1119,7 @@ boolean LightCommand() } else { // Command with only 1 parameter, Hue (0360) ? (HSB[0] % 360) : HSB[0] ) /360.0, ( (HSB[1]>100) ? (HSB[1] % 100) : HSB[1] ) /100.0, ( (HSB[2]>100) ? (HSB[2] % 100) : HSB[2] ) /100.0, - 0); + 0, + false); } } else { LightState(0); diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 93912bc76..f0b20ef59 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -17,6 +17,9 @@ along with this program. If not, see . */ +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) + #if defined(USE_WEBSERVER) && defined(USE_EMULATION) /*********************************************************************************************\ * Belkin WeMo and Philips Hue bridge emulation @@ -462,10 +465,10 @@ const char HUE_LIGHTS_STATUS_JSON[] PROGMEM = "\"hue\":{h}," "\"sat\":{s}," "\"xy\":[0.5, 0.5]," - "\"ct\":500," + "\"ct\":{t}," "\"alert\":\"none\"," "\"effect\":\"none\"," - "\"colormode\":\"hs\"," + "\"colormode\":\"{m}\"," "\"reachable\":true}"; const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = ",\"type\":\"Extended color light\"," @@ -559,20 +562,26 @@ void HueConfig(String *path) WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } +bool g_gotct = false; + void HueLightStatus1(byte device, String *response) { float hue = 0; float sat = 0; float bri = 0; + uint16_t ct = 500; if (light_type) { - LightGetHsb(&hue, &sat, &bri); + LightGetHsb(&hue, &sat, &bri, g_gotct); + ct = LightGetColorTemp(); } *response += FPSTR(HUE_LIGHTS_STATUS_JSON); response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); response->replace("{h}", String((uint16_t)(65535.0f * hue))); response->replace("{s}", String((uint8_t)(254.0f * sat))); response->replace("{b}", String((uint8_t)(254.0f * bri))); + response->replace("{t}", String(ct)); + response->replace("{m}", g_gotct?"ct":"hs"); } void HueLightStatus2(byte device, String *response) @@ -678,11 +687,13 @@ void HueLights(String *path) } if (light_type) { - LightGetHsb(&hue, &sat, &bri); + LightGetHsb(&hue, &sat, &bri, g_gotct); } - if (hue_json.containsKey("bri")) { + if (hue_json.containsKey("bri")) { // Brightness is a scale from 1 (the minimum the light is capable of) to 254 (the maximum). Note: a brightness of 1 is not off. tmp = hue_json["bri"]; + tmp = max(tmp, 1); + tmp = min(tmp, 254); bri = (float)tmp / 254.0f; if (resp) { response += ","; @@ -694,7 +705,7 @@ void HueLights(String *path) resp = true; change = true; } - if (hue_json.containsKey("hue")) { + if (hue_json.containsKey("hue")) { // The hue value is a wrapping value between 0 and 65535. Both 0 and 65535 are red, 25500 is green and 46920 is blue. tmp = hue_json["hue"]; hue = (float)tmp / 65535.0f; if (resp) { @@ -704,11 +715,14 @@ void HueLights(String *path) response.replace("{id", String(device)); response.replace("{cm", "hue"); response.replace("{re", String(tmp)); + g_gotct = false; resp = true; change = true; } - if (hue_json.containsKey("sat")) { + if (hue_json.containsKey("sat")) { // Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white). tmp = hue_json["sat"]; + tmp = max(tmp, 0); + tmp = min(tmp, 254); sat = (float)tmp / 254.0f; if (resp) { response += ","; @@ -717,6 +731,8 @@ void HueLights(String *path) response.replace("{id", String(device)); response.replace("{cm", "sat"); response.replace("{re", String(tmp)); + g_gotct = false; + resp = true; change = true; } if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm) @@ -728,11 +744,12 @@ void HueLights(String *path) response.replace("{id", String(device)); response.replace("{cm", "ct"); response.replace("{re", String(ct)); + g_gotct = true; change = true; } if (change) { if (light_type) { - LightSetHsb(hue, sat, bri, ct); + LightSetHsb(hue, sat, bri, ct, g_gotct); } change = false; } From 7cd92248196550964de87ada6bf86a2b742b5b3d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 8 Sep 2018 17:18:31 +0200 Subject: [PATCH 0080/2222] 6.2.1.3 - Change drop down list 6.2.1.3 20180907 * Change web Configure Module GPIO drop down list order for better readability * Fix showing Period Power in energy threshold messages * Fix ButtonRetain to not use default topic for clearing retain messages (#3737) --- sonoff/_changelog.ino | 8 ++- sonoff/sonoff.ino | 2 +- sonoff/sonoff_template.h | 108 ++++++++++++++++++++++++++++++++++- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_mqtt.ino | 6 +- sonoff/xdrv_02_webserver.ino | 8 +-- sonoff/xdrv_03_energy.ino | 3 + sonoff/xdrv_10_rules.ino | 2 +- 8 files changed, 125 insertions(+), 14 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 82d12f28e..c62144f8d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,8 +1,14 @@ -/* 6.2.1.2 20180906 +/* 6.2.1.3 20180907 + * Change web Configure Module GPIO drop down list order for better readability + * Fix showing Period Power in energy threshold messages + * Fix ButtonRetain to not use default topic for clearing retain messages (#3737) + * + * 6.2.1.2 20180906 * Fix KNX PA exception. Regression from 6.2.1 buffer overflow caused by subStr() (#3700, #3710) * Add command SetOption52 to control display of optional time offset from UTC in JSON messages (#3629, #3711) * Add experimental support for PZEM-003,014,016,017 Energy monitoring (#3694) * Add basic support for MP3 player using DFRobot RB-DFR-562 (#3723) + * Fix setting and getting color temperature for Philips Hue emulation (#3733) * * 6.2.1.1 20180905 * Rewrite energy monitoring using energy sensor driver modules diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 6b2e8422b..a1ab907ab 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -134,7 +134,7 @@ int ota_state_flag = 0; // OTA state flag int ota_result = 0; // OTA result int restart_flag = 0; // Sonoff restart flag int wifi_state_flag = WIFI_RESTART; // Wifi state flag -int tele_period = 0; // Tele period timer +int tele_period = 1; // Tele period timer int blinks = 201; // Number of LED blinks uint32_t uptime = 0; // Counting every second until 4294967295 = 130 year uint32_t global_update = 0; // Timestamp of last global temperature and humidity update diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 2ab43286d..23019ff10 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -21,6 +21,8 @@ #define _SONOFF_TEMPLATE_H_ // User selectable GPIO functionality +// ATTENTION: Only add at the end of this list just before GPIO_SENSOR_END +// Then add the same name(s) in a nice location in array kGpioNiceList enum UserSelectablePins { GPIO_NONE, // Not used GPIO_DHT11, // DHT11 @@ -244,7 +246,111 @@ typedef struct MYTMPLT { myio gp; } mytmplt; -const uint8_t kNiceList[MAXMODULE] PROGMEM = { +const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = { + GPIO_NONE, // Not used + GPIO_KEY1, // Buttons + GPIO_KEY1_NP, + GPIO_KEY2, + GPIO_KEY2_NP, + GPIO_KEY3, + GPIO_KEY3_NP, + GPIO_KEY4, + GPIO_KEY4_NP, + GPIO_SWT1, // User connected external switches + GPIO_SWT1_NP, + GPIO_SWT2, + GPIO_SWT2_NP, + GPIO_SWT3, + GPIO_SWT3_NP, + GPIO_SWT4, + GPIO_SWT4_NP, + GPIO_SWT5, + GPIO_SWT5_NP, + GPIO_SWT6, + GPIO_SWT6_NP, + GPIO_SWT7, + GPIO_SWT7_NP, + GPIO_SWT8, + GPIO_SWT8_NP, + GPIO_REL1, // Relays + GPIO_REL1_INV, + GPIO_REL2, + GPIO_REL2_INV, + GPIO_REL3, + GPIO_REL3_INV, + GPIO_REL4, + GPIO_REL4_INV, + GPIO_REL5, + GPIO_REL5_INV, + GPIO_REL6, + GPIO_REL6_INV, + GPIO_REL7, + GPIO_REL7_INV, + GPIO_REL8, + GPIO_REL8_INV, + GPIO_LED1, // Leds + GPIO_LED1_INV, + GPIO_LED2, + GPIO_LED2_INV, + GPIO_LED3, + GPIO_LED3_INV, + GPIO_LED4, + GPIO_LED4_INV, + GPIO_PWM1, // RGB Red or C Cold White + GPIO_PWM1_INV, + GPIO_PWM2, // RGB Green or CW Warm White + GPIO_PWM2_INV, + GPIO_PWM3, // RGB Blue + GPIO_PWM3_INV, + GPIO_PWM4, // RGBW (Cold) White + GPIO_PWM4_INV, + GPIO_PWM5, // RGBCW Warm White + GPIO_PWM5_INV, + GPIO_CNTR1, // Counters + GPIO_CNTR1_NP, + GPIO_CNTR2, + GPIO_CNTR2_NP, + GPIO_CNTR3, + GPIO_CNTR3_NP, + GPIO_CNTR4, + GPIO_CNTR4_NP, + GPIO_I2C_SCL, // I2C SCL + GPIO_I2C_SDA, // I2C SDA + GPIO_SPI_CS, // SPI Chip Select + GPIO_SPI_DC, // SPI Data Direction + GPIO_BACKLIGHT, // Display backlight control + GPIO_DHT11, // DHT11 + GPIO_DHT22, // DHT21, DHT22, AM2301, AM2302, AM2321 + GPIO_SI7021, // iTead SI7021 + GPIO_DSB, // Single wire DS18B20 or DS18S20 + GPIO_WS2812, // WS2812 Led string + GPIO_IRSEND, // IR remote + GPIO_IRRECV, // IR receiver + GPIO_SR04_TRIG, // SR04 Trigger pin + GPIO_SR04_ECHO, // SR04 Echo pin + GPIO_TM16CLK, // TM1638 Clock + GPIO_TM16DIO, // TM1638 Data I/O + GPIO_TM16STB, // TM1638 Strobe + GPIO_SBR_TX, // Serial Bridge Serial interface + GPIO_SBR_RX, // Serial Bridge Serial interface + GPIO_MHZ_TXD, // MH-Z19 Serial interface + GPIO_MHZ_RXD, // MH-Z19 Serial interface + GPIO_SAIR_TX, // SenseAir Serial interface + GPIO_SAIR_RX, // SenseAir Serial interface + GPIO_SDS0X1, // Nova Fitness SDS011 Serial interface + GPIO_PZEM_TX, // PZEM004T Serial interface + GPIO_PZEM_RX, // PZEM004T Serial interface + GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface + GPIO_PZEM2_RX, // PZEM-003,014,016,017 Serial interface + GPIO_SDM120_TX, // SDM120 Serial interface + GPIO_SDM120_RX, // SDM120 Serial interface + GPIO_SDM630_TX, // SDM630 Serial interface + GPIO_SDM630_RX, // SDM630 Serial interface + GPIO_PMS5003, // Plantower PMS5003 Serial interface + GPIO_MP3_DFR562 // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface +}; + +const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { SONOFF_BASIC, SONOFF_RF, SONOFF_TH, diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 178e0af68..f068473ab 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020102 +#define VERSION 0x06020103 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_01_mqtt.ino b/sonoff/xdrv_01_mqtt.ino index c47728df0..f3f33d693 100644 --- a/sonoff/xdrv_01_mqtt.ino +++ b/sonoff/xdrv_01_mqtt.ino @@ -380,9 +380,7 @@ void MqttConnected() MqttPublishPowerState(i); if (SONOFF_IFAN02 == Settings.module) { break; } // Only report status of light relay } - if (Settings.tele_period) { - tele_period = Settings.tele_period -9; - } + if (Settings.tele_period) { tele_period = Settings.tele_period -9; } // Enable TelePeriod in 9 seconds rules_flag.system_boot = 1; XdrvCall(FUNC_MQTT_INIT); } @@ -718,7 +716,6 @@ bool MqttCommand() } else if (CMND_BUTTONRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { - strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic)); if (!payload) { for(i = 1; i <= MAX_KEYS; i++) { SendKey(0, i, 9); // Clear MQTT retain in broker @@ -730,7 +727,6 @@ bool MqttCommand() } else if (CMND_SWITCHRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { - strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic)); if (!payload) { for(i = 1; i <= MAX_SWITCHES; i++) { SendKey(1, i, 9); // Clear MQTT retain in broker diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index 4059459c5..4398a9eb0 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -768,7 +768,7 @@ void HandleModuleConfiguration() page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE)); page += FPSTR(HTTP_SCRIPT_MODULE1); for (byte i = 0; i < MAXMODULE; i++) { - midx = pgm_read_byte(kNiceList + i); + midx = pgm_read_byte(kModuleNiceList + i); snprintf_P(stemp, sizeof(stemp), kModules[midx].name); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, midx, midx +1, stemp); page += mqtt_data; @@ -779,10 +779,10 @@ void HandleModuleConfiguration() mytmplt cmodule; memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); - for (byte j = 0; j < GPIO_SENSOR_END; j++) { - if (!GetUsedInModule(j, cmodule.gp.io)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, j, j, GetTextIndexed(stemp, sizeof(stemp), j, kSensorNames)); + midx = pgm_read_byte(kGpioNiceList + j); + if (!GetUsedInModule(midx, cmodule.gp.io)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, midx, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames)); page += mqtt_data; } } diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 081b52d83..ac26a18da 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -304,7 +304,10 @@ void EnergyMqttShow() { // {"Time":"2017-12-16T11:48:55","ENERGY":{"Total":0.212,"Yesterday":0.000,"Today":0.014,"Period":2.0,"Power":22.0,"Factor":1.00,"Voltage":213.6,"Current":0.100}} snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + int tele_period_save = tele_period; + tele_period = 2; EnergyShow(1); + tele_period = tele_period_save; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); energy_power_delta = 0; diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index df27cb4cd..930bde7d5 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -426,7 +426,7 @@ void RulesEvery100ms() { if (Settings.rule_enabled) { // Any rule enabled mqtt_data[0] = '\0'; - uint16_t tele_period_save = tele_period; + int tele_period_save = tele_period; tele_period = 2; // Do not allow HA updates during next function call XsnsNextCall(FUNC_JSON_APPEND); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} tele_period = tele_period_save; From b96c0d7773477b758ec2ce0818f3b8901b7312d6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 8 Sep 2018 18:17:36 +0200 Subject: [PATCH 0081/2222] Fix Novafitnes GPIO selection Fix Novafitnes GPIO selection --- sonoff/sonoff_template.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index fd2806fa9..1ab62ae63 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -94,8 +94,7 @@ enum UserSelectablePins { GPIO_SPI_DC, // SPI Data Direction GPIO_BACKLIGHT, // Display backlight control GPIO_PMS5003, // Plantower PMS5003 Serial interface - GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface - GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface + GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface GPIO_SBR_TX, // Serial Bridge Serial interface GPIO_SBR_RX, // Serial Bridge Serial interface GPIO_SR04_TRIG, // SR04 Trigger pin @@ -126,6 +125,7 @@ enum UserSelectablePins { GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface GPIO_PZEM2_RX, // PZEM-003,014,016,017 Serial interface GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player + GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -167,8 +167,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|" D_SENSOR_SAIR_TX "|" D_SENSOR_SAIR_RX "|" D_SENSOR_SPI_CS "|" D_SENSOR_SPI_DC "|" D_SENSOR_BACKLIGHT "|" - D_SENSOR_PMS5003 "|" - D_SENSOR_SDS0X1_TX "|" D_SENSOR_SDS0X1_RX "|" + D_SENSOR_PMS5003 "|" D_SENSOR_SDS0X1_RX "|" D_SENSOR_SBR_TX "|" D_SENSOR_SBR_RX "|" D_SENSOR_SR04_TRIG "|" D_SENSOR_SR04_ECHO "|" D_SENSOR_SDM120_TX "|" D_SENSOR_SDM120_RX "|" @@ -178,7 +177,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_BUTTON "1n|" D_SENSOR_BUTTON "2n|" D_SENSOR_BUTTON "3n|" D_SENSOR_BUTTON "4n|" D_SENSOR_COUNTER "1n|" D_SENSOR_COUNTER "2n|" D_SENSOR_COUNTER "3n|" D_SENSOR_COUNTER "4n|" D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|" - D_SENSOR_DFR562; + D_SENSOR_DFR562 "|" D_SENSOR_SDS0X1_TX; /********************************************************************************************/ @@ -339,7 +338,8 @@ const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = { GPIO_MHZ_RXD, // MH-Z19 Serial interface GPIO_SAIR_TX, // SenseAir Serial interface GPIO_SAIR_RX, // SenseAir Serial interface - GPIO_SDS0X1, // Nova Fitness SDS011 Serial interface + GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface + GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface GPIO_PZEM_TX, // PZEM004T Serial interface GPIO_PZEM_RX, // PZEM004T Serial interface GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface From 3b029797b6534bdcd8c78be42b9e0b99cf7eed53 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 8 Sep 2018 18:25:06 +0200 Subject: [PATCH 0082/2222] Add sleep to Nova Fitness SDS01X Add sleep to Nova Fitness SDS01X sensor (#2841, #3724) --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index c62144f8d..230a541b7 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Change web Configure Module GPIO drop down list order for better readability * Fix showing Period Power in energy threshold messages * Fix ButtonRetain to not use default topic for clearing retain messages (#3737) + * Add sleep to Nova Fitness SDS01X sensor (#2841, #3724) * * 6.2.1.2 20180906 * Fix KNX PA exception. Regression from 6.2.1 buffer overflow caused by subStr() (#3700, #3710) From 56920ad8263c7b50f5811a29b057807af483417a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 8 Sep 2018 18:33:56 +0200 Subject: [PATCH 0083/2222] Adjust list box width Adjust GPIO drop down list box width --- sonoff/xdrv_02_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index 4398a9eb0..55eb0f41b 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -805,7 +805,7 @@ void HandleModuleConfiguration() for (byte i = 0; i < MAX_GPIO_PIN; i++) { if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s " D_GPIO "%d %s"), + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s " D_GPIO "%d %s"), (WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "ESP8285" :(10==i)? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); page += mqtt_data; } From 4c41ea446154e780610bc1b96ec0f08803893a6b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 9 Sep 2018 14:31:40 +0200 Subject: [PATCH 0084/2222] Houskeeping --- sonoff/sonoff.ino | 3 --- sonoff/support.ino | 12 ++++++++++++ sonoff/xdrv_02_webserver.ino | 2 +- tools/decode-status.py | 6 +++--- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index a1ab907ab..52cdb68ba 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -849,10 +849,8 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) else if ((CMND_GPIO == command_code) && (index < MAX_GPIO_PIN)) { mytmplt cmodule; memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); -// if ((GPIO_USER == cmodule.gp.io[index]) && (payload >= 0) && (payload < GPIO_SENSOR_END)) { if ((GPIO_USER == ValidGPIO(index, 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]) && (Settings.my_gp.io[i] == payload)) { if ((GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) && (Settings.my_gp.io[i] == payload)) { Settings.my_gp.io[i] = 0; } @@ -862,7 +860,6 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); for (byte i = 0; i < MAX_GPIO_PIN; i++) { -// if (GPIO_USER == cmodule.gp.io[i]) { if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { if (jsflg) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); jsflg = 1; diff --git a/sonoff/support.ino b/sonoff/support.ino index 291f2069d..af93fa148 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -936,8 +936,20 @@ void GetFeatures() #ifdef USE_DISPLAY_SH1106 feature_drv2 |= 0x00001000; // xdsp_06_sh1106.ino #endif +#ifdef USE_MP3_PLAYER + feature_drv2 |= 0x00002000; // xdrv_14_mp3.ino +#endif +#ifdef NO_EXTRA_4K_HEAP + feature_drv2 |= 0x00800000; // sonoff_post.h +#endif +#ifdef VTABLES_IN_IRAM + feature_drv2 |= 0x01000000; // platformio.ini +#endif +#ifdef VTABLES_IN_DRAM + feature_drv2 |= 0x02000000; // platformio.ini +#endif #ifdef VTABLES_IN_FLASH feature_drv2 |= 0x04000000; // platformio.ini #endif diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index 55eb0f41b..6cadb952f 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -1193,7 +1193,7 @@ void HandleSaveSettings() if (Settings.last_module != new_module) { Settings.my_gp.io[i] = 0; } else { - if (GPIO_USER == cmodule.gp.io[i]) { + if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), i); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); diff --git a/tools/decode-status.py b/tools/decode-status.py index b26be9df0..154b6e719 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -108,10 +108,10 @@ a_features = [[ "USE_CONFIG_OVERRIDE","BE_MINIMAL","USE_SENSORS","USE_CLASSIC", "USE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD", "USE_DISPLAY_SSD1306","USE_DISPLAY_MATRIX","USE_DISPLAY_ILI9341","USE_DISPLAY_EPAPER", - "USE_DISPLAY_SH1106","","","", + "USE_DISPLAY_SH1106","USE_MP3_PLAYER","","", "","","","", - "","","","", - "","","VTABLES_IN_FLASH","PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH", + "","","","NO_EXTRA_4K_HEAP", + "VTABLES_IN_IRAM","VTABLES_IN_DRAM","VTABLES_IN_FLASH","PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH", "PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY","PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH","DEBUG_THEO","USE_DEBUG_DRIVER" ],[ "","USE_ADC_VCC","USE_ENERGY_SENSOR","USE_PZEM004T", From 550c7d256f3d63f24f9b6613bc0e2f5d311fbf89 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 9 Sep 2018 14:58:50 +0200 Subject: [PATCH 0085/2222] Add option -mtarget-align Add option -mtarget-align to solve linux compiled un-aligned binaries (#3678) --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index 4cda52b6f..d333fd187 100644 --- a/platformio.ini +++ b/platformio.ini @@ -61,6 +61,7 @@ build_unflags = -Wall build_flags = -Wl,-Tesp8266.flash.1m0.ld + -mtarget-align ; -DUSE_CONFIG_OVERRIDE ; lwIP 1.4 (Default) ; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH From cc23deac00908118000a7851df88c3edc695bf06 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 10 Sep 2018 11:37:16 +0200 Subject: [PATCH 0086/2222] use SDS0X1 working period command --- sonoff/xsns_20_novasds.ino | 119 ++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 62 deletions(-) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 851326f3f..607bcc545 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -27,26 +27,65 @@ #include +#ifndef WORKING_PERIOD + #define WORKING_PERIOD 5 +#endif + TasmotaSerial *NovaSdsSerial; uint8_t novasds_type = 1; uint8_t novasds_valid = 0; -uint8_t novasds_running = 1; -uint8_t novasds_read_tick = 30; -uint8_t novasds_wakup_tick = 179; -uint8_t novasds_ticker = 0; + +uint8_t novasds_workperiod[19] = {0xAA, 0xB4, 0x08, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0C, 0xAB}; //5 minutes +uint8_t novasds_setquerymode[19] = {0xAA, 0xB4, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0xAB}; //query mode +uint8_t novasds_querydata[19] = {0xAA, 0xB4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0xAB}; //query DATA + struct sds011data { uint16_t pm100; uint16_t pm25; } novasds_data; +//Put sensor to sleep +void NovaSdsSetWorkPeriod() +{ -bool NovaSdsReadData(bool publish) + while (NovaSdsSerial->available() > 0) { + NovaSdsSerial->read(); + } + + novasds_workperiod[4] = WORKING_PERIOD; + novasds_workperiod[17] = ((novasds_workperiod[2] + novasds_workperiod[3] + novasds_workperiod[4] + novasds_workperiod[15] + novasds_workperiod[16]) & 0xFF); //checksum + + + NovaSdsSerial->write(novasds_workperiod, sizeof(novasds_workperiod)); + + NovaSdsSerial->flush(); + + while (NovaSdsSerial->available() > 0) { + NovaSdsSerial->read(); + } + + NovaSdsSerial->write(novasds_setquerymode, sizeof(novasds_setquerymode)); + + NovaSdsSerial->flush(); + + while (NovaSdsSerial->available() > 0) { + NovaSdsSerial->read(); + } +} + + + +bool NovaSdsReadData() { if (! NovaSdsSerial->available()) return false; - while ((NovaSdsSerial->peek() != 0xAA) && NovaSdsSerial->available()) { + NovaSdsSerial->write(novasds_querydata, sizeof(novasds_querydata)); + + NovaSdsSerial->flush(); + + while ((NovaSdsSerial->peek() != 0xAA) && NovaSdsSerial->available()) { NovaSdsSerial->read(); } @@ -56,9 +95,7 @@ bool NovaSdsReadData(bool publish) NovaSdsSerial->flush(); AddLogSerial(LOG_LEVEL_DEBUG_MORE, d, 8); - if (!publish){ - return false; - } + if (d[7] == ((d[1] + d[2] + d[3] + d[4] + d[5] + d[6]) & 0xFF)) { novasds_data.pm25 = (d[1] + 256 * d[2]); novasds_data.pm100 = (d[3] + 256 * d[4]); @@ -66,6 +103,9 @@ bool NovaSdsReadData(bool publish) AddLog_P(LOG_LEVEL_DEBUG, PSTR("SDS: " D_CHECKSUM_FAILURE)); return false; } + + novasds_valid = 10; + return true; } @@ -73,35 +113,12 @@ bool NovaSdsReadData(bool publish) void NovaSdsSecond() // Every second { - if (novasds_ticker < novasds_read_tick) { - // wake up the sensor and wait read ticks to stabalize the sensor - if (!novasds_running) { - NovaSdsStart(); - novasds_running = 1; - } - - // drain the serial without publishing data - NovaSdsReadData(false); - novasds_ticker++; - - } else if (novasds_ticker == novasds_read_tick) { - - // try to take a single stable reading and sleep the sensor - if (NovaSdsReadData(true)) { - novasds_valid = 1; - NovaSdsStop(); - novasds_running = 0; - novasds_ticker++; - } else { - novasds_valid = 0; - } - - } else if (novasds_ticker >= novasds_wakup_tick) { - // reset the counter - novasds_ticker = 0; + if (NovaSdsReadData()) { + novasds_valid = 10; } else { - // sensor is sleeping keep waiting - novasds_ticker++; + if (novasds_valid) { + novasds_valid--; + } } } @@ -110,37 +127,15 @@ void NovaSdsSecond() // Every second void NovaSdsInit() { novasds_type = 0; - if (pin[GPIO_SDS0X1_RX] < 99 && pin[GPIO_SDS0X1_TX] < 99) { + if ((pin[GPIO_SDS0X1_RX] < 99) && (pin[GPIO_SDS0X1_TX] < 99)) { NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1_RX], pin[GPIO_SDS0X1_TX], 1); - if (NovaSdsSerial->begin(9600)) { - if (NovaSdsSerial->hardwareSerial()) { - ClaimSerial(); - } + if (NovaSdsSerial->hardwareSerial()) { ClaimSerial(); } novasds_type = 1; } - } -} -void NovaSdsStart() -{ - AddLog_P(LOG_LEVEL_DEBUG, "SDS: start"); - const uint8_t novasds_start_cmd[] = {0xAA, 0xB4, 0x06, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x06, 0xAB}; - NovaSdsSerial->write(novasds_start_cmd, sizeof(novasds_start_cmd)); - NovaSdsSerial->flush(); -} - -void NovaSdsStop() -{ - AddLog_P(LOG_LEVEL_DEBUG, "SDS: stop"); - const uint8_t novasds_stop_cmd[] = {0xAA, 0xB4, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x05, 0xAB}; - NovaSdsSerial->write(novasds_stop_cmd, sizeof(novasds_stop_cmd)); - NovaSdsSerial->flush(); - // drain any old data - while (NovaSdsSerial->available()) { - NovaSdsSerial->read(); - } + NovaSdsSetWorkPeriod(); } #ifdef USE_WEBSERVER From 0f25925357554efa51fe40346196fe8e46c2b2e8 Mon Sep 17 00:00:00 2001 From: edelstahlratte <17500289+edelstahlratte@users.noreply.github.com> Date: Mon, 10 Sep 2018 11:50:54 +0200 Subject: [PATCH 0087/2222] Add SDS0X1 working period --- sonoff/user_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/user_config.h b/sonoff/user_config.h index d46a295d7..357fe5fab 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -335,6 +335,7 @@ #define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) #define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) + #define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) //#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) #define SDM120_SPEED 9600 // SDM120-Modbus RS485 serial speed (default: 2400 baud) From ef6d5bb340c6d26509414c450d4afce71b4a45b3 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 10 Sep 2018 12:11:28 +0200 Subject: [PATCH 0088/2222] cosmetics --- sonoff/xsns_20_novasds.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 607bcc545..02614c912 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -46,7 +46,6 @@ struct sds011data { uint16_t pm25; } novasds_data; -//Put sensor to sleep void NovaSdsSetWorkPeriod() { @@ -57,7 +56,6 @@ void NovaSdsSetWorkPeriod() novasds_workperiod[4] = WORKING_PERIOD; novasds_workperiod[17] = ((novasds_workperiod[2] + novasds_workperiod[3] + novasds_workperiod[4] + novasds_workperiod[15] + novasds_workperiod[16]) & 0xFF); //checksum - NovaSdsSerial->write(novasds_workperiod, sizeof(novasds_workperiod)); NovaSdsSerial->flush(); @@ -127,10 +125,12 @@ void NovaSdsSecond() // Every second void NovaSdsInit() { novasds_type = 0; - if ((pin[GPIO_SDS0X1_RX] < 99) && (pin[GPIO_SDS0X1_TX] < 99)) { + if (pin[GPIO_SDS0X1_RX] < 99 && pin[GPIO_SDS0X1_TX] < 99) { NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1_RX], pin[GPIO_SDS0X1_TX], 1); if (NovaSdsSerial->begin(9600)) { - if (NovaSdsSerial->hardwareSerial()) { ClaimSerial(); } + if (NovaSdsSerial->hardwareSerial()) { + ClaimSerial(); + } novasds_type = 1; } } From 804e74d0de0322eac9a466db6a57f3578c99b351 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 10 Sep 2018 12:22:00 +0200 Subject: [PATCH 0089/2222] cosmetics --- sonoff/xsns_20_novasds.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 02614c912..2bce13e2a 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -53,7 +53,7 @@ void NovaSdsSetWorkPeriod() NovaSdsSerial->read(); } - novasds_workperiod[4] = WORKING_PERIOD; + novasds_workperiod[4] = WORKING_PERIOD; novasds_workperiod[17] = ((novasds_workperiod[2] + novasds_workperiod[3] + novasds_workperiod[4] + novasds_workperiod[15] + novasds_workperiod[16]) & 0xFF); //checksum NovaSdsSerial->write(novasds_workperiod, sizeof(novasds_workperiod)); From dc3d699fd1436c245806bbe804e117a9c2ad7dba Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 10 Sep 2018 12:23:51 +0200 Subject: [PATCH 0090/2222] cosmetics --- sonoff/xsns_20_novasds.ino | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 2bce13e2a..b6bd4a2c0 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -60,17 +60,17 @@ void NovaSdsSetWorkPeriod() NovaSdsSerial->flush(); - while (NovaSdsSerial->available() > 0) { - NovaSdsSerial->read(); - } + while (NovaSdsSerial->available() > 0) { + NovaSdsSerial->read(); + } NovaSdsSerial->write(novasds_setquerymode, sizeof(novasds_setquerymode)); NovaSdsSerial->flush(); - while (NovaSdsSerial->available() > 0) { - NovaSdsSerial->read(); - } + while (NovaSdsSerial->available() > 0) { + NovaSdsSerial->read(); + } } From 047932a191ccc38c43d4ffb262b5695aaae903ee Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 10 Sep 2018 12:25:57 +0200 Subject: [PATCH 0091/2222] cosmetics --- sonoff/xsns_20_novasds.ino | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index b6bd4a2c0..46db2fb6a 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -57,15 +57,13 @@ void NovaSdsSetWorkPeriod() novasds_workperiod[17] = ((novasds_workperiod[2] + novasds_workperiod[3] + novasds_workperiod[4] + novasds_workperiod[15] + novasds_workperiod[16]) & 0xFF); //checksum NovaSdsSerial->write(novasds_workperiod, sizeof(novasds_workperiod)); - NovaSdsSerial->flush(); while (NovaSdsSerial->available() > 0) { NovaSdsSerial->read(); } - NovaSdsSerial->write(novasds_setquerymode, sizeof(novasds_setquerymode)); - + NovaSdsSerial->write(novasds_setquerymode, sizeof(novasds_setquerymode)); NovaSdsSerial->flush(); while (NovaSdsSerial->available() > 0) { @@ -80,10 +78,9 @@ bool NovaSdsReadData() if (! NovaSdsSerial->available()) return false; NovaSdsSerial->write(novasds_querydata, sizeof(novasds_querydata)); - NovaSdsSerial->flush(); - while ((NovaSdsSerial->peek() != 0xAA) && NovaSdsSerial->available()) { + while ((NovaSdsSerial->peek() != 0xAA) && NovaSdsSerial->available()) { NovaSdsSerial->read(); } From b9d1bb965ced0887af43467f747cef38da692209 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 10 Sep 2018 14:06:31 +0200 Subject: [PATCH 0092/2222] correct error --- sonoff/xsns_20_novasds.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 46db2fb6a..815041cab 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -129,10 +129,9 @@ void NovaSdsInit() ClaimSerial(); } novasds_type = 1; + NovaSdsSetWorkPeriod(); } } - - NovaSdsSetWorkPeriod(); } #ifdef USE_WEBSERVER From 6f4fefbd771008fe2ea9ce5adb2a1a34a744451e Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 10 Sep 2018 18:32:41 +0200 Subject: [PATCH 0093/2222] Fix potential buffer overun for EVENT --- sonoff/xsns_29_mcp230xx.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index d6683da44..058d6c25c 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -300,7 +300,7 @@ void MCP230xx_CheckForInterrupt(void) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); } if (int_event) { - char command[18]; + char command[19]; // Theoretical max = 'event MCPINT_D16=1' so 18 + 1 (for the \n) sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01)); ExecuteCommand(command, SRC_RULE); } From 786fd792b715607fc0752c1c2ffb6ce7f9492c27 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 10 Sep 2018 19:44:23 +0200 Subject: [PATCH 0094/2222] Fix tr-TR.h and uk-UK.h compiler errors --- sonoff/language/tr-TR.h | 2 ++ sonoff/language/uk-UK.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 1f11d4a01..086c236aa 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -476,6 +476,8 @@ #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" #define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 90cfb9f4a..19094d574 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -476,6 +476,8 @@ #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" #define D_SENSOR_SDS0X1 "SDS0X1" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" From 40b9e06b1e678497018d305910aa19150009d4c3 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 10 Sep 2018 18:04:21 -0300 Subject: [PATCH 0095/2222] Enable AD0 in sonoff-sensors.bin #3756 --- sonoff/sonoff_post.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 7504af3b4..8622d0818 100755 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -62,7 +62,10 @@ void KNX_CB_Action(message_t const &msg, void *arg); #ifdef USE_SENSORS -#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices +#ifdef USE_ADC_VCC +#undef USE_ADC_VCC +#endif +//#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices #define USE_DS18x20 // For more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) //#define USE_DS18x20_LEGACY // For more than one DS18x20 sensors with dynamic scan using library OneWire (+1k5 code) #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) From e4ebee738b437fcc101f80e2f8d7df119aea9f02 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 11 Sep 2018 10:49:13 +0200 Subject: [PATCH 0096/2222] Minor fixes Minor fixes --- sonoff/_changelog.ino | 3 ++- sonoff/xdrv_99_debug.ino | 3 +-- sonoff/xdsp_05_epaper.ino | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 230a541b7..d9044fcae 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,7 +2,8 @@ * Change web Configure Module GPIO drop down list order for better readability * Fix showing Period Power in energy threshold messages * Fix ButtonRetain to not use default topic for clearing retain messages (#3737) - * Add sleep to Nova Fitness SDS01X sensor (#2841, #3724) + * Add sleep to Nova Fitness SDS01X sensor (#2841, #3724, #3749) + * Add Analog input AD0 enabled to sonoff-sensors.bin (#3756, #3757) * * 6.2.1.2 20180906 * Fix KNX PA exception. Regression from 6.2.1 buffer overflow caused by subStr() (#3700, #3710) diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_99_debug.ino index 8a167511c..3cd2e69c5 100644 --- a/sonoff/xdrv_99_debug.ino +++ b/sonoff/xdrv_99_debug.ino @@ -182,6 +182,7 @@ void CpuLoadLoop() #if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) // All version before core 2.4.2 +// https://github.com/esp8266/Arduino/issues/2557 extern "C" { #include @@ -190,7 +191,6 @@ extern "C" { void DebugFreeMem() { -// https://github.com/esp8266/Arduino/issues/2557 register uint32_t *sp asm("a1"); // snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d, UnmodifiedStack %d (%s)"), @@ -213,7 +213,6 @@ extern "C" { void DebugFreeMem() { -// https://github.com/esp8266/Arduino/issues/2557 register uint32_t *sp asm("a1"); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), diff --git a/sonoff/xdsp_05_epaper.ino b/sonoff/xdsp_05_epaper.ino index 59a08584b..91eb747f2 100644 --- a/sonoff/xdsp_05_epaper.ino +++ b/sonoff/xdsp_05_epaper.ino @@ -188,7 +188,7 @@ boolean Xdsp05(byte function) if (FUNC_DISPLAY_INIT_DRIVER == function) { EpdInitDriver(); } - else if (XDSP_04 == Settings.display_model) { + else if (XDSP_05 == Settings.display_model) { if (!dsp_color) { dsp_color = COLORED; } From 702f44cf04467a389260b4189b8170fe64f91953 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 11 Sep 2018 14:10:51 -0300 Subject: [PATCH 0097/2222] Fixed Compilation Bug #3766 --- sonoff/xnrg_05_pzem2.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xnrg_05_pzem2.ino b/sonoff/xnrg_05_pzem2.ino index 7f9a4f8ba..b7e1eab42 100644 --- a/sonoff/xnrg_05_pzem2.ino +++ b/sonoff/xnrg_05_pzem2.ino @@ -211,7 +211,7 @@ int Xnrg05(byte function) if (FUNC_PRE_INIT == function) { Pzem2DrvInit(); } - else if (XNRG_03 == energy_flg) { + else if (XNRG_05 == energy_flg) { switch (function) { case FUNC_INIT: Pzem2SnsInit(); From e60f7e4e9edf3fed6188c6a46fce30d1cb4ac1d3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 11 Sep 2018 19:14:15 +0200 Subject: [PATCH 0098/2222] Update xnrg_05_pzem2.ino --- sonoff/xnrg_05_pzem2.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xnrg_05_pzem2.ino b/sonoff/xnrg_05_pzem2.ino index 7f9a4f8ba..b7e1eab42 100644 --- a/sonoff/xnrg_05_pzem2.ino +++ b/sonoff/xnrg_05_pzem2.ino @@ -211,7 +211,7 @@ int Xnrg05(byte function) if (FUNC_PRE_INIT == function) { Pzem2DrvInit(); } - else if (XNRG_03 == energy_flg) { + else if (XNRG_05 == energy_flg) { switch (function) { case FUNC_INIT: Pzem2SnsInit(); From 8025f28409f210760a86f603df4e7b547d3a4cec Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 12 Sep 2018 19:00:35 -0300 Subject: [PATCH 0099/2222] Let syslog to be active when emulation is active too solves issue https://github.com/arendst/Sonoff-Tasmota/issues/2109 --- sonoff/sonoff.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 52cdb68ba..a55e896c4 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1004,7 +1004,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) else if (CMND_SYSLOG == command_code) { if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) { Settings.syslog_level = payload; - syslog_level = (Settings.flag2.emulation) ? 0 : payload; + syslog_level = payload; syslog_timer = 0; } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.syslog_level, syslog_level); @@ -1596,7 +1596,7 @@ void PerformEverySecond() if (syslog_timer) { // Restore syslog level syslog_timer--; if (!syslog_timer) { - syslog_level = (Settings.flag2.emulation) ? 0 : Settings.syslog_level; + syslog_level = 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) } @@ -2513,7 +2513,7 @@ void setup() #ifndef USE_EMULATION Settings.flag2.emulation = 0; #endif // USE_EMULATION - syslog_level = (Settings.flag2.emulation) ? 0 : Settings.syslog_level; + syslog_level = Settings.syslog_level; stop_flash_rotate = Settings.flag.stop_flash_rotate; save_data_counter = Settings.save_data; sleep = Settings.sleep; From f8115a5abde45eac2748ccfb28fa5aba5e6cb9cc Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 13 Sep 2018 11:43:23 -0300 Subject: [PATCH 0100/2222] Added support for Xiaomi-Phillips bulb https://github.com/arendst/Sonoff-Tasmota/issues/3055 --- sonoff/sonoff_template.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 1ab62ae63..781b1004d 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -230,6 +230,7 @@ enum SupportedModules { BLITZWOLF_BWSHP2, SHELLY1, SHELLY2, + PHILIPS, MAXMODULE }; /********************************************************************************************/ @@ -399,7 +400,8 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { KMC_70011, AILIGHT, WEMOS, - WITTY + WITTY, + PHILIPS }; // Default module settings @@ -1044,6 +1046,14 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_SWT2_NP, // GPIO14 0, // GPIO15 MCP39F501 Reset 0, 0 + }, + { "Xiaomi Philips", // Xiaomi Philips bulb (ESP8266) + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + GPIO_PWM2, // GPIO12 cold/warm light + 0, 0, + GPIO_PWM1, // GPIO15 light intensity + 0, 0 } }; From 6f724e705b63b93d38a24ea66109ff0ac04deca6 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 13 Sep 2018 11:45:01 -0300 Subject: [PATCH 0101/2222] Added support for Xiaomi-Phillips bulb --- sonoff/xdrv_04_light.ino | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 93c2c522c..2a5a15b0c 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -427,6 +427,11 @@ void LightSetColorTemp(uint16_t ct) } uint16_t icold = (100 * (347 - my_ct)) / 136; uint16_t iwarm = (100 * my_ct) / 136; + if (PHILIPS == Settings.module) { + // Xiaomi Philips bulbs follow a different scheme: + // channel 0=intensity, channel2=temperature + Settings.light_color[1] = (uint8_t)icold; + } else if (LST_RGBWC == light_subtype) { Settings.light_color[0] = 0; Settings.light_color[1] = 0; @@ -458,6 +463,15 @@ void LightSetDimmer(uint8_t myDimmer) { float temp; + if (PHILIPS == Settings.module) { + // Xiaomi Philips bulbs use two PWM channels with a different scheme: + float dimmer = 100 / (float)myDimmer; + temp = (float)Settings.light_color[0] / dimmer; // channel 1 is intensity + light_current_color[0] = (uint8_t)temp; + temp = (float)Settings.light_color[1]; // channel 2 is temperature + light_current_color[1] = (uint8_t)temp; + return; + } if (LT_PWM1 == light_type) { Settings.light_color[0] = 255; // One PWM channel only supports Dimmer but needs max color } From 2b6e97146edc91af0d9c6b6dad6d8cbca87d5b59 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 13 Sep 2018 11:53:27 -0300 Subject: [PATCH 0102/2222] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 581b38e83..3f695f666 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ The following devices are supported: - [Supla device - Espablo-inCan mod. for electrical Installation box](https://forum.supla.org/viewtopic.php?f=33&t=2188) - [BlitzWolf BW-SHP2 Smart Socket with Energy Monitoring](https://www.banggood.com/BlitzWolf-BW-SHP2-Smart-WIFI-Socket-EU-Plug-220V-16A-Work-with-Amazon-Alexa-Google-Assistant-p-1292899.html) - [Luani HVIO board](https://luani.de/projekte/esp8266-hvio/) +- Xiaomi-Phillips Bulbs - Wemos D1 mini, NodeMcu and Ledunia ### Contribute From b3d2447fc708f470c21341283f63652a2c083ba4 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 13 Sep 2018 11:54:24 -0300 Subject: [PATCH 0103/2222] Update _changelog.ino --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index d9044fcae..eed6ffcc7 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,6 +4,7 @@ * Fix ButtonRetain to not use default topic for clearing retain messages (#3737) * Add sleep to Nova Fitness SDS01X sensor (#2841, #3724, #3749) * Add Analog input AD0 enabled to sonoff-sensors.bin (#3756, #3757) + * Add Support to Xiaomi-Phillips Bulbs * * 6.2.1.2 20180906 * Fix KNX PA exception. Regression from 6.2.1 buffer overflow caused by subStr() (#3700, #3710) From 15fb7307fc363c2e7d8f478183dc3c0af63ad58f Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Fri, 14 Sep 2018 16:39:06 +0200 Subject: [PATCH 0104/2222] Add login parms for tools/decode-status.py --- tools/decode-status.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/decode-status.py b/tools/decode-status.py index 154b6e719..74b10a57c 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -28,12 +28,13 @@ Instructions: and store it in file status.json Usage: - ./decode-status.py -d + ./decode-status.py -d [-u username] [-p password] or ./decode-status.py -f Example: ./decode-status.py -d sonoff1 + ./decode-status.py -d sonoff1 -p 12345678 or ./decode-status.py -f status.json """ @@ -42,6 +43,7 @@ import io import os.path import json import pycurl +import urllib2 from sys import exit from optparse import OptionParser from StringIO import StringIO @@ -136,13 +138,20 @@ usage = "usage: decode-status {-d | -f} arg" parser = OptionParser(usage) parser.add_option("-d", "--dev", action="store", type="string", dest="device", help="device to retrieve status from") +parser.add_option("-u", "--username", action="store", type="string", + dest="username", help="username for login", default="admin") +parser.add_option("-p", "--password", action="store", type="string", + dest="password", help="password for login", default=None) parser.add_option("-f", "--file", metavar="FILE", dest="jsonfile", default="status.json", help="status json file (default: status.json)") (options, args) = parser.parse_args() if (options.device): buffer = StringIO() - url = str("http://{}/cm?cmnd=status%200".format(options.device)) + loginstr = "" + if options.password is not None: + loginstr = "user={}&password={}&".format(urllib2.quote(options.username), urllib2.quote(options.password)) + url = str("http://{}/cm?{}cmnd=status%200".format(options.device, loginstr)) c = pycurl.Curl() c.setopt(c.URL, url) c.setopt(c.WRITEDATA, buffer) @@ -217,4 +226,4 @@ if __name__ == "__main__": try: StartDecode() except Exception as e: - print("E: {}".format(e)) \ No newline at end of file + print("E: {}".format(e)) From 63a1763a3f50a87fd2221f26cdb07f05e5974203 Mon Sep 17 00:00:00 2001 From: Mike Date: Sat, 15 Sep 2018 09:13:39 +0200 Subject: [PATCH 0105/2222] added MP3_VOLUME to init the MP3 Player --- sonoff/user_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 357fe5fab..a07c87ec3 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -342,6 +342,7 @@ //#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) //#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop +// #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) From 3c947e4c81fa71c95bfa4964a55b098affa8d427 Mon Sep 17 00:00:00 2001 From: Mike Date: Sat, 15 Sep 2018 09:33:53 +0200 Subject: [PATCH 0106/2222] Added version info and new MP3 Player commands - Added the version information to have some little hints what is done. - Added new commands and changed two commands from the first version. -- Intention was to get as less of commands as needed. -- There will be possible a version with much more function and serial->read. Command list: - MP3TRACK -- specify playback of a track, e.g. MP3Track 003. - MP3PLAY -- Play, works as a normal play on a real MP3 Player, starts at 001.mp3 file on the selected device. - MP3PAUSE -- Pause, was original designed as stop, see data sheet. - MP3STOP -- Stop, it's a real stop now, in the original version it was a pause command. - MP3VOLUME -- specifies the volume and means a console input as 0..100. - MP3EQ -- specify the EQ(0/1/2/3/4/5), 0:Normal, 1:Pop, 2:Rock, 3:Jazz, 4:Classic, 5:Bass. - MP3DEVICE -- specify playback device, USB=1, SD-Card=2, default is 2 also after reset or power down/up. --- sonoff/xdrv_14_mp3.ino | 147 ++++++++++++++++++++++++++++++----------- 1 file changed, 110 insertions(+), 37 deletions(-) diff --git a/sonoff/xdrv_14_mp3.ino b/sonoff/xdrv_14_mp3.ino index e4c72cb16..d799aa1f0 100644 --- a/sonoff/xdrv_14_mp3.ino +++ b/sonoff/xdrv_14_mp3.ino @@ -15,6 +15,40 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . + + -------------------------------------------------------------------------------------------- + Version yyyymmdd Action Description + -------------------------------------------------------------------------------------------- + 1.0.0.3 20180915 added - select device for SD-Card or USB Stick, default will be SD-Card + tested - works by MP3Device 1 = USB STick, or MP3Device 2 = SD-Card + - after power and/or reset the SD-Card(2) is the default device + --- + 1.0.0.2 20180912 added - again some if-commands to switch() because of new commands + --- + 1.0.0.1 20180911 added - command eq (equalizer 0..5) + tested - works in console with MP3EQ 1, the value can be 0..5 + added - USB device selection via command in console + tested - looks like it is working + erased - code for USB device about some errors, will be added in a next release + --- + 1.0.0.1 20180910 changed - command real MP3Stop in place of pause/stop used in the original version + changed - the command MP3Play e.g. 001 to MP3Track e.g. 001, + added - new normal command MP3Play and MP3Pause + --- + 1.0.0.0 20180907 merged - by arendst + changed - the driver name from xdrv_91_mp3.ino to xdrv_14_mp3.ino + --- + 0.9.0.3 20180906 request - Pull Request + changed - if-commands to switch() for faster response + --- + 0.9.0.2 20180906 cleaned - source code for faster reading + --- + 0.9.0.1 20180905 added - #include because compiler error (Arduino IDE v1.8.5) + --- + 0.9.0.0 20180901 started - further development by mike2nl - https://github.com/mike2nl/Sonoff-Tasmota + base - code base from gemu2015 ;-) - https://github.com/gemu2015/Sonoff-Tasmota + forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota + */ #ifdef USE_MP3_PLAYER @@ -31,14 +65,30 @@ TasmotaSerial *MP3Player; const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}"; const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}"; +const char kMP3_Commands[] PROGMEM = "Track|Play|Pause|Stop|Volume|EQ|Device"; -enum MP3_Commands { CMND_MP3_PLAY, CMND_MP3_STOP, CMND_MP3_VOLUME}; -const char kMP3_Commands[] PROGMEM = "Play|Stop|Volume"; +// enumerations +enum MP3_Commands { // commands useable in console or rules + CMND_MP3_TRACK, // MP3Track 001...255 + CMND_MP3_PLAY, // MP3Play, after pause or normal start to play + CMND_MP3_PAUSE, // MP3Pause + CMND_MP3_STOP, // MP3Stop, real stop, original version was pause function + CMND_MP3_VOLUME, // MP3Volume 0..100 + CMND_MP3_EQ, // MP3EQ 0..5 + CMND_MP3_DEVICE }; // sd-card: 02, usb-stick: 01 -#define MP3_CMD_PLAY 3 -#define MP3_CMD_VOLUME 6 -#define MP3_CMD_STOP 0x0e +// defines +#define MP3_CMD_TRACK 0x03 // specify playback of a track, e.g. MP3Track 003 +#define MP3_CMD_PLAY 0x0d // Play, works as a normal play on a real MP3 Player, starts at 001.mp3 file on the selected device +#define MP3_CMD_PAUSE 0x0e // Pause, was original designed as stop, see data sheet +#define MP3_CMD_STOP 0x16 // Stop, it's a real stop now, in the original version it was a pause command +#define MP3_CMD_VOLUME 0x06 // specifies the volume and means a console input as 0..100 +#define MP3_CMD_EQ 0x07 // specify EQ(0/1/2/3/4/5), 0:Normal, 1:Pop, 2:Rock, 3:Jazz, 4:Classic, 5:Bass +#define MP3_CMD_DEVICE 0x09 // specify playback device, USB=1, SD-Card=2, default is 2 also after reset or power down/up +// calculate the checksum +// starts with cmd[1] with a length of 6 bytes +// uint16_t MP3_Checksum(uint8_t *array) { uint16_t checksum = 0; @@ -49,51 +99,74 @@ uint16_t MP3_Checksum(uint8_t *array) return checksum+1; } -// init player define serial tx port +// init player, define serial tx port +// fixed with 9600 baud +// void MP3PlayerInit() { MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3_DFR562]); - - if (MP3Player->begin(9600)) { + // start serial communication fixed to 9600 baud + if (MP3Player->begin(9600)) { MP3Player->flush(); + delay(1000); // set delay + // volume setting + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); // set volume depending on the entry in the user_config.h } } +// create mp3 command payload and send it via serail interface to the MP3 player +// {start byte, version, length, command, feedback, para MSB, para LSB, chks MSB, chks LSB, end byte}; +// {cmd[0] , cmd[1] , cmd[2], cmd[3] , cmd[4] , cmd[5] , cmd[6] , cmd[7] , cmd[8] , cmd[9] }; +// {0x7e , 0xff , 6 , 0 , 0/1 , 0 , 0 , 0 , 0 , 0xef }; +// void MP3_CMD(uint8_t mp3cmd,uint16_t val) { - uint8_t cmd[10] = {0x7e,0xff,6,0,0,0,0,0,0,0xef}; - cmd[3] = mp3cmd; - cmd[5] = val>>8; - cmd[6] = val; - uint16_t chks = MP3_Checksum(&cmd[1]); // calculate out - cmd[7] = chks>>8; - cmd[8] = chks; - MP3Player->write(cmd, sizeof(cmd)); + uint8_t cmd[10] = {0x7e,0xff,6,0,0,0,0,0,0,0xef}; // fill array + cmd[3] = mp3cmd; // mp3 command value + //cmd[4] = ; // feedback, yet not use + cmd[5] = val>>8; // data value, shift 8 byte right + cmd[6] = val; // data value low byte + uint16_t chks = MP3_Checksum(&cmd[1]); // see calculate the checksum, line 62..72 + cmd[7] = chks>>8; // checksum. shift 8 byte right + cmd[8] = chks; // checksum low byte + MP3Player->write(cmd, sizeof(cmd)); // write mp3 data array to player } +// check the MP3 commands +// boolean MP3PlayerCmd() { char command[CMDSZ]; boolean serviced = true; uint8_t disp_len = strlen(D_CMND_MP3); - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { // Prefix + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { // prefix int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMP3_Commands); - - if (CMND_MP3_PLAY == command_code) { - if (XdrvMailbox.data_len > 0) { // play - MP3_CMD(MP3_CMD_PLAY, XdrvMailbox.payload); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); - } - else if (CMND_MP3_VOLUME == command_code) { - if (XdrvMailbox.data_len > 0) { // set volume - MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); - } - else if (CMND_MP3_STOP == command_code) { // stop - MP3_CMD(MP3_CMD_STOP, 0); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); - } else { - serviced = false; // Unknown command + + switch (command_code) { + case CMND_MP3_TRACK: + case CMND_MP3_VOLUME: + case CMND_MP3_EQ: + case CMND_MP3_DEVICE: + // play a track, set volume, select EQ, sepcify file device + if (XdrvMailbox.data_len > 0) { + if (command_code == CMND_MP3_TRACK) { MP3_CMD(MP3_CMD_TRACK, XdrvMailbox.payload); } + if (command_code == CMND_MP3_VOLUME) { MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100); } + if (command_code == CMND_MP3_EQ) { MP3_CMD(MP3_CMD_EQ, XdrvMailbox.payload); } + if (command_code == CMND_MP3_DEVICE) { MP3_CMD(MP3_CMD_DEVICE, XdrvMailbox.payload); } + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_MP3_PLAY: + case CMND_MP3_PAUSE: + case CMND_MP3_STOP: + // play or re-play after pause, pause, stop, + if (command_code == CMND_MP3_PLAY) { MP3_CMD(MP3_CMD_PLAY, 0); } + if (command_code == CMND_MP3_PAUSE) { MP3_CMD(MP3_CMD_PAUSE, 0); } + if (command_code == CMND_MP3_STOP) { MP3_CMD(MP3_CMD_STOP, 0); } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); + break; + default: + // else for Unknown command + serviced = false; + break; } } return serviced; @@ -111,10 +184,10 @@ boolean Xdrv14(byte function) switch (function) { case FUNC_PRE_INIT: - MP3PlayerInit(); + MP3PlayerInit(); // init and start communication break; case FUNC_COMMAND: - result = MP3PlayerCmd(); + result = MP3PlayerCmd(); // return result from mp3 player command break; } return result; From 9fc5d7162965e1d3415cee133404f961e85c9e99 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 15 Sep 2018 12:00:22 +0200 Subject: [PATCH 0107/2222] Update Czech translation Update Czech translation --- sonoff/language/cs-CZ.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 9a0b11062..e90797725 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -94,7 +94,7 @@ #define D_FALSE "Nepravda" #define D_FILE "Soubor" #define D_FREE_MEMORY "Volná paměť" -#define D_FREQUENCY "Frequency" +#define D_FREQUENCY "Kmitočet" #define D_GAS "Plyn" #define D_GATEWAY "Výchozí brána" #define D_GROUP "Skupina" @@ -128,7 +128,7 @@ #define D_POWERUSAGE_APPARENT "Apparent Power" #define D_POWERUSAGE_REACTIVE "Reactive Power" #define D_PRESSURE "Tlak" -#define D_PRESSUREATSEALEVEL "Tlak na úrovni hladiny moře" +#define D_PRESSUREATSEALEVEL "Tlak na hladině moře" #define D_PROGRAM_FLASH_SIZE "Velikost paměti flash" #define D_PROGRAM_SIZE "Velikost programu" #define D_PROJECT "Projekt" From d0fa749c306327f4b37c873fd18b986d163c397e Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 15 Sep 2018 15:56:56 +0200 Subject: [PATCH 0108/2222] MCP230xx - Fix support for setoption4 --- sonoff/xsns_29_mcp230xx.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 058d6c25c..586b8da8e 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -297,7 +297,7 @@ void MCP230xx_CheckForInterrupt(void) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}"), mqtt_data, intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("MCP230XX_INT")); } if (int_event) { char command[19]; // Theoretical max = 'event MCPINT_D16=1' so 18 + 1 (for the \n) From 98cfb0080382df4f3a8a0cb1a77297fdf70595e6 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 15 Sep 2018 18:59:45 +0200 Subject: [PATCH 0109/2222] MCP230xx - Fix millisecond counter reset placement --- sonoff/xsns_29_mcp230xx.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 586b8da8e..80aa76b7a 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -280,7 +280,9 @@ void MCP230xx_CheckForInterrupt(void) { if (report_int) { bool int_tele = false; bool int_event = false; - unsigned long millis_since_last_int = millis() - int_millis[intp+(mcp230xx_port*8)]; + unsigned long millis_now = millis(); + unsigned long millis_since_last_int = millis_now - int_millis[intp+(mcp230xx_port*8)]; + int_millis[intp+(mcp230xx_port*8)]=millis_now; switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_mode) { case 0: int_tele=true; @@ -304,7 +306,6 @@ void MCP230xx_CheckForInterrupt(void) { sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01)); ExecuteCommand(command, SRC_RULE); } - int_millis[intp+(mcp230xx_port*8)]=millis(); } } } From bf7dcb8eec8c898e869b04e7313e1fcd1073726c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 16 Sep 2018 16:09:00 +0200 Subject: [PATCH 0110/2222] 6.2.1.3 Add SerialSend5 6.2.1.4 20180916 * Add command SerialSend5 to send raw serial data like "A5074100545293" * Update MCP230xx driver * Update Czech translation * Update MP3 driver (#3800) * Add userid/password option to decode-status.py (#3796) * Fix syslog when emulation is selected (#2109, #3784) * Fix Pzem2 compilation error (#3766, #3767) --- sonoff/_changelog.ino | 13 +++++++++++-- sonoff/sonoff.ino | 13 ++++++++----- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 15 +++++++++++++++ sonoff/user_config.h | 2 +- sonoff/xdrv_06_snfbridge.ino | 19 ++----------------- 6 files changed, 38 insertions(+), 26 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index eed6ffcc7..bd4ee9b7c 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,10 +1,19 @@ -/* 6.2.1.3 20180907 +/* 6.2.1.4 20180916 + * Add command SerialSend5 to send raw serial data like "A5074100545293" + * Update MCP230xx driver + * Update Czech translation + * Update MP3 driver (#3800) + * Add userid/password option to decode-status.py (#3796) + * Fix syslog when emulation is selected (#2109, #3784) + * Fix Pzem2 compilation error (#3766, #3767) + * + * 6.2.1.3 20180907 * Change web Configure Module GPIO drop down list order for better readability * Fix showing Period Power in energy threshold messages * Fix ButtonRetain to not use default topic for clearing retain messages (#3737) * Add sleep to Nova Fitness SDS01X sensor (#2841, #3724, #3749) * Add Analog input AD0 enabled to sonoff-sensors.bin (#3756, #3757) - * Add Support to Xiaomi-Phillips Bulbs + * Add Support for Xiaomi-Philips Bulbs (#3787) * * 6.2.1.2 20180906 * Fix KNX PA exception. Regression from 6.2.1 buffer overflow caused by subStr() (#3700, #3710) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index a55e896c4..4903fe80f 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -969,22 +969,25 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.baudrate * 1200); } - else if ((CMND_SERIALSEND == command_code) && (index > 0) && (index <= 4)) { + else if ((CMND_SERIALSEND == command_code) && (index > 0) && (index <= 5)) { SetSeriallog(LOG_LEVEL_NONE); Settings.flag.mqtt_serial = 1; - Settings.flag.mqtt_serial_raw = (4 == index) ? 1 : 0; + Settings.flag.mqtt_serial_raw = (index > 3) ? 1 : 0; if (data_len > 0) { if (1 == index) { - Serial.printf("%s\n", dataBuf); + Serial.printf("%s\n", dataBuf); // "Hello Tiger\n" } else if (2 == index || 4 == index) { for (int i = 0; i < data_len; i++) { - Serial.write(dataBuf[i]); + Serial.write(dataBuf[i]); // "Hello Tiger" or "A0" } } else if (3 == index) { uint16_t dat_len = data_len; - Serial.printf("%s", Unescape(dataBuf, &dat_len)); + Serial.printf("%s", Unescape(dataBuf, &dat_len)); // "Hello\f" + } + else if (5 == index) { + SerialSendRaw(dataBuf, data_len); // "AA004566" } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index f068473ab..f5f94dad1 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020103 +#define VERSION 0x06020104 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index af93fa148..fb2b5eae3 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -704,6 +704,21 @@ void ClaimSerial() Settings.baudrate = baudrate / 1200; } +void SerialSendRaw(char *codes, int size) +{ + char *p; + char stemp[3]; + uint8_t code; + + while (size > 0) { + snprintf(stemp, sizeof(stemp), codes); + code = strtol(stemp, &p, 16); + Serial.write(code); + size -= 2; + codes += 2; + } +} + uint32_t GetHash(const char *buffer, size_t size) { uint32_t hash = 0; diff --git a/sonoff/user_config.h b/sonoff/user_config.h index a07c87ec3..5a2b909de 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -342,7 +342,7 @@ //#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) //#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop -// #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) + #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index b0518f133..379d29455 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -199,21 +199,6 @@ uint8_t SnfBrUpdateInit() /********************************************************************************************/ -void SonoffBridgeSendRaw(char *codes, int size) -{ - char *p; - char stemp[3]; - uint8_t code; - - while (size > 0) { - snprintf(stemp, sizeof(stemp), codes); - code = strtol(stemp, &p, 16); - Serial.write(code); - size -= 2; - codes += 2; - } -} - void SonoffBridgeReceivedRaw() { // Decoding according to https://github.com/Portisch/RF-Bridge-EFM8BB1 @@ -552,11 +537,11 @@ boolean SonoffBridgeCommand() break; case 192: // 0xC0 - Beep char beep[] = "AAC000C055"; - SonoffBridgeSendRaw(beep, sizeof(beep)); + SerialSendRaw(beep, sizeof(beep)); break; } } else { - SonoffBridgeSendRaw(XdrvMailbox.data, XdrvMailbox.data_len); + SerialSendRaw(XdrvMailbox.data, XdrvMailbox.data_len); sonoff_bridge_receive_raw_flag = 1; } } From 29b3e6ec27ae9395764e19545246f7fb76f254d3 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 16 Sep 2018 21:36:56 +0200 Subject: [PATCH 0111/2222] MCP230xx - Change address selection from auto to user defined --- sonoff/user_config.h | 3 +- sonoff/xsns_29_mcp230xx.ino | 73 +++++++++++++++---------------------- 2 files changed, 31 insertions(+), 45 deletions(-) diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 5a2b909de..20339b5f6 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -294,7 +294,8 @@ // #define USE_SI1145 // Enable SI1145/46/47 sensor (I2C address 0x60) (+1k code) #define USE_LM75AD // Enable LM75AD sensor (I2C addresses 0x48 - 0x4F) (+0k5 code) // #define USE_APDS9960 // Enable APDS9960 Proximity Sensor (I2C address 0x39). Disables SHT and VEML6070 (+4k7 code) -// #define USE_MCP230xx // Enable MCP23008/MCP23017 for GP INPUT ONLY (I2C addresses 0x20 - 0x27) providing command Sensor29 for configuration (+4k7 code) +// #define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) +// #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) // #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+1k5 code) // #define USE_MCP230xx_DISPLAYOUTPUT // Enable MCP23008/MCP23017 to display state of OUTPUT pins on Web UI (+0k2 code) // #define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 80aa76b7a..50798eb8f 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -31,15 +31,6 @@ #define XSNS_29 29 -#define MCP230xx_ADDRESS1 0x20 -#define MCP230xx_ADDRESS2 0x21 -#define MCP230xx_ADDRESS3 0x22 -#define MCP230xx_ADDRESS4 0x23 -#define MCP230xx_ADDRESS5 0x24 -#define MCP230xx_ADDRESS6 0x25 -#define MCP230xx_ADDRESS7 0x26 -#define MCP230xx_ADDRESS8 0x27 - /* Default register locations for MCP23008 - They change for MCP23017 in default bank mode */ @@ -53,8 +44,6 @@ uint8_t MCP230xx_INTCAP = 0x08; uint8_t MCP230xx_GPIO = 0x09; uint8_t mcp230xx_type = 0; -uint8_t mcp230xx_address; -uint8_t mcp230xx_addresses[] = { MCP230xx_ADDRESS1, MCP230xx_ADDRESS2, MCP230xx_ADDRESS3, MCP230xx_ADDRESS4, MCP230xx_ADDRESS5, MCP230xx_ADDRESS6, MCP230xx_ADDRESS7, MCP230xx_ADDRESS8 }; uint8_t mcp230xx_pincount = 0; uint8_t mcp230xx_int_en = 0; uint8_t mcp230xx_int_prio_counter = 0; @@ -131,7 +120,7 @@ const char* IntModeTxt(uint8_t intmo) { } uint8_t MCP230xx_readGPIO(uint8_t port) { - return I2cRead8(mcp230xx_address, MCP230xx_GPIO + port); + return I2cRead8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port); } void MCP230xx_ApplySettings(void) { @@ -178,11 +167,11 @@ void MCP230xx_ApplySettings(void) { } #endif // USE_MCP230xx_OUTPUT } - I2cWrite8(mcp230xx_address, MCP230xx_GPPU+mcp230xx_port, reg_gppu); - I2cWrite8(mcp230xx_address, MCP230xx_GPINTEN+mcp230xx_port, reg_gpinten); - I2cWrite8(mcp230xx_address, MCP230xx_IODIR+mcp230xx_port, reg_iodir); + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPPU+mcp230xx_port, reg_gppu); + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPINTEN+mcp230xx_port, reg_gpinten); + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_IODIR+mcp230xx_port, reg_iodir); #ifdef USE_MCP230xx_OUTPUT - I2cWrite8(mcp230xx_address, MCP230xx_GPIO+mcp230xx_port, reg_portpins); + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO+mcp230xx_port, reg_portpins); #endif // USE_MCP230xx_OUTPUT } for (uint8_t idx=0;idx 0) { - if (I2cValidRead8(&mcp230xx_intcap, mcp230xx_address, MCP230xx_INTCAP+mcp230xx_port)) { + if (I2cValidRead8(&mcp230xx_intcap, USE_MCP230xx_ADDR, MCP230xx_INTCAP+mcp230xx_port)) { for (uint8_t intp = 0; intp < 8; intp++) { if ((intf >> intp) & 0x01) { // we know which pin caused interrupt report_int = 0; @@ -367,7 +352,7 @@ void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { portpins ^= (1 << (pin-(port*8))); } } - I2cWrite8(mcp230xx_address, MCP230xx_GPIO + port, portpins); + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port, portpins); if (Settings.flag.save_state) { // Firmware configured to save last known state in settings Settings.mcp230xx_config[pin].saved_state=portpins>>(pin-(port*8))&1; Settings.mcp230xx_config[pin+pinadd].saved_state=portpins>>(pin+pinadd-(port*8))&1; From bffc820fb05bae7582934d27e76b6fd1bd86206b Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 17 Sep 2018 08:23:39 +0200 Subject: [PATCH 0112/2222] Update Bug_report.md --- .github/ISSUE_TEMPLATE/Bug_report.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 2616af48f..f97db3ad0 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -4,6 +4,9 @@ about: Create a report to help us improve --- +**IMPORTANT NOTICE** +If you do not complete the template below your it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses. + **Describe the bug** _A clear and concise description of what the bug is._ @@ -11,6 +14,7 @@ _A clear and concise description of what the bug is._ _Also, make sure these boxes are checked [x] before submitting your issue - Thank you!_ - [ ] _Searched the problem in issues and in the wiki_ - [ ] _Hardware used_ : +- [ ] _Development/Compiler/Upload tools used_ : - [ ] _Provide the output of command_``status 0`` : ``` STATUS 0 OUTPUT HERE From 2f0cd60cb3a6ee1cab85c1b3b73e9a13d41e1a8a Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 17 Sep 2018 08:26:43 +0200 Subject: [PATCH 0113/2222] Update Custom.md --- .github/ISSUE_TEMPLATE/Custom.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/Custom.md b/.github/ISSUE_TEMPLATE/Custom.md index 159549128..bc769a38d 100644 --- a/.github/ISSUE_TEMPLATE/Custom.md +++ b/.github/ISSUE_TEMPLATE/Custom.md @@ -4,12 +4,16 @@ about: Users Troubleshooting Help --- +**IMPORTANT NOTICE** +If you do not complete the template below your it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses. + Make sure these boxes are checked [x] before submitting your issue - Thank you! - [ ] Searched the problem in issues (https://github.com/arendst/Sonoff-Tasmota/issues) - [ ] Searched the problem in the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting) - [ ] Searched the problem in the forum (https://groups.google.com/d/forum/sonoffusers) - [ ] Searched the problem in the chat (https://discord.gg/Ks2Kzd4) +- [ ] Development/Compiler/Upload tools used : - [ ] Hardware used : - [ ] Provide the output of command ``status 0`` : ``` From 3d74ed9964b9b40ba4fc6bce18aa561d25554f58 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 17 Sep 2018 09:08:37 +0200 Subject: [PATCH 0114/2222] Update Bug_report.md --- .github/ISSUE_TEMPLATE/Bug_report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index f97db3ad0..bf55e130e 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -5,7 +5,7 @@ about: Create a report to help us improve --- **IMPORTANT NOTICE** -If you do not complete the template below your it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses. +If you do not complete the template below it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses. **Describe the bug** _A clear and concise description of what the bug is._ From de406b7868f0c6a0d7ab75a3270ef9971dec30a8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 17 Sep 2018 09:11:18 +0200 Subject: [PATCH 0115/2222] Update Custom.md --- .github/ISSUE_TEMPLATE/Custom.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/Custom.md b/.github/ISSUE_TEMPLATE/Custom.md index bc769a38d..77fc7a3e7 100644 --- a/.github/ISSUE_TEMPLATE/Custom.md +++ b/.github/ISSUE_TEMPLATE/Custom.md @@ -5,7 +5,7 @@ about: Users Troubleshooting Help --- **IMPORTANT NOTICE** -If you do not complete the template below your it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses. +If you do not complete the template below it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses. Make sure these boxes are checked [x] before submitting your issue - Thank you! From ff4f8f75c17aa21db912775d947d31caf9a2616b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 17 Sep 2018 20:32:38 +0200 Subject: [PATCH 0116/2222] Add uncalibrated energy monitor Add uncalibrated energy monitoring to Shelly2 (#2789) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_03_energy.ino | 4 +- sonoff/xnrg_04_mcp39f501.ino | 301 +++++++++++++++++++++++++++++++++++ 3 files changed, 304 insertions(+), 2 deletions(-) create mode 100644 sonoff/xnrg_04_mcp39f501.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index bd4ee9b7c..fdf73fdc7 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -6,6 +6,7 @@ * Add userid/password option to decode-status.py (#3796) * Fix syslog when emulation is selected (#2109, #3784) * Fix Pzem2 compilation error (#3766, #3767) + * Add uncalibrated energy monitoring to Shelly2 (#2789) * * 6.2.1.3 20180907 * Change web Configure Module GPIO drop down list order for better readability diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index ac26a18da..aa589efab 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -98,6 +98,8 @@ void EnergyUpdateToday() void Energy200ms() { + energy_power_on = (power != 0) | Settings.flag.no_power_on_check; + energy_fifth_second++; if (5 == energy_fifth_second) { energy_fifth_second = 0; @@ -121,8 +123,6 @@ void Energy200ms() } } - energy_power_on = (power &1) | Settings.flag.no_power_on_check; - XnrgCall(FUNC_EVERY_200_MSECOND); if (energy_calc_power_factor) { diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino new file mode 100644 index 000000000..f74111f9d --- /dev/null +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -0,0 +1,301 @@ +/* + xnrg_04_mcp39f501.ino - MCP39F501 energy sensor support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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_ENERGY_SENSOR +#ifdef USE_MCP39F501 +/*********************************************************************************************\ + * MCP39F501 - Energy (Shelly 2) + * + * Based on datasheet from https://www.microchip.com/wwwproducts/en/MCP39F501 + * and https://github.com/OLIMEX/olimex-iot-firmware-esp8266/blob/7a7f9bb56d4b72770dba8d0f18eaa9d956dd0baf/olimex/user/modules/mod_emtr.c +\*********************************************************************************************/ + +#define XNRG_04 4 + +#define MCP_START_FRAME 0xA5 +#define MCP_ACK_FRAME 0x06 +#define MCP_ERROR_NAK 0x15 +#define MCP_ERROR_CRC 0x51 + +#define MCP_SINGLE_WIRE 0xAB + +#define MCP_SET_ADDRESS 0x41 + +#define MCP_READ 0x4E +#define MCP_READ_16 0x52 +#define MCP_READ_32 0x44 + +#define MCP_WRITE 0x4D +#define MCP_WRITE_16 0x57 +#define MCP_WRITE_32 0x45 + +#define MCP_SAVE_REGISTERS 0x53 + +#define MCP_FLASH_READ 0x42 +#define MCP_FLASH_WRITE 0x50 + +uint32 mcp_system_configuration = 0x03000000; +uint8_t mcp_single_wire_active = 0; + +/*********************************************************************************************\ + * Olimex tools + * https://github.com/OLIMEX/olimex-iot-firmware-esp8266/blob/7a7f9bb56d4b72770dba8d0f18eaa9d956dd0baf/olimex/user/modules/mod_emtr.c +\*********************************************************************************************/ + + +unsigned long McpExtractInt(uint8_t *data, uint8_t offset, uint8_t size) +{ + unsigned long result = 0; + unsigned long pow = 1; + + for (byte i = 0; i < size; i++) { + result = result + data[offset + i] * pow; + pow = pow * 256; + } + return result; +} + +void McpSetSystemConfiguration(uint16 interval) +{ + uint8_t data[17]; + + data[ 0] = MCP_START_FRAME; + data[ 1] = sizeof(data); + data[ 2] = MCP_SET_ADDRESS; // Set address pointer + data[ 3] = 0x00; // address + data[ 4] = 0x42; // address + data[ 5] = MCP_WRITE_32; // Write 4 bytes + data[ 6] = (mcp_system_configuration >> 24) & 0xFF; // system_configuration + data[ 7] = (mcp_system_configuration >> 16) & 0xFF; // system_configuration + data[ 8] = (mcp_system_configuration >> 8) & 0xFF; // system_configuration + data[ 9] = (mcp_system_configuration >> 0) & 0xFF; // system_configuration + data[10] = MCP_SET_ADDRESS; // Set address pointer + data[11] = 0x00; // address + data[12] = 0x5A; // address + data[13] = MCP_WRITE_16; // Write 2 bytes + data[14] = (interval >> 8) & 0xFF; // interval + data[15] = (interval >> 0) & 0xFF; // interval + uint8_t checksum = 0; + for (byte i = 0; i < sizeof(data) -1; i++) { checksum += (uint8_t)data[i]; } + data[16] = checksum; + + // A5 11 41 00 42 45 03 00 01 00 41 00 5A 57 00 06 7A + AddLogSerial(LOG_LEVEL_DEBUG, data, sizeof(data)); + + for (byte i = 0; i < sizeof(data); i++) { Serial.write(data[i]); } +} + +void McpSingleWireStart() +{ + if ((mcp_system_configuration & (1 << 8)) != 0) { return; } + mcp_system_configuration = mcp_system_configuration | (1 << 8); + McpSetSystemConfiguration(6); // 64 + mcp_single_wire_active = 1; +} + +void McpSingleWireStop() +{ + if ((mcp_system_configuration & (1 << 8)) == 0) { return; } + mcp_system_configuration = mcp_system_configuration & (~(1 << 8)); + McpSetSystemConfiguration(2); // 4 + mcp_single_wire_active = 0; +} + +/********************************************************************************************/ + +unsigned long mcp_current = 0; +unsigned long mcp_voltage = 0; +unsigned long mcp_power = 0; +unsigned long mcp_frequency = 0; + +void McpParseData(uint8_t single_wire) +{ + if (single_wire) { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + // AB CD EF 51 06 00 00 B8 08 FC 0D 00 00 0A C4 11 + // Header-- Current---- Volt- Power------ Freq- Ck + + mcp_current = McpExtractInt((uint8_t*)serial_in_buffer, 3, 4); + mcp_voltage = McpExtractInt((uint8_t*)serial_in_buffer, 7, 2); + mcp_power = McpExtractInt((uint8_t*)serial_in_buffer, 9, 4); + mcp_frequency = McpExtractInt((uint8_t*)serial_in_buffer, 13, 2); + } else { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + // 06 19 61 06 00 00 FE 08 9B 0E 00 00 0B 00 00 00 97 0E 00 00 FF 7F 0C C6 35 + // Ak Ln Current---- Volt- ActivePower ReActivePow ApparentPow Factr Frequ Ck + + mcp_current = McpExtractInt((uint8_t*)serial_in_buffer, 2, 4); + mcp_voltage = McpExtractInt((uint8_t*)serial_in_buffer, 6, 2); + mcp_power = McpExtractInt((uint8_t*)serial_in_buffer, 8, 4); + mcp_frequency = McpExtractInt((uint8_t*)serial_in_buffer, 22, 2); + } + + if (energy_power_on) { // Powered on + energy_frequency = (float)mcp_frequency / 1000; + energy_voltage = (float)mcp_voltage / 10; + energy_power = (float)mcp_power / 100; + if (0 == energy_power) { + energy_current = 0; + } else { + energy_current = (float)mcp_current / 10000; + } + } else { // Powered off + energy_frequency = 0; + energy_voltage = 0; + energy_power = 0; + energy_current = 0; + } +} + +bool McpSerialInput() +{ + Settings.flag.mqtt_serial = 0; // Disable possible SerialReceive handling + + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (MCP_ERROR_CRC == serial_in_buffer[0]) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Send " D_CHECKSUM_FAILURE)); + return 1; + } + else if (MCP_ACK_FRAME == serial_in_buffer[0]) { + if ((serial_in_byte_counter > 1) && (serial_in_byte_counter == serial_in_buffer[1])) { + + AddLogSerial(LOG_LEVEL_DEBUG_MORE); + + uint8_t checksum = 0; + for (byte i = 0; i < serial_in_byte_counter -1; i++) { checksum += (uint8_t)serial_in_buffer[i]; } + if (checksum != serial_in_buffer[serial_in_byte_counter -1]) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); + } else { + if (25 == serial_in_buffer[1]) { McpParseData(0); } + } + return 1; + } + } + else if (MCP_SINGLE_WIRE == serial_in_buffer[0]) { + if (serial_in_byte_counter == 16) { + + AddLogSerial(LOG_LEVEL_DEBUG_MORE); + + uint8_t checksum = 0; + for (byte i = 3; i < serial_in_byte_counter -1; i++) { checksum += (uint8_t)serial_in_buffer[i]; } +// if (~checksum != serial_in_buffer[serial_in_byte_counter -1]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); +// } else { + McpParseData(1); +// } + return 1; + } + } + else { + return 1; + } + serial_in_byte = 0; // Discard + return 0; +} + +/********************************************************************************************/ + +void McpEverySecond() +{ + if (!mcp_single_wire_active) { + char get_state[] = "A5084100044E1656"; + SerialSendRaw(get_state, sizeof(get_state)); + } + + energy_kWhtoday += (energy_power / 36); + EnergyUpdateToday(); +} + +void McpSnsInit() +{ + digitalWrite(15, 1); // GPIO15 - MCP enable +} + +void McpDrvInit() +{ + if (!energy_flg) { + if (SHELLY2 == Settings.module) { + pinMode(15, OUTPUT); + digitalWrite(15, 0); // GPIO15 - MCP disable - Reset Delta Sigma ADC's + baudrate = 4800; + energy_calc_power_factor = 1; // Calculate power factor from data + energy_flg = XNRG_04; + } + } +} + +boolean McpCommand() +{ + boolean serviced = true; + + if ((CMND_POWERCAL == energy_command_code) || (CMND_VOLTAGECAL == energy_command_code) || (CMND_CURRENTCAL == energy_command_code)) { + + } + else if (CMND_POWERSET == energy_command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3601) && power_cycle) { +// Settings.energy_power_calibration = (XdrvMailbox.payload * power_cycle) / CSE_PREF; + } + } + else if (CMND_VOLTAGESET == energy_command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 501) && voltage_cycle) { +// Settings.energy_voltage_calibration = (XdrvMailbox.payload * voltage_cycle) / CSE_UREF; + } + } + else if (CMND_CURRENTSET == energy_command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 16001) && current_cycle) { +// Settings.energy_current_calibration = (XdrvMailbox.payload * current_cycle) / 1000; + } + } + else serviced = false; // Unknown command + + return serviced; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +int Xnrg04(byte function) +{ + int result = 0; + + if (FUNC_PRE_INIT == function) { + McpDrvInit(); + } + else if (XNRG_04 == energy_flg) { + switch (function) { + case FUNC_INIT: + McpSnsInit(); + break; + case FUNC_EVERY_SECOND: + McpEverySecond(); + break; + case FUNC_COMMAND: + result = McpCommand(); + break; + case FUNC_SERIAL: + result = McpSerialInput(); + break; + } + } + return result; +} + +#endif // USE_MCP39F501 +#endif // USE_ENERGY_SENSOR From c9f0c184661b7838536448823d3035a157223222 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Thu, 20 Sep 2018 20:44:17 +0200 Subject: [PATCH 0117/2222] LM75AD - Force function parameters to be C and C++ compliant --- sonoff/xsns_26_lm75ad.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_26_lm75ad.ino b/sonoff/xsns_26_lm75ad.ino index 092c8d153..1fd0f4448 100644 --- a/sonoff/xsns_26_lm75ad.ino +++ b/sonoff/xsns_26_lm75ad.ino @@ -46,7 +46,7 @@ uint8_t lm75ad_type = 0; uint8_t lm75ad_address; uint8_t lm75ad_addresses[] = { LM75AD_ADDRESS1, LM75AD_ADDRESS2, LM75AD_ADDRESS3, LM75AD_ADDRESS4, LM75AD_ADDRESS5, LM75AD_ADDRESS6, LM75AD_ADDRESS7, LM75AD_ADDRESS8 }; -void LM75ADDetect() +void LM75ADDetect(void) { if (lm75ad_type) { return; } @@ -64,7 +64,7 @@ void LM75ADDetect() } } -float LM75ADGetTemp() { +float LM75ADGetTemp(void) { int16_t sign = 1; uint16_t t = I2cRead16(lm75ad_address, LM75_TEMP_REGISTER); From 363e19d681584f09268f49fd4ed540d421f79753 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Thu, 20 Sep 2018 21:03:33 +0200 Subject: [PATCH 0118/2222] MCP230xx - Force C/C++ compliance --- sonoff/xsns_29_mcp230xx.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 50798eb8f..1ca59f8ed 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -181,7 +181,7 @@ void MCP230xx_ApplySettings(void) { MCP230xx_CheckForIntCounter(); // update register on whether or not we should be counting interrupts } -void MCP230xx_Detect() +void MCP230xx_Detect(void) { if (mcp230xx_type) { return; From 846d7a911f0571f209109a39585e7abad4e50cac Mon Sep 17 00:00:00 2001 From: andrethomas Date: Thu, 20 Sep 2018 22:56:07 +0200 Subject: [PATCH 0119/2222] Add driverXX support for FUNC_COMMAND callback --- sonoff/i18n.h | 4 ++++ sonoff/sonoff.ino | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index da47371d8..32cb458f1 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -174,6 +174,7 @@ #define D_CMND_BLINKTIME "BlinkTime" #define D_CMND_BLINKCOUNT "BlinkCount" #define D_CMND_SENSOR "Sensor" +#define D_CMND_DRIVER "Driver" #define D_CMND_SAVEDATA "SaveData" #define D_CMND_SETOPTION "SetOption" #define D_CMND_TEMPERATURE_RESOLUTION "TempRes" @@ -467,6 +468,9 @@ const char S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE[] PROGMEM = "{\"%s%d\":\"%d const char S_JSON_SENSOR_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":%d}"; const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":\"%s\"}"; +const char S_JSON_DRIVER_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":%d}"; +const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":\"%s\"}"; + const char JSON_SNS_TEMP[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"; const char JSON_SNS_TEMPHUM[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 4903fe80f..84293f5bc 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -83,7 +83,7 @@ enum TasmotaCommands { CMND_LOGHOST, CMND_LOGPORT, CMND_IPADDRESS, CMND_NTPSERVER, CMND_AP, CMND_SSID, CMND_PASSWORD, CMND_HOSTNAME, CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_TIMESTD, CMND_TIMEDST, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE, - CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER }; + CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER, CMND_DRIVER }; const char kTasmotaCommands[] PROGMEM = D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_FANSPEED "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|" D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SENSOR "|" D_CMND_SAVEDATA "|" D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" @@ -93,7 +93,7 @@ const char kTasmotaCommands[] PROGMEM = 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_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" - D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER; + D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER "|" D_CMND_DRIVER; const uint8_t kIFan02Speed[4][3] = {{6,6,6}, {7,6,6}, {7,7,6}, {7,6,7}}; @@ -690,6 +690,16 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) XsnsCall(FUNC_COMMAND); // if (!XsnsCall(FUNC_COMMAND)) type = NULL; } + else if (CMND_DRIVER == command_code) { + XdrvMailbox.index = index; + XdrvMailbox.data_len = data_len; + XdrvMailbox.payload16 = payload16; + XdrvMailbox.payload = payload; + XdrvMailbox.grpflg = grpflg; + XdrvMailbox.topic = command; + XdrvMailbox.data = dataBuf; + XdrvCall(FUNC_COMMAND); + } else if ((CMND_SETOPTION == command_code) && (index < 82)) { byte ptype; byte pindex; From 415ed97dab55c02fd1a6b4536bfa40befdaa47c4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 21 Sep 2018 11:15:42 +0200 Subject: [PATCH 0120/2222] 6.2.1.5 Add web authentication Add authentication to HTTP web pages --- sonoff/_changelog.ino | 5 +- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_02_webserver.ino | 107 ++++++++++++++--------------------- sonoff/xdrv_07_domoticz.ino | 6 +- sonoff/xdrv_09_timers.ino | 6 +- sonoff/xdrv_11_knx.ino | 10 ++-- 6 files changed, 56 insertions(+), 80 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index fdf73fdc7..aa6e8bfae 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.2.1.4 20180916 +/* 6.2.1.5 20180921 + * Add authentication to HTTP web pages + * + * 6.2.1.4 20180916 * Add command SerialSend5 to send raw serial data like "A5074100545293" * Update MCP230xx driver * Update Czech translation diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index f5f94dad1..43253e40f 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020104 +#define VERSION 0x06020105 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index 6cadb952f..5182b7051 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -29,8 +29,6 @@ uint8_t *efm8bb1_update = NULL; #endif // USE_RF_FLASH -#define D_TASMOTA_TOKEN "Tasmota-Token" - enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1 }; const char HTTP_HEAD[] PROGMEM = @@ -58,17 +56,13 @@ const char HTTP_HEAD[] PROGMEM = "eb('s1').value=l.innerText||l.textContent;" "eb('p1').focus();" "}" - "function lx(){" - "if(to==1){" - "if(tp<30){" - "tp++;" - "lt=setTimeout(lx,33);" // Wait for token from server - "}else{" - "lt=setTimeout(la,1355);" // Discard action and retry - "}" - "return;" + "function la(p){" + "var a='';" + "if(la.arguments.length==1){" + "a=p;" + "clearTimeout(lt);" "}" - "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1) + "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1) "x=new XMLHttpRequest();" "x.onreadystatechange=function(){" "if(x.readyState==4&&x.status==200){" @@ -76,32 +70,15 @@ const char HTTP_HEAD[] PROGMEM = "eb('l1').innerHTML=s;" "}" "};" - "x.open('GET','ay'+pc,true);" // Async request - "x.setRequestHeader('" D_TASMOTA_TOKEN "',to);" - "x.send();" // Perform command if available and get updated information - "pc='';" - "lt=setTimeout(la,2345-(tp*33));" - "}" - "function la(p){" - "if(la.arguments.length==1){" - "pc='?'+p;" - "clearTimeout(lt);" - "}else{pc='';}" - "to=1;tp=0;" - "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1) - "x=new XMLHttpRequest();" - "x.onreadystatechange=function(){" - "if(x.readyState==4&&x.status==200){to=x.getResponseHeader('" D_TASMOTA_TOKEN "');}else{to=1;}" - "};" - "x.open('GET','az',true);" // Async request - "x.send();" // Get token from server - "lx();" + "x.open('GET','ay'+a,true);" + "x.send();" + "lt=setTimeout(la,2345);" "}" "function lb(p){" - "la('d='+p);" + "la('?d='+p);" "}" "function lc(p){" - "la('c='+p);" + "la('?t='+p);" "}"; const char HTTP_HEAD_STYLE[] PROGMEM = @@ -340,7 +317,7 @@ const char HTTP_END[] PROGMEM = "" ""; -const char HTTP_DEVICE_CONTROL[] PROGMEM = ""; +const char HTTP_DEVICE_CONTROL[] PROGMEM = ""; const char HTTP_DEVICE_STATE[] PROGMEM = "%s%s"; // {c} = %'>
"), idx, idx); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), idx, idx); page += mqtt_data; } } @@ -634,34 +616,13 @@ void HandleRoot() } } -void HandleToken() -{ - char token[11]; - - ajax_token = random(2, 0x7FFFFFFF); - snprintf_P(token, sizeof(token), PSTR("%u"), ajax_token); - SetHeader(); - WebServer->sendHeader(FPSTR(HDR_TASMOTA_TOKEN), token); - snprintf_P(token, sizeof(token), PSTR("%u"), random(0x7FFFFFFF)); - WebServer->send(200, FPSTR(HDR_CTYPE_HTML), token); - - const char* header_key[] = { D_TASMOTA_TOKEN }; - WebServer->collectHeaders(header_key, 1); -} - void HandleAjaxStatusRefresh() { + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } + char svalue[80]; char tmp[100]; - if (WebServer->header(FPSTR(HDR_TASMOTA_TOKEN)).toInt() != ajax_token) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_FILE_NOT_FOUND)); - SetHeader(); - WebServer->send(404, FPSTR(HDR_CTYPE_PLAIN), mqtt_data); - return; - } - ajax_token = 1; - WebGetArg("o", tmp, sizeof(tmp)); if (strlen(tmp)) { ShowWebSource(SRC_WEBGUI); @@ -736,6 +697,7 @@ boolean HttpUser() void HandleConfiguration() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURATION); String page = FPSTR(HTTP_HEAD); @@ -759,6 +721,7 @@ void HandleConfiguration() void HandleModuleConfiguration() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } char stemp[20]; uint8_t midx; @@ -829,6 +792,7 @@ void HandleWifiConfiguration() void HandleWifi(boolean scan) { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); @@ -925,6 +889,7 @@ void HandleWifi(boolean scan) void HandleMqttConfiguration() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT); String page = FPSTR(HTTP_HEAD); @@ -948,6 +913,7 @@ void HandleMqttConfiguration() void HandleLoggingConfiguration() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_LOGGING); String page = FPSTR(HTTP_HEAD); @@ -995,6 +961,7 @@ void HandleLoggingConfiguration() void HandleOtherConfiguration() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_OTHER); char stemp[40]; @@ -1032,6 +999,7 @@ void HandleOtherConfiguration() void HandleBackupConfiguration() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_BACKUP_CONFIGURATION)); if (!SettingsBufferAlloc()) { return; } @@ -1067,6 +1035,7 @@ void HandleBackupConfiguration() void HandleSaveSettings() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } char stemp[TOPSZ]; char stemp2[TOPSZ]; @@ -1232,6 +1201,7 @@ void HandleSaveSettings() void HandleResetConfiguration() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } char svalue[33]; @@ -1252,6 +1222,7 @@ void HandleResetConfiguration() void HandleRestoreConfiguration() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTORE_CONFIGURATION); String page = FPSTR(HTTP_HEAD); @@ -1270,6 +1241,7 @@ void HandleRestoreConfiguration() void HandleInformation() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_INFORMATION); char stopic[TOPSZ]; @@ -1386,6 +1358,7 @@ void HandleInformation() void HandleUpgradeFirmware() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_FIRMWARE_UPGRADE); String page = FPSTR(HTTP_HEAD); @@ -1405,6 +1378,7 @@ void HandleUpgradeFirmware() void HandleUpgradeFirmwareStart() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } char svalue[100]; AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPGRADE_STARTED)); @@ -1432,6 +1406,7 @@ void HandleUpgradeFirmwareStart() void HandleUploadDone() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPLOAD_DONE)); char error[100]; @@ -1684,6 +1659,7 @@ void HandlePreflightRequest() void HandleHttpCommand() { if (HttpUser()) { return; } +// if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } char svalue[INPUT_BUFFER_SIZE]; // Large to serve Backlog AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_COMMAND)); @@ -1741,6 +1717,7 @@ void HandleHttpCommand() void HandleConsole() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONSOLE); String page = FPSTR(HTTP_HEAD); @@ -1756,6 +1733,7 @@ void HandleConsole() void HandleAjaxConsoleRefresh() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } char svalue[INPUT_BUFFER_SIZE]; // Large to serve Backlog byte cflg = 1; byte counter = 0; // Initial start, should never be 0 again @@ -1812,6 +1790,7 @@ void HandleAjaxConsoleRefresh() void HandleRestart() { if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTART); String page = FPSTR(HTTP_HEAD); diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index a7eb7708f..a30f79439 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -375,10 +375,8 @@ const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ; void HandleDomoticzConfiguration() { - if (HTTP_USER == webserver_state) { - HandleRoot(); - return; - } + if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_DOMOTICZ); char stemp[32]; diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 0652f3b53..66bf93614 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -676,10 +676,8 @@ const char S_CONFIGURE_TIMER[] PROGMEM = D_CONFIGURE_TIMER; void HandleTimerConfiguration() { - if (HTTP_USER == webserver_state) { - HandleRoot(); - return; - } + if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TIMER); String page = FPSTR(HTTP_HEAD); diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 3897caac7..88260b23c 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -803,15 +803,13 @@ const char HTTP_FORM_KNX_ADD_TABLE_ROW2[] PROGMEM = void HandleKNXConfiguration() { + if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_KNX); + char tmp[100]; String stmp; - if (HTTP_USER == webserver_state) { - HandleRoot(); - return; - } - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_KNX); - if ( WebServer->hasArg("save") ) { KNX_Save_Settings(); HandleConfiguration(); From 4065a215f05173230ce3f5c2e8a56f0b5c2984e0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 21 Sep 2018 15:22:17 +0200 Subject: [PATCH 0121/2222] Add Shelly2 Energy Monitoring Add energy monitoring to Shelly2 (#2789) --- sonoff/_changelog.ino | 1 + sonoff/i18n.h | 7 +- sonoff/settings.h | 8 +- sonoff/user_config.h | 1 + sonoff/xdrv_03_energy.ino | 8 +- sonoff/xnrg_04_mcp39f501.ino | 594 ++++++++++++++++++++++++++++++----- 6 files changed, 530 insertions(+), 89 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index aa6e8bfae..72293c30d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.2.1.5 20180921 * Add authentication to HTTP web pages + * Add energy monitoring to Shelly2 (#2789) * * 6.2.1.4 20180916 * Add command SerialSend5 to send raw serial data like "A5074100545293" diff --git a/sonoff/i18n.h b/sonoff/i18n.h index da47371d8..4ea5ab3fe 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -292,6 +292,7 @@ #define D_CMND_VOLTAGESET "VoltageSet" #define D_CMND_CURRENTCAL "CurrentCal" #define D_CMND_CURRENTSET "CurrentSet" +#define D_CMND_FREQUENCYSET "FrequencySet" #define D_CMND_MAXPOWER "MaxPower" #define D_CMND_MAXPOWERHOLD "MaxPowerHold" #define D_CMND_MAXPOWERWINDOW "MaxPowerWindow" @@ -419,7 +420,8 @@ enum UnitNames { UNIT_SECTORS, UNIT_VOLT, UNIT_WATT, - UNIT_WATTHOUR }; + UNIT_WATTHOUR, + UNIT_HERTZ }; const char kUnitNames[] PROGMEM = D_UNIT_AMPERE "|" D_UNIT_HOUR "|" @@ -439,7 +441,8 @@ const char kUnitNames[] PROGMEM = D_UNIT_SECTORS "|" D_UNIT_VOLT "|" D_UNIT_WATT "|" - D_UNIT_WATTHOUR ; + D_UNIT_WATTHOUR "|" + "d" D_UNIT_HERTZ ; const char S_JSON_COMMAND_NVALUE_SPACE_UNIT[] PROGMEM = "{\"%s\":\"%d %s\"}"; const char S_JSON_COMMAND_LVALUE_SPACE_UNIT[] PROGMEM = "{\"%s\":\"%lu %s\"}"; diff --git a/sonoff/settings.h b/sonoff/settings.h index a1fd218ac..7da610891 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -322,9 +322,13 @@ struct SYSCFG { uint16_t mcp230xx_int_timer; // 718 - byte free_71A[180]; // 71A + byte free_71A[174]; // 71A - char mems[MAX_RULE_MEMS][10]; // 7CE + unsigned long energy_frequency_calibration; // 7C8 + + byte free_7CC[2]; // 7CC + + char mems[MAX_RULE_MEMS][10]; // 7CE // 800 Full - no more free locations char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 20339b5f6..ef3e66fc2 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -348,6 +348,7 @@ // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) #define USE_PZEM2 // Add support for PZEM003,014,016,017 Energy monitor (+1k1 code) +#define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k2 code) // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index aa589efab..068261971 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -29,14 +29,14 @@ enum EnergyCommands { CMND_POWERDELTA, CMND_POWERLOW, CMND_POWERHIGH, CMND_VOLTAGELOW, CMND_VOLTAGEHIGH, CMND_CURRENTLOW, CMND_CURRENTHIGH, - CMND_POWERCAL, CMND_POWERSET, CMND_VOLTAGECAL, CMND_VOLTAGESET, CMND_CURRENTCAL, CMND_CURRENTSET, + CMND_POWERCAL, CMND_POWERSET, CMND_VOLTAGECAL, CMND_VOLTAGESET, CMND_CURRENTCAL, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_ENERGYRESET, CMND_MAXENERGY, CMND_MAXENERGYSTART, CMND_MAXPOWER, CMND_MAXPOWERHOLD, CMND_MAXPOWERWINDOW, CMND_SAFEPOWER, CMND_SAFEPOWERHOLD, CMND_SAFEPOWERWINDOW }; const char kEnergyCommands[] PROGMEM = D_CMND_POWERDELTA "|" D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|" - D_CMND_POWERCAL "|" D_CMND_POWERSET "|" D_CMND_VOLTAGECAL "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTCAL "|" D_CMND_CURRENTSET "|" + D_CMND_POWERCAL "|" D_CMND_POWERSET "|" D_CMND_VOLTAGECAL "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTCAL "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" 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 ; @@ -451,6 +451,10 @@ boolean EnergyCommand() nvalue = Settings.energy_current_calibration; unit = UNIT_MICROSECOND; } + else if ((CMND_FREQUENCYSET == command_code) && XnrgCall(FUNC_COMMAND)) { // dHz + nvalue = Settings.energy_frequency_calibration; + unit = UNIT_HERTZ; + } #if FEATURE_POWER_LIMIT else if (CMND_MAXPOWER == command_code) { diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index f74111f9d..a9620ce50 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -26,56 +26,383 @@ * and https://github.com/OLIMEX/olimex-iot-firmware-esp8266/blob/7a7f9bb56d4b72770dba8d0f18eaa9d956dd0baf/olimex/user/modules/mod_emtr.c \*********************************************************************************************/ -#define XNRG_04 4 +#define XNRG_04 4 -#define MCP_START_FRAME 0xA5 -#define MCP_ACK_FRAME 0x06 -#define MCP_ERROR_NAK 0x15 -#define MCP_ERROR_CRC 0x51 +#define MCP_TIMEOUT 4 -#define MCP_SINGLE_WIRE 0xAB +#define MCP_START_FRAME 0xA5 +#define MCP_ACK_FRAME 0x06 +#define MCP_ERROR_NAK 0x15 +#define MCP_ERROR_CRC 0x51 -#define MCP_SET_ADDRESS 0x41 +#define MCP_SINGLE_WIRE 0xAB -#define MCP_READ 0x4E -#define MCP_READ_16 0x52 -#define MCP_READ_32 0x44 +#define MCP_SET_ADDRESS 0x41 -#define MCP_WRITE 0x4D -#define MCP_WRITE_16 0x57 -#define MCP_WRITE_32 0x45 +#define MCP_READ 0x4E +#define MCP_READ_16 0x52 +#define MCP_READ_32 0x44 -#define MCP_SAVE_REGISTERS 0x53 +#define MCP_WRITE 0x4D +#define MCP_WRITE_16 0x57 +#define MCP_WRITE_32 0x45 -#define MCP_FLASH_READ 0x42 -#define MCP_FLASH_WRITE 0x50 +#define MCP_SAVE_REGISTERS 0x53 -uint32 mcp_system_configuration = 0x03000000; +#define MCP_CALIBRATION_BASE 0x0028 +#define MCP_CALIBRATION_LEN 52 + +#define MCP_FREQUENCY_REF_BASE 0x0094 +#define MCP_FREQUENCY_GAIN_BASE 0x00AE +#define MCP_FREQUENCY_LEN 4 + +#define EMTR_OUT_BASE 0x0004 +#define EMTR_OUT_LEN 28 + +#define MCP_FLASH_READ 0x42 +#define MCP_FLASH_WRITE 0x50 + +typedef struct mcp_calibration_registers_type { + uint16_t gain_current_rms; + uint16_t gain_voltage_rms; + uint16_t gain_active_power; + uint16_t gain_reactive_power; + sint32_t offset_current_rms; + sint32_t offset_active_power; + sint32_t offset_reactive_power; + sint16_t dc_offset_current; + sint16_t phase_compensation; + uint16_t apparent_power_divisor; + + uint32_t system_configuration; + uint16_t dio_configuration; + uint32_t range; + + uint32_t calibration_current; + uint16_t calibration_voltage; + uint32_t calibration_active_power; + uint32_t calibration_reactive_power; + uint16_t accumulation_interval; +} mcp_calibration_registers_type; +mcp_calibration_registers_type mcp_calibration_registers; + +typedef struct mcp_calibration_setpoint_type { + uint32_t calibration_current; + uint16_t calibration_voltage; + uint32_t calibration_active_power; + uint32_t calibration_reactive_power; + uint16_t line_frequency_ref; +} mcp_calibration_setpoint_type; +mcp_calibration_setpoint_type mcp_calibration_setpoint; + +typedef struct mcp_frequency_registers_type { + uint16_t line_frequency_ref; + uint16_t gain_line_frequency; +} mcp_frequency_registers_type; +mcp_frequency_registers_type mcp_frequency_registers; + +typedef struct mcp_output_registers_type { + uint32_t current_rms; + uint16_t voltage_rms; + uint32_t active_power; + uint32_t reactive_power; + uint32_t apparent_power; + sint16_t power_factor; + uint16_t line_frequency; + uint16_t thermistor_voltage; + uint16_t event_flag; + uint16_t system_status; +} mcp_output_registers_type; +mcp_output_registers_type mcp_output_registers; + +uint32_t mcp_system_configuration = 0x03000000; +uint16_t mcp_address = 0; uint8_t mcp_single_wire_active = 0; +uint8_t mcp_calibration_active = 0; +uint8_t mcp_init = 0; +uint8_t mcp_timeout = 0; +unsigned long mcp_kWhcounter = 0; /*********************************************************************************************\ * Olimex tools * https://github.com/OLIMEX/olimex-iot-firmware-esp8266/blob/7a7f9bb56d4b72770dba8d0f18eaa9d956dd0baf/olimex/user/modules/mod_emtr.c \*********************************************************************************************/ +uint8_t McpChecksum(uint8_t *data) +{ + uint8_t checksum = 0; + uint8_t offset = 0; + uint8_t len = data[1] -1; -unsigned long McpExtractInt(uint8_t *data, uint8_t offset, uint8_t size) + if (MCP_SINGLE_WIRE == data[0]) { + offset = 3; + len = 15; + } + for (byte i = offset; i < len; i++) { checksum += data[i]; } + return (MCP_SINGLE_WIRE == data[0]) ? ~checksum : checksum; +} + +unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size) { unsigned long result = 0; unsigned long pow = 1; for (byte i = 0; i < size; i++) { - result = result + data[offset + i] * pow; + result = result + (uint8_t)data[offset + i] * pow; pow = pow * 256; } return result; } -void McpSetSystemConfiguration(uint16 interval) +void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size) { + for (byte i = 0; i < size; i++) { + data[offset + i] = ((value >> (i * 8)) & 0xFF); + } +} + +void AddLogSerialSend(byte loglevel, uint8_t *buffer, int count) +{ + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SERIAL "Send")); + for (int i = 0; i < count; i++) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, *(buffer++)); + } + AddLog(loglevel); +} + + +void McpSend(uint8_t *data) +{ + if (mcp_timeout) { return; } + mcp_timeout = MCP_TIMEOUT; + + data[0] = MCP_START_FRAME; + data[data[1] -1] = McpChecksum(data); + +// AddLogSerialSend(LOG_LEVEL_DEBUG_MORE, data, data[1]); + + for (byte i = 0; i < data[1]; i++) { + Serial.write(data[i]); + } +} + +uint32_t McpGetRange(uint8_t shift) +{ + return (mcp_calibration_registers.range >> shift) & 0xFF; +} + +void McpSetRange(uint8_t shift, uint32_t range) +{ + uint32_t old_range = McpGetRange(shift); + mcp_calibration_registers.range = mcp_calibration_registers.range ^ (old_range << shift); + mcp_calibration_registers.range = mcp_calibration_registers.range | (range << shift); +} + +bool McpCalibrationCalc(uint8_t range_shift) +{ + uint32_t measured; + uint32_t expected; + uint16_t *gain; + uint32_t new_gain; + + if (range_shift == 0) { + measured = mcp_output_registers.voltage_rms; + expected = mcp_calibration_registers.calibration_voltage; + gain = &(mcp_calibration_registers.gain_voltage_rms); + } else if (range_shift == 8) { + measured = mcp_output_registers.current_rms; + expected = mcp_calibration_registers.calibration_current; + gain = &(mcp_calibration_registers.gain_current_rms); + } else if (range_shift == 16) { + measured = mcp_output_registers.active_power; + expected = mcp_calibration_registers.calibration_active_power; + gain = &(mcp_calibration_registers.gain_active_power); + } else { + return false; + } + + if (measured == 0) { + return false; + } + + uint32_t range = McpGetRange(range_shift); + +calc: + new_gain = (*gain) * expected / measured; + + if (new_gain < 25000) { + range++; + if (measured > 6) { + measured = measured / 2; + goto calc; + } + } + + if (new_gain > 55000) { + range--; + measured = measured * 2; + goto calc; + } + + *gain = new_gain; + McpSetRange(range_shift, range); + + return true; +} + +void McpCalibrationReactivePower() +{ + mcp_calibration_registers.gain_reactive_power = mcp_calibration_registers.gain_reactive_power * mcp_calibration_setpoint.calibration_reactive_power / mcp_output_registers.reactive_power; +} + +void McpCalibrationLineFreqency() +{ + mcp_frequency_registers.gain_line_frequency = mcp_frequency_registers.gain_line_frequency * mcp_frequency_registers.line_frequency_ref / mcp_output_registers.line_frequency; +} + +void McpResetSetpoints() +{ + mcp_calibration_setpoint.calibration_active_power = 0; + mcp_calibration_setpoint.calibration_voltage = 0; + mcp_calibration_setpoint.calibration_current = 0; + mcp_calibration_setpoint.calibration_reactive_power = 0; + mcp_calibration_setpoint.line_frequency_ref = 0; +} + +/********************************************************************************************/ + +void McpGetAddress() +{ + // A5 07 41 00 26 52 65 + uint8_t data[7]; + + data[1] = sizeof(data); + data[2] = MCP_SET_ADDRESS; // Set address pointer + data[3] = 0x00; // address + data[4] = 0x26; // address + data[5] = MCP_READ_16; // Read 2 bytes + + McpSend(data); + + // Receives 06 05 004D 58 +} + +void McpGetCalibration() +{ + if (mcp_calibration_active) { return; } + mcp_calibration_active = 4; + + // A5 08 41 00 28 4E 34 98 + uint8_t data[8]; + + data[1] = sizeof(data); + data[2] = MCP_SET_ADDRESS; // Set address pointer + data[3] = (MCP_CALIBRATION_BASE >> 8) & 0xFF; // address + data[4] = (MCP_CALIBRATION_BASE >> 0) & 0xFF; // address + data[5] = MCP_READ; // Read N bytes + data[6] = MCP_CALIBRATION_LEN; + + McpSend(data); + + // Receives 06 37 C882 B6AD 0781 9273 06000000 00000000 00000000 0000 D3FF 0300 00000003 9204 120C1300 204E0000 9808 E0AB0000 D9940000 0200 24 +} + +void McpSetCalibration() +{ + uint8_t data[7 + MCP_CALIBRATION_LEN + 2 + 1]; + + data[1] = sizeof(data); + data[2] = MCP_SET_ADDRESS; // Set address pointer + data[3] = (MCP_CALIBRATION_BASE >> 8) & 0xFF; // address + data[4] = (MCP_CALIBRATION_BASE >> 0) & 0xFF; // address + + data[5] = MCP_WRITE; // Write N bytes + data[6] = MCP_CALIBRATION_LEN; + + McpSetInt(mcp_calibration_registers.gain_current_rms, data, 0+7, 2); + McpSetInt(mcp_calibration_registers.gain_voltage_rms, data, 2+7, 2); + McpSetInt(mcp_calibration_registers.gain_active_power, data, 4+7, 2); + McpSetInt(mcp_calibration_registers.gain_reactive_power, data, 6+7, 2); + McpSetInt(mcp_calibration_registers.offset_current_rms, data, 8+7, 4); + McpSetInt(mcp_calibration_registers.offset_active_power, data, 12+7, 4); + McpSetInt(mcp_calibration_registers.offset_reactive_power, data, 16+7, 4); + McpSetInt(mcp_calibration_registers.dc_offset_current, data, 20+7, 2); + McpSetInt(mcp_calibration_registers.phase_compensation, data, 22+7, 2); + McpSetInt(mcp_calibration_registers.apparent_power_divisor, data, 24+7, 2); + + McpSetInt(mcp_calibration_registers.system_configuration, data, 26+7, 4); + McpSetInt(mcp_calibration_registers.dio_configuration, data, 30+7, 2); + McpSetInt(mcp_calibration_registers.range, data, 32+7, 4); + + McpSetInt(mcp_calibration_registers.calibration_current, data, 36+7, 4); + McpSetInt(mcp_calibration_registers.calibration_voltage, data, 40+7, 2); + McpSetInt(mcp_calibration_registers.calibration_active_power, data, 42+7, 4); + McpSetInt(mcp_calibration_registers.calibration_reactive_power, data, 46+7, 4); + McpSetInt(mcp_calibration_registers.accumulation_interval, data, 50+7, 2); + + data[MCP_CALIBRATION_LEN+7] = MCP_SAVE_REGISTERS; // Save registers to flash + data[MCP_CALIBRATION_LEN+8] = mcp_address; // Device address + + McpSend(data); +} + +void McpGetFrequency() +{ + if (mcp_calibration_active) { return; } + mcp_calibration_active = 4; + + // A5 0B 41 00 94 52 41 00 AE 52 18 + uint8_t data[11]; + + data[1] = sizeof(data); + data[2] = MCP_SET_ADDRESS; // Set address pointer + data[3] = (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF; // address + data[4] = (MCP_FREQUENCY_REF_BASE >> 0) & 0xFF; // address + + data[5] = MCP_READ_16; // Read register + + data[6] = MCP_SET_ADDRESS; // Set address pointer + data[7] = (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF; // address + data[8] = (MCP_FREQUENCY_GAIN_BASE >> 0) & 0xFF; // address + + data[9] = MCP_READ_16; // Read register + + McpSend(data); +} + +void McpSetFrequency() +{ + // A5 11 41 00 94 57 C3 B4 41 00 AE 57 7E 46 53 4D 03 + uint8_t data[17]; + + data[ 1] = sizeof(data); + data[ 2] = MCP_SET_ADDRESS; // Set address pointer + data[ 3] = (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF; // address + data[ 4] = (MCP_FREQUENCY_REF_BASE >> 0) & 0xFF; // address + + data[ 5] = MCP_WRITE_16; // Write register + data[ 6] = (mcp_frequency_registers.line_frequency_ref >> 8) & 0xFF; // line_frequency_ref high + data[ 7] = (mcp_frequency_registers.line_frequency_ref >> 0) & 0xFF; // line_frequency_ref low + + data[ 8] = MCP_SET_ADDRESS; // Set address pointer + data[ 9] = (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF; // address + data[10] = (MCP_FREQUENCY_GAIN_BASE >> 0) & 0xFF; // address + + data[11] = MCP_WRITE_16; // Write register + data[12] = (mcp_frequency_registers.gain_line_frequency >> 8) & 0xFF; // gain_line_frequency high + data[13] = (mcp_frequency_registers.gain_line_frequency >> 0) & 0xFF; // gain_line_frequency low + + data[14] = MCP_SAVE_REGISTERS; // Save registers to flash + data[15] = mcp_address; // Device address + + McpSend(data); +} + +void McpSetSystemConfiguration(uint16 interval) +{ + // A5 11 41 00 42 45 03 00 01 00 41 00 5A 57 00 06 7A uint8_t data[17]; - data[ 0] = MCP_START_FRAME; data[ 1] = sizeof(data); data[ 2] = MCP_SET_ADDRESS; // Set address pointer data[ 3] = 0x00; // address @@ -91,14 +418,8 @@ void McpSetSystemConfiguration(uint16 interval) data[13] = MCP_WRITE_16; // Write 2 bytes data[14] = (interval >> 8) & 0xFF; // interval data[15] = (interval >> 0) & 0xFF; // interval - uint8_t checksum = 0; - for (byte i = 0; i < sizeof(data) -1; i++) { checksum += (uint8_t)data[i]; } - data[16] = checksum; - // A5 11 41 00 42 45 03 00 01 00 41 00 5A 57 00 06 7A - AddLogSerial(LOG_LEVEL_DEBUG, data, sizeof(data)); - - for (byte i = 0; i < sizeof(data); i++) { Serial.write(data[i]); } + McpSend(data); } void McpSingleWireStart() @@ -109,9 +430,9 @@ void McpSingleWireStart() mcp_single_wire_active = 1; } -void McpSingleWireStop() +void McpSingleWireStop(uint8_t force) { - if ((mcp_system_configuration & (1 << 8)) == 0) { return; } + if (!force && ((mcp_system_configuration & (1 << 8)) == 0)) { return; } mcp_system_configuration = mcp_system_configuration & (~(1 << 8)); McpSetSystemConfiguration(2); // 4 mcp_single_wire_active = 0; @@ -119,10 +440,69 @@ void McpSingleWireStop() /********************************************************************************************/ -unsigned long mcp_current = 0; -unsigned long mcp_voltage = 0; -unsigned long mcp_power = 0; -unsigned long mcp_frequency = 0; +void McpAddressReceive() +{ + // 06 05 004D 58 + mcp_address = serial_in_buffer[2] * 256 + serial_in_buffer[3]; +} + +void McpParseCalibration() +{ + bool action = false; + + // 06 37 C882 B6AD 0781 9273 06000000 00000000 00000000 0000 D3FF 0300 00000003 9204 120C1300 204E0000 9808 E0AB0000 D9940000 0200 24 + mcp_calibration_registers.gain_current_rms = McpExtractInt(serial_in_buffer, 2, 2); + mcp_calibration_registers.gain_voltage_rms = McpExtractInt(serial_in_buffer, 4, 2); + mcp_calibration_registers.gain_active_power = McpExtractInt(serial_in_buffer, 6, 2); + mcp_calibration_registers.gain_reactive_power = McpExtractInt(serial_in_buffer, 8, 2); + mcp_calibration_registers.offset_current_rms = McpExtractInt(serial_in_buffer, 10, 4); + mcp_calibration_registers.offset_active_power = McpExtractInt(serial_in_buffer, 14, 4); + mcp_calibration_registers.offset_reactive_power = McpExtractInt(serial_in_buffer, 18, 4); + mcp_calibration_registers.dc_offset_current = McpExtractInt(serial_in_buffer, 22, 2); + mcp_calibration_registers.phase_compensation = McpExtractInt(serial_in_buffer, 24, 2); + mcp_calibration_registers.apparent_power_divisor = McpExtractInt(serial_in_buffer, 26, 2); + + mcp_calibration_registers.system_configuration = McpExtractInt(serial_in_buffer, 28, 4); + mcp_calibration_registers.dio_configuration = McpExtractInt(serial_in_buffer, 32, 2); + mcp_calibration_registers.range = McpExtractInt(serial_in_buffer, 34, 4); + + mcp_calibration_registers.calibration_current = McpExtractInt(serial_in_buffer, 38, 4); + mcp_calibration_registers.calibration_voltage = McpExtractInt(serial_in_buffer, 42, 2); + mcp_calibration_registers.calibration_active_power = McpExtractInt(serial_in_buffer, 44, 4); + mcp_calibration_registers.calibration_reactive_power = McpExtractInt(serial_in_buffer, 48, 4); + mcp_calibration_registers.accumulation_interval = McpExtractInt(serial_in_buffer, 52, 2); + + if (mcp_calibration_setpoint.calibration_active_power) { + mcp_calibration_registers.calibration_active_power = mcp_calibration_setpoint.calibration_active_power; + if (McpCalibrationCalc(16)) { action = true; } + } + if (mcp_calibration_setpoint.calibration_voltage) { + mcp_calibration_registers.calibration_voltage = mcp_calibration_setpoint.calibration_voltage; + if (McpCalibrationCalc(0)) { action = true; } + } + if (mcp_calibration_setpoint.calibration_current) { + mcp_calibration_registers.calibration_current = mcp_calibration_setpoint.calibration_current; + if (McpCalibrationCalc(8)) { action = true; } + } + mcp_timeout = 0; + if (action) { McpSetCalibration(); } + McpResetSetpoints(); +} + +void McpParseFrequency() +{ + // 06 07 C350 8000 A0 + mcp_frequency_registers.line_frequency_ref = serial_in_buffer[2] * 256 + serial_in_buffer[3]; + mcp_frequency_registers.gain_line_frequency = serial_in_buffer[4] * 256 + serial_in_buffer[5]; + + if (mcp_calibration_setpoint.line_frequency_ref) { + mcp_frequency_registers.line_frequency_ref = mcp_calibration_setpoint.line_frequency_ref; + McpCalibrationLineFreqency(); + mcp_timeout = 0; + McpSetFrequency(); + } + McpResetSetpoints(); +} void McpParseData(uint8_t single_wire) { @@ -131,29 +511,31 @@ void McpParseData(uint8_t single_wire) // AB CD EF 51 06 00 00 B8 08 FC 0D 00 00 0A C4 11 // Header-- Current---- Volt- Power------ Freq- Ck - mcp_current = McpExtractInt((uint8_t*)serial_in_buffer, 3, 4); - mcp_voltage = McpExtractInt((uint8_t*)serial_in_buffer, 7, 2); - mcp_power = McpExtractInt((uint8_t*)serial_in_buffer, 9, 4); - mcp_frequency = McpExtractInt((uint8_t*)serial_in_buffer, 13, 2); + mcp_output_registers.current_rms = McpExtractInt(serial_in_buffer, 3, 4); + mcp_output_registers.voltage_rms = McpExtractInt(serial_in_buffer, 7, 2); + mcp_output_registers.active_power = McpExtractInt(serial_in_buffer, 9, 4); + mcp_output_registers.line_frequency = McpExtractInt(serial_in_buffer, 13, 2); } else { // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // 06 19 61 06 00 00 FE 08 9B 0E 00 00 0B 00 00 00 97 0E 00 00 FF 7F 0C C6 35 + // 06 19 CE 18 00 00 F2 08 3A 38 00 00 66 00 00 00 93 38 00 00 36 7F 9A C6 B7 // Ak Ln Current---- Volt- ActivePower ReActivePow ApparentPow Factr Frequ Ck - mcp_current = McpExtractInt((uint8_t*)serial_in_buffer, 2, 4); - mcp_voltage = McpExtractInt((uint8_t*)serial_in_buffer, 6, 2); - mcp_power = McpExtractInt((uint8_t*)serial_in_buffer, 8, 4); - mcp_frequency = McpExtractInt((uint8_t*)serial_in_buffer, 22, 2); + mcp_output_registers.current_rms = McpExtractInt(serial_in_buffer, 2, 4); + mcp_output_registers.voltage_rms = McpExtractInt(serial_in_buffer, 6, 2); + mcp_output_registers.active_power = McpExtractInt(serial_in_buffer, 8, 4); + mcp_output_registers.reactive_power = McpExtractInt(serial_in_buffer, 12, 4); + mcp_output_registers.line_frequency = McpExtractInt(serial_in_buffer, 22, 2); } if (energy_power_on) { // Powered on - energy_frequency = (float)mcp_frequency / 1000; - energy_voltage = (float)mcp_voltage / 10; - energy_power = (float)mcp_power / 100; + energy_frequency = (float)mcp_output_registers.line_frequency / 1000; + energy_voltage = (float)mcp_output_registers.voltage_rms / 10; + energy_power = (float)mcp_output_registers.active_power / 100; if (0 == energy_power) { energy_current = 0; } else { - energy_current = (float)mcp_current / 10000; + energy_current = (float)mcp_output_registers.current_rms / 10000; } } else { // Powered off energy_frequency = 0; @@ -165,61 +547,85 @@ void McpParseData(uint8_t single_wire) bool McpSerialInput() { - Settings.flag.mqtt_serial = 0; // Disable possible SerialReceive handling - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (MCP_ERROR_CRC == serial_in_buffer[0]) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Send " D_CHECKSUM_FAILURE)); - return 1; + unsigned long start = millis(); + while (millis() - start < 20) { + yield(); + if (Serial.available()) { + serial_in_buffer[serial_in_byte_counter++] = Serial.read(); + start = millis(); + } + } + + AddLogSerial(LOG_LEVEL_DEBUG_MORE); + + if (1 == serial_in_byte_counter) { + if (MCP_ERROR_CRC == serial_in_buffer[0]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Send " D_CHECKSUM_FAILURE)); + mcp_timeout = 0; + } + else if (MCP_ERROR_NAK == serial_in_buffer[0]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: NAck")); + mcp_timeout = 0; + } } else if (MCP_ACK_FRAME == serial_in_buffer[0]) { - if ((serial_in_byte_counter > 1) && (serial_in_byte_counter == serial_in_buffer[1])) { + if (serial_in_byte_counter == serial_in_buffer[1]) { - AddLogSerial(LOG_LEVEL_DEBUG_MORE); - - uint8_t checksum = 0; - for (byte i = 0; i < serial_in_byte_counter -1; i++) { checksum += (uint8_t)serial_in_buffer[i]; } - if (checksum != serial_in_buffer[serial_in_byte_counter -1]) { + if (McpChecksum((uint8_t *)serial_in_buffer) != serial_in_buffer[serial_in_byte_counter -1]) { AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); } else { + if (5 == serial_in_buffer[1]) { McpAddressReceive(); } if (25 == serial_in_buffer[1]) { McpParseData(0); } + if (MCP_CALIBRATION_LEN + 3 == serial_in_buffer[1]) { McpParseCalibration(); } + if (MCP_FREQUENCY_LEN + 3 == serial_in_buffer[1]) { McpParseFrequency(); } } - return 1; + } + mcp_timeout = 0; } else if (MCP_SINGLE_WIRE == serial_in_buffer[0]) { if (serial_in_byte_counter == 16) { - AddLogSerial(LOG_LEVEL_DEBUG_MORE); - - uint8_t checksum = 0; - for (byte i = 3; i < serial_in_byte_counter -1; i++) { checksum += (uint8_t)serial_in_buffer[i]; } -// if (~checksum != serial_in_buffer[serial_in_byte_counter -1]) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); -// } else { + if (McpChecksum((uint8_t *)serial_in_buffer) != serial_in_buffer[serial_in_byte_counter -1]) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); + } else { McpParseData(1); -// } - return 1; + } + } + mcp_timeout = 0; } - else { - return 1; - } - serial_in_byte = 0; // Discard - return 0; + return 1; } /********************************************************************************************/ void McpEverySecond() { - if (!mcp_single_wire_active) { - char get_state[] = "A5084100044E1656"; - SerialSendRaw(get_state, sizeof(get_state)); + uint8_t get_state[] = { 0xA5, 0x08, 0x41, 0x00, 0x04, 0x4E, 0x16, 0x00 }; + + if (mcp_timeout) { + mcp_timeout--; + } + else if (mcp_calibration_active) { + mcp_calibration_active--; + } + else if (mcp_init) { + McpSingleWireStop(1); + mcp_init = 0; + } + else if (!mcp_address) { + McpGetAddress(); + } + else if (!mcp_single_wire_active) { + McpSend(get_state); } - energy_kWhtoday += (energy_power / 36); - EnergyUpdateToday(); + if (mcp_output_registers.active_power) { + energy_kWhtoday_delta += ((mcp_output_registers.active_power * 10) / 36); + EnergyUpdateToday(); + } } void McpSnsInit() @@ -235,6 +641,9 @@ void McpDrvInit() digitalWrite(15, 0); // GPIO15 - MCP disable - Reset Delta Sigma ADC's baudrate = 4800; energy_calc_power_factor = 1; // Calculate power factor from data + mcp_timeout = 4; // Wait for initialization + mcp_init = 1; // Execute initial setup + McpResetSetpoints(); energy_flg = XNRG_04; } } @@ -246,20 +655,39 @@ boolean McpCommand() if ((CMND_POWERCAL == energy_command_code) || (CMND_VOLTAGECAL == energy_command_code) || (CMND_CURRENTCAL == energy_command_code)) { + // MCP Debug commands - PowerCal + if (1 == XdrvMailbox.payload) { McpSingleWireStart(); } + if (2 == XdrvMailbox.payload) { McpSingleWireStop(0); } + if (3 == XdrvMailbox.payload) { McpGetAddress(); } + + serviced = false; } else if (CMND_POWERSET == energy_command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3601) && power_cycle) { -// Settings.energy_power_calibration = (XdrvMailbox.payload * power_cycle) / CSE_PREF; + if (XdrvMailbox.data_len && mcp_output_registers.active_power) { + Settings.energy_power_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * 100); + mcp_calibration_setpoint.calibration_active_power = Settings.energy_power_calibration; + McpGetCalibration(); } } else if (CMND_VOLTAGESET == energy_command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 501) && voltage_cycle) { -// Settings.energy_voltage_calibration = (XdrvMailbox.payload * voltage_cycle) / CSE_UREF; + if (XdrvMailbox.data_len && mcp_output_registers.voltage_rms) { + Settings.energy_voltage_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * 10); + mcp_calibration_setpoint.calibration_voltage = Settings.energy_voltage_calibration; + McpGetCalibration(); } } else if (CMND_CURRENTSET == energy_command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 16001) && current_cycle) { -// Settings.energy_current_calibration = (XdrvMailbox.payload * current_cycle) / 1000; + if (XdrvMailbox.data_len && mcp_output_registers.current_rms) { + Settings.energy_current_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * 10); + mcp_calibration_setpoint.calibration_current = Settings.energy_current_calibration; + McpGetCalibration(); + } + } + else if (CMND_FREQUENCYSET == energy_command_code) { + if (XdrvMailbox.data_len && mcp_output_registers.line_frequency) { + Settings.energy_frequency_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * 10); + mcp_calibration_setpoint.line_frequency_ref = Settings.energy_frequency_calibration; + McpGetFrequency(); } } else serviced = false; // Unknown command From f7a8b1f9234ee628596b0b00d3736753016cae3b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 21 Sep 2018 16:02:56 +0200 Subject: [PATCH 0122/2222] Shelly2 clean up Shelly2 clean up --- sonoff/i18n.h | 2 +- sonoff/user_config.h | 2 +- sonoff/xdrv_03_energy.ino | 2 +- sonoff/xnrg_04_mcp39f501.ino | 36 ++++++++++-------------------------- 4 files changed, 13 insertions(+), 29 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 4ea5ab3fe..b0a7ec071 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -442,7 +442,7 @@ const char kUnitNames[] PROGMEM = D_UNIT_VOLT "|" D_UNIT_WATT "|" D_UNIT_WATTHOUR "|" - "d" D_UNIT_HERTZ ; + D_UNIT_HERTZ ; const char S_JSON_COMMAND_NVALUE_SPACE_UNIT[] PROGMEM = "{\"%s\":\"%d %s\"}"; const char S_JSON_COMMAND_LVALUE_SPACE_UNIT[] PROGMEM = "{\"%s\":\"%lu %s\"}"; diff --git a/sonoff/user_config.h b/sonoff/user_config.h index ef3e66fc2..438983a66 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -348,7 +348,7 @@ // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) #define USE_PZEM2 // Add support for PZEM003,014,016,017 Energy monitor (+1k1 code) -#define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k2 code) +#define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 068261971..860183f49 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -451,7 +451,7 @@ boolean EnergyCommand() nvalue = Settings.energy_current_calibration; unit = UNIT_MICROSECOND; } - else if ((CMND_FREQUENCYSET == command_code) && XnrgCall(FUNC_COMMAND)) { // dHz + else if ((CMND_FREQUENCYSET == command_code) && XnrgCall(FUNC_COMMAND)) { // Hz nvalue = Settings.energy_frequency_calibration; unit = UNIT_HERTZ; } diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index a9620ce50..c34846edf 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -56,12 +56,6 @@ #define MCP_FREQUENCY_GAIN_BASE 0x00AE #define MCP_FREQUENCY_LEN 4 -#define EMTR_OUT_BASE 0x0004 -#define EMTR_OUT_LEN 28 - -#define MCP_FLASH_READ 0x42 -#define MCP_FLASH_WRITE 0x50 - typedef struct mcp_calibration_registers_type { uint16_t gain_current_rms; uint16_t gain_voltage_rms; @@ -161,16 +155,6 @@ void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size) } } -void AddLogSerialSend(byte loglevel, uint8_t *buffer, int count) -{ - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SERIAL "Send")); - for (int i = 0; i < count; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, *(buffer++)); - } - AddLog(loglevel); -} - - void McpSend(uint8_t *data) { if (mcp_timeout) { return; } @@ -179,7 +163,7 @@ void McpSend(uint8_t *data) data[0] = MCP_START_FRAME; data[data[1] -1] = McpChecksum(data); -// AddLogSerialSend(LOG_LEVEL_DEBUG_MORE, data, data[1]); +// AddLogSerial(LOG_LEVEL_DEBUG_MORE, data, data[1]); for (byte i = 0; i < data[1]; i++) { Serial.write(data[i]); @@ -252,7 +236,7 @@ calc: void McpCalibrationReactivePower() { - mcp_calibration_registers.gain_reactive_power = mcp_calibration_registers.gain_reactive_power * mcp_calibration_setpoint.calibration_reactive_power / mcp_output_registers.reactive_power; + mcp_calibration_registers.gain_reactive_power = mcp_calibration_registers.gain_reactive_power * mcp_calibration_registers.calibration_reactive_power / mcp_output_registers.reactive_power; } void McpCalibrationLineFreqency() @@ -605,6 +589,11 @@ void McpEverySecond() { uint8_t get_state[] = { 0xA5, 0x08, 0x41, 0x00, 0x04, 0x4E, 0x16, 0x00 }; + if (mcp_output_registers.active_power) { + energy_kWhtoday_delta += ((mcp_output_registers.active_power * 10) / 36); + EnergyUpdateToday(); + } + if (mcp_timeout) { mcp_timeout--; } @@ -621,11 +610,6 @@ void McpEverySecond() else if (!mcp_single_wire_active) { McpSend(get_state); } - - if (mcp_output_registers.active_power) { - energy_kWhtoday_delta += ((mcp_output_registers.active_power * 10) / 36); - EnergyUpdateToday(); - } } void McpSnsInit() @@ -656,9 +640,9 @@ boolean McpCommand() if ((CMND_POWERCAL == energy_command_code) || (CMND_VOLTAGECAL == energy_command_code) || (CMND_CURRENTCAL == energy_command_code)) { // MCP Debug commands - PowerCal - if (1 == XdrvMailbox.payload) { McpSingleWireStart(); } - if (2 == XdrvMailbox.payload) { McpSingleWireStop(0); } - if (3 == XdrvMailbox.payload) { McpGetAddress(); } +// if (1 == XdrvMailbox.payload) { McpSingleWireStart(); } +// if (2 == XdrvMailbox.payload) { McpSingleWireStop(0); } +// if (3 == XdrvMailbox.payload) { McpGetAddress(); } serviced = false; } From 557545cb56d774bfdfdeb32874a779b649a0fa2a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 21 Sep 2018 16:19:31 +0200 Subject: [PATCH 0123/2222] Cleanup Driver Cleanup Driver --- sonoff/sonoff.ino | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 84293f5bc..b5d752a3b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -679,7 +679,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, (Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data)); } - else if (CMND_SENSOR == command_code) { + else if ((CMND_SENSOR == command_code) || (CMND_DRIVER == command_code)) { XdrvMailbox.index = index; XdrvMailbox.data_len = data_len; XdrvMailbox.payload16 = payload16; @@ -687,18 +687,11 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) XdrvMailbox.grpflg = grpflg; XdrvMailbox.topic = command; XdrvMailbox.data = dataBuf; - XsnsCall(FUNC_COMMAND); -// if (!XsnsCall(FUNC_COMMAND)) type = NULL; - } - else if (CMND_DRIVER == command_code) { - XdrvMailbox.index = index; - XdrvMailbox.data_len = data_len; - XdrvMailbox.payload16 = payload16; - XdrvMailbox.payload = payload; - XdrvMailbox.grpflg = grpflg; - XdrvMailbox.topic = command; - XdrvMailbox.data = dataBuf; - XdrvCall(FUNC_COMMAND); + if (CMND_SENSOR == command_code) { + XsnsCall(FUNC_COMMAND); + } else { + XdrvCall(FUNC_COMMAND); + } } else if ((CMND_SETOPTION == command_code) && (index < 82)) { byte ptype; From 4992b4368916e7a8cdb8a35b08fee75071197379 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 21 Sep 2018 23:43:58 +0200 Subject: [PATCH 0124/2222] PCA9685 I2C Hardware PWM - Experimental --- sonoff/user_config.h | 2 + sonoff/xdrv_15_pca9685.ino | 184 +++++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 sonoff/xdrv_15_pca9685.ino diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 438983a66..ee374d41c 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -298,6 +298,8 @@ // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) // #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+1k5 code) // #define USE_MCP230xx_DISPLAYOUTPUT // Enable MCP23008/MCP23017 to display state of OUTPUT pins on Web UI (+0k2 code) +// #define USE_PCA9685 // Enable PCA9685 I2C HW PWM Driver - Must define I2C Address in #define USE_PCA9685_ADDR below - range 0x40 - 0x47 (+1k4 code) +// #define USE_PCA9685_ADDR 0x40 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) // #define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code) // #define USE_CCS811 // Enable CCS811 sensor (I2C address 0x5A) (+2k2 code) // #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino new file mode 100644 index 000000000..e53b8d17f --- /dev/null +++ b/sonoff/xdrv_15_pca9685.ino @@ -0,0 +1,184 @@ +/* + xdrv_15_pca9685.ino - Support for I2C PCA9685 12bit 16 pin hardware PWM driver + + Copyright (C) 2018 Andre Thomas 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 + 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_PCA9685 + +#define XDRV_15 15 + +#define PCA9685_REG_MODE1 0x00 +#define PCA9685_REG_LED0_ON_L 0x06 +#define PCA9685_REG_PRE_SCALE 0xFE + +uint8_t pca9685_detected = 0; +uint16_t pca9685_freq = 50; + +void PCA9685_Detect(void) +{ + if (pca9685_detected) { return; } + + uint8_t buffer; + + if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x20); + if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { + if (0x20 == buffer) { + pca9685_detected = 1; + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "PCA9685", USE_PCA9685_ADDR); + AddLog(LOG_LEVEL_DEBUG); + PCA9685_Reset(); // Reset the controller + } + } + } +} + +void PCA9685_Reset(void) +{ + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x80); + PCA9685_SetPWMfreq(50); + for (uint8_t pin=0;pin<16;pin++) { + PCA9685_SetPWM(pin,0,false); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); +} + +void PCA9685_SetPWMfreq(double freq) { +/* + 7.3.5 from datasheet + prescale value = round(25000000/(4096*freq))-1; + */ + pca9685_freq=freq; + uint8_t pre_scale_osc = round(25000000/(4096*freq))-1; + if (1526 == freq) pre_scale_osc=0xFF; // force setting for 24hz because rounding causes 1526 to be 254 + uint8_t current_mode1 = I2cRead8(USE_PCA9685_ADDR, PCA9685_REG_MODE1); // read current value of MODE1 register + uint8_t sleep_mode1 = (current_mode1&0x7F) | 0x10; // Determine register value to put PCA to sleep + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, sleep_mode1); // Let's sleep a little + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_PRE_SCALE, pre_scale_osc); // Set the pre-scaler + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, current_mode1 | 0xA0); // Reset MODE1 register to original state and enable auto increment +} + +void PCA9685_SetPWM_Reg(uint8_t pin, uint16_t on, uint16_t off) { + uint8_t led_reg = PCA9685_REG_LED0_ON_L + 4 * pin; + uint32_t led_data = 0; + I2cWrite8(USE_PCA9685_ADDR, led_reg, on); + I2cWrite8(USE_PCA9685_ADDR, led_reg+1, (on >> 8)); + I2cWrite8(USE_PCA9685_ADDR, led_reg+2, off); + I2cWrite8(USE_PCA9685_ADDR, led_reg+3, (off >> 8)); +} + +void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted) { + if (4096 == pwm) { + PCA9685_SetPWM_Reg(pin, 4096, 0); // Special use additional bit causes channel to turn on completely without PWM + } else { + PCA9685_SetPWM_Reg(pin, 0, pwm); + } +} + +bool PCA9685_Command(void) +{ + boolean serviced = true; + boolean validpin = false; + uint8_t paramcount = 0; + if (XdrvMailbox.data_len > 0) { + paramcount=1; + } else { + serviced = false; + return serviced; + } + char sub_string[XdrvMailbox.data_len]; + for (uint8_t ca=0;ca 1) { + uint16_t new_freq = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if ((new_freq >= 24) && (new_freq <= 1526)) { + PCA9685_SetPWMfreq(new_freq); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}")); + return serviced; + } + } else { // No parameter was given for setfreq, so we return current setting + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PWMF\":%i}}"),pca9685_freq); + return serviced; + } + } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"PWM")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (paramcount > 2) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "ON")) { + PCA9685_SetPWM(pin, 4096, false); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,4096); + serviced = true; + return serviced; + } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "OFF")) { + PCA9685_SetPWM(pin, 0, false); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,0); + serviced = true; + return serviced; + } + uint16_t pwm = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((pin >= 0 && pin <= 15) && (pwm >= 0 && pwm <= 4096)) { + PCA9685_SetPWM(pin, pwm, false); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,pwm); + serviced = true; + return serviced; + } + } + } + } + return serviced; +} + +boolean Xdrv15(byte function) +{ + boolean result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_MQTT_DATA: + break; + case FUNC_EVERY_SECOND: + PCA9685_Detect(); + break; + case FUNC_EVERY_50_MSECOND: + break; + case FUNC_JSON_APPEND: + break; + case FUNC_COMMAND: + if (XDRV_15 == XdrvMailbox.index) { + PCA9685_Command(); + } + break; + case FUNC_WEB_APPEND: + break; + default: + break; + } + } + return result; +} + +#endif // USE_PCA9685 +#endif // USE_IC2 From 4ff5667c2adeac42078c57d4dec38522d9ab7109 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 22 Sep 2018 00:17:08 +0200 Subject: [PATCH 0125/2222] PCA9685 I2C Hardware PWM - Experimental --- sonoff/user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/user_config.h b/sonoff/user_config.h index ee374d41c..b93e44211 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -299,7 +299,7 @@ // #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+1k5 code) // #define USE_MCP230xx_DISPLAYOUTPUT // Enable MCP23008/MCP23017 to display state of OUTPUT pins on Web UI (+0k2 code) // #define USE_PCA9685 // Enable PCA9685 I2C HW PWM Driver - Must define I2C Address in #define USE_PCA9685_ADDR below - range 0x40 - 0x47 (+1k4 code) -// #define USE_PCA9685_ADDR 0x40 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) +// #define USE_PCA9685_ADDR 0x40 // Enable PCA9685 I2C Address to use (Must be within range 0x40 through 0x47 - set according to your wired setup) // #define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code) // #define USE_CCS811 // Enable CCS811 sensor (I2C address 0x5A) (+2k2 code) // #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) From 20e8d76877123ffd0584e929c35d087e092d410c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 22 Sep 2018 12:04:38 +0200 Subject: [PATCH 0126/2222] TSL2561 driver fixes Rewrite TSL2561 driver to fix some issues (#3681) --- sonoff/_changelog.ino | 1 + sonoff/xsns_16_tsl2561.ino | 91 ++++++++++++++++++++++++++------------ 2 files changed, 63 insertions(+), 29 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 72293c30d..908fd262a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.2.1.5 20180921 * Add authentication to HTTP web pages * Add energy monitoring to Shelly2 (#2789) + * Rewrite TSL2561 driver to fix some issues (#3681) * * 6.2.1.4 20180916 * Add command SerialSend5 to send raw serial data like "A5074100545293" diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index ac0536c6a..9f785e3e4 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -31,17 +31,67 @@ Tsl2561 Tsl(Wire); +uint8_t tsl2561_type = 0; +uint8_t tsl2561_valid = 0; +uint32_t tsl2561_milliLux = 0; +char tsl2561_types[] = "TSL2561"; + +bool Tsl2561Read() +{ + if (tsl2561_valid) { tsl2561_valid--; } + + uint8_t id; + bool gain; + Tsl2561::exposure_t exposure; + uint16_t scaledFull, scaledIr; + uint32_t full, ir; + + if (Tsl.available()) { + if (Tsl.on()) { + if (Tsl.id(id) + && Tsl2561Util::autoGain(Tsl, gain, exposure, scaledFull, scaledIr) + && Tsl2561Util::normalizedLuminosity(gain, exposure, full = scaledFull, ir = scaledIr) + && Tsl2561Util::milliLux(full, ir, tsl2561_milliLux, Tsl2561::packageCS(id))) { + } else{ + tsl2561_milliLux = 0; + } + } + } + tsl2561_valid = SENSOR_MAX_MISS; + return true; +} + void Tsl2561Detect() { + if (tsl2561_type) { return; } + if (!Tsl.available()) { Tsl.begin(); if (Tsl.available()) { - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "TSL2561", Tsl.address()); + tsl2561_type = 1; + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, tsl2561_types, Tsl.address()); AddLog(LOG_LEVEL_DEBUG); } } } +void Tsl2561EverySecond() +{ + if (90 == (uptime %100)) { + // 1mS + Tsl2561Detect(); + } + else if (uptime &3) { + // 1mS + if (tsl2561_type) { + if (!Tsl2561Read()) { + AddLogMissed(tsl2561_types, tsl2561_valid); +// if (!tsl2561_valid) { tsl2561_type = 0; } + } + } + } +} + #ifdef USE_WEBSERVER const char HTTP_SNS_TSL2561[] PROGMEM = "%s{s}TSL2561 " D_ILLUMINANCE "{m}%u.%03u " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = @@ -49,37 +99,17 @@ const char HTTP_SNS_TSL2561[] PROGMEM = void Tsl2561Show(boolean json) { - uint8_t id; - bool gain; - Tsl2561::exposure_t exposure; - uint16_t scaledFull, scaledIr; - uint32_t full, ir; - uint32_t milliLux; - - if (Tsl.available()) { - if (Tsl.on()) { - if( Tsl.id(id) - && Tsl2561Util::autoGain(Tsl, gain, exposure, scaledFull, scaledIr) - && Tsl2561Util::normalizedLuminosity(gain, exposure, full = scaledFull, ir = scaledIr) - && Tsl2561Util::milliLux(full, ir, milliLux, Tsl2561::packageCS(id))) { - -// snprintf_P(log_data, sizeof(log_data), PSTR(D_ILLUMINANCE " g:%d, e:%d, f:%u, i:%u -> %u.%03u " D_UNIT_LUX), -// gain, exposure, full, ir, milliLux/1000, milliLux%1000); -// AddLog(LOG_LEVEL_DEBUG); - - if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), - mqtt_data, milliLux/1000, milliLux%1000); + if (tsl2561_valid) { + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), + mqtt_data, tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, (milliLux+500)/1000); + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, (tsl2561_milliLux + 500) / 1000); } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TSL2561, mqtt_data, milliLux/1000, milliLux%1000); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TSL2561, mqtt_data, tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); #endif // USE_WEBSERVER - } - } - Tsl.off(); } } } @@ -96,9 +126,12 @@ boolean Xsns16(byte function) if (i2c_flg) { switch (function) { - case FUNC_PREP_BEFORE_TELEPERIOD: + case FUNC_INIT: Tsl2561Detect(); break; + case FUNC_EVERY_SECOND: + Tsl2561EverySecond(); + break; case FUNC_JSON_APPEND: Tsl2561Show(1); break; From 57e7005b4898aaeb722444182123bff2651d86ca Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 22 Sep 2018 12:18:13 +0200 Subject: [PATCH 0127/2222] Fix TSL2561 timeslot --- sonoff/xsns_16_tsl2561.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index 9f785e3e4..61308aa20 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -81,8 +81,8 @@ void Tsl2561EverySecond() // 1mS Tsl2561Detect(); } - else if (uptime &3) { - // 1mS + else if (!(uptime %2)) { // Update every 2 seconds + // ?mS - 4Sec if (tsl2561_type) { if (!Tsl2561Read()) { AddLogMissed(tsl2561_types, tsl2561_valid); From 7a767f104cd2a9e1626bbcd1ee079f541086367f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 22 Sep 2018 15:09:53 +0200 Subject: [PATCH 0128/2222] 6.2.1.6 Remove some commands 6.2.1.6 20180922 * Removed commands PowerCal, VoltageCal and CurrentCal as more functionality is provided by commands PowerSet, VoltageSet and CurrentSet * Allow decimals as input to commands PowerSet, VoltageSet and CurrentSet * Add support for PCA9685 12bit 16pin hardware PWM driver (#3866) --- sonoff/_changelog.ino | 7 ++++++- sonoff/i18n.h | 3 --- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_03_energy.ino | 35 ++++++++--------------------------- sonoff/xnrg_01_hlw8012.ino | 17 +++++++---------- sonoff/xnrg_02_cse7766.ino | 17 +++++++---------- sonoff/xnrg_04_mcp39f501.ino | 11 +---------- 7 files changed, 30 insertions(+), 62 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 908fd262a..2b954e151 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,9 @@ -/* 6.2.1.5 20180921 +/* 6.2.1.6 20180922 + * Removed commands PowerCal, VoltageCal and CurrentCal as more functionality is provided by commands PowerSet, VoltageSet and CurrentSet + * Allow decimals as input to commands PowerSet, VoltageSet and CurrentSet + * Add support for PCA9685 12bit 16pin hardware PWM driver (#3866) + * + * 6.2.1.5 20180921 * Add authentication to HTTP web pages * Add energy monitoring to Shelly2 (#2789) * Rewrite TSL2561 driver to fix some issues (#3681) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index a45d7687d..80f757447 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -287,11 +287,8 @@ #define D_CMND_CURRENTLOW "CurrentLow" #define D_CMND_CURRENTHIGH "CurrentHigh" #define D_CMND_ENERGYRESET "EnergyReset" -#define D_CMND_POWERCAL "PowerCal" #define D_CMND_POWERSET "PowerSet" -#define D_CMND_VOLTAGECAL "VoltageCal" #define D_CMND_VOLTAGESET "VoltageSet" -#define D_CMND_CURRENTCAL "CurrentCal" #define D_CMND_CURRENTSET "CurrentSet" #define D_CMND_FREQUENCYSET "FrequencySet" #define D_CMND_MAXPOWER "MaxPower" diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 43253e40f..228a48d92 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020105 +#define VERSION 0x06020106 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 860183f49..3ccad7df4 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -29,14 +29,14 @@ enum EnergyCommands { CMND_POWERDELTA, CMND_POWERLOW, CMND_POWERHIGH, CMND_VOLTAGELOW, CMND_VOLTAGEHIGH, CMND_CURRENTLOW, CMND_CURRENTHIGH, - CMND_POWERCAL, CMND_POWERSET, CMND_VOLTAGECAL, CMND_VOLTAGESET, CMND_CURRENTCAL, CMND_CURRENTSET, CMND_FREQUENCYSET, + CMND_POWERSET, CMND_VOLTAGESET, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_ENERGYRESET, CMND_MAXENERGY, CMND_MAXENERGYSTART, CMND_MAXPOWER, CMND_MAXPOWERHOLD, CMND_MAXPOWERWINDOW, CMND_SAFEPOWER, CMND_SAFEPOWERHOLD, CMND_SAFEPOWERWINDOW }; const char kEnergyCommands[] PROGMEM = D_CMND_POWERDELTA "|" D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|" - D_CMND_POWERCAL "|" D_CMND_POWERSET "|" D_CMND_VOLTAGECAL "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTCAL "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" + D_CMND_POWERSET "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" 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 ; @@ -415,45 +415,21 @@ boolean EnergyCommand() command, energy_total_chr, energy_yesterday_chr, energy_daily_chr); status_flag = 1; } - else if ((CMND_POWERCAL == command_code) && XnrgCall(FUNC_COMMAND)) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 32001)) { - Settings.energy_power_calibration = (XdrvMailbox.payload > 4000) ? XdrvMailbox.payload : HLW_PREF_PULSE; // HLW = 12530, CSE = 5364 - } - nvalue = Settings.energy_power_calibration; - unit = UNIT_MICROSECOND; - } - else if ((CMND_VOLTAGECAL == command_code) && XnrgCall(FUNC_COMMAND)) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 32001)) { - Settings.energy_voltage_calibration = (XdrvMailbox.payload > 999) ? XdrvMailbox.payload : HLW_UREF_PULSE; // HLW = 1950, CSE = 1912 - } - nvalue = Settings.energy_voltage_calibration; - unit = UNIT_MICROSECOND; - } - else if ((CMND_CURRENTCAL == command_code) && XnrgCall(FUNC_COMMAND)) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 32001)) { - Settings.energy_current_calibration = (XdrvMailbox.payload > 1100) ? XdrvMailbox.payload : HLW_IREF_PULSE; // HLW = 3500, CSE = 16140 - } - nvalue = Settings.energy_current_calibration; - unit = UNIT_MICROSECOND; - } else if ((CMND_POWERSET == command_code) && XnrgCall(FUNC_COMMAND)) { // Watt - snprintf_P(command, sizeof(command), PSTR(D_CMND_POWERCAL)); nvalue = Settings.energy_power_calibration; unit = UNIT_MICROSECOND; } else if ((CMND_VOLTAGESET == command_code) && XnrgCall(FUNC_COMMAND)) { // Volt - snprintf_P(command, sizeof(command), PSTR(D_CMND_VOLTAGECAL)); nvalue = Settings.energy_voltage_calibration; unit = UNIT_MICROSECOND; } else if ((CMND_CURRENTSET == command_code) && XnrgCall(FUNC_COMMAND)) { // milliAmpere - snprintf_P(command, sizeof(command), PSTR(D_CMND_CURRENTCAL)); nvalue = Settings.energy_current_calibration; unit = UNIT_MICROSECOND; } else if ((CMND_FREQUENCYSET == command_code) && XnrgCall(FUNC_COMMAND)) { // Hz nvalue = Settings.energy_frequency_calibration; - unit = UNIT_HERTZ; + unit = UNIT_MICROSECOND; } #if FEATURE_POWER_LIMIT @@ -518,6 +494,11 @@ boolean EnergyCommand() else serviced = false; // Unknown command if (serviced && !status_flag) { + + if (UNIT_MICROSECOND == unit) { + snprintf_P(command, sizeof(command), PSTR("%sCal"), command); + } + if (Settings.flag.value_units) { snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_LVALUE_SPACE_UNIT, command, nvalue, GetTextIndexed(sunit, sizeof(sunit), unit, kUnitNames)); } else { diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 6ef196fb1..5140d6596 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -227,22 +227,19 @@ boolean HlwCommand() { boolean serviced = true; - if ((CMND_POWERCAL == energy_command_code) || (CMND_VOLTAGECAL == energy_command_code) || (CMND_CURRENTCAL == energy_command_code)) { - - } - else if (CMND_POWERSET == energy_command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3601) && hlw_cf_pulse_length) { - Settings.energy_power_calibration = (XdrvMailbox.payload * 10 * hlw_cf_pulse_length) / hlw_power_ratio; + if (CMND_POWERSET == energy_command_code) { + if (XdrvMailbox.data_len && hlw_cf_pulse_length) { + Settings.energy_power_calibration = ((unsigned long)(CharToDouble(XdrvMailbox.data) * 10) * hlw_cf_pulse_length) / hlw_power_ratio; } } else if (CMND_VOLTAGESET == energy_command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 501) && hlw_cf1_voltage_pulse_length) { - Settings.energy_voltage_calibration = (XdrvMailbox.payload * 10 * hlw_cf1_voltage_pulse_length) / hlw_voltage_ratio; + if (XdrvMailbox.data_len && hlw_cf1_voltage_pulse_length) { + Settings.energy_voltage_calibration = ((unsigned long)(CharToDouble(XdrvMailbox.data) * 10) * hlw_cf1_voltage_pulse_length) / hlw_voltage_ratio; } } else if (CMND_CURRENTSET == energy_command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 16001) && hlw_cf1_current_pulse_length) { - Settings.energy_current_calibration = (XdrvMailbox.payload * hlw_cf1_current_pulse_length) / hlw_current_ratio; + if (XdrvMailbox.data_len && hlw_cf1_current_pulse_length) { + Settings.energy_current_calibration = ((unsigned long)(CharToDouble(XdrvMailbox.data)) * hlw_cf1_current_pulse_length) / hlw_current_ratio; } } else serviced = false; // Unknown command diff --git a/sonoff/xnrg_02_cse7766.ino b/sonoff/xnrg_02_cse7766.ino index 84535cf96..a433bc4a4 100644 --- a/sonoff/xnrg_02_cse7766.ino +++ b/sonoff/xnrg_02_cse7766.ino @@ -195,22 +195,19 @@ boolean CseCommand() { boolean serviced = true; - if ((CMND_POWERCAL == energy_command_code) || (CMND_VOLTAGECAL == energy_command_code) || (CMND_CURRENTCAL == energy_command_code)) { - - } - else if (CMND_POWERSET == energy_command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3601) && power_cycle) { - Settings.energy_power_calibration = (XdrvMailbox.payload * power_cycle) / CSE_PREF; + if (CMND_POWERSET == energy_command_code) { + if (XdrvMailbox.data_len && power_cycle) { + Settings.energy_power_calibration = ((unsigned long)CharToDouble(XdrvMailbox.data) * power_cycle) / CSE_PREF; } } else if (CMND_VOLTAGESET == energy_command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 501) && voltage_cycle) { - Settings.energy_voltage_calibration = (XdrvMailbox.payload * voltage_cycle) / CSE_UREF; + if (XdrvMailbox.data_len && voltage_cycle) { + Settings.energy_voltage_calibration = ((unsigned long)CharToDouble(XdrvMailbox.data) * voltage_cycle) / CSE_UREF; } } else if (CMND_CURRENTSET == energy_command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 16001) && current_cycle) { - Settings.energy_current_calibration = (XdrvMailbox.payload * current_cycle) / 1000; + if (XdrvMailbox.data_len && current_cycle) { + Settings.energy_current_calibration = ((unsigned long)CharToDouble(XdrvMailbox.data) * current_cycle) / 1000; } } else serviced = false; // Unknown command diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index c34846edf..05d55a425 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -637,16 +637,7 @@ boolean McpCommand() { boolean serviced = true; - if ((CMND_POWERCAL == energy_command_code) || (CMND_VOLTAGECAL == energy_command_code) || (CMND_CURRENTCAL == energy_command_code)) { - - // MCP Debug commands - PowerCal -// if (1 == XdrvMailbox.payload) { McpSingleWireStart(); } -// if (2 == XdrvMailbox.payload) { McpSingleWireStop(0); } -// if (3 == XdrvMailbox.payload) { McpGetAddress(); } - - serviced = false; - } - else if (CMND_POWERSET == energy_command_code) { + if (CMND_POWERSET == energy_command_code) { if (XdrvMailbox.data_len && mcp_output_registers.active_power) { Settings.energy_power_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * 100); mcp_calibration_setpoint.calibration_active_power = Settings.energy_power_calibration; From 544abec7bf836ce945b2b65770d1895d07017951 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 22 Sep 2018 15:42:18 +0200 Subject: [PATCH 0129/2222] Set force_update to true for buttons --- sonoff/xdrv_12_home_assistant.ino | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 5c8a2a7cf..b085947ae 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -19,7 +19,7 @@ #ifdef USE_HOME_ASSISTANT -const char HASS_DISCOVER_SWITCH[] PROGMEM = +const char HASS_DISCOVER_RELAY[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 "\"command_topic\":\"%s\"," // cmnd/dualr2/POWER2 "\"state_topic\":\"%s\"," // stat/dualr2/RESULT (implies "\"optimistic\":\"false\",") @@ -39,7 +39,8 @@ const char HASS_DISCOVER_BUTTON[] PROGMEM = // "\"optimistic\":\"false\"," // false is Hass default when state_topic is set "\"availability_topic\":\"%s\"," // tele/dualr2/LWT "\"payload_available\":\"" D_ONLINE "\"," // Online - "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline + "\"payload_not_available\":\"" D_OFFLINE "\"," // Offline + "\"force_update\":true"; const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = "%s,\"brightness_command_topic\":\"%s\"," // cmnd/led2/Dimmer @@ -102,7 +103,7 @@ void HAssDiscoverRelay() GetTopic_P(command_topic, CMND, mqtt_topic, value_template); GetTopic_P(state_topic, STAT, mqtt_topic, S_RSLT_RESULT); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SWITCH, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); if (is_light) { char brightness_command_topic[TOPSZ]; From 665a4abc47cbee81eb32cf5bcd23782ee044561b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 22 Sep 2018 16:09:13 +0200 Subject: [PATCH 0130/2222] Fix Pow R2 and S31 low power * Add power value below 5W to Sonoff Pow R2 and S31 (#3745) * Add force_update to Home Assistant discovery (#3873) --- sonoff/_changelog.ino | 2 ++ sonoff/xnrg_02_cse7766.ino | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 2b954e151..cb72ff407 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,8 @@ * Removed commands PowerCal, VoltageCal and CurrentCal as more functionality is provided by commands PowerSet, VoltageSet and CurrentSet * Allow decimals as input to commands PowerSet, VoltageSet and CurrentSet * Add support for PCA9685 12bit 16pin hardware PWM driver (#3866) + * Add power value below 5W to Sonoff Pow R2 and S31 (#3745) + * Add force_update to Home Assistant discovery (#3873) * * 6.2.1.5 20180921 * Add authentication to HTTP web pages diff --git a/sonoff/xnrg_02_cse7766.ino b/sonoff/xnrg_02_cse7766.ino index a433bc4a4..8ba1b146e 100644 --- a/sonoff/xnrg_02_cse7766.ino +++ b/sonoff/xnrg_02_cse7766.ino @@ -27,6 +27,8 @@ #define XNRG_02 2 +#define CSE_MAX_INVALID_POWER 128 // Number of invalid power receipts before deciding active power is zero + #define CSE_NOT_CALIBRATED 0xAA #define CSE_PULSES_NOT_INITIALIZED -1 @@ -42,10 +44,12 @@ long power_cycle = 0; unsigned long power_cycle_first = 0; long cf_pulses = 0; long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; +uint8_t cse_power_invalid = CSE_MAX_INVALID_POWER; void CseReceived() { // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + // 55 5A 02 F7 60 00 03 5A 00 40 10 04 8B 9F 51 A6 58 18 72 75 61 AC A1 30 - Power not valid (load below 5W) // 55 5A 02 F7 60 00 03 AB 00 40 10 02 60 5D 51 A6 58 03 E9 EF 71 0B 7A 36 // Hd Id VCal---- Voltage- ICal---- Current- PCal---- Power--- Ad CF--- Ck @@ -89,10 +93,11 @@ void CseReceived() energy_voltage = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)voltage_cycle; } if (adjustement & 0x10) { // Power valid + cse_power_invalid = 0; if ((header & 0xF2) == 0xF2) { // Power cycle exceeds range energy_power = 0; } else { - if (0 == power_cycle_first) power_cycle_first = power_cycle; // Skip first incomplete power_cycle + if (0 == power_cycle_first) { power_cycle_first = power_cycle; } // Skip first incomplete power_cycle if (power_cycle_first != power_cycle) { power_cycle_first = -1; energy_power = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)power_cycle; @@ -101,8 +106,12 @@ void CseReceived() } } } else { - power_cycle_first = 0; - energy_power = 0; // Powered on but no load + if (cse_power_invalid < CSE_MAX_INVALID_POWER) { // Allow measurements down to about 1W + cse_power_invalid++; + } else { + power_cycle_first = 0; + energy_power = 0; // Powered on but no load + } } if (adjustement & 0x20) { // Current valid if (0 == energy_power) { From f05fc71d675101572a9fbd7ac90ead0542537528 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 22 Sep 2018 17:37:49 +0200 Subject: [PATCH 0131/2222] Fix rule trigger POWER1#STATE Fix rule trigger POWER1#STATE execution after restart and SetOption0 is 0 (#3856) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 6 +++++- sonoff/xdrv_10_rules.ino | 1 + sonoff/xdrv_interface.ino | 8 -------- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index cb72ff407..b220dc4b3 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,6 +4,7 @@ * Add support for PCA9685 12bit 16pin hardware PWM driver (#3866) * Add power value below 5W to Sonoff Pow R2 and S31 (#3745) * Add force_update to Home Assistant discovery (#3873) + * Fix rule trigger POWER1#STATE execution after restart and SetOption0 is 0 (#3856) * * 6.2.1.5 20180921 * Add authentication to HTTP web pages diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 80356d475..c3d514f0c 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -203,7 +203,7 @@ enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_R enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, - FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, + FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_RULE_INIT_POWER, FUNC_SHOW_SENSOR, FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index b5d752a3b..a405fe47b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -335,7 +335,8 @@ void SetDevicePower(power_t rpower, int source) } } - XdrvSetPower(rpower); + XdrvMailbox.index = rpower; + XdrvCall(FUNC_SET_POWER); if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { Serial.write(0xA0); @@ -2613,6 +2614,9 @@ void setup() } } + XdrvMailbox.index = power; + XdrvCall(FUNC_RULE_INIT_POWER); + blink_powersave = power; 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-" ARDUINO_ESP8266_RELEASE), diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 930bde7d5..5ef59c037 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -628,6 +628,7 @@ boolean Xdrv10(byte function) case FUNC_EVERY_SECOND: RulesEverySecond(); break; + case FUNC_RULE_INIT_POWER: case FUNC_SET_POWER: RulesSetPower(); break; diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 43a391076..a88d3b5f8 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -153,14 +153,6 @@ boolean XdrvCommand(uint8_t grpflg, char *type, uint16_t index, char *dataBuf, u return XdrvCall(FUNC_COMMAND); } -void XdrvSetPower(power_t mpower) -{ -// XdrvMailbox.valid = 1; - XdrvMailbox.index = mpower; - - XdrvCall(FUNC_SET_POWER); -} - boolean XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t sdataBuf) { XdrvMailbox.index = stopicBuf; From 01ce1b0c91a72d46a87c517626038b11497521da Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 23 Sep 2018 13:55:42 +0200 Subject: [PATCH 0132/2222] Fix Shelly2 monitoring Disable serial logging on Shelly2 as serial is being used by energy monitoring (#3878) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 4 ---- sonoff/xdrv_10_rules.ino | 2 +- sonoff/xnrg_04_mcp39f501.ino | 1 + 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b220dc4b3..f38b68153 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -5,6 +5,7 @@ * Add power value below 5W to Sonoff Pow R2 and S31 (#3745) * Add force_update to Home Assistant discovery (#3873) * Fix rule trigger POWER1#STATE execution after restart and SetOption0 is 0 (#3856) + * Disable serial logging on Shelly2 as serial is being used by energy monitoring (#3878) * * 6.2.1.5 20180921 * Add authentication to HTTP web pages diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index c3d514f0c..80356d475 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -203,7 +203,7 @@ enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_R enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, - FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_RULE_INIT_POWER, FUNC_SHOW_SENSOR, + FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index a405fe47b..dc1445fc4 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2613,10 +2613,6 @@ void setup() SetPulseTimer(i, Settings.pulse_timer[i]); } } - - XdrvMailbox.index = power; - XdrvCall(FUNC_RULE_INIT_POWER); - blink_powersave = power; 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-" ARDUINO_ESP8266_RELEASE), diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 5ef59c037..303207c10 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -366,6 +366,7 @@ void RulesEvery50ms() if (Settings.rule_enabled) { // Any rule enabled char json_event[120]; + if (-1 == rules_new_power) { rules_new_power = power; } if (rules_new_power != rules_old_power) { if (rules_old_power != -1) { for (byte i = 0; i < devices_present; i++) { @@ -628,7 +629,6 @@ boolean Xdrv10(byte function) case FUNC_EVERY_SECOND: RulesEverySecond(); break; - case FUNC_RULE_INIT_POWER: case FUNC_SET_POWER: RulesSetPower(); break; diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index 05d55a425..408e0ca26 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -614,6 +614,7 @@ void McpEverySecond() void McpSnsInit() { + SetSeriallog(LOG_LEVEL_NONE); // Free serial interface from logging interference digitalWrite(15, 1); // GPIO15 - MCP enable } From 683c21124114a25f9d0bdfd3a9712a9dc7095fb9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 23 Sep 2018 16:41:22 +0200 Subject: [PATCH 0133/2222] Fix Shelly2 wrong FrequencySet Fix Shelly2 wrong FrequencySet calculation and add input range checks (#3882) --- sonoff/_changelog.ino | 1 + sonoff/xnrg_04_mcp39f501.ino | 45 +++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index f38b68153..b7988c69c 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -6,6 +6,7 @@ * Add force_update to Home Assistant discovery (#3873) * Fix rule trigger POWER1#STATE execution after restart and SetOption0 is 0 (#3856) * Disable serial logging on Shelly2 as serial is being used by energy monitoring (#3878) + * Fix Shelly2 wrong FrequencySet calculation and add input range checks (#3882) * * 6.2.1.5 20180921 * Add authentication to HTTP web pages diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index 408e0ca26..3fa12da26 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -239,8 +239,12 @@ void McpCalibrationReactivePower() mcp_calibration_registers.gain_reactive_power = mcp_calibration_registers.gain_reactive_power * mcp_calibration_registers.calibration_reactive_power / mcp_output_registers.reactive_power; } -void McpCalibrationLineFreqency() +void McpCalibrationLineFrequency() { + if ((0xFFFF == mcp_output_registers.line_frequency) || (0 == mcp_frequency_registers.gain_line_frequency)) { // Reset values to 50Hz + mcp_output_registers.line_frequency = 50000; + mcp_frequency_registers.gain_line_frequency = 0x8000; + } mcp_frequency_registers.gain_line_frequency = mcp_frequency_registers.gain_line_frequency * mcp_frequency_registers.line_frequency_ref / mcp_output_registers.line_frequency; } @@ -481,7 +485,7 @@ void McpParseFrequency() if (mcp_calibration_setpoint.line_frequency_ref) { mcp_frequency_registers.line_frequency_ref = mcp_calibration_setpoint.line_frequency_ref; - McpCalibrationLineFreqency(); + McpCalibrationLineFrequency(); mcp_timeout = 0; McpSetFrequency(); } @@ -637,33 +641,46 @@ void McpDrvInit() boolean McpCommand() { boolean serviced = true; + unsigned long value = 0; if (CMND_POWERSET == energy_command_code) { if (XdrvMailbox.data_len && mcp_output_registers.active_power) { - Settings.energy_power_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * 100); - mcp_calibration_setpoint.calibration_active_power = Settings.energy_power_calibration; - McpGetCalibration(); + value = (unsigned long)(CharToDouble(XdrvMailbox.data) * 100); + if ((value > 100) && (value < 200000)) { // Between 1W and 2000W + Settings.energy_power_calibration = value; + mcp_calibration_setpoint.calibration_active_power = value; + McpGetCalibration(); + } } } else if (CMND_VOLTAGESET == energy_command_code) { if (XdrvMailbox.data_len && mcp_output_registers.voltage_rms) { - Settings.energy_voltage_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * 10); - mcp_calibration_setpoint.calibration_voltage = Settings.energy_voltage_calibration; - McpGetCalibration(); + value = (unsigned long)(CharToDouble(XdrvMailbox.data) * 10); + if ((value > 1000) && (value < 2600)) { // Between 100V and 260V + Settings.energy_voltage_calibration = value; + mcp_calibration_setpoint.calibration_voltage = value; + McpGetCalibration(); + } } } else if (CMND_CURRENTSET == energy_command_code) { if (XdrvMailbox.data_len && mcp_output_registers.current_rms) { - Settings.energy_current_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * 10); - mcp_calibration_setpoint.calibration_current = Settings.energy_current_calibration; - McpGetCalibration(); + value = (unsigned long)(CharToDouble(XdrvMailbox.data) * 10); + if ((value > 100) && (value < 80000)) { // Between 10mA and 8A + Settings.energy_current_calibration = value; + mcp_calibration_setpoint.calibration_current = value; + McpGetCalibration(); + } } } else if (CMND_FREQUENCYSET == energy_command_code) { if (XdrvMailbox.data_len && mcp_output_registers.line_frequency) { - Settings.energy_frequency_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * 10); - mcp_calibration_setpoint.line_frequency_ref = Settings.energy_frequency_calibration; - McpGetFrequency(); + value = (unsigned long)(CharToDouble(XdrvMailbox.data) * 1000); + if ((value > 45000) && (value < 65000)) { // Between 45Hz and 65Hz + Settings.energy_frequency_calibration = value; + mcp_calibration_setpoint.line_frequency_ref = value; + McpGetFrequency(); + } } } else serviced = false; // Unknown command From 5fa47c3fdce4b8842f095d8be1c8492685176909 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 24 Sep 2018 00:30:07 +0200 Subject: [PATCH 0134/2222] MCP230xx - Add missing (void) --- sonoff/xsns_29_mcp230xx.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 1ca59f8ed..9dbaf406a 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -691,7 +691,7 @@ void MCP230xx_OutputTelemetry(void) { #endif // USE_MCP230xx_OUTPUT -void MCP230xx_Interrupt_Counter_Report() { +void MCP230xx_Interrupt_Counter_Report(void) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230_INTTIMER\": {"), GetDateAndTime(DT_LOCAL).c_str()); for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].int_count_en) { // Counting is enabled for this pin so we add to report From f65d8c0cbf72ad6f68502df771fb0c91a6c3185c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 24 Sep 2018 11:44:40 +0200 Subject: [PATCH 0135/2222] Fix possible array overflow Fix possible array overflow (#3887 ) --- sonoff/sonoff.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index dc1445fc4..91c1fbb9b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -462,10 +462,11 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) 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) + type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type) index = 1; if (type != NULL) { + type++; for (i = 0; i < strlen(type); i++) { type[i] = toupper(type[i]); } From 43c3cf57d596a14c18313e55ef1ab447f377dde4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 24 Sep 2018 18:16:35 +0200 Subject: [PATCH 0136/2222] Shelly2 Cleanup Cleanup and debug updates --- sonoff/settings.h | 24 +- sonoff/settings.ino | 4 +- sonoff/xdrv_99_debug.ino | 186 ++++++++++---- sonoff/xnrg_04_mcp39f501.ino | 464 +++++++++++++++-------------------- 4 files changed, 349 insertions(+), 329 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 7da610891..bf862dd51 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -337,21 +337,21 @@ struct SYSCFG { } Settings; struct RTCRBT { - uint16_t valid; // 000 - uint8_t fast_reboot_count; // 002 - uint8_t free_003[1]; // 003 + uint16_t valid; // 280 (RTC memory offset 100 - sizeof(RTCRBT)) + uint8_t fast_reboot_count; // 282 + uint8_t free_003[1]; // 283 } RtcReboot; struct RTCMEM { - uint16_t valid; // 000 - byte oswatch_blocked_loop; // 002 - uint8_t ota_loader; // 003 - unsigned long energy_kWhtoday; // 004 - unsigned long energy_kWhtotal; // 008 - unsigned long pulse_counter[MAX_COUNTERS]; // 00C - power_t power; // 01C - uint8_t free_020[60]; // 020 - // 05C next free location (64 (=core) + 100 (=tasmota offset) + 92 (=0x5C RTCMEM struct) = 256 bytes (max = 512)) + uint16_t valid; // 290 (RTC memory offset 100) + byte oswatch_blocked_loop; // 292 + uint8_t ota_loader; // 293 + unsigned long energy_kWhtoday; // 294 + unsigned long energy_kWhtotal; // 298 + unsigned long pulse_counter[MAX_COUNTERS]; // 29C + power_t power; // 2AC + uint8_t free_020[60]; // 2B0 + // 2EC - 2FF free locations } RtcSettings; struct TIME_T { diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 5626f862b..0d8fa451a 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -95,7 +95,7 @@ void RtcSettingsSave() void RtcSettingsLoad() { - ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); + ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); // 0x290 #ifdef DEBUG_THEO AddLog_P(LOG_LEVEL_DEBUG, PSTR("Dump: Load")); RtcSettingsDump(); @@ -145,7 +145,7 @@ void RtcRebootSave() void RtcRebootLoad() { - ESP.rtcUserMemoryRead(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); + ESP.rtcUserMemoryRead(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); // 0x280 if (RtcReboot.valid != RTC_MEM_VALID) { memset(&RtcReboot, 0, sizeof(RTCRBT)); RtcReboot.valid = RTC_MEM_VALID; diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_99_debug.ino index 3cd2e69c5..abd209b82 100644 --- a/sonoff/xdrv_99_debug.ino +++ b/sonoff/xdrv_99_debug.ino @@ -35,20 +35,25 @@ * Debug commands \*********************************************************************************************/ -#define D_CMND_CFGDUMP "CfgDump" -#define D_CMND_CFGPOKE "CfgPoke" -#define D_CMND_CFGPEEK "CfgPeek" -#define D_CMND_CFGXOR "CfgXor" +#define D_CMND_CFGDUMP "CfgDump" +#define D_CMND_CFGPOKE "CfgPoke" +#define D_CMND_CFGPEEK "CfgPeek" +#define D_CMND_CFGSHOW "CfgShow" +#define D_CMND_CFGXOR "CfgXor" +#define D_CMND_CPUCHECK "CpuChk" #define D_CMND_EXCEPTION "Exception" -#define D_CMND_CPUCHECK "CpuChk" +#define D_CMND_FREEMEM "FreeMem" +#define D_CMND_RTCDUMP "RtcDump" +#define D_CMND_HELP "Help" -enum DebugCommands { CMND_CFGDUMP, CMND_CFGPEEK, CMND_CFGPOKE, CMND_CFGXOR, CMND_EXCEPTION, CMND_CPUCHECK }; -const char kDebugCommands[] PROGMEM = D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" D_CMND_CFGXOR "|" D_CMND_EXCEPTION "|" D_CMND_CPUCHECK; +enum DebugCommands { CMND_CFGDUMP, CMND_CFGPEEK, CMND_CFGPOKE, CMND_CFGSHOW, CMND_CFGXOR, CMND_CPUCHECK, CMND_EXCEPTION, CMND_FREEMEM, CMND_RTCDUMP, CMND_HELP }; +const char kDebugCommands[] PROGMEM = D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" D_CMND_CFGSHOW "|" D_CMND_CFGXOR "|" D_CMND_CPUCHECK "|" D_CMND_EXCEPTION "|" D_CMND_FREEMEM "|" D_CMND_RTCDUMP "|" D_CMND_HELP; uint32_t CPU_loops = 0; uint32_t CPU_last_millis = 0; uint32_t CPU_last_loop_time = 0; -uint8_t CPU_load_check = CPU_LOAD_CHECK; +uint8_t CPU_load_check = 0; +uint8_t CPU_show_freemem = 0; /*******************************************************************************************/ @@ -117,41 +122,6 @@ Decoding 14 results } } -/*******************************************************************************************/ - -void RtcSettingsDump() -{ - #define CFG_COLS 16 - - uint16_t idx; - uint16_t maxrow; - uint16_t row; - uint16_t col; - - uint8_t *buffer = (uint8_t *) &RtcSettings; - maxrow = ((sizeof(RTCMEM)+CFG_COLS)/CFG_COLS); - - for (row = 0; row < maxrow; row++) { - idx = row * CFG_COLS; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); - for (col = 0; col < CFG_COLS; col++) { - if (!(col%4)) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (col = 0; col < CFG_COLS; col++) { -// if (!(col%4)) { -// snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); -// } - 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); - } -} - #endif // DEBUG_THEO /*******************************************************************************************/ @@ -224,6 +194,68 @@ void DebugFreeMem() /*******************************************************************************************/ +void DebugRtcDump(char* parms) +{ + #define CFG_COLS 16 + + uint16_t idx; + uint16_t maxrow; + uint16_t row; + uint16_t col; + char *p; + + // |<--SDK data (256 bytes)-->|<--User data (512 bytes)-->| + // 000 - 0FF: SDK + // 000 - 01B: SDK rst_info + // 100 - 2FF: User + // 280 - 283: Tasmota RtcReboot (Offset 100 (x 4bytes) - sizeof(RTCRBT) (x 4bytes)) + // 290 - 2EB: Tasmota RtcSettings (Offset 100 (x 4bytes)) + + uint8_t buffer[768]; +// ESP.rtcUserMemoryRead(0, (uint32_t*)&buffer, sizeof(buffer)); + system_rtc_mem_read(0, (uint32_t*)&buffer, sizeof(buffer)); + + maxrow = ((sizeof(buffer)+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); + + if (0 == mrow) { // Default only 8 lines + mrow = 8; + } + if (srow > maxrow) { + srow = maxrow - mrow; + } + if (mrow < (maxrow - srow)) { + maxrow = srow + mrow; + } + + for (row = srow; row < maxrow; row++) { + idx = row * CFG_COLS; + snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); + for (col = 0; col < CFG_COLS; col++) { + if (!(col%4)) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + for (col = 0; col < CFG_COLS; col++) { +// if (!(col%4)) { +// snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); +// } + 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); + } +} + +/*******************************************************************************************/ + void DebugCfgDump(char* parms) { #define CFG_COLS 16 @@ -322,6 +354,53 @@ void DebugCfgPoke(char* parms) AddLog(LOG_LEVEL_INFO); } +void DebugCfgShow(uint8_t more) +{ + uint8_t *SetAddr; + SetAddr = (uint8_t *)&Settings; + + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: Hostname (%d) [%s]"), (uint8_t *)&Settings.hostname - SetAddr, sizeof(Settings.hostname)-1, Settings.hostname); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: SSids (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_ssid - SetAddr, sizeof(Settings.sta_ssid[0])-1, Settings.sta_ssid[0], Settings.sta_ssid[1]); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: Friendlynames (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.friendlyname - SetAddr, sizeof(Settings.friendlyname[0])-1, Settings.friendlyname[0], Settings.friendlyname[1], Settings.friendlyname[2], Settings.friendlyname[3]); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: OTA Url (%d) [%s]"), (uint8_t *)&Settings.ota_url - SetAddr, sizeof(Settings.ota_url)-1, Settings.ota_url); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: StateText (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.state_text - SetAddr, sizeof(Settings.state_text[0])-1, Settings.state_text[0], Settings.state_text[1], Settings.state_text[2], Settings.state_text[3]); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: Syslog Host (%d) [%s]"), (uint8_t *)&Settings.syslog_host - SetAddr, sizeof(Settings.syslog_host)-1, Settings.syslog_host); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: NTP Servers (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.ntp_server - SetAddr, sizeof(Settings.ntp_server[0])-1, Settings.ntp_server[0], Settings.ntp_server[1], Settings.ntp_server[2]); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Host (%d) [%s]"), (uint8_t *)&Settings.mqtt_host - SetAddr, sizeof(Settings.mqtt_host)-1, Settings.mqtt_host); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Client (%d) [%s]"), (uint8_t *)&Settings.mqtt_client - SetAddr, sizeof(Settings.mqtt_client)-1, Settings.mqtt_client); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT User (%d) [%s]"), (uint8_t *)&Settings.mqtt_user - SetAddr, sizeof(Settings.mqtt_user)-1, Settings.mqtt_user); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT FullTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_fulltopic - SetAddr, sizeof(Settings.mqtt_fulltopic)-1, Settings.mqtt_fulltopic); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Topic (%d) [%s]"), (uint8_t *)&Settings.mqtt_topic - SetAddr, sizeof(Settings.mqtt_topic)-1, Settings.mqtt_topic); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT GroupTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_grptopic - SetAddr, sizeof(Settings.mqtt_grptopic)-1, Settings.mqtt_grptopic); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT ButtonTopic (%d) [%s]"), (uint8_t *)&Settings.button_topic - SetAddr, sizeof(Settings.button_topic)-1, Settings.button_topic); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT SwitchTopic (%d) [%s]"), (uint8_t *)&Settings.switch_topic - SetAddr, sizeof(Settings.switch_topic)-1, Settings.switch_topic); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Prefixes (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.mqtt_prefix - SetAddr, sizeof(Settings.mqtt_prefix[0])-1, Settings.mqtt_prefix[0], Settings.mqtt_prefix[1], Settings.mqtt_prefix[2]); + AddLog(LOG_LEVEL_INFO); + if (17 == more) { + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: AP Passwords (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_pwd - SetAddr, sizeof(Settings.sta_pwd[0])-1, Settings.sta_pwd[0], Settings.sta_pwd[1]); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Password (%d) [%s]"), (uint8_t *)&Settings.mqtt_pwd - SetAddr, sizeof(Settings.mqtt_pwd)-1, Settings.mqtt_pwd); + AddLog(LOG_LEVEL_INFO); + snprintf_P(log_data, sizeof(log_data), PSTR("%03X: Web Password (%d) [%s]"), (uint8_t *)&Settings.web_password - SetAddr, sizeof(Settings.web_password)-1, Settings.web_password); + AddLog(LOG_LEVEL_INFO); + } +} + /*******************************************************************************************/ boolean DebugCommand() @@ -333,6 +412,15 @@ boolean DebugCommand() if (-1 == command_code) { serviced = false; // Unknown command } + else if (CMND_HELP == command_code) { + snprintf_P(log_data, sizeof(log_data), kDebugCommands); + AddLog(LOG_LEVEL_INFO); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + } + else if (CMND_RTCDUMP == command_code) { + DebugRtcDump(XdrvMailbox.data); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + } else if (CMND_CFGDUMP == command_code) { DebugCfgDump(XdrvMailbox.data); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); @@ -345,6 +433,10 @@ boolean DebugCommand() DebugCfgPoke(XdrvMailbox.data); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } + else if (CMND_CFGSHOW == command_code) { + DebugCfgShow(XdrvMailbox.payload); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + } #ifdef USE_WEBSERVER else if (CMND_CFGXOR == command_code) { if (XdrvMailbox.data_len > 0) { @@ -366,6 +458,12 @@ boolean DebugCommand() } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, CPU_load_check); } + else if (CMND_FREEMEM == command_code) { + if (XdrvMailbox.data_len > 0) { + CPU_show_freemem = XdrvMailbox.payload; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, CPU_show_freemem); + } else serviced = false; // Unknown command return serviced; @@ -392,7 +490,7 @@ boolean Xdrv99(byte function) result = DebugCommand(); break; case FUNC_FREE_MEM: - DebugFreeMem(); + if (CPU_show_freemem) { DebugFreeMem(); } break; } return result; diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index 3fa12da26..abf11b71f 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -56,7 +56,7 @@ #define MCP_FREQUENCY_GAIN_BASE 0x00AE #define MCP_FREQUENCY_LEN 4 -typedef struct mcp_calibration_registers_type { +typedef struct mcp_cal_registers_type { uint16_t gain_current_rms; uint16_t gain_voltage_rms; uint16_t gain_active_power; @@ -77,24 +77,17 @@ typedef struct mcp_calibration_registers_type { uint32_t calibration_active_power; uint32_t calibration_reactive_power; uint16_t accumulation_interval; -} mcp_calibration_registers_type; -mcp_calibration_registers_type mcp_calibration_registers; +} mcp_cal_registers_type; typedef struct mcp_calibration_setpoint_type { uint32_t calibration_current; uint16_t calibration_voltage; uint32_t calibration_active_power; - uint32_t calibration_reactive_power; +// uint32_t calibration_reactive_power; uint16_t line_frequency_ref; } mcp_calibration_setpoint_type; mcp_calibration_setpoint_type mcp_calibration_setpoint; -typedef struct mcp_frequency_registers_type { - uint16_t line_frequency_ref; - uint16_t gain_line_frequency; -} mcp_frequency_registers_type; -mcp_frequency_registers_type mcp_frequency_registers; - typedef struct mcp_output_registers_type { uint32_t current_rms; uint16_t voltage_rms; @@ -103,15 +96,11 @@ typedef struct mcp_output_registers_type { uint32_t apparent_power; sint16_t power_factor; uint16_t line_frequency; - uint16_t thermistor_voltage; - uint16_t event_flag; - uint16_t system_status; } mcp_output_registers_type; mcp_output_registers_type mcp_output_registers; uint32_t mcp_system_configuration = 0x03000000; -uint16_t mcp_address = 0; -uint8_t mcp_single_wire_active = 0; +uint8_t mcp_address = 0; uint8_t mcp_calibration_active = 0; uint8_t mcp_init = 0; uint8_t mcp_timeout = 0; @@ -128,12 +117,8 @@ uint8_t McpChecksum(uint8_t *data) uint8_t offset = 0; uint8_t len = data[1] -1; - if (MCP_SINGLE_WIRE == data[0]) { - offset = 3; - len = 15; - } for (byte i = offset; i < len; i++) { checksum += data[i]; } - return (MCP_SINGLE_WIRE == data[0]) ? ~checksum : checksum; + return checksum; } unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size) @@ -170,19 +155,83 @@ void McpSend(uint8_t *data) } } -uint32_t McpGetRange(uint8_t shift) +void McpResetSetpoints(void) { - return (mcp_calibration_registers.range >> shift) & 0xFF; + memset(&mcp_calibration_setpoint, 0, sizeof(mcp_calibration_setpoint)); } -void McpSetRange(uint8_t shift, uint32_t range) +/********************************************************************************************/ + +void McpGetAddress(void) { - uint32_t old_range = McpGetRange(shift); - mcp_calibration_registers.range = mcp_calibration_registers.range ^ (old_range << shift); - mcp_calibration_registers.range = mcp_calibration_registers.range | (range << shift); + uint8_t data[] = { MCP_START_FRAME, 7, MCP_SET_ADDRESS, 0x00, 0x26, MCP_READ_16, 0x00 }; + + McpSend(data); } -bool McpCalibrationCalc(uint8_t range_shift) +void McpAddressReceive(void) +{ + // 06 05 004D 58 + mcp_address = serial_in_buffer[3]; +} + +/********************************************************************************************/ + +void McpGetCalibration(void) +{ + if (mcp_calibration_active) { return; } + mcp_calibration_active = 4; + + uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, (MCP_CALIBRATION_BASE >> 8) & 0xFF, MCP_CALIBRATION_BASE & 0xFF, MCP_READ, MCP_CALIBRATION_LEN, 0x00 }; + + McpSend(data); +} + +void McpParseCalibration(void) +{ + bool action = false; + mcp_cal_registers_type cal_registers; + + // 06 37 C882 B6AD 0781 9273 06000000 00000000 00000000 0000 D3FF 0300 00000003 9204 120C1300 204E0000 9808 E0AB0000 D9940000 0200 24 + cal_registers.gain_current_rms = McpExtractInt(serial_in_buffer, 2, 2); + cal_registers.gain_voltage_rms = McpExtractInt(serial_in_buffer, 4, 2); + cal_registers.gain_active_power = McpExtractInt(serial_in_buffer, 6, 2); + cal_registers.gain_reactive_power = McpExtractInt(serial_in_buffer, 8, 2); + cal_registers.offset_current_rms = McpExtractInt(serial_in_buffer, 10, 4); + cal_registers.offset_active_power = McpExtractInt(serial_in_buffer, 14, 4); + cal_registers.offset_reactive_power = McpExtractInt(serial_in_buffer, 18, 4); + cal_registers.dc_offset_current = McpExtractInt(serial_in_buffer, 22, 2); + cal_registers.phase_compensation = McpExtractInt(serial_in_buffer, 24, 2); + cal_registers.apparent_power_divisor = McpExtractInt(serial_in_buffer, 26, 2); + + cal_registers.system_configuration = McpExtractInt(serial_in_buffer, 28, 4); + cal_registers.dio_configuration = McpExtractInt(serial_in_buffer, 32, 2); + cal_registers.range = McpExtractInt(serial_in_buffer, 34, 4); + + cal_registers.calibration_current = McpExtractInt(serial_in_buffer, 38, 4); + cal_registers.calibration_voltage = McpExtractInt(serial_in_buffer, 42, 2); + cal_registers.calibration_active_power = McpExtractInt(serial_in_buffer, 44, 4); + cal_registers.calibration_reactive_power = McpExtractInt(serial_in_buffer, 48, 4); + cal_registers.accumulation_interval = McpExtractInt(serial_in_buffer, 52, 2); + + if (mcp_calibration_setpoint.calibration_active_power) { + cal_registers.calibration_active_power = mcp_calibration_setpoint.calibration_active_power; + if (McpCalibrationCalc(&cal_registers, 16)) { action = true; } + } + if (mcp_calibration_setpoint.calibration_voltage) { + cal_registers.calibration_voltage = mcp_calibration_setpoint.calibration_voltage; + if (McpCalibrationCalc(&cal_registers, 0)) { action = true; } + } + if (mcp_calibration_setpoint.calibration_current) { + cal_registers.calibration_current = mcp_calibration_setpoint.calibration_current; + if (McpCalibrationCalc(&cal_registers, 8)) { action = true; } + } + mcp_timeout = 0; + if (action) { McpSetCalibration(&cal_registers); } + McpResetSetpoints(); +} + +bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t range_shift) { uint32_t measured; uint32_t expected; @@ -191,16 +240,16 @@ bool McpCalibrationCalc(uint8_t range_shift) if (range_shift == 0) { measured = mcp_output_registers.voltage_rms; - expected = mcp_calibration_registers.calibration_voltage; - gain = &(mcp_calibration_registers.gain_voltage_rms); + expected = cal_registers->calibration_voltage; + gain = &(cal_registers->gain_voltage_rms); } else if (range_shift == 8) { measured = mcp_output_registers.current_rms; - expected = mcp_calibration_registers.calibration_current; - gain = &(mcp_calibration_registers.gain_current_rms); + expected = cal_registers->calibration_current; + gain = &(cal_registers->gain_current_rms); } else if (range_shift == 16) { measured = mcp_output_registers.active_power; - expected = mcp_calibration_registers.calibration_active_power; - gain = &(mcp_calibration_registers.gain_active_power); + expected = cal_registers->calibration_active_power; + gain = &(cal_registers->gain_active_power); } else { return false; } @@ -209,7 +258,7 @@ bool McpCalibrationCalc(uint8_t range_shift) return false; } - uint32_t range = McpGetRange(range_shift); + uint32_t range = (cal_registers->range >> range_shift) & 0xFF; calc: new_gain = (*gain) * expected / measured; @@ -229,104 +278,50 @@ calc: } *gain = new_gain; - McpSetRange(range_shift, range); + uint32_t old_range = (cal_registers->range >> range_shift) & 0xFF; + cal_registers->range = cal_registers->range ^ (old_range << range_shift); + cal_registers->range = cal_registers->range | (range << range_shift); return true; } - -void McpCalibrationReactivePower() +/* +void McpCalibrationReactivePower(void) { - mcp_calibration_registers.gain_reactive_power = mcp_calibration_registers.gain_reactive_power * mcp_calibration_registers.calibration_reactive_power / mcp_output_registers.reactive_power; + cal_registers.gain_reactive_power = cal_registers.gain_reactive_power * cal_registers.calibration_reactive_power / mcp_output_registers.reactive_power; } - -void McpCalibrationLineFrequency() -{ - if ((0xFFFF == mcp_output_registers.line_frequency) || (0 == mcp_frequency_registers.gain_line_frequency)) { // Reset values to 50Hz - mcp_output_registers.line_frequency = 50000; - mcp_frequency_registers.gain_line_frequency = 0x8000; - } - mcp_frequency_registers.gain_line_frequency = mcp_frequency_registers.gain_line_frequency * mcp_frequency_registers.line_frequency_ref / mcp_output_registers.line_frequency; -} - -void McpResetSetpoints() -{ - mcp_calibration_setpoint.calibration_active_power = 0; - mcp_calibration_setpoint.calibration_voltage = 0; - mcp_calibration_setpoint.calibration_current = 0; - mcp_calibration_setpoint.calibration_reactive_power = 0; - mcp_calibration_setpoint.line_frequency_ref = 0; -} - -/********************************************************************************************/ - -void McpGetAddress() -{ - // A5 07 41 00 26 52 65 - uint8_t data[7]; - - data[1] = sizeof(data); - data[2] = MCP_SET_ADDRESS; // Set address pointer - data[3] = 0x00; // address - data[4] = 0x26; // address - data[5] = MCP_READ_16; // Read 2 bytes - - McpSend(data); - - // Receives 06 05 004D 58 -} - -void McpGetCalibration() -{ - if (mcp_calibration_active) { return; } - mcp_calibration_active = 4; - - // A5 08 41 00 28 4E 34 98 - uint8_t data[8]; - - data[1] = sizeof(data); - data[2] = MCP_SET_ADDRESS; // Set address pointer - data[3] = (MCP_CALIBRATION_BASE >> 8) & 0xFF; // address - data[4] = (MCP_CALIBRATION_BASE >> 0) & 0xFF; // address - data[5] = MCP_READ; // Read N bytes - data[6] = MCP_CALIBRATION_LEN; - - McpSend(data); - - // Receives 06 37 C882 B6AD 0781 9273 06000000 00000000 00000000 0000 D3FF 0300 00000003 9204 120C1300 204E0000 9808 E0AB0000 D9940000 0200 24 -} - -void McpSetCalibration() +*/ +void McpSetCalibration(struct mcp_cal_registers_type *cal_registers) { uint8_t data[7 + MCP_CALIBRATION_LEN + 2 + 1]; data[1] = sizeof(data); - data[2] = MCP_SET_ADDRESS; // Set address pointer - data[3] = (MCP_CALIBRATION_BASE >> 8) & 0xFF; // address - data[4] = (MCP_CALIBRATION_BASE >> 0) & 0xFF; // address + data[2] = MCP_SET_ADDRESS; // Set address pointer + data[3] = (MCP_CALIBRATION_BASE >> 8) & 0xFF; // address + data[4] = (MCP_CALIBRATION_BASE >> 0) & 0xFF; // address - data[5] = MCP_WRITE; // Write N bytes + data[5] = MCP_WRITE; // Write N bytes data[6] = MCP_CALIBRATION_LEN; - McpSetInt(mcp_calibration_registers.gain_current_rms, data, 0+7, 2); - McpSetInt(mcp_calibration_registers.gain_voltage_rms, data, 2+7, 2); - McpSetInt(mcp_calibration_registers.gain_active_power, data, 4+7, 2); - McpSetInt(mcp_calibration_registers.gain_reactive_power, data, 6+7, 2); - McpSetInt(mcp_calibration_registers.offset_current_rms, data, 8+7, 4); - McpSetInt(mcp_calibration_registers.offset_active_power, data, 12+7, 4); - McpSetInt(mcp_calibration_registers.offset_reactive_power, data, 16+7, 4); - McpSetInt(mcp_calibration_registers.dc_offset_current, data, 20+7, 2); - McpSetInt(mcp_calibration_registers.phase_compensation, data, 22+7, 2); - McpSetInt(mcp_calibration_registers.apparent_power_divisor, data, 24+7, 2); + McpSetInt(cal_registers->gain_current_rms, data, 0+7, 2); + McpSetInt(cal_registers->gain_voltage_rms, data, 2+7, 2); + McpSetInt(cal_registers->gain_active_power, data, 4+7, 2); + McpSetInt(cal_registers->gain_reactive_power, data, 6+7, 2); + McpSetInt(cal_registers->offset_current_rms, data, 8+7, 4); + McpSetInt(cal_registers->offset_active_power, data, 12+7, 4); + McpSetInt(cal_registers->offset_reactive_power, data, 16+7, 4); + McpSetInt(cal_registers->dc_offset_current, data, 20+7, 2); + McpSetInt(cal_registers->phase_compensation, data, 22+7, 2); + McpSetInt(cal_registers->apparent_power_divisor, data, 24+7, 2); - McpSetInt(mcp_calibration_registers.system_configuration, data, 26+7, 4); - McpSetInt(mcp_calibration_registers.dio_configuration, data, 30+7, 2); - McpSetInt(mcp_calibration_registers.range, data, 32+7, 4); + McpSetInt(cal_registers->system_configuration, data, 26+7, 4); + McpSetInt(cal_registers->dio_configuration, data, 30+7, 2); + McpSetInt(cal_registers->range, data, 32+7, 4); - McpSetInt(mcp_calibration_registers.calibration_current, data, 36+7, 4); - McpSetInt(mcp_calibration_registers.calibration_voltage, data, 40+7, 2); - McpSetInt(mcp_calibration_registers.calibration_active_power, data, 42+7, 4); - McpSetInt(mcp_calibration_registers.calibration_reactive_power, data, 46+7, 4); - McpSetInt(mcp_calibration_registers.accumulation_interval, data, 50+7, 2); + McpSetInt(cal_registers->calibration_current, data, 36+7, 4); + McpSetInt(cal_registers->calibration_voltage, data, 40+7, 2); + McpSetInt(cal_registers->calibration_active_power, data, 42+7, 4); + McpSetInt(cal_registers->calibration_reactive_power, data, 46+7, 4); + McpSetInt(cal_registers->accumulation_interval, data, 50+7, 2); data[MCP_CALIBRATION_LEN+7] = MCP_SAVE_REGISTERS; // Save registers to flash data[MCP_CALIBRATION_LEN+8] = mcp_address; // Device address @@ -334,187 +329,123 @@ void McpSetCalibration() McpSend(data); } -void McpGetFrequency() +/********************************************************************************************/ + +void McpGetFrequency(void) { if (mcp_calibration_active) { return; } mcp_calibration_active = 4; - // A5 0B 41 00 94 52 41 00 AE 52 18 - uint8_t data[11]; - - data[1] = sizeof(data); - data[2] = MCP_SET_ADDRESS; // Set address pointer - data[3] = (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF; // address - data[4] = (MCP_FREQUENCY_REF_BASE >> 0) & 0xFF; // address - - data[5] = MCP_READ_16; // Read register - - data[6] = MCP_SET_ADDRESS; // Set address pointer - data[7] = (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF; // address - data[8] = (MCP_FREQUENCY_GAIN_BASE >> 0) & 0xFF; // address - - data[9] = MCP_READ_16; // Read register + uint8_t data[] = { MCP_START_FRAME, 11, MCP_SET_ADDRESS, (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF, MCP_FREQUENCY_REF_BASE & 0xFF, MCP_READ_16, + MCP_SET_ADDRESS, (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF, MCP_FREQUENCY_GAIN_BASE & 0xFF, MCP_READ_16, 0x00 }; McpSend(data); } -void McpSetFrequency() +void McpParseFrequency(void) +{ + // 06 07 C350 8000 A0 + uint16_t line_frequency_ref = serial_in_buffer[2] * 256 + serial_in_buffer[3]; + uint16_t gain_line_frequency = serial_in_buffer[4] * 256 + serial_in_buffer[5]; + + if (mcp_calibration_setpoint.line_frequency_ref) { + line_frequency_ref = mcp_calibration_setpoint.line_frequency_ref; + + if ((0xFFFF == mcp_output_registers.line_frequency) || (0 == gain_line_frequency)) { // Reset values to 50Hz + mcp_output_registers.line_frequency = 50000; + gain_line_frequency = 0x8000; + } + gain_line_frequency = gain_line_frequency * line_frequency_ref / mcp_output_registers.line_frequency; + + mcp_timeout = 0; + McpSetFrequency(line_frequency_ref, gain_line_frequency); + } + McpResetSetpoints(); +} + +void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency) { // A5 11 41 00 94 57 C3 B4 41 00 AE 57 7E 46 53 4D 03 uint8_t data[17]; data[ 1] = sizeof(data); - data[ 2] = MCP_SET_ADDRESS; // Set address pointer + data[ 2] = MCP_SET_ADDRESS; // Set address pointer data[ 3] = (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF; // address data[ 4] = (MCP_FREQUENCY_REF_BASE >> 0) & 0xFF; // address - data[ 5] = MCP_WRITE_16; // Write register - data[ 6] = (mcp_frequency_registers.line_frequency_ref >> 8) & 0xFF; // line_frequency_ref high - data[ 7] = (mcp_frequency_registers.line_frequency_ref >> 0) & 0xFF; // line_frequency_ref low + data[ 5] = MCP_WRITE_16; // Write register + data[ 6] = (line_frequency_ref >> 8) & 0xFF; // line_frequency_ref high + data[ 7] = (line_frequency_ref >> 0) & 0xFF; // line_frequency_ref low - data[ 8] = MCP_SET_ADDRESS; // Set address pointer - data[ 9] = (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF; // address - data[10] = (MCP_FREQUENCY_GAIN_BASE >> 0) & 0xFF; // address + data[ 8] = MCP_SET_ADDRESS; // Set address pointer + data[ 9] = (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF; // address + data[10] = (MCP_FREQUENCY_GAIN_BASE >> 0) & 0xFF; // address - data[11] = MCP_WRITE_16; // Write register - data[12] = (mcp_frequency_registers.gain_line_frequency >> 8) & 0xFF; // gain_line_frequency high - data[13] = (mcp_frequency_registers.gain_line_frequency >> 0) & 0xFF; // gain_line_frequency low + data[11] = MCP_WRITE_16; // Write register + data[12] = (gain_line_frequency >> 8) & 0xFF; // gain_line_frequency high + data[13] = (gain_line_frequency >> 0) & 0xFF; // gain_line_frequency low - data[14] = MCP_SAVE_REGISTERS; // Save registers to flash - data[15] = mcp_address; // Device address + data[14] = MCP_SAVE_REGISTERS; // Save registers to flash + data[15] = mcp_address; // Device address McpSend(data); } +/********************************************************************************************/ + void McpSetSystemConfiguration(uint16 interval) { // A5 11 41 00 42 45 03 00 01 00 41 00 5A 57 00 06 7A uint8_t data[17]; data[ 1] = sizeof(data); - data[ 2] = MCP_SET_ADDRESS; // Set address pointer - data[ 3] = 0x00; // address - data[ 4] = 0x42; // address - data[ 5] = MCP_WRITE_32; // Write 4 bytes - data[ 6] = (mcp_system_configuration >> 24) & 0xFF; // system_configuration - data[ 7] = (mcp_system_configuration >> 16) & 0xFF; // system_configuration - data[ 8] = (mcp_system_configuration >> 8) & 0xFF; // system_configuration - data[ 9] = (mcp_system_configuration >> 0) & 0xFF; // system_configuration - data[10] = MCP_SET_ADDRESS; // Set address pointer - data[11] = 0x00; // address - data[12] = 0x5A; // address - data[13] = MCP_WRITE_16; // Write 2 bytes - data[14] = (interval >> 8) & 0xFF; // interval - data[15] = (interval >> 0) & 0xFF; // interval + data[ 2] = MCP_SET_ADDRESS; // Set address pointer + data[ 3] = 0x00; // address + data[ 4] = 0x42; // address + data[ 5] = MCP_WRITE_32; // Write 4 bytes + data[ 6] = (mcp_system_configuration >> 24) & 0xFF; // system_configuration + data[ 7] = (mcp_system_configuration >> 16) & 0xFF; // system_configuration + data[ 8] = (mcp_system_configuration >> 8) & 0xFF; // system_configuration + data[ 9] = (mcp_system_configuration >> 0) & 0xFF; // system_configuration + data[10] = MCP_SET_ADDRESS; // Set address pointer + data[11] = 0x00; // address + data[12] = 0x5A; // address + data[13] = MCP_WRITE_16; // Write 2 bytes + data[14] = (interval >> 8) & 0xFF; // interval + data[15] = (interval >> 0) & 0xFF; // interval McpSend(data); } -void McpSingleWireStart() -{ - if ((mcp_system_configuration & (1 << 8)) != 0) { return; } - mcp_system_configuration = mcp_system_configuration | (1 << 8); - McpSetSystemConfiguration(6); // 64 - mcp_single_wire_active = 1; -} - void McpSingleWireStop(uint8_t force) { if (!force && ((mcp_system_configuration & (1 << 8)) == 0)) { return; } mcp_system_configuration = mcp_system_configuration & (~(1 << 8)); McpSetSystemConfiguration(2); // 4 - mcp_single_wire_active = 0; } /********************************************************************************************/ -void McpAddressReceive() +void McpGetData(void) { - // 06 05 004D 58 - mcp_address = serial_in_buffer[2] * 256 + serial_in_buffer[3]; + uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, 0x00, 0x04, MCP_READ, 22, 0x00 }; + + McpSend(data); } -void McpParseCalibration() +void McpParseData(void) { - bool action = false; + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + // 06 19 61 06 00 00 FE 08 9B 0E 00 00 0B 00 00 00 97 0E 00 00 FF 7F 0C C6 35 + // 06 19 CE 18 00 00 F2 08 3A 38 00 00 66 00 00 00 93 38 00 00 36 7F 9A C6 B7 + // Ak Ln Current---- Volt- ActivePower ReActivePow ApparentPow Factr Frequ Ck - // 06 37 C882 B6AD 0781 9273 06000000 00000000 00000000 0000 D3FF 0300 00000003 9204 120C1300 204E0000 9808 E0AB0000 D9940000 0200 24 - mcp_calibration_registers.gain_current_rms = McpExtractInt(serial_in_buffer, 2, 2); - mcp_calibration_registers.gain_voltage_rms = McpExtractInt(serial_in_buffer, 4, 2); - mcp_calibration_registers.gain_active_power = McpExtractInt(serial_in_buffer, 6, 2); - mcp_calibration_registers.gain_reactive_power = McpExtractInt(serial_in_buffer, 8, 2); - mcp_calibration_registers.offset_current_rms = McpExtractInt(serial_in_buffer, 10, 4); - mcp_calibration_registers.offset_active_power = McpExtractInt(serial_in_buffer, 14, 4); - mcp_calibration_registers.offset_reactive_power = McpExtractInt(serial_in_buffer, 18, 4); - mcp_calibration_registers.dc_offset_current = McpExtractInt(serial_in_buffer, 22, 2); - mcp_calibration_registers.phase_compensation = McpExtractInt(serial_in_buffer, 24, 2); - mcp_calibration_registers.apparent_power_divisor = McpExtractInt(serial_in_buffer, 26, 2); - - mcp_calibration_registers.system_configuration = McpExtractInt(serial_in_buffer, 28, 4); - mcp_calibration_registers.dio_configuration = McpExtractInt(serial_in_buffer, 32, 2); - mcp_calibration_registers.range = McpExtractInt(serial_in_buffer, 34, 4); - - mcp_calibration_registers.calibration_current = McpExtractInt(serial_in_buffer, 38, 4); - mcp_calibration_registers.calibration_voltage = McpExtractInt(serial_in_buffer, 42, 2); - mcp_calibration_registers.calibration_active_power = McpExtractInt(serial_in_buffer, 44, 4); - mcp_calibration_registers.calibration_reactive_power = McpExtractInt(serial_in_buffer, 48, 4); - mcp_calibration_registers.accumulation_interval = McpExtractInt(serial_in_buffer, 52, 2); - - if (mcp_calibration_setpoint.calibration_active_power) { - mcp_calibration_registers.calibration_active_power = mcp_calibration_setpoint.calibration_active_power; - if (McpCalibrationCalc(16)) { action = true; } - } - if (mcp_calibration_setpoint.calibration_voltage) { - mcp_calibration_registers.calibration_voltage = mcp_calibration_setpoint.calibration_voltage; - if (McpCalibrationCalc(0)) { action = true; } - } - if (mcp_calibration_setpoint.calibration_current) { - mcp_calibration_registers.calibration_current = mcp_calibration_setpoint.calibration_current; - if (McpCalibrationCalc(8)) { action = true; } - } - mcp_timeout = 0; - if (action) { McpSetCalibration(); } - McpResetSetpoints(); -} - -void McpParseFrequency() -{ - // 06 07 C350 8000 A0 - mcp_frequency_registers.line_frequency_ref = serial_in_buffer[2] * 256 + serial_in_buffer[3]; - mcp_frequency_registers.gain_line_frequency = serial_in_buffer[4] * 256 + serial_in_buffer[5]; - - if (mcp_calibration_setpoint.line_frequency_ref) { - mcp_frequency_registers.line_frequency_ref = mcp_calibration_setpoint.line_frequency_ref; - McpCalibrationLineFrequency(); - mcp_timeout = 0; - McpSetFrequency(); - } - McpResetSetpoints(); -} - -void McpParseData(uint8_t single_wire) -{ - if (single_wire) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - // AB CD EF 51 06 00 00 B8 08 FC 0D 00 00 0A C4 11 - // Header-- Current---- Volt- Power------ Freq- Ck - - mcp_output_registers.current_rms = McpExtractInt(serial_in_buffer, 3, 4); - mcp_output_registers.voltage_rms = McpExtractInt(serial_in_buffer, 7, 2); - mcp_output_registers.active_power = McpExtractInt(serial_in_buffer, 9, 4); - mcp_output_registers.line_frequency = McpExtractInt(serial_in_buffer, 13, 2); - } else { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 - // 06 19 61 06 00 00 FE 08 9B 0E 00 00 0B 00 00 00 97 0E 00 00 FF 7F 0C C6 35 - // 06 19 CE 18 00 00 F2 08 3A 38 00 00 66 00 00 00 93 38 00 00 36 7F 9A C6 B7 - // Ak Ln Current---- Volt- ActivePower ReActivePow ApparentPow Factr Frequ Ck - - mcp_output_registers.current_rms = McpExtractInt(serial_in_buffer, 2, 4); - mcp_output_registers.voltage_rms = McpExtractInt(serial_in_buffer, 6, 2); - mcp_output_registers.active_power = McpExtractInt(serial_in_buffer, 8, 4); - mcp_output_registers.reactive_power = McpExtractInt(serial_in_buffer, 12, 4); - mcp_output_registers.line_frequency = McpExtractInt(serial_in_buffer, 22, 2); - } + mcp_output_registers.current_rms = McpExtractInt(serial_in_buffer, 2, 4); + mcp_output_registers.voltage_rms = McpExtractInt(serial_in_buffer, 6, 2); + mcp_output_registers.active_power = McpExtractInt(serial_in_buffer, 8, 4); +// mcp_output_registers.reactive_power = McpExtractInt(serial_in_buffer, 12, 4); +// mcp_output_registers.power_factor = McpExtractInt(serial_in_buffer, 20, 2); + mcp_output_registers.line_frequency = McpExtractInt(serial_in_buffer, 22, 2); if (energy_power_on) { // Powered on energy_frequency = (float)mcp_output_registers.line_frequency / 1000; @@ -533,7 +464,9 @@ void McpParseData(uint8_t single_wire) } } -bool McpSerialInput() +/********************************************************************************************/ + +bool McpSerialInput(void) { serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; unsigned long start = millis(); @@ -564,7 +497,7 @@ bool McpSerialInput() AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); } else { if (5 == serial_in_buffer[1]) { McpAddressReceive(); } - if (25 == serial_in_buffer[1]) { McpParseData(0); } + if (25 == serial_in_buffer[1]) { McpParseData(); } if (MCP_CALIBRATION_LEN + 3 == serial_in_buffer[1]) { McpParseCalibration(); } if (MCP_FREQUENCY_LEN + 3 == serial_in_buffer[1]) { McpParseFrequency(); } } @@ -573,15 +506,6 @@ bool McpSerialInput() mcp_timeout = 0; } else if (MCP_SINGLE_WIRE == serial_in_buffer[0]) { - if (serial_in_byte_counter == 16) { - - if (McpChecksum((uint8_t *)serial_in_buffer) != serial_in_buffer[serial_in_byte_counter -1]) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); - } else { - McpParseData(1); - } - - } mcp_timeout = 0; } return 1; @@ -589,10 +513,8 @@ bool McpSerialInput() /********************************************************************************************/ -void McpEverySecond() +void McpEverySecond(void) { - uint8_t get_state[] = { 0xA5, 0x08, 0x41, 0x00, 0x04, 0x4E, 0x16, 0x00 }; - if (mcp_output_registers.active_power) { energy_kWhtoday_delta += ((mcp_output_registers.active_power * 10) / 36); EnergyUpdateToday(); @@ -611,18 +533,18 @@ void McpEverySecond() else if (!mcp_address) { McpGetAddress(); } - else if (!mcp_single_wire_active) { - McpSend(get_state); + else { + McpGetData(); } } -void McpSnsInit() +void McpSnsInit(void) { SetSeriallog(LOG_LEVEL_NONE); // Free serial interface from logging interference digitalWrite(15, 1); // GPIO15 - MCP enable } -void McpDrvInit() +void McpDrvInit(void) { if (!energy_flg) { if (SHELLY2 == Settings.module) { @@ -638,7 +560,7 @@ void McpDrvInit() } } -boolean McpCommand() +boolean McpCommand(void) { boolean serviced = true; unsigned long value = 0; From ecd3175257360ac13c46042000c1297acd385242 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 24 Sep 2018 16:16:14 -0300 Subject: [PATCH 0137/2222] Prevent Command NtpServer to restart Tasmota #3890 --- sonoff/sonoff.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 91c1fbb9b..2e64b9046 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1043,7 +1043,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) for (i = 0; i < strlen(Settings.ntp_server[index -1]); i++) { if (Settings.ntp_server[index -1][i] == ',') Settings.ntp_server[index -1][i] = '.'; } - restart_flag = 2; +// restart_flag = 2; } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.ntp_server[index -1]); } From 2029440fae58b204e1d23c50e6b74fbb1383388e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 25 Sep 2018 11:35:37 +0200 Subject: [PATCH 0138/2222] 6.2.1.7 Fix NTPserver change 6.2.1.7 20180925 * Remove restart after ntpserver change and force NTP re-sync (#3890) * Release full Shelly2 support --- sonoff/_changelog.ino | 6 +- sonoff/sonoff.ino | 3 +- sonoff/sonoff_version.h | 2 +- sonoff/xnrg_04_mcp39f501.ino | 213 ++++++++++++++++++----------------- 4 files changed, 116 insertions(+), 108 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b7988c69c..5aa6e9e13 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ -/* 6.2.1.6 20180922 +/* 6.2.1.7 20180925 + * Remove restart after ntpserver change and force NTP re-sync (#3890) + * Release full Shelly2 support + * + * 6.2.1.6 20180922 * Removed commands PowerCal, VoltageCal and CurrentCal as more functionality is provided by commands PowerSet, VoltageSet and CurrentSet * Allow decimals as input to commands PowerSet, VoltageSet and CurrentSet * Add support for PCA9685 12bit 16pin hardware PWM driver (#3866) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 2e64b9046..f0619f362 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1043,7 +1043,8 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) for (i = 0; i < strlen(Settings.ntp_server[index -1]); i++) { if (Settings.ntp_server[index -1][i] == ',') Settings.ntp_server[index -1][i] = '.'; } -// restart_flag = 2; +// restart_flag = 2; // Issue #3890 + ntp_force_sync = 1; } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.ntp_server[index -1]); } diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 228a48d92..16c554783 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020106 +#define VERSION 0x06020107 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index abf11b71f..f2ce321bc 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -29,6 +29,13 @@ #define XNRG_04 4 #define MCP_TIMEOUT 4 +#define MCP_CALIBRATION_TIMEOUT 2 + +#define MCP_CALIBRATE_POWER 0x001 +#define MCP_CALIBRATE_VOLTAGE 0x002 +#define MCP_CALIBRATE_CURRENT 0x004 +#define MCP_CALIBRATE_FREQUENCY 0x008 +#define MCP_SINGLE_WIRE_FLAG 0x100 #define MCP_START_FRAME 0xA5 #define MCP_ACK_FRAME 0x06 @@ -79,32 +86,20 @@ typedef struct mcp_cal_registers_type { uint16_t accumulation_interval; } mcp_cal_registers_type; -typedef struct mcp_calibration_setpoint_type { - uint32_t calibration_current; - uint16_t calibration_voltage; - uint32_t calibration_active_power; -// uint32_t calibration_reactive_power; - uint16_t line_frequency_ref; -} mcp_calibration_setpoint_type; -mcp_calibration_setpoint_type mcp_calibration_setpoint; - -typedef struct mcp_output_registers_type { - uint32_t current_rms; - uint16_t voltage_rms; - uint32_t active_power; - uint32_t reactive_power; - uint32_t apparent_power; - sint16_t power_factor; - uint16_t line_frequency; -} mcp_output_registers_type; -mcp_output_registers_type mcp_output_registers; - +unsigned long mcp_kWhcounter = 0; uint32_t mcp_system_configuration = 0x03000000; +uint32_t mcp_active_power; +//uint32_t mcp_reactive_power; +//uint32_t mcp_apparent_power; +uint32_t mcp_current_rms; +uint16_t mcp_voltage_rms; +uint16_t mcp_line_frequency; +//sint16_t mcp_power_factor; uint8_t mcp_address = 0; uint8_t mcp_calibration_active = 0; uint8_t mcp_init = 0; uint8_t mcp_timeout = 0; -unsigned long mcp_kWhcounter = 0; +uint8_t mcp_calibrate = 0; /*********************************************************************************************\ * Olimex tools @@ -155,11 +150,6 @@ void McpSend(uint8_t *data) } } -void McpResetSetpoints(void) -{ - memset(&mcp_calibration_setpoint, 0, sizeof(mcp_calibration_setpoint)); -} - /********************************************************************************************/ void McpGetAddress(void) @@ -180,7 +170,7 @@ void McpAddressReceive(void) void McpGetCalibration(void) { if (mcp_calibration_active) { return; } - mcp_calibration_active = 4; + mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, (MCP_CALIBRATION_BASE >> 8) & 0xFF, MCP_CALIBRATION_BASE & 0xFF, MCP_READ, MCP_CALIBRATION_LEN, 0x00 }; @@ -214,21 +204,33 @@ void McpParseCalibration(void) cal_registers.calibration_reactive_power = McpExtractInt(serial_in_buffer, 48, 4); cal_registers.accumulation_interval = McpExtractInt(serial_in_buffer, 52, 2); - if (mcp_calibration_setpoint.calibration_active_power) { - cal_registers.calibration_active_power = mcp_calibration_setpoint.calibration_active_power; + if (mcp_calibrate & MCP_CALIBRATE_POWER) { + cal_registers.calibration_active_power = Settings.energy_power_calibration; if (McpCalibrationCalc(&cal_registers, 16)) { action = true; } } - if (mcp_calibration_setpoint.calibration_voltage) { - cal_registers.calibration_voltage = mcp_calibration_setpoint.calibration_voltage; + if (mcp_calibrate & MCP_CALIBRATE_VOLTAGE) { + cal_registers.calibration_voltage = Settings.energy_voltage_calibration; if (McpCalibrationCalc(&cal_registers, 0)) { action = true; } } - if (mcp_calibration_setpoint.calibration_current) { - cal_registers.calibration_current = mcp_calibration_setpoint.calibration_current; + if (mcp_calibrate & MCP_CALIBRATE_CURRENT) { + cal_registers.calibration_current = Settings.energy_current_calibration; if (McpCalibrationCalc(&cal_registers, 8)) { action = true; } } mcp_timeout = 0; if (action) { McpSetCalibration(&cal_registers); } - McpResetSetpoints(); + + mcp_calibrate = 0; + + Settings.energy_power_calibration = cal_registers.calibration_active_power; + Settings.energy_voltage_calibration = cal_registers.calibration_voltage; + Settings.energy_current_calibration = cal_registers.calibration_current; + + mcp_system_configuration = cal_registers.system_configuration; + + if (mcp_system_configuration & MCP_SINGLE_WIRE_FLAG) { + mcp_system_configuration &= ~MCP_SINGLE_WIRE_FLAG; // Reset SingleWire flag + McpSetSystemConfiguration(2); + } } bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t range_shift) @@ -239,15 +241,15 @@ bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t ra uint32_t new_gain; if (range_shift == 0) { - measured = mcp_output_registers.voltage_rms; + measured = mcp_voltage_rms; expected = cal_registers->calibration_voltage; gain = &(cal_registers->gain_voltage_rms); } else if (range_shift == 8) { - measured = mcp_output_registers.current_rms; + measured = mcp_current_rms; expected = cal_registers->calibration_current; gain = &(cal_registers->gain_current_rms); } else if (range_shift == 16) { - measured = mcp_output_registers.active_power; + measured = mcp_active_power; expected = cal_registers->calibration_active_power; gain = &(cal_registers->gain_active_power); } else { @@ -287,7 +289,7 @@ calc: /* void McpCalibrationReactivePower(void) { - cal_registers.gain_reactive_power = cal_registers.gain_reactive_power * cal_registers.calibration_reactive_power / mcp_output_registers.reactive_power; + cal_registers.gain_reactive_power = cal_registers.gain_reactive_power * cal_registers.calibration_reactive_power / mcp_reactive_power; } */ void McpSetCalibration(struct mcp_cal_registers_type *cal_registers) @@ -331,10 +333,36 @@ void McpSetCalibration(struct mcp_cal_registers_type *cal_registers) /********************************************************************************************/ +void McpSetSystemConfiguration(uint16 interval) +{ + // A5 11 41 00 42 45 03 00 01 00 41 00 5A 57 00 06 7A + uint8_t data[17]; + + data[ 1] = sizeof(data); + data[ 2] = MCP_SET_ADDRESS; // Set address pointer + data[ 3] = 0x00; // address + data[ 4] = 0x42; // address + data[ 5] = MCP_WRITE_32; // Write 4 bytes + data[ 6] = (mcp_system_configuration >> 24) & 0xFF; // system_configuration + data[ 7] = (mcp_system_configuration >> 16) & 0xFF; // system_configuration + data[ 8] = (mcp_system_configuration >> 8) & 0xFF; // system_configuration + data[ 9] = (mcp_system_configuration >> 0) & 0xFF; // system_configuration + data[10] = MCP_SET_ADDRESS; // Set address pointer + data[11] = 0x00; // address + data[12] = 0x5A; // address + data[13] = MCP_WRITE_16; // Write 2 bytes + data[14] = (interval >> 8) & 0xFF; // interval + data[15] = (interval >> 0) & 0xFF; // interval + + McpSend(data); +} + +/********************************************************************************************/ + void McpGetFrequency(void) { if (mcp_calibration_active) { return; } - mcp_calibration_active = 4; + mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; uint8_t data[] = { MCP_START_FRAME, 11, MCP_SET_ADDRESS, (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF, MCP_FREQUENCY_REF_BASE & 0xFF, MCP_READ_16, MCP_SET_ADDRESS, (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF, MCP_FREQUENCY_GAIN_BASE & 0xFF, MCP_READ_16, 0x00 }; @@ -348,19 +376,22 @@ void McpParseFrequency(void) uint16_t line_frequency_ref = serial_in_buffer[2] * 256 + serial_in_buffer[3]; uint16_t gain_line_frequency = serial_in_buffer[4] * 256 + serial_in_buffer[5]; - if (mcp_calibration_setpoint.line_frequency_ref) { - line_frequency_ref = mcp_calibration_setpoint.line_frequency_ref; + if (mcp_calibrate & MCP_CALIBRATE_FREQUENCY) { + line_frequency_ref = Settings.energy_frequency_calibration; - if ((0xFFFF == mcp_output_registers.line_frequency) || (0 == gain_line_frequency)) { // Reset values to 50Hz - mcp_output_registers.line_frequency = 50000; + if ((0xFFFF == mcp_line_frequency) || (0 == gain_line_frequency)) { // Reset values to 50Hz + mcp_line_frequency = 50000; gain_line_frequency = 0x8000; } - gain_line_frequency = gain_line_frequency * line_frequency_ref / mcp_output_registers.line_frequency; + gain_line_frequency = gain_line_frequency * line_frequency_ref / mcp_line_frequency; mcp_timeout = 0; McpSetFrequency(line_frequency_ref, gain_line_frequency); } - McpResetSetpoints(); + + Settings.energy_frequency_calibration = line_frequency_ref; + + mcp_calibrate = 0; } void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency) @@ -393,39 +424,6 @@ void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency) /********************************************************************************************/ -void McpSetSystemConfiguration(uint16 interval) -{ - // A5 11 41 00 42 45 03 00 01 00 41 00 5A 57 00 06 7A - uint8_t data[17]; - - data[ 1] = sizeof(data); - data[ 2] = MCP_SET_ADDRESS; // Set address pointer - data[ 3] = 0x00; // address - data[ 4] = 0x42; // address - data[ 5] = MCP_WRITE_32; // Write 4 bytes - data[ 6] = (mcp_system_configuration >> 24) & 0xFF; // system_configuration - data[ 7] = (mcp_system_configuration >> 16) & 0xFF; // system_configuration - data[ 8] = (mcp_system_configuration >> 8) & 0xFF; // system_configuration - data[ 9] = (mcp_system_configuration >> 0) & 0xFF; // system_configuration - data[10] = MCP_SET_ADDRESS; // Set address pointer - data[11] = 0x00; // address - data[12] = 0x5A; // address - data[13] = MCP_WRITE_16; // Write 2 bytes - data[14] = (interval >> 8) & 0xFF; // interval - data[15] = (interval >> 0) & 0xFF; // interval - - McpSend(data); -} - -void McpSingleWireStop(uint8_t force) -{ - if (!force && ((mcp_system_configuration & (1 << 8)) == 0)) { return; } - mcp_system_configuration = mcp_system_configuration & (~(1 << 8)); - McpSetSystemConfiguration(2); // 4 -} - -/********************************************************************************************/ - void McpGetData(void) { uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, 0x00, 0x04, MCP_READ, 22, 0x00 }; @@ -440,21 +438,21 @@ void McpParseData(void) // 06 19 CE 18 00 00 F2 08 3A 38 00 00 66 00 00 00 93 38 00 00 36 7F 9A C6 B7 // Ak Ln Current---- Volt- ActivePower ReActivePow ApparentPow Factr Frequ Ck - mcp_output_registers.current_rms = McpExtractInt(serial_in_buffer, 2, 4); - mcp_output_registers.voltage_rms = McpExtractInt(serial_in_buffer, 6, 2); - mcp_output_registers.active_power = McpExtractInt(serial_in_buffer, 8, 4); -// mcp_output_registers.reactive_power = McpExtractInt(serial_in_buffer, 12, 4); -// mcp_output_registers.power_factor = McpExtractInt(serial_in_buffer, 20, 2); - mcp_output_registers.line_frequency = McpExtractInt(serial_in_buffer, 22, 2); + mcp_current_rms = McpExtractInt(serial_in_buffer, 2, 4); + mcp_voltage_rms = McpExtractInt(serial_in_buffer, 6, 2); + mcp_active_power = McpExtractInt(serial_in_buffer, 8, 4); +// mcp_reactive_power = McpExtractInt(serial_in_buffer, 12, 4); +// mcp_power_factor = McpExtractInt(serial_in_buffer, 20, 2); + mcp_line_frequency = McpExtractInt(serial_in_buffer, 22, 2); if (energy_power_on) { // Powered on - energy_frequency = (float)mcp_output_registers.line_frequency / 1000; - energy_voltage = (float)mcp_output_registers.voltage_rms / 10; - energy_power = (float)mcp_output_registers.active_power / 100; + energy_frequency = (float)mcp_line_frequency / 1000; + energy_voltage = (float)mcp_voltage_rms / 10; + energy_power = (float)mcp_active_power / 100; if (0 == energy_power) { energy_current = 0; } else { - energy_current = (float)mcp_output_registers.current_rms / 10000; + energy_current = (float)mcp_current_rms / 10000; } } else { // Powered off energy_frequency = 0; @@ -515,8 +513,8 @@ bool McpSerialInput(void) void McpEverySecond(void) { - if (mcp_output_registers.active_power) { - energy_kWhtoday_delta += ((mcp_output_registers.active_power * 10) / 36); + if (mcp_active_power) { + energy_kWhtoday_delta += ((mcp_active_power * 10) / 36); EnergyUpdateToday(); } @@ -527,14 +525,19 @@ void McpEverySecond(void) mcp_calibration_active--; } else if (mcp_init) { - McpSingleWireStop(1); - mcp_init = 0; + if (2 == mcp_init) { + McpGetCalibration(); // Get calibration parameters and disable SingleWire mode if enabled + } + else if (1 == mcp_init) { + McpGetFrequency(); // Get calibration parameter + } + mcp_init--; } else if (!mcp_address) { - McpGetAddress(); + McpGetAddress(); // Get device address for future calibration changes } else { - McpGetData(); + McpGetData(); // Get energy data } } @@ -551,10 +554,10 @@ void McpDrvInit(void) pinMode(15, OUTPUT); digitalWrite(15, 0); // GPIO15 - MCP disable - Reset Delta Sigma ADC's baudrate = 4800; + mcp_calibrate = 0; + mcp_timeout = 2; // Initial wait + mcp_init = 2; // Initial setup steps energy_calc_power_factor = 1; // Calculate power factor from data - mcp_timeout = 4; // Wait for initialization - mcp_init = 1; // Execute initial setup - McpResetSetpoints(); energy_flg = XNRG_04; } } @@ -566,41 +569,41 @@ boolean McpCommand(void) unsigned long value = 0; if (CMND_POWERSET == energy_command_code) { - if (XdrvMailbox.data_len && mcp_output_registers.active_power) { + if (XdrvMailbox.data_len && mcp_active_power) { value = (unsigned long)(CharToDouble(XdrvMailbox.data) * 100); if ((value > 100) && (value < 200000)) { // Between 1W and 2000W Settings.energy_power_calibration = value; - mcp_calibration_setpoint.calibration_active_power = value; + mcp_calibrate |= MCP_CALIBRATE_POWER; McpGetCalibration(); } } } else if (CMND_VOLTAGESET == energy_command_code) { - if (XdrvMailbox.data_len && mcp_output_registers.voltage_rms) { + if (XdrvMailbox.data_len && mcp_voltage_rms) { value = (unsigned long)(CharToDouble(XdrvMailbox.data) * 10); if ((value > 1000) && (value < 2600)) { // Between 100V and 260V Settings.energy_voltage_calibration = value; - mcp_calibration_setpoint.calibration_voltage = value; + mcp_calibrate |= MCP_CALIBRATE_VOLTAGE; McpGetCalibration(); } } } else if (CMND_CURRENTSET == energy_command_code) { - if (XdrvMailbox.data_len && mcp_output_registers.current_rms) { + if (XdrvMailbox.data_len && mcp_current_rms) { value = (unsigned long)(CharToDouble(XdrvMailbox.data) * 10); if ((value > 100) && (value < 80000)) { // Between 10mA and 8A Settings.energy_current_calibration = value; - mcp_calibration_setpoint.calibration_current = value; + mcp_calibrate |= MCP_CALIBRATE_CURRENT; McpGetCalibration(); } } } else if (CMND_FREQUENCYSET == energy_command_code) { - if (XdrvMailbox.data_len && mcp_output_registers.line_frequency) { + if (XdrvMailbox.data_len && mcp_line_frequency) { value = (unsigned long)(CharToDouble(XdrvMailbox.data) * 1000); if ((value > 45000) && (value < 65000)) { // Between 45Hz and 65Hz Settings.energy_frequency_calibration = value; - mcp_calibration_setpoint.line_frequency_ref = value; + mcp_calibrate |= MCP_CALIBRATE_FREQUENCY; McpGetFrequency(); } } From ec421e614477115c99c67275bfafa5ecf33a8eb4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 25 Sep 2018 14:08:36 +0200 Subject: [PATCH 0139/2222] Released decode-config.py Released tools/decode-config.py by Norbert Richter to decode configuration data. --- sonoff/_changelog.ino | 1 + tools/decode-config.py | 1924 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1925 insertions(+) create mode 100644 tools/decode-config.py diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 5aa6e9e13..333a524a6 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.2.1.7 20180925 * Remove restart after ntpserver change and force NTP re-sync (#3890) * Release full Shelly2 support + * Released tools/decode-config.py by Norbert Richter to decode configuration data. See file for information * * 6.2.1.6 20180922 * Removed commands PowerCal, VoltageCal and CurrentCal as more functionality is provided by commands PowerSet, VoltageSet and CurrentSet diff --git a/tools/decode-config.py b/tools/decode-config.py new file mode 100644 index 000000000..299f152c4 --- /dev/null +++ b/tools/decode-config.py @@ -0,0 +1,1924 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" + decode-config.py - Decode configuration of Sonoff-Tasmota device + + Copyright (C) 2018 Norbert Richter + + 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 . + +Requirements: + - Python + - pip json pycurl urllib2 configargparse + +Instructions: + Execute command with option -d to retrieve config data from device or + use -f to read out a previously saved configuration file. + + For help execute command with argument -h + + +Usage: + decode-config.py [-h] [-f ] [-d ] + [-u ] [-p ] [--format ] + [--sort ] [--raw] [--unhide-pw] [-o ] + [-c ] [-V] + + Decode configuration of Sonoff-Tasmota device. Args that start with '--' (eg. + -f) can also be set in a config file (specified via -c). Config file syntax + allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at + https://goo.gl/R74nmi). If an arg is specified in more than one place, then + commandline values override config file values which override defaults. + + optional arguments: + -h, --help show this help message and exit + -c , --config + Config file, can be used instead of command parameter + (defaults to None) + + source: + -f , --file + file to retrieve Tasmota configuration from (default: + None) + -d , --device + device to retrieve configuration from (default: None) + -u , --username + for -d usage: http access username (default: admin) + -p , --password + for -d usage: http access password (default: None) + + output: + --format output format ("json" or "text", default: "json") + --sort sort result - can be "none" or "name" (default: + "name") + --raw output raw values (default: processed) + --unhide-pw unhide passwords (default: hide) + -o , --output-file + file to store decrypted raw binary configuration to + (default: None) + + info: + -V, --version show program's version number and exit + + Note: Either argument -d or -f must be given. + + +Examples: + Read configuration from hostname 'sonoff1' and output default json config + ./decode-config.py -d sonoff1 + + Read configuration from file 'Config__6.2.1.dmp' and output default json config + ./decode-config.py -f Config__6.2.1.dmp + + Read configuration from hostname 'sonoff1' using web login data + ./decode-config.py -d sonoff1 -u admin -p xxxx + + Read configuration from hostname 'sonoff1' using web login data and unhide passwords + ./decode-config.py -d sonoff1 -u admin -p xxxx --unhide-pw + + Read configuration from hostname 'sonoff1' using web login data, unhide passwords + and sort key names + ./decode-config.py -d sonoff1 -u admin -p xxxx --unhide-pw --sort name +""" + +import os.path +import io +import sys +import configargparse +import collections +import struct +import re +import json +try: + import pycurl +except ImportError: + print("module not found. Try 'pip pycurl' to install it") + sys.exit(9) +try: + import urllib2 +except ImportError: + print("module not found. Try 'pip urllib2' to install it") + sys.exit(9) + + +VER = '1.5.0008' +PROG='{} v{} by Norbert Richter'.format(os.path.basename(sys.argv[0]),VER) + +CONFIG_FILE_XOR = 0x5A + + +args = {} +DEFAULTS = { + 'DEFAULT': + { + 'configfile': None, + }, + 'source': + { + 'device': None, + 'username': 'admin', + 'password': None, + 'tasmotafile': None, + }, + 'output': + { + 'format': 'json', + 'sort': 'name', + 'raw': False, + 'unhide-pw': False, + 'outputfile': None, + }, +} + + +""" +Settings dictionary describes the config file fields definition: + + Each setting name has a tuple containing the following items: + + (format, baseaddr, datadef, ) + + where + + format + Define the data interpretation. + For details see struct module format string + https://docs.python.org/2.7/library/struct.html#format-strings + + baseaddr + The address (starting from 0) within config data + + datadef + Define the field interpretation different from simple + standard types (like char, byte, int) e. g. lists or bit fields + Can be None, a single integer, a list or a dictionary + None: + None must be given if the field contains a simple value + desrcibed by the prefix + n: + Same as [n] below + [n]: + Defines a one-dimensional array of size + [n, n <,n...>] + Defines a multi-dimensional array + [{} <,{}...] + Defines a bit struct. The items are simply dict + {'bitname', bitlen}, the dict order is important. + + convert (optional) + Define an output/conversion methode, can be a simple string + or a previously defined function name. + 'xxx': + a string defines a format specification of the string + formatter, see + https://docs.python.org/2.7/library/string.html#format-string-syntax + func: + a function defines the name of a formating function + +""" +# config data conversion function and helper +def baudrate(value): + return value * 1200 + +def int2ip(value): + return '{:d}.{:d}.{:d}.{:d}'.format(value & 0xff, value>>8 & 0xff, value>>16 & 0xff, value>>24 & 0xff) + +def int2geo(value): + return float(value) / 1000000 + +def password(value): + if args.unhidepw: + return value + return '********' + +def fingerprintstr(value): + s = list(value) + result = '' + for c in s: + if c in '0123456789abcdefABCDEF': + result += c + return result + + +Setting_6_2_1 = { + 'cfg_holder': ('0 and isinstance(fielddef[2][0], int)) or isinstance(fielddef[2], int): + for i in range(0, fielddef[2][0] if isinstance(fielddef[2], list) else fielddef[2] ): + # multidimensional array + if isinstance(fielddef[2], list) and len(fielddef[2])>1: + length += GetFieldLength( (fielddef[0], fielddef[1], fielddef[2][1:]) ) + else: + length += GetFieldLength( (fielddef[0], fielddef[1], None) ) + else: + if fielddef[0][-1:].lower() in ['b','c','?']: + length=1 + elif fielddef[0][-1:].lower() in ['h']: + length=2 + elif fielddef[0][-1:].lower() in ['i','l','f']: + length=4 + elif fielddef[0][-1:].lower() in ['q','d']: + length=8 + elif fielddef[0][-1:].lower() in ['s','p']: + # s and p needs prefix as length + match = re.search("\s*(\d+)", fielddef[0]) + if match: + length=int(match.group(0)) + + # it's a single value + return length + +def ConvertFieldValue(value, fielddef): + """ + Convert field value based on field desc + + @param value: + original value read from binary data + @param fielddef + field definition (contains possible conversion defiinition) + + @return: (und)converted value + """ + if not args.raw and len(fielddef)>3: + if isinstance(fielddef[3],str): # use a format string + return fielddef[3].format(value) + elif callable(fielddef[3]): # use a format function + return fielddef[3](value) + return value + + +def GetField(dobj, fieldname, fielddef): + """ + Get field value from definition + + @param dobj: + uncrypted binary config data + @param fieldname: + name of the field + @param fielddef: + see Settings desc above + + @return: read field value + """ + + result = None + + if fielddef[2] is not None: + result = [] + + # tuple 2 contains a list with integer or an integer value + if (isinstance(fielddef[2], list) and len(fielddef[2])>0 and isinstance(fielddef[2][0], int)) or isinstance(fielddef[2], int): + addr = fielddef[1] + for i in range(0, fielddef[2][0] if isinstance(fielddef[2], list) else fielddef[2] ): + # multidimensional array + if isinstance(fielddef[2], list) and len(fielddef[2])>1: + subfielddef = (fielddef[0], addr, fielddef[2][1:], None if len(fielddef)<4 else fielddef[3]) + else: # single array + subfielddef = (fielddef[0], addr, None, None if len(fielddef)<4 else fielddef[3]) + length = GetFieldLength(subfielddef) + if length != 0: + result.append(GetField(dobj, fieldname, subfielddef)) + addr += length + # tuple 2 contains a list with dict + elif isinstance(fielddef[2], list) and len(fielddef[2])>0 and isinstance(fielddef[2][0], dict): + d = {} + value = struct.unpack_from(fielddef[0], dobj, fielddef[1])[0] + d['base'] = ConvertFieldValue(value, fielddef); + union = fielddef[2] + i = 0 + for l in union: + for name,bits in l.items(): + bitval = (value & ( ((1<> i + d[name] = bitval + i += bits + result = d + else: + # it's a single value + if GetFieldLength(fielddef) != 0: + result = struct.unpack_from(fielddef[0], dobj, fielddef[1])[0] + if fielddef[0][-1:].lower() in ['s','p']: + if ord(result[:1])==0x00 or ord(result[:1])==0xff: + result = '' + s = str(result).split('\0')[0] + result = s #unicode(s, errors='replace') + result = ConvertFieldValue(result, fielddef) + + return result + + +def DeEncrypt(obj): + """ + Decrpt/Encrypt binary config data + + @param obj: + binary config data + + @return: decrypted configuration (if obj contains encrypted data) + encrypted configuration (if obj contains decrypted data) + """ + dobj = obj[0:2] + for i in range(2, len(obj)): + dobj += chr( (ord(obj[i]) ^ (CONFIG_FILE_XOR +i)) & 0xff ) + return dobj + + +def Decode(obj): + """ + Decodes (already decrypted) binary data stream + + @param obj: + binary config data + """ + # get header data + cfg_size = GetField(obj, 'cfg_size', Setting_6_2_1['cfg_size']) + version = GetField(obj, 'version', Setting_6_2_1['version']) + + # search setting definition + setting = None + for cfg in Settings: + if version >= cfg[0] and cfg_size == cfg[1]: + template = cfg + break + + setting = template[2] + # if we did not found a mathching setting + if setting is None: + exit(2, "Can't handle Tasmota configuration data for version 0x{:x} with {} bytes".format(version, cfg_size) ) + + if GetField(obj, 'cfg_crc', setting['cfg_crc']) != GetSettingsCrc(obj): + exit(3, 'Data crc error' ) + + config = {} + config['version_template'] = '0x{:x}'.format(template[0]) + for name in setting: + config[name] = GetField(obj, name, setting[name]) + + if args.sort == 'name': + config = collections.OrderedDict(sorted(config.items())) + + if args.format == 'json': + print json.dumps(config, sort_keys=args.sort=='name') + else: + for key,value in config.items(): + print '{} = {}'.format(key, repr(value)) + + + +if __name__ == "__main__": + parser = configargparse.ArgumentParser(description='Decode configuration of Sonoff-Tasmota device.', + epilog='Note: Either argument -d or -f must be given.') + + source = parser.add_argument_group('source') + source.add_argument('-f', '--file', + metavar='', + dest='tasmotafile', + default=DEFAULTS['source']['tasmotafile'], + help='file to retrieve Tasmota configuration from (default: {})'.format(DEFAULTS['source']['tasmotafile'])) + source.add_argument('-d', '--device', + metavar='', + dest='device', + default=DEFAULTS['source']['device'], + help='device to retrieve configuration from (default: {})'.format(DEFAULTS['source']['device']) ) + source.add_argument('-u', '--username', + metavar='', + dest='username', + default=DEFAULTS['source']['username'], + help='for -d usage: http access username (default: {})'.format(DEFAULTS['source']['username'])) + source.add_argument('-p', '--password', + metavar='', + dest='password', + default=DEFAULTS['source']['password'], + help='for -d usage: http access password (default: {})'.format(DEFAULTS['source']['password'])) + + output = parser.add_argument_group('output') + output.add_argument('--format', + metavar='', + dest='format', + choices=['json', 'text'], + default=DEFAULTS['output']['format'], + help='output format ("json" or "text", default: "{}")'.format(DEFAULTS['output']['format']) ) + output.add_argument('--sort', + metavar='', + dest='sort', + choices=['none', 'name'], + default=DEFAULTS['output']['sort'], + help='sort result - can be "none" or "name" (default: "{}")'.format(DEFAULTS['output']['sort']) ) + output.add_argument('--raw', + dest='raw', + action='store_true', + default=DEFAULTS['output']['raw'], + help='output raw values (default: {})'.format('raw' if DEFAULTS['output']['raw'] else 'processed') ) + output.add_argument('--unhide-pw', + dest='unhidepw', + action='store_true', + default=DEFAULTS['output']['unhide-pw'], + help='unhide passwords (default: {})'.format('unhide' if DEFAULTS['output']['unhide-pw'] else 'hide') ) + output.add_argument('-o', '--output-file', + metavar='', + dest='outputfile', + default=DEFAULTS['output']['outputfile'], + help='file to store decrypted raw binary configuration to (default: {})'.format(DEFAULTS['output']['outputfile'])) + + parser.add_argument('-c', '--config', + metavar='', + dest='configfile', + default=DEFAULTS['DEFAULT']['configfile'], + is_config_file=True, + help='Config file, can be used instead of command parameter (defaults to {})'.format(DEFAULTS['DEFAULT']['configfile']) ) + + info = parser.add_argument_group('info') + info.add_argument('-V', '--version', action='version', version=PROG) + + args = parser.parse_args() + + configobj = None + + if args.device is not None: + + # read config direct from device via http + buffer = io.BytesIO() + url = str("http://{}/dl".format(args.device)) + c = pycurl.Curl() + c.setopt(c.URL, url) + c.setopt(c.VERBOSE, 0) + if args.username is not None and args.password is not None: + c.setopt(c.HTTPAUTH, c.HTTPAUTH_BASIC) + c.setopt(c.USERPWD, args.username + ':' + args.password) + c.setopt(c.WRITEDATA, buffer) + try: + c.perform() + except Exception, e: + exit(e[0], e[1]) + response = c.getinfo(c.RESPONSE_CODE) + c.close() + if response>=400: + exit(response, 'HTTP returns {}'.format(response) ) + + configobj = buffer.getvalue() + + elif args.tasmotafile is not None: + # read config from a file + + if not os.path.isfile(args.tasmotafile): # check file exists + exit(1, "file '{}' not found".format(args.tasmotafile)) + try: + tasmotafile = open(args.tasmotafile, "rb") + configobj = tasmotafile.read() + tasmotafile.close() + except Exception, e: + exit(e[0], e[1]) + + else: + parser.print_help() + sys.exit(0) + + if configobj is not None and len(configobj)>0: + cfg = DeEncrypt(configobj) + + if args.outputfile is not None: + outputfile = open(args.outputfile, "wb") + outputfile.write(cfg) + outputfile.close() + + Decode(cfg) + + else: + exit(4, "Could not read configuration data from {} '{}'".format('device' if args.device is not None else 'file', args.device if args.device is not None else args.tasmotafile) ) \ No newline at end of file From 977ee779b06b7c90d97fef335788fd826e742e24 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:30:01 +0200 Subject: [PATCH 0140/2222] Added VEML6070 defines Added define for Rset for the VEML6070 sensor and to show or show-not the raw value --- sonoff/user_config.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/user_config.h b/sonoff/user_config.h index b93e44211..846c86097 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -283,6 +283,8 @@ // #define USE_BME680 // Enable support for BME680 sensor using Bosch BME680 library (+4k code) #define USE_BH1750 // Enable BH1750 sensor (I2C address 0x23 or 0x5C) (+0k5 code) // #define USE_VEML6070 // Enable VEML6070 sensor (I2C addresses 0x38 and 0x39) (+0k5 code) +// #define USE_VEML6070_RSET 270000 // VEML6070, Rset in Ohm used on PCB board, default 270K = 270000ohm, range for this sensor: 220K ... 1Meg +// #define USE_VEML6070_SHOW_RAW // VEML6070, shows the raw value of UV-A // #define USE_ADS1115 // Enable ADS1115 16 bit A/D converter (I2C address 0x48, 0x49, 0x4A or 0x4B) based on Adafruit ADS1x15 library (no library needed) (+0k7 code) // #define USE_ADS1115_I2CDEV // Enable ADS1115 16 bit A/D converter (I2C address 0x48, 0x49, 0x4A or 0x4B) using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code) // #define USE_INA219 // Enable INA219 (I2C address 0x40, 0x41 0x44 or 0x45) Low voltage and current sensor (+1k code) From 2ba0b1be7324f5ccec0aed308b5b0a98b50c8aca Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:32:24 +0200 Subject: [PATCH 0141/2222] driver cahnge Added a lot of new calculation for more precission and more output so as UV Index plus a text behind the value and UV Power in W/m2 --- sonoff/xsns_11_veml6070.ino | 234 ++++++++++++++++++++++++++++++++---- 1 file changed, 211 insertions(+), 23 deletions(-) diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index 557f615f3..be7d3daa0 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -15,25 +15,136 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . + + ----------------------------------------------------- + Some words to the meaning of the UV Risk Level: + ----------------------------------------------------- + D_UV_INDEX_1 = "Low" = sun->fun + D_UV_INDEX_2 = "Mid" = sun->glases advised + D_UV_INDEX_3 = "High" = sun->glases a must + D_UV_INDEX_4 = "Danger" = sun->skin burns Level 1 + D_UV_INDEX_5 = "BurnL1/2" = sun->skin burns level 1..2 + D_UV_INDEX_6 = "BurnL3" = sun->skin burns with level 3 + D_UV_INDEX_7 = "OoR" = out of range or unknown + + -------------------------------------------------------------------------------------------- + Version Date Action Description + -------------------------------------------------------------------------------------------- + + 1.0.0.1 20180925 tests - all tests are done with 1x sonoff sv, 2x Wemos D1 (not the mini) + - 3 different VEMl6070 sensors from 3 different online shops + - all the last three test where good and all looks working so far + - all tests are done at high noon with blue sky and a leaned UV light source + sience - a special Thank You to my friend the professor. He works in the aerospace industrie. Thank You R.G.T. + - all calculations are based on the very good work of Karel Vanicek. Thank You Karel + - more information about UV Index and the irradiation power calculation can be found on the internet + info - all calculations are based on the effective irradiation from Karel Vanicek + - all this was not possible without the work of @arendst. He has done really a lot of basic work/code. Thank You Theo + cleaned - source code a little bit + added - missing void in function calls: void name(void) + added - UV Risk level now defined as UV Index, 0.00 based on NASA standard with text behind the value + added - UV Power level now named as UV Power, used W/m2 because official standards + added - automatic fill of the uv-risk compare table based on the coefficient calculation + added - suspend and wakeup mode for the uv seonsor + - current drain in wake-up-ed mode was around 180uA incl. I2C bus + - current drain in suspend mode was around 70..80uA incl. I2C bus + changed - 2x the power calculation about some incorrent data sheet values + changed - float to double calculation because a rare effect on uv compare map filling + - in that case @andrethomas was a big help too (while(work){output=lot_of_fun};) + added - USE_VEML6070_RSET + - in user_config as possible input, different resistor values depending on PCB types + added - USE_VEML6070_SHOW_RAW + - in user_config, show or show-NOT the uv raw value + added - lots of #defines for automatic calulations to get the best possible values + added - error messages for LOG_LEVEL_DEBUG + added - lots of information in one of the last postings in: https://github.com/arendst/Sonoff-Tasmota/issues/3844 + debugging - without the softly hit ;-) from @andrethomas about Serial.print i would never done it. Thank You Andre + safety - personal, please read this: http://www.segurancaetrabalho.com.br/download/uv_index_karel_vanicek.pdf + next - possible i will add the calculation for LAT and LONG coordinates for much more precission + - show not only the UV Power value in W/m2, possible a @define value to show it as joule value + - add a #define to select how many characters are shown benhind the decimal point for the UV Index + --- + 1.0.0.0 20180912 started - further development by mike2nl - https://github.com/mike2nl/Sonoff-Tasmota + forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota + base - code base from arendst too + */ #ifdef USE_I2C #ifdef USE_VEML6070 /*********************************************************************************************\ - * VEML6070 - Ultra Violet Light Intensity + * VEML6070 - Ultra Violet Light Intensity (UV-A, 100% output by 255nm) * * I2C Address: 0x38 and 0x39 \*********************************************************************************************/ -#define VEML6070_ADDR_H 0x39 -#define VEML6070_ADDR_L 0x38 +#define VEML6070_ADDR_H 0x39 // on some PCB boards the address can be changed by a solder point, +#define VEML6070_ADDR_L 0x38 // to have no address conflicts with other I2C sensors and/or hardware -#define VEML6070_INTEGRATION_TIME 3 // 500msec integration time +#define VEML6070_INTEGRATION_TIME 3 // IT_4 = 500msec integration time, because the precission is 4 times higher then IT_0.5 +#define VEML6070_ENABLE 1 // +#define VEML6070_DISABLE 0 // +#define VEML6070_RSET_DEFAULT 270000 // 270K default resistor value 270000 ohm, range from 220K..1Meg +#define VEML6070_UV_MAX_INDEX 15 // normal 11, internal on weather laboratories and NASA it's 15 so far the sensor is linear +#define VEML6070_UV_MAX_DEFAULT 11 // 11 = public default table values +#define VEML6070_POWER_COEFFCIENT 0.025 // based on calculations from Karel Vanicek and reorder by hand +#define VEML6070_TABLE_COEFFCIENT 32.86270591 // calculated by hand with help from a friend of mine, a professor which works in aero space things + // (resistor, differences, power coefficients and official UV index calculations (LAT & LONG will be added later) +/********************************************************************************************/ + +// globals uint8_t veml6070_address; uint8_t veml6070_type = 0; -uint16_t Veml6070ReadUv() +/********************************************************************************************/ + +void Veml6070Detect(void) +{ + if (veml6070_type) { + return; + } + + uint8_t itime = VEML6070_INTEGRATION_TIME; + veml6070_address = VEML6070_ADDR_L; + Wire.beginTransmission(veml6070_address); + Wire.write((itime << 2) | 0x02); + uint8_t status = Wire.endTransmission(); + + if (!status) { + veml6070_type = 1; + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VEML6070", veml6070_address); + AddLog(LOG_LEVEL_DEBUG); + } +} + +/********************************************************************************************/ + +void Veml6070ModeCmd(boolean mode_cmd) +{ + uint8_t itime = VEML6070_INTEGRATION_TIME; + uint8_t opmode = 0; + + if (mode_cmd) { + opmode = VEML6070_ENABLE; + } else { + opmode = VEML6070_DISABLE; + } + + veml6070_address = VEML6070_ADDR_L; + Wire.beginTransmission(veml6070_address); + Wire.write((opmode << 0) | 0x02 | (itime << 2)); + uint8_t status = Wire.endTransmission(); + + if (!status) { + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VEML6070 opmode", veml6070_address); + AddLog(LOG_LEVEL_DEBUG); + } +} + +/********************************************************************************************/ + +uint16_t Veml6070ReadUv(void) { if (Wire.requestFrom(VEML6070_ADDR_H, 1) != 1) { return -1; @@ -50,45 +161,122 @@ uint16_t Veml6070ReadUv() /********************************************************************************************/ -void Veml6070Detect() +double Veml6070UvRiskLevel(uint16_t uv_level) { - if (veml6070_type) { - return; - } + double risk = 0; + double uv_risk_map[VEML6070_UV_MAX_INDEX] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + // fill the uv-risk compare table based on the coefficient calculation + for (uint8_t i = 0; i < VEML6070_UV_MAX_INDEX; i++) { +#ifdef USE_VEML6070_RSET + if ( (USE_VEML6070_RSET >= 220000) && (USE_VEML6070_RSET <= 1000000) ) { + uv_risk_map[i] = ( (USE_VEML6070_RSET / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT) * (i+1); + } else { + uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT) * (i+1); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "VEML6070 resistor error %d"), USE_VEML6070_RSET); + AddLog(LOG_LEVEL_DEBUG); + } +#else + uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT) * (i+1); +#endif + } - uint8_t itime = VEML6070_INTEGRATION_TIME; - - veml6070_address = VEML6070_ADDR_L; - Wire.beginTransmission(veml6070_address); - Wire.write((itime << 2) | 0x02); - uint8_t status = Wire.endTransmission(); - if (!status) { - veml6070_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VEML6070", veml6070_address); + // get the uv-risk level + if (uv_level < uv_risk_map[VEML6070_UV_MAX_INDEX-1]) { + return ( uv_level / uv_risk_map[0] ); + } else { + return ( risk = 99 ); // out of range = much to high - it must be outerspace or sensor damaged + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "VEML6070 out of range %d"), risk); AddLog(LOG_LEVEL_DEBUG); } } +/********************************************************************************************/ + +double Veml6070UvPower(double uvrisk) +{ + // based on calculations for effective irradiation from Karel Vanicek + return ( VEML6070_POWER_COEFFCIENT * uvrisk ); +} + +/********************************************************************************************/ + #ifdef USE_WEBSERVER -const char HTTP_SNS_ULTRAVIOLET[] PROGMEM = - "%s{s}VEML6070 " D_UV_LEVEL "{m}%d{e}"; // {s} = , {m} = , {e} = + // {s} = , {m} = , {e} = +#ifdef USE_VEML6070_SHOW_RAW + const char HTTP_SNS_UV_LEVEL[] PROGMEM = "%s{s}VEML6070 " D_UV_LEVEL "{m}%d " D_UNIT_INCREMENTS "{e}"; +#endif // USE_VEML6070_SHOW_RAW + // different uv index level texts + const char HTTP_SNS_UV_INDEX1[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_1 "{e}"; + const char HTTP_SNS_UV_INDEX2[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_2 "{e}"; + const char HTTP_SNS_UV_INDEX3[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_3 "{e}"; + const char HTTP_SNS_UV_INDEX4[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_4 "{e}"; + const char HTTP_SNS_UV_INDEX5[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_5 "{e}"; + const char HTTP_SNS_UV_INDEX6[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_6 "{e}"; + const char HTTP_SNS_UV_INDEX7[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_7 "{e}"; + const char HTTP_SNS_UV_POWER[] PROGMEM = "%s{s}VEML6070 " D_UV_POWER "{m}%s " D_UNIT_WATT_METER_QUADRAT "{e}"; #endif // USE_WEBSERVER +/********************************************************************************************/ + void Veml6070Show(boolean json) { if (veml6070_type) { + // wakeup the sensor + Veml6070ModeCmd(1); + + // get values from functions uint16_t uvlevel = Veml6070ReadUv(); + double uvrisk = Veml6070UvRiskLevel(uvlevel); + double uvpower = Veml6070UvPower(uvrisk); + char str_uvrisk[10]; + char str_uvpower[5]; + + // convert double values to string + dtostrfd(uvrisk, 2, str_uvrisk); + dtostrfd(uvpower, 3, str_uvpower); if (json) { +#ifdef USE_VEML6070_SHOW_RAW snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"VEML6070\":{\"" D_JSON_UV_LEVEL "\":%d}"), mqtt_data, uvlevel); +#endif // USE_VEML6070_SHOW_RAW + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"VEML6070\":{\"" D_JSON_UV_INDEX "\":%s}"), mqtt_data, str_uvrisk); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"VEML6070\":{\"" D_JSON_UV_POWER "\":%s}"), mqtt_data, str_uvpower); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, uvlevel); + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel) }; #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ULTRAVIOLET, mqtt_data, uvlevel); +#ifdef USE_VEML6070_SHOW_RAW + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_LEVEL, mqtt_data, uvlevel); +#endif // USE_VEML6070_SHOW_RAW + if ( (uvrisk >= 0) && (uvrisk <= 2.9) ) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX1, mqtt_data, str_uvrisk); + } + else if ( (uvrisk >= 3.0) && (uvrisk <= 5.9) ) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX2, mqtt_data, str_uvrisk); + } + else if ( (uvrisk >= 6.0) && (uvrisk <= 7.9) ) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX3, mqtt_data, str_uvrisk); + } + else if ( (uvrisk >= 8.0) && (uvrisk <= 10.9) ) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX4, mqtt_data, str_uvrisk); + } + else if ( (uvrisk >= 11.0) && (uvrisk <= 12.9) ) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX5, mqtt_data, str_uvrisk); + } + else if ( (uvrisk >= 13.0) && (uvrisk <= 15.9) ) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX6, mqtt_data, str_uvrisk); + } else { + // else for Unknown or Out Of Range error = 99 + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX7, mqtt_data, str_uvrisk); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_POWER, mqtt_data, str_uvpower); #endif // USE_WEBSERVER } + // suspend the sensor + Veml6070ModeCmd(0); + // delay(2000); // used while messaurment of current drain } } @@ -105,7 +293,7 @@ boolean Xsns11(byte function) if (i2c_flg) { switch (function) { case FUNC_PREP_BEFORE_TELEPERIOD: - Veml6070Detect(); + Veml6070Detect(); // detect and init the sensor break; case FUNC_JSON_APPEND: Veml6070Show(1); From af5ee5a883384b243dc73f0e400e1577f137bfba Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:37:08 +0200 Subject: [PATCH 0142/2222] Added defines for text Added defines for uv text and one unit define --- sonoff/language/bg-BG.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 266714fe4..a3ab3d539 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -163,7 +163,15 @@ #define D_USER "Потребител" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV индекс" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "Ниво на ултравиолетово излъчване" +#define D_UV_POWER "UV Power" #define D_VERSION "Версия" #define D_VOLTAGE "Напрежение" #define D_WARMLIGHT "Топла" @@ -514,6 +522,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From ee7acd849b67e8fbbebabbe9e702ce8e6b2ab0b0 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:40:55 +0200 Subject: [PATCH 0143/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/cs-CZ.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index e90797725..3886c1b4d 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -163,7 +163,15 @@ #define D_USER "Uživatel" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "úroveň UV" +#define D_UV_POWER "UV Power" #define D_VERSION "Verze" #define D_VOLTAGE "Napětí" #define D_WARMLIGHT "Teplé světlo" @@ -514,6 +522,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From 1738f68247f31f41caded85aef4b5f3633365e53 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:42:28 +0200 Subject: [PATCH 0144/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/de-DE.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index a6e62c557..9bb14bfa5 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -163,7 +163,14 @@ #define D_USER "Benutzer" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV-Index" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "UV-Level" +#define D_UV_POWER "UV Power" #define D_VERSION "Version" #define D_VOLTAGE "Spannung" #define D_WARMLIGHT "warm" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From ef6cd4530d27e662be5d2046c4afe1a4cea477d8 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:44:04 +0200 Subject: [PATCH 0145/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/el-GR.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 715b2a7cf..1b666ae1e 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -163,7 +163,14 @@ #define D_USER "Χρήστης" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "Επίπεδο UV" +#define D_UV_POWER "UV Power" #define D_VERSION "Έκδοση" #define D_VOLTAGE "Τάση" #define D_WARMLIGHT "Ζεστό" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From c18a3cd7e0a140faf2158793de7fd02049629745 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:45:27 +0200 Subject: [PATCH 0146/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/en-GB.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 9ac6c1fad..5f6f0d764 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -163,7 +163,14 @@ #define D_USER "User" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "UV Level" +#define D_UV_POWER "UV Power" #define D_VERSION "Version" #define D_VOLTAGE "Voltage" #define D_WARMLIGHT "Warm" @@ -514,6 +521,7 @@ #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_HERTZ "Hz" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From 89e04dafb099652649c245caf2ef8657a488166a Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:46:43 +0200 Subject: [PATCH 0147/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/es-AR.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 7d0408080..dafa99900 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -163,7 +163,14 @@ #define D_USER "Usuario" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Índice UV" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "Nivel UV" +#define D_UV_POWER "UV Power" #define D_VERSION "Versión" #define D_VOLTAGE "Tensión" #define D_WARMLIGHT "Cálida" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From 651bdf03c0ee556f66b5a6d4535ee692ff66c802 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:49:51 +0200 Subject: [PATCH 0148/2222] Update fr-FR.h Added some new text UV defines and one unit define W/m2 --- sonoff/language/fr-FR.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 7e6ea07b9..8cbf0ce7d 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -163,7 +163,14 @@ #define D_USER "Utilisateur" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Indice UV" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "Niveau UV" +#define D_UV_POWER "UV Power" #define D_VERSION "Version" #define D_VOLTAGE "Tension" #define D_WARMLIGHT "Chaud" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From e3f1d4ad9ae4256b25f321e2e12e1d20a55c6095 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:50:05 +0200 Subject: [PATCH 0149/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/hu-HU.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index ef2c28f80..3c9f23334 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -163,7 +163,14 @@ #define D_USER "Felhasználó" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "UV Szint" +#define D_UV_POWER "UV Power" #define D_VERSION "Verzió" #define D_VOLTAGE "Feszültség" #define D_WARMLIGHT "Meleg" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From 9182d02d0cf601ccfe0987fbbf2bcc7d1d8c8710 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:50:18 +0200 Subject: [PATCH 0150/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/it-IT.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index ac818a9f2..b44f612f3 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -163,7 +163,14 @@ #define D_USER "Utente" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Indice UV" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "Livello UV" +#define D_UV_POWER "UV Power" #define D_VERSION "Versione" #define D_VOLTAGE "Tensione" #define D_WARMLIGHT "Calda" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From 4c900eb0b720b2c2c8f69c4a392788a5568bb510 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:52:41 +0200 Subject: [PATCH 0151/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/nl-NL.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 273699477..4946dd94f 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -163,7 +163,14 @@ #define D_USER "Gebruiker" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV-index" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "UV niveau" +#define D_UV_POWER "UV Power" #define D_VERSION "Versie" #define D_VOLTAGE "Spanning" #define D_WARMLIGHT "Warm" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From f7c16f53881d18df0b4134195757ee00b4a4806a Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:53:03 +0200 Subject: [PATCH 0152/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/pl-PL.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 199f7cce9..fa118b1b1 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -163,7 +163,14 @@ #define D_USER "Użytkownik" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "Poziom UV" +#define D_UV_POWER "UV Power" #define D_VERSION "Wersja" #define D_VOLTAGE "Napięcie" #define D_WARMLIGHT "Nagrzanie" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From a6cf1cde4fd1323d43fec33a789aefa3f0d05607 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:53:25 +0200 Subject: [PATCH 0153/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/pt-BR.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 8770b9a4a..bf1318864 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -163,7 +163,14 @@ #define D_USER "Usuário" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Índice UV" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "Nível UV" +#define D_UV_POWER "UV Power" #define D_VERSION "Versão" #define D_VOLTAGE "Voltagem" #define D_WARMLIGHT "Luz quente" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "W/h" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From 78df649fcae70e9c1e463ff41151d27fd0d9904a Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:56:38 +0200 Subject: [PATCH 0154/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/pt-PT.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 0b7715583..a3b67c366 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -163,7 +163,14 @@ #define D_USER "Utilizador" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Indíce UV" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "Nível UV" +#define D_UV_POWER "UV Power" #define D_VERSION "Versão" #define D_VOLTAGE "Voltagem" #define D_WARMLIGHT "Luz Quente" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From c8f51b68fdaf424a0392c7534a9d68072d983d34 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:57:01 +0200 Subject: [PATCH 0155/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/ru-RU.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index e61cbb9c1..a4e48067d 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -163,7 +163,14 @@ #define D_USER "Пользователь" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "УФ уровень" +#define D_UV_POWER "UV Power" #define D_VERSION "Версия" #define D_VOLTAGE "Напряжение" #define D_WARMLIGHT "Тепло" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "В" #define D_UNIT_WATT "Вт" #define D_UNIT_WATTHOUR "ВтЧ" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From 56e9e92655359c179377248676f6ba7f91c0462b Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 14:57:17 +0200 Subject: [PATCH 0156/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/tr-TR.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 086c236aa..62cec3eb0 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -163,7 +163,14 @@ #define D_USER "Kullanıcı" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Indeksi" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "UV Seviyesi" +#define D_UV_POWER "UV Power" #define D_VERSION "Versiyon" #define D_VOLTAGE "Voltaj" #define D_WARMLIGHT "Sıcak" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" #define D_UNIT_HERTZ "Hz" // Log message prefix From cf952f66377026cbcf6c6eba344e4476eb7389ee Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 15:00:34 +0200 Subject: [PATCH 0157/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/uk-UK.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 19094d574..7dccdb7db 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -163,7 +163,14 @@ #define D_USER "Користувач" #define D_UTC_TIME "UTC" #define D_UV_INDEX "УФ індекс" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "УФ рівень" +#define D_UV_POWER "UV Power" #define D_VERSION "Версія" #define D_VOLTAGE "Напруга" #define D_WARMLIGHT "Тепло" @@ -515,6 +522,7 @@ #define D_UNIT_VOLT "В" #define D_UNIT_WATT "Вт" #define D_UNIT_WATTHOUR "ВтГод" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From 044363dc00eccd9c6c0b6d58cf5c6b693509a6b1 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 15:00:57 +0200 Subject: [PATCH 0158/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/zh-CN.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index ea15b6ccb..820cde18c 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -163,7 +163,14 @@ #define D_USER "用户名" #define D_UTC_TIME "UTC" #define D_UV_INDEX "紫外线指数" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "紫外线水平" +#define D_UV_POWER "UV Power" #define D_VERSION "版本" #define D_VOLTAGE "电压" #define D_WARMLIGHT "暖" @@ -514,6 +521,7 @@ #define D_UNIT_WATT "瓦" #define D_UNIT_WATTHOUR "瓦时" #define D_UNIT_HERTZ "赫兹" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From 13e0bcbd26c00e91866d8203ac5573626074eb0f Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 15:01:16 +0200 Subject: [PATCH 0159/2222] Added some text defines Added some new text UV defines and one unit define W/m2 --- sonoff/language/zh-TW.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index f4f439c8b..14052d9f3 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -163,7 +163,14 @@ #define D_USER "用戶名" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "紫外線等級" +#define D_UV_POWER "UV Power" #define D_VERSION "版本" #define D_VOLTAGE "電壓" #define D_WARMLIGHT "暖" @@ -514,6 +521,7 @@ #define D_UNIT_VOLT "伏" #define D_UNIT_WATT "瓦" #define D_UNIT_WATTHOUR "瓦時" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application From 40052a343ffe94ad1ac4f077700acdb42eadb941 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 25 Sep 2018 15:35:49 +0200 Subject: [PATCH 0160/2222] Add image sonoff-display Add define USE_DISPLAYS for selecting image sonoff-display --- platformio.ini | 15 +++++++++++++++ sonoff/_changelog.ino | 1 + sonoff/sonoff_post.h | 26 +++++++++++++++++++++++++- sonoff/user_config.h | 3 ++- 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index d333fd187..c01485f5a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,6 +16,7 @@ env_default = sonoff ;env_default = sonoff-classic ;env_default = sonoff-knx ;env_default = sonoff-sensors +;env_default = sonoff-display ;env_default = sonoff-BG ;env_default = sonoff-BR ;env_default = sonoff-CN @@ -167,6 +168,20 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} +[env:sonoff-display] +platform = ${common.platform} +framework = ${common.framework} +board = ${common.board} +board_build.flash_mode = ${common.board_build.flash_mode} +board_build.f_cpu = ${common.board_build.f_cpu} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} -DUSE_DISPLAYS +monitor_speed = ${common.monitor_speed} +upload_port = ${common.upload_port} +upload_resetmethod = ${common.upload_resetmethod} +upload_speed = ${common.upload_speed} +extra_scripts = ${common.extra_scripts} + [env:sonoff-BG] platform = ${common.platform} framework = ${common.framework} diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 333a524a6..f2525b2a7 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Remove restart after ntpserver change and force NTP re-sync (#3890) * Release full Shelly2 support * Released tools/decode-config.py by Norbert Richter to decode configuration data. See file for information + * Add define USE_DISPLAYS for selecting image sonoff-display * * 6.2.1.6 20180922 * Removed commands PowerCal, VoltageCal and CurrentCal as more functionality is provided by commands PowerSet, VoltageSet and CurrentSet diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 8622d0818..423a75f3c 100755 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -51,7 +51,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #endif #define USE_DHT // Default DHT11 sensor needs no external library -#define USE_ENERGY_SENSOR // Use energy sensors +#define USE_ENERGY_SENSOR // Use energy sensors (+14k code) #define USE_HLW8012 // Use energy sensor for Sonoff Pow and WolfBlitz #define USE_CSE7766 // Use energy sensor for Sonoff S31 and Pow R2 @@ -167,6 +167,30 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) #endif // USE_KNX_NO_EMULATION +/*********************************************************************************************\ + * [sonoff-display.bin] + * Provide an image with display drivers enabled +\*********************************************************************************************/ + +#ifdef USE_DISPLAYS + +#undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) +#undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) + +#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) + #define USE_DISPLAY // Add I2C Display Support (+2k code) + #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 + #define USE_DISPLAY_LCD // [DisplayModel 1] Enable Lcd display (I2C addresses 0x27 and 0x3F) (+6k code) + #define USE_DISPLAY_SSD1306 // [DisplayModel 2] Enable SSD1306 Oled 128x64 display (I2C addresses 0x3C and 0x3D) (+16k code) + #define USE_DISPLAY_MATRIX // [DisplayModel 3] Enable 8x8 Matrix display (I2C adresseses see below) (+11k code) + +#define USE_SPI // Hardware SPI using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK) in addition to two user selectable GPIOs(CS and DC) + #define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display (+19k code) + +#undef USE_ARILUX_RF // Remove support for Arilux RF remote controller (-0k8 code, 252 iram (non 2.3.0)) +#undef USE_RF_FLASH // Remove support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (-3k code) +#endif // USE_DISPLAYS + /*********************************************************************************************\ * Mandatory define for DS18x20 if changed by above image selections \*********************************************************************************************/ diff --git a/sonoff/user_config.h b/sonoff/user_config.h index b93e44211..f86350334 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -321,7 +321,7 @@ #endif // USE_I2C // -- SPI sensors --------------------------------- -//#define USE_SPI // SPI using library TasmotaTFT +//#define USE_SPI // Hardware SPI using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK) in addition to two user selectable GPIOs(CS and DC) #ifdef USE_SPI #ifndef USE_DISPLAY @@ -384,6 +384,7 @@ //#define USE_CLASSIC // Create sonoff-classic with initial configuration tools WPS, SmartConfig and WifiManager //#define USE_SENSORS // Create sonoff-sensors with useful sensors enabled //#define USE_KNX_NO_EMULATION // Create sonoff-knx with KNX but without Emulation +//#define USE_DISPLAYS // Create sonoff-display with display drivers enabled //#define BE_MINIMAL // Create sonoff-minimal as intermediate firmware for OTA-MAGIC /*********************************************************************************************\ From e9d6a5bc4677197a56a4885886ef11ebf2a43ebb Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:19:49 +0200 Subject: [PATCH 0161/2222] added define Forgot to add #define D_JSON_UV_POWER "UvPower" --- sonoff/i18n.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 80f757447..1c628b7b7 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -132,6 +132,7 @@ #define D_JSON_UTC_TIME "UTC" #define D_JSON_UVINDEX "UvIndex" #define D_JSON_UV_LEVEL "UvLevel" +#define D_JSON_UV_POWER "UvPower" #define D_JSON_VCC "Vcc" #define D_JSON_VERSION "Version" #define D_JSON_VOLTAGE "Voltage" From baf81daaa2c896fa3f6fa7ba6a89b49ff9053f31 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:23:38 +0200 Subject: [PATCH 0162/2222] added text forgot the #define D_UNIT_INCREMENTS "inc" --- sonoff/language/bg-BG.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index a3ab3d539..ff7801984 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -502,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From e6ae87fd829c25dcb337777aaa6f3331ff99edd3 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:24:44 +0200 Subject: [PATCH 0163/2222] added text forgot the #define D_UNIT_INCREMENTS "inc" --- sonoff/language/cs-CZ.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 3886c1b4d..570cfd4c8 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -502,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "hod" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From abd5cb23fe7ac46816d107b5ea2c2be463a05383 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:27:10 +0200 Subject: [PATCH 0164/2222] Added text forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/de-DE.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 9bb14bfa5..6e90ae409 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -163,6 +163,7 @@ #define D_USER "Benutzer" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV-Index" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -501,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From a7d59f03fa1cb0be7721e8ad4351523858ea44cd Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:28:34 +0200 Subject: [PATCH 0165/2222] Added text Forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/en-GB.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 5f6f0d764..21d8edab7 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -163,6 +163,7 @@ #define D_USER "User" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -500,6 +501,7 @@ #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HOUR "Hr" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From b15a29c046edd5d75351c2900fc84e6fb0f4f1bf Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:29:27 +0200 Subject: [PATCH 0166/2222] Added text Forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/el-GR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 1b666ae1e..23b5a2705 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -163,6 +163,7 @@ #define D_USER "Χρήστης" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -501,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From 3fd8b8f7f8a1b1cf4badbdef3af616216c10ad42 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:32:17 +0200 Subject: [PATCH 0167/2222] Added text #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/es-AR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index dafa99900..b67e6e79f 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -163,6 +163,7 @@ #define D_USER "Usuario" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Índice UV" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -501,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From cdc7b90652601a73052a55b1167f92fdf9c68beb Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:32:36 +0200 Subject: [PATCH 0168/2222] Added text #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/fr-FR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 8cbf0ce7d..c4c913fec 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -163,6 +163,7 @@ #define D_USER "Utilisateur" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Indice UV" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -501,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From 9ad0bc149f43c3ac45a239c686f557f2308b1ff4 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:32:46 +0200 Subject: [PATCH 0169/2222] Added text #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/hu-HU.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 3c9f23334..ee6b8a66a 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -163,6 +163,7 @@ #define D_USER "Felhasználó" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -501,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "ó" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From a1d5032993d65e463934632746f73a80dc35761b Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:35:17 +0200 Subject: [PATCH 0170/2222] Added text Forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/it-IT.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index b44f612f3..b0fe0767a 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -163,6 +163,7 @@ #define D_USER "Utente" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Indice UV" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -501,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From 55db6530ec61d9cc7a5d6613ebfbc6e2d166362b Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:35:29 +0200 Subject: [PATCH 0171/2222] Added text Forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/nl-NL.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 4946dd94f..70e55cb87 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -163,6 +163,7 @@ #define D_USER "Gebruiker" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV-index" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -501,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From a7495af9edb5c6f148d9f913ac6df6e27eee8682 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:35:48 +0200 Subject: [PATCH 0172/2222] Added text Forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/pl-PL.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index fa118b1b1..40383fb53 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -163,6 +163,7 @@ #define D_USER "Użytkownik" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -501,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Godz" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From 6b070e08cf046ec95ca7e6f2ff3b443aeb19d4f8 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:38:04 +0200 Subject: [PATCH 0173/2222] Added text Forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/pt-BR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index bf1318864..49affdf2f 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -163,6 +163,7 @@ #define D_USER "Usuário" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Índice UV" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -501,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "H" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From dc937ed792a0e27ef773632fa0565c91b382353b Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:38:27 +0200 Subject: [PATCH 0174/2222] Added text Forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/pt-PT.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index a3b67c366..fd2e98451 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -163,6 +163,7 @@ #define D_USER "Utilizador" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Indíce UV" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -501,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From 65dbf4c709a0a3042ed28247f90aa7168fecfaed Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:38:40 +0200 Subject: [PATCH 0175/2222] Added text Forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/ru-RU.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index a4e48067d..9c6266693 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -163,6 +163,7 @@ #define D_USER "Пользователь" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -501,6 +502,7 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Ч" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "кОм" #define D_UNIT_KILOWATTHOUR "кВт" #define D_UNIT_LUX "лк" From e719cfbf43a63e66d07e08ad3db8be28c7ece159 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:41:51 +0200 Subject: [PATCH 0176/2222] Added text Forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/tr-TR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 62cec3eb0..0c411868e 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -163,6 +163,7 @@ #define D_USER "Kullanıcı" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Indeksi" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -501,6 +502,7 @@ #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HOUR "Hr" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From 85692d6f386f7aca47e9ab8d83c8ab54cfd39d0b Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:42:01 +0200 Subject: [PATCH 0177/2222] Added text Forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/zh-CN.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 820cde18c..59271d201 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -163,6 +163,7 @@ #define D_USER "用户名" #define D_UTC_TIME "UTC" #define D_UV_INDEX "紫外线指数" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -500,6 +501,7 @@ #define D_UNIT_AMPERE "安" #define D_UNIT_CENTIMETER "厘米" #define D_UNIT_HOUR "时" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "千欧" #define D_UNIT_KILOWATTHOUR "千瓦时" #define D_UNIT_LUX "勒克斯" From a47467704e235e87370605074eaa7c9461a0b517 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:42:07 +0200 Subject: [PATCH 0178/2222] Added text Forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/uk-UK.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 7dccdb7db..3a9b44afa 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -163,6 +163,7 @@ #define D_USER "Користувач" #define D_UTC_TIME "UTC" #define D_UV_INDEX "УФ індекс" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -502,6 +503,7 @@ #define D_UNIT_CENTIMETER "cм" #define D_UNIT_HERTZ "Гц" #define D_UNIT_HOUR "Г" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "кОм" #define D_UNIT_KILOWATTHOUR "кВт" #define D_UNIT_LUX "лк" From 63dbd6d0c94b597be723467a83c4b19cbeb17055 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Sep 2018 16:42:09 +0200 Subject: [PATCH 0179/2222] Added text Forgot the #define D_UNIT_INCREMENTS "inc" and #define D_UV_INDEX_1 "Low" --- sonoff/language/zh-TW.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 14052d9f3..5b275b925 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -163,6 +163,7 @@ #define D_USER "用戶名" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_3 "High" #define D_UV_INDEX_4 "Danger" @@ -500,6 +501,7 @@ #define D_UNIT_AMPERE "安" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_HOUR "時" #define D_UNIT_KILOOHM "千歐" #define D_UNIT_KILOWATTHOUR "千瓦時" From eb53605fc1ee76f3fd893b0728ef8b9117183060 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 25 Sep 2018 17:03:22 +0200 Subject: [PATCH 0180/2222] Fix VEML6070 compile errors --- sonoff/i18n.h | 2 +- sonoff/user_config.h | 6 +++--- sonoff/xsns_11_veml6070.ino | 30 +++++++++++++++--------------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 1c628b7b7..c8d3e219f 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -130,7 +130,7 @@ #define D_JSON_TYPE "Type" #define D_JSON_UPTIME "Uptime" #define D_JSON_UTC_TIME "UTC" -#define D_JSON_UVINDEX "UvIndex" +#define D_JSON_UV_INDEX "UvIndex" #define D_JSON_UV_LEVEL "UvLevel" #define D_JSON_UV_POWER "UvPower" #define D_JSON_VCC "Vcc" diff --git a/sonoff/user_config.h b/sonoff/user_config.h index b864d7aa6..eceadc68d 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -282,9 +282,9 @@ #define USE_BMP // Enable BMP085/BMP180/BMP280/BME280 sensor (I2C address 0x76 or 0x77) (+4k code) // #define USE_BME680 // Enable support for BME680 sensor using Bosch BME680 library (+4k code) #define USE_BH1750 // Enable BH1750 sensor (I2C address 0x23 or 0x5C) (+0k5 code) -// #define USE_VEML6070 // Enable VEML6070 sensor (I2C addresses 0x38 and 0x39) (+0k5 code) -// #define USE_VEML6070_RSET 270000 // VEML6070, Rset in Ohm used on PCB board, default 270K = 270000ohm, range for this sensor: 220K ... 1Meg -// #define USE_VEML6070_SHOW_RAW // VEML6070, shows the raw value of UV-A +// #define USE_VEML6070 // Enable VEML6070 sensor (I2C addresses 0x38 and 0x39) (+1k5 code) + #define USE_VEML6070_RSET 270000 // VEML6070, Rset in Ohm used on PCB board, default 270K = 270000ohm, range for this sensor: 220K ... 1Meg + #define USE_VEML6070_SHOW_RAW // VEML6070, shows the raw value of UV-A // #define USE_ADS1115 // Enable ADS1115 16 bit A/D converter (I2C address 0x48, 0x49, 0x4A or 0x4B) based on Adafruit ADS1x15 library (no library needed) (+0k7 code) // #define USE_ADS1115_I2CDEV // Enable ADS1115 16 bit A/D converter (I2C address 0x48, 0x49, 0x4A or 0x4B) using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code) // #define USE_INA219 // Enable INA219 (I2C address 0x40, 0x41 0x44 or 0x45) Low voltage and current sensor (+1k code) diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index be7d3daa0..f60c0f00f 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -30,7 +30,7 @@ -------------------------------------------------------------------------------------------- Version Date Action Description -------------------------------------------------------------------------------------------- - + 1.0.0.1 20180925 tests - all tests are done with 1x sonoff sv, 2x Wemos D1 (not the mini) - 3 different VEMl6070 sensors from 3 different online shops - all the last three test where good and all looks working so far @@ -43,7 +43,7 @@ cleaned - source code a little bit added - missing void in function calls: void name(void) added - UV Risk level now defined as UV Index, 0.00 based on NASA standard with text behind the value - added - UV Power level now named as UV Power, used W/m2 because official standards + added - UV Power level now named as UV Power, used W/m2 because official standards added - automatic fill of the uv-risk compare table based on the coefficient calculation added - suspend and wakeup mode for the uv seonsor - current drain in wake-up-ed mode was around 180uA incl. I2C bus @@ -51,7 +51,7 @@ changed - 2x the power calculation about some incorrent data sheet values changed - float to double calculation because a rare effect on uv compare map filling - in that case @andrethomas was a big help too (while(work){output=lot_of_fun};) - added - USE_VEML6070_RSET + added - USE_VEML6070_RSET - in user_config as possible input, different resistor values depending on PCB types added - USE_VEML6070_SHOW_RAW - in user_config, show or show-NOT the uv raw value @@ -62,12 +62,12 @@ safety - personal, please read this: http://www.segurancaetrabalho.com.br/download/uv_index_karel_vanicek.pdf next - possible i will add the calculation for LAT and LONG coordinates for much more precission - show not only the UV Power value in W/m2, possible a @define value to show it as joule value - - add a #define to select how many characters are shown benhind the decimal point for the UV Index + - add a #define to select how many characters are shown benhind the decimal point for the UV Index --- 1.0.0.0 20180912 started - further development by mike2nl - https://github.com/mike2nl/Sonoff-Tasmota forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota base - code base from arendst too - + */ #ifdef USE_I2C @@ -87,8 +87,8 @@ #define VEML6070_RSET_DEFAULT 270000 // 270K default resistor value 270000 ohm, range from 220K..1Meg #define VEML6070_UV_MAX_INDEX 15 // normal 11, internal on weather laboratories and NASA it's 15 so far the sensor is linear #define VEML6070_UV_MAX_DEFAULT 11 // 11 = public default table values -#define VEML6070_POWER_COEFFCIENT 0.025 // based on calculations from Karel Vanicek and reorder by hand -#define VEML6070_TABLE_COEFFCIENT 32.86270591 // calculated by hand with help from a friend of mine, a professor which works in aero space things +#define VEML6070_POWER_COEFFCIENT 0.025 // based on calculations from Karel Vanicek and reorder by hand +#define VEML6070_TABLE_COEFFCIENT 32.86270591 // calculated by hand with help from a friend of mine, a professor which works in aero space things // (resistor, differences, power coefficients and official UV index calculations (LAT & LONG will be added later) /********************************************************************************************/ @@ -110,7 +110,7 @@ void Veml6070Detect(void) Wire.beginTransmission(veml6070_address); Wire.write((itime << 2) | 0x02); uint8_t status = Wire.endTransmission(); - + if (!status) { veml6070_type = 1; snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VEML6070", veml6070_address); @@ -130,7 +130,7 @@ void Veml6070ModeCmd(boolean mode_cmd) } else { opmode = VEML6070_DISABLE; } - + veml6070_address = VEML6070_ADDR_L; Wire.beginTransmission(veml6070_address); Wire.write((opmode << 0) | 0x02 | (itime << 2)); @@ -165,7 +165,7 @@ double Veml6070UvRiskLevel(uint16_t uv_level) { double risk = 0; double uv_risk_map[VEML6070_UV_MAX_INDEX] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - + // fill the uv-risk compare table based on the coefficient calculation for (uint8_t i = 0; i < VEML6070_UV_MAX_INDEX; i++) { #ifdef USE_VEML6070_RSET @@ -179,7 +179,7 @@ double Veml6070UvRiskLevel(uint16_t uv_level) #else uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT) * (i+1); #endif - } + } // get the uv-risk level if (uv_level < uv_risk_map[VEML6070_UV_MAX_INDEX-1]) { @@ -223,8 +223,8 @@ void Veml6070Show(boolean json) { if (veml6070_type) { // wakeup the sensor - Veml6070ModeCmd(1); - + Veml6070ModeCmd(1); + // get values from functions uint16_t uvlevel = Veml6070ReadUv(); double uvrisk = Veml6070UvRiskLevel(uvlevel); @@ -243,7 +243,7 @@ void Veml6070Show(boolean json) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"VEML6070\":{\"" D_JSON_UV_INDEX "\":%s}"), mqtt_data, str_uvrisk); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"VEML6070\":{\"" D_JSON_UV_POWER "\":%s}"), mqtt_data, str_uvpower); #ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel) }; + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); }; #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { @@ -270,7 +270,7 @@ void Veml6070Show(boolean json) } else { // else for Unknown or Out Of Range error = 99 snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX7, mqtt_data, str_uvrisk); - } + } snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_POWER, mqtt_data, str_uvpower); #endif // USE_WEBSERVER } From b78626fd480e2b8254e39afd0ca7832e8087623e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 25 Sep 2018 17:08:16 +0200 Subject: [PATCH 0181/2222] Updated with Shelly --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3f695f666..498cd2f80 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ See [Community](https://groups.google.com/d/forum/sonoffusers) for forum.
See [Chat](https://discord.gg/Ks2Kzd4) for more user experience. The following devices are supported: -- [iTead Sonoff Basic](https://www.itead.cc/smart-home/sonoff-wifi-wireless-switch-1.html) +- [iTead Sonoff Basic (R2)](https://www.itead.cc/smart-home/sonoff-wifi-wireless-switch-1.html) - [iTead Sonoff RF](https://www.itead.cc/smart-home/sonoff-rf.html) - [iTead Sonoff SV](https://www.itead.cc/smart-home/sonoff-sv.html) - [iTead Sonoff TH10/TH16 with temperature sensor](https://www.itead.cc/smart-home/sonoff-th.html) @@ -90,10 +90,15 @@ The following devices are supported: - [MagicHome PWM LED controller](https://github.com/arendst/Sonoff-Tasmota/wiki/MagicHome-LED-strip-controller) - AriLux AL-LC01, AL-LC06 and AL-LC11 PWM LED controller - [Supla device - Espablo-inCan mod. for electrical Installation box](https://forum.supla.org/viewtopic.php?f=33&t=2188) -- [BlitzWolf BW-SHP2 Smart Socket with Energy Monitoring](https://www.banggood.com/BlitzWolf-BW-SHP2-Smart-WIFI-Socket-EU-Plug-220V-16A-Work-with-Amazon-Alexa-Google-Assistant-p-1292899.html) +- [BlitzWolf BW-SHP2 Smart Socket with Energy Monitoring](https://www.banggood.com/BlitzWolf-BW-SHP2-Smart-WIFI-Socket-EU-Plug-220V-16A-Work-with-Amazon-Alexa-Google-Assistant-p-1292899.html) - [Luani HVIO board](https://luani.de/projekte/esp8266-hvio/) -- Xiaomi-Phillips Bulbs -- Wemos D1 mini, NodeMcu and Ledunia +- [Wemos D1 mini](https://wiki.wemos.cc/products:d1:d1_mini) +- [HuaFan Smart Socket](HuaFan-Smart-Socket) +- [Hyleton-313 Smart Plug](Hyleton-313-Smart-Plug) +- [Allterco Shelly 1](https://shelly.cloud/shelly1-open-source/) +- [Allterco Shelly 2 with Energy Monitoring](https://shelly.cloud/shelly2/) +- NodeMcu and Ledunia +- [KS-602 based switches like GresaTek, Jesiya, NewRice, Lyasi etc](https://ucexperiment.wordpress.com/2017/11/14/reprogramming-a-lyasi-wifi-wall-switch-with-esp8285/) ### Contribute You can contribute to Sonoff-Tasmota by From 71964e0aa46e945b7fa7d958cf926fa276d69339 Mon Sep 17 00:00:00 2001 From: localhost61 Date: Wed, 26 Sep 2018 00:59:00 +0200 Subject: [PATCH 0182/2222] Update French localization --- sonoff/language/fr-FR.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index c4c913fec..9a479177a 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.1.1.7 + * Updated until v6.2.1.7 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -65,7 +65,7 @@ #define D_BY "par" // Written by me #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" -#define D_CHANNEL "Channel" +#define D_CHANNEL "Canal" #define D_CO2 "Dioxyde de carbone" #define D_CODE "code" // Button code #define D_COLDLIGHT "Froid" @@ -163,15 +163,15 @@ #define D_USER "Utilisateur" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Indice UV" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" +#define D_UV_INDEX_1 "Faible" +#define D_UV_INDEX_2 "Modéré" +#define D_UV_INDEX_3 "Élevé" +#define D_UV_INDEX_4 "Très élevé" +#define D_UV_INDEX_5 "Brûlure niv.1/2" +#define D_UV_INDEX_6 "Brûlure niv.3" +#define D_UV_INDEX_7 "Extrême" #define D_UV_LEVEL "Niveau UV" -#define D_UV_POWER "UV Power" +#define D_UV_POWER "Puissance UV" #define D_VERSION "Version" #define D_VOLTAGE "Tension" #define D_WARMLIGHT "Chaud" From 6798eb585441e6cbceb241878dfc65a2f0dee59d Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 25 Sep 2018 21:00:56 -0300 Subject: [PATCH 0183/2222] Updated Spanish Translation --- sonoff/language/es-AR.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index b67e6e79f..713e166ab 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -163,13 +163,13 @@ #define D_USER "Usuario" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Índice UV" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" +#define D_UV_INDEX_1 "Bajo" +#define D_UV_INDEX_2 "Medio" +#define D_UV_INDEX_3 "Alto" +#define D_UV_INDEX_4 "Peligroso" +#define D_UV_INDEX_5 "Quemaduras 1 a 2 grad" +#define D_UV_INDEX_6 "Quemaduras 3 grad" +#define D_UV_INDEX_7 "Fuera de Rango" #define D_UV_LEVEL "Nivel UV" #define D_UV_POWER "UV Power" #define D_VERSION "Versión" From 8ff696b34b19cc2fcefcf2bce64ab6cb701a90b8 Mon Sep 17 00:00:00 2001 From: localhost61 Date: Wed, 26 Sep 2018 02:37:27 +0200 Subject: [PATCH 0184/2222] Correct the OoR translation (thanks Adrian ;-) ) --- sonoff/language/fr-FR.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 9a479177a..a7adaea39 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -169,7 +169,7 @@ #define D_UV_INDEX_4 "Très élevé" #define D_UV_INDEX_5 "Brûlure niv.1/2" #define D_UV_INDEX_6 "Brûlure niv.3" -#define D_UV_INDEX_7 "Extrême" +#define D_UV_INDEX_7 "Hors échelle" #define D_UV_LEVEL "Niveau UV" #define D_UV_POWER "Puissance UV" #define D_VERSION "Version" @@ -184,7 +184,7 @@ #define D_SERIAL_LOGGING_DISABLED "Journalisation série désactivée" #define D_SYSLOG_LOGGING_REENABLED "Jounalisation syslog réactivée" -#define D_SET_BAUDRATE_TO "Définir baudrate à" +#define D_SET_BAUDRATE_TO "Définir le débit à" #define D_RECEIVED_TOPIC "Topic reçu" // Terme MQTT #define D_DATA_SIZE "Taille données" #define D_ANALOG_INPUT "Analogique" From bac33345a05e57fc3fb17f8c0f82ac2f406151a8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 26 Sep 2018 10:13:44 +0200 Subject: [PATCH 0185/2222] 6.2.1.8 Extent status JSON 6.2.1.8 20180926 * Change status JSON message providing more switch and retain information --- sonoff/_changelog.ino | 5 ++++- sonoff/sonoff.ino | 9 +++++++-- sonoff/sonoff_version.h | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index f2525b2a7..a442bf59e 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.2.1.7 20180925 +/* 6.2.1.8 20180926 + * Change status JSON message providing more switch and retain information + * + * 6.2.1.7 20180925 * Remove restart after ntpserver change and force NTP re-sync (#3890) * Release full Shelly2 support * Released tools/decode-config.py by Norbert Richter to decode configuration data. See file for information diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index f0619f362..5bcf5fa7c 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1412,6 +1412,7 @@ void PublishStatus(uint8_t payload) { uint8_t option = STAT; char stemp[MAX_FRIENDLYNAMES * (sizeof(Settings.friendlyname[0]) +MAX_FRIENDLYNAMES)]; + char stemp2[MAX_SWITCHES * 3]; // Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) option++; // TELE @@ -1426,8 +1427,12 @@ void PublishStatus(uint8_t payload) for (byte i = 0; i < maxfn; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%s%s\"%s\"" ), stemp, (i > 0 ? "," : ""), Settings.friendlyname[i]); } - 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_JSON_SAVESTATE "\":%d,\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), - Settings.module +1, stemp, 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); + stemp2[0] = '\0'; + for (byte i = 0; i < MAX_SWITCHES; i++) { + snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%d" ), stemp2, (i > 0 ? "," : ""), Settings.switchmode[i]); + } + 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_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), + Settings.module +1, stemp, mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, Settings.save_data, Settings.flag.save_state, Settings.switch_topic, stemp2, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_switch_retain, Settings.flag.mqtt_sensor_retain, Settings.flag.mqtt_power_retain); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS)); } diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 16c554783..915ce52d2 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020107 +#define VERSION 0x06020108 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" From 6939d6eead78d72dc2ffc104f8a6578711c5afe1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 26 Sep 2018 11:56:58 +0200 Subject: [PATCH 0186/2222] Fix Shelly Ghost and Rule sensors * Change pinmode for no-pullup defined switches to pullup when configured as switchmode PUSHBUTTON (=3 and up) (#3896) * Add delay after restart before processing rule sensor data (#3811) --- sonoff/_changelog.ino | 2 ++ sonoff/sonoff.ino | 18 ++++++++++++++++-- sonoff/sonoff_template.h | 22 ++++++++++++++++++++-- sonoff/xdrv_10_rules.ino | 2 +- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index a442bf59e..06ebd36c1 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,7 @@ /* 6.2.1.8 20180926 * Change status JSON message providing more switch and retain information + * Change pinmode for no-pullup defined switches to pullup when configured as switchmode PUSHBUTTON (=3 and up) (#3896) + * Add delay after restart before processing rule sensor data (#3811) * * 6.2.1.7 20180925 * Remove restart after ntpserver change and force NTP re-sync (#3890) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 5bcf5fa7c..6b354bb24 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -147,6 +147,7 @@ uint16_t blink_counter = 0; // Number of blink cycles uint16_t seriallog_timer = 0; // Timer to disable Seriallog uint16_t syslog_timer = 0; // Timer to re-enable syslog_level uint16_t holdbutton[MAX_KEYS] = { 0 }; // Timer for button hold +uint16_t switch_no_pullup = 0; // Switch pull-up bitmask flags int16_t save_data_counter; // Counter and flag for config save to Flash RulesBitfield rules_flag; // Rule state flags (16 bits) uint8_t serial_local = 0; // Handle serial locally; @@ -1119,6 +1120,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) else if ((CMND_SWITCHMODE == command_code) && (index > 0) && (index <= MAX_SWITCHES)) { if ((payload >= 0) && (payload < MAX_SWITCH_OPTION)) { Settings.switchmode[index -1] = payload; + GpioSwitchPinMode(index -1); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, index, Settings.switchmode[index-1]); } @@ -2296,11 +2298,23 @@ void SerialInput() /********************************************************************************************/ +void GpioSwitchPinMode(uint8_t index) +{ + if (pin[GPIO_SWT1 +index] < 99) { +// pinMode(pin[GPIO_SWT1 +index], (16 == pin[GPIO_SWT1 +index]) ? INPUT_PULLDOWN_16 : bitRead(switch_no_pullup, index) ? INPUT : INPUT_PULLUP); + + uint8_t no_pullup = 0; + if (bitRead(switch_no_pullup, index)) { + no_pullup = (Settings.switchmode[index] < PUSHBUTTON); + } + pinMode(pin[GPIO_SWT1 +index], (16 == pin[GPIO_SWT1 +index]) ? INPUT_PULLDOWN_16 : (no_pullup) ? INPUT : INPUT_PULLUP); + } +} + void GpioInit() { uint8_t mpin; uint8_t key_no_pullup = 0; - uint16_t switch_no_pullup = 0; mytmplt def_module; if (!Settings.module || (Settings.module >= MAXMODULE)) { @@ -2457,7 +2471,7 @@ void GpioInit() for (byte i = 0; i < MAX_SWITCHES; i++) { lastwallswitch[i] = 1; // Init global to virtual switch state; if (pin[GPIO_SWT1 +i] < 99) { - pinMode(pin[GPIO_SWT1 +i], (16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 : bitRead(switch_no_pullup, i) ? INPUT : INPUT_PULLUP); + GpioSwitchPinMode(i); lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // Set global now so doesn't change the saved power state on first switch check } virtualswitch[i] = lastwallswitch[i]; diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 781b1004d..f5e332531 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -399,9 +399,9 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { HUAFAN_SS, KMC_70011, AILIGHT, - WEMOS, + PHILIPS, WITTY, - PHILIPS + WEMOS }; // Default module settings @@ -1060,6 +1060,24 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { /* Optionals + { "Arilux LC10", // Arilux LC10 (ESP8285), RGBW + RF + // https://github.com/arendst/Sonoff-Tasmota/wiki/MagicHome-with-ESP8285 + // https://www.aliexpress.com/item/DC5-24V-Wireless-WIFI-LED-RGB-Controller-RGBW-Controller-IR-RF-Remote-Control-IOS-Android-for/32827253255.html + // https://www.aliexpress.com/item/Wifi-LED-RGB-Controler-DC12V-MIni-Wifi-RGB-RGBW-LED-Controller-for-RGB-RGBW-LED-Strip/32673444047.html + GPIO_USER, // GPIO00 Optional Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, + GPIO_USER, // GPIO03 Serial TXD and Optional sensor0 + GPIO_ARIRFRCV, // GPIO04 RF receiver input + GPIO_PWM2, // GPIO05 RGB LED Green + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_PWM3, // GPIO12 RGB LED Blue + GPIO_PWM4, // GPIO13 RGBW LED White + GPIO_PWM1, // GPIO14 RGB LED Red + GPIO_LED2_INV, // GPIO15 RF receiver control + 0, 0 + } + { "Xenon 3CH", // Xenon 3CH (ESP8266) - (#1128) 0, 0, 0, GPIO_KEY2, // GPIO03 Serial TXD and Optional sensor diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 303207c10..060bf085f 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -425,7 +425,7 @@ void RulesEvery50ms() void RulesEvery100ms() { - if (Settings.rule_enabled) { // Any rule enabled + if (Settings.rule_enabled && (uptime > 4)) { // Any rule enabled and allow 4 seconds start-up time for sensors (#3811) mqtt_data[0] = '\0'; int tele_period_save = tele_period; tele_period = 2; // Do not allow HA updates during next function call From 76d203d5aaed61bf4769aaa51bce6f30953b23c0 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Wed, 26 Sep 2018 15:18:01 +0200 Subject: [PATCH 0187/2222] 'decode-config.py' version bugfixes & json output enhancements - add new arguments '--json-indent' and '--json-compact' - fix poblem with invalid string chars when having garbadge in flash - fix errors using configs for Tasmota < v6.2.1 - fix setting definition for v5.13.1/v5.14.0 --- tools/decode-config.py | 127 +++++++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 44 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 299f152c4..dc51e0f42 100644 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -21,7 +21,7 @@ Requirements: - Python - - pip json pycurl urllib2 configargparse + - pip install json pycurl urllib2 configargparse Instructions: Execute command with option -d to retrieve config data from device or @@ -31,10 +31,11 @@ Instructions: Usage: - decode-config.py [-h] [-f ] [-d ] - [-u ] [-p ] [--format ] - [--sort ] [--raw] [--unhide-pw] [-o ] - [-c ] [-V] + decode-config.py [-h] [-f ] [-d ] [-u ] + [-p ] [--format ] + [--json-indent ] [--json-compact] + [--sort ] [--raw] [--unhide-pw] [-o ] + [-c ] [-V] Decode configuration of Sonoff-Tasmota device. Args that start with '--' (eg. -f) can also be set in a config file (specified via -c). Config file syntax @@ -46,21 +47,27 @@ Usage: -h, --help show this help message and exit -c , --config Config file, can be used instead of command parameter - (defaults to None) + (default: None) source: -f , --file file to retrieve Tasmota configuration from (default: None) - -d , --device - device to retrieve configuration from (default: None) + -d , --device + hostname or IP address to retrieve Tasmota + configuration from (default: None) -u , --username - for -d usage: http access username (default: admin) + host http access username (default: admin) -p , --password - for -d usage: http access password (default: None) + host http access password (default: None) output: --format output format ("json" or "text", default: "json") + --json-indent + pretty-printed JSON output using indent level + (default: "None") + --json-compact compact JSON output by eliminate whitespace (default: + "not compact") --sort sort result - can be "none" or "name" (default: "name") --raw output raw values (default: processed) @@ -72,7 +79,7 @@ Usage: info: -V, --version show program's version number and exit - Note: Either argument -d or -f must be given. + Either argument -d or -f must be given. Examples: @@ -113,7 +120,7 @@ except ImportError: sys.exit(9) -VER = '1.5.0008' +VER = '1.5.0009' PROG='{} v{} by Norbert Richter'.format(os.path.basename(sys.argv[0]),VER) CONFIG_FILE_XOR = 0x5A @@ -135,6 +142,8 @@ DEFAULTS = { 'output': { 'format': 'json', + 'jsonindent': None, + 'jsoncompact': False, 'sort': 'name', 'raw': False, 'unhide-pw': False, @@ -940,7 +949,7 @@ Setting_5_14_0 = { 'knx_CB_addr': ('3: + if not raw and len(fielddef)>3: if isinstance(fielddef[3],str): # use a format string return fielddef[3].format(value) elif callable(fielddef[3]): # use a format function @@ -1685,7 +1696,7 @@ def ConvertFieldValue(value, fielddef): return value -def GetField(dobj, fieldname, fielddef): +def GetField(dobj, fieldname, fielddef, raw=False): """ Get field value from definition @@ -1695,6 +1706,8 @@ def GetField(dobj, fieldname, fielddef): name of the field @param fielddef: see Settings desc above + @param raw + return raw values (True) or converted values (False) @return: read field value """ @@ -1715,13 +1728,13 @@ def GetField(dobj, fieldname, fielddef): subfielddef = (fielddef[0], addr, None, None if len(fielddef)<4 else fielddef[3]) length = GetFieldLength(subfielddef) if length != 0: - result.append(GetField(dobj, fieldname, subfielddef)) + result.append(GetField(dobj, fieldname, subfielddef, raw)) addr += length # tuple 2 contains a list with dict elif isinstance(fielddef[2], list) and len(fielddef[2])>0 and isinstance(fielddef[2][0], dict): d = {} value = struct.unpack_from(fielddef[0], dobj, fielddef[1])[0] - d['base'] = ConvertFieldValue(value, fielddef); + d['base'] = ConvertFieldValue(value, fielddef, raw); union = fielddef[2] i = 0 for l in union: @@ -1738,8 +1751,8 @@ def GetField(dobj, fieldname, fielddef): if ord(result[:1])==0x00 or ord(result[:1])==0xff: result = '' s = str(result).split('\0')[0] - result = s #unicode(s, errors='replace') - result = ConvertFieldValue(result, fielddef) + result = unicode(s, errors='replace') + result = ConvertFieldValue(result, fielddef, raw) return result @@ -1762,40 +1775,52 @@ def DeEncrypt(obj): def Decode(obj): """ - Decodes (already decrypted) binary data stream + Decodes binary data stream @param obj: - binary config data + binary config data (decrypted) """ # get header data - cfg_size = GetField(obj, 'cfg_size', Setting_6_2_1['cfg_size']) - version = GetField(obj, 'version', Setting_6_2_1['version']) + version = GetField(obj, 'version', Setting_6_2_1['version'], raw=True) # search setting definition - setting = None + template = None for cfg in Settings: - if version >= cfg[0] and cfg_size == cfg[1]: + if version >= cfg[0]: template = cfg break - setting = template[2] # if we did not found a mathching setting - if setting is None: - exit(2, "Can't handle Tasmota configuration data for version 0x{:x} with {} bytes".format(version, cfg_size) ) + if template is None: + exit(2, "Can't handle Tasmota configuration data for version 0x{:x}".format(version) ) - if GetField(obj, 'cfg_crc', setting['cfg_crc']) != GetSettingsCrc(obj): + setting = template[2] + + # check size if exists + if 'cfg_size' in setting: + cfg_size = GetField(obj, 'cfg_size', setting['cfg_size'], raw=True) + # if we did not found a mathching setting + if cfg_size != template[1]: + exit(2, "Data size does not match. Expected {} bytes, read {} bytes.".format(template[1], cfg_size) ) + + # check crc if exists + if 'cfg_crc' in setting: + cfg_crc = GetField(obj, 'cfg_crc', setting['cfg_crc'], raw=True) + else: + cfg_crc = GetSettingsCrc(obj) + if cfg_crc != GetSettingsCrc(obj): exit(3, 'Data crc error' ) config = {} config['version_template'] = '0x{:x}'.format(template[0]) for name in setting: - config[name] = GetField(obj, name, setting[name]) + config[name] = GetField(obj, name, setting[name], args.raw) if args.sort == 'name': config = collections.OrderedDict(sorted(config.items())) if args.format == 'json': - print json.dumps(config, sort_keys=args.sort=='name') + print json.dumps(config, sort_keys=args.sort=='name', indent=args.jsonindent, separators=(',', ':') if args.jsoncompact else (', ', ': ') ) else: for key,value in config.items(): print '{} = {}'.format(key, repr(value)) @@ -1804,7 +1829,7 @@ def Decode(obj): if __name__ == "__main__": parser = configargparse.ArgumentParser(description='Decode configuration of Sonoff-Tasmota device.', - epilog='Note: Either argument -d or -f must be given.') + epilog='Either argument -d or -f must be given.') source = parser.add_argument_group('source') source.add_argument('-f', '--file', @@ -1813,20 +1838,20 @@ if __name__ == "__main__": default=DEFAULTS['source']['tasmotafile'], help='file to retrieve Tasmota configuration from (default: {})'.format(DEFAULTS['source']['tasmotafile'])) source.add_argument('-d', '--device', - metavar='', + metavar='', dest='device', default=DEFAULTS['source']['device'], - help='device to retrieve configuration from (default: {})'.format(DEFAULTS['source']['device']) ) + help='hostname or IP address to retrieve Tasmota configuration from (default: {})'.format(DEFAULTS['source']['device']) ) source.add_argument('-u', '--username', metavar='', dest='username', default=DEFAULTS['source']['username'], - help='for -d usage: http access username (default: {})'.format(DEFAULTS['source']['username'])) + help='host http access username (default: {})'.format(DEFAULTS['source']['username'])) source.add_argument('-p', '--password', metavar='', dest='password', default=DEFAULTS['source']['password'], - help='for -d usage: http access password (default: {})'.format(DEFAULTS['source']['password'])) + help='host http access password (default: {})'.format(DEFAULTS['source']['password'])) output = parser.add_argument_group('output') output.add_argument('--format', @@ -1835,6 +1860,17 @@ if __name__ == "__main__": choices=['json', 'text'], default=DEFAULTS['output']['format'], help='output format ("json" or "text", default: "{}")'.format(DEFAULTS['output']['format']) ) + output.add_argument('--json-indent', + metavar='', + dest='jsonindent', + type=int, + default=DEFAULTS['output']['jsonindent'], + help='pretty-printed JSON output using indent level (default: "{}")'.format(DEFAULTS['output']['jsonindent']) ) + output.add_argument('--json-compact', + dest='jsoncompact', + action='store_true', + default=DEFAULTS['output']['jsoncompact'], + help='compact JSON output by eliminate whitespace (default: "{}")'.format('compact' if DEFAULTS['output']['jsoncompact'] else 'not compact') ) output.add_argument('--sort', metavar='', dest='sort', @@ -1862,7 +1898,7 @@ if __name__ == "__main__": dest='configfile', default=DEFAULTS['DEFAULT']['configfile'], is_config_file=True, - help='Config file, can be used instead of command parameter (defaults to {})'.format(DEFAULTS['DEFAULT']['configfile']) ) + help='Config file, can be used instead of command parameter (default: {})'.format(DEFAULTS['DEFAULT']['configfile']) ) info = parser.add_argument_group('info') info.add_argument('-V', '--version', action='version', version=PROG) @@ -1921,4 +1957,7 @@ if __name__ == "__main__": Decode(cfg) else: - exit(4, "Could not read configuration data from {} '{}'".format('device' if args.device is not None else 'file', args.device if args.device is not None else args.tasmotafile) ) \ No newline at end of file + exit(4, "Could not read configuration data from {} '{}'".format('device' if args.device is not None else 'file', \ + args.device if args.device is not None else args.tasmotafile) ) + + sys.exit(0) From 8022bca19cd49f63f8bfc7bf7fcb5b3d4b940090 Mon Sep 17 00:00:00 2001 From: znanev <20048364+znanev@users.noreply.github.com> Date: Wed, 26 Sep 2018 18:27:23 +0100 Subject: [PATCH 0188/2222] Update Bulgarian language file --- sonoff/language/bg-BG.h | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index ff7801984..d79eb5210 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.2.0.1 + * Updated until v6.2.1.8 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -82,7 +82,7 @@ #define D_DNS_SERVER "DNS Сървър" #define D_DONE "Изпълнено" #define D_DST_TIME "DST" -#define D_ECO2 "eCO2" +#define D_ECO2 "eCO₂" #define D_EMULATION "Емулация" #define D_ENABLED "Активиран" #define D_ERASE "Изтриване" @@ -163,15 +163,15 @@ #define D_USER "Потребител" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV индекс" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "Ниво на ултравиолетово излъчване" -#define D_UV_POWER "UV Power" +#define D_UV_INDEX_1 "Нисък" +#define D_UV_INDEX_2 "Среден" +#define D_UV_INDEX_3 "Висок" +#define D_UV_INDEX_4 "Много висок" +#define D_UV_INDEX_5 "Изгаряне 1/2 степен" +#define D_UV_INDEX_6 "Изгаряне 3-та степен" +#define D_UV_INDEX_7 "Извън обхват" +#define D_UV_LEVEL "UV ниво" +#define D_UV_POWER "UV мощност" #define D_VERSION "Версия" #define D_VOLTAGE "Напрежение" #define D_WARMLIGHT "Топла" @@ -181,8 +181,8 @@ #define D_WARNING_MINIMAL_VERSION "ПРЕДУПРЕЖДЕНИЕ Тази версия не поддържа постоянни настройки" #define D_LEVEL_10 "ниво 1-0" #define D_LEVEL_01 "ниво 0-1" -#define D_SERIAL_LOGGING_DISABLED "Серийния логинг изключен" -#define D_SYSLOG_LOGGING_REENABLED "Системния логинг активиран" +#define D_SERIAL_LOGGING_DISABLED "Серийният лог изключен" +#define D_SYSLOG_LOGGING_REENABLED "Системният лог активиран" #define D_SET_BAUDRATE_TO "Задаване скорост на предаване (Baudrate)" #define D_RECEIVED_TOPIC "Получен топик" @@ -194,7 +194,7 @@ #define D_BLOCKED_LOOP "Блокиран цикъл" #define D_WPS_FAILED_WITH_STATUS "WPS конфигурацията е НЕУСПЕШНА със статус" #define D_ACTIVE_FOR_3_MINUTES "активно в течение на 3 минути" -#define D_FAILED_TO_START "неуспешно стартиране" +#define D_FAILED_TO_START "Неуспешно стартиране" #define D_PATCH_ISSUE_2186 "Проблем с патч 2186" #define D_CONNECTING_TO_AP "Свързване към точка за достъп" #define D_IN_MODE "в режим" @@ -241,7 +241,7 @@ #define D_CONFIGURE_WIFI "Конфигурация на WiFi" #define D_CONFIGURE_MQTT "Конфигурация на MQTT" #define D_CONFIGURE_DOMOTICZ "Конфигурация на Domoticz" -#define D_CONFIGURE_LOGGING "Конфигурация на логинга" +#define D_CONFIGURE_LOGGING "Конфигурация на лога" #define D_CONFIGURE_OTHER "Драги конфигурации" #define D_CONFIRM_RESET_CONFIGURATION "Потвърдете изчистването" #define D_RESET_CONFIGURATION "Изчистване на конфигурацията" @@ -275,7 +275,7 @@ #define D_CLIENT "Клиент" #define D_FULL_TOPIC "Пълен топик" -#define D_LOGGING_PARAMETERS "Параметри на логинга" +#define D_LOGGING_PARAMETERS "Параметри на лога" #define D_SERIAL_LOG_LEVEL "Степен на серийния лог" #define D_WEB_LOG_LEVEL "Степен на Уеб лога" #define D_SYS_LOG_LEVEL "Степен на системния лог" @@ -379,13 +379,13 @@ #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/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2,5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" -#define D_DOMOTICZ_UPDATE_TIMER "Update timer" + #define D_DOMOTICZ_POWER_ENERGY "Мощност,Енергия" + #define D_DOMOTICZ_ILLUMINANCE "Осветеност" + #define D_DOMOTICZ_COUNT "Брояч/PM1" + #define D_DOMOTICZ_VOLTAGE "Напрежение/PM2,5" + #define D_DOMOTICZ_CURRENT "Ток/PM10" + #define D_DOMOTICZ_AIRQUALITY "Качество на въздуха" +#define D_DOMOTICZ_UPDATE_TIMER "Период на опресняване" // xdrv_09_timers.ino #define D_CONFIGURE_TIMER "Конфигуриране на таймер" @@ -464,7 +464,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_DFR562 "MP3 плейър" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "Ключ" // Suffix "1" #define D_SENSOR_BUTTON "Бутон" // Suffix "1" @@ -506,7 +506,7 @@ #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" #define D_UNIT_MICROSECOND "µs" #define D_UNIT_MILLIAMPERE "mA" From 9acbcc805f206dbbab0dde03d7666f6505e79e7b Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 26 Sep 2018 20:35:39 +0200 Subject: [PATCH 0189/2222] Fix logic for forced light discovery --- sonoff/xdrv_12_home_assistant.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index b085947ae..c4e5d833b 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -76,7 +76,7 @@ void HAssDiscoverRelay() for (int i = 1; i <= MAX_RELAYS; i++) { is_light = ((i == devices_present) && (light_type)); - is_topic_light = Settings.flag.hass_light; + is_topic_light = Settings.flag.hass_light || is_light; mqtt_data[0] = '\0'; // Clear retained message From 3bb8b2fe261d5c22dcce4f75dc017302bc2e0d92 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Wed, 26 Sep 2018 22:10:32 +0200 Subject: [PATCH 0190/2222] Update de-DE.h --- sonoff/language/de-DE.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 6e90ae409..07dcc9bfd 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -163,15 +163,15 @@ #define D_USER "Benutzer" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV-Index" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "UV-Level" -#define D_UV_POWER "UV Power" +#define D_UV_INDEX_1 "Niedrig" +#define D_UV_INDEX_2 "Mittel" +#define D_UV_INDEX_3 "Hoch" +#define D_UV_INDEX_4 "Intensiv" +#define D_UV_INDEX_5 "Gefährlich" +#define D_UV_INDEX_6 "Schädlich" +#define D_UV_INDEX_7 "Messwert!" +#define D_UV_LEVEL "UV-Index" +#define D_UV_POWER "UV Intensität" #define D_VERSION "Version" #define D_VOLTAGE "Spannung" #define D_WARMLIGHT "warm" From 86b3ccf6099b85a7bd71961d737e2fd9b82a2210 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Wed, 26 Sep 2018 22:20:19 +0200 Subject: [PATCH 0191/2222] Update de-DE.h --- sonoff/language/de-DE.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 07dcc9bfd..72f63f9c4 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -170,7 +170,7 @@ #define D_UV_INDEX_5 "Gefährlich" #define D_UV_INDEX_6 "Schädlich" #define D_UV_INDEX_7 "Messwert!" -#define D_UV_LEVEL "UV-Index" +#define D_UV_LEVEL "UV-Level" #define D_UV_POWER "UV Intensität" #define D_VERSION "Version" #define D_VOLTAGE "Spannung" From a67efa0ab2c36e4c94de31c13e93d6ccbfc382aa Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 26 Sep 2018 23:02:55 -0300 Subject: [PATCH 0192/2222] Added new triggers for rules on boot time To make it possible to trigger a rule at boot time with the state of the switches or relays (in order to take decisions), 2 new trigger types has been added: * SWITCH1#BOOT to be used like: ON SWITCH1#BOOT DO ... %value% ENDON ON SWITCH1#BOOT=0 DO .... ENDON ON SWITCH1#BOOT=1 DO .... ENDON and * POWER1#BOOT to be used like: ON POWER1#BOOT DO ... %value% ENDON ON POWER1#BOOT=0 DO .... ENDON ON POWER1#BOOT=1 DO .... ENDON --- sonoff/xdrv_10_rules.ino | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 060bf085f..b13dfc771 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -376,6 +376,25 @@ void RulesEvery50ms() RulesProcessEvent(json_event); } } + } else { + // Boot time POWER OUTPUTS (Relays) Status + for (byte i = 0; i < devices_present; i++) { + uint8_t new_state = (rules_new_power >> i) &1; + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Power%d\":{\"Boot\":%d}}"), i +1, new_state); + RulesProcessEvent(json_event); + } + // Boot time SWITCHES Status + for (byte i = 0; i < MAX_SWITCHES; i++) { +#ifdef USE_TM1638 + if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { +#else + if (pin[GPIO_SWT1 +i] < 99) { +#endif // USE_TM1638 + boolean swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"" D_JSON_SWITCH "%d\":{\"Boot\":%d}}"), i +1, (swm ^ lastwallswitch[i])); + RulesProcessEvent(json_event); + } + } } rules_old_power = rules_new_power; } From a84b38dae2b542f5c0a596b05084d15e482a63ed Mon Sep 17 00:00:00 2001 From: Staars Date: Thu, 27 Sep 2018 08:34:12 +0200 Subject: [PATCH 0193/2222] intermediate version for aTime-adjustment --- sonoff/xsns_27_apds9960.ino | 91 +++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 20 deletions(-) diff --git a/sonoff/xsns_27_apds9960.ino b/sonoff/xsns_27_apds9960.ino index 2907bc030..d2e5dbc8b 100644 --- a/sonoff/xsns_27_apds9960.ino +++ b/sonoff/xsns_27_apds9960.ino @@ -39,7 +39,7 @@ * I2C Address: 0x39 \*********************************************************************************************/ -#if defined(USE_SHT) || defined(USE_VEML6070) +#if defined(USE_SHT) || defined(USE_VEML6070) || defined(USE_TSL2561) #warning **** Turned off conflicting drivers SHT and VEML6070 **** #ifdef USE_SHT #undef USE_SHT // SHT-Driver blocks gesture sensor @@ -47,6 +47,9 @@ #ifdef USE_VEML6070 #undef USE_VEML6070 // address conflict on the I2C-bus #endif + #ifdef USE_TSL2561 + #undef USE_TSL2561 // possible address conflict on the I2C-bus + #endif #endif #define APDS9960_I2C_ADDR 0x39 @@ -64,10 +67,11 @@ uint8_t APDS9960addr; uint8_t APDS9960type = 0; -char APDS9960stype[7]; +char APDS9960stype[9]; char currentGesture[6]; uint8_t gesture_mode = 1; + volatile uint8_t recovery_loop_counter = 0; //count number of stateloops to switch the sensor off, if needed #define APDS9960_LONG_RECOVERY 50 //long pause after sensor overload in loops #define APDS9960_MAX_GESTURE_CYCLES 50 //how many FIFO-reads are allowed to prevent crash @@ -78,8 +82,7 @@ const char HTTP_APDS_9960_SNS[] PROGMEM = "%s" "{s}" "Red" "{m}%s{e}" "{s}" "Green" "{m}%s{e}" "{s}" "Blue" "{m}%s{e}" - "{s}" "Ambient" "{m}%s{e}" - "{s}" "Illuminance" "{m}%s " D_UNIT_LUX "{e}" + "{s}" "Ambient" "{m}%s " D_UNIT_LUX "{e}" "{s}" "CCT" "{m}%s " "K" "{e}" // calculated color temperature in Kelvin "{s}" "Proximity" "{m}%s{e}"; // {s} = , {m} = , {e} = #endif // USE_WEBSERVER @@ -209,7 +212,7 @@ const char HTTP_APDS_9960_SNS[] PROGMEM = "%s" #define GWTIME_39_2MS 7 /* Default values */ -#define DEFAULT_ATIME 219 // 103ms +#define DEFAULT_ATIME 0xdb // 103ms = 0xdb #define DEFAULT_WTIME 246 // 27ms #define DEFAULT_PROX_PPULSE 0x87 // 16us, 8 pulses #define DEFAULT_GESTURE_PPULSE 0x89 // 16us, 10 pulses ---89 @@ -218,7 +221,7 @@ const char HTTP_APDS_9960_SNS[] PROGMEM = "%s" #define DEFAULT_CONFIG1 0x60 // No 12x wait (WTIME) factor #define DEFAULT_LDRIVE LED_DRIVE_100MA #define DEFAULT_PGAIN PGAIN_4X -#define DEFAULT_AGAIN AGAIN_4X +#define DEFAULT_AGAIN AGAIN_4X // we have to divide by the same facot at the end #define DEFAULT_PILT 0 // Low proximity threshold #define DEFAULT_PIHT 50 // High proximity threshold #define DEFAULT_AILT 0xFFFF // Force interrupt for calibration @@ -287,6 +290,7 @@ typedef struct gesture_data_type { } color_data_type; color_data_type color_data; + uint8_t APDS9960_aTime = DEFAULT_ATIME; /******************************************************************************* @@ -360,7 +364,7 @@ void calculateColorTemperature() /* and 60W incandescent values for a wide range. */ /* Note: Y = Illuminance or lux */ X = (-0.14282F * color_data.r) + (1.54924F * color_data.g) + (-0.95641F * color_data.b); - Y = (-0.32466F * color_data.r) + (1.57837F * color_data.g) + (-0.73191F * color_data.b); // this is Lux + Y = (-0.32466F * color_data.r) + (1.57837F * color_data.g) + (-0.73191F * color_data.b); // this is Lux ... under certain circumstances Z = (-0.68202F * color_data.r) + (0.77073F * color_data.g) + ( 0.56332F * color_data.b); /* 2. Calculate the chromaticity co-ordinates */ @@ -372,7 +376,6 @@ void calculateColorTemperature() /* Calculate the final CCT */ color_data.cct = (449.0F * powf(n, 3)) + (3525.0F * powf(n, 2)) + (6823.3F * n) + 5520.33F; - color_data.lux = Y; // according to Adafruit code comments this seems to be not a perfect solution return; } @@ -1611,7 +1614,7 @@ void readAllColorAndProximityData() if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9)) { // not absolutely shure, if this is a correct way to do this, but it is very short - // we fill the struct byte by byte + // we fill the struct byte by byte } } @@ -1803,11 +1806,11 @@ void handleGesture() { break; case DIR_LEFT: snprintf_P(log, sizeof(log), PSTR("LEFT")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Left")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Left")); break; case DIR_RIGHT: snprintf_P(log, sizeof(log), PSTR("RIGHT")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Right")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Right")); break; default: if(APDS9960_overload) @@ -1832,6 +1835,41 @@ void handleGesture() { } } +void APDS9960_adjustATime(void) // not really used atm +{ + //readAllColorAndProximityData(); + I2cValidRead16LE(&color_data.a, APDS9960_I2C_ADDR, APDS9960_CDATAL); + //disablePower(); + + if (color_data.a < (uint16_t)20){ + APDS9960_aTime = 0x40; + } + else if (color_data.a < (uint16_t)40){ + APDS9960_aTime = 0x80; + } + else if (color_data.a < (uint16_t)50){ + APDS9960_aTime = DEFAULT_ATIME; + } + else if (color_data.a < (uint16_t)70){ + APDS9960_aTime = 0xc0; + } + if (color_data.a < 200){ + APDS9960_aTime = 0xe9; + } +/* if (color_data.a < 10000){ + APDS9960_aTime = 0xF0; + }*/ + else{ + APDS9960_aTime = 0xff; + } + + //disableLightSensor(); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, APDS9960_aTime); + enablePower(); + enableLightSensor(); + delay(20); +} + void APDS9960_loop() { @@ -1910,29 +1948,30 @@ void APDS9960_show(boolean json) char green_chr[10]; char blue_chr[10]; char ambient_chr[10]; - char illuminance_chr[10]; char cct_chr[10]; char prox_chr[10]; readAllColorAndProximityData(); - sprintf (ambient_chr, "%u", color_data.a); + + sprintf (ambient_chr, "%u", color_data.a/4); sprintf (red_chr, "%u", color_data.r); sprintf (green_chr, "%u", color_data.g); sprintf (blue_chr, "%u", color_data.b ); sprintf (prox_chr, "%u", color_data.p ); + /* disableLightSensor(); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, DEFAULT_ATIME); // reset to default + enableLightSensor();*/ + calculateColorTemperature(); // and calculate Lux sprintf (cct_chr, "%u", color_data.cct); - sprintf (illuminance_chr, "%u", color_data.lux); - - if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"Illuminance\":%s,\"CCT\":%s,\"Proximity\":%s}"), - mqtt_data, APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, illuminance_chr, cct_chr, prox_chr); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"CCT\":%s,\"Proximity\":%s}"), + mqtt_data, APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_APDS_9960_SNS, mqtt_data, red_chr, green_chr, blue_chr, ambient_chr, illuminance_chr, cct_chr, prox_chr ); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_APDS_9960_SNS, mqtt_data, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr ); #endif // USE_WEBSERVER } } @@ -1952,6 +1991,7 @@ void APDS9960_show(boolean json) * Sensor27 | | Show current gesture mode * Sensor27 | 0 / Off | Disable gesture mode * Sensor27 | 1 / On | Enable gesture mode + * Sensor27 | 2 / On | Enable gesture mode with half gain \*********************************************************************************************/ bool APDS9960CommandSensor() @@ -1973,7 +2013,8 @@ bool APDS9960CommandSensor() enableGestureSensor(); gesture_mode = 1; } - case 2: + break; + case 2: // gain of 2x , needed for some models if (APDS9960type) { setGestureGain(GGAIN_2X); setProximityGain(PGAIN_2X); @@ -1981,6 +2022,16 @@ bool APDS9960CommandSensor() enableGestureSensor(); gesture_mode = 1; } + break; + default: + int temp_aTime = (uint8_t)XdrvMailbox.payload; + if (temp_aTime > 2 && temp_aTime < 256){ + disablePower(); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, temp_aTime); + enablePower(); + enableLightSensor(); + } + break; } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_27, GetStateText(gesture_mode)); From 1a4458528e1f1269062d03ad45055779e8895959 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 27 Sep 2018 18:36:42 +0200 Subject: [PATCH 0194/2222] Add Neo Coolcam support Add support for Neo Coolcam Wifi Smart Power Plug --- sonoff/_changelog.ino | 3 +++ sonoff/sonoff_template.h | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 06ebd36c1..ebf1b83cb 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,9 @@ * Change status JSON message providing more switch and retain information * Change pinmode for no-pullup defined switches to pullup when configured as switchmode PUSHBUTTON (=3 and up) (#3896) * Add delay after restart before processing rule sensor data (#3811) + * Fix Home Assistant forced light discovery (#3908) + * Add rule triggers SWITCH1#BOOT and POWER1#BOOT (#3904, #3910) + * Add support for Neo Coolcam Wifi Smart Power Plug * * 6.2.1.7 20180925 * Remove restart after ntpserver change and force NTP re-sync (#3890) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index f5e332531..8374fa09d 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -231,6 +231,7 @@ enum SupportedModules { SHELLY1, SHELLY2, PHILIPS, + NEO_COOLCAM, MAXMODULE }; /********************************************************************************************/ @@ -390,6 +391,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { SHELLY1, SHELLY2, BLITZWOLF_BWSHP2, + NEO_COOLCAM, H801, MAGICHOME, ARILUX_LC01, @@ -1054,6 +1056,16 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, GPIO_PWM1, // GPIO15 light intensity 0, 0 + }, + { "Neo Coolcam", // Neo Coolcam (ESP8266) + // https://www.banggood.com/NEO-COOLCAM-WiFi-Mini-Smart-Plug-APP-Remote-Control-Timing-Smart-Socket-EU-Plug-p-1288562.html?cur_warehouse=CN + 0, 0, 0, 0, + GPIO_LED1_INV, // GPIO13 Red Led (0 = On, 1 = Off) + 0, + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_KEY1, // GPIO13 Button + 0, 0, 0, 0 } }; From 1a0d630da214a180b77096f7f4129dc701562a4d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 28 Sep 2018 11:48:55 +0200 Subject: [PATCH 0195/2222] Removed debug code Removed unavailable debug code (#3917) --- sonoff/settings.ino | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 0d8fa451a..95e6ce367 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -86,20 +86,12 @@ void RtcSettingsSave() RtcSettings.valid = RTC_MEM_VALID; ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); rtc_settings_crc = GetRtcSettingsCrc(); -#ifdef DEBUG_THEO - AddLog_P(LOG_LEVEL_DEBUG, PSTR("Dump: Save")); - RtcSettingsDump(); -#endif // DEBUG_THEO } } void RtcSettingsLoad() { ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); // 0x290 -#ifdef DEBUG_THEO - AddLog_P(LOG_LEVEL_DEBUG, PSTR("Dump: Load")); - RtcSettingsDump(); -#endif // DEBUG_THEO if (RtcSettings.valid != RTC_MEM_VALID) { memset(&RtcSettings, 0, sizeof(RTCMEM)); RtcSettings.valid = RTC_MEM_VALID; From 4b7c797fb76cf8e6ee1a5680b5af430705fbbf65 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 28 Sep 2018 15:48:42 +0200 Subject: [PATCH 0196/2222] 6.2.1.9 Apparent/Reactive Power 6.2.1.9 20180928 * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251) --- sonoff/_changelog.ino | 5 +- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 26 +++++++ sonoff/xdrv_03_energy.ino | 146 +++++++++++++++++++++-------------- sonoff/xnrg_01_hlw8012.ino | 7 +- sonoff/xnrg_02_cse7766.ino | 15 ++-- sonoff/xnrg_03_pzem004t.ino | 3 +- sonoff/xnrg_04_mcp39f501.ino | 7 +- sonoff/xnrg_05_pzem2.ino | 6 +- 9 files changed, 137 insertions(+), 80 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index ebf1b83cb..abf4572f6 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.2.1.8 20180926 +/* 6.2.1.9 20180928 + * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251) + * + * 6.2.1.8 20180926 * Change status JSON message providing more switch and retain information * Change pinmode for no-pullup defined switches to pullup when configured as switchmode PUSHBUTTON (=3 and up) (#3896) * Add delay after restart before processing rule sensor data (#3811) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 915ce52d2..4f2b5c0ec 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020108 +#define VERSION 0x06020109 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index fb2b5eae3..fc73e726e 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -494,6 +494,32 @@ double FastPrecisePow(double a, double b) return r * u.d; } +uint32_t SqrtInt(uint32_t num) +{ + if (num <= 1) { + return num; + } + + uint32_t x = num / 2; + uint32_t y; + do { + y = (x + num / x) / 2; + if (y >= x) { + return x; + } + x = y; + } while (true); +} + +uint32_t RoundSqrtInt(uint32_t num) +{ + uint32_t s = SqrtInt(4 * num); + if (s & 1) { + s++; + } + return s / 2; +} + char* GetTextIndexed(char* destination, size_t destination_size, uint16_t index, const char* haystack) { // Returns empty string if not found diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 3ccad7df4..13ab1cb62 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -41,23 +41,25 @@ const char kEnergyCommands[] PROGMEM = D_CMND_MAXPOWER "|" D_CMND_MAXPOWERHOLD "|" D_CMND_MAXPOWERWINDOW "|" D_CMND_SAFEPOWER "|" D_CMND_SAFEPOWERHOLD "|" D_CMND_SAFEPOWERWINDOW ; -float energy_voltage = 0; // 123.1 V -float energy_current = 0; // 123.123 A -float energy_power = 0; // 123.1 W -float energy_power_factor = NAN; // 0.12 -int energy_calc_power_factor = 0; // Do not calculate power factor from data -float energy_frequency = NAN; // 123.1 Hz -float energy_start = 0; // 12345.12345 kWh total previous +float energy_voltage = 0; // 123.1 V +float energy_current = 0; // 123.123 A +float energy_active_power = 0; // 123.1 W +float energy_apparent_power = NAN; // 123.1 VA +float energy_reactive_power = NAN; // 123.1 VAr +float energy_power_factor = NAN; // 0.12 +float energy_frequency = NAN; // 123.1 Hz +float energy_start = 0; // 12345.12345 kWh total previous -float energy_daily = 0; // 123.123 kWh -float energy_total = 0; // 12345.12345 kWh +float energy_daily = 0; // 123.123 kWh +float energy_total = 0; // 12345.12345 kWh unsigned long energy_kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to energy_kWhtoday (HLW and CSE only) -unsigned long energy_kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = energy_daily -unsigned long energy_period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = energy_daily +unsigned long energy_kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = energy_daily +unsigned long energy_period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = energy_daily float energy_power_last[3] = { 0 }; uint8_t energy_power_delta = 0; +bool energy_type_dc = false; bool energy_power_on = true; byte energy_min_power_flag = 0; @@ -124,15 +126,6 @@ void Energy200ms() } XnrgCall(FUNC_EVERY_200_MSECOND); - - if (energy_calc_power_factor) { - float power_factor = 0; - if (energy_voltage && energy_current && energy_power) { - power_factor = energy_power / (energy_voltage * energy_current); - if (power_factor > 1) power_factor = 1; - } - energy_power_factor = power_factor; - } } void EnergySaveState() @@ -178,21 +171,21 @@ void EnergyMarginCheck() } if (Settings.energy_power_delta) { - float delta = abs(energy_power_last[0] - energy_power); + float delta = abs(energy_power_last[0] - energy_active_power); // Any delta compared to minimal delta - float min_power = (energy_power_last[0] > energy_power) ? energy_power : energy_power_last[0]; + float min_power = (energy_power_last[0] > energy_active_power) ? energy_active_power : energy_power_last[0]; if (((delta / min_power) * 100) > Settings.energy_power_delta) { energy_power_delta = 1; - energy_power_last[1] = energy_power; // We only want one report so reset history - energy_power_last[2] = energy_power; + energy_power_last[1] = energy_active_power; // We only want one report so reset history + energy_power_last[2] = energy_active_power; } } energy_power_last[0] = energy_power_last[1]; // Shift in history every second allowing power changes to settle for up to three seconds energy_power_last[1] = energy_power_last[2]; - energy_power_last[2] = energy_power; + energy_power_last[2] = energy_active_power; if (energy_power_on && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) { - energy_power_u = (uint16_t)(energy_power); + energy_power_u = (uint16_t)(energy_active_power); energy_voltage_u = (uint16_t)(energy_voltage); energy_current_u = (uint16_t)(energy_current * 1000); @@ -235,7 +228,7 @@ void EnergyMarginCheck() #if FEATURE_POWER_LIMIT // Max Power if (Settings.energy_max_power_limit) { - if (energy_power > Settings.energy_max_power_limit) { + if (energy_active_power > Settings.energy_max_power_limit) { if (!energy_mplh_counter) { energy_mplh_counter = Settings.energy_max_power_limit_hold; } else { @@ -535,6 +528,8 @@ const char HTTP_ENERGY_SNS1[] PROGMEM = "%s" "{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; const char HTTP_ENERGY_SNS2[] PROGMEM = "%s" + "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" + "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" "{s}" D_POWER_FACTOR "{m}%s{e}"; const char HTTP_ENERGY_SNS3[] PROGMEM = "%s" @@ -548,27 +543,64 @@ const char HTTP_ENERGY_SNS4[] PROGMEM = "%s" void EnergyShow(boolean json) { - char energy_total_chr[10]; + char voltage_chr[10]; + char current_chr[10]; + char active_power_chr[10]; + char apparent_power_chr[10]; + char reactive_power_chr[10]; + char power_factor_chr[10]; + char frequency_chr[10]; char energy_daily_chr[10]; char energy_period_chr[10]; - char energy_power_chr[10]; - char energy_voltage_chr[10]; - char energy_current_chr[10]; - char energy_frequency_chr[10]; - char energy_power_factor_chr[10]; char energy_yesterday_chr[10]; + char energy_total_chr[10]; + char speriod[20]; - char spfactor[20]; char sfrequency[20]; bool show_energy_period = (0 == tele_period); - dtostrfd(energy_power, Settings.flag2.wattage_resolution, energy_power_chr); - dtostrfd(energy_voltage, Settings.flag2.voltage_resolution, energy_voltage_chr); - dtostrfd(energy_current, Settings.flag2.current_resolution, energy_current_chr); - dtostrfd(energy_total, Settings.flag2.energy_resolution, energy_total_chr); + if (!energy_type_dc) { + float apparent_power = energy_apparent_power; + if (isnan(apparent_power)) { + apparent_power = energy_voltage * energy_current; + } + if (apparent_power < energy_active_power) { // Should be impossible + energy_active_power = apparent_power; + } + + float power_factor = energy_power_factor; + if (isnan(power_factor)) { + power_factor = (energy_active_power && apparent_power) ? energy_active_power / apparent_power : 0; + if (power_factor > 1) power_factor = 1; + } + + float reactive_power = energy_reactive_power; + if (isnan(reactive_power)) { + reactive_power = 0; + uint32_t difference = ((uint32_t)(apparent_power * 100) - (uint32_t)(energy_active_power * 100)) / 10; + if ((energy_current > 0.005) && ((difference > 15) || (difference > (uint32_t)(apparent_power * 100 / 1000)))) { + // calculating reactive power only if current is greater than 0.005A and + // difference between active and apparent power is greater than 1.5W or 1% + reactive_power = (float)(RoundSqrtInt((uint32_t)(apparent_power * apparent_power * 100) - (uint32_t)(energy_active_power * energy_active_power * 100))) / 10; + } + } + + dtostrfd(apparent_power, Settings.flag2.wattage_resolution, apparent_power_chr); + dtostrfd(reactive_power, Settings.flag2.wattage_resolution, reactive_power_chr); + dtostrfd(power_factor, 2, power_factor_chr); + if (!isnan(energy_frequency)) { + dtostrfd(energy_frequency, Settings.flag2.frequency_resolution, frequency_chr); + snprintf_P(sfrequency, sizeof(sfrequency), PSTR(",\"" D_JSON_FREQUENCY "\":%s"), frequency_chr); + } + } + + dtostrfd(energy_voltage, Settings.flag2.voltage_resolution, voltage_chr); + dtostrfd(energy_current, Settings.flag2.current_resolution, current_chr); + dtostrfd(energy_active_power, Settings.flag2.wattage_resolution, active_power_chr); dtostrfd(energy_daily, Settings.flag2.energy_resolution, energy_daily_chr); dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); + dtostrfd(energy_total, Settings.flag2.energy_resolution, energy_total_chr); float energy = 0; if (show_energy_period) { @@ -577,34 +609,30 @@ void EnergyShow(boolean json) dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr); snprintf_P(speriod, sizeof(speriod), PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr); } - if (!isnan(energy_frequency)) { - dtostrfd(energy_frequency, Settings.flag2.frequency_resolution, energy_frequency_chr); - snprintf_P(sfrequency, sizeof(sfrequency), PSTR(",\"" D_JSON_FREQUENCY "\":%s"), energy_frequency_chr); - } - if (!isnan(energy_power_factor)) { - dtostrfd(energy_power_factor, 2, energy_power_factor_chr); - snprintf_P(spfactor, sizeof(spfactor), PSTR(",\"" D_JSON_POWERFACTOR "\":%s"), energy_power_factor_chr); - } if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" - D_JSON_POWERUSAGE "\":%s%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s%s}"), - mqtt_data, energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", - energy_power_chr, (!isnan(energy_power_factor)) ? spfactor : "", energy_voltage_chr, energy_current_chr, (!isnan(energy_frequency)) ? sfrequency : ""); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" D_JSON_POWERUSAGE "\":%s"), + mqtt_data, energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", active_power_chr); + if (!energy_type_dc) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s%s"), + mqtt_data, apparent_power_chr, reactive_power_chr, power_factor_chr, (!isnan(energy_frequency)) ? sfrequency : ""); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), mqtt_data, voltage_chr, current_chr); + #ifdef USE_DOMOTICZ if (show_energy_period) { // Only send if telemetry dtostrfd(energy_total * 1000, 1, energy_total_chr); - DomoticzSensorPowerEnergy((int)energy_power, energy_total_chr); // PowerUsage, EnergyToday - DomoticzSensor(DZ_VOLTAGE, energy_voltage_chr); // Voltage - DomoticzSensor(DZ_CURRENT, energy_current_chr); // Current + DomoticzSensorPowerEnergy((int)energy_active_power, energy_total_chr); // PowerUsage, EnergyToday + DomoticzSensor(DZ_VOLTAGE, voltage_chr); // Voltage + DomoticzSensor(DZ_CURRENT, current_chr); // Current } #endif // USE_DOMOTICZ #ifdef USE_KNX if (show_energy_period) { KnxSensor(KNX_ENERGY_VOLTAGE, energy_voltage); KnxSensor(KNX_ENERGY_CURRENT, energy_current); - KnxSensor(KNX_ENERGY_POWER, energy_power); - if (!isnan(energy_power_factor)) { KnxSensor(KNX_ENERGY_POWERFACTOR, energy_power_factor); } + KnxSensor(KNX_ENERGY_POWER, energy_active_power); + if (!energy_type_dc) { KnxSensor(KNX_ENERGY_POWERFACTOR, power_factor); } KnxSensor(KNX_ENERGY_DAILY, energy_daily); KnxSensor(KNX_ENERGY_TOTAL, energy_total); KnxSensor(KNX_ENERGY_START, energy_start); @@ -612,9 +640,11 @@ void EnergyShow(boolean json) #endif // USE_KNX #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS1, mqtt_data, energy_voltage_chr, energy_current_chr, energy_power_chr); - if (!isnan(energy_power_factor)) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS2, mqtt_data, energy_power_factor_chr); } - if (!isnan(energy_frequency)) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS3, mqtt_data, energy_frequency_chr); } + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS1, mqtt_data, voltage_chr, current_chr, active_power_chr); + if (!energy_type_dc) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS2, mqtt_data, apparent_power_chr, reactive_power_chr, power_factor_chr); + if (!isnan(energy_frequency)) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS3, mqtt_data, frequency_chr); } + } snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS4, mqtt_data, energy_daily_chr, energy_yesterday_chr, energy_total_chr); #endif // USE_WEBSERVER } diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 5140d6596..025ccff44 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -111,9 +111,9 @@ void HlwEvery200ms() if (hlw_cf_pulse_length && energy_power_on && !hlw_load_off) { hlw_w = (hlw_power_ratio * Settings.energy_power_calibration) / hlw_cf_pulse_length; - energy_power = (float)hlw_w / 10; + energy_active_power = (float)hlw_w / 10; } else { - energy_power = 0; + energy_active_power = 0; } hlw_cf1_timer++; @@ -142,7 +142,7 @@ void HlwEvery200ms() hlw_cf1_current_pulse_length = hlw_cf1_pulse_length; hlw_cf1_current_max_pulse_counter = hlw_cf1_pulse_counter; - if (hlw_cf1_current_pulse_length && energy_power) { // No current if no power being consumed + if (hlw_cf1_current_pulse_length && energy_active_power) { // No current if no power being consumed hlw_i = (hlw_current_ratio * Settings.energy_current_calibration) / hlw_cf1_current_pulse_length; energy_current = (float)hlw_i / 1000; } else { @@ -217,7 +217,6 @@ void HlwDrvInit() { if (!energy_flg) { if ((pin[GPIO_HLW_SEL] < 99) && (pin[GPIO_HLW_CF1] < 99) && (pin[GPIO_HLW_CF] < 99)) { // Sonoff Pow or any HLW8012 based device - energy_calc_power_factor = 1; // Calculate power factor from data energy_flg = XNRG_01; } } diff --git a/sonoff/xnrg_02_cse7766.ino b/sonoff/xnrg_02_cse7766.ino index 8ba1b146e..1be231192 100644 --- a/sonoff/xnrg_02_cse7766.ino +++ b/sonoff/xnrg_02_cse7766.ino @@ -95,14 +95,14 @@ void CseReceived() if (adjustement & 0x10) { // Power valid cse_power_invalid = 0; if ((header & 0xF2) == 0xF2) { // Power cycle exceeds range - energy_power = 0; + energy_active_power = 0; } else { if (0 == power_cycle_first) { power_cycle_first = power_cycle; } // Skip first incomplete power_cycle if (power_cycle_first != power_cycle) { power_cycle_first = -1; - energy_power = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)power_cycle; + energy_active_power = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)power_cycle; } else { - energy_power = 0; + energy_active_power = 0; } } } else { @@ -110,11 +110,11 @@ void CseReceived() cse_power_invalid++; } else { power_cycle_first = 0; - energy_power = 0; // Powered on but no load + energy_active_power = 0; // Powered on but no load } } if (adjustement & 0x20) { // Current valid - if (0 == energy_power) { + if (0 == energy_active_power) { energy_current = 0; } else { energy_current = (float)Settings.energy_current_calibration / (float)current_cycle; @@ -123,7 +123,7 @@ void CseReceived() } else { // Powered off power_cycle_first = 0; energy_voltage = 0; - energy_power = 0; + energy_active_power = 0; energy_current = 0; } } @@ -180,7 +180,7 @@ void CseEverySecond() } else { cf_frequency = cf_pulses - cf_pulses_last_time; } - if (cf_frequency && energy_power) { + if (cf_frequency && energy_active_power) { cf_pulses_last_time = cf_pulses; energy_kWhtoday_delta += (cf_frequency * Settings.energy_power_calibration) / 36; EnergyUpdateToday(); @@ -194,7 +194,6 @@ void CseDrvInit() if ((SONOFF_S31 == Settings.module) || (SONOFF_POW_R2 == Settings.module)) { // Sonoff S31 or Sonoff Pow R2 baudrate = 4800; serial_config = SERIAL_8E1; - energy_calc_power_factor = 1; // Calculate power factor from data energy_flg = XNRG_02; } } diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index 03581862c..3dfbc3879 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -177,7 +177,7 @@ void PzemEvery200ms() energy_current = value; break; case 3: // Power as 20W - energy_power = value; + energy_active_power = value; break; case 4: // Total energy as 99999Wh if (!energy_start || (value < energy_start)) energy_start = value; // Init after restart and hanlde roll-over if any @@ -215,7 +215,6 @@ void PzemDrvInit() { if (!energy_flg) { if ((pin[GPIO_PZEM_RX] < 99) && (pin[GPIO_PZEM_TX] < 99)) { // Any device with a Pzem004T - energy_calc_power_factor = 1; // Calculate power factor from data energy_flg = XNRG_03; } } diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index f2ce321bc..d962ef204 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -448,8 +448,8 @@ void McpParseData(void) if (energy_power_on) { // Powered on energy_frequency = (float)mcp_line_frequency / 1000; energy_voltage = (float)mcp_voltage_rms / 10; - energy_power = (float)mcp_active_power / 100; - if (0 == energy_power) { + energy_active_power = (float)mcp_active_power / 100; + if (0 == energy_active_power) { energy_current = 0; } else { energy_current = (float)mcp_current_rms / 10000; @@ -457,7 +457,7 @@ void McpParseData(void) } else { // Powered off energy_frequency = 0; energy_voltage = 0; - energy_power = 0; + energy_active_power = 0; energy_current = 0; } } @@ -557,7 +557,6 @@ void McpDrvInit(void) mcp_calibrate = 0; mcp_timeout = 2; // Initial wait mcp_init = 2; // Initial setup steps - energy_calc_power_factor = 1; // Calculate power factor from data energy_flg = XNRG_04; } } diff --git a/sonoff/xnrg_05_pzem2.ino b/sonoff/xnrg_05_pzem2.ino index b7e1eab42..bb0f4864d 100644 --- a/sonoff/xnrg_05_pzem2.ino +++ b/sonoff/xnrg_05_pzem2.ino @@ -141,12 +141,13 @@ void Pzem2Every200ms() float energy = 0; if (PZEM2_TYPES_003_017 == pzem2_type) { + energy_type_dc = true; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // FE 04 10 27 10 00 64 03 E8 00 00 00 00 00 00 00 00 00 00 HH LL = PZEM-017 // Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc-- energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V energy_current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A - energy_power = (float)((uint32_t)buffer[9] << 24 + (uint32_t)buffer[10] << 16 + (uint32_t)buffer[7] << 8 + buffer[8]) / 10.0; // 429496729.0 W + energy_active_power = (float)((uint32_t)buffer[9] << 24 + (uint32_t)buffer[10] << 16 + (uint32_t)buffer[7] << 8 + buffer[8]) / 10.0; // 429496729.0 W energy = (float)((uint32_t)buffer[13] << 24 + (uint32_t)buffer[14] << 16 + (uint32_t)buffer[11] << 8 + buffer[12]); // 4294967295 Wh if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any energy_kWhtoday += (energy - energy_start) * 100; @@ -154,12 +155,13 @@ void Pzem2Every200ms() EnergyUpdateToday(); } else if (PZEM2_TYPES_014_016 == pzem2_type) { // PZEM-014,016 + energy_type_dc = false; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // FE 04 14 08 98 03 E8 00 00 08 98 00 00 00 00 00 00 01 F4 00 64 00 00 HH LL = PZEM-014 // Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc-- energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V energy_current = (float)((uint32_t)buffer[7] << 24 + (uint32_t)buffer[8] << 16 + (uint32_t)buffer[5] << 8 + buffer[6]) / 1000.0; // 4294967.000 A - energy_power = (float)((uint32_t)buffer[11] << 24 + (uint32_t)buffer[12] << 16 + (uint32_t)buffer[9] << 8 + buffer[10]) / 10.0; // 429496729.0 W + energy_active_power = (float)((uint32_t)buffer[11] << 24 + (uint32_t)buffer[12] << 16 + (uint32_t)buffer[9] << 8 + buffer[10]) / 10.0; // 429496729.0 W energy_frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00 energy = (float)((uint32_t)buffer[15] << 24 + (uint32_t)buffer[16] << 16 + (uint32_t)buffer[13] << 8 + buffer[14]); // 4294967295 Wh From f05a471e48bb0ae891df61cdde1679abab0f0f4c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 28 Sep 2018 17:02:55 +0200 Subject: [PATCH 0197/2222] Fix KNX compile error --- sonoff/xdrv_03_energy.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 13ab1cb62..341fc71b5 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -560,6 +560,8 @@ void EnergyShow(boolean json) bool show_energy_period = (0 == tele_period); + float power_factor = energy_power_factor; + if (!energy_type_dc) { float apparent_power = energy_apparent_power; if (isnan(apparent_power)) { @@ -569,7 +571,6 @@ void EnergyShow(boolean json) energy_active_power = apparent_power; } - float power_factor = energy_power_factor; if (isnan(power_factor)) { power_factor = (energy_active_power && apparent_power) ? energy_active_power / apparent_power : 0; if (power_factor > 1) power_factor = 1; From 8f95f07b518010a6c3bf37a2ac34a02b5309fd5e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 28 Sep 2018 17:26:08 +0200 Subject: [PATCH 0198/2222] Add RF to MagicHome / LC10 Add RF Receiver control to module MagicHome to be used on Arilux LC10 (#3792) --- sonoff/_changelog.ino | 1 + sonoff/sonoff_template.h | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index abf4572f6..efd0944b7 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.2.1.9 20180928 * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251) + * Add RF Receiver control to module MagicHome to be used on Arilux LC10 (#3792) * * 6.2.1.8 20180926 * Change status JSON message providing more switch and retain information diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 8374fa09d..d083675d3 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -855,6 +855,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 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, @@ -869,6 +870,22 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_PWM1, // GPIO14 RGB LED Red 0, 0, 0 }, +*/ + { "MagicHome", // Magic Home (aka Flux-light) (ESP8266) and Arilux LC10 (ESP8285) + // https://www.aliexpress.com/item/Magic-Home-Mini-RGB-RGBW-Wifi-Controller-For-Led-Strip-Panel-light-Timing-Function-16million-colors/32686853650.html + 0, + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_LED1_INV, // GPIO02 Blue onboard LED + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_ARIRFRCV, // GPIO04 IR or RF 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 as used on Arilux LC10) + GPIO_PWM1, // GPIO14 RGB LED Red + GPIO_LED2_INV, // GPIO15 RF receiver control + 0, 0 + }, { "Luani HVIO", // ESP8266_HVIO // https://luani.de/projekte/esp8266-hvio/ 0, // GPIO00 Flash jumper From 36d6ae080368aac0987cc8279a365a29ff7a1cb5 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 28 Sep 2018 17:26:13 +0200 Subject: [PATCH 0199/2222] Added D_JSON_UV_INDEX_TEXT Added D_JSON_UV_INDEX_TEXT for more info on json output --- sonoff/i18n.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index c8d3e219f..2090f4793 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -131,6 +131,7 @@ #define D_JSON_UPTIME "Uptime" #define D_JSON_UTC_TIME "UTC" #define D_JSON_UV_INDEX "UvIndex" +#define D_JSON_UV_INDEX_TEXT "UvIndexText" #define D_JSON_UV_LEVEL "UvLevel" #define D_JSON_UV_POWER "UvPower" #define D_JSON_VCC "Vcc" From e8a56755d90226bf6e2f1840657dbcfb9d6106ff Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 28 Sep 2018 17:34:25 +0200 Subject: [PATCH 0200/2222] Updated the driver Updated the driver and changed a lot. - Starting with switch(function) and the end of it. - Changed the json output code a lot to more visibility and a better way of working. - Changed the web sever outout so that we need less code. In #ifdef USE_DOMOTICZ i have changed nothing because i don't have a domotica system. Therefor someone with a stable running system can build it further or we can work together on it. Dirver version changed to v1.0.0.2 Theo, i hope the if (11 == (uptime %100)) { .. part is ok. Please have a look on it. --- sonoff/xsns_11_veml6070.ino | 225 ++++++++++++++++++++---------------- 1 file changed, 123 insertions(+), 102 deletions(-) diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index f60c0f00f..de4d903bd 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -31,6 +31,19 @@ Version Date Action Description -------------------------------------------------------------------------------------------- + 1.0.0.2 20180928 tests - same as in version 1.0.0.1 + cleaned - source code + changed - snprintf_P for json and web server output + - much more compressed and more professional code + added - uv_risk_text to json and web server output + changed - switch (function) to be 100% compatible + - added Veml6070EverySecond in thought of compatibile + added - Veml6070UvTableInit to do this only once to spare time + debugging - @Adrian helped me out in case of a %s%s in mqtt_data. Thank You Adrian + next - possible i will add the calculation for LAT and LONG coordinates for much more precission (TBD) + - show not only the UV Power value in W/m2, possible a @define value to show it as joule value (TBD) + - add a #define to select how many characters are shown benhind the decimal point for the UV Index (TBD) + --- 1.0.0.1 20180925 tests - all tests are done with 1x sonoff sv, 2x Wemos D1 (not the mini) - 3 different VEMl6070 sensors from 3 different online shops - all the last three test where good and all looks working so far @@ -80,7 +93,6 @@ #define VEML6070_ADDR_H 0x39 // on some PCB boards the address can be changed by a solder point, #define VEML6070_ADDR_L 0x38 // to have no address conflicts with other I2C sensors and/or hardware - #define VEML6070_INTEGRATION_TIME 3 // IT_4 = 500msec integration time, because the precission is 4 times higher then IT_0.5 #define VEML6070_ENABLE 1 // #define VEML6070_DISABLE 0 // @@ -94,8 +106,18 @@ /********************************************************************************************/ // globals -uint8_t veml6070_address; -uint8_t veml6070_type = 0; +const char kVemlTypes[] PROGMEM = "VEML6070"; // in preperation of veml6075 +double uv_risk_map[VEML6070_UV_MAX_INDEX] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +double uvrisk = 0; +double uvpower = 0; +uint16_t uvlevel = 0; +uint8_t veml6070_addr_low = VEML6070_ADDR_L; +uint8_t veml6070_addr_high = VEML6070_ADDR_H; +uint8_t itime = VEML6070_INTEGRATION_TIME; +uint8_t veml6070_type = 0; +uint8_t veml6070_valid = 0; +char veml6070_name[9]; +char str_uvrisk_text[10]; /********************************************************************************************/ @@ -104,40 +126,72 @@ void Veml6070Detect(void) if (veml6070_type) { return; } - - uint8_t itime = VEML6070_INTEGRATION_TIME; - veml6070_address = VEML6070_ADDR_L; - Wire.beginTransmission(veml6070_address); + // init the UV sensor + Wire.beginTransmission(VEML6070_ADDR_L); Wire.write((itime << 2) | 0x02); uint8_t status = Wire.endTransmission(); - + // action on status if (!status) { - veml6070_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VEML6070", veml6070_address); + veml6070_type = 1; + uint8_t veml_model = 0; + GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes); + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VEML6070", VEML6070_ADDR_L); AddLog(LOG_LEVEL_DEBUG); } } /********************************************************************************************/ +void Veml6070UvTableInit(void) +{ + // fill the uv-risk compare table once, based on the coefficient calculation + for (uint8_t i = 0; i < VEML6070_UV_MAX_INDEX; i++) { +#ifdef USE_VEML6070_RSET + if ( (USE_VEML6070_RSET >= 220000) && (USE_VEML6070_RSET <= 1000000) ) { + uv_risk_map[i] = ( (USE_VEML6070_RSET / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); + } else { + uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "VEML6070 resistor error %d"), USE_VEML6070_RSET); + AddLog(LOG_LEVEL_DEBUG); + } +#else + uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "VEML6070 resistor default used %d"), VEML6070_RSET_DEFAULT); + AddLog(LOG_LEVEL_DEBUG); +#endif + } +} + +/********************************************************************************************/ + +void Veml6070EverySecond(void) +{ + // all = 10..15[ms] + if (11 == (uptime %100)) { + Veml6070ModeCmd(1); // on = 1[ms], wakeup the UV sensor + Veml6070Detect(); // 1[ms], check for sensor and init with IT time + Veml6070ModeCmd(0); // off = 5[ms], suspend the UV sensor + } else { + Veml6070ModeCmd(1); // 1[ms], wakeup the UV sensor + uvlevel = Veml6070ReadUv(); // 1..2[ms], get UV raw values + uvrisk = Veml6070UvRiskLevel(uvlevel); // 0..1[ms], get UV risk level + uvpower = Veml6070UvPower(uvrisk); // 2[ms], get UV power in W/m2 + Veml6070ModeCmd(0); // off = 5[ms], suspend the UV sensor + } +} + +/********************************************************************************************/ + void Veml6070ModeCmd(boolean mode_cmd) { - uint8_t itime = VEML6070_INTEGRATION_TIME; - uint8_t opmode = 0; - - if (mode_cmd) { - opmode = VEML6070_ENABLE; - } else { - opmode = VEML6070_DISABLE; - } - - veml6070_address = VEML6070_ADDR_L; - Wire.beginTransmission(veml6070_address); - Wire.write((opmode << 0) | 0x02 | (itime << 2)); + // mode_cmd 1 = on = 1[ms] + // mode_cmd 0 = off = 2[ms] + Wire.beginTransmission(VEML6070_ADDR_L); + Wire.write((mode_cmd << 0) | 0x02 | (itime << 2)); uint8_t status = Wire.endTransmission(); - + // action on status if (!status) { - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VEML6070 opmode", veml6070_address); + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VEML6070 mode_cmd", VEML6070_ADDR_L); AddLog(LOG_LEVEL_DEBUG); } } @@ -146,17 +200,20 @@ void Veml6070ModeCmd(boolean mode_cmd) uint16_t Veml6070ReadUv(void) { + uint16_t uv_raw = 0; + // read high byte if (Wire.requestFrom(VEML6070_ADDR_H, 1) != 1) { return -1; } - uint16_t uvi = Wire.read(); - uvi <<= 8; + uv_raw = Wire.read(); + uv_raw <<= 8; + // read low byte if (Wire.requestFrom(VEML6070_ADDR_L, 1) != 1) { return -1; } - uvi |= Wire.read(); - - return uvi; + uv_raw |= Wire.read(); + // high and low done + return uv_raw; } /********************************************************************************************/ @@ -164,28 +221,21 @@ uint16_t Veml6070ReadUv(void) double Veml6070UvRiskLevel(uint16_t uv_level) { double risk = 0; - double uv_risk_map[VEML6070_UV_MAX_INDEX] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - - // fill the uv-risk compare table based on the coefficient calculation - for (uint8_t i = 0; i < VEML6070_UV_MAX_INDEX; i++) { -#ifdef USE_VEML6070_RSET - if ( (USE_VEML6070_RSET >= 220000) && (USE_VEML6070_RSET <= 1000000) ) { - uv_risk_map[i] = ( (USE_VEML6070_RSET / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT) * (i+1); - } else { - uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT) * (i+1); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "VEML6070 resistor error %d"), USE_VEML6070_RSET); - AddLog(LOG_LEVEL_DEBUG); - } -#else - uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT) * (i+1); -#endif - } - - // get the uv-risk level if (uv_level < uv_risk_map[VEML6070_UV_MAX_INDEX-1]) { - return ( uv_level / uv_risk_map[0] ); + risk = (double)uv_level / uv_risk_map[0]; + // generate uv-risk string + if ( (risk >= 0) && (risk <= 2.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_1); } + else if ( (risk >= 3.0) && (risk <= 5.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_2); } + else if ( (risk >= 6.0) && (risk <= 7.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_3); } + else if ( (risk >= 8.0) && (risk <= 10.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_4); } + else if ( (risk >= 11.0) && (risk <= 12.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_5); } + else if ( (risk >= 13.0) && (risk <= 25.0) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_6); } + else { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); } + return risk; } else { - return ( risk = 99 ); // out of range = much to high - it must be outerspace or sensor damaged + // out of range and much to high - it must be outerspace or sensor damaged + snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); + return ( risk = 99 ); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "VEML6070 out of range %d"), risk); AddLog(LOG_LEVEL_DEBUG); } @@ -196,25 +246,21 @@ double Veml6070UvRiskLevel(uint16_t uv_level) double Veml6070UvPower(double uvrisk) { // based on calculations for effective irradiation from Karel Vanicek - return ( VEML6070_POWER_COEFFCIENT * uvrisk ); + double power = 0; + return ( power = VEML6070_POWER_COEFFCIENT * uvrisk ); } /********************************************************************************************/ +// normaly in i18n.h, Line 520 .. 525 #ifdef USE_WEBSERVER // {s} = , {m} = , {e} = #ifdef USE_VEML6070_SHOW_RAW - const char HTTP_SNS_UV_LEVEL[] PROGMEM = "%s{s}VEML6070 " D_UV_LEVEL "{m}%d " D_UNIT_INCREMENTS "{e}"; + const char HTTP_SNS_UV_LEVEL[] PROGMEM = "%s{s}VEML6070 " D_UV_LEVEL "{m}%s " D_UNIT_INCREMENTS "{e}"; #endif // USE_VEML6070_SHOW_RAW // different uv index level texts - const char HTTP_SNS_UV_INDEX1[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_1 "{e}"; - const char HTTP_SNS_UV_INDEX2[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_2 "{e}"; - const char HTTP_SNS_UV_INDEX3[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_3 "{e}"; - const char HTTP_SNS_UV_INDEX4[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_4 "{e}"; - const char HTTP_SNS_UV_INDEX5[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_5 "{e}"; - const char HTTP_SNS_UV_INDEX6[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_6 "{e}"; - const char HTTP_SNS_UV_INDEX7[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX "{m}%s " D_UV_INDEX_7 "{e}"; - const char HTTP_SNS_UV_POWER[] PROGMEM = "%s{s}VEML6070 " D_UV_POWER "{m}%s " D_UNIT_WATT_METER_QUADRAT "{e}"; + const char HTTP_SNS_UV_INDEX[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX " {m}%s %s{e}"; + const char HTTP_SNS_UV_POWER[] PROGMEM = "%s{s}VEML6070 " D_UV_POWER "{m}%s " D_UNIT_WATT_METER_QUADRAT "{e}"; #endif // USE_WEBSERVER /********************************************************************************************/ @@ -222,61 +268,33 @@ double Veml6070UvPower(double uvrisk) void Veml6070Show(boolean json) { if (veml6070_type) { - // wakeup the sensor - Veml6070ModeCmd(1); - - // get values from functions - uint16_t uvlevel = Veml6070ReadUv(); - double uvrisk = Veml6070UvRiskLevel(uvlevel); - double uvpower = Veml6070UvPower(uvrisk); - char str_uvrisk[10]; - char str_uvpower[5]; - + char str_uvlevel[6]; // e.g. 99999 inc = UVLevel + char str_uvrisk[6]; // e.g. 25.99 text = UvIndex + char str_uvpower[6]; // e.g. 0.399 W/m² = UvPower // convert double values to string + dtostrfd((double)uvlevel, 0, str_uvlevel); dtostrfd(uvrisk, 2, str_uvrisk); dtostrfd(uvpower, 3, str_uvpower); - if (json) { #ifdef USE_VEML6070_SHOW_RAW - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"VEML6070\":{\"" D_JSON_UV_LEVEL "\":%d}"), mqtt_data, uvlevel); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":%s,\"" D_JSON_UV_POWER "\":%s}"), + mqtt_data, veml6070_name, str_uvlevel, str_uvrisk, str_uvrisk_text, str_uvpower); +#else + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":%s,\"" D_JSON_UV_POWER "\":%s}"), + mqtt_data, veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); #endif // USE_VEML6070_SHOW_RAW - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"VEML6070\":{\"" D_JSON_UV_INDEX "\":%s}"), mqtt_data, str_uvrisk); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"VEML6070\":{\"" D_JSON_UV_POWER "\":%s}"), mqtt_data, str_uvpower); #ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); }; + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { #ifdef USE_VEML6070_SHOW_RAW - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_LEVEL, mqtt_data, uvlevel); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_LEVEL, mqtt_data, str_uvlevel); #endif // USE_VEML6070_SHOW_RAW - if ( (uvrisk >= 0) && (uvrisk <= 2.9) ) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX1, mqtt_data, str_uvrisk); - } - else if ( (uvrisk >= 3.0) && (uvrisk <= 5.9) ) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX2, mqtt_data, str_uvrisk); - } - else if ( (uvrisk >= 6.0) && (uvrisk <= 7.9) ) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX3, mqtt_data, str_uvrisk); - } - else if ( (uvrisk >= 8.0) && (uvrisk <= 10.9) ) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX4, mqtt_data, str_uvrisk); - } - else if ( (uvrisk >= 11.0) && (uvrisk <= 12.9) ) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX5, mqtt_data, str_uvrisk); - } - else if ( (uvrisk >= 13.0) && (uvrisk <= 15.9) ) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX6, mqtt_data, str_uvrisk); - } else { - // else for Unknown or Out Of Range error = 99 - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX7, mqtt_data, str_uvrisk); - } + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX, mqtt_data, str_uvrisk, str_uvrisk_text); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_POWER, mqtt_data, str_uvpower); #endif // USE_WEBSERVER } - // suspend the sensor - Veml6070ModeCmd(0); - // delay(2000); // used while messaurment of current drain } } @@ -292,8 +310,12 @@ boolean Xsns11(byte function) if (i2c_flg) { switch (function) { - case FUNC_PREP_BEFORE_TELEPERIOD: - Veml6070Detect(); // detect and init the sensor + case FUNC_INIT: + Veml6070Detect(); // 1[ms], detect and init the sensor + Veml6070UvTableInit(); // 1[ms], initalize the UV compare table only once + break; + case FUNC_EVERY_SECOND: + Veml6070EverySecond(); // 10..15[ms], tested with OLED display, do all the actions needed to get all sensor values break; case FUNC_JSON_APPEND: Veml6070Show(1); @@ -310,4 +332,3 @@ boolean Xsns11(byte function) #endif // USE_VEML6070 #endif // USE_I2C - From 41e6939a8150595520261718053eb9b13a96d058 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 28 Sep 2018 17:38:06 +0200 Subject: [PATCH 0201/2222] outline corrections of // comments --- sonoff/xsns_11_veml6070.ino | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index de4d903bd..c06175584 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -133,8 +133,8 @@ void Veml6070Detect(void) // action on status if (!status) { veml6070_type = 1; - uint8_t veml_model = 0; - GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes); + uint8_t veml_model = 0; + GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes); snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VEML6070", VEML6070_ADDR_L); AddLog(LOG_LEVEL_DEBUG); } @@ -168,13 +168,13 @@ void Veml6070EverySecond(void) { // all = 10..15[ms] if (11 == (uptime %100)) { - Veml6070ModeCmd(1); // on = 1[ms], wakeup the UV sensor + Veml6070ModeCmd(1); // on = 1[ms], wakeup the UV sensor Veml6070Detect(); // 1[ms], check for sensor and init with IT time Veml6070ModeCmd(0); // off = 5[ms], suspend the UV sensor } else { - Veml6070ModeCmd(1); // 1[ms], wakeup the UV sensor - uvlevel = Veml6070ReadUv(); // 1..2[ms], get UV raw values - uvrisk = Veml6070UvRiskLevel(uvlevel); // 0..1[ms], get UV risk level + Veml6070ModeCmd(1); // 1[ms], wakeup the UV sensor + uvlevel = Veml6070ReadUv(); // 1..2[ms], get UV raw values + uvrisk = Veml6070UvRiskLevel(uvlevel); // 0..1[ms], get UV risk level uvpower = Veml6070UvPower(uvrisk); // 2[ms], get UV power in W/m2 Veml6070ModeCmd(0); // off = 5[ms], suspend the UV sensor } @@ -312,9 +312,9 @@ boolean Xsns11(byte function) switch (function) { case FUNC_INIT: Veml6070Detect(); // 1[ms], detect and init the sensor - Veml6070UvTableInit(); // 1[ms], initalize the UV compare table only once + Veml6070UvTableInit(); // 1[ms], initalize the UV compare table only once break; - case FUNC_EVERY_SECOND: + case FUNC_EVERY_SECOND: Veml6070EverySecond(); // 10..15[ms], tested with OLED display, do all the actions needed to get all sensor values break; case FUNC_JSON_APPEND: From aa0407493731ed841d9dfe3819247d9052dbb12c Mon Sep 17 00:00:00 2001 From: znanev <20048364+znanev@users.noreply.github.com> Date: Fri, 28 Sep 2018 23:21:17 +0100 Subject: [PATCH 0202/2222] Fix dead links to wiki pages --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 498cd2f80..524ad49ab 100644 --- a/README.md +++ b/README.md @@ -93,8 +93,8 @@ The following devices are supported: - [BlitzWolf BW-SHP2 Smart Socket with Energy Monitoring](https://www.banggood.com/BlitzWolf-BW-SHP2-Smart-WIFI-Socket-EU-Plug-220V-16A-Work-with-Amazon-Alexa-Google-Assistant-p-1292899.html) - [Luani HVIO board](https://luani.de/projekte/esp8266-hvio/) - [Wemos D1 mini](https://wiki.wemos.cc/products:d1:d1_mini) -- [HuaFan Smart Socket](HuaFan-Smart-Socket) -- [Hyleton-313 Smart Plug](Hyleton-313-Smart-Plug) +- [HuaFan Smart Socket](https://github.com/arendst/Sonoff-Tasmota/wiki/HuaFan-Smart-Socket) +- [Hyleton-313 Smart Plug](https://github.com/arendst/Sonoff-Tasmota/wiki/Hyleton-313-Smart-Plug) - [Allterco Shelly 1](https://shelly.cloud/shelly1-open-source/) - [Allterco Shelly 2 with Energy Monitoring](https://shelly.cloud/shelly2/) - NodeMcu and Ledunia From 8255c001b6ac687a6b5007846b194ca708c3fa23 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 29 Sep 2018 10:12:32 +0200 Subject: [PATCH 0203/2222] Use color2 command (HASS sends normalized RGB) --- sonoff/xdrv_12_home_assistant.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index b085947ae..304d5fc2f 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -50,7 +50,7 @@ const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = "\"brightness_value_template\":\"{{value_json." D_CMND_DIMMER "}}\""; const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = - "%s,\"rgb_command_topic\":\"%s\"," // cmnd/led2/Color + "%s,\"rgb_command_topic\":\"%s2\"," // cmnd/led2/Color2 "\"rgb_state_topic\":\"%s\"," // stat/led2/RESULT "\"rgb_value_template\":\"{{value_json." D_CMND_COLOR "}}\""; // "\"rgb_value_template\":\"{{value_json." D_CMND_COLOR " | join(',')}}\""; From 2252be521ab58afed0bd65f0247ed2f3c445b74b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 29 Sep 2018 12:34:24 +0200 Subject: [PATCH 0204/2222] Fix I2CScan invalid JSON Fix I2CScan invalid JSON error message (#3925) --- sonoff/_changelog.ino | 1 + sonoff/sonoff_template.h | 34 ++++++++++++++++------------------ sonoff/support.ino | 24 ++++++++++++++++-------- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index efd0944b7..2cc23ac4a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.2.1.9 20180928 * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251) * Add RF Receiver control to module MagicHome to be used on Arilux LC10 (#3792) + * Fix I2CScan invalid JSON error message (#3925) * * 6.2.1.8 20180926 * Change status JSON message providing more switch and retain information diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index d083675d3..55b1ce3aa 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -855,35 +855,19 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 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, - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_LED1_INV, // GPIO02 Blue onboard LED - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - 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 - }, -*/ { "MagicHome", // Magic Home (aka Flux-light) (ESP8266) and Arilux LC10 (ESP8285) // https://www.aliexpress.com/item/Magic-Home-Mini-RGB-RGBW-Wifi-Controller-For-Led-Strip-Panel-light-Timing-Function-16million-colors/32686853650.html 0, GPIO_USER, // GPIO01 Serial RXD and Optional sensor GPIO_LED1_INV, // GPIO02 Blue onboard LED GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional) + GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional) (Arilux LC10) 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 as used on Arilux LC10) GPIO_PWM1, // GPIO14 RGB LED Red - GPIO_LED2_INV, // GPIO15 RF receiver control + GPIO_LED2_INV, // GPIO15 RF receiver control (Arilux LC10) 0, 0 }, { "Luani HVIO", // ESP8266_HVIO @@ -1089,6 +1073,20 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { /* Optionals + { "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, + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_LED1_INV, // GPIO02 Blue onboard LED + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + 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 + }, { "Arilux LC10", // Arilux LC10 (ESP8285), RGBW + RF // https://github.com/arendst/Sonoff-Tasmota/wiki/MagicHome-with-ESP8285 // https://www.aliexpress.com/item/DC5-24V-Wireless-WIFI-LED-RGB-Controller-RGBW-Controller-IR-RF-Remote-Control-IOS-Android-for/32827253255.html diff --git a/sonoff/support.ino b/sonoff/support.ino index fc73e726e..3665650dd 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1775,27 +1775,35 @@ int8_t I2cWriteBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len void I2cScan(char *devs, unsigned int devs_len) { - byte error; - byte address; + // Return error codes defined in twi.h and core_esp8266_si2c.c + // I2C_OK 0 + // I2C_SCL_HELD_LOW 1 = SCL held low by another device, no procedure available to recover + // I2C_SCL_HELD_LOW_AFTER_READ 2 = I2C bus error. SCL held low beyond slave clock stretch time + // I2C_SDA_HELD_LOW 3 = I2C bus error. SDA line held low by slave/another_master after n bits + // I2C_SDA_HELD_LOW_AFTER_INIT 4 = line busy. SDA again held low by another device. 2nd master? + + byte error = 0; + byte address = 0; byte any = 0; - char tstr[10]; snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_DEVICES_FOUND_AT)); for (address = 1; address <= 127; address++) { Wire.beginTransmission(address); error = Wire.endTransmission(); if (0 == error) { - snprintf_P(tstr, sizeof(tstr), PSTR(" 0x%2x"), address); - strncat(devs, tstr, devs_len); any = 1; + snprintf_P(devs, devs_len, PSTR("%s 0x%02x"), devs, address); } - else if (4 == error) { - snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_UNKNOWN_ERROR_AT " 0x%2x\"}"), address); + else if (error != 2) { // Seems to happen anyway using this scan + any = 2; + snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"Error %d at 0x%02x"), error, address); + break; } } if (any) { strncat(devs, "\"}", devs_len); - } else { + } + else { snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_NO_DEVICES_FOUND "\"}")); } } From 3b3579f1db1c5e06fafa90050e2a3ef63f0b53e5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 29 Sep 2018 13:09:51 +0200 Subject: [PATCH 0205/2222] Fix config crc errors Fix invalid configuration restores and decode_config.py crc error when savedata = 0 (#3918) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_02_webserver.ino | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 2cc23ac4a..0a113a04f 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251) * Add RF Receiver control to module MagicHome to be used on Arilux LC10 (#3792) * Fix I2CScan invalid JSON error message (#3925) + * Fix invalid configuration restores and decode_config.py crc error when savedata = 0 (#3918) * * 6.2.1.8 20180926 * Change status JSON message providing more switch and retain information diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index 5182b7051..6a939dc24 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -1013,6 +1013,10 @@ void HandleBackupConfiguration() WebServer->sendHeader(F("Content-Disposition"), attachment); WebServer->send(200, FPSTR(HDR_CTYPE_STREAM), ""); + + uint16_t cfg_crc = Settings.cfg_crc; + Settings.cfg_crc = GetSettingsCrc(); // Calculate crc (again) as it might be wrong when savedata = 0 (#3918) + memcpy(settings_buffer, &Settings, sizeof(Settings)); if (config_xor_on_set) { for (uint16_t i = 2; i < sizeof(Settings); i++) { @@ -1030,6 +1034,8 @@ void HandleBackupConfiguration() #endif SettingsBufferFree(); + + Settings.cfg_crc = cfg_crc; // Restore crc in case savedata = 0 to make sure settings will be noted as changed } void HandleSaveSettings() From 3997792429d92b24d441911952a93bc51fe51e9c Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Sat, 29 Sep 2018 13:37:42 +0200 Subject: [PATCH 0206/2222] v1.5.0011: 'decode-config.py' fixes & enhancements - add configuration data header to json and binary outputs --add template @v and @f for output filename - add output of crc values on crc error - add '--exit-on-error-only' arg make it possible to process partly valid data - replaced '--sort ' by '--unsort' - changed data size and data crc error into warnings - changed output always in json format - removed arg '--format' (obsolete) - removed collections module (obsolete) v1.5.0010: 'decode-config.py' add more detailed outputs - add bit structure for struct TimeRule, Timer, Mcp230xxCfg - add program return code desc - add error handling for additonal python modules - changed 'Settings' definition to handle array of struct - changed field conversion string to formular evaluation for values - fix and enhance output values --- tools/decode-config.py | 1631 ++++++++++++++++++++++++---------------- 1 file changed, 983 insertions(+), 648 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index dc51e0f42..284904fb9 100644 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -19,23 +19,25 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . + Requirements: - Python - pip install json pycurl urllib2 configargparse + Instructions: - Execute command with option -d to retrieve config data from device or - use -f to read out a previously saved configuration file. + Execute command with option -d to retrieve config data from a host + or use -f to read out a configuration file saved using Tasmota Web-UI For help execute command with argument -h Usage: decode-config.py [-h] [-f ] [-d ] [-u ] - [-p ] [--format ] - [--json-indent ] [--json-compact] - [--sort ] [--raw] [--unhide-pw] [-o ] - [-c ] [-V] + [-p ] [--json-indent ] + [--json-compact] [--unsort] [--raw] [--unhide-pw] + [-o ] [--output-file-format ] + [-c ] [--exit-on-error-only] [-V] Decode configuration of Sonoff-Tasmota device. Args that start with '--' (eg. -f) can also be set in a config file (specified via -c). Config file syntax @@ -48,89 +50,84 @@ Usage: -c , --config Config file, can be used instead of command parameter (default: None) + --exit-on-error-only exit on error only (default: exit on ERROR and + WARNING). Not recommended, used by your own + responsibility! source: -f , --file file to retrieve Tasmota configuration from (default: - None) + None)' -d , --device hostname or IP address to retrieve Tasmota configuration from (default: None) -u , --username - host http access username (default: admin) + host HTTP access username (default: admin) -p , --password - host http access password (default: None) + host HTTP access password (default: None) output: - --format output format ("json" or "text", default: "json") --json-indent pretty-printed JSON output using indent level - (default: "None") + (default: 'None') --json-compact compact JSON output by eliminate whitespace (default: - "not compact") - --sort sort result - can be "none" or "name" (default: - "name") - --raw output raw values (default: processed) + normal) + --unsort do not sort results (default: sort) + --raw output raw values (default: process) --unhide-pw unhide passwords (default: hide) -o , --output-file - file to store decrypted raw binary configuration to - (default: None) + file to store configuration to (default: None) Macros: + @v=Tasmota version, @f=friendly name + --output-file-format + output format ('json' or 'binary', default: 'json') info: -V, --version show program's version number and exit Either argument -d or -f must be given. - -Examples: - Read configuration from hostname 'sonoff1' and output default json config - ./decode-config.py -d sonoff1 - - Read configuration from file 'Config__6.2.1.dmp' and output default json config - ./decode-config.py -f Config__6.2.1.dmp - - Read configuration from hostname 'sonoff1' using web login data - ./decode-config.py -d sonoff1 -u admin -p xxxx - - Read configuration from hostname 'sonoff1' using web login data and unhide passwords - ./decode-config.py -d sonoff1 -u admin -p xxxx --unhide-pw - - Read configuration from hostname 'sonoff1' using web login data, unhide passwords - and sort key names - ./decode-config.py -d sonoff1 -u admin -p xxxx --unhide-pw --sort name """ import os.path import io import sys -import configargparse -import collections import struct import re -import json +import math +from datetime import datetime +try: + import json +except ImportError: + print("module not found. Try 'pip install json' to install it") + sys.exit(9) +try: + import configargparse +except ImportError: + print("module not found. Try 'pip install configargparse' to install it") + sys.exit(9) try: import pycurl except ImportError: - print("module not found. Try 'pip pycurl' to install it") + print("module not found. Try 'pip install pycurl' to install it") sys.exit(9) try: import urllib2 except ImportError: - print("module not found. Try 'pip urllib2' to install it") + print("module not found. Try 'pip install urllib2' to install it") sys.exit(9) -VER = '1.5.0009' +VER = '1.5.0011' PROG='{} v{} by Norbert Richter'.format(os.path.basename(sys.argv[0]),VER) CONFIG_FILE_XOR = 0x5A - args = {} DEFAULTS = { 'DEFAULT': { 'configfile': None, + 'exitonwarning':True, }, 'source': { @@ -141,15 +138,16 @@ DEFAULTS = { }, 'output': { - 'format': 'json', 'jsonindent': None, 'jsoncompact': False, - 'sort': 'name', + 'unsort': False, 'raw': False, 'unhide-pw': False, 'outputfile': None, + 'outputfileformat': 'json', }, } +exitcode = 0 """ @@ -163,11 +161,35 @@ Settings dictionary describes the config file fields definition: format Define the data interpretation. - For details see struct module format string - https://docs.python.org/2.7/library/struct.html#format-strings + It is either a string or a tuple containing a string and a + sub-Settings dictionary. + 'xxx': + A string is used to interpret the data at + The string defines the format interpretion as described + in 'struct module format string', see + https://docs.python.org/2.7/library/struct.html#format-strings + In addition to this format string there is as special + meaning of a dot '.' - this means a bit with an optional + prefix length. If no prefix is given, 1 is assumed. + {}: + A dictionary describes itself a 'Settings' dictonary (recursive) baseaddr - The address (starting from 0) within config data + The address (starting from 0) within config data. + For bit fields must be a tuple. + n: + Defines a simple address within config data. + must be a positive integer. + (n, b, s): + A tuple defines a bit field: + + is the address within config data (integer) + + how many bits are used (positive integer) + + bit shift (integer) + positive shift the result right bits + negative shift the result left bits datadef Define the field interpretation different from simple @@ -182,91 +204,74 @@ Settings dictionary describes the config file fields definition: Defines a one-dimensional array of size [n, n <,n...>] Defines a multi-dimensional array - [{} <,{}...] - Defines a bit struct. The items are simply dict - {'bitname', bitlen}, the dict order is important. convert (optional) Define an output/conversion methode, can be a simple string or a previously defined function name. - 'xxx': - a string defines a format specification of the string - formatter, see - https://docs.python.org/2.7/library/string.html#format-string-syntax + 'xxx?': + a string will be evaluate as is replacing all '?' chars + with the current value. This can also be contain pyhton + code. func: a function defines the name of a formating function """ # config data conversion function and helper -def baudrate(value): - return value * 1200 - def int2ip(value): return '{:d}.{:d}.{:d}.{:d}'.format(value & 0xff, value>>8 & 0xff, value>>16 & 0xff, value>>24 & 0xff) -def int2geo(value): - return float(value) / 1000000 - def password(value): if args.unhidepw: return value return '********' -def fingerprintstr(value): - s = list(value) - result = '' - for c in s: - if c in '0123456789abcdefABCDEF': - result += c - return result - - Setting_6_2_1 = { 'cfg_holder': (' from fielddef[0] """ + return fielddef[0] - length=0 - if fielddef[2] is not None: - # fielddef[2] contains a array or int - # calc size recursive by sum of all elements +def GetFieldBaseAddr(fielddef): + """ + Return the format item of field definition - # tuple 2 contains a list with integer or an integer value - if (isinstance(fielddef[2], list) and len(fielddef[2])>0 and isinstance(fielddef[2][0], int)) or isinstance(fielddef[2], int): - for i in range(0, fielddef[2][0] if isinstance(fielddef[2], list) else fielddef[2] ): - # multidimensional array - if isinstance(fielddef[2], list) and len(fielddef[2])>1: - length += GetFieldLength( (fielddef[0], fielddef[1], fielddef[2][1:]) ) - else: - length += GetFieldLength( (fielddef[0], fielddef[1], None) ) - else: - if fielddef[0][-1:].lower() in ['b','c','?']: - length=1 - elif fielddef[0][-1:].lower() in ['h']: - length=2 - elif fielddef[0][-1:].lower() in ['i','l','f']: - length=4 - elif fielddef[0][-1:].lower() in ['q','d']: - length=8 - elif fielddef[0][-1:].lower() in ['s','p']: - # s and p needs prefix as length - match = re.search("\s*(\d+)", fielddef[0]) - if match: - length=int(match.group(0)) + @param fielddef: + field format - see "Settings dictionary" above + + @return: ,, from fielddef[1] + + """ + baseaddr = fielddef[1] + if isinstance(baseaddr, tuple): + return baseaddr[0], baseaddr[1], baseaddr[2] + + return baseaddr, 0, 0 + + +def MakeFieldBaseAddr(baseaddr, bitlen, bitshift): + """ + Return a based on given arguments + + @param baseaddr: + baseaddr from Settings definition + @param bitlen: + 0 or bitlen + @param bitshift: + 0 or bitshift + + @return: (,,) if bitlen != 0 + baseaddr if bitlen == 0 + + """ + if bitlen!=0: + return (baseaddr, bitlen, bitshift) + return baseaddr - # it's a single value - return length def ConvertFieldValue(value, fielddef, raw=False): """ @@ -1682,21 +1850,94 @@ def ConvertFieldValue(value, fielddef, raw=False): @param value: original value read from binary data @param fielddef - field definition (contains possible conversion defiinition) + field definition - see "Settings dictionary" above @param raw return raw values (True) or converted values (False) @return: (un)converted value """ if not raw and len(fielddef)>3: - if isinstance(fielddef[3],str): # use a format string - return fielddef[3].format(value) - elif callable(fielddef[3]): # use a format function - return fielddef[3](value) + convert = fielddef[3] + if isinstance(convert,str): # evaluate strings + try: + return eval(convert.replace('?','value')) + except: + return value + elif callable(convert): # use as format function + return convert(value) return value -def GetField(dobj, fieldname, fielddef, raw=False): +def GetFieldLength(fielddef): + """ + Return length of a field in bytes based on field format definition + + @param fielddef: + field format - see "Settings dictionary" above + + @return: length of field in bytes + + """ + + length=0 + format_ = GetFieldFormat(fielddef) + + # get datadef from field definition + datadef = None + if len(fielddef)>2: + datadef = fielddef[2] + + if datadef is not None: + # fielddef[2] contains a array or int + # calc size recursive by sum of all elements + + # contains a integer list or an single integer value + if (isinstance(datadef, list) \ + and len(datadef)>0 \ + and isinstance(datadef[0], int)) \ + or isinstance(datadef, int): + + for i in range(0, datadef[0] if isinstance(datadef, list) else datadef ): + + # multidimensional array + if isinstance(datadef, list) and len(datadef)>1: + length += GetFieldLength( (fielddef[0], fielddef[1], fielddef[2][1:]) ) + + # single array + else: + length += GetFieldLength( (fielddef[0], fielddef[1], None) ) + + else: + if isinstance(fielddef[0], dict): + # -> iterate through format_ + addr = -1 + setting = fielddef[0] + for name in setting: + baseaddr, bitlen, bitshift = GetFieldBaseAddr(setting[name]) + len_ = GetFieldLength(setting[name]) + if addr != baseaddr: + addr = baseaddr + length += len_ + + else: + if format_[-1:].lower() in ['b','c','?']: + length=1 + elif format_[-1:].lower() in ['h']: + length=2 + elif format_[-1:].lower() in ['i','l','f']: + length=4 + elif format_[-1:].lower() in ['q','d']: + length=8 + elif format_[-1:].lower() in ['s','p']: + # s and p may have a prefix as length + match = re.search("\s*(\d+)", format_) + if match: + length=int(match.group(0)) + + return length + + +def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): """ Get field value from definition @@ -1714,45 +1955,78 @@ def GetField(dobj, fieldname, fielddef, raw=False): result = None - if fielddef[2] is not None: + # get format from field definition + format_ = GetFieldFormat(fielddef) + + # get baseaddr from field definition + baseaddr, bitlen, bitshift = GetFieldBaseAddr(fielddef) + + # get datadef from field definition + datadef = None + if len(fielddef)>2: + datadef = fielddef[2] + + if datadef is not None: result = [] - # tuple 2 contains a list with integer or an integer value - if (isinstance(fielddef[2], list) and len(fielddef[2])>0 and isinstance(fielddef[2][0], int)) or isinstance(fielddef[2], int): - addr = fielddef[1] - for i in range(0, fielddef[2][0] if isinstance(fielddef[2], list) else fielddef[2] ): + # contains a integer list or an single integer value + if (isinstance(datadef, list) \ + and len(datadef)>0 \ + and isinstance(datadef[0], int)) \ + or isinstance(datadef, int): + + offset = 0 + for i in range(0, datadef[0] if isinstance(datadef, list) else datadef): + # multidimensional array - if isinstance(fielddef[2], list) and len(fielddef[2])>1: - subfielddef = (fielddef[0], addr, fielddef[2][1:], None if len(fielddef)<4 else fielddef[3]) - else: # single array - subfielddef = (fielddef[0], addr, None, None if len(fielddef)<4 else fielddef[3]) + if isinstance(datadef, list) and len(datadef)>1: + if len(fielddef)<4: + subfielddef = (fielddef[0], MakeFieldBaseAddr(baseaddr, bitlen, bitshift), datadef[1:]) + else: + subfielddef = (fielddef[0], MakeFieldBaseAddr(baseaddr, bitlen, bitshift), datadef[1:], fielddef[3]) + + # single array + else: + if len(fielddef)<4: + subfielddef = (fielddef[0], MakeFieldBaseAddr(baseaddr, bitlen, bitshift), None) + else: + subfielddef = (fielddef[0], MakeFieldBaseAddr(baseaddr, bitlen, bitshift), None, fielddef[3]) + length = GetFieldLength(subfielddef) if length != 0: - result.append(GetField(dobj, fieldname, subfielddef, raw)) - addr += length - # tuple 2 contains a list with dict - elif isinstance(fielddef[2], list) and len(fielddef[2])>0 and isinstance(fielddef[2][0], dict): - d = {} - value = struct.unpack_from(fielddef[0], dobj, fielddef[1])[0] - d['base'] = ConvertFieldValue(value, fielddef, raw); - union = fielddef[2] - i = 0 - for l in union: - for name,bits in l.items(): - bitval = (value & ( ((1<> i - d[name] = bitval - i += bits - result = d + result.append(GetField(dobj, fieldname, subfielddef, raw=raw, addroffset=addroffset+offset)) + offset += length + else: - # it's a single value - if GetFieldLength(fielddef) != 0: - result = struct.unpack_from(fielddef[0], dobj, fielddef[1])[0] - if fielddef[0][-1:].lower() in ['s','p']: - if ord(result[:1])==0x00 or ord(result[:1])==0xff: - result = '' - s = str(result).split('\0')[0] - result = unicode(s, errors='replace') - result = ConvertFieldValue(result, fielddef, raw) + # contains a dict + if isinstance(fielddef[0], dict): + # -> iterate through format_ + setting = fielddef[0] + config = {} + for name in setting: + config[name] = GetField(dobj, name, setting[name], raw=args.raw, addroffset=addroffset) + result = config + else: + # a simple value + if GetFieldLength(fielddef) != 0: + result = struct.unpack_from(format_, dobj, baseaddr+addroffset)[0] + + if not format_[-1:].lower() in ['s','p']: + if bitshift>=0: + result >>= bitshift + else: + result <<= abs(bitshift) + if bitlen>0: + result &= (1< 127 + result = unicode(s, errors='ignore') + + result = ConvertFieldValue(result, fielddef, raw) return result @@ -1779,6 +2053,8 @@ def Decode(obj): @param obj: binary config data (decrypted) + + @return: configuration dictionary """ # get header data version = GetField(obj, 'version', Setting_6_2_1['version'], raw=True) @@ -1792,16 +2068,20 @@ def Decode(obj): # if we did not found a mathching setting if template is None: - exit(2, "Can't handle Tasmota configuration data for version 0x{:x}".format(version) ) - + exit(2, "Tasmota configuration version 0x{:x} not supported".format(version) ) + setting = template[2] # check size if exists if 'cfg_size' in setting: cfg_size = GetField(obj, 'cfg_size', setting['cfg_size'], raw=True) - # if we did not found a mathching setting - if cfg_size != template[1]: - exit(2, "Data size does not match. Expected {} bytes, read {} bytes.".format(template[1], cfg_size) ) + # read size should be same as definied in template + if cfg_size > template[1]: + # may be processed + exit(3, "Number of bytes read does ot match - read {}, expected {} byte".format(cfg_size, template[1]), typ='WARNING', doexit=args.exitonwarning) + elif cfg_size < template[1]: + # less number of bytes can not be processed + exit(3, "Number of bytes read to small to process - read {}, expected {} byte".format(cfg_size, template[1]), typ='ERROR') # check crc if exists if 'cfg_crc' in setting: @@ -1809,25 +2089,34 @@ def Decode(obj): else: cfg_crc = GetSettingsCrc(obj) if cfg_crc != GetSettingsCrc(obj): - exit(3, 'Data crc error' ) + exit(4, 'Data CRC error, read 0x{:x} should be 0x{:x}'.format(cfg_crc, GetSettingsCrc(obj)), typ='WARNING', doexit=args.exitonwarning) config = {} - config['version_template'] = '0x{:x}'.format(template[0]) for name in setting: - config[name] = GetField(obj, name, setting[name], args.raw) + config[name] = GetField(obj, name, setting[name], raw=args.raw) - if args.sort == 'name': - config = collections.OrderedDict(sorted(config.items())) - - if args.format == 'json': - print json.dumps(config, sort_keys=args.sort=='name', indent=args.jsonindent, separators=(',', ':') if args.jsoncompact else (', ', ': ') ) - else: - for key,value in config.items(): - print '{} = {}'.format(key, repr(value)) + # add header info + timestamp = datetime.now() + config['header'] = { 'timestamp': timestamp.strftime("%Y-%m-%d %H:%M:%S"), + 'data': { + 'crc': hex(GetSettingsCrc(obj)), + 'size': len(obj), + 'template_version': hex(template[0]), + 'content': { + 'crc': hex(cfg_crc), + 'size': cfg_size, + 'version': hex(version), + }, + }, + 'scriptname': os.path.basename(__file__), + 'scriptversion': VER, + } + return config if __name__ == "__main__": + # program argument processing parser = configargparse.ArgumentParser(description='Decode configuration of Sonoff-Tasmota device.', epilog='Either argument -d or -f must be given.') @@ -1836,80 +2125,89 @@ if __name__ == "__main__": metavar='', dest='tasmotafile', default=DEFAULTS['source']['tasmotafile'], - help='file to retrieve Tasmota configuration from (default: {})'.format(DEFAULTS['source']['tasmotafile'])) + help="file to retrieve Tasmota configuration from (default: {})'".format(DEFAULTS['source']['tasmotafile'])) source.add_argument('-d', '--device', metavar='', dest='device', default=DEFAULTS['source']['device'], - help='hostname or IP address to retrieve Tasmota configuration from (default: {})'.format(DEFAULTS['source']['device']) ) + help="hostname or IP address to retrieve Tasmota configuration from (default: {})".format(DEFAULTS['source']['device']) ) source.add_argument('-u', '--username', metavar='', dest='username', default=DEFAULTS['source']['username'], - help='host http access username (default: {})'.format(DEFAULTS['source']['username'])) + help="host HTTP access username (default: {})".format(DEFAULTS['source']['username'])) source.add_argument('-p', '--password', metavar='', dest='password', default=DEFAULTS['source']['password'], - help='host http access password (default: {})'.format(DEFAULTS['source']['password'])) + help="host HTTP access password (default: {})".format(DEFAULTS['source']['password'])) output = parser.add_argument_group('output') - output.add_argument('--format', - metavar='', - dest='format', - choices=['json', 'text'], - default=DEFAULTS['output']['format'], - help='output format ("json" or "text", default: "{}")'.format(DEFAULTS['output']['format']) ) output.add_argument('--json-indent', metavar='', dest='jsonindent', type=int, default=DEFAULTS['output']['jsonindent'], - help='pretty-printed JSON output using indent level (default: "{}")'.format(DEFAULTS['output']['jsonindent']) ) + help="pretty-printed JSON output using indent level (default: '{}')".format(DEFAULTS['output']['jsonindent']) ) output.add_argument('--json-compact', dest='jsoncompact', action='store_true', default=DEFAULTS['output']['jsoncompact'], - help='compact JSON output by eliminate whitespace (default: "{}")'.format('compact' if DEFAULTS['output']['jsoncompact'] else 'not compact') ) - output.add_argument('--sort', - metavar='', - dest='sort', - choices=['none', 'name'], - default=DEFAULTS['output']['sort'], - help='sort result - can be "none" or "name" (default: "{}")'.format(DEFAULTS['output']['sort']) ) + help="compact JSON output by eliminate whitespace (default: {})".format('normal' if not DEFAULTS['output']['jsoncompact'] else 'compact') ) + output.add_argument('--unsort', + dest='unsort', + action='store_true', + default=DEFAULTS['output']['unsort'], + help="do not sort results (default: {})".format('sort' if not DEFAULTS['output']['unsort'] else 'unsort') ) output.add_argument('--raw', dest='raw', action='store_true', default=DEFAULTS['output']['raw'], - help='output raw values (default: {})'.format('raw' if DEFAULTS['output']['raw'] else 'processed') ) + help="output raw values (default: {})".format('raw' if DEFAULTS['output']['raw'] else 'process') ) output.add_argument('--unhide-pw', dest='unhidepw', action='store_true', default=DEFAULTS['output']['unhide-pw'], - help='unhide passwords (default: {})'.format('unhide' if DEFAULTS['output']['unhide-pw'] else 'hide') ) + help="unhide passwords (default: {})".format('unhide' if DEFAULTS['output']['unhide-pw'] else 'hide') ) output.add_argument('-o', '--output-file', metavar='', dest='outputfile', default=DEFAULTS['output']['outputfile'], - help='file to store decrypted raw binary configuration to (default: {})'.format(DEFAULTS['output']['outputfile'])) + help="file to store configuration to (default: {}) Macros: @v=Tasmota version, @f=friendly name".format(DEFAULTS['output']['outputfile'])) + output.add_argument('--output-file-format', + metavar='', + dest='outputfileformat', + choices=['json', 'binary'], + default=DEFAULTS['output']['outputfileformat'], + help="output format ('json' or 'binary', default: '{}')".format(DEFAULTS['output']['outputfileformat']) ) parser.add_argument('-c', '--config', metavar='', dest='configfile', default=DEFAULTS['DEFAULT']['configfile'], is_config_file=True, - help='Config file, can be used instead of command parameter (default: {})'.format(DEFAULTS['DEFAULT']['configfile']) ) + help="Config file, can be used instead of command parameter (default: {})".format(DEFAULTS['DEFAULT']['configfile']) ) + parser.add_argument('--exit-on-error-only', + dest='exitonwarning', + action='store_false', + default=DEFAULTS['DEFAULT']['exitonwarning'], + help="exit on error only (default: {}). Not recommended, used by your own responsibility!".format('exit on ERROR and WARNING' if DEFAULTS['DEFAULT']['exitonwarning'] else 'exit on ERROR') ) info = parser.add_argument_group('info') info.add_argument('-V', '--version', action='version', version=PROG) args = parser.parse_args() - + + # default no configuration available configobj = None - + + # check source args + if args.device is not None and args.tasmotafile is not None: + exit(6, "Only one source allowed. Do not use -d and -f together") + + # read config direct from device via http if args.device is not None: - # read config direct from device via http buffer = io.BytesIO() url = str("http://{}/dl".format(args.device)) c = pycurl.Curl() @@ -1930,11 +2228,11 @@ if __name__ == "__main__": configobj = buffer.getvalue() + # read config from a file elif args.tasmotafile is not None: - # read config from a file if not os.path.isfile(args.tasmotafile): # check file exists - exit(1, "file '{}' not found".format(args.tasmotafile)) + exit(1, "File '{}' not found".format(args.tasmotafile)) try: tasmotafile = open(args.tasmotafile, "rb") configobj = tasmotafile.read() @@ -1942,22 +2240,59 @@ if __name__ == "__main__": except Exception, e: exit(e[0], e[1]) + # no config source given else: parser.print_help() sys.exit(0) + if configobj is not None and len(configobj)>0: cfg = DeEncrypt(configobj) - if args.outputfile is not None: - outputfile = open(args.outputfile, "wb") - outputfile.write(cfg) - outputfile.close() + config = Decode(cfg) - Decode(cfg) + # output to file + if args.outputfile is not None: + outputfilename = args.outputfile + v = f1 = f2 = f3 = f4 = '' + if 'version' in config: + ver = int(str(config['version']), 0) + major = ((ver>>24) & 0xff) + minor = ((ver>>16) & 0xff) + release = ((ver>> 8) & 0xff) + subrelease = (ver & 0xff) + if major>=6: + if subrelease>0: + subreleasestr = str(subrelease) + else: + subreleasestr = '' + else: + if subrelease>0: + subreleasestr = str(chr(subrelease+ord('a')-1)) + else: + subreleasestr = '' + v = "{:d}.{:d}.{:d}{}{}".format( major, minor, release, '.' if major>=6 else '', subreleasestr) + outputfilename = outputfilename.replace('@v', v) + if 'friendlyname' in config: + outputfilename = outputfilename.replace('@f', config['friendlyname'][0] ) + + if args.outputfileformat == 'binary': + outputfile = open(outputfilename, "wb") + outputfile.write(struct.pack(' Date: Sat, 29 Sep 2018 16:55:53 +0200 Subject: [PATCH 0207/2222] Add basic support for color calibration --- sonoff/i18n.h | 1 + sonoff/settings.h | 4 +++- sonoff/settings.ino | 9 +++++++++ sonoff/sonoff_version.h | 2 +- sonoff/xdrv_04_light.ino | 34 +++++++++++++++++++++++++++++++--- 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 2090f4793..bc161c078 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -317,6 +317,7 @@ #define D_CMND_LEDTABLE "LedTable" #define D_CMND_FADE "Fade" #define D_CMND_PIXELS "Pixels" +#define D_CMND_RGBWWTABLE "RGBWWTable" #define D_CMND_ROTATION "Rotation" #define D_CMND_SCHEME "Scheme" #define D_CMND_SPEED "Speed" diff --git a/sonoff/settings.h b/sonoff/settings.h index bf862dd51..7dfb91089 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -322,7 +322,9 @@ struct SYSCFG { uint16_t mcp230xx_int_timer; // 718 - byte free_71A[174]; // 71A + uint8_t rgbwwTable[5]; // 71A + + byte free_71A[169]; // 71F unsigned long energy_frequency_calibration; // 7C8 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 95e6ce367..4116a1c6d 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -624,6 +624,10 @@ void SettingsDefaultSet2() Settings.button_debounce = KEY_DEBOUNCE_TIME; Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; + + for (byte j = 0; j < 5; j++) { + Settings.rgbwwTable[j] = 255; + } } /********************************************************************************************/ @@ -827,6 +831,11 @@ void SettingsDelta() Settings.button_debounce = KEY_DEBOUNCE_TIME; Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; } + if (Settings.version < 0x0602010A) { + for (byte j = 0; j < 5; j++) { + Settings.rgbwwTable[j] = 255; + } + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 4f2b5c0ec..c5765ec38 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06020109 +#define VERSION 0x0602010A #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 2a5a15b0c..6c8aa938d 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -55,11 +55,11 @@ enum LightCommands { CMND_COLOR, CMND_COLORTEMPERATURE, CMND_DIMMER, CMND_LED, CMND_LEDTABLE, CMND_FADE, - CMND_PIXELS, CMND_ROTATION, CMND_SCHEME, CMND_SPEED, CMND_WAKEUP, CMND_WAKEUPDURATION, + CMND_PIXELS, CMND_RGBWWTABLE, CMND_ROTATION, CMND_SCHEME, CMND_SPEED, CMND_WAKEUP, CMND_WAKEUPDURATION, CMND_WIDTH, CMND_CHANNEL, CMND_HSBCOLOR, 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_ROTATION "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" + D_CMND_PIXELS "|" D_CMND_RGBWWTABLE "|" D_CMND_ROTATION "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" D_CMND_WIDTH "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ; struct LRgbColor { @@ -799,7 +799,8 @@ void LightAnimate() 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]; + cur_col[i] = light_last_color[i]*Settings.rgbwwTable[i]/255; + cur_col[i] = (Settings.light_correction) ? ledTable[cur_col[i]] : cur_col[i]; if (light_type < LT_PWM6) { if (pin[GPIO_PWM1 +i] < 99) { if (cur_col[i] > 0xFC) { @@ -1279,6 +1280,33 @@ boolean LightCommand() } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.light_correction)); } + else if (CMND_RGBWWTABLE == command_code) { + bool validtable = (XdrvMailbox.data_len > 0); + char scolor[25]; + if (validtable) { + uint16_t HSB[3]; + if (strstr(XdrvMailbox.data, ",")) { // Command with up to 5 comma separated parameters + for (int i = 0; i < LST_RGBWC; i++) { + char *substr; + + if (0 == i) { + substr = strtok(XdrvMailbox.data, ","); + } else { + substr = strtok(NULL, ","); + } + if (substr != NULL) { + Settings.rgbwwTable[i] = atoi(substr); + } + } + } + light_update = 1; + } + scolor[0] = '\0'; + for (byte i = 0; i < LST_RGBWC; i++) { + snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor); + } else if (CMND_FADE == command_code) { switch (XdrvMailbox.payload) { case 0: // Off From cdc8a4d9ebc6043db47aaf7f79a5f8132ad68350 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Sep 2018 10:54:52 +0200 Subject: [PATCH 0208/2222] tiny change --- sonoff/settings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 7dfb91089..978b72b24 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -324,7 +324,7 @@ struct SYSCFG { uint8_t rgbwwTable[5]; // 71A - byte free_71A[169]; // 71F + byte free_71F[169]; // 71F unsigned long energy_frequency_calibration; // 7C8 From 6a1a21f03a1d9fcaab3bfe81162a8eb1b575c778 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Sep 2018 11:02:47 +0200 Subject: [PATCH 0209/2222] 6.2.1.10 Add RGBWWTable 6.2.1.10 20180930 * Add command RGBWWTable to support color calibration (#3933) --- sonoff/_changelog.ino | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0a113a04f..d4c609f14 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,8 +1,11 @@ -/* 6.2.1.9 20180928 +/* 6.2.1.10 20180930 + * Add command RGBWWTable to support color calibration (#3933) + * + * 6.2.1.9 20180928 * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251) * Add RF Receiver control to module MagicHome to be used on Arilux LC10 (#3792) * Fix I2CScan invalid JSON error message (#3925) - * Fix invalid configuration restores and decode_config.py crc error when savedata = 0 (#3918) + * Fix invalid configuration restores and decode_config.py crc error when savedata = 0 (#3918) * * 6.2.1.8 20180926 * Change status JSON message providing more switch and retain information From 2fd42446e99b0582545521f875f044ad6345f435 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Sep 2018 14:33:26 +0200 Subject: [PATCH 0210/2222] Add ESP Switch support Add support for Michael Haustein ESP Switch --- sonoff/_changelog.ino | 3 ++- sonoff/sonoff_template.h | 43 +++++++++++++++++++++++++++++----------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index d4c609f14..20cbded76 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.2.1.10 20180930 * Add command RGBWWTable to support color calibration (#3933) - * + * Add support for Michael Haustein ESP Switch + * * 6.2.1.9 20180928 * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251) * Add RF Receiver control to module MagicHome to be used on Arilux LC10 (#3792) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 55b1ce3aa..e51e918fe 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -232,6 +232,7 @@ enum SupportedModules { SHELLY2, PHILIPS, NEO_COOLCAM, + ESP_SWITCH, MAXMODULE }; /********************************************************************************************/ @@ -392,6 +393,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { SHELLY2, BLITZWOLF_BWSHP2, NEO_COOLCAM, + ESP_SWITCH, H801, MAGICHOME, ARILUX_LC01, @@ -598,21 +600,22 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1, // GPIO16 Green/Blue Led (1 = On, 0 = Off) GPIO_ADC0 // ADC0 A0 Analog input }, - { "EXS Relay", // Latching relay (ESP8266) + { "EXS Relay(s)", // ES-Store Latching relay(s) (ESP8266) // https://ex-store.de/ESP8266-WiFi-Relay-V31 - // Module Pin 1 VCC 3V3, Module Pin 6 GND - GPIO_KEY1, // GPIO00 Module Pin 8 - Button (firmware flash) - GPIO_USER, // GPIO01 Module Pin 2 = UART0_TXD - GPIO_USER, // GPIO02 Module Pin 7 - GPIO_USER, // GPIO03 Module Pin 3 = UART0_RXD - GPIO_USER, // GPIO04 Module Pin 10 - GPIO_USER, // GPIO05 Module Pin 9 + // V3.1 Module Pin 1 VCC 3V3, Module Pin 6 GND + // https://ex-store.de/2-Kanal-WiFi-WLan-Relay-V5-Blackline-fuer-Unterputzmontage + GPIO_USER, // GPIO00 V3.1 Module Pin 8 - V5.0 Module Pin 4 + GPIO_USER, // GPIO01 UART0_TXD V3.1 Module Pin 2 - V5.0 Module Pin 3 + GPIO_USER, // GPIO02 V3.1 Module Pin 7 + GPIO_USER, // GPIO03 UART0_RXD V3.1 Module Pin 3 + GPIO_USER, // GPIO04 V3.1 Module Pin 10 - V5.0 Module Pin 2 + GPIO_USER, // GPIO05 V3.1 Module Pin 9 - V5.0 Module Pin 1 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Relay1 ( 1 = Off) GPIO_REL2, // GPIO13 Relay1 ( 1 = On) - GPIO_USER, // GPIO14 Module Pin 5 - 0, - GPIO_USER, // GPIO16 Module Pin 4 + GPIO_USER, // GPIO14 V3.1 Module Pin 5 - V5.0 Relay2 ( 1 = Off) + GPIO_LED1, // GPIO15 V5.0 LED1 + GPIO_USER, // GPIO16 V3.1 Module Pin 4 - V5.0 Relay2 ( 1 = On) 0 }, { "WiOn", // Indoor Tap (ESP8266) @@ -1061,12 +1064,28 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "Neo Coolcam", // Neo Coolcam (ESP8266) // https://www.banggood.com/NEO-COOLCAM-WiFi-Mini-Smart-Plug-APP-Remote-Control-Timing-Smart-Socket-EU-Plug-p-1288562.html?cur_warehouse=CN 0, 0, 0, 0, - GPIO_LED1_INV, // GPIO13 Red Led (0 = On, 1 = Off) + GPIO_LED1_INV, // GPIO04 Red Led (0 = On, 1 = Off) 0, 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_KEY1, // GPIO13 Button 0, 0, 0, 0 + }, + { "ESP Switch", // Michael Haustein 4 channel wall switch (ESP07 = ESP8266) + // Use rules for further actions like - rule on power1#state do publish cmnd/other_device/power %value% endon + GPIO_KEY2, // GPIO00 Button 2 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_REL3_INV, // GPIO02 Yellow Led 3 (0 = On, 1 = Off) + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_KEY1, // GPIO04 Button 1 + GPIO_REL2_INV, // GPIO05 Red Led 2 (0 = On, 1 = Off) + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_REL4_INV, // GPIO12 Blue Led 4 (0 = On, 1 = Off) + GPIO_KEY4, // GPIO13 Button 4 + GPIO_KEY3, // GPIO14 Button 3 + GPIO_LED1, // GPIO15 Optional sensor + GPIO_REL1_INV, // GPIO16 Green Led 1 (0 = On, 1 = Off) + 0 } }; From 191df17b13fa4e3c1204421d68060c8bca4f61b6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Sep 2018 16:52:25 +0200 Subject: [PATCH 0211/2222] Add support for EXS Relay V5.0 Add support for EXS Relay V5.0 (#3810) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 35 +++++++++++++++++++---------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 20cbded76..da3db4570 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.2.1.10 20180930 * Add command RGBWWTable to support color calibration (#3933) * Add support for Michael Haustein ESP Switch + * Add support for EXS Relay V5.0 (#3810) * * 6.2.1.9 20180928 * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 6b354bb24..b89ffe138 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -296,20 +296,23 @@ char* GetStateText(byte state) /********************************************************************************************/ -void SetLatchingRelay(power_t power, uint8_t state) +void SetLatchingRelay(power_t lpower, uint8_t state) { - power &= 1; - if (2 == state) { // Reset relay - state = 0; - latching_power = power; - latching_relay_pulse = 0; + // power xx00 - toggle REL1 (Off) and REL3 (Off) - device 1 Off, device 2 Off + // power xx01 - toggle REL2 (On) and REL3 (Off) - device 1 On, device 2 Off + // power xx10 - toggle REL1 (Off) and REL4 (On) - device 1 Off, device 2 On + // power xx11 - toggle REL2 (On) and REL4 (On) - device 1 On, device 2 On + + if (state && !latching_relay_pulse) { // Set latching relay to power if previous pulse has finished + latching_power = lpower; + latching_relay_pulse = 2; // max 200mS (initiated by stateloop()) } - else if (state && !latching_relay_pulse) { // Set port power to On - latching_power = power; - latching_relay_pulse = 2; // max 200mS (initiated by stateloop()) - } - if (pin[GPIO_REL1 +latching_power] < 99) { - digitalWrite(pin[GPIO_REL1 +latching_power], bitRead(rel_inverted, latching_power) ? !state : state); + + for (byte i = 0; i < devices_present; i++) { + uint8_t port = (i << 1) + ((latching_power >> i) &1); + if (pin[GPIO_REL1 +port] < 99) { + digitalWrite(pin[GPIO_REL1 +port], bitRead(rel_inverted, port) ? !state : state); + } } } @@ -2453,6 +2456,10 @@ void GpioInit() if (pin[GPIO_REL1 +i] < 99) { pinMode(pin[GPIO_REL1 +i], OUTPUT); devices_present++; + if (EXS_RELAY == Settings.module) { + digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? 1 : 0); + if (i &1) { devices_present--; } + } } } } @@ -2493,10 +2500,6 @@ void GpioInit() } } - if (EXS_RELAY == Settings.module) { - SetLatchingRelay(0,2); - SetLatchingRelay(1,2); - } SetLedPower(Settings.ledstate &8); XdrvCall(FUNC_PRE_INIT); From b9b6d132f53753987ef8a86e28aa104f03844512 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Sep 2018 17:52:41 +0200 Subject: [PATCH 0212/2222] Fix timer offset -00:00 Fix timer offset -00:00 causing 12:00 hour offset (#3923) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_09_timers.ino | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index da3db4570..21e00702e 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Add command RGBWWTable to support color calibration (#3933) * Add support for Michael Haustein ESP Switch * Add support for EXS Relay V5.0 (#3810) + * Fix timer offset -00:00 causing 12:00 hour offset (#3923) * * 6.2.1.9 20180928 * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251) diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 66bf93614..124b41534 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -194,7 +194,7 @@ void ApplyTimerOffsets(Timer *duskdawn) // apply offsets, check for over- and underflows uint16_t timeBuffer; - if ((uint16_t)stored.time > 720) { + if ((uint16_t)stored.time > 719) { // negative offset, time after 12:00 timeBuffer = (uint16_t)stored.time - 720; // check for underflow From 89825907d05b8e3816f22ad1194734b8bc9327da Mon Sep 17 00:00:00 2001 From: Florian Schroen Date: Sun, 30 Sep 2018 18:38:01 +0200 Subject: [PATCH 0213/2222] Add support for OBI smart socket Model tested: WFG-1 Models maybe working: WFF-1, WFE-1, WFI-1, WFD-1, WFR-1, WFA-1, WFU-1 Manufactured by: Cixi Yidong Electronics Co. Ltd - http://www.cn-yidong.com/ Sold by: OBI DIY market in Germany - https://www.obi.de/ --- sonoff/sonoff_template.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index e51e918fe..0a4f98d35 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -233,6 +233,7 @@ enum SupportedModules { PHILIPS, NEO_COOLCAM, ESP_SWITCH, + OBI, MAXMODULE }; /********************************************************************************************/ @@ -394,6 +395,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { BLITZWOLF_BWSHP2, NEO_COOLCAM, ESP_SWITCH, + OBI, H801, MAGICHOME, ARILUX_LC01, @@ -1085,7 +1087,21 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY3, // GPIO14 Button 3 GPIO_LED1, // GPIO15 Optional sensor GPIO_REL1_INV, // GPIO16 Green Led 1 (0 = On, 1 = Off) - 0 + }, + { "OBI Socket", // OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko/p/2291706 + 0, // GPIO00 Flash jumper - not available + 0, // GPIO01 + 0, // GPIO02 + 0, // GPIO03 + GPIO_LED1, // GPIO04 LED on top and in switch button + GPIO_REL1, // GPIO05 Relay 1 (0 = Off, 1 = On) + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_LED2, // GPIO12 + 0, // GPIO13 + GPIO_KEY1, // GPIO14 switch button + 0, // GPIO15 + 0, // GPIO16 + 0 // GPIO17 } }; From ee0ef227dcf6830ae5c4a53ed7bb95f5b29d3aee Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 30 Sep 2018 23:07:46 +0200 Subject: [PATCH 0214/2222] Add ability to set default PWM Freq using #define #define USE_PCA9685_FREQ --- sonoff/user_config.h | 1 + sonoff/xdrv_15_pca9685.ino | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/sonoff/user_config.h b/sonoff/user_config.h index eceadc68d..72aa97d53 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -302,6 +302,7 @@ // #define USE_MCP230xx_DISPLAYOUTPUT // Enable MCP23008/MCP23017 to display state of OUTPUT pins on Web UI (+0k2 code) // #define USE_PCA9685 // Enable PCA9685 I2C HW PWM Driver - Must define I2C Address in #define USE_PCA9685_ADDR below - range 0x40 - 0x47 (+1k4 code) // #define USE_PCA9685_ADDR 0x40 // Enable PCA9685 I2C Address to use (Must be within range 0x40 through 0x47 - set according to your wired setup) +// #define USE_PCA9685_FREQ 50 // Define default PWM frequency in Hz to be used (must be within 24 to 1526) - If other value is used, it will rever to 50Hz // #define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code) // #define USE_CCS811 // Enable CCS811 sensor (I2C address 0x5A) (+2k2 code) // #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index e53b8d17f..c17ec3bee 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -27,7 +27,7 @@ #define PCA9685_REG_PRE_SCALE 0xFE uint8_t pca9685_detected = 0; -uint16_t pca9685_freq = 50; +uint16_t pca9685_freq = USE_PCA9685_FREQ; void PCA9685_Detect(void) { @@ -51,7 +51,7 @@ void PCA9685_Detect(void) void PCA9685_Reset(void) { I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x80); - PCA9685_SetPWMfreq(50); + PCA9685_SetPWMfreq(USE_PCA9685_FREQ); for (uint8_t pin=0;pin<16;pin++) { PCA9685_SetPWM(pin,0,false); } @@ -63,9 +63,13 @@ void PCA9685_SetPWMfreq(double freq) { 7.3.5 from datasheet prescale value = round(25000000/(4096*freq))-1; */ - pca9685_freq=freq; - uint8_t pre_scale_osc = round(25000000/(4096*freq))-1; - if (1526 == freq) pre_scale_osc=0xFF; // force setting for 24hz because rounding causes 1526 to be 254 + if (freq > 23 && freq < 1527) { + pca9685_freq=freq; + } else { + pca9685_freq=50; + } + uint8_t pre_scale_osc = round(25000000/(4096*pca9685_freq))-1; + if (1526 == pca9685_freq) pre_scale_osc=0xFF; // force setting for 24hz because rounding causes 1526 to be 254 uint8_t current_mode1 = I2cRead8(USE_PCA9685_ADDR, PCA9685_REG_MODE1); // read current value of MODE1 register uint8_t sleep_mode1 = (current_mode1&0x7F) | 0x10; // Determine register value to put PCA to sleep I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, sleep_mode1); // Let's sleep a little From 068211cae9857bb93373690772f35b33b3f48c4d Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 30 Sep 2018 23:33:14 +0200 Subject: [PATCH 0215/2222] Add #define USE_PCA9685_FREQ 50 if not defined Add #define USE_PCA9685_FREQ 50 if not defined in user_config.h --- sonoff/xdrv_15_pca9685.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index c17ec3bee..3114aa461 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -26,6 +26,10 @@ #define PCA9685_REG_LED0_ON_L 0x06 #define PCA9685_REG_PRE_SCALE 0xFE +#ifndef USE_PCA9685_FREQ + #define USE_PCA9685_FREQ 50 +#endif + uint8_t pca9685_detected = 0; uint16_t pca9685_freq = USE_PCA9685_FREQ; From da0b283fe7249e8b3b1c46f8808bb9a7251ff14f Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 1 Oct 2018 00:18:37 +0200 Subject: [PATCH 0216/2222] PCA9685 - Add telemetry output --- sonoff/xdrv_15_pca9685.ino | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index 3114aa461..841ae22ab 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -32,6 +32,7 @@ uint8_t pca9685_detected = 0; uint16_t pca9685_freq = USE_PCA9685_FREQ; +uint16_t pca9685_pin_pwm_value[16]; void PCA9685_Detect(void) { @@ -57,7 +58,8 @@ void PCA9685_Reset(void) I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x80); PCA9685_SetPWMfreq(USE_PCA9685_FREQ); for (uint8_t pin=0;pin<16;pin++) { - PCA9685_SetPWM(pin,0,false); + PCA9685_SetPWM(pin,0,false); + pca9685_pin_pwm_value[pin] = 0; } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); } @@ -115,6 +117,7 @@ bool PCA9685_Command(void) if (',' == XdrvMailbox.data[ca]) { paramcount++; } } UpperCase(XdrvMailbox.data,XdrvMailbox.data); + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"RESET")) { PCA9685_Reset(); return serviced; } if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"PWMF")) { @@ -122,7 +125,7 @@ bool PCA9685_Command(void) uint16_t new_freq = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); if ((new_freq >= 24) && (new_freq <= 1526)) { PCA9685_SetPWMfreq(new_freq); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}")); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}"),new_freq); return serviced; } } else { // No parameter was given for setfreq, so we return current setting @@ -159,6 +162,17 @@ bool PCA9685_Command(void) return serviced; } +void PCA9685_OutputTelemetry(void) { + if (0 == pca9685_detected) { return; } // We do not do this if the PCA9685 has not been detected + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"PCA9685\": {"), GetDateAndTime(DT_LOCAL).c_str()); + snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"PWM_FREQ\":%i,"),mqtt_data,pca9685_freq); + for (uint8_t pin=0;pin<16;pin++) { + snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"PWM%i\":%i,"),mqtt_data,pin,pca9685_pin_pwm_value[pin]); + } + snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"END\":1}}"),mqtt_data); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +} + boolean Xdrv15(byte function) { boolean result = false; @@ -169,6 +183,9 @@ boolean Xdrv15(byte function) break; case FUNC_EVERY_SECOND: PCA9685_Detect(); + if (tele_period == 0) { + PCA9685_OutputTelemetry(); + } break; case FUNC_EVERY_50_MSECOND: break; From 047f430ad8c8ae65e8a376928b7792a88074810e Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 1 Oct 2018 00:27:16 +0200 Subject: [PATCH 0217/2222] PCA9685 - Remove unused callbacks in Xdrv15() --- sonoff/xdrv_15_pca9685.ino | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index 841ae22ab..9cb9292a0 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -179,25 +179,17 @@ boolean Xdrv15(byte function) if (i2c_flg) { switch (function) { - case FUNC_MQTT_DATA: - break; case FUNC_EVERY_SECOND: PCA9685_Detect(); if (tele_period == 0) { PCA9685_OutputTelemetry(); } break; - case FUNC_EVERY_50_MSECOND: - break; - case FUNC_JSON_APPEND: - break; case FUNC_COMMAND: if (XDRV_15 == XdrvMailbox.index) { PCA9685_Command(); } break; - case FUNC_WEB_APPEND: - break; default: break; } From 9e5aaef51f9cdf2cca08bd23e08aead10c03c7d9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 1 Oct 2018 12:19:58 +0200 Subject: [PATCH 0218/2222] Add OBI/Teckin Socket support * Add support for OBI Power Socket (#1988, #3944) * Add support for Teckin Power Socket with Energy Monitoring (#3950) --- sonoff/_changelog.ino | 2 ++ sonoff/sonoff_template.h | 66 +++++++++++++++++++++++----------------- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 21e00702e..04f209e10 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,8 @@ * Add support for Michael Haustein ESP Switch * Add support for EXS Relay V5.0 (#3810) * Fix timer offset -00:00 causing 12:00 hour offset (#3923) + * Add support for OBI Power Socket (#1988, #3944) + * Add support for Teckin Power Socket with Energy Monitoring (#3950) * * 6.2.1.9 20180928 * Add Apparent Power and Reactive Power to Energy Monitoring devices (#251) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 0a4f98d35..aad498f3b 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -234,6 +234,7 @@ enum SupportedModules { NEO_COOLCAM, ESP_SWITCH, OBI, + TECKIN, MAXMODULE }; /********************************************************************************************/ @@ -357,31 +358,31 @@ const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = { }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { - SONOFF_BASIC, + SONOFF_BASIC, // Sonoff Relay Devices SONOFF_RF, SONOFF_TH, SONOFF_DUAL, SONOFF_DUAL_R2, SONOFF_POW, SONOFF_POW_R2, - SONOFF_S31, SONOFF_4CH, SONOFF_4CHPRO, - SONOFF_SV, - SONOFF_DEV, - SONOFF_S2X, - SLAMPHER, - SONOFF_TOUCH, + SONOFF_S31, // Sonoff Socket Relay Devices with Energy Monitoring + SONOFF_S2X, // Sonoff Socket Relay Devices + SONOFF_TOUCH, // Sonoff Switch Devices SONOFF_T11, SONOFF_T12, SONOFF_T13, - SONOFF_SC, - SONOFF_B1, - SONOFF_LED, + SONOFF_LED, // Sonoff Light Devices SONOFF_BN, - SONOFF_IFAN02, - SONOFF_BRIDGE, - CH1, + SONOFF_B1, // Sonoff Light Bulbs + SLAMPHER, + SONOFF_SC, // Sonoff Environmemtal Sensor + SONOFF_IFAN02, // Sonoff Fan + SONOFF_BRIDGE, // Sonoff Bridge + SONOFF_SV, // Sonoff Development Devices + SONOFF_DEV, + CH1, // Relay Devices CH4, MOTOR, ELECTRODRAGON, @@ -392,11 +393,12 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { WION, SHELLY1, SHELLY2, - BLITZWOLF_BWSHP2, - NEO_COOLCAM, - ESP_SWITCH, + BLITZWOLF_BWSHP2, // Socket Relay Devices with Energy Monitoring + TECKIN, + NEO_COOLCAM, // Socket Relay Devices OBI, - H801, + ESP_SWITCH, // Switch Devices + H801, // Light Devices MAGICHOME, ARILUX_LC01, ARILUX_LC06, @@ -404,9 +406,9 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { ZENGGE_ZF_WF017, HUAFAN_SS, KMC_70011, - AILIGHT, + AILIGHT, // Light Bulbs PHILIPS, - WITTY, + WITTY, // Development Devices WEMOS }; @@ -615,9 +617,9 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Relay1 ( 1 = Off) GPIO_REL2, // GPIO13 Relay1 ( 1 = On) - GPIO_USER, // GPIO14 V3.1 Module Pin 5 - V5.0 Relay2 ( 1 = Off) + GPIO_USER, // GPIO14 V3.1 Module Pin 5 - V5.0 GPIO_REL3_INV Relay2 ( 1 = Off) GPIO_LED1, // GPIO15 V5.0 LED1 - GPIO_USER, // GPIO16 V3.1 Module Pin 4 - V5.0 Relay2 ( 1 = On) + GPIO_USER, // GPIO16 V3.1 Module Pin 4 - V5.0 GPIO_REL4_INV Relay2 ( 1 = On) 0 }, { "WiOn", // Indoor Tap (ESP8266) @@ -1089,19 +1091,27 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL1_INV, // GPIO16 Green Led 1 (0 = On, 1 = Off) }, { "OBI Socket", // OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko/p/2291706 - 0, // GPIO00 Flash jumper - not available - 0, // GPIO01 - 0, // GPIO02 - 0, // GPIO03 + 0, 0, 0, 0, GPIO_LED1, // GPIO04 LED on top and in switch button GPIO_REL1, // GPIO05 Relay 1 (0 = Off, 1 = On) 0, 0, 0, 0, 0, 0, // Flash connection GPIO_LED2, // GPIO12 0, // GPIO13 GPIO_KEY1, // GPIO14 switch button - 0, // GPIO15 - 0, // GPIO16 - 0 // GPIO17 + 0, 0, 0 + }, + { "Teckin", // https://www.amazon.de/gp/product/B07D5V139R + 0, + GPIO_KEY1, // GPIO01 Serial TXD and Button + 0, + GPIO_LED2_INV, // GPIO03 Serial RXD and Red Led (0 = On, 1 = Off) + GPIO_HLW_CF, // GPIO04 BL0937 or HJL-01 CF power + GPIO_HLW_CF1, // GPIO05 BL0937 or HJL-01 CF1 voltage / current + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_HLW_SEL, // GPIO12 BL0937 or HJL-01 Sel output + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) + GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) + 0, 0, 0 } }; From 13d37a144aa83a6f8f2114b80f490bcb823707f7 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 1 Oct 2018 18:06:25 +0200 Subject: [PATCH 0219/2222] Fixed wrong sensor name Fixed a wrong sensor name in line 23. It's not the SPG30, it's the CSS811 --- sonoff/xsns_31_ccs811.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index 482572cdb..d57c9cb06 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -20,7 +20,7 @@ #ifdef USE_I2C #ifdef USE_CCS811 /*********************************************************************************************\ - * SGP30 - Gas (TVOC - Total Volatile Organic Compounds) and Air Quality (CO2) + * CCS811 - Gas (TVOC - Total Volatile Organic Compounds) and Air Quality (CO2) * * Source: Adafruit * From bcc9432214961fdd8dd4f8ab6daa44f6516bd6cb Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 1 Oct 2018 13:13:47 -0300 Subject: [PATCH 0220/2222] Added Dimmer Trigger for Rules For example rule on Dimmer#state<30 do ... endon rule on Dimmer#boot<10 do ... endon --- sonoff/xdrv_10_rules.ino | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index b13dfc771..54fcb3f08 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -83,6 +83,7 @@ unsigned long rules_timer[MAX_RULE_TIMERS] = { 0 }; uint8_t rules_quota = 0; long rules_new_power = -1; long rules_old_power = -1; +long rules_old_dimm = -1; uint32_t rules_triggers[MAX_RULE_SETS] = { 0 }; uint16_t rules_last_minute = 60; @@ -398,6 +399,16 @@ void RulesEvery50ms() } rules_old_power = rules_new_power; } + else if (rules_old_dimm != Settings.light_dimmer) { + if (rules_old_dimm != -1) { + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Dimmer\":{\"State\":%d}}"), Settings.light_dimmer); + } else { + // Boot time DIMMER VALUE + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Dimmer\":{\"Boot\":%d}}"), Settings.light_dimmer); + } + RulesProcessEvent(json_event); + rules_old_dimm = Settings.light_dimmer; + } else if (event_data[0]) { char *event; char *parameter; From 2f85a4728b238fcc548d393ce04eb2c7aa8314f4 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 1 Oct 2018 19:32:55 +0200 Subject: [PATCH 0221/2222] PCA9685 - bugfix for telemetry + status command --- sonoff/xdrv_15_pca9685.ino | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index 9cb9292a0..b29e85a5b 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -98,6 +98,7 @@ void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted) { } else { PCA9685_SetPWM_Reg(pin, 0, pwm); } + pca9685_pin_pwm_value[pin] = pwm; } bool PCA9685_Command(void) @@ -120,6 +121,8 @@ bool PCA9685_Command(void) if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"RESET")) { PCA9685_Reset(); return serviced; } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"STATUS")) { PCA9685_OutputTelemetry(false); return serviced; } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"PWMF")) { if (paramcount > 1) { uint16_t new_freq = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); @@ -162,7 +165,7 @@ bool PCA9685_Command(void) return serviced; } -void PCA9685_OutputTelemetry(void) { +void PCA9685_OutputTelemetry(bool telemetry) { if (0 == pca9685_detected) { return; } // We do not do this if the PCA9685 has not been detected snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"PCA9685\": {"), GetDateAndTime(DT_LOCAL).c_str()); snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"PWM_FREQ\":%i,"),mqtt_data,pca9685_freq); @@ -170,7 +173,9 @@ void PCA9685_OutputTelemetry(void) { snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"PWM%i\":%i,"),mqtt_data,pin,pca9685_pin_pwm_value[pin]); } snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"END\":1}}"),mqtt_data); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + if (telemetry) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + } } boolean Xdrv15(byte function) @@ -182,7 +187,7 @@ boolean Xdrv15(byte function) case FUNC_EVERY_SECOND: PCA9685_Detect(); if (tele_period == 0) { - PCA9685_OutputTelemetry(); + PCA9685_OutputTelemetry(true); } break; case FUNC_COMMAND: From 3280c7d177f07282ecd72b9aa881325136b55569 Mon Sep 17 00:00:00 2001 From: "Christian W. Zuckschwerdt" Date: Mon, 1 Oct 2018 14:28:21 +0000 Subject: [PATCH 0222/2222] Add W1_PARASITE_POWER optimization for DS18X20 --- sonoff/user_config.h | 1 + sonoff/xsns_05_ds18x20.ino | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 72aa97d53..ee77854bc 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -271,6 +271,7 @@ // -- One wire sensors ---------------------------- // WARNING: Select none for default one DS18B20 sensor or enable one of the following two options for multiple sensors #define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) +//#define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors //#define USE_DS18x20_LEGACY // Optional for more than one DS18x20 sensors with dynamic scan using library OneWire (+1k5 code) // -- I2C sensors --------------------------------- diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index 869deac8e..474f26e2e 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -49,6 +49,10 @@ struct DS18X20STRUCT { uint8_t ds18x20_sensors = 0; uint8_t ds18x20_pin = 0; char ds18x20_types[12]; +#ifdef W1_PARASITE_POWER +uint8_t ds18x20_sensor_curr = 0; +unsigned long w1_power_until = 0; +#endif /*********************************************************************************************\ * Embedded tuned OneWire library @@ -285,7 +289,14 @@ void Ds18x20Init() void Ds18x20Convert() { OneWireReset(); +#ifdef W1_PARASITE_POWER + // With parasite power address one sensor at a time + if (++ds18x20_sensor_curr >= ds18x20_sensors) + ds18x20_sensor_curr = 0; + OneWireSelect(ds18x20_sensor[ds18x20_sensor_curr].address); +#else OneWireWrite(W1_SKIP_ROM); // Address all Sensors on Bus +#endif OneWireWrite(W1_CONVERT_TEMP); // start conversion, no parasite power on at the end // delay(750); // 750ms should be enough for 12bit conv } @@ -334,6 +345,9 @@ bool Ds18x20Read(uint8_t sensor) OneWireWrite(data[4]); // Configuration Register OneWireSelect(ds18x20_sensor[index].address); OneWireWrite(W1_WRITE_EEPROM); // Save scratchpad to EEPROM +#ifdef W1_PARASITE_POWER + w1_power_until = millis() + 10; // 10ms specified duration for EEPROM write +#endif } temp12 = (data[1] << 8) + data[0]; if (temp12 > 2047) { @@ -374,7 +388,18 @@ void Ds18x20Name(uint8_t sensor) void Ds18x20EverySecond() { - if (uptime &1) { +#ifdef W1_PARASITE_POWER + // skip access if there is still an eeprom write ongoing + unsigned long now = millis(); + if (now < w1_power_until) + return; +#endif + if (uptime & 1 +#ifdef W1_PARASITE_POWER + // if more than 1 sensor and only parasite power: convert every cycle + || ds18x20_sensors >= 2 +#endif + ) { // 2mS Ds18x20Convert(); // Start conversion, takes up to one second } else { From 3ed06695bade88e21778afa99d5609455e6e8427 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Oct 2018 09:38:36 +0200 Subject: [PATCH 0223/2222] Fix Teckin energy monitoring Fix Teckin energy monitoring (#3950) --- sonoff/xnrg_01_hlw8012.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 025ccff44..902df89ae 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -177,7 +177,7 @@ void HlwSnsInit() Settings.energy_current_calibration = HLW_IREF_PULSE; } - if (BLITZWOLF_BWSHP2 == Settings.module) { + if ((BLITZWOLF_BWSHP2 == Settings.module) || (TECKIN == Settings.module)) { hlw_power_ratio = HJL_PREF; hlw_voltage_ratio = HJL_UREF; hlw_current_ratio = HJL_IREF; From 7dcb10a91172d6b9391912a7d0a205e4cb898643 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Tue, 2 Oct 2018 13:42:21 +0200 Subject: [PATCH 0224/2222] v1.5.0012: 'decode-config.py' add args, add 6.2.1.x settings, fix filename with @ - add: developer version settings 6.2.1.2, 6.2.1.3, 6.2.1.6, 6.2.1.10 - add: args '--raw-keys', '--no-raw-keys', '--raw-values', '--no-raw-values', '--hide-pw' - add: value -1 for arg '--json-indent' to disable indent if default is enabled - changed: json output to file use always raw values - fix: add again removed return code desc - fix: needless dot . in filename for @v - fix: rule(123) none-raw outputs --- tools/decode-config.py | 1317 +++++++++++++++++++++++++++++++++++----- 1 file changed, 1177 insertions(+), 140 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 284904fb9..258a8accd 100644 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +#!/usr/bin/env python # -*- coding: utf-8 -*- +VER = '1.5.0012' """ decode-config.py - Decode configuration of Sonoff-Tasmota device @@ -35,9 +37,11 @@ Instructions: Usage: decode-config.py [-h] [-f ] [-d ] [-u ] [-p ] [--json-indent ] - [--json-compact] [--unsort] [--raw] [--unhide-pw] - [-o ] [--output-file-format ] - [-c ] [--exit-on-error-only] [-V] + [--json-compact] [--sort] [--unsort] [--raw-values] + [--no-raw-values] [--raw-keys] [--no-raw-keys] + [--hide-pw] [--unhide-pw] [-o ] + [--output-file-format ] [-c ] + [--exit-on-error-only] [-V] Decode configuration of Sonoff-Tasmota device. Args that start with '--' (eg. -f) can also be set in a config file (specified via -c). Config file syntax @@ -66,18 +70,23 @@ Usage: -p , --password host HTTP access password (default: None) - output: + config: --json-indent pretty-printed JSON output using indent level - (default: 'None') - --json-compact compact JSON output by eliminate whitespace (default: - normal) - --unsort do not sort results (default: sort) - --raw output raw values (default: process) - --unhide-pw unhide passwords (default: hide) + (default: 'None'). Use values greater equal 0 to + indent or -1 to disabled indent. + --json-compact compact JSON output by eliminate whitespace + --sort sort json keywords (default) + --unsort do not sort json keywords + --raw-values, --raw output raw values + --no-raw-values output human readable values (default) + --raw-keys output bitfield raw keys (default) + --no-raw-keys do not output bitfield raw keys + --hide-pw hide passwords (default) + --unhide-pw unhide passwords -o , --output-file - file to store configuration to (default: None) Macros: - @v=Tasmota version, @f=friendly name + file to store configuration to (default: None). + Replacements: @v=Tasmota version, @f=friendly name --output-file-format output format ('json' or 'binary', default: 'json') @@ -86,41 +95,44 @@ Usage: Either argument -d or -f must be given. + +Returns: + 0: successful + 1: file not found + 2: configuration version not supported + 3: data size mismatch + 4: data CRC error + 5: configuration file read error + 6: argument error + 9: python module is missing + 4xx, 5xx: HTTP error + """ import os.path import io import sys -import struct -import re -import math -from datetime import datetime +def ModuleImportError(module): + er = str(module) + print("{}. Try 'pip install {}' to install it".format(er,er.split(' ')[len(er.split(' '))-1]) ) + sys.exit(9) try: + import struct + import re + import math + from datetime import datetime import json -except ImportError: - print("module not found. Try 'pip install json' to install it") - sys.exit(9) -try: import configargparse -except ImportError: - print("module not found. Try 'pip install configargparse' to install it") - sys.exit(9) -try: import pycurl -except ImportError: - print("module not found. Try 'pip install pycurl' to install it") - sys.exit(9) -try: import urllib2 -except ImportError: - print("module not found. Try 'pip install urllib2' to install it") - sys.exit(9) +except ImportError, e: + ModuleImportError(e) -VER = '1.5.0011' PROG='{} v{} by Norbert Richter'.format(os.path.basename(sys.argv[0]),VER) CONFIG_FILE_XOR = 0x5A +BINARYFILE_MAGIC = 0x63576223 args = {} DEFAULTS = { @@ -136,13 +148,14 @@ DEFAULTS = { 'password': None, 'tasmotafile': None, }, - 'output': + 'config': { 'jsonindent': None, 'jsoncompact': False, - 'unsort': False, - 'raw': False, - 'unhide-pw': False, + 'sort': True, + 'rawvalues': False, + 'rawkeys': True, + 'hidepw': True, 'outputfile': None, 'outputfileformat': 'json', }, @@ -166,7 +179,7 @@ Settings dictionary describes the config file fields definition: 'xxx': A string is used to interpret the data at The string defines the format interpretion as described - in 'struct module format string', see + in 'struct module format string', see https://docs.python.org/2.7/library/struct.html#format-strings In addition to this format string there is as special meaning of a dot '.' - this means a bit with an optional @@ -178,7 +191,7 @@ Settings dictionary describes the config file fields definition: The address (starting from 0) within config data. For bit fields must be a tuple. n: - Defines a simple address within config data. + Defines a simple address within config data. must be a positive integer. (n, b, s): A tuple defines a bit field: @@ -221,11 +234,12 @@ def int2ip(value): return '{:d}.{:d}.{:d}.{:d}'.format(value & 0xff, value>>8 & 0xff, value>>16 & 0xff, value>>24 & 0xff) def password(value): - if args.unhidepw: - return value - return '********' + if args.hidepw: + return '********' + return value -Setting_6_2_1 = { + +Setting_6_2_1_10 = { 'cfg_holder': ('>24) & 0xff) + minor = ((ver>>16) & 0xff) + release = ((ver>> 8) & 0xff) + subrelease = (ver & 0xff) + if major>=6: + if subrelease>0: + subreleasestr = str(subrelease) + else: + subreleasestr = '' + else: + if subrelease>0: + subreleasestr = str(chr(subrelease+ord('a')-1)) + else: + subreleasestr = '' + v = "{:d}.{:d}.{:d}{}{}".format( major, minor, release, '.' if (major>=6 and subreleasestr!='') else '', subreleasestr) + filename = filename.replace('@v', v) + if 'friendlyname' in configuration: + filename = filename.replace('@f', configuration['friendlyname'][0] ) + + return filename + + def GetSettingsCrc(dobj): """ Return binary config data calclulated crc @param dobj: - uncrypted binary config data + decrypted binary config data @return: 2 byte unsigned integer crc value @@ -1918,7 +2928,7 @@ def GetFieldLength(fielddef): if addr != baseaddr: addr = baseaddr length += len_ - + else: if format_[-1:].lower() in ['b','c','?']: length=1 @@ -1942,13 +2952,15 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): Get field value from definition @param dobj: - uncrypted binary config data + decrypted binary config data @param fieldname: name of the field @param fielddef: see Settings desc above @param raw return raw values (True) or converted values (False) + @param addroffset + use offset for baseaddr (used for recursive calls) @return: read field value """ @@ -1963,7 +2975,7 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): # get datadef from field definition datadef = None - if len(fielddef)>2: + if fielddef is not None and len(fielddef)>2: datadef = fielddef[2] if datadef is not None: @@ -1993,7 +3005,7 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): subfielddef = (fielddef[0], MakeFieldBaseAddr(baseaddr, bitlen, bitshift), None, fielddef[3]) length = GetFieldLength(subfielddef) - if length != 0: + if length != 0 and (fieldname != 'raw' or args.rawkeys): result.append(GetField(dobj, fieldname, subfielddef, raw=raw, addroffset=addroffset+offset)) offset += length @@ -2004,7 +3016,8 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): setting = fielddef[0] config = {} for name in setting: - config[name] = GetField(dobj, name, setting[name], raw=args.raw, addroffset=addroffset) + if name != 'raw' or args.rawkeys: + config[name] = GetField(dobj, name, setting[name], raw=raw, addroffset=addroffset) result = config else: # a simple value @@ -2047,39 +3060,56 @@ def DeEncrypt(obj): return dobj -def Decode(obj): +def GetTemplateSetting(version): + """ + Search for template, settings and size to be used depending on given version number + + @param version: + version number from read binary data to search for + + @return: template, settings to use, None if version is invalid + """ + # search setting definition + template = None + setting = None + size = None + for cfg in Settings: + if version >= cfg[0]: + template = cfg + size = template[1] + setting = template[2] + break + + return template, size, setting + + +def Decode(obj, raw=True): """ Decodes binary data stream @param obj: binary config data (decrypted) - + @param raw + decode raw values (True) or converted values (False) + @return: configuration dictionary """ # get header data version = GetField(obj, 'version', Setting_6_2_1['version'], raw=True) - # search setting definition - template = None - for cfg in Settings: - if version >= cfg[0]: - template = cfg - break - + template, size, setting = GetTemplateSetting(version) # if we did not found a mathching setting if template is None: exit(2, "Tasmota configuration version 0x{:x} not supported".format(version) ) - - setting = template[2] # check size if exists if 'cfg_size' in setting: cfg_size = GetField(obj, 'cfg_size', setting['cfg_size'], raw=True) # read size should be same as definied in template - if cfg_size > template[1]: + if cfg_size > size: # may be processed exit(3, "Number of bytes read does ot match - read {}, expected {} byte".format(cfg_size, template[1]), typ='WARNING', doexit=args.exitonwarning) - elif cfg_size < template[1]: + elif cfg_size < size: # less number of bytes can not be processed exit(3, "Number of bytes read to small to process - read {}, expected {} byte".format(cfg_size, template[1]), typ='ERROR') @@ -2091,9 +3121,8 @@ def Decode(obj): if cfg_crc != GetSettingsCrc(obj): exit(4, 'Data CRC error, read 0x{:x} should be 0x{:x}'.format(cfg_crc, GetSettingsCrc(obj)), typ='WARNING', doexit=args.exitonwarning) - config = {} - for name in setting: - config[name] = GetField(obj, name, setting[name], raw=args.raw) + # get config + config = GetField(obj, None, (setting,None,None), raw=raw) # add header info timestamp = datetime.now() @@ -2142,44 +3171,74 @@ if __name__ == "__main__": default=DEFAULTS['source']['password'], help="host HTTP access password (default: {})".format(DEFAULTS['source']['password'])) - output = parser.add_argument_group('output') - output.add_argument('--json-indent', + config = parser.add_argument_group('config') + config.add_argument('--json-indent', metavar='', dest='jsonindent', type=int, - default=DEFAULTS['output']['jsonindent'], - help="pretty-printed JSON output using indent level (default: '{}')".format(DEFAULTS['output']['jsonindent']) ) - output.add_argument('--json-compact', + default=DEFAULTS['config']['jsonindent'], + help="pretty-printed JSON output using indent level (default: '{}'). Use values greater equal 0 to indent or -1 to disabled indent.".format(DEFAULTS['config']['jsonindent']) ) + config.add_argument('--json-compact', dest='jsoncompact', action='store_true', - default=DEFAULTS['output']['jsoncompact'], - help="compact JSON output by eliminate whitespace (default: {})".format('normal' if not DEFAULTS['output']['jsoncompact'] else 'compact') ) - output.add_argument('--unsort', - dest='unsort', + default=DEFAULTS['config']['jsoncompact'], + help="compact JSON output by eliminate whitespace{}".format(' (default)' if DEFAULTS['config']['jsoncompact'] else '') ) + + config.add_argument('--sort', + dest='sort', action='store_true', - default=DEFAULTS['output']['unsort'], - help="do not sort results (default: {})".format('sort' if not DEFAULTS['output']['unsort'] else 'unsort') ) - output.add_argument('--raw', - dest='raw', + default=DEFAULTS['config']['sort'], + help="sort json keywords{}".format(' (default)' if DEFAULTS['config']['sort'] else '') ) + config.add_argument('--unsort', + dest='sort', + action='store_false', + default=DEFAULTS['config']['sort'], + help="do not sort json keywords{}".format(' (default)' if not DEFAULTS['config']['sort'] else '') ) + + config.add_argument('--raw-values', '--raw', + dest='rawvalues', action='store_true', - default=DEFAULTS['output']['raw'], - help="output raw values (default: {})".format('raw' if DEFAULTS['output']['raw'] else 'process') ) - output.add_argument('--unhide-pw', - dest='unhidepw', + default=DEFAULTS['config']['rawvalues'], + help="output raw values{}".format(' (default)' if DEFAULTS['config']['rawvalues'] else '') ) + config.add_argument('--no-raw-values', + dest='rawvalues', + action='store_false', + default=DEFAULTS['config']['rawvalues'], + help="output human readable values{}".format(' (default)' if not DEFAULTS['config']['rawvalues'] else '') ) + + config.add_argument('--raw-keys', + dest='rawkeys', action='store_true', - default=DEFAULTS['output']['unhide-pw'], - help="unhide passwords (default: {})".format('unhide' if DEFAULTS['output']['unhide-pw'] else 'hide') ) - output.add_argument('-o', '--output-file', + default=DEFAULTS['config']['rawkeys'], + help="output bitfield raw keys{}".format(' (default)' if DEFAULTS['config']['rawkeys'] else '') ) + config.add_argument('--no-raw-keys', + dest='rawkeys', + action='store_false', + default=DEFAULTS['config']['rawkeys'], + help="do not output bitfield raw keys{}".format(' (default)' if not DEFAULTS['config']['rawkeys'] else '') ) + + config.add_argument('--hide-pw', + dest='hidepw', + action='store_true', + default=DEFAULTS['config']['hidepw'], + help="hide passwords{}".format(' (default)' if DEFAULTS['config']['hidepw'] else '') ) + config.add_argument('--unhide-pw', + dest='hidepw', + action='store_false', + default=DEFAULTS['config']['hidepw'], + help="unhide passwords{}".format(' (default)' if not DEFAULTS['config']['hidepw'] else '') ) + + config.add_argument('-o', '--output-file', metavar='', dest='outputfile', - default=DEFAULTS['output']['outputfile'], - help="file to store configuration to (default: {}) Macros: @v=Tasmota version, @f=friendly name".format(DEFAULTS['output']['outputfile'])) - output.add_argument('--output-file-format', + default=DEFAULTS['config']['outputfile'], + help="file to store configuration to (default: {}). Replacements: @v=Tasmota version, @f=friendly name".format(DEFAULTS['config']['outputfile'])) + config.add_argument('--output-file-format', metavar='', dest='outputfileformat', choices=['json', 'binary'], - default=DEFAULTS['output']['outputfileformat'], - help="output format ('json' or 'binary', default: '{}')".format(DEFAULTS['output']['outputfileformat']) ) + default=DEFAULTS['config']['outputfileformat'], + help="output format ('json' or 'binary', default: '{}')".format(DEFAULTS['config']['outputfileformat']) ) parser.add_argument('-c', '--config', metavar='', @@ -2197,14 +3256,14 @@ if __name__ == "__main__": info.add_argument('-V', '--version', action='version', version=PROG) args = parser.parse_args() - + # default no configuration available configobj = None - + # check source args if args.device is not None and args.tasmotafile is not None: exit(6, "Only one source allowed. Do not use -d and -f together") - + # read config direct from device via http if args.device is not None: @@ -2245,51 +3304,29 @@ if __name__ == "__main__": parser.print_help() sys.exit(0) - if configobj is not None and len(configobj)>0: cfg = DeEncrypt(configobj) - config = Decode(cfg) + configuration = Decode(cfg, args.rawvalues) # output to file if args.outputfile is not None: - outputfilename = args.outputfile - v = f1 = f2 = f3 = f4 = '' - if 'version' in config: - ver = int(str(config['version']), 0) - major = ((ver>>24) & 0xff) - minor = ((ver>>16) & 0xff) - release = ((ver>> 8) & 0xff) - subrelease = (ver & 0xff) - if major>=6: - if subrelease>0: - subreleasestr = str(subrelease) - else: - subreleasestr = '' - else: - if subrelease>0: - subreleasestr = str(chr(subrelease+ord('a')-1)) - else: - subreleasestr = '' - v = "{:d}.{:d}.{:d}{}{}".format( major, minor, release, '.' if major>=6 else '', subreleasestr) - outputfilename = outputfilename.replace('@v', v) - if 'friendlyname' in config: - outputfilename = outputfilename.replace('@f', config['friendlyname'][0] ) - + outputfilename = GetFilenameReplaced(args.outputfile, configuration) if args.outputfileformat == 'binary': outputfile = open(outputfilename, "wb") outputfile.write(struct.pack(' Date: Tue, 2 Oct 2018 17:07:30 +0200 Subject: [PATCH 0225/2222] 6.2.1.11 Add MQTT Client 6.2.1.11 20191002 * Remove support for MQTT Client based on esp-mqtt-arduino by #define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO * Add support for MQTT Client based on lwmqtt to be selected by #define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT --- sonoff/_changelog.ino | 6 ++- sonoff/sonoff.h | 7 +++- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 5 ++- sonoff/user_config.h | 8 ++-- sonoff/xdrv_01_mqtt.ino | 84 ++++++++++++++++++++++---------------- sonoff/xnrg_01_hlw8012.ino | 2 +- tools/decode-status.py | 2 +- 8 files changed, 71 insertions(+), 45 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 04f209e10..217b665ff 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ -/* 6.2.1.10 20180930 +/* 6.2.1.11 20191002 + * Remove support for MQTT Client based on esp-mqtt-arduino by #define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO + * Add support for MQTT Client based on lwmqtt to be selected by #define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT + * + * 6.2.1.10 20180930 * Add command RGBWWTable to support color calibration (#3933) * Add support for Michael Haustein ESP Switch * Add support for EXS Relay V5.0 (#3810) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 80356d475..f891e387a 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -20,6 +20,11 @@ #ifndef _SONOFF_H_ #define _SONOFF_H_ +#define USE_DHT // Default DHT11 sensor needs no external library +#define USE_ENERGY_SENSOR // Use energy sensors (+14k code) +#define USE_HLW8012 // Use energy sensor for Sonoff Pow and WolfBlitz +#define USE_CSE7766 // Use energy sensor for Sonoff S31 and Pow R2 + /*********************************************************************************************\ * Power Type \*********************************************************************************************/ @@ -136,7 +141,7 @@ typedef unsigned long power_t; // Power (Relay) type #define MQTT_PUBSUBCLIENT 1 // Mqtt PubSubClient library #define MQTT_TASMOTAMQTT 2 // Mqtt TasmotaMqtt library based on esp-mqtt-arduino -#define MQTT_ESPMQTTARDUINO 3 // Mqtt esp-mqtt-arduino library by Ingo Randolf +#define MQTT_ARDUINOMQTT 3 // Mqtt arduino-mqtt library by Joel Gaehwiler (https://github.com/256dpi/arduino-mqtt) // Sunrise and Sunset DawnType #define DAWN_NORMAL -0.8333 diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index c5765ec38..60a044326 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0602010A +#define VERSION 0x0602010B #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index 3665650dd..d2b38bb09 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -876,7 +876,7 @@ void GetFeatures() #if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) feature_drv1 |= 0x00000800; // xdrv_01_mqtt.ino #endif -#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) +#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) // Obsolete since 6.2.1.11 feature_drv1 |= 0x00001000; // xdrv_01_mqtt.ino #endif #ifdef MQTT_HOST_DISCOVERY @@ -933,6 +933,9 @@ void GetFeatures() #ifdef USE_SMARTCONFIG feature_drv1 |= 0x40000000; // support.ino #endif +#if (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT) + feature_drv1 |= 0x80000000; // xdrv_01_mqtt.ino +#endif /*********************************************************************************************/ diff --git a/sonoff/user_config.h b/sonoff/user_config.h index ee77854bc..11b8c1d61 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -216,14 +216,14 @@ //#define USE_ARDUINO_OTA // Add optional support for Arduino OTA (+13k code) /*-------------------------------------------------------------------------------------------*\ - * Select ONE of possible three MQTT library types below + * Select ONE of possible MQTT library types below \*-------------------------------------------------------------------------------------------*/ // Default MQTT driver for both non-TLS and TLS connections. Blocks network if MQTT server is unavailable. #define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library // Alternative MQTT driver does not block network when MQTT server is unavailable. No TLS support -//#define MQTT_LIBRARY_TYPE MQTT_TASMOTAMQTT // Use TasmotaMqtt library (+4k4 code, +4k mem) - non-TLS only - // Alternative MQTT driver does not block network when MQTT server is unavailable. No TLS support -//#define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO // Use (patched) esp-mqtt-arduino library (+4k8 code, +4k mem) - non-TLS only +//#define MQTT_LIBRARY_TYPE MQTT_TASMOTAMQTT // Use TasmotaMqtt library (+4k4 (core 2.3.0), +14k4 (core 2.4.2 lwip2) code, +4k mem) - non-TLS only + // Alternative MQTT driver does not block network when MQTT server is unavailable. TLS should work but needs to be tested. +//#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem) // -- MQTT ---------------------------------------- #define MQTT_TELE_RETAIN 0 // Tele messages may send retain flag (0 = off, 1 = on) diff --git a/sonoff/xdrv_01_mqtt.ino b/sonoff/xdrv_01_mqtt.ino index f3f33d693..42214216a 100644 --- a/sonoff/xdrv_01_mqtt.ino +++ b/sonoff/xdrv_01_mqtt.ino @@ -23,19 +23,29 @@ // Default MQTT driver for both non-TLS and TLS connections. Blocks network if MQTT server is unavailable. //#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library // Alternative MQTT driver does not block network when MQTT server is unavailable. No TLS support -//#define MQTT_LIBRARY_TYPE MQTT_TASMOTAMQTT // Use TasmotaMqtt library (+4k4 code, +4k mem) - non-TLS only -// Alternative MQTT driver does not block network when MQTT server is unavailable. No TLS support -//#define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO // Use (patched) esp-mqtt-arduino library (+4k8 code, +4k mem) - non-TLS only +//#define MQTT_LIBRARY_TYPE MQTT_TASMOTAMQTT // Use TasmotaMqtt library (+4k4 (core 2.3.0), +14k4 (core 2.4.2 lwip2) code, +4k mem) - non-TLS only +// Alternative MQTT driver does not block network when MQTT server is unavailable. TLS should work but needs to be tested. +//#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem) #ifdef USE_MQTT_TLS + +/* #ifdef MQTT_LIBRARY_TYPE #undef MQTT_LIBRARY_TYPE #endif #define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library as it only supports TLS +*/ +#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) +#undef MQTT_LIBRARY_TYPE +#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library as it only supports TLS +#endif + #else + #ifndef MQTT_LIBRARY_TYPE #define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library as default #endif + #endif /*********************************************************************************************/ @@ -136,48 +146,48 @@ void MqttLoop() { } -#elif (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) /*******************************************/ +#elif (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT) /**********************************************/ -#include -MQTT *MqttClient = NULL; +#include +MQTTClient MqttClient(MQTT_MAX_PACKET_SIZE); bool MqttIsConnected() { - return mqtt_connected; + return MqttClient.connected(); } void MqttDisconnect() { - if (MqttClient) MqttClient->disconnect(); + MqttClient.disconnect(); } -void MqttDisconnectedCb() +/* +void MqttMyDataCb(MQTTClient* client, char* topic, char* data, int data_len) +//void MqttMyDataCb(MQTTClient *client, char topic[], char data[], int data_len) { - MqttDisconnected(MqttClient->getState()); // status codes are documented in file mqtt.h as tConnState +// MqttDataHandler((char*)topic, (byte*)data, data_len); } +*/ -void MqttMyDataCb(const char* topic, uint32_t topic_len, const char* data, uint32_t data_len) +void MqttMyDataCb(String &topic, String &data) { - char topic_copy[topic_len +1]; - - memcpy(topic_copy, topic, topic_len); - topic_copy[topic_len] = 0; - if (0 == data_len) data = (const char*)&topic_copy + topic_len; - MqttDataHandler((char*)topic_copy, (byte*)data, data_len); + MqttDataHandler((char*)topic.c_str(), (byte*)data.c_str(), data.length()); } void MqttSubscribeLib(char *topic) { - MqttClient->subscribe(topic); + MqttClient.subscribe(topic, 0); } bool MqttPublishLib(const char* topic, boolean retained) { - return MqttClient->publish(topic, mqtt_data, strlen(mqtt_data), 0, retained); + return MqttClient.publish(topic, mqtt_data, strlen(mqtt_data), retained, 0); } void MqttLoop() { + MqttClient.loop(); +// delay(10); } #endif // MQTT_LIBRARY_TYPE @@ -467,6 +477,14 @@ void MqttReconnect() GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); snprintf_P(mqtt_data, sizeof(mqtt_data), S_OFFLINE); +//#ifdef ARDUINO_ESP8266_RELEASE_2_4_1 +#ifdef USE_MQTT_TLS + EspClient = WiFiClientSecure(); // Wifi Secure Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497) +#else + EspClient = WiFiClient(); // Wifi Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497) +#endif +//#endif + if (2 == mqtt_initial_connection_state) { // Executed once just after power on and wifi is connected #ifdef USE_MQTT_TLS if (!MqttCheckTls()) return; @@ -479,25 +497,17 @@ void MqttReconnect() MqttClient.OnConnected(MqttConnected); MqttClient.OnDisconnected(MqttDisconnectedCb); MqttClient.OnData(MqttDataHandler); -#elif (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) - MqttClient = new MQTT(mqtt_client, Settings.mqtt_host, Settings.mqtt_port, stopic, 1, true, mqtt_data); - MqttClient->setUserPwd(mqtt_user, mqtt_pwd); - MqttClient->onConnected(MqttConnected); - MqttClient->onDisconnected(MqttDisconnectedCb); - MqttClient->onData(MqttMyDataCb); +#elif (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT) + MqttClient.begin(Settings.mqtt_host, Settings.mqtt_port, EspClient); + MqttClient.setWill(stopic, mqtt_data, true, 1); + MqttClient.setOptions(MQTT_KEEPALIVE, true, 1000); +// MqttClient.onMessageAdvanced(MqttMyDataCb); + MqttClient.onMessage(MqttMyDataCb); #endif mqtt_initial_connection_state = 1; } -//#ifdef ARDUINO_ESP8266_RELEASE_2_4_1 -#ifdef USE_MQTT_TLS - EspClient = WiFiClientSecure(); // Wifi Secure Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497) -#else - EspClient = WiFiClient(); // Wifi Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497) -#endif -//#endif - #if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT) MqttClient.setCallback(MqttDataHandler); MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); @@ -508,8 +518,12 @@ void MqttReconnect() } #elif (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) MqttClient.Connect(); -#elif (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) - MqttClient->connect(); +#elif (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT) + if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd)) { + MqttConnected(); + } else { + MqttDisconnected(MqttClient.lastError()); // status codes are documented here https://github.com/256dpi/lwmqtt/blob/master/include/lwmqtt.h#L11 + } #endif // MQTT_LIBRARY_TYPE } diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 902df89ae..0bcfa9060 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -33,7 +33,7 @@ #define HLW_IREF 4545 // 4.545A #define HLW_SEL_VOLTAGE 1 -// HJL-01 based (BlitzWolf, Homecube, Gosund) +// HJL-01 based (BlitzWolf, Homecube, Gosund, Teckin) #define HJL_PREF 1362 #define HJL_UREF 822 #define HJL_IREF 3300 diff --git a/tools/decode-status.py b/tools/decode-status.py index 74b10a57c..99c73af69 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -105,7 +105,7 @@ a_features = [[ "USE_WS2812_DMA","USE_IR_REMOTE","USE_IR_HVAC","USE_IR_RECEIVE", "USE_DOMOTICZ","USE_DISPLAY","USE_HOME_ASSISTANT","USE_SERIAL_BRIDGE", "USE_TIMERS","USE_SUNRISE","USE_TIMERS_WEB","USE_RULES", - "USE_KNX","USE_WPS","USE_SMARTCONFIG","" + "USE_KNX","USE_WPS","USE_SMARTCONFIG","MQTT_ARDUINOMQTT" ],[ "USE_CONFIG_OVERRIDE","BE_MINIMAL","USE_SENSORS","USE_CLASSIC", "USE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD", From 6cd59d2b3e3b983778532bf5d437dfba42b131f1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Oct 2018 17:19:02 +0200 Subject: [PATCH 0226/2222] Forgot the library swap --- lib/arduino-mqtt-2.3.3.02/.editorconfig | 7 + lib/arduino-mqtt-2.3.3.02/.gitignore | 2 + lib/arduino-mqtt-2.3.3.02/.travis.yml | 46 + lib/arduino-mqtt-2.3.3.02/CMakeLists.txt | 40 + lib/arduino-mqtt-2.3.3.02/LICENSE.md | 21 + lib/arduino-mqtt-2.3.3.02/Makefile | 14 + lib/arduino-mqtt-2.3.3.02/README.md | 225 ++++ .../AdafruitHuzzahESP8266.ino | 69 ++ .../AdafruitHuzzahESP8266Secure.ino | 71 ++ .../ArduinoEthernetShield.ino | 62 + .../ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino | 84 ++ .../ArduinoMKRGSM1400Secure.ino | 86 ++ .../ArduinoWiFi101/ArduinoWiFi101.ino | 70 ++ .../ArduinoWiFi101Secure.ino | 75 ++ .../ArduinoWiFiShield/ArduinoWiFiShield.ino | 68 ++ .../examples/ArduinoYun/ArduinoYun.ino | 60 + .../ArduinoYunSecure/ArduinoYunSecure.ino | 62 + .../ESP32DevelopmentBoard.ino | 69 ++ .../ESP32DevelopmentBoardSecure.ino | 71 ++ lib/arduino-mqtt-2.3.3.02/library.properties | 9 + lib/arduino-mqtt-2.3.3.02/src/MQTTClient.h | 386 ++++++ lib/arduino-mqtt-2.3.3.02/src/MQTTlw.h | 6 + lib/arduino-mqtt-2.3.3.02/src/lwmqtt/client.c | 618 ++++++++++ .../src/lwmqtt/helpers.c | 249 ++++ .../src/lwmqtt/helpers.h | 137 +++ lib/arduino-mqtt-2.3.3.02/src/lwmqtt/lwmqtt.h | 381 ++++++ lib/arduino-mqtt-2.3.3.02/src/lwmqtt/packet.c | 742 ++++++++++++ lib/arduino-mqtt-2.3.3.02/src/lwmqtt/packet.h | 185 +++ lib/arduino-mqtt-2.3.3.02/src/lwmqtt/string.c | 38 + lib/arduino-mqtt-2.3.3.02/src/system.cpp | 48 + lib/arduino-mqtt-2.3.3.02/src/system.h | 26 + lib/esp-mqtt-arduino-1.0.1.02.1/.gitignore | 28 - lib/esp-mqtt-arduino-1.0.1.02.1/README.md | 15 - .../examples/mqtt_pub/mqtt_pub.ino | 102 -- .../examples/mqtt_sub/mqtt_sub.ino | 95 -- lib/esp-mqtt-arduino-1.0.1.02.1/keywords.txt | 43 - .../library.properties | 9 - lib/esp-mqtt-arduino-1.0.1.02.1/src/MQTT.cpp | 269 ----- lib/esp-mqtt-arduino-1.0.1.02.1/src/MQTT.h | 93 -- .../src/mqtt/debug.h | 19 - .../src/mqtt/mqtt.c | 1048 ----------------- .../src/mqtt/mqtt.h | 152 --- .../src/mqtt/mqtt_config.h | 19 - .../src/mqtt/mqtt_msg.c | 487 -------- .../src/mqtt/mqtt_msg.h | 141 --- .../src/mqtt/proto.c | 129 -- .../src/mqtt/proto.h | 32 - .../src/mqtt/queue.c | 75 -- .../src/mqtt/queue.h | 44 - .../src/mqtt/ringbuf.c | 67 -- .../src/mqtt/ringbuf.h | 19 - .../src/mqtt/typedef.h | 17 - .../src/mqtt/utils.c | 149 --- .../src/mqtt/utils.h | 9 - 54 files changed, 4027 insertions(+), 3061 deletions(-) create mode 100644 lib/arduino-mqtt-2.3.3.02/.editorconfig create mode 100644 lib/arduino-mqtt-2.3.3.02/.gitignore create mode 100644 lib/arduino-mqtt-2.3.3.02/.travis.yml create mode 100644 lib/arduino-mqtt-2.3.3.02/CMakeLists.txt create mode 100644 lib/arduino-mqtt-2.3.3.02/LICENSE.md create mode 100644 lib/arduino-mqtt-2.3.3.02/Makefile create mode 100644 lib/arduino-mqtt-2.3.3.02/README.md create mode 100644 lib/arduino-mqtt-2.3.3.02/examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino create mode 100644 lib/arduino-mqtt-2.3.3.02/examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino create mode 100644 lib/arduino-mqtt-2.3.3.02/examples/ArduinoEthernetShield/ArduinoEthernetShield.ino create mode 100644 lib/arduino-mqtt-2.3.3.02/examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino create mode 100644 lib/arduino-mqtt-2.3.3.02/examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino create mode 100644 lib/arduino-mqtt-2.3.3.02/examples/ArduinoWiFi101/ArduinoWiFi101.ino create mode 100644 lib/arduino-mqtt-2.3.3.02/examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino create mode 100644 lib/arduino-mqtt-2.3.3.02/examples/ArduinoWiFiShield/ArduinoWiFiShield.ino create mode 100644 lib/arduino-mqtt-2.3.3.02/examples/ArduinoYun/ArduinoYun.ino create mode 100644 lib/arduino-mqtt-2.3.3.02/examples/ArduinoYunSecure/ArduinoYunSecure.ino create mode 100644 lib/arduino-mqtt-2.3.3.02/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino create mode 100644 lib/arduino-mqtt-2.3.3.02/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino create mode 100644 lib/arduino-mqtt-2.3.3.02/library.properties create mode 100644 lib/arduino-mqtt-2.3.3.02/src/MQTTClient.h create mode 100644 lib/arduino-mqtt-2.3.3.02/src/MQTTlw.h create mode 100644 lib/arduino-mqtt-2.3.3.02/src/lwmqtt/client.c create mode 100644 lib/arduino-mqtt-2.3.3.02/src/lwmqtt/helpers.c create mode 100644 lib/arduino-mqtt-2.3.3.02/src/lwmqtt/helpers.h create mode 100644 lib/arduino-mqtt-2.3.3.02/src/lwmqtt/lwmqtt.h create mode 100644 lib/arduino-mqtt-2.3.3.02/src/lwmqtt/packet.c create mode 100644 lib/arduino-mqtt-2.3.3.02/src/lwmqtt/packet.h create mode 100644 lib/arduino-mqtt-2.3.3.02/src/lwmqtt/string.c create mode 100644 lib/arduino-mqtt-2.3.3.02/src/system.cpp create mode 100644 lib/arduino-mqtt-2.3.3.02/src/system.h delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/.gitignore delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/README.md delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/examples/mqtt_pub/mqtt_pub.ino delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/examples/mqtt_sub/mqtt_sub.ino delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/keywords.txt delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/library.properties delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/MQTT.cpp delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/MQTT.h delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/debug.h delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt.c delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt.h delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt_config.h delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt_msg.c delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt_msg.h delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/proto.c delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/proto.h delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/queue.c delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/queue.h delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/ringbuf.c delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/ringbuf.h delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/typedef.h delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/utils.c delete mode 100644 lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/utils.h diff --git a/lib/arduino-mqtt-2.3.3.02/.editorconfig b/lib/arduino-mqtt-2.3.3.02/.editorconfig new file mode 100644 index 000000000..3edae7b53 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/.editorconfig @@ -0,0 +1,7 @@ +[Makefile] +indent_style = tab +indent_size = 4 + +[src/*.h,src/*.cpp,examples/**.ino] +indent_style = space +indent_size = 2 diff --git a/lib/arduino-mqtt-2.3.3.02/.gitignore b/lib/arduino-mqtt-2.3.3.02/.gitignore new file mode 100644 index 000000000..0c4fe4711 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +cmake-build-debug/ diff --git a/lib/arduino-mqtt-2.3.3.02/.travis.yml b/lib/arduino-mqtt-2.3.3.02/.travis.yml new file mode 100644 index 000000000..b59599cef --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/.travis.yml @@ -0,0 +1,46 @@ +language: generic +env: + global: + - IDE_VERSION=1.8.5 + matrix: + - EXAMPLE="AdafruitHuzzahESP8266" BOARD="esp8266:esp8266:huzzah:FlashSize=4M3M,CpuFrequency=80" + - EXAMPLE="AdafruitHuzzahESP8266Secure" BOARD="esp8266:esp8266:huzzah:FlashSize=4M3M,CpuFrequency=80" + - EXAMPLE="ArduinoEthernetShield" BOARD="arduino:avr:uno" + - EXAMPLE="ArduinoMKRGSM1400" BOARD="arduino:samd:mkrgsm1400" + - EXAMPLE="ArduinoMKRGSM1400Secure" BOARD="arduino:samd:mkrgsm1400" + - EXAMPLE="ArduinoWiFi101Secure" BOARD="arduino:avr:uno" + - EXAMPLE="ArduinoWiFiShield" BOARD="arduino:avr:uno" + - EXAMPLE="ArduinoYun" BOARD="arduino:avr:yun" + - EXAMPLE="ArduinoYunSecure" BOARD="arduino:avr:yun" + - EXAMPLE="ESP32DevelopmentBoard" BOARD="espressif:esp32:esp32:FlashFreq=80" + - EXAMPLE="ESP32DevelopmentBoardSecure" BOARD="espressif:esp32:esp32:FlashFreq=80" +before_install: + - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 + - sleep 3 + - export DISPLAY=:1.0 + - wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz + - tar xf arduino-$IDE_VERSION-linux64.tar.xz + - mv arduino-$IDE_VERSION ~/arduino-ide + - export PATH=$PATH:~/arduino-ide + - if [[ "$BOARD" =~ "esp8266:esp8266:" ]]; then + arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --install-boards esp8266:esp8266; + arduino --pref "boardsmanager.additional.urls=" --save-prefs; + fi + - if [[ "$BOARD" =~ "espressif:esp32:" ]]; then + mkdir -p ~/Arduino/hardware/espressif && + cd ~/Arduino/hardware/espressif && + git clone https://github.com/espressif/arduino-esp32.git esp32 && + cd esp32/tools/ && + python get.py && + cd $TRAVIS_BUILD_DIR; + fi + - if [[ "$BOARD" =~ "arduino:samd:mkrgsm1400" ]]; then + arduino --install-boards arduino:samd; + arduino --install-library MKRGSM; + fi + - arduino --install-library WiFi101 +install: + - mkdir -p ~/Arduino/libraries + - ln -s $PWD ~/Arduino/libraries/. +script: + - arduino --verbose-build --verify --board $BOARD $PWD/examples/$EXAMPLE/$EXAMPLE.ino; diff --git a/lib/arduino-mqtt-2.3.3.02/CMakeLists.txt b/lib/arduino-mqtt-2.3.3.02/CMakeLists.txt new file mode 100644 index 000000000..58b0e31c9 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/CMakeLists.txt @@ -0,0 +1,40 @@ +# Uncompilable CMake File to enable project editing with CLion IDE + +cmake_minimum_required(VERSION 2.8.4) +project(arduino-mqtt) + +include_directories( + /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/ + /Users/256dpi/Development/Arduino/libraries/Ethernet/src + /Users/256dpi/Development/Arduino/libraries/WiFi101/src + /Users/256dpi/Development/Arduino/libraries/MKRGSM/src + /Applications/Arduino.app/Contents/Java/libraries/Bridge/src + /Users/256dpi/Library/Arduino15/packages/esp8266/hardware/esp8266/2.3.0/libraries/ESP8266WiFi/src + /Users/256dpi/Development/Arduino/hardware/espressif/esp32/libraries/WiFi/src + /Users/256dpi/Development/Arduino/hardware/espressif/esp32/libraries/WiFiClientSecure/src + src/) + +include_directories(src/) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +set(SOURCE_FILES + examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino + examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino + examples/ArduinoEthernetShield/ArduinoEthernetShield.ino + examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino + examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino + examples/ArduinoWiFi101/ArduinoWiFi101.ino + examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino + examples/ArduinoWiFiShield/ArduinoWiFiShield.ino + examples/ArduinoYun/ArduinoYun.ino + examples/ArduinoYunSecure/ArduinoYunSecure.ino + examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino + examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino + src/lwmqtt + src/MQTT.h + src/MQTTClient.h + src/system.cpp + src/system.h) + +add_executable(arduino-mqtt ${SOURCE_FILES}) diff --git a/lib/arduino-mqtt-2.3.3.02/LICENSE.md b/lib/arduino-mqtt-2.3.3.02/LICENSE.md new file mode 100644 index 000000000..325e07cff --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Joël Gähwiler + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/arduino-mqtt-2.3.3.02/Makefile b/lib/arduino-mqtt-2.3.3.02/Makefile new file mode 100644 index 000000000..cfd69e49c --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/Makefile @@ -0,0 +1,14 @@ +all: fmt + +fmt: + clang-format -i src/*.cpp src/*.h -style="{BasedOnStyle: Google, ColumnLimit: 120}" + +update: + rm -rf ./lwmqtt + git clone --branch v0.6.2 https://github.com/256dpi/lwmqtt.git ./lwmqtt + mkdir -p ./src/lwmqtt + cp -r ./lwmqtt/src/*.c ./src/lwmqtt/ + cp -r ./lwmqtt/src/*.h ./src/lwmqtt/ + cp -r ./lwmqtt/include/*.h ./src/lwmqtt/ + rm -rf ./lwmqtt + sed -i '' "s//\"lwmqtt.h\"/g" ./src/lwmqtt/* diff --git a/lib/arduino-mqtt-2.3.3.02/README.md b/lib/arduino-mqtt-2.3.3.02/README.md new file mode 100644 index 000000000..470c4a58c --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/README.md @@ -0,0 +1,225 @@ +# arduino-mqtt + +[![Build Status](https://travis-ci.org/256dpi/arduino-mqtt.svg?branch=master)](https://travis-ci.org/256dpi/arduino-mqtt) +[![GitHub release](https://img.shields.io/github/release/256dpi/arduino-mqtt.svg)](https://github.com/256dpi/arduino-mqtt/releases) + +This library bundles the [lwmqtt](https://github.com/256dpi/lwmqtt) MQTT 3.1.1 client and adds a thin wrapper to get an Arduino like API. + +Download the latest version from the [release](https://github.com/256dpi/arduino-mqtt/releases) section. Or even better use the builtin Library Manager in the Arduino IDE and search for "MQTT". + +The library is also available on [PlatformIO](https://platformio.org/lib/show/617/MQTT). You can install it by running: `pio lib install "MQTT"`. + +## Compatibility + +The following examples show how you can use the library with various Arduino compatible hardware: + +- [Arduino Yun & Yun-Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoYun/ArduinoYun.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoYunSecure/ArduinoYunSecure.ino)) +- [Arduino Ethernet Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoEthernetShield/ArduinoEthernetShield.ino) +- [Arduino WiFi Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoWiFiShield/ArduinoWiFiShield.ino) +- [Adafruit HUZZAH ESP8266](https://github.com/256dpi/arduino-mqtt/blob/master/examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino)) +- [Arduino/Genuino WiFi101 Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoWiFi101/ArduinoWiFi101.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino)) +- [Arduino MKR GSM 1400](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino)) +- [ESP32 Development Board](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino)) + +Other shields and boards should also work if they provide a [Client](https://www.arduino.cc/en/Reference/ClientConstructor) based network implementation. + +## Notes + +- The maximum size for packets being published and received is set by default to 128 bytes. To change the buffer sizes, you need to use `MQTTClient client(256)` instead of just `MQTTClient client` on the top of your sketch. The passed value denotes the read and write buffer size. + +- On the ESP8266 it has been reported that an additional `delay(10);` after `client.loop();` fixes many stability issues with WiFi connections. + +- To use the library with shiftr.io, you need to provide the token key (username) and token secret (password) as the second and third argument to `client.connect(name, key, secret)`. + +## Example + +The following example uses an Arduino MKR1000 to connect to shiftr.io. You can check on your device after a successful connection here: https://shiftr.io/try. + +```c++ +#include +#include +#include + +const char ssid[] = "ssid"; +const char pass[] = "pass"; + +WiFiClient net; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + Serial.print("checking wifi..."); + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); + delay(1000); + } + + Serial.print("\nconnecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Serial.begin(115200); + WiFi.begin(ssid, pass); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + client.begin("broker.shiftr.io", net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} +``` + +## API + +Initialize the object using the hostname of the broker, the brokers port (default: `1883`) and the underlying Client class for network transport: + +```c++ +void begin(const char hostname[], Client &client); +void begin(const char hostname[], int port, Client &client); +``` + +- Specify port `8883` when using secure clients for encrypted connections. +- Local domain names (e.g. `Computer.local` on OSX) are not supported by Arduino. You need to set the IP address directly. + +The hostname and port can also be changed after calling `begin()`: + +```c++ +void setHost(const char hostname[]); +void setHost(const char hostname[], int port); +``` + +Set a will message (last testament) that gets registered on the broker after connecting. `setWill()` has to be called before calling `connect()`: + +```c++ +void setWill(const char topic[]); +void setWill(const char topic[], const char payload[]); +void setWill(const char topic[], const char payload[], bool retained, int qos); +void clearWill(); +``` + +Register a callback to receive messages: + +```c++ +void onMessage(MQTTClientCallbackSimple); +// Callback signature: void messageReceived(String &topic, String &payload) {} + +void onMessageAdvanced(MQTTClientCallbackAdvanced); +// Callback signature: void messageReceived(MQTTClient *client, char topic[], char payload[], int payload_length) {} +``` + +- The set callback is mostly called during a call to `loop()` but may also be called during a call to `subscribe()`, `unsubscribe()` or `publish() // QoS > 0` if messages have been received before receiving the required acknowledgement. Therefore, it is strongly recommended to not call `subscribe()`, `unsubscribe()` or `publish() // QoS > 0` directly in the callback. + +Set more advanced options: + +```c++ +void setOptions(int keepAlive, bool cleanSession, int timeout); +``` + +- The `keepAlive` option controls the keep alive interval in seconds (default: 10). +- The `cleanSession` option controls the session retention on the broker side (default: true). +- The `timeout` option controls the default timeout for all commands in milliseconds (default: 1000). + +Connect to broker using the supplied client id and an optional username and password: + +```c++ +bool connect(const char clientId[]); +bool connect(const char clientId[], const char username[]); +bool connect(const char clientId[], const char username[], const char password[]); +``` + +- This functions returns a boolean that indicates if the connection has been established successfully. + +Publishes a message to the broker with an optional payload: + +```c++ +bool publish(const String &topic); +bool publish(const char topic[]); +bool publish(const String &topic, const String &payload); +bool publish(const String &topic, const String &payload, bool retained, int qos); +bool publish(const char topic[], const String &payload); +bool publish(const char topic[], const String &payload, bool retained, int qos); +bool publish(const char topic[], const char payload[]); +bool publish(const char topic[], const char payload[], bool retained, int qos); +bool publish(const char topic[], const char payload[], int length); +bool publish(const char topic[], const char payload[], int length, bool retained, int qos); +``` + +Subscribe to a topic: + +```c++ +bool subscribe(const String &topic); +bool subscribe(const String &topic, int qos); +bool subscribe(const char topic[]); +bool subscribe(const char topic[], int qos); +``` + +Unsubscribe from a topic: + +```c++ +bool unsubscribe(const String &topic); +bool unsubscribe(const char topic[]); +``` + +Sends and receives packets: + +```c++ +bool loop(); +``` + +- This function should be called in every `loop`. + +Check if the client is currently connected: + +```c++ +bool connected(); +``` + +Access low-level information for debugging: + +```c++ +lwmqtt_err_t lastError(); +lwmqtt_return_code_t returnCode(); +``` + +- The error codes can be found [here](https://github.com/256dpi/lwmqtt/blob/master/include/lwmqtt.h#L11). +- The return codes can be found [here](https://github.com/256dpi/lwmqtt/blob/master/include/lwmqtt.h#L243). + +Disconnect from the broker: + +```c++ +bool disconnect(); +``` + +## Release Management + +- Update version in `library.properties`. +- Create release on GitHub. diff --git a/lib/arduino-mqtt-2.3.3.02/examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino b/lib/arduino-mqtt-2.3.3.02/examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino new file mode 100644 index 000000000..ca5a22607 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino @@ -0,0 +1,69 @@ +// This example uses an Adafruit Huzzah ESP8266 +// to connect to shiftr.io. +// +// You can check on your device after a successful +// connection here: https://shiftr.io/try. +// +// by Joël Gähwiler +// https://github.com/256dpi/arduino-mqtt + +#include +#include + +const char ssid[] = "ssid"; +const char pass[] = "pass"; + +WiFiClient net; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + Serial.print("checking wifi..."); + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); + delay(1000); + } + + Serial.print("\nconnecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Serial.begin(115200); + WiFi.begin(ssid, pass); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + client.begin("broker.shiftr.io", net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + delay(10); // <- fixes some issues with WiFi stability + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} diff --git a/lib/arduino-mqtt-2.3.3.02/examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino b/lib/arduino-mqtt-2.3.3.02/examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino new file mode 100644 index 000000000..1def5678d --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino @@ -0,0 +1,71 @@ +// This example uses an Adafruit Huzzah ESP8266 +// to connect to shiftr.io. +// +// You can check on your device after a successful +// connection here: https://shiftr.io/try. +// +// by Joël Gähwiler +// https://github.com/256dpi/arduino-mqtt + +#include +#include + +const char ssid[] = "ssid"; +const char pass[] = "pass"; + +WiFiClientSecure net; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + Serial.print("checking wifi..."); + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); + delay(1000); + } + + Serial.print("\nconnecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Serial.begin(115200); + WiFi.begin(ssid, pass); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + // + // MQTT brokers usually use port 8883 for secure connections. + client.begin("broker.shiftr.io", 8883, net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + delay(10); // <- fixes some issues with WiFi stability + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} diff --git a/lib/arduino-mqtt-2.3.3.02/examples/ArduinoEthernetShield/ArduinoEthernetShield.ino b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoEthernetShield/ArduinoEthernetShield.ino new file mode 100644 index 000000000..8386c7788 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoEthernetShield/ArduinoEthernetShield.ino @@ -0,0 +1,62 @@ +// This example uses an Arduino Uno together with +// an Ethernet Shield to connect to shiftr.io. +// +// You can check on your device after a successful +// connection here: https://shiftr.io/try. +// +// by Joël Gähwiler +// https://github.com/256dpi/arduino-mqtt + +#include +#include + +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +byte ip[] = {192, 168, 1, 177}; // <- change to match your network + +EthernetClient net; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + Serial.print("connecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Serial.begin(115200); + Ethernet.begin(mac, ip); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + client.begin("broker.shiftr.io", net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} diff --git a/lib/arduino-mqtt-2.3.3.02/examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino new file mode 100644 index 000000000..dd56d5e21 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino @@ -0,0 +1,84 @@ +// This example uses an Arduino MKR GSM 1400 board +// to connect to shiftr.io. +// +// IMPORTANT: This example uses the new MKRGSM library. +// +// You can check on your device after a successful +// connection here: https://shiftr.io/try. +// +// by Sandeep Mistry +// https://github.com/256dpi/arduino-mqtt + +#include +#include + +const char pin[] = ""; +const char apn[] = "apn"; +const char login[] = "login"; +const char password[] = "password"; + +GSMClient net; +GPRS gprs; +GSM gsmAccess; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + // connection state + bool connected = false; + + Serial.print("connecting to cellular network ..."); + + // After starting the modem with gsmAccess.begin() + // attach to the GPRS network with the APN, login and password + while (!connected) { + if ((gsmAccess.begin(pin) == GSM_READY) && + (gprs.attachGPRS(apn, login, password) == GPRS_READY)) { + connected = true; + } else { + Serial.print("."); + delay(1000); + } + } + + Serial.print("\nconnecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Serial.begin(115200); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + client.begin("broker.shiftr.io", net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} diff --git a/lib/arduino-mqtt-2.3.3.02/examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino new file mode 100644 index 000000000..1b172ab6e --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino @@ -0,0 +1,86 @@ +// This example uses an Arduino MKR GSM 1400 board +// to securely connect to shiftr.io. +// +// IMPORTANT: This example uses the new MKRGSM library. +// +// You can check on your device after a successful +// connection here: https://shiftr.io/try. +// +// by Sandeep Mistry +// https://github.com/256dpi/arduino-mqtt + +#include +#include + +const char pin[] = ""; +const char apn[] = "apn"; +const char login[] = "login"; +const char password[] = "password"; + +GSMSSLClient net; +GPRS gprs; +GSM gsmAccess; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + // connection state + bool connected = false; + + Serial.print("connecting to cellular network ..."); + + // After starting the modem with gsmAccess.begin() + // attach to the GPRS network with the APN, login and password + while (!connected) { + if ((gsmAccess.begin(pin) == GSM_READY) && + (gprs.attachGPRS(apn, login, password) == GPRS_READY)) { + connected = true; + } else { + Serial.print("."); + delay(1000); + } + } + + Serial.print("\nconnecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Serial.begin(115200); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + // + // MQTT brokers usually use port 8883 for secure connections. + client.begin("broker.shiftr.io", 8883, net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} diff --git a/lib/arduino-mqtt-2.3.3.02/examples/ArduinoWiFi101/ArduinoWiFi101.ino b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoWiFi101/ArduinoWiFi101.ino new file mode 100644 index 000000000..a36bd65aa --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoWiFi101/ArduinoWiFi101.ino @@ -0,0 +1,70 @@ +// This example uses an Arduino/Genuino Zero together with +// a WiFi101 Shield or a MKR1000 to connect to shiftr.io. +// +// IMPORTANT: This example uses the new WiFi101 library. +// +// You can check on your device after a successful +// connection here: https://shiftr.io/try. +// +// by Gilberto Conti +// https://github.com/256dpi/arduino-mqtt + +#include +#include + +const char ssid[] = "ssid"; +const char pass[] = "pass"; + +WiFiClient net; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + Serial.print("checking wifi..."); + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); + delay(1000); + } + + Serial.print("\nconnecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Serial.begin(115200); + WiFi.begin(ssid, pass); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + client.begin("broker.shiftr.io", net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} diff --git a/lib/arduino-mqtt-2.3.3.02/examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino new file mode 100644 index 000000000..c21e7ae99 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino @@ -0,0 +1,75 @@ +// This example uses an Arduino/Genuino Zero together with +// a WiFi101 Shield or a MKR1000 to connect to shiftr.io. +// +// IMPORTANT: This example uses the new WiFi101 library. +// +// IMPORTANT: You need to install/update the SSL certificates first: +// https://github.com/arduino-libraries/WiFi101-FirmwareUpdater#to-update-ssl-certificates +// +// You can check on your device after a successful +// connection here: https://shiftr.io/try. +// +// by Gilberto Conti +// https://github.com/256dpi/arduino-mqtt + +#include +#include + +const char ssid[] = "ssid"; +const char pass[] = "pass"; + +WiFiSSLClient net; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + Serial.print("checking wifi..."); + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); + delay(1000); + } + + Serial.print("\nconnecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Serial.begin(115200); + WiFi.begin(ssid, pass); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + // + // MQTT brokers usually use port 8883 for secure connections. + client.begin("broker.shiftr.io", 8883, net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} diff --git a/lib/arduino-mqtt-2.3.3.02/examples/ArduinoWiFiShield/ArduinoWiFiShield.ino b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoWiFiShield/ArduinoWiFiShield.ino new file mode 100644 index 000000000..4aff769f4 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoWiFiShield/ArduinoWiFiShield.ino @@ -0,0 +1,68 @@ +// This example uses an Arduino Uno together with +// a WiFi Shield to connect to shiftr.io. +// +// You can check on your device after a successful +// connection here: https://shiftr.io/try. +// +// by Joël Gähwiler +// https://github.com/256dpi/arduino-mqtt + +#include +#include + +const char ssid[] = "ssid"; +const char pass[] = "pass"; + +WiFiClient net; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + Serial.print("checking wifi..."); + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); + delay(1000); + } + + Serial.print("\nconnecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Serial.begin(115200); + WiFi.begin(ssid, pass); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + client.begin("broker.shiftr.io", net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} diff --git a/lib/arduino-mqtt-2.3.3.02/examples/ArduinoYun/ArduinoYun.ino b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoYun/ArduinoYun.ino new file mode 100644 index 000000000..823bdff36 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoYun/ArduinoYun.ino @@ -0,0 +1,60 @@ +// This example uses an Arduino Yun or a Yun-Shield +// and the MQTTClient to connect to shiftr.io. +// +// You can check on your device after a successful +// connection here: https://shiftr.io/try. +// +// by Joël Gähwiler +// https://github.com/256dpi/arduino-mqtt + +#include +#include +#include + +BridgeClient net; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + Serial.print("connecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Bridge.begin(); + Serial.begin(115200); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + client.begin("broker.shiftr.io", net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} diff --git a/lib/arduino-mqtt-2.3.3.02/examples/ArduinoYunSecure/ArduinoYunSecure.ino b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoYunSecure/ArduinoYunSecure.ino new file mode 100644 index 000000000..46c068ab2 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/examples/ArduinoYunSecure/ArduinoYunSecure.ino @@ -0,0 +1,62 @@ +// This example uses an Arduino Yun or a Yun-Shield +// and the MQTTClient to connect to shiftr.io. +// +// You can check on your device after a successful +// connection here: https://shiftr.io/try. +// +// by Joël Gähwiler +// https://github.com/256dpi/arduino-mqtt + +#include +#include +#include + +BridgeSSLClient net; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + Serial.print("connecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Bridge.begin(); + Serial.begin(115200); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + // + // MQTT brokers usually use port 8883 for secure connections. + client.begin("broker.shiftr.io", 8883, net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} diff --git a/lib/arduino-mqtt-2.3.3.02/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino b/lib/arduino-mqtt-2.3.3.02/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino new file mode 100644 index 000000000..c6919280d --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino @@ -0,0 +1,69 @@ +// This example uses an ESP32 Development Board +// to connect to shiftr.io. +// +// You can check on your device after a successful +// connection here: https://shiftr.io/try. +// +// by Joël Gähwiler +// https://github.com/256dpi/arduino-mqtt + +#include +#include + +const char ssid[] = "ssid"; +const char pass[] = "pass"; + +WiFiClient net; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + Serial.print("checking wifi..."); + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); + delay(1000); + } + + Serial.print("\nconnecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Serial.begin(115200); + WiFi.begin(ssid, pass); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + client.begin("broker.shiftr.io", net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + delay(10); // <- fixes some issues with WiFi stability + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} diff --git a/lib/arduino-mqtt-2.3.3.02/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino b/lib/arduino-mqtt-2.3.3.02/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino new file mode 100644 index 000000000..cff75379e --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino @@ -0,0 +1,71 @@ +// This example uses an ESP32 Development Board +// to connect to shiftr.io. +// +// You can check on your device after a successful +// connection here: https://shiftr.io/try. +// +// by Joël Gähwiler +// https://github.com/256dpi/arduino-mqtt + +#include +#include + +const char ssid[] = "ssid"; +const char pass[] = "pass"; + +WiFiClientSecure net; +MQTTClient client; + +unsigned long lastMillis = 0; + +void connect() { + Serial.print("checking wifi..."); + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); + delay(1000); + } + + Serial.print("\nconnecting..."); + while (!client.connect("arduino", "try", "try")) { + Serial.print("."); + delay(1000); + } + + Serial.println("\nconnected!"); + + client.subscribe("/hello"); + // client.unsubscribe("/hello"); +} + +void messageReceived(String &topic, String &payload) { + Serial.println("incoming: " + topic + " - " + payload); +} + +void setup() { + Serial.begin(115200); + WiFi.begin(ssid, pass); + + // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. + // You need to set the IP address directly. + // + // MQTT brokers usually use port 8883 for secure connections. + client.begin("broker.shiftr.io", 8883, net); + client.onMessage(messageReceived); + + connect(); +} + +void loop() { + client.loop(); + delay(10); // <- fixes some issues with WiFi stability + + if (!client.connected()) { + connect(); + } + + // publish a message roughly every second. + if (millis() - lastMillis > 1000) { + lastMillis = millis(); + client.publish("/hello", "world"); + } +} diff --git a/lib/arduino-mqtt-2.3.3.02/library.properties b/lib/arduino-mqtt-2.3.3.02/library.properties new file mode 100644 index 000000000..a5ce4138a --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/library.properties @@ -0,0 +1,9 @@ +name=MQTT +version=2.3.3 +author=Joel Gaehwiler +maintainer=Joel Gaehwiler +sentence=MQTT library for Arduino +paragraph=This library bundles the lwmqtt client and adds a thin wrapper to get an Arduino like API. +category=Communication +url=https://github.com/256dpi/arduino-mqtt +architectures=* diff --git a/lib/arduino-mqtt-2.3.3.02/src/MQTTClient.h b/lib/arduino-mqtt-2.3.3.02/src/MQTTClient.h new file mode 100644 index 000000000..ecb69ec1d --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/src/MQTTClient.h @@ -0,0 +1,386 @@ +#ifndef MQTT_CLIENT_H +#define MQTT_CLIENT_H + +#include +#include +#include + +#include "system.h" + +class MQTTClient; + +typedef void (*MQTTClientCallbackSimple)(String &topic, String &payload); +typedef void (*MQTTClientCallbackAdvanced)(MQTTClient *client, char topic[], char bytes[], int length); + +typedef struct { + MQTTClient *client = nullptr; + MQTTClientCallbackSimple simple = nullptr; + MQTTClientCallbackAdvanced advanced = nullptr; +} MQTTClientCallback; + +static void MQTTClientHandler(lwmqtt_client_t * /*client*/, void *ref, lwmqtt_string_t topic, + lwmqtt_message_t message) { + // get callback + auto cb = (MQTTClientCallback *)ref; + + // null terminate topic + char terminated_topic[topic.len + 1]; + memcpy(terminated_topic, topic.data, topic.len); + terminated_topic[topic.len] = '\0'; + + // null terminate payload if available + if (message.payload != nullptr) { + message.payload[message.payload_len] = '\0'; + } + + // call the advanced callback and return if available + if (cb->advanced != nullptr) { + cb->advanced(cb->client, terminated_topic, (char *)message.payload, (int)message.payload_len); + return; + } + + // return if simple callback is not set + if (cb->simple == nullptr) { + return; + } + + // create topic string + String str_topic = String(terminated_topic); + + // create payload string + String str_payload; + if (message.payload != nullptr) { + str_payload = String((const char *)message.payload); + } + + // call simple callback + cb->simple(str_topic, str_payload); +} + +class MQTTClient { + private: + size_t bufSize = 0; + uint8_t *readBuf = nullptr; + uint8_t *writeBuf = nullptr; + + uint16_t keepAlive = 10; + bool cleanSession = true; + uint32_t timeout = 1000; + + Client *netClient = nullptr; + const char *hostname = nullptr; + int port = 0; + lwmqtt_will_t will = lwmqtt_default_will; + bool hasWill = false; + MQTTClientCallback callback; + + lwmqtt_arduino_network_t network = {nullptr}; + lwmqtt_arduino_timer_t timer1 = {0}; + lwmqtt_arduino_timer_t timer2 = {0}; + lwmqtt_client_t client; + + bool _connected = false; + lwmqtt_return_code_t _returnCode = (lwmqtt_return_code_t)0; + lwmqtt_err_t _lastError = (lwmqtt_err_t)0; + + public: + explicit MQTTClient(int bufSize = 128) { + memset(&client, 0, sizeof(client)); + this->bufSize = (size_t)bufSize; + this->readBuf = (uint8_t *)malloc((size_t)bufSize + 1); + this->writeBuf = (uint8_t *)malloc((size_t)bufSize); + } + + ~MQTTClient() { + free(this->readBuf); + free(this->writeBuf); + } + + void begin(const char hostname[], Client &client) { this->begin(hostname, 1883, client); } + + void begin(const char hostname[], int port, Client &client) { + // set hostname and port + this->setHost(hostname, port); + + // set client + this->netClient = &client; + + // initialize client + lwmqtt_init(&this->client, this->writeBuf, this->bufSize, this->readBuf, this->bufSize); + + // set timers + lwmqtt_set_timers(&this->client, &this->timer1, &this->timer2, lwmqtt_arduino_timer_set, lwmqtt_arduino_timer_get); + + // set network + lwmqtt_set_network(&this->client, &this->network, lwmqtt_arduino_network_read, lwmqtt_arduino_network_write); + + // set callback + lwmqtt_set_callback(&this->client, (void *)&this->callback, MQTTClientHandler); + } + + void onMessage(MQTTClientCallbackSimple cb) { + // set callback + this->callback.client = this; + this->callback.simple = cb; + this->callback.advanced = nullptr; + } + + void onMessageAdvanced(MQTTClientCallbackAdvanced cb) { + // set callback + this->callback.client = this; + this->callback.simple = nullptr; + this->callback.advanced = cb; + } + + void setHost(const char hostname[]) { this->setHost(hostname, 1883); } + + void setHost(const char hostname[], int port) { + // free hostname if set + if(this->hostname != nullptr) { + free((void *)this->hostname); + } + + // set hostname and port + this->hostname = strdup(hostname); + this->port = port; + } + + void setWill(const char topic[]) { this->setWill(topic, ""); } + + void setWill(const char topic[], const char payload[]) { this->setWill(topic, payload, false, 0); } + + void setWill(const char topic[], const char payload[], bool retained, int qos) { + this->hasWill = true; + this->will.topic = lwmqtt_string(topic); + this->will.payload = lwmqtt_string(payload); + this->will.retained = retained; + this->will.qos = (lwmqtt_qos_t)qos; + } + + void clearWill() { this->hasWill = false; } + + void setOptions(int keepAlive, bool cleanSession, int timeout) { + this->keepAlive = (uint16_t)keepAlive; + this->cleanSession = cleanSession; + this->timeout = (uint32_t)timeout; + } + + bool connect(const char clientId[]) { return this->connect(clientId, nullptr, nullptr); } + + bool connect(const char clientId[], const char username[]) { return this->connect(clientId, username, nullptr); } + + bool connect(const char clientId[], const char username[], const char password[]) { + // close left open connection if still connected + if (this->connected()) { + this->close(); + } + + // save client + this->network.client = this->netClient; + + // connect to host + if (this->netClient->connect(this->hostname, (uint16_t)this->port) < 0) { + return false; + } + + // prepare options + lwmqtt_options_t options = lwmqtt_default_options; + options.keep_alive = this->keepAlive; + options.clean_session = this->cleanSession; + options.client_id = lwmqtt_string(clientId); + + // set username and password if available + if (username != nullptr) { + options.username = lwmqtt_string(username); + + if (password != nullptr) { + options.password = lwmqtt_string(password); + } + } + + // prepare will reference + lwmqtt_will_t *will = nullptr; + if (this->hasWill) { + will = &this->will; + } + + // connect to broker + this->_lastError = lwmqtt_connect(&this->client, options, will, &this->_returnCode, this->timeout); + if (this->_lastError != LWMQTT_SUCCESS) { + // close connection + this->close(); + + return false; + } + + // set flag + this->_connected = true; + + return true; + } + + bool publish(const String &topic) { return this->publish(topic.c_str(), ""); } + + bool publish(const char topic[]) { return this->publish(topic, ""); } + + bool publish(const String &topic, const String &payload) { return this->publish(topic.c_str(), payload.c_str()); } + + bool publish(const String &topic, const String &payload, bool retained, int qos) { + return this->publish(topic.c_str(), payload.c_str(), retained, qos); + } + + bool publish(const char topic[], const String &payload) { return this->publish(topic, payload.c_str()); } + + bool publish(const char topic[], const String &payload, bool retained, int qos) { + return this->publish(topic, payload.c_str(), retained, qos); + } + + bool publish(const char topic[], const char payload[]) { + return this->publish(topic, (char *)payload, (int)strlen(payload)); + } + + bool publish(const char topic[], const char payload[], bool retained, int qos) { + return this->publish(topic, (char *)payload, (int)strlen(payload), retained, qos); + } + + bool publish(const char topic[], const char payload[], int length) { + return this->publish(topic, payload, length, false, 0); + } + + bool publish(const char topic[], const char payload[], int length, bool retained, int qos) { + // return immediately if not connected + if (!this->connected()) { + return false; + } + + // prepare message + lwmqtt_message_t message = lwmqtt_default_message; + message.payload = (uint8_t *)payload; + message.payload_len = (size_t)length; + message.retained = retained; + message.qos = lwmqtt_qos_t(qos); + + // publish message + this->_lastError = lwmqtt_publish(&this->client, lwmqtt_string(topic), message, this->timeout); + if (this->_lastError != LWMQTT_SUCCESS) { + // close connection + this->close(); + + return false; + } + + return true; + } + + bool subscribe(const String &topic) { return this->subscribe(topic.c_str()); } + + bool subscribe(const String &topic, int qos) { return this->subscribe(topic.c_str(), qos); } + + bool subscribe(const char topic[]) { return this->subscribe(topic, 0); } + + bool subscribe(const char topic[], int qos) { + // return immediately if not connected + if (!this->connected()) { + return false; + } + + // subscribe to topic + this->_lastError = lwmqtt_subscribe_one(&this->client, lwmqtt_string(topic), (lwmqtt_qos_t)qos, this->timeout); + if (this->_lastError != LWMQTT_SUCCESS) { + // close connection + this->close(); + + return false; + } + + return true; + } + + bool unsubscribe(const String &topic) { return this->unsubscribe(topic.c_str()); } + + bool unsubscribe(const char topic[]) { + // return immediately if not connected + if (!this->connected()) { + return false; + } + + // unsubscribe from topic + this->_lastError = lwmqtt_unsubscribe_one(&this->client, lwmqtt_string(topic), this->timeout); + if (this->_lastError != LWMQTT_SUCCESS) { + // close connection + this->close(); + + return false; + } + + return true; + } + + bool loop() { + // return immediately if not connected + if (!this->connected()) { + return false; + } + + // get available bytes on the network + auto available = (size_t)this->netClient->available(); + + // yield if data is available + if (available > 0) { + this->_lastError = lwmqtt_yield(&this->client, available, this->timeout); + if (this->_lastError != LWMQTT_SUCCESS) { + // close connection + this->close(); + + return false; + } + } + + // keep the connection alive + this->_lastError = lwmqtt_keep_alive(&this->client, this->timeout); + if (this->_lastError != LWMQTT_SUCCESS) { + // close connection + this->close(); + + return false; + } + + return true; + } + + bool connected() { + // a client is connected if the network is connected, a client is available and + // the connection has been properly initiated + return this->netClient != nullptr && this->netClient->connected() == 1 && this->_connected; + } + + lwmqtt_err_t lastError() { return this->_lastError; } + + lwmqtt_return_code_t returnCode() { return this->_returnCode; } + + bool disconnect() { + // return immediately if not connected anymore + if (!this->connected()) { + return false; + } + + // cleanly disconnect + this->_lastError = lwmqtt_disconnect(&this->client, this->timeout); + + // close + this->close(); + + return this->_lastError == LWMQTT_SUCCESS; + } + + private: + void close() { + // set flag + this->_connected = false; + + // close network + this->netClient->stop(); + } +}; + +#endif diff --git a/lib/arduino-mqtt-2.3.3.02/src/MQTTlw.h b/lib/arduino-mqtt-2.3.3.02/src/MQTTlw.h new file mode 100644 index 000000000..35652c45f --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/src/MQTTlw.h @@ -0,0 +1,6 @@ +#ifndef MQTT_H +#define MQTT_H + +#include "MQTTClient.h" + +#endif diff --git a/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/client.c b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/client.c new file mode 100644 index 000000000..b1772b9f7 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/client.c @@ -0,0 +1,618 @@ +#include "packet.h" + +void lwmqtt_init(lwmqtt_client_t *client, uint8_t *write_buf, size_t write_buf_size, uint8_t *read_buf, + size_t read_buf_size) { + client->last_packet_id = 1; + client->keep_alive_interval = 0; + client->pong_pending = false; + + client->write_buf = write_buf; + client->write_buf_size = write_buf_size; + client->read_buf = read_buf; + client->read_buf_size = read_buf_size; + + client->callback = NULL; + client->callback_ref = NULL; + + client->network = NULL; + client->network_read = NULL; + client->network_write = NULL; + + client->keep_alive_timer = NULL; + client->command_timer = NULL; + client->timer_set = NULL; + client->timer_get = NULL; +} + +void lwmqtt_set_network(lwmqtt_client_t *client, void *ref, lwmqtt_network_read_t read, lwmqtt_network_write_t write) { + client->network = ref; + client->network_read = read; + client->network_write = write; +} + +void lwmqtt_set_timers(lwmqtt_client_t *client, void *keep_alive_timer, void *command_timer, lwmqtt_timer_set_t set, + lwmqtt_timer_get_t get) { + client->keep_alive_timer = keep_alive_timer; + client->command_timer = command_timer; + client->timer_set = set; + client->timer_get = get; + + client->timer_set(client->keep_alive_timer, 0); + client->timer_set(client->command_timer, 0); +} + +void lwmqtt_set_callback(lwmqtt_client_t *client, void *ref, lwmqtt_callback_t cb) { + client->callback_ref = ref; + client->callback = cb; +} + +static uint16_t lwmqtt_get_next_packet_id(lwmqtt_client_t *client) { + // check overflow + if (client->last_packet_id == 65535) { + client->last_packet_id = 1; + return 1; + } + + // increment packet id + client->last_packet_id++; + + return client->last_packet_id; +} + +static lwmqtt_err_t lwmqtt_read_from_network(lwmqtt_client_t *client, size_t offset, size_t len) { + // check read buffer capacity + if (client->read_buf_size < offset + len) { + return LWMQTT_BUFFER_TOO_SHORT; + } + + // prepare counter + size_t read = 0; + + // read while data is missing + while (read < len) { + // check remaining time + int32_t remaining_time = client->timer_get(client->command_timer); + if (remaining_time <= 0) { + return LWMQTT_NETWORK_TIMEOUT; + } + + // read + size_t partial_read = 0; + lwmqtt_err_t err = client->network_read(client->network, client->read_buf + offset + read, len - read, + &partial_read, (uint32_t)remaining_time); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // increment counter + read += partial_read; + } + + return LWMQTT_SUCCESS; +} + +static lwmqtt_err_t lwmqtt_write_to_network(lwmqtt_client_t *client, size_t offset, size_t len) { + // prepare counter + size_t written = 0; + + // write while data is left + while (written < len) { + // check remaining time + int32_t remaining_time = client->timer_get(client->command_timer); + if (remaining_time <= 0) { + return LWMQTT_NETWORK_TIMEOUT; + } + + // write + size_t partial_write = 0; + lwmqtt_err_t err = client->network_write(client->network, client->write_buf + offset + written, len - written, + &partial_write, (uint32_t)remaining_time); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // increment counter + written += partial_write; + } + + return LWMQTT_SUCCESS; +} + +static lwmqtt_err_t lwmqtt_read_packet_in_buffer(lwmqtt_client_t *client, size_t *read, + lwmqtt_packet_type_t *packet_type) { + // preset packet type + *packet_type = LWMQTT_NO_PACKET; + + // read or wait for header byte + lwmqtt_err_t err = lwmqtt_read_from_network(client, 0, 1); + if (err == LWMQTT_NETWORK_TIMEOUT) { + // this is ok as no data has been read at all + return LWMQTT_SUCCESS; + } else if (err != LWMQTT_SUCCESS) { + return err; + } + + // detect packet type + err = lwmqtt_detect_packet_type(client->read_buf, 1, packet_type); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // prepare variables + size_t len = 0; + uint32_t rem_len = 0; + + do { + // adjust len + len++; + + // read next byte + err = lwmqtt_read_from_network(client, len, 1); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // attempt to detect remaining length + err = lwmqtt_detect_remaining_length(client->read_buf + 1, len, &rem_len); + } while (err == LWMQTT_BUFFER_TOO_SHORT); + + // check final error + if (err != LWMQTT_SUCCESS) { + return err; + } + + // read the rest of the buffer if needed + if (rem_len > 0) { + err = lwmqtt_read_from_network(client, 1 + len, rem_len); + if (err != LWMQTT_SUCCESS) { + return err; + } + } + + // adjust counter + *read += 1 + len + rem_len; + + return LWMQTT_SUCCESS; +} + +static lwmqtt_err_t lwmqtt_send_packet_in_buffer(lwmqtt_client_t *client, size_t length) { + // write to network + lwmqtt_err_t err = lwmqtt_write_to_network(client, 0, length); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // reset keep alive timer + client->timer_set(client->keep_alive_timer, client->keep_alive_interval); + + return LWMQTT_SUCCESS; +} + +static lwmqtt_err_t lwmqtt_cycle(lwmqtt_client_t *client, size_t *read, lwmqtt_packet_type_t *packet_type) { + // read next packet from the network + lwmqtt_err_t err = lwmqtt_read_packet_in_buffer(client, read, packet_type); + if (err != LWMQTT_SUCCESS) { + return err; + } else if (*packet_type == LWMQTT_NO_PACKET) { + return LWMQTT_SUCCESS; + } + + switch (*packet_type) { + // handle publish packets + case LWMQTT_PUBLISH_PACKET: { + // decode publish packet + bool dup; + uint16_t packet_id; + lwmqtt_string_t topic; + lwmqtt_message_t msg; + err = lwmqtt_decode_publish(client->read_buf, client->read_buf_size, &dup, &packet_id, &topic, &msg); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // call callback if set + if (client->callback != NULL) { + client->callback(client, client->callback_ref, topic, msg); + } + + // break early on qos zero + if (msg.qos == LWMQTT_QOS0) { + break; + } + + // define ack packet + lwmqtt_packet_type_t ack_type = LWMQTT_NO_PACKET; + if (msg.qos == LWMQTT_QOS1) { + ack_type = LWMQTT_PUBACK_PACKET; + } else if (msg.qos == LWMQTT_QOS2) { + ack_type = LWMQTT_PUBREC_PACKET; + } + + // encode ack packet + size_t len; + err = lwmqtt_encode_ack(client->write_buf, client->write_buf_size, &len, ack_type, false, packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // send ack packet + err = lwmqtt_send_packet_in_buffer(client, len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + break; + } + + // handle pubrec packets + case LWMQTT_PUBREC_PACKET: { + // decode pubrec packet + bool dup; + uint16_t packet_id; + err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, LWMQTT_PUBREC_PACKET, &dup, &packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // encode pubrel packet + size_t len; + err = lwmqtt_encode_ack(client->write_buf, client->write_buf_size, &len, LWMQTT_PUBREL_PACKET, 0, packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // send pubrel packet + err = lwmqtt_send_packet_in_buffer(client, len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + break; + } + + // handle pubrel packets + case LWMQTT_PUBREL_PACKET: { + // decode pubrec packet + bool dup; + uint16_t packet_id; + err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, LWMQTT_PUBREL_PACKET, &dup, &packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // encode pubcomp packet + size_t len; + err = lwmqtt_encode_ack(client->write_buf, client->write_buf_size, &len, LWMQTT_PUBCOMP_PACKET, 0, packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // send pubcomp packet + err = lwmqtt_send_packet_in_buffer(client, len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + break; + } + + // handle pingresp packets + case LWMQTT_PINGRESP_PACKET: { + // set flag + client->pong_pending = false; + + break; + } + + // handle all other packets + default: { break; } + } + + return LWMQTT_SUCCESS; +} + +static lwmqtt_err_t lwmqtt_cycle_until(lwmqtt_client_t *client, lwmqtt_packet_type_t *packet_type, size_t available, + lwmqtt_packet_type_t needle) { + // prepare counter + size_t read = 0; + + // loop until timeout has been reached + do { + // do one cycle + lwmqtt_err_t err = lwmqtt_cycle(client, &read, packet_type); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // return when one packet has been successfully read when no availability has been given + if (needle == LWMQTT_NO_PACKET && available == 0) { + return LWMQTT_SUCCESS; + } + + // otherwise check if needle has been found + if (*packet_type == needle) { + return LWMQTT_SUCCESS; + } + } while (client->timer_get(client->command_timer) > 0 && (available == 0 || read < available)); + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_yield(lwmqtt_client_t *client, size_t available, uint32_t timeout) { + // set command timer + client->timer_set(client->command_timer, timeout); + + // cycle until timeout has been reached + lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET; + lwmqtt_err_t err = lwmqtt_cycle_until(client, &packet_type, available, LWMQTT_NO_PACKET); + if (err != LWMQTT_SUCCESS) { + return err; + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_connect(lwmqtt_client_t *client, lwmqtt_options_t options, lwmqtt_will_t *will, + lwmqtt_return_code_t *return_code, uint32_t timeout) { + // set command timer + client->timer_set(client->command_timer, timeout); + + // save keep alive interval (take 75% to be a little earlier than actually needed) + client->keep_alive_interval = (uint32_t)(options.keep_alive * 750); + + // set keep alive timer + client->timer_set(client->keep_alive_timer, client->keep_alive_interval); + + // reset pong pending flag + client->pong_pending = false; + + // initialize return code + *return_code = LWMQTT_UNKNOWN_RETURN_CODE; + + // encode connect packet + size_t len; + lwmqtt_err_t err = lwmqtt_encode_connect(client->write_buf, client->write_buf_size, &len, options, will); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // send packet + err = lwmqtt_send_packet_in_buffer(client, len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // wait for connack packet + lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET; + err = lwmqtt_cycle_until(client, &packet_type, 0, LWMQTT_CONNACK_PACKET); + if (err != LWMQTT_SUCCESS) { + return err; + } else if (packet_type != LWMQTT_CONNACK_PACKET) { + return LWMQTT_MISSING_OR_WRONG_PACKET; + } + + // decode connack packet + bool session_present; + err = lwmqtt_decode_connack(client->read_buf, client->read_buf_size, &session_present, return_code); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // return error if connection was not accepted + if (*return_code != LWMQTT_CONNECTION_ACCEPTED) { + return LWMQTT_CONNECTION_DENIED; + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_subscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, lwmqtt_qos_t *qos, + uint32_t timeout) { + // set command timer + client->timer_set(client->command_timer, timeout); + + // encode subscribe packet + size_t len; + lwmqtt_err_t err = lwmqtt_encode_subscribe(client->write_buf, client->write_buf_size, &len, + lwmqtt_get_next_packet_id(client), count, topic_filter, qos); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // send packet + err = lwmqtt_send_packet_in_buffer(client, len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // wait for suback packet + lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET; + err = lwmqtt_cycle_until(client, &packet_type, 0, LWMQTT_SUBACK_PACKET); + if (err != LWMQTT_SUCCESS) { + return err; + } else if (packet_type != LWMQTT_SUBACK_PACKET) { + return LWMQTT_MISSING_OR_WRONG_PACKET; + } + + // decode packet + int suback_count = 0; + lwmqtt_qos_t granted_qos[count]; + uint16_t packet_id; + err = lwmqtt_decode_suback(client->read_buf, client->read_buf_size, &packet_id, count, &suback_count, granted_qos); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // check suback codes + for (int i = 0; i < suback_count; i++) { + if (granted_qos[i] == LWMQTT_QOS_FAILURE) { + return LWMQTT_FAILED_SUBSCRIPTION; + } + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_subscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, lwmqtt_qos_t qos, + uint32_t timeout) { + return lwmqtt_subscribe(client, 1, &topic_filter, &qos, timeout); +} + +lwmqtt_err_t lwmqtt_unsubscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, uint32_t timeout) { + // set command timer + client->timer_set(client->command_timer, timeout); + + // encode unsubscribe packet + size_t len; + lwmqtt_err_t err = lwmqtt_encode_unsubscribe(client->write_buf, client->write_buf_size, &len, + lwmqtt_get_next_packet_id(client), count, topic_filter); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // send unsubscribe packet + err = lwmqtt_send_packet_in_buffer(client, len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // wait for unsuback packet + lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET; + err = lwmqtt_cycle_until(client, &packet_type, 0, LWMQTT_UNSUBACK_PACKET); + if (err != LWMQTT_SUCCESS) { + return err; + } else if (packet_type != LWMQTT_UNSUBACK_PACKET) { + return LWMQTT_MISSING_OR_WRONG_PACKET; + } + + // decode unsuback packet + bool dup; + uint16_t packet_id; + err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, LWMQTT_UNSUBACK_PACKET, &dup, &packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_unsubscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, uint32_t timeout) { + return lwmqtt_unsubscribe(client, 1, &topic_filter, timeout); +} + +lwmqtt_err_t lwmqtt_publish(lwmqtt_client_t *client, lwmqtt_string_t topic, lwmqtt_message_t message, + uint32_t timeout) { + // set command timer + client->timer_set(client->command_timer, timeout); + + // add packet id if at least qos 1 + uint16_t packet_id = 0; + if (message.qos == LWMQTT_QOS1 || message.qos == LWMQTT_QOS2) { + packet_id = lwmqtt_get_next_packet_id(client); + } + + // encode publish packet + size_t len = 0; + lwmqtt_err_t err = + lwmqtt_encode_publish(client->write_buf, client->write_buf_size, &len, 0, packet_id, topic, message); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // send packet + err = lwmqtt_send_packet_in_buffer(client, len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // immediately return on qos zero + if (message.qos == LWMQTT_QOS0) { + return LWMQTT_SUCCESS; + } + + // define ack packet + lwmqtt_packet_type_t ack_type = LWMQTT_NO_PACKET; + if (message.qos == LWMQTT_QOS1) { + ack_type = LWMQTT_PUBACK_PACKET; + } else if (message.qos == LWMQTT_QOS2) { + ack_type = LWMQTT_PUBCOMP_PACKET; + } + + // wait for ack packet + lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET; + err = lwmqtt_cycle_until(client, &packet_type, 0, ack_type); + if (err != LWMQTT_SUCCESS) { + return err; + } else if (packet_type != ack_type) { + return LWMQTT_MISSING_OR_WRONG_PACKET; + } + + // decode ack packet + bool dup; + err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, ack_type, &dup, &packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_disconnect(lwmqtt_client_t *client, uint32_t timeout) { + // set command timer + client->timer_set(client->command_timer, timeout); + + // encode disconnect packet + size_t len; + lwmqtt_err_t err = lwmqtt_encode_zero(client->write_buf, client->write_buf_size, &len, LWMQTT_DISCONNECT_PACKET); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // send disconnected packet + err = lwmqtt_send_packet_in_buffer(client, len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_keep_alive(lwmqtt_client_t *client, uint32_t timeout) { + // set command timer + client->timer_set(client->command_timer, timeout); + + // return immediately if keep alive interval is zero + if (client->keep_alive_interval == 0) { + return LWMQTT_SUCCESS; + } + + // return immediately if no ping is due + if (client->timer_get(client->keep_alive_timer) > 0) { + return LWMQTT_SUCCESS; + } + + // a ping is due + + // fail immediately if a pong is already pending + if (client->pong_pending) { + return LWMQTT_PONG_TIMEOUT; + } + + // encode pingreq packet + size_t len; + lwmqtt_err_t err = lwmqtt_encode_zero(client->write_buf, client->write_buf_size, &len, LWMQTT_PINGREQ_PACKET); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // send packet + err = lwmqtt_send_packet_in_buffer(client, len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // set flag + client->pong_pending = true; + + return LWMQTT_SUCCESS; +} diff --git a/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/helpers.c b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/helpers.c new file mode 100644 index 000000000..9c78f4eaf --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/helpers.c @@ -0,0 +1,249 @@ +#include + +#include "helpers.h" + +uint8_t lwmqtt_read_bits(uint8_t byte, int pos, int num) { return (byte & (uint8_t)((~(0xFF << num)) << pos)) >> pos; } + +void lwmqtt_write_bits(uint8_t *byte, uint8_t value, int pos, int num) { + *byte = (*byte & ~(uint8_t)((~(0xFF << num)) << pos)) | (value << pos); +} + +lwmqtt_err_t lwmqtt_read_data(uint8_t **buf, const uint8_t *buf_end, uint8_t **data, size_t len) { + // check zero length + if (len == 0) { + *data = NULL; + return LWMQTT_SUCCESS; + } + + // check buffer size + if ((size_t)(buf_end - (*buf)) < len) { + return LWMQTT_BUFFER_TOO_SHORT; + } + + // read data + *data = *buf; + + // advance pointer + *buf += len; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_write_data(uint8_t **buf, const uint8_t *buf_end, uint8_t *data, size_t len) { + // check zero length + if (len == 0) { + return LWMQTT_SUCCESS; + } + + // check buffer size + if ((size_t)(buf_end - (*buf)) < len) { + return LWMQTT_BUFFER_TOO_SHORT; + } + + // write data + memcpy(*buf, data, len); + + // advance pointer + *buf += len; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_read_num(uint8_t **buf, const uint8_t *buf_end, uint16_t *num) { + // check buffer size + if ((size_t)(buf_end - (*buf)) < 2) { + *num = 0; + return LWMQTT_BUFFER_TOO_SHORT; + } + + // read two byte integer + *num = (uint16_t)256 * (*buf)[0] + (*buf)[1]; + + // adjust pointer + *buf += 2; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_write_num(uint8_t **buf, const uint8_t *buf_end, uint16_t num) { + // check buffer size + if ((size_t)(buf_end - (*buf)) < 2) { + return LWMQTT_BUFFER_TOO_SHORT; + } + + // write bytes + (*buf)[0] = (uint8_t)(num / 256); + (*buf)[1] = (uint8_t)(num % 256); + + // adjust pointer + *buf += 2; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_read_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t *str) { + // read length + uint16_t len; + lwmqtt_err_t err = lwmqtt_read_num(buf, buf_end, &len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // read data + err = lwmqtt_read_data(buf, buf_end, (uint8_t **)&str->data, len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // set length + str->len = len; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_write_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t str) { + // write string length + lwmqtt_err_t err = lwmqtt_write_num(buf, buf_end, str.len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write data + err = lwmqtt_write_data(buf, buf_end, (uint8_t *)str.data, str.len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_read_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t *byte) { + // check buffer size + if ((size_t)(buf_end - (*buf)) < 1) { + *byte = 0; + return LWMQTT_BUFFER_TOO_SHORT; + } + + // read byte + *byte = (*buf)[0]; + + // adjust pointer + *buf += 1; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_write_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t byte) { + // check buffer size + if ((size_t)(buf_end - (*buf)) < 1) { + return LWMQTT_BUFFER_TOO_SHORT; + } + + // write byte + (*buf)[0] = byte; + + // adjust pointer + *buf += 1; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_varnum_length(uint32_t varnum, int *len) { + if (varnum < 128) { + *len = 1; + return LWMQTT_SUCCESS; + } else if (varnum < 16384) { + *len = 2; + return LWMQTT_SUCCESS; + } else if (varnum < 2097151) { + *len = 3; + return LWMQTT_SUCCESS; + } else if (varnum < 268435455) { + *len = 4; + return LWMQTT_SUCCESS; + } else { + *len = 0; + return LWMQTT_VARNUM_OVERFLOW; + } +} + +lwmqtt_err_t lwmqtt_read_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t *varnum) { + // prepare last byte + uint8_t byte; + + // prepare multiplier + uint32_t multiplier = 1; + + // prepare length + size_t len = 0; + + // initialize number + *varnum = 0; + + // decode variadic number + do { + // increment length + len++; + + // return error if buffer is to small + if ((size_t)(buf_end - (*buf)) < len) { + return LWMQTT_BUFFER_TOO_SHORT; + } + + // return error if the length has overflowed + if (len > 4) { + return LWMQTT_VARNUM_OVERFLOW; + } + + // read byte + byte = (*buf)[len - 1]; + + // add byte to number + *varnum += (byte & 127) * multiplier; + + // increase multiplier + multiplier *= 128; + } while ((byte & 128) != 0); + + // adjust pointer + *buf += len; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_write_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t varnum) { + // init len counter + size_t len = 0; + + // encode variadic number + do { + // check overflow + if (len == 4) { + return LWMQTT_VARNUM_OVERFLOW; + } + + // return error if buffer is to small + if ((size_t)(buf_end - (*buf)) < len + 1) { + return LWMQTT_BUFFER_TOO_SHORT; + } + + // calculate current byte + uint8_t byte = (uint8_t)(varnum % 128); + + // change remaining length + varnum /= 128; + + // set the top bit of this byte if there are more to encode + if (varnum > 0) { + byte |= 0x80; + } + + // write byte + (*buf)[len++] = byte; + } while (varnum > 0); + + // adjust pointer + *buf += len; + + return LWMQTT_SUCCESS; +} diff --git a/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/helpers.h b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/helpers.h new file mode 100644 index 000000000..978eaf4a5 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/helpers.h @@ -0,0 +1,137 @@ +#ifndef LWMQTT_HELPERS_H +#define LWMQTT_HELPERS_H + +#include "lwmqtt.h" + +/** + * Reads bits from a byte. + * + * @param byte - The byte to read from. + * @param pos - The position of the first bit. + * @param num - The number of bits to read. + * @return The read bits as a byte. + */ +uint8_t lwmqtt_read_bits(uint8_t byte, int pos, int num); + +/** + * Write bits to a byte. + * + * @param byte - The byte to write bits to. + * @param value - The bits to write as a byte. + * @param pos - The position of the first bit. + * @param num - The number of bits to write. + */ +void lwmqtt_write_bits(uint8_t *byte, uint8_t value, int pos, int num); + +/** + * Reads arbitrary data from the specified buffer. The pointer is incremented by bytes read. + * + * @param buf - Pointer to the buffer. + * @param buf_end - Pointer to the end of the buffer. + * @param data - Pointer to beginning of data. + * @param len - The amount of data to read. + * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. + */ +lwmqtt_err_t lwmqtt_read_data(uint8_t **buf, const uint8_t *buf_end, uint8_t **data, size_t len); + +/** + * Writes arbitrary data to the specified buffer. The pointer is incremented by the bytes written. + * + * @param buf - Pointer to the buffer. + * @param buf_end - Pointer to the end of the buffer. + * @param data - Pointer to the to be written data. + * @param len - The amount of data to write. + * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. + */ +lwmqtt_err_t lwmqtt_write_data(uint8_t **buf, const uint8_t *buf_end, uint8_t *data, size_t len); + +/** + * Reads two byte number from the specified buffer. The pointer is incremented by two. + * + * @param buf - Pointer to the buffer. + * @param buf_end - Pointer to the end of the buffer. + * @param num - The read number. + * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. + */ +lwmqtt_err_t lwmqtt_read_num(uint8_t **buf, const uint8_t *buf_end, uint16_t *num); + +/** + * Writes a two byte number to the specified buffer. The pointer is incremented by two. + * + * @param buf - Pointer to the buffer. + * @param buf_end - Pointer to the end of the buffer. + * @param num - The number to write. + * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. + */ +lwmqtt_err_t lwmqtt_write_num(uint8_t **buf, const uint8_t *buf_end, uint16_t num); + +/** + * Reads a string from the specified buffer into the passed object. The pointer is incremented by the bytes read. + * + * @param buf - Pointer to the buffer. + * @param buf_end - Pointer to the end of the buffer. + * @param str - The object into which the data is to be read. + * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. + */ +lwmqtt_err_t lwmqtt_read_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t *str); + +/** + * Writes a string to the specified buffer. The pointer is incremented by the bytes written. + * + * @param buf - Pointer to the buffer. + * @param buf_end - Pointer to the end of the buffer. + * @param str - The string to write. + * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. + */ +lwmqtt_err_t lwmqtt_write_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t str); + +/** + * Reads one byte from the buffer. The pointer is incremented by one. + * + * @param buf - Pointer to the buffer. + * @param buf_end - Pointer to the end of the buffer. + * @param byte - The read byte. + * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. + */ +lwmqtt_err_t lwmqtt_read_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t *byte); + +/** + * Writes one byte to the specified buffer. The pointer is incremented by one. + * + * @param buf - Pointer to the buffer. + * @param buf_end - Pointer to the end of the buffer. + * @param byte - The byte to write. + * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. + */ +lwmqtt_err_t lwmqtt_write_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t byte); + +/** + * Returns the amount of bytes required by the variable number. + * + * @param varnum - The number to check. + * @param len - The required length; + * @return LWMQTT_SUCCESS or LWMQTT_VARNUM_OVERFLOW. + */ +lwmqtt_err_t lwmqtt_varnum_length(uint32_t varnum, int *len); + +/** + * Reads a variable number from the specified buffer. The pointer is incremented by the bytes read. + * + * @param buf - Pointer to the buffer. + * @param buf_end - Pointer to the end of the buffer. + * @param varnum - The read varnum. + * @return LWMQTT_SUCCESS, LWMQTT_BUFFER_TOO_SHORT or LWMQTT_VARNUM_OVERFLOW. + */ +lwmqtt_err_t lwmqtt_read_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t *varnum); + +/** + * Writes a variable number to the specified buffer. The pointer is incremented by the bytes written. + * + * @param buf - Pointer to the buffer. + * @param buf_end - Pointer to the end of the buffer. + * @param varnum - The number to write. + * @return LWMQTT_SUCCESS, LWMQTT_BUFFER_TOO_SHORT or LWMQTT_VARNUM_OVERFLOW. + */ +lwmqtt_err_t lwmqtt_write_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t varnum); + +#endif diff --git a/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/lwmqtt.h b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/lwmqtt.h new file mode 100644 index 000000000..7a7f142cc --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/lwmqtt.h @@ -0,0 +1,381 @@ +#ifndef LWMQTT_H +#define LWMQTT_H + +#include +#include +#include + +/** + * The error type used by all exposed APIs. + * + * If a function returns an error that operates on a connected client (e.g publish, keep_alive, etc.) the caller should + * switch into a disconnected state, close and cleanup the current connection and start over by creating a new + * connection. + */ +typedef enum { + LWMQTT_SUCCESS = 0, + LWMQTT_BUFFER_TOO_SHORT = -1, + LWMQTT_VARNUM_OVERFLOW = -2, + LWMQTT_NETWORK_FAILED_CONNECT = -3, + LWMQTT_NETWORK_TIMEOUT = -4, + LWMQTT_NETWORK_FAILED_READ = -5, + LWMQTT_NETWORK_FAILED_WRITE = -6, + LWMQTT_REMAINING_LENGTH_OVERFLOW = -7, + LWMQTT_REMAINING_LENGTH_MISMATCH = -8, + LWMQTT_MISSING_OR_WRONG_PACKET = -9, + LWMQTT_CONNECTION_DENIED = -10, + LWMQTT_FAILED_SUBSCRIPTION = -11, + LWMQTT_SUBACK_ARRAY_OVERFLOW = -12, + LWMQTT_PONG_TIMEOUT = -13, +} lwmqtt_err_t; + +/** + * A common string object. + */ +typedef struct { + uint16_t len; + char *data; +} lwmqtt_string_t; + +/** + * The initializer for string objects. + */ +#define lwmqtt_default_string \ + { 0, NULL } + +/** + * Returns a string object for the passed C string. + * + * @param str - The C string. + * @return A string object. + */ +lwmqtt_string_t lwmqtt_string(const char *str); + +/** + * Compares a string object to a C string. + * + * @param a - The string object to compare. + * @param b - The C string to compare. + * @return Similarity e.g. strcmp(). + */ +int lwmqtt_strcmp(lwmqtt_string_t a, const char *b); + +/** + * The available QOS levels. + */ +typedef enum { LWMQTT_QOS0 = 0, LWMQTT_QOS1 = 1, LWMQTT_QOS2 = 2, LWMQTT_QOS_FAILURE = 128 } lwmqtt_qos_t; + +/** + * The message object used to publish and receive messages. + */ +typedef struct { + lwmqtt_qos_t qos; + bool retained; + uint8_t *payload; + size_t payload_len; +} lwmqtt_message_t; + +/** + * The initializer for message objects. + */ +#define lwmqtt_default_message \ + { LWMQTT_QOS0, false, NULL, 0 } + +/** + * Forward declaration of the client object. + */ +typedef struct lwmqtt_client_t lwmqtt_client_t; + +/** + * The callback used to read from a network object. + * + * The callbacks is expected to read up to the amount of bytes in to the passed buffer. It should block the specified + * timeout and wait for more incoming data. + * + * @param ref - A custom reference. + * @param buf - The buffer. + * @param len - The length of the buffer. + * @param read - Variable that must be set with the amount of read bytes. + * @param timeout - The timeout in milliseconds for the operation. + */ +typedef lwmqtt_err_t (*lwmqtt_network_read_t)(void *ref, uint8_t *buf, size_t len, size_t *read, uint32_t timeout); + +/** + * The callback used to write to a network object. + * + * The callback is expected to write up to the amount of bytes from the passed buffer. It should wait up to the + * specified timeout to write the specified data to the network. + * + * @param ref - A custom reference. + * @param buf - The buffer. + * @param len - The length of the buffer. + * @param sent - Variable that must be set with the amount of written bytes. + * @param timeout - The timeout in milliseconds for the operation. + */ +typedef lwmqtt_err_t (*lwmqtt_network_write_t)(void *ref, uint8_t *buf, size_t len, size_t *sent, uint32_t timeout); + +/** + * The callback used to set a timer. + * + * @param ref - A custom reference. + * @param timeout - The amount of milliseconds until the deadline. + */ +typedef void (*lwmqtt_timer_set_t)(void *ref, uint32_t timeout); + +/** + * The callback used to get a timers value. + * + * @param - A custom reference. + * @return The amount of milliseconds until the deadline. May return negative numbers if the deadline has been reached. + */ +typedef int32_t (*lwmqtt_timer_get_t)(void *ref); + +/** + * The callback used to forward incoming messages. + * + * Note: The callback is mostly executed because of a call to lwmqtt_yield() that processes incoming messages. However, + * it is possible that the callback is also executed during a call to lwmqtt_subscribe(), lwmqtt_publish() or + * lwmqtt_unsubscribe() if incoming messages are received between the required acknowledgements. It is therefore not + * recommended to call any further lwmqtt methods in the callback as this might result in weird call stacks. The + * callback should place the received messages in a queue and dispatch them after the caller has returned. + */ +typedef void (*lwmqtt_callback_t)(lwmqtt_client_t *client, void *ref, lwmqtt_string_t str, lwmqtt_message_t msg); + +/** + * The client object. + */ +struct lwmqtt_client_t { + uint16_t last_packet_id; + uint32_t keep_alive_interval; + bool pong_pending; + + size_t write_buf_size, read_buf_size; + uint8_t *write_buf, *read_buf; + + lwmqtt_callback_t callback; + void *callback_ref; + + void *network; + lwmqtt_network_read_t network_read; + lwmqtt_network_write_t network_write; + + void *keep_alive_timer; + void *command_timer; + lwmqtt_timer_set_t timer_set; + lwmqtt_timer_get_t timer_get; +}; + +/** + * Will initialize the specified client object. + * + * @param client - The client object. + * @param write_buf - The write buffer. + * @param write_buf_size - The write buffer size. + * @param read_buf - The read buffer. + * @param read_buf_size - The read buffer size. + */ +void lwmqtt_init(lwmqtt_client_t *client, uint8_t *write_buf, size_t write_buf_size, uint8_t *read_buf, + size_t read_buf_size); + +/** + * Will set the network reference and callbacks for this client object. + * + * @param client - The client object. + * @param ref - The reference to the network object. + * @param read - The read callback. + * @param write - The write callback. + */ +void lwmqtt_set_network(lwmqtt_client_t *client, void *ref, lwmqtt_network_read_t read, lwmqtt_network_write_t write); + +/** + * Will set the timer references and callbacks for this client object. + * + * @param client - The client object. + * @param keep_alive_timer - The reference to the keep alive timer. + * @param command_timer - The reference to the command timer. + * @param set - The set callback. + * @param get - The get callback. + */ +void lwmqtt_set_timers(lwmqtt_client_t *client, void *keep_alive_timer, void *command_timer, lwmqtt_timer_set_t set, + lwmqtt_timer_get_t get); + +/** + * Will set the callback used to receive incoming messages. + * + * @param client - The client object. + * @param ref - A custom reference that will passed to the callback. + * @param cb - The callback to be called. + */ +void lwmqtt_set_callback(lwmqtt_client_t *client, void *ref, lwmqtt_callback_t cb); + +/** + * The object defining the last will of a client. + */ +typedef struct { + lwmqtt_string_t topic; + lwmqtt_qos_t qos; + bool retained; + lwmqtt_string_t payload; +} lwmqtt_will_t; + +/** + * The default initializer for the will object. + */ +#define lwmqtt_default_will \ + { lwmqtt_default_string, LWMQTT_QOS0, false, lwmqtt_default_string } + +/** + * The object containing the connection options for a client. + */ +typedef struct { + lwmqtt_string_t client_id; + uint16_t keep_alive; + bool clean_session; + lwmqtt_string_t username; + lwmqtt_string_t password; +} lwmqtt_options_t; + +/** + * The default initializer for the options object. + */ +#define lwmqtt_default_options \ + { lwmqtt_default_string, 60, true, lwmqtt_default_string, lwmqtt_default_string } + +/** + * The available return codes transported by the connack packet. + */ +typedef enum { + LWMQTT_CONNECTION_ACCEPTED = 0, + LWMQTT_UNACCEPTABLE_PROTOCOL = 1, + LWMQTT_IDENTIFIER_REJECTED = 2, + LWMQTT_SERVER_UNAVAILABLE = 3, + LWMQTT_BAD_USERNAME_OR_PASSWORD = 4, + LWMQTT_NOT_AUTHORIZED = 5, + LWMQTT_UNKNOWN_RETURN_CODE = 6 +} lwmqtt_return_code_t; + +/** + * Will send a connect packet and wait for a connack response and set the return code. + * + * The network object must already be connected to the server. An error is returned if the broker rejects the + * connection. + * + * @param client - The client object. + * @param options - The options object. + * @param will - The will object. + * @param return_code - The variable that will receive the return code. + * @param timeout - The command timeout. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_connect(lwmqtt_client_t *client, lwmqtt_options_t options, lwmqtt_will_t *will, + lwmqtt_return_code_t *return_code, uint32_t timeout); + +/** + * Will send a publish packet and wait for all acks to complete. + * + * Note: The message callback might be called with incoming messages as part of this call. + * + * @param client - The client object. + * @param topic - The topic. + * @param message - The message. + * @param timeout - The command timeout. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_publish(lwmqtt_client_t *client, lwmqtt_string_t topic, lwmqtt_message_t msg, uint32_t timeout); + +/** + * Will send a subscribe packet with multiple topic filters plus QOS levels and wait for the suback to complete. + * + * Note: The message callback might be called with incoming messages as part of this call. + * + * @param client - The client object. + * @param count - The number of topic filters and QOS levels. + * @param topic_filter - The list of topic filters. + * @param qos - The list of QOS levels. + * @param timeout - The command timeout. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_subscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, lwmqtt_qos_t *qos, + uint32_t timeout); + +/** + * Will send a subscribe packet with a single topic filter plus QOS level and wait for the suback to complete. + * + * Note: The message callback might be called with incoming messages as part of this call. + * + * @param client - The client object. + * @param topic_filter - The topic filter. + * @param qos - The QOS level. + * @param timeout - The command timeout. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_subscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, lwmqtt_qos_t qos, + uint32_t timeout); + +/** + * Will send an unsubscribe packet with multiple topic filters and wait for the unsuback to complete. + * + * Note: The message callback might be called with incoming messages as part of this call. + * + * @param client - The client object. + * @param count - The number of topic filters. + * @param topic_filter - The topic filter. + * @param timeout - The command timeout. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_unsubscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, uint32_t timeout); + +/** + * Will send an unsubscribe packet with a single topic filter and wait for the unsuback to complete. + * + * Note: The message callback might be called with incoming messages as part of this call. + * + * @param client - The client object. + * @param topic_filter - The topic filter. + * @param timeout - The command timeout. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_unsubscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, uint32_t timeout); + +/** + * Will send a disconnect packet and finish the client. + * + * @param client - The client object. + * @param timeout - The command timeout. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_disconnect(lwmqtt_client_t *client, uint32_t timeout); + +/** + * Will yield control to the client and receive incoming packets from the network. + * + * Single-threaded applications may peek on the network and assess if data is available to read before calling yield and + * potentially block until the timeout is reached. Multi-threaded applications may select on the socket and block until + * data is available and then yield to the client if data is available. All applications may specify the amount of bytes + * available to read in order to constrain the yield to only receive packets that are already in-flight. + * + * If no availability info is given the yield will return after one packet has been successfully read or the deadline + * has been reached but no single bytes has been received. + * + * Note: The message callback might be called with incoming messages as part of this call. + * + * @param client - The client object. + * @param available - The available bytes to read. + * @param timeout - The command timeout. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_yield(lwmqtt_client_t *client, size_t available, uint32_t timeout); + +/** + * Will yield control to the client to keep the connection alive. + * + * This functions must be called at a rate slightly lower than 25% of the configured keep alive. If keep alive is zero, + * the function must not be called at all. + * + * @param client - The client object. + * @param timeout - The command timeout. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_keep_alive(lwmqtt_client_t *client, uint32_t timeout); + +#endif // LWMQTT_H diff --git a/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/packet.c b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/packet.c new file mode 100644 index 000000000..512b44d94 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/packet.c @@ -0,0 +1,742 @@ +#include "packet.h" + +lwmqtt_err_t lwmqtt_detect_packet_type(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t *packet_type) { + // set default packet type + *packet_type = LWMQTT_NO_PACKET; + + // prepare pointer + uint8_t *buf_ptr = buf; + uint8_t *buf_end = buf + buf_len; + + // prepare header + uint8_t header; + + // read header + lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // get packet type + *packet_type = (lwmqtt_packet_type_t)lwmqtt_read_bits(header, 4, 4); + + // check if packet type is correct and can be received + switch (*packet_type) { + case LWMQTT_CONNACK_PACKET: + case LWMQTT_PUBLISH_PACKET: + case LWMQTT_PUBACK_PACKET: + case LWMQTT_PUBREC_PACKET: + case LWMQTT_PUBREL_PACKET: + case LWMQTT_PUBCOMP_PACKET: + case LWMQTT_SUBACK_PACKET: + case LWMQTT_UNSUBACK_PACKET: + case LWMQTT_PINGRESP_PACKET: + return LWMQTT_SUCCESS; + default: + *packet_type = LWMQTT_NO_PACKET; + return LWMQTT_MISSING_OR_WRONG_PACKET; + } +} + +lwmqtt_err_t lwmqtt_detect_remaining_length(uint8_t *buf, size_t buf_len, uint32_t *rem_len) { + // prepare pointer + uint8_t *ptr = buf; + + // attempt to decode remaining length + lwmqtt_err_t err = lwmqtt_read_varnum(&ptr, buf + buf_len, rem_len); + if (err == LWMQTT_VARNUM_OVERFLOW) { + *rem_len = 0; + return LWMQTT_REMAINING_LENGTH_OVERFLOW; + } else if (err != LWMQTT_SUCCESS) { + *rem_len = 0; + return err; + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_encode_connect(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_options_t options, + lwmqtt_will_t *will) { + // prepare pointers + uint8_t *buf_ptr = buf; + uint8_t *buf_end = buf + buf_len; + + // fixed header is 10 + uint32_t rem_len = 10; + + // add client id to remaining length + rem_len += options.client_id.len + 2; + + // add will if present to remaining length + if (will != NULL) { + rem_len += will->topic.len + 2 + will->payload.len + 2; + } + + // add username if present to remaining length + if (options.username.len > 0) { + rem_len += options.username.len + 2; + + // add password if present to remaining length + if (options.password.len > 0) { + rem_len += options.password.len + 2; + } + } + + // check remaining length length + int rem_len_len; + lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len); + if (err == LWMQTT_VARNUM_OVERFLOW) { + return LWMQTT_REMAINING_LENGTH_OVERFLOW; + } + + // prepare header + uint8_t header = 0; + lwmqtt_write_bits(&header, LWMQTT_CONNECT_PACKET, 4, 4); + + // write header + err = lwmqtt_write_byte(&buf_ptr, buf_end, header); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write remaining length + err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write version string + err = lwmqtt_write_string(&buf_ptr, buf_end, lwmqtt_string("MQTT")); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write version number + err = lwmqtt_write_byte(&buf_ptr, buf_end, 4); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // prepare flags + uint8_t flags = 0; + + // set clean session + lwmqtt_write_bits(&flags, (uint8_t)(options.clean_session), 1, 1); + + // set will flags if present + if (will != NULL) { + lwmqtt_write_bits(&flags, 1, 2, 1); + lwmqtt_write_bits(&flags, will->qos, 3, 2); + lwmqtt_write_bits(&flags, (uint8_t)(will->retained), 5, 1); + } + + // set username flag if present + if (options.username.len > 0) { + lwmqtt_write_bits(&flags, 1, 7, 1); + + // set password flag if present + if (options.password.len > 0) { + lwmqtt_write_bits(&flags, 1, 6, 1); + } + } + + // write flags + err = lwmqtt_write_byte(&buf_ptr, buf_end, flags); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write keep alive + err = lwmqtt_write_num(&buf_ptr, buf_end, options.keep_alive); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write client id + err = lwmqtt_write_string(&buf_ptr, buf_end, options.client_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write will if present + if (will != NULL) { + // write topic + err = lwmqtt_write_string(&buf_ptr, buf_end, will->topic); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write payload length + err = lwmqtt_write_num(&buf_ptr, buf_end, (uint16_t)will->payload.len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write payload + err = lwmqtt_write_data(&buf_ptr, buf_end, (uint8_t *)will->payload.data, will->payload.len); + if (err != LWMQTT_SUCCESS) { + return err; + } + } + + // write username if present + if (options.username.len > 0) { + err = lwmqtt_write_string(&buf_ptr, buf_end, options.username); + if (err != LWMQTT_SUCCESS) { + return err; + } + } + + // write password if present + if (options.username.len > 0 && options.password.len > 0) { + err = lwmqtt_write_string(&buf_ptr, buf_end, options.password); + if (err != LWMQTT_SUCCESS) { + return err; + } + } + + // set written length + *len = buf_ptr - buf; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_decode_connack(uint8_t *buf, size_t buf_len, bool *session_present, + lwmqtt_return_code_t *return_code) { + // prepare pointers + uint8_t *buf_ptr = buf; + uint8_t *buf_end = buf + buf_len; + + // read header + uint8_t header; + lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // check packet type + if (lwmqtt_read_bits(header, 4, 4) != LWMQTT_CONNACK_PACKET) { + return LWMQTT_MISSING_OR_WRONG_PACKET; + } + + // read remaining length + uint32_t rem_len; + err = lwmqtt_read_varnum(&buf_ptr, buf_end, &rem_len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // check remaining length + if (rem_len != 2) { + return LWMQTT_REMAINING_LENGTH_MISMATCH; + } + + // read flags + uint8_t flags; + err = lwmqtt_read_byte(&buf_ptr, buf_end, &flags); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // read return code + uint8_t raw_return_code; + err = lwmqtt_read_byte(&buf_ptr, buf_end, &raw_return_code); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // get session present + *session_present = lwmqtt_read_bits(flags, 7, 1) == 1; + + // get return code + switch (raw_return_code) { + case 0: + *return_code = LWMQTT_CONNECTION_ACCEPTED; + break; + case 1: + *return_code = LWMQTT_UNACCEPTABLE_PROTOCOL; + break; + case 2: + *return_code = LWMQTT_IDENTIFIER_REJECTED; + break; + case 3: + *return_code = LWMQTT_SERVER_UNAVAILABLE; + break; + case 4: + *return_code = LWMQTT_BAD_USERNAME_OR_PASSWORD; + break; + case 5: + *return_code = LWMQTT_NOT_AUTHORIZED; + break; + default: + *return_code = LWMQTT_UNKNOWN_RETURN_CODE; + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_encode_zero(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type) { + // prepare pointer + uint8_t *buf_ptr = buf; + uint8_t *buf_end = buf + buf_len; + + // write header + uint8_t header = 0; + lwmqtt_write_bits(&header, packet_type, 4, 4); + lwmqtt_err_t err = lwmqtt_write_byte(&buf_ptr, buf_end, header); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write remaining length + err = lwmqtt_write_varnum(&buf_ptr, buf_end, 0); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // set length + *len = buf_ptr - buf; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_decode_ack(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t packet_type, bool *dup, + uint16_t *packet_id) { + // prepare pointer + uint8_t *buf_ptr = buf; + uint8_t *buf_end = buf + buf_len; + + // read header + uint8_t header = 0; + lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // check packet type + if (lwmqtt_read_bits(header, 4, 4) != packet_type) { + return LWMQTT_MISSING_OR_WRONG_PACKET; + } + + // get dup + *dup = lwmqtt_read_bits(header, 3, 1) == 1; + + // read remaining length + uint32_t rem_len; + err = lwmqtt_read_varnum(&buf_ptr, buf + buf_len, &rem_len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // check remaining length + if (rem_len != 2) { + return LWMQTT_REMAINING_LENGTH_MISMATCH; + } + + // read packet id + err = lwmqtt_read_num(&buf_ptr, buf_end, packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_encode_ack(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type, bool dup, + uint16_t packet_id) { + // prepare pointer + uint8_t *buf_ptr = buf; + uint8_t *buf_end = buf + buf_len; + + // prepare header + uint8_t header = 0; + + // set packet type + lwmqtt_write_bits(&header, packet_type, 4, 4); + + // set dup + lwmqtt_write_bits(&header, (uint8_t)(dup), 3, 1); + + // set qos + lwmqtt_write_bits(&header, (uint8_t)(packet_type == LWMQTT_PUBREL_PACKET ? LWMQTT_QOS1 : LWMQTT_QOS0), 1, 2); + + // write header + lwmqtt_err_t err = lwmqtt_write_byte(&buf_ptr, buf_end, header); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write remaining length + err = lwmqtt_write_varnum(&buf_ptr, buf_end, 2); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write packet id + err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // set written length + *len = buf_ptr - buf; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_decode_publish(uint8_t *buf, size_t buf_len, bool *dup, uint16_t *packet_id, lwmqtt_string_t *topic, + lwmqtt_message_t *msg) { + // prepare pointer + uint8_t *buf_ptr = buf; + uint8_t *buf_end = buf + buf_len; + + // read header + uint8_t header; + lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // check packet type + if (lwmqtt_read_bits(header, 4, 4) != LWMQTT_PUBLISH_PACKET) { + return LWMQTT_MISSING_OR_WRONG_PACKET; + } + + // get dup + *dup = lwmqtt_read_bits(header, 3, 1) == 1; + + // get retained + msg->retained = lwmqtt_read_bits(header, 0, 1) == 1; + + // get qos + switch (lwmqtt_read_bits(header, 1, 2)) { + case 0: + msg->qos = LWMQTT_QOS0; + break; + case 1: + msg->qos = LWMQTT_QOS1; + break; + case 2: + msg->qos = LWMQTT_QOS2; + break; + default: + msg->qos = LWMQTT_QOS0; + break; + } + + // read remaining length + uint32_t rem_len; + err = lwmqtt_read_varnum(&buf_ptr, buf_end, &rem_len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // check remaining length (topic length) + if (rem_len < 2) { + return LWMQTT_REMAINING_LENGTH_MISMATCH; + } + + // check buffer capacity + if ((uint32_t)(buf_end - buf_ptr) < rem_len) { + return LWMQTT_BUFFER_TOO_SHORT; + } + + // reset buf end + buf_end = buf_ptr + rem_len; + + // read topic + err = lwmqtt_read_string(&buf_ptr, buf_end, topic); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // read packet id if qos is at least 1 + if (msg->qos > 0) { + err = lwmqtt_read_num(&buf_ptr, buf_end, packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + } else { + *packet_id = 0; + } + + // set payload length + msg->payload_len = buf_end - buf_ptr; + + // read payload + err = lwmqtt_read_data(&buf_ptr, buf_end, &msg->payload, buf_end - buf_ptr); + if (err != LWMQTT_SUCCESS) { + return err; + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_encode_publish(uint8_t *buf, size_t buf_len, size_t *len, bool dup, uint16_t packet_id, + lwmqtt_string_t topic, lwmqtt_message_t msg) { + // prepare pointer + uint8_t *buf_ptr = buf; + uint8_t *buf_end = buf + buf_len; + + // calculate remaining length + uint32_t rem_len = 2 + topic.len + (uint32_t)msg.payload_len; + if (msg.qos > 0) { + rem_len += 2; + } + + // check remaining length length + int rem_len_len; + lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len); + if (err == LWMQTT_VARNUM_OVERFLOW) { + return LWMQTT_REMAINING_LENGTH_OVERFLOW; + } + + // prepare header + uint8_t header = 0; + + // set packet type + lwmqtt_write_bits(&header, LWMQTT_PUBLISH_PACKET, 4, 4); + + // set dup + lwmqtt_write_bits(&header, (uint8_t)(dup), 3, 1); + + // set qos + lwmqtt_write_bits(&header, msg.qos, 1, 2); + + // set retained + lwmqtt_write_bits(&header, (uint8_t)(msg.retained), 0, 1); + + // write header + err = lwmqtt_write_byte(&buf_ptr, buf_end, header); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write remaining length + err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write topic + err = lwmqtt_write_string(&buf_ptr, buf_end, topic); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write packet id if qos is at least 1 + if (msg.qos > 0) { + err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + } + + // write payload + err = lwmqtt_write_data(&buf_ptr, buf_end, msg.payload, msg.payload_len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // set length + *len = buf_ptr - buf; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_encode_subscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count, + lwmqtt_string_t *topic_filters, lwmqtt_qos_t *qos_levels) { + // prepare pointer + uint8_t *buf_ptr = buf; + uint8_t *buf_end = buf + buf_len; + + // calculate remaining length + uint32_t rem_len = 2; + for (int i = 0; i < count; i++) { + rem_len += 2 + topic_filters[i].len + 1; + } + + // check remaining length length + int rem_len_len; + lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len); + if (err == LWMQTT_VARNUM_OVERFLOW) { + return LWMQTT_REMAINING_LENGTH_OVERFLOW; + } + + // prepare header + uint8_t header = 0; + + // set packet type + lwmqtt_write_bits(&header, LWMQTT_SUBSCRIBE_PACKET, 4, 4); + + // set qos + lwmqtt_write_bits(&header, LWMQTT_QOS1, 1, 2); + + // write header + err = lwmqtt_write_byte(&buf_ptr, buf_end, header); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write remaining length + err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write packet id + err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write all subscriptions + for (int i = 0; i < count; i++) { + // write topic + err = lwmqtt_write_string(&buf_ptr, buf_end, topic_filters[i]); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write qos level + err = lwmqtt_write_byte(&buf_ptr, buf_end, (uint8_t)qos_levels[i]); + if (err != LWMQTT_SUCCESS) { + return err; + } + } + + // set length + *len = buf_ptr - buf; + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_decode_suback(uint8_t *buf, size_t buf_len, uint16_t *packet_id, int max_count, int *count, + lwmqtt_qos_t *granted_qos_levels) { + // prepare pointer + uint8_t *buf_ptr = buf; + uint8_t *buf_end = buf + buf_len; + + // read header + uint8_t header; + lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // check packet type + if (lwmqtt_read_bits(header, 4, 4) != LWMQTT_SUBACK_PACKET) { + return LWMQTT_MISSING_OR_WRONG_PACKET; + } + + // read remaining length + uint32_t rem_len; + err = lwmqtt_read_varnum(&buf_ptr, buf_end, &rem_len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // check remaining length (packet id + min. one suback code) + if (rem_len < 3) { + return LWMQTT_REMAINING_LENGTH_MISMATCH; + } + + // read packet id + err = lwmqtt_read_num(&buf_ptr, buf_end, packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // read all suback codes + for (*count = 0; *count < (int)rem_len - 2; (*count)++) { + // check max count + if (*count > max_count) { + return LWMQTT_SUBACK_ARRAY_OVERFLOW; + } + + // read qos level + uint8_t raw_qos_level; + err = lwmqtt_read_byte(&buf_ptr, buf_end, &raw_qos_level); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // set qos level + switch (raw_qos_level) { + case 0: + granted_qos_levels[*count] = LWMQTT_QOS0; + break; + case 1: + granted_qos_levels[*count] = LWMQTT_QOS1; + break; + case 2: + granted_qos_levels[*count] = LWMQTT_QOS2; + break; + default: + granted_qos_levels[*count] = LWMQTT_QOS_FAILURE; + break; + } + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_encode_unsubscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count, + lwmqtt_string_t *topic_filters) { + // prepare pointer + uint8_t *buf_ptr = buf; + uint8_t *buf_end = buf + buf_len; + + // calculate remaining length + uint32_t rem_len = 2; + for (int i = 0; i < count; i++) { + rem_len += 2 + topic_filters[i].len; + } + + // check remaining length length + int rem_len_len; + lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len); + if (err == LWMQTT_VARNUM_OVERFLOW) { + return LWMQTT_REMAINING_LENGTH_OVERFLOW; + } + + // prepare header + uint8_t header = 0; + + // set packet type + lwmqtt_write_bits(&header, LWMQTT_UNSUBSCRIBE_PACKET, 4, 4); + + // set qos + lwmqtt_write_bits(&header, LWMQTT_QOS1, 1, 2); + + // write header + err = lwmqtt_write_byte(&buf_ptr, buf_end, header); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write remaining length + err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write packet id + err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id); + if (err != LWMQTT_SUCCESS) { + return err; + } + + // write topics + for (int i = 0; i < count; i++) { + err = lwmqtt_write_string(&buf_ptr, buf_end, topic_filters[i]); + if (err != LWMQTT_SUCCESS) { + return err; + } + } + + // set length + *len = buf_ptr - buf; + + return LWMQTT_SUCCESS; +} diff --git a/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/packet.h b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/packet.h new file mode 100644 index 000000000..5fe9e50f1 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/packet.h @@ -0,0 +1,185 @@ +#ifndef LWMQTT_PACKET_H +#define LWMQTT_PACKET_H + +#include "helpers.h" + +/** + * The available packet types. + */ +typedef enum { + LWMQTT_NO_PACKET = 0, + LWMQTT_CONNECT_PACKET = 1, + LWMQTT_CONNACK_PACKET, + LWMQTT_PUBLISH_PACKET, + LWMQTT_PUBACK_PACKET, + LWMQTT_PUBREC_PACKET, + LWMQTT_PUBREL_PACKET, + LWMQTT_PUBCOMP_PACKET, + LWMQTT_SUBSCRIBE_PACKET, + LWMQTT_SUBACK_PACKET, + LWMQTT_UNSUBSCRIBE_PACKET, + LWMQTT_UNSUBACK_PACKET, + LWMQTT_PINGREQ_PACKET, + LWMQTT_PINGRESP_PACKET, + LWMQTT_DISCONNECT_PACKET +} lwmqtt_packet_type_t; + +/** + * Will detect the packet type from the at least one byte long buffer. + * + * @param buf - The buffer from which the packet type will be detected. + * @param buf_len - The length of the specified buffer. + * @param packet_type - The packet type. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_detect_packet_type(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t *packet_type); + +/** + * Will detect the remaining length form the at least on byte long buffer. + * + * It will return LWMQTT_BUFFER_TOO_SHORT if the buffer is to short and an additional byte should be read from the + * network. In case the remaining length is overflowed it will return LWMQTT_REMAINING_LENGTH_OVERFLOW. + * + * @param buf - The buffer from which the remaining length will be detected. + * @param buf_len - The length of the specified buffer. + * @param rem_len - The detected remaining length. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_detect_remaining_length(uint8_t *buf, size_t buf_len, uint32_t *rem_len); + +/** + * Encodes a connect packet into the supplied buffer. + * + * @param buf - The buffer into which the packet will be encoded. + * @param buf_len - The length of the specified buffer. + * @param len - The encoded length of the packet. + * @param options - The options to be used to build the connect packet. + * @param will - The last will and testament. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_encode_connect(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_options_t options, + lwmqtt_will_t *will); + +/** + * Decodes a connack packet from the supplied buffer. + * + * @param buf - The raw buffer data. + * @param buf_len - The length of the specified buffer. + * @param session_present - The session present flag. + * @param return_code - The return code. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_decode_connack(uint8_t *buf, size_t buf_len, bool *session_present, + lwmqtt_return_code_t *return_code); + +/** + * Encodes a zero (disconnect, pingreq) packet into the supplied buffer. + * + * @param buf - The buffer into which the packet will be encoded. + * @param buf_len - The length of the specified buffer. + * @param len - The encoded length of the packet. + * @param packet_type - The packets type. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_encode_zero(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type); + +/** + * Decodes an ack (puback, pubrec, pubrel, pubcomp, unsuback) packet from the supplied buffer. + * + * @param buf - The raw buffer data. + * @param buf_len - The length of the specified buffer. + * @param packet_type - The packet type. + * @param dup - The dup flag. + * @param packet_id - The packet id. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_decode_ack(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t packet_type, bool *dup, + uint16_t *packet_id); + +/** + * Encodes an ack (puback, pubrec, pubrel, pubcomp) packet into the supplied buffer. + * + * @param buf - The buffer into which the packet will be encoded. + * @param buf_len - The length of the specified buffer. + * @param len - The encoded length of the packet. + * @param packet_type - The packets type. + * @param dup - The dup flag. + * @param packet_id - The packet id. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_encode_ack(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type, bool dup, + uint16_t packet_id); + +/** + * Decodes a publish packet from the supplied buffer. + * + * @param buf - The raw buffer data. + * @param buf_len - The length of the specified buffer. + * @param dup - The dup flag. + * @param packet_id - The packet id. + * @param topic - The topic. + * @parma msg - The message. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_decode_publish(uint8_t *buf, size_t buf_len, bool *dup, uint16_t *packet_id, lwmqtt_string_t *topic, + lwmqtt_message_t *msg); + +/** + * Encodes a publish packet into the supplied buffer. + * + * @param buf - The buffer into which the packet will be encoded. + * @param buf_len - The length of the specified buffer. + * @param len - The encoded length of the packet. + * @param dup - The dup flag. + * @param packet_id - The packet id. + * @param topic - The topic. + * @param msg - The message. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_encode_publish(uint8_t *buf, size_t buf_len, size_t *len, bool dup, uint16_t packet_id, + lwmqtt_string_t topic, lwmqtt_message_t msg); + +/** + * Encodes a subscribe packet into the supplied buffer. + * + * @param buf - The buffer into which the packet will be encoded. + * @param buf_len - The length of the specified buffer. + * @param len - The encoded length of the packet. + * @param packet_id - The packet id. + * @param count - The number of members in the topic_filters and qos_levels array. + * @param topic_filters - The array of topic filter. + * @param qos_levels - The array of requested QoS levels. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_encode_subscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count, + lwmqtt_string_t *topic_filters, lwmqtt_qos_t *qos_levels); + +/** + * Decodes a suback packet from the supplied buffer. + * + * @param buf - The raw buffer data. + * @param buf_len - The length of the specified buffer. + * @param packet_id - The packet id. + * @param max_count - The maximum number of members allowed in the granted_qos_levels array. + * @param count - The number of members in the granted_qos_levels array. + * @param granted_qos_levels - The granted QoS levels. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_decode_suback(uint8_t *buf, size_t buf_len, uint16_t *packet_id, int max_count, int *count, + lwmqtt_qos_t *granted_qos_levels); + +/** + * Encodes the supplied unsubscribe data into the supplied buffer, ready for sending + * + * @param buf - The buffer into which the packet will be encoded. + * @param buf_len - The length of the specified buffer. + * @param len - The encoded length of the packet. + * @param packet_id - The packet id. + * @param count - The number of members in the topic_filters array. + * @param topic_filters - The array of topic filters. + * @return An error value. + */ +lwmqtt_err_t lwmqtt_encode_unsubscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count, + lwmqtt_string_t *topic_filters); + +#endif // LWMQTT_PACKET_H diff --git a/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/string.c b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/string.c new file mode 100644 index 000000000..c27dc94e3 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/src/lwmqtt/string.c @@ -0,0 +1,38 @@ +#include + +#include "lwmqtt.h" + +lwmqtt_string_t lwmqtt_string(const char *str) { + // check for null + if (str == NULL) { + return (lwmqtt_string_t){0, NULL}; + } + + // get length + uint16_t len = (uint16_t)strlen(str); + + // check zero length + if (len == 0) { + return (lwmqtt_string_t){0, NULL}; + } + + return (lwmqtt_string_t){len, (char *)str}; +} + +int lwmqtt_strcmp(lwmqtt_string_t a, const char *b) { + // get string of b + lwmqtt_string_t b_str = lwmqtt_string(b); + + // return if both are zero length + if (a.len == 0 && b_str.len == 0) { + return 0; + } + + // return if lengths are different + if (a.len != b_str.len) { + return -1; + } + + // compare memory of same length + return strncmp(a.data, b_str.data, a.len); +} diff --git a/lib/arduino-mqtt-2.3.3.02/src/system.cpp b/lib/arduino-mqtt-2.3.3.02/src/system.cpp new file mode 100644 index 000000000..cfd8c4740 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/src/system.cpp @@ -0,0 +1,48 @@ +#include + +#include "system.h" + +void lwmqtt_arduino_timer_set(void *ref, uint32_t timeout) { + // cast timer reference + auto t = (lwmqtt_arduino_timer_t *)ref; + + // set future end time + t->end = (uint32_t)(millis() + timeout); +} + +int32_t lwmqtt_arduino_timer_get(void *ref) { + // cast timer reference + auto t = (lwmqtt_arduino_timer_t *)ref; + + // get difference to end time + return (int32_t)t->end - (int32_t)millis(); +} + +lwmqtt_err_t lwmqtt_arduino_network_read(void *ref, uint8_t *buffer, size_t len, size_t *read, uint32_t timeout) { + // cast network reference + auto n = (lwmqtt_arduino_network_t *)ref; + + // set timeout + n->client->setTimeout(timeout); + + // read bytes + *read = n->client->readBytes(buffer, len); + if (*read <= 0) { + return LWMQTT_NETWORK_FAILED_READ; + } + + return LWMQTT_SUCCESS; +} + +lwmqtt_err_t lwmqtt_arduino_network_write(void *ref, uint8_t *buffer, size_t len, size_t *sent, uint32_t /*timeout*/) { + // cast network reference + auto n = (lwmqtt_arduino_network_t *)ref; + + // write bytes + *sent = n->client->write(buffer, len); + if (*sent <= 0) { + return LWMQTT_NETWORK_FAILED_WRITE; + }; + + return LWMQTT_SUCCESS; +} diff --git a/lib/arduino-mqtt-2.3.3.02/src/system.h b/lib/arduino-mqtt-2.3.3.02/src/system.h new file mode 100644 index 000000000..e51739fb8 --- /dev/null +++ b/lib/arduino-mqtt-2.3.3.02/src/system.h @@ -0,0 +1,26 @@ +#ifndef LWMQTT_ARDUINO_H +#define LWMQTT_ARDUINO_H + +#include +#include + +extern "C" { +#include "lwmqtt/lwmqtt.h" +}; + +typedef struct { + uint32_t end; +} lwmqtt_arduino_timer_t; + +void lwmqtt_arduino_timer_set(void *ref, uint32_t timeout); + +int32_t lwmqtt_arduino_timer_get(void *ref); + +typedef struct { + Client *client; +} lwmqtt_arduino_network_t; + +lwmqtt_err_t lwmqtt_arduino_network_read(void *ref, uint8_t *buf, size_t len, size_t *read, uint32_t timeout); +lwmqtt_err_t lwmqtt_arduino_network_write(void *ref, uint8_t *buf, size_t len, size_t *sent, uint32_t timeout); + +#endif // LWMQTT_ARDUINO_H diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/.gitignore b/lib/esp-mqtt-arduino-1.0.1.02.1/.gitignore deleted file mode 100644 index 2ee75414c..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -# C++ objects and libs - -*.slo -*.lo -*.o -#*.a -*.la -*.lai -*.so -*.dll -*.dylib - -#Makefile -*-build-* -build-* -*.autosave - -# .log files (usually created by QtTest - thanks to VestniK) -*.log - - -# Editors temporary files -*~ - - -#OSX -.DS_Store -._* diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/README.md b/lib/esp-mqtt-arduino-1.0.1.02.1/README.md deleted file mode 100644 index a7ddbecac..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/README.md +++ /dev/null @@ -1,15 +0,0 @@ -MQTT -==== - -A Wrapper around mqtt for Arduino to be used with esp8266 modules. - -It wraps a slightly modified version of mqtt for esp8266 ported by Tuan PM. -Original code for esp: https://github.com/tuanpmt/esp_mqtt -Original code for contiki: https://github.com/esar/contiki-mqtt - - -==== - -**secure libssl:** - -If you want to use secure communication, please use the `secure`-branch! diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/examples/mqtt_pub/mqtt_pub.ino b/lib/esp-mqtt-arduino-1.0.1.02.1/examples/mqtt_pub/mqtt_pub.ino deleted file mode 100644 index 17b3be8db..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/examples/mqtt_pub/mqtt_pub.ino +++ /dev/null @@ -1,102 +0,0 @@ -#include -#include - -void myDataCb(String& topic, String& data); -void myPublishedCb(); -void myDisconnectedCb(); -void myConnectedCb(); - -#define CLIENT_ID "client1" - -// create MQTT object -MQTT myMqtt(CLIENT_ID, "192.168.0.1", 1883); - -// -const char* ssid = "ssid"; -const char* password = "ssid_password"; - - -// -void setup() { - Serial.begin(115200); - delay(1000); - - Serial.println(); - Serial.println(); - Serial.print("Connecting to "); - Serial.println(ssid); - - WiFi.begin(ssid, password); - - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - } - - Serial.println(""); - Serial.println("WiFi connected"); - Serial.println("IP address: "); - Serial.println(WiFi.localIP()); - - Serial.println("Connecting to MQTT server"); - - // setup callbacks - myMqtt.onConnected(myConnectedCb); - myMqtt.onDisconnected(myDisconnectedCb); - myMqtt.onPublished(myPublishedCb); - myMqtt.onData(myDataCb); - - Serial.println("connect mqtt..."); - myMqtt.connect(); - - delay(10); -} - -// -void loop() { - - int value = analogRead(A0); - - String topic("/"); - topic += CLIENT_ID; - topic += "/value"; - - String valueStr(value); - - // publish value to topic - boolean result = myMqtt.publish(topic, valueStr); - - delay(1000); -} - - -/* - * - */ -void myConnectedCb() -{ - Serial.println("connected to MQTT server"); -} - -void myDisconnectedCb() -{ - Serial.println("disconnected. try to reconnect..."); - delay(500); - myMqtt.connect(); -} - -void myPublishedCb() -{ - //Serial.println("published."); -} - -void myDataCb(String& topic, String& data) -{ - - Serial.print(topic); - Serial.print(": "); - Serial.println(data); -} - - - diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/examples/mqtt_sub/mqtt_sub.ino b/lib/esp-mqtt-arduino-1.0.1.02.1/examples/mqtt_sub/mqtt_sub.ino deleted file mode 100644 index 1f7591617..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/examples/mqtt_sub/mqtt_sub.ino +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -void myDataCb(String& topic, String& data); -void myPublishedCb(); -void myDisconnectedCb(); -void myConnectedCb(); - -#define CLIENT_ID "client3" -#define TOPIC "/client1/value" - - -// create MQTT -MQTT myMqtt(CLIENT_ID, "192.168.0.1", 1883); - - -const char* ssid = "ssid"; -const char* password = "ssid_password"; - - -// -void setup() { - Serial.begin(115200); - delay(1000); - - Serial.println(); - Serial.println(); - Serial.print("Connecting to "); - Serial.println(ssid); - - WiFi.begin(ssid, password); - - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - } - - Serial.println(""); - Serial.println("WiFi connected"); - Serial.println("IP address: "); - Serial.println(WiFi.localIP()); - - - Serial.println("Connecting to MQTT server"); - - // setup callbacks - myMqtt.onConnected(myConnectedCb); - myMqtt.onDisconnected(myDisconnectedCb); - myMqtt.onPublished(myPublishedCb); - myMqtt.onData(myDataCb); - - Serial.println("connect mqtt..."); - myMqtt.connect(); - - Serial.println("subscribe to topic..."); - myMqtt.subscribe(TOPIC); - - delay(10); -} - -// -void loop() { -} - - -/* - * - */ -void myConnectedCb() -{ - Serial.println("connected to MQTT server"); -} - -void myDisconnectedCb() -{ - Serial.println("disconnected. try to reconnect..."); - delay(500); - myMqtt.connect(); -} - -void myPublishedCb() -{ - //Serial.println("published."); -} - -void myDataCb(String& topic, String& data) -{ - - Serial.print(topic); - Serial.print(": "); - Serial.println(data); -} - - - diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/keywords.txt b/lib/esp-mqtt-arduino-1.0.1.02.1/keywords.txt deleted file mode 100644 index 527b5bf0c..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/keywords.txt +++ /dev/null @@ -1,43 +0,0 @@ -####################################### -# Syntax Coloring Map For Test -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -MQTT.h KEYWORD1 - -MQTT KEYWORD1 - - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -setClientId KEYWORD2 -setUserPwd KEYWORD2 - -connect KEYWORD2 -disconnect KEYWORD2 -isConnected KEYWORD2 - -publish KEYWORD2 -subscribe KEYWORD2 - -getState KEYWORD2 - -#general -onConnected KEYWORD2 -onDisconnected KEYWORD2 -onPublished KEYWORD2 -onData KEYWORD2 - -####################################### -# Instances (KEYWORD2) -####################################### - -####################################### -# Constants (LITERAL1) -####################################### - diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/library.properties b/lib/esp-mqtt-arduino-1.0.1.02.1/library.properties deleted file mode 100644 index 110da0ac4..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=ESP MQTT -version=1.0.1 -author=Ingo Randolf -maintainer=Ingo Randolf -sentence=A Wrapper around mqtt for Arduino to be used with esp8266 modules. -paragraph=It wraps a slightly modified version of mqtt for esp8266 ported by Tuan PM. Original code for esp: https://github.com/tuanpmt/esp_mqtt (7ec2ef8e1df0422b77348fe1da7885568e0c9d01) Original code for contiki: https://github.com/esar/contiki-mqtt -category=Communication -url=https://github.com/i-n-g-o/esp-mqtt-arduino -architectures=esp8266 \ No newline at end of file diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/MQTT.cpp b/lib/esp-mqtt-arduino-1.0.1.02.1/src/MQTT.cpp deleted file mode 100644 index b330bad4b..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/MQTT.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/*//------------------------------------------------------------------------------- - * MQTT.cpp - * - * Implementation file for MQTT Wrapper - * - * Wrapper for Arduino written by Ingo Randolf during - * eTextiles Summercamp 2015. - * - * This library is intended to be used with esp8266 modules. - * - * - * This class wraps a slightly modified version of mqtt - * for esp8266 written by Tuan PM. - * Original code: https://github.com/tuanpmt/esp_mqtt - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - //-------------------------------------------------------------------------------*/ -#include "MQTT.h" - -#include "user_interface.h" -#include "osapi.h" -#include "os_type.h" -#include "mqtt/debug.h" - - -//------------------------------------------------------------------------------------ -// mqtt internal callbacks -//------------------------------------------------------------------------------------ -static void mqttConnectedCb(uint32_t *args) -{ - MQTT_Client* client = (MQTT_Client*)args; - - MQTT* _this = (MQTT*)client->user_data; - - if (_this && _this->onMqttConnectedCb) { - _this->onMqttConnectedCb(); - } -} - -static void mqttDisconnectedCb(uint32_t *args) -{ - MQTT_Client* client = (MQTT_Client*)args; - - MQTT* _this = (MQTT*)client->user_data; - - if (_this && _this->onMqttDisconnectedCb) { - _this->onMqttDisconnectedCb(); - } -} - -static void mqttPublishedCb(uint32_t *args) -{ - MQTT_Client* client = (MQTT_Client*)args; - - MQTT* _this = (MQTT*)client->user_data; - - if (_this && _this->onMqttPublishedCb) { - _this->onMqttPublishedCb(); - } -} - -static void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len) -{ - MQTT_Client* client = (MQTT_Client*)args; - - MQTT* _this = (MQTT*)client->user_data; - - if (_this) { - - _this->_onMqttDataCb(topic, topic_len, data, data_len); - } -} - -static void mqttTimeoutCb(uint32_t *args) -{ - MQTT_Client* client = (MQTT_Client*)args; - - MQTT* _this = (MQTT*)client->user_data; - -// if (_this && _this->onMqttTimeoutCb) { -// _this->onMqttTimeoutCb(); -// } -} - - -//------------------------------------------------------------------------------------ -// MQTT class implementation -//------------------------------------------------------------------------------------ - -//MQTT::MQTT(const char* client_id, const char* host, uint32_t port) : -MQTT::MQTT(const char* client_id, const char* host, uint32_t port, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) : - onMqttConnectedCb(0) - ,onMqttDisconnectedCb(0) - ,onMqttPublishedCb(0) - ,onMqttDataCb(0) - ,onMqttDataRawCb(0) -{ - // init connections - MQTT_InitConnection(&mqttClient, (uint8_t*)host, port, 0); - - // init client - if ( !MQTT_InitClient(&mqttClient, (uint8_t*)client_id, (uint8_t*)"", (uint8_t*)"", 15, 1) ) { - MQTT_INFO("Failed to initialize properly. Check MQTT version.\r\n"); - } - - // init LWT -// MQTT_InitLWT(&mqttClient, (uint8_t*)"/lwt", (uint8_t*)"offline", 0, 0); - MQTT_InitLWT(&mqttClient, (uint8_t*)willTopic, (uint8_t*)willMessage, willQos, (uint8_t)willRetain); - - // set user data - mqttClient.user_data = (void*)this; - - // setup callbacks - MQTT_OnConnected(&mqttClient, mqttConnectedCb); - MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb); - MQTT_OnPublished(&mqttClient, mqttPublishedCb); - MQTT_OnData(&mqttClient, mqttDataCb); - - MQTT_OnTimeout(&mqttClient, mqttTimeoutCb); -} - - -MQTT::~MQTT() -{ - MQTT_DeleteClient(&mqttClient); -} - - -/* - */ -void MQTT::setClientId(const char* client_id) -{ - MQTT_SetUserId(&mqttClient, client_id); -} - -void MQTT::setUserPwd(const char* user, const char* pwd) -{ - MQTT_SetUserPwd(&mqttClient, user, pwd); -} - - -/* - */ -void MQTT::connect() -{ - MQTT_Connect(&mqttClient); -} - -void MQTT::disconnect() -{ - MQTT_Disconnect(&mqttClient); -} - -bool MQTT::isConnected() -{ - return (mqttClient.connState >= TCP_CONNECTED); -} - -/* - */ -bool MQTT::publish(const char* topic, const char* buf, uint32_t buf_len, int qos, int retain) -{ - return MQTT_Publish(&mqttClient, topic, buf, buf_len, qos, retain); -} - -bool MQTT::publish(String& topic, String& data, int qos, int retain) -{ - return publish(topic.c_str(), data.c_str(), data.length(), qos, retain); -} - -bool MQTT::publish(String& topic, const char* buf, uint32_t buf_len, int qos, int retain) -{ - return publish(topic.c_str(), buf, buf_len, qos, retain); -} - -bool MQTT::publish(const char* topic, String& data, int qos, int retain) -{ - return publish(topic, data.c_str(), data.length(), qos, retain); -} - - -/* - */ -bool MQTT::subscribe(const char* topic, uint8_t qos) -{ - return MQTT_Subscribe(&mqttClient, (char*)topic, qos); -} - -bool MQTT::subscribe(const String& topic, uint8_t qos) -{ - return MQTT_Subscribe(&mqttClient, (char*)topic.c_str(), qos); -} - - - -//------------------------------------------------------------------------------- -// set user callback functions -//------------------------------------------------------------------------------- -void MQTT::onConnected( void (*function)(void) ) -{ - onMqttConnectedCb = function; -} - -void MQTT::onDisconnected( void (*function)(void) ) -{ - onMqttDisconnectedCb = function; -} - -void MQTT::onPublished( void (*function)(void) ) -{ - onMqttPublishedCb = function; -} - -void MQTT::onData( void (*function)(String&, String&) ) -{ - onMqttDataCb = function; -} - -void MQTT::onData( void (*function)(const char*, uint32_t, const char*, uint32_t) ) -{ - onMqttDataRawCb = function; -} - - -// internal callback, calling user CB -void MQTT::_onMqttDataCb(const char* topic, uint32_t topic_len, const char* buf, uint32_t buf_len) -{ - if (onMqttDataRawCb) { - onMqttDataRawCb(topic, topic_len, buf, buf_len); - } - - if (onMqttDataCb) { - - char* topicCpy = (char*)malloc(topic_len+1); - memcpy(topicCpy, topic, topic_len); - topicCpy[topic_len] = 0; - // string it - String topicStr(topicCpy); - - char* bufCpy = (char*)malloc(buf_len+1); - memcpy(bufCpy, buf, buf_len); - bufCpy[buf_len] = 0; - // string it - String bufStr(bufCpy); - - onMqttDataCb(topicStr, bufStr); - - free(topicCpy); - free(bufCpy); - } -} - - - - - - - - - diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/MQTT.h b/lib/esp-mqtt-arduino-1.0.1.02.1/src/MQTT.h deleted file mode 100644 index 8838ef482..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/MQTT.h +++ /dev/null @@ -1,93 +0,0 @@ -/*//------------------------------------------------------------------------------- - * MQTT.h - * - * Header file for MQTT Wrapper - * - * Wrapper for Arduino written by Ingo Randolf during - * eTextiles Summercamp 2015. - * - * This library is intended to be used with esp8266 modules. - * - * - * This class wraps a slightly modified version of mqtt - * for esp8266 written by Tuan PM. - * Original code: https://github.com/tuanpmt/esp_mqtt - * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - //-------------------------------------------------------------------------------*/ -#ifndef MQTT_WRAPPER_H -#define MQTT_WRAPPER_H - -#include - -#include -#include -#include -#include -#include - -extern "C" { - #include - #include "mqtt/mqtt.h" -} - -class MQTT -{ -public: -// MQTT(const char* client_id, const char* host, uint32_t port); - MQTT(const char* client_id, const char* host, uint32_t port, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); - - ~MQTT(); - - void setClientId(const char* client_id); - void setUserPwd(const char* user, const char* pwd); - - void connect(); - void disconnect(); - bool isConnected(); - - bool publish(const char* topic, const char* buf, uint32_t buf_len, int qos = 0, int retain = 0); - bool publish(String& topic, String& data, int qos = 0, int retain = 0); - bool publish(String& topic, const char* buf, uint32_t buf_len, int qos = 0, int retain = 0); - bool publish(const char* topic, String& data, int qos = 0, int retain = 0); - - bool subscribe(const char* topic, uint8_t qos = 0); - bool subscribe(const String& topic, uint8_t qos = 0); - - int getState() { return mqttClient.connState; }; - - // set callbacks - void onConnected( void (*)(void) ); - void onDisconnected( void (*)(void) ); - void onPublished( void (*)(void) ); - void onData( void (*)(String&, String&) ); - void onData( void (*)(const char*, uint32_t, const char*, uint32_t) ); - - // user callbacks - void (*onMqttConnectedCb)(void); - void (*onMqttDisconnectedCb)(void); - void (*onMqttPublishedCb)(void); - void (*onMqttDataCb) (String&, String&); - void (*onMqttDataRawCb) (const char*, uint32_t, const char*, uint32_t); - - // internal callback - void _onMqttDataCb(const char*, uint32_t, const char*, uint32_t); - -private: - MQTT_Client mqttClient; - -}; - - - - -#endif \ No newline at end of file diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/debug.h b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/debug.h deleted file mode 100644 index f45dd6d8d..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/debug.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * debug.h - * - * Created on: Dec 4, 2014 - * Author: Minh - */ - -#ifndef USER_DEBUG_H_ -#define USER_DEBUG_H_ - - -#if defined(MQTT_DEBUG_ON) -#define MQTT_INFO( format, ... ) os_printf( format, ## __VA_ARGS__ ) -#else -#define MQTT_INFO( format, ... ) -#endif - - -#endif /* USER_DEBUG_H_ */ diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt.c b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt.c deleted file mode 100644 index ed63d713a..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt.c +++ /dev/null @@ -1,1048 +0,0 @@ -/* mqtt.c -* Protocol: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html -* -* Copyright (c) 2014-2015, Tuan PM -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* * Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of Redis nor the names of its contributors may be used -* to endorse or promote products derived from this software without -* specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "user_interface.h" -#include "osapi.h" -#include "espconn.h" -#include "os_type.h" -#include "mem.h" -#include "mqtt_msg.h" -#include "debug.h" -#include "user_config.h" -#include "mqtt.h" -#include "queue.h" - -#define MQTT_TASK_PRIO 1 -#define MQTT_TASK_QUEUE_SIZE 1 -#define MQTT_SEND_TIMOUT 5 - -#ifndef MQTT_SSL_SIZE -#define MQTT_SSL_SIZE 5120 -#endif - -#ifndef QUEUE_BUFFER_SIZE -#define QUEUE_BUFFER_SIZE 2048 -#endif - - -os_event_t mqtt_procTaskQueue[MQTT_TASK_QUEUE_SIZE]; - -#ifdef PROTOCOL_NAMEv311 -LOCAL uint8_t zero_len_id[2] = { 0, 0 }; -#endif - -LOCAL void ICACHE_FLASH_ATTR -mqtt_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) -{ - struct espconn *pConn = (struct espconn *)arg; - MQTT_Client* client = (MQTT_Client *)pConn->reverse; - - - if (ipaddr == NULL) - { - MQTT_INFO("DNS: Found, but got no ip, try to reconnect\r\n"); - client->connState = TCP_RECONNECT_REQ; - return; - } - - MQTT_INFO("DNS: found ip %d.%d.%d.%d\n", - *((uint8 *) &ipaddr->addr), - *((uint8 *) &ipaddr->addr + 1), - *((uint8 *) &ipaddr->addr + 2), - *((uint8 *) &ipaddr->addr + 3)); - - if (client->ip.addr == 0 && ipaddr->addr != 0) - { - os_memcpy(client->pCon->proto.tcp->remote_ip, &ipaddr->addr, 4); - if (client->security) { -#ifdef MQTT_SSL_ENABLE - espconn_secure_set_size(ESPCONN_CLIENT, MQTT_SSL_SIZE); - espconn_secure_connect(client->pCon); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - espconn_connect(client->pCon); - } - - client->connState = TCP_CONNECTING; - MQTT_INFO("TCP: connecting...\r\n"); - } - - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); -} - - - -LOCAL void ICACHE_FLASH_ATTR -deliver_publish(MQTT_Client* client, uint8_t* message, int length) -{ - mqtt_event_data_t event_data; - - event_data.topic_length = length; - event_data.topic = mqtt_get_publish_topic(message, &event_data.topic_length); - event_data.data_length = length; - event_data.data = mqtt_get_publish_data(message, &event_data.data_length); - - if (client->dataCb) - client->dataCb((uint32_t*)client, event_data.topic, event_data.topic_length, event_data.data, event_data.data_length); - -} - -void ICACHE_FLASH_ATTR -mqtt_send_keepalive(MQTT_Client *client) -{ - MQTT_INFO("\r\nMQTT: Send keepalive packet to %s:%d!\r\n", client->host, client->port); - client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection); - client->mqtt_state.pending_msg_type = MQTT_MSG_TYPE_PINGREQ; - client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); - client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); - - - client->sendTimeout = MQTT_SEND_TIMOUT; - MQTT_INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); - err_t result = ESPCONN_OK; - if (client->security) { -#ifdef MQTT_SSL_ENABLE - result = espconn_secure_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - result = espconn_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); - } - - client->mqtt_state.outbound_message = NULL; - if (ESPCONN_OK == result) { - client->keepAliveTick = 0; - client->connState = MQTT_DATA; - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - } - else { - client->connState = TCP_RECONNECT_DISCONNECTING; - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - } -} - -/** - * @brief Delete tcp client and free all memory - * @param mqttClient: The mqtt client which contain TCP client - * @retval None - */ -void ICACHE_FLASH_ATTR -mqtt_tcpclient_delete(MQTT_Client *mqttClient) -{ - if (mqttClient->pCon != NULL) { - MQTT_INFO("TCP: Free memory\r\n"); - // Force abort connections - espconn_abort(mqttClient->pCon); - // Delete connections - espconn_delete(mqttClient->pCon); - - if (mqttClient->pCon->proto.tcp) { - os_free(mqttClient->pCon->proto.tcp); - mqttClient->pCon->proto.tcp = NULL; - } - os_free(mqttClient->pCon); - mqttClient->pCon = NULL; - } -} - -/** - * @brief Delete MQTT client and free all memory - * @param mqttClient: The mqtt client - * @retval None - */ -void ICACHE_FLASH_ATTR -mqtt_client_delete(MQTT_Client *mqttClient) -{ - if (mqttClient == NULL) - return; - - if (mqttClient->pCon != NULL) { - mqtt_tcpclient_delete(mqttClient); - } - - if (mqttClient->host != NULL) { - os_free(mqttClient->host); - mqttClient->host = NULL; - } - - if (mqttClient->user_data != NULL) { - os_free(mqttClient->user_data); - mqttClient->user_data = NULL; - } - - if (mqttClient->mqtt_state.in_buffer != NULL) { - os_free(mqttClient->mqtt_state.in_buffer); - mqttClient->mqtt_state.in_buffer = NULL; - } - - if (mqttClient->mqtt_state.out_buffer != NULL) { - os_free(mqttClient->mqtt_state.out_buffer); - mqttClient->mqtt_state.out_buffer = NULL; - } - - if (mqttClient->mqtt_state.outbound_message != NULL) { - if (mqttClient->mqtt_state.outbound_message->data != NULL) - { - os_free(mqttClient->mqtt_state.outbound_message->data); - mqttClient->mqtt_state.outbound_message->data = NULL; - } - } - - if (mqttClient->mqtt_state.mqtt_connection.buffer != NULL) { - // Already freed but not NULL - mqttClient->mqtt_state.mqtt_connection.buffer = NULL; - } - - if (mqttClient->connect_info.client_id != NULL) { -#ifdef PROTOCOL_NAMEv311 - /* Don't attempt to free if it's the zero_len array */ - if ( ((uint8_t*)mqttClient->connect_info.client_id) != zero_len_id ) - os_free(mqttClient->connect_info.client_id); -#else - os_free(mqttClient->connect_info.client_id); -#endif - mqttClient->connect_info.client_id = NULL; - } - - if (mqttClient->connect_info.username != NULL) { - os_free(mqttClient->connect_info.username); - mqttClient->connect_info.username = NULL; - } - - if (mqttClient->connect_info.password != NULL) { - os_free(mqttClient->connect_info.password); - mqttClient->connect_info.password = NULL; - } - - if (mqttClient->connect_info.will_topic != NULL) { - os_free(mqttClient->connect_info.will_topic); - mqttClient->connect_info.will_topic = NULL; - } - - if (mqttClient->connect_info.will_message != NULL) { - os_free(mqttClient->connect_info.will_message); - mqttClient->connect_info.will_message = NULL; - } - - if (mqttClient->msgQueue.buf != NULL) { - os_free(mqttClient->msgQueue.buf); - mqttClient->msgQueue.buf = NULL; - } - - // Initialize state - mqttClient->connState = WIFI_INIT; - // Clear callback functions to avoid abnormal callback - mqttClient->connectedCb = NULL; - mqttClient->disconnectedCb = NULL; - mqttClient->publishedCb = NULL; - mqttClient->timeoutCb = NULL; - mqttClient->dataCb = NULL; - - MQTT_INFO("MQTT: client already deleted\r\n"); -} - - -/** - * @brief Client received callback function. - * @param arg: contain the ip link information - * @param pdata: received data - * @param len: the lenght of received data - * @retval None - */ -void ICACHE_FLASH_ATTR -mqtt_tcpclient_recv(void *arg, char *pdata, unsigned short len) -{ - uint8_t msg_type; - uint8_t msg_qos; - uint16_t msg_id; - uint8_t msg_conn_ret; - - struct espconn *pCon = (struct espconn*)arg; - MQTT_Client *client = (MQTT_Client *)pCon->reverse; - -READPACKET: - MQTT_INFO("TCP: data received %d bytes\r\n", len); - // MQTT_INFO("STATE: %d\r\n", client->connState); - if (len < MQTT_BUF_SIZE && len > 0) { - os_memcpy(client->mqtt_state.in_buffer, pdata, len); - - msg_type = mqtt_get_type(client->mqtt_state.in_buffer); - msg_qos = mqtt_get_qos(client->mqtt_state.in_buffer); - msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length); - switch (client->connState) { - case MQTT_CONNECT_SENDING: - if (msg_type == MQTT_MSG_TYPE_CONNACK) { - if (client->mqtt_state.pending_msg_type != MQTT_MSG_TYPE_CONNECT) { - MQTT_INFO("MQTT: Invalid packet\r\n"); - if (client->security) { -#ifdef MQTT_SSL_ENABLE - espconn_secure_disconnect(client->pCon); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - espconn_disconnect(client->pCon); - } - } else { - msg_conn_ret = mqtt_get_connect_return_code(client->mqtt_state.in_buffer); - switch (msg_conn_ret) { - case CONNECTION_ACCEPTED: - MQTT_INFO("MQTT: Connected to %s:%d\r\n", client->host, client->port); - client->connState = MQTT_DATA; - if (client->connectedCb) - client->connectedCb((uint32_t*)client); - break; - case CONNECTION_REFUSE_PROTOCOL: - case CONNECTION_REFUSE_SERVER_UNAVAILABLE: - case CONNECTION_REFUSE_BAD_USERNAME: - case CONNECTION_REFUSE_NOT_AUTHORIZED: - MQTT_INFO("MQTT: Connection refuse, reason code: %d\r\n", msg_conn_ret); - default: - if (client->security) { -#ifdef MQTT_SSL_ENABLE - espconn_secure_disconnect(client->pCon); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - espconn_disconnect(client->pCon); - } - - } - - } - - } - break; - case MQTT_DATA: - case MQTT_KEEPALIVE_SEND: - client->mqtt_state.message_length_read = len; - client->mqtt_state.message_length = mqtt_get_total_length(client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); - - - switch (msg_type) - { - - case MQTT_MSG_TYPE_SUBACK: - if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) - MQTT_INFO("MQTT: Subscribe successful\r\n"); - break; - case MQTT_MSG_TYPE_UNSUBACK: - if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) - MQTT_INFO("MQTT: UnSubscribe successful\r\n"); - break; - case MQTT_MSG_TYPE_PUBLISH: - if (msg_qos == 1) - client->mqtt_state.outbound_message = mqtt_msg_puback(&client->mqtt_state.mqtt_connection, msg_id); - else if (msg_qos == 2) - client->mqtt_state.outbound_message = mqtt_msg_pubrec(&client->mqtt_state.mqtt_connection, msg_id); - if (msg_qos == 1 || msg_qos == 2) { - MQTT_INFO("MQTT: Queue response QoS: %d\r\n", msg_qos); - if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - } - } - - deliver_publish(client, client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); - break; - case MQTT_MSG_TYPE_PUBACK: - if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id) { - MQTT_INFO("MQTT: received MQTT_MSG_TYPE_PUBACK, finish QoS1 publish\r\n"); - } - - break; - case MQTT_MSG_TYPE_PUBREC: - client->mqtt_state.outbound_message = mqtt_msg_pubrel(&client->mqtt_state.mqtt_connection, msg_id); - if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - } - break; - case MQTT_MSG_TYPE_PUBREL: - client->mqtt_state.outbound_message = mqtt_msg_pubcomp(&client->mqtt_state.mqtt_connection, msg_id); - if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - } - break; - case MQTT_MSG_TYPE_PUBCOMP: - if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id) { - MQTT_INFO("MQTT: receive MQTT_MSG_TYPE_PUBCOMP, finish QoS2 publish\r\n"); - } - break; - case MQTT_MSG_TYPE_PINGREQ: - client->mqtt_state.outbound_message = mqtt_msg_pingresp(&client->mqtt_state.mqtt_connection); - if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - } - break; - case MQTT_MSG_TYPE_PINGRESP: - // Ignore - break; - } - // NOTE: this is done down here and not in the switch case above - // because the PSOCK_READBUF_LEN() won't work inside a switch - // statement due to the way protothreads resume. - if (msg_type == MQTT_MSG_TYPE_PUBLISH) - { - len = client->mqtt_state.message_length_read; - - if (client->mqtt_state.message_length < client->mqtt_state.message_length_read) - { - //client->connState = MQTT_PUBLISH_RECV; - //Not Implement yet - len -= client->mqtt_state.message_length; - pdata += client->mqtt_state.message_length; - - MQTT_INFO("Get another published message\r\n"); - goto READPACKET; - } - - } - break; - } - } else { - MQTT_INFO("ERROR: Message too long\r\n"); - } - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); -} - -/** - * @brief Client send over callback function. - * @param arg: contain the ip link information - * @retval None - */ -void ICACHE_FLASH_ATTR -mqtt_tcpclient_sent_cb(void *arg) -{ - struct espconn *pCon = (struct espconn *)arg; - MQTT_Client* client = (MQTT_Client *)pCon->reverse; - MQTT_INFO("TCP: Sent\r\n"); - client->sendTimeout = 0; - client->keepAliveTick = 0; - - if ((client->connState == MQTT_DATA || client->connState == MQTT_KEEPALIVE_SEND) - && client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH) { - if (client->publishedCb) - client->publishedCb((uint32_t*)client); - } - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); -} - -void ICACHE_FLASH_ATTR mqtt_timer(void *arg) -{ - MQTT_Client* client = (MQTT_Client*)arg; - - if (client->connState == MQTT_DATA) { - client->keepAliveTick ++; - if (client->keepAliveTick > (client->mqtt_state.connect_info->keepalive / 2)) { - client->connState = MQTT_KEEPALIVE_SEND; - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - } - - } else if (client->connState == TCP_RECONNECT_REQ) { - client->reconnectTick ++; - if (client->reconnectTick > MQTT_RECONNECT_TIMEOUT) { - client->reconnectTick = 0; - client->connState = TCP_RECONNECT; - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - if (client->timeoutCb) - client->timeoutCb((uint32_t*)client); - } - } - if (client->sendTimeout > 0) - client->sendTimeout --; -} - -void ICACHE_FLASH_ATTR -mqtt_tcpclient_discon_cb(void *arg) -{ - - struct espconn *pespconn = (struct espconn *)arg; - MQTT_Client* client = (MQTT_Client *)pespconn->reverse; - MQTT_INFO("TCP: Disconnected callback\r\n"); - if (TCP_DISCONNECTING == client->connState) { - client->connState = TCP_DISCONNECTED; - } - else if (MQTT_DELETING == client->connState) { - client->connState = MQTT_DELETED; - } - else { - client->connState = TCP_RECONNECT_REQ; - } - if (client->disconnectedCb) - client->disconnectedCb((uint32_t*)client); - - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); -} - - - -/** - * @brief Tcp client connect success callback function. - * @param arg: contain the ip link information - * @retval None - */ -void ICACHE_FLASH_ATTR -mqtt_tcpclient_connect_cb(void *arg) -{ - struct espconn *pCon = (struct espconn *)arg; - MQTT_Client* client = (MQTT_Client *)pCon->reverse; - - espconn_regist_disconcb(client->pCon, mqtt_tcpclient_discon_cb); - espconn_regist_recvcb(client->pCon, mqtt_tcpclient_recv);//////// - espconn_regist_sentcb(client->pCon, mqtt_tcpclient_sent_cb);/////// - MQTT_INFO("MQTT: Connected to broker %s:%d\r\n", client->host, client->port); - - mqtt_msg_init(&client->mqtt_state.mqtt_connection, client->mqtt_state.out_buffer, client->mqtt_state.out_buffer_length); - client->mqtt_state.outbound_message = mqtt_msg_connect(&client->mqtt_state.mqtt_connection, client->mqtt_state.connect_info); - client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); - client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); - - - client->sendTimeout = MQTT_SEND_TIMOUT; - MQTT_INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); - if (client->security) { -#ifdef MQTT_SSL_ENABLE - espconn_secure_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - espconn_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); - } - - client->mqtt_state.outbound_message = NULL; - client->connState = MQTT_CONNECT_SENDING; - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); -} - -/** - * @brief Tcp client connect repeat callback function. - * @param arg: contain the ip link information - * @retval None - */ -void ICACHE_FLASH_ATTR -mqtt_tcpclient_recon_cb(void *arg, sint8 errType) -{ - struct espconn *pCon = (struct espconn *)arg; - MQTT_Client* client = (MQTT_Client *)pCon->reverse; - - MQTT_INFO("TCP: Reconnect to %s:%d\r\n", client->host, client->port); - - client->connState = TCP_RECONNECT_REQ; - - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - -} - -/** - * @brief MQTT publish function. - * @param client: MQTT_Client reference - * @param topic: string topic will publish to - * @param data: buffer data send point to - * @param data_length: length of data - * @param qos: qos - * @param retain: retain - * @retval TRUE if success queue - */ -BOOL ICACHE_FLASH_ATTR -MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain) -{ - uint8_t dataBuffer[MQTT_BUF_SIZE]; - uint16_t dataLen; - client->mqtt_state.outbound_message = mqtt_msg_publish(&client->mqtt_state.mqtt_connection, - topic, data, data_length, - qos, retain, - &client->mqtt_state.pending_msg_id); - if (client->mqtt_state.outbound_message->length == 0) { - MQTT_INFO("MQTT: Queuing publish failed\r\n"); - return FALSE; - } - MQTT_INFO("MQTT: queuing publish, length: %d, queue size(%d/%d)\r\n", client->mqtt_state.outbound_message->length, client->msgQueue.rb.fill_cnt, client->msgQueue.rb.size); - while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) { - MQTT_INFO("MQTT: Serious buffer error\r\n"); - return FALSE; - } - } - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - return TRUE; -} - -/** - * @brief MQTT subscibe function. - * @param client: MQTT_Client reference - * @param topic: string topic will subscribe - * @param qos: qos - * @retval TRUE if success queue - */ -BOOL ICACHE_FLASH_ATTR -MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos) -{ - uint8_t dataBuffer[MQTT_BUF_SIZE]; - uint16_t dataLen; - - client->mqtt_state.outbound_message = mqtt_msg_subscribe(&client->mqtt_state.mqtt_connection, - topic, qos, - &client->mqtt_state.pending_msg_id); - MQTT_INFO("MQTT: queue subscribe, topic\"%s\", id: %d\r\n", topic, client->mqtt_state.pending_msg_id); - while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) { - MQTT_INFO("MQTT: Serious buffer error\r\n"); - return FALSE; - } - } - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - - return TRUE; -} - -/** - * @brief MQTT un-subscibe function. - * @param client: MQTT_Client reference - * @param topic: String topic will un-subscribe - * @retval TRUE if success queue - */ -BOOL ICACHE_FLASH_ATTR -MQTT_UnSubscribe(MQTT_Client *client, char* topic) -{ - uint8_t dataBuffer[MQTT_BUF_SIZE]; - uint16_t dataLen; - client->mqtt_state.outbound_message = mqtt_msg_unsubscribe(&client->mqtt_state.mqtt_connection, - topic, - &client->mqtt_state.pending_msg_id); - MQTT_INFO("MQTT: queue un-subscribe, topic\"%s\", id: %d\r\n", topic, client->mqtt_state.pending_msg_id); - while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) { - MQTT_INFO("MQTT: Serious buffer error\r\n"); - return FALSE; - } - } - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - return TRUE; -} - -/** - * @brief MQTT ping function. - * @param client: MQTT_Client reference - * @retval TRUE if success queue - */ -BOOL ICACHE_FLASH_ATTR -MQTT_Ping(MQTT_Client *client) -{ - uint8_t dataBuffer[MQTT_BUF_SIZE]; - uint16_t dataLen; - client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection); - if (client->mqtt_state.outbound_message->length == 0) { - MQTT_INFO("MQTT: Queuing publish failed\r\n"); - return FALSE; - } - MQTT_INFO("MQTT: queuing publish, length: %d, queue size(%d/%d)\r\n", client->mqtt_state.outbound_message->length, client->msgQueue.rb.fill_cnt, client->msgQueue.rb.size); - while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) { - MQTT_INFO("MQTT: Serious buffer error\r\n"); - return FALSE; - } - } - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - return TRUE; -} - -void ICACHE_FLASH_ATTR -MQTT_Task(os_event_t *e) -{ - MQTT_Client* client = (MQTT_Client*)e->par; - uint8_t dataBuffer[MQTT_BUF_SIZE]; - uint16_t dataLen; - if (e->par == 0) - return; - switch (client->connState) { - - case TCP_RECONNECT_REQ: - break; - case TCP_RECONNECT: - mqtt_tcpclient_delete(client); - MQTT_Connect(client); - MQTT_INFO("TCP: Reconnect to: %s:%d\r\n", client->host, client->port); - client->connState = TCP_CONNECTING; - break; - case MQTT_DELETING: - case TCP_DISCONNECTING: - case TCP_RECONNECT_DISCONNECTING: - if (client->security) { -#ifdef MQTT_SSL_ENABLE - espconn_secure_disconnect(client->pCon); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - espconn_disconnect(client->pCon); - } - break; - case TCP_DISCONNECTED: - MQTT_INFO("MQTT: Disconnected\r\n"); - mqtt_tcpclient_delete(client); - break; - case MQTT_DELETED: - MQTT_INFO("MQTT: Deleted client\r\n"); - mqtt_client_delete(client); - break; - case MQTT_KEEPALIVE_SEND: - mqtt_send_keepalive(client); - break; - case MQTT_DATA: - if (QUEUE_IsEmpty(&client->msgQueue) || client->sendTimeout != 0) { - break; - } - if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == 0) { - client->mqtt_state.pending_msg_type = mqtt_get_type(dataBuffer); - client->mqtt_state.pending_msg_id = mqtt_get_id(dataBuffer, dataLen); - - - client->sendTimeout = MQTT_SEND_TIMOUT; - MQTT_INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); - client->keepAliveTick = 0; - if (client->security) { -#ifdef MQTT_SSL_ENABLE - espconn_secure_send(client->pCon, dataBuffer, dataLen); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - espconn_send(client->pCon, dataBuffer, dataLen); - } - - client->mqtt_state.outbound_message = NULL; - break; - } - break; - } -} - -/** - * @brief MQTT initialization connection function - * @param client: MQTT_Client reference - * @param host: Domain or IP string - * @param port: Port to connect - * @param security: 1 for ssl, 0 for none - * @retval None - */ -void ICACHE_FLASH_ATTR -MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security) -{ - uint32_t temp; - MQTT_INFO("MQTT:InitConnection\r\n"); - os_memset(mqttClient, 0, sizeof(MQTT_Client)); - temp = os_strlen(host); - mqttClient->host = (uint8_t*)os_zalloc(temp + 1); - os_strcpy(mqttClient->host, host); - mqttClient->host[temp] = 0; - mqttClient->port = port; - mqttClient->security = security; - -} - -/** - * @brief MQTT initialization mqtt client function - * @param client: MQTT_Client reference - * @param clientid: MQTT client id - * @param client_user:MQTT client user - * @param client_pass:MQTT client password - * @param client_pass:MQTT keep alive timer, in second - * @retval None - */ -BOOL ICACHE_FLASH_ATTR -MQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession) -{ - uint32_t temp; - MQTT_INFO("MQTT:InitClient\r\n"); - - os_memset(&mqttClient->connect_info, 0, sizeof(mqtt_connect_info_t)); - - if ( !client_id ) - { - /* Should be allowed by broker, but clean session flag must be set. */ - #ifdef PROTOCOL_NAMEv311 - if (cleanSession) - { - mqttClient->connect_info.client_id = zero_len_id; - } else { - MQTT_INFO("cleanSession must be set to use 0 length client_id\r\n"); - return false; - } - /* Not supported. Return. */ - #else - MQTT_INFO("Client ID required for MQTT < 3.1.1!\r\n"); - return false; - #endif - } - - /* If connect_info's client_id is still NULL and we get here, we can * - * assume the passed client_id is non-NULL. */ - if ( !(mqttClient->connect_info.client_id) ) - { - temp = os_strlen(client_id); - mqttClient->connect_info.client_id = (uint8_t*)os_zalloc(temp + 1); - os_strcpy(mqttClient->connect_info.client_id, client_id); - mqttClient->connect_info.client_id[temp] = 0; - } - - if (client_user) - { - temp = os_strlen(client_user); - mqttClient->connect_info.username = (uint8_t*)os_zalloc(temp + 1); - os_strcpy(mqttClient->connect_info.username, client_user); - mqttClient->connect_info.username[temp] = 0; - } - - if (client_pass) - { - temp = os_strlen(client_pass); - mqttClient->connect_info.password = (uint8_t*)os_zalloc(temp + 1); - os_strcpy(mqttClient->connect_info.password, client_pass); - mqttClient->connect_info.password[temp] = 0; - } - - - mqttClient->connect_info.keepalive = keepAliveTime; - mqttClient->connect_info.clean_session = cleanSession; - - mqttClient->mqtt_state.in_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE); - mqttClient->mqtt_state.in_buffer_length = MQTT_BUF_SIZE; - mqttClient->mqtt_state.out_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE); - mqttClient->mqtt_state.out_buffer_length = MQTT_BUF_SIZE; - mqttClient->mqtt_state.connect_info = &mqttClient->connect_info; - - mqtt_msg_init(&mqttClient->mqtt_state.mqtt_connection, mqttClient->mqtt_state.out_buffer, mqttClient->mqtt_state.out_buffer_length); - - QUEUE_Init(&mqttClient->msgQueue, QUEUE_BUFFER_SIZE); - - system_os_task(MQTT_Task, MQTT_TASK_PRIO, mqtt_procTaskQueue, MQTT_TASK_QUEUE_SIZE); - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient); - return true; -} -void ICACHE_FLASH_ATTR -MQTT_InitLWT(MQTT_Client *mqttClient, uint8_t* will_topic, uint8_t* will_msg, uint8_t will_qos, uint8_t will_retain) -{ - uint32_t temp; - temp = os_strlen(will_topic); - mqttClient->connect_info.will_topic = (uint8_t*)os_zalloc(temp + 1); - os_strcpy(mqttClient->connect_info.will_topic, will_topic); - mqttClient->connect_info.will_topic[temp] = 0; - - temp = os_strlen(will_msg); - mqttClient->connect_info.will_message = (uint8_t*)os_zalloc(temp + 1); - os_strcpy(mqttClient->connect_info.will_message, will_msg); - mqttClient->connect_info.will_message[temp] = 0; - - - mqttClient->connect_info.will_qos = will_qos; - mqttClient->connect_info.will_retain = will_retain; -} -/** - * @brief Begin connect to MQTT broker - * @param client: MQTT_Client reference - * @retval None - */ -void ICACHE_FLASH_ATTR -MQTT_Connect(MQTT_Client *mqttClient) -{ - if (mqttClient->pCon) { - // Clean up the old connection forcefully - using MQTT_Disconnect - // does not actually release the old connection until the - // disconnection callback is invoked. - mqtt_tcpclient_delete(mqttClient); - } - mqttClient->pCon = (struct espconn *)os_zalloc(sizeof(struct espconn)); - mqttClient->pCon->type = ESPCONN_TCP; - mqttClient->pCon->state = ESPCONN_NONE; - mqttClient->pCon->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp)); - mqttClient->pCon->proto.tcp->local_port = espconn_port(); - mqttClient->pCon->proto.tcp->remote_port = mqttClient->port; - mqttClient->pCon->reverse = mqttClient; - espconn_regist_connectcb(mqttClient->pCon, mqtt_tcpclient_connect_cb); - espconn_regist_reconcb(mqttClient->pCon, mqtt_tcpclient_recon_cb); - - mqttClient->keepAliveTick = 0; - mqttClient->reconnectTick = 0; - - - os_timer_disarm(&mqttClient->mqttTimer); - os_timer_setfn(&mqttClient->mqttTimer, (os_timer_func_t *)mqtt_timer, mqttClient); - os_timer_arm(&mqttClient->mqttTimer, 1000, 1); - - if (UTILS_StrToIP(mqttClient->host, &mqttClient->pCon->proto.tcp->remote_ip)) { - MQTT_INFO("TCP: Connect to ip %s:%d\r\n", mqttClient->host, mqttClient->port); - if (mqttClient->security) - { -#ifdef MQTT_SSL_ENABLE - espconn_secure_set_size(ESPCONN_CLIENT, MQTT_SSL_SIZE); - espconn_secure_connect(mqttClient->pCon); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else - { - espconn_connect(mqttClient->pCon); - } - } - else { - MQTT_INFO("TCP: Connect to domain %s:%d\r\n", mqttClient->host, mqttClient->port); - espconn_gethostbyname(mqttClient->pCon, mqttClient->host, &mqttClient->ip, mqtt_dns_found); - } - mqttClient->connState = TCP_CONNECTING; -} - -void ICACHE_FLASH_ATTR -MQTT_Disconnect(MQTT_Client *mqttClient) -{ - mqttClient->connState = TCP_DISCONNECTING; - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient); - os_timer_disarm(&mqttClient->mqttTimer); -} - -void ICACHE_FLASH_ATTR -MQTT_DeleteClient(MQTT_Client *mqttClient) -{ - if (NULL == mqttClient) - return; - - mqttClient->connState = MQTT_DELETED; - // if(TCP_DISCONNECTED == mqttClient->connState) { - // mqttClient->connState = MQTT_DELETED; - // } else if(MQTT_DELETED != mqttClient->connState) { - // mqttClient->connState = MQTT_DELETING; - // } - - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient); - os_timer_disarm(&mqttClient->mqttTimer); -} - -void ICACHE_FLASH_ATTR -MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb) -{ - mqttClient->connectedCb = connectedCb; -} - -void ICACHE_FLASH_ATTR -MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb) -{ - mqttClient->disconnectedCb = disconnectedCb; -} - -void ICACHE_FLASH_ATTR -MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb) -{ - mqttClient->dataCb = dataCb; -} - -void ICACHE_FLASH_ATTR -MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb) -{ - mqttClient->publishedCb = publishedCb; -} - -void ICACHE_FLASH_ATTR -MQTT_OnTimeout(MQTT_Client *mqttClient, MqttCallback timeoutCb) -{ - mqttClient->timeoutCb = timeoutCb; -} - - - -void ICACHE_FLASH_ATTR -MQTT_SetUserId(MQTT_Client *mqttClient, const char* client_id) -{ - if (mqttClient->connect_info.client_id != 0) { - os_free(mqttClient->connect_info.client_id); - mqttClient->connect_info.client_id = 0; - } - - - uint32_t len = os_strlen(client_id); - - mqttClient->connect_info.client_id = (uint8_t*)os_zalloc(len + 1); - if (len) { - os_strcpy(mqttClient->connect_info.client_id, client_id); - } - mqttClient->connect_info.client_id[len] = 0; -} - -void ICACHE_FLASH_ATTR -MQTT_SetUserPwd(MQTT_Client *mqttClient, const char* user, const char* pwd) -{ - uint32_t len; - - // free username - if (mqttClient->connect_info.username != 0) { - os_free(mqttClient->connect_info.username); - mqttClient->connect_info.username = 0; - } - // free password - if (mqttClient->connect_info.password != 0) { - os_free(mqttClient->connect_info.password); - mqttClient->connect_info.password = 0; - } - - - // copy username - len = os_strlen(user); - mqttClient->connect_info.username = (uint8_t*)os_zalloc(len + 1); - if (len) { - os_strcpy(mqttClient->connect_info.username, user); - } - mqttClient->connect_info.username[len] = 0; - - - // copy password - len = os_strlen(pwd); - mqttClient->connect_info.password = (uint8_t*)os_zalloc(len + 1); - if (len) { - os_strcpy(mqttClient->connect_info.password, pwd); - } - mqttClient->connect_info.password[len] = 0; - -} - diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt.h b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt.h deleted file mode 100644 index 6ef619433..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt.h +++ /dev/null @@ -1,152 +0,0 @@ -/* mqtt.h -* -* Copyright (c) 2014-2015, Tuan PM -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* * Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of Redis nor the names of its contributors may be used -* to endorse or promote products derived from this software without -* specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef USER_AT_MQTT_H_ -#define USER_AT_MQTT_H_ -#include "mqtt_config.h" -#include "mqtt_msg.h" -#include "user_interface.h" - -#include "queue.h" -typedef struct mqtt_event_data_t -{ - uint8_t type; - const char* topic; - const char* data; - uint16_t topic_length; - uint16_t data_length; - uint16_t data_offset; -} mqtt_event_data_t; - -typedef struct mqtt_state_t -{ - uint16_t port; - int auto_reconnect; - mqtt_connect_info_t* connect_info; - uint8_t* in_buffer; - uint8_t* out_buffer; - int in_buffer_length; - int out_buffer_length; - uint16_t message_length; - uint16_t message_length_read; - mqtt_message_t* outbound_message; - mqtt_connection_t mqtt_connection; - uint16_t pending_msg_id; - int pending_msg_type; - int pending_publish_qos; -} mqtt_state_t; - -typedef enum { - WIFI_INIT, - WIFI_CONNECTING, - WIFI_CONNECTING_ERROR, - WIFI_CONNECTED, - DNS_RESOLVE, - TCP_DISCONNECTING, - TCP_DISCONNECTED, - TCP_RECONNECT_DISCONNECTING, - TCP_RECONNECT_REQ, - TCP_RECONNECT, - TCP_CONNECTING, - TCP_CONNECTING_ERROR, - TCP_CONNECTED, - MQTT_CONNECT_SEND, - MQTT_CONNECT_SENDING, - MQTT_SUBSCIBE_SEND, - MQTT_SUBSCIBE_SENDING, - MQTT_DATA, - MQTT_KEEPALIVE_SEND, - MQTT_PUBLISH_RECV, - MQTT_PUBLISHING, - MQTT_DELETING, - MQTT_DELETED, -} tConnState; - -typedef void (*MqttCallback)(uint32_t *args); -typedef void (*MqttDataCallback)(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t lengh); - -typedef struct { - struct espconn *pCon; - uint8_t security; - uint8_t* host; - uint32_t port; - ip_addr_t ip; - mqtt_state_t mqtt_state; - mqtt_connect_info_t connect_info; - MqttCallback connectedCb; - MqttCallback disconnectedCb; - MqttCallback publishedCb; - MqttCallback timeoutCb; - MqttDataCallback dataCb; - ETSTimer mqttTimer; - uint32_t keepAliveTick; - uint32_t reconnectTick; - uint32_t sendTimeout; - tConnState connState; - QUEUE msgQueue; - void* user_data; -} MQTT_Client; - -#define SEC_NONSSL 0 -#define SEC_SSL 1 - -#define MQTT_FLAG_CONNECTED 1 -#define MQTT_FLAG_READY 2 -#define MQTT_FLAG_EXIT 4 - -#define MQTT_EVENT_TYPE_NONE 0 -#define MQTT_EVENT_TYPE_CONNECTED 1 -#define MQTT_EVENT_TYPE_DISCONNECTED 2 -#define MQTT_EVENT_TYPE_SUBSCRIBED 3 -#define MQTT_EVENT_TYPE_UNSUBSCRIBED 4 -#define MQTT_EVENT_TYPE_PUBLISH 5 -#define MQTT_EVENT_TYPE_PUBLISHED 6 -#define MQTT_EVENT_TYPE_EXITED 7 -#define MQTT_EVENT_TYPE_PUBLISH_CONTINUATION 8 - -void ICACHE_FLASH_ATTR MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security); -bool ICACHE_FLASH_ATTR MQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession); -void ICACHE_FLASH_ATTR MQTT_DeleteClient(MQTT_Client *mqttClient); -void ICACHE_FLASH_ATTR MQTT_InitLWT(MQTT_Client *mqttClient, uint8_t* will_topic, uint8_t* will_msg, uint8_t will_qos, uint8_t will_retain); - -void ICACHE_FLASH_ATTR MQTT_SetUserId(MQTT_Client *mqttClient, const char* client_id); -void ICACHE_FLASH_ATTR MQTT_SetUserPwd(MQTT_Client *mqttClient, const char* user_id, const char* pwd); - -void ICACHE_FLASH_ATTR MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb); -void ICACHE_FLASH_ATTR MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb); -void ICACHE_FLASH_ATTR MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb); -void ICACHE_FLASH_ATTR MQTT_OnTimeout(MQTT_Client *mqttClient, MqttCallback timeoutCb); -void ICACHE_FLASH_ATTR MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb); -bool ICACHE_FLASH_ATTR MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos); -bool ICACHE_FLASH_ATTR MQTT_UnSubscribe(MQTT_Client *client, char* topic); -void ICACHE_FLASH_ATTR MQTT_Connect(MQTT_Client *mqttClient); -void ICACHE_FLASH_ATTR MQTT_Disconnect(MQTT_Client *mqttClient); -bool ICACHE_FLASH_ATTR MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain); - -#endif /* USER_AT_MQTT_H_ */ diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt_config.h b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt_config.h deleted file mode 100644 index 5332f82ee..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt_config.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __MQTT_CONFIG_H__ -#define __MQTT_CONFIG_H__ - -//#define MQTT_SSL_ENABLE - -/*DEFAULT CONFIGURATIONS*/ - -#define MQTT_BUF_SIZE 1024 -//#define MQTT_KEEPALIVE 120 /*second*/ -#define MQTT_KEEPALIVE 15 /*second*/ - -#define MQTT_RECONNECT_TIMEOUT 5 /*second*/ - -#define QUEUE_BUFFER_SIZE 2048 - -//#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/ -#define PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/ - -#endif // __MQTT_CONFIG_H__ \ No newline at end of file diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt_msg.c b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt_msg.c deleted file mode 100644 index c2b320311..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt_msg.c +++ /dev/null @@ -1,487 +0,0 @@ -/* -* Copyright (c) 2014, Stephen Robinson -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holder nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -*/ - -#include -#include "mqtt_msg.h" -#include "mqtt_config.h" -#define MQTT_MAX_FIXED_HEADER_SIZE 3 - -enum mqtt_connect_flag -{ - MQTT_CONNECT_FLAG_USERNAME = 1 << 7, - MQTT_CONNECT_FLAG_PASSWORD = 1 << 6, - MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5, - MQTT_CONNECT_FLAG_WILL = 1 << 2, - MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1 -}; - -struct __attribute((__packed__)) mqtt_connect_variable_header -{ - uint8_t lengthMsb; - uint8_t lengthLsb; -#if defined(PROTOCOL_NAMEv31) - uint8_t magic[6]; -#elif defined(PROTOCOL_NAMEv311) - uint8_t magic[4]; -#else -#error "Please define protocol name" -#endif - uint8_t version; - uint8_t flags; - uint8_t keepaliveMsb; - uint8_t keepaliveLsb; -}; - -static int ICACHE_FLASH_ATTR append_string(mqtt_connection_t* connection, const char* string, int len) -{ - if (connection->message.length + len + 2 > connection->buffer_length) - return -1; - - connection->buffer[connection->message.length++] = len >> 8; - connection->buffer[connection->message.length++] = len & 0xff; - memcpy(connection->buffer + connection->message.length, string, len); - connection->message.length += len; - - return len + 2; -} - -static uint16_t ICACHE_FLASH_ATTR append_message_id(mqtt_connection_t* connection, uint16_t message_id) -{ - // If message_id is zero then we should assign one, otherwise - // we'll use the one supplied by the caller - while (message_id == 0) - message_id = ++connection->message_id; - - if (connection->message.length + 2 > connection->buffer_length) - return 0; - - connection->buffer[connection->message.length++] = message_id >> 8; - connection->buffer[connection->message.length++] = message_id & 0xff; - - return message_id; -} - -static int ICACHE_FLASH_ATTR init_message(mqtt_connection_t* connection) -{ - connection->message.length = MQTT_MAX_FIXED_HEADER_SIZE; - return MQTT_MAX_FIXED_HEADER_SIZE; -} - -static mqtt_message_t* ICACHE_FLASH_ATTR fail_message(mqtt_connection_t* connection) -{ - connection->message.data = connection->buffer; - connection->message.length = 0; - return &connection->message; -} - -static mqtt_message_t* ICACHE_FLASH_ATTR fini_message(mqtt_connection_t* connection, int type, int dup, int qos, int retain) -{ - int remaining_length = connection->message.length - MQTT_MAX_FIXED_HEADER_SIZE; - - if (remaining_length > 127) - { - connection->buffer[0] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1); - connection->buffer[1] = 0x80 | (remaining_length % 128); - connection->buffer[2] = remaining_length / 128; - connection->message.length = remaining_length + 3; - connection->message.data = connection->buffer; - } - else - { - connection->buffer[1] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1); - connection->buffer[2] = remaining_length; - connection->message.length = remaining_length + 2; - connection->message.data = connection->buffer + 1; - } - - return &connection->message; -} - -void ICACHE_FLASH_ATTR mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length) -{ - memset(connection, 0, sizeof(mqtt_connection_t)); - connection->buffer = buffer; - connection->buffer_length = buffer_length; -} - -int ICACHE_FLASH_ATTR mqtt_get_total_length(uint8_t* buffer, uint16_t length) -{ - int i; - int totlen = 0; - - for (i = 1; i < length; ++i) - { - totlen += (buffer[i] & 0x7f) << (7 * (i - 1)); - if ((buffer[i] & 0x80) == 0) - { - ++i; - break; - } - } - totlen += i; - - return totlen; -} - -const char* ICACHE_FLASH_ATTR mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length) -{ - int i; - int totlen = 0; - int topiclen; - - for (i = 1; i < *length; ++i) - { - totlen += (buffer[i] & 0x7f) << (7 * (i - 1)); - if ((buffer[i] & 0x80) == 0) - { - ++i; - break; - } - } - totlen += i; - - if (i + 2 >= *length) - return NULL; - topiclen = buffer[i++] << 8; - topiclen |= buffer[i++]; - - if (i + topiclen > *length) - return NULL; - - *length = topiclen; - return (const char*)(buffer + i); -} - -const char* ICACHE_FLASH_ATTR mqtt_get_publish_data(uint8_t* buffer, uint16_t* length) -{ - int i; - int totlen = 0; - int topiclen; - int blength = *length; - *length = 0; - - for (i = 1; i < blength; ++i) - { - totlen += (buffer[i] & 0x7f) << (7 * (i - 1)); - if ((buffer[i] & 0x80) == 0) - { - ++i; - break; - } - } - totlen += i; - - if (i + 2 >= blength) - return NULL; - topiclen = buffer[i++] << 8; - topiclen |= buffer[i++]; - - if (i + topiclen >= blength) - return NULL; - - i += topiclen; - - if (mqtt_get_qos(buffer) > 0) - { - if (i + 2 >= blength) - return NULL; - i += 2; - } - - if (totlen < i) - return NULL; - - if (totlen <= blength) - *length = totlen - i; - else - *length = blength - i; - return (const char*)(buffer + i); -} - -uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length) -{ - if (length < 1) - return 0; - - switch (mqtt_get_type(buffer)) - { - case MQTT_MSG_TYPE_PUBLISH: - { - int i; - int topiclen; - - for (i = 1; i < length; ++i) - { - if ((buffer[i] & 0x80) == 0) - { - ++i; - break; - } - } - - if (i + 2 >= length) - return 0; - topiclen = buffer[i++] << 8; - topiclen |= buffer[i++]; - - if (i + topiclen >= length) - return 0; - i += topiclen; - - if (mqtt_get_qos(buffer) > 0) - { - if (i + 2 >= length) - return 0; - //i += 2; - } else { - return 0; - } - - return (buffer[i] << 8) | buffer[i + 1]; - } - case MQTT_MSG_TYPE_PUBACK: - case MQTT_MSG_TYPE_PUBREC: - case MQTT_MSG_TYPE_PUBREL: - case MQTT_MSG_TYPE_PUBCOMP: - case MQTT_MSG_TYPE_SUBACK: - case MQTT_MSG_TYPE_UNSUBACK: - case MQTT_MSG_TYPE_SUBSCRIBE: - { - // This requires the remaining length to be encoded in 1 byte, - // which it should be. - if (length >= 4 && (buffer[1] & 0x80) == 0) - return (buffer[2] << 8) | buffer[3]; - else - return 0; - } - - default: - return 0; - } -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info) -{ - struct mqtt_connect_variable_header* variable_header; - - init_message(connection); - - if (connection->message.length + sizeof(*variable_header) > connection->buffer_length) - return fail_message(connection); - variable_header = (void*)(connection->buffer + connection->message.length); - connection->message.length += sizeof(*variable_header); - - variable_header->lengthMsb = 0; -#if defined(PROTOCOL_NAMEv31) - variable_header->lengthLsb = 6; - memcpy(variable_header->magic, "MQIsdp", 6); - variable_header->version = 3; -#elif defined(PROTOCOL_NAMEv311) - variable_header->lengthLsb = 4; - memcpy(variable_header->magic, "MQTT", 4); - variable_header->version = 4; -#else -#error "Please define protocol name" -#endif - - variable_header->flags = 0; - variable_header->keepaliveMsb = info->keepalive >> 8; - variable_header->keepaliveLsb = info->keepalive & 0xff; - - if (info->clean_session) - variable_header->flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; - - if (info->client_id == NULL) - { - /* Never allowed */ - return fail_message(connection); - } - else if (info->client_id[0] == '\0') - { -#ifdef PROTOCOL_NAMEv311 - /* Allowed. Format 0 Length ID */ - append_string(connection, info->client_id, 2) ; -#else - /* 0 Length not allowed */ - return fail_message(connection); -#endif - } - else - { - /* No 0 data and at least 1 long. Good to go. */ - if(append_string(connection, info->client_id, strlen(info->client_id)) < 0) - return fail_message(connection); - } - - if (info->will_topic != NULL && info->will_topic[0] != '\0') - { - if (append_string(connection, info->will_topic, strlen(info->will_topic)) < 0) - return fail_message(connection); - - if (append_string(connection, info->will_message, strlen(info->will_message)) < 0) - return fail_message(connection); - - variable_header->flags |= MQTT_CONNECT_FLAG_WILL; - if (info->will_retain) - variable_header->flags |= MQTT_CONNECT_FLAG_WILL_RETAIN; - variable_header->flags |= (info->will_qos & 3) << 3; - } - - if (info->username != NULL && info->username[0] != '\0') - { - if (append_string(connection, info->username, strlen(info->username)) < 0) - return fail_message(connection); - - variable_header->flags |= MQTT_CONNECT_FLAG_USERNAME; - } - - if (info->password != NULL && info->password[0] != '\0') - { - if (append_string(connection, info->password, strlen(info->password)) < 0) - return fail_message(connection); - - variable_header->flags |= MQTT_CONNECT_FLAG_PASSWORD; - } - - return fini_message(connection, MQTT_MSG_TYPE_CONNECT, 0, 0, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id) -{ - init_message(connection); - - if (topic == NULL || topic[0] == '\0') - return fail_message(connection); - - if (append_string(connection, topic, strlen(topic)) < 0) - return fail_message(connection); - - if (qos > 0) - { - if ((*message_id = append_message_id(connection, 0)) == 0) - return fail_message(connection); - } - else - *message_id = 0; - - if (connection->message.length + data_length > connection->buffer_length) - return fail_message(connection); - memcpy(connection->buffer + connection->message.length, data, data_length); - connection->message.length += data_length; - - return fini_message(connection, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id) -{ - init_message(connection); - if (append_message_id(connection, message_id) == 0) - return fail_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_PUBACK, 0, 0, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id) -{ - init_message(connection); - if (append_message_id(connection, message_id) == 0) - return fail_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_PUBREC, 0, 0, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id) -{ - init_message(connection); - if (append_message_id(connection, message_id) == 0) - return fail_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_PUBREL, 0, 1, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id) -{ - init_message(connection); - if (append_message_id(connection, message_id) == 0) - return fail_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_PUBCOMP, 0, 0, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id) -{ - init_message(connection); - - if (topic == NULL || topic[0] == '\0') - return fail_message(connection); - - if ((*message_id = append_message_id(connection, 0)) == 0) - return fail_message(connection); - - if (append_string(connection, topic, strlen(topic)) < 0) - return fail_message(connection); - - if (connection->message.length + 1 > connection->buffer_length) - return fail_message(connection); - connection->buffer[connection->message.length++] = qos; - - return fini_message(connection, MQTT_MSG_TYPE_SUBSCRIBE, 0, 1, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id) -{ - init_message(connection); - - if (topic == NULL || topic[0] == '\0') - return fail_message(connection); - - if ((*message_id = append_message_id(connection, 0)) == 0) - return fail_message(connection); - - if (append_string(connection, topic, strlen(topic)) < 0) - return fail_message(connection); - - return fini_message(connection, MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection) -{ - init_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection) -{ - init_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_PINGRESP, 0, 0, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection) -{ - init_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_DISCONNECT, 0, 0, 0); -} diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt_msg.h b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt_msg.h deleted file mode 100644 index be3cc55cb..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/mqtt_msg.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * File: mqtt_msg.h - * Author: Minh Tuan - * - * Created on July 12, 2014, 1:05 PM - */ - -#ifndef MQTT_MSG_H -#define MQTT_MSG_H -#include "user_config.h" -#include "c_types.h" -#ifdef __cplusplus -extern "C" { -#endif - -/* -* Copyright (c) 2014, Stephen Robinson -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holder nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -*/ -/* 7 6 5 4 3 2 1 0*/ -/*| --- Message Type---- | DUP Flag | QoS Level | Retain | -/* Remaining Length */ - - -enum mqtt_message_type -{ - MQTT_MSG_TYPE_CONNECT = 1, - MQTT_MSG_TYPE_CONNACK = 2, - MQTT_MSG_TYPE_PUBLISH = 3, - MQTT_MSG_TYPE_PUBACK = 4, - MQTT_MSG_TYPE_PUBREC = 5, - MQTT_MSG_TYPE_PUBREL = 6, - MQTT_MSG_TYPE_PUBCOMP = 7, - MQTT_MSG_TYPE_SUBSCRIBE = 8, - MQTT_MSG_TYPE_SUBACK = 9, - MQTT_MSG_TYPE_UNSUBSCRIBE = 10, - MQTT_MSG_TYPE_UNSUBACK = 11, - MQTT_MSG_TYPE_PINGREQ = 12, - MQTT_MSG_TYPE_PINGRESP = 13, - MQTT_MSG_TYPE_DISCONNECT = 14 -}; - -enum mqtt_connect_return_code -{ - CONNECTION_ACCEPTED = 0, - CONNECTION_REFUSE_PROTOCOL, - CONNECTION_REFUSE_ID_REJECTED, - CONNECTION_REFUSE_SERVER_UNAVAILABLE, - CONNECTION_REFUSE_BAD_USERNAME, - CONNECTION_REFUSE_NOT_AUTHORIZED -}; - -typedef struct mqtt_message -{ - uint8_t* data; - uint16_t length; - -} mqtt_message_t; - -typedef struct mqtt_connection -{ - mqtt_message_t message; - - uint16_t message_id; - uint8_t* buffer; - uint16_t buffer_length; - -} mqtt_connection_t; - -typedef struct mqtt_connect_info -{ - char* client_id; - char* username; - char* password; - char* will_topic; - char* will_message; - uint32_t keepalive; - int will_qos; - int will_retain; - int clean_session; - -} mqtt_connect_info_t; - - -static inline int ICACHE_FLASH_ATTR mqtt_get_type(uint8_t* buffer) { return (buffer[0] & 0xf0) >> 4; } -static inline int ICACHE_FLASH_ATTR mqtt_get_connect_return_code(uint8_t* buffer) { return buffer[3]; } -static inline int ICACHE_FLASH_ATTR mqtt_get_dup(uint8_t* buffer) { return (buffer[0] & 0x08) >> 3; } -static inline int ICACHE_FLASH_ATTR mqtt_get_qos(uint8_t* buffer) { return (buffer[0] & 0x06) >> 1; } -static inline int ICACHE_FLASH_ATTR mqtt_get_retain(uint8_t* buffer) { return (buffer[0] & 0x01); } - -void ICACHE_FLASH_ATTR mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length); -int ICACHE_FLASH_ATTR mqtt_get_total_length(uint8_t* buffer, uint16_t length); -const char* ICACHE_FLASH_ATTR mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length); -const char* ICACHE_FLASH_ATTR mqtt_get_publish_data(uint8_t* buffer, uint16_t* length); -uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length); - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection); - - -#ifdef __cplusplus -} -#endif - -#endif /* MQTT_MSG_H */ - diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/proto.c b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/proto.c deleted file mode 100644 index 84078b233..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/proto.c +++ /dev/null @@ -1,129 +0,0 @@ -#include "proto.h" -#include "ringbuf.h" -I8 ICACHE_FLASH_ATTR PROTO_Init(PROTO_PARSER *parser, PROTO_PARSE_CALLBACK *completeCallback, U8 *buf, U16 bufSize) -{ - parser->buf = buf; - parser->bufSize = bufSize; - parser->dataLen = 0; - parser->callback = completeCallback; - parser->isEsc = 0; - return 0; -} - -I8 ICACHE_FLASH_ATTR PROTO_ParseByte(PROTO_PARSER *parser, U8 value) -{ - switch (value) { - case 0x7D: - parser->isEsc = 1; - break; - - case 0x7E: - parser->dataLen = 0; - parser->isEsc = 0; - parser->isBegin = 1; - break; - - case 0x7F: - if (parser->callback != NULL) - parser->callback(); - parser->isBegin = 0; - return 0; - break; - - default: - if (parser->isBegin == 0) break; - - if (parser->isEsc) { - value ^= 0x20; - parser->isEsc = 0; - } - - if (parser->dataLen < parser->bufSize) - parser->buf[parser->dataLen++] = value; - - break; - } - return -1; -} - -I8 ICACHE_FLASH_ATTR PROTO_Parse(PROTO_PARSER *parser, U8 *buf, U16 len) -{ - while (len--) - PROTO_ParseByte(parser, *buf++); - - return 0; -} -I16 ICACHE_FLASH_ATTR PROTO_ParseRb(RINGBUF* rb, U8 *bufOut, U16* len, U16 maxBufLen) -{ - U8 c; - - PROTO_PARSER proto; - PROTO_Init(&proto, NULL, bufOut, maxBufLen); - while (RINGBUF_Get(rb, &c) == 0) { - if (PROTO_ParseByte(&proto, c) == 0) { - *len = proto.dataLen; - return 0; - } - } - return -1; -} -I16 ICACHE_FLASH_ATTR PROTO_Add(U8 *buf, const U8 *packet, I16 bufSize) -{ - U16 i = 2; - U16 len = *(U16*) packet; - - if (bufSize < 1) return -1; - - *buf++ = 0x7E; - bufSize--; - - while (len--) { - switch (*packet) { - case 0x7D: - case 0x7E: - case 0x7F: - if (bufSize < 2) return -1; - *buf++ = 0x7D; - *buf++ = *packet++ ^ 0x20; - i += 2; - bufSize -= 2; - break; - default: - if (bufSize < 1) return -1; - *buf++ = *packet++; - i++; - bufSize--; - break; - } - } - - if (bufSize < 1) return -1; - *buf++ = 0x7F; - - return i; -} - -I16 ICACHE_FLASH_ATTR PROTO_AddRb(RINGBUF *rb, const U8 *packet, I16 len) -{ - U16 i = 2; - if (RINGBUF_Put(rb, 0x7E) == -1) return -1; - while (len--) { - switch (*packet) { - case 0x7D: - case 0x7E: - case 0x7F: - if (RINGBUF_Put(rb, 0x7D) == -1) return -1; - if (RINGBUF_Put(rb, *packet++ ^ 0x20) == -1) return -1; - i += 2; - break; - default: - if (RINGBUF_Put(rb, *packet++) == -1) return -1; - i++; - break; - } - } - if (RINGBUF_Put(rb, 0x7F) == -1) return -1; - - return i; -} - diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/proto.h b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/proto.h deleted file mode 100644 index a405bcb95..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/proto.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * File: proto.h - * Author: ThuHien - * - * Created on November 23, 2012, 8:57 AM - */ - -#ifndef _PROTO_H_ -#define _PROTO_H_ -#include -#include "typedef.h" -#include "ringbuf.h" - -typedef void(PROTO_PARSE_CALLBACK)(); - -typedef struct { - U8 *buf; - U16 bufSize; - U16 dataLen; - U8 isEsc; - U8 isBegin; - PROTO_PARSE_CALLBACK* callback; -} PROTO_PARSER; - -I8 ICACHE_FLASH_ATTR PROTO_Init(PROTO_PARSER *parser, PROTO_PARSE_CALLBACK *completeCallback, U8 *buf, U16 bufSize); -I8 ICACHE_FLASH_ATTR PROTO_Parse(PROTO_PARSER *parser, U8 *buf, U16 len); -I16 ICACHE_FLASH_ATTR PROTO_Add(U8 *buf, const U8 *packet, I16 bufSize); -I16 ICACHE_FLASH_ATTR PROTO_AddRb(RINGBUF *rb, const U8 *packet, I16 len); -I8 ICACHE_FLASH_ATTR PROTO_ParseByte(PROTO_PARSER *parser, U8 value); -I16 ICACHE_FLASH_ATTR PROTO_ParseRb(RINGBUF *rb, U8 *bufOut, U16* len, U16 maxBufLen); -#endif - diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/queue.c b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/queue.c deleted file mode 100644 index 95bbec0cd..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/queue.c +++ /dev/null @@ -1,75 +0,0 @@ -/* str_queue.c -* -* Copyright (c) 2014-2015, Tuan PM -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* * Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of Redis nor the names of its contributors may be used -* to endorse or promote products derived from this software without -* specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*/ -#include "queue.h" - -#include "user_interface.h" -#include "osapi.h" -#include "os_type.h" -#include "mem.h" -#include "proto.h" - -uint8_t *last_rb_p_r; -uint8_t *last_rb_p_w; -uint32_t last_fill_cnt; - -void ICACHE_FLASH_ATTR QUEUE_Init(QUEUE *queue, int bufferSize) -{ - queue->buf = (uint8_t*)os_zalloc(bufferSize); - RINGBUF_Init(&queue->rb, queue->buf, bufferSize); -} -int32_t ICACHE_FLASH_ATTR QUEUE_Puts(QUEUE *queue, uint8_t* buffer, uint16_t len) -{ - uint32_t ret; - - last_rb_p_r = queue->rb.p_r; - last_rb_p_w = queue->rb.p_w; - last_fill_cnt = queue->rb.fill_cnt; - - ret = PROTO_AddRb(&queue->rb, buffer, len); - if (ret == -1) { - // rolling ring buffer back - queue->rb.p_r = last_rb_p_r; - queue->rb.p_w = last_rb_p_w; - queue->rb.fill_cnt = last_fill_cnt; - } - return ret; -} -int32_t ICACHE_FLASH_ATTR QUEUE_Gets(QUEUE *queue, uint8_t* buffer, uint16_t* len, uint16_t maxLen) -{ - - return PROTO_ParseRb(&queue->rb, buffer, len, maxLen); -} - -BOOL ICACHE_FLASH_ATTR QUEUE_IsEmpty(QUEUE *queue) -{ - if (queue->rb.fill_cnt <= 0) - return TRUE; - return FALSE; -} diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/queue.h b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/queue.h deleted file mode 100644 index 79107f2d5..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/queue.h +++ /dev/null @@ -1,44 +0,0 @@ -/* str_queue.h -- -* -* Copyright (c) 2014-2015, Tuan PM -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* * Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of Redis nor the names of its contributors may be used -* to endorse or promote products derived from this software without -* specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef USER_QUEUE_H_ -#define USER_QUEUE_H_ -#include "os_type.h" -#include "ringbuf.h" -typedef struct { - uint8_t *buf; - RINGBUF rb; -} QUEUE; - -void ICACHE_FLASH_ATTR QUEUE_Init(QUEUE *queue, int bufferSize); -int32_t ICACHE_FLASH_ATTR QUEUE_Puts(QUEUE *queue, uint8_t* buffer, uint16_t len); -int32_t ICACHE_FLASH_ATTR QUEUE_Gets(QUEUE *queue, uint8_t* buffer, uint16_t* len, uint16_t maxLen); -bool ICACHE_FLASH_ATTR QUEUE_IsEmpty(QUEUE *queue); -#endif /* USER_QUEUE_H_ */ diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/ringbuf.c b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/ringbuf.c deleted file mode 100644 index fc882fd5c..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/ringbuf.c +++ /dev/null @@ -1,67 +0,0 @@ -/** -* \file -* Ring Buffer library -*/ - -#include "ringbuf.h" - - -/** -* \brief init a RINGBUF object -* \param r pointer to a RINGBUF object -* \param buf pointer to a byte array -* \param size size of buf -* \return 0 if successfull, otherwise failed -*/ -I16 ICACHE_FLASH_ATTR RINGBUF_Init(RINGBUF *r, U8* buf, I32 size) -{ - if (r == NULL || buf == NULL || size < 2) return -1; - - r->p_o = r->p_r = r->p_w = buf; - r->fill_cnt = 0; - r->size = size; - - return 0; -} -/** -* \brief put a character into ring buffer -* \param r pointer to a ringbuf object -* \param c character to be put -* \return 0 if successfull, otherwise failed -*/ -I16 ICACHE_FLASH_ATTR RINGBUF_Put(RINGBUF *r, U8 c) -{ - if (r->fill_cnt >= r->size)return -1; // ring buffer is full, this should be atomic operation - - - r->fill_cnt++; // increase filled slots count, this should be atomic operation - - - *r->p_w++ = c; // put character into buffer - - if (r->p_w >= r->p_o + r->size) // rollback if write pointer go pass - r->p_w = r->p_o; // the physical boundary - - return 0; -} -/** -* \brief get a character from ring buffer -* \param r pointer to a ringbuf object -* \param c read character -* \return 0 if successfull, otherwise failed -*/ -I16 ICACHE_FLASH_ATTR RINGBUF_Get(RINGBUF *r, U8* c) -{ - if (r->fill_cnt <= 0)return -1; // ring buffer is empty, this should be atomic operation - - - r->fill_cnt--; // decrease filled slots count - - - *c = *r->p_r++; // get the character out - - if (r->p_r >= r->p_o + r->size) // rollback if write pointer go pass - r->p_r = r->p_o; // the physical boundary - - return 0; -} diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/ringbuf.h b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/ringbuf.h deleted file mode 100644 index f1a4f7e8b..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/ringbuf.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _RING_BUF_H_ -#define _RING_BUF_H_ - -#include -#include -#include "typedef.h" - -typedef struct { - U8* p_o; /**< Original pointer */ - U8* volatile p_r; /**< Read pointer */ - U8* volatile p_w; /**< Write pointer */ - volatile I32 fill_cnt; /**< Number of filled slots */ - I32 size; /**< Buffer size */ -} RINGBUF; - -I16 ICACHE_FLASH_ATTR RINGBUF_Init(RINGBUF *r, U8* buf, I32 size); -I16 ICACHE_FLASH_ATTR RINGBUF_Put(RINGBUF *r, U8 c); -I16 ICACHE_FLASH_ATTR RINGBUF_Get(RINGBUF *r, U8* c); -#endif diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/typedef.h b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/typedef.h deleted file mode 100644 index 887001ace..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/typedef.h +++ /dev/null @@ -1,17 +0,0 @@ -/** -* \file -* Standard Types definition -*/ - -#ifndef _TYPE_DEF_H_ -#define _TYPE_DEF_H_ - -typedef char I8; -typedef unsigned char U8; -typedef short I16; -typedef unsigned short U16; -typedef long I32; -typedef unsigned long U32; -typedef unsigned long long U64; - -#endif diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/utils.c b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/utils.c deleted file mode 100644 index ac4c9272b..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/utils.c +++ /dev/null @@ -1,149 +0,0 @@ -/* -* Copyright (c) 2014, Tuan PM -* Email: tuanpm@live.com -* -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holder nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -*/ -#include -#include -#include -#include -#include -#include "utils.h" - - -uint8_t ICACHE_FLASH_ATTR UTILS_IsIPV4 (int8_t *str) -{ - uint8_t segs = 0; /* Segment count. */ - uint8_t chcnt = 0; /* Character count within segment. */ - uint8_t accum = 0; /* Accumulator for segment. */ - /* Catch NULL pointer. */ - if (str == 0) - return 0; - /* Process every character in string. */ - - while (*str != '\0') { - /* Segment changeover. */ - - if (*str == '.') { - /* Must have some digits in segment. */ - if (chcnt == 0) - return 0; - /* Limit number of segments. */ - if (++segs == 4) - return 0; - /* Reset segment values and restart loop. */ - chcnt = accum = 0; - str++; - continue; - } - - /* Check numeric. */ - if ((*str < '0') || (*str > '9')) - return 0; - - /* Accumulate and check segment. */ - - if ((accum = accum * 10 + *str - '0') > 255) - return 0; - /* Advance other segment specific stuff and continue loop. */ - - chcnt++; - str++; - } - - /* Check enough segments and enough characters in last segment. */ - - if (segs != 3) - return 0; - if (chcnt == 0) - return 0; - /* Address okay. */ - - return 1; -} -uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const int8_t* str, void *ip) -{ - - /* The count of the number of bytes processed. */ - int i; - /* A pointer to the next digit to process. */ - const char * start; - - start = str; - for (i = 0; i < 4; i++) { - /* The digit being processed. */ - char c; - /* The value of this byte. */ - int n = 0; - while (1) { - c = * start; - start++; - if (c >= '0' && c <= '9') { - n *= 10; - n += c - '0'; - } - /* We insist on stopping at "." if we are still parsing - the first, second, or third numbers. If we have reached - the end of the numbers, we will allow any character. */ - else if ((i < 3 && c == '.') || i == 3) { - break; - } - else { - return 0; - } - } - if (n >= 256) { - return 0; - } - ((uint8_t*)ip)[i] = n; - } - return 1; - -} -uint32_t ICACHE_FLASH_ATTR UTILS_Atoh(const int8_t *s) -{ - uint32_t value = 0, digit; - int8_t c; - - while ((c = *s++)) { - if ('0' <= c && c <= '9') - digit = c - '0'; - else if ('A' <= c && c <= 'F') - digit = c - 'A' + 10; - else if ('a' <= c && c <= 'f') - digit = c - 'a' + 10; - else break; - - value = (value << 4) | digit; - } - - return value; -} - diff --git a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/utils.h b/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/utils.h deleted file mode 100644 index fe2874803..000000000 --- a/lib/esp-mqtt-arduino-1.0.1.02.1/src/mqtt/utils.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _UTILS_H_ -#define _UTILS_H_ - -#include "c_types.h" - -uint32_t ICACHE_FLASH_ATTR UTILS_Atoh(const int8_t *s); -uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const int8_t* str, void *ip); -uint8_t ICACHE_FLASH_ATTR UTILS_IsIPV4 (int8_t *str); -#endif From 0826249cff5c7c4419cf24c452b22a524c7506e5 Mon Sep 17 00:00:00 2001 From: Yuval <38878996+rt400@users.noreply.github.com> Date: Tue, 2 Oct 2018 19:25:18 +0300 Subject: [PATCH 0227/2222] Create Hebrew Language File --- sonoff/language/he-HE.h | 543 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 543 insertions(+) create mode 100644 sonoff/language/he-HE.h diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h new file mode 100644 index 000000000..be6094233 --- /dev/null +++ b/sonoff/language/he-HE.h @@ -0,0 +1,543 @@ +/* + he-HE.h - localization for Hebrew - Israel for Sonoff-Tasmota + + Copyright (C) 2018 Yuval Mejahez + + 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_HE_HE_H_ +#define _LANGUAGE_HE_HE_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. + * + * Updated until v5.14.0b +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1037 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "he" + +// "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 "SunMonTueWedThuFriSat" +#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "מנהל" +#define D_AIR_QUALITY "איכות אוויר" +#define D_AP "AP" // Access Point +#define D_AS "as" +#define D_AUTO "AUTO" +#define D_BLINK "מהבהב" +#define D_BLINKOFF "כיבוי היבהוב" +#define D_BOOT_COUNT "מונה הפעלה מחדש" +#define D_BRIGHTLIGHT "בהירות" +#define D_BSSID "BSSId" +#define D_BUTTON "לחצן" +#define D_BY "by" // Written by me +#define D_BYTES "בייט" +#define D_CELSIUS "צלזיוס" +#define D_CHANNEL "ערוץ" +#define D_CO2 "Carbon dioxide" +#define D_CODE "קוד" // Button code +#define D_COLDLIGHT "קור" +#define D_COMMAND "פקודה" +#define D_CONNECTED "מחובר" +#define D_COUNT "סופר" +#define D_COUNTER "מונה" +#define D_CURRENT "נוכחי" // As in Voltage and Current +#define D_DATA "נתונים" +#define D_DARKLIGHT "חושך" +#define D_DEBUG "באגים" +#define D_DISABLED "מבוטל" +#define D_DISTANCE "מרחק" +#define D_DNS_SERVER "DNS שרת" +#define D_DONE "סיים" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "הדמיה" +#define D_ENABLED "מאופשר" +#define D_ERASE "מחיקה" +#define D_ERROR "שגיאה" +#define D_FAHRENHEIT "פרנהייט" +#define D_FAILED "נכשל" +#define D_FALLBACK "חזרה" +#define D_FALLBACK_TOPIC "נושא לחזרה" +#define D_FALSE "שגוי" +#define D_FILE "קובץ" +#define D_FREE_MEMORY "זכרון פנוי" +#define D_FREQUENCY "תדר" +#define D_GAS "גז" +#define D_GATEWAY "שער" +#define D_GROUP "קבוצה" +#define D_HOST "מארח" +#define D_HOSTNAME "שם מארח" +#define D_HUMIDITY "לחות" +#define D_ILLUMINANCE "רמת חשיפה" +#define D_IMMEDIATE "מידי" // Button immediate +#define D_INDEX "אינדקס" +#define D_INFO "מידע" +#define D_INFRARED "אינפרא" +#define D_INITIALIZED "מאותחל" +#define D_IP_ADDRESS "IP כתובת" +#define D_LIGHT "אור" +#define D_LWT "LWT" +#define D_MODULE "מודול" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-press" +#define D_NOISE "רעש" +#define D_NONE "כלום" +#define D_OFF "כבוי" +#define D_OFFLINE "מנותק" +#define D_OK "אוקיי" +#define D_ON "פועל" +#define D_ONLINE "מחובר" +#define D_PASSWORD "סיסמא" +#define D_PORT "פורט" +#define D_POWER_FACTOR "גורם כוח" +#define D_POWERUSAGE "כוח" +#define D_POWERUSAGE_ACTIVE "כוח פעיל" +#define D_POWERUSAGE_APPARENT "כוח לכאורה" +#define D_POWERUSAGE_REACTIVE "כוח תגובתי" +#define D_PRESSURE "לחץ" +#define D_PRESSUREATSEALEVEL "לחץ ימי" +#define D_PROGRAM_FLASH_SIZE "גודל תוכנית פלאש" +#define D_PROGRAM_SIZE "גודל תוכנית" +#define D_PROJECT "פרויקט" +#define D_RECEIVED "התקבל" +#define D_RESTART "איתחול" +#define D_RESTARTING "הפעלה מחדש" +#define D_RESTART_REASON "סיבת הפעלה מחדש" +#define D_RESTORE "שחזור" +#define D_RETAINED "שמור" +#define D_RULE "חוק" +#define D_SAVE "שמירה" +#define D_SENSOR "חיישן" +#define D_SSID "SSId" +#define D_START "התחלה" +#define D_STD_TIME "STD" +#define D_STOP "עצירה" +#define D_SUBNET_MASK "רשת מסכת משנה" +#define D_SUBSCRIBE_TO "הרשם ל" +#define D_SUCCESSFUL "הצליח" +#define D_SUNRISE "זריחה" +#define D_SUNSET "שקיעה" +#define D_TEMPERATURE "טמפרטורה" +#define D_TO "ל" +#define D_TOGGLE "מתג" +#define D_TOPIC "נושא" +#define D_TRANSMIT "עבר" +#define D_TRUE "נכון" +#define D_TVOC "TVOC" +#define D_UPGRADE "שדרוג" +#define D_UPLOAD "העלאה" +#define D_UPTIME "זמן עליה" +#define D_USER "משתמש" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV אינדקס" +#define D_UV_LEVEL "UV רמת" +#define D_VERSION "גרסה" +#define D_VOLTAGE "מתח" +#define D_WARMLIGHT "חום" +#define D_WEB_SERVER "Web שרת" + +// sonoff.ino +#define D_WARNING_MINIMAL_VERSION "WARNING This version does not support persistent settings" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serial logging disabled" +#define D_SYSLOG_LOGGING_REENABLED "Syslog logging re-enabled" + +#define D_SET_BAUDRATE_TO "Set Baudrate to" +#define D_RECEIVED_TOPIC "Received Topic" +#define D_DATA_SIZE "Data Size" +#define D_ANALOG_INPUT "אנלוגי" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" +#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes" +#define D_FAILED_TO_START "failed to start" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "Connecting to AP" +#define D_IN_MODE "in mode" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connect failed as no IP address received" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Connect failed as AP cannot be reached" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Connect failed with AP incorrect password" +#define D_CONNECT_FAILED_AP_TIMEOUT "Connect failed with AP timeout" +#define D_ATTEMPTING_CONNECTION "Attempting connection..." +#define D_CHECKING_CONNECTION "Checking connection..." +#define D_QUERY_DONE "Query done. MQTT services found" +#define D_MQTT_SERVICE_FOUND "MQTT service found on" +#define D_FOUND_AT "found at" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host not found" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Saved to flash at" +#define D_LOADED_FROM_FLASH_AT "Loaded from flash at" +#define D_USE_DEFAULTS "השתמש בהגדרות ברירת המחדל" +#define D_ERASED_SECTOR "סקטור מחוק" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "JavaScript - כדי להשתמש ב קושחה אסמוטה אנא הפעל" +#define D_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" +#define D_FILE_NOT_FOUND "File Not Found" +#define D_REDIRECTED "Redirected to captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" +#define D_TRYING_TO_CONNECT "מנסה לחבר את ההתקן לרשת" + +#define D_RESTART_IN "הפעלה מחדש תןך" +#define D_SECONDS "שניות" +#define D_DEVICE_WILL_RESTART "ההתקן יופעל מחדש בעוד מס' שניות" +#define D_BUTTON_TOGGLE "מצב" +#define D_CONFIGURATION "הגדרות" +#define D_INFORMATION "מידע" +#define D_FIRMWARE_UPGRADE "שדרוג קושחה" +#define D_CONSOLE "קונסול" +#define D_CONFIRM_RESTART "אישור הפעלה מחדש" + +#define D_CONFIGURE_MODULE "הגדרות מודול" +#define D_CONFIGURE_WIFI "WIFI הגדרות" +#define D_CONFIGURE_MQTT "MQTT הגדרות" +#define D_CONFIGURE_DOMOTICZ "Domoticz הגדרות" +#define D_CONFIGURE_LOGGING "הגדרת לוגים" +#define D_CONFIGURE_OTHER "הגדרות שונות" +#define D_CONFIRM_RESET_CONFIGURATION "אישור שינוי הגדרות" +#define D_RESET_CONFIGURATION "אתחול הגדרות" +#define D_BACKUP_CONFIGURATION "גיבוי הגדרות" +#define D_RESTORE_CONFIGURATION "שחזור הגדרות" +#define D_MAIN_MENU "תפריט ראשי" + +#define D_MODULE_PARAMETERS "מודול פרמטרים" +#define D_MODULE_TYPE "סוג מודול" +#define D_GPIO " רגל " +#define D_SERIAL_IN "כניסת סריאל" +#define D_SERIAL_OUT "יציאת סריאל" + +#define D_WIFI_PARAMETERS "Wifi פרמטרים" +#define D_SCAN_FOR_WIFI_NETWORKS "סורק עבור רשתות אלחוטיות" +#define D_SCAN_DONE "סריקה הושלמה" +#define D_NO_NETWORKS_FOUND "לא נמצאו רשתות אלחוטיות" +#define D_REFRESH_TO_SCAN_AGAIN "רענן כדי לסרוק שוב" +#define D_DUPLICATE_ACCESSPOINT "נקודות גישה משוכפלות" +#define D_SKIPPING_LOW_QUALITY "מדלג עקב איכות רשת נמוכה" +#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 פרמטרים" +#define D_CLIENT "לקוח" +#define D_FULL_TOPIC "זיהוי מלא" + +#define D_LOGGING_PARAMETERS "פרמטרי לוגים" +#define D_SERIAL_LOG_LEVEL "רמת לוג עבור סריאל" +#define D_WEB_LOG_LEVEL "רמת לוג עבור אתר" +#define D_SYS_LOG_LEVEL "Syslog רמת לוג עבור שרת" +#define D_MORE_DEBUG "מיפוי נוסף" +#define D_SYSLOG_HOST "Syslog מארח" +#define D_SYSLOG_PORT "Syslog פורט" +#define D_TELEMETRY_PERIOD "Telemetry period" + +#define D_OTHER_PARAMETERS "פרמטרים שונים" +#define D_WEB_ADMIN_PASSWORD "סיסמת מנהל - אתר" +#define D_MQTT_ENABLE "MQTT אפשר" +#define D_FRIENDLY_NAME "שם ידידותי" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "התקן בודד" +#define D_MULTI_DEVICE "התקנים" + +#define D_SAVE_CONFIGURATION "שמירת הגדרות" +#define D_CONFIGURATION_SAVED "הגדרות נשמרו" +#define D_CONFIGURATION_RESET "איפוס הגדרות" + +#define D_PROGRAM_VERSION "גירסת תוכנה" +#define D_BUILD_DATE_AND_TIME "Build Date & Time" +#define D_CORE_AND_SDK_VERSION "Core/SDK Version" +#define D_FLASH_WRITE_COUNT "מונה צריבות" +#define D_MAC_ADDRESS "MAC כתובת" +#define D_MQTT_HOST "MQTT מארח" +#define D_MQTT_PORT "MQTT פורט" +#define D_MQTT_CLIENT "MQTT לקוח" +#define D_MQTT_USER "MQTT שם משתמש" +#define D_MQTT_TOPIC "MQTT נושא" +#define D_MQTT_GROUP_TOPIC "MQTT נושא קבוצת" +#define D_MQTT_FULL_TOPIC "MQTT נושא מלא" +#define D_MDNS_DISCOVERY "mDNS זיהוי" +#define D_MDNS_ADVERTISE "mDNS פרסום" +#define D_ESP_CHIP_ID "ESP מס' רכיב" +#define D_FLASH_CHIP_ID "מס' רכיב פלאש" +#define D_FLASH_CHIP_SIZE "גודל זיכרון פלאש" +#define D_FREE_PROGRAM_SPACE "מקום פנוי - תוכנה" + +#define D_UPGRADE_BY_WEBSERVER "שדרוג קושחה" +#define D_OTA_URL "OTA כתובת" +#define D_START_UPGRADE "התחל בשדרוג" +#define D_UPGRADE_BY_FILE_UPLOAD "שדרוג דרך קובץ נכשל" +#define D_UPLOAD_STARTED "העלאה מתחילה" +#define D_UPGRADE_STARTED "שדרוג מתחיל" +#define D_UPLOAD_DONE "העלאה הסתיימה" +#define D_UPLOAD_ERR_1 "לא נבחר קובץ" +#define D_UPLOAD_ERR_2 "אין מספיק מקום" +#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" +#define D_UPLOAD_ERR_4 "גודל קובץ השדרוג גדול מנפח האחסון של הפלאש" +#define D_UPLOAD_ERR_5 "מאגר העלאה לא תקין" +#define D_UPLOAD_ERR_6 "העלאה נכשלה. אפשר רישום 3" +#define D_UPLOAD_ERR_7 "ההעלאה בוטלה" +#define D_UPLOAD_ERR_8 "קובץ שגוי" +#define D_UPLOAD_ERR_9 "קובץ גדול מדי" +#define D_UPLOAD_ERR_10 "נכשלה RF הפעלת שבב" +#define D_UPLOAD_ERR_11 "נכשלה RF מחיקת שבב" +#define D_UPLOAD_ERR_12 "נכשלה RF כתיבת שבב" +#define D_UPLOAD_ERR_13 "נכשלה RF קידוד קושחת שבב" +#define D_UPLOAD_ERROR_CODE "שגיאת קוד העלאה" + +#define D_ENTER_COMMAND "הקש פקודה" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" +#define D_NEED_USER_AND_PASSWORD "Need user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verify TLS fingerprint..." +#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to" +#define D_RETRY_IN "Retry in" +#define D_VERIFIED "Verified using Fingerprint" +#define D_INSECURE "Insecure connection due to invalid Fingerprint" +#define D_CONNECT_FAILED_TO "Connect failed to" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast disabled" +#define D_MULTICAST_REJOINED "Multicast (re)joined" +#define D_MULTICAST_JOIN_FAILED "Multicast join failed" +#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo setup" +#define D_RESPONSE_SENT "Response sent" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API not implemented" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" + +// xdrv_07_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/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" +#define D_DOMOTICZ_UPDATE_TIMER "Update timer" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "הגדרות תזמון" +#define D_TIMER_PARAMETERS "פרמטרים עבור תזמון" +#define D_TIMER_ENABLE "אפשר תזמון" +#define D_TIMER_ARM "חמש" +#define D_TIMER_TIME "זמן" +#define D_TIMER_DAYS "ימים" +#define D_TIMER_REPEAT "חזרות" +#define D_TIMER_OUTPUT "פלט" +#define D_TIMER_ACTION "פעולה" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configure KNX" +#define D_KNX_PARAMETERS "KNX Parameters" +#define D_KNX_GENERAL_CONFIG "General" +#define D_KNX_PHYSICAL_ADDRESS "Physical Address" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" +#define D_KNX_ENABLE "Enable KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" +#define D_ADD "Add" +#define D_DELETE "Delete" +#define D_REPLY "Reply" +#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" +#define D_LOG_KNX "KNX: " +#define D_RECEIVED_FROM "Received from" +#define D_KNX_COMMAND_WRITE "Write" +#define D_KNX_COMMAND_READ "Read" +#define D_KNX_COMMAND_OTHER "Other" +#define D_SENT_TO "sent to" +#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "צריכה יומית" +#define D_ENERGY_YESTERDAY "צריכה בעבר" +#define D_ENERGY_TOTAL "צריכה כללית" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor busy" +#define D_SENSOR_CRC_ERROR "Sensor CRC error" +#define D_SENSORS_FOUND "Sensors found" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Timeout waiting for" +#define D_START_SIGNAL_LOW "start signal low" +#define D_START_SIGNAL_HIGH "start signal high" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "Checksum failure" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" +#define D_SHT1X_FOUND "SHT1X found" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particals" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// sonoff_template.h +#define D_SENSOR_NONE "None" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "מתג" // Suffix "1" +#define D_SENSOR_BUTTON "לחצן" // Suffix "1" +#define D_SENSOR_RELAY "ממסר" // Suffix "1i" +#define D_SENSOR_LED "לד" // Suffix "1i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "מונה" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM_RX "PZEM Rx" +#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_BACKLIGHT "BkLight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri" +#define D_SENSOR_SR04_ECHO "SR04 Ech" +#define D_SENSOR_SDM120_TX "SDM120 Tx" +#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sectors" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_HERTZ "Hz" + +// Log message prefix +#define D_LOG_APPLICATION "APP: " // Application +#define D_LOG_BRIDGE "BRG: " // Bridge +#define D_LOG_CONFIG "CFG: " // Settings +#define D_LOG_COMMAND "CMD: " // Command +#define D_LOG_DEBUG "DBG: " // Debug +#define D_LOG_DHT "DHT: " // DHT sensor +#define D_LOG_DOMOTICZ "DOM: " // Domoticz +#define D_LOG_DSB "DSB: " // DS18xB20 sensor +#define D_LOG_HTTP "HTP: " // HTTP webserver +#define D_LOG_I2C "I2C: " // I2C +#define D_LOG_IRR "IRR: " // Infra Red Received +#define D_LOG_LOG "LOG: " // Logging +#define D_LOG_MODULE "MOD: " // Module +#define D_LOG_MDNS "DNS: " // mDNS +#define D_LOG_MQTT "MQT: " // MQTT +#define D_LOG_OTHER "OTH: " // Other +#define D_LOG_RESULT "RSL: " // Result +#define D_LOG_RFR "RFR: " // RF Received +#define D_LOG_SERIAL "SER: " // Serial +#define D_LOG_SHT1 "SHT: " // SHT1x sensor +#define D_LOG_UPLOAD "UPL: " // Upload +#define D_LOG_UPNP "UPP: " // UPnP +#define D_LOG_WIFI "WIF: " // Wifi + +#endif // _LANGUAGE_HE_HE_H_ From ee9f609ed3fd5c39f2fc715c0d8d4c042fe68523 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Tue, 2 Oct 2018 19:33:31 +0200 Subject: [PATCH 0228/2222] Update README.md Update README to include link and information about newly proposed MQTT library and the availability of pre-compiled binaries for same. --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 524ad49ab..fae7f5d52 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,16 @@ See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development The development codebase is checked hourly for changes and if new commits have been merged and compile successfuly they will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA too). It is important to note that these are based on the current development codebase and it is not recommended to flash it to devices used in production or which are hard to reach in the event that you need to manually flash the device if OTA failed. The last compiled commit number is also posted on the same page along with the current build status (if a firmware rebuild is in progress). +The current development codebase also stages a new experimental MQTT library that is not enabled by default. This may be enabled by commenting out: + +#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT + +and uncommenting: + +//#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT + +For those interested in pre-compiled binaries based on this proposed MQTT library these may be downloaded from http://thehackbox.org/mqtt/ (This URL is also OTA friendly) but please do not under any circumstances use binaries from this link on devices used for day to day purposes as the testing of this newly proposed library still needs to follow its course of testing and possible debugging - Only use it on devices that you would normally use for testing purposes as to not inconvenience yourself when having to revert back to previous firmware versions by cable upload. + ### Disclaimer :warning: **DANGER OF ELECTROCUTION** :warning: From 93460c6498652cb5563d71d41ad1d5416719a683 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 3 Oct 2018 10:00:46 +0200 Subject: [PATCH 0229/2222] Change MQTT timeout Change MQTT_ARDUINOMQTT command timeout from 1 to 10 seconds --- sonoff/_changelog.ino | 1 + sonoff/sonoff_post.h | 12 +++++------- sonoff/xdrv_01_mqtt.ino | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 217b665ff..c0eea6fde 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.2.1.11 20191002 * Remove support for MQTT Client based on esp-mqtt-arduino by #define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO * Add support for MQTT Client based on lwmqtt to be selected by #define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT + * Change MQTT_ARDUINOMQTT command timeout from 1 to 10 seconds * * 6.2.1.10 20180930 * Add command RGBWWTable to support color calibration (#3933) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 423a75f3c..bc747155e 100755 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -50,11 +50,6 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define MODULE SONOFF_BASIC // [Module] Select default model #endif -#define USE_DHT // Default DHT11 sensor needs no external library -#define USE_ENERGY_SENSOR // Use energy sensors (+14k code) -#define USE_HLW8012 // Use energy sensor for Sonoff Pow and WolfBlitz -#define USE_CSE7766 // Use energy sensor for Sonoff S31 and Pow R2 - /*********************************************************************************************\ * [sonoff-sensors.bin] * Provide an image with useful supported sensors enabled @@ -272,10 +267,13 @@ void KNX_CB_Action(message_t const &msg, void *arg); #endif #ifndef MQTT_MAX_PACKET_SIZE -#define MQTT_MAX_PACKET_SIZE 1000 +#define MQTT_MAX_PACKET_SIZE 1000 // Bytes #endif #ifndef MQTT_KEEPALIVE -#define MQTT_KEEPALIVE 15 +#define MQTT_KEEPALIVE 15 // Seconds +#endif +#ifndef MQTT_TIMEOUT +#define MQTT_TIMEOUT 10000 // milli seconds #endif #ifndef MESSZ diff --git a/sonoff/xdrv_01_mqtt.ino b/sonoff/xdrv_01_mqtt.ino index 42214216a..3a7d16990 100644 --- a/sonoff/xdrv_01_mqtt.ino +++ b/sonoff/xdrv_01_mqtt.ino @@ -500,7 +500,7 @@ void MqttReconnect() #elif (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT) MqttClient.begin(Settings.mqtt_host, Settings.mqtt_port, EspClient); MqttClient.setWill(stopic, mqtt_data, true, 1); - MqttClient.setOptions(MQTT_KEEPALIVE, true, 1000); + MqttClient.setOptions(MQTT_KEEPALIVE, true, MQTT_TIMEOUT); // MqttClient.onMessageAdvanced(MqttMyDataCb); MqttClient.onMessage(MqttMyDataCb); #endif From 1707c73264a1bf40c97abdfa458163bb4ad2fc3a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 3 Oct 2018 13:55:07 +0200 Subject: [PATCH 0230/2222] Update Hebrew language file Add Hebrew language file (#3960) --- platformio.ini | 15 +++++++++++++++ sonoff/_changelog.ino | 3 ++- sonoff/language/en-GB.h | 4 ++-- sonoff/language/he-HE.h | 12 +++++++++++- sonoff/user_config.h | 1 + 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/platformio.ini b/platformio.ini index c01485f5a..5dfd0a442 100644 --- a/platformio.ini +++ b/platformio.ini @@ -25,6 +25,7 @@ env_default = sonoff ;env_default = sonoff-ES ;env_default = sonoff-FR ;env_default = sonoff-GR +;env_default = sonoff-HE ;env_default = sonoff-HU ;env_default = sonoff-IT ;env_default = sonoff-NL @@ -294,6 +295,20 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} +[env:sonoff-HE] +platform = ${common.platform} +framework = ${common.framework} +board = ${common.board} +board_build.flash_mode = ${common.board_build.flash_mode} +board_build.f_cpu = ${common.board_build.f_cpu} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} -DMY_LANGUAGE=he-HE +monitor_speed = ${common.monitor_speed} +upload_port = ${common.upload_port} +upload_resetmethod = ${common.upload_resetmethod} +upload_speed = ${common.upload_speed} +extra_scripts = ${common.extra_scripts} + [env:sonoff-HU] platform = ${common.platform} framework = ${common.framework} diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index c0eea6fde..5fb481c67 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,7 +2,8 @@ * Remove support for MQTT Client based on esp-mqtt-arduino by #define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO * Add support for MQTT Client based on lwmqtt to be selected by #define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT * Change MQTT_ARDUINOMQTT command timeout from 1 to 10 seconds - * + * Add Hebrew language file (#3960) + * * 6.2.1.10 20180930 * Add command RGBWWTable to support color calibration (#3933) * Add support for Michael Haustein ESP Switch diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 21d8edab7..043545d65 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -32,7 +32,7 @@ \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - +// https://www.science.co.il/language/Locale-codes.php #define LANGUAGE_LCID 2057 // HTML (ISO 639-1) Language Code #define D_HTML_LANGUAGE "en" @@ -169,7 +169,7 @@ #define D_UV_INDEX_4 "Danger" #define D_UV_INDEX_5 "BurnL1/2" #define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" +#define D_UV_INDEX_7 "OoR" // Out of Range #define D_UV_LEVEL "UV Level" #define D_UV_POWER "UV Power" #define D_VERSION "Version" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index be6094233..a8afee86a 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -1,7 +1,7 @@ /* he-HE.h - localization for Hebrew - Israel for Sonoff-Tasmota - Copyright (C) 2018 Yuval Mejahez + Copyright (C) 2018 Yuval Mejahez 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 @@ -163,7 +163,15 @@ #define D_USER "משתמש" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV אינדקס" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" // Out of Range #define D_UV_LEVEL "UV רמת" +#define D_UV_POWER "UV Power" #define D_VERSION "גרסה" #define D_VOLTAGE "מתח" #define D_WARMLIGHT "חום" @@ -493,6 +501,7 @@ #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HOUR "Hr" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" @@ -514,6 +523,7 @@ #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" #define D_UNIT_HERTZ "Hz" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 11b8c1d61..161b84fa1 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -196,6 +196,7 @@ //#define MY_LANGUAGE en-GB // English in Great Britain. Enabled by Default //#define MY_LANGUAGE es-AR // Spanish in Argentina //#define MY_LANGUAGE fr-FR // French in France +//#define MY_LANGUAGE he-HE // Hebrew in Israel //#define MY_LANGUAGE hu-HU // Hungarian in Hungary //#define MY_LANGUAGE it-IT // Italian in Italy //#define MY_LANGUAGE nl-NL // Dutch in the Netherlands From cea848dec4489c13376a00d5573c11129e7c3733 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 3 Oct 2018 19:29:46 +0200 Subject: [PATCH 0231/2222] Fix XSS-Vulnerability in configuration page Add HTML entity encoding to the SSID of networks that can be found using the "Scan for wifi networks" function of the configuration page. --- sonoff/xdrv_02_webserver.ino | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index 6a939dc24..86472b27c 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -789,6 +789,17 @@ void HandleWifiConfiguration() HandleWifi(false); } +String htmlEscape(String s) +{ + s.replace("&", "&"); + s.replace("<", "<"); + s.replace(">", ">"); + s.replace("\"", """); + s.replace("'", "'"); + s.replace("/", "/"); + return s; +} + void HandleWifi(boolean scan) { if (HttpUser()) { return; } @@ -854,7 +865,7 @@ void HandleWifi(boolean scan) String item = FPSTR(HTTP_LNK_ITEM); String rssiQ; rssiQ += quality; - item.replace(F("{v}"), WiFi.SSID(indices[i])); + item.replace(F("{v}"), htmlEscape(WiFi.SSID(indices[i]))); item.replace(F("{w}"), String(WiFi.channel(indices[i]))); item.replace(F("{r}"), rssiQ); uint8_t auth = WiFi.encryptionType(indices[i]); From dbb7b279056a876a3a13f4bd8ff792546212aa6e Mon Sep 17 00:00:00 2001 From: Frank Maas Date: Thu, 4 Oct 2018 00:19:32 +0200 Subject: [PATCH 0232/2222] Update _changelog.ino It's not 2019 yet... --- sonoff/_changelog.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 5fb481c67..00c59c3a5 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,4 @@ -/* 6.2.1.11 20191002 +/* 6.2.1.11 20181002 * Remove support for MQTT Client based on esp-mqtt-arduino by #define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO * Add support for MQTT Client based on lwmqtt to be selected by #define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT * Change MQTT_ARDUINOMQTT command timeout from 1 to 10 seconds From 4ebcbf084adb4a3b48a88ee1837d4c0f7ad19640 Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 4 Oct 2018 08:25:32 +0200 Subject: [PATCH 0233/2222] Driver update 1.0.0.4 20181003 added - MP3Reset command in case that the player do rare things and needs a reset, the default volume will be set again too - MP3_CMD_RESET_VALUE for the player reset function - MP3_CMD_DAC command to switch off/on the dac outputs cleaned - some comments and added function text header fixed - missing void's in function calls tested - works with MP3Device 1 = USB STick, or MP3Device 2 = SD-Card - DAC looks working too on a headset. Had no amplifier for test --- sonoff/xdrv_14_mp3.ino | 102 ++++++++++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 27 deletions(-) diff --git a/sonoff/xdrv_14_mp3.ino b/sonoff/xdrv_14_mp3.ino index d799aa1f0..3bbf32bd0 100644 --- a/sonoff/xdrv_14_mp3.ino +++ b/sonoff/xdrv_14_mp3.ino @@ -19,6 +19,16 @@ -------------------------------------------------------------------------------------------- Version yyyymmdd Action Description -------------------------------------------------------------------------------------------- + 1.0.0.4 20181003 added - MP3Reset command in case that the player do rare things + - and needs a reset, the default volume will be set again too + added - MP3_CMD_RESET_VALUE for the player reset function + cleaned - some comments and added function text header + fixed - missing void's in function calls + added - MP3_CMD_DAC command to switch off/on the dac outputs + tested - works with MP3Device 1 = USB STick, or MP3Device 2 = SD-Card + - after power and/or reset the SD-Card(2) is the default device + - DAC looks working too on a headset. Had no amplifier for test + --- 1.0.0.3 20180915 added - select device for SD-Card or USB Stick, default will be SD-Card tested - works by MP3Device 1 = USB STick, or MP3Device 2 = SD-Card - after power and/or reset the SD-Card(2) is the default device @@ -61,13 +71,20 @@ TasmotaSerial *MP3Player; +/*********************************************************************************************\ + * constants +\*********************************************************************************************/ + #define D_CMND_MP3 "MP3" const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}"; const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}"; -const char kMP3_Commands[] PROGMEM = "Track|Play|Pause|Stop|Volume|EQ|Device"; +const char kMP3_Commands[] PROGMEM = "Track|Play|Pause|Stop|Volume|EQ|Device|Reset|DAC"; + +/*********************************************************************************************\ + * enumerationsines +\*********************************************************************************************/ -// enumerations enum MP3_Commands { // commands useable in console or rules CMND_MP3_TRACK, // MP3Track 001...255 CMND_MP3_PLAY, // MP3Play, after pause or normal start to play @@ -75,9 +92,17 @@ enum MP3_Commands { // commands useable in conso CMND_MP3_STOP, // MP3Stop, real stop, original version was pause function CMND_MP3_VOLUME, // MP3Volume 0..100 CMND_MP3_EQ, // MP3EQ 0..5 - CMND_MP3_DEVICE }; // sd-card: 02, usb-stick: 01 + CMND_MP3_DEVICE, // sd-card: 02, usb-stick: 01 + CMND_MP3_RESET, // MP3Reset, a fresh and default restart + CMND_MP3_DAC }; // set dac, 1=off, 0=on, DAC is turned on (0) by default -// defines + +/*********************************************************************************************\ + * command defines +\*********************************************************************************************/ + +#define MP3_CMD_RESET_VALUE 0 // mp3 reset command value +// player commands #define MP3_CMD_TRACK 0x03 // specify playback of a track, e.g. MP3Track 003 #define MP3_CMD_PLAY 0x0d // Play, works as a normal play on a real MP3 Player, starts at 001.mp3 file on the selected device #define MP3_CMD_PAUSE 0x0e // Pause, was original designed as stop, see data sheet @@ -85,10 +110,14 @@ enum MP3_Commands { // commands useable in conso #define MP3_CMD_VOLUME 0x06 // specifies the volume and means a console input as 0..100 #define MP3_CMD_EQ 0x07 // specify EQ(0/1/2/3/4/5), 0:Normal, 1:Pop, 2:Rock, 3:Jazz, 4:Classic, 5:Bass #define MP3_CMD_DEVICE 0x09 // specify playback device, USB=1, SD-Card=2, default is 2 also after reset or power down/up +#define MP3_CMD_RESET 0x0C // send a reset command to start fresh +#define MP3_CMD_DAC 0x1A // activate or deactivate the DAC output for an external amplifier, DAC is turned on by default + +/*********************************************************************************************\ + * calculate the checksum + * starts with cmd[1] with a length of 6 bytes +\*********************************************************************************************/ -// calculate the checksum -// starts with cmd[1] with a length of 6 bytes -// uint16_t MP3_Checksum(uint8_t *array) { uint16_t checksum = 0; @@ -96,43 +125,58 @@ uint16_t MP3_Checksum(uint8_t *array) checksum += array[i]; } checksum = checksum^0xffff; - return checksum+1; + return (checksum+1); } -// init player, define serial tx port -// fixed with 9600 baud -// -void MP3PlayerInit() { +/*********************************************************************************************\ + * init player + * define serial tx port fixed with 9600 baud +\*********************************************************************************************/ + +void MP3PlayerInit(void) { MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3_DFR562]); // start serial communication fixed to 9600 baud if (MP3Player->begin(9600)) { MP3Player->flush(); - delay(1000); // set delay - // volume setting - MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); // set volume depending on the entry in the user_config.h + delay(1000); + MP3_CMD(MP3_CMD_RESET, MP3_CMD_RESET_VALUE); // reset the player to defaults + delay(3000); + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); // after reset set volume depending on the entry in the user_config.h } + return; } -// create mp3 command payload and send it via serail interface to the MP3 player -// {start byte, version, length, command, feedback, para MSB, para LSB, chks MSB, chks LSB, end byte}; -// {cmd[0] , cmd[1] , cmd[2], cmd[3] , cmd[4] , cmd[5] , cmd[6] , cmd[7] , cmd[8] , cmd[9] }; -// {0x7e , 0xff , 6 , 0 , 0/1 , 0 , 0 , 0 , 0 , 0xef }; -// +/*********************************************************************************************\ + * create the MP3 commands payload, and send it via serial interface to the MP3 player + * data length is 6 = 6 bytes [FF 06 09 00 00 00] but not counting the start, end, and verification. + * {start byte, version, length, command, feedback, para MSB, para LSB, chks MSB, chks LSB, end byte}; + * {cmd[0] , cmd[1] , cmd[2], cmd[3] , cmd[4] , cmd[5] , cmd[6] , cmd[7] , cmd[8] , cmd[9] }; + * {0x7e , 0xff , 6 , 0 , 0/1 , 0 , 0 , 0 , 0 , 0xef }; +\*********************************************************************************************/ + void MP3_CMD(uint8_t mp3cmd,uint16_t val) { + uint8_t i = 0; uint8_t cmd[10] = {0x7e,0xff,6,0,0,0,0,0,0,0xef}; // fill array cmd[3] = mp3cmd; // mp3 command value - //cmd[4] = ; // feedback, yet not use + cmd[4] = 0; // feedback, 1=yes, 0=no, yet not use cmd[5] = val>>8; // data value, shift 8 byte right cmd[6] = val; // data value low byte - uint16_t chks = MP3_Checksum(&cmd[1]); // see calculate the checksum, line 62..72 + uint16_t chks = MP3_Checksum(&cmd[1]); // see calculate the checksum cmd[7] = chks>>8; // checksum. shift 8 byte right cmd[8] = chks; // checksum low byte MP3Player->write(cmd, sizeof(cmd)); // write mp3 data array to player + delay(1000); + if (mp3cmd == MP3_CMD_RESET) { + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); // after reset set volume depending on the entry in the user_config.h + } + return; } -// check the MP3 commands -// -boolean MP3PlayerCmd() { +/*********************************************************************************************\ + * check the MP3 commands +\*********************************************************************************************/ + +boolean MP3PlayerCmd(void) { char command[CMDSZ]; boolean serviced = true; uint8_t disp_len = strlen(D_CMND_MP3); @@ -145,27 +189,31 @@ boolean MP3PlayerCmd() { case CMND_MP3_VOLUME: case CMND_MP3_EQ: case CMND_MP3_DEVICE: + case CMND_MP3_DAC: // play a track, set volume, select EQ, sepcify file device if (XdrvMailbox.data_len > 0) { if (command_code == CMND_MP3_TRACK) { MP3_CMD(MP3_CMD_TRACK, XdrvMailbox.payload); } if (command_code == CMND_MP3_VOLUME) { MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100); } if (command_code == CMND_MP3_EQ) { MP3_CMD(MP3_CMD_EQ, XdrvMailbox.payload); } if (command_code == CMND_MP3_DEVICE) { MP3_CMD(MP3_CMD_DEVICE, XdrvMailbox.payload); } + if (command_code == CMND_MP3_DAC) { MP3_CMD(MP3_CMD_DAC, XdrvMailbox.payload); } } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); break; case CMND_MP3_PLAY: case CMND_MP3_PAUSE: case CMND_MP3_STOP: + case CMND_MP3_RESET: // play or re-play after pause, pause, stop, if (command_code == CMND_MP3_PLAY) { MP3_CMD(MP3_CMD_PLAY, 0); } if (command_code == CMND_MP3_PAUSE) { MP3_CMD(MP3_CMD_PAUSE, 0); } if (command_code == CMND_MP3_STOP) { MP3_CMD(MP3_CMD_STOP, 0); } + if (command_code == CMND_MP3_RESET) { MP3_CMD(MP3_CMD_RESET, 0); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); break; default: - // else for Unknown command - serviced = false; + // else for Unknown command + serviced = false; break; } } From 52d88439ffe0f4fbc6ccbda235f512cb7045ad62 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 4 Oct 2018 11:01:50 +0200 Subject: [PATCH 0234/2222] Fix Domoticz exception Fix exception when wrong Domoticz JSON message is received (#3963) --- sonoff/_changelog.ino | 3 ++- sonoff/xdrv_07_domoticz.ino | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 00c59c3a5..2af5885db 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,7 +3,8 @@ * Add support for MQTT Client based on lwmqtt to be selected by #define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT * Change MQTT_ARDUINOMQTT command timeout from 1 to 10 seconds * Add Hebrew language file (#3960) - * + * Fix exception when wrong Domoticz JSON message is received (#3963) + * * 6.2.1.10 20180930 * Add command RGBWWTable to support color calibration (#3933) * Add support for Michael Haustein ESP Switch diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index a30f79439..7710cad13 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -150,6 +150,15 @@ void DomoticzMqttSubscribe() "svalue1" : "0", "switchType" : "Dimmer", "unit" : 1 +} + * Fail on this one +{ + "LastUpdate" : "2018-10-02 20:39:45", + "Name" : "Sfeerverlichting", + "Status" : "Off", + "Timers" : "true", + "Type" : "Group", + "idx" : "2" } */ @@ -157,7 +166,7 @@ boolean DomoticzMqttData() { char stemp1[10]; unsigned long idx = 0; - int16_t nvalue; + int16_t nvalue = -1; int16_t found = 0; domoticz_update_flag = 1; @@ -174,7 +183,9 @@ boolean DomoticzMqttData() // return 1; // } idx = domoticz["idx"]; - nvalue = domoticz["nvalue"]; + if (domoticz.containsKey("nvalue")) { + 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); @@ -198,7 +209,11 @@ boolean DomoticzMqttData() found = 1; } else if ((!iscolordimmer && 2 == nvalue) || // gswitch_sSetLevel (iscolordimmer && 15 == nvalue)) { // Color_SetBrightnessLevel - nvalue = domoticz["svalue1"]; + if (domoticz.containsKey("svalue1")) { + nvalue = domoticz["svalue1"]; + } else { + return 1; + } if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) { return 1; } From 4ba10206091f0ec873beceea4f84417bfd19adbc Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Thu, 4 Oct 2018 13:41:15 +0200 Subject: [PATCH 0235/2222] Update de-DE.h --- sonoff/language/de-DE.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 72f63f9c4..f035235c7 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -124,9 +124,9 @@ #define D_PORT "Port" #define D_POWER_FACTOR "Leistungsfaktor" #define D_POWERUSAGE "Leistung" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_POWERUSAGE_ACTIVE "Wirkleistung" +#define D_POWERUSAGE_APPARENT "Scheinleistung" +#define D_POWERUSAGE_REACTIVE "Blindleistung" #define D_PRESSURE "Luftdruck" #define D_PRESSUREATSEALEVEL "Luftdruck auf Meereshöhe" #define D_PROGRAM_FLASH_SIZE "Ges. Flash Speicher" From 4208baddac848a423e35d219e971808b234c11d8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 5 Oct 2018 17:54:12 +0200 Subject: [PATCH 0236/2222] Update language files Update language files --- sonoff/language/bg-BG.h | 4 ++++ sonoff/language/cs-CZ.h | 4 ++++ sonoff/language/de-DE.h | 4 ++++ sonoff/language/el-GR.h | 4 ++++ sonoff/language/en-GB.h | 8 ++++++-- sonoff/language/es-AR.h | 4 ++++ sonoff/language/fr-FR.h | 4 ++++ sonoff/language/he-HE.h | 6 +++++- sonoff/language/hu-HU.h | 4 ++++ sonoff/language/it-IT.h | 4 ++++ sonoff/language/nl-NL.h | 4 ++++ sonoff/language/pl-PL.h | 4 ++++ sonoff/language/pt-BR.h | 4 ++++ sonoff/language/pt-PT.h | 4 ++++ sonoff/language/ru-RU.h | 4 ++++ sonoff/language/tr-TR.h | 4 ++++ sonoff/language/uk-UK.h | 5 ++++- sonoff/language/zh-CN.h | 4 ++++ sonoff/language/zh-TW.h | 6 +++++- 19 files changed, 80 insertions(+), 5 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index d79eb5210..177bc69ab 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV мощност" #define D_VERSION "Версия" #define D_VOLTAGE "Напрежение" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Топла" #define D_WEB_SERVER "Уеб сървър" @@ -496,12 +497,15 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 570cfd4c8..498287457 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Verze" #define D_VOLTAGE "Napětí" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Teplé světlo" #define D_WEB_SERVER "Web Server" @@ -496,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" @@ -503,6 +506,7 @@ #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "hod" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index f035235c7..dec1e4723 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Intensität" #define D_VERSION "Version" #define D_VOLTAGE "Spannung" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "warm" #define D_WEB_SERVER "Web-Server" @@ -496,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" @@ -503,6 +506,7 @@ #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 23b5a2705..e0a1cca7a 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Έκδοση" #define D_VOLTAGE "Τάση" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Ζεστό" #define D_WEB_SERVER "Web διακομιστής" @@ -496,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" @@ -503,6 +506,7 @@ #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 043545d65..6478d5bde 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v5.14.0b + * Updated until v6.2.1.11 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Version" #define D_VOLTAGE "Voltage" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Warm" #define D_WEB_SERVER "Web Server" @@ -496,12 +497,16 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" @@ -522,7 +527,6 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_HERTZ "Hz" #define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 713e166ab..843dd3dd8 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Versión" #define D_VOLTAGE "Tensión" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Cálida" #define D_WEB_SERVER "Servidor Web" @@ -496,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" @@ -503,6 +506,7 @@ #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index a7adaea39..6f0c2960a 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -174,6 +174,7 @@ #define D_UV_POWER "Puissance UV" #define D_VERSION "Version" #define D_VOLTAGE "Tension" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Chaud" #define D_WEB_SERVER "Serveur web" @@ -496,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" @@ -503,6 +506,7 @@ #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index a8afee86a..b81cbd355 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "גרסה" #define D_VOLTAGE "מתח" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "חום" #define D_WEB_SERVER "Web שרת" @@ -496,12 +497,16 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" @@ -522,7 +527,6 @@ #define D_UNIT_VOLT "V" #define D_UNIT_WATT "W" #define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_HERTZ "Hz" #define D_UNIT_WATT_METER_QUADRAT "W/m²" // Log message prefix diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index ee6b8a66a..88ddb273a 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Verzió" #define D_VOLTAGE "Feszültség" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Meleg" #define D_WEB_SERVER "Web Szerver" @@ -496,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" @@ -503,6 +506,7 @@ #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "ó" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index b0fe0767a..62deadea5 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Versione" #define D_VOLTAGE "Tensione" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Calda" #define D_WEB_SERVER "Web Server" @@ -496,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" @@ -503,6 +506,7 @@ #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 70e55cb87..921e3b483 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Versie" #define D_VOLTAGE "Spanning" +#define D_WEIGHT "Gewicht" #define D_WARMLIGHT "Warm" #define D_WEB_SERVER "Webserver" @@ -496,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" @@ -503,6 +506,7 @@ #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 40383fb53..85e141c29 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Wersja" #define D_VOLTAGE "Napięcie" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Nagrzanie" #define D_WEB_SERVER "Web Server" @@ -496,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" @@ -503,6 +506,7 @@ #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Godz" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 49affdf2f..96874a2c0 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Versão" #define D_VOLTAGE "Voltagem" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Luz quente" #define D_WEB_SERVER "Servidor WEB" @@ -496,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" @@ -503,6 +506,7 @@ #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "H" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index fd2e98451..51b40d248 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Versão" #define D_VOLTAGE "Voltagem" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Luz Quente" #define D_WEB_SERVER "servidor WEB" @@ -496,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" @@ -503,6 +506,7 @@ #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 9c6266693..1bcf140d6 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Версия" #define D_VOLTAGE "Напряжение" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Тепло" #define D_WEB_SERVER "Web сервер" @@ -496,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "А" @@ -503,6 +506,7 @@ #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Ч" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "кОм" #define D_UNIT_KILOWATTHOUR "кВт" #define D_UNIT_LUX "лк" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 0c411868e..f28764d50 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Versiyon" #define D_VOLTAGE "Voltaj" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Sıcak" #define D_WEB_SERVER "Web Sunucusu" @@ -497,12 +498,15 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 3a9b44afa..f6a2d39c7 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Версія" #define D_VOLTAGE "Напруга" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "Тепло" #define D_WEB_SERVER "Web сервер" @@ -483,7 +484,6 @@ #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1 "SDS0X1" #define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" #define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" #define D_SENSOR_SBR_RX "SerBr Rx" @@ -497,6 +497,8 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "А" @@ -504,6 +506,7 @@ #define D_UNIT_HERTZ "Гц" #define D_UNIT_HOUR "Г" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "кОм" #define D_UNIT_KILOWATTHOUR "кВт" #define D_UNIT_LUX "лк" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 59271d201..763601964 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "版本" #define D_VOLTAGE "电压" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "暖" #define D_WEB_SERVER "Web Server" @@ -496,12 +497,15 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "安" #define D_UNIT_CENTIMETER "厘米" #define D_UNIT_HOUR "时" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "千欧" #define D_UNIT_KILOWATTHOUR "千瓦时" #define D_UNIT_LUX "勒克斯" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 5b275b925..59791b776 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -174,6 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "版本" #define D_VOLTAGE "電壓" +#define D_WEIGHT "Weight" #define D_WARMLIGHT "暖" #define D_WEB_SERVER "Web Server" @@ -496,13 +497,16 @@ #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" // Units #define D_UNIT_AMPERE "安" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" -#define D_UNIT_INCREMENTS "inc" #define D_UNIT_HOUR "時" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOOHM "千歐" #define D_UNIT_KILOWATTHOUR "千瓦時" #define D_UNIT_LUX "勒克斯" From f8b93ad3ea5ff5940b0c1892dccab7f9f65f88f8 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 5 Oct 2018 21:59:39 -0300 Subject: [PATCH 0237/2222] Updated Spanish Translation --- sonoff/language/es-AR.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 843dd3dd8..ddf191b19 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.2.0.1 + * Updated until v6.2.1.11 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -174,7 +174,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Versión" #define D_VOLTAGE "Tensión" -#define D_WEIGHT "Weight" +#define D_WEIGHT "Peso" #define D_WARMLIGHT "Cálida" #define D_WEB_SERVER "Servidor Web" From d3d40a160907443acc76d590fe60efbddcfb1d59 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Oct 2018 16:46:25 +0200 Subject: [PATCH 0238/2222] Update cs-CZ language --- sonoff/language/cs-CZ.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 498287457..9d3cbf160 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -124,9 +124,9 @@ #define D_PORT "Port" #define D_POWER_FACTOR "Účiník" #define D_POWERUSAGE "Příkon" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_POWERUSAGE_ACTIVE "Činný příkon" +#define D_POWERUSAGE_APPARENT "Zdánlivý příkon" +#define D_POWERUSAGE_REACTIVE "Jalový příkon" #define D_PRESSURE "Tlak" #define D_PRESSUREATSEALEVEL "Tlak na hladině moře" #define D_PROGRAM_FLASH_SIZE "Velikost paměti flash" @@ -163,18 +163,18 @@ #define D_USER "Uživatel" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" +#define D_UV_INDEX_1 "Nízký" +#define D_UV_INDEX_2 "Střední" +#define D_UV_INDEX_3 "Vysoký" +#define D_UV_INDEX_4 "Nebezpečný" +#define D_UV_INDEX_5 "Popál1/2" +#define D_UV_INDEX_6 "Popál3" +#define D_UV_INDEX_7 "MimoRozsah" #define D_UV_LEVEL "úroveň UV" #define D_UV_POWER "UV Power" #define D_VERSION "Verze" #define D_VOLTAGE "Napětí" -#define D_WEIGHT "Weight" +#define D_WEIGHT "Hmotnost" #define D_WARMLIGHT "Teplé světlo" #define D_WEB_SERVER "Web Server" @@ -333,10 +333,10 @@ #define D_UPLOAD_ERR_7 "Nahrávání přerušeno" #define D_UPLOAD_ERR_8 "Špatný soubor" #define D_UPLOAD_ERR_9 "Soubor je příliš velký" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERR_10 "Chyba inicializace RF chipu" +#define D_UPLOAD_ERR_11 "Chyba smazání RF chipu" +#define D_UPLOAD_ERR_12 "Chyba při zápisu do RF chipu" +#define D_UPLOAD_ERR_13 "Chyba dekódování RF firmwaru" #define D_UPLOAD_ERROR_CODE "Chyba nahrávání" #define D_ENTER_COMMAND "Vlož příkaz" @@ -505,8 +505,8 @@ #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "hod" -#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From 174f2736dccbd5307c6d33bc46e8d73e24786399 Mon Sep 17 00:00:00 2001 From: synekvl <42292671+synekvl@users.noreply.github.com> Date: Sat, 6 Oct 2018 18:46:29 +0200 Subject: [PATCH 0239/2222] Update cs-CZ.h --- sonoff/language/cs-CZ.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 9d3cbf160..e4fb5c66d 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.1.1c + * Updated until v6.2.1.11 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) From 461fed62909b6da85451c1d49aa6827a80a4479b Mon Sep 17 00:00:00 2001 From: Mike Date: Sat, 6 Oct 2018 20:48:26 +0200 Subject: [PATCH 0240/2222] missing "" around UV Index test in json Fixed the missing "" around the UV Index test in json Old one: "VEML6070":{"UvLevel":6212,"UvIndex":8.32,"UvIndexText":Danger,"UvPower":0.208}} New one: "VEML6070":{"UvLevel":6212,"UvIndex":8.32,"UvIndexText":"Danger","UvPower":0.208}} Now it works. I have no mqtt system running so i did not know that this would happen. Possible i have to build up one system. --- sonoff/xsns_11_veml6070.ino | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index c06175584..68d25234a 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -31,6 +31,9 @@ Version Date Action Description -------------------------------------------------------------------------------------------- + 1.0.0.3 20181006 fixed - missing "" around the UV Index text + - thanks to Lisa she had tested it on here mqtt system. + -- 1.0.0.2 20180928 tests - same as in version 1.0.0.1 cleaned - source code changed - snprintf_P for json and web server output @@ -77,9 +80,9 @@ - show not only the UV Power value in W/m2, possible a @define value to show it as joule value - add a #define to select how many characters are shown benhind the decimal point for the UV Index --- - 1.0.0.0 20180912 started - further development by mike2nl - https://github.com/mike2nl/Sonoff-Tasmota - forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota - base - code base from arendst too + 1.0.0.0 20180912 started - further development by mike2nl - https://github.com/mike2nl/Sonoff-Tasmota + forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota + base - code base from arendst too */ @@ -168,11 +171,11 @@ void Veml6070EverySecond(void) { // all = 10..15[ms] if (11 == (uptime %100)) { - Veml6070ModeCmd(1); // on = 1[ms], wakeup the UV sensor + Veml6070ModeCmd(1); // on = 1[ms], wakeup the UV sensor Veml6070Detect(); // 1[ms], check for sensor and init with IT time Veml6070ModeCmd(0); // off = 5[ms], suspend the UV sensor } else { - Veml6070ModeCmd(1); // 1[ms], wakeup the UV sensor + Veml6070ModeCmd(1); // 1[ms], wakeup the UV sensor uvlevel = Veml6070ReadUv(); // 1..2[ms], get UV raw values uvrisk = Veml6070UvRiskLevel(uvlevel); // 0..1[ms], get UV risk level uvpower = Veml6070UvPower(uvrisk); // 2[ms], get UV power in W/m2 @@ -277,10 +280,10 @@ void Veml6070Show(boolean json) dtostrfd(uvpower, 3, str_uvpower); if (json) { #ifdef USE_VEML6070_SHOW_RAW - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":%s,\"" D_JSON_UV_POWER "\":%s}"), + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), mqtt_data, veml6070_name, str_uvlevel, str_uvrisk, str_uvrisk_text, str_uvpower); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":%s,\"" D_JSON_UV_POWER "\":%s}"), + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), mqtt_data, veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); #endif // USE_VEML6070_SHOW_RAW #ifdef USE_DOMOTICZ From adc3d4ebaa0be33a9184307c5b6c489395eeb94b Mon Sep 17 00:00:00 2001 From: phelagor Date: Sat, 6 Oct 2018 22:05:15 +0200 Subject: [PATCH 0241/2222] Added support for CSL Aplic WDP303075 - Added template for Module. - Added support for HLW8012 (HLW_SEL is different to sonoff POW, needs different level to read voltage) --- sonoff/sonoff_template.h | 19 ++++++++++++++++++- sonoff/xnrg_01_hlw8012.ino | 9 +++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index aad498f3b..f997eb555 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -235,6 +235,7 @@ enum SupportedModules { ESP_SWITCH, OBI, TECKIN, + APLIC_WDP303075, MAXMODULE }; /********************************************************************************************/ @@ -409,7 +410,8 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { AILIGHT, // Light Bulbs PHILIPS, WITTY, // Development Devices - WEMOS + WEMOS, + APLIC_WDP303075 }; // Default module settings @@ -1112,6 +1114,21 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) 0, 0, 0 + }, + { "AplicWDP303075", // Aplic WDP 303075 (ESP8285 - HLW8012 Energy Monitoring) + // https://www.amazon.de/dp/B07CNWVNJ2 + 0, // GPIO00 + 0, // GPIO01 + 0, // GPIO02 + GPIO_KEY1, // GPIO03 Button + GPIO_HLW_CF, // GPIO04 HLW8012 CF (power) + GPIO_HLW_CF1, // GPIO05 HLW8012 CF1 (current/voltage) + 0, 0, 0, 0, 0, 0, // ? + GPIO_HLW_SEL, // GPIO12 HLW8012 CF Sel output (CF) + GPIO_LED1_INV, // GPIO13 LED + GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0= Off, 1 = On ) + 0, // GPIO15 + 0, 0 } }; diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 0bcfa9060..5c63b4826 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -33,6 +33,10 @@ #define HLW_IREF 4545 // 4.545A #define HLW_SEL_VOLTAGE 1 + +// HLW8012 based (APLIC_WDP303075) +#define A_HLW_SEL_VOLTAGE 0 + // HJL-01 based (BlitzWolf, Homecube, Gosund, Teckin) #define HJL_PREF 1362 #define HJL_UREF 822 @@ -182,6 +186,11 @@ void HlwSnsInit() hlw_voltage_ratio = HJL_UREF; hlw_current_ratio = HJL_IREF; hlw_ui_flag = HJL_SEL_VOLTAGE; + } else if (APLIC_WDP303075 == Settings.module){ + hlw_power_ratio = HLW_PREF; + hlw_voltage_ratio = HLW_UREF; + hlw_current_ratio = HLW_IREF; + hlw_ui_flag = A_HLW_SEL_VOLTAGE; } else { hlw_power_ratio = HLW_PREF; hlw_voltage_ratio = HLW_UREF; From 5bbec2617fab2520d9acd547f324d3d8fa7fc66f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 7 Oct 2018 12:37:03 +0200 Subject: [PATCH 0242/2222] 6.2.1.12 - Fixes Shelly1 and CSL 6.2.1.12 20181007 * Fix Shelly1 switchmode 3 and 4 when using pushbutton (#3989) * Add support for CSL Aplic WDP 303075 Power Socket with Energy Monitoring (#3991, #3996) --- sonoff/_changelog.ino | 6 +++- sonoff/sonoff.ino | 8 +++-- sonoff/sonoff_template.h | 61 +++++++++++++++++++------------------- sonoff/sonoff_version.h | 2 +- sonoff/xnrg_01_hlw8012.ino | 46 ++++++++++++++-------------- 5 files changed, 65 insertions(+), 58 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 2af5885db..e04c9c727 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ -/* 6.2.1.11 20181002 +/* 6.2.1.12 20181007 + * Fix Shelly1 switchmode 3 and 4 when using pushbutton (#3989) + * Add support for CSL Aplic WDP 303075 Power Socket with Energy Monitoring (#3991, #3996) + * + * 6.2.1.11 20181002 * Remove support for MQTT Client based on esp-mqtt-arduino by #define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO * Add support for MQTT Client based on lwmqtt to be selected by #define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT * Change MQTT_ARDUINOMQTT command timeout from 1 to 10 seconds diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index b89ffe138..958c7879b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2306,9 +2306,11 @@ void GpioSwitchPinMode(uint8_t index) if (pin[GPIO_SWT1 +index] < 99) { // pinMode(pin[GPIO_SWT1 +index], (16 == pin[GPIO_SWT1 +index]) ? INPUT_PULLDOWN_16 : bitRead(switch_no_pullup, index) ? INPUT : INPUT_PULLUP); - uint8_t no_pullup = 0; - if (bitRead(switch_no_pullup, index)) { - no_pullup = (Settings.switchmode[index] < PUSHBUTTON); + uint8_t no_pullup = bitRead(switch_no_pullup, index); + if (no_pullup) { + if (SHELLY2 == Settings.module) { + no_pullup = (Settings.switchmode[index] < PUSHBUTTON); + } } pinMode(pin[GPIO_SWT1 +index], (16 == pin[GPIO_SWT1 +index]) ? INPUT_PULLDOWN_16 : (no_pullup) ? INPUT : INPUT_PULLUP); } diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index f997eb555..ca352149d 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -135,9 +135,11 @@ enum ProgramSelectablePins { GPIO_SPI_MISO, // SPI MISO library fixed pin GPIO12 GPIO_SPI_MOSI, // SPI MOSI library fixed pin GPIO13 GPIO_SPI_CLK, // SPI Clk library fixed pin GPIO14 - GPIO_HLW_SEL, // HLW8012 Sel output (Sonoff Pow) - GPIO_HLW_CF1, // HLW8012 CF1 voltage / current (Sonoff Pow) - GPIO_HLW_CF, // HLW8012 CF power (Sonoff Pow) + GPIO_NRG_SEL, // HLW8012/HLJ-01 Sel output (1 = Voltage) + GPIO_NRG_SEL_INV, // HLW8012/HLJ-01 Sel output (0 = Voltage) + GPIO_NRG_CF1, // HLW8012/HLJ-01 CF1 voltage / current + GPIO_HLW_CF, // HLW8012 CF power + GPIO_HJL_CF, // HJL-01/BL0937 CF power GPIO_ADC0, // ADC GPIO_DI, // my92x1 PWM input GPIO_DCKI, // my92x1 CLK input @@ -396,6 +398,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { SHELLY2, BLITZWOLF_BWSHP2, // Socket Relay Devices with Energy Monitoring TECKIN, + APLIC_WDP303075, NEO_COOLCAM, // Socket Relay Devices OBI, ESP_SWITCH, // Switch Devices @@ -410,8 +413,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { AILIGHT, // Light Bulbs PHILIPS, WITTY, // Development Devices - WEMOS, - APLIC_WDP303075 + WEMOS }; // Default module settings @@ -492,10 +494,10 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "Sonoff Pow", // Sonoff Pow (ESP8266 - HLW8012) GPIO_KEY1, // GPIO00 Button 0, 0, 0, 0, - GPIO_HLW_SEL, // GPIO05 HLW8012 Sel output + GPIO_NRG_SEL, // GPIO05 HLW8012 Sel output (1 = Voltage) 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - GPIO_HLW_CF1, // GPIO13 HLW8012 CF1 voltage / current + GPIO_NRG_CF1, // GPIO13 HLW8012 CF1 voltage / current GPIO_HLW_CF, // GPIO14 HLW8012 CF power GPIO_LED1, // GPIO15 Blue Led (0 = On, 1 = Off) 0, 0 @@ -729,8 +731,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY1, // GPIO4 Button GPIO_REL1_INV, // GPIO5 Relay (0 = On, 1 = Off) 0, 0, 0, 0, 0, 0, // Flash connection - GPIO_HLW_CF1, // GPIO12 HLW8012 CF1 voltage / current - GPIO_HLW_SEL, // GPIO13 HLW8012 Sel output + GPIO_NRG_CF1, // GPIO12 HLW8012 CF1 voltage / current + GPIO_NRG_SEL, // GPIO13 HLW8012 Sel output (1 = Voltage) GPIO_HLW_CF, // GPIO14 HLW8012 CF power 0, 0, 0 }, @@ -899,10 +901,10 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { // 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 + GPIO_HLW_CF, // GPIO04 HLW8012 CF power + GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 voltage / current 0, 0, 0, 0, 0, 0, // Flash connection - GPIO_HLW_SEL, // GPIO12 HLW8012 SEL + GPIO_NRG_SEL, // GPIO12 HLW8012 SEL (1 = Voltage) GPIO_LED1_INV, // GPIO13 Green Led GPIO_REL1, // GPIO14 Relay 0, 0, 0 @@ -1030,11 +1032,11 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1_INV, // GPIO02 Blue Led (1 = On, 0 = Off) GPIO_USER, // GPIO03 Serial TXD and Optional sensor 0, - GPIO_HLW_CF, // GPIO05 BL0937 or HJL-01 CF power + GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power 0, 0, 0, 0, 0, 0, // Flash connection - GPIO_HLW_SEL, // GPIO12 BL0937 or HJL-01 Sel output + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) GPIO_KEY1, // GPIO13 Button - GPIO_HLW_CF1, // GPIO14 BL0937 or HJL-01 CF1 voltage / current + GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) 0, 0 }, @@ -1107,28 +1109,25 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY1, // GPIO01 Serial TXD and Button 0, GPIO_LED2_INV, // GPIO03 Serial RXD and Red Led (0 = On, 1 = Off) - GPIO_HLW_CF, // GPIO04 BL0937 or HJL-01 CF power - GPIO_HLW_CF1, // GPIO05 BL0937 or HJL-01 CF1 voltage / current + GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage 0, 0, 0, 0, 0, 0, // Flash connection - GPIO_HLW_SEL, // GPIO12 BL0937 or HJL-01 Sel output + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) 0, 0, 0 }, - { "AplicWDP303075", // Aplic WDP 303075 (ESP8285 - HLW8012 Energy Monitoring) + { "AplicWDP303075", // Aplic WDP 303075 (ESP8285 - HLW8012 Energy Monitoring) // https://www.amazon.de/dp/B07CNWVNJ2 - 0, // GPIO00 - 0, // GPIO01 - 0, // GPIO02 - GPIO_KEY1, // GPIO03 Button - GPIO_HLW_CF, // GPIO04 HLW8012 CF (power) - GPIO_HLW_CF1, // GPIO05 HLW8012 CF1 (current/voltage) - 0, 0, 0, 0, 0, 0, // ? - GPIO_HLW_SEL, // GPIO12 HLW8012 CF Sel output (CF) - GPIO_LED1_INV, // GPIO13 LED - GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0= Off, 1 = On ) - 0, // GPIO15 - 0, 0 + 0, 0, 0, + GPIO_KEY1, // GPIO03 Button + GPIO_HLW_CF, // GPIO04 HLW8012 CF power + GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 current / voltage + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage) + GPIO_LED1_INV, // GPIO13 LED (0 = On, 1 = Off) + GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On ) + 0, 0, 0 } }; diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 60a044326..df02100d3 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0602010B +#define VERSION 0x0602010C #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 5c63b4826..0a7a074e7 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -27,26 +27,21 @@ #define XNRG_01 1 -// HLW8012 based (Sonoff Pow, KMC70011, HuaFan) +// Energy model type 0 (GPIO_HLW_CF) - HLW8012 based (Sonoff Pow, KMC70011, HuaFan, AplicWDP303075) #define HLW_PREF 10000 // 1000.0W #define HLW_UREF 2200 // 220.0V #define HLW_IREF 4545 // 4.545A -#define HLW_SEL_VOLTAGE 1 - -// HLW8012 based (APLIC_WDP303075) -#define A_HLW_SEL_VOLTAGE 0 - -// HJL-01 based (BlitzWolf, Homecube, Gosund, Teckin) +// Energy model type 1 (GPIO_HJL_CF) - HJL-01/BL0937 based (BlitzWolf, Homecube, Gosund, Teckin) #define HJL_PREF 1362 #define HJL_UREF 822 #define HJL_IREF 3300 -#define HJL_SEL_VOLTAGE 0 #define HLW_POWER_PROBE_TIME 10 // Number of seconds to probe for power before deciding none used byte hlw_select_ui_flag; byte hlw_ui_flag = 1; +byte hlw_model_type = 0; byte hlw_load_off; byte hlw_cf1_timer; unsigned long hlw_cf_pulse_length; @@ -124,7 +119,7 @@ void HlwEvery200ms() if (hlw_cf1_timer >= 8) { hlw_cf1_timer = 0; hlw_select_ui_flag = (hlw_select_ui_flag) ? 0 : 1; - digitalWrite(pin[GPIO_HLW_SEL], hlw_select_ui_flag); + digitalWrite(pin[GPIO_NRG_SEL], hlw_select_ui_flag); if (hlw_cf1_pulse_counter) { hlw_cf1_pulse_length = hlw_cf1_summed_pulse_length / hlw_cf1_pulse_counter; @@ -181,21 +176,14 @@ void HlwSnsInit() Settings.energy_current_calibration = HLW_IREF_PULSE; } - if ((BLITZWOLF_BWSHP2 == Settings.module) || (TECKIN == Settings.module)) { + if (hlw_model_type) { hlw_power_ratio = HJL_PREF; hlw_voltage_ratio = HJL_UREF; hlw_current_ratio = HJL_IREF; - hlw_ui_flag = HJL_SEL_VOLTAGE; - } else if (APLIC_WDP303075 == Settings.module){ - hlw_power_ratio = HLW_PREF; - hlw_voltage_ratio = HLW_UREF; - hlw_current_ratio = HLW_IREF; - hlw_ui_flag = A_HLW_SEL_VOLTAGE; } else { hlw_power_ratio = HLW_PREF; hlw_voltage_ratio = HLW_UREF; hlw_current_ratio = HLW_IREF; - hlw_ui_flag = HLW_SEL_VOLTAGE; } hlw_cf_pulse_length = 0; @@ -212,10 +200,10 @@ void HlwSnsInit() hlw_select_ui_flag = 0; // Voltage; - pinMode(pin[GPIO_HLW_SEL], OUTPUT); - digitalWrite(pin[GPIO_HLW_SEL], hlw_select_ui_flag); - pinMode(pin[GPIO_HLW_CF1], INPUT_PULLUP); - attachInterrupt(pin[GPIO_HLW_CF1], HlwCf1Interrupt, FALLING); + pinMode(pin[GPIO_NRG_SEL], OUTPUT); + digitalWrite(pin[GPIO_NRG_SEL], hlw_select_ui_flag); + pinMode(pin[GPIO_NRG_CF1], INPUT_PULLUP); + attachInterrupt(pin[GPIO_NRG_CF1], HlwCf1Interrupt, FALLING); pinMode(pin[GPIO_HLW_CF], INPUT_PULLUP); attachInterrupt(pin[GPIO_HLW_CF], HlwCfInterrupt, FALLING); @@ -225,7 +213,21 @@ void HlwSnsInit() void HlwDrvInit() { if (!energy_flg) { - if ((pin[GPIO_HLW_SEL] < 99) && (pin[GPIO_HLW_CF1] < 99) && (pin[GPIO_HLW_CF] < 99)) { // Sonoff Pow or any HLW8012 based device + hlw_model_type = 0; + if (pin[GPIO_HJL_CF] < 99) { + pin[GPIO_HLW_CF] = pin[GPIO_HJL_CF]; + pin[GPIO_HJL_CF] = 99; + hlw_model_type = 1; + } + + hlw_ui_flag = 1; + if (pin[GPIO_NRG_SEL_INV] < 99) { + pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV]; + pin[GPIO_NRG_SEL_INV] = 99; + hlw_ui_flag = 0; + } + + if ((pin[GPIO_NRG_SEL] < 99) && (pin[GPIO_NRG_CF1] < 99) && (pin[GPIO_HLW_CF] < 99)) { // HLW8012 or HJL-01 based device energy_flg = XNRG_01; } } From dfce7a280acf4371f6627404e0adbf57f991ec62 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sun, 7 Oct 2018 14:24:52 -0300 Subject: [PATCH 0243/2222] Add PWM Freq Limits Config at Compile time PWM_MAX and PWM_MIN are added with explanation comments in order to let a user, who wants to use a Servo, to config these values. Not added at runtime in order to avoid issues with dimmers. --- sonoff/sonoff.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index f891e387a..9a84fabd6 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -80,6 +80,10 @@ typedef unsigned long power_t; // Power (Relay) type //#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 PWM_MAX 4000 // [PWM_MAX] Maximum frequency - Default: 4000 +#define PWM_MIN 100 // [PWM_MIN] Minimum frequency - Default: 100 + // For Dimmers use double of your mains AC frequecy (100 for 50Hz and 120 for 60Hz) + // For Controlling Servos use 50 and also set PWM_FREQ as 50 (DO NOT USE THESE VALUES FOR DIMMERS) #define DEFAULT_POWER_DELTA 80 // Power change percentage #define MAX_POWER_HOLD 10 // Time in SECONDS to allow max agreed power From efb328de099e6e486494b4f49efbd26dd22f4529 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sun, 7 Oct 2018 14:27:09 -0300 Subject: [PATCH 0244/2222] Add PWM Freq Limits Config at Compile time --- sonoff/sonoff.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 958c7879b..89badfbe1 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -914,7 +914,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } else if (CMND_PWMFREQUENCY == command_code) { - if ((1 == payload) || ((payload >= 100) && (payload <= 4000))) { + if ((1 == payload) || ((payload >= PWM_MIN) && (payload <= PWM_MAX))) { Settings.pwm_frequency = (1 == payload) ? PWM_FREQ : payload; analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) } From 30154e23352faddbffbf8b9a75212970895cce8b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 8 Oct 2018 10:30:24 +0200 Subject: [PATCH 0245/2222] 6.2.1.13 Change to ArduinoMqtt 6.2.1.13 20181008 * Change default Mqtt client library from PubSubClient to non-blocking ArduinoMqtt by Joel Gaehwiler --- sonoff/_changelog.ino | 5 ++++- sonoff/sonoff.h | 5 +++-- sonoff/sonoff_version.h | 2 +- sonoff/user_config.h | 4 ++-- sonoff/xdrv_01_mqtt.ino | 23 +++++++++++++---------- 5 files changed, 23 insertions(+), 16 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e04c9c727..2f3a38392 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.2.1.12 20181007 +/* 6.2.1.13 20181008 + * Change default Mqtt client library from PubSubClient to non-blocking ArduinoMqtt by Joel Gaehwiler + * + * 6.2.1.12 20181007 * Fix Shelly1 switchmode 3 and 4 when using pushbutton (#3989) * Add support for CSL Aplic WDP 303075 Power Socket with Energy Monitoring (#3991, #3996) * diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 9a84fabd6..2e16b59b0 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -144,8 +144,9 @@ typedef unsigned long power_t; // Power (Relay) type #define NEO_GRBW 6 // Neopixel GRBW leds #define MQTT_PUBSUBCLIENT 1 // Mqtt PubSubClient library -#define MQTT_TASMOTAMQTT 2 // Mqtt TasmotaMqtt library based on esp-mqtt-arduino -#define MQTT_ARDUINOMQTT 3 // Mqtt arduino-mqtt library by Joel Gaehwiler (https://github.com/256dpi/arduino-mqtt) +#define MQTT_TASMOTAMQTT 2 // Mqtt TasmotaMqtt library based on esp-mqtt-arduino - soon obsolete +#define MQTT_ESPMQTTARDUINO 3 // Mqtt esp-mqtt-arduino library by Ingo Randolf - obsolete +#define MQTT_ARDUINOMQTT 4 // Mqtt arduino-mqtt library by Joel Gaehwiler (https://github.com/256dpi/arduino-mqtt) // Sunrise and Sunset DawnType #define DAWN_NORMAL -0.8333 diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index df02100d3..eba7ddc21 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0602010C +#define VERSION 0x0602010D #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 161b84fa1..0ed7eba35 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -220,11 +220,11 @@ * Select ONE of possible MQTT library types below \*-------------------------------------------------------------------------------------------*/ // Default MQTT driver for both non-TLS and TLS connections. Blocks network if MQTT server is unavailable. -#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library +//#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library // Alternative MQTT driver does not block network when MQTT server is unavailable. No TLS support //#define MQTT_LIBRARY_TYPE MQTT_TASMOTAMQTT // Use TasmotaMqtt library (+4k4 (core 2.3.0), +14k4 (core 2.4.2 lwip2) code, +4k mem) - non-TLS only // Alternative MQTT driver does not block network when MQTT server is unavailable. TLS should work but needs to be tested. -//#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem) +#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem) // -- MQTT ---------------------------------------- #define MQTT_TELE_RETAIN 0 // Tele messages may send retain flag (0 = off, 1 = on) diff --git a/sonoff/xdrv_01_mqtt.ino b/sonoff/xdrv_01_mqtt.ino index 3a7d16990..3cb76e86d 100644 --- a/sonoff/xdrv_01_mqtt.ino +++ b/sonoff/xdrv_01_mqtt.ino @@ -27,23 +27,26 @@ // Alternative MQTT driver does not block network when MQTT server is unavailable. TLS should work but needs to be tested. //#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem) -#ifdef USE_MQTT_TLS +#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) // Obsolete as of v6.2.1.11 +#undef MQTT_LIBRARY_TYPE +#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT +#endif /* -#ifdef MQTT_LIBRARY_TYPE -#undef MQTT_LIBRARY_TYPE -#endif -#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library as it only supports TLS -*/ #if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) #undef MQTT_LIBRARY_TYPE -#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library as it only supports TLS +#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Obsolete in near future +#endif +*/ + +#ifdef USE_MQTT_TLS + +#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) +#undef MQTT_LIBRARY_TYPE #endif -#else - #ifndef MQTT_LIBRARY_TYPE -#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library as default +#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library as it only supports TLS #endif #endif From 641005ebbc6dbece43a87a75d04b2597cdc466c8 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 8 Oct 2018 12:01:38 +0200 Subject: [PATCH 0246/2222] Remove note on new MQTT build --- README.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/README.md b/README.md index fae7f5d52..524ad49ab 100644 --- a/README.md +++ b/README.md @@ -21,16 +21,6 @@ See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development The development codebase is checked hourly for changes and if new commits have been merged and compile successfuly they will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA too). It is important to note that these are based on the current development codebase and it is not recommended to flash it to devices used in production or which are hard to reach in the event that you need to manually flash the device if OTA failed. The last compiled commit number is also posted on the same page along with the current build status (if a firmware rebuild is in progress). -The current development codebase also stages a new experimental MQTT library that is not enabled by default. This may be enabled by commenting out: - -#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT - -and uncommenting: - -//#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT - -For those interested in pre-compiled binaries based on this proposed MQTT library these may be downloaded from http://thehackbox.org/mqtt/ (This URL is also OTA friendly) but please do not under any circumstances use binaries from this link on devices used for day to day purposes as the testing of this newly proposed library still needs to follow its course of testing and possible debugging - Only use it on devices that you would normally use for testing purposes as to not inconvenience yourself when having to revert back to previous firmware versions by cable upload. - ### Disclaimer :warning: **DANGER OF ELECTROCUTION** :warning: From ba16e00e3645e4ca7d35addbd721e7df13fe606e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 8 Oct 2018 14:39:36 +0200 Subject: [PATCH 0247/2222] Add command WebRefresh Add command WebRefresh 1000..10000 to control web page refresh in milliseconds. Default is 2345 --- sonoff/_changelog.ino | 1 + sonoff/i18n.h | 4 ++++ sonoff/settings.h | 17 +++++++---------- sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 10 ++++++++-- sonoff/xdrv_02_webserver.ino | 16 ++++++++++++---- 6 files changed, 33 insertions(+), 17 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 2f3a38392..b2210c830 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.2.1.13 20181008 * Change default Mqtt client library from PubSubClient to non-blocking ArduinoMqtt by Joel Gaehwiler + * Add command WebRefresh 1000..10000 to control web page refresh in milliseconds. Default is 2345 * * 6.2.1.12 20181007 * Fix Shelly1 switchmode 3 and 4 when using pushbutton (#3989) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index bc161c078..ab1f0a1d2 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -46,6 +46,7 @@ #define D_JSON_COMMAND "Command" #define D_JSON_CONNECT_FAILED "Connect failed" #define D_JSON_COREVERSION "Core" +#define D_JSON_COUNT "Count" #define D_JSON_COUNTER "Counter" #define D_JSON_CURRENT "Current" // As in Voltage and Current #define D_JSON_DATA "Data" @@ -137,6 +138,7 @@ #define D_JSON_VCC "Vcc" #define D_JSON_VERSION "Version" #define D_JSON_VOLTAGE "Voltage" +#define D_JSON_WEIGHT "Weight" #define D_JSON_WIFI "Wifi" #define D_JSON_WRONG "Wrong" #define D_JSON_WRONG_PARAMETERS "Wrong parameters" @@ -187,6 +189,7 @@ #define D_CMND_FREQUENCY_RESOLUTION "FreqRes" #define D_CMND_CURRENT_RESOLUTION "AmpRes" #define D_CMND_ENERGY_RESOLUTION "EnergyRes" +#define D_CMND_WEIGHT_RESOLUTION "WeightRes" #define D_CMND_MODULE "Module" #define D_CMND_MODULES "Modules" #define D_CMND_GPIO "GPIO" @@ -277,6 +280,7 @@ #define D_JSON_WITH_IP_ADDRESS "with IP address" #define D_CMND_WEBPASSWORD "WebPassword" #define D_CMND_WEBLOG "WebLog" +#define D_CMND_WEBREFRESH "WebRefresh" #define D_CMND_WEBSEND "WebSend" #define D_CMND_EMULATION "Emulation" diff --git a/sonoff/settings.h b/sonoff/settings.h index 978b72b24..26f4f2865 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -110,8 +110,7 @@ typedef union { uint32_t spare06 : 1; uint32_t spare07 : 1; uint32_t spare08 : 1; - uint32_t spare09 : 1; - uint32_t spare10 : 1; + uint32_t weight_resolution : 2; uint32_t frequency_resolution : 2; uint32_t axis_resolution : 2; uint32_t current_resolution : 2; @@ -321,20 +320,18 @@ struct SYSCFG { byte free_717[1]; // 717 uint16_t mcp230xx_int_timer; // 718 - uint8_t rgbwwTable[5]; // 71A - byte free_71F[169]; // 71F + byte free_71F[157]; // 71F + uint16_t weight_item; // 7BC Weight of one item in gram * 10 + uint16_t weight_max; // 7BE Total max weight in kilogram + unsigned long weight_reference; // 7C0 Reference weight in gram + unsigned long weight_calibration; // 7C4 unsigned long energy_frequency_calibration; // 7C8 - - byte free_7CC[2]; // 7CC - + uint16_t web_refresh; // 7CC char mems[MAX_RULE_MEMS][10]; // 7CE - // 800 Full - no more free locations - char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b - // E00 - FFF free locations } Settings; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 2e16b59b0..5d41aa18d 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -145,7 +145,7 @@ typedef unsigned long power_t; // Power (Relay) type #define MQTT_PUBSUBCLIENT 1 // Mqtt PubSubClient library #define MQTT_TASMOTAMQTT 2 // Mqtt TasmotaMqtt library based on esp-mqtt-arduino - soon obsolete -#define MQTT_ESPMQTTARDUINO 3 // Mqtt esp-mqtt-arduino library by Ingo Randolf - obsolete +#define MQTT_ESPMQTTARDUINO 3 // Mqtt esp-mqtt-arduino library by Ingo Randolf - obsolete but define is present for debugging purposes #define MQTT_ARDUINOMQTT 4 // Mqtt arduino-mqtt library by Joel Gaehwiler (https://github.com/256dpi/arduino-mqtt) // Sunrise and Sunset DawnType diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 89badfbe1..23ee2a27d 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -77,7 +77,7 @@ enum TasmotaCommands { CMND_BACKLOG, CMND_DELAY, CMND_POWER, CMND_FANSPEED, CMND_STATUS, CMND_STATE, CMND_POWERONSTATE, CMND_PULSETIME, CMND_BLINKTIME, CMND_BLINKCOUNT, CMND_SENSOR, CMND_SAVEDATA, CMND_SETOPTION, CMND_TEMPERATURE_RESOLUTION, CMND_HUMIDITY_RESOLUTION, - CMND_PRESSURE_RESOLUTION, CMND_POWER_RESOLUTION, CMND_VOLTAGE_RESOLUTION, CMND_FREQUENCY_RESOLUTION, CMND_CURRENT_RESOLUTION, CMND_ENERGY_RESOLUTION, + CMND_PRESSURE_RESOLUTION, CMND_POWER_RESOLUTION, CMND_VOLTAGE_RESOLUTION, CMND_FREQUENCY_RESOLUTION, CMND_CURRENT_RESOLUTION, CMND_ENERGY_RESOLUTION, CMND_WEIGHT_RESOLUTION, CMND_MODULE, CMND_MODULES, CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE, CMND_COUNTERDEBOUNCE, CMND_BUTTONDEBOUNCE, CMND_SWITCHDEBOUNCE, 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, @@ -87,7 +87,7 @@ enum TasmotaCommands { const char kTasmotaCommands[] PROGMEM = D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_FANSPEED "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|" D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SENSOR "|" 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_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" + D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_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_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" 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 "|" @@ -821,6 +821,12 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.energy_resolution); } + else if (CMND_WEIGHT_RESOLUTION == command_code) { + if ((payload >= 0) && (payload <= 3)) { + Settings.flag2.weight_resolution = payload; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.weight_resolution); + } else if (CMND_MODULE == command_code) { if ((payload > 0) && (payload <= MAXMODULE)) { payload--; diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index 86472b27c..099411eba 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -25,6 +25,8 @@ * Based on source by AlexT (https://github.com/tzapu) \*********************************************************************************************/ +#define HTTP_REFRESH_TIME 2345 // milliseconds + #ifdef USE_RF_FLASH uint8_t *efm8bb1_update = NULL; #endif // USE_RF_FLASH @@ -72,7 +74,7 @@ const char HTTP_HEAD[] PROGMEM = "};" "x.open('GET','ay'+a,true);" "x.send();" - "lt=setTimeout(la,2345);" + "lt=setTimeout(la,{a});" // Settings.web_refresh "}" "function lb(p){" "la('?d='+p);" @@ -147,7 +149,7 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "x.open('GET','ax?c2='+id+o,true);" "x.send();" "}" - "lt=setTimeout(l,2345);" + "lt=setTimeout(l,{a});" "return false;" "}" ""; @@ -367,6 +369,7 @@ void ExecuteWebCommand(char* svalue, int source) void StartWebserver(int type, IPAddress ipweb) { + if (!Settings.web_refresh) { Settings.web_refresh = HTTP_REFRESH_TIME; } if (!webserver_state) { if (!WebServer) { WebServer = new ESP8266WebServer((HTTP_MANAGER==type) ? 80 : WEB_PORT); @@ -497,6 +500,7 @@ void ShowPage(String &page, bool auth) return WebServer->requestAuthentication(); } + page.replace(F("{a}"), String(Settings.web_refresh)); page.replace(F("{ha"), my_module.name); page.replace(F("{h}"), Settings.friendlyname[0]); if (HTTP_MANAGER == webserver_state) { @@ -1994,8 +1998,8 @@ int WebSend(char *buffer) /*********************************************************************************************/ -enum WebCommands { CMND_WEBSERVER, CMND_WEBPASSWORD, CMND_WEBLOG, CMND_WEBSEND, CMND_EMULATION }; -const char kWebCommands[] PROGMEM = D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBSEND "|" D_CMND_EMULATION ; +enum WebCommands { CMND_WEBSERVER, CMND_WEBPASSWORD, CMND_WEBLOG, CMND_WEBREFRESH, CMND_WEBSEND, CMND_EMULATION }; +const char kWebCommands[] PROGMEM = D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_EMULATION ; const char kWebSendStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND ; bool WebCommand() @@ -2028,6 +2032,10 @@ bool WebCommand() if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { Settings.weblog_level = XdrvMailbox.payload; } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.weblog_level); } + else if (CMND_WEBREFRESH == command_code) { + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload <= 10000)) { Settings.web_refresh = XdrvMailbox.payload; } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.web_refresh); + } else if (CMND_WEBSEND == command_code) { if (XdrvMailbox.data_len > 0) { uint8_t result = WebSend(XdrvMailbox.data); From 3bc3e7e3323b30eeb6bfe46a2cd666e7cbf11d28 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 8 Oct 2018 17:25:42 -0300 Subject: [PATCH 0248/2222] Add comment for sleep command (datasheet) --- sonoff/support.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index d2b38bb09..d5cf005ba 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1298,13 +1298,13 @@ void WiFiSetSleepMode() * See https://github.com/arendst/Sonoff-Tasmota/issues/2559 */ -//#ifdef ARDUINO_ESP8266_RELEASE_2_4_1 +// Sleep explanation: https://github.com/esp8266/Arduino/blob/3f0c601cfe81439ce17e9bd5d28994a7ed144482/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp#L255 #if defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) #else // Enabled in 2.3.0, 2.4.0 and stage if (sleep) { WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times } else { - WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Diable sleep (Esp8288/Arduino core and sdk default) + WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default) } #endif } From 077b8a79e15be9446c3a7f796e895a87628de0cc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 10 Oct 2018 16:40:54 +0200 Subject: [PATCH 0249/2222] 6.2.1.14 Webserver rewrite 6.2.1.14 20181010 * Rewrite Webserver page handler for easier extension (thx to Adrian Scillato) --- sonoff/_changelog.ino | 5 +- sonoff/i18n.h | 1 - sonoff/sonoff.h | 2 +- sonoff/sonoff_version.h | 2 +- ...02_webserver.ino => xdrv_01_webserver.ino} | 466 ++++++++---------- sonoff/{xdrv_01_mqtt.ino => xdrv_02_mqtt.ino} | 103 +++- sonoff/xdrv_07_domoticz.ino | 49 +- sonoff/xdrv_09_timers.ino | 33 +- sonoff/xdrv_11_knx.ino | 18 +- sonoff/xplg_wemohue.ino | 14 + 10 files changed, 389 insertions(+), 304 deletions(-) rename sonoff/{xdrv_02_webserver.ino => xdrv_01_webserver.ino} (84%) rename sonoff/{xdrv_01_mqtt.ino => xdrv_02_mqtt.ino} (86%) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b2210c830..def41834a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.2.1.13 20181008 +/* 6.2.1.14 20181010 + * Rewrite Webserver page handler for easier extension (thx to Adrian Scillato) + * + * 6.2.1.13 20181008 * Change default Mqtt client library from PubSubClient to non-blocking ArduinoMqtt by Joel Gaehwiler * Add command WebRefresh 1000..10000 to control web page refresh in milliseconds. Default is 2345 * diff --git a/sonoff/i18n.h b/sonoff/i18n.h index ab1f0a1d2..62226f91f 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -539,7 +539,6 @@ const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION; const char S_CONFIGURE_MODULE[] PROGMEM = D_CONFIGURE_MODULE; const char S_CONFIGURE_WIFI[] PROGMEM = D_CONFIGURE_WIFI; const char S_NO_NETWORKS_FOUND[] PROGMEM = D_NO_NETWORKS_FOUND; -const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT; const char S_CONFIGURE_LOGGING[] PROGMEM = D_CONFIGURE_LOGGING; const char S_CONFIGURE_OTHER[] PROGMEM = D_CONFIGURE_OTHER; const char S_SAVE_CONFIGURATION[] PROGMEM = D_SAVE_CONFIGURATION; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 5d41aa18d..5bc744157 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -214,7 +214,7 @@ enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MA enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, - FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM}; + FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_HANDLER}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index eba7ddc21..080c76fa4 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0602010D +#define VERSION 0x0602010E #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_01_webserver.ino similarity index 84% rename from sonoff/xdrv_02_webserver.ino rename to sonoff/xdrv_01_webserver.ino index 099411eba..50345145f 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1,5 +1,5 @@ /* - xdrv_02_webserver.ino - webserver for Sonoff-Tasmota + xdrv_01_webserver.ino - webserver for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -193,25 +193,9 @@ const char HTTP_BTN_MENU1[] PROGMEM = const char HTTP_BTN_RSTRT[] PROGMEM = "
"; const char HTTP_BTN_MENU_MODULE[] PROGMEM = - "
"; -#if defined(USE_TIMERS) && defined(USE_TIMERS_WEB) -const char HTTP_BTN_MENU_TIMER[] PROGMEM = - "
"; -#endif // USE_TIMERS and USE_TIMERS_WEB -const char HTTP_BTN_MENU_WIFI[] PROGMEM = - "
"; -const char HTTP_BTN_MENU_MQTT[] PROGMEM = - "
" -#ifdef USE_DOMOTICZ - "
" -#endif // USE_DOMOTICZ - ""; + "
" + "
"; const char HTTP_BTN_MENU4[] PROGMEM = -#ifdef USE_KNX -#ifdef USE_KNX_WEB_MENU - "
" -#endif // USE_KNX_WEB_MENU -#endif // USE_KNX "
" "
" "
" @@ -229,34 +213,21 @@ const char HTTP_FORM_LOGIN[] PROGMEM = const char HTTP_BTN_CONF[] PROGMEM = "

"; const char HTTP_FORM_MODULE[] PROGMEM = - "
 " D_MODULE_PARAMETERS " 
" - "" + "
 " D_MODULE_PARAMETERS " " "
" D_MODULE_TYPE " ({mt)

"; const char HTTP_LNK_ITEM[] PROGMEM = "
{v} ({w}) {i} {r}%
"; const char HTTP_LNK_SCAN[] PROGMEM = - "
"; + "
"; const char HTTP_FORM_WIFI[] PROGMEM = - "
 " D_WIFI_PARAMETERS " " - "" + "
 " D_WIFI_PARAMETERS " " "
" D_AP1_SSID " (" STA_SSID1 ")

" "
" D_AP1_PASSWORD "

" "
" D_AP2_SSID " (" STA_SSID2 ")

" "
" D_AP2_PASSWORD "

" "
" D_HOSTNAME " (" WIFI_HOSTNAME ")

"; -const char HTTP_FORM_MQTT[] PROGMEM = - "
 " D_MQTT_PARAMETERS " " - "" - "
" D_HOST " (" MQTT_HOST ")

" - "
" D_PORT " (" STR(MQTT_PORT) ")

" - "
" D_CLIENT " ({m0)

" - "
" D_USER " (" MQTT_USER ")

" - "
" D_PASSWORD "

" - "
" D_TOPIC " = %topic% (" MQTT_TOPIC ")

" - "
" D_FULL_TOPIC " (" MQTT_FULLTOPIC ")

"; const char HTTP_FORM_LOG1[] PROGMEM = - "
 " D_LOGGING_PARAMETERS " " - ""; + "
 " D_LOGGING_PARAMETERS " "; const char HTTP_FORM_LOG2[] PROGMEM = "
{b0 ({b1)

" "
" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

"; const char HTTP_FORM_OTHER[] PROGMEM = - "
 " D_OTHER_PARAMETERS " " - "" + "
 " D_OTHER_PARAMETERS " " +// "" "
" D_WEB_ADMIN_PASSWORD "

" "
" D_MQTT_ENABLE "
"; const char HTTP_FORM_OTHER2[] PROGMEM = @@ -283,7 +254,7 @@ const char HTTP_FORM_OTHER3b[] PROGMEM = "
{3{4"; // Different id only used for labels #endif // USE_EMULATION const char HTTP_FORM_END[] PROGMEM = - "
"; + "
"; const char HTTP_FORM_RST[] PROGMEM = "
" "
 " D_RESTORE_CONFIGURATION " "; @@ -383,46 +354,23 @@ void StartWebserver(int type, IPAddress ipweb) WebServer->on("/ay", HandleAjaxStatusRefresh); WebServer->on("/cm", HandleHttpCommand); WebServer->on("/rb", HandleRestart); +// WebServer->on("/fwlink", HandleRoot); // Microsoft captive portal. Maybe not needed. Might be handled by notFound handler. + WebServer->onNotFound(HandleNotFound); #ifndef BE_MINIMAL WebServer->on("/cn", HandleConfiguration); WebServer->on("/md", HandleModuleConfiguration); -#if defined(USE_TIMERS) && defined(USE_TIMERS_WEB) - WebServer->on("/tm", HandleTimerConfiguration); -#endif // USE_TIMERS and USE_TIMERS_WEB - WebServer->on("/w1", HandleWifiConfigurationWithScan); - WebServer->on("/w0", HandleWifiConfiguration); - if (Settings.flag.mqtt_enabled) { - WebServer->on("/mq", HandleMqttConfiguration); -#ifdef USE_DOMOTICZ - WebServer->on("/dm", HandleDomoticzConfiguration); -#endif // USE_DOMOTICZ - } -#ifdef USE_KNX -#ifdef USE_KNX_WEB_MENU - WebServer->on("/kn", HandleKNXConfiguration); -#endif // USE_KNX_WEB_MENU -#endif // USE_KNX + WebServer->on("/wi", HandleWifiConfiguration); WebServer->on("/lg", HandleLoggingConfiguration); WebServer->on("/co", HandleOtherConfiguration); WebServer->on("/dl", HandleBackupConfiguration); - WebServer->on("/sv", HandleSaveSettings); WebServer->on("/rs", HandleRestoreConfiguration); WebServer->on("/rt", HandleResetConfiguration); WebServer->on("/in", HandleInformation); #ifdef USE_EMULATION - if (EMUL_WEMO == Settings.flag2.emulation) { - WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); - WebServer->on("/eventservice.xml", HandleUpnpService); - WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); - WebServer->on("/setup.xml", HandleUpnpSetupWemo); - } - if (EMUL_HUE == Settings.flag2.emulation) { - WebServer->on("/description.xml", HandleUpnpSetupHue); - } + HueWemoAddHandlers(); #endif // USE_EMULATION + XdrvCall(FUNC_WEB_ADD_HANDLER); #endif // Not BE_MINIMAL - WebServer->on("/fwlink", HandleRoot); // Microsoft captive portal. Maybe not needed. Might be handled by notFound handler. - WebServer->onNotFound(HandleNotFound); } reset_web_log_flag = 0; WebServer->begin(); // Web server start @@ -697,7 +645,30 @@ boolean HttpUser() return status; } +/*-------------------------------------------------------------------------------------------*/ + #ifndef BE_MINIMAL + +void WaitForRestart(String result) +{ + String page = FPSTR(HTTP_HEAD); + page.replace(F("{v}"), FPSTR(S_SAVE_CONFIGURATION)); + page += FPSTR(HTTP_HEAD_STYLE); + page += F("
" D_CONFIGURATION_SAVED "
"); + page += result; + page += F("
"); + page += FPSTR(HTTP_MSG_RSTRT); + if (HTTP_MANAGER == webserver_state) { + webserver_state = HTTP_ADMIN; + } else { + page += FPSTR(HTTP_BTN_MAIN); + } + ShowPage(page); + + ShowWebSource(SRC_WEBGUI); + restart_flag = 2; +} + void HandleConfiguration() { if (HttpUser()) { return; } @@ -708,29 +679,34 @@ void HandleConfiguration() page.replace(F("{v}"), FPSTR(S_CONFIGURATION)); page += FPSTR(HTTP_HEAD_STYLE); page += FPSTR(HTTP_BTN_MENU_MODULE); -#if defined(USE_TIMERS) && defined(USE_TIMERS_WEB) -#ifdef USE_RULES - page += FPSTR(HTTP_BTN_MENU_TIMER); -#else - if (devices_present) { page += FPSTR(HTTP_BTN_MENU_TIMER); } -#endif // USE_RULES -#endif // USE_TIMERS and USE_TIMERS_WEB - page += FPSTR(HTTP_BTN_MENU_WIFI); - if (Settings.flag.mqtt_enabled) { page += FPSTR(HTTP_BTN_MENU_MQTT); } + + mqtt_data[0] = '\0'; + XdrvCall(FUNC_WEB_ADD_BUTTON); + page += String(mqtt_data); + page += FPSTR(HTTP_BTN_MENU4); page += FPSTR(HTTP_BTN_MAIN); ShowPage(page); } +/*-------------------------------------------------------------------------------------------*/ + void HandleModuleConfiguration() { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } - char stemp[20]; - uint8_t midx; AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); + if (WebServer->hasArg("save")) { + ModuleSaveSettings(); + WaitForRestart(""); + return; + } + + char stemp[20]; + uint8_t midx; + String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE)); page += FPSTR(HTTP_SCRIPT_MODULE1); @@ -783,15 +759,36 @@ void HandleModuleConfiguration() ShowPage(page); } -void HandleWifiConfigurationWithScan() +void ModuleSaveSettings() { - HandleWifi(true); + char tmp[100]; + char stemp[TOPSZ]; + + WebGetArg("g99", tmp, sizeof(tmp)); + byte new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); + Settings.last_module = Settings.module; + Settings.module = new_module; + mytmplt cmodule; + memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); + String gpios = ""; + for (byte i = 0; i < MAX_GPIO_PIN; i++) { + if (Settings.last_module != new_module) { + Settings.my_gp.io[i] = 0; + } else { + if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { + snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), i); + WebGetArg(stemp, tmp, sizeof(tmp)); + Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); + gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); + } + } + } + snprintf_P(stemp, sizeof(stemp), kModules[Settings.module].name); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), stemp, gpios.c_str()); + AddLog(LOG_LEVEL_INFO); } -void HandleWifiConfiguration() -{ - HandleWifi(false); -} +/*-------------------------------------------------------------------------------------------*/ String htmlEscape(String s) { @@ -804,18 +801,25 @@ String htmlEscape(String s) return s; } -void HandleWifi(boolean scan) +void HandleWifiConfiguration() { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); + if (WebServer->hasArg("save")) { + WifiSaveSettings(); + String result = F("
" D_TRYING_TO_CONNECT "
"); + WaitForRestart(result); + return; + } + String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_CONFIGURE_WIFI)); page += FPSTR(HTTP_HEAD_STYLE); - if (scan) { + if (WebServer->hasArg("scan")) { #ifdef USE_EMULATION UdpDisconnect(); #endif // USE_EMULATION @@ -901,39 +905,46 @@ void HandleWifi(boolean scan) ShowPage(page, !(HTTP_MANAGER == webserver_state)); } -void HandleMqttConfiguration() +void WifiSaveSettings() { - if (HttpUser()) { return; } - if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT); + char tmp[100]; - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_MQTT)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_MQTT); - char str[sizeof(Settings.mqtt_client)]; - page.replace(F("{m0"), Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client))); - page.replace(F("{m1"), Settings.mqtt_host); - page.replace(F("{m2"), String(Settings.mqtt_port)); - page.replace(F("{m3"), Settings.mqtt_client); - page.replace(F("{m4"), (Settings.mqtt_user[0] == '\0')?"0":Settings.mqtt_user); - page.replace(F("{m5"), (Settings.mqtt_pwd[0] == '\0')?"0":Settings.mqtt_pwd); - page.replace(F("{m6"), Settings.mqtt_topic); - page.replace(F("{m7"), Settings.mqtt_fulltopic); - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WebGetArg("h", tmp, sizeof(tmp)); + strlcpy(Settings.hostname, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp, sizeof(Settings.hostname)); + if (strstr(Settings.hostname,"%")) { + strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); + } + WebGetArg("s1", tmp, sizeof(tmp)); + strlcpy(Settings.sta_ssid[0], (!strlen(tmp)) ? STA_SSID1 : tmp, sizeof(Settings.sta_ssid[0])); + WebGetArg("s2", tmp, sizeof(tmp)); + strlcpy(Settings.sta_ssid[1], (!strlen(tmp)) ? STA_SSID2 : tmp, sizeof(Settings.sta_ssid[1])); + WebGetArg("p1", tmp, sizeof(tmp)); + strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); + WebGetArg("p2", tmp, sizeof(tmp)); + strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s"), + Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1]); + AddLog(LOG_LEVEL_INFO); } +/*-------------------------------------------------------------------------------------------*/ + void HandleLoggingConfiguration() { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_LOGGING); + if (WebServer->hasArg("save")) { + LoggingSaveSettings(); + HandleConfiguration(); + return; + } + String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_CONFIGURE_LOGGING)); page += FPSTR(HTTP_HEAD_STYLE); + page += FPSTR(HTTP_FORM_LOG1); for (byte idx = 0; idx < 3; idx++) { page += FPSTR(HTTP_FORM_LOG2); @@ -973,11 +984,46 @@ void HandleLoggingConfiguration() ShowPage(page); } +void LoggingSaveSettings() +{ + char tmp[100]; + + WebGetArg("ls", tmp, sizeof(tmp)); + Settings.seriallog_level = (!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp); + WebGetArg("lw", tmp, sizeof(tmp)); + Settings.weblog_level = (!strlen(tmp)) ? WEB_LOG_LEVEL : atoi(tmp); + WebGetArg("ll", tmp, sizeof(tmp)); + Settings.syslog_level = (!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp); + syslog_level = Settings.syslog_level; + syslog_timer = 0; + WebGetArg("lh", tmp, sizeof(tmp)); + strlcpy(Settings.syslog_host, (!strlen(tmp)) ? SYS_LOG_HOST : tmp, sizeof(Settings.syslog_host)); + WebGetArg("lp", tmp, sizeof(tmp)); + Settings.syslog_port = (!strlen(tmp)) ? SYS_LOG_PORT : atoi(tmp); + WebGetArg("lt", tmp, sizeof(tmp)); + Settings.tele_period = (!strlen(tmp)) ? TELE_PERIOD : atoi(tmp); + if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) { + Settings.tele_period = 10; // Do not allow periods < 10 seconds + } + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_LOG D_CMND_SERIALLOG " %d, " D_CMND_WEBLOG " %d, " D_CMND_SYSLOG " %d, " D_CMND_LOGHOST " %s, " D_CMND_LOGPORT " %d, " D_CMND_TELEPERIOD " %d"), + Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); + AddLog(LOG_LEVEL_INFO); +} + +/*-------------------------------------------------------------------------------------------*/ + void HandleOtherConfiguration() { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_OTHER); + + if (WebServer->hasArg("save")) { + OtherSaveSettings(); + WaitForRestart(""); + return; + } + char stemp[40]; String page = FPSTR(HTTP_HEAD); @@ -1011,6 +1057,32 @@ void HandleOtherConfiguration() ShowPage(page); } +void OtherSaveSettings() +{ + char tmp[100]; + char stemp[TOPSZ]; + char stemp2[TOPSZ]; + + WebGetArg("p1", tmp, sizeof(tmp)); + strlcpy(Settings.web_password, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.web_password : tmp, sizeof(Settings.web_password)); + Settings.flag.mqtt_enabled = WebServer->hasArg("b1"); +#ifdef USE_EMULATION + WebGetArg("b2", tmp, sizeof(tmp)); + Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); +#endif // USE_EMULATION + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); + for (byte i = 0; i < MAX_FRIENDLYNAMES; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("a%d"), i +1); + WebGetArg(stemp, tmp, sizeof(tmp)); + snprintf_P(stemp2, sizeof(stemp2), PSTR(FRIENDLY_NAME"%d"), i +1); + strlcpy(Settings.friendlyname[i], (!strlen(tmp)) ? (i) ? stemp2 : FRIENDLY_NAME : tmp, sizeof(Settings.friendlyname[i])); + snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", Settings.friendlyname[i]); + } + AddLog(LOG_LEVEL_INFO); +} + +/*-------------------------------------------------------------------------------------------*/ + void HandleBackupConfiguration() { if (HttpUser()) { return; } @@ -1053,171 +1125,7 @@ void HandleBackupConfiguration() Settings.cfg_crc = cfg_crc; // Restore crc in case savedata = 0 to make sure settings will be noted as changed } -void HandleSaveSettings() -{ - if (HttpUser()) { return; } - if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } - - char stemp[TOPSZ]; - char stemp2[TOPSZ]; - String result = ""; - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_SAVE_CONFIGURATION); - - char tmp[100]; - WebGetArg("w", tmp, sizeof(tmp)); // Returns "5,1" where 5 is config type and 1 is restart flag - char *p = tmp; - uint8_t what = strtol(p, &p, 10); - p++; // Skip comma - uint8_t restart = strtol(p, &p, 10); - switch (what) { - case 1: - WebGetArg("h", tmp, sizeof(tmp)); - strlcpy(Settings.hostname, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp, sizeof(Settings.hostname)); - if (strstr(Settings.hostname,"%")) { - strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); - } - WebGetArg("s1", tmp, sizeof(tmp)); - strlcpy(Settings.sta_ssid[0], (!strlen(tmp)) ? STA_SSID1 : tmp, sizeof(Settings.sta_ssid[0])); - WebGetArg("s2", tmp, sizeof(tmp)); - strlcpy(Settings.sta_ssid[1], (!strlen(tmp)) ? STA_SSID2 : tmp, sizeof(Settings.sta_ssid[1])); -// WebGetArg("s1", tmp, sizeof(tmp)); -// strlcpy(Settings.sta_ssid[0], (!strlen(tmp)) ? "" : tmp, sizeof(Settings.sta_ssid[0])); -// WebGetArg("s2", tmp, sizeof(tmp)); -// strlcpy(Settings.sta_ssid[1], (!strlen(tmp)) ? "" : tmp, sizeof(Settings.sta_ssid[1])); - WebGetArg("p1", tmp, sizeof(tmp)); - strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); - WebGetArg("p2", tmp, sizeof(tmp)); - strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s"), - Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1]); - AddLog(LOG_LEVEL_INFO); - result += F("
" D_TRYING_TO_CONNECT "
"); - break; - case 2: - WebGetArg("mt", tmp, sizeof(tmp)); - strlcpy(stemp, (!strlen(tmp)) ? MQTT_TOPIC : tmp, sizeof(stemp)); - MakeValidMqtt(0, stemp); - WebGetArg("mf", tmp, sizeof(tmp)); - strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); - MakeValidMqtt(1,stemp2); - if ((strcmp(stemp, Settings.mqtt_topic)) || (strcmp(stemp2, Settings.mqtt_fulltopic))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : ""); - MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic - } - strlcpy(Settings.mqtt_topic, stemp, sizeof(Settings.mqtt_topic)); - strlcpy(Settings.mqtt_fulltopic, stemp2, sizeof(Settings.mqtt_fulltopic)); - WebGetArg("mh", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_host, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_host)); - WebGetArg("ml", tmp, sizeof(tmp)); - Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); - WebGetArg("mc", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_client, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp, sizeof(Settings.mqtt_client)); - WebGetArg("mu", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user)); - WebGetArg("mp", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? MQTT_PASS : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_pwd)); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_MQTTPASSWORD " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), - Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_pwd, Settings.mqtt_topic, Settings.mqtt_fulltopic); - AddLog(LOG_LEVEL_INFO); - break; - case 3: - WebGetArg("ls", tmp, sizeof(tmp)); - Settings.seriallog_level = (!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp); - WebGetArg("lw", tmp, sizeof(tmp)); - Settings.weblog_level = (!strlen(tmp)) ? WEB_LOG_LEVEL : atoi(tmp); - WebGetArg("ll", tmp, sizeof(tmp)); - Settings.syslog_level = (!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp); - syslog_level = Settings.syslog_level; - syslog_timer = 0; - WebGetArg("lh", tmp, sizeof(tmp)); - strlcpy(Settings.syslog_host, (!strlen(tmp)) ? SYS_LOG_HOST : tmp, sizeof(Settings.syslog_host)); - WebGetArg("lp", tmp, sizeof(tmp)); - Settings.syslog_port = (!strlen(tmp)) ? SYS_LOG_PORT : atoi(tmp); - WebGetArg("lt", tmp, sizeof(tmp)); - Settings.tele_period = (!strlen(tmp)) ? TELE_PERIOD : atoi(tmp); - if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) { - Settings.tele_period = 10; // Do not allow periods < 10 seconds - } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_LOG D_CMND_SERIALLOG " %d, " D_CMND_WEBLOG " %d, " D_CMND_SYSLOG " %d, " D_CMND_LOGHOST " %s, " D_CMND_LOGPORT " %d, " D_CMND_TELEPERIOD " %d"), - Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); - AddLog(LOG_LEVEL_INFO); - break; -#if defined(USE_TIMERS) && defined(USE_TIMERS_WEB) - case 7: - TimerSaveSettings(); - break; -#endif // USE_TIMERS and USE_TIMERS_WEB -#ifdef USE_DOMOTICZ - case 4: - DomoticzSaveSettings(); - break; -#endif // USE_DOMOTICZ - case 5: - WebGetArg("p1", tmp, sizeof(tmp)); - strlcpy(Settings.web_password, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.web_password : tmp, sizeof(Settings.web_password)); - Settings.flag.mqtt_enabled = WebServer->hasArg("b1"); -#ifdef USE_EMULATION - WebGetArg("b2", tmp, sizeof(tmp)); - Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); -#endif // USE_EMULATION - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); - for (byte i = 0; i < MAX_FRIENDLYNAMES; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("a%d"), i +1); - WebGetArg(stemp, tmp, sizeof(tmp)); - snprintf_P(stemp2, sizeof(stemp2), PSTR(FRIENDLY_NAME"%d"), i +1); - strlcpy(Settings.friendlyname[i], (!strlen(tmp)) ? (i) ? stemp2 : FRIENDLY_NAME : tmp, sizeof(Settings.friendlyname[i])); - snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", Settings.friendlyname[i]); - } - AddLog(LOG_LEVEL_INFO); - break; - case 6: - WebGetArg("g99", tmp, sizeof(tmp)); - byte new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); - Settings.last_module = Settings.module; - Settings.module = new_module; - mytmplt cmodule; - memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); - String gpios = ""; - for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (Settings.last_module != new_module) { - Settings.my_gp.io[i] = 0; - } else { - if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { - snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), i); - WebGetArg(stemp, tmp, sizeof(tmp)); - Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); - } - } - } - snprintf_P(stemp, sizeof(stemp), kModules[Settings.module].name); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), stemp, gpios.c_str()); - AddLog(LOG_LEVEL_INFO); - break; - } - - if (restart) { - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_SAVE_CONFIGURATION)); - page += FPSTR(HTTP_HEAD_STYLE); - page += F("
" D_CONFIGURATION_SAVED "
"); - page += result; - page += F("
"); - page += FPSTR(HTTP_MSG_RSTRT); - if (HTTP_MANAGER == webserver_state) { - webserver_state = HTTP_ADMIN; - } else { - page += FPSTR(HTTP_BTN_MAIN); - } - ShowPage(page); - - ShowWebSource(SRC_WEBGUI); - restart_flag = 2; - } else { - HandleConfiguration(); - } -} +/*-------------------------------------------------------------------------------------------*/ void HandleResetConfiguration() { @@ -1259,6 +1167,8 @@ void HandleRestoreConfiguration() upload_file_type = UPL_SETTINGS; } +/*-------------------------------------------------------------------------------------------*/ + void HandleInformation() { if (HttpUser()) { return; } @@ -1376,6 +1286,8 @@ void HandleInformation() } #endif // Not BE_MINIMAL +/*-------------------------------------------------------------------------------------------*/ + void HandleUpgradeFirmware() { if (HttpUser()) { return; } @@ -1669,6 +1581,8 @@ void HandleUploadLoop() delay(0); } +/*-------------------------------------------------------------------------------------------*/ + void HandlePreflightRequest() { WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); @@ -1677,6 +1591,8 @@ void HandlePreflightRequest() WebServer->send(200, FPSTR(HDR_CTYPE_HTML), ""); } +/*-------------------------------------------------------------------------------------------*/ + void HandleHttpCommand() { if (HttpUser()) { return; } @@ -1735,6 +1651,8 @@ void HandleHttpCommand() WebServer->send(200, FPSTR(HDR_CTYPE_JSON), message); } +/*-------------------------------------------------------------------------------------------*/ + void HandleConsole() { if (HttpUser()) { return; } @@ -1808,6 +1726,8 @@ void HandleAjaxConsoleRefresh() WebServer->send(200, FPSTR(HDR_CTYPE_XML), message); } +/*-------------------------------------------------------------------------------------------*/ + void HandleRestart() { if (HttpUser()) { return; } @@ -2061,9 +1981,9 @@ bool WebCommand() * Interface \*********************************************************************************************/ -#define XDRV_02 +#define XDRV_01 -boolean Xdrv02(byte function) +boolean Xdrv01(byte function) { boolean result = false; diff --git a/sonoff/xdrv_01_mqtt.ino b/sonoff/xdrv_02_mqtt.ino similarity index 86% rename from sonoff/xdrv_01_mqtt.ino rename to sonoff/xdrv_02_mqtt.ino index 3cb76e86d..1cd6d9aff 100644 --- a/sonoff/xdrv_01_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -1,5 +1,5 @@ /* - xdrv_01_mqtt.ino - mqtt support for Sonoff-Tasmota + xdrv_02_mqtt.ino - mqtt support for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -782,18 +782,115 @@ bool MqttCommand() return serviced; } +/*********************************************************************************************\ + * Presentation +\*********************************************************************************************/ + +#ifdef USE_WEBSERVER + +#define WEB_HANDLE_MQTT "mq" + +const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT; + +const char HTTP_BTN_MENU_MQTT[] PROGMEM = + "
"; + +const char HTTP_FORM_MQTT[] PROGMEM = + "
 " D_MQTT_PARAMETERS " 
" + "
" D_HOST " (" MQTT_HOST ")

" + "
" D_PORT " (" STR(MQTT_PORT) ")

" + "
" D_CLIENT " ({m0)

" + "
" D_USER " (" MQTT_USER ")

" + "
" D_PASSWORD "

" + "
" D_TOPIC " = %topic% (" MQTT_TOPIC ")

" + "
" D_FULL_TOPIC " (" MQTT_FULLTOPIC ")

"; + +void HandleMqttConfiguration() +{ + if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT); + + if (WebServer->hasArg("save")) { + MqttSaveSettings(); + WaitForRestart(""); + return; + } + + String page = FPSTR(HTTP_HEAD); + page.replace(F("{v}"), FPSTR(S_CONFIGURE_MQTT)); + page += FPSTR(HTTP_HEAD_STYLE); + + page += FPSTR(HTTP_FORM_MQTT); + char str[sizeof(Settings.mqtt_client)]; + page.replace(F("{m0"), Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client))); + page.replace(F("{m1"), Settings.mqtt_host); + page.replace(F("{m2"), String(Settings.mqtt_port)); + page.replace(F("{m3"), Settings.mqtt_client); + page.replace(F("{m4"), (Settings.mqtt_user[0] == '\0')?"0":Settings.mqtt_user); + page.replace(F("{m5"), (Settings.mqtt_pwd[0] == '\0')?"0":Settings.mqtt_pwd); + page.replace(F("{m6"), Settings.mqtt_topic); + page.replace(F("{m7"), Settings.mqtt_fulltopic); + + page += FPSTR(HTTP_FORM_END); + page += FPSTR(HTTP_BTN_CONF); + ShowPage(page); +} + +void MqttSaveSettings() +{ + char tmp[100]; + char stemp[TOPSZ]; + char stemp2[TOPSZ]; + + WebGetArg("mt", tmp, sizeof(tmp)); + strlcpy(stemp, (!strlen(tmp)) ? MQTT_TOPIC : tmp, sizeof(stemp)); + MakeValidMqtt(0, stemp); + WebGetArg("mf", tmp, sizeof(tmp)); + strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); + MakeValidMqtt(1,stemp2); + if ((strcmp(stemp, Settings.mqtt_topic)) || (strcmp(stemp2, Settings.mqtt_fulltopic))) { + snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic + } + strlcpy(Settings.mqtt_topic, stemp, sizeof(Settings.mqtt_topic)); + strlcpy(Settings.mqtt_fulltopic, stemp2, sizeof(Settings.mqtt_fulltopic)); + WebGetArg("mh", tmp, sizeof(tmp)); + strlcpy(Settings.mqtt_host, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_host)); + WebGetArg("ml", tmp, sizeof(tmp)); + Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); + WebGetArg("mc", tmp, sizeof(tmp)); + strlcpy(Settings.mqtt_client, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp, sizeof(Settings.mqtt_client)); + WebGetArg("mu", tmp, sizeof(tmp)); + strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user)); + WebGetArg("mp", tmp, sizeof(tmp)); + strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? MQTT_PASS : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_pwd)); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_MQTTPASSWORD " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), + Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_pwd, Settings.mqtt_topic, Settings.mqtt_fulltopic); + AddLog(LOG_LEVEL_INFO); +} +#endif // USE_WEBSERVER + /*********************************************************************************************\ * Interface \*********************************************************************************************/ -#define XDRV_01 +#define XDRV_02 -boolean Xdrv01(byte function) +boolean Xdrv02(byte function) { boolean result = false; if (Settings.flag.mqtt_enabled) { switch (function) { +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + strncat_P(mqtt_data, HTTP_BTN_MENU_MQTT, sizeof(mqtt_data)); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); + break; +#endif // USE_WEBSERVER case FUNC_LOOP: MqttLoop(); break; diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 7710cad13..d40bae88f 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -19,22 +19,6 @@ #ifdef USE_DOMOTICZ -#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_SENSOR[] PROGMEM = - ""; -const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM = - ""; -#endif // USE_WEBSERVER - const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\",\"Battery\":%d,\"RSSI\":%d}"; enum DomoticzCommands { CMND_IDX, CMND_KEYIDX, CMND_SWITCHIDX, CMND_SENSORIDX, CMND_UPDATETIMER }; @@ -386,14 +370,39 @@ void DomoticzSensorPowerEnergy(int power, char *energy) \*********************************************************************************************/ #ifdef USE_WEBSERVER + +#define WEB_HANDLE_DOMOTICZ "dm" + const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ; +const char HTTP_BTN_MENU_DOMOTICZ[] PROGMEM = + "
"; + +const char HTTP_FORM_DOMOTICZ[] PROGMEM = + "
 " D_DOMOTICZ_PARAMETERS " 
" + "
" D_DOMOTICZ_IDX " {1
" D_DOMOTICZ_KEY_IDX " {1
" D_DOMOTICZ_SWITCH_IDX " {1
" D_DOMOTICZ_SENSOR_IDX " {1 {2
" D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ")
"; +const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM = + "" + ""; + const char HTTP_FORM_DOMOTICZ_SWITCH[] PROGMEM = + ""; +const char HTTP_FORM_DOMOTICZ_SENSOR[] PROGMEM = + ""; +const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM = + ""; + void HandleDomoticzConfiguration() { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_DOMOTICZ); + if (WebServer->hasArg("save")) { + DomoticzSaveSettings(); + WaitForRestart(""); + return; + } + char stemp[32]; String page = FPSTR(HTTP_HEAD); @@ -474,6 +483,14 @@ boolean Xdrv07(byte function) if (Settings.flag.mqtt_enabled) { switch (function) { +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + strncat_P(mqtt_data, HTTP_BTN_MENU_DOMOTICZ, sizeof(mqtt_data)); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration); + break; +#endif // USE_WEBSERVER case FUNC_COMMAND: result = DomoticzCommand(); break; diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 124b41534..338a8ddc0 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -510,6 +510,14 @@ boolean TimerCommand() #ifdef USE_WEBSERVER #ifdef USE_TIMERS_WEB + +#define WEB_HANDLE_TIMER "tm" + +const char S_CONFIGURE_TIMER[] PROGMEM = D_CONFIGURE_TIMER; + +const char HTTP_BTN_MENU_TIMER[] PROGMEM = + "
"; + const char HTTP_TIMER_SCRIPT[] PROGMEM = "var pt=[],ct=99;" "function qs(s){" // Alias to save code space @@ -639,8 +647,7 @@ const char HTTP_TIMER_STYLE[] PROGMEM = #endif ""; const char HTTP_FORM_TIMER[] PROGMEM = - "
 " D_TIMER_PARAMETERS " 
" - "" + "
 " D_TIMER_PARAMETERS " " "
" D_TIMER_ENABLE "


" "requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TIMER); + if (WebServer->hasArg("save")) { + TimerSaveSettings(); + HandleConfiguration(); + return; + } + String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_CONFIGURE_TIMER)); page += FPSTR(HTTP_TIMER_SCRIPT); @@ -743,6 +754,20 @@ boolean Xdrv09(byte function) case FUNC_PRE_INIT: TimerSetRandomWindows(); break; +#ifdef USE_WEBSERVER +#ifdef USE_TIMERS_WEB + case FUNC_WEB_ADD_BUTTON: +#ifdef USE_RULES + strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data)); +#else + if (devices_present) { strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data)); } +#endif // USE_RULES + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_TIMER, HandleTimerConfiguration); + break; +#endif // USE_TIMERS_WEB +#endif // USE_WEBSERVER case FUNC_EVERY_SECOND: TimerEverySecond(); break; diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 88260b23c..6132133ae 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -749,6 +749,9 @@ void KnxSensor(byte sensor_type, float value) #ifdef USE_KNX_WEB_MENU const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX; +const char HTTP_BTN_MENU_KNX[] PROGMEM = + "
"; + const char HTTP_FORM_KNX[] PROGMEM = "
 " D_KNX_PARAMETERS " 
" "
" @@ -784,7 +787,6 @@ const char HTTP_FORM_KNX_ADD_BTN[] PROGMEM = const char HTTP_FORM_KNX_ADD_TABLE_ROW[] PROGMEM = "
" -// ""; ""; const char HTTP_FORM_KNX3[] PROGMEM = @@ -797,10 +799,8 @@ const char HTTP_FORM_KNX4[] PROGMEM = const char HTTP_FORM_KNX_ADD_TABLE_ROW2[] PROGMEM = "" -// ""; ""; - void HandleKNXConfiguration() { if (HttpUser()) { return; } @@ -971,7 +971,7 @@ void HandleKNXConfiguration() } } page += F("
" D_DOMOTICZ_IDX " {1
" D_DOMOTICZ_KEY_IDX " {1
" D_DOMOTICZ_SWITCH_IDX " {1
" D_DOMOTICZ_SENSOR_IDX " {1 {2
" D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ")
{optex} -> GAfnum / GAarea / GAfdef
GAfnum / GAarea / GAfdef -> {optex}
"); - page += F("
"); + page += F("
"); page += FPSTR(HTTP_BTN_CONF); page.replace( F(""), @@ -1295,6 +1295,16 @@ boolean Xdrv11(byte function) case FUNC_PRE_INIT: KNX_INIT(); break; +#ifdef USE_WEBSERVER +#ifdef USE_KNX_WEB_MENU + case FUNC_WEB_ADD_BUTTON: + strncat_P(mqtt_data, HTTP_BTN_MENU_KNX, sizeof(mqtt_data)); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/kn", HandleKNXConfiguration); + break; +#endif // USE_KNX_WEB_MENU +#endif // USE_WEBSERVER case FUNC_LOOP: knx.loop(); // Process knx events break; diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index f0b20ef59..d43ca90b1 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -835,4 +835,18 @@ void HandleHueApi(String *path) else if (path->endsWith("/rules")) HueNotImplemented(path); else HueGlobalConfig(path); } + +void HueWemoAddHandlers() +{ + if (EMUL_WEMO == Settings.flag2.emulation) { + WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); + WebServer->on("/eventservice.xml", HandleUpnpService); + WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); + WebServer->on("/setup.xml", HandleUpnpSetupWemo); + } + if (EMUL_HUE == Settings.flag2.emulation) { + WebServer->on("/description.xml", HandleUpnpSetupHue); + } +} + #endif // USE_WEBSERVER && USE_EMULATION From 8aabe10711d9cbfff479d47358d13d684412f797 Mon Sep 17 00:00:00 2001 From: guyelg Date: Wed, 10 Oct 2018 20:25:04 +0300 Subject: [PATCH 0250/2222] Add support for DS3231-external I2C RTC --- sonoff/xsns_33_ds3231.ino | 191 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 sonoff/xsns_33_ds3231.ino diff --git a/sonoff/xsns_33_ds3231.ino b/sonoff/xsns_33_ds3231.ino new file mode 100644 index 000000000..df18c73db --- /dev/null +++ b/sonoff/xsns_33_ds3231.ino @@ -0,0 +1,191 @@ +/* + xsns_33_ds3231.ino - ds3231 RTC chip, act like sensor support for Sonoff-Tasmota + + Copyright (C) 2018 Guy Elgabsi (guy.elg AT gmail.com) + + 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_DS3231 +/*********************************************************************************************\ + DS3231 - its a accurate RTC that used in the SONOFF for get time when you not have internet connection + This is minimal library that use only for read/write time ! + We store UTC time in the DS3231 , so we can use the standart functions. + HOWTO Use : first time, you must to have internet connection (use your mobile phone or try in other location). + once you have ntp connection , the DS3231 internal clock will be updated automatically. + you can now power off the device, from now and on the time is stored in the module and will + be restored when the is no connection to NTP. + Source: Guy Elgabsi with special thanks to Jack Christensen + + I2C Address: 0x68 + \*********************************************************************************************/ + +//DS3232 I2C Address +#ifndef USE_RTC_ADDR + #define USE_RTC_ADDR 0x68 +#endif + +//DS3232 Register Addresses +#define RTC_SECONDS 0x00 +#define RTC_MINUTES 0x01 +#define RTC_HOURS 0x02 +#define RTC_DAY 0x03 +#define RTC_DATE 0x04 +#define RTC_MONTH 0x05 +#define RTC_YEAR 0x06 +#define RTC_CONTROL 0x0E +#define RTC_STATUS 0x0F +//Control register bits +#define OSF 7 +#define EOSC 7 +#define BBSQW 6 +#define CONV 5 +#define RS2 4 +#define RS1 3 +#define INTCN 2 + +//Other +#define HR1224 6 //Hours register 12 or 24 hour mode (24 hour mode==0) +#define CENTURY 7 //Century bit in Month register +#define DYDT 6 //Day/Date flag bit in alarm Day/Date registers +boolean ds3231ReadStatus = false , ds3231WriteStatus = false; //flag, we want to wriet/write to DS3231 onlu once +boolean DS3231chipDetected; + + +/*----------------------------------------------------------------------* + Detect the DS3231 Chip + ----------------------------------------------------------------------*/ +boolean DS3231Detect() +{ + if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) + { + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "DS3231", USE_RTC_ADDR); + AddLog(LOG_LEVEL_INFO); + return true; + } + else + { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s *NOT* " D_FOUND_AT " 0x%x"), "DS3231", USE_RTC_ADDR); + AddLog(LOG_LEVEL_INFO); + return false; + } +} + +/*----------------------------------------------------------------------* + BCD-to-Decimal conversion + ----------------------------------------------------------------------*/ +uint8_t bcd2dec(uint8_t n) +{ + return n - 6 * (n >> 4); +} + +/*----------------------------------------------------------------------* + Decimal-to-BCD conversion + ----------------------------------------------------------------------*/ +uint8_t dec2bcd(uint8_t n) +{ + return n + 6 * (n / 10); +} + +/*----------------------------------------------------------------------* + Read time from DS3231 and return the epoch time (second since 1-1-1970 00:00) + ----------------------------------------------------------------------*/ +uint32_t ReadFromDS3231() +{ + TIME_T tm; + tm.second = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_SECONDS)); + tm.minute = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MINUTES)); + tm.hour = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_HOURS) & ~_BV(HR1224)); //assumes 24hr clock + tm.day_of_week = I2cRead8(USE_RTC_ADDR, RTC_DAY); + tm.day_of_month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_DATE)); + tm.month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MONTH) & ~_BV(CENTURY)); //don't use the Century bit + tm.year = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_YEAR)); + return MakeTime(tm); +} +/*----------------------------------------------------------------------* + Get time as TIME_T and set the DS3231 time to this value + ----------------------------------------------------------------------*/ +void SetDS3231Time (uint32_t epoch_time) { + TIME_T tm; + BreakTime(epoch_time, tm); + I2cWrite8(USE_RTC_ADDR, RTC_SECONDS, dec2bcd(tm.second)); + I2cWrite8(USE_RTC_ADDR, RTC_MINUTES, dec2bcd(tm.minute)); + I2cWrite8(USE_RTC_ADDR, RTC_HOURS, dec2bcd(tm.hour)); + I2cWrite8(USE_RTC_ADDR, RTC_DAY, tm.day_of_week); + I2cWrite8(USE_RTC_ADDR, RTC_DATE, dec2bcd(tm.day_of_month)); + I2cWrite8(USE_RTC_ADDR, RTC_MONTH, dec2bcd(tm.month)); + I2cWrite8(USE_RTC_ADDR, RTC_YEAR, dec2bcd(tm.year)); + I2cWrite8(USE_RTC_ADDR, RTC_STATUS, I2cRead8(USE_RTC_ADDR, RTC_STATUS) & ~_BV(OSF)); //clear the Oscillator Stop Flag +} + +/*********************************************************************************************\ + Interface + \*********************************************************************************************/ + +#define XSNS_33 + +boolean Xsns33(byte function) +{ + boolean result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + DS3231chipDetected = DS3231Detect(); + result = DS3231chipDetected; + break; + + case FUNC_EVERY_SECOND: + TIME_T tmpTime; + if (!ds3231ReadStatus && DS3231chipDetected && utc_time < 1451602800 ) { // We still did not sync with NTP (time not valid) , so, read time from DS3231 + ntp_force_sync = 1; //force to sync with ntp + utc_time = ReadFromDS3231(); //we read UTC TIME from DS3231 + // from this line, we just copy the function from "void RtcSecond()" at the support.ino ,line 2143 and above + // We need it to set rules etc. + BreakTime(utc_time, tmpTime); + if (utc_time < 1451602800 ) { + ds3231ReadStatus = true; //if time in DS3231 is valid, do not update again + } + RtcTime.year = tmpTime.year + 1970; + daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); + standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); + snprintf_P(log_data, sizeof(log_data), PSTR("Set time from DS3231 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + AddLog(LOG_LEVEL_INFO); + if (local_time < 1451602800) { // 2016-01-01 + rules_flag.time_init = 1; + } else { + rules_flag.time_set = 1; + } + result = true; + } + else if (!ds3231WriteStatus && DS3231chipDetected && utc_time > 1451602800 && abs(utc_time - ReadFromDS3231()) > 60) {//if time is valid and is drift from RTC in more that 60 second + snprintf_P(log_data, sizeof(log_data), PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + AddLog(LOG_LEVEL_INFO); + SetDS3231Time (utc_time); //update the DS3231 time + ds3231WriteStatus = true; + } + else { + result = false; + } + break; + } + } + return result; +} + +#endif // USE_DS3231 +#endif // USE_I2C From f98b4cf69d5e9f418d250de965bae1759bf3c03b Mon Sep 17 00:00:00 2001 From: guyelg Date: Wed, 10 Oct 2018 20:31:21 +0300 Subject: [PATCH 0251/2222] add support for DS3231 - I2C RTC --- sonoff/user_config.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 0ed7eba35..46a98c4e3 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -322,6 +322,8 @@ #define MTX_ADDRESS6 0x76 // [DisplayAddress6] I2C address of sixth 8x8 matrix module #define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module #define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module + #define USE_DS3231 // Enable use DS3231 external RTC , usefall when you don't have avaliable WIFI. see docs in the source file (+1k2 code) +// #define USE_RTC_ADDR //you can change the addrsss of the DS3231 RTC, default is 0x68, not mandatory fieled #endif // USE_I2C From 633a45f964d0dbf4d29b7dbc418d5d2a4504f91f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 10 Oct 2018 19:41:08 +0200 Subject: [PATCH 0252/2222] Revert "6.2.1.14 Webserver rewrite" This reverts commit 077b8a79e15be9446c3a7f796e895a87628de0cc. --- sonoff/_changelog.ino | 5 +- sonoff/i18n.h | 1 + sonoff/sonoff.h | 2 +- sonoff/sonoff_version.h | 2 +- sonoff/{xdrv_02_mqtt.ino => xdrv_01_mqtt.ino} | 103 +--- ...01_webserver.ino => xdrv_02_webserver.ino} | 466 ++++++++++-------- sonoff/xdrv_07_domoticz.ino | 49 +- sonoff/xdrv_09_timers.ino | 33 +- sonoff/xdrv_11_knx.ino | 18 +- sonoff/xplg_wemohue.ino | 14 - 10 files changed, 304 insertions(+), 389 deletions(-) rename sonoff/{xdrv_02_mqtt.ino => xdrv_01_mqtt.ino} (86%) rename sonoff/{xdrv_01_webserver.ino => xdrv_02_webserver.ino} (84%) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index def41834a..b2210c830 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,7 +1,4 @@ -/* 6.2.1.14 20181010 - * Rewrite Webserver page handler for easier extension (thx to Adrian Scillato) - * - * 6.2.1.13 20181008 +/* 6.2.1.13 20181008 * Change default Mqtt client library from PubSubClient to non-blocking ArduinoMqtt by Joel Gaehwiler * Add command WebRefresh 1000..10000 to control web page refresh in milliseconds. Default is 2345 * diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 62226f91f..ab1f0a1d2 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -539,6 +539,7 @@ const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION; const char S_CONFIGURE_MODULE[] PROGMEM = D_CONFIGURE_MODULE; const char S_CONFIGURE_WIFI[] PROGMEM = D_CONFIGURE_WIFI; const char S_NO_NETWORKS_FOUND[] PROGMEM = D_NO_NETWORKS_FOUND; +const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT; const char S_CONFIGURE_LOGGING[] PROGMEM = D_CONFIGURE_LOGGING; const char S_CONFIGURE_OTHER[] PROGMEM = D_CONFIGURE_OTHER; const char S_SAVE_CONFIGURATION[] PROGMEM = D_SAVE_CONFIGURATION; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 5bc744157..5d41aa18d 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -214,7 +214,7 @@ enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MA enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, - FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_HANDLER}; + FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 080c76fa4..eba7ddc21 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0602010E +#define VERSION 0x0602010D #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_01_mqtt.ino similarity index 86% rename from sonoff/xdrv_02_mqtt.ino rename to sonoff/xdrv_01_mqtt.ino index 1cd6d9aff..3cb76e86d 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_01_mqtt.ino @@ -1,5 +1,5 @@ /* - xdrv_02_mqtt.ino - mqtt support for Sonoff-Tasmota + xdrv_01_mqtt.ino - mqtt support for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -782,115 +782,18 @@ bool MqttCommand() return serviced; } -/*********************************************************************************************\ - * Presentation -\*********************************************************************************************/ - -#ifdef USE_WEBSERVER - -#define WEB_HANDLE_MQTT "mq" - -const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT; - -const char HTTP_BTN_MENU_MQTT[] PROGMEM = - "
"; - -const char HTTP_FORM_MQTT[] PROGMEM = - "
 " D_MQTT_PARAMETERS " 
" - "
" D_HOST " (" MQTT_HOST ")

" - "
" D_PORT " (" STR(MQTT_PORT) ")

" - "
" D_CLIENT " ({m0)

" - "
" D_USER " (" MQTT_USER ")

" - "
" D_PASSWORD "

" - "
" D_TOPIC " = %topic% (" MQTT_TOPIC ")

" - "
" D_FULL_TOPIC " (" MQTT_FULLTOPIC ")

"; - -void HandleMqttConfiguration() -{ - if (HttpUser()) { return; } - if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT); - - if (WebServer->hasArg("save")) { - MqttSaveSettings(); - WaitForRestart(""); - return; - } - - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_MQTT)); - page += FPSTR(HTTP_HEAD_STYLE); - - page += FPSTR(HTTP_FORM_MQTT); - char str[sizeof(Settings.mqtt_client)]; - page.replace(F("{m0"), Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client))); - page.replace(F("{m1"), Settings.mqtt_host); - page.replace(F("{m2"), String(Settings.mqtt_port)); - page.replace(F("{m3"), Settings.mqtt_client); - page.replace(F("{m4"), (Settings.mqtt_user[0] == '\0')?"0":Settings.mqtt_user); - page.replace(F("{m5"), (Settings.mqtt_pwd[0] == '\0')?"0":Settings.mqtt_pwd); - page.replace(F("{m6"), Settings.mqtt_topic); - page.replace(F("{m7"), Settings.mqtt_fulltopic); - - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); -} - -void MqttSaveSettings() -{ - char tmp[100]; - char stemp[TOPSZ]; - char stemp2[TOPSZ]; - - WebGetArg("mt", tmp, sizeof(tmp)); - strlcpy(stemp, (!strlen(tmp)) ? MQTT_TOPIC : tmp, sizeof(stemp)); - MakeValidMqtt(0, stemp); - WebGetArg("mf", tmp, sizeof(tmp)); - strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); - MakeValidMqtt(1,stemp2); - if ((strcmp(stemp, Settings.mqtt_topic)) || (strcmp(stemp2, Settings.mqtt_fulltopic))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : ""); - MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic - } - strlcpy(Settings.mqtt_topic, stemp, sizeof(Settings.mqtt_topic)); - strlcpy(Settings.mqtt_fulltopic, stemp2, sizeof(Settings.mqtt_fulltopic)); - WebGetArg("mh", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_host, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_host)); - WebGetArg("ml", tmp, sizeof(tmp)); - Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); - WebGetArg("mc", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_client, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp, sizeof(Settings.mqtt_client)); - WebGetArg("mu", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user)); - WebGetArg("mp", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? MQTT_PASS : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_pwd)); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_MQTTPASSWORD " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), - Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_pwd, Settings.mqtt_topic, Settings.mqtt_fulltopic); - AddLog(LOG_LEVEL_INFO); -} -#endif // USE_WEBSERVER - /*********************************************************************************************\ * Interface \*********************************************************************************************/ -#define XDRV_02 +#define XDRV_01 -boolean Xdrv02(byte function) +boolean Xdrv01(byte function) { boolean result = false; if (Settings.flag.mqtt_enabled) { switch (function) { -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_MQTT, sizeof(mqtt_data)); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); - break; -#endif // USE_WEBSERVER case FUNC_LOOP: MqttLoop(); break; diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_02_webserver.ino similarity index 84% rename from sonoff/xdrv_01_webserver.ino rename to sonoff/xdrv_02_webserver.ino index 50345145f..099411eba 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -1,5 +1,5 @@ /* - xdrv_01_webserver.ino - webserver for Sonoff-Tasmota + xdrv_02_webserver.ino - webserver for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -193,9 +193,25 @@ const char HTTP_BTN_MENU1[] PROGMEM = const char HTTP_BTN_RSTRT[] PROGMEM = "
"; const char HTTP_BTN_MENU_MODULE[] PROGMEM = - "
" - "
"; + "
"; +#if defined(USE_TIMERS) && defined(USE_TIMERS_WEB) +const char HTTP_BTN_MENU_TIMER[] PROGMEM = + "
"; +#endif // USE_TIMERS and USE_TIMERS_WEB +const char HTTP_BTN_MENU_WIFI[] PROGMEM = + "
"; +const char HTTP_BTN_MENU_MQTT[] PROGMEM = + "
" +#ifdef USE_DOMOTICZ + "
" +#endif // USE_DOMOTICZ + ""; const char HTTP_BTN_MENU4[] PROGMEM = +#ifdef USE_KNX +#ifdef USE_KNX_WEB_MENU + "
" +#endif // USE_KNX_WEB_MENU +#endif // USE_KNX "
" "
" "
" @@ -213,21 +229,34 @@ const char HTTP_FORM_LOGIN[] PROGMEM = const char HTTP_BTN_CONF[] PROGMEM = "

"; const char HTTP_FORM_MODULE[] PROGMEM = - "
 " D_MODULE_PARAMETERS " 
" + "
 " D_MODULE_PARAMETERS " " + "" "
" D_MODULE_TYPE " ({mt)

"; const char HTTP_LNK_ITEM[] PROGMEM = "
{v} ({w}) {i} {r}%
"; const char HTTP_LNK_SCAN[] PROGMEM = - "
"; + "
"; const char HTTP_FORM_WIFI[] PROGMEM = - "
 " D_WIFI_PARAMETERS " " + "
 " D_WIFI_PARAMETERS " " + "" "
" D_AP1_SSID " (" STA_SSID1 ")

" "
" D_AP1_PASSWORD "

" "
" D_AP2_SSID " (" STA_SSID2 ")

" "
" D_AP2_PASSWORD "

" "
" D_HOSTNAME " (" WIFI_HOSTNAME ")

"; +const char HTTP_FORM_MQTT[] PROGMEM = + "
 " D_MQTT_PARAMETERS " " + "" + "
" D_HOST " (" MQTT_HOST ")

" + "
" D_PORT " (" STR(MQTT_PORT) ")

" + "
" D_CLIENT " ({m0)

" + "
" D_USER " (" MQTT_USER ")

" + "
" D_PASSWORD "

" + "
" D_TOPIC " = %topic% (" MQTT_TOPIC ")

" + "
" D_FULL_TOPIC " (" MQTT_FULLTOPIC ")

"; const char HTTP_FORM_LOG1[] PROGMEM = - "
 " D_LOGGING_PARAMETERS " "; + "
 " D_LOGGING_PARAMETERS " " + ""; const char HTTP_FORM_LOG2[] PROGMEM = "
{b0 ({b1)

" "
" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

"; const char HTTP_FORM_OTHER[] PROGMEM = - "
 " D_OTHER_PARAMETERS " " -// "" + "
 " D_OTHER_PARAMETERS " " + "" "
" D_WEB_ADMIN_PASSWORD "

" "
" D_MQTT_ENABLE "
"; const char HTTP_FORM_OTHER2[] PROGMEM = @@ -254,7 +283,7 @@ const char HTTP_FORM_OTHER3b[] PROGMEM = "
{3{4"; // Different id only used for labels #endif // USE_EMULATION const char HTTP_FORM_END[] PROGMEM = - "
"; + "
"; const char HTTP_FORM_RST[] PROGMEM = "
" "
 " D_RESTORE_CONFIGURATION " "; @@ -354,23 +383,46 @@ void StartWebserver(int type, IPAddress ipweb) WebServer->on("/ay", HandleAjaxStatusRefresh); WebServer->on("/cm", HandleHttpCommand); WebServer->on("/rb", HandleRestart); -// WebServer->on("/fwlink", HandleRoot); // Microsoft captive portal. Maybe not needed. Might be handled by notFound handler. - WebServer->onNotFound(HandleNotFound); #ifndef BE_MINIMAL WebServer->on("/cn", HandleConfiguration); WebServer->on("/md", HandleModuleConfiguration); - WebServer->on("/wi", HandleWifiConfiguration); +#if defined(USE_TIMERS) && defined(USE_TIMERS_WEB) + WebServer->on("/tm", HandleTimerConfiguration); +#endif // USE_TIMERS and USE_TIMERS_WEB + WebServer->on("/w1", HandleWifiConfigurationWithScan); + WebServer->on("/w0", HandleWifiConfiguration); + if (Settings.flag.mqtt_enabled) { + WebServer->on("/mq", HandleMqttConfiguration); +#ifdef USE_DOMOTICZ + WebServer->on("/dm", HandleDomoticzConfiguration); +#endif // USE_DOMOTICZ + } +#ifdef USE_KNX +#ifdef USE_KNX_WEB_MENU + WebServer->on("/kn", HandleKNXConfiguration); +#endif // USE_KNX_WEB_MENU +#endif // USE_KNX WebServer->on("/lg", HandleLoggingConfiguration); WebServer->on("/co", HandleOtherConfiguration); WebServer->on("/dl", HandleBackupConfiguration); + WebServer->on("/sv", HandleSaveSettings); WebServer->on("/rs", HandleRestoreConfiguration); WebServer->on("/rt", HandleResetConfiguration); WebServer->on("/in", HandleInformation); #ifdef USE_EMULATION - HueWemoAddHandlers(); + if (EMUL_WEMO == Settings.flag2.emulation) { + WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); + WebServer->on("/eventservice.xml", HandleUpnpService); + WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); + WebServer->on("/setup.xml", HandleUpnpSetupWemo); + } + if (EMUL_HUE == Settings.flag2.emulation) { + WebServer->on("/description.xml", HandleUpnpSetupHue); + } #endif // USE_EMULATION - XdrvCall(FUNC_WEB_ADD_HANDLER); #endif // Not BE_MINIMAL + WebServer->on("/fwlink", HandleRoot); // Microsoft captive portal. Maybe not needed. Might be handled by notFound handler. + WebServer->onNotFound(HandleNotFound); } reset_web_log_flag = 0; WebServer->begin(); // Web server start @@ -645,30 +697,7 @@ boolean HttpUser() return status; } -/*-------------------------------------------------------------------------------------------*/ - #ifndef BE_MINIMAL - -void WaitForRestart(String result) -{ - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_SAVE_CONFIGURATION)); - page += FPSTR(HTTP_HEAD_STYLE); - page += F("
" D_CONFIGURATION_SAVED "
"); - page += result; - page += F("
"); - page += FPSTR(HTTP_MSG_RSTRT); - if (HTTP_MANAGER == webserver_state) { - webserver_state = HTTP_ADMIN; - } else { - page += FPSTR(HTTP_BTN_MAIN); - } - ShowPage(page); - - ShowWebSource(SRC_WEBGUI); - restart_flag = 2; -} - void HandleConfiguration() { if (HttpUser()) { return; } @@ -679,34 +708,29 @@ void HandleConfiguration() page.replace(F("{v}"), FPSTR(S_CONFIGURATION)); page += FPSTR(HTTP_HEAD_STYLE); page += FPSTR(HTTP_BTN_MENU_MODULE); - - mqtt_data[0] = '\0'; - XdrvCall(FUNC_WEB_ADD_BUTTON); - page += String(mqtt_data); - +#if defined(USE_TIMERS) && defined(USE_TIMERS_WEB) +#ifdef USE_RULES + page += FPSTR(HTTP_BTN_MENU_TIMER); +#else + if (devices_present) { page += FPSTR(HTTP_BTN_MENU_TIMER); } +#endif // USE_RULES +#endif // USE_TIMERS and USE_TIMERS_WEB + page += FPSTR(HTTP_BTN_MENU_WIFI); + if (Settings.flag.mqtt_enabled) { page += FPSTR(HTTP_BTN_MENU_MQTT); } page += FPSTR(HTTP_BTN_MENU4); page += FPSTR(HTTP_BTN_MAIN); ShowPage(page); } -/*-------------------------------------------------------------------------------------------*/ - void HandleModuleConfiguration() { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); - - if (WebServer->hasArg("save")) { - ModuleSaveSettings(); - WaitForRestart(""); - return; - } - char stemp[20]; uint8_t midx; + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); + String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE)); page += FPSTR(HTTP_SCRIPT_MODULE1); @@ -759,36 +783,15 @@ void HandleModuleConfiguration() ShowPage(page); } -void ModuleSaveSettings() +void HandleWifiConfigurationWithScan() { - char tmp[100]; - char stemp[TOPSZ]; - - WebGetArg("g99", tmp, sizeof(tmp)); - byte new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); - Settings.last_module = Settings.module; - Settings.module = new_module; - mytmplt cmodule; - memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); - String gpios = ""; - for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (Settings.last_module != new_module) { - Settings.my_gp.io[i] = 0; - } else { - if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { - snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), i); - WebGetArg(stemp, tmp, sizeof(tmp)); - Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); - } - } - } - snprintf_P(stemp, sizeof(stemp), kModules[Settings.module].name); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), stemp, gpios.c_str()); - AddLog(LOG_LEVEL_INFO); + HandleWifi(true); } -/*-------------------------------------------------------------------------------------------*/ +void HandleWifiConfiguration() +{ + HandleWifi(false); +} String htmlEscape(String s) { @@ -801,25 +804,18 @@ String htmlEscape(String s) return s; } -void HandleWifiConfiguration() +void HandleWifi(boolean scan) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); - if (WebServer->hasArg("save")) { - WifiSaveSettings(); - String result = F("
" D_TRYING_TO_CONNECT "
"); - WaitForRestart(result); - return; - } - String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_CONFIGURE_WIFI)); page += FPSTR(HTTP_HEAD_STYLE); - if (WebServer->hasArg("scan")) { + if (scan) { #ifdef USE_EMULATION UdpDisconnect(); #endif // USE_EMULATION @@ -905,46 +901,39 @@ void HandleWifiConfiguration() ShowPage(page, !(HTTP_MANAGER == webserver_state)); } -void WifiSaveSettings() +void HandleMqttConfiguration() { - char tmp[100]; + if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT); - WebGetArg("h", tmp, sizeof(tmp)); - strlcpy(Settings.hostname, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp, sizeof(Settings.hostname)); - if (strstr(Settings.hostname,"%")) { - strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); - } - WebGetArg("s1", tmp, sizeof(tmp)); - strlcpy(Settings.sta_ssid[0], (!strlen(tmp)) ? STA_SSID1 : tmp, sizeof(Settings.sta_ssid[0])); - WebGetArg("s2", tmp, sizeof(tmp)); - strlcpy(Settings.sta_ssid[1], (!strlen(tmp)) ? STA_SSID2 : tmp, sizeof(Settings.sta_ssid[1])); - WebGetArg("p1", tmp, sizeof(tmp)); - strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); - WebGetArg("p2", tmp, sizeof(tmp)); - strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s"), - Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1]); - AddLog(LOG_LEVEL_INFO); + String page = FPSTR(HTTP_HEAD); + page.replace(F("{v}"), FPSTR(S_CONFIGURE_MQTT)); + page += FPSTR(HTTP_HEAD_STYLE); + page += FPSTR(HTTP_FORM_MQTT); + char str[sizeof(Settings.mqtt_client)]; + page.replace(F("{m0"), Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client))); + page.replace(F("{m1"), Settings.mqtt_host); + page.replace(F("{m2"), String(Settings.mqtt_port)); + page.replace(F("{m3"), Settings.mqtt_client); + page.replace(F("{m4"), (Settings.mqtt_user[0] == '\0')?"0":Settings.mqtt_user); + page.replace(F("{m5"), (Settings.mqtt_pwd[0] == '\0')?"0":Settings.mqtt_pwd); + page.replace(F("{m6"), Settings.mqtt_topic); + page.replace(F("{m7"), Settings.mqtt_fulltopic); + page += FPSTR(HTTP_FORM_END); + page += FPSTR(HTTP_BTN_CONF); + ShowPage(page); } -/*-------------------------------------------------------------------------------------------*/ - void HandleLoggingConfiguration() { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_LOGGING); - if (WebServer->hasArg("save")) { - LoggingSaveSettings(); - HandleConfiguration(); - return; - } - String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_CONFIGURE_LOGGING)); page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_LOG1); for (byte idx = 0; idx < 3; idx++) { page += FPSTR(HTTP_FORM_LOG2); @@ -984,46 +973,11 @@ void HandleLoggingConfiguration() ShowPage(page); } -void LoggingSaveSettings() -{ - char tmp[100]; - - WebGetArg("ls", tmp, sizeof(tmp)); - Settings.seriallog_level = (!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp); - WebGetArg("lw", tmp, sizeof(tmp)); - Settings.weblog_level = (!strlen(tmp)) ? WEB_LOG_LEVEL : atoi(tmp); - WebGetArg("ll", tmp, sizeof(tmp)); - Settings.syslog_level = (!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp); - syslog_level = Settings.syslog_level; - syslog_timer = 0; - WebGetArg("lh", tmp, sizeof(tmp)); - strlcpy(Settings.syslog_host, (!strlen(tmp)) ? SYS_LOG_HOST : tmp, sizeof(Settings.syslog_host)); - WebGetArg("lp", tmp, sizeof(tmp)); - Settings.syslog_port = (!strlen(tmp)) ? SYS_LOG_PORT : atoi(tmp); - WebGetArg("lt", tmp, sizeof(tmp)); - Settings.tele_period = (!strlen(tmp)) ? TELE_PERIOD : atoi(tmp); - if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) { - Settings.tele_period = 10; // Do not allow periods < 10 seconds - } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_LOG D_CMND_SERIALLOG " %d, " D_CMND_WEBLOG " %d, " D_CMND_SYSLOG " %d, " D_CMND_LOGHOST " %s, " D_CMND_LOGPORT " %d, " D_CMND_TELEPERIOD " %d"), - Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); - AddLog(LOG_LEVEL_INFO); -} - -/*-------------------------------------------------------------------------------------------*/ - void HandleOtherConfiguration() { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_OTHER); - - if (WebServer->hasArg("save")) { - OtherSaveSettings(); - WaitForRestart(""); - return; - } - char stemp[40]; String page = FPSTR(HTTP_HEAD); @@ -1057,32 +1011,6 @@ void HandleOtherConfiguration() ShowPage(page); } -void OtherSaveSettings() -{ - char tmp[100]; - char stemp[TOPSZ]; - char stemp2[TOPSZ]; - - WebGetArg("p1", tmp, sizeof(tmp)); - strlcpy(Settings.web_password, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.web_password : tmp, sizeof(Settings.web_password)); - Settings.flag.mqtt_enabled = WebServer->hasArg("b1"); -#ifdef USE_EMULATION - WebGetArg("b2", tmp, sizeof(tmp)); - Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); -#endif // USE_EMULATION - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); - for (byte i = 0; i < MAX_FRIENDLYNAMES; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("a%d"), i +1); - WebGetArg(stemp, tmp, sizeof(tmp)); - snprintf_P(stemp2, sizeof(stemp2), PSTR(FRIENDLY_NAME"%d"), i +1); - strlcpy(Settings.friendlyname[i], (!strlen(tmp)) ? (i) ? stemp2 : FRIENDLY_NAME : tmp, sizeof(Settings.friendlyname[i])); - snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", Settings.friendlyname[i]); - } - AddLog(LOG_LEVEL_INFO); -} - -/*-------------------------------------------------------------------------------------------*/ - void HandleBackupConfiguration() { if (HttpUser()) { return; } @@ -1125,7 +1053,171 @@ void HandleBackupConfiguration() Settings.cfg_crc = cfg_crc; // Restore crc in case savedata = 0 to make sure settings will be noted as changed } -/*-------------------------------------------------------------------------------------------*/ +void HandleSaveSettings() +{ + if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } + + char stemp[TOPSZ]; + char stemp2[TOPSZ]; + String result = ""; + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_SAVE_CONFIGURATION); + + char tmp[100]; + WebGetArg("w", tmp, sizeof(tmp)); // Returns "5,1" where 5 is config type and 1 is restart flag + char *p = tmp; + uint8_t what = strtol(p, &p, 10); + p++; // Skip comma + uint8_t restart = strtol(p, &p, 10); + switch (what) { + case 1: + WebGetArg("h", tmp, sizeof(tmp)); + strlcpy(Settings.hostname, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp, sizeof(Settings.hostname)); + if (strstr(Settings.hostname,"%")) { + strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); + } + WebGetArg("s1", tmp, sizeof(tmp)); + strlcpy(Settings.sta_ssid[0], (!strlen(tmp)) ? STA_SSID1 : tmp, sizeof(Settings.sta_ssid[0])); + WebGetArg("s2", tmp, sizeof(tmp)); + strlcpy(Settings.sta_ssid[1], (!strlen(tmp)) ? STA_SSID2 : tmp, sizeof(Settings.sta_ssid[1])); +// WebGetArg("s1", tmp, sizeof(tmp)); +// strlcpy(Settings.sta_ssid[0], (!strlen(tmp)) ? "" : tmp, sizeof(Settings.sta_ssid[0])); +// WebGetArg("s2", tmp, sizeof(tmp)); +// strlcpy(Settings.sta_ssid[1], (!strlen(tmp)) ? "" : tmp, sizeof(Settings.sta_ssid[1])); + WebGetArg("p1", tmp, sizeof(tmp)); + strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); + WebGetArg("p2", tmp, sizeof(tmp)); + strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s"), + Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1]); + AddLog(LOG_LEVEL_INFO); + result += F("
" D_TRYING_TO_CONNECT "
"); + break; + case 2: + WebGetArg("mt", tmp, sizeof(tmp)); + strlcpy(stemp, (!strlen(tmp)) ? MQTT_TOPIC : tmp, sizeof(stemp)); + MakeValidMqtt(0, stemp); + WebGetArg("mf", tmp, sizeof(tmp)); + strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); + MakeValidMqtt(1,stemp2); + if ((strcmp(stemp, Settings.mqtt_topic)) || (strcmp(stemp2, Settings.mqtt_fulltopic))) { + snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic + } + strlcpy(Settings.mqtt_topic, stemp, sizeof(Settings.mqtt_topic)); + strlcpy(Settings.mqtt_fulltopic, stemp2, sizeof(Settings.mqtt_fulltopic)); + WebGetArg("mh", tmp, sizeof(tmp)); + strlcpy(Settings.mqtt_host, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_host)); + WebGetArg("ml", tmp, sizeof(tmp)); + Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); + WebGetArg("mc", tmp, sizeof(tmp)); + strlcpy(Settings.mqtt_client, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp, sizeof(Settings.mqtt_client)); + WebGetArg("mu", tmp, sizeof(tmp)); + strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user)); + WebGetArg("mp", tmp, sizeof(tmp)); + strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? MQTT_PASS : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_pwd)); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_MQTTPASSWORD " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), + Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_pwd, Settings.mqtt_topic, Settings.mqtt_fulltopic); + AddLog(LOG_LEVEL_INFO); + break; + case 3: + WebGetArg("ls", tmp, sizeof(tmp)); + Settings.seriallog_level = (!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp); + WebGetArg("lw", tmp, sizeof(tmp)); + Settings.weblog_level = (!strlen(tmp)) ? WEB_LOG_LEVEL : atoi(tmp); + WebGetArg("ll", tmp, sizeof(tmp)); + Settings.syslog_level = (!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp); + syslog_level = Settings.syslog_level; + syslog_timer = 0; + WebGetArg("lh", tmp, sizeof(tmp)); + strlcpy(Settings.syslog_host, (!strlen(tmp)) ? SYS_LOG_HOST : tmp, sizeof(Settings.syslog_host)); + WebGetArg("lp", tmp, sizeof(tmp)); + Settings.syslog_port = (!strlen(tmp)) ? SYS_LOG_PORT : atoi(tmp); + WebGetArg("lt", tmp, sizeof(tmp)); + Settings.tele_period = (!strlen(tmp)) ? TELE_PERIOD : atoi(tmp); + if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) { + Settings.tele_period = 10; // Do not allow periods < 10 seconds + } + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_LOG D_CMND_SERIALLOG " %d, " D_CMND_WEBLOG " %d, " D_CMND_SYSLOG " %d, " D_CMND_LOGHOST " %s, " D_CMND_LOGPORT " %d, " D_CMND_TELEPERIOD " %d"), + Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); + AddLog(LOG_LEVEL_INFO); + break; +#if defined(USE_TIMERS) && defined(USE_TIMERS_WEB) + case 7: + TimerSaveSettings(); + break; +#endif // USE_TIMERS and USE_TIMERS_WEB +#ifdef USE_DOMOTICZ + case 4: + DomoticzSaveSettings(); + break; +#endif // USE_DOMOTICZ + case 5: + WebGetArg("p1", tmp, sizeof(tmp)); + strlcpy(Settings.web_password, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.web_password : tmp, sizeof(Settings.web_password)); + Settings.flag.mqtt_enabled = WebServer->hasArg("b1"); +#ifdef USE_EMULATION + WebGetArg("b2", tmp, sizeof(tmp)); + Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); +#endif // USE_EMULATION + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); + for (byte i = 0; i < MAX_FRIENDLYNAMES; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("a%d"), i +1); + WebGetArg(stemp, tmp, sizeof(tmp)); + snprintf_P(stemp2, sizeof(stemp2), PSTR(FRIENDLY_NAME"%d"), i +1); + strlcpy(Settings.friendlyname[i], (!strlen(tmp)) ? (i) ? stemp2 : FRIENDLY_NAME : tmp, sizeof(Settings.friendlyname[i])); + snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", Settings.friendlyname[i]); + } + AddLog(LOG_LEVEL_INFO); + break; + case 6: + WebGetArg("g99", tmp, sizeof(tmp)); + byte new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); + Settings.last_module = Settings.module; + Settings.module = new_module; + mytmplt cmodule; + memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); + String gpios = ""; + for (byte i = 0; i < MAX_GPIO_PIN; i++) { + if (Settings.last_module != new_module) { + Settings.my_gp.io[i] = 0; + } else { + if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { + snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), i); + WebGetArg(stemp, tmp, sizeof(tmp)); + Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); + gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); + } + } + } + snprintf_P(stemp, sizeof(stemp), kModules[Settings.module].name); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), stemp, gpios.c_str()); + AddLog(LOG_LEVEL_INFO); + break; + } + + if (restart) { + String page = FPSTR(HTTP_HEAD); + page.replace(F("{v}"), FPSTR(S_SAVE_CONFIGURATION)); + page += FPSTR(HTTP_HEAD_STYLE); + page += F("
" D_CONFIGURATION_SAVED "
"); + page += result; + page += F("
"); + page += FPSTR(HTTP_MSG_RSTRT); + if (HTTP_MANAGER == webserver_state) { + webserver_state = HTTP_ADMIN; + } else { + page += FPSTR(HTTP_BTN_MAIN); + } + ShowPage(page); + + ShowWebSource(SRC_WEBGUI); + restart_flag = 2; + } else { + HandleConfiguration(); + } +} void HandleResetConfiguration() { @@ -1167,8 +1259,6 @@ void HandleRestoreConfiguration() upload_file_type = UPL_SETTINGS; } -/*-------------------------------------------------------------------------------------------*/ - void HandleInformation() { if (HttpUser()) { return; } @@ -1286,8 +1376,6 @@ void HandleInformation() } #endif // Not BE_MINIMAL -/*-------------------------------------------------------------------------------------------*/ - void HandleUpgradeFirmware() { if (HttpUser()) { return; } @@ -1581,8 +1669,6 @@ void HandleUploadLoop() delay(0); } -/*-------------------------------------------------------------------------------------------*/ - void HandlePreflightRequest() { WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); @@ -1591,8 +1677,6 @@ void HandlePreflightRequest() WebServer->send(200, FPSTR(HDR_CTYPE_HTML), ""); } -/*-------------------------------------------------------------------------------------------*/ - void HandleHttpCommand() { if (HttpUser()) { return; } @@ -1651,8 +1735,6 @@ void HandleHttpCommand() WebServer->send(200, FPSTR(HDR_CTYPE_JSON), message); } -/*-------------------------------------------------------------------------------------------*/ - void HandleConsole() { if (HttpUser()) { return; } @@ -1726,8 +1808,6 @@ void HandleAjaxConsoleRefresh() WebServer->send(200, FPSTR(HDR_CTYPE_XML), message); } -/*-------------------------------------------------------------------------------------------*/ - void HandleRestart() { if (HttpUser()) { return; } @@ -1981,9 +2061,9 @@ bool WebCommand() * Interface \*********************************************************************************************/ -#define XDRV_01 +#define XDRV_02 -boolean Xdrv01(byte function) +boolean Xdrv02(byte function) { boolean result = false; diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index d40bae88f..7710cad13 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -19,6 +19,22 @@ #ifdef USE_DOMOTICZ +#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_SENSOR[] PROGMEM = + ""; +const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM = + ""; +#endif // USE_WEBSERVER + const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\",\"Battery\":%d,\"RSSI\":%d}"; enum DomoticzCommands { CMND_IDX, CMND_KEYIDX, CMND_SWITCHIDX, CMND_SENSORIDX, CMND_UPDATETIMER }; @@ -370,39 +386,14 @@ void DomoticzSensorPowerEnergy(int power, char *energy) \*********************************************************************************************/ #ifdef USE_WEBSERVER - -#define WEB_HANDLE_DOMOTICZ "dm" - const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ; -const char HTTP_BTN_MENU_DOMOTICZ[] PROGMEM = - "
"; - -const char HTTP_FORM_DOMOTICZ[] PROGMEM = - "
 " D_DOMOTICZ_PARAMETERS " 
" - "
" D_DOMOTICZ_IDX " {1
" D_DOMOTICZ_KEY_IDX " {1
" D_DOMOTICZ_SWITCH_IDX " {1
" D_DOMOTICZ_SENSOR_IDX " {1 {2
" D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ")
"; -const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM = - "" - ""; - const char HTTP_FORM_DOMOTICZ_SWITCH[] PROGMEM = - ""; -const char HTTP_FORM_DOMOTICZ_SENSOR[] PROGMEM = - ""; -const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM = - ""; - void HandleDomoticzConfiguration() { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_DOMOTICZ); - if (WebServer->hasArg("save")) { - DomoticzSaveSettings(); - WaitForRestart(""); - return; - } - char stemp[32]; String page = FPSTR(HTTP_HEAD); @@ -483,14 +474,6 @@ boolean Xdrv07(byte function) if (Settings.flag.mqtt_enabled) { switch (function) { -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_DOMOTICZ, sizeof(mqtt_data)); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration); - break; -#endif // USE_WEBSERVER case FUNC_COMMAND: result = DomoticzCommand(); break; diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 338a8ddc0..124b41534 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -510,14 +510,6 @@ boolean TimerCommand() #ifdef USE_WEBSERVER #ifdef USE_TIMERS_WEB - -#define WEB_HANDLE_TIMER "tm" - -const char S_CONFIGURE_TIMER[] PROGMEM = D_CONFIGURE_TIMER; - -const char HTTP_BTN_MENU_TIMER[] PROGMEM = - "
"; - const char HTTP_TIMER_SCRIPT[] PROGMEM = "var pt=[],ct=99;" "function qs(s){" // Alias to save code space @@ -647,7 +639,8 @@ const char HTTP_TIMER_STYLE[] PROGMEM = #endif ""; const char HTTP_FORM_TIMER[] PROGMEM = - "
 " D_TIMER_PARAMETERS " 
" + "
 " D_TIMER_PARAMETERS " " + "" "
" D_TIMER_ENABLE "


" "requestAuthentication(); } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TIMER); - if (WebServer->hasArg("save")) { - TimerSaveSettings(); - HandleConfiguration(); - return; - } - String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_CONFIGURE_TIMER)); page += FPSTR(HTTP_TIMER_SCRIPT); @@ -754,20 +743,6 @@ boolean Xdrv09(byte function) case FUNC_PRE_INIT: TimerSetRandomWindows(); break; -#ifdef USE_WEBSERVER -#ifdef USE_TIMERS_WEB - case FUNC_WEB_ADD_BUTTON: -#ifdef USE_RULES - strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data)); -#else - if (devices_present) { strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data)); } -#endif // USE_RULES - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_TIMER, HandleTimerConfiguration); - break; -#endif // USE_TIMERS_WEB -#endif // USE_WEBSERVER case FUNC_EVERY_SECOND: TimerEverySecond(); break; diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 6132133ae..88260b23c 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -749,9 +749,6 @@ void KnxSensor(byte sensor_type, float value) #ifdef USE_KNX_WEB_MENU const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX; -const char HTTP_BTN_MENU_KNX[] PROGMEM = - "
"; - const char HTTP_FORM_KNX[] PROGMEM = "
 " D_KNX_PARAMETERS " 
" "
" @@ -787,6 +784,7 @@ const char HTTP_FORM_KNX_ADD_BTN[] PROGMEM = const char HTTP_FORM_KNX_ADD_TABLE_ROW[] PROGMEM = "
" +// ""; ""; const char HTTP_FORM_KNX3[] PROGMEM = @@ -799,8 +797,10 @@ const char HTTP_FORM_KNX4[] PROGMEM = const char HTTP_FORM_KNX_ADD_TABLE_ROW2[] PROGMEM = "" +// ""; ""; + void HandleKNXConfiguration() { if (HttpUser()) { return; } @@ -971,7 +971,7 @@ void HandleKNXConfiguration() } } page += F("
" D_DOMOTICZ_IDX " {1
" D_DOMOTICZ_KEY_IDX " {1
" D_DOMOTICZ_SWITCH_IDX " {1
" D_DOMOTICZ_SENSOR_IDX " {1 {2
" D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ")
{optex} -> GAfnum / GAarea / GAfdef
GAfnum / GAarea / GAfdef -> {optex}
"); - page += F("
"); + page += F("
"); page += FPSTR(HTTP_BTN_CONF); page.replace( F(""), @@ -1295,16 +1295,6 @@ boolean Xdrv11(byte function) case FUNC_PRE_INIT: KNX_INIT(); break; -#ifdef USE_WEBSERVER -#ifdef USE_KNX_WEB_MENU - case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_KNX, sizeof(mqtt_data)); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/kn", HandleKNXConfiguration); - break; -#endif // USE_KNX_WEB_MENU -#endif // USE_WEBSERVER case FUNC_LOOP: knx.loop(); // Process knx events break; diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index d43ca90b1..f0b20ef59 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -835,18 +835,4 @@ void HandleHueApi(String *path) else if (path->endsWith("/rules")) HueNotImplemented(path); else HueGlobalConfig(path); } - -void HueWemoAddHandlers() -{ - if (EMUL_WEMO == Settings.flag2.emulation) { - WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); - WebServer->on("/eventservice.xml", HandleUpnpService); - WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); - WebServer->on("/setup.xml", HandleUpnpSetupWemo); - } - if (EMUL_HUE == Settings.flag2.emulation) { - WebServer->on("/description.xml", HandleUpnpSetupHue); - } -} - #endif // USE_WEBSERVER && USE_EMULATION From 5684c844aa3b6a6f77a6a1b22d07137cd0c8c469 Mon Sep 17 00:00:00 2001 From: guyelg Date: Wed, 10 Oct 2018 20:54:26 +0300 Subject: [PATCH 0253/2222] fix address in user_config.h --- sonoff/user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 46a98c4e3..d2f89d9b9 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -323,7 +323,7 @@ #define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module #define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module #define USE_DS3231 // Enable use DS3231 external RTC , usefall when you don't have avaliable WIFI. see docs in the source file (+1k2 code) -// #define USE_RTC_ADDR //you can change the addrsss of the DS3231 RTC, default is 0x68, not mandatory fieled +// #define USE_RTC_ADDR 0x68 //you can change the addrsss of the DS3231 RTC, default is 0x68, not mandatory fieled #endif // USE_I2C From 9c77d1d7610e2118927021f09119ac64cb5f88a4 Mon Sep 17 00:00:00 2001 From: guyelg Date: Wed, 10 Oct 2018 21:01:07 +0300 Subject: [PATCH 0254/2222] disable the sensor by default --- sonoff/user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/user_config.h b/sonoff/user_config.h index d2f89d9b9..f37f8dc63 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -322,7 +322,7 @@ #define MTX_ADDRESS6 0x76 // [DisplayAddress6] I2C address of sixth 8x8 matrix module #define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module #define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module - #define USE_DS3231 // Enable use DS3231 external RTC , usefall when you don't have avaliable WIFI. see docs in the source file (+1k2 code) +// #define USE_DS3231 // Enable use DS3231 external RTC , usefall when you don't have avaliable WIFI. see docs in the source file (+1k2 code) // #define USE_RTC_ADDR 0x68 //you can change the addrsss of the DS3231 RTC, default is 0x68, not mandatory fieled #endif // USE_I2C From b3039de1b6b844ff5987e23ebf27ad5a06b6763c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 10 Oct 2018 22:21:44 +0200 Subject: [PATCH 0255/2222] 6.2.1.14 Rewrite Webserver 6.2.1.14 20181010 * Rewrite Webserver page handler for easier extension (thx to Adrian Scillato) --- sonoff/_changelog.ino | 5 +- sonoff/i18n.h | 1 - sonoff/sonoff.h | 2 +- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_webserver.ino | 2003 ++++++++++++++++++++++++++++++++++ sonoff/xdrv_02_mqtt.ino | 903 +++++++++++++++ sonoff/xdrv_07_domoticz.ino | 49 +- sonoff/xdrv_09_timers.ino | 33 +- sonoff/xdrv_11_knx.ino | 18 +- sonoff/xplg_wemohue.ino | 14 + 10 files changed, 3002 insertions(+), 28 deletions(-) create mode 100644 sonoff/xdrv_01_webserver.ino create mode 100644 sonoff/xdrv_02_mqtt.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b2210c830..def41834a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.2.1.13 20181008 +/* 6.2.1.14 20181010 + * Rewrite Webserver page handler for easier extension (thx to Adrian Scillato) + * + * 6.2.1.13 20181008 * Change default Mqtt client library from PubSubClient to non-blocking ArduinoMqtt by Joel Gaehwiler * Add command WebRefresh 1000..10000 to control web page refresh in milliseconds. Default is 2345 * diff --git a/sonoff/i18n.h b/sonoff/i18n.h index ab1f0a1d2..62226f91f 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -539,7 +539,6 @@ const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION; const char S_CONFIGURE_MODULE[] PROGMEM = D_CONFIGURE_MODULE; const char S_CONFIGURE_WIFI[] PROGMEM = D_CONFIGURE_WIFI; const char S_NO_NETWORKS_FOUND[] PROGMEM = D_NO_NETWORKS_FOUND; -const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT; const char S_CONFIGURE_LOGGING[] PROGMEM = D_CONFIGURE_LOGGING; const char S_CONFIGURE_OTHER[] PROGMEM = D_CONFIGURE_OTHER; const char S_SAVE_CONFIGURATION[] PROGMEM = D_SAVE_CONFIGURATION; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 5d41aa18d..5bc744157 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -214,7 +214,7 @@ enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MA enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, - FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM}; + FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_HANDLER}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index eba7ddc21..080c76fa4 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0602010D +#define VERSION 0x0602010E #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino new file mode 100644 index 000000000..50345145f --- /dev/null +++ b/sonoff/xdrv_01_webserver.ino @@ -0,0 +1,2003 @@ +/* + xdrv_01_webserver.ino - webserver for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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_WEBSERVER +/*********************************************************************************************\ + * Web server and WiFi Manager + * + * Enables configuration and reconfiguration of WiFi credentials using a Captive Portal + * Based on source by AlexT (https://github.com/tzapu) +\*********************************************************************************************/ + +#define HTTP_REFRESH_TIME 2345 // milliseconds + +#ifdef USE_RF_FLASH +uint8_t *efm8bb1_update = NULL; +#endif // USE_RF_FLASH + +enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1 }; + +const char HTTP_HEAD[] PROGMEM = + "" + "" + "" + "" + "{h} - {v}" + + "" + + "" + + "" + "" + "
" +#ifdef BE_MINIMAL + "

" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "

" +#endif + "
" +#ifdef LANGUAGE_MODULE_NAME + "

" D_MODULE " {ha

" +#else + "

{ha " D_MODULE "

" +#endif + "

{h}

"; +const char HTTP_SCRIPT_CONSOL[] PROGMEM = + "var sn=0;" // Scroll position + "var id=0;" // Get most of weblog initially + "function l(p){" // Console log and command service + "var c,o,t;" + "clearTimeout(lt);" + "o='';" + "t=eb('t1');" + "if(p==1){" + "c=eb('c1');" + "o='&c1='+encodeURIComponent(c.value);" + "c.value='';" + "t.scrollTop=sn;" + "}" + "if(t.scrollTop>=sn){" // User scrolled back so no updates + "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1) + "x=new XMLHttpRequest();" + "x.onreadystatechange=function(){" + "if(x.readyState==4&&x.status==200){" + "var z,d;" + "d=x.responseXML;" + "id=d.getElementsByTagName('i')[0].childNodes[0].nodeValue;" + "if(d.getElementsByTagName('j')[0].childNodes[0].nodeValue==0){t.value='';}" + "z=d.getElementsByTagName('l')[0].childNodes;" + "if(z.length>0){t.value+=decodeURIComponent(z[0].nodeValue);}" + "t.scrollTop=99999;" + "sn=t.scrollTop;" + "}" + "};" + "x.open('GET','ax?c2='+id+o,true);" + "x.send();" + "}" + "lt=setTimeout(l,{a});" + "return false;" + "}" + ""; +const char HTTP_SCRIPT_MODULE1[] PROGMEM = + "var os;" + "function sk(s,g){" + "var o=os.replace(\"value='\"+s+\"'\",\"selected value='\"+s+\"'\");" + "eb('g'+g).innerHTML=o;" + "}" + "function sl(){" + "var o0=\""; +const char HTTP_SCRIPT_MODULE2[] PROGMEM = + "}1'%d'>%02d %s}2"; // "}1" and "}2" means do not use "}x" in Module name and Sensor name +const char HTTP_SCRIPT_MODULE3[] PROGMEM = + "\";" + "os=o0.replace(/}1/g,\"

" "
"; -const char HTTP_FORM_TIMER2[] PROGMEM = - "type='submit' onclick='st();this.form.submit();'"; void HandleTimerConfiguration() { @@ -710,7 +710,6 @@ void HandleTimerConfiguration() page.replace(F("299"), String(100 + (strlen(D_SUNSET) *12))); // Fix string length to keep radios centered #endif // USE_SUNRISE page += FPSTR(HTTP_FORM_END); - page.replace(F("type='submit'"), FPSTR(HTTP_FORM_TIMER2)); page += F(""); // Init elements and select first tab/button page += FPSTR(HTTP_BTN_CONF); ShowPage(page); From 98c7e467f86d22653f7a25916ad90134b3701d48 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sun, 4 Nov 2018 22:14:05 +0100 Subject: [PATCH 0432/2222] Update de-DE.h Fixing some minor errors --- sonoff/language/de-DE.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index d024562a6..9c2f7c24e 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -94,7 +94,7 @@ #define D_FALSE "falsch" #define D_FILE "Datei" #define D_FREE_MEMORY "Freier Arbeitsspeicher" -#define D_FREQUENCY "Frequency" +#define D_FREQUENCY "Frequenz" #define D_GAS "Gas" #define D_GATEWAY "Gateway" #define D_GROUP "Gruppe" @@ -174,7 +174,7 @@ #define D_UV_POWER "UV Intensität" #define D_VERSION "Version" #define D_VOLTAGE "Spannung" -#define D_WEIGHT "Weight" +#define D_WEIGHT "Gewicht" #define D_WARMLIGHT "warm" #define D_WEB_SERVER "Web-Server" @@ -436,7 +436,7 @@ #define D_TIMEOUT_WAITING_FOR "Timeout während Warten auf" #define D_START_SIGNAL_LOW "Startausschlag niedrig" #define D_START_SIGNAL_HIGH "Startausschlag hoch" -#define D_PULSE "pulse" +#define D_PULSE "Puls" #define D_CHECKSUM_FAILURE "Checksum-Fehler" // xsns_07_sht1x.ino @@ -537,7 +537,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From b5f20dd643dd26498ed22e201d32adbaf096f677 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 4 Nov 2018 23:43:34 +0100 Subject: [PATCH 0433/2222] Correctly announce non RGBWW light --- sonoff/xplg_wemohue.ino | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 8bd5e529c..7f70fd739 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -461,15 +461,19 @@ const char HUE_DESCRIPTION_XML[] PROGMEM = "\r\n"; const char HUE_LIGHTS_STATUS_JSON[] PROGMEM = "{\"on\":{state}," - "\"bri\":{b}," - "\"hue\":{h}," - "\"sat\":{s}," - "\"xy\":[0.5, 0.5]," - "\"ct\":{t}," "\"alert\":\"none\"," "\"effect\":\"none\"," - "\"colormode\":\"{m}\"," - "\"reachable\":true}"; + "\"reachable\":true"; +const char HUE_LIGHTS_STATUS_JSON_DIM[] PROGMEM = + ",\"bri\":{b}"; +const char HUE_LIGHTS_STATUS_JSON_RGB[] PROGMEM = + ",\"hue\":{h}," + "\"sat\":{s}," + "\"xy\":[0.5, 0.5]"; +const char HUE_LIGHTS_STATUS_JSON_CT[] PROGMEM = + ",\"ct\":{t}"; +const char HUE_LIGHTS_STATUS_JSON_CM[] PROGMEM = + ",\"colormode\":\"{m}\""; const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = ",\"type\":\"Extended color light\"," "\"name\":\"{j1\"," @@ -576,6 +580,19 @@ void HueLightStatus1(byte device, String *response) ct = LightGetColorTemp(); } *response += FPSTR(HUE_LIGHTS_STATUS_JSON); + //The light can be dimmed + if (light_subtype >= LST_SINGLE) *response += FPSTR(HUE_LIGHTS_STATUS_JSON_DIM); + + //The light has adjustabe color temperature + if (light_subtype == LST_COLDWARM || light_subtype == LST_RGBWC) *response += FPSTR(HUE_LIGHTS_STATUS_JSON_CT); + + //The light has RGB + if (light_subtype >= LST_RGB) *response += FPSTR(HUE_LIGHTS_STATUS_JSON_RGB); + + //The light supports colormode + if (light_subtype >= LST_COLDWARM) *response += FPSTR(HUE_LIGHTS_STATUS_JSON_CM); + + *response += "}"; response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); response->replace("{h}", String((uint16_t)(65535.0f * hue))); response->replace("{s}", String((uint8_t)(254.0f * sat))); From e9050be550e84945fb63020762a1444d188cf6dc Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Mon, 5 Nov 2018 07:13:16 +0100 Subject: [PATCH 0434/2222] TasmotaSerial: fix hardware-serial --- lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp index d9fc29e6f..42253ade6 100644 --- a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp @@ -87,7 +87,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fa m_rx_pin = receive_pin; m_tx_pin = transmit_pin; m_in_pos = m_out_pos = 0; - if (hardware_fallback && (((1 == m_rx_pin) && (3 == m_tx_pin)) || ((3 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (1 == m_tx_pin)))) { + if (hardware_fallback && (((3 == m_rx_pin) && (1 == m_tx_pin)) || ((3 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (1 == m_tx_pin)))) { m_hardserial = 1; } else { if (m_rx_pin > -1) { From d6983d268b9a0c173d1e54a0e26d69c601d01dbe Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Mon, 5 Nov 2018 07:34:12 +0100 Subject: [PATCH 0435/2222] TasmotaSerial: use Serial.swap to map UART0 to GPIO13 and GPIO15 --- lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp | 7 +++++++ lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h | 1 + 2 files changed, 8 insertions(+) diff --git a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp index 42253ade6..0b5db85bb 100644 --- a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp @@ -80,6 +80,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fa { m_valid = false; m_hardserial = 0; + m_hardswap = 0; m_stop_bits = 1; if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) { return; @@ -89,6 +90,9 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fa m_in_pos = m_out_pos = 0; if (hardware_fallback && (((3 == m_rx_pin) && (1 == m_tx_pin)) || ((3 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (1 == m_tx_pin)))) { m_hardserial = 1; + } else if (hardware_fallback && (((13 == m_rx_pin) && (15 == m_tx_pin)) || ((13 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (15 == m_tx_pin)))) { + m_hardserial = 1; + m_hardswap = 1; } else { if (m_rx_pin > -1) { m_buffer = (uint8_t*)malloc(TM_SERIAL_BUFFER_SIZE); @@ -134,6 +138,9 @@ bool TasmotaSerial::begin(long speed, int stop_bits) { } else { Serial.begin(speed, SERIAL_8N1); } + if(m_hardswap) { + Serial.swap(); + } } else { // Use getCycleCount() loop to get as exact timing as possible m_bit_time = ESP.getCpuFreqMHz() *1000000 /speed; diff --git a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h index e40c34ee8..3136a8e46 100644 --- a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h +++ b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h @@ -62,6 +62,7 @@ class TasmotaSerial : public Stream { // Member variables bool m_valid; bool m_hardserial; + bool m_hardswap; bool m_high_speed; int m_rx_pin; int m_tx_pin; From cf66923e52524572bd588a216caf9fef9919c69f Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Mon, 5 Nov 2018 09:09:53 +0100 Subject: [PATCH 0436/2222] add/fix v6.3.0.2 config changes - upset settings: reduce to diffs --- tools/decode-config.py | 509 ++++++++++++----------------------------- 1 file changed, 147 insertions(+), 362 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index dfb7b1f7c..1683a6a2f 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.0.0003' +VER = '2.0.0004' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -309,26 +309,26 @@ Setting_5_10_0 = { 'version': (' Date: Mon, 5 Nov 2018 10:26:06 +0100 Subject: [PATCH 0437/2222] 6.3.0.3 Swap Tx/Rx hardware serial 6.3.0.3 20181105 * Fix hardware serial pin configuration. To keep using hardware serial swap current Rx/Tx pin configuration only (#4280) --- sonoff/_changelog.ino | 5 ++++- sonoff/sonoff_version.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 48f133a61..d53687938 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.3.0.2 20181101 +/* 6.3.0.3 20181105 + * Fix hardware serial pin configuration. To keep using hardware serial swap current Rx/Tx pin configuration only (#4280) + * + * 6.3.0.2 20181101 * Add minutes to commands Timezone to allow all possible world timezones * Add command SetOption24 0/1 to select pressure unit as hPa or mmHg (#4241) * diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 9e1a5d4fa..733bad937 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06030002 +#define VERSION 0x06030003 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" From c9cf375c6ca0e25278043e08eee01234585d76b5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 5 Nov 2018 17:27:02 +0100 Subject: [PATCH 0438/2222] Add checks for GPIO selections Add more strict checks for GPIO selections --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 31 +++++++---- sonoff/sonoff_template.h | 50 ++++++++++++++++- sonoff/support.ino | 101 +++++++---------------------------- sonoff/xdrv_01_webserver.ino | 2 +- 5 files changed, 92 insertions(+), 93 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index d53687938..0750b4d06 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.3.0.3 20181105 * Fix hardware serial pin configuration. To keep using hardware serial swap current Rx/Tx pin configuration only (#4280) + * Add more strict checks for GPIO selections * * 6.3.0.2 20181101 * Add minutes to commands Timezone to allow all possible world timezones diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 7a3948382..09e029a15 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -869,13 +869,20 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) mytmplt cmodule; memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); if ((GPIO_USER == ValidGPIO(index, cmodule.gp.io[index])) && (payload >= 0) && (payload < GPIO_SENSOR_END)) { - for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if ((GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) && (Settings.my_gp.io[i] == payload)) { - Settings.my_gp.io[i] = 0; - } + bool present = false; + for (byte i = 0; i < sizeof(kGpioNiceList); i++) { + uint8_t midx = pgm_read_byte(kGpioNiceList + i); + if (midx == payload) { present = true; } + } + if (present) { + for (byte i = 0; i < MAX_GPIO_PIN; i++) { + if ((GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) && (Settings.my_gp.io[i] == payload)) { + Settings.my_gp.io[i] = 0; + } + } + Settings.my_gp.io[index] = payload; + restart_flag = 2; } - Settings.my_gp.io[index] = payload; - restart_flag = 2; } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); for (byte i = 0; i < MAX_GPIO_PIN; i++) { @@ -895,16 +902,19 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) else if (CMND_GPIOS == command_code) { mytmplt cmodule; memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); - for (byte i = 0; i < GPIO_SENSOR_END; i++) { - if (!GetUsedInModule(i, cmodule.gp.io)) { + uint8_t midx; + for (byte i = 0; i < sizeof(kGpioNiceList); i++) { + midx = pgm_read_byte(kGpioNiceList + i); + if (!GetUsedInModule(midx, cmodule.gp.io)) { + if (!jsflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_GPIOS "%d\":["), lines); } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); } jsflg = 1; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, i, GetTextIndexed(stemp1, sizeof(stemp1), i, kSensorNames)); - if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == GPIO_SENSOR_END -1)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)); + if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]}"), mqtt_data); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); jsflg = 0; @@ -912,6 +922,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } } } + mqtt_data[0] = '\0'; } else if ((CMND_PWM == command_code) && pwm_present && (index > 0) && (index <= MAX_PWMS)) { diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 036e2400d..eb4d910d0 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -267,7 +267,7 @@ typedef struct MYTMPLT { myio gp; } mytmplt; -const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = { +const uint8_t kGpioNiceList[] PROGMEM = { GPIO_NONE, // Not used GPIO_KEY1, // Buttons GPIO_KEY1_NP, @@ -335,48 +335,96 @@ const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = { GPIO_CNTR3_NP, GPIO_CNTR4, GPIO_CNTR4_NP, +#ifdef USE_I2C GPIO_I2C_SCL, // I2C SCL GPIO_I2C_SDA, // I2C SDA +#endif +#ifdef USE_SPI GPIO_SPI_CS, // SPI Chip Select GPIO_SPI_DC, // SPI Data Direction +#endif +#ifdef USE_DISPLAY GPIO_BACKLIGHT, // Display backlight control +#endif GPIO_DHT11, // DHT11 GPIO_DHT22, // DHT21, DHT22, AM2301, AM2302, AM2321 GPIO_SI7021, // iTead SI7021 GPIO_DSB, // Single wire DS18B20 or DS18S20 +#ifdef USE_WS2812 GPIO_WS2812, // WS2812 Led string +#endif +#ifdef USE_IR_REMOTE GPIO_IRSEND, // IR remote +#ifdef USE_IR_RECEIVE GPIO_IRRECV, // IR receiver +#endif +#endif +#ifdef USE_RC_SWITCH GPIO_RFSEND, // RF transmitter GPIO_RFRECV, // RF receiver +#endif +#ifdef USE_SR04 GPIO_SR04_TRIG, // SR04 Trigger pin GPIO_SR04_ECHO, // SR04 Echo pin +#endif +#ifdef USE_TM1638 GPIO_TM16CLK, // TM1638 Clock GPIO_TM16DIO, // TM1638 Data I/O GPIO_TM16STB, // TM1638 Strobe +#endif +#ifdef USE_HX711 GPIO_HX711_SCK, // HX711 Load Cell clock GPIO_HX711_DAT, // HX711 Load Cell data +#endif +#ifdef USE_SERIAL_BRIDGE GPIO_SBR_TX, // Serial Bridge Serial interface GPIO_SBR_RX, // Serial Bridge Serial interface +#endif +#ifdef USE_MHZ19 GPIO_MHZ_TXD, // MH-Z19 Serial interface GPIO_MHZ_RXD, // MH-Z19 Serial interface +#endif +#ifdef USE_SENSEAIR GPIO_SAIR_TX, // SenseAir Serial interface GPIO_SAIR_RX, // SenseAir Serial interface +#endif +#ifdef USE_NOVA_SDS GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface +#endif +#if defined(USE_PZEM004T) || defined(USE_PZEM_AC) || defined(USE_PZEM_DC) GPIO_PZEM0XX_TX, // PZEM0XX Serial interface +#endif +#ifdef USE_PZEM004T GPIO_PZEM004_RX, // PZEM004T Serial interface +#endif +#ifdef USE_PZEM_AC GPIO_PZEM016_RX, // PZEM-014,016 Serial Modbus interface +#endif +#ifdef USE_PZEM_DC GPIO_PZEM017_RX, // PZEM-003,017 Serial Modbus interface +#endif +#ifdef USE_SDM120 GPIO_SDM120_TX, // SDM120 Serial interface GPIO_SDM120_RX, // SDM120 Serial interface +#endif +#ifdef USE_SDM630 GPIO_SDM630_TX, // SDM630 Serial interface GPIO_SDM630_RX, // SDM630 Serial interface +#endif +#ifdef USE_PMS5003 GPIO_PMS5003, // Plantower PMS5003 Serial interface +#endif +#ifdef USE_TX20_WIND_SENSOR GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin +#endif +#ifdef USE_MP3_PLAYER GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface +#endif +#ifdef USE_TUYA_DIMMER GPIO_TUYA_TX, // Tuya Serial interface GPIO_TUYA_RX // Tuya Serial interface +#endif }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { diff --git a/sonoff/support.ino b/sonoff/support.ino index ba7ae0d6e..c2856a782 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -646,89 +646,20 @@ boolean GetUsedInModule(byte val, uint8_t *arr) int offset = 0; if (!val) { return false; } // None -#ifndef USE_I2C - if (GPIO_I2C_SCL == val) { return true; } - if (GPIO_I2C_SDA == val) { return true; } -#endif -#ifndef USE_WS2812 - if (GPIO_WS2812 == val) { return true; } -#endif -#ifndef USE_IR_REMOTE - if (GPIO_IRSEND == val) { return true; } -#ifndef USE_IR_RECEIVE - if (GPIO_IRRECV == val) { return true; } -#endif -#endif -#ifndef USE_MHZ19 - if (GPIO_MHZ_TXD == val) { return true; } - if (GPIO_MHZ_RXD == val) { return true; } -#endif - int pzem = 3; -#ifndef USE_PZEM004T - pzem--; - if (GPIO_PZEM004_RX == val) { return true; } -#endif -#ifndef USE_PZEM_AC - pzem--; - if (GPIO_PZEM016_RX == val) { return true; } -#endif -#ifndef USE_PZEM_DC - pzem--; - if (GPIO_PZEM017_RX == val) { return true; } -#endif - if (!pzem && (GPIO_PZEM0XX_TX == val)) { return true; } + if ((val >= GPIO_KEY1) && (val < GPIO_KEY1 + MAX_KEYS)) { + offset = (GPIO_KEY1_NP - GPIO_KEY1); + } + if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) { + offset = -(GPIO_KEY1_NP - GPIO_KEY1); + } -#ifndef USE_SENSEAIR - if (GPIO_SAIR_TX == val) { return true; } - if (GPIO_SAIR_RX == val) { return true; } -#endif -#ifndef USE_SPI - if (GPIO_SPI_CS == val) { return true; } - if (GPIO_SPI_DC == val) { return true; } -#endif -#ifndef USE_DISPLAY - if (GPIO_BACKLIGHT == val) { return true; } -#endif -#ifndef USE_PMS5003 - if (GPIO_PMS5003 == val) { return true; } -#endif -#ifndef USE_NOVA_SDS - if (GPIO_SDS0X1_TX == val) { return true; } - if (GPIO_SDS0X1_RX == val) { return true; } -#endif -#ifndef USE_SERIAL_BRIDGE - if (GPIO_SBR_TX == val) { return true; } - if (GPIO_SBR_RX == val) { return true; } -#endif -#ifndef USE_SR04 - if (GPIO_SR04_TRIG == val) { return true; } - if (GPIO_SR04_ECHO == val) { return true; } -#endif -#ifndef USE_SDM120 - if (GPIO_SDM120_TX == val) { return true; } - if (GPIO_SDM120_RX == val) { return true; } -#endif -#ifndef USE_SDM630 - if (GPIO_SDM630_TX == val) { return true; } - if (GPIO_SDM630_RX == val) { return true; } -#endif -#ifndef USE_TM1638 - if (GPIO_TM16CLK == val) { return true; } - if (GPIO_TM16DIO == val) { return true; } - if (GPIO_TM16STB == val) { return true; } -#endif -#ifndef USE_HX711 - if (GPIO_HX711_SCK == val) { return true; } - if (GPIO_HX711_DAT == val) { return true; } -#endif -#ifndef USE_TX20_WIND_SENSOR - if (GPIO_TX20_TXD_BLACK == val) { return true; } -#endif -#ifndef USE_RC_SWITCH - if (GPIO_RFSEND == val) { return true; } - if (GPIO_RFRECV == val) { return true; } -#endif + if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) { + offset = (GPIO_SWT1_NP - GPIO_SWT1); + } + if ((val >= GPIO_SWT1_NP) && (val < GPIO_SWT1_NP + MAX_SWITCHES)) { + offset = -(GPIO_SWT1_NP - GPIO_SWT1); + } if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { offset = (GPIO_REL1_INV - GPIO_REL1); @@ -750,6 +681,14 @@ boolean GetUsedInModule(byte val, uint8_t *arr) if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) { offset = -(GPIO_PWM1_INV - GPIO_PWM1); } + + if ((val >= GPIO_CNTR1) && (val < GPIO_CNTR1 + MAX_COUNTERS)) { + offset = (GPIO_CNTR1_NP - GPIO_CNTR1); + } + if ((val >= GPIO_CNTR1_NP) && (val < GPIO_CNTR1_NP + MAX_COUNTERS)) { + offset = -(GPIO_CNTR1_NP - GPIO_CNTR1); + } + for (byte i = 0; i < MAX_GPIO_PIN; i++) { if (arr[i] == val) { return true; } if (arr[i] == val + offset) { return true; } diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 8f7bcdefb..e7327b769 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -773,7 +773,7 @@ void HandleModuleConfiguration() mytmplt cmodule; memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); - for (byte j = 0; j < GPIO_SENSOR_END; j++) { + for (byte j = 0; j < sizeof(kGpioNiceList); j++) { midx = pgm_read_byte(kGpioNiceList + j); if (!GetUsedInModule(midx, cmodule.gp.io)) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, midx, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames)); From aa148f67a3193898cc6d5b2aaeb33f95754d9048 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Tue, 6 Nov 2018 05:29:30 +0100 Subject: [PATCH 0439/2222] tuya: fix SetOption20 for Oittm/Moes --- sonoff/xdrv_16_tuyadimmer.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index bf8213da2..a1356784d 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -207,7 +207,7 @@ void TuyaPacketProcess() } tuya_new_dim = round(tuya_buffer[13] * (100. / 255.)); - if((power) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 2)) { + if((power || bitRead(Settings.flag.data, 20)) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 1)) { snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), tuya_new_dim ); From 49acf4a7d31ffc001737c5d63d4557e112f3d6b5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 6 Nov 2018 11:27:19 +0100 Subject: [PATCH 0440/2222] Add optional hardware serial * Add optional hardware serial when GPIO13(Rx) and GPIO15(Tx) are selected removing hardware serial from GPIO01(Tx) and GPIO03(Rx) (#4288) * Bump TasmotaSerial version from 2.1.0 to 2.2.0 --- .../README.md | 0 .../examples/swsertest/swsertest.ino | 0 .../keywords.txt | 0 .../library.json | 2 +- .../library.properties | 2 +- .../src/TasmotaSerial.cpp | 8 +++++--- .../src/TasmotaSerial.h | 0 sonoff/_changelog.ino | 2 ++ 8 files changed, 9 insertions(+), 5 deletions(-) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/README.md (100%) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/examples/swsertest/swsertest.ino (100%) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/keywords.txt (100%) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/library.json (94%) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/library.properties (94%) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/src/TasmotaSerial.cpp (97%) rename lib/{TasmotaSerial-2.1.0 => TasmotaSerial-2.2.0}/src/TasmotaSerial.h (100%) diff --git a/lib/TasmotaSerial-2.1.0/README.md b/lib/TasmotaSerial-2.2.0/README.md similarity index 100% rename from lib/TasmotaSerial-2.1.0/README.md rename to lib/TasmotaSerial-2.2.0/README.md diff --git a/lib/TasmotaSerial-2.1.0/examples/swsertest/swsertest.ino b/lib/TasmotaSerial-2.2.0/examples/swsertest/swsertest.ino similarity index 100% rename from lib/TasmotaSerial-2.1.0/examples/swsertest/swsertest.ino rename to lib/TasmotaSerial-2.2.0/examples/swsertest/swsertest.ino diff --git a/lib/TasmotaSerial-2.1.0/keywords.txt b/lib/TasmotaSerial-2.2.0/keywords.txt similarity index 100% rename from lib/TasmotaSerial-2.1.0/keywords.txt rename to lib/TasmotaSerial-2.2.0/keywords.txt diff --git a/lib/TasmotaSerial-2.1.0/library.json b/lib/TasmotaSerial-2.2.0/library.json similarity index 94% rename from lib/TasmotaSerial-2.1.0/library.json rename to lib/TasmotaSerial-2.2.0/library.json index 59d06ad5f..23a2ddab9 100644 --- a/lib/TasmotaSerial-2.1.0/library.json +++ b/lib/TasmotaSerial-2.2.0/library.json @@ -1,6 +1,6 @@ { "name": "TasmotaSerial", - "version": "2.1.0", + "version": "2.2.0", "keywords": [ "serial", "io", "TasmotaSerial" ], diff --git a/lib/TasmotaSerial-2.1.0/library.properties b/lib/TasmotaSerial-2.2.0/library.properties similarity index 94% rename from lib/TasmotaSerial-2.1.0/library.properties rename to lib/TasmotaSerial-2.2.0/library.properties index 93f4a1d39..54c79e218 100644 --- a/lib/TasmotaSerial-2.1.0/library.properties +++ b/lib/TasmotaSerial-2.2.0/library.properties @@ -1,5 +1,5 @@ name=TasmotaSerial -version=2.1.0 +version=2.2.0 author=Theo Arends maintainer=Theo Arends sentence=Implementation of software serial with hardware serial fallback for ESP8266. diff --git a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp similarity index 97% rename from lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp rename to lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp index 0b5db85bb..7e6ddf72f 100644 --- a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp @@ -90,10 +90,12 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fa m_in_pos = m_out_pos = 0; if (hardware_fallback && (((3 == m_rx_pin) && (1 == m_tx_pin)) || ((3 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (1 == m_tx_pin)))) { m_hardserial = 1; - } else if (hardware_fallback && (((13 == m_rx_pin) && (15 == m_tx_pin)) || ((13 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (15 == m_tx_pin)))) { + } + else if (hardware_fallback && (((13 == m_rx_pin) && (15 == m_tx_pin)) || ((13 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (15 == m_tx_pin)))) { m_hardserial = 1; m_hardswap = 1; - } else { + } + else { if (m_rx_pin > -1) { m_buffer = (uint8_t*)malloc(TM_SERIAL_BUFFER_SIZE); if (m_buffer == NULL) return; @@ -138,7 +140,7 @@ bool TasmotaSerial::begin(long speed, int stop_bits) { } else { Serial.begin(speed, SERIAL_8N1); } - if(m_hardswap) { + if (m_hardswap) { Serial.swap(); } } else { diff --git a/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h b/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h similarity index 100% rename from lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h rename to lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0750b4d06..58e084d34 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,8 @@ /* 6.3.0.3 20181105 * Fix hardware serial pin configuration. To keep using hardware serial swap current Rx/Tx pin configuration only (#4280) * Add more strict checks for GPIO selections + * Add optional hardware serial when GPIO13(Rx) and GPIO15(Tx) are selected removing hardware serial from GPIO01(Tx) and GPIO03(Rx) (#4288) + * Bump TasmotaSerial version from 2.1.0 to 2.2.0 * * 6.3.0.2 20181101 * Add minutes to commands Timezone to allow all possible world timezones From 28c1eed302544054f36585d56685dd4cd9a3c1f2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 6 Nov 2018 11:48:04 +0100 Subject: [PATCH 0441/2222] Fix baudrate when module changed Fix baudrate when module changed --- sonoff/sonoff.ino | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 09e029a15..3ef470de4 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2394,10 +2394,13 @@ void GpioInit() uint8_t key_no_pullup = 0; mytmplt def_module; - if (!Settings.module || (Settings.module >= MAXMODULE)) { + if (Settings.module >= MAXMODULE) { Settings.module = MODULE; Settings.last_module = MODULE; } + if (Settings.module != Settings.last_module) { + baudrate = APP_BAUDRATE; + } memcpy_P(&def_module, &kModules[Settings.module], sizeof(def_module)); strlcpy(my_module.name, def_module.name, sizeof(my_module.name)); @@ -2646,7 +2649,7 @@ void setup() } if (RtcReboot.fast_reboot_count > 4) { // Restarted 5 times Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic - Settings.last_module = SONOFF_BASIC; +// Settings.last_module = SONOFF_BASIC; for (byte i = 0; i < MAX_GPIO_PIN; i++) { Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors } From a0c38ad397e4c94fd96899bb813fccaa18ef9983 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 6 Nov 2018 11:35:06 -0300 Subject: [PATCH 0442/2222] Reverting PR #4279 that brokes Alexa support --- sonoff/xplg_wemohue.ino | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 7f70fd739..dbdf3d27b 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -1,18 +1,14 @@ /* xplg_wemohue.ino - wemo and hue support for Sonoff-Tasmota - Copyright (C) 2018 Heiko Krupp 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 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 . */ @@ -461,19 +457,15 @@ const char HUE_DESCRIPTION_XML[] PROGMEM = "\r\n"; const char HUE_LIGHTS_STATUS_JSON[] PROGMEM = "{\"on\":{state}," + "\"bri\":{b}," + "\"hue\":{h}," + "\"sat\":{s}," + "\"xy\":[0.5, 0.5]," + "\"ct\":{t}," "\"alert\":\"none\"," "\"effect\":\"none\"," - "\"reachable\":true"; -const char HUE_LIGHTS_STATUS_JSON_DIM[] PROGMEM = - ",\"bri\":{b}"; -const char HUE_LIGHTS_STATUS_JSON_RGB[] PROGMEM = - ",\"hue\":{h}," - "\"sat\":{s}," - "\"xy\":[0.5, 0.5]"; -const char HUE_LIGHTS_STATUS_JSON_CT[] PROGMEM = - ",\"ct\":{t}"; -const char HUE_LIGHTS_STATUS_JSON_CM[] PROGMEM = - ",\"colormode\":\"{m}\""; + "\"colormode\":\"{m}\"," + "\"reachable\":true}"; const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = ",\"type\":\"Extended color light\"," "\"name\":\"{j1\"," @@ -580,19 +572,6 @@ void HueLightStatus1(byte device, String *response) ct = LightGetColorTemp(); } *response += FPSTR(HUE_LIGHTS_STATUS_JSON); - //The light can be dimmed - if (light_subtype >= LST_SINGLE) *response += FPSTR(HUE_LIGHTS_STATUS_JSON_DIM); - - //The light has adjustabe color temperature - if (light_subtype == LST_COLDWARM || light_subtype == LST_RGBWC) *response += FPSTR(HUE_LIGHTS_STATUS_JSON_CT); - - //The light has RGB - if (light_subtype >= LST_RGB) *response += FPSTR(HUE_LIGHTS_STATUS_JSON_RGB); - - //The light supports colormode - if (light_subtype >= LST_COLDWARM) *response += FPSTR(HUE_LIGHTS_STATUS_JSON_CM); - - *response += "}"; response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); response->replace("{h}", String((uint16_t)(65535.0f * hue))); response->replace("{s}", String((uint8_t)(254.0f * sat))); From 15148f290da4f616033048e6748c6a6fd20a289c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 6 Nov 2018 17:33:51 +0100 Subject: [PATCH 0443/2222] 6.3.0.4 Add SetSensorXX 6.3.0.4 20181106 * Add command SetSensorXX 0/1 to disable/re-enable compiled xsns_XX_sensor.ino driver --- sonoff/_changelog.ino | 5 +- sonoff/i18n.h | 1 + sonoff/settings.h | 6 +- sonoff/settings.ino | 5 + sonoff/sonoff.h | 4 + sonoff/sonoff.ino | 11 +- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 75 -------- sonoff/xdrv_03_energy.ino | 9 +- sonoff/xplg_wemohue.ino | 4 + sonoff/xsns_01_counter.ino | 4 +- sonoff/xsns_02_analog.ino | 94 +++++++++ sonoff/xsns_04_snfsc.ino | 4 +- sonoff/xsns_05_ds18b20.ino | 4 +- sonoff/xsns_05_ds18x20.ino | 5 +- sonoff/xsns_05_ds18x20_legacy.ino | 4 +- sonoff/xsns_06_dht.ino | 4 +- sonoff/xsns_07_sht1x.ino | 4 +- sonoff/xsns_08_htu21.ino | 4 +- sonoff/xsns_09_bmp.ino | 4 +- sonoff/xsns_10_bh1750.ino | 4 +- sonoff/xsns_11_veml6070.ino | 4 +- sonoff/xsns_12_ads1115.ino | 4 +- sonoff/xsns_12_ads1115_i2cdev.ino | 4 +- sonoff/xsns_13_ina219.ino | 5 +- sonoff/xsns_14_sht3x.ino | 4 +- sonoff/xsns_15_mhz19.ino | 21 +- sonoff/xsns_16_tsl2561.ino | 4 +- sonoff/xsns_17_senseair.ino | 4 +- sonoff/xsns_18_pms5003.ino | 4 +- sonoff/xsns_19_mgs.ino | 4 +- sonoff/xsns_20_novasds.ino | 6 +- sonoff/xsns_21_sgp30.ino | 4 +- sonoff/xsns_22_sr04.ino | 4 +- sonoff/xsns_23_sdm120.ino | 4 +- sonoff/xsns_24_si1145.ino | 8 +- sonoff/xsns_25_sdm630.ino | 4 +- sonoff/xsns_26_lm75ad.ino | 4 +- sonoff/xsns_27_apds9960.ino | 5 +- sonoff/xsns_28_tm1638.ino | 4 +- sonoff/xsns_29_mcp230xx.ino | 1 - sonoff/xsns_30_mpr121.ino | 12 +- sonoff/xsns_31_ccs811.ino | 4 +- sonoff/xsns_32_mpu6050.ino | 10 +- sonoff/xsns_33_ds3231.ino | 6 +- sonoff/xsns_35_tx20.ino | 4 +- sonoff/xsns_interface.ino | 305 ++++++++++++++++++++++++++++-- 47 files changed, 508 insertions(+), 192 deletions(-) create mode 100644 sonoff/xsns_02_analog.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 58e084d34..08b5942e8 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.3.0.3 20181105 +/* 6.3.0.4 20181106 + * Add command SetSensorXX 0/1 to disable/re-enable compiled xsns_XX_sensor.ino driver + * + * 6.3.0.3 20181105 * Fix hardware serial pin configuration. To keep using hardware serial swap current Rx/Tx pin configuration only (#4280) * Add more strict checks for GPIO selections * Add optional hardware serial when GPIO13(Rx) and GPIO15(Tx) are selected removing hardware serial from GPIO01(Tx) and GPIO03(Rx) (#4288) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 587987c4d..73e1d0be2 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -183,6 +183,7 @@ #define D_CMND_DRIVER "Driver" #define D_CMND_SAVEDATA "SaveData" #define D_CMND_SETOPTION "SetOption" +#define D_CMND_SETSENSOR "SetSensor" #define D_CMND_TEMPERATURE_RESOLUTION "TempRes" #define D_CMND_HUMIDITY_RESOLUTION "HumRes" #define D_CMND_PRESSURE_RESOLUTION "PressRes" diff --git a/sonoff/settings.h b/sonoff/settings.h index 677a02bf3..032ea530d 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -320,8 +320,12 @@ struct SYSCFG { uint16_t mcp230xx_int_timer; // 718 uint8_t rgbwwTable[5]; // 71A - byte free_71F[149]; // 71F + byte free_71F[109]; // 71F + uint32_t monitors; // 78C + uint32_t displays; // 790 + uint32_t drivers[4]; // 794 + uint32_t sensors[4]; // 7A4 uint32_t energy_kWhtotal_time; // 7B4 unsigned long weight_item; // 7B8 Weight of one item in gram * 10 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 072cabf2f..88c6838a3 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -635,6 +635,8 @@ void SettingsDefaultSet2() for (byte j = 0; j < 5; j++) { Settings.rgbwwTable[j] = 255; } + + memset(&Settings.monitors, 0xFF, 40); // Enable all possible monitors, displays, drivers and sensors } /********************************************************************************************/ @@ -846,6 +848,9 @@ void SettingsDelta() if (Settings.version < 0x06030002) { Settings.timezone_minutes = 0; } + if (Settings.version < 0x06030004) { + memset(&Settings.monitors, 0xFF, 40); // Enable all possible monitors, displays, drivers and sensors + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index a7cb1ce9a..a0ad03c13 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -50,6 +50,10 @@ typedef unsigned long power_t; // Power (Relay) type #define MAX_DOMOTICZ_SNS_IDX 12 // Max number of Domoticz sensors indices #define MAX_KNX_GA 10 // Max number of KNX Group Addresses to read that can be set #define MAX_KNX_CB 10 // Max number of KNX Group Addresses to write that can be set +#define MAX_XNRG_DRIVERS 32 // Max number of allowed energy drivers +#define MAX_XDSP_DRIVERS 32 // Max number of allowed display drivers +#define MAX_XDRV_DRIVERS 100 // Max number of allowed driver drivers +#define MAX_XSNS_DRIVERS 100 // Max number of allowed sensor drivers #define MAX_RULE_MEMS 5 // Max number of saved vars #define MAX_RULE_SETS 3 // Max number of rule sets of size 512 characters #define MAX_RULE_SIZE 512 // Max number of characters in rules diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 3ef470de4..42a541162 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -81,7 +81,7 @@ enum TasmotaCommands { CMND_MODULE, CMND_MODULES, CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE, CMND_COUNTERDEBOUNCE, CMND_BUTTONDEBOUNCE, CMND_SWITCHDEBOUNCE, 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_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_SETSENSOR, CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_TIMESTD, CMND_TIMEDST, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER, CMND_DRIVER }; const char kTasmotaCommands[] PROGMEM = @@ -91,7 +91,7 @@ const char kTasmotaCommands[] PROGMEM = 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_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" 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_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_SETSENSOR "|" D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER "|" D_CMND_DRIVER; @@ -777,6 +777,13 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, (2 == ptype) ? stemp1 : (1 == ptype) ? GetStateText(bitRead(Settings.flag3.data, pindex)) : GetStateText(bitRead(Settings.flag.data, pindex))); } } + else if ((CMND_SETSENSOR == command_code) && (index < MAX_XSNS_DRIVERS)) { + if ((payload >= 0) && XsnsPresent(index)) { + bitWrite(Settings.sensors[index / 32], index % 32, payload &1); + if (1 == payload) { restart_flag = 2; } // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, XsnsGetSensors().c_str()); + } else if (CMND_TEMPERATURE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.temperature_resolution = payload; diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 733bad937..7bb3242ae 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06030003 +#define VERSION 0x06030004 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index c2856a782..bbc81b1a3 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -2221,81 +2221,6 @@ void RtcInit() TickerRtc.attach(1, RtcSecond); } -#ifndef USE_ADC_VCC -/*********************************************************************************************\ - * ADC support -\*********************************************************************************************/ - -uint16_t adc_last_value = 0; - -uint16_t AdcRead() -{ - uint16_t analog = 0; - for (byte i = 0; i < 32; i++) { - analog += analogRead(A0); - delay(1); - } - analog >>= 5; - return analog; -} - -#ifdef USE_RULES -void AdcEvery250ms() -{ - uint16_t new_value = AdcRead(); - if ((new_value < adc_last_value -10) || (new_value > adc_last_value +10)) { - adc_last_value = new_value; - uint16_t value = adc_last_value / 10; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); - XdrvRulesProcess(); - } -} -#endif // USE_RULES - -void AdcShow(boolean json) -{ - uint16_t analog = AdcRead(); - - if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ANALOG\":{\"A0\":%d}"), mqtt_data, analog); -#ifdef USE_WEBSERVER - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "", 0, analog); -#endif // USE_WEBSERVER - } -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -#define XSNS_02 - -boolean Xsns02(byte function) -{ - boolean result = false; - - if (pin[GPIO_ADC0] < 99) { - switch (function) { -#ifdef USE_RULES - case FUNC_EVERY_250_MSECOND: - AdcEvery250ms(); - break; -#endif // USE_RULES - case FUNC_JSON_APPEND: - AdcShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: - AdcShow(0); - break; -#endif // USE_WEBSERVER - } - } - return result; -} -#endif // USE_ADC_VCC - /*********************************************************************************************\ * Syslog * diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 717ff234c..93bae4078 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -22,7 +22,10 @@ * Energy \*********************************************************************************************/ -#define ENERGY_NONE 0 +#define XDRV_03 3 +#define XSNS_03 3 + +#define ENERGY_NONE 0 #define FEATURE_POWER_LIMIT true @@ -656,8 +659,6 @@ void EnergyShow(boolean json) * Interface \*********************************************************************************************/ -#define XDRV_03 - boolean Xdrv03(byte function) { boolean result = false; @@ -681,8 +682,6 @@ boolean Xdrv03(byte function) return result; } -#define XSNS_03 - boolean Xsns03(byte function) { boolean result = false; diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index dbdf3d27b..8bd5e529c 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -1,14 +1,18 @@ /* xplg_wemohue.ino - wemo and hue support for Sonoff-Tasmota + Copyright (C) 2018 Heiko Krupp 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 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 . */ diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index b5822cac7..0c4271f81 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -21,6 +21,8 @@ * Counter sensors (water meters, electricity meters etc.) \*********************************************************************************************/ +#define XSNS_01 1 + unsigned long last_counter_timer[MAX_COUNTERS]; // Last counter time in micro seconds void CounterUpdate(byte index) @@ -139,8 +141,6 @@ void CounterShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_01 - boolean Xsns01(byte function) { boolean result = false; diff --git a/sonoff/xsns_02_analog.ino b/sonoff/xsns_02_analog.ino new file mode 100644 index 000000000..ce794b3a2 --- /dev/null +++ b/sonoff/xsns_02_analog.ino @@ -0,0 +1,94 @@ +/* + xsns_02_analog.ino - ESP8266 ADC support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 USE_ADC_VCC +/*********************************************************************************************\ + * ADC support +\*********************************************************************************************/ + +#define XSNS_02 2 + +uint16_t adc_last_value = 0; + +uint16_t AdcRead() +{ + uint16_t analog = 0; + for (byte i = 0; i < 32; i++) { + analog += analogRead(A0); + delay(1); + } + analog >>= 5; + return analog; +} + +#ifdef USE_RULES +void AdcEvery250ms() +{ + uint16_t new_value = AdcRead(); + if ((new_value < adc_last_value -10) || (new_value > adc_last_value +10)) { + adc_last_value = new_value; + uint16_t value = adc_last_value / 10; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); + XdrvRulesProcess(); + } +} +#endif // USE_RULES + +void AdcShow(boolean json) +{ + uint16_t analog = AdcRead(); + + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ANALOG\":{\"A0\":%d}"), mqtt_data, analog); +#ifdef USE_WEBSERVER + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "", 0, analog); +#endif // USE_WEBSERVER + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +boolean Xsns02(byte function) +{ + boolean result = false; + + if (pin[GPIO_ADC0] < 99) { + switch (function) { +#ifdef USE_RULES + case FUNC_EVERY_250_MSECOND: + AdcEvery250ms(); + break; +#endif // USE_RULES + case FUNC_JSON_APPEND: + AdcShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_APPEND: + AdcShow(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_ADC_VCC diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index 1628e9abf..a294ad32f 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -53,6 +53,8 @@ \*********************************************************************************************/ +#define XSNS_04 4 + uint16_t sc_value[5] = { 0 }; void SonoffScSend(const char *data) @@ -152,8 +154,6 @@ void SonoffScShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_04 - boolean Xsns04(byte function) { boolean result = false; diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index fa0f4fee8..1f96ba5b6 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -22,6 +22,8 @@ * DS18B20 - Temperature - Single sensor \*********************************************************************************************/ +#define XSNS_05 5 + #define W1_SKIP_ROM 0xCC #define W1_CONVERT_TEMP 0x44 #define W1_READ_SCRATCHPAD 0xBE @@ -215,8 +217,6 @@ void Ds18b20Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_05 - boolean Xsns05(byte function) { boolean result = false; diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index 474f26e2e..10625c0c8 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -21,6 +21,9 @@ /*********************************************************************************************\ * DS18B20 - Temperature - Multiple sensors \*********************************************************************************************/ + +#define XSNS_05 5 + //#define USE_DS18x20_RECONFIGURE // When sensor is lost keep retrying or re-configure #define DS18S20_CHIPID 0x10 // +/-0.5C 9-bit @@ -464,8 +467,6 @@ void Ds18x20Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_05 - boolean Xsns05(byte function) { boolean result = false; diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index 03754bbe1..385278432 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -22,6 +22,8 @@ * DS18B20 - Temperature \*********************************************************************************************/ +#define XSNS_05 5 + #define DS18S20_CHIPID 0x10 #define DS18B20_CHIPID 0x28 #define MAX31850_CHIPID 0x3B @@ -218,8 +220,6 @@ void Ds18x20Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_05 - boolean Xsns05(byte function) { boolean result = false; diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index 048337d25..1434b4f47 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -26,6 +26,8 @@ * Source: Adafruit Industries https://github.com/adafruit/DHT-sensor-library \*********************************************************************************************/ +#define XSNS_06 6 + #define DHT_MAX_SENSORS 3 #define DHT_MAX_RETRY 8 @@ -238,8 +240,6 @@ void DhtShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_06 - boolean Xsns06(byte function) { boolean result = false; diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index 8771dab7f..f636a8cf3 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -28,6 +28,8 @@ * I2C Address: None \*********************************************************************************************/ +#define XSNS_07 7 + enum { SHT1X_CMD_MEASURE_TEMP = B00000011, SHT1X_CMD_MEASURE_RH = B00000101, @@ -218,8 +220,6 @@ void ShtShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_07 - boolean Xsns07(byte function) { boolean result = false; diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index 61266e106..9a24050f0 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -27,6 +27,8 @@ * I2C Address: 0x40 \*********************************************************************************************/ +#define XSNS_08 8 + #define HTU21_ADDR 0x40 #define SI7013_CHIPID 0x0D @@ -279,8 +281,6 @@ void HtuShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_08 - boolean Xsns08(byte function) { boolean result = false; diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index 36070578a..bcc4632bd 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -27,6 +27,8 @@ * I2C Address: 0x76 or 0x77 \*********************************************************************************************/ +#define XSNS_09 9 + #define BMP_ADDR1 0x76 #define BMP_ADDR2 0x77 @@ -585,8 +587,6 @@ void BmpShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_09 - boolean Xsns09(byte function) { boolean result = false; diff --git a/sonoff/xsns_10_bh1750.ino b/sonoff/xsns_10_bh1750.ino index 1dd18d90a..2cdc9bcbd 100644 --- a/sonoff/xsns_10_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -25,6 +25,8 @@ * I2C Address: 0x23 or 0x5C \*********************************************************************************************/ +#define XSNS_10 10 + #define BH1750_ADDR1 0x23 #define BH1750_ADDR2 0x5C @@ -114,8 +116,6 @@ void Bh1750Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_10 - boolean Xsns10(byte function) { boolean result = false; diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index 68d25234a..590f61300 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -94,6 +94,8 @@ * I2C Address: 0x38 and 0x39 \*********************************************************************************************/ +#define XSNS_11 11 + #define VEML6070_ADDR_H 0x39 // on some PCB boards the address can be changed by a solder point, #define VEML6070_ADDR_L 0x38 // to have no address conflicts with other I2C sensors and/or hardware #define VEML6070_INTEGRATION_TIME 3 // IT_4 = 500msec integration time, because the precission is 4 times higher then IT_0.5 @@ -305,8 +307,6 @@ void Veml6070Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_11 - boolean Xsns11(byte function) { boolean result = false; diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index bcfb6dfad..06da4acd4 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -40,6 +40,8 @@ * ADS1115_REG_CONFIG_PGA_0_256V // 16x gain +/- 0.256V 1 bit = 0.0078125mV \*********************************************************************************************/ +#define XSNS_12 12 + #define ADS1115_ADDRESS_ADDR_GND 0x48 // address pin low (GND) #define ADS1115_ADDRESS_ADDR_VDD 0x49 // address pin high (VCC) #define ADS1115_ADDRESS_ADDR_SDA 0x4A // address pin tied to SDA pin @@ -210,8 +212,6 @@ void Ads1115Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_12 - boolean Xsns12(byte function) { boolean result = false; diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/sonoff/xsns_12_ads1115_i2cdev.ino index 588a37ac5..dcfab91c7 100644 --- a/sonoff/xsns_12_ads1115_i2cdev.ino +++ b/sonoff/xsns_12_ads1115_i2cdev.ino @@ -40,6 +40,8 @@ * ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV \*********************************************************************************************/ +#define XSNS_12 12 + #include ADS1115 adc0; @@ -130,8 +132,6 @@ void Ads1115Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_12 - boolean Xsns12(byte function) { boolean result = false; diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index deb4d5f4f..6f0e2c1e9 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -19,9 +19,6 @@ #ifdef USE_I2C #ifdef USE_INA219 - -#define XSNS_13 13 - /*********************************************************************************************\ * INA219 - Low voltage (max 32V!) Current sensor * @@ -30,6 +27,8 @@ * I2C Address: 0x40, 0x41 0x44 or 0x45 \*********************************************************************************************/ +#define XSNS_13 13 + #define INA219_ADDRESS1 (0x40) // 1000000 (A0+A1=GND) #define INA219_ADDRESS2 (0x41) // 1000000 (A0=Vcc, A1=GND) #define INA219_ADDRESS3 (0x44) // 1000000 (A0=GND, A1=Vcc) diff --git a/sonoff/xsns_14_sht3x.ino b/sonoff/xsns_14_sht3x.ino index c3c8b2f9c..c9b36571b 100755 --- a/sonoff/xsns_14_sht3x.ino +++ b/sonoff/xsns_14_sht3x.ino @@ -25,6 +25,8 @@ * I2C Address: 0x44, 0x45 or 0x70 (SHTC3) \*********************************************************************************************/ +#define XSNS_14 14 + #define SHT3X_ADDR_GND 0x44 // address pin low (GND) #define SHT3X_ADDR_VDD 0x45 // address pin high (VDD) #define SHTC3_ADDR 0x70 // address for shtc3 sensor @@ -138,8 +140,6 @@ void Sht3xShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_14 - boolean Xsns14(byte function) { boolean result = false; diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 3b9945bca..5b9817561 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -18,9 +18,6 @@ */ #ifdef USE_MHZ19 - -#define XSNS_15 15 - /*********************************************************************************************\ * MH-Z19 - CO2 sensor * @@ -33,6 +30,8 @@ * Select filter usage on low stability readings \*********************************************************************************************/ +#define XSNS_15 15 + enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILTER_FAST, MHZ19_FILTER_MEDIUM, MHZ19_FILTER_SLOW}; #define MHZ19_FILTER_OPTION MHZ19_FILTER_FAST @@ -246,18 +245,14 @@ void MhzEverySecond() /*********************************************************************************************\ * Command Sensor15 + * + * 0 - (Not implemented) ABC Off + * 1 - (Not implemented) ABC On + * 2 - Manual start = ABC Off + * 3 - (Not implemented) Optional filter settings + * 9 - Reset \*********************************************************************************************/ -/* - 0 - ABC Off - 1 - ABC On - 2 - Manual start = ABC Off - - 3 - Optional filter settings - - 9 - Reset -*/ - bool MhzCommandSensor() { boolean serviced = true; diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index 61308aa20..8f2884c25 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -27,6 +27,8 @@ * I2C Addresses: 0x29 (low), 0x39 (float) or 0x49 (high) \*********************************************************************************************/ +#define XSNS_16 16 + #include Tsl2561 Tsl(Wire); @@ -118,8 +120,6 @@ void Tsl2561Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_16 - boolean Xsns16(byte function) { boolean result = false; diff --git a/sonoff/xsns_17_senseair.ino b/sonoff/xsns_17_senseair.ino index a810a0e27..7a2060dd9 100644 --- a/sonoff/xsns_17_senseair.ino +++ b/sonoff/xsns_17_senseair.ino @@ -26,6 +26,8 @@ * Hardware Serial will be selected if GPIO1 = [SAir Rx] and GPIO3 = [SAir Tx] \*********************************************************************************************/ +#define XSNS_17 17 + #define SENSEAIR_MODBUS_SPEED 9600 #define SENSEAIR_DEVICE_ADDRESS 0xFE // Any address #define SENSEAIR_READ_REGISTER 0x04 // Command Read @@ -175,8 +177,6 @@ void SenseairShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_17 - boolean Xsns17(byte function) { boolean result = false; diff --git a/sonoff/xsns_18_pms5003.ino b/sonoff/xsns_18_pms5003.ino index fb2aca0fb..ec605cf46 100644 --- a/sonoff/xsns_18_pms5003.ino +++ b/sonoff/xsns_18_pms5003.ino @@ -25,6 +25,8 @@ * Hardware Serial will be selected if GPIO3 = [PMS5003] \*********************************************************************************************/ +#define XSNS_18 18 + #include TasmotaSerial *PmsSerial; @@ -156,8 +158,6 @@ void PmsShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_18 - boolean Xsns18(byte function) { boolean result = false; diff --git a/sonoff/xsns_19_mgs.ino b/sonoff/xsns_19_mgs.ino index f27b734fd..75fbea5b8 100644 --- a/sonoff/xsns_19_mgs.ino +++ b/sonoff/xsns_19_mgs.ino @@ -26,6 +26,8 @@ * https://github.com/Seeed-Studio/Mutichannel_Gas_Sensor.git \*********************************************************************************************/ +#define XSNS_19 19 + #ifndef MGS_SENSOR_ADDR #define MGS_SENSOR_ADDR 0x04 // Default Mutichannel Gas sensor i2c address #endif @@ -89,8 +91,6 @@ void MGSShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_19 - boolean Xsns19(byte function) { boolean result = false; diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 815041cab..8a584571c 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -25,10 +25,12 @@ * Hardware Serial will be selected if GPIO3 = [SDS0X01] \*********************************************************************************************/ +#define XSNS_20 20 + #include #ifndef WORKING_PERIOD - #define WORKING_PERIOD 5 +#define WORKING_PERIOD 5 #endif TasmotaSerial *NovaSdsSerial; @@ -169,8 +171,6 @@ void NovaSdsShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_20 - boolean Xsns20(byte function) { boolean result = false; diff --git a/sonoff/xsns_21_sgp30.ino b/sonoff/xsns_21_sgp30.ino index 5fef47bfd..ff6cbb749 100644 --- a/sonoff/xsns_21_sgp30.ino +++ b/sonoff/xsns_21_sgp30.ino @@ -27,6 +27,8 @@ * I2C Address: 0x58 \*********************************************************************************************/ +#define XSNS_21 21 + #include "Adafruit_SGP30.h" Adafruit_SGP30 sgp; @@ -88,8 +90,6 @@ void Sgp30Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_21 - boolean Xsns21(byte function) { boolean result = false; diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index 775ea93c9..9d447b3f3 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -26,6 +26,8 @@ * - https://www.dfrobot.com/wiki/index.php/Weather-proof_Ultrasonic_Sensor_SKU_:_SEN0207 \*********************************************************************************************/ +#define XSNS_22 22 + uint8_t sr04_echo_pin = 0; uint8_t sr04_trig_pin = 0; @@ -146,8 +148,6 @@ void Sr04Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_22 - boolean Xsns22(byte function) { boolean result = false; diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino index e5cc64418..5c2dfa630 100644 --- a/sonoff/xsns_23_sdm120.ino +++ b/sonoff/xsns_23_sdm120.ino @@ -25,6 +25,8 @@ * Based on: https://github.com/reaper7/SDM_Energy_Meter \*********************************************************************************************/ +#define XSNS_23 23 + #include TasmotaSerial *SDM120Serial; @@ -270,8 +272,6 @@ void SDM120Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_23 - boolean Xsns23(byte function) { boolean result = false; diff --git a/sonoff/xsns_24_si1145.ino b/sonoff/xsns_24_si1145.ino index 95ad930af..d84eef62f 100644 --- a/sonoff/xsns_24_si1145.ino +++ b/sonoff/xsns_24_si1145.ino @@ -27,9 +27,7 @@ * I2C Addresses: 0x60 \*********************************************************************************************/ -uint8_t si1145_type = 0; - -/********************************************************************************************/ +#define XSNS_24 24 #define SI114X_ADDR 0X60 // @@ -184,6 +182,8 @@ uint8_t si1145_type = 0; #define SI114X_IRQEN_PS2 0x08 #define SI114X_IRQEN_PS3 0x10 +uint8_t si1145_type = 0; + /********************************************************************************************/ uint8_t Si1145ReadByte(uint8_t reg) @@ -349,8 +349,6 @@ void Si1145Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_24 - boolean Xsns24(byte function) { boolean result = false; diff --git a/sonoff/xsns_25_sdm630.ino b/sonoff/xsns_25_sdm630.ino index c3513fd42..8c5e556fc 100644 --- a/sonoff/xsns_25_sdm630.ino +++ b/sonoff/xsns_25_sdm630.ino @@ -25,6 +25,8 @@ * Based on: https://github.com/reaper7/SDM_Energy_Meter \*********************************************************************************************/ +#define XSNS_25 25 + #include TasmotaSerial *SDM630Serial; @@ -325,8 +327,6 @@ void SDM630Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_25 - boolean Xsns25(byte function) { boolean result = false; diff --git a/sonoff/xsns_26_lm75ad.ino b/sonoff/xsns_26_lm75ad.ino index 1fd0f4448..ba2f39b16 100644 --- a/sonoff/xsns_26_lm75ad.ino +++ b/sonoff/xsns_26_lm75ad.ino @@ -28,6 +28,8 @@ * I2C Address: 0x48 - 0x4F \*********************************************************************************************/ +#define XSNS_26 26 + #define LM75AD_ADDRESS1 0x48 #define LM75AD_ADDRESS2 0x49 #define LM75AD_ADDRESS3 0x4A @@ -101,8 +103,6 @@ void LM75ADShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_26 - boolean Xsns26(byte function) { boolean result = false; diff --git a/sonoff/xsns_27_apds9960.ino b/sonoff/xsns_27_apds9960.ino index d2e5dbc8b..1b99e4304 100644 --- a/sonoff/xsns_27_apds9960.ino +++ b/sonoff/xsns_27_apds9960.ino @@ -27,9 +27,6 @@ #ifdef USE_I2C #ifdef USE_APDS9960 - -#define XSNS_27 27 - /*********************************************************************************************\ * APDS9960 - Digital Proximity Ambient Light RGB and Gesture Sensor * @@ -39,6 +36,8 @@ * I2C Address: 0x39 \*********************************************************************************************/ +#define XSNS_27 27 + #if defined(USE_SHT) || defined(USE_VEML6070) || defined(USE_TSL2561) #warning **** Turned off conflicting drivers SHT and VEML6070 **** #ifdef USE_SHT diff --git a/sonoff/xsns_28_tm1638.ino b/sonoff/xsns_28_tm1638.ino index a81344880..7dd62d2b5 100644 --- a/sonoff/xsns_28_tm1638.ino +++ b/sonoff/xsns_28_tm1638.ino @@ -24,6 +24,8 @@ * Uses GPIO TM16 DIO, TM16 CLK and TM16 STB \*********************************************************************************************/ +#define XSNS_28 28 + #define TM1638_COLOR_NONE 0 #define TM1638_COLOR_RED 1 #define TM1638_COLOR_GREEN 2 @@ -196,8 +198,6 @@ void TmShow(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_28 - boolean Xsns28(byte function) { boolean result = false; diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 9dbaf406a..867fa54ec 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -19,7 +19,6 @@ #ifdef USE_I2C #ifdef USE_MCP230xx - /*********************************************************************************************\ MCP23008/17 - I2C GPIO EXPANDER diff --git a/sonoff/xsns_30_mpr121.ino b/sonoff/xsns_30_mpr121.ino index 86191c079..4021247a6 100644 --- a/sonoff/xsns_30_mpr121.ino +++ b/sonoff/xsns_30_mpr121.ino @@ -43,6 +43,12 @@ #ifdef USE_I2C #ifdef USE_MPR121 +/** + * @ingroup group1 + * Assign Tasmota sensor model ID + */ +#define XSNS_30 30 + /** @defgroup group1 MPR121 * MPR121 preprocessor directives * @{ @@ -384,12 +390,6 @@ void Mpr121Show(struct mpr121 *pS, byte function) * Interface \*********************************************************************************************/ -/** - * @ingroup group1 - * Assign Tasmota sensor model ID - */ -#define XSNS_30 - /** * The function Xsns30() interfaces Tasmota with the driver. * diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index d57c9cb06..93bda1a4f 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -27,6 +27,8 @@ * I2C Address: 0x5A assumes ADDR connected to Gnd, Wake also must be grounded \*********************************************************************************************/ +#define XSNS_31 31 + #include "Adafruit_CCS811.h" Adafruit_CCS811 ccs; @@ -101,8 +103,6 @@ void CCS811Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_31 - boolean Xsns31(byte function) { boolean result = false; diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index 58ac705a3..c41549775 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -1,5 +1,5 @@ /* - xsns_32_MPU_6050.ino - MPU_6050 gyroscope and temperature sensor support for Sonoff-Tasmota + xsns_32_mpu6050.ino - MPU6050 gyroscope and temperature sensor support for Sonoff-Tasmota Copyright (C) 2018 Oliver Welter @@ -20,14 +20,16 @@ #ifdef USE_I2C #ifdef USE_MPU6050 /*********************************************************************************************\ - * MPU_6050 3 axis gyroscope and temperature sensor + * MPU6050 3 axis gyroscope and temperature sensor * * Source: Oliver Welter, with special thanks to Jeff Rowberg * * I2C Address: 0x68 or 0x69 with AD0 HIGH \*********************************************************************************************/ -#define D_SENSOR_MPU6050 "MPU6050" +#define XSNS_32 32 + +#define D_SENSOR_MPU6050 "MPU6050" #define MPU_6050_ADDR_AD0_LOW 0x68 #define MPU_6050_ADDR_AD0_HIGH 0x69 @@ -173,8 +175,6 @@ void MPU_6050Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_32 - boolean Xsns32(byte function) { boolean result = false; diff --git a/sonoff/xsns_33_ds3231.ino b/sonoff/xsns_33_ds3231.ino index df18c73db..bc5c4ba3b 100644 --- a/sonoff/xsns_33_ds3231.ino +++ b/sonoff/xsns_33_ds3231.ino @@ -32,9 +32,11 @@ I2C Address: 0x68 \*********************************************************************************************/ +#define XSNS_33 33 + //DS3232 I2C Address #ifndef USE_RTC_ADDR - #define USE_RTC_ADDR 0x68 +#define USE_RTC_ADDR 0x68 #endif //DS3232 Register Addresses @@ -134,8 +136,6 @@ void SetDS3231Time (uint32_t epoch_time) { Interface \*********************************************************************************************/ -#define XSNS_33 - boolean Xsns33(byte function) { boolean result = false; diff --git a/sonoff/xsns_35_tx20.ino b/sonoff/xsns_35_tx20.ino index d87c6de25..91a80ba81 100644 --- a/sonoff/xsns_35_tx20.ino +++ b/sonoff/xsns_35_tx20.ino @@ -26,6 +26,8 @@ * https://www.john.geek.nz/2011/07/la-crosse-tx20-anemometer-communication-protocol/ \*********************************************************************************************/ +#define XSNS_35 35 + #define TX20_BIT_TIME 1220 // microseconds #define TX20_RESET_VALUES 60 // seconds @@ -194,8 +196,6 @@ void Tx20Show(boolean json) * Interface \*********************************************************************************************/ -#define XSNS_35 - boolean Xsns35(byte function) { boolean result = false; diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index a51ab5947..522ef7665 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -260,19 +260,296 @@ boolean (* const xsns_func_ptr[])(byte) PROGMEM = { // Sensor Function Pointers const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); // Number of External Sensors found uint8_t xsns_index = 0; +const uint8_t kXsnsList[] PROGMEM = { +#ifdef XSNS_01 + XSNS_01, +#endif + +#ifdef XSNS_02 + XSNS_02, +#endif + +#ifdef XSNS_03 + XSNS_03, +#endif + +#ifdef XSNS_04 + XSNS_04, +#endif + +#ifdef XSNS_05 + XSNS_05, +#endif + +#ifdef XSNS_06 + XSNS_06, +#endif + +#ifdef XSNS_07 + XSNS_07, +#endif + +#ifdef XSNS_08 + XSNS_08, +#endif + +#ifdef XSNS_09 + XSNS_09, +#endif + +#ifdef XSNS_10 + XSNS_10, +#endif + +#ifdef XSNS_11 + XSNS_11, +#endif + +#ifdef XSNS_12 + XSNS_12, +#endif + +#ifdef XSNS_13 + XSNS_13, +#endif + +#ifdef XSNS_14 + XSNS_14, +#endif + +#ifdef XSNS_15 + XSNS_15, +#endif + +#ifdef XSNS_16 + XSNS_16, +#endif + +#ifdef XSNS_17 + XSNS_17, +#endif + +#ifdef XSNS_18 + XSNS_18, +#endif + +#ifdef XSNS_19 + XSNS_19, +#endif + +#ifdef XSNS_20 + XSNS_20, +#endif + +#ifdef XSNS_21 + XSNS_21, +#endif + +#ifdef XSNS_22 + XSNS_22, +#endif + +#ifdef XSNS_23 + XSNS_23, +#endif + +#ifdef XSNS_24 + XSNS_24, +#endif + +#ifdef XSNS_25 + XSNS_25, +#endif + +#ifdef XSNS_26 + XSNS_26, +#endif + +#ifdef XSNS_27 + XSNS_27, +#endif + +#ifdef XSNS_28 + XSNS_28, +#endif + +#ifdef XSNS_29 + XSNS_29, +#endif + +#ifdef XSNS_30 + XSNS_30, +#endif + +#ifdef XSNS_31 + XSNS_31, +#endif + +#ifdef XSNS_32 + XSNS_32, +#endif + +#ifdef XSNS_33 + XSNS_33, +#endif + +#ifdef XSNS_34 + XSNS_34, +#endif + +#ifdef XSNS_35 + XSNS_35, +#endif + +#ifdef XSNS_36 + XSNS_36, +#endif + +#ifdef XSNS_37 + XSNS_37, +#endif + +#ifdef XSNS_38 + XSNS_38, +#endif + +#ifdef XSNS_39 + XSNS_39, +#endif + +#ifdef XSNS_40 + XSNS_40, +#endif + +#ifdef XSNS_41 + XSNS_41, +#endif + +#ifdef XSNS_42 + XSNS_42, +#endif + +#ifdef XSNS_43 + XSNS_43, +#endif + +#ifdef XSNS_44 + XSNS_44, +#endif + +#ifdef XSNS_45 + XSNS_45, +#endif + +#ifdef XSNS_46 + XSNS_46, +#endif + +#ifdef XSNS_47 + XSNS_47, +#endif + +#ifdef XSNS_48 + XSNS_48, +#endif + +#ifdef XSNS_49 + XSNS_49, +#endif + +#ifdef XSNS_50 + XSNS_50, +#endif + +// Optional user defined sensors in range 91 - 99 + +#ifdef XSNS_91 + XSNS_91, +#endif + +#ifdef XSNS_92 + XSNS_92, +#endif + +#ifdef XSNS_93 + XSNS_93, +#endif + +#ifdef XSNS_94 + XSNS_94, +#endif + +#ifdef XSNS_95 + XSNS_95, +#endif + +#ifdef XSNS_96 + XSNS_96, +#endif + +#ifdef XSNS_97 + XSNS_97, +#endif + +#ifdef XSNS_98 + XSNS_98, +#endif + +#ifdef XSNS_99 + XSNS_99 +#endif +}; + + /*********************************************************************************************\ * Function call to all xsns \*********************************************************************************************/ -uint8_t XsnsPresent() +boolean XsnsEnabled(byte sns_index) { - return xsns_present; + if (sns_index < sizeof(kXsnsList)) { + uint8_t index = pgm_read_byte(kXsnsList + sns_index); + return bitRead(Settings.sensors[index / 32], index % 32); + } + return 1; +} + +boolean XsnsPresent(byte sns_index) +{ + uint8_t index = 0; + for (byte i = 0; i < sizeof(kXsnsList); i++) { + index = pgm_read_byte(kXsnsList + i); + if (index == sns_index) { return true; } + } + return false; +} + +String XsnsGetSensors() +{ + char state[2] = { 0 }; + + String data = F("["); + for (byte i = 0; i < MAX_XSNS_DRIVERS; i++) { + if (i && (!(i % 10))) { data += F(","); } + if (!(i % 10)) { data += F("\""); } + state[0] = '-'; + if (XsnsPresent(i)) { state[0] = bitRead(Settings.sensors[i / 32], i % 32) ? '1' : '0'; } + data += String(state); + if (i && (!((i +1) % 10))) { data += F("\""); } + } + data += F("]"); + + return data; } boolean XsnsNextCall(byte Function) { xsns_index++; - if (xsns_index == xsns_present) xsns_index = 0; + if (xsns_index == xsns_present) { xsns_index = 0; } + while (!XsnsEnabled(xsns_index) && !xsns_index) { // Perform at least first sensor (counter) + xsns_index++; + if (xsns_index == xsns_present) { xsns_index = 0; } + } if (global_state.wifi_down) { delay(DRIVER_BOOT_DELAY); } return xsns_func_ptr[xsns_index](Function); } @@ -286,24 +563,26 @@ boolean XsnsCall(byte Function) #endif // PROFILE_XSNS_EVERY_SECOND for (byte x = 0; x < xsns_present; x++) { + if (XsnsEnabled(x)) { #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND - uint32_t profile_start_millis = millis(); + uint32_t profile_start_millis = millis(); #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND - if (global_state.wifi_down) { delay(DRIVER_BOOT_DELAY); } - result = xsns_func_ptr[x](Function); + if (global_state.wifi_down) { delay(DRIVER_BOOT_DELAY); } + result = xsns_func_ptr[x](Function); #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND - uint32_t profile_millis = millis() - profile_start_millis; - if (profile_millis) { - if (FUNC_EVERY_SECOND == Function) { - snprintf_P(log_data, sizeof(log_data), PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), uptime, Function, x, profile_millis); - AddLog(LOG_LEVEL_DEBUG); + uint32_t profile_millis = millis() - profile_start_millis; + if (profile_millis) { + if (FUNC_EVERY_SECOND == Function) { + snprintf_P(log_data, sizeof(log_data), PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), uptime, Function, x, profile_millis); + AddLog(LOG_LEVEL_DEBUG); + } } - } #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND - if (result) break; + if (result) break; + } } #ifdef PROFILE_XSNS_EVERY_SECOND From 134a10d2c409eb645400fc8d4776c6a7ddb07c90 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Tue, 6 Nov 2018 20:06:25 +0100 Subject: [PATCH 0444/2222] tuya: Add SetOption22 to select if brightness-commands from faceplate should be ignored while powered off --- sonoff/sonoff.ino | 1 - sonoff/xdrv_16_tuyadimmer.ino | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 09e029a15..829879c31 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -729,7 +729,6 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) case 6: // mqtt_button_retain (CMND_BUTTONRETAIN) case 7: // mqtt_switch_retain (CMND_SWITCHRETAIN) case 9: // mqtt_sensor_retain (CMND_SENSORRETAIN) - case 22: // mqtt_serial (SerialSend and SerialLog) case 23: // mqtt_serial_raw (SerialSend) case 25: // knx_enabled (Web config) case 27: // knx_enable_enhancement (Web config) diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index a1356784d..d31d22609 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -207,7 +207,7 @@ void TuyaPacketProcess() } tuya_new_dim = round(tuya_buffer[13] * (100. / 255.)); - if((power || bitRead(Settings.flag.data, 20)) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 1)) { + if((power || bitRead(Settings.flag.data, 22)) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 1)) { snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), tuya_new_dim ); From 7003435b346006638c09daa8333aeee5e1a4dfc4 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Tue, 6 Nov 2018 22:58:07 +0100 Subject: [PATCH 0445/2222] tuya: use SetOption54 instead of SetOption22 --- sonoff/sonoff.ino | 1 + sonoff/xdrv_16_tuyadimmer.ino | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 829879c31..09e029a15 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -729,6 +729,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) case 6: // mqtt_button_retain (CMND_BUTTONRETAIN) case 7: // mqtt_switch_retain (CMND_SWITCHRETAIN) case 9: // mqtt_sensor_retain (CMND_SENSORRETAIN) + case 22: // mqtt_serial (SerialSend and SerialLog) case 23: // mqtt_serial_raw (SerialSend) case 25: // knx_enabled (Web config) case 27: // knx_enable_enhancement (Web config) diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index d31d22609..9b3630211 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -207,7 +207,7 @@ void TuyaPacketProcess() } tuya_new_dim = round(tuya_buffer[13] * (100. / 255.)); - if((power || bitRead(Settings.flag.data, 22)) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 1)) { + if((power || bitRead(Settings.flag3.data, 4)) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 1)) { snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), tuya_new_dim ); From a2b7bdac45de9d6c0a865648c2478412bdfd9326 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Tue, 6 Nov 2018 23:27:49 +0100 Subject: [PATCH 0446/2222] tuya: name flag SetOption54 --- sonoff/settings.h | 2 +- sonoff/xdrv_16_tuyadimmer.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 677a02bf3..6914379b8 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -67,7 +67,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t user_esp8285_enable : 1; // bit 1 (v6.1.1.14) uint32_t time_append_timezone : 1; // bit 2 (v6.2.1.2) uint32_t gui_hostname_ip : 1; // bit 3 (v6.2.1.20) - uint32_t spare04 : 1; + uint32_t tuya_apply_o20 : 1; uint32_t spare05 : 1; uint32_t spare06 : 1; uint32_t spare07 : 1; diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index 9b3630211..06926acba 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -207,7 +207,7 @@ void TuyaPacketProcess() } tuya_new_dim = round(tuya_buffer[13] * (100. / 255.)); - if((power || bitRead(Settings.flag3.data, 4)) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 1)) { + if((power || Settings.flag3.tuya_apply_o20) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 1)) { snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), tuya_new_dim ); From 9fef82736d27510b6e736d424ed034213e1aa4c3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 7 Nov 2018 10:30:03 +0100 Subject: [PATCH 0447/2222] Prep drivers for management Prep drivers for management --- sonoff/settings.h | 12 ++++++------ sonoff/settings.ino | 4 ++-- sonoff/sonoff.h | 4 ++-- sonoff/xdrv_01_webserver.ino | 4 ++-- sonoff/xdrv_02_mqtt.ino | 4 ++-- sonoff/xdrv_04_light.ino | 4 ++-- sonoff/xdrv_05_irremote.ino | 4 ++-- sonoff/xdrv_06_snfbridge.ino | 4 ++-- sonoff/xdrv_07_domoticz.ino | 4 ++-- sonoff/xdrv_08_serial_bridge.ino | 5 +++-- sonoff/xdrv_09_timers.ino | 4 ++-- sonoff/xdrv_10_rules.ino | 4 ++-- sonoff/xdrv_11_knx.ino | 4 ++-- sonoff/xdrv_12_home_assistant.ino | 4 ++-- sonoff/xdrv_13_display.ino | 4 ++-- sonoff/xdrv_14_mp3.ino | 4 ++-- sonoff/xdrv_16_tuyadimmer.ino | 8 ++++---- sonoff/xdrv_17_rcswitch.ino | 4 ++-- sonoff/{xdrv_99_debug.ino => xdrv_95_debug.ino} | 13 ++++++++----- sonoff/xsns_interface.ino | 6 +++--- 20 files changed, 54 insertions(+), 50 deletions(-) rename sonoff/{xdrv_99_debug.ino => xdrv_95_debug.ino} (98%) diff --git a/sonoff/settings.h b/sonoff/settings.h index c1f568ca1..f185004c4 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -67,7 +67,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t user_esp8285_enable : 1; // bit 1 (v6.1.1.14) uint32_t time_append_timezone : 1; // bit 2 (v6.2.1.2) uint32_t gui_hostname_ip : 1; // bit 3 (v6.2.1.20) - uint32_t tuya_apply_o20 : 1; + uint32_t tuya_apply_o20 : 1; // bit 4 (v6.3.0.4) uint32_t spare05 : 1; uint32_t spare06 : 1; uint32_t spare07 : 1; @@ -320,12 +320,12 @@ struct SYSCFG { uint16_t mcp230xx_int_timer; // 718 uint8_t rgbwwTable[5]; // 71A - byte free_71F[109]; // 71F + byte free_71F[117]; // 71F - uint32_t monitors; // 78C - uint32_t displays; // 790 - uint32_t drivers[4]; // 794 - uint32_t sensors[4]; // 7A4 + uint32_t drivers[3]; // 794 + uint32_t monitors; // 7A0 + uint32_t sensors[3]; // 7A4 + uint32_t displays; // 7B0 uint32_t energy_kWhtotal_time; // 7B4 unsigned long weight_item; // 7B8 Weight of one item in gram * 10 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 88c6838a3..a38e2113e 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -636,7 +636,7 @@ void SettingsDefaultSet2() Settings.rgbwwTable[j] = 255; } - memset(&Settings.monitors, 0xFF, 40); // Enable all possible monitors, displays, drivers and sensors + memset(&Settings.drivers, 0xFF, 32); // Enable all possible monitors, displays, drivers and sensors } /********************************************************************************************/ @@ -849,7 +849,7 @@ void SettingsDelta() Settings.timezone_minutes = 0; } if (Settings.version < 0x06030004) { - memset(&Settings.monitors, 0xFF, 40); // Enable all possible monitors, displays, drivers and sensors + memset(&Settings.drivers, 0xFF, 32); // Enable all possible monitors, displays, drivers and sensors } Settings.version = VERSION; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index a0ad03c13..4c6abee0d 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -52,8 +52,8 @@ typedef unsigned long power_t; // Power (Relay) type #define MAX_KNX_CB 10 // Max number of KNX Group Addresses to write that can be set #define MAX_XNRG_DRIVERS 32 // Max number of allowed energy drivers #define MAX_XDSP_DRIVERS 32 // Max number of allowed display drivers -#define MAX_XDRV_DRIVERS 100 // Max number of allowed driver drivers -#define MAX_XSNS_DRIVERS 100 // Max number of allowed sensor drivers +#define MAX_XDRV_DRIVERS 96 // Max number of allowed driver drivers +#define MAX_XSNS_DRIVERS 96 // Max number of allowed sensor drivers #define MAX_RULE_MEMS 5 // Max number of saved vars #define MAX_RULE_SETS 3 // Max number of rule sets of size 512 characters #define MAX_RULE_SIZE 512 // Max number of characters in rules diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index e7327b769..8352e9820 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -25,6 +25,8 @@ * Based on source by AlexT (https://github.com/tzapu) \*********************************************************************************************/ +#define XDRV_01 1 + #define HTTP_REFRESH_TIME 2345 // milliseconds #ifdef USE_RF_FLASH @@ -2009,8 +2011,6 @@ bool WebCommand() * Interface \*********************************************************************************************/ -#define XDRV_01 - boolean Xdrv01(byte function) { boolean result = false; diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index ed24d31ed..40f69d93a 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -17,6 +17,8 @@ along with this program. If not, see . */ +#define XDRV_02 2 + /*********************************************************************************************\ * Select ONE of possible MQTT library types below \*********************************************************************************************/ @@ -909,8 +911,6 @@ void MqttSaveSettings() * Interface \*********************************************************************************************/ -#define XDRV_02 - boolean Xdrv02(byte function) { boolean result = false; diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index c5ba2acc7..9bd88e2cb 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -51,6 +51,8 @@ * \*********************************************************************************************/ +#define XDRV_04 4 + #define WS2812_SCHEMES 7 // Number of additional WS2812 schemes supported by xdrv_ws2812.ino enum LightCommands { @@ -1369,8 +1371,6 @@ boolean LightCommand() * Interface \*********************************************************************************************/ -#define XDRV_04 - boolean Xdrv04(byte function) { boolean result = false; diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 83cde7419..8ab611ead 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -22,6 +22,8 @@ * IR Remote send and receive using IRremoteESP8266 library \*********************************************************************************************/ +#define XDRV_05 5 + #include // Based on IRremoteESP8266.h enum decode_type_t @@ -401,8 +403,6 @@ boolean IrSendCommand() * Interface \*********************************************************************************************/ -#define XDRV_05 - boolean Xdrv05(byte function) { boolean result = false; diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 8e9201b43..3afdf6066 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -21,6 +21,8 @@ Sonoff RF Bridge 433 \*********************************************************************************************/ +#define XDRV_06 6 + #define SFB_TIME_AVOID_DUPLICATE 2000 // Milliseconds enum SonoffBridgeCommands { @@ -564,8 +566,6 @@ void SonoffBridgeInit() * Interface \*********************************************************************************************/ -#define XDRV_06 - boolean Xdrv06(byte function) { boolean result = false; diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 060301323..527053832 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -19,6 +19,8 @@ #ifdef USE_DOMOTICZ +#define XDRV_07 7 + const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\",\"Battery\":%d,\"RSSI\":%d}"; enum DomoticzCommands { CMND_IDX, CMND_KEYIDX, CMND_SWITCHIDX, CMND_SENSORIDX, CMND_UPDATETIMER }; @@ -475,8 +477,6 @@ void DomoticzSaveSettings() * Interface \*********************************************************************************************/ -#define XDRV_07 - boolean Xdrv07(byte function) { boolean result = false; diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 5d04c8059..f1ac48fe7 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -21,6 +21,9 @@ /*********************************************************************************************\ * Serial Bridge using Software Serial library (TasmotaSerial) \*********************************************************************************************/ + +#define XDRV_08 8 + #define SERIAL_BRIDGE_BUFFER_SIZE 130 #include @@ -127,8 +130,6 @@ boolean SerialBridgeCommand() * Interface \*********************************************************************************************/ -#define XDRV_08 - boolean Xdrv08(byte function) { boolean result = false; diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 73c143ae9..5907943f6 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -35,6 +35,8 @@ * \*********************************************************************************************/ +#define XDRV_09 9 + enum TimerCommands { CMND_TIMER, CMND_TIMERS #ifdef USE_SUNRISE , CMND_LATITUDE, CMND_LONGITUDE @@ -743,8 +745,6 @@ void TimerSaveSettings() * Interface \*********************************************************************************************/ -#define XDRV_09 - boolean Xdrv09(byte function) { boolean result = false; diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 54fcb3f08..4da4937d7 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -63,6 +63,8 @@ * RuleTimer2 100 \*********************************************************************************************/ +#define XDRV_10 10 + #define D_CMND_RULE "Rule" #define D_CMND_RULETIMER "RuleTimer" #define D_CMND_EVENT "Event" @@ -640,8 +642,6 @@ double map_double(double x, double in_min, double in_max, double out_min, double * Interface \*********************************************************************************************/ -#define XDRV_10 - boolean Xdrv10(byte function) { boolean result = false; diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 944f1ba90..86a8a7fca 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -48,6 +48,8 @@ byte Settings.knx_CB_param[MAX_KNX_CB] Type of Output (set relay, t \*********************************************************************************************/ +#define XDRV_11 11 + #include // KNX Library address_t KNX_physs_addr; // Physical KNX address of this device @@ -1278,8 +1280,6 @@ boolean KnxCommand() * Interface \*********************************************************************************************/ -#define XDRV_11 - boolean Xdrv11(byte function) { boolean result = false; diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 3c38cbc46..46a5c0521 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -19,6 +19,8 @@ #ifdef USE_HOME_ASSISTANT +#define XDRV_12 12 + const char HASS_DISCOVER_RELAY[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 "\"command_topic\":\"%s\"," // cmnd/dualr2/POWER2 @@ -255,8 +257,6 @@ boolean HassCommand() * Interface \*********************************************************************************************/ -#define XDRV_12 - boolean Xdrv12(byte function) { boolean result = false; diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index fcb9a33f8..9656c14ec 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -20,6 +20,8 @@ #if defined(USE_I2C) || defined(USE_SPI) #ifdef USE_DISPLAY +#define XDRV_13 13 + #define DISPLAY_MAX_DRIVERS 16 // Max number of display drivers/models supported by xdsp_interface.ino #define DISPLAY_MAX_COLS 40 // Max number of columns allowed with command DisplayCols #define DISPLAY_MAX_ROWS 32 // Max number of lines allowed with command DisplayRows @@ -1060,8 +1062,6 @@ boolean DisplayCommand() * Interface \*********************************************************************************************/ -#define XDRV_13 - boolean Xdrv13(byte function) { boolean result = false; diff --git a/sonoff/xdrv_14_mp3.ino b/sonoff/xdrv_14_mp3.ino index ae0c69fd0..0a72b68ab 100644 --- a/sonoff/xdrv_14_mp3.ino +++ b/sonoff/xdrv_14_mp3.ino @@ -67,6 +67,8 @@ * https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299 \*********************************************************************************************/ +#define XDRV_14 14 + #include TasmotaSerial *MP3Player; @@ -224,8 +226,6 @@ boolean MP3PlayerCmd(void) { * Interface \*********************************************************************************************/ -#define XDRV_14 - boolean Xdrv14(byte function) { boolean result = false; diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index 06926acba..c8bf04961 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -19,6 +19,8 @@ #ifdef USE_TUYA_DIMMER +#define XDRV_16 16 + #ifndef TUYA_DIMMER_ID #define TUYA_DIMMER_ID 0 #endif @@ -137,7 +139,7 @@ void LightSerialDuty(uint8_t duty) if (duty < 25) { duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself } - + TuyaSendValue(Settings.param[P_TUYA_DIMMER_ID], duty); snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Serial Packet Dim Value=%d (id=%d)"), duty, Settings.param[P_TUYA_DIMMER_ID]); @@ -177,7 +179,7 @@ void TuyaPacketProcess() switch(tuya_buffer[3]) { - case TUYA_CMD_HEARTBEAT: + case TUYA_CMD_HEARTBEAT: AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); if(tuya_buffer[6] == 0){ AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Detected MCU restart")); @@ -386,8 +388,6 @@ void TuyaSetWifiLed(){ * Interface \*********************************************************************************************/ -#define XDRV_16 - boolean Xdrv16(byte function) { boolean result = false; diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index 137bd82b1..701b8c119 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -22,6 +22,8 @@ * RF send and receive using RCSwitch library https://github.com/sui77/rc-switch/ \*********************************************************************************************/ +#define XDRV_17 17 + #define D_JSON_RF_PROTOCOL "Protocol" #define D_JSON_RF_BITS "Bits" #define D_JSON_RF_DATA "Data" @@ -164,8 +166,6 @@ boolean RfSendCommand() * Interface \*********************************************************************************************/ -#define XDRV_17 - boolean Xdrv17(byte function) { boolean result = false; diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_95_debug.ino similarity index 98% rename from sonoff/xdrv_99_debug.ino rename to sonoff/xdrv_95_debug.ino index abd209b82..18f9ad76f 100644 --- a/sonoff/xdrv_99_debug.ino +++ b/sonoff/xdrv_95_debug.ino @@ -1,5 +1,5 @@ /* - xdrv_99_debug.ino - debug support for Sonoff-Tasmota + xdrv_95_debug.ino - debug support for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -26,9 +26,14 @@ #endif // DEBUG_THEO #ifdef USE_DEBUG_DRIVER +/*********************************************************************************************\ + * Virtual debugging support +\*********************************************************************************************/ + +#define XDRV_95 95 #ifndef CPU_LOAD_CHECK -#define CPU_LOAD_CHECK 1 // Seconds between each CPU_LOAD log +#define CPU_LOAD_CHECK 1 // Seconds between each CPU_LOAD log #endif /*********************************************************************************************\ @@ -473,9 +478,7 @@ boolean DebugCommand() * Interface \*********************************************************************************************/ -#define XDRV_99 - -boolean Xdrv99(byte function) +boolean Xdrv95(byte function) { boolean result = false; diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index 522ef7665..e858ec43e 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -530,12 +530,12 @@ String XsnsGetSensors() String data = F("["); for (byte i = 0; i < MAX_XSNS_DRIVERS; i++) { - if (i && (!(i % 10))) { data += F(","); } - if (!(i % 10)) { data += F("\""); } + if (i && (!(i % 16))) { data += F(","); } + if (!(i % 16)) { data += F("\""); } state[0] = '-'; if (XsnsPresent(i)) { state[0] = bitRead(Settings.sensors[i / 32], i % 32) ? '1' : '0'; } data += String(state); - if (i && (!((i +1) % 10))) { data += F("\""); } + if (i && (!((i +1) % 16))) { data += F("\""); } } data += F("]"); From a4df728115fa1906abfdd265d3622221a2ab8e43 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 7 Nov 2018 11:38:24 +0100 Subject: [PATCH 0448/2222] Moved func ptr tables to RAM Moved function pointer tables to RAM to check performance issues --- sonoff/xdrv_interface.ino | 7 +++++++ sonoff/xsns_interface.ino | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 69bbcbada..11699543c 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -17,7 +17,14 @@ along with this program. If not, see . */ +//#define XDRV_IN_ROM + +#ifdef XDRV_IN_ROM boolean (* const xdrv_func_ptr[])(byte) PROGMEM = { // Driver Function Pointers +#else +boolean (* const xdrv_func_ptr[])(byte) = { // Driver Function Pointers +#endif + #ifdef XDRV_01 &Xdrv01, #endif diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index e858ec43e..adfebea22 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -17,7 +17,13 @@ along with this program. If not, see . */ +//#define XSNS_IN_ROM + +#ifdef XSNS_IN_ROM boolean (* const xsns_func_ptr[])(byte) PROGMEM = { // Sensor Function Pointers for simple implementation of sensors +#else +boolean (* const xsns_func_ptr[])(byte) = { // Sensor Function Pointers for simple implementation of sensors +#endif #ifdef XSNS_01 &Xsns01, #endif @@ -260,7 +266,11 @@ boolean (* const xsns_func_ptr[])(byte) PROGMEM = { // Sensor Function Pointers const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); // Number of External Sensors found uint8_t xsns_index = 0; +#ifdef XSNS_IN_ROM const uint8_t kXsnsList[] PROGMEM = { +#else +const uint8_t kXsnsList[] = { +#endif #ifdef XSNS_01 XSNS_01, #endif @@ -508,7 +518,11 @@ const uint8_t kXsnsList[] PROGMEM = { boolean XsnsEnabled(byte sns_index) { if (sns_index < sizeof(kXsnsList)) { +#ifdef XSNS_IN_ROM uint8_t index = pgm_read_byte(kXsnsList + sns_index); +#else + uint8_t index = kXsnsList[sns_index]; +#endif return bitRead(Settings.sensors[index / 32], index % 32); } return 1; @@ -518,7 +532,11 @@ boolean XsnsPresent(byte sns_index) { uint8_t index = 0; for (byte i = 0; i < sizeof(kXsnsList); i++) { +#ifdef XSNS_IN_ROM index = pgm_read_byte(kXsnsList + i); +#else + index = kXsnsList[i]; +#endif if (index == sns_index) { return true; } } return false; From 44d6714b69b9979960a4b2f8e18595f299cde373 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 7 Nov 2018 11:57:28 +0100 Subject: [PATCH 0449/2222] Moved all func ptr tables to RAM Moved all function pointer tables to RAM to check performance issues --- sonoff/sonoff.h | 10 ++++++++++ sonoff/xdrv_interface.ino | 4 +--- sonoff/xdsp_interface.ino | 5 +++++ sonoff/xnrg_interface.ino | 5 +++++ sonoff/xsns_interface.ino | 12 ++++++------ 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 4c6abee0d..1e27988e0 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -20,6 +20,16 @@ #ifndef _SONOFF_H_ #define _SONOFF_H_ +/*********************************************************************************************\ + * Performance ROM (PROGMEM) vs RAM (RODATA) +\*********************************************************************************************/ + +//#define XFUNC_PTR_IN_ROM // Enable for keeping tables in ROM (PROGMEM) which seem to have access issues on some flash types + +/*********************************************************************************************\ + * Default sensor states +\*********************************************************************************************/ + #define USE_DHT // Default DHT11 sensor needs no external library #define USE_ENERGY_SENSOR // Use energy sensors (+14k code) #define USE_HLW8012 // Use energy sensor for Sonoff Pow and WolfBlitz diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 11699543c..0f0171e20 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -17,9 +17,7 @@ along with this program. If not, see . */ -//#define XDRV_IN_ROM - -#ifdef XDRV_IN_ROM +#ifdef XFUNC_PTR_IN_ROM boolean (* const xdrv_func_ptr[])(byte) PROGMEM = { // Driver Function Pointers #else boolean (* const xdrv_func_ptr[])(byte) = { // Driver Function Pointers diff --git a/sonoff/xdsp_interface.ino b/sonoff/xdsp_interface.ino index 8d6d5a814..06fbf01dc 100644 --- a/sonoff/xdsp_interface.ino +++ b/sonoff/xdsp_interface.ino @@ -17,7 +17,12 @@ along with this program. If not, see . */ +#ifdef XFUNC_PTR_IN_ROM boolean (* const xdsp_func_ptr[])(byte) PROGMEM = { // Display Function Pointers +#else +boolean (* const xdsp_func_ptr[])(byte) = { // Display Function Pointers +#endif + #ifdef XDSP_01 &Xdsp01, #endif diff --git a/sonoff/xnrg_interface.ino b/sonoff/xnrg_interface.ino index 015d5d284..cea14e47c 100644 --- a/sonoff/xnrg_interface.ino +++ b/sonoff/xnrg_interface.ino @@ -17,7 +17,12 @@ along with this program. If not, see . */ +#ifdef XFUNC_PTR_IN_ROM int (* const xnrg_func_ptr[])(byte) PROGMEM = { // Energy driver Function Pointers +#else +int (* const xnrg_func_ptr[])(byte) = { // Energy driver Function Pointers +#endif + #ifdef XNRG_01 &Xnrg01, #endif diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index adfebea22..a3cf4d772 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -17,13 +17,12 @@ along with this program. If not, see . */ -//#define XSNS_IN_ROM - -#ifdef XSNS_IN_ROM +#ifdef XFUNC_PTR_IN_ROM boolean (* const xsns_func_ptr[])(byte) PROGMEM = { // Sensor Function Pointers for simple implementation of sensors #else boolean (* const xsns_func_ptr[])(byte) = { // Sensor Function Pointers for simple implementation of sensors #endif + #ifdef XSNS_01 &Xsns01, #endif @@ -266,11 +265,12 @@ boolean (* const xsns_func_ptr[])(byte) = { // Sensor Function Pointers for sim const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); // Number of External Sensors found uint8_t xsns_index = 0; -#ifdef XSNS_IN_ROM +#ifdef XFUNC_PTR_IN_ROM const uint8_t kXsnsList[] PROGMEM = { #else const uint8_t kXsnsList[] = { #endif + #ifdef XSNS_01 XSNS_01, #endif @@ -518,7 +518,7 @@ const uint8_t kXsnsList[] = { boolean XsnsEnabled(byte sns_index) { if (sns_index < sizeof(kXsnsList)) { -#ifdef XSNS_IN_ROM +#ifdef XFUNC_PTR_IN_ROM uint8_t index = pgm_read_byte(kXsnsList + sns_index); #else uint8_t index = kXsnsList[sns_index]; @@ -532,7 +532,7 @@ boolean XsnsPresent(byte sns_index) { uint8_t index = 0; for (byte i = 0; i < sizeof(kXsnsList); i++) { -#ifdef XSNS_IN_ROM +#ifdef XFUNC_PTR_IN_ROM index = pgm_read_byte(kXsnsList + i); #else index = kXsnsList[i]; From 9380312e7fc9c470767efdc3f2e50ef8b17f9d01 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Wed, 7 Nov 2018 13:42:13 +0100 Subject: [PATCH 0450/2222] add v6.3.0.4 config changes - pack setting templates using diffs - add more '--verbose' outputs - fix wrong templates selection - fix wrong filename handling - fix --verbose filename output --- tools/decode-config.py | 480 +++++++++++++++++++++++++---------------- 1 file changed, 298 insertions(+), 182 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 1683a6a2f..dd0073d8d 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.0.0004' +VER = '2.0.0005' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -155,6 +155,7 @@ def ModuleImportError(module): sys.exit(ExitCode.MODULE_NOT_FOUND) try: from datetime import datetime + import copy import struct import socket import re @@ -445,8 +446,8 @@ Setting_5_10_0 = { 'pulse_counter_debounce': ('= cfg[0]: - template = cfg - size = template[1] - setting = template[2] - break - except: - pass + size = setting = None - return version, template, size, setting + version = GetField(decode_cfg, 'version', Setting_6_2_1['version'], raw=True) + # search setting definition top-down + for cfg in sorted(Settings, key=lambda s: s[0], reverse=True): + if version >= cfg[0]: + version = cfg[0] + size = cfg[1] + setting = cfg[2].copy() + break + + return version, size, setting class LogType: @@ -944,6 +955,8 @@ def GetVersionStr(version): @return: version string """ + if isinstance(version, (unicode,str)): + version = int(version, 0) major = ((version>>24) & 0xff) minor = ((version>>16) & 0xff) release = ((version>> 8) & 0xff) @@ -1007,16 +1020,29 @@ def MakeFilename(filename, filetype, decode_cfg): if 'hostname' in decode_cfg: filename = filename.replace('@h', decode_cfg['hostname'] ) - filename = MakeValidFilename(filename) - ext = '' + dirname = basename = ext = '' try: - name, ext = os.path.splitext(filename) + dirname = os.path.normpath(os.path.dirname(filename)) + basename = os.path.basename(filename) + name, ext = os.path.splitext(basename) except: pass + name = MakeValidFilename(name) + if len(ext) and ext[0]=='.': ext = ext[1:] if filetype is not None and args.extension and (len(ext)<2 or all(c.isdigit() for c in ext)): - filename += '.'+filetype.lower() + ext = filetype.lower() + + if len(ext): + name_ext = name+'.'+ext + else: + name_ext = name + + try: + filename = os.path.join(dirname, name_ext) + except: + pass return filename @@ -1042,59 +1068,84 @@ def MakeUrl(host, port=80, location=''): slocation=location ) -def PullTasmotaConfig(): +def LoadTasmotaConfig(filename): """ - Pull config from Tasmota device/file + Load config from Tasmota file + + @param filename: + filename to load @return: binary config data (encrypted) or None on error """ - if args.device is not None: - # read config direct from device via http - - c = pycurl.Curl() - buffer = io.BytesIO() - c.setopt(c.WRITEDATA, buffer) - header = HTTPHeader() - c.setopt(c.HEADERFUNCTION, header.store) - c.setopt(c.FOLLOWLOCATION, True) - c.setopt(c.URL, MakeUrl(args.device, args.port, 'dl')) - if args.username is not None and args.password is not None: - c.setopt(c.HTTPAUTH, c.HTTPAUTH_BASIC) - c.setopt(c.USERPWD, args.username + ':' + args.password) - c.setopt(c.VERBOSE, False) + encode_cfg = None - responsecode = 200 - try: - c.perform() - responsecode = c.getinfo(c.RESPONSE_CODE) - response = header.response() - except Exception, e: - exit(e[0], e[1],line=inspect.getlineno(inspect.currentframe())) - finally: - c.close() - - if responsecode>=400: - exit(responsecode, 'HTTP result: {}'.format(header.response()),line=inspect.getlineno(inspect.currentframe())) - elif header.contenttype()!='application/octet-stream': - exit(ExitCode.DOWNLOAD_CONFIG_ERROR, "Device did not response properly, may be Tasmota webserver admin mode is disabled (WebServer 2)",line=inspect.getlineno(inspect.currentframe())) + # read config from a file + if not os.path.isfile(filename): # check file exists + exit(ExitCode.FILE_NOT_FOUND, "File '{}' not found".format(filename),line=inspect.getlineno(inspect.currentframe())) + try: + tasmotafile = open(filename, "rb") + encode_cfg = tasmotafile.read() + tasmotafile.close() + except Exception, e: + exit(e[0], "'{}' {}".format(filename, e[1]),line=inspect.getlineno(inspect.currentframe())) + + return encode_cfg + + +def PullTasmotaConfig(host, port, username=DEFAULTS['source']['username'], password=None): + """ + Pull config from Tasmota device + + @param host: + hostname or IP of Tasmota device + @param port: + http port of Tasmota device + @param username: + optional username for Tasmota web login + @param password + optional password for Tasmota web login + + @return: + binary config data (encrypted) or None on error + """ + + encode_cfg = None + + # read config direct from device via http + c = pycurl.Curl() + buffer = io.BytesIO() + c.setopt(c.WRITEDATA, buffer) + header = HTTPHeader() + c.setopt(c.HEADERFUNCTION, header.store) + c.setopt(c.FOLLOWLOCATION, True) + c.setopt(c.URL, MakeUrl(host, port, 'dl')) + if username is not None and password is not None: + c.setopt(c.HTTPAUTH, c.HTTPAUTH_BASIC) + c.setopt(c.USERPWD, username + ':' + password) + c.setopt(c.VERBOSE, False) + + responsecode = 200 + try: + c.perform() + responsecode = c.getinfo(c.RESPONSE_CODE) + response = header.response() + except Exception, e: + exit(e[0], e[1],line=inspect.getlineno(inspect.currentframe())) + finally: + c.close() + + if responsecode >= 400: + exit(responsecode, 'HTTP result: {}'.format(header.response()),line=inspect.getlineno(inspect.currentframe())) + elif header.contenttype()!='application/octet-stream': + exit(ExitCode.DOWNLOAD_CONFIG_ERROR, "Device did not response properly, may be Tasmota webserver admin mode is disabled (WebServer 2)",line=inspect.getlineno(inspect.currentframe())) + + try: encode_cfg = buffer.getvalue() - - elif args.tasmotafile is not None: - # read config from a file - if not os.path.isfile(args.tasmotafile): # check file exists - exit(ExitCode.FILE_NOT_FOUND, "File '{}' not found".format(args.tasmotafile),line=inspect.getlineno(inspect.currentframe())) - try: - tasmotafile = open(args.tasmotafile, "rb") - encode_cfg = tasmotafile.read() - tasmotafile.close() - except Exception, e: - exit(e[0], "'{}' {}".format(args.tasmotafile, e[1]),line=inspect.getlineno(inspect.currentframe())) - - else: - return None - + except: + pass + return encode_cfg @@ -1238,14 +1289,14 @@ def GetFieldDef(fielddef): , , , , , undefined items can be None """ - _format = baseaddr = datadef = convert = None + format = baseaddr = datadef = convert = None bits = bitshift = 0 if len(fielddef)==3: # def without convert tuple - _format, baseaddr, datadef = fielddef + format, baseaddr, datadef = fielddef elif len(fielddef)==4: # def with convert tuple - _format, baseaddr, datadef, convert = fielddef + format, baseaddr, datadef, convert = fielddef if isinstance(baseaddr, (list,tuple)): baseaddr, bits, bitshift = baseaddr @@ -1253,7 +1304,7 @@ def GetFieldDef(fielddef): if isinstance(datadef, int): # convert single int into list with one item datadef = [datadef] - return _format, baseaddr, bits, bitshift, datadef, convert + return format, baseaddr, bits, bitshift, datadef, convert def MakeFieldBaseAddr(baseaddr, bits, bitshift): @@ -1293,7 +1344,7 @@ def ConvertFieldValue(value, fielddef, read=True, raw=False): @return: (un)converted value """ - _format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) + format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) # call password functions even if raw value should be processed if callable(convert) and (convert==passwordread or convert==passwordwrite): @@ -1345,15 +1396,15 @@ def GetFieldMinMax(fielddef): 'f': (sys.float_info.min, sys.float_info.max), 'd': (sys.float_info.min, sys.float_info.max), } - _format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) + format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) _min = 0 _max = 0 - if _format[-1:] in minmax: - _min, _max = minmax[_format[-1:]] - elif _format[-1:] in ['s','p']: + if format[-1:] in minmax: + _min, _max = minmax[format[-1:]] + elif format[-1:] in ['s','p']: # s and p may have a prefix as length - match = re.search("\s*(\d+)", _format) + match = re.search("\s*(\d+)", format) if match: _max=int(match.group(0)) return _min,_max @@ -1371,7 +1422,7 @@ def GetFieldLength(fielddef): """ length=0 - _format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) + format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) if datadef is not None: # datadef contains a list @@ -1388,10 +1439,10 @@ def GetFieldLength(fielddef): length += GetFieldLength( (fielddef[0], fielddef[1], None) ) else: - if isinstance(_format, dict): - # -> iterate through _format + if isinstance(format, dict): + # -> iterate through format addr = None - setting = _format + setting = format for name in setting: _dummy1, baseaddr, bits, bitshift, _dummy2, _dummy3 = GetFieldDef(setting[name]) _len = GetFieldLength(setting[name]) @@ -1400,17 +1451,17 @@ def GetFieldLength(fielddef): length += _len else: - if _format[-1:] in ['b','B','c','?']: + if format[-1:] in ['b','B','c','?']: length=1 - elif _format[-1:] in ['h','H']: + elif format[-1:] in ['h','H']: length=2 - elif _format[-1:] in ['i','I','l','L','f']: + elif format[-1:] in ['i','I','l','L','f']: length=4 - elif _format[-1:] in ['q','Q','d']: + elif format[-1:] in ['q','Q','d']: length=8 - elif _format[-1:] in ['s','p']: + elif format[-1:] in ['s','p']: # s and p may have a prefix as length - match = re.search("\s*(\d+)", _format) + match = re.search("\s*(\d+)", format) if match: length=int(match.group(0)) @@ -1429,18 +1480,18 @@ def GetSubfieldDef(fielddef): """ subfielddef = None - _format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) + format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) if isinstance(datadef, list) and len(datadef)>1: if len(fielddef)<4: - subfielddef = (_format, MakeFieldBaseAddr(baseaddr, bits, bitshift), datadef[1:]) + subfielddef = (format, MakeFieldBaseAddr(baseaddr, bits, bitshift), datadef[1:]) else: - subfielddef = (_format, MakeFieldBaseAddr(baseaddr, bits, bitshift), datadef[1:], convert) + subfielddef = (format, MakeFieldBaseAddr(baseaddr, bits, bitshift), datadef[1:], convert) # single array else: if len(fielddef)<4: - subfielddef = (_format, MakeFieldBaseAddr(baseaddr, bits, bitshift), None) + subfielddef = (format, MakeFieldBaseAddr(baseaddr, bits, bitshift), None) else: - subfielddef = (_format, MakeFieldBaseAddr(baseaddr, bits, bitshift), None, convert) + subfielddef = (format, MakeFieldBaseAddr(baseaddr, bits, bitshift), None, convert) return subfielddef @@ -1472,7 +1523,7 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): return result # get field definition - _format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) + format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) # contains a integer list if isinstance(datadef, list): @@ -1486,19 +1537,19 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): offset += length # contains a dict - elif isinstance(_format, dict): + elif isinstance(format, dict): config = {} - for name in _format: # -> iterate through _format + for name in format: # -> iterate through format if name != 'raw' or args.jsonrawkeys: - config[name] = GetField(dobj, name, _format[name], raw=raw, addroffset=addroffset) + config[name] = GetField(dobj, name, format[name], raw=raw, addroffset=addroffset) result = config # a simple value - elif isinstance(_format, (str, bool, int, float, long)): + elif isinstance(format, (str, bool, int, float, long)): if GetFieldLength(fielddef) != 0: - result = struct.unpack_from(_format, dobj, baseaddr+addroffset)[0] + result = struct.unpack_from(format, dobj, baseaddr+addroffset)[0] - if not _format[-1:].lower() in ['s','p']: + if not format[-1:].lower() in ['s','p']: if bitshift>=0: result >>= bitshift else: @@ -1507,7 +1558,7 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): result &= (1< 127 @@ -1516,7 +1567,7 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): result = ConvertFieldValue(result, fielddef, read=True, raw=raw) else: - exit(ExitCode.INTERNAL_ERROR, "Wrong mapping format definition: '{}'".format(_format), typ=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) + exit(ExitCode.INTERNAL_ERROR, "Wrong mapping format definition: '{}'".format(format), typ=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) return result @@ -1538,7 +1589,7 @@ def SetField(dobj, fieldname, fielddef, restore, raw=False, addroffset=0, filena @param restore restore mapping with the new value(s) """ - _format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) + format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) fieldname = str(fieldname) if fieldname == 'raw' and not args.jsonrawkeys: @@ -1547,7 +1598,7 @@ def SetField(dobj, fieldname, fielddef, restore, raw=False, addroffset=0, filena # do not write readonly values if isinstance(convert, (list,tuple)) and len(convert)>1 and convert[1]==None: if args.debug: - print >> sys.stderr, "SetField(): Readonly '{}' using '{}'/{}{} @{} skipped".format(fieldname, _format, datadef, bits, hex(baseaddr+addroffset)) + print >> sys.stderr, "SetField(): Readonly '{}' using '{}'/{}{} @{} skipped".format(fieldname, format, datadef, bits, hex(baseaddr+addroffset)) return dobj # contains a list @@ -1569,41 +1620,46 @@ def SetField(dobj, fieldname, fielddef, restore, raw=False, addroffset=0, filena offset += length # contains a dict - elif isinstance(_format, dict): - for name in _format: # -> iterate through _format + elif isinstance(format, dict): + for name in format: # -> iterate through format if name in restore: - dobj = SetField(dobj, name, _format[name], restore[name], raw=raw, addroffset=addroffset, filename=filename) + dobj = SetField(dobj, name, format[name], restore[name], raw=raw, addroffset=addroffset, filename=filename) # a simple value - elif isinstance(_format, (str, bool, int, float, long)): + elif isinstance(format, (str, bool, int, float, long)): valid = True - err = "outside range" + err = "" + errformat = "" _min, _max = GetFieldMinMax(fielddef) - value = _value = valid = None + value = _value = None + skip = False + # simple one value - if _format[-1:] in ['c']: + if format[-1:] in ['c']: try: value = ConvertFieldValue(restore.encode(STR_ENCODING)[0], fielddef, read=False, raw=raw) except: + err = "valid range exceeding" valid = False # bool - elif _format[-1:] in ['?']: + elif format[-1:] in ['?']: try: value = ConvertFieldValue(bool(restore), fielddef, read=False, raw=raw) except: + err = "valid range exceeding" valid = False # integer - elif _format[-1:] in ['b','B','h','H','i','I','l','L','q','Q','P']: + elif format[-1:] in ['b','B','h','H','i','I','l','L','q','Q','P']: try: value = ConvertFieldValue(restore, fielddef, read=False, raw=raw) if isinstance(value, (str, unicode)): value = int(value, 0) else: value = int(value) - # bits + # bit value if bits!=0: - value = struct.unpack_from(_format, dobj, baseaddr+addroffset)[0] + value = struct.unpack_from(format, dobj, baseaddr+addroffset)[0] bitvalue = int(restore) mask = (1<mask: @@ -1611,6 +1667,7 @@ def SetField(dobj, fieldname, fielddef, restore, raw=False, addroffset=0, filena _max = mask _value = bitvalue valid = False + err = "valid bit range exceeding" else: if bitshift>=0: bitvalue <<= bitshift @@ -1620,46 +1677,69 @@ def SetField(dobj, fieldname, fielddef, restore, raw=False, addroffset=0, filena mask >>= abs(bitshift) value &= (0xffffffff ^ mask) value |= bitvalue + # full size values else: _value = value except: valid = False + err = "valid range exceeding" # float - elif _format[-1:] in ['f','d']: + elif format[-1:] in ['f','d']: try: value = ConvertFieldValue(float(restore), fielddef, read=False, raw=raw) except: + err = "valid range exceeding" valid = False # string - elif _format[-1:] in ['s','p']: + elif format[-1:] in ['s','p']: try: value = ConvertFieldValue(restore.encode(STR_ENCODING), fielddef, read=False, raw=raw) - # be aware 0 byte at end of string (str must be < max, not <= max) - _max -= 1 - valid = (len(value)>=_min) and (len(value)<=_max) - err = "string exceeds max length" + err = "string length exceeding" + if value is not None: + # be aware 0 byte at end of string (str must be < max, not <= max) + _max -= 1 + valid = _min <= len(value) < _max + else: + skip = True + valid = True except: valid = False - if value is None: + if value is None and not skip: + # None is an invalid value valid = False - if valid is None: - valid = (value>=_min) and (value<=_max) + + if valid is None and not skip: + # validate against object type size + valid = _min <= value <= _max + if not valid: + err = "type range exceeding" + errformat = " [{smin},{smax}]" + if _value is None: + # copy value before possible change below _value = value + if isinstance(value, (str, unicode)): _value = "'{}'".format(_value) if valid: - if args.debug: - if bits: - sbits=" {} bits shift {}".format(bits, bitshift) - else: - sbits = "" - print >> sys.stderr, "SetField(): Set '{}' using '{}'/{}{} @{} to {}".format(fieldname, _format, datadef, sbits, hex(baseaddr+addroffset), _value) - struct.pack_into(_format, dobj, baseaddr+addroffset, value) + if not skip: + if args.debug: + if bits: + sbits=" {} bits shift {}".format(bits, bitshift) + else: + sbits = "" + print >> sys.stderr, "SetField(): Set '{}' using '{}'/{}{} @{} to {}".format(fieldname, format, datadef, sbits, hex(baseaddr+addroffset), _value) + if fieldname != 'cfg_crc': + prevvalue = struct.unpack_from(format, dobj, baseaddr+addroffset)[0] + struct.pack_into(format, dobj, baseaddr+addroffset, value) + curvalue = struct.unpack_from(format, dobj, baseaddr+addroffset)[0] + if prevvalue != curvalue and args.verbose: + message("Value for '{}' changed from {} to {}".format(fieldname, prevvalue, curvalue), typ=LogType.INFO) else: - exit(ExitCode.RESTORE_DATA_ERROR, "file '{sfile}', value for name '{sname}': {svalue} {serror} [{smin},{smax}]".format(sfile=filename, sname=fieldname, serror=err, svalue=_value, smin=_min, smax=_max), typ=LogType.WARNING, doexit=not args.ignorewarning) + sformat = "file '{sfile}' - {{'{sname}': {svalue}}} ({serror})"+errformat + exit(ExitCode.RESTORE_DATA_ERROR, sformat.format(sfile=filename, sname=fieldname, serror=err, svalue=_value, smin=_min, smax=_max), typ=LogType.WARNING, doexit=not args.ignorewarning) return dobj @@ -1679,23 +1759,26 @@ def Bin2Mapping(decode_cfg, raw=True): if isinstance(decode_cfg, bytearray): decode_cfg = str(decode_cfg) - # get binary header and template to use - version, template, size, setting = GetTemplateSetting(decode_cfg) + # get binary header to use + version, size, setting = GetTemplateSetting(decode_cfg) # if we did not found a mathching setting - if template is None: + if setting is None: exit(ExitCode.UNSUPPORTED_VERSION, "Tasmota configuration version 0x{:x} not supported".format(version),line=inspect.getlineno(inspect.currentframe())) + if 'version' in setting: + cfg_version = GetField(decode_cfg, 'version', setting['version'], raw=True) + # check size if exists if 'cfg_size' in setting: cfg_size = GetField(decode_cfg, 'cfg_size', setting['cfg_size'], raw=True) # read size should be same as definied in template if cfg_size > size: # may be processed - exit(ExitCode.DATA_SIZE_MISMATCH, "Number of bytes read does ot match - read {}, expected {} byte".format(cfg_size, template[1]), typ=LogType.ERROR,line=inspect.getlineno(inspect.currentframe())) + exit(ExitCode.DATA_SIZE_MISMATCH, "Number of bytes read does ot match - read {}, expected {} byte".format(cfg_size, size), typ=LogType.ERROR,line=inspect.getlineno(inspect.currentframe())) elif cfg_size < size: # less number of bytes can not be processed - exit(ExitCode.DATA_SIZE_MISMATCH, "Number of bytes read to small to process - read {}, expected {} byte".format(cfg_size, template[1]), typ=LogType.ERROR,line=inspect.getlineno(inspect.currentframe())) + exit(ExitCode.DATA_SIZE_MISMATCH, "Number of bytes read to small to process - read {}, expected {} byte".format(cfg_size, size), typ=LogType.ERROR,line=inspect.getlineno(inspect.currentframe())) # check crc if exists if 'cfg_crc' in setting: @@ -1719,15 +1802,13 @@ def Bin2Mapping(decode_cfg, raw=True): 'jsonrawkeys': args.jsonrawkeys, 'jsonhidepw': args.jsonhidepw, }, - 'src': { - 'crc': hex(cfg_crc), - 'size': cfg_size, + 'template': { 'version': hex(version), + 'crc': hex(cfg_crc), }, 'data': { 'crc': hex(GetSettingsCrc(decode_cfg)), 'size': len(decode_cfg), - 'version': hex(template[0]), }, 'script': { 'name': os.path.basename(__file__), @@ -1736,6 +1817,10 @@ def Bin2Mapping(decode_cfg, raw=True): 'os': (platform.machine(), platform.system(), platform.release(), platform.version(), platform.platform()), 'python': platform.python_version(), } + if 'cfg_crc' in setting: + config['header']['template'].update({'size': cfg_size}) + if 'version' in setting: + config['header']['data'].update({'version': hex(cfg_version)}) return config @@ -1759,12 +1844,12 @@ def Mapping2Bin(decode_cfg, jsonconfig, filename=""): # get binary header data to use the correct version template from device - version, template, size, setting = GetTemplateSetting(decode_cfg) + version, size, setting = GetTemplateSetting(decode_cfg) _buffer = bytearray() _buffer.extend(decode_cfg) - if template is not None: + if setting is not None: try: raw = jsonconfig['header']['format']['jsonrawvalues'] except: @@ -1828,6 +1913,8 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configuration): if backupfileformat.lower() == FileType.BIN.lower(): fileformat = "binary" backup_filename = MakeFilename(backupfile, FileType.BIN, configuration) + if args.verbose: + message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), typ=LogType.INFO) try: backupfp = open(backup_filename, "wb") magic = BINARYFILE_MAGIC @@ -1842,6 +1929,8 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configuration): if backupfileformat.lower() == FileType.DMP.lower(): fileformat = "Tasmota" backup_filename = MakeFilename(backupfile, FileType.DMP, configuration) + if args.verbose: + message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), typ=LogType.INFO) try: backupfp = open(backup_filename, "wb") backupfp.write(encode_cfg) @@ -1854,6 +1943,8 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configuration): elif backupfileformat.lower() == FileType.JSON.lower(): fileformat = "JSON" backup_filename = MakeFilename(backupfile, FileType.JSON, configuration) + if args.verbose: + message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), typ=LogType.INFO) try: backupfp = open(backup_filename, "w") json.dump(configuration, backupfp, sort_keys=args.jsonsort, indent=None if args.jsonindent<0 else args.jsonindent, separators=(',', ':') if args.jsoncompact else (', ', ': ') ) @@ -1867,7 +1958,7 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configuration): if args.tasmotafile is not None: srctype = 'file' src = args.tasmotafile - message("Backup successful from {} '{}' using {} format to file '{}' ".format(srctype, src, fileformat, backup_filename), typ=LogType.INFO) + message("Backup successful from {} '{}' to file '{}' ({} format)".format(srctype, src, backup_filename, fileformat), typ=LogType.INFO) def Restore(restorefile, encode_cfg, decode_cfg, configuration): @@ -1888,6 +1979,8 @@ def Restore(restorefile, encode_cfg, decode_cfg, configuration): filetype = GetFileType(restorefilename) if filetype == FileType.DMP: + if args.verbose: + message("Reading restore file '{}' (Tasmota format)".format(restorefilename), typ=LogType.INFO) try: restorefp = open(restorefilename, "rb") new_encode_cfg = restorefp.read() @@ -1896,6 +1989,8 @@ def Restore(restorefile, encode_cfg, decode_cfg, configuration): exit(e[0], "'{}' {}".format(restorefilename, e[1]),line=inspect.getlineno(inspect.currentframe())) elif filetype == FileType.BIN: + if args.verbose: + message("Reading restore file '{}' (binary format)".format(restorefilename), typ=LogType.INFO) try: restorefp = open(restorefilename, "rb") restorebin = restorefp.read() @@ -1908,6 +2003,8 @@ def Restore(restorefile, encode_cfg, decode_cfg, configuration): new_encode_cfg = DecryptEncrypt(decode_cfg) # process binary to binary config elif filetype == FileType.JSON or filetype == FileType.INVALID_JSON: + if args.verbose: + message("Reading restore file '{}' (JSON format)".format(restorefilename), typ=LogType.INFO) try: restorefp = open(restorefilename, "r") jsonconfig = json.load(restorefp) @@ -1932,6 +2029,8 @@ def Restore(restorefile, encode_cfg, decode_cfg, configuration): if new_encode_cfg != encode_cfg or args.ignorewarning: # write config direct to device via http if args.device is not None: + if args.verbose: + message("Push new data to '{}' using restore file '{}'".format(args.device, restorefilename), typ=LogType.INFO) error_code, error_str = PushTasmotaConfig(new_encode_cfg, args.device, args.port, args.username, args.password) if error_code: exit(ExitCode.UPLOAD_CONFIG_ERROR, "Config data upload failed - {}".format(error_str),line=inspect.getlineno(inspect.currentframe())) @@ -1941,6 +2040,8 @@ def Restore(restorefile, encode_cfg, decode_cfg, configuration): # write config from a file elif args.tasmotafile is not None: + if args.verbose: + message("Write new data to file '{}' using restore file '{}'".format(args.tasmotafile, restorefilename), typ=LogType.INFO) try: outputfile = open(args.tasmotafile, "wb") outputfile.write(new_encode_cfg) @@ -1955,7 +2056,7 @@ def Restore(restorefile, encode_cfg, decode_cfg, configuration): global exitcode exitcode = ExitCode.RESTORE_SKIPPED if args.verbose: - exit(exitcode, "Configuration data unchanged, upload skipped", typ=LogType.WARNING) + message("Configuration data leaving unchanged", typ=LogType.INFO) def ParseArgs(): @@ -2132,15 +2233,25 @@ if __name__ == "__main__": if args.shorthelp: ShortHelp() - # default no configuration available - encode_cfg = None - # check source args if args.device is not None and args.tasmotafile is not None: exit(ExitCode.ARGUMENT_ERROR, "Unable to select source, do not use -d and -f together",line=inspect.getlineno(inspect.currentframe())) - # pull config from Tasmota device/file - encode_cfg = PullTasmotaConfig() + # default no configuration available + encode_cfg = None + + # pull config from Tasmota device + if args.tasmotafile is not None: + if args.verbose: + message("Load data from file '{}'".format(args.tasmotafile), typ=LogType.INFO) + encode_cfg = LoadTasmotaConfig(args.tasmotafile) + + # load config from Tasmota file + if args.device is not None: + if args.verbose: + message("Load data from device '{}'".format(args.device), typ=LogType.INFO) + encode_cfg = PullTasmotaConfig(args.device, args.port, username=args.username, password=args.password) + if encode_cfg is None: # no config source given ShortHelp(False) @@ -2157,6 +2268,11 @@ if __name__ == "__main__": # decode into mappings dictionary configuration = Bin2Mapping(decode_cfg, args.jsonrawvalues) + if args.verbose and 'version' in configuration: + if args.tasmotafile is not None: + message("File '{}' contains data for Tasmota v{}".format(args.tasmotafile, GetVersionStr(configuration['version'])),typ=LogType.INFO) + else: + message("Device '{}' runs Tasmota v{}".format(args.device,GetVersionStr(configuration['version'])),typ=LogType.INFO) # backup to file if args.backupfile is not None: From 13c6057108fde9f587a9525918c820717a637576 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Wed, 7 Nov 2018 14:05:03 +0100 Subject: [PATCH 0451/2222] update settings to last commit for v6.3.0.4 --- tools/decode-config.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index dd0073d8d..187eec5f3 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -660,11 +660,10 @@ Setting_6_3_0_2['flag'][0].update ({ # ======== Setting_6_3_0_4 = copy.deepcopy(Setting_6_3_0_2) Setting_6_3_0_4.update({ - 'energy_kWhtotal_time': (' Date: Wed, 7 Nov 2018 15:03:41 +0100 Subject: [PATCH 0452/2222] 6.3.0.5 Add code image 6.3.0.5 20181107 * Add code image and optional commit number to version --- sonoff/_changelog.ino | 5 ++++- sonoff/i18n.h | 2 ++ sonoff/sonoff.h | 2 ++ sonoff/sonoff.ino | 19 +++++++++---------- sonoff/sonoff_post.h | 18 ++++++++++++++++++ sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_webserver.ino | 2 +- sonoff/xdrv_02_mqtt.ino | 4 ++-- sonoff/xdrv_13_display.ino | 2 +- 9 files changed, 40 insertions(+), 16 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 08b5942e8..0d508f1a5 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.3.0.4 20181106 +/* 6.3.0.5 20181107 + * Add code image and optional commit number to version + * + * 6.3.0.4 20181106 * Add command SetSensorXX 0/1 to disable/re-enable compiled xsns_XX_sensor.ino driver * * 6.3.0.3 20181105 diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 73e1d0be2..112959a25 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -518,6 +518,8 @@ const char kPrefixes[3][PRFX_MAX_STRING_LENGTH] PROGMEM = { D_STAT, D_TELE }; +const char kCodeImage[] PROGMEM = "sonoff|minimal|classic|sensors|knx|basic|display"; + // support.ino static const char kMonthNames[] = D_MONTH3LIST; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 1e27988e0..d13460e64 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -30,6 +30,8 @@ * Default sensor states \*********************************************************************************************/ +#define CODE_IMAGE 0 + #define USE_DHT // Default DHT11 sensor needs no external library #define USE_ENERGY_SENSOR // Use energy sensors (+14k code) #define USE_HLW8012 // Use energy sensor for Sonoff Pow and WolfBlitz diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 42a541162..d4c38f479 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -193,6 +193,7 @@ boolean mdns_begun = false; // mDNS active mytmplt my_module; // Active copy of Module name and GPIOs (23 x 8 bits) StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits) char my_version[33]; // Composed version string +char my_image[33]; // Code image and/or commit char my_hostname[33]; // Composed Wifi hostname char mqtt_client[33]; // Composed MQTT Clientname char mqtt_topic[33]; // Composed MQTT topic @@ -609,7 +610,6 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) // 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))) { ota_state_flag = 3; -// snprintf_P(mqtt_data, sizeof(mqtt_data), "{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}", command, my_version, Settings.ota_url); snprintf_P(mqtt_data, sizeof(mqtt_data), "{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}", command, my_version, GetOtaUrl(stemp1, sizeof(stemp1))); } else { snprintf_P(mqtt_data, sizeof(mqtt_data), "{\"%s\":\"" D_JSON_ONE_OR_GT "\"}", command, my_version); @@ -1497,8 +1497,8 @@ void PublishStatus(uint8_t payload) } if ((0 == payload) || (2 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"}}"), - my_version, GetBuildDateAndTime().c_str(), ESP.getBootVersion(), ESP.getSdkVersion()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"}}"), + my_version, my_image, GetBuildDateAndTime().c_str(), ESP.getBootVersion(), ESP.getSdkVersion()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); } @@ -2610,13 +2610,12 @@ void setup() Serial.println(); seriallog_level = LOG_LEVEL_INFO; // Allow specific serial messages until config loaded - snprintf_P(my_version, sizeof(my_version), PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff); - if (VERSION & 0xff) { + snprintf_P(my_version, sizeof(my_version), PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff); // Release version 6.3.0 + if (VERSION & 0xff) { // Development or patched version 6.3.0.10 snprintf_P(my_version, sizeof(my_version), PSTR("%s.%d"), my_version, VERSION & 0xff); } -#ifdef BE_MINIMAL - snprintf_P(my_version, sizeof(my_version), PSTR("%s-" D_JSON_MINIMAL), my_version); -#endif // BE_MINIMAL + char code_image[20]; + snprintf_P(my_image, sizeof(my_image), PSTR("(%s)"), GetTextIndexed(code_image, sizeof(code_image), CODE_IMAGE, kCodeImage)); SettingsLoad(); SettingsDelta(); @@ -2731,8 +2730,8 @@ void setup() } blink_powersave = power; - 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-" ARDUINO_ESP8266_RELEASE), - PROJECT, Settings.friendlyname[0], mqtt_topic, mqtt_client, Settings.mqtt_grptopic, my_version); + 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%s-" ARDUINO_ESP8266_RELEASE), + PROJECT, Settings.friendlyname[0], mqtt_topic, mqtt_client, Settings.mqtt_grptopic, my_version, my_image); AddLog(LOG_LEVEL_INFO); #ifdef BE_MINIMAL snprintf_P(log_data, sizeof(log_data), PSTR(D_WARNING_MINIMAL_VERSION)); diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 7498d40e9..86b2c810d 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -57,6 +57,9 @@ void KNX_CB_Action(message_t const &msg, void *arg); #ifdef USE_SENSORS +#undef CODE_IMAGE +#define CODE_IMAGE 3 + #undef USE_ADC_VCC // Add Analog input on selected devices #define USE_DS18x20 // For more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) //#define USE_DS18x20_LEGACY // For more than one DS18x20 sensors with dynamic scan using library OneWire (+1k5 code) @@ -134,6 +137,9 @@ void KNX_CB_Action(message_t const &msg, void *arg); #ifdef USE_CLASSIC +#undef CODE_IMAGE +#define CODE_IMAGE 2 + #ifndef USE_WPS #define USE_WPS // Add support for WPS as initial wifi configuration tool (+33k code, 1k mem (5k mem with core v2.4.2+)) #endif @@ -183,6 +189,9 @@ void KNX_CB_Action(message_t const &msg, void *arg); #ifdef USE_KNX_NO_EMULATION +#undef CODE_IMAGE +#define CODE_IMAGE 4 + #ifndef USE_KNX #define USE_KNX // Enable KNX IP Protocol Support (+23k code, +3k3 mem) #endif @@ -196,6 +205,9 @@ void KNX_CB_Action(message_t const &msg, void *arg); #ifdef USE_DISPLAYS +#undef CODE_IMAGE +#define CODE_IMAGE 6 + #undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) #undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) @@ -229,6 +241,9 @@ void KNX_CB_Action(message_t const &msg, void *arg); #ifdef USE_BASIC +#undef CODE_IMAGE +#define CODE_IMAGE 5 + #undef APP_SLEEP #define APP_SLEEP 1 // Default to sleep = 1 for USE_BASIC @@ -288,6 +303,9 @@ void KNX_CB_Action(message_t const &msg, void *arg); #ifdef BE_MINIMAL +#undef CODE_IMAGE +#define CODE_IMAGE 1 + #undef USE_ENERGY_SENSOR // Disable energy sensors #undef USE_ARDUINO_OTA // Disable support for Arduino OTA #undef USE_WPS // Disable support for WPS as initial wifi configuration tool diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 7bb3242ae..aef909e8a 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06030004 +#define VERSION 0x06030005 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 8352e9820..627cebc52 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1244,7 +1244,7 @@ void HandleInformation() // }2 = String func = FPSTR(HTTP_SCRIPT_INFO_BEGIN); func += F(" const char HTTP_SNS_ANALOG[] PROGMEM = "%s{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = +const char HTTP_SNS_ILLUMINANCE_S[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%s " D_UNIT_LUX "{e}"; // {s} = #if defined(USE_MHZ19) || defined(USE_SENSEAIR) || defined(USE_AZ7798) const char HTTP_SNS_CO2[] PROGMEM = "%s{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = diff --git a/sonoff/xsns_91_max44009.ino b/sonoff/xsns_91_max44009.ino new file mode 100644 index 000000000..499a88eb0 --- /dev/null +++ b/sonoff/xsns_91_max44009.ino @@ -0,0 +1,166 @@ +/* + xsns_91_max44009.ino - MAX44009 ambient light sensor support for Sonoff-Tasmota + + Copyright (C) 2019 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_MAX44009 +/*********************************************************************************************\ + * MAX44009 - Ambient Light Intensity + * + * I2C Address: 0x23 or 0x5C +\*********************************************************************************************/ + +#define XSNS_91 91 + +#define MAX44009_ADDR1 0x4A +#define MAX44009_ADDR2 0x4B +#define REG_CONFIG 0x02 +#define REG_LUMINANCE 0x03 +#define MAX44009_CONTINUOUS_AUTO_MODE 0x80 // Start measurement in automatic, continous mode + +uint8_t max44009_address; +uint8_t max44009_addresses[] = { MAX44009_ADDR1, MAX44009_ADDR2 }; +uint8_t max44009_type = 0; +uint8_t max44009_valid = 0; +float max44009_illuminance = 0; +char max44009_types[] = "MAX44009"; + +bool Max4409Read_lum(void) +{ + if (max44009_valid) { max44009_valid--; } + + /* Select luminance start register */ + Wire.beginTransmission(max44009_address); + Wire.write(REG_LUMINANCE); + Wire.endTransmission(); + + if (2 != Wire.requestFrom(max44009_address, (uint8_t)2)) { return false; } + byte msb = Wire.read(); + byte lsb = Wire.read(); + int exponent = (msb & 0xF0) >> 4; + int mantissa = ((msb & 0x0F) << 4) | (lsb & 0x0F); + max44009_illuminance = pow(2, exponent) * mantissa * 0.045; + + max44009_valid = SENSOR_MAX_MISS; + return true; +} + +/********************************************************************************************/ + +void Max4409Detect(void) +{ + if (max44009_type) { + return; + } + + for (byte i = 0; i < sizeof(max44009_addresses); i++) { + max44009_address = max44009_addresses[i]; + Wire.beginTransmission(max44009_address); + + /* select configuration register iand set mode */ + Wire.write(REG_CONFIG); + Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); + if (!Wire.endTransmission()) { + max44009_type = 1; + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, max44009_types, max44009_address); + AddLog(LOG_LEVEL_DEBUG); + break; + } + } +} + +void Max4409EverySecond(void) +{ + if (90 == (uptime %100)) { + // 1mS + Max4409Detect(); + } + else { + // 1mS + if (max44009_type) { + if (!Max4409Read_lum()) { + AddLogMissed(max44009_types, max44009_valid); +// if (!max44009_valid) { max44009_type = 0; } + } + } + } +} + +void Max4409Show(boolean json) +{ + char illum_str[8]; + + if (max44009_valid) { + + /* convert illuminance to fixed size string */ + if (max44009_illuminance < 10) { + dtostrf(max44009_illuminance, sizeof(illum_str) -1, 3, illum_str); + } else if (max44009_illuminance < 100) { + dtostrf(max44009_illuminance, sizeof(illum_str) -1, 2, illum_str); + } else if (max44009_illuminance < 1000) { + dtostrf(max44009_illuminance, sizeof(illum_str) -1, 1, illum_str); + } else { + dtostrf(max44009_illuminance, sizeof(illum_str) -1, 0, illum_str); + } + + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), mqtt_data, max44009_types, illum_str); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_ILLUMINANCE, illum_str); + } +#endif // USE_DOMOTICZ +#ifdef USE_WEBSERVER + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE_S, mqtt_data, max44009_types, illum_str); +#endif // USE_WEBSERVER + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +boolean Xsns91(byte function) +{ + boolean result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + Max4409Detect(); + break; + case FUNC_EVERY_SECOND: + Max4409EverySecond(); + break; + case FUNC_JSON_APPEND: + Max4409Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_APPEND: + Max4409Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_MAX44009 +#endif // USE_I2C From 7b9c2d6797ee912be2fba61333b65f79893d5cac Mon Sep 17 00:00:00 2001 From: Louis Lagendijk Date: Sat, 12 Jan 2019 23:27:37 +0100 Subject: [PATCH 0846/2222] Added MAX44009 in my_user_config.h --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index a4fbfef7a..537aafaef 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -338,7 +338,7 @@ #define MTX_ADDRESS6 0x76 // [DisplayAddress6] I2C address of sixth 8x8 matrix module #define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module #define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module - + #define USE_MAX44009 // Enable MAX44009 sensor ((I2C address 0x4a 0x4b) +5k2 code) #endif // USE_I2C // -- SPI sensors --------------------------------- From 15e4918238e49e6e8d6ce504b2e0786e49387447 Mon Sep 17 00:00:00 2001 From: lobocobra Date: Sun, 13 Jan 2019 11:00:02 +0100 Subject: [PATCH 0847/2222] As requested in issue 824# by ascillato2, implement split interlock. => Split interlock of SONOFF with more than 2 channel into 2 groups => This is needed for shutter and similar utilization --- sonoff/settings.h | 2 +- sonoff/sonoff.ino | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 618cc03f2..714dee800 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -76,7 +76,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t sleep_normal : 1; // bit 10 (v6.3.0.15) - SetOption60 - Enable normal sleep instead of dynamic sleep uint32_t button_switch_force_local : 1;// bit 11 (v6.3.0.16) - SetOption61 - Force local operation when button/switch topic is set uint32_t no_pullup : 1; // bit 12 (v6.4.1.7) - SetOption62 - Force no pull-up (0 = (no)pull-up, 1 = no pull-up) - uint32_t spare13 : 1; + uint32_t split_interlock : 1; // bit 13 (v6.4.1.8) - SetOption63 - Split interlock on CH4 uint32_t spare14 : 1; uint32_t spare15 : 1; uint32_t spare16 : 1; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 404403d5a..16239e046 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -319,6 +319,23 @@ void SetDevicePower(power_t rpower, int source) power = (1 << devices_present) -1; rpower = power; } + if (Settings.flag3.split_interlock) { + Settings.flag.interlock = 1; // prevent the situation where interlock is off and split-interlock is on + uint8_t mask = 0x01; + uint8_t count = 0; + byte result1 = 0; + byte result2 = 0; + for (byte i = 0; i < devices_present; i++) { + if (rpower & mask) { + if (i <2) { result1++;}//increment if low part is ON + if (i >1) { result2++;}//increment if high part is ON + } + mask <<= 1; // shift the bitmask one left (1,2,4,8) to find out what is on + } + if ((result1) >1 && (result2 >1)) {power = 0; rpower = 0;} // all 4 switch are on, something is wrong, so we turn all off + if ((result1) >1 && (result2 <2)) {power = power & 0x0C; rpower = power;} // 1/2 are both on and 3/4 max one is on + if ((result1) <2 && (result2 >1)) {power = power & 0x03; rpower = power;} // 1/2 max one is on and 3/4 both are on + } else { if (Settings.flag.interlock) { // Allow only one or no relay set power_t mask = 1; uint8_t count = 0; @@ -331,6 +348,7 @@ void SetDevicePower(power_t rpower, int source) rpower = 0; } } + } XdrvMailbox.index = rpower; XdrvCall(FUNC_SET_POWER); // Signal power state @@ -1389,7 +1407,28 @@ void ExecuteCommandPower(byte device, byte state, int source) blink_mask &= (POWER_MASK ^ mask); // Clear device mask MqttPublishPowerBlinkState(device); } - if (Settings.flag.interlock && !interlock_mutex) { // Clear all but masked relay + if (Settings.flag3.split_interlock && !Settings.flag.interlock ) Settings.flag.interlock=1; // ensure interlock is on, in case split_interlock is on + // check if channel 1/2 or 3/4 are to be changed + if (device <= 2 && Settings.flag3.split_interlock ) { // channel 1/2 are changed + if (Settings.flag3.split_interlock && !interlock_mutex) { // Clear all but masked relay, but only if we are not already doing something + interlock_mutex = 1; + for (byte i = 0; i < 2; i++) { + byte imask = 0x01 << i; + if ((power & imask) && (mask != imask)) { ExecuteCommandPower(i +1, POWER_OFF, SRC_IGNORE); delay(50); }// example, first power is ON but the pushed button is not the first, then powerOFF the first one + } + interlock_mutex = 0; // avoid infinite loop due to recursive requests + } + } else { // channel 3/4 are changed + if (Settings.flag3.split_interlock && !interlock_mutex) { // only start if we are on interlock split and have no re-call + interlock_mutex = 1; + for (byte i = 2; i < devices_present; i++) { + byte imask = 0x01 << i; + if ((power & imask) && (mask != imask)) ExecuteCommandPower(i +1, POWER_OFF, SRC_IGNORE); + } + interlock_mutex = 0; + } + } + if ( Settings.flag.interlock && !interlock_mutex && !Settings.flag3.split_interlock) { //execute regular interlock-mode as interlock-split is off interlock_mutex = 1; for (byte i = 0; i < devices_present; i++) { power_t imask = 1 << i; From bab1e4e6acc49d2519537b473e00d50daf16e7e0 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sun, 13 Jan 2019 05:33:54 +0100 Subject: [PATCH 0848/2222] light: improve handling of dimmer_plugin (fix rules) --- sonoff/xdrv_04_light.ino | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 9265e4f67..ef4540401 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -111,6 +111,7 @@ uint8_t light_wheel = 0; uint8_t light_subtype = 0; uint8_t light_device = 0; uint8_t light_power = 0; +uint8_t light_old_power = 1; uint8_t light_update = 1; uint8_t light_wakeup_active = 0; uint8_t light_wakeup_dimmer = 0; @@ -715,11 +716,12 @@ void LightRandomColor(void) void LightSetPower(void) { // light_power = XdrvMailbox.index; + light_old_power = light_power; light_power = bitRead(XdrvMailbox.index, light_device -1); if (light_wakeup_active) { light_wakeup_active--; } - if (light_power) { + if (light_power && !light_old_power) { light_update = 1; } LightAnimate(); @@ -828,7 +830,10 @@ void LightAnimate(void) } } } - XdrvMailbox.index = light_device; + + char *tmp_data = XdrvMailbox.data; + uint16_t tmp_data_len = XdrvMailbox.data_len; + XdrvMailbox.data = (char*)cur_col; XdrvMailbox.data_len = sizeof(cur_col); if (XdrvCall(FUNC_SET_CHANNELS)) { @@ -842,6 +847,8 @@ void LightAnimate(void) else if (light_type > LT_WS2812) { LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); } + XdrvMailbox.data = tmp_data; + XdrvMailbox.data_len = tmp_data_len; } } } From 5b5ad077fd53a0f83d810941211351186431f908 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Sun, 13 Jan 2019 17:33:33 +0100 Subject: [PATCH 0849/2222] decode-config.py: adapt settings - add SetOption63 (split_interlock) --- tools/decode-config.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 53481b791..739314710 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0017' +VER = '2.1.0018' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -824,7 +824,13 @@ Setting_6_4_1_7['flag3'][0].update ({ 'no_pullup': (' Date: Sun, 13 Jan 2019 15:33:27 -0300 Subject: [PATCH 0850/2222] Add template for Luminea ZX2820 https://github.com/arendst/Sonoff-Tasmota/issues/4904 --- sonoff/sonoff_template.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index e15fb9a99..c1f1c3545 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -277,6 +277,7 @@ enum SupportedModules { YTF_IR_BRIDGE, DIGOO, KA10, + ZX2820, MAXMODULE }; /********************************************************************************************/ @@ -568,6 +569,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { PHILIPS, YTF_IR_BRIDGE, WITTY, // Development Devices + ZX2820, WEMOS }; @@ -1737,6 +1739,22 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL1, // GPIO14 Relay 1 0, 0, 0 } + { "Luminea ZX2820", + GPIO_KEY1, // GPIO00 Button + 0, 0, 0, + GPIO_HLW_CF, // GPIO04 HLW8012 CF power + GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 voltage / current + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 HLW8012 SEL (0 = Voltage) + GPIO_LED1_INV, // GPIO13 Green Led - Link and Power status + GPIO_REL1, // GPIO14 Relay + 0, 0, 0 + } }; /* From 2e38c5ba0711775db500a2a203f02818ccf1ab23 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sun, 13 Jan 2019 23:35:33 -0300 Subject: [PATCH 0851/2222] Fix missing , --- sonoff/sonoff_template.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index c1f1c3545..5db27e817 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1738,7 +1738,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED2, // GPIO13 Red LED - Power status GPIO_REL1, // GPIO14 Relay 1 0, 0, 0 - } + }, { "Luminea ZX2820", GPIO_KEY1, // GPIO00 Button 0, 0, 0, From fc1198c1f9203b1ddcd21df8324d0c40eb6785d1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 14 Jan 2019 10:57:01 +0100 Subject: [PATCH 0852/2222] Add features * Add support for Luminea ZX2820 Smart Socket with Energy monitoring (#4921) * Add define MDNS_ENABLE to control initial mDNS state (#4923) * Add split interlock part 1 (#4910) --- sonoff/_changelog.ino | 3 +++ sonoff/my_user_config.h | 3 +++ sonoff/settings.ino | 3 ++- sonoff/sonoff_template.h | 6 +++--- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 8c65c845b..42b97ddcb 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -8,6 +8,9 @@ * Change web authentication (#4865) * Add support for Digoo DG-SP202 Smart Socket with Energy monitoring (#4891) * Add support for Smanergy KA10 Smart Wall Socket with Energy monitoring + * Add support for Luminea ZX2820 Smart Socket with Energy monitoring (#4921) + * Add define MDNS_ENABLE to control initial mDNS state (#4923) + * Add split interlock part 1 (#4910) * * 6.4.1.7 20190106 * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6 diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index a4fbfef7a..706276c22 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -134,6 +134,9 @@ #define FRIENDLY_NAME "Sonoff" // [FriendlyName] Friendlyname up to 32 characters used by webpages and Alexa #define EMULATION EMUL_NONE // [Emulation] Select Belkin WeMo (single relay/light) or Hue Bridge emulation (multi relay/light) (EMUL_NONE, EMUL_WEMO or EMUL_HUE) +// -- mDNS ---------------------------------------- +#define MDNS_ENABLED 0 // [SetOption55] Use mDNS (0 = Disable, 1 = Enable) + // -- Time - Up to three NTP servers in your region #define NTP_SERVER1 "pool.ntp.org" // [NtpServer1] Select first NTP server by name or IP address (129.250.35.250) #define NTP_SERVER2 "nl.pool.ntp.org" // [NtpServer2] Select second NTP server by name or IP address (5.39.184.5) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 055b35566..65f42e979 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -621,6 +621,7 @@ void SettingsDefaultSet2(void) Settings.webserver = WEB_SERVER; Settings.weblog_level = WEB_LOG_LEVEL; strlcpy(Settings.web_password, WEB_PASSWORD, sizeof(Settings.web_password)); + Settings.flag3.mdns_enabled = MDNS_ENABLED; // Button // Settings.flag.button_restrict = 0; @@ -1018,7 +1019,7 @@ void SettingsDelta(void) } } if (Settings.version < 0x06040105) { - Settings.flag3.mdns_enabled = 0; + Settings.flag3.mdns_enabled = MDNS_ENABLED; Settings.param[P_MDNS_DELAYED_START] = 0; } diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 5db27e817..66a83cd1e 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -546,6 +546,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { TECKIN_US, APLIC_WDP303075, GOSUND, + ZX2820, SK03_TUYA, DIGOO, KA10, @@ -569,7 +570,6 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { PHILIPS, YTF_IR_BRIDGE, WITTY, // Development Devices - ZX2820, WEMOS }; @@ -1740,7 +1740,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, 0 }, { "Luminea ZX2820", - GPIO_KEY1, // GPIO00 Button + GPIO_KEY1, // GPIO00 Button 0, 0, 0, GPIO_HLW_CF, // GPIO04 HLW8012 CF power GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 voltage / current @@ -1754,7 +1754,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1_INV, // GPIO13 Green Led - Link and Power status GPIO_REL1, // GPIO14 Relay 0, 0, 0 - } + } }; /* From 2aac0683bee2ed93d8757867989017db19cd3616 Mon Sep 17 00:00:00 2001 From: "dh.harald" Date: Fri, 11 Jan 2019 00:50:40 +0000 Subject: [PATCH 0853/2222] Add support for Mi Desk Lamp --- sonoff/_changelog.ino | 6 +- sonoff/i18n.h | 1 + sonoff/my_user_config.h | 1 + sonoff/settings.h | 2 +- sonoff/settings.ino | 5 ++ sonoff/sonoff.h | 1 + sonoff/sonoff.ino | 2 + sonoff/sonoff_template.h | 23 +++++++ sonoff/sonoff_version.h | 2 +- sonoff/support_rotary.ino | 134 ++++++++++++++++++++++++++++++++++++++ 10 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 sonoff/support_rotary.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 42b97ddcb..90a05184c 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ -/* 6.4.1.8 20190107 +/* 6.4.1.9 20190111 + * Add support for rotary switch + * Add support for Mi Desk Lamp + * + * 6.4.1.8 20190107 * Change sonoff_template.h layout regarding optional module flags like ADC0 * Add command SetOption62 1 to force no Button/Switch pullup on dedicated modules. Currently only supported on Shelly2 (#4841) * Fix Display exception 28 when JSON value is NULL received diff --git a/sonoff/i18n.h b/sonoff/i18n.h index a90028e8d..f12f562da 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -214,6 +214,7 @@ #define D_CMND_COUNTERDEBOUNCE "CounterDebounce" #define D_CMND_BUTTONDEBOUNCE "ButtonDebounce" #define D_CMND_SWITCHDEBOUNCE "SwitchDebounce" +#define D_CMND_ROTARYDEBOUNCE "RotaryDebounce" #define D_CMND_SLEEP "Sleep" #define D_CMND_UPLOAD "Upload" #define D_CMND_UPGRADE "Upgrade" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 706276c22..a364fcf22 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -177,6 +177,7 @@ #define KEY_HOLD_TIME 40 // [SetOption32] Number of 0.1 seconds to hold Button or external Pushbutton before sending HOLD message #define SWITCH_DEBOUNCE_TIME 50 // [SwitchDebounce] Number of mSeconds switch press debounce time #define SWITCH_MODE TOGGLE // [SwitchMode] TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE (the wall switch state) +#define ROTARY_DEBOUNCE_TIME 50 // [RotaryDebounce] Number of mSeconds rotary debounce time #define WS2812_LEDS 30 // [Pixels] Number of WS2812 LEDs to start with (max is 512) #define TEMP_CONVERSION 0 // [SetOption8] Return temperature in (0 = Celsius or 1 = Fahrenheit) diff --git a/sonoff/settings.h b/sonoff/settings.h index 714dee800..e472ff292 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -330,7 +330,7 @@ struct SYSCFG { uint32_t energy_kWhtotal_time; // 7B4 unsigned long weight_item; // 7B8 Weight of one item in gram * 10 - byte free_7BC[2]; // 7BC + uint16_t rotary_debounce; // 7BC uint16_t weight_max; // 7BE Total max weight in kilogram unsigned long weight_reference; // 7C0 Reference weight in gram diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 65f42e979..db0c7cbef 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -789,6 +789,7 @@ void SettingsDefaultSet2(void) SettingsDefaultSet_5_13_1c(); // Time STD/DST settings Settings.button_debounce = KEY_DEBOUNCE_TIME; + Settings.rotary_debounce = ROTARY_DEBOUNCE_TIME; Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; for (byte j = 0; j < 5; j++) { @@ -1023,6 +1024,10 @@ void SettingsDelta(void) Settings.param[P_MDNS_DELAYED_START] = 0; } + if (Settings.version < 0x06040109) { + Settings.rotary_debounce = ROTARY_DEBOUNCE_TIME; + } + Settings.version = VERSION; SettingsSave(1); } diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 59b7a96f2..9cf6e46f2 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -260,5 +260,6 @@ const uint8_t kIFan02Speed[MAX_FAN_SPEED][3] = {{6,6,6}, {7,6,6}, {7,7,6}, {7,6, \*********************************************************************************************/ extern uint8_t light_device; // Light device number +extern uint8_t light_power; // Light power #endif // _SONOFF_H_ diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 16239e046..d4ccbc904 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2362,6 +2362,7 @@ void GpioInit(void) ButtonInit(); SwitchInit(); + RotaryInit(); #ifdef USE_WS2812 if (!light_type && (pin[GPIO_WS2812] < 99)) { // RGB led @@ -2548,6 +2549,7 @@ void loop(void) ButtonLoop(); SwitchLoop(); + RotaryLoop(); if (TimeReached(state_50msecond)) { SetNextTimeInterval(state_50msecond, 50); diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 66a83cd1e..4c2ca84a6 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -146,6 +146,8 @@ enum UserSelectablePins { GPIO_MAX31855CS, // MAX31855 Serial interface GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface + GPIO_ROT_A, // Rotary switch A Pin + GPIO_ROT_B, // Rotary switch B Pin GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -278,6 +280,7 @@ enum SupportedModules { DIGOO, KA10, ZX2820, + MI_DESK_LAMP, MAXMODULE }; /********************************************************************************************/ @@ -503,6 +506,8 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface #endif + GPIO_ROT_A, // Rotary switch A pin + GPIO_ROT_B, // Rotary switch B pin }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { @@ -565,6 +570,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { ARILUX_LC11, ZENGGE_ZF_WF017, HUAFAN_SS, + MI_DESK_LAMP, KMC_70011, AILIGHT, // Light Bulbs PHILIPS, @@ -1754,6 +1760,23 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1_INV, // GPIO13 Green Led - Link and Power status GPIO_REL1, // GPIO14 Relay 0, 0, 0 + }, + { "Mi Desk Lamp", // Mi LED Desk Lamp + // https://www.mi.com/global/smartlamp/ + 0, 0, + GPIO_KEY1, // GPIO02 Button + 0, + GPIO_PWM1, // GPIO04 Cold White + GPIO_PWM2, // GPIO05 Warm White + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, + 0, + // GPIO11 (SD_CMD Flash) + GPIO_ROT_A, // GPIO12 Rotary switch A pin + GPIO_ROT_B, // GPIO13 Rotary switch B pin + 0, 0, 0, 0 } }; diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index f371936aa..534276418 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040108 +#define VERSION 0x06040109 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support_rotary.ino b/sonoff/support_rotary.ino new file mode 100644 index 000000000..842bc7ca5 --- /dev/null +++ b/sonoff/support_rotary.ino @@ -0,0 +1,134 @@ +/* + support_rotary.ino - rotary switch support for Sonoff-Tasmota + + Copyright (C) 2019 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 . +*/ + +#define ROTARY_V1 +#ifdef ROTARY_V1 +/*********************************************************************************************\ + * Rotary support +\*********************************************************************************************/ + +unsigned long rotary_debounce = 0; // Rotary debounce timer +uint8_t rotaries_found = 0; +uint8_t rotary_state = 0; +uint8_t rotary_position = 128; +uint8_t rotary_last_position = 128; +uint8_t interrupts_in_use = 0; + +/********************************************************************************************/ + +void update_position() { + uint8_t s; + + /* + * https://github.com/PaulStoffregen/Encoder/blob/master/Encoder.h + */ + + s = rotary_state & 3; + if (digitalRead(pin[GPIO_ROT_A])) s |= 4; + if (digitalRead(pin[GPIO_ROT_B])) s |= 8; + switch (s) { + case 0: case 5: case 10: case 15: + break; + case 1: case 7: case 8: case 14: + rotary_position++; break; + case 2: case 4: case 11: case 13: + rotary_position--; break; + case 3: case 12: + rotary_position = rotary_position + 2; break; + default: + rotary_position = rotary_position - 2; break; + } + rotary_state = (s >> 2); +} + +void update_rotary() { + if (MI_DESK_LAMP == Settings.module){ + if (light_power) { + update_position(); + } + } +} + +void RotaryInit(void) +{ + rotaries_found = 0; + if (pin[GPIO_ROT_A] < 99 && pin[GPIO_ROT_B] < 99) { + rotaries_found++; + pinMode(pin[GPIO_ROT_A], INPUT_PULLUP); + pinMode(pin[GPIO_ROT_B], INPUT_PULLUP); + + // GPIO6-GPIO11 are typically used to interface with the flash memory IC on + // most esp8266 modules, so we should avoid adding interrupts to these pins. + + if (pin[GPIO_ROT_A] < 6 || pin[GPIO_ROT_A] > 11) { + attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT_A]), update_rotary, CHANGE); + interrupts_in_use++; + } + if (pin[GPIO_ROT_B] < 6 || pin[GPIO_ROT_B] > 11) { + attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT_B]), update_rotary, CHANGE); + interrupts_in_use++; + } + } +} + +/*********************************************************************************************\ + * Rotary handler +\*********************************************************************************************/ + +void RotaryHandler(void) +{ + if (interrupts_in_use < 2) { + noInterrupts(); + update_rotary(); + } else { + noInterrupts(); + } + interrupts(); + + if (rotary_last_position != rotary_position) { + if (MI_DESK_LAMP == Settings.module) { // Mi Desk lamp + int8_t d = Settings.light_dimmer; + d = d + (rotary_position - rotary_last_position); + if (d < 1) { + d = 1; + } + if (d > 100) { + d = 100; + } + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_CMND_DIMMER " %d"), rotary_position - rotary_last_position); + AddLog(LOG_LEVEL_DEBUG); + + LightSetDimmer(d); + Settings.light_dimmer = d; + } + rotary_last_position = rotary_position; + } +} + +void RotaryLoop(void) +{ + if (rotaries_found) { + if (TimeReached(rotary_debounce)) { + SetNextTimeInterval(rotary_debounce, Settings.rotary_debounce); + RotaryHandler(); + } + } +} + +#endif // ROTARY_V1 From 8e43bb38101728af57a759620b7018dfb9b8aea4 Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Fri, 11 Jan 2019 13:08:09 +0200 Subject: [PATCH 0854/2222] Add void's to functions that have no parameters --- sonoff/support_rotary.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/support_rotary.ino b/sonoff/support_rotary.ino index 842bc7ca5..2e1cf8f3d 100644 --- a/sonoff/support_rotary.ino +++ b/sonoff/support_rotary.ino @@ -32,7 +32,7 @@ uint8_t interrupts_in_use = 0; /********************************************************************************************/ -void update_position() { +void update_position(void) { uint8_t s; /* @@ -57,7 +57,7 @@ void update_position() { rotary_state = (s >> 2); } -void update_rotary() { +void update_rotary(void) { if (MI_DESK_LAMP == Settings.module){ if (light_power) { update_position(); From 4952c4d72fa8a24b51d6456e5a2844d545d8d160 Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Fri, 11 Jan 2019 13:12:08 +0200 Subject: [PATCH 0855/2222] Update support_rotary.ino --- sonoff/support_rotary.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/support_rotary.ino b/sonoff/support_rotary.ino index 2e1cf8f3d..6a186bae4 100644 --- a/sonoff/support_rotary.ino +++ b/sonoff/support_rotary.ino @@ -68,7 +68,7 @@ void update_rotary(void) { void RotaryInit(void) { rotaries_found = 0; - if (pin[GPIO_ROT_A] < 99 && pin[GPIO_ROT_B] < 99) { + if ((pin[GPIO_ROT_A] < 99) && (pin[GPIO_ROT_B] < 99)) { rotaries_found++; pinMode(pin[GPIO_ROT_A], INPUT_PULLUP); pinMode(pin[GPIO_ROT_B], INPUT_PULLUP); @@ -76,11 +76,11 @@ void RotaryInit(void) // GPIO6-GPIO11 are typically used to interface with the flash memory IC on // most esp8266 modules, so we should avoid adding interrupts to these pins. - if (pin[GPIO_ROT_A] < 6 || pin[GPIO_ROT_A] > 11) { + if ((pin[GPIO_ROT_A] < 6) || (pin[GPIO_ROT_A] > 11)) { attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT_A]), update_rotary, CHANGE); interrupts_in_use++; } - if (pin[GPIO_ROT_B] < 6 || pin[GPIO_ROT_B] > 11) { + if ((pin[GPIO_ROT_B] < 6) || (pin[GPIO_ROT_B] > 11)) { attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT_B]), update_rotary, CHANGE); interrupts_in_use++; } From b5ad2c8c06adc08545ef22e2c9b307d086a7ea3f Mon Sep 17 00:00:00 2001 From: Peter Nyilas Date: Fri, 11 Jan 2019 13:59:51 +0000 Subject: [PATCH 0856/2222] Remove rotary_debounce from settings --- sonoff/_changelog.ino | 10 ++++------ sonoff/i18n.h | 1 - sonoff/my_user_config.h | 1 - sonoff/settings.h | 2 +- sonoff/settings.ino | 5 ----- sonoff/sonoff_version.h | 2 +- sonoff/support_rotary.ino | 2 +- 7 files changed, 7 insertions(+), 16 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 90a05184c..1d133a47d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,8 +1,4 @@ -/* 6.4.1.9 20190111 - * Add support for rotary switch - * Add support for Mi Desk Lamp - * - * 6.4.1.8 20190107 +/* 6.4.1.8 20190107 * Change sonoff_template.h layout regarding optional module flags like ADC0 * Add command SetOption62 1 to force no Button/Switch pullup on dedicated modules. Currently only supported on Shelly2 (#4841) * Fix Display exception 28 when JSON value is NULL received @@ -15,7 +11,9 @@ * Add support for Luminea ZX2820 Smart Socket with Energy monitoring (#4921) * Add define MDNS_ENABLE to control initial mDNS state (#4923) * Add split interlock part 1 (#4910) - * + * Add support for rotary switch + * Add support for Mi Desk Lamp + * * 6.4.1.7 20190106 * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6 * Add Power status functionality to LED2 when configured leaving LED1 for Link status indication diff --git a/sonoff/i18n.h b/sonoff/i18n.h index f12f562da..a90028e8d 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -214,7 +214,6 @@ #define D_CMND_COUNTERDEBOUNCE "CounterDebounce" #define D_CMND_BUTTONDEBOUNCE "ButtonDebounce" #define D_CMND_SWITCHDEBOUNCE "SwitchDebounce" -#define D_CMND_ROTARYDEBOUNCE "RotaryDebounce" #define D_CMND_SLEEP "Sleep" #define D_CMND_UPLOAD "Upload" #define D_CMND_UPGRADE "Upgrade" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index a364fcf22..706276c22 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -177,7 +177,6 @@ #define KEY_HOLD_TIME 40 // [SetOption32] Number of 0.1 seconds to hold Button or external Pushbutton before sending HOLD message #define SWITCH_DEBOUNCE_TIME 50 // [SwitchDebounce] Number of mSeconds switch press debounce time #define SWITCH_MODE TOGGLE // [SwitchMode] TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE (the wall switch state) -#define ROTARY_DEBOUNCE_TIME 50 // [RotaryDebounce] Number of mSeconds rotary debounce time #define WS2812_LEDS 30 // [Pixels] Number of WS2812 LEDs to start with (max is 512) #define TEMP_CONVERSION 0 // [SetOption8] Return temperature in (0 = Celsius or 1 = Fahrenheit) diff --git a/sonoff/settings.h b/sonoff/settings.h index e472ff292..714dee800 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -330,7 +330,7 @@ struct SYSCFG { uint32_t energy_kWhtotal_time; // 7B4 unsigned long weight_item; // 7B8 Weight of one item in gram * 10 - uint16_t rotary_debounce; // 7BC + byte free_7BC[2]; // 7BC uint16_t weight_max; // 7BE Total max weight in kilogram unsigned long weight_reference; // 7C0 Reference weight in gram diff --git a/sonoff/settings.ino b/sonoff/settings.ino index db0c7cbef..65f42e979 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -789,7 +789,6 @@ void SettingsDefaultSet2(void) SettingsDefaultSet_5_13_1c(); // Time STD/DST settings Settings.button_debounce = KEY_DEBOUNCE_TIME; - Settings.rotary_debounce = ROTARY_DEBOUNCE_TIME; Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; for (byte j = 0; j < 5; j++) { @@ -1024,10 +1023,6 @@ void SettingsDelta(void) Settings.param[P_MDNS_DELAYED_START] = 0; } - if (Settings.version < 0x06040109) { - Settings.rotary_debounce = ROTARY_DEBOUNCE_TIME; - } - Settings.version = VERSION; SettingsSave(1); } diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 534276418..f371936aa 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040109 +#define VERSION 0x06040108 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support_rotary.ino b/sonoff/support_rotary.ino index 6a186bae4..9c7600b09 100644 --- a/sonoff/support_rotary.ino +++ b/sonoff/support_rotary.ino @@ -125,7 +125,7 @@ void RotaryLoop(void) { if (rotaries_found) { if (TimeReached(rotary_debounce)) { - SetNextTimeInterval(rotary_debounce, Settings.rotary_debounce); + SetNextTimeInterval(rotary_debounce, Settings.button_debounce); // Using button_debounce setting for this as well RotaryHandler(); } } From 9f030ae431e3789d0c8ee3907f02939c864906aa Mon Sep 17 00:00:00 2001 From: "dh.harald" Date: Tue, 15 Jan 2019 00:45:19 +0000 Subject: [PATCH 0857/2222] Change color temp with rotary when Button1 pressed --- sonoff/sonoff.h | 1 + sonoff/support_button.ino | 24 +++++++++++--------- sonoff/support_rotary.ino | 47 ++++++++++++++++++++++++++------------- 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 9cf6e46f2..c520d3981 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -261,5 +261,6 @@ const uint8_t kIFan02Speed[MAX_FAN_SPEED][3] = {{6,6,6}, {7,6,6}, {7,7,6}, {7,6, extern uint8_t light_device; // Light device number extern uint8_t light_power; // Light power +extern uint8_t rotary_changed; // Rotary switch changed #endif // _SONOFF_H_ diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index ed5cecce6..dd4b298c8 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -203,19 +203,23 @@ void ButtonHandler(void) multipress[button_index] = 1; } } + if ((MI_DESK_LAMP == Settings.module) && (button_index == 0) && (rotary_changed) && (light_power)) { + rotary_changed = 0; // Color temp changed, no need to turn of the light + } else { if (single_press && SendKey(0, button_index + multipress[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set // Success } else { - if (multipress[button_index] < 3) { // Single or Double press - if (WifiState() > WIFI_RESTART) { // WPSconfig, Smartconfig or Wifimanager active - restart_flag = 1; - } else { - ExecuteCommandPower(button_index + multipress[button_index], POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally - } - } else { // 3 - 7 press - if (!Settings.flag.button_restrict) { - snprintf_P(scmnd, sizeof(scmnd), kCommands[multipress[button_index] -3]); - ExecuteCommand(scmnd, SRC_BUTTON); + if (multipress[button_index] < 3) { // Single or Double press + if (WifiState() > WIFI_RESTART) { // WPSconfig, Smartconfig or Wifimanager active + restart_flag = 1; + } else { + ExecuteCommandPower(button_index + multipress[button_index], POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally + } + } else { // 3 - 7 press + if (!Settings.flag.button_restrict) { + snprintf_P(scmnd, sizeof(scmnd), kCommands[multipress[button_index] -3]); + ExecuteCommand(scmnd, SRC_BUTTON); + } } } } diff --git a/sonoff/support_rotary.ino b/sonoff/support_rotary.ino index 9c7600b09..d11450858 100644 --- a/sonoff/support_rotary.ino +++ b/sonoff/support_rotary.ino @@ -29,6 +29,7 @@ uint8_t rotary_state = 0; uint8_t rotary_position = 128; uint8_t rotary_last_position = 128; uint8_t interrupts_in_use = 0; +uint8_t rotary_changed = 0; /********************************************************************************************/ @@ -99,26 +100,42 @@ void RotaryHandler(void) } else { noInterrupts(); } - interrupts(); - if (rotary_last_position != rotary_position) { if (MI_DESK_LAMP == Settings.module) { // Mi Desk lamp - int8_t d = Settings.light_dimmer; - d = d + (rotary_position - rotary_last_position); - if (d < 1) { - d = 1; - } - if (d > 100) { - d = 100; - } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_CMND_DIMMER " %d"), rotary_position - rotary_last_position); - AddLog(LOG_LEVEL_DEBUG); + if (holdbutton[0]) { + rotary_changed = 1; + // button1 is pressed: set color temperature + int16_t t = LightGetColorTemp(); + t = t + (rotary_position - rotary_last_position); + if (t < 153) { + t = 153; + } + if (t > 500) { + t = 500; + } + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_CMND_COLORTEMPERATURE " %d"), rotary_position - rotary_last_position); + AddLog(LOG_LEVEL_DEBUG); + LightSetColorTemp((uint16_t)t); + } else { + int8_t d = Settings.light_dimmer; + d = d + (rotary_position - rotary_last_position); + if (d < 1) { + d = 1; + } + if (d > 100) { + d = 100; + } + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_CMND_DIMMER " %d"), rotary_position - rotary_last_position); + AddLog(LOG_LEVEL_DEBUG); - LightSetDimmer(d); - Settings.light_dimmer = d; + LightSetDimmer((uint8_t)d); + Settings.light_dimmer = d; + } } - rotary_last_position = rotary_position; + rotary_last_position = 128; + rotary_position = 128; } + interrupts(); } void RotaryLoop(void) From fbf8370b4acc76815d4cef6772ef3e37db3718ad Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 15 Jan 2019 15:35:13 +0100 Subject: [PATCH 0858/2222] Update sonoff_template.h Move rotary GPIO to non-user config for now. --- sonoff/sonoff_template.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 4c2ca84a6..5de0caf74 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -146,8 +146,6 @@ enum UserSelectablePins { GPIO_MAX31855CS, // MAX31855 Serial interface GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface - GPIO_ROT_A, // Rotary switch A Pin - GPIO_ROT_B, // Rotary switch B Pin GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -165,6 +163,8 @@ enum ProgramSelectablePins { GPIO_DI, // my92x1 PWM input GPIO_DCKI, // my92x1 CLK input GPIO_ARIRFRCV, // AliLux RF Receive input + GPIO_ROT_A, // Rotary switch A Pin + GPIO_ROT_B, // Rotary switch B Pin GPIO_USER, // User configurable GPIO_MAX }; @@ -506,8 +506,6 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface #endif - GPIO_ROT_A, // Rotary switch A pin - GPIO_ROT_B, // Rotary switch B pin }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { From e5fd45c9c82fa5bdd341ef947b7814b99db3bb64 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 15 Jan 2019 16:11:42 +0100 Subject: [PATCH 0859/2222] 6.4.1.9 Fix mDNS addService 6.4.1.9 20190115 * Add support for Mi LED Desk Lamp with rotary switch (#4887) * Fix mDNS addService (#4938) --- sonoff/_changelog.ino | 10 ++++++---- sonoff/sonoff.ino | 1 - sonoff/sonoff_template.h | 11 +++++------ sonoff/sonoff_version.h | 2 +- sonoff/support_button.ino | 14 +++++++------- sonoff/support_rotary.ino | 8 +++++--- sonoff/support_wifi.ino | 8 +++++--- 7 files changed, 29 insertions(+), 25 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 1d133a47d..704e95d67 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ -/* 6.4.1.8 20190107 +/* 6.4.1.9 20190115 + * Add support for Mi LED Desk Lamp with rotary switch (#4887) + * Fix mDNS addService (#4938) + * + * 6.4.1.8 20190107 * Change sonoff_template.h layout regarding optional module flags like ADC0 * Add command SetOption62 1 to force no Button/Switch pullup on dedicated modules. Currently only supported on Shelly2 (#4841) * Fix Display exception 28 when JSON value is NULL received @@ -11,9 +15,7 @@ * Add support for Luminea ZX2820 Smart Socket with Energy monitoring (#4921) * Add define MDNS_ENABLE to control initial mDNS state (#4923) * Add split interlock part 1 (#4910) - * Add support for rotary switch - * Add support for Mi Desk Lamp - * + * * 6.4.1.7 20190106 * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6 * Add Power status functionality to LED2 when configured leaving LED1 for Link status indication diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index d4ccbc904..f16a3ba10 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -167,7 +167,6 @@ byte syslog_level; // Current copy of Settings.syslog_l //byte mdns_delayed_start = 0; // mDNS delayed start boolean latest_uptime_flag = true; // Signal latest uptime boolean pwm_present = false; // Any PWM channel configured with SetOption15 0 -boolean mdns_begun = false; // mDNS active myio my_module; // Active copy of Module GPIOs (17 x 8 bits) gpio_flag my_module_flag; // Active copy of Module GPIO flags StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 5de0caf74..39eb8737d 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1759,8 +1759,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL1, // GPIO14 Relay 0, 0, 0 }, - { "Mi Desk Lamp", // Mi LED Desk Lamp - // https://www.mi.com/global/smartlamp/ + { "Mi Desk Lamp", // Mi LED Desk Lamp - https://www.mi.com/global/smartlamp/ 0, 0, GPIO_KEY1, // GPIO02 Button 0, @@ -1769,11 +1768,11 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { // GPIO06 (SD_CLK Flash) // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, - 0, + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) // GPIO11 (SD_CMD Flash) - GPIO_ROT_A, // GPIO12 Rotary switch A pin - GPIO_ROT_B, // GPIO13 Rotary switch B pin + GPIO_ROT_A, // GPIO12 Rotary switch A pin + GPIO_ROT_B, // GPIO13 Rotary switch B pin 0, 0, 0, 0 } }; diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index f371936aa..534276418 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040108 +#define VERSION 0x06040109 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index dd4b298c8..b058b685a 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -204,18 +204,18 @@ void ButtonHandler(void) } } if ((MI_DESK_LAMP == Settings.module) && (button_index == 0) && (rotary_changed) && (light_power)) { - rotary_changed = 0; // Color temp changed, no need to turn of the light + rotary_changed = 0; // Color temp changed, no need to turn of the light } else { - if (single_press && SendKey(0, button_index + multipress[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set - // Success - } else { - if (multipress[button_index] < 3) { // Single or Double press - if (WifiState() > WIFI_RESTART) { // WPSconfig, Smartconfig or Wifimanager active + if (single_press && SendKey(0, button_index + multipress[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set + // Success + } else { + if (multipress[button_index] < 3) { // Single or Double press + if (WifiState() > WIFI_RESTART) { // WPSconfig, Smartconfig or Wifimanager active restart_flag = 1; } else { ExecuteCommandPower(button_index + multipress[button_index], POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally } - } else { // 3 - 7 press + } else { // 3 - 7 press if (!Settings.flag.button_restrict) { snprintf_P(scmnd, sizeof(scmnd), kCommands[multipress[button_index] -3]); ExecuteCommand(scmnd, SRC_BUTTON); diff --git a/sonoff/support_rotary.ino b/sonoff/support_rotary.ino index d11450858..726f45379 100644 --- a/sonoff/support_rotary.ino +++ b/sonoff/support_rotary.ino @@ -33,7 +33,8 @@ uint8_t rotary_changed = 0; /********************************************************************************************/ -void update_position(void) { +void update_position(void) +{ uint8_t s; /* @@ -58,7 +59,8 @@ void update_position(void) { rotary_state = (s >> 2); } -void update_rotary(void) { +void update_rotary(void) +{ if (MI_DESK_LAMP == Settings.module){ if (light_power) { update_position(); @@ -132,7 +134,7 @@ void RotaryHandler(void) Settings.light_dimmer = d; } } - rotary_last_position = 128; + rotary_last_position = 128; rotary_position = 128; } interrupts(); diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 817577900..0971d104a 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -41,6 +41,7 @@ uint8_t wifi_status; uint8_t wps_result; uint8_t wifi_config_type = 0; uint8_t wifi_config_counter = 0; +uint8_t mdns_begun = 0; // mDNS active uint8_t wifi_scan_state; uint8_t wifi_bssid[6]; @@ -492,7 +493,7 @@ void WifiCheck(uint8_t param) // mdns_delayed_start--; // } else { // mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; - mdns_begun = MDNS.begin(my_hostname); + mdns_begun = (uint8_t)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); // } @@ -505,7 +506,8 @@ void WifiCheck(uint8_t param) StartWebserver(Settings.webserver, WiFi.localIP()); #ifdef USE_DISCOVERY #ifdef WEBSERVER_ADVERTISE - if (mdns_begun) { + if (1 == mdns_begun) { + mdns_begun = 2; MDNS.addService("http", "tcp", WEB_PORT); } #endif // WEBSERVER_ADVERTISE @@ -530,7 +532,7 @@ void WifiCheck(uint8_t param) #if defined(USE_WEBSERVER) && defined(USE_EMULATION) UdpDisconnect(); #endif // USE_EMULATION - mdns_begun = false; + mdns_begun = 0; #ifdef USE_KNX knx_started = false; #endif // USE_KNX From 0186a97cb0ad9964455cdfb95dff80527eb2de70 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 15 Jan 2019 16:30:20 +0100 Subject: [PATCH 0860/2222] Fix allowable MAX_RULE_VARS to 16 Fix allowable MAX_RULE_VARS to 16 (#4933) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_10_rules.ino | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 704e95d67..27b47a02f 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.4.1.9 20190115 * Add support for Mi LED Desk Lamp with rotary switch (#4887) * Fix mDNS addService (#4938) + * Fix allowable MAX_RULE_VARS to 16 (#4933) * * 6.4.1.8 20190107 * Change sonoff_template.h layout regarding optional module flags like ADC0 diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index df2db9748..5c43db43c 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -95,13 +95,13 @@ uint8_t rules_teleperiod = 0; char event_data[100]; char vars[MAX_RULE_VARS][33] = { 0 }; -#if (MAX_RULE_VARS>8) -#error MAX_RULE_VARS is bigger than 8 +#if (MAX_RULE_VARS>16) +#error MAX_RULE_VARS is bigger than 16 #endif -#if (MAX_RULE_MEMS>8) -#error MAX_RULE_MEMS is bigger than 8 +#if (MAX_RULE_MEMS>5) +#error MAX_RULE_MEMS is bigger than 5 #endif -uint8_t vars_event = 0; +uint16_t vars_event = 0; uint8_t mems_event = 0; /*******************************************************************************************/ From 44ea65a389457acf79111a1d2072f949505e249d Mon Sep 17 00:00:00 2001 From: andrethomas Date: Tue, 15 Jan 2019 22:03:55 +0200 Subject: [PATCH 0861/2222] PN532: Segregate UID and DATA usage --- sonoff/my_user_config.h | 5 +++-- sonoff/xsns_40_pn532_i2c.ino | 38 +++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 706276c22..c3524c127 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -325,8 +325,9 @@ // #define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) // #define USE_RTC_ADDR 0x68 // Default I2C address 0x68 // #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) -// #define USE_PN532_I2C // Enable PN532 - Near Field Communication (NFC) controller (+3k3 code, 508 bytes of mem) -// #define USE_PN532_CAUSE_EVENTS // Enable PN532 driver to cause event's on card read in addition to immediate telemetry +// #define USE_PN532_I2C // Enable PN532 - Near Field Communication (NFC) controller (+1k7 code, 164 bytes of mem) +// #define USE_PN532_DATA_FUNCTION // Enable PN532 DATA Usage using Sensor15 command (+1k6 code, 316 bytes of mem) +// #define USE_PN532_CAUSE_EVENTS // Enable PN532 driver to cause event's on card read in addition to immediate telemetry (+64 bytes code, 48 bytes mem) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index 567b19a77..c2fdf65e7 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -61,9 +61,13 @@ uint8_t pn532_i2c_detected = 0; uint8_t pn532_i2c_packetbuffer[64]; uint8_t pn532_i2c_scan_defer_report = 0; // If a valid card was found we will not scan for one again in the same two seconds so we set this to 19 if a card was found uint8_t pn532_i2c_command = 0; + uint8_t pn532_i2c_disable = 0; + +#ifdef USE_PN532_DATA_FUNCTION uint8_t pn532_i2c_function = 0; uint8_t pn532_i2c_newdata[16]; +#endif // USE_PN532_DATA_FUNCTION const uint8_t PROGMEM pn532_global_timeout = 10; @@ -285,6 +289,8 @@ boolean PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *u return true; } +#ifdef USE_PN532_DATA_FUNCTION + uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData) { uint8_t i; @@ -370,6 +376,7 @@ uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data) return (0 < PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer))); } +#endif // USE_PN532_DATA_FUNCTION void PN532_ScanForTag(void) { @@ -384,11 +391,17 @@ void PN532_ScanForTag(void) pn532_i2c_scan_defer_report--; } else { char uids[15]; + +#ifdef USE_PN532_DATA_FUNCTION char card_datas[34]; +#endif // USE_PN532_DATA_FUNCTION + sprintf(uids,""); for (uint8_t i = 0;i < uid_len;i++) { sprintf(uids,"%s%02X",uids,uid[i]); } + +#ifdef USE_PN532_DATA_FUNCTION if (uid_len == 4) { // Lets try to read block 0 of the mifare classic card for more information uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) { @@ -435,17 +448,28 @@ void PN532_ScanForTag(void) break; } pn532_i2c_function = 0; +#endif // USE_PN532_DATA_FUNCTION + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + +#ifdef USE_PN532_DATA_FUNCTION snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), mqtt_data, uids, card_datas); +#else + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids); +#endif // USE_PN532_DATA_FUNCTION + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -#ifdef USE_PN532_CAUSE_EVENTS +#ifdef USE_PN532_CAUSE_EVENTS char command[71]; +#ifdef USE_PN532_DATA_FUNCTION sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas); +#else + sprintf(command,"event PN532_UID=%s",uids); +#endif // USE_PN532_DATA_FUNCTION ExecuteCommand(command, SRC_RULE); - -#endif +#endif // USE_PN532_CAUSE_EVENTS pn532_i2c_scan_defer_report = 7; // Ignore tags found for two seconds } @@ -454,6 +478,8 @@ void PN532_ScanForTag(void) } } +#ifdef USE_PN532_DATA_FUNCTION + boolean PN532_Command(void) { boolean serviced = true; @@ -500,6 +526,8 @@ boolean PN532_Command(void) } } +#endif // USE_PN532_DATA_FUNCTION + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -518,11 +546,15 @@ boolean Xsns40(byte function) case FUNC_EVERY_SECOND: PN532_Detect(); break; + +#ifdef USE_PN532_DATA_FUNCTION case FUNC_COMMAND: if (XSNS_40 == XdrvMailbox.index) { result = PN532_Command(); } break; +#endif // USE_PN532_DATA_FUNCTION + case FUNC_SAVE_BEFORE_RESTART: if (!pn532_i2c_disable) { pn532_i2c_disable = 1; From d2d07543b2a3d46fbc2f100ef94c60e816a1f139 Mon Sep 17 00:00:00 2001 From: Mike <7153163+hackbar@users.noreply.github.com> Date: Tue, 15 Jan 2019 17:26:51 -0800 Subject: [PATCH 0862/2222] Do an MDNS resolve before using the cached host. MDNS shouldn't be aggressively cached, since the IP could change. This makes using DHCP for the host a lot easier. --- sonoff/xdrv_02_mqtt.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 1d3c3a4b8..ae84d1940 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -516,7 +516,7 @@ void MqttReconnect(void) #ifndef USE_MQTT_TLS #ifdef USE_DISCOVERY #ifdef MQTT_HOST_DISCOVERY - if (!strlen(Settings.mqtt_host) && !MqttDiscoverServer()) { return; } + if (!MqttDiscoverServer() && !strlen(Settings.mqtt_host)) { return; } #endif // MQTT_HOST_DISCOVERY #endif // USE_DISCOVERY #endif // USE_MQTT_TLS From 5e06ae1d8197b17069c92a3b7e61f4a0621d8c6c Mon Sep 17 00:00:00 2001 From: Mike <7153163+hackbar@users.noreply.github.com> Date: Tue, 15 Jan 2019 18:08:28 -0800 Subject: [PATCH 0863/2222] Do MDNS even if TLS is enabled. I imagine this was disabled due to memory issues, but this seems to work fine on a Sonoff Basic. --- sonoff/xdrv_02_mqtt.ino | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index ae84d1940..58204dd9a 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -513,13 +513,11 @@ void MqttReconnect(void) mqtt_retry_counter = Settings.mqtt_retry; global_state.mqtt_down = 1; -#ifndef USE_MQTT_TLS #ifdef USE_DISCOVERY #ifdef MQTT_HOST_DISCOVERY if (!MqttDiscoverServer() && !strlen(Settings.mqtt_host)) { return; } #endif // MQTT_HOST_DISCOVERY #endif // USE_DISCOVERY -#endif // USE_MQTT_TLS char *mqtt_user = NULL; char *mqtt_pwd = NULL; @@ -585,13 +583,11 @@ void MqttCheck(void) if (!MqttIsConnected()) { global_state.mqtt_down = 1; if (!mqtt_retry_counter) { -#ifndef USE_MQTT_TLS #ifdef USE_DISCOVERY #ifdef MQTT_HOST_DISCOVERY if (!strlen(Settings.mqtt_host) && !mdns_begun) { return; } #endif // MQTT_HOST_DISCOVERY #endif // USE_DISCOVERY -#endif // USE_MQTT_TLS MqttReconnect(); } else { mqtt_retry_counter--; From 838b113fa34a128c90bf26a66c60cb9886706ed0 Mon Sep 17 00:00:00 2001 From: Mike <7153163+hackbar@users.noreply.github.com> Date: Tue, 15 Jan 2019 21:48:07 -0800 Subject: [PATCH 0864/2222] Add a define for mDNS hostname to connect to for MQTT. --- sonoff/xdrv_02_mqtt.ino | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 58204dd9a..4321cb7b0 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -220,9 +220,19 @@ boolean MqttDiscoverServer(void) AddLog(LOG_LEVEL_INFO); if (n > 0) { - // Note: current strategy is to get the first MQTT service (even when many are found) + #ifdef MDNS_HOSTNAME + for (int i = 0; i < n; i++) { + if (!strcmp(MDNS.hostname(i).c_str(), MDNS_HOSTNAME)) { + snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(i).toString().c_str()); + Settings.mqtt_port = MDNS.port(i); + break; // stop at the first matching record + } + } + #else + // If the hostname isn't set, use the first record found. snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(0).toString().c_str()); Settings.mqtt_port = MDNS.port(0); + #endif // MDNS_HOSTNAME snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), MDNS.hostname(0).c_str(), Settings.mqtt_host, Settings.mqtt_port); From b074d94ef43951258177582601e4b7464fbf9d6c Mon Sep 17 00:00:00 2001 From: araczkowski Date: Wed, 16 Jan 2019 17:53:23 +0100 Subject: [PATCH 0865/2222] #4938 MDNS.update(); --- sonoff/support_wifi.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 0971d104a..de2cb9b9c 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -350,6 +350,10 @@ void WifiCheckIp(void) Settings.ip_address[3] = (uint32_t)WiFi.dnsIP(); } wifi_status = WL_CONNECTED; + if (2 == mdns_begun) { + MDNS.update(); + AddLog_P(LOG_LEVEL_DEBUG_MORE, D_LOG_MDNS, "MDNS.update"); + } } else { WifiSetState(0); uint8_t wifi_config_tool = Settings.sta_config; From 01ecc12f13283b4bef9202dc2723ac67aff360bf Mon Sep 17 00:00:00 2001 From: andrethomas Date: Thu, 17 Jan 2019 01:22:51 +0200 Subject: [PATCH 0866/2222] PN532: Prevent non AlphaNumberic on DATA --- sonoff/xsns_40_pn532_i2c.ino | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index c2fdf65e7..dd5fb4aba 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -406,7 +406,13 @@ void PN532_ScanForTag(void) uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) { if (mifareclassic_ReadDataBlock(1, card_data)) { - memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string + for (uint8_t i = 0;i < sizeof(card_data);i++) { + if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) { + card_datas[i] = char(card_data[i]); + } else { + card_datas[i] = '\0'; + } + } } if (pn532_i2c_function == 1) { // erase block 1 of card for (uint8_t i = 0;i<16;i++) { From 66c39ce88c60b628ff9d9109ea1d19b38d77ceca Mon Sep 17 00:00:00 2001 From: andrethomas Date: Thu, 17 Jan 2019 02:10:22 +0200 Subject: [PATCH 0867/2222] PN532: Prevent non AlphaNumberic on DATA --- sonoff/xsns_40_pn532_i2c.ino | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index dd5fb4aba..a03b30e6b 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -67,6 +67,7 @@ uint8_t pn532_i2c_disable = 0; #ifdef USE_PN532_DATA_FUNCTION uint8_t pn532_i2c_function = 0; uint8_t pn532_i2c_newdata[16]; +uint8_t pn532_i2c_newdata_len = 0; #endif // USE_PN532_DATA_FUNCTION const uint8_t PROGMEM pn532_global_timeout = 10; @@ -426,12 +427,23 @@ void PN532_ScanForTag(void) } } if (pn532_i2c_function == 2) { - memcpy(&card_data,&pn532_i2c_newdata,sizeof(card_data)); - if (mifareclassic_WriteDataBlock(1, card_data)) { - set_success = true; - snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful"); + boolean IsAlphaNumeric = true; + for (uint8_t i = 0;i < pn532_i2c_newdata_len;i++) { + if ((!isalpha(pn532_i2c_newdata[i])) || (!isdigit(pn532_i2c_newdata[i]))) { + IsAlphaNumeric = false; + } + } + if (IsAlphaNumeric) { + if (mifareclassic_WriteDataBlock(1, card_data)) { + memcpy(&card_data,&pn532_i2c_newdata,sizeof(card_data)); + set_success = true; + snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful"); + AddLog(LOG_LEVEL_INFO); + memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string + } + } else { + snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data must be alphanumeric"); AddLog(LOG_LEVEL_INFO); - memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string } } } else { @@ -518,10 +530,10 @@ boolean PN532_Command(void) return serviced; } sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2)); - uint8_t dlen = strlen(sub_string_tmp); - if (dlen > 15) { dlen = 15; } - memcpy(&pn532_i2c_newdata,&sub_string_tmp,dlen); - pn532_i2c_newdata[dlen] = 0x00; // Null terminate the string + pn532_i2c_newdata_len = strlen(sub_string_tmp); + if (pn532_i2c_newdata_len > 15) { pn532_i2c_newdata_len = 15; } + memcpy(&pn532_i2c_newdata,&sub_string_tmp,pn532_i2c_newdata_len); + pn532_i2c_newdata[pn532_i2c_newdata_len] = 0x00; // Null terminate the string pn532_i2c_function = 2; snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Next scanned tag data block 1 will be set to '%s'",pn532_i2c_newdata); AddLog(LOG_LEVEL_INFO); From 6f173a59c3021df13bc86371c6df92587b7ef1ee Mon Sep 17 00:00:00 2001 From: araczkowski Date: Thu, 17 Jan 2019 12:34:06 +0100 Subject: [PATCH 0868/2222] fix MDNS.update(); between ifdefs --- sonoff/support_wifi.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index de2cb9b9c..6f19546a3 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -350,10 +350,14 @@ void WifiCheckIp(void) Settings.ip_address[3] = (uint32_t)WiFi.dnsIP(); } wifi_status = WL_CONNECTED; +#ifdef USE_DISCOVERY +#ifdef WEBSERVER_ADVERTISE if (2 == mdns_begun) { MDNS.update(); AddLog_P(LOG_LEVEL_DEBUG_MORE, D_LOG_MDNS, "MDNS.update"); } +#endif // USE_DISCOVERY +#endif // WEBSERVER_ADVERTISE } else { WifiSetState(0); uint8_t wifi_config_tool = Settings.sta_config; From 092aba945f87128141fb22fe5f41b71eaa8e1eb2 Mon Sep 17 00:00:00 2001 From: Daniel Schroeder Date: Thu, 17 Jan 2019 15:29:41 +0100 Subject: [PATCH 0869/2222] Tiny typo fix in comment --- sonoff/user_config_override_sample.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/user_config_override_sample.h b/sonoff/user_config_override_sample.h index b2b403e1a..9a48d2d50 100644 --- a/sonoff/user_config_override_sample.h +++ b/sonoff/user_config_override_sample.h @@ -20,7 +20,7 @@ #ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ -// force the compiler to show a warning to confirm that this file is inlcuded +// force the compiler to show a warning to confirm that this file is included #warning **** user_config_override.h: Using Settings from this File **** /*****************************************************************************************************\ @@ -93,4 +93,4 @@ Examples : -#endif // _USER_CONFIG_OVERRIDE_H_ \ No newline at end of file +#endif // _USER_CONFIG_OVERRIDE_H_ From e7e378f463bf9a3232506d671d1b85be5aad69bd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 17 Jan 2019 17:48:34 +0100 Subject: [PATCH 0870/2222] Add (S)SerialSend features * Fix mDNS addService (#4938, #4951) * Add (S)SerialSend3 escape sequence \x to allow hexadecimal byte value (#3560, #4947) * Add SerialBridge command SSerialSend5 --- sonoff/_changelog.ino | 4 +++- sonoff/sonoff.ino | 4 ++-- sonoff/support.ino | 27 ++++++++++++++++++++------- sonoff/xdrv_08_serial_bridge.ino | 24 ++++++++++++++++++++---- sonoff/xnrg_03_pzem004t.ino | 2 +- sonoff/xnrg_04_mcp39f501.ino | 2 +- sonoff/xnrg_05_pzem_ac.ino | 2 +- sonoff/xnrg_06_pzem_dc.ino | 2 +- sonoff/xsns_15_mhz19.ino | 2 +- sonoff/xsns_18_pms5003.ino | 2 +- sonoff/xsns_20_novasds.ino | 2 +- sonoff/xsns_38_az7798.ino | 2 +- 12 files changed, 53 insertions(+), 22 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 27b47a02f..2d77e925f 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,7 +1,9 @@ /* 6.4.1.9 20190115 * Add support for Mi LED Desk Lamp with rotary switch (#4887) - * Fix mDNS addService (#4938) + * Fix mDNS addService (#4938, #4951) * Fix allowable MAX_RULE_VARS to 16 (#4933) + * Add (S)SerialSend3 escape sequence \x to allow hexadecimal byte value (#3560, #4947) + * Add SerialBridge command SSerialSend5 * * 6.4.1.8 20190107 * Change sonoff_template.h layout regarding optional module flags like ADC0 diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index f16a3ba10..a4fe3bf38 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1051,7 +1051,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) Serial.printf("%s", Unescape(dataBuf, &dat_len)); // "Hello\f" } else if (5 == index) { - SerialSendRaw(RemoveSpace(dataBuf)); // "AA004566" + SerialSendRaw(RemoveSpace(dataBuf)); // "AA004566" as hex values } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } @@ -1427,7 +1427,7 @@ void ExecuteCommandPower(byte device, byte state, int source) interlock_mutex = 0; } } - if ( Settings.flag.interlock && !interlock_mutex && !Settings.flag3.split_interlock) { //execute regular interlock-mode as interlock-split is off + if ( Settings.flag.interlock && !interlock_mutex && !Settings.flag3.split_interlock) { //execute regular interlock-mode as interlock-split is off interlock_mutex = 1; for (byte i = 0; i < devices_present; i++) { power_t imask = 1 << i; diff --git a/sonoff/support.ino b/sonoff/support.ino index 55be05df7..148ae8783 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -210,10 +210,12 @@ char* Unescape(char* buffer, uint16_t* size) { uint8_t* read = (uint8_t*)buffer; uint8_t* write = (uint8_t*)buffer; - uint16_t start_size = *size; - uint16_t end_size = *size; + int16_t start_size = *size; + int16_t end_size = *size; uint8_t che = 0; +// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)buffer, *size); + while (start_size > 0) { uint8_t ch = *read++; start_size--; @@ -235,6 +237,14 @@ char* Unescape(char* buffer, uint16_t* size) case 's': che = ' '; break; // 20 Space case 't': che = '\t'; break; // 09 Horizontal tab case 'v': che = '\v'; break; // 0B Vertical tab + case 'x': { + uint8_t* start = read; + che = (uint8_t)strtol((const char*)read, (char**)&read, 16); + start_size -= (uint16_t)(read - start); + end_size -= (uint16_t)(read - start); + break; + } + case '"': che = '\"'; break; // 22 Quotation mark // case '?': che = '\?'; break; // 3F Question mark default : { che = chi; @@ -247,6 +257,9 @@ char* Unescape(char* buffer, uint16_t* size) } } *size = end_size; + +// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)buffer, *size); + return buffer; } @@ -511,7 +524,7 @@ void ModuleGpios(myio *gp) memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio)); // 11 85 00 85 85 00 00 00 15 38 85 00 00 81 -// AddLogSerial(LOG_LEVEL_DEBUG, (uint8_t *)&src, sizeof(mycfgio)); +// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)&src, sizeof(mycfgio)); for (uint8_t i = 0; i < sizeof(mycfgio); i++) { if (i < 6) { @@ -526,7 +539,7 @@ void ModuleGpios(myio *gp) } // 11 85 00 85 85 00 00 00 00 00 00 00 15 38 85 00 00 81 -// AddLogSerial(LOG_LEVEL_DEBUG, (uint8_t *)gp, sizeof(myio)); +// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)gp, sizeof(myio)); } gpio_flag ModuleFlag() @@ -1197,9 +1210,9 @@ void AddLog_P(byte loglevel, const char *formatP, const char *formatP2) AddLog(loglevel); } -void AddLogSerial(byte loglevel, uint8_t *buffer, int count) +void AddLogBuffer(byte loglevel, uint8_t *buffer, int count) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SERIAL D_RECEIVED)); + snprintf_P(log_data, sizeof(log_data), PSTR("DMP:")); for (int i = 0; i < count; i++) { snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, *(buffer++)); } @@ -1208,7 +1221,7 @@ void AddLogSerial(byte loglevel, uint8_t *buffer, int count) void AddLogSerial(byte loglevel) { - AddLogSerial(loglevel, (uint8_t*)serial_in_buffer, serial_in_byte_counter); + AddLogBuffer(loglevel, (uint8_t*)serial_in_buffer, serial_in_byte_counter); } void AddLogMissed(char *sensor, uint8_t misses) diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 08a4f7211..80ec37178 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -99,18 +99,34 @@ boolean SerialBridgeCommand(void) if (-1 == command_code) { serviced = false; // Unknown command } - else if ((CMND_SSERIALSEND == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { - if (XdrvMailbox.data_len > 0) { + else if ((CMND_SSERIALSEND == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { + if (XdrvMailbox.data_len > 0) { // "Hello Tiger\n" if (1 == XdrvMailbox.index) { SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); SerialBridgeSerial->write("\n"); } - else if (2 == XdrvMailbox.index) { + else if ((2 == XdrvMailbox.index) || (4 == XdrvMailbox.index)) { // "Hello Tiger" or "A0" SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); } - else if (3 == XdrvMailbox.index) { + else if (3 == XdrvMailbox.index) { // "Hello\f" SerialBridgeSerial->write(Unescape(XdrvMailbox.data, &XdrvMailbox.data_len), XdrvMailbox.data_len); } + else if (5 == XdrvMailbox.index) { // "AA004566" as hex values + char *p; + char stemp[3]; + uint8_t code; + + char *codes = RemoveSpace(XdrvMailbox.data); + int size = strlen(XdrvMailbox.data); + + while (size > 0) { + snprintf(stemp, sizeof(stemp), codes); + code = strtol(stemp, &p, 16); + SerialBridgeSerial->write(code); + size -= 2; + codes += 2; + } + } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } } diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index 846c14431..34bff43fe 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -122,7 +122,7 @@ bool PzemRecieve(uint8_t resp, float *data) } } - AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, len); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, len); if (len != sizeof(PZEMCommand)) { // AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Pzem comms timeout")); diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index 0301bf040..1ff04fb7d 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -143,7 +143,7 @@ void McpSend(uint8_t *data) data[0] = MCP_START_FRAME; data[data[1] -1] = McpChecksum(data); -// AddLogSerial(LOG_LEVEL_DEBUG_MORE, data, data[1]); +// AddLogBuffer(LOG_LEVEL_DEBUG_MORE, data, data[1]); for (byte i = 0; i < data[1]; i++) { Serial.write(data[i]); diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index a171b4079..f01ebad3e 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -46,7 +46,7 @@ void PzemAcEverySecond(void) uint8_t buffer[26]; uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, 10); - AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); if (error) { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PzemAc response error %d"), error); diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index 2adda5092..536cb4b97 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -46,7 +46,7 @@ void PzemDcEverySecond(void) uint8_t buffer[22]; uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, 8); - AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); if (error) { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PzemDc response error %d"), error); diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index d04d5a0c5..bc8e46ada 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -198,7 +198,7 @@ void MhzEverySecond(void) } } - AddLogSerial(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); if (counter < 9) { // AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 comms timeout")); diff --git a/sonoff/xsns_18_pms5003.ino b/sonoff/xsns_18_pms5003.ino index 50ad9f7af..1f048134a 100644 --- a/sonoff/xsns_18_pms5003.ino +++ b/sonoff/xsns_18_pms5003.ino @@ -62,7 +62,7 @@ boolean PmsReadData(void) PmsSerial->readBytes(buffer, 32); PmsSerial->flush(); // Make room for another burst - AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, 32); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 32); // get checksum ready for (uint8_t i = 0; i < 30; i++) { diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index e3e1e48e9..1f94dea6a 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -108,7 +108,7 @@ bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensor // read rest (9 of 10 bytes) of message NovaSdsSerial->readBytes(&recbuf[1], 9); - AddLogSerial(LOG_LEVEL_DEBUG_MORE, recbuf, sizeof(recbuf)); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, recbuf, sizeof(recbuf)); if ( NULL != buffer ) { // return data to buffer diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino index d53b657c7..433b380b0 100644 --- a/sonoff/xsns_38_az7798.ino +++ b/sonoff/xsns_38_az7798.ino @@ -158,7 +158,7 @@ void AzEverySecond(void) } } while(((millis() - start) < AZ_READ_TIMEOUT) && (counter < sizeof(az_response)) && !az_received); - AddLogSerial(LOG_LEVEL_DEBUG_MORE, az_response, counter); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, az_response, counter); if (!az_received) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 comms timeout")); From c963900709ee8fe014ce71c670a5aea1dfff6055 Mon Sep 17 00:00:00 2001 From: Mike <7153163+hackbar@users.noreply.github.com> Date: Thu, 17 Jan 2019 19:09:58 -0800 Subject: [PATCH 0871/2222] If the MDNS hostname is set, use it to verify the cert name. --- sonoff/xdrv_02_mqtt.ino | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 4321cb7b0..0b903f463 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -495,7 +495,19 @@ boolean MqttCheckTls(void) AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "2")); result = true; } -#endif +#ifdef MDNS_HOSTNAME + // If the hostname is set, check that as well. + // This lets certs with the hostname for the CN be used. + else if (EspClient.verify(fingerprint1, MDNS_HOSTNAME)) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "1")); + result = true; + } + else if (EspClient.verify(fingerprint2, MDNS_HOSTNAME)) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "2")); + result = true; + } +#endif // MDNS_HOSTNAME +#endif // USE_MQTT_TLS_CA_CERT } if (!result) AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_FAILED)); EspClient.stop(); From b5824fc361505ba645b5e84c9825202f03a98c6e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Jan 2019 10:52:18 +0100 Subject: [PATCH 0872/2222] Housekeeping --- sonoff/settings.h | 4 +--- sonoff/sonoff.ino | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 714dee800..a6f846aec 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -271,9 +271,7 @@ struct SYSCFG { uint8_t ws_color[4][3]; // 475 uint8_t ws_width[3]; // 481 myio my_gp; // 484 - - byte free_495[1]; // 495 - + uint8_t test_step; // 495 uint16_t light_pixels; // 496 uint8_t light_color[5]; // 498 uint8_t light_correction; // 49D diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index a4fe3bf38..878a24d50 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2445,12 +2445,14 @@ void setup(void) Settings.rule_enabled = 0; // Disable all rules } if (RtcReboot.fast_reboot_count > 4) { // Restarted 5 times - Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic -// Settings.last_module = SONOFF_BASIC; for (byte i = 0; i < sizeof(Settings.my_gp); i++) { Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors } } + if (RtcReboot.fast_reboot_count > 5) { // Restarted 6 times + Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic +// Settings.last_module = SONOFF_BASIC; + } snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); AddLog(LOG_LEVEL_DEBUG); } From 99bb6977bf9dad2b43c8455dfc65ffc36f03d979 Mon Sep 17 00:00:00 2001 From: Staars Date: Fri, 18 Jan 2019 22:10:22 +0100 Subject: [PATCH 0873/2222] make tsl2561 compatible with SHT3x --- sonoff/xsns_16_tsl2561.ino | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index 063adfb87..07c95941e 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -48,7 +48,6 @@ bool Tsl2561Read(void) uint16_t scaledFull, scaledIr; uint32_t full, ir; - if (Tsl.available()) { if (Tsl.on()) { if (Tsl.id(id) && Tsl2561Util::autoGain(Tsl, gain, exposure, scaledFull, scaledIr) @@ -58,7 +57,6 @@ bool Tsl2561Read(void) tsl2561_milliLux = 0; } } - } tsl2561_valid = SENSOR_MAX_MISS; return true; } @@ -67,9 +65,9 @@ void Tsl2561Detect(void) { if (tsl2561_type) { return; } - if (!Tsl.available()) { + if (I2cDevice(0x29) || I2cDevice(0x39) || I2cDevice(0x49)) { Tsl.begin(); - if (Tsl.available()) { + if (Tsl.on()) { tsl2561_type = 1; snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, tsl2561_types, Tsl.address()); AddLog(LOG_LEVEL_DEBUG); @@ -88,7 +86,7 @@ void Tsl2561EverySecond(void) if (tsl2561_type) { if (!Tsl2561Read()) { AddLogMissed(tsl2561_types, tsl2561_valid); -// if (!tsl2561_valid) { tsl2561_type = 0; } + if (!tsl2561_valid) { tsl2561_type = 0; } } } } From c6ddba8fd71dc849a3d3049820ec0c8a338bb81a Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Sat, 19 Jan 2019 14:37:22 +0000 Subject: [PATCH 0874/2222] Started SM16716 support --- sonoff/language/bg-BG.h | 2 + sonoff/language/cs-CZ.h | 2 + sonoff/language/de-DE.h | 2 + sonoff/language/en-GB.h | 2 + sonoff/language/es-AR.h | 2 + sonoff/language/fr-FR.h | 2 + sonoff/language/he-HE.h | 2 + sonoff/language/hu-HU.h | 2 + sonoff/language/it-IT.h | 2 + sonoff/language/nl-NL.h | 2 + sonoff/language/pl-PL.h | 2 + sonoff/language/pt-BR.h | 2 + sonoff/language/pt-PT.h | 2 + sonoff/language/ru-RU.h | 2 + sonoff/language/sk-SK.h | 2 + sonoff/language/sv-SE.h | 2 + sonoff/language/tr-TR.h | 2 + sonoff/language/uk-UK.h | 2 + sonoff/language/zh-CN.h | 2 + sonoff/language/zh-TW.h | 2 + sonoff/xdrv_20_sm16717.ino | 325 +++++++++++++++++++++++++++++++++++++ 21 files changed, 365 insertions(+) create mode 100644 sonoff/xdrv_20_sm16717.ino diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index d7d812385..03c1b9f32 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index e10ec2c4f..c87260f71 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index bea56f0f6..692c74e17 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 4ac9186e5..9644e8b4d 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 8add1a3ba..a2f8bcf8a 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index aca69fac6..b9fa0d423 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index d4b41f0b5..22f9677b5 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index ee071da54..b6dd5b55a 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 5ebef743d..fa3c0b533 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 1235ab26d..684545acf 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 6327f87d0..bc4dad5ca 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 8f1364771..1d708f072 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index f863a2148..baa0e28a5 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 20f9a2d9f..19c09a7fc 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 0edd9bea0..e2551f9bc 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 21246a8f3..2b7b672a4 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 3ef7dd3f5..bdab28afb 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 59d9ab8b4..4e3c255d5 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index c64c1b5c3..d4ff8eba8 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 3560ddf34..186c5bae3 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/xdrv_20_sm16717.ino b/sonoff/xdrv_20_sm16717.ino new file mode 100644 index 000000000..98416019c --- /dev/null +++ b/sonoff/xdrv_20_sm16717.ino @@ -0,0 +1,325 @@ +/* + xdrv_20_sm16716.ino - SM16716 RGB led controller support for Sonoff-Tasmota + + Copyright (C) 2019 Gabor Simon + + 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_SM16716 +/*********************************************************************************************\ + * SM16716 - Controlling RGB over a synchronous serial line + * + * Source: https://community.home-assistant.io/t/cheap-uk-wifi-bulbs-with-tasmota-teardown-help-tywe3s/40508/27 + * +\*********************************************************************************************/ + +#define D_LOG_SM16716 "SM16716: " +#define XDRV_20 20 + +#define CLK_USEC 10 // Clock interval in microseconds + +enum SM16716_Commands { + CMND_SM16716_POWER, CMND_SM16716_DIMMER, CMND_SM16716_COLOR }; + +const char k_SM16716_Commands[] PROGMEM = + D_CMND_POWER "|" D_CMND_DIMMER "|" D_CMND_COLOR ; + +uint8_t sm61716_pin_clk = 100; +uint8_t sm61716_pin_dat = 100; + +uint8_t sm61716_colour[3] = {0, 0, 0}; + +uint8_t sm61716_eff_red = 0; +uint8_t sm61716_eff_green = 0; +uint8_t sm61716_eff_blue = 0; + +int8_t sm61716_colour_preset = 0; + +/*********************************************************************************************/ + +void SM16716_SendBit(uint8_t v) +{ + digitalWrite(sm61716_pin_dat, v ? HIGH : LOW); + digitalWrite(sm61716_pin_clk, HIGH); + delayMicroseconds(CLK_USEC); + digitalWrite(sm61716_pin_clk, LOW); + delayMicroseconds(CLK_USEC); +} + +void SM16716_SendByte(uint8_t v) +{ + uint8_t mask; + + for (mask = 0x80; mask; mask >>= 1) + SM16716_SendBit(v & mask); +} + +/*********************************************************************************************/ +void SM16716_Append_JSON(void) +{ + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Append_JSON;")); + AddLog(LOG_LEVEL_DEBUG); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SM16716\":{\"Red\":%d,\"Green\":%d,\"Blue\":%d}"), mqtt_data, sm61716_colour[0], sm61716_colour[1], sm61716_colour[2]); +} + +/*********************************************************************************************/ +boolean SM16716_Show_State(void) +{ + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_COLOR "\":\"%02x%02x%02x\"}"), + sm61716_colour[0], sm61716_colour[1], sm61716_colour[2]); + return true; +} + +/*********************************************************************************************/ +void SM16716_Update() +{ + uint8_t eff_red, eff_green, eff_blue; + + if (Settings.power) { // any bit is ok for us + eff_red = (uint16_t)sm61716_colour[0] * Settings.light_dimmer / 100; + eff_green = (uint16_t)sm61716_colour[1] * Settings.light_dimmer / 100; + eff_blue = (uint16_t)sm61716_colour[2] * Settings.light_dimmer / 100; + } + else { + eff_red = eff_green = eff_blue = 0; + } + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Update; pwr=%02x, rgb=%02x%02x%02x, dimmer=%d, eff=%02x%02x%02x"), + Settings.power, sm61716_colour[0], sm61716_colour[1], sm61716_colour[2], Settings.light_dimmer, eff_red, eff_green, eff_blue); + AddLog(LOG_LEVEL_DEBUG); + + if ((eff_red != sm61716_eff_red) || (eff_green != sm61716_eff_green) || (eff_blue != sm61716_eff_blue)) { + sm61716_eff_red = eff_red; + sm61716_eff_green = eff_green; + sm61716_eff_blue = eff_blue; + + SM16716_SendBit(1); + SM16716_SendByte(eff_red); + SM16716_SendByte(eff_green); + SM16716_SendByte(eff_blue); + } + SM16716_Show_State(); +} + +/*********************************************************************************************/ +boolean SM16716_ModuleSelected(void) +{ + sm61716_pin_clk = pin[GPIO_SM16716_CLK]; + sm61716_pin_dat = pin[GPIO_SM16716_DAT]; + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), sm61716_pin_clk, sm61716_pin_dat); + AddLog(LOG_LEVEL_DEBUG); + return (sm61716_pin_clk < 99) && (sm61716_pin_dat < 99); +} + +/*********************************************************************************************/ +boolean SM16716_Init(void) +{ + uint8_t t_init; + if (!SM16716_ModuleSelected()) + return false; + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Init;")); + + pinMode(sm61716_pin_clk, OUTPUT); + digitalWrite(sm61716_pin_clk, LOW); + + pinMode(sm61716_pin_dat, OUTPUT); + digitalWrite(sm61716_pin_dat, LOW); + + AddLog(LOG_LEVEL_DEBUG); + for (t_init = 0; t_init < 50; ++t_init) + SM16716_SendBit(0); + + return true; +} + +boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { + char component[3]; + char *endptr = NULL; + uint8_t candidate[3]; + int i; + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Parse_RRGGBB; data='%s', data_len=%d"), data, data_len); + AddLog(LOG_LEVEL_DEBUG); + + if (data_len != 6) + return false; + + component[2] = '\0'; + + for (i = 0; i < 3; ++i) { + component[0] = data[0]; + component[1] = data[1]; + candidate[i] = (uint8_t)strtoul(component, &endptr, 16); + if (!endptr || *endptr) + return false; + data += 2; + } + + sm61716_colour[0] = candidate[0]; + sm61716_colour[1] = candidate[1]; + sm61716_colour[2] = candidate[2]; + return true; +} + +boolean SM16716_Parse_Colour(char *data, int data_len) { + /* NOTE: Very similar to 'LightColorEntry', but it's not reusable, because + * 'light_type' must be PWM, but then it won't parse the colour components. + * It's indeed more effective to not do the parsing when the current light + * type couldn't handle it, but enum LightTypes is not to be changed, so + * I can't implement new light types. + * + * If the parsing/handling of light attributes were separated from the + * technical details of actually sending it to the device, then only the + * device-specific parts should've been adapted, but unfortunately this is + * not the case here, so, here we go */ + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Parse_Colour; data='%s', data_len=%d"), data, data_len); + AddLog(LOG_LEVEL_DEBUG); + + if (data_len < 3) { // Colour preset + switch (data[0]) { + case '+': + ++sm61716_colour_preset; + if (sm61716_colour_preset >= MAX_FIXED_COLOR) + sm61716_colour_preset = 0; + break; + + case '-': + --sm61716_colour_preset; + if (sm61716_colour_preset < 0) + sm61716_colour_preset = MAX_FIXED_COLOR - 1; + break; + + default: + { + char *endptr = NULL; + uint8_t candidate = (uint8_t)strtoul(data, &endptr, 10); + if (!endptr || *endptr || (candidate < 0) || (MAX_FIXED_COLOR <= candidate)) + return false; + sm61716_colour_preset = candidate; + } + break; + } + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Parse_Colour; preset=%d"), sm61716_colour_preset); + AddLog(LOG_LEVEL_DEBUG); + memcpy_P(sm61716_colour, &kFixedColor[sm61716_colour_preset], 3); + } + else if (data[0] == '#') { // #RRGGBB + if (!SM16716_Parse_RRGGBB(data + 1, data_len - 1)) + return false; + } + else if (SM16716_Parse_RRGGBB(data, data_len)) { // RRGGBB + } + else { // rrr,g,bb + uint8_t candidate[3]; + char *tok, *last, *endptr = NULL; + int i; + + for (i = 0; i < 3; ++i) { + tok = strtok_r(data, ",", &last); + if (!tok) + return false; + candidate[i] = (uint8_t)strtoul(tok, &endptr, 0); + if (!endptr || *endptr) + return false; + data = NULL; + } + tok = strtok_r(NULL, ",", &last); + if (tok) + return false; // junk at the end + sm61716_colour[0] = candidate[0]; + sm61716_colour[1] = candidate[1]; + sm61716_colour[2] = candidate[2]; + } + return true; +} + +/*********************************************************************************************/ +bool SM16716_Command(void) +{ + char command [CMDSZ]; + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, k_SM16716_Commands); + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Command; topic='%s', data_len=%d, data='%s', code=%d"), + XdrvMailbox.topic, XdrvMailbox.data_len, XdrvMailbox.data, command_code); + AddLog(LOG_LEVEL_DEBUG); + + switch (command_code) { + case CMND_SM16716_POWER: + SM16716_Update(); + return false; // Don't catch the event, only handle the change + + case CMND_SM16716_DIMMER: + SM16716_Update(); + return false; // Don't catch the event, only handle the change + + case CMND_SM16716_COLOR: + if (XdrvMailbox.data_len == 0) + return SM16716_Show_State(); + if (!SM16716_Parse_Colour(XdrvMailbox.data, XdrvMailbox.data_len)) + return false; + SM16716_Update(); + return true; + } + return false; // Unknown command +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ +boolean Xdrv20(byte function) +{ + //snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Xdrv20; function=%d, index=%d"), function, XdrvMailbox.index); + //AddLog(LOG_LEVEL_DEBUG); + + switch (function) { + case FUNC_MODULE_INIT: + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_MODULE_INIT")); + AddLog(LOG_LEVEL_DEBUG); + return SM16716_ModuleSelected(); + + case FUNC_INIT: + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_INIT")); + AddLog(LOG_LEVEL_DEBUG); + return SM16716_Init(); + + case FUNC_COMMAND: + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_COMMAND")); + AddLog(LOG_LEVEL_DEBUG); + return SM16716_Command(); + + case FUNC_SET_POWER: + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_SET_POWER, index=%02x, payload=%02x"), XdrvMailbox.index, XdrvMailbox.payload); + AddLog(LOG_LEVEL_DEBUG); + return false; + + case FUNC_SET_DEVICE_POWER: + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_SET_DEVICE_POWER, index=%02x, payload=%02x"), XdrvMailbox.index, XdrvMailbox.payload); + AddLog(LOG_LEVEL_DEBUG); + return false; + + case FUNC_JSON_APPEND: + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_JSON_APPEND")); + AddLog(LOG_LEVEL_DEBUG); + SM16716_Append_JSON(); + break; + } + return false; +} + +#endif // USE_SM16716 + +// vim: set ft=c sw=2 ts=2 et: From a5059a7a93e7f774361808993ebafed13840ec9e Mon Sep 17 00:00:00 2001 From: Mikka20 Date: Sat, 19 Jan 2019 22:32:12 +0100 Subject: [PATCH 0875/2222] Update README.md Please fix this typo :-) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 09354028a..1d2ad635b 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ If you want to compile Sonoff-Tasmota yourself keep in mind the following: - Only Flash Mode **DOUT** is supported. Do not use Flash Mode DIO / QIO / QOUT as it might seem to brick your device. See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Theo's-Tasmota-Tips) for background information. - Sonoff-Tasmota uses a 1M linker script WITHOUT spiffs **1M (no SPIFFS)** for optimal code space. If you compile using ESP/Arduino library 2.3.0 then download the provided new linker script to your Arduino IDE or Platformio base folder. Later version of ESP/Arduino library already contain the correct linker script. See [Wiki > Prerequisite](https://github.com/arendst/Sonoff-Tasmota/wiki/Prerequisite). -- To make compile time changes to Sonoff-Tasmota it can use the ``user_config_override.h`` file. It assures keeping your settings when you download and compile a new version. To use ``user_config.override.h`` you will have to make a copy of the provided ``user_config.override_sample.h`` file and add your setting overrides. To enable the override file you will need to use a compile define as documented in the ``user_config_override_sample.h`` file. +- To make compile time changes to Sonoff-Tasmota it can use the ``user_config_override.h`` file. It assures keeping your settings when you download and compile a new version. To use ``user_config.override.h`` you will have to make a copy of the provided ``user_config_override_sample.h`` file and add your setting overrides. To enable the override file you will need to use a compile define as documented in the ``user_config_override_sample.h`` file. ### Version Information - Sonoff-Tasmota provides all (Sonoff) modules in one file and starts with module Sonoff Basic. From 08512fc5fa6ea028edc3da49403ed4578fbbe7f8 Mon Sep 17 00:00:00 2001 From: Louis Lagendijk Date: Sat, 19 Jan 2019 23:27:12 +0100 Subject: [PATCH 0876/2222] First draft of better MAX44009 detection --- sonoff/xsns_91_max44009.ino | 100 +++++++++++++++++++++++++++--------- 1 file changed, 75 insertions(+), 25 deletions(-) diff --git a/sonoff/xsns_91_max44009.ino b/sonoff/xsns_91_max44009.ino index 499a88eb0..e113f1e01 100644 --- a/sonoff/xsns_91_max44009.ino +++ b/sonoff/xsns_91_max44009.ino @@ -29,34 +29,47 @@ #define MAX44009_ADDR1 0x4A #define MAX44009_ADDR2 0x4B +#define MAX44009_NO_REGISTERS 8 #define REG_CONFIG 0x02 #define REG_LUMINANCE 0x03 #define MAX44009_CONTINUOUS_AUTO_MODE 0x80 // Start measurement in automatic, continous mode uint8_t max44009_address; -uint8_t max44009_addresses[] = { MAX44009_ADDR1, MAX44009_ADDR2 }; -uint8_t max44009_type = 0; +uint8_t max44009_addresses[] = { MAX44009_ADDR1, MAX44009_ADDR2, 0 }; //0 terminated list +uint8_t max44009_found = 0; uint8_t max44009_valid = 0; float max44009_illuminance = 0; char max44009_types[] = "MAX44009"; bool Max4409Read_lum(void) { - if (max44009_valid) { max44009_valid--; } - + max44009_valid = 0; /* Select luminance start register */ Wire.beginTransmission(max44009_address); Wire.write(REG_LUMINANCE); Wire.endTransmission(); - if (2 != Wire.requestFrom(max44009_address, (uint8_t)2)) { return false; } + if (2 != Wire.requestFrom(max44009_address, (uint8_t)2)) { + return false; + } byte msb = Wire.read(); byte lsb = Wire.read(); int exponent = (msb & 0xF0) >> 4; int mantissa = ((msb & 0x0F) << 4) | (lsb & 0x0F); max44009_illuminance = pow(2, exponent) * mantissa * 0.045; - max44009_valid = SENSOR_MAX_MISS; + max44009_valid = 1; + return true; +} + +bool Max4409Read_register(uint8_t regno, byte *value) { + Wire.beginTransmission(max44009_address); + Wire.write(regno); + if ((0 != Wire.endTransmission()) || + (1 != Wire.requestFrom(max44009_address, (uint8_t)1))) { + return false; + } + *value = (byte)Wire.read(); return true; } @@ -64,23 +77,63 @@ bool Max4409Read_lum(void) void Max4409Detect(void) { - if (max44009_type) { + byte reg[8]; + bool failed = false; + + if (max44009_found) { return; } - for (byte i = 0; i < sizeof(max44009_addresses); i++) { + for (byte i = 0; 0 != max44009_addresses[i]; i++) { max44009_address = max44009_addresses[i]; - Wire.beginTransmission(max44009_address); - /* select configuration register iand set mode */ - Wire.write(REG_CONFIG); - Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); - if (!Wire.endTransmission()) { - max44009_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, max44009_types, max44009_address); + // we need to read each register separately, as auto-increment is only + // supported for illiminance registers + for (byte r = 0; r < MAX44009_NO_REGISTERS; r++) { + if (false == Max4409Read_register(r, ®[r])) { + snprintf_P(log_data, sizeof(log_data), "MAX44009 at %x: Failed to read register %d", + max44009_address, (int)r); + AddLog(LOG_LEVEL_DEBUG); + failed = true; + break; + } + } + if (failed) { + continue; + } + + snprintf_P(log_data, sizeof(log_data), "MAX44009 at %x: Read %x %x %x %x %x %x %x %x", + (int) max44009_address, (int)reg[0], (int)reg[1], (int)reg[2], (int)reg[3], + (int)reg[4], (int)reg[5], (int)reg[6], (int)reg[7]); + AddLog(LOG_LEVEL_DEBUG); + + if ( (0x00 == reg[0]) && + (0x00 == reg[1]) && + ( (0x00 == (reg[2] & 0xc0)) || (MAX44009_CONTINUOUS_AUTO_MODE == (reg[2] & 0xc0)) ) && + (0xef == reg[5]) && + (0x00 == reg[6]) && + (0xff == reg[7])) { + + // looks reasonable, try to initialize + + Wire.beginTransmission(max44009_address); + + // select configuration register and set mode + Wire.write(REG_CONFIG); + Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); + if (0 == Wire.endTransmission()) { + max44009_found = 1; + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, max44009_types, max44009_address); + AddLog(LOG_LEVEL_DEBUG); + break; + } else { + snprintf_P(log_data, sizeof(log_data), "MAX44009 at %x: config failed!", max44009_address); + AddLog(LOG_LEVEL_DEBUG); + } + } else { + snprintf_P(log_data, sizeof(log_data), "Reading initial data failed: No MAX44009 at %x", max44009_address); AddLog(LOG_LEVEL_DEBUG); - break; - } + } } } @@ -92,11 +145,8 @@ void Max4409EverySecond(void) } else { // 1mS - if (max44009_type) { - if (!Max4409Read_lum()) { - AddLogMissed(max44009_types, max44009_valid); -// if (!max44009_valid) { max44009_type = 0; } - } + if (max44009_found) { + Max4409Read_lum(); } } } @@ -143,9 +193,9 @@ boolean Xsns91(byte function) if (i2c_flg) { switch (function) { - case FUNC_INIT: - Max4409Detect(); - break; +// case FUNC_INIT: +// Max4409Detect(); +// break; case FUNC_EVERY_SECOND: Max4409EverySecond(); break; From 553738335278c8ef12446ae40b1e2237b65c562e Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Sat, 19 Jan 2019 22:28:58 +0000 Subject: [PATCH 0877/2222] sm16716 works via mqtt --- sonoff/sonoff_template.h | 37 +++++- sonoff/xdrv_20_sm16717.ino | 257 +++++++++++++++++++++---------------- 2 files changed, 179 insertions(+), 115 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 39eb8737d..250bd9f46 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -146,6 +146,8 @@ enum UserSelectablePins { GPIO_MAX31855CS, // MAX31855 Serial interface GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface + GPIO_SM16716_CLK, // SM16716 CLK + GPIO_SM16716_DAT, // SM16716 DAT GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -209,7 +211,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC "|" D_SENSOR_RF_SENSOR "|" D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX "|" - D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO; + D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO "|" + D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT; /********************************************************************************************/ @@ -281,6 +284,7 @@ enum SupportedModules { KA10, ZX2820, MI_DESK_LAMP, + SYF05, MAXMODULE }; /********************************************************************************************/ @@ -506,6 +510,10 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface #endif +#ifdef USE_SM16716 + GPIO_SM16716_CLK, // SM16716 CLK + GPIO_SM16716_DAT, // SM16716 DAT +#endif // USE_SM16716 }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { @@ -574,7 +582,8 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { PHILIPS, YTF_IR_BRIDGE, WITTY, // Development Devices - WEMOS + WEMOS, + SYF05 }; // Default module settings @@ -1774,6 +1783,30 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_ROT_A, // GPIO12 Rotary switch A pin GPIO_ROT_B, // GPIO13 Rotary switch B pin 0, 0, 0, 0 + }, + { "SYF05", // Sunyesmart SYF05 (a.k.a. Fcmila) = TYWE3S + SM16726 + // https://www.flipkart.com/fc-mila-bxav-xs-ad-smart-bulb/p/itmf85zgs45fzr7n + // https://docs.tuya.com/en/hardware/WiFi-module/wifi-e3s-module.html + // http://www.datasheet-pdf.com/PDF/SM16716-Datasheet-Sunmoon-932771 + GPIO_USER, // GPIO00 N.C. + 0, + GPIO_USER, // GPIO02 N.C. + 0, + GPIO_SM16716_CLK, // GPIO04 + GPIO_PWM1, // GPIO05 Cold White + // GPIO06 + // GPIO07 + // GPIO08 + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 + GPIO_USER, // GPIO12 Warm White, not used on the LED panel + GPIO_USER, // GPIO13 N.C. (used as LED if you add it) + GPIO_SM16716_DAT, // GPIO14 + 0, // GPIO15 + GPIO_USER, // GPIO16 N.C. + GPIO_FLAG_ADC0 // ADC0 A0 Analog input +// + GPIO_FLAG_PULLUP // Allow input pull-up control } }; diff --git a/sonoff/xdrv_20_sm16717.ino b/sonoff/xdrv_20_sm16717.ino index 98416019c..1779d1e74 100644 --- a/sonoff/xdrv_20_sm16717.ino +++ b/sonoff/xdrv_20_sm16717.ino @@ -18,6 +18,7 @@ */ #ifdef USE_SM16716 + /*********************************************************************************************\ * SM16716 - Controlling RGB over a synchronous serial line * @@ -25,134 +26,156 @@ * \*********************************************************************************************/ -#define D_LOG_SM16716 "SM16716: " #define XDRV_20 20 -#define CLK_USEC 10 // Clock interval in microseconds +// Enable this for debug logging +//#define D_LOG_SM16716 "SM16716: " enum SM16716_Commands { - CMND_SM16716_POWER, CMND_SM16716_DIMMER, CMND_SM16716_COLOR }; + CMND_SM16716_COLOR }; const char k_SM16716_Commands[] PROGMEM = - D_CMND_POWER "|" D_CMND_DIMMER "|" D_CMND_COLOR ; + D_CMND_COLOR ; -uint8_t sm61716_pin_clk = 100; -uint8_t sm61716_pin_dat = 100; +uint8_t sm16716_pin_clk = 100; +uint8_t sm16716_pin_dat = 100; -uint8_t sm61716_colour[3] = {0, 0, 0}; +boolean sm16716_is_selected = false; +boolean sm16716_is_on = false; +uint8_t sm16716_color[3] = {0, 0, 0}; +int8_t sm16716_color_preset = 0; -uint8_t sm61716_eff_red = 0; -uint8_t sm61716_eff_green = 0; -uint8_t sm61716_eff_blue = 0; - -int8_t sm61716_colour_preset = 0; /*********************************************************************************************/ - void SM16716_SendBit(uint8_t v) { - digitalWrite(sm61716_pin_dat, v ? HIGH : LOW); - digitalWrite(sm61716_pin_clk, HIGH); - delayMicroseconds(CLK_USEC); - digitalWrite(sm61716_pin_clk, LOW); - delayMicroseconds(CLK_USEC); + /* NOTE: + * According to the spec sheet, max freq is 30 MHz, that is 16.6 ns per high/low half of the + * clk square wave. That is less than the overhead of 'digitalWrite' at this clock rate, + * so no additional delays are needed yet. */ + + digitalWrite(sm16716_pin_dat, (v != 0) ? HIGH : LOW); + //delayMicroseconds(1); + digitalWrite(sm16716_pin_clk, HIGH); + //delayMicroseconds(1); + digitalWrite(sm16716_pin_clk, LOW); } + +/*********************************************************************************************/ void SM16716_SendByte(uint8_t v) { uint8_t mask; - for (mask = 0x80; mask; mask >>= 1) + for (mask = 0x80; mask; mask >>= 1) { SM16716_SendBit(v & mask); + } } + /*********************************************************************************************/ void SM16716_Append_JSON(void) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Append_JSON;")); - AddLog(LOG_LEVEL_DEBUG); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SM16716\":{\"Red\":%d,\"Green\":%d,\"Blue\":%d}"), mqtt_data, sm61716_colour[0], sm61716_colour[1], sm61716_colour[2]); + snprintf_P(mqtt_data, sizeof(mqtt_data), + PSTR("%s,\"SM16716\":{\"Red\":%d,\"Green\":%d,\"Blue\":%d}"), + mqtt_data, sm16716_color[0], sm16716_color[1], sm16716_color[2]); } + /*********************************************************************************************/ boolean SM16716_Show_State(void) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_COLOR "\":\"%02x%02x%02x\"}"), - sm61716_colour[0], sm61716_colour[1], sm61716_colour[2]); + snprintf_P(mqtt_data, sizeof(mqtt_data), + PSTR("{\"" D_CMND_COLOR "\":\"%02x%02x%02x\"}"), + sm16716_color[0], sm16716_color[1], sm16716_color[2]); return true; } + /*********************************************************************************************/ void SM16716_Update() { - uint8_t eff_red, eff_green, eff_blue; +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "Update; pwr=%02x, rgb=%02x%02x%02x"), + sm16716_is_on, sm16716_color[0], sm16716_color[1], sm16716_color[2]); + AddLog(LOG_LEVEL_DEBUG); +#endif // D_LOG_SM16716 - if (Settings.power) { // any bit is ok for us - eff_red = (uint16_t)sm61716_colour[0] * Settings.light_dimmer / 100; - eff_green = (uint16_t)sm61716_colour[1] * Settings.light_dimmer / 100; - eff_blue = (uint16_t)sm61716_colour[2] * Settings.light_dimmer / 100; + // send start bit + SM16716_SendBit(1); + // send 24-bit rgb data + if (sm16716_is_on) { + SM16716_SendByte(sm16716_color[0]); + SM16716_SendByte(sm16716_color[1]); + SM16716_SendByte(sm16716_color[2]); } else { - eff_red = eff_green = eff_blue = 0; - } - - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Update; pwr=%02x, rgb=%02x%02x%02x, dimmer=%d, eff=%02x%02x%02x"), - Settings.power, sm61716_colour[0], sm61716_colour[1], sm61716_colour[2], Settings.light_dimmer, eff_red, eff_green, eff_blue); - AddLog(LOG_LEVEL_DEBUG); - - if ((eff_red != sm61716_eff_red) || (eff_green != sm61716_eff_green) || (eff_blue != sm61716_eff_blue)) { - sm61716_eff_red = eff_red; - sm61716_eff_green = eff_green; - sm61716_eff_blue = eff_blue; - - SM16716_SendBit(1); - SM16716_SendByte(eff_red); - SM16716_SendByte(eff_green); - SM16716_SendByte(eff_blue); + SM16716_SendByte(0); + SM16716_SendByte(0); + SM16716_SendByte(0); } + // send a 'do it' pulse + // (if multiple chips are chained, each one processes the 1st '1rgb' 25-bit block and + // passes on the rest, right until the one starting with 0) + SM16716_SendBit(0); + SM16716_SendByte(0); + SM16716_SendByte(0); + SM16716_SendByte(0); SM16716_Show_State(); } + /*********************************************************************************************/ boolean SM16716_ModuleSelected(void) { - sm61716_pin_clk = pin[GPIO_SM16716_CLK]; - sm61716_pin_dat = pin[GPIO_SM16716_DAT]; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), sm61716_pin_clk, sm61716_pin_dat); + sm16716_pin_clk = pin[GPIO_SM16716_CLK]; + sm16716_pin_dat = pin[GPIO_SM16716_DAT]; +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), + sm16716_pin_clk, sm16716_pin_dat); AddLog(LOG_LEVEL_DEBUG); - return (sm61716_pin_clk < 99) && (sm61716_pin_dat < 99); +#endif // D_LOG_SM16716 + sm16716_is_selected = (sm16716_pin_clk < 99) && (sm16716_pin_dat < 99); + return sm16716_is_selected; } + /*********************************************************************************************/ boolean SM16716_Init(void) { uint8_t t_init; + if (!SM16716_ModuleSelected()) return false; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Init;")); + pinMode(sm16716_pin_clk, OUTPUT); + digitalWrite(sm16716_pin_clk, LOW); - pinMode(sm61716_pin_clk, OUTPUT); - digitalWrite(sm61716_pin_clk, LOW); + pinMode(sm16716_pin_dat, OUTPUT); + digitalWrite(sm16716_pin_dat, LOW); - pinMode(sm61716_pin_dat, OUTPUT); - digitalWrite(sm61716_pin_dat, LOW); - - AddLog(LOG_LEVEL_DEBUG); for (t_init = 0; t_init < 50; ++t_init) SM16716_SendBit(0); return true; } + +/*********************************************************************************************/ boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { char component[3]; char *endptr = NULL; uint8_t candidate[3]; int i; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Parse_RRGGBB; data='%s', data_len=%d"), data, data_len); +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "Parse_RRGGBB; data='%s', data_len=%d"), + data, data_len); AddLog(LOG_LEVEL_DEBUG); +#endif // D_LOG_SM16716 if (data_len != 6) return false; @@ -168,39 +191,37 @@ boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { data += 2; } - sm61716_colour[0] = candidate[0]; - sm61716_colour[1] = candidate[1]; - sm61716_colour[2] = candidate[2]; + sm16716_color[0] = candidate[0]; + sm16716_color[1] = candidate[1]; + sm16716_color[2] = candidate[2]; return true; } -boolean SM16716_Parse_Colour(char *data, int data_len) { - /* NOTE: Very similar to 'LightColorEntry', but it's not reusable, because - * 'light_type' must be PWM, but then it won't parse the colour components. - * It's indeed more effective to not do the parsing when the current light - * type couldn't handle it, but enum LightTypes is not to be changed, so - * I can't implement new light types. - * - * If the parsing/handling of light attributes were separated from the - * technical details of actually sending it to the device, then only the - * device-specific parts should've been adapted, but unfortunately this is - * not the case here, so, here we go */ - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Parse_Colour; data='%s', data_len=%d"), data, data_len); +/*********************************************************************************************/ +boolean SM16716_Parse_Color(char *data, int data_len) { + /* NOTE: Very similar to 'LightColorEntry', but can't reuse it here, because + * 'light_type' must be PWM, and then it won't parse the color components. */ + +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "Parse_Color; data='%s', data_len=%d"), + data, data_len); AddLog(LOG_LEVEL_DEBUG); +#endif // D_LOG_SM16716 - if (data_len < 3) { // Colour preset + if (data_len < 3) { // a color preset switch (data[0]) { case '+': - ++sm61716_colour_preset; - if (sm61716_colour_preset >= MAX_FIXED_COLOR) - sm61716_colour_preset = 0; + ++sm16716_color_preset; + if (sm16716_color_preset >= MAX_FIXED_COLOR) + sm16716_color_preset = 0; break; case '-': - --sm61716_colour_preset; - if (sm61716_colour_preset < 0) - sm61716_colour_preset = MAX_FIXED_COLOR - 1; + --sm16716_color_preset; + if (sm16716_color_preset < 0) + sm16716_color_preset = MAX_FIXED_COLOR - 1; break; default: @@ -209,13 +230,17 @@ boolean SM16716_Parse_Colour(char *data, int data_len) { uint8_t candidate = (uint8_t)strtoul(data, &endptr, 10); if (!endptr || *endptr || (candidate < 0) || (MAX_FIXED_COLOR <= candidate)) return false; - sm61716_colour_preset = candidate; + sm16716_color_preset = candidate; } break; } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Parse_Colour; preset=%d"), sm61716_colour_preset); +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "Parse_Color; preset=%d"), + sm16716_color_preset); AddLog(LOG_LEVEL_DEBUG); - memcpy_P(sm61716_colour, &kFixedColor[sm61716_colour_preset], 3); +#endif // D_LOG_SM16716 + memcpy_P(sm16716_color, &kFixedColor[sm16716_color_preset], 3); } else if (data[0] == '#') { // #RRGGBB if (!SM16716_Parse_RRGGBB(data + 1, data_len - 1)) @@ -240,36 +265,32 @@ boolean SM16716_Parse_Colour(char *data, int data_len) { tok = strtok_r(NULL, ",", &last); if (tok) return false; // junk at the end - sm61716_colour[0] = candidate[0]; - sm61716_colour[1] = candidate[1]; - sm61716_colour[2] = candidate[2]; + sm16716_color[0] = candidate[0]; + sm16716_color[1] = candidate[1]; + sm16716_color[2] = candidate[2]; } return true; } + /*********************************************************************************************/ bool SM16716_Command(void) { char command [CMDSZ]; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, k_SM16716_Commands); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Command; topic='%s', data_len=%d, data='%s', code=%d"), +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "Command; topic='%s', data_len=%d, data='%s', code=%d"), XdrvMailbox.topic, XdrvMailbox.data_len, XdrvMailbox.data, command_code); AddLog(LOG_LEVEL_DEBUG); +#endif // D_LOG_SM16716 switch (command_code) { - case CMND_SM16716_POWER: - SM16716_Update(); - return false; // Don't catch the event, only handle the change - - case CMND_SM16716_DIMMER: - SM16716_Update(); - return false; // Don't catch the event, only handle the change - case CMND_SM16716_COLOR: if (XdrvMailbox.data_len == 0) return SM16716_Show_State(); - if (!SM16716_Parse_Colour(XdrvMailbox.data, XdrvMailbox.data_len)) + if (!SM16716_Parse_Color(XdrvMailbox.data, XdrvMailbox.data_len)) return false; SM16716_Update(); return true; @@ -277,43 +298,54 @@ bool SM16716_Command(void) return false; // Unknown command } + /*********************************************************************************************\ * Interface \*********************************************************************************************/ boolean Xdrv20(byte function) { - //snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Xdrv20; function=%d, index=%d"), function, XdrvMailbox.index); - //AddLog(LOG_LEVEL_DEBUG); + if (function == FUNC_MODULE_INIT) { + return SM16716_ModuleSelected(); + } + + if (!sm16716_is_selected) + return false; switch (function) { - case FUNC_MODULE_INIT: - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_MODULE_INIT")); - AddLog(LOG_LEVEL_DEBUG); - return SM16716_ModuleSelected(); - case FUNC_INIT: - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_INIT")); +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "Entry; function=FUNC_INIT")); AddLog(LOG_LEVEL_DEBUG); +#endif return SM16716_Init(); case FUNC_COMMAND: - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_COMMAND")); +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "Entry; function=FUNC_COMMAND")); AddLog(LOG_LEVEL_DEBUG); return SM16716_Command(); +#endif - case FUNC_SET_POWER: - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_SET_POWER, index=%02x, payload=%02x"), XdrvMailbox.index, XdrvMailbox.payload); - AddLog(LOG_LEVEL_DEBUG); - return false; - + //case FUNC_SET_POWER: case FUNC_SET_DEVICE_POWER: - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_SET_DEVICE_POWER, index=%02x, payload=%02x"), XdrvMailbox.index, XdrvMailbox.payload); +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "Entry; function=FUNC_SET_DEVICE_POWER, index=%02x, payload=%02x"), + XdrvMailbox.index, XdrvMailbox.payload); AddLog(LOG_LEVEL_DEBUG); - return false; +#endif + sm16716_is_on = (XdrvMailbox.index != 0); + SM16716_Update(); + return false; // don't catch the event case FUNC_JSON_APPEND: - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_JSON_APPEND")); +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "Entry; function=FUNC_JSON_APPEND")); AddLog(LOG_LEVEL_DEBUG); +#endif SM16716_Append_JSON(); break; } @@ -321,5 +353,4 @@ boolean Xdrv20(byte function) } #endif // USE_SM16716 - // vim: set ft=c sw=2 ts=2 et: From 2b7fbe22e3f3373857e266b7d07250c27a1ce0f3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 20 Jan 2019 16:57:07 +0100 Subject: [PATCH 0878/2222] Fix MQTT host detection Fix MQTT host detection --- sonoff/xdrv_02_mqtt.ino | 47 +++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 0b903f463..b6ceec2f6 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -76,6 +76,7 @@ const char kMqttCommands[] PROGMEM = uint16_t mqtt_retry_counter = 1; // MQTT connection retry counter uint8_t mqtt_initial_connection_state = 2; // MQTT connection messages state bool mqtt_connected = false; // MQTT virtual connection status +bool mqtt_allowed = false; // MQTT enabled and parameters valid /*********************************************************************************************\ * MQTT driver specific code need to provide the following functions: @@ -210,9 +211,9 @@ void MqttLoop(void) #ifdef USE_DISCOVERY #ifdef MQTT_HOST_DISCOVERY -boolean MqttDiscoverServer(void) +void MqttDiscoverServer(void) { - if (!mdns_begun) { return false; } + if (!mdns_begun) { return; } int n = MDNS.queryService("mqtt", "tcp"); // Search for mqtt service @@ -220,26 +221,21 @@ boolean MqttDiscoverServer(void) AddLog(LOG_LEVEL_INFO); if (n > 0) { - #ifdef MDNS_HOSTNAME - for (int i = 0; i < n; i++) { + uint8_t i = 0; // If the hostname isn't set, use the first record found. +#ifdef MDNS_HOSTNAME + for (i = n; i > 0; i--) { // Search from last to first and use first if not found if (!strcmp(MDNS.hostname(i).c_str(), MDNS_HOSTNAME)) { - snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(i).toString().c_str()); - Settings.mqtt_port = MDNS.port(i); - break; // stop at the first matching record + break; // Stop at matching record } } - #else - // If the hostname isn't set, use the first record found. - snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(0).toString().c_str()); - Settings.mqtt_port = MDNS.port(0); - #endif // MDNS_HOSTNAME +#endif // MDNS_HOSTNAME + snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(i).toString().c_str()); + Settings.mqtt_port = MDNS.port(i); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), - MDNS.hostname(0).c_str(), Settings.mqtt_host, Settings.mqtt_port); + MDNS.hostname(i).c_str(), Settings.mqtt_host, Settings.mqtt_port); AddLog(LOG_LEVEL_INFO); } - - return n > 0; } #endif // MQTT_HOST_DISCOVERY #endif // USE_DISCOVERY @@ -398,7 +394,7 @@ void MqttConnected(void) { char stopic[TOPSZ]; - if (Settings.flag.mqtt_enabled) { + if (mqtt_allowed) { AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_CONNECTED)); mqtt_connected = true; mqtt_retry_counter = 0; @@ -520,7 +516,18 @@ void MqttReconnect(void) { char stopic[TOPSZ]; - if (!Settings.flag.mqtt_enabled) { + mqtt_allowed = Settings.flag.mqtt_enabled; + if (mqtt_allowed) { +#ifdef USE_DISCOVERY +#ifdef MQTT_HOST_DISCOVERY + MqttDiscoverServer(); +#endif // MQTT_HOST_DISCOVERY +#endif // USE_DISCOVERY + if (!strlen(Settings.mqtt_host) || !Settings.mqtt_port) { + mqtt_allowed = false; + } + } + if (!mqtt_allowed) { MqttConnected(); return; } @@ -535,12 +542,6 @@ void MqttReconnect(void) mqtt_retry_counter = Settings.mqtt_retry; global_state.mqtt_down = 1; -#ifdef USE_DISCOVERY -#ifdef MQTT_HOST_DISCOVERY - if (!MqttDiscoverServer() && !strlen(Settings.mqtt_host)) { return; } -#endif // MQTT_HOST_DISCOVERY -#endif // USE_DISCOVERY - char *mqtt_user = NULL; char *mqtt_pwd = NULL; if (strlen(Settings.mqtt_user) > 0) mqtt_user = Settings.mqtt_user; From d9e0e9f89e0d913e5a158cad569485b0d4af796c Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Sun, 20 Jan 2019 21:18:28 +0000 Subject: [PATCH 0879/2222] Added missing definitions to Greek localisation header --- sonoff/language/el-GR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 8a4402538..81a017a0b 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" From f833dd07ad02b2fd2c39d37cb95b864f0337c672 Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Mon, 21 Jan 2019 06:44:07 +0000 Subject: [PATCH 0880/2222] Enabled 'warm white' pwm in the module config, code comments added, coding style improved --- sonoff/sonoff_template.h | 4 +- sonoff/xdrv_20_sm16717.ino | 86 ++++++++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 23 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 250bd9f46..ceca9685e 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1800,10 +1800,10 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO09 0, // GPIO10 // GPIO11 - GPIO_USER, // GPIO12 Warm White, not used on the LED panel + GPIO_PWM2, // GPIO12 Warm White GPIO_USER, // GPIO13 N.C. (used as LED if you add it) GPIO_SM16716_DAT, // GPIO14 - 0, // GPIO15 + 0, // GPIO15 wired to GND GPIO_USER, // GPIO16 N.C. GPIO_FLAG_ADC0 // ADC0 A0 Analog input // + GPIO_FLAG_PULLUP // Allow input pull-up control diff --git a/sonoff/xdrv_20_sm16717.ino b/sonoff/xdrv_20_sm16717.ino index 1779d1e74..7b367fc2f 100644 --- a/sonoff/xdrv_20_sm16717.ino +++ b/sonoff/xdrv_20_sm16717.ino @@ -147,8 +147,9 @@ boolean SM16716_Init(void) { uint8_t t_init; - if (!SM16716_ModuleSelected()) + if (!SM16716_ModuleSelected()) { return false; + } pinMode(sm16716_pin_clk, OUTPUT); digitalWrite(sm16716_pin_clk, LOW); @@ -156,14 +157,18 @@ boolean SM16716_Init(void) pinMode(sm16716_pin_dat, OUTPUT); digitalWrite(sm16716_pin_dat, LOW); - for (t_init = 0; t_init < 50; ++t_init) + for (t_init = 0; t_init < 50; ++t_init) { SM16716_SendBit(0); + } return true; } /*********************************************************************************************/ +/* Try to parse a string as 'RRGGBB' hex-encoded color value + * Accept only exact match (i.e. there can be no leftover chars) + */ boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { char component[3]; char *endptr = NULL; @@ -177,20 +182,30 @@ boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { AddLog(LOG_LEVEL_DEBUG); #endif // D_LOG_SM16716 - if (data_len != 6) + if (data_len != 6) { + // too long or too short return false; + } + // a component is exactly 3 chars, so terminate the string now component[2] = '\0'; + // try to parse 3 components for (i = 0; i < 3; ++i) { + // copy the value to the temp string component[0] = data[0]; component[1] = data[1]; + // try to interpret it as a hex number candidate[i] = (uint8_t)strtoul(component, &endptr, 16); - if (!endptr || *endptr) + if (!endptr || *endptr) { + // not a valid hex number return false; + } + // advance to the next 2 characters data += 2; } + // now that we have all 3, we may change sm16716_color[] sm16716_color[0] = candidate[0]; sm16716_color[1] = candidate[1]; sm16716_color[2] = candidate[2]; @@ -210,61 +225,87 @@ boolean SM16716_Parse_Color(char *data, int data_len) { AddLog(LOG_LEVEL_DEBUG); #endif // D_LOG_SM16716 - if (data_len < 3) { // a color preset + if (data_len < 3) { // too short for color literal: try to interpret as a color preset + // check for '+' and '-' commands first switch (data[0]) { - case '+': + case '+': // advance to the next preset, handle wrap-around ++sm16716_color_preset; - if (sm16716_color_preset >= MAX_FIXED_COLOR) + if (sm16716_color_preset >= MAX_FIXED_COLOR) { sm16716_color_preset = 0; + } break; - case '-': + case '-': // return to the previous preset, handle wrap-around --sm16716_color_preset; - if (sm16716_color_preset < 0) + if (sm16716_color_preset < 0) { sm16716_color_preset = MAX_FIXED_COLOR - 1; + } break; default: + // try to interpret it as a decimal integer { char *endptr = NULL; uint8_t candidate = (uint8_t)strtoul(data, &endptr, 10); - if (!endptr || *endptr || (candidate < 0) || (MAX_FIXED_COLOR <= candidate)) + if (!endptr || *endptr || (candidate < 0) || (MAX_FIXED_COLOR <= candidate)) { + // it's not a valid integer (and nothing else), or the number is not a valid preset index return false; + } + // we have the requested preset index sm16716_color_preset = candidate; } break; } + #ifdef D_LOG_SM16716 snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Parse_Color; preset=%d"), sm16716_color_preset); AddLog(LOG_LEVEL_DEBUG); #endif // D_LOG_SM16716 + + // copy the requested preset values memcpy_P(sm16716_color, &kFixedColor[sm16716_color_preset], 3); } - else if (data[0] == '#') { // #RRGGBB - if (!SM16716_Parse_RRGGBB(data + 1, data_len - 1)) + else if (data[0] == '#') { // starts with #, so try to interpret as #RRGGBB + if (!SM16716_Parse_RRGGBB(data + 1, data_len - 1)) { + // not a valid RRGGBB after the # return false; + } } - else if (SM16716_Parse_RRGGBB(data, data_len)) { // RRGGBB + // two more formats left: RRGGBB (without #) and comma separated color components + else if (SM16716_Parse_RRGGBB(data, data_len)) { // try to interpret as RRGGBB + // parsed successfully as RRGGBB, nothing more to do } - else { // rrr,g,bb + else { // try to interpret as rrr,g,bb uint8_t candidate[3]; char *tok, *last, *endptr = NULL; int i; + // try to parse the first 3 comma-separated tokens for (i = 0; i < 3; ++i) { + // try to isolate the next token tok = strtok_r(data, ",", &last); - if (!tok) + if (!tok) { + // we're beyond the end of string: there were too few tokens return false; + } + // try to interpret the token as integer candidate[i] = (uint8_t)strtoul(tok, &endptr, 0); - if (!endptr || *endptr) + if (!endptr || *endptr) { + // not a valid integer return false; + } + // in the next cycle just continue this token-processing session data = NULL; } + // there shouldn't be any leftover characters (i.e. we need exactly 3 components) tok = strtok_r(NULL, ",", &last); - if (tok) - return false; // junk at the end + if (tok) { + // too many components + return false; + } + // now that we have all 3 components, we may change sm16716_color sm16716_color[0] = candidate[0]; sm16716_color[1] = candidate[1]; sm16716_color[2] = candidate[2]; @@ -288,10 +329,12 @@ bool SM16716_Command(void) switch (command_code) { case CMND_SM16716_COLOR: - if (XdrvMailbox.data_len == 0) + if (XdrvMailbox.data_len == 0) { return SM16716_Show_State(); - if (!SM16716_Parse_Color(XdrvMailbox.data, XdrvMailbox.data_len)) + } + if (!SM16716_Parse_Color(XdrvMailbox.data, XdrvMailbox.data_len)) { return false; + } SM16716_Update(); return true; } @@ -308,8 +351,9 @@ boolean Xdrv20(byte function) return SM16716_ModuleSelected(); } - if (!sm16716_is_selected) + if (!sm16716_is_selected) { return false; + } switch (function) { case FUNC_INIT: From dcabb9c6dc1668209a6a770446253b79efbe1cc5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 21 Jan 2019 22:18:19 +0100 Subject: [PATCH 0881/2222] 6.4.1.10 Fix Hass discovery of MHZ19(B) 6.4.1.10 20190121 * Fix Hass discovery of MHZ19(B) sensors (#4992) --- sonoff/_changelog.ino | 5 ++++- sonoff/i18n.h | 1 + sonoff/sonoff_version.h | 2 +- sonoff/xsns_15_mhz19.ino | 13 +++++++------ 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 2d77e925f..8db379f8b 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.9 20190115 +/* 6.4.1.10 20190121 + * Fix Hass discovery of MHZ19(B) sensors (#4992) + * + * 6.4.1.9 20190115 * Add support for Mi LED Desk Lamp with rotary switch (#4887) * Fix mDNS addService (#4938, #4951) * Fix allowable MAX_RULE_VARS to 16 (#4933) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index a90028e8d..1003a3996 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -92,6 +92,7 @@ #define D_JSON_MAC "Mac" #define D_JSON_MASK "Mask" #define D_JSON_MINIMAL "minimal" +#define D_JSON_MODEL "Model" #define D_JSON_NO "No" #define D_JSON_NOISE "Noise" #define D_JSON_NONE "None" diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 534276418..47bbb82f2 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040109 +#define VERSION 0x0604010A #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index bc8e46ada..7585ff3d9 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -70,7 +70,7 @@ enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILT TasmotaSerial *MhzSerial; -const char kMhzTypes[] PROGMEM = "MHZ19|MHZ19B"; +const char kMhzModels[] PROGMEM = "|B"; enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; const uint8_t kMhzCommands[][4] PROGMEM = { @@ -90,7 +90,6 @@ uint16_t mhz_last_ppm = 0; uint8_t mhz_filter = MHZ19_FILTER_OPTION; bool mhz_abc_enable = MHZ19_ABC_ENABLE; bool mhz_abc_must_apply = false; -char mhz_types[7]; float mhz_temperature = 0; uint8_t mhz_retry = MHZ19_RETRY_COUNT; @@ -322,19 +321,21 @@ void MhzInit(void) void MhzShow(boolean json) { + char types[7] = "MHZ19B"; // MHZ19B for legacy reasons. Prefered is MHZ19 char temperature[33]; dtostrfd(mhz_temperature, Settings.flag2.temperature_resolution, temperature); - GetTextIndexed(mhz_types, sizeof(mhz_types), mhz_type -1, kMhzTypes); + char model[3]; + GetTextIndexed(model, sizeof(model), mhz_type -1, kMhzModels); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, mhz_types, mhz_last_ppm, temperature); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, types, model, mhz_last_ppm, temperature); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm); #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CO2, mqtt_data, mhz_types, mhz_last_ppm); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, mhz_types, temperature, TempUnit()); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CO2, mqtt_data, types, mhz_last_ppm); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, types, temperature, TempUnit()); #endif // USE_WEBSERVER } } From 7745e1e7794d305aa0088457f52a4140ca74d6a2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 22 Jan 2019 12:46:55 +0100 Subject: [PATCH 0882/2222] Fix Hass Software Watchdog Fix Hass Software Watchdog exception during discovery (#4988) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 26 +++++----- sonoff/xdrv_12_home_assistant.ino | 85 +++++++++++-------------------- 3 files changed, 44 insertions(+), 68 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 8db379f8b..a32d7f7f2 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.4.1.10 20190121 * Fix Hass discovery of MHZ19(B) sensors (#4992) + * Fix Hass Software Watchdog exception during discovery (#4988) * * 6.4.1.9 20190115 * Add support for Mi LED Desk Lamp with rotary switch (#4887) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 878a24d50..43ac0ce3b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -318,7 +318,7 @@ void SetDevicePower(power_t rpower, int source) power = (1 << devices_present) -1; rpower = power; } - if (Settings.flag3.split_interlock) { + if (Settings.flag3.split_interlock) { Settings.flag.interlock = 1; // prevent the situation where interlock is off and split-interlock is on uint8_t mask = 0x01; uint8_t count = 0; @@ -335,18 +335,18 @@ void SetDevicePower(power_t rpower, int source) if ((result1) >1 && (result2 <2)) {power = power & 0x0C; rpower = power;} // 1/2 are both on and 3/4 max one is on if ((result1) <2 && (result2 >1)) {power = power & 0x03; rpower = power;} // 1/2 max one is on and 3/4 both are on } else { - if (Settings.flag.interlock) { // Allow only one or no relay set - power_t mask = 1; - uint8_t count = 0; - for (byte i = 0; i < devices_present; i++) { - if (rpower & mask) count++; - mask <<= 1; + if (Settings.flag.interlock) { // Allow only one or no relay set + power_t mask = 1; + uint8_t count = 0; + for (byte i = 0; i < devices_present; i++) { + if (rpower & mask) count++; + mask <<= 1; + } + if (count > 1) { + power = 0; + rpower = 0; + } } - if (count > 1) { - power = 0; - rpower = 0; - } - } } XdrvMailbox.index = rpower; @@ -772,7 +772,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } #ifdef USE_HOME_ASSISTANT if ((19 == pindex) || (30 == pindex)) { - HAssDiscovery(1); // hass_discovery or hass_light + HAssDiscover(); // Delayed execution to provide enough resources during hass_discovery or hass_light } #endif // USE_HOME_ASSISTANT } diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index fd276bdcb..1309f9e07 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -133,6 +133,9 @@ const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM = "%s, \"~\":\"%s\""; +uint8_t hass_init_step = 0; +uint8_t hass_mode = 0; + static void FindPrefix(char* s1, char* s2, char* out) { int prefixlen = 0; @@ -423,6 +426,7 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) void HAssAnnounceSensors(void) { uint8_t hass_xsns_index = 0; + do { mqtt_data[0] = '\0'; int tele_period_save = tele_period; @@ -430,14 +434,18 @@ void HAssAnnounceSensors(void) XsnsNextCall(FUNC_JSON_APPEND, hass_xsns_index); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} tele_period = tele_period_save; - char sensordata[256]; // Copy because we need to write to mqtt_data + char sensordata[256]; // Copy because we need to write to mqtt_data strlcpy(sensordata, mqtt_data, sizeof(sensordata)); if (strlen(sensordata)) { sensordata[0] = '{'; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} - snprintf_P(sensordata, sizeof(sensordata), PSTR("%s}"), sensordata); + snprintf_P(sensordata, sizeof(sensordata), PSTR("%s}"), sensordata); // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}} - StaticJsonBuffer<256> jsonBuffer; + // JsonBuffer size calculation (https://arduinojson.org/v5/assistant/) + // 383 = {"MCP230XX":{"D0":0,"D1":0,"D2":0,"D3":0,"D4":0,"D5":0,"D6":0,"D7":0,"D8":0,"D9":0,"D10":0,"D11":0,"D12":0,"D13":0,"D14":0,"D15":0}} + // 381 = {"MPR121A":{"Button0":0,"Button1":0,"Button2":0,"Button3":0,"Button4":0,"Button5":0,"Button6":0,"Button7":0,"Button8":0,"Button9":0,"Button10":0,"Button11":0,"Button12":0}} + // 420 = {"ENERGY":{"TotalStartTime":"2018-10-30T17:09:47","Total":2.684,"Yesterday":0.020,"Today":0.006,"Period":0.04,"Power":0.49,"ApparentPower":4.71,"ReactivePower":4.70,"Factor":0.10,"Frequency":50.04,"Voltage":226.3,"Current":0.021}} + StaticJsonBuffer<500> jsonBuffer; JsonObject& root = jsonBuffer.parseObject(sensordata); if (!root.success()) { snprintf_P(log_data, sizeof(log_data), PSTR("HASS: failed to parse '%s'"), sensordata); @@ -469,21 +477,22 @@ static int string_ends_with(const char * str, const char * suffix) return (str_len >= suffix_len) && (0 == strcmp(str + (str_len-suffix_len), suffix)); } -void HAssDiscovery(uint8_t mode) +void HAssDiscovery(void) { // Configure Tasmota for default Home Assistant parameters to keep discovery message as short as possible if (Settings.flag.hass_discovery) { - Settings.flag.mqtt_response = 0; // Response always as RESULT and not as uppercase command - Settings.flag.decimal_text = 1; // Respond with decimal color values - Settings.flag3.hass_tele_on_power = 1; // send tele/STATE message as stat/RESULT -// Settings.light_scheme = 0; // To just control color it needs to be Scheme 0 + Settings.flag.mqtt_response = 0; // Response always as RESULT and not as uppercase command + Settings.flag.decimal_text = 1; // Respond with decimal color values + Settings.flag3.hass_tele_on_power = 1; // send tele/STATE message as stat/RESULT +// Settings.light_scheme = 0; // To just control color it needs to be Scheme 0 if (!string_ends_with(Settings.mqtt_fulltopic, "%prefix%/")) { strncpy_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"), sizeof(Settings.mqtt_fulltopic)); restart_flag = 2; + return; // As full topic has changed do restart first before sending discovery data } } - if (Settings.flag.hass_discovery || (1 == mode)) { + if (Settings.flag.hass_discovery || (1 == hass_mode)) { // Send info about relays and lights HAssAnnounceRelayLight(); @@ -498,49 +507,11 @@ void HAssDiscovery(uint8_t mode) } } -/* -#define D_CMND_HASSDISCOVER "HassDiscover" - -enum HassCommands { CMND_HASSDISCOVER }; -const char kHassCommands[] PROGMEM = D_CMND_HASSDISCOVER ; - -boolean HassCommand(void) +void HAssDiscover(void) { - char command[CMDSZ]; - boolean serviced = true; - - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kHassCommands); - if (-1 == command_code) { - serviced = false; // Unknown command - } - else if (CMND_HASSDISCOVER == command_code) { - if (XdrvMailbox.data_len > 0) { - switch (XdrvMailbox.payload) { - case 0: // Off - case 1: // On - Settings.flag.hass_discovery = XdrvMailbox.payload; - break; - case 2: // Toggle - Settings.flag.hass_discovery ^= 1; - break; - case 4: // Off - case 5: // On - Settings.flag.hass_light = XdrvMailbox.payload &1; - break; - case 6: // Toggle - Settings.flag.hass_light ^= 1; - break; - } - HAssDiscovery(1); - } - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\",\"Force light\":\"%s\"}"), - command, GetStateText(Settings.flag.hass_discovery), GetStateText(Settings.flag.hass_light)); - } - else serviced = false; // Unknown command - - return serviced; + hass_mode = 1; // Force discovery + hass_init_step = 1; // Delayed discovery } -*/ /*********************************************************************************************\ * Interface @@ -553,13 +524,17 @@ boolean Xdrv12(byte function) if (Settings.flag.mqtt_enabled) { switch (function) { case FUNC_MQTT_INIT: - HAssDiscovery(0); + hass_mode = 0; // Discovery only if Settings.flag.hass_discovery is set + hass_init_step = 2; // Delayed discovery break; -/* - case FUNC_COMMAND: - result = HassCommand(); + case FUNC_EVERY_SECOND: + if (hass_init_step) { + hass_init_step--; + if (!hass_init_step) { + HAssDiscovery(); // Scheduled discovery using available resources + } + } break; -*/ } } return result; From 2f8b083bdaf15ff422e5497f0179769c03621664 Mon Sep 17 00:00:00 2001 From: araczkowski Date: Tue, 22 Jan 2019 12:53:02 +0100 Subject: [PATCH 0883/2222] fixed some typos --- sonoff/language/pl-PL.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 6327f87d0..fa02ffc7f 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -62,7 +62,7 @@ #define D_BRIGHTLIGHT "Jasny" #define D_BSSID "BSSId" #define D_BUTTON "Przycisk" -#define D_BY "przez" // Written by me +#define D_BY "by" // Written by me #define D_BYTES "Bajtow" #define D_CELSIUS "Celsiusza" #define D_CHANNEL "Kanał" @@ -139,7 +139,7 @@ #define D_RESTART_REASON "Przyczyna restartu" #define D_RESTORE "Przywracanie" #define D_RETAINED "Zachowane" -#define D_RULE "Rule" +#define D_RULE "Reguła" #define D_SAVE "Zapisz" #define D_SENSOR "Czujnik" #define D_SSID "SSID" @@ -235,7 +235,7 @@ #define D_BUTTON_TOGGLE "Przełącznik" #define D_CONFIGURATION "Konfiguracja" #define D_INFORMATION "Informacje" -#define D_FIRMWARE_UPGRADE "Uaktualnienie oprogramowania" +#define D_FIRMWARE_UPGRADE "Aktualnizacja oprogramowania" #define D_CONSOLE "Konsola" #define D_CONFIRM_RESTART "Potwierdź restart" @@ -248,10 +248,10 @@ #define D_CONFIRM_RESET_CONFIGURATION "Potwierdź reset ustawień" #define D_RESET_CONFIGURATION "Reset ustawień" #define D_BACKUP_CONFIGURATION "Kopia ustawień" -#define D_RESTORE_CONFIGURATION "Przywrócenie ustawień" +#define D_RESTORE_CONFIGURATION "Przywracanie ustawień" #define D_MAIN_MENU "Menu główne" -#define D_MODULE_PARAMETERS "Parametery modułu" +#define D_MODULE_PARAMETERS "Parametry modułu" #define D_MODULE_TYPE "Typ modułu" #define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" @@ -274,23 +274,23 @@ #define D_AP2_SSID "AP2 SSID" #define D_AP2_PASSWORD "Hasło AP2" -#define D_MQTT_PARAMETERS "Parametery MQTT" +#define D_MQTT_PARAMETERS "Parametry MQTT" #define D_CLIENT "Klient" -#define D_FULL_TOPIC "Pełen temat" +#define D_FULL_TOPIC "Pełny temat" #define D_LOGGING_PARAMETERS "Opcje dziennika" #define D_SERIAL_LOG_LEVEL "Serial poziom dziennika" #define D_WEB_LOG_LEVEL "Web poziom dziennika" #define D_SYS_LOG_LEVEL "System poziom dziennika" -#define D_MORE_DEBUG "Więcej informacji debugujacych" +#define D_MORE_DEBUG "Więcej informacji debug" #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_OTHER_PARAMETERS "Inne parametry" #define D_WEB_ADMIN_PASSWORD "Hasło administratora Web" #define D_MQTT_ENABLE "MQTT aktywne" -#define D_FRIENDLY_NAME "Przyjazna nazwa" +#define D_FRIENDLY_NAME "Twoja nazwa" #define D_BELKIN_WEMO "Belkin WeMo" #define D_HUE_BRIDGE "Hue Bridge" #define D_SINGLE_DEVICE "single device" @@ -391,18 +391,18 @@ #define D_DOMOTICZ_UPDATE_TIMER "Zaktualizuj czasomierz" // xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Skonfiguruj harmonogram" +#define D_CONFIGURE_TIMER "Konfiguruj harmonogram" #define D_TIMER_PARAMETERS "Parametry harmonogramów" #define D_TIMER_ENABLE "Włącz Harmonogramy" #define D_TIMER_ARM "Włącz" -#define D_TIMER_TIME "Czas" +#define D_TIMER_TIME "Według godziny" #define D_TIMER_DAYS "Dni" #define D_TIMER_REPEAT "Powtarzaj" #define D_TIMER_OUTPUT "Wyjście" #define D_TIMER_ACTION "Akcja" // xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Skonfiguruj KNX" +#define D_CONFIGURE_KNX "Konfiguruj KNX" #define D_KNX_PARAMETERS "Parametry KNX" #define D_KNX_GENERAL_CONFIG "Ogólne" #define D_KNX_PHYSICAL_ADDRESS "Adres Fizyczny" From e13fd7983e90b51a167f6cb0a929697b2d7a084f Mon Sep 17 00:00:00 2001 From: araczkowski Date: Tue, 22 Jan 2019 12:56:35 +0100 Subject: [PATCH 0884/2222] fix --- sonoff/language/pl-PL.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index fa02ffc7f..639704a4d 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -235,7 +235,7 @@ #define D_BUTTON_TOGGLE "Przełącznik" #define D_CONFIGURATION "Konfiguracja" #define D_INFORMATION "Informacje" -#define D_FIRMWARE_UPGRADE "Aktualnizacja oprogramowania" +#define D_FIRMWARE_UPGRADE "Aktualizacja oprogramowania" #define D_CONSOLE "Konsola" #define D_CONFIRM_RESTART "Potwierdź restart" From 1fe183969014af3485d42d2ddd1d0c62916cca79 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 22 Jan 2019 16:07:16 +0100 Subject: [PATCH 0885/2222] Force Hass fulltopic change Force Hass fulltopic change (#4988) --- sonoff/xdrv_12_home_assistant.ino | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 1309f9e07..cbab0d2c5 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -469,14 +469,6 @@ void HAssAnnounceSensors(void) } while (hass_xsns_index != 0); } -static int string_ends_with(const char * str, const char * suffix) -{ - int str_len = strlen(str); - int suffix_len = strlen(suffix); - - return (str_len >= suffix_len) && (0 == strcmp(str + (str_len-suffix_len), suffix)); -} - void HAssDiscovery(void) { // Configure Tasmota for default Home Assistant parameters to keep discovery message as short as possible @@ -485,7 +477,7 @@ void HAssDiscovery(void) Settings.flag.decimal_text = 1; // Respond with decimal color values Settings.flag3.hass_tele_on_power = 1; // send tele/STATE message as stat/RESULT // Settings.light_scheme = 0; // To just control color it needs to be Scheme 0 - if (!string_ends_with(Settings.mqtt_fulltopic, "%prefix%/")) { + if (strcmp_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"))) { strncpy_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"), sizeof(Settings.mqtt_fulltopic)); restart_flag = 2; return; // As full topic has changed do restart first before sending discovery data From ee3ab87d07828bca4da1b6693870b0ed2e27e31a Mon Sep 17 00:00:00 2001 From: Louis Lagendijk Date: Wed, 23 Jan 2019 16:06:06 +0100 Subject: [PATCH 0886/2222] Made requested changes: - Added checks for improved MAX44009 detection - removed HTTP_SNS_ILLUMINANCE_S (show only integer in web-interface) - removed missed readings and repeated detection --- sonoff/i18n.h | 1 - sonoff/my_user_config.h | 2 +- sonoff/xsns_91_max44009.ino | 60 ++++++++++++++++++------------------- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 4469ae006..a90028e8d 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -549,7 +549,6 @@ const char HTTP_SNS_PRESSURE[] PROGMEM = "%s{s}%s " D_PRESSURE "{m}%s %s{e}"; const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}"; // {s} = const char HTTP_SNS_ANALOG[] PROGMEM = "%s{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = -const char HTTP_SNS_ILLUMINANCE_S[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%s " D_UNIT_LUX "{e}"; // {s} = #if defined(USE_MHZ19) || defined(USE_SENSEAIR) || defined(USE_AZ7798) const char HTTP_SNS_CO2[] PROGMEM = "%s{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 2c02809f8..65109d3bf 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -342,7 +342,7 @@ #define MTX_ADDRESS6 0x76 // [DisplayAddress6] I2C address of sixth 8x8 matrix module #define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module #define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module - #define USE_MAX44009 // Enable MAX44009 sensor ((I2C address 0x4a 0x4b) +5k2 code) + #define USE_MAX44009 // Enable MAX44009 sensor ((I2C address 0x4a 0x4b) +6k1 code) #endif // USE_I2C // -- SPI sensors --------------------------------- diff --git a/sonoff/xsns_91_max44009.ino b/sonoff/xsns_91_max44009.ino index e113f1e01..596884879 100644 --- a/sonoff/xsns_91_max44009.ino +++ b/sonoff/xsns_91_max44009.ino @@ -22,7 +22,7 @@ /*********************************************************************************************\ * MAX44009 - Ambient Light Intensity * - * I2C Address: 0x23 or 0x5C + * I2C Address: 0x4a or 0x4b \*********************************************************************************************/ #define XSNS_91 91 @@ -91,9 +91,9 @@ void Max4409Detect(void) // supported for illiminance registers for (byte r = 0; r < MAX44009_NO_REGISTERS; r++) { if (false == Max4409Read_register(r, ®[r])) { - snprintf_P(log_data, sizeof(log_data), "MAX44009 at %x: Failed to read register %d", - max44009_address, (int)r); - AddLog(LOG_LEVEL_DEBUG); + // snprintf_P(log_data, sizeof(log_data), "MAX44009 at %x: Failed to read register %d", + // max44009_address, (int)r); + // AddLog(LOG_LEVEL_DEBUG_MORE); failed = true; break; } @@ -102,19 +102,22 @@ void Max4409Detect(void) continue; } - snprintf_P(log_data, sizeof(log_data), "MAX44009 at %x: Read %x %x %x %x %x %x %x %x", - (int) max44009_address, (int)reg[0], (int)reg[1], (int)reg[2], (int)reg[3], - (int)reg[4], (int)reg[5], (int)reg[6], (int)reg[7]); - AddLog(LOG_LEVEL_DEBUG); + // snprintf_P(log_data, sizeof(log_data), "MAX44009 at %x: Read %x %x %x %x %x %x %x %x", + // (int) max44009_address, (int)reg[0], (int)reg[1], (int)reg[2], (int)reg[3], + // (int)reg[4], (int)reg[5], (int)reg[6], (int)reg[7]); + // AddLog(LOG_LEVEL_DEBUG_MORE); if ( (0x00 == reg[0]) && (0x00 == reg[1]) && - ( (0x00 == (reg[2] & 0xc0)) || (MAX44009_CONTINUOUS_AUTO_MODE == (reg[2] & 0xc0)) ) && - (0xef == reg[5]) && + // reg[2] is written at configuration, so we cannot rely on its value after restart + // reg[3] and reg[4] will always contain lux values + // Datasheet says reg[5] is on power-up is 0xff, but we get 0xef? + // This makes sense as 0xf for exponent means invalid, so we accept both + ( (0xef == reg[5]) || (0xff == reg[5]) ) && (0x00 == reg[6]) && (0xff == reg[7])) { - // looks reasonable, try to initialize + // looks like a MAX44009, try to initialize Wire.beginTransmission(max44009_address); @@ -127,27 +130,20 @@ void Max4409Detect(void) AddLog(LOG_LEVEL_DEBUG); break; } else { - snprintf_P(log_data, sizeof(log_data), "MAX44009 at %x: config failed!", max44009_address); - AddLog(LOG_LEVEL_DEBUG); + // snprintf_P(log_data, sizeof(log_data), "MAX44009 at %x: config failed!", max44009_address); + // AddLog(LOG_LEVEL_DEBUG_MORE); } } else { - snprintf_P(log_data, sizeof(log_data), "Reading initial data failed: No MAX44009 at %x", max44009_address); - AddLog(LOG_LEVEL_DEBUG); + //snprintf_P(log_data, sizeof(log_data), "Reading initial data failed: No MAX44009 at %x", max44009_address); + //AddLog(LOG_LEVEL_DEBUG_MORE); } } } void Max4409EverySecond(void) { - if (90 == (uptime %100)) { - // 1mS - Max4409Detect(); - } - else { - // 1mS - if (max44009_found) { - Max4409Read_lum(); - } + if (max44009_found) { + Max4409Read_lum(); } } @@ -157,7 +153,7 @@ void Max4409Show(boolean json) if (max44009_valid) { - /* convert illuminance to fixed size string */ + /* convert illuminance to string with suitable accuracy */ if (max44009_illuminance < 10) { dtostrf(max44009_illuminance, sizeof(illum_str) -1, 3, illum_str); } else if (max44009_illuminance < 100) { @@ -169,7 +165,9 @@ void Max4409Show(boolean json) } if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), mqtt_data, max44009_types, illum_str); + snprintf_P(mqtt_data, sizeof(mqtt_data), + PSTR("%s,\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), + mqtt_data, max44009_types, illum_str); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, illum_str); @@ -177,7 +175,9 @@ void Max4409Show(boolean json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE_S, mqtt_data, max44009_types, illum_str); + // show integer value for lx on web-server + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE, + mqtt_data, max44009_types, (int)max44009_illuminance); #endif // USE_WEBSERVER } } @@ -193,9 +193,9 @@ boolean Xsns91(byte function) if (i2c_flg) { switch (function) { -// case FUNC_INIT: -// Max4409Detect(); -// break; + case FUNC_INIT: + Max4409Detect(); + break; case FUNC_EVERY_SECOND: Max4409EverySecond(); break; From 4cdc3d5404c688a848770c4e04d66854d50e50f0 Mon Sep 17 00:00:00 2001 From: Louis Lagendijk Date: Wed, 23 Jan 2019 22:20:29 +0100 Subject: [PATCH 0887/2222] Implemented changes suggested by Theo (Thanks!): - use functions from support.ino (had to split reading in Max4409Detect in 2 8 bits reads as the MAX44009 only supports 16 bits reads for luminance registers) - Used the << instead of pow() to save a lot of xompiled code - Improved float -> string conversion along the suggested lines - Code size is now +/- 750 bytes (without other I2C sensors compiled in I think --- sonoff/my_user_config.h | 2 +- sonoff/xsns_91_max44009.ino | 130 +++++++++++++----------------------- 2 files changed, 48 insertions(+), 84 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 65109d3bf..83830916f 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -342,7 +342,7 @@ #define MTX_ADDRESS6 0x76 // [DisplayAddress6] I2C address of sixth 8x8 matrix module #define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module #define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module - #define USE_MAX44009 // Enable MAX44009 sensor ((I2C address 0x4a 0x4b) +6k1 code) + #define USE_MAX44009 // Enable MAX44009 sensor ((I2C address 0x4a 0x4b) +0k8 code) #endif // USE_I2C // -- SPI sensors --------------------------------- diff --git a/sonoff/xsns_91_max44009.ino b/sonoff/xsns_91_max44009.ino index 596884879..a0aa51a47 100644 --- a/sonoff/xsns_91_max44009.ino +++ b/sonoff/xsns_91_max44009.ino @@ -30,8 +30,11 @@ #define MAX44009_ADDR1 0x4A #define MAX44009_ADDR2 0x4B #define MAX44009_NO_REGISTERS 8 -#define REG_CONFIG 0x02 -#define REG_LUMINANCE 0x03 +#define REG_CONFIG 0x02 +#define REG_LUMINANCE 0x03 +#define REG_LOWER_THRESHOLD 0x06 +#define REG_THRESHOLD_TIMER 0x07 + #define MAX44009_CONTINUOUS_AUTO_MODE 0x80 // Start measurement in automatic, continous mode uint8_t max44009_address; @@ -44,33 +47,18 @@ char max44009_types[] = "MAX44009"; bool Max4409Read_lum(void) { max44009_valid = 0; - /* Select luminance start register */ - Wire.beginTransmission(max44009_address); - Wire.write(REG_LUMINANCE); - Wire.endTransmission(); + uint8_t regdata[2]; - if (2 != Wire.requestFrom(max44009_address, (uint8_t)2)) { - return false; + /* Read 2 bytes luminance */ + if (I2cValidRead16((uint16_t *)®data, max44009_address, REG_LUMINANCE)) { + int exponent = (regdata[0] & 0xF0) >> 4; + int mantissa = ((regdata[0] & 0x0F) << 4) | (regdata[1] & 0x0F); + max44009_illuminance = (float)(((0x00000001 << exponent) * (float)mantissa) * 0.045); + max44009_valid = 1; + return true; + } else { + return false; } - byte msb = Wire.read(); - byte lsb = Wire.read(); - int exponent = (msb & 0xF0) >> 4; - int mantissa = ((msb & 0x0F) << 4) | (lsb & 0x0F); - max44009_illuminance = pow(2, exponent) * mantissa * 0.045; - - max44009_valid = 1; - return true; -} - -bool Max4409Read_register(uint8_t regno, byte *value) { - Wire.beginTransmission(max44009_address); - Wire.write(regno); - if ((0 != Wire.endTransmission()) || - (1 != Wire.requestFrom(max44009_address, (uint8_t)1))) { - return false; - } - *value = (byte)Wire.read(); - return true; } /********************************************************************************************/ @@ -84,58 +72,33 @@ void Max4409Detect(void) return; } + uint8_t buffer1; + uint8_t buffer2; for (byte i = 0; 0 != max44009_addresses[i]; i++) { + max44009_address = max44009_addresses[i]; - // we need to read each register separately, as auto-increment is only - // supported for illiminance registers - for (byte r = 0; r < MAX44009_NO_REGISTERS; r++) { - if (false == Max4409Read_register(r, ®[r])) { - // snprintf_P(log_data, sizeof(log_data), "MAX44009 at %x: Failed to read register %d", - // max44009_address, (int)r); - // AddLog(LOG_LEVEL_DEBUG_MORE); - failed = true; - break; - } - } - if (failed) { - continue; - } - - // snprintf_P(log_data, sizeof(log_data), "MAX44009 at %x: Read %x %x %x %x %x %x %x %x", - // (int) max44009_address, (int)reg[0], (int)reg[1], (int)reg[2], (int)reg[3], - // (int)reg[4], (int)reg[5], (int)reg[6], (int)reg[7]); - // AddLog(LOG_LEVEL_DEBUG_MORE); - - if ( (0x00 == reg[0]) && - (0x00 == reg[1]) && - // reg[2] is written at configuration, so we cannot rely on its value after restart - // reg[3] and reg[4] will always contain lux values - // Datasheet says reg[5] is on power-up is 0xff, but we get 0xef? - // This makes sense as 0xf for exponent means invalid, so we accept both - ( (0xef == reg[5]) || (0xff == reg[5]) ) && - (0x00 == reg[6]) && - (0xff == reg[7])) { - - // looks like a MAX44009, try to initialize - - Wire.beginTransmission(max44009_address); - - // select configuration register and set mode - Wire.write(REG_CONFIG); - Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); - if (0 == Wire.endTransmission()) { - max44009_found = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, max44009_types, max44009_address); - AddLog(LOG_LEVEL_DEBUG); - break; - } else { - // snprintf_P(log_data, sizeof(log_data), "MAX44009 at %x: config failed!", max44009_address); - // AddLog(LOG_LEVEL_DEBUG_MORE); - } - } else { - //snprintf_P(log_data, sizeof(log_data), "Reading initial data failed: No MAX44009 at %x", max44009_address); + if ((I2cValidRead8(&buffer1, max44009_address, REG_LOWER_THRESHOLD)) && + (I2cValidRead8(&buffer2, max44009_address, REG_THRESHOLD_TIMER))) { + //snprintf(log_data, sizeof(log_data), "MAX44009 %x: %x, %x", max44009_address, (int)buffer1, (int)buffer2); //AddLog(LOG_LEVEL_DEBUG_MORE); + if ((0x00 == buffer1) && + (0xFF == buffer2)) { + + // looks like a MAX44009, try to initialize + + Wire.beginTransmission(max44009_address); + + // select configuration register and set mode + Wire.write(REG_CONFIG); + Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); + if (0 == Wire.endTransmission()) { + max44009_found = 1; + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, max44009_types, max44009_address); + AddLog(LOG_LEVEL_DEBUG); + break; + } + } } } } @@ -154,15 +117,16 @@ void Max4409Show(boolean json) if (max44009_valid) { /* convert illuminance to string with suitable accuracy */ - if (max44009_illuminance < 10) { - dtostrf(max44009_illuminance, sizeof(illum_str) -1, 3, illum_str); - } else if (max44009_illuminance < 100) { - dtostrf(max44009_illuminance, sizeof(illum_str) -1, 2, illum_str); - } else if (max44009_illuminance < 1000) { - dtostrf(max44009_illuminance, sizeof(illum_str) -1, 1, illum_str); - } else { - dtostrf(max44009_illuminance, sizeof(illum_str) -1, 0, illum_str); + + uint8_t prec = 0; + if (10 > max44009_illuminance ) { + prec = 3; + } else if (100 > max44009_illuminance) { + prec = 2; + } else if (1000 > max44009_illuminance) { + prec = 1; } + dtostrf(max44009_illuminance, sizeof(illum_str) -1, prec, illum_str); if (json) { snprintf_P(mqtt_data, sizeof(mqtt_data), From caabada2141d08bcf780118327b2f140299bdf32 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 24 Jan 2019 11:21:16 +0100 Subject: [PATCH 0888/2222] Update my_user_config.h --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 83830916f..83bbb7b65 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -328,6 +328,7 @@ // #define USE_PN532_I2C // Enable PN532 - Near Field Communication (NFC) controller (+1k7 code, 164 bytes of mem) // #define USE_PN532_DATA_FUNCTION // Enable PN532 DATA Usage using Sensor15 command (+1k6 code, 316 bytes of mem) // #define USE_PN532_CAUSE_EVENTS // Enable PN532 driver to cause event's on card read in addition to immediate telemetry (+64 bytes code, 48 bytes mem) +// #define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 @@ -342,7 +343,6 @@ #define MTX_ADDRESS6 0x76 // [DisplayAddress6] I2C address of sixth 8x8 matrix module #define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module #define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module - #define USE_MAX44009 // Enable MAX44009 sensor ((I2C address 0x4a 0x4b) +0k8 code) #endif // USE_I2C // -- SPI sensors --------------------------------- From ced019eaa53de2dc853d5789f20609d8e6879c06 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 24 Jan 2019 11:41:52 +0100 Subject: [PATCH 0889/2222] Add support for MAX44009 Add support for MAX44009 Ambient Light sensor (#4907) --- sonoff/_changelog.ino | 1 + sonoff/sonoff_post.h | 1 + sonoff/support_features.ino | 4 ++- ...s_91_max44009.ino => xsns_41_max44009.ino} | 26 +++++++++---------- tools/decode-status.py | 2 +- 5 files changed, 19 insertions(+), 15 deletions(-) rename sonoff/{xsns_91_max44009.ino => xsns_41_max44009.ino} (92%) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index a32d7f7f2..47f2132a1 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.4.1.10 20190121 * Fix Hass discovery of MHZ19(B) sensors (#4992) * Fix Hass Software Watchdog exception during discovery (#4988) + * Add support for MAX44009 Ambient Light sensor (#4907) * * 6.4.1.9 20190115 * Add support for Mi LED Desk Lamp with rotary switch (#4887) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 5defb494d..726ec6cba 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -93,6 +93,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); //#define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) //#define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) //#define USE_PN532_I2C // Enable PN532 - Near Field Communication (NFC) controller (+1k6 code) +//#define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code) #define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) #define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) #ifndef CO2_LOW diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 21d67178b..6c1abf97a 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -379,7 +379,9 @@ void GetFeatures(void) #ifdef USE_PN532_I2C feature_sns2 |= 0x00100000; // xsns_40_pn532_i2c.ino #endif -// feature_sns2 |= 0x00200000; +#ifdef USE_MAX44009 + feature_sns2 |= 0x00200000; +#endif // feature_sns2 |= 0x00400000; // feature_sns2 |= 0x00800000; // feature_sns2 |= 0x01000000; diff --git a/sonoff/xsns_91_max44009.ino b/sonoff/xsns_41_max44009.ino similarity index 92% rename from sonoff/xsns_91_max44009.ino rename to sonoff/xsns_41_max44009.ino index a0aa51a47..92bd7d8a7 100644 --- a/sonoff/xsns_91_max44009.ino +++ b/sonoff/xsns_41_max44009.ino @@ -1,5 +1,5 @@ /* - xsns_91_max44009.ino - MAX44009 ambient light sensor support for Sonoff-Tasmota + xsns_41_max44009.ino - MAX44009 ambient light sensor support for Sonoff-Tasmota Copyright (C) 2019 Theo Arends @@ -25,7 +25,7 @@ * I2C Address: 0x4a or 0x4b \*********************************************************************************************/ -#define XSNS_91 91 +#define XSNS_41 41 #define MAX44009_ADDR1 0x4A #define MAX44009_ADDR2 0x4B @@ -41,7 +41,7 @@ uint8_t max44009_address; uint8_t max44009_addresses[] = { MAX44009_ADDR1, MAX44009_ADDR2, 0 }; //0 terminated list uint8_t max44009_found = 0; uint8_t max44009_valid = 0; -float max44009_illuminance = 0; +float max44009_illuminance = 0; char max44009_types[] = "MAX44009"; bool Max4409Read_lum(void) @@ -53,7 +53,7 @@ bool Max4409Read_lum(void) if (I2cValidRead16((uint16_t *)®data, max44009_address, REG_LUMINANCE)) { int exponent = (regdata[0] & 0xF0) >> 4; int mantissa = ((regdata[0] & 0x0F) << 4) | (regdata[1] & 0x0F); - max44009_illuminance = (float)(((0x00000001 << exponent) * (float)mantissa) * 0.045); + max44009_illuminance = (float)(((0x00000001 << exponent) * (float)mantissa) * 0.045); max44009_valid = 1; return true; } else { @@ -84,12 +84,12 @@ void Max4409Detect(void) //AddLog(LOG_LEVEL_DEBUG_MORE); if ((0x00 == buffer1) && (0xFF == buffer2)) { - - // looks like a MAX44009, try to initialize - + + // looks like a MAX44009, try to initialize + Wire.beginTransmission(max44009_address); - // select configuration register and set mode + // select configuration register and set mode Wire.write(REG_CONFIG); Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); if (0 == Wire.endTransmission()) { @@ -119,7 +119,7 @@ void Max4409Show(boolean json) /* convert illuminance to string with suitable accuracy */ uint8_t prec = 0; - if (10 > max44009_illuminance ) { + if (10 > max44009_illuminance ) { prec = 3; } else if (100 > max44009_illuminance) { prec = 2; @@ -129,8 +129,8 @@ void Max4409Show(boolean json) dtostrf(max44009_illuminance, sizeof(illum_str) -1, prec, illum_str); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), - PSTR("%s,\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), + snprintf_P(mqtt_data, sizeof(mqtt_data), + PSTR("%s,\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), mqtt_data, max44009_types, illum_str); #ifdef USE_DOMOTICZ if (0 == tele_period) { @@ -140,7 +140,7 @@ void Max4409Show(boolean json) #ifdef USE_WEBSERVER } else { // show integer value for lx on web-server - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE, + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE, mqtt_data, max44009_types, (int)max44009_illuminance); #endif // USE_WEBSERVER } @@ -151,7 +151,7 @@ void Max4409Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns91(byte function) +boolean Xsns41(byte function) { boolean result = false; diff --git a/tools/decode-status.py b/tools/decode-status.py index 04b549465..1b9478a8e 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -137,7 +137,7 @@ a_features = [[ "USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711", "USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","USE_RF_SENSOR", "USE_THEO_V2","USE_ALECTO_V2","USE_AZ7798","USE_MAX31855", - "USE_PN532_I2C","","","", + "USE_PN532_I2C","USE_MAX44009","","", "","","","", "","","",""]] From eab6be8bcbcd241140c7ea82364c1b3d4ffc4f3c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 24 Jan 2019 11:55:31 +0100 Subject: [PATCH 0890/2222] Fix WS2812 led command Fix WS2812 led command to address last pixel (#5015) --- sonoff/xdrv_04_light.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index ef4540401..bfeaf889f 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -1203,7 +1203,7 @@ boolean LightCommand(void) if (LightColorEntry(color, strlen(color))) { Ws2812SetColor(idx, light_entry_color[0], light_entry_color[1], light_entry_color[2], light_entry_color[3]); idx++; - if (idx >= Settings.light_pixels) break; + if (idx > Settings.light_pixels) break; } else { break; } From 505c4794d1bd4cac7bb4894d0b85f934e2e3f03e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 25 Jan 2019 17:46:27 +0100 Subject: [PATCH 0891/2222] 6.4.1.11 Rewrite interlock 6.4.1.11 20190124 * Remove command SetOption14 as it has been superseded by command Interlock * Remove command SetOption63 as it has been superseded by command Interlock * Add command Interlock 0 / 1 / 1,2 3,4 .. to control interlock ON/OFF and add up to 8 relays in 1 to 4 interlock groups (#5014) --- sonoff/_changelog.ino | 7 +- sonoff/i18n.h | 2 + sonoff/settings.h | 6 +- sonoff/settings.ino | 5 +- sonoff/sonoff.h | 1 + sonoff/sonoff.ino | 141 ++++++++++++++++++++++++++-------------- sonoff/sonoff_version.h | 2 +- 7 files changed, 108 insertions(+), 56 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 47f2132a1..4388afb82 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,9 @@ -/* 6.4.1.10 20190121 +/* 6.4.1.11 20190124 + * Remove command SetOption14 as it has been superseded by command Interlock + * Remove command SetOption63 as it has been superseded by command Interlock + * Add command Interlock 0 / 1 / 1,2 3,4 .. to control interlock ON/OFF and add up to 8 relays in 1 to 4 interlock groups (#5014) + * + * 6.4.1.10 20190121 * Fix Hass discovery of MHZ19(B) sensors (#4992) * Fix Hass Software Watchdog exception during discovery (#4988) * Add support for MAX44009 Ambient Light sensor (#4907) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 1003a3996..39f054a01 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -72,6 +72,7 @@ #define D_JSON_FROM "from" #define D_JSON_GAS "Gas" #define D_JSON_GATEWAY "Gateway" +#define D_JSON_GROUPS "Groups" #define D_JSON_HEAPSIZE "Heap" #define D_JSON_HIGH "High" #define D_JSON_HOST_NOT_FOUND "Host not found" @@ -241,6 +242,7 @@ #define D_WCFG_6_SERIAL "Serial" #define D_CMND_FRIENDLYNAME "FriendlyName" #define D_CMND_SWITCHMODE "SwitchMode" +#define D_CMND_INTERLOCK "Interlock" #define D_CMND_TELEPERIOD "TelePeriod" #define D_CMND_RESTART "Restart" #define D_JSON_ONE_TO_RESTART "1 to restart" diff --git a/sonoff/settings.h b/sonoff/settings.h index a6f846aec..99c2ddb26 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -76,7 +76,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t sleep_normal : 1; // bit 10 (v6.3.0.15) - SetOption60 - Enable normal sleep instead of dynamic sleep uint32_t button_switch_force_local : 1;// bit 11 (v6.3.0.16) - SetOption61 - Force local operation when button/switch topic is set uint32_t no_pullup : 1; // bit 12 (v6.4.1.7) - SetOption62 - Force no pull-up (0 = (no)pull-up, 1 = no pull-up) - uint32_t split_interlock : 1; // bit 13 (v6.4.1.8) - SetOption63 - Split interlock on CH4 + uint32_t spare13 : 1; uint32_t spare14 : 1; uint32_t spare15 : 1; uint32_t spare16 : 1; @@ -286,9 +286,7 @@ struct SYSCFG { uint16_t light_wakeup; // 4A6 byte knx_CB_registered; // 4A8 Number of Group Address to write char web_password[33]; // 4A9 - - uint8_t ex_switchmode[4]; // 4CA Free since 6.0.0a - + uint8_t interlock[MAX_INTERLOCKS]; // 4CA char ntp_server[3][33]; // 4CE byte ina219_mode; // 531 uint16_t pulse_timer[MAX_PULSETIMERS]; // 532 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 65f42e979..c483977f5 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -976,7 +976,7 @@ void SettingsDelta(void) if (Settings.version < 0x06000002) { for (byte i = 0; i < MAX_SWITCHES; i++) { if (i < 4) { - Settings.switchmode[i] = Settings.ex_switchmode[i]; + Settings.switchmode[i] = Settings.interlock[i]; } else { Settings.switchmode[i] = SWITCH_MODE; } @@ -1022,6 +1022,9 @@ void SettingsDelta(void) Settings.flag3.mdns_enabled = MDNS_ENABLED; Settings.param[P_MDNS_DELAYED_START] = 0; } + if (Settings.version < 0x0604010B) { + for (byte i = 0; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index c520d3981..699d8c819 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -51,6 +51,7 @@ typedef unsigned long power_t; // Power (Relay) type // Changes to the following MAX_ defines will impact settings layout #define MAX_SWITCHES 8 // Max number of switches #define MAX_RELAYS 8 // Max number of relays +#define MAX_INTERLOCKS 4 // Max number of interlock groups (MAX_RELAYS / 2) #define MAX_LEDS 4 // Max number of leds #define MAX_KEYS 4 // Max number of keys or buttons #define MAX_PWMS 5 // Max number of PWM channels diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 43ac0ce3b..ac82f968d 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -75,7 +75,7 @@ enum TasmotaCommands { CMND_MODULE, CMND_MODULES, CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE, CMND_COUNTERDEBOUNCE, CMND_BUTTONDEBOUNCE, CMND_SWITCHDEBOUNCE, 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_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_INTERLOCK, CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_TIMESTD, CMND_TIMEDST, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER, CMND_DRIVER }; const char kTasmotaCommands[] PROGMEM = @@ -85,7 +85,7 @@ const char kTasmotaCommands[] PROGMEM = 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_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" 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_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER "|" D_CMND_DRIVER; @@ -318,33 +318,19 @@ void SetDevicePower(power_t rpower, int source) power = (1 << devices_present) -1; rpower = power; } - if (Settings.flag3.split_interlock) { - Settings.flag.interlock = 1; // prevent the situation where interlock is off and split-interlock is on - uint8_t mask = 0x01; - uint8_t count = 0; - byte result1 = 0; - byte result2 = 0; - for (byte i = 0; i < devices_present; i++) { - if (rpower & mask) { - if (i <2) { result1++;}//increment if low part is ON - if (i >1) { result2++;}//increment if high part is ON - } - mask <<= 1; // shift the bitmask one left (1,2,4,8) to find out what is on - } - if ((result1) >1 && (result2 >1)) {power = 0; rpower = 0;} // all 4 switch are on, something is wrong, so we turn all off - if ((result1) >1 && (result2 <2)) {power = power & 0x0C; rpower = power;} // 1/2 are both on and 3/4 max one is on - if ((result1) <2 && (result2 >1)) {power = power & 0x03; rpower = power;} // 1/2 max one is on and 3/4 both are on - } else { - if (Settings.flag.interlock) { // Allow only one or no relay set + + if (Settings.flag.interlock) { // Allow only one or no relay set + for (byte i = 0; i < MAX_INTERLOCKS; i++) { power_t mask = 1; uint8_t count = 0; - for (byte i = 0; i < devices_present; i++) { - if (rpower & mask) count++; + for (byte j = 0; j < devices_present; j++) { + if ((Settings.interlock[i] & mask) && (rpower & mask)) { count++; } mask <<= 1; } if (count > 1) { - power = 0; - rpower = 0; + mask = ~Settings.interlock[i]; // Turn interlocked group off as there would be multiple relays on + power &= mask; + rpower &= mask; } } } @@ -754,6 +740,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) case 6: // mqtt_button_retain (CMND_BUTTONRETAIN) case 7: // mqtt_switch_retain (CMND_SWITCHRETAIN) case 9: // mqtt_sensor_retain (CMND_SENSORRETAIN) + case 14: // interlock (CMND_INTERLOCK) case 22: // mqtt_serial (SerialSend and SerialLog) case 23: // mqtt_serial_raw (SerialSend) case 25: // knx_enabled (Web config) @@ -1181,6 +1168,74 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, index, Settings.switchmode[index-1]); } + else if (CMND_INTERLOCK == command_code) { // Interlock 0 - Off, Interlock 1 - On, Interlock 1,2 3,4 5,6,7 + uint8_t max_relays = devices_present; + if (light_type) { max_relays--; } + if (max_relays > sizeof(Settings.interlock[0]) * 8) { max_relays = sizeof(Settings.interlock[0]) * 8; } + if (max_relays > 1) { // Only interlock with more than 1 relay + if (data_len > 0) { + if (strstr(dataBuf, ",")) { // Interlock entry + for (byte i = 0; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } // Reset current interlocks + char *group; + char *q; + uint8_t group_index = 0; + power_t relay_mask = 0; + for (group = strtok_r(dataBuf, " ", &q); group && group_index < MAX_INTERLOCKS; group = strtok_r(NULL, " ", &q)) { + char *str; + for (str = strtok_r(group, ",", &p); str; str = strtok_r(NULL, ",", &p)) { + int pbit = atoi(str); + if ((pbit > 0) && (pbit <= max_relays)) { // Only valid relays + pbit--; + if (!bitRead(relay_mask, pbit)) { // Only relay once + bitSet(relay_mask, pbit); + bitSet(Settings.interlock[group_index], pbit); + } + } + } + group_index++; + } + for (byte i = 0; i < group_index; i++) { + uint8_t minimal_bits = 0; + for (byte j = 0; j < max_relays; j++) { + if (bitRead(Settings.interlock[i], j)) { minimal_bits++; } + } + if (minimal_bits < 2) { Settings.interlock[i] = 0; } // Discard single relay as interlock + } + } else { + Settings.flag.interlock = payload &1; // Enable/disable interlock + if (Settings.flag.interlock) { + SetDevicePower(power, SRC_IGNORE); // Remove multiple relays if set + } + } + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_INTERLOCK "\":\"%s\",\"" D_JSON_GROUPS "\":\""), GetStateText(Settings.flag.interlock)); + uint8_t anygroup = 0; + for (byte i = 0; i < MAX_INTERLOCKS; i++) { + if (Settings.interlock[i]) { + anygroup++; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s"), mqtt_data, (anygroup > 1) ? " " : ""); + uint8_t anybit = 0; + power_t mask = 1; + for (byte j = 0; j < max_relays; j++) { + if (Settings.interlock[i] & mask) { + anybit++; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (anybit > 1) ? "," : "", j +1); + } + mask <<= 1; + } + } + } + if (!anygroup) { + for (byte j = 1; j <= max_relays; j++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (j > 1) ? "," : "", j); + } + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); + } else { + Settings.flag.interlock = 0; + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.interlock)); + } + } else if (CMND_TELEPERIOD == command_code) { if ((payload >= 0) && (payload < 3601)) { Settings.tele_period = (1 == payload) ? TELE_PERIOD : payload; @@ -1400,41 +1455,29 @@ void ExecuteCommandPower(byte device, byte state, int source) } if ((device < 1) || (device > devices_present)) device = 1; if (device <= MAX_PULSETIMERS) { SetPulseTimer(device -1, 0); } - power_t mask = 1 << (device -1); + power_t mask = 1 << (device -1); // Device to control if (state <= POWER_TOGGLE) { if ((blink_mask & mask)) { blink_mask &= (POWER_MASK ^ mask); // Clear device mask MqttPublishPowerBlinkState(device); } - if (Settings.flag3.split_interlock && !Settings.flag.interlock ) Settings.flag.interlock=1; // ensure interlock is on, in case split_interlock is on - // check if channel 1/2 or 3/4 are to be changed - if (device <= 2 && Settings.flag3.split_interlock ) { // channel 1/2 are changed - if (Settings.flag3.split_interlock && !interlock_mutex) { // Clear all but masked relay, but only if we are not already doing something + + if (Settings.flag.interlock && !interlock_mutex) { // Clear all but masked relay in interlock group interlock_mutex = 1; - for (byte i = 0; i < 2; i++) { - byte imask = 0x01 << i; - if ((power & imask) && (mask != imask)) { ExecuteCommandPower(i +1, POWER_OFF, SRC_IGNORE); delay(50); }// example, first power is ON but the pushed button is not the first, then powerOFF the first one + for (byte i = 0; i < MAX_INTERLOCKS; i++) { + if (Settings.interlock[i] & mask) { // Find interlock group + for (byte j = 0; j < devices_present; j++) { + power_t imask = 1 << j; + if ((Settings.interlock[i] & imask) && (power & imask) && (mask != imask)) { + ExecuteCommandPower(j +1, POWER_OFF, SRC_IGNORE); + } + } + break; // An interlocked relay is only present in one group so quit } - interlock_mutex = 0; // avoid infinite loop due to recursive requests - } - } else { // channel 3/4 are changed - if (Settings.flag3.split_interlock && !interlock_mutex) { // only start if we are on interlock split and have no re-call - interlock_mutex = 1; - for (byte i = 2; i < devices_present; i++) { - byte imask = 0x01 << i; - if ((power & imask) && (mask != imask)) ExecuteCommandPower(i +1, POWER_OFF, SRC_IGNORE); - } - interlock_mutex = 0; - } - } - if ( Settings.flag.interlock && !interlock_mutex && !Settings.flag3.split_interlock) { //execute regular interlock-mode as interlock-split is off - interlock_mutex = 1; - for (byte i = 0; i < devices_present; i++) { - power_t imask = 1 << i; - if ((power & imask) && (mask != imask)) ExecuteCommandPower(i +1, POWER_OFF, SRC_IGNORE); } interlock_mutex = 0; } + switch (state) { case POWER_OFF: { power &= (POWER_MASK ^ mask); diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 47bbb82f2..ff290a84c 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0604010A +#define VERSION 0x0604010B #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" From 1fb7eb646fba2a95aecfc1cc65a9dc705d89731e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 25 Jan 2019 18:30:10 +0100 Subject: [PATCH 0892/2222] Add 50 mSec delay Add 50 mSec delay between interlocked relay switch --- sonoff/sonoff.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ac82f968d..bec71038d 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1470,6 +1470,7 @@ void ExecuteCommandPower(byte device, byte state, int source) power_t imask = 1 << j; if ((Settings.interlock[i] & imask) && (power & imask) && (mask != imask)) { ExecuteCommandPower(j +1, POWER_OFF, SRC_IGNORE); + delay(50); // Add some delay to make sure never have more than one relay on } } break; // An interlocked relay is only present in one group so quit From f0b56c6b8ad7e55de69c0a82eaf2b6ff3af8e700 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sat, 26 Jan 2019 08:58:21 +0100 Subject: [PATCH 0893/2222] Changed core 2.5.0 to version Beta3 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 461ca61ea..e1cd74df5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -65,7 +65,7 @@ build_flags = ${esp82xx_defaults.build_flags} -DVTABLES_IN_FLASH [core_2_5_0] -; *** Esp8266 core for Arduino version Core 2.5.0 beta tested for Tasmota +; *** Esp8266 core for Arduino version Core 2.5.0 beta3 tested for Tasmota platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld From 0870b5a7e89067045d92ec772954e91f018bd029 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sat, 26 Jan 2019 09:33:11 +0100 Subject: [PATCH 0894/2222] Update platformio.ini --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index e1cd74df5..6b6176db0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -81,7 +81,7 @@ build_flags = ${esp82xx_defaults.build_flags} -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -DVTABLES_IN_FLASH -fno-exceptions - -lstdc++-nox + -lstdc++ [core_stage] ; *** Esp8266 core for Arduino version latest beta From f5a20534f3c70fe179dc84bdd48cf8328bac1c7e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 26 Jan 2019 12:03:58 +0100 Subject: [PATCH 0895/2222] Add tasmotized core 2.5.0-beta3 files Add tasmotized boards.txt and platform.txt for core 2.5.0-beta3 (#5026) --- .../boards.txt | 0 .../platform.txt | 0 arduino/version 2.5.0-beta3/boards.txt | 6122 +++++++++++++++++ arduino/version 2.5.0-beta3/platform.txt | 154 + 4 files changed, 6276 insertions(+) rename arduino/{version 2.5.0 => version 2.5.0-beta2}/boards.txt (100%) rename arduino/{version 2.5.0 => version 2.5.0-beta2}/platform.txt (100%) create mode 100644 arduino/version 2.5.0-beta3/boards.txt create mode 100644 arduino/version 2.5.0-beta3/platform.txt diff --git a/arduino/version 2.5.0/boards.txt b/arduino/version 2.5.0-beta2/boards.txt similarity index 100% rename from arduino/version 2.5.0/boards.txt rename to arduino/version 2.5.0-beta2/boards.txt diff --git a/arduino/version 2.5.0/platform.txt b/arduino/version 2.5.0-beta2/platform.txt similarity index 100% rename from arduino/version 2.5.0/platform.txt rename to arduino/version 2.5.0-beta2/platform.txt diff --git a/arduino/version 2.5.0-beta3/boards.txt b/arduino/version 2.5.0-beta3/boards.txt new file mode 100644 index 000000000..542054e59 --- /dev/null +++ b/arduino/version 2.5.0-beta3/boards.txt @@ -0,0 +1,6122 @@ +# +# Do not create pull-requests for this file only, CI will not accept them. +# You *must* edit/modify/run boards.txt.py to regenerate boards.txt. +# All modified files after running with option "--allgen" must be included in the pull-request. +# + +menu.BoardModel=Model +menu.baud=Upload Speed +menu.UploadTool=Upload Using +menu.xtal=CPU Frequency +menu.CrystalFreq=Crystal Frequency +menu.eesz=Flash Size +menu.FlashMode=Flash Mode +menu.FlashFreq=Flash Frequency +menu.ResetMethod=Reset Method +menu.ESPModule=Module +menu.dbg=Debug port +menu.lvl=Debug Level +menu.ip=lwIP Variant +menu.vt=VTables +menu.exception=Exceptions +menu.led=Builtin Led +menu.wipe=Erase Flash + +############################################################## +generic.name=Generic ESP8266 Module +generic.build.board=ESP8266_GENERIC +generic.upload.tool=esptool +generic.upload.maximum_data_size=81920 +generic.upload.wait_for_upload_port=true +generic.upload.erase_cmd= +generic.serial.disableDTR=true +generic.serial.disableRTS=true +generic.build.mcu=esp8266 +generic.build.core=esp8266 +generic.build.variant=generic +generic.build.spiffs_pagesize=256 +generic.build.debug_port= +generic.build.debug_level= + +generic.menu.UploadTool.esptool=Serial +generic.menu.UploadTool.esptool.upload.tool=esptool +generic.menu.UploadTool.esptool.upload.verbose=-vv +generic.menu.UploadTool.espupload=OTA_upload +generic.menu.UploadTool.espupload.upload.tool=espupload + +generic.menu.xtal.80=80 MHz +generic.menu.xtal.80.build.f_cpu=80000000L +generic.menu.xtal.160=160 MHz +generic.menu.xtal.160.build.f_cpu=160000000L +generic.menu.vt.flash=Flash +generic.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +generic.menu.vt.heap=Heap +generic.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +generic.menu.vt.iram=IRAM +generic.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +generic.menu.exception.disabled=Disabled +generic.menu.exception.disabled.build.exception_flags=-fno-exceptions +generic.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +generic.menu.exception.enabled=Enabled +generic.menu.exception.enabled.build.exception_flags=-fexceptions +generic.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +generic.menu.ResetMethod.ck=ck +generic.menu.ResetMethod.ck.upload.resetmethod=ck +generic.menu.ResetMethod.nodemcu=nodemcu +generic.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +generic.menu.ResetMethod.none=none +generic.menu.ResetMethod.none.upload.resetmethod=none +generic.menu.ResetMethod.dtrset=dtrset +generic.menu.ResetMethod.dtrset.upload.resetmethod=dtrset +generic.menu.CrystalFreq.26=26 MHz +generic.menu.CrystalFreq.40=40 MHz +generic.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +generic.menu.FlashFreq.40=40MHz +generic.menu.FlashFreq.40.build.flash_freq=40 +generic.menu.FlashFreq.80=80MHz +generic.menu.FlashFreq.80.build.flash_freq=80 +generic.menu.FlashMode.dout=DOUT (compatible) +generic.menu.FlashMode.dout.build.flash_mode=dout +generic.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT +generic.menu.FlashMode.dio=DIO +generic.menu.FlashMode.dio.build.flash_mode=dio +generic.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO +generic.menu.FlashMode.qout=QOUT +generic.menu.FlashMode.qout.build.flash_mode=qout +generic.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT +generic.menu.FlashMode.qio=QIO (fast) +generic.menu.FlashMode.qio.build.flash_mode=qio +generic.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO +generic.menu.eesz.512K=512K (no SPIFFS) +generic.menu.eesz.512K.build.flash_size=512K +generic.menu.eesz.512K.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +generic.menu.eesz.512K.build.spiffs_pagesize=256 +generic.menu.eesz.512K.upload.maximum_size=499696 +generic.menu.eesz.512K.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K32=512K (32K SPIFFS) +generic.menu.eesz.512K32.build.flash_size=512K +generic.menu.eesz.512K32.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +generic.menu.eesz.512K32.build.spiffs_pagesize=256 +generic.menu.eesz.512K32.upload.maximum_size=466928 +generic.menu.eesz.512K32.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K32.build.spiffs_start=0x73000 +generic.menu.eesz.512K32.build.spiffs_end=0x7B000 +generic.menu.eesz.512K32.build.spiffs_blocksize=4096 +generic.menu.eesz.512K64=512K (64K SPIFFS) +generic.menu.eesz.512K64.build.flash_size=512K +generic.menu.eesz.512K64.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +generic.menu.eesz.512K64.build.spiffs_pagesize=256 +generic.menu.eesz.512K64.upload.maximum_size=434160 +generic.menu.eesz.512K64.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K64.build.spiffs_start=0x6B000 +generic.menu.eesz.512K64.build.spiffs_end=0x7B000 +generic.menu.eesz.512K64.build.spiffs_blocksize=4096 +generic.menu.eesz.512K128=512K (128K SPIFFS) +generic.menu.eesz.512K128.build.flash_size=512K +generic.menu.eesz.512K128.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +generic.menu.eesz.512K128.build.spiffs_pagesize=256 +generic.menu.eesz.512K128.upload.maximum_size=368624 +generic.menu.eesz.512K128.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K128.build.spiffs_start=0x5B000 +generic.menu.eesz.512K128.build.spiffs_end=0x7B000 +generic.menu.eesz.512K128.build.spiffs_blocksize=4096 +generic.menu.eesz.1M=1M (no SPIFFS) +generic.menu.eesz.1M.build.flash_size=1M +generic.menu.eesz.1M.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +generic.menu.eesz.1M.build.spiffs_pagesize=256 +generic.menu.eesz.1M.upload.maximum_size=1023984 +generic.menu.eesz.1M.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M64=1M (64K SPIFFS) +generic.menu.eesz.1M64.build.flash_size=1M +generic.menu.eesz.1M64.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +generic.menu.eesz.1M64.build.spiffs_pagesize=256 +generic.menu.eesz.1M64.upload.maximum_size=958448 +generic.menu.eesz.1M64.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M64.build.spiffs_start=0xEB000 +generic.menu.eesz.1M64.build.spiffs_end=0xFB000 +generic.menu.eesz.1M64.build.spiffs_blocksize=4096 +generic.menu.eesz.1M128=1M (128K SPIFFS) +generic.menu.eesz.1M128.build.flash_size=1M +generic.menu.eesz.1M128.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +generic.menu.eesz.1M128.build.spiffs_pagesize=256 +generic.menu.eesz.1M128.upload.maximum_size=892912 +generic.menu.eesz.1M128.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M128.build.spiffs_start=0xDB000 +generic.menu.eesz.1M128.build.spiffs_end=0xFB000 +generic.menu.eesz.1M128.build.spiffs_blocksize=4096 +generic.menu.eesz.1M144=1M (144K SPIFFS) +generic.menu.eesz.1M144.build.flash_size=1M +generic.menu.eesz.1M144.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +generic.menu.eesz.1M144.build.spiffs_pagesize=256 +generic.menu.eesz.1M144.upload.maximum_size=876528 +generic.menu.eesz.1M144.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M144.build.spiffs_start=0xD7000 +generic.menu.eesz.1M144.build.spiffs_end=0xFB000 +generic.menu.eesz.1M144.build.spiffs_blocksize=4096 +generic.menu.eesz.1M160=1M (160K SPIFFS) +generic.menu.eesz.1M160.build.flash_size=1M +generic.menu.eesz.1M160.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +generic.menu.eesz.1M160.build.spiffs_pagesize=256 +generic.menu.eesz.1M160.upload.maximum_size=860144 +generic.menu.eesz.1M160.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M160.build.spiffs_start=0xD3000 +generic.menu.eesz.1M160.build.spiffs_end=0xFB000 +generic.menu.eesz.1M160.build.spiffs_blocksize=4096 +generic.menu.eesz.1M192=1M (192K SPIFFS) +generic.menu.eesz.1M192.build.flash_size=1M +generic.menu.eesz.1M192.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +generic.menu.eesz.1M192.build.spiffs_pagesize=256 +generic.menu.eesz.1M192.upload.maximum_size=827376 +generic.menu.eesz.1M192.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M192.build.spiffs_start=0xCB000 +generic.menu.eesz.1M192.build.spiffs_end=0xFB000 +generic.menu.eesz.1M192.build.spiffs_blocksize=4096 +generic.menu.eesz.1M256=1M (256K SPIFFS) +generic.menu.eesz.1M256.build.flash_size=1M +generic.menu.eesz.1M256.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +generic.menu.eesz.1M256.build.spiffs_pagesize=256 +generic.menu.eesz.1M256.upload.maximum_size=761840 +generic.menu.eesz.1M256.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M256.build.spiffs_start=0xBB000 +generic.menu.eesz.1M256.build.spiffs_end=0xFB000 +generic.menu.eesz.1M256.build.spiffs_blocksize=4096 +generic.menu.eesz.1M512=1M (512K SPIFFS) +generic.menu.eesz.1M512.build.flash_size=1M +generic.menu.eesz.1M512.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +generic.menu.eesz.1M512.build.spiffs_pagesize=256 +generic.menu.eesz.1M512.upload.maximum_size=499696 +generic.menu.eesz.1M512.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M512.build.spiffs_start=0x7B000 +generic.menu.eesz.1M512.build.spiffs_end=0xFB000 +generic.menu.eesz.1M512.build.spiffs_blocksize=4096 +generic.menu.eesz.2M=2M (no SPIFFS) +generic.menu.eesz.2M.build.flash_size=2M +generic.menu.eesz.2M.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld +generic.menu.eesz.2M.build.spiffs_pagesize=256 +generic.menu.eesz.2M.upload.maximum_size=1044464 +generic.menu.eesz.2M.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M128=2M (128K SPIFFS) +generic.menu.eesz.2M128.build.flash_size=2M +generic.menu.eesz.2M128.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld +generic.menu.eesz.2M128.build.spiffs_pagesize=256 +generic.menu.eesz.2M128.upload.maximum_size=1044464 +generic.menu.eesz.2M128.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M128.build.spiffs_start=0x1E0000 +generic.menu.eesz.2M128.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M128.build.spiffs_blocksize=4096 +generic.menu.eesz.2M256=2M (256K SPIFFS) +generic.menu.eesz.2M256.build.flash_size=2M +generic.menu.eesz.2M256.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld +generic.menu.eesz.2M256.build.spiffs_pagesize=256 +generic.menu.eesz.2M256.upload.maximum_size=1044464 +generic.menu.eesz.2M256.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M256.build.spiffs_start=0x1C0000 +generic.menu.eesz.2M256.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M256.build.spiffs_blocksize=4096 +generic.menu.eesz.2M512=2M (512K SPIFFS) +generic.menu.eesz.2M512.build.flash_size=2M +generic.menu.eesz.2M512.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld +generic.menu.eesz.2M512.build.spiffs_pagesize=256 +generic.menu.eesz.2M512.upload.maximum_size=1044464 +generic.menu.eesz.2M512.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M512.build.spiffs_start=0x180000 +generic.menu.eesz.2M512.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M512.build.spiffs_blocksize=8192 +generic.menu.eesz.2M1M=2M (1M SPIFFS) +generic.menu.eesz.2M1M.build.flash_size=2M +generic.menu.eesz.2M1M.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld +generic.menu.eesz.2M1M.build.spiffs_pagesize=256 +generic.menu.eesz.2M1M.upload.maximum_size=1044464 +generic.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M1M.build.spiffs_start=0x100000 +generic.menu.eesz.2M1M.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M1M.build.spiffs_blocksize=8192 +generic.menu.eesz.4M=4M (no SPIFFS) +generic.menu.eesz.4M.build.flash_size=4M +generic.menu.eesz.4M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +generic.menu.eesz.4M.build.spiffs_pagesize=256 +generic.menu.eesz.4M.upload.maximum_size=1044464 +generic.menu.eesz.4M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M1M=4M (1M SPIFFS) +generic.menu.eesz.4M1M.build.flash_size=4M +generic.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +generic.menu.eesz.4M1M.build.spiffs_pagesize=256 +generic.menu.eesz.4M1M.upload.maximum_size=1044464 +generic.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M1M.build.spiffs_start=0x300000 +generic.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +generic.menu.eesz.4M1M.build.spiffs_blocksize=8192 +generic.menu.eesz.4M2M=4M (2M SPIFFS) +generic.menu.eesz.4M2M.build.flash_size=4M +generic.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +generic.menu.eesz.4M2M.build.spiffs_pagesize=256 +generic.menu.eesz.4M2M.upload.maximum_size=1044464 +generic.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M2M.build.spiffs_start=0x200000 +generic.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +generic.menu.eesz.4M2M.build.spiffs_blocksize=8192 +generic.menu.eesz.4M3M=4M (3M SPIFFS) +generic.menu.eesz.4M3M.build.flash_size=4M +generic.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +generic.menu.eesz.4M3M.build.spiffs_pagesize=256 +generic.menu.eesz.4M3M.upload.maximum_size=1044464 +generic.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M3M.build.spiffs_start=0x100000 +generic.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +generic.menu.eesz.4M3M.build.spiffs_blocksize=8192 +generic.menu.eesz.8M6M=8M (6M SPIFFS) +generic.menu.eesz.8M6M.build.flash_size=8M +generic.menu.eesz.8M6M.build.flash_size_bytes=0x800000 +generic.menu.eesz.8M6M.build.flash_ld=eagle.flash.8m6m.ld +generic.menu.eesz.8M6M.build.spiffs_pagesize=256 +generic.menu.eesz.8M6M.upload.maximum_size=1044464 +generic.menu.eesz.8M6M.build.rfcal_addr=0x7FC000 +generic.menu.eesz.8M6M.build.spiffs_start=0x200000 +generic.menu.eesz.8M6M.build.spiffs_end=0x7FB000 +generic.menu.eesz.8M6M.build.spiffs_blocksize=8192 +generic.menu.eesz.8M7M=8M (7M SPIFFS) +generic.menu.eesz.8M7M.build.flash_size=8M +generic.menu.eesz.8M7M.build.flash_size_bytes=0x800000 +generic.menu.eesz.8M7M.build.flash_ld=eagle.flash.8m7m.ld +generic.menu.eesz.8M7M.build.spiffs_pagesize=256 +generic.menu.eesz.8M7M.upload.maximum_size=1044464 +generic.menu.eesz.8M7M.build.rfcal_addr=0x7FC000 +generic.menu.eesz.8M7M.build.spiffs_start=0x100000 +generic.menu.eesz.8M7M.build.spiffs_end=0x7FB000 +generic.menu.eesz.8M7M.build.spiffs_blocksize=8192 +generic.menu.eesz.16M14M=16M (14M SPIFFS) +generic.menu.eesz.16M14M.build.flash_size=16M +generic.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 +generic.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld +generic.menu.eesz.16M14M.build.spiffs_pagesize=256 +generic.menu.eesz.16M14M.upload.maximum_size=1044464 +generic.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 +generic.menu.eesz.16M14M.build.spiffs_start=0x200000 +generic.menu.eesz.16M14M.build.spiffs_end=0xFFB000 +generic.menu.eesz.16M14M.build.spiffs_blocksize=8192 +generic.menu.eesz.16M15M=16M (15M SPIFFS) +generic.menu.eesz.16M15M.build.flash_size=16M +generic.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 +generic.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld +generic.menu.eesz.16M15M.build.spiffs_pagesize=256 +generic.menu.eesz.16M15M.upload.maximum_size=1044464 +generic.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 +generic.menu.eesz.16M15M.build.spiffs_start=0x100000 +generic.menu.eesz.16M15M.build.spiffs_end=0xFFB000 +generic.menu.eesz.16M15M.build.spiffs_blocksize=8192 +generic.menu.led.2=2 +generic.menu.led.2.build.led=-DLED_BUILTIN=2 +generic.menu.led.0=0 +generic.menu.led.0.build.led=-DLED_BUILTIN=0 +generic.menu.led.1=1 +generic.menu.led.1.build.led=-DLED_BUILTIN=1 +generic.menu.led.3=3 +generic.menu.led.3.build.led=-DLED_BUILTIN=3 +generic.menu.led.4=4 +generic.menu.led.4.build.led=-DLED_BUILTIN=4 +generic.menu.led.5=5 +generic.menu.led.5.build.led=-DLED_BUILTIN=5 +generic.menu.led.6=6 +generic.menu.led.6.build.led=-DLED_BUILTIN=6 +generic.menu.led.7=7 +generic.menu.led.7.build.led=-DLED_BUILTIN=7 +generic.menu.led.8=8 +generic.menu.led.8.build.led=-DLED_BUILTIN=8 +generic.menu.led.9=9 +generic.menu.led.9.build.led=-DLED_BUILTIN=9 +generic.menu.led.10=10 +generic.menu.led.10.build.led=-DLED_BUILTIN=10 +generic.menu.led.11=11 +generic.menu.led.11.build.led=-DLED_BUILTIN=11 +generic.menu.led.12=12 +generic.menu.led.12.build.led=-DLED_BUILTIN=12 +generic.menu.led.13=13 +generic.menu.led.13.build.led=-DLED_BUILTIN=13 +generic.menu.led.14=14 +generic.menu.led.14.build.led=-DLED_BUILTIN=14 +generic.menu.led.15=15 +generic.menu.led.15.build.led=-DLED_BUILTIN=15 +generic.menu.ip.lm2f=v2 Lower Memory +generic.menu.ip.lm2f.build.lwip_include=lwip2/include +generic.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +generic.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +generic.menu.ip.hb2f=v2 Higher Bandwidth +generic.menu.ip.hb2f.build.lwip_include=lwip2/include +generic.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +generic.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +generic.menu.ip.lm2n=v2 Lower Memory (no features) +generic.menu.ip.lm2n.build.lwip_include=lwip2/include +generic.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +generic.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +generic.menu.ip.hb2n=v2 Higher Bandwidth (no features) +generic.menu.ip.hb2n.build.lwip_include=lwip2/include +generic.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +generic.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +generic.menu.ip.lm6f=v2 IPv6 Lower Memory +generic.menu.ip.lm6f.build.lwip_include=lwip2/include +generic.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +generic.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +generic.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +generic.menu.ip.hb6f.build.lwip_include=lwip2/include +generic.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +generic.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +generic.menu.ip.hb1=v1.4 Higher Bandwidth +generic.menu.ip.hb1.build.lwip_lib=-llwip_gcc +generic.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +generic.menu.ip.src=v1.4 Compile from source +generic.menu.ip.src.build.lwip_lib=-llwip_src +generic.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +generic.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +generic.menu.dbg.Disabled=Disabled +generic.menu.dbg.Disabled.build.debug_port= +generic.menu.dbg.Serial=Serial +generic.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +generic.menu.dbg.Serial1=Serial1 +generic.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +generic.menu.lvl.None____=None +generic.menu.lvl.None____.build.debug_level= +generic.menu.lvl.SSL=SSL +generic.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +generic.menu.lvl.TLS_MEM=TLS_MEM +generic.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +generic.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +generic.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.HTTP_SERVER=HTTP_SERVER +generic.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +generic.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +generic.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +generic.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +generic.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +generic.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.CORE=CORE +generic.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +generic.menu.lvl.WIFI=WIFI +generic.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +generic.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +generic.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +generic.menu.lvl.UPDATER=UPDATER +generic.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +generic.menu.lvl.OTA=OTA +generic.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +generic.menu.lvl.OOM=OOM +generic.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +generic.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +generic.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +generic.menu.wipe.none=Only Sketch +generic.menu.wipe.none.upload.erase_cmd= +generic.menu.wipe.sdk=Sketch + WiFi Settings +generic.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +generic.menu.wipe.all=All Flash Contents +generic.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +generic.menu.baud.115200=115200 +generic.menu.baud.115200.upload.speed=115200 +generic.menu.baud.9600=9600 +generic.menu.baud.9600.upload.speed=9600 +generic.menu.baud.57600=57600 +generic.menu.baud.57600.upload.speed=57600 +generic.menu.baud.230400.linux=230400 +generic.menu.baud.230400.macosx=230400 +generic.menu.baud.230400.upload.speed=230400 +generic.menu.baud.256000.windows=256000 +generic.menu.baud.256000.upload.speed=256000 +generic.menu.baud.460800.linux=460800 +generic.menu.baud.460800.macosx=460800 +generic.menu.baud.460800.upload.speed=460800 +generic.menu.baud.512000.windows=512000 +generic.menu.baud.512000.upload.speed=512000 +generic.menu.baud.921600=921600 +generic.menu.baud.921600.upload.speed=921600 + +############################################################## +esp8285.name=Generic ESP8285 Module +esp8285.build.board=ESP8266_ESP01 +esp8285.build.variant=esp8285 +esp8285.upload.tool=esptool +esp8285.upload.maximum_data_size=81920 +esp8285.upload.wait_for_upload_port=true +esp8285.upload.erase_cmd= +esp8285.serial.disableDTR=true +esp8285.serial.disableRTS=true +esp8285.build.mcu=esp8266 +esp8285.build.core=esp8266 +esp8285.build.spiffs_pagesize=256 +esp8285.build.debug_port= +esp8285.build.debug_level= +esp8285.menu.xtal.80=80 MHz +esp8285.menu.xtal.80.build.f_cpu=80000000L +esp8285.menu.xtal.160=160 MHz +esp8285.menu.xtal.160.build.f_cpu=160000000L +esp8285.menu.vt.flash=Flash +esp8285.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +esp8285.menu.vt.heap=Heap +esp8285.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +esp8285.menu.vt.iram=IRAM +esp8285.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +esp8285.menu.exception.disabled=Disabled +esp8285.menu.exception.disabled.build.exception_flags=-fno-exceptions +esp8285.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +esp8285.menu.exception.enabled=Enabled +esp8285.menu.exception.enabled.build.exception_flags=-fexceptions +esp8285.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +esp8285.menu.ResetMethod.ck=ck +esp8285.menu.ResetMethod.ck.upload.resetmethod=ck +esp8285.menu.ResetMethod.nodemcu=nodemcu +esp8285.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +esp8285.menu.ResetMethod.none=none +esp8285.menu.ResetMethod.none.upload.resetmethod=none +esp8285.menu.ResetMethod.dtrset=dtrset +esp8285.menu.ResetMethod.dtrset.upload.resetmethod=dtrset +esp8285.menu.CrystalFreq.26=26 MHz +esp8285.menu.CrystalFreq.40=40 MHz +esp8285.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +esp8285.build.flash_mode=dout +esp8285.build.flash_flags=-DFLASHMODE_DOUT +esp8285.build.flash_freq=40 +esp8285.menu.eesz.1M=1M (no SPIFFS) +esp8285.menu.eesz.1M.build.flash_size=1M +esp8285.menu.eesz.1M.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +esp8285.menu.eesz.1M.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M.upload.maximum_size=1023984 +esp8285.menu.eesz.1M.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M64=1M (64K SPIFFS) +esp8285.menu.eesz.1M64.build.flash_size=1M +esp8285.menu.eesz.1M64.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +esp8285.menu.eesz.1M64.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M64.upload.maximum_size=958448 +esp8285.menu.eesz.1M64.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M64.build.spiffs_start=0xEB000 +esp8285.menu.eesz.1M64.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M64.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M128=1M (128K SPIFFS) +esp8285.menu.eesz.1M128.build.flash_size=1M +esp8285.menu.eesz.1M128.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +esp8285.menu.eesz.1M128.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M128.upload.maximum_size=892912 +esp8285.menu.eesz.1M128.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M128.build.spiffs_start=0xDB000 +esp8285.menu.eesz.1M128.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M128.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M144=1M (144K SPIFFS) +esp8285.menu.eesz.1M144.build.flash_size=1M +esp8285.menu.eesz.1M144.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +esp8285.menu.eesz.1M144.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M144.upload.maximum_size=876528 +esp8285.menu.eesz.1M144.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M144.build.spiffs_start=0xD7000 +esp8285.menu.eesz.1M144.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M144.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M160=1M (160K SPIFFS) +esp8285.menu.eesz.1M160.build.flash_size=1M +esp8285.menu.eesz.1M160.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +esp8285.menu.eesz.1M160.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M160.upload.maximum_size=860144 +esp8285.menu.eesz.1M160.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M160.build.spiffs_start=0xD3000 +esp8285.menu.eesz.1M160.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M160.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M192=1M (192K SPIFFS) +esp8285.menu.eesz.1M192.build.flash_size=1M +esp8285.menu.eesz.1M192.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +esp8285.menu.eesz.1M192.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M192.upload.maximum_size=827376 +esp8285.menu.eesz.1M192.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M192.build.spiffs_start=0xCB000 +esp8285.menu.eesz.1M192.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M192.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M256=1M (256K SPIFFS) +esp8285.menu.eesz.1M256.build.flash_size=1M +esp8285.menu.eesz.1M256.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +esp8285.menu.eesz.1M256.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M256.upload.maximum_size=761840 +esp8285.menu.eesz.1M256.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M256.build.spiffs_start=0xBB000 +esp8285.menu.eesz.1M256.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M256.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M512=1M (512K SPIFFS) +esp8285.menu.eesz.1M512.build.flash_size=1M +esp8285.menu.eesz.1M512.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +esp8285.menu.eesz.1M512.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M512.upload.maximum_size=499696 +esp8285.menu.eesz.1M512.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M512.build.spiffs_start=0x7B000 +esp8285.menu.eesz.1M512.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M512.build.spiffs_blocksize=4096 +esp8285.menu.led.2=2 +esp8285.menu.led.2.build.led=-DLED_BUILTIN=2 +esp8285.menu.led.0=0 +esp8285.menu.led.0.build.led=-DLED_BUILTIN=0 +esp8285.menu.led.1=1 +esp8285.menu.led.1.build.led=-DLED_BUILTIN=1 +esp8285.menu.led.3=3 +esp8285.menu.led.3.build.led=-DLED_BUILTIN=3 +esp8285.menu.led.4=4 +esp8285.menu.led.4.build.led=-DLED_BUILTIN=4 +esp8285.menu.led.5=5 +esp8285.menu.led.5.build.led=-DLED_BUILTIN=5 +esp8285.menu.led.6=6 +esp8285.menu.led.6.build.led=-DLED_BUILTIN=6 +esp8285.menu.led.7=7 +esp8285.menu.led.7.build.led=-DLED_BUILTIN=7 +esp8285.menu.led.8=8 +esp8285.menu.led.8.build.led=-DLED_BUILTIN=8 +esp8285.menu.led.9=9 +esp8285.menu.led.9.build.led=-DLED_BUILTIN=9 +esp8285.menu.led.10=10 +esp8285.menu.led.10.build.led=-DLED_BUILTIN=10 +esp8285.menu.led.11=11 +esp8285.menu.led.11.build.led=-DLED_BUILTIN=11 +esp8285.menu.led.12=12 +esp8285.menu.led.12.build.led=-DLED_BUILTIN=12 +esp8285.menu.led.13=13 +esp8285.menu.led.13.build.led=-DLED_BUILTIN=13 +esp8285.menu.led.14=14 +esp8285.menu.led.14.build.led=-DLED_BUILTIN=14 +esp8285.menu.led.15=15 +esp8285.menu.led.15.build.led=-DLED_BUILTIN=15 +esp8285.menu.ip.lm2f=v2 Lower Memory +esp8285.menu.ip.lm2f.build.lwip_include=lwip2/include +esp8285.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +esp8285.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp8285.menu.ip.hb2f=v2 Higher Bandwidth +esp8285.menu.ip.hb2f.build.lwip_include=lwip2/include +esp8285.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +esp8285.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp8285.menu.ip.lm2n=v2 Lower Memory (no features) +esp8285.menu.ip.lm2n.build.lwip_include=lwip2/include +esp8285.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +esp8285.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp8285.menu.ip.hb2n=v2 Higher Bandwidth (no features) +esp8285.menu.ip.hb2n.build.lwip_include=lwip2/include +esp8285.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +esp8285.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp8285.menu.ip.lm6f=v2 IPv6 Lower Memory +esp8285.menu.ip.lm6f.build.lwip_include=lwip2/include +esp8285.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +esp8285.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp8285.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +esp8285.menu.ip.hb6f.build.lwip_include=lwip2/include +esp8285.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +esp8285.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp8285.menu.ip.hb1=v1.4 Higher Bandwidth +esp8285.menu.ip.hb1.build.lwip_lib=-llwip_gcc +esp8285.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +esp8285.menu.ip.src=v1.4 Compile from source +esp8285.menu.ip.src.build.lwip_lib=-llwip_src +esp8285.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +esp8285.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +esp8285.menu.dbg.Disabled=Disabled +esp8285.menu.dbg.Disabled.build.debug_port= +esp8285.menu.dbg.Serial=Serial +esp8285.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +esp8285.menu.dbg.Serial1=Serial1 +esp8285.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +esp8285.menu.lvl.None____=None +esp8285.menu.lvl.None____.build.debug_level= +esp8285.menu.lvl.SSL=SSL +esp8285.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +esp8285.menu.lvl.TLS_MEM=TLS_MEM +esp8285.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +esp8285.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +esp8285.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.HTTP_SERVER=HTTP_SERVER +esp8285.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +esp8285.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +esp8285.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +esp8285.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +esp8285.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +esp8285.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.CORE=CORE +esp8285.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +esp8285.menu.lvl.WIFI=WIFI +esp8285.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +esp8285.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +esp8285.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +esp8285.menu.lvl.UPDATER=UPDATER +esp8285.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +esp8285.menu.lvl.OTA=OTA +esp8285.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +esp8285.menu.lvl.OOM=OOM +esp8285.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +esp8285.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +esp8285.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +esp8285.menu.wipe.none=Only Sketch +esp8285.menu.wipe.none.upload.erase_cmd= +esp8285.menu.wipe.sdk=Sketch + WiFi Settings +esp8285.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +esp8285.menu.wipe.all=All Flash Contents +esp8285.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +esp8285.menu.baud.115200=115200 +esp8285.menu.baud.115200.upload.speed=115200 +esp8285.menu.baud.9600=9600 +esp8285.menu.baud.9600.upload.speed=9600 +esp8285.menu.baud.57600=57600 +esp8285.menu.baud.57600.upload.speed=57600 +esp8285.menu.baud.230400.linux=230400 +esp8285.menu.baud.230400.macosx=230400 +esp8285.menu.baud.230400.upload.speed=230400 +esp8285.menu.baud.256000.windows=256000 +esp8285.menu.baud.256000.upload.speed=256000 +esp8285.menu.baud.460800.linux=460800 +esp8285.menu.baud.460800.macosx=460800 +esp8285.menu.baud.460800.upload.speed=460800 +esp8285.menu.baud.512000.windows=512000 +esp8285.menu.baud.512000.upload.speed=512000 +esp8285.menu.baud.921600=921600 +esp8285.menu.baud.921600.upload.speed=921600 + +############################################################## +espduino.name=ESPDuino (ESP-13 Module) +espduino.build.board=ESP8266_ESP13 +espduino.build.variant=ESPDuino +espduino.menu.ResetMethod.v2=ESPduino-V2 +espduino.menu.ResetMethod.v2.upload.resetmethod=nodemcu +espduino.menu.ResetMethod.v1=ESPduino-V1 +espduino.menu.ResetMethod.v1.upload.resetmethod=ck +espduino.menu.UploadTool.esptool=Serial +espduino.menu.UploadTool.esptool.upload.tool=esptool +espduino.menu.UploadTool.esptool.upload.verbose=-vv +espduino.menu.UploadTool.espota=OTA +espduino.menu.UploadTool.espota.upload.tool=espota +espduino.upload.tool=esptool +espduino.upload.maximum_data_size=81920 +espduino.upload.wait_for_upload_port=true +espduino.upload.erase_cmd= +espduino.serial.disableDTR=true +espduino.serial.disableRTS=true +espduino.build.mcu=esp8266 +espduino.build.core=esp8266 +espduino.build.spiffs_pagesize=256 +espduino.build.debug_port= +espduino.build.debug_level= +espduino.menu.xtal.80=80 MHz +espduino.menu.xtal.80.build.f_cpu=80000000L +espduino.menu.xtal.160=160 MHz +espduino.menu.xtal.160.build.f_cpu=160000000L +espduino.menu.vt.flash=Flash +espduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espduino.menu.vt.heap=Heap +espduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espduino.menu.vt.iram=IRAM +espduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espduino.menu.exception.disabled=Disabled +espduino.menu.exception.disabled.build.exception_flags=-fno-exceptions +espduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espduino.menu.exception.enabled=Enabled +espduino.menu.exception.enabled.build.exception_flags=-fexceptions +espduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espduino.build.flash_mode=dio +espduino.build.flash_flags=-DFLASHMODE_DIO +espduino.build.flash_freq=40 +espduino.menu.eesz.4M=4M (no SPIFFS) +espduino.menu.eesz.4M.build.flash_size=4M +espduino.menu.eesz.4M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espduino.menu.eesz.4M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M.upload.maximum_size=1044464 +espduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M1M=4M (1M SPIFFS) +espduino.menu.eesz.4M1M.build.flash_size=4M +espduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espduino.menu.eesz.4M1M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M1M.upload.maximum_size=1044464 +espduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M1M.build.spiffs_start=0x300000 +espduino.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +espduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espduino.menu.eesz.4M2M=4M (2M SPIFFS) +espduino.menu.eesz.4M2M.build.flash_size=4M +espduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espduino.menu.eesz.4M2M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M2M.upload.maximum_size=1044464 +espduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M2M.build.spiffs_start=0x200000 +espduino.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +espduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espduino.menu.eesz.4M3M=4M (3M SPIFFS) +espduino.menu.eesz.4M3M.build.flash_size=4M +espduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espduino.menu.eesz.4M3M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M3M.upload.maximum_size=1044464 +espduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M3M.build.spiffs_start=0x100000 +espduino.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +espduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espduino.menu.ip.lm2f=v2 Lower Memory +espduino.menu.ip.lm2f.build.lwip_include=lwip2/include +espduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espduino.menu.ip.hb2f=v2 Higher Bandwidth +espduino.menu.ip.hb2f.build.lwip_include=lwip2/include +espduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espduino.menu.ip.lm2n=v2 Lower Memory (no features) +espduino.menu.ip.lm2n.build.lwip_include=lwip2/include +espduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espduino.menu.ip.hb2n.build.lwip_include=lwip2/include +espduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espduino.menu.ip.lm6f=v2 IPv6 Lower Memory +espduino.menu.ip.lm6f.build.lwip_include=lwip2/include +espduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espduino.menu.ip.hb6f.build.lwip_include=lwip2/include +espduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espduino.menu.ip.hb1=v1.4 Higher Bandwidth +espduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espduino.menu.ip.src=v1.4 Compile from source +espduino.menu.ip.src.build.lwip_lib=-llwip_src +espduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espduino.menu.dbg.Disabled=Disabled +espduino.menu.dbg.Disabled.build.debug_port= +espduino.menu.dbg.Serial=Serial +espduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espduino.menu.dbg.Serial1=Serial1 +espduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espduino.menu.lvl.None____=None +espduino.menu.lvl.None____.build.debug_level= +espduino.menu.lvl.SSL=SSL +espduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espduino.menu.lvl.TLS_MEM=TLS_MEM +espduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.HTTP_SERVER=HTTP_SERVER +espduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.CORE=CORE +espduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espduino.menu.lvl.WIFI=WIFI +espduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espduino.menu.lvl.UPDATER=UPDATER +espduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espduino.menu.lvl.OTA=OTA +espduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espduino.menu.lvl.OOM=OOM +espduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espduino.menu.wipe.none=Only Sketch +espduino.menu.wipe.none.upload.erase_cmd= +espduino.menu.wipe.sdk=Sketch + WiFi Settings +espduino.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +espduino.menu.wipe.all=All Flash Contents +espduino.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +espduino.menu.baud.115200=115200 +espduino.menu.baud.115200.upload.speed=115200 +espduino.menu.baud.9600=9600 +espduino.menu.baud.9600.upload.speed=9600 +espduino.menu.baud.57600=57600 +espduino.menu.baud.57600.upload.speed=57600 +espduino.menu.baud.230400.linux=230400 +espduino.menu.baud.230400.macosx=230400 +espduino.menu.baud.230400.upload.speed=230400 +espduino.menu.baud.256000.windows=256000 +espduino.menu.baud.256000.upload.speed=256000 +espduino.menu.baud.460800.linux=460800 +espduino.menu.baud.460800.macosx=460800 +espduino.menu.baud.460800.upload.speed=460800 +espduino.menu.baud.512000.windows=512000 +espduino.menu.baud.512000.upload.speed=512000 +espduino.menu.baud.921600=921600 +espduino.menu.baud.921600.upload.speed=921600 + +############################################################## +huzzah.name=Adafruit Feather HUZZAH ESP8266 +huzzah.build.board=ESP8266_ESP12 +huzzah.build.variant=adafruit +huzzah.upload.tool=esptool +huzzah.upload.maximum_data_size=81920 +huzzah.upload.wait_for_upload_port=true +huzzah.upload.erase_cmd= +huzzah.serial.disableDTR=true +huzzah.serial.disableRTS=true +huzzah.build.mcu=esp8266 +huzzah.build.core=esp8266 +huzzah.build.spiffs_pagesize=256 +huzzah.build.debug_port= +huzzah.build.debug_level= +huzzah.menu.xtal.80=80 MHz +huzzah.menu.xtal.80.build.f_cpu=80000000L +huzzah.menu.xtal.160=160 MHz +huzzah.menu.xtal.160.build.f_cpu=160000000L +huzzah.menu.vt.flash=Flash +huzzah.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +huzzah.menu.vt.heap=Heap +huzzah.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +huzzah.menu.vt.iram=IRAM +huzzah.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +huzzah.menu.exception.disabled=Disabled +huzzah.menu.exception.disabled.build.exception_flags=-fno-exceptions +huzzah.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +huzzah.menu.exception.enabled=Enabled +huzzah.menu.exception.enabled.build.exception_flags=-fexceptions +huzzah.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +huzzah.upload.resetmethod=nodemcu +huzzah.build.flash_mode=qio +huzzah.build.flash_flags=-DFLASHMODE_QIO +huzzah.build.flash_freq=40 +huzzah.menu.eesz.4M=4M (no SPIFFS) +huzzah.menu.eesz.4M.build.flash_size=4M +huzzah.menu.eesz.4M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +huzzah.menu.eesz.4M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M1M=4M (1M SPIFFS) +huzzah.menu.eesz.4M1M.build.flash_size=4M +huzzah.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +huzzah.menu.eesz.4M1M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M1M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M1M.build.spiffs_start=0x300000 +huzzah.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +huzzah.menu.eesz.4M1M.build.spiffs_blocksize=8192 +huzzah.menu.eesz.4M2M=4M (2M SPIFFS) +huzzah.menu.eesz.4M2M.build.flash_size=4M +huzzah.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +huzzah.menu.eesz.4M2M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M2M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M2M.build.spiffs_start=0x200000 +huzzah.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +huzzah.menu.eesz.4M2M.build.spiffs_blocksize=8192 +huzzah.menu.eesz.4M3M=4M (3M SPIFFS) +huzzah.menu.eesz.4M3M.build.flash_size=4M +huzzah.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +huzzah.menu.eesz.4M3M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M3M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M3M.build.spiffs_start=0x100000 +huzzah.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +huzzah.menu.eesz.4M3M.build.spiffs_blocksize=8192 +huzzah.menu.ip.lm2f=v2 Lower Memory +huzzah.menu.ip.lm2f.build.lwip_include=lwip2/include +huzzah.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +huzzah.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +huzzah.menu.ip.hb2f=v2 Higher Bandwidth +huzzah.menu.ip.hb2f.build.lwip_include=lwip2/include +huzzah.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +huzzah.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +huzzah.menu.ip.lm2n=v2 Lower Memory (no features) +huzzah.menu.ip.lm2n.build.lwip_include=lwip2/include +huzzah.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +huzzah.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +huzzah.menu.ip.hb2n=v2 Higher Bandwidth (no features) +huzzah.menu.ip.hb2n.build.lwip_include=lwip2/include +huzzah.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +huzzah.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +huzzah.menu.ip.lm6f=v2 IPv6 Lower Memory +huzzah.menu.ip.lm6f.build.lwip_include=lwip2/include +huzzah.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +huzzah.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +huzzah.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +huzzah.menu.ip.hb6f.build.lwip_include=lwip2/include +huzzah.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +huzzah.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +huzzah.menu.ip.hb1=v1.4 Higher Bandwidth +huzzah.menu.ip.hb1.build.lwip_lib=-llwip_gcc +huzzah.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +huzzah.menu.ip.src=v1.4 Compile from source +huzzah.menu.ip.src.build.lwip_lib=-llwip_src +huzzah.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +huzzah.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +huzzah.menu.dbg.Disabled=Disabled +huzzah.menu.dbg.Disabled.build.debug_port= +huzzah.menu.dbg.Serial=Serial +huzzah.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +huzzah.menu.dbg.Serial1=Serial1 +huzzah.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +huzzah.menu.lvl.None____=None +huzzah.menu.lvl.None____.build.debug_level= +huzzah.menu.lvl.SSL=SSL +huzzah.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +huzzah.menu.lvl.TLS_MEM=TLS_MEM +huzzah.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +huzzah.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +huzzah.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.HTTP_SERVER=HTTP_SERVER +huzzah.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +huzzah.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +huzzah.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +huzzah.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +huzzah.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +huzzah.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.CORE=CORE +huzzah.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +huzzah.menu.lvl.WIFI=WIFI +huzzah.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +huzzah.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +huzzah.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +huzzah.menu.lvl.UPDATER=UPDATER +huzzah.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +huzzah.menu.lvl.OTA=OTA +huzzah.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +huzzah.menu.lvl.OOM=OOM +huzzah.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +huzzah.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +huzzah.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +huzzah.menu.wipe.none=Only Sketch +huzzah.menu.wipe.none.upload.erase_cmd= +huzzah.menu.wipe.sdk=Sketch + WiFi Settings +huzzah.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +huzzah.menu.wipe.all=All Flash Contents +huzzah.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +huzzah.menu.baud.115200=115200 +huzzah.menu.baud.115200.upload.speed=115200 +huzzah.menu.baud.9600=9600 +huzzah.menu.baud.9600.upload.speed=9600 +huzzah.menu.baud.57600=57600 +huzzah.menu.baud.57600.upload.speed=57600 +huzzah.menu.baud.230400.linux=230400 +huzzah.menu.baud.230400.macosx=230400 +huzzah.menu.baud.230400.upload.speed=230400 +huzzah.menu.baud.256000.windows=256000 +huzzah.menu.baud.256000.upload.speed=256000 +huzzah.menu.baud.460800.linux=460800 +huzzah.menu.baud.460800.macosx=460800 +huzzah.menu.baud.460800.upload.speed=460800 +huzzah.menu.baud.512000.windows=512000 +huzzah.menu.baud.512000.upload.speed=512000 +huzzah.menu.baud.921600=921600 +huzzah.menu.baud.921600.upload.speed=921600 + +############################################################## +inventone.name=Invent One +inventone.build.board=ESP8266_GENERIC +inventone.build.variant=inventone +inventone.upload.tool=esptool +inventone.upload.maximum_data_size=81920 +inventone.upload.wait_for_upload_port=true +inventone.upload.erase_cmd= +inventone.serial.disableDTR=true +inventone.serial.disableRTS=true +inventone.build.mcu=esp8266 +inventone.build.core=esp8266 +inventone.build.spiffs_pagesize=256 +inventone.build.debug_port= +inventone.build.debug_level= +inventone.menu.xtal.80=80 MHz +inventone.menu.xtal.80.build.f_cpu=80000000L +inventone.menu.xtal.160=160 MHz +inventone.menu.xtal.160.build.f_cpu=160000000L +inventone.menu.vt.flash=Flash +inventone.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +inventone.menu.vt.heap=Heap +inventone.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +inventone.menu.vt.iram=IRAM +inventone.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +inventone.menu.exception.disabled=Disabled +inventone.menu.exception.disabled.build.exception_flags=-fno-exceptions +inventone.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +inventone.menu.exception.enabled=Enabled +inventone.menu.exception.enabled.build.exception_flags=-fexceptions +inventone.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +inventone.upload.resetmethod=nodemcu +inventone.build.flash_mode=dio +inventone.build.flash_flags=-DFLASHMODE_DIO +inventone.build.flash_freq=40 +inventone.menu.eesz.4M=4M (no SPIFFS) +inventone.menu.eesz.4M.build.flash_size=4M +inventone.menu.eesz.4M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +inventone.menu.eesz.4M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M.upload.maximum_size=1044464 +inventone.menu.eesz.4M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M1M=4M (1M SPIFFS) +inventone.menu.eesz.4M1M.build.flash_size=4M +inventone.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +inventone.menu.eesz.4M1M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M1M.upload.maximum_size=1044464 +inventone.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M1M.build.spiffs_start=0x300000 +inventone.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +inventone.menu.eesz.4M1M.build.spiffs_blocksize=8192 +inventone.menu.eesz.4M2M=4M (2M SPIFFS) +inventone.menu.eesz.4M2M.build.flash_size=4M +inventone.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +inventone.menu.eesz.4M2M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M2M.upload.maximum_size=1044464 +inventone.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M2M.build.spiffs_start=0x200000 +inventone.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +inventone.menu.eesz.4M2M.build.spiffs_blocksize=8192 +inventone.menu.eesz.4M3M=4M (3M SPIFFS) +inventone.menu.eesz.4M3M.build.flash_size=4M +inventone.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +inventone.menu.eesz.4M3M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M3M.upload.maximum_size=1044464 +inventone.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M3M.build.spiffs_start=0x100000 +inventone.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +inventone.menu.eesz.4M3M.build.spiffs_blocksize=8192 +inventone.menu.ip.lm2f=v2 Lower Memory +inventone.menu.ip.lm2f.build.lwip_include=lwip2/include +inventone.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +inventone.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +inventone.menu.ip.hb2f=v2 Higher Bandwidth +inventone.menu.ip.hb2f.build.lwip_include=lwip2/include +inventone.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +inventone.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +inventone.menu.ip.lm2n=v2 Lower Memory (no features) +inventone.menu.ip.lm2n.build.lwip_include=lwip2/include +inventone.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +inventone.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +inventone.menu.ip.hb2n=v2 Higher Bandwidth (no features) +inventone.menu.ip.hb2n.build.lwip_include=lwip2/include +inventone.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +inventone.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +inventone.menu.ip.lm6f=v2 IPv6 Lower Memory +inventone.menu.ip.lm6f.build.lwip_include=lwip2/include +inventone.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +inventone.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +inventone.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +inventone.menu.ip.hb6f.build.lwip_include=lwip2/include +inventone.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +inventone.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +inventone.menu.ip.hb1=v1.4 Higher Bandwidth +inventone.menu.ip.hb1.build.lwip_lib=-llwip_gcc +inventone.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +inventone.menu.ip.src=v1.4 Compile from source +inventone.menu.ip.src.build.lwip_lib=-llwip_src +inventone.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +inventone.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +inventone.menu.dbg.Disabled=Disabled +inventone.menu.dbg.Disabled.build.debug_port= +inventone.menu.dbg.Serial=Serial +inventone.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +inventone.menu.dbg.Serial1=Serial1 +inventone.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +inventone.menu.lvl.None____=None +inventone.menu.lvl.None____.build.debug_level= +inventone.menu.lvl.SSL=SSL +inventone.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +inventone.menu.lvl.TLS_MEM=TLS_MEM +inventone.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +inventone.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +inventone.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.HTTP_SERVER=HTTP_SERVER +inventone.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +inventone.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +inventone.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +inventone.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +inventone.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +inventone.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.CORE=CORE +inventone.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +inventone.menu.lvl.WIFI=WIFI +inventone.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +inventone.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +inventone.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +inventone.menu.lvl.UPDATER=UPDATER +inventone.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +inventone.menu.lvl.OTA=OTA +inventone.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +inventone.menu.lvl.OOM=OOM +inventone.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +inventone.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +inventone.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +inventone.menu.wipe.none=Only Sketch +inventone.menu.wipe.none.upload.erase_cmd= +inventone.menu.wipe.sdk=Sketch + WiFi Settings +inventone.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +inventone.menu.wipe.all=All Flash Contents +inventone.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +inventone.menu.baud.115200=115200 +inventone.menu.baud.115200.upload.speed=115200 +inventone.menu.baud.9600=9600 +inventone.menu.baud.9600.upload.speed=9600 +inventone.menu.baud.57600=57600 +inventone.menu.baud.57600.upload.speed=57600 +inventone.menu.baud.230400.linux=230400 +inventone.menu.baud.230400.macosx=230400 +inventone.menu.baud.230400.upload.speed=230400 +inventone.menu.baud.256000.windows=256000 +inventone.menu.baud.256000.upload.speed=256000 +inventone.menu.baud.460800.linux=460800 +inventone.menu.baud.460800.macosx=460800 +inventone.menu.baud.460800.upload.speed=460800 +inventone.menu.baud.512000.windows=512000 +inventone.menu.baud.512000.upload.speed=512000 +inventone.menu.baud.921600=921600 +inventone.menu.baud.921600.upload.speed=921600 + +############################################################## +cw01.name=XinaBox CW01 +cw01.build.board=ESP8266_GENERIC +cw01.build.variant=xinabox +cw01.upload.tool=esptool +cw01.upload.maximum_data_size=81920 +cw01.upload.wait_for_upload_port=true +cw01.upload.erase_cmd= +cw01.serial.disableDTR=true +cw01.serial.disableRTS=true +cw01.build.mcu=esp8266 +cw01.build.core=esp8266 +cw01.build.spiffs_pagesize=256 +cw01.build.debug_port= +cw01.build.debug_level= +cw01.menu.xtal.80=80 MHz +cw01.menu.xtal.80.build.f_cpu=80000000L +cw01.menu.xtal.160=160 MHz +cw01.menu.xtal.160.build.f_cpu=160000000L +cw01.menu.vt.flash=Flash +cw01.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +cw01.menu.vt.heap=Heap +cw01.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +cw01.menu.vt.iram=IRAM +cw01.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +cw01.menu.exception.disabled=Disabled +cw01.menu.exception.disabled.build.exception_flags=-fno-exceptions +cw01.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +cw01.menu.exception.enabled=Enabled +cw01.menu.exception.enabled.build.exception_flags=-fexceptions +cw01.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +cw01.upload.resetmethod=nodemcu +cw01.menu.CrystalFreq.26=26 MHz +cw01.menu.CrystalFreq.40=40 MHz +cw01.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +cw01.build.flash_mode=qio +cw01.build.flash_flags=-DFLASHMODE_QIO +cw01.build.flash_freq=40 +cw01.menu.eesz.4M=4M (no SPIFFS) +cw01.menu.eesz.4M.build.flash_size=4M +cw01.menu.eesz.4M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +cw01.menu.eesz.4M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M.upload.maximum_size=1044464 +cw01.menu.eesz.4M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M1M=4M (1M SPIFFS) +cw01.menu.eesz.4M1M.build.flash_size=4M +cw01.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +cw01.menu.eesz.4M1M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M1M.upload.maximum_size=1044464 +cw01.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M1M.build.spiffs_start=0x300000 +cw01.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +cw01.menu.eesz.4M1M.build.spiffs_blocksize=8192 +cw01.menu.eesz.4M2M=4M (2M SPIFFS) +cw01.menu.eesz.4M2M.build.flash_size=4M +cw01.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +cw01.menu.eesz.4M2M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M2M.upload.maximum_size=1044464 +cw01.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M2M.build.spiffs_start=0x200000 +cw01.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +cw01.menu.eesz.4M2M.build.spiffs_blocksize=8192 +cw01.menu.eesz.4M3M=4M (3M SPIFFS) +cw01.menu.eesz.4M3M.build.flash_size=4M +cw01.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +cw01.menu.eesz.4M3M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M3M.upload.maximum_size=1044464 +cw01.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M3M.build.spiffs_start=0x100000 +cw01.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +cw01.menu.eesz.4M3M.build.spiffs_blocksize=8192 +cw01.menu.ip.lm2f=v2 Lower Memory +cw01.menu.ip.lm2f.build.lwip_include=lwip2/include +cw01.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +cw01.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +cw01.menu.ip.hb2f=v2 Higher Bandwidth +cw01.menu.ip.hb2f.build.lwip_include=lwip2/include +cw01.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +cw01.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +cw01.menu.ip.lm2n=v2 Lower Memory (no features) +cw01.menu.ip.lm2n.build.lwip_include=lwip2/include +cw01.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +cw01.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +cw01.menu.ip.hb2n=v2 Higher Bandwidth (no features) +cw01.menu.ip.hb2n.build.lwip_include=lwip2/include +cw01.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +cw01.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +cw01.menu.ip.lm6f=v2 IPv6 Lower Memory +cw01.menu.ip.lm6f.build.lwip_include=lwip2/include +cw01.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +cw01.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +cw01.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +cw01.menu.ip.hb6f.build.lwip_include=lwip2/include +cw01.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +cw01.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +cw01.menu.ip.hb1=v1.4 Higher Bandwidth +cw01.menu.ip.hb1.build.lwip_lib=-llwip_gcc +cw01.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +cw01.menu.ip.src=v1.4 Compile from source +cw01.menu.ip.src.build.lwip_lib=-llwip_src +cw01.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +cw01.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +cw01.menu.dbg.Disabled=Disabled +cw01.menu.dbg.Disabled.build.debug_port= +cw01.menu.dbg.Serial=Serial +cw01.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +cw01.menu.dbg.Serial1=Serial1 +cw01.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +cw01.menu.lvl.None____=None +cw01.menu.lvl.None____.build.debug_level= +cw01.menu.lvl.SSL=SSL +cw01.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +cw01.menu.lvl.TLS_MEM=TLS_MEM +cw01.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +cw01.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +cw01.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.HTTP_SERVER=HTTP_SERVER +cw01.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +cw01.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +cw01.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +cw01.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +cw01.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +cw01.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.CORE=CORE +cw01.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +cw01.menu.lvl.WIFI=WIFI +cw01.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +cw01.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +cw01.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +cw01.menu.lvl.UPDATER=UPDATER +cw01.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +cw01.menu.lvl.OTA=OTA +cw01.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +cw01.menu.lvl.OOM=OOM +cw01.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +cw01.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +cw01.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +cw01.menu.wipe.none=Only Sketch +cw01.menu.wipe.none.upload.erase_cmd= +cw01.menu.wipe.sdk=Sketch + WiFi Settings +cw01.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +cw01.menu.wipe.all=All Flash Contents +cw01.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +cw01.menu.baud.115200=115200 +cw01.menu.baud.115200.upload.speed=115200 +cw01.menu.baud.9600=9600 +cw01.menu.baud.9600.upload.speed=9600 +cw01.menu.baud.57600=57600 +cw01.menu.baud.57600.upload.speed=57600 +cw01.menu.baud.230400.linux=230400 +cw01.menu.baud.230400.macosx=230400 +cw01.menu.baud.230400.upload.speed=230400 +cw01.menu.baud.256000.windows=256000 +cw01.menu.baud.256000.upload.speed=256000 +cw01.menu.baud.460800.linux=460800 +cw01.menu.baud.460800.macosx=460800 +cw01.menu.baud.460800.upload.speed=460800 +cw01.menu.baud.512000.windows=512000 +cw01.menu.baud.512000.upload.speed=512000 +cw01.menu.baud.921600=921600 +cw01.menu.baud.921600.upload.speed=921600 + +############################################################## +espresso_lite_v1.name=ESPresso Lite 1.0 +espresso_lite_v1.build.board=ESP8266_ESPRESSO_LITE_V1 +espresso_lite_v1.build.variant=espresso_lite_v1 +espresso_lite_v1.upload.tool=esptool +espresso_lite_v1.upload.maximum_data_size=81920 +espresso_lite_v1.upload.wait_for_upload_port=true +espresso_lite_v1.upload.erase_cmd= +espresso_lite_v1.serial.disableDTR=true +espresso_lite_v1.serial.disableRTS=true +espresso_lite_v1.build.mcu=esp8266 +espresso_lite_v1.build.core=esp8266 +espresso_lite_v1.build.spiffs_pagesize=256 +espresso_lite_v1.build.debug_port= +espresso_lite_v1.build.debug_level= +espresso_lite_v1.menu.xtal.80=80 MHz +espresso_lite_v1.menu.xtal.80.build.f_cpu=80000000L +espresso_lite_v1.menu.xtal.160=160 MHz +espresso_lite_v1.menu.xtal.160.build.f_cpu=160000000L +espresso_lite_v1.menu.vt.flash=Flash +espresso_lite_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espresso_lite_v1.menu.vt.heap=Heap +espresso_lite_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espresso_lite_v1.menu.vt.iram=IRAM +espresso_lite_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espresso_lite_v1.menu.exception.disabled=Disabled +espresso_lite_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions +espresso_lite_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espresso_lite_v1.menu.exception.enabled=Enabled +espresso_lite_v1.menu.exception.enabled.build.exception_flags=-fexceptions +espresso_lite_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espresso_lite_v1.build.flash_mode=dio +espresso_lite_v1.build.flash_flags=-DFLASHMODE_DIO +espresso_lite_v1.build.flash_freq=40 +espresso_lite_v1.menu.eesz.4M=4M (no SPIFFS) +espresso_lite_v1.menu.eesz.4M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espresso_lite_v1.menu.eesz.4M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M1M=4M (1M SPIFFS) +espresso_lite_v1.menu.eesz.4M1M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M1M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espresso_lite_v1.menu.eesz.4M2M=4M (2M SPIFFS) +espresso_lite_v1.menu.eesz.4M2M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M2M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espresso_lite_v1.menu.eesz.4M3M=4M (3M SPIFFS) +espresso_lite_v1.menu.eesz.4M3M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M3M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espresso_lite_v1.menu.ResetMethod.ck=ck +espresso_lite_v1.menu.ResetMethod.ck.upload.resetmethod=ck +espresso_lite_v1.menu.ResetMethod.nodemcu=nodemcu +espresso_lite_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +espresso_lite_v1.menu.ip.lm2f=v2 Lower Memory +espresso_lite_v1.menu.ip.lm2f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espresso_lite_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.hb2f=v2 Higher Bandwidth +espresso_lite_v1.menu.ip.hb2f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espresso_lite_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.lm2n=v2 Lower Memory (no features) +espresso_lite_v1.menu.ip.lm2n.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espresso_lite_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espresso_lite_v1.menu.ip.hb2n.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espresso_lite_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.lm6f=v2 IPv6 Lower Memory +espresso_lite_v1.menu.ip.lm6f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espresso_lite_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espresso_lite_v1.menu.ip.hb6f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espresso_lite_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v1.menu.ip.hb1=v1.4 Higher Bandwidth +espresso_lite_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espresso_lite_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v1.menu.ip.src=v1.4 Compile from source +espresso_lite_v1.menu.ip.src.build.lwip_lib=-llwip_src +espresso_lite_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espresso_lite_v1.menu.dbg.Disabled=Disabled +espresso_lite_v1.menu.dbg.Disabled.build.debug_port= +espresso_lite_v1.menu.dbg.Serial=Serial +espresso_lite_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espresso_lite_v1.menu.dbg.Serial1=Serial1 +espresso_lite_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espresso_lite_v1.menu.lvl.None____=None +espresso_lite_v1.menu.lvl.None____.build.debug_level= +espresso_lite_v1.menu.lvl.SSL=SSL +espresso_lite_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espresso_lite_v1.menu.lvl.TLS_MEM=TLS_MEM +espresso_lite_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espresso_lite_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espresso_lite_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER +espresso_lite_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espresso_lite_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.CORE=CORE +espresso_lite_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espresso_lite_v1.menu.lvl.WIFI=WIFI +espresso_lite_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espresso_lite_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espresso_lite_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espresso_lite_v1.menu.lvl.UPDATER=UPDATER +espresso_lite_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espresso_lite_v1.menu.lvl.OTA=OTA +espresso_lite_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espresso_lite_v1.menu.lvl.OOM=OOM +espresso_lite_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espresso_lite_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espresso_lite_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espresso_lite_v1.menu.wipe.none=Only Sketch +espresso_lite_v1.menu.wipe.none.upload.erase_cmd= +espresso_lite_v1.menu.wipe.sdk=Sketch + WiFi Settings +espresso_lite_v1.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +espresso_lite_v1.menu.wipe.all=All Flash Contents +espresso_lite_v1.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +espresso_lite_v1.menu.baud.115200=115200 +espresso_lite_v1.menu.baud.115200.upload.speed=115200 +espresso_lite_v1.menu.baud.9600=9600 +espresso_lite_v1.menu.baud.9600.upload.speed=9600 +espresso_lite_v1.menu.baud.57600=57600 +espresso_lite_v1.menu.baud.57600.upload.speed=57600 +espresso_lite_v1.menu.baud.230400.linux=230400 +espresso_lite_v1.menu.baud.230400.macosx=230400 +espresso_lite_v1.menu.baud.230400.upload.speed=230400 +espresso_lite_v1.menu.baud.256000.windows=256000 +espresso_lite_v1.menu.baud.256000.upload.speed=256000 +espresso_lite_v1.menu.baud.460800.linux=460800 +espresso_lite_v1.menu.baud.460800.macosx=460800 +espresso_lite_v1.menu.baud.460800.upload.speed=460800 +espresso_lite_v1.menu.baud.512000.windows=512000 +espresso_lite_v1.menu.baud.512000.upload.speed=512000 +espresso_lite_v1.menu.baud.921600=921600 +espresso_lite_v1.menu.baud.921600.upload.speed=921600 + +############################################################## +espresso_lite_v2.name=ESPresso Lite 2.0 +espresso_lite_v2.build.board=ESP8266_ESPRESSO_LITE_V2 +espresso_lite_v2.build.variant=espresso_lite_v2 +espresso_lite_v2.upload.tool=esptool +espresso_lite_v2.upload.maximum_data_size=81920 +espresso_lite_v2.upload.wait_for_upload_port=true +espresso_lite_v2.upload.erase_cmd= +espresso_lite_v2.serial.disableDTR=true +espresso_lite_v2.serial.disableRTS=true +espresso_lite_v2.build.mcu=esp8266 +espresso_lite_v2.build.core=esp8266 +espresso_lite_v2.build.spiffs_pagesize=256 +espresso_lite_v2.build.debug_port= +espresso_lite_v2.build.debug_level= +espresso_lite_v2.menu.xtal.80=80 MHz +espresso_lite_v2.menu.xtal.80.build.f_cpu=80000000L +espresso_lite_v2.menu.xtal.160=160 MHz +espresso_lite_v2.menu.xtal.160.build.f_cpu=160000000L +espresso_lite_v2.menu.vt.flash=Flash +espresso_lite_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espresso_lite_v2.menu.vt.heap=Heap +espresso_lite_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espresso_lite_v2.menu.vt.iram=IRAM +espresso_lite_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espresso_lite_v2.menu.exception.disabled=Disabled +espresso_lite_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions +espresso_lite_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espresso_lite_v2.menu.exception.enabled=Enabled +espresso_lite_v2.menu.exception.enabled.build.exception_flags=-fexceptions +espresso_lite_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espresso_lite_v2.build.flash_mode=dio +espresso_lite_v2.build.flash_flags=-DFLASHMODE_DIO +espresso_lite_v2.build.flash_freq=40 +espresso_lite_v2.menu.eesz.4M=4M (no SPIFFS) +espresso_lite_v2.menu.eesz.4M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espresso_lite_v2.menu.eesz.4M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M1M=4M (1M SPIFFS) +espresso_lite_v2.menu.eesz.4M1M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M1M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espresso_lite_v2.menu.eesz.4M2M=4M (2M SPIFFS) +espresso_lite_v2.menu.eesz.4M2M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M2M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espresso_lite_v2.menu.eesz.4M3M=4M (3M SPIFFS) +espresso_lite_v2.menu.eesz.4M3M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M3M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espresso_lite_v2.menu.ResetMethod.ck=ck +espresso_lite_v2.menu.ResetMethod.ck.upload.resetmethod=ck +espresso_lite_v2.menu.ResetMethod.nodemcu=nodemcu +espresso_lite_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +espresso_lite_v2.menu.ip.lm2f=v2 Lower Memory +espresso_lite_v2.menu.ip.lm2f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espresso_lite_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.hb2f=v2 Higher Bandwidth +espresso_lite_v2.menu.ip.hb2f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espresso_lite_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.lm2n=v2 Lower Memory (no features) +espresso_lite_v2.menu.ip.lm2n.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espresso_lite_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espresso_lite_v2.menu.ip.hb2n.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espresso_lite_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.lm6f=v2 IPv6 Lower Memory +espresso_lite_v2.menu.ip.lm6f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espresso_lite_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espresso_lite_v2.menu.ip.hb6f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espresso_lite_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v2.menu.ip.hb1=v1.4 Higher Bandwidth +espresso_lite_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espresso_lite_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v2.menu.ip.src=v1.4 Compile from source +espresso_lite_v2.menu.ip.src.build.lwip_lib=-llwip_src +espresso_lite_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espresso_lite_v2.menu.dbg.Disabled=Disabled +espresso_lite_v2.menu.dbg.Disabled.build.debug_port= +espresso_lite_v2.menu.dbg.Serial=Serial +espresso_lite_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espresso_lite_v2.menu.dbg.Serial1=Serial1 +espresso_lite_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espresso_lite_v2.menu.lvl.None____=None +espresso_lite_v2.menu.lvl.None____.build.debug_level= +espresso_lite_v2.menu.lvl.SSL=SSL +espresso_lite_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espresso_lite_v2.menu.lvl.TLS_MEM=TLS_MEM +espresso_lite_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espresso_lite_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espresso_lite_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER +espresso_lite_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espresso_lite_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.CORE=CORE +espresso_lite_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espresso_lite_v2.menu.lvl.WIFI=WIFI +espresso_lite_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espresso_lite_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espresso_lite_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espresso_lite_v2.menu.lvl.UPDATER=UPDATER +espresso_lite_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espresso_lite_v2.menu.lvl.OTA=OTA +espresso_lite_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espresso_lite_v2.menu.lvl.OOM=OOM +espresso_lite_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espresso_lite_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espresso_lite_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espresso_lite_v2.menu.wipe.none=Only Sketch +espresso_lite_v2.menu.wipe.none.upload.erase_cmd= +espresso_lite_v2.menu.wipe.sdk=Sketch + WiFi Settings +espresso_lite_v2.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +espresso_lite_v2.menu.wipe.all=All Flash Contents +espresso_lite_v2.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +espresso_lite_v2.menu.baud.115200=115200 +espresso_lite_v2.menu.baud.115200.upload.speed=115200 +espresso_lite_v2.menu.baud.9600=9600 +espresso_lite_v2.menu.baud.9600.upload.speed=9600 +espresso_lite_v2.menu.baud.57600=57600 +espresso_lite_v2.menu.baud.57600.upload.speed=57600 +espresso_lite_v2.menu.baud.230400.linux=230400 +espresso_lite_v2.menu.baud.230400.macosx=230400 +espresso_lite_v2.menu.baud.230400.upload.speed=230400 +espresso_lite_v2.menu.baud.256000.windows=256000 +espresso_lite_v2.menu.baud.256000.upload.speed=256000 +espresso_lite_v2.menu.baud.460800.linux=460800 +espresso_lite_v2.menu.baud.460800.macosx=460800 +espresso_lite_v2.menu.baud.460800.upload.speed=460800 +espresso_lite_v2.menu.baud.512000.windows=512000 +espresso_lite_v2.menu.baud.512000.upload.speed=512000 +espresso_lite_v2.menu.baud.921600=921600 +espresso_lite_v2.menu.baud.921600.upload.speed=921600 + +############################################################## +phoenix_v1.name=Phoenix 1.0 +phoenix_v1.build.board=ESP8266_PHOENIX_V1 +phoenix_v1.build.variant=phoenix_v1 +phoenix_v1.upload.tool=esptool +phoenix_v1.upload.maximum_data_size=81920 +phoenix_v1.upload.wait_for_upload_port=true +phoenix_v1.upload.erase_cmd= +phoenix_v1.serial.disableDTR=true +phoenix_v1.serial.disableRTS=true +phoenix_v1.build.mcu=esp8266 +phoenix_v1.build.core=esp8266 +phoenix_v1.build.spiffs_pagesize=256 +phoenix_v1.build.debug_port= +phoenix_v1.build.debug_level= +phoenix_v1.menu.xtal.80=80 MHz +phoenix_v1.menu.xtal.80.build.f_cpu=80000000L +phoenix_v1.menu.xtal.160=160 MHz +phoenix_v1.menu.xtal.160.build.f_cpu=160000000L +phoenix_v1.menu.vt.flash=Flash +phoenix_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +phoenix_v1.menu.vt.heap=Heap +phoenix_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +phoenix_v1.menu.vt.iram=IRAM +phoenix_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +phoenix_v1.menu.exception.disabled=Disabled +phoenix_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions +phoenix_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +phoenix_v1.menu.exception.enabled=Enabled +phoenix_v1.menu.exception.enabled.build.exception_flags=-fexceptions +phoenix_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +phoenix_v1.build.flash_mode=dio +phoenix_v1.build.flash_flags=-DFLASHMODE_DIO +phoenix_v1.build.flash_freq=40 +phoenix_v1.menu.eesz.4M=4M (no SPIFFS) +phoenix_v1.menu.eesz.4M.build.flash_size=4M +phoenix_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +phoenix_v1.menu.eesz.4M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M1M=4M (1M SPIFFS) +phoenix_v1.menu.eesz.4M1M.build.flash_size=4M +phoenix_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +phoenix_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M1M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 +phoenix_v1.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +phoenix_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 +phoenix_v1.menu.eesz.4M2M=4M (2M SPIFFS) +phoenix_v1.menu.eesz.4M2M.build.flash_size=4M +phoenix_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +phoenix_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M2M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 +phoenix_v1.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +phoenix_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 +phoenix_v1.menu.eesz.4M3M=4M (3M SPIFFS) +phoenix_v1.menu.eesz.4M3M.build.flash_size=4M +phoenix_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +phoenix_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M3M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 +phoenix_v1.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +phoenix_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 +phoenix_v1.menu.ResetMethod.ck=ck +phoenix_v1.menu.ResetMethod.ck.upload.resetmethod=ck +phoenix_v1.menu.ResetMethod.nodemcu=nodemcu +phoenix_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +phoenix_v1.menu.ip.lm2f=v2 Lower Memory +phoenix_v1.menu.ip.lm2f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +phoenix_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.hb2f=v2 Higher Bandwidth +phoenix_v1.menu.ip.hb2f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +phoenix_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.lm2n=v2 Lower Memory (no features) +phoenix_v1.menu.ip.lm2n.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +phoenix_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) +phoenix_v1.menu.ip.hb2n.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +phoenix_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.lm6f=v2 IPv6 Lower Memory +phoenix_v1.menu.ip.lm6f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +phoenix_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +phoenix_v1.menu.ip.hb6f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +phoenix_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v1.menu.ip.hb1=v1.4 Higher Bandwidth +phoenix_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc +phoenix_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v1.menu.ip.src=v1.4 Compile from source +phoenix_v1.menu.ip.src.build.lwip_lib=-llwip_src +phoenix_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +phoenix_v1.menu.dbg.Disabled=Disabled +phoenix_v1.menu.dbg.Disabled.build.debug_port= +phoenix_v1.menu.dbg.Serial=Serial +phoenix_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +phoenix_v1.menu.dbg.Serial1=Serial1 +phoenix_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +phoenix_v1.menu.lvl.None____=None +phoenix_v1.menu.lvl.None____.build.debug_level= +phoenix_v1.menu.lvl.SSL=SSL +phoenix_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +phoenix_v1.menu.lvl.TLS_MEM=TLS_MEM +phoenix_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +phoenix_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +phoenix_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER +phoenix_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +phoenix_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +phoenix_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +phoenix_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +phoenix_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.CORE=CORE +phoenix_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +phoenix_v1.menu.lvl.WIFI=WIFI +phoenix_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +phoenix_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +phoenix_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +phoenix_v1.menu.lvl.UPDATER=UPDATER +phoenix_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +phoenix_v1.menu.lvl.OTA=OTA +phoenix_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +phoenix_v1.menu.lvl.OOM=OOM +phoenix_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +phoenix_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +phoenix_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +phoenix_v1.menu.wipe.none=Only Sketch +phoenix_v1.menu.wipe.none.upload.erase_cmd= +phoenix_v1.menu.wipe.sdk=Sketch + WiFi Settings +phoenix_v1.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +phoenix_v1.menu.wipe.all=All Flash Contents +phoenix_v1.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +phoenix_v1.menu.baud.115200=115200 +phoenix_v1.menu.baud.115200.upload.speed=115200 +phoenix_v1.menu.baud.9600=9600 +phoenix_v1.menu.baud.9600.upload.speed=9600 +phoenix_v1.menu.baud.57600=57600 +phoenix_v1.menu.baud.57600.upload.speed=57600 +phoenix_v1.menu.baud.230400.linux=230400 +phoenix_v1.menu.baud.230400.macosx=230400 +phoenix_v1.menu.baud.230400.upload.speed=230400 +phoenix_v1.menu.baud.256000.windows=256000 +phoenix_v1.menu.baud.256000.upload.speed=256000 +phoenix_v1.menu.baud.460800.linux=460800 +phoenix_v1.menu.baud.460800.macosx=460800 +phoenix_v1.menu.baud.460800.upload.speed=460800 +phoenix_v1.menu.baud.512000.windows=512000 +phoenix_v1.menu.baud.512000.upload.speed=512000 +phoenix_v1.menu.baud.921600=921600 +phoenix_v1.menu.baud.921600.upload.speed=921600 + +############################################################## +phoenix_v2.name=Phoenix 2.0 +phoenix_v2.build.board=ESP8266_PHOENIX_V2 +phoenix_v2.build.variant=phoenix_v2 +phoenix_v2.upload.tool=esptool +phoenix_v2.upload.maximum_data_size=81920 +phoenix_v2.upload.wait_for_upload_port=true +phoenix_v2.upload.erase_cmd= +phoenix_v2.serial.disableDTR=true +phoenix_v2.serial.disableRTS=true +phoenix_v2.build.mcu=esp8266 +phoenix_v2.build.core=esp8266 +phoenix_v2.build.spiffs_pagesize=256 +phoenix_v2.build.debug_port= +phoenix_v2.build.debug_level= +phoenix_v2.menu.xtal.80=80 MHz +phoenix_v2.menu.xtal.80.build.f_cpu=80000000L +phoenix_v2.menu.xtal.160=160 MHz +phoenix_v2.menu.xtal.160.build.f_cpu=160000000L +phoenix_v2.menu.vt.flash=Flash +phoenix_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +phoenix_v2.menu.vt.heap=Heap +phoenix_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +phoenix_v2.menu.vt.iram=IRAM +phoenix_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +phoenix_v2.menu.exception.disabled=Disabled +phoenix_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions +phoenix_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +phoenix_v2.menu.exception.enabled=Enabled +phoenix_v2.menu.exception.enabled.build.exception_flags=-fexceptions +phoenix_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +phoenix_v2.build.flash_mode=dio +phoenix_v2.build.flash_flags=-DFLASHMODE_DIO +phoenix_v2.build.flash_freq=40 +phoenix_v2.menu.eesz.4M=4M (no SPIFFS) +phoenix_v2.menu.eesz.4M.build.flash_size=4M +phoenix_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +phoenix_v2.menu.eesz.4M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M1M=4M (1M SPIFFS) +phoenix_v2.menu.eesz.4M1M.build.flash_size=4M +phoenix_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +phoenix_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M1M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 +phoenix_v2.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +phoenix_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 +phoenix_v2.menu.eesz.4M2M=4M (2M SPIFFS) +phoenix_v2.menu.eesz.4M2M.build.flash_size=4M +phoenix_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +phoenix_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M2M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 +phoenix_v2.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +phoenix_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 +phoenix_v2.menu.eesz.4M3M=4M (3M SPIFFS) +phoenix_v2.menu.eesz.4M3M.build.flash_size=4M +phoenix_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +phoenix_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M3M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 +phoenix_v2.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +phoenix_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 +phoenix_v2.menu.ResetMethod.ck=ck +phoenix_v2.menu.ResetMethod.ck.upload.resetmethod=ck +phoenix_v2.menu.ResetMethod.nodemcu=nodemcu +phoenix_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +phoenix_v2.menu.ip.lm2f=v2 Lower Memory +phoenix_v2.menu.ip.lm2f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +phoenix_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.hb2f=v2 Higher Bandwidth +phoenix_v2.menu.ip.hb2f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +phoenix_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.lm2n=v2 Lower Memory (no features) +phoenix_v2.menu.ip.lm2n.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +phoenix_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) +phoenix_v2.menu.ip.hb2n.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +phoenix_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.lm6f=v2 IPv6 Lower Memory +phoenix_v2.menu.ip.lm6f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +phoenix_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +phoenix_v2.menu.ip.hb6f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +phoenix_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v2.menu.ip.hb1=v1.4 Higher Bandwidth +phoenix_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc +phoenix_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v2.menu.ip.src=v1.4 Compile from source +phoenix_v2.menu.ip.src.build.lwip_lib=-llwip_src +phoenix_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +phoenix_v2.menu.dbg.Disabled=Disabled +phoenix_v2.menu.dbg.Disabled.build.debug_port= +phoenix_v2.menu.dbg.Serial=Serial +phoenix_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +phoenix_v2.menu.dbg.Serial1=Serial1 +phoenix_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +phoenix_v2.menu.lvl.None____=None +phoenix_v2.menu.lvl.None____.build.debug_level= +phoenix_v2.menu.lvl.SSL=SSL +phoenix_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +phoenix_v2.menu.lvl.TLS_MEM=TLS_MEM +phoenix_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +phoenix_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +phoenix_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER +phoenix_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +phoenix_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +phoenix_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +phoenix_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +phoenix_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.CORE=CORE +phoenix_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +phoenix_v2.menu.lvl.WIFI=WIFI +phoenix_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +phoenix_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +phoenix_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +phoenix_v2.menu.lvl.UPDATER=UPDATER +phoenix_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +phoenix_v2.menu.lvl.OTA=OTA +phoenix_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +phoenix_v2.menu.lvl.OOM=OOM +phoenix_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +phoenix_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +phoenix_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +phoenix_v2.menu.wipe.none=Only Sketch +phoenix_v2.menu.wipe.none.upload.erase_cmd= +phoenix_v2.menu.wipe.sdk=Sketch + WiFi Settings +phoenix_v2.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +phoenix_v2.menu.wipe.all=All Flash Contents +phoenix_v2.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +phoenix_v2.menu.baud.115200=115200 +phoenix_v2.menu.baud.115200.upload.speed=115200 +phoenix_v2.menu.baud.9600=9600 +phoenix_v2.menu.baud.9600.upload.speed=9600 +phoenix_v2.menu.baud.57600=57600 +phoenix_v2.menu.baud.57600.upload.speed=57600 +phoenix_v2.menu.baud.230400.linux=230400 +phoenix_v2.menu.baud.230400.macosx=230400 +phoenix_v2.menu.baud.230400.upload.speed=230400 +phoenix_v2.menu.baud.256000.windows=256000 +phoenix_v2.menu.baud.256000.upload.speed=256000 +phoenix_v2.menu.baud.460800.linux=460800 +phoenix_v2.menu.baud.460800.macosx=460800 +phoenix_v2.menu.baud.460800.upload.speed=460800 +phoenix_v2.menu.baud.512000.windows=512000 +phoenix_v2.menu.baud.512000.upload.speed=512000 +phoenix_v2.menu.baud.921600=921600 +phoenix_v2.menu.baud.921600.upload.speed=921600 + +############################################################## +nodemcu.name=NodeMCU 0.9 (ESP-12 Module) +nodemcu.build.board=ESP8266_NODEMCU +nodemcu.build.variant=nodemcu +nodemcu.upload.tool=esptool +nodemcu.upload.maximum_data_size=81920 +nodemcu.upload.wait_for_upload_port=true +nodemcu.upload.erase_cmd= +nodemcu.serial.disableDTR=true +nodemcu.serial.disableRTS=true +nodemcu.build.mcu=esp8266 +nodemcu.build.core=esp8266 +nodemcu.build.spiffs_pagesize=256 +nodemcu.build.debug_port= +nodemcu.build.debug_level= +nodemcu.menu.xtal.80=80 MHz +nodemcu.menu.xtal.80.build.f_cpu=80000000L +nodemcu.menu.xtal.160=160 MHz +nodemcu.menu.xtal.160.build.f_cpu=160000000L +nodemcu.menu.vt.flash=Flash +nodemcu.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +nodemcu.menu.vt.heap=Heap +nodemcu.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +nodemcu.menu.vt.iram=IRAM +nodemcu.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +nodemcu.menu.exception.disabled=Disabled +nodemcu.menu.exception.disabled.build.exception_flags=-fno-exceptions +nodemcu.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +nodemcu.menu.exception.enabled=Enabled +nodemcu.menu.exception.enabled.build.exception_flags=-fexceptions +nodemcu.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +nodemcu.upload.resetmethod=nodemcu +nodemcu.build.flash_mode=qio +nodemcu.build.flash_flags=-DFLASHMODE_QIO +nodemcu.build.flash_freq=40 +nodemcu.menu.eesz.4M=4M (no SPIFFS) +nodemcu.menu.eesz.4M.build.flash_size=4M +nodemcu.menu.eesz.4M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +nodemcu.menu.eesz.4M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M1M=4M (1M SPIFFS) +nodemcu.menu.eesz.4M1M.build.flash_size=4M +nodemcu.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +nodemcu.menu.eesz.4M1M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M1M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M1M.build.spiffs_start=0x300000 +nodemcu.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +nodemcu.menu.eesz.4M1M.build.spiffs_blocksize=8192 +nodemcu.menu.eesz.4M2M=4M (2M SPIFFS) +nodemcu.menu.eesz.4M2M.build.flash_size=4M +nodemcu.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +nodemcu.menu.eesz.4M2M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M2M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M2M.build.spiffs_start=0x200000 +nodemcu.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +nodemcu.menu.eesz.4M2M.build.spiffs_blocksize=8192 +nodemcu.menu.eesz.4M3M=4M (3M SPIFFS) +nodemcu.menu.eesz.4M3M.build.flash_size=4M +nodemcu.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +nodemcu.menu.eesz.4M3M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M3M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M3M.build.spiffs_start=0x100000 +nodemcu.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +nodemcu.menu.eesz.4M3M.build.spiffs_blocksize=8192 +nodemcu.menu.ip.lm2f=v2 Lower Memory +nodemcu.menu.ip.lm2f.build.lwip_include=lwip2/include +nodemcu.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +nodemcu.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcu.menu.ip.hb2f=v2 Higher Bandwidth +nodemcu.menu.ip.hb2f.build.lwip_include=lwip2/include +nodemcu.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +nodemcu.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcu.menu.ip.lm2n=v2 Lower Memory (no features) +nodemcu.menu.ip.lm2n.build.lwip_include=lwip2/include +nodemcu.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +nodemcu.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcu.menu.ip.hb2n=v2 Higher Bandwidth (no features) +nodemcu.menu.ip.hb2n.build.lwip_include=lwip2/include +nodemcu.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +nodemcu.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcu.menu.ip.lm6f=v2 IPv6 Lower Memory +nodemcu.menu.ip.lm6f.build.lwip_include=lwip2/include +nodemcu.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +nodemcu.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcu.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +nodemcu.menu.ip.hb6f.build.lwip_include=lwip2/include +nodemcu.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +nodemcu.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcu.menu.ip.hb1=v1.4 Higher Bandwidth +nodemcu.menu.ip.hb1.build.lwip_lib=-llwip_gcc +nodemcu.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcu.menu.ip.src=v1.4 Compile from source +nodemcu.menu.ip.src.build.lwip_lib=-llwip_src +nodemcu.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcu.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +nodemcu.menu.dbg.Disabled=Disabled +nodemcu.menu.dbg.Disabled.build.debug_port= +nodemcu.menu.dbg.Serial=Serial +nodemcu.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +nodemcu.menu.dbg.Serial1=Serial1 +nodemcu.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +nodemcu.menu.lvl.None____=None +nodemcu.menu.lvl.None____.build.debug_level= +nodemcu.menu.lvl.SSL=SSL +nodemcu.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +nodemcu.menu.lvl.TLS_MEM=TLS_MEM +nodemcu.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +nodemcu.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +nodemcu.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.HTTP_SERVER=HTTP_SERVER +nodemcu.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +nodemcu.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +nodemcu.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +nodemcu.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +nodemcu.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.CORE=CORE +nodemcu.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +nodemcu.menu.lvl.WIFI=WIFI +nodemcu.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +nodemcu.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +nodemcu.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +nodemcu.menu.lvl.UPDATER=UPDATER +nodemcu.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +nodemcu.menu.lvl.OTA=OTA +nodemcu.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +nodemcu.menu.lvl.OOM=OOM +nodemcu.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +nodemcu.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +nodemcu.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +nodemcu.menu.wipe.none=Only Sketch +nodemcu.menu.wipe.none.upload.erase_cmd= +nodemcu.menu.wipe.sdk=Sketch + WiFi Settings +nodemcu.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +nodemcu.menu.wipe.all=All Flash Contents +nodemcu.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +nodemcu.menu.baud.115200=115200 +nodemcu.menu.baud.115200.upload.speed=115200 +nodemcu.menu.baud.9600=9600 +nodemcu.menu.baud.9600.upload.speed=9600 +nodemcu.menu.baud.57600=57600 +nodemcu.menu.baud.57600.upload.speed=57600 +nodemcu.menu.baud.230400.linux=230400 +nodemcu.menu.baud.230400.macosx=230400 +nodemcu.menu.baud.230400.upload.speed=230400 +nodemcu.menu.baud.256000.windows=256000 +nodemcu.menu.baud.256000.upload.speed=256000 +nodemcu.menu.baud.460800.linux=460800 +nodemcu.menu.baud.460800.macosx=460800 +nodemcu.menu.baud.460800.upload.speed=460800 +nodemcu.menu.baud.512000.windows=512000 +nodemcu.menu.baud.512000.upload.speed=512000 +nodemcu.menu.baud.921600=921600 +nodemcu.menu.baud.921600.upload.speed=921600 + +############################################################## +nodemcuv2.name=NodeMCU 1.0 (ESP-12E Module) +nodemcuv2.build.board=ESP8266_NODEMCU +nodemcuv2.build.variant=nodemcu +nodemcuv2.upload.tool=esptool +nodemcuv2.upload.maximum_data_size=81920 +nodemcuv2.upload.wait_for_upload_port=true +nodemcuv2.upload.erase_cmd= +nodemcuv2.serial.disableDTR=true +nodemcuv2.serial.disableRTS=true +nodemcuv2.build.mcu=esp8266 +nodemcuv2.build.core=esp8266 +nodemcuv2.build.spiffs_pagesize=256 +nodemcuv2.build.debug_port= +nodemcuv2.build.debug_level= +nodemcuv2.menu.xtal.80=80 MHz +nodemcuv2.menu.xtal.80.build.f_cpu=80000000L +nodemcuv2.menu.xtal.160=160 MHz +nodemcuv2.menu.xtal.160.build.f_cpu=160000000L +nodemcuv2.menu.vt.flash=Flash +nodemcuv2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +nodemcuv2.menu.vt.heap=Heap +nodemcuv2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +nodemcuv2.menu.vt.iram=IRAM +nodemcuv2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +nodemcuv2.menu.exception.disabled=Disabled +nodemcuv2.menu.exception.disabled.build.exception_flags=-fno-exceptions +nodemcuv2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +nodemcuv2.menu.exception.enabled=Enabled +nodemcuv2.menu.exception.enabled.build.exception_flags=-fexceptions +nodemcuv2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +nodemcuv2.upload.resetmethod=nodemcu +nodemcuv2.build.flash_mode=dio +nodemcuv2.build.flash_flags=-DFLASHMODE_DIO +nodemcuv2.build.flash_freq=40 +nodemcuv2.menu.eesz.4M=4M (no SPIFFS) +nodemcuv2.menu.eesz.4M.build.flash_size=4M +nodemcuv2.menu.eesz.4M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +nodemcuv2.menu.eesz.4M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M1M=4M (1M SPIFFS) +nodemcuv2.menu.eesz.4M1M.build.flash_size=4M +nodemcuv2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +nodemcuv2.menu.eesz.4M1M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M1M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M1M.build.spiffs_start=0x300000 +nodemcuv2.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +nodemcuv2.menu.eesz.4M1M.build.spiffs_blocksize=8192 +nodemcuv2.menu.eesz.4M2M=4M (2M SPIFFS) +nodemcuv2.menu.eesz.4M2M.build.flash_size=4M +nodemcuv2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +nodemcuv2.menu.eesz.4M2M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M2M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M2M.build.spiffs_start=0x200000 +nodemcuv2.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +nodemcuv2.menu.eesz.4M2M.build.spiffs_blocksize=8192 +nodemcuv2.menu.eesz.4M3M=4M (3M SPIFFS) +nodemcuv2.menu.eesz.4M3M.build.flash_size=4M +nodemcuv2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +nodemcuv2.menu.eesz.4M3M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M3M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M3M.build.spiffs_start=0x100000 +nodemcuv2.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +nodemcuv2.menu.eesz.4M3M.build.spiffs_blocksize=8192 +nodemcuv2.menu.ip.lm2f=v2 Lower Memory +nodemcuv2.menu.ip.lm2f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +nodemcuv2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.hb2f=v2 Higher Bandwidth +nodemcuv2.menu.ip.hb2f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +nodemcuv2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.lm2n=v2 Lower Memory (no features) +nodemcuv2.menu.ip.lm2n.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +nodemcuv2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.hb2n=v2 Higher Bandwidth (no features) +nodemcuv2.menu.ip.hb2n.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +nodemcuv2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.lm6f=v2 IPv6 Lower Memory +nodemcuv2.menu.ip.lm6f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +nodemcuv2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcuv2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +nodemcuv2.menu.ip.hb6f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +nodemcuv2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcuv2.menu.ip.hb1=v1.4 Higher Bandwidth +nodemcuv2.menu.ip.hb1.build.lwip_lib=-llwip_gcc +nodemcuv2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcuv2.menu.ip.src=v1.4 Compile from source +nodemcuv2.menu.ip.src.build.lwip_lib=-llwip_src +nodemcuv2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcuv2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +nodemcuv2.menu.dbg.Disabled=Disabled +nodemcuv2.menu.dbg.Disabled.build.debug_port= +nodemcuv2.menu.dbg.Serial=Serial +nodemcuv2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +nodemcuv2.menu.dbg.Serial1=Serial1 +nodemcuv2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +nodemcuv2.menu.lvl.None____=None +nodemcuv2.menu.lvl.None____.build.debug_level= +nodemcuv2.menu.lvl.SSL=SSL +nodemcuv2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +nodemcuv2.menu.lvl.TLS_MEM=TLS_MEM +nodemcuv2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +nodemcuv2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +nodemcuv2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.HTTP_SERVER=HTTP_SERVER +nodemcuv2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +nodemcuv2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +nodemcuv2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +nodemcuv2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +nodemcuv2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.CORE=CORE +nodemcuv2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +nodemcuv2.menu.lvl.WIFI=WIFI +nodemcuv2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +nodemcuv2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +nodemcuv2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +nodemcuv2.menu.lvl.UPDATER=UPDATER +nodemcuv2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +nodemcuv2.menu.lvl.OTA=OTA +nodemcuv2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +nodemcuv2.menu.lvl.OOM=OOM +nodemcuv2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +nodemcuv2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +nodemcuv2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +nodemcuv2.menu.wipe.none=Only Sketch +nodemcuv2.menu.wipe.none.upload.erase_cmd= +nodemcuv2.menu.wipe.sdk=Sketch + WiFi Settings +nodemcuv2.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +nodemcuv2.menu.wipe.all=All Flash Contents +nodemcuv2.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +nodemcuv2.menu.baud.115200=115200 +nodemcuv2.menu.baud.115200.upload.speed=115200 +nodemcuv2.menu.baud.9600=9600 +nodemcuv2.menu.baud.9600.upload.speed=9600 +nodemcuv2.menu.baud.57600=57600 +nodemcuv2.menu.baud.57600.upload.speed=57600 +nodemcuv2.menu.baud.230400.linux=230400 +nodemcuv2.menu.baud.230400.macosx=230400 +nodemcuv2.menu.baud.230400.upload.speed=230400 +nodemcuv2.menu.baud.256000.windows=256000 +nodemcuv2.menu.baud.256000.upload.speed=256000 +nodemcuv2.menu.baud.460800.linux=460800 +nodemcuv2.menu.baud.460800.macosx=460800 +nodemcuv2.menu.baud.460800.upload.speed=460800 +nodemcuv2.menu.baud.512000.windows=512000 +nodemcuv2.menu.baud.512000.upload.speed=512000 +nodemcuv2.menu.baud.921600=921600 +nodemcuv2.menu.baud.921600.upload.speed=921600 + +############################################################## +modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV) +modwifi.build.board=MOD_WIFI_ESP8266 +modwifi.build.variant=modwifi +modwifi.upload.tool=esptool +modwifi.upload.maximum_data_size=81920 +modwifi.upload.wait_for_upload_port=true +modwifi.upload.erase_cmd= +modwifi.serial.disableDTR=true +modwifi.serial.disableRTS=true +modwifi.build.mcu=esp8266 +modwifi.build.core=esp8266 +modwifi.build.spiffs_pagesize=256 +modwifi.build.debug_port= +modwifi.build.debug_level= +modwifi.menu.xtal.80=80 MHz +modwifi.menu.xtal.80.build.f_cpu=80000000L +modwifi.menu.xtal.160=160 MHz +modwifi.menu.xtal.160.build.f_cpu=160000000L +modwifi.menu.vt.flash=Flash +modwifi.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +modwifi.menu.vt.heap=Heap +modwifi.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +modwifi.menu.vt.iram=IRAM +modwifi.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +modwifi.menu.exception.disabled=Disabled +modwifi.menu.exception.disabled.build.exception_flags=-fno-exceptions +modwifi.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +modwifi.menu.exception.enabled=Enabled +modwifi.menu.exception.enabled.build.exception_flags=-fexceptions +modwifi.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +modwifi.upload.resetmethod=ck +modwifi.build.flash_mode=qio +modwifi.build.flash_flags=-DFLASHMODE_QIO +modwifi.build.flash_freq=40 +modwifi.menu.eesz.2M=2M (no SPIFFS) +modwifi.menu.eesz.2M.build.flash_size=2M +modwifi.menu.eesz.2M.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld +modwifi.menu.eesz.2M.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M.upload.maximum_size=1044464 +modwifi.menu.eesz.2M.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M128=2M (128K SPIFFS) +modwifi.menu.eesz.2M128.build.flash_size=2M +modwifi.menu.eesz.2M128.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld +modwifi.menu.eesz.2M128.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M128.upload.maximum_size=1044464 +modwifi.menu.eesz.2M128.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M128.build.spiffs_start=0x1E0000 +modwifi.menu.eesz.2M128.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M128.build.spiffs_blocksize=4096 +modwifi.menu.eesz.2M256=2M (256K SPIFFS) +modwifi.menu.eesz.2M256.build.flash_size=2M +modwifi.menu.eesz.2M256.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld +modwifi.menu.eesz.2M256.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M256.upload.maximum_size=1044464 +modwifi.menu.eesz.2M256.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M256.build.spiffs_start=0x1C0000 +modwifi.menu.eesz.2M256.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M256.build.spiffs_blocksize=4096 +modwifi.menu.eesz.2M512=2M (512K SPIFFS) +modwifi.menu.eesz.2M512.build.flash_size=2M +modwifi.menu.eesz.2M512.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld +modwifi.menu.eesz.2M512.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M512.upload.maximum_size=1044464 +modwifi.menu.eesz.2M512.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M512.build.spiffs_start=0x180000 +modwifi.menu.eesz.2M512.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M512.build.spiffs_blocksize=8192 +modwifi.menu.eesz.2M1M=2M (1M SPIFFS) +modwifi.menu.eesz.2M1M.build.flash_size=2M +modwifi.menu.eesz.2M1M.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld +modwifi.menu.eesz.2M1M.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M1M.upload.maximum_size=1044464 +modwifi.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M1M.build.spiffs_start=0x100000 +modwifi.menu.eesz.2M1M.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M1M.build.spiffs_blocksize=8192 +modwifi.menu.ip.lm2f=v2 Lower Memory +modwifi.menu.ip.lm2f.build.lwip_include=lwip2/include +modwifi.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +modwifi.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +modwifi.menu.ip.hb2f=v2 Higher Bandwidth +modwifi.menu.ip.hb2f.build.lwip_include=lwip2/include +modwifi.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +modwifi.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +modwifi.menu.ip.lm2n=v2 Lower Memory (no features) +modwifi.menu.ip.lm2n.build.lwip_include=lwip2/include +modwifi.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +modwifi.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +modwifi.menu.ip.hb2n=v2 Higher Bandwidth (no features) +modwifi.menu.ip.hb2n.build.lwip_include=lwip2/include +modwifi.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +modwifi.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +modwifi.menu.ip.lm6f=v2 IPv6 Lower Memory +modwifi.menu.ip.lm6f.build.lwip_include=lwip2/include +modwifi.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +modwifi.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +modwifi.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +modwifi.menu.ip.hb6f.build.lwip_include=lwip2/include +modwifi.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +modwifi.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +modwifi.menu.ip.hb1=v1.4 Higher Bandwidth +modwifi.menu.ip.hb1.build.lwip_lib=-llwip_gcc +modwifi.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +modwifi.menu.ip.src=v1.4 Compile from source +modwifi.menu.ip.src.build.lwip_lib=-llwip_src +modwifi.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +modwifi.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +modwifi.menu.dbg.Disabled=Disabled +modwifi.menu.dbg.Disabled.build.debug_port= +modwifi.menu.dbg.Serial=Serial +modwifi.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +modwifi.menu.dbg.Serial1=Serial1 +modwifi.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +modwifi.menu.lvl.None____=None +modwifi.menu.lvl.None____.build.debug_level= +modwifi.menu.lvl.SSL=SSL +modwifi.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +modwifi.menu.lvl.TLS_MEM=TLS_MEM +modwifi.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +modwifi.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +modwifi.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.HTTP_SERVER=HTTP_SERVER +modwifi.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +modwifi.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +modwifi.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +modwifi.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +modwifi.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +modwifi.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.CORE=CORE +modwifi.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +modwifi.menu.lvl.WIFI=WIFI +modwifi.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +modwifi.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +modwifi.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +modwifi.menu.lvl.UPDATER=UPDATER +modwifi.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +modwifi.menu.lvl.OTA=OTA +modwifi.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +modwifi.menu.lvl.OOM=OOM +modwifi.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +modwifi.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +modwifi.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +modwifi.menu.wipe.none=Only Sketch +modwifi.menu.wipe.none.upload.erase_cmd= +modwifi.menu.wipe.sdk=Sketch + WiFi Settings +modwifi.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +modwifi.menu.wipe.all=All Flash Contents +modwifi.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +modwifi.menu.baud.115200=115200 +modwifi.menu.baud.115200.upload.speed=115200 +modwifi.menu.baud.9600=9600 +modwifi.menu.baud.9600.upload.speed=9600 +modwifi.menu.baud.57600=57600 +modwifi.menu.baud.57600.upload.speed=57600 +modwifi.menu.baud.230400.linux=230400 +modwifi.menu.baud.230400.macosx=230400 +modwifi.menu.baud.230400.upload.speed=230400 +modwifi.menu.baud.256000.windows=256000 +modwifi.menu.baud.256000.upload.speed=256000 +modwifi.menu.baud.460800.linux=460800 +modwifi.menu.baud.460800.macosx=460800 +modwifi.menu.baud.460800.upload.speed=460800 +modwifi.menu.baud.512000.windows=512000 +modwifi.menu.baud.512000.upload.speed=512000 +modwifi.menu.baud.921600=921600 +modwifi.menu.baud.921600.upload.speed=921600 + +############################################################## +thing.name=SparkFun ESP8266 Thing +thing.build.board=ESP8266_THING +thing.build.variant=thing +thing.upload.tool=esptool +thing.upload.maximum_data_size=81920 +thing.upload.wait_for_upload_port=true +thing.upload.erase_cmd= +thing.serial.disableDTR=true +thing.serial.disableRTS=true +thing.build.mcu=esp8266 +thing.build.core=esp8266 +thing.build.spiffs_pagesize=256 +thing.build.debug_port= +thing.build.debug_level= +thing.menu.xtal.80=80 MHz +thing.menu.xtal.80.build.f_cpu=80000000L +thing.menu.xtal.160=160 MHz +thing.menu.xtal.160.build.f_cpu=160000000L +thing.menu.vt.flash=Flash +thing.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +thing.menu.vt.heap=Heap +thing.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +thing.menu.vt.iram=IRAM +thing.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +thing.menu.exception.disabled=Disabled +thing.menu.exception.disabled.build.exception_flags=-fno-exceptions +thing.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +thing.menu.exception.enabled=Enabled +thing.menu.exception.enabled.build.exception_flags=-fexceptions +thing.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +thing.upload.resetmethod=ck +thing.build.flash_mode=qio +thing.build.flash_flags=-DFLASHMODE_QIO +thing.build.flash_freq=40 +thing.menu.eesz.512K=512K (no SPIFFS) +thing.menu.eesz.512K.build.flash_size=512K +thing.menu.eesz.512K.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +thing.menu.eesz.512K.build.spiffs_pagesize=256 +thing.menu.eesz.512K.upload.maximum_size=499696 +thing.menu.eesz.512K.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K32=512K (32K SPIFFS) +thing.menu.eesz.512K32.build.flash_size=512K +thing.menu.eesz.512K32.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +thing.menu.eesz.512K32.build.spiffs_pagesize=256 +thing.menu.eesz.512K32.upload.maximum_size=466928 +thing.menu.eesz.512K32.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K32.build.spiffs_start=0x73000 +thing.menu.eesz.512K32.build.spiffs_end=0x7B000 +thing.menu.eesz.512K32.build.spiffs_blocksize=4096 +thing.menu.eesz.512K64=512K (64K SPIFFS) +thing.menu.eesz.512K64.build.flash_size=512K +thing.menu.eesz.512K64.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +thing.menu.eesz.512K64.build.spiffs_pagesize=256 +thing.menu.eesz.512K64.upload.maximum_size=434160 +thing.menu.eesz.512K64.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K64.build.spiffs_start=0x6B000 +thing.menu.eesz.512K64.build.spiffs_end=0x7B000 +thing.menu.eesz.512K64.build.spiffs_blocksize=4096 +thing.menu.eesz.512K128=512K (128K SPIFFS) +thing.menu.eesz.512K128.build.flash_size=512K +thing.menu.eesz.512K128.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +thing.menu.eesz.512K128.build.spiffs_pagesize=256 +thing.menu.eesz.512K128.upload.maximum_size=368624 +thing.menu.eesz.512K128.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K128.build.spiffs_start=0x5B000 +thing.menu.eesz.512K128.build.spiffs_end=0x7B000 +thing.menu.eesz.512K128.build.spiffs_blocksize=4096 +thing.menu.ip.lm2f=v2 Lower Memory +thing.menu.ip.lm2f.build.lwip_include=lwip2/include +thing.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +thing.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thing.menu.ip.hb2f=v2 Higher Bandwidth +thing.menu.ip.hb2f.build.lwip_include=lwip2/include +thing.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +thing.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thing.menu.ip.lm2n=v2 Lower Memory (no features) +thing.menu.ip.lm2n.build.lwip_include=lwip2/include +thing.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +thing.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thing.menu.ip.hb2n=v2 Higher Bandwidth (no features) +thing.menu.ip.hb2n.build.lwip_include=lwip2/include +thing.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +thing.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thing.menu.ip.lm6f=v2 IPv6 Lower Memory +thing.menu.ip.lm6f.build.lwip_include=lwip2/include +thing.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +thing.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thing.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +thing.menu.ip.hb6f.build.lwip_include=lwip2/include +thing.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +thing.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thing.menu.ip.hb1=v1.4 Higher Bandwidth +thing.menu.ip.hb1.build.lwip_lib=-llwip_gcc +thing.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +thing.menu.ip.src=v1.4 Compile from source +thing.menu.ip.src.build.lwip_lib=-llwip_src +thing.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +thing.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +thing.menu.dbg.Disabled=Disabled +thing.menu.dbg.Disabled.build.debug_port= +thing.menu.dbg.Serial=Serial +thing.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +thing.menu.dbg.Serial1=Serial1 +thing.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +thing.menu.lvl.None____=None +thing.menu.lvl.None____.build.debug_level= +thing.menu.lvl.SSL=SSL +thing.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +thing.menu.lvl.TLS_MEM=TLS_MEM +thing.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +thing.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +thing.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.HTTP_SERVER=HTTP_SERVER +thing.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +thing.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +thing.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +thing.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +thing.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +thing.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.CORE=CORE +thing.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +thing.menu.lvl.WIFI=WIFI +thing.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +thing.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +thing.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +thing.menu.lvl.UPDATER=UPDATER +thing.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +thing.menu.lvl.OTA=OTA +thing.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +thing.menu.lvl.OOM=OOM +thing.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +thing.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +thing.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +thing.menu.wipe.none=Only Sketch +thing.menu.wipe.none.upload.erase_cmd= +thing.menu.wipe.sdk=Sketch + WiFi Settings +thing.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +thing.menu.wipe.all=All Flash Contents +thing.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +thing.menu.baud.115200=115200 +thing.menu.baud.115200.upload.speed=115200 +thing.menu.baud.9600=9600 +thing.menu.baud.9600.upload.speed=9600 +thing.menu.baud.57600=57600 +thing.menu.baud.57600.upload.speed=57600 +thing.menu.baud.230400.linux=230400 +thing.menu.baud.230400.macosx=230400 +thing.menu.baud.230400.upload.speed=230400 +thing.menu.baud.256000.windows=256000 +thing.menu.baud.256000.upload.speed=256000 +thing.menu.baud.460800.linux=460800 +thing.menu.baud.460800.macosx=460800 +thing.menu.baud.460800.upload.speed=460800 +thing.menu.baud.512000.windows=512000 +thing.menu.baud.512000.upload.speed=512000 +thing.menu.baud.921600=921600 +thing.menu.baud.921600.upload.speed=921600 + +############################################################## +thingdev.name=SparkFun ESP8266 Thing Dev +thingdev.build.board=ESP8266_THING_DEV +thingdev.build.variant=thing +thingdev.upload.tool=esptool +thingdev.upload.maximum_data_size=81920 +thingdev.upload.wait_for_upload_port=true +thingdev.upload.erase_cmd= +thingdev.serial.disableDTR=true +thingdev.serial.disableRTS=true +thingdev.build.mcu=esp8266 +thingdev.build.core=esp8266 +thingdev.build.spiffs_pagesize=256 +thingdev.build.debug_port= +thingdev.build.debug_level= +thingdev.menu.xtal.80=80 MHz +thingdev.menu.xtal.80.build.f_cpu=80000000L +thingdev.menu.xtal.160=160 MHz +thingdev.menu.xtal.160.build.f_cpu=160000000L +thingdev.menu.vt.flash=Flash +thingdev.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +thingdev.menu.vt.heap=Heap +thingdev.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +thingdev.menu.vt.iram=IRAM +thingdev.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +thingdev.menu.exception.disabled=Disabled +thingdev.menu.exception.disabled.build.exception_flags=-fno-exceptions +thingdev.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +thingdev.menu.exception.enabled=Enabled +thingdev.menu.exception.enabled.build.exception_flags=-fexceptions +thingdev.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +thingdev.upload.resetmethod=nodemcu +thingdev.build.flash_mode=dio +thingdev.build.flash_flags=-DFLASHMODE_DIO +thingdev.build.flash_freq=40 +thingdev.menu.eesz.512K=512K (no SPIFFS) +thingdev.menu.eesz.512K.build.flash_size=512K +thingdev.menu.eesz.512K.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +thingdev.menu.eesz.512K.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K.upload.maximum_size=499696 +thingdev.menu.eesz.512K.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K32=512K (32K SPIFFS) +thingdev.menu.eesz.512K32.build.flash_size=512K +thingdev.menu.eesz.512K32.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +thingdev.menu.eesz.512K32.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K32.upload.maximum_size=466928 +thingdev.menu.eesz.512K32.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K32.build.spiffs_start=0x73000 +thingdev.menu.eesz.512K32.build.spiffs_end=0x7B000 +thingdev.menu.eesz.512K32.build.spiffs_blocksize=4096 +thingdev.menu.eesz.512K64=512K (64K SPIFFS) +thingdev.menu.eesz.512K64.build.flash_size=512K +thingdev.menu.eesz.512K64.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +thingdev.menu.eesz.512K64.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K64.upload.maximum_size=434160 +thingdev.menu.eesz.512K64.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K64.build.spiffs_start=0x6B000 +thingdev.menu.eesz.512K64.build.spiffs_end=0x7B000 +thingdev.menu.eesz.512K64.build.spiffs_blocksize=4096 +thingdev.menu.eesz.512K128=512K (128K SPIFFS) +thingdev.menu.eesz.512K128.build.flash_size=512K +thingdev.menu.eesz.512K128.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +thingdev.menu.eesz.512K128.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K128.upload.maximum_size=368624 +thingdev.menu.eesz.512K128.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K128.build.spiffs_start=0x5B000 +thingdev.menu.eesz.512K128.build.spiffs_end=0x7B000 +thingdev.menu.eesz.512K128.build.spiffs_blocksize=4096 +thingdev.menu.ip.lm2f=v2 Lower Memory +thingdev.menu.ip.lm2f.build.lwip_include=lwip2/include +thingdev.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +thingdev.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thingdev.menu.ip.hb2f=v2 Higher Bandwidth +thingdev.menu.ip.hb2f.build.lwip_include=lwip2/include +thingdev.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +thingdev.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thingdev.menu.ip.lm2n=v2 Lower Memory (no features) +thingdev.menu.ip.lm2n.build.lwip_include=lwip2/include +thingdev.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +thingdev.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thingdev.menu.ip.hb2n=v2 Higher Bandwidth (no features) +thingdev.menu.ip.hb2n.build.lwip_include=lwip2/include +thingdev.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +thingdev.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thingdev.menu.ip.lm6f=v2 IPv6 Lower Memory +thingdev.menu.ip.lm6f.build.lwip_include=lwip2/include +thingdev.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +thingdev.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thingdev.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +thingdev.menu.ip.hb6f.build.lwip_include=lwip2/include +thingdev.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +thingdev.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thingdev.menu.ip.hb1=v1.4 Higher Bandwidth +thingdev.menu.ip.hb1.build.lwip_lib=-llwip_gcc +thingdev.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +thingdev.menu.ip.src=v1.4 Compile from source +thingdev.menu.ip.src.build.lwip_lib=-llwip_src +thingdev.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +thingdev.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +thingdev.menu.dbg.Disabled=Disabled +thingdev.menu.dbg.Disabled.build.debug_port= +thingdev.menu.dbg.Serial=Serial +thingdev.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +thingdev.menu.dbg.Serial1=Serial1 +thingdev.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +thingdev.menu.lvl.None____=None +thingdev.menu.lvl.None____.build.debug_level= +thingdev.menu.lvl.SSL=SSL +thingdev.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +thingdev.menu.lvl.TLS_MEM=TLS_MEM +thingdev.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +thingdev.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +thingdev.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.HTTP_SERVER=HTTP_SERVER +thingdev.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +thingdev.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +thingdev.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +thingdev.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +thingdev.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +thingdev.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.CORE=CORE +thingdev.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +thingdev.menu.lvl.WIFI=WIFI +thingdev.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +thingdev.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +thingdev.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +thingdev.menu.lvl.UPDATER=UPDATER +thingdev.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +thingdev.menu.lvl.OTA=OTA +thingdev.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +thingdev.menu.lvl.OOM=OOM +thingdev.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +thingdev.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +thingdev.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +thingdev.menu.wipe.none=Only Sketch +thingdev.menu.wipe.none.upload.erase_cmd= +thingdev.menu.wipe.sdk=Sketch + WiFi Settings +thingdev.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +thingdev.menu.wipe.all=All Flash Contents +thingdev.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +thingdev.menu.baud.115200=115200 +thingdev.menu.baud.115200.upload.speed=115200 +thingdev.menu.baud.9600=9600 +thingdev.menu.baud.9600.upload.speed=9600 +thingdev.menu.baud.57600=57600 +thingdev.menu.baud.57600.upload.speed=57600 +thingdev.menu.baud.230400.linux=230400 +thingdev.menu.baud.230400.macosx=230400 +thingdev.menu.baud.230400.upload.speed=230400 +thingdev.menu.baud.256000.windows=256000 +thingdev.menu.baud.256000.upload.speed=256000 +thingdev.menu.baud.460800.linux=460800 +thingdev.menu.baud.460800.macosx=460800 +thingdev.menu.baud.460800.upload.speed=460800 +thingdev.menu.baud.512000.windows=512000 +thingdev.menu.baud.512000.upload.speed=512000 +thingdev.menu.baud.921600=921600 +thingdev.menu.baud.921600.upload.speed=921600 + +############################################################## +esp210.name=SweetPea ESP-210 +esp210.build.board=ESP8266_ESP210 +esp210.upload.tool=esptool +esp210.upload.maximum_data_size=81920 +esp210.upload.wait_for_upload_port=true +esp210.upload.erase_cmd= +esp210.serial.disableDTR=true +esp210.serial.disableRTS=true +esp210.build.mcu=esp8266 +esp210.build.core=esp8266 +esp210.build.variant=generic +esp210.build.spiffs_pagesize=256 +esp210.build.debug_port= +esp210.build.debug_level= +esp210.menu.xtal.80=80 MHz +esp210.menu.xtal.80.build.f_cpu=80000000L +esp210.menu.xtal.160=160 MHz +esp210.menu.xtal.160.build.f_cpu=160000000L +esp210.menu.vt.flash=Flash +esp210.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +esp210.menu.vt.heap=Heap +esp210.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +esp210.menu.vt.iram=IRAM +esp210.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +esp210.menu.exception.disabled=Disabled +esp210.menu.exception.disabled.build.exception_flags=-fno-exceptions +esp210.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +esp210.menu.exception.enabled=Enabled +esp210.menu.exception.enabled.build.exception_flags=-fexceptions +esp210.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +esp210.upload.resetmethod=ck +esp210.build.flash_mode=qio +esp210.build.flash_flags=-DFLASHMODE_QIO +esp210.build.flash_freq=40 +esp210.menu.eesz.4M=4M (no SPIFFS) +esp210.menu.eesz.4M.build.flash_size=4M +esp210.menu.eesz.4M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +esp210.menu.eesz.4M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M.upload.maximum_size=1044464 +esp210.menu.eesz.4M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M1M=4M (1M SPIFFS) +esp210.menu.eesz.4M1M.build.flash_size=4M +esp210.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +esp210.menu.eesz.4M1M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M1M.upload.maximum_size=1044464 +esp210.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M1M.build.spiffs_start=0x300000 +esp210.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +esp210.menu.eesz.4M1M.build.spiffs_blocksize=8192 +esp210.menu.eesz.4M2M=4M (2M SPIFFS) +esp210.menu.eesz.4M2M.build.flash_size=4M +esp210.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +esp210.menu.eesz.4M2M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M2M.upload.maximum_size=1044464 +esp210.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M2M.build.spiffs_start=0x200000 +esp210.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +esp210.menu.eesz.4M2M.build.spiffs_blocksize=8192 +esp210.menu.eesz.4M3M=4M (3M SPIFFS) +esp210.menu.eesz.4M3M.build.flash_size=4M +esp210.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +esp210.menu.eesz.4M3M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M3M.upload.maximum_size=1044464 +esp210.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M3M.build.spiffs_start=0x100000 +esp210.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +esp210.menu.eesz.4M3M.build.spiffs_blocksize=8192 +esp210.menu.ip.lm2f=v2 Lower Memory +esp210.menu.ip.lm2f.build.lwip_include=lwip2/include +esp210.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +esp210.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp210.menu.ip.hb2f=v2 Higher Bandwidth +esp210.menu.ip.hb2f.build.lwip_include=lwip2/include +esp210.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +esp210.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp210.menu.ip.lm2n=v2 Lower Memory (no features) +esp210.menu.ip.lm2n.build.lwip_include=lwip2/include +esp210.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +esp210.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp210.menu.ip.hb2n=v2 Higher Bandwidth (no features) +esp210.menu.ip.hb2n.build.lwip_include=lwip2/include +esp210.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +esp210.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp210.menu.ip.lm6f=v2 IPv6 Lower Memory +esp210.menu.ip.lm6f.build.lwip_include=lwip2/include +esp210.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +esp210.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp210.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +esp210.menu.ip.hb6f.build.lwip_include=lwip2/include +esp210.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +esp210.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp210.menu.ip.hb1=v1.4 Higher Bandwidth +esp210.menu.ip.hb1.build.lwip_lib=-llwip_gcc +esp210.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +esp210.menu.ip.src=v1.4 Compile from source +esp210.menu.ip.src.build.lwip_lib=-llwip_src +esp210.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +esp210.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +esp210.menu.dbg.Disabled=Disabled +esp210.menu.dbg.Disabled.build.debug_port= +esp210.menu.dbg.Serial=Serial +esp210.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +esp210.menu.dbg.Serial1=Serial1 +esp210.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +esp210.menu.lvl.None____=None +esp210.menu.lvl.None____.build.debug_level= +esp210.menu.lvl.SSL=SSL +esp210.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +esp210.menu.lvl.TLS_MEM=TLS_MEM +esp210.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +esp210.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +esp210.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.HTTP_SERVER=HTTP_SERVER +esp210.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +esp210.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +esp210.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +esp210.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +esp210.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +esp210.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.CORE=CORE +esp210.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +esp210.menu.lvl.WIFI=WIFI +esp210.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +esp210.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +esp210.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +esp210.menu.lvl.UPDATER=UPDATER +esp210.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +esp210.menu.lvl.OTA=OTA +esp210.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +esp210.menu.lvl.OOM=OOM +esp210.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +esp210.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +esp210.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +esp210.menu.wipe.none=Only Sketch +esp210.menu.wipe.none.upload.erase_cmd= +esp210.menu.wipe.sdk=Sketch + WiFi Settings +esp210.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +esp210.menu.wipe.all=All Flash Contents +esp210.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +esp210.menu.baud.57600=57600 +esp210.menu.baud.57600.upload.speed=57600 +esp210.menu.baud.9600=9600 +esp210.menu.baud.9600.upload.speed=9600 +esp210.menu.baud.115200=115200 +esp210.menu.baud.115200.upload.speed=115200 +esp210.menu.baud.230400.linux=230400 +esp210.menu.baud.230400.macosx=230400 +esp210.menu.baud.230400.upload.speed=230400 +esp210.menu.baud.256000.windows=256000 +esp210.menu.baud.256000.upload.speed=256000 +esp210.menu.baud.460800.linux=460800 +esp210.menu.baud.460800.macosx=460800 +esp210.menu.baud.460800.upload.speed=460800 +esp210.menu.baud.512000.windows=512000 +esp210.menu.baud.512000.upload.speed=512000 +esp210.menu.baud.921600=921600 +esp210.menu.baud.921600.upload.speed=921600 + +############################################################## +d1_mini.name=LOLIN(WEMOS) D1 R2 & mini +d1_mini.build.board=ESP8266_WEMOS_D1MINI +d1_mini.build.variant=d1_mini +d1_mini.upload.tool=esptool +d1_mini.upload.maximum_data_size=81920 +d1_mini.upload.wait_for_upload_port=true +d1_mini.upload.erase_cmd= +d1_mini.serial.disableDTR=true +d1_mini.serial.disableRTS=true +d1_mini.build.mcu=esp8266 +d1_mini.build.core=esp8266 +d1_mini.build.spiffs_pagesize=256 +d1_mini.build.debug_port= +d1_mini.build.debug_level= +d1_mini.menu.xtal.80=80 MHz +d1_mini.menu.xtal.80.build.f_cpu=80000000L +d1_mini.menu.xtal.160=160 MHz +d1_mini.menu.xtal.160.build.f_cpu=160000000L +d1_mini.menu.vt.flash=Flash +d1_mini.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1_mini.menu.vt.heap=Heap +d1_mini.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1_mini.menu.vt.iram=IRAM +d1_mini.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1_mini.menu.exception.disabled=Disabled +d1_mini.menu.exception.disabled.build.exception_flags=-fno-exceptions +d1_mini.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1_mini.menu.exception.enabled=Enabled +d1_mini.menu.exception.enabled.build.exception_flags=-fexceptions +d1_mini.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1_mini.upload.resetmethod=nodemcu +d1_mini.build.flash_mode=dio +d1_mini.build.flash_flags=-DFLASHMODE_DIO +d1_mini.build.flash_freq=40 +d1_mini.menu.eesz.4M=4M (no SPIFFS) +d1_mini.menu.eesz.4M.build.flash_size=4M +d1_mini.menu.eesz.4M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +d1_mini.menu.eesz.4M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M1M=4M (1M SPIFFS) +d1_mini.menu.eesz.4M1M.build.flash_size=4M +d1_mini.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +d1_mini.menu.eesz.4M1M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M1M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M1M.build.spiffs_start=0x300000 +d1_mini.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +d1_mini.menu.eesz.4M1M.build.spiffs_blocksize=8192 +d1_mini.menu.eesz.4M2M=4M (2M SPIFFS) +d1_mini.menu.eesz.4M2M.build.flash_size=4M +d1_mini.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +d1_mini.menu.eesz.4M2M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M2M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M2M.build.spiffs_start=0x200000 +d1_mini.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +d1_mini.menu.eesz.4M2M.build.spiffs_blocksize=8192 +d1_mini.menu.eesz.4M3M=4M (3M SPIFFS) +d1_mini.menu.eesz.4M3M.build.flash_size=4M +d1_mini.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +d1_mini.menu.eesz.4M3M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M3M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M3M.build.spiffs_start=0x100000 +d1_mini.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +d1_mini.menu.eesz.4M3M.build.spiffs_blocksize=8192 +d1_mini.menu.ip.lm2f=v2 Lower Memory +d1_mini.menu.ip.lm2f.build.lwip_include=lwip2/include +d1_mini.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1_mini.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini.menu.ip.hb2f=v2 Higher Bandwidth +d1_mini.menu.ip.hb2f.build.lwip_include=lwip2/include +d1_mini.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1_mini.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini.menu.ip.lm2n=v2 Lower Memory (no features) +d1_mini.menu.ip.lm2n.build.lwip_include=lwip2/include +d1_mini.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1_mini.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1_mini.menu.ip.hb2n.build.lwip_include=lwip2/include +d1_mini.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1_mini.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini.menu.ip.lm6f=v2 IPv6 Lower Memory +d1_mini.menu.ip.lm6f.build.lwip_include=lwip2/include +d1_mini.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1_mini.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1_mini.menu.ip.hb6f.build.lwip_include=lwip2/include +d1_mini.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1_mini.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini.menu.ip.hb1=v1.4 Higher Bandwidth +d1_mini.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1_mini.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini.menu.ip.src=v1.4 Compile from source +d1_mini.menu.ip.src.build.lwip_lib=-llwip_src +d1_mini.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1_mini.menu.dbg.Disabled=Disabled +d1_mini.menu.dbg.Disabled.build.debug_port= +d1_mini.menu.dbg.Serial=Serial +d1_mini.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1_mini.menu.dbg.Serial1=Serial1 +d1_mini.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1_mini.menu.lvl.None____=None +d1_mini.menu.lvl.None____.build.debug_level= +d1_mini.menu.lvl.SSL=SSL +d1_mini.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1_mini.menu.lvl.TLS_MEM=TLS_MEM +d1_mini.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1_mini.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1_mini.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1_mini.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1_mini.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1_mini.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1_mini.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1_mini.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.CORE=CORE +d1_mini.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1_mini.menu.lvl.WIFI=WIFI +d1_mini.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1_mini.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1_mini.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1_mini.menu.lvl.UPDATER=UPDATER +d1_mini.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1_mini.menu.lvl.OTA=OTA +d1_mini.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1_mini.menu.lvl.OOM=OOM +d1_mini.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1_mini.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1_mini.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1_mini.menu.wipe.none=Only Sketch +d1_mini.menu.wipe.none.upload.erase_cmd= +d1_mini.menu.wipe.sdk=Sketch + WiFi Settings +d1_mini.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +d1_mini.menu.wipe.all=All Flash Contents +d1_mini.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +d1_mini.menu.baud.921600=921600 +d1_mini.menu.baud.921600.upload.speed=921600 +d1_mini.menu.baud.9600=9600 +d1_mini.menu.baud.9600.upload.speed=9600 +d1_mini.menu.baud.57600=57600 +d1_mini.menu.baud.57600.upload.speed=57600 +d1_mini.menu.baud.115200=115200 +d1_mini.menu.baud.115200.upload.speed=115200 +d1_mini.menu.baud.230400.linux=230400 +d1_mini.menu.baud.230400.macosx=230400 +d1_mini.menu.baud.230400.upload.speed=230400 +d1_mini.menu.baud.256000.windows=256000 +d1_mini.menu.baud.256000.upload.speed=256000 +d1_mini.menu.baud.460800.linux=460800 +d1_mini.menu.baud.460800.macosx=460800 +d1_mini.menu.baud.460800.upload.speed=460800 +d1_mini.menu.baud.512000.windows=512000 +d1_mini.menu.baud.512000.upload.speed=512000 + +############################################################## +d1_mini_pro.name=LOLIN(WEMOS) D1 mini Pro +d1_mini_pro.build.board=ESP8266_WEMOS_D1MINIPRO +d1_mini_pro.build.variant=d1_mini +d1_mini_pro.upload.tool=esptool +d1_mini_pro.upload.maximum_data_size=81920 +d1_mini_pro.upload.wait_for_upload_port=true +d1_mini_pro.upload.erase_cmd= +d1_mini_pro.serial.disableDTR=true +d1_mini_pro.serial.disableRTS=true +d1_mini_pro.build.mcu=esp8266 +d1_mini_pro.build.core=esp8266 +d1_mini_pro.build.spiffs_pagesize=256 +d1_mini_pro.build.debug_port= +d1_mini_pro.build.debug_level= +d1_mini_pro.menu.xtal.80=80 MHz +d1_mini_pro.menu.xtal.80.build.f_cpu=80000000L +d1_mini_pro.menu.xtal.160=160 MHz +d1_mini_pro.menu.xtal.160.build.f_cpu=160000000L +d1_mini_pro.menu.vt.flash=Flash +d1_mini_pro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1_mini_pro.menu.vt.heap=Heap +d1_mini_pro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1_mini_pro.menu.vt.iram=IRAM +d1_mini_pro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1_mini_pro.menu.exception.disabled=Disabled +d1_mini_pro.menu.exception.disabled.build.exception_flags=-fno-exceptions +d1_mini_pro.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1_mini_pro.menu.exception.enabled=Enabled +d1_mini_pro.menu.exception.enabled.build.exception_flags=-fexceptions +d1_mini_pro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1_mini_pro.upload.resetmethod=nodemcu +d1_mini_pro.build.flash_mode=dio +d1_mini_pro.build.flash_flags=-DFLASHMODE_DIO +d1_mini_pro.build.flash_freq=40 +d1_mini_pro.menu.eesz.16M14M=16M (14M SPIFFS) +d1_mini_pro.menu.eesz.16M14M.build.flash_size=16M +d1_mini_pro.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 +d1_mini_pro.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld +d1_mini_pro.menu.eesz.16M14M.build.spiffs_pagesize=256 +d1_mini_pro.menu.eesz.16M14M.upload.maximum_size=1044464 +d1_mini_pro.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 +d1_mini_pro.menu.eesz.16M14M.build.spiffs_start=0x200000 +d1_mini_pro.menu.eesz.16M14M.build.spiffs_end=0xFFB000 +d1_mini_pro.menu.eesz.16M14M.build.spiffs_blocksize=8192 +d1_mini_pro.menu.eesz.16M15M=16M (15M SPIFFS) +d1_mini_pro.menu.eesz.16M15M.build.flash_size=16M +d1_mini_pro.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 +d1_mini_pro.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld +d1_mini_pro.menu.eesz.16M15M.build.spiffs_pagesize=256 +d1_mini_pro.menu.eesz.16M15M.upload.maximum_size=1044464 +d1_mini_pro.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 +d1_mini_pro.menu.eesz.16M15M.build.spiffs_start=0x100000 +d1_mini_pro.menu.eesz.16M15M.build.spiffs_end=0xFFB000 +d1_mini_pro.menu.eesz.16M15M.build.spiffs_blocksize=8192 +d1_mini_pro.menu.ip.lm2f=v2 Lower Memory +d1_mini_pro.menu.ip.lm2f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1_mini_pro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.hb2f=v2 Higher Bandwidth +d1_mini_pro.menu.ip.hb2f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1_mini_pro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.lm2n=v2 Lower Memory (no features) +d1_mini_pro.menu.ip.lm2n.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1_mini_pro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1_mini_pro.menu.ip.hb2n.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1_mini_pro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.lm6f=v2 IPv6 Lower Memory +d1_mini_pro.menu.ip.lm6f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1_mini_pro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_pro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1_mini_pro.menu.ip.hb6f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1_mini_pro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_pro.menu.ip.hb1=v1.4 Higher Bandwidth +d1_mini_pro.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1_mini_pro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_pro.menu.ip.src=v1.4 Compile from source +d1_mini_pro.menu.ip.src.build.lwip_lib=-llwip_src +d1_mini_pro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_pro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1_mini_pro.menu.dbg.Disabled=Disabled +d1_mini_pro.menu.dbg.Disabled.build.debug_port= +d1_mini_pro.menu.dbg.Serial=Serial +d1_mini_pro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1_mini_pro.menu.dbg.Serial1=Serial1 +d1_mini_pro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1_mini_pro.menu.lvl.None____=None +d1_mini_pro.menu.lvl.None____.build.debug_level= +d1_mini_pro.menu.lvl.SSL=SSL +d1_mini_pro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1_mini_pro.menu.lvl.TLS_MEM=TLS_MEM +d1_mini_pro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1_mini_pro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1_mini_pro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1_mini_pro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1_mini_pro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1_mini_pro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.CORE=CORE +d1_mini_pro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1_mini_pro.menu.lvl.WIFI=WIFI +d1_mini_pro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1_mini_pro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1_mini_pro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1_mini_pro.menu.lvl.UPDATER=UPDATER +d1_mini_pro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1_mini_pro.menu.lvl.OTA=OTA +d1_mini_pro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1_mini_pro.menu.lvl.OOM=OOM +d1_mini_pro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1_mini_pro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1_mini_pro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1_mini_pro.menu.wipe.none=Only Sketch +d1_mini_pro.menu.wipe.none.upload.erase_cmd= +d1_mini_pro.menu.wipe.sdk=Sketch + WiFi Settings +d1_mini_pro.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +d1_mini_pro.menu.wipe.all=All Flash Contents +d1_mini_pro.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +d1_mini_pro.menu.baud.921600=921600 +d1_mini_pro.menu.baud.921600.upload.speed=921600 +d1_mini_pro.menu.baud.9600=9600 +d1_mini_pro.menu.baud.9600.upload.speed=9600 +d1_mini_pro.menu.baud.57600=57600 +d1_mini_pro.menu.baud.57600.upload.speed=57600 +d1_mini_pro.menu.baud.115200=115200 +d1_mini_pro.menu.baud.115200.upload.speed=115200 +d1_mini_pro.menu.baud.230400.linux=230400 +d1_mini_pro.menu.baud.230400.macosx=230400 +d1_mini_pro.menu.baud.230400.upload.speed=230400 +d1_mini_pro.menu.baud.256000.windows=256000 +d1_mini_pro.menu.baud.256000.upload.speed=256000 +d1_mini_pro.menu.baud.460800.linux=460800 +d1_mini_pro.menu.baud.460800.macosx=460800 +d1_mini_pro.menu.baud.460800.upload.speed=460800 +d1_mini_pro.menu.baud.512000.windows=512000 +d1_mini_pro.menu.baud.512000.upload.speed=512000 + +############################################################## +d1_mini_lite.name=LOLIN(WEMOS) D1 mini Lite +d1_mini_lite.build.board=ESP8266_WEMOS_D1MINILITE +d1_mini_lite.build.variant=d1_mini +d1_mini_lite.upload.tool=esptool +d1_mini_lite.upload.maximum_data_size=81920 +d1_mini_lite.upload.wait_for_upload_port=true +d1_mini_lite.upload.erase_cmd= +d1_mini_lite.serial.disableDTR=true +d1_mini_lite.serial.disableRTS=true +d1_mini_lite.build.mcu=esp8266 +d1_mini_lite.build.core=esp8266 +d1_mini_lite.build.spiffs_pagesize=256 +d1_mini_lite.build.debug_port= +d1_mini_lite.build.debug_level= +d1_mini_lite.menu.xtal.80=80 MHz +d1_mini_lite.menu.xtal.80.build.f_cpu=80000000L +d1_mini_lite.menu.xtal.160=160 MHz +d1_mini_lite.menu.xtal.160.build.f_cpu=160000000L +d1_mini_lite.menu.vt.flash=Flash +d1_mini_lite.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1_mini_lite.menu.vt.heap=Heap +d1_mini_lite.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1_mini_lite.menu.vt.iram=IRAM +d1_mini_lite.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1_mini_lite.menu.exception.disabled=Disabled +d1_mini_lite.menu.exception.disabled.build.exception_flags=-fno-exceptions +d1_mini_lite.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1_mini_lite.menu.exception.enabled=Enabled +d1_mini_lite.menu.exception.enabled.build.exception_flags=-fexceptions +d1_mini_lite.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1_mini_lite.upload.resetmethod=nodemcu +d1_mini_lite.build.flash_mode=dout +d1_mini_lite.build.flash_flags=-DFLASHMODE_DOUT +d1_mini_lite.build.flash_freq=40 +d1_mini_lite.menu.eesz.1M=1M (no SPIFFS) +d1_mini_lite.menu.eesz.1M.build.flash_size=1M +d1_mini_lite.menu.eesz.1M.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +d1_mini_lite.menu.eesz.1M.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M.upload.maximum_size=1023984 +d1_mini_lite.menu.eesz.1M.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M64=1M (64K SPIFFS) +d1_mini_lite.menu.eesz.1M64.build.flash_size=1M +d1_mini_lite.menu.eesz.1M64.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +d1_mini_lite.menu.eesz.1M64.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M64.upload.maximum_size=958448 +d1_mini_lite.menu.eesz.1M64.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M64.build.spiffs_start=0xEB000 +d1_mini_lite.menu.eesz.1M64.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M64.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M128=1M (128K SPIFFS) +d1_mini_lite.menu.eesz.1M128.build.flash_size=1M +d1_mini_lite.menu.eesz.1M128.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +d1_mini_lite.menu.eesz.1M128.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M128.upload.maximum_size=892912 +d1_mini_lite.menu.eesz.1M128.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M128.build.spiffs_start=0xDB000 +d1_mini_lite.menu.eesz.1M128.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M128.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M144=1M (144K SPIFFS) +d1_mini_lite.menu.eesz.1M144.build.flash_size=1M +d1_mini_lite.menu.eesz.1M144.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +d1_mini_lite.menu.eesz.1M144.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M144.upload.maximum_size=876528 +d1_mini_lite.menu.eesz.1M144.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M144.build.spiffs_start=0xD7000 +d1_mini_lite.menu.eesz.1M144.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M144.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M160=1M (160K SPIFFS) +d1_mini_lite.menu.eesz.1M160.build.flash_size=1M +d1_mini_lite.menu.eesz.1M160.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +d1_mini_lite.menu.eesz.1M160.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M160.upload.maximum_size=860144 +d1_mini_lite.menu.eesz.1M160.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M160.build.spiffs_start=0xD3000 +d1_mini_lite.menu.eesz.1M160.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M160.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M192=1M (192K SPIFFS) +d1_mini_lite.menu.eesz.1M192.build.flash_size=1M +d1_mini_lite.menu.eesz.1M192.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +d1_mini_lite.menu.eesz.1M192.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M192.upload.maximum_size=827376 +d1_mini_lite.menu.eesz.1M192.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M192.build.spiffs_start=0xCB000 +d1_mini_lite.menu.eesz.1M192.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M192.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M256=1M (256K SPIFFS) +d1_mini_lite.menu.eesz.1M256.build.flash_size=1M +d1_mini_lite.menu.eesz.1M256.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +d1_mini_lite.menu.eesz.1M256.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M256.upload.maximum_size=761840 +d1_mini_lite.menu.eesz.1M256.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M256.build.spiffs_start=0xBB000 +d1_mini_lite.menu.eesz.1M256.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M256.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M512=1M (512K SPIFFS) +d1_mini_lite.menu.eesz.1M512.build.flash_size=1M +d1_mini_lite.menu.eesz.1M512.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +d1_mini_lite.menu.eesz.1M512.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M512.upload.maximum_size=499696 +d1_mini_lite.menu.eesz.1M512.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M512.build.spiffs_start=0x7B000 +d1_mini_lite.menu.eesz.1M512.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M512.build.spiffs_blocksize=4096 +d1_mini_lite.menu.ip.lm2f=v2 Lower Memory +d1_mini_lite.menu.ip.lm2f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1_mini_lite.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.hb2f=v2 Higher Bandwidth +d1_mini_lite.menu.ip.hb2f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1_mini_lite.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.lm2n=v2 Lower Memory (no features) +d1_mini_lite.menu.ip.lm2n.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1_mini_lite.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1_mini_lite.menu.ip.hb2n.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1_mini_lite.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.lm6f=v2 IPv6 Lower Memory +d1_mini_lite.menu.ip.lm6f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1_mini_lite.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_lite.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1_mini_lite.menu.ip.hb6f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1_mini_lite.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_lite.menu.ip.hb1=v1.4 Higher Bandwidth +d1_mini_lite.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1_mini_lite.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_lite.menu.ip.src=v1.4 Compile from source +d1_mini_lite.menu.ip.src.build.lwip_lib=-llwip_src +d1_mini_lite.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_lite.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1_mini_lite.menu.dbg.Disabled=Disabled +d1_mini_lite.menu.dbg.Disabled.build.debug_port= +d1_mini_lite.menu.dbg.Serial=Serial +d1_mini_lite.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1_mini_lite.menu.dbg.Serial1=Serial1 +d1_mini_lite.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1_mini_lite.menu.lvl.None____=None +d1_mini_lite.menu.lvl.None____.build.debug_level= +d1_mini_lite.menu.lvl.SSL=SSL +d1_mini_lite.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1_mini_lite.menu.lvl.TLS_MEM=TLS_MEM +d1_mini_lite.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1_mini_lite.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1_mini_lite.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1_mini_lite.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1_mini_lite.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1_mini_lite.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.CORE=CORE +d1_mini_lite.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1_mini_lite.menu.lvl.WIFI=WIFI +d1_mini_lite.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1_mini_lite.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1_mini_lite.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1_mini_lite.menu.lvl.UPDATER=UPDATER +d1_mini_lite.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1_mini_lite.menu.lvl.OTA=OTA +d1_mini_lite.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1_mini_lite.menu.lvl.OOM=OOM +d1_mini_lite.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1_mini_lite.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1_mini_lite.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1_mini_lite.menu.wipe.none=Only Sketch +d1_mini_lite.menu.wipe.none.upload.erase_cmd= +d1_mini_lite.menu.wipe.sdk=Sketch + WiFi Settings +d1_mini_lite.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +d1_mini_lite.menu.wipe.all=All Flash Contents +d1_mini_lite.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +d1_mini_lite.menu.baud.921600=921600 +d1_mini_lite.menu.baud.921600.upload.speed=921600 +d1_mini_lite.menu.baud.9600=9600 +d1_mini_lite.menu.baud.9600.upload.speed=9600 +d1_mini_lite.menu.baud.57600=57600 +d1_mini_lite.menu.baud.57600.upload.speed=57600 +d1_mini_lite.menu.baud.115200=115200 +d1_mini_lite.menu.baud.115200.upload.speed=115200 +d1_mini_lite.menu.baud.230400.linux=230400 +d1_mini_lite.menu.baud.230400.macosx=230400 +d1_mini_lite.menu.baud.230400.upload.speed=230400 +d1_mini_lite.menu.baud.256000.windows=256000 +d1_mini_lite.menu.baud.256000.upload.speed=256000 +d1_mini_lite.menu.baud.460800.linux=460800 +d1_mini_lite.menu.baud.460800.macosx=460800 +d1_mini_lite.menu.baud.460800.upload.speed=460800 +d1_mini_lite.menu.baud.512000.windows=512000 +d1_mini_lite.menu.baud.512000.upload.speed=512000 + +############################################################## +d1.name=WeMos D1 R1 +d1.build.board=ESP8266_WEMOS_D1R1 +d1.build.variant=d1 +d1.upload.tool=esptool +d1.upload.maximum_data_size=81920 +d1.upload.wait_for_upload_port=true +d1.upload.erase_cmd= +d1.serial.disableDTR=true +d1.serial.disableRTS=true +d1.build.mcu=esp8266 +d1.build.core=esp8266 +d1.build.spiffs_pagesize=256 +d1.build.debug_port= +d1.build.debug_level= +d1.menu.xtal.80=80 MHz +d1.menu.xtal.80.build.f_cpu=80000000L +d1.menu.xtal.160=160 MHz +d1.menu.xtal.160.build.f_cpu=160000000L +d1.menu.vt.flash=Flash +d1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1.menu.vt.heap=Heap +d1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1.menu.vt.iram=IRAM +d1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1.menu.exception.disabled=Disabled +d1.menu.exception.disabled.build.exception_flags=-fno-exceptions +d1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1.menu.exception.enabled=Enabled +d1.menu.exception.enabled.build.exception_flags=-fexceptions +d1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1.upload.resetmethod=nodemcu +d1.build.flash_mode=dio +d1.build.flash_flags=-DFLASHMODE_DIO +d1.build.flash_freq=40 +d1.menu.eesz.4M=4M (no SPIFFS) +d1.menu.eesz.4M.build.flash_size=4M +d1.menu.eesz.4M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +d1.menu.eesz.4M.build.spiffs_pagesize=256 +d1.menu.eesz.4M.upload.maximum_size=1044464 +d1.menu.eesz.4M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M1M=4M (1M SPIFFS) +d1.menu.eesz.4M1M.build.flash_size=4M +d1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +d1.menu.eesz.4M1M.build.spiffs_pagesize=256 +d1.menu.eesz.4M1M.upload.maximum_size=1044464 +d1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M1M.build.spiffs_start=0x300000 +d1.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +d1.menu.eesz.4M1M.build.spiffs_blocksize=8192 +d1.menu.eesz.4M2M=4M (2M SPIFFS) +d1.menu.eesz.4M2M.build.flash_size=4M +d1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +d1.menu.eesz.4M2M.build.spiffs_pagesize=256 +d1.menu.eesz.4M2M.upload.maximum_size=1044464 +d1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M2M.build.spiffs_start=0x200000 +d1.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +d1.menu.eesz.4M2M.build.spiffs_blocksize=8192 +d1.menu.eesz.4M3M=4M (3M SPIFFS) +d1.menu.eesz.4M3M.build.flash_size=4M +d1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +d1.menu.eesz.4M3M.build.spiffs_pagesize=256 +d1.menu.eesz.4M3M.upload.maximum_size=1044464 +d1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M3M.build.spiffs_start=0x100000 +d1.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +d1.menu.eesz.4M3M.build.spiffs_blocksize=8192 +d1.menu.ip.lm2f=v2 Lower Memory +d1.menu.ip.lm2f.build.lwip_include=lwip2/include +d1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1.menu.ip.hb2f=v2 Higher Bandwidth +d1.menu.ip.hb2f.build.lwip_include=lwip2/include +d1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1.menu.ip.lm2n=v2 Lower Memory (no features) +d1.menu.ip.lm2n.build.lwip_include=lwip2/include +d1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1.menu.ip.hb2n.build.lwip_include=lwip2/include +d1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1.menu.ip.lm6f=v2 IPv6 Lower Memory +d1.menu.ip.lm6f.build.lwip_include=lwip2/include +d1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1.menu.ip.hb6f.build.lwip_include=lwip2/include +d1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1.menu.ip.hb1=v1.4 Higher Bandwidth +d1.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1.menu.ip.src=v1.4 Compile from source +d1.menu.ip.src.build.lwip_lib=-llwip_src +d1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1.menu.dbg.Disabled=Disabled +d1.menu.dbg.Disabled.build.debug_port= +d1.menu.dbg.Serial=Serial +d1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1.menu.dbg.Serial1=Serial1 +d1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1.menu.lvl.None____=None +d1.menu.lvl.None____.build.debug_level= +d1.menu.lvl.SSL=SSL +d1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1.menu.lvl.TLS_MEM=TLS_MEM +d1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.CORE=CORE +d1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1.menu.lvl.WIFI=WIFI +d1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1.menu.lvl.UPDATER=UPDATER +d1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1.menu.lvl.OTA=OTA +d1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1.menu.lvl.OOM=OOM +d1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1.menu.wipe.none=Only Sketch +d1.menu.wipe.none.upload.erase_cmd= +d1.menu.wipe.sdk=Sketch + WiFi Settings +d1.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +d1.menu.wipe.all=All Flash Contents +d1.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +d1.menu.baud.921600=921600 +d1.menu.baud.921600.upload.speed=921600 +d1.menu.baud.9600=9600 +d1.menu.baud.9600.upload.speed=9600 +d1.menu.baud.57600=57600 +d1.menu.baud.57600.upload.speed=57600 +d1.menu.baud.115200=115200 +d1.menu.baud.115200.upload.speed=115200 +d1.menu.baud.230400.linux=230400 +d1.menu.baud.230400.macosx=230400 +d1.menu.baud.230400.upload.speed=230400 +d1.menu.baud.256000.windows=256000 +d1.menu.baud.256000.upload.speed=256000 +d1.menu.baud.460800.linux=460800 +d1.menu.baud.460800.macosx=460800 +d1.menu.baud.460800.upload.speed=460800 +d1.menu.baud.512000.windows=512000 +d1.menu.baud.512000.upload.speed=512000 + +############################################################## +espino.name=ESPino (ESP-12 Module) +espino.build.board=ESP8266_ESP12 +espino.build.variant=espino +espino.upload.tool=esptool +espino.upload.maximum_data_size=81920 +espino.upload.wait_for_upload_port=true +espino.upload.erase_cmd= +espino.serial.disableDTR=true +espino.serial.disableRTS=true +espino.build.mcu=esp8266 +espino.build.core=esp8266 +espino.build.spiffs_pagesize=256 +espino.build.debug_port= +espino.build.debug_level= +espino.menu.xtal.80=80 MHz +espino.menu.xtal.80.build.f_cpu=80000000L +espino.menu.xtal.160=160 MHz +espino.menu.xtal.160.build.f_cpu=160000000L +espino.menu.vt.flash=Flash +espino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espino.menu.vt.heap=Heap +espino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espino.menu.vt.iram=IRAM +espino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espino.menu.exception.disabled=Disabled +espino.menu.exception.disabled.build.exception_flags=-fno-exceptions +espino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espino.menu.exception.enabled=Enabled +espino.menu.exception.enabled.build.exception_flags=-fexceptions +espino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espino.menu.ResetMethod.ck=ck +espino.menu.ResetMethod.ck.upload.resetmethod=ck +espino.menu.ResetMethod.nodemcu=nodemcu +espino.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +espino.build.flash_mode=qio +espino.build.flash_flags=-DFLASHMODE_QIO +espino.build.flash_freq=40 +espino.menu.eesz.4M=4M (no SPIFFS) +espino.menu.eesz.4M.build.flash_size=4M +espino.menu.eesz.4M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espino.menu.eesz.4M.build.spiffs_pagesize=256 +espino.menu.eesz.4M.upload.maximum_size=1044464 +espino.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M1M=4M (1M SPIFFS) +espino.menu.eesz.4M1M.build.flash_size=4M +espino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espino.menu.eesz.4M1M.build.spiffs_pagesize=256 +espino.menu.eesz.4M1M.upload.maximum_size=1044464 +espino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M1M.build.spiffs_start=0x300000 +espino.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +espino.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espino.menu.eesz.4M2M=4M (2M SPIFFS) +espino.menu.eesz.4M2M.build.flash_size=4M +espino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espino.menu.eesz.4M2M.build.spiffs_pagesize=256 +espino.menu.eesz.4M2M.upload.maximum_size=1044464 +espino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M2M.build.spiffs_start=0x200000 +espino.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +espino.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espino.menu.eesz.4M3M=4M (3M SPIFFS) +espino.menu.eesz.4M3M.build.flash_size=4M +espino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espino.menu.eesz.4M3M.build.spiffs_pagesize=256 +espino.menu.eesz.4M3M.upload.maximum_size=1044464 +espino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M3M.build.spiffs_start=0x100000 +espino.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +espino.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espino.menu.ip.lm2f=v2 Lower Memory +espino.menu.ip.lm2f.build.lwip_include=lwip2/include +espino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espino.menu.ip.hb2f=v2 Higher Bandwidth +espino.menu.ip.hb2f.build.lwip_include=lwip2/include +espino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espino.menu.ip.lm2n=v2 Lower Memory (no features) +espino.menu.ip.lm2n.build.lwip_include=lwip2/include +espino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espino.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espino.menu.ip.hb2n.build.lwip_include=lwip2/include +espino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espino.menu.ip.lm6f=v2 IPv6 Lower Memory +espino.menu.ip.lm6f.build.lwip_include=lwip2/include +espino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espino.menu.ip.hb6f.build.lwip_include=lwip2/include +espino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espino.menu.ip.hb1=v1.4 Higher Bandwidth +espino.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espino.menu.ip.src=v1.4 Compile from source +espino.menu.ip.src.build.lwip_lib=-llwip_src +espino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espino.menu.dbg.Disabled=Disabled +espino.menu.dbg.Disabled.build.debug_port= +espino.menu.dbg.Serial=Serial +espino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espino.menu.dbg.Serial1=Serial1 +espino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espino.menu.lvl.None____=None +espino.menu.lvl.None____.build.debug_level= +espino.menu.lvl.SSL=SSL +espino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espino.menu.lvl.TLS_MEM=TLS_MEM +espino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.HTTP_SERVER=HTTP_SERVER +espino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.CORE=CORE +espino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espino.menu.lvl.WIFI=WIFI +espino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espino.menu.lvl.UPDATER=UPDATER +espino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espino.menu.lvl.OTA=OTA +espino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espino.menu.lvl.OOM=OOM +espino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espino.menu.wipe.none=Only Sketch +espino.menu.wipe.none.upload.erase_cmd= +espino.menu.wipe.sdk=Sketch + WiFi Settings +espino.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +espino.menu.wipe.all=All Flash Contents +espino.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +espino.menu.baud.115200=115200 +espino.menu.baud.115200.upload.speed=115200 +espino.menu.baud.9600=9600 +espino.menu.baud.9600.upload.speed=9600 +espino.menu.baud.57600=57600 +espino.menu.baud.57600.upload.speed=57600 +espino.menu.baud.230400.linux=230400 +espino.menu.baud.230400.macosx=230400 +espino.menu.baud.230400.upload.speed=230400 +espino.menu.baud.256000.windows=256000 +espino.menu.baud.256000.upload.speed=256000 +espino.menu.baud.460800.linux=460800 +espino.menu.baud.460800.macosx=460800 +espino.menu.baud.460800.upload.speed=460800 +espino.menu.baud.512000.windows=512000 +espino.menu.baud.512000.upload.speed=512000 +espino.menu.baud.921600=921600 +espino.menu.baud.921600.upload.speed=921600 + +############################################################## +espinotee.name=ThaiEasyElec's ESPino +espinotee.build.board=ESP8266_ESP13 +espinotee.build.variant=espinotee +espinotee.upload.tool=esptool +espinotee.upload.maximum_data_size=81920 +espinotee.upload.wait_for_upload_port=true +espinotee.upload.erase_cmd= +espinotee.serial.disableDTR=true +espinotee.serial.disableRTS=true +espinotee.build.mcu=esp8266 +espinotee.build.core=esp8266 +espinotee.build.spiffs_pagesize=256 +espinotee.build.debug_port= +espinotee.build.debug_level= +espinotee.menu.xtal.80=80 MHz +espinotee.menu.xtal.80.build.f_cpu=80000000L +espinotee.menu.xtal.160=160 MHz +espinotee.menu.xtal.160.build.f_cpu=160000000L +espinotee.menu.vt.flash=Flash +espinotee.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espinotee.menu.vt.heap=Heap +espinotee.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espinotee.menu.vt.iram=IRAM +espinotee.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espinotee.menu.exception.disabled=Disabled +espinotee.menu.exception.disabled.build.exception_flags=-fno-exceptions +espinotee.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espinotee.menu.exception.enabled=Enabled +espinotee.menu.exception.enabled.build.exception_flags=-fexceptions +espinotee.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espinotee.upload.resetmethod=nodemcu +espinotee.build.flash_mode=qio +espinotee.build.flash_flags=-DFLASHMODE_QIO +espinotee.build.flash_freq=40 +espinotee.menu.eesz.4M=4M (no SPIFFS) +espinotee.menu.eesz.4M.build.flash_size=4M +espinotee.menu.eesz.4M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espinotee.menu.eesz.4M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M1M=4M (1M SPIFFS) +espinotee.menu.eesz.4M1M.build.flash_size=4M +espinotee.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espinotee.menu.eesz.4M1M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M1M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M1M.build.spiffs_start=0x300000 +espinotee.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +espinotee.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espinotee.menu.eesz.4M2M=4M (2M SPIFFS) +espinotee.menu.eesz.4M2M.build.flash_size=4M +espinotee.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espinotee.menu.eesz.4M2M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M2M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M2M.build.spiffs_start=0x200000 +espinotee.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +espinotee.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espinotee.menu.eesz.4M3M=4M (3M SPIFFS) +espinotee.menu.eesz.4M3M.build.flash_size=4M +espinotee.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espinotee.menu.eesz.4M3M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M3M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M3M.build.spiffs_start=0x100000 +espinotee.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +espinotee.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espinotee.menu.ip.lm2f=v2 Lower Memory +espinotee.menu.ip.lm2f.build.lwip_include=lwip2/include +espinotee.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espinotee.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espinotee.menu.ip.hb2f=v2 Higher Bandwidth +espinotee.menu.ip.hb2f.build.lwip_include=lwip2/include +espinotee.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espinotee.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espinotee.menu.ip.lm2n=v2 Lower Memory (no features) +espinotee.menu.ip.lm2n.build.lwip_include=lwip2/include +espinotee.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espinotee.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espinotee.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espinotee.menu.ip.hb2n.build.lwip_include=lwip2/include +espinotee.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espinotee.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espinotee.menu.ip.lm6f=v2 IPv6 Lower Memory +espinotee.menu.ip.lm6f.build.lwip_include=lwip2/include +espinotee.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espinotee.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espinotee.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espinotee.menu.ip.hb6f.build.lwip_include=lwip2/include +espinotee.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espinotee.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espinotee.menu.ip.hb1=v1.4 Higher Bandwidth +espinotee.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espinotee.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espinotee.menu.ip.src=v1.4 Compile from source +espinotee.menu.ip.src.build.lwip_lib=-llwip_src +espinotee.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espinotee.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espinotee.menu.dbg.Disabled=Disabled +espinotee.menu.dbg.Disabled.build.debug_port= +espinotee.menu.dbg.Serial=Serial +espinotee.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espinotee.menu.dbg.Serial1=Serial1 +espinotee.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espinotee.menu.lvl.None____=None +espinotee.menu.lvl.None____.build.debug_level= +espinotee.menu.lvl.SSL=SSL +espinotee.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espinotee.menu.lvl.TLS_MEM=TLS_MEM +espinotee.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espinotee.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espinotee.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.HTTP_SERVER=HTTP_SERVER +espinotee.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espinotee.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espinotee.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espinotee.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espinotee.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espinotee.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.CORE=CORE +espinotee.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espinotee.menu.lvl.WIFI=WIFI +espinotee.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espinotee.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espinotee.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espinotee.menu.lvl.UPDATER=UPDATER +espinotee.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espinotee.menu.lvl.OTA=OTA +espinotee.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espinotee.menu.lvl.OOM=OOM +espinotee.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espinotee.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espinotee.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espinotee.menu.wipe.none=Only Sketch +espinotee.menu.wipe.none.upload.erase_cmd= +espinotee.menu.wipe.sdk=Sketch + WiFi Settings +espinotee.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +espinotee.menu.wipe.all=All Flash Contents +espinotee.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +espinotee.menu.baud.115200=115200 +espinotee.menu.baud.115200.upload.speed=115200 +espinotee.menu.baud.9600=9600 +espinotee.menu.baud.9600.upload.speed=9600 +espinotee.menu.baud.57600=57600 +espinotee.menu.baud.57600.upload.speed=57600 +espinotee.menu.baud.230400.linux=230400 +espinotee.menu.baud.230400.macosx=230400 +espinotee.menu.baud.230400.upload.speed=230400 +espinotee.menu.baud.256000.windows=256000 +espinotee.menu.baud.256000.upload.speed=256000 +espinotee.menu.baud.460800.linux=460800 +espinotee.menu.baud.460800.macosx=460800 +espinotee.menu.baud.460800.upload.speed=460800 +espinotee.menu.baud.512000.windows=512000 +espinotee.menu.baud.512000.upload.speed=512000 +espinotee.menu.baud.921600=921600 +espinotee.menu.baud.921600.upload.speed=921600 + +############################################################## +wifinfo.name=WifInfo +wifinfo.menu.ESPModule.ESP12.build.board=ESP8266_ESP12 +wifinfo.menu.ESPModule.ESP12.upload.maximum_size=1044464 +wifinfo.menu.ESPModule.ESP12.build.spiffs_pagesize=256 +wifinfo.menu.ESPModule.ESP12.build.flash_ld=eagle.flash.4m1m.ld +wifinfo.menu.ESPModule.ESP07192.build.spiffs_blocksize=4096 +wifinfo.menu.ESPModule.ESP07192.build.spiffs_end=0xFB000 +wifinfo.menu.ESPModule.ESP12=ESP12 (4M/1M SPIFFS) +wifinfo.menu.ESPModule.ESP12.build.spiffs_start=0x300000 +wifinfo.menu.ESPModule.ESP12.build.spiffs_end=0x3FB000 +wifinfo.menu.ESPModule.ESP07192.build.spiffs_start=0xCB000 +wifinfo.menu.ESPModule.ESP07192.build.board=ESP8266_ESP07 +wifinfo.menu.ESPModule.ESP12.build.spiffs_blocksize=8192 +wifinfo.menu.ESPModule.ESP12.build.flash_size=4M +wifinfo.build.board=WIFINFO +wifinfo.build.variant=wifinfo +wifinfo.menu.ESPModule.ESP07192.build.flash_ld=eagle.flash.1m192.ld +wifinfo.menu.ESPModule.ESP07192.build.flash_size=1M +wifinfo.menu.ESPModule.ESP07192=ESP07 (1M/192K SPIFFS) +wifinfo.menu.ESPModule.ESP07192.upload.maximum_size=827376 +wifinfo.upload.tool=esptool +wifinfo.upload.maximum_data_size=81920 +wifinfo.upload.wait_for_upload_port=true +wifinfo.upload.erase_cmd= +wifinfo.serial.disableDTR=true +wifinfo.serial.disableRTS=true +wifinfo.build.mcu=esp8266 +wifinfo.build.core=esp8266 +wifinfo.build.spiffs_pagesize=256 +wifinfo.build.debug_port= +wifinfo.build.debug_level= +wifinfo.menu.xtal.80=80 MHz +wifinfo.menu.xtal.80.build.f_cpu=80000000L +wifinfo.menu.xtal.160=160 MHz +wifinfo.menu.xtal.160.build.f_cpu=160000000L +wifinfo.menu.vt.flash=Flash +wifinfo.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wifinfo.menu.vt.heap=Heap +wifinfo.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wifinfo.menu.vt.iram=IRAM +wifinfo.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wifinfo.menu.exception.disabled=Disabled +wifinfo.menu.exception.disabled.build.exception_flags=-fno-exceptions +wifinfo.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wifinfo.menu.exception.enabled=Enabled +wifinfo.menu.exception.enabled.build.exception_flags=-fexceptions +wifinfo.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wifinfo.upload.resetmethod=nodemcu +wifinfo.build.flash_mode=qio +wifinfo.build.flash_flags=-DFLASHMODE_QIO +wifinfo.menu.FlashFreq.40=40MHz +wifinfo.menu.FlashFreq.40.build.flash_freq=40 +wifinfo.menu.FlashFreq.80=80MHz +wifinfo.menu.FlashFreq.80.build.flash_freq=80 +wifinfo.menu.eesz.1M=1M (no SPIFFS) +wifinfo.menu.eesz.1M.build.flash_size=1M +wifinfo.menu.eesz.1M.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +wifinfo.menu.eesz.1M.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M.upload.maximum_size=1023984 +wifinfo.menu.eesz.1M.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M64=1M (64K SPIFFS) +wifinfo.menu.eesz.1M64.build.flash_size=1M +wifinfo.menu.eesz.1M64.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +wifinfo.menu.eesz.1M64.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M64.upload.maximum_size=958448 +wifinfo.menu.eesz.1M64.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M64.build.spiffs_start=0xEB000 +wifinfo.menu.eesz.1M64.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M64.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M128=1M (128K SPIFFS) +wifinfo.menu.eesz.1M128.build.flash_size=1M +wifinfo.menu.eesz.1M128.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +wifinfo.menu.eesz.1M128.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M128.upload.maximum_size=892912 +wifinfo.menu.eesz.1M128.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M128.build.spiffs_start=0xDB000 +wifinfo.menu.eesz.1M128.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M128.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M144=1M (144K SPIFFS) +wifinfo.menu.eesz.1M144.build.flash_size=1M +wifinfo.menu.eesz.1M144.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +wifinfo.menu.eesz.1M144.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M144.upload.maximum_size=876528 +wifinfo.menu.eesz.1M144.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M144.build.spiffs_start=0xD7000 +wifinfo.menu.eesz.1M144.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M144.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M160=1M (160K SPIFFS) +wifinfo.menu.eesz.1M160.build.flash_size=1M +wifinfo.menu.eesz.1M160.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +wifinfo.menu.eesz.1M160.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M160.upload.maximum_size=860144 +wifinfo.menu.eesz.1M160.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M160.build.spiffs_start=0xD3000 +wifinfo.menu.eesz.1M160.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M160.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M192=1M (192K SPIFFS) +wifinfo.menu.eesz.1M192.build.flash_size=1M +wifinfo.menu.eesz.1M192.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +wifinfo.menu.eesz.1M192.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M192.upload.maximum_size=827376 +wifinfo.menu.eesz.1M192.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M192.build.spiffs_start=0xCB000 +wifinfo.menu.eesz.1M192.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M192.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M256=1M (256K SPIFFS) +wifinfo.menu.eesz.1M256.build.flash_size=1M +wifinfo.menu.eesz.1M256.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +wifinfo.menu.eesz.1M256.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M256.upload.maximum_size=761840 +wifinfo.menu.eesz.1M256.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M256.build.spiffs_start=0xBB000 +wifinfo.menu.eesz.1M256.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M256.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M512=1M (512K SPIFFS) +wifinfo.menu.eesz.1M512.build.flash_size=1M +wifinfo.menu.eesz.1M512.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +wifinfo.menu.eesz.1M512.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M512.upload.maximum_size=499696 +wifinfo.menu.eesz.1M512.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M512.build.spiffs_start=0x7B000 +wifinfo.menu.eesz.1M512.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M512.build.spiffs_blocksize=4096 +wifinfo.menu.ip.lm2f=v2 Lower Memory +wifinfo.menu.ip.lm2f.build.lwip_include=lwip2/include +wifinfo.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wifinfo.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifinfo.menu.ip.hb2f=v2 Higher Bandwidth +wifinfo.menu.ip.hb2f.build.lwip_include=lwip2/include +wifinfo.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wifinfo.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifinfo.menu.ip.lm2n=v2 Lower Memory (no features) +wifinfo.menu.ip.lm2n.build.lwip_include=lwip2/include +wifinfo.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wifinfo.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifinfo.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wifinfo.menu.ip.hb2n.build.lwip_include=lwip2/include +wifinfo.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wifinfo.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifinfo.menu.ip.lm6f=v2 IPv6 Lower Memory +wifinfo.menu.ip.lm6f.build.lwip_include=lwip2/include +wifinfo.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wifinfo.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifinfo.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wifinfo.menu.ip.hb6f.build.lwip_include=lwip2/include +wifinfo.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wifinfo.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifinfo.menu.ip.hb1=v1.4 Higher Bandwidth +wifinfo.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wifinfo.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wifinfo.menu.ip.src=v1.4 Compile from source +wifinfo.menu.ip.src.build.lwip_lib=-llwip_src +wifinfo.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wifinfo.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wifinfo.menu.dbg.Disabled=Disabled +wifinfo.menu.dbg.Disabled.build.debug_port= +wifinfo.menu.dbg.Serial=Serial +wifinfo.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wifinfo.menu.dbg.Serial1=Serial1 +wifinfo.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wifinfo.menu.lvl.None____=None +wifinfo.menu.lvl.None____.build.debug_level= +wifinfo.menu.lvl.SSL=SSL +wifinfo.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wifinfo.menu.lvl.TLS_MEM=TLS_MEM +wifinfo.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wifinfo.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wifinfo.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.HTTP_SERVER=HTTP_SERVER +wifinfo.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wifinfo.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wifinfo.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wifinfo.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wifinfo.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.CORE=CORE +wifinfo.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wifinfo.menu.lvl.WIFI=WIFI +wifinfo.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wifinfo.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wifinfo.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wifinfo.menu.lvl.UPDATER=UPDATER +wifinfo.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wifinfo.menu.lvl.OTA=OTA +wifinfo.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wifinfo.menu.lvl.OOM=OOM +wifinfo.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wifinfo.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wifinfo.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wifinfo.menu.wipe.none=Only Sketch +wifinfo.menu.wipe.none.upload.erase_cmd= +wifinfo.menu.wipe.sdk=Sketch + WiFi Settings +wifinfo.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +wifinfo.menu.wipe.all=All Flash Contents +wifinfo.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +wifinfo.menu.baud.115200=115200 +wifinfo.menu.baud.115200.upload.speed=115200 +wifinfo.menu.baud.9600=9600 +wifinfo.menu.baud.9600.upload.speed=9600 +wifinfo.menu.baud.57600=57600 +wifinfo.menu.baud.57600.upload.speed=57600 +wifinfo.menu.baud.230400.linux=230400 +wifinfo.menu.baud.230400.macosx=230400 +wifinfo.menu.baud.230400.upload.speed=230400 +wifinfo.menu.baud.256000.windows=256000 +wifinfo.menu.baud.256000.upload.speed=256000 +wifinfo.menu.baud.460800.linux=460800 +wifinfo.menu.baud.460800.macosx=460800 +wifinfo.menu.baud.460800.upload.speed=460800 +wifinfo.menu.baud.512000.windows=512000 +wifinfo.menu.baud.512000.upload.speed=512000 +wifinfo.menu.baud.921600=921600 +wifinfo.menu.baud.921600.upload.speed=921600 + +############################################################## +arduino-esp8266.name=Arduino +arduino-esp8266.menu.BoardModel.starottodeved.build.board=ESP8266_ARDUINO_STAR_OTTO +arduino-esp8266.menu.BoardModel.primo.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +arduino-esp8266.menu.BoardModel.starottodeved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +arduino-esp8266.menu.BoardModel.starottodeved.build.variant=arduino_uart +arduino-esp8266.menu.BoardModel.unowifideved.build.board=ESP8266_ARDUINO_UNOWIFI +arduino-esp8266.menu.BoardModel.unowifideved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +arduino-esp8266.menu.BoardModel.primo=Primo +arduino-esp8266.menu.BoardModel.unowifideved.build.variant=arduino_uart +arduino-esp8266.menu.BoardModel.primo.build.variant=arduino_spi +arduino-esp8266.menu.BoardModel.starottodeved=Star OTTO +arduino-esp8266.build.board=ESP8266_ARDUINO +arduino-esp8266.menu.BoardModel.primo.build.board=ESP8266_ARDUINO_PRIMO +arduino-esp8266.menu.BoardModel.unowifideved=Uno WiFi +arduino-esp8266.upload.tool=esptool +arduino-esp8266.upload.maximum_data_size=81920 +arduino-esp8266.upload.wait_for_upload_port=true +arduino-esp8266.upload.erase_cmd= +arduino-esp8266.serial.disableDTR=true +arduino-esp8266.serial.disableRTS=true +arduino-esp8266.build.mcu=esp8266 +arduino-esp8266.build.core=esp8266 +arduino-esp8266.build.variant=generic +arduino-esp8266.build.spiffs_pagesize=256 +arduino-esp8266.build.debug_port= +arduino-esp8266.build.debug_level= +arduino-esp8266.menu.xtal.80=80 MHz +arduino-esp8266.menu.xtal.80.build.f_cpu=80000000L +arduino-esp8266.menu.xtal.160=160 MHz +arduino-esp8266.menu.xtal.160.build.f_cpu=160000000L +arduino-esp8266.menu.vt.flash=Flash +arduino-esp8266.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +arduino-esp8266.menu.vt.heap=Heap +arduino-esp8266.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +arduino-esp8266.menu.vt.iram=IRAM +arduino-esp8266.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +arduino-esp8266.menu.exception.disabled=Disabled +arduino-esp8266.menu.exception.disabled.build.exception_flags=-fno-exceptions +arduino-esp8266.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +arduino-esp8266.menu.exception.enabled=Enabled +arduino-esp8266.menu.exception.enabled.build.exception_flags=-fexceptions +arduino-esp8266.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +arduino-esp8266.upload.resetmethod=ck +arduino-esp8266.build.flash_mode=qio +arduino-esp8266.build.flash_flags=-DFLASHMODE_QIO +arduino-esp8266.build.flash_freq=40 +arduino-esp8266.menu.eesz.4M=4M (no SPIFFS) +arduino-esp8266.menu.eesz.4M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +arduino-esp8266.menu.eesz.4M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M1M=4M (1M SPIFFS) +arduino-esp8266.menu.eesz.4M1M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +arduino-esp8266.menu.eesz.4M1M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M1M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M1M.build.spiffs_start=0x300000 +arduino-esp8266.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +arduino-esp8266.menu.eesz.4M1M.build.spiffs_blocksize=8192 +arduino-esp8266.menu.eesz.4M2M=4M (2M SPIFFS) +arduino-esp8266.menu.eesz.4M2M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +arduino-esp8266.menu.eesz.4M2M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M2M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M2M.build.spiffs_start=0x200000 +arduino-esp8266.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +arduino-esp8266.menu.eesz.4M2M.build.spiffs_blocksize=8192 +arduino-esp8266.menu.eesz.4M3M=4M (3M SPIFFS) +arduino-esp8266.menu.eesz.4M3M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +arduino-esp8266.menu.eesz.4M3M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M3M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M3M.build.spiffs_start=0x100000 +arduino-esp8266.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +arduino-esp8266.menu.eesz.4M3M.build.spiffs_blocksize=8192 +arduino-esp8266.menu.ip.lm2f=v2 Lower Memory +arduino-esp8266.menu.ip.lm2f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +arduino-esp8266.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.hb2f=v2 Higher Bandwidth +arduino-esp8266.menu.ip.hb2f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +arduino-esp8266.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.lm2n=v2 Lower Memory (no features) +arduino-esp8266.menu.ip.lm2n.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +arduino-esp8266.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.hb2n=v2 Higher Bandwidth (no features) +arduino-esp8266.menu.ip.hb2n.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +arduino-esp8266.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.lm6f=v2 IPv6 Lower Memory +arduino-esp8266.menu.ip.lm6f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +arduino-esp8266.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +arduino-esp8266.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +arduino-esp8266.menu.ip.hb6f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +arduino-esp8266.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +arduino-esp8266.menu.ip.hb1=v1.4 Higher Bandwidth +arduino-esp8266.menu.ip.hb1.build.lwip_lib=-llwip_gcc +arduino-esp8266.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +arduino-esp8266.menu.ip.src=v1.4 Compile from source +arduino-esp8266.menu.ip.src.build.lwip_lib=-llwip_src +arduino-esp8266.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +arduino-esp8266.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +arduino-esp8266.menu.dbg.Disabled=Disabled +arduino-esp8266.menu.dbg.Disabled.build.debug_port= +arduino-esp8266.menu.dbg.Serial=Serial +arduino-esp8266.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +arduino-esp8266.menu.dbg.Serial1=Serial1 +arduino-esp8266.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +arduino-esp8266.menu.lvl.None____=None +arduino-esp8266.menu.lvl.None____.build.debug_level= +arduino-esp8266.menu.lvl.SSL=SSL +arduino-esp8266.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +arduino-esp8266.menu.lvl.TLS_MEM=TLS_MEM +arduino-esp8266.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +arduino-esp8266.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +arduino-esp8266.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.HTTP_SERVER=HTTP_SERVER +arduino-esp8266.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +arduino-esp8266.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +arduino-esp8266.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.CORE=CORE +arduino-esp8266.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +arduino-esp8266.menu.lvl.WIFI=WIFI +arduino-esp8266.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +arduino-esp8266.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +arduino-esp8266.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +arduino-esp8266.menu.lvl.UPDATER=UPDATER +arduino-esp8266.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +arduino-esp8266.menu.lvl.OTA=OTA +arduino-esp8266.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +arduino-esp8266.menu.lvl.OOM=OOM +arduino-esp8266.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +arduino-esp8266.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +arduino-esp8266.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +arduino-esp8266.menu.wipe.none=Only Sketch +arduino-esp8266.menu.wipe.none.upload.erase_cmd= +arduino-esp8266.menu.wipe.sdk=Sketch + WiFi Settings +arduino-esp8266.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +arduino-esp8266.menu.wipe.all=All Flash Contents +arduino-esp8266.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +arduino-esp8266.menu.baud.115200=115200 +arduino-esp8266.menu.baud.115200.upload.speed=115200 +arduino-esp8266.menu.baud.9600=9600 +arduino-esp8266.menu.baud.9600.upload.speed=9600 +arduino-esp8266.menu.baud.57600=57600 +arduino-esp8266.menu.baud.57600.upload.speed=57600 +arduino-esp8266.menu.baud.230400.linux=230400 +arduino-esp8266.menu.baud.230400.macosx=230400 +arduino-esp8266.menu.baud.230400.upload.speed=230400 +arduino-esp8266.menu.baud.256000.windows=256000 +arduino-esp8266.menu.baud.256000.upload.speed=256000 +arduino-esp8266.menu.baud.460800.linux=460800 +arduino-esp8266.menu.baud.460800.macosx=460800 +arduino-esp8266.menu.baud.460800.upload.speed=460800 +arduino-esp8266.menu.baud.512000.windows=512000 +arduino-esp8266.menu.baud.512000.upload.speed=512000 +arduino-esp8266.menu.baud.921600=921600 +arduino-esp8266.menu.baud.921600.upload.speed=921600 + +############################################################## +gen4iod.name=4D Systems gen4 IoD Range +gen4iod.build.board=GEN4_IOD +gen4iod.build.f_cpu=160000000L +gen4iod.build.variant=generic +gen4iod.upload.tool=esptool +gen4iod.upload.maximum_data_size=81920 +gen4iod.upload.wait_for_upload_port=true +gen4iod.upload.erase_cmd= +gen4iod.serial.disableDTR=true +gen4iod.serial.disableRTS=true +gen4iod.build.mcu=esp8266 +gen4iod.build.core=esp8266 +gen4iod.build.spiffs_pagesize=256 +gen4iod.build.debug_port= +gen4iod.build.debug_level= +gen4iod.menu.xtal.80=80 MHz +gen4iod.menu.xtal.80.build.f_cpu=80000000L +gen4iod.menu.xtal.160=160 MHz +gen4iod.menu.xtal.160.build.f_cpu=160000000L +gen4iod.menu.vt.flash=Flash +gen4iod.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +gen4iod.menu.vt.heap=Heap +gen4iod.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +gen4iod.menu.vt.iram=IRAM +gen4iod.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +gen4iod.menu.exception.disabled=Disabled +gen4iod.menu.exception.disabled.build.exception_flags=-fno-exceptions +gen4iod.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +gen4iod.menu.exception.enabled=Enabled +gen4iod.menu.exception.enabled.build.exception_flags=-fexceptions +gen4iod.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +gen4iod.upload.resetmethod=nodemcu +gen4iod.build.flash_mode=dio +gen4iod.build.flash_flags=-DFLASHMODE_DIO +gen4iod.build.flash_freq=80 +gen4iod.menu.eesz.512K=512K (no SPIFFS) +gen4iod.menu.eesz.512K.build.flash_size=512K +gen4iod.menu.eesz.512K.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +gen4iod.menu.eesz.512K.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K.upload.maximum_size=499696 +gen4iod.menu.eesz.512K.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K32=512K (32K SPIFFS) +gen4iod.menu.eesz.512K32.build.flash_size=512K +gen4iod.menu.eesz.512K32.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +gen4iod.menu.eesz.512K32.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K32.upload.maximum_size=466928 +gen4iod.menu.eesz.512K32.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K32.build.spiffs_start=0x73000 +gen4iod.menu.eesz.512K32.build.spiffs_end=0x7B000 +gen4iod.menu.eesz.512K32.build.spiffs_blocksize=4096 +gen4iod.menu.eesz.512K64=512K (64K SPIFFS) +gen4iod.menu.eesz.512K64.build.flash_size=512K +gen4iod.menu.eesz.512K64.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +gen4iod.menu.eesz.512K64.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K64.upload.maximum_size=434160 +gen4iod.menu.eesz.512K64.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K64.build.spiffs_start=0x6B000 +gen4iod.menu.eesz.512K64.build.spiffs_end=0x7B000 +gen4iod.menu.eesz.512K64.build.spiffs_blocksize=4096 +gen4iod.menu.eesz.512K128=512K (128K SPIFFS) +gen4iod.menu.eesz.512K128.build.flash_size=512K +gen4iod.menu.eesz.512K128.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +gen4iod.menu.eesz.512K128.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K128.upload.maximum_size=368624 +gen4iod.menu.eesz.512K128.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K128.build.spiffs_start=0x5B000 +gen4iod.menu.eesz.512K128.build.spiffs_end=0x7B000 +gen4iod.menu.eesz.512K128.build.spiffs_blocksize=4096 +gen4iod.menu.ip.lm2f=v2 Lower Memory +gen4iod.menu.ip.lm2f.build.lwip_include=lwip2/include +gen4iod.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +gen4iod.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +gen4iod.menu.ip.hb2f=v2 Higher Bandwidth +gen4iod.menu.ip.hb2f.build.lwip_include=lwip2/include +gen4iod.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +gen4iod.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +gen4iod.menu.ip.lm2n=v2 Lower Memory (no features) +gen4iod.menu.ip.lm2n.build.lwip_include=lwip2/include +gen4iod.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +gen4iod.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +gen4iod.menu.ip.hb2n=v2 Higher Bandwidth (no features) +gen4iod.menu.ip.hb2n.build.lwip_include=lwip2/include +gen4iod.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +gen4iod.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +gen4iod.menu.ip.lm6f=v2 IPv6 Lower Memory +gen4iod.menu.ip.lm6f.build.lwip_include=lwip2/include +gen4iod.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +gen4iod.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +gen4iod.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +gen4iod.menu.ip.hb6f.build.lwip_include=lwip2/include +gen4iod.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +gen4iod.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +gen4iod.menu.ip.hb1=v1.4 Higher Bandwidth +gen4iod.menu.ip.hb1.build.lwip_lib=-llwip_gcc +gen4iod.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +gen4iod.menu.ip.src=v1.4 Compile from source +gen4iod.menu.ip.src.build.lwip_lib=-llwip_src +gen4iod.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +gen4iod.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +gen4iod.menu.dbg.Disabled=Disabled +gen4iod.menu.dbg.Disabled.build.debug_port= +gen4iod.menu.dbg.Serial=Serial +gen4iod.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +gen4iod.menu.dbg.Serial1=Serial1 +gen4iod.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +gen4iod.menu.lvl.None____=None +gen4iod.menu.lvl.None____.build.debug_level= +gen4iod.menu.lvl.SSL=SSL +gen4iod.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +gen4iod.menu.lvl.TLS_MEM=TLS_MEM +gen4iod.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +gen4iod.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +gen4iod.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.HTTP_SERVER=HTTP_SERVER +gen4iod.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +gen4iod.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +gen4iod.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +gen4iod.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +gen4iod.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.CORE=CORE +gen4iod.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +gen4iod.menu.lvl.WIFI=WIFI +gen4iod.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +gen4iod.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +gen4iod.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +gen4iod.menu.lvl.UPDATER=UPDATER +gen4iod.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +gen4iod.menu.lvl.OTA=OTA +gen4iod.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +gen4iod.menu.lvl.OOM=OOM +gen4iod.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +gen4iod.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +gen4iod.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +gen4iod.menu.wipe.none=Only Sketch +gen4iod.menu.wipe.none.upload.erase_cmd= +gen4iod.menu.wipe.sdk=Sketch + WiFi Settings +gen4iod.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +gen4iod.menu.wipe.all=All Flash Contents +gen4iod.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +gen4iod.menu.baud.115200=115200 +gen4iod.menu.baud.115200.upload.speed=115200 +gen4iod.menu.baud.9600=9600 +gen4iod.menu.baud.9600.upload.speed=9600 +gen4iod.menu.baud.57600=57600 +gen4iod.menu.baud.57600.upload.speed=57600 +gen4iod.menu.baud.230400.linux=230400 +gen4iod.menu.baud.230400.macosx=230400 +gen4iod.menu.baud.230400.upload.speed=230400 +gen4iod.menu.baud.256000.windows=256000 +gen4iod.menu.baud.256000.upload.speed=256000 +gen4iod.menu.baud.460800.linux=460800 +gen4iod.menu.baud.460800.macosx=460800 +gen4iod.menu.baud.460800.upload.speed=460800 +gen4iod.menu.baud.512000.windows=512000 +gen4iod.menu.baud.512000.upload.speed=512000 +gen4iod.menu.baud.921600=921600 +gen4iod.menu.baud.921600.upload.speed=921600 + +############################################################## +oak.name=Digistump Oak +oak.build.board=ESP8266_OAK +oak.build.variant=oak +oak.upload.maximum_size=1040368 +oak.upload.tool=esptool +oak.upload.maximum_data_size=81920 +oak.upload.wait_for_upload_port=true +oak.upload.erase_cmd= +oak.serial.disableDTR=true +oak.serial.disableRTS=true +oak.build.mcu=esp8266 +oak.build.core=esp8266 +oak.build.spiffs_pagesize=256 +oak.build.debug_port= +oak.build.debug_level= +oak.menu.xtal.80=80 MHz +oak.menu.xtal.80.build.f_cpu=80000000L +oak.menu.xtal.160=160 MHz +oak.menu.xtal.160.build.f_cpu=160000000L +oak.menu.vt.flash=Flash +oak.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +oak.menu.vt.heap=Heap +oak.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +oak.menu.vt.iram=IRAM +oak.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +oak.menu.exception.disabled=Disabled +oak.menu.exception.disabled.build.exception_flags=-fno-exceptions +oak.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +oak.menu.exception.enabled=Enabled +oak.menu.exception.enabled.build.exception_flags=-fexceptions +oak.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +oak.upload.resetmethod=none +oak.build.flash_mode=dio +oak.build.flash_flags=-DFLASHMODE_DIO +oak.build.flash_freq=40 +oak.menu.eesz.4M=4M (no SPIFFS) +oak.menu.eesz.4M.build.flash_size=4M +oak.menu.eesz.4M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +oak.menu.eesz.4M.build.spiffs_pagesize=256 +oak.menu.eesz.4M.upload.maximum_size=1044464 +oak.menu.eesz.4M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M1M=4M (1M SPIFFS) +oak.menu.eesz.4M1M.build.flash_size=4M +oak.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +oak.menu.eesz.4M1M.build.spiffs_pagesize=256 +oak.menu.eesz.4M1M.upload.maximum_size=1044464 +oak.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M1M.build.spiffs_start=0x300000 +oak.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +oak.menu.eesz.4M1M.build.spiffs_blocksize=8192 +oak.menu.eesz.4M2M=4M (2M SPIFFS) +oak.menu.eesz.4M2M.build.flash_size=4M +oak.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +oak.menu.eesz.4M2M.build.spiffs_pagesize=256 +oak.menu.eesz.4M2M.upload.maximum_size=1044464 +oak.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M2M.build.spiffs_start=0x200000 +oak.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +oak.menu.eesz.4M2M.build.spiffs_blocksize=8192 +oak.menu.eesz.4M3M=4M (3M SPIFFS) +oak.menu.eesz.4M3M.build.flash_size=4M +oak.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +oak.menu.eesz.4M3M.build.spiffs_pagesize=256 +oak.menu.eesz.4M3M.upload.maximum_size=1044464 +oak.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M3M.build.spiffs_start=0x100000 +oak.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +oak.menu.eesz.4M3M.build.spiffs_blocksize=8192 +oak.menu.ip.lm2f=v2 Lower Memory +oak.menu.ip.lm2f.build.lwip_include=lwip2/include +oak.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +oak.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +oak.menu.ip.hb2f=v2 Higher Bandwidth +oak.menu.ip.hb2f.build.lwip_include=lwip2/include +oak.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +oak.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +oak.menu.ip.lm2n=v2 Lower Memory (no features) +oak.menu.ip.lm2n.build.lwip_include=lwip2/include +oak.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +oak.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +oak.menu.ip.hb2n=v2 Higher Bandwidth (no features) +oak.menu.ip.hb2n.build.lwip_include=lwip2/include +oak.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +oak.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +oak.menu.ip.lm6f=v2 IPv6 Lower Memory +oak.menu.ip.lm6f.build.lwip_include=lwip2/include +oak.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +oak.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +oak.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +oak.menu.ip.hb6f.build.lwip_include=lwip2/include +oak.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +oak.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +oak.menu.ip.hb1=v1.4 Higher Bandwidth +oak.menu.ip.hb1.build.lwip_lib=-llwip_gcc +oak.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +oak.menu.ip.src=v1.4 Compile from source +oak.menu.ip.src.build.lwip_lib=-llwip_src +oak.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +oak.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +oak.menu.dbg.Disabled=Disabled +oak.menu.dbg.Disabled.build.debug_port= +oak.menu.dbg.Serial=Serial +oak.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +oak.menu.dbg.Serial1=Serial1 +oak.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +oak.menu.lvl.None____=None +oak.menu.lvl.None____.build.debug_level= +oak.menu.lvl.SSL=SSL +oak.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +oak.menu.lvl.TLS_MEM=TLS_MEM +oak.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +oak.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +oak.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.HTTP_SERVER=HTTP_SERVER +oak.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +oak.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +oak.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +oak.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +oak.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +oak.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.CORE=CORE +oak.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +oak.menu.lvl.WIFI=WIFI +oak.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +oak.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +oak.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +oak.menu.lvl.UPDATER=UPDATER +oak.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +oak.menu.lvl.OTA=OTA +oak.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +oak.menu.lvl.OOM=OOM +oak.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +oak.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +oak.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +oak.menu.wipe.none=Only Sketch +oak.menu.wipe.none.upload.erase_cmd= +oak.menu.wipe.sdk=Sketch + WiFi Settings +oak.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +oak.menu.wipe.all=All Flash Contents +oak.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +oak.menu.baud.921600=921600 +oak.menu.baud.921600.upload.speed=921600 +oak.menu.baud.9600=9600 +oak.menu.baud.9600.upload.speed=9600 +oak.menu.baud.57600=57600 +oak.menu.baud.57600.upload.speed=57600 +oak.menu.baud.115200=115200 +oak.menu.baud.115200.upload.speed=115200 +oak.menu.baud.230400.linux=230400 +oak.menu.baud.230400.macosx=230400 +oak.menu.baud.230400.upload.speed=230400 +oak.menu.baud.256000.windows=256000 +oak.menu.baud.256000.upload.speed=256000 +oak.menu.baud.460800.linux=460800 +oak.menu.baud.460800.macosx=460800 +oak.menu.baud.460800.upload.speed=460800 +oak.menu.baud.512000.windows=512000 +oak.menu.baud.512000.upload.speed=512000 + +############################################################## +wifiduino.name=WiFiduino +wifiduino.build.board=WIFIDUINO_ESP8266 +wifiduino.build.variant=wifiduino +wifiduino.upload.tool=esptool +wifiduino.upload.maximum_data_size=81920 +wifiduino.upload.wait_for_upload_port=true +wifiduino.upload.erase_cmd= +wifiduino.serial.disableDTR=true +wifiduino.serial.disableRTS=true +wifiduino.build.mcu=esp8266 +wifiduino.build.core=esp8266 +wifiduino.build.spiffs_pagesize=256 +wifiduino.build.debug_port= +wifiduino.build.debug_level= +wifiduino.menu.xtal.80=80 MHz +wifiduino.menu.xtal.80.build.f_cpu=80000000L +wifiduino.menu.xtal.160=160 MHz +wifiduino.menu.xtal.160.build.f_cpu=160000000L +wifiduino.menu.vt.flash=Flash +wifiduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wifiduino.menu.vt.heap=Heap +wifiduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wifiduino.menu.vt.iram=IRAM +wifiduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wifiduino.menu.exception.disabled=Disabled +wifiduino.menu.exception.disabled.build.exception_flags=-fno-exceptions +wifiduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wifiduino.menu.exception.enabled=Enabled +wifiduino.menu.exception.enabled.build.exception_flags=-fexceptions +wifiduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wifiduino.upload.resetmethod=nodemcu +wifiduino.build.flash_mode=dio +wifiduino.build.flash_flags=-DFLASHMODE_DIO +wifiduino.build.flash_freq=40 +wifiduino.menu.eesz.4M=4M (no SPIFFS) +wifiduino.menu.eesz.4M.build.flash_size=4M +wifiduino.menu.eesz.4M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +wifiduino.menu.eesz.4M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M1M=4M (1M SPIFFS) +wifiduino.menu.eesz.4M1M.build.flash_size=4M +wifiduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +wifiduino.menu.eesz.4M1M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M1M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M1M.build.spiffs_start=0x300000 +wifiduino.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +wifiduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 +wifiduino.menu.eesz.4M2M=4M (2M SPIFFS) +wifiduino.menu.eesz.4M2M.build.flash_size=4M +wifiduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +wifiduino.menu.eesz.4M2M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M2M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M2M.build.spiffs_start=0x200000 +wifiduino.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +wifiduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 +wifiduino.menu.eesz.4M3M=4M (3M SPIFFS) +wifiduino.menu.eesz.4M3M.build.flash_size=4M +wifiduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +wifiduino.menu.eesz.4M3M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M3M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M3M.build.spiffs_start=0x100000 +wifiduino.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +wifiduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 +wifiduino.menu.ip.lm2f=v2 Lower Memory +wifiduino.menu.ip.lm2f.build.lwip_include=lwip2/include +wifiduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wifiduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifiduino.menu.ip.hb2f=v2 Higher Bandwidth +wifiduino.menu.ip.hb2f.build.lwip_include=lwip2/include +wifiduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wifiduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifiduino.menu.ip.lm2n=v2 Lower Memory (no features) +wifiduino.menu.ip.lm2n.build.lwip_include=lwip2/include +wifiduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wifiduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifiduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wifiduino.menu.ip.hb2n.build.lwip_include=lwip2/include +wifiduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wifiduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifiduino.menu.ip.lm6f=v2 IPv6 Lower Memory +wifiduino.menu.ip.lm6f.build.lwip_include=lwip2/include +wifiduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wifiduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifiduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wifiduino.menu.ip.hb6f.build.lwip_include=lwip2/include +wifiduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wifiduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifiduino.menu.ip.hb1=v1.4 Higher Bandwidth +wifiduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wifiduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wifiduino.menu.ip.src=v1.4 Compile from source +wifiduino.menu.ip.src.build.lwip_lib=-llwip_src +wifiduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wifiduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wifiduino.menu.dbg.Disabled=Disabled +wifiduino.menu.dbg.Disabled.build.debug_port= +wifiduino.menu.dbg.Serial=Serial +wifiduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wifiduino.menu.dbg.Serial1=Serial1 +wifiduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wifiduino.menu.lvl.None____=None +wifiduino.menu.lvl.None____.build.debug_level= +wifiduino.menu.lvl.SSL=SSL +wifiduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wifiduino.menu.lvl.TLS_MEM=TLS_MEM +wifiduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wifiduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wifiduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.HTTP_SERVER=HTTP_SERVER +wifiduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wifiduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wifiduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wifiduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wifiduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.CORE=CORE +wifiduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wifiduino.menu.lvl.WIFI=WIFI +wifiduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wifiduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wifiduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wifiduino.menu.lvl.UPDATER=UPDATER +wifiduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wifiduino.menu.lvl.OTA=OTA +wifiduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wifiduino.menu.lvl.OOM=OOM +wifiduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wifiduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wifiduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wifiduino.menu.wipe.none=Only Sketch +wifiduino.menu.wipe.none.upload.erase_cmd= +wifiduino.menu.wipe.sdk=Sketch + WiFi Settings +wifiduino.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +wifiduino.menu.wipe.all=All Flash Contents +wifiduino.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +wifiduino.menu.baud.921600=921600 +wifiduino.menu.baud.921600.upload.speed=921600 +wifiduino.menu.baud.9600=9600 +wifiduino.menu.baud.9600.upload.speed=9600 +wifiduino.menu.baud.57600=57600 +wifiduino.menu.baud.57600.upload.speed=57600 +wifiduino.menu.baud.115200=115200 +wifiduino.menu.baud.115200.upload.speed=115200 +wifiduino.menu.baud.230400.linux=230400 +wifiduino.menu.baud.230400.macosx=230400 +wifiduino.menu.baud.230400.upload.speed=230400 +wifiduino.menu.baud.256000.windows=256000 +wifiduino.menu.baud.256000.upload.speed=256000 +wifiduino.menu.baud.460800.linux=460800 +wifiduino.menu.baud.460800.macosx=460800 +wifiduino.menu.baud.460800.upload.speed=460800 +wifiduino.menu.baud.512000.windows=512000 +wifiduino.menu.baud.512000.upload.speed=512000 + +############################################################## +wifi_slot.name=Amperka WiFi Slot +wifi_slot.build.board=AMPERKA_WIFI_SLOT +wifi_slot.build.variant=wifi_slot +wifi_slot.upload.tool=esptool +wifi_slot.upload.maximum_data_size=81920 +wifi_slot.upload.wait_for_upload_port=true +wifi_slot.upload.erase_cmd= +wifi_slot.serial.disableDTR=true +wifi_slot.serial.disableRTS=true +wifi_slot.build.mcu=esp8266 +wifi_slot.build.core=esp8266 +wifi_slot.build.spiffs_pagesize=256 +wifi_slot.build.debug_port= +wifi_slot.build.debug_level= +wifi_slot.menu.xtal.80=80 MHz +wifi_slot.menu.xtal.80.build.f_cpu=80000000L +wifi_slot.menu.xtal.160=160 MHz +wifi_slot.menu.xtal.160.build.f_cpu=160000000L +wifi_slot.menu.vt.flash=Flash +wifi_slot.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wifi_slot.menu.vt.heap=Heap +wifi_slot.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wifi_slot.menu.vt.iram=IRAM +wifi_slot.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wifi_slot.menu.exception.disabled=Disabled +wifi_slot.menu.exception.disabled.build.exception_flags=-fno-exceptions +wifi_slot.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wifi_slot.menu.exception.enabled=Enabled +wifi_slot.menu.exception.enabled.build.exception_flags=-fexceptions +wifi_slot.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wifi_slot.upload.resetmethod=nodemcu +wifi_slot.menu.FlashFreq.40=40MHz +wifi_slot.menu.FlashFreq.40.build.flash_freq=40 +wifi_slot.menu.FlashFreq.80=80MHz +wifi_slot.menu.FlashFreq.80.build.flash_freq=80 +wifi_slot.menu.FlashMode.dout=DOUT (compatible) +wifi_slot.menu.FlashMode.dout.build.flash_mode=dout +wifi_slot.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT +wifi_slot.menu.FlashMode.dio=DIO +wifi_slot.menu.FlashMode.dio.build.flash_mode=dio +wifi_slot.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO +wifi_slot.menu.FlashMode.qout=QOUT +wifi_slot.menu.FlashMode.qout.build.flash_mode=qout +wifi_slot.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT +wifi_slot.menu.FlashMode.qio=QIO (fast) +wifi_slot.menu.FlashMode.qio.build.flash_mode=qio +wifi_slot.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO +wifi_slot.menu.eesz.1M=1M (no SPIFFS) +wifi_slot.menu.eesz.1M.build.flash_size=1M +wifi_slot.menu.eesz.1M.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +wifi_slot.menu.eesz.1M.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M.upload.maximum_size=1023984 +wifi_slot.menu.eesz.1M.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M64=1M (64K SPIFFS) +wifi_slot.menu.eesz.1M64.build.flash_size=1M +wifi_slot.menu.eesz.1M64.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +wifi_slot.menu.eesz.1M64.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M64.upload.maximum_size=958448 +wifi_slot.menu.eesz.1M64.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M64.build.spiffs_start=0xEB000 +wifi_slot.menu.eesz.1M64.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M64.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M128=1M (128K SPIFFS) +wifi_slot.menu.eesz.1M128.build.flash_size=1M +wifi_slot.menu.eesz.1M128.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +wifi_slot.menu.eesz.1M128.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M128.upload.maximum_size=892912 +wifi_slot.menu.eesz.1M128.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M128.build.spiffs_start=0xDB000 +wifi_slot.menu.eesz.1M128.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M128.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M144=1M (144K SPIFFS) +wifi_slot.menu.eesz.1M144.build.flash_size=1M +wifi_slot.menu.eesz.1M144.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +wifi_slot.menu.eesz.1M144.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M144.upload.maximum_size=876528 +wifi_slot.menu.eesz.1M144.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M144.build.spiffs_start=0xD7000 +wifi_slot.menu.eesz.1M144.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M144.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M160=1M (160K SPIFFS) +wifi_slot.menu.eesz.1M160.build.flash_size=1M +wifi_slot.menu.eesz.1M160.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +wifi_slot.menu.eesz.1M160.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M160.upload.maximum_size=860144 +wifi_slot.menu.eesz.1M160.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M160.build.spiffs_start=0xD3000 +wifi_slot.menu.eesz.1M160.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M160.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M192=1M (192K SPIFFS) +wifi_slot.menu.eesz.1M192.build.flash_size=1M +wifi_slot.menu.eesz.1M192.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +wifi_slot.menu.eesz.1M192.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M192.upload.maximum_size=827376 +wifi_slot.menu.eesz.1M192.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M192.build.spiffs_start=0xCB000 +wifi_slot.menu.eesz.1M192.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M192.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M256=1M (256K SPIFFS) +wifi_slot.menu.eesz.1M256.build.flash_size=1M +wifi_slot.menu.eesz.1M256.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +wifi_slot.menu.eesz.1M256.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M256.upload.maximum_size=761840 +wifi_slot.menu.eesz.1M256.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M256.build.spiffs_start=0xBB000 +wifi_slot.menu.eesz.1M256.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M256.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M512=1M (512K SPIFFS) +wifi_slot.menu.eesz.1M512.build.flash_size=1M +wifi_slot.menu.eesz.1M512.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +wifi_slot.menu.eesz.1M512.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M512.upload.maximum_size=499696 +wifi_slot.menu.eesz.1M512.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M512.build.spiffs_start=0x7B000 +wifi_slot.menu.eesz.1M512.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M512.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.2M=2M (no SPIFFS) +wifi_slot.menu.eesz.2M.build.flash_size=2M +wifi_slot.menu.eesz.2M.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld +wifi_slot.menu.eesz.2M.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M128=2M (128K SPIFFS) +wifi_slot.menu.eesz.2M128.build.flash_size=2M +wifi_slot.menu.eesz.2M128.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld +wifi_slot.menu.eesz.2M128.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M128.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M128.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M128.build.spiffs_start=0x1E0000 +wifi_slot.menu.eesz.2M128.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M128.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.2M256=2M (256K SPIFFS) +wifi_slot.menu.eesz.2M256.build.flash_size=2M +wifi_slot.menu.eesz.2M256.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld +wifi_slot.menu.eesz.2M256.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M256.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M256.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M256.build.spiffs_start=0x1C0000 +wifi_slot.menu.eesz.2M256.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M256.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.2M512=2M (512K SPIFFS) +wifi_slot.menu.eesz.2M512.build.flash_size=2M +wifi_slot.menu.eesz.2M512.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld +wifi_slot.menu.eesz.2M512.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M512.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M512.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M512.build.spiffs_start=0x180000 +wifi_slot.menu.eesz.2M512.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M512.build.spiffs_blocksize=8192 +wifi_slot.menu.eesz.2M1M=2M (1M SPIFFS) +wifi_slot.menu.eesz.2M1M.build.flash_size=2M +wifi_slot.menu.eesz.2M1M.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld +wifi_slot.menu.eesz.2M1M.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M1M.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M1M.build.spiffs_start=0x100000 +wifi_slot.menu.eesz.2M1M.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M1M.build.spiffs_blocksize=8192 +wifi_slot.menu.ip.lm2f=v2 Lower Memory +wifi_slot.menu.ip.lm2f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wifi_slot.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifi_slot.menu.ip.hb2f=v2 Higher Bandwidth +wifi_slot.menu.ip.hb2f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wifi_slot.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifi_slot.menu.ip.lm2n=v2 Lower Memory (no features) +wifi_slot.menu.ip.lm2n.build.lwip_include=lwip2/include +wifi_slot.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wifi_slot.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifi_slot.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wifi_slot.menu.ip.hb2n.build.lwip_include=lwip2/include +wifi_slot.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wifi_slot.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifi_slot.menu.ip.lm6f=v2 IPv6 Lower Memory +wifi_slot.menu.ip.lm6f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wifi_slot.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifi_slot.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wifi_slot.menu.ip.hb6f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wifi_slot.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifi_slot.menu.ip.hb1=v1.4 Higher Bandwidth +wifi_slot.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wifi_slot.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wifi_slot.menu.ip.src=v1.4 Compile from source +wifi_slot.menu.ip.src.build.lwip_lib=-llwip_src +wifi_slot.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wifi_slot.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wifi_slot.menu.dbg.Disabled=Disabled +wifi_slot.menu.dbg.Disabled.build.debug_port= +wifi_slot.menu.dbg.Serial=Serial +wifi_slot.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wifi_slot.menu.dbg.Serial1=Serial1 +wifi_slot.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wifi_slot.menu.lvl.None____=None +wifi_slot.menu.lvl.None____.build.debug_level= +wifi_slot.menu.lvl.SSL=SSL +wifi_slot.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wifi_slot.menu.lvl.TLS_MEM=TLS_MEM +wifi_slot.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wifi_slot.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wifi_slot.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.HTTP_SERVER=HTTP_SERVER +wifi_slot.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wifi_slot.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wifi_slot.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wifi_slot.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wifi_slot.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.CORE=CORE +wifi_slot.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wifi_slot.menu.lvl.WIFI=WIFI +wifi_slot.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wifi_slot.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wifi_slot.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wifi_slot.menu.lvl.UPDATER=UPDATER +wifi_slot.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wifi_slot.menu.lvl.OTA=OTA +wifi_slot.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wifi_slot.menu.lvl.OOM=OOM +wifi_slot.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wifi_slot.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wifi_slot.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wifi_slot.menu.wipe.none=Only Sketch +wifi_slot.menu.wipe.none.upload.erase_cmd= +wifi_slot.menu.wipe.sdk=Sketch + WiFi Settings +wifi_slot.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +wifi_slot.menu.wipe.all=All Flash Contents +wifi_slot.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +wifi_slot.menu.baud.115200=115200 +wifi_slot.menu.baud.115200.upload.speed=115200 +wifi_slot.menu.baud.9600=9600 +wifi_slot.menu.baud.9600.upload.speed=9600 +wifi_slot.menu.baud.57600=57600 +wifi_slot.menu.baud.57600.upload.speed=57600 +wifi_slot.menu.baud.230400.linux=230400 +wifi_slot.menu.baud.230400.macosx=230400 +wifi_slot.menu.baud.230400.upload.speed=230400 +wifi_slot.menu.baud.256000.windows=256000 +wifi_slot.menu.baud.256000.upload.speed=256000 +wifi_slot.menu.baud.460800.linux=460800 +wifi_slot.menu.baud.460800.macosx=460800 +wifi_slot.menu.baud.460800.upload.speed=460800 +wifi_slot.menu.baud.512000.windows=512000 +wifi_slot.menu.baud.512000.upload.speed=512000 +wifi_slot.menu.baud.921600=921600 +wifi_slot.menu.baud.921600.upload.speed=921600 + +############################################################## +wiolink.name=Seeed Wio Link +wiolink.build.board=ESP8266_WIO_LINK +wiolink.build.variant=wiolink +wiolink.upload.tool=esptool +wiolink.upload.maximum_data_size=81920 +wiolink.upload.wait_for_upload_port=true +wiolink.upload.erase_cmd= +wiolink.serial.disableDTR=true +wiolink.serial.disableRTS=true +wiolink.build.mcu=esp8266 +wiolink.build.core=esp8266 +wiolink.build.spiffs_pagesize=256 +wiolink.build.debug_port= +wiolink.build.debug_level= +wiolink.menu.xtal.80=80 MHz +wiolink.menu.xtal.80.build.f_cpu=80000000L +wiolink.menu.xtal.160=160 MHz +wiolink.menu.xtal.160.build.f_cpu=160000000L +wiolink.menu.vt.flash=Flash +wiolink.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wiolink.menu.vt.heap=Heap +wiolink.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wiolink.menu.vt.iram=IRAM +wiolink.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wiolink.menu.exception.disabled=Disabled +wiolink.menu.exception.disabled.build.exception_flags=-fno-exceptions +wiolink.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wiolink.menu.exception.enabled=Enabled +wiolink.menu.exception.enabled.build.exception_flags=-fexceptions +wiolink.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wiolink.upload.resetmethod=nodemcu +wiolink.build.flash_mode=qio +wiolink.build.flash_flags=-DFLASHMODE_QIO +wiolink.build.flash_freq=40 +wiolink.menu.eesz.4M=4M (no SPIFFS) +wiolink.menu.eesz.4M.build.flash_size=4M +wiolink.menu.eesz.4M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +wiolink.menu.eesz.4M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M1M=4M (1M SPIFFS) +wiolink.menu.eesz.4M1M.build.flash_size=4M +wiolink.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +wiolink.menu.eesz.4M1M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M1M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M1M.build.spiffs_start=0x300000 +wiolink.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +wiolink.menu.eesz.4M1M.build.spiffs_blocksize=8192 +wiolink.menu.eesz.4M2M=4M (2M SPIFFS) +wiolink.menu.eesz.4M2M.build.flash_size=4M +wiolink.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +wiolink.menu.eesz.4M2M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M2M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M2M.build.spiffs_start=0x200000 +wiolink.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +wiolink.menu.eesz.4M2M.build.spiffs_blocksize=8192 +wiolink.menu.eesz.4M3M=4M (3M SPIFFS) +wiolink.menu.eesz.4M3M.build.flash_size=4M +wiolink.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +wiolink.menu.eesz.4M3M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M3M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M3M.build.spiffs_start=0x100000 +wiolink.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +wiolink.menu.eesz.4M3M.build.spiffs_blocksize=8192 +wiolink.menu.ip.lm2f=v2 Lower Memory +wiolink.menu.ip.lm2f.build.lwip_include=lwip2/include +wiolink.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wiolink.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wiolink.menu.ip.hb2f=v2 Higher Bandwidth +wiolink.menu.ip.hb2f.build.lwip_include=lwip2/include +wiolink.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wiolink.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wiolink.menu.ip.lm2n=v2 Lower Memory (no features) +wiolink.menu.ip.lm2n.build.lwip_include=lwip2/include +wiolink.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wiolink.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wiolink.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wiolink.menu.ip.hb2n.build.lwip_include=lwip2/include +wiolink.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wiolink.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wiolink.menu.ip.lm6f=v2 IPv6 Lower Memory +wiolink.menu.ip.lm6f.build.lwip_include=lwip2/include +wiolink.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wiolink.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wiolink.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wiolink.menu.ip.hb6f.build.lwip_include=lwip2/include +wiolink.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wiolink.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wiolink.menu.ip.hb1=v1.4 Higher Bandwidth +wiolink.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wiolink.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wiolink.menu.ip.src=v1.4 Compile from source +wiolink.menu.ip.src.build.lwip_lib=-llwip_src +wiolink.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wiolink.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wiolink.menu.dbg.Disabled=Disabled +wiolink.menu.dbg.Disabled.build.debug_port= +wiolink.menu.dbg.Serial=Serial +wiolink.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wiolink.menu.dbg.Serial1=Serial1 +wiolink.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wiolink.menu.lvl.None____=None +wiolink.menu.lvl.None____.build.debug_level= +wiolink.menu.lvl.SSL=SSL +wiolink.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wiolink.menu.lvl.TLS_MEM=TLS_MEM +wiolink.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wiolink.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wiolink.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.HTTP_SERVER=HTTP_SERVER +wiolink.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wiolink.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wiolink.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wiolink.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wiolink.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wiolink.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.CORE=CORE +wiolink.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wiolink.menu.lvl.WIFI=WIFI +wiolink.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wiolink.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wiolink.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wiolink.menu.lvl.UPDATER=UPDATER +wiolink.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wiolink.menu.lvl.OTA=OTA +wiolink.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wiolink.menu.lvl.OOM=OOM +wiolink.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wiolink.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wiolink.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wiolink.menu.wipe.none=Only Sketch +wiolink.menu.wipe.none.upload.erase_cmd= +wiolink.menu.wipe.sdk=Sketch + WiFi Settings +wiolink.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +wiolink.menu.wipe.all=All Flash Contents +wiolink.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +wiolink.menu.baud.115200=115200 +wiolink.menu.baud.115200.upload.speed=115200 +wiolink.menu.baud.9600=9600 +wiolink.menu.baud.9600.upload.speed=9600 +wiolink.menu.baud.57600=57600 +wiolink.menu.baud.57600.upload.speed=57600 +wiolink.menu.baud.230400.linux=230400 +wiolink.menu.baud.230400.macosx=230400 +wiolink.menu.baud.230400.upload.speed=230400 +wiolink.menu.baud.256000.windows=256000 +wiolink.menu.baud.256000.upload.speed=256000 +wiolink.menu.baud.460800.linux=460800 +wiolink.menu.baud.460800.macosx=460800 +wiolink.menu.baud.460800.upload.speed=460800 +wiolink.menu.baud.512000.windows=512000 +wiolink.menu.baud.512000.upload.speed=512000 +wiolink.menu.baud.921600=921600 +wiolink.menu.baud.921600.upload.speed=921600 + +############################################################## +espectro.name=ESPectro Core +espectro.build.board=ESP8266_ESPECTRO_CORE +espectro.build.variant=espectro +espectro.upload.tool=esptool +espectro.upload.maximum_data_size=81920 +espectro.upload.wait_for_upload_port=true +espectro.upload.erase_cmd= +espectro.serial.disableDTR=true +espectro.serial.disableRTS=true +espectro.build.mcu=esp8266 +espectro.build.core=esp8266 +espectro.build.spiffs_pagesize=256 +espectro.build.debug_port= +espectro.build.debug_level= +espectro.menu.xtal.80=80 MHz +espectro.menu.xtal.80.build.f_cpu=80000000L +espectro.menu.xtal.160=160 MHz +espectro.menu.xtal.160.build.f_cpu=160000000L +espectro.menu.vt.flash=Flash +espectro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espectro.menu.vt.heap=Heap +espectro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espectro.menu.vt.iram=IRAM +espectro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espectro.menu.exception.disabled=Disabled +espectro.menu.exception.disabled.build.exception_flags=-fno-exceptions +espectro.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espectro.menu.exception.enabled=Enabled +espectro.menu.exception.enabled.build.exception_flags=-fexceptions +espectro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espectro.upload.resetmethod=nodemcu +espectro.build.flash_mode=dio +espectro.build.flash_flags=-DFLASHMODE_DIO +espectro.build.flash_freq=40 +espectro.menu.eesz.4M=4M (no SPIFFS) +espectro.menu.eesz.4M.build.flash_size=4M +espectro.menu.eesz.4M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espectro.menu.eesz.4M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M.upload.maximum_size=1044464 +espectro.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M1M=4M (1M SPIFFS) +espectro.menu.eesz.4M1M.build.flash_size=4M +espectro.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espectro.menu.eesz.4M1M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M1M.upload.maximum_size=1044464 +espectro.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M1M.build.spiffs_start=0x300000 +espectro.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +espectro.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espectro.menu.eesz.4M2M=4M (2M SPIFFS) +espectro.menu.eesz.4M2M.build.flash_size=4M +espectro.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espectro.menu.eesz.4M2M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M2M.upload.maximum_size=1044464 +espectro.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M2M.build.spiffs_start=0x200000 +espectro.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +espectro.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espectro.menu.eesz.4M3M=4M (3M SPIFFS) +espectro.menu.eesz.4M3M.build.flash_size=4M +espectro.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espectro.menu.eesz.4M3M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M3M.upload.maximum_size=1044464 +espectro.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M3M.build.spiffs_start=0x100000 +espectro.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +espectro.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espectro.menu.ip.lm2f=v2 Lower Memory +espectro.menu.ip.lm2f.build.lwip_include=lwip2/include +espectro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espectro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espectro.menu.ip.hb2f=v2 Higher Bandwidth +espectro.menu.ip.hb2f.build.lwip_include=lwip2/include +espectro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espectro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espectro.menu.ip.lm2n=v2 Lower Memory (no features) +espectro.menu.ip.lm2n.build.lwip_include=lwip2/include +espectro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espectro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espectro.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espectro.menu.ip.hb2n.build.lwip_include=lwip2/include +espectro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espectro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espectro.menu.ip.lm6f=v2 IPv6 Lower Memory +espectro.menu.ip.lm6f.build.lwip_include=lwip2/include +espectro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espectro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espectro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espectro.menu.ip.hb6f.build.lwip_include=lwip2/include +espectro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espectro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espectro.menu.ip.hb1=v1.4 Higher Bandwidth +espectro.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espectro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espectro.menu.ip.src=v1.4 Compile from source +espectro.menu.ip.src.build.lwip_lib=-llwip_src +espectro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espectro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espectro.menu.dbg.Disabled=Disabled +espectro.menu.dbg.Disabled.build.debug_port= +espectro.menu.dbg.Serial=Serial +espectro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espectro.menu.dbg.Serial1=Serial1 +espectro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espectro.menu.lvl.None____=None +espectro.menu.lvl.None____.build.debug_level= +espectro.menu.lvl.SSL=SSL +espectro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espectro.menu.lvl.TLS_MEM=TLS_MEM +espectro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espectro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espectro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.HTTP_SERVER=HTTP_SERVER +espectro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espectro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espectro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espectro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espectro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espectro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.CORE=CORE +espectro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espectro.menu.lvl.WIFI=WIFI +espectro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espectro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espectro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espectro.menu.lvl.UPDATER=UPDATER +espectro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espectro.menu.lvl.OTA=OTA +espectro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espectro.menu.lvl.OOM=OOM +espectro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espectro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espectro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espectro.menu.wipe.none=Only Sketch +espectro.menu.wipe.none.upload.erase_cmd= +espectro.menu.wipe.sdk=Sketch + WiFi Settings +espectro.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +espectro.menu.wipe.all=All Flash Contents +espectro.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +espectro.menu.baud.115200=115200 +espectro.menu.baud.115200.upload.speed=115200 +espectro.menu.baud.9600=9600 +espectro.menu.baud.9600.upload.speed=9600 +espectro.menu.baud.57600=57600 +espectro.menu.baud.57600.upload.speed=57600 +espectro.menu.baud.230400.linux=230400 +espectro.menu.baud.230400.macosx=230400 +espectro.menu.baud.230400.upload.speed=230400 +espectro.menu.baud.256000.windows=256000 +espectro.menu.baud.256000.upload.speed=256000 +espectro.menu.baud.460800.linux=460800 +espectro.menu.baud.460800.macosx=460800 +espectro.menu.baud.460800.upload.speed=460800 +espectro.menu.baud.512000.windows=512000 +espectro.menu.baud.512000.upload.speed=512000 +espectro.menu.baud.921600=921600 +espectro.menu.baud.921600.upload.speed=921600 + diff --git a/arduino/version 2.5.0-beta3/platform.txt b/arduino/version 2.5.0-beta3/platform.txt new file mode 100644 index 000000000..a790bc6c0 --- /dev/null +++ b/arduino/version 2.5.0-beta3/platform.txt @@ -0,0 +1,154 @@ + +# ESP8266 platform +# ------------------------------ + +# For more info: +# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification + +name=ESP8266 Boards (2.5.0-beta3) +version=2.5.0-beta3 + + + +runtime.tools.signing={runtime.platform.path}/tools/signing.py + +compiler.warning_flags=-w +compiler.warning_flags.none=-w +compiler.warning_flags.default= +compiler.warning_flags.more=-Wall +compiler.warning_flags.all=-Wall -Wextra + +build.lwip_lib=-llwip_gcc +build.lwip_include=lwip/include +build.lwip_flags=-DLWIP_OPEN_SRC + +build.vtable_flags=-DVTABLES_IN_FLASH + +build.exception_flags=-fno-exceptions +build.stdcpp_lib=-lstdc++ + +#build.float=-u _printf_float -u _scanf_float +build.float= +build.led= + +compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/ +compiler.sdk.path={runtime.platform.path}/tools/sdk +compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf +compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" + +compiler.c.cmd=xtensa-lx106-elf-gcc +compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} + +compiler.S.cmd=xtensa-lx106-elf-gcc +compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls + +compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read + +compiler.c.elf.cmd=xtensa-lx106-elf-gcc +compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc + +compiler.cpp.cmd=xtensa-lx106-elf-g++ +compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections {build.exception_flags} + +compiler.as.cmd=xtensa-lx106-elf-as + +compiler.ar.cmd=xtensa-lx106-elf-ar +compiler.ar.flags=cru + +compiler.elf2hex.cmd=esptool +compiler.elf2hex.flags= + +compiler.size.cmd=xtensa-lx106-elf-size + +compiler.esptool.cmd=esptool +compiler.esptool.cmd.windows=esptool.exe + +# This can be overriden in boards.txt +build.extra_flags=-DESP8266 + +# These can be overridden in platform.local.txt +compiler.c.extra_flags= +compiler.c.elf.extra_flags= +compiler.S.extra_flags= +compiler.cpp.extra_flags= +compiler.ar.extra_flags= +compiler.objcopy.eep.extra_flags= +compiler.elf2hex.extra_flags= + +## generate file with git version number +## needs bash, git, and echo +recipe.hooks.core.prebuild.1.pattern=python "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h" + + + +## windows-compatible version without git +recipe.hooks.core.prebuild.1.pattern.windows=cmd.exe /c rem cannot sign on windows + + + +## Build the app.ld linker file +recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld" + +## Compile c files +recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Compile c++ files +recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Compile S files +recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Create archives +recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" + +## Combine gc-sections, archives, and objects +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" + +## Create eeprom +recipe.objcopy.eep.pattern= + +## Create hex +#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" + +recipe.objcopy.hex.1.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec +recipe.objcopy.hex.2.pattern=python "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed" + +# No signing on Windows +recipe.objcopy.hex.1.pattern.windows="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec +recipe.objcopy.hex.2.pattern.windows= + +## Save hex +recipe.output.tmp_file={build.project_name}.bin +recipe.output.save_file={build.project_name}.{build.variant}.bin + +## Compute size +recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" +recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).* +recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* +#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* + +# ------------------------------ + +tools.esptool.cmd=esptool +tools.esptool.cmd.windows=esptool.exe +tools.esptool.path={runtime.tools.esptool.path} +tools.esptool.network_cmd=python +tools.esptool.network_cmd.windows=python.exe + +tools.esptool.upload.protocol=esp +tools.esptool.upload.params.verbose=-vv +tools.esptool.upload.params.quiet= +tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin" +tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" + +tools.mkspiffs.cmd=mkspiffs +tools.mkspiffs.cmd.windows=mkspiffs.exe +tools.mkspiffs.path={runtime.tools.mkspiffs.path} + +tools.espupload.cmd=python +tools.espupload.cmd.windows=python.exe +tools.espupload.path={runtime.platform.path}/tools +tools.espupload.upload.protocol=espupload +tools.espupload.upload.params.verbose= +tools.espupload.upload.params.quiet= +tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin" From f23d18723e1cbd469ac95a51d3c1aa910c3377e6 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Sat, 26 Jan 2019 16:43:36 +0200 Subject: [PATCH 0896/2222] Disable sleep 0 for scheme 0 Disable sleep 0 for scheme 0 as there is no animation required --- sonoff/xdrv_04_light.ino | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index bfeaf889f..ab3450ec2 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -756,7 +756,11 @@ void LightAnimate(void) } } else { - sleep = 0; + if (Settings.light_scheme > 0) { + sleep = 0; + } else { + sleep = Settings.sleep; + } switch (Settings.light_scheme) { case LS_POWER: LightSetDimmer(Settings.light_dimmer); From 5dfc8a951b23f7d62d9b5ce6a86f8541c025464a Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 27 Jan 2019 00:53:52 +0200 Subject: [PATCH 0897/2222] PN532:Allow RAW DATA usage by define --- sonoff/xsns_40_pn532_i2c.ino | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index a03b30e6b..785894f20 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -407,6 +407,9 @@ void PN532_ScanForTag(void) uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) { if (mifareclassic_ReadDataBlock(1, card_data)) { +#ifdef USE_PN532_DATA_RAW + memcpy(&card_datas,&card_data,sizeof(card_data)); +#else for (uint8_t i = 0;i < sizeof(card_data);i++) { if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) { card_datas[i] = char(card_data[i]); @@ -414,6 +417,7 @@ void PN532_ScanForTag(void) card_datas[i] = '\0'; } } +#endif // USE_PN532_DATA_RAW } if (pn532_i2c_function == 1) { // erase block 1 of card for (uint8_t i = 0;i<16;i++) { @@ -427,6 +431,15 @@ void PN532_ScanForTag(void) } } if (pn532_i2c_function == 2) { +#ifdef USE_PN532_DATA_RAW + if (mifareclassic_WriteDataBlock(1, card_data)) { + memcpy(&card_data,&pn532_i2c_newdata,sizeof(card_data)); + set_success = true; + snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful"); + AddLog(LOG_LEVEL_INFO); + memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string + } +#else boolean IsAlphaNumeric = true; for (uint8_t i = 0;i < pn532_i2c_newdata_len;i++) { if ((!isalpha(pn532_i2c_newdata[i])) || (!isdigit(pn532_i2c_newdata[i]))) { @@ -445,6 +458,7 @@ void PN532_ScanForTag(void) snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data must be alphanumeric"); AddLog(LOG_LEVEL_INFO); } +#endif // USE_PN532_DATA_RAW } } else { sprintf(card_datas,"AUTHFAIL"); From 13b84010895174ef63cf1e9aa341fe7451037f07 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Sun, 27 Jan 2019 01:11:55 +0200 Subject: [PATCH 0898/2222] Update xsns_40_pn532_i2c.ino --- sonoff/xsns_40_pn532_i2c.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index 785894f20..212a98905 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -433,7 +433,6 @@ void PN532_ScanForTag(void) if (pn532_i2c_function == 2) { #ifdef USE_PN532_DATA_RAW if (mifareclassic_WriteDataBlock(1, card_data)) { - memcpy(&card_data,&pn532_i2c_newdata,sizeof(card_data)); set_success = true; snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful"); AddLog(LOG_LEVEL_INFO); From 2827de40a3d8316e9ac135e76a66e0de03d3fe59 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Jan 2019 11:02:12 +0100 Subject: [PATCH 0899/2222] Set initial legacy interlock state Set initial legacy interlock state --- sonoff/settings.ino | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index c483977f5..ef502d230 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -574,6 +574,7 @@ void SettingsDefaultSet2(void) // Module // Settings.flag.interlock = 0; + Settings.interlock[0] = 0xFF; // Legacy support using all relays in one interlock group Settings.module = MODULE; // for (byte i = 0; i < sizeof(Settings.my_gp); i++) { Settings.my_gp.io[i] = GPIO_NONE; } strlcpy(Settings.friendlyname[0], FRIENDLY_NAME, sizeof(Settings.friendlyname[0])); @@ -1023,7 +1024,8 @@ void SettingsDelta(void) Settings.param[P_MDNS_DELAYED_START] = 0; } if (Settings.version < 0x0604010B) { - for (byte i = 0; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } + Settings.interlock[0] = 0xFF; // Legacy support using all relays in one interlock group + for (byte i = 1; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } } Settings.version = VERSION; From 269258bde57a9c226473f7ad7f63df38a171b640 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Jan 2019 11:25:28 +0100 Subject: [PATCH 0900/2222] Update xdrv_04_light.ino --- sonoff/xdrv_04_light.ino | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index ab3450ec2..4a1d19478 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -756,11 +756,7 @@ void LightAnimate(void) } } else { - if (Settings.light_scheme > 0) { - sleep = 0; - } else { - sleep = Settings.sleep; - } + sleep = (LS_POWER == Settings.light_scheme) ? Settings.sleep : 0; // If no animation then use sleep as is switch (Settings.light_scheme) { case LS_POWER: LightSetDimmer(Settings.light_dimmer); From d1c6cfb6f965340e79d05dd2caa947c0ccc7041d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Jan 2019 12:42:05 +0100 Subject: [PATCH 0901/2222] Disable patched core PWM Disable patched core PWM starting with core 2.5.0-beta3 --- sonoff/core_esp8266_timer.c | 10 +++++----- sonoff/core_esp8266_wiring_digital.c | 10 +++++----- sonoff/core_esp8266_wiring_pwm.c | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/sonoff/core_esp8266_timer.c b/sonoff/core_esp8266_timer.c index 81c3a76e0..bf852784c 100644 --- a/sonoff/core_esp8266_timer.c +++ b/sonoff/core_esp8266_timer.c @@ -19,10 +19,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -// Use PWM from core 2.4.0 as all other version produce LED flickering when settings are saved to flash. Still true for 2.5.0 -//#include -//#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) -//#warning **** Tasmota is using v2.4.0 timer.c as planned **** +// Use PWM from core 2.4.0 as all versions below 2.5.0-beta3 produce LED flickering when settings are saved to flash +#include +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) +#warning **** Tasmota is using v2.4.0 timer.c as planned **** #include "wiring_private.h" #include "pins_arduino.h" @@ -108,4 +108,4 @@ void ICACHE_RAM_ATTR timer0_detachInterrupt(void) { ETS_CCOMPARE0_DISABLE(); } -//#endif // ARDUINO_ESP8266_RELEASE +#endif // ARDUINO_ESP8266_RELEASE diff --git a/sonoff/core_esp8266_wiring_digital.c b/sonoff/core_esp8266_wiring_digital.c index 33de53c75..f8d521748 100644 --- a/sonoff/core_esp8266_wiring_digital.c +++ b/sonoff/core_esp8266_wiring_digital.c @@ -19,10 +19,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -// Use PWM from core 2.4.0 as all other version produce LED flickering when settings are saved to flash. Still true for 2.5.0 -//#include -//#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) -//#warning **** Tasmota is using v2.4.0 wiring_digital.c as planned **** +// Use PWM from core 2.4.0 as all versions below 2.5.0-beta3 produce LED flickering when settings are saved to flash +#include +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) +#warning **** Tasmota is using v2.4.0 wiring_digital.c as planned **** #define ARDUINO_MAIN #include "wiring_private.h" @@ -214,4 +214,4 @@ extern int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead") extern void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterrupt"))); extern void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt"))); -//#endif // ARDUINO_ESP8266_RELEASE +#endif // ARDUINO_ESP8266_RELEASE diff --git a/sonoff/core_esp8266_wiring_pwm.c b/sonoff/core_esp8266_wiring_pwm.c index 780190059..d7e179b9b 100644 --- a/sonoff/core_esp8266_wiring_pwm.c +++ b/sonoff/core_esp8266_wiring_pwm.c @@ -19,10 +19,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -// Use PWM from core 2.4.0 as all other version produce flicker when settings are saved to flash. Still true for 2.5.0 -//#include -//#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) -//#warning **** Tasmota is using v2.4.0 wiring_pwm.c as planned **** +// Use PWM from core 2.4.0 as all versions below 2.5.0-beta3 produce LED flickering when settings are saved to flash +#include +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) +#warning **** Tasmota is using v2.4.0 wiring_pwm.c as planned **** #include "wiring_private.h" #include "pins_arduino.h" @@ -226,4 +226,4 @@ extern void analogWrite(uint8_t pin, int val) __attribute__ ((weak, alias("__ana extern void analogWriteFreq(uint32_t freq) __attribute__ ((weak, alias("__analogWriteFreq"))); extern void analogWriteRange(uint32_t range) __attribute__ ((weak, alias("__analogWriteRange"))); -//#endif // ARDUINO_ESP8266_RELEASE +#endif // ARDUINO_ESP8266_RELEASE From dc75b473cff67320292eb8e3e7e5830e2b5850b1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Jan 2019 14:54:28 +0100 Subject: [PATCH 0902/2222] Add support for inverted buttons * Add core version conditional compile options to provided PWM files (#4917) * Add support for inverted buttons and inverted buttons without pullup (#4914) --- sonoff/_changelog.ino | 2 ++ sonoff/sonoff.ino | 11 +++++++++- sonoff/sonoff_template.h | 42 ++++++++++++++++++++++++++++++++++++++- sonoff/support_button.ino | 12 ++++++++--- 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 4388afb82..909715904 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,8 @@ * Remove command SetOption14 as it has been superseded by command Interlock * Remove command SetOption63 as it has been superseded by command Interlock * Add command Interlock 0 / 1 / 1,2 3,4 .. to control interlock ON/OFF and add up to 8 relays in 1 to 4 interlock groups (#5014) + * Add core version conditional compile options to provided PWM files (#4917) + * Add support for inverted buttons and inverted buttons without pullup (#4914) * * 6.4.1.10 20190121 * Fix Hass discovery of MHZ19(B) sensors (#4992) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index bec71038d..b50544a7d 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2279,9 +2279,18 @@ void GpioInit(void) mpin -= (GPIO_SWT1_NP - GPIO_SWT1); } else if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) { - ButtonPullupFlag(mpin - GPIO_KEY1_NP); + ButtonPullupFlag(mpin - GPIO_KEY1_NP); // 0 .. 3 mpin -= (GPIO_KEY1_NP - GPIO_KEY1); } + else if ((mpin >= GPIO_KEY1_INV) && (mpin < (GPIO_KEY1_INV + MAX_KEYS))) { + ButtonInvertFlag(mpin - GPIO_KEY1_INV); // 0 .. 3 + mpin -= (GPIO_KEY1_INV - GPIO_KEY1); + } + else if ((mpin >= GPIO_KEY1_INV_NP) && (mpin < (GPIO_KEY1_INV_NP + MAX_KEYS))) { + ButtonPullupFlag(mpin - GPIO_KEY1_INV_NP); // 0 .. 3 + ButtonInvertFlag(mpin - GPIO_KEY1_INV_NP); // 0 .. 3 + mpin -= (GPIO_KEY1_INV_NP - GPIO_KEY1); + } else if ((mpin >= GPIO_REL1_INV) && (mpin < (GPIO_REL1_INV + MAX_RELAYS))) { bitSet(rel_inverted, mpin - GPIO_REL1_INV); mpin -= (GPIO_REL1_INV - GPIO_REL1); diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 39eb8737d..3385930f4 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -146,6 +146,14 @@ enum UserSelectablePins { GPIO_MAX31855CS, // MAX31855 Serial interface GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface + GPIO_KEY1_INV, // Inverted buttons + GPIO_KEY2_INV, + GPIO_KEY3_INV, + GPIO_KEY4_INV, + GPIO_KEY1_INV_NP, // Inverted buttons without pull-up + GPIO_KEY2_INV_NP, + GPIO_KEY3_INV_NP, + GPIO_KEY4_INV_NP, GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -209,7 +217,10 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC "|" D_SENSOR_RF_SENSOR "|" D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX "|" - D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO; + D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO "|" + D_SENSOR_BUTTON "1i|" D_SENSOR_BUTTON "2i|" D_SENSOR_BUTTON "3i|" D_SENSOR_BUTTON "4i|" + D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in" + ; /********************************************************************************************/ @@ -331,12 +342,20 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_NONE, // Not used GPIO_KEY1, // Buttons GPIO_KEY1_NP, + GPIO_KEY1_INV, + GPIO_KEY1_INV_NP, GPIO_KEY2, GPIO_KEY2_NP, + GPIO_KEY2_INV, + GPIO_KEY2_INV_NP, GPIO_KEY3, GPIO_KEY3_NP, + GPIO_KEY3_INV, + GPIO_KEY3_INV_NP, GPIO_KEY4, GPIO_KEY4_NP, + GPIO_KEY4_INV, + GPIO_KEY4_INV_NP, GPIO_SWT1, // User connected external switches GPIO_SWT1_NP, GPIO_SWT2, @@ -1780,6 +1799,27 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { /* Optionals + { "ESP RGBWWC", // esp rgbww controller https://github.com/pljakobs/esp_rgbww_controller/tree/v2.3 + GPIO_KEY1, // GPIO00 Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, // GPIO02 + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_PWM5, // GPIO04 LED Warm White + GPIO_PWM4, // GPIO05 LED Cold White + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM2, // GPIO12 LED Green + GPIO_PWM1, // GPIO13 LED Red + GPIO_PWM3, // GPIO14 LED Blue + 0, // GPIO15 + GPIO_KEY2, // GPIO16 Button + 0 + } + { "N0DY Relay", // N0DY Wifi Dual Relay (ESP-07) // https://www.n0dy.com/product/web-controlled-dual-relay/ // https://www.amazon.com/dp/B072MKV8ZM diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index b058b685a..092c50a97 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -32,8 +32,9 @@ uint8_t multiwindow[MAX_KEYS] = { 0 }; // Max time between button presses t uint8_t multipress[MAX_KEYS] = { 0 }; // Number of button presses within multiwindow uint8_t dual_hex_code = 0; // Sonoff dual input flag -uint8_t key_no_pullup = 0; -uint8_t buttons_found = 0; +uint8_t key_no_pullup = 0; // key no pullup flag (1 = no pullup) +uint8_t key_inverted = 0; // Key inverted flag (1 = inverted) +uint8_t buttons_found = 0; // Number of buttons found flag /********************************************************************************************/ @@ -42,6 +43,11 @@ void ButtonPullupFlag(uint8 button_bit) bitSet(key_no_pullup, button_bit); } +void ButtonInvertFlag(uint8 button_bit) +{ + bitSet(key_inverted, button_bit); +} + void ButtonInit(void) { if (my_module_flag.pullup) { @@ -115,7 +121,7 @@ void ButtonHandler(void) } else { if (pin[GPIO_KEY1 +button_index] < 99) { button_present = 1; - button = digitalRead(pin[GPIO_KEY1 +button_index]); + button = (digitalRead(pin[GPIO_KEY1 +button_index]) != key_inverted); } } From 2fc2535c7b12bbc9dbd242680669563791c0bcf9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 27 Jan 2019 15:13:57 +0100 Subject: [PATCH 0903/2222] Remove functionality not present Remove functionality not present (#5043) --- sonoff/sonoff_post.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 726ec6cba..e6eb186a5 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -228,6 +228,10 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define CODE_IMAGE 6 #undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) + #undef USE_PZEM004T // Disable PZEM004T energy sensor + #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor + #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor + #undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 #undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) #undef USE_DOMOTICZ // Disable Domoticz #undef USE_HOME_ASSISTANT // Disable Home Assistant From 6c8e15dadd7ae4477349a980b79f3a160ad66a78 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 28 Jan 2019 10:18:44 +0100 Subject: [PATCH 0904/2222] Fix inverted buttons Fix inverted buttons --- sonoff/support_button.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index 092c50a97..63726a05e 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -121,7 +121,7 @@ void ButtonHandler(void) } else { if (pin[GPIO_KEY1 +button_index] < 99) { button_present = 1; - button = (digitalRead(pin[GPIO_KEY1 +button_index]) != key_inverted); + button = (digitalRead(pin[GPIO_KEY1 +button_index]) != bitRead(key_inverted, button_index)); } } From 304ac6fe44c9ba9aca4478036555e9eaa442dc9b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 28 Jan 2019 14:08:33 +0100 Subject: [PATCH 0905/2222] 6.4.1.12 code changes (byte/boolean) 6.4.1.12 20190128 * Change code use of boolean to bool and byte to uint8_t * Change code uint8_t flags to bool flags --- sonoff/_changelog.ino | 6 +- sonoff/settings.h | 30 ++-- sonoff/settings.ino | 58 +++--- sonoff/sonoff.ino | 254 +++++++++++++-------------- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 50 +++--- sonoff/support_button.ino | 10 +- sonoff/support_rtc.ino | 10 +- sonoff/support_switch.ino | 8 +- sonoff/support_wifi.ino | 6 +- sonoff/xdrv_01_webserver.ino | 74 ++++---- sonoff/xdrv_02_mqtt.ino | 42 ++--- sonoff/xdrv_03_energy.ino | 79 ++++----- sonoff/xdrv_04_light.ino | 56 +++--- sonoff/xdrv_05_irremote.ino | 56 +++--- sonoff/xdrv_06_snfbridge.ino | 22 +-- sonoff/xdrv_07_domoticz.ino | 36 ++-- sonoff/xdrv_08_serial_bridge.ino | 10 +- sonoff/xdrv_09_timers.ino | 30 ++-- sonoff/xdrv_10_rules.ino | 42 ++--- sonoff/xdrv_11_knx.ino | 112 ++++++------ sonoff/xdrv_12_home_assistant.ino | 18 +- sonoff/xdrv_13_display.ino | 24 +-- sonoff/xdrv_14_mp3.ino | 8 +- sonoff/xdrv_15_pca9685.ino | 8 +- sonoff/xdrv_16_tuyadimmer.ino | 28 +-- sonoff/xdrv_17_rcswitch.ino | 12 +- sonoff/xdrv_18_armtronix_dimmers.ino | 10 +- sonoff/xdrv_19_ps16dz_dimmer.ino | 18 +- sonoff/xdrv_99_debug.ino | 16 +- sonoff/xdrv_interface.ino | 16 +- sonoff/xdsp_01_lcd.ino | 12 +- sonoff/xdsp_02_ssd1306.ino | 6 +- sonoff/xdsp_03_matrix.ino | 20 +-- sonoff/xdsp_04_ili9341.ino | 8 +- sonoff/xdsp_05_epaper_29.ino | 9 +- sonoff/xdsp_interface.ino | 10 +- sonoff/xnrg_01_hlw8012.ino | 16 +- sonoff/xnrg_02_cse7766.ino | 8 +- sonoff/xnrg_03_pzem004t.ino | 2 +- sonoff/xnrg_04_mcp39f501.ino | 14 +- sonoff/xnrg_05_pzem_ac.ino | 2 +- sonoff/xnrg_06_pzem_dc.ino | 2 +- sonoff/xnrg_interface.ino | 8 +- sonoff/xplg_wemohue.ino | 12 +- sonoff/xplg_ws2812.ino | 4 +- sonoff/xsns_01_counter.ino | 18 +- sonoff/xsns_02_analog.ino | 8 +- sonoff/xsns_04_snfsc.ino | 8 +- sonoff/xsns_05_ds18b20.ino | 10 +- sonoff/xsns_05_ds18x20.ino | 10 +- sonoff/xsns_05_ds18x20_legacy.ino | 24 +-- sonoff/xsns_06_dht.ino | 30 ++-- sonoff/xsns_07_sht1x.ino | 22 +-- sonoff/xsns_08_htu21.ino | 8 +- sonoff/xsns_09_bmp.ino | 20 +-- sonoff/xsns_10_bh1750.ino | 12 +- sonoff/xsns_11_veml6070.ino | 8 +- sonoff/xsns_12_ads1115.ino | 12 +- sonoff/xsns_12_ads1115_i2cdev.ino | 14 +- sonoff/xsns_13_ina219.ino | 10 +- sonoff/xsns_14_sht3x.ino | 10 +- sonoff/xsns_15_mhz19.ino | 18 +- sonoff/xsns_16_tsl2561.ino | 6 +- sonoff/xsns_17_senseair.ino | 6 +- sonoff/xsns_18_pms5003.ino | 8 +- sonoff/xsns_19_mgs.ino | 8 +- sonoff/xsns_20_novasds.ino | 16 +- sonoff/xsns_21_sgp30.ino | 6 +- sonoff/xsns_22_sr04.ino | 6 +- sonoff/xsns_23_sdm120.ino | 6 +- sonoff/xsns_24_si1145.ino | 10 +- sonoff/xsns_25_sdm630.ino | 6 +- sonoff/xsns_26_lm75ad.ino | 8 +- sonoff/xsns_27_apds9960.ino | 10 +- sonoff/xsns_28_tm1638.ino | 30 ++-- sonoff/xsns_29_mcp230xx.ino | 10 +- sonoff/xsns_30_mpr121.ino | 12 +- sonoff/xsns_31_ccs811.ino | 6 +- sonoff/xsns_32_mpu6050.ino | 8 +- sonoff/xsns_33_ds3231.ino | 12 +- sonoff/xsns_34_hx711.ino | 16 +- sonoff/xsns_35_tx20.ino | 8 +- sonoff/xsns_36_mgc3130.ino | 10 +- sonoff/xsns_37_rfsensor.ino | 44 ++--- sonoff/xsns_38_az7798.ino | 6 +- sonoff/xsns_39_max31855.ino | 4 +- sonoff/xsns_40_pn532_i2c.ino | 16 +- sonoff/xsns_41_max44009.ino | 10 +- sonoff/xsns_interface.ino | 12 +- sonoff/zzzz_debug.ino | 8 +- 91 files changed, 919 insertions(+), 915 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 909715904..78200f2d8 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ -/* 6.4.1.11 20190124 +/* 6.4.1.12 20190128 + * Change code use of boolean to bool and byte to uint8_t + * Change code uint8_t flags to bool flags + * + * 6.4.1.11 20190124 * Remove command SetOption14 as it has been superseded by command Interlock * Remove command SetOption63 as it has been superseded by command Interlock * Add command Interlock 0 / 1 / 1,2 3,4 .. to control interlock ON/OFF and add up to 8 relays in 1 to 4 interlock groups (#5014) diff --git a/sonoff/settings.h b/sonoff/settings.h index 99c2ddb26..83a26e311 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -183,21 +183,21 @@ struct SYSCFG { char ota_url[101]; // 017 char mqtt_prefix[3][11]; // 07C uint8_t baudrate; // 09D - byte seriallog_level; // 09E + uint8_t seriallog_level; // 09E uint8_t sta_config; // 09F - byte sta_active; // 0A0 + uint8_t sta_active; // 0A0 char sta_ssid[2][33]; // 0A1 - Keep together with sta_pwd as being copied as one chunck with reset 4/5 char sta_pwd[2][65]; // 0E3 - Keep together with sta_ssid as being copied as one chunck with reset 4/5 char hostname[33]; // 165 char syslog_host[33]; // 186 uint8_t rule_stop; // 1A7 uint16_t syslog_port; // 1A8 - byte syslog_level; // 1AA + uint8_t syslog_level; // 1AA uint8_t webserver; // 1AB - byte weblog_level; // 1AC + uint8_t weblog_level; // 1AC uint8_t mqtt_fingerprint[2][20]; // 1AD - byte free_1D5[20]; // 1D5 Free since 5.12.0e + uint8_t free_1D5[20]; // 1D5 Free since 5.12.0e char mqtt_host[33]; // 1E9 uint16_t mqtt_port; // 20A @@ -282,13 +282,13 @@ struct SYSCFG { uint8_t light_speed; // 4A2 uint8_t light_scheme; // 4A3 uint8_t light_width; // 4A4 - byte knx_GA_registered; // 4A5 Number of Group Address to read + uint8_t knx_GA_registered; // 4A5 Number of Group Address to read uint16_t light_wakeup; // 4A6 - byte knx_CB_registered; // 4A8 Number of Group Address to write + uint8_t knx_CB_registered; // 4A8 Number of Group Address to write char web_password[33]; // 4A9 uint8_t interlock[MAX_INTERLOCKS]; // 4CA char ntp_server[3][33]; // 4CE - byte ina219_mode; // 531 + uint8_t ina219_mode; // 531 uint16_t pulse_timer[MAX_PULSETIMERS]; // 532 uint16_t button_debounce; // 542 uint32_t ip_address[4]; // 544 @@ -307,17 +307,17 @@ struct SYSCFG { uint16_t knx_physsical_addr; // 6B8 (address_t is a uint16_t) uint16_t knx_GA_addr[MAX_KNX_GA]; // 6BA (address_t is a uint16_t) x KNX_max_GA uint16_t knx_CB_addr[MAX_KNX_CB]; // 6CE (address_t is a uint16_t) x KNX_max_CB - byte knx_GA_param[MAX_KNX_GA]; // 6E2 Type of Input (relay changed, button pressed, sensor read <-teleperiod) - byte knx_CB_param[MAX_KNX_CB]; // 6EC Type of Output (set relay, toggle relay, reply sensor value) + uint8_t knx_GA_param[MAX_KNX_GA]; // 6E2 Type of Input (relay changed, button pressed, sensor read <-teleperiod) + uint8_t knx_CB_param[MAX_KNX_CB]; // 6EC Type of Output (set relay, toggle relay, reply sensor value) Mcp230xxCfg mcp230xx_config[16]; // 6F6 uint8_t mcp230xx_int_prio; // 716 - byte free_717[1]; // 717 + uint8_t free_717[1]; // 717 uint16_t mcp230xx_int_timer; // 718 uint8_t rgbwwTable[5]; // 71A - byte free_71F[117]; // 71F + uint8_t free_71F[117]; // 71F uint32_t drivers[3]; // 794 uint32_t monitors; // 7A0 @@ -326,7 +326,7 @@ struct SYSCFG { uint32_t energy_kWhtotal_time; // 7B4 unsigned long weight_item; // 7B8 Weight of one item in gram * 10 - byte free_7BC[2]; // 7BC + uint8_t free_7BC[2]; // 7BC uint16_t weight_max; // 7BE Total max weight in kilogram unsigned long weight_reference; // 7C0 Reference weight in gram @@ -346,7 +346,7 @@ struct RTCRBT { struct RTCMEM { uint16_t valid; // 290 (RTC memory offset 100) - byte oswatch_blocked_loop; // 292 + uint8_t oswatch_blocked_loop; // 292 uint8_t ota_loader; // 293 unsigned long energy_kWhtoday; // 294 unsigned long energy_kWhtotal; // 298 @@ -376,7 +376,7 @@ struct XDRVMAILBOX { uint16_t data_len; uint16_t payload16; int16_t payload; - uint8_t grpflg; + bool grpflg; uint8_t notused; char *topic; char *data; diff --git a/sonoff/settings.ino b/sonoff/settings.ino index ef502d230..c1b84cafa 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -97,7 +97,7 @@ void RtcSettingsLoad(void) RtcSettings.valid = RTC_MEM_VALID; RtcSettings.energy_kWhtoday = Settings.energy_kWhtoday; RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal; - for (byte i = 0; i < MAX_COUNTERS; i++) { + for (uint8_t i = 0; i < MAX_COUNTERS; i++) { RtcSettings.pulse_counter[i] = Settings.pulse_counter[i]; } RtcSettings.power = Settings.power; @@ -106,7 +106,7 @@ void RtcSettingsLoad(void) rtc_settings_crc = GetRtcSettingsCrc(); } -boolean RtcSettingsValid(void) +bool RtcSettingsValid(void) { return (RTC_MEM_VALID == RtcSettings.valid); } @@ -147,7 +147,7 @@ void RtcRebootLoad(void) rtc_reboot_crc = GetRtcRebootCrc(); } -boolean RtcRebootValid(void) +bool RtcRebootValid(void) { return (RTC_MEM_VALID == RtcReboot.valid); } @@ -381,7 +381,7 @@ uint32_t GetSettingsAddress(void) return settings_location * SPI_FLASH_SEC_SIZE; } -void SettingsSave(byte rotate) +void SettingsSave(uint8_t rotate) { /* Save configuration in eeprom or one of 7 slots below * @@ -430,7 +430,7 @@ void SettingsSave(byte rotate) } if (!stop_flash_rotate && rotate) { - for (byte i = 1; i < CFG_ROTATES; i++) { + for (uint8_t i = 1; i < CFG_ROTATES; i++) { ESP.flashEraseSector(settings_location -i); // Delete previous configurations by resetting to 0xFF delay(1); } @@ -457,7 +457,7 @@ void SettingsLoad(void) bool bad_crc = false; settings_location = SETTINGS_LOCATION +1; - for (byte i = 0; i < CFG_ROTATES; i++) { + for (uint8_t i = 0; i < CFG_ROTATES; i++) { settings_location--; ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); ESP.flashRead((settings_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); @@ -495,7 +495,7 @@ void SettingsErase(uint8_t type) _sectorEnd = SETTINGS_LOCATION +5; } - boolean _serialoutput = (LOG_LEVEL_DEBUG_MORE <= seriallog_level); + bool _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); @@ -576,7 +576,7 @@ void SettingsDefaultSet2(void) // Settings.flag.interlock = 0; Settings.interlock[0] = 0xFF; // Legacy support using all relays in one interlock group Settings.module = MODULE; -// for (byte i = 0; i < sizeof(Settings.my_gp); i++) { Settings.my_gp.io[i] = GPIO_NONE; } +// for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { Settings.my_gp.io[i] = GPIO_NONE; } 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])); @@ -591,7 +591,7 @@ void SettingsDefaultSet2(void) Settings.blinkcount = APP_BLINKCOUNT; Settings.ledstate = APP_LEDSTATE; Settings.pulse_timer[0] = APP_PULSETIME; -// for (byte i = 1; i < MAX_PULSETIMERS; i++) { Settings.pulse_timer[i] = 0; } +// for (uint8_t i = 1; i < MAX_PULSETIMERS; i++) { Settings.pulse_timer[i] = 0; } // Serial Settings.baudrate = APP_BAUDRATE / 1200; @@ -631,7 +631,7 @@ void SettingsDefaultSet2(void) Settings.param[P_HOLD_TIME] = KEY_HOLD_TIME; // Default 4 seconds hold time // Switch - for (byte i = 0; i < MAX_SWITCHES; i++) { Settings.switchmode[i] = SWITCH_MODE; } + for (uint8_t i = 0; i < MAX_SWITCHES; i++) { Settings.switchmode[i] = SWITCH_MODE; } // MQTT Settings.flag.mqtt_enabled = MQTT_USE; @@ -665,12 +665,12 @@ void SettingsDefaultSet2(void) char fingerprint[60]; strlcpy(fingerprint, MQTT_FINGERPRINT1, sizeof(fingerprint)); char *p = fingerprint; - for (byte i = 0; i < 20; i++) { + for (uint8_t i = 0; i < 20; i++) { Settings.mqtt_fingerprint[0][i] = strtol(p, &p, 16); } strlcpy(fingerprint, MQTT_FINGERPRINT2, sizeof(fingerprint)); p = fingerprint; - for (byte i = 0; i < 20; i++) { + for (uint8_t i = 0; i < 20; i++) { Settings.mqtt_fingerprint[1][i] = strtol(p, &p, 16); } Settings.tele_period = TELE_PERIOD; @@ -706,17 +706,17 @@ void SettingsDefaultSet2(void) RtcSettings.energy_kWhtotal = 0; // RF Bridge -// for (byte i = 0; i < 17; i++) { Settings.rf_code[i][0] = 0; } +// for (uint8_t i = 0; i < 17; i++) { Settings.rf_code[i][0] = 0; } memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); // Domoticz Settings.domoticz_update_timer = DOMOTICZ_UPDATE_TIMER; -// for (byte i = 0; i < MAX_DOMOTICZ_IDX; i++) { +// for (uint8_t i = 0; i < MAX_DOMOTICZ_IDX; i++) { // Settings.domoticz_relay_idx[i] = 0; // Settings.domoticz_key_idx[i] = 0; // Settings.domoticz_switch_idx[i] = 0; // } -// for (byte i = 0; i < MAX_DOMOTICZ_SNS_IDX; i++) { +// for (uint8_t i = 0; i < MAX_DOMOTICZ_SNS_IDX; i++) { // Settings.domoticz_sensor_idx[i] = 0; // } @@ -731,7 +731,7 @@ void SettingsDefaultSet2(void) // Rules // Settings.rule_enabled = 0; // Settings.rule_once = 0; -// for (byte i = 1; i < MAX_RULE_SETS; i++) { Settings.rules[i][0] = '\0'; } +// for (uint8_t i = 1; i < MAX_RULE_SETS; i++) { Settings.rules[i][0] = '\0'; } Settings.flag2.calc_resolution = CALC_RESOLUTION; // Home Assistant @@ -749,7 +749,7 @@ void SettingsDefaultSet2(void) //Settings.flag.decimal_text = 0; Settings.pwm_frequency = PWM_FREQ; Settings.pwm_range = PWM_RANGE; - for (byte i = 0; i < MAX_PWMS; i++) { + for (uint8_t i = 0; i < MAX_PWMS; i++) { Settings.light_color[i] = 255; // Settings.pwm_value[i] = 0; } @@ -778,8 +778,8 @@ void SettingsDefaultSet2(void) 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++) { + for (uint8_t j = 0; j < 3; j++) { + for (uint8_t i = 0; i < strlen(Settings.ntp_server[j]); i++) { if (Settings.ntp_server[j][i] == ',') { Settings.ntp_server[j][i] = '.'; } @@ -792,7 +792,7 @@ void SettingsDefaultSet2(void) Settings.button_debounce = KEY_DEBOUNCE_TIME; Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; - for (byte j = 0; j < 5; j++) { + for (uint8_t j = 0; j < 5; j++) { Settings.rgbwwTable[j] = 255; } @@ -873,7 +873,7 @@ void SettingsDelta(void) if (Settings.version != VERSION) { // Fix version dependent changes if (Settings.version < 0x05050000) { - for (byte i = 0; i < 17; i++) { Settings.rf_code[i][0] = 0; } + for (uint8_t i = 0; i < 17; i++) { Settings.rf_code[i][0] = 0; } memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); } if (Settings.version < 0x05080000) { @@ -895,12 +895,12 @@ void SettingsDelta(void) Settings.altitude = 0; } if (Settings.version < 0x0508000B) { - for (byte i = 0; i < sizeof(Settings.my_gp); i++) { // Move GPIO_LEDs + for (uint8_t i = 0; i < sizeof(Settings.my_gp); 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 + for (uint8_t 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; } @@ -931,7 +931,7 @@ void SettingsDelta(void) char fingerprint[60]; memcpy(fingerprint, Settings.mqtt_fingerprint, sizeof(fingerprint)); char *p = fingerprint; - for (byte i = 0; i < 20; i++) { + for (uint8_t i = 0; i < 20; i++) { Settings.mqtt_fingerprint[0][i] = strtol(p, &p, 16); Settings.mqtt_fingerprint[1][i] = Settings.mqtt_fingerprint[0][i]; } @@ -966,7 +966,7 @@ void SettingsDelta(void) SettingsDefaultSet_5_13_1c(); } if (Settings.version < 0x050E0002) { - for (byte i = 1; i < MAX_RULE_SETS; i++) { Settings.rules[i][0] = '\0'; } + for (uint8_t i = 1; i < MAX_RULE_SETS; i++) { Settings.rules[i][0] = '\0'; } Settings.rule_enabled = Settings.flag.mqtt_serial_raw; // Was rules_enabled until 5.14.0b Settings.rule_once = Settings.flag.pressure_conversion; // Was rules_once until 5.14.0b } @@ -975,14 +975,14 @@ void SettingsDelta(void) Settings.cfg_crc = GetSettingsCrc(); } if (Settings.version < 0x06000002) { - for (byte i = 0; i < MAX_SWITCHES; i++) { + for (uint8_t i = 0; i < MAX_SWITCHES; i++) { if (i < 4) { Settings.switchmode[i] = Settings.interlock[i]; } else { Settings.switchmode[i] = SWITCH_MODE; } } - for (byte i = 0; i < sizeof(Settings.my_gp); i++) { + for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { if (Settings.my_gp.io[i] >= GPIO_SWT5) { // Move up from GPIO_SWT5 to GPIO_KEY1 Settings.my_gp.io[i] += 4; } @@ -1001,7 +1001,7 @@ void SettingsDelta(void) Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; } if (Settings.version < 0x0602010A) { - for (byte j = 0; j < 5; j++) { + for (uint8_t j = 0; j < 5; j++) { Settings.rgbwwTable[j] = 255; } } @@ -1025,7 +1025,7 @@ void SettingsDelta(void) } if (Settings.version < 0x0604010B) { Settings.interlock[0] = 0xFF; // Legacy support using all relays in one interlock group - for (byte i = 1; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } + for (uint8_t i = 1; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } } Settings.version = VERSION; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index b50544a7d..936f7930e 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -134,39 +134,39 @@ uint16_t seriallog_timer = 0; // Timer to disable Seriallog uint16_t syslog_timer = 0; // Timer to re-enable syslog_level int16_t save_data_counter; // Counter and flag for config save to Flash RulesBitfield rules_flag; // Rule state flags (16 bits) -uint8_t serial_local = 0; // Handle serial locally; -uint8_t fallback_topic_flag = 0; // Use Topic or FallbackTopic uint8_t state_250mS = 0; // State 250msecond per second flag 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 -uint8_t interlock_mutex = 0; // Interlock power command pending uint8_t sleep; // Current copy of Settings.sleep -uint8_t stop_flash_rotate = 0; // Allow flash configuration rotation -uint8_t blinkstate = 0; // LED state uint8_t blinkspeed = 1; // LED blink rate uint8_t pin[GPIO_MAX]; // Possible pin configurations 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 counter_no_pullup = 0; // Counter input pullup flag (1 = No pullup) -uint8_t dht_flg = 0; // DHT configured uint8_t energy_flg = 0; // Energy monitor configured -uint8_t i2c_flg = 0; // I2C configured -uint8_t spi_flg = 0; // SPI configured -uint8_t soft_spi_flg = 0; // Software SPI configured uint8_t light_type = 0; // Light types -uint8_t ntp_force_sync = 0; // Force NTP sync -byte serial_in_byte; // Received byte -byte ota_retry_counter = OTA_ATTEMPTS; // OTA retry counter -byte web_log_index = 1; // Index in Web log buffer (should never be 0) -byte reset_web_log_flag = 0; // Reset web console log -byte devices_present = 0; // Max number of devices supported -byte seriallog_level; // Current copy of Settings.seriallog_level -byte syslog_level; // Current copy of Settings.syslog_level -//byte mdns_delayed_start = 0; // mDNS delayed start -boolean latest_uptime_flag = true; // Signal latest uptime -boolean pwm_present = false; // Any PWM channel configured with SetOption15 0 +uint8_t serial_in_byte; // Received byte +uint8_t ota_retry_counter = OTA_ATTEMPTS; // OTA retry counter +uint8_t web_log_index = 1; // Index in Web log buffer (should never be 0) +uint8_t devices_present = 0; // Max number of devices supported +uint8_t seriallog_level; // Current copy of Settings.seriallog_level +uint8_t syslog_level; // Current copy of Settings.syslog_level +//uint8_t mdns_delayed_start = 0; // mDNS delayed start +bool serial_local = false; // Handle serial locally; +bool fallback_topic_flag = false; // Use Topic or FallbackTopic +bool backlog_mutex = false; // Command backlog pending +bool interlock_mutex = false; // Interlock power command pending +bool stop_flash_rotate = false; // Allow flash configuration rotation +bool blinkstate = false; // LED state +bool latest_uptime_flag = true; // Signal latest uptime +bool pwm_present = false; // Any PWM channel configured with SetOption15 0 +bool dht_flg = false; // DHT configured +bool i2c_flg = false; // I2C configured +bool spi_flg = false; // SPI configured +bool soft_spi_flg = false; // Software SPI configured +bool ntp_force_sync = false; // Force NTP sync +bool reset_web_log_flag = false; // Reset web console log myio my_module; // Active copy of Module GPIOs (17 x 8 bits) gpio_flag my_module_flag; // Active copy of Module GPIO flags StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits) @@ -214,7 +214,7 @@ char* Format(char* output, const char* input, int size) } } } - if (!digits) strlcpy(output, input, size); + if (!digits) { strlcpy(output, input, size); } return output; } @@ -232,7 +232,7 @@ char* GetOtaUrl(char *otaurl, size_t otaurl_size) return otaurl; } -char* GetTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic) +char* GetTopic_P(char *stopic, uint8_t prefix, char *topic, const char* subtopic) { /* prefix 0 = Cmnd prefix 1 = Stat @@ -256,7 +256,7 @@ char* GetTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic) 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++) { + for (uint8_t i = 0; i < 3; i++) { if ('\0' == Settings.mqtt_prefix[i][0]) { snprintf_P(Settings.mqtt_prefix[i], sizeof(Settings.mqtt_prefix[i]), kPrefixes[i]); } @@ -275,14 +275,14 @@ char* GetTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic) return stopic; } -char* GetFallbackTopic_P(char *stopic, byte prefix, const char* subtopic) +char* GetFallbackTopic_P(char *stopic, uint8_t prefix, const char* subtopic) { return GetTopic_P(stopic, prefix +4, NULL, subtopic); } -char* GetStateText(byte state) +char* GetStateText(uint8_t state) { - if (state > 3) state = 1; + if (state > 3) { state = 1; } return Settings.state_text[state]; } @@ -300,7 +300,7 @@ void SetLatchingRelay(power_t lpower, uint8_t state) latching_relay_pulse = 2; // max 200mS (initiated by stateloop()) } - for (byte i = 0; i < devices_present; i++) { + for (uint8_t i = 0; i < devices_present; i++) { uint8_t port = (i << 1) + ((latching_power >> i) &1); if (pin[GPIO_REL1 +port] < 99) { digitalWrite(pin[GPIO_REL1 +port], bitRead(rel_inverted, port) ? !state : state); @@ -320,10 +320,10 @@ void SetDevicePower(power_t rpower, int source) } if (Settings.flag.interlock) { // Allow only one or no relay set - for (byte i = 0; i < MAX_INTERLOCKS; i++) { + for (uint8_t i = 0; i < MAX_INTERLOCKS; i++) { power_t mask = 1; uint8_t count = 0; - for (byte j = 0; j < devices_present; j++) { + for (uint8_t j = 0; j < devices_present; j++) { if ((Settings.interlock[i] & mask) && (rpower & mask)) { count++; } mask <<= 1; } @@ -355,7 +355,7 @@ void SetDevicePower(power_t rpower, int source) SetLatchingRelay(rpower, 1); } else { - for (byte i = 0; i < devices_present; i++) { + for (uint8_t i = 0; i < devices_present; i++) { state = rpower &1; if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) { digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? !state : state); @@ -367,7 +367,7 @@ void SetDevicePower(power_t rpower, int source) void SetLedPower(uint8_t state) { - if (state) state = 1; + if (state) { state = 1; } uint8_t led_pin = 0; if (pin[GPIO_LED2] < 99) { led_pin = 1; } @@ -376,7 +376,7 @@ void SetLedPower(uint8_t state) void SetLedLink(uint8_t state) { - if (state) state = 1; + if (state) { state = 1; } digitalWrite(pin[GPIO_LED1], (bitRead(led_inverted, 0)) ? !state : state); } @@ -399,7 +399,7 @@ uint8_t GetFanspeed(void) void SetFanspeed(uint8_t fanspeed) { - for (byte i = 0; i < MAX_FAN_SPEED -1; i++) { + for (uint8_t i = 0; i < MAX_FAN_SPEED -1; i++) { uint8_t state = kIFan02Speed[fanspeed][i]; // uint8_t state = pgm_read_byte(kIFan02Speed +(speed *3) +i); ExecuteCommandPower(i +2, state, SRC_IGNORE); // Use relay 2, 3 and 4 @@ -428,7 +428,7 @@ uint16_t GetPulseTimer(uint8_t index) /********************************************************************************************/ -void MqttDataHandler(char* topic, byte* data, unsigned int data_len) +void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) { char *str; @@ -450,10 +450,10 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) char stemp1[TOPSZ]; char *p; char *type = NULL; - byte jsflg = 0; - byte lines = 1; - uint8_t grpflg = 0; -// uint8_t user_append_index = 0; + uint8_t lines = 1; + bool jsflg = false; + bool grpflg = false; +// bool user_append_index = false; uint16_t i = 0; uint16_t index; uint32_t address; @@ -462,7 +462,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) strlcpy(topicBuf, topic, sizeof(topicBuf)); for (i = 0; i < data_len; i++) { - if (!isspace(data[i])) break; + if (!isspace(data[i])) { break; } } data_len -= i; memcpy(dataBuf, data +i, sizeof(dataBuf)); @@ -473,9 +473,9 @@ void MqttDataHandler(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); -// if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) Serial.println(dataBuf); +// if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) { Serial.println(dataBuf); } - if (XdrvMqttData(topicBuf, sizeof(topicBuf), dataBuf, sizeof(dataBuf))) return; + if (XdrvMqttData(topicBuf, sizeof(topicBuf), dataBuf, sizeof(dataBuf))) { return; } grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != NULL); @@ -495,7 +495,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } if (i < strlen(type)) { index = atoi(type +i); -// user_append_index = 1; +// user_append_index = true; } type[i] = '\0'; } @@ -506,9 +506,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if (type != NULL) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); - if (Settings.ledstate &0x02) blinks++; + if (Settings.ledstate &0x02) { blinks++; } - if (!strcmp(dataBuf,"?")) data_len = 0; + if (!strcmp(dataBuf,"?")) { data_len = 0; } int16_t payload = -99; // No payload uint16_t payload16 = 0; long payload32 = strtol(dataBuf, &p, 10); @@ -571,10 +571,10 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, bl_delay); } else if ((CMND_POWER == command_code) && (index > 0) && (index <= devices_present)) { - if ((payload < 0) || (payload > 4)) payload = 9; + if ((payload < 0) || (payload > 4)) { payload = 9; } // Settings.flag.device_index_enable = user_append_index; ExecuteCommandPower(index, payload, SRC_IGNORE); - fallback_topic_flag = 0; + fallback_topic_flag = false; return; } else if ((CMND_FANSPEED == command_code) && (SONOFF_IFAN02 == Settings.module)) { @@ -596,7 +596,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) else if (CMND_STATUS == command_code) { if ((payload < 0) || (payload > MAX_STATUS)) payload = 99; PublishStatus(payload); - fallback_topic_flag = 0; + fallback_topic_flag = false; return; } else if (CMND_STATE == command_code) { @@ -664,7 +664,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if ((payload >= POWER_ALL_OFF) && (payload <= POWER_ALL_OFF_PULSETIME_ON)) { Settings.poweronstate = payload; if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - for (byte i = 1; i <= devices_present; i++) { + for (uint8_t i = 1; i <= devices_present; i++) { ExecuteCommandPower(i, POWER_ON, SRC_IGNORE); } } @@ -718,8 +718,8 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } } else if ((CMND_SETOPTION == command_code) && (index < 82)) { - byte ptype; - byte pindex; + uint8_t ptype; + uint8_t pindex; if (index <= 31) { // SetOption0 .. 31 = Settings.flag ptype = 0; pindex = index; // 0 .. 31 @@ -860,7 +860,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) Settings.last_module = Settings.module; Settings.module = payload; if (Settings.last_module != payload) { - for (byte i = 0; i < sizeof(Settings.my_gp); i++) { + for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { Settings.my_gp.io[i] = GPIO_NONE; } } @@ -869,18 +869,18 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.module +1, ModuleName().c_str()); } else if (CMND_MODULES == command_code) { - for (byte i = 0; i < MAXMODULE; i++) { + for (uint8_t i = 0; i < MAXMODULE; i++) { if (!jsflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULES "%d\":["), lines); } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); } - jsflg = 1; + jsflg = true; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, i +1, AnyModuleName(i).c_str()); if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == MAXMODULE -1)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]}"), mqtt_data); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); - jsflg = 0; + jsflg = false; lines++; } } @@ -891,12 +891,12 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) ModuleGpios(&cmodule); if ((GPIO_USER == ValidGPIO(index, cmodule.io[index])) && (payload >= 0) && (payload < GPIO_SENSOR_END)) { bool present = false; - for (byte i = 0; i < sizeof(kGpioNiceList); i++) { + for (uint8_t i = 0; i < sizeof(kGpioNiceList); i++) { uint8_t midx = pgm_read_byte(kGpioNiceList + i); if (midx == payload) { present = true; } } if (present) { - for (byte i = 0; i < sizeof(Settings.my_gp); i++) { + for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { if ((GPIO_USER == ValidGPIO(i, cmodule.io[i])) && (Settings.my_gp.io[i] == payload)) { Settings.my_gp.io[i] = GPIO_NONE; } @@ -906,10 +906,10 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); - for (byte i = 0; i < sizeof(Settings.my_gp); i++) { + for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { if (jsflg) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); - jsflg = 1; + jsflg = true; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_GPIO "%d\":\"%d (%s)\""), mqtt_data, i, Settings.my_gp.io[i], GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_gp.io[i], kSensorNames)); } @@ -924,7 +924,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) myio cmodule; ModuleGpios(&cmodule); uint8_t midx; - for (byte i = 0; i < sizeof(kGpioNiceList); i++) { + for (uint8_t i = 0; i < sizeof(kGpioNiceList); i++) { midx = pgm_read_byte(kGpioNiceList + i); if (!GetUsedInModule(midx, cmodule.io)) { @@ -933,12 +933,12 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); } - jsflg = 1; + jsflg = true; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)); if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]}"), mqtt_data); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); - jsflg = 0; + jsflg = false; lines++; } } @@ -965,7 +965,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) else if (CMND_PWMRANGE == command_code) { if ((1 == payload) || ((payload > 254) && (payload < 1024))) { Settings.pwm_range = (1 == payload) ? PWM_RANGE : payload; - for (byte i = 0; i < MAX_PWMS; i++) { + for (uint8_t i = 0; i < MAX_PWMS; i++) { if (Settings.pwm_value[i] > Settings.pwm_range) { Settings.pwm_value[i] = Settings.pwm_range; } @@ -1090,7 +1090,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if (Settings.ntp_server[index -1][i] == ',') Settings.ntp_server[index -1][i] = '.'; } // restart_flag = 2; // Issue #3890 - ntp_force_sync = 1; + ntp_force_sync = true; } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.ntp_server[index -1]); } @@ -1175,7 +1175,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if (max_relays > 1) { // Only interlock with more than 1 relay if (data_len > 0) { if (strstr(dataBuf, ",")) { // Interlock entry - for (byte i = 0; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } // Reset current interlocks + for (uint8_t i = 0; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } // Reset current interlocks char *group; char *q; uint8_t group_index = 0; @@ -1194,9 +1194,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } group_index++; } - for (byte i = 0; i < group_index; i++) { + for (uint8_t i = 0; i < group_index; i++) { uint8_t minimal_bits = 0; - for (byte j = 0; j < max_relays; j++) { + for (uint8_t j = 0; j < max_relays; j++) { if (bitRead(Settings.interlock[i], j)) { minimal_bits++; } } if (minimal_bits < 2) { Settings.interlock[i] = 0; } // Discard single relay as interlock @@ -1210,13 +1210,13 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_INTERLOCK "\":\"%s\",\"" D_JSON_GROUPS "\":\""), GetStateText(Settings.flag.interlock)); uint8_t anygroup = 0; - for (byte i = 0; i < MAX_INTERLOCKS; i++) { + for (uint8_t i = 0; i < MAX_INTERLOCKS; i++) { if (Settings.interlock[i]) { anygroup++; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s"), mqtt_data, (anygroup > 1) ? " " : ""); uint8_t anybit = 0; power_t mask = 1; - for (byte j = 0; j < max_relays; j++) { + for (uint8_t j = 0; j < max_relays; j++) { if (Settings.interlock[i] & mask) { anybit++; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (anybit > 1) ? "," : "", j +1); @@ -1226,7 +1226,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } } if (!anygroup) { - for (byte j = 1; j <= max_relays; j++) { + for (uint8_t j = 1; j <= max_relays; j++) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (j > 1) ? "," : "", j); } } @@ -1277,7 +1277,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } else { Settings.timezone = 99; } - ntp_force_sync = 1; + ntp_force_sync = true; } if (99 == Settings.timezone) { snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.timezone); @@ -1312,7 +1312,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) value = strtol(p, &p, 10); tpos++; // Next parameter } - ntp_force_sync = 1; + ntp_force_sync = true; } else { if (0 == payload) { if (0 == ts) { @@ -1321,7 +1321,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) SettingsResetDst(); } } - ntp_force_sync = 1; + ntp_force_sync = true; } } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d}}"), @@ -1374,12 +1374,12 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) type = (char*)topicBuf; } if (mqtt_data[0] != '\0') MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); - fallback_topic_flag = 0; + fallback_topic_flag = false; } /********************************************************************************************/ -boolean SendKey(byte key, byte device, byte state) +bool SendKey(uint8_t key, uint8_t device, uint8_t state) { // key 0 = button_topic // key 1 = switch_topic @@ -1392,7 +1392,7 @@ boolean SendKey(byte key, byte device, byte state) char stopic[TOPSZ]; char scommand[CMDSZ]; char key_topic[sizeof(Settings.button_topic)]; - boolean result = false; + bool result = false; char *tmp = (key) ? Settings.switch_topic : Settings.button_topic; Format(key_topic, tmp, sizeof(key_topic)); @@ -1426,7 +1426,7 @@ boolean SendKey(byte key, byte device, byte state) return result; } -void ExecuteCommandPower(byte device, byte state, int source) +void ExecuteCommandPower(uint8_t device, uint8_t state, int source) { // device = Relay number 1 and up // state 0 = Relay Off @@ -1463,10 +1463,10 @@ void ExecuteCommandPower(byte device, byte state, int source) } if (Settings.flag.interlock && !interlock_mutex) { // Clear all but masked relay in interlock group - interlock_mutex = 1; - for (byte i = 0; i < MAX_INTERLOCKS; i++) { + interlock_mutex = true; + for (uint8_t i = 0; i < MAX_INTERLOCKS; i++) { if (Settings.interlock[i] & mask) { // Find interlock group - for (byte j = 0; j < devices_present; j++) { + for (uint8_t j = 0; j < devices_present; j++) { power_t imask = 1 << j; if ((Settings.interlock[i] & imask) && (power & imask) && (mask != imask)) { ExecuteCommandPower(j +1, POWER_OFF, SRC_IGNORE); @@ -1476,7 +1476,7 @@ void ExecuteCommandPower(byte device, byte state, int source) break; // An interlocked relay is only present in one group so quit } } - interlock_mutex = 0; + interlock_mutex = false; } switch (state) { @@ -1517,7 +1517,7 @@ void ExecuteCommandPower(byte device, byte state, int source) return; } else if (POWER_BLINK_STOP == state) { - byte flag = (blink_mask & mask); + uint8_t flag = (blink_mask & mask); blink_mask &= (POWER_MASK ^ mask); // Clear device mask MqttPublishPowerBlinkState(device); if (flag) ExecuteCommandPower(device, (blink_powersave >> (device -1))&1, SRC_IGNORE); // Restore state @@ -1530,7 +1530,7 @@ void StopAllPowerBlink(void) { power_t mask; - for (byte i = 1; i <= devices_present; i++) { + for (uint8_t i = 1; i <= devices_present; i++) { mask = 1 << (i -1); if (blink_mask & mask) { blink_mask &= (POWER_MASK ^ mask); // Clear device mask @@ -1553,13 +1553,13 @@ void ExecuteCommand(char *cmnd, int source) token = strtok(cmnd, " "); if (token != NULL) { start = strrchr(token, '/'); // Skip possible cmnd/sonoff/ preamble - if (start) token = start +1; + if (start) { token = start +1; } } snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == NULL) ? "" : token); token = strtok(NULL, ""); // 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 - MqttDataHandler(stopic, (byte*)svalue, strlen(svalue)); + MqttDataHandler(stopic, (uint8_t*)svalue, strlen(svalue)); } void PublishStatus(uint8_t payload) @@ -1569,20 +1569,20 @@ void PublishStatus(uint8_t payload) char stemp2[MAX_SWITCHES * 3]; // Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX - if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) option++; // TELE + if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) { option++; } // TELE - if ((!Settings.flag.mqtt_enabled) && (6 == payload)) payload = 99; - if (!energy_flg && (9 == payload)) payload = 99; + if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } + if (!energy_flg && (9 == payload)) { payload = 99; } if ((0 == payload) || (99 == payload)) { uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; if (SONOFF_IFAN02 == Settings.module) { maxfn = 1; } stemp[0] = '\0'; - for (byte i = 0; i < maxfn; i++) { + for (uint8_t i = 0; i < maxfn; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%s%s\"%s\"" ), stemp, (i > 0 ? "," : ""), Settings.friendlyname[i]); } stemp2[0] = '\0'; - for (byte i = 0; i < MAX_SWITCHES; i++) { + for (uint8_t i = 0; i < MAX_SWITCHES; i++) { snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%d" ), stemp2, (i > 0 ? "," : ""), Settings.switchmode[i]); } 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_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), @@ -1675,7 +1675,7 @@ void MqttShowPWMState(void) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_PWM "\":{"), mqtt_data); bool first = true; - for (byte i = 0; i < MAX_PWMS; i++) { + for (uint8_t 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, Settings.pwm_value[i]); first = false; @@ -1698,7 +1698,7 @@ void MqttShowState(void) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u"), mqtt_data, GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), sleep, loop_load_avg); - for (byte i = 0; i < devices_present; i++) { + for (uint8_t i = 0; i < devices_present; i++) { if (i == light_device -1) { LightState(1); } else { @@ -1719,22 +1719,22 @@ void MqttShowState(void) mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI())); } -boolean MqttShowSensor(void) +bool MqttShowSensor(void) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\""), mqtt_data, GetDateAndTime(DT_LOCAL).c_str()); int json_data_start = strlen(mqtt_data); - for (byte i = 0; i < MAX_SWITCHES; i++) { + for (uint8_t i = 0; i < MAX_SWITCHES; i++) { #ifdef USE_TM1638 if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { #else if (pin[GPIO_SWT1 +i] < 99) { #endif // USE_TM1638 - boolean swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); + bool 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_JSON_SWITCH "%d\":\"%s\""), mqtt_data, i +1, GetStateText(swm ^ SwitchLastState(i))); } } XsnsCall(FUNC_JSON_APPEND); - boolean json_data_available = (strlen(mqtt_data) - json_data_start); + bool json_data_available = (strlen(mqtt_data) - json_data_start); if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE))) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), mqtt_data, PressureUnit().c_str()); } @@ -1839,7 +1839,7 @@ void Every100mSeconds(void) if (!latching_relay_pulse) SetLatchingRelay(0, 0); } - for (byte i = 0; i < MAX_PULSETIMERS; i++) { + for (uint8_t i = 0; i < MAX_PULSETIMERS; i++) { if (pulse_timer[i] != 0L) { // Timer active? if (TimeReached(pulse_timer[i])) { // Timer finished? pulse_timer[i] = 0L; // Turn off this timer @@ -1865,9 +1865,9 @@ void Every100mSeconds(void) // Backlog if (TimeReached(backlog_delay)) { if ((backlog_pointer != backlog_index) && !backlog_mutex) { - backlog_mutex = 1; + backlog_mutex = true; ExecuteCommand((char*)backlog[backlog_pointer].c_str(), SRC_BACKLOG); - backlog_mutex = 0; + backlog_mutex = false; backlog_pointer++; if (backlog_pointer >= MAX_BACKLOG) { backlog_pointer = 0; } } @@ -1898,7 +1898,7 @@ void Every250mSeconds(void) } if (blinks || restart_flag || ota_state_flag) { if (restart_flag || ota_state_flag) { // Overrule blinks and keep led lit - blinkstate = 1; // Stay lit + blinkstate = true; // Stay lit } else { blinkspeed--; if (!blinkspeed) { @@ -1917,7 +1917,7 @@ void Every250mSeconds(void) } } else if (Settings.ledstate &1) { - boolean tstate = power; + bool tstate = power; if ((SONOFF_TOUCH == Settings.module) || (SONOFF_T11 == Settings.module) || (SONOFF_T12 == Settings.module) || (SONOFF_T13 == Settings.module)) { tstate = (!power) ? 1 : 0; // As requested invert signal for Touch devices to find them in the dark } @@ -1958,7 +1958,7 @@ void Every250mSeconds(void) char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it char *pch = strrchr((bch != NULL) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin char *ech = strrchr((bch != NULL) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin - if (!pch) pch = ech; + if (!pch) { pch = ech; } if (pch) { mqtt_data[pch - mqtt_data] = '\0'; char *ech = strrchr(Settings.ota_url, '.'); // Change from filename.bin into filename-minimal.bin @@ -2008,7 +2008,7 @@ void Every250mSeconds(void) if (save_data_counter <= 0) { if (Settings.flag.save_state) { power_t mask = POWER_MASK; - for (byte i = 0; i < MAX_PULSETIMERS; i++) { + for (uint8_t i = 0; i < MAX_PULSETIMERS; i++) { if ((Settings.pulse_timer[i] > 0) && (Settings.pulse_timer[i] < 30)) { // 3 seconds mask &= ~(1 << i); } @@ -2079,18 +2079,18 @@ void ArduinoOTAInit(void) { ArduinoOTA.setPort(8266); ArduinoOTA.setHostname(my_hostname); - if (Settings.web_password[0] !=0) ArduinoOTA.setPassword(Settings.web_password); + if (Settings.web_password[0] !=0) { ArduinoOTA.setPassword(Settings.web_password); } ArduinoOTA.onStart([]() { SettingsSave(1); // Free flash for OTA update #ifdef USE_WEBSERVER - if (Settings.webserver) StopWebserver(); + if (Settings.webserver) { StopWebserver(); } #endif // USE_WEBSERVER #ifdef USE_ARILUX_RF AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine #endif // USE_ARILUX_RF - if (Settings.flag.mqtt_enabled) MqttDisconnect(); + if (Settings.flag.mqtt_enabled) { MqttDisconnect(); } snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Arduino OTA " D_UPLOAD_STARTED)); AddLog(LOG_LEVEL_INFO); arduino_ota_triggered = true; @@ -2103,7 +2103,7 @@ void ArduinoOTAInit(void) if ((LOG_LEVEL_DEBUG <= seriallog_level)) { arduino_ota_progress_dot_count++; Serial.printf("."); - if (!(arduino_ota_progress_dot_count % 80)) Serial.println(); + if (!(arduino_ota_progress_dot_count % 80)) { Serial.println(); } } }); @@ -2115,7 +2115,7 @@ void ArduinoOTAInit(void) */ char error_str[100]; - if ((LOG_LEVEL_DEBUG <= seriallog_level) && arduino_ota_progress_dot_count) Serial.println(); + if ((LOG_LEVEL_DEBUG <= seriallog_level) && arduino_ota_progress_dot_count) { Serial.println(); } switch (error) { case OTA_BEGIN_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_2), sizeof(error_str)); break; case OTA_RECEIVE_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_5), sizeof(error_str)); break; @@ -2130,7 +2130,7 @@ void ArduinoOTAInit(void) ArduinoOTA.onEnd([]() { - if ((LOG_LEVEL_DEBUG <= seriallog_level)) Serial.println(); + if ((LOG_LEVEL_DEBUG <= seriallog_level)) { Serial.println(); } snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Arduino OTA " D_SUCCESSFUL ". " D_RESTARTING)); AddLog(LOG_LEVEL_INFO); EspRestart(); @@ -2210,7 +2210,7 @@ void SerialInput(void) else if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) { serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed - seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (byte)LOG_LEVEL_INFO : Settings.seriallog_level; + seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)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, SRC_SERIAL); @@ -2254,7 +2254,7 @@ void GpioInit(void) myio def_gp; ModuleGpios(&def_gp); - for (byte i = 0; i < sizeof(Settings.my_gp); i++) { + for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { if (Settings.my_gp.io[i] > GPIO_NONE) { my_module.io[i] = Settings.my_gp.io[i]; } @@ -2264,10 +2264,10 @@ void GpioInit(void) } my_module_flag = ModuleFlag(); - for (byte i = 0; i < GPIO_MAX; i++) { + for (uint8_t i = 0; i < GPIO_MAX; i++) { pin[i] = 99; } - for (byte i = 0; i < sizeof(my_module.io); i++) { + for (uint8_t i = 0; i < sizeof(my_module.io); i++) { mpin = ValidGPIO(i, my_module.io[i]); // snprintf_P(log_data, sizeof(log_data), PSTR("DBG: gpio pin %d, mpin %d"), i, mpin); @@ -2310,7 +2310,7 @@ void GpioInit(void) #ifdef USE_DHT else if ((mpin >= GPIO_DHT11) && (mpin <= GPIO_SI7021)) { if (DhtSetup(i, mpin)) { - dht_flg = 1; + dht_flg = true; mpin = GPIO_DHT11; } else { mpin = 0; @@ -2329,7 +2329,7 @@ void GpioInit(void) #ifdef USE_SPI spi_flg = ((((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CS] > 14)) || (pin[GPIO_SPI_CS] < 12)) || (((pin[GPIO_SPI_DC] < 99) && (pin[GPIO_SPI_DC] > 14)) || (pin[GPIO_SPI_DC] < 12))); if (spi_flg) { - for (byte i = 0; i < GPIO_MAX; i++) { + for (uint8_t i = 0; i < GPIO_MAX; i++) { if ((pin[i] >= 12) && (pin[i] <=14)) pin[i] = 99; } my_module.io[12] = GPIO_SPI_MISO; @@ -2344,15 +2344,15 @@ void GpioInit(void) #ifdef USE_I2C i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); - if (i2c_flg) Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]); + if (i2c_flg) { Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]); } #endif // USE_I2C devices_present = 1; light_type = LT_BASIC; // Use basic PWM control if SetOption15 = 0 if (Settings.flag.pwm_control) { - 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 + for (uint8_t i = 0; i < MAX_PWMS; i++) { + if (pin[GPIO_PWM1 +i] < 99) { light_type++; } // Use Dimmer/Color control for all PWM as SetOption15 = 1 } } @@ -2392,8 +2392,8 @@ void GpioInit(void) light_type = LT_RGBWC; } else { - if (!light_type) devices_present = 0; - for (byte i = 0; i < MAX_RELAYS; i++) { + if (!light_type) { devices_present = 0; } + for (uint8_t i = 0; i < MAX_RELAYS; i++) { if (pin[GPIO_REL1 +i] < 99) { pinMode(pin[GPIO_REL1 +i], OUTPUT); devices_present++; @@ -2405,7 +2405,7 @@ void GpioInit(void) } } - for (byte i = 0; i < MAX_LEDS; i++) { + for (uint8_t 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)); @@ -2423,7 +2423,7 @@ void GpioInit(void) } #endif // USE_WS2812 if (!light_type) { - for (byte i = 0; i < MAX_PWMS; i++) { // Basic PWM control only + for (uint8_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only if (pin[GPIO_PWM1 +i] < 99) { pwm_present = true; pinMode(pin[GPIO_PWM1 +i], OUTPUT); @@ -2488,7 +2488,7 @@ void setup(void) if (RtcReboot.fast_reboot_count > 1) { // Restart twice Settings.flag3.user_esp8285_enable = 0; // Disable ESP8285 Generic GPIOs interfering with flash SPI if (RtcReboot.fast_reboot_count > 2) { // Restart 3 times - for (byte i = 0; i < MAX_RULE_SETS; i++) { + for (uint8_t i = 0; i < MAX_RULE_SETS; i++) { if (bitRead(Settings.rule_stop, i)) { bitWrite(Settings.rule_enabled, i, 0); // Disable rules causing boot loop } @@ -2498,7 +2498,7 @@ void setup(void) Settings.rule_enabled = 0; // Disable all rules } if (RtcReboot.fast_reboot_count > 4) { // Restarted 5 times - for (byte i = 0; i < sizeof(Settings.my_gp); i++) { + for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors } } @@ -2525,7 +2525,7 @@ void setup(void) WifiConnect(); - if (MOTOR == Settings.module) Settings.poweronstate = POWER_ALL_ON; // Needs always on else in limbo! + if (MOTOR == Settings.module) { Settings.poweronstate = POWER_ALL_ON; } // Needs always on else in limbo! if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { SetDevicePower(1, SRC_RESTART); } else { @@ -2562,7 +2562,7 @@ void setup(void) } // Issue #526 and #909 - for (byte i = 0; i < devices_present; i++) { + for (uint8_t 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)); } @@ -2623,7 +2623,7 @@ void loop(void) XsnsCall(FUNC_EVERY_250_MSECOND); } - if (!serial_local) SerialInput(); + if (!serial_local) { SerialInput(); } #ifdef USE_ARDUINO_OTA MDNS.update(); diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index ff290a84c..83db36b91 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0604010B +#define VERSION 0x0604010C #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index 148ae8783..91d1f7633 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -31,7 +31,7 @@ Ticker tickerOSWatch; #define OSWATCH_RESET_TIME 120 static unsigned long oswatch_last_loop_time; -byte oswatch_blocked_loop = 0; +uint8_t oswatch_blocked_loop = 0; #ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception //void OsWatchTicker() ICACHE_RAM_ATTR; @@ -84,7 +84,7 @@ String GetResetReason(void) } } -boolean OsWatchBlockedLoop(void) +bool OsWatchBlockedLoop(void) { return oswatch_blocked_loop; } @@ -374,10 +374,10 @@ uint8_t Shortcut(const char* str) return result; } -boolean ParseIp(uint32_t* addr, const char* str) +bool ParseIp(uint32_t* addr, const char* str) { uint8_t *part = (uint8_t*)addr; - byte i; + uint8_t i; *addr = 0; for (i = 0; i < 4; i++) { @@ -391,7 +391,7 @@ boolean ParseIp(uint32_t* addr, const char* str) return (3 == i); } -void MakeValidMqtt(byte option, char* str) +void MakeValidMqtt(uint8_t option, char* str) { // option 0 = replace by underscore // option 1 = delete character @@ -701,7 +701,7 @@ int GetStateNumber(char *state_text) return state_number; } -boolean GetUsedInModule(byte val, uint8_t *arr) +bool GetUsedInModule(uint8_t val, uint8_t *arr) { int offset = 0; @@ -749,7 +749,7 @@ boolean GetUsedInModule(byte val, uint8_t *arr) offset = -(GPIO_CNTR1_NP - GPIO_CNTR1); } - for (byte i = 0; i < MAX_GPIO_PIN; i++) { + for (uint8_t i = 0; i < MAX_GPIO_PIN; i++) { if (arr[i] == val) { return true; } if (arr[i] == val + offset) { return true; } } @@ -774,7 +774,7 @@ void SetSerialBaudrate(int baudrate) void ClaimSerial(void) { - serial_local = 1; + serial_local = true; AddLog_P(LOG_LEVEL_INFO, PSTR("SNS: Hardware Serial")); SetSeriallog(LOG_LEVEL_NONE); baudrate = Serial.baudRate(); @@ -899,7 +899,7 @@ uint32_t i2c_buffer = 0; bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size) { - byte x = I2C_RETRY_COUNTER; + uint8_t x = I2C_RETRY_COUNTER; i2c_buffer = 0; do { @@ -908,7 +908,7 @@ bool I2cValidRead(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 (uint8_t i = 0; i < size; i++) { i2c_buffer = i2c_buffer << 8 | Wire.read(); // receive DATA } } @@ -1000,7 +1000,7 @@ int32_t I2cRead24(uint8_t addr, uint8_t reg) bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size) { - byte x = I2C_RETRY_COUNTER; + uint8_t x = I2C_RETRY_COUNTER; do { Wire.beginTransmission((uint8_t)addr); // start transmission to device @@ -1029,7 +1029,7 @@ int8_t I2cReadBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len) Wire.beginTransmission((uint8_t)addr); Wire.write((uint8_t)reg); Wire.endTransmission(); - if (len != Wire.requestFrom((uint8_t)addr, (byte)len)) { + if (len != Wire.requestFrom((uint8_t)addr, (uint8_t)len)) { return 1; } while (len--) { @@ -1060,9 +1060,9 @@ void I2cScan(char *devs, unsigned int devs_len) // I2C_SDA_HELD_LOW 3 = I2C bus error. SDA line held low by slave/another_master after n bits // I2C_SDA_HELD_LOW_AFTER_INIT 4 = line busy. SDA again held low by another device. 2nd master? - byte error = 0; - byte address = 0; - byte any = 0; + uint8_t error = 0; + uint8_t address = 0; + uint8_t any = 0; snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_DEVICES_FOUND_AT)); for (address = 1; address <= 127; address++) { @@ -1086,9 +1086,9 @@ void I2cScan(char *devs, unsigned int devs_len) } } -boolean I2cDevice(byte addr) +bool I2cDevice(uint8_t addr) { - for (byte address = 1; address <= 127; address++) { + for (uint8_t address = 1; address <= 127; address++) { Wire.beginTransmission(address); if (!Wire.endTransmission() && (address == addr)) { return true; @@ -1107,7 +1107,7 @@ boolean I2cDevice(byte addr) * \*********************************************************************************************/ -void SetSeriallog(byte loglevel) +void SetSeriallog(uint8_t loglevel) { Settings.seriallog_level = loglevel; seriallog_level = loglevel; @@ -1115,7 +1115,7 @@ void SetSeriallog(byte loglevel) } #ifdef USE_WEBSERVER -void GetLog(byte idx, char** entry_pp, size_t* len_p) +void GetLog(uint8_t idx, char** entry_pp, size_t* len_p) { char* entry_p = NULL; size_t len = 0; @@ -1123,7 +1123,7 @@ void GetLog(byte idx, char** entry_pp, size_t* len_p) if (idx) { char* it = web_log; do { - byte cur_idx = *it; + uint8_t cur_idx = *it; it++; size_t tmp = strchrspn(it, '\1'); tmp++; // Skip terminating '\1' @@ -1164,7 +1164,7 @@ void Syslog(void) } } -void AddLog(byte loglevel) +void AddLog(uint8_t loglevel) { char mxtime[10]; // "13:45:21 " @@ -1194,13 +1194,13 @@ void AddLog(byte loglevel) if (!global_state.wifi_down && (loglevel <= syslog_level)) { Syslog(); } } -void AddLog_P(byte loglevel, const char *formatP) +void AddLog_P(uint8_t loglevel, const char *formatP) { snprintf_P(log_data, sizeof(log_data), formatP); AddLog(loglevel); } -void AddLog_P(byte loglevel, const char *formatP, const char *formatP2) +void AddLog_P(uint8_t loglevel, const char *formatP, const char *formatP2) { char message[100]; @@ -1210,7 +1210,7 @@ void AddLog_P(byte loglevel, const char *formatP, const char *formatP2) AddLog(loglevel); } -void AddLogBuffer(byte loglevel, uint8_t *buffer, int count) +void AddLogBuffer(uint8_t loglevel, uint8_t *buffer, int count) { snprintf_P(log_data, sizeof(log_data), PSTR("DMP:")); for (int i = 0; i < count; i++) { @@ -1219,7 +1219,7 @@ void AddLogBuffer(byte loglevel, uint8_t *buffer, int count) AddLog(loglevel); } -void AddLogSerial(byte loglevel) +void AddLogSerial(uint8_t loglevel) { AddLogBuffer(loglevel, (uint8_t*)serial_in_buffer, serial_in_byte_counter); } diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index 63726a05e..4ed30b469 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -57,7 +57,7 @@ void ButtonInit(void) } buttons_found = 0; - for (byte i = 0; i < MAX_KEYS; i++) { + for (uint8_t i = 0; i < MAX_KEYS; i++) { if (pin[GPIO_KEY1 +i] < 99) { buttons_found++; pinMode(pin[GPIO_KEY1 +i], bitRead(key_no_pullup, i) ? INPUT : ((16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); @@ -65,7 +65,7 @@ void ButtonInit(void) } } -byte ButtonSerial(byte serial_in_byte) +uint8_t ButtonSerial(uint8_t serial_in_byte) { if (dual_hex_code) { dual_hex_code--; @@ -102,7 +102,7 @@ void ButtonHandler(void) char scmnd[20]; uint8_t maxdev = (devices_present > MAX_KEYS) ? MAX_KEYS : devices_present; - for (byte button_index = 0; button_index < maxdev; button_index++) { + for (uint8_t button_index = 0; button_index < maxdev; button_index++) { button = NOT_PRESSED; button_present = 0; @@ -134,7 +134,7 @@ void ButtonHandler(void) else if (SONOFF_4CHPRO == Settings.module) { if (holdbutton[button_index]) { holdbutton[button_index]--; } - boolean button_pressed = false; + bool button_pressed = false; if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); AddLog(LOG_LEVEL_DEBUG); @@ -200,7 +200,7 @@ void ButtonHandler(void) multiwindow[button_index]--; } else { if (!restart_flag && !holdbutton[button_index] && (multipress[button_index] > 0) && (multipress[button_index] < MAX_BUTTON_COMMANDS +3)) { - boolean single_press = false; + bool single_press = false; if (multipress[button_index] < 3) { // Single or Double press if ((SONOFF_DUAL_R2 == Settings.module) || (SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { single_press = true; diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index e5f302de3..12a4d89ec 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -60,7 +60,7 @@ String GetBuildDateAndTime(void) int year = 0; // sscanf(mdate, "%s %d %d", bdt, &day, &year); // Not implemented in 2.3.0 and probably too much code - byte i = 0; + uint8_t i = 0; for (char *str = strtok_r(mdate, " ", &p); str && i < 3; str = strtok_r(NULL, " ", &p)) { switch (i++) { case 0: // Month @@ -112,7 +112,7 @@ String GetDT(uint32_t time) * "2017-03-07T11:08:02-07:00" - if DT_LOCAL and SetOption52 = 1 * "2017-03-07T11:08:02" - otherwise */ -String GetDateAndTime(byte time_type) +String GetDateAndTime(uint8_t time_type) { // "2017-03-07T11:08:02-07:00" - ISO8601:2004 uint32_t time = local_time; @@ -332,9 +332,9 @@ uint32_t Midnight(void) return midnight; } -boolean MidnightNow(void) +bool MidnightNow(void) { - boolean mnflg = midnight_now; + bool mnflg = midnight_now; if (mnflg) midnight_now = 0; return mnflg; } @@ -348,7 +348,7 @@ void RtcSecond(void) if (!global_state.wifi_down && (offset == RtcTime.second) && ((RtcTime.year < 2016) || (ntp_sync_minute == RtcTime.minute) || ntp_force_sync)) { ntp_time = sntp_get_current_timestamp(); if (ntp_time > 1451602800) { // Fix NTP bug in core 2.4.1/SDK 2.2.1 (returns Thu Jan 01 08:00:10 1970 after power on) - ntp_force_sync = 0; + ntp_force_sync = false; utc_time = ntp_time; ntp_sync_minute = 60; // Sync so block further requests if (restart_time == 0) { diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino index cb685cb81..b820a8151 100644 --- a/sonoff/support_switch.ino +++ b/sonoff/support_switch.ino @@ -71,7 +71,7 @@ void SwitchProbe(void) uint8_t force_high = (Settings.switch_debounce % 50) &1; // 51, 101, 151 etc uint8_t force_low = (Settings.switch_debounce % 50) &2; // 52, 102, 152 etc - for (byte i = 0; i < MAX_SWITCHES; i++) { + for (uint8_t i = 0; i < MAX_SWITCHES; i++) { if (pin[GPIO_SWT1 +i] < 99) { // Olimex user_switch2.c code to fix 50Hz induced pulses if (1 == digitalRead(pin[GPIO_SWT1 +i])) { @@ -117,7 +117,7 @@ void SwitchInit(void) } switches_found = 0; - for (byte i = 0; i < MAX_SWITCHES; i++) { + for (uint8_t i = 0; i < MAX_SWITCHES; i++) { lastwallswitch[i] = 1; // Init global to virtual switch state; if (pin[GPIO_SWT1 +i] < 99) { switches_found++; @@ -133,7 +133,7 @@ void SwitchInit(void) * Switch handler \*********************************************************************************************/ -void SwitchHandler(byte mode) +void SwitchHandler(uint8_t mode) { if (uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit @@ -141,7 +141,7 @@ void SwitchHandler(byte mode) uint8_t switchflag; uint16_t loops_per_second = 1000 / Settings.switch_debounce; - for (byte i = 0; i < MAX_SWITCHES; i++) { + for (uint8_t i = 0; i < MAX_SWITCHES; i++) { if ((pin[GPIO_SWT1 +i] < 99) || (mode)) { if (holdwallswitch[i]) { diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 6f19546a3..50f2895b0 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -60,7 +60,7 @@ int WifiGetRssiAsQuality(int rssi) return quality; } -boolean WifiConfigCounter(void) +bool WifiConfigCounter(void) { if (wifi_config_counter) { wifi_config_counter = WIFI_CONFIG_SEC; @@ -95,12 +95,12 @@ void WifiWpsStatusCallback(wps_cb_status status) } } -boolean WifiWpsConfigDone(void) +bool WifiWpsConfigDone(void) { return (!wps_result); } -boolean WifiWpsConfigBegin(void) +bool WifiWpsConfigBegin(void) { wps_result = 99; if (!wifi_wps_disable()) { return false; } diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 9c62a7561..1974e9128 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -349,7 +349,7 @@ enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER}; DNSServer *DnsServer; ESP8266WebServer *WebServer; -boolean remove_duplicate_access_points = true; +bool remove_duplicate_access_points = true; int minimum_signal_quality = -1; uint8_t webserver_state = HTTP_OFF; uint8_t upload_error = 0; @@ -415,7 +415,7 @@ void StartWebserver(int type, IPAddress ipweb) XsnsCall(FUNC_WEB_ADD_HANDLER); #endif // Not BE_MINIMAL } - reset_web_log_flag = 0; + reset_web_log_flag = false; WebServer->begin(); // Web server start } if (webserver_state != type) { @@ -640,13 +640,13 @@ void HandleRoot(void) if (SONOFF_IFAN02 == Settings.module) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); page += mqtt_data; - for (byte i = 0; i < MAX_FAN_SPEED; i++) { + for (uint8_t i = 0; i < MAX_FAN_SPEED; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 16, i +2, stemp, ""); page += mqtt_data; } } else { - for (byte idx = 1; idx <= devices_present; idx++) { + for (uint8_t idx = 1; idx <= devices_present; idx++) { snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); @@ -658,10 +658,10 @@ void HandleRoot(void) if (SONOFF_BRIDGE == Settings.module) { page += FPSTR(HTTP_TABLE100); page += F(""); - byte idx = 0; - for (byte i = 0; i < 4; i++) { + uint8_t idx = 0; + for (uint8_t i = 0; i < 4; i++) { if (idx > 0) { page += F(""); } - for (byte j = 0; j < 4; j++) { + for (uint8_t j = 0; j < 4; j++) { idx++; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), idx, idx); // ?k is related to WebGetArg("k", tmp, sizeof(tmp)); page += mqtt_data; @@ -744,7 +744,7 @@ void HandleAjaxStatusRefresh(void) snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_STATE, mqtt_data, 64, (fanspeed) ? "bold" : "normal", 54, (fanspeed) ? svalue : GetStateText(0)); } else { - for (byte idx = 1; idx <= devices_present; idx++) { + for (uint8_t idx = 1; idx <= devices_present; idx++) { snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1)); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_STATE, mqtt_data, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue); @@ -755,7 +755,7 @@ void HandleAjaxStatusRefresh(void) WebServer->send(200, FPSTR(HDR_CTYPE_HTML), mqtt_data); } -boolean HttpCheckPriviledgedAccess(boolean autorequestauth = true) +bool HttpCheckPriviledgedAccess(bool autorequestauth = true) { if (HTTP_USER == webserver_state) { HandleRoot(); @@ -812,13 +812,13 @@ void HandleModuleConfiguration(void) if (WebServer->hasArg("m")) { String page = ""; - for (byte i = 0; i < MAXMODULE; i++) { + for (uint8_t i = 0; i < MAXMODULE; i++) { midx = pgm_read_byte(kModuleNiceList + i); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE3, midx, AnyModuleName(midx).c_str(), midx +1); page += mqtt_data; } page += "}3"; // String separator means do not use "}3" in Module name and Sensor name - for (byte j = 0; j < sizeof(kGpioNiceList); j++) { + for (uint8_t j = 0; j < sizeof(kGpioNiceList); j++) { midx = pgm_read_byte(kGpioNiceList + j); if (!GetUsedInModule(midx, cmodule.io)) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE3, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); @@ -835,7 +835,7 @@ void HandleModuleConfiguration(void) page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE)); page += FPSTR(HTTP_SCRIPT_MODULE1); page.replace(F("}4"), String(Settings.module)); - for (byte i = 0; i < sizeof(cmodule); i++) { + for (uint8_t i = 0; i < sizeof(cmodule); i++) { if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,%d);"), my_module.io[i], i); // g0 - g16 page += mqtt_data; @@ -853,7 +853,7 @@ void HandleModuleConfiguration(void) } page += F("
"); - func += F(D_PROGRAM_VERSION "}2"); func += my_version; + func += F(D_PROGRAM_VERSION "}2"); func += my_version; func += my_image; func += F("}1" D_BUILD_DATE_AND_TIME "}2"); func += GetBuildDateAndTime(); func += F("}1" D_CORE_AND_SDK_VERSION "}2" ARDUINO_ESP8266_RELEASE "/"); func += String(ESP.getSdkVersion()); func += F("}1" D_UPTIME "}2"); func += GetUptime(); diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 40f69d93a..b74577a75 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -404,8 +404,8 @@ void MqttConnected() } if (mqtt_initial_connection_state) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), - my_module.name, my_version, mqtt_client, Settings.mqtt_grptopic); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), + my_module.name, my_version, my_image, mqtt_client, Settings.mqtt_grptopic); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); #ifdef USE_WEBSERVER if (Settings.webserver) { diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 9656c14ec..26438aabe 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -629,7 +629,7 @@ void DisplayLogBufferInit() DisplayReAllocLogBuffer(); char buffer[40]; - snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s"), my_version); + snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s%s"), my_version, my_image); DisplayLogBufferAdd(buffer); snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings.display_mode); DisplayLogBufferAdd(buffer); From 4a21d3270da745abf94c121f5b95dd09ecb5b24b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 7 Nov 2018 15:37:06 +0100 Subject: [PATCH 0453/2222] Restrict hardware serial Restrict hardware serial --- lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp | 4 ++-- lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h | 2 +- sonoff/xdrv_16_tuyadimmer.ino | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp index 7e6ddf72f..3df42f834 100644 --- a/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp @@ -76,7 +76,7 @@ static void (*ISRList[16])() = { tms_isr_15 }; -TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fallback) +TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback) { m_valid = false; m_hardserial = 0; @@ -91,7 +91,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fa if (hardware_fallback && (((3 == m_rx_pin) && (1 == m_tx_pin)) || ((3 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (1 == m_tx_pin)))) { m_hardserial = 1; } - else if (hardware_fallback && (((13 == m_rx_pin) && (15 == m_tx_pin)) || ((13 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (15 == m_tx_pin)))) { + else if ((2 == hardware_fallback) && (((13 == m_rx_pin) && (15 == m_tx_pin)) || ((13 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (15 == m_tx_pin)))) { m_hardserial = 1; m_hardswap = 1; } diff --git a/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h b/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h index 3136a8e46..de991526a 100644 --- a/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h +++ b/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h @@ -38,7 +38,7 @@ class TasmotaSerial : public Stream { public: - TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fallback = false); + TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback = 0); virtual ~TasmotaSerial(); bool begin(long speed, int stop_bits = 1); diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index c8bf04961..71f5374d8 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -284,7 +284,7 @@ void TuyaInit() if (!Settings.param[P_TUYA_DIMMER_ID]) { Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID; } - TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 1); + TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); if (TuyaSerial->begin(9600)) { if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } // Get MCU Configuration From 61985ca16bb98c58aa224006242a070084bc7a73 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 7 Nov 2018 18:43:44 +0100 Subject: [PATCH 0454/2222] Add hex to flash info --- sonoff/sonoff.ino | 5 +++-- sonoff/xdrv_01_webserver.ino | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index d4c38f479..b8c42350d 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2385,10 +2385,11 @@ void GpioSwitchPinMode(uint8_t index) if (pin[GPIO_SWT1 +index] < 99) { // pinMode(pin[GPIO_SWT1 +index], (16 == pin[GPIO_SWT1 +index]) ? INPUT_PULLDOWN_16 : bitRead(switch_no_pullup, index) ? INPUT : INPUT_PULLUP); - uint8_t no_pullup = bitRead(switch_no_pullup, index); + uint8_t no_pullup = bitRead(switch_no_pullup, index); // 0 = INPUT_PULLUP, 1 = INPUT if (no_pullup) { if (SHELLY2 == Settings.module) { - no_pullup = (Settings.switchmode[index] < PUSHBUTTON); + // Switchmodes : TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION + no_pullup = (Settings.switchmode[index] < PUSHBUTTON); // INPUT on TOGGLE, FOLLOW and FOLLOW_INV. INPUT_PULLUP on anything else } } pinMode(pin[GPIO_SWT1 +index], (16 == pin[GPIO_SWT1 +index]) ? INPUT_PULLDOWN_16 : (no_pullup) ? INPUT : INPUT_PULLUP); diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 627cebc52..35781290a 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1321,8 +1321,10 @@ void HandleInformation() #endif // USE_DISCOVERY 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()); + snprintf_P(stopic, sizeof(stopic), PSTR(" (0x%X)"), ESP.getChipId()); + func += F("}1" D_ESP_CHIP_ID "}2"); func += String(ESP.getChipId()); func += stopic; + snprintf_P(stopic, sizeof(stopic), PSTR(" (0x%X)"), ESP.getFlashChipId()); + func += F("}1" D_FLASH_CHIP_ID "}2"); func += String(ESP.getFlashChipId()); func += stopic; 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"); From b5d38c4eeef560a170b4020487b8b905ed661ca8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 8 Nov 2018 10:24:10 +0100 Subject: [PATCH 0455/2222] Add support for Gosund SP1 v2.3 Add support for Gosund SP1 v2.3 Power Socket with Energy Monitoring (#4297) --- RELEASENOTES.md | 5 +++-- sonoff/_changelog.ino | 1 + sonoff/sonoff_template.h | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2c987308c..161f03415 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -66,16 +66,17 @@ Module | Description 42 Zengge WF017 | Zengge WF017 Wifi RGB(W) Led Controller 43 Sonoff Pow R2 | Sonoff Pow R2 Wifi Smart Switch with Energy Monitoring 44 Sonoff iFan02 | Sonoff iFan02 Wifi Smart Ceiling Fan with Light -45 BlitzWolf SHP2 | BlitzWolf BW-SHP2, BW-SHP6, HomeCube SP1, Gosund SP111 Wifi Smart Switch with Energy Monitoring +45 BlitzWolf SHP2 | BlitzWolf BW-SHP2, BW-SHP6, HomeCube SP1, Gosund SP111, Teckin SP22 Wifi Smart Switch with Energy Monitoring 46 Shelly 1 | Shelly 1 Open Source Wifi Relay Module 47 Shelly 2 | Shelly 2 Wifi 2-gang Relay Module with Energy Monitoring 48 Xiaomi Philips | Xiaomi Philips Wifi WW Led Bulb 49 Neo Coolcam | Neo Coolcam Wifi Smart Socket 50 ESP Switch | ESP Switch 4-gang Wifi Switch with Leds 51 OBI Socket | OBI Wifi Smart Socket -52 Teckin | Teckin SP20, SP22 Wifi Smart Switch with Energy Monitoring +52 Teckin | Teckin SP20 Wifi Smart Switch with Energy Monitoring 53 AplicWDP303075 | Aplic WDP 303075 CSL Wifi Smart Switch with Energy Monitoring 54 Tuya Dimmer | MIUO (and other Tuya based) Wifi Dimmer for Incandescent Lights and Led +55 Gosund SP1_v23 | Gosund SP1 v2.3 Wifi Smart Switch with Energy Monitoring ## Provided Binary Downloads The following binary downloads have been compiled with ESP8266/Arduino library version **2.3.0** diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0d508f1a5..83a3eb644 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.3.0.5 20181107 * Add code image and optional commit number to version + * Add support for Gosund SP1 v2.3 Power Socket with Energy Monitoring (#4297) * * 6.3.0.4 20181106 * Add command SetSensorXX 0/1 to disable/re-enable compiled xsns_XX_sensor.ino driver diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index eb4d910d0..642914a53 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -250,6 +250,7 @@ enum SupportedModules { TECKIN, APLIC_WDP303075, TUYA_DIMMER, + GOSUND, MAXMODULE }; /********************************************************************************************/ @@ -466,6 +467,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { BLITZWOLF_BWSHP2, // Socket Relay Devices with Energy Monitoring TECKIN, APLIC_WDP303075, + GOSUND, NEO_COOLCAM, // Socket Relay Devices OBI, ESP_SWITCH, // Switch Devices @@ -1215,6 +1217,19 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, GPIO_USER, 0 + }, + { "Gosund SP1_v23", // https://www.amazon.de/gp/product/B0777BWS1P + 0, + GPIO_LED1_INV, // GPIO01 Serial RXD and LED1 (blue) inv + 0, + GPIO_KEY1, // GPIO03 Serial TXD and Button + GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_LED2_INV, // GPIO13 LED2 (red) inv + GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) + 0, 0, 0 } }; From f9bddb6c540634fb1405572a8f3156ff639d65ff Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 8 Nov 2018 10:40:19 +0100 Subject: [PATCH 0456/2222] Add flashchipid info Add flashchipid info --- sonoff/i18n.h | 1 + sonoff/sonoff.ino | 4 ++-- sonoff/xdrv_01_webserver.ino | 9 ++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 112959a25..36d93ccd7 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -62,6 +62,7 @@ #define D_JSON_FAILED "Failed" #define D_JSON_FALLBACKTOPIC "FallbackTopic" #define D_JSON_FEATURES "Features" +#define D_JSON_FLASHCHIPID "FlashChipId" #define D_JSON_FLASHMODE "FlashMode" #define D_JSON_FLASHSIZE "FlashSize" #define D_JSON_FREEMEMORY "Free" diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index b8c42350d..c4b0cbb20 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1509,8 +1509,8 @@ void PublishStatus(uint8_t payload) } if ((0 == payload) || (4 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHMODE "\":%d,\"" D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]}}"), - ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipMode(), LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\"" D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]}}"), + ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipId(), ESP.getFlashChipMode(), LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "4")); } diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 35781290a..c645808eb 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1248,7 +1248,7 @@ void HandleInformation() func += F("}1" D_BUILD_DATE_AND_TIME "}2"); func += GetBuildDateAndTime(); func += F("}1" D_CORE_AND_SDK_VERSION "}2" ARDUINO_ESP8266_RELEASE "/"); func += String(ESP.getSdkVersion()); func += F("}1" D_UPTIME "}2"); func += GetUptime(); - snprintf_P(stopic, sizeof(stopic), PSTR(" at %X"), GetSettingsAddress()); + snprintf_P(stopic, sizeof(stopic), PSTR(" at 0x%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(); @@ -1321,10 +1321,9 @@ void HandleInformation() #endif // USE_DISCOVERY func += F("}1}2 "); // Empty line - snprintf_P(stopic, sizeof(stopic), PSTR(" (0x%X)"), ESP.getChipId()); - func += F("}1" D_ESP_CHIP_ID "}2"); func += String(ESP.getChipId()); func += stopic; - snprintf_P(stopic, sizeof(stopic), PSTR(" (0x%X)"), ESP.getFlashChipId()); - func += F("}1" D_FLASH_CHIP_ID "}2"); func += String(ESP.getFlashChipId()); func += stopic; + func += F("}1" D_ESP_CHIP_ID "}2"); func += String(ESP.getChipId()); + snprintf_P(stopic, sizeof(stopic), PSTR("0x%06X"), ESP.getFlashChipId()); + func += F("}1" D_FLASH_CHIP_ID "}2"); func += stopic; 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"); From 2a4d82f4b69ab4f91ba2be1c3d4a3bb8983f5c08 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 8 Nov 2018 14:21:45 +0100 Subject: [PATCH 0457/2222] Add RF calibration on next restart Add RF calibration on next restart --- sonoff/sonoff.ino | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c4b0cbb20..e8bd64542 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2176,6 +2176,21 @@ void Every250mSeconds() restart_flag--; if (restart_flag <= 0) { AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); + + /* + Function: + Set whether the chip will do RF calibration or not when power up. The option is 0 by default. + Prototype: + void system_phy_set_powerup_option(uint8 option) + Parameter: + uint8 option : RF initialization when power up. + 0 : RF initialization when power up depends on esp_init_data_default.bin(0〜~127byte) byte 114. + 1 : RF initialization only calibrate VDD33 and TX power which will take about 18 ms; this reduces the current consumption. + 2 : RF initialization only calibrate VDD33 which will take about 2 ms; this has the least current consumption. + 3 : RF initialization will do the whole RF calibration which will take about 200 ms; this increases the current consumption. + */ + system_phy_set_powerup_option(3); + EspRestart(); } } From 3332ab01a1dfa6ecaf28bca7d3382cffa3d43134 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 8 Nov 2018 16:33:34 +0100 Subject: [PATCH 0458/2222] Revert "Add RF calibration on next restart" This reverts commit 2a4d82f4b69ab4f91ba2be1c3d4a3bb8983f5c08. --- sonoff/sonoff.ino | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index e8bd64542..c4b0cbb20 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2176,21 +2176,6 @@ void Every250mSeconds() restart_flag--; if (restart_flag <= 0) { AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); - - /* - Function: - Set whether the chip will do RF calibration or not when power up. The option is 0 by default. - Prototype: - void system_phy_set_powerup_option(uint8 option) - Parameter: - uint8 option : RF initialization when power up. - 0 : RF initialization when power up depends on esp_init_data_default.bin(0〜~127byte) byte 114. - 1 : RF initialization only calibrate VDD33 and TX power which will take about 18 ms; this reduces the current consumption. - 2 : RF initialization only calibrate VDD33 which will take about 2 ms; this has the least current consumption. - 3 : RF initialization will do the whole RF calibration which will take about 200 ms; this increases the current consumption. - */ - system_phy_set_powerup_option(3); - EspRestart(); } } From d573f7641a33ff31726787b5d8cb7bad65c9d5dc Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Fri, 9 Nov 2018 01:28:11 +0100 Subject: [PATCH 0459/2222] tuya: formatting --- sonoff/xdrv_16_tuyadimmer.ino | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index 71f5374d8..52b1450a5 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -140,11 +140,11 @@ void LightSerialDuty(uint8_t duty) duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself } - TuyaSendValue(Settings.param[P_TUYA_DIMMER_ID], duty); - snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Serial Packet Dim Value=%d (id=%d)"), duty, Settings.param[P_TUYA_DIMMER_ID]); AddLog(LOG_LEVEL_DEBUG); + TuyaSendValue(Settings.param[P_TUYA_DIMMER_ID], duty); + } else { tuya_ignore_dim = false; // reset flag @@ -156,6 +156,7 @@ void LightSerialDuty(uint8_t duty) void TuyaRequestState(){ if(TuyaSerial) { + // Get current status of MCU snprintf_P(log_data, sizeof(log_data), "TYA: Request MCU state"); AddLog(LOG_LEVEL_DEBUG); @@ -325,7 +326,7 @@ void TuyaSerialInput() else if ((tuya_cmd_status == 3) && (tuya_byte_counter == (6 + tuya_data_len)) && (tuya_cmd_checksum == serial_in_byte)){ // Compare checksum and process packet tuya_buffer[tuya_byte_counter++] = serial_in_byte; - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Received Packet: \"")); + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Rcvd Packet: \"")); for (int i = 0; i < tuya_byte_counter; i++) { snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, tuya_buffer[i]); } From 7a235cc8ef57572bac23f5afb378b226fac9ceee Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 10 Nov 2018 10:48:28 +0100 Subject: [PATCH 0460/2222] Fix shelly2 ghost switching Fix shelly2 ghost switching caused by lack of pull-up inputs (#4255) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 6 ++++-- sonoff/sonoff_template.h | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 83a3eb644..1fae97a15 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.3.0.5 20181107 * Add code image and optional commit number to version * Add support for Gosund SP1 v2.3 Power Socket with Energy Monitoring (#4297) + * Fix shelly2 ghost switching caused by lack of pull-up inputs (#4255) * * 6.3.0.4 20181106 * Add command SetSensorXX 0/1 to disable/re-enable compiled xsns_XX_sensor.ino driver diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c4b0cbb20..e92536a1b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2383,8 +2383,9 @@ void SerialInput() void GpioSwitchPinMode(uint8_t index) { if (pin[GPIO_SWT1 +index] < 99) { -// pinMode(pin[GPIO_SWT1 +index], (16 == pin[GPIO_SWT1 +index]) ? INPUT_PULLDOWN_16 : bitRead(switch_no_pullup, index) ? INPUT : INPUT_PULLUP); - + pinMode(pin[GPIO_SWT1 +index], (16 == pin[GPIO_SWT1 +index]) ? INPUT_PULLDOWN_16 : bitRead(switch_no_pullup, index) ? INPUT : INPUT_PULLUP); +/* + // Re-enable pull-up on Shelly2 as of 20181110 (#4255) uint8_t no_pullup = bitRead(switch_no_pullup, index); // 0 = INPUT_PULLUP, 1 = INPUT if (no_pullup) { if (SHELLY2 == Settings.module) { @@ -2393,6 +2394,7 @@ void GpioSwitchPinMode(uint8_t index) } } pinMode(pin[GPIO_SWT1 +index], (16 == pin[GPIO_SWT1 +index]) ? INPUT_PULLDOWN_16 : (no_pullup) ? INPUT : INPUT_PULLUP); +*/ } } diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 642914a53..2735ac76e 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1125,9 +1125,9 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL1, // GPIO04 GPIO_REL2, // GPIO05 0, 0, 0, 0, 0, 0, // Flash connection - GPIO_SWT1_NP, // GPIO12 + GPIO_SWT1, // GPIO12 0, - GPIO_SWT2_NP, // GPIO14 + GPIO_SWT2, // GPIO14 0, // GPIO15 MCP39F501 Reset 0, 0 }, From 9872f942ae12ddbd4c849e6586c3ab3c6148da30 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 10 Nov 2018 15:10:58 +0100 Subject: [PATCH 0461/2222] 6.3.0.6 Change GUI page load 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% --- sonoff/_changelog.ino | 5 ++- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_webserver.ino | 73 +++++++++++++++++++++--------------- 3 files changed, 47 insertions(+), 33 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 1fae97a15..01108f603 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.3.0.5 20181107 +/* 6.3.0.6 20181110 + * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% + * + * 6.3.0.5 20181107 * Add code image and optional commit number to version * Add support for Gosund SP1 v2.3 Power Socket with Energy Monitoring (#4297) * Fix shelly2 ghost switching caused by lack of pull-up inputs (#4255) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index aef909e8a..7f25e0ebc 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06030005 +#define VERSION 0x06030006 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index c645808eb..37d63d566 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -84,7 +84,7 @@ const char HTTP_HEAD[] PROGMEM = "function lc(p){" "la('?t='+p);" // ?t related to WebGetArg("t", tmp, sizeof(tmp)); "}"; - + const char HTTP_HEAD_RELOAD[] PROGMEM = "setTimeout(function(){location.href='.';},4000);"; @@ -160,17 +160,28 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = ""; const char HTTP_SCRIPT_MODULE1[] PROGMEM = "var os;" - "function sk(s,g){" + "function sk(s,g){" // s = value, g = id and name "var o=os.replace(\"value='\"+s+\"'\",\"selected value='\"+s+\"'\");" "eb('g'+g).innerHTML=o;" "}" "function sl(){" - "var o0=\""; + "if(x!=null){x.abort();}" // Abort any request pending + "x=new XMLHttpRequest();" + "x.onreadystatechange=function(){" + "if(x.readyState==4&&x.status==200){" + "var i,o=x.responseText.replace(/}1/g,\"
\").replace(/}2/g,\"\");" "eb('i').innerHTML=s;" "}" ""; + +const char HTTP_HEAD_STYLE[] PROGMEM = + "" + + "" + + "" + "" + "
" +#ifdef BE_MINIMAL + "

" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "

" +#endif + "
" +#ifdef LANGUAGE_MODULE_NAME + "

" D_MODULE " {ha

" +#else + "

{ha " D_MODULE "

" +#endif + "

{h}

{j}
"; const char HTTP_MSG_SLIDER1[] PROGMEM = "
" D_COLDLIGHT "" D_WARMLIGHT "
" "
"; @@ -487,6 +497,7 @@ void ShowPage(String &page, bool auth) if (HTTP_MANAGER == webserver_state) { if (WifiConfigCounter()) { + page.replace(F(""), FPSTR(HTTP_SCRIPT_COUNTER)); page.replace(F(""), F("")); page += FPSTR(HTTP_COUNTER); } @@ -515,7 +526,6 @@ void WebRestart(uint8_t type) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTART); String page = FPSTR(HTTP_HEAD); - page += FPSTR(HTTP_HEAD_RELOAD); page += FPSTR(HTTP_HEAD_STYLE); if (type) { @@ -536,6 +546,7 @@ void WebRestart(uint8_t type) } else { page += FPSTR(HTTP_BTN_MAIN); } + page.replace(F(""), FPSTR(HTTP_SCRIPT_RELOAD)); ShowPage(page); ShowWebSource(SRC_WEBGUI); @@ -588,6 +599,7 @@ void HandleRoot() char stemp[10]; String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_MAIN_MENU)); + page += FPSTR(HTTP_SCRIPT_ROOT); page += FPSTR(HTTP_HEAD_STYLE); page.replace(F(""), F("")); @@ -881,6 +893,7 @@ void HandleWifiConfiguration() String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_CONFIGURE_WIFI)); + page += FPSTR(HTTP_SCRIPT_WIFI); page += FPSTR(HTTP_HEAD_STYLE); if (WebServer->hasArg("scan")) { @@ -1396,6 +1409,7 @@ void HandleUpgradeFirmwareStart() page += F("
" D_UPGRADE_STARTED " ...
"); page += FPSTR(HTTP_MSG_RSTRT); page += FPSTR(HTTP_BTN_MAIN); +// page.replace(F(""), FPSTR(HTTP_SCRIPT_RELOAD)); ShowPage(page); snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_UPGRADE " 1")); @@ -1446,6 +1460,7 @@ void HandleUploadDone() } else { page += F("green'>" D_SUCCESSFUL "
"); page += FPSTR(HTTP_MSG_RSTRT); + page.replace(F(""), FPSTR(HTTP_SCRIPT_RELOAD)); ShowWebSource(SRC_WEBGUI); restart_flag = 2; // Always restart to re-enable disabled features during update } From 0d78ec4fad7d36e5cf79eb285bb720a4018cdcbc Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sat, 10 Nov 2018 18:08:31 +0100 Subject: [PATCH 0466/2222] tuya: change Sent -> TX, Rcvd -> RX --- sonoff/xdrv_16_tuyadimmer.ino | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index 52b1450a5..a142365a1 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -68,7 +68,7 @@ void TuyaSendCmd(uint8_t cmd, uint8_t payload[] = nullptr, uint16_t payload_len TuyaSerial->write(cmd); // Tuya command TuyaSerial->write(payload_len >> 8); // following data length (Hi) TuyaSerial->write(payload_len & 0xFF); // following data length (Lo) - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Sent Packet: \"55aa00%02x%02x%02x"), cmd, payload_len >> 8, payload_len & 0xFF); + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: TX Packet: \"55aa00%02x%02x%02x"), cmd, payload_len >> 8, payload_len & 0xFF); for(int i = 0; i < payload_len; ++i) { TuyaSerial->write(payload[i]); checksum += payload[i]; @@ -191,7 +191,7 @@ void TuyaPacketProcess() case TUYA_CMD_STATE: if (tuya_buffer[5] == 5) { // on/off packet - snprintf_P(log_data, sizeof(log_data),PSTR("TYA: Rcvd - %s State"),tuya_buffer[10]?"On":"Off"); + snprintf_P(log_data, sizeof(log_data),PSTR("TYA: RX - %s State"),tuya_buffer[10]?"On":"Off"); AddLog(LOG_LEVEL_DEBUG); if((power || Settings.light_dimmer > 0) && (power != tuya_buffer[10])) { @@ -200,7 +200,7 @@ void TuyaPacketProcess() } else if (tuya_buffer[5] == 8) { // dim packet - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Rcvd Dim State=%d"), tuya_buffer[13]); + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: RX Dim State=%d"), tuya_buffer[13]); AddLog(LOG_LEVEL_DEBUG); if (!Settings.param[P_TUYA_DIMMER_ID]) { @@ -225,17 +225,17 @@ void TuyaPacketProcess() case TUYA_CMD_WIFI_RESET: case TUYA_CMD_WIFI_SELECT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Rcvd WiFi Reset")); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi Reset")); TuyaResetWifi(); break; case TUYA_CMD_WIFI_STATE: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Rcvd WiFi LED set ACK")); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi LED set ACK")); tuya_wifi_state = WifiState(); break; case TUYA_CMD_MCU_CONF: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Rcvd MCU configuration")); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration")); if (tuya_buffer[5] == 2) { uint8_t led1_gpio = tuya_buffer[6]; @@ -259,7 +259,7 @@ void TuyaPacketProcess() break; default: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Rcvd unknown command")); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX unknown command")); } } @@ -326,7 +326,7 @@ void TuyaSerialInput() else if ((tuya_cmd_status == 3) && (tuya_byte_counter == (6 + tuya_data_len)) && (tuya_cmd_checksum == serial_in_byte)){ // Compare checksum and process packet tuya_buffer[tuya_byte_counter++] = serial_in_byte; - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Rcvd Packet: \"")); + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: RX Packet: \"")); for (int i = 0; i < tuya_byte_counter; i++) { snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, tuya_buffer[i]); } From 72dede855ac6ab6f6362d6f65175da9c57844d3c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 11 Nov 2018 13:21:46 +0100 Subject: [PATCH 0467/2222] Add domoticz support to SR04 Add domoticz support to sensor SR04 (#4325) --- sonoff/xsns_22_sr04.ino | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index 9d447b3f3..118a37cc0 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -136,6 +136,11 @@ void Sr04Show(boolean json) if (Sr04Read(&distance)) { // Check if read failed if(json) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SR04\":{\"" D_JSON_DISTANCE "\":%d}"), mqtt_data, distance); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_COUNT, distance); // Send distance as Domoticz Counter value + } +#endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_DISTANCE, mqtt_data, distance); From e76f862b8f16c60f382a5800a636fea8288917da Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 11 Nov 2018 13:39:24 +0100 Subject: [PATCH 0468/2222] Add info Add info --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 01108f603..39b060289 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% + * In case of web page errors clear your browser cache or do Page Reload (F5 or Ctrl+R) * * 6.3.0.5 20181107 * Add code image and optional commit number to version From a55ec91a106e4d42bc1c3c761820dbcc2914f89c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 11 Nov 2018 14:28:46 +0100 Subject: [PATCH 0469/2222] 6.3.0.7 Use ESP.reset 6.3.0.7 20181111 * Fix wifi connection errors using ESP.reset instead of ESP.restart --- sonoff/_changelog.ino | 5 ++++- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 11 ++++++----- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 39b060289..c2ee44a65 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.3.0.6 20181110 +/* 6.3.0.7 20181111 + * Fix wifi connection errors using ESP.reset instead of ESP.restart + * + * 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% * In case of web page errors clear your browser cache or do Page Reload (F5 or Ctrl+R) * diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 7f25e0ebc..14eee4f25 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06030006 +#define VERSION 0x06030007 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index bbc81b1a3..9389714ec 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1577,15 +1577,15 @@ int WifiState() void WifiConnect() { WifiSetState(0); - WiFi.persistent(false); // Solve possible wifi init errors + WiFi.persistent(false); // Solve possible wifi init errors wifi_status = 0; wifi_retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); wifi_retry = wifi_retry_init; wifi_counter = 1; } -/* // Enable from 6.0.0a until 6.1.0a - disabled due to possible cause of bad wifi connect on core 2.3.0 +// Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset void WifiDisconnect() { // Courtesy of EspEasy @@ -1598,17 +1598,18 @@ void WifiDisconnect() void EspRestart() { - // This results in exception 3 on restarts delay(100); // Allow time for message xfer - disabled v6.1.0b WifiDisconnect(); - ESP.restart(); +// ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 + ESP.reset(); } -*/ +/* void EspRestart() { ESP.restart(); } +*/ /*********************************************************************************************\ * Basic I2C routines From 2a2b224a24367d21f1a24063d501799099f930d2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 11 Nov 2018 14:45:19 +0100 Subject: [PATCH 0470/2222] Add pulse time to received JSON Add pulse time to received JSON message in RcSwitch driver (#2702) --- sonoff/xdrv_17_rcswitch.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index 701b8c119..82ce95096 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -36,7 +36,7 @@ RCSwitch mySwitch = RCSwitch(); -#define RF_TIME_AVOID_DUPLICATE 1000 // Milliseconds +#define RF_TIME_AVOID_DUPLICATE 1000 // Milliseconds uint32_t rf_lasttime = 0; @@ -62,8 +62,8 @@ void RfReceiveCheck() } else { snprintf_P(stemp, sizeof(stemp), PSTR("\"%lX\""), (uint32_t)data); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d}}"), - stemp, bits, protocol); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), + stemp, bits, protocol, delay); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); XdrvRulesProcess(); #ifdef USE_DOMOTICZ From c2e1e0344db8320a85374652e2789519f87ef53f Mon Sep 17 00:00:00 2001 From: wvdv2002 Date: Sun, 11 Nov 2018 15:20:10 +0100 Subject: [PATCH 0471/2222] Revert "Added language strings for uart TX/RX" This reverts commit fd8622d546454597575dabf9bbf62c1d9fd98fc3. --- sonoff/language/bg-BG.h | 2 -- sonoff/language/cs-CZ.h | 2 -- sonoff/language/de-DE.h | 2 -- sonoff/language/el-GR.h | 2 -- sonoff/language/en-GB.h | 4 ---- sonoff/language/es-AR.h | 2 -- sonoff/language/fr-FR.h | 2 -- sonoff/language/he-HE.h | 2 -- sonoff/language/hu-HU.h | 2 -- sonoff/language/it-IT.h | 2 -- sonoff/language/nl-NL.h | 2 -- sonoff/language/pl-PL.h | 2 -- sonoff/language/pt-BR.h | 2 -- sonoff/language/pt-PT.h | 2 -- sonoff/language/ru-RU.h | 2 -- sonoff/language/tr-TR.h | 2 -- sonoff/language/uk-UK.h | 2 -- sonoff/language/zh-CN.h | 2 -- sonoff/language/zh-TW.h | 2 -- 19 files changed, 40 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 75f9178b0..1503884c3 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index bb1de8fa4..2b667cec1 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index e69a5fb09..9c2f7c24e 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index d84f566bf..79558615d 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -530,8 +530,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index accc7ab90..1a9304a7d 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -529,10 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index cc4eb3da7..e5c3135fe 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 29dd9f213..0dfb2929c 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 3ccbade21..cb041ffba 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 4913a8597..5cee46a52 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 05d151c0c..0eaca9337 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 99d7985aa..0567e0849 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 077b23feb..678a7b770 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index e587bbedf..712ea6a74 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index ee71a81cf..0bba501bd 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 12288e899..f9062a572 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 512f7f885..f892fafbb 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index ed981ce53..4c290613a 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 36662cd4d..fe6dabe8d 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index d286e4b7a..92a805587 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -529,8 +529,6 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_ARMTRONIX_TX "Armtronix Tx" -#define D_SENSOR_ARMTRONIX_RX "Armtronix Rx" // Units #define D_UNIT_AMPERE "安" From 0868c721405069e73d1162f6d370453077c0fa28 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 11 Nov 2018 16:52:09 +0100 Subject: [PATCH 0472/2222] Fix Sonoff Pow R2 and Sonoff S31 Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by MP3 driver --- sonoff/_changelog.ino | 3 ++- sonoff/xdrv_14_mp3.ino | 36 +++++++++++++++++++----------------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index c2ee44a65..23bbe3dc2 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.3.0.7 20181111 - * Fix wifi connection errors using ESP.reset instead of ESP.restart + * Fix wifi connection errors using wifi disconnect and ESP.reset instead of ESP.restart + * Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by MP3 driver * * 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/xdrv_14_mp3.ino b/sonoff/xdrv_14_mp3.ino index 0a72b68ab..973c3fe5e 100644 --- a/sonoff/xdrv_14_mp3.ino +++ b/sonoff/xdrv_14_mp3.ino @@ -33,7 +33,7 @@ tested - works by MP3Device 1 = USB STick, or MP3Device 2 = SD-Card - after power and/or reset the SD-Card(2) is the default device --- - 1.0.0.2 20180912 added - again some if-commands to switch() because of new commands + 1.0.0.2 20180912 added - again some if-commands to switch() because of new commands --- 1.0.0.1 20180911 added - command eq (equalizer 0..5) tested - works in console with MP3EQ 1, the value can be 0..5 @@ -42,13 +42,13 @@ erased - code for USB device about some errors, will be added in a next release --- 1.0.0.1 20180910 changed - command real MP3Stop in place of pause/stop used in the original version - changed - the command MP3Play e.g. 001 to MP3Track e.g. 001, - added - new normal command MP3Play and MP3Pause + changed - the command MP3Play e.g. 001 to MP3Track e.g. 001, + added - new normal command MP3Play and MP3Pause --- - 1.0.0.0 20180907 merged - by arendst + 1.0.0.0 20180907 merged - by arendst changed - the driver name from xdrv_91_mp3.ino to xdrv_14_mp3.ino --- - 0.9.0.3 20180906 request - Pull Request + 0.9.0.3 20180906 request - Pull Request changed - if-commands to switch() for faster response --- 0.9.0.2 20180906 cleaned - source code for faster reading @@ -98,7 +98,7 @@ enum MP3_Commands { // commands useable in conso CMND_MP3_RESET, // MP3Reset, a fresh and default restart CMND_MP3_DAC }; // set dac, 1=off, 0=on, DAC is turned on (0) by default - + /*********************************************************************************************\ * command defines \*********************************************************************************************/ @@ -107,7 +107,7 @@ enum MP3_Commands { // commands useable in conso // player commands #define MP3_CMD_TRACK 0x03 // specify playback of a track, e.g. MP3Track 003 #define MP3_CMD_PLAY 0x0d // Play, works as a normal play on a real MP3 Player, starts at 001.mp3 file on the selected device -#define MP3_CMD_PAUSE 0x0e // Pause, was original designed as stop, see data sheet +#define MP3_CMD_PAUSE 0x0e // Pause, was original designed as stop, see data sheet #define MP3_CMD_STOP 0x16 // Stop, it's a real stop now, in the original version it was a pause command #define MP3_CMD_VOLUME 0x06 // specifies the volume and means a console input as 0..100 #define MP3_CMD_EQ 0x07 // specify EQ(0/1/2/3/4/5), 0:Normal, 1:Pop, 2:Rock, 3:Jazz, 4:Classic, 5:Bass @@ -138,7 +138,7 @@ uint16_t MP3_Checksum(uint8_t *array) void MP3PlayerInit(void) { MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3_DFR562]); // start serial communication fixed to 9600 baud - if (MP3Player->begin(9600)) { + if (MP3Player->begin(9600)) { MP3Player->flush(); delay(1000); MP3_CMD(MP3_CMD_RESET, MP3_CMD_RESET_VALUE); // reset the player to defaults @@ -185,7 +185,7 @@ boolean MP3PlayerCmd(void) { if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { // prefix int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMP3_Commands); - + switch (command_code) { case CMND_MP3_TRACK: case CMND_MP3_VOLUME: @@ -206,7 +206,7 @@ boolean MP3PlayerCmd(void) { case CMND_MP3_PAUSE: case CMND_MP3_STOP: case CMND_MP3_RESET: - // play or re-play after pause, pause, stop, + // play or re-play after pause, pause, stop, if (command_code == CMND_MP3_PLAY) { MP3_CMD(MP3_CMD_PLAY, 0); } if (command_code == CMND_MP3_PAUSE) { MP3_CMD(MP3_CMD_PAUSE, 0); } if (command_code == CMND_MP3_STOP) { MP3_CMD(MP3_CMD_STOP, 0); } @@ -230,13 +230,15 @@ boolean Xdrv14(byte function) { boolean result = false; - switch (function) { - case FUNC_PRE_INIT: - MP3PlayerInit(); // init and start communication - break; - case FUNC_COMMAND: - result = MP3PlayerCmd(); // return result from mp3 player command - break; + if (pin[GPIO_MP3_DFR562] < 99) { + switch (function) { + case FUNC_PRE_INIT: + MP3PlayerInit(); // init and start communication + break; + case FUNC_COMMAND: + result = MP3PlayerCmd(); // return result from mp3 player command + break; + } } return result; } From a3ee9e74920db86652ddf125ba542dd2e0f3a8f3 Mon Sep 17 00:00:00 2001 From: wvdv2002 Date: Sun, 11 Nov 2018 16:58:21 +0100 Subject: [PATCH 0473/2222] Cleaned up code and settings --- sonoff/settings.h | 2 +- sonoff/sonoff.h | 2 +- sonoff/sonoff_template.h | 23 ++++----- sonoff/xdrv_18_armtronixDualDimmer.ino | 68 ++------------------------ 4 files changed, 14 insertions(+), 81 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index fcffe681f..cde1b2283 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -68,7 +68,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t time_append_timezone : 1; // bit 2 (v6.2.1.2) uint32_t gui_hostname_ip : 1; // bit 3 (v6.2.1.20) uint32_t tuya_apply_o20 : 1; // bit 4 (v6.3.0.4) - uint32_t armtronix_apply_o20 : 1; // bit 5 (v????) + uint32_t spare05 : 1; uint32_t spare06 : 1; uint32_t spare07 : 1; uint32_t spare08 : 1; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index ed23f80f2..1050557c0 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -221,7 +221,7 @@ enum ButtonStates { PRESSED, NOT_PRESSED }; enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; -enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_ARMTRONIX_DIMMER_ID, P_MDNS_DELAYED_START, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) +enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_MAX_SENSORS}; diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 412717677..be6b18085 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -133,8 +133,6 @@ enum UserSelectablePins { GPIO_RFRECV, // RF receiver GPIO_TUYA_TX, // Tuya Serial interface GPIO_TUYA_RX, // Tuya Serial interface - GPIO_ARMTRONIX_TX, // ARMTRONIX Serial interface - GPIO_ARMTRONIX_RX, // ARMTRONIX Serial interface GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -192,8 +190,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|" D_SENSOR_TX20_TX "|" D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|" - D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|" - D_SENSOR_ARMTRONIX_TX "|" D_SENSOR_ARMTRONIX_RX; + D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX; + /********************************************************************************************/ // Supported hardware modules @@ -429,10 +427,6 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_TUYA_TX, // Tuya Serial interface GPIO_TUYA_RX // Tuya Serial interface #endif -#ifdef USE_ARMTRONIX_DIMMERS - GPIO_ARMTRONIX_TX, // Tuya Serial interface - GPIO_ARMTRONIX_RX // Tuya Serial interface -#endif }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { @@ -1226,18 +1220,19 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, 0 }, - { "ARMTR Dimmr", // ARMTRONIX Dimmer (ESP8266 w/ separate MCU dimmer) - // https://www.amazon.com/gp/product/B07CTNSZZ8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1 - GPIO_USER, // Virtual Button (controlled by MCU) - GPIO_USER, // GPIO01 MCU serial control + { "ARMTR Dimmer", // ARMTRONIX Dimmer, one or two channel (ESP8266 w/ separate MCU dimmer) + // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-two-triac-board/ + // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-esp8266-one-triac-board-alexaecho/ + GPIO_USER, + GPIO_TXD, // GPIO01 MCU serial control GPIO_USER, - GPIO_USER, // GPIO03 MCU serial control + GPIO_RXD, // GPIO03 MCU serial control GPIO_USER, GPIO_USER, 0, 0, 0, 0, 0, 0, // Flash connection GPIO_USER, GPIO_USER, - GPIO_USER, // GPIO14 Green Led + GPIO_USER, GPIO_USER, GPIO_USER, 0 diff --git a/sonoff/xdrv_18_armtronixDualDimmer.ino b/sonoff/xdrv_18_armtronixDualDimmer.ino index 8b4c2ea83..0e440bd7e 100644 --- a/sonoff/xdrv_18_armtronixDualDimmer.ino +++ b/sonoff/xdrv_18_armtronixDualDimmer.ino @@ -23,12 +23,6 @@ #define XDRV_18 18 -#ifndef ARMTRONIX_DIMMER_ID -#define ARMTRONIX_DIMMER_ID 0 -#endif - -#define ARMTRONIX_POWER_ID 1 - #include TasmotaSerial *ArmtronixSerial = nullptr; @@ -45,25 +39,6 @@ int8_t armtronix_knobState[2]; //Dimmer state values. -boolean ArmtronixSetPower() -{ - boolean status = false; - - uint8_t rpower = XdrvMailbox.index; - int16_t source = XdrvMailbox.payload; - - if (source != SRC_SWITCH && ArmtronixSerial) { // ignore to prevent loop from pushing state from faceplate interaction - - snprintf_P(log_data, sizeof(log_data), PSTR("ARM: SetDevicePower.rpower=%d"), rpower); - AddLog(LOG_LEVEL_DEBUG); - //ArmtronixSendBool(ARMTRONIX_POWER_ID, rpower); - - status = true; - } - return status; -} - - void LightSerial2Duty(uint8_t duty1, uint8_t duty2) { if (ArmtronixSerial && !armtronix_ignore_dim) { @@ -76,7 +51,7 @@ void LightSerial2Duty(uint8_t duty1, uint8_t duty2) ArmtronixSerial->print("\nDimmer2:"); ArmtronixSerial->println(duty2); - snprintf_P(log_data, sizeof(log_data), PSTR( "ARM: Send Serial Packet Dim Values=%d,%d (id=%d)"), armtronix_dimState[0],armtronix_dimState[1], Settings.param[P_ARMTRONIX_DIMMER_ID]); + snprintf_P(log_data, sizeof(log_data), PSTR( "ARM: Send Serial Packet Dim Values=%d,%d"), armtronix_dimState[0],armtronix_dimState[1]); AddLog(LOG_LEVEL_DEBUG); } else { @@ -97,28 +72,12 @@ void ArmtronixRequestState(){ } } -void ArmtronixResetWifi() -{ - if (!Settings.flag.button_restrict) { - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2); - ExecuteCommand(scmnd, SRC_BUTTON); - } -} - /*********************************************************************************************\ * API Functions \*********************************************************************************************/ boolean ArmtronixModuleSelected() { - if (!(pin[GPIO_ARMTRONIX_RX] < 99) || !(pin[GPIO_ARMTRONIX_TX] < 99)) { // fallback to hardware-serial if not explicitly selected - pin[GPIO_ARMTRONIX_TX] = 1; - pin[GPIO_ARMTRONIX_RX] = 3; - Settings.my_gp.io[1] = GPIO_ARMTRONIX_TX; - Settings.my_gp.io[3] = GPIO_ARMTRONIX_RX; - restart_flag = 2; - } light_type = LT_SERIAL2; return true; } @@ -129,10 +88,7 @@ void ArmtronixInit() armtronix_dimState[1] = -1; armtronix_knobState[0] = -1; armtronix_knobState[1] = -1; - if (!Settings.param[P_ARMTRONIX_DIMMER_ID]) { - Settings.param[P_ARMTRONIX_DIMMER_ID] = ARMTRONIX_DIMMER_ID; - } - ArmtronixSerial = new TasmotaSerial(pin[GPIO_ARMTRONIX_RX], pin[GPIO_ARMTRONIX_TX], 2); + ArmtronixSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); if (ArmtronixSerial->begin(115200)) { if (ArmtronixSerial->hardwareSerial()) { ClaimSerial(); } ArmtronixSerial->println("Status"); @@ -171,17 +127,6 @@ void ArmtronixSerialInput() } } -boolean ArmtronixButtonPressed() -{ - if (!XdrvMailbox.index && ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == lastbutton[XdrvMailbox.index]))) { - snprintf_P(log_data, sizeof(log_data), PSTR("ARM: Reset GPIO triggered")); - AddLog(LOG_LEVEL_DEBUG); - ArmtronixResetWifi(); - return true; // Reset GPIO served here - } - return false; // Don't serve other buttons -} - void ArmtronixSetWifiLed(){ uint8_t wifi_state = 0x02; switch(WifiState()){ @@ -233,17 +178,10 @@ boolean Xdrv18(byte function) case FUNC_LOOP: if (ArmtronixSerial) { ArmtronixSerialInput(); } break; - case FUNC_SET_DEVICE_POWER: - result = ArmtronixSetPower(); - break; - case FUNC_BUTTON_PRESSED: - result = ArmtronixButtonPressed(); - break; case FUNC_EVERY_SECOND: if(ArmtronixSerial){ - flip = !flip; if (armtronix_wifi_state!=WifiState()) { ArmtronixSetWifiLed(); } - if(flip){ + if(uptime&1){ ArmtronixSerial->println("Status"); } } From c0cfdde8ac77fd64690bb96b5845479833867207 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 11 Nov 2018 17:58:18 +0100 Subject: [PATCH 0474/2222] Fix Sonoff Pow R2 and Sonoff S31 Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by Sonoff Basic R2 driver delay implementation (and possibly core bug) --- sonoff/_changelog.ino | 2 +- sonoff/support.ino | 9 +++++++++ sonoff/xdrv_interface.ino | 2 +- sonoff/xsns_interface.ino | 4 ++-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 23bbe3dc2..f664eb7a6 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,6 @@ /* 6.3.0.7 20181111 * Fix wifi connection errors using wifi disconnect and ESP.reset instead of ESP.restart - * Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by MP3 driver + * Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by Sonoff Basic R2 driver delay implementation (and possibly core bug) * * 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/support.ino b/sonoff/support.ino index 9389714ec..0c5203d69 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -765,6 +765,15 @@ uint8_t ValidGPIO(uint8_t pin, uint8_t gpio) return result; } +void AppDelay() +{ + if (APP_BAUDRATE == baudrate) { // When baudrate too low it will fail on Sonoff Pow R2 and S31 serial interface initialization + if (global_state.wifi_down) { + delay(DRIVER_BOOT_DELAY); + } + } +} + /*********************************************************************************************\ * Sleep aware time scheduler functions borrowed from ESPEasy \*********************************************************************************************/ diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 0f0171e20..cb3a69c22 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -238,7 +238,7 @@ boolean XdrvCall(byte Function) boolean result = false; for (byte x = 0; x < xdrv_present; x++) { - if (global_state.wifi_down) { delay(DRIVER_BOOT_DELAY); } + AppDelay(); result = xdrv_func_ptr[x](Function); if (result) break; } diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index a3cf4d772..723e8f070 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -568,7 +568,7 @@ boolean XsnsNextCall(byte Function) xsns_index++; if (xsns_index == xsns_present) { xsns_index = 0; } } - if (global_state.wifi_down) { delay(DRIVER_BOOT_DELAY); } + AppDelay(); return xsns_func_ptr[xsns_index](Function); } @@ -586,7 +586,7 @@ boolean XsnsCall(byte Function) #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND uint32_t profile_start_millis = millis(); #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND - if (global_state.wifi_down) { delay(DRIVER_BOOT_DELAY); } + AppDelay(); result = xsns_func_ptr[x](Function); #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND From 41aafe05ae7baab132743fe2e0b866c28c533a81 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 12 Nov 2018 10:20:30 +0100 Subject: [PATCH 0475/2222] Change command WebSend Change command WebSend Host header field from IP address to hostname (#4331) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_01_webserver.ino | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index f664eb7a6..ce35adbe0 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.3.0.7 20181111 * Fix wifi connection errors using wifi disconnect and ESP.reset instead of ESP.restart * Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by Sonoff Basic R2 driver delay implementation (and possibly core bug) + * Change command WebSend Host header field from IP address to hostname (#4331) * * 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 74e6d32f6..6f99b30a1 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1950,7 +1950,8 @@ int WebSend(char *buffer) String url = F("GET /cm?"); url += uri; url += F(" HTTP/1.1\r\n Host: "); - url += IPAddress(host_ip).toString(); +// url += IPAddress(host_ip).toString(); + url += host; // https://tools.ietf.org/html/rfc7230#section-5.4 (#4331) if (port) { url += F(" \r\n Port: "); url += port; From 59c581721470b654d495bea4caf2110aeb7be056 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 12 Nov 2018 11:10:55 +0100 Subject: [PATCH 0476/2222] Update command WebSend * Change command WebSend Host header field from IP address to hostname (#4331) * Add to command WebSend option to send a direct path when command starts with a slash (#4329) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_01_webserver.ino | 40 +++++++++++++++++++++--------------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index ce35adbe0..e661b54fb 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Fix wifi connection errors using wifi disconnect and ESP.reset instead of ESP.restart * Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by Sonoff Basic R2 driver delay implementation (and possibly core bug) * Change command WebSend Host header field from IP address to hostname (#4331) + * Add to command WebSend option to send a direct path when command starts with a slash (#4329) * * 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 6f99b30a1..5b989ce3b 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1895,9 +1895,11 @@ String UrlEncode(const String& text) int WebSend(char *buffer) { - // http://192.168.178.86:80/cm?user=admin&password=joker&cmnd=POWER1 ON - // http://192.168.178.86:80/cm?cmnd=POWER1 ON - // [192.168.178.86:80,admin:joker] POWER1 ON + /* [sonoff] POWER1 ON --> Sends http://sonoff/cm?cmnd=POWER1 ON + * [192.168.178.86:80,admin:joker] POWER1 ON --> Sends http://hostname:80/cm?user=admin&password=joker&cmnd=POWER1 ON + * [sonoff] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 + * [sonoff,admin:joker] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 + */ char *host; char *port; @@ -1923,15 +1925,19 @@ int WebSend(char *buffer) if (port) { nport = atoi(port); } String nuri = ""; - if (user && password) { - nuri += F("user="); - nuri += user; - nuri += F("&password="); - nuri += password; - nuri += F("&"); + command = LTrim(command); + if (command[0] != '/') { + nuri = "/cm?"; + if (user && password) { + nuri += F("user="); + nuri += user; + nuri += F("&password="); + nuri += password; + nuri += F("&"); + } + nuri += F("cmnd="); } - nuri += F("cmnd="); - nuri += LTrim(command); + nuri += command; // command = POWER1 ON or /any/link/starting/with/a/slash.php?log=123 String uri = UrlEncode(nuri); IPAddress host_ip; @@ -1947,19 +1953,19 @@ int WebSend(char *buffer) } if (connected) { - String url = F("GET /cm?"); + String url = F("GET "); url += uri; - url += F(" HTTP/1.1\r\n Host: "); + url += F(" HTTP/1.1\r\nHost: "); // url += IPAddress(host_ip).toString(); url += host; // https://tools.ietf.org/html/rfc7230#section-5.4 (#4331) if (port) { - url += F(" \r\n Port: "); + url += F(":"); url += port; } - url += F(" \r\n Connection: close\r\n\r\n"); + url += F("\r\nConnection: close\r\n\r\n"); -//snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Url |%s|"), url.c_str()); -//AddLog(LOG_LEVEL_DEBUG); +snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Url |%s|"), url.c_str()); +AddLog(LOG_LEVEL_DEBUG); client.print(url.c_str()); client.flush(); From 406907cbe27677b39f86865105e45f6441632cf6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 12 Nov 2018 11:11:22 +0100 Subject: [PATCH 0477/2222] Revert "Update command WebSend" This reverts commit 59c581721470b654d495bea4caf2110aeb7be056. --- sonoff/_changelog.ino | 1 - sonoff/xdrv_01_webserver.ino | 40 +++++++++++++++--------------------- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e661b54fb..ce35adbe0 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,7 +2,6 @@ * Fix wifi connection errors using wifi disconnect and ESP.reset instead of ESP.restart * Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by Sonoff Basic R2 driver delay implementation (and possibly core bug) * Change command WebSend Host header field from IP address to hostname (#4331) - * Add to command WebSend option to send a direct path when command starts with a slash (#4329) * * 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 5b989ce3b..6f99b30a1 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1895,11 +1895,9 @@ String UrlEncode(const String& text) int WebSend(char *buffer) { - /* [sonoff] POWER1 ON --> Sends http://sonoff/cm?cmnd=POWER1 ON - * [192.168.178.86:80,admin:joker] POWER1 ON --> Sends http://hostname:80/cm?user=admin&password=joker&cmnd=POWER1 ON - * [sonoff] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 - * [sonoff,admin:joker] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 - */ + // http://192.168.178.86:80/cm?user=admin&password=joker&cmnd=POWER1 ON + // http://192.168.178.86:80/cm?cmnd=POWER1 ON + // [192.168.178.86:80,admin:joker] POWER1 ON char *host; char *port; @@ -1925,19 +1923,15 @@ int WebSend(char *buffer) if (port) { nport = atoi(port); } String nuri = ""; - command = LTrim(command); - if (command[0] != '/') { - nuri = "/cm?"; - if (user && password) { - nuri += F("user="); - nuri += user; - nuri += F("&password="); - nuri += password; - nuri += F("&"); - } - nuri += F("cmnd="); + if (user && password) { + nuri += F("user="); + nuri += user; + nuri += F("&password="); + nuri += password; + nuri += F("&"); } - nuri += command; // command = POWER1 ON or /any/link/starting/with/a/slash.php?log=123 + nuri += F("cmnd="); + nuri += LTrim(command); String uri = UrlEncode(nuri); IPAddress host_ip; @@ -1953,19 +1947,19 @@ int WebSend(char *buffer) } if (connected) { - String url = F("GET "); + String url = F("GET /cm?"); url += uri; - url += F(" HTTP/1.1\r\nHost: "); + url += F(" HTTP/1.1\r\n Host: "); // url += IPAddress(host_ip).toString(); url += host; // https://tools.ietf.org/html/rfc7230#section-5.4 (#4331) if (port) { - url += F(":"); + url += F(" \r\n Port: "); url += port; } - url += F("\r\nConnection: close\r\n\r\n"); + url += F(" \r\n Connection: close\r\n\r\n"); -snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Url |%s|"), url.c_str()); -AddLog(LOG_LEVEL_DEBUG); +//snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Url |%s|"), url.c_str()); +//AddLog(LOG_LEVEL_DEBUG); client.print(url.c_str()); client.flush(); From d3f5c8978b03f8ed1791c9d385ebb2e439550639 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 12 Nov 2018 11:13:05 +0100 Subject: [PATCH 0478/2222] Update command WebSend * Change command WebSend Host header field from IP address to hostname (#4331) * Add to command WebSend option to send a direct path when command starts with a slash (#4329) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_01_webserver.ino | 36 +++++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index ce35adbe0..e661b54fb 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Fix wifi connection errors using wifi disconnect and ESP.reset instead of ESP.restart * Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by Sonoff Basic R2 driver delay implementation (and possibly core bug) * Change command WebSend Host header field from IP address to hostname (#4331) + * Add to command WebSend option to send a direct path when command starts with a slash (#4329) * * 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 6f99b30a1..ed14472cd 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1895,9 +1895,11 @@ String UrlEncode(const String& text) int WebSend(char *buffer) { - // http://192.168.178.86:80/cm?user=admin&password=joker&cmnd=POWER1 ON - // http://192.168.178.86:80/cm?cmnd=POWER1 ON - // [192.168.178.86:80,admin:joker] POWER1 ON + /* [sonoff] POWER1 ON --> Sends http://sonoff/cm?cmnd=POWER1 ON + * [192.168.178.86:80,admin:joker] POWER1 ON --> Sends http://hostname:80/cm?user=admin&password=joker&cmnd=POWER1 ON + * [sonoff] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 + * [sonoff,admin:joker] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 + */ char *host; char *port; @@ -1923,15 +1925,19 @@ int WebSend(char *buffer) if (port) { nport = atoi(port); } String nuri = ""; - if (user && password) { - nuri += F("user="); - nuri += user; - nuri += F("&password="); - nuri += password; - nuri += F("&"); + command = LTrim(command); + if (command[0] != '/') { + nuri = "/cm?"; + if (user && password) { + nuri += F("user="); + nuri += user; + nuri += F("&password="); + nuri += password; + nuri += F("&"); + } + nuri += F("cmnd="); } - nuri += F("cmnd="); - nuri += LTrim(command); + nuri += command; // command = POWER1 ON or /any/link/starting/with/a/slash.php?log=123 String uri = UrlEncode(nuri); IPAddress host_ip; @@ -1947,16 +1953,16 @@ int WebSend(char *buffer) } if (connected) { - String url = F("GET /cm?"); + String url = F("GET "); url += uri; - url += F(" HTTP/1.1\r\n Host: "); + url += F(" HTTP/1.1\r\nHost: "); // url += IPAddress(host_ip).toString(); url += host; // https://tools.ietf.org/html/rfc7230#section-5.4 (#4331) if (port) { - url += F(" \r\n Port: "); + url += F(":"); url += port; } - url += F(" \r\n Connection: close\r\n\r\n"); + url += F("\r\nConnection: close\r\n\r\n"); //snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Url |%s|"), url.c_str()); //AddLog(LOG_LEVEL_DEBUG); From e2dd11b0bcd195c18c69a0f59822df46eec79f74 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 12 Nov 2018 12:33:49 +0100 Subject: [PATCH 0479/2222] Consolidate LTrim into Trim Consolidate LTrim into Trim --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 6 +++--- sonoff/support.ino | 8 ++++---- sonoff/xdrv_01_webserver.ino | 31 +++++++++++++++++-------------- 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e661b54fb..cc698a386 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by Sonoff Basic R2 driver delay implementation (and possibly core bug) * Change command WebSend Host header field from IP address to hostname (#4331) * Add to command WebSend option to send a direct path when command starts with a slash (#4329) + * Consolidate LTrim into Trim * * 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index e92536a1b..0c7b16beb 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -531,7 +531,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) char *blcommand = strtok(dataBuf, ";"); while ((blcommand != NULL) && (backlog_index != bl_pointer)) { while(true) { - blcommand = LTrim(blcommand); + blcommand = Trim(blcommand); if (!strncasecmp_P(blcommand, PSTR(D_CMND_BACKLOG), strlen(D_CMND_BACKLOG))) { blcommand += strlen(D_CMND_BACKLOG); // Skip unnecessary command Backlog } else { @@ -1224,9 +1224,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if (5 == tpos) { Settings.tflag[ts].hour = (value < 0) ? 0 : (value > 23) ? 23 : value; } if (6 == tpos) { Settings.toffset[ts] = (value < -900) ? -900 : (value > 900) ? 900 : value; } } - p = LTrim(p); // Skip spaces + p = Trim(p); // Skip spaces if (tpos && (*p == ',')) { p++; } // Skip separator - p = LTrim(p); // Skip spaces + p = Trim(p); // Skip spaces q = p; // Reset any value entered flag value = strtol(p, &p, 10); tpos++; // Next parameter diff --git a/sonoff/support.ino b/sonoff/support.ino index 0c5203d69..7df675b13 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -290,6 +290,7 @@ char* UpperCase_P(char* dest, const char* source) return dest; } +/* char* LTrim(char* p) { while ((*p != '\0') && (isblank(*p))) { @@ -308,14 +309,13 @@ char* RTrim(char* p) *q = '\0'; return p; } +*/ char* Trim(char* p) { - if (*p == '\0') { return p; } - while (isspace(*p)) { p++; } // Trim leading spaces - if (*p == '\0') { return p; } + while ((*p != '\0') && isblank(*p)) { p++; } // Trim leading spaces char* q = p + strlen(p) -1; - while (isspace(*q) && q >= p) { q--; } // Trim trailing spaces + while ((q >= p) && isblank(*q)) { q--; } // Trim trailing spaces q++; *q = '\0'; return p; diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index ed14472cd..25c4c013b 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1909,23 +1909,26 @@ int WebSend(char *buffer) uint16_t nport = 80; int status = 1; // Wrong parameters - host = strtok_r(buffer, "]", &command); // buffer = [192.168.178.86:80,admin:joker] POWER1 ON + // buffer = | [ 192.168.178.86 : 80 , admin : joker ] POWER1 ON | + host = strtok_r(buffer, "]", &command); // host = | [ 192.168.178.86 : 80 , admin : joker |, command = | POWER1 ON | if (host && command) { - host = LTrim(host); - host++; // Skip [ - host = strtok_r(host, ",", &user); // host = 192.168.178.86:80,admin:joker > 192.168.178.86:80 - host = strtok_r(host, ":", &port); // host = 192.168.178.86:80 > 192.168.178.86 - if (user) { - user = strtok_r(user, ":", &password); // user = admin:joker > admin + host = Trim(host); // host = |[ 192.168.178.86 : 80 , admin : joker| + host++; // host = | 192.168.178.86 : 80 , admin : joker| - Skip [ + host = strtok_r(host, ",", &user); // host = | 192.168.178.86 : 80 |, user = | admin : joker| + host = strtok_r(host, ":", &port); // host = | 192.168.178.86 |, port = | 80 | + host = Trim(host); // host = |192.168.178.86| + if (port) { + port = Trim(port); // port = |80| + nport = atoi(port); } - -//snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Buffer |%X|, Host |%X|, Port |%X|, User |%X|, Password |%X|, Command |%X|"), buffer, host, port, user, password, command); -//AddLog(LOG_LEVEL_DEBUG); - - if (port) { nport = atoi(port); } + if (user) { + user = strtok_r(user, ":", &password); // user = | admin |, password = | joker| + user = Trim(user); // user = |admin| + if (password) { password = Trim(password); } // password = |joker| + } + command = Trim(command); // command = |POWER1 ON| or |/any/link/starting/with/a/slash.php?log=123| String nuri = ""; - command = LTrim(command); if (command[0] != '/') { nuri = "/cm?"; if (user && password) { @@ -1937,7 +1940,7 @@ int WebSend(char *buffer) } nuri += F("cmnd="); } - nuri += command; // command = POWER1 ON or /any/link/starting/with/a/slash.php?log=123 + nuri += command; String uri = UrlEncode(nuri); IPAddress host_ip; From 830319bc6e19cbeb4d5eeb813bbcf38850dcd125 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 12 Nov 2018 15:09:09 +0100 Subject: [PATCH 0480/2222] Moved command SetSensorXX Moved command SetSensorXX to debugging --- sonoff/_changelog.ino | 1 + sonoff/i18n.h | 1 - sonoff/sonoff.ino | 15 +- .../{xdrv_95_debug.ino => xdrv_99_debug.ino} | 26 +- sonoff/xsns_interface.ino | 297 +---------------- sonoff/zzzz_debug.ino | 309 ++++++++++++++++++ 6 files changed, 340 insertions(+), 309 deletions(-) rename sonoff/{xdrv_95_debug.ino => xdrv_99_debug.ino} (94%) create mode 100644 sonoff/zzzz_debug.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index cc698a386..60e68853d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,6 +4,7 @@ * Change command WebSend Host header field from IP address to hostname (#4331) * Add to command WebSend option to send a direct path when command starts with a slash (#4329) * Consolidate LTrim into Trim + * Moved command SetSensorXX to debugging * * 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 36d93ccd7..f53433553 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -184,7 +184,6 @@ #define D_CMND_DRIVER "Driver" #define D_CMND_SAVEDATA "SaveData" #define D_CMND_SETOPTION "SetOption" -#define D_CMND_SETSENSOR "SetSensor" #define D_CMND_TEMPERATURE_RESOLUTION "TempRes" #define D_CMND_HUMIDITY_RESOLUTION "HumRes" #define D_CMND_PRESSURE_RESOLUTION "PressRes" diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 0c7b16beb..43ca32952 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -81,7 +81,7 @@ enum TasmotaCommands { CMND_MODULE, CMND_MODULES, CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE, CMND_COUNTERDEBOUNCE, CMND_BUTTONDEBOUNCE, CMND_SWITCHDEBOUNCE, 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_SETSENSOR, + CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_TIMESTD, CMND_TIMEDST, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER, CMND_DRIVER }; const char kTasmotaCommands[] PROGMEM = @@ -91,7 +91,7 @@ const char kTasmotaCommands[] PROGMEM = 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_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" 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_SETSENSOR "|" + D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER "|" D_CMND_DRIVER; @@ -777,13 +777,6 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, (2 == ptype) ? stemp1 : (1 == ptype) ? GetStateText(bitRead(Settings.flag3.data, pindex)) : GetStateText(bitRead(Settings.flag.data, pindex))); } } - else if ((CMND_SETSENSOR == command_code) && (index < MAX_XSNS_DRIVERS)) { - if ((payload >= 0) && XsnsPresent(index)) { - bitWrite(Settings.sensors[index / 32], index % 32, payload &1); - if (1 == payload) { restart_flag = 2; } // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, XsnsGetSensors().c_str()); - } else if (CMND_TEMPERATURE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.temperature_resolution = payload; @@ -1224,9 +1217,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if (5 == tpos) { Settings.tflag[ts].hour = (value < 0) ? 0 : (value > 23) ? 23 : value; } if (6 == tpos) { Settings.toffset[ts] = (value < -900) ? -900 : (value > 900) ? 900 : value; } } - p = Trim(p); // Skip spaces + p = Trim(p); // Skip spaces if (tpos && (*p == ',')) { p++; } // Skip separator - p = Trim(p); // Skip spaces + p = Trim(p); // Skip spaces q = p; // Reset any value entered flag value = strtol(p, &p, 10); tpos++; // Next parameter diff --git a/sonoff/xdrv_95_debug.ino b/sonoff/xdrv_99_debug.ino similarity index 94% rename from sonoff/xdrv_95_debug.ino rename to sonoff/xdrv_99_debug.ino index 18f9ad76f..26a5ad2dc 100644 --- a/sonoff/xdrv_95_debug.ino +++ b/sonoff/xdrv_99_debug.ino @@ -1,5 +1,5 @@ /* - xdrv_95_debug.ino - debug support for Sonoff-Tasmota + xdrv_99_debug.ino - debug support for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -27,10 +27,12 @@ #ifdef USE_DEBUG_DRIVER /*********************************************************************************************\ - * Virtual debugging support + * Virtual debugging support - Part1 + * + * Needs file zzzz_debug.ino due to DEFINE processing \*********************************************************************************************/ -#define XDRV_95 95 +#define XDRV_99 99 #ifndef CPU_LOAD_CHECK #define CPU_LOAD_CHECK 1 // Seconds between each CPU_LOAD log @@ -50,9 +52,14 @@ #define D_CMND_FREEMEM "FreeMem" #define D_CMND_RTCDUMP "RtcDump" #define D_CMND_HELP "Help" +#define D_CMND_SETSENSOR "SetSensor" -enum DebugCommands { CMND_CFGDUMP, CMND_CFGPEEK, CMND_CFGPOKE, CMND_CFGSHOW, CMND_CFGXOR, CMND_CPUCHECK, CMND_EXCEPTION, CMND_FREEMEM, CMND_RTCDUMP, CMND_HELP }; -const char kDebugCommands[] PROGMEM = D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" D_CMND_CFGSHOW "|" D_CMND_CFGXOR "|" D_CMND_CPUCHECK "|" D_CMND_EXCEPTION "|" D_CMND_FREEMEM "|" D_CMND_RTCDUMP "|" D_CMND_HELP; +enum DebugCommands { + CMND_CFGDUMP, CMND_CFGPEEK, CMND_CFGPOKE, CMND_CFGSHOW, CMND_CFGXOR, + CMND_CPUCHECK, CMND_EXCEPTION, CMND_FREEMEM, CMND_RTCDUMP, CMND_SETSENSOR, CMND_HELP }; +const char kDebugCommands[] PROGMEM = + D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" D_CMND_CFGSHOW "|" D_CMND_CFGXOR "|" + D_CMND_CPUCHECK "|" D_CMND_EXCEPTION "|" D_CMND_FREEMEM "|" D_CMND_RTCDUMP "|" D_CMND_SETSENSOR "|" D_CMND_HELP; uint32_t CPU_loops = 0; uint32_t CPU_last_millis = 0; @@ -469,6 +476,13 @@ boolean DebugCommand() } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, CPU_show_freemem); } + else if ((CMND_SETSENSOR == command_code) && (XdrvMailbox.index < MAX_XSNS_DRIVERS)) { + if ((XdrvMailbox.payload >= 0) && XsnsPresent(XdrvMailbox.index)) { + bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); + if (1 == XdrvMailbox.payload) { restart_flag = 2; } // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, XsnsGetSensors().c_str()); + } else serviced = false; // Unknown command return serviced; @@ -478,7 +492,7 @@ boolean DebugCommand() * Interface \*********************************************************************************************/ -boolean Xdrv95(byte function) +boolean Xdrv99(byte function) { boolean result = false; diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index 723e8f070..ab466d25c 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -265,309 +265,20 @@ boolean (* const xsns_func_ptr[])(byte) = { // Sensor Function Pointers for sim const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); // Number of External Sensors found uint8_t xsns_index = 0; -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kXsnsList[] PROGMEM = { -#else -const uint8_t kXsnsList[] = { -#endif - -#ifdef XSNS_01 - XSNS_01, -#endif - -#ifdef XSNS_02 - XSNS_02, -#endif - -#ifdef XSNS_03 - XSNS_03, -#endif - -#ifdef XSNS_04 - XSNS_04, -#endif - -#ifdef XSNS_05 - XSNS_05, -#endif - -#ifdef XSNS_06 - XSNS_06, -#endif - -#ifdef XSNS_07 - XSNS_07, -#endif - -#ifdef XSNS_08 - XSNS_08, -#endif - -#ifdef XSNS_09 - XSNS_09, -#endif - -#ifdef XSNS_10 - XSNS_10, -#endif - -#ifdef XSNS_11 - XSNS_11, -#endif - -#ifdef XSNS_12 - XSNS_12, -#endif - -#ifdef XSNS_13 - XSNS_13, -#endif - -#ifdef XSNS_14 - XSNS_14, -#endif - -#ifdef XSNS_15 - XSNS_15, -#endif - -#ifdef XSNS_16 - XSNS_16, -#endif - -#ifdef XSNS_17 - XSNS_17, -#endif - -#ifdef XSNS_18 - XSNS_18, -#endif - -#ifdef XSNS_19 - XSNS_19, -#endif - -#ifdef XSNS_20 - XSNS_20, -#endif - -#ifdef XSNS_21 - XSNS_21, -#endif - -#ifdef XSNS_22 - XSNS_22, -#endif - -#ifdef XSNS_23 - XSNS_23, -#endif - -#ifdef XSNS_24 - XSNS_24, -#endif - -#ifdef XSNS_25 - XSNS_25, -#endif - -#ifdef XSNS_26 - XSNS_26, -#endif - -#ifdef XSNS_27 - XSNS_27, -#endif - -#ifdef XSNS_28 - XSNS_28, -#endif - -#ifdef XSNS_29 - XSNS_29, -#endif - -#ifdef XSNS_30 - XSNS_30, -#endif - -#ifdef XSNS_31 - XSNS_31, -#endif - -#ifdef XSNS_32 - XSNS_32, -#endif - -#ifdef XSNS_33 - XSNS_33, -#endif - -#ifdef XSNS_34 - XSNS_34, -#endif - -#ifdef XSNS_35 - XSNS_35, -#endif - -#ifdef XSNS_36 - XSNS_36, -#endif - -#ifdef XSNS_37 - XSNS_37, -#endif - -#ifdef XSNS_38 - XSNS_38, -#endif - -#ifdef XSNS_39 - XSNS_39, -#endif - -#ifdef XSNS_40 - XSNS_40, -#endif - -#ifdef XSNS_41 - XSNS_41, -#endif - -#ifdef XSNS_42 - XSNS_42, -#endif - -#ifdef XSNS_43 - XSNS_43, -#endif - -#ifdef XSNS_44 - XSNS_44, -#endif - -#ifdef XSNS_45 - XSNS_45, -#endif - -#ifdef XSNS_46 - XSNS_46, -#endif - -#ifdef XSNS_47 - XSNS_47, -#endif - -#ifdef XSNS_48 - XSNS_48, -#endif - -#ifdef XSNS_49 - XSNS_49, -#endif - -#ifdef XSNS_50 - XSNS_50, -#endif - -// Optional user defined sensors in range 91 - 99 - -#ifdef XSNS_91 - XSNS_91, -#endif - -#ifdef XSNS_92 - XSNS_92, -#endif - -#ifdef XSNS_93 - XSNS_93, -#endif - -#ifdef XSNS_94 - XSNS_94, -#endif - -#ifdef XSNS_95 - XSNS_95, -#endif - -#ifdef XSNS_96 - XSNS_96, -#endif - -#ifdef XSNS_97 - XSNS_97, -#endif - -#ifdef XSNS_98 - XSNS_98, -#endif - -#ifdef XSNS_99 - XSNS_99 -#endif -}; - - /*********************************************************************************************\ * Function call to all xsns \*********************************************************************************************/ -boolean XsnsEnabled(byte sns_index) -{ - if (sns_index < sizeof(kXsnsList)) { -#ifdef XFUNC_PTR_IN_ROM - uint8_t index = pgm_read_byte(kXsnsList + sns_index); -#else - uint8_t index = kXsnsList[sns_index]; -#endif - return bitRead(Settings.sensors[index / 32], index % 32); - } - return 1; -} - -boolean XsnsPresent(byte sns_index) -{ - uint8_t index = 0; - for (byte i = 0; i < sizeof(kXsnsList); i++) { -#ifdef XFUNC_PTR_IN_ROM - index = pgm_read_byte(kXsnsList + i); -#else - index = kXsnsList[i]; -#endif - if (index == sns_index) { return true; } - } - return false; -} - -String XsnsGetSensors() -{ - char state[2] = { 0 }; - - String data = F("["); - for (byte i = 0; i < MAX_XSNS_DRIVERS; i++) { - if (i && (!(i % 16))) { data += F(","); } - if (!(i % 16)) { data += F("\""); } - state[0] = '-'; - if (XsnsPresent(i)) { state[0] = bitRead(Settings.sensors[i / 32], i % 32) ? '1' : '0'; } - data += String(state); - if (i && (!((i +1) % 16))) { data += F("\""); } - } - data += F("]"); - - return data; -} - boolean XsnsNextCall(byte Function) { xsns_index++; if (xsns_index == xsns_present) { xsns_index = 0; } +#ifdef USE_DEBUG_DRIVER while (!XsnsEnabled(xsns_index) && !xsns_index) { // Perform at least first sensor (counter) xsns_index++; if (xsns_index == xsns_present) { xsns_index = 0; } } +#endif AppDelay(); return xsns_func_ptr[xsns_index](Function); } @@ -581,7 +292,9 @@ boolean XsnsCall(byte Function) #endif // PROFILE_XSNS_EVERY_SECOND for (byte x = 0; x < xsns_present; x++) { +#ifdef USE_DEBUG_DRIVER if (XsnsEnabled(x)) { +#endif #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND uint32_t profile_start_millis = millis(); @@ -600,7 +313,9 @@ boolean XsnsCall(byte Function) #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND if (result) break; +#ifdef USE_DEBUG_DRIVER } +#endif } #ifdef PROFILE_XSNS_EVERY_SECOND diff --git a/sonoff/zzzz_debug.ino b/sonoff/zzzz_debug.ino new file mode 100644 index 000000000..9f07c29ce --- /dev/null +++ b/sonoff/zzzz_debug.ino @@ -0,0 +1,309 @@ +/* + zzzz_debug.ino - debug support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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_DEBUG_DRIVER +/*********************************************************************************************\ + * Virtual debugging support - Part 2 + * + * Needs to be the last alphabetical file due to DEFINE compile order +\*********************************************************************************************/ + +/*********************************************************************************************\ + * Xsns available list +\*********************************************************************************************/ + +#ifdef XFUNC_PTR_IN_ROM +const uint8_t kXsnsList[] PROGMEM = { +#else +const uint8_t kXsnsList[] = { +#endif + +#ifdef XSNS_01 + XSNS_01, +#endif + +#ifdef XSNS_02 + XSNS_02, +#endif + +#ifdef XSNS_03 + XSNS_03, +#endif + +#ifdef XSNS_04 + XSNS_04, +#endif + +#ifdef XSNS_05 + XSNS_05, +#endif + +#ifdef XSNS_06 + XSNS_06, +#endif + +#ifdef XSNS_07 + XSNS_07, +#endif + +#ifdef XSNS_08 + XSNS_08, +#endif + +#ifdef XSNS_09 + XSNS_09, +#endif + +#ifdef XSNS_10 + XSNS_10, +#endif + +#ifdef XSNS_11 + XSNS_11, +#endif + +#ifdef XSNS_12 + XSNS_12, +#endif + +#ifdef XSNS_13 + XSNS_13, +#endif + +#ifdef XSNS_14 + XSNS_14, +#endif + +#ifdef XSNS_15 + XSNS_15, +#endif + +#ifdef XSNS_16 + XSNS_16, +#endif + +#ifdef XSNS_17 + XSNS_17, +#endif + +#ifdef XSNS_18 + XSNS_18, +#endif + +#ifdef XSNS_19 + XSNS_19, +#endif + +#ifdef XSNS_20 + XSNS_20, +#endif + +#ifdef XSNS_21 + XSNS_21, +#endif + +#ifdef XSNS_22 + XSNS_22, +#endif + +#ifdef XSNS_23 + XSNS_23, +#endif + +#ifdef XSNS_24 + XSNS_24, +#endif + +#ifdef XSNS_25 + XSNS_25, +#endif + +#ifdef XSNS_26 + XSNS_26, +#endif + +#ifdef XSNS_27 + XSNS_27, +#endif + +#ifdef XSNS_28 + XSNS_28, +#endif + +#ifdef XSNS_29 + XSNS_29, +#endif + +#ifdef XSNS_30 + XSNS_30, +#endif + +#ifdef XSNS_31 + XSNS_31, +#endif + +#ifdef XSNS_32 + XSNS_32, +#endif + +#ifdef XSNS_33 + XSNS_33, +#endif + +#ifdef XSNS_34 + XSNS_34, +#endif + +#ifdef XSNS_35 + XSNS_35, +#endif + +#ifdef XSNS_36 + XSNS_36, +#endif + +#ifdef XSNS_37 + XSNS_37, +#endif + +#ifdef XSNS_38 + XSNS_38, +#endif + +#ifdef XSNS_39 + XSNS_39, +#endif + +#ifdef XSNS_40 + XSNS_40, +#endif + +#ifdef XSNS_41 + XSNS_41, +#endif + +#ifdef XSNS_42 + XSNS_42, +#endif + +#ifdef XSNS_43 + XSNS_43, +#endif + +#ifdef XSNS_44 + XSNS_44, +#endif + +#ifdef XSNS_45 + XSNS_45, +#endif + +#ifdef XSNS_46 + XSNS_46, +#endif + +#ifdef XSNS_47 + XSNS_47, +#endif + +#ifdef XSNS_48 + XSNS_48, +#endif + +#ifdef XSNS_49 + XSNS_49, +#endif + +#ifdef XSNS_50 + XSNS_50, +#endif + +// Optional user defined sensors in range 91 - 99 + +#ifdef XSNS_91 + XSNS_91, +#endif + +#ifdef XSNS_92 + XSNS_92, +#endif + +#ifdef XSNS_93 + XSNS_93, +#endif + +#ifdef XSNS_94 + XSNS_94, +#endif + +#ifdef XSNS_95 + XSNS_95 +#endif +}; + +/*********************************************************************************************\ + * Xsns sensor control +\*********************************************************************************************/ + +boolean XsnsEnabled(byte sns_index) +{ + if (sns_index < sizeof(kXsnsList)) { +#ifdef XFUNC_PTR_IN_ROM + uint8_t index = pgm_read_byte(kXsnsList + sns_index); +#else + uint8_t index = kXsnsList[sns_index]; +#endif + return bitRead(Settings.sensors[index / 32], index % 32); + } + return 1; +} + +boolean XsnsPresent(byte sns_index) +{ + uint8_t index = 0; + for (byte i = 0; i < sizeof(kXsnsList); i++) { +#ifdef XFUNC_PTR_IN_ROM + index = pgm_read_byte(kXsnsList + i); +#else + index = kXsnsList[i]; +#endif + if (index == sns_index) { return true; } + } + return false; +} + +String XsnsGetSensors() +{ + char state[2] = { 0 }; + + String data = F("["); + for (byte i = 0; i < MAX_XSNS_DRIVERS; i++) { + if (i && (!(i % 16))) { data += F(","); } + if (!(i % 16)) { data += F("\""); } + state[0] = '-'; + if (XsnsPresent(i)) { state[0] = bitRead(Settings.sensors[i / 32], i % 32) ? '1' : '0'; } + data += String(state); + if (i && (!((i +1) % 16))) { data += F("\""); } + } + data += F("]"); + + return data; +} + +#endif // USE_DEBUG_DRIVER \ No newline at end of file From 3ef78e809548a26b0f621b6841846cb0b8872eac Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 12 Nov 2018 15:54:18 +0100 Subject: [PATCH 0481/2222] Revert "Moved command SetSensorXX" This reverts commit 830319bc6e19cbeb4d5eeb813bbcf38850dcd125. --- sonoff/_changelog.ino | 1 - sonoff/i18n.h | 1 + sonoff/sonoff.ino | 15 +- .../{xdrv_99_debug.ino => xdrv_95_debug.ino} | 26 +- sonoff/xsns_interface.ino | 297 ++++++++++++++++- sonoff/zzzz_debug.ino | 309 ------------------ 6 files changed, 309 insertions(+), 340 deletions(-) rename sonoff/{xdrv_99_debug.ino => xdrv_95_debug.ino} (94%) delete mode 100644 sonoff/zzzz_debug.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 60e68853d..cc698a386 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,7 +4,6 @@ * Change command WebSend Host header field from IP address to hostname (#4331) * Add to command WebSend option to send a direct path when command starts with a slash (#4329) * Consolidate LTrim into Trim - * Moved command SetSensorXX to debugging * * 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/i18n.h b/sonoff/i18n.h index f53433553..36d93ccd7 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -184,6 +184,7 @@ #define D_CMND_DRIVER "Driver" #define D_CMND_SAVEDATA "SaveData" #define D_CMND_SETOPTION "SetOption" +#define D_CMND_SETSENSOR "SetSensor" #define D_CMND_TEMPERATURE_RESOLUTION "TempRes" #define D_CMND_HUMIDITY_RESOLUTION "HumRes" #define D_CMND_PRESSURE_RESOLUTION "PressRes" diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 43ca32952..0c7b16beb 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -81,7 +81,7 @@ enum TasmotaCommands { CMND_MODULE, CMND_MODULES, CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE, CMND_COUNTERDEBOUNCE, CMND_BUTTONDEBOUNCE, CMND_SWITCHDEBOUNCE, 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_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_SETSENSOR, CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_TIMESTD, CMND_TIMEDST, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER, CMND_DRIVER }; const char kTasmotaCommands[] PROGMEM = @@ -91,7 +91,7 @@ const char kTasmotaCommands[] PROGMEM = 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_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" 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_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_SETSENSOR "|" D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER "|" D_CMND_DRIVER; @@ -777,6 +777,13 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, (2 == ptype) ? stemp1 : (1 == ptype) ? GetStateText(bitRead(Settings.flag3.data, pindex)) : GetStateText(bitRead(Settings.flag.data, pindex))); } } + else if ((CMND_SETSENSOR == command_code) && (index < MAX_XSNS_DRIVERS)) { + if ((payload >= 0) && XsnsPresent(index)) { + bitWrite(Settings.sensors[index / 32], index % 32, payload &1); + if (1 == payload) { restart_flag = 2; } // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, XsnsGetSensors().c_str()); + } else if (CMND_TEMPERATURE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.temperature_resolution = payload; @@ -1217,9 +1224,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if (5 == tpos) { Settings.tflag[ts].hour = (value < 0) ? 0 : (value > 23) ? 23 : value; } if (6 == tpos) { Settings.toffset[ts] = (value < -900) ? -900 : (value > 900) ? 900 : value; } } - p = Trim(p); // Skip spaces + p = Trim(p); // Skip spaces if (tpos && (*p == ',')) { p++; } // Skip separator - p = Trim(p); // Skip spaces + p = Trim(p); // Skip spaces q = p; // Reset any value entered flag value = strtol(p, &p, 10); tpos++; // Next parameter diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_95_debug.ino similarity index 94% rename from sonoff/xdrv_99_debug.ino rename to sonoff/xdrv_95_debug.ino index 26a5ad2dc..18f9ad76f 100644 --- a/sonoff/xdrv_99_debug.ino +++ b/sonoff/xdrv_95_debug.ino @@ -1,5 +1,5 @@ /* - xdrv_99_debug.ino - debug support for Sonoff-Tasmota + xdrv_95_debug.ino - debug support for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -27,12 +27,10 @@ #ifdef USE_DEBUG_DRIVER /*********************************************************************************************\ - * Virtual debugging support - Part1 - * - * Needs file zzzz_debug.ino due to DEFINE processing + * Virtual debugging support \*********************************************************************************************/ -#define XDRV_99 99 +#define XDRV_95 95 #ifndef CPU_LOAD_CHECK #define CPU_LOAD_CHECK 1 // Seconds between each CPU_LOAD log @@ -52,14 +50,9 @@ #define D_CMND_FREEMEM "FreeMem" #define D_CMND_RTCDUMP "RtcDump" #define D_CMND_HELP "Help" -#define D_CMND_SETSENSOR "SetSensor" -enum DebugCommands { - CMND_CFGDUMP, CMND_CFGPEEK, CMND_CFGPOKE, CMND_CFGSHOW, CMND_CFGXOR, - CMND_CPUCHECK, CMND_EXCEPTION, CMND_FREEMEM, CMND_RTCDUMP, CMND_SETSENSOR, CMND_HELP }; -const char kDebugCommands[] PROGMEM = - D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" D_CMND_CFGSHOW "|" D_CMND_CFGXOR "|" - D_CMND_CPUCHECK "|" D_CMND_EXCEPTION "|" D_CMND_FREEMEM "|" D_CMND_RTCDUMP "|" D_CMND_SETSENSOR "|" D_CMND_HELP; +enum DebugCommands { CMND_CFGDUMP, CMND_CFGPEEK, CMND_CFGPOKE, CMND_CFGSHOW, CMND_CFGXOR, CMND_CPUCHECK, CMND_EXCEPTION, CMND_FREEMEM, CMND_RTCDUMP, CMND_HELP }; +const char kDebugCommands[] PROGMEM = D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" D_CMND_CFGSHOW "|" D_CMND_CFGXOR "|" D_CMND_CPUCHECK "|" D_CMND_EXCEPTION "|" D_CMND_FREEMEM "|" D_CMND_RTCDUMP "|" D_CMND_HELP; uint32_t CPU_loops = 0; uint32_t CPU_last_millis = 0; @@ -476,13 +469,6 @@ boolean DebugCommand() } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, CPU_show_freemem); } - else if ((CMND_SETSENSOR == command_code) && (XdrvMailbox.index < MAX_XSNS_DRIVERS)) { - if ((XdrvMailbox.payload >= 0) && XsnsPresent(XdrvMailbox.index)) { - bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); - if (1 == XdrvMailbox.payload) { restart_flag = 2; } // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, XsnsGetSensors().c_str()); - } else serviced = false; // Unknown command return serviced; @@ -492,7 +478,7 @@ boolean DebugCommand() * Interface \*********************************************************************************************/ -boolean Xdrv99(byte function) +boolean Xdrv95(byte function) { boolean result = false; diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index ab466d25c..723e8f070 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -265,20 +265,309 @@ boolean (* const xsns_func_ptr[])(byte) = { // Sensor Function Pointers for sim const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); // Number of External Sensors found uint8_t xsns_index = 0; +#ifdef XFUNC_PTR_IN_ROM +const uint8_t kXsnsList[] PROGMEM = { +#else +const uint8_t kXsnsList[] = { +#endif + +#ifdef XSNS_01 + XSNS_01, +#endif + +#ifdef XSNS_02 + XSNS_02, +#endif + +#ifdef XSNS_03 + XSNS_03, +#endif + +#ifdef XSNS_04 + XSNS_04, +#endif + +#ifdef XSNS_05 + XSNS_05, +#endif + +#ifdef XSNS_06 + XSNS_06, +#endif + +#ifdef XSNS_07 + XSNS_07, +#endif + +#ifdef XSNS_08 + XSNS_08, +#endif + +#ifdef XSNS_09 + XSNS_09, +#endif + +#ifdef XSNS_10 + XSNS_10, +#endif + +#ifdef XSNS_11 + XSNS_11, +#endif + +#ifdef XSNS_12 + XSNS_12, +#endif + +#ifdef XSNS_13 + XSNS_13, +#endif + +#ifdef XSNS_14 + XSNS_14, +#endif + +#ifdef XSNS_15 + XSNS_15, +#endif + +#ifdef XSNS_16 + XSNS_16, +#endif + +#ifdef XSNS_17 + XSNS_17, +#endif + +#ifdef XSNS_18 + XSNS_18, +#endif + +#ifdef XSNS_19 + XSNS_19, +#endif + +#ifdef XSNS_20 + XSNS_20, +#endif + +#ifdef XSNS_21 + XSNS_21, +#endif + +#ifdef XSNS_22 + XSNS_22, +#endif + +#ifdef XSNS_23 + XSNS_23, +#endif + +#ifdef XSNS_24 + XSNS_24, +#endif + +#ifdef XSNS_25 + XSNS_25, +#endif + +#ifdef XSNS_26 + XSNS_26, +#endif + +#ifdef XSNS_27 + XSNS_27, +#endif + +#ifdef XSNS_28 + XSNS_28, +#endif + +#ifdef XSNS_29 + XSNS_29, +#endif + +#ifdef XSNS_30 + XSNS_30, +#endif + +#ifdef XSNS_31 + XSNS_31, +#endif + +#ifdef XSNS_32 + XSNS_32, +#endif + +#ifdef XSNS_33 + XSNS_33, +#endif + +#ifdef XSNS_34 + XSNS_34, +#endif + +#ifdef XSNS_35 + XSNS_35, +#endif + +#ifdef XSNS_36 + XSNS_36, +#endif + +#ifdef XSNS_37 + XSNS_37, +#endif + +#ifdef XSNS_38 + XSNS_38, +#endif + +#ifdef XSNS_39 + XSNS_39, +#endif + +#ifdef XSNS_40 + XSNS_40, +#endif + +#ifdef XSNS_41 + XSNS_41, +#endif + +#ifdef XSNS_42 + XSNS_42, +#endif + +#ifdef XSNS_43 + XSNS_43, +#endif + +#ifdef XSNS_44 + XSNS_44, +#endif + +#ifdef XSNS_45 + XSNS_45, +#endif + +#ifdef XSNS_46 + XSNS_46, +#endif + +#ifdef XSNS_47 + XSNS_47, +#endif + +#ifdef XSNS_48 + XSNS_48, +#endif + +#ifdef XSNS_49 + XSNS_49, +#endif + +#ifdef XSNS_50 + XSNS_50, +#endif + +// Optional user defined sensors in range 91 - 99 + +#ifdef XSNS_91 + XSNS_91, +#endif + +#ifdef XSNS_92 + XSNS_92, +#endif + +#ifdef XSNS_93 + XSNS_93, +#endif + +#ifdef XSNS_94 + XSNS_94, +#endif + +#ifdef XSNS_95 + XSNS_95, +#endif + +#ifdef XSNS_96 + XSNS_96, +#endif + +#ifdef XSNS_97 + XSNS_97, +#endif + +#ifdef XSNS_98 + XSNS_98, +#endif + +#ifdef XSNS_99 + XSNS_99 +#endif +}; + + /*********************************************************************************************\ * Function call to all xsns \*********************************************************************************************/ +boolean XsnsEnabled(byte sns_index) +{ + if (sns_index < sizeof(kXsnsList)) { +#ifdef XFUNC_PTR_IN_ROM + uint8_t index = pgm_read_byte(kXsnsList + sns_index); +#else + uint8_t index = kXsnsList[sns_index]; +#endif + return bitRead(Settings.sensors[index / 32], index % 32); + } + return 1; +} + +boolean XsnsPresent(byte sns_index) +{ + uint8_t index = 0; + for (byte i = 0; i < sizeof(kXsnsList); i++) { +#ifdef XFUNC_PTR_IN_ROM + index = pgm_read_byte(kXsnsList + i); +#else + index = kXsnsList[i]; +#endif + if (index == sns_index) { return true; } + } + return false; +} + +String XsnsGetSensors() +{ + char state[2] = { 0 }; + + String data = F("["); + for (byte i = 0; i < MAX_XSNS_DRIVERS; i++) { + if (i && (!(i % 16))) { data += F(","); } + if (!(i % 16)) { data += F("\""); } + state[0] = '-'; + if (XsnsPresent(i)) { state[0] = bitRead(Settings.sensors[i / 32], i % 32) ? '1' : '0'; } + data += String(state); + if (i && (!((i +1) % 16))) { data += F("\""); } + } + data += F("]"); + + return data; +} + boolean XsnsNextCall(byte Function) { xsns_index++; if (xsns_index == xsns_present) { xsns_index = 0; } -#ifdef USE_DEBUG_DRIVER while (!XsnsEnabled(xsns_index) && !xsns_index) { // Perform at least first sensor (counter) xsns_index++; if (xsns_index == xsns_present) { xsns_index = 0; } } -#endif AppDelay(); return xsns_func_ptr[xsns_index](Function); } @@ -292,9 +581,7 @@ boolean XsnsCall(byte Function) #endif // PROFILE_XSNS_EVERY_SECOND for (byte x = 0; x < xsns_present; x++) { -#ifdef USE_DEBUG_DRIVER if (XsnsEnabled(x)) { -#endif #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND uint32_t profile_start_millis = millis(); @@ -313,9 +600,7 @@ boolean XsnsCall(byte Function) #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND if (result) break; -#ifdef USE_DEBUG_DRIVER } -#endif } #ifdef PROFILE_XSNS_EVERY_SECOND diff --git a/sonoff/zzzz_debug.ino b/sonoff/zzzz_debug.ino deleted file mode 100644 index 9f07c29ce..000000000 --- a/sonoff/zzzz_debug.ino +++ /dev/null @@ -1,309 +0,0 @@ -/* - zzzz_debug.ino - debug support for Sonoff-Tasmota - - Copyright (C) 2018 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - 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_DEBUG_DRIVER -/*********************************************************************************************\ - * Virtual debugging support - Part 2 - * - * Needs to be the last alphabetical file due to DEFINE compile order -\*********************************************************************************************/ - -/*********************************************************************************************\ - * Xsns available list -\*********************************************************************************************/ - -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kXsnsList[] PROGMEM = { -#else -const uint8_t kXsnsList[] = { -#endif - -#ifdef XSNS_01 - XSNS_01, -#endif - -#ifdef XSNS_02 - XSNS_02, -#endif - -#ifdef XSNS_03 - XSNS_03, -#endif - -#ifdef XSNS_04 - XSNS_04, -#endif - -#ifdef XSNS_05 - XSNS_05, -#endif - -#ifdef XSNS_06 - XSNS_06, -#endif - -#ifdef XSNS_07 - XSNS_07, -#endif - -#ifdef XSNS_08 - XSNS_08, -#endif - -#ifdef XSNS_09 - XSNS_09, -#endif - -#ifdef XSNS_10 - XSNS_10, -#endif - -#ifdef XSNS_11 - XSNS_11, -#endif - -#ifdef XSNS_12 - XSNS_12, -#endif - -#ifdef XSNS_13 - XSNS_13, -#endif - -#ifdef XSNS_14 - XSNS_14, -#endif - -#ifdef XSNS_15 - XSNS_15, -#endif - -#ifdef XSNS_16 - XSNS_16, -#endif - -#ifdef XSNS_17 - XSNS_17, -#endif - -#ifdef XSNS_18 - XSNS_18, -#endif - -#ifdef XSNS_19 - XSNS_19, -#endif - -#ifdef XSNS_20 - XSNS_20, -#endif - -#ifdef XSNS_21 - XSNS_21, -#endif - -#ifdef XSNS_22 - XSNS_22, -#endif - -#ifdef XSNS_23 - XSNS_23, -#endif - -#ifdef XSNS_24 - XSNS_24, -#endif - -#ifdef XSNS_25 - XSNS_25, -#endif - -#ifdef XSNS_26 - XSNS_26, -#endif - -#ifdef XSNS_27 - XSNS_27, -#endif - -#ifdef XSNS_28 - XSNS_28, -#endif - -#ifdef XSNS_29 - XSNS_29, -#endif - -#ifdef XSNS_30 - XSNS_30, -#endif - -#ifdef XSNS_31 - XSNS_31, -#endif - -#ifdef XSNS_32 - XSNS_32, -#endif - -#ifdef XSNS_33 - XSNS_33, -#endif - -#ifdef XSNS_34 - XSNS_34, -#endif - -#ifdef XSNS_35 - XSNS_35, -#endif - -#ifdef XSNS_36 - XSNS_36, -#endif - -#ifdef XSNS_37 - XSNS_37, -#endif - -#ifdef XSNS_38 - XSNS_38, -#endif - -#ifdef XSNS_39 - XSNS_39, -#endif - -#ifdef XSNS_40 - XSNS_40, -#endif - -#ifdef XSNS_41 - XSNS_41, -#endif - -#ifdef XSNS_42 - XSNS_42, -#endif - -#ifdef XSNS_43 - XSNS_43, -#endif - -#ifdef XSNS_44 - XSNS_44, -#endif - -#ifdef XSNS_45 - XSNS_45, -#endif - -#ifdef XSNS_46 - XSNS_46, -#endif - -#ifdef XSNS_47 - XSNS_47, -#endif - -#ifdef XSNS_48 - XSNS_48, -#endif - -#ifdef XSNS_49 - XSNS_49, -#endif - -#ifdef XSNS_50 - XSNS_50, -#endif - -// Optional user defined sensors in range 91 - 99 - -#ifdef XSNS_91 - XSNS_91, -#endif - -#ifdef XSNS_92 - XSNS_92, -#endif - -#ifdef XSNS_93 - XSNS_93, -#endif - -#ifdef XSNS_94 - XSNS_94, -#endif - -#ifdef XSNS_95 - XSNS_95 -#endif -}; - -/*********************************************************************************************\ - * Xsns sensor control -\*********************************************************************************************/ - -boolean XsnsEnabled(byte sns_index) -{ - if (sns_index < sizeof(kXsnsList)) { -#ifdef XFUNC_PTR_IN_ROM - uint8_t index = pgm_read_byte(kXsnsList + sns_index); -#else - uint8_t index = kXsnsList[sns_index]; -#endif - return bitRead(Settings.sensors[index / 32], index % 32); - } - return 1; -} - -boolean XsnsPresent(byte sns_index) -{ - uint8_t index = 0; - for (byte i = 0; i < sizeof(kXsnsList); i++) { -#ifdef XFUNC_PTR_IN_ROM - index = pgm_read_byte(kXsnsList + i); -#else - index = kXsnsList[i]; -#endif - if (index == sns_index) { return true; } - } - return false; -} - -String XsnsGetSensors() -{ - char state[2] = { 0 }; - - String data = F("["); - for (byte i = 0; i < MAX_XSNS_DRIVERS; i++) { - if (i && (!(i % 16))) { data += F(","); } - if (!(i % 16)) { data += F("\""); } - state[0] = '-'; - if (XsnsPresent(i)) { state[0] = bitRead(Settings.sensors[i / 32], i % 32) ? '1' : '0'; } - data += String(state); - if (i && (!((i +1) % 16))) { data += F("\""); } - } - data += F("]"); - - return data; -} - -#endif // USE_DEBUG_DRIVER \ No newline at end of file From dd00af3fe0f74494190602829244ebbda522695a Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Mon, 12 Nov 2018 16:08:09 +0100 Subject: [PATCH 0482/2222] decode-config.py: add features Tasmota cmnds, grouping and filters - add restore value validation - add '--force-restore' - add output filter by Tasmota groups '--filter [...]' - add '--output' and '--output-format cmnd' (adds - most of all - Tasomta command output) - add Tasomta command output control: '--cmnd-indent', '--cmnd-groups', '--cmnd-nogroups', '--cmnd-sort', '--cmnd-unsort' - removed 'raw' data handling (obsolete) --- tools/decode-config.html | 281 +++-- tools/decode-config.md | 177 +++- tools/decode-config.py | 2083 +++++++++++++++++++++++--------------- 3 files changed, 1606 insertions(+), 935 deletions(-) diff --git a/tools/decode-config.html b/tools/decode-config.html index dd3d43d01..4fa7b4e04 100644 --- a/tools/decode-config.html +++ b/tools/decode-config.html @@ -1,5 +1,11 @@

decode-config.py

-

decode-config.py backup and restore Sonoff-Tasmota configuration.

+

decode-config.py is able to backup and restore Sonoff-Tasmota configuration.

+

In contrast to the Tasmota build-in "Backup/Restore Configuration" function,

+
    +
  • decode-config.py uses human readable and editable JSON-format for backup/restore,
  • +
  • decode-config.py can restore previous backuped and changed JSON-format files,
  • +
  • decode-config.py is able to create Tasomta commands based on given configuration
  • +

Comparing backup files created by decode-config.py and *.dmp files created by Tasmota "Backup/Restore Configuration":

@@ -32,29 +38,35 @@
-

decode-config.py handles Tasmota configurations for release version since 5.10.0 up to now.

+

decode-config.py is able to handle Tasmota configurations for release version starting from 5.10.0 up to now.

Content

    -
  • Prerequisite
  • -
  • File Types
      -
    • .dmp File Format
    • -
    • .json File Format
    • -
    • .bin File Format
        -
      • File extensions
      • +
      • Prerequisite
      • +
      • File Types
      • -
      • Usage
          -
        • Basics
        • -
        • Save backup file
        • -
        • Restore backup file
        • -
        • Configuration file
        • -
        • More program arguments
        • -
        • Examples

          Prerequisite

            -
          • Python)
            This program is written in Python) so you need to install a python environment (for details see Python Setup and Usage)
          • -
          • Sonoff-Tasmota Firmware with enabled Web-Server
            To backup or restore configurations from/to a Sonoff-Tasmota device you need a firmare with enabled web-server in admin mode (command WebServer 2). -
            Only self compiled firmware may do not have a web-server sod if you use your own compiled firmware be aware to enable the web-server, otherwise you can only use the --file parameter as source.
          • +
          • Python)
            This program is written in Python) so you need to install a python environment (for details see Python Setup and Usage)

            +
          • +
          • Sonoff-Tasmota Firmware with Web-Server enabled:

            +
              +
            • To backup or restore configurations from/to a Sonoff-Tasmota device you need a firmare with enabled web-server in admin mode (command WebServer 2).
            • +
            • If using your own compiled firmware be aware to enable the web-server (#define USE_WEBSERVER and #define WEB_SERVER 2).
            • +
            +

          File Types

          decode-config.py can handle the following backup file types:

          @@ -83,7 +100,7 @@

          The source can be either

          • a Tasmota device hostname or IP by passing it using the -d <host> arg
          • -
          • or a previously stored Tasmota *.dmpconfiguration file by passing the filename using-f ` arg
          • +
          • or a previously stored Tasmota *.dmp configuration file by passing the filename using -f <filename> arg

          Example:

          decode-config.py -d sonoff-4281
          @@ -112,6 +129,72 @@
           
          decode-config.py -d sonoff-4281 --restore-file Config_Sonoff_6.2.1.json
           

          with password set by WebPassword:

          decode-config.py -d sonoff-4281 -p <yourpassword> --restore-file Config_Sonoff_6.2.1.json
          +

          Output to screen

          +

          Output to screen is default enabled when calling the program with a source arg but without a backup or restore arg.

          +

          --output arg will force screen output even if you use backup or restore arg.

          +

          JSON output

          +

          The default output format is JSON. You can force JSON output with --output-format json arg.

          +

          Example:

          +
          decode-config.py -d sonoff-4281 -c my.conf -x Wifi --output-format json
          +
          +{
          +  ...
          +  "hostname": "%s-%04d", 
          +  "ip_address": [
          +    "0.0.0.0", 
          +    "192.168.12.1", 
          +    "255.255.255.0", 
          +    "192.168.12.1"
          +  ], 
          +  "ntp_server": [
          +    "ntp.localnet.home", 
          +    "ntp2.localnet.home", 
          +    "192.168.12.1"
          +  ], 
          +  "sta_active": 0, 
          +  "sta_config": 5, 
          +  "sta_pwd": [
          +    "myWlAnPaszxwo!z", 
          +    "myWlAnPaszxwo!z2"
          +  ], 
          +  "sta_ssid": [
          +    "wlan.1", 
          +    "my-wlan"
          +  ], 
          +  "web_password": "myPaszxwo!z", 
          +  "webserver": 2
          +  ...
          +}
          +

          Note: JSON output always contains all configuration data like the backup file except you are using --group arg.

          +

          Tasmota command output

          +

          decode-config.py is able to translate the configuration data to (most all) Tasmota commands. To output your configuration as Tasmota commands use --output-format cmnd or --output-format command.

          +

          Example:

          +
          decode-config.py -d sonoff-4281 -c my.conf -g Wifi --output-format cmnd
          +
          +# Wifi:
          +  AP 0
          +  Hostname %s-%04d
          +  IPAddress1 0.0.0.0
          +  IPAddress2 192.168.12.1
          +  IPAddress3 255.255.255.0
          +  IPAddress4 192.168.12.1
          +  NtpServer1 ntp.localnet.home
          +  NtpServer2 ntp2.localnet.home
          +  NtpServer3 192.168.12.1
          +  Password1 myWlAnPaszxwo!z
          +  Password2 myWlAnPaszxwo!z2
          +  SSId1 wlan.1
          +  SSId2 wlan.1
          +  WebPassword myPaszxwo!z
          +  WebServer 2
          +  WifiConfig 5
          +

          Note: A few very specific module commands like MPC230xx, KNX and some Display commands are not supported. These are still available by JSON output.

          +

          Filter data

          +

          The huge number of Tasomta configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories.

          +

          With decode-config.py the following categories are available: Display, Domoticz, Internal, KNX, Led, Logging, MCP230xx, MQTT, Main, Management, Pow, Sensor, Serial, SetOption, SonoffRF, System, Timers, Wifi

          +

          These are similary to the categories on https://github.com/arendst/Sonoff-Tasmota/wiki/Commands.

          +

          To filter outputs to a subset of groups use the -g or --group arg concatenating the grooup you want, e. g.

          +
          decode-config.py -d sonoff-4281 -c my.conf --output-format cmnd --group Main MQTT Management Wifi
           

          Configuration file

          Each argument that start with -- (eg. --file) can also be set in a config file (specified via -c). Config file syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at https://pypi.org/project/ConfigArgParse).

          If an argument is specified in more than one place, then commandline values override config file values which override defaults. This is usefull if you always use the same argument or a basic set of arguments.

          @@ -123,83 +206,111 @@

          To make a backup file from example above you can now pass the config file instead using the password on command line:

          decode-config.py -d sonoff-4281 -c my.conf --backup-file Config_@f_@v
           

          More program arguments

          -

          For better reading your porgram arguments each short written arg (minus sign -) has a corresponding readable long version (two minus signs --), eg. --device for -d or --file for -f (note: not even all -- arg has a corresponding - one).

          +

          For better reading each short written arg (minus sign -) has a corresponding long version (two minus signs --), eg. --device for -d or --file for -f (note: not even all -- arg has a corresponding - one).

          A short list of possible program args is displayed using -h or --help.

          For advanced help use -H or --full-help:

          -
          usage: decode-config.py [-f <filename>] [-d <host>] [-P <port>]
          +
          usage: decode-config.py [-f <filename>] [-d <host>] [-P <port>]
                                   [-u <username>] [-p <password>] [-i <filename>]
          -                        [-o <filename>] [-F json|bin|dmp] [-E] [-e]
          +                        [-o <filename>] [-t json|bin|dmp] [-E] [-e] [-F]
                                   [--json-indent <indent>] [--json-compact]
          -                        [--json-hide-pw] [--json-unhide-pw] [-h] [-H] [-v]
          -                        [-V] [-c <filename>] [--ignore-warnings]
          +                        [--json-hide-pw] [--json-show-pw]
          +                        [--cmnd-indent <indent>] [--cmnd-groups]
          +                        [--cmnd-nogroups] [--cmnd-sort] [--cmnd-unsort]
          +                        [-c <filename>] [-S] [-T json|cmnd|command]
          +                        [-g {Display,Domoticz,Internal,KNX,Led,Logging,MCP230xx,MQTT,Main,Management,Pow,Sensor,Serial,SetOption,SonoffRF,System,Timers,Wifi} [{Display,Domoticz,Internal,KNX,Led,Logging,MCP230xx,MQTT,Main,Management,Pow,Sensor,Serial,SetOption,SonoffRF,System,Timers,Wifi} ...]]
          +                        [--ignore-warnings] [-h] [-H] [-v] [-V]
           
          -Backup/Restore Sonoff-Tasmota configuration data. Args that start with '--'
          -(eg. -f) can also be set in a config file (specified via -c). Config file
          -syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at
          -https://goo.gl/R74nmi). If an arg is specified in more than one place, then
          -commandline values override config file values which override defaults.
          +Backup/Restore Sonoff-Tasmota configuration data. Args that start with '--'
          +(eg. -f) can also be set in a config file (specified via -c). Config file
          +syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at
          +https://goo.gl/R74nmi). If an arg is specified in more than one place, then
          +commandline values override config file values which override defaults.
          +
          +Source:
          +  Read/Write Tasmota configuration from/to
          +
          +  -f, --file, --tasmota-file <filename>
          +                        file to retrieve/write Tasmota configuration from/to
          +                        (default: None)'
          +  -d, --device, --host <host>
          +                        hostname or IP address to retrieve/send Tasmota
          +                        configuration from/to (default: None)
          +  -P, --port <port>     TCP/IP port number to use for the host connection
          +                        (default: 80)
          +  -u, --username <username>
          +                        host HTTP access username (default: admin)
          +  -p, --password <password>
          +                        host HTTP access password (default: None)
          +
          +Backup/Restore:
          +  Backup & restore specification
          +
          +  -i, --restore-file <filename>
          +                        file to restore configuration from (default: None).
          +                        Replacements: @v=firmware version, @f=device friendly
          +                        name, @h=device hostname
          +  -o, --backup-file <filename>
          +                        file to backup configuration to (default: None).
          +                        Replacements: @v=firmware version, @f=device friendly
          +                        name, @h=device hostname
          +  -t, --backup-type json|bin|dmp
          +                        backup filetype (default: 'json')
          +  -E, --extension       append filetype extension for -i and -o filename
          +                        (default)
          +  -e, --no-extension    do not append filetype extension, use -i and -o
          +                        filename as passed
          +  -F, --force-restore   force restore even configuration is identical
          +
          +JSON output:
          +  JSON format specification
          +
          +  --json-indent <indent>
          +                        pretty-printed JSON output using indent level
          +                        (default: 'None'). -1 disables indent.
          +  --json-compact        compact JSON output by eliminate whitespace
          +  --json-hide-pw        hide passwords
          +  --json-show-pw, --json-unhide-pw
          +                        unhide passwords (default)
          +
          +Tasmota command output:
          +  Tasmota command output format specification
          +
          +  --cmnd-indent <indent>
          +                        Tasmota command grouping indent level (default: '2').
          +                        0 disables indent
          +  --cmnd-groups         group Tasmota commands (default)
          +  --cmnd-nogroups       leave Tasmota commands ungrouped
          +  --cmnd-sort           sort Tasmota commands (default)
          +  --cmnd-unsort         leave Tasmota commands unsorted
          +
          +Common:
          +  Optional arguments
           
          -optional arguments:
             -c, --config <filename>
          -                        program config file - can be used to set default
          -                        command args (default: None)
          +                        program config file - can be used to set default
          +                        command args (default: None)
          +  -S, --output          display output regardsless of backup/restore usage
          +                        (default do not output on backup or restore usage)
          +  -T, --output-format json|cmnd|command
          +                        display output format (default: 'json')
          +  -g, --group {Display,Domoticz,Internal,KNX,Led,Logging,MCP230xx,MQTT,Main,Management,Pow,Sensor,Serial,SetOption,SonoffRF,System,Timers,Wifi}
          +                        limit data processing to command groups (default no
          +                        filter)
             --ignore-warnings     do not exit on warnings. Not recommended, used by your
                                   own responsibility!
           
          -Source:
          -  Read/Write Tasmota configuration from/to
          -
          -  -f, --file, --tasmota-file <filename>
          -                        file to retrieve/write Tasmota configuration from/to
          -                        (default: None)'
          -  -d, --device, --host <host>
          -                        hostname or IP address to retrieve/send Tasmota
          -                        configuration from/to (default: None)
          -  -P, --port <port>     TCP/IP port number to use for the host connection
          -                        (default: 80)
          -  -u, --username <username>
          -                        host HTTP access username (default: admin)
          -  -p, --password <password>
          -                        host HTTP access password (default: None)
          -
          -Backup/Restore:
          -  Backup/Restore configuration file specification
          -
          -  -i, --restore-file <filename>
          -                        file to restore configuration from (default: None).
          -                        Replacements: @v=firmware version, @f=device friendly
          -                        name, @h=device hostname
          -  -o, --backup-file <filename>
          -                        file to backup configuration to (default: None).
          -                        Replacements: @v=firmware version, @f=device friendly
          -                        name, @h=device hostname
          -  -F, --backup-type json|bin|dmp
          -                        backup filetype (default: 'json')
          -  -E, --extension       append filetype extension for -i and -o filename
          -                        (default)
          -  -e, --no-extension    do not append filetype extension, use -i and -o
          -                        filename as passed
          -
          -JSON:
          -  JSON backup format specification
          -
          -  --json-indent <indent>
          -                        pretty-printed JSON output using indent level
          -                        (default: 'None'). -1 disables indent.
          -  --json-compact        compact JSON output by eliminate whitespace
          -  --json-hide-pw        hide passwords (default)
          -  --json-unhide-pw      unhide passwords
          -
          -Info:
          -  additional information
          +Info:
          +  Extra information
           
             -h, --help            show usage help message and exit
          -  -H, --full-help       show full help message and exit
          +  -H, --full-help       show full help message and exit
             -v, --verbose         produce more output about what the program does
          -  -V, --version         show program's version number and exit
          +  -V, --version         show program's version number and exit
           
          -Either argument -d <host> or -f <filename> must be given.
          -

          Examples

          +Either argument -d <host> or -f <filename> must be given. +

          Program parameter notes

          +

          decode-config.py

          +

          Examples

          The most of the examples are for linux command line. Under Windows call the program using python decode-config.py ....

          Config file

          Note: The example contains .ini style sections [...]. Sections are always treated as comment and serves as clarity only. diff --git a/tools/decode-config.md b/tools/decode-config.md index d1cb05bd8..dab16a2c8 100644 --- a/tools/decode-config.md +++ b/tools/decode-config.md @@ -1,5 +1,10 @@ # decode-config.py -_decode-config.py_ backup and restore Sonoff-Tasmota configuration. +_decode-config.py_ is able to backup and restore Sonoff-Tasmota configuration. + +In contrast to the Tasmota build-in "Backup/Restore Configuration" function, +* _decode-config.py_ uses human readable and editable [JSON](http://www.json.org/)-format for backup/restore, +* _decode-config.py_ can restore previous backuped and changed [JSON](http://www.json.org/)-format files, +* _decode-config.py_ is able to create Tasomta commands based on given configuration Comparing backup files created by *decode-config.py* and *.dmp files created by Tasmota "Backup/Restore Configuration": @@ -10,19 +15,23 @@ Comparing backup files created by *decode-config.py* and *.dmp files created by | Simply editable | Yes | No | | Simply batch processing | Yes | No | -_decode-config.py_ handles Tasmota configurations for release version since 5.10.0 up to now. +_decode-config.py_ is able to handle Tasmota configurations for release version starting from 5.10.0 up to now. # Content * [Prerequisite](decode-config.md#prerequisite) * [File Types](decode-config.md#file-types) - * [.dmp File Format](decode-config.md#-dmp-file-format) - * [.json File Format](decode-config.md#-json-file-format) - * [.bin File Format](decode-config.md#-bin-file-format) + * [.dmp File Format](decode-config.md#-dmp-format) + * [.json File Format](decode-config.md#-json-format) + * [.bin File Format](decode-config.md#-bin-format) * [File extensions](decode-config.md#file-extensions) * [Usage](decode-config.md#usage) * [Basics](decode-config.md#basics) * [Save backup file](decode-config.md#save-backup-file) * [Restore backup file](decode-config.md#restore-backup-file) + * [Output to screen](decode-config.md#output-to-screen) + * [JSON output](decode-config.md#json-output) + * [Tasmota command output](decode-config.md#tasmota-command-output) + * [Filter data](decode-config.md#filter-data) * [Configuration file](decode-config.md#configuration-file) * [More program arguments](decode-config.md#more-program-arguments) * [Examples](decode-config.md#examples) @@ -33,9 +42,10 @@ _decode-config.py_ handles Tasmota configurations for release version since 5.10 ## Prerequisite * [Python](https://en.wikipedia.org/wiki/Python_(programming_language)) This program is written in [Python](https://en.wikipedia.org/wiki/Python_(programming_language)) so you need to install a python environment (for details see [Python Setup and Usage](https://docs.python.org/2.7/using/index.html)) -* [Sonoff-Tasmota](https://github.com/arendst/Sonoff-Tasmota) [Firmware](https://github.com/arendst/Sonoff-Tasmota/releases) with enabled Web-Server - To backup or restore configurations from/to a Sonoff-Tasmota device you need a firmare with enabled web-server in admin mode (command [WebServer 2](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands#wifi)). -
          Only self compiled firmware may do not have a web-server sod if you use your own compiled firmware be aware to enable the web-server, otherwise you can only use the `--file` parameter as source. + +* [Sonoff-Tasmota](https://github.com/arendst/Sonoff-Tasmota) [Firmware](https://github.com/arendst/Sonoff-Tasmota/releases) with Web-Server enabled: + * To backup or restore configurations from/to a Sonoff-Tasmota device you need a firmare with enabled web-server in admin mode (command [WebServer 2](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands#wifi)). + * If using your own compiled firmware be aware to enable the web-server (`#define USE_WEBSERVER` and `#define WEB_SERVER 2`). ## File Types _decode-config.py_ can handle the following backup file types: @@ -65,7 +75,7 @@ At least pass a source where you want to read the configuration data from using The source can be either * a Tasmota device hostname or IP by passing it using the `-d ` arg -* or a previously stored Tasmota *.dmp` configuration file by passing the filename using `-f ` arg +* or a previously stored Tasmota `*.dmp` configuration file by passing the filename using `-f ` arg Example: @@ -109,6 +119,89 @@ with password set by WebPassword: decode-config.py -d sonoff-4281 -p --restore-file Config_Sonoff_6.2.1.json +### Output to screen +Output to screen is default enabled when calling the program with a source arg but without a backup or restore arg. + +`--output` arg will force screen output even if you use backup or restore arg. + +#### JSON output +The default output format is JSON. You can force JSON output with `--output-format json` arg. + +Example: + + decode-config.py -d sonoff-4281 -c my.conf -x Wifi --output-format json + + { + ... + "hostname": "%s-%04d", + "ip_address": [ + "0.0.0.0", + "192.168.12.1", + "255.255.255.0", + "192.168.12.1" + ], + "ntp_server": [ + "ntp.localnet.home", + "ntp2.localnet.home", + "192.168.12.1" + ], + "sta_active": 0, + "sta_config": 5, + "sta_pwd": [ + "myWlAnPaszxwo!z", + "myWlAnPaszxwo!z2" + ], + "sta_ssid": [ + "wlan.1", + "my-wlan" + ], + "web_password": "myPaszxwo!z", + "webserver": 2 + ... + } + +Note: JSON output always contains all configuration data like the backup file except you are using `--group` arg. + + +#### Tasmota command output +_decode-config.py_ is able to translate the configuration data to (most all) Tasmota commands. To output your configuration as Tasmota commands use `--output-format cmnd` or `--output-format command`. + +Example: + + decode-config.py -d sonoff-4281 -c my.conf -g Wifi --output-format cmnd + + # Wifi: + AP 0 + Hostname %s-%04d + IPAddress1 0.0.0.0 + IPAddress2 192.168.12.1 + IPAddress3 255.255.255.0 + IPAddress4 192.168.12.1 + NtpServer1 ntp.localnet.home + NtpServer2 ntp2.localnet.home + NtpServer3 192.168.12.1 + Password1 myWlAnPaszxwo!z + Password2 myWlAnPaszxwo!z2 + SSId1 wlan.1 + SSId2 wlan.1 + WebPassword myPaszxwo!z + WebServer 2 + WifiConfig 5 + +Note: A few very specific module commands like MPC230xx, KNX and some Display commands are not supported. These are still available by JSON output. + +### Filter data +The huge number of Tasomta configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories. + +With _decode-config.py_ the following categories are available: `Display`, `Domoticz`, `Internal`, `KNX`, `Led`, `Logging`, `MCP230xx`, `MQTT`, `Main`, `Management`, `Pow`, `Sensor`, `Serial`, `SetOption`, `SonoffRF`, `System`, `Timers`, `Wifi` + +These are similary to the categories on [https://github.com/arendst/Sonoff-Tasmota/wiki/Commands](Tasmota Command Wiki). + +To filter outputs to a subset of groups use the `-g` or `--group` arg concatenating the grooup you want, e. g. + + decode-config.py -d sonoff-4281 -c my.conf --output-format cmnd --group Main MQTT Management Wifi + + ### Configuration file Each argument that start with `--` (eg. `--file`) can also be set in a config file (specified via -c). Config file syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at [https://pypi.org/project/ConfigArgParse](https://pypi.org/project/ConfigArgParse/)). @@ -129,7 +222,7 @@ To make a backup file from example above you can now pass the config file instea ### More program arguments -For better reading your porgram arguments each short written arg (minus sign `-`) has a corresponding readable long version (two minus signs `--`), eg. `--device` for `-d` or `--file` for `-f` (note: not even all `--` arg has a corresponding `-` one). +For better reading each short written arg (minus sign `-`) has a corresponding long version (two minus signs `--`), eg. `--device` for `-d` or `--file` for `-f` (note: not even all `--` arg has a corresponding `-` one). A short list of possible program args is displayed using `-h` or `--help`. @@ -137,10 +230,14 @@ For advanced help use `-H` or `--full-help`: usage: decode-config.py [-f ] [-d ] [-P ] [-u ] [-p ] [-i ] - [-o ] [-F json|bin|dmp] [-E] [-e] + [-o ] [-t json|bin|dmp] [-E] [-e] [-F] [--json-indent ] [--json-compact] - [--json-hide-pw] [--json-unhide-pw] [-h] [-H] [-v] - [-V] [-c ] [--ignore-warnings] + [--json-hide-pw] [--json-show-pw] + [--cmnd-indent ] [--cmnd-groups] + [--cmnd-nogroups] [--cmnd-sort] [--cmnd-unsort] + [-c ] [-S] [-T json|cmnd|command] + [-g {Display,Domoticz,Internal,KNX,Led,Logging,MCP230xx,MQTT,Main,Management,Pow,Sensor,Serial,SetOption,SonoffRF,System,Timers,Wifi} [{Display,Domoticz,Internal,KNX,Led,Logging,MCP230xx,MQTT,Main,Management,Pow,Sensor,Serial,SetOption,SonoffRF,System,Timers,Wifi} ...]] + [--ignore-warnings] [-h] [-H] [-v] [-V] Backup/Restore Sonoff-Tasmota configuration data. Args that start with '--' (eg. -f) can also be set in a config file (specified via -c). Config file @@ -148,13 +245,6 @@ For advanced help use `-H` or `--full-help`: https://goo.gl/R74nmi). If an arg is specified in more than one place, then commandline values override config file values which override defaults. - optional arguments: - -c, --config - program config file - can be used to set default - command args (default: None) - --ignore-warnings do not exit on warnings. Not recommended, used by your - own responsibility! - Source: Read/Write Tasmota configuration from/to @@ -172,7 +262,7 @@ For advanced help use `-H` or `--full-help`: host HTTP access password (default: None) Backup/Restore: - Backup/Restore configuration file specification + Backup & restore specification -i, --restore-file file to restore configuration from (default: None). @@ -182,25 +272,54 @@ For advanced help use `-H` or `--full-help`: file to backup configuration to (default: None). Replacements: @v=firmware version, @f=device friendly name, @h=device hostname - -F, --backup-type json|bin|dmp + -t, --backup-type json|bin|dmp backup filetype (default: 'json') -E, --extension append filetype extension for -i and -o filename (default) -e, --no-extension do not append filetype extension, use -i and -o filename as passed + -F, --force-restore force restore even configuration is identical - JSON: - JSON backup format specification + JSON output: + JSON format specification --json-indent pretty-printed JSON output using indent level (default: 'None'). -1 disables indent. --json-compact compact JSON output by eliminate whitespace - --json-hide-pw hide passwords (default) - --json-unhide-pw unhide passwords + --json-hide-pw hide passwords + --json-show-pw, --json-unhide-pw + unhide passwords (default) + + Tasmota command output: + Tasmota command output format specification + + --cmnd-indent + Tasmota command grouping indent level (default: '2'). + 0 disables indent + --cmnd-groups group Tasmota commands (default) + --cmnd-nogroups leave Tasmota commands ungrouped + --cmnd-sort sort Tasmota commands (default) + --cmnd-unsort leave Tasmota commands unsorted + + Common: + Optional arguments + + -c, --config + program config file - can be used to set default + command args (default: None) + -S, --output display output regardsless of backup/restore usage + (default do not output on backup or restore usage) + -T, --output-format json|cmnd|command + display output format (default: 'json') + -g, --group {Display,Domoticz,Internal,KNX,Led,Logging,MCP230xx,MQTT,Main,Management,Pow,Sensor,Serial,SetOption,SonoffRF,System,Timers,Wifi} + limit data processing to command groups (default no + filter) + --ignore-warnings do not exit on warnings. Not recommended, used by your + own responsibility! Info: - additional information + Extra information -h, --help show usage help message and exit -H, --full-help show full help message and exit @@ -209,6 +328,10 @@ For advanced help use `-H` or `--full-help`: Either argument -d or -f must be given. +### Program parameter notes + +_decode-config.py_ + ### Examples The most of the examples are for linux command line. Under Windows call the program using `python decode-config.py ...`. diff --git a/tools/decode-config.py b/tools/decode-config.py index 187eec5f3..d6632dbda 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,13 +1,13 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.0.0005' +VER = '2.1.0006' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data Copyright (C) 2018 Norbert Richter - This program is free software: you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modfy 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. @@ -37,10 +37,14 @@ Instructions: Usage: decode-config.py [-f ] [-d ] [-P ] [-u ] [-p ] [-i ] - [-o ] [-F json|bin|dmp] [-E] [-e] + [-o ] [-t json|bin|dmp] [-E] [-e] [-F] [--json-indent ] [--json-compact] - [--json-hide-pw] [--json-unhide-pw] [-h] [-H] [-v] - [-V] [-c ] [--ignore-warnings] + [--json-hide-pw] [--json-show-pw] + [--cmnd-indent ] [--cmnd-groups] + [--cmnd-nogroups] [--cmnd-sort] [--cmnd-unsort] + [-c ] [-S] [-T json|cmnd|command] + [-g {Display,Domoticz,Internal,KNX,Led,Logging,MCP230xx,MQTT,Main,Management,Pow,Sensor,Serial,SetOption,SonoffRF,System,Timers,Wifi} [{Display,Domoticz,Internal,KNX,Led,Logging,MCP230xx,MQTT,Main,Management,Pow,Sensor,Serial,SetOption,SonoffRF,System,Timers,Wifi} ...]] + [--ignore-warnings] [-h] [-H] [-v] [-V] Backup/Restore Sonoff-Tasmota configuration data. Args that start with '--' (eg. -f) can also be set in a config file (specified via -c). Config file @@ -48,13 +52,6 @@ Usage: decode-config.py [-f ] [-d ] [-P ] https://goo.gl/R74nmi). If an arg is specified in more than one place, then commandline values override config file values which override defaults. - optional arguments: - -c, --config - program config file - can be used to set default - command args (default: None) - --ignore-warnings do not exit on warnings. Not recommended, used by your - own responsibility! - Source: Read/Write Tasmota configuration from/to @@ -72,7 +69,7 @@ Usage: decode-config.py [-f ] [-d ] [-P ] host HTTP access password (default: None) Backup/Restore: - Backup/Restore configuration file specification + Backup & restore specification -i, --restore-file file to restore configuration from (default: None). @@ -82,25 +79,54 @@ Usage: decode-config.py [-f ] [-d ] [-P ] file to backup configuration to (default: None). Replacements: @v=firmware version, @f=device friendly name, @h=device hostname - -F, --backup-type json|bin|dmp + -t, --backup-type json|bin|dmp backup filetype (default: 'json') -E, --extension append filetype extension for -i and -o filename (default) -e, --no-extension do not append filetype extension, use -i and -o filename as passed + -F, --force-restore force restore even configuration is identical - JSON: - JSON backup format specification + JSON output: + JSON format specification --json-indent pretty-printed JSON output using indent level (default: 'None'). -1 disables indent. --json-compact compact JSON output by eliminate whitespace - --json-hide-pw hide passwords (default) - --json-unhide-pw unhide passwords + --json-hide-pw hide passwords + --json-show-pw, --json-unhide-pw + unhide passwords (default) + + Tasmota command output: + Tasmota command output format specification + + --cmnd-indent + Tasmota command grouping indent level (default: '2'). + 0 disables indent + --cmnd-groups group Tasmota commands (default) + --cmnd-nogroups leave Tasmota commands ungrouped + --cmnd-sort sort Tasmota commands (default) + --cmnd-unsort leave Tasmota commands unsorted + + Common: + Optional arguments + + -c, --config + program config file - can be used to set default + command args (default: None) + -S, --output display output regardsless of backup/restore usage + (default do not output on backup or restore usage) + -T, --output-format json|cmnd|command + display output format (default: 'json') + -g, --group {Display,Domoticz,Internal,KNX,Led,Logging,MCP230xx,MQTT,Main,Management,Pow,Sensor,Serial,SetOption,SonoffRF,System,Timers,Wifi} + limit data processing to command groups (default no + filter) + --ignore-warnings do not exit on warnings. Not recommended, used by your + own responsibility! Info: - additional information + Extra information -h, --help show usage help message and exit -H, --full-help show full help message and exit @@ -146,6 +172,9 @@ class ExitCode: MODULE_NOT_FOUND = 20 INTERNAL_ERROR = 21 +# ====================================================================== +# imports +# ====================================================================== import os.path import io import sys, platform @@ -155,6 +184,7 @@ def ModuleImportError(module): sys.exit(ExitCode.MODULE_NOT_FOUND) try: from datetime import datetime + import time import copy import struct import socket @@ -168,18 +198,18 @@ try: except ImportError, e: ModuleImportError(e) - +# ====================================================================== +# globals +# ====================================================================== PROG='{} v{} by Norbert Richter '.format(os.path.basename(sys.argv[0]),VER) CONFIG_FILE_XOR = 0x5A BINARYFILE_MAGIC = 0x63576223 STR_ENCODING = 'utf8' +HIDDEN_PASSWORD = '********' +INTERNAL = 'Internal' + DEFAULTS = { - 'DEFAULT': - { - 'configfile': None, - 'ignorewarning':False, - }, 'source': { 'device': None, @@ -194,483 +224,542 @@ DEFAULTS = { 'backupfile': None, 'backupfileformat': 'json', 'extension': True, + 'forcerestore': False, }, 'jsonformat': { 'jsonindent': None, 'jsoncompact': False, 'jsonsort': True, - 'jsonrawvalues':False, - 'jsonrawkeys': False, 'jsonhidepw': False, }, + 'cmndformat': + { + 'cmndindent': 2, + 'cmndgroup': True, + 'cmndsort': True, + }, + 'common': + { + 'output': False, + 'outputformat': 'json', + 'configfile': None, + 'ignorewarning':False, + 'filter': None, + }, } args = {} exitcode = 0 +# ====================================================================== +# Settings mapping +# ====================================================================== """ Settings dictionary describes the config file fields definition: - Each setting name has a tuple containing the following items: + = { : } + + : "string" + a python valid dictionary key (string) - (format, baseaddr, datadef, ) + : ( , , [,] ) + a tuple containing the following items: - where + : | + data type & format definition + : + defines the use of data at + format is defined in 'struct module format string' + see + https://docs.python.org/2.7/library/struct.html#format-strings + : + A dictionary describes a (sub)setting dictonary + and can recursively define another - format - Define the data interpretation. - It is either a string or a tuple containing a string and a - sub-Settings dictionary. - 'xxx': - A string is used to interpret the data at - The string defines the format interpretion as described - in 'struct module format string', see - https://docs.python.org/2.7/library/struct.html#format-strings - In addition to this format string there is as special - meaning of a dot '.' - this means a bit with an optional - prefix length. If no prefix is given, 1 is assumed. - {}: - A dictionary describes itself a 'Settings' dictonary (recursive) + : | (, , ) + address definition + : + The address (starting from 0) within binary config data. + : + number of bits used (positive integer) + : + bit shift : + >= 0: shift the result right + < 0: shift the result left - baseaddr - The address (starting from 0) within config data. - For bit fields must be a tuple. - n: - Defines a simple address within config data. - must be a positive integer. - (n, b, s): - A tuple defines a bit field: - - is the address within config data (integer) - - how many bits are used (positive integer) - - bit shift (integer) - positive shift the result right bits - negative shift the result left bits - - datadef - Data definition, is either a array definition or a - tuple containing an array definition and min/max values - Format: arraydef|(arraydef, min, max) - arraydef: + : | (, [,cmd]) + data definition + : None | | [] | [ ,...] None: - None must be given if the field contains a - simple value desrcibed by the prefix - n: - [n]: + Single value, not an array + : + [] Defines a one-dimensional array of size - [n, m <,o...>] - Defines a multi-dimensional array - min: - defines a minimum valid value or None if all values - for this format is allowed. - max: - defines a maximum valid value or None if all values - for this format is allowed. + [ ,...] + Defines a one- or multi-dimensional array + : + value validation function + : (, ) + Tasmota command definition + : + command group string + : + convert data into Tasmota command function - converter (optional) - Conversion methode(s): 'xxx'|func or ('xxx'|func, 'xxx'|func) - Read conversion is used if args.jsonrawvalues is False - Write conversion is used if jsonrawvalues from restore json - file is False or args.jsonrawvalues is False. - Converter is either a single methode 'xxx'|func or a tuple - Single methode will be used for reading conversion only: - 'xxx': - string will used for reading conversion and will be - evaluate as is, this can also contain python code. - Use '$' for current value. - func: - name of a formating function that will be used for - reading conversion - None: - will read as definied in - (read, write): - a tuple with 2 objects. Each can be of the same type - as the single method above ('xxx'|func) or None. - read: - method will be used for read conversion - (unpack data from dmp object) - write: - method will be used for write conversion - (pack data to dmp object) - If write method is None indicates value is - readable only and will not be write + : | (, ) + read/write converter + : None | + Will be used in Bin2Mapping to convert values read + from the binary data object into mapping dictionary + None + None indicates not read conversion + + to convert value from binary object to JSON. + : None | False | + Will be used in Mapping2Bin to convert values read + from mapping dictionary before write to binary + data object + None + None indicates not write conversion + False + False indicates the value is readonly and will + not be written into the binary object. + + to convert value from JSON back to binary object + Common definitions + + : | | None + function to be called or string to evaluate: + : + A function name will be called with one or two parameter: + The value to be processed + (optional) the current array index (1,n) + + A string will be evaluate as is. The following + placeholder can be used to replace it by runtime values: + '$': + will be replaced by the mapping name value + '#': + will be replace by array index (if any) + '@': + can be used as reference to other mapping values + see definition below for examples + + : 'string' | "string" + characters enclosed in ' or " + + : integer + numbers in the range -2147483648 through 2147483647 + : unsigned integer + numbers in the range 0 through 4294967295 + """ +# ---------------------------------------------------------------------- +# Settings helper +# ---------------------------------------------------------------------- def passwordread(value): - return "********" if args.jsonhidepw else value + return HIDDEN_PASSWORD if args.jsonhidepw else value def passwordwrite(value): - return None if value=="********" else value + return None if value == HIDDEN_PASSWORD else value +def bitsRead(x, n=0, c=1): + """ + Reads bit(s) of a number + + @param x: + the number from which to read + + @param n: + which bit position to read + + @param c: + how many bits to read (1 if omitted) + + @return: + the bit value(s) + """ + if isinstance(x,str): + x = int(x, 0) + if isinstance(x,str): + n = int(n, 0) + if n >= 0: + x >>= n + else: + x <<= abs(n) + if c>0: + x &= (1<, , [,] + 'cfg_holder': ('0 and bitsRead($,0,11)>(12*60) else "",time=time.strftime("%H:%M",time.gmtime((bitsRead($,0,11) if bitsRead($,29,2)==0 else bitsRead($,0,11) if bitsRead($,0,11)<=(12*60) else bitsRead($,0,11)-(12*60))*60)),window=bitsRead($,11,4),repeat=bitsRead($,15),days="{:07b}".format(bitsRead($,16,7))[::-1],device=bitsRead($,23,4)+1,power=bitsRead($,27,2) )')), ('"0x{:08x}".format($)', False) ), + 'time': (' version number from read binary data to search for - - @return: - template sizes as list [] - """ - sizes = [] - for cfg in Settings: - sizes.append(cfg[1]) - # return unique sizes only (remove duplicates) - return list(set(sizes)) - - -def GetTemplateSetting(decode_cfg): - """ - Search for version, size and settings to be used depending on given binary config data - - @param decode_cfg: - binary config data (decrypted) - - @return: - version, size, settings to use; None if version is invalid - """ - version = 0x0 - size = setting = None - - version = GetField(decode_cfg, 'version', Setting_6_2_1['version'], raw=True) - # search setting definition top-down - for cfg in sorted(Settings, key=lambda s: s[0], reverse=True): - if version >= cfg[0]: - version = cfg[0] - size = cfg[1] - setting = cfg[2].copy() - break - - return version, size, setting - - +# ====================================================================== +# Common helper +# ====================================================================== class LogType: INFO = 'INFO' WARNING = 'WARNING' @@ -756,8 +803,8 @@ def message(msg, typ=None, status=None, line=None): """ print >> sys.stderr, '{styp}{sdelimiter}{sstatus}{slineno}{scolon}{smgs}'.format(\ styp=typ if typ is not None else '', - sdelimiter=' ' if status is not None and status>0 and typ is not None else '', - sstatus=status if status is not None and status>0 else '', + sdelimiter=' ' if status is not None and status > 0 and typ is not None else '', + sstatus=status if status is not None and status > 0 else '', scolon=': ' if typ is not None or line is not None else '', smgs=msg, slineno=' (@{:04d})'.format(line) if line is not None else '') @@ -816,14 +863,14 @@ class HTTPHeader: def response(self): header = str(self.contents).split('\n') - if len(header)>0: + if len(header) > 0: return header[0].rstrip() return '' def contenttype(self): for item in str(self.contents).split('\n'): ditem = item.split(":") - if ditem[0].strip().lower()=='content-type' and len(ditem)>1: + if ditem[0].strip().lower() == 'content-type' and len(ditem) > 1: return ditem[1].strip() return '' @@ -852,7 +899,7 @@ class CustomHelpFormatter(configargparse.HelpFormatter): return res options = orgstr.split(', ') - if len(options) <=1: + if len(options) <= 1: action._formatted_action_invocation = orgstr return orgstr @@ -860,18 +907,83 @@ class CustomHelpFormatter(configargparse.HelpFormatter): for option in options: meta = "" arg = option.split(' ') - if len(arg)>1: + if len(arg) > 1: meta = arg[1] return_list.append(arg[0]) - if len(meta) >0 and len(return_list) >0: + if len(meta) > 0 and len(return_list) > 0: return_list[len(return_list)-1] += " "+meta action._formatted_action_invocation = ', '.join(return_list) return action._formatted_action_invocation -# ---------------------------------------------------------------------- +# ====================================================================== # Tasmota config data handling -# ---------------------------------------------------------------------- +# ====================================================================== +def GetTemplateSizes(): + """ + Get all possible template sizes as list + + @param version: + version number from read binary data to search for + + @return: + template sizes as list [] + """ + sizes = [] + for cfg in Settings: + sizes.append(cfg[1]) + # return unique sizes only (remove duplicates) + return list(set(sizes)) + + +def GetTemplateSetting(decode_cfg): + """ + Search for version, size and settings to be used depending on given binary config data + + @param decode_cfg: + binary config data (decrypted) + + @return: + version, size, settings to use; None if version is invalid + """ + version = 0x0 + size = setting = None + version = GetField(decode_cfg, 'version', Setting_6_2_1['version'], raw=True) + # search setting definition top-down + for cfg in sorted(Settings, key=lambda s: s[0], reverse=True): + if version >= cfg[0]: + size = cfg[1] + setting = cfg[2] + break + + return version, size, setting + + +def GetGroupList(setting): + """ + Get all avilable group definition from setting + + @return: + configargparse.parse_args() result + """ + groups = set() + + for name in setting: + dev = setting[name] + format, group = GetFieldDef(dev, fields="format, group") + if group is not None and len(group) > 0: + groups.add(group) + if isinstance(format, dict): + subgroups = GetGroupList(format) + if subgroups is not None and len(subgroups) > 0: + for group in subgroups: + groups.add(group) + + groups=list(groups) + groups.sort() + return groups + + class FileType: FILE_NOT_FOUND = None DMP = 'dmp' @@ -882,7 +994,6 @@ class FileType: INVALID_JSON = 'invalid json' INVALID_BIN = 'invalid bin' - def GetFileType(filename): """ Get the FileType class member of a given filename @@ -960,39 +1071,22 @@ def GetVersionStr(version): minor = ((version>>16) & 0xff) release = ((version>> 8) & 0xff) subrelease = (version & 0xff) - if major>=6: - if subrelease>0: + if major >= 6: + if subrelease > 0: subreleasestr = str(subrelease) else: subreleasestr = '' else: - if subrelease>0: + if subrelease > 0: subreleasestr = str(chr(subrelease+ord('a')-1)) else: subreleasestr = '' - return "{:d}.{:d}.{:d}{}{}".format( major, minor, release, '.' if (major>=6 and subreleasestr!='') else '', subreleasestr) + return "{:d}.{:d}.{:d}{}{}".format( major, minor, release, '.' if (major >= 6 and subreleasestr != '') else '', subreleasestr) -def MakeValidFilename(filename): +def MakeFilename(filename, filetype, configmapping): """ - Make a valid filename - - @param filename: - filename src - - @return: - valid filename removed invalid chars and replace space with _ - """ - try: - filename = filename.decode('unicode-escape').translate(dict((ord(char), None) for char in '\/*?:"<>|')) - except: - pass - return str(filename.replace(' ','_')) - - -def MakeFilename(filename, filetype, decode_cfg): - """ - Replace variable within a filename + Replace variables within a filename @param filename: original filename possible containing replacements: @@ -1004,40 +1098,49 @@ def MakeFilename(filename, filetype, decode_cfg): hostname @param filetype: FileType.x object - creates extension if not None - @param decode_cfg: + @param configmapping: binary config data (decrypted) @return: New filename with replacements """ v = f1 = f2 = f3 = f4 = '' - if 'version' in decode_cfg: - v = GetVersionStr( int(str(decode_cfg['version']), 0) ) + if 'version' in configmapping: + v = GetVersionStr( int(str(configmapping['version']), 0) ) filename = filename.replace('@v', v) - if 'friendlyname' in decode_cfg: - filename = filename.replace('@f', decode_cfg['friendlyname'][0] ) - if 'hostname' in decode_cfg: - filename = filename.replace('@h', decode_cfg['hostname'] ) + if 'friendlyname' in configmapping: + filename = filename.replace('@f', configmapping['friendlyname'][0] ) + if 'hostname' in configmapping: + filename = filename.replace('@h', configmapping['hostname'] ) dirname = basename = ext = '' + name = filename + + # split file parts + dirname = os.path.normpath(os.path.dirname(filename)) + basename = os.path.basename(filename) + name, ext = os.path.splitext(basename) + + # make a valid filename try: - dirname = os.path.normpath(os.path.dirname(filename)) - basename = os.path.basename(filename) - name, ext = os.path.splitext(basename) + name = name.decode('unicode-escape').translate(dict((ord(char), None) for char in '\/*?:"<>|')) except: pass - name = MakeValidFilename(name) + name = str(name.replace(' ','_')) + # append extension based on filetype if not given if len(ext) and ext[0]=='.': ext = ext[1:] if filetype is not None and args.extension and (len(ext)<2 or all(c.isdigit() for c in ext)): ext = filetype.lower() + # join filename + extension if len(ext): name_ext = name+'.'+ext else: name_ext = name + # join path and filename try: filename = os.path.join(dirname, name_ext) except: @@ -1156,6 +1259,8 @@ def PushTasmotaConfig(encode_cfg, host, port, username=DEFAULTS['source']['usern encrypted binary data or filename containing Tasmota encrypted binary config @param host: hostname or IP of Tasmota device + @param port: + http port of Tasmota device @param username: optional username for Tasmota web login @param password @@ -1165,8 +1270,6 @@ def PushTasmotaConfig(encode_cfg, host, port, username=DEFAULTS['source']['usern errorcode, errorstring errorcode=0 if success, otherwise http response or exception code """ - # ~ return 0, 'OK' - if isinstance(encode_cfg, bytearray): encode_cfg = str(encode_cfg) @@ -1192,10 +1295,10 @@ def PushTasmotaConfig(encode_cfg, host, port, username=DEFAULTS['source']['usern c.close() return e[0], e[1] - if responsecode>=400: + if responsecode >= 400: c.close() return responsecode, header.response() - elif header.contenttype()!='text/html': + elif header.contenttype() != 'text/html': c.close() return ExitCode.UPLOAD_CONFIG_ERROR, "Device did not response properly, may be Tasmota webserver admin mode is disabled (WebServer 2)" @@ -1227,9 +1330,9 @@ def PushTasmotaConfig(encode_cfg, host, port, username=DEFAULTS['source']['usern return e[0], e[1] c.close() - if responsecode>=400: + if responsecode >= 400: return responsecode, header.response() - elif header.contenttype()!='text/html': + elif header.contenttype() != 'text/html': return ExitCode.UPLOAD_CONFIG_ERROR, "Device did not response properly, may be Tasmota webserver admin mode is disabled (WebServer 2)" return 0, 'OK' @@ -1244,7 +1347,6 @@ def DecryptEncrypt(obj): @return: decrypted configuration (if obj contains encrypted data) - encrypted configuration (if obj contains decrypted data) """ if isinstance(obj, bytearray): obj = str(obj) @@ -1276,58 +1378,124 @@ def GetSettingsCrc(dobj): return crc & 0xffff -def GetFieldDef(fielddef): +def GetFieldDef(fielddef, fields="format, addrdef, baseaddr, bits, bitshift, datadef, arraydef, validate, cmd, group, tasmotacmnd, converter, readconverter, writeconverter"): """ - Get the field def items + Get field definition items @param fielddef: field format - see "Settings dictionary" above + @param fields: + comma separated string list of values to be returned + possible values see fields default @return: - , , , , , - undefined items can be None + set of values defined in """ - format = baseaddr = datadef = convert = None + format = addrdef = baseaddr = datadef = arraydef = validate = cmd = group = tasmotacmnd = converter = readconverter = writeconverter = None bits = bitshift = 0 - if len(fielddef)==3: - # def without convert tuple - format, baseaddr, datadef = fielddef - elif len(fielddef)==4: - # def with convert tuple - format, baseaddr, datadef, convert = fielddef + # calling with nothing is wrong + if fielddef is None: + print >> sys.stderr, ' is None' + raise SyntaxError(' error') + + # get top level items + if len(fielddef) == 3: + # converter not present + format, addrdef, datadef = fielddef + elif len(fielddef) == 4: + # converter present + format, addrdef, datadef, converter = fielddef + else: + print >> sys.stderr, 'wrong {} length ({}) in setting'.format(fielddef, len(fielddef)) + raise SyntaxError(' error') + + # ignore calls with 'root' setting + if isinstance(format, dict) and baseaddr is None and datadef is None: + return eval(fields) + + if not isinstance(format, (unicode,str,dict)): + print >> sys.stderr, 'wrong {} type {} in {}'.format(format, type(format), fielddef) + raise SyntaxError(' error') + + # extract addrdef items + baseaddr = addrdef if isinstance(baseaddr, (list,tuple)): - baseaddr, bits, bitshift = baseaddr + if len(baseaddr) == 3: + # baseaddr bit definition + baseaddr, bits, bitshift = baseaddr + if not isinstance(bits, int): + print >> sys.stderr, ' must be a integer in {}'.format(bits, fielddef) + raise SyntaxError(' error') + if not isinstance(bitshift, int): + print >> sys.stderr, ' must be a integer in {}'.format(bitshift, fielddef) + raise SyntaxError(' error') + else: + print >> sys.stderr, 'wrong {} length ({}) in {}'.format(addrdef, len(addrdef), fielddef) + raise SyntaxError(' error') + if not isinstance(baseaddr, int): + print >> sys.stderr, ' must be a integer in {}'.format(baseaddr, fielddef) + raise SyntaxError(' error') - if isinstance(datadef, int): - # convert single int into list with one item - datadef = [datadef] - return format, baseaddr, bits, bitshift, datadef, convert + # extract datadef items + arraydef = datadef + if isinstance(datadef, (tuple)): + if len(datadef) == 2: + # datadef has a validator + arraydef, validate = datadef + elif len(datadef) == 3: + # datadef has a validator and cmd set + arraydef, validate, cmd = datadef + # cmd must be a tuple with 2 objects + if isinstance(cmd, (tuple)) and len(cmd) == 2: + group, tasmotacmnd = cmd + if group is not None and not isinstance(group, (str, unicode)): + print >> sys.stderr, 'wrong {} in {}'.format(group, fielddef) + raise SyntaxError(' error') + if tasmotacmnd is not None and not isinstance(tasmotacmnd, (str, unicode)): + print >> sys.stderr, 'wrong {} in {}'.format(tasmotacmnd, fielddef) + raise SyntaxError(' error') + else: + print >> sys.stderr, 'wrong {} length ({}) in {}'.format(cmd, len(cmd), fielddef) + raise SyntaxError(' error') + else: + print >> sys.stderr, 'wrong {} length ({}) in {}'.format(datadef, len(datadef), fielddef) + raise SyntaxError(' error') + + if validate is not None and (not isinstance(validate, (unicode,str)) and not callable(validate)): + print >> sys.stderr, 'wrong {} type {} in {}'.format(validate, type(validate), fielddef) + raise SyntaxError(' error') + + # convert single int into one-dimensional list + if isinstance(arraydef, int): + arraydef = [arraydef] + + if arraydef is not None and not isinstance(arraydef, (list)): + print >> sys.stderr, 'wrong {} type {} in {}'.format(arraydef, type(arraydef), fielddef) + raise SyntaxError(' error') + + # get read/write converter items + readconverter = converter + if isinstance(converter, (tuple)): + if len(converter) == 2: + # converter has read/write converter + readconverter, writeconverter = converter + if readconverter is not None and not isinstance(readconverter, (str,unicode)) and not callable(readconverter): + print >> sys.stderr, 'wrong {} type {} in {}'.format(readconverter, type(readconverter), fielddef) + raise SyntaxError(' error') + if writeconverter is not None and (not isinstance(writeconverter, (bool,str,unicode)) and not callable(writeconverter)): + print >> sys.stderr, 'wrong {} type {} in {}'.format(writeconverter, type(writeconverter), fielddef) + raise SyntaxError(' error') + else: + print >> sys.stderr, 'wrong {} length ({}) in {}'.format(converter, len(converter), fielddef) + raise SyntaxError(' error') + + + return eval(fields) -def MakeFieldBaseAddr(baseaddr, bits, bitshift): - """ - Return a based on given arguments - - @param baseaddr: - baseaddr from Settings definition - @param bits: - 0 or bits - @param bitshift: - 0 or bitshift - - @return: - (,,) if bits != 0 - baseaddr if bits == 0 - - """ - if bits!=0: - return (baseaddr, bits, bitshift) - return baseaddr - - -def ConvertFieldValue(value, fielddef, read=True, raw=False): +def ReadWriteConverter(value, fielddef, read=True, raw=False): """ Convert field value based on field desc @@ -1343,33 +1511,107 @@ def ConvertFieldValue(value, fielddef, read=True, raw=False): @return: (un)converted value """ - format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) + converter, readconverter, writeconverter = GetFieldDef(fielddef, fields='converter, readconverter, writeconverter') # call password functions even if raw value should be processed - if callable(convert) and (convert==passwordread or convert==passwordwrite): + if read and callable(readconverter) and readconverter == passwordread: raw = False - if isinstance(convert, (list,tuple)) and len(convert)>0 and (convert[0]==passwordread or convert[0]==passwordwrite): - raw = False - if isinstance(convert, (list,tuple)) and len(convert)>1 and (convert[1]==passwordread or convert[1]==passwordwrite): + if not read and callable(writeconverter) and writeconverter == passwordwrite: raw = False - if not raw and convert is not None: - if isinstance(convert, (list,tuple)): # extract read conversion if tuple is given - if read: - convert = convert[0] - else: - convert = convert[1] + if not raw and converter is not None: + conv = readconverter if read else writeconverter try: - if isinstance(convert, str): # evaluate strings - return eval(convert.replace('$','value')) - elif callable(convert): # use as format function - return convert(value) - except: - pass + if isinstance(conv, str): # evaluate strings + return eval(conv.replace('$','value')) + elif callable(conv): # use as format function + return conv(value) + except Exception, e: + exit(e[0], e[1], typ=LogType.WARNING, line=inspect.getlineno(inspect.currentframe())) return value +def CmndConverter(valuemapping, value, idx, fielddef): + """ + Convert field value into Tasmota command if available + + @param valuemapping: + data mapping + @param value: + original value + @param fielddef + field definition - see "Settings dictionary" above + + @return: + converted value or None if unable to convert + """ + converter, readconverter, writeconverter, group, tasmotacmnd = GetFieldDef(fielddef, fields='converter, readconverter, writeconverter, group, tasmotacmnd') + + result = None + + if (callable(readconverter) and readconverter == passwordread) or (callable(writeconverter) and writeconverter == passwordwrite): + if value == HIDDEN_PASSWORD: + return None + else: + result = value + + if tasmotacmnd is not None and len(tasmotacmnd) > 0: + if idx is not None: + idx += 1 + if isinstance(tasmotacmnd, str): # evaluate strings + if idx is not None: + evalstr = tasmotacmnd.replace('$','value').replace('#','idx').replace('@','valuemapping') + else: + evalstr = tasmotacmnd.replace('$','value').replace('@','valuemapping') + # ~ try: + result = eval(evalstr) + # ~ except: + # ~ print evalstr + # ~ print value + + elif callable(tasmotacmnd): # use as format function + if idx is not None: + result = tasmotacmnd(value, idx) + else: + result = tasmotacmnd(value) + + return result + + +def ValidateValue(value, fielddef): + """ + Validate a value if validator is defined in fielddef + + @param value: + original value + @param fielddef + field definition - see "Settings dictionary" above + + @return: + True if value is valid, False if invalid + """ + validate = GetFieldDef(fielddef, fields='validate') + + if value == 0: + # can not complete all validate condition + # some Tasmota values are not allowed to be 0 on input + # even though these values are set to 0 on Tasmota initial. + # so we can't validate 0 values + return True; + + valid = True + try: + if isinstance(validate, str): # evaluate strings + valid = eval(validate.replace('$','value')) + elif callable(validate): # use as format function + valid = validate(value) + except: + valid = False + + return valid + + def GetFieldMinMax(fielddef): """ Get minimum, maximum of field based on field format definition @@ -1395,7 +1637,7 @@ def GetFieldMinMax(fielddef): 'f': (sys.float_info.min, sys.float_info.max), 'd': (sys.float_info.min, sys.float_info.max), } - format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) + format = GetFieldDef(fielddef, fields='format') _min = 0 _max = 0 @@ -1421,48 +1663,46 @@ def GetFieldLength(fielddef): """ length=0 - format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) + format, addrdef, arraydef = GetFieldDef(fielddef, fields='format, addrdef, arraydef') - if datadef is not None: - # datadef contains a list + # contains a integer list + if isinstance(arraydef, list) and len(arraydef) > 0: + # arraydef contains a list # calc size recursive by sum of all elements - if isinstance(datadef, list): - for i in range(0, datadef[0]): + for i in range(0, arraydef[0]): + subfielddef = GetSubfieldDef(fielddef) + if len(arraydef) > 1: + length += GetFieldLength( (format, addrdef, subfielddef) ) + # single array + else: + length += GetFieldLength( (format, addrdef, None) ) - # multidimensional array - if isinstance(datadef, list) and len(datadef)>1: - length += GetFieldLength( (fielddef[0], fielddef[1], fielddef[2][1:]) ) - - # single array - else: - length += GetFieldLength( (fielddef[0], fielddef[1], None) ) - - else: - if isinstance(format, dict): + elif isinstance(format, dict): # -> iterate through format addr = None setting = format for name in setting: - _dummy1, baseaddr, bits, bitshift, _dummy2, _dummy3 = GetFieldDef(setting[name]) + baseaddr, bits, bitshift = GetFieldDef(setting[name], fields='baseaddr, bits, bitshift') _len = GetFieldLength(setting[name]) if addr != baseaddr: addr = baseaddr length += _len - else: - if format[-1:] in ['b','B','c','?']: - length=1 - elif format[-1:] in ['h','H']: - length=2 - elif format[-1:] in ['i','I','l','L','f']: - length=4 - elif format[-1:] in ['q','Q','d']: - length=8 - elif format[-1:] in ['s','p']: - # s and p may have a prefix as length - match = re.search("\s*(\d+)", format) - if match: - length=int(match.group(0)) + # a simple value + elif isinstance(format, str): + if format[-1:] in ['b','B','c','?']: + length=1 + elif format[-1:] in ['h','H']: + length=2 + elif format[-1:] in ['i','I','l','L','f']: + length=4 + elif format[-1:] in ['q','Q','d']: + length=8 + elif format[-1:] in ['s','p']: + # s and p may have a prefix as length + match = re.search("\s*(\d+)", format) + if match: + length=int(match.group(0)) return length @@ -1477,23 +1717,52 @@ def GetSubfieldDef(fielddef): @return: subfield definition """ - subfielddef = None - format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) - if isinstance(datadef, list) and len(datadef)>1: - if len(fielddef)<4: - subfielddef = (format, MakeFieldBaseAddr(baseaddr, bits, bitshift), datadef[1:]) - else: - subfielddef = (format, MakeFieldBaseAddr(baseaddr, bits, bitshift), datadef[1:], convert) - # single array + format, addrdef, datadef, arraydef, validate, cmd, converter = GetFieldDef(fielddef, fields='format, addrdef, datadef, arraydef, validate, cmd, converter') + + # create new arraydef + if len(arraydef) > 1: + arraydef = arraydef[1:] else: - if len(fielddef)<4: - subfielddef = (format, MakeFieldBaseAddr(baseaddr, bits, bitshift), None) + arraydef = None + + # create new datadef + if isinstance(datadef, tuple): + if cmd is not None: + datadef = (arraydef, validate, cmd) else: - subfielddef = (format, MakeFieldBaseAddr(baseaddr, bits, bitshift), None, convert) + datadef = (arraydef, validate) + else: + datadef = arraydef + + # set new field def + subfielddef = None + if converter is not None: + subfielddef = (format, addrdef, datadef, converter) + else: + subfielddef = (format, addrdef, datadef) + return subfielddef +def IsFilterGroup(group): + """ + Check if group is valid on filter + + @param grooup: + group name to check + + @return: + True if group is in filter, otherwise False + """ + if args.filter is not None: + if group is None: + return False + if group != INTERNAL and group != '*' and group not in args.filter: + return False + return True + + def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): """ Get field value from definition @@ -1510,68 +1779,69 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): use offset for baseaddr (used for recursive calls) @return: - read field value + field mapping """ if isinstance(dobj, bytearray): dobj = str(dobj) - result = None - - if fieldname == 'raw' and not args.jsonrawkeys: - return result + valuemapping = None # get field definition - format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) + format, baseaddr, bits, bitshift, arraydef, group, tasmotacmnd = GetFieldDef(fielddef, fields='format, baseaddr, bits, bitshift, arraydef, group, tasmotacmnd') - # contains a integer list - if isinstance(datadef, list): - result = [] + # filter groups + if not IsFilterGroup(group): + return valuemapping + + # contains a integer list + if isinstance(arraydef, list) and len(arraydef) > 0: + valuemapping = [] offset = 0 - for i in range(0, datadef[0]): + for i in range(0, arraydef[0]): subfielddef = GetSubfieldDef(fielddef) length = GetFieldLength(subfielddef) if length != 0: - result.append(GetField(dobj, fieldname, subfielddef, raw=raw, addroffset=addroffset+offset)) + value = GetField(dobj, fieldname, subfielddef, raw=raw, addroffset=addroffset+offset) + valuemapping.append(value) offset += length - + # contains a dict elif isinstance(format, dict): - config = {} - for name in format: # -> iterate through format - if name != 'raw' or args.jsonrawkeys: - config[name] = GetField(dobj, name, format[name], raw=raw, addroffset=addroffset) - result = config + mapping_value = {} + # -> iterate through format + for name in format: + value = None + value = GetField(dobj, name, format[name], raw=raw, addroffset=addroffset) + if value is not None: + mapping_value[name] = value + # copy complete returned mapping + valuemapping = copy.deepcopy(mapping_value) # a simple value elif isinstance(format, (str, bool, int, float, long)): if GetFieldLength(fielddef) != 0: - result = struct.unpack_from(format, dobj, baseaddr+addroffset)[0] + valuemapping = struct.unpack_from(format, dobj, baseaddr+addroffset)[0] if not format[-1:].lower() in ['s','p']: - if bitshift>=0: - result >>= bitshift - else: - result <<= abs(bitshift) - if bits>0: - result &= (1< 127 - result = unicode(s, errors='ignore') + valuemapping = unicode(s, errors='ignore') - result = ConvertFieldValue(result, fielddef, read=True, raw=raw) + valuemapping = ReadWriteConverter(valuemapping, fielddef, read=True, raw=raw) else: exit(ExitCode.INTERNAL_ERROR, "Wrong mapping format definition: '{}'".format(format), typ=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) - return result + return valuemapping -def SetField(dobj, fieldname, fielddef, restore, raw=False, addroffset=0, filename=""): +def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""): """ Get field value from definition @@ -1581,48 +1851,50 @@ def SetField(dobj, fieldname, fielddef, restore, raw=False, addroffset=0, filena name of the field @param fielddef: see Settings desc above - @param raw - handle values as raw values (True) or converted (False) - @param addroffset - use offset for baseaddr (used for recursive calls) @param restore restore mapping with the new value(s) + @param addroffset + use offset for baseaddr (used for recursive calls) + @param filename + related filename (for messages only) + + @return: + new decrypted binary config data """ - format, baseaddr, bits, bitshift, datadef, convert = GetFieldDef(fielddef) + format, baseaddr, bits, bitshift, arraydef, group, writeconverter = GetFieldDef(fielddef, fields='format, baseaddr, bits, bitshift, arraydef, group, writeconverter') + # cast unicode fieldname = str(fieldname) - if fieldname == 'raw' and not args.jsonrawkeys: + # filter groups + if not IsFilterGroup(group): return dobj # do not write readonly values - if isinstance(convert, (list,tuple)) and len(convert)>1 and convert[1]==None: + if writeconverter is False: if args.debug: - print >> sys.stderr, "SetField(): Readonly '{}' using '{}'/{}{} @{} skipped".format(fieldname, format, datadef, bits, hex(baseaddr+addroffset)) + print >> sys.stderr, "SetField(): Readonly '{}' using '{}'/{}{} @{} skipped".format(fieldname, format, arraydef, bits, hex(baseaddr+addroffset)) return dobj - # contains a list - if isinstance(datadef, list): + # contains a list + if isinstance(arraydef, list) and len(arraydef) > 0: offset = 0 - if len(restore)>datadef[0]: - exit(ExitCode.RESTORE_DATA_ERROR, "file '{sfile}', array '{sname}[{selem}]' exceeds max number of elements [{smax}]".format(sfile=filename, sname=fieldname, selem=len(restore), smax=datadef[0]), typ=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) - for i in range(0, datadef[0]): + if len(restore) > arraydef[0]: + exit(ExitCode.RESTORE_DATA_ERROR, "file '{sfile}', array '{sname}[{selem}]' exceeds max number of elements [{smax}]".format(sfile=filename, sname=fieldname, selem=len(restore), smax=arraydef[0]), typ=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) + for i in range(0, arraydef[0]): subfielddef = GetSubfieldDef(fielddef) length = GetFieldLength(subfielddef) if length != 0: - if i>=len(restore): # restore data list may be shorter than definition + if i >= len(restore): # restore data list may be shorter than definition break - try: - subrestore = restore[i] - dobj = SetField(dobj, fieldname, subfielddef, subrestore, raw=raw, addroffset=addroffset+offset, filename=filename) - except: - pass + subrestore = restore[i] + dobj = SetField(dobj, fieldname, subfielddef, subrestore, addroffset=addroffset+offset, filename=filename) offset += length # contains a dict elif isinstance(format, dict): for name in format: # -> iterate through format if name in restore: - dobj = SetField(dobj, name, format[name], restore[name], raw=raw, addroffset=addroffset, filename=filename) + dobj = SetField(dobj, name, format[name], restore[name], addroffset=addroffset, filename=filename) # a simple value elif isinstance(format, (str, bool, int, float, long)): @@ -1633,76 +1905,82 @@ def SetField(dobj, fieldname, fielddef, restore, raw=False, addroffset=0, filena _min, _max = GetFieldMinMax(fielddef) value = _value = None skip = False - - # simple one value + + # simple char value if format[-1:] in ['c']: try: - value = ConvertFieldValue(restore.encode(STR_ENCODING)[0], fielddef, read=False, raw=raw) - except: - err = "valid range exceeding" + value = ReadWriteConverter(restore.encode(STR_ENCODING)[0], fielddef, read=False) + except Exception, e: + exit(e[0], e[1], typ=LogType.WARNING, line=inspect.getlineno(inspect.currentframe())) valid = False + # bool elif format[-1:] in ['?']: try: - value = ConvertFieldValue(bool(restore), fielddef, read=False, raw=raw) - except: - err = "valid range exceeding" + value = ReadWriteConverter(bool(restore), fielddef, read=False) + except Exception, e: + exit(e[0], e[1], typ=LogType.WARNING, line=inspect.getlineno(inspect.currentframe())) valid = False + # integer elif format[-1:] in ['b','B','h','H','i','I','l','L','q','Q','P']: - try: - value = ConvertFieldValue(restore, fielddef, read=False, raw=raw) - if isinstance(value, (str, unicode)): - value = int(value, 0) + value = ReadWriteConverter(restore, fielddef, read=False) + if isinstance(value, (str, unicode)): + value = int(value, 0) + else: + value = int(value) + # bits + if bits != 0: + bitvalue = value + value = struct.unpack_from(format, dobj, baseaddr+addroffset)[0] + # validate restore value + valid = ValidateValue(bitvalue, fielddef) + if not valid: + err = "valid bit range exceeding" else: - value = int(value) - # bit value - if bits!=0: - value = struct.unpack_from(format, dobj, baseaddr+addroffset)[0] - bitvalue = int(restore) mask = (1<mask: + if bitvalue > mask: _min = 0 _max = mask _value = bitvalue valid = False - err = "valid bit range exceeding" else: - if bitshift>=0: + if bitshift >= 0: bitvalue <<= bitshift mask <<= bitshift else: bitvalue >>= abs(bitshift) mask >>= abs(bitshift) + v=value value &= (0xffffffff ^ mask) value |= bitvalue - # full size values - else: - _value = value - except: - valid = False - err = "valid range exceeding" + + # full size values + else: + # validate restore function + valid = ValidateValue(value, fielddef) + if not valid: + err = "valid range exceeding" + _value = value + # float elif format[-1:] in ['f','d']: try: - value = ConvertFieldValue(float(restore), fielddef, read=False, raw=raw) + value = ReadWriteConverter(float(restore), fielddef, read=False) except: - err = "valid range exceeding" valid = False + # string elif format[-1:] in ['s','p']: - try: - value = ConvertFieldValue(restore.encode(STR_ENCODING), fielddef, read=False, raw=raw) - err = "string length exceeding" - if value is not None: - # be aware 0 byte at end of string (str must be < max, not <= max) - _max -= 1 - valid = _min <= len(value) < _max - else: - skip = True - valid = True - except: - valid = False + value = ReadWriteConverter(restore.encode(STR_ENCODING), fielddef, read=False) + err = "string length exceeding" + if value is not None: + # be aware 0 byte at end of string (str must be < max, not <= max) + _max -= 1 + valid = _min <= len(value) < _max + else: + skip = True + valid = True if value is None and not skip: # None is an invalid value @@ -1719,7 +1997,7 @@ def SetField(dobj, fieldname, fielddef, restore, raw=False, addroffset=0, filena # copy value before possible change below _value = value - if isinstance(value, (str, unicode)): + if isinstance(_value, (str, unicode)): _value = "'{}'".format(_value) if valid: @@ -1729,7 +2007,7 @@ def SetField(dobj, fieldname, fielddef, restore, raw=False, addroffset=0, filena sbits=" {} bits shift {}".format(bits, bitshift) else: sbits = "" - print >> sys.stderr, "SetField(): Set '{}' using '{}'/{}{} @{} to {}".format(fieldname, format, datadef, sbits, hex(baseaddr+addroffset), _value) + print >> sys.stderr, "SetField(): Set '{}' using '{}'/{}{} @{} to {}".format(fieldname, format, arraydef, sbits, hex(baseaddr+addroffset), _value) if fieldname != 'cfg_crc': prevvalue = struct.unpack_from(format, dobj, baseaddr+addroffset)[0] struct.pack_into(format, dobj, baseaddr+addroffset, value) @@ -1743,22 +2021,84 @@ def SetField(dobj, fieldname, fielddef, restore, raw=False, addroffset=0, filena return dobj -def Bin2Mapping(decode_cfg, raw=True): +def SetCmnd(cmnds, fieldname, fielddef, valuemapping, mappedvalue, addroffset=0, idx=None): + """ + Get field value from definition + + @param cmnds: + Tasmota command mapping: { 'group': ['cmnd' <,'cmnd'...>] ... } + @param fieldname: + name of the field + @param fielddef: + see Settings desc above + @param valuemapping: + data mapping + @param mappedvalue + mappedvalue mapping with the new value(s) + @param addroffset + use offset for baseaddr (used for recursive calls) + @param idx + optional array index + + @return: + new Tasmota command mapping + """ + format, baseaddr, bits, bitshift, arraydef, group, tasmotacmnd, writeconverter = GetFieldDef(fielddef, fields='format, baseaddr, bits, bitshift, arraydef, group, tasmotacmnd, writeconverter') + + # cast unicode + fieldname = str(fieldname) + + # filter groups + if not IsFilterGroup(group): + return cmnds + + # contains a list + if isinstance(arraydef, list) and len(arraydef) > 0: + offset = 0 + if len(mappedvalue) > arraydef[0]: + exit(ExitCode.RESTORE_DATA_ERROR, "array '{sname}[{selem}]' exceeds max number of elements [{smax}]".format(sname=fieldname, selem=len(mappedvalue), smax=arraydef[0]), typ=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) + for i in range(0, arraydef[0]): + subfielddef = GetSubfieldDef(fielddef) + length = GetFieldLength(subfielddef) + if length != 0: + if i >= len(mappedvalue): # mappedvalue data list may be shorter than definition + break + subrestore = mappedvalue[i] + cmnds = SetCmnd(cmnds, fieldname, subfielddef, valuemapping, subrestore, addroffset=addroffset+offset, idx=i) + offset += length + + # contains a dict + elif isinstance(format, dict): + for name in format: # -> iterate through format + if name in mappedvalue: + cmnds = SetCmnd(cmnds, name, format[name], valuemapping, mappedvalue[name], addroffset=addroffset, idx=idx) + + # a simple value + elif isinstance(format, (str, bool, int, float, long)): + cmnd = CmndConverter(valuemapping, mappedvalue, idx, fielddef) + + if group is not None and cmnd is not None: + if group not in cmnds: + cmnds[group] = [] + cmnds[group].append(cmnd) + + return cmnds + + +def Bin2Mapping(decode_cfg): """ Decodes binary data stream into pyhton mappings dict @param decode_cfg: binary config data (decrypted) - @param raw: - decode raw values (True) or converted values (False) @return: - config data as mapping dictionary + valuemapping data as mapping dictionary """ if isinstance(decode_cfg, bytearray): decode_cfg = str(decode_cfg) - # get binary header to use + # get binary header and template to use version, size, setting = GetTemplateSetting(decode_cfg) # if we did not found a mathching setting @@ -1771,7 +2111,7 @@ def Bin2Mapping(decode_cfg, raw=True): # check size if exists if 'cfg_size' in setting: cfg_size = GetField(decode_cfg, 'cfg_size', setting['cfg_size'], raw=True) - # read size should be same as definied in template + # read size should be same as definied in setting if cfg_size > size: # may be processed exit(ExitCode.DATA_SIZE_MISMATCH, "Number of bytes read does ot match - read {}, expected {} byte".format(cfg_size, size), typ=LogType.ERROR,line=inspect.getlineno(inspect.currentframe())) @@ -1787,41 +2127,39 @@ def Bin2Mapping(decode_cfg, raw=True): if cfg_crc != GetSettingsCrc(decode_cfg): exit(ExitCode.DATA_CRC_ERROR, 'Data CRC error, read 0x{:x} should be 0x{:x}'.format(cfg_crc, GetSettingsCrc(decode_cfg)), typ=LogType.WARNING, doexit=not args.ignorewarning,line=inspect.getlineno(inspect.currentframe())) - # get config - config = GetField(decode_cfg, None, (setting,None,None), raw=raw) + # get valuemapping + valuemapping = GetField(decode_cfg, None, (setting,0,(None, None, (INTERNAL, None)))) # add header info timestamp = datetime.now() - config['header'] = {'timestamp':timestamp.strftime("%Y-%m-%d %H:%M:%S"), - 'format': { - 'jsonindent': args.jsonindent, - 'jsoncompact': args.jsoncompact, - 'jsonsort': args.jsonsort, - 'jsonrawvalues':args.jsonrawvalues, - 'jsonrawkeys': args.jsonrawkeys, - 'jsonhidepw': args.jsonhidepw, - }, - 'template': { - 'version': hex(version), - 'crc': hex(cfg_crc), - }, - 'data': { - 'crc': hex(GetSettingsCrc(decode_cfg)), - 'size': len(decode_cfg), - }, - 'script': { - 'name': os.path.basename(__file__), - 'version': VER, - }, - 'os': (platform.machine(), platform.system(), platform.release(), platform.version(), platform.platform()), - 'python': platform.python_version(), - } + valuemapping['header'] = { 'timestamp':timestamp.strftime("%Y-%m-%d %H:%M:%S"), + 'format': { + 'jsonindent': args.jsonindent, + 'jsoncompact': args.jsoncompact, + 'jsonsort': args.jsonsort, + 'jsonhidepw': args.jsonhidepw, + }, + 'template': { + 'version': hex(version), + 'crc': hex(cfg_crc), + }, + 'data': { + 'crc': hex(GetSettingsCrc(decode_cfg)), + 'size': len(decode_cfg), + }, + 'script': { + 'name': os.path.basename(__file__), + 'version': VER, + }, + 'os': (platform.machine(), platform.system(), platform.release(), platform.version(), platform.platform()), + 'python': platform.python_version(), + } if 'cfg_crc' in setting: - config['header']['template'].update({'size': cfg_size}) + valuemapping['header']['template'].update({'size': cfg_size}) if 'version' in setting: - config['header']['data'].update({'version': hex(cfg_version)}) + valuemapping['header']['data'].update({'version': hex(cfg_version)}) - return config + return valuemapping def Mapping2Bin(decode_cfg, jsonconfig, filename=""): @@ -1836,7 +2174,7 @@ def Mapping2Bin(decode_cfg, jsonconfig, filename=""): name of the restore file (for error output only) @return: - changed binary config data (decrypted) + changed binary config data (decrypted) or None on error """ if isinstance(decode_cfg, str): decode_cfg = bytearray(decode_cfg) @@ -1845,41 +2183,73 @@ def Mapping2Bin(decode_cfg, jsonconfig, filename=""): # get binary header data to use the correct version template from device version, size, setting = GetTemplateSetting(decode_cfg) + # make empty binarray array _buffer = bytearray() + # add data _buffer.extend(decode_cfg) if setting is not None: - try: - raw = jsonconfig['header']['format']['jsonrawvalues'] - except: - if 'header' not in jsonconfig: - errkey = 'header' - elif 'format' not in jsonconfig['header']: - errkey = 'header.format' - elif 'jsonrawvalues' not in jsonconfig['header']['format']: - errkey = 'header.format.jsonrawvalues' - exit(ExitCode.RESTORE_DATA_ERROR, "Restore file '{sfile}' name '{skey}' missing, don't know how to evaluate restore data!".format(sfile=filename, skey=errkey), typ=LogType.ERROR, doexit=not args.ignorewarning) - # iterate through restore data mapping for name in jsonconfig: # key must exist in both dict if name in setting: - SetField(_buffer, name, setting[name], jsonconfig[name], raw=raw, addroffset=0, filename=filename) + SetField(_buffer, name, setting[name], jsonconfig[name], addroffset=0, filename=filename) else: if name != 'header': exit(ExitCode.RESTORE_DATA_ERROR, "Restore file '{}' contains obsolete name '{}', skipped".format(filename, name), typ=LogType.WARNING, doexit=not args.ignorewarning) - crc = GetSettingsCrc(_buffer) - struct.pack_into(setting['cfg_crc'][0], _buffer, setting['cfg_crc'][1], crc) + if 'cfg_crc' in setting: + crc = GetSettingsCrc(_buffer) + struct.pack_into(setting['cfg_crc'][0], _buffer, setting['cfg_crc'][1], crc) return _buffer else: exit(ExitCode.UNSUPPORTED_VERSION,"File '{}', Tasmota configuration version 0x{:x} not supported".format(filename, version), typ=LogType.WARNING, doexit=not args.ignorewarning) - return decode_cfg + return None -def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configuration): +def Mapping2Cmnd(decode_cfg, valuemapping, filename=""): + """ + Encodes mapping data into Tasmota command mapping + + @param decode_cfg: + binary config data (decrypted) + @param valuemapping: + data mapping + @param filename: + name of the restore file (for error output only) + + @return: + Tasmota command mapping {group: [cmnd <,cmnd <,...>>]} + """ + if isinstance(decode_cfg, str): + decode_cfg = bytearray(decode_cfg) + + # get binary header data to use the correct version template from device + version, size, setting = GetTemplateSetting(decode_cfg) + + cmnds = {} + + if setting is not None: + # iterate through restore data mapping + for name in valuemapping: + # key must exist in both dict + if name in setting: + cmnds = SetCmnd(cmnds, name, setting[name], valuemapping, valuemapping[name], addroffset=0) + else: + if name != 'header': + exit(ExitCode.RESTORE_DATA_ERROR, "Restore file '{}' contains obsolete name '{}', skipped".format(filename, name), typ=LogType.WARNING, doexit=not args.ignorewarning) + + return cmnds + + else: + exit(ExitCode.UNSUPPORTED_VERSION,"File '{}', Tasmota configuration version 0x{:x} not supported".format(filename, version), typ=LogType.WARNING, doexit=not args.ignorewarning) + + return None + + +def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configmapping): """ Create backup file @@ -1891,27 +2261,38 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configuration): binary config data (encrypted) @param decode_cfg: binary config data (decrypted) - @param configuration: + @param configmapping: config data mapppings """ backupfileformat = args.backupfileformat - try: - name, ext = os.path.splitext(backupfile) - if ext.lower() == '.'+FileType.BIN.lower(): - backupfileformat = FileType.BIN - elif ext.lower() == '.'+FileType.DMP.lower(): - backupfileformat = FileType.DMP - elif ext.lower() == '.'+FileType.JSON.lower(): - backupfileformat = FileType.JSON - except: - pass + name, ext = os.path.splitext(backupfile) + if ext.lower() == '.'+FileType.BIN.lower(): + backupfileformat = FileType.BIN + elif ext.lower() == '.'+FileType.DMP.lower(): + backupfileformat = FileType.DMP + elif ext.lower() == '.'+FileType.JSON.lower(): + backupfileformat = FileType.JSON fileformat = "" + # Tasmota format + if backupfileformat.lower() == FileType.DMP.lower(): + fileformat = "Tasmota" + backup_filename = MakeFilename(backupfile, FileType.DMP, configmapping) + if args.verbose: + message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), typ=LogType.INFO) + try: + backupfp = open(backup_filename, "wb") + backupfp.write(encode_cfg) + except Exception, e: + exit(e[0], "'{}' {}".format(backup_filename, e[1]),line=inspect.getlineno(inspect.currentframe())) + finally: + backupfp.close() + # binary format - if backupfileformat.lower() == FileType.BIN.lower(): + elif backupfileformat.lower() == FileType.BIN.lower(): fileformat = "binary" - backup_filename = MakeFilename(backupfile, FileType.BIN, configuration) + backup_filename = MakeFilename(backupfile, FileType.BIN, configmapping) if args.verbose: message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), typ=LogType.INFO) try: @@ -1924,33 +2305,20 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configuration): finally: backupfp.close() - # Tasmota format - if backupfileformat.lower() == FileType.DMP.lower(): - fileformat = "Tasmota" - backup_filename = MakeFilename(backupfile, FileType.DMP, configuration) + # JSON format + elif backupfileformat.lower() == FileType.JSON.lower(): + fileformat = "JSON" + backup_filename = MakeFilename(backupfile, FileType.JSON, configmapping) if args.verbose: message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), typ=LogType.INFO) try: - backupfp = open(backup_filename, "wb") - backupfp.write(encode_cfg) + backupfp = open(backup_filename, "w") + json.dump(configmapping, backupfp, sort_keys=args.jsonsort, indent=None if args.jsonindent < 0 else args.jsonindent, separators=(',', ':') if args.jsoncompact else (', ', ': ') ) except Exception, e: exit(e[0], "'{}' {}".format(backup_filename, e[1]),line=inspect.getlineno(inspect.currentframe())) finally: backupfp.close() - # JSON format - elif backupfileformat.lower() == FileType.JSON.lower(): - fileformat = "JSON" - backup_filename = MakeFilename(backupfile, FileType.JSON, configuration) - if args.verbose: - message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), typ=LogType.INFO) - try: - backupfp = open(backup_filename, "w") - json.dump(configuration, backupfp, sort_keys=args.jsonsort, indent=None if args.jsonindent<0 else args.jsonindent, separators=(',', ':') if args.jsoncompact else (', ', ': ') ) - except Exception, e: - exit(e[0], "'{}' {}".format(backup_filename, e[1]),line=inspect.getlineno(inspect.currentframe())) - finally: - backupfp.close() if args.verbose: srctype = 'device' src = args.device @@ -1960,7 +2328,7 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configuration): message("Backup successful from {} '{}' to file '{}' ({} format)".format(srctype, src, backup_filename, fileformat), typ=LogType.INFO) -def Restore(restorefile, encode_cfg, decode_cfg, configuration): +def Restore(restorefile, encode_cfg, decode_cfg, configmapping): """ Restore from file @@ -1968,13 +2336,13 @@ def Restore(restorefile, encode_cfg, decode_cfg, configuration): binary config data (encrypted) @param decode_cfg: binary config data (decrypted) - @param configuration: + @param configmapping: config data mapppings """ new_encode_cfg = None - restorefilename = MakeFilename(restorefile, None, configuration) + restorefilename = MakeFilename(restorefile, None, configmapping) filetype = GetFileType(restorefilename) if filetype == FileType.DMP: @@ -2025,7 +2393,7 @@ def Restore(restorefile, encode_cfg, decode_cfg, configuration): exit(ExitCode.FILE_READ_ERROR, "File '{}' unknown error".format(restorefilename),line=inspect.getlineno(inspect.currentframe())) if new_encode_cfg is not None: - if new_encode_cfg != encode_cfg or args.ignorewarning: + if args.forcerestore or new_encode_cfg != encode_cfg: # write config direct to device via http if args.device is not None: if args.verbose: @@ -2058,6 +2426,36 @@ def Restore(restorefile, encode_cfg, decode_cfg, configuration): message("Configuration data leaving unchanged", typ=LogType.INFO) +def OutputTasmotaCmnds(tasmotacmnds): + """ + Print Tasmota command mapping + + @param tasmotacmnds: + Tasmota command mapping {group: [cmnd <,cmnd <,...>>]} + """ + def OutputTasmotaSubCmnds(cmnds): + if args.cmndsort: + for cmnd in sorted(cmnds, key = lambda cmnd:[int(c) if c.isdigit() else c for c in re.split('(\d+)', cmnd)]): + print "{}{}".format(" "*args.cmndindent, cmnd) + else: + for cmnd in cmnds: + print "{}{}".format(" "*args.cmndindent, cmnd) + + if args.cmndgroup: + for group in Groups: + if group in tasmotacmnds: + cmnds = tasmotacmnds[group] + print + print "# {}:".format(group) + OutputTasmotaSubCmnds(cmnds) + + else: + cmnds = [] + for group in Groups: + if group in tasmotacmnds: + cmnds.extend(tasmotacmnds[group]) + OutputTasmotaSubCmnds(cmnds) + def ParseArgs(): """ Program argument parser @@ -2098,7 +2496,7 @@ def ParseArgs(): default=DEFAULTS['source']['password'], help="host HTTP access password (default: {})".format(DEFAULTS['source']['password'])) - backup = parser.add_argument_group('Backup/Restore', 'Backup/Restore configuration file specification') + backup = parser.add_argument_group('Backup/Restore', 'Backup & restore specification') backup.add_argument('-i', '--restore-file', metavar='', dest='restorefile', @@ -2109,11 +2507,11 @@ def ParseArgs(): dest='backupfile', default=DEFAULTS['backup']['backupfile'], help="file to backup configuration to (default: {}). Replacements: @v=firmware version, @f=device friendly name, @h=device hostname".format(DEFAULTS['backup']['backupfile'])) - output_file_formats = ['json', 'bin', 'dmp'] - backup.add_argument('-F', '--backup-type', - metavar='|'.join(output_file_formats), + backup_file_formats = ['json', 'bin', 'dmp'] + backup.add_argument('-t', '--backup-type', + metavar='|'.join(backup_file_formats), dest='backupfileformat', - choices=output_file_formats, + choices=backup_file_formats, default=DEFAULTS['backup']['backupfileformat'], help="backup filetype (default: '{}')".format(DEFAULTS['backup']['backupfileformat']) ) backup.add_argument('-E', '--extension', @@ -2126,8 +2524,13 @@ def ParseArgs(): action='store_false', default=DEFAULTS['backup']['extension'], help="do not append filetype extension, use -i and -o filename as passed{}".format(' (default)' if not DEFAULTS['backup']['extension'] else '') ) + backup.add_argument('-F', '--force-restore', + dest='forcerestore', + action='store_true', + default=DEFAULTS['backup']['forcerestore'], + help="force restore even configuration is identical{}".format(' (default)' if DEFAULTS['backup']['forcerestore'] else '') ) - jsonformat = parser.add_argument_group('JSON', 'JSON backup format specification') + jsonformat = parser.add_argument_group('JSON output', 'JSON format specification') jsonformat.add_argument('--json-indent', metavar='', dest='jsonindent', @@ -2151,40 +2554,82 @@ def ParseArgs(): default=DEFAULTS['jsonformat']['jsonsort'], help=configargparse.SUPPRESS) #"do not sort json keywords{}".format(' (default)' if not DEFAULTS['jsonformat']['jsonsort'] else '') ) - jsonformat.add_argument('--json-raw-values', - dest='jsonrawvalues', - action='store_true', - default=DEFAULTS['jsonformat']['jsonrawvalues'], - help=configargparse.SUPPRESS) #"output raw values{}".format(' (default)' if DEFAULTS['jsonformat']['jsonrawvalues'] else '') ) - jsonformat.add_argument('--json-convert-values', - dest='jsonrawvalues', - action='store_false', - default=DEFAULTS['jsonformat']['jsonrawvalues'], - help=configargparse.SUPPRESS) #"output converted, human readable values{}".format(' (default)' if not DEFAULTS['jsonformat']['jsonrawvalues'] else '') ) - - jsonformat.add_argument('--json-raw-keys', - dest='jsonrawkeys', - action='store_true', - default=DEFAULTS['jsonformat']['jsonrawkeys'], - help=configargparse.SUPPRESS) #"output bitfield raw keys{}".format(' (default)' if DEFAULTS['jsonformat']['jsonrawkeys'] else '') ) - jsonformat.add_argument('--json-no-raw-keys', - dest='jsonrawkeys', - action='store_false', - default=DEFAULTS['jsonformat']['jsonrawkeys'], - help=configargparse.SUPPRESS) #"do not output bitfield raw keys{}".format(' (default)' if not DEFAULTS['jsonformat']['jsonrawkeys'] else '') ) - jsonformat.add_argument('--json-hide-pw', dest='jsonhidepw', action='store_true', default=DEFAULTS['jsonformat']['jsonhidepw'], help="hide passwords{}".format(' (default)' if DEFAULTS['jsonformat']['jsonhidepw'] else '') ) - jsonformat.add_argument('--json-unhide-pw', + jsonformat.add_argument('--json-show-pw', '--json-unhide-pw', dest='jsonhidepw', action='store_false', default=DEFAULTS['jsonformat']['jsonhidepw'], help="unhide passwords{}".format(' (default)' if not DEFAULTS['jsonformat']['jsonhidepw'] else '') ) - info = parser.add_argument_group('Info','additional information') + cmndformat = parser.add_argument_group('Tasmota command output', 'Tasmota command output format specification') + cmndformat.add_argument('--cmnd-indent', + metavar='', + dest='cmndindent', + type=int, + default=DEFAULTS['cmndformat']['cmndindent'], + help="Tasmota command grouping indent level (default: '{}'). 0 disables indent".format(DEFAULTS['cmndformat']['cmndindent']) ) + cmndformat.add_argument('--cmnd-groups', + dest='cmndgroup', + action='store_true', + default=DEFAULTS['cmndformat']['cmndgroup'], + help="group Tasmota commands{}".format(' (default)' if DEFAULTS['cmndformat']['cmndgroup'] else '') ) + cmndformat.add_argument('--cmnd-nogroups', + dest='cmndgroup', + action='store_false', + default=DEFAULTS['cmndformat']['cmndgroup'], + help="leave Tasmota commands ungrouped{}".format(' (default)' if not DEFAULTS['cmndformat']['cmndgroup'] else '') ) + cmndformat.add_argument('--cmnd-sort', + dest='cmndsort', + action='store_true', + default=DEFAULTS['cmndformat']['cmndsort'], + help="sort Tasmota commands{}".format(' (default)' if DEFAULTS['cmndformat']['cmndsort'] else '') ) + cmndformat.add_argument('--cmnd-unsort', + dest='cmndsort', + action='store_false', + default=DEFAULTS['cmndformat']['cmndsort'], + help="leave Tasmota commands unsorted{}".format(' (default)' if not DEFAULTS['cmndformat']['cmndsort'] else '') ) + + common = parser.add_argument_group('Common', 'Optional arguments') + common.add_argument('-c', '--config', + metavar='', + dest='configfile', + default=DEFAULTS['common']['configfile'], + is_config_file=True, + help="program config file - can be used to set default command args (default: {})".format(DEFAULTS['common']['configfile']) ) + + common.add_argument('-S', '--output', + dest='output', + action='store_true', + default=DEFAULTS['common']['output'], + help="display output regardsless of backup/restore usage{}".format(" (default)" if DEFAULTS['common']['output'] else " (default do not output on backup or restore usage)") ) + output_formats = ['json', 'cmnd','command'] + common.add_argument('-T', '--output-format', + metavar='|'.join(output_formats), + dest='outputformat', + choices=output_formats, + default=DEFAULTS['common']['outputformat'], + help="display output format (default: '{}')".format(DEFAULTS['common']['outputformat']) ) + groups = GetGroupList(Settings[0][2]) + if '*' in groups: + groups.remove('*') + common.add_argument('-g', '--group', + dest='filter', + choices=groups, + nargs='+', + default=DEFAULTS['common']['filter'], + help="limit data processing to command groups (default {})".format("no filter" if DEFAULTS['common']['filter'] == None else DEFAULTS['common']['filter']) ) + common.add_argument('--ignore-warnings', + dest='ignorewarning', + action='store_true', + default=DEFAULTS['common']['ignorewarning'], + help="do not exit on warnings{}. Not recommended, used by your own responsibility!".format(' (default)' if DEFAULTS['common']['ignorewarning'] else '') ) + + + info = parser.add_argument_group('Info','Extra information') info.add_argument('-D', '--debug', dest='debug', action='store_true', @@ -2204,19 +2649,6 @@ def ParseArgs(): action='version', version=PROG) - # optional arguments - parser.add_argument('-c', '--config', - metavar='', - dest='configfile', - default=DEFAULTS['DEFAULT']['configfile'], - is_config_file=True, - help="program config file - can be used to set default command args (default: {})".format(DEFAULTS['DEFAULT']['configfile']) ) - parser.add_argument('--ignore-warnings', - dest='ignorewarning', - action='store_true', - default=DEFAULTS['DEFAULT']['ignorewarning'], - help="do not exit on warnings{}. Not recommended, used by your own responsibility!".format(' (default)' if DEFAULTS['DEFAULT']['ignorewarning'] else '') ) - args = parser.parse_args() if args.debug: @@ -2266,23 +2698,28 @@ if __name__ == "__main__": decode_cfg = DecryptEncrypt(encode_cfg) # decode into mappings dictionary - configuration = Bin2Mapping(decode_cfg, args.jsonrawvalues) - if args.verbose and 'version' in configuration: - if args.tasmotafile is not None: - message("File '{}' contains data for Tasmota v{}".format(args.tasmotafile, GetVersionStr(configuration['version'])),typ=LogType.INFO) - else: - message("Device '{}' runs Tasmota v{}".format(args.device,GetVersionStr(configuration['version'])),typ=LogType.INFO) + configmapping = Bin2Mapping(decode_cfg) + if args.verbose and 'version' in configmapping: + message("{} '{}' is using version {}".format('File' if args.tasmotafile is not None else 'Device', + args.tasmotafile if args.tasmotafile is not None else args.device, + GetVersionStr(configmapping['version'])), + typ=LogType.INFO) # backup to file if args.backupfile is not None: - Backup(args.backupfile, args.backupfileformat, encode_cfg, decode_cfg, configuration) + Backup(args.backupfile, args.backupfileformat, encode_cfg, decode_cfg, configmapping) # restore from file if args.restorefile is not None: - Restore(args.restorefile, encode_cfg, decode_cfg, configuration) + Restore(args.restorefile, encode_cfg, decode_cfg, configmapping) # json screen output - if args.backupfile is None and args.restorefile is None: - print json.dumps(configuration, sort_keys=args.jsonsort, indent=None if args.jsonindent<0 else args.jsonindent, separators=(',', ':') if args.jsoncompact else (', ', ': ') ) + if (args.backupfile is None and args.restorefile is None) or args.output: + if args.outputformat == 'json': + print json.dumps(configmapping, sort_keys=args.jsonsort, indent=None if args.jsonindent<0 else args.jsonindent, separators=(',', ':') if args.jsoncompact else (', ', ': ') ) + if args.outputformat == 'cmnd' or args.outputformat == 'command': + tasmotacmnds = Mapping2Cmnd(decode_cfg, configmapping) + OutputTasmotaCmnds(tasmotacmnds) + sys.exit(exitcode) From a01f9bdda1d2aa0d7f2aee24a42b068809f3ae7f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 13 Nov 2018 15:15:11 +0100 Subject: [PATCH 0483/2222] Add re-probe to NovaSDS sensor Add re-probe to NovaSDS sensor (#4335) --- sonoff/xsns_20_novasds.ino | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 8a584571c..c100c6ad6 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -73,8 +73,6 @@ void NovaSdsSetWorkPeriod() } } - - bool NovaSdsReadData() { if (! NovaSdsSerial->available()) return false; @@ -101,8 +99,6 @@ bool NovaSdsReadData() return false; } - novasds_valid = 10; - return true; } @@ -110,11 +106,17 @@ bool NovaSdsReadData() void NovaSdsSecond() // Every second { - if (NovaSdsReadData()) { - novasds_valid = 10; + if (XSNS_20 == (uptime % 100)) { + if (!novasds_valid) { + NovaSdsSetWorkPeriod(); + } } else { - if (novasds_valid) { - novasds_valid--; + if (NovaSdsReadData()) { + novasds_valid = 10; + } else { + if (novasds_valid) { + novasds_valid--; + } } } } From 2c138e69c2f5dd5e7853457bf97d7e1b51bffc2e Mon Sep 17 00:00:00 2001 From: Denis Taranushin Date: Tue, 13 Nov 2018 19:55:24 +0500 Subject: [PATCH 0484/2222] Add SDM220 Support Add some electric parameters for SDM220 --- sonoff/i18n.h | 6 +++ sonoff/language/bg-BG.h | 14 ++++++- sonoff/language/cs-CZ.h | 14 ++++++- sonoff/language/de-DE.h | 14 ++++++- sonoff/language/el-GR.h | 14 ++++++- sonoff/language/en-GB.h | 13 +++++- sonoff/language/es-AR.h | 14 ++++++- sonoff/language/fr-FR.h | 14 ++++++- sonoff/language/he-HE.h | 14 ++++++- sonoff/language/hu-HU.h | 14 ++++++- sonoff/language/it-IT.h | 14 ++++++- sonoff/language/nl-NL.h | 14 ++++++- sonoff/language/pl-PL.h | 14 ++++++- sonoff/language/pt-BR.h | 14 ++++++- sonoff/language/pt-PT.h | 14 ++++++- sonoff/language/ru-RU.h | 14 ++++++- sonoff/language/tr-TR.h | 14 ++++++- sonoff/language/uk-UK.h | 14 ++++++- sonoff/language/zh-CN.h | 14 ++++++- sonoff/language/zh-TW.h | 14 ++++++- sonoff/my_user_config.h | 3 +- sonoff/xsns_23_sdm120.ino | 88 +++++++++++++++++++++++++++++++++++---- 22 files changed, 315 insertions(+), 47 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 36d93ccd7..6e6669237 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -49,6 +49,12 @@ #define D_JSON_COUNT "Count" #define D_JSON_COUNTER "Counter" #define D_JSON_CURRENT "Current" // As in Voltage and Current +#define D_JSON_PHASE_ANGLE "Phase angle" +#define D_JSON_IMPORT_ACTIVE "Import Active Power" +#define D_JSON_EXPORT_ACTIVE "Export Active Power" +#define D_JSON_IMPORT_REACTIVE "Import Reactive Power" +#define D_JSON_EXPORT_REACTIVE "Export Reactive Power" +#define D_JSON_TOTAL_REACTIVE "Total Reactive Power" #define D_JSON_DATA "Data" #define D_JSON_DISTANCE "Distance" #define D_JSON_DNSSERVER "DNSServer" diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 1503884c3..898157a20 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_BG_BG_H_ diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 2b667cec1..29f65af85 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_CS_CZ_H_ diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 9c2f7c24e..e6293044c 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_DE_DE_H_ diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 79558615d..3ecd442a3 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -516,8 +516,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -587,4 +587,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_EN_GB_H_ diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 1a9304a7d..e93850170 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,13 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_EN_GB_H_ diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index e5c3135fe..c2d6481e9 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_ES_AR_H_ diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 0dfb2929c..6fea65b6b 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_FR_FR_H_ diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index cb041ffba..1a6d44f7a 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_HE_HE_H_ diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 5cee46a52..2bc0d41d6 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_HU_HU_H_ diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 0eaca9337..b15b9aed2 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_IT_IT_H_ diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 0567e0849..9010722cc 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_NL_NL_H_ diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 678a7b770..f82fce1ae 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_PL_PL_D_H_ diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 712ea6a74..27e3ac64a 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_PT_BR_H_ diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 0bba501bd..58bf2cf73 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_PT_PT_H_ diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index f9062a572..bc1a6ee0e 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Угол фазы" +#define D_IMPORT_ACTIVE "Импорт активной мощности" +#define D_EXPORT_ACTIVE "Экспорт активной мощности" +#define D_IMPORT_REACTIVE "Импорт реактивной мощности" +#define D_EXPORT_REACTIVE "Экспорт реактивной мощности" +#define D_TOTAL_REACTIVE "Итого реактивная мощность" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Град" + #endif // _LANGUAGE_RU_RU_H_ diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index f892fafbb..55020e7a6 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_TR_TR_H_ diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 4c290613a..f6eb37689 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_UK_UK_H_ diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index fe6dabe8d..085460ef5 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_ZH_CN_H_ diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 92a805587..6656194ca 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -586,4 +586,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_ZH_TW_H_ diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index e1f6e364a..66f96b0ff 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -348,8 +348,9 @@ #define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) #define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) -//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) +#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) #define SDM120_SPEED 9600 // SDM120-Modbus RS485 serial speed (default: 2400 baud) + #define USE_SDM220 // add extra parameters for SDM220 (+0k1 code) //#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) //#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino index 5c2dfa630..dcbd263fa 100644 --- a/sonoff/xsns_23_sdm120.ino +++ b/sonoff/xsns_23_sdm120.ino @@ -42,6 +42,12 @@ float sdm120_reactive_power = 0; float sdm120_power_factor = 0; float sdm120_frequency = 0; float sdm120_energy_total = 0; +float sdm120_phase_angle = 0; +float sdm120_import_active = 0; +float sdm120_export_active = 0; +float sdm120_import_reactive = 0; +float sdm120_export_reactive = 0; +float sdm120_total_reactive = 0; bool SDM120_ModbusReceiveReady() { @@ -131,7 +137,17 @@ const uint16_t sdm120_start_addresses[] { 0x0018, // SDM120C_REACTIVE_POWER [VAR] 0x001E, // SDM120C_POWER_FACTOR 0x0046, // SDM120C_FREQUENCY [Hz] +#ifdef USE_SDM220 + 0x0156, // SDM120C_TOTAL_ACTIVE_ENERGY [Wh] + 0X0024, // SDM220_PHASE_ANGLE [Degre] + 0X0048, // SDM220_IMPORT_ACTIVE [kWh] + 0X004A, // SDM220_EXPORT_ACTIVE [kWh] + 0X004C, // SDM220_IMPORT_REACTIVE [kVArh] + 0X004E, // SDM220_EXPORT_REACTIVE [kVArh] + 0X0158 // SDM220 TOTAL_REACTIVE [kVArh] +#else // USE_SDM220 0x0156 // SDM120C_TOTAL_ACTIVE_ENERGY [Wh] +#endif // USE_SDM220 }; uint8_t sdm120_read_state = 0; @@ -184,6 +200,31 @@ void SDM120250ms() // Every 250 mSec case 7: sdm120_energy_total = value; break; +#ifdef USE_SDM220 + case 8: + sdm120_phase_angle = value; + break; + + case 9: + sdm120_import_active = value; + break; + + case 10: + sdm120_export_active = value; + break; + + case 11: + sdm120_import_reactive = value; + break; + + case 12: + sdm120_export_reactive = value; + break; + + case 13: + sdm120_total_reactive = value; + break; +#endif // USE_SDM220 } // end switch sdm120_read_state++; @@ -228,7 +269,16 @@ const char HTTP_SNS_SDM120_DATA[] PROGMEM = "%s" "{s}SDM120 " D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" "{s}SDM120 " D_POWER_FACTOR "{m}%s{e}" "{s}SDM120 " D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}" - "{s}SDM120 " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; + "{s}SDM120 " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}" +#ifdef USE_SDM220 + "{s}SDM120 " D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}" + "{s}SDM120 " D_IMPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}SDM120 " D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}SDM120 " D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + "{s}SDM120 " D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + "{s}SDM120 " D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" +#endif // USE_SDM220 + ; #endif // USE_WEBSERVER void SDM120Show(boolean json) @@ -241,19 +291,37 @@ void SDM120Show(boolean json) char power_factor[10]; char frequency[10]; char energy_total[10]; + char phase_angle[10]; + char import_active[10]; + char export_active[10]; + char import_reactive[10]; + char export_reactive[10]; + char total_reactive[10]; - dtostrfd(sdm120_voltage, Settings.flag2.voltage_resolution, voltage); - dtostrfd(sdm120_current, Settings.flag2.current_resolution, current); - dtostrfd(sdm120_active_power, Settings.flag2.wattage_resolution, active_power); + dtostrfd(sdm120_voltage, Settings.flag2.voltage_resolution, voltage); + dtostrfd(sdm120_current, Settings.flag2.current_resolution, current); + dtostrfd(sdm120_active_power, Settings.flag2.wattage_resolution, active_power); dtostrfd(sdm120_apparent_power, Settings.flag2.wattage_resolution, apparent_power); dtostrfd(sdm120_reactive_power, Settings.flag2.wattage_resolution, reactive_power); - dtostrfd(sdm120_power_factor, 2, power_factor); - dtostrfd(sdm120_frequency, Settings.flag2.frequency_resolution, frequency); - dtostrfd(sdm120_energy_total, Settings.flag2.energy_resolution, energy_total); - + dtostrfd(sdm120_power_factor, 2, power_factor); + dtostrfd(sdm120_frequency, Settings.flag2.frequency_resolution, frequency); + dtostrfd(sdm120_energy_total, Settings.flag2.energy_resolution, energy_total); +#ifdef USE_SDM220 + dtostrfd(sdm120_phase_angle, 2, phase_angle); + dtostrfd(sdm120_import_active, Settings.flag2.wattage_resolution, import_active); + dtostrfd(sdm120_export_active, Settings.flag2.wattage_resolution, export_active); + dtostrfd(sdm120_import_reactive,Settings.flag2.wattage_resolution, import_reactive); + dtostrfd(sdm120_export_reactive,Settings.flag2.wattage_resolution, export_reactive); + dtostrfd(sdm120_total_reactive, Settings.flag2.wattage_resolution, total_reactive); +#endif // USE_SDM220 if (json) { +#ifdef USE_SDM220 + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s,\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_EXPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s}"), + mqtt_data, energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current, phase_angle, import_active, export_active, import_reactive, export_reactive, total_reactive); +#else snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), mqtt_data, energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current); +#endif // USE_SDM220 #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_VOLTAGE, voltage); @@ -263,7 +331,11 @@ void SDM120Show(boolean json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { +#ifdef USE_SDM220 + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SDM120_DATA, mqtt_data, voltage, current, active_power, apparent_power, reactive_power, power_factor, frequency, energy_total, phase_angle,import_active,export_active,import_reactive,export_reactive,total_reactive); +#else snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SDM120_DATA, mqtt_data, voltage, current, active_power, apparent_power, reactive_power, power_factor, frequency, energy_total); +#endif // USE_SDM220 #endif // USE_WEBSERVER } } From 0ff2f9072d66c9b62112ac708bfe35cb87d5766c Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Wed, 14 Nov 2018 08:03:55 +0100 Subject: [PATCH 0485/2222] decode-config.py: add/fix Tasmota cmnd output and filename macros - add Tasmota SetOption51/53/54 - add filename network hostname macro @H - fix filename @* macros (removed if data source is unavailable) - fix Tasmota SetOption3x - fix http body garbadge output on screen - revise desc md/html files --- tools/decode-config.html | 26 +++-- tools/decode-config.md | 26 +++-- tools/decode-config.py | 223 ++++++++++++++++++++++++--------------- 3 files changed, 177 insertions(+), 98 deletions(-) diff --git a/tools/decode-config.html b/tools/decode-config.html index 4fa7b4e04..dd24495b7 100644 --- a/tools/decode-config.html +++ b/tools/decode-config.html @@ -4,7 +4,7 @@

          • decode-config.py uses human readable and editable JSON-format for backup/restore,
          • decode-config.py can restore previous backuped and changed JSON-format files,
          • -
          • decode-config.py is able to create Tasomta commands based on given configuration
          • +
          • decode-config.py is able to create Tasmota commands based on given configuration

          Comparing backup files created by decode-config.py and *.dmp files created by Tasmota "Backup/Restore Configuration":

          @@ -69,6 +69,7 @@
        • Use batch processing
        • +
        • Notes
        • @@ -190,7 +191,7 @@ WifiConfig 5

          Note: A few very specific module commands like MPC230xx, KNX and some Display commands are not supported. These are still available by JSON output.

          Filter data

          -

          The huge number of Tasomta configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories.

          +

          The huge number of Tasmota configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories.

          With decode-config.py the following categories are available: Display, Domoticz, Internal, KNX, Led, Logging, MCP230xx, MQTT, Main, Management, Pow, Sensor, Serial, SetOption, SonoffRF, System, Timers, Wifi

          These are similary to the categories on https://github.com/arendst/Sonoff-Tasmota/wiki/Commands.

          To filter outputs to a subset of groups use the -g or --group arg concatenating the grooup you want, e. g.

          @@ -247,12 +248,16 @@ -i, --restore-file <filename> file to restore configuration from (default: None). - Replacements: @v=firmware version, @f=device friendly - name, @h=device hostname + Replacements: @v=firmware version from config, + @f=device friendly name from config, @h=device + hostname from config, @H=device hostname from device + (-d arg only) -o, --backup-file <filename> file to backup configuration to (default: None). - Replacements: @v=firmware version, @f=device friendly - name, @h=device hostname + Replacements: @v=firmware version from config, + @f=device friendly name from config, @h=device + hostname from config, @H=device hostname from device + (-d arg only) -t, --backup-type json|bin|dmp backup filetype (default: 'json') -E, --extension append filetype extension for -i and -o filename @@ -339,3 +344,12 @@ json-indent 2

          or under windows

          for device in (sonoff1 sonoff2 sonoff3) do python decode-config.py -c my.conf -d %device -o Config_@f_@v
           

          will produce JSON configuration files for host sonoff1, sonoff2 and sonoff3 using friendly name and Tasmota firmware version for backup filenames.

          +

          Notes

          +

          Some general notes:

          +
            +
          • Filename replacement macros @h and @H:
              +
            • @h
              The @h replacement macro uses the hostname configured with the Tasomta Wifi Hostname <host> command (defaults to %s-%04d). It will not use the network hostname of your device because this is not available when working with files only (e.g. --file <filename> as source).
              To prevent having a useless % in your filename, @h will not replaced by configuration data hostname if this contains '%' characters.
            • +
            • @H
              If you want to use the network hostname within your filename, use the @H replacement macro instead - but be aware this will only replaced if you are using a network device as source (-d, --device, --host); it will not work when using a file as source (-f, --file)
            • +
            +
          • +
          diff --git a/tools/decode-config.md b/tools/decode-config.md index dab16a2c8..97978114a 100644 --- a/tools/decode-config.md +++ b/tools/decode-config.md @@ -4,7 +4,7 @@ _decode-config.py_ is able to backup and restore Sonoff-Tasmota configuration. In contrast to the Tasmota build-in "Backup/Restore Configuration" function, * _decode-config.py_ uses human readable and editable [JSON](http://www.json.org/)-format for backup/restore, * _decode-config.py_ can restore previous backuped and changed [JSON](http://www.json.org/)-format files, -* _decode-config.py_ is able to create Tasomta commands based on given configuration +* _decode-config.py_ is able to create Tasmota commands based on given configuration Comparing backup files created by *decode-config.py* and *.dmp files created by Tasmota "Backup/Restore Configuration": @@ -38,6 +38,7 @@ _decode-config.py_ is able to handle Tasmota configurations for release version * [Config file](decode-config.md#config-file) * [Using Tasmota binary configuration files](decode-config.md#using-tasmota-binary-configuration-files) * [Use batch processing](decode-config.md#use-batch-processing) + * [Notes](decode-config.md#notes) ## Prerequisite * [Python](https://en.wikipedia.org/wiki/Python_(programming_language)) @@ -191,7 +192,7 @@ Example: Note: A few very specific module commands like MPC230xx, KNX and some Display commands are not supported. These are still available by JSON output. ### Filter data -The huge number of Tasomta configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories. +The huge number of Tasmota configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories. With _decode-config.py_ the following categories are available: `Display`, `Domoticz`, `Internal`, `KNX`, `Led`, `Logging`, `MCP230xx`, `MQTT`, `Main`, `Management`, `Pow`, `Sensor`, `Serial`, `SetOption`, `SonoffRF`, `System`, `Timers`, `Wifi` @@ -266,12 +267,16 @@ For advanced help use `-H` or `--full-help`: -i, --restore-file file to restore configuration from (default: None). - Replacements: @v=firmware version, @f=device friendly - name, @h=device hostname + Replacements: @v=firmware version from config, + @f=device friendly name from config, @h=device + hostname from config, @H=device hostname from device + (-d arg only) -o, --backup-file file to backup configuration to (default: None). - Replacements: @v=firmware version, @f=device friendly - name, @h=device hostname + Replacements: @v=firmware version from config, + @f=device friendly name from config, @h=device + hostname from config, @H=device hostname from device + (-d arg only) -t, --backup-type json|bin|dmp backup filetype (default: 'json') -E, --extension append filetype extension for -i and -o filename @@ -374,3 +379,12 @@ or under windows for device in (sonoff1 sonoff2 sonoff3) do python decode-config.py -c my.conf -d %device -o Config_@f_@v will produce JSON configuration files for host sonoff1, sonoff2 and sonoff3 using friendly name and Tasmota firmware version for backup filenames. + +## Notes +Some general notes: +* Filename replacement macros **@h** and **@H**: + * **@h** +The **@h** replacement macro uses the hostname configured with the Tasomta Wifi `Hostname ` command (defaults to `%s-%04d`). It will not use the network hostname of your device because this is not available when working with files only (e.g. `--file ` as source). +To prevent having a useless % in your filename, **@h** will not replaced by configuration data hostname if this contains '%' characters. + * **@H** +If you want to use the network hostname within your filename, use the **@H** replacement macro instead - but be aware this will only replaced if you are using a network device as source (`-d`, `--device`, `--host`); it will not work when using a file as source (`-f`, `--file`) diff --git a/tools/decode-config.py b/tools/decode-config.py index d6632dbda..a6299f104 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,13 +1,13 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0006' +VER = '2.1.0007' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data Copyright (C) 2018 Norbert Richter - This program is free software: you can redistribute it and/or modfy + 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. @@ -73,12 +73,16 @@ Usage: decode-config.py [-f ] [-d ] [-P ] -i, --restore-file file to restore configuration from (default: None). - Replacements: @v=firmware version, @f=device friendly - name, @h=device hostname + Replacements: @v=firmware version from config, + @f=device friendly name from config, @h=device + hostname from config, @H=device hostname from device + (-d arg only) -o, --backup-file file to backup configuration to (default: None). - Replacements: @v=firmware version, @f=device friendly - name, @h=device hostname + Replacements: @v=firmware version from config, + @f=device friendly name from config, @h=device + hostname from config, @H=device hostname from device + (-d arg only) -t, --backup-type json|bin|dmp backup filetype (default: 'json') -E, --extension append filetype extension for -i and -o filename @@ -461,7 +465,7 @@ Setting_5_10_0 = { 'altitude': ('= 0 and args.device is not None: + device_hostname = GetTasmotaHostname(args.device, args.port, username=args.username, password=args.password) + if device_hostname is None: + device_hostname = '' + + filename = filename.replace('@v', config_version) + filename = filename.replace('@f', config_friendlyname ) + filename = filename.replace('@h', config_hostname ) + filename = filename.replace('@H', device_hostname ) + dirname = basename = ext = '' name = filename @@ -1196,6 +1212,94 @@ def LoadTasmotaConfig(filename): return encode_cfg +def TasmotaGet(cmnd, host, port, username=DEFAULTS['source']['username'], password=None, contenttype = None): + """ + Tasmota http request + + @param host: + hostname or IP of Tasmota device + @param port: + http port of Tasmota device + @param username: + optional username for Tasmota web login + @param password + optional password for Tasmota web login + + @return: + binary config data (encrypted) or None on error + """ + body = None + + # read config direct from device via http + c = pycurl.Curl() + buffer = io.BytesIO() + c.setopt(c.WRITEDATA, buffer) + header = HTTPHeader() + c.setopt(c.HEADERFUNCTION, header.store) + c.setopt(c.FOLLOWLOCATION, True) + c.setopt(c.URL, MakeUrl(host, port, cmnd)) + if username is not None and password is not None: + c.setopt(c.HTTPAUTH, c.HTTPAUTH_BASIC) + c.setopt(c.USERPWD, username + ':' + password) + c.setopt(c.HTTPGET, True) + c.setopt(c.VERBOSE, False) + + responsecode = 200 + try: + c.perform() + responsecode = c.getinfo(c.RESPONSE_CODE) + response = header.response() + except Exception, e: + exit(e[0], e[1],line=inspect.getlineno(inspect.currentframe())) + finally: + c.close() + + if responsecode >= 400: + exit(responsecode, 'HTTP result: {}'.format(header.response()),line=inspect.getlineno(inspect.currentframe())) + elif contenttype is not None and header.contenttype()!=contenttype: + exit(ExitCode.DOWNLOAD_CONFIG_ERROR, "Device did not response properly, may be Tasmota webserver admin mode is disabled (WebServer 2)",line=inspect.getlineno(inspect.currentframe())) + + try: + body = buffer.getvalue() + except: + pass + + return responsecode, body + + +def GetTasmotaHostname(host, port, username=DEFAULTS['source']['username'], password=None): + """ + Get Tasmota hostname from device + + @param host: + hostname or IP of Tasmota device + @param port: + http port of Tasmota device + @param username: + optional username for Tasmota web login + @param password + optional password for Tasmota web login + + @return: + Tasmota real hostname or None on error + """ + hostname = None + + loginstr = "" + if password is not None: + loginstr = "user={}&password={}&".format(urllib2.quote(username), urllib2.quote(password)) + # get hostname + responsecode, body = TasmotaGet("cm?{}cmnd=status%205".format(loginstr), host, port, username=username, password=password) + if body is not None: + jsonbody = json.loads(body) + if "StatusNET" in jsonbody and "Hostname" in jsonbody["StatusNET"]: + hostname = jsonbody["StatusNET"]["Hostname"] + if args.verbose: + message("Hostname for '{}' retrieved: '{}'".format(host, hostname), typ=LogType.INFO) + + return hostname + + def PullTasmotaConfig(host, port, username=DEFAULTS['source']['username'], password=None): """ Pull config from Tasmota device @@ -1212,43 +1316,9 @@ def PullTasmotaConfig(host, port, username=DEFAULTS['source']['username'], passw @return: binary config data (encrypted) or None on error """ + responsecode, body = TasmotaGet('dl', host, port, username, password, contenttype='application/octet-stream') - encode_cfg = None - - # read config direct from device via http - c = pycurl.Curl() - buffer = io.BytesIO() - c.setopt(c.WRITEDATA, buffer) - header = HTTPHeader() - c.setopt(c.HEADERFUNCTION, header.store) - c.setopt(c.FOLLOWLOCATION, True) - c.setopt(c.URL, MakeUrl(host, port, 'dl')) - if username is not None and password is not None: - c.setopt(c.HTTPAUTH, c.HTTPAUTH_BASIC) - c.setopt(c.USERPWD, username + ':' + password) - c.setopt(c.VERBOSE, False) - - responsecode = 200 - try: - c.perform() - responsecode = c.getinfo(c.RESPONSE_CODE) - response = header.response() - except Exception, e: - exit(e[0], e[1],line=inspect.getlineno(inspect.currentframe())) - finally: - c.close() - - if responsecode >= 400: - exit(responsecode, 'HTTP result: {}'.format(header.response()),line=inspect.getlineno(inspect.currentframe())) - elif header.contenttype()!='application/octet-stream': - exit(ExitCode.DOWNLOAD_CONFIG_ERROR, "Device did not response properly, may be Tasmota webserver admin mode is disabled (WebServer 2)",line=inspect.getlineno(inspect.currentframe())) - - try: - encode_cfg = buffer.getvalue() - except: - pass - - return encode_cfg + return body def PushTasmotaConfig(encode_cfg, host, port, username=DEFAULTS['source']['username'], password=None): @@ -1273,40 +1343,21 @@ def PushTasmotaConfig(encode_cfg, host, port, username=DEFAULTS['source']['usern if isinstance(encode_cfg, bytearray): encode_cfg = str(encode_cfg) - c = pycurl.Curl() - buffer = io.BytesIO() - c.setopt(c.WRITEDATA, buffer) - header = HTTPHeader() - c.setopt(c.HEADERFUNCTION, header.store) - c.setopt(c.FOLLOWLOCATION, True) # get restore config page first to set internal Tasmota vars - c.setopt(c.URL, MakeUrl(host, port, 'rs?')) - if args.username is not None and args.password is not None: - c.setopt(c.HTTPAUTH, c.HTTPAUTH_BASIC) - c.setopt(c.USERPWD, args.username + ':' + args.password) - c.setopt(c.HTTPGET, True) - c.setopt(c.VERBOSE, False) - - responsecode = 200 - try: - c.perform() - responsecode = c.getinfo(c.RESPONSE_CODE) - except Exception, e: - c.close() - return e[0], e[1] - - if responsecode >= 400: - c.close() - return responsecode, header.response() - elif header.contenttype() != 'text/html': - c.close() - return ExitCode.UPLOAD_CONFIG_ERROR, "Device did not response properly, may be Tasmota webserver admin mode is disabled (WebServer 2)" + responsecode, body = TasmotaGet('rs?', host, port, username, password, contenttype='text/html') + if body is None: + return responsecode, "ERROR" # post data - header.clear() + c = pycurl.Curl() + header = HTTPHeader() c.setopt(c.HEADERFUNCTION, header.store) + c.setopt(c.WRITEFUNCTION, lambda x: None) c.setopt(c.POST, 1) c.setopt(c.URL, MakeUrl(host, port, 'u2')) + if username is not None and password is not None: + c.setopt(c.HTTPAUTH, c.HTTPAUTH_BASIC) + c.setopt(c.USERPWD, username + ':' + password) try: isfile = os.path.isfile(encode_cfg) except: @@ -2501,12 +2552,12 @@ def ParseArgs(): metavar='', dest='restorefile', default=DEFAULTS['backup']['backupfile'], - help="file to restore configuration from (default: {}). Replacements: @v=firmware version, @f=device friendly name, @h=device hostname".format(DEFAULTS['backup']['restorefile'])) + help="file to restore configuration from (default: {}). Replacements: @v=firmware version from config, @f=device friendly name from config, @h=device hostname from config, @H=device hostname from device (-d arg only)".format(DEFAULTS['backup']['restorefile'])) backup.add_argument('-o', '--backup-file', metavar='', dest='backupfile', default=DEFAULTS['backup']['backupfile'], - help="file to backup configuration to (default: {}). Replacements: @v=firmware version, @f=device friendly name, @h=device hostname".format(DEFAULTS['backup']['backupfile'])) + help="file to backup configuration to (default: {}). Replacements: @v=firmware version from config, @f=device friendly name from config, @h=device hostname from config, @H=device hostname from device (-d arg only)".format(DEFAULTS['backup']['backupfile'])) backup_file_formats = ['json', 'bin', 'dmp'] backup.add_argument('-t', '--backup-type', metavar='|'.join(backup_file_formats), From 4a7e7b0dbbf82b308ed88c6815d06e1fc1cd77d5 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Wed, 14 Nov 2018 15:32:09 +0200 Subject: [PATCH 0486/2222] Change C functions with () to (void) --- sonoff/core_esp8266_timer.c | 10 ++-- sonoff/core_esp8266_wiring_digital.c | 2 +- sonoff/core_esp8266_wiring_pwm.c | 6 +-- sonoff/settings.ino | 50 +++++++++--------- sonoff/sonoff.ino | 28 +++++----- sonoff/support.ino | 60 +++++++++++----------- sonoff/xdrv_01_webserver.ino | 64 +++++++++++------------ sonoff/xdrv_02_mqtt.ino | 38 +++++++------- sonoff/xdrv_03_energy.ino | 18 +++---- sonoff/xdrv_04_light.ino | 36 ++++++------- sonoff/xdrv_05_irremote.ino | 4 +- sonoff/xdrv_06_snfbridge.ino | 18 +++---- sonoff/xdrv_07_domoticz.ino | 16 +++--- sonoff/xdrv_08_serial_bridge.ino | 4 +- sonoff/xdrv_09_timers.ino | 12 ++--- sonoff/xdrv_10_rules.ino | 16 +++--- sonoff/xdrv_11_knx.ino | 12 ++--- sonoff/xdrv_12_home_assistant.ino | 6 +-- sonoff/xdrv_13_display.ino | 36 ++++++------- sonoff/xdrv_16_tuyadimmer.ino | 18 +++---- sonoff/xdrv_17_rcswitch.ino | 6 +-- sonoff/xdrv_95_debug.ino | 8 +-- sonoff/xdrv_interface.ino | 2 +- sonoff/xdsp_01_lcd.ino | 12 ++--- sonoff/xdsp_02_ssd1306.ino | 14 ++--- sonoff/xdsp_03_matrix.ino | 12 ++--- sonoff/xdsp_04_ili9341.ino | 12 ++--- sonoff/xdsp_05_epaper.ino | 14 ++--- sonoff/xdsp_interface.ino | 2 +- sonoff/xnrg_01_hlw8012.ino | 18 +++---- sonoff/xnrg_02_cse7766.ino | 10 ++-- sonoff/xnrg_03_pzem004t.ino | 8 +-- sonoff/xnrg_05_pzem_ac.ino | 6 +-- sonoff/xnrg_06_pzem_dc.ino | 6 +-- sonoff/xplg_wemohue.ino | 32 ++++++------ sonoff/xplg_ws2812.ino | 12 ++--- sonoff/xsns_01_counter.ino | 12 ++--- sonoff/xsns_02_analog.ino | 4 +- sonoff/xsns_04_snfsc.ino | 2 +- sonoff/xsns_05_ds18b20.ino | 12 ++--- sonoff/xsns_05_ds18x20.ino | 14 ++--- sonoff/xsns_05_ds18x20_legacy.ino | 8 +-- sonoff/xsns_06_dht.ino | 6 +-- sonoff/xsns_07_sht1x.ino | 12 ++--- sonoff/xsns_08_htu21.ino | 8 +-- sonoff/xsns_09_bmp.ino | 6 +-- sonoff/xsns_10_bh1750.ino | 6 +-- sonoff/xsns_12_ads1115.ino | 2 +- sonoff/xsns_12_ads1115_i2cdev.ino | 2 +- sonoff/xsns_13_ina219.ino | 14 ++--- sonoff/xsns_14_sht3x.ino | 2 +- sonoff/xsns_15_mhz19.ino | 6 +-- sonoff/xsns_16_tsl2561.ino | 6 +-- sonoff/xsns_17_senseair.ino | 4 +- sonoff/xsns_18_pms5003.ino | 6 +-- sonoff/xsns_19_mgs.ino | 4 +- sonoff/xsns_20_novasds.ino | 8 +-- sonoff/xsns_21_sgp30.ino | 2 +- sonoff/xsns_22_sr04.ino | 2 +- sonoff/xsns_23_sdm120.ino | 6 +-- sonoff/xsns_24_si1145.ino | 16 +++--- sonoff/xsns_25_sdm630.ino | 6 +-- sonoff/xsns_27_apds9960.ino | 76 ++++++++++++++-------------- sonoff/xsns_28_tm1638.ino | 10 ++-- sonoff/xsns_31_ccs811.ino | 2 +- sonoff/xsns_32_mpu6050.ino | 4 +- sonoff/xsns_33_ds3231.ino | 4 +- sonoff/xsns_34_hx711.ino | 14 ++--- sonoff/xsns_35_tx20.ino | 6 +-- sonoff/xsns_interface.ino | 2 +- 70 files changed, 461 insertions(+), 461 deletions(-) diff --git a/sonoff/core_esp8266_timer.c b/sonoff/core_esp8266_timer.c index 478471a36..fdc7342e5 100644 --- a/sonoff/core_esp8266_timer.c +++ b/sonoff/core_esp8266_timer.c @@ -46,7 +46,7 @@ void ICACHE_RAM_ATTR timer1_isr_handler(void *para){ } } -void ICACHE_RAM_ATTR timer1_isr_init(){ +void ICACHE_RAM_ATTR timer1_isr_init(void){ ETS_FRC_TIMER1_INTR_ATTACH(timer1_isr_handler, NULL); } @@ -55,7 +55,7 @@ void timer1_attachInterrupt(timercallback userFunc) { ETS_FRC1_INTR_ENABLE(); } -void ICACHE_RAM_ATTR timer1_detachInterrupt() { +void ICACHE_RAM_ATTR timer1_detachInterrupt(void) { timer1_user_cb = 0; TEIE &= ~TEIE1;//edge int disable ETS_FRC1_INTR_DISABLE(); @@ -71,7 +71,7 @@ void ICACHE_RAM_ATTR timer1_write(uint32_t ticks){ if ((T1C & (1 << TCIT)) == 0) TEIE |= TEIE1;//edge int enable } -void ICACHE_RAM_ATTR timer1_disable(){ +void ICACHE_RAM_ATTR timer1_disable(void){ T1C = 0; T1I = 0; } @@ -92,7 +92,7 @@ void ICACHE_RAM_ATTR timer0_isr_handler(void* para){ } } -void timer0_isr_init(){ +void timer0_isr_init(void){ ETS_CCOMPARE0_INTR_ATTACH(timer0_isr_handler, NULL); } @@ -101,7 +101,7 @@ void timer0_attachInterrupt(timercallback userFunc) { ETS_CCOMPARE0_ENABLE(); } -void ICACHE_RAM_ATTR timer0_detachInterrupt() { +void ICACHE_RAM_ATTR timer0_detachInterrupt(void) { timer0_user_cb = NULL; ETS_CCOMPARE0_DISABLE(); } diff --git a/sonoff/core_esp8266_wiring_digital.c b/sonoff/core_esp8266_wiring_digital.c index 06323c1ce..b51a85aad 100644 --- a/sonoff/core_esp8266_wiring_digital.c +++ b/sonoff/core_esp8266_wiring_digital.c @@ -188,7 +188,7 @@ extern void ICACHE_RAM_ATTR __detachInterrupt(uint8_t pin) { } } -void initPins() { +void initPins(void) { //Disable UART interrupts system_set_os_print(0); U0IE = 0; diff --git a/sonoff/core_esp8266_wiring_pwm.c b/sonoff/core_esp8266_wiring_pwm.c index 0ef8cb67f..92d73a4b7 100644 --- a/sonoff/core_esp8266_wiring_pwm.c +++ b/sonoff/core_esp8266_wiring_pwm.c @@ -84,7 +84,7 @@ uint32_t pwm_get_mask(uint16_t value) return mask; } -void prep_pwm_steps() +void prep_pwm_steps(void) { if(pwm_mask == 0) { return; @@ -123,7 +123,7 @@ void prep_pwm_steps() pwm_steps_changed = 1; } -void ICACHE_RAM_ATTR pwm_timer_isr() //103-138 +void ICACHE_RAM_ATTR pwm_timer_isr(void) //103-138 { struct pwm_isr_table *table = &(_pwm_isr_data.tables[_pwm_isr_data.active]); static uint8_t current_step = 0; @@ -160,7 +160,7 @@ void ICACHE_RAM_ATTR pwm_timer_isr() //103-138 TEIE |= TEIE1;//13 } -void pwm_start_timer() +void pwm_start_timer(void) { timer1_disable(); ETS_FRC_TIMER1_INTR_ATTACH(NULL, NULL); diff --git a/sonoff/settings.ino b/sonoff/settings.ino index a38e2113e..38e9bb3f3 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -69,7 +69,7 @@ uint32_t rtc_settings_crc = 0; -uint32_t GetRtcSettingsCrc() +uint32_t GetRtcSettingsCrc(void) { uint32_t crc = 0; uint8_t *bytes = (uint8_t*)&RtcSettings; @@ -80,7 +80,7 @@ uint32_t GetRtcSettingsCrc() return crc; } -void RtcSettingsSave() +void RtcSettingsSave(void) { if (GetRtcSettingsCrc() != rtc_settings_crc) { RtcSettings.valid = RTC_MEM_VALID; @@ -89,7 +89,7 @@ void RtcSettingsSave() } } -void RtcSettingsLoad() +void RtcSettingsLoad(void) { ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); // 0x290 if (RtcSettings.valid != RTC_MEM_VALID) { @@ -106,7 +106,7 @@ void RtcSettingsLoad() rtc_settings_crc = GetRtcSettingsCrc(); } -boolean RtcSettingsValid() +boolean RtcSettingsValid(void) { return (RTC_MEM_VALID == RtcSettings.valid); } @@ -115,7 +115,7 @@ boolean RtcSettingsValid() uint32_t rtc_reboot_crc = 0; -uint32_t GetRtcRebootCrc() +uint32_t GetRtcRebootCrc(void) { uint32_t crc = 0; uint8_t *bytes = (uint8_t*)&RtcReboot; @@ -126,7 +126,7 @@ uint32_t GetRtcRebootCrc() return crc; } -void RtcRebootSave() +void RtcRebootSave(void) { if (GetRtcRebootCrc() != rtc_reboot_crc) { RtcReboot.valid = RTC_MEM_VALID; @@ -135,7 +135,7 @@ void RtcRebootSave() } } -void RtcRebootLoad() +void RtcRebootLoad(void) { ESP.rtcUserMemoryRead(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); // 0x280 if (RtcReboot.valid != RTC_MEM_VALID) { @@ -147,7 +147,7 @@ void RtcRebootLoad() rtc_reboot_crc = GetRtcRebootCrc(); } -boolean RtcRebootValid() +boolean RtcRebootValid(void) { return (RTC_MEM_VALID == RtcReboot.valid); } @@ -179,7 +179,7 @@ uint8_t *settings_buffer = NULL; /* * Based on cores/esp8266/Updater.cpp */ -void SetFlashModeDout() +void SetFlashModeDout(void) { uint8_t *_buffer; uint32_t address; @@ -198,7 +198,7 @@ void SetFlashModeDout() delete[] _buffer; } -void SettingsBufferFree() +void SettingsBufferFree(void) { if (settings_buffer != NULL) { free(settings_buffer); @@ -206,7 +206,7 @@ void SettingsBufferFree() } } -bool SettingsBufferAlloc() +bool SettingsBufferAlloc(void) { SettingsBufferFree(); if (!(settings_buffer = (uint8_t *)malloc(sizeof(Settings)))) { @@ -216,7 +216,7 @@ bool SettingsBufferAlloc() return true; } -uint16_t GetSettingsCrc() +uint16_t GetSettingsCrc(void) { uint16_t crc = 0; uint8_t *bytes = (uint8_t*)&Settings; @@ -227,7 +227,7 @@ uint16_t GetSettingsCrc() return crc; } -void SettingsSaveAll() +void SettingsSaveAll(void) { if (Settings.flag.save_state) { Settings.power = power; @@ -242,7 +242,7 @@ void SettingsSaveAll() * Config Save - Save parameters to Flash ONLY if any parameter has changed \*********************************************************************************************/ -uint32_t GetSettingsAddress() +uint32_t GetSettingsAddress(void) { return settings_location * SPI_FLASH_SEC_SIZE; } @@ -294,7 +294,7 @@ void SettingsSave(byte rotate) RtcSettingsSave(); } -void SettingsLoad() +void SettingsLoad(void) { /* Load configuration from eeprom or one of 7 slots below if first load does not stop_flash_rotate */ @@ -377,7 +377,7 @@ bool SettingsEraseConfig(void) { return true; } -void SettingsSdkErase() +void SettingsSdkErase(void) { WiFi.disconnect(true); // Delete SDK wifi config SettingsErase(1); @@ -387,7 +387,7 @@ void SettingsSdkErase() /********************************************************************************************/ -void SettingsDefault() +void SettingsDefault(void) { AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_USE_DEFAULTS)); SettingsDefaultSet1(); @@ -395,7 +395,7 @@ void SettingsDefault() SettingsSave(2); } -void SettingsDefaultSet1() +void SettingsDefaultSet1(void) { memset(&Settings, 0x00, sizeof(SYSCFG)); @@ -407,7 +407,7 @@ void SettingsDefaultSet1() // Settings.cfg_crc = 0; } -void SettingsDefaultSet2() +void SettingsDefaultSet2(void) { memset((char*)&Settings +16, 0x00, sizeof(SYSCFG) -16); @@ -641,7 +641,7 @@ void SettingsDefaultSet2() /********************************************************************************************/ -void SettingsDefaultSet_5_8_1() +void SettingsDefaultSet_5_8_1(void) { // Settings.flag.ws_clock_reverse = 0; Settings.ws_width[WS_SECOND] = 1; @@ -658,7 +658,7 @@ void SettingsDefaultSet_5_8_1() Settings.ws_color[WS_HOUR][WS_BLUE] = 0; } -void SettingsDefaultSet_5_10_1() +void SettingsDefaultSet_5_10_1(void) { Settings.display_model = 0; Settings.display_mode = 1; @@ -680,7 +680,7 @@ void SettingsDefaultSet_5_10_1() Settings.display_address[7] = MTX_ADDRESS8; } -void SettingsResetStd() +void SettingsResetStd(void) { Settings.tflag[0].hemis = TIME_STD_HEMISPHERE; Settings.tflag[0].week = TIME_STD_WEEK; @@ -690,7 +690,7 @@ void SettingsResetStd() Settings.toffset[0] = TIME_STD_OFFSET; } -void SettingsResetDst() +void SettingsResetDst(void) { Settings.tflag[1].hemis = TIME_DST_HEMISPHERE; Settings.tflag[1].week = TIME_DST_WEEK; @@ -700,7 +700,7 @@ void SettingsResetDst() Settings.toffset[1] = TIME_DST_OFFSET; } -void SettingsDefaultSet_5_13_1c() +void SettingsDefaultSet_5_13_1c(void) { SettingsResetStd(); SettingsResetDst(); @@ -708,7 +708,7 @@ void SettingsDefaultSet_5_13_1c() /********************************************************************************************/ -void SettingsDelta() +void SettingsDelta(void) { if (Settings.version != VERSION) { // Fix version dependent changes diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 0c7b16beb..ddf73a3c8 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -378,7 +378,7 @@ void SetLedPower(uint8_t state) digitalWrite(pin[GPIO_LED1], (bitRead(led_inverted, 0)) ? !state : state); } -uint8_t GetFanspeed() +uint8_t GetFanspeed(void) { uint8_t fanspeed = 0; @@ -1426,7 +1426,7 @@ void ExecuteCommandPower(byte device, byte state, int source) if (publish_power) MqttPublishPowerState(device); } -void StopAllPowerBlink() +void StopAllPowerBlink(void) { power_t mask; @@ -1571,7 +1571,7 @@ void PublishStatus(uint8_t payload) } -void MqttShowPWMState() +void MqttShowPWMState(void) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_PWM "\":{"), mqtt_data); bool first = true; @@ -1584,7 +1584,7 @@ void MqttShowPWMState() snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } -void MqttShowState() +void MqttShowState(void) { char stemp1[33]; @@ -1615,7 +1615,7 @@ void MqttShowState() mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI())); } -boolean MqttShowSensor() +boolean MqttShowSensor(void) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\""), mqtt_data, GetDateAndTime(DT_LOCAL).c_str()); int json_data_start = strlen(mqtt_data); @@ -1645,7 +1645,7 @@ boolean MqttShowSensor() /********************************************************************************************/ -void PerformEverySecond() +void PerformEverySecond(void) { uptime++; @@ -1718,7 +1718,7 @@ void PerformEverySecond() * Button handler with single press only or multi-press and hold on all buttons \*********************************************************************************************/ -void ButtonHandler() +void ButtonHandler(void) { uint8_t button = NOT_PRESSED; uint8_t button_present = 0; @@ -1956,7 +1956,7 @@ void SwitchHandler(byte mode) * Every 0.1 second \*-------------------------------------------------------------------------------------------*/ -void Every100mSeconds() +void Every100mSeconds(void) { // As the max amount of sleep = 250 mSec this loop will shift in time... power_t power_now; @@ -2005,7 +2005,7 @@ void Every100mSeconds() * Every 0.25 second \*-------------------------------------------------------------------------------------------*/ -void Every250mSeconds() +void Every250mSeconds(void) { // As the max amount of sleep = 250 mSec this loop should always be taken... @@ -2201,7 +2201,7 @@ void Every250mSeconds() bool arduino_ota_triggered = false; uint16_t arduino_ota_progress_dot_count = 0; -void ArduinoOTAInit() +void ArduinoOTAInit(void) { ArduinoOTA.setPort(8266); ArduinoOTA.setHostname(Settings.hostname); @@ -2270,7 +2270,7 @@ void ArduinoOTAInit() /********************************************************************************************/ -void SerialInput() +void SerialInput(void) { while (Serial.available()) { yield(); @@ -2398,7 +2398,7 @@ void GpioSwitchPinMode(uint8_t index) } } -void GpioInit() +void GpioInit(void) { uint8_t mpin; uint8_t key_no_pullup = 0; @@ -2599,7 +2599,7 @@ extern "C" { extern struct rst_info resetInfo; } -void setup() +void setup(void) { byte idx; @@ -2751,7 +2751,7 @@ void setup() XsnsCall(FUNC_INIT); } -void loop() +void loop(void) { XdrvCall(FUNC_LOOP); diff --git a/sonoff/support.ino b/sonoff/support.ino index 7df675b13..a27e08866 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -39,7 +39,7 @@ byte oswatch_blocked_loop = 0; bool knx_started = false; #endif // USE_KNX -void OsWatchTicker() +void OsWatchTicker(void) { unsigned long t = millis(); unsigned long last_run = abs(t - oswatch_last_loop_time); @@ -57,7 +57,7 @@ void OsWatchTicker() } } -void OsWatchInit() +void OsWatchInit(void) { oswatch_blocked_loop = RtcSettings.oswatch_blocked_loop; RtcSettings.oswatch_blocked_loop = 0; @@ -65,13 +65,13 @@ void OsWatchInit() tickerOSWatch.attach_ms(((OSWATCH_RESET_TIME / 3) * 1000), OsWatchTicker); } -void OsWatchLoop() +void OsWatchLoop(void) { oswatch_last_loop_time = millis(); // while(1) delay(1000); // this will trigger the os watch } -String GetResetReason() +String GetResetReason(void) { char buff[32]; if (oswatch_blocked_loop) { @@ -82,7 +82,7 @@ String GetResetReason() } } -boolean OsWatchBlockedLoop() +boolean OsWatchBlockedLoop(void) { return oswatch_blocked_loop; } @@ -470,7 +470,7 @@ float ConvertTemp(float c) return result; } -char TempUnit() +char TempUnit(void) { return (Settings.flag.temperature_conversion) ? 'F' : 'C'; } @@ -485,7 +485,7 @@ float ConvertPressure(float p) return result; } -String PressureUnit() +String PressureUnit(void) { return (Settings.flag.pressure_conversion) ? String(D_UNIT_MILLIMETER_MERCURY) : String(D_UNIT_PRESSURE); } @@ -497,7 +497,7 @@ void SetGlobalValues(float temperature, float humidity) global_humidity = humidity; } -void ResetGlobalValues() +void ResetGlobalValues(void) { if ((uptime - global_update) > GLOBAL_VALUES_VALID) { // Reset after 5 minutes global_update = 0; @@ -712,7 +712,7 @@ void SetSerialBaudrate(int baudrate) } } -void ClaimSerial() +void ClaimSerial(void) { serial_local = 1; AddLog_P(LOG_LEVEL_INFO, PSTR("SNS: Hardware Serial")); @@ -765,7 +765,7 @@ uint8_t ValidGPIO(uint8_t pin, uint8_t gpio) return result; } -void AppDelay() +void AppDelay(void) { if (APP_BAUDRATE == baudrate) { // When baudrate too low it will fail on Sonoff Pow R2 and S31 serial interface initialization if (global_state.wifi_down) { @@ -841,7 +841,7 @@ void SetNextTimeInterval(unsigned long& timer, const unsigned long step) * Fill feature list \*********************************************************************************************/ -void GetFeatures() +void GetFeatures(void) { feature_drv1 = 0x00000000; // xdrv_01_mqtt.ino, xdrv_01_light.ino, xdrv_04_snfbridge.ino @@ -1206,7 +1206,7 @@ int WifiGetRssiAsQuality(int rssi) return quality; } -boolean WifiConfigCounter() +boolean WifiConfigCounter(void) { if (wifi_config_counter) { wifi_config_counter = WIFI_CONFIG_SEC; @@ -1310,7 +1310,7 @@ void WifiConfig(uint8_t type) } } -void WiFiSetSleepMode() +void WiFiSetSleepMode(void) { /* Excerpt from the esp8266 non os sdk api reference (v2.2.1): * Sets sleep type for power saving. Set WIFI_NONE_SLEEP to disable power saving. @@ -1387,7 +1387,7 @@ void WifiSetState(uint8_t state) global_state.wifi_down = state ^1; } -void WifiCheckIp() +void WifiCheckIp(void) { if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { WifiSetState(1); @@ -1574,7 +1574,7 @@ void WifiCheck(uint8_t param) } } -int WifiState() +int WifiState(void) { int state = -1; @@ -1583,7 +1583,7 @@ int WifiState() return state; } -void WifiConnect() +void WifiConnect(void) { WifiSetState(0); WiFi.persistent(false); // Solve possible wifi init errors @@ -1595,7 +1595,7 @@ void WifiConnect() // Enable from 6.0.0a until 6.1.0a - disabled due to possible cause of bad wifi connect on core 2.3.0 // Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset -void WifiDisconnect() +void WifiDisconnect(void) { // Courtesy of EspEasy WiFi.persistent(true); // use SDK storage of SSID/WPA parameters @@ -1605,7 +1605,7 @@ void WifiDisconnect() WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters } -void EspRestart() +void EspRestart(void) { delay(100); // Allow time for message xfer - disabled v6.1.0b WifiDisconnect(); @@ -1614,7 +1614,7 @@ void EspRestart() } /* -void EspRestart() +void EspRestart(void) { ESP.restart(); } @@ -1863,7 +1863,7 @@ int32_t time_timezone = 0; uint8_t midnight_now = 0; uint8_t ntp_sync_minute = 0; -String GetBuildDateAndTime() +String GetBuildDateAndTime(void) { // "2017-03-07T11:08:02" - ISO8601:2004 char bdt[21]; @@ -1892,7 +1892,7 @@ String GetBuildDateAndTime() return String(bdt); // 2017-03-07T11:08:02 } -String GetTimeZone() +String GetTimeZone(void) { char tz[7]; @@ -1966,7 +1966,7 @@ String GetTime(int type) return String(stime); // Thu Nov 01 11:41:02 2018 } -String GetUptime() +String GetUptime(void) { char dt[16]; @@ -1988,7 +1988,7 @@ String GetUptime() return String(dt); // 128T14:35:44 } -uint32_t GetMinutesUptime() +uint32_t GetMinutesUptime(void) { TIME_T ut; @@ -2001,7 +2001,7 @@ uint32_t GetMinutesUptime() return (ut.days *1440) + (ut.hour *60) + ut.minute; } -uint32_t GetMinutesPastMidnight() +uint32_t GetMinutesPastMidnight(void) { uint32_t minutes = 0; @@ -2133,24 +2133,24 @@ uint32_t RuleToTime(TimeRule r, int yr) return t; } -uint32_t LocalTime() +uint32_t LocalTime(void) { return local_time; } -uint32_t Midnight() +uint32_t Midnight(void) { return midnight; } -boolean MidnightNow() +boolean MidnightNow(void) { boolean mnflg = midnight_now; if (mnflg) midnight_now = 0; return mnflg; } -void RtcSecond() +void RtcSecond(void) { TIME_T tmpTime; @@ -2218,7 +2218,7 @@ void RtcSecond() RtcTime.year += 1970; } -void RtcInit() +void RtcInit(void) { sntp_setservername(0, Settings.ntp_server[0]); sntp_setservername(1, Settings.ntp_server[1]); @@ -2273,7 +2273,7 @@ void GetLog(byte idx, char** entry_pp, size_t* len_p) } #endif // USE_WEBSERVER -void Syslog() +void Syslog(void) { // Destroys log_data char syslog_preamble[64]; // Hostname + Id diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 25c4c013b..2c3f85d5e 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -408,7 +408,7 @@ void StartWebserver(int type, IPAddress ipweb) if (type) { webserver_state = type; } } -void StopWebserver() +void StopWebserver(void) { if (webserver_state) { WebServer->close(); @@ -417,7 +417,7 @@ void StopWebserver() } } -void WifiManagerBegin() +void WifiManagerBegin(void) { // setup AP if (!global_state.wifi_down) { @@ -440,7 +440,7 @@ void WifiManagerBegin() StartWebserver(HTTP_MANAGER, WiFi.softAPIP()); } -void PollDnsWebserver() +void PollDnsWebserver(void) { if (DnsServer) { DnsServer->processNextRequest(); } if (WebServer) { WebServer->handleClient(); } @@ -448,7 +448,7 @@ void PollDnsWebserver() /*********************************************************************************************/ -void SetHeader() +void SetHeader(void) { WebServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate")); WebServer->sendHeader(F("Pragma"), F("no-cache")); @@ -555,7 +555,7 @@ void WebRestart(uint8_t type) /*********************************************************************************************/ -void HandleWifiLogin() +void HandleWifiLogin(void) { String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR( D_CONFIGURE_WIFI )); @@ -564,7 +564,7 @@ void HandleWifiLogin() ShowPage(page, false); // false means show page no matter if the client has or has not credentials } -void HandleRoot() +void HandleRoot(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_MAIN_MENU); @@ -663,7 +663,7 @@ void HandleRoot() } } -void HandleAjaxStatusRefresh() +void HandleAjaxStatusRefresh(void) { if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -733,7 +733,7 @@ void HandleAjaxStatusRefresh() WebServer->send(200, FPSTR(HDR_CTYPE_HTML), mqtt_data); } -boolean HttpUser() +boolean HttpUser(void) { boolean status = (HTTP_USER == webserver_state); if (status) { HandleRoot(); } @@ -744,7 +744,7 @@ boolean HttpUser() #ifndef BE_MINIMAL -void HandleConfiguration() +void HandleConfiguration(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -767,7 +767,7 @@ void HandleConfiguration() /*-------------------------------------------------------------------------------------------*/ -void HandleModuleConfiguration() +void HandleModuleConfiguration(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -836,7 +836,7 @@ void HandleModuleConfiguration() ShowPage(page); } -void ModuleSaveSettings() +void ModuleSaveSettings(void) { char tmp[100]; char stemp[TOPSZ]; @@ -878,7 +878,7 @@ String htmlEscape(String s) return s; } -void HandleWifiConfiguration() +void HandleWifiConfiguration(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -982,7 +982,7 @@ void HandleWifiConfiguration() ShowPage(page, !(HTTP_MANAGER == webserver_state)); } -void WifiSaveSettings() +void WifiSaveSettings(void) { char tmp[100]; @@ -1006,7 +1006,7 @@ void WifiSaveSettings() /*-------------------------------------------------------------------------------------------*/ -void HandleLoggingConfiguration() +void HandleLoggingConfiguration(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -1061,7 +1061,7 @@ void HandleLoggingConfiguration() ShowPage(page); } -void LoggingSaveSettings() +void LoggingSaveSettings(void) { char tmp[100]; @@ -1089,7 +1089,7 @@ void LoggingSaveSettings() /*-------------------------------------------------------------------------------------------*/ -void HandleOtherConfiguration() +void HandleOtherConfiguration(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -1134,7 +1134,7 @@ void HandleOtherConfiguration() ShowPage(page); } -void OtherSaveSettings() +void OtherSaveSettings(void) { char tmp[100]; char stemp[TOPSZ]; @@ -1160,7 +1160,7 @@ void OtherSaveSettings() /*-------------------------------------------------------------------------------------------*/ -void HandleBackupConfiguration() +void HandleBackupConfiguration(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -1204,7 +1204,7 @@ void HandleBackupConfiguration() /*-------------------------------------------------------------------------------------------*/ -void HandleResetConfiguration() +void HandleResetConfiguration(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -1225,7 +1225,7 @@ void HandleResetConfiguration() ExecuteWebCommand(svalue, SRC_WEBGUI); } -void HandleRestoreConfiguration() +void HandleRestoreConfiguration(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -1246,7 +1246,7 @@ void HandleRestoreConfiguration() /*-------------------------------------------------------------------------------------------*/ -void HandleInformation() +void HandleInformation(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -1367,7 +1367,7 @@ void HandleInformation() /*-------------------------------------------------------------------------------------------*/ -void HandleUpgradeFirmware() +void HandleUpgradeFirmware(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -1387,7 +1387,7 @@ void HandleUpgradeFirmware() upload_file_type = UPL_TASMOTA; } -void HandleUpgradeFirmwareStart() +void HandleUpgradeFirmwareStart(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -1416,7 +1416,7 @@ void HandleUpgradeFirmwareStart() ExecuteWebCommand(svalue, SRC_WEBGUI); } -void HandleUploadDone() +void HandleUploadDone(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -1470,7 +1470,7 @@ void HandleUploadDone() ShowPage(page); } -void HandleUploadLoop() +void HandleUploadLoop(void) { // Based on ESP8266HTTPUpdateServer.cpp uses ESP8266WebServer Parsing.cpp and Cores Updater.cpp (Update) boolean _serialoutput = (LOG_LEVEL_DEBUG <= seriallog_level); @@ -1664,7 +1664,7 @@ void HandleUploadLoop() /*-------------------------------------------------------------------------------------------*/ -void HandlePreflightRequest() +void HandlePreflightRequest(void) { WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); WebServer->sendHeader(F("Access-Control-Allow-Methods"), F("GET, POST")); @@ -1674,7 +1674,7 @@ void HandlePreflightRequest() /*-------------------------------------------------------------------------------------------*/ -void HandleHttpCommand() +void HandleHttpCommand(void) { if (HttpUser()) { return; } // if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -1734,7 +1734,7 @@ void HandleHttpCommand() /*-------------------------------------------------------------------------------------------*/ -void HandleConsole() +void HandleConsole(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -1750,7 +1750,7 @@ void HandleConsole() ShowPage(page); } -void HandleAjaxConsoleRefresh() +void HandleAjaxConsoleRefresh(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -1809,7 +1809,7 @@ void HandleAjaxConsoleRefresh() /********************************************************************************************/ -void HandleNotFound() +void HandleNotFound(void) { // snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_HTTP "Not fount (%s)"), WebServer->uri().c_str()); // AddLog(LOG_LEVEL_DEBUG); @@ -1834,7 +1834,7 @@ void HandleNotFound() } /* 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(void) { if ((HTTP_MANAGER == webserver_state) && !ValidIpAddress(WebServer->hostHeader())) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); @@ -1990,7 +1990,7 @@ enum WebCommands { CMND_WEBSERVER, CMND_WEBPASSWORD, CMND_WEBLOG, CMND_WEBREFRES const char kWebCommands[] PROGMEM = D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_EMULATION ; const char kWebSendStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND ; -bool WebCommand() +bool WebCommand(void) { char command[CMDSZ]; bool serviced = true; diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index b74577a75..2da603a99 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -89,12 +89,12 @@ bool mqtt_connected = false; // MQTT virtual connection status PubSubClient MqttClient(EspClient); -bool MqttIsConnected() +bool MqttIsConnected(void) { return MqttClient.connected(); } -void MqttDisconnect() +void MqttDisconnect(void) { MqttClient.disconnect(); } @@ -112,7 +112,7 @@ bool MqttPublishLib(const char* topic, boolean retained) return result; } -void MqttLoop() +void MqttLoop(void) { MqttClient.loop(); } @@ -122,17 +122,17 @@ void MqttLoop() #include TasmotaMqtt MqttClient; -bool MqttIsConnected() +bool MqttIsConnected(void) { return MqttClient.Connected(); } -void MqttDisconnect() +void MqttDisconnect(void) { MqttClient.Disconnect(); } -void MqttDisconnectedCb() +void MqttDisconnectedCb(void) { MqttDisconnected(MqttClient.State()); // status codes are documented in file mqtt.h as tConnState } @@ -147,7 +147,7 @@ bool MqttPublishLib(const char* topic, boolean retained) return MqttClient.Publish(topic, mqtt_data, strlen(mqtt_data), 0, retained); } -void MqttLoop() +void MqttLoop(void) { } @@ -156,12 +156,12 @@ void MqttLoop() #include MQTTClient MqttClient(MQTT_MAX_PACKET_SIZE); -bool MqttIsConnected() +bool MqttIsConnected(void) { return MqttClient.connected(); } -void MqttDisconnect() +void MqttDisconnect(void) { MqttClient.disconnect(); } @@ -189,7 +189,7 @@ bool MqttPublishLib(const char* topic, boolean retained) return MqttClient.publish(topic, mqtt_data, strlen(mqtt_data), retained, 0); } -void MqttLoop() +void MqttLoop(void) { MqttClient.loop(); // delay(10); @@ -201,7 +201,7 @@ void MqttLoop() #ifdef USE_DISCOVERY #ifdef MQTT_HOST_DISCOVERY -boolean MqttDiscoverServer() +boolean MqttDiscoverServer(void) { if (!mdns_begun) { return false; } @@ -225,7 +225,7 @@ boolean MqttDiscoverServer() #endif // MQTT_HOST_DISCOVERY #endif // USE_DISCOVERY -int MqttLibraryType() +int MqttLibraryType(void) { return (int)MQTT_LIBRARY_TYPE; } @@ -372,7 +372,7 @@ void MqttDisconnected(int state) rules_flag.mqtt_disconnected = 1; } -void MqttConnected() +void MqttConnected(void) { char stopic[TOPSZ]; @@ -434,7 +434,7 @@ void MqttConnected() } #ifdef USE_MQTT_TLS -boolean MqttCheckTls() +boolean MqttCheckTls(void) { char fingerprint1[60]; char fingerprint2[60]; @@ -474,7 +474,7 @@ boolean MqttCheckTls() } #endif // USE_MQTT_TLS -void MqttReconnect() +void MqttReconnect(void) { char stopic[TOPSZ]; @@ -559,7 +559,7 @@ void MqttReconnect() #endif // MQTT_LIBRARY_TYPE } -void MqttCheck() +void MqttCheck(void) { if (Settings.flag.mqtt_enabled) { if (!MqttIsConnected()) { @@ -587,7 +587,7 @@ void MqttCheck() /*********************************************************************************************/ -bool MqttCommand() +bool MqttCommand(void) { char command [CMDSZ]; bool serviced = true; @@ -841,7 +841,7 @@ const char HTTP_FORM_MQTT[] PROGMEM = "
          " D_TOPIC " = %topic% (" MQTT_TOPIC ")

          " "
          " D_FULL_TOPIC " (" MQTT_FULLTOPIC ")

          "; -void HandleMqttConfiguration() +void HandleMqttConfiguration(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -873,7 +873,7 @@ void HandleMqttConfiguration() ShowPage(page); } -void MqttSaveSettings() +void MqttSaveSettings(void) { char tmp[100]; char stemp[TOPSZ]; diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 93bae4078..9486a577f 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -87,7 +87,7 @@ Ticker ticker_energy; int energy_command_code = 0; /********************************************************************************************/ -void EnergyUpdateToday() +void EnergyUpdateToday(void) { if (energy_kWhtoday_delta > 1000) { unsigned long delta = energy_kWhtoday_delta / 1000; @@ -101,7 +101,7 @@ void EnergyUpdateToday() /*********************************************************************************************/ -void Energy200ms() +void Energy200ms(void) { energy_power_on = (power != 0) | Settings.flag.no_power_on_check; @@ -131,7 +131,7 @@ void Energy200ms() XnrgCall(FUNC_EVERY_200_MSECOND); } -void EnergySaveState() +void EnergySaveState(void) { Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; Settings.energy_kWhtoday = energy_kWhtoday; @@ -154,12 +154,12 @@ boolean EnergyMargin(byte type, uint16_t margin, uint16_t value, byte &flag, byt return (change != save_flag); } -void EnergySetPowerSteadyCounter() +void EnergySetPowerSteadyCounter(void) { energy_power_steady_cntr = 2; } -void EnergyMarginCheck() +void EnergyMarginCheck(void) { uint16_t energy_daily_u = 0; uint16_t energy_power_u = 0; @@ -296,7 +296,7 @@ void EnergyMarginCheck() if (energy_power_delta) EnergyMqttShow(); } -void EnergyMqttShow() +void EnergyMqttShow(void) { // {"Time":"2017-12-16T11:48:55","ENERGY":{"Total":0.212,"Yesterday":0.000,"Today":0.014,"Period":2.0,"Power":22.0,"Factor":1.00,"Voltage":213.6,"Current":0.100}} snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); @@ -313,7 +313,7 @@ void EnergyMqttShow() * Commands \*********************************************************************************************/ -boolean EnergyCommand() +boolean EnergyCommand(void) { char command [CMDSZ]; char sunit[CMDSZ]; @@ -506,13 +506,13 @@ boolean EnergyCommand() return serviced; } -void EnergyDrvInit() +void EnergyDrvInit(void) { energy_flg = ENERGY_NONE; XnrgCall(FUNC_PRE_INIT); } -void EnergySnsInit() +void EnergySnsInit(void) { XnrgCall(FUNC_INIT); diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 9bd88e2cb..ae632b912 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -146,11 +146,11 @@ uint8_t arilux_rf_toggle = 0; #ifndef ARDUINO_ESP8266_RELEASE_2_3_0 #ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves RF misses -void AriluxRfInterrupt() ICACHE_RAM_ATTR; // As iram is tight and it works this way too +void AriluxRfInterrupt(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too #endif // USE_WS2812_DMA #endif // ARDUINO_ESP8266_RELEASE_2_3_0 -void AriluxRfInterrupt() +void AriluxRfInterrupt(void) { unsigned long time = micros(); unsigned int duration = time - arilux_rf_lasttime; @@ -184,7 +184,7 @@ void AriluxRfInterrupt() arilux_rf_lasttime = time; } -void AriluxRfHandler() +void AriluxRfHandler(void) { unsigned long now = millis(); if (arilux_rf_received_value && !((arilux_rf_received_value == arilux_rf_last_received_value) && (now - arilux_rf_last_time < ARILUX_RF_TIME_AVOID_DUPLICATE))) { @@ -245,7 +245,7 @@ void AriluxRfHandler() arilux_rf_received_value = 0; } -void AriluxRfInit() +void AriluxRfInit(void) { if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_LED2] < 99)) { if (Settings.last_module != Settings.module) { @@ -259,7 +259,7 @@ void AriluxRfInit() } } -void AriluxRfDisable() +void AriluxRfDisable(void) { if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_LED2] < 99)) { detachInterrupt(pin[GPIO_ARIRFRCV]); @@ -309,7 +309,7 @@ void LightMy92x1Write(uint8_t data) } } -void LightMy92x1Init() +void LightMy92x1Init(void) { uint8_t chips = light_type -11; // 1 (AiLight) or 2 (Sonoff B1) @@ -347,7 +347,7 @@ void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t dut /********************************************************************************************/ -void LightInit() +void LightInit(void) { uint8_t max_scheme = LS_MAX -1; @@ -449,7 +449,7 @@ void LightSetColorTemp(uint16_t ct) } } -uint16_t LightGetColorTemp() +uint16_t LightGetColorTemp(void) { uint8_t ct_idx = 0; if (LST_RGBWC == light_subtype) { @@ -491,7 +491,7 @@ void LightSetDimmer(uint8_t myDimmer) } } -void LightSetColor() +void LightSetColor(void) { uint8_t highest = 0; @@ -551,7 +551,7 @@ char* LightGetColor(uint8_t type, char* scolor) return scolor; } -void LightPowerOn() +void LightPowerOn(void) { if (Settings.light_dimmer && !(light_power)) { ExecuteCommandPower(light_device, POWER_ON, SRC_LIGHT); @@ -606,7 +606,7 @@ void LightState(uint8_t append) } } -void LightPreparePower() +void LightPreparePower(void) { if (Settings.light_dimmer && !(light_power)) { if (!Settings.flag.not_power_linked) { @@ -623,7 +623,7 @@ void LightPreparePower() LightState(0); } -void LightFade() +void LightFade(void) { if (0 == Settings.light_fade) { for (byte i = 0; i < light_subtype; i++) { @@ -686,7 +686,7 @@ void LightCycleColor(int8_t direction) memcpy(light_new_color, light_entry_color, sizeof(light_new_color)); } -void LightRandomColor() +void LightRandomColor(void) { uint8_t light_update = 0; for (byte i = 0; i < LST_RGB; i++) { @@ -702,7 +702,7 @@ void LightRandomColor() LightFade(); } -void LightSetPower() +void LightSetPower(void) { // light_power = XdrvMailbox.index; light_power = bitRead(XdrvMailbox.index, light_device -1); @@ -715,7 +715,7 @@ void LightSetPower() LightAnimate(); } -void LightAnimate() +void LightAnimate(void) { uint8_t cur_col[5]; uint16_t light_still_on = 0; @@ -843,7 +843,7 @@ float light_hue = 0.0; float light_saturation = 0.0; float light_brightness = 0.0; -void LightRgbToHsb() +void LightRgbToHsb(void) { LightSetDimmer(Settings.light_dimmer); @@ -874,7 +874,7 @@ void LightRgbToHsb() } } -void LightHsbToRgb() +void LightHsbToRgb(void) { float r; float g; @@ -1064,7 +1064,7 @@ boolean LightColorEntry(char *buffer, uint8_t buffer_length) /********************************************************************************************/ //boolean LightCommand(char *type, uint16_t index, char *dataBuf, uint16_t XdrvMailbox.data_len, int16_t XdrvMailbox.payload) -boolean LightCommand() +boolean LightCommand(void) { char command [CMDSZ]; boolean serviced = true; diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 8ab611ead..dd8178c12 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -88,7 +88,7 @@ void IrReceiveInit(void) // AddLog_P(LOG_LEVEL_DEBUG, PSTR("IrReceive initialized")); } -void IrReceiveCheck() +void IrReceiveCheck(void) { char sirtype[14]; // Max is AIWA_RC_T501 char stemp[16]; @@ -285,7 +285,7 @@ boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolea */ //boolean IrSendCommand(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload) -boolean IrSendCommand() +boolean IrSendCommand(void) { boolean serviced = true; boolean error = false; diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 3afdf6066..30bd6e4f0 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -167,7 +167,7 @@ ssize_t rf_search_and_write(uint8_t *buf, size_t size) return 0; } -uint8_t rf_erase_flash() +uint8_t rf_erase_flash(void) { uint8_t err; @@ -190,7 +190,7 @@ uint8_t rf_erase_flash() return 0; } -uint8_t SnfBrUpdateInit() +uint8_t SnfBrUpdateInit(void) { pinMode(PIN_C2CK, OUTPUT); pinMode(PIN_C2D, INPUT); @@ -201,7 +201,7 @@ uint8_t SnfBrUpdateInit() /********************************************************************************************/ -void SonoffBridgeReceivedRaw() +void SonoffBridgeReceivedRaw(void) { // Decoding according to https://github.com/Portisch/RF-Bridge-EFM8BB1 uint8_t buckets = 0; @@ -225,14 +225,14 @@ void SonoffBridgeReceivedRaw() /********************************************************************************************/ -void SonoffBridgeLearnFailed() +void SonoffBridgeLearnFailed(void) { 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_JSON_LEARN_FAILED); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); } -void SonoffBridgeReceived() +void SonoffBridgeReceived(void) { uint16_t sync_time = 0; uint16_t low_time = 0; @@ -300,7 +300,7 @@ void SonoffBridgeReceived() } } -boolean SonoffBridgeSerialInput() +boolean SonoffBridgeSerialInput(void) { // iTead Rf Universal Transceiver Module Serial Protocol Version 1.0 (20170420) static int8_t receive_len = 0; @@ -359,7 +359,7 @@ void SonoffBridgeSendCommand(byte code) Serial.write(0x55); // End of Text } -void SonoffBridgeSendAck() +void SonoffBridgeSendAck(void) { Serial.write(0xAA); // Start of Text Serial.write(0xA0); // Acknowledge @@ -418,7 +418,7 @@ void SonoffBridgeLearn(uint8_t key) * Commands \*********************************************************************************************/ -boolean SonoffBridgeCommand() +boolean SonoffBridgeCommand(void) { char command [CMDSZ]; boolean serviced = true; @@ -556,7 +556,7 @@ boolean SonoffBridgeCommand() /*********************************************************************************************/ -void SonoffBridgeInit() +void SonoffBridgeInit(void) { sonoff_bridge_receive_raw_flag = 0; SonoffBridgeSendCommand(0xA7); // Stop reading RF signals enabling iTead default RF handling diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 527053832..a4851a7b8 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -45,7 +45,7 @@ boolean domoticz_subscribe = false; int domoticz_update_timer = 0; byte domoticz_update_flag = 1; -int DomoticzBatteryQuality() +int DomoticzBatteryQuality(void) { // Battery 0%: ESP 2.6V (minimum operating voltage is 2.5) // Battery 100%: ESP 3.6V (maximum operating voltage is 3.6) @@ -64,7 +64,7 @@ int DomoticzBatteryQuality() return quality; } -int DomoticzRssiQuality() +int DomoticzRssiQuality(void) { // RSSI range: 0% to 10% (12 means disable RSSI in Domoticz) @@ -94,7 +94,7 @@ void DomoticzUpdatePowerState(byte device) domoticz_update_flag = 1; } -void DomoticzMqttUpdate() +void DomoticzMqttUpdate(void) { if (domoticz_subscribe && (Settings.domoticz_update_timer || domoticz_update_timer)) { domoticz_update_timer--; @@ -107,7 +107,7 @@ void DomoticzMqttUpdate() } } -void DomoticzMqttSubscribe() +void DomoticzMqttSubscribe(void) { uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; for (byte i = 0; i < maxdev; i++) { @@ -148,7 +148,7 @@ void DomoticzMqttSubscribe() } */ -boolean DomoticzMqttData() +boolean DomoticzMqttData(void) { char stemp1[10]; unsigned long idx = 0; @@ -234,7 +234,7 @@ boolean DomoticzMqttData() * Commands \*********************************************************************************************/ -boolean DomoticzCommand() +boolean DomoticzCommand(void) { char command [CMDSZ]; boolean serviced = true; @@ -393,7 +393,7 @@ const char HTTP_FORM_DOMOTICZ_SENSOR[] PROGMEM = const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM = "
          "; -void HandleDomoticzConfiguration() +void HandleDomoticzConfiguration(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -437,7 +437,7 @@ void HandleDomoticzConfiguration() ShowPage(page); } -void DomoticzSaveSettings() +void DomoticzSaveSettings(void) { char stemp[20]; char ssensor_indices[6 * MAX_DOMOTICZ_SNS_IDX]; diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index f1ac48fe7..3d28e49bc 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -38,7 +38,7 @@ uint8_t serial_bridge_in_byte_counter = 0; unsigned long serial_bridge_polling_window = 0; char serial_bridge_buffer[SERIAL_BRIDGE_BUFFER_SIZE]; -void SerialBridgeInput() +void SerialBridgeInput(void) { while (SerialBridgeSerial->available()) { yield(); @@ -87,7 +87,7 @@ void SerialBridgeInit(void) * Commands \*********************************************************************************************/ -boolean SerialBridgeCommand() +boolean SerialBridgeCommand(void) { char command [CMDSZ]; boolean serviced = true; diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 5907943f6..6fa499efd 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -64,7 +64,7 @@ const double pi2 = TWO_PI; const double pi = PI; const double RAD = DEG_TO_RAD; -double JulianischesDatum() +double JulianischesDatum(void) { // Gregorianischer Kalender int Gregor; @@ -255,12 +255,12 @@ void TimerSetRandomWindow(byte index) } } -void TimerSetRandomWindows() +void TimerSetRandomWindows(void) { for (byte i = 0; i < MAX_TIMERS; i++) { TimerSetRandomWindow(i); } } -void TimerEverySecond() +void TimerEverySecond(void) { if (RtcTime.valid) { if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second) { TimerSetRandomWindows(); } // Midnight @@ -338,7 +338,7 @@ void PrepShowTimer(uint8_t index) * Commands \*********************************************************************************************/ -boolean TimerCommand() +boolean TimerCommand(void) { char command[CMDSZ]; char dataBufUc[XdrvMailbox.data_len]; @@ -681,7 +681,7 @@ const char HTTP_FORM_TIMER1[] PROGMEM = "
          " "
          "; -void HandleTimerConfiguration() +void HandleTimerConfiguration(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -717,7 +717,7 @@ void HandleTimerConfiguration() ShowPage(page); } -void TimerSaveSettings() +void TimerSaveSettings(void) { char tmp[MAX_TIMERS *12]; // Need space for MAX_TIMERS x 10 digit numbers separated by a comma Timer timer; diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 4da4937d7..e53c3f249 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -347,12 +347,12 @@ bool RulesProcessEvent(char *json_event) return serviced; } -bool RulesProcess() +bool RulesProcess(void) { return RulesProcessEvent(mqtt_data); } -void RulesInit() +void RulesInit(void) { rules_flag.data = 0; for (byte i = 0; i < MAX_RULE_SETS; i++) { @@ -364,7 +364,7 @@ void RulesInit() rules_teleperiod = 0; } -void RulesEvery50ms() +void RulesEvery50ms(void) { if (Settings.rule_enabled) { // Any rule enabled char json_event[120]; @@ -455,7 +455,7 @@ void RulesEvery50ms() } } -void RulesEvery100ms() +void RulesEvery100ms(void) { if (Settings.rule_enabled && (uptime > 4)) { // Any rule enabled and allow 4 seconds start-up time for sensors (#3811) mqtt_data[0] = '\0'; @@ -471,7 +471,7 @@ void RulesEvery100ms() } } -void RulesEverySecond() +void RulesEverySecond(void) { if (Settings.rule_enabled) { // Any rule enabled char json_event[120]; @@ -495,19 +495,19 @@ void RulesEverySecond() } } -void RulesSetPower() +void RulesSetPower(void) { rules_new_power = XdrvMailbox.index; } -void RulesTeleperiod() +void RulesTeleperiod(void) { rules_teleperiod = 1; RulesProcess(); rules_teleperiod = 0; } -boolean RulesCommand() +boolean RulesCommand(void) { char command[CMDSZ]; boolean serviced = true; diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 86a8a7fca..69fa558fa 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -392,7 +392,7 @@ void KNX_DEL_CB( byte CBnum ) } -bool KNX_CONFIG_NOT_MATCH() +bool KNX_CONFIG_NOT_MATCH(void) { // Check for configured parameters that the device does not have (module changed) for (byte i = 0; i < KNX_MAX_device_param; ++i) @@ -442,7 +442,7 @@ bool KNX_CONFIG_NOT_MATCH() } -void KNXStart() +void KNXStart(void) { knx.start(nullptr); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_START)); @@ -450,7 +450,7 @@ void KNXStart() } -void KNX_INIT() +void KNX_INIT(void) { // Check for incompatible config if (Settings.knx_GA_registered > MAX_KNX_GA) { Settings.knx_GA_registered = MAX_KNX_GA; } @@ -795,7 +795,7 @@ const char HTTP_FORM_KNX_ADD_TABLE_ROW2[] PROGMEM = "" ""; -void HandleKNXConfiguration() +void HandleKNXConfiguration(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -994,7 +994,7 @@ void HandleKNXConfiguration() } -void KNX_Save_Settings() +void KNX_Save_Settings(void) { String stmp; address_t KNX_addr; @@ -1047,7 +1047,7 @@ void KNX_Save_Settings() #endif // USE_WEBSERVER -boolean KnxCommand() +boolean KnxCommand(void) { char command[CMDSZ]; uint8_t index = XdrvMailbox.index; diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 46a5c0521..91a538292 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -69,7 +69,7 @@ const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = "\"effect_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; // string list with reference to scheme parameter. Currently only supports numbers 0 to 11 as it make the mqtt string too long */ -void HAssDiscoverRelay() +void HAssDiscoverRelay(void) { char sidx[8]; char stopic[TOPSZ]; @@ -138,7 +138,7 @@ void HAssDiscoverRelay() } } -void HAssDiscoverButton() +void HAssDiscoverButton(void) { char sidx[8]; char stopic[TOPSZ]; @@ -215,7 +215,7 @@ void HAssDiscovery(uint8_t mode) enum HassCommands { CMND_HASSDISCOVER }; const char kHassCommands[] PROGMEM = D_CMND_HASSDISCOVER ; -boolean HassCommand() +boolean HassCommand(void) { char command[CMDSZ]; boolean serviced = true; diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 26438aabe..fe93fc8ca 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -106,7 +106,7 @@ void DisplayInit(uint8_t mode) XdspCall(FUNC_DISPLAY_INIT); } -void DisplayClear() +void DisplayClear(void) { XdspCall(FUNC_DISPLAY_CLEAR); } @@ -177,7 +177,7 @@ void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2 XdspCall(FUNC_DISPLAY_FILL_RECTANGLE); } -void DisplayDrawFrame() +void DisplayDrawFrame(void) { XdspCall(FUNC_DISPLAY_DRAW_FRAME); } @@ -254,7 +254,7 @@ uint8_t atoiV(char *cp, uint16_t *res) #define DISPLAY_BUFFER_COLS 128 // Max number of characters in linebuf -void DisplayText() +void DisplayText(void) { uint8_t lpos; uint8_t escape = 0; @@ -487,7 +487,7 @@ void DisplayText() #ifdef USE_DISPLAY_MODES1TO5 -void DisplayClearScreenBuffer() +void DisplayClearScreenBuffer(void) { if (disp_screen_buffer_cols) { for (byte i = 0; i < disp_screen_buffer_rows; i++) { @@ -496,7 +496,7 @@ void DisplayClearScreenBuffer() } } -void DisplayFreeScreenBuffer() +void DisplayFreeScreenBuffer(void) { if (disp_screen_buffer != NULL) { for (byte i = 0; i < disp_screen_buffer_rows; i++) { @@ -508,7 +508,7 @@ void DisplayFreeScreenBuffer() } } -void DisplayAllocScreenBuffer() +void DisplayAllocScreenBuffer(void) { if (!disp_screen_buffer_cols) { disp_screen_buffer_rows = Settings.display_rows; @@ -529,7 +529,7 @@ void DisplayAllocScreenBuffer() } } -void DisplayReAllocScreenBuffer() +void DisplayReAllocScreenBuffer(void) { DisplayFreeScreenBuffer(); DisplayAllocScreenBuffer(); @@ -546,7 +546,7 @@ void DisplayFillScreen(uint8_t line) /*-------------------------------------------------------------------------------------------*/ -void DisplayClearLogBuffer() +void DisplayClearLogBuffer(void) { if (disp_log_buffer_cols) { for (byte i = 0; i < DISPLAY_LOG_ROWS; i++) { @@ -555,7 +555,7 @@ void DisplayClearLogBuffer() } } -void DisplayFreeLogBuffer() +void DisplayFreeLogBuffer(void) { if (disp_log_buffer != NULL) { for (byte i = 0; i < DISPLAY_LOG_ROWS; i++) { @@ -566,7 +566,7 @@ void DisplayFreeLogBuffer() } } -void DisplayAllocLogBuffer() +void DisplayAllocLogBuffer(void) { if (!disp_log_buffer_cols) { disp_log_buffer = (char**)malloc(sizeof(*disp_log_buffer) * DISPLAY_LOG_ROWS); @@ -586,7 +586,7 @@ void DisplayAllocLogBuffer() } } -void DisplayReAllocLogBuffer() +void DisplayReAllocLogBuffer(void) { DisplayFreeLogBuffer(); DisplayAllocLogBuffer(); @@ -617,7 +617,7 @@ char* DisplayLogBuffer(char temp_code) return result; } -void DisplayLogBufferInit() +void DisplayLogBufferInit(void) { if (Settings.display_mode) { disp_log_buffer_idx = 0; @@ -798,7 +798,7 @@ void DisplayAnalyzeJson(char *topic, char *json) } } -void DisplayMqttSubscribe() +void DisplayMqttSubscribe(void) { /* Subscribe to tele messages only * Supports the following FullTopic formats @@ -831,7 +831,7 @@ void DisplayMqttSubscribe() } } -boolean DisplayMqttData() +boolean DisplayMqttData(void) { if (disp_subscribed) { char stopic[TOPSZ]; @@ -850,7 +850,7 @@ boolean DisplayMqttData() return false; } -void DisplayLocalSensor() +void DisplayLocalSensor(void) { if ((Settings.display_mode &0x02) && (0 == tele_period)) { DisplayAnalyzeJson(mqtt_topic, mqtt_data); @@ -863,7 +863,7 @@ void DisplayLocalSensor() * Public \*********************************************************************************************/ -void DisplayInitDriver() +void DisplayInitDriver(void) { XdspCall(FUNC_DISPLAY_INIT_DRIVER); @@ -882,7 +882,7 @@ void DisplayInitDriver() } } -void DisplaySetPower() +void DisplaySetPower(void) { disp_power = bitRead(XdrvMailbox.index, disp_device -1); if (Settings.display_model) { @@ -894,7 +894,7 @@ void DisplaySetPower() * Commands \*********************************************************************************************/ -boolean DisplayCommand() +boolean DisplayCommand(void) { char command [CMDSZ]; boolean serviced = true; diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index a142365a1..278ef6941 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -114,7 +114,7 @@ void TuyaSendValue(uint8_t id, uint32_t value){ TuyaSendState(id, TUYA_TYPE_VALUE, (uint8_t*)(&value)); } -boolean TuyaSetPower() +boolean TuyaSetPower(void) { boolean status = false; @@ -154,7 +154,7 @@ void LightSerialDuty(uint8_t duty) } } -void TuyaRequestState(){ +void TuyaRequestState(void){ if(TuyaSerial) { // Get current status of MCU @@ -165,7 +165,7 @@ void TuyaRequestState(){ } } -void TuyaResetWifi() +void TuyaResetWifi(void) { if (!Settings.flag.button_restrict) { char scmnd[20]; @@ -174,7 +174,7 @@ void TuyaResetWifi() } } -void TuyaPacketProcess() +void TuyaPacketProcess(void) { char scmnd[20]; @@ -267,7 +267,7 @@ void TuyaPacketProcess() * API Functions \*********************************************************************************************/ -boolean TuyaModuleSelected() +boolean TuyaModuleSelected(void) { if (!(pin[GPIO_TUYA_RX] < 99) || !(pin[GPIO_TUYA_TX] < 99)) { // fallback to hardware-serial if not explicitly selected pin[GPIO_TUYA_TX] = 1; @@ -280,7 +280,7 @@ boolean TuyaModuleSelected() return true; } -void TuyaInit() +void TuyaInit(void) { if (!Settings.param[P_TUYA_DIMMER_ID]) { Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID; @@ -296,7 +296,7 @@ void TuyaInit() } } -void TuyaSerialInput() +void TuyaSerialInput(void) { while (TuyaSerial->available()) { yield(); @@ -352,7 +352,7 @@ void TuyaSerialInput() } -boolean TuyaButtonPressed() +boolean TuyaButtonPressed(void) { if (!XdrvMailbox.index && ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == lastbutton[XdrvMailbox.index]))) { snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Reset GPIO triggered")); @@ -363,7 +363,7 @@ boolean TuyaButtonPressed() return false; // Don't serve other buttons } -void TuyaSetWifiLed(){ +void TuyaSetWifiLed(void){ uint8_t wifi_state = 0x02; switch(WifiState()){ case WIFI_SMARTCONFIG: diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index 82ce95096..cb972e87d 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -40,7 +40,7 @@ RCSwitch mySwitch = RCSwitch(); uint32_t rf_lasttime = 0; -void RfReceiveCheck() +void RfReceiveCheck(void) { if (mySwitch.available()) { @@ -74,7 +74,7 @@ void RfReceiveCheck() } } -void RfInit() +void RfInit(void) { if (pin[GPIO_RFSEND] < 99) { mySwitch.enableTransmit(pin[GPIO_RFSEND]); @@ -88,7 +88,7 @@ void RfInit() * Commands \*********************************************************************************************/ -boolean RfSendCommand() +boolean RfSendCommand(void) { boolean serviced = true; boolean error = false; diff --git a/sonoff/xdrv_95_debug.ino b/sonoff/xdrv_95_debug.ino index 18f9ad76f..a1c9ac22d 100644 --- a/sonoff/xdrv_95_debug.ino +++ b/sonoff/xdrv_95_debug.ino @@ -131,7 +131,7 @@ Decoding 14 results /*******************************************************************************************/ -void CpuLoadLoop() +void CpuLoadLoop(void) { CPU_last_loop_time = millis(); if (CPU_load_check && CPU_last_millis) { @@ -164,7 +164,7 @@ extern "C" { extern cont_t g_cont; } -void DebugFreeMem() +void DebugFreeMem(void) { register uint32_t *sp asm("a1"); @@ -186,7 +186,7 @@ extern "C" { extern cont_t* g_pcont; } -void DebugFreeMem() +void DebugFreeMem(void) { register uint32_t *sp asm("a1"); @@ -408,7 +408,7 @@ void DebugCfgShow(uint8_t more) /*******************************************************************************************/ -boolean DebugCommand() +boolean DebugCommand(void) { char command[CMDSZ]; boolean serviced = true; diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index cb3a69c22..c9557ec56 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -216,7 +216,7 @@ boolean XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t return XdrvCall(FUNC_MQTT_DATA); } -boolean XdrvRulesProcess() +boolean XdrvRulesProcess(void) { return XdrvCall(FUNC_RULES_PROCESS); } diff --git a/sonoff/xdsp_01_lcd.ino b/sonoff/xdsp_01_lcd.ino index bfc0b3536..60fe0bab6 100644 --- a/sonoff/xdsp_01_lcd.ino +++ b/sonoff/xdsp_01_lcd.ino @@ -33,7 +33,7 @@ LiquidCrystal_I2C *lcd; /*********************************************************************************************/ -void LcdInitMode() +void LcdInitMode(void) { lcd->init(); lcd->clear(); @@ -54,7 +54,7 @@ void LcdInit(uint8_t mode) } } -void LcdInitDriver() +void LcdInitDriver(void) { if (!Settings.display_model) { if (I2cDevice(LCD_ADDRESS1)) { @@ -78,7 +78,7 @@ void LcdInitDriver() } } -void LcdDrawStringAt() +void LcdDrawStringAt(void) { lcd->setCursor(dsp_x, dsp_y); lcd->print(dsp_str); @@ -112,7 +112,7 @@ void LcdCenter(byte row, char* txt) lcd->print(line); } -boolean LcdPrintLog() +boolean LcdPrintLog(void) { boolean result = false; @@ -145,7 +145,7 @@ boolean LcdPrintLog() return result; } -void LcdTime() +void LcdTime(void) { char line[Settings.display_cols[0] +1]; @@ -155,7 +155,7 @@ void LcdTime() LcdCenter(1, line); } -void LcdRefresh() // Every second +void LcdRefresh(void) // Every second { if (Settings.display_mode) { // Mode 0 is User text switch (Settings.display_mode) { diff --git a/sonoff/xdsp_02_ssd1306.ino b/sonoff/xdsp_02_ssd1306.ino index 6b4d72f96..4ccdcd9c9 100644 --- a/sonoff/xdsp_02_ssd1306.ino +++ b/sonoff/xdsp_02_ssd1306.ino @@ -43,7 +43,7 @@ uint8_t ssd1306_font_y = OLED_FONT_HEIGTH; /*********************************************************************************************/ -void Ssd1306InitMode() +void Ssd1306InitMode(void) { oled->setRotation(Settings.display_rotate); // 0 oled->invertDisplay(false); @@ -72,7 +72,7 @@ void Ssd1306Init(uint8_t mode) } } -void Ssd1306InitDriver() +void Ssd1306InitDriver(void) { if (!Settings.display_model) { if (I2cDevice(OLED_ADDRESS1)) { @@ -97,7 +97,7 @@ void Ssd1306InitDriver() } } -void Ssd1306Clear() +void Ssd1306Clear(void) { oled->clearDisplay(); oled->setCursor(0, 0); @@ -123,7 +123,7 @@ void Ssd1306DisplayOnOff(uint8_t on) } } -void Ssd1306OnOff() +void Ssd1306OnOff(void) { Ssd1306DisplayOnOff(disp_power); oled->display(); @@ -133,7 +133,7 @@ void Ssd1306OnOff() #ifdef USE_DISPLAY_MODES1TO5 -void Ssd1306PrintLog() +void Ssd1306PrintLog(void) { disp_refresh--; if (!disp_refresh) { @@ -163,7 +163,7 @@ void Ssd1306PrintLog() } } -void Ssd1306Time() +void Ssd1306Time(void) { char line[12]; @@ -177,7 +177,7 @@ void Ssd1306Time() oled->display(); } -void Ssd1306Refresh() // Every second +void Ssd1306Refresh(void) // Every second { if (Settings.display_mode) { // Mode 0 is User text switch (Settings.display_mode) { diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index 36c5955d6..7af998470 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -43,14 +43,14 @@ uint8_t mtx_done = 0; /*********************************************************************************************/ -void MatrixWrite() +void MatrixWrite(void) { for (byte i = 0; i < mtx_matrices; i++) { matrix[i]->writeDisplay(); } } -void MatrixClear() +void MatrixClear(void) { for (byte i = 0; i < mtx_matrices; i++) { matrix[i]->clear(); @@ -166,7 +166,7 @@ void MatrixScrollUp(char* txt, int loop) /*********************************************************************************************/ -void MatrixInitMode() +void MatrixInitMode(void) { for (byte i = 0; i < mtx_matrices; i++) { matrix[i]->setRotation(Settings.display_rotate); // 1 @@ -192,7 +192,7 @@ void MatrixInit(uint8_t mode) } } -void MatrixInitDriver() +void MatrixInitDriver(void) { if (!Settings.display_model) { if (I2cDevice(Settings.display_address[1])) { @@ -215,7 +215,7 @@ void MatrixInitDriver() } } -void MatrixOnOff() +void MatrixOnOff(void) { if (!disp_power) { MatrixClear(); } } @@ -278,7 +278,7 @@ void MatrixPrintLog(uint8_t direction) #endif // USE_DISPLAY_MODES1TO5 -void MatrixRefresh() // Every second +void MatrixRefresh(void) // Every second { if (disp_power) { switch (Settings.display_mode) { diff --git a/sonoff/xdsp_04_ili9341.ino b/sonoff/xdsp_04_ili9341.ino index 5f7f506fe..b4149035e 100644 --- a/sonoff/xdsp_04_ili9341.ino +++ b/sonoff/xdsp_04_ili9341.ino @@ -38,7 +38,7 @@ uint16_t tft_scroll; /*********************************************************************************************/ -void Ili9341InitMode() +void Ili9341InitMode(void) { tft->setRotation(Settings.display_rotate); // 0 tft->invertDisplay(0); @@ -77,7 +77,7 @@ void Ili9341Init(uint8_t mode) } } -void Ili9341InitDriver() +void Ili9341InitDriver(void) { if (!Settings.display_model) { Settings.display_model = XDSP_04; @@ -97,7 +97,7 @@ void Ili9341InitDriver() } } -void Ili9341Clear() +void Ili9341Clear(void) { tft->fillScreen(ILI9341_BLACK); tft->setCursor(0, 0); @@ -128,7 +128,7 @@ void Ili9341DisplayOnOff(uint8_t on) } } -void Ili9341OnOff() +void Ili9341OnOff(void) { Ili9341DisplayOnOff(disp_power); } @@ -137,7 +137,7 @@ void Ili9341OnOff() #ifdef USE_DISPLAY_MODES1TO5 -void Ili9341PrintLog() +void Ili9341PrintLog(void) { disp_refresh--; if (!disp_refresh) { @@ -184,7 +184,7 @@ void Ili9341PrintLog() } } -void Ili9341Refresh() // Every second +void Ili9341Refresh(void) // Every second { if (Settings.display_mode) { // Mode 0 is User text char tftdt[Settings.display_cols[0] +1]; diff --git a/sonoff/xdsp_05_epaper.ino b/sonoff/xdsp_05_epaper.ino index 91eb747f2..3d5c5b4e6 100644 --- a/sonoff/xdsp_05_epaper.ino +++ b/sonoff/xdsp_05_epaper.ino @@ -41,7 +41,7 @@ sFONT *selected_font; /*********************************************************************************************/ -void EpdInitMode() +void EpdInitMode(void) { // whiten display with full update epd.Init(lut_full_update); @@ -72,7 +72,7 @@ void EpdInitMode() paint.Clear(UNCOLORED); } -void EpdInitPartial() +void EpdInitPartial(void) { epd.Init(lut_partial_update); //paint.Clear(UNCOLORED); @@ -80,7 +80,7 @@ void EpdInitPartial() delay(500); } -void EpdInitFull() +void EpdInitFull(void) { epd.Init(lut_full_update); //paint.Clear(UNCOLORED); @@ -104,7 +104,7 @@ void EpdInit(uint8_t mode) } } -void EpdInitDriver() +void EpdInitDriver(void) { if (!Settings.display_model) { Settings.display_model = XDSP_05; @@ -121,7 +121,7 @@ void EpdInitDriver() /*********************************************************************************************/ -void EpdClear() +void EpdClear(void) { paint.Clear(UNCOLORED); } @@ -158,7 +158,7 @@ void EpdDisplayOnOff(uint8_t on) } -void EpdOnOff() +void EpdOnOff(void) { EpdDisplayOnOff(disp_power); } @@ -167,7 +167,7 @@ void EpdOnOff() #ifdef USE_DISPLAY_MODES1TO5 -void EpdRefresh() // Every second +void EpdRefresh(void) // Every second { if (Settings.display_mode) { // Mode 0 is User text diff --git a/sonoff/xdsp_interface.ino b/sonoff/xdsp_interface.ino index 06fbf01dc..e2847d85e 100644 --- a/sonoff/xdsp_interface.ino +++ b/sonoff/xdsp_interface.ino @@ -112,7 +112,7 @@ const uint8_t xdsp_present = sizeof(xdsp_func_ptr) / sizeof(xdsp_func_ptr[0]); * FUNC_DISPLAY_ONOFF \*********************************************************************************************/ -uint8_t XdspPresent() +uint8_t XdspPresent(void) { return xdsp_present; } diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 0a7a074e7..0a4419498 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -62,11 +62,11 @@ unsigned long hlw_cf1_voltage_max_pulse_counter; unsigned long hlw_cf1_current_max_pulse_counter; #ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception -void HlwCfInterrupt() ICACHE_RAM_ATTR; -void HlwCf1Interrupt() ICACHE_RAM_ATTR; +void HlwCfInterrupt(void) ICACHE_RAM_ATTR; +void HlwCf1Interrupt(void) ICACHE_RAM_ATTR; #endif // USE_WS2812_DMA -void HlwCfInterrupt() // Service Power +void HlwCfInterrupt(void) // Service Power { unsigned long us = micros(); @@ -80,7 +80,7 @@ void HlwCfInterrupt() // Service Power } } -void HlwCf1Interrupt() // Service Voltage and Current +void HlwCf1Interrupt(void) // Service Voltage and Current { unsigned long us = micros(); @@ -97,7 +97,7 @@ void HlwCf1Interrupt() // Service Voltage and Current /********************************************************************************************/ -void HlwEvery200ms() +void HlwEvery200ms(void) { unsigned long hlw_w = 0; unsigned long hlw_u = 0; @@ -154,7 +154,7 @@ void HlwEvery200ms() } } -void HlwEverySecond() +void HlwEverySecond(void) { unsigned long hlw_len; @@ -168,7 +168,7 @@ void HlwEverySecond() } } -void HlwSnsInit() +void HlwSnsInit(void) { if (!Settings.energy_power_calibration || (4975 == Settings.energy_power_calibration)) { Settings.energy_power_calibration = HLW_PREF_PULSE; @@ -210,7 +210,7 @@ void HlwSnsInit() hlw_cf1_timer = 0; } -void HlwDrvInit() +void HlwDrvInit(void) { if (!energy_flg) { hlw_model_type = 0; @@ -233,7 +233,7 @@ void HlwDrvInit() } } -boolean HlwCommand() +boolean HlwCommand(void) { boolean serviced = true; diff --git a/sonoff/xnrg_02_cse7766.ino b/sonoff/xnrg_02_cse7766.ino index 1be231192..318fb02a7 100644 --- a/sonoff/xnrg_02_cse7766.ino +++ b/sonoff/xnrg_02_cse7766.ino @@ -46,7 +46,7 @@ long cf_pulses = 0; long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; uint8_t cse_power_invalid = CSE_MAX_INVALID_POWER; -void CseReceived() +void CseReceived(void) { // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // 55 5A 02 F7 60 00 03 5A 00 40 10 04 8B 9F 51 A6 58 18 72 75 61 AC A1 30 - Power not valid (load below 5W) @@ -128,7 +128,7 @@ void CseReceived() } } -bool CseSerialInput() +bool CseSerialInput(void) { if (cse_receive_flag) { serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; @@ -168,7 +168,7 @@ bool CseSerialInput() /********************************************************************************************/ -void CseEverySecond() +void CseEverySecond(void) { long cf_frequency = 0; @@ -188,7 +188,7 @@ void CseEverySecond() } } -void CseDrvInit() +void CseDrvInit(void) { if (!energy_flg) { if ((SONOFF_S31 == Settings.module) || (SONOFF_POW_R2 == Settings.module)) { // Sonoff S31 or Sonoff Pow R2 @@ -199,7 +199,7 @@ void CseDrvInit() } } -boolean CseCommand() +boolean CseCommand(void) { boolean serviced = true; diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index dae285b01..d30b769c2 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -87,7 +87,7 @@ void PzemSend(uint8_t cmd) PzemSerial->write(bytes, sizeof(pzem)); } -bool PzemReceiveReady() +bool PzemReceiveReady(void) { return PzemSerial->available() >= (int)sizeof(PZEMCommand); } @@ -162,7 +162,7 @@ const uint8_t pzem_responses[] { RESP_SET_ADDRESS, RESP_VOLTAGE, RESP_CURRENT, R uint8_t pzem_read_state = 0; uint8_t pzem_sendRetry = 0; -void PzemEvery200ms() +void PzemEvery200ms(void) { bool data_ready = PzemReceiveReady(); @@ -200,7 +200,7 @@ void PzemEvery200ms() } } -void PzemSnsInit() +void PzemSnsInit(void) { // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions PzemSerial = new TasmotaSerial(pin[GPIO_PZEM004_RX], pin[GPIO_PZEM0XX_TX], 1); @@ -211,7 +211,7 @@ void PzemSnsInit() } } -void PzemDrvInit() +void PzemDrvInit(void) { if (!energy_flg) { if ((pin[GPIO_PZEM004_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { // Any device with a Pzem004T diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index ca2262bb5..6bbabdaa9 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -36,7 +36,7 @@ #include TasmotaModbus *PzemAcModbus; -void PzemAcEverySecond() +void PzemAcEverySecond(void) { static uint8_t send_retry = 0; @@ -78,7 +78,7 @@ void PzemAcEverySecond() } } -void PzemAcSnsInit() +void PzemAcSnsInit(void) { PzemAcModbus = new TasmotaModbus(pin[GPIO_PZEM016_RX], pin[GPIO_PZEM0XX_TX]); uint8_t result = PzemAcModbus->Begin(9600); @@ -89,7 +89,7 @@ void PzemAcSnsInit() } } -void PzemAcDrvInit() +void PzemAcDrvInit(void) { if (!energy_flg) { if ((pin[GPIO_PZEM016_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index b7a693bef..3dcaf8332 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -36,7 +36,7 @@ #include TasmotaModbus *PzemDcModbus; -void PzemDcEverySecond() +void PzemDcEverySecond(void) { static uint8_t send_retry = 0; @@ -76,7 +76,7 @@ void PzemDcEverySecond() } } -void PzemDcSnsInit() +void PzemDcSnsInit(void) { PzemDcModbus = new TasmotaModbus(pin[GPIO_PZEM017_RX], pin[GPIO_PZEM0XX_TX]); uint8_t result = PzemDcModbus->Begin(9600, 2); // Uses two stop bits!! @@ -88,7 +88,7 @@ void PzemDcSnsInit() } } -void PzemDcDrvInit() +void PzemDcDrvInit(void) { if (!energy_flg) { if ((pin[GPIO_PZEM017_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 8bd5e529c..6c031fd94 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -59,7 +59,7 @@ const char WEMO_MSEARCH[] PROGMEM = "X-User-Agent: redsonic\r\n" "\r\n"; -String WemoSerialnumber() +String WemoSerialnumber(void) { char serial[16]; @@ -67,7 +67,7 @@ String WemoSerialnumber() return String(serial); } -String WemoUuid() +String WemoUuid(void) { char uuid[27]; @@ -131,7 +131,7 @@ const char HUE_ST3[] PROGMEM = "USN: uuid:{r3\r\n" "\r\n"; -String HueBridgeId() +String HueBridgeId(void) { String temp = WiFi.macAddress(); temp.replace(":", ""); @@ -139,7 +139,7 @@ String HueBridgeId() return bridgeid; // 5CCF7FFFFE139F3D } -String HueSerialnumber() +String HueSerialnumber(void) { String serial = WiFi.macAddress(); serial.replace(":", ""); @@ -147,14 +147,14 @@ String HueSerialnumber() return serial; // 5ccf7f139f3d } -String HueUuid() +String HueUuid(void) { String uuid = F("f6543a06-da50-11ba-8d8f-"); uuid += HueSerialnumber(); return uuid; // f6543a06-da50-11ba-8d8f-5ccf7f139f3d } -void HueRespondToMSearch() +void HueRespondToMSearch(void) { char message[TOPSZ]; @@ -197,7 +197,7 @@ void HueRespondToMSearch() * Belkin WeMo and Philips Hue bridge UDP multicast support \*********************************************************************************************/ -boolean UdpDisconnect() +boolean UdpDisconnect(void) { if (udp_connected) { WiFiUDP::stopAll(); @@ -207,7 +207,7 @@ boolean UdpDisconnect() return udp_connected; } -boolean UdpConnect() +boolean UdpConnect(void) { if (!udp_connected) { if (PortUdp.beginMulticast(WiFi.localIP(), ipMulticast, port_multicast)) { @@ -222,7 +222,7 @@ boolean UdpConnect() return udp_connected; } -void PollUdp() +void PollUdp(void) { if (udp_connected && !udp_response_mutex) { if (PortUdp.parsePacket()) { @@ -381,7 +381,7 @@ const char WEMO_SETUP_XML[] PROGMEM = /********************************************************************************************/ -void HandleUpnpEvent() +void HandleUpnpEvent(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); @@ -408,21 +408,21 @@ void HandleUpnpEvent() WebServer->send(200, FPSTR(HDR_CTYPE_XML), state_xml); } -void HandleUpnpService() +void HandleUpnpService(void) { 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 HandleUpnpMetaService() +void HandleUpnpMetaService(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_META_SERVICE)); WebServer->send(200, FPSTR(HDR_CTYPE_PLAIN), FPSTR(WEMO_METASERVICE_XML)); } -void HandleUpnpSetupWemo() +void HandleUpnpSetupWemo(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_SETUP)); @@ -517,7 +517,7 @@ String GetHueDeviceId(uint8_t id) return deviceid; // 5c:cf:7f:13:9f:3d:00:11-1 } -String GetHueUserId() +String GetHueUserId(void) { char userid[7]; @@ -525,7 +525,7 @@ String GetHueUserId() return String(userid); } -void HandleUpnpSetupHue() +void HandleUpnpSetupHue(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_HUE_BRIDGE_SETUP)); String description_xml = FPSTR(HUE_DESCRIPTION_XML); @@ -841,7 +841,7 @@ void HandleHueApi(String *path) else HueGlobalConfig(path); } -void HueWemoAddHandlers() +void HueWemoAddHandlers(void) { if (EMUL_WEMO == Settings.flag2.emulation) { WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); diff --git a/sonoff/xplg_ws2812.ino b/sonoff/xplg_ws2812.ino index 2e4c47b34..3c4c34457 100644 --- a/sonoff/xplg_ws2812.ino +++ b/sonoff/xplg_ws2812.ino @@ -96,7 +96,7 @@ uint8_t ws_show_next = 1; bool ws_suspend_update = false; /********************************************************************************************/ -void Ws2812StripShow() +void Ws2812StripShow(void) { #if (USE_WS2812_CTYPE > NEO_3LED) RgbwColor c; @@ -163,7 +163,7 @@ void Ws2812UpdateHand(int position, uint8_t index) } } -void Ws2812Clock() +void Ws2812Clock(void) { strip->ClearTo(0); // Reset strip int clksize = 60000 / (int)Settings.light_pixels; @@ -302,7 +302,7 @@ void Ws2812Bars(uint8_t schemenr) * Public \*********************************************************************************************/ -void Ws2812Init() +void Ws2812Init(void) { #ifdef USE_WS2812_DMA #if (USE_WS2812_CTYPE == NEO_GRB) @@ -337,7 +337,7 @@ void Ws2812Init() Ws2812Clear(); } -void Ws2812Clear() +void Ws2812Clear(void) { strip->ClearTo(0); strip->Show(); @@ -371,11 +371,11 @@ void Ws2812SetColor(uint16_t led, uint8_t red, uint8_t green, uint8_t blue, uint } } -void Ws2812ForceSuspend () { +void Ws2812ForceSuspend (void) { ws_suspend_update = true; } -void Ws2812ForceUpdate () { +void Ws2812ForceUpdate (void) { ws_suspend_update = false; strip->Show(); ws_show_next = 1; diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index 0c4271f81..4f3b7d0f4 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -41,29 +41,29 @@ void CounterUpdate(byte index) } } -void CounterUpdate1() +void CounterUpdate1(void) { CounterUpdate(1); } -void CounterUpdate2() +void CounterUpdate2(void) { CounterUpdate(2); } -void CounterUpdate3() +void CounterUpdate3(void) { CounterUpdate(3); } -void CounterUpdate4() +void CounterUpdate4(void) { CounterUpdate(4); } /********************************************************************************************/ -void CounterSaveState() +void CounterSaveState(void) { for (byte i = 0; i < MAX_COUNTERS; i++) { if (pin[GPIO_CNTR1 +i] < 99) { @@ -72,7 +72,7 @@ void CounterSaveState() } } -void CounterInit() +void CounterInit(void) { typedef void (*function) () ; function counter_callbacks[] = { CounterUpdate1, CounterUpdate2, CounterUpdate3, CounterUpdate4 }; diff --git a/sonoff/xsns_02_analog.ino b/sonoff/xsns_02_analog.ino index ce794b3a2..cb4e794f1 100644 --- a/sonoff/xsns_02_analog.ino +++ b/sonoff/xsns_02_analog.ino @@ -26,7 +26,7 @@ uint16_t adc_last_value = 0; -uint16_t AdcRead() +uint16_t AdcRead(void) { uint16_t analog = 0; for (byte i = 0; i < 32; i++) { @@ -38,7 +38,7 @@ uint16_t AdcRead() } #ifdef USE_RULES -void AdcEvery250ms() +void AdcEvery250ms(void) { uint16_t new_value = AdcRead(); if ((new_value < adc_last_value -10) || (new_value > adc_last_value +10)) { diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index a294ad32f..d31f6b5bb 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -65,7 +65,7 @@ void SonoffScSend(const char *data) AddLog(LOG_LEVEL_DEBUG); } -void SonoffScInit() +void SonoffScInit(void) { // SonoffScSend("AT+DEVCONFIG=\"uploadFreq\":1800"); SonoffScSend("AT+START"); diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index 1f96ba5b6..864e03f51 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -37,7 +37,7 @@ char ds18b20_types[] = "DS18B20"; * Embedded stripped and tuned OneWire library \*********************************************************************************************/ -uint8_t OneWireReset() +uint8_t OneWireReset(void) { uint8_t retries = 125; @@ -75,7 +75,7 @@ void OneWireWriteBit(uint8_t v) delayMicroseconds(delay_high[v]); } -uint8_t OneWireReadBit() +uint8_t OneWireReadBit(void) { //noInterrupts(); pinMode(ds18x20_pin, OUTPUT); @@ -96,7 +96,7 @@ void OneWireWrite(uint8_t v) } } -uint8_t OneWireRead() +uint8_t OneWireRead(void) { uint8_t r = 0; @@ -129,7 +129,7 @@ boolean OneWireCrc8(uint8_t *addr) /********************************************************************************************/ -void Ds18b20Convert() +void Ds18b20Convert(void) { OneWireReset(); OneWireWrite(W1_SKIP_ROM); // Address all Sensors on Bus @@ -137,7 +137,7 @@ void Ds18b20Convert() // delay(750); // 750ms should be enough for 12bit conv } -boolean Ds18b20Read() +boolean Ds18b20Read(void) { uint8_t data[9]; int8_t sign = 1; @@ -173,7 +173,7 @@ boolean Ds18b20Read() /********************************************************************************************/ -void Ds18b20EverySecond() +void Ds18b20EverySecond(void) { ds18x20_pin = pin[GPIO_DSB]; if (uptime &1) { diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index 10625c0c8..09f656730 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -69,7 +69,7 @@ uint8_t onewire_last_family_discrepancy = 0; bool onewire_last_device_flag = false; unsigned char onewire_rom_id[8] = { 0 }; -uint8_t OneWireReset() +uint8_t OneWireReset(void) { uint8_t retries = 125; @@ -107,7 +107,7 @@ void OneWireWriteBit(uint8_t v) delayMicroseconds(delay_high[v]); } -uint8_t OneWireReadBit() +uint8_t OneWireReadBit(void) { //noInterrupts(); pinMode(ds18x20_pin, OUTPUT); @@ -128,7 +128,7 @@ void OneWireWrite(uint8_t v) } } -uint8_t OneWireRead() +uint8_t OneWireRead(void) { uint8_t r = 0; @@ -148,7 +148,7 @@ void OneWireSelect(const uint8_t rom[8]) } } -void OneWireResetSearch() +void OneWireResetSearch(void) { onewire_last_discrepancy = 0; onewire_last_device_flag = false; @@ -254,7 +254,7 @@ boolean OneWireCrc8(uint8_t *addr) /********************************************************************************************/ -void Ds18x20Init() +void Ds18x20Init(void) { uint64_t ids[DS18X20_MAX_SENSORS]; @@ -289,7 +289,7 @@ void Ds18x20Init() AddLog(LOG_LEVEL_DEBUG); } -void Ds18x20Convert() +void Ds18x20Convert(void) { OneWireReset(); #ifdef W1_PARASITE_POWER @@ -389,7 +389,7 @@ void Ds18x20Name(uint8_t sensor) /********************************************************************************************/ -void Ds18x20EverySecond() +void Ds18x20EverySecond(void) { #ifdef W1_PARASITE_POWER // skip access if there is still an eeprom write ongoing diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index 385278432..dda92f831 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -43,12 +43,12 @@ uint8_t ds18x20_index[DS18X20_MAX_SENSORS]; uint8_t ds18x20_sensors = 0; char ds18x20_types[9]; -void Ds18x20Init() +void Ds18x20Init(void) { ds = new OneWire(pin[GPIO_DSB]); } -void Ds18x20Search() +void Ds18x20Search(void) { uint8_t num_sensors=0; uint8_t sensor = 0; @@ -78,7 +78,7 @@ void Ds18x20Search() ds18x20_sensors = num_sensors; } -uint8_t Ds18x20Sensors() +uint8_t Ds18x20Sensors(void) { return ds18x20_sensors; } @@ -93,7 +93,7 @@ String Ds18x20Addresses(uint8_t sensor) return String(address); } -void Ds18x20Convert() +void Ds18x20Convert(void) { ds->reset(); ds->write(W1_SKIP_ROM); // Address all Sensors on Bus diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index 1434b4f47..fa91e1f9b 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -45,7 +45,7 @@ struct DHTSTRUCT { float h = NAN; } Dht[DHT_MAX_SENSORS]; -void DhtReadPrep() +void DhtReadPrep(void) { for (byte i = 0; i < dht_sensors; i++) { digitalWrite(Dht[i].pin, HIGH); @@ -177,7 +177,7 @@ boolean DhtSetup(byte pin, byte type) /********************************************************************************************/ -void DhtInit() +void DhtInit(void) { dht_max_cycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for reading pulses from DHT sensor. @@ -192,7 +192,7 @@ void DhtInit() } } -void DhtEverySecond() +void DhtEverySecond(void) { if (uptime &1) { // <1mS diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index f636a8cf3..fdb06328a 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -44,7 +44,7 @@ uint8_t sht_valid = 0; float sht_temperature = 0; float sht_humidity = 0; -boolean ShtReset() +boolean ShtReset(void) { pinMode(sht_sda_pin, INPUT_PULLUP); pinMode(sht_scl_pin, OUTPUT); @@ -90,7 +90,7 @@ boolean ShtSendCommand(const byte cmd) return (!ackerror); } -boolean ShtAwaitResult() +boolean ShtAwaitResult(void) { // Maximum 320ms for 14 bit measurement for (byte i = 0; i < 16; i++) { @@ -104,7 +104,7 @@ boolean ShtAwaitResult() return false; } -int ShtReadData() +int ShtReadData(void) { int val = 0; @@ -125,7 +125,7 @@ int ShtReadData() return val; } -boolean ShtRead() +boolean ShtRead(void) { if (sht_valid) { sht_valid--; } if (!ShtReset()) { return false; } @@ -157,7 +157,7 @@ boolean ShtRead() /********************************************************************************************/ -void ShtDetect() +void ShtDetect(void) { if (sht_type) { return; @@ -174,7 +174,7 @@ void ShtDetect() } } -void ShtEverySecond() +void ShtEverySecond(void) { if (sht_type && !(uptime %4)) { // Update every 4 seconds // 344mS diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index 9a24050f0..87332287a 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -133,14 +133,14 @@ void HtuHeater(uint8_t heater) I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); } -void HtuInit() +void HtuInit(void) { HtuReset(); HtuHeater(HTU21_HEATER_OFF); HtuSetResolution(HTU21_RES_RH12_T14); } -boolean HtuRead() +boolean HtuRead(void) { uint8_t checksum = 0; uint16_t sensorval = 0; @@ -195,7 +195,7 @@ boolean HtuRead() /********************************************************************************************/ -void HtuDetect() +void HtuDetect(void) { if (htu_type) { return; } @@ -229,7 +229,7 @@ void HtuDetect() } } -void HtuEverySecond() +void HtuEverySecond(void) { if (92 == (uptime %100)) { // 1mS diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index bcc4632bd..68eef5c14 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -417,7 +417,7 @@ void Bme680Read(uint8_t bmp_idx) /********************************************************************************************/ -void BmpDetect() +void BmpDetect(void) { if (bmp_count) return; @@ -456,7 +456,7 @@ void BmpDetect() } } -void BmpRead() +void BmpRead(void) { for (byte bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { switch (bmp_sensors[bmp_idx].bmp_type) { @@ -477,7 +477,7 @@ void BmpRead() SetGlobalValues(ConvertTemp(bmp_sensors[0].bmp_temperature), bmp_sensors[0].bmp_humidity); } -void BmpEverySecond() +void BmpEverySecond(void) { if (91 == (uptime %100)) { // 1mS diff --git a/sonoff/xsns_10_bh1750.ino b/sonoff/xsns_10_bh1750.ino index 2cdc9bcbd..c93a3513f 100644 --- a/sonoff/xsns_10_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -39,7 +39,7 @@ uint8_t bh1750_valid = 0; uint16_t bh1750_illuminance = 0; char bh1750_types[] = "BH1750"; -bool Bh1750Read() +bool Bh1750Read(void) { if (bh1750_valid) { bh1750_valid--; } @@ -53,7 +53,7 @@ bool Bh1750Read() /********************************************************************************************/ -void Bh1750Detect() +void Bh1750Detect(void) { if (bh1750_type) { return; @@ -72,7 +72,7 @@ void Bh1750Detect() } } -void Bh1750EverySecond() +void Bh1750EverySecond(void) { if (90 == (uptime %100)) { // 1mS diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index 06da4acd4..d07831725 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -157,7 +157,7 @@ int16_t Ads1115GetConversion(uint8_t channel) /********************************************************************************************/ -void Ads1115Detect() +void Ads1115Detect(void) { uint16_t buffer; diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/sonoff/xsns_12_ads1115_i2cdev.ino index dcfab91c7..96c2f7006 100644 --- a/sonoff/xsns_12_ads1115_i2cdev.ino +++ b/sonoff/xsns_12_ads1115_i2cdev.ino @@ -75,7 +75,7 @@ int16_t Ads1115GetConversion(byte channel) /********************************************************************************************/ -void Ads1115Detect() +void Ads1115Detect(void) { if (ads1115_type) { return; diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index 6f0e2c1e9..2ca2f0288 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -128,7 +128,7 @@ bool Ina219SetCalibration(uint8_t mode) return success; } -float Ina219GetShuntVoltage_mV() +float Ina219GetShuntVoltage_mV(void) { // raw shunt voltage (16-bit signed integer, so +-32767) int16_t value = I2cReadS16(ina219_address, INA219_REG_SHUNTVOLTAGE); @@ -136,7 +136,7 @@ float Ina219GetShuntVoltage_mV() return value * 0.01; } -float Ina219GetBusVoltage_V() +float Ina219GetBusVoltage_V(void) { // Shift to the right 3 to drop CNVR and OVF and multiply by LSB // raw bus voltage (16-bit signed integer, so +-32767) @@ -145,7 +145,7 @@ float Ina219GetBusVoltage_V() return value * 0.001; } -float Ina219GetCurrent_mA() +float Ina219GetCurrent_mA(void) { // Sometimes a sharp load will reset the INA219, which will reset the cal register, // meaning CURRENT and POWER will not be available ... avoid this by always setting @@ -159,7 +159,7 @@ float Ina219GetCurrent_mA() return value; } -bool Ina219Read() +bool Ina219Read(void) { ina219_voltage = Ina219GetBusVoltage_V() + (Ina219GetShuntVoltage_mV() / 1000); ina219_current = Ina219GetCurrent_mA() / 1000; @@ -175,7 +175,7 @@ bool Ina219Read() * 2 - Max 16V 0.4A range \*********************************************************************************************/ -bool Ina219CommandSensor() +bool Ina219CommandSensor(void) { boolean serviced = true; @@ -190,7 +190,7 @@ bool Ina219CommandSensor() /********************************************************************************************/ -void Ina219Detect() +void Ina219Detect(void) { if (ina219_type) { return; } @@ -205,7 +205,7 @@ void Ina219Detect() } } -void Ina219EverySecond() +void Ina219EverySecond(void) { if (87 == (uptime %100)) { // 2mS diff --git a/sonoff/xsns_14_sht3x.ino b/sonoff/xsns_14_sht3x.ino index c9b36571b..84bc86be8 100755 --- a/sonoff/xsns_14_sht3x.ino +++ b/sonoff/xsns_14_sht3x.ino @@ -76,7 +76,7 @@ bool Sht3xRead(float &t, float &h, uint8_t sht3x_address) /********************************************************************************************/ -void Sht3xDetect() +void Sht3xDetect(void) { if (sht3x_count) return; diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 5b9817561..21f5d8a15 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -159,7 +159,7 @@ bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) return true; } -void MhzEverySecond() +void MhzEverySecond(void) { mhz_state++; if (8 == mhz_state) { // Every 8 sec start a MH-Z19 measuring cycle (which takes 1005 +5% ms) @@ -253,7 +253,7 @@ void MhzEverySecond() * 9 - Reset \*********************************************************************************************/ -bool MhzCommandSensor() +bool MhzCommandSensor(void) { boolean serviced = true; @@ -275,7 +275,7 @@ bool MhzCommandSensor() /*********************************************************************************************/ -void MhzInit() +void MhzInit(void) { mhz_type = 0; if ((pin[GPIO_MHZ_RXD] < 99) && (pin[GPIO_MHZ_TXD] < 99)) { diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index 8f2884c25..0285c55e0 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -38,7 +38,7 @@ uint8_t tsl2561_valid = 0; uint32_t tsl2561_milliLux = 0; char tsl2561_types[] = "TSL2561"; -bool Tsl2561Read() +bool Tsl2561Read(void) { if (tsl2561_valid) { tsl2561_valid--; } @@ -63,7 +63,7 @@ bool Tsl2561Read() return true; } -void Tsl2561Detect() +void Tsl2561Detect(void) { if (tsl2561_type) { return; } @@ -77,7 +77,7 @@ void Tsl2561Detect() } } -void Tsl2561EverySecond() +void Tsl2561EverySecond(void) { if (90 == (uptime %100)) { // 1mS diff --git a/sonoff/xsns_17_senseair.ino b/sonoff/xsns_17_senseair.ino index 7a2060dd9..04360457f 100644 --- a/sonoff/xsns_17_senseair.ino +++ b/sonoff/xsns_17_senseair.ino @@ -58,7 +58,7 @@ const uint8_t start_addresses[] { 0x1A, 0x00, 0x03, 0x04, 0x05, 0x1C, 0x0A }; uint8_t senseair_read_state = 0; uint8_t senseair_send_retry = 0; -void Senseair250ms() // Every 250 mSec +void Senseair250ms(void) // Every 250 mSec { // senseair_state++; // if (6 == senseair_state) { // Every 300 mSec @@ -132,7 +132,7 @@ void Senseair250ms() // Every 250 mSec /*********************************************************************************************/ -void SenseairInit() +void SenseairInit(void) { senseair_type = 0; if ((pin[GPIO_SAIR_RX] < 99) && (pin[GPIO_SAIR_TX] < 99)) { diff --git a/sonoff/xsns_18_pms5003.ino b/sonoff/xsns_18_pms5003.ino index ec605cf46..271b94301 100644 --- a/sonoff/xsns_18_pms5003.ino +++ b/sonoff/xsns_18_pms5003.ino @@ -45,7 +45,7 @@ struct pms5003data { /*********************************************************************************************/ -boolean PmsReadData() +boolean PmsReadData(void) { if (! PmsSerial->available()) { return false; @@ -87,7 +87,7 @@ boolean PmsReadData() /*********************************************************************************************/ -void PmsSecond() // Every second +void PmsSecond(void) // Every second { if (PmsReadData()) { pms_valid = 10; @@ -100,7 +100,7 @@ void PmsSecond() // Every second /*********************************************************************************************/ -void PmsInit() +void PmsInit(void) { pms_type = 0; if (pin[GPIO_PMS5003] < 99) { diff --git a/sonoff/xsns_19_mgs.ino b/sonoff/xsns_19_mgs.ino index 75fbea5b8..a9fdf7d9e 100644 --- a/sonoff/xsns_19_mgs.ino +++ b/sonoff/xsns_19_mgs.ino @@ -34,11 +34,11 @@ #include "MutichannelGasSensor.h" -void MGSInit() { +void MGSInit(void) { gas.begin(MGS_SENSOR_ADDR); } -boolean MGSPrepare() +boolean MGSPrepare(void) { gas.begin(MGS_SENSOR_ADDR); if (!gas.isError()) { diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index c100c6ad6..aa6242619 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -48,7 +48,7 @@ struct sds011data { uint16_t pm25; } novasds_data; -void NovaSdsSetWorkPeriod() +void NovaSdsSetWorkPeriod(void) { while (NovaSdsSerial->available() > 0) { @@ -73,7 +73,7 @@ void NovaSdsSetWorkPeriod() } } -bool NovaSdsReadData() +bool NovaSdsReadData(void) { if (! NovaSdsSerial->available()) return false; @@ -104,7 +104,7 @@ bool NovaSdsReadData() /*********************************************************************************************/ -void NovaSdsSecond() // Every second +void NovaSdsSecond(void) // Every second { if (XSNS_20 == (uptime % 100)) { if (!novasds_valid) { @@ -123,7 +123,7 @@ void NovaSdsSecond() // Every second /*********************************************************************************************/ -void NovaSdsInit() +void NovaSdsInit(void) { novasds_type = 0; if (pin[GPIO_SDS0X1_RX] < 99 && pin[GPIO_SDS0X1_TX] < 99) { diff --git a/sonoff/xsns_21_sgp30.ino b/sonoff/xsns_21_sgp30.ino index ff6cbb749..7c22da514 100644 --- a/sonoff/xsns_21_sgp30.ino +++ b/sonoff/xsns_21_sgp30.ino @@ -38,7 +38,7 @@ uint8_t sgp30_counter = 0; /********************************************************************************************/ -void Sgp30Update() // Perform every second to ensure proper operation of the baseline compensation algorithm +void Sgp30Update(void) // Perform every second to ensure proper operation of the baseline compensation algorithm { sgp30_ready = 0; if (!sgp30_type) { diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index 118a37cc0..b361b7e96 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -46,7 +46,7 @@ uint8_t sr04_trig_pin = 0; /********************************************************************************************/ -void Sr04Init() +void Sr04Init(void) { sr04_echo_pin = pin[GPIO_SR04_ECHO]; sr04_trig_pin = pin[GPIO_SR04_TRIG]; diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino index 5c2dfa630..a5d47ec67 100644 --- a/sonoff/xsns_23_sdm120.ino +++ b/sonoff/xsns_23_sdm120.ino @@ -43,7 +43,7 @@ float sdm120_power_factor = 0; float sdm120_frequency = 0; float sdm120_energy_total = 0; -bool SDM120_ModbusReceiveReady() +bool SDM120_ModbusReceiveReady(void) { return (SDM120Serial->available() > 1); } @@ -137,7 +137,7 @@ const uint16_t sdm120_start_addresses[] { uint8_t sdm120_read_state = 0; uint8_t sdm120_send_retry = 0; -void SDM120250ms() // Every 250 mSec +void SDM120250ms(void) // Every 250 mSec { // sdm120_state++; // if (6 == sdm120_state) { // Every 300 mSec @@ -203,7 +203,7 @@ void SDM120250ms() // Every 250 mSec // } // end 300 ms } -void SDM120Init() +void SDM120Init(void) { sdm120_type = 0; if ((pin[GPIO_SDM120_RX] < 99) && (pin[GPIO_SDM120_TX] < 99)) { diff --git a/sonoff/xsns_24_si1145.ino b/sonoff/xsns_24_si1145.ino index d84eef62f..7b051ebe0 100644 --- a/sonoff/xsns_24_si1145.ino +++ b/sonoff/xsns_24_si1145.ino @@ -210,12 +210,12 @@ uint8_t Si1145WriteParamData(uint8_t p, uint8_t v) /********************************************************************************************/ -bool Si1145Present() +bool Si1145Present(void) { return (Si1145ReadByte(SI114X_PART_ID) == 0X45); } -void Si1145Reset() +void Si1145Reset(void) { Si1145WriteByte(SI114X_MEAS_RATE0, 0); Si1145WriteByte(SI114X_MEAS_RATE1, 0); @@ -231,7 +231,7 @@ void Si1145Reset() delay(10); } -void Si1145DeInit() +void Si1145DeInit(void) { //ENABLE UV reading //these reg must be set to the fixed value @@ -276,7 +276,7 @@ void Si1145DeInit() Si1145WriteByte(SI114X_COMMAND, SI114X_PSALS_AUTO); } -boolean Si1145Begin() +boolean Si1145Begin(void) { if (!Si1145Present()) { return false; } @@ -286,26 +286,26 @@ boolean Si1145Begin() } // returns the UV index * 100 (divide by 100 to get the index) -uint16_t Si1145ReadUV() +uint16_t Si1145ReadUV(void) { return Si1145ReadHalfWord(SI114X_AUX_DATA0_UVINDEX0); } // returns visible+IR light levels -uint16_t Si1145ReadVisible() +uint16_t Si1145ReadVisible(void) { return Si1145ReadHalfWord(SI114X_ALS_VIS_DATA0); } // returns IR light levels -uint16_t Si1145ReadIR() +uint16_t Si1145ReadIR(void) { return Si1145ReadHalfWord(SI114X_ALS_IR_DATA0); } /********************************************************************************************/ -void Si1145Update() +void Si1145Update(void) { if (!si1145_type) { if (Si1145Begin()) { diff --git a/sonoff/xsns_25_sdm630.ino b/sonoff/xsns_25_sdm630.ino index 8c5e556fc..39614efc5 100644 --- a/sonoff/xsns_25_sdm630.ino +++ b/sonoff/xsns_25_sdm630.ino @@ -41,7 +41,7 @@ float sdm630_reactive_power[] = {0,0,0}; float sdm630_power_factor[] = {0,0,0}; float sdm630_energy_total = 0; -bool SDM630_ModbusReceiveReady() +bool SDM630_ModbusReceiveReady(void) { return (SDM630Serial->available() > 1); } @@ -143,7 +143,7 @@ const uint16_t sdm630_start_addresses[] { uint8_t sdm630_read_state = 0; uint8_t sdm630_send_retry = 0; -void SDM630250ms() // Every 250 mSec +void SDM630250ms(void) // Every 250 mSec { // sdm630_state++; // if (6 == sdm630_state) { // Every 300 mSec @@ -241,7 +241,7 @@ void SDM630250ms() // Every 250 mSec // } // end 300 ms } -void SDM630Init() +void SDM630Init(void) { sdm630_type = 0; if ((pin[GPIO_SDM630_RX] < 99) && (pin[GPIO_SDM630_TX] < 99)) { diff --git a/sonoff/xsns_27_apds9960.ino b/sonoff/xsns_27_apds9960.ino index 1b99e4304..ad009c131 100644 --- a/sonoff/xsns_27_apds9960.ino +++ b/sonoff/xsns_27_apds9960.ino @@ -351,7 +351,7 @@ int8_t wireReadDataBlock( uint8_t reg, * Kelvin */ -void calculateColorTemperature() +void calculateColorTemperature(void) { float X, Y, Z; /* RGB to XYZ correlation */ float xc, yc; /* Chromaticity co-ordinates */ @@ -398,7 +398,7 @@ float powf(const float x, const float y) * * @return lower threshold */ - uint8_t getProxIntLowThresh() + uint8_t getProxIntLowThresh(void) { uint8_t val; @@ -422,7 +422,7 @@ float powf(const float x, const float y) * * @return high threshold */ - uint8_t getProxIntHighThresh() + uint8_t getProxIntHighThresh(void) { uint8_t val; @@ -454,7 +454,7 @@ float powf(const float x, const float y) * * @return the value of the LED drive strength. 0xFF on failure. */ - uint8_t getLEDDrive() + uint8_t getLEDDrive(void) { uint8_t val; @@ -506,7 +506,7 @@ float powf(const float x, const float y) * * @return the value of the proximity gain. 0xFF on failure. */ - uint8_t getProximityGain() + uint8_t getProximityGain(void) { uint8_t val; @@ -597,7 +597,7 @@ float powf(const float x, const float y) * * @return The LED boost value. 0xFF on failure. */ - uint8_t getLEDBoost() + uint8_t getLEDBoost(void) { uint8_t val; @@ -642,7 +642,7 @@ float powf(const float x, const float y) * * @return 1 if compensation is enabled. 0 if not. 0xFF on error. */ - uint8_t getProxGainCompEnable() + uint8_t getProxGainCompEnable(void) { uint8_t val; @@ -689,7 +689,7 @@ float powf(const float x, const float y) * * @return Current proximity mask for photodiodes. 0xFF on error. */ - uint8_t getProxPhotoMask() + uint8_t getProxPhotoMask(void) { uint8_t val; @@ -735,7 +735,7 @@ float powf(const float x, const float y) * * @return Current entry proximity threshold. */ - uint8_t getGestureEnterThresh() + uint8_t getGestureEnterThresh(void) { uint8_t val; @@ -761,7 +761,7 @@ float powf(const float x, const float y) * * @return Current exit proximity threshold. */ - uint8_t getGestureExitThresh() + uint8_t getGestureExitThresh(void) { uint8_t val; @@ -792,7 +792,7 @@ float powf(const float x, const float y) * * @return the current photodiode gain. 0xFF on error. */ - uint8_t getGestureGain() + uint8_t getGestureGain(void) { uint8_t val; @@ -844,7 +844,7 @@ float powf(const float x, const float y) * * @return the LED drive current value. 0xFF on error. */ - uint8_t getGestureLEDDrive() + uint8_t getGestureLEDDrive(void) { uint8_t val; @@ -900,7 +900,7 @@ float powf(const float x, const float y) * * @return the current wait time between gestures. 0xFF on error. */ - uint8_t getGestureWaitTime() + uint8_t getGestureWaitTime(void) { uint8_t val; @@ -1087,7 +1087,7 @@ float powf(const float x, const float y) * * @return 1 if interrupts are enabled, 0 if not. 0xFF on error. */ - uint8_t getAmbientLightIntEnable() + uint8_t getAmbientLightIntEnable(void) { uint8_t val; @@ -1127,7 +1127,7 @@ float powf(const float x, const float y) * * @return 1 if interrupts are enabled, 0 if not. 0xFF on error. */ - uint8_t getProximityIntEnable() + uint8_t getProximityIntEnable(void) { uint8_t val; @@ -1167,7 +1167,7 @@ float powf(const float x, const float y) * * @return 1 if interrupts are enabled, 0 if not. 0xFF on error. */ - uint8_t getGestureIntEnable() + uint8_t getGestureIntEnable(void) { uint8_t val; @@ -1206,7 +1206,7 @@ float powf(const float x, const float y) * @brief Clears the ambient light interrupt * */ - void clearAmbientLightInt() + void clearAmbientLightInt(void) { uint8_t throwaway; throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AICLEAR); @@ -1216,7 +1216,7 @@ float powf(const float x, const float y) * @brief Clears the proximity interrupt * */ - void clearProximityInt() + void clearProximityInt(void) { uint8_t throwaway; throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PICLEAR) ; @@ -1228,7 +1228,7 @@ float powf(const float x, const float y) * * @return 1 if gesture state machine is running, 0 if not. 0xFF on error. */ - uint8_t getGestureMode() + uint8_t getGestureMode(void) { uint8_t val; @@ -1263,7 +1263,7 @@ float powf(const float x, const float y) } -bool APDS9960_init() +bool APDS9960_init(void) { /* Set default values for ambient light and proximity registers */ @@ -1339,7 +1339,7 @@ bool APDS9960_init() * * @return Contents of the ENABLE register. 0xFF if error. */ -uint8_t getMode() +uint8_t getMode(void) { uint8_t enable_value; @@ -1388,7 +1388,7 @@ void setMode(uint8_t mode, uint8_t enable) * * no interrupts */ -void enableLightSensor() +void enableLightSensor(void) { /* Set default gain, interrupts, enable power, and enable sensor */ setAmbientLightGain(DEFAULT_AGAIN); @@ -1401,7 +1401,7 @@ void enableLightSensor() * @brief Ends the light sensor on the APDS-9960 * */ -void disableLightSensor() +void disableLightSensor(void) { setAmbientLightIntEnable(0) ; setMode(AMBIENT_LIGHT, 0) ; @@ -1412,7 +1412,7 @@ void disableLightSensor() * * no interrupts */ -void enableProximitySensor() +void enableProximitySensor(void) { /* Set default gain, LED, interrupts, enable power, and enable sensor */ setProximityGain(DEFAULT_PGAIN); @@ -1426,7 +1426,7 @@ void enableProximitySensor() * @brief Ends the proximity sensor on the APDS-9960 * */ -void disableProximitySensor() +void disableProximitySensor(void) { setProximityIntEnable(0) ; setMode(PROXIMITY, 0) ; @@ -1437,7 +1437,7 @@ void disableProximitySensor() * * no interrupts */ -void enableGestureSensor() +void enableGestureSensor(void) { /* Enable gesture mode Set ENABLE to 0 (power off) @@ -1462,7 +1462,7 @@ void enableGestureSensor() * @brief Ends the gesture recognition engine on the APDS-9960 * */ -void disableGestureSensor() +void disableGestureSensor(void) { resetGestureParameters(); setGestureIntEnable(0) ; @@ -1475,7 +1475,7 @@ void disableGestureSensor() * * @return True if gesture available. False otherwise. */ -bool isGestureAvailable() +bool isGestureAvailable(void) { uint8_t val; @@ -1498,7 +1498,7 @@ bool isGestureAvailable() * * @return Number corresponding to gesture. -1 on error. */ -int16_t readGesture() +int16_t readGesture(void) { uint8_t fifo_level = 0; uint8_t bytes_read = 0; @@ -1585,7 +1585,7 @@ int16_t readGesture() * Turn the APDS-9960 on * */ -void enablePower() +void enablePower(void) { setMode(POWER, 1) ; } @@ -1594,7 +1594,7 @@ void enablePower() * Turn the APDS-9960 off * */ -void disablePower() +void disablePower(void) { setMode(POWER, 0) ; } @@ -1608,7 +1608,7 @@ void disablePower() * */ -void readAllColorAndProximityData() +void readAllColorAndProximityData(void) { if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9)) { @@ -1624,7 +1624,7 @@ void readAllColorAndProximityData() /** * @brief Resets all the parameters in the gesture data member */ -void resetGestureParameters() +void resetGestureParameters(void) { gesture_data_.index = 0; gesture_data_.total_gestures = 0; @@ -1644,7 +1644,7 @@ void resetGestureParameters() * * @return True if near or far state seen. False otherwise. */ -bool processGestureData() +bool processGestureData(void) { uint8_t u_first = 0; uint8_t d_first = 0; @@ -1748,7 +1748,7 @@ bool processGestureData() * * @return True if near/far event. False otherwise. */ -bool decodeGesture() +bool decodeGesture(void) { /* Determine swipe direction */ @@ -1791,7 +1791,7 @@ bool decodeGesture() return true; } -void handleGesture() { +void handleGesture(void) { if (isGestureAvailable() ) { char log[LOGSZ]; switch (readGesture()) { @@ -1870,7 +1870,7 @@ void APDS9960_adjustATime(void) // not really used atm } -void APDS9960_loop() +void APDS9960_loop(void) { if (recovery_loop_counter > 0){ recovery_loop_counter -= 1; @@ -1993,7 +1993,7 @@ void APDS9960_show(boolean json) * Sensor27 | 2 / On | Enable gesture mode with half gain \*********************************************************************************************/ -bool APDS9960CommandSensor() +bool APDS9960CommandSensor(void) { boolean serviced = true; diff --git a/sonoff/xsns_28_tm1638.ino b/sonoff/xsns_28_tm1638.ino index 7dd62d2b5..61852b40d 100644 --- a/sonoff/xsns_28_tm1638.ino +++ b/sonoff/xsns_28_tm1638.ino @@ -72,7 +72,7 @@ void TM16XXSendData(byte address, byte data) digitalWrite(tm1638_strobe_pin, HIGH); } -byte Tm16XXReceive() +byte Tm16XXReceive(void) { byte temp = 0; @@ -96,7 +96,7 @@ byte Tm16XXReceive() /*********************************************************************************************/ -void Tm16XXClearDisplay() +void Tm16XXClearDisplay(void) { for (int i = 0; i < tm1638_displays; i++) { TM16XXSendData(i << 1, 0); @@ -125,7 +125,7 @@ void Tm1638SetLEDs(word leds) } } -byte Tm1638GetButtons() +byte Tm1638GetButtons(void) { byte keys = 0; @@ -141,7 +141,7 @@ byte Tm1638GetButtons() /*********************************************************************************************/ -void TmInit() +void TmInit(void) { tm1638_type = 0; if ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99)) { @@ -171,7 +171,7 @@ void TmInit() } } -void TmLoop() +void TmLoop(void) { if (tm1638_state) { byte buttons = Tm1638GetButtons(); diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index 93bda1a4f..624dac34e 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -42,7 +42,7 @@ uint8_t ecnt = 0; /********************************************************************************************/ #define EVERYNSECONDS 5 -void CCS811Update() // Perform every n second +void CCS811Update(void) // Perform every n second { tcnt++; if (tcnt >= EVERYNSECONDS) { diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index c41549775..795405688 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -45,7 +45,7 @@ int16_t MPU_6050_temperature = 0; #include MPU6050 mpu6050; -void MPU_6050PerformReading() +void MPU_6050PerformReading(void) { mpu6050.getMotion6( &MPU_6050_ax, @@ -75,7 +75,7 @@ void MPU_6050SetAccelOffsets(int x, int y, int z) } */ -void MPU_6050Detect() +void MPU_6050Detect(void) { if (MPU_6050_found) { diff --git a/sonoff/xsns_33_ds3231.ino b/sonoff/xsns_33_ds3231.ino index bc5c4ba3b..48cb12553 100644 --- a/sonoff/xsns_33_ds3231.ino +++ b/sonoff/xsns_33_ds3231.ino @@ -69,7 +69,7 @@ boolean DS3231chipDetected; /*----------------------------------------------------------------------* Detect the DS3231 Chip ----------------------------------------------------------------------*/ -boolean DS3231Detect() +boolean DS3231Detect(void) { if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) { @@ -104,7 +104,7 @@ uint8_t dec2bcd(uint8_t n) /*----------------------------------------------------------------------* Read time from DS3231 and return the epoch time (second since 1-1-1970 00:00) ----------------------------------------------------------------------*/ -uint32_t ReadFromDS3231() +uint32_t ReadFromDS3231(void) { TIME_T tm; tm.second = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_SECONDS)); diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index e46f1d445..0382efc12 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -116,7 +116,7 @@ long HxRead() /*********************************************************************************************/ -void HxReset() +void HxReset(void) { hx_tare_flg = 1; hx_sum_weight = 0; @@ -149,7 +149,7 @@ void HxCalibrationStateTextJson(uint8_t msg_id) * Sensor34 6 - Set item weight \*********************************************************************************************/ -bool HxCommand() +bool HxCommand(void) { bool serviced = true; bool show_parms = false; @@ -220,7 +220,7 @@ long HxWeight() return (hx_calibrate_step < HX_CAL_FAIL) ? hx_weight : 0; } -void HxInit() +void HxInit(void) { hx_type = 0; if ((pin[GPIO_HX711_DAT] < 99) && (pin[GPIO_HX711_SCK] < 99)) { @@ -245,7 +245,7 @@ void HxInit() } } -void HxEvery100mSecond() +void HxEvery100mSecond(void) { hx_sum_weight += HxRead(); @@ -391,7 +391,7 @@ const char HTTP_FORM_HX711[] PROGMEM = "" "
          " D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

          "; -void HandleHxAction() +void HandleHxAction(void) { if (HttpUser()) { return; } if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } @@ -440,7 +440,7 @@ void HandleHxAction() ShowPage(page); } -void HxSaveSettings() +void HxSaveSettings(void) { char tmp[100]; @@ -450,7 +450,7 @@ void HxSaveSettings() HxLogUpdates(); } -void HxLogUpdates() +void HxLogUpdates(void) { char weigth_ref_chr[10]; char weigth_item_chr[10]; diff --git a/sonoff/xsns_35_tx20.ino b/sonoff/xsns_35_tx20.ino index 91a80ba81..8ab868b45 100644 --- a/sonoff/xsns_35_tx20.ino +++ b/sonoff/xsns_35_tx20.ino @@ -80,7 +80,7 @@ uint8_t tx20_wind_direction = 0; boolean tx20_available = false; -void Tx20StartRead() +void Tx20StartRead(void) { /* La Crosse TX20 Anemometer datagram every 2 seconds * 0-0 11011 0011 111010101111 0101 1100 000101010000 0-0 - Received pin data at 1200 uSec per bit @@ -146,7 +146,7 @@ void Tx20StartRead() GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX20_TXD_BLACK]); } -void Tx20Read() +void Tx20Read(void) { if (!(uptime % TX20_RESET_VALUES)) { tx20_count = 0; @@ -165,7 +165,7 @@ void Tx20Read() } } -void Tx20Init() { +void Tx20Init(void) { pinMode(pin[GPIO_TX20_TXD_BLACK], INPUT); attachInterrupt(pin[GPIO_TX20_TXD_BLACK], Tx20StartRead, RISING); } diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index 723e8f070..7b5002c88 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -542,7 +542,7 @@ boolean XsnsPresent(byte sns_index) return false; } -String XsnsGetSensors() +String XsnsGetSensors(void) { char state[2] = { 0 }; From d5f3b8483cba04d7f622aac636a7d72ebd9dabe1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 15 Nov 2018 14:24:19 +0100 Subject: [PATCH 0487/2222] Extent log buffer to 520 characters * Extent log buffer to accomodate up to 8 DS18B20 sensors http JSON data (#4354) * Fix APDS9960 sensor use of log buffer --- sonoff/sonoff.h | 2 +- sonoff/xsns_27_apds9960.ino | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index d13460e64..d66ccf218 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -119,7 +119,7 @@ typedef unsigned long power_t; // Power (Relay) type #define INPUT_BUFFER_SIZE 520 // Max number of characters in (serial and http) command buffer #define CMDSZ 24 // Max number of characters in command #define TOPSZ 100 // Max number of characters in topic string -#define LOGSZ 512 // Max number of characters in log +#define LOGSZ 520 // Max number of characters in log #define MIN_MESSZ 893 // Min number of characters in MQTT message #define SENSOR_MAX_MISS 5 // Max number of missed sensor reads before deciding it's offline diff --git a/sonoff/xsns_27_apds9960.ino b/sonoff/xsns_27_apds9960.ino index ad009c131..33b98a5d2 100644 --- a/sonoff/xsns_27_apds9960.ino +++ b/sonoff/xsns_27_apds9960.ino @@ -1518,9 +1518,8 @@ int16_t readGesture(void) if (gesture_loop_counter == APDS9960_MAX_GESTURE_CYCLES){ // We will escape after a few loops disableGestureSensor(); // stop the sensor to prevent problems with power consumption/blocking and return to the main loop APDS9960_overload = true; // we report this as "long"-gesture - char log[LOGSZ]; - snprintf_P(log, sizeof(log), PSTR("Sensor overload")); - AddLog_P(LOG_LEVEL_DEBUG, log); + snprintf_P(log_data, sizeof(log_data), PSTR("Sensor overload")); + AddLog(LOG_LEVEL_DEBUG); } gesture_loop_counter += 1; /* Wait some time to collect next batch of FIFO data */ @@ -1793,36 +1792,35 @@ bool decodeGesture(void) void handleGesture(void) { if (isGestureAvailable() ) { - char log[LOGSZ]; switch (readGesture()) { case DIR_UP: - snprintf_P(log, sizeof(log), PSTR("UP")); + snprintf_P(log_data, sizeof(log_data), PSTR("UP")); snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Up")); break; case DIR_DOWN: - snprintf_P(log, sizeof(log), PSTR("DOWN")); + snprintf_P(log_data, sizeof(log_data), PSTR("DOWN")); snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Down")); break; case DIR_LEFT: - snprintf_P(log, sizeof(log), PSTR("LEFT")); + snprintf_P(log_data, sizeof(log_data), PSTR("LEFT")); snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Left")); break; case DIR_RIGHT: - snprintf_P(log, sizeof(log), PSTR("RIGHT")); + snprintf_P(log_data, sizeof(log_data), PSTR("RIGHT")); snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Right")); break; default: if(APDS9960_overload) { - snprintf_P(log, sizeof(log), PSTR("LONG")); + snprintf_P(log_data, sizeof(log_data), PSTR("LONG")); snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Long")); } else{ - snprintf_P(log, sizeof(log), PSTR("NONE")); + snprintf_P(log_data, sizeof(log_data), PSTR("NONE")); snprintf_P(currentGesture, sizeof(currentGesture), PSTR("None")); } } - AddLog_P(LOG_LEVEL_DEBUG, log); + AddLog(LOG_LEVEL_DEBUG); mqtt_data[0] = '\0'; if (MqttShowSensor()) { @@ -1834,7 +1832,7 @@ void handleGesture(void) { } } -void APDS9960_adjustATime(void) // not really used atm +void APDS9960_adjustATime(void) // not really used atm { //readAllColorAndProximityData(); I2cValidRead16LE(&color_data.a, APDS9960_I2C_ADDR, APDS9960_CDATAL); From 222ec13f8059c49a689e14f825953b7773dc9ee0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 15 Nov 2018 14:41:23 +0100 Subject: [PATCH 0488/2222] Rename MPU6050 library Rename MPU6050 library --- .../Examples/MPU6050_DMP6/MPU6050_DMP6.ino | 0 .../Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde | 0 .../Examples/MPU6050_raw/MPU6050_raw.ino | 0 lib/{MPU6050 => I2Cdevlib-MPU6050}/MPU6050.cpp | 0 lib/{MPU6050 => I2Cdevlib-MPU6050}/MPU6050.h | 0 lib/{MPU6050 => I2Cdevlib-MPU6050}/MPU6050_6Axis_MotionApps20.h | 0 lib/{MPU6050 => I2Cdevlib-MPU6050}/MPU6050_9Axis_MotionApps41.h | 0 lib/{MPU6050 => I2Cdevlib-MPU6050}/helper_3dmath.h | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename lib/{MPU6050 => I2Cdevlib-MPU6050}/Examples/MPU6050_DMP6/MPU6050_DMP6.ino (100%) rename lib/{MPU6050 => I2Cdevlib-MPU6050}/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde (100%) rename lib/{MPU6050 => I2Cdevlib-MPU6050}/Examples/MPU6050_raw/MPU6050_raw.ino (100%) rename lib/{MPU6050 => I2Cdevlib-MPU6050}/MPU6050.cpp (100%) rename lib/{MPU6050 => I2Cdevlib-MPU6050}/MPU6050.h (100%) rename lib/{MPU6050 => I2Cdevlib-MPU6050}/MPU6050_6Axis_MotionApps20.h (100%) rename lib/{MPU6050 => I2Cdevlib-MPU6050}/MPU6050_9Axis_MotionApps41.h (100%) rename lib/{MPU6050 => I2Cdevlib-MPU6050}/helper_3dmath.h (100%) diff --git a/lib/MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino b/lib/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino similarity index 100% rename from lib/MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino rename to lib/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino diff --git a/lib/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde b/lib/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde similarity index 100% rename from lib/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde rename to lib/I2Cdevlib-MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde diff --git a/lib/MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino b/lib/I2Cdevlib-MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino similarity index 100% rename from lib/MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino rename to lib/I2Cdevlib-MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino diff --git a/lib/MPU6050/MPU6050.cpp b/lib/I2Cdevlib-MPU6050/MPU6050.cpp similarity index 100% rename from lib/MPU6050/MPU6050.cpp rename to lib/I2Cdevlib-MPU6050/MPU6050.cpp diff --git a/lib/MPU6050/MPU6050.h b/lib/I2Cdevlib-MPU6050/MPU6050.h similarity index 100% rename from lib/MPU6050/MPU6050.h rename to lib/I2Cdevlib-MPU6050/MPU6050.h diff --git a/lib/MPU6050/MPU6050_6Axis_MotionApps20.h b/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h similarity index 100% rename from lib/MPU6050/MPU6050_6Axis_MotionApps20.h rename to lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h diff --git a/lib/MPU6050/MPU6050_9Axis_MotionApps41.h b/lib/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h similarity index 100% rename from lib/MPU6050/MPU6050_9Axis_MotionApps41.h rename to lib/I2Cdevlib-MPU6050/MPU6050_9Axis_MotionApps41.h diff --git a/lib/MPU6050/helper_3dmath.h b/lib/I2Cdevlib-MPU6050/helper_3dmath.h similarity index 100% rename from lib/MPU6050/helper_3dmath.h rename to lib/I2Cdevlib-MPU6050/helper_3dmath.h From 877771c90a4b5b40938d8a2fddd809d995183001 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 15 Nov 2018 14:55:45 +0100 Subject: [PATCH 0489/2222] 6.3.0.8 Stop enforcing dout 6.3.0.8 20181115 * Stop enforcing flashmode dout. Still mandatory but this a chk for possible future flash corruption --- sonoff/_changelog.ino | 6 +++++- sonoff/sonoff.ino | 2 +- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_webserver.ino | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index cc698a386..a07a74af0 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,9 +1,13 @@ -/* 6.3.0.7 20181111 +/* 6.3.0.8 20181115 + * Stop enforcing flashmode dout. Still mandatory but this a chk for possible future flash corruption + * + * 6.3.0.7 20181111 * Fix wifi connection errors using wifi disconnect and ESP.reset instead of ESP.restart * Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by Sonoff Basic R2 driver delay implementation (and possibly core bug) * Change command WebSend Host header field from IP address to hostname (#4331) * Add to command WebSend option to send a direct path when command starts with a slash (#4329) * Consolidate LTrim into Trim + * Increase log buffer size from 512 to 520 to accommodate http sensor data (#4354) * * 6.3.0.6 20181110 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ddf73a3c8..4263ffa48 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2117,7 +2117,7 @@ void Every250mSeconds(void) if (90 == ota_state_flag) { // Allow MQTT to reconnect ota_state_flag = 0; if (ota_result) { - SetFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285 +// SetFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285 snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 14eee4f25..9ddcef51c 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06030007 +#define VERSION 0x06030008 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 2c3f85d5e..a55fdd1fa 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1544,7 +1544,7 @@ void HandleUploadLoop(void) upload_error = 4; // Program flash size is larger than real flash size return; } - upload.buf[2] = 3; // Force DOUT - ESP8285 +// upload.buf[2] = 3; // Force DOUT - ESP8285 } } } From 999f0a3f920223c5078f8c30f1a5c56a255bbf39 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 15 Nov 2018 17:29:48 +0100 Subject: [PATCH 0490/2222] Quietly allow settings update Quietly allow settings update to solve issues caused by Reset command leading to unusable device --- sonoff/settings.ino | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 38e9bb3f3..44d1e961f 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -257,7 +257,6 @@ void SettingsSave(byte rotate) * stop_flash_rotate 0 = Allow flash slot rotation (SetOption12 0) * stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1) */ -#ifndef BE_MINIMAL if ((GetSettingsCrc() != settings_crc) || rotate) { if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade) stop_flash_rotate = 1; @@ -290,7 +289,6 @@ void SettingsSave(byte rotate) settings_crc = Settings.cfg_crc; } -#endif // BE_MINIMAL RtcSettingsSave(); } @@ -319,10 +317,8 @@ void SettingsLoad(void) snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %d"), settings_location, Settings.save_flag); AddLog(LOG_LEVEL_DEBUG); -#ifndef BE_MINIMAL if (bad_crc || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { SettingsDefault(); } settings_crc = GetSettingsCrc(); -#endif // BE_MINIMAL RtcSettingsLoad(); } From 8628c54ba03364b1b45715ebce84ebcd42dac84b Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 13 Nov 2018 20:52:12 +0100 Subject: [PATCH 0491/2222] Support abbreviations in discovery message --- sonoff/xdrv_12_home_assistant.ino | 52 +++++++++++++++---------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 91a538292..6258f5aeb 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -23,44 +23,44 @@ const char HASS_DISCOVER_RELAY[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 - "\"command_topic\":\"%s\"," // cmnd/dualr2/POWER2 - "\"state_topic\":\"%s\"," // stat/dualr2/RESULT (implies "\"optimistic\":\"false\",") - "\"value_template\":\"{{value_json.%s}}\"," // POWER2 - "\"payload_off\":\"%s\"," // OFF - "\"payload_on\":\"%s\"," // ON + "\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2 + "\"stat_t\":\"%s\"," // stat/dualr2/RESULT (implies "\"optimistic\":\"false\",") + "\"val_tpl\":\"{{value_json.%s}}\"," // POWER2 + "\"pl_off\":\"%s\"," // OFF + "\"pl_on\":\"%s\"," // ON // "\"optimistic\":\"false\"," // false is Hass default when state_topic is set - "\"availability_topic\":\"%s\"," // tele/dualr2/LWT - "\"payload_available\":\"" D_ONLINE "\"," // Online - "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline + "\"avty_t\":\"%s\"," // tele/dualr2/LWT + "\"pl_avail\":\"" D_ONLINE "\"," // Online + "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline const char HASS_DISCOVER_BUTTON[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 BTN - "\"state_topic\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") + "\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") // "\"value_template\":\"{{value_json.%s}}\"," // POWER2 - "\"payload_on\":\"%s\"," // TOGGLE + "\"pl_on\":\"%s\"," // TOGGLE // "\"optimistic\":\"false\"," // false is Hass default when state_topic is set - "\"availability_topic\":\"%s\"," // tele/dualr2/LWT - "\"payload_available\":\"" D_ONLINE "\"," // Online - "\"payload_not_available\":\"" D_OFFLINE "\"," // Offline - "\"force_update\":true"; + "\"avty_t\":\"%s\"," // tele/dualr2/LWT + "\"pl_avail\":\"" D_ONLINE "\"," // Online + "\"pl_not_avail\":\"" D_OFFLINE "\"," // Offline + "\"frc_upd\":true"; const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = - "%s,\"brightness_command_topic\":\"%s\"," // cmnd/led2/Dimmer - "\"brightness_state_topic\":\"%s\"," // stat/led2/RESULT - "\"brightness_scale\":100," // 100% - "\"on_command_type\":\"brightness\"," // power on (first), power on (last), no power on (brightness) - "\"brightness_value_template\":\"{{value_json." D_CMND_DIMMER "}}\""; + "%s,\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer + "\"bri_stat_t\":\"%s\"," // stat/led2/RESULT + "\"bri_scl\":100," // 100% + "\"on_cmd_type\":\"brightness\"," // power on (first), power on (last), no power on (brightness) + "\"bri_val_tpl\":\"{{value_json." D_CMND_DIMMER "}}\""; const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = - "%s,\"rgb_command_topic\":\"%s2\"," // cmnd/led2/Color2 - "\"rgb_state_topic\":\"%s\"," // stat/led2/RESULT - "\"rgb_value_template\":\"{{value_json." D_CMND_COLOR "}}\""; -// "\"rgb_value_template\":\"{{value_json." D_CMND_COLOR " | join(',')}}\""; + "%s,\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2 + "\"rgb_stat_t\":\"%s\"," // stat/led2/RESULT + "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR "}}\""; +// "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR " | join(',')}}\""; const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = - "%s,\"color_temp_command_topic\":\"%s\"," // cmnd/led2/CT - "\"color_temp_state_topic\":\"%s\"," // stat/led2/RESULT - "\"color_temp_value_template\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; + "%s,\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT + "\"clr_temp_stat_t\":\"%s\"," // stat/led2/RESULT + "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; /* const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = "%s,\"effect_command_topic\":\"%s\"," // cmnd/led2/Scheme From 89b58f62aff627cccfed6e568494de343bd5dc49 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 15 Nov 2018 17:35:02 +0100 Subject: [PATCH 0492/2222] Add option for new Hass discovery feature --- sonoff/settings.h | 2 +- sonoff/xdrv_12_home_assistant.ino | 64 ++++++++++++++++++++++++++----- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index f185004c4..124314f0a 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -68,7 +68,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t time_append_timezone : 1; // bit 2 (v6.2.1.2) uint32_t gui_hostname_ip : 1; // bit 3 (v6.2.1.20) uint32_t tuya_apply_o20 : 1; // bit 4 (v6.3.0.4) - uint32_t spare05 : 1; + uint32_t hass_short_discovery_msg : 1; // bit 5 (vTBD) uint32_t spare06 : 1; uint32_t spare07 : 1; uint32_t spare08 : 1; diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 6258f5aeb..ab48aaf7d 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -22,6 +22,47 @@ #define XDRV_12 12 const char HASS_DISCOVER_RELAY[] PROGMEM = + "{\"name\":\"%s\"," // dualr2 1 + "\"command_topic\":\"%s\"," // cmnd/dualr2/POWER2 + "\"state_topic\":\"%s\"," // stat/dualr2/RESULT (implies "\"optimistic\":\"false\",") + "\"value_template\":\"{{value_json.%s}}\"," // POWER2 + "\"payload_off\":\"%s\"," // OFF + "\"payload_on\":\"%s\"," // ON +// "\"optimistic\":\"false\"," // false is Hass default when state_topic is set + "\"availability_topic\":\"%s\"," // tele/dualr2/LWT + "\"payload_available\":\"" D_ONLINE "\"," // Online + "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline + +const char HASS_DISCOVER_BUTTON[] PROGMEM = + "{\"name\":\"%s\"," // dualr2 1 BTN + "\"state_topic\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") +// "\"value_template\":\"{{value_json.%s}}\"," // POWER2 + "\"payload_on\":\"%s\"," // TOGGLE +// "\"optimistic\":\"false\"," // false is Hass default when state_topic is set + "\"availability_topic\":\"%s\"," // tele/dualr2/LWT + "\"payload_available\":\"" D_ONLINE "\"," // Online + "\"payload_not_available\":\"" D_OFFLINE "\"," // Offline + "\"force_update\":true"; + +const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = + "%s,\"brightness_command_topic\":\"%s\"," // cmnd/led2/Dimmer + "\"brightness_state_topic\":\"%s\"," // stat/led2/RESULT + "\"brightness_scale\":100," // 100% + "\"on_command_type\":\"brightness\"," // power on (first), power on (last), no power on (brightness) + "\"brightness_value_template\":\"{{value_json." D_CMND_DIMMER "}}\""; + +const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = + "%s,\"rgb_command_topic\":\"%s2\"," // cmnd/led2/Color2 + "\"rgb_state_topic\":\"%s\"," // stat/led2/RESULT + "\"rgb_value_template\":\"{{value_json." D_CMND_COLOR "}}\""; +// "\"rgb_value_template\":\"{{value_json." D_CMND_COLOR " | join(',')}}\""; + +const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = + "%s,\"color_temp_command_topic\":\"%s\"," // cmnd/led2/CT + "\"color_temp_state_topic\":\"%s\"," // stat/led2/RESULT + "\"color_temp_value_template\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; + +const char HASS_DISCOVER_RELAY_SHORT[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 "\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2 "\"stat_t\":\"%s\"," // stat/dualr2/RESULT (implies "\"optimistic\":\"false\",") @@ -33,7 +74,7 @@ const char HASS_DISCOVER_RELAY[] PROGMEM = "\"pl_avail\":\"" D_ONLINE "\"," // Online "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline -const char HASS_DISCOVER_BUTTON[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SHORT[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 BTN "\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") // "\"value_template\":\"{{value_json.%s}}\"," // POWER2 @@ -44,20 +85,20 @@ const char HASS_DISCOVER_BUTTON[] PROGMEM = "\"pl_not_avail\":\"" D_OFFLINE "\"," // Offline "\"frc_upd\":true"; -const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = +const char HASS_DISCOVER_LIGHT_DIMMER_SHORT[] PROGMEM = "%s,\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer "\"bri_stat_t\":\"%s\"," // stat/led2/RESULT "\"bri_scl\":100," // 100% "\"on_cmd_type\":\"brightness\"," // power on (first), power on (last), no power on (brightness) "\"bri_val_tpl\":\"{{value_json." D_CMND_DIMMER "}}\""; -const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = +const char HASS_DISCOVER_LIGHT_COLOR_SHORT[] PROGMEM = "%s,\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2 "\"rgb_stat_t\":\"%s\"," // stat/led2/RESULT "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR "}}\""; // "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR " | join(',')}}\""; -const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = +const char HASS_DISCOVER_LIGHT_CT_SHORT[] PROGMEM = "%s,\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT "\"clr_temp_stat_t\":\"%s\"," // stat/led2/RESULT "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; @@ -105,19 +146,22 @@ void HAssDiscoverRelay(void) GetTopic_P(command_topic, CMND, mqtt_topic, value_template); GetTopic_P(state_topic, STAT, mqtt_topic, S_RSLT_RESULT); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_RELAY_SHORT:HASS_DISCOVER_RELAY, + name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); if (is_light) { char brightness_command_topic[TOPSZ]; GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_DIMMER, mqtt_data, brightness_command_topic, state_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_DIMMER_SHORT:HASS_DISCOVER_LIGHT_DIMMER, + mqtt_data, brightness_command_topic, state_topic); if (light_subtype >= LST_RGB) { char rgb_command_topic[TOPSZ]; GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_COLOR, mqtt_data, rgb_command_topic, state_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_COLOR_SHORT:HASS_DISCOVER_LIGHT_COLOR, + mqtt_data, rgb_command_topic, state_topic); /* char effect_command_topic[TOPSZ]; @@ -129,7 +173,8 @@ void HAssDiscoverRelay(void) char color_temp_command_topic[TOPSZ]; GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_CT, mqtt_data, color_temp_command_topic, state_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_CT_SHORT:HASS_DISCOVER_LIGHT_CT, + mqtt_data, color_temp_command_topic, state_topic); } } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); @@ -179,7 +224,8 @@ void HAssDiscoverButton(void) GetPowerDevice(value_template, button_index+1, sizeof(value_template), Settings.flag.device_index_enable); GetTopic_P(state_topic, CMND, key_topic, value_template); // State of button is sent as CMND TOGGLE GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON, name, state_topic, Settings.state_text[2], availability_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SHORT:HASS_DISCOVER_BUTTON, + name, state_topic, Settings.state_text[2], availability_topic); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } From 7c2c4edd1f8ab0ef62bd43a93e9104ffbb652ebc Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 15 Nov 2018 17:19:08 +0100 Subject: [PATCH 0493/2222] Add support for topic prefix Also fix announcement of RGB capable light. --- sonoff/xdrv_12_home_assistant.ino | 82 +++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 10 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index ab48aaf7d..d33ed78e0 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -95,7 +95,7 @@ const char HASS_DISCOVER_LIGHT_DIMMER_SHORT[] PROGMEM = const char HASS_DISCOVER_LIGHT_COLOR_SHORT[] PROGMEM = "%s,\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2 "\"rgb_stat_t\":\"%s\"," // stat/led2/RESULT - "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR "}}\""; + "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; // "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR " | join(',')}}\""; const char HASS_DISCOVER_LIGHT_CT_SHORT[] PROGMEM = @@ -109,6 +109,28 @@ const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = "\"effect_value_template\":\"{{value_json." D_CMND_SCHEME "}}\"," "\"effect_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; // string list with reference to scheme parameter. Currently only supports numbers 0 to 11 as it make the mqtt string too long */ +const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM = + "%s, \"~\":\"%s\""; + +static void FindPrefix(char* s1, char* s2, char* out) +{ + int prefixlen = 0; + + while (s1[prefixlen] != '\0' && s2[prefixlen] != '\0' && s1[prefixlen] == s2[prefixlen]) { + prefixlen++; + } + strlcpy(out, s1, prefixlen+1); +} + +static void Shorten(char** s, char *prefix) +{ + size_t len = strlen(*s); + size_t prefixlen = strlen(prefix); + if (len > prefixlen && !strncmp(*s, prefix, prefixlen)) { + *s += prefixlen-1; + *s[0] = '~'; + } +} void HAssDiscoverRelay(void) { @@ -133,9 +155,13 @@ void HAssDiscoverRelay(void) if (Settings.flag.hass_discovery && (i <= devices_present)) { char name[33]; char value_template[33]; - char command_topic[TOPSZ]; - char state_topic[TOPSZ]; - char availability_topic[TOPSZ]; + char _command_topic[TOPSZ]; + char _state_topic[TOPSZ]; + char _availability_topic[TOPSZ]; + char prefix[TOPSZ]; + char *command_topic = _command_topic; + char *state_topic = _state_topic; + char *availability_topic = _availability_topic; if (i > MAX_FRIENDLYNAMES) { snprintf_P(name, sizeof(name), PSTR("%s %d"), Settings.friendlyname[0], i); @@ -146,20 +172,32 @@ void HAssDiscoverRelay(void) GetTopic_P(command_topic, CMND, mqtt_topic, value_template); GetTopic_P(state_topic, STAT, mqtt_topic, S_RSLT_RESULT); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + FindPrefix(command_topic, state_topic, prefix); + if (Settings.flag3.hass_short_discovery_msg) { + Shorten(&command_topic, prefix); + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + } snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_RELAY_SHORT:HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); if (is_light) { - char brightness_command_topic[TOPSZ]; + char _brightness_command_topic[TOPSZ]; + char *brightness_command_topic = _brightness_command_topic; GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); + if (Settings.flag3.hass_short_discovery_msg) + Shorten(&brightness_command_topic, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_DIMMER_SHORT:HASS_DISCOVER_LIGHT_DIMMER, mqtt_data, brightness_command_topic, state_topic); if (light_subtype >= LST_RGB) { - char rgb_command_topic[TOPSZ]; + char _rgb_command_topic[TOPSZ]; + char *rgb_command_topic = _rgb_command_topic; GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); + if (Settings.flag3.hass_short_discovery_msg) + Shorten(&rgb_command_topic, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_COLOR_SHORT:HASS_DISCOVER_LIGHT_COLOR, mqtt_data, rgb_command_topic, state_topic); /* @@ -170,13 +208,18 @@ void HAssDiscoverRelay(void) */ } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { - char color_temp_command_topic[TOPSZ]; + char _color_temp_command_topic[TOPSZ]; + char *color_temp_command_topic = _color_temp_command_topic; GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); + if (Settings.flag3.hass_short_discovery_msg) + Shorten(&color_temp_command_topic, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_CT_SHORT:HASS_DISCOVER_LIGHT_CT, mqtt_data, color_temp_command_topic, state_topic); } } + if (Settings.flag3.hass_short_discovery_msg) + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } MqttPublish(stopic, true); @@ -213,8 +256,11 @@ void HAssDiscoverButton(void) if (Settings.flag.hass_discovery && button_present) { char name[33]; char value_template[33]; - char state_topic[TOPSZ]; - char availability_topic[TOPSZ]; + char _state_topic[TOPSZ]; + char _availability_topic[TOPSZ]; + char prefix[TOPSZ]; + char *state_topic = _state_topic; + char *availability_topic = _availability_topic; if (button_index+1 > MAX_FRIENDLYNAMES) { snprintf_P(name, sizeof(name), PSTR("%s %d BTN"), Settings.friendlyname[0], button_index+1); @@ -224,9 +270,16 @@ void HAssDiscoverButton(void) GetPowerDevice(value_template, button_index+1, sizeof(value_template), Settings.flag.device_index_enable); GetTopic_P(state_topic, CMND, key_topic, value_template); // State of button is sent as CMND TOGGLE GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + FindPrefix(state_topic, availability_topic, prefix); + if (Settings.flag3.hass_short_discovery_msg) { + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + } snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SHORT:HASS_DISCOVER_BUTTON, name, state_topic, Settings.state_text[2], availability_topic); + if (Settings.flag3.hass_short_discovery_msg) + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } MqttPublish(stopic, true); @@ -234,6 +287,14 @@ void HAssDiscoverButton(void) } } +static int string_ends_with(const char * str, const char * suffix) +{ + int str_len = strlen(str); + int suffix_len = strlen(suffix); + + return (str_len >= suffix_len) && (0 == strcmp(str + (str_len-suffix_len), suffix)); +} + void HAssDiscovery(uint8_t mode) { // Configure Tasmota for default Home Assistant parameters to keep discovery message as short as possible @@ -241,7 +302,8 @@ void HAssDiscovery(uint8_t mode) Settings.flag.mqtt_response = 0; // Response always as RESULT and not as uppercase command Settings.flag.decimal_text = 1; // Respond with decimal color values // Settings.light_scheme = 0; // To just control color it needs to be Scheme 0 -// strncpy_P(Settings.mqtt_fulltopic, PSTR("%prefix%/%topic%/"), sizeof(Settings.mqtt_fulltopic)); // Make MQTT topic as short as possible to make this process posible within MQTT_MAX_PACKET_SIZE + if (!string_ends_with(Settings.mqtt_fulltopic, "%prefix%/")) + strncpy_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"), sizeof(Settings.mqtt_fulltopic)); } if (Settings.flag.hass_discovery || (1 == mode)) { From a1ff02933501b10d359b103466481e8863063977 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 16 Nov 2018 09:18:40 +0100 Subject: [PATCH 0494/2222] Revert "Quietly allow settings update" This reverts commit 999f0a3f920223c5078f8c30f1a5c56a255bbf39. --- sonoff/settings.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 44d1e961f..38e9bb3f3 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -257,6 +257,7 @@ void SettingsSave(byte rotate) * stop_flash_rotate 0 = Allow flash slot rotation (SetOption12 0) * stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1) */ +#ifndef BE_MINIMAL if ((GetSettingsCrc() != settings_crc) || rotate) { if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade) stop_flash_rotate = 1; @@ -289,6 +290,7 @@ void SettingsSave(byte rotate) settings_crc = Settings.cfg_crc; } +#endif // BE_MINIMAL RtcSettingsSave(); } @@ -317,8 +319,10 @@ void SettingsLoad(void) snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %d"), settings_location, Settings.save_flag); AddLog(LOG_LEVEL_DEBUG); +#ifndef BE_MINIMAL if (bad_crc || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { SettingsDefault(); } settings_crc = GetSettingsCrc(); +#endif // BE_MINIMAL RtcSettingsLoad(); } From 9eacabc4f02411d32caf72e90018d3dbc0d64b2a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 16 Nov 2018 09:36:41 +0100 Subject: [PATCH 0495/2222] Delay initial flash write * Stop enforcing flashmode dout but it is still mandatory * Moved bootcount update (being first) flash write to 10 seconds after restart --- sonoff/_changelog.ino | 3 ++- sonoff/settings.ino | 2 ++ sonoff/sonoff.ino | 14 +++++++------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index a07a74af0..226fdcec1 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.3.0.8 20181115 - * Stop enforcing flashmode dout. Still mandatory but this a chk for possible future flash corruption + * Stop enforcing flashmode dout but it is still mandatory + * Moved bootcount update (being first) flash write to 10 seconds after restart * * 6.3.0.7 20181111 * Fix wifi connection errors using wifi disconnect and ESP.reset instead of ESP.restart diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 38e9bb3f3..d683eee79 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -334,6 +334,7 @@ void SettingsErase(uint8_t type) 1 = Erase SDK parameter area at end of linker memory model (0x0FDxxx - 0x0FFFFF) solving possible wifi errors */ +#ifndef BE_MINIMAL bool result; uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; @@ -362,6 +363,7 @@ void SettingsErase(uint8_t type) } OsWatchLoop(); } +#endif // BE_MINIMAL } // Copied from 2.4.0 as 2.3.0 is incomplete diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 4263ffa48..d8d6cba1d 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1652,6 +1652,10 @@ void PerformEverySecond(void) if (BOOT_LOOP_TIME == uptime) { RtcReboot.fast_reboot_count = 0; RtcRebootSave(); + + Settings.bootcount++; // Moved to here to stop flash writes during start-up + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); + AddLog(LOG_LEVEL_DEBUG); } if ((4 == uptime) && (SONOFF_IFAN02 == Settings.module)) { // Microcontroller needs 3 seconds before accepting commands @@ -2635,13 +2639,13 @@ void setup(void) mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; seriallog_level = Settings.seriallog_level; seriallog_timer = SERIALLOG_TIMER; -#ifndef USE_EMULATION - Settings.flag2.emulation = 0; -#endif // USE_EMULATION syslog_level = Settings.syslog_level; stop_flash_rotate = Settings.flag.stop_flash_rotate; save_data_counter = Settings.save_data; sleep = Settings.sleep; +#ifndef USE_EMULATION + Settings.flag2.emulation = 0; +#endif // USE_EMULATION // Disable functionality as possible cause of fast restart within BOOT_LOOP_TIME seconds (Exception, WDT or restarts) if (RtcReboot.fast_reboot_count > 1) { // Restart twice @@ -2667,10 +2671,6 @@ void setup(void) 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); - Format(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); Format(mqtt_topic, Settings.mqtt_topic, sizeof(mqtt_topic)); if (strstr(Settings.hostname, "%")) { From c2dfd559ebc0b84025655ca726c2ede3ae780804 Mon Sep 17 00:00:00 2001 From: wvdv2002 Date: Fri, 16 Nov 2018 09:48:55 +0100 Subject: [PATCH 0496/2222] Added user config define to enable armtronix dimmers --- sonoff/my_user_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index e1f6e364a..2145d0458 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -356,6 +356,7 @@ #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) #define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer #define TUYA_DIMMER_ID 0 // Default dimmer Id +#define USE_ARMTRONIX_DIMMERS //Add support for Armtronix Dimmers // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) From 9ab3eb05bd55d8c6576a0228b6b3fca33656975c Mon Sep 17 00:00:00 2001 From: wvdv2002 Date: Fri, 16 Nov 2018 09:53:23 +0100 Subject: [PATCH 0497/2222] Renamed driver so it is more clear that it is not only for the dual dimmer --- ...armtronixDualDimmer.ino => xdrv_18_armtronixDimmers.ino} | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) rename sonoff/{xdrv_18_armtronixDualDimmer.ino => xdrv_18_armtronixDimmers.ino} (98%) diff --git a/sonoff/xdrv_18_armtronixDualDimmer.ino b/sonoff/xdrv_18_armtronixDimmers.ino similarity index 98% rename from sonoff/xdrv_18_armtronixDualDimmer.ino rename to sonoff/xdrv_18_armtronixDimmers.ino index 0e440bd7e..0de7fac77 100644 --- a/sonoff/xdrv_18_armtronixDualDimmer.ino +++ b/sonoff/xdrv_18_armtronixDimmers.ino @@ -1,5 +1,5 @@ /* - xdrv_16_armtronixdimmer.ino - Armtronix dimmer support for Sonoff-Tasmota + xdrv_18_armtronixdimmer.ino - Armtronix dimmers support for Sonoff-Tasmota Copyright (C) 2018 digiblur, Joel Stein and Theo Arends @@ -17,8 +17,6 @@ along with this program. If not, see . */ -#define USE_ARMTRONIX_DIMMERS - #ifdef USE_ARMTRONIX_DIMMERS #define XDRV_18 18 @@ -161,8 +159,6 @@ void ArmtronixSetWifiLed(){ /*********************************************************************************************\ * Interface \*********************************************************************************************/ -bool flip; - boolean Xdrv18(byte function) { boolean result = false; From 45cc387748246798729ced9102ac43c879d95d5f Mon Sep 17 00:00:00 2001 From: wvdv2002 Date: Fri, 16 Nov 2018 09:58:14 +0100 Subject: [PATCH 0498/2222] Added small description in the driver --- sonoff/xdrv_18_armtronixDimmers.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonoff/xdrv_18_armtronixDimmers.ino b/sonoff/xdrv_18_armtronixDimmers.ino index 0de7fac77..9fae00ff0 100644 --- a/sonoff/xdrv_18_armtronixDimmers.ino +++ b/sonoff/xdrv_18_armtronixDimmers.ino @@ -17,6 +17,10 @@ along with this program. If not, see . */ +/*This code can be used for Armtronix dimmers. The dimmers contain a Atmega328 to do the actual dimming. + Checkout the Tasmota Wiki for information on how to flash this Atmega328 with the firmware to work together with this driver. +*/ + #ifdef USE_ARMTRONIX_DIMMERS #define XDRV_18 18 From 04cc11b46d05c8737e562f2e2915fa80b1a43aea Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 16 Nov 2018 10:36:43 +0100 Subject: [PATCH 0499/2222] Use correct index --- sonoff/sonoff.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index d63ce9d35..fb59eac68 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -227,7 +227,7 @@ enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, D enum Ws2812ClockIndex { WS_SECOND, WS_MINUTE, WS_HOUR, WS_MARKER }; 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_SERIAL, LT_SERIAL2, LT_NU9, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC}; +enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_SERIAL, LT_SERIAL2, 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}; From 5d798e3381568e71ade3fdbd244ba6a5f5c96ae4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 16 Nov 2018 10:37:52 +0100 Subject: [PATCH 0500/2222] Make it optional on first implementation --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 2145d0458..8e3050a4e 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -356,7 +356,7 @@ #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) #define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer #define TUYA_DIMMER_ID 0 // Default dimmer Id -#define USE_ARMTRONIX_DIMMERS //Add support for Armtronix Dimmers +//#define USE_ARMTRONIX_DIMMERS //Add support for Armtronix Dimmers // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) From 77e76691b65ab4ba7b425783d350ea6deeaf1ae1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 16 Nov 2018 10:39:57 +0100 Subject: [PATCH 0501/2222] Fix correct module index --- sonoff/sonoff_template.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index be6b18085..f2595c82c 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -250,8 +250,8 @@ enum SupportedModules { TECKIN, APLIC_WDP303075, TUYA_DIMMER, - ARMTRONIX_DIMMERS, GOSUND, + ARMTRONIX_DIMMERS, MAXMODULE }; /********************************************************************************************/ @@ -1220,7 +1220,20 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, 0 }, - { "ARMTR Dimmer", // ARMTRONIX Dimmer, one or two channel (ESP8266 w/ separate MCU dimmer) + { "Gosund SP1_v23", // https://www.amazon.de/gp/product/B0777BWS1P + 0, + GPIO_LED1_INV, // GPIO01 Serial RXD and LED1 (blue) inv + 0, + GPIO_KEY1, // GPIO03 Serial TXD and Button + GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_LED2_INV, // GPIO13 LED2 (red) inv + GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) + 0, 0, 0 + }, + { "ARMTR Dimmer", // ARMTRONIX Dimmer, one or two channel (ESP8266 w/ separate MCU dimmer) // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-two-triac-board/ // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-esp8266-one-triac-board-alexaecho/ GPIO_USER, @@ -1236,19 +1249,6 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, GPIO_USER, 0 - }, - { "Gosund SP1_v23", // https://www.amazon.de/gp/product/B0777BWS1P - 0, - GPIO_LED1_INV, // GPIO01 Serial RXD and LED1 (blue) inv - 0, - GPIO_KEY1, // GPIO03 Serial TXD and Button - GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power - GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage - 0, 0, 0, 0, 0, 0, // Flash connection - GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) - GPIO_LED2_INV, // GPIO13 LED2 (red) inv - GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) - 0, 0, 0 } }; From e284e78b4d526459a3279f9373313b9afec4c1bb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 16 Nov 2018 12:22:15 +0100 Subject: [PATCH 0502/2222] Add support for Armtronix dimmers Add support for Armtronix dimmers. See wiki for info (#4321) --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 2 +- sonoff/sonoff.h | 7 +- sonoff/xdrv_04_light.ino | 28 +++-- sonoff/xdrv_16_tuyadimmer.ino | 2 +- ...mers.ino => xdrv_18_armtronix_dimmers.ino} | 116 +++++++++--------- 6 files changed, 81 insertions(+), 75 deletions(-) rename sonoff/{xdrv_18_armtronixDimmers.ino => xdrv_18_armtronix_dimmers.ino} (67%) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 226fdcec1..3914c426b 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.3.0.8 20181115 * Stop enforcing flashmode dout but it is still mandatory * Moved bootcount update (being first) flash write to 10 seconds after restart + * Add support for Armtronix dimmers. See wiki for info (#4321) * * 6.3.0.7 20181111 * Fix wifi connection errors using wifi disconnect and ESP.reset instead of ESP.restart diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 8e3050a4e..3e0efdef4 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -356,7 +356,7 @@ #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) #define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer #define TUYA_DIMMER_ID 0 // Default dimmer Id -//#define USE_ARMTRONIX_DIMMERS //Add support for Armtronix Dimmers +#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index fb59eac68..5a43e147f 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -227,8 +227,11 @@ enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, D enum Ws2812ClockIndex { WS_SECOND, WS_MINUTE, WS_HOUR, WS_MARKER }; 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_SERIAL, LT_SERIAL2, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC}; -enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC}; + +enum LightSubtypes { LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC }; // Do not insert new fields +enum LightTypes { LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, + LT_NU8, LT_SERIAL1, LT_SERIAL2, LT_WS2812, LT_RGBW, LT_RGBWC, LT_NU14, LT_NU15 }; // Do not insert new fields + enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT, diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 35cda4f97..92e19fb57 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -311,7 +311,10 @@ void LightMy92x1Write(uint8_t data) void LightMy92x1Init(void) { - uint8_t chips = light_type -11; // 1 (AiLight) or 2 (Sonoff B1) + uint8_t chips = 1; // 1 (AiLight) + if (LT_RGBWC == light_type) { + chips = 2; // 2 (Sonoff B1) + } LightDckiPulse(chips * 32); // Clear all duty register os_delay_us(12); // TStop > 12us. @@ -332,7 +335,12 @@ void LightMy92x1Init(void) 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 = light_type -12; // 0 or 1 + + uint8_t didx = 0; // 0 (AiLight) + if (LT_RGBWC == light_type) { + didx = 1; // 1 (Sonoff B1) + } + 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 @@ -352,8 +360,11 @@ void LightInit(void) uint8_t max_scheme = LS_MAX -1; light_device = devices_present; - light_subtype = light_type &7; + light_subtype = light_type &7; // Always 0 - 7 + if (LST_SINGLE == light_subtype) { + Settings.light_color[0] = 255; // One channel only supports Dimmer but needs max color + } if (light_type < LT_PWM6) { // PWM for (byte i = 0; i < light_type; i++) { Settings.pwm_value[i] = 0; // Disable direct PWM control @@ -361,9 +372,6 @@ void LightInit(void) pinMode(pin[GPIO_PWM1 +i], OUTPUT); } } - if (LT_PWM1 == light_type || LT_SERIAL == light_type) { - Settings.light_color[0] = 255; // One PWM channel only supports Dimmer but needs max color - } if (SONOFF_LED == Settings.module) { // Fix Sonoff Led instabilities if (!my_module.gp.io[4]) { pinMode(4, OUTPUT); // Stop floating outputs @@ -393,12 +401,6 @@ void LightInit(void) max_scheme = LS_MAX + WS2812_SCHEMES; } #endif // USE_WS2812 ************************************************************************ - else if (LT_SERIAL == light_type) { - light_subtype = LST_SINGLE; - } - else if (LT_SERIAL2 == light_type) { - light_subtype = LST_COLDWARM; - } else { light_pdi_pin = pin[GPIO_DI]; light_pdcki_pin = pin[GPIO_DCKI]; @@ -830,7 +832,7 @@ void LightAnimate(void) LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); } #ifdef USE_TUYA_DIMMER - if (light_type == LT_SERIAL) { + if (light_type == LT_SERIAL1) { LightSerialDuty(cur_col[0]); } #endif // USE_TUYA_DIMMER diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index 278ef6941..1322da33a 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -276,7 +276,7 @@ boolean TuyaModuleSelected(void) Settings.my_gp.io[3] = GPIO_TUYA_RX; restart_flag = 2; } - light_type = LT_SERIAL; + light_type = LT_SERIAL1; return true; } diff --git a/sonoff/xdrv_18_armtronixDimmers.ino b/sonoff/xdrv_18_armtronix_dimmers.ino similarity index 67% rename from sonoff/xdrv_18_armtronixDimmers.ino rename to sonoff/xdrv_18_armtronix_dimmers.ino index 9fae00ff0..0cab44e1d 100644 --- a/sonoff/xdrv_18_armtronixDimmers.ino +++ b/sonoff/xdrv_18_armtronix_dimmers.ino @@ -1,7 +1,7 @@ /* - xdrv_18_armtronixdimmer.ino - Armtronix dimmers support for Sonoff-Tasmota + xdrv_18_armtronix_dimmers.ino - Armtronix dimmers support for Sonoff-Tasmota - Copyright (C) 2018 digiblur, Joel Stein and Theo Arends + Copyright (C) 2018 wvdv2002 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 @@ -17,11 +17,13 @@ along with this program. If not, see . */ -/*This code can be used for Armtronix dimmers. The dimmers contain a Atmega328 to do the actual dimming. - Checkout the Tasmota Wiki for information on how to flash this Atmega328 with the firmware to work together with this driver. -*/ - #ifdef USE_ARMTRONIX_DIMMERS +/*********************************************************************************************\ + * This code can be used for Armtronix dimmers. + * The dimmers contain a Atmega328 to do the actual dimming. + * Checkout the Tasmota Wiki for information on how to flash this Atmega328 with the firmware + * to work together with this driver. +\*********************************************************************************************/ #define XDRV_18 18 @@ -31,27 +33,24 @@ TasmotaSerial *ArmtronixSerial = nullptr; boolean armtronix_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction int8_t armtronix_wifi_state = -2; // Keep MCU wifi-status in sync with WifiState() -int8_t armtronix_dimState[2]; //Dimmer state values. -int8_t armtronix_knobState[2]; //Dimmer state values. - +int8_t armtronix_dimState[2]; // Dimmer state values. +int8_t armtronix_knobState[2]; // Dimmer state values. /*********************************************************************************************\ * Internal Functions \*********************************************************************************************/ - - void LightSerial2Duty(uint8_t duty1, uint8_t duty2) { if (ArmtronixSerial && !armtronix_ignore_dim) { - duty1 = ((float)duty1)/2.575757; //max 99 - duty2 = ((float)duty2)/2.575757; //max 99 - armtronix_dimState[0] = duty1; - armtronix_dimState[1] = duty2; - ArmtronixSerial->print("Dimmer1:"); - ArmtronixSerial->print(duty1); - ArmtronixSerial->print("\nDimmer2:"); - ArmtronixSerial->println(duty2); + duty1 = ((float)duty1)/2.575757; //max 99 + duty2 = ((float)duty2)/2.575757; //max 99 + armtronix_dimState[0] = duty1; + armtronix_dimState[1] = duty2; + ArmtronixSerial->print("Dimmer1:"); + ArmtronixSerial->print(duty1); + ArmtronixSerial->print("\nDimmer2:"); + ArmtronixSerial->println(duty2); snprintf_P(log_data, sizeof(log_data), PSTR( "ARM: Send Serial Packet Dim Values=%d,%d"), armtronix_dimState[0],armtronix_dimState[1]); AddLog(LOG_LEVEL_DEBUG); @@ -64,13 +63,14 @@ void LightSerial2Duty(uint8_t duty1, uint8_t duty2) } } -void ArmtronixRequestState(){ - if(ArmtronixSerial) { +void ArmtronixRequestState(void) +{ + if (ArmtronixSerial) { // Get current status of MCU snprintf_P(log_data, sizeof(log_data), "TYA: Request MCU state"); AddLog(LOG_LEVEL_DEBUG); ArmtronixSerial->println("Status"); - + } } @@ -78,13 +78,13 @@ void ArmtronixRequestState(){ * API Functions \*********************************************************************************************/ -boolean ArmtronixModuleSelected() +boolean ArmtronixModuleSelected(void) { light_type = LT_SERIAL2; return true; } -void ArmtronixInit() +void ArmtronixInit(void) { armtronix_dimState[0] = -1; armtronix_dimState[1] = -1; @@ -97,21 +97,21 @@ void ArmtronixInit() } } -void ArmtronixSerialInput() +void ArmtronixSerialInput(void) { String answer; int8_t newDimState[2]; uint8_t temp; int commaIndex; - char scmnd[20]; + char scmnd[20]; if (ArmtronixSerial->available()) { yield(); answer = ArmtronixSerial->readStringUntil('\n'); - if(answer.substring(0,7) == "Status:"){ + if (answer.substring(0,7) == "Status:") { commaIndex = 6; - for(int i =0;i<2;i++){ + for (int i =0; i<2; i++) { newDimState[i] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); - if(newDimState[i] != armtronix_dimState[i]){ + if (newDimState[i] != armtronix_dimState[i]) { temp = ((float)newDimState[i])*1.01010101010101; //max 255 armtronix_dimState[i] = newDimState[i]; armtronix_ignore_dim = true; @@ -120,7 +120,7 @@ void ArmtronixSerialInput() snprintf_P(log_data, sizeof(log_data), PSTR("ARM: Send CMND_CHANNEL=%s"), scmnd ); AddLog(LOG_LEVEL_DEBUG); } - commaIndex = answer.indexOf(',',commaIndex+1); + commaIndex = answer.indexOf(',',commaIndex+1); } armtronix_knobState[0] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); commaIndex = answer.indexOf(',',commaIndex+1); @@ -129,40 +129,40 @@ void ArmtronixSerialInput() } } -void ArmtronixSetWifiLed(){ - uint8_t wifi_state = 0x02; - switch(WifiState()){ - case WIFI_SMARTCONFIG: - wifi_state = 0x00; - break; - case WIFI_MANAGER: - case WIFI_WPSCONFIG: - wifi_state = 0x01; - break; - case WIFI_RESTART: - wifi_state = 0x03; - break; - } +void ArmtronixSetWifiLed(void) +{ + uint8_t wifi_state = 0x02; - snprintf_P(log_data, sizeof(log_data), "ARM: Set WiFi LED to state %d (%d)", wifi_state, WifiState()); - AddLog(LOG_LEVEL_DEBUG); - - char state = '0' + (wifi_state & 1 > 0); - ArmtronixSerial->print("Setled:"); - ArmtronixSerial->write(state); - ArmtronixSerial->write(','); - state = '0' + (wifi_state & 2 > 0); - ArmtronixSerial->write(state); - ArmtronixSerial->write(10); - armtronix_wifi_state = WifiState(); + switch (WifiState()) { + case WIFI_SMARTCONFIG: + wifi_state = 0x00; + break; + case WIFI_MANAGER: + case WIFI_WPSCONFIG: + wifi_state = 0x01; + break; + case WIFI_RESTART: + wifi_state = 0x03; + break; + } + snprintf_P(log_data, sizeof(log_data), "ARM: Set WiFi LED to state %d (%d)", wifi_state, WifiState()); + AddLog(LOG_LEVEL_DEBUG); + char state = '0' + (wifi_state & 1 > 0); + ArmtronixSerial->print("Setled:"); + ArmtronixSerial->write(state); + ArmtronixSerial->write(','); + state = '0' + (wifi_state & 2 > 0); + ArmtronixSerial->write(state); + ArmtronixSerial->write(10); + armtronix_wifi_state = WifiState(); } - /*********************************************************************************************\ * Interface \*********************************************************************************************/ + boolean Xdrv18(byte function) { boolean result = false; @@ -179,9 +179,9 @@ boolean Xdrv18(byte function) if (ArmtronixSerial) { ArmtronixSerialInput(); } break; case FUNC_EVERY_SECOND: - if(ArmtronixSerial){ + if (ArmtronixSerial) { if (armtronix_wifi_state!=WifiState()) { ArmtronixSetWifiLed(); } - if(uptime&1){ + if (uptime &1) { ArmtronixSerial->println("Status"); } } From c903b7d830db91b6ebeccb1f1714ba1291a5fcdc Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Fri, 16 Nov 2018 18:09:02 +0100 Subject: [PATCH 0503/2222] decode-config.py: add 6.3.0.8 settings - fix Tasmota cmnd "MqttFingerprint" - fix setting callable definition handling --- tools/decode-config.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index a6299f104..7e0fef959 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0007' +VER = '2.1.0008' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -395,6 +395,15 @@ def bitsRead(x, n=0, c=1): if c>0: x &= (1< Date: Sun, 18 Nov 2018 09:06:59 +0200 Subject: [PATCH 0505/2222] Added support for LG wall hvac --- sonoff/my_user_config.h | 5 +- sonoff/xdrv_05_irremote.ino | 133 ++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 2 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 3e0efdef4..154c5bd7f 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -36,7 +36,8 @@ * Users are advised to use the user_config_override.h file for most changes. \*********************************************************************************************/ -//#define USE_CONFIG_OVERRIDE // Uncomment to use user_config_override.h file. See README.md +#define USE_CONFIG_OVERRIDE // Uncomment to use user_config_override.h file. See README.md +#warning Override settings are used :-) /*********************************************************************************************\ * SECTION 1 @@ -366,7 +367,7 @@ // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) -// #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) +#define USE_IR_HVAC // Support for HVAC system using IR (+2k code) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index dd8178c12..56ad491d9 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -44,6 +44,9 @@ const char kIrRemoteProtocols[] PROGMEM = #define HVAC_TOSHIBA_RPT_SPACE 7048 // Above original iremote limit #define HVAC_TOSHIBA_DATALEN 9 +// HVAC LG +#define HVAC_LG_DATALEN 7 + IRMitsubishiAC *mitsubir = NULL; const char kFanSpeedOptions[] = "A12345S"; @@ -137,6 +140,10 @@ void IrReceiveCheck(void) * IR Heating, Ventilation and Air Conditioning using IRMitsubishiAC library \*********************************************************************************************/ +/******************* + TOSCHIBA +********************/ + boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) { uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; @@ -226,6 +233,11 @@ boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H return false; } + +/******************* + MITSUBISHI +********************/ + boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) { char *p; @@ -269,6 +281,124 @@ boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolea return false; } + + +/******************* + LG +********************/ + +boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) +{ + uint32_t LG_Code; + byte data[HVAC_LG_DATALEN]; + static boolean hvacOn = false; + char *p; + uint8_t mode; + byte Temp; + + // Constant data + data[0] = 0x08; + data[1] = 0x08; + data[2] = 0x00; + + if (!HVAC_Power) { + data[2] = (byte)0x0C; // Turn OFF HVAC, code 0x88C0051 + data[3] = (byte)0x00; + data[4] = (byte)0x00; + data[5] = (byte)0x05; + data[6] = (byte)0x01; + hvacOn = false; + } + + else { + + // Set code for HVAC Mode - data[3] + if (HVAC_Mode == NULL) { + p = (char *)kHvacModeOptions; // default HVAC_HOT + } + else { + p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); + } + if (!p) { + return true; + } + mode = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 + switch (mode) { + case 0: // AUTO + data[3] = 11; + break; + case 1: // COOL + data[3] = 8; + break; + case 2: // DRY + data[3] = 9; + break; + case 3: // HOT + data[3] = 12; + break; + } + if (!hvacOn) { + data[3] = data[3] & 7; // reset bit3 + hvacOn = true; + } + + snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: HvacMode %s, ModeVal %d, Code %d"), p, mode, data[3]); + AddLog(LOG_LEVEL_DEBUG); + + // Set code for HVAC temperature - data[4] + if (HVAC_Temp > 30) { + Temp = 30; + } + else if (HVAC_Temp < 18) { + Temp = 18; + } + else { + Temp = HVAC_Temp; + } + data[4] = (byte)(Temp - 15); + + // Set code for HVAC fan mode - data[5] + if (HVAC_FanMode == NULL) { + p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO + } + else { + p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); + } + if (!p) { + return true; + } + mode = p - kFanSpeedOptions; + if ((mode == 0) || (mode > 3)) { + data[5] = 5; // Auto = 0x05 + } + else { + data[5] = (mode * 2) - 2; // Low = 0x00, Mid = 0x02, High = 0x04 + } + + snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: FanMode %s, ModeVal %d, Code %d"), p, mode, data[5]); + AddLog(LOG_LEVEL_DEBUG); + + // Set CRC code - data[6] + data[6] = (data[3] + data[4] + data[5]) & 0x0f; // CRC + + } + // Build LG IR code + LG_Code = data[0] << 4; + for (int i = 1; i < 6; i++) { + LG_Code = (LG_Code + data[i]) << 4; + } + LG_Code = LG_Code + data[6]; + + snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: LG_Code %d"), LG_Code); + AddLog(LOG_LEVEL_DEBUG); + + // Send LG IR Code + noInterrupts(); + irsend->sendLG(LG_Code, 28); + interrupts(); + + return false; +} #endif // USE_IR_HVAC /*********************************************************************************************\ @@ -381,6 +511,9 @@ boolean IrSendCommand(void) else if (!strcasecmp_P(HVAC_Vendor, PSTR("MITSUBISHI"))) { error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); } + else if (!strcasecmp_P(HVAC_Vendor, PSTR("LG"))) { + error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); + } else { error = true; } From 3be1b7a1e0ee2f40b93a8ccdf7ebf964bd7e3eef Mon Sep 17 00:00:00 2001 From: evzone Date: Sun, 18 Nov 2018 11:03:02 +0200 Subject: [PATCH 0506/2222] Revert "Added support for LG wall hvac" This reverts commit 40c1331b8a7a876173571041b0099e6bffed592f. --- sonoff/my_user_config.h | 5 +- sonoff/xdrv_05_irremote.ino | 133 ------------------------------------ 2 files changed, 2 insertions(+), 136 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 154c5bd7f..3e0efdef4 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -36,8 +36,7 @@ * Users are advised to use the user_config_override.h file for most changes. \*********************************************************************************************/ -#define USE_CONFIG_OVERRIDE // Uncomment to use user_config_override.h file. See README.md -#warning Override settings are used :-) +//#define USE_CONFIG_OVERRIDE // Uncomment to use user_config_override.h file. See README.md /*********************************************************************************************\ * SECTION 1 @@ -367,7 +366,7 @@ // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) -#define USE_IR_HVAC // Support for HVAC system using IR (+2k code) +// #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 56ad491d9..dd8178c12 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -44,9 +44,6 @@ const char kIrRemoteProtocols[] PROGMEM = #define HVAC_TOSHIBA_RPT_SPACE 7048 // Above original iremote limit #define HVAC_TOSHIBA_DATALEN 9 -// HVAC LG -#define HVAC_LG_DATALEN 7 - IRMitsubishiAC *mitsubir = NULL; const char kFanSpeedOptions[] = "A12345S"; @@ -140,10 +137,6 @@ void IrReceiveCheck(void) * IR Heating, Ventilation and Air Conditioning using IRMitsubishiAC library \*********************************************************************************************/ -/******************* - TOSCHIBA -********************/ - boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) { uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; @@ -233,11 +226,6 @@ boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H return false; } - -/******************* - MITSUBISHI -********************/ - boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) { char *p; @@ -281,124 +269,6 @@ boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolea return false; } - - -/******************* - LG -********************/ - -boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) -{ - uint32_t LG_Code; - byte data[HVAC_LG_DATALEN]; - static boolean hvacOn = false; - char *p; - uint8_t mode; - byte Temp; - - // Constant data - data[0] = 0x08; - data[1] = 0x08; - data[2] = 0x00; - - if (!HVAC_Power) { - data[2] = (byte)0x0C; // Turn OFF HVAC, code 0x88C0051 - data[3] = (byte)0x00; - data[4] = (byte)0x00; - data[5] = (byte)0x05; - data[6] = (byte)0x01; - hvacOn = false; - } - - else { - - // Set code for HVAC Mode - data[3] - if (HVAC_Mode == NULL) { - p = (char *)kHvacModeOptions; // default HVAC_HOT - } - else { - p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); - } - if (!p) { - return true; - } - mode = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 - switch (mode) { - case 0: // AUTO - data[3] = 11; - break; - case 1: // COOL - data[3] = 8; - break; - case 2: // DRY - data[3] = 9; - break; - case 3: // HOT - data[3] = 12; - break; - } - if (!hvacOn) { - data[3] = data[3] & 7; // reset bit3 - hvacOn = true; - } - - snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: HvacMode %s, ModeVal %d, Code %d"), p, mode, data[3]); - AddLog(LOG_LEVEL_DEBUG); - - // Set code for HVAC temperature - data[4] - if (HVAC_Temp > 30) { - Temp = 30; - } - else if (HVAC_Temp < 18) { - Temp = 18; - } - else { - Temp = HVAC_Temp; - } - data[4] = (byte)(Temp - 15); - - // Set code for HVAC fan mode - data[5] - if (HVAC_FanMode == NULL) { - p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO - } - else { - p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); - } - if (!p) { - return true; - } - mode = p - kFanSpeedOptions; - if ((mode == 0) || (mode > 3)) { - data[5] = 5; // Auto = 0x05 - } - else { - data[5] = (mode * 2) - 2; // Low = 0x00, Mid = 0x02, High = 0x04 - } - - snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: FanMode %s, ModeVal %d, Code %d"), p, mode, data[5]); - AddLog(LOG_LEVEL_DEBUG); - - // Set CRC code - data[6] - data[6] = (data[3] + data[4] + data[5]) & 0x0f; // CRC - - } - // Build LG IR code - LG_Code = data[0] << 4; - for (int i = 1; i < 6; i++) { - LG_Code = (LG_Code + data[i]) << 4; - } - LG_Code = LG_Code + data[6]; - - snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: LG_Code %d"), LG_Code); - AddLog(LOG_LEVEL_DEBUG); - - // Send LG IR Code - noInterrupts(); - irsend->sendLG(LG_Code, 28); - interrupts(); - - return false; -} #endif // USE_IR_HVAC /*********************************************************************************************\ @@ -511,9 +381,6 @@ boolean IrSendCommand(void) else if (!strcasecmp_P(HVAC_Vendor, PSTR("MITSUBISHI"))) { error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); } - else if (!strcasecmp_P(HVAC_Vendor, PSTR("LG"))) { - error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); - } else { error = true; } From 7e576a58f93086397afb504e9fd3922ad8f0688e Mon Sep 17 00:00:00 2001 From: evzone Date: Sun, 18 Nov 2018 11:05:50 +0200 Subject: [PATCH 0507/2222] commented user override to pass travis ci test --- sonoff/my_user_config.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 3e0efdef4..8634b5be7 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -38,6 +38,7 @@ //#define USE_CONFIG_OVERRIDE // Uncomment to use user_config_override.h file. See README.md + /*********************************************************************************************\ * SECTION 1 * - After initial load any change here only take effect if CFG_HOLDER is changed too @@ -366,7 +367,7 @@ // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) -// #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) +#define USE_IR_HVAC // Support for HVAC system using IR (+2k code) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // From 1900aec31889631aa92d367e6b52c3894ed4a927 Mon Sep 17 00:00:00 2001 From: evzone Date: Sun, 18 Nov 2018 11:08:48 +0200 Subject: [PATCH 0508/2222] Revert "commented user override to pass travis ci test" This reverts commit 7e576a58f93086397afb504e9fd3922ad8f0688e. --- sonoff/my_user_config.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 8634b5be7..3e0efdef4 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -38,7 +38,6 @@ //#define USE_CONFIG_OVERRIDE // Uncomment to use user_config_override.h file. See README.md - /*********************************************************************************************\ * SECTION 1 * - After initial load any change here only take effect if CFG_HOLDER is changed too @@ -367,7 +366,7 @@ // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) -#define USE_IR_HVAC // Support for HVAC system using IR (+2k code) +// #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // From 68e78036512d352dd46b40151f358beb9ae1d55c Mon Sep 17 00:00:00 2001 From: evzone Date: Sun, 18 Nov 2018 11:15:54 +0200 Subject: [PATCH 0509/2222] add support to LG wall HVAC systems --- sonoff/my_user_config.h | 3 +- sonoff/xdrv_05_irremote.ino | 138 ++++++++++++++++++++++++++++++++++-- 2 files changed, 135 insertions(+), 6 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 3e0efdef4..8634b5be7 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -38,6 +38,7 @@ //#define USE_CONFIG_OVERRIDE // Uncomment to use user_config_override.h file. See README.md + /*********************************************************************************************\ * SECTION 1 * - After initial load any change here only take effect if CFG_HOLDER is changed too @@ -366,7 +367,7 @@ // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) -// #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) +#define USE_IR_HVAC // Support for HVAC system using IR (+2k code) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index dd8178c12..8bd267759 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -1,18 +1,14 @@ /* xdrv_05_irremote.ino - infra red support for Sonoff-Tasmota - Copyright (C) 2018 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 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 . */ @@ -44,6 +40,9 @@ const char kIrRemoteProtocols[] PROGMEM = #define HVAC_TOSHIBA_RPT_SPACE 7048 // Above original iremote limit #define HVAC_TOSHIBA_DATALEN 9 +// HVAC LG +#define HVAC_LG_DATALEN 7 + IRMitsubishiAC *mitsubir = NULL; const char kFanSpeedOptions[] = "A12345S"; @@ -137,6 +136,10 @@ void IrReceiveCheck(void) * IR Heating, Ventilation and Air Conditioning using IRMitsubishiAC library \*********************************************************************************************/ +/******************* + TOSHIBA +********************/ + boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) { uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; @@ -226,6 +229,11 @@ boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H return false; } + +/******************* + MITSUBISHI +********************/ + boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) { char *p; @@ -269,6 +277,124 @@ boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolea return false; } + + +/******************* + LG +********************/ + +boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) +{ + uint32_t LG_Code; + byte data[HVAC_LG_DATALEN]; + static boolean hvacOn = false; + char *p; + uint8_t mode; + byte Temp; + + // Constant data + data[0] = 0x08; + data[1] = 0x08; + data[2] = 0x00; + + if (!HVAC_Power) { + data[2] = (byte)0x0C; // Turn OFF HVAC, code 0x88C0051 + data[3] = (byte)0x00; + data[4] = (byte)0x00; + data[5] = (byte)0x05; + data[6] = (byte)0x01; + hvacOn = false; + } + + else { + + // Set code for HVAC Mode - data[3] + if (HVAC_Mode == NULL) { + p = (char *)kHvacModeOptions; // default HVAC_HOT + } + else { + p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); + } + if (!p) { + return true; + } + mode = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 + switch (mode) { + case 0: // AUTO + data[3] = 11; + break; + case 1: // COOL + data[3] = 8; + break; + case 2: // DRY + data[3] = 9; + break; + case 3: // HOT + data[3] = 12; + break; + } + if (!hvacOn) { + data[3] = data[3] & 7; // reset bit3 + hvacOn = true; + } + + snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: HvacMode %s, ModeVal %d, Code %d"), p, mode, data[3]); + AddLog(LOG_LEVEL_DEBUG); + + // Set code for HVAC temperature - data[4] + if (HVAC_Temp > 30) { + Temp = 30; + } + else if (HVAC_Temp < 18) { + Temp = 18; + } + else { + Temp = HVAC_Temp; + } + data[4] = (byte)(Temp - 15); + + // Set code for HVAC fan mode - data[5] + if (HVAC_FanMode == NULL) { + p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO + } + else { + p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); + } + if (!p) { + return true; + } + mode = p - kFanSpeedOptions; + if ((mode == 0) || (mode > 3)) { + data[5] = 5; // Auto = 0x05 + } + else { + data[5] = (mode * 2) - 2; // Low = 0x00, Mid = 0x02, High = 0x04 + } + + snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: FanMode %s, ModeVal %d, Code %d"), p, mode, data[5]); + AddLog(LOG_LEVEL_DEBUG); + + // Set CRC code - data[6] + data[6] = (data[3] + data[4] + data[5]) & 0x0f; // CRC + + } + // Build LG IR code + LG_Code = data[0] << 4; + for (int i = 1; i < 6; i++) { + LG_Code = (LG_Code + data[i]) << 4; + } + LG_Code = LG_Code + data[6]; + + snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: LG_Code %d"), LG_Code); + AddLog(LOG_LEVEL_DEBUG); + + // Send LG IR Code + noInterrupts(); + irsend->sendLG(LG_Code, 28); + interrupts(); + + return false; +} #endif // USE_IR_HVAC /*********************************************************************************************\ @@ -279,7 +405,6 @@ boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolea * 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> } */ @@ -381,6 +506,9 @@ boolean IrSendCommand(void) else if (!strcasecmp_P(HVAC_Vendor, PSTR("MITSUBISHI"))) { error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); } + else if (!strcasecmp_P(HVAC_Vendor, PSTR("LG"))) { + error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); + } else { error = true; } From 13c7958c9924c0467d919033afe34aad869ec960 Mon Sep 17 00:00:00 2001 From: evzone Date: Sun, 18 Nov 2018 11:28:23 +0200 Subject: [PATCH 0510/2222] Revert "add support to LG wall HVAC systems" This reverts commit 68e78036512d352dd46b40151f358beb9ae1d55c. --- sonoff/my_user_config.h | 3 +- sonoff/xdrv_05_irremote.ino | 138 ++---------------------------------- 2 files changed, 6 insertions(+), 135 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 8634b5be7..3e0efdef4 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -38,7 +38,6 @@ //#define USE_CONFIG_OVERRIDE // Uncomment to use user_config_override.h file. See README.md - /*********************************************************************************************\ * SECTION 1 * - After initial load any change here only take effect if CFG_HOLDER is changed too @@ -367,7 +366,7 @@ // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) -#define USE_IR_HVAC // Support for HVAC system using IR (+2k code) +// #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 8bd267759..dd8178c12 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -1,14 +1,18 @@ /* xdrv_05_irremote.ino - infra red support for Sonoff-Tasmota + Copyright (C) 2018 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 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 . */ @@ -40,9 +44,6 @@ const char kIrRemoteProtocols[] PROGMEM = #define HVAC_TOSHIBA_RPT_SPACE 7048 // Above original iremote limit #define HVAC_TOSHIBA_DATALEN 9 -// HVAC LG -#define HVAC_LG_DATALEN 7 - IRMitsubishiAC *mitsubir = NULL; const char kFanSpeedOptions[] = "A12345S"; @@ -136,10 +137,6 @@ void IrReceiveCheck(void) * IR Heating, Ventilation and Air Conditioning using IRMitsubishiAC library \*********************************************************************************************/ -/******************* - TOSHIBA -********************/ - boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) { uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; @@ -229,11 +226,6 @@ boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H return false; } - -/******************* - MITSUBISHI -********************/ - boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) { char *p; @@ -277,124 +269,6 @@ boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolea return false; } - - -/******************* - LG -********************/ - -boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) -{ - uint32_t LG_Code; - byte data[HVAC_LG_DATALEN]; - static boolean hvacOn = false; - char *p; - uint8_t mode; - byte Temp; - - // Constant data - data[0] = 0x08; - data[1] = 0x08; - data[2] = 0x00; - - if (!HVAC_Power) { - data[2] = (byte)0x0C; // Turn OFF HVAC, code 0x88C0051 - data[3] = (byte)0x00; - data[4] = (byte)0x00; - data[5] = (byte)0x05; - data[6] = (byte)0x01; - hvacOn = false; - } - - else { - - // Set code for HVAC Mode - data[3] - if (HVAC_Mode == NULL) { - p = (char *)kHvacModeOptions; // default HVAC_HOT - } - else { - p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); - } - if (!p) { - return true; - } - mode = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 - switch (mode) { - case 0: // AUTO - data[3] = 11; - break; - case 1: // COOL - data[3] = 8; - break; - case 2: // DRY - data[3] = 9; - break; - case 3: // HOT - data[3] = 12; - break; - } - if (!hvacOn) { - data[3] = data[3] & 7; // reset bit3 - hvacOn = true; - } - - snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: HvacMode %s, ModeVal %d, Code %d"), p, mode, data[3]); - AddLog(LOG_LEVEL_DEBUG); - - // Set code for HVAC temperature - data[4] - if (HVAC_Temp > 30) { - Temp = 30; - } - else if (HVAC_Temp < 18) { - Temp = 18; - } - else { - Temp = HVAC_Temp; - } - data[4] = (byte)(Temp - 15); - - // Set code for HVAC fan mode - data[5] - if (HVAC_FanMode == NULL) { - p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO - } - else { - p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); - } - if (!p) { - return true; - } - mode = p - kFanSpeedOptions; - if ((mode == 0) || (mode > 3)) { - data[5] = 5; // Auto = 0x05 - } - else { - data[5] = (mode * 2) - 2; // Low = 0x00, Mid = 0x02, High = 0x04 - } - - snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: FanMode %s, ModeVal %d, Code %d"), p, mode, data[5]); - AddLog(LOG_LEVEL_DEBUG); - - // Set CRC code - data[6] - data[6] = (data[3] + data[4] + data[5]) & 0x0f; // CRC - - } - // Build LG IR code - LG_Code = data[0] << 4; - for (int i = 1; i < 6; i++) { - LG_Code = (LG_Code + data[i]) << 4; - } - LG_Code = LG_Code + data[6]; - - snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: LG_Code %d"), LG_Code); - AddLog(LOG_LEVEL_DEBUG); - - // Send LG IR Code - noInterrupts(); - irsend->sendLG(LG_Code, 28); - interrupts(); - - return false; -} #endif // USE_IR_HVAC /*********************************************************************************************\ @@ -405,6 +279,7 @@ boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_P * 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> } */ @@ -506,9 +381,6 @@ boolean IrSendCommand(void) else if (!strcasecmp_P(HVAC_Vendor, PSTR("MITSUBISHI"))) { error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); } - else if (!strcasecmp_P(HVAC_Vendor, PSTR("LG"))) { - error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); - } else { error = true; } From beb9d0ff841e8c9b6b871f2d415bc075d6a2767b Mon Sep 17 00:00:00 2001 From: evzone Date: Sun, 18 Nov 2018 11:35:53 +0200 Subject: [PATCH 0511/2222] add IR support to LG wall HVAC systems --- .../src/IRremoteESP8266.h | 4 +- sonoff/my_user_config.h | 2 +- sonoff/xdrv_05_irremote.ino | 138 +++++++++++++++++- 3 files changed, 136 insertions(+), 8 deletions(-) diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h b/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h index e2dc26904..f2c730dee 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h +++ b/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h @@ -171,8 +171,8 @@ #define DECODE_AIWA_RC_T501 false #define SEND_AIWA_RC_T501 false -#define DECODE_LG false -#define SEND_LG false +#define DECODE_LG true +#define SEND_LG true #define DECODE_SANYO false #define SEND_SANYO false diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 3e0efdef4..9d5b871c4 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -366,7 +366,7 @@ // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) -// #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) + #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index dd8178c12..8bd267759 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -1,18 +1,14 @@ /* xdrv_05_irremote.ino - infra red support for Sonoff-Tasmota - Copyright (C) 2018 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 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 . */ @@ -44,6 +40,9 @@ const char kIrRemoteProtocols[] PROGMEM = #define HVAC_TOSHIBA_RPT_SPACE 7048 // Above original iremote limit #define HVAC_TOSHIBA_DATALEN 9 +// HVAC LG +#define HVAC_LG_DATALEN 7 + IRMitsubishiAC *mitsubir = NULL; const char kFanSpeedOptions[] = "A12345S"; @@ -137,6 +136,10 @@ void IrReceiveCheck(void) * IR Heating, Ventilation and Air Conditioning using IRMitsubishiAC library \*********************************************************************************************/ +/******************* + TOSHIBA +********************/ + boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) { uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; @@ -226,6 +229,11 @@ boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H return false; } + +/******************* + MITSUBISHI +********************/ + boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) { char *p; @@ -269,6 +277,124 @@ boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolea return false; } + + +/******************* + LG +********************/ + +boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) +{ + uint32_t LG_Code; + byte data[HVAC_LG_DATALEN]; + static boolean hvacOn = false; + char *p; + uint8_t mode; + byte Temp; + + // Constant data + data[0] = 0x08; + data[1] = 0x08; + data[2] = 0x00; + + if (!HVAC_Power) { + data[2] = (byte)0x0C; // Turn OFF HVAC, code 0x88C0051 + data[3] = (byte)0x00; + data[4] = (byte)0x00; + data[5] = (byte)0x05; + data[6] = (byte)0x01; + hvacOn = false; + } + + else { + + // Set code for HVAC Mode - data[3] + if (HVAC_Mode == NULL) { + p = (char *)kHvacModeOptions; // default HVAC_HOT + } + else { + p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); + } + if (!p) { + return true; + } + mode = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 + switch (mode) { + case 0: // AUTO + data[3] = 11; + break; + case 1: // COOL + data[3] = 8; + break; + case 2: // DRY + data[3] = 9; + break; + case 3: // HOT + data[3] = 12; + break; + } + if (!hvacOn) { + data[3] = data[3] & 7; // reset bit3 + hvacOn = true; + } + + snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: HvacMode %s, ModeVal %d, Code %d"), p, mode, data[3]); + AddLog(LOG_LEVEL_DEBUG); + + // Set code for HVAC temperature - data[4] + if (HVAC_Temp > 30) { + Temp = 30; + } + else if (HVAC_Temp < 18) { + Temp = 18; + } + else { + Temp = HVAC_Temp; + } + data[4] = (byte)(Temp - 15); + + // Set code for HVAC fan mode - data[5] + if (HVAC_FanMode == NULL) { + p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO + } + else { + p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); + } + if (!p) { + return true; + } + mode = p - kFanSpeedOptions; + if ((mode == 0) || (mode > 3)) { + data[5] = 5; // Auto = 0x05 + } + else { + data[5] = (mode * 2) - 2; // Low = 0x00, Mid = 0x02, High = 0x04 + } + + snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: FanMode %s, ModeVal %d, Code %d"), p, mode, data[5]); + AddLog(LOG_LEVEL_DEBUG); + + // Set CRC code - data[6] + data[6] = (data[3] + data[4] + data[5]) & 0x0f; // CRC + + } + // Build LG IR code + LG_Code = data[0] << 4; + for (int i = 1; i < 6; i++) { + LG_Code = (LG_Code + data[i]) << 4; + } + LG_Code = LG_Code + data[6]; + + snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: LG_Code %d"), LG_Code); + AddLog(LOG_LEVEL_DEBUG); + + // Send LG IR Code + noInterrupts(); + irsend->sendLG(LG_Code, 28); + interrupts(); + + return false; +} #endif // USE_IR_HVAC /*********************************************************************************************\ @@ -279,7 +405,6 @@ boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolea * 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> } */ @@ -381,6 +506,9 @@ boolean IrSendCommand(void) else if (!strcasecmp_P(HVAC_Vendor, PSTR("MITSUBISHI"))) { error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); } + else if (!strcasecmp_P(HVAC_Vendor, PSTR("LG"))) { + error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); + } else { error = true; } From 18997e841f62056db8e7e57167e632ce93592cf7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 18 Nov 2018 15:02:52 +0100 Subject: [PATCH 0512/2222] 6.3.0.9 Add dynamic delay in loop 6.3.0.9 20181118 * Moved command SetSensorXX to debugging driver freeing user code space * Add dynamic delay to main loop providing time for wifi background tasks * Remove delays introduced in 6.3.0.1 (#4233) --- sonoff/_changelog.ino | 7 +- sonoff/i18n.h | 1 - sonoff/sonoff.h | 3 +- sonoff/sonoff.ino | 18 +- sonoff/sonoff_version.h | 2 +- .../{xdrv_95_debug.ino => xdrv_99_debug.ino} | 50 ++- sonoff/xdrv_interface.ino | 2 +- sonoff/xsns_interface.ino | 302 +---------------- sonoff/zzzz_debug.ino | 309 ++++++++++++++++++ 9 files changed, 380 insertions(+), 314 deletions(-) rename sonoff/{xdrv_95_debug.ino => xdrv_99_debug.ino} (91%) create mode 100644 sonoff/zzzz_debug.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 3914c426b..6f1c097f2 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,9 @@ -/* 6.3.0.8 20181115 +/* 6.3.0.9 20181118 + * Moved command SetSensorXX to debugging driver freeing user code space + * Add dynamic delay to main loop providing time for wifi background tasks + * Remove delays introduced in 6.3.0.1 (#4233) + * + * 6.3.0.8 20181115 * Stop enforcing flashmode dout but it is still mandatory * Moved bootcount update (being first) flash write to 10 seconds after restart * Add support for Armtronix dimmers. See wiki for info (#4321) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 36d93ccd7..f53433553 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -184,7 +184,6 @@ #define D_CMND_DRIVER "Driver" #define D_CMND_SAVEDATA "SaveData" #define D_CMND_SETOPTION "SetOption" -#define D_CMND_SETSENSOR "SetSensor" #define D_CMND_TEMPERATURE_RESOLUTION "TempRes" #define D_CMND_HUMIDITY_RESOLUTION "HumRes" #define D_CMND_PRESSURE_RESOLUTION "PressRes" diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 5a43e147f..3d6acfaab 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -189,7 +189,8 @@ typedef unsigned long power_t; // Power (Relay) type #define KNX_MAX_device_param 30 #define MAX_KNXTX_CMNDS 5 -#define DRIVER_BOOT_DELAY 1 // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting +#define DRIVER_BOOT_DELAY 1 // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting +#define LOOP_SLEEP_DELAY 10 // Lowest number of milliseconds to go through the main loop using delay when needed /*********************************************************************************************\ * Enumeration diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index d8d6cba1d..ad50c3573 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -81,7 +81,7 @@ enum TasmotaCommands { CMND_MODULE, CMND_MODULES, CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE, CMND_COUNTERDEBOUNCE, CMND_BUTTONDEBOUNCE, CMND_SWITCHDEBOUNCE, 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_SETSENSOR, + CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_TIMESTD, CMND_TIMEDST, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER, CMND_DRIVER }; const char kTasmotaCommands[] PROGMEM = @@ -91,7 +91,7 @@ const char kTasmotaCommands[] PROGMEM = 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_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" 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_SETSENSOR "|" + D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER "|" D_CMND_DRIVER; @@ -777,13 +777,6 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, (2 == ptype) ? stemp1 : (1 == ptype) ? GetStateText(bitRead(Settings.flag3.data, pindex)) : GetStateText(bitRead(Settings.flag.data, pindex))); } } - else if ((CMND_SETSENSOR == command_code) && (index < MAX_XSNS_DRIVERS)) { - if ((payload >= 0) && XsnsPresent(index)) { - bitWrite(Settings.sensors[index / 32], index % 32, payload &1); - if (1 == payload) { restart_flag = 2; } // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, XsnsGetSensors().c_str()); - } else if (CMND_TEMPERATURE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.temperature_resolution = payload; @@ -2753,6 +2746,8 @@ void setup(void) void loop(void) { + uint32_t my_sleep = millis(); + XdrvCall(FUNC_LOOP); OsWatchLoop(); @@ -2791,6 +2786,9 @@ void loop(void) while (arduino_ota_triggered) ArduinoOTA.handle(); #endif // USE_ARDUINO_OTA -// yield(); // yield == delay(0), delay contains yield, auto yield in loop +// yield(); // yield == delay(0), delay contains yield, auto yield in loop delay(sleep); // https://github.com/esp8266/Arduino/issues/2021 + + uint32_t my_activity = millis() - my_sleep; + if (my_activity < LOOP_SLEEP_DELAY) { delay(LOOP_SLEEP_DELAY - my_activity); } // Provide time for background tasks like wifi } diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 9ddcef51c..5ccff62e0 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06030008 +#define VERSION 0x06030009 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_95_debug.ino b/sonoff/xdrv_99_debug.ino similarity index 91% rename from sonoff/xdrv_95_debug.ino rename to sonoff/xdrv_99_debug.ino index a1c9ac22d..30e51121f 100644 --- a/sonoff/xdrv_95_debug.ino +++ b/sonoff/xdrv_99_debug.ino @@ -1,5 +1,5 @@ /* - xdrv_95_debug.ino - debug support for Sonoff-Tasmota + xdrv_99_debug.ino - debug support for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -27,10 +27,12 @@ #ifdef USE_DEBUG_DRIVER /*********************************************************************************************\ - * Virtual debugging support + * Virtual debugging support - Part1 + * + * Needs file zzzz_debug.ino due to DEFINE processing \*********************************************************************************************/ -#define XDRV_95 95 +#define XDRV_99 99 #ifndef CPU_LOAD_CHECK #define CPU_LOAD_CHECK 1 // Seconds between each CPU_LOAD log @@ -50,9 +52,15 @@ #define D_CMND_FREEMEM "FreeMem" #define D_CMND_RTCDUMP "RtcDump" #define D_CMND_HELP "Help" +#define D_CMND_SETSENSOR "SetSensor" +#define D_CMND_FLASHMODE "FlashMode" -enum DebugCommands { CMND_CFGDUMP, CMND_CFGPEEK, CMND_CFGPOKE, CMND_CFGSHOW, CMND_CFGXOR, CMND_CPUCHECK, CMND_EXCEPTION, CMND_FREEMEM, CMND_RTCDUMP, CMND_HELP }; -const char kDebugCommands[] PROGMEM = D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" D_CMND_CFGSHOW "|" D_CMND_CFGXOR "|" D_CMND_CPUCHECK "|" D_CMND_EXCEPTION "|" D_CMND_FREEMEM "|" D_CMND_RTCDUMP "|" D_CMND_HELP; +enum DebugCommands { + CMND_CFGDUMP, CMND_CFGPEEK, CMND_CFGPOKE, CMND_CFGSHOW, CMND_CFGXOR, + CMND_CPUCHECK, CMND_EXCEPTION, CMND_FREEMEM, CMND_RTCDUMP, CMND_SETSENSOR, CMND_FLASHMODE, CMND_HELP }; +const char kDebugCommands[] PROGMEM = + D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" D_CMND_CFGSHOW "|" D_CMND_CFGXOR "|" + D_CMND_CPUCHECK "|" D_CMND_EXCEPTION "|" D_CMND_FREEMEM "|" D_CMND_RTCDUMP "|" D_CMND_SETSENSOR "|" D_CMND_FLASHMODE "|" D_CMND_HELP; uint32_t CPU_loops = 0; uint32_t CPU_last_millis = 0; @@ -406,6 +414,23 @@ void DebugCfgShow(uint8_t more) } } +void SetFlashMode(uint8_t mode) +{ + uint8_t *_buffer; + uint32_t address; + + address = 0; + _buffer = new uint8_t[FLASH_SECTOR_SIZE]; + + if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) { + if (_buffer[2] != mode) { // DOUT + _buffer[2] = mode; + if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); + } + } + delete[] _buffer; +} + /*******************************************************************************************/ boolean DebugCommand(void) @@ -469,6 +494,19 @@ boolean DebugCommand(void) } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, CPU_show_freemem); } + else if ((CMND_SETSENSOR == command_code) && (XdrvMailbox.index < MAX_XSNS_DRIVERS)) { + if ((XdrvMailbox.payload >= 0) && XsnsPresent(XdrvMailbox.index)) { + bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); + if (1 == XdrvMailbox.payload) { restart_flag = 2; } // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, XsnsGetSensors().c_str()); + } + else if (CMND_FLASHMODE == command_code) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + SetFlashMode(XdrvMailbox.payload); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, ESP.getFlashChipMode()); + } else serviced = false; // Unknown command return serviced; @@ -478,7 +516,7 @@ boolean DebugCommand(void) * Interface \*********************************************************************************************/ -boolean Xdrv95(byte function) +boolean Xdrv99(byte function) { boolean result = false; diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index c9557ec56..12b9e2711 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -238,7 +238,7 @@ boolean XdrvCall(byte Function) boolean result = false; for (byte x = 0; x < xdrv_present; x++) { - AppDelay(); +// AppDelay(); result = xdrv_func_ptr[x](Function); if (result) break; } diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index 7b5002c88..a7ab6d7a7 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -265,310 +265,22 @@ boolean (* const xsns_func_ptr[])(byte) = { // Sensor Function Pointers for sim const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); // Number of External Sensors found uint8_t xsns_index = 0; -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kXsnsList[] PROGMEM = { -#else -const uint8_t kXsnsList[] = { -#endif - -#ifdef XSNS_01 - XSNS_01, -#endif - -#ifdef XSNS_02 - XSNS_02, -#endif - -#ifdef XSNS_03 - XSNS_03, -#endif - -#ifdef XSNS_04 - XSNS_04, -#endif - -#ifdef XSNS_05 - XSNS_05, -#endif - -#ifdef XSNS_06 - XSNS_06, -#endif - -#ifdef XSNS_07 - XSNS_07, -#endif - -#ifdef XSNS_08 - XSNS_08, -#endif - -#ifdef XSNS_09 - XSNS_09, -#endif - -#ifdef XSNS_10 - XSNS_10, -#endif - -#ifdef XSNS_11 - XSNS_11, -#endif - -#ifdef XSNS_12 - XSNS_12, -#endif - -#ifdef XSNS_13 - XSNS_13, -#endif - -#ifdef XSNS_14 - XSNS_14, -#endif - -#ifdef XSNS_15 - XSNS_15, -#endif - -#ifdef XSNS_16 - XSNS_16, -#endif - -#ifdef XSNS_17 - XSNS_17, -#endif - -#ifdef XSNS_18 - XSNS_18, -#endif - -#ifdef XSNS_19 - XSNS_19, -#endif - -#ifdef XSNS_20 - XSNS_20, -#endif - -#ifdef XSNS_21 - XSNS_21, -#endif - -#ifdef XSNS_22 - XSNS_22, -#endif - -#ifdef XSNS_23 - XSNS_23, -#endif - -#ifdef XSNS_24 - XSNS_24, -#endif - -#ifdef XSNS_25 - XSNS_25, -#endif - -#ifdef XSNS_26 - XSNS_26, -#endif - -#ifdef XSNS_27 - XSNS_27, -#endif - -#ifdef XSNS_28 - XSNS_28, -#endif - -#ifdef XSNS_29 - XSNS_29, -#endif - -#ifdef XSNS_30 - XSNS_30, -#endif - -#ifdef XSNS_31 - XSNS_31, -#endif - -#ifdef XSNS_32 - XSNS_32, -#endif - -#ifdef XSNS_33 - XSNS_33, -#endif - -#ifdef XSNS_34 - XSNS_34, -#endif - -#ifdef XSNS_35 - XSNS_35, -#endif - -#ifdef XSNS_36 - XSNS_36, -#endif - -#ifdef XSNS_37 - XSNS_37, -#endif - -#ifdef XSNS_38 - XSNS_38, -#endif - -#ifdef XSNS_39 - XSNS_39, -#endif - -#ifdef XSNS_40 - XSNS_40, -#endif - -#ifdef XSNS_41 - XSNS_41, -#endif - -#ifdef XSNS_42 - XSNS_42, -#endif - -#ifdef XSNS_43 - XSNS_43, -#endif - -#ifdef XSNS_44 - XSNS_44, -#endif - -#ifdef XSNS_45 - XSNS_45, -#endif - -#ifdef XSNS_46 - XSNS_46, -#endif - -#ifdef XSNS_47 - XSNS_47, -#endif - -#ifdef XSNS_48 - XSNS_48, -#endif - -#ifdef XSNS_49 - XSNS_49, -#endif - -#ifdef XSNS_50 - XSNS_50, -#endif - -// Optional user defined sensors in range 91 - 99 - -#ifdef XSNS_91 - XSNS_91, -#endif - -#ifdef XSNS_92 - XSNS_92, -#endif - -#ifdef XSNS_93 - XSNS_93, -#endif - -#ifdef XSNS_94 - XSNS_94, -#endif - -#ifdef XSNS_95 - XSNS_95, -#endif - -#ifdef XSNS_96 - XSNS_96, -#endif - -#ifdef XSNS_97 - XSNS_97, -#endif - -#ifdef XSNS_98 - XSNS_98, -#endif - -#ifdef XSNS_99 - XSNS_99 -#endif -}; - - /*********************************************************************************************\ * Function call to all xsns \*********************************************************************************************/ -boolean XsnsEnabled(byte sns_index) -{ - if (sns_index < sizeof(kXsnsList)) { -#ifdef XFUNC_PTR_IN_ROM - uint8_t index = pgm_read_byte(kXsnsList + sns_index); -#else - uint8_t index = kXsnsList[sns_index]; -#endif - return bitRead(Settings.sensors[index / 32], index % 32); - } - return 1; -} - -boolean XsnsPresent(byte sns_index) -{ - uint8_t index = 0; - for (byte i = 0; i < sizeof(kXsnsList); i++) { -#ifdef XFUNC_PTR_IN_ROM - index = pgm_read_byte(kXsnsList + i); -#else - index = kXsnsList[i]; -#endif - if (index == sns_index) { return true; } - } - return false; -} - -String XsnsGetSensors(void) -{ - char state[2] = { 0 }; - - String data = F("["); - for (byte i = 0; i < MAX_XSNS_DRIVERS; i++) { - if (i && (!(i % 16))) { data += F(","); } - if (!(i % 16)) { data += F("\""); } - state[0] = '-'; - if (XsnsPresent(i)) { state[0] = bitRead(Settings.sensors[i / 32], i % 32) ? '1' : '0'; } - data += String(state); - if (i && (!((i +1) % 16))) { data += F("\""); } - } - data += F("]"); - - return data; -} - boolean XsnsNextCall(byte Function) { + xsns_index++; if (xsns_index == xsns_present) { xsns_index = 0; } +#ifdef USE_DEBUG_DRIVER while (!XsnsEnabled(xsns_index) && !xsns_index) { // Perform at least first sensor (counter) xsns_index++; if (xsns_index == xsns_present) { xsns_index = 0; } } - AppDelay(); +#endif +// AppDelay(); return xsns_func_ptr[xsns_index](Function); } @@ -581,12 +293,14 @@ boolean XsnsCall(byte Function) #endif // PROFILE_XSNS_EVERY_SECOND for (byte x = 0; x < xsns_present; x++) { +#ifdef USE_DEBUG_DRIVER if (XsnsEnabled(x)) { +#endif #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND uint32_t profile_start_millis = millis(); #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND - AppDelay(); +// AppDelay(); result = xsns_func_ptr[x](Function); #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND @@ -600,7 +314,9 @@ boolean XsnsCall(byte Function) #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND if (result) break; +#ifdef USE_DEBUG_DRIVER } +#endif } #ifdef PROFILE_XSNS_EVERY_SECOND diff --git a/sonoff/zzzz_debug.ino b/sonoff/zzzz_debug.ino new file mode 100644 index 000000000..3d159b922 --- /dev/null +++ b/sonoff/zzzz_debug.ino @@ -0,0 +1,309 @@ +/* + zzzz_debug.ino - debug support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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_DEBUG_DRIVER +/*********************************************************************************************\ + * Virtual debugging support - Part 2 + * + * Needs to be the last alphabetical file due to DEFINE compile order +\*********************************************************************************************/ + +/*********************************************************************************************\ + * Xsns available list +\*********************************************************************************************/ + +#ifdef XFUNC_PTR_IN_ROM +const uint8_t kXsnsList[] PROGMEM = { +#else +const uint8_t kXsnsList[] = { +#endif + +#ifdef XSNS_01 + XSNS_01, +#endif + +#ifdef XSNS_02 + XSNS_02, +#endif + +#ifdef XSNS_03 + XSNS_03, +#endif + +#ifdef XSNS_04 + XSNS_04, +#endif + +#ifdef XSNS_05 + XSNS_05, +#endif + +#ifdef XSNS_06 + XSNS_06, +#endif + +#ifdef XSNS_07 + XSNS_07, +#endif + +#ifdef XSNS_08 + XSNS_08, +#endif + +#ifdef XSNS_09 + XSNS_09, +#endif + +#ifdef XSNS_10 + XSNS_10, +#endif + +#ifdef XSNS_11 + XSNS_11, +#endif + +#ifdef XSNS_12 + XSNS_12, +#endif + +#ifdef XSNS_13 + XSNS_13, +#endif + +#ifdef XSNS_14 + XSNS_14, +#endif + +#ifdef XSNS_15 + XSNS_15, +#endif + +#ifdef XSNS_16 + XSNS_16, +#endif + +#ifdef XSNS_17 + XSNS_17, +#endif + +#ifdef XSNS_18 + XSNS_18, +#endif + +#ifdef XSNS_19 + XSNS_19, +#endif + +#ifdef XSNS_20 + XSNS_20, +#endif + +#ifdef XSNS_21 + XSNS_21, +#endif + +#ifdef XSNS_22 + XSNS_22, +#endif + +#ifdef XSNS_23 + XSNS_23, +#endif + +#ifdef XSNS_24 + XSNS_24, +#endif + +#ifdef XSNS_25 + XSNS_25, +#endif + +#ifdef XSNS_26 + XSNS_26, +#endif + +#ifdef XSNS_27 + XSNS_27, +#endif + +#ifdef XSNS_28 + XSNS_28, +#endif + +#ifdef XSNS_29 + XSNS_29, +#endif + +#ifdef XSNS_30 + XSNS_30, +#endif + +#ifdef XSNS_31 + XSNS_31, +#endif + +#ifdef XSNS_32 + XSNS_32, +#endif + +#ifdef XSNS_33 + XSNS_33, +#endif + +#ifdef XSNS_34 + XSNS_34, +#endif + +#ifdef XSNS_35 + XSNS_35, +#endif + +#ifdef XSNS_36 + XSNS_36, +#endif + +#ifdef XSNS_37 + XSNS_37, +#endif + +#ifdef XSNS_38 + XSNS_38, +#endif + +#ifdef XSNS_39 + XSNS_39, +#endif + +#ifdef XSNS_40 + XSNS_40, +#endif + +#ifdef XSNS_41 + XSNS_41, +#endif + +#ifdef XSNS_42 + XSNS_42, +#endif + +#ifdef XSNS_43 + XSNS_43, +#endif + +#ifdef XSNS_44 + XSNS_44, +#endif + +#ifdef XSNS_45 + XSNS_45, +#endif + +#ifdef XSNS_46 + XSNS_46, +#endif + +#ifdef XSNS_47 + XSNS_47, +#endif + +#ifdef XSNS_48 + XSNS_48, +#endif + +#ifdef XSNS_49 + XSNS_49, +#endif + +#ifdef XSNS_50 + XSNS_50, +#endif + +// Optional user defined sensors in range 91 - 99 + +#ifdef XSNS_91 + XSNS_91, +#endif + +#ifdef XSNS_92 + XSNS_92, +#endif + +#ifdef XSNS_93 + XSNS_93, +#endif + +#ifdef XSNS_94 + XSNS_94, +#endif + +#ifdef XSNS_95 + XSNS_95 +#endif +}; + +/*********************************************************************************************\ + * Xsns sensor control +\*********************************************************************************************/ + +boolean XsnsEnabled(byte sns_index) +{ + if (sns_index < sizeof(kXsnsList)) { +#ifdef XFUNC_PTR_IN_ROM + uint8_t index = pgm_read_byte(kXsnsList + sns_index); +#else + uint8_t index = kXsnsList[sns_index]; +#endif + return bitRead(Settings.sensors[index / 32], index % 32); + } + return 1; +} + +boolean XsnsPresent(byte sns_index) +{ + uint8_t index = 0; + for (byte i = 0; i < sizeof(kXsnsList); i++) { +#ifdef XFUNC_PTR_IN_ROM + index = pgm_read_byte(kXsnsList + i); +#else + index = kXsnsList[i]; +#endif + if (index == sns_index) { return true; } + } + return false; +} + +String XsnsGetSensors(void) +{ + char state[2] = { 0 }; + + String data = F("["); + for (byte i = 0; i < MAX_XSNS_DRIVERS; i++) { + if (i && (!(i % 16))) { data += F(","); } + if (!(i % 16)) { data += F("\""); } + state[0] = '-'; + if (XsnsPresent(i)) { state[0] = bitRead(Settings.sensors[i / 32], i % 32) ? '1' : '0'; } + data += String(state); + if (i && (!((i +1) % 16))) { data += F("\""); } + } + data += F("]"); + + return data; +} + +#endif // USE_DEBUG_DRIVER \ No newline at end of file From 4899178362a6881193df93c9a3fe86447f3edcc2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 18 Nov 2018 16:49:02 +0100 Subject: [PATCH 0513/2222] 6.3.0.10 Add command SetOption36 6.3.0.10 20181118 * Add command SetOption36 0..255 milliseconds (10 default) to tune main loop dynamic delay --- sonoff/_changelog.ino | 5 ++++- sonoff/settings.ino | 4 ++++ sonoff/sonoff.h | 8 ++++---- sonoff/sonoff.ino | 2 +- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_webserver.ino | 6 ++++-- sonoff/xdrv_02_mqtt.ino | 2 +- sonoff/xdrv_11_knx.ino | 2 +- 8 files changed, 20 insertions(+), 11 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 6f1c097f2..306784da2 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.3.0.9 20181118 +/* 6.3.0.10 20181118 + * Add command SetOption36 0..255 milliseconds (10 default) to tune main loop dynamic delay + * + * 6.3.0.9 20181118 * Moved command SetSensorXX to debugging driver freeing user code space * Add dynamic delay to main loop providing time for wifi background tasks * Remove delays introduced in 6.3.0.1 (#4233) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index d683eee79..2a346feb7 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -417,6 +417,7 @@ void SettingsDefaultSet2(void) // Settings.flag.stop_flash_rotate = 0; Settings.save_data = SAVE_DATA; Settings.sleep = APP_SLEEP; + Settings.param[P_LOOP_SLEEP_DELAY] = LOOP_SLEEP_DELAY; // Module // Settings.flag.interlock = 0; @@ -853,6 +854,9 @@ void SettingsDelta(void) if (Settings.version < 0x06030004) { memset(&Settings.drivers, 0xFF, 32); // Enable all possible monitors, displays, drivers and sensors } + if (Settings.version < 0x0603000A) { + Settings.param[P_LOOP_SLEEP_DELAY] = LOOP_SLEEP_DELAY; + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 3d6acfaab..98031c402 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -189,8 +189,8 @@ typedef unsigned long power_t; // Power (Relay) type #define KNX_MAX_device_param 30 #define MAX_KNXTX_CMNDS 5 -#define DRIVER_BOOT_DELAY 1 // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting -#define LOOP_SLEEP_DELAY 10 // Lowest number of milliseconds to go through the main loop using delay when needed +#define DRIVER_BOOT_DELAY 1 // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting +#define LOOP_SLEEP_DELAY 10 // Lowest number of milliseconds to go through the main loop using delay when needed /*********************************************************************************************\ * Enumeration @@ -222,7 +222,7 @@ enum ButtonStates { PRESSED, NOT_PRESSED }; enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; -enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) +enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_LOOP_SLEEP_DELAY, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_MAX_SENSORS}; @@ -233,7 +233,7 @@ enum LightSubtypes { LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LS enum LightTypes { LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_NU8, LT_SERIAL1, LT_SERIAL2, LT_WS2812, LT_RGBW, LT_RGBWC, LT_NU14, LT_NU15 }; // Do not insert new fields -enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; +enum LightSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ad50c3573..4930fdab4 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2790,5 +2790,5 @@ void loop(void) delay(sleep); // https://github.com/esp8266/Arduino/issues/2021 uint32_t my_activity = millis() - my_sleep; - if (my_activity < LOOP_SLEEP_DELAY) { delay(LOOP_SLEEP_DELAY - my_activity); } // Provide time for background tasks like wifi + if (my_activity < (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]) { delay((uint32_t)Settings.param[P_LOOP_SLEEP_DELAY] - my_activity); } // Provide time for background tasks like wifi } diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 5ccff62e0..78acd0305 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06030009 +#define VERSION 0x0603000A #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index a55fdd1fa..a4cf8c137 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2055,10 +2055,12 @@ boolean Xdrv01(byte function) switch (function) { case FUNC_LOOP: - PollDnsWebserver(); + if (!global_state.wifi_down) { + PollDnsWebserver(); #ifdef USE_EMULATION - if (Settings.flag2.emulation) PollUdp(); + if (Settings.flag2.emulation) PollUdp(); #endif // USE_EMULATION + } break; case FUNC_COMMAND: result = WebCommand(); diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 2da603a99..a67a15d7e 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -926,7 +926,7 @@ boolean Xdrv02(byte function) break; #endif // USE_WEBSERVER case FUNC_LOOP: - MqttLoop(); + if (!global_state.mqtt_down) { MqttLoop(); } break; case FUNC_COMMAND: result = MqttCommand(); diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 69fa558fa..5391cd17c 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -1298,7 +1298,7 @@ boolean Xdrv11(byte function) #endif // USE_KNX_WEB_MENU #endif // USE_WEBSERVER case FUNC_LOOP: - knx.loop(); // Process knx events + if (!global_state.wifi_down) { knx.loop(); } // Process knx events break; case FUNC_EVERY_50_MSECOND: if (toggle_inhibit) { From 50f4f0300b64f184fbfe6ddfc8b360b023f0ed56 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 18 Nov 2018 17:25:39 +0100 Subject: [PATCH 0514/2222] Update sonoff.h Update default loop sleep delay from 10 to 50 --- sonoff/sonoff.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 98031c402..9f9350c64 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -190,7 +190,7 @@ typedef unsigned long power_t; // Power (Relay) type #define MAX_KNXTX_CMNDS 5 #define DRIVER_BOOT_DELAY 1 // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting -#define LOOP_SLEEP_DELAY 10 // Lowest number of milliseconds to go through the main loop using delay when needed +#define LOOP_SLEEP_DELAY 50 // Lowest number of milliseconds to go through the main loop using delay when needed /*********************************************************************************************\ * Enumeration From 809ae966df349e0208c11c641fd45e8c78b91bc5 Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Sun, 18 Nov 2018 20:03:59 +0200 Subject: [PATCH 0515/2222] Update _changelog.ino --- sonoff/_changelog.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 306784da2..b60ebf9f0 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,5 @@ /* 6.3.0.10 20181118 - * Add command SetOption36 0..255 milliseconds (10 default) to tune main loop dynamic delay + * Add command SetOption36 0..255 milliseconds (50 default) to tune main loop dynamic delay * * 6.3.0.9 20181118 * Moved command SetSensorXX to debugging driver freeing user code space From a2ca0dd567436598c4a72606667739592aa5ab3b Mon Sep 17 00:00:00 2001 From: digiblur <3240875+digiblur@users.noreply.github.com> Date: Sun, 18 Nov 2018 17:02:09 -0600 Subject: [PATCH 0516/2222] Add SK03 Outdoor Module with Power Monitoring Couldn't add the module using Generic as the power monitoring had to be added. See the Tasmota wiki entry for more info: https://github.com/arendst/Sonoff-Tasmota/wiki/SK03-Outdoor-Smart-Plug-w--Power-Monitoring-(HLW8012-&-Tuya-Module) --- sonoff/sonoff_template.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index f2595c82c..dcc87c27f 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -252,6 +252,7 @@ enum SupportedModules { TUYA_DIMMER, GOSUND, ARMTRONIX_DIMMERS, + SK03_TUYA, MAXMODULE }; /********************************************************************************************/ @@ -469,6 +470,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { TECKIN, APLIC_WDP303075, GOSUND, + SK03_TUYA, NEO_COOLCAM, // Socket Relay Devices OBI, ESP_SWITCH, // Switch Devices @@ -1249,7 +1251,19 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, GPIO_USER, 0 - } + }, + { "SK03 Outdoor", // Outdoor smart plug with power monitoring HLW8012 chip - https://www.amazon.com/gp/product/B07CG7MBPV + GPIO_KEY1, // GPIO00 Button + 0, 0, 0, + GPIO_HLW_CF, // GPIO04 HLW8012 CF power + GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 current / voltage + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage) + GPIO_LED2_INV, // GPIO13 Red Led (0 = On, 1 = Off) + GPIO_LED1_INV, // GPIO14 Blue Led (0 = On, 1 = Off) + GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) + 0, 0 + } }; /* From fe7f154b257aa7cbc69f5644f908a0e5ea0d5029 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 19 Nov 2018 10:59:01 +0100 Subject: [PATCH 0517/2222] Update my_user_config.h --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 9d5b871c4..3e0efdef4 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -366,7 +366,7 @@ // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) - #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) +// #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // From 288fefebb74f67cfa2c3fbdba359b409a0a098ae Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 19 Nov 2018 11:00:24 +0100 Subject: [PATCH 0518/2222] Update xdrv_05_irremote.ino --- sonoff/xdrv_05_irremote.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 8bd267759..03f3a739f 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -1,14 +1,18 @@ /* xdrv_05_irremote.ino - infra red support for Sonoff-Tasmota + Copyright (C) 2018 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 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 . */ From 88528d8ef3b1613b065ac225ec757d4adef5a08f Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Mon, 19 Nov 2018 12:56:54 +0100 Subject: [PATCH 0519/2222] Fix NovaSDS sensor rare checksum failure - NodeSDS send/rec rewritten (common func) --- sonoff/xsns_20_novasds.ino | 134 +++++++++++++++++++++++++------------ 1 file changed, 90 insertions(+), 44 deletions(-) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 63f5b76f3..909711472 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -21,6 +21,8 @@ /*********************************************************************************************\ * Nova Fitness SDS011 (and possibly SDS021) particle concentration sensor * For background information see http://aqicn.org/sensor/sds011/ + * For protocol specification see + * https://cdn.sparkfun.com/assets/parts/1/2/2/7/5/Laser_Dust_Sensor_Control_Protocol_V1.3.pdf * * Hardware Serial will be selected if GPIO3 = [SDS0X01] \*********************************************************************************************/ @@ -30,70 +32,114 @@ #include #ifndef WORKING_PERIOD -#define WORKING_PERIOD 5 +#define WORKING_PERIOD 5 // NodaSDS sleep working period in minutes #endif -#ifndef XSNS_20_QUERY_INTERVAL -#define XSNS_20_QUERY_INTERVAL 3 // query every 3 seconds +#ifndef NOVA_SDS_REINIT_CHECK +#define NOVA_SDS_REINIT_CHECK 80 // NodaSDS reinitalized check in seconds #endif +#ifndef NOVA_SDS_QUERY_INTERVAL +#define NOVA_SDS_QUERY_INTERVAL 3 // NodaSDS query interval in seconds +#endif +#ifndef NOVA_SDS_RECDATA_TIMEOUT +#define NOVA_SDS_RECDATA_TIMEOUT 150 // NodaSDS query data timeout in ms +#endif +#ifndef NOVA_SDS_DEVICE_ID +#define NOVA_SDS_DEVICE_ID 0xFFFF // NodaSDS all sensor response +#endif + TasmotaSerial *NovaSdsSerial; uint8_t novasds_type = 1; uint8_t novasds_valid = 0; -uint8_t novasds_workperiod[19] = {0xAA, 0xB4, 0x08, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0C, 0xAB}; //5 minutes -uint8_t novasds_setquerymode[19] = {0xAA, 0xB4, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0xAB}; //query mode -uint8_t novasds_querydata[19] = {0xAA, 0xB4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0xAB}; //query DATA - struct sds011data { uint16_t pm100; uint16_t pm25; } novasds_data; +// NovaSDS commands +#define NOVA_SDS_REPORTING_MODE 2 // Cmnd "data reporting mode" +#define NOVA_SDS_QUERY_DATA 4 // Cmnd "Query data" +#define NOVA_SDS_SET_DEVICE_ID 5 // Cmnd "Set Device ID" +#define NOVA_SDS_SLEEP_AND_WORK 6 // Cmnd "sleep and work mode" +#define NOVA_SDS_WORKING_PERIOD 8 // Cmnd "working period" +#define NOVA_SDS_CHECK_FIRMWARE_VER 7 // Cmnd "Check firmware version" + #define NOVA_SDS_QUERY_MODE 0 // Subcmnd "query mode" + #define NOVA_SDS_SET_MODE 1 // Subcmnd "set mode" + #define NOVA_SDS_REPORT_ACTIVE 0 // Subcmnd "report active mode" - Sensor received query data command to report a measurement data + #define NOVA_SDS_REPORT_QUERY 1 // Subcmnd "report query mode" - Sensor automatically reports a measurement data in a work period + #define NOVA_SDS_WORK 0 // Subcmnd "work mode" + #define NOVA_SDS_SLEEP 1 // Subcmnd "sleep mode" + + +bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, byte *buffer) +{ + uint8_t novasds_cmnd[19] = {0xAA, 0xB4, byte1, byte2, byte3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (uint8_t)(sensorid & 0xFF), (uint8_t)((sensorid>>8) & 0xFF), 0x00, 0xAB}; + + // calc crc + for (byte i = 2; i < 17; i++) { + novasds_cmnd[17] += novasds_cmnd[i]; + } + //~ snprintf_P(log_data, sizeof(log_data), PSTR("SDS: Send %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X"), + //~ novasds_cmnd[0],novasds_cmnd[1],novasds_cmnd[2],novasds_cmnd[3],novasds_cmnd[4],novasds_cmnd[5],novasds_cmnd[6],novasds_cmnd[7],novasds_cmnd[8],novasds_cmnd[9], + //~ novasds_cmnd[10],novasds_cmnd[11],novasds_cmnd[12],novasds_cmnd[13],novasds_cmnd[14],novasds_cmnd[15],novasds_cmnd[16],novasds_cmnd[17],novasds_cmnd[18]); + //~ AddLog(LOG_LEVEL_DEBUG); + // send cmnd + NovaSdsSerial->write(novasds_cmnd, sizeof(novasds_cmnd)); + NovaSdsSerial->flush(); + + // wait for any response + unsigned long cmndtime = millis(); + while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( ! NovaSdsSerial->available() ) ); + if ( ! NovaSdsSerial->available() ) { + // timeout + return false; + } + byte recbuf[10]; + memset(recbuf, 0, sizeof(recbuf)); + // sync to 0xAA header + while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( NovaSdsSerial->available() > 0) && (0xAA != (recbuf[0] = NovaSdsSerial->read())) ); + if ( 0xAA != recbuf[0] ) { + // no head found + return false; + } + + // read rest (9 of 10 bytes) of message + NovaSdsSerial->readBytes(&recbuf[1], 9); + AddLogSerial(LOG_LEVEL_DEBUG_MORE, recbuf, sizeof(recbuf)); + + if ( NULL != buffer ) { + // return data to buffer + memcpy(buffer, recbuf, sizeof(recbuf)); + } + + // checksum & tail check + if ((0xAB != recbuf[9] ) || (recbuf[8] != ((recbuf[2] + recbuf[3] + recbuf[4] + recbuf[5] + recbuf[6] + recbuf[7]) & 0xFF))) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SDS: " D_CHECKSUM_FAILURE)); + return false; + } + + return true; +} + void NovaSdsSetWorkPeriod(void) { - - while (NovaSdsSerial->available() > 0) { - NovaSdsSerial->read(); - } - - novasds_workperiod[4] = WORKING_PERIOD; - novasds_workperiod[17] = ((novasds_workperiod[2] + novasds_workperiod[3] + novasds_workperiod[4] + novasds_workperiod[15] + novasds_workperiod[16]) & 0xFF); //checksum - - NovaSdsSerial->flush(); - NovaSdsSerial->write(novasds_workperiod, sizeof(novasds_workperiod)); - - while (NovaSdsSerial->available() > 0) { - NovaSdsSerial->read(); - } - - NovaSdsSerial->flush(); - NovaSdsSerial->write(novasds_setquerymode, sizeof(novasds_setquerymode)); - - while (NovaSdsSerial->available() > 0) { - NovaSdsSerial->read(); - } + // set sensor working period + NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, WORKING_PERIOD, NOVA_SDS_DEVICE_ID, NULL); + // set sensor report only on query + NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, NULL); } bool NovaSdsReadData(void) { - if (! NovaSdsSerial->available()) return false; - - byte d[10] = { 0 }; - NovaSdsSerial->flush(); - NovaSdsSerial->write(novasds_querydata, sizeof(novasds_querydata)); - NovaSdsSerial->readBytes(d, 10); - - AddLogSerial(LOG_LEVEL_DEBUG_MORE, d, 10); - - if (d[0] == 0xAA && d[9] == 0xAB && (d[8] == ((d[2] + d[3] + d[4] + d[5] + d[6] + d[7]) & 0xFF))) { - novasds_data.pm25 = (d[2] + 256 * d[3]); - novasds_data.pm100 = (d[4] + 256 * d[5]); - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("SDS: " D_CHECKSUM_FAILURE)); + byte d[10]; + if ( ! NovaSdsCommand(NOVA_SDS_QUERY_DATA, 0, 0, NOVA_SDS_DEVICE_ID, d) ) { return false; } + novasds_data.pm25 = (d[2] + 256 * d[3]); + novasds_data.pm100 = (d[4] + 256 * d[5]); return true; } @@ -102,11 +148,11 @@ bool NovaSdsReadData(void) void NovaSdsSecond(void) // Every second { - if (XSNS_20 == (uptime % 100)) { + if (0 == (uptime % NOVA_SDS_REINIT_CHECK)) { if (!novasds_valid) { NovaSdsSetWorkPeriod(); } - } else if (0 == (uptime % XSNS_20_QUERY_INTERVAL)) { // Every 5 seconds + } else if (0 == (uptime % NOVA_SDS_QUERY_INTERVAL)) { if (NovaSdsReadData()) { novasds_valid = 10; } else { From e34a1f0719be4e27ddcc3d2a275c342b013f9e7c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 19 Nov 2018 18:07:25 +0100 Subject: [PATCH 0520/2222] Add wifi network scan * Add command SetOption56 0/1 to enable wifi network scan and select highest RSSI (#3173) --- sonoff/_changelog.ino | 2 + sonoff/my_user_config.h | 6 +- sonoff/settings.h | 4 +- sonoff/sonoff.ino | 11 - sonoff/support.ino | 444 ---------------------------- sonoff/support_wifi.ino | 548 +++++++++++++++++++++++++++++++++++ sonoff/xdrv_01_webserver.ino | 3 + 7 files changed, 558 insertions(+), 460 deletions(-) create mode 100644 sonoff/support_wifi.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b60ebf9f0..6d13b0c17 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,7 @@ /* 6.3.0.10 20181118 * Add command SetOption36 0..255 milliseconds (50 default) to tune main loop dynamic delay + * Add support for LG HVac and IrRemote (#4377) + * Add command SetOption56 0/1 to enable wifi network scan and select highest RSSI (#3173) * * 6.3.0.9 20181118 * Moved command SetSensorXX to debugging driver freeing user code space diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 3e0efdef4..004e93a09 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -365,9 +365,9 @@ #define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) // -- Low level interface devices ----------------- -#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) -// #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) - #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) +#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k3 code, 0k3 mem, 48 iram) +// #define USE_IR_HVAC // Support for HVAC (Toshiba, Mitsubishi and LG) system using IR (+3k5 code) + #define USE_IR_RECEIVE // Support for IR receiver (+6k5 code, 264 iram) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // #define USE_WS2812_CTYPE NEO_GRB // WS2812 Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW) diff --git a/sonoff/settings.h b/sonoff/settings.h index 124314f0a..cc4d9840f 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -68,8 +68,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t time_append_timezone : 1; // bit 2 (v6.2.1.2) uint32_t gui_hostname_ip : 1; // bit 3 (v6.2.1.20) uint32_t tuya_apply_o20 : 1; // bit 4 (v6.3.0.4) - uint32_t hass_short_discovery_msg : 1; // bit 5 (vTBD) - uint32_t spare06 : 1; + uint32_t hass_short_discovery_msg : 1; // bit 5 (v6.3.0.7) + uint32_t use_wifi_scan : 1; // bit 6 (v6.3.0.10) uint32_t spare07 : 1; uint32_t spare08 : 1; uint32_t spare09 : 1; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 4930fdab4..486a3ba93 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -46,15 +46,10 @@ // Libraries #include // RTC, Energy, OSWatch -#include // MQTT, Ota, WifiManager #include // MQTT, Ota #include // Ota #include // Webserver, Updater #include // WemoHue, IRremote, Domoticz -#ifdef USE_WEBSERVER - #include // WifiManager, Webserver - #include // WifiManager -#endif // USE_WEBSERVER #ifdef USE_ARDUINO_OTA #include // Arduino OTA #ifndef USE_DISCOVERY @@ -100,12 +95,6 @@ const uint8_t kIFan02Speed[4][3] = {{6,6,6}, {7,6,6}, {7,7,6}, {7,6,7}}; // Global variables SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit -#ifdef USE_MQTT_TLS - WiFiClientSecure EspClient; // Wifi Secure Client -#else - WiFiClient EspClient; // Wifi Client -#endif - WiFiUDP PortUdp; // UDP Syslog and Alexa unsigned long feature_drv1; // Compiled driver feature map diff --git a/sonoff/support.ino b/sonoff/support.ino index 02e8ad74f..64af2e472 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1178,450 +1178,6 @@ void GetFeatures(void) } -/*********************************************************************************************\ - * Wifi -\*********************************************************************************************/ - -#define WIFI_CONFIG_SEC 180 // seconds before restart -#define WIFI_CHECK_SEC 20 // seconds -#define WIFI_RETRY_OFFSET_SEC 20 // seconds - -uint8_t wifi_counter; -uint8_t wifi_retry_init; -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 WifiGetRssiAsQuality(int rssi) -{ - int quality = 0; - - if (rssi <= -100) { - quality = 0; - } else if (rssi >= -50) { - quality = 100; - } else { - quality = 2 * (rssi + 100); - } - return quality; -} - -boolean WifiConfigCounter(void) -{ - if (wifi_config_counter) { - wifi_config_counter = WIFI_CONFIG_SEC; - } - return (wifi_config_counter); -} - -extern "C" { -#include "user_interface.h" -} - -void WifiWpsStatusCallback(wps_cb_status status); - -void WifiWpsStatusCallback(wps_cb_status status) -{ -/* from user_interface.h: - enum wps_cb_status { - WPS_CB_ST_SUCCESS = 0, - WPS_CB_ST_FAILED, - WPS_CB_ST_TIMEOUT, - WPS_CB_ST_WEP, // WPS failed because that WEP is not supported - WPS_CB_ST_SCAN_ERR, // can not find the target WPS AP - }; -*/ - 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"), wps_result); - AddLog(LOG_LEVEL_DEBUG); - wifi_config_counter = 2; - } -} - -boolean WifiWpsConfigDone(void) -{ - return (!wps_result); -} - -boolean WifiWpsConfigBegin(void) -{ - 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) &WifiWpsStatusCallback)) { return false; } - if (!wifi_wps_start()) { return false; } - return true; -} - -void WifiConfig(uint8_t type) -{ - if (!wifi_config_type) { - if ((WIFI_RETRY == type) || (WIFI_WAIT == type)) { return; } -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) - UdpDisconnect(); -#endif // USE_EMULATION - WiFi.disconnect(); // Solve possible Wifi hangs - wifi_config_type = type; - -#ifndef USE_WPS - if (WIFI_WPSCONFIG == wifi_config_type) { wifi_config_type = WIFI_MANAGER; } -#endif // USE_WPS -#ifndef USE_WEBSERVER - if (WIFI_MANAGER == wifi_config_type) { wifi_config_type = WIFI_SMARTCONFIG; } -#endif // USE_WEBSERVER -#ifndef USE_SMARTCONFIG - if (WIFI_SMARTCONFIG == wifi_config_type) { wifi_config_type = WIFI_SERIAL; } -#endif // USE_SMARTCONFIG - - 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 == wifi_config_type) { - restart_flag = 2; - } - else if (WIFI_SERIAL == wifi_config_type) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_6_SERIAL " " D_ACTIVE_FOR_3_MINUTES)); - } -#ifdef USE_SMARTCONFIG - else if (WIFI_SMARTCONFIG == wifi_config_type) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_1_SMARTCONFIG " " D_ACTIVE_FOR_3_MINUTES)); - WiFi.beginSmartConfig(); - } -#endif // USE_SMARTCONFIG -#ifdef USE_WPS - 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_3_MINUTES)); - } else { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_3_WPSCONFIG " " D_FAILED_TO_START)); - wifi_config_counter = 3; - } - } -#endif // USE_WPS -#ifdef USE_WEBSERVER - else if (WIFI_MANAGER == wifi_config_type) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_2_WIFIMANAGER " " D_ACTIVE_FOR_3_MINUTES)); - WifiManagerBegin(); - } -#endif // USE_WEBSERVER - } -} - -void WiFiSetSleepMode(void) -{ -/* Excerpt from the esp8266 non os sdk api reference (v2.2.1): - * Sets sleep type for power saving. Set WIFI_NONE_SLEEP to disable power saving. - * - Default mode: WIFI_MODEM_SLEEP. - * - In order to lower the power comsumption, ESP8266 changes the TCP timer - * tick from 250ms to 3s in WIFI_LIGHT_SLEEP mode, which leads to increased timeout for - * TCP timer. Therefore, the WIFI_MODEM_SLEEP or deep-sleep mode should be used - * where there is a requirement for the accurancy of the TCP timer. - * - * Sleep is disabled in core 2.4.1 and 2.4.2 as there are bugs in their SDKs - * See https://github.com/arendst/Sonoff-Tasmota/issues/2559 - */ - -// Sleep explanation: https://github.com/esp8266/Arduino/blob/3f0c601cfe81439ce17e9bd5d28994a7ed144482/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp#L255 -#if defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) -#else // Enabled in 2.3.0, 2.4.0 and stage - if (sleep) { - WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times - } else { - WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default) - } -#endif -} - -void WifiBegin(uint8_t flag) -{ - const char kWifiPhyMode[] = " BGN"; - -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) - UdpDisconnect(); -#endif // USE_EMULATION - -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 // (!strncmp_P(ESP.getSdkVersion(),PSTR("1.5.3"),5)) - 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 -#endif - - WiFi.persistent(false); // Solve possible wifi init errors (re-add at 6.2.1.16 #4044, #4083) - WiFi.disconnect(true); // Delete SDK wifi config - delay(200); - WiFi.mode(WIFI_STA); // Disable AP mode - WiFiSetSleepMode(); -// if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); } - if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } -// WiFi.setAutoReconnect(true); - switch (flag) { - case 0: // AP1 - case 1: // AP2 - Settings.sta_active = flag; - break; - case 2: // Toggle - Settings.sta_active ^= 1; - } // 3: Current AP - if ('\0' == Settings.sta_ssid[Settings.sta_active][0]) { Settings.sta_active ^= 1; } // Skip empty SSID - 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(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..."), - Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); - AddLog(LOG_LEVEL_INFO); -} - -void WifiSetState(uint8_t state) -{ - if (state == global_state.wifi_down) { - if (state) { - rules_flag.wifi_connected = 1; - } else { - rules_flag.wifi_disconnected = 1; - } - } - global_state.wifi_down = state ^1; -} - -void WifiCheckIp(void) -{ - if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { - WifiSetState(1); - wifi_counter = WIFI_CHECK_SEC; - wifi_retry = wifi_retry_init; - 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(); - } - wifi_status = WL_CONNECTED; - } else { - WifiSetState(0); - uint8_t wifi_config_tool = Settings.sta_config; - 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)); - wifi_status = 0; - wifi_retry = wifi_retry_init; - break; - case WL_NO_SSID_AVAIL: - 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_init; - } else { - if (wifi_retry > (wifi_retry_init / 2)) { - wifi_retry = wifi_retry_init / 2; - } - 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 (wifi_retry > (wifi_retry_init / 2)) { - wifi_retry = wifi_retry_init / 2; - } - else if (wifi_retry) { - wifi_retry = 0; - } - break; - default: // WL_IDLE_STATUS and WL_DISCONNECTED - if (!wifi_retry || ((wifi_retry_init / 2) == wifi_retry)) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); - } else { - if (('\0' == Settings.sta_ssid[0][0]) && ('\0' == Settings.sta_ssid[1][0])) { - wifi_config_tool = WIFI_CONFIG_NO_SSID; // Skip empty SSIDs and start Wifi config tool - wifi_retry = 0; - } else { - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_ATTEMPTING_CONNECTION)); - } - } - } - if (wifi_retry) { - if (wifi_retry_init == wifi_retry) { - WifiBegin(3); // Select default SSID - } - if ((Settings.sta_config != WIFI_WAIT) && ((wifi_retry_init / 2) == wifi_retry)) { - WifiBegin(2); // Select alternate SSID - } - wifi_counter = 1; - wifi_retry--; - } else { - WifiConfig(wifi_config_tool); - wifi_counter = 1; - wifi_retry = wifi_retry_init; - } - } -} - -void WifiCheck(uint8_t param) -{ - wifi_counter--; - switch (param) { - case WIFI_SERIAL: - case WIFI_SMARTCONFIG: - case WIFI_MANAGER: - case WIFI_WPSCONFIG: - WifiConfig(param); - break; - default: - if (wifi_config_counter) { - wifi_config_counter--; - wifi_counter = wifi_config_counter +5; - if (wifi_config_counter) { -#ifdef USE_SMARTCONFIG - if ((WIFI_SMARTCONFIG == wifi_config_type) && WiFi.smartConfigDone()) { - wifi_config_counter = 0; - } -#endif // USE_SMARTCONFIG -#ifdef USE_WPS - if ((WIFI_WPSCONFIG == wifi_config_type) && WifiWpsConfigDone()) { - wifi_config_counter = 0; - } -#endif // USE_WPS - if (!wifi_config_counter) { - if (strlen(WiFi.SSID().c_str())) { - strlcpy(Settings.sta_ssid[0], WiFi.SSID().c_str(), sizeof(Settings.sta_ssid[0])); - } - if (strlen(WiFi.psk().c_str())) { - strlcpy(Settings.sta_pwd[0], WiFi.psk().c_str(), sizeof(Settings.sta_pwd[0])); - } - Settings.sta_active = 0; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_WCFG_1_SMARTCONFIG D_CMND_SSID "1 %s"), Settings.sta_ssid[0]); - AddLog(LOG_LEVEL_INFO); - } - } - if (!wifi_config_counter) { -#ifdef USE_SMARTCONFIG - if (WIFI_SMARTCONFIG == wifi_config_type) { WiFi.stopSmartConfig(); } -#endif // USE_SMARTCONFIG -// SettingsSdkErase(); // Disabled v6.1.0b due to possible bad wifi connects - restart_flag = 2; - } - } else { - 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) && !wifi_config_type) { - WifiSetState(1); -#ifdef BE_MINIMAL - if (1 == RtcSettings.ota_loader) { - RtcSettings.ota_loader = 0; - ota_state_flag = 3; - } -#endif // BE_MINIMAL - -#ifdef USE_DISCOVERY - if (!mdns_begun) { - if (mdns_delayed_start) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_ATTEMPTING_CONNECTION)); - mdns_delayed_start--; - } else { - mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; - mdns_begun = MDNS.begin(my_hostname); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS "%s"), (mdns_begun) ? D_INITIALIZED : D_FAILED); - AddLog(LOG_LEVEL_INFO); - } - } -#endif // USE_DISCOVERY - -#ifdef USE_WEBSERVER - if (Settings.webserver) { - StartWebserver(Settings.webserver, WiFi.localIP()); -#ifdef USE_DISCOVERY -#ifdef WEBSERVER_ADVERTISE - if (mdns_begun) { - MDNS.addService("http", "tcp", WEB_PORT); - } -#endif // WEBSERVER_ADVERTISE -#endif // USE_DISCOVERY - } else { - StopWebserver(); - } -#ifdef USE_EMULATION - if (Settings.flag2.emulation) { UdpConnect(); } -#endif // USE_EMULATION -#endif // USE_WEBSERVER - -#ifdef USE_KNX - if (!knx_started && Settings.flag.knx_enabled) { - KNXStart(); - knx_started = true; - } -#endif // USE_KNX - - } else { - WifiSetState(0); -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) - UdpDisconnect(); -#endif // USE_EMULATION - mdns_begun = false; -#ifdef USE_KNX - knx_started = false; -#endif // USE_KNX - } - } - } -} - -int WifiState(void) -{ - int state = -1; - - if (!global_state.wifi_down) { state = WIFI_RESTART; } - if (wifi_config_type) { state = wifi_config_type; } - return state; -} - -void WifiConnect(void) -{ - WifiSetState(0); - WiFi.persistent(false); // Solve possible wifi init errors - wifi_status = 0; - wifi_retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); - wifi_retry = wifi_retry_init; - wifi_counter = 1; -} - -// Enable from 6.0.0a until 6.1.0a - disabled due to possible cause of bad wifi connect on core 2.3.0 -// Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset -void WifiDisconnect(void) -{ - // Courtesy of EspEasy - WiFi.persistent(true); // use SDK storage of SSID/WPA parameters - ETS_UART_INTR_DISABLE(); - wifi_station_disconnect(); // this will store empty ssid/wpa into sdk storage - ETS_UART_INTR_ENABLE(); - WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters -} - -void EspRestart(void) -{ - delay(100); // Allow time for message xfer - disabled v6.1.0b - WifiDisconnect(); -// ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 - ESP.reset(); -} - -/* -void EspRestart(void) -{ - ESP.restart(); -} -*/ - /*********************************************************************************************\ * Basic I2C routines \*********************************************************************************************/ diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino new file mode 100644 index 000000000..dbd0f24a5 --- /dev/null +++ b/sonoff/support_wifi.ino @@ -0,0 +1,548 @@ +/* + support_wifi.ino - wifi support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 . +*/ + +/*********************************************************************************************\ + * Wifi +\*********************************************************************************************/ + +#define WIFI_CONFIG_SEC 180 // seconds before restart +#define WIFI_CHECK_SEC 20 // seconds +#define WIFI_RETRY_OFFSET_SEC 20 // seconds + +#include // Wifi, MQTT, Ota, WifiManager +#include + +#ifdef USE_MQTT_TLS + WiFiClientSecure EspClient; // Wifi Secure Client +#else + WiFiClient EspClient; // Wifi Client +#endif + +uint8_t wifi_counter; +uint8_t wifi_retry_init; +uint8_t wifi_retry; +uint8_t wifi_status; +uint8_t wps_result; +uint8_t wifi_config_type = 0; +uint8_t wifi_config_counter = 0; + +uint8_t wifi_scan_state; +int8_t wifi_best_ap = 3; +uint8_t wifi_best_bssid[6]; +int32_t wifi_best_channel; + +int WifiGetRssiAsQuality(int rssi) +{ + int quality = 0; + + if (rssi <= -100) { + quality = 0; + } else if (rssi >= -50) { + quality = 100; + } else { + quality = 2 * (rssi + 100); + } + return quality; +} + +boolean WifiConfigCounter(void) +{ + if (wifi_config_counter) { + wifi_config_counter = WIFI_CONFIG_SEC; + } + return (wifi_config_counter); +} + +extern "C" { +#include "user_interface.h" +} + +void WifiWpsStatusCallback(wps_cb_status status); + +void WifiWpsStatusCallback(wps_cb_status status) +{ +/* from user_interface.h: + enum wps_cb_status { + WPS_CB_ST_SUCCESS = 0, + WPS_CB_ST_FAILED, + WPS_CB_ST_TIMEOUT, + WPS_CB_ST_WEP, // WPS failed because that WEP is not supported + WPS_CB_ST_SCAN_ERR, // can not find the target WPS AP + }; +*/ + 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"), wps_result); + AddLog(LOG_LEVEL_DEBUG); + wifi_config_counter = 2; + } +} + +boolean WifiWpsConfigDone(void) +{ + return (!wps_result); +} + +boolean WifiWpsConfigBegin(void) +{ + 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) &WifiWpsStatusCallback)) { return false; } + if (!wifi_wps_start()) { return false; } + return true; +} + +void WifiConfig(uint8_t type) +{ + if (!wifi_config_type) { + if ((WIFI_RETRY == type) || (WIFI_WAIT == type)) { return; } +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) + UdpDisconnect(); +#endif // USE_EMULATION + WiFi.disconnect(); // Solve possible Wifi hangs + wifi_config_type = type; + +#ifndef USE_WPS + if (WIFI_WPSCONFIG == wifi_config_type) { wifi_config_type = WIFI_MANAGER; } +#endif // USE_WPS +#ifndef USE_WEBSERVER + if (WIFI_MANAGER == wifi_config_type) { wifi_config_type = WIFI_SMARTCONFIG; } +#endif // USE_WEBSERVER +#ifndef USE_SMARTCONFIG + if (WIFI_SMARTCONFIG == wifi_config_type) { wifi_config_type = WIFI_SERIAL; } +#endif // USE_SMARTCONFIG + + 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 == wifi_config_type) { + restart_flag = 2; + } + else if (WIFI_SERIAL == wifi_config_type) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_6_SERIAL " " D_ACTIVE_FOR_3_MINUTES)); + } +#ifdef USE_SMARTCONFIG + else if (WIFI_SMARTCONFIG == wifi_config_type) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_1_SMARTCONFIG " " D_ACTIVE_FOR_3_MINUTES)); + WiFi.beginSmartConfig(); + } +#endif // USE_SMARTCONFIG +#ifdef USE_WPS + 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_3_MINUTES)); + } else { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_3_WPSCONFIG " " D_FAILED_TO_START)); + wifi_config_counter = 3; + } + } +#endif // USE_WPS +#ifdef USE_WEBSERVER + else if (WIFI_MANAGER == wifi_config_type) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_2_WIFIMANAGER " " D_ACTIVE_FOR_3_MINUTES)); + WifiManagerBegin(); + } +#endif // USE_WEBSERVER + } +} + +void WiFiSetSleepMode(void) +{ +/* Excerpt from the esp8266 non os sdk api reference (v2.2.1): + * Sets sleep type for power saving. Set WIFI_NONE_SLEEP to disable power saving. + * - Default mode: WIFI_MODEM_SLEEP. + * - In order to lower the power comsumption, ESP8266 changes the TCP timer + * tick from 250ms to 3s in WIFI_LIGHT_SLEEP mode, which leads to increased timeout for + * TCP timer. Therefore, the WIFI_MODEM_SLEEP or deep-sleep mode should be used + * where there is a requirement for the accurancy of the TCP timer. + * + * Sleep is disabled in core 2.4.1 and 2.4.2 as there are bugs in their SDKs + * See https://github.com/arendst/Sonoff-Tasmota/issues/2559 + */ + +// Sleep explanation: https://github.com/esp8266/Arduino/blob/3f0c601cfe81439ce17e9bd5d28994a7ed144482/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp#L255 +#if defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) +#else // Enabled in 2.3.0, 2.4.0 and stage + if (sleep) { + WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times + } else { + WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default) + } +#endif +} + +void WifiBegin(uint8_t flag) +{ + const char kWifiPhyMode[] = " BGN"; + +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) + UdpDisconnect(); +#endif // USE_EMULATION + +#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 // (!strncmp_P(ESP.getSdkVersion(),PSTR("1.5.3"),5)) + 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 +#endif + + WiFi.persistent(false); // Solve possible wifi init errors (re-add at 6.2.1.16 #4044, #4083) + WiFi.disconnect(true); // Delete SDK wifi config + delay(200); + WiFi.mode(WIFI_STA); // Disable AP mode + WiFiSetSleepMode(); +// if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); } + if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } +// WiFi.setAutoReconnect(true); + switch (flag) { + case 0: // AP1 + case 1: // AP2 + Settings.sta_active = flag; + break; + case 2: // Toggle + Settings.sta_active ^= 1; + } // 3: Current AP + if ('\0' == Settings.sta_ssid[Settings.sta_active][0]) { Settings.sta_active ^= 1; } // Skip empty SSID + 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(my_hostname); + if (wifi_best_ap < 3) { + WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active], wifi_best_channel, wifi_best_bssid); + } else { + 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..."), + Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); + AddLog(LOG_LEVEL_INFO); +} + +void WifiSetState(uint8_t state) +{ + if (state == global_state.wifi_down) { + if (state) { + rules_flag.wifi_connected = 1; + } else { + rules_flag.wifi_disconnected = 1; + } + } + global_state.wifi_down = state ^1; +} + +void WifiCheckIp(void) +{ + if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { + WifiSetState(1); + wifi_counter = WIFI_CHECK_SEC; + wifi_retry = wifi_retry_init; + 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(); + } + wifi_status = WL_CONNECTED; + } else { + WifiSetState(0); + uint8_t wifi_config_tool = Settings.sta_config; + 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)); + wifi_status = 0; + wifi_retry = wifi_retry_init; + break; + case WL_NO_SSID_AVAIL: + 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_init; + } else { + if (wifi_retry > (wifi_retry_init / 2)) { + wifi_retry = wifi_retry_init / 2; + } + 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 (wifi_retry > (wifi_retry_init / 2)) { + wifi_retry = wifi_retry_init / 2; + } + else if (wifi_retry) { + wifi_retry = 0; + } + break; + default: // WL_IDLE_STATUS and WL_DISCONNECTED + if (!wifi_retry || ((wifi_retry_init / 2) == wifi_retry)) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); + } else { + if (('\0' == Settings.sta_ssid[0][0]) && ('\0' == Settings.sta_ssid[1][0])) { + wifi_config_tool = WIFI_CONFIG_NO_SSID; // Skip empty SSIDs and start Wifi config tool + wifi_retry = 0; + } else { + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_ATTEMPTING_CONNECTION)); + } + } + } + if (wifi_retry) { + if (!Settings.flag3.use_wifi_scan) { + if (wifi_retry_init == wifi_retry) { + WifiBegin(3); // Select default SSID + } + if ((Settings.sta_config != WIFI_WAIT) && ((wifi_retry_init / 2) == wifi_retry)) { + WifiBegin(2); // Select alternate SSID + } + } else { + if (wifi_retry_init == wifi_retry) { + wifi_best_ap = 3; + wifi_scan_state = 1; + } + if (1 == wifi_scan_state) { + if (WiFi.scanComplete() != WIFI_SCAN_RUNNING) { + WiFi.disconnect(); + WiFi.scanNetworks(true); // Start wifi scan async + wifi_scan_state = 2; + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR("Network scan started...")); + } + } + int8_t wifi_scan_result = WiFi.scanComplete(); + if (2 == wifi_scan_state) { // Scan started + if (wifi_scan_result != WIFI_SCAN_RUNNING) { + wifi_scan_state = 3; + } + } + if (3 == wifi_scan_state) { // Scan done + if (wifi_scan_result > 0) { + int best_network_db = INT_MIN; + for (int8_t i = 0; i < wifi_scan_result; ++i) { + String ssid_scan; + int32_t rssi_scan; + uint8_t sec_scan; + uint8_t* bssid_scan; + int32_t chan_scan; + bool hidden_scan; + + WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, bssid_scan, chan_scan, hidden_scan); + + bool known = false; + uint8_t j; + for (j = 0; j < 2; j++) { + if (ssid_scan == Settings.sta_ssid[j]) { // SSID match + known = true; + if (rssi_scan > best_network_db) { // Best network + if (sec_scan == ENC_TYPE_NONE || Settings.sta_pwd[j]) { // Check for passphrase if not open wlan + best_network_db = rssi_scan; + wifi_best_channel = chan_scan; + wifi_best_ap = j; + memcpy((void*) &wifi_best_bssid, (void*) bssid_scan, sizeof(wifi_best_bssid)); + } + } + break; + } + } + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI "Network %d, AP%c, SSId %s, Channel %d, BSSId %02X:%02X:%02X:%02X:%02X:%02X, RSSI %d, Encryption %d"), + i, (known) ? (j) ? '2' : '1' : '-', ssid_scan.c_str(), chan_scan, bssid_scan[0], bssid_scan[1], bssid_scan[2], bssid_scan[3], bssid_scan[4], bssid_scan[5], rssi_scan, (sec_scan == ENC_TYPE_NONE) ? 0 : 1); + AddLog(LOG_LEVEL_DEBUG); + delay(0); + } + WiFi.scanDelete(); // Clean up ram + delay(0); + } else { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR("No network found")); + } + wifi_scan_state = 4; + } + if (4 == wifi_scan_state) { // Strongest found + WifiBegin(wifi_best_ap); // Select strongest or default SSID + wifi_scan_state = 0; + } + } + + wifi_counter = 1; + wifi_retry--; + } else { + WifiConfig(wifi_config_tool); + wifi_counter = 1; + wifi_retry = wifi_retry_init; + } + } +} + +void WifiCheck(uint8_t param) +{ + wifi_counter--; + switch (param) { + case WIFI_SERIAL: + case WIFI_SMARTCONFIG: + case WIFI_MANAGER: + case WIFI_WPSCONFIG: + WifiConfig(param); + break; + default: + if (wifi_config_counter) { + wifi_config_counter--; + wifi_counter = wifi_config_counter +5; + if (wifi_config_counter) { +#ifdef USE_SMARTCONFIG + if ((WIFI_SMARTCONFIG == wifi_config_type) && WiFi.smartConfigDone()) { + wifi_config_counter = 0; + } +#endif // USE_SMARTCONFIG +#ifdef USE_WPS + if ((WIFI_WPSCONFIG == wifi_config_type) && WifiWpsConfigDone()) { + wifi_config_counter = 0; + } +#endif // USE_WPS + if (!wifi_config_counter) { + if (strlen(WiFi.SSID().c_str())) { + strlcpy(Settings.sta_ssid[0], WiFi.SSID().c_str(), sizeof(Settings.sta_ssid[0])); + } + if (strlen(WiFi.psk().c_str())) { + strlcpy(Settings.sta_pwd[0], WiFi.psk().c_str(), sizeof(Settings.sta_pwd[0])); + } + Settings.sta_active = 0; + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_WCFG_1_SMARTCONFIG D_CMND_SSID "1 %s"), Settings.sta_ssid[0]); + AddLog(LOG_LEVEL_INFO); + } + } + if (!wifi_config_counter) { +#ifdef USE_SMARTCONFIG + if (WIFI_SMARTCONFIG == wifi_config_type) { WiFi.stopSmartConfig(); } +#endif // USE_SMARTCONFIG +// SettingsSdkErase(); // Disabled v6.1.0b due to possible bad wifi connects + restart_flag = 2; + } + } else { + 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) && !wifi_config_type) { + WifiSetState(1); +#ifdef BE_MINIMAL + if (1 == RtcSettings.ota_loader) { + RtcSettings.ota_loader = 0; + ota_state_flag = 3; + } +#endif // BE_MINIMAL + +#ifdef USE_DISCOVERY + if (!mdns_begun) { + if (mdns_delayed_start) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_ATTEMPTING_CONNECTION)); + mdns_delayed_start--; + } else { + mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; + mdns_begun = MDNS.begin(my_hostname); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS "%s"), (mdns_begun) ? D_INITIALIZED : D_FAILED); + AddLog(LOG_LEVEL_INFO); + } + } +#endif // USE_DISCOVERY + +#ifdef USE_WEBSERVER + if (Settings.webserver) { + StartWebserver(Settings.webserver, WiFi.localIP()); +#ifdef USE_DISCOVERY +#ifdef WEBSERVER_ADVERTISE + if (mdns_begun) { + MDNS.addService("http", "tcp", WEB_PORT); + } +#endif // WEBSERVER_ADVERTISE +#endif // USE_DISCOVERY + } else { + StopWebserver(); + } +#ifdef USE_EMULATION + if (Settings.flag2.emulation) { UdpConnect(); } +#endif // USE_EMULATION +#endif // USE_WEBSERVER + +#ifdef USE_KNX + if (!knx_started && Settings.flag.knx_enabled) { + KNXStart(); + knx_started = true; + } +#endif // USE_KNX + + } else { + WifiSetState(0); +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) + UdpDisconnect(); +#endif // USE_EMULATION + mdns_begun = false; +#ifdef USE_KNX + knx_started = false; +#endif // USE_KNX + } + } + } +} + +int WifiState(void) +{ + int state = -1; + + if (!global_state.wifi_down) { state = WIFI_RESTART; } + if (wifi_config_type) { state = wifi_config_type; } + return state; +} + +void WifiConnect(void) +{ + WifiSetState(0); + WiFi.persistent(false); // Solve possible wifi init errors + wifi_status = 0; + wifi_retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); + wifi_retry = wifi_retry_init; + wifi_counter = 1; +} + +// Enable from 6.0.0a until 6.1.0a - disabled due to possible cause of bad wifi connect on core 2.3.0 +// Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset +void WifiDisconnect(void) +{ + // Courtesy of EspEasy + WiFi.persistent(true); // use SDK storage of SSID/WPA parameters + ETS_UART_INTR_DISABLE(); + wifi_station_disconnect(); // this will store empty ssid/wpa into sdk storage + ETS_UART_INTR_ENABLE(); + WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters +} + +void EspRestart(void) +{ + delay(100); // Allow time for message xfer - disabled v6.1.0b + WifiDisconnect(); +// ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 + ESP.reset(); +} + +/* +void EspRestart(void) +{ + ESP.restart(); +} +*/ + diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index a4cf8c137..85f1c71e2 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -29,6 +29,9 @@ #define HTTP_REFRESH_TIME 2345 // milliseconds +#include // WifiManager, Webserver +#include // WifiManager + #ifdef USE_RF_FLASH uint8_t *efm8bb1_update = NULL; #endif // USE_RF_FLASH From 93cb0a18a9bb13eeb391e36055dc9eac6bde7e05 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 19 Nov 2018 18:14:53 +0100 Subject: [PATCH 0521/2222] Update support_wifi.ino Fix undefine --- sonoff/support_wifi.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index dbd0f24a5..177bb5849 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -333,7 +333,7 @@ void WifiCheckIp(void) } if (3 == wifi_scan_state) { // Scan done if (wifi_scan_result > 0) { - int best_network_db = INT_MIN; + int best_network_db = -2147483646; for (int8_t i = 0; i < wifi_scan_result; ++i) { String ssid_scan; int32_t rssi_scan; From bf90e60f99c2cf0a6f1be59ad96c3c43cfae1dd4 Mon Sep 17 00:00:00 2001 From: Alexander Savchenko Date: Mon, 19 Nov 2018 20:39:44 +0200 Subject: [PATCH 0522/2222] Fujitsu HVAC support --- .../src/IRremoteESP8266.h | 2 +- sonoff/xdrv_05_irremote.ino | 54 ++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h b/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h index f2c730dee..52c8b6e10 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h +++ b/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h @@ -196,7 +196,7 @@ #define SEND_MITSUBISHI_AC true #define DECODE_FUJITSU_AC false // Not written. -#define SEND_FUJITSU_AC false +#define SEND_FUJITSU_AC true #define DECODE_DAIKIN false // Not finished. #define SEND_DAIKIN false diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 03f3a739f..4f71fd6d9 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -33,6 +33,7 @@ const char kIrRemoteProtocols[] PROGMEM = #ifdef USE_IR_HVAC #include +#include // HVAC TOSHIBA_ #define HVAC_TOSHIBA_HDR_MARK 4400 @@ -136,7 +137,56 @@ void IrReceiveCheck(void) #endif // USE_IR_RECEIVE #ifdef USE_IR_HVAC -/*********************************************************************************************\ + +boolean IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) +{ + const char kFujitsuHvacModeOptions[] = "HDCAF"; + + char stemp[64]; + snprintf_P(stemp, sizeof(stemp), PSTR("FUJITSU: mode:%s, fan:%s, power:%u, temp:%u"), HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); + IRFujitsuAC ac(pin[GPIO_IRSEND]); + + if (HVAC_Power == 0) { + ac.off(); + ac.send(); + return false; + } + + byte modes[5] = {FUJITSU_AC_MODE_HEAT, FUJITSU_AC_MODE_DRY, FUJITSU_AC_MODE_COOL, FUJITSU_AC_MODE_AUTO, FUJITSU_AC_MODE_FAN}; + byte fanModes[7] = {FUJITSU_AC_FAN_AUTO, FUJITSU_AC_FAN_LOW, FUJITSU_AC_FAN_MED, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_QUIET}; + ac.setCmd(FUJITSU_AC_CMD_TURN_ON); + ac.setSwing(FUJITSU_AC_SWING_VERT); + + char *p; + if (HVAC_Mode == NULL) { + p = (char *)kFujitsuHvacModeOptions; + } + else { + p = strchr(kFujitsuHvacModeOptions, toupper(HVAC_Mode[0])); + } + if (!p) { + return true; + } + ac.setMode(modes[p - kFujitsuHvacModeOptions]); + + if (HVAC_FanMode == NULL) { + p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO + } + else { + p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); + } + if (!p) { + return true; + } + ac.setFanSpeed(fanModes[p - kFanSpeedOptions]); + + ac.setTemp(HVAC_Temp); + ac.send(); + + return false; +} + +/********************************************************************************************* \ * IR Heating, Ventilation and Air Conditioning using IRMitsubishiAC library \*********************************************************************************************/ @@ -512,6 +562,8 @@ boolean IrSendCommand(void) } else if (!strcasecmp_P(HVAC_Vendor, PSTR("LG"))) { error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); + else if (!strcasecmp_P(HVAC_Vendor, PSTR("FUJITSU"))) { + error = IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); } else { error = true; From c502f0934fa752bbebf8918120a0d212853d91c3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 19 Nov 2018 23:06:42 +0100 Subject: [PATCH 0523/2222] Add command SetOption57 * Add command SetOption57 0/1 to enable wifi network re-scan every 44 minutes with a rssi threshold of 10 to select highest RSSI (#3173) * Fix MQTT connection error after restart --- sonoff/_changelog.ino | 2 + sonoff/settings.h | 2 +- sonoff/support_wifi.ino | 176 ++++++++++++++++++++++++---------------- 3 files changed, 108 insertions(+), 72 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 6d13b0c17..0847a8347 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,8 @@ * Add command SetOption36 0..255 milliseconds (50 default) to tune main loop dynamic delay * Add support for LG HVac and IrRemote (#4377) * Add command SetOption56 0/1 to enable wifi network scan and select highest RSSI (#3173) + * Add command SetOption57 0/1 to enable wifi network re-scan every 44 minutes with a rssi threshold of 10 to select highest RSSI (#3173) + * Fix MQTT connection error after restart * * 6.3.0.9 20181118 * Moved command SetSensorXX to debugging driver freeing user code space diff --git a/sonoff/settings.h b/sonoff/settings.h index cc4d9840f..14ae43faf 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -70,7 +70,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t tuya_apply_o20 : 1; // bit 4 (v6.3.0.4) uint32_t hass_short_discovery_msg : 1; // bit 5 (v6.3.0.7) uint32_t use_wifi_scan : 1; // bit 6 (v6.3.0.10) - uint32_t spare07 : 1; + uint32_t use_wifi_rescan : 1; // bit 7 (v6.3.0.10) uint32_t spare08 : 1; uint32_t spare09 : 1; uint32_t spare10 : 1; diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 177bb5849..e6464dc94 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -26,7 +26,6 @@ #define WIFI_RETRY_OFFSET_SEC 20 // seconds #include // Wifi, MQTT, Ota, WifiManager -#include #ifdef USE_MQTT_TLS WiFiClientSecure EspClient; // Wifi Secure Client @@ -43,9 +42,7 @@ uint8_t wifi_config_type = 0; uint8_t wifi_config_counter = 0; uint8_t wifi_scan_state; -int8_t wifi_best_ap = 3; -uint8_t wifi_best_bssid[6]; -int32_t wifi_best_channel; +uint8_t wifi_bssid[6]; int WifiGetRssiAsQuality(int rssi) { @@ -190,7 +187,7 @@ void WiFiSetSleepMode(void) #endif } -void WifiBegin(uint8_t flag) +void WifiBegin(uint8_t flag, uint8_t channel) { const char kWifiPhyMode[] = " BGN"; @@ -210,7 +207,7 @@ void WifiBegin(uint8_t flag) WiFiSetSleepMode(); // if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); } if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } -// WiFi.setAutoReconnect(true); + WiFi.setAutoReconnect(true); switch (flag) { case 0: // AP1 case 1: // AP2 @@ -224,8 +221,8 @@ void WifiBegin(uint8_t flag) WiFi.config(Settings.ip_address[0], Settings.ip_address[1], Settings.ip_address[2], Settings.ip_address[3]); // Set static IP } WiFi.hostname(my_hostname); - if (wifi_best_ap < 3) { - WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active], wifi_best_channel, wifi_best_bssid); + if (channel) { + WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active], channel, wifi_bssid); } else { WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active]); } @@ -234,6 +231,94 @@ void WifiBegin(uint8_t flag) AddLog(LOG_LEVEL_INFO); } +void WifiBeginAfterScan() +{ + static int8_t rssi_threshold; + + // Not active + if (0 == wifi_scan_state) { return; } + // Init scan when not connected + if (1 == wifi_scan_state) { + memset((void*) &wifi_bssid, 0, sizeof(wifi_bssid)); + rssi_threshold = 0; + wifi_scan_state = 3; + } + // Init scan when connected + if (2 == wifi_scan_state) { + rssi_threshold = 10; + wifi_scan_state = 3; + } + // Init scan + if (3 == wifi_scan_state) { + if (WiFi.scanComplete() != WIFI_SCAN_RUNNING) { + WiFi.scanNetworks(true); // Start wifi scan async + wifi_scan_state++; + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR("Network (re)scan started...")); + return; + } + } + int8_t wifi_scan_result = WiFi.scanComplete(); + // Check scan done + if (4 == wifi_scan_state) { + if (wifi_scan_result != WIFI_SCAN_RUNNING) { + wifi_scan_state++; + } + } + // Scan done + if (5 == wifi_scan_state) { + int32_t channel = 0; // No scan result + int8_t ap = 3; // AP default if not found + uint8_t last_bssid[6]; + memcpy((void*) &last_bssid, (void*) &wifi_bssid, sizeof(last_bssid)); + + if (wifi_scan_result > 0) { + // Networks found + int32_t best_network_db = -127; + for (int8_t i = 0; i < wifi_scan_result; ++i) { + + String ssid_scan; + int32_t rssi_scan; + uint8_t sec_scan; + uint8_t* bssid_scan; + int32_t chan_scan; + bool hidden_scan; + + WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, bssid_scan, chan_scan, hidden_scan); + + bool known = false; + uint8_t j; + for (j = 0; j < 2; j++) { + if (ssid_scan == Settings.sta_ssid[j]) { // SSID match + known = true; + if (rssi_scan > (best_network_db + rssi_threshold)) { // Best network + if (sec_scan == ENC_TYPE_NONE || Settings.sta_pwd[j]) { // Check for passphrase if not open wlan + best_network_db = rssi_scan; + channel = chan_scan; + ap = j; // AP1 or AP2 + memcpy((void*) &wifi_bssid, (void*) bssid_scan, sizeof(wifi_bssid)); + } + } + break; + } + } + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI "Network %d, AP%c, SSId %s, Channel %d, BSSId %02X:%02X:%02X:%02X:%02X:%02X, RSSI %d, Encryption %d"), + i, (known) ? (j) ? '2' : '1' : '-', ssid_scan.c_str(), chan_scan, bssid_scan[0], bssid_scan[1], bssid_scan[2], bssid_scan[3], bssid_scan[4], bssid_scan[5], rssi_scan, (sec_scan == ENC_TYPE_NONE) ? 0 : 1); + AddLog(LOG_LEVEL_DEBUG); + delay(0); + } + WiFi.scanDelete(); // Clean up Ram + delay(0); + } + wifi_scan_state = 0; + for (uint8_t i = 0; i < sizeof(wifi_bssid); i++) { + if (last_bssid[i] != wifi_bssid[i]) { + WifiBegin(ap, channel); // 0 (AP1), 1 (AP2) or 3 (default AP) + break; + } + } + } +} + void WifiSetState(uint8_t state) { if (state == global_state.wifi_down) { @@ -307,77 +392,16 @@ void WifiCheckIp(void) if (wifi_retry) { if (!Settings.flag3.use_wifi_scan) { if (wifi_retry_init == wifi_retry) { - WifiBegin(3); // Select default SSID + WifiBegin(3, 0); // Select default SSID } if ((Settings.sta_config != WIFI_WAIT) && ((wifi_retry_init / 2) == wifi_retry)) { - WifiBegin(2); // Select alternate SSID + WifiBegin(2, 0); // Select alternate SSID } } else { if (wifi_retry_init == wifi_retry) { - wifi_best_ap = 3; wifi_scan_state = 1; } - if (1 == wifi_scan_state) { - if (WiFi.scanComplete() != WIFI_SCAN_RUNNING) { - WiFi.disconnect(); - WiFi.scanNetworks(true); // Start wifi scan async - wifi_scan_state = 2; - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR("Network scan started...")); - } - } - int8_t wifi_scan_result = WiFi.scanComplete(); - if (2 == wifi_scan_state) { // Scan started - if (wifi_scan_result != WIFI_SCAN_RUNNING) { - wifi_scan_state = 3; - } - } - if (3 == wifi_scan_state) { // Scan done - if (wifi_scan_result > 0) { - int best_network_db = -2147483646; - for (int8_t i = 0; i < wifi_scan_result; ++i) { - String ssid_scan; - int32_t rssi_scan; - uint8_t sec_scan; - uint8_t* bssid_scan; - int32_t chan_scan; - bool hidden_scan; - - WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, bssid_scan, chan_scan, hidden_scan); - - bool known = false; - uint8_t j; - for (j = 0; j < 2; j++) { - if (ssid_scan == Settings.sta_ssid[j]) { // SSID match - known = true; - if (rssi_scan > best_network_db) { // Best network - if (sec_scan == ENC_TYPE_NONE || Settings.sta_pwd[j]) { // Check for passphrase if not open wlan - best_network_db = rssi_scan; - wifi_best_channel = chan_scan; - wifi_best_ap = j; - memcpy((void*) &wifi_best_bssid, (void*) bssid_scan, sizeof(wifi_best_bssid)); - } - } - break; - } - } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI "Network %d, AP%c, SSId %s, Channel %d, BSSId %02X:%02X:%02X:%02X:%02X:%02X, RSSI %d, Encryption %d"), - i, (known) ? (j) ? '2' : '1' : '-', ssid_scan.c_str(), chan_scan, bssid_scan[0], bssid_scan[1], bssid_scan[2], bssid_scan[3], bssid_scan[4], bssid_scan[5], rssi_scan, (sec_scan == ENC_TYPE_NONE) ? 0 : 1); - AddLog(LOG_LEVEL_DEBUG); - delay(0); - } - WiFi.scanDelete(); // Clean up ram - delay(0); - } else { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR("No network found")); - } - wifi_scan_state = 4; - } - if (4 == wifi_scan_state) { // Strongest found - WifiBegin(wifi_best_ap); // Select strongest or default SSID - wifi_scan_state = 0; - } } - wifi_counter = 1; wifi_retry--; } else { @@ -433,6 +457,8 @@ void WifiCheck(uint8_t param) restart_flag = 2; } } else { + WifiBeginAfterScan(); + if (wifi_counter <= 0) { AddLog_P(LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CHECKING_CONNECTION)); wifi_counter = WIFI_CHECK_SEC; @@ -440,6 +466,13 @@ void WifiCheck(uint8_t param) } if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0) && !wifi_config_type) { WifiSetState(1); + + if (Settings.flag3.use_wifi_rescan) { + if (!(uptime % (60 * 44))) { + wifi_scan_state = 2; + } + } + #ifdef BE_MINIMAL if (1 == RtcSettings.ota_loader) { RtcSettings.ota_loader = 0; @@ -534,6 +567,7 @@ void WifiDisconnect(void) void EspRestart(void) { delay(100); // Allow time for message xfer - disabled v6.1.0b + if (Settings.flag.mqtt_enabled) MqttDisconnect(); WifiDisconnect(); // ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 ESP.reset(); From ca24d20551226233e209e8665a08bc31fd8417da Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 20 Nov 2018 00:08:29 -0300 Subject: [PATCH 0524/2222] Update de-DE.h #4388 --- sonoff/language/de-DE.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 9c2f7c24e..f0f9e0f17 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -116,10 +116,10 @@ #define D_NOISE "Lautstärke" #define D_NONE "keine" #define D_OFF "aus" -#define D_OFFLINE "offline" +#define D_OFFLINE "Offline" #define D_OK "OK" #define D_ON "an" -#define D_ONLINE "online" +#define D_ONLINE "Online" #define D_PASSWORD "Passwort" #define D_PORT "Port" #define D_POWER_FACTOR "Leistungsfaktor" From 5ee6922da926d7a37169a100870031861f7c49e2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 20 Nov 2018 12:03:42 +0100 Subject: [PATCH 0525/2222] Fix wifi re-scan connection baseline Fix wifi re-scan connection baseline --- sonoff/_changelog.ino | 1 + sonoff/support_wifi.ino | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0847a8347..3a3e18910 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,6 +4,7 @@ * Add command SetOption56 0/1 to enable wifi network scan and select highest RSSI (#3173) * Add command SetOption57 0/1 to enable wifi network re-scan every 44 minutes with a rssi threshold of 10 to select highest RSSI (#3173) * Fix MQTT connection error after restart + * Fix wifi re-scan connection baseline * * 6.3.0.9 20181118 * Moved command SetSensorXX to debugging driver freeing user code space diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index e6464dc94..4c5546687 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -231,21 +231,26 @@ void WifiBegin(uint8_t flag, uint8_t channel) AddLog(LOG_LEVEL_INFO); } +#define WIFI_RSSI_THRESHOLD 10 + void WifiBeginAfterScan() { - static int8_t rssi_threshold; + static int8_t best_network_db; // Not active if (0 == wifi_scan_state) { return; } // Init scan when not connected if (1 == wifi_scan_state) { memset((void*) &wifi_bssid, 0, sizeof(wifi_bssid)); - rssi_threshold = 0; + best_network_db = -127; wifi_scan_state = 3; } // Init scan when connected if (2 == wifi_scan_state) { - rssi_threshold = 10; + uint8_t* bssid = WiFi.BSSID(); // Get current bssid + memcpy((void*) &wifi_bssid, (void*) bssid, sizeof(wifi_bssid)); + best_network_db = WiFi.RSSI(); // Get current rssi and add threshold + if (best_network_db < -WIFI_RSSI_THRESHOLD) { best_network_db +WIFI_RSSI_THRESHOLD; } wifi_scan_state = 3; } // Init scan @@ -268,12 +273,11 @@ void WifiBeginAfterScan() if (5 == wifi_scan_state) { int32_t channel = 0; // No scan result int8_t ap = 3; // AP default if not found - uint8_t last_bssid[6]; + uint8_t last_bssid[6]; // Save last bssid memcpy((void*) &last_bssid, (void*) &wifi_bssid, sizeof(last_bssid)); if (wifi_scan_result > 0) { // Networks found - int32_t best_network_db = -127; for (int8_t i = 0; i < wifi_scan_result; ++i) { String ssid_scan; @@ -290,9 +294,9 @@ void WifiBeginAfterScan() for (j = 0; j < 2; j++) { if (ssid_scan == Settings.sta_ssid[j]) { // SSID match known = true; - if (rssi_scan > (best_network_db + rssi_threshold)) { // Best network + if (rssi_scan > best_network_db) { // Best network if (sec_scan == ENC_TYPE_NONE || Settings.sta_pwd[j]) { // Check for passphrase if not open wlan - best_network_db = rssi_scan; + best_network_db = (int8_t)rssi_scan; channel = chan_scan; ap = j; // AP1 or AP2 memcpy((void*) &wifi_bssid, (void*) bssid_scan, sizeof(wifi_bssid)); @@ -310,6 +314,7 @@ void WifiBeginAfterScan() delay(0); } wifi_scan_state = 0; + // If bssid changed then (re)connect wifi for (uint8_t i = 0; i < sizeof(wifi_bssid); i++) { if (last_bssid[i] != wifi_bssid[i]) { WifiBegin(ap, channel); // 0 (AP1), 1 (AP2) or 3 (default AP) @@ -457,7 +462,7 @@ void WifiCheck(uint8_t param) restart_flag = 2; } } else { - WifiBeginAfterScan(); + if (wifi_scan_state) { WifiBeginAfterScan(); } if (wifi_counter <= 0) { AddLog_P(LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CHECKING_CONNECTION)); From 76829d4ced051fc7382164572f4d4f3f2abc0bc4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 20 Nov 2018 14:10:32 +0100 Subject: [PATCH 0526/2222] 6.3.0.11 Add delays 6.3.0.11 20181120 * Add delays removed in 6.3.0.9 (#4233) * Allow user definition of defines WIFI_RSSI_THRESHOLD (default 10) and WIFI_RESCAN_MINUTES (default 44) * Add support for Fujitsu HVac and IrRemote (#4387) --- sonoff/_changelog.ino | 7 +- sonoff/sonoff.h | 6 +- sonoff/sonoff_version.h | 2 +- sonoff/support_wifi.ino | 23 +++--- sonoff/xdrv_05_irremote.ino | 145 +++++++++++++++++++----------------- sonoff/xdrv_interface.ino | 2 +- sonoff/xsns_interface.ino | 4 +- 7 files changed, 103 insertions(+), 86 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 3a3e18910..bcca8cde8 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,9 @@ -/* 6.3.0.10 20181118 +/* 6.3.0.11 20181120 + * Add delays removed in 6.3.0.9 (#4233) + * Allow user definition of defines WIFI_RSSI_THRESHOLD (default 10) and WIFI_RESCAN_MINUTES (default 44) + * Add support for Fujitsu HVac and IrRemote (#4387) + * + * 6.3.0.10 20181118 * Add command SetOption36 0..255 milliseconds (50 default) to tune main loop dynamic delay * Add support for LG HVac and IrRemote (#4377) * Add command SetOption56 0/1 to enable wifi network scan and select highest RSSI (#3173) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 9f9350c64..e53a7c83d 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -138,6 +138,9 @@ typedef unsigned long power_t; // Power (Relay) type #define SERIAL_POLLING 100 // Serial receive polling in ms #define MAX_STATUS 11 // Max number of status lines +#define DRIVER_BOOT_DELAY 1 // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting +#define LOOP_SLEEP_DELAY 50 // Lowest number of milliseconds to go through the main loop using delay when needed + #define NO_EXTRA_4K_HEAP // Allocate 4k heap for WPS in ESP8166/Arduino core v2.4.2 (was always allocated in previous versions) /* @@ -189,9 +192,6 @@ typedef unsigned long power_t; // Power (Relay) type #define KNX_MAX_device_param 30 #define MAX_KNXTX_CMNDS 5 -#define DRIVER_BOOT_DELAY 1 // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting -#define LOOP_SLEEP_DELAY 50 // Lowest number of milliseconds to go through the main loop using delay when needed - /*********************************************************************************************\ * Enumeration \*********************************************************************************************/ diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 78acd0305..21ed0ce8f 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0603000A +#define VERSION 0x0603000B #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 4c5546687..b427a3f9b 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -21,6 +21,13 @@ * Wifi \*********************************************************************************************/ +#ifndef WIFI_RSSI_THRESHOLD +#define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network +#endif +#ifndef WIFI_RESCAN_MINUTES +#define WIFI_RESCAN_MINUTES 44 // Number of minutes between wifi network rescan +#endif + #define WIFI_CONFIG_SEC 180 // seconds before restart #define WIFI_CHECK_SEC 20 // seconds #define WIFI_RETRY_OFFSET_SEC 20 // seconds @@ -207,7 +214,7 @@ void WifiBegin(uint8_t flag, uint8_t channel) WiFiSetSleepMode(); // if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); } if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } - WiFi.setAutoReconnect(true); +// WiFi.setAutoReconnect(true); switch (flag) { case 0: // AP1 case 1: // AP2 @@ -231,8 +238,6 @@ void WifiBegin(uint8_t flag, uint8_t channel) AddLog(LOG_LEVEL_INFO); } -#define WIFI_RSSI_THRESHOLD 10 - void WifiBeginAfterScan() { static int8_t best_network_db; @@ -395,17 +400,17 @@ void WifiCheckIp(void) } } if (wifi_retry) { - if (!Settings.flag3.use_wifi_scan) { + if (Settings.flag3.use_wifi_scan) { + if (wifi_retry_init == wifi_retry) { + wifi_scan_state = 1; // Select scanned SSID + } + } else { if (wifi_retry_init == wifi_retry) { WifiBegin(3, 0); // Select default SSID } if ((Settings.sta_config != WIFI_WAIT) && ((wifi_retry_init / 2) == wifi_retry)) { WifiBegin(2, 0); // Select alternate SSID } - } else { - if (wifi_retry_init == wifi_retry) { - wifi_scan_state = 1; - } } wifi_counter = 1; wifi_retry--; @@ -473,7 +478,7 @@ void WifiCheck(uint8_t param) WifiSetState(1); if (Settings.flag3.use_wifi_rescan) { - if (!(uptime % (60 * 44))) { + if (!(uptime % (60 * WIFI_RESCAN_MINUTES))) { wifi_scan_state = 2; } } diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 4f71fd6d9..8836c4ddf 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -1,18 +1,18 @@ /* xdrv_05_irremote.ino - infra red support for Sonoff-Tasmota - + Copyright (C) 2018 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 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 . */ @@ -137,60 +137,11 @@ void IrReceiveCheck(void) #endif // USE_IR_RECEIVE #ifdef USE_IR_HVAC - -boolean IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) -{ - const char kFujitsuHvacModeOptions[] = "HDCAF"; - - char stemp[64]; - snprintf_P(stemp, sizeof(stemp), PSTR("FUJITSU: mode:%s, fan:%s, power:%u, temp:%u"), HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); - IRFujitsuAC ac(pin[GPIO_IRSEND]); - - if (HVAC_Power == 0) { - ac.off(); - ac.send(); - return false; - } - - byte modes[5] = {FUJITSU_AC_MODE_HEAT, FUJITSU_AC_MODE_DRY, FUJITSU_AC_MODE_COOL, FUJITSU_AC_MODE_AUTO, FUJITSU_AC_MODE_FAN}; - byte fanModes[7] = {FUJITSU_AC_FAN_AUTO, FUJITSU_AC_FAN_LOW, FUJITSU_AC_FAN_MED, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_QUIET}; - ac.setCmd(FUJITSU_AC_CMD_TURN_ON); - ac.setSwing(FUJITSU_AC_SWING_VERT); - - char *p; - if (HVAC_Mode == NULL) { - p = (char *)kFujitsuHvacModeOptions; - } - else { - p = strchr(kFujitsuHvacModeOptions, toupper(HVAC_Mode[0])); - } - if (!p) { - return true; - } - ac.setMode(modes[p - kFujitsuHvacModeOptions]); - - if (HVAC_FanMode == NULL) { - p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO - } - else { - p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); - } - if (!p) { - return true; - } - ac.setFanSpeed(fanModes[p - kFanSpeedOptions]); - - ac.setTemp(HVAC_Temp); - ac.send(); - - return false; -} - /********************************************************************************************* \ * IR Heating, Ventilation and Air Conditioning using IRMitsubishiAC library \*********************************************************************************************/ -/******************* +/******************* TOSHIBA ********************/ @@ -284,7 +235,7 @@ boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H } -/******************* +/******************* MITSUBISHI ********************/ @@ -333,7 +284,7 @@ boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolea } -/******************* +/******************* LG ********************/ @@ -353,21 +304,21 @@ boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_P if (!HVAC_Power) { data[2] = (byte)0x0C; // Turn OFF HVAC, code 0x88C0051 - data[3] = (byte)0x00; - data[4] = (byte)0x00; - data[5] = (byte)0x05; - data[6] = (byte)0x01; + data[3] = (byte)0x00; + data[4] = (byte)0x00; + data[5] = (byte)0x05; + data[6] = (byte)0x01; hvacOn = false; } else { - + // Set code for HVAC Mode - data[3] if (HVAC_Mode == NULL) { p = (char *)kHvacModeOptions; // default HVAC_HOT } else { - p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); + p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); } if (!p) { return true; @@ -385,16 +336,16 @@ boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_P break; case 3: // HOT data[3] = 12; - break; + break; } if (!hvacOn) { data[3] = data[3] & 7; // reset bit3 hvacOn = true; } - + snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: HvacMode %s, ModeVal %d, Code %d"), p, mode, data[3]); AddLog(LOG_LEVEL_DEBUG); - + // Set code for HVAC temperature - data[4] if (HVAC_Temp > 30) { Temp = 30; @@ -424,14 +375,14 @@ boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_P else { data[5] = (mode * 2) - 2; // Low = 0x00, Mid = 0x02, High = 0x04 } - + snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: FanMode %s, ModeVal %d, Code %d"), p, mode, data[5]); AddLog(LOG_LEVEL_DEBUG); // Set CRC code - data[6] data[6] = (data[3] + data[4] + data[5]) & 0x0f; // CRC - } + } // Build LG IR code LG_Code = data[0] << 4; for (int i = 1; i < 6; i++) { @@ -442,13 +393,68 @@ boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_P snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: LG_Code %d"), LG_Code); AddLog(LOG_LEVEL_DEBUG); - // Send LG IR Code + // Send LG IR Code noInterrupts(); irsend->sendLG(LG_Code, 28); interrupts(); - + return false; } + + +/******************* + Fujitsu +********************/ + +boolean IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) +{ + const char kFujitsuHvacModeOptions[] = "HDCAF"; + + char stemp[64]; + snprintf_P(stemp, sizeof(stemp), PSTR("FUJITSU: mode:%s, fan:%s, power:%u, temp:%u"), HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); + + IRFujitsuAC ac(pin[GPIO_IRSEND]); + + if (0 == HVAC_Power) { + ac.off(); + ac.send(); + return false; + } + + byte modes[5] = {FUJITSU_AC_MODE_HEAT, FUJITSU_AC_MODE_DRY, FUJITSU_AC_MODE_COOL, FUJITSU_AC_MODE_AUTO, FUJITSU_AC_MODE_FAN}; + byte fanModes[7] = {FUJITSU_AC_FAN_AUTO, FUJITSU_AC_FAN_LOW, FUJITSU_AC_FAN_MED, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_QUIET}; + ac.setCmd(FUJITSU_AC_CMD_TURN_ON); + ac.setSwing(FUJITSU_AC_SWING_VERT); + + char *p; + if (NULL == HVAC_Mode) { + p = (char *)kFujitsuHvacModeOptions; + } + else { + p = strchr(kFujitsuHvacModeOptions, toupper(HVAC_Mode[0])); + } + if (!p) { + return true; + } + ac.setMode(modes[p - kFujitsuHvacModeOptions]); + + if (HVAC_FanMode == NULL) { + p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO + } + else { + p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); + } + if (!p) { + return true; + } + ac.setFanSpeed(fanModes[p - kFanSpeedOptions]); + + ac.setTemp(HVAC_Temp); + ac.send(); + + return false; +} + #endif // USE_IR_HVAC /*********************************************************************************************\ @@ -562,6 +568,7 @@ boolean IrSendCommand(void) } else if (!strcasecmp_P(HVAC_Vendor, PSTR("LG"))) { error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); + } else if (!strcasecmp_P(HVAC_Vendor, PSTR("FUJITSU"))) { error = IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); } diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 12b9e2711..c9557ec56 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -238,7 +238,7 @@ boolean XdrvCall(byte Function) boolean result = false; for (byte x = 0; x < xdrv_present; x++) { -// AppDelay(); + AppDelay(); result = xdrv_func_ptr[x](Function); if (result) break; } diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index a7ab6d7a7..cb1649d11 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -280,7 +280,7 @@ boolean XsnsNextCall(byte Function) if (xsns_index == xsns_present) { xsns_index = 0; } } #endif -// AppDelay(); + AppDelay(); return xsns_func_ptr[xsns_index](Function); } @@ -300,7 +300,7 @@ boolean XsnsCall(byte Function) #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND uint32_t profile_start_millis = millis(); #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND -// AppDelay(); + AppDelay(); result = xsns_func_ptr[x](Function); #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND From 23c16e58a991f3934af5ae1dc3c66bd68e1ae83d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 20 Nov 2018 15:00:24 +0100 Subject: [PATCH 0527/2222] Housekeeping Housekeeping --- sonoff/_changelog.ino | 2 +- sonoff/sonoff.ino | 3 +- sonoff/support.ino | 748 +---------------------------------- sonoff/support_features.ino | 381 ++++++++++++++++++ sonoff/support_rtc.ino | 418 ++++++++++++++++++++ sonoff/support_wifi.ino | 6 - sonoff/xdrv_01_webserver.ino | 2 +- sonoff/xdrv_02_mqtt.ino | 6 + sonoff/xdrv_03_energy.ino | 2 + tools/decode-status.py | 7 +- 10 files changed, 817 insertions(+), 758 deletions(-) create mode 100644 sonoff/support_features.ino create mode 100644 sonoff/support_rtc.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index bcca8cde8..cd44e7dbd 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,7 +2,7 @@ * Add delays removed in 6.3.0.9 (#4233) * Allow user definition of defines WIFI_RSSI_THRESHOLD (default 10) and WIFI_RESCAN_MINUTES (default 44) * Add support for Fujitsu HVac and IrRemote (#4387) - * + * * 6.3.0.10 20181118 * Add command SetOption36 0..255 milliseconds (50 default) to tune main loop dynamic delay * Add support for LG HVac and IrRemote (#4377) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 486a3ba93..949f82cb7 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -45,8 +45,7 @@ #endif // Libraries -#include // RTC, Energy, OSWatch -#include // MQTT, Ota +#include // Ota #include // Ota #include // Webserver, Updater #include // WemoHue, IRremote, Domoticz diff --git a/sonoff/support.ino b/sonoff/support.ino index 64af2e472..f32657c37 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -24,6 +24,8 @@ uint32_t syslog_host_hash = 0; // Syslog host name hash * Watchdog extension (https://github.com/esp8266/Arduino/issues/1532) \*********************************************************************************************/ +#include + Ticker tickerOSWatch; #define OSWATCH_RESET_TIME 120 @@ -835,347 +837,6 @@ void SetNextTimeInterval(unsigned long& timer, const unsigned long step) } // Try to get in sync again. timer = millis() + (step - passed); -} - -/*********************************************************************************************\ - * Fill feature list -\*********************************************************************************************/ - -void GetFeatures(void) -{ - feature_drv1 = 0x00000000; // xdrv_01_mqtt.ino, xdrv_01_light.ino, xdrv_04_snfbridge.ino - -// feature_drv1 |= 0x00000001; -// feature_drv1 |= 0x00000002; - -#ifdef USE_I2C - feature_drv1 |= 0x00000004; // sonoff.ino -#endif -#ifdef USE_SPI - feature_drv1 |= 0x00000008; // sonoff.ino -#endif -#ifdef USE_DISCOVERY - feature_drv1 |= 0x00000010; // sonoff.ino -#endif -#ifdef USE_ARDUINO_OTA - feature_drv1 |= 0x00000020; // sonoff.ino -#endif -#ifdef USE_MQTT_TLS - feature_drv1 |= 0x00000040; // sonoff.ino -#endif -#ifdef USE_WEBSERVER - feature_drv1 |= 0x00000080; // xdrv_02_webserver.ino -#endif -#ifdef WEBSERVER_ADVERTISE - feature_drv1 |= 0x00000100; // xdrv_02_webserver.ino -#endif -#ifdef USE_EMULATION - feature_drv1 |= 0x00000200; // xplg_wemohue.ino -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT) - feature_drv1 |= 0x00000400; // xdrv_01_mqtt.ino -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) - feature_drv1 |= 0x00000800; // xdrv_01_mqtt.ino -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) // Obsolete since 6.2.1.11 - feature_drv1 |= 0x00001000; // xdrv_01_mqtt.ino -#endif -#ifdef MQTT_HOST_DISCOVERY - feature_drv1 |= 0x00002000; // xdrv_01_mqtt.ino -#endif -#ifdef USE_ARILUX_RF - feature_drv1 |= 0x00004000; // xdrv_04_light.ino -#endif -#ifdef USE_WS2812 - feature_drv1 |= 0x00008000; // xdrv_04_light.ino -#endif -#ifdef USE_WS2812_DMA - feature_drv1 |= 0x00010000; // xdrv_04_light.ino -#endif -#ifdef USE_IR_REMOTE - feature_drv1 |= 0x00020000; // xdrv_05_irremote.ino -#endif -#ifdef USE_IR_HVAC - feature_drv1 |= 0x00040000; // xdrv_05_irremote.ino -#endif -#ifdef USE_IR_RECEIVE - feature_drv1 |= 0x00080000; // xdrv_05_irremote.ino -#endif -#ifdef USE_DOMOTICZ - feature_drv1 |= 0x00100000; // xdrv_07_domoticz.ino -#endif -#ifdef USE_DISPLAY - feature_drv1 |= 0x00200000; // xdrv_13_display.ino -#endif -#ifdef USE_HOME_ASSISTANT - feature_drv1 |= 0x00400000; // xdrv_12_home_assistant.ino -#endif -#ifdef USE_SERIAL_BRIDGE - feature_drv1 |= 0x00800000; // xdrv_08_serial_bridge.ino -#endif -#ifdef USE_TIMERS - feature_drv1 |= 0x01000000; // xdrv_09_timers.ino -#endif -#ifdef USE_SUNRISE - feature_drv1 |= 0x02000000; // xdrv_09_timers.ino -#endif -#ifdef USE_TIMERS_WEB - feature_drv1 |= 0x04000000; // xdrv_09_timers.ino -#endif -#ifdef USE_RULES - feature_drv1 |= 0x08000000; // xdrv_10_rules.ino -#endif -#ifdef USE_KNX - feature_drv1 |= 0x10000000; // xdrv_11_knx.ino -#endif -#ifdef USE_WPS - feature_drv1 |= 0x20000000; // support.ino -#endif -#ifdef USE_SMARTCONFIG - feature_drv1 |= 0x40000000; // support.ino -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT) - feature_drv1 |= 0x80000000; // xdrv_01_mqtt.ino -#endif - -/*********************************************************************************************/ - - feature_drv2 = 0x00000000; - -#ifdef USE_CONFIG_OVERRIDE - feature_drv2 |= 0x00000001; // user_config(_override).h -#endif -#ifdef BE_MINIMAL - feature_drv2 |= 0x00000002; // user_config(_override).h -#endif -#ifdef USE_SENSORS - feature_drv2 |= 0x00000004; // user_config(_override).h -#endif -#ifdef USE_CLASSIC - feature_drv2 |= 0x00000008; // user_config(_override).h -#endif -#ifdef USE_KNX_NO_EMULATION - feature_drv2 |= 0x00000010; // user_config(_override).h -#endif -#ifdef USE_DISPLAY_MODES1TO5 - feature_drv2 |= 0x00000020; // xdrv_13_display.ino -#endif -#ifdef USE_DISPLAY_GRAPH - feature_drv2 |= 0x00000040; // xdrv_13_display.ino -#endif -#ifdef USE_DISPLAY_LCD - feature_drv2 |= 0x00000080; // xdsp_01_lcd.ino -#endif -#ifdef USE_DISPLAY_SSD1306 - feature_drv2 |= 0x00000100; // xdsp_02_ssd1306.ino -#endif -#ifdef USE_DISPLAY_MATRIX - feature_drv2 |= 0x00000200; // xdsp_03_matrix.ino -#endif -#ifdef USE_DISPLAY_ILI9341 - feature_drv2 |= 0x00000400; // xdsp_04_ili9341.ino -#endif -#ifdef USE_DISPLAY_EPAPER - feature_drv2 |= 0x00000800; // xdsp_05_epaper.ino -#endif -#ifdef USE_DISPLAY_SH1106 - feature_drv2 |= 0x00001000; // xdsp_06_sh1106.ino -#endif -#ifdef USE_MP3_PLAYER - feature_drv2 |= 0x00002000; // xdrv_14_mp3.ino -#endif -#ifdef USE_PCA9685 - feature_drv2 |= 0x00004000; // xdrv_15_pca9685.ino -#endif -#ifdef USE_TUYA_DIMMER - feature_drv2 |= 0x00008000; // xdrv_16_tuyadimmer.ino -#endif -#ifdef USE_RC_SWITCH - feature_drv2 |= 0x00010000; // xdrv_17_rcswitch.ino -#endif -#ifdef USE_ARMTRONIX_DIMMERS - feature_drv2 |= 0x00020000; // xdrv_18_armtronixdimmer.ino -#endif - - -#ifdef NO_EXTRA_4K_HEAP - feature_drv2 |= 0x00800000; // sonoff_post.h -#endif -#ifdef VTABLES_IN_IRAM - feature_drv2 |= 0x01000000; // platformio.ini -#endif -#ifdef VTABLES_IN_DRAM - feature_drv2 |= 0x02000000; // platformio.ini -#endif -#ifdef VTABLES_IN_FLASH - feature_drv2 |= 0x04000000; // platformio.ini -#endif -#ifdef PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH - feature_drv2 |= 0x08000000; // platformio.ini -#endif -#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY - feature_drv2 |= 0x10000000; // platformio.ini -#endif -#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH - feature_drv2 |= 0x20000000; // platformio.ini -#endif -#ifdef DEBUG_THEO - feature_drv2 |= 0x40000000; // xdrv_99_debug.ino -#endif -#ifdef USE_DEBUG_DRIVER - feature_drv2 |= 0x80000000; // xdrv_99_debug.ino -#endif - -/*********************************************************************************************/ - - feature_sns1 = 0x00000000; // xsns_01_counter.ino, xsns_04_snfsc.ino - -// feature_sns1 |= 0x00000001; - -#ifdef USE_ADC_VCC - feature_sns1 |= 0x00000002; // support.ino (ADC) -#endif -#ifdef USE_ENERGY_SENSOR - feature_sns1 |= 0x00000004; // xdrv_03_energy.ino -#endif -#ifdef USE_PZEM004T - feature_sns1 |= 0x00000008; // xnrg_03_pzem004t.ino -#endif -#ifdef USE_DS18B20 - feature_sns1 |= 0x00000010; // xsns_05_ds18b20.ino -#endif -#ifdef USE_DS18x20_LEGACY - feature_sns1 |= 0x00000020; // xsns_05_ds18x20_legacy.ino -#endif -#ifdef USE_DS18x20 - feature_sns1 |= 0x00000040; // xsns_05_ds18x20.ino -#endif -#ifdef USE_DHT - feature_sns1 |= 0x00000080; // xsns_06_dht.ino -#endif -#ifdef USE_SHT - feature_sns1 |= 0x00000100; // xsns_07_sht1x.ino -#endif -#ifdef USE_HTU - feature_sns1 |= 0x00000200; // xsns_08_htu21.ino -#endif -#ifdef USE_BMP - feature_sns1 |= 0x00000400; // xsns_09_bmp.ino -#endif -#ifdef USE_BME680 - feature_sns1 |= 0x00000800; // xsns_09_bmp.ino - BME680 -#endif -#ifdef USE_BH1750 - feature_sns1 |= 0x00001000; // xsns_10_bh1750.ino -#endif -#ifdef USE_VEML6070 - feature_sns1 |= 0x00002000; // xsns_11_veml6070.ino -#endif -#ifdef USE_ADS1115_I2CDEV - feature_sns1 |= 0x00004000; // xsns_12_ads1115_i2cdev.ino -#endif -#ifdef USE_ADS1115 - feature_sns1 |= 0x00008000; // xsns_12_ads1115.ino -#endif -#ifdef USE_INA219 - feature_sns1 |= 0x00010000; // xsns_13_ina219.ino -#endif -#ifdef USE_SHT3X - feature_sns1 |= 0x00020000; // xsns_14_sht3x.ino -#endif -#ifdef USE_MHZ19 - feature_sns1 |= 0x00040000; // xsns_15_mhz19.ino -#endif -#ifdef USE_TSL2561 - feature_sns1 |= 0x00080000; // xsns_16_tsl2561.ino -#endif -#ifdef USE_SENSEAIR - feature_sns1 |= 0x00100000; // xsns_17_senseair.ino -#endif -#ifdef USE_PMS5003 - feature_sns1 |= 0x00200000; // xsns_18_pms5003.ino -#endif -#ifdef USE_MGS - feature_sns1 |= 0x00400000; // xsns_19_mgs.ino -#endif -#ifdef USE_NOVA_SDS - feature_sns1 |= 0x00800000; // xsns_20_novasds.ino -#endif -#ifdef USE_SGP30 - feature_sns1 |= 0x01000000; // xsns_21_sgp30.ino -#endif -#ifdef USE_SR04 - feature_sns1 |= 0x02000000; // xsns_22_sr04.ino -#endif -#ifdef USE_SDM120 - feature_sns1 |= 0x04000000; // xsns_23_sdm120.ino -#endif -#ifdef USE_SI1145 - feature_sns1 |= 0x08000000; // xsns_24_si1145.ino -#endif -#ifdef USE_SDM630 - feature_sns1 |= 0x10000000; // xsns_25_sdm630.ino -#endif -#ifdef USE_LM75AD - feature_sns1 |= 0x20000000; // xsns_26_lm75ad.ino -#endif -#ifdef USE_APDS9960 - feature_sns1 |= 0x40000000; // xsns_27_apds9960.ino -#endif -#ifdef USE_TM1638 - feature_sns1 |= 0x80000000; // xsns_28_tm1638.ino -#endif - -/*********************************************************************************************/ - - feature_sns2 = 0x00000000; - -#ifdef USE_MCP230xx - feature_sns2 |= 0x00000001; // xsns_29_mcp230xx.ino -#endif -#ifdef USE_MPR121 - feature_sns2 |= 0x00000002; // xsns_30_mpr121.ino -#endif -#ifdef USE_CCS811 - feature_sns2 |= 0x00000004; // xsns_31_ccs811.ino -#endif -#ifdef USE_MPU6050 - feature_sns2 |= 0x00000008; // xsns_32_mpu6050.ino -#endif -#ifdef USE_MCP230xx_OUTPUT - feature_sns2 |= 0x00000010; // xsns_29_mcp230xx.ino -#endif -#ifdef USE_MCP230xx_DISPLAYOUTPUT - feature_sns2 |= 0x00000020; // xsns_29_mcp230xx.ino -#endif -#ifdef USE_HLW8012 - feature_sns2 |= 0x00000040; // xnrg_01_hlw8012.ino -#endif -#ifdef USE_CSE7766 - feature_sns2 |= 0x00000080; // xnrg_02_cse7766.ino -#endif -#ifdef USE_MCP39F501 - feature_sns2 |= 0x00000100; // xnrg_04_mcp39f501.ino -#endif -#ifdef USE_PZEM_AC - feature_sns2 |= 0x00000200; // xnrg_05_pzem_ac.ino -#endif -#ifdef USE_DS3231 - feature_sns2 |= 0x00000400; // xsns_33_ds3231.ino -#endif -#ifdef USE_HX711 - feature_sns2 |= 0x00000800; // xsns_34_hx711.ino -#endif -#ifdef USE_PZEM_DC - feature_sns2 |= 0x00001000; // xnrg_06_pzem_dc.ino -#endif -#ifdef USE_TX20_WIND_SENSOR - feature_sns2 |= 0x00002000; // xsns_35_tx20.ino -#endif - - - } /*********************************************************************************************\ @@ -1388,407 +1049,6 @@ boolean I2cDevice(byte addr) } #endif // USE_I2C -/*********************************************************************************************\ - * Real Time Clock - * - * Sources: Time by Michael Margolis and Paul Stoffregen (https://github.com/PaulStoffregen/Time) - * Timezone by Jack Christensen (https://github.com/JChristensen/Timezone) -\*********************************************************************************************/ - -extern "C" { -#include "sntp.h" -} - -#define SECS_PER_MIN ((uint32_t)(60UL)) -#define SECS_PER_HOUR ((uint32_t)(3600UL)) -#define SECS_PER_DAY ((uint32_t)(SECS_PER_HOUR * 24UL)) -#define MINS_PER_HOUR ((uint32_t)(60UL)) -#define LEAP_YEAR(Y) (((1970+Y)>0) && !((1970+Y)%4) && (((1970+Y)%100) || !((1970+Y)%400))) - -Ticker TickerRtc; - -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 -static const char kMonthNamesEnglish[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; - -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; -uint32_t restart_time = 0; -int32_t time_timezone = 0; -uint8_t midnight_now = 0; -uint8_t ntp_sync_minute = 0; - -String GetBuildDateAndTime(void) -{ - // "2017-03-07T11:08:02" - ISO8601:2004 - char bdt[21]; - char *p; - char mdate[] = __DATE__; // "Mar 7 2017" - char *smonth = mdate; - int day = 0; - int year = 0; - - // sscanf(mdate, "%s %d %d", bdt, &day, &year); // Not implemented in 2.3.0 and probably too much code - byte i = 0; - for (char *str = strtok_r(mdate, " ", &p); str && i < 3; str = strtok_r(NULL, " ", &p)) { - switch (i++) { - case 0: // Month - smonth = str; - break; - case 1: // Day - day = atoi(str); - break; - case 2: // Year - year = atoi(str); - } - } - int month = (strstr(kMonthNamesEnglish, smonth) -kMonthNamesEnglish) /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); // 2017-03-07T11:08:02 -} - -String GetTimeZone(void) -{ - char tz[7]; - - snprintf_P(tz, sizeof(tz), PSTR("%+03d:%02d"), time_timezone / 60, abs(time_timezone % 60)); - - return String(tz); // -03:45 -} - -/* - * timestamps in https://en.wikipedia.org/wiki/ISO_8601 format - * - * DT_UTC - current data and time in Greenwich, England (aka GMT) - * DT_LOCAL - current date and time taking timezone into account - * DT_RESTART - the date and time this device last started, in local timezone - * - * Format: - * "2017-03-07T11:08:02-07:00" - if DT_LOCAL and SetOption52 = 1 - * "2017-03-07T11:08:02" - otherwise - */ -String GetDateAndTime(byte time_type) -{ - // "2017-03-07T11:08:02-07:00" - ISO8601:2004 - char dt[27]; - TIME_T tmpTime; - - switch (time_type) { - case DT_ENERGY: - BreakTime(Settings.energy_kWhtotal_time, tmpTime); - tmpTime.year += 1970; - break; - case DT_UTC: - BreakTime(utc_time, tmpTime); - tmpTime.year += 1970; - break; - case DT_RESTART: - if (restart_time == 0) { - return ""; - } - BreakTime(restart_time, tmpTime); - tmpTime.year += 1970; - break; - default: - tmpTime = RtcTime; - } - - snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), - tmpTime.year, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); - - if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { -// if (Settings.flag3.time_append_timezone && ((DT_LOCAL == time_type) || (DT_ENERGY == time_type))) { - strncat(dt, GetTimeZone().c_str(), sizeof(dt)); - } - - return String(dt); // 2017-03-07T11:08:02-07:00 -} - -String GetTime(int type) -{ - /* type 1 - Local time - * type 2 - Daylight Savings time - * type 3 - Standard time - */ - char stime[25]; // Skip newline - - 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); // Thu Nov 01 11:41:02 2018 -} - -String GetUptime(void) -{ - char dt[16]; - - TIME_T ut; - - if (restart_time) { - BreakTime(utc_time - restart_time, ut); - } else { - BreakTime(uptime, ut); - } - - // "P128DT14H35M44S" - ISO8601:2004 - https://en.wikipedia.org/wiki/ISO_8601 Durations -// snprintf_P(dt, sizeof(dt), PSTR("P%dDT%02dH%02dM%02dS"), ut.days, ut.hour, ut.minute, ut.second); - - // "128 14:35:44" - OpenVMS - // "128T14:35:44" - Tasmota - snprintf_P(dt, sizeof(dt), PSTR("%dT%02d:%02d:%02d"), ut.days, ut.hour, ut.minute, ut.second); - - return String(dt); // 128T14:35:44 -} - -uint32_t GetMinutesUptime(void) -{ - TIME_T ut; - - if (restart_time) { - BreakTime(utc_time - restart_time, ut); - } else { - BreakTime(uptime, ut); - } - - return (ut.days *1440) + (ut.hour *60) + ut.minute; -} - -uint32_t GetMinutesPastMidnight(void) -{ - uint32_t minutes = 0; - - if (RtcTime.valid) { - minutes = (RtcTime.hour *60) + RtcTime.minute; - } - return minutes; -} - -void BreakTime(uint32_t time_input, TIME_T &tm) -{ -// 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 month_length; - uint32_t time; - unsigned long days; - - time = time_input; - tm.second = time % 60; - time /= 60; // now it is minutes - tm.minute = time % 60; - time /= 60; // now it is hours - tm.hour = time % 24; - time /= 24; // now it is days - tm.days = time; - 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 - - days -= LEAP_YEAR(year) ? 366 : 365; - time -= days; // now it is days in this year, starting at 0 - tm.day_of_year = time; - - days = 0; - month = 0; - month_length = 0; - for (month = 0; month < 12; month++) { - if (1 == month) { // february - if (LEAP_YEAR(year)) { - month_length = 29; - } else { - month_length = 28; - } - } else { - month_length = kDaysInMonth[month]; - } - - if (time >= month_length) { - time -= month_length; - } else { - break; - } - } - 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) -{ -// assemble time elements into time_t -// note year argument is offset from 1970 - - int i; - 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++) { - 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)) { - seconds += SECS_PER_DAY * 29; - } else { - seconds += SECS_PER_DAY * kDaysInMonth[i-1]; // monthDay array starts from 0 - } - } - 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 RuleToTime(TimeRule r, int yr) -{ - TIME_T tm; - uint32_t t; - uint8_t m; - uint8_t w; // temp copies of r.month and r.week - - m = r.month; - w = r.week; - if (0 == w) { // Last week = 0 - if (++m > 12) { // for "Last", go to the next month - m = 1; - 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_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; -} - -uint32_t LocalTime(void) -{ - return local_time; -} - -uint32_t Midnight(void) -{ - return midnight; -} - -boolean MidnightNow(void) -{ - boolean mnflg = midnight_now; - if (mnflg) midnight_now = 0; - return mnflg; -} - -void RtcSecond(void) -{ - TIME_T tmpTime; - - if ((ntp_sync_minute > 59) && (RtcTime.minute > 2)) ntp_sync_minute = 1; // If sync prepare for a new cycle - uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP.getChipId() & 0xF) * 3) + 3) ; // First try ASAP to sync. If fails try once every 60 seconds based on chip id - if (!global_state.wifi_down && (offset == RtcTime.second) && ((RtcTime.year < 2016) || (ntp_sync_minute == RtcTime.minute) || ntp_force_sync)) { - ntp_time = sntp_get_current_timestamp(); - if (ntp_time > 1451602800) { // Fix NTP bug in core 2.4.1/SDK 2.2.1 (returns Thu Jan 01 08:00:10 1970 after power on) - ntp_force_sync = 0; - utc_time = ntp_time; - ntp_sync_minute = 60; // Sync so block further requests - if (restart_time == 0) { - restart_time = utc_time - uptime; // save first ntp time as restart time - } - BreakTime(utc_time, tmpTime); - RtcTime.year = tmpTime.year + 1970; - daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); - standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "(" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - AddLog(LOG_LEVEL_DEBUG); - if (local_time < 1451602800) { // 2016-01-01 - rules_flag.time_init = 1; - } else { - rules_flag.time_set = 1; - } - } else { - ntp_sync_minute++; // Try again in next minute - } - } - utc_time++; - local_time = utc_time; - if (local_time > 1451602800) { // 2016-01-01 - int16_t timezone_minutes = Settings.timezone_minutes; - if (Settings.timezone < 0) { timezone_minutes *= -1; } - time_timezone = (Settings.timezone * SECS_PER_HOUR) + (timezone_minutes * SECS_PER_MIN); - if (99 == Settings.timezone) { - int32_t dstoffset = Settings.toffset[1] * SECS_PER_MIN; - int32_t stdoffset = Settings.toffset[0] * SECS_PER_MIN; - if (Settings.tflag[1].hemis) { - // Southern hemisphere - if ((utc_time >= (standard_time - dstoffset)) && (utc_time < (daylight_saving_time - stdoffset))) { - time_timezone = stdoffset; // Standard Time - } else { - time_timezone = dstoffset; // Daylight Saving Time - } - } else { - // Northern hemisphere - if ((utc_time >= (daylight_saving_time - stdoffset)) && (utc_time < (standard_time - dstoffset))) { - time_timezone = dstoffset; // Daylight Saving Time - } else { - time_timezone = stdoffset; // Standard Time - } - } - } - local_time += time_timezone; - time_timezone /= 60; - if (!Settings.energy_kWhtotal_time) { Settings.energy_kWhtotal_time = local_time; } - } - BreakTime(local_time, RtcTime); - if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second && RtcTime.valid) { - midnight = local_time; - midnight_now = 1; - } - RtcTime.year += 1970; -} - -void RtcInit(void) -{ - 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(); - utc_time = 0; - BreakTime(utc_time, RtcTime); - TickerRtc.attach(1, RtcSecond); -} - /*********************************************************************************************\ * Syslog * @@ -1920,7 +1180,3 @@ void AddLogMissed(char *sensor, uint8_t misses) snprintf_P(log_data, sizeof(log_data), PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses); AddLog(LOG_LEVEL_DEBUG); } - -/*********************************************************************************************\ - * -\*********************************************************************************************/ diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino new file mode 100644 index 000000000..826e73090 --- /dev/null +++ b/sonoff/support_features.ino @@ -0,0 +1,381 @@ +/* + support_features.ino - feature support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 . +*/ + +/*********************************************************************************************\ + * Fill feature list +\*********************************************************************************************/ + +void GetFeatures(void) +{ + feature_drv1 = 0x00000000; // xdrv_01_mqtt.ino, xdrv_01_light.ino, xdrv_04_snfbridge.ino + +// feature_drv1 |= 0x00000001; +// feature_drv1 |= 0x00000002; + +#ifdef USE_I2C + feature_drv1 |= 0x00000004; // sonoff.ino +#endif +#ifdef USE_SPI + feature_drv1 |= 0x00000008; // sonoff.ino +#endif +#ifdef USE_DISCOVERY + feature_drv1 |= 0x00000010; // sonoff.ino +#endif +#ifdef USE_ARDUINO_OTA + feature_drv1 |= 0x00000020; // sonoff.ino +#endif +#ifdef USE_MQTT_TLS + feature_drv1 |= 0x00000040; // sonoff.ino +#endif +#ifdef USE_WEBSERVER + feature_drv1 |= 0x00000080; // xdrv_02_webserver.ino +#endif +#ifdef WEBSERVER_ADVERTISE + feature_drv1 |= 0x00000100; // xdrv_02_webserver.ino +#endif +#ifdef USE_EMULATION + feature_drv1 |= 0x00000200; // xplg_wemohue.ino +#endif +#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT) + feature_drv1 |= 0x00000400; // xdrv_01_mqtt.ino +#endif +#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) + feature_drv1 |= 0x00000800; // xdrv_01_mqtt.ino +#endif +#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) // Obsolete since 6.2.1.11 + feature_drv1 |= 0x00001000; // xdrv_01_mqtt.ino +#endif +#ifdef MQTT_HOST_DISCOVERY + feature_drv1 |= 0x00002000; // xdrv_01_mqtt.ino +#endif +#ifdef USE_ARILUX_RF + feature_drv1 |= 0x00004000; // xdrv_04_light.ino +#endif +#ifdef USE_WS2812 + feature_drv1 |= 0x00008000; // xdrv_04_light.ino +#endif +#ifdef USE_WS2812_DMA + feature_drv1 |= 0x00010000; // xdrv_04_light.ino +#endif +#ifdef USE_IR_REMOTE + feature_drv1 |= 0x00020000; // xdrv_05_irremote.ino +#endif +#ifdef USE_IR_HVAC + feature_drv1 |= 0x00040000; // xdrv_05_irremote.ino +#endif +#ifdef USE_IR_RECEIVE + feature_drv1 |= 0x00080000; // xdrv_05_irremote.ino +#endif +#ifdef USE_DOMOTICZ + feature_drv1 |= 0x00100000; // xdrv_07_domoticz.ino +#endif +#ifdef USE_DISPLAY + feature_drv1 |= 0x00200000; // xdrv_13_display.ino +#endif +#ifdef USE_HOME_ASSISTANT + feature_drv1 |= 0x00400000; // xdrv_12_home_assistant.ino +#endif +#ifdef USE_SERIAL_BRIDGE + feature_drv1 |= 0x00800000; // xdrv_08_serial_bridge.ino +#endif +#ifdef USE_TIMERS + feature_drv1 |= 0x01000000; // xdrv_09_timers.ino +#endif +#ifdef USE_SUNRISE + feature_drv1 |= 0x02000000; // xdrv_09_timers.ino +#endif +#ifdef USE_TIMERS_WEB + feature_drv1 |= 0x04000000; // xdrv_09_timers.ino +#endif +#ifdef USE_RULES + feature_drv1 |= 0x08000000; // xdrv_10_rules.ino +#endif +#ifdef USE_KNX + feature_drv1 |= 0x10000000; // xdrv_11_knx.ino +#endif +#ifdef USE_WPS + feature_drv1 |= 0x20000000; // support.ino +#endif +#ifdef USE_SMARTCONFIG + feature_drv1 |= 0x40000000; // support.ino +#endif +#if (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT) + feature_drv1 |= 0x80000000; // xdrv_01_mqtt.ino +#endif + +/*********************************************************************************************/ + + feature_drv2 = 0x00000000; + +#ifdef USE_CONFIG_OVERRIDE + feature_drv2 |= 0x00000001; // user_config(_override).h +#endif +#ifdef BE_MINIMAL + feature_drv2 |= 0x00000002; // user_config(_override).h +#endif +#ifdef USE_SENSORS + feature_drv2 |= 0x00000004; // user_config(_override).h +#endif +#ifdef USE_CLASSIC + feature_drv2 |= 0x00000008; // user_config(_override).h +#endif +#ifdef USE_KNX_NO_EMULATION + feature_drv2 |= 0x00000010; // user_config(_override).h +#endif +#ifdef USE_DISPLAY_MODES1TO5 + feature_drv2 |= 0x00000020; // xdrv_13_display.ino +#endif +#ifdef USE_DISPLAY_GRAPH + feature_drv2 |= 0x00000040; // xdrv_13_display.ino +#endif +#ifdef USE_DISPLAY_LCD + feature_drv2 |= 0x00000080; // xdsp_01_lcd.ino +#endif +#ifdef USE_DISPLAY_SSD1306 + feature_drv2 |= 0x00000100; // xdsp_02_ssd1306.ino +#endif +#ifdef USE_DISPLAY_MATRIX + feature_drv2 |= 0x00000200; // xdsp_03_matrix.ino +#endif +#ifdef USE_DISPLAY_ILI9341 + feature_drv2 |= 0x00000400; // xdsp_04_ili9341.ino +#endif +#ifdef USE_DISPLAY_EPAPER + feature_drv2 |= 0x00000800; // xdsp_05_epaper.ino +#endif +#ifdef USE_DISPLAY_SH1106 + feature_drv2 |= 0x00001000; // xdsp_06_sh1106.ino +#endif +#ifdef USE_MP3_PLAYER + feature_drv2 |= 0x00002000; // xdrv_14_mp3.ino +#endif +#ifdef USE_PCA9685 + feature_drv2 |= 0x00004000; // xdrv_15_pca9685.ino +#endif +#ifdef USE_TUYA_DIMMER + feature_drv2 |= 0x00008000; // xdrv_16_tuyadimmer.ino +#endif +#ifdef USE_RC_SWITCH + feature_drv2 |= 0x00010000; // xdrv_17_rcswitch.ino +#endif +#ifdef USE_ARMTRONIX_DIMMERS + feature_drv2 |= 0x00020000; // xdrv_18_armtronixdimmer.ino +#endif + +// feature_drv2 |= 0x00040000; +// feature_drv2 |= 0x00080000; +// feature_drv2 |= 0x00100000; +// feature_drv2 |= 0x00200000; +// feature_drv2 |= 0x00400000; + +#ifdef NO_EXTRA_4K_HEAP + feature_drv2 |= 0x00800000; // sonoff_post.h +#endif +#ifdef VTABLES_IN_IRAM + feature_drv2 |= 0x01000000; // platformio.ini +#endif +#ifdef VTABLES_IN_DRAM + feature_drv2 |= 0x02000000; // platformio.ini +#endif +#ifdef VTABLES_IN_FLASH + feature_drv2 |= 0x04000000; // platformio.ini +#endif +#ifdef PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH + feature_drv2 |= 0x08000000; // platformio.ini +#endif +#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY + feature_drv2 |= 0x10000000; // platformio.ini +#endif +#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH + feature_drv2 |= 0x20000000; // platformio.ini +#endif +#ifdef DEBUG_THEO + feature_drv2 |= 0x40000000; // xdrv_99_debug.ino +#endif +#ifdef USE_DEBUG_DRIVER + feature_drv2 |= 0x80000000; // xdrv_99_debug.ino +#endif + +/*********************************************************************************************/ + + feature_sns1 = 0x00000000; // xsns_01_counter.ino, xsns_04_snfsc.ino + +// feature_sns1 |= 0x00000001; + +#ifdef USE_ADC_VCC + feature_sns1 |= 0x00000002; // support.ino (ADC) +#endif +#ifdef USE_ENERGY_SENSOR + feature_sns1 |= 0x00000004; // xdrv_03_energy.ino +#endif +#ifdef USE_PZEM004T + feature_sns1 |= 0x00000008; // xnrg_03_pzem004t.ino +#endif +#ifdef USE_DS18B20 + feature_sns1 |= 0x00000010; // xsns_05_ds18b20.ino +#endif +#ifdef USE_DS18x20_LEGACY + feature_sns1 |= 0x00000020; // xsns_05_ds18x20_legacy.ino +#endif +#ifdef USE_DS18x20 + feature_sns1 |= 0x00000040; // xsns_05_ds18x20.ino +#endif +#ifdef USE_DHT + feature_sns1 |= 0x00000080; // xsns_06_dht.ino +#endif +#ifdef USE_SHT + feature_sns1 |= 0x00000100; // xsns_07_sht1x.ino +#endif +#ifdef USE_HTU + feature_sns1 |= 0x00000200; // xsns_08_htu21.ino +#endif +#ifdef USE_BMP + feature_sns1 |= 0x00000400; // xsns_09_bmp.ino +#endif +#ifdef USE_BME680 + feature_sns1 |= 0x00000800; // xsns_09_bmp.ino - BME680 +#endif +#ifdef USE_BH1750 + feature_sns1 |= 0x00001000; // xsns_10_bh1750.ino +#endif +#ifdef USE_VEML6070 + feature_sns1 |= 0x00002000; // xsns_11_veml6070.ino +#endif +#ifdef USE_ADS1115_I2CDEV + feature_sns1 |= 0x00004000; // xsns_12_ads1115_i2cdev.ino +#endif +#ifdef USE_ADS1115 + feature_sns1 |= 0x00008000; // xsns_12_ads1115.ino +#endif +#ifdef USE_INA219 + feature_sns1 |= 0x00010000; // xsns_13_ina219.ino +#endif +#ifdef USE_SHT3X + feature_sns1 |= 0x00020000; // xsns_14_sht3x.ino +#endif +#ifdef USE_MHZ19 + feature_sns1 |= 0x00040000; // xsns_15_mhz19.ino +#endif +#ifdef USE_TSL2561 + feature_sns1 |= 0x00080000; // xsns_16_tsl2561.ino +#endif +#ifdef USE_SENSEAIR + feature_sns1 |= 0x00100000; // xsns_17_senseair.ino +#endif +#ifdef USE_PMS5003 + feature_sns1 |= 0x00200000; // xsns_18_pms5003.ino +#endif +#ifdef USE_MGS + feature_sns1 |= 0x00400000; // xsns_19_mgs.ino +#endif +#ifdef USE_NOVA_SDS + feature_sns1 |= 0x00800000; // xsns_20_novasds.ino +#endif +#ifdef USE_SGP30 + feature_sns1 |= 0x01000000; // xsns_21_sgp30.ino +#endif +#ifdef USE_SR04 + feature_sns1 |= 0x02000000; // xsns_22_sr04.ino +#endif +#ifdef USE_SDM120 + feature_sns1 |= 0x04000000; // xsns_23_sdm120.ino +#endif +#ifdef USE_SI1145 + feature_sns1 |= 0x08000000; // xsns_24_si1145.ino +#endif +#ifdef USE_SDM630 + feature_sns1 |= 0x10000000; // xsns_25_sdm630.ino +#endif +#ifdef USE_LM75AD + feature_sns1 |= 0x20000000; // xsns_26_lm75ad.ino +#endif +#ifdef USE_APDS9960 + feature_sns1 |= 0x40000000; // xsns_27_apds9960.ino +#endif +#ifdef USE_TM1638 + feature_sns1 |= 0x80000000; // xsns_28_tm1638.ino +#endif + +/*********************************************************************************************/ + + feature_sns2 = 0x00000000; + +#ifdef USE_MCP230xx + feature_sns2 |= 0x00000001; // xsns_29_mcp230xx.ino +#endif +#ifdef USE_MPR121 + feature_sns2 |= 0x00000002; // xsns_30_mpr121.ino +#endif +#ifdef USE_CCS811 + feature_sns2 |= 0x00000004; // xsns_31_ccs811.ino +#endif +#ifdef USE_MPU6050 + feature_sns2 |= 0x00000008; // xsns_32_mpu6050.ino +#endif +#ifdef USE_MCP230xx_OUTPUT + feature_sns2 |= 0x00000010; // xsns_29_mcp230xx.ino +#endif +#ifdef USE_MCP230xx_DISPLAYOUTPUT + feature_sns2 |= 0x00000020; // xsns_29_mcp230xx.ino +#endif +#ifdef USE_HLW8012 + feature_sns2 |= 0x00000040; // xnrg_01_hlw8012.ino +#endif +#ifdef USE_CSE7766 + feature_sns2 |= 0x00000080; // xnrg_02_cse7766.ino +#endif +#ifdef USE_MCP39F501 + feature_sns2 |= 0x00000100; // xnrg_04_mcp39f501.ino +#endif +#ifdef USE_PZEM_AC + feature_sns2 |= 0x00000200; // xnrg_05_pzem_ac.ino +#endif +#ifdef USE_DS3231 + feature_sns2 |= 0x00000400; // xsns_33_ds3231.ino +#endif +#ifdef USE_HX711 + feature_sns2 |= 0x00000800; // xsns_34_hx711.ino +#endif +#ifdef USE_PZEM_DC + feature_sns2 |= 0x00001000; // xnrg_06_pzem_dc.ino +#endif +#ifdef USE_TX20_WIND_SENSOR + feature_sns2 |= 0x00002000; // xsns_35_tx20.ino +#endif + +// feature_sns2 |= 0x00004000; +// feature_sns2 |= 0x00008000; +// feature_sns2 |= 0x00010000; +// feature_sns2 |= 0x00020000; +// feature_sns2 |= 0x00040000; +// feature_sns2 |= 0x00080000; +// feature_sns2 |= 0x00100000; +// feature_sns2 |= 0x00200000; +// feature_sns2 |= 0x00400000; +// feature_sns2 |= 0x00800000; +// feature_sns2 |= 0x01000000; +// feature_sns2 |= 0x02000000; +// feature_sns2 |= 0x04000000; +// feature_sns2 |= 0x08000000; +// feature_sns2 |= 0x10000000; +// feature_sns2 |= 0x20000000; +// feature_sns2 |= 0x40000000; +// feature_sns2 |= 0x80000000; + +} diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino new file mode 100644 index 000000000..b6067bd15 --- /dev/null +++ b/sonoff/support_rtc.ino @@ -0,0 +1,418 @@ +/* + support_rtc.ino - Real Time Clock support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 . +*/ + +/*********************************************************************************************\ + * Sources: Time by Michael Margolis and Paul Stoffregen (https://github.com/PaulStoffregen/Time) + * Timezone by Jack Christensen (https://github.com/JChristensen/Timezone) +\*********************************************************************************************/ + +#define SECS_PER_MIN ((uint32_t)(60UL)) +#define SECS_PER_HOUR ((uint32_t)(3600UL)) +#define SECS_PER_DAY ((uint32_t)(SECS_PER_HOUR * 24UL)) +#define MINS_PER_HOUR ((uint32_t)(60UL)) +#define LEAP_YEAR(Y) (((1970+Y)>0) && !((1970+Y)%4) && (((1970+Y)%100) || !((1970+Y)%400))) + +extern "C" { +#include "sntp.h" +} +#include + +Ticker TickerRtc; + +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 +static const char kMonthNamesEnglish[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + +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; +uint32_t restart_time = 0; +int32_t time_timezone = 0; +uint8_t midnight_now = 0; +uint8_t ntp_sync_minute = 0; + +String GetBuildDateAndTime(void) +{ + // "2017-03-07T11:08:02" - ISO8601:2004 + char bdt[21]; + char *p; + char mdate[] = __DATE__; // "Mar 7 2017" + char *smonth = mdate; + int day = 0; + int year = 0; + + // sscanf(mdate, "%s %d %d", bdt, &day, &year); // Not implemented in 2.3.0 and probably too much code + byte i = 0; + for (char *str = strtok_r(mdate, " ", &p); str && i < 3; str = strtok_r(NULL, " ", &p)) { + switch (i++) { + case 0: // Month + smonth = str; + break; + case 1: // Day + day = atoi(str); + break; + case 2: // Year + year = atoi(str); + } + } + int month = (strstr(kMonthNamesEnglish, smonth) -kMonthNamesEnglish) /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); // 2017-03-07T11:08:02 +} + +String GetTimeZone(void) +{ + char tz[7]; + + snprintf_P(tz, sizeof(tz), PSTR("%+03d:%02d"), time_timezone / 60, abs(time_timezone % 60)); + + return String(tz); // -03:45 +} + +/* + * timestamps in https://en.wikipedia.org/wiki/ISO_8601 format + * + * DT_UTC - current data and time in Greenwich, England (aka GMT) + * DT_LOCAL - current date and time taking timezone into account + * DT_RESTART - the date and time this device last started, in local timezone + * + * Format: + * "2017-03-07T11:08:02-07:00" - if DT_LOCAL and SetOption52 = 1 + * "2017-03-07T11:08:02" - otherwise + */ +String GetDateAndTime(byte time_type) +{ + // "2017-03-07T11:08:02-07:00" - ISO8601:2004 + char dt[27]; + TIME_T tmpTime; + + switch (time_type) { + case DT_ENERGY: + BreakTime(Settings.energy_kWhtotal_time, tmpTime); + tmpTime.year += 1970; + break; + case DT_UTC: + BreakTime(utc_time, tmpTime); + tmpTime.year += 1970; + break; + case DT_RESTART: + if (restart_time == 0) { + return ""; + } + BreakTime(restart_time, tmpTime); + tmpTime.year += 1970; + break; + default: + tmpTime = RtcTime; + } + + snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), + tmpTime.year, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); + + if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { +// if (Settings.flag3.time_append_timezone && ((DT_LOCAL == time_type) || (DT_ENERGY == time_type))) { + strncat(dt, GetTimeZone().c_str(), sizeof(dt)); + } + + return String(dt); // 2017-03-07T11:08:02-07:00 +} + +String GetTime(int type) +{ + /* type 1 - Local time + * type 2 - Daylight Savings time + * type 3 - Standard time + */ + char stime[25]; // Skip newline + + 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); // Thu Nov 01 11:41:02 2018 +} + +String GetUptime(void) +{ + char dt[16]; + + TIME_T ut; + + if (restart_time) { + BreakTime(utc_time - restart_time, ut); + } else { + BreakTime(uptime, ut); + } + + // "P128DT14H35M44S" - ISO8601:2004 - https://en.wikipedia.org/wiki/ISO_8601 Durations +// snprintf_P(dt, sizeof(dt), PSTR("P%dDT%02dH%02dM%02dS"), ut.days, ut.hour, ut.minute, ut.second); + + // "128 14:35:44" - OpenVMS + // "128T14:35:44" - Tasmota + snprintf_P(dt, sizeof(dt), PSTR("%dT%02d:%02d:%02d"), ut.days, ut.hour, ut.minute, ut.second); + + return String(dt); // 128T14:35:44 +} + +uint32_t GetMinutesUptime(void) +{ + TIME_T ut; + + if (restart_time) { + BreakTime(utc_time - restart_time, ut); + } else { + BreakTime(uptime, ut); + } + + return (ut.days *1440) + (ut.hour *60) + ut.minute; +} + +uint32_t GetMinutesPastMidnight(void) +{ + uint32_t minutes = 0; + + if (RtcTime.valid) { + minutes = (RtcTime.hour *60) + RtcTime.minute; + } + return minutes; +} + +void BreakTime(uint32_t time_input, TIME_T &tm) +{ +// 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 month_length; + uint32_t time; + unsigned long days; + + time = time_input; + tm.second = time % 60; + time /= 60; // now it is minutes + tm.minute = time % 60; + time /= 60; // now it is hours + tm.hour = time % 24; + time /= 24; // now it is days + tm.days = time; + 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 + + days -= LEAP_YEAR(year) ? 366 : 365; + time -= days; // now it is days in this year, starting at 0 + tm.day_of_year = time; + + days = 0; + month = 0; + month_length = 0; + for (month = 0; month < 12; month++) { + if (1 == month) { // february + if (LEAP_YEAR(year)) { + month_length = 29; + } else { + month_length = 28; + } + } else { + month_length = kDaysInMonth[month]; + } + + if (time >= month_length) { + time -= month_length; + } else { + break; + } + } + 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) +{ +// assemble time elements into time_t +// note year argument is offset from 1970 + + int i; + 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++) { + 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)) { + seconds += SECS_PER_DAY * 29; + } else { + seconds += SECS_PER_DAY * kDaysInMonth[i-1]; // monthDay array starts from 0 + } + } + 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 RuleToTime(TimeRule r, int yr) +{ + TIME_T tm; + uint32_t t; + uint8_t m; + uint8_t w; // temp copies of r.month and r.week + + m = r.month; + w = r.week; + if (0 == w) { // Last week = 0 + if (++m > 12) { // for "Last", go to the next month + m = 1; + 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_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; +} + +uint32_t LocalTime(void) +{ + return local_time; +} + +uint32_t Midnight(void) +{ + return midnight; +} + +boolean MidnightNow(void) +{ + boolean mnflg = midnight_now; + if (mnflg) midnight_now = 0; + return mnflg; +} + +void RtcSecond(void) +{ + TIME_T tmpTime; + + if ((ntp_sync_minute > 59) && (RtcTime.minute > 2)) ntp_sync_minute = 1; // If sync prepare for a new cycle + uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP.getChipId() & 0xF) * 3) + 3) ; // First try ASAP to sync. If fails try once every 60 seconds based on chip id + if (!global_state.wifi_down && (offset == RtcTime.second) && ((RtcTime.year < 2016) || (ntp_sync_minute == RtcTime.minute) || ntp_force_sync)) { + ntp_time = sntp_get_current_timestamp(); + if (ntp_time > 1451602800) { // Fix NTP bug in core 2.4.1/SDK 2.2.1 (returns Thu Jan 01 08:00:10 1970 after power on) + ntp_force_sync = 0; + utc_time = ntp_time; + ntp_sync_minute = 60; // Sync so block further requests + if (restart_time == 0) { + restart_time = utc_time - uptime; // save first ntp time as restart time + } + BreakTime(utc_time, tmpTime); + RtcTime.year = tmpTime.year + 1970; + daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); + standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "(" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + AddLog(LOG_LEVEL_DEBUG); + if (local_time < 1451602800) { // 2016-01-01 + rules_flag.time_init = 1; + } else { + rules_flag.time_set = 1; + } + } else { + ntp_sync_minute++; // Try again in next minute + } + } + utc_time++; + local_time = utc_time; + if (local_time > 1451602800) { // 2016-01-01 + int16_t timezone_minutes = Settings.timezone_minutes; + if (Settings.timezone < 0) { timezone_minutes *= -1; } + time_timezone = (Settings.timezone * SECS_PER_HOUR) + (timezone_minutes * SECS_PER_MIN); + if (99 == Settings.timezone) { + int32_t dstoffset = Settings.toffset[1] * SECS_PER_MIN; + int32_t stdoffset = Settings.toffset[0] * SECS_PER_MIN; + if (Settings.tflag[1].hemis) { + // Southern hemisphere + if ((utc_time >= (standard_time - dstoffset)) && (utc_time < (daylight_saving_time - stdoffset))) { + time_timezone = stdoffset; // Standard Time + } else { + time_timezone = dstoffset; // Daylight Saving Time + } + } else { + // Northern hemisphere + if ((utc_time >= (daylight_saving_time - stdoffset)) && (utc_time < (standard_time - dstoffset))) { + time_timezone = dstoffset; // Daylight Saving Time + } else { + time_timezone = stdoffset; // Standard Time + } + } + } + local_time += time_timezone; + time_timezone /= 60; + if (!Settings.energy_kWhtotal_time) { Settings.energy_kWhtotal_time = local_time; } + } + BreakTime(local_time, RtcTime); + if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second && RtcTime.valid) { + midnight = local_time; + midnight_now = 1; + } + RtcTime.year += 1970; +} + +void RtcInit(void) +{ + 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(); + utc_time = 0; + BreakTime(utc_time, RtcTime); + TickerRtc.attach(1, RtcSecond); +} diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index b427a3f9b..4a7902303 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -34,12 +34,6 @@ #include // Wifi, MQTT, Ota, WifiManager -#ifdef USE_MQTT_TLS - WiFiClientSecure EspClient; // Wifi Secure Client -#else - WiFiClient EspClient; // Wifi Client -#endif - uint8_t wifi_counter; uint8_t wifi_retry_init; uint8_t wifi_retry; diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 85f1c71e2..09df2dd7d 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2058,7 +2058,7 @@ boolean Xdrv01(byte function) switch (function) { case FUNC_LOOP: - if (!global_state.wifi_down) { + if (!global_state.wifi_down) { PollDnsWebserver(); #ifdef USE_EMULATION if (Settings.flag2.emulation) PollUdp(); diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index a67a15d7e..b4876d436 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -55,6 +55,12 @@ /*********************************************************************************************/ +#ifdef USE_MQTT_TLS + WiFiClientSecure EspClient; // Wifi Secure Client +#else + WiFiClient EspClient; // Wifi Client +#endif + 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_PUBLISH, diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 9486a577f..1c54c12e5 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -29,6 +29,8 @@ #define FEATURE_POWER_LIMIT true +#include + enum EnergyCommands { CMND_POWERDELTA, CMND_POWERLOW, CMND_POWERHIGH, CMND_VOLTAGELOW, CMND_VOLTAGEHIGH, CMND_CURRENTLOW, CMND_CURRENTHIGH, diff --git a/tools/decode-status.py b/tools/decode-status.py index 3fad3c5c6..cca379ca6 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -88,7 +88,10 @@ a_setoption = [[ "Generic ESP8285 GPIO enabled", "Add UTC time offset to JSON message", "Show hostname and IP address in GUI", - "","","","", + "Apply SetOption20 to Tuya", + "Use short Hass discovery messages", + "Use wifi network scan at restart", + "Use wifi network rescan regularly", "","","","", "","","","", "","","","", @@ -111,7 +114,7 @@ a_features = [[ "USE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD", "USE_DISPLAY_SSD1306","USE_DISPLAY_MATRIX","USE_DISPLAY_ILI9341","USE_DISPLAY_EPAPER", "USE_DISPLAY_SH1106","USE_MP3_PLAYER","USE_PCA9685","USE_TUYA_DIMMER", - "USE_RC_SWITCH","","","", + "USE_RC_SWITCH","USE_ARMTRONIX_DIMMERS","","", "","","","NO_EXTRA_4K_HEAP", "VTABLES_IN_IRAM","VTABLES_IN_DRAM","VTABLES_IN_FLASH","PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH", "PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY","PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH","DEBUG_THEO","USE_DEBUG_DRIVER" From 0924dfcfb77cde27033d59ce92d7eded73e5d68d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 20 Nov 2018 15:53:56 +0100 Subject: [PATCH 0528/2222] Update IRRemoteESP8266 library Update IRRemoteESP8266 library from 2.2.1 to 2.5.2 --- lib/IRremoteESP8266-2.2.1.02/README.md | 74 - lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md | 112 -- .../examples/IRrecvDumpV2/IRrecvDumpV2.ino | 199 -- .../TurnOnFujitsuAC/TurnOnFujitsuAC.ino | 44 - lib/IRremoteESP8266-2.2.1.02/keywords.txt | 128 -- lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h | 207 --- .../src/IRremoteESP8266.h | 337 ---- lib/IRremoteESP8266-2.2.1.02/src/IRsend.cpp | 327 ---- lib/IRremoteESP8266-2.2.1.02/src/IRsend.h | 209 --- lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp | 82 - lib/IRremoteESP8266-2.2.1.02/src/IRutils.h | 23 - .../src/ir_Coolix.cpp | 167 -- .../src/ir_Daikin.cpp | 347 ---- lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h | 107 -- .../src/ir_Fujitsu.cpp | 221 --- lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h | 80 - lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp | 113 -- .../src/ir_Kelvinator.cpp | 329 ---- lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp | 233 --- .../src/ir_Mitsubishi.cpp | 349 ---- .../src/ir_Mitsubishi.h | 65 - lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp | 120 -- .../src/ir_Panasonic.cpp | 196 -- .../src/ir_Samsung.cpp | 175 -- .../src/ir_Trotec.cpp | 151 -- lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h | 80 - .../src/ir_Whynter.cpp | 144 -- .../test/IRsend_test.cpp | 139 -- .../test/IRsend_test.h | 106 -- .../test/IRutils_test.cpp | 91 - .../test/ir_Daikin_test.cpp | 419 ----- .../test/ir_Fujitsu_test.cpp | 207 --- .../test/ir_GlobalCache_test.cpp | 68 - .../test/ir_Gree_test.cpp | 192 -- .../test/ir_Kelvinator_test.cpp | 432 ----- .../test/ir_Mitsubishi_test.cpp | 694 ------- .../test/ir_Nikai_test.cpp | 210 --- .../test/ir_Panasonic_test.cpp | 457 ----- .../test/ir_Samsung_test.cpp | 276 --- .../test/ir_Sherwood_test.cpp | 72 - .../test/ir_Sony_test.cpp | 323 ---- .../tools/gc_decode.cpp | 106 -- .../.github/CONTRIBUTING.md | 0 .../.github/Contributors.md | 2 + .../.github/issue_template.md | 7 +- .../.gitignore | 7 + .../.gitmodules | 1 + lib/IRremoteESP8266-2.5.2.03/.style.yapf | 3 + .../.travis.yml | 4 + .../CPPLINT.cfg | 0 .../LICENSE.txt | 0 lib/IRremoteESP8266-2.5.2.03/README.md | 78 + lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md | 308 +++ .../examples/IRGCSendDemo/IRGCSendDemo.ino | 29 +- .../examples/IRGCSendDemo/platformio.ini | 0 .../examples/IRGCTCPServer/IRGCTCPServer.ino | 16 +- .../examples/IRGCTCPServer/platformio.ini | 0 .../examples/IRMQTTServer/IRMQTTServer.ino | 866 +++++++-- .../examples/IRMQTTServer/platformio.ini | 2 +- .../examples/IRServer/IRServer.ino | 19 +- .../examples/IRServer/platformio.ini | 0 .../examples/IRrecvDemo/IRrecvDemo.ino | 14 +- .../examples/IRrecvDemo/platformio.ini | 0 .../examples/IRrecvDump/IRrecvDump.ino | 4 +- .../examples/IRrecvDump/platformio.ini | 0 .../examples/IRrecvDumpV2/IRrecvDumpV2.ino | 262 +++ .../examples/IRrecvDumpV2/platformio.ini | 0 .../examples/IRsendDemo/IRsendDemo.ino | 13 +- .../examples/IRsendDemo/platformio.ini | 0 .../IRsendProntoDemo/IRsendProntoDemo.ino | 11 +- .../examples/IRsendProntoDemo/platformio.ini | 0 .../JVCPanasonicSendDemo.ino | 29 +- .../JVCPanasonicSendDemo/platformio.ini | 0 .../examples/LGACSend/LGACSend.ino | 18 +- .../examples/LGACSend}/platformio.ini | 0 .../examples/TurnOnArgoAC/TurnOnArgoAC.ino | 24 +- .../examples/TurnOnArgoAC}/platformio.ini | 0 .../TurnOnDaikinAC/TurnOnDaikinAC.ino | 37 +- .../examples/TurnOnDaikinAC}/platformio.ini | 0 .../TurnOnFujitsuAC/TurnOnFujitsuAC.ino | 50 + .../examples/TurnOnFujitsuAC}/platformio.ini | 0 .../TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino | 45 +- .../TurnOnKelvinatorAC}/platformio.ini | 0 .../TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino | 33 +- .../TurnOnMitsubishiAC}/platformio.ini | 0 .../TurnOnToshibaAC/TurnOnToshibaAC.ino | 71 + .../examples/TurnOnToshibaAC/platformio.ini | 17 + .../TurnOnTrotecAC/TurnOnTrotecAC.ino | 22 +- .../examples/TurnOnTrotecAC/platformio.ini | 17 + lib/IRremoteESP8266-2.5.2.03/keywords.txt | 1645 +++++++++++++++++ .../library.json | 2 +- .../library.properties | 2 +- .../platformio.ini | 0 lib/IRremoteESP8266-2.5.2.03/pylintrc | 12 + .../src/CPPLINT.cfg | 0 .../src/IRrecv.cpp | 390 ++-- lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h | 335 ++++ .../src/IRremoteESP8266.h | 601 ++++++ lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp | 601 ++++++ lib/IRremoteESP8266-2.5.2.03/src/IRsend.h | 333 ++++ .../src/IRtimer.cpp | 20 +- .../src/IRtimer.h | 3 + lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp | 470 +++++ lib/IRremoteESP8266-2.5.2.03/src/IRutils.h | 41 + .../src/ir_Aiwa.cpp | 40 +- .../src/ir_Argo.cpp | 104 +- .../src/ir_Argo.h | 74 +- .../src/ir_Carrier.cpp | 111 ++ .../src/ir_Coolix.cpp | 423 +++++ lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h | 139 ++ .../src/ir_Daikin.cpp | 750 ++++++++ lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h | 208 +++ .../src/ir_Denon.cpp | 77 +- .../src/ir_Dish.cpp | 80 +- .../src/ir_Electra.cpp | 112 ++ .../src/ir_Fujitsu.cpp | 519 ++++++ lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h | 123 ++ .../src/ir_GICable.cpp | 116 ++ .../src/ir_GlobalCache.cpp | 32 +- lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp | 478 +++++ lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h | 130 ++ lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp | 865 +++++++++ lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h | 297 +++ .../src/ir_Hitachi.cpp | 424 +++++ lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h | 76 + .../src/ir_JVC.cpp | 95 +- .../src/ir_Kelvinator.cpp | 550 ++++++ .../src/ir_Kelvinator.h | 60 +- lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp | 290 +++ .../src/ir_LG.h | 0 .../src/ir_Lasertag.cpp | 122 ++ .../src/ir_Lutron.cpp | 156 ++ lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp | 202 ++ .../src/ir_Magiquest.cpp | 166 ++ .../src/ir_Magiquest.h | 35 + lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp | 403 ++++ lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h | 103 ++ .../src/ir_Mitsubishi.cpp | 714 +++++++ .../src/ir_Mitsubishi.h | 109 ++ .../src/ir_NEC.cpp | 125 +- lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.h | 46 + lib/IRremoteESP8266-2.5.2.03/src/ir_Nikai.cpp | 104 ++ .../src/ir_Panasonic.cpp | 863 +++++++++ .../src/ir_Panasonic.h | 145 ++ .../src/ir_Pioneer.cpp | 143 ++ .../src/ir_Pronto.cpp | 31 +- .../src/ir_RC5_RC6.cpp | 228 +-- .../src/ir_RCMM.cpp | 116 +- .../src/ir_Samsung.cpp | 590 ++++++ lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h | 107 ++ .../src/ir_Sanyo.cpp | 100 +- .../src/ir_Sharp.cpp | 129 +- .../src/ir_Sherwood.cpp | 9 +- .../src/ir_Sony.cpp | 90 +- .../src/ir_Toshiba.cpp | 340 ++++ lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h | 85 + .../src/ir_Trotec.cpp | 127 ++ lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h | 92 + .../src/ir_Whirlpool.cpp | 149 ++ .../src/ir_Whynter.cpp | 135 ++ .../test/IRrecv_test.cpp | 181 +- .../test/IRrecv_test.h | 17 + .../test/IRsend_test.cpp | 290 +++ .../test/IRsend_test.h | 135 ++ .../test/IRutils_test.cpp | 352 ++++ .../test/Makefile | 186 +- .../test/ir_Aiwa_test.cpp | 128 +- .../test/ir_Carrier_test.cpp | 225 +++ .../test/ir_Coolix_test.cpp | 223 ++- .../test/ir_Daikin_test.cpp | 838 +++++++++ .../test/ir_Denon_test.cpp | 74 +- .../test/ir_Dish_test.cpp | 129 +- .../test/ir_Electra_test.cpp | 98 + .../test/ir_Fujitsu_test.cpp | 555 ++++++ .../test/ir_GICable_test.cpp | 161 ++ .../test/ir_GlobalCache_test.cpp | 71 + .../test/ir_Gree_test.cpp | 527 ++++++ .../test/ir_Haier_test.cpp | 989 ++++++++++ .../test/ir_Hitachi_test.cpp | 765 ++++++++ .../test/ir_JVC_test.cpp | 91 +- .../test/ir_Kelvinator_test.cpp | 518 ++++++ .../test/ir_LG_test.cpp | 202 +- .../test/ir_Lasertag_test.cpp | 342 ++++ .../test/ir_Lutron_test.cpp | 143 ++ .../test/ir_MWM_test.cpp | 124 ++ .../test/ir_Magiquest_test.cpp | 162 ++ .../test/ir_Midea_test.cpp | 651 +++++++ .../test/ir_Mitsubishi_test.cpp | 1118 +++++++++++ .../test/ir_NEC_test.cpp | 151 +- .../test/ir_Nikai_test.cpp | 212 +++ .../test/ir_Panasonic_test.cpp | 1135 ++++++++++++ .../test/ir_Pioneer_test.cpp | 152 ++ .../test/ir_Pronto_test.cpp | 210 ++- .../test/ir_RC5_RC6_test.cpp | 341 ++-- .../test/ir_RCMM_test.cpp | 90 +- .../test/ir_Samsung_test.cpp | 907 +++++++++ .../test/ir_Sanyo_test.cpp | 126 +- .../test/ir_Sharp_test.cpp | 99 +- .../test/ir_Sherwood_test.cpp | 78 + .../test/ir_Sony_test.cpp | 357 ++++ .../test/ir_Toshiba_test.cpp | 664 +++++++ .../test/ir_Whirlpool_test.cpp | 118 ++ .../test/ir_Whynter_test.cpp | 73 +- .../tools/Makefile | 72 +- .../tools/RawToGlobalCache.sh | 53 + .../tools/auto_analyse_raw_data.py | 432 +++++ .../tools/auto_analyse_raw_data_test.py | 492 +++++ .../tools/gc_decode.cpp | 109 ++ lib/IRremoteESP8266-2.5.2.03/tools/mkkeywords | 82 + .../tools/mode2_decode.cpp | 122 ++ sonoff/xplg_ws2812.ino | 6 +- 211 files changed, 31772 insertions(+), 10416 deletions(-) delete mode 100644 lib/IRremoteESP8266-2.2.1.02/README.md delete mode 100644 lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md delete mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/IRrecvDumpV2.ino delete mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino delete mode 100644 lib/IRremoteESP8266-2.2.1.02/keywords.txt delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRsend.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRsend.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRutils.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Coolix.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Panasonic.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Samsung.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Whynter.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.h delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/IRutils_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Daikin_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Fujitsu_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_GlobalCache_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Gree_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Kelvinator_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Mitsubishi_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Nikai_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Panasonic_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Samsung_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Sherwood_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Sony_test.cpp delete mode 100644 lib/IRremoteESP8266-2.2.1.02/tools/gc_decode.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/.github/CONTRIBUTING.md (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/.github/Contributors.md (91%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/.github/issue_template.md (84%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/.gitignore (88%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/.gitmodules (85%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/.style.yapf rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/.travis.yml (94%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/CPPLINT.cfg (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/LICENSE.txt (100%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/README.md create mode 100644 lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRGCSendDemo/IRGCSendDemo.ino (66%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRGCSendDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRGCTCPServer/IRGCTCPServer.ino (89%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRGCTCPServer/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRMQTTServer/IRMQTTServer.ino (55%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRMQTTServer/platformio.ini (96%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRServer/IRServer.ino (88%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRServer/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRrecvDemo/IRrecvDemo.ino (66%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRrecvDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRrecvDump/IRrecvDump.ino (96%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRrecvDump/platformio.ini (100%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/IRrecvDumpV2.ino rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRrecvDumpV2/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRsendDemo/IRsendDemo.ino (87%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRsendDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRsendProntoDemo/IRsendProntoDemo.ino (93%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/IRsendProntoDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino (64%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/JVCPanasonicSendDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/LGACSend/LGACSend.ino (95%) rename lib/{IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC => IRremoteESP8266-2.5.2.03/examples/LGACSend}/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/TurnOnArgoAC/TurnOnArgoAC.ino (72%) rename lib/{IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC => IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC}/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino (64%) rename lib/{IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC => IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC}/platformio.ini (100%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino rename lib/{IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC => IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC}/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino (63%) rename lib/{IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC => IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC}/platformio.ini (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino (72%) rename lib/{IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC => IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC}/platformio.ini (100%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino create mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/platformio.ini rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino (74%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/platformio.ini create mode 100644 lib/IRremoteESP8266-2.5.2.03/keywords.txt rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/library.json (97%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/library.properties (96%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/platformio.ini (100%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/pylintrc rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/CPPLINT.cfg (100%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/IRrecv.cpp (59%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRremoteESP8266.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRsend.h rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/IRtimer.cpp (52%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/IRtimer.h (78%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRutils.h rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Aiwa.cpp (76%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Argo.cpp (69%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Argo.h (51%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Carrier.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Denon.cpp (59%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Dish.cpp (59%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Electra.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_GICable.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_GlobalCache.cpp (66%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_JVC.cpp (57%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Kelvinator.h (71%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_LG.h (100%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Lasertag.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Lutron.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.h rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_NEC.cpp (53%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Nikai.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Pioneer.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Pronto.cpp (81%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_RC5_RC6.cpp (70%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_RCMM.cpp (58%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Sanyo.cpp (70%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Sharp.cpp (68%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Sherwood.cpp (71%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/src/ir_Sony.cpp (62%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Whirlpool.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Whynter.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/IRrecv_test.cpp (68%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.h create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/IRutils_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/Makefile (63%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Aiwa_test.cpp (70%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Carrier_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Coolix_test.cpp (60%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Daikin_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Denon_test.cpp (82%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Dish_test.cpp (76%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Electra_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Fujitsu_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_GICable_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_GlobalCache_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Gree_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Haier_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Hitachi_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_JVC_test.cpp (76%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Kelvinator_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_LG_test.cpp (63%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Lasertag_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Lutron_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_MWM_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Magiquest_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Midea_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Mitsubishi_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_NEC_test.cpp (63%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Nikai_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Panasonic_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Pioneer_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Pronto_test.cpp (81%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_RC5_RC6_test.cpp (70%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_RCMM_test.cpp (72%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Samsung_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Sanyo_test.cpp (63%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Sharp_test.cpp (79%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Sherwood_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Sony_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Toshiba_test.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Whirlpool_test.cpp rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/test/ir_Whynter_test.cpp (82%) rename lib/{IRremoteESP8266-2.2.1.02 => IRremoteESP8266-2.5.2.03}/tools/Makefile (63%) create mode 100644 lib/IRremoteESP8266-2.5.2.03/tools/RawToGlobalCache.sh create mode 100644 lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data.py create mode 100644 lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data_test.py create mode 100644 lib/IRremoteESP8266-2.5.2.03/tools/gc_decode.cpp create mode 100644 lib/IRremoteESP8266-2.5.2.03/tools/mkkeywords create mode 100644 lib/IRremoteESP8266-2.5.2.03/tools/mode2_decode.cpp diff --git a/lib/IRremoteESP8266-2.2.1.02/README.md b/lib/IRremoteESP8266-2.2.1.02/README.md deleted file mode 100644 index 6b2975793..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# IRremote ESP8266 Library - -[![Build Status](https://travis-ci.org/markszabo/IRremoteESP8266.svg?branch=master)](https://travis-ci.org/markszabo/IRremoteESP8266) -[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Average time to resolve an issue") -[![Percentage of issues still open](http://isitmaintained.com/badge/open/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Percentage of issues still open") -[![GitLicense](https://gitlicense.com/badge/markszabo/IRremoteESP8266)](https://gitlicense.com/license/markszabo/IRremoteESP8266) - -This library enables you to **send and receive** infra-red signals on an ESP8266 using Arduino framework (https://github.com/esp8266/Arduino) - -## v2.2 Now Available -Version 2.2 of the library is now available. This is a significant internal change to existing versions. - -## Upgrading from versions prior to v2.0 -You will need to change your pre-v2.0 code slightly to work with post-v2.0 versions of the library. You can read more about the changes on our [wiki](https://github.com/markszabo/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. -Please [report an issue](https://github.com/markszabo/IRremoteESP8266/issues/new) if you find any problems with the documentation or the library itself. - -## Troubleshooting -Before reporting an issue or asking for help, please try to follow our [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide) first. - -## Frequently Asked Questions -Some common answers to common questions and problems can be found on our [F.A.Q. wiki page](https://github.com/markszabo/IRremoteESP8266/wiki/Frequently-Asked-Questions). - -## History -This library was originally based on Ken Shirriff's work (https://github.com/shirriff/Arduino-IRremote/) - -[Mark Szabo](https://github.com/markszabo/IRremoteESP8266) has updated the IRsend class to work on ESP8266 and [Sebastien Warin](https://github.com/sebastienwarin/IRremoteESP8266) the receiving & decoding part (IRrecv class). - -## Installation -1. Click "Download ZIP" -2. Extract the downloaded zip file -3. Rename the extracted folder to "IRremoteESP8266" -4. Move this folder to your libraries directory (under windows: C:\Users\YOURNAME\Documents\Arduino\libraries\) -5. Restart your Arduino ide -6. Check out the examples - -###### Using Git to install library ( Linux ) -``` -cd ~/Arduino/libraries -git clone https://github.com/markszabo/IRremoteESP8266.git -``` -###### To Update to the latest version of the library -` -cd ~/Arduino/libraries/IRremoteESP8266 && git pull -` - -## Unit Tests -The [Unit Tests](https://en.wikipedia.org/wiki/Unit_testing) under the test/ directory are for a Unix machine, **not** the micro-controller (ESP8266). -This allows execution under Travis and on the developer's machine. -We can do this from v2.0 of the library onwards, as everything now uses c98-style type definitions. -e.g. uint16_t etc. -Any Arduino/ESP8266 specific code needs to be disabled using something similar to the following lines: -``` -#ifndef UNIT_TEST - -#endif -``` - -This is not a perfect situation as we can not obviously emulate hardware specific features and differences. e.g. Interrupts, GPIOs, CPU instruction timing etc, etc. - -If you want to run all the tests yourself, try the following: -``` -$ cd test -$ make run -``` - -## Contributing -If you want to [contribute](.github/CONTRIBUTING.md#how-can-i-contribute) to this project, consider: -- [Report](.github/CONTRIBUTING.md#reporting-bugs) bugs and errors -- Ask for enhancements -- [Create issues](.github/CONTRIBUTING.md#reporting-bugs) and [pull requests](.github/CONTRIBUTING.md#pull-requests) -- Tell other people about this library - -## Contributors -Available [here](.github/Contributors.md) diff --git a/lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md b/lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md deleted file mode 100644 index 3b9bce86a..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md +++ /dev/null @@ -1,112 +0,0 @@ -# Release Notes - -## _v2.2.1 (20171025)_ - -**[Features]** -- Support for sending and decoding Nikai TV messages. (#311, #313) -- gc_decode: External utility to decode Global Cache codes. (#308, #312) -- IRMQTTServer: Example code to send IR messages via HTTP & MQTT. (#316, #323) -- Improve converting 64bit values to hexidecimal. (#318) - -**[Misc]** -- IRrecvDump.ino code is now deprecated. Use IRrecvDumpV2.ino instead. (#314) - - -## _v2.2.0 (20170922)_ - -**[Bug Fixes]** -- Add printing output of RC-MM and RC-5X protocols in example code. (#284) -- LG timing improvements based on observations (#291) - -**[Features]** -- Automatic capture timing calibration for some protocols. (#268) -- Support for creating & sending Trotec AC codes. (#279) -- Support for creating & sending Argo Ulisse 13 DCI codes. (#280 #300) -- Move to 2 microsecond timing resolution for capture of codes. (#287) -- Capture buffer changes: -- Size at runtime. (#276) -- Message timeout at runtime. (#294) -- Simplify creating & using a second buffer (#303) -- New example code: - - Trotec A/C (#279) - - LG A/C units (#289) - - Argo Ulisse 13 DCI codes. (#300) - - -## _v2.1.1 (20170711)_ - -**[Bug Fixes]** -- GlobalCache incorrectly using hardware offset for period calc. (#267) - -**[Features]** -- Support reporting of 'NEC'-like 32-bit protocols. e.g. Apple TV remote (#265) -- Add an example of sendRaw() to IRsendDemo.ino (#270) - - -## _v2.1.0 (20170704)_ - -**[Features]** -- Support for sending Pronto IR codes. (#248) -- Support for sending Fujitsu A/C codes. (#88) -- Minor improvements to examples. - - -## _v2.0.3 (20170618)_ - -**[Bug fixes]** -- Capture buffer could become corrupt after large message, breaking subsequent decodes. (#253) - - -## _v2.0.2 (20170615)_ - -**[Bug fixes]** -- Correct decode issue introduced in v2.0.1 affecting multiple protocol decoders (#243) -- Correct post-message gap for the Panasonic protocol(s) (#245) -- Incorrect display of the decoded uint64_t value in the example code. (#245) - - -## _v2.0.1 (20170614)_ - -**[Bug fixes]** -- Decoding protocols when it doesn't detect a post-command gap, and there is no more data. (#243) -- Incorrect minimum size calculation when there is no post-command gap. (#243) - - -## _v2.0.0 - 64 bit support and major improvements (20170612)_ - -**[Misc]** -- This is almost a complete re-write of the library. - -**[Features]** -- All suitable protocols now handle 64-bit data messages and are repeatable via an optional argument. -- Unit tests for all protocols. -- Far better and stricter decoding for most protocols. -- Address & command decoding for protocols where that information is available. -- Much more precise timing for generation of signals sent. -- Lower duty-cycles for some protocols. -- Several new protocols added, and some new sending and decoding routines for existing ones. -- Ability to optionally chose which protocols are included, enabling faster decoding and smaller code footprints if desired. -- Support for far larger capture buffers. (e.g. RAWLEN > 256) - -**[Bug fixes]** -- Numerous bug fixes. - - -## _v1.2.0 (20170429)_ - -**[Features]** -- Add ability to copy IR capture buffer, and continue capturing. Means faster and better IR command decoding. -- Reduce IRAM usage by 28 bytes. -- Improve capture of RC-MM & Panasonic protocols. -- Upgrade IRrecvDumpV2 to new IR capture buffer. Much fewer corrupted/truncated IR messages. - - -## _v1.1.1 (20170413)_ - -**[Bug fixes]** -- Fix a reported problem when sending the LG protocol. Preemptive fix for possible similar cases. -- Fix minor issues in examples. - -**[Features]** -- Add documentation to some examples to aid new people. -- Add ALPHA support for RC-MM protocol. (Known to be currently not 100% working.) diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/IRrecvDumpV2.ino deleted file mode 100644 index bb86a5f9d..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/IRrecvDumpV2.ino +++ /dev/null @@ -1,199 +0,0 @@ -/* - * IRremoteESP8266: IRrecvDumpV2 - dump details of IR codes with IRrecv - * An IR detector/demodulator must be connected to the input RECV_PIN. - * Example circuit diagram: - * https://github.com/markszabo/IRremoteESP8266/wiki#ir-receiving - * Changes: - * Version 0.2 April, 2017 - * - Decode from a copy of the data so we can start capturing faster thus - * reduce the likelihood of miscaptures. - * Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, Copyright 2009 Ken Shirriff, http://arcfn.com - */ - -#ifndef UNIT_TEST -#include -#endif -#include -#include -#include - -// An IR detector/demodulator is connected to GPIO pin 14(D5 on a NodeMCU -// board). -uint16_t RECV_PIN = 14; -// As this program is a special purpose capture/decoder, let us use a larger -// than normal buffer so we can handle Air Conditioner remote codes. -uint16_t CAPTURE_BUFFER_SIZE = 1024; - -// Nr. of milli-Seconds of no-more-data before we consider a message ended. -// NOTE: Don't exceed MAX_TIMEOUT_MS. Typically 130ms. -#define TIMEOUT 15U // Suits most messages, while not swallowing repeats. -// #define TIMEOUT 90U // Suits messages with big gaps like XMP-1 & some aircon - // units, but can accidently swallow repeated messages - // in the rawData[] output. - -// Use turn on the save buffer feature for more complete capture coverage. -IRrecv irrecv(RECV_PIN, CAPTURE_BUFFER_SIZE, TIMEOUT, true); - -decode_results results; // Somewhere to store the results - -void setup() { - // Status message will be sent to the PC at 115200 baud - Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY); - delay(500); // Wait a bit for the serial connection to be establised. - - irrecv.enableIRIn(); // Start the receiver -} - -// Display encoding type -// -void encoding(decode_results *results) { - switch (results->decode_type) { - default: - case UNKNOWN: Serial.print("UNKNOWN"); break; - case NEC: Serial.print("NEC"); break; - case NEC_LIKE: Serial.print("NEC (non-strict)"); break; - case SONY: Serial.print("SONY"); break; - case RC5: Serial.print("RC5"); break; - case RC5X: Serial.print("RC5X"); break; - case RC6: Serial.print("RC6"); break; - case RCMM: Serial.print("RCMM"); break; - case DISH: Serial.print("DISH"); break; - case SHARP: Serial.print("SHARP"); break; - case JVC: Serial.print("JVC"); break; - case SANYO: Serial.print("SANYO"); break; - case SANYO_LC7461: Serial.print("SANYO_LC7461"); break; - case MITSUBISHI: Serial.print("MITSUBISHI"); break; - case SAMSUNG: Serial.print("SAMSUNG"); break; - case LG: Serial.print("LG"); break; - case WHYNTER: Serial.print("WHYNTER"); break; - case AIWA_RC_T501: Serial.print("AIWA_RC_T501"); break; - case PANASONIC: Serial.print("PANASONIC"); break; - case DENON: Serial.print("DENON"); break; - case COOLIX: Serial.print("COOLIX"); break; - case NIKAI: Serial.print("NIKAI"); break; - } - if (results->repeat) Serial.print(" (Repeat)"); -} - -// Dump out the decode_results structure. -// -void dumpInfo(decode_results *results) { - if (results->overflow) - Serial.printf("WARNING: IR code too big for buffer (>= %d). " - "These results shouldn't be trusted until this is resolved. " - "Edit & increase CAPTURE_BUFFER_SIZE.\n", - CAPTURE_BUFFER_SIZE); - - // Show Encoding standard - Serial.print("Encoding : "); - encoding(results); - Serial.println(""); - - // Show Code & length - Serial.print("Code : "); - serialPrintUint64(results->value, 16); - Serial.print(" ("); - Serial.print(results->bits, DEC); - Serial.println(" bits)"); -} - -uint16_t getCookedLength(decode_results *results) { - uint16_t length = results->rawlen - 1; - for (uint16_t i = 0; i < results->rawlen - 1; i++) { - uint32_t usecs = results->rawbuf[i] * RAWTICK; - // Add two extra entries for multiple larger than UINT16_MAX it is. - length += (usecs / UINT16_MAX) * 2; - } - return length; -} - -// Dump out the decode_results structure. -// -void dumpRaw(decode_results *results) { - // Print Raw data - Serial.print("Timing["); - Serial.print(results->rawlen - 1, DEC); - Serial.println("]: "); - - for (uint16_t i = 1; i < results->rawlen; i++) { - if (i % 100 == 0) - yield(); // Preemptive yield every 100th entry to feed the WDT. - if (i % 2 == 0) { // even - Serial.print("-"); - } else { // odd - Serial.print(" +"); - } - Serial.printf("%6d", results->rawbuf[i] * RAWTICK); - if (i < results->rawlen - 1) - Serial.print(", "); // ',' not needed for last one - if (!(i % 8)) Serial.println(""); - } - Serial.println(""); // Newline -} - -// Dump out the decode_results structure. -// -void dumpCode(decode_results *results) { - // Start declaration - Serial.print("uint16_t "); // variable type - Serial.print("rawData["); // array name - Serial.print(getCookedLength(results), DEC); // array size - Serial.print("] = {"); // Start declaration - - // Dump data - for (uint16_t i = 1; i < results->rawlen; i++) { - uint32_t usecs; - for (usecs = results->rawbuf[i] * RAWTICK; - usecs > UINT16_MAX; - usecs -= UINT16_MAX) - Serial.printf("%d, 0", UINT16_MAX); - Serial.print(usecs, DEC); - if (i < results->rawlen - 1) - Serial.print(", "); // ',' not needed on last one - if (i % 2 == 0) Serial.print(" "); // Extra if it was even. - } - - // End declaration - Serial.print("};"); // - - // Comment - Serial.print(" // "); - encoding(results); - Serial.print(" "); - serialPrintUint64(results->value, HEX); - - // Newline - Serial.println(""); - - // Now dump "known" codes - if (results->decode_type != UNKNOWN) { - // Some protocols have an address &/or command. - // NOTE: It will ignore the atypical case when a message has been decoded - // but the address & the command are both 0. - if (results->address > 0 || results->command > 0) { - Serial.print("uint32_t address = 0x"); - Serial.print(results->address, HEX); - Serial.println(";"); - Serial.print("uint32_t command = 0x"); - Serial.print(results->command, HEX); - Serial.println(";"); - } - - // All protocols have data - Serial.print("uint64_t data = 0x"); - serialPrintUint64(results->value, 16); - Serial.println(";"); - } -} - -// The repeating section of the code -// -void loop() { - // Check if the IR code has been received. - if (irrecv.decode(&results)) { - dumpInfo(&results); // Output the results - dumpRaw(&results); // Output the results in RAW format - dumpCode(&results); // Output the results as source code - Serial.println(""); // Blank line between entries - } -} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino deleted file mode 100644 index 52e31b5d8..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2017 Jonny Graham -#include -#include - -IRFujitsuAC fujitsu(5); // IR led controlled by Pin D1. - -void printState() { - // Display the settings. - Serial.println("Fujitsu A/C remote is in the following state:"); - Serial.printf(" Command:%d, Mode: %d, Temp: %dC, Fan Speed: %d," \ - " Swing Mode: %d\n", - fujitsu.getCmd(), fujitsu.getMode(), fujitsu.getTemp(), - fujitsu.getFanSpeed(), fujitsu.getSwing()); - // Display the encoded IR sequence. - unsigned char* ir_code = fujitsu.getRaw(); - Serial.print("IR Code: 0x"); - for (uint8_t i = 0; i < FUJITSU_AC_STATE_LENGTH; i++) - Serial.printf("%02X", ir_code[i]); - Serial.println(); -} - -void setup() { - fujitsu.begin(); - Serial.begin(115200); - delay(200); - - // Set up what we want to send. See ir_Mitsubishi.cpp for all the options. - Serial.println("Default state of the remote."); - printState(); - Serial.println("Setting desired state for A/C."); - fujitsu.setCmd(FUJITSU_AC_CMD_TURN_ON); - fujitsu.setSwing(FUJITSU_AC_SWING_BOTH); - fujitsu.setMode(FUJITSU_AC_MODE_COOL); - fujitsu.setFanSpeed(FUJITSU_AC_FAN_HIGH); - fujitsu.setTemp(24); -} - -void loop() { - // Now send the IR signal. - Serial.println("Sending IR command to A/C ..."); - fujitsu.send(); - printState(); - delay(5000); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/keywords.txt b/lib/IRremoteESP8266-2.2.1.02/keywords.txt deleted file mode 100644 index ab1b3f70c..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/keywords.txt +++ /dev/null @@ -1,128 +0,0 @@ -######################################### -# Syntax Coloring Map For IRremoteESP8266 -######################################### - -####################################################### -# The Arduino IDE requires the use of a tab separator -# between the name and identifier. Without this tab the -# keyword is not highlighted. -# -# Reference: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords -####################################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -decode_results KEYWORD1 -IRrecv KEYWORD1 -IRsend KEYWORD1 -IRtimer KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -decode KEYWORD2 -enableIRIn KEYWORD2 -disableIRIn KEYWORD2 -resume KEYWORD2 -begin KEYWORD2 -send KEYWORD2 -enableIROut KEYWORD2 -sendNEC KEYWORD2 -encodeNEC KEYWORD2 -sendLG KEYWORD2 -encodeLG KEYWORD2 -sendSony KEYWORD2 -encodeSony KEYWORD2 -sendSanyo KEYWORD2 -sendSanyoLC7461 KEYWORD2 -encodeSanyoLC7461 KEYWORD2 -sendMitsubishi KEYWORD2 -sendRaw KEYWORD2 -sendGC KEYWORD2 -sendRC5 KEYWORD2 -sendRC6 KEYWORD2 -sendRCMM KEYWORD2 -sendDISH KEYWORD2 -sendSharp KEYWORD2 -sendSharpRaw KEYWORD2 -encodeSharp KEYWORD2 -sendPanasonic KEYWORD2 -sendPanasonic64 KEYWORD2 -encodePanasonic KEYWORD2 -sendJVC KEYWORD2 -encodeJVC KEYWORD2 -sendWhynter KEYWORD2 -sendSAMSUNG KEYWORD2 -encodeSAMSUNG KEYWORD2 -sendDaikin KEYWORD2 -sendCOOLIX KEYWORD2 -sendDenon KEYWORD2 -sendKelvinator KEYWORD2 -sendSherwood KEYWORD2 -sendMitsubishiAC KEYWORD2 -mark KEYWORD2 -space KEYWORD2 -reset KEYWORD2 -elapsed KEYWORD2 -calcLGChecksum KEYWORD2 -reverseBits KEYWORD2 - -####################################### -# Constants (LITERAL1) -####################################### - -NEC LITERAL1 -SONY LITERAL1 -SANYO LITERAL1 -MITSUBISHI LITERAL1 -RC5 LITERAL1 -RC5X LITERAL1 -RC6 LITERAL1 -DISH LITERAL1 -SHARP LITERAL1 -PANASONIC LITERAL1 -JVC LITERAL1 -LG LITERAL1 -SAMSUNG LITERAL1 -WHYNTER LITERAL1 -AIWA_RC_T501 LITERAL1 -COOLIX LITERAL1 -UNKNOWN LITERAL1 -REPEAT LITERAL1 -DENON LITERAL1 -DAIKIN LITERAL1 -KELVINATOR LITERAL1 -SHERWOOD LITERAL1 -MITSUBISHIAC LITERAL1 -RCMM LITERAL1 -SANYO_LC7461 LITERAL1 -NEC_BITS LITERAL1 -SHERWOOD_BITS LITERAL1 -SONY_MIN_BITS LITERAL1 -SONY_12_BITS LITERAL1 -SONY_15_BITS LITERAL1 -SONY_20_BITS LITERAL1 -SANYO_SA8650B_BITS LITERAL1 -MITSUBISHI_BITS LITERAL1 -PANASONIC_BITS LITERAL1 -JVC_BITS LITERAL1 -LG_BITS LITERAL1 -SAMSUNG_BITS LITERAL1 -COOLIX_BITS LITERAL1 -DAIKIN_BITS LITERAL1 -RC5X_BITS LITERAL1 -RC6_36_BITS LITERAL1 -RC6_MODE0_BITS LITERAL1 -RCMM_BITS LITERAL1 -WHYNTER_BITS LITERAL1 -SANYO_LC7461_BITS LITERAL1 -SHARP_BITS LITERAL1 -DISH_BITS LITERAL1 -DENON_BITS LITERAL1 -SONY_MIN_REPEAT LITERAL1 -MITSUBISHI_MIN_REPEAT LITERAL1 -DISH_MIN_REPEAT LITERAL1 -SHERWOOD_MIN_REPEAT LITERAL1 diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h b/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h deleted file mode 100644 index febe5e2d5..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2015 Mark Szabo -// Copyright 2015 Sebastien Warin -// Copyright 2017 David Conran - -#ifndef IRRECV_H_ -#define IRRECV_H_ - -#ifndef UNIT_TEST -#include -#endif -#include -#define __STDC_LIMIT_MACROS -#include -#include "IRremoteESP8266.h" - -// Constants -#define HEADER 2U // Usual nr. of header entries. -#define FOOTER 2U // Usual nr. of footer (stop bits) entries. -#define OFFSET_START 1U // Usual rawbuf entry to start processing from. -#define MS_TO_USEC(x) (x * 1000U) // Convert milli-Seconds to micro-Seconds. -// Marks tend to be 100us too long, and spaces 100us too short -// when received due to sensor lag. -#define MARK_EXCESS 50U -#define RAWBUF 100U // Default length of raw capture buffer -#define REPEAT UINT64_MAX -// receiver states -#define STATE_IDLE 2U -#define STATE_MARK 3U -#define STATE_SPACE 4U -#define STATE_STOP 5U -#define TOLERANCE 25U // default percent tolerance in measurements -#define RAWTICK 2U // Capture tick to uSec factor. -// How long (ms) before we give up wait for more data? -// Don't exceed MAX_TIMEOUT_MS without a good reason. -// That is the capture buffers maximum value size. (UINT16_MAX / RAWTICK) -// Typically messages/protocols tend to repeat around the 100ms timeframe, -// thus we should timeout before that to give us some time to try to decode -// before we need to start capturing a possible new message. -// Typically 15ms suits most applications. However, some protocols demand a -// higher value. e.g. 90ms for XMP-1 and some aircon units. -#define TIMEOUT_MS 15U // In MilliSeconds. -#define MAX_TIMEOUT_MS (RAWTICK * UINT16_MAX / MS_TO_USEC(1)) - -// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param -#define FNV_PRIME_32 16777619UL -#define FNV_BASIS_32 2166136261UL - -// Types -// information for the interrupt handler -typedef struct { - uint8_t recvpin; // pin for IR data from detector - uint8_t rcvstate; // state machine - uint16_t timer; // state timer, counts 50uS ticks. - uint16_t bufsize; // max. nr. of entries in the capture buffer. - uint16_t *rawbuf; // raw data - // uint16_t is used for rawlen as it saves 3 bytes of iram in the interrupt - // handler. Don't ask why, I don't know. It just does. - uint16_t rawlen; // counter of entries in rawbuf. - uint8_t overflow; // Buffer overflow indicator. - uint8_t timeout; // Nr. of milliSeconds before we give up. -} irparams_t; - -// results from a data match -typedef struct { - bool success; // Was the match successful? - uint64_t data; // The data found. - uint16_t used; // How many buffer positions were used. -} match_result_t; - -// Classes - -// Results returned from the decoder -class decode_results { - public: - decode_type_t decode_type; // NEC, SONY, RC5, UNKNOWN - uint64_t value; // Decoded value - uint16_t bits; // Number of bits in decoded value - volatile uint16_t *rawbuf; // Raw intervals in .5 us ticks - uint16_t rawlen; // Number of records in rawbuf. - bool overflow; - bool repeat; // Is the result a repeat code? - uint32_t address; // Decoded device address. - uint32_t command; // Decoded command. -}; - -// main class for receiving IR -class IRrecv { - public: - explicit IRrecv(uint16_t recvpin, uint16_t bufsize = RAWBUF, - uint8_t timeout = TIMEOUT_MS, - bool save_buffer = false); // Constructor - ~IRrecv(); // Destructor - bool decode(decode_results *results, irparams_t *save = NULL); - void enableIRIn(); - void disableIRIn(); - void resume(); - uint16_t getBufSize(); - -#ifndef UNIT_TEST - - private: -#endif - irparams_t *irparams_save; - // These are called by decode - void copyIrParams(volatile irparams_t *src, irparams_t *dst); - int16_t compare(uint16_t oldval, uint16_t newval); - uint32_t ticksLow(uint32_t usecs, uint8_t tolerance = TOLERANCE); - uint32_t ticksHigh(uint32_t usecs, uint8_t tolerance = TOLERANCE); - bool match(uint32_t measured, uint32_t desired, - uint8_t tolerance = TOLERANCE); - bool matchAtLeast(uint32_t measured, uint32_t desired, - uint8_t tolerance = TOLERANCE); - bool matchMark(uint32_t measured, uint32_t desired, - uint8_t tolerance = TOLERANCE, int16_t excess = MARK_EXCESS); - bool matchSpace(uint32_t measured, uint32_t desired, - uint8_t tolerance = TOLERANCE, int16_t excess = MARK_EXCESS); - match_result_t matchData(volatile uint16_t *data_ptr, uint16_t nbits, - uint16_t onemark, uint32_t onespace, - uint16_t zeromark, uint32_t zerospace); - bool decodeHash(decode_results *results); -#if (DECODE_NEC || DECODE_SHERWOOD || DECODE_AIWA_RC_T501 || SEND_SANYO) - bool decodeNEC(decode_results *results, uint16_t nbits = NEC_BITS, - bool strict = true); -#endif -#if DECODE_SONY - bool decodeSony(decode_results *results, uint16_t nbits = SONY_MIN_BITS, - bool strict = false); -#endif -#if DECODE_SANYO - // DISABLED due to poor quality. - // bool decodeSanyo(decode_results *results, - // uint16_t nbits = SANYO_SA8650B_BITS, - // bool strict = false); - bool decodeSanyoLC7461(decode_results *results, - uint16_t nbits = SANYO_LC7461_BITS, - bool strict = true); -#endif -#if DECODE_MITSUBISHI - bool decodeMitsubishi(decode_results *results, - uint16_t nbits = MITSUBISHI_BITS, - bool strict = true); -#endif -#if (DECODE_RC5 || DECODE_R6) - int16_t getRClevel(decode_results *results, uint16_t *offset, uint16_t *used, - uint16_t bitTime); -#endif -#if DECODE_RC5 - bool decodeRC5(decode_results *results, uint16_t nbits = RC5X_BITS, - bool strict = true); -#endif -#if DECODE_RC6 - bool decodeRC6(decode_results *results, uint16_t nbits = RC6_MODE0_BITS, - bool strict = false); -#endif -#if DECODE_RCMM - bool decodeRCMM(decode_results *results, uint16_t nbits = RCMM_BITS, - bool strict = false); -#endif -#if (DECODE_PANASONIC || DECODE_DENON) - bool decodePanasonic(decode_results *results, uint16_t nbits = PANASONIC_BITS, - bool strict = false, - uint32_t manufacturer = PANASONIC_MANUFACTURER); -#endif -#if DECODE_LG - bool decodeLG(decode_results *results, uint16_t nbits = LG_BITS, - bool strict = false); -#endif -#if DECODE_JVC - bool decodeJVC(decode_results *results, uint16_t nbits = JVC_BITS, - bool strict = true); -#endif -#if DECODE_SAMSUNG - bool decodeSAMSUNG(decode_results *results, uint16_t nbits = SAMSUNG_BITS, - bool strict = true); -#endif -#if DECODE_WHYNTER - bool decodeWhynter(decode_results *results, uint16_t nbits = WHYNTER_BITS, - bool strict = true); -#endif -#if DECODE_COOLIX - bool decodeCOOLIX(decode_results *results, uint16_t nbits = COOLIX_BITS, - bool strict = true); -#endif -#if DECODE_DENON - bool decodeDenon(decode_results *results, uint16_t nbits = DENON_BITS, - bool strict = true); -#endif -#if DECODE_DISH - bool decodeDISH(decode_results *results, uint16_t nbits = DISH_BITS, - bool strict = true); -#endif -#if (DECODE_SHARP || DECODE_DENON) - bool decodeSharp(decode_results *results, uint16_t nbits = SHARP_BITS, - bool strict = true, bool expansion = true); -#endif -#if DECODE_AIWA_RC_T501 - bool decodeAiwaRCT501(decode_results *results, - uint16_t nbits = AIWA_RC_T501_BITS, bool strict = true); -#endif -#if DECODE_NIKAI - bool decodeNikai(decode_results *results, uint16_t nbits = NIKAI_BITS, - bool strict = true); -#endif -}; - -#endif // IRRECV_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h b/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h deleted file mode 100644 index 52c8b6e10..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h +++ /dev/null @@ -1,337 +0,0 @@ - /*************************************************** - * IRremote for ESP8266 - * - * Based on the IRremote library for Arduino by Ken Shirriff - * Version 0.11 August, 2009 - * Copyright 2009 Ken Shirriff - * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html - * - * Edited by Mitra to add new controller SANYO - * - * Interrupt code based on NECIRrcv by Joe Knapp - * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 - * Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ - * - * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) - * LG added by Darryl Smith (based on the JVC protocol) - * Whynter A/C ARC-110WD added by Francesco Meschia - * Coolix A/C / heatpump added by (send) bakrus & (decode) crankyoldgit - * Denon: sendDenon, decodeDenon added by Massimiliano Pinto - (from https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Denon.cpp) - * Kelvinator A/C and Sherwood added by crankyoldgit - * Mitsubishi (TV) sending added by crankyoldgit - * Pronto code sending added by crankyoldgit - * Mitsubishi A/C added by crankyoldgit - * (derived from https://github.com/r45635/HVAC-IR-Control) - * DISH decode by marcosamarinho - * Gree Heatpump sending added by Ville Skyttä (scop) - * (derived from https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp) - * Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for sending IR code on ESP8266 - * Updated by Sebastien Warin (http://sebastien.warin.fr) for receiving IR code on ESP8266 - * - * Updated by sillyfrog for Daikin, adopted from - * (https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/) - * Fujitsu A/C code added by jonnygraham - * Trotec AC code by stufisher - * GPL license, all text above must be included in any redistribution - ****************************************************/ - -#ifndef IRREMOTEESP8266_H_ -#define IRREMOTEESP8266_H_ - -#define __STDC_LIMIT_MACROS -#include -#ifdef UNIT_TEST -#include -#endif - -// Library Version -#define _IRREMOTEESP8266_VERSION_ "2.2.1" -// Supported IR protocols -// Each protocol you include costs memory and, during decode, costs time -// Disable (set to false) all the protocols you do not need/want! -// -/* -#define DECODE_NEC true -#define SEND_NEC true - -#define DECODE_SHERWOOD true // Doesn't exist. Actually is DECODE_NEC -#define SEND_SHERWOOD true - -#define DECODE_RC5 true -#define SEND_RC5 true - -#define DECODE_RC6 true -#define SEND_RC6 true - -#define DECODE_RCMM true -#define SEND_RCMM true - -#define DECODE_SONY true -#define SEND_SONY true - -#define DECODE_PANASONIC true -#define SEND_PANASONIC true - -#define DECODE_JVC true -#define SEND_JVC true - -#define DECODE_SAMSUNG true -#define SEND_SAMSUNG true - -#define DECODE_WHYNTER true -#define SEND_WHYNTER true - -#define DECODE_AIWA_RC_T501 true -#define SEND_AIWA_RC_T501 true - -#define DECODE_LG true -#define SEND_LG true - -#define DECODE_SANYO true -#define SEND_SANYO true - -#define DECODE_MITSUBISHI true -#define SEND_MITSUBISHI true - -#define DECODE_DISH true -#define SEND_DISH true - -#define DECODE_SHARP true -#define SEND_SHARP true - -#define DECODE_DENON true -#define SEND_DENON true - -#define DECODE_KELVINATOR false // Not written. -#define SEND_KELVINATOR true - -#define DECODE_MITSUBISHI_AC false // Not written. -#define SEND_MITSUBISHI_AC true - -#define DECODE_FUJITSU_AC false // Not written. -#define SEND_FUJITSU_AC true - -#define DECODE_DAIKIN false // Not finished. -#define SEND_DAIKIN true - -#define DECODE_COOLIX true -#define SEND_COOLIX true - -#define DECODE_GLOBALCACHE false // Not written. -#define SEND_GLOBALCACHE true - -#define DECODE_GREE false // Not written. -#define SEND_GREE true - -#define DECODE_PRONTO false // Not written. -#define SEND_PRONTO true - -#define DECODE_ARGO false // Not written. -#define SEND_ARGO true - -#define DECODE_TROTEC false // Not implemented. -#define SEND_TROTEC true - -#define DECODE_NIKAI true -#define SEND_NIKAI true -*/ - -// Tasmota supported protocols (less protocols is less code size) -#define DECODE_NEC true -#define SEND_NEC true - -#define DECODE_SHERWOOD false // Doesn't exist. Actually is DECODE_NEC -#define SEND_SHERWOOD false - -#define DECODE_RC5 true -#define SEND_RC5 true - -#define DECODE_RC6 true -#define SEND_RC6 true - -#define DECODE_RCMM false -#define SEND_RCMM false - -#define DECODE_SONY true -#define SEND_SONY true - -#define DECODE_PANASONIC true -#define SEND_PANASONIC true - -#define DECODE_JVC true -#define SEND_JVC true - -#define DECODE_SAMSUNG true -#define SEND_SAMSUNG true - -#define DECODE_WHYNTER false -#define SEND_WHYNTER false - -#define DECODE_AIWA_RC_T501 false -#define SEND_AIWA_RC_T501 false - -#define DECODE_LG true -#define SEND_LG true - -#define DECODE_SANYO false -#define SEND_SANYO false - -#define DECODE_MITSUBISHI false -#define SEND_MITSUBISHI false - -#define DECODE_DISH false -#define SEND_DISH true - -#define DECODE_SHARP false -#define SEND_SHARP false - -#define DECODE_DENON false -#define SEND_DENON false - -#define DECODE_KELVINATOR false // Not written. -#define SEND_KELVINATOR false - -#define DECODE_MITSUBISHI_AC false // Not written. -#define SEND_MITSUBISHI_AC true - -#define DECODE_FUJITSU_AC false // Not written. -#define SEND_FUJITSU_AC true - -#define DECODE_DAIKIN false // Not finished. -#define SEND_DAIKIN false - -#define DECODE_COOLIX false -#define SEND_COOLIX false - -#define DECODE_GLOBALCACHE false // Not written. -#define SEND_GLOBALCACHE false - -#define DECODE_GREE false // Not written. -#define SEND_GREE false - -#define DECODE_PRONTO false // Not written. -#define SEND_PRONTO false - -#define DECODE_ARGO false // Not written. -#define SEND_ARGO false - -#define DECODE_TROTEC false // Not implemented. -#define SEND_TROTEC false - -#define DECODE_NIKAI false -#define SEND_NIKAI false - -/* - * Always add to the end of the list and should never remove entries - * or change order. Projects may save the type number for later usage - * so numbering should always stay the same. - */ -enum decode_type_t { - UNKNOWN = -1, - UNUSED = 0, - RC5, - RC6, - NEC, - SONY, - PANASONIC, - JVC, - SAMSUNG, - WHYNTER, - AIWA_RC_T501, - LG, - SANYO, - MITSUBISHI, - DISH, - SHARP, - COOLIX, - DAIKIN, - DENON, - KELVINATOR, - SHERWOOD, - MITSUBISHI_AC, - RCMM, - SANYO_LC7461, - RC5X, - GREE, - PRONTO, // Technically not a protocol, but an encoding. - NEC_LIKE, - ARGO, - TROTEC, - NIKAI, - RAW, // Technically not a protocol, but an encoding. - GLOBALCACHE // Technically not a protocol, but an encoding. -}; - -// Message lengths & required repeat values -#define AIWA_RC_T501_BITS 15U -#define AIWA_RC_T501_MIN_REPEAT 1U -#define COOLIX_BITS 24U -#define DAIKIN_BITS 99U -#define DAIKIN_COMMAND_LENGTH 27U -#define DENON_BITS SHARP_BITS -#define DENON_48_BITS PANASONIC_BITS -#define DENON_LEGACY_BITS 14U -#define DISH_BITS 16U -#define DISH_MIN_REPEAT 3U -#define GREE_STATE_LENGTH 8U -#define GREE_BITS (GREE_STATE_LENGTH * 8) -#define JVC_BITS 16U -#define KELVINATOR_STATE_LENGTH 16U -#define LG_BITS 28U -#define LG32_BITS 32U -#define MITSUBISHI_BITS 16U -// TODO(anyone): Verify that the Mitsubishi repeat is really needed. -#define MITSUBISHI_MIN_REPEAT 1U // Based on marcosamarinho's code. -#define MITSUBISHI_AC_STATE_LENGTH 18U -#define MITSUBISHI_AC_MIN_REPEAT 1U -#define FUJITSU_AC_MIN_REPEAT 0U -#define NEC_BITS 32U -#define PANASONIC_BITS 48U -#define PANASONIC_MANUFACTURER 0x4004ULL -#define PRONTO_MIN_LENGTH 6U -#define RC5_RAW_BITS 14U -#define RC5_BITS RC5_RAW_BITS - 2U -#define RC5X_BITS RC5_RAW_BITS - 1U -#define RC6_MODE0_BITS 20U // Excludes the 'start' bit. -#define RC6_36_BITS 36U // Excludes the 'start' bit. -#define RCMM_BITS 24U -#define SAMSUNG_BITS 32U -#define SANYO_SA8650B_BITS 12U -#define SANYO_LC7461_ADDRESS_BITS 13U -#define SANYO_LC7461_COMMAND_BITS 8U -#define SANYO_LC7461_BITS ((SANYO_LC7461_ADDRESS_BITS + \ - SANYO_LC7461_COMMAND_BITS) * 2) -#define SHARP_ADDRESS_BITS 5U -#define SHARP_COMMAND_BITS 8U -#define SHARP_BITS (SHARP_ADDRESS_BITS + SHARP_COMMAND_BITS + 2) // 15U -#define SHERWOOD_BITS NEC_BITS -#define SHERWOOD_MIN_REPEAT 1U -#define SONY_12_BITS 12U -#define SONY_15_BITS 15U -#define SONY_20_BITS 20U -#define SONY_MIN_BITS SONY_12_BITS -#define SONY_MIN_REPEAT 2U -#define TROTEC_COMMAND_LENGTH 9U -#define WHYNTER_BITS 32U -#define ARGO_COMMAND_LENGTH 12U -#define NIKAI_BITS 24U - -// Turn on Debugging information by uncommenting the following line. -// #define DEBUG 1 - -#ifdef DEBUG -#ifdef UNIT_TEST -#define DPRINT(x) do { std::cout << x; } while (0) -#define DPRINTLN(x) do { std::cout << x << std::endl; } while (0) -#endif // UNIT_TEST -#ifdef ARDUINO -#define DPRINT(x) do { Serial.print(x); } while (0) -#define DPRINTLN(x) do { Serial.println(x); } while (0) -#endif // ARDUINO -#else // DEBUG -#define DPRINT(x) -#define DPRINTLN(x) -#endif // DEBUG - -#endif // IRREMOTEESP8266_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRsend.cpp b/lib/IRremoteESP8266-2.2.1.02/src/IRsend.cpp deleted file mode 100644 index 300b1fa99..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRsend.cpp +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2015 Mark Szabo -// Copyright 2017 David Conran - -#include "IRsend.h" -#ifndef UNIT_TEST -#include -#else -#define __STDC_LIMIT_MACROS -#include -#endif -#include -#ifdef UNIT_TEST -#include -#endif -#include "IRtimer.h" - -// Originally from https://github.com/shirriff/Arduino-IRremote/ -// Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for -// sending IR code on ESP8266 - -// IRsend ---------------------------------------------------------------------- -// Create an IRsend object. -// -// Args: -// IRsendPin: Which GPIO pin to use when sending an IR command. -// inverted: *DANGER* Optional flag to invert the output. (default = false) -// e.g. LED is illuminated when GPIO is LOW rather than HIGH. -// Setting this to something other than the default could -// easily destroy your IR LED if you are overdriving it. -// Unless you *REALLY* know what you are doing, don't change this. -// Returns: -// An IRsend object. -IRsend::IRsend(uint16_t IRsendPin, bool inverted) : IRpin(IRsendPin), - periodOffset(PERIOD_OFFSET) { - if (inverted) { - outputOn = LOW; - outputOff = HIGH; - } else { - outputOn = HIGH; - outputOff = LOW; - } -} - -// Enable the pin for output. -void IRsend::begin() { -#ifndef UNIT_TEST - pinMode(IRpin, OUTPUT); -#endif -} - -// Turn off the IR LED. -void IRsend::ledOff() { -#ifndef UNIT_TEST - digitalWrite(IRpin, outputOff); -#endif -} - -// Calculate the period for a given frequency. (T = 1/f) -// -// Args: -// freq: Frequency in Hz. -// use_offset: Should we use the calculated offset or not? -// Returns: -// nr. of uSeconds. -uint32_t IRsend::calcUSecPeriod(uint32_t hz, bool use_offset) { - if (hz == 0) hz = 1; // Avoid Zero hz. Divide by Zero is nasty. - uint32_t period = (1000000UL + hz/2) / hz; // The equiv of round(1000000/hz). - // Apply the offset and ensure we don't result in a <= 0 value. - if (use_offset) - return std::max((uint32_t) 1, period + periodOffset); - else - return std::max((uint32_t) 1, period); -} - -// Set the output frequency modulation and duty cycle. -// -// Args: -// freq: The freq we want to modulate at. Assumes < 1000 means kHz else Hz. -// duty: Percentage duty cycle of the LED. e.g. 25 = 25% = 1/4 on, 3/4 off. -// -// Note: -// Integer timing functions & math mean we can't do fractions of -// microseconds timing. Thus minor changes to the freq & duty values may have -// limited effect. You've been warned. -void IRsend::enableIROut(uint32_t freq, uint8_t duty) { - // Can't have more than 100% duty cycle. - duty = std::min(duty, (uint8_t) 100); - if (freq < 1000) // Were we given kHz? Supports the old call usage. - freq *= 1000; - uint32_t period = calcUSecPeriod(freq); - // Nr. of uSeconds the LED will be on per pulse. - onTimePeriod = (period * duty) / 100; - // Nr. of uSeconds the LED will be off per pulse. - offTimePeriod = period - onTimePeriod; -} - -// Modulate the IR LED for the given period (usec) and at the duty cycle set. -// -// Args: -// usec: The period of time to modulate the IR LED for, in microseconds. -// Returns: -// Nr. of pulses actually sent. -// -// Note: -// The ESP8266 has no good way to do hardware PWM, so we have to do it all -// in software. There is a horrible kludge/brilliant hack to use the second -// serial TX line to do fairly accurate hardware PWM, but it is only -// available on a single specific GPIO and only available on some modules. -// e.g. It's not available on the ESP-01 module. -// Hence, for greater compatibility & choice, we don't use that method. -// Ref: -// https://www.analysir.com/blog/2017/01/29/updated-esp8266-nodemcu-backdoor-upwm-hack-for-ir-signals/ -uint16_t IRsend::mark(uint16_t usec) { - uint16_t counter = 0; - IRtimer usecTimer = IRtimer(); - // Cache the time taken so far. This saves us calling time, and we can be - // assured that we can't have odd math problems. i.e. unsigned under/overflow. - uint32_t elapsed = usecTimer.elapsed(); - - while (elapsed < usec) { // Loop until we've met/exceeded our required time. -#ifndef UNIT_TEST - digitalWrite(IRpin, outputOn); // Turn the LED on. - // Calculate how long we should pulse on for. - // e.g. Are we to close to the end of our requested mark time (usec)? - delayMicroseconds(std::min((uint32_t) onTimePeriod, usec - elapsed)); - digitalWrite(IRpin, outputOff); // Turn the LED off. -#endif - counter++; - if (elapsed + onTimePeriod >= usec) - return counter; // LED is now off & we've passed our allotted time. - // Wait for the lesser of the rest of the duty cycle, or the time remaining. -#ifndef UNIT_TEST - delayMicroseconds(std::min(usec - elapsed - onTimePeriod, - (uint32_t) offTimePeriod)); -#endif - elapsed = usecTimer.elapsed(); // Update & recache the actual elapsed time. - } - return counter; -} - -// Turn the pin (LED) off for a given time. -// Sends an IR space for the specified number of microseconds. -// A space is no output, so the PWM output is disabled. -// -// Args: -// time: Time in microseconds (us). -void IRsend::space(uint32_t time) { - ledOff(); - if (time == 0) return; -#ifndef UNIT_TEST - // delayMicroseconds is only accurate to 16383us. - // Ref: https://www.arduino.cc/en/Reference/delayMicroseconds - if (time <= 16383) { - delayMicroseconds(time); - } else { - // Invoke a delay(), where possible, to avoid triggering the WDT. - delay(time / 1000UL); // Delay for as many whole milliseconds as we can. - // Delay the remaining sub-millisecond. - delayMicroseconds(static_cast(time % 1000UL)); - } -#endif -} - -// Calculate & set any offsets to account for execution times. -// -// Args: -// hz: The frequency to calibrate at >= 1000Hz. Default is 38000Hz. -// -// Status: ALPHA / Untested. -// -// NOTE: -// This will generate an 65535us mark() IR LED signal. -// This only needs to be called once, if at all. -void IRsend::calibrate(uint16_t hz) { - if (hz < 1000) // Were we given kHz? Supports the old call usage. - hz *= 1000; - periodOffset = 0; // Turn off any existing offset while we calibrate. - enableIROut(hz); - IRtimer usecTimer = IRtimer(); // Start a timer *just* before we do the call. - uint16_t pulses = mark(UINT16_MAX); // Generate a PWM of 65,535 us. (Max.) - uint32_t timeTaken = usecTimer.elapsed(); // Record the time it took. - // While it shouldn't be necessary, assume at least 1 pulse, to avoid a - // divide by 0 situation. - pulses = std::max(pulses, (uint16_t) 1U); - uint32_t calcPeriod = calcUSecPeriod(hz); // e.g. @38kHz it should be 26us. - // Assuming 38kHz for the example calculations: - // In a 65535us pulse, we should have 2520.5769 pulses @ 26us periods. - // e.g. 65535.0us / 26us = 2520.5769 - // This should have caused approx 2520 loops through the main loop in mark(). - // The average over that many interations should give us a reasonable - // approximation at what offset we need to use to account for instruction - // execution times. - // - // Calculate the actual period from the actual time & the actual pulses - // generated. - double_t actualPeriod = (double_t) timeTaken / (double_t) pulses; - // Store the difference between the actual time per period vs. calculated. - periodOffset = (int8_t) ((double_t) calcPeriod - actualPeriod); -} - -// Generic method for sending data that is common to most protocols. -// Will send leading or trailing 0's if the nbits is larger than the number -// of bits in data. -// -// Args: -// onemark: Nr. of usecs for the led to be pulsed for a '1' bit. -// onespace: Nr. of usecs for the led to be fully off for a '1' bit. -// zeromark: Nr. of usecs for the led to be pulsed for a '0' bit. -// zerospace: Nr. of usecs for the led to be fully off for a '0' bit. -// data: The data to be transmitted. -// nbits: Nr. of bits of data to be sent. -// MSBfirst: Flag for bit transmission order. Defaults to MSB->LSB order. -void IRsend::sendData(uint16_t onemark, uint32_t onespace, - uint16_t zeromark, uint32_t zerospace, - uint64_t data, uint16_t nbits, bool MSBfirst) { - if (nbits == 0) // If we are asked to send nothing, just return. - return; - if (MSBfirst) { // Send the MSB first. - // Send 0's until we get down to a bit size we can actually manage. - while (nbits > sizeof(data) * 8) { - mark(zeromark); - space(zerospace); - nbits--; - } - // Send the supplied data. - for (uint64_t mask = 1ULL << (nbits - 1); mask; mask >>= 1) - if (data & mask) { // Send a 1 - mark(onemark); - space(onespace); - } else { // Send a 0 - mark(zeromark); - space(zerospace); - } - } else { // Send the Least Significant Bit (LSB) first / MSB last. - for (uint16_t bit = 0; bit < nbits; bit++, data >>= 1) - if (data & 1) { // Send a 1 - mark(onemark); - space(onespace); - } else { // Send a 0 - mark(zeromark); - space(zerospace); - } - } -} - -// Send a raw IRremote message. -// -// Args: -// buf: An array of uint16_t's that has microseconds elements. -// len: Nr. of elements in the buf[] array. -// hz: Frequency to send the message at. (kHz < 1000; Hz >= 1000) -// -// Status: STABLE / Known working. -// -// Notes: -// Even elements are Mark times (On), Odd elements are Space times (Off). -// -// Ref: -// examples/IRrecvDumpV2/IRrecvDumpV2.ino -void IRsend::sendRaw(uint16_t buf[], uint16_t len, uint16_t hz) { - // Set IR carrier frequency - enableIROut(hz); - for (uint16_t i = 0; i < len; i++) { - if (i & 1) { // Odd bit. - space(buf[i]); - } else { // Even bit. - mark(buf[i]); - } - } - ledOff(); // We potentially have ended with a mark(), so turn of the LED. -} - -#ifndef UNIT_TEST -void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) { - switch (type) { -#if SEND_NEC - case NEC: sendNEC(data, nbits); break; -#endif -#if SEND_SONY - case SONY: sendSony(data, nbits); break; -#endif -#if SEND_RC5 - case RC5: sendRC5(data, nbits); break; -#endif -#if SEND_RC6 - case RC6: sendRC6(data, nbits); break; -#endif -#if SEND_DISH - case DISH: sendDISH(data, nbits); break; -#endif -#if SEND_JVC - case JVC: sendJVC(data, nbits); break; -#endif -#if SEND_SAMSUNG - case SAMSUNG: sendSAMSUNG(data, nbits); break; -#endif -#if SEND_LG - case LG: sendLG(data, nbits); break; -#endif -#if SEND_WHYNTER - case WHYNTER: sendWhynter(data, nbits); break; -#endif -#if SEND_COOLIX - case COOLIX: sendCOOLIX(data, nbits); break; -#endif -#if SEND_DENON - case DENON: sendDenon(data, nbits); break; -#endif -#if SEND_SHERWOOD - case SHERWOOD: sendSherwood(data, nbits); break; -#endif -#if SEND_RCMM - case RCMM: sendRCMM(data, nbits); break; -#endif -#if SEND_MITSUBISHI - case MITSUBISHI: sendMitsubishi(data, nbits); break; -#endif -#if SEND_SHARP - case SHARP: sendSharpRaw(data, nbits); break; -#endif -#if SEND_AIWA_RC_T501 - case AIWA_RC_T501: sendAiwaRCT501(data, nbits); break; -#endif - } -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRsend.h b/lib/IRremoteESP8266-2.2.1.02/src/IRsend.h deleted file mode 100644 index 87c1fdd9a..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRsend.h +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2015 Mark Szabo -// Copyright 2017 David Conran -#ifndef IRSEND_H_ -#define IRSEND_H_ - -#define __STDC_LIMIT_MACROS -#include -#include "IRremoteESP8266.h" - -// Originally from https://github.com/shirriff/Arduino-IRremote/ -// Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for -// sending IR code on ESP8266 - -#if TEST || UNIT_TEST -#define VIRTUAL virtual -#else -#define VIRTUAL -#endif - -// Constants -// Offset (in microseconds) to use in Period time calculations to account for -// code excution time in producing the software PWM signal. -// Value determined in https://github.com/markszabo/IRremoteESP8266/issues/62 -#define PERIOD_OFFSET -3 -#define DUTY_DEFAULT 50 - -// Classes -class IRsend { - public: - explicit IRsend(uint16_t IRsendPin, bool inverted = false); - void begin(); - void enableIROut(uint32_t freq, uint8_t duty = DUTY_DEFAULT); - VIRTUAL uint16_t mark(uint16_t usec); - VIRTUAL void space(uint32_t usec); - void calibrate(uint16_t hz = 38000U); - void sendRaw(uint16_t buf[], uint16_t len, uint16_t hz); - void sendData(uint16_t onemark, uint32_t onespace, uint16_t zeromark, - uint32_t zerospace, uint64_t data, uint16_t nbits, - bool MSBfirst = true); - void send(uint16_t type, uint64_t data, uint16_t nbits); -#if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO) - void sendNEC(uint64_t data, uint16_t nbits = NEC_BITS, uint16_t repeat = 0); - uint32_t encodeNEC(uint16_t address, uint16_t command); -#endif -#if SEND_SONY - // sendSony() should typically be called with repeat=2 as Sony devices - // expect the code to be sent at least 3 times. (code + 2 repeats = 3 codes) - // Legacy use of this procedure was to only send a single code so call it with - // repeat=0 for backward compatibility. As of v2.0 it defaults to sending - // a Sony command that will be accepted be a device. - void sendSony(uint64_t data, uint16_t nbits = SONY_20_BITS, - uint16_t repeat = SONY_MIN_REPEAT); - uint32_t encodeSony(uint16_t nbits, uint16_t command, uint16_t address, - uint16_t extended = 0); -#endif -#if SEND_SHERWOOD - void sendSherwood(uint64_t data, uint16_t nbits = SHERWOOD_BITS, - uint16_t repeat = SHERWOOD_MIN_REPEAT); -#endif -#if SEND_SAMSUNG - void sendSAMSUNG(uint64_t data, uint16_t nbits = SAMSUNG_BITS, - uint16_t repeat = 0); - uint32_t encodeSAMSUNG(uint8_t customer, uint8_t command); -#endif -#if SEND_LG - void sendLG(uint64_t data, uint16_t nbits = LG_BITS, uint16_t repeat = 0); - uint32_t encodeLG(uint16_t address, uint16_t command); -#endif -#if (SEND_SHARP || SEND_DENON) - uint32_t encodeSharp(uint16_t address, uint16_t command, - uint16_t expansion = 1, uint16_t check = 0, - bool MSBfirst = false); - void sendSharp(uint16_t address, uint16_t command, - uint16_t nbits = SHARP_BITS, uint16_t repeat = 0); - void sendSharpRaw(uint64_t data, uint16_t nbits = SHARP_BITS, - uint16_t repeat = 0); -#endif -#if SEND_JVC - void sendJVC(uint64_t data, uint16_t nbits = JVC_BITS, uint16_t repeat = 0); - uint16_t encodeJVC(uint8_t address, uint8_t command); -#endif -#if SEND_DENON - void sendDenon(uint64_t data, uint16_t nbits = DENON_BITS, - uint16_t repeat = 0); -#endif -#if SEND_SANYO - uint64_t encodeSanyoLC7461(uint16_t address, uint8_t command); - void sendSanyoLC7461(uint64_t data, uint16_t nbits = SANYO_LC7461_BITS, - uint16_t repeat = 0); -#endif -#if SEND_DISH - // sendDISH() should typically be called with repeat=3 as DISH devices - // expect the code to be sent at least 4 times. (code + 3 repeats = 4 codes) - // Legacy use of this procedure was only to send a single code - // so use repeat=0 for backward compatibility. - void sendDISH(uint64_t data, uint16_t nbits = DISH_BITS, - uint16_t repeat = DISH_MIN_REPEAT); -#endif -#if (SEND_PANASONIC || SEND_DENON) - void sendPanasonic64(uint64_t data, uint16_t nbits = PANASONIC_BITS, - uint16_t repeat = 0); - void sendPanasonic(uint16_t address, uint32_t data, - uint16_t nbits = PANASONIC_BITS, uint16_t repeat = 0); - uint64_t encodePanasonic(uint16_t manufacturer, uint8_t device, - uint8_t subdevice, uint8_t function); -#endif -#if SEND_RC5 - void sendRC5(uint64_t data, uint16_t nbits = RC5X_BITS, uint16_t repeat = 0); - uint16_t encodeRC5(uint8_t address, uint8_t command, - bool key_released = false); - uint16_t encodeRC5X(uint8_t address, uint8_t command, - bool key_released = false); - uint64_t toggleRC5(uint64_t data); -#endif -#if SEND_RC6 - void sendRC6(uint64_t data, uint16_t nbits = RC6_MODE0_BITS, - uint16_t repeat = 0); - uint64_t encodeRC6(uint32_t address, uint8_t command, - uint16_t mode = RC6_MODE0_BITS); - uint64_t toggleRC6(uint64_t data, uint16_t nbits = RC6_MODE0_BITS); -#endif -#if SEND_RCMM - void sendRCMM(uint64_t data, uint16_t nbits = RCMM_BITS, uint16_t repeat = 0); -#endif -#if SEND_COOLIX - void sendCOOLIX(uint64_t data, uint16_t nbits = COOLIX_BITS, - uint16_t repeat = 0); -#endif -#if SEND_WHYNTER - void sendWhynter(uint64_t data, uint16_t nbits = WHYNTER_BITS, - uint16_t repeat = 0); -#endif -#if SEND_MITSUBISHI - void sendMitsubishi(uint64_t data, uint16_t nbits = MITSUBISHI_BITS, - uint16_t repeat = MITSUBISHI_MIN_REPEAT); -#endif -#if SEND_MITSUBISHI_AC - void sendMitsubishiAC(unsigned char data[], - uint16_t nbytes = MITSUBISHI_AC_STATE_LENGTH, - uint16_t repeat = MITSUBISHI_AC_MIN_REPEAT); -#endif -#if SEND_FUJITSU_AC - void sendFujitsuAC(unsigned char data[], - uint16_t nbytes, - uint16_t repeat = FUJITSU_AC_MIN_REPEAT); -#endif -#if SEND_GLOBALCACHE - void sendGC(uint16_t buf[], uint16_t len); -#endif -#if SEND_KELVINATOR - void sendKelvinator(unsigned char data[], - uint16_t nbytes = KELVINATOR_STATE_LENGTH, - uint16_t repeat = 0); -#endif -#if SEND_DAIKIN - void sendDaikin(unsigned char data[], - uint16_t nbytes = DAIKIN_COMMAND_LENGTH, - uint16_t repeat = 0); -#endif -#if SEND_AIWA_RC_T501 - void sendAiwaRCT501(uint64_t data, uint16_t nbits = AIWA_RC_T501_BITS, - uint16_t repeat = AIWA_RC_T501_MIN_REPEAT); -#endif -#if SEND_GREE - void sendGree(uint64_t data, uint16_t nbits = GREE_BITS, uint16_t repeat = 0); - void sendGree(uint8_t data[], uint16_t nbytes = GREE_STATE_LENGTH, - uint16_t repeat = 0); -#endif -#if SEND_PRONTO - void sendPronto(uint16_t data[], uint16_t len, uint16_t repeat = 0); -#endif -#if SEND_ARGO - void sendArgo(unsigned char data[], - uint16_t nbytes = ARGO_COMMAND_LENGTH, - uint16_t repeat = 0); -#endif -#if SEND_TROTEC - void sendTrotec(unsigned char data[], - uint16_t nbytes = TROTEC_COMMAND_LENGTH, - uint16_t repeat = 0); -#endif -#if SEND_NIKAI - void sendNikai(uint64_t data, uint16_t nbits = NIKAI_BITS, - uint16_t repeat = 0); -#endif - - protected: -#ifdef UNIT_TEST -#ifndef HIGH -#define HIGH 0x1 -#endif -#ifndef LOW -#define LOW 0x0 -#endif -#endif // UNIT_TEST - uint8_t outputOn; - uint8_t outputOff; - - private: - uint16_t onTimePeriod; - uint16_t offTimePeriod; - uint16_t IRpin; - int8_t periodOffset; - void ledOff(); - uint32_t calcUSecPeriod(uint32_t hz, bool use_offset = true); -}; - -#endif // IRSEND_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp b/lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp deleted file mode 100644 index 22b4bb3b7..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRutils.h" -#ifndef UNIT_TEST -#include -#endif - -#define __STDC_LIMIT_MACROS -#include -#include -#ifndef ARDUINO -#include -#endif -#include "IRrecv.h" - -// Reverse the order of the requested least significant nr. of bits. -// Args: -// input: Bit pattern/integer to reverse. -// nbits: Nr. of bits to reverse. -// Returns: -// The reversed bit pattern. -uint64_t reverseBits(uint64_t input, uint16_t nbits) { - if (nbits <= 1) - return input; // Reversing <= 1 bits makes no change at all. - // Cap the nr. of bits to rotate to the max nr. of bits in the input. - nbits = std::min(nbits, (uint16_t) (sizeof(input) * 8)); - uint64_t output = 0; - for (uint16_t i = 0; i < nbits; i++) { - output <<= 1; - output |= (input & 1); - input >>= 1; - } - // Merge any remaining unreversed bits back to the top of the reversed bits. - return (input << nbits) | output; -} - -// Convert a uint64_t (unsigned long long) to a string. -// Arduino String/toInt/Serial.print() can't handle printing 64 bit values. -// -// Args: -// input: The value to print -// base: The output base. -// Returns: -// A string representation of the integer. -// Note: Based on Arduino's Print::printNumber() -#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. -String uint64ToString(uint64_t input, uint8_t base) { - String result = ""; -#else -std::string uint64ToString(uint64_t input, uint8_t base) { - std::string result = ""; -#endif - // prevent issues if called with base <= 1 - if (base < 2) base = 10; - // Check we have a base that we can actually print. - // i.e. [0-9A-Z] == 36 - if (base > 36) base = 10; - - do { - char c = input % base; - input /= base; - - if (c < 10) - c +='0'; - else - c += 'A' - 10; - result = c + result; - } while (input); - return result; -} - -#ifdef ARDUINO -// Print a uint64_t/unsigned long long to the Serial port -// Serial.print() can't handle printing long longs. (uint64_t) -// -// Args: -// input: The value to print -// base: The output base. -void serialPrintUint64(uint64_t input, uint8_t base) { - Serial.print(uint64ToString(input, base)); -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRutils.h b/lib/IRremoteESP8266-2.2.1.02/src/IRutils.h deleted file mode 100644 index eb3f1d8ee..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRutils.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef IRUTILS_H_ -#define IRUTILS_H_ - -// Copyright 2017 David Conran - -#ifndef UNIT_TEST -#include -#endif -#define __STDC_LIMIT_MACROS -#include -#ifndef ARDUINO -#include -#endif - -uint64_t reverseBits(uint64_t input, uint16_t nbits); -#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. -String uint64ToString(uint64_t input, uint8_t base = 10); -#else -std::string uint64ToString(uint64_t input, uint8_t base = 10); -#endif -void serialPrintUint64(uint64_t input, uint8_t base = 10); - -#endif // IRUTILS_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Coolix.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Coolix.cpp deleted file mode 100644 index f664d6ad7..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Coolix.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright bakrus -// Copyright 2017 David Conran - -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// CCCCC OOOOO OOOOO LL IIIII XX XX -// CC C OO OO OO OO LL III XX XX -// CC OO OO OO OO LL III XXXX -// CC C OO OO OO OO LL III XX XX -// CCCCC OOOO0 OOOO0 LLLLLLL IIIII XX XX - -// Coolix A/C / heatpump added by (send) bakrus & (decode) crankyoldgit - -// Constants -// Pulse parms are *50-100 for the Mark and *50+100 for the space -// First MARK is the one after the long gap -// pulse parameters in usec -#define COOLIX_TICK 560U // Approximately 21 cycles at 38kHz -#define COOLIX_BIT_MARK_TICKS 1U -#define COOLIX_BIT_MARK (COOLIX_BIT_MARK_TICKS * COOLIX_TICK) -#define COOLIX_ONE_SPACE_TICKS 3U -#define COOLIX_ONE_SPACE (COOLIX_ONE_SPACE_TICKS * COOLIX_TICK) -#define COOLIX_ZERO_SPACE_TICKS 1U -#define COOLIX_ZERO_SPACE (COOLIX_ZERO_SPACE_TICKS * COOLIX_TICK) -#define COOLIX_HDR_MARK_TICKS 8U -#define COOLIX_HDR_MARK (COOLIX_HDR_MARK_TICKS * COOLIX_TICK) -#define COOLIX_HDR_SPACE_TICKS 8U -#define COOLIX_HDR_SPACE (COOLIX_HDR_SPACE_TICKS * COOLIX_TICK) -#define COOLIX_MIN_GAP_TICKS (COOLIX_HDR_MARK_TICKS + \ - COOLIX_ZERO_SPACE_TICKS) -#define COOLIX_MIN_GAP (COOLIX_MIN_GAP_TICKS * COOLIX_TICK) - -#if SEND_COOLIX -// Send a Coolix message -// -// Args: -// data: Contents of the message to be sent. -// nbits: Nr. of bits of data to be sent. Typically COOLIX_BITS. -// repeat: Nr. of additional times the message is to be sent. -// -// Status: BETA / Probably works. -// -// Ref: -// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_COOLIX.cpp -// TODO(anyone): Verify repeat functionality against a real unit. -void IRsend::sendCOOLIX(uint64_t data, uint16_t nbits, uint16_t repeat) { - if (nbits % 8 != 0) - return; // nbits is required to be a multiple of 8. - - // Set IR carrier frequency - enableIROut(38); - - for (uint16_t r = 0; r <= repeat; r++) { - // Header - mark(COOLIX_HDR_MARK); - space(COOLIX_HDR_SPACE); - - // Data - // Break data into byte segments, starting at the Most Significant - // Byte. Each byte then being sent normal, then followed inverted. - for (uint16_t i = 8; i <= nbits; i += 8) { - // Grab a bytes worth of data. - uint8_t segment = (data >> (nbits - i)) & 0xFF; - // Normal - sendData(COOLIX_BIT_MARK, COOLIX_ONE_SPACE, - COOLIX_BIT_MARK, COOLIX_ZERO_SPACE, - segment, 8, true); - // Inverted. - sendData(COOLIX_BIT_MARK, COOLIX_ONE_SPACE, - COOLIX_BIT_MARK, COOLIX_ZERO_SPACE, - segment ^ 0xFF, 8, true); - } - - // Footer - mark(COOLIX_BIT_MARK); - space(COOLIX_MIN_GAP); // Pause before repeating - } -} -#endif - -#if DECODE_COOLIX -// Decode the supplied Coolix message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: The number of data bits to expect. Typically COOLIX_BITS. -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA / Probably working. -bool IRrecv::decodeCOOLIX(decode_results *results, uint16_t nbits, - bool strict) { - // The protocol sends the data normal + inverted, alternating on - // each byte. Hence twice the number of expected data bits. - if (results->rawlen < 2 * 2 * nbits + HEADER + FOOTER - 1) - return false; // Can't possibly be a valid COOLIX message. - if (strict && nbits != COOLIX_BITS) - return false; // Not strictly an COOLIX message. - if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. - return false; - - uint64_t data = 0; - uint64_t inverted = 0; - uint16_t offset = OFFSET_START; - - if (nbits > sizeof(data) * 8) - return false; // We can't possibly capture a Coolix packet that big. - - // Header - if (!matchMark(results->rawbuf[offset], COOLIX_HDR_MARK)) return false; - // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / COOLIX_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], COOLIX_HDR_SPACE)) return false; - // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / - COOLIX_HDR_SPACE_TICKS; - - // Data - // Twice as many bits as there are normal plus inverted bits. - for (uint16_t i = 0; i < nbits * 2; i++, offset++) { - bool flip = (i / 8) % 2; - if (!matchMark(results->rawbuf[offset++], COOLIX_BIT_MARK_TICKS * m_tick)) - return false; - if (matchSpace(results->rawbuf[offset], COOLIX_ONE_SPACE_TICKS * s_tick)) { - if (flip) - inverted = (inverted << 1) | 1; - else - data = (data << 1) | 1; - } else if (matchSpace(results->rawbuf[offset], - COOLIX_ZERO_SPACE_TICKS * s_tick)) { - if (flip) - inverted <<= 1; - else - data <<= 1; - } else { - return false; - } - } - - // Footer - if (!matchMark(results->rawbuf[offset++], COOLIX_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], COOLIX_MIN_GAP_TICKS * s_tick)) - return false; - - // Compliance - uint64_t orig = data; // Save a copy of the data. - if (strict) { - for (uint16_t i = 0; i < nbits; i += 8, data >>= 8, inverted >>= 8) - if ((data & 0xFF) != ((inverted & 0xFF) ^ 0xFF)) - return false; - } - - // Success - results->decode_type = COOLIX; - results->bits = nbits; - results->value = orig; - results->address = 0; - results->command = 0; - return true; -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.cpp deleted file mode 100644 index f57b67608..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* -An Arduino sketch to emulate IR Daikin ARC433** remote control unit -Read more at: -http://harizanov.com/2012/02/control-daikin-air-conditioner-over-the-internet/ - -Copyright 2016 sillyfrog -*/ - -#include "ir_Daikin.h" -#include -#include "IRremoteESP8266.h" -#include "IRutils.h" - -// DDDDD AAA IIIII KK KK IIIII NN NN -// DD DD AAAAA III KK KK III NNN NN -// DD DD AA AA III KKKK III NN N NN -// DD DD AAAAAAA III KK KK III NN NNN -// DDDDDD AA AA IIIII KK KK IIIII NN NN - -// Constants -// Ref: -// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote -#define DAIKIN_HDR_MARK 3650U // DAIKIN_ZERO_MARK * 8 -#define DAIKIN_HDR_SPACE 1623U // DAIKIN_ZERO_MARK * 4 -#define DAIKIN_ONE_SPACE 1280U -#define DAIKIN_ONE_MARK 428U -#define DAIKIN_ZERO_MARK 428U -#define DAIKIN_ZERO_SPACE 428U -#define DAIKIN_GAP 29000U - -#if SEND_DAIKIN -// Send a Daikin A/C message. -// -// Args: -// data: An array of DAIKIN_COMMAND_LENGTH bytes containing the IR command. -// -// Status: STABLE -// -// Ref: -// IRDaikinESP.cpp -// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote -void IRsend::sendDaikin(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - if (nbytes < DAIKIN_COMMAND_LENGTH) - return; // Not enough bytes to send a proper message. - // Set IR carrier frequency - enableIROut(38); - for (uint16_t r = 0; r <= repeat; r++) { - // Header #1 - mark(DAIKIN_HDR_MARK); - space(DAIKIN_HDR_SPACE); - // Data #1 - for (uint16_t i = 0; i < 8 && i < nbytes; i++) - sendData(DAIKIN_ONE_MARK, DAIKIN_ONE_SPACE, DAIKIN_ZERO_MARK, - DAIKIN_ZERO_SPACE, data[i], 8, false); - // Footer #1 - mark(DAIKIN_ONE_MARK); - space(DAIKIN_ZERO_SPACE + DAIKIN_GAP); - - // Header #2 - mark(DAIKIN_HDR_MARK); - space(DAIKIN_HDR_SPACE); - // Data #2 - for (uint16_t i = 8; i < nbytes; i++) - sendData(DAIKIN_ONE_MARK, DAIKIN_ONE_SPACE, DAIKIN_ZERO_MARK, - DAIKIN_ZERO_SPACE, data[i], 8, false); - // Footer #2 - mark(DAIKIN_ONE_MARK); - space(DAIKIN_ZERO_SPACE + DAIKIN_GAP); - } -} - -IRDaikinESP::IRDaikinESP(uint16_t pin) : _irsend(pin) { - stateReset(); -} - -void IRDaikinESP::begin() { - _irsend.begin(); -} - -void IRDaikinESP::send() { - _irsend.sendDaikin(daikin); -} - -void IRDaikinESP::checksum() { - uint8_t sum = 0; - uint8_t i; - - for (i = 0; i <= 6; i++) - sum += daikin[i]; - - daikin[7] = sum & 0xFF; - sum = 0; - for (i = 8; i <= 25; i++) - sum += daikin[i]; - daikin[26] = sum & 0xFF; -} - - -void IRDaikinESP::stateReset() { - for (uint8_t i = 4; i < DAIKIN_COMMAND_LENGTH; i++) - daikin[i] = 0x0; - - daikin[0] = 0x11; - daikin[1] = 0xDA; - daikin[2] = 0x27; - daikin[3] = 0xF0; - daikin[7] = 0x20; - daikin[8] = 0x11; - daikin[9] = 0xDA; - daikin[10] = 0x27; - daikin[13] = 0x41; - daikin[14] = 0x1E; - daikin[16] = 0xB0; - daikin[23] = 0xC0; - daikin[26] = 0xE3; - checksum(); -} - -uint8_t* IRDaikinESP::getRaw() { - checksum(); // Ensure correct settings before sending. - return daikin; -} - -void IRDaikinESP::on() { - // state = ON; - daikin[13] |= 0x01; - checksum(); -} - -void IRDaikinESP::off() { - // state = OFF; - daikin[13] &= 0xFE; - checksum(); -} - -void IRDaikinESP::setPower(bool state) { - if (state) - on(); - else - off(); -} - -uint8_t IRDaikinESP::getPower() { - return daikin[13] & 0x01; -} - -// DAIKIN_SILENT or DAIKIN_POWERFUL -void IRDaikinESP::setAux(uint8_t aux) { - daikin[21] = aux; - checksum(); -} - -uint8_t IRDaikinESP::getAux() { - return daikin[21]; -} - -void IRDaikinESP::setQuiet(bool state) { - if (state) - setAux(DAIKIN_SILENT); - else - setAux(0x0); -} - -bool IRDaikinESP::getQuiet() { - return (getAux() == DAIKIN_SILENT); -} - -void IRDaikinESP::setPowerful(bool state) { - if (state) - setAux(DAIKIN_POWERFUL); - else - setAux(0x0); -} - -bool IRDaikinESP::getPowerful() { - return (getAux() == DAIKIN_POWERFUL); -} - -// Set the temp in deg C -void IRDaikinESP::setTemp(uint8_t temp) { - if (temp < DAIKIN_MIN_TEMP) - temp = DAIKIN_MIN_TEMP; - else if (temp > DAIKIN_MAX_TEMP) - temp = DAIKIN_MAX_TEMP; - daikin[14] = temp * 2; - checksum(); -} - -uint8_t IRDaikinESP::getTemp() { - return daikin[14] / 2; -} - -// Set the speed of the fan, 0-5, 0 is auto, 1-5 is the speed -void IRDaikinESP::setFan(uint8_t fan) { - // Set the fan speed bits, leave low 4 bits alone - uint8_t fanset; - daikin[16] &= 0x0F; - fan = std::min(fan, DAIKIN_FAN_MAX); - if (fan == DAIKIN_FAN_AUTO) - fanset = 0xA0; - else - fanset = 0x20 + (0x10 * fan); - daikin[16] |= fanset; - checksum(); -} - -uint8_t IRDaikinESP::getFan() { - uint8_t fan = daikin[16] >> 4; - fan -= 2; - if (fan > DAIKIN_FAN_MAX) - fan = DAIKIN_FAN_AUTO; - return fan; -} - -uint8_t IRDaikinESP::getMode() { - /* - DAIKIN_COOL - DAIKIN_HEAT - DAIKIN_FAN - DAIKIN_AUTO - DAIKIN_DRY - */ - return daikin[13] >> 4; -} - -void IRDaikinESP::setMode(uint8_t mode) { - switch (mode) { - case DAIKIN_COOL: - case DAIKIN_HEAT: - case DAIKIN_FAN: - case DAIKIN_DRY: - break; - default: - mode = DAIKIN_AUTO; - } - daikin[13] = (mode << 4) | getPower(); - checksum(); -} - -void IRDaikinESP::setSwingVertical(bool state) { - if (state) - daikin[16] |= 0x0F; - else - daikin[16] &= 0xF0; - checksum(); -} - -bool IRDaikinESP::getSwingVertical() { - return daikin[16] & 0x01; -} - -void IRDaikinESP::setSwingHorizontal(bool state) { - if (state) - daikin[17] |= 0x0F; - else - daikin[17] &= 0xF0; - checksum(); -} - -bool IRDaikinESP::getSwingHorizontal() { - return daikin[17] & 0x01; -} -#endif // SEND_DAIKIN - -#if DECODE_DAIKIN -// TODO(crankyoldgit): NOT WORKING. This needs to be finished. -// Decode the supplied Daikin A/C message. (NOT WORKING - DO NOT USE) -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. Typically SAMSUNG_BITS. -// strict: Flag to indicate if we strictly adhere to the specification. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: UNFINISHED / Completely not working, not even vaguely. -// -// Ref: -// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote -bool IRrecv::decodeDaikin(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER) - return false; - - // Compliance - if (strict && nbits != DAIKIN_BITS) - return false; - - uint32_t data = 0; - uint16_t offset = OFFSET_START; - - // Header - if (!matchMark(results->rawbuf[offset++], DAIKIN_HDR_MARK)) - return false; - if (!matchSpace(results->rawbuf[offset++], DAIKIN_HDR_SPACE)) - return false; - - // Data (#1) - for (uint8_t i = 0; i < sizeof(data) * 8; i++, offset++) { - if (!matchMark(results->rawbuf[offset++], DAIKIN_ONE_MARK)) - return false; - if (matchSpace(results->rawbuf[offset], DAIKIN_ONE_SPACE)) - data = (data << 1) | 1; // 1 - else if (matchSpace(results->rawbuf[offset], DAIKIN_ZERO_SPACE)) - data <<= 1; // 0 - else - return false; - } - - uint32_t number = data; // some number... - uint32_t reversed = reverseBits(number, sizeof(number) * 8) - - DPRINT("Code "); - DPRINTLN(reversed, HEX); - - // Data (#2) - for (uint8_t i = 0; i < sizeof(data) * 8; i++, offset++) { - if (!matchMark(results->rawbuf[offset++], DAIKIN_ONE_MARK)) - return false; - if (matchSpace(results->rawbuf[offset], DAIKIN_ONE_SPACE)) - data = (data << 1) | 1; // 1 - else if (matchSpace(results->rawbuf[offset], DAIKIN_ZERO_SPACE)) - data <<= 1; // 0 - else - return false; - } - - number = data; // some number... - reversed = reverseBits(number, sizeof(number) * 8) - - DPRINT("Code2 "); - DPRINTLN(reversed, HEX); - - if (!matchSpace(results->rawbuf[offset++], DAIKIN_GAP)) { - DPRINTLN("no gap"); - return false; - } - - // Success - results->bits = DAIKIN_BITS; - results->value = reversed; - results->decode_type = DAIKIN; - results->address = 0; - results->command = 0; - return true; -} -#endif // DECODE_DAIKIN diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h b/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h deleted file mode 100644 index 7172a5e27..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h +++ /dev/null @@ -1,107 +0,0 @@ -/* Copyright 2016 sillyfrog */ -#ifndef IR_DAIKIN_H_ -#define IR_DAIKIN_H_ - -#include "IRremoteESP8266.h" -#include "IRsend.h" - -// DDDDD AAA IIIII KK KK IIIII NN NN -// DD DD AAAAA III KK KK III NNN NN -// DD DD AA AA III KKKK III NN N NN -// DD DD AAAAAAA III KK KK III NN NNN -// DDDDDD AA AA IIIII KK KK IIIII NN NN - -/* - Daikin AC map - byte 7= checksum of the first part (and last byte before a 29ms pause) - byte 13=mode - b7 = 0 - b6+b5+b4 = Mode - Modes: b6+b5+b4 - 011 = Cool - 100 = Heat (temp 23) - 110 = FAN (temp not shown, but 25) - 000 = Fully Automatic (temp 25) - 010 = DRY (temp 0xc0 = 96 degrees c) - b3 = 0 - b2 = OFF timer set - b1 = ON timer set - b0 = Air Conditioner ON - byte 14=temp*2 (Temp should be between 18 - 32) - byte 16=Fan - FAN control - b7+b6+b5+b4 = Fan speed - Fan: b7+b6+b5+b4 - 0×30 = 1 bar - 0×40 = 2 bar - 0×50 = 3 bar - 0×60 = 4 bar - 0×70 = 5 bar - 0xa0 = Auto - 0xb0 = Not auto, moon + tree - b3+b2+b1+b0 = Swing control up/down - Swing control up/down: - 0000 = Swing up/down off - 1111 = Swing up/down on - byte 17 - Swing control left/right: - 0000 = Swing left/right off - 1111 = Swing left/right on - byte 21=Aux -> Powerful (bit 1), Silent (bit 5) - byte 24=Aux2 -> Intelligent eye on (bit 7) - byte 26= checksum of the second part -*/ - -// Constants -#define DAIKIN_COOL 0b011 -#define DAIKIN_HEAT 0b100 -#define DAIKIN_FAN 0b110 -#define DAIKIN_AUTO 0b000 -#define DAIKIN_DRY 0b010 -#define DAIKIN_POWERFUL 0b00000010 -#define DAIKIN_SILENT 0b00100000 -#define DAIKIN_MIN_TEMP 18U // Celsius -#define DAIKIN_MAX_TEMP 32U // Celsius -#define DAIKIN_FAN_AUTO (uint8_t) 0U -#define DAIKIN_FAN_MIN (uint8_t) 1U -#define DAIKIN_FAN_MAX (uint8_t) 5U - -#if SEND_DAIKIN -class IRDaikinESP { - public: - explicit IRDaikinESP(uint16_t pin); - - void send(); - void begin(); - void on(); - void off(); - void setPower(bool state); - uint8_t getPower(); - void setAux(uint8_t aux); - uint8_t getAux(); - void setTemp(uint8_t temp); - uint8_t getTemp(); - void setFan(uint8_t fan); - uint8_t getFan(); - uint8_t getMode(); - void setMode(uint8_t mode); - void setSwingVertical(bool state); - bool getSwingVertical(); - void setSwingHorizontal(bool state); - bool getSwingHorizontal(); - bool getQuiet(); - void setQuiet(bool state); - bool getPowerful(); - void setPowerful(bool state); - uint8_t* getRaw(); - - private: - // # of bytes per command - uint8_t daikin[DAIKIN_COMMAND_LENGTH]; - void stateReset(); - void checksum(); - IRsend _irsend; -}; -#endif - -#endif // IR_DAIKIN_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.cpp deleted file mode 100644 index adf753c0c..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.cpp +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright 2017 Jonny Graham -#include "ir_Fujitsu.h" -#include -#include "IRsend.h" - - -// Fujitsu A/C support added by Jonny Graham - - -// Fujitsu A/C -// Ref: -// These values are based on averages of measurements -#define FUJITSU_AC_HDR_MARK 3224U -#define FUJITSU_AC_HDR_SPACE 1574U -#define FUJITSU_AC_BIT_MARK 448U -#define FUJITSU_AC_ONE_SPACE 1182U -#define FUJITSU_AC_ZERO_SPACE 367U -#define FUJITSU_AC_TRL_MARK 448U -#define FUJITSU_AC_TRL_SPACE 8100U - -#if SEND_FUJITSU_AC -// Send a Fujitsu A/C message. -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (typically either -// FUJITSU_AC_STATE_LENGTH or FUJITSU_AC_STATE_LENGTH_SHORT) -// repeat: Nr. of times the message is to be repeated. -// (Default = FUJITSU_AC_MIN_REPEAT). -// -// Status: BETA / Appears to be working. -// -void IRsend::sendFujitsuAC(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - // Set IR carrier frequency - enableIROut(38); - for (uint16_t r = 0; r <= repeat; ++r) { - // Header - mark(FUJITSU_AC_HDR_MARK); - space(FUJITSU_AC_HDR_SPACE); - // Data - for (uint16_t i = 0; i < nbytes; i++) - sendData(FUJITSU_AC_BIT_MARK, FUJITSU_AC_ONE_SPACE, - FUJITSU_AC_BIT_MARK, FUJITSU_AC_ZERO_SPACE, - data[i], 8, false); - // Footer - mark(FUJITSU_AC_TRL_MARK); - space(FUJITSU_AC_TRL_SPACE); - } -} - -// Code to emulate Fujitsu A/C IR remote control unit. - -// Warning: Consider this very alpha code. Seems to work, but not validated. -// -// Equipment it seems compatible with: -// * Fujitsu ASYG30LFCA with remote AR-RAH2E -// * -// Initialise the object. -IRFujitsuAC::IRFujitsuAC(uint16_t pin) : _irsend(pin) { - stateReset(); -} - -// Reset the state of the remote to a known good state/sequence. -void IRFujitsuAC::stateReset() { - _temp = 24; - _fanSpeed = FUJITSU_AC_FAN_HIGH; - _mode = FUJITSU_AC_MODE_COOL; - _swingMode = FUJITSU_AC_SWING_BOTH; - _cmd = FUJITSU_AC_CMD_TURN_ON; -} - -// Configure the pin for output. -void IRFujitsuAC::begin() { - _irsend.begin(); -} - -// Send the current desired state to the IR LED. -void IRFujitsuAC::send() { - getRaw(); - uint8_t len = getCommandLength(); - _irsend.sendFujitsuAC(remote_state, len); -} - -uint8_t IRFujitsuAC::getCommandLength() { - if (remote_state[5] != 0xFE) - return FUJITSU_AC_STATE_LENGTH_SHORT; - else - return FUJITSU_AC_STATE_LENGTH; -} - -// Return a pointer to the internal state date of the remote. -uint8_t* IRFujitsuAC::getRaw() { - remote_state[0] = 0x14; - remote_state[1] = 0x63; - remote_state[2] = 0x00; - remote_state[3] = 0x10; - remote_state[4] = 0x10; - bool fullCmd = false; - switch (_cmd) { - case FUJITSU_AC_CMD_TURN_OFF: - remote_state[5] = 0x02; - break; - case FUJITSU_AC_CMD_STEP_HORIZ: - remote_state[5] = 0x79; - break; - case FUJITSU_AC_CMD_STEP_VERT: - remote_state[5] = 0x6C; - break; - default: - remote_state[5] = 0xFE; - fullCmd = true; - break; - } - if (fullCmd) { - remote_state[6] = 0x09; - remote_state[7] = 0x30; - uint8_t tempByte = _temp - FUJITSU_AC_MIN_TEMP; - remote_state[8] = (_cmd == FUJITSU_AC_CMD_TURN_ON) | (tempByte << 4); - remote_state[9] = _mode | 0 << 4; // timer off - remote_state[10] = _fanSpeed | _swingMode << 4; - remote_state[11] = 0; // timerOff values - remote_state[12] = 0; // timerOff/on values - remote_state[13] = 0; // timerOn values - remote_state[14] = 0x20; - // Checksum is the sum of the 8th to 16th bytes (ie remote_state[7] - // thru remote_state[15]). - // The checksum itself is stored in the 16th byte (ie remote_state[15]). - // So we sum bytes 8th-15th... - uint8_t checksum = 0; - for (uint8_t i = 7 ; i < 15; ++i) { - checksum += remote_state[i]; - } - // and then do 0 - sum and store it in 16th. - remote_state[15] = 0 - checksum; - } else { - // For the short codes, byte 7 is the inverse of byte 6 - remote_state[6] = ~remote_state[5]; - for (uint8_t i = 7; i < FUJITSU_AC_STATE_LENGTH; ++i) { - remote_state[i] = 0; - } - } - return remote_state; -} - -// Set the requested power state of the A/C to off. -void IRFujitsuAC::off() { - _cmd = FUJITSU_AC_CMD_TURN_OFF; -} - -void IRFujitsuAC::stepHoriz() { - _cmd = FUJITSU_AC_CMD_STEP_HORIZ; -} - -void IRFujitsuAC::stepVert() { - _cmd = FUJITSU_AC_CMD_STEP_VERT; -} - -// Set the requested command of the A/C. -void IRFujitsuAC::setCmd(uint8_t cmd) { - switch (cmd) { - case FUJITSU_AC_CMD_TURN_OFF: - case FUJITSU_AC_CMD_TURN_ON: - case FUJITSU_AC_CMD_STAY_ON: - case FUJITSU_AC_CMD_STEP_HORIZ: - case FUJITSU_AC_CMD_STEP_VERT: - break; - default: - cmd = FUJITSU_AC_CMD_STAY_ON; - break; - } - _cmd = cmd; -} - -uint8_t IRFujitsuAC::getCmd() { - return _cmd; -} - -// Set the temp. in deg C -void IRFujitsuAC::setTemp(uint8_t temp) { - temp = std::max((uint8_t) FUJITSU_AC_MIN_TEMP, temp); - temp = std::min((uint8_t) FUJITSU_AC_MAX_TEMP, temp); - _temp = temp; -} - -uint8_t IRFujitsuAC::getTemp() { - return _temp; -} - -// Set the speed of the fan -void IRFujitsuAC::setFanSpeed(uint8_t fanSpeed) { - if (fanSpeed > FUJITSU_AC_FAN_QUIET) - fanSpeed = FUJITSU_AC_FAN_HIGH; // Set the fan to maximum if out of range. - _fanSpeed = fanSpeed; -} -uint8_t IRFujitsuAC::getFanSpeed() { - return _fanSpeed; -} - -// Set the requested climate operation mode of the a/c unit. -void IRFujitsuAC::setMode(uint8_t mode) { - if (mode > FUJITSU_AC_MODE_HEAT) - mode = FUJITSU_AC_MODE_HEAT; // Set the mode to maximum if out of range. - _mode = mode; -} - -uint8_t IRFujitsuAC::getMode() { - return _mode; -} -// Set the requested swing operation mode of the a/c unit. -void IRFujitsuAC::setSwing(uint8_t swingMode) { - if (swingMode > FUJITSU_AC_SWING_BOTH) - swingMode = FUJITSU_AC_SWING_BOTH; // Set the mode to max if out of range - _swingMode = swingMode; -} - -uint8_t IRFujitsuAC::getSwing() { - return _swingMode; -} - -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h b/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h deleted file mode 100644 index 451a5b203..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2017 Jonny Graham -#ifndef IR_FUJITSU_H_ -#define IR_FUJITSU_H_ - -#define __STDC_LIMIT_MACROS -#include -#include "IRremoteESP8266.h" -#include "IRsend.h" - - -// FUJITSU A/C support added by Jonny Graham - -// Constants - -#define FUJITSU_AC_MODE_AUTO 0x00U -#define FUJITSU_AC_MODE_COOL 0x01U -#define FUJITSU_AC_MODE_DRY 0x02U -#define FUJITSU_AC_MODE_FAN 0x03U -#define FUJITSU_AC_MODE_HEAT 0x04U - -#define FUJITSU_AC_CMD_STAY_ON 0x00U -#define FUJITSU_AC_CMD_TURN_ON 0x01U -#define FUJITSU_AC_CMD_TURN_OFF 0x02U -#define FUJITSU_AC_CMD_STEP_HORIZ 0x79U -#define FUJITSU_AC_CMD_STEP_VERT 0x6CU - -#define FUJITSU_AC_FAN_AUTO 0x00U -#define FUJITSU_AC_FAN_HIGH 0x01U -#define FUJITSU_AC_FAN_MED 0x02U -#define FUJITSU_AC_FAN_LOW 0x03U -#define FUJITSU_AC_FAN_QUIET 0x04U - -#define FUJITSU_AC_MIN_TEMP 16U // 16C -#define FUJITSU_AC_MAX_TEMP 30U // 30C - -#define FUJITSU_AC_SWING_OFF 0x00U -#define FUJITSU_AC_SWING_VERT 0x01U -#define FUJITSU_AC_SWING_HORIZ 0x02U -#define FUJITSU_AC_SWING_BOTH 0x03U - -#define FUJITSU_AC_STATE_LENGTH 16 -#define FUJITSU_AC_STATE_LENGTH_SHORT 7 - -#if SEND_FUJITSU_AC -class IRFujitsuAC { - public: - explicit IRFujitsuAC(uint16_t pin); - - void stateReset(); - void send(); - void begin(); - void off(); - void stepHoriz(); - void stepVert(); - void setCmd(uint8_t cmd); - uint8_t getCmd(); - void setTemp(uint8_t temp); - uint8_t getTemp(); - void setFanSpeed(uint8_t fan); - uint8_t getFanSpeed(); - void setMode(uint8_t mode); - uint8_t getMode(); - void setSwing(uint8_t mode); - uint8_t getSwing(); - uint8_t* getRaw(); - - private: - uint8_t remote_state[FUJITSU_AC_STATE_LENGTH]; - uint8_t getCommandLength(); - IRsend _irsend; - uint8_t _temp; - uint8_t _fanSpeed; - uint8_t _mode; - uint8_t _swingMode; - uint8_t _cmd; -}; - -#endif - -#endif // IR_FUJITSU_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp deleted file mode 100644 index d1bc760bf..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2017 Ville Skyttä (scop) -// Copyright 2017 David Conran -// -// Gree protocol compatible heat pump carrying the "Ultimate" brand name. -// - -#include "IRremoteESP8266.h" -#include "IRsend.h" - -// GGGG RRRRRR EEEEEEE EEEEEEE -// GG GG RR RR EE EE -// GG RRRRRR EEEEE EEEEE -// GG GG RR RR EE EE -// GGGGGG RR RR EEEEEEE EEEEEEE - -// Constants -// Ref: https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.h -#define GREE_HDR_MARK 9000U -#define GREE_HDR_SPACE 4000U -#define GREE_BIT_MARK 620U -#define GREE_ONE_SPACE 1600U -#define GREE_ZERO_SPACE 540U -#define GREE_MSG_SPACE 19000U - -#if SEND_GREE -// Send a Gree Heat Pump message. -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (>=GREE_STATE_LENGTH) -// repeat: Nr. of times the message is to be repeated. (Default = 0). -// -// Status: ALPHA / Untested. -// -// Ref: -// https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp -void IRsend::sendGree(unsigned char data[], uint16_t nbytes, uint16_t repeat) { - if (nbytes < GREE_STATE_LENGTH) - return; // Not enough bytes to send a proper message. - - // Set IR carrier frequency - enableIROut(38); - - for (uint16_t r = 0; r <= repeat; r++) { - // Header #1 - mark(GREE_HDR_MARK); - space(GREE_HDR_SPACE); - - // Data #1 - uint16_t i; - for (i = 0; i < 4 && i < nbytes; i++) - sendData(GREE_BIT_MARK, GREE_ONE_SPACE, GREE_BIT_MARK, GREE_ZERO_SPACE, - data[i], 8, false); - - // Footer #1 (010) - sendData(GREE_BIT_MARK, GREE_ONE_SPACE, GREE_BIT_MARK, GREE_ZERO_SPACE, - 0b010, 3); - - // Header #2 - mark(GREE_BIT_MARK); - space(GREE_MSG_SPACE); - - // Data #2 - for (; i < nbytes; i++) - sendData(GREE_BIT_MARK, GREE_ONE_SPACE, GREE_BIT_MARK, GREE_ZERO_SPACE, - data[i], 8, false); - - // Footer #2 - mark(GREE_BIT_MARK); - space(GREE_MSG_SPACE); - } -} - -// Send a Gree Heat Pump message. -// -// Args: -// data: The raw message to be sent. -// nbits: Nr. of bits of data in the message. (Default is GREE_BITS) -// repeat: Nr. of times the message is to be repeated. (Default = 0). -// -// Status: ALPHA / Untested. -// -// Ref: -// https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp -void IRsend::sendGree(uint64_t data, uint16_t nbits, uint16_t repeat) { - if (nbits != GREE_BITS) - return; // Wrong nr. of bits to send a proper message. - // Set IR carrier frequency - enableIROut(38); - - for (uint16_t r = 0; r <= repeat; r++) { - // Header - mark(GREE_HDR_MARK); - space(GREE_HDR_SPACE); - - // Data - for (int16_t i = 8; i <= nbits; i += 8) { - sendData(GREE_BIT_MARK, GREE_ONE_SPACE, GREE_BIT_MARK, GREE_ZERO_SPACE, - (data >> (nbits - i)) & 0xFF, 8, false); - if (i == nbits / 2) { - // Send the mid-message Footer. - sendData(GREE_BIT_MARK, GREE_ONE_SPACE, GREE_BIT_MARK, GREE_ZERO_SPACE, - 0b010, 3); - mark(GREE_BIT_MARK); - space(GREE_MSG_SPACE); - } - } - // Footer - mark(GREE_BIT_MARK); - space(GREE_MSG_SPACE); - } -} -#endif // SEND_GREE diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.cpp deleted file mode 100644 index 257a32e1a..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.cpp +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2016 David Conran -// -// Code to emulate IR Kelvinator YALIF remote control unit, which should control -// at least the following Kelvinator A/C units: -// KSV26CRC, KSV26HRC, KSV35CRC, KSV35HRC, KSV53HRC, KSV62HRC, KSV70CRC, -// KSV70HRC, KSV80HRC. -// -// Note: -// * Unsupported: -// - All Sleep modes. -// - All Timer modes. -// - "I Feel" button & mode. -// - Energy Saving mode. -// - Low Heat mode. -// - Fahrenheit. - -#include "ir_Kelvinator.h" -#include - -// KK KK EEEEEEE LL VV VV IIIII NN NN AAA TTTTTTT OOOOO RRRRRR -// KK KK EE LL VV VV III NNN NN AAAAA TTT OO OO RR RR -// KKKK EEEEE LL VV VV III NN N NN AA AA TTT OO OO RRRRRR -// KK KK EE LL VV VV III NN NNN AAAAAAA TTT OO OO RR RR -// KK KK EEEEEEE LLLLLLL VVV IIIII NN NN AA AA TTT OOOO0 RR RR - -// Constants -#define KELVINATOR_HDR_MARK 8990U -#define KELVINATOR_HDR_SPACE 4490U -#define KELVINATOR_BIT_MARK 675U -#define KELVINATOR_ONE_SPACE 1560U -#define KELVINATOR_ZERO_SPACE 520U -#define KELVINATOR_GAP_SPACE 19950U -#define KELVINATOR_CMD_FOOTER 2U - -#define KELVINATOR_POWER 8U -#define KELVINATOR_MODE_MASK 0xF8U -#define KELVINATOR_FAN_OFFSET 4U -#define KELVINATOR_BASIC_FAN_MASK uint8_t(0xFFU ^ (3U << KELVINATOR_FAN_OFFSET)) -#define KELVINATOR_FAN_MASK uint8_t(0xFFU ^ (7U << KELVINATOR_FAN_OFFSET)) -#define KELVINATOR_CHECKSUM_START 10U -#define KELVINATOR_VENT_SWING_OFFSET 6U -#define KELVINATOR_VENT_SWING uint8_t(1U << KELVINATOR_VENT_SWING_OFFSET) -#define KELVINATOR_VENT_SWING_V uint8_t(1U) -#define KELVINATOR_VENT_SWING_H uint8_t(1U << 4) -#define KELVINATOR_SLEEP_1_AND_3 uint8_t(1U << 7) -#define KELVINATOR_QUIET_OFFSET 7U -#define KELVINATOR_QUIET uint8_t(1U << KELVINATOR_QUIET_OFFSET) -#define KELVINATOR_ION_FILTER_OFFSET 6U -#define KELVINATOR_ION_FILTER uint8_t(1U << KELVINATOR_ION_FILTER_OFFSET) -#define KELVINATOR_LIGHT_OFFSET 5U -#define KELVINATOR_LIGHT uint8_t(1U << KELVINATOR_LIGHT_OFFSET) -#define KELVINATOR_XFAN_OFFSET 7U -#define KELVINATOR_XFAN uint8_t(1U << KELVINATOR_XFAN_OFFSET) -#define KELVINATOR_TURBO_OFFSET 4U -#define KELVINATOR_TURBO uint8_t(1U << KELVINATOR_TURBO_OFFSET) - -#if SEND_KELVINATOR -// Send a Kelvinator A/C message. -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (>=KELVINATOR_STATE_LENGTH) -// repeat: Nr. of times the message is to be repeated. (Default = 0). -// -// Status: STABLE / Known working. -// -void IRsend::sendKelvinator(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - if (nbytes < KELVINATOR_STATE_LENGTH) - return; // Not enough bytes to send a proper message. - - // Set IR carrier frequency - enableIROut(38); - - for (uint16_t r = 0; r <= repeat; r++) { - // Header #1 - mark(KELVINATOR_HDR_MARK); - space(KELVINATOR_HDR_SPACE); - // Data (command) - // Send the first command data (4 bytes) - uint8_t i; - for (i = 0; i < 4; i++) - sendData(KELVINATOR_BIT_MARK, KELVINATOR_ONE_SPACE, KELVINATOR_BIT_MARK, - KELVINATOR_ZERO_SPACE, data[i], 8, false); - // Send Footer for the command data (3 bits (0b010)) - sendData(KELVINATOR_BIT_MARK, KELVINATOR_ONE_SPACE, KELVINATOR_BIT_MARK, - KELVINATOR_ZERO_SPACE, KELVINATOR_CMD_FOOTER, 3, false); - // Send an interdata gap. - mark(KELVINATOR_BIT_MARK); - space(KELVINATOR_GAP_SPACE); - // Data (options) - // Send the 1st option chunk of data (4 bytes). - for (; i < 8; i++) - sendData(KELVINATOR_BIT_MARK, KELVINATOR_ONE_SPACE, KELVINATOR_BIT_MARK, - KELVINATOR_ZERO_SPACE, data[i], 8, false); - // Send a double data gap to signify we are starting a new command sequence. - mark(KELVINATOR_BIT_MARK); - space(KELVINATOR_GAP_SPACE * 2); - // Header #2 - mark(KELVINATOR_HDR_MARK); - space(KELVINATOR_HDR_SPACE); - // Data (command) - // Send the 2nd command data (4 bytes). - // Basically an almost identical repeat of the earlier command data. - for (; i < 12; i++) - sendData(KELVINATOR_BIT_MARK, KELVINATOR_ONE_SPACE, KELVINATOR_BIT_MARK, - KELVINATOR_ZERO_SPACE, data[i], 8, false); - // Send Footer for the command data (3 bits (B010)) - sendData(KELVINATOR_BIT_MARK, KELVINATOR_ONE_SPACE, KELVINATOR_BIT_MARK, - KELVINATOR_ZERO_SPACE, KELVINATOR_CMD_FOOTER, 3, false); - // Send an interdata gap. - mark(KELVINATOR_BIT_MARK); - space(KELVINATOR_GAP_SPACE); - // Data (options) - // Send the 2nd option chunk of data (4 bytes). - // Unlike the commands, definitely not a repeat of the earlier option data. - for (; i < KELVINATOR_STATE_LENGTH; i++) - sendData(KELVINATOR_BIT_MARK, KELVINATOR_ONE_SPACE, KELVINATOR_BIT_MARK, - KELVINATOR_ZERO_SPACE, data[i], 8, false); - // Footer - mark(KELVINATOR_BIT_MARK); - space(KELVINATOR_GAP_SPACE * 2); - } -} - -IRKelvinatorAC::IRKelvinatorAC(uint16_t pin) : _irsend(pin) { - stateReset(); -} - -void IRKelvinatorAC::stateReset() { - for (uint8_t i = 0; i < KELVINATOR_STATE_LENGTH; i++) - remote_state[i] = 0x0; - remote_state[3] = 0x50; - remote_state[11] = 0x70; -} - -void IRKelvinatorAC::begin() { - _irsend.begin(); -} - -void IRKelvinatorAC::fixup() { - // X-Fan mode is only valid in COOL or DRY modes. - if (getMode() != KELVINATOR_COOL && getMode() != KELVINATOR_DRY) - setXFan(false); - checksum(); // Calculate the checksums -} - -void IRKelvinatorAC::send() { - fixup(); // Ensure correct settings before sending. - _irsend.sendKelvinator(remote_state); -} - -uint8_t* IRKelvinatorAC::getRaw() { - fixup(); // Ensure correct settings before sending. - return remote_state; -} - -// Many Bothans died to bring us this information. -void IRKelvinatorAC::checksum() { - // For each command + options block. - for (uint8_t offset = 0; offset < KELVINATOR_STATE_LENGTH; offset += 8) { - uint8_t sum = KELVINATOR_CHECKSUM_START; - // Sum the lower half of the first 4 bytes of this block. - for (uint8_t i = 0; i < 4; i++) - sum += (remote_state[i + offset] & 0xFU); - // then sum the upper half of the next 3 bytes. - for (uint8_t i = 4; i < 7; i++) - sum += (remote_state[i + offset] >> 4); - // Trim it down to fit into the 4 bits allowed. i.e. Mod 16. - sum &= 0xFU; - // Place it into the IR code in the top half of the 8th & 16th byte. - remote_state[7 + offset] = (sum << 4) | (remote_state[7 + offset] & 0xFU); - } -} - -void IRKelvinatorAC::on() { - remote_state[0] |= KELVINATOR_POWER; - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. -} - -void IRKelvinatorAC::off() { - remote_state[0] &= ~KELVINATOR_POWER; - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. -} - -void IRKelvinatorAC::setPower(bool state) { - if (state) - on(); - else - off(); -} - -bool IRKelvinatorAC::getPower() { - return ((remote_state[0] & KELVINATOR_POWER) != 0); -} - -// Set the temp. in deg C -void IRKelvinatorAC::setTemp(uint8_t temp) { - temp = std::max((uint8_t) KELVINATOR_MIN_TEMP, temp); - temp = std::min((uint8_t) KELVINATOR_MAX_TEMP, temp); - remote_state[1] = (remote_state[1] & 0xF0U) | (temp - KELVINATOR_MIN_TEMP); - remote_state[9] = remote_state[1]; // Duplicate to the 2nd command chunk. -} - -// Return the set temp. in deg C -uint8_t IRKelvinatorAC::getTemp() { - return ((remote_state[1] & 0xFU) + KELVINATOR_MIN_TEMP); -} - -// Set the speed of the fan, 0-5, 0 is auto, 1-5 is the speed -void IRKelvinatorAC::setFan(uint8_t fan) { - fan = std::min((uint8_t) KELVINATOR_FAN_MAX, fan); // Bounds check - - // Only change things if we need to. - if (fan != getFan()) { - // Set the basic fan values. - uint8_t fan_basic = std::min((uint8_t) KELVINATOR_BASIC_FAN_MAX, fan); - remote_state[0] = (remote_state[0] & KELVINATOR_BASIC_FAN_MASK) | - (fan_basic << KELVINATOR_FAN_OFFSET); - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. - // Set the advanced(?) fan value. - remote_state[14] = (remote_state[14] & KELVINATOR_FAN_MASK) | - (fan << KELVINATOR_FAN_OFFSET); - setTurbo(false); // Turbo mode is turned off if we change the fan settings. - } -} - -uint8_t IRKelvinatorAC::getFan() { - return ((remote_state[14] & ~KELVINATOR_FAN_MASK) >> KELVINATOR_FAN_OFFSET); -} - -uint8_t IRKelvinatorAC::getMode() { - return (remote_state[0] & ~KELVINATOR_MODE_MASK); -} - -void IRKelvinatorAC::setMode(uint8_t mode) { - // If we get an unexpected mode, default to AUTO. - if (mode > KELVINATOR_HEAT) mode = KELVINATOR_AUTO; - remote_state[0] = (remote_state[0] & KELVINATOR_MODE_MASK) | mode; - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. - if (mode == KELVINATOR_AUTO || KELVINATOR_DRY) - // When the remote is set to Auto or Dry, it defaults to 25C and doesn't - // show it. - setTemp(KELVINATOR_AUTO_TEMP); -} - -void IRKelvinatorAC::setSwingVertical(bool state) { - if (state) { - remote_state[0] |= KELVINATOR_VENT_SWING; - remote_state[4] |= KELVINATOR_VENT_SWING_V; - } else { - remote_state[4] &= ~KELVINATOR_VENT_SWING_V; - if (!getSwingHorizontal()) - remote_state[0] &= ~KELVINATOR_VENT_SWING; - } - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. -} - -bool IRKelvinatorAC::getSwingVertical() { - return ((remote_state[4] & KELVINATOR_VENT_SWING_V) != 0); -} - -void IRKelvinatorAC::setSwingHorizontal(bool state) { - if (state) { - remote_state[0] |= KELVINATOR_VENT_SWING; - remote_state[4] |= KELVINATOR_VENT_SWING_H; - } else { - remote_state[4] &= ~KELVINATOR_VENT_SWING_H; - if (!getSwingVertical()) - remote_state[0] &= ~KELVINATOR_VENT_SWING; - } - remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. -} - -bool IRKelvinatorAC::getSwingHorizontal() { - return ((remote_state[4] & KELVINATOR_VENT_SWING_H) != 0); -} - -void IRKelvinatorAC::setQuiet(bool state) { - remote_state[12] &= ~KELVINATOR_QUIET; - remote_state[12] |= (state << KELVINATOR_QUIET_OFFSET); -} - -bool IRKelvinatorAC::getQuiet() { - return ((remote_state[12] & KELVINATOR_QUIET) != 0); -} - -void IRKelvinatorAC::setIonFilter(bool state) { - remote_state[2] &= ~KELVINATOR_ION_FILTER; - remote_state[2] |= (state << KELVINATOR_ION_FILTER_OFFSET); - remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. -} - -bool IRKelvinatorAC::getIonFilter() { - return ((remote_state[2] & KELVINATOR_ION_FILTER) != 0); -} - -void IRKelvinatorAC::setLight(bool state) { - remote_state[2] &= ~KELVINATOR_LIGHT; - remote_state[2] |= (state << KELVINATOR_LIGHT_OFFSET); - remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. -} - -bool IRKelvinatorAC::getLight() { - return ((remote_state[2] & KELVINATOR_LIGHT) != 0); -} - -// Note: XFan mode is only valid in Cool or Dry mode. -void IRKelvinatorAC::setXFan(bool state) { - remote_state[2] &= ~KELVINATOR_XFAN; - remote_state[2] |= (state << KELVINATOR_XFAN_OFFSET); - remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. -} - -bool IRKelvinatorAC::getXFan() { - return ((remote_state[2] & KELVINATOR_XFAN) != 0); -} - -// Note: Turbo mode is turned off if the fan speed is changed. -void IRKelvinatorAC::setTurbo(bool state) { - remote_state[2] &= ~KELVINATOR_TURBO; - remote_state[2] |= (state << KELVINATOR_TURBO_OFFSET); - remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. -} - -bool IRKelvinatorAC::getTurbo() { - return ((remote_state[2] & KELVINATOR_TURBO) != 0); -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp deleted file mode 100644 index 716ddd205..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2015 Darryl Smith -// Copyright 2015 cheaplin -// Copyright 2017 David Conran - -#include "ir_LG.h" -#include -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// L GGGG -// L G -// L G GG -// L G G -// LLLLL GGG - -// LG decode originally added by Darryl Smith (based on the JVC protocol) -// LG send originally added by https://github.com/chaeplin - -// Constants -#define LG_TICK 50U -#define LG_HDR_MARK_TICKS 160U -#define LG_HDR_MARK (LG_HDR_MARK_TICKS * LG_TICK) -#define LG_HDR_SPACE_TICKS 80U -#define LG_HDR_SPACE (LG_HDR_SPACE_TICKS * LG_TICK) -#define LG_BIT_MARK_TICKS 11U -#define LG_BIT_MARK (LG_BIT_MARK_TICKS * LG_TICK) -#define LG_ONE_SPACE_TICKS 32U -#define LG_ONE_SPACE (LG_ONE_SPACE_TICKS * LG_TICK) -#define LG_ZERO_SPACE_TICKS 11U -#define LG_ZERO_SPACE (LG_ZERO_SPACE_TICKS * LG_TICK) -#define LG_RPT_SPACE_TICKS 45U -#define LG_RPT_SPACE (LG_RPT_SPACE_TICKS * LG_TICK) -#define LG_MIN_GAP_TICKS 795U -#define LG_MIN_GAP (LG_MIN_GAP_TICKS * LG_TICK) -#define LG_MIN_MESSAGE_LENGTH_TICKS 2161U -#define LG_MIN_MESSAGE_LENGTH (LG_MIN_MESSAGE_LENGTH_TICKS * LG_TICK) -#define LG32_HDR_MARK_TICKS 90U -#define LG32_HDR_MARK (LG32_HDR_MARK_TICKS * LG_TICK) -#define LG32_HDR_SPACE_TICKS 89U -#define LG32_HDR_SPACE (LG32_HDR_SPACE_TICKS * LG_TICK) -#define LG32_RPT_HDR_MARK_TICKS 179U -#define LG32_RPT_HDR_MARK (LG32_RPT_HDR_MARK_TICKS * LG_TICK) - -#if (SEND_LG || DECODE_LG) -// Calculate the rolling 4-bit wide checksum over all of the data. -// Args: -// data: The value to be checksum'ed. -// Returns: -// A 4-bit checksum. -uint8_t calcLGChecksum(uint16_t data) { - return(((data >> 12) + ((data >> 8) & 0xF) + ((data >> 4) & 0xF) + - (data & 0xF)) & 0xF); -} -#endif - -#if SEND_LG -// Send an LG formatted message. -// -// Args: -// data: The contents of the message you want to send. -// nbits: The bit size of the message being sent. -// Typically LG_BITS or LG32_BITS. -// repeat: The number of times you want the message to be repeated. -// -// Status: Beta / Should be working. -// -// Notes: -// LG has a separate message to indicate a repeat, like NEC does. -void IRsend::sendLG(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set IR carrier frequency - enableIROut(38); - - uint16_t repeatHeaderMark = 0; - IRtimer usecTimer = IRtimer(); - - if (nbits >= LG32_BITS) { - // LG 32bit protocol is near identical to Samsung except for repeats. - sendSAMSUNG(data, nbits, 0); // Send it as a single Samsung message. - repeatHeaderMark = LG32_RPT_HDR_MARK; - repeat++; - } else { - // LG (28-bit) protocol. - repeatHeaderMark = LG_HDR_MARK; - // Header - usecTimer.reset(); - mark(LG_HDR_MARK); - space(LG_HDR_SPACE); - // Data - sendData(LG_BIT_MARK, LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, - data, nbits, true); - // Footer - mark(LG_BIT_MARK); - space(std::max((uint32_t) (LG_MIN_MESSAGE_LENGTH - usecTimer.elapsed()), - (uint32_t) LG_MIN_GAP)); - } - - // Repeat - // Protocol has a mandatory repeat-specific code sent after every command. - for (uint16_t i = 0; i < repeat; i++) { - usecTimer.reset(); - mark(repeatHeaderMark); - space(LG_RPT_SPACE); - mark(LG_BIT_MARK); - space(std::max((uint32_t) LG_MIN_MESSAGE_LENGTH - usecTimer.elapsed(), - (uint32_t) LG_MIN_GAP)); - } -} - -// Construct a raw 28-bit LG message from the supplied address & command. -// -// Args: -// address: The address code. -// command: The command code. -// Returns: -// A raw 28-bit LG message suitable for sendLG(). -// -// Status: BETA / Should work. -// -// Notes: -// e.g. Sequence of bits = address + command + checksum. -uint32_t IRsend::encodeLG(uint16_t address, uint16_t command) { - return ((address << 20) | (command << 4) | calcLGChecksum(command)); -} -#endif - -#if DECODE_LG -// Decode the supplied LG message. -// LG protocol has a repeat code which is 4 items long. -// Even though the protocol has 28/32 bits of data, only 24/28 bits are -// distinct. -// In transmission order, the 28/32 bits are constructed as follows: -// 8/12 bits of address + 16 bits of command + 4 bits of checksum. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. -// Typically LG_BITS or LG32_BITS. -// strict: Flag to indicate if we strictly adhere to the specification. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA / Should work. -// -// Note: -// LG 32bit protocol appears near identical to the Samsung protocol. -// They possibly differ on how they repeat and initial HDR mark. - -// Ref: -// https://funembedded.wordpress.com/2014/11/08/ir-remote-control-for-lg-conditioner-using-stm32f302-mcu-on-mbed-platform/ -bool IRrecv::decodeLG(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1 && results->rawlen != 4) - return false; // Can't possibly be a valid LG message. - if (strict && nbits != LG_BITS && nbits != LG32_BITS) - return false; // Doesn't comply with expected LG protocol. - - uint64_t data = 0; - uint16_t offset = OFFSET_START; - - // Header - if (!matchMark(results->rawbuf[offset], LG_HDR_MARK) && - !matchMark(results->rawbuf[offset], LG32_HDR_MARK)) return false; - uint32_t m_tick; - if (matchMark(results->rawbuf[offset], LG_HDR_MARK)) - m_tick = results->rawbuf[offset++] * RAWTICK / LG_HDR_MARK_TICKS; - else - m_tick = results->rawbuf[offset++] * RAWTICK / LG32_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], LG_HDR_SPACE) && - !matchSpace(results->rawbuf[offset], LG32_HDR_SPACE)) return false; - uint32_t s_tick; - if (matchSpace(results->rawbuf[offset], LG_HDR_SPACE)) - s_tick = results->rawbuf[offset++] * RAWTICK / LG_HDR_SPACE_TICKS; - else - s_tick = results->rawbuf[offset++] * RAWTICK / LG32_HDR_SPACE_TICKS; - - // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - LG_BIT_MARK_TICKS * m_tick, - LG_ONE_SPACE_TICKS * s_tick, - LG_BIT_MARK_TICKS * m_tick, - LG_ZERO_SPACE_TICKS * s_tick); - if (data_result.success == false) return false; - data = data_result.data; - offset += data_result.used; - - // Footer - if (!matchMark(results->rawbuf[offset++], LG_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], LG_MIN_GAP_TICKS * s_tick)) - return false; - - // Repeat - if (nbits >= LG32_BITS) { - // If we are expecting the LG 32-bit protocol, there is always - // a repeat message. So, check for it. -#ifndef UNIT_TEST - if (!matchSpace(results->rawbuf[offset], LG_MIN_GAP_TICKS * s_tick)) -#else - if (!(matchSpace(results->rawbuf[offset], - LG_MIN_MESSAGE_LENGTH_TICKS * s_tick) || - matchSpace(results->rawbuf[offset], 65500) || - matchSpace(results->rawbuf[offset], LG_MIN_GAP_TICKS * s_tick))) -#endif // UNIT_TEST - return false; - offset++; - if (!matchMark(results->rawbuf[offset++], LG32_RPT_HDR_MARK_TICKS * m_tick)) - return false; - if (!matchSpace(results->rawbuf[offset++], LG_RPT_SPACE_TICKS * s_tick)) - return false; - if (!matchMark(results->rawbuf[offset++], LG_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], LG_MIN_GAP_TICKS * s_tick)) - return false; - } - - // Compliance - uint16_t command = (data >> 4) & 0xFFFF; // The 16 bits before the checksum. - - if (strict && (data & 0xF) != calcLGChecksum(command)) - return false; // The last 4 bits sent are the expected checksum. - - // Success - results->decode_type = LG; - results->bits = nbits; - results->value = data; - results->command = command; - results->address = data >> 20; // The bits before the command. - return true; -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.cpp deleted file mode 100644 index df8b6e1ef..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.cpp +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2017 David Conran - -#include "ir_Mitsubishi.h" -#include -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// MMMMM IIIII TTTTT SSSS U U BBBB IIIII SSSS H H IIIII -// M M M I T S U U B B I S H H I -// M M M I T SSS U U BBBB I SSS HHHHH I -// M M I T S U U B B I S H H I -// M M IIIII T SSSS UUU BBBBB IIIII SSSS H H IIIII - -// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote -// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran - -// Constants -// Mitsubishi TV -// period time is 1/33000Hz = 30.303 uSeconds (T) -// Ref: -// GlobalCache's Control Tower's Mitsubishi TV data. -// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Mitsubishi.cpp -#define MITSUBISHI_TICK 30U -#define MITSUBISHI_BIT_MARK_TICKS 10U -#define MITSUBISHI_BIT_MARK (MITSUBISHI_BIT_MARK_TICKS * \ - MITSUBISHI_TICK) -#define MITSUBISHI_ONE_SPACE_TICKS 70U -#define MITSUBISHI_ONE_SPACE (MITSUBISHI_ONE_SPACE_TICKS * \ - MITSUBISHI_TICK) -#define MITSUBISHI_ZERO_SPACE_TICKS 30U -#define MITSUBISHI_ZERO_SPACE (MITSUBISHI_ZERO_SPACE_TICKS * \ - MITSUBISHI_TICK) -#define MITSUBISHI_MIN_COMMAND_LENGTH_TICKS 1786U -#define MITSUBISHI_MIN_COMMAND_LENGTH (MITSUBISHI_MIN_COMMAND_LENGTH_TICKS * \ - MITSUBISHI_TICK) -#define MITSUBISHI_MIN_GAP_TICKS 936U -#define MITSUBISHI_MIN_GAP (MITSUBISHI_MIN_GAP_TICKS * \ - MITSUBISHI_TICK) - -// Mitsubishi A/C -// Ref: -// https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L84 -#define MITSUBISHI_AC_HDR_MARK 3400U -#define MITSUBISHI_AC_HDR_SPACE 1750U -#define MITSUBISHI_AC_BIT_MARK 450U -#define MITSUBISHI_AC_ONE_SPACE 1300U -#define MITSUBISHI_AC_ZERO_SPACE 420U -#define MITSUBISHI_AC_RPT_MARK 440U -#define MITSUBISHI_AC_RPT_SPACE 17100UL - -#if SEND_MITSUBISHI -// Send a Mitsubishi message -// -// Args: -// data: Contents of the message to be sent. -// nbits: Nr. of bits of data to be sent. Typically MITSUBISHI_BITS. -// repeat: Nr. of additional times the message is to be sent. -// -// Status: ALPHA / untested. -// -// Notes: -// This protocol appears to have no header. -// Ref: -// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Mitsubishi.cpp -// GlobalCache's Control Tower's Mitsubishi TV data. -void IRsend::sendMitsubishi(uint64_t data, uint16_t nbits, uint16_t repeat) { - enableIROut(33); // Set IR carrier frequency - IRtimer usecTimer = IRtimer(); - - for (uint16_t i = 0; i <= repeat; i++) { - usecTimer.reset(); - // No header - - // Data - sendData(MITSUBISHI_BIT_MARK, MITSUBISHI_ONE_SPACE, - MITSUBISHI_BIT_MARK, MITSUBISHI_ZERO_SPACE, - data, nbits, true); - // Footer - mark(MITSUBISHI_BIT_MARK); - space(std::max(MITSUBISHI_MIN_COMMAND_LENGTH - usecTimer.elapsed(), - MITSUBISHI_MIN_GAP)); - } -} -#endif - -#if DECODE_MITSUBISHI -// Decode the supplied Mitsubishi message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of data bits to expect. -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA / previously working. -// -// Notes: -// This protocol appears to have no header. -// -// Ref: -// GlobalCache's Control Tower's Mitsubishi TV data. -bool IRrecv::decodeMitsubishi(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + FOOTER - 1) - return false; // Shorter than shortest possibly expected. - if (strict && nbits != MITSUBISHI_BITS) - return false; // Request is out of spec. - - uint16_t offset = OFFSET_START; - uint64_t data = 0; - - // No Header - // But try to auto-calibrate off the initial mark signal. - if (!matchMark(results->rawbuf[offset], MITSUBISHI_BIT_MARK, 30)) - return false; - // Calculate how long the common tick time is based on the initial mark. - uint32_t tick = results->rawbuf[offset] * RAWTICK / MITSUBISHI_BIT_MARK_TICKS; - - // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - MITSUBISHI_BIT_MARK_TICKS * tick, - MITSUBISHI_ONE_SPACE_TICKS * tick, - MITSUBISHI_BIT_MARK_TICKS * tick, - MITSUBISHI_ZERO_SPACE_TICKS * tick); - if (data_result.success == false) return false; - data = data_result.data; - offset += data_result.used; - uint16_t actualBits = data_result.used / 2; - - // Footer - if (!matchMark(results->rawbuf[offset++], MITSUBISHI_BIT_MARK_TICKS * tick, - 30)) return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], MITSUBISHI_MIN_GAP_TICKS * tick)) - return false; - - // Compliance - if (actualBits < nbits) - return false; - if (strict && actualBits != nbits) - return false; // Not as we expected. - - // Success - results->decode_type = MITSUBISHI; - results->bits = actualBits; - results->value = data; - results->address = 0; - results->command = 0; - return true; -} -#endif - -#if SEND_MITSUBISHI_AC -// Send a Mitsubishi A/C message. -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (>=MITSUBISHI_AC_STATE_LENGTH) -// repeat: Nr. of times the message is to be repeated. -// (Default = MITSUBISHI_AC_MIN_REPEAT). -// -// Status: BETA / Appears to be working. -// -void IRsend::sendMitsubishiAC(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - if (nbytes < MITSUBISHI_AC_STATE_LENGTH) - return; // Not enough bytes to send a proper message. - - // Set IR carrier frequency - enableIROut(38); - // Mitsubishi AC remote sends the packet twice. - for (uint16_t r = 0; r <= repeat; r++) { - // Header - mark(MITSUBISHI_AC_HDR_MARK); - space(MITSUBISHI_AC_HDR_SPACE); - // Data - for (uint16_t i = 0; i < nbytes; i++) - sendData(MITSUBISHI_AC_BIT_MARK, MITSUBISHI_AC_ONE_SPACE, - MITSUBISHI_AC_BIT_MARK, MITSUBISHI_AC_ZERO_SPACE, - data[i], 8, false); - // Footer - mark(MITSUBISHI_AC_RPT_MARK); - space(MITSUBISHI_AC_RPT_SPACE); - } -} - -// Code to emulate Mitsubishi A/C IR remote control unit. -// Inspired and derived from the work done at: -// https://github.com/r45635/HVAC-IR-Control -// -// Warning: Consider this very alpha code. Seems to work, but not validated. -// -// Equipment it seems compatible with: -// * -// Initialise the object. -IRMitsubishiAC::IRMitsubishiAC(uint16_t pin) : _irsend(pin) { - stateReset(); -} - -// Reset the state of the remote to a known good state/sequence. -void IRMitsubishiAC::stateReset() { - // The state of the IR remote in IR code form. - // Known good state obtained from: - // https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L108 - // Note: Can't use the following because it requires -std=c++11 - // uint8_t known_good_state[MITSUBISHI_AC_STATE_LENGTH] = { - // 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, 0x45, 0x67, 0x00, - // 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; - remote_state[0] = 0x23; - remote_state[1] = 0xCB; - remote_state[2] = 0x26; - remote_state[3] = 0x01; - remote_state[4] = 0x00; - remote_state[5] = 0x20; - remote_state[6] = 0x08; - remote_state[7] = 0x06; - remote_state[8] = 0x30; - remote_state[9] = 0x45; - remote_state[10] = 0x67; - for (uint8_t i = 11; i < MITSUBISHI_AC_STATE_LENGTH - 1; i++) - remote_state[i] = 0; - remote_state[MITSUBISHI_AC_STATE_LENGTH - 1] = 0x1F; - checksum(); // Calculate the checksum -} - -// Configure the pin for output. -void IRMitsubishiAC::begin() { - _irsend.begin(); -} - -// Send the current desired state to the IR LED. -void IRMitsubishiAC::send() { - checksum(); // Ensure correct checksum before sending. - _irsend.sendMitsubishiAC(remote_state); -} - -// Return a pointer to the internal state date of the remote. -uint8_t* IRMitsubishiAC::getRaw() { - checksum(); - return remote_state; -} - -// Calculate the checksum for the current internal state of the remote. -void IRMitsubishiAC::checksum() { - uint8_t sum = 0; - // Checksum is simple addition of all previous bytes stored - // as a 8 bit value. - for (uint8_t i = 0; i < 17; i++) - sum += remote_state[i]; - remote_state[17] = sum & 0xFFU; -} - -// Set the requested power state of the A/C to off. -void IRMitsubishiAC::on() { - // state = ON; - remote_state[5] |= MITSUBISHI_AC_POWER; -} - -// Set the requested power state of the A/C to off. -void IRMitsubishiAC::off() { - // state = OFF; - remote_state[5] &= ~MITSUBISHI_AC_POWER; -} - -// Set the requested power state of the A/C. -void IRMitsubishiAC::setPower(bool state) { - if (state) - on(); - else - off(); -} - -// Return the requested power state of the A/C. -bool IRMitsubishiAC::getPower() { - return((remote_state[5] & MITSUBISHI_AC_POWER) != 0); -} - -// Set the temp. in deg C -void IRMitsubishiAC::setTemp(uint8_t temp) { - temp = std::max((uint8_t) MITSUBISHI_AC_MIN_TEMP, temp); - temp = std::min((uint8_t) MITSUBISHI_AC_MAX_TEMP, temp); - remote_state[7] = temp - MITSUBISHI_AC_MIN_TEMP; -} - -// Return the set temp. in deg C -uint8_t IRMitsubishiAC::getTemp() { - return(remote_state[7] + MITSUBISHI_AC_MIN_TEMP); -} - -// Set the speed of the fan, 0-6. -// 0 is auto, 1-5 is the speed, 6 is silent. -void IRMitsubishiAC::setFan(uint8_t fan) { - // Bounds check - if (fan > MITSUBISHI_AC_FAN_SILENT) - fan = MITSUBISHI_AC_FAN_MAX; // Set the fan to maximum if out of range. - if (fan == MITSUBISHI_AC_FAN_AUTO) { // Automatic is a special case. - remote_state[9] = 0b10000000 | (remote_state[9] & 0b01111000); - return; - } else if (fan >= MITSUBISHI_AC_FAN_MAX) { - fan--; // There is no spoon^H^H^Heed 5 (max), pretend it doesn't exist. - } - remote_state[9] &= 0b01111000; // Clear the previous state - remote_state[9] |= fan; -} - -// Return the requested state of the unit's fan. -uint8_t IRMitsubishiAC::getFan() { - uint8_t fan = remote_state[9] & 0b111; - if (fan == MITSUBISHI_AC_FAN_MAX) - return MITSUBISHI_AC_FAN_SILENT; - return fan; -} - -// Return the requested climate operation mode of the a/c unit. -uint8_t IRMitsubishiAC::getMode() { - return(remote_state[6]); -} - -// Set the requested climate operation mode of the a/c unit. -void IRMitsubishiAC::setMode(uint8_t mode) { - // If we get an unexpected mode, default to AUTO. - switch (mode) { - case MITSUBISHI_AC_AUTO: break; - case MITSUBISHI_AC_COOL: break; - case MITSUBISHI_AC_DRY: break; - case MITSUBISHI_AC_HEAT: break; - default: mode = MITSUBISHI_AC_AUTO; - } - remote_state[6] = mode; -} - -// Set the requested vane operation mode of the a/c unit. -void IRMitsubishiAC::setVane(uint8_t mode) { - mode = std::min(mode, (uint8_t) 0b111); // bounds check - mode |= 0b1000; - mode <<= 3; - remote_state[9] &= 0b11000111; // Clear the previous setting. - remote_state[9] |= mode; -} - -// Return the requested vane operation mode of the a/c unit. -uint8_t IRMitsubishiAC::getVane() { - return ((remote_state[9] & 0b00111000) >> 3); -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.h b/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.h deleted file mode 100644 index e9f5731aa..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2017 David Conran -#ifndef IR_MITSUBISHI_H_ -#define IR_MITSUBISHI_H_ - -#define __STDC_LIMIT_MACROS -#include -#include "IRremoteESP8266.h" -#include "IRsend.h" - -// MMMMM IIIII TTTTT SSSS U U BBBB IIIII SSSS H H IIIII -// M M M I T S U U B B I S H H I -// M M M I T SSS U U BBBB I SSS HHHHH I -// M M I T S U U B B I S H H I -// M M IIIII T SSSS UUU BBBBB IIIII SSSS H H IIIII - -// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote -// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran - -// Constants -#define MITSUBISHI_AC_AUTO 0x20U -#define MITSUBISHI_AC_COOL 0x18U -#define MITSUBISHI_AC_DRY 0x10U -#define MITSUBISHI_AC_HEAT 0x08U -#define MITSUBISHI_AC_POWER 0x20U -#define MITSUBISHI_AC_FAN_AUTO 0U -#define MITSUBISHI_AC_FAN_MAX 5U -#define MITSUBISHI_AC_FAN_REAL_MAX 4U -#define MITSUBISHI_AC_FAN_SILENT 6U -#define MITSUBISHI_AC_MIN_TEMP 16U // 16C -#define MITSUBISHI_AC_MAX_TEMP 31U // 31C -#define MITSUBISHI_AC_VANE_AUTO 0U -#define MITSUBISHI_AC_VANE_AUTO_MOVE 7U - -#if SEND_MITSUBISHI_AC -class IRMitsubishiAC { - public: - explicit IRMitsubishiAC(uint16_t pin); - - void stateReset(); - void send(); - void begin(); - void on(); - void off(); - void setPower(bool state); - bool getPower(); - void setTemp(uint8_t temp); - uint8_t getTemp(); - void setFan(uint8_t fan); - uint8_t getFan(); - void setMode(uint8_t mode); - uint8_t getMode(); - void setVane(uint8_t mode); - uint8_t getVane(); - uint8_t* getRaw(); - - private: - uint8_t remote_state[MITSUBISHI_AC_STATE_LENGTH]; - void checksum(); - IRsend _irsend; -}; - -#endif - -#endif // IR_MITSUBISHI_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp deleted file mode 100644 index e1afda4c5..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2017 David Conran - -#include -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// NN NN IIIII KK KK AAA IIIII -// NNN NN III KK KK AAAAA III -// NN N NN III KKKK AA AA III -// NN NNN III KK KK AAAAAAA III -// NN NN IIIII KK KK AA AA IIIII - -// Constants -// Ref: -// https://github.com/markszabo/IRremoteESP8266/issues/309 -#define NIKAI_TICK 500U -#define NIKAI_HDR_MARK_TICKS 8U -#define NIKAI_HDR_MARK (NIKAI_HDR_MARK_TICKS * NIKAI_TICK) -#define NIKAI_HDR_SPACE_TICKS 8U -#define NIKAI_HDR_SPACE (NIKAI_HDR_SPACE_TICKS * NIKAI_TICK) -#define NIKAI_BIT_MARK_TICKS 1U -#define NIKAI_BIT_MARK (NIKAI_BIT_MARK_TICKS * NIKAI_TICK) -#define NIKAI_ONE_SPACE_TICKS 2U -#define NIKAI_ONE_SPACE (NIKAI_ONE_SPACE_TICKS * NIKAI_TICK) -#define NIKAI_ZERO_SPACE_TICKS 4U -#define NIKAI_ZERO_SPACE (NIKAI_ZERO_SPACE_TICKS * NIKAI_TICK) -#define NIKAI_MIN_GAP_TICKS 17U -#define NIKAI_MIN_GAP (NIKAI_MIN_GAP_TICKS * NIKAI_TICK) - - -#if SEND_NIKAI -// Send a Nikai TV formatted message. -// -// Args: -// data: The message to be sent. -// nbits: The bit size of the message being sent. typically NIKAI_BITS. -// repeat: The number of times the message is to be repeated. -// -// Status: ALPHA / Untested. -// -// Ref: https://github.com/markszabo/IRremoteESP8266/issues/309 -void IRsend::sendNikai(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set 38kHz IR carrier frequency & a 1/3 (33%) duty cycle. - enableIROut(38, 33); - // We always send a message, even for repeat=0, hence '<= repeat'. - for (uint16_t i=0; i <= repeat; i++) { - // Header - mark(NIKAI_HDR_MARK); - space(NIKAI_HDR_SPACE); - // Data - sendData(NIKAI_BIT_MARK, NIKAI_ONE_SPACE, NIKAI_BIT_MARK, - NIKAI_ZERO_SPACE, data, nbits, true); - // Footer - mark(NIKAI_BIT_MARK); - space(NIKAI_MIN_GAP); - } -} -#endif - -#if DECODE_NIKAI -// Decode the supplied Nikai message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. -// Typically NIKAI_BITS. -// strict: Flag to indicate if we strictly adhere to the specification. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: ALPHA / Untested. -// -bool IRrecv::decodeNikai(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1) - return false; // Can't possibly be a valid Nikai message. - if (strict && nbits != NIKAI_BITS) - return false; // We expect Nikai to be a certain sized message. - - uint64_t data = 0; - uint16_t offset = OFFSET_START; - - // Header - if (!matchMark(results->rawbuf[offset], NIKAI_HDR_MARK)) return false; - // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / - NIKAI_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], NIKAI_HDR_SPACE)) return false; - // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / - NIKAI_HDR_SPACE_TICKS; - // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - NIKAI_BIT_MARK_TICKS * m_tick, - NIKAI_ONE_SPACE_TICKS * s_tick, - NIKAI_BIT_MARK_TICKS * m_tick, - NIKAI_ZERO_SPACE_TICKS * s_tick); - if (data_result.success == false) return false; - data = data_result.data; - offset += data_result.used; - // Footer - if (!matchMark(results->rawbuf[offset++], NIKAI_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], NIKAI_MIN_GAP_TICKS * s_tick)) - return false; - - // Compliance - - // Success - results->bits = nbits; - results->value = data; - results->decode_type = NIKAI; - results->command = 0; - results->address = 0; - return true; -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Panasonic.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Panasonic.cpp deleted file mode 100644 index fb1f12234..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Panasonic.cpp +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2015 Kristian Lauszus -// Copyright 2017 David Conran - -#include -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// PPPP AAA N N AAA SSSS OOO N N IIIII CCCC -// P P A A NN N A A S O O NN N I C -// PPPP AAAAA N N N AAAAA SSS O O N N N I C -// P A A N NN A A S O O N NN I C -// P A A N N A A SSSS OOO N N IIIII CCCC - -// Panasonic protocol originally added by Kristian Lauszus from: -// https://github.com/z3t0/Arduino-IRremote -// (Thanks to zenwheel and other people at the original blog post) - -// Constants -// Ref: -// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152 -#define PANASONIC_TICK 432U -#define PANASONIC_HDR_MARK_TICKS 8U -#define PANASONIC_HDR_MARK (PANASONIC_HDR_MARK_TICKS * PANASONIC_TICK) -#define PANASONIC_HDR_SPACE_TICKS 4U -#define PANASONIC_HDR_SPACE (PANASONIC_HDR_SPACE_TICKS * PANASONIC_TICK) -#define PANASONIC_BIT_MARK_TICKS 1U -#define PANASONIC_BIT_MARK (PANASONIC_BIT_MARK_TICKS * PANASONIC_TICK) -#define PANASONIC_ONE_SPACE_TICKS 3U -#define PANASONIC_ONE_SPACE (PANASONIC_ONE_SPACE_TICKS * PANASONIC_TICK) -#define PANASONIC_ZERO_SPACE_TICKS 1U -#define PANASONIC_ZERO_SPACE (PANASONIC_ZERO_SPACE_TICKS * PANASONIC_TICK) -#define PANASONIC_MIN_COMMAND_LENGTH_TICKS 300UL -#define PANASONIC_MIN_COMMAND_LENGTH (PANASONIC_MIN_COMMAND_LENGTH_TICKS * \ - PANASONIC_TICK) -#define PANASONIC_END_GAP 5000U // See issue #245 -#define PANASONIC_MIN_GAP_TICKS (PANASONIC_MIN_COMMAND_LENGTH_TICKS - \ - (PANASONIC_HDR_MARK_TICKS + PANASONIC_HDR_SPACE_TICKS + \ - PANASONIC_BITS * (PANASONIC_BIT_MARK_TICKS + PANASONIC_ONE_SPACE_TICKS) + \ - PANASONIC_BIT_MARK_TICKS)) -#define PANASONIC_MIN_GAP ((uint32_t)(PANASONIC_MIN_GAP_TICKS * PANASONIC_TICK)) -#if (SEND_PANASONIC || SEND_DENON) -// Send a Panasonic formatted message. -// -// Args: -// data: The message to be sent. -// nbits: The number of bits of the message to be sent. (PANASONIC_BITS). -// repeat: The number of times the command is to be repeated. -// -// Status: BETA / Should be working. -// -// Note: -// This protocol is a modified version of Kaseikyo. -void IRsend::sendPanasonic64(uint64_t data, uint16_t nbits, uint16_t repeat) { - enableIROut(36700U); // Set IR carrier frequency of 36.7kHz. - IRtimer usecTimer = IRtimer(); - - for (uint16_t i = 0; i <= repeat; i++) { - usecTimer.reset(); - // Header - mark(PANASONIC_HDR_MARK); - space(PANASONIC_HDR_SPACE); - // Data - sendData(PANASONIC_BIT_MARK, PANASONIC_ONE_SPACE, - PANASONIC_BIT_MARK, PANASONIC_ZERO_SPACE, - data, nbits, true); - // Footer - mark(PANASONIC_BIT_MARK); - space(std::max((uint32_t) PANASONIC_MIN_COMMAND_LENGTH - - usecTimer.elapsed(), - PANASONIC_MIN_GAP)); - } -} - -// Send a Panasonic formatted message. -// -// Args: -// address: The manufacturer code. -// data: The data portion to be sent. -// nbits: The number of bits of the message to be sent. (PANASONIC_BITS). -// repeat: The number of times the command is to be repeated. -// -// Status: STABLE. -// -// Note: -// This protocol is a modified version of Kaseikyo. -void IRsend::sendPanasonic(uint16_t address, uint32_t data, uint16_t nbits, - uint16_t repeat) { - sendPanasonic64(((uint64_t) address << 32) | (uint64_t) data, nbits, repeat); -} - -// Calculate the raw Panasonic data based on device, subdevice, & function. -// -// Args: -// manufacturer: A 16-bit manufacturer code. e.g. 0x4004 is Panasonic. -// device: An 8-bit code. -// subdevice: An 8-bit code. -// function: An 8-bit code. -// Returns: -// A raw uint64_t Panasonic message. -// -// Status: BETA / Should be working.. -// -// Note: -// Panasonic 48-bit protocol is a modified version of Kaseikyo. -// Ref: -// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?2615 -uint64_t IRsend::encodePanasonic(uint16_t manufacturer, - uint8_t device, - uint8_t subdevice, - uint8_t function) { - uint8_t checksum = device ^ subdevice ^ function; - return (((uint64_t) manufacturer << 32) | - ((uint64_t) device << 24) | - ((uint64_t) subdevice << 16) | - ((uint64_t) function << 8) | - checksum); -} -#endif // (SEND_PANASONIC || SEND_DENON) - -#if (DECODE_PANASONIC || DECODE_DENON) -// Decode the supplied Panasonic message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of data bits to expect. -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA / Should be working. -// Note: -// Panasonic 48-bit protocol is a modified version of Kaseikyo. -// Ref: -// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152 -// http://www.hifi-remote.com/wiki/index.php?title=Panasonic -bool IRrecv::decodePanasonic(decode_results *results, uint16_t nbits, - bool strict, uint32_t manufacturer) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1) - return false; // Not enough entries to be a Panasonic message. - if (strict && nbits != PANASONIC_BITS) - return false; // Request is out of spec. - - uint64_t data = 0; - uint16_t offset = OFFSET_START; - - // Header - if (!matchMark(results->rawbuf[offset], PANASONIC_HDR_MARK)) return false; - // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / - PANASONIC_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], PANASONIC_HDR_SPACE)) return false; - // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / - PANASONIC_HDR_SPACE_TICKS; - - // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - PANASONIC_BIT_MARK_TICKS * m_tick, - PANASONIC_ONE_SPACE_TICKS * s_tick, - PANASONIC_BIT_MARK_TICKS * m_tick, - PANASONIC_ZERO_SPACE_TICKS * s_tick); - if (data_result.success == false) return false; - data = data_result.data; - offset += data_result.used; - - // Footer - if (!match(results->rawbuf[offset++], PANASONIC_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], PANASONIC_END_GAP)) - return false; - - // Compliance - uint32_t address = data >> 32; - uint32_t command = data & 0xFFFFFFFF; - if (strict) { - if (address != manufacturer) // Verify the Manufacturer code. - return false; - // Verify the checksum. - uint8_t checksumOrig = data & 0xFF; - uint8_t checksumCalc = ((data >> 24) ^ (data >> 16) ^ (data >> 8)) & 0xFF; - if (checksumOrig != checksumCalc) - return false; - } - - // Success - results->value = data; - results->address = address; - results->command = command; - results->decode_type = PANASONIC; - results->bits = nbits; - return true; -} -#endif // (DECODE_PANASONIC || DECODE_DENON) diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Samsung.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Samsung.cpp deleted file mode 100644 index dbd94bcd4..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Samsung.cpp +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2017 David Conran - -#include -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// SSSS AAA MMM SSSS U U N N GGGG -// S A A M M M S U U NN N G -// SSS AAAAA M M M SSS U U N N N G GG -// S A A M M S U U N NN G G -// SSSS A A M M SSSS UUU N N GGG - -// Samsung originally added from https://github.com/shirriff/Arduino-IRremote/ - -// Constants -// Ref: -// http://elektrolab.wz.cz/katalog/samsung_protocol.pdf -#define SAMSUNG_TICK 560U -#define SAMSUNG_HDR_MARK_TICKS 8U -#define SAMSUNG_HDR_MARK (SAMSUNG_HDR_MARK_TICKS * SAMSUNG_TICK) -#define SAMSUNG_HDR_SPACE_TICKS 8U -#define SAMSUNG_HDR_SPACE (SAMSUNG_HDR_SPACE_TICKS * SAMSUNG_TICK) -#define SAMSUNG_BIT_MARK_TICKS 1U -#define SAMSUNG_BIT_MARK (SAMSUNG_BIT_MARK_TICKS * SAMSUNG_TICK) -#define SAMSUNG_ONE_SPACE_TICKS 3U -#define SAMSUNG_ONE_SPACE (SAMSUNG_ONE_SPACE_TICKS * SAMSUNG_TICK) -#define SAMSUNG_ZERO_SPACE_TICKS 1U -#define SAMSUNG_ZERO_SPACE (SAMSUNG_ZERO_SPACE_TICKS * SAMSUNG_TICK) -#define SAMSUNG_RPT_SPACE_TICKS 4U -#define SAMSUNG_RPT_SPACE (SAMSUNG_RPT_SPACE_TICKS * SAMSUNG_TICK) -#define SAMSUNG_MIN_MESSAGE_LENGTH_TICKS 193U -#define SAMSUNG_MIN_MESSAGE_LENGTH (SAMSUNG_MIN_MESSAGE_LENGTH_TICKS * \ - SAMSUNG_TICK) -#define SAMSUNG_MIN_GAP_TICKS (SAMSUNG_MIN_MESSAGE_LENGTH_TICKS - \ - (SAMSUNG_HDR_MARK_TICKS + SAMSUNG_HDR_SPACE_TICKS + \ - SAMSUNG_BITS * (SAMSUNG_BIT_MARK_TICKS + SAMSUNG_ONE_SPACE_TICKS) + \ - SAMSUNG_BIT_MARK_TICKS)) -#define SAMSUNG_MIN_GAP (SAMSUNG_MIN_GAP_TICKS * SAMSUNG_TICK) - - - -#if SEND_SAMSUNG -// Send a Samsung formatted message. -// Samsung has a separate message to indicate a repeat, like NEC does. -// TODO(crankyoldgit): Confirm that is actually how Samsung sends a repeat. -// The refdoc doesn't indicate it is true. -// -// Args: -// data: The message to be sent. -// nbits: The bit size of the message being sent. typically SAMSUNG_BITS. -// repeat: The number of times the message is to be repeated. -// -// Status: BETA / Should be working. -// -// Ref: http://elektrolab.wz.cz/katalog/samsung_protocol.pdf -void IRsend::sendSAMSUNG(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set 38kHz IR carrier frequency & a 1/3 (33%) duty cycle. - enableIROut(38, 33); - IRtimer usecTimer = IRtimer(); - // We always send a message, even for repeat=0, hence '<= repeat'. - for (uint16_t i=0; i <= repeat; i++) { - usecTimer.reset(); - // Header - mark(SAMSUNG_HDR_MARK); - space(SAMSUNG_HDR_SPACE); - // Data - sendData(SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, - SAMSUNG_ZERO_SPACE, data, nbits, true); - // Footer - mark(SAMSUNG_BIT_MARK); - space(std::max((uint32_t) SAMSUNG_MIN_GAP, - (uint32_t) (SAMSUNG_MIN_MESSAGE_LENGTH - - usecTimer.elapsed()))); - } -} - -// Construct a raw Samsung message from the supplied customer(address) & -// command. -// -// Args: -// customer: The customer code. (aka. Address) -// command: The command code. -// Returns: -// A raw 32-bit Samsung message suitable for sendSAMSUNG(). -// -// Status: BETA / Should be working. -uint32_t IRsend::encodeSAMSUNG(uint8_t customer, uint8_t command) { - customer = reverseBits(customer, sizeof(customer) * 8); - command = reverseBits(command, sizeof(command) * 8); - return((command ^ 0xFF) | (command << 8) | - (customer << 16) | (customer << 24)); -} -#endif - -#if DECODE_SAMSUNG -// Decode the supplied Samsung message. -// Samsung messages whilst 32 bits in size, only contain 16 bits of distinct -// data. e.g. In transmition order: -// customer_byte + customer_byte(same) + address_byte + invert(address_byte) -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. Typically SAMSUNG_BITS. -// strict: Flag to indicate if we strictly adhere to the specification. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: STABLE -// -// Note: -// LG 32bit protocol appears near identical to the Samsung protocol. -// They differ on their compliance criteria and how they repeat. -// Ref: -// http://elektrolab.wz.cz/katalog/samsung_protocol.pdf -bool IRrecv::decodeSAMSUNG(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1) - return false; // Can't possibly be a valid Samsung message. - if (strict && nbits != SAMSUNG_BITS) - return false; // We expect Samsung to be 32 bits of message. - - uint64_t data = 0; - uint16_t offset = OFFSET_START; - - // Header - if (!matchMark(results->rawbuf[offset], SAMSUNG_HDR_MARK)) return false; - // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / - SAMSUNG_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], SAMSUNG_HDR_SPACE)) return false; - // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / - SAMSUNG_HDR_SPACE_TICKS; - // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - SAMSUNG_BIT_MARK_TICKS * m_tick, - SAMSUNG_ONE_SPACE_TICKS * s_tick, - SAMSUNG_BIT_MARK_TICKS * m_tick, - SAMSUNG_ZERO_SPACE_TICKS * s_tick); - if (data_result.success == false) return false; - data = data_result.data; - offset += data_result.used; - // Footer - if (!matchMark(results->rawbuf[offset++], SAMSUNG_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], SAMSUNG_MIN_GAP_TICKS * s_tick)) - return false; - - // Compliance - - // According to the spec, the customer (address) code is the first 8 - // transmitted bits. It's then repeated. Check for that. - uint8_t address = data >> 24; - if (strict && address != ((data >> 16) & 0xFF)) - return false; - // Spec says the command code is the 3rd block of transmitted 8-bits, - // followed by the inverted command code. - uint8_t command = (data & 0xFF00) >> 8; - if (strict && command != ((data & 0xFF) ^ 0xFF)) - return false; - - // Success - results->bits = nbits; - results->value = data; - results->decode_type = SAMSUNG; - // command & address need to be reversed as they are transmitted LSB first, - results->command = reverseBits(command, sizeof(command) * 8); - results->address = reverseBits(address, sizeof(address) * 8); - return true; -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.cpp deleted file mode 100644 index ef8e9efa6..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2017 stufisher - -#include "ir_Trotec.h" -#include "IRremoteESP8266.h" -#include "IRutils.h" - -// Constants -#define TROTEC_HDR_MARK 5952U -#define TROTEC_HDR_SPACE 7364U -#define TROTEC_ONE_MARK 592U -#define TROTEC_ONE_SPACE 1560U -#define TROTEC_ZERO_MARK 592U -#define TROTEC_ZERO_SPACE 592U -#define TROTEC_GAP 6184U -#define TROTEC_GAP_END 1500U // made up value - -#if SEND_TROTEC - -void IRsend::sendTrotec(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - if (nbytes < TROTEC_COMMAND_LENGTH) - return; - - enableIROut(36); - - for (uint16_t r = 0; r <= repeat; r++) { - // Header - mark(TROTEC_HDR_MARK); - space(TROTEC_HDR_SPACE); - - // Data - for (uint16_t i = 0; i < nbytes; i++) - sendData(TROTEC_ONE_MARK, TROTEC_ONE_SPACE, TROTEC_ZERO_MARK, - TROTEC_ZERO_SPACE, data[i], 8, false); - - // Footer - mark(TROTEC_ONE_MARK); - space(TROTEC_GAP); - mark(TROTEC_ONE_MARK); - space(TROTEC_GAP_END); - } -} - -IRTrotecESP::IRTrotecESP(uint16_t pin) : _irsend(pin) { - stateReset(); -} - -void IRTrotecESP::begin() { - _irsend.begin(); -} - -void IRTrotecESP::send() { - checksum(); - _irsend.sendTrotec(trotec); -} - -void IRTrotecESP::checksum() { - uint8_t sum = 0; - uint8_t i; - - for (i = 2; i < 8; i++) sum += trotec[i]; - - trotec[8] = sum & 0xFF; -} - -void IRTrotecESP::stateReset() { - for (uint8_t i = 2; i < TROTEC_COMMAND_LENGTH; i++) - trotec[i] = 0x0; - - trotec[0] = TROTEC_INTRO1; - trotec[1] = TROTEC_INTRO2; - - setPower(false); - setTemp(TROTEC_DEF_TEMP); - setSpeed(TROTEC_FAN_MED); - setMode(TROTEC_AUTO); -} - -uint8_t* IRTrotecESP::getRaw() { - checksum(); - return trotec; -} - -void IRTrotecESP::setPower(bool state) { - if (state) - trotec[2] |= (TROTEC_ON << 3); - else - trotec[2] &= ~(TROTEC_ON << 3); -} - -uint8_t IRTrotecESP::getPower() { - return trotec[2] & (TROTEC_ON << 3); -} - -void IRTrotecESP::setSpeed(uint8_t speed) { - trotec[2] = (trotec[2] & 0xcf) | (speed << 4); -} - -uint8_t IRTrotecESP::getSpeed() { - return trotec[2] & 0x30; -} - -void IRTrotecESP::setMode(uint8_t mode) { - trotec[2] = (trotec[2] & 0xfc) | mode; -} - -uint8_t IRTrotecESP::getMode() { - return trotec[2] & 0x03; -} - -void IRTrotecESP::setTemp(uint8_t temp) { - if (temp < TROTEC_MIN_TEMP) - temp = TROTEC_MIN_TEMP; - else if (temp > TROTEC_MAX_TEMP) - temp = TROTEC_MAX_TEMP; - - trotec[3] = (trotec[3] & 0x80) | (temp - TROTEC_MIN_TEMP); -} - -uint8_t IRTrotecESP::getTemp() { - return trotec[3] & 0x7f; -} - -void IRTrotecESP::setSleep(bool sleep) { - if (sleep) - trotec[3] |= (TROTEC_SLEEP_ON << 7); - else - trotec[3] &= ~(TROTEC_SLEEP_ON << 7); -} - -bool IRTrotecESP::getSleep(void) { - return trotec[3] & (TROTEC_SLEEP_ON << 7); -} - -void IRTrotecESP::setTimer(uint8_t timer) { - if (timer > TROTEC_MAX_TIMER) timer = TROTEC_MAX_TIMER; - - if (timer) { - trotec[5] |= (TROTEC_TIMER_ON << 6); - trotec[6] = timer; - } else { - trotec[5] &= ~(TROTEC_TIMER_ON << 6); - trotec[6] = 0; - } -} - -uint8_t IRTrotecESP::getTimer() { - return trotec[6]; -} - -#endif // SEND_TROTEC diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h b/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h deleted file mode 100644 index 01ac13c59..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2017 stufisher - -#ifndef IR_TROTEC_H_ -#define IR_TROTEC_H_ - -#include "IRremoteESP8266.h" -#include "IRsend.h" - -// Constants -// Byte 0 -#define TROTEC_INTRO1 0x12 - -// Byte 1 -#define TROTEC_INTRO2 0x34 - -// Byte 2 -#define TROTEC_AUTO 0 -#define TROTEC_COOL 1 -#define TROTEC_DRY 2 -#define TROTEC_FAN 3 - -#define TROTEC_ON 1 -#define TROTEC_OFF 0 - -#define TROTEC_FAN_LOW 1 -#define TROTEC_FAN_MED 2 -#define TROTEC_FAN_HIGH 3 - -// Byte 3 -#define TROTEC_MIN_TEMP 18 -#define TROTEC_MAX_TEMP 32 -#define TROTEC_DEF_TEMP 25 - -#define TROTEC_SLEEP_ON 1 - -// Byte 5 -#define TROTEC_TIMER_ON 1 - -// Byte 6 -#define TROTEC_MIN_TIMER 0 -#define TROTEC_MAX_TIMER 23 - -#if SEND_TROTEC - -class IRTrotecESP { - public: - explicit IRTrotecESP(uint16_t pin); - - void send(); - void begin(); - - void setPower(bool state); - uint8_t getPower(); - - void setTemp(uint8_t temp); - uint8_t getTemp(); - - void setSpeed(uint8_t fan); - uint8_t getSpeed(); - - uint8_t getMode(); - void setMode(uint8_t mode); - - bool getSleep(); - void setSleep(bool sleep); - - uint8_t getTimer(); - void setTimer(uint8_t timer); - - uint8_t* getRaw(); - - private: - uint8_t trotec[TROTEC_COMMAND_LENGTH]; - void stateReset(); - void checksum(); - IRsend _irsend; -}; -#endif - -#endif // IR_TROTEC_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Whynter.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Whynter.cpp deleted file mode 100644 index 4efb2c570..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Whynter.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2009 Ken Shirriff -// Copyright 2017 David Conran - -#include -#include "IRrecv.h" -#include "IRsend.h" -#include "IRtimer.h" -#include "IRutils.h" - -// W W H H Y Y N N TTTTT EEEEE RRRRR -// W W H H Y Y NN N T E R R -// W W W HHHHH Y N N N T EEE RRRR -// W W W H H Y N NN T E R R -// WWW H H Y N N T EEEEE R R - -// Whynter A/C ARC-110WD added by Francesco Meschia -// Whynter originally added from https://github.com/shirriff/Arduino-IRremote/ - -// Constants -#define WHYNTER_TICK 50U -#define WHYNTER_HDR_MARK_TICKS 57U -#define WHYNTER_HDR_MARK (WHYNTER_HDR_MARK_TICKS * WHYNTER_TICK) -#define WHYNTER_HDR_SPACE_TICKS 57U -#define WHYNTER_HDR_SPACE (WHYNTER_HDR_SPACE_TICKS * \ - WHYNTER_TICK) -#define WHYNTER_BIT_MARK_TICKS 15U -#define WHYNTER_BIT_MARK (WHYNTER_BIT_MARK_TICKS * WHYNTER_TICK) -#define WHYNTER_ONE_SPACE_TICKS 43U -#define WHYNTER_ONE_SPACE (WHYNTER_ONE_SPACE_TICKS * \ - WHYNTER_TICK) -#define WHYNTER_ZERO_SPACE_TICKS 15U -#define WHYNTER_ZERO_SPACE (WHYNTER_ZERO_SPACE_TICKS * \ - WHYNTER_TICK) -#define WHYNTER_MIN_COMMAND_LENGTH_TICKS 2160U // Completely made up value. -#define WHYNTER_MIN_COMMAND_LENGTH (WHYNTER_MIN_COMMAND_LENGTH_TICKS * \ - WHYNTER_TICK) -#define WHYNTER_MIN_GAP_TICKS (WHYNTER_MIN_COMMAND_LENGTH_TICKS - \ - (2 * (WHYNTER_BIT_MARK_TICKS + WHYNTER_ZERO_SPACE_TICKS) + \ - WHYNTER_BITS * (WHYNTER_BIT_MARK_TICKS + WHYNTER_ONE_SPACE_TICKS))) -#define WHYNTER_MIN_GAP (WHYNTER_MIN_GAP_TICKS * WHYNTER_TICK) - -#if SEND_WHYNTER -// Send a Whynter message. -// -// Args: -// data: message to be sent. -// nbits: Nr. of bits of the message to be sent. -// repeat: Nr. of additional times the message is to be sent. -// -// Status: STABLE -// -// Ref: -// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp -void IRsend::sendWhynter(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set IR carrier frequency - enableIROut(38); - IRtimer usecTimer = IRtimer(); - - for (uint16_t i = 0; i <= repeat; i++) { - usecTimer.reset(); - // Header - mark(WHYNTER_BIT_MARK); - space(WHYNTER_ZERO_SPACE); - mark(WHYNTER_HDR_MARK); - space(WHYNTER_HDR_SPACE); - // Data - sendData(WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, - WHYNTER_ZERO_SPACE, data, nbits, true); - // Footer - mark(WHYNTER_BIT_MARK); - space(std::max(WHYNTER_MIN_COMMAND_LENGTH - usecTimer.elapsed(), - WHYNTER_MIN_GAP)); - } -} -#endif - -#if DECODE_WHYNTER -// Decode the supplied Whynter message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of data bits to expect. -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA Strict mode is ALPHA. -// -// Ref: -// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp -bool IRrecv::decodeWhynter(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + 2 * HEADER + FOOTER - 1) - return false; // We don't have enough entries to possibly match. - - // Compliance - if (strict && nbits != WHYNTER_BITS) - return false; // Incorrect nr. of bits per spec. - - uint16_t offset = OFFSET_START; - - // Header - // Sequence begins with a bit mark and a zero space. - // These are typically small, so we'll prefer to do the calibration - // on the much larger header mark & space that are next. - if (!matchMark(results->rawbuf[offset++], WHYNTER_BIT_MARK)) return false; - if (!matchSpace(results->rawbuf[offset++], WHYNTER_ZERO_SPACE)) return false; - // Main header mark and space - if (!matchMark(results->rawbuf[offset], WHYNTER_HDR_MARK)) return false; - // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / - WHYNTER_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], WHYNTER_HDR_SPACE)) return false; - // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / - WHYNTER_HDR_SPACE_TICKS; - - // Data - uint64_t data = 0; - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - WHYNTER_BIT_MARK_TICKS * m_tick, - WHYNTER_ONE_SPACE_TICKS * s_tick, - WHYNTER_BIT_MARK_TICKS * m_tick, - WHYNTER_ZERO_SPACE_TICKS * s_tick); - if (data_result.success == false) return false; - data = data_result.data; - offset += data_result.used; - - // Footer - if (!matchMark(results->rawbuf[offset++], WHYNTER_BIT_MARK_TICKS * m_tick)) - return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], WHYNTER_MIN_GAP_TICKS * s_tick)) - return false; - - // Success - results->decode_type = WHYNTER; - results->bits = nbits; - results->value = data; - results->address = 0; - results->command = 0; - return true; -} -#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.cpp deleted file mode 100644 index 3b18ae582..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.cpp +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend_test.h" -#include "IRsend.h" -#include "gtest/gtest.h" - -// Tests sendData(). - -// Test sending zero bits. -TEST(TestSendData, SendZeroBits) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b1, 0, true); - EXPECT_EQ("", irsend.outputStr()); -} - -// Test sending zero and one. -TEST(TestSendData, SendSingleBit) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b1, 1, true); - EXPECT_EQ("m1s2", irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0b0, 1, true); - EXPECT_EQ("m3s4", irsend.outputStr()); -} - -// Test sending bit order. -TEST(TestSendData, TestingBitSendOrder) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b10, 2, true); - EXPECT_EQ("m1s2m3s4", irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0b10, 2, false); - EXPECT_EQ("m3s4m1s2", irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0b0001, 4, false); - EXPECT_EQ("m1s2m3s4m3s4m3s4", irsend.outputStr()); -} - -// Test sending typical data. -TEST(TestSendData, SendTypicalData) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b1010110011110000, 16, true); - EXPECT_EQ("m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4m3s4", - irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0x1234567890ABCDEF, 64, true); - EXPECT_EQ("m3s4m3s4m3s4m1s2m3s4m3s4m1s2m3s4m3s4m3s4m1s2m1s2m3s4m1s2m3s4m3s4" - "m3s4m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4" - "m1s2m3s4m3s4m1s2m3s4m3s4m3s4m3s4m1s2m3s4m1s2m3s4m1s2m3s4m1s2m1s2" - "m1s2m1s2m3s4m3s4m1s2m1s2m3s4m1s2m1s2m1s2m1s2m3s4m1s2m1s2m1s2m1s2", - irsend.outputStr()); -} - -// Test sending more than expected bits. -TEST(TestSendData, SendOverLargeData) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0xFFFFFFFFFFFFFFFF, 70, true); - EXPECT_EQ("m3s4m3s4m3s4m3s4m3s4m3s4" - "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" - "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" - "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" - "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2", - irsend.outputStr()); -} - -// Test inverting the output. -TEST(TestIRSend, InvertedOutput) { - IRsendTest irsend(4, true); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b1, 1, true); - EXPECT_EQ("s1m2", irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0b0, 1, true); - EXPECT_EQ("s3m4", irsend.outputStr()); -} - -// Test typical use of sendRaw(). -TEST(TestSendRaw, GeneralUse) { - IRsendTest irsend(4); - IRrecv irrecv(0); - - irsend.begin(); - // NEC C3E0E0E8 as measured in #204 - uint16_t rawData[67] = {8950, 4500, 550, 1650, 600, 1650, 550, 550, 600, 500, - 600, 550, 550, 550, 600, 1650, 550, 1650, 600, 1650, - 600, 1650, 550, 1700, 550, 550, 600, 550, 550, 550, - 600, 500, 600, 550, 550, 1650, 600, 1650, 600, 1650, - 550, 550, 600, 500, 600, 500, 600, 550, 550, 550, - 600, 1650, 550, 1650, 600, 1650, 600, 500, 650, 1600, - 600, 500, 600, 550, 550, 550, 600}; - - irsend.sendRaw(rawData, 67, 38); - EXPECT_EQ( - "m8950s4500" - "m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650" - "m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550" - "m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550" - "m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550" - "m600", irsend.outputStr()); - - irsend.reset(); - irsend.sendRaw(rawData, 67, 38); - irsend.makeDecodeResult(); - EXPECT_EQ( - "m8950s4500" - "m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650" - "m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550" - "m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550" - "m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550" - "m600", irsend.outputStr()); - ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, NEC_BITS, false)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(32, irsend.capture.bits); - EXPECT_EQ(0xC3E0E0E8, irsend.capture.value); -} - -// Incorrect handling of decodes from Raw. i.e. There is no gap recorded at -// the end of a command when using the interrupt code. sendRaw() best emulates -// this for unit testing purposes. sendGC() and sendXXX() will add the trailing -// gap. Users won't see this in normal use. -TEST(TestSendRaw, NoTrailingGap) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - uint16_t rawData[67] = {9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, - 600, 1650, 650, 550, 600, 1650, 650, 1650, 650, 1650, - 600, 550, 650, 1650, 650, 1650, 650, 550, 600, 1650, - 650, 1650, 650, 550, 650, 550, 650, 1650, 650, 550, - 650, 550, 650, 550, 600, 550, 650, 550, 650, 550, - 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650, - 650, 1650, 650, 1650, 650, 1650, 600}; - irsend.sendRaw(rawData, 67, 38); - irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.h b/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.h deleted file mode 100644 index 94de487af..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2017 David Conran - -#ifndef TEST_IRSEND_TEST_H_ -#define TEST_IRSEND_TEST_H_ - -#define __STDC_LIMIT_MACROS -#include -#include -#include -#include -#include "IRrecv.h" -#include "IRsend.h" - -#define OUTPUT_BUF 1000U -#define RAW_BUF 1000U -class IRsendTest: public IRsend { - public: - uint32_t output[OUTPUT_BUF]; - uint16_t last; - uint16_t rawbuf[RAW_BUF]; - decode_results capture; - - explicit IRsendTest(uint16_t x, bool i = false) : IRsend(x, i) { - reset(); - } - - void reset() { - last = 0; - output[last] = 0; - } - - std::string outputStr() { - std::stringstream result; - if (last == 0 && output[0] == 0) - return ""; - for (uint16_t i = 0; i <= last; i++) { - if ((i & 1) != outputOff ) // Odd XOR outputOff - result << "s"; - else - result << "m"; - result << output[i]; - } - reset(); - return result.str(); - } - - void makeDecodeResult(uint16_t offset = 0) { - capture.decode_type = UNKNOWN; - capture.bits = 0; - capture.rawlen = last + 1 - offset; - capture.overflow = (last - offset >= (int16_t) RAW_BUF); - capture.repeat = false; - capture.address = 0; - capture.command = 0; - capture.value = 0; - capture.rawbuf = rawbuf; - for (uint16_t i = 0; - (i < RAW_BUF - 1) && (offset < OUTPUT_BUF); - i++, offset++) - if (output[offset] / RAWTICK > UINT16_MAX) - rawbuf[i + 1] = UINT16_MAX; - else - rawbuf[i + 1] = output[offset] / RAWTICK; - } - - void dumpRawResult() { - std::cout << std::dec; - if (capture.rawlen == 0) return; - std::cout << "uint16_t rawbuf["<< capture.rawlen - 1 << "] = {"; - for (uint16_t i = 1; i < capture.rawlen; i++) { - if (i % 8 == 1) - std::cout << std::endl << " "; - std::cout << (capture.rawbuf[i] * RAWTICK); - // std::cout << "(" << capture.rawbuf[i] << ")"; - if (i < capture.rawlen - 1) - std::cout << ", "; - } - std::cout << "};" << std::endl; - } - - void addGap(uint32_t usecs) { - space(usecs); - } - - protected: - uint16_t mark(uint16_t usec) { - if (last >= OUTPUT_BUF) - return 0; - if (last & 1) // Is odd? (i.e. last call was a space()) - output[++last] = usec; - else - output[last] += usec; - return 0; - } - - void space(uint32_t time) { - if (last >= OUTPUT_BUF) - return; - if (last & 1) { // Is odd? (i.e. last call was a space()) - output[last] += time; - } else { - output[++last] = time; - } - } -}; -#endif // TEST_IRSEND_TEST_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/test/IRutils_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/IRutils_test.cpp deleted file mode 100644 index 3b4c4145a..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/IRutils_test.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRutils.h" -#include -#include "gtest/gtest.h" - -// Tests reverseBits(). - -// Tests reverseBits for typical use. -TEST(ReverseBitsTest, TypicalUse) { - EXPECT_EQ(0xF, reverseBits(0xF0, 8)); - EXPECT_EQ(0xFFFF, reverseBits(0xFFFF0000, 32)); - EXPECT_EQ(0x555500005555FFFF, reverseBits(0xFFFFAAAA0000AAAA, 64)); - EXPECT_EQ(0, reverseBits(0, 64)); - EXPECT_EQ(0xFFFFFFFFFFFFFFFF, reverseBits(0xFFFFFFFFFFFFFFFF, 64)); -} - -// Tests reverseBits for bit size values <= 1 -TEST(ReverseBitsTest, LessThanTwoBitsReversed) { - EXPECT_EQ(0x12345678, reverseBits(0x12345678, 1)); - EXPECT_EQ(1234, reverseBits(1234, 0)); -} - -// Tests reverseBits for bit size larger than a uint64_t. -TEST(ReverseBitsTest, LargerThan64BitsReversed) { - EXPECT_EQ(0, reverseBits(0, 65)); - EXPECT_EQ(0xFFFFFFFFFFFFFFFF, reverseBits(0xFFFFFFFFFFFFFFFF, 100)); - EXPECT_EQ(0x555500005555FFFF, reverseBits(0xFFFFAAAA0000AAAA, 3000)); -} - -// Tests reverseBits for bit sizes less than all the data stored. -TEST(ReverseBitsTest, LessBitsReversedThanInputHasSet) { - EXPECT_EQ(0xF8, reverseBits(0xF1, 4)); - EXPECT_EQ(0xF5, reverseBits(0xFA, 4)); - EXPECT_EQ(0x12345678FFFF0000, reverseBits(0x123456780000FFFF, 32)); -} - -// Tests for uint64ToString() - -TEST(TestUint64ToString, TrivialCases) { - EXPECT_EQ("0", uint64ToString(0)); // Default base (10) - EXPECT_EQ("0", uint64ToString(0, 2)); // Base-2 - EXPECT_EQ("0", uint64ToString(0, 8)); // Base-8 - EXPECT_EQ("0", uint64ToString(0, 10)); // Base-10 - EXPECT_EQ("0", uint64ToString(0, 16)); // Base-16 - - EXPECT_EQ("1", uint64ToString(1, 2)); // Base-2 - EXPECT_EQ("2", uint64ToString(2, 8)); // Base-8 - EXPECT_EQ("3", uint64ToString(3, 10)); // Base-10 - EXPECT_EQ("4", uint64ToString(4, 16)); // Base-16 -} - -TEST(TestUint64ToString, NormalUse) { - EXPECT_EQ("12345", uint64ToString(12345)); - EXPECT_EQ("100", uint64ToString(4, 2)); - EXPECT_EQ("3039", uint64ToString(12345, 16)); - EXPECT_EQ("123456", uint64ToString(123456)); - EXPECT_EQ("1E240", uint64ToString(123456, 16)); - EXPECT_EQ("FEEDDEADBEEF", uint64ToString(0xfeeddeadbeef, 16)); -} - -TEST(TestUint64ToString, Max64Bit) { - EXPECT_EQ("18446744073709551615", uint64ToString(UINT64_MAX)); // Default - EXPECT_EQ("1111111111111111111111111111111111111111111111111111111111111111", - uint64ToString(UINT64_MAX, 2)); // Base-2 - EXPECT_EQ("1777777777777777777777", uint64ToString(UINT64_MAX, 8)); // Base-8 - EXPECT_EQ("18446744073709551615", uint64ToString(UINT64_MAX, 10)); // Base-10 - EXPECT_EQ("FFFFFFFFFFFFFFFF", uint64ToString(UINT64_MAX, 16)); // Base-16 -} - -TEST(TestUint64ToString, Max32Bit) { - EXPECT_EQ("4294967295", uint64ToString(UINT32_MAX)); // Default - EXPECT_EQ("37777777777", uint64ToString(UINT32_MAX, 8)); // Base-8 - EXPECT_EQ("4294967295", uint64ToString(UINT32_MAX, 10)); // Base-10 - EXPECT_EQ("FFFFFFFF", uint64ToString(UINT32_MAX, 16)); // Base-16 -} - -TEST(TestUint64ToString, InterestingCases) { - // Previous hacky-code didn't handle leading zeros in the lower 32 bits. - EXPECT_EQ("100000000", uint64ToString(0x100000000, 16)); - EXPECT_EQ("100000001", uint64ToString(0x100000001, 16)); -} - -TEST(TestUint64ToString, SillyBases) { - // If we are given a silly base, we should defer to Base-10. - EXPECT_EQ("12345", uint64ToString(12345, 0)); // Super silly, makes no sense. - EXPECT_EQ("12345", uint64ToString(12345, 1)); // We don't do unary. - EXPECT_EQ("12345", uint64ToString(12345, 100)); // We can't print base-100. - EXPECT_EQ("12345", uint64ToString(12345, 37)); // Base-37 is one to far. - EXPECT_EQ("9IX", uint64ToString(12345, 36)); // But we *can* do base-36. -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Daikin_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Daikin_test.cpp deleted file mode 100644 index b516008c1..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Daikin_test.cpp +++ /dev/null @@ -1,419 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "ir_Daikin.h" -#include "gtest/gtest.h" - -// Tests for sendDaikin(). - -// Test sending typical data only. -TEST(TestSendDaikin, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t daikin_code[DAIKIN_COMMAND_LENGTH] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, - 0x11, 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, - 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3}; - - irsend.reset(); - irsend.sendDaikin(daikin_code); - EXPECT_EQ( - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" - "m428s29428" - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" - "m428s29428", irsend.outputStr()); -} - -// Test sending with repeats. -TEST(TestSendDaikin, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - uint8_t daikin_code[DAIKIN_COMMAND_LENGTH] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, - 0x11, 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, - 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3}; - irsend.reset(); - - irsend.sendDaikin(daikin_code, DAIKIN_COMMAND_LENGTH, 1); - EXPECT_EQ( - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" - "m428s29428" - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" - "m428s29428" - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" - "m428s29428" - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" - "m428s29428", irsend.outputStr()); -} - -// Test sending atypical sizes. -TEST(TestSendDaikin, SendUnexpectedSizes) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t daikin_short_code[DAIKIN_COMMAND_LENGTH - 1] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, - 0x11, 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, - 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00}; - - irsend.reset(); - irsend.sendDaikin(daikin_short_code, DAIKIN_COMMAND_LENGTH - 1); - ASSERT_EQ("", irsend.outputStr()); - - uint8_t daikin_long_code[DAIKIN_COMMAND_LENGTH + 1] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, - 0x11, 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, - 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3, 0x11}; - irsend.reset(); - irsend.sendDaikin(daikin_long_code, DAIKIN_COMMAND_LENGTH + 1); - ASSERT_EQ( - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" - "m428s29428" - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s29428", irsend.outputStr()); -} - -// Tests for IRDaikinESP class. - -TEST(TestDaikinClass, Power) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.on(); - EXPECT_TRUE(irdaikin.getPower()); - - irdaikin.off(); - EXPECT_FALSE(irdaikin.getPower()); - - irdaikin.setPower(true); - EXPECT_TRUE(irdaikin.getPower()); - - irdaikin.setPower(false); - EXPECT_FALSE(irdaikin.getPower()); -} - -TEST(TestDaikinClass, Temperature) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setTemp(0); - EXPECT_EQ(DAIKIN_MIN_TEMP, irdaikin.getTemp()); - - irdaikin.setTemp(255); - EXPECT_EQ(DAIKIN_MAX_TEMP, irdaikin.getTemp()); - - irdaikin.setTemp(DAIKIN_MIN_TEMP); - EXPECT_EQ(DAIKIN_MIN_TEMP, irdaikin.getTemp()); - - irdaikin.setTemp(DAIKIN_MAX_TEMP); - EXPECT_EQ(DAIKIN_MAX_TEMP, irdaikin.getTemp()); - - irdaikin.setTemp(DAIKIN_MIN_TEMP - 1); - EXPECT_EQ(DAIKIN_MIN_TEMP, irdaikin.getTemp()); - - irdaikin.setTemp(DAIKIN_MAX_TEMP + 1); - EXPECT_EQ(DAIKIN_MAX_TEMP, irdaikin.getTemp()); - - irdaikin.setTemp(DAIKIN_MIN_TEMP + 1); - EXPECT_EQ(DAIKIN_MIN_TEMP + 1, irdaikin.getTemp()); - - irdaikin.setTemp(21); - EXPECT_EQ(21, irdaikin.getTemp()); - - irdaikin.setTemp(25); - EXPECT_EQ(25, irdaikin.getTemp()); - - irdaikin.setTemp(29); - EXPECT_EQ(29, irdaikin.getTemp()); -} - -TEST(TestDaikinClass, OperatingMode) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setMode(DAIKIN_AUTO); - EXPECT_EQ(DAIKIN_AUTO, irdaikin.getMode()); - - irdaikin.setMode(DAIKIN_COOL); - EXPECT_EQ(DAIKIN_COOL, irdaikin.getMode()); - - irdaikin.setMode(DAIKIN_HEAT); - EXPECT_EQ(DAIKIN_HEAT, irdaikin.getMode()); - - irdaikin.setMode(DAIKIN_DRY); - EXPECT_EQ(DAIKIN_DRY, irdaikin.getMode()); - - irdaikin.setMode(DAIKIN_FAN); - EXPECT_EQ(DAIKIN_FAN, irdaikin.getMode()); - - irdaikin.setMode(DAIKIN_FAN + 1); - EXPECT_EQ(DAIKIN_AUTO, irdaikin.getMode()); - - irdaikin.setMode(DAIKIN_AUTO + 1); - EXPECT_EQ(DAIKIN_AUTO, irdaikin.getMode()); - - irdaikin.setMode(255); - EXPECT_EQ(DAIKIN_AUTO, irdaikin.getMode()); -} - -TEST(TestDaikinClass, VaneSwing) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setSwingHorizontal(true); - irdaikin.setSwingVertical(false); - - irdaikin.setSwingHorizontal(true); - EXPECT_TRUE(irdaikin.getSwingHorizontal()); - EXPECT_FALSE(irdaikin.getSwingVertical()); - - irdaikin.setSwingVertical(true); - EXPECT_TRUE(irdaikin.getSwingHorizontal()); - EXPECT_TRUE(irdaikin.getSwingVertical()); - - irdaikin.setSwingHorizontal(false); - EXPECT_FALSE(irdaikin.getSwingHorizontal()); - EXPECT_TRUE(irdaikin.getSwingVertical()); - - irdaikin.setSwingVertical(false); - EXPECT_FALSE(irdaikin.getSwingHorizontal()); - EXPECT_FALSE(irdaikin.getSwingVertical()); -} - -TEST(TestDaikinClass, QuietMode) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setQuiet(true); - EXPECT_TRUE(irdaikin.getQuiet()); - - irdaikin.setQuiet(false); - EXPECT_FALSE(irdaikin.getQuiet()); - - irdaikin.setQuiet(true); - EXPECT_TRUE(irdaikin.getQuiet()); - - irdaikin.setPowerful(true); - EXPECT_FALSE(irdaikin.getQuiet()); -} - -TEST(TestDaikinClass, PowerfulMode) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setPowerful(true); - EXPECT_TRUE(irdaikin.getPowerful()); - - irdaikin.setPowerful(false); - EXPECT_FALSE(irdaikin.getPowerful()); - - irdaikin.setPowerful(true); - EXPECT_TRUE(irdaikin.getPowerful()); - - irdaikin.setQuiet(true); - EXPECT_FALSE(irdaikin.getPowerful()); -} - -TEST(TestDaikinClass, FanSpeed) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setFan(0); - EXPECT_EQ(0, irdaikin.getFan()); - - irdaikin.setFan(255); - EXPECT_EQ(DAIKIN_FAN_MAX, irdaikin.getFan()); - - irdaikin.setFan(DAIKIN_FAN_MAX); - EXPECT_EQ(DAIKIN_FAN_MAX, irdaikin.getFan()); - - irdaikin.setFan(DAIKIN_FAN_MAX + 1); - EXPECT_EQ(DAIKIN_FAN_MAX, irdaikin.getFan()); - - irdaikin.setFan(DAIKIN_FAN_MAX - 1); - EXPECT_EQ(DAIKIN_FAN_MAX - 1, irdaikin.getFan()); - - irdaikin.setFan(DAIKIN_FAN_MIN); - EXPECT_EQ(DAIKIN_FAN_MIN, irdaikin.getFan()); - - irdaikin.setFan(DAIKIN_FAN_MIN + 1); - EXPECT_EQ(DAIKIN_FAN_MIN + 1, irdaikin.getFan()); - - irdaikin.setFan(3); - EXPECT_EQ(3, irdaikin.getFan()); - - irdaikin.setFan(DAIKIN_FAN_AUTO); - EXPECT_EQ(DAIKIN_FAN_AUTO, irdaikin.getFan()); -} - -TEST(TestDaikinClass, MessageConstuction) { - IRDaikinESP irdaikin(0); - IRsendTest irsend(4); - irdaikin.begin(); - irsend.begin(); - - irdaikin.setFan(DAIKIN_FAN_MIN); - irdaikin.setMode(DAIKIN_COOL); - irdaikin.setTemp(27); - irdaikin.setSwingVertical(false); - irdaikin.setSwingHorizontal(true); - irdaikin.setQuiet(false); - irdaikin.setPower(true); - - // Check everything for kicks. - EXPECT_EQ(DAIKIN_FAN_MIN, irdaikin.getFan()); - EXPECT_EQ(DAIKIN_COOL, irdaikin.getMode()); - EXPECT_EQ(27, irdaikin.getTemp()); - EXPECT_FALSE(irdaikin.getSwingVertical()); - EXPECT_TRUE(irdaikin.getSwingHorizontal()); - EXPECT_FALSE(irdaikin.getQuiet()); - EXPECT_TRUE(irdaikin.getPower()); - - irsend.reset(); - irsend.sendDaikin(irdaikin.getRaw()); - EXPECT_EQ( - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s29428" - "m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s428m428s428" - "m428s428m428s1280m428s1280m428s428m428s1280m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s428" - "m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280m428s428" - "m428s29428", irsend.outputStr()); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Fujitsu_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Fujitsu_test.cpp deleted file mode 100644 index f1b6c04f6..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Fujitsu_test.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2017 Jonny Graham - -#include "IRsend.h" -#include "IRsend_test.h" -#include "ir_Fujitsu.h" -#include "gtest/gtest.h" - -template -::testing::AssertionResult ArraysMatch(const T (&expected)[size], - const T* actual) { - for (size_t i(0); i < size; ++i) { - if (expected[i] != actual[i]) { - int e = expected[i]; - int a = actual[i]; - return ::testing::AssertionFailure() << "array[" << i - << "] (" << std::hex << a << std::dec << ") != expected[" << i - << "] (" << std::hex << e << std::dec << ")"; - } - } - - return ::testing::AssertionSuccess(); -} -// Tests for Mitsubishi A/C methods. - -// Test sending typical data only. -TEST(TestSendFujitsuAC, GetRawDefault) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - fujitsuACSender.setCmd(FUJITSU_AC_CMD_TURN_ON); - fujitsuACSender.setSwing(FUJITSU_AC_SWING_BOTH); - fujitsuACSender.setMode(FUJITSU_AC_MODE_COOL); - fujitsuACSender.setFanSpeed(FUJITSU_AC_FAN_HIGH); - fujitsuACSender.setTemp(24); - uint8_t expected[16] = {0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30, - 0x81, 0x1, 0x31, 0x0, 0x0, 0x0, 0x20, 0xFD}; - EXPECT_TRUE(ArraysMatch(expected, fujitsuACSender.getRaw())); -} - -TEST(TestSendFujitsuAC, GetRawTurnOff) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - fujitsuACSender.off(); - uint8_t expected[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD}; - EXPECT_TRUE(ArraysMatch(expected, fujitsuACSender.getRaw())); -} -TEST(TestSendFujitsuAC, GetRawStepHoriz) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - fujitsuACSender.stepHoriz(); - uint8_t expected[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x79, 0x86}; - EXPECT_TRUE(ArraysMatch(expected, fujitsuACSender.getRaw())); -} -TEST(TestSendFujitsuAC, GetRawStepVert) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - fujitsuACSender.stepVert(); - uint8_t expected[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x6C, 0x93}; - EXPECT_TRUE(ArraysMatch(expected, fujitsuACSender.getRaw())); -} - -TEST(TestSendFujitsuAC, GetRawWithSwingHoriz) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - fujitsuACSender.setCmd(FUJITSU_AC_CMD_STAY_ON); - fujitsuACSender.setSwing(FUJITSU_AC_SWING_HORIZ); - fujitsuACSender.setMode(FUJITSU_AC_MODE_COOL); - fujitsuACSender.setFanSpeed(FUJITSU_AC_FAN_QUIET); - fujitsuACSender.setTemp(25); - uint8_t expected[16] = {0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30, - 0x90, 0x1, 0x24, 0x0, 0x0, 0x0, 0x20, 0xFB}; - EXPECT_TRUE(ArraysMatch(expected, fujitsuACSender.getRaw())); -} - -TEST(TestSendFujitsuAC, GetRawWithFan) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - fujitsuACSender.setCmd(FUJITSU_AC_CMD_STAY_ON); - fujitsuACSender.setSwing(FUJITSU_AC_SWING_HORIZ); - fujitsuACSender.setMode(FUJITSU_AC_MODE_FAN); - fujitsuACSender.setFanSpeed(FUJITSU_AC_FAN_MED); - fujitsuACSender.setTemp(20); // temp doesn't matter for fan - // but it is sent by the RC anyway - uint8_t expected[16] = {0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30, - 0x40, 0x3, 0x22, 0x0, 0x0, 0x0, 0x20, 0x4B}; - EXPECT_TRUE(ArraysMatch(expected, fujitsuACSender.getRaw())); -} - -TEST(TestSendFujitsuAC, GenerateMessage) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - IRsendTest irsend(4); - fujitsuACSender.begin(); - irsend.begin(); - - fujitsuACSender.setCmd(FUJITSU_AC_CMD_STAY_ON); - fujitsuACSender.setSwing(FUJITSU_AC_SWING_BOTH); - fujitsuACSender.setMode(FUJITSU_AC_MODE_COOL); - fujitsuACSender.setFanSpeed(FUJITSU_AC_FAN_HIGH); - fujitsuACSender.setTemp(24); - - EXPECT_EQ(FUJITSU_AC_FAN_HIGH, fujitsuACSender.getFanSpeed()); - EXPECT_EQ(FUJITSU_AC_MODE_COOL, fujitsuACSender.getMode()); - EXPECT_EQ(24, fujitsuACSender.getTemp()); - EXPECT_EQ(FUJITSU_AC_SWING_BOTH, fujitsuACSender.getSwing()); - EXPECT_EQ(FUJITSU_AC_CMD_STAY_ON, fujitsuACSender.getCmd()); - - irsend.reset(); - irsend.sendFujitsuAC(fujitsuACSender.getRaw(), FUJITSU_AC_STATE_LENGTH); - EXPECT_EQ( - "m3224s1574m448s367m448s367m448s1182m448s367m448s1182m448s367m448s367m448" - "s367m448s1182m448s1182m448s367m448s367m448s367m448s1182m448s1182m448s367" - "m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448" - "s367m448s367m448s367m448s367m448s1182m448s367m448s367m448s367m448s367m448" - "s367m448s367m448s367m448s1182m448s367m448s367m448s367m448s367m448s1182" - "m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s367" - "m448s367m448s1182m448s367m448s367m448s367m448s367m448s367m448s367m448s367" - "m448s367m448s1182m448s1182m448s367m448s367m448s367m448s367m448s367m448s367" - "m448s367m448s367m448s367m448s1182m448s1182m448s367m448s367m448s367m448" - "s367m448s367m448s367m448s367m448s1182m448s367m448s367m448s367m448s1182m448" - "s1182m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448" - "s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448" - "s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448" - "s367m448s367m448s367m448s367m448s367m448s1182m448s367m448s367m448s367m448" - "s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s8100", - irsend.outputStr()); -} -TEST(TestSendFujitsuAC, GenerateShortMessage) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - IRsendTest irsend(4); - fujitsuACSender.begin(); - irsend.begin(); - - fujitsuACSender.off(); - - EXPECT_EQ(FUJITSU_AC_CMD_TURN_OFF, fujitsuACSender.getCmd()); - - irsend.reset(); - irsend.sendFujitsuAC(fujitsuACSender.getRaw(), FUJITSU_AC_STATE_LENGTH_SHORT); - EXPECT_EQ( - "m3224s1574m448s367m448s367m448s1182m448s367m448s1182m448s367m448s367m448" - "s367m448s1182m448s1182m448s367m448s367m448s367m448s1182m448s1182m448s367" - "m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367" - "m448s367m448s367m448s367m448s1182m448s367m448s367m448s367m448s367m448s367" - "m448s367m448s367m448s1182m448s367m448s367m448s367m448s367m448s1182m448s367" - "m448s367m448s367m448s367m448s367m448s367m448s1182m448s367m448s1182m448" - "s1182m448s1182m448s1182m448s1182m448s1182m448s8100", - irsend.outputStr()); -} - -// Issue #275 -TEST(TestSendFujitsuAC, Issue275) { - IRFujitsuAC fujitsuACSender = IRFujitsuAC(4); - IRsendTest irsend(4); - fujitsuACSender.begin(); - irsend.begin(); - irsend.reset(); - - fujitsuACSender.setCmd(FUJITSU_AC_CMD_TURN_OFF); - irsend.sendFujitsuAC(fujitsuACSender.getRaw(), FUJITSU_AC_STATE_LENGTH_SHORT); - EXPECT_EQ( - // Header - "m3224s1574" - // 0 0 1 0 1 0 0 0 (0x28) - "m448s367m448s367m448s1182m448s367m448s1182m448s367m448s367m448s367" - // 1 1 0 0 0 1 1 0 (0xC6) - "m448s1182m448s1182m448s367m448s367m448s367m448s1182m448s1182m448s367" - // 0 0 0 0 0 0 0 0 (0x00) - "m448s367m448s367m448s367m448s367m448s367m448s367m448s367m448s367" - // 0 0 0 0 1 0 0 0 (0x08) - "m448s367m448s367m448s367m448s367m448s1182m448s367m448s367m448s367" - // 0 0 0 0 1 0 0 0 (0x08) - "m448s367m448s367m448s367m448s367m448s1182m448s367m448s367m448s367" - // 0 1 0 0 0 0 0 0 (0x40) - "m448s367m448s1182m448s367m448s367m448s367m448s367m448s367m448s367" - // 1 0 1 1 1 1 1 1 (0xBF) - "m448s1182m448s367m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182" - // Footer - "m448s8100", irsend.outputStr()); - - irsend.reset(); - // Per report in Issue #275 - uint16_t off[115] = { - 3350, 1650, - 450, 400, 450, 450, 450, 1250, 450, 400, 450, 1250, 450, 400, 450, 400, - 450, 400, 450, 1250, 450, 1250, 450, 400, 450, 400, 450, 400, 450, 1250, - 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, - 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, - 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, - 450, 400, 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 1250, - 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 1250, - 450, 400, 450, 1250, 450, 1250, 450, 1250, 450, 1250, 450, 1250, - 450, 1250, 450}; - irsend.sendRaw(off, 115, 38); - EXPECT_EQ( - // Header - "m3350s1650" - // 0 0 1 0 1 0 0 0 (0x28) - "m450s400m450s450m450s1250m450s400m450s1250m450s400m450s400m450s400" - // 1 1 0 0 0 1 1 0 (0xC6) - "m450s1250m450s1250m450s400m450s400m450s400m450s1250m450s1250m450s400" - // 0 0 0 0 0 0 0 0 (0x00) - "m450s400m450s400m450s400m450s400m450s400m450s400m450s400m450s400" - // 0 0 0 0 1 0 0 0 (0x08) - "m450s400m450s400m450s400m450s400m450s1250m450s400m450s400m450s400" - // 0 0 0 0 1 0 0 0 (0x08) - "m450s400m450s400m450s400m450s400m450s1250m450s400m450s400m450s400" - // 0 1 0 0 0 0 0 0 (0x40) - "m450s400m450s1250m450s400m450s400m450s400m450s400m450s400m450s400" - // 1 0 1 1 1 1 1 1 (0xBF) - "m450s1250m450s400m450s1250m450s1250m450s1250m450s1250m450s1250m450s1250" - // Footer - "m450", - irsend.outputStr()); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_GlobalCache_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_GlobalCache_test.cpp deleted file mode 100644 index c2e9762a2..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_GlobalCache_test.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendGlobalCache(). - -// Test sending a typical command wihtout a repeat. -TEST(TestSendGlobalCache, NonRepeatingCode) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - irsend.reset(); - - // Modified NEC TV "Power On" from Global Cache with no repeats - uint16_t gc_test[71] = {38000, 1, 1, 342, 172, 21, 22, 21, 21, 21, 65, 21, 21, - 21, 22, 21, 22, 21, 21, 21, 22, 21, 65, 21, 65, 21, - 22, 21, 65, 21, 65, 21, 65, 21, 65, 21, 65, 21, 65, - 21, 22, 21, 22, 21, 21, 21, 22, 21, 22, 21, 65, 21, - 22, 21, 21, 21, 65, 21, 65, 21, 65, 21, 64, 22, 65, - 21, 22, 21, 65, 21, 1519}; - irsend.sendGC(gc_test, 71); - irsend.makeDecodeResult(); - EXPECT_EQ("m8892s4472m546s572m546s546m546s1690m546s546m546s572m546s572" - "m546s546m546s572m546s1690m546s1690m546s572m546s1690m546s1690" - "m546s1690m546s1690m546s1690m546s1690m546s572m546s572m546s546" - "m546s572m546s572m546s1690m546s572m546s546m546s1690m546s1690" - "m546s1690m546s1664m572s1690m546s572m546s1690m546s39494", - irsend.outputStr()); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); - EXPECT_EQ(0x20DF827D, irsend.capture.value); - EXPECT_EQ(0x4, irsend.capture.address); - EXPECT_EQ(0x41, irsend.capture.command); -} - -// Test sending typical command with repeats. -TEST(TestSendGlobalCache, RepeatCode) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - irsend.reset(); - - // Sherwood (NEC-like) "Power On" from Global Cache with 2 repeats - uint16_t gc_test[75] = {38000, 2, 69, 341, 171, 21, 64, 21, 64, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 64, 21, 64, 21, 21, - 21, 64, 21, 21, 21, 21, 21, 21, 21, 64, 21, 21, 21, - 64, 21, 21, 21, 21, 21, 21, 21, 64, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 64, 21, 64, 21, 64, 21, 21, 21, - 64, 21, 64, 21, 64, 21, 1600, 341, 85, 21, 3647}; - irsend.sendGC(gc_test, 75); - irsend.makeDecodeResult(); - EXPECT_EQ("m8866s4446m546s1664m546s1664m546s546m546s546m546s546m546s546" - "m546s546m546s1664m546s1664m546s546m546s1664m546s546m546s546" - "m546s546m546s1664m546s546m546s1664m546s546m546s546m546s546" - "m546s1664m546s546m546s546m546s546m546s546m546s1664m546s1664" - "m546s1664m546s546m546s1664m546s1664m546s1664m546s41600" - "m8866s2210m546s94822" - "m8866s2210m546s94822", irsend.outputStr()); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); - EXPECT_EQ(0xC1A28877, irsend.capture.value); - EXPECT_EQ(0x4583, irsend.capture.address); - EXPECT_EQ(0x11, irsend.capture.command); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Gree_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Gree_test.cpp deleted file mode 100644 index 80a3dec1d..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Gree_test.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendGree(). - -// Test sending typical data only. -TEST(TestSendGreeChars, SendData) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t gree_code[GREE_STATE_LENGTH] = { - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF}; - irsend.reset(); - irsend.sendGree(gree_code); - EXPECT_EQ( - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s19000", irsend.outputStr()); -} - -TEST(TestSendGreeUint64, SendData) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendGree(0x1234567890ABCDEF); - EXPECT_EQ( - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s19000", irsend.outputStr()); -} - -// Test sending with repeats. -TEST(TestSendGreeChars, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - uint8_t gree_code[GREE_STATE_LENGTH] = { - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF}; - irsend.reset(); - - irsend.sendGree(gree_code, GREE_STATE_LENGTH, 1); - EXPECT_EQ( - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s19000" - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s19000", irsend.outputStr()); -} - -TEST(TestSendGreeUint64, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendGree(0x1234567890ABCDEF, GREE_BITS, 1); - EXPECT_EQ( - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s19000" - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s19000", irsend.outputStr()); -} - -// Test sending atypical sizes. -TEST(TestSendGreeChars, SendUnexpectedSizes) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t gree_short_code[GREE_STATE_LENGTH - 1] = { - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD}; - uint8_t gree_long_code[GREE_STATE_LENGTH + 1] = { - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12}; - irsend.reset(); - irsend.sendGree(gree_short_code, GREE_STATE_LENGTH - 1); - ASSERT_EQ("", irsend.outputStr()); - - irsend.reset(); - irsend.sendGree(gree_long_code, GREE_STATE_LENGTH + 1); - ASSERT_EQ( - "m9000s4000" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" - "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" - "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" - "m620s540m620s1600m620s540" - "m620s19000" - "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" - "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" - "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" - "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" - "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" - "m620s19000", irsend.outputStr()); -} - -TEST(TestSendGreeUint64, SendUnexpectedSizes) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendGree(0x1234567890ABCDEF, GREE_BITS - 1); - ASSERT_EQ("", irsend.outputStr()); - - irsend.reset(); - irsend.sendGree(0x1234567890ABCDEF, GREE_BITS + 1); - ASSERT_EQ("", irsend.outputStr()); -} - -TEST(TestSendGree, CompareUint64ToCharResults) { - IRsendTest irsend_chars(4); - IRsendTest irsend_uint64(0); - - uint8_t gree_code[GREE_STATE_LENGTH] = { - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF}; - - irsend_chars.begin(); - irsend_uint64.begin(); - - irsend_chars.reset(); - irsend_uint64.reset(); - irsend_chars.sendGree(gree_code); - irsend_uint64.sendGree(0x1234567890ABCDEF); - ASSERT_EQ(irsend_chars.outputStr(), irsend_uint64.outputStr()); - - uint8_t gree_zero_code[GREE_STATE_LENGTH] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - irsend_chars.reset(); - irsend_uint64.reset(); - irsend_chars.sendGree(gree_zero_code); - irsend_uint64.sendGree((uint64_t) 0x0); - ASSERT_EQ(irsend_chars.outputStr(), irsend_uint64.outputStr()); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Kelvinator_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Kelvinator_test.cpp deleted file mode 100644 index c409c20ba..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Kelvinator_test.cpp +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "ir_Kelvinator.h" -#include "gtest/gtest.h" - -// Tests for sendKelvinator(). - -// Test sending typical data only. -TEST(TestSendKelvinator, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t kelv_code[KELVINATOR_STATE_LENGTH] = { - 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, - 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0}; - irsend.reset(); - irsend.sendKelvinator(kelv_code); - EXPECT_EQ( - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560" - "m675s39900" - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s1560" - "m675s39900", irsend.outputStr()); -} - -// Test sending with repeats. -TEST(TestSendKelvinator, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - uint8_t kelv_code[KELVINATOR_STATE_LENGTH] = { - 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, - 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0}; - irsend.reset(); - - irsend.sendKelvinator(kelv_code, KELVINATOR_STATE_LENGTH, 1); - EXPECT_EQ( - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560" - "m675s39900" - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s1560" - "m675s39900" - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560" - "m675s39900" - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s1560" - "m675s39900", irsend.outputStr()); -} - -// Test sending atypical sizes. -TEST(TestSendKelvinator, SendUnexpectedSizes) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t kelv_short_code[15] = {0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, - 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10}; - uint8_t kelv_long_code[17] = {0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, - 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0, - 0x00}; - irsend.reset(); - irsend.sendKelvinator(kelv_short_code, 15); - ASSERT_EQ("", irsend.outputStr()); - - irsend.reset(); - // Shouldn't be different from the SendDataOnly. We just don't send the - // extra data. - irsend.sendKelvinator(kelv_long_code, 17); - ASSERT_EQ( - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560" - "m675s39900" - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s520m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s1560" - "m675s39900", irsend.outputStr()); -} - - -// Tests for IRKelvinatorAC class. - -TEST(TestKelvinatorClass, Power) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.on(); - EXPECT_TRUE(irkelv.getPower()); - - irkelv.off(); - EXPECT_FALSE(irkelv.getPower()); - - irkelv.setPower(true); - EXPECT_TRUE(irkelv.getPower()); - - irkelv.setPower(false); - EXPECT_FALSE(irkelv.getPower()); -} - -TEST(TestKelvinatorClass, Temperature) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setTemp(0); - EXPECT_EQ(KELVINATOR_MIN_TEMP, irkelv.getTemp()); - - irkelv.setTemp(255); - EXPECT_EQ(KELVINATOR_MAX_TEMP, irkelv.getTemp()); - - irkelv.setTemp(KELVINATOR_MIN_TEMP); - EXPECT_EQ(KELVINATOR_MIN_TEMP, irkelv.getTemp()); - - irkelv.setTemp(KELVINATOR_MAX_TEMP); - EXPECT_EQ(KELVINATOR_MAX_TEMP, irkelv.getTemp()); - - irkelv.setTemp(KELVINATOR_MIN_TEMP - 1); - EXPECT_EQ(KELVINATOR_MIN_TEMP, irkelv.getTemp()); - - irkelv.setTemp(KELVINATOR_MAX_TEMP + 1); - EXPECT_EQ(KELVINATOR_MAX_TEMP, irkelv.getTemp()); - - irkelv.setTemp(17); - EXPECT_EQ(17, irkelv.getTemp()); - - irkelv.setTemp(21); - EXPECT_EQ(21, irkelv.getTemp()); - - irkelv.setTemp(25); - EXPECT_EQ(25, irkelv.getTemp()); - - irkelv.setTemp(29); - EXPECT_EQ(29, irkelv.getTemp()); -} - -TEST(TestKelvinatorClass, OperatingMode) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setTemp(24); - irkelv.setMode(KELVINATOR_AUTO); - EXPECT_EQ(KELVINATOR_AUTO, irkelv.getMode()); - EXPECT_EQ(KELVINATOR_AUTO_TEMP, irkelv.getTemp()); - - irkelv.setMode(KELVINATOR_COOL); - EXPECT_EQ(KELVINATOR_COOL, irkelv.getMode()); - - irkelv.setMode(KELVINATOR_HEAT); - EXPECT_EQ(KELVINATOR_HEAT, irkelv.getMode()); - - irkelv.setTemp(24); - irkelv.setMode(KELVINATOR_DRY); - EXPECT_EQ(KELVINATOR_DRY, irkelv.getMode()); - EXPECT_EQ(KELVINATOR_AUTO_TEMP, irkelv.getTemp()); - - irkelv.setMode(KELVINATOR_FAN); - EXPECT_EQ(KELVINATOR_FAN, irkelv.getMode()); - - irkelv.setMode(KELVINATOR_HEAT + 1); - EXPECT_EQ(KELVINATOR_AUTO, irkelv.getMode()); - - irkelv.setMode(255); - EXPECT_EQ(KELVINATOR_AUTO, irkelv.getMode()); -} - -TEST(TestKelvinatorClass, VaneSwing) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setSwingHorizontal(true); - irkelv.setSwingVertical(false); - - irkelv.setSwingHorizontal(true); - EXPECT_TRUE(irkelv.getSwingHorizontal()); - EXPECT_FALSE(irkelv.getSwingVertical()); - - irkelv.setSwingVertical(true); - EXPECT_TRUE(irkelv.getSwingHorizontal()); - EXPECT_TRUE(irkelv.getSwingVertical()); - - irkelv.setSwingHorizontal(false); - EXPECT_FALSE(irkelv.getSwingHorizontal()); - EXPECT_TRUE(irkelv.getSwingVertical()); - - irkelv.setSwingVertical(false); - EXPECT_FALSE(irkelv.getSwingHorizontal()); - EXPECT_FALSE(irkelv.getSwingVertical()); -} - -TEST(TestKelvinatorClass, QuietMode) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setQuiet(true); - EXPECT_TRUE(irkelv.getQuiet()); - - irkelv.setQuiet(false); - EXPECT_FALSE(irkelv.getQuiet()); - - irkelv.setQuiet(true); - EXPECT_TRUE(irkelv.getQuiet()); -} - -TEST(TestKelvinatorClass, IonFilter) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setIonFilter(true); - EXPECT_TRUE(irkelv.getIonFilter()); - - irkelv.setIonFilter(false); - EXPECT_FALSE(irkelv.getIonFilter()); - - irkelv.setIonFilter(true); - EXPECT_TRUE(irkelv.getIonFilter()); -} - -TEST(TestKelvinatorClass, Light) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setLight(true); - EXPECT_TRUE(irkelv.getLight()); - - irkelv.setLight(false); - EXPECT_FALSE(irkelv.getLight()); - - irkelv.setLight(true); - EXPECT_TRUE(irkelv.getLight()); -} - -TEST(TestKelvinatorClass, XFan) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setXFan(true); - EXPECT_TRUE(irkelv.getXFan()); - - irkelv.setXFan(false); - EXPECT_FALSE(irkelv.getXFan()); - - irkelv.setXFan(true); - EXPECT_TRUE(irkelv.getXFan()); -} - -TEST(TestKelvinatorClass, TurboFan) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setTurbo(true); - EXPECT_TRUE(irkelv.getTurbo()); - - irkelv.setTurbo(false); - EXPECT_FALSE(irkelv.getTurbo()); - - irkelv.setFan(2); - irkelv.setTurbo(true); - EXPECT_TRUE(irkelv.getTurbo()); - - // Turbo mode is turned off if the temperature is changed. - irkelv.setFan(3); - EXPECT_FALSE(irkelv.getTurbo()); - - // But only when it is changed, not set to the same value again. - irkelv.setTurbo(true); - irkelv.setFan(3); - EXPECT_TRUE(irkelv.getTurbo()); -} - -TEST(TestKelvinatorClass, FanSpeed) { - IRKelvinatorAC irkelv(0); - irkelv.begin(); - - irkelv.setFan(0); - EXPECT_EQ(0, irkelv.getFan()); - - irkelv.setFan(255); - EXPECT_EQ(KELVINATOR_FAN_MAX, irkelv.getFan()); - - irkelv.setFan(KELVINATOR_FAN_MAX); - EXPECT_EQ(KELVINATOR_FAN_MAX, irkelv.getFan()); - - irkelv.setFan(KELVINATOR_FAN_MAX + 1); - EXPECT_EQ(KELVINATOR_FAN_MAX, irkelv.getFan()); - - irkelv.setFan(KELVINATOR_FAN_MAX - 1); - EXPECT_EQ(KELVINATOR_FAN_MAX - 1, irkelv.getFan()); - - irkelv.setFan(1); - EXPECT_EQ(1, irkelv.getFan()); - - irkelv.setFan(1); - EXPECT_EQ(1, irkelv.getFan()); - - irkelv.setFan(3); - EXPECT_EQ(3, irkelv.getFan()); -} - - -TEST(TestKelvinatorClass, MessageConstuction) { - IRKelvinatorAC irkelv(0); - IRsendTest irsend(4); - irkelv.begin(); - irsend.begin(); - - irkelv.setFan(1); - irkelv.setMode(KELVINATOR_COOL); - irkelv.setTemp(27); - irkelv.setSwingVertical(false); - irkelv.setSwingHorizontal(true); - irkelv.setIonFilter(true); - irkelv.setQuiet(false); - irkelv.setLight(false); - irkelv.setPower(true); - irkelv.setTurbo(false); - irkelv.setXFan(true); - - // Check everything for kicks. - EXPECT_EQ(1, irkelv.getFan()); - EXPECT_EQ(KELVINATOR_COOL, irkelv.getMode()); - EXPECT_EQ(27, irkelv.getTemp()); - EXPECT_FALSE(irkelv.getSwingVertical()); - EXPECT_TRUE(irkelv.getSwingHorizontal()); - EXPECT_TRUE(irkelv.getIonFilter()); - EXPECT_FALSE(irkelv.getQuiet()); - EXPECT_FALSE(irkelv.getLight()); - EXPECT_TRUE(irkelv.getPower()); - EXPECT_FALSE(irkelv.getTurbo()); - EXPECT_TRUE(irkelv.getXFan()); - - irsend.reset(); - irsend.sendKelvinator(irkelv.getRaw()); - EXPECT_EQ( - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s1560m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s1560m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s1560" - "m675s39900" - "m8990s4490" - "m675s1560m675s520m675s520m675s1560m675s1560m675s520m675s1560m675s520" - "m675s1560m675s1560m675s520m675s1560m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s1560m675s1560" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s520" - "m675s520m675s1560m675s520" - "m675s19950" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s520m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s520m675s520m675s520" - "m675s520m675s520m675s520m675s520m675s1560m675s1560m675s1560m675s1560" - "m675s39900", irsend.outputStr()); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Mitsubishi_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Mitsubishi_test.cpp deleted file mode 100644 index 2f28657fb..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Mitsubishi_test.cpp +++ /dev/null @@ -1,694 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "ir_Mitsubishi.h" -#include "gtest/gtest.h" - -// Tests for sendMitsubishi(). - -// Test sending typical data only. -TEST(TestSendMitsubishi, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendMitsubishi(0xE242); - EXPECT_EQ( - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580" - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580", irsend.outputStr()); - - irsend.reset(); - irsend.sendMitsubishi(0x0); - EXPECT_EQ( - "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" - "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" - "m300s53580" - "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" - "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" - "m300s53580", irsend.outputStr()); - - irsend.reset(); - irsend.sendMitsubishi(0x4321); - EXPECT_EQ( - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s2100" - "m300s900m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100" - "m300s53580" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s2100" - "m300s900m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100" - "m300s53580", irsend.outputStr()); -} - -// Test sending with different repeats. -TEST(TestSendMitsubishi, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendMitsubishi(0xE242, MITSUBISHI_BITS, 0); // 0 repeat. - EXPECT_EQ( - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580", irsend.outputStr()); - - irsend.reset(); - irsend.sendMitsubishi(0xE242, MITSUBISHI_BITS, 1); // 1 repeat. - EXPECT_EQ( - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580" - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580", irsend.outputStr()); - irsend.sendMitsubishi(0xE242, MITSUBISHI_BITS, 2); // 2 repeats. - EXPECT_EQ( - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580" - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580" - "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" - "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" - "m300s53580", irsend.outputStr()); -} - -// Test sending an atypical data size. -TEST(TestSendMitsubishi, SendUsualSize) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendMitsubishi(0x0, 8); - EXPECT_EQ( - "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" - "m300s53580" - "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" - "m300s53580", irsend.outputStr()); - - irsend.reset(); - irsend.sendMitsubishi(0x1234567890ABCDEF, 64); - EXPECT_EQ( - "m300s900m300s900m300s900m300s2100m300s900m300s900m300s2100m300s900" - "m300s900m300s900m300s2100m300s2100m300s900m300s2100m300s900m300s900" - "m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100m300s900" - "m300s900m300s2100m300s2100m300s2100m300s2100m300s900m300s900m300s900" - "m300s2100m300s900m300s900m300s2100m300s900m300s900m300s900m300s900" - "m300s2100m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100" - "m300s2100m300s2100m300s900m300s900m300s2100m300s2100m300s900m300s2100" - "m300s2100m300s2100m300s2100m300s900m300s2100m300s2100m300s2100m300s2100" - "m300s53580" - "m300s900m300s900m300s900m300s2100m300s900m300s900m300s2100m300s900" - "m300s900m300s900m300s2100m300s2100m300s900m300s2100m300s900m300s900" - "m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100m300s900" - "m300s900m300s2100m300s2100m300s2100m300s2100m300s900m300s900m300s900" - "m300s2100m300s900m300s900m300s2100m300s900m300s900m300s900m300s900" - "m300s2100m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100" - "m300s2100m300s2100m300s900m300s900m300s2100m300s2100m300s900m300s2100" - "m300s2100m300s2100m300s2100m300s900m300s2100m300s2100m300s2100m300s2100" - "m300s53580", irsend.outputStr()); -} - -// Decode normal Mitsubishi messages. -TEST(TestDecodeMitsubishi, NormalDecodeWithStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Mitsubishi 16-bit message. - irsend.reset(); - irsend.sendMitsubishi(0xC2B8); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); - EXPECT_EQ(0xC2B8, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - irsend.reset(); - irsend.sendMitsubishi(0x0); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - irsend.reset(); - irsend.sendMitsubishi(0xFFFF); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); - EXPECT_EQ(0xFFFF, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - // Non-standard Mitsubishi sizes should fail with strict. - irsend.reset(); - // 12 bits. - irsend.sendMitsubishi(0xFFF, 12); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 12, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, true)); - - // 32 bits. - irsend.sendMitsubishi(0xFFF, 32); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 12, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 32, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, true)); -} - -// Decode normal repeated Mitsubishi messages. -TEST(TestDecodeMitsubishi, NormalDecodeWithRepeatAndStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Mitsubishi 16-bit message with 2 repeats. - irsend.reset(); - irsend.sendMitsubishi(0xC2B8, MITSUBISHI_BITS, 2); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); - EXPECT_EQ(0xC2B8, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - // Normal Mitsubishi 16-bit message with 0 repeats. - irsend.reset(); - irsend.sendMitsubishi(0xC2B8, MITSUBISHI_BITS, 0); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); - EXPECT_EQ(0xC2B8, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); -} - -// Decode unsupported Mitsubishi messages. -TEST(TestDecodeMitsubishi, DecodeWithNonStrictValues) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - irsend.sendMitsubishi(0x0, 8); // Illegal sized Mitsubishi 8-bit message. - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, 8, false)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(8, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, false)); - - irsend.reset(); - // Illegal sized Mitsubishi 64-bit message. - irsend.sendMitsubishi(0xFEDCBA9876543210, 64); - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, 64, false)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(64, irsend.capture.bits); - EXPECT_EQ(0xFEDCBA9876543210, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - // Should fail when we are after a shorter message than we got. - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 8, false)); -} - -// Decode a 'real' example via GlobalCache -TEST(TestDecodeMitsubishi, DecodeGlobalCacheExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Mitsubishi "Power On" (16-bit) code from Global Cache. - uint16_t gc_test[37] = {33000, 1, 1, 10, 70, 10, 70, 10, 70, 10, 30, 10, 30, - 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, 10, 30, - 10, 30, 10, 30, 10, 30, 10, 70, 10, 30, 10, 936}; - irsend.sendGC(gc_test, 37); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture)); - EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); - EXPECT_EQ(0xE242, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); -} - -// Fail to decode a non-Mitsubishi example via GlobalCache -TEST(TestDecodeMitsubishi, FailToDecodeNonMitsubishiExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; - irsend.sendGC(gc_test, 39); - irsend.makeDecodeResult(); - - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, MITSUBISHI_BITS, - false)); -} - -// Tests for Mitsubishi A/C methods. - -// Test sending typical data only. -TEST(TestSendMitsubishiAC, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t mitsub_code[MITSUBISHI_AC_STATE_LENGTH] = { - 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, - 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; - irsend.reset(); - irsend.sendMitsubishiAC(mitsub_code); - EXPECT_EQ( - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m440s17100" - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m440s17100", irsend.outputStr()); -} - -// Test sending with repeats. -TEST(TestSendMitsubishiAC, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - uint8_t mitsub_code[MITSUBISHI_AC_STATE_LENGTH] = { - 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, - 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; - - irsend.sendMitsubishiAC(mitsub_code, MITSUBISHI_AC_STATE_LENGTH, 0); - EXPECT_EQ( - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m440s17100", irsend.outputStr()); - - irsend.reset(); - irsend.sendMitsubishiAC(mitsub_code, MITSUBISHI_AC_STATE_LENGTH, 2); - EXPECT_EQ( - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m440s17100" - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m440s17100" - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m440s17100", irsend.outputStr()); -} - -// Test sending atypical sizes. -TEST(TestSendMitsubishiAC, SendUnexpectedSizes) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t mitsub_short_code[17] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, - 0x08, 0x06, 0x30, 0x45, 0x67, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t mitsub_long_code[19] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, - 0x08, 0x06, 0x30, 0x45, 0x67, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, - 0x00}; - irsend.reset(); - irsend.sendMitsubishiAC(mitsub_short_code, 17); - ASSERT_EQ("", irsend.outputStr()); - - irsend.reset(); - irsend.sendMitsubishiAC(mitsub_long_code, 19); - ASSERT_EQ( - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m440s17100" - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m440s17100", irsend.outputStr()); -} - -// Tests for IRMitsubishiAC class. - -TEST(TestMitsubishiACClass, Power) { - IRMitsubishiAC mitsub(0); - mitsub.begin(); - - mitsub.on(); - EXPECT_TRUE(mitsub.getPower()); - - mitsub.off(); - EXPECT_FALSE(mitsub.getPower()); - - mitsub.setPower(true); - EXPECT_TRUE(mitsub.getPower()); - - mitsub.setPower(false); - EXPECT_FALSE(mitsub.getPower()); -} - -TEST(TestMitsubishiACClass, Temperature) { - IRMitsubishiAC mitsub(0); - mitsub.begin(); - - mitsub.setTemp(0); - EXPECT_EQ(MITSUBISHI_AC_MIN_TEMP, mitsub.getTemp()); - - mitsub.setTemp(255); - EXPECT_EQ(MITSUBISHI_AC_MAX_TEMP, mitsub.getTemp()); - - mitsub.setTemp(MITSUBISHI_AC_MIN_TEMP); - EXPECT_EQ(MITSUBISHI_AC_MIN_TEMP, mitsub.getTemp()); - - mitsub.setTemp(MITSUBISHI_AC_MAX_TEMP); - EXPECT_EQ(MITSUBISHI_AC_MAX_TEMP, mitsub.getTemp()); - - mitsub.setTemp(MITSUBISHI_AC_MIN_TEMP - 1); - EXPECT_EQ(MITSUBISHI_AC_MIN_TEMP, mitsub.getTemp()); - - mitsub.setTemp(MITSUBISHI_AC_MAX_TEMP + 1); - EXPECT_EQ(MITSUBISHI_AC_MAX_TEMP, mitsub.getTemp()); - - mitsub.setTemp(17); - EXPECT_EQ(17, mitsub.getTemp()); - - mitsub.setTemp(21); - EXPECT_EQ(21, mitsub.getTemp()); - - mitsub.setTemp(25); - EXPECT_EQ(25, mitsub.getTemp()); - - mitsub.setTemp(30); - EXPECT_EQ(30, mitsub.getTemp()); -} - -TEST(TestMitsubishiACClass, OperatingMode) { - IRMitsubishiAC mitsub(0); - mitsub.begin(); - - mitsub.setMode(MITSUBISHI_AC_AUTO); - EXPECT_EQ(MITSUBISHI_AC_AUTO, mitsub.getMode()); - - mitsub.setMode(MITSUBISHI_AC_COOL); - EXPECT_EQ(MITSUBISHI_AC_COOL, mitsub.getMode()); - - mitsub.setMode(MITSUBISHI_AC_HEAT); - EXPECT_EQ(MITSUBISHI_AC_HEAT, mitsub.getMode()); - - mitsub.setMode(MITSUBISHI_AC_DRY); - EXPECT_EQ(MITSUBISHI_AC_DRY, mitsub.getMode()); - - mitsub.setMode(MITSUBISHI_AC_AUTO + 1); - EXPECT_EQ(MITSUBISHI_AC_AUTO, mitsub.getMode()); - - mitsub.setMode(255); - EXPECT_EQ(MITSUBISHI_AC_AUTO, mitsub.getMode()); -} - -TEST(TestMitsubishiACClass, VaneMode) { - IRMitsubishiAC mitsub(0); - mitsub.begin(); - - mitsub.setVane(MITSUBISHI_AC_VANE_AUTO); - EXPECT_EQ(MITSUBISHI_AC_VANE_AUTO, mitsub.getVane()); - - mitsub.setVane(MITSUBISHI_AC_VANE_AUTO + 1); - EXPECT_EQ(MITSUBISHI_AC_VANE_AUTO + 1, mitsub.getVane()); - - mitsub.setVane(MITSUBISHI_AC_VANE_AUTO_MOVE); - EXPECT_EQ(MITSUBISHI_AC_VANE_AUTO_MOVE, mitsub.getVane()); - - mitsub.setVane(MITSUBISHI_AC_VANE_AUTO_MOVE + 1); - EXPECT_EQ(MITSUBISHI_AC_VANE_AUTO_MOVE, mitsub.getVane()); - - mitsub.setVane(MITSUBISHI_AC_VANE_AUTO_MOVE - 1); - EXPECT_EQ(MITSUBISHI_AC_VANE_AUTO_MOVE - 1, mitsub.getVane()); -} - -TEST(TestMitsubishiACClass, FanSpeed) { - IRMitsubishiAC mitsub(0); - mitsub.begin(); - - mitsub.setFan(MITSUBISHI_AC_FAN_AUTO); - EXPECT_EQ(MITSUBISHI_AC_FAN_AUTO, mitsub.getFan()); - - mitsub.setFan(255); - EXPECT_EQ(MITSUBISHI_AC_FAN_REAL_MAX, mitsub.getFan()); - - mitsub.setFan(MITSUBISHI_AC_FAN_MAX); - EXPECT_EQ(MITSUBISHI_AC_FAN_REAL_MAX, mitsub.getFan()); - - mitsub.setFan(MITSUBISHI_AC_FAN_MAX - 1); - EXPECT_EQ(MITSUBISHI_AC_FAN_MAX - 1, mitsub.getFan()); - - mitsub.setFan(1); - EXPECT_EQ(1, mitsub.getFan()); - - mitsub.setFan(2); - EXPECT_EQ(2, mitsub.getFan()); - - mitsub.setFan(3); - EXPECT_EQ(3, mitsub.getFan()); - - mitsub.setFan(4); - EXPECT_EQ(4, mitsub.getFan()); - - mitsub.setFan(MITSUBISHI_AC_FAN_SILENT); - EXPECT_EQ(MITSUBISHI_AC_FAN_SILENT, mitsub.getFan()); - - mitsub.setFan(MITSUBISHI_AC_FAN_SILENT + 1); - EXPECT_EQ(MITSUBISHI_AC_FAN_REAL_MAX, mitsub.getFan()); -} - -TEST(TestMitsubishiACClass, MessageConstuction) { - IRMitsubishiAC mitsub(0); - IRsendTest irsend(4); - mitsub.begin(); - irsend.begin(); - - mitsub.setFan(1); - mitsub.setMode(MITSUBISHI_AC_COOL); - mitsub.setTemp(27); - mitsub.setVane(3); - mitsub.on(); - - // Check everything for kicks. - EXPECT_EQ(1, mitsub.getFan()); - EXPECT_EQ(MITSUBISHI_AC_COOL, mitsub.getMode()); - EXPECT_EQ(27, mitsub.getTemp()); - EXPECT_EQ(3, mitsub.getVane()); - EXPECT_TRUE(mitsub.getPower()); - - irsend.reset(); - irsend.sendMitsubishiAC(mitsub.getRaw()); - EXPECT_EQ( - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s1300m450s1300m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s1300m450s420" - "m440s17100" - "m3400s1750" - "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" - "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420m450s420" - "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" - "m450s1300m450s420m450s420m450s1300m450s1300m450s420m450s1300m450s420" - "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" - "m450s420m450s420m450s420m450s1300m450s420m450s420m450s1300m450s420" - "m440s17100", irsend.outputStr()); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Nikai_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Nikai_test.cpp deleted file mode 100644 index 0eea2bc40..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Nikai_test.cpp +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendNikai(). -// Test sending typical data only. -TEST(TestSendNikai, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendNikai(0xD5F2A); // Nikai TV Power Off. - EXPECT_EQ("m4000s4000" - "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" - "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" - "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" - "m500s2000m500s1000m500s2000m500s8500", - irsend.outputStr()); - - irsend.reset(); -} - -// Test sending with different repeats. -TEST(TestSendNikai, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendNikai(0xD5F2A, NIKAI_BITS, 1); // 1 repeat. - EXPECT_EQ("m4000s4000" - "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" - "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" - "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" - "m500s2000m500s1000m500s2000m500s8500" - "m4000s4000" - "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" - "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" - "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" - "m500s2000m500s1000m500s2000m500s8500", - irsend.outputStr()); - irsend.sendNikai(0xD5F2A, NIKAI_BITS, 2); // 2 repeat. - EXPECT_EQ("m4000s4000" - "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" - "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" - "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" - "m500s2000m500s1000m500s2000m500s8500" - "m4000s4000" - "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" - "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" - "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" - "m500s2000m500s1000m500s2000m500s8500" - "m4000s4000" - "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" - "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" - "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" - "m500s2000m500s1000m500s2000m500s8500", - irsend.outputStr()); -} - -// Tests for decodeNikai(). - -// Decode normal Nikai messages. -TEST(TestDecodeNikai, NormalDecodeWithStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Nikai 24-bit message. - irsend.reset(); - irsend.sendNikai(0x123456); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, true)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(NIKAI_BITS, irsend.capture.bits); - EXPECT_EQ(0x123456, irsend.capture.value); - - irsend.reset(); - irsend.sendNikai(0x101); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, true)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(NIKAI_BITS, irsend.capture.bits); - EXPECT_EQ(0x101, irsend.capture.value); -} - -// Decode normal repeated Nikai messages. -TEST(TestDecodeNikai, NormalDecodeWithRepeatAndStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Nikai 24-bit message. - irsend.reset(); - irsend.sendNikai(0xD5F2A, NIKAI_BITS, 2); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, true)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(NIKAI_BITS, irsend.capture.bits); - EXPECT_EQ(0xD5F2A, irsend.capture.value); -} - -TEST(TestDecodeNikai, NormalDecodeWithNonStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Illegal under length (16-bit) message - irsend.reset(); - irsend.sendNikai(0x0, 16); - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, true)); - // And it should fail when we expect more bits. - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, false)); - - // Should pass if strict off if we ask for correct nr. of bits sent. - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, 16, false)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(16, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - - // Should fail as we are expecting less bits than there are. - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, 12, false)); -} - -// Decode (non-standard) 64-bit messages. -// Decode unsupported Nikai messages. -TEST(TestDecodeNikai, Decode64BitMessages) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Illegal size Nikai 64-bit message. - irsend.sendNikai(0xFFFFFFFFFFFFFFFF, 64); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, 64, false)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(64, irsend.capture.bits); - EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); -} - -// Decode real example via Issue #309 -TEST(TestDecodeNikai, DecodeExamples) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Nikai TV Power Off from Issue #309 - uint16_t rawdata_off[100] = {4060, 3918, - 508, 2004, 508, 2002, 510, 2002, 508, 2004, 506, 1050, 508, 1048, - 510, 2004, 508, 1048, 508, 2002, 510, 1050, 508, 2004, 510, 1048, - 508, 1050, 508, 1048, 508, 1050, 508, 1050, 508, 2004, 508, 2002, - 510, 1048, 508, 2004, 508, 1050, 506, 2004, 508, 1048, 510, 2002, - 456, 8446, - 3956, 3998, - 508, 2004, 508, 2002, 508, 2004, 508, 1978, 532, 1050, 508, 1050, - 508, 2002, 508, 1050, 508, 2004, 508, 1050, 508, 2002, 510, 1050, - 508, 1050, 508, 1048, 508, 1050, 508, 1050, 508, 2002, 510, 2002, - 508, 1050, 508, 2002, 510, 1050, 508, 2002, 508}; - irsend.sendRaw(rawdata_off, 100, 38); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(NIKAI_BITS, irsend.capture.bits); - EXPECT_EQ(0xD5F2A, irsend.capture.value); - - // Nikai TV Volume Up from Issue #309 - uint16_t rawdata_volup[52] = {3972, 4002, - 504, 1982, 526, 2010, 502, 2010, 502, 2010, 500, 1056, 502, 1056, - 502, 2010, 500, 1056, 502, 2010, 502, 2010, 500, 2010, 502, 2010, - 502, 1056, 502, 1056, 502, 1056, 500, 1056, 502, 2010, 502, 2010, - 500, 1056, 502, 2008, 502, 1054, 504, 1054, 504, 1054, 500, 1056, - 450}; - - irsend.reset(); - irsend.sendRaw(rawdata_volup, 52, 38); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(NIKAI, irsend.capture.decode_type); - EXPECT_EQ(NIKAI_BITS, irsend.capture.bits); - EXPECT_EQ(0xD0F2F, irsend.capture.value); -} - -// Fail to decode a non-Nikai example via GlobalCache -TEST(TestDecodeNikai, FailToDecodeNonNikaiExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - uint16_t gc_test[71] = {38000, 1, 1, 172, 172, 22, 64, 22, 64, 22, 64, 22, 21, - 22, 21, 22, 21, 22, 11, 22, 21, 22, 128, 22, 64, 22, - 64, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 64, - 22, 21, 22, 21, 22, 64, 22, 64, 22, 21, 22, 21, 22, - 64, 22, 21, 22, 64, 22, 64, 22, 21, 22, 21, 22, 64, - 22, 64, 22, 21, 22, 1820}; - irsend.sendGC(gc_test, 71); - irsend.makeDecodeResult(); - - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, NIKAI_BITS, false)); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Panasonic_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Panasonic_test.cpp deleted file mode 100644 index 3f27b90bf..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Panasonic_test.cpp +++ /dev/null @@ -1,457 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for encodePanasonic(). - -TEST(TestEncodePanasonic, General) { - IRsendTest irsend(4); - EXPECT_EQ(0x0, irsend.encodePanasonic(0, 0, 0, 0)); - EXPECT_EQ(0x101010101, irsend.encodePanasonic(1, 1, 1, 1)); - EXPECT_EQ(0xFFFF, irsend.encodePanasonic(0, 0, 0, 0xFF)); - EXPECT_EQ(0xFF00FF, irsend.encodePanasonic(0, 0, 0xFF, 0)); - EXPECT_EQ(0xFF0000FF, irsend.encodePanasonic(0, 0xFF, 0, 0)); - EXPECT_EQ(0xFFFF00000000, irsend.encodePanasonic(0xFFFF, 0, 0, 0)); - EXPECT_EQ(0xFFFFFFFFFFFF, irsend.encodePanasonic(0xFFFF, 0xFF, 0xFF, 0xFF)); - EXPECT_EQ(0x40040190ED7C, irsend.encodePanasonic(0x4004, 0x01, 0x90, 0xED)); -} - - -// Tests for sendPanasonic64(). - -// Test sending typical data only. -TEST(TestSendPanasonic64, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendPanasonic64(0x0); - EXPECT_EQ( - "m3456s1728" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s129600", irsend.outputStr()); - - irsend.reset(); - irsend.sendPanasonic64(0x40040190ED7C); - EXPECT_EQ( - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600", irsend.outputStr()); - - irsend.reset(); - irsend.sendPanasonic64(0xFFFFFFFFFFFF); - EXPECT_EQ( - "m3456s1728" - "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" - "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" - "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" - "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" - "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" - "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" - "m432s129600", irsend.outputStr()); -} - -// Test sending with different repeats. -TEST(TestSendPanasonic64, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendPanasonic64(0x40040190ED7C, PANASONIC_BITS, 0); // 0 repeats. - EXPECT_EQ( - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600", irsend.outputStr()); - - irsend.reset(); - irsend.sendPanasonic64(0x40040190ED7C, PANASONIC_BITS, 1); // 1 repeat. - EXPECT_EQ( - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600" - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600", irsend.outputStr()); - - irsend.sendPanasonic64(0x40040190ED7C, PANASONIC_BITS, 2); // 2 repeats. - EXPECT_EQ( - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600" - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600" - "m3456s1728" - "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" - "m432s129600", irsend.outputStr()); -} - -// Test sending an atypical data size. -TEST(TestSendPanasonic64, SendUnusualSize) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendPanasonic64(0x0, 8); - EXPECT_EQ( - "m3456s1728" - "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" - "m432s129600", irsend.outputStr()); - - irsend.reset(); - irsend.sendPanasonic64(0x1234567890ABCDEF, 64); - EXPECT_EQ( - "m3456s1728" - "m432s432m432s432m432s432m432s1296m432s432m432s432m432s1296m432s432" - "m432s432m432s432m432s1296m432s1296m432s432m432s1296m432s432m432s432" - "m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296m432s432" - "m432s432m432s1296m432s1296m432s1296m432s1296m432s432m432s432m432s432" - "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" - "m432s1296m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296" - "m432s1296m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s1296" - "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s1296m432s1296" - "m432s129600", irsend.outputStr()); -} - -// Tests for sendPanasonic(). - -TEST(TestSendPanasonic, CompareToSendPanasonic64) { - IRsendTest panasonic(4); - IRsendTest panasonic64(0); - - panasonic.begin(); - panasonic64.begin(); - - panasonic.reset(); - panasonic64.reset(); - - panasonic.sendPanasonic(0x4004, 0x0190ED7C); - panasonic64.sendPanasonic64(0x40040190ED7C); - EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); - - panasonic.sendPanasonic(0x0, 0x0); - panasonic64.sendPanasonic64(0x0); - EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); - - panasonic.sendPanasonic(0x0, 0x0, 8); - panasonic64.sendPanasonic64(0x0, 8); - EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); - - panasonic.sendPanasonic(0x1234, 0x567890AB, 64); - panasonic64.sendPanasonic64(0x1234567890AB, 64); - EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); - - panasonic.sendPanasonic(0x1234, 0x567890AB, PANASONIC_BITS, 2); - panasonic64.sendPanasonic64(0x1234567890AB, PANASONIC_BITS, 2); - EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); -} - -// Tests for decodePanasonic(). - -// Decode normal Panasonic messages. -TEST(TestDecodePanasonic, NormalDecodeWithStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Panasonic 48-bit message. - irsend.reset(); - irsend.sendPanasonic64(0x40040190ED7C); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040190ED7C, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x0190ED7C, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - // Synthesised Normal Panasonic 48-bit message. - irsend.reset(); - irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 0x12, 0x34, 0x56)); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x400412345670, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x12345670, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - // Synthesised Normal Panasonic 48-bit message. - irsend.reset(); - irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 0x1, 0x1, 0x1)); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x400401010101, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x1010101, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); -} - -// Decode normal repeated Panasonic messages. -TEST(TestDecodePanasonic, NormalDecodeWithRepeatAndStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Panasonic 48-bit message with 2 repeats. - irsend.reset(); - irsend.sendPanasonic64(0x40040190ED7C, PANASONIC_BITS, 2); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040190ED7C, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x190ED7C, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - irsend.makeDecodeResult(2 * PANASONIC_BITS + 4); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040190ED7C, irsend.capture.value); - - irsend.makeDecodeResult(2 * (2 * PANASONIC_BITS + 4)); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040190ED7C, irsend.capture.value); -} - -// Decode Panasonic messages with unsupported values. -TEST(TestDecodePanasonic, DecodeWithNonStrictValues) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - irsend.sendPanasonic64(0x0); // Illegal value Panasonic 48-bit message. - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, false)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - - irsend.reset(); - // Illegal address/Manufacturer code. The rest is legal. - irsend.sendPanasonic64(irsend.encodePanasonic(0, 1, 2, 3)); - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, false)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x1020300, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x1020300, irsend.capture.command); -} - -// Decode Panasonic messages with unsupported size/lengths. -TEST(TestDecodePanasonic, DecodeWithNonStrictSize) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - irsend.sendPanasonic64(0x12345678, 32); // Illegal size Panasonic message. - irsend.makeDecodeResult(); - - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - - irsend.makeDecodeResult(); - // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 32, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 32, false)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(32, irsend.capture.bits); - EXPECT_EQ(0x12345678, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x12345678, irsend.capture.command); - - // Illegal over length (56-bit) message. - irsend.reset(); - irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 1, 2, 3), 56); - irsend.makeDecodeResult(); - - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - // Shouldn't pass if strict off and wrong bit size. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, false)); - // Re-decode with correct bit size. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 56, true)); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 56, false)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(56, irsend.capture.bits); - EXPECT_EQ(0x400401020300, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x01020300, irsend.capture.command); -} - -// Decode (non-standard) 64-bit messages. -TEST(TestDecodePanasonic, Decode64BitMessages) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Illegal value & size Panasonic 64-bit message. - irsend.sendPanasonic64(0xFFFFFFFFFFFFFFFF, 64); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 64, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 64, false)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(64, irsend.capture.bits); - EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); - EXPECT_EQ(0xFFFFFFFF, irsend.capture.address); - EXPECT_EQ(0xFFFFFFFF, irsend.capture.command); -} - -// Decode a 'real' example via GlobalCache -TEST(TestDecodePanasonic, DecodeGlobalCacheExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Panasonic code from Global Cache. - uint16_t gc_test[103] = {37000, 1, 1, 126, 64, 16, 17, 16, 49, 15, 16, 16, 16, - 16, 16, 16, 17, 15, 17, 15, 17, 15, 17, 15, 16, 16, - 16, 16, 16, 16, 17, 15, 49, 16, 16, 16, 16, 16, 17, - 15, 17, 15, 17, 15, 17, 15, 16, 16, 16, 16, 16, 16, - 49, 15, 49, 16, 17, 15, 17, 15, 49, 16, 16, 16, 17, - 16, 17, 15, 17, 15, 49, 16, 49, 15, 49, 16, 17, 16, - 49, 15, 49, 16, 17, 15, 48, 16, 16, 16, 49, 15, 48, - 16, 49, 15, 49, 16, 49, 15, 17, 15, 16, 16, 2721}; - irsend.sendGC(gc_test, 103); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040190ED7C, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x0190ED7C, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040190ED7C, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x0190ED7C, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); -} - -// Fail to decode a non-Panasonic example via GlobalCache -TEST(TestDecodePanasonic, FailToDecodeNonPanasonicExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; - irsend.sendGC(gc_test, 39); - irsend.makeDecodeResult(); - - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture)); - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, false)); -} - -// Failing to decode Panasonic in Issue #245 -TEST(TestDecodePanasonic, DecodeIssue245) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - - uint16_t rawData[100] = {3550, 1750, 500, 450, 500, 1300, 500, 450, 500, 450, - 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, - 500, 450, 500, 450, 500, 450, 500, 450, 500, 1300, - 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, - 500, 450, 500, 450, 500, 450, 500, 450, 500, 1300, - 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, - 500, 450, 500, 450, 500, 450, 500, 1300, 500, 450, - 500, 1300, 500, 1300, 500, 1300, 500, 1300, 500, 450, - 500, 450, 500, 1300, 500, 450, 500, 1300, 500, 1300, - 500, 1300, 500, 1300, 500, 450, 500, 1300, 500, 5000}; - - irsend.sendRaw(rawData, 100, 37); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040100BCBD, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x100BCBD, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); - - irsend.reset(); - irsend.sendRaw(rawData, 99, 37); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x40040100BCBD, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x100BCBD, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Samsung_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Samsung_test.cpp deleted file mode 100644 index 8c35ebebf..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Samsung_test.cpp +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendSAMSUNG(). - -// Test sending typical data only. -TEST(TestSendSamsung, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSAMSUNG(0xE0E09966); // Samsung TV Power On. - EXPECT_EQ("m4480s4480" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" - "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s560m560s1680m560s1680m560s560m560s108080", - irsend.outputStr()); - - irsend.reset(); -} - -// Test sending with different repeats. -TEST(TestSendSamsung, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSAMSUNG(0xE0E09966, SAMSUNG_BITS, 1); // 1 repeat. - EXPECT_EQ("m4480s4480" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" - "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s560m560s1680m560s1680m560s560m560s108080" - "m4480s4480" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" - "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s560m560s1680m560s1680m560s560m560s108080" - , irsend.outputStr()); - irsend.sendSAMSUNG(0xE0E09966, SAMSUNG_BITS, 2); // 2 repeats. - EXPECT_EQ("m4480s4480" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" - "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s560m560s1680m560s1680m560s560m560s108080" - "m4480s4480" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" - "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s560m560s1680m560s1680m560s560m560s108080" - "m4480s4480" - "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" - "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" - "m560s560m560s1680m560s1680m560s560m560s108080" - , irsend.outputStr()); -} - -// Tests for encodeSAMSUNG(). - -TEST(TestEncodeSamsung, NormalEncoding) { - IRsendTest irsend(4); - EXPECT_EQ(0xFF, irsend.encodeSAMSUNG(0, 0)); - EXPECT_EQ(0x8080807F, irsend.encodeSAMSUNG(1, 1)); - EXPECT_EQ(0xF8F805FA, irsend.encodeSAMSUNG(0x1F, 0xA0)); - EXPECT_EQ(0xA0A0CC33, irsend.encodeSAMSUNG(0x05, 0x33)); - EXPECT_EQ(0xFFFFFF00, irsend.encodeSAMSUNG(0xFF, 0xFF)); - EXPECT_EQ(0xE0E09966, irsend.encodeSAMSUNG(0x07, 0x99)); -} - -// Tests for decodeSAMSUNG(). - -// Decode normal Samsung messages. -TEST(TestDecodeSamsung, NormalDecodeWithStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Samsung 32-bit message. - irsend.reset(); - irsend.sendSAMSUNG(0xE0E09966); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0xE0E09966, irsend.capture.value); - EXPECT_EQ(0x07, irsend.capture.address); - EXPECT_EQ(0x99, irsend.capture.command); - - // Synthesised Normal Samsung 32-bit message. - irsend.reset(); - irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x07, 0x99)); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0xE0E09966, irsend.capture.value); - EXPECT_EQ(0x07, irsend.capture.address); - EXPECT_EQ(0x99, irsend.capture.command); - - // Synthesised Normal Samsung 32-bit message. - irsend.reset(); - irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x1, 0x1)); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0x8080807F, irsend.capture.value); - EXPECT_EQ(0x1, irsend.capture.address); - EXPECT_EQ(0x1, irsend.capture.command); -} - -// Decode normal repeated Samsung messages. -TEST(TestDecodeSamsung, NormalDecodeWithRepeatAndStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Normal Samsung 32-bit message. - irsend.reset(); - irsend.sendSAMSUNG(0xE0E09966, SAMSUNG_BITS, 2); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0xE0E09966, irsend.capture.value); - EXPECT_EQ(0x07, irsend.capture.address); - EXPECT_EQ(0x99, irsend.capture.command); -} - -// Decode unsupported Samsung messages. -TEST(TestDecodeSamsung, DecodeWithNonStrictValues) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSAMSUNG(0x0); // Illegal value Samsung 32-bit message. - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, false)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - - irsend.reset(); - irsend.sendSAMSUNG(0x12345678); // Illegal value Samsung 32-bit message. - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, false)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0x12345678, irsend.capture.value); - EXPECT_EQ(0x48, irsend.capture.address); - EXPECT_EQ(0x6A, irsend.capture.command); - - // Illegal over length (36-bit) message. - irsend.reset(); - irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0, 0), 36); - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - // Shouldn't pass if strict off and wrong expected bit size. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, false)); - // Re-decode with correct bit size. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, 36, true)); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 36, false)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(36, irsend.capture.bits); - EXPECT_EQ(0xFF, irsend.capture.value); // We told it to expect 8 bits less. - EXPECT_EQ(0x00, irsend.capture.address); - EXPECT_EQ(0x00, irsend.capture.command); - - // Illegal under length (16-bit) message - irsend.reset(); - irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x0, 0x0), 16); - irsend.makeDecodeResult(); - // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - // And it should fail when we expect more bits. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, false)); - - // Should pass if strict off if we ask for correct nr. of bits sent. - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 16, false)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(16, irsend.capture.bits); - EXPECT_EQ(0xFF, irsend.capture.value); // We told it to expect 4 bits less. - EXPECT_EQ(0x00, irsend.capture.address); - EXPECT_EQ(0x00, irsend.capture.command); - - // Should fail as we are expecting less bits than there are. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, 12, false)); -} - -// Decode (non-standard) 64-bit messages. -// Decode unsupported Samsung messages. -TEST(TestDecodeSamsung, Decode64BitMessages) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Illegal value & size Samsung 64-bit message. - irsend.sendSAMSUNG(0xFFFFFFFFFFFFFFFF, 64); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 64, false)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(64, irsend.capture.bits); - EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); - EXPECT_EQ(0xFF, irsend.capture.address); - EXPECT_EQ(0xFF, irsend.capture.command); -} - -// Decode a 'real' example via GlobalCache -TEST(TestDecodeSamsung, DecodeGlobalCacheExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Samsung TV Power On from Global Cache. - uint16_t gc_test[71] = {38000, 1, 1, 172, 172, 22, 64, 22, 64, 22, 64, 22, 21, - 22, 21, 22, 21, 22, 21, 22, 21, 22, 64, 22, 64, 22, - 64, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 64, - 22, 21, 22, 21, 22, 64, 22, 64, 22, 21, 22, 21, 22, - 64, 22, 21, 22, 64, 22, 64, 22, 21, 22, 21, 22, 64, - 22, 64, 22, 21, 22, 1820}; - irsend.sendGC(gc_test, 71); - irsend.makeDecodeResult(); - - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture)); - EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); - EXPECT_EQ(0xE0E09966, irsend.capture.value); - EXPECT_EQ(0x07, irsend.capture.address); - EXPECT_EQ(0x99, irsend.capture.command); -} - -// Fail to decode a non-Samsung example via GlobalCache -TEST(TestDecodeSamsung, FailToDecodeNonSamsungExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[71] = {38000, 1, 1, 172, 172, 22, 64, 22, 64, 22, 64, 22, 21, - 22, 21, 22, 21, 22, 11, 22, 21, 22, 128, 22, 64, 22, - 64, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 64, - 22, 21, 22, 21, 22, 64, 22, 64, 22, 21, 22, 21, 22, - 64, 22, 21, 22, 64, 22, 64, 22, 21, 22, 21, 22, 64, - 22, 64, 22, 21, 22, 1820}; - irsend.sendGC(gc_test, 71); - irsend.makeDecodeResult(); - - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, SAMSUNG_BITS, false)); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sherwood_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Sherwood_test.cpp deleted file mode 100644 index b5750b3b1..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sherwood_test.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendSherwood(). - -// Test sending typical data only. -TEST(TestSendSherwood, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSherwood(0xC1A28877); - EXPECT_EQ("m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" - "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680" - "m560s1680m560s560m560s1680m560s1680m560s1680m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); -} - -// Test sending typical data with extra repeats. -TEST(TestSendSherwood, SendDataWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSherwood(0xC1A28877, 32, 2); - EXPECT_EQ("m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" - "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680" - "m560s1680m560s560m560s1680m560s1680m560s1680m560s108080" - "m8960s2240m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); -} - -// Test sending typical data with explicit no repeats. -TEST(TestSendSherwood, SendDataWithZeroRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSherwood(0xC1A28877, 32, 0); - // Should have a single NEC repeat, as we always send one. - EXPECT_EQ("m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" - "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" - "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" - "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680" - "m560s1680m560s560m560s1680m560s1680m560s1680m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); -} - -// Test that a typical Sherwood send decodes as the appropriate NEC value. -TEST(TestSendSherwood, DecodesAsNEC) { - IRsendTest irsend(4); - IRrecv irrecv(0); - irsend.begin(); - - irsend.reset(); - irsend.sendSherwood(0xC1A28877); - irsend.makeDecodeResult(); - - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); - EXPECT_EQ(0xC1A28877, irsend.capture.value); - EXPECT_EQ(0x4583, irsend.capture.address); - EXPECT_EQ(0x11, irsend.capture.command); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sony_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Sony_test.cpp deleted file mode 100644 index 76d351441..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sony_test.cpp +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendSony(). - -// Test sending typical data only. -TEST(TestSendSony, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSony(0); - // We expect three 20-bit commands to be sent. - EXPECT_EQ("m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m600s600m600s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m600s600m600s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m600s600m600s600m600s600m600s45600", irsend.outputStr()); - - irsend.reset(); - irsend.sendSony(0x240C, SONY_20_BITS); - // We expect three 20-bit commands to be sent. - EXPECT_EQ("m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600", irsend.outputStr()); - - irsend.reset(); - irsend.sendSony(0x240C, SONY_15_BITS); - // We expect three 15-bit commands to be sent. - EXPECT_EQ("m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" - "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" - "m600s45600" - "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" - "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" - "m600s45600" - "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" - "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" - "m600s45600", irsend.outputStr()); - - irsend.reset(); - irsend.sendSony(0xA90, SONY_12_BITS); - // We expect three 15-bit commands to be sent. - EXPECT_EQ("m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" - "m600s600m1200s600m600s600m600s600m600s600m600s45600" - "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" - "m600s600m1200s600m600s600m600s600m600s600m600s45600" - "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" - "m600s600m1200s600m600s600m600s600m600s600m600s45600", - irsend.outputStr()); -} - -// Test sending with different repeats. -TEST(TestSendSony, SendWithDiffRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSony(0x240C, SONY_20_BITS, 0); // Send a command with 0 repeats. - EXPECT_EQ("m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600", irsend.outputStr()); - irsend.sendSony(0x240C, SONY_20_BITS, 1); // Send a command with 1 repeat. - EXPECT_EQ("m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600", irsend.outputStr()); - irsend.sendSony(0x240C, SONY_20_BITS, 3); // Send a command with 3 repeats. - EXPECT_EQ("m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600" - "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" - "m600s600m1200s600m1200s600m600s600m600s45600", irsend.outputStr()); -} - -// Tests for encodeSony(). - -TEST(TestEncodeSony, NormalSonyEncoding) { - IRsendTest irsend(4); - EXPECT_EQ(0x0, irsend.encodeSony(SONY_12_BITS, 0, 0)); - EXPECT_EQ(0xA90, irsend.encodeSony(SONY_12_BITS, 21, 1)); - EXPECT_EQ(0xFFF, irsend.encodeSony(SONY_12_BITS, 0x7F, 0x1F)); - - EXPECT_EQ(0x0, irsend.encodeSony(SONY_15_BITS, 0, 0)); - EXPECT_EQ(0x5480, irsend.encodeSony(SONY_15_BITS, 21, 1)); - EXPECT_EQ(0x5455, irsend.encodeSony(SONY_15_BITS, 21, 0xAA)); - EXPECT_EQ(0x7FFF, irsend.encodeSony(SONY_15_BITS, 0x7F, 0xFF)); - - EXPECT_EQ(0x0, irsend.encodeSony(SONY_20_BITS, 0, 0, 0)); - EXPECT_EQ(0x81080, irsend.encodeSony(SONY_20_BITS, 1, 1, 1)); - EXPECT_EQ(0xFFFFF, irsend.encodeSony(SONY_20_BITS, 0x7F, 0x1F, 0xFF)); -} - -TEST(TestEncodeSony, SonyEncodingWithOversizedValues) { - IRsendTest irsend(4); - EXPECT_EQ(0xFFF, irsend.encodeSony(SONY_12_BITS, 0xFFFF, 0xFFFF)); - - EXPECT_EQ(0x7FFF, irsend.encodeSony(SONY_15_BITS, 0xFFFF, 0xFFFF)); - - EXPECT_EQ(0xFFFFF, irsend.encodeSony(SONY_20_BITS, 0xFFFF, 0xFFFF, 0xFFFF)); -} - -// Tests for decodeSony(). - -// Decode normal Sony messages. -TEST(TestDecodeSony, NormalSonyDecodeWithStrict) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Synthesised Normal Sony 20-bit message. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_20_BITS, 0x1, 0x1, 0x1)); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_20_BITS, irsend.capture.bits); - EXPECT_EQ(0x81080, irsend.capture.value); - EXPECT_EQ(0x1, irsend.capture.address); - EXPECT_EQ(0x81, irsend.capture.command); - - // Synthesised Normal Sony 15-bit message. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_15_BITS, 21, 1), SONY_15_BITS); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_15_BITS, irsend.capture.bits); - EXPECT_EQ(0x5480, irsend.capture.value); - EXPECT_EQ(1, irsend.capture.address); - EXPECT_EQ(21, irsend.capture.command); - - // Synthesised Normal Sony 12-bit message. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_12_BITS, 21, 1), SONY_12_BITS); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_12_BITS, irsend.capture.bits); - EXPECT_EQ(0xA90, irsend.capture.value); - EXPECT_EQ(1, irsend.capture.address); - EXPECT_EQ(21, irsend.capture.command); -} - -// Decode unexpected Sony messages. i.e longer than minimum etc. -TEST(TestDecodeSony, SonyDecodeWithUnexpectedLegalSize) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - // Synthesised Normal Sony 20-bit message decoded when looking for 12-bits - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_20_BITS, 0x1, 0x1, 0x1)); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, SONY_MIN_BITS)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_20_BITS, irsend.capture.bits); - EXPECT_EQ(0x81080, irsend.capture.value); - EXPECT_EQ(0x1, irsend.capture.address); - EXPECT_EQ(0x81, irsend.capture.command); - - // Synthesised Normal Sony 12-bit message when expecting 20-bits. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_12_BITS, 21, 1), SONY_12_BITS); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_12_BITS, irsend.capture.bits); - EXPECT_EQ(0xA90, irsend.capture.value); - EXPECT_EQ(1, irsend.capture.address); - EXPECT_EQ(21, irsend.capture.command); - - // 12-bit message should be regected when using strict and a different size. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_12_BITS, 21, 1), SONY_12_BITS); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); - - // 15-bit message should be regected when using strict and a different size. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_15_BITS, 21, 1), SONY_15_BITS); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - - // 20-bit message should be regected when using strict and a different size. - irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_20_BITS, 1, 1, 1), SONY_20_BITS); - irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); -} - -// Decode unsupported Sony messages. i.e non-standard sizes. -TEST(TestDecodeSony, SonyDecodeWithIllegalSize) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - irsend.sendSony(0xFF, 8); // Illegal 8-bit Sony-like message. - irsend.makeDecodeResult(); - // Should fail with strict on. - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_MIN_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(8, irsend.capture.bits); - EXPECT_EQ(0xFF, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - - irsend.reset(); - irsend.sendSony(0x1FFF, 13); // Illegal 13-bit Sony-like message. - irsend.makeDecodeResult(); - // Should fail with strict on. - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_MIN_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(13, irsend.capture.bits); - EXPECT_EQ(0x1FFF, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - - irsend.reset(); - irsend.sendSony(0x1FFFF, 17); // Illegal 17-bit Sony-like message. - irsend.makeDecodeResult(); - // Should fail with strict on. - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_MIN_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(17, irsend.capture.bits); - EXPECT_EQ(0x1FFFF, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - - irsend.reset(); - irsend.sendSony(0x1FFFFF, 21); // Illegal 21-bit Sony-like message. - irsend.makeDecodeResult(); - // Should fail with strict on. - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_MIN_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_15_BITS, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, SONY_20_BITS, true)); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(21, irsend.capture.bits); - EXPECT_EQ(0x1FFFFF, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - - irsend.reset(); - // Illegal 64-bit (max) Sony-like message. - irsend.sendSony(0xFFFFFFFFFFFFFFFF, 64, 0); - irsend.makeDecodeResult(); - // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(64, irsend.capture.bits); - EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); -} - - -// Decode unsupported Sony messages. i.e non-standard sizes. -TEST(TestDecodeSony, DecodeGlobalCacheExample) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - // Sony "Power On" from Global Cache. - uint16_t gc_test[29] = {40000, 1, 1, 96, 24, 24, 24, 48, 24, 48, 24, 48, 24, - 24, 24, 48, 24, 24, 24, 48, 24, 24, 24, 24, 24, 24, - 24, 24, 1013}; - irsend.sendGC(gc_test, 29); - irsend.makeDecodeResult(); - - // Without strict. - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(12, irsend.capture.bits); - EXPECT_EQ(0x750, irsend.capture.value); - EXPECT_EQ(0x1, irsend.capture.address); - EXPECT_EQ(0x2E, irsend.capture.command); - // With strict and correct size. - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, SONY_12_BITS, true)); -} diff --git a/lib/IRremoteESP8266-2.2.1.02/tools/gc_decode.cpp b/lib/IRremoteESP8266-2.2.1.02/tools/gc_decode.cpp deleted file mode 100644 index 9c3d316ca..000000000 --- a/lib/IRremoteESP8266-2.2.1.02/tools/gc_decode.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// Quick and dirty tool to decode GlobalCache (GC) codes -// Copyright 2017 Jorge Cisneros - -#include -#include -#include -#include -#include "IRsend.h" -#include "IRsend_test.h" - -#define MAX_GC_CODE_LENGHT 512 - -void str_to_uint16(char *str, uint16_t *res) { - char *end; - errno = 0; - intmax_t val = strtoimax(str, &end, 10); - if (errno == ERANGE || val < 0 || val > UINT16_MAX || - end == str || *end != '\0') - return; - *res = (uint16_t) val; -} - -std::string encoding(decode_results *results) { - switch (results->decode_type) { - default: - case UNKNOWN: return "UNKNOWN"; break; - case NEC: return "NEC"; break; - case NEC_LIKE: return "NEC (non-strict)"; break; - case SONY: return "SONY"; break; - case RC5: return "RC5"; break; - case RC5X: return "RC5X"; break; - case RC6: return "RC6"; break; - case RCMM: return "RCMM"; break; - case DISH: return "DISH"; break; - case SHARP: return "SHARP"; break; - case JVC: return "JVC"; break; - case SANYO: return "SANYO"; break; - case SANYO_LC7461: return "SANYO_LC7461"; break; - case MITSUBISHI: return "MITSUBISHI"; break; - case SAMSUNG: return "SAMSUNG"; break; - case LG: return "LG"; break; - case WHYNTER: return "WHYNTER"; break; - case AIWA_RC_T501: return "AIWA_RC_T501"; break; - case PANASONIC: return "PANASONIC"; break; - case DENON: return "DENON"; break; - case COOLIX: return "COOLIX"; break; - case NIKAI: return "NIKAI"; break; - } -} - -void usage_error(char * name) { - std::cerr << "Usage: " << name << " [-raw] " << std::endl; -} - -int main(int argc, char * argv[]) { - int argv_offset = 1; - bool dumpraw = false; - - // Check the invocation/calling usage. - if (argc < 2 || argc > 3) { - usage_error(argv[0]); - return 1; - } - if (strncmp("-raw", argv[argv_offset], 4) == 0) { - dumpraw = true; - argv_offset++; - } - if (argc - argv_offset != 1) { - usage_error(argv[0]); - return 1; - } - - uint16_t gc_test[MAX_GC_CODE_LENGHT]; - int index = 0; - char *pch; - char *saveptr1; - - pch = strtok_r(argv[argv_offset], ",", &saveptr1); - while (pch != NULL && index < MAX_GC_CODE_LENGHT) { - str_to_uint16(pch, &gc_test[index]); - pch = strtok_r(NULL, ",", &saveptr1); - index++; - } - - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - irsend.reset(); - - irsend.sendGC(gc_test, index); - irsend.makeDecodeResult(); - irrecv.decode(&irsend.capture); - - std::cout << "Code GC length " << index << std::endl - << "Code type " << irsend.capture.decode_type - << " (" << encoding(&irsend.capture) << ")" << std::endl - << "Code bits " << irsend.capture.bits << std::endl - << "Code value 0x" << std::hex << irsend.capture.value << std::endl - << "Code address 0x" << std::hex << irsend.capture.address << std::endl - << "Code command 0x" << std::hex << irsend.capture.command << std::endl; - - if (dumpraw || irsend.capture.decode_type == UNKNOWN) - irsend.dumpRawResult(); - - return 0; -} diff --git a/lib/IRremoteESP8266-2.2.1.02/.github/CONTRIBUTING.md b/lib/IRremoteESP8266-2.5.2.03/.github/CONTRIBUTING.md similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/.github/CONTRIBUTING.md rename to lib/IRremoteESP8266-2.5.2.03/.github/CONTRIBUTING.md diff --git a/lib/IRremoteESP8266-2.2.1.02/.github/Contributors.md b/lib/IRremoteESP8266-2.5.2.03/.github/Contributors.md similarity index 91% rename from lib/IRremoteESP8266-2.2.1.02/.github/Contributors.md rename to lib/IRremoteESP8266-2.5.2.03/.github/Contributors.md index 151a0c03d..5f75ea3b4 100644 --- a/lib/IRremoteESP8266-2.2.1.02/.github/Contributors.md +++ b/lib/IRremoteESP8266-2.5.2.03/.github/Contributors.md @@ -10,6 +10,8 @@ - [Jonny Graham](https://github.com/jonnygraham/) - [Stu Fisher](https://github.com/stufisher/) - [Jorge Cisneros](https://github.com/jorgecis/) +- [Denes Varga](https://github.com/denxhun/) +- [Brett T. Warden](https://github.com/bwarden/) All contributors can be found on the [contributors site](https://github.com/markszabo/IRremoteESP8266/graphs/contributors). diff --git a/lib/IRremoteESP8266-2.2.1.02/.github/issue_template.md b/lib/IRremoteESP8266-2.5.2.03/.github/issue_template.md similarity index 84% rename from lib/IRremoteESP8266-2.2.1.02/.github/issue_template.md rename to lib/IRremoteESP8266-2.5.2.03/.github/issue_template.md index 664b99570..024a0398c 100644 --- a/lib/IRremoteESP8266-2.2.1.02/.github/issue_template.md +++ b/lib/IRremoteESP8266-2.5.2.03/.github/issue_template.md @@ -1,7 +1,7 @@ _(Please use this template for reporting issues. You can delete what ever is not relevant. Giving us this information will help us help you faster. Please also read the [FAQ](https://github.com/markszabo/IRremoteESP8266/wiki/Frequently-Asked-Questions) & [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide). Your problem may already have an answer there.)_ ### Version/revison of the library used -_Typically located in the `library.json` file in the root directory of the library. +_Typically located in the `library.json` & `src/IRremoteESP8266.h` files in the root directory of the library. e.g. v2.0.0, or 'master' as at 1st of June, 2017. etc._ ### Expected behavior @@ -30,10 +30,13 @@ _What can we do to (pref. reliably) repeat what is happening?_ _Include all relevant code snippets or links to the actual code files. Tip: [How to quote your code so it is still readable](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code)._ #### Circuit diagram and hardware used (if applicable) -_Link to an image of the circuit diagram used._ +_Link to an image of the circuit diagram used. Part number of the IR receiver module etc._ ### I have followed the steps in the [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide) & read the [FAQ](https://github.com/markszabo/IRremoteESP8266/wiki/Frequently-Asked-Questions) _Yes/No._ +### Has this library/code previously worked as expected for you? +_Yes/No. If "Yes", which version last worked for you?_ + ### Other useful information _More information is always welcome. Be verbose._ diff --git a/lib/IRremoteESP8266-2.2.1.02/.gitignore b/lib/IRremoteESP8266-2.5.2.03/.gitignore similarity index 88% rename from lib/IRremoteESP8266-2.2.1.02/.gitignore rename to lib/IRremoteESP8266-2.5.2.03/.gitignore index 6d57ebaab..23e21ca3e 100644 --- a/lib/IRremoteESP8266-2.2.1.02/.gitignore +++ b/lib/IRremoteESP8266-2.5.2.03/.gitignore @@ -23,6 +23,9 @@ lib/googletest/**/* # GCC pre-compiled headers. **/*.gch +# Python compiled files +**/*.pyc + # Unit Test builds test/*.o test/*.a @@ -32,8 +35,12 @@ test/*_test tools/*.o tools/*.a tools/gc_decode +tools/mode2_decode .pioenvs .piolibdeps .clang_complete .gcc-flags.json + +#Cygwin builds +*.exe diff --git a/lib/IRremoteESP8266-2.2.1.02/.gitmodules b/lib/IRremoteESP8266-2.5.2.03/.gitmodules similarity index 85% rename from lib/IRremoteESP8266-2.2.1.02/.gitmodules rename to lib/IRremoteESP8266-2.5.2.03/.gitmodules index 80925b865..c28fe0509 100644 --- a/lib/IRremoteESP8266-2.2.1.02/.gitmodules +++ b/lib/IRremoteESP8266-2.5.2.03/.gitmodules @@ -1,3 +1,4 @@ [submodule "lib/googletest"] path = lib/googletest url = https://github.com/google/googletest.git + branch = v1.8.x diff --git a/lib/IRremoteESP8266-2.5.2.03/.style.yapf b/lib/IRremoteESP8266-2.5.2.03/.style.yapf new file mode 100644 index 000000000..65fa0ee33 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/.style.yapf @@ -0,0 +1,3 @@ +[style] +based_on_style: google +indent_width: 2 diff --git a/lib/IRremoteESP8266-2.2.1.02/.travis.yml b/lib/IRremoteESP8266-2.5.2.03/.travis.yml similarity index 94% rename from lib/IRremoteESP8266-2.2.1.02/.travis.yml rename to lib/IRremoteESP8266-2.5.2.03/.travis.yml index 33d91ba47..4331425e9 100644 --- a/lib/IRremoteESP8266-2.2.1.02/.travis.yml +++ b/lib/IRremoteESP8266-2.5.2.03/.travis.yml @@ -20,6 +20,7 @@ install: - arduino --board $BD --save-prefs - arduino --pref "compiler.warning_level=all" --save-prefs - sudo apt-get install jq + - sudo pip install pylint script: # Check that everything compiles. - arduino --verify --board $BD $PWD/examples/IRrecvDemo/IRrecvDemo.ino @@ -38,14 +39,17 @@ script: - arduino --verify --board $BD $PWD/examples/LGACSend/LGACSend.ino - arduino --verify --board $BD $PWD/examples/TurnOnArgoAC/TurnOnArgoAC.ino - arduino --verify --board $BD $PWD/examples/IRMQTTServer/IRMQTTServer.ino + - arduino --verify --board $BD $PWD/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino # Also check the tools programs compile. - (cd tools; make all) # Check for lint issues. - shopt -s nullglob - python cpplint.py --extensions=c,cc,cpp,ino --headers=h,hpp {src,test,tools}/*.{h,c,cc,cpp,hpp,ino} examples/*/*.{h,c,cc,cpp,hpp,ino} + - pylint {src,test,tools}/*.py - shopt -u nullglob # Build and run the unit tests. - (cd test; make run) + - (cd tools; make run_tests) # Check the version numbers match. - LIB_VERSION=$(egrep "^#define\s+_IRREMOTEESP8266_VERSION_\s+" src/IRremoteESP8266.h | cut -d\" -f2) - test ${LIB_VERSION} == "$(jq -r .version library.json)" diff --git a/lib/IRremoteESP8266-2.2.1.02/CPPLINT.cfg b/lib/IRremoteESP8266-2.5.2.03/CPPLINT.cfg similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/CPPLINT.cfg rename to lib/IRremoteESP8266-2.5.2.03/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.2.1.02/LICENSE.txt b/lib/IRremoteESP8266-2.5.2.03/LICENSE.txt similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/LICENSE.txt rename to lib/IRremoteESP8266-2.5.2.03/LICENSE.txt diff --git a/lib/IRremoteESP8266-2.5.2.03/README.md b/lib/IRremoteESP8266-2.5.2.03/README.md new file mode 100644 index 000000000..bb9d5a9d8 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/README.md @@ -0,0 +1,78 @@ +# IRremote ESP8266 Library + +[![Build Status](https://travis-ci.org/markszabo/IRremoteESP8266.svg?branch=master)](https://travis-ci.org/markszabo/IRremoteESP8266) +[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Average time to resolve an issue") +[![Percentage of issues still open](http://isitmaintained.com/badge/open/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Percentage of issues still open") +[![GitLicense](https://gitlicense.com/badge/markszabo/IRremoteESP8266)](https://gitlicense.com/license/markszabo/IRremoteESP8266) + +This library enables you to **send _and_ receive** infra-red signals on an [ESP8266 using the Arduino framework](https://github.com/esp8266/Arduino) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* etc. + +## v2.5.2 Now Available +Version 2.5.2 of the library is now [available](https://github.com/markszabo/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. + +#### Upgrading from pre-v2.0 +Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/markszabo/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. + +#### Upgrading from pre-v2.5 +The library has changed from using constants declared as `#define` to +[const](https://google.github.io/styleguide/cppguide.html#Constant_Names) with +the appropriate naming per the +[C++ style guide](https://google.github.io/styleguide/cppguide.html). +This may potentially cause old programs to not compile. +The most likely externally used `#define`s have been _aliased_ for limited +backward compatibility for projects using the old style. Going forward, only the +new `kConstantName` style will be supported for new protocol additions. + +In the unlikely case it does break your code, then you may have been referencing +something you likely should not have. You should be able to quickly determine +the new name from the old. e.g. `CONSTANT_NAME` to `kConstantName`. +Use common sense or examining the library's code if this does affect code. + +## Troubleshooting +Before reporting an issue or asking for help, please try to follow our [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide) first. + +## Frequently Asked Questions +Some common answers to common questions and problems are on our [F.A.Q. wiki page](https://github.com/markszabo/IRremoteESP8266/wiki/Frequently-Asked-Questions). + +## Installation +##### Official releases via the Arduino IDE v1.8+ (Windows & Linux) +1. Click the _"Sketch"_ -> _"Include Library"_ -> _"Manage Libraries..."_ Menu items. +1. Enter `IRremoteESP8266` into the _"Filter your search..."_ top right search box. +1. Click on the IRremoteESP8266 result of the search. +1. Select the version you wish to install and click _"Install"_. + +##### Manual Installation for Windows +1. Click on _"Clone or Download"_ button, then _"[Download ZIP](https://github.com/markszabo/IRremoteESP8266/archive->master.zip)"_ on the page. +1. Extract the contents of the downloaded zip file. +1. Rename the extracted folder to _"IRremoteESP8266"_. +1. Move this folder to your libraries directory. (under windows: `C:\Users\YOURNAME\Documents\Arduino\libraries\`) +1. Restart your Arduino IDE. +1. Check out the examples. + +##### Using Git to install library ( Linux ) +``` +cd ~/Arduino/libraries +git clone https://github.com/markszabo/IRremoteESP8266.git +``` +###### To Update to the latest version of the library +``` +cd ~/Arduino/libraries/IRremoteESP8266 && git pull +``` + +## Contributing +If you want to [contribute](.github/CONTRIBUTING.md#how-can-i-contribute) to this project, consider: +- [Report](.github/CONTRIBUTING.md#reporting-bugs) bugs and errors +- Ask for enhancements +- Improve our documentation +- [Create issues](.github/CONTRIBUTING.md#reporting-bugs) and [pull requests](.github/CONTRIBUTING.md#pull-requests) +- Tell other people about this library + +## Contributors +Available [here](.github/Contributors.md) + +## Library History +This library was originally based on Ken Shirriff's work (https://github.com/shirriff/Arduino-IRremote/) + +[Mark Szabo](https://github.com/markszabo/IRremoteESP8266) has updated the IRsend class to work on ESP8266 and [Sebastien Warin](https://github.com/sebastienwarin/IRremoteESP8266) the receiving & decoding part (IRrecv class). + +As of v2.0, the library was almost entirely re-written with the ESP8266's resources in mind. diff --git a/lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md b/lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md new file mode 100644 index 000000000..56e84dd89 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md @@ -0,0 +1,308 @@ +# Release Notes + +## _v2.5.2 (20181021)_ + +**[Bug Fixes]** +- Add missing send() method to IRPanasonicAC class. (#545) +- Add missing sendWhirlpoolAC() to IRMQTTServer.ino (#558) + +**[Features]** +- Add IR receiving support to IRMQTTServer. (#543) +- Pioneer support (#547) +- Add support for a second LG protocol variant. (#552) +- Support for short Panasonic A/C messages. (#553) +- Add support for Panasonic CKP series A/Cs. (#554) +- Experimental timer/clock support for Panasonic A/Cs. (#546) +- Add Made With Magic (MWM) support (#557) + +**[Misc]** +- Grammar and typo fixes (#541, #549) +- Increase Panasonic A/C message tolerances. (#542) +- Added command mode2_decode in tools/ (#557) +- General code style cleanup (#560) + + +## _v2.5.1 (20181002)_ + +**[Bug Fixes]** +- Correct the byte used for Samsung AC Swing. (#529) +- Fix not sending Samsung A/C messages in IRMQTTServer. (#529) + +**[Features]** +- Experimental support for Electra A/C messages. (#528) +- Experimental support for Panasonic A/C messages. (#535) +- Samsung A/C fixes & improvements (#529) +- IRMQTTServer v0.6.0 (#530) + +**[Misc]** +- Change required WifiManager lib version to v0.14 +- Add alias for RAWTICK to kRawTick. (#535) +- Update sendLutron() status. (#515) +- Remove leftover debug message in IRrecvDumpV2 (#526) + + +## _v2.5.0 (20180919)_ + +**[Bug Fixes]** +- Fix HTML menu error for GICABLE in IRMQTTServer. (#516) +- Fix Mitsubishi A/C mode setting. (#514) +- Add missing ',' in auto analyse tool generated code. (#513) +- Fix Fujitsu checksum validation. (#501) +- Remove errant Repeat debug statement in IRMQTTServer. (#507) + +**[Features]** +- Mitsubishi A/C decode improvements. (#514) +- Basic support for Whirlpool A/C messages. (#511) +- Basic support for Samsung A/C messages. (#512) +- Experimental support for detailed Samsung A/C messages. (#521) +- Experimental support for detailed Coolix A/C messages. (#518) +- Experimental support for Lutron protocol. (#516) +- Calculate and use average values for timings in analysing tool. (#513) + +**[Misc]** +- Style change from using #define's for constants to `const kConstantName`. +- Improve the JVC example code. + + +## _v2.4.3 (20180727)_ + +**[Bug Fixes]** +- Handle Space Gaps better in auto analyse tool. (#482) +- Correct min repeat for GICABLE in IRMQTTServer. (#494) + +**[Features]** +- Add static IP config option to IRMQTTServer (#480) +- Full decoding/encoding support for the Haier YRW02 A/C. (#485 #486 #487) + +**[Misc]** +- Update LG (28-bit) HDR mark and space timings. (#492) +- Spelling and grammar fixes (#491) + + +## _v2.4.2 (20180601)_ + +**[Bug Fixes]** +- Timing Fix: Update the period offset compensation. + +**[Features]** +- Improvements for IRMQTTServer example (#466) + + +## _v2.4.1 (20180520)_ + +**[Bug Fixes]** +- Fix crash in IRMQTTServer when compiled under Arduino IDE. (#455) +- Default bit length not set for RCMM in IRMQTTServer example. (#456) +- Bad acknowledgements for some A/C protocols in IRMQTTServer example. (#460) + +**[Features]** +- Allow disabling the use of delay() calls. (#450) +- Initial support for G.I. Cable protocol. (#458) +- Support of Hitachi A/C 13 & 53 byte messages. (#461) + +**[Misc]** +- Auto Analyse Raw Data script converted to Python. (#454) + +## _v2.4.0 (20180407)_ + +**[Bug Fixes]** +- Add missing WiFi.begin() call to IRGCTCPServer example. (#433) +- Add missing sendHaierAC() to IRMQTTServer example. (#434 & #444) +- Make mqtt clientid unique in IRMQTTServer example. (#444) + +**[Features]** + +- Initial Mitsubishi projector protocol support. (#442) +- Experimental support of Hitachi A/C messages. (#445) +- Improve transmission pulse modulation support. + Allow disabling of transmission frequency modulation.(#439) + +**[Misc]** +- IRMQTTServer example improvements. (#444) + + +## _v2.3.3 (20180302)_ + +**[Bug Fixes]** +- Ensure the IR LED is off before we start. (#405) + +**[Features]** +- Experimental decode support for Gree HVAC units (#397) +- Initial support for Haier A/Cs. (#409) +- Improve timing accuracy of unit tests. (#403) +- Rework matchData() to handle equal total data bit time protocols. (#408) + +**[Misc]** +- Add startup text to IRrecvDumpV2 and IRrecvDemo (#412) +- Tweak timings on Fujitsu A/C header (#418) +- AutoAnalyseRawData.sh: Add some support for handling larger than 64 bit codes. (#419) +- Use better comments for send GPIO in examples. (#425) + + +## _v2.3.2 (20180126)_ + +**[Bug Fixes]** +- Integer underflow caused device not to respond in `sendJVC()` (#401) + +**[Features]** +- Initial support for sending & receiving Carrier HVAC codes. (#387) +- Add Pronto HEX code support to _gc_decode_ tool. (#388) + +**[Misc]** +- Make mDNS independent of MQTT in IRMQTTServer example code. (#390 #391) + + +## _v2.3.1 (20171229)_ + +**[Bug Fixes]** +- Setting `#define SEND_FUJITSU_AC false` caused a compilation error (#375) +- Integer underflow caused huge `space()` in `sendGeneric()` (#381) + +**[Features]** +- Support sending & receiving Lasertag codes. (#374) +- Reduce the library footprint by using a new `sendGeneric()` routine. (#373) + +**[Misc]** +- Lots of grammar & typo fixes. (#378) +- Update keywords.txt for Arduino IDE users (#371) +- Update pins in examples so they are compatible with Adafruit boards. (#383) + + +## _v2.3.0 (20171208)_ + +**[Bug Fixes]** +- Panasonic-based protocols had incorrect message gap. (#358) +- Formatting error for large rawData values in example code. (#355) +- Off-by-one error in payload_copy malloc. (#337) +- Off-by-one error in unit test helper routines (#363) + +**[Features]** +- Support sending and receiving Midea A/C codes. +- Support for receiving Kelvinator A/C codes. (#332) +- Support more operation features for Daikin A/Cs. +- Support for decoding Daikin A/Cs. +- Support sending and receiving Toshiba A/Cs. (#333) +- Support sending and receiving AR-DB1 Fujitsu A/C codes. (#367) +- Add new AutoAnalyseRawData.sh & RawToGlobalCache.sh tools (#345) (#343) +- Support for MagiQuest wands. (#365) + +**[Misc]** +- Add checksum verification to Kelvinator A/C decodes. (#348) +- Changes to the threshold reporting of UNKNOWN messages (#347) +- Major re-work of Daikin A/C support. +- Sending for all A/Cs added to MQTT example code. +- MQTT example code improvements. (#334) +- IRrecvDumpV2 significant output improvements. (#363) +- Improved unit test coverage for the library. + + +## _v2.2.1 (20171025)_ + +**[Features]** +- Support for sending and decoding Nikai TV messages. (#311, #313) +- gc_decode: External utility to decode Global Cache codes. (#308, #312) +- IRMQTTServer: Example code to send IR messages via HTTP & MQTT. (#316, #323) +- Improve converting 64bit values to hexadecimal. (#318) + +**[Misc]** +- IRrecvDump.ino code is now deprecated. Use IRrecvDumpV2.ino instead. (#314) + + +## _v2.2.0 (20170922)_ + +**[Bug Fixes]** +- Add printing output of RC-MM and RC-5X protocols in example code. (#284) +- LG timing improvements based on observations (#291) + +**[Features]** +- Automatic capture timing calibration for some protocols. (#268) +- Support for creating & sending Trotec AC codes. (#279) +- Support for creating & sending Argo Ulisse 13 DCI codes. (#280 #300) +- Move to 2 microsecond timing resolution for capture of codes. (#287) +- Capture buffer changes: +- Size at runtime. (#276) +- Message timeout at runtime. (#294) +- Simplify creating & using a second buffer (#303) +- New example code: + - Trotec A/C (#279) + - LG A/C units (#289) + - Argo Ulisse 13 DCI codes. (#300) + + +## _v2.1.1 (20170711)_ + +**[Bug Fixes]** +- GlobalCache incorrectly using hardware offset for period calc. (#267) + +**[Features]** +- Support reporting of 'NEC'-like 32-bit protocols. e.g. Apple TV remote (#265) +- Add an example of sendRaw() to IRsendDemo.ino (#270) + + +## _v2.1.0 (20170704)_ + +**[Features]** +- Support for sending Pronto IR codes. (#248) +- Support for sending Fujitsu A/C codes. (#88) +- Minor improvements to examples. + + +## _v2.0.3 (20170618)_ + +**[Bug fixes]** +- Capture buffer could become corrupt after large message, breaking subsequent decodes. (#253) + + +## _v2.0.2 (20170615)_ + +**[Bug fixes]** +- Correct decode issue introduced in v2.0.1 affecting multiple protocol decoders (#243) +- Correct post-message gap for the Panasonic protocol(s) (#245) +- Incorrect display of the decoded uint64_t value in the example code. (#245) + + +## _v2.0.1 (20170614)_ + +**[Bug fixes]** +- Decoding protocols when it doesn't detect a post-command gap, and there is no more data. (#243) +- Incorrect minimum size calculation when there is no post-command gap. (#243) + + +## _v2.0.0 - 64 bit support and major improvements (20170612)_ + +**[Misc]** +- This is almost a complete re-write of the library. + +**[Features]** +- All suitable protocols now handle 64-bit data messages and are repeatable via an optional argument. +- Unit tests for all protocols. +- Far better and stricter decoding for most protocols. +- Address & command decoding for protocols where that information is available. +- Much more precise timing for generation of signals sent. +- Lower duty-cycles for some protocols. +- Several new protocols added, and some new sending and decoding routines for existing ones. +- Ability to optionally chose which protocols are included, enabling faster decoding and smaller code footprints if desired. +- Support for far larger capture buffers. (e.g. RAWLEN > 256) + +**[Bug fixes]** +- Numerous bug fixes. + + +## _v1.2.0 (20170429)_ + +**[Features]** +- Add ability to copy IR capture buffer, and continue capturing. Means faster and better IR command decoding. +- Reduce IRAM usage by 28 bytes. +- Improve capture of RC-MM & Panasonic protocols. +- Upgrade IRrecvDumpV2 to new IR capture buffer. Much fewer corrupted/truncated IR messages. + + +## _v1.1.1 (20170413)_ + +**[Bug fixes]** +- Fix a reported problem when sending the LG protocol. Preemptive fix for possible similar cases. +- Fix minor issues in examples. + +**[Features]** +- Add documentation to some examples to aid new people. +- Add ALPHA support for RC-MM protocol. (Known to be currently not 100% working.) diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/IRGCSendDemo.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/IRGCSendDemo.ino similarity index 66% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/IRGCSendDemo.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/IRGCSendDemo.ino index b36938e3d..03c80e18b 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/IRGCSendDemo.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/IRGCSendDemo.ino @@ -11,7 +11,8 @@ * Based on Ken Shirriff's IrsendDemo * Version 0.1 July, 2009 * - * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). + * An IR LED circuit *MUST* be connected to the ESP8266 on a pin + * as specified by IR_LED below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -23,12 +24,13 @@ * have enough current to drive the IR LED effectively. * * Make sure you have the IR LED polarity correct. * See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity - * * Typical digital camera/phones can be used to see if the IR LED is flashed. - * Replace the IR LED with a normal LED if you don't have a digital camera - * when debugging. + * * Typical digital camera/phones can be used to see if the IR LED is + * flashed. Replace the IR LED with a normal LED if you don't have a digital + * camera when debugging. * * Avoid using the following pins unless you really know what you are doing: * * Pin 0/D3: Can interfere with the boot/program mode & support circuits. - * * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will interfere. + * * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will + * interfere. * * Pin 3/RX/RXD0: Any serial transmissions to the ESP8266 will interfere. * * ESP-01 modules are tricky. We suggest you use a module with more GPIOs * for your first time. e.g. ESP-12 etc. @@ -44,12 +46,15 @@ // These codes can be found in GC's Control Tower database. uint16_t Samsung_power_toggle[71] = { - 38000, 1, 1, 170, 170, 20, 63, 20, 63, 20, 63, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 63, 20, 63, 20, 63, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 63, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 63, 20, - 20, 20, 63, 20, 63, 20, 63, 20, 63, 20, 63, 20, 63, 20, 1798}; + 38000, 1, 1, 170, 170, 20, 63, 20, 63, 20, 63, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 63, 20, 63, 20, 63, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 63, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 63, 20, 20, 20, 63, 20, + 63, 20, 63, 20, 63, 20, 63, 20, 63, 20, 1798}; -IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) +#define IR_LED 4 // ESP8266 GPIO pin to use. Recommended: 4 (D2). + +IRsend irsend(IR_LED); // Set the GPIO to be used to sending the message. void setup() { irsend.begin(); @@ -58,6 +63,10 @@ void setup() { void loop() { Serial.println("Toggling power"); +#if SEND_GLOBALCACHE irsend.sendGC(Samsung_power_toggle, 71); +#else // SEND_GLOBALCACHE + Serial.println("Can't send because SEND_GLOBALCACHE has been disabled."); +#endif // SEND_GLOBALCACHE delay(10000); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/IRGCTCPServer.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/IRGCTCPServer.ino similarity index 89% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/IRGCTCPServer.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/IRGCTCPServer.ino index 2fd38be42..69f7299fb 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/IRGCTCPServer.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/IRGCTCPServer.ino @@ -9,7 +9,7 @@ * For more codes, visit: https://irdb.globalcache.com/ * * How to use this program: - * 1) Update "ssid" and "password" below for your WIFI network. + * 1) Update "kSsid" and "kPassword" below for your WIFI network. * 2) Compile and upload the sketch to your ESP8266 module. * 3) (Optional) Use the serial connection to confirm it started and get the * IP address. @@ -46,14 +46,16 @@ #include #include -const char* ssid = "..."; // Put your WIFI SSID here. -const char* password = "..."; // Put your WIFI password here. +const char* kSsid = "..."; // Put your WIFI SSID here. +const char* kPassword = "..."; // Put your WIFI Password here. WiFiServer server(4998); // Uses port 4998. WiFiClient client; uint16_t *code_array; -IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) +#define IR_LED 4 // ESP8266 GPIO pin to use. Recommended: 4 (D2). + +IRsend irsend(IR_LED); // Set the GPIO to be used to sending the message. void sendGCString(String str) { int16_t index; @@ -89,7 +91,9 @@ void sendGCString(String str) { count++; } while (index != -1); +#if SEND_GLOBALCACHE irsend.sendGC(code_array, count); // All done. Send it. +#endif // SEND_GLOBALCACHE free(code_array); // Free up the memory allocated. } @@ -99,7 +103,7 @@ void setup() { delay(100); Serial.println(" "); Serial.println("IR TCP Server"); - + WiFi.begin(kSsid, kPassword); while (WiFi.status() != WL_CONNECTED) { delay(900); Serial.print("."); @@ -107,7 +111,7 @@ void setup() { server.begin(); IPAddress myAddress = WiFi.localIP(); - Serial.println(myAddress); + Serial.println(myAddress.toString()); irsend.begin(); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/IRMQTTServer.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/IRMQTTServer.ino similarity index 55% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/IRMQTTServer.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/IRMQTTServer.ino index e2c1f81d8..7851cf5dc 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/IRMQTTServer.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/IRMQTTServer.ino @@ -1,9 +1,11 @@ /* - * Send arbitary IR codes via a web server or MQTT. - * Copyright David Conran 2016 - * Version 0.3 Oct, 2017 + * Send & receive arbitrary IR codes via a web server or MQTT. + * Copyright David Conran 2016, 2017, 2018 * - * NOTE: An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). See IR_LED + * NOTE: An IR LED circuit *MUST* be connected to ESP8266 GPIO4 (D2) if + * you want to send IR messages. See IR_LED below. + * A compatible IR RX modules *MUST* be connected to ESP8266 GPIO14 (D5) + * if you want to capture & decode IR nessages. See IR_RX below. * * WARN: This is very advanced & complicated example code. Not for beginners. * You are strongly suggested to try & look at other example code first. @@ -11,10 +13,14 @@ * # Instructions * * ## Before First Boot (i.e. Compile time) - * - Set the MQTT_SERVER define below to the address of your MQTT server. + * - Either: + * o Set the MQTT_SERVER define below to the address of your MQTT server. + * or + * o Disable MQTT by commenting out the line "#define MQTT_ENABLE" down below. + * * - Arduino IDE: * o Install the following libraries via Library Manager - * - WiFiManager (https://github.com/tzapu/WiFiManager) + * - WiFiManager (https://github.com/tzapu/WiFiManager) (Version >= 0.14) * - PubSubClient (https://pubsubclient.knolleary.net/) * o You MUST change to have the following (or larger) value: * #define MQTT_MAX_PACKET_SIZE 512 @@ -63,13 +69,17 @@ * GlobalCache (31) & "40000,1,1,96,..." (Sony Vol Up) * 25,Rrepeats,hex_code_string e.g. 25,R1,0000,006E,0022,0002,0155,00AA,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0040,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0040,0015,0040,0015,0040,0015,0640,0155,0055,0015,0E40 * Pronto (25), 1 repeat, & "0000 006E 0022 0002 ..." (Sherwood Amp Tape Input) - * 18,really_long_hexcode e.g. 18,190B8050000000E0190B8070000010f0 + * ac_protocol_num,really_long_hexcode e.g. 18,190B8050000000E0190B8070000010F0 * Kelvinator (18) Air Con on, Low Fan, 25 deg etc. + * NOTE: Ensure you zero-pad to the correct number of + * digits for the bit/byte size you want to send + * as some A/C units have units have different + * sized messages. e.g. Fujitsu A/C units. * In short: * No spaces after/before commas. * Values are comma separated. * The first value is always in Decimal. - * For simple protocols, the next value (hexcode) is always hexidecimal. + * For simple protocols, the next value (hexcode) is always hexadecimal. * The optional bit size is in decimal. * * Unix command line usage example: @@ -87,6 +97,19 @@ * # Listen to MQTT acknowledgements. * $ mosquitto_sub -h 10.20.0.253 -t ir_server/sent * + * Incoming IR messages (from an IR remote control) will be transmitted to + * the MQTT topic 'ir_server/received'. The MQTT message will be formatted + * similar to what is required to for the 'sent' topic. + * e.g. "3,C1A2F00F,32" (Protocol,Value,Bits) for simple codes + * or "18,110B805000000060110B807000001070" (Protocol,Value) for complex codes + * Note: If the protocol is listed as -1, then that is an UNKNOWN IR protocol. + * You can't use that to recreate/resend an IR message. It's only for + * matching purposes and shouldn't be trusted. + * + * Unix command line usage example: + * # Listen via MQTT for IR messages captured by this server. + * $ mosquitto_sub -h 10.20.0.253 -t ir_server/received + * * If DEBUG is turned on, there is additional information printed on the Serial * Port. * @@ -111,6 +134,7 @@ #include #include #include +#include #include #include #ifdef MQTT_ENABLE @@ -124,22 +148,43 @@ #include #include -// Configuration paramters -#define IR_LED 4 // GPIO the IR LED is connected to/controlled by. GPIO 4 = D2. -#define HTTP_PORT 80 // The port the HTTP server is listening on. +// Configuration parameters +// GPIO the IR LED is connected to/controlled by. GPIO 4 = D2. +#define IR_LED 4 +// define IR_LED 3 // For an ESP-01 we suggest you use RX/GPIO3/Pin 7. +// +// GPIO the IR RX module is connected to/controlled by. GPIO 14 = D5. +// Comment this out to disable receiving/decoding IR messages entirely. +#define IR_RX 14 +const uint16_t kHttpPort = 80; // The TCP port the HTTP server is listening on. +// Name of the device you want in mDNS. +// NOTE: Changing this will change the MQTT path too unless you override it +// via MQTTprefix below. +#define HOSTNAME "ir_server" + +// We obtain our network config via DHCP by default but allow an easy way to +// use a static IP config. +#define USE_STATIC_IP false // Change to 'true' if you don't want to use DHCP. +#if USE_STATIC_IP +const IPAddress kIPAddress = IPAddress(10, 0, 1, 78); +const IPAddress kGateway = IPAddress(10, 0, 1, 1); +const IPAddress kSubnetMask = IPAddress(255, 255, 255, 0); +#endif // USE_STATIC_IP #ifdef MQTT_ENABLE // Address of your MQTT server. #define MQTT_SERVER "10.20.0.253" // <=- CHANGE ME -#define MQTT_PORT 1883 // Default port used by MQTT servers. +const uint16_t kMqttPort = 1883; // Default port used by MQTT servers. // Set if your MQTT server requires a Username & Password to connect. const char* mqtt_user = ""; const char* mqtt_password = ""; -#define MQTT_RECONNECT_TIME 5000 // Delay(ms) between reconnect tries. +const uint32_t kMqttReconnectTime = 5000; // Delay(ms) between reconnect tries. -#define MQTTprefix "ir_server" +#define MQTTprefix HOSTNAME // Change this if you want the MQTT topic to be + // independent of the hostname. #define MQTTack MQTTprefix "/sent" // Topic we send back acknowledgements on #define MQTTcommand MQTTprefix "/send" // Topic we get new commands from. +#define MQTTrecv MQTTprefix "/received" // Topic we send received IRs to. #endif // MQTT_ENABLE // HTML arguments we will parse for IR code information. @@ -147,27 +192,71 @@ const char* mqtt_password = ""; #define argData "code" #define argBits "bits" #define argRepeat "repeats" -#define DEBUG True +// Let's use a larger than normal buffer so we can handle AirCon remote codes. +const uint16_t kCaptureBufferSize = 1024; +#if DECODE_AC +// Some A/C units have gaps in their protocols of ~40ms. e.g. Kelvinator +// A value this large may swallow repeats of some protocols +const uint8_t kCaptureTimeout = 50; +#else // DECODE_AC +// Suits most messages, while not swallowing many repeats. +const uint8_t kCaptureTimeout = 15; +#endif // DECODE_AC +// Ignore unknown messages with <10 pulses +const uint16_t kMinUnknownSize = 20; + +#define _MY_VERSION_ "v0.7.0" + +// Disable debug output if any of the IR pins are on the TX (D1) pin. +#if (IR_LED != 1 && IR_RX != 1) +#undef DEBUG +#define DEBUG true // Change to 'false' to disable all serial output. +#else +#undef DEBUG +#define DEBUG false +#endif +// NOTE: Make sure you set your Serial Monitor to the same speed. +#define BAUD_RATE 115200 // Serial port Baud rate. // Globals -ESP8266WebServer server(HTTP_PORT); +ESP8266WebServer server(kHttpPort); IRsend irsend = IRsend(IR_LED); +#ifdef IR_RX +IRrecv irrecv(IR_RX, kCaptureBufferSize, kCaptureTimeout, true); +decode_results capture; // Somewhere to store inbound IR messages. +#endif // IR_RX MDNSResponder mdns; WiFiClient espClient; WiFiManager wifiManager; uint16_t *codeArray; -uint32_t lastReconnectAttempt = 0; // MQTT last attemps reconnection number +uint32_t lastReconnectAttempt = 0; // MQTT last attempt reconnection number bool boot = true; -bool ir_lock = false; // Primative locking for gating the IR LED. +bool ir_lock = false; // Primitive locking for gating the IR LED. +uint32_t sendReqCounter = 0; +bool lastSendSucceeded = false; // Store the success status of the last send. +uint32_t lastSendTime = 0; +int8_t offset; // The calculated period offset for this chip and library. #ifdef MQTT_ENABLE +String lastMqttCmd = "None"; +uint32_t lastMqttCmdTime = 0; +uint32_t lastConnectedTime = 0; +uint32_t lastDisconnectedTime = 0; +uint32_t mqttDisconnectCounter = 0; +bool wasConnected = true; +#ifdef IR_RX +String lastIrReceived = "None"; +uint32_t lastIrReceivedTime = 0; +uint32_t irRecvCounter = 0; +#endif // IR_RX + + // MQTT client parameters void callback(char* topic, byte* payload, unsigned int length); -PubSubClient mqtt_client(MQTT_SERVER, MQTT_PORT, callback, espClient); +PubSubClient mqtt_client(MQTT_SERVER, kMqttPort, callback, espClient); // Create a unique MQTT client id. -const char* mqtt_clientid = String(MQTTprefix + - String(ESP.getChipId(), HEX)).c_str(); +String mqtt_clientid = MQTTprefix + String(ESP.getChipId(), HEX); #endif // MQTT_ENABLE // Debug messages get sent to the serial port. @@ -178,6 +267,50 @@ void debug(String str) { #endif // DEBUG } +String timeSince(uint32_t const start) { + if (start == 0) + return "Never"; + uint32_t diff = 0; + uint32_t now = millis(); + if (start < now) + diff = now - start; + else + diff = UINT32_MAX - start + now; + diff /= 1000; // Convert to seconds. + if (diff == 0) return "Now"; + + // Note: millis() can only count up to 45 days, so uint8_t is safe. + uint8_t days = diff / (60 * 60 * 24); + uint8_t hours = (diff / (60 * 60)) % 24; + uint8_t minutes = (diff / 60) % 60; + uint8_t seconds = diff % 60; + + String result = ""; + if (days) + result += String(days) + " day"; + if (days > 1) result += "s"; + if (hours) + result += " " + String(hours) + " hour"; + if (hours > 1) result += "s"; + if (minutes) + result += " " + String(minutes) + " minute"; + if (minutes > 1) result += "s"; + if (seconds) + result += " " + String(seconds) + " second"; + if (seconds > 1) result += "s"; + result.trim(); + return result + " ago"; +} + +// Quick and dirty check for any unsafe chars in a string +// that may cause HTML shenanigans. e.g. An XSS. +bool hasUnsafeHTMLChars(String input) { + static char unsafe[] = "';!-\"<>=&{}()"; + for (uint8_t i = 0; unsafe[i]; i++) + if (input.indexOf(unsafe[i]) != -1) return true; + return false; +} + // Root web page with example usage etc. void handleRoot() { server.send(200, "text/html", @@ -185,13 +318,43 @@ void handleRoot() { "" "

          ESP8266 IR MQTT Server

          " "

          " - "

          Connection details

          " - "

          IP address: " + WiFi.localIP().toString() + "

          " + "

          Information

          " + "

          IP address: " + WiFi.localIP().toString() + "
          " + "Booted: " + timeSince(1) + "
          " + + "Version: " _MY_VERSION_ "
          " + "Period Offset: " + String(offset) + "us
          " + "IR Lib Version: " _IRREMOTEESP8266_VERSION_ "
          " + "ESP8266 Core Version: " + ESP.getCoreVersion() + "
          " + "IR Send GPIO: " + String(IR_LED) + "
          " + "Total send requests: " + String(sendReqCounter) + "
          " + "Last message sent: " + String(lastSendSucceeded ? "Ok" : "FAILED") + + " (" + timeSince(lastSendTime) + ")
          " +#ifdef IR_RX + "IR Recv GPIO: " + String(IR_RX) + "
          " + "Total IR Received: " + String(irRecvCounter) + "
          " + "Last IR Received: " + lastIrReceived + + " (" + timeSince(lastIrReceivedTime) + ")
          " +#endif // IR_RX + "

          " #ifdef MQTT_ENABLE - "

          MQTT server: " MQTT_SERVER ":" + String(MQTT_PORT) + " ("+ - (mqtt_client.connected() ? "Connected" : "Disconnected") + ")
          " + "

          MQTT Information

          " + "

          Server: " MQTT_SERVER ":" + String(kMqttPort) + " (" + + (mqtt_client.connected() ? "Connected " + timeSince(lastDisconnectedTime) + : "Disconnected " + timeSince(lastConnectedTime)) + + ")
          " + "Disconnections: " + String(mqttDisconnectCounter - 1) + "
          " + "Client id: " + mqtt_clientid + "
          " "Command topic: " MQTTcommand "
          " - "Acknowledgements topic: " MQTTack "

          " + "Acknowledgements topic: " MQTTack "
          " +#ifdef IR_RX + "IR Received topic: " MQTTrecv "
          " +#endif // IR_RX + "Last MQTT command seen: " + + // lastMqttCmd is unescaped untrusted input. + // Avoid any possible HTML/XSS when displaying it. + (hasUnsafeHTMLChars(lastMqttCmd) ? + "Contains unsafe HTML characters" : lastMqttCmd) + + " (" + timeSince(lastMqttCmdTime) + ")

          " #endif // MQTT_ENABLE "

          " "

          Hardcoded examples

          " @@ -222,15 +385,24 @@ void handleRoot() { "Type: " "" " Repeats: " @@ -305,11 +479,32 @@ void handleRoot() { " " "" "

          " - "

          Send a Kelvinator A/C IR message

          " + "

          Send an Air Conditioner IR message

          " "
          " - "" - "State code: 0x" + "Type: " + "" + " State code: 0x" + "" " " "" "


          " @@ -340,26 +535,245 @@ void handleReset() { delay(1000); } -// Parse a Kelvinator A/C Hex String/code and send it. -void parseStringAndSendKelv(const String str) { - // str should be a 32 digit hexidecimal string. - uint8_t offset = 0; - uint8_t codeArray[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +// Parse an Air Conditioner A/C Hex String/code and send it. +// Args: +// irType: Nr. of the protocol we need to send. +// str: A hexadecimal string containing the state to be sent. +// Returns: +// bool: Successfully sent or not. +bool parseStringAndSendAirCon(const uint16_t irType, const String str) { + uint8_t strOffset = 0; + uint8_t state[kStateSizeMax] = {0}; // All array elements are set to 0. + uint16_t stateSize = 0; + if (str.startsWith("0x") || str.startsWith("0X")) - offset = 2; - for (int i = 0; i < 32; i++) { - unsigned char c = tolower(str[i + offset]); - uint8_t entry = 0; + strOffset = 2; + // Calculate how many hexadecimal characters there are. + uint16_t inputLength = str.length() - strOffset; + if (inputLength == 0) { + debug("Zero length AirCon code encountered. Ignored."); + return false; // No input. Abort. + } + + switch (irType) { // Get the correct state size for the protocol. + case KELVINATOR: + stateSize = kKelvinatorStateLength; + break; + case TOSHIBA_AC: + stateSize = kToshibaACStateLength; + break; + case DAIKIN: + stateSize = kDaikinStateLength; + break; + case ELECTRA_AC: + stateSize = kElectraAcStateLength; + break; + case MITSUBISHI_AC: + stateSize = kMitsubishiACStateLength; + break; + case PANASONIC_AC: + stateSize = kPanasonicAcStateLength; + break; + case TROTEC: + stateSize = kTrotecStateLength; + break; + case ARGO: + stateSize = kArgoStateLength; + break; + case GREE: + stateSize = kGreeStateLength; + break; + case FUJITSU_AC: + // Fujitsu has four distinct & different size states, so make a best guess + // which one we are being presented with based on the number of + // hexadecimal digits provided. i.e. Zero-pad if you need to to get + // the correct length/byte size. + stateSize = inputLength / 2; // Every two hex chars is a byte. + // Use at least the minimum size. + stateSize = std::max(stateSize, + (uint16_t) (kFujitsuAcStateLengthShort - 1)); + // If we think it isn't a "short" message. + if (stateSize > kFujitsuAcStateLengthShort) + // Then it has to be at least the smaller version of the "normal" size. + stateSize = std::max(stateSize, (uint16_t) (kFujitsuAcStateLength - 1)); + // Lastly, it should never exceed the maximum "normal" size. + stateSize = std::min(stateSize, kFujitsuAcStateLength); + break; + case HAIER_AC: + stateSize = kHaierACStateLength; + break; + case HAIER_AC_YRW02: + stateSize = kHaierACYRW02StateLength; + break; + case HITACHI_AC: + stateSize = kHitachiAcStateLength; + break; + case HITACHI_AC1: + stateSize = kHitachiAc1StateLength; + break; + case HITACHI_AC2: + stateSize = kHitachiAc2StateLength; + break; + case WHIRLPOOL_AC: + stateSize = kWhirlpoolAcStateLength; + break; + case SAMSUNG_AC: + // Samsung has two distinct & different size states, so make a best guess + // which one we are being presented with based on the number of + // hexadecimal digits provided. i.e. Zero-pad if you need to to get + // the correct length/byte size. + stateSize = inputLength / 2; // Every two hex chars is a byte. + // Use at least the minimum size. + stateSize = std::max(stateSize, (uint16_t) (kSamsungAcStateLength)); + // If we think it isn't a "normal" message. + if (stateSize > kSamsungAcStateLength) + // Then it probably the extended size. + stateSize = std::max(stateSize, + (uint16_t) (kSamsungAcExtendedStateLength)); + // Lastly, it should never exceed the maximum "extended" size. + stateSize = std::min(stateSize, kSamsungAcExtendedStateLength); + break; + case MWM: + // MWM has variable size states, so make a best guess + // which one we are being presented with based on the number of + // hexadecimal digits provided. i.e. Zero-pad if you need to to get + // the correct length/byte size. + stateSize = inputLength / 2; // Every two hex chars is a byte. + // Use at least the minimum size. + stateSize = std::max(stateSize, (uint16_t) 3); + // Cap the maximum size. + stateSize = std::min(stateSize, kStateSizeMax); + break; + default: // Not a protocol we expected. Abort. + debug("Unexpected AirCon protocol detected. Ignoring."); + return false; + } + if (inputLength > stateSize * 2) { + debug("AirCon code to large for the given protocol."); + return false; + } + + // Ptr to the least significant byte of the resulting state for this protocol. + uint8_t *statePtr = &state[stateSize - 1]; + + // Convert the string into a state array of the correct length. + for (uint16_t i = 0; i < inputLength; i++) { + // Grab the next least sigificant hexadecimal digit from the string. + uint8_t c = tolower(str[inputLength + strOffset - i - 1]); if (isxdigit(c)) { if (isdigit(c)) - codeArray[i / 2] += c - '0'; + c -= '0'; else - codeArray[i / 2] += c - 'a' + 10; + c = c - 'a' + 10; + } else { + debug("Aborting! Non-hexadecimal char found in AirCon state: " + str); + return false; + } + if (i % 2 == 1) { // Odd: Upper half of the byte. + *statePtr += (c << 4); + statePtr--; // Advance up to the next least significant byte of state. + } else { // Even: Lower half of the byte. + *statePtr = c; } - if (i % 2 == 0) - codeArray[i / 2] <<= 4; } - irsend.sendKelvinator(reinterpret_cast(codeArray)); + + // Make the appropriate call for the protocol type. + switch (irType) { +#if SEND_KELVINATOR + case KELVINATOR: + irsend.sendKelvinator(reinterpret_cast(state)); + break; +#endif +#if SEND_TOSHIBA_AC + case TOSHIBA_AC: + irsend.sendToshibaAC(reinterpret_cast(state)); + break; +#endif +#if SEND_DAIKIN + case DAIKIN: + irsend.sendDaikin(reinterpret_cast(state)); + break; +#endif +#if MITSUBISHI_AC + case MITSUBISHI_AC: + irsend.sendMitsubishiAC(reinterpret_cast(state)); + break; +#endif +#if SEND_TROTEC + case TROTEC: + irsend.sendTrotec(reinterpret_cast(state)); + break; +#endif +#if SEND_ARGO + case ARGO: + irsend.sendArgo(reinterpret_cast(state)); + break; +#endif +#if SEND_GREE + case GREE: + irsend.sendGree(reinterpret_cast(state)); + break; +#endif +#if SEND_FUJITSU_AC + case FUJITSU_AC: + irsend.sendFujitsuAC(reinterpret_cast(state), stateSize); + break; +#endif +#if SEND_HAIER_AC + case HAIER_AC: + irsend.sendHaierAC(reinterpret_cast(state)); + break; +#endif +#if SEND_HAIER_AC_YRW02 + case HAIER_AC_YRW02: + irsend.sendHaierACYRW02(reinterpret_cast(state)); + break; +#endif +#if SEND_HITACHI_AC + case HITACHI_AC: + irsend.sendHitachiAC(reinterpret_cast(state)); + break; +#endif +#if SEND_HITACHI_AC1 + case HITACHI_AC1: + irsend.sendHitachiAC1(reinterpret_cast(state)); + break; +#endif +#if SEND_HITACHI_AC2 + case HITACHI_AC2: + irsend.sendHitachiAC2(reinterpret_cast(state)); + break; +#endif +#if SEND_WHIRLPOOL_AC + case WHIRLPOOL_AC: + irsend.sendWhirlpoolAC(reinterpret_cast(state)); + break; +#endif +#if SEND_SAMSUNG_AC + case SAMSUNG_AC: + irsend.sendSamsungAC(reinterpret_cast(state), stateSize); + break; +#endif +#if SEND_ELECTRA_AC + case ELECTRA_AC: + irsend.sendElectraAC(reinterpret_cast(state)); + break; +#endif +#if SEND_PANASONIC_AC + case PANASONIC_AC: + irsend.sendPanasonicAC(reinterpret_cast(state)); + break; +#endif +#if SEND_MWM_ + case MWM: + irsend.sendMWM(reinterpret_cast(state), stateSize); + break; +#endif + default: + debug("Unexpected AirCon type in send request. Not sent."); + return false; + } + return true; // We were successful as far as we can tell. } // Count how many values are in the String. @@ -399,6 +813,7 @@ uint16_t * newCodeArray(const uint16_t size) { return result; } +#if SEND_GLOBALCACHE // Parse a GlobalCache String/code and send it. // Args: // str: A GlobalCache formatted String of comma separated numbers. @@ -407,7 +822,9 @@ uint16_t * newCodeArray(const uint16_t size) { // 20,20,20,20,20,20,20,20,20,20,20,20,20,63,20,20,20,63,20,63,20, // 63,20,63,20,63,20,63,20,1798" // Note: The leading "1:1,1," of normal GC codes should be removed. -void parseStringAndSendGC(const String str) { +// Returns: +// bool: Successfully sent or not. +bool parseStringAndSendGC(const String str) { uint16_t count; uint16_t *code_array; String tmp_str; @@ -437,22 +854,29 @@ void parseStringAndSendGC(const String str) { irsend.sendGC(code_array, count); // All done. Send it. free(code_array); // Free up the memory allocated. + if (count > 0) + return true; // We sent something. + return false; // We probably didn't. } +#endif // SEND_GLOBALCACHE +#if SEND_PRONTO // Parse a Pronto Hex String/code and send it. // Args: -// str: A comma-separated String of nr. of repeats, then hexidecimal numbers. +// str: A comma-separated String of nr. of repeats, then hexadecimal numbers. // e.g. "R1,0000,0067,0000,0015,0060,0018,0018,0018,0030,0018,0030,0018, // 0030,0018,0018,0018,0030,0018,0018,0018,0018,0018,0030,0018, // 0018,0018,0030,0018,0030,0018,0030,0018,0018,0018,0018,0018, // 0030,0018,0018,0018,0018,0018,0030,0018,0018,03f6" // or // "0000,0067,0000,0015,0060,0018". i.e. without the Repeat value -// Requires at least PRONTO_MIN_LENGTH comma-separated values. +// Requires at least kProntoMinLength comma-separated values. // sendPronto() only supports raw pronto code types, thus so does this. // repeats: Nr. of times the message is to be repeated. // This value is ignored if an embeddd repeat is found in str. -void parseStringAndSendPronto(const String str, uint16_t repeats) { +// Returns: +// bool: Successfully sent or not. +bool parseStringAndSendPronto(const String str, uint16_t repeats) { uint16_t count; uint16_t *code_array; int16_t index = -1; @@ -470,8 +894,8 @@ void parseStringAndSendPronto(const String str, uint16_t repeats) { count--; // We don't count the repeats value as part of the code array. } - // We need at least PRONTO_MIN_LENGTH values for the code part. - if (count < PRONTO_MIN_LENGTH) return; + // We need at least kProntoMinLength values for the code part. + if (count < kProntoMinLength) return false; // Now we know how many there are, allocate the memory to store them all. code_array = newCodeArray(count); @@ -481,7 +905,7 @@ void parseStringAndSendPronto(const String str, uint16_t repeats) { count = 0; do { index = str.indexOf(',', start_from); - // Convert the hexidecimal value string to an unsigned integer. + // Convert the hexadecimal value string to an unsigned integer. code_array[count] = strtoul(str.substring(start_from, index).c_str(), NULL, 16); start_from = index + 1; @@ -490,15 +914,22 @@ void parseStringAndSendPronto(const String str, uint16_t repeats) { irsend.sendPronto(code_array, count, repeats); // All done. Send it. free(code_array); // Free up the memory allocated. + if (count > 0) + return true; // We sent something. + return false; // We probably didn't. } +#endif // SEND_PRONTO -// Parse a IRremote Raw Hex String/code and send it. +#if SEND_RAW +// Parse an IRremote Raw Hex String/code and send it. // Args: // str: A comma-separated String containing the freq and raw IR data. // e.g. "38000,9000,4500,600,1450,600,900,650,1500,..." // Requires at least two comma-separated values. // First value is the transmission frequency in Hz or kHz. -void parseStringAndSendRaw(const String str) { +// Returns: +// bool: Successfully sent or not. +bool parseStringAndSendRaw(const String str) { uint16_t count; uint16_t freq = 38000; // Default to 38kHz. uint16_t *raw_array; @@ -508,7 +939,7 @@ void parseStringAndSendRaw(const String str) { // We expect the frequency as the first comma separated value, so we need at // least two values. If not, bail out. - if (count < 2) return; + if (count < 2) return false; count--; // We don't count the frequency value as part of the raw array. // Now we know how many there are, allocate the memory to store them all. @@ -530,7 +961,11 @@ void parseStringAndSendRaw(const String str) { irsend.sendRaw(raw_array, count, freq); // All done. Send it. free(raw_array); // Free up the memory allocated. + if (count > 0) + return true; // We sent something. + return false; // We probably didn't. } +#endif // SEND_RAW // Parse the URL args to find the IR code. void handleIr() { @@ -553,7 +988,8 @@ void handleIr() { repeat = atoi(server.arg(i).c_str()); } debug("New code received via HTTP"); - sendIRCode(ir_type, data, data_str.c_str(), nbits, repeat); + lastSendSucceeded = sendIRCode(ir_type, data, data_str.c_str(), nbits, + repeat); handleRoot(); } @@ -576,6 +1012,10 @@ void setup_wifi() { // We start by connecting to a WiFi network wifiManager.setTimeout(300); // Time out after 5 mins. +#if USE_STATIC_IP + // Use a static IP config rather than the one supplied via DHCP. + wifiManager.setSTAStaticIPConfig(kIPAddress, kGateway, kSubnetMask); +#endif // USE_STATIC_IP if (!wifiManager.autoConnect()) { debug("Wifi failed to connect and hit timeout."); delay(3000); @@ -584,14 +1024,27 @@ void setup_wifi() { delay(5000); } - debug("WiFi connected. IP address: " + WiFi.localIP()); + debug("WiFi connected. IP address: " + WiFi.localIP().toString()); } void setup(void) { irsend.begin(); + offset = irsend.calibrate(); +#if IR_RX +#if DECODE_HASH + // Ignore messages with less than minimum on or off pulses. + irrecv.setUnknownThreshold(kMinUnknownSize); +#endif // DECODE_HASH + irrecv.enableIRIn(); // Start the receiver +#endif // IR_RX #ifdef DEBUG - Serial.begin(115200); + // Use SERIAL_TX_ONLY so that the RX pin can be freed up for GPIO/IR use. + Serial.begin(BAUD_RATE, SERIAL_8N1, SERIAL_TX_ONLY); + while (!Serial) // Wait for the serial connection to be establised. + delay(50); + Serial.println(); + debug("IRMQTTServer " _MY_VERSION_" has booted."); #endif // DEBUG setup_wifi(); @@ -601,7 +1054,7 @@ void setup(void) { lastReconnectAttempt = 0; - if (mdns.begin(MQTTprefix, WiFi.localIP())) { + if (mdns.begin(HOSTNAME, WiFi.localIP())) { debug("MDNS responder started"); } @@ -667,12 +1120,13 @@ bool reconnect() { while (!mqtt_client.connected() && tries <= 3) { int connected = false; // Attempt to connect - debug("Attempting MQTT connection to " MQTT_SERVER ":" + String(MQTT_PORT) + + debug("Attempting MQTT connection to " MQTT_SERVER ":" + String(kMqttPort) + "... "); if (mqtt_user && mqtt_password) - connected = mqtt_client.connect(mqtt_clientid, mqtt_user, mqtt_password); + connected = mqtt_client.connect(mqtt_clientid.c_str(), mqtt_user, + mqtt_password); else - connected = mqtt_client.connect(mqtt_clientid); + connected = mqtt_client.connect(mqtt_clientid.c_str()); if (connected) { // Once connected, publish an announcement... mqtt_client.publish(MQTTack, "Connected"); @@ -692,32 +1146,57 @@ bool reconnect() { #endif // MQTT_ENABLE void loop(void) { - server.handleClient(); + server.handleClient(); // Handle any web activity #ifdef MQTT_ENABLE + uint32_t now = millis(); // MQTT client connection management if (!mqtt_client.connected()) { - uint32_t now = millis(); - // Reconnect if it's longer than MQTT_RECONNECT_TIME since we last tried. - if (now - lastReconnectAttempt > MQTT_RECONNECT_TIME) { + if (wasConnected) { + lastDisconnectedTime = now; + wasConnected = false; + mqttDisconnectCounter++; + } + // Reconnect if it's longer than kMqttReconnectTime since we last tried. + if (now - lastReconnectAttempt > kMqttReconnectTime) { lastReconnectAttempt = now; debug("client mqtt not connected, trying to connect"); // Attempt to reconnect if (reconnect()) { lastReconnectAttempt = 0; + wasConnected = true; if (boot) { mqtt_client.publish(MQTTack, "IR Server just booted"); boot = false; } else { - mqtt_client.publish(MQTTack, "IR Server just (re)connected to MQTT"); + String text = "IR Server just (re)connected to MQTT. " + "Lost connection about " + timeSince(lastConnectedTime); + mqtt_client.publish(MQTTack, text.c_str()); } + lastConnectedTime = now; + debug("successful client mqtt connection"); } } } else { + lastConnectedTime = now; // MQTT loop mqtt_client.loop(); } #endif // MQTT_ENABLE +#ifdef IR_RX + // Check if an IR code has been received via the IR RX module. + if (irrecv.decode(&capture)) { + lastIrReceivedTime = millis(); + lastIrReceived = String(capture.decode_type) + "," + + resultToHexidecimal(&capture); + // If it isn't an AC code, add the bits. + if (!hasACState(capture.decode_type)) + lastIrReceived += "," + String(capture.bits); + mqtt_client.publish(MQTTrecv, lastIrReceived.c_str()); + irRecvCounter++; + debug("Incoming IR message sent to MQTT: " + lastIrReceived); + } +#endif // IR_RX delay(100); } @@ -749,149 +1228,291 @@ uint64_t getUInt64fromHex(char const *str) { // code_str: The unparsed code to be sent. Used by complex protocol encodings. // bits: Nr. of bits in the protocol. 0 means use the protocol's default. // repeat: Nr. of times the message is to be repeated. (Not all protcols.) -void sendIRCode(int const ir_type, uint64_t const code, char const * code_str, +// Returns: +// bool: Successfully sent or not. +bool sendIRCode(int const ir_type, uint64_t const code, char const * code_str, uint16_t bits, uint16_t repeat) { // Create a pseudo-lock so we don't try to send two codes at the same time. while (ir_lock) delay(20); ir_lock = true; + bool success = true; // Assume success. + // send the IR message. switch (ir_type) { +#if SEND_RC5 case RC5: // 1 if (bits == 0) - bits = RC5_BITS; + bits = kRC5Bits; irsend.sendRC5(code, bits, repeat); break; +#endif +#if SEND_RC6 case RC6: // 2 if (bits == 0) - bits = RC6_MODE0_BITS; + bits = kRC6Mode0Bits; irsend.sendRC6(code, bits, repeat); break; +#endif +#if SEND_NEC case NEC: // 3 if (bits == 0) - bits = NEC_BITS; + bits = kNECBits; irsend.sendNEC(code, bits, repeat); break; +#endif +#if SEND_SONY case SONY: // 4 if (bits == 0) - bits = SONY_12_BITS; - repeat = std::max(repeat, (uint16_t) SONY_MIN_REPEAT); + bits = kSony12Bits; + repeat = std::max(repeat, kSonyMinRepeat); irsend.sendSony(code, bits, repeat); break; +#endif +#if SEND_PANASONIC case PANASONIC: // 5 if (bits == 0) - bits = PANASONIC_BITS; + bits = kPanasonicBits; irsend.sendPanasonic64(code, bits, repeat); break; +#endif +#if SEND_JVC case JVC: // 6 if (bits == 0) - bits = JVC_BITS; + bits = kJvcBits; irsend.sendJVC(code, bits, repeat); break; +#endif +#if SEND_SAMSUNG case SAMSUNG: // 7 if (bits == 0) - bits = SAMSUNG_BITS; + bits = kSamsungBits; irsend.sendSAMSUNG(code, bits, repeat); break; +#endif +#if SEND_WHYNTER case WHYNTER: // 8 if (bits == 0) - bits = WHYNTER_BITS; + bits = kWhynterBits; irsend.sendWhynter(code, bits, repeat); break; +#endif +#if SEND_AIWA_RC_T501 case AIWA_RC_T501: // 9 if (bits == 0) - bits = AIWA_RC_T501_BITS; - repeat = std::max(repeat, (uint16_t) AIWA_RC_T501_MIN_REPEAT); + bits = kAiwaRcT501Bits; + repeat = std::max(repeat, kAiwaRcT501MinRepeats); irsend.sendAiwaRCT501(code, bits, repeat); break; +#endif +#if SEND_LG case LG: // 10 if (bits == 0) - bits = LG_BITS; + bits = kLgBits; irsend.sendLG(code, bits, repeat); break; +#endif +#if SEND_MITSUBISHI case MITSUBISHI: // 12 if (bits == 0) - bits = MITSUBISHI_BITS; - repeat = std::max(repeat, (uint16_t) MITSUBISHI_MIN_REPEAT); + bits = kMitsubishiBits; + repeat = std::max(repeat, kMitsubishiMinRepeat); irsend.sendMitsubishi(code, bits, repeat); break; +#endif +#if SEND_DISH case DISH: // 13 if (bits == 0) - bits = DISH_BITS; - repeat = std::max(repeat, (uint16_t) DISH_MIN_REPEAT); + bits = kDishBits; + repeat = std::max(repeat, kDishMinRepeat); irsend.sendDISH(code, bits, repeat); break; +#endif +#if SEND_SHARP case SHARP: // 14 if (bits == 0) - bits = SHARP_BITS; + bits = kSharpBits; irsend.sendSharpRaw(code, bits, repeat); break; +#endif +#if SEND_COOLIX case COOLIX: // 15 if (bits == 0) - bits = COOLIX_BITS; + bits = kCoolixBits; irsend.sendCOOLIX(code, bits, repeat); break; +#endif + case DAIKIN: // 16 + case KELVINATOR: // 18 + case MITSUBISHI_AC: // 20 + case GREE: // 24 + case ARGO: // 27 + case TROTEC: // 28 + case TOSHIBA_AC: // 32 + case FUJITSU_AC: // 33 + case HAIER_AC: // 38 + case HAIER_AC_YRW02: // 44 + case HITACHI_AC: // 40 + case HITACHI_AC1: // 41 + case HITACHI_AC2: // 42 + case WHIRLPOOL_AC: // 45 + case SAMSUNG_AC: // 46 + case ELECTRA_AC: // 48 + case PANASONIC_AC: // 49 + case MWM: // 52 + success = parseStringAndSendAirCon(ir_type, code_str); + break; +#if SEND_DENON case DENON: // 17 if (bits == 0) bits = DENON_BITS; irsend.sendDenon(code, bits, repeat); break; - case KELVINATOR: // 18 - parseStringAndSendKelv(code_str); - break; +#endif +#if SEND_SHERWOOD case SHERWOOD: // 19 if (bits == 0) - bits = SHERWOOD_BITS; - repeat = std::max(repeat, (uint16_t) SHERWOOD_MIN_REPEAT); + bits = kSherwoodBits; + repeat = std::max(repeat, kSherwoodMinRepeat); irsend.sendSherwood(code, bits, repeat); break; +#endif +#if SEND_RCMM case RCMM: // 21 if (bits == 0) - bits == RCMM_BITS; + bits = kRCMMBits; irsend.sendRCMM(code, bits, repeat); break; +#endif +#if SEND_SANYO case SANYO_LC7461: // 22 if (bits == 0) - bits = SANYO_LC7461_BITS; + bits = kSanyoLC7461Bits; irsend.sendSanyoLC7461(code, bits, repeat); break; +#endif +#if SEND_RC5 case RC5X: // 23 if (bits == 0) - bits = RC5X_BITS; + bits = kRC5XBits; irsend.sendRC5(code, bits, repeat); - case PRONTO: // 25 - parseStringAndSendPronto(code_str, repeat); break; +#endif +#if SEND_PRONTO + case PRONTO: // 25 + success = parseStringAndSendPronto(code_str, repeat); + break; +#endif +#if SEND_NIKAI case NIKAI: // 29 if (bits == 0) - bits = NIKAI_BITS; + bits = kNikaiBits; irsend.sendNikai(code, bits, repeat); break; +#endif +#if SEND_RAW case RAW: // 30 - parseStringAndSendRaw(code_str); + success = parseStringAndSendRaw(code_str); break; +#endif +#if SEND_GLOBALCACHE case GLOBALCACHE: // 31 - parseStringAndSendGC(code_str); + success = parseStringAndSendGC(code_str); break; - } +#endif +#if SEND_MIDEA + case MIDEA: // 34 + if (bits == 0) + bits = kMideaBits; + irsend.sendMidea(code, bits, repeat); + break; +#endif +#if SEND_MAGIQUEST + case MAGIQUEST: // 35 + if (bits == 0) + bits = kMagiquestBits; + irsend.sendMagiQuest(code, bits, repeat); + break; +#endif +#if SEND_LASERTAG + case LASERTAG: // 36 + if (bits == 0) + bits = kLasertagBits; + irsend.sendLasertag(code, bits, repeat); + break; +#endif +#if SEND_CARRIER_AC + case CARRIER_AC: // 37 + if (bits == 0) + bits = kCarrierAcBits; + irsend.sendCarrierAC(code, bits, repeat); + break; +#endif +#if SEND_MITSUBISHI2 + case MITSUBISHI2: // 39 + if (bits == 0) + bits = kMitsubishiBits; + repeat = std::max(repeat, kMitsubishiMinRepeat); + irsend.sendMitsubishi2(code, bits, repeat); + break; +#endif +#if SEND_GICABLE + case GICABLE: // 43 + if (bits == 0) + bits = kGicableBits; + repeat = std::max(repeat, kGicableMinRepeat); + irsend.sendGICable(code, bits, repeat); + break; +#endif +#if SEND_LUTRON + case LUTRON: // 47 + if (bits == 0) + bits = kLutronBits; + irsend.sendLutron(code, bits, repeat); + break; +#endif +#if SEND_PIONEER + case PIONEER: // 50 + if (bits == 0) + bits = kPioneerBits; + irsend.sendPioneer(code, bits, repeat); + break; +#endif +#if SEND_LG + case LG2: // 51 + if (bits == 0) + bits = kLgBits; + irsend.sendLG2(code, bits, repeat); + break; +#endif + default: + // If we got here, we didn't know how to send it. + success = false; + } + lastSendTime = millis(); // Release the lock. ir_lock = false; - // Indicate that we sent the message. - debug("Sent the IR message."); + // Indicate that we sent the message or not. + if (success) { + sendReqCounter++; + debug("Sent the IR message:"); + } else { + debug("Failed to send IR Message:"); + } debug("Type: " + String(ir_type)); - switch (ir_type) { - case KELVINATOR: - case PRONTO: - case RAW: - case GLOBALCACHE: - debug("Code: "); - debug(code_str); - debug("Repeats: " + String(repeat)); - // Confirm what we were asked to send was sent. + // For "long" codes we basically repeat what we got. + if (hasACState((decode_type_t) ir_type) || + ir_type == PRONTO || + ir_type == RAW || + ir_type == GLOBALCACHE) { + debug("Code: "); + debug(code_str); + // Confirm what we were asked to send was sent. #ifdef MQTT_ENABLE + if (success) { if (ir_type == PRONTO && repeat > 0) mqtt_client.publish(MQTTack, (String(ir_type) + ",R" + String(repeat) + "," + @@ -899,20 +1520,21 @@ void sendIRCode(int const ir_type, uint64_t const code, char const * code_str, else mqtt_client.publish(MQTTack, (String(ir_type) + "," + String(code_str)).c_str()); + } #endif // MQTT_ENABLE - break; - default: - debug("Code: 0x" + uint64ToString(code, 16)); - debug("Bits: " + String(bits)); - debug("Repeats: " + String(repeat)); - + } else { // For "short" codes, we break it down a bit more before we report. + debug("Code: 0x" + uint64ToString(code, 16)); + debug("Bits: " + String(bits)); + debug("Repeats: " + String(repeat)); #ifdef MQTT_ENABLE + if (success) mqtt_client.publish(MQTTack, (String(ir_type) + "," + uint64ToString(code, 16) + "," + String(bits) + "," + String(repeat)).c_str()); #endif // MQTT_ENABLE } + return success; } #ifdef MQTT_ENABLE @@ -924,9 +1546,12 @@ void receivingMQTT(String const topic_name, String const callback_str) { debug("Receiving data by MQTT topic " + topic_name); - // Make a copy of the callback string as strtok destorys it. + // Make a copy of the callback string as strtok destroys it. char* callback_c_str = strdup(callback_str.c_str()); debug("MQTT Payload (raw): " + callback_str); + // Save the message as the last command seen (global). + lastMqttCmd = callback_str; + lastMqttCmdTime = millis(); // Get the numeric protocol type. int ir_type = strtoul(strtok_r(callback_c_str, ",", &tok_ptr), NULL, 10); @@ -952,9 +1577,10 @@ void receivingMQTT(String const topic_name, String const callback_str) { // send received MQTT value by IR signal - sendIRCode(ir_type, code, - callback_str.substring(callback_str.indexOf(",") + 1).c_str(), - nbits, repeat); + lastSendSucceeded = sendIRCode( + ir_type, code, + callback_str.substring(callback_str.indexOf(",") + 1).c_str(), + nbits, repeat); } // Callback function, when the gateway receive an MQTT value on the topics diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/platformio.ini similarity index 96% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/platformio.ini index c87e56962..27b44ddca 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/platformio.ini +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/platformio.ini @@ -7,7 +7,7 @@ build_flags = -DMQTT_MAX_PACKET_SIZE=512 lib_deps_builtin = lib_deps_external = PubSubClient - WifiManager@0.12 + WifiManager@0.14 [env:nodemcuv2] platform = espressif8266 diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRServer/IRServer.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRServer/IRServer.ino similarity index 88% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRServer/IRServer.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRServer/IRServer.ino index 82f2e7dd7..b378d3bd5 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRServer/IRServer.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRServer/IRServer.ino @@ -3,7 +3,8 @@ * Version 0.2 June, 2017 * Copyright 2015 Mark Szabo * - * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). + * An IR LED circuit *MUST* be connected to the ESP8266 on a pin + * as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -35,13 +36,15 @@ #include #include -const char* ssid = "....."; -const char* password = "....."; +const char* kSsid = "....."; +const char* kPassword = "....."; MDNSResponder mdns; ESP8266WebServer server(80); -IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). + +IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message. void handleRoot() { server.send(200, "text/html", @@ -61,7 +64,9 @@ void handleIr() { for (uint8_t i = 0; i < server.args(); i++) { if (server.argName(i) == "code") { uint32_t code = strtoul(server.arg(i).c_str(), NULL, 10); +#if SEND_NEC irsend.sendNEC(code, 32); +#endif // SEND_NEC } } handleRoot(); @@ -85,7 +90,7 @@ void setup(void) { irsend.begin(); Serial.begin(115200); - WiFi.begin(ssid, password); + WiFi.begin(kSsid, kPassword); Serial.println(""); // Wait for connection @@ -95,9 +100,9 @@ void setup(void) { } Serial.println(""); Serial.print("Connected to "); - Serial.println(ssid); + Serial.println(kSsid); Serial.print("IP address: "); - Serial.println(WiFi.localIP()); + Serial.println(WiFi.localIP().toString()); if (mdns.begin("esp8266", WiFi.localIP())) { Serial.println("MDNS responder started"); diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRServer/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRServer/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/IRrecvDemo.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/IRrecvDemo.ino similarity index 66% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/IRrecvDemo.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/IRrecvDemo.ino index ae9ed66f9..09babe4fe 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/IRrecvDemo.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/IRrecvDemo.ino @@ -1,6 +1,9 @@ /* * IRremoteESP8266: IRrecvDemo - demonstrates receiving IR codes with IRrecv - * An IR detector/demodulator must be connected to the input RECV_PIN. + * This is very simple teaching code to show you how to use the library. + * If you are trying to decode your Infra-Red remote(s) for later replay, + * use the IRrecvDumpV2.ino example code instead of this. + * An IR detector/demodulator must be connected to the input kRecvPin. * Copyright 2009 Ken Shirriff, http://arcfn.com * Example circuit diagram: * https://github.com/markszabo/IRremoteESP8266/wiki#ir-receiving @@ -22,15 +25,20 @@ // An IR detector/demodulator is connected to GPIO pin 14(D5 on a NodeMCU // board). -uint16_t RECV_PIN = 14; +const uint16_t kRecvPin = 14; -IRrecv irrecv(RECV_PIN); +IRrecv irrecv(kRecvPin); decode_results results; void setup() { Serial.begin(115200); irrecv.enableIRIn(); // Start the receiver + while (!Serial) // Wait for the serial connection to be establised. + delay(50); + Serial.println(); + Serial.print("IRrecvDemo is now running and waiting for IR message on Pin "); + Serial.println(kRecvPin); } void loop() { diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/IRrecvDump.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/IRrecvDump.ino similarity index 96% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/IRrecvDump.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/IRrecvDump.ino index 856449695..34f10dc83 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/IRrecvDump.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/IRrecvDump.ino @@ -86,10 +86,10 @@ void dump(decode_results *results) { if (i % 100 == 0) yield(); // Preemptive yield every 100th entry to feed the WDT. if (i & 1) { - Serial.print(results->rawbuf[i] * RAWTICK, DEC); + Serial.print(results->rawbuf[i] * kRawTick, DEC); } else { Serial.print(", "); - Serial.print((uint32_t) results->rawbuf[i] * RAWTICK, DEC); + Serial.print((uint32_t) results->rawbuf[i] * kRawTick, DEC); } } Serial.println("};"); diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/platformio.ini diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/IRrecvDumpV2.ino new file mode 100644 index 000000000..d72e0814c --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/IRrecvDumpV2.ino @@ -0,0 +1,262 @@ +/* + * IRremoteESP8266: IRrecvDumpV2 - dump details of IR codes with IRrecv + * An IR detector/demodulator must be connected to the input kRecvPin. + * + * Copyright 2009 Ken Shirriff, http://arcfn.com + * Copyright 2017 David Conran + * + * Example circuit diagram: + * https://github.com/markszabo/IRremoteESP8266/wiki#ir-receiving + * + * Changes: + * Version 0.4 July, 2018 + * - Minor improvements and more A/C unit support. + * Version 0.3 November, 2017 + * - Support for A/C decoding for some protcols. + * Version 0.2 April, 2017 + * - Decode from a copy of the data so we can start capturing faster thus + * reduce the likelihood of miscaptures. + * Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, + */ + +#ifndef UNIT_TEST +#include +#endif +#include +#include +#include +// The following are only needed for extended decoding of A/C Messages +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ==================== start of TUNEABLE PARAMETERS ==================== +// An IR detector/demodulator is connected to GPIO pin 14 +// e.g. D5 on a NodeMCU board. +const uint16_t kRecvPin = 14; + +// The Serial connection baud rate. +// i.e. Status message will be sent to the PC at this baud rate. +// Try to avoid slow speeds like 9600, as you will miss messages and +// cause other problems. 115200 (or faster) is recommended. +// NOTE: Make sure you set your Serial Monitor to the same speed. +const uint32_t kBaudRate = 115200; + +// As this program is a special purpose capture/decoder, let us use a larger +// than normal buffer so we can handle Air Conditioner remote codes. +const uint16_t kCaptureBufferSize = 1024; + +// kTimeout is the Nr. of milli-Seconds of no-more-data before we consider a +// message ended. +// This parameter is an interesting trade-off. The longer the timeout, the more +// complex a message it can capture. e.g. Some device protocols will send +// multiple message packets in quick succession, like Air Conditioner remotes. +// Air Coniditioner protocols often have a considerable gap (20-40+ms) between +// packets. +// The downside of a large timeout value is a lot of less complex protocols +// send multiple messages when the remote's button is held down. The gap between +// them is often also around 20+ms. This can result in the raw data be 2-3+ +// times larger than needed as it has captured 2-3+ messages in a single +// capture. Setting a low timeout value can resolve this. +// So, choosing the best kTimeout value for your use particular case is +// quite nuanced. Good luck and happy hunting. +// NOTE: Don't exceed kMaxTimeoutMs. Typically 130ms. +#if DECODE_AC +// Some A/C units have gaps in their protocols of ~40ms. e.g. Kelvinator +// A value this large may swallow repeats of some protocols +const uint8_t kTimeout = 50; +#else // DECODE_AC +// Suits most messages, while not swallowing many repeats. +const uint8_t kTimeout = 15; +#endif // DECODE_AC +// Alternatives: +// const uint8_t kTimeout = 90; +// Suits messages with big gaps like XMP-1 & some aircon units, but can +// accidentally swallow repeated messages in the rawData[] output. +// +// const uint8_t kTimeout = kMaxTimeoutMs; +// This will set it to our currently allowed maximum. +// Values this high are problematic because it is roughly the typical boundary +// where most messages repeat. +// e.g. It will stop decoding a message and start sending it to serial at +// precisely the time when the next message is likely to be transmitted, +// and may miss it. + +// Set the smallest sized "UNKNOWN" message packets we actually care about. +// This value helps reduce the false-positive detection rate of IR background +// noise as real messages. The chances of background IR noise getting detected +// as a message increases with the length of the kTimeout value. (See above) +// The downside of setting this message too large is you can miss some valid +// short messages for protocols that this library doesn't yet decode. +// +// Set higher if you get lots of random short UNKNOWN messages when nothing +// should be sending a message. +// Set lower if you are sure your setup is working, but it doesn't see messages +// from your device. (e.g. Other IR remotes work.) +// NOTE: Set this value very high to effectively turn off UNKNOWN detection. +const uint16_t kMinUnknownSize = 12; +// ==================== end of TUNEABLE PARAMETERS ==================== + +// Use turn on the save buffer feature for more complete capture coverage. +IRrecv irrecv(kRecvPin, kCaptureBufferSize, kTimeout, true); + +decode_results results; // Somewhere to store the results + +// Display the human readable state of an A/C message if we can. +void dumpACInfo(decode_results *results) { + String description = ""; +#if DECODE_DAIKIN + if (results->decode_type == DAIKIN) { + IRDaikinESP ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_DAIKIN +#if DECODE_FUJITSU_AC + if (results->decode_type == FUJITSU_AC) { + IRFujitsuAC ac(0); + ac.setRaw(results->state, results->bits / 8); + description = ac.toString(); + } +#endif // DECODE_FUJITSU_AC +#if DECODE_KELVINATOR + if (results->decode_type == KELVINATOR) { + IRKelvinatorAC ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_KELVINATOR +#if DECODE_MITSUBISHI_AC + if (results->decode_type == MITSUBISHI_AC) { + IRMitsubishiAC ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_MITSUBISHI_AC +#if DECODE_TOSHIBA_AC + if (results->decode_type == TOSHIBA_AC) { + IRToshibaAC ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_TOSHIBA_AC +#if DECODE_GREE + if (results->decode_type == GREE) { + IRGreeAC ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_GREE +#if DECODE_MIDEA + if (results->decode_type == MIDEA) { + IRMideaAC ac(0); + ac.setRaw(results->value); // Midea uses value instead of state. + description = ac.toString(); + } +#endif // DECODE_MIDEA +#if DECODE_HAIER_AC + if (results->decode_type == HAIER_AC) { + IRHaierAC ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_HAIER_AC +#if DECODE_HAIER_AC_YRW02 + if (results->decode_type == HAIER_AC_YRW02) { + IRHaierACYRW02 ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_HAIER_AC_YRW02 +#if DECODE_SAMSUNG_AC + if (results->decode_type == SAMSUNG_AC) { + IRSamsungAc ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_SAMSUNG_AC +#if DECODE_COOLIX + if (results->decode_type == COOLIX) { + IRCoolixAC ac(0); + ac.setRaw(results->value); // Coolix uses value instead of state. + description = ac.toString(); + } +#endif // DECODE_COOLIX +#if DECODE_PANASONIC_AC + if (results->decode_type == PANASONIC_AC && + results->bits > kPanasonicAcShortBits) { + IRPanasonicAc ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_PANASONIC_AC +#if DECODE_HITACHI_AC + if (results->decode_type == HITACHI_AC) { + IRHitachiAc ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_HITACHI_AC + // If we got a human-readable description of the message, display it. + if (description != "") Serial.println("Mesg Desc.: " + description); +} + +// The section of code run only once at start-up. +void setup() { + Serial.begin(kBaudRate, SERIAL_8N1, SERIAL_TX_ONLY); + while (!Serial) // Wait for the serial connection to be establised. + delay(50); + Serial.println(); + Serial.print("IRrecvDumpV2 is now running and waiting for IR input on Pin "); + Serial.println(kRecvPin); + +#if DECODE_HASH + // Ignore messages with less than minimum on or off pulses. + irrecv.setUnknownThreshold(kMinUnknownSize); +#endif // DECODE_HASH + irrecv.enableIRIn(); // Start the receiver +} + +// The repeating section of the code +// +void loop() { + // Check if the IR code has been received. + if (irrecv.decode(&results)) { + // Display a crude timestamp. + uint32_t now = millis(); + Serial.printf("Timestamp : %06u.%03u\n", now / 1000, now % 1000); + if (results.overflow) + Serial.printf( + "WARNING: IR code is too big for buffer (>= %d). " + "This result shouldn't be trusted until this is resolved. " + "Edit & increase kCaptureBufferSize.\n", + kCaptureBufferSize); + // Display the basic output of what we found. + Serial.print(resultToHumanReadableBasic(&results)); + dumpACInfo(&results); // Display any extra A/C info if we have it. + yield(); // Feed the WDT as the text output can take a while to print. + + // Display the library version the message was captured with. + Serial.print("Library : v"); + Serial.println(_IRREMOTEESP8266_VERSION_); + Serial.println(); + + // Output RAW timing info of the result. + Serial.println(resultToTimingInfo(&results)); + yield(); // Feed the WDT (again) + + // Output the results as source code + Serial.println(resultToSourceCode(&results)); + Serial.println(""); // Blank line between entries + yield(); // Feed the WDT (again) + } +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/IRsendDemo.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/IRsendDemo.ino similarity index 87% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/IRsendDemo.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/IRsendDemo.ino index 1a688cba3..892016b3e 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/IRsendDemo.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/IRsendDemo.ino @@ -4,7 +4,8 @@ * Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, * Copyright 2009 Ken Shirriff, http://arcfn.com * - * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). + * An IR LED circuit *MUST* be connected to the ESP8266 on a pin + * as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -33,7 +34,9 @@ #include #include -IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). + +IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message. // Example of data captured by IRrecvDumpV2.ino uint16_t rawData[67] = {9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, @@ -50,13 +53,19 @@ void setup() { } void loop() { +#if SEND_NEC Serial.println("NEC"); irsend.sendNEC(0x00FFE01FUL, 32); +#endif // SEND_NEC delay(2000); +#if SEND_SONY Serial.println("Sony"); irsend.sendSony(0xa90, 12, 2); +#endif // SEND_SONY delay(2000); +#if SEND_RAW Serial.println("a rawData capture from IRrecvDumpV2"); irsend.sendRaw(rawData, 67, 38); // Send a raw data capture at 38kHz. +#endif // SEND_RAW delay(2000); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/IRsendProntoDemo.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/IRsendProntoDemo.ino similarity index 93% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/IRsendProntoDemo.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/IRsendProntoDemo.ino index 0a7a014a7..3bef2179e 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/IRsendProntoDemo.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/IRsendProntoDemo.ino @@ -6,7 +6,7 @@ * Version 1.0 June, 2017 * * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2), unless you - * change the irsend() value below. + * change the kIrLed value below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -35,7 +35,9 @@ #include #include -IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). + +IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message. // Panasonic Plasma TV Descrete code (Power On). // Acquired from: @@ -96,10 +98,15 @@ void setup() { } void loop() { +#if SEND_PRONTO Serial.println("Sending a Samsung TV 'on' command."); irsend.sendPronto(samsungProntoCode, 72); delay(2000); Serial.println("Sending a Panasonic Plasma TV 'on' command."); irsend.sendPronto(panasonicProntoCode, 104); delay(2000); +#else // SEND_PRONTO + Serial.println("Can't send because SEND_PRONTO has been disabled."); + delay(10000); +#endif // SEND_PRONTO } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino b/lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino similarity index 64% rename from lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino index 9c7068000..ee2422915 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino @@ -4,7 +4,8 @@ * Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, Copyright 2009 Ken Shirriff, http://arcfn.com * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) * - * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). + * An IR LED circuit *MUST* be connected to the ESP8266 on a pin + * as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -33,12 +34,13 @@ #include #include -#define PanasonicAddress 0x4004 // Panasonic address (Pre data) -#define PanasonicPower 0x100BCBD // Panasonic Power button +const uint16_t kPanasonicAddress = 0x4004; // Panasonic address (Pre data) +const uint32_t kPanasonicPower = 0x100BCBD; // Panasonic Power button +const uint16_t kJVCPower = 0xC5E8; -#define JVCPower 0xC5E8 +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). -IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) +IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message. void setup() { irsend.begin(); @@ -46,11 +48,16 @@ void setup() { void loop() { // This should turn your TV on and off - irsend.sendPanasonic(PanasonicAddress, PanasonicPower); +#if SEND_PANASONIC + irsend.sendPanasonic(kPanasonicAddress, kPanasonicPower); +#else // SEND_PANASONIC + Serial.println("Can't send because SEND_PANASONIC has been disabled."); +#endif // SEND_PANASONIC - irsend.sendJVC(JVCPower, 16, 0); // hex value, 16 bits, no repeat - // see http://www.sbprojects.com/knowledge/ir/jvc.php for information - delayMicroseconds(50); - irsend.sendJVC(JVCPower, 16, 1); // hex value, 16 bits, repeat - delayMicroseconds(50); +#if SEND_JVC + irsend.sendJVC(kJVCPower, 16, 1); // hex value, 16 bits, single repeat +#else // SEND_JVC + Serial.println("Can't send because SEND_JVC has been disabled."); +#endif // SEND_JVC + delay(10000); // Wait 10 seconds before we repeat everything. } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/LGACSend/LGACSend.ino b/lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/LGACSend.ino similarity index 95% rename from lib/IRremoteESP8266-2.2.1.02/examples/LGACSend/LGACSend.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/LGACSend.ino index 7cced0c88..9139983c9 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/LGACSend/LGACSend.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/LGACSend.ino @@ -45,7 +45,11 @@ void Ac_Send_Code(uint32_t code) { Serial.print(" : "); Serial.println(code, HEX); +#if SEND_LG irsend.sendLG(code, 28); +#else // SEND_LG + Serial.println("Can't send because SEND_LG has been disabled."); +#endif // SEND_LG } void Ac_Activate(unsigned int temperature, unsigned int air_flow, @@ -60,9 +64,9 @@ void Ac_Activate(unsigned int temperature, unsigned int air_flow, else ac_msbits4 = 0; // cooling unsigned int ac_msbits5 = (temperature < 15) ? 0 : temperature - 15; - unsigned int ac_msbits6; + unsigned int ac_msbits6 = 0; - if (0 <= air_flow && air_flow <= 2) { + if (air_flow <= 2) { if (kAc_Type == 0) ac_msbits6 = kAc_Flow_Tower[air_flow]; else @@ -128,7 +132,7 @@ void setup() { } void loop() { - char b; + char b = ' '; Serial.println("# a : mode or temp b : air_flow, temp, swing, clean," " cooling/heating"); Serial.println("# 0 : off 0"); @@ -158,7 +162,7 @@ void loop() { default: Serial.println("b="); // Prompt User for input while (Serial.available() == 0) {} - char b = Serial.read(); + b = Serial.read(); } /* @@ -171,8 +175,8 @@ void loop() { # 4 : air_flow 0 ~ 3 : flow # + : temp + 1 # - : temp - 1 - # c : cooling - # h : heating + # c : cooling + # h : heating # m : change cooling to air clean, air clean to cooling */ Serial.print("a : "); @@ -194,7 +198,7 @@ void loop() { Ac_Change_Air_Swing(1); break; case '3': // 1 : clean on, power on - if (b == '0' | b == '1') + if (b == '0' || b == '1') Ac_Air_Clean(b); break; case '4': diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/TurnOnArgoAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/TurnOnArgoAC.ino similarity index 72% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/TurnOnArgoAC.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/TurnOnArgoAC.ino index a2e450ac5..3993d1151 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/TurnOnArgoAC.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/TurnOnArgoAC.ino @@ -1,5 +1,6 @@ -/* Copyright 2017 crankyoldgit -* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +/* Copyright 2017, 2018 crankyoldgit +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -29,10 +30,11 @@ #include #include -IRArgoAC argoir(4); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRArgoAC ac(kIrLed); // Set the GPIO to be used to sending the message. void setup() { - argoir.begin(); + ac.begin(); Serial.begin(115200); } @@ -40,13 +42,17 @@ void loop() { Serial.println("Sending..."); // Set up what we want to send. See ir_Argo.cpp for all the options. - argoir.setPower(true); - argoir.setFan(ARGO_FAN_1); - argoir.setCoolMode(ARGO_COOL_AUTO); - argoir.setTemp(25); + ac.setPower(true); + ac.setFan(kArgoFan1); + ac.setCoolMode(kArgoCoolAuto); + ac.setTemp(25); +#if SEND_ARGO // Now send the IR signal. - argoir.send(); + ac.send(); +#else // SEND_ARGO + Serial.println("Can't send because SEND_ARGO has been disabled."); +#endif // SEND_ARGO delay(5000); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino similarity index 64% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino index eb5cda5e7..b3ab757de 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino @@ -1,6 +1,7 @@ -/* Copyright 2016 sillyfrog +/* Copyright 2017 sillyfrog * -* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -30,10 +31,11 @@ #include #include -IRDaikinESP dakinir(D2); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRDaikinESP ac(kIrLed); // Set the GPIO to be used to sending the message void setup() { - dakinir.begin(); + ac.begin(); Serial.begin(115200); } @@ -42,15 +44,26 @@ void loop() { Serial.println("Sending..."); // Set up what we want to send. See ir_Daikin.cpp for all the options. - dakinir.on(); - dakinir.setFan(1); - dakinir.setMode(DAIKIN_COOL); - dakinir.setTemp(25); - dakinir.setSwingVertical(0); - dakinir.setSwingHorizontal(0); + ac.on(); + ac.setFan(1); + ac.setMode(kDaikinCool); + ac.setTemp(25); + ac.setSwingVertical(false); + ac.setSwingHorizontal(false); + + // Set the current time to 1:33PM (13:33) + // Time works in minutes past midnight + ac.setCurrentTime(13 * 60 + 33); + // Turn off about 1 hour later at 2:30PM (14:30) + ac.enableOffTimer(14 * 60 + 30); + + // Display what we are going to send. + Serial.println(ac.toString()); // Now send the IR signal. - dakinir.send(); +#if SEND_DAIKIN + ac.send(); +#endif // SEND_DAIKIN - delay(5000); + delay(15000); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino new file mode 100644 index 000000000..823a3f485 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino @@ -0,0 +1,50 @@ +// Copyright 2017 Jonny Graham, 2018 David Conran +#ifndef UNIT_TEST +#include +#endif +#include +#include +#include + +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRFujitsuAC ac(kIrLed); + +void printState() { + // Display the settings. + Serial.println("Fujitsu A/C remote is in the following state:"); + Serial.printf(" %s\n", ac.toString().c_str()); + // Display the encoded IR sequence. + unsigned char* ir_code = ac.getRaw(); + Serial.print("IR Code: 0x"); + for (uint8_t i = 0; i < ac.getStateLength(); i++) + Serial.printf("%02X", ir_code[i]); + Serial.println(); +} + +void setup() { + ac.begin(); + Serial.begin(115200); + delay(200); + + // Set up what we want to send. See ir_Fujitsu.cpp for all the options. + Serial.println("Default state of the remote."); + printState(); + Serial.println("Setting desired state for A/C."); + ac.setCmd(kFujitsuAcCmdTurnOn); + ac.setSwing(kFujitsuAcSwingBoth); + ac.setMode(kFujitsuAcModeCool); + ac.setFanSpeed(kFujitsuAcFanHigh); + ac.setTemp(24); // 24C +} + +void loop() { + // Now send the IR signal. + Serial.println("Sending IR command to A/C ..."); +#if SEND_FUJITSU_AC + ac.send(); +#else // SEND_FUJITSU_AC + Serial.println("Can't send because SEND_FUJITSU_AC has been disabled."); +#endif // SEND_FUJITSU_AC + printState(); + delay(5000); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino similarity index 63% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino index 393ba28ff..b9b700741 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino @@ -1,6 +1,7 @@ -/* Copyright 2016 David Conran +/* Copyright 2016, 2018 David Conran * -* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -29,29 +30,23 @@ #include #include -IRKelvinatorAC kelvir(D2); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRKelvinatorAC ac(kIrLed); // Set the GPIO to be used for sending messages. void printState() { // Display the settings. Serial.println("Kelvinator A/C remote is in the following state:"); - Serial.printf(" Basic\n Power: %d, Mode: %d, Temp: %dC, Fan Speed: %d\n", - kelvir.getPower(), kelvir.getMode(), kelvir.getTemp(), - kelvir.getFan()); - Serial.printf(" Options\n X-Fan: %d, Light: %d, Ion Filter: %d\n", - kelvir.getXFan(), kelvir.getLight(), kelvir.getIonFilter()); - Serial.printf(" Swing (V): %d, Swing (H): %d, Turbo: %d, Quiet: %d\n", - kelvir.getSwingVertical(), kelvir.getSwingHorizontal(), - kelvir.getTurbo(), kelvir.getQuiet()); + Serial.printf(" %s\n", ac.toString().c_str()); // Display the encoded IR sequence. - unsigned char* ir_code = kelvir.getRaw(); + unsigned char* ir_code = ac.getRaw(); Serial.print("IR Code: 0x"); - for (uint8_t i = 0; i < KELVINATOR_STATE_LENGTH; i++) + for (uint8_t i = 0; i < kKelvinatorStateLength; i++) Serial.printf("%02X", ir_code[i]); Serial.println(); } void setup() { - kelvir.begin(); + ac.begin(); Serial.begin(115200); delay(200); @@ -60,21 +55,23 @@ void setup() { Serial.println("Default state of the remote."); printState(); Serial.println("Setting desired state for A/C."); - kelvir.on(); - kelvir.setFan(1); - kelvir.setMode(KELVINATOR_COOL); - kelvir.setTemp(26); - kelvir.setSwingVertical(false); - kelvir.setSwingHorizontal(true); - kelvir.setXFan(true); - kelvir.setIonFilter(false); - kelvir.setLight(true); + ac.on(); + ac.setFan(1); + ac.setMode(kKelvinatorCool); + ac.setTemp(26); + ac.setSwingVertical(false); + ac.setSwingHorizontal(true); + ac.setXFan(true); + ac.setIonFilter(false); + ac.setLight(true); } void loop() { // Now send the IR signal. +#if SEND_KELVINATOR Serial.println("Sending IR command to A/C ..."); - kelvir.send(); + ac.send(); +#endif // SEND_KELVINATOR printState(); delay(5000); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino similarity index 72% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino index 1ea9b0d31..e719af68e 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino @@ -1,6 +1,7 @@ -/* Copyright 2017 David Conran +/* Copyright 2017, 2018 David Conran * -* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -29,25 +30,23 @@ #include #include -IRMitsubishiAC mitsubir(D2); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRMitsubishiAC ac(kIrLed); // Set the GPIO used for sending messages. void printState() { // Display the settings. Serial.println("Mitsubishi A/C remote is in the following state:"); - Serial.printf(" Power: %d, Mode: %d, Temp: %dC, Fan Speed: %d," \ - " Vane Mode: %d\n", - mitsubir.getPower(), mitsubir.getMode(), mitsubir.getTemp(), - mitsubir.getFan(), mitsubir.getVane()); + Serial.printf(" %s\n", ac.toString().c_str()); // Display the encoded IR sequence. - unsigned char* ir_code = mitsubir.getRaw(); + unsigned char* ir_code = ac.getRaw(); Serial.print("IR Code: 0x"); - for (uint8_t i = 0; i < MITSUBISHI_AC_STATE_LENGTH; i++) + for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) Serial.printf("%02X", ir_code[i]); Serial.println(); } void setup() { - mitsubir.begin(); + ac.begin(); Serial.begin(115200); delay(200); @@ -55,17 +54,19 @@ void setup() { Serial.println("Default state of the remote."); printState(); Serial.println("Setting desired state for A/C."); - mitsubir.on(); - mitsubir.setFan(1); - mitsubir.setMode(MITSUBISHI_AC_COOL); - mitsubir.setTemp(26); - mitsubir.setVane(MITSUBISHI_AC_VANE_AUTO); + ac.on(); + ac.setFan(1); + ac.setMode(kMitsubishiAcCool); + ac.setTemp(26); + ac.setVane(kMitsubishiAcVaneAuto); } void loop() { // Now send the IR signal. +#if SEND_MITSUBISHI_AC Serial.println("Sending IR command to A/C ..."); - mitsubir.send(); + ac.send(); +#endif // SEND_MITSUBISHI_AC printState(); delay(5000); } diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino new file mode 100644 index 000000000..d78178098 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino @@ -0,0 +1,71 @@ +/* Copyright 2017, 2018 David Conran +* +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. +* +* TL;DR: The IR LED needs to be driven by a transistor for a good result. +* +* Suggested circuit: +* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending +* +* Common mistakes & tips: +* * Don't just connect the IR LED directly to the pin, it won't +* have enough current to drive the IR LED effectively. +* * Make sure you have the IR LED polarity correct. +* See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity +* * Typical digital camera/phones can be used to see if the IR LED is flashed. +* Replace the IR LED with a normal LED if you don't have a digital camera +* when debugging. +* * Avoid using the following pins unless you really know what you are doing: +* * Pin 0/D3: Can interfere with the boot/program mode & support circuits. +* * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will interfere. +* * Pin 3/RX/RXD0: Any serial transmissions to the ESP8266 will interfere. +* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs +* for your first time. e.g. ESP-12 etc. +*/ +#ifndef UNIT_TEST +#include +#endif +#include +#include +#include + +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRToshibaAC ac(kIrLed); // Set the GPIO to be used for sending messages. + +void printState() { + // Display the settings. + Serial.println("Toshiba A/C remote is in the following state:"); + Serial.printf(" %s\n", ac.toString().c_str()); + // Display the encoded IR sequence. + unsigned char* ir_code = ac.getRaw(); + Serial.print("IR Code: 0x"); + for (uint8_t i = 0; i < kToshibaACStateLength; i++) + Serial.printf("%02X", ir_code[i]); + Serial.println(); +} + +void setup() { + ac.begin(); + Serial.begin(115200); + delay(200); + + // Set up what we want to send. See ir_Toshiba.cpp for all the options. + Serial.println("Default state of the remote."); + printState(); + Serial.println("Setting desired state for A/C."); + ac.on(); + ac.setFan(1); + ac.setMode(kToshibaAcCool); + ac.setTemp(26); +} + +void loop() { + // Now send the IR signal. +#if SEND_TOSHIBA_AC + Serial.println("Sending IR command to A/C ..."); + ac.send(); +#endif // SEND_TOSHIBA_AC + printState(); + delay(5000); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino similarity index 74% rename from lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino rename to lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino index 2476ff557..b7881eead 100644 --- a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino @@ -1,5 +1,6 @@ /* Copyright 2017 stufisher -* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. * * TL;DR: The IR LED needs to be driven by a transistor for a good result. * @@ -29,10 +30,11 @@ #include #include -IRTrotecESP trotecir(D2); // An IR LED is controlled by GPIO pin 4 (D2) +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRTrotecESP ac(kIrLed); // Set the GPIO to be used for sending messages. void setup() { - trotecir.begin(); + ac.begin(); Serial.begin(115200); } @@ -40,13 +42,17 @@ void loop() { Serial.println("Sending..."); // Set up what we want to send. See ir_Trotec.cpp for all the options. - trotecir.setPower(true); - trotecir.setSpeed(TROTEC_FAN_LOW); - trotecir.setMode(TROTEC_COOL); - trotecir.setTemp(25); + ac.setPower(true); + ac.setSpeed(kTrotecFanLow); + ac.setMode(kTrotecCool); + ac.setTemp(25); // Now send the IR signal. - trotecir.send(); +#if SEND_TROTEC + ac.send(); +#else // SEND_TROTEC + Serial.println("Can't send because SEND_TROTEC has been disabled."); +#endif // SEND_TROTEC delay(5000); } diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/platformio.ini @@ -0,0 +1,17 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/keywords.txt b/lib/IRremoteESP8266-2.5.2.03/keywords.txt new file mode 100644 index 000000000..ac3f43fe1 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/keywords.txt @@ -0,0 +1,1645 @@ +######################################### +# Syntax Coloring Map For IRremoteESP8266 +######################################### + +################################################ +# WARNING: Do NOT edit this file directly. +# It is generated by 'tools/mkkeywords' +# e.g. tools/mkkeywords > keywords.txt +################################################ + +####################################################### +# The Arduino IDE requires the use of a tab separator +# between the name and identifier. Without this tab the +# keyword is not highlighted. +# +# Reference: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords +####################################################### + +####################################### +# Datatypes & Classes (KEYWORD1) +####################################### + +IRArgoAC KEYWORD1 +IRCoolixAC KEYWORD1 +IRDaikinESP KEYWORD1 +IRFujitsuAC KEYWORD1 +IRGreeAC KEYWORD1 +IRHaierAC KEYWORD1 +IRHaierACYRW02 KEYWORD1 +IRKelvinatorAC KEYWORD1 +IRMideaAC KEYWORD1 +IRMitsubishiAC KEYWORD1 +IRPanasonicAc KEYWORD1 +IRSamsungAc KEYWORD1 +IRToshibaAC KEYWORD1 +IRTrotecESP KEYWORD1 +IRrecv KEYWORD1 +IRsend KEYWORD1 +IRtimer KEYWORD1 +decode_results KEYWORD1 +ir_params_t KEYWORD1 +match_result_t KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +_delayMicroseconds KEYWORD2 +add KEYWORD2 +addbit KEYWORD2 +begin KEYWORD2 +buildFromState KEYWORD2 +buildState KEYWORD2 +calcBlockChecksum KEYWORD2 +calcChecksum KEYWORD2 +calcLGChecksum KEYWORD2 +calcUSecPeriod KEYWORD2 +calculateChecksum KEYWORD2 +calibrate KEYWORD2 +cancelOffTimer KEYWORD2 +cancelOnTimer KEYWORD2 +cancelTimers KEYWORD2 +checkheader KEYWORD2 +checksum KEYWORD2 +clearBit KEYWORD2 +clearSensorTemp KEYWORD2 +compare KEYWORD2 +copyIrParams KEYWORD2 +decode KEYWORD2 +decodeAiwaRCT501 KEYWORD2 +decodeCOOLIX KEYWORD2 +decodeCarrierAC KEYWORD2 +decodeDISH KEYWORD2 +decodeDaikin KEYWORD2 +decodeDenon KEYWORD2 +decodeElectraAC KEYWORD2 +decodeFujitsuAC KEYWORD2 +decodeGICable KEYWORD2 +decodeGree KEYWORD2 +decodeHaierAC KEYWORD2 +decodeHaierACYRW02 KEYWORD2 +decodeHash KEYWORD2 +decodeHitachiAC KEYWORD2 +decodeJVC KEYWORD2 +decodeKelvinator KEYWORD2 +decodeLG KEYWORD2 +decodeLasertag KEYWORD2 +decodeLutron KEYWORD2 +decodeMWM KEYWORD2 +decodeMagiQuest KEYWORD2 +decodeMidea KEYWORD2 +decodeMitsubishi KEYWORD2 +decodeMitsubishi2 KEYWORD2 +decodeMitsubishiAC KEYWORD2 +decodeNEC KEYWORD2 +decodeNikai KEYWORD2 +decodePanasonic KEYWORD2 +decodePanasonicAC KEYWORD2 +decodePioneer KEYWORD2 +decodeRC5 KEYWORD2 +decodeRC6 KEYWORD2 +decodeRCMM KEYWORD2 +decodeSAMSUNG KEYWORD2 +decodeSamsungAC KEYWORD2 +decodeSanyo KEYWORD2 +decodeSanyoLC7461 KEYWORD2 +decodeSharp KEYWORD2 +decodeSony KEYWORD2 +decodeToshibaAC KEYWORD2 +decodeWhirlpoolAC KEYWORD2 +decodeWhynter KEYWORD2 +disableIRIn KEYWORD2 +disableOffTimer KEYWORD2 +disableOnTimer KEYWORD2 +elapsed KEYWORD2 +enableIRIn KEYWORD2 +enableIROut KEYWORD2 +enableOffTimer KEYWORD2 +enableOnTimer KEYWORD2 +encodeJVC KEYWORD2 +encodeLG KEYWORD2 +encodeMagiQuest KEYWORD2 +encodeNEC KEYWORD2 +encodePanasonic KEYWORD2 +encodePioneer KEYWORD2 +encodeRC5 KEYWORD2 +encodeRC5X KEYWORD2 +encodeRC6 KEYWORD2 +encodeSAMSUNG KEYWORD2 +encodeSanyoLC7461 KEYWORD2 +encodeSharp KEYWORD2 +encodeSony KEYWORD2 +encodeTime KEYWORD2 +fixChecksum KEYWORD2 +fixup KEYWORD2 +getBeep KEYWORD2 +getBit KEYWORD2 +getBufSize KEYWORD2 +getButton KEYWORD2 +getClean KEYWORD2 +getClock KEYWORD2 +getCmd KEYWORD2 +getCommand KEYWORD2 +getCoolMode KEYWORD2 +getCorrectedRawLength KEYWORD2 +getCurrTime KEYWORD2 +getCurrentTime KEYWORD2 +getEcono KEYWORD2 +getEye KEYWORD2 +getFan KEYWORD2 +getFanSpeed KEYWORD2 +getFlap KEYWORD2 +getHealth KEYWORD2 +getHeatMode KEYWORD2 +getIonFilter KEYWORD2 +getLed KEYWORD2 +getLight KEYWORD2 +getMax KEYWORD2 +getMode KEYWORD2 +getMold KEYWORD2 +getNight KEYWORD2 +getOffTime KEYWORD2 +getOffTimer KEYWORD2 +getOffTimerEnabled KEYWORD2 +getOnTime KEYWORD2 +getOnTimer KEYWORD2 +getOnTimerEnabled KEYWORD2 +getPower KEYWORD2 +getPowerful KEYWORD2 +getQuiet KEYWORD2 +getRClevel KEYWORD2 +getRaw KEYWORD2 +getSensor KEYWORD2 +getSensorTemp KEYWORD2 +getSleep KEYWORD2 +getSpeed KEYWORD2 +getStartClock KEYWORD2 +getStateLength KEYWORD2 +getStopClock KEYWORD2 +getSwing KEYWORD2 +getSwingHorizontal KEYWORD2 +getSwingVertical KEYWORD2 +getSwingVerticalAuto KEYWORD2 +getSwingVerticalPosition KEYWORD2 +getTemp KEYWORD2 +getTempRaw KEYWORD2 +getTime KEYWORD2 +getTimer KEYWORD2 +getTurbo KEYWORD2 +getVane KEYWORD2 +getXFan KEYWORD2 +getZoneFollow KEYWORD2 +getiFeel KEYWORD2 +hasACState KEYWORD2 +invertBits KEYWORD2 +isOffTimerEnabled KEYWORD2 +isOnTimerEnabled KEYWORD2 +ledOff KEYWORD2 +ledOn KEYWORD2 +mark KEYWORD2 +match KEYWORD2 +matchAtLeast KEYWORD2 +matchData KEYWORD2 +matchMark KEYWORD2 +matchSpace KEYWORD2 +off KEYWORD2 +on KEYWORD2 +printState KEYWORD2 +readbits KEYWORD2 +renderTime KEYWORD2 +reset KEYWORD2 +resultToHexidecimal KEYWORD2 +resultToHumanReadableBasic KEYWORD2 +resultToSourceCode KEYWORD2 +resultToTimingInfo KEYWORD2 +resume KEYWORD2 +reverseBits KEYWORD2 +send KEYWORD2 +sendAiwaRCT501 KEYWORD2 +sendArgo KEYWORD2 +sendCOOLIX KEYWORD2 +sendCarrierAC KEYWORD2 +sendDISH KEYWORD2 +sendDaikin KEYWORD2 +sendData KEYWORD2 +sendDenon KEYWORD2 +sendElectraAC KEYWORD2 +sendExtended KEYWORD2 +sendFujitsuAC KEYWORD2 +sendGC KEYWORD2 +sendGICable KEYWORD2 +sendGeneric KEYWORD2 +sendGree KEYWORD2 +sendHaierAC KEYWORD2 +sendHaierACYRW02 KEYWORD2 +sendHitachiAC KEYWORD2 +sendHitachiAC1 KEYWORD2 +sendHitachiAC2 KEYWORD2 +sendJVC KEYWORD2 +sendKelvinator KEYWORD2 +sendLG KEYWORD2 +sendLG2 KEYWORD2 +sendLasertag KEYWORD2 +sendLutron KEYWORD2 +sendMWM KEYWORD2 +sendMagiQuest KEYWORD2 +sendMidea KEYWORD2 +sendMitsubishi KEYWORD2 +sendMitsubishi2 KEYWORD2 +sendMitsubishiAC KEYWORD2 +sendNEC KEYWORD2 +sendNikai KEYWORD2 +sendPanasonic KEYWORD2 +sendPanasonic64 KEYWORD2 +sendPanasonicAC KEYWORD2 +sendPioneer KEYWORD2 +sendPronto KEYWORD2 +sendRC5 KEYWORD2 +sendRC6 KEYWORD2 +sendRCMM KEYWORD2 +sendRaw KEYWORD2 +sendSAMSUNG KEYWORD2 +sendSamsungAC KEYWORD2 +sendSanyoLC7461 KEYWORD2 +sendSharp KEYWORD2 +sendSharpRaw KEYWORD2 +sendSherwood KEYWORD2 +sendSony KEYWORD2 +sendToshibaAC KEYWORD2 +sendTrotec KEYWORD2 +sendWhirlpoolAC KEYWORD2 +sendWhynter KEYWORD2 +serialPrintUint64 KEYWORD2 +setBeep KEYWORD2 +setBit KEYWORD2 +setButton KEYWORD2 +setClean KEYWORD2 +setClock KEYWORD2 +setCmd KEYWORD2 +setCommand KEYWORD2 +setCoolMode KEYWORD2 +setCurrTime KEYWORD2 +setCurrentTime KEYWORD2 +setEcono KEYWORD2 +setEye KEYWORD2 +setFan KEYWORD2 +setFanSpeed KEYWORD2 +setFlap KEYWORD2 +setHealth KEYWORD2 +setHeatMode KEYWORD2 +setIonFilter KEYWORD2 +setLed KEYWORD2 +setLight KEYWORD2 +setMax KEYWORD2 +setMode KEYWORD2 +setModel KEYWORD2 +setMold KEYWORD2 +setNight KEYWORD2 +setOffTimer KEYWORD2 +setOnTimer KEYWORD2 +setPower KEYWORD2 +setPowerful KEYWORD2 +setQuiet KEYWORD2 +setRaw KEYWORD2 +setRoomTemp KEYWORD2 +setSensor KEYWORD2 +setSensorTemp KEYWORD2 +setSensorTempRaw KEYWORD2 +setSleep KEYWORD2 +setSpeed KEYWORD2 +setStartClock KEYWORD2 +setStopClock KEYWORD2 +setSwing KEYWORD2 +setSwingHorizontal KEYWORD2 +setSwingVertical KEYWORD2 +setTemp KEYWORD2 +setTempRaw KEYWORD2 +setTime KEYWORD2 +setTimer KEYWORD2 +setTurbo KEYWORD2 +setUnknownThreshold KEYWORD2 +setVane KEYWORD2 +setXFan KEYWORD2 +setZoneFollow KEYWORD2 +setiFeel KEYWORD2 +space KEYWORD2 +stateReset KEYWORD2 +stepHoriz KEYWORD2 +stepVert KEYWORD2 +sumBytes KEYWORD2 +ticksHigh KEYWORD2 +ticksLow KEYWORD2 +timeToString KEYWORD2 +toString KEYWORD2 +toggleRC5 KEYWORD2 +toggleRC6 KEYWORD2 +typeToString KEYWORD2 +uint64ToString KEYWORD2 +validChecksum KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +AIWA_RC_T501 LITERAL1 +AIWA_RC_T501_BITS LITERAL1 +ALLOW_DELAY_CALLS LITERAL1 +ARDB1 LITERAL1 +ARGO LITERAL1 +ARGO_COMMAND_LENGTH LITERAL1 +ARGO_COOL_AUTO LITERAL1 +ARGO_COOL_OFF LITERAL1 +ARGO_COOL_ON LITERAL1 +ARGO_COOl_HUM LITERAL1 +ARGO_FAN_1 LITERAL1 +ARGO_FAN_2 LITERAL1 +ARGO_FAN_3 LITERAL1 +ARGO_FAN_AUTO LITERAL1 +ARGO_FLAP_1 LITERAL1 +ARGO_FLAP_2 LITERAL1 +ARGO_FLAP_3 LITERAL1 +ARGO_FLAP_4 LITERAL1 +ARGO_FLAP_5 LITERAL1 +ARGO_FLAP_6 LITERAL1 +ARGO_FLAP_AUTO LITERAL1 +ARGO_FLAP_FULL LITERAL1 +ARGO_HEAT_AUTO LITERAL1 +ARGO_HEAT_BLINK LITERAL1 +ARGO_HEAT_ON LITERAL1 +ARGO_MAX_TEMP LITERAL1 +ARGO_MIN_TEMP LITERAL1 +ARRAH2E LITERAL1 +CARRIER_AC LITERAL1 +CARRIER_AC_BITS LITERAL1 +COOLIX LITERAL1 +COOLIX_BITS LITERAL1 +DAIKIN LITERAL1 +DAIKIN_AUTO LITERAL1 +DAIKIN_COMMAND_LENGTH LITERAL1 +DAIKIN_COOL LITERAL1 +DAIKIN_DEBUG LITERAL1 +DAIKIN_DRY LITERAL1 +DAIKIN_FAN LITERAL1 +DAIKIN_FAN_AUTO LITERAL1 +DAIKIN_FAN_MAX LITERAL1 +DAIKIN_FAN_MIN LITERAL1 +DAIKIN_FAN_QUIET LITERAL1 +DAIKIN_HEAT LITERAL1 +DAIKIN_MAX_TEMP LITERAL1 +DAIKIN_MIN_TEMP LITERAL1 +DECODE_AC LITERAL1 +DECODE_AIWA_RC_T501 LITERAL1 +DECODE_ARGO LITERAL1 +DECODE_CARRIER_AC LITERAL1 +DECODE_COOLIX LITERAL1 +DECODE_DAIKIN LITERAL1 +DECODE_DENON LITERAL1 +DECODE_DISH LITERAL1 +DECODE_ELECTRA_AC LITERAL1 +DECODE_FUJITSU_AC LITERAL1 +DECODE_GICABLE LITERAL1 +DECODE_GLOBALCACHE LITERAL1 +DECODE_GREE LITERAL1 +DECODE_HAIER_AC LITERAL1 +DECODE_HAIER_AC_YRW02 LITERAL1 +DECODE_HASH LITERAL1 +DECODE_HITACHI_AC LITERAL1 +DECODE_HITACHI_AC1 LITERAL1 +DECODE_HITACHI_AC2 LITERAL1 +DECODE_JVC LITERAL1 +DECODE_KELVINATOR LITERAL1 +DECODE_LASERTAG LITERAL1 +DECODE_LG LITERAL1 +DECODE_LUTRON LITERAL1 +DECODE_MAGIQUEST LITERAL1 +DECODE_MIDEA LITERAL1 +DECODE_MITSUBISHI LITERAL1 +DECODE_MITSUBISHI2 LITERAL1 +DECODE_MITSUBISHI_AC LITERAL1 +DECODE_MWM LITERAL1 +DECODE_NEC LITERAL1 +DECODE_NIKAI LITERAL1 +DECODE_PANASONIC LITERAL1 +DECODE_PANASONIC_AC LITERAL1 +DECODE_PIONEER LITERAL1 +DECODE_PRONTO LITERAL1 +DECODE_RC5 LITERAL1 +DECODE_RC6 LITERAL1 +DECODE_RCMM LITERAL1 +DECODE_SAMSUNG LITERAL1 +DECODE_SAMSUNG_AC LITERAL1 +DECODE_SANYO LITERAL1 +DECODE_SHARP LITERAL1 +DECODE_SHERWOOD LITERAL1 +DECODE_SONY LITERAL1 +DECODE_TOSHIBA_AC LITERAL1 +DECODE_TROTEC LITERAL1 +DECODE_WHIRLPOOL_AC LITERAL1 +DECODE_WHYNTER LITERAL1 +DENON LITERAL1 +DENON_48_BITS LITERAL1 +DENON_BITS LITERAL1 +DENON_LEGACY_BITS LITERAL1 +DISH LITERAL1 +DISH_BITS LITERAL1 +ELECTRA_AC LITERAL1 +FUJITSU_AC LITERAL1 +FUJITSU_AC_BITS LITERAL1 +FUJITSU_AC_CMD_STAY_ON LITERAL1 +FUJITSU_AC_CMD_STEP_HORIZ LITERAL1 +FUJITSU_AC_CMD_STEP_VERT LITERAL1 +FUJITSU_AC_CMD_TURN_OFF LITERAL1 +FUJITSU_AC_CMD_TURN_ON LITERAL1 +FUJITSU_AC_FAN_AUTO LITERAL1 +FUJITSU_AC_FAN_HIGH LITERAL1 +FUJITSU_AC_FAN_LOW LITERAL1 +FUJITSU_AC_FAN_MED LITERAL1 +FUJITSU_AC_FAN_QUIET LITERAL1 +FUJITSU_AC_MAX_TEMP LITERAL1 +FUJITSU_AC_MIN_BITS LITERAL1 +FUJITSU_AC_MIN_REPEAT LITERAL1 +FUJITSU_AC_MIN_TEMP LITERAL1 +FUJITSU_AC_MODE_AUTO LITERAL1 +FUJITSU_AC_MODE_COOL LITERAL1 +FUJITSU_AC_MODE_DRY LITERAL1 +FUJITSU_AC_MODE_FAN LITERAL1 +FUJITSU_AC_MODE_HEAT LITERAL1 +FUJITSU_AC_STATE_LENGTH LITERAL1 +FUJITSU_AC_STATE_LENGTH_SHORT LITERAL1 +FUJITSU_AC_SWING_BOTH LITERAL1 +FUJITSU_AC_SWING_HORIZ LITERAL1 +FUJITSU_AC_SWING_OFF LITERAL1 +FUJITSU_AC_SWING_VERT LITERAL1 +GICABLE LITERAL1 +GICABLE_BITS LITERAL1 +GLOBALCACHE LITERAL1 +GREE LITERAL1 +GREE_AUTO LITERAL1 +GREE_COOL LITERAL1 +GREE_DRY LITERAL1 +GREE_FAN LITERAL1 +GREE_FAN_MAX LITERAL1 +GREE_HEAT LITERAL1 +GREE_MAX_TEMP LITERAL1 +GREE_MIN_TEMP LITERAL1 +GREE_STATE_LENGTH LITERAL1 +GREE_SWING_AUTO LITERAL1 +GREE_SWING_DOWN LITERAL1 +GREE_SWING_DOWN_AUTO LITERAL1 +GREE_SWING_LAST_POS LITERAL1 +GREE_SWING_MIDDLE LITERAL1 +GREE_SWING_MIDDLE_AUTO LITERAL1 +GREE_SWING_MIDDLE_DOWN LITERAL1 +GREE_SWING_MIDDLE_UP LITERAL1 +GREE_SWING_UP LITERAL1 +GREE_SWING_UP_AUTO LITERAL1 +HAIER_AC LITERAL1 +HAIER_AC_AUTO LITERAL1 +HAIER_AC_CMD_FAN LITERAL1 +HAIER_AC_CMD_HEALTH LITERAL1 +HAIER_AC_CMD_MODE LITERAL1 +HAIER_AC_CMD_OFF LITERAL1 +HAIER_AC_CMD_ON LITERAL1 +HAIER_AC_CMD_SLEEP LITERAL1 +HAIER_AC_CMD_SWING LITERAL1 +HAIER_AC_CMD_TEMP_DOWN LITERAL1 +HAIER_AC_CMD_TEMP_UP LITERAL1 +HAIER_AC_CMD_TIMER_CANCEL LITERAL1 +HAIER_AC_CMD_TIMER_SET LITERAL1 +HAIER_AC_COOL LITERAL1 +HAIER_AC_DEF_TEMP LITERAL1 +HAIER_AC_DRY LITERAL1 +HAIER_AC_FAN LITERAL1 +HAIER_AC_FAN_AUTO LITERAL1 +HAIER_AC_FAN_HIGH LITERAL1 +HAIER_AC_FAN_LOW LITERAL1 +HAIER_AC_FAN_MED LITERAL1 +HAIER_AC_HEAT LITERAL1 +HAIER_AC_MAX_TEMP LITERAL1 +HAIER_AC_MIN_TEMP LITERAL1 +HAIER_AC_STATE_LENGTH LITERAL1 +HAIER_AC_SWING_CHG LITERAL1 +HAIER_AC_SWING_DOWN LITERAL1 +HAIER_AC_SWING_OFF LITERAL1 +HAIER_AC_SWING_UP LITERAL1 +HAIER_AC_YRW02 LITERAL1 +HAIER_AC_YRW02_AUTO LITERAL1 +HAIER_AC_YRW02_BUTTON_FAN LITERAL1 +HAIER_AC_YRW02_BUTTON_HEALTH LITERAL1 +HAIER_AC_YRW02_BUTTON_MODE LITERAL1 +HAIER_AC_YRW02_BUTTON_POWER LITERAL1 +HAIER_AC_YRW02_BUTTON_SLEEP LITERAL1 +HAIER_AC_YRW02_BUTTON_SWING LITERAL1 +HAIER_AC_YRW02_BUTTON_TEMP_DOWN LITERAL1 +HAIER_AC_YRW02_BUTTON_TEMP_UP LITERAL1 +HAIER_AC_YRW02_BUTTON_TURBO LITERAL1 +HAIER_AC_YRW02_COOL LITERAL1 +HAIER_AC_YRW02_DRY LITERAL1 +HAIER_AC_YRW02_FAN LITERAL1 +HAIER_AC_YRW02_FAN_AUTO LITERAL1 +HAIER_AC_YRW02_FAN_HIGH LITERAL1 +HAIER_AC_YRW02_FAN_LOW LITERAL1 +HAIER_AC_YRW02_FAN_MED LITERAL1 +HAIER_AC_YRW02_HEAT LITERAL1 +HAIER_AC_YRW02_STATE_LENGTH LITERAL1 +HAIER_AC_YRW02_SWING_AUTO LITERAL1 +HAIER_AC_YRW02_SWING_BOTTOM LITERAL1 +HAIER_AC_YRW02_SWING_DOWN LITERAL1 +HAIER_AC_YRW02_SWING_MIDDLE LITERAL1 +HAIER_AC_YRW02_SWING_OFF LITERAL1 +HAIER_AC_YRW02_SWING_TOP LITERAL1 +HAIER_AC_YRW02_TURBO_HIGH LITERAL1 +HAIER_AC_YRW02_TURBO_LOW LITERAL1 +HAIER_AC_YRW02_TURBO_OFF LITERAL1 +HIGH LITERAL1 +HITACHI_AC LITERAL1 +HITACHI_AC1 LITERAL1 +HITACHI_AC1_BITS LITERAL1 +HITACHI_AC1_STATE_LENGTH LITERAL1 +HITACHI_AC2 LITERAL1 +HITACHI_AC2_BITS LITERAL1 +HITACHI_AC2_STATE_LENGTH LITERAL1 +HITACHI_AC_BITS LITERAL1 +HITACHI_AC_STATE_LENGTH LITERAL1 +ICACHE_RAM_ATTR LITERAL1 +JVC LITERAL1 +JVC_BITS LITERAL1 +KELVINATOR LITERAL1 +KELVINATOR_AUTO LITERAL1 +KELVINATOR_AUTO_TEMP LITERAL1 +KELVINATOR_BASIC_FAN_MAX LITERAL1 +KELVINATOR_COOL LITERAL1 +KELVINATOR_DRY LITERAL1 +KELVINATOR_FAN LITERAL1 +KELVINATOR_FAN_AUTO LITERAL1 +KELVINATOR_FAN_MAX LITERAL1 +KELVINATOR_HEAT LITERAL1 +KELVINATOR_MAX_TEMP LITERAL1 +KELVINATOR_MIN_TEMP LITERAL1 +KELVINATOR_STATE_LENGTH LITERAL1 +LASERTAG LITERAL1 +LASERTAG_BITS LITERAL1 +LG LITERAL1 +LG2 LITERAL1 +LG32_BITS LITERAL1 +LG_BITS LITERAL1 +LOW LITERAL1 +LUTRON LITERAL1 +MAGIQUEST LITERAL1 +MAGIQUEST_BITS LITERAL1 +MIDEA LITERAL1 +MIDEA_AC_AUTO LITERAL1 +MIDEA_AC_COOL LITERAL1 +MIDEA_AC_DRY LITERAL1 +MIDEA_AC_FAN LITERAL1 +MIDEA_AC_FAN_AUTO LITERAL1 +MIDEA_AC_FAN_HI LITERAL1 +MIDEA_AC_FAN_LOW LITERAL1 +MIDEA_AC_FAN_MED LITERAL1 +MIDEA_AC_HEAT LITERAL1 +MIDEA_AC_MAX_TEMP_C LITERAL1 +MIDEA_AC_MAX_TEMP_F LITERAL1 +MIDEA_AC_MIN_TEMP_C LITERAL1 +MIDEA_AC_MIN_TEMP_F LITERAL1 +MIDEA_AC_POWER LITERAL1 +MIDEA_AC_SLEEP LITERAL1 +MIDEA_BITS LITERAL1 +MITSUBISHI LITERAL1 +MITSUBISHI2 LITERAL1 +MITSUBISHI_AC LITERAL1 +MITSUBISHI_AC_AUTO LITERAL1 +MITSUBISHI_AC_COOL LITERAL1 +MITSUBISHI_AC_DRY LITERAL1 +MITSUBISHI_AC_FAN_AUTO LITERAL1 +MITSUBISHI_AC_FAN_MAX LITERAL1 +MITSUBISHI_AC_FAN_REAL_MAX LITERAL1 +MITSUBISHI_AC_FAN_SILENT LITERAL1 +MITSUBISHI_AC_HEAT LITERAL1 +MITSUBISHI_AC_MAX_TEMP LITERAL1 +MITSUBISHI_AC_MIN_TEMP LITERAL1 +MITSUBISHI_AC_POWER LITERAL1 +MITSUBISHI_AC_STATE_LENGTH LITERAL1 +MITSUBISHI_AC_VANE_AUTO LITERAL1 +MITSUBISHI_AC_VANE_AUTO_MOVE LITERAL1 +MITSUBISHI_BITS LITERAL1 +MWM LITERAL1 +NEC LITERAL1 +NEC_BITS LITERAL1 +NEC_LIKE LITERAL1 +NIKAI LITERAL1 +NIKAI_BITS LITERAL1 +ONCE LITERAL1 +PANASONIC LITERAL1 +PANASONIC_AC LITERAL1 +PANASONIC_BITS LITERAL1 +PIONEER LITERAL1 +PRONTO LITERAL1 +RAW LITERAL1 +RAWTICK LITERAL1 +RC5 LITERAL1 +RC5X LITERAL1 +RC5X_BITS LITERAL1 +RC5_BITS LITERAL1 +RC6 LITERAL1 +RC6_36_BITS LITERAL1 +RC6_MODE0_BITS LITERAL1 +RCMM LITERAL1 +RCMM_BITS LITERAL1 +SAMSUNG LITERAL1 +SAMSUNG_AC LITERAL1 +SAMSUNG_BITS LITERAL1 +SANYO LITERAL1 +SANYO_LC7461 LITERAL1 +SANYO_LC7461_BITS LITERAL1 +SANYO_SA8650B_BITS LITERAL1 +SEND_AIWA_RC_T501 LITERAL1 +SEND_ARGO LITERAL1 +SEND_CARRIER_AC LITERAL1 +SEND_COOLIX LITERAL1 +SEND_DAIKIN LITERAL1 +SEND_DENON LITERAL1 +SEND_DISH LITERAL1 +SEND_ELECTRA_AC LITERAL1 +SEND_FUJITSU_AC LITERAL1 +SEND_GICABLE LITERAL1 +SEND_GLOBALCACHE LITERAL1 +SEND_GREE LITERAL1 +SEND_HAIER_AC LITERAL1 +SEND_HAIER_AC_YRW02 LITERAL1 +SEND_HITACHI_AC LITERAL1 +SEND_HITACHI_AC1 LITERAL1 +SEND_HITACHI_AC2 LITERAL1 +SEND_JVC LITERAL1 +SEND_KELVINATOR LITERAL1 +SEND_LASERTAG LITERAL1 +SEND_LG LITERAL1 +SEND_LUTRON LITERAL1 +SEND_MAGIQUEST LITERAL1 +SEND_MIDEA LITERAL1 +SEND_MITSUBISHI LITERAL1 +SEND_MITSUBISHI2 LITERAL1 +SEND_MITSUBISHI_AC LITERAL1 +SEND_MWM LITERAL1 +SEND_NEC LITERAL1 +SEND_NIKAI LITERAL1 +SEND_PANASONIC LITERAL1 +SEND_PANASONIC_AC LITERAL1 +SEND_PIONEER LITERAL1 +SEND_PRONTO LITERAL1 +SEND_RAW LITERAL1 +SEND_RC5 LITERAL1 +SEND_RC6 LITERAL1 +SEND_RCMM LITERAL1 +SEND_SAMSUNG LITERAL1 +SEND_SAMSUNG_AC LITERAL1 +SEND_SANYO LITERAL1 +SEND_SHARP LITERAL1 +SEND_SHERWOOD LITERAL1 +SEND_SONY LITERAL1 +SEND_TOSHIBA_AC LITERAL1 +SEND_TROTEC LITERAL1 +SEND_WHIRLPOOL_AC LITERAL1 +SEND_WHYNTER LITERAL1 +SHARP LITERAL1 +SHARP_BITS LITERAL1 +SHERWOOD LITERAL1 +SHERWOOD_BITS LITERAL1 +SONY LITERAL1 +SONY_12_BITS LITERAL1 +SONY_15_BITS LITERAL1 +SONY_20_BITS LITERAL1 +TIMEOUT_MS LITERAL1 +TOSHIBA_AC LITERAL1 +TOSHIBA_AC_AUTO LITERAL1 +TOSHIBA_AC_COOL LITERAL1 +TOSHIBA_AC_DRY LITERAL1 +TOSHIBA_AC_FAN_AUTO LITERAL1 +TOSHIBA_AC_FAN_MAX LITERAL1 +TOSHIBA_AC_HEAT LITERAL1 +TOSHIBA_AC_MAX_TEMP LITERAL1 +TOSHIBA_AC_MIN_TEMP LITERAL1 +TOSHIBA_AC_POWER LITERAL1 +TOSHIBA_AC_STATE_LENGTH LITERAL1 +TROTEC LITERAL1 +TROTEC_AUTO LITERAL1 +TROTEC_COMMAND_LENGTH LITERAL1 +TROTEC_COOL LITERAL1 +TROTEC_DRY LITERAL1 +TROTEC_FAN LITERAL1 +TROTEC_FAN_HIGH LITERAL1 +TROTEC_FAN_LOW LITERAL1 +TROTEC_FAN_MED LITERAL1 +TROTEC_MAX_TEMP LITERAL1 +TROTEC_MAX_TIMER LITERAL1 +TROTEC_MIN_TEMP LITERAL1 +TROTEC_MIN_TIMER LITERAL1 +UNKNOWN LITERAL1 +UNUSED LITERAL1 +WHIRLPOOL_AC LITERAL1 +WHYNTER LITERAL1 +WHYNTER_BITS LITERAL1 +kAiwaRcT501Bits LITERAL1 +kAiwaRcT501MinRepeats LITERAL1 +kAiwaRcT501PostBits LITERAL1 +kAiwaRcT501PostData LITERAL1 +kAiwaRcT501PreBits LITERAL1 +kAiwaRcT501PreData LITERAL1 +kArgoBitMark LITERAL1 +kArgoCoolAuto LITERAL1 +kArgoCoolHum LITERAL1 +kArgoCoolOff LITERAL1 +kArgoCoolOn LITERAL1 +kArgoFan1 LITERAL1 +kArgoFan2 LITERAL1 +kArgoFan3 LITERAL1 +kArgoFanAuto LITERAL1 +kArgoFlap1 LITERAL1 +kArgoFlap2 LITERAL1 +kArgoFlap3 LITERAL1 +kArgoFlap4 LITERAL1 +kArgoFlap5 LITERAL1 +kArgoFlap6 LITERAL1 +kArgoFlapAuto LITERAL1 +kArgoFlapFull LITERAL1 +kArgoHdrMark LITERAL1 +kArgoHdrSpace LITERAL1 +kArgoHeatAuto LITERAL1 +kArgoHeatBlink LITERAL1 +kArgoHeatOn LITERAL1 +kArgoMaxTemp LITERAL1 +kArgoMinTemp LITERAL1 +kArgoOneSpace LITERAL1 +kArgoStateLength LITERAL1 +kArgoZeroSpace LITERAL1 +kCarrierAcBitMark LITERAL1 +kCarrierAcBits LITERAL1 +kCarrierAcGap LITERAL1 +kCarrierAcHdrMark LITERAL1 +kCarrierAcHdrSpace LITERAL1 +kCarrierAcMinRepeat LITERAL1 +kCarrierAcOneSpace LITERAL1 +kCarrierAcZeroSpace LITERAL1 +kCoolixAuto LITERAL1 +kCoolixBitMark LITERAL1 +kCoolixBitMarkTicks LITERAL1 +kCoolixBits LITERAL1 +kCoolixClean LITERAL1 +kCoolixCool LITERAL1 +kCoolixDefaultState LITERAL1 +kCoolixDry LITERAL1 +kCoolixFan LITERAL1 +kCoolixFanAuto LITERAL1 +kCoolixFanFixed LITERAL1 +kCoolixFanMask LITERAL1 +kCoolixFanMax LITERAL1 +kCoolixFanMed LITERAL1 +kCoolixFanMin LITERAL1 +kCoolixFanTempCode LITERAL1 +kCoolixFanZoneFollow LITERAL1 +kCoolixHdrMark LITERAL1 +kCoolixHdrMarkTicks LITERAL1 +kCoolixHdrSpace LITERAL1 +kCoolixHdrSpaceTicks LITERAL1 +kCoolixHeat LITERAL1 +kCoolixLed LITERAL1 +kCoolixMinGap LITERAL1 +kCoolixMinGapTicks LITERAL1 +kCoolixModeMask LITERAL1 +kCoolixOff LITERAL1 +kCoolixOneSpace LITERAL1 +kCoolixOneSpaceTicks LITERAL1 +kCoolixPrefix LITERAL1 +kCoolixSensorTempIgnoreCode LITERAL1 +kCoolixSensorTempMask LITERAL1 +kCoolixSensorTempMax LITERAL1 +kCoolixSensorTempMin LITERAL1 +kCoolixSleep LITERAL1 +kCoolixSwing LITERAL1 +kCoolixTempMap LITERAL1 +kCoolixTempMask LITERAL1 +kCoolixTempMax LITERAL1 +kCoolixTempMin LITERAL1 +kCoolixTempRange LITERAL1 +kCoolixTick LITERAL1 +kCoolixTurbo LITERAL1 +kCoolixUnknown LITERAL1 +kCoolixZeroSpace LITERAL1 +kCoolixZeroSpaceTicks LITERAL1 +kCoolixZoneFollowMask LITERAL1 +kDaikinAuto LITERAL1 +kDaikinBitEcono LITERAL1 +kDaikinBitEye LITERAL1 +kDaikinBitMark LITERAL1 +kDaikinBitMold LITERAL1 +kDaikinBitOffTimer LITERAL1 +kDaikinBitOnTimer LITERAL1 +kDaikinBitPower LITERAL1 +kDaikinBitPowerful LITERAL1 +kDaikinBitSensor LITERAL1 +kDaikinBitSilent LITERAL1 +kDaikinBits LITERAL1 +kDaikinByteEcono LITERAL1 +kDaikinByteEye LITERAL1 +kDaikinByteMold LITERAL1 +kDaikinByteOffTimer LITERAL1 +kDaikinByteOnTimer LITERAL1 +kDaikinBytePower LITERAL1 +kDaikinBytePowerful LITERAL1 +kDaikinByteSensor LITERAL1 +kDaikinByteSilent LITERAL1 +kDaikinCool LITERAL1 +kDaikinCurBit LITERAL1 +kDaikinCurIndex LITERAL1 +kDaikinDry LITERAL1 +kDaikinFan LITERAL1 +kDaikinFanAuto LITERAL1 +kDaikinFanMax LITERAL1 +kDaikinFanMin LITERAL1 +kDaikinFanQuiet LITERAL1 +kDaikinFirstHeader64 LITERAL1 +kDaikinGap LITERAL1 +kDaikinHdrMark LITERAL1 +kDaikinHdrSpace LITERAL1 +kDaikinHeat LITERAL1 +kDaikinMarkExcess LITERAL1 +kDaikinMaxTemp LITERAL1 +kDaikinMinTemp LITERAL1 +kDaikinOneSpace LITERAL1 +kDaikinRawBits LITERAL1 +kDaikinStateLength LITERAL1 +kDaikinTolerance LITERAL1 +kDaikinZeroSpace LITERAL1 +kDenonBitMark LITERAL1 +kDenonBitMarkTicks LITERAL1 +kDenonBits LITERAL1 +kDenonHdrMark LITERAL1 +kDenonHdrMarkTicks LITERAL1 +kDenonHdrSpace LITERAL1 +kDenonHdrSpaceTicks LITERAL1 +kDenonLegacyBits LITERAL1 +kDenonManufacturer LITERAL1 +kDenonMinCommandLengthTicks LITERAL1 +kDenonMinGap LITERAL1 +kDenonMinGapTicks LITERAL1 +kDenonOneSpace LITERAL1 +kDenonOneSpaceTicks LITERAL1 +kDenonTick LITERAL1 +kDenonZeroSpace LITERAL1 +kDenonZeroSpaceTicks LITERAL1 +kDishBitMark LITERAL1 +kDishBitMarkTicks LITERAL1 +kDishBits LITERAL1 +kDishHdrMark LITERAL1 +kDishHdrMarkTicks LITERAL1 +kDishHdrSpace LITERAL1 +kDishHdrSpaceTicks LITERAL1 +kDishMinRepeat LITERAL1 +kDishOneSpace LITERAL1 +kDishOneSpaceTicks LITERAL1 +kDishRptSpace LITERAL1 +kDishRptSpaceTicks LITERAL1 +kDishTick LITERAL1 +kDishZeroSpace LITERAL1 +kDishZeroSpaceTicks LITERAL1 +kDutyDefault LITERAL1 +kDutyMax LITERAL1 +kElectraAcBitMark LITERAL1 +kElectraAcBits LITERAL1 +kElectraAcHdrMark LITERAL1 +kElectraAcHdrSpace LITERAL1 +kElectraAcMessageGap LITERAL1 +kElectraAcOneSpace LITERAL1 +kElectraAcStateLength LITERAL1 +kElectraAcZeroSpace LITERAL1 +kFnvBasis32 LITERAL1 +kFnvPrime32 LITERAL1 +kFooter LITERAL1 +kFujitsuAcBitMark LITERAL1 +kFujitsuAcBits LITERAL1 +kFujitsuAcCmdStayOn LITERAL1 +kFujitsuAcCmdStepHoriz LITERAL1 +kFujitsuAcCmdStepVert LITERAL1 +kFujitsuAcCmdTurnOff LITERAL1 +kFujitsuAcCmdTurnOn LITERAL1 +kFujitsuAcFanAuto LITERAL1 +kFujitsuAcFanHigh LITERAL1 +kFujitsuAcFanLow LITERAL1 +kFujitsuAcFanMed LITERAL1 +kFujitsuAcFanQuiet LITERAL1 +kFujitsuAcHdrMark LITERAL1 +kFujitsuAcHdrSpace LITERAL1 +kFujitsuAcMaxTemp LITERAL1 +kFujitsuAcMinBits LITERAL1 +kFujitsuAcMinGap LITERAL1 +kFujitsuAcMinRepeat LITERAL1 +kFujitsuAcMinTemp LITERAL1 +kFujitsuAcModeAuto LITERAL1 +kFujitsuAcModeCool LITERAL1 +kFujitsuAcModeDry LITERAL1 +kFujitsuAcModeFan LITERAL1 +kFujitsuAcModeHeat LITERAL1 +kFujitsuAcOneSpace LITERAL1 +kFujitsuAcStateLength LITERAL1 +kFujitsuAcStateLengthShort LITERAL1 +kFujitsuAcSwingBoth LITERAL1 +kFujitsuAcSwingHoriz LITERAL1 +kFujitsuAcSwingOff LITERAL1 +kFujitsuAcSwingVert LITERAL1 +kFujitsuAcZeroSpace LITERAL1 +kGicableBitMark LITERAL1 +kGicableBits LITERAL1 +kGicableHdrMark LITERAL1 +kGicableHdrSpace LITERAL1 +kGicableMinCommandLength LITERAL1 +kGicableMinGap LITERAL1 +kGicableMinRepeat LITERAL1 +kGicableOneSpace LITERAL1 +kGicableRptSpace LITERAL1 +kGicableZeroSpace LITERAL1 +kGlobalCacheFreqIndex LITERAL1 +kGlobalCacheMaxRepeat LITERAL1 +kGlobalCacheMinUsec LITERAL1 +kGlobalCacheRptIndex LITERAL1 +kGlobalCacheRptStartIndex LITERAL1 +kGlobalCacheStartIndex LITERAL1 +kGreeAuto LITERAL1 +kGreeBitMark LITERAL1 +kGreeBits LITERAL1 +kGreeBlockFooter LITERAL1 +kGreeBlockFooterBits LITERAL1 +kGreeCool LITERAL1 +kGreeDry LITERAL1 +kGreeFan LITERAL1 +kGreeFanMask LITERAL1 +kGreeFanMax LITERAL1 +kGreeHdrMark LITERAL1 +kGreeHdrSpace LITERAL1 +kGreeHeat LITERAL1 +kGreeLightMask LITERAL1 +kGreeMaxTemp LITERAL1 +kGreeMinTemp LITERAL1 +kGreeModeMask LITERAL1 +kGreeMsgSpace LITERAL1 +kGreeOneSpace LITERAL1 +kGreePower1Mask LITERAL1 +kGreePower2Mask LITERAL1 +kGreeSleepMask LITERAL1 +kGreeStateLength LITERAL1 +kGreeSwingAuto LITERAL1 +kGreeSwingAutoMask LITERAL1 +kGreeSwingDown LITERAL1 +kGreeSwingDownAuto LITERAL1 +kGreeSwingLastPos LITERAL1 +kGreeSwingMiddle LITERAL1 +kGreeSwingMiddleAuto LITERAL1 +kGreeSwingMiddleDown LITERAL1 +kGreeSwingMiddleUp LITERAL1 +kGreeSwingPosMask LITERAL1 +kGreeSwingUp LITERAL1 +kGreeSwingUpAuto LITERAL1 +kGreeTurboMask LITERAL1 +kGreeXfanMask LITERAL1 +kGreeZeroSpace LITERAL1 +kHaierACBits LITERAL1 +kHaierACStateLength LITERAL1 +kHaierACYRW02Bits LITERAL1 +kHaierACYRW02StateLength LITERAL1 +kHaierAcAuto LITERAL1 +kHaierAcBitMark LITERAL1 +kHaierAcCmdFan LITERAL1 +kHaierAcCmdHealth LITERAL1 +kHaierAcCmdMode LITERAL1 +kHaierAcCmdOff LITERAL1 +kHaierAcCmdOn LITERAL1 +kHaierAcCmdSleep LITERAL1 +kHaierAcCmdSwing LITERAL1 +kHaierAcCmdTempDown LITERAL1 +kHaierAcCmdTempUp LITERAL1 +kHaierAcCmdTimerCancel LITERAL1 +kHaierAcCmdTimerSet LITERAL1 +kHaierAcCool LITERAL1 +kHaierAcDefTemp LITERAL1 +kHaierAcDry LITERAL1 +kHaierAcFan LITERAL1 +kHaierAcFanAuto LITERAL1 +kHaierAcFanHigh LITERAL1 +kHaierAcFanLow LITERAL1 +kHaierAcFanMed LITERAL1 +kHaierAcHdr LITERAL1 +kHaierAcHdrGap LITERAL1 +kHaierAcHeat LITERAL1 +kHaierAcMaxTemp LITERAL1 +kHaierAcMaxTime LITERAL1 +kHaierAcMinGap LITERAL1 +kHaierAcMinTemp LITERAL1 +kHaierAcOneSpace LITERAL1 +kHaierAcPrefix LITERAL1 +kHaierAcSwingChg LITERAL1 +kHaierAcSwingDown LITERAL1 +kHaierAcSwingOff LITERAL1 +kHaierAcSwingUp LITERAL1 +kHaierAcYrw02Auto LITERAL1 +kHaierAcYrw02ButtonFan LITERAL1 +kHaierAcYrw02ButtonHealth LITERAL1 +kHaierAcYrw02ButtonMode LITERAL1 +kHaierAcYrw02ButtonPower LITERAL1 +kHaierAcYrw02ButtonSleep LITERAL1 +kHaierAcYrw02ButtonSwing LITERAL1 +kHaierAcYrw02ButtonTempDown LITERAL1 +kHaierAcYrw02ButtonTempUp LITERAL1 +kHaierAcYrw02ButtonTurbo LITERAL1 +kHaierAcYrw02Cool LITERAL1 +kHaierAcYrw02Dry LITERAL1 +kHaierAcYrw02Fan LITERAL1 +kHaierAcYrw02FanAuto LITERAL1 +kHaierAcYrw02FanHigh LITERAL1 +kHaierAcYrw02FanLow LITERAL1 +kHaierAcYrw02FanMed LITERAL1 +kHaierAcYrw02Heat LITERAL1 +kHaierAcYrw02Power LITERAL1 +kHaierAcYrw02Prefix LITERAL1 +kHaierAcYrw02Sleep LITERAL1 +kHaierAcYrw02SwingAuto LITERAL1 +kHaierAcYrw02SwingBottom LITERAL1 +kHaierAcYrw02SwingDown LITERAL1 +kHaierAcYrw02SwingMiddle LITERAL1 +kHaierAcYrw02SwingOff LITERAL1 +kHaierAcYrw02SwingTop LITERAL1 +kHaierAcYrw02TurboHigh LITERAL1 +kHaierAcYrw02TurboLow LITERAL1 +kHaierAcYrw02TurboOff LITERAL1 +kHaierAcZeroSpace LITERAL1 +kHeader LITERAL1 +kHitachiAc1Bits LITERAL1 +kHitachiAc1HdrMark LITERAL1 +kHitachiAc1HdrSpace LITERAL1 +kHitachiAc1StateLength LITERAL1 +kHitachiAc2Bits LITERAL1 +kHitachiAc2StateLength LITERAL1 +kHitachiAcBitMark LITERAL1 +kHitachiAcBits LITERAL1 +kHitachiAcHdrMark LITERAL1 +kHitachiAcHdrSpace LITERAL1 +kHitachiAcMinGap LITERAL1 +kHitachiAcOneSpace LITERAL1 +kHitachiAcStateLength LITERAL1 +kHitachiAcZeroSpace LITERAL1 +kIdleState LITERAL1 +kJvcBitMark LITERAL1 +kJvcBitMarkTicks LITERAL1 +kJvcBits LITERAL1 +kJvcHdrMark LITERAL1 +kJvcHdrMarkTicks LITERAL1 +kJvcHdrSpace LITERAL1 +kJvcHdrSpaceTicks LITERAL1 +kJvcMinGap LITERAL1 +kJvcMinGapTicks LITERAL1 +kJvcOneSpace LITERAL1 +kJvcOneSpaceTicks LITERAL1 +kJvcRptLength LITERAL1 +kJvcRptLengthTicks LITERAL1 +kJvcTick LITERAL1 +kJvcZeroSpace LITERAL1 +kJvcZeroSpaceTicks LITERAL1 +kKelvinatorAuto LITERAL1 +kKelvinatorAutoTemp LITERAL1 +kKelvinatorBasicFanMask LITERAL1 +kKelvinatorBasicFanMax LITERAL1 +kKelvinatorBitMark LITERAL1 +kKelvinatorBitMarkTicks LITERAL1 +kKelvinatorBits LITERAL1 +kKelvinatorChecksumStart LITERAL1 +kKelvinatorCmdFooter LITERAL1 +kKelvinatorCmdFooterBits LITERAL1 +kKelvinatorCool LITERAL1 +kKelvinatorDry LITERAL1 +kKelvinatorFan LITERAL1 +kKelvinatorFanAuto LITERAL1 +kKelvinatorFanMask LITERAL1 +kKelvinatorFanMax LITERAL1 +kKelvinatorFanOffset LITERAL1 +kKelvinatorGapSpace LITERAL1 +kKelvinatorGapSpaceTicks LITERAL1 +kKelvinatorHdrMark LITERAL1 +kKelvinatorHdrMarkTicks LITERAL1 +kKelvinatorHdrSpace LITERAL1 +kKelvinatorHdrSpaceTicks LITERAL1 +kKelvinatorHeat LITERAL1 +kKelvinatorIonFilter LITERAL1 +kKelvinatorIonFilterOffset LITERAL1 +kKelvinatorLight LITERAL1 +kKelvinatorLightOffset LITERAL1 +kKelvinatorMaxTemp LITERAL1 +kKelvinatorMinTemp LITERAL1 +kKelvinatorModeMask LITERAL1 +kKelvinatorOneSpace LITERAL1 +kKelvinatorOneSpaceTicks LITERAL1 +kKelvinatorPower LITERAL1 +kKelvinatorQuiet LITERAL1 +kKelvinatorQuietOffset LITERAL1 +kKelvinatorSleep1And3 LITERAL1 +kKelvinatorStateLength LITERAL1 +kKelvinatorTick LITERAL1 +kKelvinatorTurbo LITERAL1 +kKelvinatorTurboOffset LITERAL1 +kKelvinatorVentSwing LITERAL1 +kKelvinatorVentSwingH LITERAL1 +kKelvinatorVentSwingOffset LITERAL1 +kKelvinatorVentSwingV LITERAL1 +kKelvinatorXfan LITERAL1 +kKelvinatorXfanOffset LITERAL1 +kKelvinatorZeroSpace LITERAL1 +kKelvinatorZeroSpaceTicks LITERAL1 +kLasertagBits LITERAL1 +kLasertagDelta LITERAL1 +kLasertagExcess LITERAL1 +kLasertagMinGap LITERAL1 +kLasertagMinRepeat LITERAL1 +kLasertagMinSamples LITERAL1 +kLasertagTick LITERAL1 +kLasertagTolerance LITERAL1 +kLg2BitMark LITERAL1 +kLg2BitMarkTicks LITERAL1 +kLg2HdrMark LITERAL1 +kLg2HdrMarkTicks LITERAL1 +kLg2HdrSpace LITERAL1 +kLg2HdrSpaceTicks LITERAL1 +kLg32Bits LITERAL1 +kLg32HdrMark LITERAL1 +kLg32HdrMarkTicks LITERAL1 +kLg32HdrSpace LITERAL1 +kLg32HdrSpaceTicks LITERAL1 +kLg32RptHdrMark LITERAL1 +kLg32RptHdrMarkTicks LITERAL1 +kLgBitMark LITERAL1 +kLgBitMarkTicks LITERAL1 +kLgBits LITERAL1 +kLgHdrMark LITERAL1 +kLgHdrMarkTicks LITERAL1 +kLgHdrSpace LITERAL1 +kLgHdrSpaceTicks LITERAL1 +kLgMinGap LITERAL1 +kLgMinGapTicks LITERAL1 +kLgMinMessageLength LITERAL1 +kLgMinMessageLengthTicks LITERAL1 +kLgOneSpace LITERAL1 +kLgOneSpaceTicks LITERAL1 +kLgRptSpace LITERAL1 +kLgRptSpaceTicks LITERAL1 +kLgTick LITERAL1 +kLgZeroSpace LITERAL1 +kLgZeroSpaceTicks LITERAL1 +kLutronBits LITERAL1 +kLutronDelta LITERAL1 +kLutronGap LITERAL1 +kLutronTick LITERAL1 +kMWMDelta LITERAL1 +kMWMExcess LITERAL1 +kMWMMaxWidth LITERAL1 +kMWMMinGap LITERAL1 +kMWMMinSamples LITERAL1 +kMWMTick LITERAL1 +kMWMTolerance LITERAL1 +kMagiQuestGap LITERAL1 +kMagiQuestMarkOne LITERAL1 +kMagiQuestMarkZero LITERAL1 +kMagiQuestOneRatio LITERAL1 +kMagiQuestSpaceOne LITERAL1 +kMagiQuestSpaceZero LITERAL1 +kMagiQuestTotalUsec LITERAL1 +kMagiQuestZeroRatio LITERAL1 +kMagiquestBits LITERAL1 +kMark LITERAL1 +kMarkExcess LITERAL1 +kMarkState LITERAL1 +kMaxAccurateUsecDelay LITERAL1 +kMaxTimeoutMs LITERAL1 +kMideaACAuto LITERAL1 +kMideaACChecksumMask LITERAL1 +kMideaACCool LITERAL1 +kMideaACDry LITERAL1 +kMideaACFan LITERAL1 +kMideaACFanAuto LITERAL1 +kMideaACFanHigh LITERAL1 +kMideaACFanLow LITERAL1 +kMideaACFanMask LITERAL1 +kMideaACFanMed LITERAL1 +kMideaACHeat LITERAL1 +kMideaACMaxTempC LITERAL1 +kMideaACMaxTempF LITERAL1 +kMideaACMinTempC LITERAL1 +kMideaACMinTempF LITERAL1 +kMideaACModeMask LITERAL1 +kMideaACPower LITERAL1 +kMideaACSleep LITERAL1 +kMideaACStateMask LITERAL1 +kMideaACTempMask LITERAL1 +kMideaBitMark LITERAL1 +kMideaBitMarkTicks LITERAL1 +kMideaBits LITERAL1 +kMideaHdrMark LITERAL1 +kMideaHdrMarkTicks LITERAL1 +kMideaHdrSpace LITERAL1 +kMideaHdrSpaceTicks LITERAL1 +kMideaMinGap LITERAL1 +kMideaMinGapTicks LITERAL1 +kMideaMinRepeat LITERAL1 +kMideaOneSpace LITERAL1 +kMideaOneSpaceTicks LITERAL1 +kMideaTick LITERAL1 +kMideaTolerance LITERAL1 +kMideaZeroSpace LITERAL1 +kMideaZeroSpaceTicks LITERAL1 +kMitsubishi2BitMark LITERAL1 +kMitsubishi2HdrMark LITERAL1 +kMitsubishi2HdrSpace LITERAL1 +kMitsubishi2MinGap LITERAL1 +kMitsubishi2OneSpace LITERAL1 +kMitsubishi2ZeroSpace LITERAL1 +kMitsubishiACBits LITERAL1 +kMitsubishiACMinRepeat LITERAL1 +kMitsubishiACStateLength LITERAL1 +kMitsubishiAcAuto LITERAL1 +kMitsubishiAcBitMark LITERAL1 +kMitsubishiAcCool LITERAL1 +kMitsubishiAcDry LITERAL1 +kMitsubishiAcFanAuto LITERAL1 +kMitsubishiAcFanMax LITERAL1 +kMitsubishiAcFanRealMax LITERAL1 +kMitsubishiAcFanSilent LITERAL1 +kMitsubishiAcHdrMark LITERAL1 +kMitsubishiAcHdrSpace LITERAL1 +kMitsubishiAcHeat LITERAL1 +kMitsubishiAcMaxTemp LITERAL1 +kMitsubishiAcMinTemp LITERAL1 +kMitsubishiAcNoTimer LITERAL1 +kMitsubishiAcOneSpace LITERAL1 +kMitsubishiAcPower LITERAL1 +kMitsubishiAcRptMark LITERAL1 +kMitsubishiAcRptSpace LITERAL1 +kMitsubishiAcStartStopTimer LITERAL1 +kMitsubishiAcStartTimer LITERAL1 +kMitsubishiAcStopTimer LITERAL1 +kMitsubishiAcVaneAuto LITERAL1 +kMitsubishiAcVaneAutoMove LITERAL1 +kMitsubishiAcZeroSpace LITERAL1 +kMitsubishiBitMark LITERAL1 +kMitsubishiBitMarkTicks LITERAL1 +kMitsubishiBits LITERAL1 +kMitsubishiMinCommandLength LITERAL1 +kMitsubishiMinCommandLengthTicks LITERAL1 +kMitsubishiMinGap LITERAL1 +kMitsubishiMinGapTicks LITERAL1 +kMitsubishiMinRepeat LITERAL1 +kMitsubishiOneSpace LITERAL1 +kMitsubishiOneSpaceTicks LITERAL1 +kMitsubishiTick LITERAL1 +kMitsubishiZeroSpace LITERAL1 +kMitsubishiZeroSpaceTicks LITERAL1 +kNECBits LITERAL1 +kNecBitMark LITERAL1 +kNecBitMarkTicks LITERAL1 +kNecHdrMark LITERAL1 +kNecHdrMarkTicks LITERAL1 +kNecHdrSpace LITERAL1 +kNecHdrSpaceTicks LITERAL1 +kNecMinCommandLength LITERAL1 +kNecMinCommandLengthTicks LITERAL1 +kNecMinGap LITERAL1 +kNecMinGapTicks LITERAL1 +kNecOneSpace LITERAL1 +kNecOneSpaceTicks LITERAL1 +kNecRptLength LITERAL1 +kNecRptSpace LITERAL1 +kNecRptSpaceTicks LITERAL1 +kNecTick LITERAL1 +kNecZeroSpace LITERAL1 +kNecZeroSpaceTicks LITERAL1 +kNikaiBitMark LITERAL1 +kNikaiBitMarkTicks LITERAL1 +kNikaiBits LITERAL1 +kNikaiHdrMark LITERAL1 +kNikaiHdrMarkTicks LITERAL1 +kNikaiHdrSpace LITERAL1 +kNikaiHdrSpaceTicks LITERAL1 +kNikaiMinGap LITERAL1 +kNikaiMinGapTicks LITERAL1 +kNikaiOneSpace LITERAL1 +kNikaiOneSpaceTicks LITERAL1 +kNikaiTick LITERAL1 +kNikaiZeroSpace LITERAL1 +kNikaiZeroSpaceTicks LITERAL1 +kNoRepeat LITERAL1 +kPanasonicAcAuto LITERAL1 +kPanasonicAcBits LITERAL1 +kPanasonicAcChecksumInit LITERAL1 +kPanasonicAcCool LITERAL1 +kPanasonicAcDry LITERAL1 +kPanasonicAcExcess LITERAL1 +kPanasonicAcFan LITERAL1 +kPanasonicAcFanAuto LITERAL1 +kPanasonicAcFanMax LITERAL1 +kPanasonicAcFanMin LITERAL1 +kPanasonicAcFanModeTemp LITERAL1 +kPanasonicAcFanOffset LITERAL1 +kPanasonicAcHeat LITERAL1 +kPanasonicAcMaxTemp LITERAL1 +kPanasonicAcMessageGap LITERAL1 +kPanasonicAcMinTemp LITERAL1 +kPanasonicAcOffTimer LITERAL1 +kPanasonicAcOnTimer LITERAL1 +kPanasonicAcPower LITERAL1 +kPanasonicAcPowerful LITERAL1 +kPanasonicAcPowerfulCkp LITERAL1 +kPanasonicAcQuiet LITERAL1 +kPanasonicAcQuietCkp LITERAL1 +kPanasonicAcSection1Length LITERAL1 +kPanasonicAcSectionGap LITERAL1 +kPanasonicAcShortBits LITERAL1 +kPanasonicAcStateLength LITERAL1 +kPanasonicAcStateShortLength LITERAL1 +kPanasonicAcSwingHAuto LITERAL1 +kPanasonicAcSwingHFullLeft LITERAL1 +kPanasonicAcSwingHFullRight LITERAL1 +kPanasonicAcSwingHLeft LITERAL1 +kPanasonicAcSwingHMiddle LITERAL1 +kPanasonicAcSwingHRight LITERAL1 +kPanasonicAcSwingVAuto LITERAL1 +kPanasonicAcSwingVDown LITERAL1 +kPanasonicAcSwingVUp LITERAL1 +kPanasonicAcTimeMax LITERAL1 +kPanasonicAcTimeSpecial LITERAL1 +kPanasonicAcTolerance LITERAL1 +kPanasonicBitMark LITERAL1 +kPanasonicBitMarkTicks LITERAL1 +kPanasonicBits LITERAL1 +kPanasonicCkp LITERAL1 +kPanasonicDke LITERAL1 +kPanasonicEndGap LITERAL1 +kPanasonicFreq LITERAL1 +kPanasonicHdrMark LITERAL1 +kPanasonicHdrMarkTicks LITERAL1 +kPanasonicHdrSpace LITERAL1 +kPanasonicHdrSpaceTicks LITERAL1 +kPanasonicJke LITERAL1 +kPanasonicKnownGoodState LITERAL1 +kPanasonicLke LITERAL1 +kPanasonicManufacturer LITERAL1 +kPanasonicMinCommandLength LITERAL1 +kPanasonicMinCommandLengthTicks LITERAL1 +kPanasonicMinGap LITERAL1 +kPanasonicMinGapTicks LITERAL1 +kPanasonicNke LITERAL1 +kPanasonicOneSpace LITERAL1 +kPanasonicOneSpaceTicks LITERAL1 +kPanasonicTick LITERAL1 +kPanasonicUnknown LITERAL1 +kPanasonicZeroSpace LITERAL1 +kPanasonicZeroSpaceTicks LITERAL1 +kPeriodOffset LITERAL1 +kPioneerBits LITERAL1 +kProntoDataOffset LITERAL1 +kProntoFreqFactor LITERAL1 +kProntoFreqOffset LITERAL1 +kProntoMinLength LITERAL1 +kProntoSeq1LenOffset LITERAL1 +kProntoSeq2LenOffset LITERAL1 +kProntoTypeOffset LITERAL1 +kRC5Bits LITERAL1 +kRC5RawBits LITERAL1 +kRC5XBits LITERAL1 +kRC6Mode0Bits LITERAL1 +kRC6_36Bits LITERAL1 +kRCMMBits LITERAL1 +kRawBuf LITERAL1 +kRawTick LITERAL1 +kRc5MinCommandLength LITERAL1 +kRc5MinGap LITERAL1 +kRc5SamplesMin LITERAL1 +kRc5T1 LITERAL1 +kRc5ToggleMask LITERAL1 +kRc6HdrMark LITERAL1 +kRc6HdrMarkTicks LITERAL1 +kRc6HdrSpace LITERAL1 +kRc6HdrSpaceTicks LITERAL1 +kRc6RptLength LITERAL1 +kRc6RptLengthTicks LITERAL1 +kRc6Tick LITERAL1 +kRc6ToggleMask LITERAL1 +kRc6_36ToggleMask LITERAL1 +kRcmmBitMark LITERAL1 +kRcmmBitMarkTicks LITERAL1 +kRcmmBitSpace0 LITERAL1 +kRcmmBitSpace0Ticks LITERAL1 +kRcmmBitSpace1 LITERAL1 +kRcmmBitSpace1Ticks LITERAL1 +kRcmmBitSpace2 LITERAL1 +kRcmmBitSpace2Ticks LITERAL1 +kRcmmBitSpace3 LITERAL1 +kRcmmBitSpace3Ticks LITERAL1 +kRcmmExcess LITERAL1 +kRcmmHdrMark LITERAL1 +kRcmmHdrMarkTicks LITERAL1 +kRcmmHdrSpace LITERAL1 +kRcmmHdrSpaceTicks LITERAL1 +kRcmmMinGap LITERAL1 +kRcmmMinGapTicks LITERAL1 +kRcmmRptLength LITERAL1 +kRcmmRptLengthTicks LITERAL1 +kRcmmTick LITERAL1 +kRcmmTolerance LITERAL1 +kRepeat LITERAL1 +kSamsungACSectionLength LITERAL1 +kSamsungAcAuto LITERAL1 +kSamsungAcAutoTemp LITERAL1 +kSamsungAcBeepMask LITERAL1 +kSamsungAcBitMark LITERAL1 +kSamsungAcBits LITERAL1 +kSamsungAcCleanMask10 LITERAL1 +kSamsungAcCleanMask11 LITERAL1 +kSamsungAcCool LITERAL1 +kSamsungAcDry LITERAL1 +kSamsungAcExtendedBits LITERAL1 +kSamsungAcExtendedStateLength LITERAL1 +kSamsungAcFan LITERAL1 +kSamsungAcFanAuto LITERAL1 +kSamsungAcFanAuto2 LITERAL1 +kSamsungAcFanHigh LITERAL1 +kSamsungAcFanLow LITERAL1 +kSamsungAcFanMask LITERAL1 +kSamsungAcFanMed LITERAL1 +kSamsungAcFanTurbo LITERAL1 +kSamsungAcHdrMark LITERAL1 +kSamsungAcHdrSpace LITERAL1 +kSamsungAcHeat LITERAL1 +kSamsungAcMaxTemp LITERAL1 +kSamsungAcMinTemp LITERAL1 +kSamsungAcModeMask LITERAL1 +kSamsungAcOneSpace LITERAL1 +kSamsungAcPowerMask1 LITERAL1 +kSamsungAcPowerMask2 LITERAL1 +kSamsungAcPowerSection LITERAL1 +kSamsungAcQuietMask11 LITERAL1 +kSamsungAcSectionGap LITERAL1 +kSamsungAcSectionMark LITERAL1 +kSamsungAcSectionSpace LITERAL1 +kSamsungAcSections LITERAL1 +kSamsungAcStateLength LITERAL1 +kSamsungAcSwingMask LITERAL1 +kSamsungAcSwingMove LITERAL1 +kSamsungAcSwingStop LITERAL1 +kSamsungAcTempMask LITERAL1 +kSamsungAcZeroSpace LITERAL1 +kSamsungBitMark LITERAL1 +kSamsungBitMarkTicks LITERAL1 +kSamsungBits LITERAL1 +kSamsungHdrMark LITERAL1 +kSamsungHdrMarkTicks LITERAL1 +kSamsungHdrSpace LITERAL1 +kSamsungHdrSpaceTicks LITERAL1 +kSamsungMinGap LITERAL1 +kSamsungMinGapTicks LITERAL1 +kSamsungMinMessageLength LITERAL1 +kSamsungMinMessageLengthTicks LITERAL1 +kSamsungOneSpace LITERAL1 +kSamsungOneSpaceTicks LITERAL1 +kSamsungRptSpace LITERAL1 +kSamsungRptSpaceTicks LITERAL1 +kSamsungTick LITERAL1 +kSamsungZeroSpace LITERAL1 +kSamsungZeroSpaceTicks LITERAL1 +kSanyoLC7461AddressBits LITERAL1 +kSanyoLC7461Bits LITERAL1 +kSanyoLC7461CommandBits LITERAL1 +kSanyoLc7461AddressMask LITERAL1 +kSanyoLc7461BitMark LITERAL1 +kSanyoLc7461CommandMask LITERAL1 +kSanyoLc7461HdrMark LITERAL1 +kSanyoLc7461HdrSpace LITERAL1 +kSanyoLc7461MinCommandLength LITERAL1 +kSanyoLc7461MinGap LITERAL1 +kSanyoLc7461OneSpace LITERAL1 +kSanyoLc7461ZeroSpace LITERAL1 +kSanyoSA8650BBits LITERAL1 +kSanyoSa8650bDoubleSpaceUsecs LITERAL1 +kSanyoSa8650bHdrMark LITERAL1 +kSanyoSa8650bHdrSpace LITERAL1 +kSanyoSa8650bOneMark LITERAL1 +kSanyoSa8650bRptLength LITERAL1 +kSanyoSa8650bZeroMark LITERAL1 +kSharpAddressBits LITERAL1 +kSharpAddressMask LITERAL1 +kSharpBitMark LITERAL1 +kSharpBitMarkTicks LITERAL1 +kSharpBits LITERAL1 +kSharpCommandBits LITERAL1 +kSharpCommandMask LITERAL1 +kSharpGap LITERAL1 +kSharpGapTicks LITERAL1 +kSharpOneSpace LITERAL1 +kSharpOneSpaceTicks LITERAL1 +kSharpTick LITERAL1 +kSharpToggleMask LITERAL1 +kSharpZeroSpace LITERAL1 +kSharpZeroSpaceTicks LITERAL1 +kSherwoodBits LITERAL1 +kSherwoodMinRepeat LITERAL1 +kSingleRepeat LITERAL1 +kSony12Bits LITERAL1 +kSony15Bits LITERAL1 +kSony20Bits LITERAL1 +kSonyHdrMark LITERAL1 +kSonyHdrMarkTicks LITERAL1 +kSonyMinBits LITERAL1 +kSonyMinGap LITERAL1 +kSonyMinGapTicks LITERAL1 +kSonyMinRepeat LITERAL1 +kSonyOneMark LITERAL1 +kSonyOneMarkTicks LITERAL1 +kSonyRptLength LITERAL1 +kSonyRptLengthTicks LITERAL1 +kSonySpace LITERAL1 +kSonySpaceTicks LITERAL1 +kSonyTick LITERAL1 +kSonyZeroMark LITERAL1 +kSonyZeroMarkTicks LITERAL1 +kSpace LITERAL1 +kSpaceState LITERAL1 +kStartOffset LITERAL1 +kStateSizeMax LITERAL1 +kStopState LITERAL1 +kTimeoutMs LITERAL1 +kTolerance LITERAL1 +kToshibaACBits LITERAL1 +kToshibaACMinRepeat LITERAL1 +kToshibaACStateLength LITERAL1 +kToshibaAcAuto LITERAL1 +kToshibaAcBitMark LITERAL1 +kToshibaAcCool LITERAL1 +kToshibaAcDry LITERAL1 +kToshibaAcFanAuto LITERAL1 +kToshibaAcFanMax LITERAL1 +kToshibaAcHdrMark LITERAL1 +kToshibaAcHdrSpace LITERAL1 +kToshibaAcHeat LITERAL1 +kToshibaAcMaxTemp LITERAL1 +kToshibaAcMinGap LITERAL1 +kToshibaAcMinTemp LITERAL1 +kToshibaAcOneSpace LITERAL1 +kToshibaAcPower LITERAL1 +kToshibaAcZeroSpace LITERAL1 +kTrotecAuto LITERAL1 +kTrotecCool LITERAL1 +kTrotecDefTemp LITERAL1 +kTrotecDry LITERAL1 +kTrotecFan LITERAL1 +kTrotecFanHigh LITERAL1 +kTrotecFanLow LITERAL1 +kTrotecFanMed LITERAL1 +kTrotecGap LITERAL1 +kTrotecGapEnd LITERAL1 +kTrotecHdrMark LITERAL1 +kTrotecHdrSpace LITERAL1 +kTrotecIntro1 LITERAL1 +kTrotecIntro2 LITERAL1 +kTrotecMaxTemp LITERAL1 +kTrotecMaxTimer LITERAL1 +kTrotecMinTemp LITERAL1 +kTrotecMinTimer LITERAL1 +kTrotecOff LITERAL1 +kTrotecOn LITERAL1 +kTrotecOneMark LITERAL1 +kTrotecOneSpace LITERAL1 +kTrotecSleepOn LITERAL1 +kTrotecStateLength LITERAL1 +kTrotecTimerOn LITERAL1 +kTrotecZeroMark LITERAL1 +kTrotecZeroSpace LITERAL1 +kUnknownThreshold LITERAL1 +kWhirlpoolAcBitMark LITERAL1 +kWhirlpoolAcBits LITERAL1 +kWhirlpoolAcGap LITERAL1 +kWhirlpoolAcHdrMark LITERAL1 +kWhirlpoolAcHdrSpace LITERAL1 +kWhirlpoolAcMinGap LITERAL1 +kWhirlpoolAcOneSpace LITERAL1 +kWhirlpoolAcSections LITERAL1 +kWhirlpoolAcStateLength LITERAL1 +kWhirlpoolAcZeroSpace LITERAL1 +kWhynterBitMark LITERAL1 +kWhynterBitMarkTicks LITERAL1 +kWhynterBits LITERAL1 +kWhynterHdrMark LITERAL1 +kWhynterHdrMarkTicks LITERAL1 +kWhynterHdrSpace LITERAL1 +kWhynterHdrSpaceTicks LITERAL1 +kWhynterMinCommandLength LITERAL1 +kWhynterMinCommandLengthTicks LITERAL1 +kWhynterMinGap LITERAL1 +kWhynterMinGapTicks LITERAL1 +kWhynterOneSpace LITERAL1 +kWhynterOneSpaceTicks LITERAL1 +kWhynterTick LITERAL1 +kWhynterZeroSpace LITERAL1 +kWhynterZeroSpaceTicks LITERAL1 diff --git a/lib/IRremoteESP8266-2.2.1.02/library.json b/lib/IRremoteESP8266-2.5.2.03/library.json similarity index 97% rename from lib/IRremoteESP8266-2.2.1.02/library.json rename to lib/IRremoteESP8266-2.5.2.03/library.json index b8141a2eb..3fc14f027 100644 --- a/lib/IRremoteESP8266-2.2.1.02/library.json +++ b/lib/IRremoteESP8266-2.5.2.03/library.json @@ -1,6 +1,6 @@ { "name": "IRremoteESP8266", - "version": "2.2.1", + "version": "2.5.2", "keywords": "infrared, ir, remote, esp8266", "description": "Send and receive infrared signals with multiple protocols (ESP8266)", "repository": diff --git a/lib/IRremoteESP8266-2.2.1.02/library.properties b/lib/IRremoteESP8266-2.5.2.03/library.properties similarity index 96% rename from lib/IRremoteESP8266-2.2.1.02/library.properties rename to lib/IRremoteESP8266-2.5.2.03/library.properties index ae6f93da7..e71dc4154 100644 --- a/lib/IRremoteESP8266-2.2.1.02/library.properties +++ b/lib/IRremoteESP8266-2.5.2.03/library.properties @@ -1,5 +1,5 @@ name=IRremoteESP8266 -version=2.2.1 +version=2.5.2 author=Sebastien Warin, Mark Szabo, Ken Shirriff, David Conran maintainer=Mark Szabo, David Conran, Sebastien Warin, Roi Dayan, Massimiliano Pinto sentence=Send and receive infrared signals with multiple protocols (ESP8266) diff --git a/lib/IRremoteESP8266-2.2.1.02/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/platformio.ini rename to lib/IRremoteESP8266-2.5.2.03/platformio.ini diff --git a/lib/IRremoteESP8266-2.5.2.03/pylintrc b/lib/IRremoteESP8266-2.5.2.03/pylintrc new file mode 100644 index 000000000..987c6abf9 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/pylintrc @@ -0,0 +1,12 @@ +[REPORTS] + +# Tells whether to display a full report or only the messages +reports=no + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# String used as indentation unit. +indent-string=' ' diff --git a/lib/IRremoteESP8266-2.2.1.02/src/CPPLINT.cfg b/lib/IRremoteESP8266-2.5.2.03/src/CPPLINT.cfg similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/src/CPPLINT.cfg rename to lib/IRremoteESP8266-2.5.2.03/src/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.cpp b/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.cpp similarity index 59% rename from lib/IRremoteESP8266-2.2.1.02/src/IRrecv.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/IRrecv.cpp index d8e390633..b2c984396 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.cpp @@ -7,13 +7,14 @@ #include #ifndef UNIT_TEST extern "C" { - #include - #include +#include +#include } #include #endif #include #include "IRremoteESP8266.h" +#include "IRutils.h" #ifdef UNIT_TEST #undef ICACHE_RAM_ATTR @@ -34,8 +35,7 @@ irparams_t *irparams_save; // A copy of the interrupt state while decoding. #ifndef UNIT_TEST static void ICACHE_RAM_ATTR read_timeout(void *arg __attribute__((unused))) { os_intr_lock(); - if (irparams.rawlen) - irparams.rcvstate = STATE_STOP; + if (irparams.rawlen) irparams.rcvstate = kStopState; os_intr_unlock(); } @@ -57,25 +57,24 @@ static void ICACHE_RAM_ATTR gpio_intr() { if (rawlen >= irparams.bufsize) { irparams.overflow = true; - irparams.rcvstate = STATE_STOP; + irparams.rcvstate = kStopState; } - if (irparams.rcvstate == STATE_STOP) - return; + if (irparams.rcvstate == kStopState) return; - if (irparams.rcvstate == STATE_IDLE) { - irparams.rcvstate = STATE_MARK; + if (irparams.rcvstate == kIdleState) { + irparams.rcvstate = kMarkState; irparams.rawbuf[rawlen] = 1; } else { if (now < start) - irparams.rawbuf[rawlen] = (UINT32_MAX - start + now) / RAWTICK; + irparams.rawbuf[rawlen] = (UINT32_MAX - start + now) / kRawTick; else - irparams.rawbuf[rawlen] = (now - start) / RAWTICK; + irparams.rawbuf[rawlen] = (now - start) / kRawTick; } irparams.rawlen++; start = now; - #define ONCE 0 +#define ONCE 0 os_timer_arm(&timer, irparams.timeout, ONCE); } #endif // UNIT_TEST @@ -85,23 +84,24 @@ static void ICACHE_RAM_ATTR gpio_intr() { // Class constructor // Args: // recvpin: GPIO pin the IR receiver module's data pin is connected to. -// bufsize: Nr. of entries to have in the capture buffer. (Default: RAWBUF) +// bufsize: Nr. of entries to have in the capture buffer. (Default: kRawBuf) // timeout: Nr. of milli-Seconds of no signal before we stop capturing data. -// (Default: TIMEOUT_MS) +// (Default: kTimeoutMs) // save_buffer: Use a second (save) buffer to decode from. (Def: false) // Returns: -// A IRrecv class object. +// An IRrecv class object. IRrecv::IRrecv(uint16_t recvpin, uint16_t bufsize, uint8_t timeout, bool save_buffer) { irparams.recvpin = recvpin; irparams.bufsize = bufsize; // Ensure we are going to be able to store all possible values in the // capture buffer. - irparams.timeout = std::min(timeout, (uint8_t) MAX_TIMEOUT_MS); + irparams.timeout = std::min(timeout, (uint8_t)kMaxTimeoutMs); irparams.rawbuf = new uint16_t[bufsize]; if (irparams.rawbuf == NULL) { - DPRINTLN("Could not allocate memory for the primary IR buffer.\n" - "Try a smaller size for CAPTURE_BUFFER_SIZE.\nRebooting!"); + DPRINTLN( + "Could not allocate memory for the primary IR buffer.\n" + "Try a smaller size for CAPTURE_BUFFER_SIZE.\nRebooting!"); #ifndef UNIT_TEST ESP.restart(); // Mem alloc failure. Reboot. #endif @@ -112,8 +112,9 @@ IRrecv::IRrecv(uint16_t recvpin, uint16_t bufsize, uint8_t timeout, irparams_save->rawbuf = new uint16_t[bufsize]; // Check we allocated the memory successfully. if (irparams_save->rawbuf == NULL) { - DPRINTLN("Could not allocate memory for the second IR buffer.\n" - "Try a smaller size for CAPTURE_BUFFER_SIZE.\nRebooting!"); + DPRINTLN( + "Could not allocate memory for the second IR buffer.\n" + "Try a smaller size for CAPTURE_BUFFER_SIZE.\nRebooting!"); #ifndef UNIT_TEST ESP.restart(); // Mem alloc failure. Reboot. #endif @@ -121,13 +122,16 @@ IRrecv::IRrecv(uint16_t recvpin, uint16_t bufsize, uint8_t timeout, } else { irparams_save = NULL; } +#if DECODE_HASH + unknown_threshold = kUnknownThreshold; +#endif // DECODE_HASH } // Class destructor IRrecv::~IRrecv(void) { - delete [] irparams.rawbuf; + delete[] irparams.rawbuf; if (irparams_save != NULL) { - delete [] irparams_save->rawbuf; + delete[] irparams_save->rawbuf; delete irparams_save; } } @@ -156,7 +160,7 @@ void IRrecv::disableIRIn() { } void IRrecv::resume() { - irparams.rcvstate = STATE_IDLE; + irparams.rcvstate = kIdleState; irparams.rawlen = 0; irparams.overflow = false; } @@ -164,15 +168,15 @@ void IRrecv::resume() { // Make a copy of the interrupt state & buffer data. // Needed because irparams is marked as volatile, thus memcpy() isn't allowed. // Only call this when you know the interrupt handlers won't modify anything. -// i.e. In STATE_STOP. +// i.e. In kStopState. // // Args: // src: Pointer to an irparams_t structure to copy from. // dst: Pointer to an irparams_t structure to copy to. void IRrecv::copyIrParams(volatile irparams_t *src, irparams_t *dst) { // Typecast src and dst addresses to (char *) - char *csrc = (char *) src; // NOLINT(readability/casting) - char *cdst = (char *) dst; // NOLINT(readability/casting) + char *csrc = (char *)src; // NOLINT(readability/casting) + char *cdst = (char *)dst; // NOLINT(readability/casting) // Save the pointer to the destination's rawbuf so we don't lose it as // the for-loop/copy after this will overwrite it with src's rawbuf pointer. @@ -181,22 +185,25 @@ void IRrecv::copyIrParams(volatile irparams_t *src, irparams_t *dst) { dst_rawbuf_ptr = dst->rawbuf; // Copy contents of src[] to dst[] - for (uint16_t i = 0; i < sizeof(irparams_t); i++) - cdst[i] = csrc[i]; + for (uint16_t i = 0; i < sizeof(irparams_t); i++) cdst[i] = csrc[i]; // Restore the buffer pointer dst->rawbuf = dst_rawbuf_ptr; // Copy the rawbuf - for (uint16_t i = 0; i < dst->bufsize; i++) - dst->rawbuf[i] = src->rawbuf[i]; + for (uint16_t i = 0; i < dst->bufsize; i++) dst->rawbuf[i] = src->rawbuf[i]; } // Obtain the maximum number of entries possible in the capture buffer. // i.e. It's size. -uint16_t IRrecv::getBufSize() { - return irparams.bufsize; +uint16_t IRrecv::getBufSize() { return irparams.bufsize; } + +#if DECODE_HASH +// Set the minimum length we will consider for reporting UNKNOWN message types. +void IRrecv::setUnknownThreshold(uint16_t length) { + unknown_threshold = length; } +#endif // DECODE_HASH // Decodes the received IR message. // If the interrupt state is saved, we will immediately resume waiting @@ -213,8 +220,7 @@ uint16_t IRrecv::getBufSize() { bool IRrecv::decode(decode_results *results, irparams_t *save) { // Proceed only if an IR message been received. #ifndef UNIT_TEST - if (irparams.rcvstate != STATE_STOP) - return false; + if (irparams.rcvstate != kStopState) return false; #endif // Clear the entry we are currently pointing to when we got the timeout. @@ -230,8 +236,7 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { bool resumed = false; // Flag indicating if we have resumed. // If we were requested to use a save buffer previously, do so. - if (save == NULL) - save = irparams_save; + if (save == NULL) save = irparams_save; if (save == NULL) { // We haven't been asked to copy it so use the existing memory. @@ -263,8 +268,7 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { // Try decodeAiwaRCT501() before decodeSanyoLC7461() & decodeNEC() // because the protocols are similar. This protocol is more specific than // those ones, so should got before them. - if (decodeAiwaRCT501(results)) - return true; + if (decodeAiwaRCT501(results)) return true; #endif #if DECODE_SANYO DPRINTLN("Attempting Sanyo LC7461 decode"); @@ -272,97 +276,135 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { // similar in timings & structure, but the Sanyo one is much longer than the // NEC protocol (42 vs 32 bits) so this one should be tried first to try to // reduce false detection as a NEC packet. - if (decodeSanyoLC7461(results)) - return true; + if (decodeSanyoLC7461(results)) return true; +#endif +#if DECODE_CARRIER_AC + DPRINTLN("Attempting Carrier AC decode"); + // Try decodeCarrierAC() before decodeNEC() because the protocols are + // similar in timings & structure, but the Carrier one is much longer than the + // NEC protocol (3x32 bits vs 1x32 bits) so this one should be tried first to + // try to reduce false detection as a NEC packet. + if (decodeCarrierAC(results)) return true; +#endif +#if DECODE_PIONEER + DPRINTLN("Attempting Pioneer decode"); + // Try decodePioneer() before decodeNEC() because the protocols are + // similar in timings & structure, but the Pioneer one is much longer than the + // NEC protocol (2x32 bits vs 1x32 bits) so this one should be tried first to + // try to reduce false detection as a NEC packet. + if (decodePioneer(results)) return true; #endif #if DECODE_NEC DPRINTLN("Attempting NEC decode"); - if (decodeNEC(results)) - return true; + if (decodeNEC(results)) return true; #endif #if DECODE_SONY DPRINTLN("Attempting Sony decode"); - if (decodeSony(results)) - return true; + if (decodeSony(results)) return true; #endif #if DECODE_MITSUBISHI DPRINTLN("Attempting Mitsubishi decode"); - if (decodeMitsubishi(results)) - return true; + if (decodeMitsubishi(results)) return true; +#endif +#if DECODE_MITSUBISHI_AC + DPRINTLN("Attempting Mitsubishi AC decode"); + if (decodeMitsubishiAC(results)) return true; +#endif +#if DECODE_MITSUBISHI2 + DPRINTLN("Attempting Mitsubishi2 decode"); + if (decodeMitsubishi2(results)) return true; #endif #if DECODE_RC5 DPRINTLN("Attempting RC5 decode"); - if (decodeRC5(results)) - return true; + if (decodeRC5(results)) return true; #endif #if DECODE_RC6 DPRINTLN("Attempting RC6 decode"); - if (decodeRC6(results)) - return true; + if (decodeRC6(results)) return true; #endif #if DECODE_RCMM DPRINTLN("Attempting RC-MM decode"); - if (decodeRCMM(results)) - return true; + if (decodeRCMM(results)) return true; +#endif +#if DECODE_FUJITSU_AC + // Fujitsu A/C needs to precede Panasonic and Denon as it has a short + // message which looks exactly the same as a Panasonic/Denon message. + DPRINTLN("Attempting Fujitsu A/C decode"); + if (decodeFujitsuAC(results)) return true; #endif #if DECODE_DENON // Denon needs to precede Panasonic as it is a special case of Panasonic. -#ifdef DEBUG DPRINTLN("Attempting Denon decode"); -#endif - if (decodeDenon(results, DENON_48_BITS) || - decodeDenon(results, DENON_BITS) || - decodeDenon(results, DENON_LEGACY_BITS)) + if (decodeDenon(results, DENON_48_BITS) || decodeDenon(results, DENON_BITS) || + decodeDenon(results, kDenonLegacyBits)) return true; #endif #if DECODE_PANASONIC DPRINTLN("Attempting Panasonic decode"); - if (decodePanasonic(results)) - return true; + if (decodePanasonic(results)) return true; #endif #if DECODE_LG DPRINTLN("Attempting LG (28-bit) decode"); - if (decodeLG(results, LG_BITS, true)) - return true; + if (decodeLG(results, kLgBits, true)) return true; DPRINTLN("Attempting LG (32-bit) decode"); // LG32 should be tried before Samsung - if (decodeLG(results, LG32_BITS, true)) - return true; + if (decodeLG(results, kLg32Bits, true)) return true; +#endif +#if DECODE_GICABLE + // Note: Needs to happen before JVC decode, because it looks similar except + // with a required NEC-like repeat code. + DPRINTLN("Attempting GICable decode"); + if (decodeGICable(results)) return true; #endif #if DECODE_JVC DPRINTLN("Attempting JVC decode"); - if (decodeJVC(results)) - return true; + if (decodeJVC(results)) return true; #endif #if DECODE_SAMSUNG DPRINTLN("Attempting SAMSUNG decode"); - if (decodeSAMSUNG(results)) - return true; + if (decodeSAMSUNG(results)) return true; #endif #if DECODE_WHYNTER DPRINTLN("Attempting Whynter decode"); - if (decodeWhynter(results)) - return true; + if (decodeWhynter(results)) return true; #endif #if DECODE_DISH DPRINTLN("Attempting DISH decode"); - if (decodeDISH(results)) - return true; + if (decodeDISH(results)) return true; #endif #if DECODE_SHARP DPRINTLN("Attempting Sharp decode"); - if (decodeSharp(results)) - return true; + if (decodeSharp(results)) return true; #endif #if DECODE_COOLIX DPRINTLN("Attempting Coolix decode"); - if (decodeCOOLIX(results)) - return true; + if (decodeCOOLIX(results)) return true; #endif #if DECODE_NIKAI DPRINTLN("Attempting Nikai decode"); - if (decodeNikai(results)) - return true; + if (decodeNikai(results)) return true; +#endif +#if DECODE_KELVINATOR + // Kelvinator based-devices use a similar code to Gree ones, to avoid false + // matches this needs to happen before decodeGree(). + DPRINTLN("Attempting Kelvinator decode"); + if (decodeKelvinator(results)) return true; +#endif +#if DECODE_DAIKIN + DPRINTLN("Attempting Daikin decode"); + if (decodeDaikin(results)) return true; +#endif +#if DECODE_TOSHIBA_AC + DPRINTLN("Attempting Toshiba AC decode"); + if (decodeToshibaAC(results)) return true; +#endif +#if DECODE_MIDEA + DPRINTLN("Attempting Midea decode"); + if (decodeMidea(results)) return true; +#endif +#if DECODE_MAGIQUEST + DPRINTLN("Attempting Magiquest decode"); + if (decodeMagiQuest(results)) return true; #endif /* NOTE: Disabled due to poor quality. #if DECODE_SANYO @@ -380,18 +422,81 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { // This needs to be done after all other codes that use strict and some // other protocols that are NEC-like as well, as turning off strict may // cause this to match other valid protocols. - DPRINTLN("Attempting NEC (non-stict) decode"); - if (decodeNEC(results, NEC_BITS, false)) { + DPRINTLN("Attempting NEC (non-strict) decode"); + if (decodeNEC(results, kNECBits, false)) { results->decode_type = NEC_LIKE; return true; } #endif +#if DECODE_LASERTAG + DPRINTLN("Attempting Lasertag decode"); + if (decodeLasertag(results)) return true; +#endif +#if DECODE_GREE + // Gree based-devices use a similar code to Kelvinator ones, to avoid false + // matches this needs to happen after decodeKelvinator(). + DPRINTLN("Attempting Gree decode"); + if (decodeGree(results)) return true; +#endif +#if DECODE_HAIER_AC + DPRINTLN("Attempting Haier AC decode"); + if (decodeHaierAC(results)) return true; +#endif +#if DECODE_HAIER_AC_YRW02 + DPRINTLN("Attempting Haier AC YR-W02 decode"); + if (decodeHaierACYRW02(results)) return true; +#endif +#if DECODE_HITACHI_AC2 + // HitachiAC2 should be checked before HitachiAC + DPRINTLN("Attempting Hitachi AC2 decode"); + if (decodeHitachiAC(results, kHitachiAc2Bits)) return true; +#endif +#if DECODE_HITACHI_AC + DPRINTLN("Attempting Hitachi AC decode"); + if (decodeHitachiAC(results, kHitachiAcBits)) return true; +#endif +#if DECODE_HITACHI_AC1 + DPRINTLN("Attempting Hitachi AC1 decode"); + if (decodeHitachiAC(results, kHitachiAc1Bits)) return true; +#endif +#if DECODE_WHIRLPOOL_AC + DPRINTLN("Attempting Whirlpool AC decode"); + if (decodeWhirlpoolAC(results)) return true; +#endif +#if DECODE_SAMSUNG_AC + DPRINTLN("Attempting Samsung AC (extended) decode"); + // Check the extended size first, as it should fail fast due to longer length. + if (decodeSamsungAC(results, kSamsungAcExtendedBits, false)) return true; + // Now check for the more common length. + DPRINTLN("Attempting Samsung AC decode"); + if (decodeSamsungAC(results, kSamsungAcBits)) return true; +#endif +#if DECODE_ELECTRA_AC + DPRINTLN("Attempting Electra AC decode"); + if (decodeElectraAC(results)) return true; +#endif +#if DECODE_PANASONIC_AC + DPRINTLN("Attempting Panasonic AC decode"); + if (decodePanasonicAC(results)) return true; + DPRINTLN("Attempting Panasonic AC short decode"); + if (decodePanasonicAC(results, kPanasonicAcShortBits)) return true; +#endif +#if DECODE_LUTRON + DPRINTLN("Attempting Lutron decode"); + if (decodeLutron(results)) return true; +#endif +#if DECODE_MWM + DPRINTLN("Attempting MWM decode"); + if (decodeMWM(results)) return true; +#endif +#if DECODE_HASH // decodeHash returns a hash on any input. // Thus, it needs to be last in the list. // If you add any decodes, add them before this. if (decodeHash(results)) { return true; } +#endif // DECODE_HASH // Throw away and start over if (!resumed) // Check if we have already resumed. resume(); @@ -403,11 +508,13 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { // Args: // usecs: Nr. of uSeconds. // tolerance: Percent as an integer. e.g. 10 is 10% +// delta: A non-scaling amount to reduce usecs by. // Returns: // Nr. of ticks. -uint32_t IRrecv::ticksLow(uint32_t usecs, uint8_t tolerance) { +uint32_t IRrecv::ticksLow(uint32_t usecs, uint8_t tolerance, uint16_t delta) { // max() used to ensure the result can't drop below 0 before the cast. - return((uint32_t) std::max((int32_t) (usecs * (1.0 - tolerance / 100.0)), 0)); + return ((uint32_t)std::max( + (int32_t)(usecs * (1.0 - tolerance / 100.0) - delta), 0)); } // Calculate the upper bound of the nr. of ticks. @@ -415,49 +522,52 @@ uint32_t IRrecv::ticksLow(uint32_t usecs, uint8_t tolerance) { // Args: // usecs: Nr. of uSeconds. // tolerance: Percent as an integer. e.g. 10 is 10% +// delta: A non-scaling amount to increase usecs by. // Returns: // Nr. of ticks. -uint32_t IRrecv::ticksHigh(uint32_t usecs, uint8_t tolerance) { - return((uint32_t) (usecs * (1.0 + tolerance / 100.0)) + 1); +uint32_t IRrecv::ticksHigh(uint32_t usecs, uint8_t tolerance, uint16_t delta) { + return ((uint32_t)(usecs * (1.0 + tolerance / 100.0)) + 1 + delta); } // Check if we match a pulse(measured) with the desired within -// +/-tolerance percent. +// +/-tolerance percent and/or +/- a fixed delta range. // // Args: // measured: The recorded period of the signal pulse. // desired: The expected period (in useconds) we are matching against. // tolerance: A percentage expressed as an integer. e.g. 10 is 10%. +// delta: A non-scaling (+/-) error margin (in useconds). // // Returns: // Boolean: true if it matches, false if it doesn't. -bool IRrecv::match(uint32_t measured, uint32_t desired, - uint8_t tolerance) { - measured *= RAWTICK; // Convert to uSecs. +bool IRrecv::match(uint32_t measured, uint32_t desired, uint8_t tolerance, + uint16_t delta) { + measured *= kRawTick; // Convert to uSecs. DPRINT("Matching: "); - DPRINT(ticksLow(desired, tolerance)); + DPRINT(ticksLow(desired, tolerance, delta)); DPRINT(" <= "); DPRINT(measured); DPRINT(" <= "); - DPRINTLN(ticksHigh(desired, tolerance)); - return (measured >= ticksLow(desired, tolerance) && - measured <= ticksHigh(desired, tolerance)); + DPRINTLN(ticksHigh(desired, tolerance, delta)); + return (measured >= ticksLow(desired, tolerance, delta) && + measured <= ticksHigh(desired, tolerance, delta)); } - // Check if we match a pulse(measured) of at least desired within -// +/-tolerance percent. +// tolerance percent and/or a fixed delta margin. // // Args: // measured: The recorded period of the signal pulse. // desired: The expected period (in useconds) we are matching against. // tolerance: A percentage expressed as an integer. e.g. 10 is 10%. +// delta: A non-scaling amount to reduce usecs by. + // // Returns: // Boolean: true if it matches, false if it doesn't. bool IRrecv::matchAtLeast(uint32_t measured, uint32_t desired, - uint8_t tolerance) { - measured *= RAWTICK; // Convert to uSecs. + uint8_t tolerance, uint16_t delta) { + measured *= kRawTick; // Convert to uSecs. DPRINT("Matching ATLEAST "); DPRINT(measured); DPRINT(" vs "); @@ -465,17 +575,18 @@ bool IRrecv::matchAtLeast(uint32_t measured, uint32_t desired, DPRINT(". Matching: "); DPRINT(measured); DPRINT(" >= "); - DPRINT(ticksLow(std::min(desired, MS_TO_USEC(irparams.timeout)), tolerance)); + DPRINT(ticksLow(std::min(desired, MS_TO_USEC(irparams.timeout)), tolerance, + delta)); DPRINT(" [min("); - DPRINT(ticksLow(desired, tolerance)); + DPRINT(ticksLow(desired, tolerance, delta)); DPRINT(", "); - DPRINT(ticksLow(MS_TO_USEC(irparams.timeout), tolerance)); + DPRINT(ticksLow(MS_TO_USEC(irparams.timeout), tolerance, delta)); DPRINTLN(")]"); // We really should never get a value of 0, except as the last value // in the buffer. If that is the case, then assume infinity and return true. if (measured == 0) return true; return measured >= ticksLow(std::min(desired, MS_TO_USEC(irparams.timeout)), - tolerance); + tolerance, delta); } // Check if we match a mark signal(measured) with the desired within @@ -489,10 +600,10 @@ bool IRrecv::matchAtLeast(uint32_t measured, uint32_t desired, // // Returns: // Boolean: true if it matches, false if it doesn't. -bool IRrecv::matchMark(uint32_t measured, uint32_t desired, - uint8_t tolerance, int16_t excess) { +bool IRrecv::matchMark(uint32_t measured, uint32_t desired, uint8_t tolerance, + int16_t excess) { DPRINT("Matching MARK "); - DPRINT(measured * RAWTICK); + DPRINT(measured * kRawTick); DPRINT(" vs "); DPRINT(desired); DPRINT(" + "); @@ -512,10 +623,10 @@ bool IRrecv::matchMark(uint32_t measured, uint32_t desired, // // Returns: // Boolean: true if it matches, false if it doesn't. -bool IRrecv::matchSpace(uint32_t measured, uint32_t desired, - uint8_t tolerance, int16_t excess) { +bool IRrecv::matchSpace(uint32_t measured, uint32_t desired, uint8_t tolerance, + int16_t excess) { DPRINT("Matching SPACE "); - DPRINT(measured * RAWTICK); + DPRINT(measured * kRawTick); DPRINT(" vs "); DPRINT(desired); DPRINT(" - "); @@ -550,15 +661,15 @@ int16_t IRrecv::compare(uint16_t oldval, uint16_t newval) { return 1; } +#if DECODE_HASH /* Converts the raw code values into a 32-bit hash code. * Hopefully this code is unique for each button. * This isn't a "real" decoding, just an arbitrary value. */ bool IRrecv::decodeHash(decode_results *results) { - // Require at least 6 samples to prevent triggering on noise - if (results->rawlen < 6) - return false; - int32_t hash = FNV_BASIS_32; + // Require at least some samples to prevent triggering on noise + if (results->rawlen < unknown_threshold) return false; + int32_t hash = kFnvBasis32; // 'rawlen - 2' to avoid the look ahead from going out of bounds. // Should probably be -3 to avoid comparing the trailing space entry, // however it is left this way for compatibility with previously captured @@ -566,7 +677,7 @@ bool IRrecv::decodeHash(decode_results *results) { for (uint16_t i = 1; i < results->rawlen - 2; i++) { int16_t value = compare(results->rawbuf[i], results->rawbuf[i + 2]); // Add value into the hash - hash = (hash * FNV_PRIME_32) ^ value; + hash = (hash * kFnvPrime32) ^ value; } results->value = hash & 0xFFFFFFFF; results->bits = results->rawlen / 2; @@ -575,9 +686,11 @@ bool IRrecv::decodeHash(decode_results *results) { results->decode_type = UNKNOWN; return true; } +#endif // DECODE_HASH // Match & decode the typical data section of an IR message. -// The data value constructed as the Most Significant Bit first. +// The data value is stored in the least significant bits reguardless of the +// bit ordering requested. // // Args: // data_ptr: A pointer to where we are at in the capture buffer. @@ -586,46 +699,35 @@ bool IRrecv::decodeHash(decode_results *results) { // onespace: Nr. of uSeconds in an expected space signal for a '1' bit. // zeromark: Nr. of uSeconds in an expected mark signal for a '0' bit. // zerospace: Nr. of uSeconds in an expected space signal for a '0' bit. +// tolerance: Percentage error margin to allow. (Def: kTolerance) +// excess: Nr. of useconds. (Def: kMarkExcess) +// MSBfirst: Bit order to save the data in. (Def: true) // Returns: // A match_result_t structure containing the success (or not), the data value, // and how many buffer entries were used. -match_result_t IRrecv::matchData(volatile uint16_t *data_ptr, uint16_t nbits, - uint16_t onemark, uint32_t onespace, - uint16_t zeromark, uint32_t zerospace) { +match_result_t IRrecv::matchData( + volatile uint16_t *data_ptr, const uint16_t nbits, const uint16_t onemark, + const uint32_t onespace, const uint16_t zeromark, const uint32_t zerospace, + const uint8_t tolerance, const int16_t excess, const bool MSBfirst) { match_result_t result; - result.success = false; + result.success = false; // Fail by default. result.data = 0; - if (onemark == zeromark) { // Is this space encoded data format? - for (result.used = 0; - result.used < nbits * 2; - result.used += 2, data_ptr++) { - if (!matchMark(*data_ptr, onemark)) - return result; // Fail - data_ptr++; - if (matchSpace(*data_ptr, onespace)) - result.data = (result.data << 1) | 1; - else if (matchSpace(*data_ptr, zerospace)) - result.data <<= 1; - else - return result; // Fail + for (result.used = 0; result.used < nbits * 2; + result.used += 2, data_ptr += 2) { + // Is the bit a '1'? + if (matchMark(*data_ptr, onemark, tolerance, excess) && + matchSpace(*(data_ptr + 1), onespace, tolerance, excess)) { + result.data = (result.data << 1) | 1; + } else if (matchMark(*data_ptr, zeromark, tolerance, excess) && + matchSpace(*(data_ptr + 1), zerospace, tolerance, excess)) { + result.data <<= 1; // The bit is a '0'. + } else { + if (!MSBfirst) result.data = reverseBits(result.data, result.used / 2); + return result; // It's neither, so fail. } - result.success = true; - } else if (onespace == zerospace) { // Is this mark encoded data format? - for (result.used = 0; - result.used < nbits * 2; - result.used += 2, data_ptr++) { - if (matchMark(*data_ptr, onemark)) - result.data = (result.data << 1) | 1; - else if (matchMark(*data_ptr, zeromark)) - result.data <<= 1; - else - return result; // Fail - data_ptr++; - if (!matchSpace(*data_ptr, onespace)) - return result; // Fail - } - result.success = true; } + result.success = true; + if (!MSBfirst) result.data = reverseBits(result.data, nbits); return result; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h b/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h new file mode 100644 index 000000000..c0f5e781a --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h @@ -0,0 +1,335 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2015 Mark Szabo +// Copyright 2015 Sebastien Warin +// Copyright 2017 David Conran + +#ifndef IRRECV_H_ +#define IRRECV_H_ + +#ifndef UNIT_TEST +#include +#endif +#include +#define __STDC_LIMIT_MACROS +#include +#include "IRremoteESP8266.h" + +// Constants +const uint16_t kHeader = 2; // Usual nr. of header entries. +const uint16_t kFooter = 2; // Usual nr. of footer (stop bits) entries. +const uint16_t kStartOffset = 1; // Usual rawbuf entry to start from. +#define MS_TO_USEC(x) (x * 1000U) // Convert milli-Seconds to micro-Seconds. +// Marks tend to be 100us too long, and spaces 100us too short +// when received due to sensor lag. +const uint16_t kMarkExcess = 50; +const uint16_t kRawBuf = 100; // Default length of raw capture buffer +const uint64_t kRepeat = UINT64_MAX; +// Default min size of reported UNKNOWN messages. +const uint16_t kUnknownThreshold = 6; + +// receiver states +const uint8_t kIdleState = 2; +const uint8_t kMarkState = 3; +const uint8_t kSpaceState = 4; +const uint8_t kStopState = 5; +const uint8_t kTolerance = 25; // default percent tolerance in measurements. +const uint16_t kRawTick = 2; // Capture tick to uSec factor. +#define RAWTICK kRawTick // Deprecated. For legacy user code support only. +// How long (ms) before we give up wait for more data? +// Don't exceed kMaxTimeoutMs without a good reason. +// That is the capture buffers maximum value size. (UINT16_MAX / kRawTick) +// Typically messages/protocols tend to repeat around the 100ms timeframe, +// thus we should timeout before that to give us some time to try to decode +// before we need to start capturing a possible new message. +// Typically 15ms suits most applications. However, some protocols demand a +// higher value. e.g. 90ms for XMP-1 and some aircon units. +const uint8_t kTimeoutMs = 15; // In MilliSeconds. +#define TIMEOUT_MS kTimeoutMs // For legacy documentation. +const uint16_t kMaxTimeoutMs = kRawTick * (UINT16_MAX / MS_TO_USEC(1)); + +// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param +const uint32_t kFnvPrime32 = 16777619UL; +const uint32_t kFnvBasis32 = 2166136261UL; + +#if DECODE_AC +// Hitachi AC is the current largest state size. +const uint16_t kStateSizeMax = kHitachiAc2StateLength; +#else +// Just define something +const uint16_t kStateSizeMax = 0; +#endif + +// Types +// information for the interrupt handler +typedef struct { + uint8_t recvpin; // pin for IR data from detector + uint8_t rcvstate; // state machine + uint16_t timer; // state timer, counts 50uS ticks. + uint16_t bufsize; // max. nr. of entries in the capture buffer. + uint16_t *rawbuf; // raw data + // uint16_t is used for rawlen as it saves 3 bytes of iram in the interrupt + // handler. Don't ask why, I don't know. It just does. + uint16_t rawlen; // counter of entries in rawbuf. + uint8_t overflow; // Buffer overflow indicator. + uint8_t timeout; // Nr. of milliSeconds before we give up. +} irparams_t; + +// results from a data match +typedef struct { + bool success; // Was the match successful? + uint64_t data; // The data found. + uint16_t used; // How many buffer positions were used. +} match_result_t; + +// Classes + +// Results returned from the decoder +class decode_results { + public: + decode_type_t decode_type; // NEC, SONY, RC5, UNKNOWN + // value, address, & command are all mutually exclusive with state. + // i.e. They MUST NOT be used at the same time as state, so we can use a union + // structure to save us a handful of valuable bytes of memory. + union { + struct { + uint64_t value; // Decoded value + uint32_t address; // Decoded device address. + uint32_t command; // Decoded command. + }; + uint8_t state[kStateSizeMax]; // Multi-byte results. + }; + uint16_t bits; // Number of bits in decoded value + volatile uint16_t *rawbuf; // Raw intervals in .5 us ticks + uint16_t rawlen; // Number of records in rawbuf. + bool overflow; + bool repeat; // Is the result a repeat code? +}; + +// main class for receiving IR +class IRrecv { + public: + explicit IRrecv(uint16_t recvpin, uint16_t bufsize = kRawBuf, + uint8_t timeout = kTimeoutMs, + bool save_buffer = false); // Constructor + ~IRrecv(); // Destructor + bool decode(decode_results *results, irparams_t *save = NULL); + void enableIRIn(); + void disableIRIn(); + void resume(); + uint16_t getBufSize(); +#if DECODE_HASH + void setUnknownThreshold(uint16_t length); +#endif + static bool match(uint32_t measured, uint32_t desired, + uint8_t tolerance = kTolerance, uint16_t delta = 0); + static bool matchMark(uint32_t measured, uint32_t desired, + uint8_t tolerance = kTolerance, + int16_t excess = kMarkExcess); + static bool matchSpace(uint32_t measured, uint32_t desired, + uint8_t tolerance = kTolerance, + int16_t excess = kMarkExcess); +#ifndef UNIT_TEST + + private: +#endif + irparams_t *irparams_save; +#if DECODE_HASH + uint16_t unknown_threshold; +#endif + // These are called by decode + void copyIrParams(volatile irparams_t *src, irparams_t *dst); + int16_t compare(uint16_t oldval, uint16_t newval); + static uint32_t ticksLow(uint32_t usecs, uint8_t tolerance = kTolerance, + uint16_t delta = 0); + static uint32_t ticksHigh(uint32_t usecs, uint8_t tolerance = kTolerance, + uint16_t delta = 0); + bool matchAtLeast(uint32_t measured, uint32_t desired, + uint8_t tolerance = kTolerance, uint16_t delta = 0); + match_result_t matchData(volatile uint16_t *data_ptr, const uint16_t nbits, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint8_t tolerance = kTolerance, + const int16_t excess = kMarkExcess, + const bool MSBfirst = true); + bool decodeHash(decode_results *results); +#if (DECODE_NEC || DECODE_SHERWOOD || DECODE_AIWA_RC_T501 || SEND_SANYO) + bool decodeNEC(decode_results *results, uint16_t nbits = kNECBits, + bool strict = true); +#endif +#if DECODE_SONY + bool decodeSony(decode_results *results, uint16_t nbits = kSonyMinBits, + bool strict = false); +#endif +#if DECODE_SANYO + // DISABLED due to poor quality. + // bool decodeSanyo(decode_results *results, + // uint16_t nbits = kSanyoSA8650BBits, + // bool strict = false); + bool decodeSanyoLC7461(decode_results *results, + uint16_t nbits = kSanyoLC7461Bits, bool strict = true); +#endif +#if DECODE_MITSUBISHI + bool decodeMitsubishi(decode_results *results, + uint16_t nbits = kMitsubishiBits, bool strict = true); +#endif +#if DECODE_MITSUBISHI2 + bool decodeMitsubishi2(decode_results *results, + uint16_t nbits = kMitsubishiBits, bool strict = true); +#endif +#if DECODE_MITSUBISHI_AC + bool decodeMitsubishiAC(decode_results *results, + uint16_t nbits = kMitsubishiACBits, + bool strict = false); +#endif +#if (DECODE_RC5 || DECODE_R6 || DECODE_LASERTAG || DECODE_MWM) + int16_t getRClevel(decode_results *results, uint16_t *offset, uint16_t *used, + uint16_t bitTime, uint8_t tolerance = kTolerance, + int16_t excess = kMarkExcess, uint16_t delta = 0, + uint8_t maxwidth = 3); +#endif +#if DECODE_RC5 + bool decodeRC5(decode_results *results, uint16_t nbits = kRC5XBits, + bool strict = true); +#endif +#if DECODE_RC6 + bool decodeRC6(decode_results *results, uint16_t nbits = kRC6Mode0Bits, + bool strict = false); +#endif +#if DECODE_RCMM + bool decodeRCMM(decode_results *results, uint16_t nbits = kRCMMBits, + bool strict = false); +#endif +#if (DECODE_PANASONIC || DECODE_DENON) + bool decodePanasonic(decode_results *results, uint16_t nbits = kPanasonicBits, + bool strict = false, + uint32_t manufacturer = kPanasonicManufacturer); +#endif +#if DECODE_LG + bool decodeLG(decode_results *results, uint16_t nbits = kLgBits, + bool strict = false); +#endif +#if DECODE_JVC + bool decodeJVC(decode_results *results, uint16_t nbits = kJvcBits, + bool strict = true); +#endif +#if DECODE_SAMSUNG + bool decodeSAMSUNG(decode_results *results, uint16_t nbits = kSamsungBits, + bool strict = true); +#endif +#if DECODE_SAMSUNG_AC + bool decodeSamsungAC(decode_results *results, uint16_t nbits = kSamsungAcBits, + bool strict = true); +#endif +#if DECODE_WHYNTER + bool decodeWhynter(decode_results *results, uint16_t nbits = kWhynterBits, + bool strict = true); +#endif +#if DECODE_COOLIX + bool decodeCOOLIX(decode_results *results, uint16_t nbits = kCoolixBits, + bool strict = true); +#endif +#if DECODE_DENON + bool decodeDenon(decode_results *results, uint16_t nbits = DENON_BITS, + bool strict = true); +#endif +#if DECODE_DISH + bool decodeDISH(decode_results *results, uint16_t nbits = kDishBits, + bool strict = true); +#endif +#if (DECODE_SHARP || DECODE_DENON) + bool decodeSharp(decode_results *results, uint16_t nbits = kSharpBits, + bool strict = true, bool expansion = true); +#endif +#if DECODE_AIWA_RC_T501 + bool decodeAiwaRCT501(decode_results *results, + uint16_t nbits = kAiwaRcT501Bits, bool strict = true); +#endif +#if DECODE_NIKAI + bool decodeNikai(decode_results *results, uint16_t nbits = kNikaiBits, + bool strict = true); +#endif +#if DECODE_MAGIQUEST + bool decodeMagiQuest(decode_results *results, uint16_t nbits = kMagiquestBits, + bool strict = true); +#endif +#if DECODE_KELVINATOR + bool decodeKelvinator(decode_results *results, + uint16_t nbits = kKelvinatorBits, bool strict = true); +#endif +#if DECODE_DAIKIN + bool decodeDaikin(decode_results *results, uint16_t nbits = kDaikinRawBits, + bool strict = true); +#endif +#if DECODE_TOSHIBA_AC + bool decodeToshibaAC(decode_results *results, + uint16_t nbytes = kToshibaACBits, bool strict = true); +#endif +#if DECODE_MIDEA + bool decodeMidea(decode_results *results, uint16_t nbits = kMideaBits, + bool strict = true); +#endif +#if DECODE_FUJITSU_AC + bool decodeFujitsuAC(decode_results *results, uint16_t nbits = kFujitsuAcBits, + bool strict = false); +#endif +#if DECODE_LASERTAG + bool decodeLasertag(decode_results *results, uint16_t nbits = kLasertagBits, + bool strict = true); +#endif +#if DECODE_CARRIER_AC + bool decodeCarrierAC(decode_results *results, uint16_t nbits = kCarrierAcBits, + bool strict = true); +#endif +#if DECODE_GREE + bool decodeGree(decode_results *results, uint16_t nbits = kGreeBits, + bool strict = true); +#endif +#if (DECODE_HAIER_AC | DECODE_HAIER_AC_YRW02) + bool decodeHaierAC(decode_results *results, uint16_t nbits = kHaierACBits, + bool strict = true); +#endif +#if DECODE_HAIER_AC_YRW02 + bool decodeHaierACYRW02(decode_results *results, + uint16_t nbits = kHaierACYRW02Bits, + bool strict = true); +#endif +#if (DECODE_HITACHI_AC || DECODE_HITACHI_AC2) + bool decodeHitachiAC(decode_results *results, uint16_t nbits = kHitachiAcBits, + bool strict = true); +#endif +#if DECODE_HITACHI_AC1 + bool decodeHitachiAC1(decode_results *results, + uint16_t nbits = kHitachiAc1Bits, bool strict = true); +#endif +#if DECODE_GICABLE + bool decodeGICable(decode_results *results, uint16_t nbits = kGicableBits, + bool strict = true); +#endif +#if DECODE_WHIRLPOOL_AC + bool decodeWhirlpoolAC(decode_results *results, + uint16_t nbits = kWhirlpoolAcBits, bool strict = true); +#endif +#if DECODE_LUTRON + bool decodeLutron(decode_results *results, uint16_t nbits = kLutronBits, + bool strict = true); +#endif +#if DECODE_ELECTRA_AC + bool decodeElectraAC(decode_results *results, uint16_t nbits = kElectraAcBits, + bool strict = true); +#endif +#if DECODE_PANASONIC_AC + bool decodePanasonicAC(decode_results *results, + uint16_t nbits = kPanasonicAcBits, bool strict = true); +#endif +#if DECODE_PIONEER + bool decodePioneer(decode_results *results, + const uint16_t nbits = kPioneerBits, + const bool strict = true); +#endif +#if DECODE_MWM + bool decodeMWM(decode_results *results, uint16_t nbits = 24, + bool strict = true); +#endif +}; + +#endif // IRRECV_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRremoteESP8266.h b/lib/IRremoteESP8266-2.5.2.03/src/IRremoteESP8266.h new file mode 100644 index 000000000..e228cbcb0 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRremoteESP8266.h @@ -0,0 +1,601 @@ + /*************************************************** + * IRremote for ESP8266 + * + * Based on the IRremote library for Arduino by Ken Shirriff + * Version 0.11 August, 2009 + * Copyright 2009 Ken Shirriff + * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html + * + * Edited by Mitra to add new controller SANYO + * + * Interrupt code based on NECIRrcv by Joe Knapp + * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 + * Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ + * + * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post) + * LG added by Darryl Smith (based on the JVC protocol) + * Whynter A/C ARC-110WD added by Francesco Meschia + * Coolix A/C / heatpump added by (send) bakrus & (decode) crankyoldgit + * Denon: sendDenon, decodeDenon added by Massimiliano Pinto + (from https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Denon.cpp) + * Kelvinator A/C and Sherwood added by crankyoldgit + * Mitsubishi (TV) sending added by crankyoldgit + * Pronto code sending added by crankyoldgit + * Mitsubishi & Toshiba A/C added by crankyoldgit + * (derived from https://github.com/r45635/HVAC-IR-Control) + * DISH decode by marcosamarinho + * Gree Heatpump sending added by Ville Skyttä (scop) + * (derived from https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp) + * Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for sending IR code on ESP8266 + * Updated by Sebastien Warin (http://sebastien.warin.fr) for receiving IR code on ESP8266 + * + * Updated by sillyfrog for Daikin, adopted from + * (https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/) + * Fujitsu A/C code added by jonnygraham + * Trotec AC code by stufisher + * Carrier & Haier AC code by crankyoldgit + * + * GPL license, all text above must be included in any redistribution + ****************************************************/ + +#ifndef IRREMOTEESP8266_H_ +#define IRREMOTEESP8266_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifdef UNIT_TEST +#include +#endif + +// Library Version +#define _IRREMOTEESP8266_VERSION_ "2.5.2" +// Supported IR protocols +// Each protocol you include costs memory and, during decode, costs time +// Disable (set to false) all the protocols you do not need/want! +// The Air Conditioner protocols are the most expensive memory-wise. +// +/* +#define DECODE_HASH true // Semi-unique code for unknown messages + +#define SEND_RAW true + +#define DECODE_NEC true +#define SEND_NEC true + +#define DECODE_SHERWOOD true // Doesn't exist. Actually is DECODE_NEC +#define SEND_SHERWOOD true + +#define DECODE_RC5 true +#define SEND_RC5 true + +#define DECODE_RC6 true +#define SEND_RC6 true + +#define DECODE_RCMM true +#define SEND_RCMM true + +#define DECODE_SONY true +#define SEND_SONY true + +#define DECODE_PANASONIC true +#define SEND_PANASONIC true + +#define DECODE_JVC true +#define SEND_JVC true + +#define DECODE_SAMSUNG true +#define SEND_SAMSUNG true + +#define DECODE_SAMSUNG_AC true +#define SEND_SAMSUNG_AC true + +#define DECODE_WHYNTER true +#define SEND_WHYNTER true + +#define DECODE_AIWA_RC_T501 true +#define SEND_AIWA_RC_T501 true + +#define DECODE_LG true +#define SEND_LG true + +#define DECODE_SANYO true +#define SEND_SANYO true + +#define DECODE_MITSUBISHI true +#define SEND_MITSUBISHI true + +#define DECODE_MITSUBISHI2 true +#define SEND_MITSUBISHI2 true + +#define DECODE_DISH true +#define SEND_DISH true + +#define DECODE_SHARP true +#define SEND_SHARP true + +#define DECODE_DENON true +#define SEND_DENON true + +#define DECODE_KELVINATOR true +#define SEND_KELVINATOR true + +#define DECODE_MITSUBISHI_AC true // Beta. +#define SEND_MITSUBISHI_AC true + +#define DECODE_FUJITSU_AC true +#define SEND_FUJITSU_AC true + +#define DECODE_DAIKIN true +#define SEND_DAIKIN true + +#define DECODE_COOLIX true +#define SEND_COOLIX true + +#define DECODE_GLOBALCACHE false // Not written. +#define SEND_GLOBALCACHE true + +#define DECODE_GREE true +#define SEND_GREE true + +#define DECODE_PRONTO false // Not written. +#define SEND_PRONTO true + +#define DECODE_ARGO false // Not written. +#define SEND_ARGO true + +#define DECODE_TROTEC false // Not implemented. +#define SEND_TROTEC true + +#define DECODE_NIKAI true +#define SEND_NIKAI true + +#define DECODE_TOSHIBA_AC true +#define SEND_TOSHIBA_AC true + +#define DECODE_MAGIQUEST true +#define SEND_MAGIQUEST true + +#define DECODE_MIDEA true +#define SEND_MIDEA true + +#define DECODE_LASERTAG true +#define SEND_LASERTAG true + +#define DECODE_CARRIER_AC true +#define SEND_CARRIER_AC true + +#define DECODE_HAIER_AC true +#define SEND_HAIER_AC true + +#define DECODE_HITACHI_AC true +#define SEND_HITACHI_AC true + +#define DECODE_HITACHI_AC1 true +#define SEND_HITACHI_AC1 true + +#define DECODE_HITACHI_AC2 true +#define SEND_HITACHI_AC2 true + +#define DECODE_GICABLE true +#define SEND_GICABLE true + +#define DECODE_HAIER_AC_YRW02 true +#define SEND_HAIER_AC_YRW02 true + +#define DECODE_WHIRLPOOL_AC true +#define SEND_WHIRLPOOL_AC true + +#define DECODE_LUTRON true +#define SEND_LUTRON true + +#define DECODE_ELECTRA_AC true +#define SEND_ELECTRA_AC true + +#define DECODE_PANASONIC_AC true +#define SEND_PANASONIC_AC true + +#define DECODE_MWM true +#define SEND_MWM true + +#define DECODE_PIONEER true +#define SEND_PIONEER true +*/ + +// Tasmota supported protocols (less protocols is less code size) +#define DECODE_HASH true // Semi-unique code for unknown messages + +#define SEND_RAW true + +#define DECODE_NEC true +#define SEND_NEC true + +#define DECODE_SHERWOOD false // Doesn't exist. Actually is DECODE_NEC +#define SEND_SHERWOOD false + +#define DECODE_RC5 true +#define SEND_RC5 true + +#define DECODE_RC6 true +#define SEND_RC6 true + +#define DECODE_RCMM false +#define SEND_RCMM false + +#define DECODE_SONY true +#define SEND_SONY true + +#define DECODE_PANASONIC true +#define SEND_PANASONIC true + +#define DECODE_JVC true +#define SEND_JVC true + +#define DECODE_SAMSUNG true +#define SEND_SAMSUNG true + +#define DECODE_SAMSUNG_AC false +#define SEND_SAMSUNG_AC false + +#define DECODE_WHYNTER false +#define SEND_WHYNTER false + +#define DECODE_AIWA_RC_T501 false +#define SEND_AIWA_RC_T501 false + +#define DECODE_LG true +#define SEND_LG true + +#define DECODE_SANYO false +#define SEND_SANYO false + +#define DECODE_MITSUBISHI false +#define SEND_MITSUBISHI false + +#define DECODE_MITSUBISHI2 false +#define SEND_MITSUBISHI2 false + +#define DECODE_DISH false +#define SEND_DISH true + +#define DECODE_SHARP false +#define SEND_SHARP false + +#define DECODE_DENON false +#define SEND_DENON false + +#define DECODE_KELVINATOR false +#define SEND_KELVINATOR false + +#define DECODE_MITSUBISHI_AC false // Beta. +#define SEND_MITSUBISHI_AC true + +#define DECODE_FUJITSU_AC false +#define SEND_FUJITSU_AC true + +#define DECODE_DAIKIN false +#define SEND_DAIKIN false + +#define DECODE_COOLIX false +#define SEND_COOLIX false + +#define DECODE_GLOBALCACHE false // Not written. +#define SEND_GLOBALCACHE false + +#define DECODE_GREE false +#define SEND_GREE false + +#define DECODE_PRONTO false // Not written. +#define SEND_PRONTO false + +#define DECODE_ARGO false // Not written. +#define SEND_ARGO false + +#define DECODE_TROTEC false // Not implemented. +#define SEND_TROTEC false + +#define DECODE_NIKAI false +#define SEND_NIKAI false + +#define DECODE_TOSHIBA_AC false +#define SEND_TOSHIBA_AC false + +#define DECODE_MAGIQUEST false +#define SEND_MAGIQUEST false + +#define DECODE_MIDEA false +#define SEND_MIDEA false + +#define DECODE_LASERTAG false +#define SEND_LASERTAG false + +#define DECODE_CARRIER_AC false +#define SEND_CARRIER_AC false + +#define DECODE_HAIER_AC false +#define SEND_HAIER_AC false + +#define DECODE_HITACHI_AC false +#define SEND_HITACHI_AC false + +#define DECODE_HITACHI_AC1 false +#define SEND_HITACHI_AC1 false + +#define DECODE_HITACHI_AC2 false +#define SEND_HITACHI_AC2 false + +#define DECODE_GICABLE false +#define SEND_GICABLE false + +#define DECODE_HAIER_AC_YRW02 false +#define SEND_HAIER_AC_YRW02 false + +#define DECODE_WHIRLPOOL_AC false +#define SEND_WHIRLPOOL_AC false + +#define DECODE_LUTRON false +#define SEND_LUTRON false + +#define DECODE_ELECTRA_AC false +#define SEND_ELECTRA_AC false + +#define DECODE_PANASONIC_AC false +#define SEND_PANASONIC_AC false + +#define DECODE_MWM false +#define SEND_MWM false + +#define DECODE_PIONEER false +#define SEND_PIONEER false + +#if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \ + DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \ + DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \ + DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2 || DECODE_HAIER_AC_YRW02 || \ + DECODE_WHIRLPOOL_AC || DECODE_SAMSUNG_AC || DECODE_ELECTRA_AC || \ + DECODE_PANASONIC_AC || DECODE_MWM) +#define DECODE_AC true // We need some common infrastructure for decoding A/Cs. +#else +#define DECODE_AC false // We don't need that infrastructure. +#endif + +// Use millisecond 'delay()' calls where we can to avoid tripping the WDT. +// Note: If you plan to send IR messages in the callbacks of the AsyncWebserver +// library, you need to set ALLOW_DELAY_CALLS to false. +// Ref: https://github.com/markszabo/IRremoteESP8266/issues/430 +#define ALLOW_DELAY_CALLS true + +/* + * Always add to the end of the list and should never remove entries + * or change order. Projects may save the type number for later usage + * so numbering should always stay the same. + */ +enum decode_type_t { + UNKNOWN = -1, + UNUSED = 0, + RC5, + RC6, + NEC, + SONY, + PANASONIC, + JVC, + SAMSUNG, + WHYNTER, + AIWA_RC_T501, + LG, + SANYO, + MITSUBISHI, + DISH, + SHARP, + COOLIX, + DAIKIN, + DENON, + KELVINATOR, + SHERWOOD, + MITSUBISHI_AC, + RCMM, + SANYO_LC7461, + RC5X, + GREE, + PRONTO, // Technically not a protocol, but an encoding. + NEC_LIKE, + ARGO, + TROTEC, + NIKAI, + RAW, // Technically not a protocol, but an encoding. + GLOBALCACHE, // Technically not a protocol, but an encoding. + TOSHIBA_AC, + FUJITSU_AC, + MIDEA, + MAGIQUEST, + LASERTAG, + CARRIER_AC, + HAIER_AC, + MITSUBISHI2, + HITACHI_AC, + HITACHI_AC1, + HITACHI_AC2, + GICABLE, + HAIER_AC_YRW02, + WHIRLPOOL_AC, + SAMSUNG_AC, + LUTRON, + ELECTRA_AC, + PANASONIC_AC, + PIONEER, + LG2, + MWM, +}; + +// Message lengths & required repeat values +const uint16_t kNoRepeat = 0; +const uint16_t kSingleRepeat = 1; + +const uint16_t kAiwaRcT501Bits = 15; +const uint16_t kAiwaRcT501MinRepeats = kSingleRepeat; +const uint16_t kArgoStateLength = 12; +const uint16_t kCoolixBits = 24; +const uint16_t kCarrierAcBits = 32; +const uint16_t kCarrierAcMinRepeat = kNoRepeat; +// Daikin has a lot of static stuff that is discarded +const uint16_t kDaikinRawBits = 583; +const uint16_t kDaikinStateLength = 27; +const uint16_t kDaikinBits = kDaikinStateLength * 8; +const uint16_t kDenonBits = 15; +const uint16_t kDenonLegacyBits = 14; +const uint16_t kDishBits = 16; +const uint16_t kDishMinRepeat = 3; +const uint16_t kElectraAcStateLength = 13; +const uint16_t kElectraAcBits = kElectraAcStateLength * 8; +const uint16_t kFujitsuAcMinRepeat = kNoRepeat; +const uint16_t kFujitsuAcStateLength = 16; +const uint16_t kFujitsuAcStateLengthShort = 7; +const uint16_t kFujitsuAcBits = kFujitsuAcStateLength * 8; +const uint16_t kFujitsuAcMinBits = (kFujitsuAcStateLengthShort - 1) * 8; +const uint16_t kGicableBits = 16; +const uint16_t kGicableMinRepeat = kSingleRepeat; +const uint16_t kGreeStateLength = 8; +const uint16_t kGreeBits = kGreeStateLength * 8; +const uint16_t kHaierACStateLength = 9; +const uint16_t kHaierACBits = kHaierACStateLength * 8; +const uint16_t kHaierACYRW02StateLength = 14; +const uint16_t kHaierACYRW02Bits = kHaierACYRW02StateLength * 8; +const uint16_t kHitachiAcStateLength = 28; +const uint16_t kHitachiAcBits = kHitachiAcStateLength * 8; +const uint16_t kHitachiAc1StateLength = 13; +const uint16_t kHitachiAc1Bits = kHitachiAc1StateLength * 8; +const uint16_t kHitachiAc2StateLength = 53; +const uint16_t kHitachiAc2Bits = kHitachiAc2StateLength * 8; +const uint16_t kJvcBits = 16; +const uint16_t kKelvinatorStateLength = 16; +const uint16_t kKelvinatorBits = kKelvinatorStateLength * 8; +const uint16_t kLasertagBits = 13; +const uint16_t kLasertagMinRepeat = kNoRepeat; +const uint16_t kLgBits = 28; +const uint16_t kLg32Bits = 32; +const uint16_t kLutronBits = 35; +const uint16_t kMagiquestBits = 56; +const uint16_t kMideaBits = 48; +const uint16_t kMideaMinRepeat = kNoRepeat; +const uint16_t kMitsubishiBits = 16; +// TODO(anyone): Verify that the Mitsubishi repeat is really needed. +// Based on marcosamarinho's code. +const uint16_t kMitsubishiMinRepeat = kSingleRepeat; +const uint16_t kMitsubishiACStateLength = 18; +const uint16_t kMitsubishiACBits = kMitsubishiACStateLength * 8; +const uint16_t kMitsubishiACMinRepeat = kSingleRepeat; +const uint16_t kNikaiBits = 24; +const uint16_t kNECBits = 32; +const uint16_t kPanasonicBits = 48; +const uint32_t kPanasonicManufacturer = 0x4004; +const uint16_t kPanasonicAcStateLength = 27; +const uint16_t kPanasonicAcStateShortLength = 16; +const uint16_t kPanasonicAcBits = kPanasonicAcStateLength * 8; +const uint16_t kPanasonicAcShortBits = kPanasonicAcStateShortLength * 8; +const uint16_t kPioneerBits = 64; +const uint16_t kProntoMinLength = 6; +const uint16_t kRC5RawBits = 14; +const uint16_t kRC5Bits = kRC5RawBits - 2; +const uint16_t kRC5XBits = kRC5RawBits - 1; +const uint16_t kRC6Mode0Bits = 20; // Excludes the 'start' bit. +const uint16_t kRC6_36Bits = 36; // Excludes the 'start' bit. +const uint16_t kRCMMBits = 24; +const uint16_t kSamsungBits = 32; +const uint16_t kSamsungAcStateLength = 14; +const uint16_t kSamsungAcBits = kSamsungAcStateLength * 8; +const uint16_t kSamsungAcExtendedStateLength = 21; +const uint16_t kSamsungAcExtendedBits = kSamsungAcExtendedStateLength * 8; +const uint16_t kSanyoSA8650BBits = 12; +const uint16_t kSanyoLC7461AddressBits = 13; +const uint16_t kSanyoLC7461CommandBits = 8; +const uint16_t kSanyoLC7461Bits = (kSanyoLC7461AddressBits + + kSanyoLC7461CommandBits) * 2; +const uint8_t kSharpAddressBits = 5; +const uint8_t kSharpCommandBits = 8; +const uint16_t kSharpBits = kSharpAddressBits + kSharpCommandBits + 2; // 15 +const uint8_t kSherwoodBits = kNECBits; +const uint16_t kSherwoodMinRepeat = kSingleRepeat; +const uint16_t kSony12Bits = 12; +const uint16_t kSony15Bits = 15; +const uint16_t kSony20Bits = 20; +const uint16_t kSonyMinBits = 12; +const uint16_t kSonyMinRepeat = 2; +const uint16_t kToshibaACStateLength = 9; +const uint16_t kToshibaACBits = kToshibaACStateLength * 8; +const uint16_t kToshibaACMinRepeat = kSingleRepeat; +const uint16_t kTrotecStateLength = 9; +const uint16_t kWhirlpoolAcStateLength = 21; +const uint16_t kWhirlpoolAcBits = kWhirlpoolAcStateLength * 8; +const uint16_t kWhynterBits = 32; + +// Legacy defines. (Deprecated) +#define AIWA_RC_T501_BITS kAiwaRcT501Bits +#define ARGO_COMMAND_LENGTH kArgoStateLength +#define COOLIX_BITS kCoolixBits +#define CARRIER_AC_BITS kCarrierAcBits +#define DAIKIN_COMMAND_LENGTH kDaikinStateLength +#define DENON_BITS kDenonBits +#define DENON_48_BITS kPanasonicBits +#define DENON_LEGACY_BITS kDenonLegacyBits +#define DISH_BITS kDishBits +#define FUJITSU_AC_MIN_REPEAT kFujitsuAcMinRepeat +#define FUJITSU_AC_STATE_LENGTH kFujitsuAcStateLength +#define FUJITSU_AC_STATE_LENGTH_SHORT kFujitsuAcStateLengthShort +#define FUJITSU_AC_BITS kFujitsuAcBits +#define FUJITSU_AC_MIN_BITS kFujitsuAcMinBits +#define GICABLE_BITS kGicableBits +#define GREE_STATE_LENGTH kGreeStateLength +#define HAIER_AC_STATE_LENGTH kHaierACStateLength +#define HAIER_AC_YRW02_STATE_LENGTH kHaierACYRW02StateLength +#define HITACHI_AC_STATE_LENGTH kHitachiAcStateLength +#define HITACHI_AC_BITS kHitachiAcBits +#define HITACHI_AC1_STATE_LENGTH kHitachiAc1StateLength +#define HITACHI_AC1_BITS kHitachiAc1Bits +#define HITACHI_AC2_STATE_LENGTH kHitachiAc2StateLength +#define HITACHI_AC2_BITS kHitachiAc2Bits +#define JVC_BITS kJvcBits +#define KELVINATOR_STATE_LENGTH kKelvinatorStateLength +#define LASERTAG_BITS kLasertagBits +#define LG_BITS kLgBits +#define LG32_BITS kLg32Bits +#define MAGIQUEST_BITS kMagiquestBits +#define MIDEA_BITS kMideaBits +#define MITSUBISHI_BITS kMitsubishiBits +#define MITSUBISHI_AC_STATE_LENGTH kMitsubishiACStateLength +#define NEC_BITS kNECBits +#define NIKAI_BITS kNikaiBits +#define PANASONIC_BITS kPanasonicBits +#define RC5_BITS kRC5Bits +#define RC5X_BITS kRC5XBits +#define RC6_MODE0_BITS kRC6Mode0Bits +#define RC6_36_BITS kRC6_36Bits +#define RCMM_BITS kRCMMBits +#define SANYO_LC7461_BITS kSanyoLC7461Bits +#define SAMSUNG_BITS kSamsungBits +#define SANYO_SA8650B_BITS kSanyoSA8650BBits +#define SHARP_BITS kSharpBits +#define SHERWOOD_BITS kSherwoodBits +#define SONY_12_BITS kSony12Bits +#define SONY_15_BITS kSony15Bits +#define SONY_20_BITS kSony20Bits +#define TOSHIBA_AC_STATE_LENGTH kToshibaACStateLength +#define TROTEC_COMMAND_LENGTH kTrotecStateLength +#define WHYNTER_BITS kWhynterBits + +// Turn on Debugging information by uncommenting the following line. +// #define DEBUG 1 + +#ifdef DEBUG +#ifdef UNIT_TEST +#define DPRINT(x) do { std::cout << x; } while (0) +#define DPRINTLN(x) do { std::cout << x << std::endl; } while (0) +#endif // UNIT_TEST +#ifdef ARDUINO +#define DPRINT(x) do { Serial.print(x); } while (0) +#define DPRINTLN(x) do { Serial.println(x); } while (0) +#endif // ARDUINO +#else // DEBUG +#define DPRINT(x) +#define DPRINTLN(x) +#endif // DEBUG + +#endif // IRREMOTEESP8266_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp b/lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp new file mode 100644 index 000000000..96f95172d --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp @@ -0,0 +1,601 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2015 Mark Szabo +// Copyright 2017 David Conran + +#include "IRsend.h" +#ifndef UNIT_TEST +#include +#else +#define __STDC_LIMIT_MACROS +#include +#endif +#include +#ifdef UNIT_TEST +#include +#endif +#include "IRtimer.h" + +// Originally from https://github.com/shirriff/Arduino-IRremote/ +// Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for +// sending IR code on ESP8266 + +// IRsend ---------------------------------------------------------------------- +// Create an IRsend object. +// +// Args: +// IRsendPin: Which GPIO pin to use when sending an IR command. +// inverted: *DANGER* Optional flag to invert the output. (default = false) +// e.g. LED is illuminated when GPIO is LOW rather than HIGH. +// Setting this to something other than the default could +// easily destroy your IR LED if you are overdriving it. +// Unless you *REALLY* know what you are doing, don't change this. +// use_modulation: Do we do frequency modulation during transmission? +// i.e. If not, assume a 100% duty cycle. Ignore attempts +// to change the duty cycle etc. +// Returns: +// An IRsend object. +IRsend::IRsend(uint16_t IRsendPin, bool inverted, bool use_modulation) + : IRpin(IRsendPin), periodOffset(kPeriodOffset) { + if (inverted) { + outputOn = LOW; + outputOff = HIGH; + } else { + outputOn = HIGH; + outputOff = LOW; + } + modulation = use_modulation; + if (modulation) + _dutycycle = kDutyDefault; + else + _dutycycle = kDutyMax; +} + +// Enable the pin for output. +void IRsend::begin() { +#ifndef UNIT_TEST + pinMode(IRpin, OUTPUT); +#endif + ledOff(); // Ensure the LED is in a known safe state when we start. +} + +// Turn off the IR LED. +void IRsend::ledOff() { +#ifndef UNIT_TEST + digitalWrite(IRpin, outputOff); +#endif +} + +// Turn on the IR LED. +void IRsend::ledOn() { +#ifndef UNIT_TEST + digitalWrite(IRpin, outputOn); +#endif +} + +// Calculate the period for a given frequency. (T = 1/f) +// +// Args: +// freq: Frequency in Hz. +// use_offset: Should we use the calculated offset or not? +// Returns: +// nr. of uSeconds. +uint32_t IRsend::calcUSecPeriod(uint32_t hz, bool use_offset) { + if (hz == 0) hz = 1; // Avoid Zero hz. Divide by Zero is nasty. + uint32_t period = + (1000000UL + hz / 2) / hz; // The equiv of round(1000000/hz). + // Apply the offset and ensure we don't result in a <= 0 value. + if (use_offset) + return std::max((uint32_t)1, period + periodOffset); + else + return std::max((uint32_t)1, period); +} + +// Set the output frequency modulation and duty cycle. +// +// Args: +// freq: The freq we want to modulate at. Assumes < 1000 means kHz else Hz. +// duty: Percentage duty cycle of the LED. e.g. 25 = 25% = 1/4 on, 3/4 off. +// This is ignored if modulation is disabled at object instantiation. +// +// Note: +// Integer timing functions & math mean we can't do fractions of +// microseconds timing. Thus minor changes to the freq & duty values may have +// limited effect. You've been warned. +void IRsend::enableIROut(uint32_t freq, uint8_t duty) { + // Set the duty cycle to use if we want freq. modulation. + if (modulation) { + _dutycycle = std::min(duty, kDutyMax); + } else { + _dutycycle = kDutyMax; + } + if (freq < 1000) // Were we given kHz? Supports the old call usage. + freq *= 1000; + uint32_t period = calcUSecPeriod(freq); + // Nr. of uSeconds the LED will be on per pulse. + onTimePeriod = (period * _dutycycle) / kDutyMax; + // Nr. of uSeconds the LED will be off per pulse. + offTimePeriod = period - onTimePeriod; +} + +#if ALLOW_DELAY_CALLS +// An ESP8266 RTOS watch-dog timer friendly version of delayMicroseconds(). +// Args: +// usec: Nr. of uSeconds to delay for. +void IRsend::_delayMicroseconds(uint32_t usec) { + // delayMicroseconds() is only accurate to 16383us. + // Ref: https://www.arduino.cc/en/Reference/delayMicroseconds + if (usec <= kMaxAccurateUsecDelay) { +#ifndef UNIT_TEST + delayMicroseconds(usec); +#endif + } else { +#ifndef UNIT_TEST + // Invoke a delay(), where possible, to avoid triggering the WDT. + delay(usec / 1000UL); // Delay for as many whole milliseconds as we can. + // Delay the remaining sub-millisecond. + delayMicroseconds(static_cast(usec % 1000UL)); +#endif + } +} +#else // ALLOW_DELAY_CALLS +// A version of delayMicroseconds() that handles large values and does NOT use +// the watch-dog friendly delay() calls where appropriate. +// Args: +// usec: Nr. of uSeconds to delay for. +// +// NOTE: Use this only if you know what you are doing as it may cause the WDT +// to reset the ESP8266. +void IRsend::_delayMicroseconds(uint32_t usec) { + for (; usec > kMaxAccurateUsecDelay; usec -= kMaxAccurateUsecDelay) +#ifndef UNIT_TEST + delayMicroseconds(kMaxAccurateUsecDelay); + delayMicroseconds(static_cast(usec)); +#endif // UNIT_TEST +} +#endif // ALLOW_DELAY_CALLS + +// Modulate the IR LED for the given period (usec) and at the duty cycle set. +// +// Args: +// usec: The period of time to modulate the IR LED for, in microseconds. +// Returns: +// Nr. of pulses actually sent. +// +// Note: +// The ESP8266 has no good way to do hardware PWM, so we have to do it all +// in software. There is a horrible kludge/brilliant hack to use the second +// serial TX line to do fairly accurate hardware PWM, but it is only +// available on a single specific GPIO and only available on some modules. +// e.g. It's not available on the ESP-01 module. +// Hence, for greater compatibility & choice, we don't use that method. +// Ref: +// https://www.analysir.com/blog/2017/01/29/updated-esp8266-nodemcu-backdoor-upwm-hack-for-ir-signals/ +uint16_t IRsend::mark(uint16_t usec) { + // Handle the simple case of no required frequency modulation. + if (!modulation || _dutycycle >= 100) { + ledOn(); + _delayMicroseconds(usec); + ledOff(); + return 1; + } + + // Not simple, so do it assuming frequency modulation. + uint16_t counter = 0; + IRtimer usecTimer = IRtimer(); + // Cache the time taken so far. This saves us calling time, and we can be + // assured that we can't have odd math problems. i.e. unsigned under/overflow. + uint32_t elapsed = usecTimer.elapsed(); + + while (elapsed < usec) { // Loop until we've met/exceeded our required time. + ledOn(); + // Calculate how long we should pulse on for. + // e.g. Are we to close to the end of our requested mark time (usec)? + _delayMicroseconds(std::min((uint32_t)onTimePeriod, usec - elapsed)); + ledOff(); + counter++; + if (elapsed + onTimePeriod >= usec) + return counter; // LED is now off & we've passed our allotted time. + // Wait for the lesser of the rest of the duty cycle, or the time remaining. + _delayMicroseconds( + std::min(usec - elapsed - onTimePeriod, (uint32_t)offTimePeriod)); + elapsed = usecTimer.elapsed(); // Update & recache the actual elapsed time. + } + return counter; +} + +// Turn the pin (LED) off for a given time. +// Sends an IR space for the specified number of microseconds. +// A space is no output, so the PWM output is disabled. +// +// Args: +// time: Time in microseconds (us). +void IRsend::space(uint32_t time) { + ledOff(); + if (time == 0) return; + _delayMicroseconds(time); +} + +// Calculate & set any offsets to account for execution times. +// +// Args: +// hz: The frequency to calibrate at >= 1000Hz. Default is 38000Hz. +// +// Returns: +// The calculated period offset (in uSeconds) which is now in use. e.g. -5. +// +// Status: Stable / Working. +// +// NOTE: +// This will generate an 65535us mark() IR LED signal. +// This only needs to be called once, if at all. +int8_t IRsend::calibrate(uint16_t hz) { + if (hz < 1000) // Were we given kHz? Supports the old call usage. + hz *= 1000; + periodOffset = 0; // Turn off any existing offset while we calibrate. + enableIROut(hz); + IRtimer usecTimer = IRtimer(); // Start a timer *just* before we do the call. + uint16_t pulses = mark(UINT16_MAX); // Generate a PWM of 65,535 us. (Max.) + uint32_t timeTaken = usecTimer.elapsed(); // Record the time it took. + // While it shouldn't be necessary, assume at least 1 pulse, to avoid a + // divide by 0 situation. + pulses = std::max(pulses, (uint16_t)1U); + uint32_t calcPeriod = calcUSecPeriod(hz); // e.g. @38kHz it should be 26us. + // Assuming 38kHz for the example calculations: + // In a 65535us pulse, we should have 2520.5769 pulses @ 26us periods. + // e.g. 65535.0us / 26us = 2520.5769 + // This should have caused approx 2520 loops through the main loop in mark(). + // The average over that many interations should give us a reasonable + // approximation at what offset we need to use to account for instruction + // execution times. + // + // Calculate the actual period from the actual time & the actual pulses + // generated. + double_t actualPeriod = (double_t)timeTaken / (double_t)pulses; + // Store the difference between the actual time per period vs. calculated. + periodOffset = (int8_t)((double_t)calcPeriod - actualPeriod); + return periodOffset; +} + +// Generic method for sending data that is common to most protocols. +// Will send leading or trailing 0's if the nbits is larger than the number +// of bits in data. +// +// Args: +// onemark: Nr. of usecs for the led to be pulsed for a '1' bit. +// onespace: Nr. of usecs for the led to be fully off for a '1' bit. +// zeromark: Nr. of usecs for the led to be pulsed for a '0' bit. +// zerospace: Nr. of usecs for the led to be fully off for a '0' bit. +// data: The data to be transmitted. +// nbits: Nr. of bits of data to be sent. +// MSBfirst: Flag for bit transmission order. Defaults to MSB->LSB order. +void IRsend::sendData(uint16_t onemark, uint32_t onespace, uint16_t zeromark, + uint32_t zerospace, uint64_t data, uint16_t nbits, + bool MSBfirst) { + if (nbits == 0) // If we are asked to send nothing, just return. + return; + if (MSBfirst) { // Send the MSB first. + // Send 0's until we get down to a bit size we can actually manage. + while (nbits > sizeof(data) * 8) { + mark(zeromark); + space(zerospace); + nbits--; + } + // Send the supplied data. + for (uint64_t mask = 1ULL << (nbits - 1); mask; mask >>= 1) + if (data & mask) { // Send a 1 + mark(onemark); + space(onespace); + } else { // Send a 0 + mark(zeromark); + space(zerospace); + } + } else { // Send the Least Significant Bit (LSB) first / MSB last. + for (uint16_t bit = 0; bit < nbits; bit++, data >>= 1) + if (data & 1) { // Send a 1 + mark(onemark); + space(onespace); + } else { // Send a 0 + mark(zeromark); + space(zerospace); + } + } +} + +// Generic method for sending simple protocol messages. +// Will send leading or trailing 0's if the nbits is larger than the number +// of bits in data. +// +// Args: +// headermark: Nr. of usecs for the led to be pulsed for the header mark. +// A value of 0 means no header mark. +// headerspace: Nr. of usecs for the led to be off after the header mark. +// A value of 0 means no header space. +// onemark: Nr. of usecs for the led to be pulsed for a '1' bit. +// onespace: Nr. of usecs for the led to be fully off for a '1' bit. +// zeromark: Nr. of usecs for the led to be pulsed for a '0' bit. +// zerospace: Nr. of usecs for the led to be fully off for a '0' bit. +// footermark: Nr. of usecs for the led to be pulsed for the footer mark. +// A value of 0 means no footer mark. +// gap: Nr. of usecs for the led to be off after the footer mark. +// This is effectively the gap between messages. +// A value of 0 means no gap space. +// data: The data to be transmitted. +// nbits: Nr. of bits of data to be sent. +// frequency: The frequency we want to modulate at. +// Assumes < 1000 means kHz otherwise it is in Hz. +// Most common value is 38000 or 38, for 38kHz. +// MSBfirst: Flag for bit transmission order. Defaults to MSB->LSB order. +// repeat: Nr. of extra times the message will be sent. +// e.g. 0 = 1 message sent, 1 = 1 initial + 1 repeat = 2 messages +// dutycycle: Percentage duty cycle of the LED. +// e.g. 25 = 25% = 1/4 on, 3/4 off. +// If you are not sure, try 50 percent. +void IRsend::sendGeneric(const uint16_t headermark, const uint32_t headerspace, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint16_t footermark, const uint32_t gap, + const uint64_t data, const uint16_t nbits, + const uint16_t frequency, const bool MSBfirst, + const uint16_t repeat, const uint8_t dutycycle) { + sendGeneric(headermark, headerspace, onemark, onespace, zeromark, zerospace, + footermark, gap, 0U, data, nbits, frequency, MSBfirst, repeat, + dutycycle); +} + +// Generic method for sending simple protocol messages. +// Will send leading or trailing 0's if the nbits is larger than the number +// of bits in data. +// +// Args: +// headermark: Nr. of usecs for the led to be pulsed for the header mark. +// A value of 0 means no header mark. +// headerspace: Nr. of usecs for the led to be off after the header mark. +// A value of 0 means no header space. +// onemark: Nr. of usecs for the led to be pulsed for a '1' bit. +// onespace: Nr. of usecs for the led to be fully off for a '1' bit. +// zeromark: Nr. of usecs for the led to be pulsed for a '0' bit. +// zerospace: Nr. of usecs for the led to be fully off for a '0' bit. +// footermark: Nr. of usecs for the led to be pulsed for the footer mark. +// A value of 0 means no footer mark. +// gap: Min. nr. of usecs for the led to be off after the footer mark. +// This is effectively the absolute minimum gap between messages. +// mesgtime: Min. nr. of usecs a single message needs to be. +// This is effectively the min. total length of a single message. +// data: The data to be transmitted. +// nbits: Nr. of bits of data to be sent. +// frequency: The frequency we want to modulate at. +// Assumes < 1000 means kHz otherwise it is in Hz. +// Most common value is 38000 or 38, for 38kHz. +// MSBfirst: Flag for bit transmission order. Defaults to MSB->LSB order. +// repeat: Nr. of extra times the message will be sent. +// e.g. 0 = 1 message sent, 1 = 1 initial + 1 repeat = 2 messages +// dutycycle: Percentage duty cycle of the LED. +// e.g. 25 = 25% = 1/4 on, 3/4 off. +// If you are not sure, try 50 percent. +void IRsend::sendGeneric(const uint16_t headermark, const uint32_t headerspace, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint16_t footermark, const uint32_t gap, + const uint32_t mesgtime, const uint64_t data, + const uint16_t nbits, const uint16_t frequency, + const bool MSBfirst, const uint16_t repeat, + const uint8_t dutycycle) { + // Setup + enableIROut(frequency, dutycycle); + IRtimer usecs = IRtimer(); + + // We always send a message, even for repeat=0, hence '<= repeat'. + for (uint16_t r = 0; r <= repeat; r++) { + usecs.reset(); + + // Header + if (headermark) mark(headermark); + if (headerspace) space(headerspace); + + // Data + sendData(onemark, onespace, zeromark, zerospace, data, nbits, MSBfirst); + + // Footer + if (footermark) mark(footermark); + uint32_t elapsed = usecs.elapsed(); + // Avoid potential unsigned integer underflow. e.g. when mesgtime is 0. + if (elapsed >= mesgtime) + space(gap); + else + space(std::max(gap, mesgtime - elapsed)); + } +} + +// Generic method for sending simple protocol messages. +// +// Args: +// headermark: Nr. of usecs for the led to be pulsed for the header mark. +// A value of 0 means no header mark. +// headerspace: Nr. of usecs for the led to be off after the header mark. +// A value of 0 means no header space. +// onemark: Nr. of usecs for the led to be pulsed for a '1' bit. +// onespace: Nr. of usecs for the led to be fully off for a '1' bit. +// zeromark: Nr. of usecs for the led to be pulsed for a '0' bit. +// zerospace: Nr. of usecs for the led to be fully off for a '0' bit. +// footermark: Nr. of usecs for the led to be pulsed for the footer mark. +// A value of 0 means no footer mark. +// gap: Nr. of usecs for the led to be off after the footer mark. +// This is effectively the gap between messages. +// A value of 0 means no gap space. +// dataptr: Pointer to the data to be transmitted. +// nbytes: Nr. of bytes of data to be sent. +// frequency: The frequency we want to modulate at. +// Assumes < 1000 means kHz otherwise it is in Hz. +// Most common value is 38000 or 38, for 38kHz. +// MSBfirst: Flag for bit transmission order. Defaults to MSB->LSB order. +// repeat: Nr. of extra times the message will be sent. +// e.g. 0 = 1 message sent, 1 = 1 initial + 1 repeat = 2 messages +// dutycycle: Percentage duty cycle of the LED. +// e.g. 25 = 25% = 1/4 on, 3/4 off. +// If you are not sure, try 50 percent. +void IRsend::sendGeneric(const uint16_t headermark, const uint32_t headerspace, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint16_t footermark, const uint32_t gap, + const uint8_t *dataptr, const uint16_t nbytes, + const uint16_t frequency, const bool MSBfirst, + const uint16_t repeat, const uint8_t dutycycle) { + // Setup + enableIROut(frequency, dutycycle); + // We always send a message, even for repeat=0, hence '<= repeat'. + for (uint16_t r = 0; r <= repeat; r++) { + // Header + if (headermark) mark(headermark); + if (headerspace) space(headerspace); + + // Data + for (uint16_t i = 0; i < nbytes; i++) + sendData(onemark, onespace, zeromark, zerospace, *(dataptr + i), 8, + MSBfirst); + + // Footer + if (footermark) mark(footermark); + space(gap); + } +} + +#if SEND_RAW +// Send a raw IRremote message. +// +// Args: +// buf: An array of uint16_t's that has microseconds elements. +// len: Nr. of elements in the buf[] array. +// hz: Frequency to send the message at. (kHz < 1000; Hz >= 1000) +// +// Status: STABLE / Known working. +// +// Notes: +// Even elements are Mark times (On), Odd elements are Space times (Off). +// +// Ref: +// examples/IRrecvDumpV2/IRrecvDumpV2.ino +void IRsend::sendRaw(uint16_t buf[], uint16_t len, uint16_t hz) { + // Set IR carrier frequency + enableIROut(hz); + for (uint16_t i = 0; i < len; i++) { + if (i & 1) { // Odd bit. + space(buf[i]); + } else { // Even bit. + mark(buf[i]); + } + } + ledOff(); // We potentially have ended with a mark(), so turn of the LED. +} +#endif // SEND_RAW + +#ifndef UNIT_TEST +void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) { + switch (type) { +#if SEND_NEC + case NEC: + sendNEC(data, nbits); + break; +#endif +#if SEND_SONY + case SONY: + sendSony(data, nbits); + break; +#endif +#if SEND_RC5 + case RC5: + sendRC5(data, nbits); + break; +#endif +#if SEND_RC6 + case RC6: + sendRC6(data, nbits); + break; +#endif +#if SEND_DISH + case DISH: + sendDISH(data, nbits); + break; +#endif +#if SEND_JVC + case JVC: + sendJVC(data, nbits); + break; +#endif +#if SEND_SAMSUNG + case SAMSUNG: + sendSAMSUNG(data, nbits); + break; +#endif +#if SEND_LG + case LG: + sendLG(data, nbits); + break; +#endif +#if SEND_LG + case LG2: + sendLG2(data, nbits); + break; +#endif +#if SEND_WHYNTER + case WHYNTER: + sendWhynter(data, nbits); + break; +#endif +#if SEND_COOLIX + case COOLIX: + sendCOOLIX(data, nbits); + break; +#endif +#if SEND_DENON + case DENON: + sendDenon(data, nbits); + break; +#endif +#if SEND_SHERWOOD + case SHERWOOD: + sendSherwood(data, nbits); + break; +#endif +#if SEND_RCMM + case RCMM: + sendRCMM(data, nbits); + break; +#endif +#if SEND_MITSUBISHI + case MITSUBISHI: + sendMitsubishi(data, nbits); + break; +#endif +#if SEND_MITSUBISHI2 + case MITSUBISHI2: + sendMitsubishi2(data, nbits); + break; +#endif +#if SEND_SHARP + case SHARP: + sendSharpRaw(data, nbits); + break; +#endif +#if SEND_AIWA_RC_T501 + case AIWA_RC_T501: + sendAiwaRCT501(data, nbits); + break; +#endif +#if SEND_MIDEA + case MIDEA: + sendMidea(data, nbits); + break; +#endif +#if SEND_GICABLE + case GICABLE: + sendGICable(data, nbits); + break; +#endif +#if SEND_PIONEER + case PIONEER: + sendPioneer(data, nbits); + break; +#endif + } +} +#endif diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRsend.h b/lib/IRremoteESP8266-2.5.2.03/src/IRsend.h new file mode 100644 index 000000000..8e2dc248e --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRsend.h @@ -0,0 +1,333 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2015 Mark Szabo +// Copyright 2017 David Conran +#ifndef IRSEND_H_ +#define IRSEND_H_ + +#define __STDC_LIMIT_MACROS +#include +#include "IRremoteESP8266.h" + +// Originally from https://github.com/shirriff/Arduino-IRremote/ +// Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for +// sending IR code on ESP8266 + +#if TEST || UNIT_TEST +#define VIRTUAL virtual +#else +#define VIRTUAL +#endif + +// Constants +// Offset (in microseconds) to use in Period time calculations to account for +// code excution time in producing the software PWM signal. +// Value was calculated on Wemos D1 mini using v2.4.1 with v2.4.0 ESP core +const int8_t kPeriodOffset = -5; +const uint8_t kDutyDefault = 50; // Percentage +const uint8_t kDutyMax = 100; // Percentage +// delayMicroseconds() is only accurate to 16383us. +// Ref: https://www.arduino.cc/en/Reference/delayMicroseconds +const uint16_t kMaxAccurateUsecDelay = 16383; + +// Classes +class IRsend { + public: + explicit IRsend(uint16_t IRsendPin, bool inverted = false, + bool use_modulation = true); + void begin(); + void enableIROut(uint32_t freq, uint8_t duty = kDutyDefault); + VIRTUAL void _delayMicroseconds(uint32_t usec); + VIRTUAL uint16_t mark(uint16_t usec); + VIRTUAL void space(uint32_t usec); + int8_t calibrate(uint16_t hz = 38000U); + void sendRaw(uint16_t buf[], uint16_t len, uint16_t hz); + void sendData(uint16_t onemark, uint32_t onespace, uint16_t zeromark, + uint32_t zerospace, uint64_t data, uint16_t nbits, + bool MSBfirst = true); + void sendGeneric(const uint16_t headermark, const uint32_t headerspace, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint16_t footermark, const uint32_t gap, + const uint64_t data, const uint16_t nbits, + const uint16_t frequency, const bool MSBfirst, + const uint16_t repeat, const uint8_t dutycycle); + void sendGeneric(const uint16_t headermark, const uint32_t headerspace, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint16_t footermark, const uint32_t gap, + const uint32_t mesgtime, const uint64_t data, + const uint16_t nbits, const uint16_t frequency, + const bool MSBfirst, const uint16_t repeat, + const uint8_t dutycycle); + void sendGeneric(const uint16_t headermark, const uint32_t headerspace, + const uint16_t onemark, const uint32_t onespace, + const uint16_t zeromark, const uint32_t zerospace, + const uint16_t footermark, const uint32_t gap, + const uint8_t *dataptr, const uint16_t nbytes, + const uint16_t frequency, const bool MSBfirst, + const uint16_t repeat, const uint8_t dutycycle); + void send(uint16_t type, uint64_t data, uint16_t nbits); +#if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO) + void sendNEC(uint64_t data, uint16_t nbits = kNECBits, + uint16_t repeat = kNoRepeat); + uint32_t encodeNEC(uint16_t address, uint16_t command); +#endif +#if SEND_SONY + // sendSony() should typically be called with repeat=2 as Sony devices + // expect the code to be sent at least 3 times. (code + 2 repeats = 3 codes) + // Legacy use of this procedure was to only send a single code so call it with + // repeat=0 for backward compatibility. As of v2.0 it defaults to sending + // a Sony command that will be accepted be a device. + void sendSony(uint64_t data, uint16_t nbits = kSony20Bits, + uint16_t repeat = kSonyMinRepeat); + uint32_t encodeSony(uint16_t nbits, uint16_t command, uint16_t address, + uint16_t extended = 0); +#endif +#if SEND_SHERWOOD + void sendSherwood(uint64_t data, uint16_t nbits = kSherwoodBits, + uint16_t repeat = kSherwoodMinRepeat); +#endif +#if SEND_SAMSUNG + void sendSAMSUNG(uint64_t data, uint16_t nbits = kSamsungBits, + uint16_t repeat = kNoRepeat); + uint32_t encodeSAMSUNG(uint8_t customer, uint8_t command); +#endif +#if SEND_SAMSUNG_AC + void sendSamsungAC(unsigned char data[], + uint16_t nbytes = kSamsungAcStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_LG + void sendLG(uint64_t data, uint16_t nbits = kLgBits, + uint16_t repeat = kNoRepeat); + void sendLG2(uint64_t data, uint16_t nbits = kLgBits, + uint16_t repeat = kNoRepeat); + uint32_t encodeLG(uint16_t address, uint16_t command); +#endif +#if (SEND_SHARP || SEND_DENON) + uint32_t encodeSharp(uint16_t address, uint16_t command, + uint16_t expansion = 1, uint16_t check = 0, + bool MSBfirst = false); + void sendSharp(uint16_t address, uint16_t command, + uint16_t nbits = kSharpBits, uint16_t repeat = kNoRepeat); + void sendSharpRaw(uint64_t data, uint16_t nbits = kSharpBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_JVC + void sendJVC(uint64_t data, uint16_t nbits = kJvcBits, + uint16_t repeat = kNoRepeat); + uint16_t encodeJVC(uint8_t address, uint8_t command); +#endif +#if SEND_DENON + void sendDenon(uint64_t data, uint16_t nbits = DENON_BITS, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_SANYO + uint64_t encodeSanyoLC7461(uint16_t address, uint8_t command); + void sendSanyoLC7461(uint64_t data, uint16_t nbits = kSanyoLC7461Bits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_DISH + // sendDISH() should typically be called with repeat=3 as DISH devices + // expect the code to be sent at least 4 times. (code + 3 repeats = 4 codes) + // Legacy use of this procedure was only to send a single code + // so use repeat=0 for backward compatibility. + void sendDISH(uint64_t data, uint16_t nbits = kDishBits, + uint16_t repeat = kDishMinRepeat); +#endif +#if (SEND_PANASONIC || SEND_DENON) + void sendPanasonic64(uint64_t data, uint16_t nbits = kPanasonicBits, + uint16_t repeat = kNoRepeat); + void sendPanasonic(uint16_t address, uint32_t data, + uint16_t nbits = kPanasonicBits, + uint16_t repeat = kNoRepeat); + uint64_t encodePanasonic(uint16_t manufacturer, uint8_t device, + uint8_t subdevice, uint8_t function); +#endif +#if SEND_RC5 + void sendRC5(uint64_t data, uint16_t nbits = kRC5XBits, + uint16_t repeat = kNoRepeat); + uint16_t encodeRC5(uint8_t address, uint8_t command, + bool key_released = false); + uint16_t encodeRC5X(uint8_t address, uint8_t command, + bool key_released = false); + uint64_t toggleRC5(uint64_t data); +#endif +#if SEND_RC6 + void sendRC6(uint64_t data, uint16_t nbits = kRC6Mode0Bits, + uint16_t repeat = kNoRepeat); + uint64_t encodeRC6(uint32_t address, uint8_t command, + uint16_t mode = kRC6Mode0Bits); + uint64_t toggleRC6(uint64_t data, uint16_t nbits = kRC6Mode0Bits); +#endif +#if SEND_RCMM + void sendRCMM(uint64_t data, uint16_t nbits = kRCMMBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_COOLIX + void sendCOOLIX(uint64_t data, uint16_t nbits = kCoolixBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_WHYNTER + void sendWhynter(uint64_t data, uint16_t nbits = kWhynterBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_MITSUBISHI + void sendMitsubishi(uint64_t data, uint16_t nbits = kMitsubishiBits, + uint16_t repeat = kMitsubishiMinRepeat); +#endif +#if SEND_MITSUBISHI2 + void sendMitsubishi2(uint64_t data, uint16_t nbits = kMitsubishiBits, + uint16_t repeat = kMitsubishiMinRepeat); +#endif +#if SEND_MITSUBISHI_AC + void sendMitsubishiAC(unsigned char data[], + uint16_t nbytes = kMitsubishiACStateLength, + uint16_t repeat = kMitsubishiACMinRepeat); +#endif +#if SEND_FUJITSU_AC + void sendFujitsuAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat = kFujitsuAcMinRepeat); +#endif +#if SEND_GLOBALCACHE + void sendGC(uint16_t buf[], uint16_t len); +#endif +#if SEND_KELVINATOR + void sendKelvinator(unsigned char data[], + uint16_t nbytes = kKelvinatorStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_DAIKIN + void sendDaikin(unsigned char data[], uint16_t nbytes = kDaikinStateLength, + uint16_t repeat = kNoRepeat); + void sendDaikinGapHeader(); +#endif +#if SEND_AIWA_RC_T501 + void sendAiwaRCT501(uint64_t data, uint16_t nbits = kAiwaRcT501Bits, + uint16_t repeat = kAiwaRcT501MinRepeats); +#endif +#if SEND_GREE + void sendGree(uint64_t data, uint16_t nbits = kGreeBits, + uint16_t repeat = kNoRepeat); + void sendGree(uint8_t data[], uint16_t nbytes = kGreeStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_PRONTO + void sendPronto(uint16_t data[], uint16_t len, uint16_t repeat = kNoRepeat); +#endif +#if SEND_ARGO + void sendArgo(unsigned char data[], uint16_t nbytes = kArgoStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_TROTEC + void sendTrotec(unsigned char data[], uint16_t nbytes = kTrotecStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_NIKAI + void sendNikai(uint64_t data, uint16_t nbits = kNikaiBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_TOSHIBA_AC + void sendToshibaAC(unsigned char data[], + uint16_t nbytes = kToshibaACStateLength, + uint16_t repeat = kToshibaACMinRepeat); +#endif +#if SEND_MIDEA + void sendMidea(uint64_t data, uint16_t nbits = kMideaBits, + uint16_t repeat = kMideaMinRepeat); +#endif +#if SEND_MAGIQUEST + void sendMagiQuest(uint64_t data, uint16_t nbits = kMagiquestBits, + uint16_t repeat = kNoRepeat); + uint64_t encodeMagiQuest(uint32_t wand_id, uint16_t magnitude); +#endif +#if SEND_LASERTAG + void sendLasertag(uint64_t data, uint16_t nbits = kLasertagBits, + uint16_t repeat = kLasertagMinRepeat); +#endif +#if SEND_CARRIER_AC + void sendCarrierAC(uint64_t data, uint16_t nbits = kCarrierAcBits, + uint16_t repeat = kCarrierAcMinRepeat); +#endif +#if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02) + void sendHaierAC(unsigned char data[], uint16_t nbytes = kHaierACStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_HAIER_AC_YRW02 + void sendHaierACYRW02(unsigned char data[], + uint16_t nbytes = kHaierACYRW02StateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_HITACHI_AC + void sendHitachiAC(unsigned char data[], + uint16_t nbytes = kHitachiAcStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_HITACHI_AC1 + void sendHitachiAC1(unsigned char data[], + uint16_t nbytes = kHitachiAc1StateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_HITACHI_AC2 + void sendHitachiAC2(unsigned char data[], + uint16_t nbytes = kHitachiAc2StateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_GICABLE + void sendGICable(uint64_t data, uint16_t nbits = kGicableBits, + uint16_t repeat = kGicableMinRepeat); +#endif +#if SEND_WHIRLPOOL_AC + void sendWhirlpoolAC(unsigned char data[], + uint16_t nbytes = kWhirlpoolAcStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_LUTRON + void sendLutron(uint64_t data, uint16_t nbits = kLutronBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_ELECTRA_AC + void sendElectraAC(unsigned char data[], + uint16_t nbytes = kElectraAcStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_PANASONIC_AC + void sendPanasonicAC(unsigned char data[], + uint16_t nbytes = kPanasonicAcStateLength, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_PIONEER + void sendPioneer(const uint64_t data, const uint16_t nbits = kPioneerBits, + const uint16_t repeat = kNoRepeat); + uint64_t encodePioneer(uint16_t address, uint16_t command); +#endif +#if SEND_MWM + void sendMWM(unsigned char data[], uint16_t nbytes, + uint16_t repeat = kNoRepeat); +#endif + + protected: +#ifdef UNIT_TEST +#ifndef HIGH +#define HIGH 0x1 +#endif +#ifndef LOW +#define LOW 0x0 +#endif +#endif // UNIT_TEST + uint8_t outputOn; + uint8_t outputOff; + VIRTUAL void ledOff(); + VIRTUAL void ledOn(); + + private: + uint16_t onTimePeriod; + uint16_t offTimePeriod; + uint16_t IRpin; + int8_t periodOffset; + uint8_t _dutycycle; + bool modulation; + uint32_t calcUSecPeriod(uint32_t hz, bool use_offset = true); +}; + +#endif // IRSEND_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.cpp b/lib/IRremoteESP8266-2.5.2.03/src/IRtimer.cpp similarity index 52% rename from lib/IRremoteESP8266-2.2.1.02/src/IRtimer.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/IRtimer.cpp index cc5cdfaff..029637cbb 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRtimer.cpp @@ -5,18 +5,21 @@ #include #endif +#ifdef UNIT_TEST +// Used to help simulate elapsed time in unit tests. +extern uint32_t _IRtimer_unittest_now; +#endif // UNIT_TEST + // This class performs a simple time in useconds since instantiated. // Handles when the system timer wraps around (once). -IRtimer::IRtimer() { - reset(); -} +IRtimer::IRtimer() { reset(); } void IRtimer::reset() { #ifndef UNIT_TEST start = micros(); #else - start = 0; + start = _IRtimer_unittest_now; #endif } @@ -24,10 +27,15 @@ uint32_t IRtimer::elapsed() { #ifndef UNIT_TEST uint32_t now = micros(); #else - uint32_t now = 0; + uint32_t now = _IRtimer_unittest_now; #endif - if (start <= now) // Check if the system timer has wrapped. + if (start <= now) // Check if the system timer has wrapped. return now - start; // No wrap. else return UINT32_MAX - start + now; // Has wrapped. } + +// Only used in unit testing. +#ifdef UNIT_TEST +void IRtimer::add(uint32_t usecs) { _IRtimer_unittest_now += usecs; } +#endif // UNIT_TEST diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.h b/lib/IRremoteESP8266-2.5.2.03/src/IRtimer.h similarity index 78% rename from lib/IRremoteESP8266-2.2.1.02/src/IRtimer.h rename to lib/IRremoteESP8266-2.5.2.03/src/IRtimer.h index 6cf7f7dc8..baca1cf74 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.h +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRtimer.h @@ -12,6 +12,9 @@ class IRtimer { IRtimer(); void reset(); uint32_t elapsed(); +#ifdef UNIT_TEST + static void add(uint32_t usecs); +#endif // UNIT_TEST private: uint32_t start; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp b/lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp new file mode 100644 index 000000000..7864625a5 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp @@ -0,0 +1,470 @@ +// Copyright 2017 David Conran + +#include "IRutils.h" +#ifndef UNIT_TEST +#include +#endif + +#define __STDC_LIMIT_MACROS +#include +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" + +// Reverse the order of the requested least significant nr. of bits. +// Args: +// input: Bit pattern/integer to reverse. +// nbits: Nr. of bits to reverse. +// Returns: +// The reversed bit pattern. +uint64_t reverseBits(uint64_t input, uint16_t nbits) { + if (nbits <= 1) return input; // Reversing <= 1 bits makes no change at all. + // Cap the nr. of bits to rotate to the max nr. of bits in the input. + nbits = std::min(nbits, (uint16_t)(sizeof(input) * 8)); + uint64_t output = 0; + for (uint16_t i = 0; i < nbits; i++) { + output <<= 1; + output |= (input & 1); + input >>= 1; + } + // Merge any remaining unreversed bits back to the top of the reversed bits. + return (input << nbits) | output; +} + +// Convert a uint64_t (unsigned long long) to a string. +// Arduino String/toInt/Serial.print() can't handle printing 64 bit values. +// +// Args: +// input: The value to print +// base: The output base. +// Returns: +// A string representation of the integer. +// Note: Based on Arduino's Print::printNumber() +#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. +String uint64ToString(uint64_t input, uint8_t base) { + String result = ""; +#else +std::string uint64ToString(uint64_t input, uint8_t base) { + std::string result = ""; +#endif + // prevent issues if called with base <= 1 + if (base < 2) base = 10; + // Check we have a base that we can actually print. + // i.e. [0-9A-Z] == 36 + if (base > 36) base = 10; + + do { + char c = input % base; + input /= base; + + if (c < 10) + c += '0'; + else + c += 'A' - 10; + result = c + result; + } while (input); + return result; +} + +#ifdef ARDUINO +// Print a uint64_t/unsigned long long to the Serial port +// Serial.print() can't handle printing long longs. (uint64_t) +// +// Args: +// input: The value to print +// base: The output base. +void serialPrintUint64(uint64_t input, uint8_t base) { + Serial.print(uint64ToString(input, base)); +} +#endif + +// Convert a protocol type (enum etc) to a human readable string. +// Args: +// protocol: Nr. (enum) of the protocol. +// isRepeat: A flag indicating if it is a repeat message of the protocol. +// Returns: +// A string containing the protocol name. +#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. +String typeToString(const decode_type_t protocol, const bool isRepeat) { + String result = ""; +#else +std::string typeToString(const decode_type_t protocol, const bool isRepeat) { + std::string result = ""; +#endif + switch (protocol) { + default: + case UNKNOWN: + result = "UNKNOWN"; + break; + case UNUSED: + result = "UNUSED"; + break; + case AIWA_RC_T501: + result = "AIWA_RC_T501"; + break; + case ARGO: + result = "ARGO"; + break; + case CARRIER_AC: + result = "CARRIER_AC"; + break; + case COOLIX: + result = "COOLIX"; + break; + case DAIKIN: + result = "DAIKIN"; + break; + case DENON: + result = "DENON"; + break; + case DISH: + result = "DISH"; + break; + case ELECTRA_AC: + result = "ELECTRA_AC"; + break; + case FUJITSU_AC: + result = "FUJITSU_AC"; + break; + case GICABLE: + result = "GICABLE"; + break; + case GLOBALCACHE: + result = "GLOBALCACHE"; + break; + case GREE: + result = "GREE"; + break; + case HAIER_AC: + result = "HAIER_AC"; + break; + case HAIER_AC_YRW02: + result = "HAIER_AC_YRW02"; + break; + case HITACHI_AC: + result = "HITACHI_AC"; + break; + case HITACHI_AC1: + result = "HITACHI_AC1"; + break; + case HITACHI_AC2: + result = "HITACHI_AC2"; + break; + case JVC: + result = "JVC"; + break; + case KELVINATOR: + result = "KELVINATOR"; + break; + case LG: + result = "LG"; + break; + case LG2: + result = "LG2"; + break; + case LASERTAG: + result = "LASERTAG"; + break; + case LUTRON: + result = "LUTRON"; + break; + case MAGIQUEST: + result = "MAGIQUEST"; + break; + case MIDEA: + result = "MIDEA"; + break; + case MITSUBISHI: + result = "MITSUBISHI"; + break; + case MITSUBISHI2: + result = "MITSUBISHI2"; + break; + case MITSUBISHI_AC: + result = "MITSUBISHI_AC"; + break; + case MWM: + result = "MWM"; + break; + case NEC: + result = "NEC"; + break; + case NEC_LIKE: + result = "NEC (non-strict)"; + break; + case NIKAI: + result = "NIKAI"; + break; + case PANASONIC: + result = "PANASONIC"; + break; + case PANASONIC_AC: + result = "PANASONIC_AC"; + break; + case PIONEER: + result = "PIONEER"; + break; + case PRONTO: + result = "PRONTO"; + break; + case RAW: + result = "RAW"; + break; + case RC5: + result = "RC5"; + break; + case RC5X: + result = "RC5X"; + break; + case RC6: + result = "RC6"; + break; + case RCMM: + result = "RCMM"; + break; + case SAMSUNG: + result = "SAMSUNG"; + break; + case SAMSUNG_AC: + result = "SAMSUNG_AC"; + break; + case SANYO: + result = "SANYO"; + break; + case SANYO_LC7461: + result = "SANYO_LC7461"; + break; + case SHARP: + result = "SHARP"; + break; + case SHERWOOD: + result = "SHERWOOD"; + break; + case SONY: + result = "SONY"; + break; + case TOSHIBA_AC: + result = "TOSHIBA_AC"; + break; + case TROTEC: + result = "TROTEC"; + break; + case WHIRLPOOL_AC: + result = "WHIRLPOOL_AC"; + break; + case WHYNTER: + result = "WHYNTER"; + break; + } + if (isRepeat) result += " (Repeat)"; + return result; +} + +// Does the given protocol use a complex state as part of the decode? +bool hasACState(const decode_type_t protocol) { + switch (protocol) { + case DAIKIN: + case ELECTRA_AC: + case FUJITSU_AC: + case GREE: + case HAIER_AC: + case HAIER_AC_YRW02: + case HITACHI_AC: + case HITACHI_AC1: + case HITACHI_AC2: + case KELVINATOR: + case MITSUBISHI_AC: + case MWM: + case PANASONIC_AC: + case SAMSUNG_AC: + case TOSHIBA_AC: + case WHIRLPOOL_AC: + return true; + default: + return false; + } +} + +// Return the corrected length of a 'raw' format array structure +// after over-large values are converted into multiple entries. +// Args: +// results: A ptr to a decode result. +// Returns: +// A uint16_t containing the length. +uint16_t getCorrectedRawLength(const decode_results *results) { + uint16_t extended_length = results->rawlen - 1; + for (uint16_t i = 0; i < results->rawlen - 1; i++) { + uint32_t usecs = results->rawbuf[i] * kRawTick; + // Add two extra entries for multiple larger than UINT16_MAX it is. + extended_length += (usecs / (UINT16_MAX + 1)) * 2; + } + return extended_length; +} + +// Return a string containing the key values of a decode_results structure +// in a C/C++ code style format. +#ifdef ARDUINO +String resultToSourceCode(const decode_results *results) { + String output = ""; +#else +std::string resultToSourceCode(const decode_results *results) { + std::string output = ""; +#endif + // Start declaration + output += "uint16_t "; // variable type + output += "rawData["; // array name + output += uint64ToString(getCorrectedRawLength(results), 10); + // array size + output += "] = {"; // Start declaration + + // Dump data + for (uint16_t i = 1; i < results->rawlen; i++) { + uint32_t usecs; + for (usecs = results->rawbuf[i] * kRawTick; usecs > UINT16_MAX; + usecs -= UINT16_MAX) { + output += uint64ToString(UINT16_MAX); + if (i % 2) + output += ", 0, "; + else + output += ", 0, "; + } + output += uint64ToString(usecs, 10); + if (i < results->rawlen - 1) + output += ", "; // ',' not needed on the last one + if (i % 2 == 0) output += " "; // Extra if it was even. + } + + // End declaration + output += "};"; + + // Comment + output += " // " + typeToString(results->decode_type, results->repeat); + // Only display the value if the decode type doesn't have an A/C state. + if (!hasACState(results->decode_type)) + output += " " + uint64ToString(results->value, 16); + output += "\n"; + + // Now dump "known" codes + if (results->decode_type != UNKNOWN) { + if (hasACState(results->decode_type)) { +#if DECODE_AC + uint16_t nbytes = results->bits / 8; + output += "uint8_t state[" + uint64ToString(nbytes) + "] = {"; + for (uint16_t i = 0; i < nbytes; i++) { + output += "0x"; + if (results->state[i] < 0x10) output += "0"; + output += uint64ToString(results->state[i], 16); + if (i < nbytes - 1) output += ", "; + } + output += "};\n"; +#endif // DECODE_AC + } else { + // Simple protocols + // Some protocols have an address &/or command. + // NOTE: It will ignore the atypical case when a message has been + // decoded but the address & the command are both 0. + if (results->address > 0 || results->command > 0) { + output += "uint32_t address = 0x" + + uint64ToString(results->address, 16) + ";\n"; + output += "uint32_t command = 0x" + + uint64ToString(results->command, 16) + ";\n"; + } + // Most protocols have data + output += + "uint64_t data = 0x" + uint64ToString(results->value, 16) + ";\n"; + } + } + return output; +} + +// Dump out the decode_results structure. +// +#ifdef ARDUINO +String resultToTimingInfo(const decode_results *results) { + String output = ""; + String value = ""; +#else +std::string resultToTimingInfo(const decode_results *results) { + std::string output = ""; + std::string value = ""; +#endif + output += "Raw Timing[" + uint64ToString(results->rawlen - 1, 10) + "]:\n"; + + for (uint16_t i = 1; i < results->rawlen; i++) { + if (i % 2 == 0) + output += "-"; // even + else + output += " +"; // odd + value = uint64ToString(results->rawbuf[i] * kRawTick); + // Space pad the value till it is at least 6 chars long. + while (value.length() < 6) value = " " + value; + output += value; + if (i < results->rawlen - 1) output += ", "; // ',' not needed for last one + if (!(i % 8)) output += "\n"; // Newline every 8 entries. + } + output += "\n"; + return output; +} + +// Convert the decode_results structure's value/state to simple hexadecimal. +// +#ifdef ARDUINO +String resultToHexidecimal(const decode_results *result) { + String output = ""; +#else +std::string resultToHexidecimal(const decode_results *result) { + std::string output = ""; +#endif + if (hasACState(result->decode_type)) { +#if DECODE_AC + for (uint16_t i = 0; result->bits > i * 8; i++) { + if (result->state[i] < 0x10) output += "0"; // Zero pad + output += uint64ToString(result->state[i], 16); + } +#endif // DECODE_AC + } else { + output += uint64ToString(result->value, 16); + } + return output; +} + +// Dump out the decode_results structure. +// +#ifdef ARDUINO +String resultToHumanReadableBasic(const decode_results *results) { + String output = ""; +#else +std::string resultToHumanReadableBasic(const decode_results *results) { + std::string output = ""; +#endif + // Show Encoding standard + output += + "Encoding : " + typeToString(results->decode_type, results->repeat) + + "\n"; + + // Show Code & length + output += "Code : "; + output += resultToHexidecimal(results); + output += " (" + uint64ToString(results->bits) + " bits)\n"; + return output; +} + +uint8_t sumBytes(uint8_t *start, const uint16_t length, const uint8_t init) { + uint8_t checksum = init; + uint8_t *ptr; + for (ptr = start; ptr - start < length; ptr++) checksum += *ptr; + return checksum; +} + +uint64_t invertBits(const uint64_t data, const uint16_t nbits) { + // No change if we are asked to invert no bits. + if (nbits == 0) return data; + uint64_t result = ~data; + // If we are asked to invert all the bits or more than we have, it's simple. + if (nbits >= sizeof(data) * 8) return result; + // Mask off any unwanted bits and return the result. + return (result & ((1ULL << nbits) - 1)); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRutils.h b/lib/IRremoteESP8266-2.5.2.03/src/IRutils.h new file mode 100644 index 000000000..c17375d98 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/IRutils.h @@ -0,0 +1,41 @@ +#ifndef IRUTILS_H_ +#define IRUTILS_H_ + +// Copyright 2017 David Conran + +#ifndef UNIT_TEST +#include +#endif +#define __STDC_LIMIT_MACROS +#include +#ifndef ARDUINO +#include +#endif +#include "IRremoteESP8266.h" +#include "IRrecv.h" + +uint64_t reverseBits(uint64_t input, uint16_t nbits); +#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. +String uint64ToString(uint64_t input, uint8_t base = 10); +String typeToString(const decode_type_t protocol, + const bool isRepeat = false); +void serialPrintUint64(uint64_t input, uint8_t base = 10); +String resultToSourceCode(const decode_results *results); +String resultToTimingInfo(const decode_results *results); +String resultToHumanReadableBasic(const decode_results *results); +String resultToHexidecimal(const decode_results *result); +#else +std::string uint64ToString(uint64_t input, uint8_t base = 10); +std::string typeToString(const decode_type_t protocol, + const bool isRepeat = false); +std::string resultToSourceCode(const decode_results *results); +std::string resultToTimingInfo(const decode_results *results); +std::string resultToHumanReadableBasic(const decode_results *results); +std::string resultToHexidecimal(const decode_results *result); +#endif +bool hasACState(const decode_type_t protocol); +uint16_t getCorrectedRawLength(const decode_results *results); +uint8_t sumBytes(uint8_t *start, const uint16_t length, const uint8_t init = 0); +uint64_t invertBits(const uint64_t data, const uint16_t nbits); + +#endif // IRUTILS_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Aiwa.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Aiwa.cpp similarity index 76% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Aiwa.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Aiwa.cpp index 99a97e187..617711a99 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Aiwa.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Aiwa.cpp @@ -2,7 +2,6 @@ #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" // AAA IIIII W W AAA // A A I W W A A @@ -14,20 +13,20 @@ // Added by David Conran. (Inspired by IRremoteESP8266's implementation: // https://github.com/z3t0/Arduino-IRremote) -#define AIWA_RC_T501_PRE_BITS 26U -#define AIWA_RC_T501_POST_BITS 1U +const uint16_t kAiwaRcT501PreBits = 26; +const uint16_t kAiwaRcT501PostBits = 1; // NOTE: These are the compliment (inverted) of lirc values as // lirc uses a '0' for a mark, and a '1' for a space. -#define AIWA_RC_T501_PRE_DATA 0x1D8113FULL // 26-bits -#define AIWA_RC_T501_POST_DATA 1ULL +const uint64_t kAiwaRcT501PreData = 0x1D8113FULL; // 26-bits +const uint64_t kAiwaRcT501PostData = 1ULL; #if SEND_AIWA_RC_T501 -// Send a Aiwa RC T501 formatted message. +// Send an Aiwa RC T501 formatted message. // // Args: // data: The message to be sent. // nbits: The number of bits of the message to be sent. -// Typically AIWA_RC_T501_BITS. Max is 37 = (64 - 27) +// Typically kAiwaRcT501Bits. Max is 37 = (64 - 27) // repeat: The number of times the command is to be repeated. // // Status: BETA / Should work. @@ -38,10 +37,9 @@ void IRsend::sendAiwaRCT501(uint64_t data, uint16_t nbits, uint16_t repeat) { // Appears to be an extended NEC1 protocol. i.e. 42 bits instead of 32 bits. // So use sendNEC instead, however the twist is it has a fixed 26 bit // prefix, and a fixed postfix bit. - uint64_t new_data = ( - (AIWA_RC_T501_PRE_DATA << (nbits + AIWA_RC_T501_POST_BITS)) | - (data << AIWA_RC_T501_POST_BITS) | AIWA_RC_T501_POST_DATA); - nbits += AIWA_RC_T501_PRE_BITS + AIWA_RC_T501_POST_BITS; + uint64_t new_data = ((kAiwaRcT501PreData << (nbits + kAiwaRcT501PostBits)) | + (data << kAiwaRcT501PostBits) | kAiwaRcT501PostData); + nbits += kAiwaRcT501PreBits + kAiwaRcT501PostBits; if (nbits > sizeof(new_data) * 8) return; // We are overflowing. Abort, and don't send. sendNEC(new_data, nbits, repeat); @@ -53,7 +51,7 @@ void IRsend::sendAiwaRCT501(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. -// nbits: The number of data bits to expect. Typically AIWA_RC_T501_BITS. +// nbits: The number of data bits to expect. Typically kAiwaRcT501Bits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. @@ -72,12 +70,11 @@ void IRsend::sendAiwaRCT501(uint64_t data, uint16_t nbits, uint16_t repeat) { bool IRrecv::decodeAiwaRCT501(decode_results *results, uint16_t nbits, bool strict) { // Compliance - if (strict && nbits != AIWA_RC_T501_BITS) + if (strict && nbits != kAiwaRcT501Bits) return false; // Doesn't match our protocol defn. // Add on the pre & post bits to our requested bit length. - uint16_t expected_nbits = nbits + AIWA_RC_T501_PRE_BITS + - AIWA_RC_T501_POST_BITS; + uint16_t expected_nbits = nbits + kAiwaRcT501PreBits + kAiwaRcT501PostBits; uint64_t new_data; if (expected_nbits > sizeof(new_data) * 8) return false; // We can't possibly match something that big. @@ -89,24 +86,23 @@ bool IRrecv::decodeAiwaRCT501(decode_results *results, uint16_t nbits, new_data = results->value; if (actual_bits < expected_nbits) return false; // The data we caught was undersized. Throw it back. - if ((new_data & 0x1ULL) != AIWA_RC_T501_POST_DATA) + if ((new_data & 0x1ULL) != kAiwaRcT501PostData) return false; // The post data doesn't match, so it can't be this protocol. // Trim off the post data bit. - new_data >>= AIWA_RC_T501_POST_BITS; - actual_bits -= AIWA_RC_T501_POST_BITS; + new_data >>= kAiwaRcT501PostBits; + actual_bits -= kAiwaRcT501PostBits; // Extract out our likely new value and put it back in the results. - actual_bits -= AIWA_RC_T501_PRE_BITS; + actual_bits -= kAiwaRcT501PreBits; results->value = new_data & ((1ULL << actual_bits) - 1); // Check the prefix data matches. new_data >>= actual_bits; // Trim off the new data to expose the prefix. - if (new_data != AIWA_RC_T501_PRE_DATA) // Check the prefix. + if (new_data != kAiwaRcT501PreData) // Check the prefix. return false; // Compliance - if (strict && results->bits != expected_nbits) - return false; + if (strict && results->bits != expected_nbits) return false; // Success results->decode_type = AIWA_RC_T501; diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.cpp similarity index 69% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.cpp index 0129c7231..8a3e69f72 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.cpp @@ -11,53 +11,40 @@ Copyright 2017 Schmolders // Constants // using SPACE modulation. MARK is always const 400u -#define ARGO_PREAMBLE_1 6400U // Mark -#define ARGO_PREAMBLE_2 3300U // Space -#define ARGO_MARK 400U -#define ARGO_ONE_SPACE 2200U -#define ARGO_ZERO_SPACE 900U +const uint16_t kArgoHdrMark = 6400; +const uint16_t kArgoHdrSpace = 3300; +const uint16_t kArgoBitMark = 400; +const uint16_t kArgoOneSpace = 2200; +const uint16_t kArgoZeroSpace = 900; #if SEND_ARGO -// Send a Argo A/C message. +// Send an Argo A/C message. // // Args: -// data: An array of ARGO_COMMAND_LENGTH bytes containing the IR command. +// data: An array of kArgoStateLength bytes containing the IR command. // // Status: ALPHA / Untested. -// -// Overloading the IRSend Function void IRsend::sendArgo(unsigned char data[], uint16_t nbytes, uint16_t repeat) { // Check if we have enough bytes to send a proper message. - if (nbytes < ARGO_COMMAND_LENGTH) return; - // Set IR carrier frequency - enableIROut(38); - for (uint16_t r = 0; r <= repeat; r++) { - // Header - // TODO(kaschmo): validate - mark(ARGO_PREAMBLE_1); - space(ARGO_PREAMBLE_2); - // send data, defined in IRSend.cpp - for (uint16_t i = 0; i < nbytes; i++) - sendData(ARGO_MARK, ARGO_ONE_SPACE, ARGO_MARK, - ARGO_ZERO_SPACE, data[i], 8, false); - // send LSB first reverses the bit order in array for sending. - } + if (nbytes < kArgoStateLength) return; + // TODO(kaschmo): validate + sendGeneric(kArgoHdrMark, kArgoHdrSpace, kArgoBitMark, kArgoOneSpace, + kArgoBitMark, kArgoZeroSpace, 0, 0, // No Footer. + data, nbytes, 38, false, repeat, kDutyDefault); } +#endif // SEND_ARGO -IRArgoAC::IRArgoAC(uint16_t pin) : _irsend(pin) { - stateReset(); -} +IRArgoAC::IRArgoAC(uint16_t pin) : _irsend(pin) { stateReset(); } -void IRArgoAC::begin() { - _irsend.begin(); -} +void IRArgoAC::begin() { _irsend.begin(); } +#if SEND_ARGO void IRArgoAC::send() { - // Serial.println("Sending IR code"); // Only for Debug checksum(); // Create valid checksum before sending _irsend.sendArgo(argo); } +#endif // SEND_ARGO void IRArgoAC::checksum() { uint8_t sum = 2; // Corresponds to byte 11 being constant 0b01 @@ -65,20 +52,18 @@ void IRArgoAC::checksum() { // Only add up bytes to 9. byte 10 is 0b01 constant anyway. // Assume that argo array is MSB first (left) - for (i = 0; i < 10; i++) - sum += argo[i]; + for (i = 0; i < 10; i++) sum += argo[i]; sum = sum % 256; // modulo 256 // Append sum to end of array // Set const part of checksum bit 10 argo[10] = 0b00000010; argo[10] += sum << 2; // Shift up 2 bits and append to byte 10 - argo[11] = sum >> 6; // Shift down 6 bits and add in two LSBs of bit 11 + argo[11] = sum >> 6; // Shift down 6 bits and add in two LSBs of bit 11 } void IRArgoAC::stateReset() { - for (uint8_t i = 0; i < ARGO_COMMAND_LENGTH; i++) - argo[i] = 0x0; + for (uint8_t i = 0; i < kArgoStateLength; i++) argo[i] = 0x0; // Argo Message. Store MSB left. // Default message: @@ -91,8 +76,8 @@ void IRArgoAC::stateReset() { this->off(); this->setTemp(20); this->setRoomTemp(25); - this->setCoolMode(ARGO_COOL_AUTO); - this->setFan(ARGO_FAN_AUTO); + this->setCoolMode(kArgoCoolAuto); + this->setFan(kArgoFanAuto); } uint8_t* IRArgoAC::getRaw() { @@ -123,9 +108,7 @@ void IRArgoAC::setPower(bool state) { off(); } -uint8_t IRArgoAC::getPower() { - return ac_state; -} +uint8_t IRArgoAC::getPower() { return ac_state; } void IRArgoAC::setMax(bool state) { max_mode = state; @@ -135,17 +118,15 @@ void IRArgoAC::setMax(bool state) { argo[9] &= 0b11110111; } -bool IRArgoAC::getMax() { - return max_mode; -} +bool IRArgoAC::getMax() { return max_mode; } // Set the temp in deg C // Sending 0 equals +4 void IRArgoAC::setTemp(uint8_t temp) { - if (temp < ARGO_MIN_TEMP) - temp = ARGO_MIN_TEMP; - else if (temp > ARGO_MAX_TEMP) - temp = ARGO_MAX_TEMP; + if (temp < kArgoMinTemp) + temp = kArgoMinTemp; + else if (temp > kArgoMaxTemp) + temp = kArgoMaxTemp; // Store in attributes set_temp = temp; @@ -161,9 +142,7 @@ void IRArgoAC::setTemp(uint8_t temp) { argo[3] += temp >> 2; // remove lowest to bits and append in 0-2 } -uint8_t IRArgoAC::getTemp() { - return set_temp; -} +uint8_t IRArgoAC::getTemp() { return set_temp; } // Set the speed of the fan void IRArgoAC::setFan(uint8_t fan) { @@ -175,18 +154,14 @@ void IRArgoAC::setFan(uint8_t fan) { argo[3] += fan << 3; } -uint8_t IRArgoAC::getFan() { - return fan_mode; -} +uint8_t IRArgoAC::getFan() { return fan_mode; } void IRArgoAC::setFlap(uint8_t flap) { flap_mode = flap; // TODO(kaschmo): set correct bits for flap mode } -uint8_t IRArgoAC::getFlap() { - return flap_mode; -} +uint8_t IRArgoAC::getFlap() { return flap_mode; } uint8_t IRArgoAC::getMode() { // return cooling 0, heating 1 @@ -203,9 +178,7 @@ void IRArgoAC::setCoolMode(uint8_t mode) { argo[2] += mode << 3; } -uint8_t IRArgoAC::getCoolMode() { - return cool_mode; -} +uint8_t IRArgoAC::getCoolMode() { return cool_mode; } void IRArgoAC::setHeatMode(uint8_t mode) { ac_mode = 1; // Set ac mode to heating @@ -218,9 +191,7 @@ void IRArgoAC::setHeatMode(uint8_t mode) { argo[2] += mode << 3; } -uint8_t IRArgoAC::getHeatMode() { - return heat_mode; -} +uint8_t IRArgoAC::getHeatMode() { return heat_mode; } void IRArgoAC::setNight(bool state) { night_mode = state; @@ -231,9 +202,7 @@ void IRArgoAC::setNight(bool state) { argo[9] &= 0b11111011; } -bool IRArgoAC::getNight() { - return night_mode; -} +bool IRArgoAC::getNight() { return night_mode; } void IRArgoAC::setiFeel(bool state) { ifeel_mode = state; @@ -244,9 +213,7 @@ void IRArgoAC::setiFeel(bool state) { argo[9] &= 0b01111111; } -bool IRArgoAC::getiFeel() { - return ifeel_mode; -} +bool IRArgoAC::getiFeel() { return ifeel_mode; } void IRArgoAC::setTime() { // TODO(kaschmo): use function call from checksum to set time first @@ -261,4 +228,3 @@ void IRArgoAC::setRoomTemp(uint8_t temp) { argo[3] += temp << 5; // Append to bit 5,6,7 argo[4] += temp >> 3; // Remove lowest 3 bits and append in 0,1 } -#endif // SEND_ARGO diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.h similarity index 51% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.h rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.h index a25199208..b49fc3517 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.h +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.h @@ -29,40 +29,59 @@ // Constants. Store MSB left. -#define ARGO_COOL_ON 0U // 0b000 -#define ARGO_COOL_OFF 3U // 0b110 -#define ARGO_COOL_AUTO 2U // 0b010 -#define ARGO_COOl_HUM 1U // 0b100 +const uint8_t kArgoCoolOn = 0; // 0b000 +const uint8_t kArgoCoolOff = 3; // 0b110 +const uint8_t kArgoCoolAuto = 2; // 0b010 +const uint8_t kArgoCoolHum = 1; // 0b100 +const uint8_t kArgoHeatOn = 0; // 0b001 +const uint8_t kArgoHeatAuto = 1; // 0b101 +const uint8_t kArgoHeatBlink = 2; // 0b011 // ??no idea what mode that is +const uint8_t kArgoMinTemp = 10; // Celsius offset +4 +const uint8_t kArgoMaxTemp = 32; // Celsius +const uint8_t kArgoFanAuto = 0; // 0b00 +const uint8_t kArgoFan3 = 3; // 0b11 +const uint8_t kArgoFan2 = 2; // 0b01 +const uint8_t kArgoFan1 = 1; // 0b10 +const uint8_t kArgoFlapAuto = 0; // 0b000 +const uint8_t kArgoFlap1 = 1; // 0b100 +const uint8_t kArgoFlap2 = 2; // 0b010 +const uint8_t kArgoFlap3 = 3; // 0b110 +const uint8_t kArgoFlap4 = 4; // 0b001 +const uint8_t kArgoFlap5 = 5; // 0b101 +const uint8_t kArgoFlap6 = 6; // 0b011 +const uint8_t kArgoFlapFull = 7; // 0b111 -#define ARGO_HEAT_ON 0U // 0b001 -#define ARGO_HEAT_AUTO 1U // 0b101 -#define ARGO_HEAT_BLINK 2U // 0b011 // ??no idea what mode that is +// Legacy defines. (Deperecated) +#define ARGO_COOL_ON kArgoCoolOn +#define ARGO_COOL_OFF kArgoCoolOff +#define ARGO_COOL_AUTO kArgoCoolAuto +#define ARGO_COOl_HUM kArgoCoolHum +#define ARGO_HEAT_ON kArgoHeatOn +#define ARGO_HEAT_AUTO kArgoHeatAuto +#define ARGO_HEAT_BLINK kArgoHeatBlink +#define ARGO_MIN_TEMP kArgoMinTemp +#define ARGO_MAX_TEMP kArgoMaxTemp +#define ARGO_FAN_AUTO kArgoFanAuto +#define ARGO_FAN_3 kArgoFan3 +#define ARGO_FAN_2 kArgoFan2 +#define ARGO_FAN_1 kArgoFan1 +#define ARGO_FLAP_AUTO kArgoFlapAuto +#define ARGO_FLAP_1 kArgoFlap1 +#define ARGO_FLAP_2 kArgoFlap2 +#define ARGO_FLAP_3 kArgoFlap3 +#define ARGO_FLAP_4 kArgoFlap4 +#define ARGO_FLAP_5 kArgoFlap5 +#define ARGO_FLAP_6 kArgoFlap6 +#define ARGO_FLAP_FULL kArgoFlapFull -#define ARGO_MIN_TEMP 10U // Celsius offset +4 -#define ARGO_MAX_TEMP 32U // Celsius - -#define ARGO_FAN_AUTO 0U // 0b00 -#define ARGO_FAN_3 3U // 0b11 -#define ARGO_FAN_2 2U // 0b01 -#define ARGO_FAN_1 1U // 0b10 - -#define ARGO_FLAP_AUTO 0U // 0b000 -#define ARGO_FLAP_1 1U // 0b100 -#define ARGO_FLAP_2 2U // 0b010 -#define ARGO_FLAP_3 3U // 0b110 -#define ARGO_FLAP_4 4U // 0b001 -#define ARGO_FLAP_5 5U // 0b101 -#define ARGO_FLAP_6 6U // 0b011 -#define ARGO_FLAP_FULL 7U // 0b111 - - -#if SEND_ARGO class IRArgoAC { public: explicit IRArgoAC(uint16_t pin); +#if SEND_ARGO void send(); +#endif // SEND_ARGO void begin(); void on(); void off(); @@ -102,7 +121,7 @@ class IRArgoAC { private: // # of bytes per command - uint8_t argo[ARGO_COMMAND_LENGTH]; // Defined in IRremoteESP8266.h + uint8_t argo[kArgoStateLength]; // Defined in IRremoteESP8266.h void stateReset(); void checksum(); IRsend _irsend; // instance of the IR send class @@ -119,6 +138,5 @@ class IRArgoAC { uint8_t max_mode; // on/off uint8_t ifeel_mode; // on/off }; -#endif // SEND_ARGO #endif // IR_ARGO_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Carrier.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Carrier.cpp new file mode 100644 index 000000000..350d61cc1 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Carrier.cpp @@ -0,0 +1,111 @@ +// Copyright 2018 David Conran + +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// CCCCC AAA RRRRRR RRRRRR IIIII EEEEEEE RRRRRR +// CC C AAAAA RR RR RR RR III EE RR RR +// CC AA AA RRRRRR RRRRRR III EEEEE RRRRRR +// CC C AAAAAAA RR RR RR RR III EE RR RR +// CCCCC AA AA RR RR RR RR IIIII EEEEEEE RR RR + +// Suits Carrier/Surrey HVAC models: +// 42QG5A55970 (remote) +// 619EGX0090E0 / 619EGX0120E0 / 619EGX0180E0 / 619EGX0220E0 (indoor units) +// 53NGK009/012 (inverter) + +// Constants +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/385 +const uint16_t kCarrierAcHdrMark = 8532; +const uint16_t kCarrierAcHdrSpace = 4228; +const uint16_t kCarrierAcBitMark = 628; +const uint16_t kCarrierAcOneSpace = 1320; +const uint16_t kCarrierAcZeroSpace = 532; +const uint16_t kCarrierAcGap = 20000; + +#if SEND_CARRIER_AC +// Send a Carrier HVAC formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The bit size of the message being sent. typically kCarrierAcBits. +// repeat: The number of times the message is to be repeated. +// +// Status: BETA / Appears to work on real devices. +// +void IRsend::sendCarrierAC(uint64_t data, uint16_t nbits, uint16_t repeat) { + for (uint16_t r = 0; r <= repeat; r++) { + uint64_t temp_data = data; + // Carrier sends the data block three times. normal + inverted + normal. + for (uint16_t i = 0; i < 3; i++) { + sendGeneric(kCarrierAcHdrMark, kCarrierAcHdrSpace, kCarrierAcBitMark, + kCarrierAcOneSpace, kCarrierAcBitMark, kCarrierAcZeroSpace, + kCarrierAcBitMark, kCarrierAcGap, temp_data, nbits, 38, true, + 0, kDutyDefault); + temp_data = invertBits(temp_data, nbits); + } + } +} +#endif + +#if DECODE_CARRIER_AC +// Decode the supplied Carrier HVAC message. +// Carrier HVAC messages contain only 32 bits, but it is sent three(3) times. +// i.e. normal + inverted + normal +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. +// Typically kCarrierAcBits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +// +bool IRrecv::decodeCarrierAC(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < ((2 * nbits + kHeader + kFooter) * 3) - 1) + return false; // Can't possibly be a valid Carrier message. + if (strict && nbits != kCarrierAcBits) + return false; // We expect Carrier to be 32 bits of message. + + uint64_t data = 0; + uint64_t prev_data = 0; + uint16_t offset = kStartOffset; + + for (uint8_t i = 0; i < 3; i++) { + prev_data = data; + // Header + if (!matchMark(results->rawbuf[offset++], kCarrierAcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kCarrierAcHdrSpace)) + return false; + // Data + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kCarrierAcBitMark, + kCarrierAcOneSpace, kCarrierAcBitMark, kCarrierAcZeroSpace); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + // Footer + if (!matchMark(results->rawbuf[offset++], kCarrierAcBitMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kCarrierAcGap)) + return false; + // Compliance. + if (strict) { + // Check if the data is an inverted copy of the previous data. + if (i > 0 && prev_data != invertBits(data, nbits)) return false; + } + } + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = CARRIER_AC; + results->address = data >> 16; + results->command = data & 0xFFFF; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.cpp new file mode 100644 index 000000000..ee539af25 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.cpp @@ -0,0 +1,423 @@ +// Copyright bakrus +// Copyright 2017 David Conran + +#include "ir_Coolix.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// CCCCC OOOOO OOOOO LL IIIII XX XX +// CC C OO OO OO OO LL III XX XX +// CC OO OO OO OO LL III XXXX +// CC C OO OO OO OO LL III XX XX +// CCCCC OOOO0 OOOO0 LLLLLLL IIIII XX XX + +// Coolix A/C / heatpump added by (send) bakrus & (decode) crankyoldgit +// +// Supports: +// RG57K7(B)/BGEF remote control for Beko BINR 070/071 split-type aircon. +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/484 + +// Constants +// Pulse parms are *50-100 for the Mark and *50+100 for the space +// First MARK is the one after the long gap +// pulse parameters in usec +const uint16_t kCoolixTick = 560; // Approximately 21 cycles at 38kHz +const uint16_t kCoolixBitMarkTicks = 1; +const uint16_t kCoolixBitMark = kCoolixBitMarkTicks * kCoolixTick; +const uint16_t kCoolixOneSpaceTicks = 3; +const uint16_t kCoolixOneSpace = kCoolixOneSpaceTicks * kCoolixTick; +const uint16_t kCoolixZeroSpaceTicks = 1; +const uint16_t kCoolixZeroSpace = kCoolixZeroSpaceTicks * kCoolixTick; +const uint16_t kCoolixHdrMarkTicks = 8; +const uint16_t kCoolixHdrMark = kCoolixHdrMarkTicks * kCoolixTick; +const uint16_t kCoolixHdrSpaceTicks = 8; +const uint16_t kCoolixHdrSpace = kCoolixHdrSpaceTicks * kCoolixTick; +const uint16_t kCoolixMinGapTicks = kCoolixHdrMarkTicks + kCoolixZeroSpaceTicks; +const uint16_t kCoolixMinGap = kCoolixMinGapTicks * kCoolixTick; + +#if SEND_COOLIX +// Send a Coolix message +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kCoolixBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: BETA / Probably works. +// +// Ref: +// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_COOLIX.cpp +// TODO(anyone): Verify repeat functionality against a real unit. +void IRsend::sendCOOLIX(uint64_t data, uint16_t nbits, uint16_t repeat) { + if (nbits % 8 != 0) return; // nbits is required to be a multiple of 8. + + // Set IR carrier frequency + enableIROut(38); + + for (uint16_t r = 0; r <= repeat; r++) { + // Header + mark(kCoolixHdrMark); + space(kCoolixHdrSpace); + + // Data + // Break data into byte segments, starting at the Most Significant + // Byte. Each byte then being sent normal, then followed inverted. + for (uint16_t i = 8; i <= nbits; i += 8) { + // Grab a bytes worth of data. + uint8_t segment = (data >> (nbits - i)) & 0xFF; + // Normal + sendData(kCoolixBitMark, kCoolixOneSpace, kCoolixBitMark, + kCoolixZeroSpace, segment, 8, true); + // Inverted. + sendData(kCoolixBitMark, kCoolixOneSpace, kCoolixBitMark, + kCoolixZeroSpace, segment ^ 0xFF, 8, true); + } + + // Footer + mark(kCoolixBitMark); + space(kCoolixMinGap); // Pause before repeating + } +} +#endif + +// IRCoolixAC class +// Supports: +// RG57K7(B)/BGEF remote control for Beko BINR 070/071 split-type aircon. +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/484 +IRCoolixAC::IRCoolixAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRCoolixAC::stateReset() { remote_state = kCoolixDefaultState; } + +void IRCoolixAC::begin() { _irsend.begin(); } + +#if SEND_COOLIX +void IRCoolixAC::send() { _irsend.sendCOOLIX(remote_state); } +#endif // SEND_COOLIX + +uint32_t IRCoolixAC::getRaw() { return remote_state; } + +void IRCoolixAC::setRaw(const uint32_t new_code) { remote_state = new_code; } + +void IRCoolixAC::setTempRaw(const uint8_t code) { + remote_state &= ~kCoolixTempMask; // Clear the old temp. + remote_state |= (code << 4); +} + +uint8_t IRCoolixAC::getTempRaw() { + return (remote_state & kCoolixTempMask) >> 4; +} + +void IRCoolixAC::setTemp(const uint8_t desired) { + // Range check. + uint8_t temp = std::min(desired, kCoolixTempMax); + temp = std::max(temp, kCoolixTempMin); + setTempRaw(kCoolixTempMap[temp - kCoolixTempMin]); +} + +uint8_t IRCoolixAC::getTemp() { + uint8_t code = getTempRaw(); + uint8_t i; + for (i = 0; i < kCoolixTempRange; i++) + if (kCoolixTempMap[i] == code) return kCoolixTempMin + i; + return kCoolixUnknown; // Not a temp we expected. +} + +void IRCoolixAC::setSensorTempRaw(const uint8_t code) { + remote_state &= ~kCoolixSensorTempMask; // Clear previous sensor temp. + remote_state |= ((code & 0xF) << 8); +} + +void IRCoolixAC::setSensorTemp(const uint8_t desired) { + uint8_t temp = desired; + temp = std::min(temp, kCoolixSensorTempMax); + temp = std::max(temp, kCoolixSensorTempMin); + setSensorTempRaw(temp - kCoolixSensorTempMin); + setZoneFollow(true); // Setting a Sensor temp means you want to Zone Follow. +} + +uint8_t IRCoolixAC::getSensorTemp() { + return ((remote_state & kCoolixSensorTempMask) >> 8) + kCoolixSensorTempMin; +} + +bool IRCoolixAC::getPower() { + // There is only an off state. Everything else is "on". + return remote_state != kCoolixOff; +} + +void IRCoolixAC::setPower(const bool power) { + if (!power) remote_state = kCoolixOff; + // There really is no distinct "on" setting, so do nothing. +} + +bool IRCoolixAC::getSwing() { return remote_state == kCoolixSwing; } + +void IRCoolixAC::setSwing() { + // Assumes that repeated sending "swing" toggles the action on the device. + remote_state = kCoolixSwing; +} + +bool IRCoolixAC::getSleep() { return remote_state == kCoolixSleep; } + +void IRCoolixAC::setSleep() { remote_state = kCoolixSleep; } + +bool IRCoolixAC::getTurbo() { return remote_state == kCoolixTurbo; } + +void IRCoolixAC::setTurbo() { + // Assumes that repeated sending "turbo" toggles the action on the device. + remote_state = kCoolixTurbo; +} + +bool IRCoolixAC::getLed() { return remote_state == kCoolixLed; } + +void IRCoolixAC::setLed() { + // Assumes that repeated sending "Led" toggles the action on the device. + remote_state = kCoolixLed; +} + +bool IRCoolixAC::getClean() { return remote_state == kCoolixClean; } + +void IRCoolixAC::setClean() { remote_state = kCoolixClean; } + +bool IRCoolixAC::getZoneFollow() { + return remote_state & kCoolixZoneFollowMask; +} + +// Internal use only. +void IRCoolixAC::setZoneFollow(bool state) { + if (state) { + remote_state |= kCoolixZoneFollowMask; + } else { + remote_state &= ~kCoolixZoneFollowMask; + } +} + +void IRCoolixAC::clearSensorTemp() { + setZoneFollow(false); + setSensorTempRaw(kCoolixSensorTempIgnoreCode); +} + +void IRCoolixAC::setMode(const uint8_t mode) { + uint32_t actualmode = mode; + // Fan mode is a special case of Dry. + if (mode == kCoolixFan) actualmode = kCoolixDry; + switch (actualmode) { + case kCoolixCool: + case kCoolixAuto: + case kCoolixHeat: + case kCoolixDry: + remote_state = (remote_state & ~kCoolixModeMask) | (actualmode << 2); + // Force the temp into a known-good state. + setTemp(getTemp()); + } + if (mode == kCoolixFan) setTempRaw(kCoolixFanTempCode); +} + +uint8_t IRCoolixAC::getMode() { + uint8_t mode = (remote_state & kCoolixModeMask) >> 2; + if (mode == kCoolixDry) + if (getTempRaw() == kCoolixFanTempCode) return kCoolixFan; + return mode; +} + +uint8_t IRCoolixAC::getFan() { return (remote_state & kCoolixFanMask) >> 13; } + +void IRCoolixAC::setFan(const uint8_t speed) { + uint8_t newspeed = speed; + switch (speed) { + case kCoolixFanMin: + case kCoolixFanMed: + case kCoolixFanMax: + case kCoolixFanAuto: + case kCoolixFanZoneFollow: + case kCoolixFanFixed: + break; + default: // Unknown speed requested. + newspeed = kCoolixFanAuto; + } + remote_state &= ~kCoolixFanMask; + remote_state |= ((newspeed << 13) & kCoolixFanMask); +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRCoolixAC::toString() { + String result = ""; +#else +std::string IRCoolixAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) { + result += "On"; + } else { + result += "Off"; + return result; // If it's off, there is no other info. + } + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kCoolixFanAuto: + result += " (AUTO)"; + break; + case kCoolixFanMax: + result += " (MAX)"; + break; + case kCoolixFanMin: + result += " (MIN)"; + break; + case kCoolixFanMed: + result += " (MED)"; + break; + case kCoolixFanZoneFollow: + result += " (ZONEFOLLOW)"; + break; + case kCoolixFanFixed: + result += " (FIXED)"; + break; + default: + result += " (UNKNOWN)"; + } + // Special modes. + if (getSwing()) { + result += ", Swing: Toggle"; + return result; + } + if (getSleep()) { + result += ", Sleep: Toggle"; + return result; + } + if (getTurbo()) { + result += ", Turbo: Toggle"; + return result; + } + if (getLed()) { + result += ", Led: Toggle"; + return result; + } + if (getClean()) { + result += ", Mode: Self clean"; + return result; + } + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kCoolixAuto: + result += " (AUTO)"; + break; + case kCoolixCool: + result += " (COOL)"; + break; + case kCoolixHeat: + result += " (HEAT)"; + break; + case kCoolixDry: + result += " (DRY)"; + break; + case kCoolixFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + if (getMode() != kCoolixFan) // Fan mode doesn't have a temperature. + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Zone Follow: "; + if (getZoneFollow()) + result += "On"; + else + result += "Off"; + result += ", Sensor Temp: "; + if (getSensorTemp() > kCoolixSensorTempMax) + result += "Ignored"; + else + result += uint64ToString(getSensorTemp()) + "C"; + return result; +} + +#if DECODE_COOLIX +// Decode the supplied Coolix message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kCoolixBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Probably working. +bool IRrecv::decodeCOOLIX(decode_results *results, uint16_t nbits, + bool strict) { + // The protocol sends the data normal + inverted, alternating on + // each byte. Hence twice the number of expected data bits. + if (results->rawlen < 2 * 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid COOLIX message. + if (strict && nbits != kCoolixBits) + return false; // Not strictly a COOLIX message. + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + + uint64_t data = 0; + uint64_t inverted = 0; + uint16_t offset = kStartOffset; + + if (nbits > sizeof(data) * 8) + return false; // We can't possibly capture a Coolix packet that big. + + // Header + if (!matchMark(results->rawbuf[offset], kCoolixHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kCoolixHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kCoolixHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = results->rawbuf[offset++] * kRawTick / kCoolixHdrSpaceTicks; + + // Data + // Twice as many bits as there are normal plus inverted bits. + for (uint16_t i = 0; i < nbits * 2; i++, offset++) { + bool flip = (i / 8) % 2; + if (!matchMark(results->rawbuf[offset++], kCoolixBitMarkTicks * m_tick)) + return false; + if (matchSpace(results->rawbuf[offset], kCoolixOneSpaceTicks * s_tick)) { + if (flip) + inverted = (inverted << 1) | 1; + else + data = (data << 1) | 1; + } else if (matchSpace(results->rawbuf[offset], + kCoolixZeroSpaceTicks * s_tick)) { + if (flip) + inverted <<= 1; + else + data <<= 1; + } else { + return false; + } + } + + // Footer + if (!matchMark(results->rawbuf[offset++], kCoolixBitMarkTicks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kCoolixMinGapTicks * s_tick)) + return false; + + // Compliance + uint64_t orig = data; // Save a copy of the data. + if (strict) { + for (uint16_t i = 0; i < nbits; i += 8, data >>= 8, inverted >>= 8) + if ((data & 0xFF) != ((inverted & 0xFF) ^ 0xFF)) return false; + } + + // Success + results->decode_type = COOLIX; + results->bits = nbits; + results->value = orig; + results->address = 0; + results->command = 0; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h new file mode 100644 index 000000000..ee4552074 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h @@ -0,0 +1,139 @@ +// Coolix A/C +// +// Copyright 2018 David Conran + +#ifndef IR_COOLIX_H_ +#define IR_COOLIX_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// CCCCC OOOOO OOOOO LL IIIII XX XX +// CC C OO OO OO OO LL III XX XX +// CC OO OO OO OO LL III XXXX +// CC C OO OO OO OO LL III XX XX +// CCCCC OOOO0 OOOO0 LLLLLLL IIIII XX XX + +// Supports: +// RG57K7(B)/BGEF remote control for Beko BINR 070/071 split-type aircon. +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/484 +// Kudos: +// Hamper: For the breakdown and mapping of the bit values. + +// Constants +// Modes +const uint8_t kCoolixCool = 0b00; +const uint8_t kCoolixDry = 0b01; +const uint8_t kCoolixAuto = 0b10; +const uint8_t kCoolixHeat = 0b11; +const uint8_t kCoolixFan = 4; // Synthetic. +const uint32_t kCoolixModeMask = 0b000000000000000000001100; // 0xC +const uint32_t kCoolixZoneFollowMask = 0b000010000000000000000000; // 0x80000 +// Fan Control +const uint8_t kCoolixFanMin = 0b100; +const uint8_t kCoolixFanMed = 0b010; +const uint8_t kCoolixFanMax = 0b001; +const uint8_t kCoolixFanAuto = 0b101; +const uint8_t kCoolixFanZoneFollow = 0b110; +const uint8_t kCoolixFanFixed = 0b111; +const uint32_t kCoolixFanMask = 0b000000001110000000000000; // 0x00E000 +// Temperature +const uint8_t kCoolixTempMin = 17; // Celsius +const uint8_t kCoolixTempMax = 30; // Celsius +const uint8_t kCoolixTempRange = kCoolixTempMax - kCoolixTempMin + 1; +const uint8_t kCoolixFanTempCode = 0b1110; // Part of Fan Mode. +const uint32_t kCoolixTempMask = 0b11110000; +const uint8_t kCoolixTempMap[kCoolixTempRange] = { + 0b0000, // 17C + 0b0001, // 18c + 0b0011, // 19C + 0b0010, // 20C + 0b0110, // 21C + 0b0111, // 22C + 0b0101, // 23C + 0b0100, // 24C + 0b1100, // 25C + 0b1101, // 26C + 0b1001, // 27C + 0b1000, // 28C + 0b1010, // 29C + 0b1011 // 30C +}; +const uint8_t kCoolixSensorTempMin = 16; // Celsius +const uint8_t kCoolixSensorTempMax = 30; // Celsius +const uint8_t kCoolixSensorTempIgnoreCode = 0b1111; +const uint32_t kCoolixSensorTempMask = 0b000000000000111100000000; // 0xF00 +// Fixed states/messages. +const uint8_t kCoolixPrefix = 0b1011; // 0xB +const uint8_t kCoolixUnknown = 0xFF; +const uint32_t kCoolixOff = 0b101100100111101111100000; // 0xB27BE0 +const uint32_t kCoolixSwing = 0b101100100110101111100000; // 0xB26BE0 +const uint32_t kCoolixSleep = 0b101100101110000000000011; // 0xB2E003 +const uint32_t kCoolixTurbo = 0b101101011111010110100010; // 0xB5F5A2 +const uint32_t kCoolixLed = 0b101101011111010110100101; // 0xB5F5A5 +const uint32_t kCoolixClean = 0b101101011111010110101010; // 0xB5F5AA +// On, 25C, Mode: Auto, Fan: Auto, Zone Follow: Off, Sensor Temp: Ignore. +const uint32_t kCoolixDefaultState = 0b101100101011111111001000; // 0xB2BFC8 + +// Classes +class IRCoolixAC { + public: + explicit IRCoolixAC(uint16_t pin); + + void stateReset(); +#if SEND_COOLIX + void send(); +#endif // SEND_COOLIX + void begin(); + void on(); + void off(); + void setPower(const bool state); + bool getPower(); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setSensorTemp(const uint8_t desired); + uint8_t getSensorTemp(); + void clearSensorTemp(); + void setFan(const uint8_t fan); + uint8_t getFan(); + void setMode(const uint8_t mode); + uint8_t getMode(); + void setSwing(); + bool getSwing(); + void setSleep(); + bool getSleep(); + void setTurbo(); + bool getTurbo(); + void setLed(); + bool getLed(); + void setClean(); + bool getClean(); + bool getZoneFollow(); + uint32_t getRaw(); + void setRaw(const uint32_t new_code); + +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: + // The state of the IR remote in IR code form. + uint32_t remote_state; + IRsend _irsend; + void setTempRaw(const uint8_t code); + uint8_t getTempRaw(); + void setSensorTempRaw(const uint8_t code); + void setZoneFollow(const bool state); +}; + +#endif // IR_COOLIX_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.cpp new file mode 100644 index 000000000..b94b4a63a --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.cpp @@ -0,0 +1,750 @@ +/* +An Arduino sketch to emulate IR Daikin ARC433** remote control unit +Read more at: +http://harizanov.com/2012/02/control-daikin-air-conditioner-over-the-internet/ + +Copyright 2016 sillyfrog +Copyright 2017 sillyfrog, crankyoldgit +*/ + +#include "ir_Daikin.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRutils.h" + +// DDDDD AAA IIIII KK KK IIIII NN NN +// DD DD AAAAA III KK KK III NNN NN +// DD DD AA AA III KKKK III NN N NN +// DD DD AAAAAAA III KK KK III NN NNN +// DDDDDD AA AA IIIII KK KK IIIII NN NN + +// Constants +// Ref: +// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote +// http://rdlab.cdmt.vn/project-2013/daikin-ir-protocol + +#if SEND_DAIKIN +// Original header +// static uint8_t header1[DAIKIN_HEADER1_LENGTH]; +// header1[0] = 0b00010001; +// header1[1] = 0b11011010; +// header1[2] = 0b00100111; +// header1[3] = 0b00000000; +// header1[4] = 0b11000101; +// header1[5] = 0b00000000; +// header1[6] = 0b00000000; +// header1[7] = 0b11010111; + +// Send a Daikin A/C message. +// +// Args: +// data: An array of kDaikinStateLength bytes containing the IR command. +// +// Status: STABLE +// +// Ref: +// IRDaikinESP.cpp +// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote +void IRsend::sendDaikin(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kDaikinStateLength) + return; // Not enough bytes to send a proper message. + + for (uint16_t r = 0; r <= repeat; r++) { + // Send the header, 0b00000 + sendGeneric(0, 0, // No header for the header + kDaikinBitMark, kDaikinOneSpace, kDaikinBitMark, + kDaikinZeroSpace, kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, + (uint64_t)0b00000, 5, 38, false, 0, 50); + // Leading header + // Do this as a constant to save RAM and keep in flash memory + sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, + kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, + kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, + kDaikinFirstHeader64, 64, 38, false, 0, 50); + // Data #1 + sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, + kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, + kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, data, 8, 38, + false, 0, 50); + // Data #2 + sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, + kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, + kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, data + 8, + nbytes - 8, 38, false, 0, 50); + } +} +#endif // SEND_DAIKIN + +IRDaikinESP::IRDaikinESP(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRDaikinESP::begin() { _irsend.begin(); } + +#if SEND_DAIKIN +void IRDaikinESP::send() { + checksum(); + _irsend.sendDaikin(daikin); +} +#endif // SEND_DAIKIN + +// Calculate the checksum for a given data block. +// Args: +// block: Ptr to the start of the data block. +// length: Nr. of bytes to checksum. +// Returns: +// A byte containing the calculated checksum. +uint8_t IRDaikinESP::calcBlockChecksum(const uint8_t *block, + const uint16_t length) { + uint8_t sum = 0; + // Daikin checksum is just the addition of all the data bytes + // in the block but capped to 8 bits. + for (uint16_t i = 0; i < length; i++, block++) sum += *block; + return sum & 0xFFU; +} + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRDaikinESP::validChecksum(const uint8_t state[], const uint16_t length) { + if (length < 8 || state[7] != calcBlockChecksum(state, 7)) return false; + if (length < 10 || + state[length - 1] != calcBlockChecksum(state + 8, length - 9)) + return false; + return true; +} + +// Calculate and set the checksum values for the internal state. +void IRDaikinESP::checksum() { + daikin[7] = calcBlockChecksum(daikin, 7); + daikin[26] = calcBlockChecksum(daikin + 8, 17); +} + +void IRDaikinESP::stateReset() { + for (uint8_t i = 0; i < kDaikinStateLength; i++) daikin[i] = 0x0; + + daikin[0] = 0x11; + daikin[1] = 0xDA; + daikin[2] = 0x27; + daikin[4] = 0x42; + // daikin[7] is a checksum byte, it will be set by checksum(). + daikin[8] = 0x11; + daikin[9] = 0xDA; + daikin[10] = 0x27; + daikin[13] = 0x49; + daikin[14] = 0x1E; + daikin[16] = 0xB0; + daikin[19] = 0x06; + daikin[20] = 0x60; + daikin[23] = 0xC0; + // daikin[26] is a checksum byte, it will be set by checksum(). + checksum(); +} + +uint8_t *IRDaikinESP::getRaw() { + checksum(); // Ensure correct settings before sending. + return daikin; +} + +void IRDaikinESP::setRaw(uint8_t new_code[]) { + for (uint8_t i = 0; i < kDaikinStateLength; i++) daikin[i] = new_code[i]; +} + +void IRDaikinESP::on() { + // state = ON; + setBit(kDaikinBytePower, kDaikinBitPower); +} + +void IRDaikinESP::off() { + // state = OFF; + clearBit(kDaikinBytePower, kDaikinBitPower); +} + +void IRDaikinESP::setPower(bool state) { + if (state) + on(); + else + off(); +} + +bool IRDaikinESP::getPower() { + return (getBit(kDaikinBytePower, kDaikinBitPower) > 0); +} + +// Set the temp in deg C +void IRDaikinESP::setTemp(uint8_t temp) { + if (temp < kDaikinMinTemp) + temp = kDaikinMinTemp; + else if (temp > kDaikinMaxTemp) + temp = kDaikinMaxTemp; + daikin[14] = temp * 2; +} + +uint8_t IRDaikinESP::getTemp() { return daikin[14] / 2; } + +// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet +void IRDaikinESP::setFan(uint8_t fan) { + // Set the fan speed bits, leave low 4 bits alone + uint8_t fanset; + if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto) + fanset = fan; + else if (fan < kDaikinFanMin || fan > kDaikinFanMax) + fanset = kDaikinFanAuto; + else + fanset = 2 + fan; + daikin[16] &= 0x0F; + daikin[16] |= (fanset << 4); +} + +uint8_t IRDaikinESP::getFan() { + uint8_t fan = daikin[16] >> 4; + if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2; + return fan; +} + +uint8_t IRDaikinESP::getMode() { + /* + kDaikinCool + kDaikinHeat + kDaikinFan + kDaikinAuto + kDaikinDry + */ + return daikin[13] >> 4; +} + +void IRDaikinESP::setMode(uint8_t mode) { + switch (mode) { + case kDaikinCool: + case kDaikinHeat: + case kDaikinFan: + case kDaikinDry: + break; + default: + mode = kDaikinAuto; + } + mode <<= 4; + daikin[13] &= 0b10001111; + daikin[13] |= mode; +} + +void IRDaikinESP::setSwingVertical(bool state) { + if (state) + daikin[16] |= 0x0F; + else + daikin[16] &= 0xF0; +} + +bool IRDaikinESP::getSwingVertical() { return daikin[16] & 0x01; } + +void IRDaikinESP::setSwingHorizontal(bool state) { + if (state) + daikin[17] |= 0x0F; + else + daikin[17] &= 0xF0; +} + +bool IRDaikinESP::getSwingHorizontal() { return daikin[17] & 0x01; } + +void IRDaikinESP::setQuiet(bool state) { + if (state) { + setBit(kDaikinByteSilent, kDaikinBitSilent); + // Powerful & Quiet mode being on are mutually exclusive. + setPowerful(false); + } else { + clearBit(kDaikinByteSilent, kDaikinBitSilent); + } +} + +bool IRDaikinESP::getQuiet() { + return (getBit(kDaikinByteSilent, kDaikinBitSilent) > 0); +} + +void IRDaikinESP::setPowerful(bool state) { + if (state) { + setBit(kDaikinBytePowerful, kDaikinBitPowerful); + // Powerful, Quiet, & Econo mode being on are mutually exclusive. + setQuiet(false); + setEcono(false); + } else { + clearBit(kDaikinBytePowerful, kDaikinBitPowerful); + } +} + +bool IRDaikinESP::getPowerful() { + return (getBit(kDaikinBytePowerful, kDaikinBitPowerful) > 0); +} + +void IRDaikinESP::setSensor(bool state) { + if (state) + setBit(kDaikinByteSensor, kDaikinBitSensor); + else + clearBit(kDaikinByteSensor, kDaikinBitSensor); +} + +bool IRDaikinESP::getSensor() { + return (getBit(kDaikinByteSensor, kDaikinBitSensor) > 0); +} + +void IRDaikinESP::setEcono(bool state) { + if (state) { + setBit(kDaikinByteEcono, kDaikinBitEcono); + // Powerful & Econo mode being on are mutually exclusive. + setPowerful(false); + } else { + clearBit(kDaikinByteEcono, kDaikinBitEcono); + } +} + +bool IRDaikinESP::getEcono() { + return (getBit(kDaikinByteEcono, kDaikinBitEcono) > 0); +} + +void IRDaikinESP::setEye(bool state) { + if (state) + setBit(kDaikinByteEye, kDaikinBitEye); + else + clearBit(kDaikinByteEye, kDaikinBitEye); +} + +bool IRDaikinESP::getEye() { + return (getBit(kDaikinByteEye, kDaikinBitEye) > 0); +} + +void IRDaikinESP::setMold(bool state) { + if (state) + setBit(kDaikinByteMold, kDaikinBitMold); + else + clearBit(kDaikinByteMold, kDaikinBitMold); +} + +bool IRDaikinESP::getMold() { + return (getBit(kDaikinByteMold, kDaikinBitMold) > 0); +} + +void IRDaikinESP::setBit(uint8_t byte, uint8_t bitmask) { + daikin[byte] |= bitmask; +} + +void IRDaikinESP::clearBit(uint8_t byte, uint8_t bitmask) { + bitmask = ~bitmask; + daikin[byte] &= bitmask; +} + +uint8_t IRDaikinESP::getBit(uint8_t byte, uint8_t bitmask) { + return daikin[byte] & bitmask; +} + +// starttime: Number of minutes after midnight, in 10 minutes increments +void IRDaikinESP::enableOnTimer(uint16_t starttime) { + setBit(kDaikinByteOnTimer, kDaikinBitOnTimer); + daikin[18] = (uint8_t)(starttime & 0x00FF); + // only keep 4 bits + daikin[19] &= 0xF0; + daikin[19] |= (uint8_t)((starttime >> 8) & 0x0F); +} + +void IRDaikinESP::disableOnTimer() { + enableOnTimer(0x600); + clearBit(kDaikinByteOnTimer, kDaikinBitOnTimer); +} + +uint16_t IRDaikinESP::getOnTime() { + uint16_t ret; + ret = daikin[19] & 0x0F; + ret = ret << 8; + ret += daikin[18]; + return ret; +} + +bool IRDaikinESP::getOnTimerEnabled() { + return getBit(kDaikinByteOnTimer, kDaikinBitOnTimer); +} + +// endtime: Number of minutes after midnight, in 10 minutes increments +void IRDaikinESP::enableOffTimer(uint16_t endtime) { + setBit(kDaikinByteOffTimer, kDaikinBitOffTimer); + daikin[20] = (uint8_t)((endtime >> 4) & 0xFF); + daikin[19] &= 0x0F; + daikin[19] |= (uint8_t)((endtime & 0x000F) << 4); +} + +void IRDaikinESP::disableOffTimer() { + enableOffTimer(0x600); + clearBit(kDaikinByteOffTimer, kDaikinBitOffTimer); +} + +uint16_t IRDaikinESP::getOffTime() { + uint16_t ret, tmp; + ret = daikin[20]; + ret <<= 4; + tmp = daikin[19] & 0xF0; + tmp >>= 4; + ret += tmp; + return ret; +} + +bool IRDaikinESP::getOffTimerEnabled() { + return getBit(kDaikinByteOffTimer, kDaikinBitOffTimer); +} + +void IRDaikinESP::setCurrentTime(uint16_t numMins) { + if (numMins > 24 * 60) numMins = 0; // If > 23:59, set to 00:00 + daikin[5] = (uint8_t)(numMins & 0x00FF); + // only keep 4 bits + daikin[6] &= 0xF0; + daikin[6] |= (uint8_t)((numMins >> 8) & 0x0F); +} + +uint16_t IRDaikinESP::getCurrentTime() { + uint16_t ret; + ret = daikin[6] & 0x0F; + ret <<= 8; + ret += daikin[5]; + return ret; +} + +#ifdef ARDUINO +String IRDaikinESP::renderTime(uint16_t timemins) { + String ret; +#else // ARDUINO +std::string IRDaikinESP::renderTime(uint16_t timemins) { + std::string ret; +#endif // ARDUINO + uint16_t hours, mins; + hours = timemins / 60; + ret = uint64ToString(hours) + ":"; + mins = timemins - (hours * 60); + if (mins < 10) ret += "0"; + ret += uint64ToString(mins); + return ret; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRDaikinESP::toString() { + String result = ""; +#else // ARDUINO +std::string IRDaikinESP::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kDaikinAuto: + result += " (AUTO)"; + break; + case kDaikinCool: + result += " (COOL)"; + break; + case kDaikinHeat: + result += " (HEAT)"; + break; + case kDaikinDry: + result += " (DRY)"; + break; + case kDaikinFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kDaikinFanAuto: + result += " (AUTO)"; + break; + case kDaikinFanQuiet: + result += " (QUIET)"; + break; + case kDaikinFanMin: + result += " (MIN)"; + break; + case kDaikinFanMax: + result += " (MAX)"; + break; + } + result += ", Powerful: "; + if (getPowerful()) + result += "On"; + else + result += "Off"; + result += ", Quiet: "; + if (getQuiet()) + result += "On"; + else + result += "Off"; + result += ", Sensor: "; + if (getSensor()) + result += "On"; + else + result += "Off"; + result += ", Eye: "; + if (getEye()) + result += "On"; + else + result += "Off"; + result += ", Mold: "; + if (getMold()) + result += "On"; + else + result += "Off"; + result += ", Swing (Horizontal): "; + if (getSwingHorizontal()) + result += "On"; + else + result += "Off"; + result += ", Swing (Vertical): "; + if (getSwingVertical()) + result += "On"; + else + result += "Off"; + result += ", Current Time: " + renderTime(getCurrentTime()); + result += ", On Time: "; + if (getOnTimerEnabled()) + result += renderTime(getOnTime()); + else + result += "Off"; + result += ", Off Time: "; + if (getOffTimerEnabled()) + result += renderTime(getOffTime()); + else + result += "Off"; + + return result; +} + +#if DAIKIN_DEBUG +// Print what we have +void IRDaikinESP::printState() { +#ifdef ARDUINO + String strbits; +#else // ARDUINO + std::string strbits; +#endif // ARDUINO + DPRINTLN("Raw Bits:"); + for (uint8_t i = 0; i < kDaikinStateLength; i++) { + strbits = uint64ToString(daikin[i], BIN); + while (strbits.length() < 8) strbits = "0" + strbits; + DPRINT(strbits); + DPRINT(" "); + } + DPRINTLN(""); + DPRINTLN(toString()); +} +#endif // DAIKIN_DEBUG + +/* + * Return most important bits to allow replay + * layout is: + * 0: Power + * 1-3: Mode + * 4-7: Fan speed/mode + * 8-14: Target Temperature + * 15: Econo + * 16: Powerful + * 17: Quiet + * 18: Sensor + * 19: Swing Vertical + * 20-31: Current time (mins since midnight) + * */ +uint32_t IRDaikinESP::getCommand() { + uint32_t ret = 0; + uint32_t tmp = 0; + if (getPower()) ret |= 0b00000000000000000000000000000001; + tmp = getMode(); + tmp = tmp << 1; + ret |= tmp; + + tmp = getFan(); + tmp <<= 4; + ret |= tmp; + + tmp = getTemp(); + tmp <<= 8; + ret |= tmp; + + if (getEcono()) ret |= 0b00000000000000001000000000000000; + if (getPowerful()) ret |= 0b00000000000000010000000000000000; + if (getQuiet()) ret |= 0b00000000000000100000000000000000; + if (getSensor()) ret |= 0b00000000000001000000000000000000; + if (getSwingVertical()) ret |= 0b00000000000010000000000000000000; + ret |= (getCurrentTime() << 20); + return ret; +} + +void IRDaikinESP::setCommand(uint32_t value) { + uint32_t tmp = 0; + if (value & 0b00000000000000000000000000000001) setPower(true); + tmp = value & 0b00000000000000000000000000001110; + tmp >>= 1; + setMode(tmp); + + tmp = value & 0b00000000000000000000000011110000; + tmp >>= 4; + setFan(tmp); + + tmp = value & 0b00000000000000000111111100000000; + tmp >>= 8; + setTemp(tmp); + + if (value & 0b00000000000000001000000000000000) setEcono(true); + if (value & 0b00000000000000010000000000000000) setPowerful(true); + if (value & 0b00000000000000100000000000000000) setQuiet(true); + if (value & 0b00000000000001000000000000000000) setSensor(true); + if (value & 0b00000000000010000000000000000000) setSwingVertical(true); + + value >>= 20; + setCurrentTime(value); +} + +#if DECODE_DAIKIN + +void addbit(bool val, unsigned char data[]) { + uint8_t curbit = data[kDaikinCurBit]; + uint8_t curindex = data[kDaikinCurIndex]; + if (val) { + unsigned char bit = 1; + bit = bit << curbit; + data[curindex] |= bit; + } + curbit++; + if (curbit == 8) { + curbit = 0; + curindex++; + } + data[kDaikinCurBit] = curbit; + data[kDaikinCurIndex] = curindex; +} + +bool checkheader(decode_results *results, uint16_t *offset) { + if (!IRrecv::matchMark(results->rawbuf[(*offset)++], kDaikinBitMark, + kDaikinTolerance, kDaikinMarkExcess)) + return false; + if (!IRrecv::matchSpace(results->rawbuf[(*offset)++], + kDaikinZeroSpace + kDaikinGap, kDaikinTolerance, + kDaikinMarkExcess)) + return false; + if (!IRrecv::matchMark(results->rawbuf[(*offset)++], kDaikinHdrMark, + kDaikinTolerance, kDaikinMarkExcess)) + return false; + if (!IRrecv::matchSpace(results->rawbuf[(*offset)++], kDaikinHdrSpace, + kDaikinTolerance, kDaikinMarkExcess)) + return false; + + return true; +} + +bool readbits(decode_results *results, uint16_t *offset, + unsigned char daikin_code[], uint16_t countbits) { + for (uint16_t i = 0; i < countbits && *offset < results->rawlen - 1; + i++, (*offset)++) { + if (!IRrecv::matchMark(results->rawbuf[(*offset)++], kDaikinBitMark, + kDaikinTolerance, kDaikinMarkExcess)) + return false; + if (IRrecv::matchSpace(results->rawbuf[*offset], kDaikinOneSpace, + kDaikinTolerance, kDaikinMarkExcess)) + addbit(1, daikin_code); + else if (IRrecv::matchSpace(results->rawbuf[*offset], kDaikinZeroSpace, + kDaikinTolerance, kDaikinMarkExcess)) + addbit(0, daikin_code); + else + return false; + } + return true; +} + +// Decode the supplied Daikin A/C message. +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. (kDaikinRawBits) +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Should be working. +// +// Notes: +// If DAIKIN_DEBUG enabled, will print all the set options and values. +// +// Ref: +// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote +bool IRrecv::decodeDaikin(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < kDaikinRawBits) return false; + + // Compliance + if (strict && nbits != kDaikinRawBits) return false; + + uint16_t offset = kStartOffset; + unsigned char daikin_code[kDaikinStateLength + 2]; + for (uint8_t i = 0; i < kDaikinStateLength + 2; i++) daikin_code[i] = 0; + + // Header (#1) + for (uint8_t i = 0; i < 10; i++) { + if (!matchMark(results->rawbuf[offset++], kDaikinBitMark)) return false; + } + if (!checkheader(results, &offset)) return false; + + // Data (#1) + if (!readbits(results, &offset, daikin_code, 8 * 8)) return false; + + // Ignore everything that has just been captured as it is not needed. + // Some remotes may not send this portion, my remote did, but it's not + // required. + for (uint8_t i = 0; i < kDaikinStateLength + 2; i++) daikin_code[i] = 0; + + // Header (#2) + if (!checkheader(results, &offset)) return false; + + // Data (#2) + if (!readbits(results, &offset, daikin_code, 8 * 8)) return false; + + // Header (#3) + if (!checkheader(results, &offset)) return false; + + // Data (#3), read up everything else + if (!readbits(results, &offset, daikin_code, kDaikinBits - (8 * 8))) + return false; + + // Footer + if (!matchMark(results->rawbuf[offset++], kDaikinBitMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kDaikinGap)) + return false; + + // Compliance + if (strict) { + if (!IRDaikinESP::validChecksum(daikin_code)) return false; + } + + // Success +#if DAIKIN_DEBUG + IRDaikinESP dako = IRDaikinESP(0); + dako.setRaw(daikin_code); +#ifdef ARDUINO + yield(); +#endif // ARDUINO + dako.printState(); +#endif // DAIKIN_DEBUG + + // Copy across the bits to state + for (uint8_t i = 0; i < kDaikinStateLength; i++) + results->state[i] = daikin_code[i]; + results->bits = kDaikinStateLength * 8; + results->decode_type = DAIKIN; + return true; +} +#endif // DECODE_DAIKIN diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h new file mode 100644 index 000000000..7094990d8 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h @@ -0,0 +1,208 @@ +// Copyright 2016 sillyfrog +// Copyright 2017 sillyfrog, crankyoldgit +#ifndef IR_DAIKIN_H_ +#define IR_DAIKIN_H_ + +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// Option to disable the additional Daikin debug info to conserve memory +#define DAIKIN_DEBUG false + +// DDDDD AAA IIIII KK KK IIIII NN NN +// DD DD AAAAA III KK KK III NNN NN +// DD DD AA AA III KKKK III NN N NN +// DD DD AAAAAAA III KK KK III NN NNN +// DDDDDD AA AA IIIII KK KK IIIII NN NN + +/* + Daikin AC map + byte 5=Current time, mins past midnight, low bits + byte 6 + b0-b3=Current time, mins past midnight, high bits + byte 7= checksum of the first part (and last byte before a 29ms pause) + byte 13=mode + b7 = 0 + b6+b5+b4 = Mode + Modes: b6+b5+b4 + 011 = Cool + 100 = Heat (temp 23) + 110 = FAN (temp not shown, but 25) + 000 = Fully Automatic (temp 25) + 010 = DRY (temp 0xc0 = 96 degrees c) + b3 = 1 + b2 = OFF timer set + b1 = ON timer set + b0 = Air Conditioner ON + byte 14=temp*2 (Temp should be between 10 - 32) + byte 16=Fan + FAN control + b7+b6+b5+b4 = Fan speed + Fan: b7+b6+b5+b4 + 0×3 = 1 bar + 0×4 = 2 bar + 0×5 = 3 bar + 0×6 = 4 bar + 0×7 = 5 bar + 0xa = Auto + 0xb = Quite + b3+b2+b1+b0 = Swing control up/down + Swing control up/down: + 0000 = Swing up/down off + 1111 = Swing up/down on + byte 17 + Swing control left/right: + 0000 = Swing left/right off + 1111 = Swing left/right on + byte 18=On timer mins past midnight, low bits + byte 19 + b0-b3=On timer mins past midnight, high bits + b4-b7=Off timer mins past midnight, low bits + byte 20=Off timer mins past midnight, high bits + byte 21=Aux -> Powerful (bit 1), Silent (bit 5) + byte 24=Aux2 + b1: Sensor + b2: Econo mode + b7: Intelligent eye on + byte 25=Aux3 + b1: Mold Proof + byte 26= checksum of the second part +*/ + +// Constants +const uint8_t kDaikinAuto = 0b000; +const uint8_t kDaikinDry = 0b010; +const uint8_t kDaikinCool = 0b011; +const uint8_t kDaikinHeat = 0b100; +const uint8_t kDaikinFan = 0b110; +const uint8_t kDaikinMinTemp = 10; // Celsius +const uint8_t kDaikinMaxTemp = 32; // Celsius +const uint8_t kDaikinFanMin = 1; +const uint8_t kDaikinFanMax = 5; +const uint8_t kDaikinFanAuto = 0b1010; +const uint8_t kDaikinFanQuiet = 0b1011; +const uint8_t kDaikinBytePower = 13; +const uint8_t kDaikinBitPower = 0b00000001; +const uint8_t kDaikinBytePowerful = 21; +const uint8_t kDaikinBitPowerful = 0b00000001; +const uint8_t kDaikinByteSilent = 21; +const uint8_t kDaikinBitSilent = 0b00100000; +const uint8_t kDaikinByteSensor = 24; +const uint8_t kDaikinBitSensor = 0b00000010; +const uint8_t kDaikinByteEcono = 24; +const uint8_t kDaikinBitEcono = 0b00000100; +const uint8_t kDaikinByteEye = 24; +const uint8_t kDaikinBitEye = 0b10000000; +const uint8_t kDaikinByteMold = 25; +const uint8_t kDaikinBitMold = 0b00000010; +const uint8_t kDaikinByteOffTimer = 13; +const uint8_t kDaikinBitOffTimer = 0b00000100; +const uint8_t kDaikinByteOnTimer = 13; +const uint8_t kDaikinBitOnTimer = 0b00000010; +const uint8_t kDaikinCurBit = kDaikinStateLength; +const uint8_t kDaikinCurIndex = kDaikinStateLength + 1; +const uint8_t kDaikinTolerance = 35; +const uint16_t kDaikinMarkExcess = kMarkExcess; +const uint16_t kDaikinHdrMark = 3650; // kDaikinBitMark * 8 +const uint16_t kDaikinHdrSpace = 1623; // kDaikinBitMark * 4 +const uint16_t kDaikinBitMark = 428; +const uint16_t kDaikinZeroSpace = 428; +const uint16_t kDaikinOneSpace = 1280; +const uint16_t kDaikinGap = 29000; +// Note bits in each octet swapped so can be sent as a single value +const uint64_t kDaikinFirstHeader64 = + 0b1101011100000000000000001100010100000000001001111101101000010001; + +// Legacy defines. +#define DAIKIN_COOL kDaikinCool +#define DAIKIN_HEAT kDaikinHeat +#define DAIKIN_FAN kDaikinFan +#define DAIKIN_AUTO kDaikinAuto +#define DAIKIN_DRY kDaikinDry +#define DAIKIN_MIN_TEMP kDaikinMinTemp +#define DAIKIN_MAX_TEMP kDaikinMaxTemp +#define DAIKIN_FAN_MIN kDaikinFanMin +#define DAIKIN_FAN_MAX kDaikinFanMax +#define DAIKIN_FAN_AUTO kDaikinFanAuto +#define DAIKIN_FAN_QUIET kDaikinFanQuiet + +class IRDaikinESP { + public: + explicit IRDaikinESP(uint16_t pin); + +#if SEND_DAIKIN + void send(); +#endif + void begin(); + void on(); + void off(); + void setPower(bool state); + bool getPower(); + void setTemp(uint8_t temp); + uint8_t getTemp(); + void setFan(uint8_t fan); + uint8_t getFan(); + uint8_t getMode(); + void setMode(uint8_t mode); + void setSwingVertical(bool state); + bool getSwingVertical(); + void setSwingHorizontal(bool state); + bool getSwingHorizontal(); + bool getQuiet(); + void setQuiet(bool state); + bool getPowerful(); + void setPowerful(bool state); + void setSensor(bool state); + bool getSensor(); + void setEcono(bool state); + bool getEcono(); + void setEye(bool state); + bool getEye(); + void setMold(bool state); + bool getMold(); + void enableOnTimer(uint16_t starttime); + void disableOnTimer(); + uint16_t getOnTime(); + bool getOnTimerEnabled(); + void enableOffTimer(uint16_t endtime); + void disableOffTimer(); + uint16_t getOffTime(); + bool getOffTimerEnabled(); + void setCurrentTime(uint16_t time); + uint16_t getCurrentTime(); + uint8_t* getRaw(); + void setRaw(uint8_t new_code[]); +#if DAIKIN_DEBUG + void printState(); +#endif // DAIKIN_DEBUG + uint32_t getCommand(); + void setCommand(uint32_t value); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kDaikinStateLength); +#ifdef ARDUINO + String toString(); + static String renderTime(uint16_t timemins); +#else + std::string toString(); + static std::string renderTime(uint16_t timemins); +#endif + + private: + // # of bytes per command + uint8_t daikin[kDaikinStateLength]; + void stateReset(); + static uint8_t calcBlockChecksum(const uint8_t* block, const uint16_t length); + void checksum(); + void setBit(uint8_t byte, uint8_t bitmask); + void clearBit(uint8_t byte, uint8_t bitmask); + uint8_t getBit(uint8_t byte, uint8_t bitmask); + IRsend _irsend; +}; + +#endif // IR_DAIKIN_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Denon.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Denon.cpp similarity index 59% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Denon.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Denon.cpp index 538e5af10..6798e022e 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Denon.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Denon.cpp @@ -4,7 +4,6 @@ #include #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" #include "IRutils.h" // DDDD EEEEE N N OOO N N @@ -19,25 +18,25 @@ // Constants // Ref: // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Denon.cpp -#define DENON_TICK 263U -#define DENON_HDR_MARK_TICKS 1U -#define DENON_HDR_MARK (DENON_HDR_MARK_TICKS * DENON_TICK) -#define DENON_HDR_SPACE_TICKS 3U -#define DENON_HDR_SPACE (DENON_HDR_SPACE_TICKS * DENON_TICK) -#define DENON_BIT_MARK_TICKS 1U -#define DENON_BIT_MARK (DENON_BIT_MARK_TICKS * DENON_TICK) -#define DENON_ONE_SPACE_TICKS 7U -#define DENON_ONE_SPACE (DENON_ONE_SPACE_TICKS * DENON_TICK) -#define DENON_ZERO_SPACE_TICKS 3U -#define DENON_ZERO_SPACE (DENON_ZERO_SPACE_TICKS * DENON_TICK) -#define DENON_MIN_COMMAND_LENGTH_TICKS 510U -#define DENON_MIN_COMMAND_LENGTH (DENON_MIN_COMMAND_LENGTH_TICKS * DENON_TICK) -#define DENON_MIN_GAP_TICKS (DENON_MIN_COMMAND_LENGTH_TICKS - \ - (DENON_HDR_MARK_TICKS + DENON_HDR_SPACE_TICKS + \ - DENON_BITS * (DENON_BIT_MARK_TICKS + DENON_ONE_SPACE_TICKS) + \ - DENON_BIT_MARK_TICKS)) -#define DENON_MIN_GAP (DENON_MIN_GAP_TICKS * DENON_TICK) -#define DENON_MANUFACTURER 0x2A4CULL +const uint16_t kDenonTick = 263; +const uint16_t kDenonHdrMarkTicks = 1; +const uint16_t kDenonHdrMark = kDenonHdrMarkTicks * kDenonTick; +const uint16_t kDenonHdrSpaceTicks = 3; +const uint16_t kDenonHdrSpace = kDenonHdrSpaceTicks * kDenonTick; +const uint16_t kDenonBitMarkTicks = 1; +const uint16_t kDenonBitMark = kDenonBitMarkTicks * kDenonTick; +const uint16_t kDenonOneSpaceTicks = 7; +const uint16_t kDenonOneSpace = kDenonOneSpaceTicks * kDenonTick; +const uint16_t kDenonZeroSpaceTicks = 3; +const uint16_t kDenonZeroSpace = kDenonZeroSpaceTicks * kDenonTick; +const uint16_t kDenonMinCommandLengthTicks = 510; +const uint16_t kDenonMinGapTicks = + kDenonMinCommandLengthTicks - + (kDenonHdrMarkTicks + kDenonHdrSpaceTicks + + kDenonBits * (kDenonBitMarkTicks + kDenonOneSpaceTicks) + + kDenonBitMarkTicks); +const uint32_t kDenonMinGap = kDenonMinGapTicks * kDenonTick; +const uint64_t kDenonManufacturer = 0x2A4CULL; #if SEND_DENON // Send a Denon message @@ -56,9 +55,9 @@ // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Denon.cpp // http://assets.denon.com/documentmaster/us/denon%20master%20ir%20hex.xls void IRsend::sendDenon(uint64_t data, uint16_t nbits, uint16_t repeat) { - if (nbits >= PANASONIC_BITS) // Is this really Panasonic? + if (nbits >= kPanasonicBits) // Is this really Panasonic? sendPanasonic64(data, nbits, repeat); - else if (nbits == DENON_LEGACY_BITS) + else if (nbits == kDenonLegacyBits) // Support legacy (broken) calls of sendDenon(). sendSharpRaw(data & (~0x2000ULL), nbits + 1, repeat); else @@ -85,7 +84,7 @@ bool IRrecv::decodeDenon(decode_results *results, uint16_t nbits, bool strict) { switch (nbits) { case DENON_BITS: case DENON_48_BITS: - case DENON_LEGACY_BITS: + case kDenonLegacyBits: break; default: return false; @@ -100,40 +99,36 @@ bool IRrecv::decodeDenon(decode_results *results, uint16_t nbits, bool strict) { // manufacturer code. if (!decodeSharp(results, nbits, true, false) && - !decodePanasonic(results, nbits, true, DENON_MANUFACTURER)) { + !decodePanasonic(results, nbits, true, kDenonManufacturer)) { // We couldn't decode it as expected, so try the old legacy method. // NOTE: I don't think this following protocol actually exists. // Looks like a partial version of the Sharp protocol. // Check we have enough data - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1) - return false; - if (strict && nbits != DENON_LEGACY_BITS) - return false; + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false; + if (strict && nbits != kDenonLegacyBits) return false; uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; // Header - if (!matchMark(results->rawbuf[offset], DENON_HDR_MARK)) return false; + if (!matchMark(results->rawbuf[offset], kDenonHdrMark)) return false; // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / - DENON_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], DENON_HDR_SPACE)) return false; - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / - DENON_HDR_SPACE_TICKS; + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kDenonHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kDenonHdrSpace)) return false; + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kDenonHdrSpaceTicks; // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - DENON_BIT_MARK_TICKS * m_tick, - DENON_ONE_SPACE_TICKS * s_tick, - DENON_BIT_MARK_TICKS * m_tick, - DENON_ZERO_SPACE_TICKS * s_tick); + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, + kDenonBitMarkTicks * m_tick, kDenonOneSpaceTicks * s_tick, + kDenonBitMarkTicks * m_tick, kDenonZeroSpaceTicks * s_tick); if (data_result.success == false) return false; data = data_result.data; offset += data_result.used; // Footer - if (!matchMark(results->rawbuf[offset++], DENON_BIT_MARK_TICKS * m_tick)) + if (!matchMark(results->rawbuf[offset++], kDenonBitMarkTicks * m_tick)) return false; // Success diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Dish.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Dish.cpp similarity index 59% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Dish.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Dish.cpp index 4555db92f..040aa3bf7 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Dish.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Dish.cpp @@ -3,7 +3,6 @@ #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" #include "IRutils.h" // DDDD IIIII SSSS H H @@ -19,19 +18,19 @@ // Ref: // https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Dish.cpp // http://www.hifi-remote.com/wiki/index.php?title=Dish -#define DISH_TICK 100U -#define DISH_HDR_MARK_TICKS 4U -#define DISH_HDR_MARK (DISH_HDR_MARK_TICKS * DISH_TICK) -#define DISH_HDR_SPACE_TICKS 61U -#define DISH_HDR_SPACE (DISH_HDR_SPACE_TICKS * DISH_TICK) -#define DISH_BIT_MARK_TICKS 4U -#define DISH_BIT_MARK (DISH_BIT_MARK_TICKS * DISH_TICK) -#define DISH_ONE_SPACE_TICKS 17U -#define DISH_ONE_SPACE (DISH_ONE_SPACE_TICKS * DISH_TICK) -#define DISH_ZERO_SPACE_TICKS 28U -#define DISH_ZERO_SPACE (DISH_ZERO_SPACE_TICKS * DISH_TICK) -#define DISH_RPT_SPACE_TICKS DISH_HDR_SPACE_TICKS -#define DISH_RPT_SPACE (DISH_RPT_SPACE_TICKS * DISH_TICK) +const uint16_t kDishTick = 100; +const uint16_t kDishHdrMarkTicks = 4; +const uint16_t kDishHdrMark = kDishHdrMarkTicks * kDishTick; +const uint16_t kDishHdrSpaceTicks = 61; +const uint16_t kDishHdrSpace = kDishHdrSpaceTicks * kDishTick; +const uint16_t kDishBitMarkTicks = 4; +const uint16_t kDishBitMark = kDishBitMarkTicks * kDishTick; +const uint16_t kDishOneSpaceTicks = 17; +const uint16_t kDishOneSpace = kDishOneSpaceTicks * kDishTick; +const uint16_t kDishZeroSpaceTicks = 28; +const uint16_t kDishZeroSpace = kDishZeroSpaceTicks * kDishTick; +const uint16_t kDishRptSpaceTicks = kDishHdrSpaceTicks; +const uint16_t kDishRptSpace = kDishRptSpaceTicks * kDishTick; #if SEND_DISH // Send an IR command to a DISH NETWORK device. @@ -56,20 +55,15 @@ // Ref: // http://www.hifi-remote.com/wiki/index.php?title=Dish void IRsend::sendDISH(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set 57.6kHz IR carrier frequency, duty cycle is unknown. - enableIROut(57600); - // Header - mark(DISH_HDR_MARK); - space(DISH_HDR_SPACE); - // We always send a command, even for repeat=0, hence '<= repeat'. - for (uint16_t i = 0; i <= repeat; i++) { - // Data - sendData(DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, - data, nbits, true); - // Footer - mark(DISH_BIT_MARK); - space(DISH_RPT_SPACE); - } + enableIROut(57600); // Set modulation freq. to 57.6kHz. + // Header is only ever sent once. + mark(kDishHdrMark); + space(kDishHdrSpace); + + sendGeneric(0, 0, // No headers from here on in. + kDishBitMark, kDishOneSpace, kDishBitMark, kDishZeroSpace, + kDishBitMark, kDishRptSpace, data, nbits, 57600, true, repeat, + 50); } #endif @@ -78,7 +72,7 @@ void IRsend::sendDISH(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. Typically DISH_BITS. +// nbits: Nr. of bits to expect in the data portion. Typically kDishBits. // strict: Flag to indicate if we strictly adhere to the specification. // Returns: // boolean: True if it can decode it, false if it can't. @@ -94,34 +88,32 @@ void IRsend::sendDISH(uint64_t data, uint16_t nbits, uint16_t repeat) { // http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx // https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Dish.cpp bool IRrecv::decodeDISH(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1) + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false; // Not enough entries to be valid. - if (strict && nbits != DISH_BITS) - return false; // Not strictly compliant. + if (strict && nbits != kDishBits) return false; // Not strictly compliant. uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; // Header - if (!match(results->rawbuf[offset], DISH_HDR_MARK)) return false; + if (!match(results->rawbuf[offset], kDishHdrMark)) return false; // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / DISH_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], DISH_HDR_SPACE)) return false; + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kDishHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kDishHdrSpace)) return false; // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / DISH_HDR_SPACE_TICKS; + uint32_t s_tick = results->rawbuf[offset++] * kRawTick / kDishHdrSpaceTicks; // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - DISH_BIT_MARK_TICKS * m_tick, - DISH_ONE_SPACE_TICKS * s_tick, - DISH_BIT_MARK_TICKS * m_tick, - DISH_ZERO_SPACE_TICKS * s_tick); + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kDishBitMarkTicks * m_tick, + kDishOneSpaceTicks * s_tick, kDishBitMarkTicks * m_tick, + kDishZeroSpaceTicks * s_tick); if (data_result.success == false) return false; data = data_result.data; offset += data_result.used; // Footer - if (!matchMark(results->rawbuf[offset++], DISH_BIT_MARK_TICKS * m_tick)) + if (!matchMark(results->rawbuf[offset++], kDishBitMarkTicks * m_tick)) return false; // Compliance @@ -129,7 +121,7 @@ bool IRrecv::decodeDISH(decode_results *results, uint16_t nbits, bool strict) { // The DISH protocol calls for a repeated message, so strictly speaking // there should be a code following this. Only require it if we are set to // strict matching. - if (!matchSpace(results->rawbuf[offset], DISH_RPT_SPACE_TICKS * s_tick)) + if (!matchSpace(results->rawbuf[offset], kDishRptSpaceTicks * s_tick)) return false; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Electra.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Electra.cpp new file mode 100644 index 000000000..df69be748 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Electra.cpp @@ -0,0 +1,112 @@ +// Copyright 2018 David Conran + +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// EEEEEEE LL EEEEEEE CCCCC TTTTTTT RRRRRR AAA +// EE LL EE CC C TTT RR RR AAAAA +// EEEEE LL EEEEE CC TTT RRRRRR AA AA +// EE LL EE CC C TTT RR RR AAAAAAA +// EEEEEEE LLLLLLL EEEEEEE CCCCC TTT RR RR AA AA + +// Electra A/C added by crankyoldgit +// +// Equipment it seems compatible with: +// * + +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/527 + +// Constants +const uint16_t kElectraAcHdrMark = 9166; +const uint16_t kElectraAcBitMark = 646; +const uint16_t kElectraAcHdrSpace = 4470; +const uint16_t kElectraAcOneSpace = 1647; +const uint16_t kElectraAcZeroSpace = 547; +const uint32_t kElectraAcMessageGap = 100000; // Completely made-up guess. + +#if SEND_ELECTRA_AC +// Send a Electra message +// +// Args: +// data: Contents of the message to be sent. (Guessing MSBF order) +// nbits: Nr. of bits of data to be sent. Typically kElectraAcBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: Alpha / Needs testing against a real device. +// +void IRsend::sendElectraAC(uint8_t data[], uint16_t nbytes, uint16_t repeat) { + for (uint16_t r = 0; r <= repeat; r++) + sendGeneric(kElectraAcHdrMark, kElectraAcHdrSpace, kElectraAcBitMark, + kElectraAcOneSpace, kElectraAcBitMark, kElectraAcZeroSpace, + kElectraAcBitMark, kElectraAcMessageGap, data, nbytes, + 38000, // Complete guess of the modulation frequency. + true, 0, 50); +} +#endif + +#if DECODE_ELECTRA_AC +// Decode the supplied Electra A/C message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kElectraAcBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Alpha / Needs testing against a real device. +// +bool IRrecv::decodeElectraAC(decode_results *results, uint16_t nbits, + bool strict) { + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + + if (strict) { + if (nbits != kElectraAcBits) + return false; // Not strictly a ELECTRA_AC message. + } + + // The protocol sends the data normal + inverted, alternating on + // each byte. Hence twice the number of expected data bits. + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid ELECTRA_AC message. + + uint16_t offset = kStartOffset; + + // Message Header + if (!matchMark(results->rawbuf[offset++], kElectraAcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kElectraAcHdrSpace)) return false; + + // Data Section + match_result_t data_result; + uint16_t dataBitsSoFar = 0; + // Keep reading bytes until we either run out of section or state to fill. + for (uint16_t i = 0; offset <= results->rawlen - 16 && i < nbits / 8; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData(&(results->rawbuf[offset]), 8, kElectraAcBitMark, + kElectraAcOneSpace, kElectraAcBitMark, + kElectraAcZeroSpace, kTolerance, 0, true); + if (data_result.success == false) return false; // Fail + results->state[i] = data_result.data; + } + + // Message Footer + if (!matchMark(results->rawbuf[offset++], kElectraAcBitMark)) return false; + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kElectraAcMessageGap)) + return false; + + // Compliance + if (strict && dataBitsSoFar != nbits) return false; + + // Success + results->decode_type = ELECTRA_AC; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_ELECTRA_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.cpp new file mode 100644 index 000000000..7c1b99834 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.cpp @@ -0,0 +1,519 @@ +// Copyright 2017 Jonny Graham, David Conran +#include "ir_Fujitsu.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRsend.h" +#include "IRutils.h" + +// Fujitsu A/C support added by Jonny Graham & David Conran + +// Equipment it seems compatible with: +// * Fujitsu ASYG30LFCA with remote AR-RAH2E +// * Fujitsu AST9RSGCW with remote AR-DB1 +// * + +// Ref: +// These values are based on averages of measurements +const uint16_t kFujitsuAcHdrMark = 3324; +const uint16_t kFujitsuAcHdrSpace = 1574; +const uint16_t kFujitsuAcBitMark = 448; +const uint16_t kFujitsuAcOneSpace = 1182; +const uint16_t kFujitsuAcZeroSpace = 390; +const uint16_t kFujitsuAcMinGap = 8100; + +#if SEND_FUJITSU_AC +// Send a Fujitsu A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. Typically one of: +// kFujitsuAcStateLength +// kFujitsuAcStateLength - 1 +// kFujitsuAcStateLengthShort +// kFujitsuAcStateLengthShort - 1 +// repeat: Nr. of times the message is to be repeated. +// (Default = kFujitsuAcMinRepeat). +// +// Status: BETA / Appears to be working. +// +void IRsend::sendFujitsuAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + sendGeneric(kFujitsuAcHdrMark, kFujitsuAcHdrSpace, kFujitsuAcBitMark, + kFujitsuAcOneSpace, kFujitsuAcBitMark, kFujitsuAcZeroSpace, + kFujitsuAcBitMark, kFujitsuAcMinGap, data, nbytes, 38, false, + repeat, 50); +} +#endif // SEND_FUJITSU_AC + +// Code to emulate Fujitsu A/C IR remote control unit. + +// Initialise the object. +IRFujitsuAC::IRFujitsuAC(uint16_t pin, fujitsu_ac_remote_model_t model) + : _irsend(pin) { + setModel(model); + stateReset(); +} + +void IRFujitsuAC::setModel(fujitsu_ac_remote_model_t model) { + _model = model; + switch (model) { + case ARDB1: + _state_length = kFujitsuAcStateLength - 1; + _state_length_short = kFujitsuAcStateLengthShort - 1; + break; + default: + _state_length = kFujitsuAcStateLength; + _state_length_short = kFujitsuAcStateLengthShort; + } +} + +// Reset the state of the remote to a known good state/sequence. +void IRFujitsuAC::stateReset() { + _temp = 24; + _fanSpeed = kFujitsuAcFanHigh; + _mode = kFujitsuAcModeCool; + _swingMode = kFujitsuAcSwingBoth; + _cmd = kFujitsuAcCmdTurnOn; + buildState(); +} + +// Configure the pin for output. +void IRFujitsuAC::begin() { _irsend.begin(); } + +#if SEND_FUJITSU_AC +// Send the current desired state to the IR LED. +void IRFujitsuAC::send() { + getRaw(); + _irsend.sendFujitsuAC(remote_state, getStateLength()); +} +#endif // SEND_FUJITSU_AC + +void IRFujitsuAC::buildState() { + remote_state[0] = 0x14; + remote_state[1] = 0x63; + remote_state[2] = 0x00; + remote_state[3] = 0x10; + remote_state[4] = 0x10; + bool fullCmd = false; + switch (_cmd) { + case kFujitsuAcCmdTurnOff: + remote_state[5] = 0x02; + break; + case kFujitsuAcCmdStepHoriz: + remote_state[5] = 0x79; + break; + case kFujitsuAcCmdStepVert: + remote_state[5] = 0x6C; + break; + default: + switch (_model) { + case ARRAH2E: + remote_state[5] = 0xFE; + break; + case ARDB1: + remote_state[5] = 0xFC; + break; + } + fullCmd = true; + break; + } + if (fullCmd) { // long codes + uint8_t tempByte = _temp - kFujitsuAcMinTemp; + // Nr. of bytes in the message after this byte. + remote_state[6] = _state_length - 7; + + remote_state[7] = 0x30; + remote_state[8] = (_cmd == kFujitsuAcCmdTurnOn) | (tempByte << 4); + remote_state[9] = _mode | 0 << 4; // timer off + remote_state[10] = _fanSpeed | _swingMode << 4; + remote_state[11] = 0; // timerOff values + remote_state[12] = 0; // timerOff/On values + remote_state[13] = 0; // timerOn values + if (_model == ARRAH2E) + remote_state[14] = 0x20; + else + remote_state[14] = 0x00; + + uint8_t checksum = 0; + uint8_t checksum_complement = 0; + if (_model == ARRAH2E) { + checksum = sumBytes(remote_state + _state_length_short, + _state_length - _state_length_short - 1); + } else if (_model == ARDB1) { + checksum = sumBytes(remote_state, _state_length - 1); + checksum_complement = 0x9B; + } + // and negate the checksum and store it in the last byte. + remote_state[_state_length - 1] = checksum_complement - checksum; + } else { // short codes + if (_model == ARRAH2E) + // The last byte is the inverse of penultimate byte + remote_state[_state_length_short - 1] = + ~remote_state[_state_length_short - 2]; + // Zero the rest of the state. + for (uint8_t i = _state_length_short; i < kFujitsuAcStateLength; i++) + remote_state[i] = 0; + } +} + +uint8_t IRFujitsuAC::getStateLength() { + buildState(); // Force an update of the internal state. + if ((_model == ARRAH2E && remote_state[5] != 0xFE) || + (_model == ARDB1 && remote_state[5] != 0xFC)) + return _state_length_short; + else + return _state_length; +} + +// Return a pointer to the internal state date of the remote. +uint8_t* IRFujitsuAC::getRaw() { + buildState(); + return remote_state; +} + +void IRFujitsuAC::buildFromState(const uint16_t length) { + switch (length) { + case kFujitsuAcStateLength - 1: + case kFujitsuAcStateLengthShort - 1: + setModel(ARDB1); + break; + default: + setModel(ARRAH2E); + } + switch (remote_state[6]) { + case 8: + setModel(ARDB1); + break; + case 9: + setModel(ARRAH2E); + break; + } + setTemp((remote_state[8] >> 4) + kFujitsuAcMinTemp); + if (remote_state[8] & 0x1) + setCmd(kFujitsuAcCmdTurnOn); + else + setCmd(kFujitsuAcCmdStayOn); + setMode(remote_state[9] & 0b111); + setFanSpeed(remote_state[10] & 0b111); + setSwing(remote_state[10] >> 4); + switch (remote_state[5]) { + case kFujitsuAcCmdTurnOff: + case kFujitsuAcCmdStepHoriz: + case kFujitsuAcCmdStepVert: + setCmd(remote_state[5]); + break; + } +} + +bool IRFujitsuAC::setRaw(const uint8_t newState[], const uint16_t length) { + if (length > kFujitsuAcStateLength) return false; + for (uint16_t i = 0; i < kFujitsuAcStateLength; i++) { + if (i < length) + remote_state[i] = newState[i]; + else + remote_state[i] = 0; + } + buildFromState(length); + return true; +} + +// Set the requested power state of the A/C to off. +void IRFujitsuAC::off() { _cmd = kFujitsuAcCmdTurnOff; } + +void IRFujitsuAC::stepHoriz() { + switch (_model) { + case ARDB1: + break; // This remote doesn't have a horizontal option. + default: + _cmd = kFujitsuAcCmdStepHoriz; + } +} + +void IRFujitsuAC::stepVert() { _cmd = kFujitsuAcCmdStepVert; } + +// Set the requested command of the A/C. +void IRFujitsuAC::setCmd(uint8_t cmd) { + switch (cmd) { + case kFujitsuAcCmdTurnOff: + case kFujitsuAcCmdTurnOn: + case kFujitsuAcCmdStayOn: + case kFujitsuAcCmdStepVert: + _cmd = cmd; + break; + case kFujitsuAcCmdStepHoriz: + if (_model != ARDB1) // AR-DB1 remote doesn't have step horizontal. + _cmd = cmd; + // FALLTHRU + default: + _cmd = kFujitsuAcCmdStayOn; + break; + } +} + +uint8_t IRFujitsuAC::getCmd() { return _cmd; } + +bool IRFujitsuAC::getPower() { return _cmd != kFujitsuAcCmdTurnOff; } + +// Set the temp. in deg C +void IRFujitsuAC::setTemp(uint8_t temp) { + temp = std::max((uint8_t)kFujitsuAcMinTemp, temp); + temp = std::min((uint8_t)kFujitsuAcMaxTemp, temp); + _temp = temp; +} + +uint8_t IRFujitsuAC::getTemp() { return _temp; } + +// Set the speed of the fan +void IRFujitsuAC::setFanSpeed(uint8_t fanSpeed) { + if (fanSpeed > kFujitsuAcFanQuiet) + fanSpeed = kFujitsuAcFanHigh; // Set the fan to maximum if out of range. + _fanSpeed = fanSpeed; +} +uint8_t IRFujitsuAC::getFanSpeed() { return _fanSpeed; } + +// Set the requested climate operation mode of the a/c unit. +void IRFujitsuAC::setMode(uint8_t mode) { + if (mode > kFujitsuAcModeHeat) + mode = kFujitsuAcModeHeat; // Set the mode to maximum if out of range. + _mode = mode; +} + +uint8_t IRFujitsuAC::getMode() { return _mode; } +// Set the requested swing operation mode of the a/c unit. +void IRFujitsuAC::setSwing(uint8_t swingMode) { + switch (_model) { + case ARDB1: + // Set the mode to max if out of range + if (swingMode > kFujitsuAcSwingVert) swingMode = kFujitsuAcSwingVert; + break; + case ARRAH2E: + default: + // Set the mode to max if out of range + if (swingMode > kFujitsuAcSwingBoth) swingMode = kFujitsuAcSwingBoth; + } + _swingMode = swingMode; +} + +uint8_t IRFujitsuAC::getSwing() { return _swingMode; } + +bool IRFujitsuAC::validChecksum(uint8_t state[], uint16_t length) { + uint8_t sum = 0; + uint8_t sum_complement = 0; + uint8_t checksum = state[length - 1]; + switch (length) { + case kFujitsuAcStateLengthShort: // ARRAH2E + return state[length - 1] == (uint8_t)~state[length - 2]; + case kFujitsuAcStateLength - 1: // ARDB1 + sum = sumBytes(state, length - 1); + sum_complement = 0x9B; + break; + case kFujitsuAcStateLength: // ARRAH2E + sum = sumBytes(state + kFujitsuAcStateLengthShort, + length - 1 - kFujitsuAcStateLengthShort); + break; + default: // Includes ARDB1 short. + return true; // Assume the checksum is valid for other lengths. + } + return checksum == (uint8_t)(sum_complement - sum); // Does it match? +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRFujitsuAC::toString() { + String result = ""; +#else +std::string IRFujitsuAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kFujitsuAcModeAuto: + result += " (AUTO)"; + break; + case kFujitsuAcModeCool: + result += " (COOL)"; + break; + case kFujitsuAcModeHeat: + result += " (HEAT)"; + break; + case kFujitsuAcModeDry: + result += " (DRY)"; + break; + case kFujitsuAcModeFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFanSpeed()); + switch (getFanSpeed()) { + case kFujitsuAcFanAuto: + result += " (AUTO)"; + break; + case kFujitsuAcFanHigh: + result += " (HIGH)"; + break; + case kFujitsuAcFanMed: + result += " (MED)"; + break; + case kFujitsuAcFanLow: + result += " (LOW)"; + break; + case kFujitsuAcFanQuiet: + result += " (QUIET)"; + break; + } + result += ", Swing: "; + switch (getSwing()) { + case kFujitsuAcSwingOff: + result += "Off"; + break; + case kFujitsuAcSwingVert: + result += "Vert"; + break; + case kFujitsuAcSwingHoriz: + result += "Horiz"; + break; + case kFujitsuAcSwingBoth: + result += "Vert + Horiz"; + break; + default: + result += "UNKNOWN"; + } + result += ", Command: "; + switch (getCmd()) { + case kFujitsuAcCmdStepHoriz: + result += "Step vane horizontally"; + break; + case kFujitsuAcCmdStepVert: + result += "Step vane vertically"; + break; + default: + result += "N/A"; + } + return result; +} + +#if DECODE_FUJITSU_AC +// Decode a Fujitsu AC IR message if possible. +// Places successful decode information in the results pointer. +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kFujitsuAcBits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +// +// Ref: +// +bool IRrecv::decodeFujitsuAC(decode_results* results, uint16_t nbits, + bool strict) { + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + + // Have we got enough data to successfully decode? + if (results->rawlen < (2 * kFujitsuAcMinBits) + kHeader + kFooter - 1) + return false; // Can't possibly be a valid message. + + // Compliance + if (strict) { + switch (nbits) { + case kFujitsuAcBits: + case kFujitsuAcBits - 8: + case kFujitsuAcMinBits: + case kFujitsuAcMinBits + 8: + break; + default: + return false; // Must be called with the correct nr. of bits. + } + } + + // Header + if (!matchMark(results->rawbuf[offset++], kFujitsuAcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kFujitsuAcHdrSpace)) return false; + + // Data (Fixed signature) + match_result_t data_result = + matchData(&(results->rawbuf[offset]), kFujitsuAcMinBits - 8, + kFujitsuAcBitMark, kFujitsuAcOneSpace, kFujitsuAcBitMark, + kFujitsuAcZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; // Fail + if (data_result.data != 0x1010006314) return false; // Signature failed. + dataBitsSoFar += kFujitsuAcMinBits - 8; + offset += data_result.used; + results->state[0] = 0x14; + results->state[1] = 0x63; + results->state[2] = 0x00; + results->state[3] = 0x10; + results->state[4] = 0x10; + + // Keep reading bytes until we either run out of message or state to fill. + for (uint16_t i = 5; + offset <= results->rawlen - 16 && i < kFujitsuAcStateLength; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData( + &(results->rawbuf[offset]), 8, kFujitsuAcBitMark, kFujitsuAcOneSpace, + kFujitsuAcBitMark, kFujitsuAcZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) break; // Fail + results->state[i] = data_result.data; + } + + // Footer + if (offset > results->rawlen || + !matchMark(results->rawbuf[offset++], kFujitsuAcBitMark)) + return false; + // The space is optional if we are out of capture. + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kFujitsuAcMinGap)) + return false; + + // Compliance + if (strict) { + if (dataBitsSoFar != nbits) return false; + } + + results->decode_type = FUJITSU_AC; + results->bits = dataBitsSoFar; + + // Compliance + switch (dataBitsSoFar) { + case kFujitsuAcMinBits: + // Check if this values indicate that this should have been a long state + // message. + if (results->state[5] == 0xFC) return false; + return true; // Success + case kFujitsuAcMinBits + 8: + // Check if this values indicate that this should have been a long state + // message. + if (results->state[5] == 0xFE) return false; + // The last byte needs to be the inverse of the penultimate byte. + if (results->state[5] != (uint8_t)~results->state[6]) return false; + return true; // Success + case kFujitsuAcBits - 8: + // Long messages of this size require this byte be correct. + if (results->state[5] != 0xFC) return false; + break; + case kFujitsuAcBits: + // Long messages of this size require this byte be correct. + if (results->state[5] != 0xFE) return false; + break; + default: + return false; // Unexpected size. + } + if (!IRFujitsuAC::validChecksum(results->state, dataBitsSoFar / 8)) + return false; + + // Success + return true; // All good. +} +#endif // DECODE_FUJITSU_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h new file mode 100644 index 000000000..bba634be6 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h @@ -0,0 +1,123 @@ +// Copyright 2017 Jonny Graham +// Copyright 2018 David Conran +#ifndef IR_FUJITSU_H_ +#define IR_FUJITSU_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifdef ARDUINO +#include +#else +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// FUJITSU A/C support added by Jonny Graham + +// Constants +const uint8_t kFujitsuAcModeAuto = 0x00; +const uint8_t kFujitsuAcModeCool = 0x01; +const uint8_t kFujitsuAcModeDry = 0x02; +const uint8_t kFujitsuAcModeFan = 0x03; +const uint8_t kFujitsuAcModeHeat = 0x04; + +const uint8_t kFujitsuAcCmdStayOn = 0x00; +const uint8_t kFujitsuAcCmdTurnOn = 0x01; +const uint8_t kFujitsuAcCmdTurnOff = 0x02; +const uint8_t kFujitsuAcCmdStepHoriz = 0x79; +const uint8_t kFujitsuAcCmdStepVert = 0x6C; + +const uint8_t kFujitsuAcFanAuto = 0x00; +const uint8_t kFujitsuAcFanHigh = 0x01; +const uint8_t kFujitsuAcFanMed = 0x02; +const uint8_t kFujitsuAcFanLow = 0x03; +const uint8_t kFujitsuAcFanQuiet = 0x04; + +const uint8_t kFujitsuAcMinTemp = 16; // 16C +const uint8_t kFujitsuAcMaxTemp = 30; // 30C + +const uint8_t kFujitsuAcSwingOff = 0x00; +const uint8_t kFujitsuAcSwingVert = 0x01; +const uint8_t kFujitsuAcSwingHoriz = 0x02; +const uint8_t kFujitsuAcSwingBoth = 0x03; + +// Legacy defines. +#define FUJITSU_AC_MODE_AUTO kFujitsuAcModeAuto +#define FUJITSU_AC_MODE_COOL kFujitsuAcModeCool +#define FUJITSU_AC_MODE_DRY kFujitsuAcModeDry +#define FUJITSU_AC_MODE_FAN kFujitsuAcModeFan +#define FUJITSU_AC_MODE_HEAT kFujitsuAcModeHeat +#define FUJITSU_AC_CMD_STAY_ON kFujitsuAcCmdStayOn +#define FUJITSU_AC_CMD_TURN_ON kFujitsuAcCmdTurnOn +#define FUJITSU_AC_CMD_TURN_OFF kFujitsuAcCmdTurnOff +#define FUJITSU_AC_CMD_STEP_HORIZ kFujitsuAcCmdStepHoriz +#define FUJITSU_AC_CMD_STEP_VERT kFujitsuAcCmdStepVert +#define FUJITSU_AC_FAN_AUTO kFujitsuAcFanAuto +#define FUJITSU_AC_FAN_HIGH kFujitsuAcFanHigh +#define FUJITSU_AC_FAN_MED kFujitsuAcFanMed +#define FUJITSU_AC_FAN_LOW kFujitsuAcFanLow +#define FUJITSU_AC_FAN_QUIET kFujitsuAcFanQuiet +#define FUJITSU_AC_MIN_TEMP kFujitsuAcMinTemp +#define FUJITSU_AC_MAX_TEMP kFujitsuAcMaxTemp +#define FUJITSU_AC_SWING_OFF kFujitsuAcSwingOff +#define FUJITSU_AC_SWING_VERT kFujitsuAcSwingVert +#define FUJITSU_AC_SWING_HORIZ kFujitsuAcSwingHoriz +#define FUJITSU_AC_SWING_BOTH kFujitsuAcSwingBoth + +enum fujitsu_ac_remote_model_t { + ARRAH2E = 1, + ARDB1, +}; + +class IRFujitsuAC { + public: + explicit IRFujitsuAC(uint16_t pin, fujitsu_ac_remote_model_t model = ARRAH2E); + + void setModel(fujitsu_ac_remote_model_t model); + void stateReset(); +#if SEND_FUJITSU_AC + void send(); +#endif // SEND_FUJITSU_AC + void begin(); + void off(); + void stepHoriz(); + void stepVert(); + void setCmd(uint8_t cmd); + uint8_t getCmd(); + void setTemp(uint8_t temp); + uint8_t getTemp(); + void setFanSpeed(uint8_t fan); + uint8_t getFanSpeed(); + void setMode(uint8_t mode); + uint8_t getMode(); + void setSwing(uint8_t mode); + uint8_t getSwing(); + uint8_t* getRaw(); + bool setRaw(const uint8_t newState[], const uint16_t length); + uint8_t getStateLength(); + static bool validChecksum(uint8_t* state, uint16_t length); + bool getPower(); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: + uint8_t remote_state[kFujitsuAcStateLength]; + IRsend _irsend; + uint8_t _temp; + uint8_t _fanSpeed; + uint8_t _mode; + uint8_t _swingMode; + uint8_t _cmd; + fujitsu_ac_remote_model_t _model; + uint8_t _state_length; + uint8_t _state_length_short; + void buildState(); + void buildFromState(const uint16_t length); +}; + +#endif // IR_FUJITSU_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_GICable.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_GICable.cpp new file mode 100644 index 000000000..229e4e5bb --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_GICable.cpp @@ -0,0 +1,116 @@ +// Copyright 2018 David Conran + +#define __STDC_LIMIT_MACROS +#include +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// GGGG IIIII CCCCC AAA BBBBB LL EEEEEEE +// GG GG III CC C AAAAA BB B LL EE +// GG III CC AA AA BBBBBB LL EEEEE +// GG GG ... III ... CC C AAAAAAA BB BB LL EE +// GGGGGG ... IIIII ... CCCCC AA AA BBBBBB LLLLLLL EEEEEEE +// +// Ref: +// https://github.com/cyborg5/IRLib2/blob/master/IRLibProtocols/IRLib_P09_GICable.h +// https://github.com/markszabo/IRremoteESP8266/issues/447 + +// Constants +const uint16_t kGicableHdrMark = 9000; +const uint16_t kGicableHdrSpace = 4400; +const uint16_t kGicableBitMark = 550; +const uint16_t kGicableOneSpace = 4400; +const uint16_t kGicableZeroSpace = 2200; +const uint16_t kGicableRptSpace = 2200; +const uint32_t kGicableMinCommandLength = 99600; +const uint32_t kGicableMinGap = + kGicableMinCommandLength - + (kGicableHdrMark + kGicableHdrSpace + + kGicableBits * (kGicableBitMark + kGicableOneSpace) + kGicableBitMark); + +#if SEND_GICABLE +// Send a raw G.I. Cable formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The number of bits of the message to be sent. +// Typically kGicableBits. +// repeat: The number of times the command is to be repeated. +// +// Status: Alpha / Untested. +// +// Ref: +void IRsend::sendGICable(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(kGicableHdrMark, kGicableHdrSpace, kGicableBitMark, + kGicableOneSpace, kGicableBitMark, kGicableZeroSpace, + kGicableBitMark, kGicableMinGap, kGicableMinCommandLength, data, + nbits, 39, true, 0, // Repeats are handled later. + 50); + // Message repeat sequence. + if (repeat) + sendGeneric(kGicableHdrMark, kGicableRptSpace, 0, 0, 0, + 0, // No actual data sent. + kGicableBitMark, kGicableMinGap, kGicableMinCommandLength, 0, + 0, // No data to be sent. + 39, true, repeat - 1, 50); +} +#endif // SEND_GICABLE + +#if DECODE_GICABLE +// Decode the supplied G.I. Cable message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kGicableBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Alpha / Not tested against a real device. +bool IRrecv::decodeGICable(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1) + return false; // Can't possibly be a valid GICABLE message. + if (strict && nbits != kGicableBits) + return false; // Not strictly an GICABLE message. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + + // Header + if (!matchMark(results->rawbuf[offset++], kGicableHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kGicableHdrSpace)) return false; + + // Data + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kGicableBitMark, + kGicableOneSpace, kGicableBitMark, kGicableZeroSpace); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Footer + if (!matchMark(results->rawbuf[offset++], kGicableBitMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kGicableMinGap)) + return false; + + // Compliance + if (strict) { + // We expect a repeat frame. + if (!matchMark(results->rawbuf[offset++], kGicableHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kGicableRptSpace)) return false; + if (!matchMark(results->rawbuf[offset++], kGicableBitMark)) return false; + } + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = GICABLE; + results->command = 0; + results->address = 0; + return true; +} +#endif // DECODE_GICABLE diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_GlobalCache.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_GlobalCache.cpp similarity index 66% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_GlobalCache.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_GlobalCache.cpp index 019413b96..daa9dd22c 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_GlobalCache.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_GlobalCache.cpp @@ -3,7 +3,6 @@ #include #include "IRsend.h" -#include "IRtimer.h" // GGG L OOOO BBBB AA L CCCC AA CCCC H H EEEEEE // G G L O O B B AAAA L C C AAAA C C H H E @@ -15,12 +14,12 @@ // (http://www.hishamkhalifa.com) // Constants -#define GLOBALCACHE_MAX_REPEAT 50U -#define GLOBALCACHE_MIN_USEC 80U -#define GLOBALCACHE_FREQ_INDEX 0U -#define GLOBALCACHE_RPT_INDEX GLOBALCACHE_FREQ_INDEX + 1U -#define GLOBALCACHE_RPT_START_INDEX GLOBALCACHE_RPT_INDEX + 1U -#define GLOBALCACHE_START_INDEX GLOBALCACHE_RPT_START_INDEX + 1U +const uint16_t kGlobalCacheMaxRepeat = 50; +const uint32_t kGlobalCacheMinUsec = 80; +const uint8_t kGlobalCacheFreqIndex = 0; +const uint8_t kGlobalCacheRptIndex = kGlobalCacheFreqIndex + 1; +const uint8_t kGlobalCacheRptStartIndex = kGlobalCacheRptIndex + 1; +const uint8_t kGlobalCacheStartIndex = kGlobalCacheRptStartIndex + 1; #if SEND_GLOBALCACHE // Send a shortened GlobalCache (GC) IRdb/control tower formatted message. @@ -41,24 +40,23 @@ // Ref: // https://irdb.globalcache.com/Home/Database void IRsend::sendGC(uint16_t buf[], uint16_t len) { - uint16_t hz = buf[GLOBALCACHE_FREQ_INDEX]; // GC frequency is in Hz. + uint16_t hz = buf[kGlobalCacheFreqIndex]; // GC frequency is in Hz. enableIROut(hz); uint32_t periodic_time = calcUSecPeriod(hz, false); - uint8_t emits = std::min(buf[GLOBALCACHE_RPT_INDEX], - (uint16_t) GLOBALCACHE_MAX_REPEAT); + uint8_t emits = + std::min(buf[kGlobalCacheRptIndex], (uint16_t)kGlobalCacheMaxRepeat); // Repeat for (uint8_t repeat = 0; repeat < emits; repeat++) { - // First time through, start at the beginning (GLOBALCACHE_START_INDEX), + // First time through, start at the beginning (kGlobalCacheStartIndex), // otherwise for repeats, we start a specified offset from that. - uint16_t offset = GLOBALCACHE_START_INDEX; - if (repeat) - offset += buf[GLOBALCACHE_RPT_START_INDEX] - 1; + uint16_t offset = kGlobalCacheStartIndex; + if (repeat) offset += buf[kGlobalCacheRptStartIndex] - 1; // Data for (; offset < len; offset++) { // Convert periodic units to microseconds. - // Minimum is GLOBALCACHE_MIN_USEC for actual GC units. - uint32_t microseconds = std::max(buf[offset] * periodic_time, - GLOBALCACHE_MIN_USEC); + // Minimum is kGlobalCacheMinUsec for actual GC units. + uint32_t microseconds = + std::max(buf[offset] * periodic_time, kGlobalCacheMinUsec); // These codes start at an odd index (not even as with sendRaw). if (offset & 1) // Odd bit. mark(microseconds); diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp new file mode 100644 index 000000000..df8afada6 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp @@ -0,0 +1,478 @@ +// Copyright 2017 Ville Skyttä (scop) +// Copyright 2017, 2018 David Conran +// +// Code to emulate Gree protocol compatible HVAC devices. +// Should be compatible with: +// * Heat pumps carrying the "Ultimate" brand name. +// * EKOKAI air conditioners. +// + +#include "ir_Gree.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRutils.h" +#include "ir_Kelvinator.h" + +// GGGG RRRRRR EEEEEEE EEEEEEE +// GG GG RR RR EE EE +// GG RRRRRR EEEEE EEEEE +// GG GG RR RR EE EE +// GGGGGG RR RR EEEEEEE EEEEEEE + +// Constants +// Ref: https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.h +const uint16_t kGreeHdrMark = 9000; +const uint16_t kGreeHdrSpace = 4000; +const uint16_t kGreeBitMark = 620; +const uint16_t kGreeOneSpace = 1600; +const uint16_t kGreeZeroSpace = 540; +const uint16_t kGreeMsgSpace = 19000; +const uint8_t kGreeBlockFooter = 0b010; +const uint8_t kGreeBlockFooterBits = 3; + +#if SEND_GREE +// Send a Gree Heat Pump message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kGreeStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: ALPHA / Untested. +// +// Ref: +// https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp +void IRsend::sendGree(unsigned char data[], uint16_t nbytes, uint16_t repeat) { + if (nbytes < kGreeStateLength) + return; // Not enough bytes to send a proper message. + + for (uint16_t r = 0; r <= repeat; r++) { + // Block #1 + sendGeneric(kGreeHdrMark, kGreeHdrSpace, kGreeBitMark, kGreeOneSpace, + kGreeBitMark, kGreeZeroSpace, 0, 0, // No Footer. + data, 4, 38, false, 0, 50); + // Footer #1 + sendGeneric(0, 0, // No Header + kGreeBitMark, kGreeOneSpace, kGreeBitMark, kGreeZeroSpace, + kGreeBitMark, kGreeMsgSpace, 0b010, 3, 38, true, 0, false); + + // Block #2 + sendGeneric(0, 0, // No Header for Block #2 + kGreeBitMark, kGreeOneSpace, kGreeBitMark, kGreeZeroSpace, + kGreeBitMark, kGreeMsgSpace, data + 4, nbytes - 4, 38, false, 0, + 50); + } +} + +// Send a Gree Heat Pump message. +// +// Args: +// data: The raw message to be sent. +// nbits: Nr. of bits of data in the message. (Default is kGreeBits) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: ALPHA / Untested. +// +// Ref: +// https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.cpp +void IRsend::sendGree(uint64_t data, uint16_t nbits, uint16_t repeat) { + if (nbits != kGreeBits) + return; // Wrong nr. of bits to send a proper message. + // Set IR carrier frequency + enableIROut(38); + + for (uint16_t r = 0; r <= repeat; r++) { + // Header + mark(kGreeHdrMark); + space(kGreeHdrSpace); + + // Data + for (int16_t i = 8; i <= nbits; i += 8) { + sendData(kGreeBitMark, kGreeOneSpace, kGreeBitMark, kGreeZeroSpace, + (data >> (nbits - i)) & 0xFF, 8, false); + if (i == nbits / 2) { + // Send the mid-message Footer. + sendData(kGreeBitMark, kGreeOneSpace, kGreeBitMark, kGreeZeroSpace, + 0b010, 3); + mark(kGreeBitMark); + space(kGreeMsgSpace); + } + } + // Footer + mark(kGreeBitMark); + space(kGreeMsgSpace); + } +} +#endif // SEND_GREE + +IRGreeAC::IRGreeAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRGreeAC::stateReset() { + // This resets to a known-good state to Power Off, Fan Auto, Mode Auto, 25C. + for (uint8_t i = 0; i < kGreeStateLength; i++) remote_state[i] = 0x0; + remote_state[1] = 0x09; + remote_state[2] = 0x20; + remote_state[3] = 0x50; + remote_state[5] = 0x20; + remote_state[7] = 0x50; +} + +void IRGreeAC::fixup() { + checksum(); // Calculate the checksums +} + +void IRGreeAC::begin() { _irsend.begin(); } + +#if SEND_GREE +void IRGreeAC::send() { + fixup(); // Ensure correct settings before sending. + _irsend.sendGree(remote_state); +} +#endif // SEND_GREE + +uint8_t* IRGreeAC::getRaw() { + fixup(); // Ensure correct settings before sending. + return remote_state; +} + +void IRGreeAC::setRaw(uint8_t new_code[]) { + for (uint8_t i = 0; i < kGreeStateLength; i++) { + remote_state[i] = new_code[i]; + } +} + +void IRGreeAC::checksum(const uint16_t length) { + // Gree uses the same checksum alg. as Kelvinator's block checksum. + uint8_t sum = IRKelvinatorAC::calcBlockChecksum(remote_state, length); + remote_state[length - 1] = (sum << 4) | (remote_state[length - 1] & 0xFU); +} + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRGreeAC::validChecksum(const uint8_t state[], const uint16_t length) { + // Top 4 bits of the last byte in the state is the state's checksum. + if (state[length - 1] >> 4 == + IRKelvinatorAC::calcBlockChecksum(state, length)) + return true; + else + return false; +} + +void IRGreeAC::on() { + remote_state[0] |= kGreePower1Mask; + remote_state[2] |= kGreePower2Mask; +} + +void IRGreeAC::off() { + remote_state[0] &= ~kGreePower1Mask; + remote_state[2] &= ~kGreePower2Mask; +} + +void IRGreeAC::setPower(const bool state) { + if (state) + on(); + else + off(); +} + +bool IRGreeAC::getPower() { + return (remote_state[0] & kGreePower1Mask) && + (remote_state[2] & kGreePower2Mask); +} + +// Set the temp. in deg C +void IRGreeAC::setTemp(const uint8_t temp) { + uint8_t new_temp = std::max((uint8_t)kGreeMinTemp, temp); + new_temp = std::min((uint8_t)kGreeMaxTemp, new_temp); + if (getMode() == kGreeAuto) new_temp = 25; + remote_state[1] = (remote_state[1] & 0xF0U) | (new_temp - kGreeMinTemp); +} + +// Return the set temp. in deg C +uint8_t IRGreeAC::getTemp() { + return ((remote_state[1] & 0xFU) + kGreeMinTemp); +} + +// Set the speed of the fan, 0-3, 0 is auto, 1-3 is the speed +void IRGreeAC::setFan(const uint8_t speed) { + uint8_t fan = std::min((uint8_t)kGreeFanMax, speed); // Bounds check + + if (getMode() == kGreeDry) fan = 1; // DRY mode is always locked to fan 1. + // Set the basic fan values. + remote_state[0] &= ~kGreeFanMask; + remote_state[0] |= (fan << 4); +} + +uint8_t IRGreeAC::getFan() { return ((remote_state[0] & kGreeFanMask) >> 4); } + +void IRGreeAC::setMode(const uint8_t new_mode) { + uint8_t mode = new_mode; + switch (mode) { + case kGreeAuto: + // AUTO is locked to 25C + setTemp(25); + break; + case kGreeDry: + // DRY always sets the fan to 1. + setFan(1); + break; + case kGreeCool: + case kGreeFan: + case kGreeHeat: + break; + default: + // If we get an unexpected mode, default to AUTO. + mode = kGreeAuto; + } + remote_state[0] &= ~kGreeModeMask; + remote_state[0] |= mode; +} + +uint8_t IRGreeAC::getMode() { return (remote_state[0] & kGreeModeMask); } + +void IRGreeAC::setLight(const bool state) { + remote_state[2] &= ~kGreeLightMask; + remote_state[2] |= (state << 5); +} + +bool IRGreeAC::getLight() { return remote_state[2] & kGreeLightMask; } + +void IRGreeAC::setXFan(const bool state) { + remote_state[2] &= ~kGreeXfanMask; + remote_state[2] |= (state << 7); +} + +bool IRGreeAC::getXFan() { return remote_state[2] & kGreeXfanMask; } + +void IRGreeAC::setSleep(const bool state) { + remote_state[0] &= ~kGreeSleepMask; + remote_state[0] |= (state << 7); +} + +bool IRGreeAC::getSleep() { return remote_state[0] & kGreeSleepMask; } + +void IRGreeAC::setTurbo(const bool state) { + remote_state[2] &= ~kGreeTurboMask; + remote_state[2] |= (state << 4); +} + +bool IRGreeAC::getTurbo() { return remote_state[2] & kGreeTurboMask; } + +void IRGreeAC::setSwingVertical(const bool automatic, const uint8_t position) { + remote_state[0] &= ~kGreeSwingAutoMask; + remote_state[0] |= (automatic << 6); + uint8_t new_position = position; + if (!automatic) { + switch (position) { + case kGreeSwingUp: + case kGreeSwingMiddleUp: + case kGreeSwingMiddle: + case kGreeSwingMiddleDown: + case kGreeSwingDown: + break; + default: + new_position = kGreeSwingLastPos; + } + } else { + switch (position) { + case kGreeSwingAuto: + case kGreeSwingDownAuto: + case kGreeSwingMiddleAuto: + case kGreeSwingUpAuto: + break; + default: + new_position = kGreeSwingAuto; + } + } + remote_state[4] &= ~kGreeSwingPosMask; + remote_state[4] |= new_position; +} + +bool IRGreeAC::getSwingVerticalAuto() { + return remote_state[0] & kGreeSwingAutoMask; +} + +uint8_t IRGreeAC::getSwingVerticalPosition() { + return remote_state[4] & kGreeSwingPosMask; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRGreeAC::toString() { + String result = ""; +#else +std::string IRGreeAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kGreeAuto: + result += " (AUTO)"; + break; + case kGreeCool: + result += " (COOL)"; + break; + case kGreeHeat: + result += " (HEAT)"; + break; + case kGreeDry: + result += " (DRY)"; + break; + case kGreeFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case 0: + result += " (AUTO)"; + break; + case kGreeFanMax: + result += " (MAX)"; + break; + } + result += ", Turbo: "; + if (getTurbo()) + result += "On"; + else + result += "Off"; + result += ", XFan: "; + if (getXFan()) + result += "On"; + else + result += "Off"; + result += ", Light: "; + if (getLight()) + result += "On"; + else + result += "Off"; + result += ", Sleep: "; + if (getSleep()) + result += "On"; + else + result += "Off"; + result += ", Swing Vertical Mode: "; + if (getSwingVerticalAuto()) + result += "Auto"; + else + result += "Manual"; + result += + ", Swing Vertical Pos: " + uint64ToString(getSwingVerticalPosition()); + switch (getSwingVerticalPosition()) { + case kGreeSwingLastPos: + result += " (Last Pos)"; + break; + case kGreeSwingAuto: + result += " (Auto)"; + break; + } + return result; +} + +#if DECODE_GREE +// Decode the supplied Gree message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kGreeBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +bool IRrecv::decodeGree(decode_results* results, uint16_t nbits, bool strict) { + if (results->rawlen < + 2 * (nbits + kGreeBlockFooterBits) + (kHeader + kFooter + 1)) + return false; // Can't possibly be a valid Gree message. + if (strict && nbits != kGreeBits) + return false; // Not strictly a Gree message. + + uint32_t data; + uint16_t offset = kStartOffset; + + // There are two blocks back-to-back in a full Gree IR message + // sequence. + int8_t state_pos = 0; + match_result_t data_result; + + // Header + if (!matchMark(results->rawbuf[offset++], kGreeHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kGreeHdrSpace)) return false; + // Data Block #1 (32 bits) + data_result = + matchData(&(results->rawbuf[offset]), 32, kGreeBitMark, kGreeOneSpace, + kGreeBitMark, kGreeZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Record Data Block #1 in the state. + for (uint16_t i = 0; i < 4; i++, data >>= 8) + results->state[state_pos + i] = data & 0xFF; + state_pos += 4; + + // Block #1 footer (3 bits, B010) + data_result = matchData(&(results->rawbuf[offset]), kGreeBlockFooterBits, + kGreeBitMark, kGreeOneSpace, kGreeBitMark, + kGreeZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + if (data_result.data != kGreeBlockFooter) return false; + offset += data_result.used; + + // Inter-block gap. + if (!matchMark(results->rawbuf[offset++], kGreeBitMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kGreeMsgSpace)) return false; + + // Data Block #2 (32 bits) + data_result = + matchData(&(results->rawbuf[offset]), 32, kGreeBitMark, kGreeOneSpace, + kGreeBitMark, kGreeZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Record Data Block #2 in the state. + for (uint16_t i = 0; i < 4; i++, data >>= 8) + results->state[state_pos + i] = data & 0xFF; + state_pos += 4; + + // Footer. + if (!matchMark(results->rawbuf[offset++], kGreeBitMark)) return false; + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset], kGreeMsgSpace)) + return false; + + // Compliance + if (strict) { + // Correct size/length) + if (state_pos != kGreeStateLength) return false; + // Verify the message's checksum is correct. + if (!IRGreeAC::validChecksum(results->state)) return false; + } + + // Success + results->decode_type = GREE; + results->bits = state_pos * 8; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_GREE diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h new file mode 100644 index 000000000..73f69eb31 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h @@ -0,0 +1,130 @@ +// Kelvinator A/C +// +// Copyright 2016 David Conran + +#ifndef IR_GREE_H_ +#define IR_GREE_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// GGGG RRRRRR EEEEEEE EEEEEEE +// GG GG RR RR EE EE +// GG RRRRRR EEEEE EEEEE +// GG GG RR RR EE EE +// GGGGGG RR RR EEEEEEE EEEEEEE + +// Constants +const uint8_t kGreeAuto = 0; +const uint8_t kGreeCool = 1; +const uint8_t kGreeDry = 2; +const uint8_t kGreeFan = 3; +const uint8_t kGreeHeat = 4; + +// Byte 0 +const uint8_t kGreeModeMask = 0b00000111; +const uint8_t kGreePower1Mask = 0b00001000; +const uint8_t kGreeFanMask = 0b00110000; +const uint8_t kGreeSwingAutoMask = 0b01000000; +const uint8_t kGreeSleepMask = 0b10000000; +// Byte 2 +const uint8_t kGreeTurboMask = 0b00010000; +const uint8_t kGreeLightMask = 0b00100000; +const uint8_t kGreePower2Mask = 0b01000000; +const uint8_t kGreeXfanMask = 0b10000000; +// Byte 4 +const uint8_t kGreeSwingPosMask = 0b00001111; + +const uint8_t kGreeMinTemp = 16; // Celsius +const uint8_t kGreeMaxTemp = 30; // Celsius +const uint8_t kGreeFanMax = 3; + +const uint8_t kGreeSwingLastPos = 0b00000000; +const uint8_t kGreeSwingAuto = 0b00000001; +const uint8_t kGreeSwingUp = 0b00000010; +const uint8_t kGreeSwingMiddleUp = 0b00000011; +const uint8_t kGreeSwingMiddle = 0b00000100; +const uint8_t kGreeSwingMiddleDown = 0b00000101; +const uint8_t kGreeSwingDown = 0b00000110; +const uint8_t kGreeSwingDownAuto = 0b00000111; +const uint8_t kGreeSwingMiddleAuto = 0b00001001; +const uint8_t kGreeSwingUpAuto = 0b00001011; + +// Legacy defines. +#define GREE_AUTO kGreeAuto +#define GREE_COOL kGreeCool +#define GREE_DRY kGreeDry +#define GREE_FAN kGreeFan +#define GREE_HEAT kGreeHeat +#define GREE_MIN_TEMP kGreeMinTemp +#define GREE_MAX_TEMP kGreeMaxTemp +#define GREE_FAN_MAX kGreeFanMax +#define GREE_SWING_LAST_POS kGreeSwingLastPos +#define GREE_SWING_AUTO kGreeSwingAuto +#define GREE_SWING_UP kGreeSwingUp +#define GREE_SWING_MIDDLE_UP kGreeSwingMiddleUp +#define GREE_SWING_MIDDLE kGreeSwingMiddle +#define GREE_SWING_MIDDLE_DOWN kGreeSwingMiddleDown +#define GREE_SWING_DOWN kGreeSwingDown +#define GREE_SWING_DOWN_AUTO kGreeSwingDownAuto +#define GREE_SWING_MIDDLE_AUTO kGreeSwingMiddleAuto +#define GREE_SWING_UP_AUTO kGreeSwingUpAuto + +// Classes +class IRGreeAC { + public: + explicit IRGreeAC(uint16_t pin); + + void stateReset(); +#if SEND_GREE + void send(); +#endif // SEND_GREE + void begin(); + void on(); + void off(); + void setPower(const bool state); + bool getPower(); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setFan(const uint8_t speed); + uint8_t getFan(); + void setMode(const uint8_t new_mode); + uint8_t getMode(); + void setLight(const bool state); + bool getLight(); + void setXFan(const bool state); + bool getXFan(); + void setSleep(const bool state); + bool getSleep(); + void setTurbo(const bool state); + bool getTurbo(); + void setSwingVertical(const bool automatic, const uint8_t position); + bool getSwingVerticalAuto(); + uint8_t getSwingVerticalPosition(); + + uint8_t* getRaw(); + void setRaw(uint8_t new_code[]); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kGreeStateLength); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: + // The state of the IR remote in IR code form. + uint8_t remote_state[kGreeStateLength]; + void checksum(const uint16_t length = kGreeStateLength); + void fixup(); + IRsend _irsend; +}; + +#endif // IR_GREE_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp new file mode 100644 index 000000000..2c47e4eac --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp @@ -0,0 +1,865 @@ +// Copyright 2018 crankyoldgit +// The specifics of reverse engineering the protocols details: +// * HSU07-HEA03 by kuzin2006. +// * YR-W02/HSU-09HMC203 by non7top. + +#include "ir_Haier.h" +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRutils.h" + +// HH HH AAA IIIII EEEEEEE RRRRRR +// HH HH AAAAA III EE RR RR +// HHHHHHH AA AA III EEEEE RRRRRR +// HH HH AAAAAAA III EE RR RR +// HH HH AA AA IIIII EEEEEEE RR RR + +// Supported devices: +// * Haier HSU07-HEA03 Remote control. +// * Haier YR-W02 Remote control +// * Haier HSU-09HMC203 A/C unit. + +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/404 +// https://www.dropbox.com/s/mecyib3lhdxc8c6/IR%20data%20reverse%20engineering.xlsx?dl=0 +// https://github.com/markszabo/IRremoteESP8266/issues/485 +// https://www.dropbox.com/sh/w0bt7egp0fjger5/AADRFV6Wg4wZskJVdFvzb8Z0a?dl=0&preview=haer2.ods + +// Constants +const uint16_t kHaierAcHdr = 3000; +const uint16_t kHaierAcHdrGap = 4300; +const uint16_t kHaierAcBitMark = 520; +const uint16_t kHaierAcOneSpace = 1650; +const uint16_t kHaierAcZeroSpace = 650; +const uint32_t kHaierAcMinGap = 150000; // Completely made up value. + +#if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02) +// Send a Haier A/C message. (HSU07-HEA03 remote) +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHaierACStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: Beta / Probably working. +// +void IRsend::sendHaierAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kHaierACStateLength) return; + + for (uint16_t r = 0; r <= repeat; r++) { + enableIROut(38000); + mark(kHaierAcHdr); + space(kHaierAcHdr); + sendGeneric(kHaierAcHdr, kHaierAcHdrGap, kHaierAcBitMark, kHaierAcOneSpace, + kHaierAcBitMark, kHaierAcZeroSpace, kHaierAcBitMark, + kHaierAcMinGap, data, nbytes, 38, true, + 0, // Repeats handled elsewhere + 50); + } +} +#endif // (SEND_HAIER_AC || SEND_HAIER_AC_YRW02) + +#if SEND_HAIER_AC_YRW02 +// Send a Haier YR-W02 remote A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHaierACYRW02StateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: Alpha / Untested on a real device. +// +void IRsend::sendHaierACYRW02(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes >= kHaierACYRW02StateLength) sendHaierAC(data, nbytes, repeat); +} +#endif // SEND_HAIER_AC_YRW02 + +// Class for emulating a Haier HSU07-HEA03 remote +IRHaierAC::IRHaierAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRHaierAC::begin() { _irsend.begin(); } + +#if SEND_HAIER_AC +void IRHaierAC::send() { + checksum(); + _irsend.sendHaierAC(remote_state); +} +#endif // SEND_HAIER_AC + +void IRHaierAC::checksum() { + remote_state[8] = sumBytes(remote_state, kHaierACStateLength - 1); +} + +bool IRHaierAC::validChecksum(uint8_t state[], const uint16_t length) { + if (length < 2) return false; // 1 byte of data can't have a checksum. + return (state[length - 1] == sumBytes(state, length - 1)); +} + +void IRHaierAC::stateReset() { + for (uint8_t i = 1; i < kHaierACStateLength; i++) remote_state[i] = 0x0; + remote_state[0] = kHaierAcPrefix; + remote_state[2] = 0b00100000; + + setTemp(kHaierAcDefTemp); + setFan(kHaierAcFanAuto); + setMode(kHaierAcAuto); + setCommand(kHaierAcCmdOn); +} + +uint8_t* IRHaierAC::getRaw() { + checksum(); + return remote_state; +} + +void IRHaierAC::setRaw(uint8_t new_code[]) { + for (uint8_t i = 0; i < kHaierACStateLength; i++) { + remote_state[i] = new_code[i]; + } +} + +void IRHaierAC::setCommand(uint8_t state) { + remote_state[1] &= 0b11110000; + switch (state) { + case kHaierAcCmdOff: + case kHaierAcCmdOn: + case kHaierAcCmdMode: + case kHaierAcCmdFan: + case kHaierAcCmdTempUp: + case kHaierAcCmdTempDown: + case kHaierAcCmdSleep: + case kHaierAcCmdTimerSet: + case kHaierAcCmdTimerCancel: + case kHaierAcCmdHealth: + case kHaierAcCmdSwing: + remote_state[1] |= (state & 0b00001111); + } +} + +uint8_t IRHaierAC::getCommand() { return remote_state[1] & (0b00001111); } + +void IRHaierAC::setFan(uint8_t speed) { + uint8_t new_speed = kHaierAcFanAuto; + switch (speed) { + case kHaierAcFanLow: + new_speed = 3; + break; + case kHaierAcFanMed: + new_speed = 1; + break; + case kHaierAcFanHigh: + new_speed = 2; + break; + default: + new_speed = kHaierAcFanAuto; // Default to auto for anything else. + } + + if (speed != getFan()) setCommand(kHaierAcCmdFan); + remote_state[5] &= 0b11111100; + remote_state[5] |= new_speed; +} + +uint8_t IRHaierAC::getFan() { + switch (remote_state[5] & 0b00000011) { + case 1: + return kHaierAcFanMed; + case 2: + return kHaierAcFanHigh; + case 3: + return kHaierAcFanLow; + default: + return kHaierAcFanAuto; + } +} + +void IRHaierAC::setMode(uint8_t mode) { + uint8_t new_mode = mode; + setCommand(kHaierAcCmdMode); + if (mode > kHaierAcFan) // If out of range, default to auto mode. + new_mode = kHaierAcAuto; + remote_state[7] &= 0b00011111; + remote_state[7] |= (new_mode << 5); +} + +uint8_t IRHaierAC::getMode() { return (remote_state[7] & 0b11100000) >> 5; } + +void IRHaierAC::setTemp(const uint8_t celsius) { + uint8_t temp = celsius; + if (temp < kHaierAcMinTemp) + temp = kHaierAcMinTemp; + else if (temp > kHaierAcMaxTemp) + temp = kHaierAcMaxTemp; + + uint8_t old_temp = getTemp(); + if (old_temp == temp) return; + if (old_temp > temp) + setCommand(kHaierAcCmdTempDown); + else + setCommand(kHaierAcCmdTempUp); + + remote_state[1] &= 0b00001111; // Clear the previous temp. + remote_state[1] |= ((temp - kHaierAcMinTemp) << 4); +} + +uint8_t IRHaierAC::getTemp() { + return ((remote_state[1] & 0b11110000) >> 4) + kHaierAcMinTemp; +} + +void IRHaierAC::setHealth(bool state) { + setCommand(kHaierAcCmdHealth); + remote_state[4] &= 0b11011111; + remote_state[4] |= (state << 5); +} + +bool IRHaierAC::getHealth(void) { return remote_state[4] & (1 << 5); } + +void IRHaierAC::setSleep(bool state) { + setCommand(kHaierAcCmdSleep); + remote_state[7] &= 0b10111111; + remote_state[7] |= (state << 6); +} + +bool IRHaierAC::getSleep(void) { return remote_state[7] & 0b01000000; } + +uint16_t IRHaierAC::getTime(const uint8_t ptr[]) { + return (ptr[0] & 0b00011111) * 60 + (ptr[1] & 0b00111111); +} + +int16_t IRHaierAC::getOnTimer() { + if (remote_state[3] & 0b10000000) // Check if the timer is turned on. + return getTime(remote_state + 6); + else + return -1; +} + +int16_t IRHaierAC::getOffTimer() { + if (remote_state[3] & 0b01000000) // Check if the timer is turned on. + return getTime(remote_state + 4); + else + return -1; +} + +uint16_t IRHaierAC::getCurrTime() { return getTime(remote_state + 2); } + +void IRHaierAC::setTime(uint8_t ptr[], const uint16_t nr_mins) { + uint16_t mins = nr_mins; + if (nr_mins > kHaierAcMaxTime) mins = kHaierAcMaxTime; + + // Hours + ptr[0] &= 0b11100000; + ptr[0] |= (mins / 60); + // Minutes + ptr[1] &= 0b11000000; + ptr[1] |= (mins % 60); +} + +void IRHaierAC::setOnTimer(const uint16_t nr_mins) { + setCommand(kHaierAcCmdTimerSet); + remote_state[3] |= 0b10000000; + setTime(remote_state + 6, nr_mins); +} + +void IRHaierAC::setOffTimer(const uint16_t nr_mins) { + setCommand(kHaierAcCmdTimerSet); + remote_state[3] |= 0b01000000; + setTime(remote_state + 4, nr_mins); +} + +void IRHaierAC::cancelTimers() { + setCommand(kHaierAcCmdTimerCancel); + remote_state[3] &= 0b00111111; +} + +void IRHaierAC::setCurrTime(const uint16_t nr_mins) { + setTime(remote_state + 2, nr_mins); +} + +uint8_t IRHaierAC::getSwing() { return (remote_state[2] & 0b11000000) >> 6; } + +void IRHaierAC::setSwing(const uint8_t state) { + if (state == getSwing()) return; // Nothing to do. + setCommand(kHaierAcCmdSwing); + switch (state) { + case kHaierAcSwingOff: + case kHaierAcSwingUp: + case kHaierAcSwingDown: + case kHaierAcSwingChg: + remote_state[2] &= 0b00111111; + remote_state[2] |= (state << 6); + break; + } +} + +// Convert a Haier time into a human readable string. +#ifdef ARDUINO +String IRHaierAC::timeToString(const uint16_t nr_mins) { + String result = ""; +#else +std::string IRHaierAC::timeToString(const uint16_t nr_mins) { + std::string result = ""; +#endif // ARDUINO + + if (nr_mins / 24 < 10) result += "0"; // Zero pad. + result += uint64ToString(nr_mins / 60); + result += ":"; + if (nr_mins % 60 < 10) result += "0"; // Zero pad. + result += uint64ToString(nr_mins % 60); + return result; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRHaierAC::toString() { + String result = ""; +#else +std::string IRHaierAC::toString() { + std::string result = ""; +#endif // ARDUINO + uint8_t cmd = getCommand(); + result += "Command: " + uint64ToString(cmd) + " ("; + switch (cmd) { + case kHaierAcCmdOff: + result += "Off"; + break; + case kHaierAcCmdOn: + result += "On"; + break; + case kHaierAcCmdMode: + result += "Mode"; + break; + case kHaierAcCmdFan: + result += "Fan"; + break; + case kHaierAcCmdTempUp: + result += "Temp Up"; + break; + case kHaierAcCmdTempDown: + result += "Temp Down"; + break; + case kHaierAcCmdSleep: + result += "Sleep"; + break; + case kHaierAcCmdTimerSet: + result += "Timer Set"; + break; + case kHaierAcCmdTimerCancel: + result += "Timer Cancel"; + break; + case kHaierAcCmdHealth: + result += "Health"; + break; + case kHaierAcCmdSwing: + result += "Swing"; + break; + default: + result += "Unknown"; + } + result += ")"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kHaierAcAuto: + result += " (AUTO)"; + break; + case kHaierAcCool: + result += " (COOL)"; + break; + case kHaierAcHeat: + result += " (HEAT)"; + break; + case kHaierAcDry: + result += " (DRY)"; + break; + case kHaierAcFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kHaierAcFanAuto: + result += " (AUTO)"; + break; + case kHaierAcFanHigh: + result += " (MAX)"; + break; + } + result += ", Swing: " + uint64ToString(getSwing()) + " ("; + switch (getSwing()) { + case kHaierAcSwingOff: + result += "Off"; + break; + case kHaierAcSwingUp: + result += "Up"; + break; + case kHaierAcSwingDown: + result += "Down"; + break; + case kHaierAcSwingChg: + result += "Chg"; + break; + default: + result += "Unknown"; + } + result += ")"; + result += ", Sleep: "; + if (getSleep()) + result += "On"; + else + result += "Off"; + result += ", Health: "; + if (getHealth()) + result += "On"; + else + result += "Off"; + result += ", Current Time: " + timeToString(getCurrTime()); + result += ", On Timer: "; + if (getOnTimer() >= 0) + result += timeToString(getOnTimer()); + else + result += "Off"; + result += ", Off Timer: "; + if (getOffTimer() >= 0) + result += timeToString(getOffTimer()); + else + result += "Off"; + + return result; +} +// End of IRHaierAC class. + +// Class for emulating a Haier YRW02 remote +IRHaierACYRW02::IRHaierACYRW02(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRHaierACYRW02::begin() { _irsend.begin(); } + +#if SEND_HAIER_AC_YRW02 +void IRHaierACYRW02::send() { + checksum(); + _irsend.sendHaierACYRW02(remote_state); +} +#endif // SEND_HAIER_AC_YRW02 + +void IRHaierACYRW02::checksum() { + remote_state[kHaierACYRW02StateLength - 1] = + sumBytes(remote_state, kHaierACYRW02StateLength - 1); +} + +bool IRHaierACYRW02::validChecksum(uint8_t state[], const uint16_t length) { + if (length < 2) return false; // 1 byte of data can't have a checksum. + return (state[length - 1] == sumBytes(state, length - 1)); +} + +void IRHaierACYRW02::stateReset() { + for (uint8_t i = 1; i < kHaierACYRW02StateLength; i++) remote_state[i] = 0x0; + remote_state[0] = kHaierAcYrw02Prefix; + + setTemp(kHaierAcDefTemp); + setHealth(true); + setTurbo(kHaierAcYrw02TurboOff); + setSleep(false); + setFan(kHaierAcYrw02FanAuto); + setSwing(kHaierAcYrw02SwingOff); + setMode(kHaierAcYrw02Auto); + setPower(true); +} + +uint8_t* IRHaierACYRW02::getRaw() { + checksum(); + return remote_state; +} + +void IRHaierACYRW02::setRaw(uint8_t new_code[]) { + for (uint8_t i = 0; i < kHaierACYRW02StateLength; i++) { + remote_state[i] = new_code[i]; + } +} + +void IRHaierACYRW02::setButton(uint8_t button) { + switch (button) { + case kHaierAcYrw02ButtonTempUp: + case kHaierAcYrw02ButtonTempDown: + case kHaierAcYrw02ButtonSwing: + case kHaierAcYrw02ButtonFan: + case kHaierAcYrw02ButtonPower: + case kHaierAcYrw02ButtonMode: + case kHaierAcYrw02ButtonHealth: + case kHaierAcYrw02ButtonTurbo: + case kHaierAcYrw02ButtonSleep: + remote_state[12] &= 0b11110000; + remote_state[12] |= (button & 0b00001111); + } +} + +uint8_t IRHaierACYRW02::getButton() { return remote_state[12] & (0b00001111); } + +void IRHaierACYRW02::setMode(uint8_t mode) { + uint8_t new_mode = mode; + setButton(kHaierAcYrw02ButtonMode); + switch (mode) { + case kHaierAcYrw02Auto: + case kHaierAcYrw02Cool: + case kHaierAcYrw02Dry: + case kHaierAcYrw02Heat: + case kHaierAcYrw02Fan: + break; + default: // If unexpected, default to auto mode. + new_mode = kHaierAcYrw02Auto; + } + remote_state[7] &= 0b0001111; + remote_state[7] |= (new_mode << 4); +} + +uint8_t IRHaierACYRW02::getMode() { return remote_state[7] >> 4; } + +void IRHaierACYRW02::setTemp(const uint8_t celcius) { + uint8_t temp = celcius; + if (temp < kHaierAcMinTemp) + temp = kHaierAcMinTemp; + else if (temp > kHaierAcMaxTemp) + temp = kHaierAcMaxTemp; + + uint8_t old_temp = getTemp(); + if (old_temp == temp) return; + if (old_temp > temp) + setButton(kHaierAcYrw02ButtonTempDown); + else + setButton(kHaierAcYrw02ButtonTempUp); + + remote_state[1] &= 0b00001111; // Clear the previous temp. + remote_state[1] |= ((temp - kHaierAcMinTemp) << 4); +} + +uint8_t IRHaierACYRW02::getTemp() { + return ((remote_state[1] & 0b11110000) >> 4) + kHaierAcMinTemp; +} + +void IRHaierACYRW02::setHealth(bool state) { + setButton(kHaierAcYrw02ButtonHealth); + remote_state[3] &= 0b11111101; + remote_state[3] |= (state << 1); +} + +bool IRHaierACYRW02::getHealth(void) { return remote_state[3] & 0b00000010; } + +bool IRHaierACYRW02::getPower() { return remote_state[4] & kHaierAcYrw02Power; } + +void IRHaierACYRW02::setPower(bool state) { + setButton(kHaierAcYrw02ButtonPower); + if (state) + remote_state[4] |= kHaierAcYrw02Power; + else + remote_state[4] &= ~kHaierAcYrw02Power; +} + +void IRHaierACYRW02::on() { setPower(true); } + +void IRHaierACYRW02::off() { setPower(false); } + +bool IRHaierACYRW02::getSleep() { return remote_state[8] & kHaierAcYrw02Sleep; } + +void IRHaierACYRW02::setSleep(bool state) { + setButton(kHaierAcYrw02ButtonSleep); + if (state) + remote_state[8] |= kHaierAcYrw02Sleep; + else + remote_state[8] &= ~kHaierAcYrw02Sleep; +} + +uint8_t IRHaierACYRW02::getTurbo() { return remote_state[6] >> 6; } + +void IRHaierACYRW02::setTurbo(uint8_t speed) { + switch (speed) { + case kHaierAcYrw02TurboOff: + case kHaierAcYrw02TurboLow: + case kHaierAcYrw02TurboHigh: + remote_state[6] &= 0b00111111; + remote_state[6] |= (speed << 6); + setButton(kHaierAcYrw02ButtonTurbo); + } +} + +uint8_t IRHaierACYRW02::getFan() { return remote_state[5] >> 4; } + +void IRHaierACYRW02::setFan(uint8_t speed) { + switch (speed) { + case kHaierAcYrw02FanLow: + case kHaierAcYrw02FanMed: + case kHaierAcYrw02FanHigh: + case kHaierAcYrw02FanAuto: + remote_state[5] &= 0b00001111; + remote_state[5] |= (speed << 4); + setButton(kHaierAcYrw02ButtonFan); + } +} + +uint8_t IRHaierACYRW02::getSwing() { return remote_state[1] & 0b00001111; } + +void IRHaierACYRW02::setSwing(uint8_t state) { + uint8_t newstate = state; + switch (state) { + case kHaierAcYrw02SwingOff: + case kHaierAcYrw02SwingAuto: + case kHaierAcYrw02SwingTop: + case kHaierAcYrw02SwingMiddle: + case kHaierAcYrw02SwingBottom: + case kHaierAcYrw02SwingDown: + setButton(kHaierAcYrw02ButtonSwing); + break; + default: + return; // Unexpected value so don't do anything. + } + + // Heat mode has no MIDDLE setting, use BOTTOM instead. + if (state == kHaierAcYrw02SwingMiddle && getMode() == kHaierAcYrw02Heat) + newstate = kHaierAcYrw02SwingBottom; + + // BOTTOM is only allowed if we are in Heat mode, otherwise MIDDLE. + if (state == kHaierAcYrw02SwingBottom && getMode() != kHaierAcYrw02Heat) + newstate = kHaierAcYrw02SwingMiddle; + + remote_state[1] &= 0b11110000; + remote_state[1] |= newstate; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRHaierACYRW02::toString() { + String result = ""; +#else +std::string IRHaierACYRW02::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + uint8_t cmd = getButton(); + result += ", Button: " + uint64ToString(cmd) + " ("; + switch (cmd) { + case kHaierAcYrw02ButtonPower: + result += "Power"; + break; + case kHaierAcYrw02ButtonMode: + result += "Mode"; + break; + case kHaierAcYrw02ButtonFan: + result += "Fan"; + break; + case kHaierAcYrw02ButtonTempUp: + result += "Temp Up"; + break; + case kHaierAcYrw02ButtonTempDown: + result += "Temp Down"; + break; + case kHaierAcYrw02ButtonSleep: + result += "Sleep"; + break; + case kHaierAcYrw02ButtonHealth: + result += "Health"; + break; + case kHaierAcYrw02ButtonSwing: + result += "Swing"; + break; + case kHaierAcYrw02ButtonTurbo: + result += "Turbo"; + break; + default: + result += "Unknown"; + } + result += ")"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kHaierAcYrw02Auto: + result += " (Auto)"; + break; + case kHaierAcYrw02Cool: + result += " (Cool)"; + break; + case kHaierAcYrw02Heat: + result += " (Heat)"; + break; + case kHaierAcYrw02Dry: + result += " (Dry)"; + break; + case kHaierAcYrw02Fan: + result += " (Fan)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kHaierAcYrw02FanAuto: + result += " (Auto)"; + break; + case kHaierAcYrw02FanHigh: + result += " (High)"; + break; + case kHaierAcYrw02FanLow: + result += " (Low)"; + break; + case kHaierAcYrw02FanMed: + result += " (Med)"; + break; + default: + result += " (Unknown)"; + } + result += ", Turbo: " + uint64ToString(getTurbo()) + " ("; + switch (getTurbo()) { + case kHaierAcYrw02TurboOff: + result += "Off"; + break; + case kHaierAcYrw02TurboLow: + result += "Low"; + break; + case kHaierAcYrw02TurboHigh: + result += "High"; + break; + default: + result += "Unknown"; + } + result += ")"; + result += ", Swing: " + uint64ToString(getSwing()) + " ("; + switch (getSwing()) { + case kHaierAcYrw02SwingOff: + result += "Off"; + break; + case kHaierAcYrw02SwingAuto: + result += "Auto"; + break; + case kHaierAcYrw02SwingBottom: + result += "Bottom"; + break; + case kHaierAcYrw02SwingDown: + result += "Down"; + break; + case kHaierAcYrw02SwingTop: + result += "Top"; + break; + case kHaierAcYrw02SwingMiddle: + result += "Middle"; + break; + default: + result += "Unknown"; + } + result += ")"; + result += ", Sleep: "; + if (getSleep()) + result += "On"; + else + result += "Off"; + result += ", Health: "; + if (getHealth()) + result += "On"; + else + result += "Off"; + + return result; +} +// End of IRHaierACYRW02 class. + +#if (DECODE_HAIER_AC || DECODE_HAIER_AC_YRW02) +// Decode the supplied Haier HSU07-HEA03 remote message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kHaierACBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Appears to be working. +// +bool IRrecv::decodeHaierAC(decode_results* results, uint16_t nbits, + bool strict) { + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + + if (strict) { + if (nbits != kHaierACBits) + return false; // Not strictly a HAIER_AC message. + } + + if (results->rawlen < (2 * nbits + kHeader) + kFooter - 1) + return false; // Can't possibly be a valid HAIER_AC message. + + uint16_t offset = kStartOffset; + + // Header + if (!matchMark(results->rawbuf[offset++], kHaierAcHdr)) return false; + if (!matchSpace(results->rawbuf[offset++], kHaierAcHdr)) return false; + if (!matchMark(results->rawbuf[offset++], kHaierAcHdr)) return false; + if (!matchSpace(results->rawbuf[offset++], kHaierAcHdrGap)) return false; + + // Data + for (uint16_t i = 0; i < nbits / 8; i++) { + match_result_t data_result = + matchData(&(results->rawbuf[offset]), 8, kHaierAcBitMark, + kHaierAcOneSpace, kHaierAcBitMark, kHaierAcZeroSpace); + if (data_result.success == false) return false; + offset += data_result.used; + results->state[i] = (uint8_t)data_result.data; + } + + // Footer + if (!matchMark(results->rawbuf[offset++], kHaierAcBitMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kHaierAcMinGap)) + return false; + + // Compliance + if (strict) { + if (results->state[0] != kHaierAcPrefix) return false; + if (!IRHaierAC::validChecksum(results->state, nbits / 8)) return false; + } + + // Success + results->decode_type = HAIER_AC; + results->bits = nbits; + return true; +} +#endif // (DECODE_HAIER_AC || DECODE_HAIER_AC_YRW02) + +#if DECODE_HAIER_AC_YRW02 +// Decode the supplied Haier YR-W02 remote A/C message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kHaierACYRW02Bits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Appears to be working. +// +bool IRrecv::decodeHaierACYRW02(decode_results* results, uint16_t nbits, + bool strict) { + if (strict) { + if (nbits != kHaierACYRW02Bits) + return false; // Not strictly a HAIER_AC_YRW02 message. + } + + // The protocol is almost exactly the same as HAIER_AC + if (!decodeHaierAC(results, nbits, false)) return false; + + // Compliance + if (strict) { + if (results->state[0] != kHaierAcYrw02Prefix) return false; + if (!IRHaierACYRW02::validChecksum(results->state, nbits / 8)) return false; + } + + // Success + // It looks correct, but we haven't check the checksum etc. + results->decode_type = HAIER_AC_YRW02; + return true; +} +#endif // DECODE_HAIER_AC_YRW02 diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h new file mode 100644 index 000000000..fdc15a3a8 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h @@ -0,0 +1,297 @@ +// Copyright 2018 crankyoldgit +// The specifics of reverse engineering the protocol details by kuzin2006 + +#ifndef IR_HAIER_H_ +#define IR_HAIER_H_ + +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// HH HH AAA IIIII EEEEEEE RRRRRR +// HH HH AAAAA III EE RR RR +// HHHHHHH AA AA III EEEEE RRRRRR +// HH HH AAAAAAA III EE RR RR +// HH HH AA AA IIIII EEEEEEE RR RR + +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/404 +// https://www.dropbox.com/s/mecyib3lhdxc8c6/IR%20data%20reverse%20engineering.xlsx?dl=0 +// https://github.com/markszabo/IRremoteESP8266/issues/485 +// https://www.dropbox.com/sh/w0bt7egp0fjger5/AADRFV6Wg4wZskJVdFvzb8Z0a?dl=0&preview=haer2.ods + +// Constants + +// Haier HSU07-HEA03 remote +// Byte 0 +const uint8_t kHaierAcPrefix = 0b10100101; + +// Byte 1 +const uint8_t kHaierAcMinTemp = 16; +const uint8_t kHaierAcDefTemp = 25; +const uint8_t kHaierAcMaxTemp = 30; +const uint8_t kHaierAcCmdOff = 0b00000000; +const uint8_t kHaierAcCmdOn = 0b00000001; +const uint8_t kHaierAcCmdMode = 0b00000010; +const uint8_t kHaierAcCmdFan = 0b00000011; +const uint8_t kHaierAcCmdTempUp = 0b00000110; +const uint8_t kHaierAcCmdTempDown = 0b00000111; +const uint8_t kHaierAcCmdSleep = 0b00001000; +const uint8_t kHaierAcCmdTimerSet = 0b00001001; +const uint8_t kHaierAcCmdTimerCancel = 0b00001010; +const uint8_t kHaierAcCmdHealth = 0b00001100; +const uint8_t kHaierAcCmdSwing = 0b00001101; + +// Byte 2 +const uint8_t kHaierAcSwingOff = 0b00000000; +const uint8_t kHaierAcSwingUp = 0b00000001; +const uint8_t kHaierAcSwingDown = 0b00000010; +const uint8_t kHaierAcSwingChg = 0b00000011; + +// Byte 6 +const uint8_t kHaierAcAuto = 0; +const uint8_t kHaierAcCool = 1; +const uint8_t kHaierAcDry = 2; +const uint8_t kHaierAcHeat = 3; +const uint8_t kHaierAcFan = 4; + +const uint8_t kHaierAcFanAuto = 0; +const uint8_t kHaierAcFanLow = 1; +const uint8_t kHaierAcFanMed = 2; +const uint8_t kHaierAcFanHigh = 3; + +const uint16_t kHaierAcMaxTime = (23 * 60) + 59; + +// Legacy Haier AC defines. +#define HAIER_AC_MIN_TEMP kHaierAcMinTemp +#define HAIER_AC_DEF_TEMP kHaierAcDefTemp +#define HAIER_AC_MAX_TEMP kHaierAcMaxTemp +#define HAIER_AC_CMD_OFF kHaierAcCmdOff +#define HAIER_AC_CMD_ON kHaierAcCmdOn +#define HAIER_AC_CMD_MODE kHaierAcCmdMode +#define HAIER_AC_CMD_FAN kHaierAcCmdFan +#define HAIER_AC_CMD_TEMP_UP kHaierAcCmdTempUp +#define HAIER_AC_CMD_TEMP_DOWN kHaierAcCmdTempDown +#define HAIER_AC_CMD_SLEEP kHaierAcCmdSleep +#define HAIER_AC_CMD_TIMER_SET kHaierAcCmdTimerSet +#define HAIER_AC_CMD_TIMER_CANCEL kHaierAcCmdTimerCancel +#define HAIER_AC_CMD_HEALTH kHaierAcCmdHealth +#define HAIER_AC_CMD_SWING kHaierAcCmdSwing +#define HAIER_AC_SWING_OFF kHaierAcSwingOff +#define HAIER_AC_SWING_UP kHaierAcSwingUp +#define HAIER_AC_SWING_DOWN kHaierAcSwingDown +#define HAIER_AC_SWING_CHG kHaierAcSwingChg +#define HAIER_AC_AUTO kHaierAcAuto +#define HAIER_AC_COOL kHaierAcCool +#define HAIER_AC_DRY kHaierAcDry +#define HAIER_AC_HEAT kHaierAcHeat +#define HAIER_AC_FAN kHaierAcFan +#define HAIER_AC_FAN_AUTO kHaierAcFanAuto +#define HAIER_AC_FAN_LOW kHaierAcFanLow +#define HAIER_AC_FAN_MED kHaierAcFanMed +#define HAIER_AC_FAN_HIGH kHaierAcFanHigh + +// Haier YRW02 remote +// Byte 0 +const uint8_t kHaierAcYrw02Prefix = 0xA6; + +// Byte 1 +// Bits 0-3 +// 0x0 = 16DegC, ... 0xE = 30DegC +// Bits 4-7 - Swing +const uint8_t kHaierAcYrw02SwingOff = 0x0; +const uint8_t kHaierAcYrw02SwingTop = 0x1; +const uint8_t kHaierAcYrw02SwingMiddle = 0x2; // Not available in heat mode. +const uint8_t kHaierAcYrw02SwingBottom = 0x3; // Only available in heat mode. +const uint8_t kHaierAcYrw02SwingDown = 0xA; +const uint8_t kHaierAcYrw02SwingAuto = 0xC; // Airflow + +// Byte 3 +// Bit 7 - Health mode + +// Byte 4 +const uint8_t kHaierAcYrw02Power = 0b01000000; + +// Byte 5 +// Bits 0-3 +const uint8_t kHaierAcYrw02FanHigh = 0x2; +const uint8_t kHaierAcYrw02FanMed = 0x4; +const uint8_t kHaierAcYrw02FanLow = 0x6; +const uint8_t kHaierAcYrw02FanAuto = 0xA; + +// Byte 6 +// Bits 0-1 +const uint8_t kHaierAcYrw02TurboOff = 0x0; +const uint8_t kHaierAcYrw02TurboHigh = 0x1; +const uint8_t kHaierAcYrw02TurboLow = 0x2; + +// Byte 7 +// Bits 0-3 +const uint8_t kHaierAcYrw02Auto = 0x0; +const uint8_t kHaierAcYrw02Cool = 0x2; +const uint8_t kHaierAcYrw02Dry = 0x4; +const uint8_t kHaierAcYrw02Heat = 0x8; +const uint8_t kHaierAcYrw02Fan = 0xC; + +// Byte 8 +const uint8_t kHaierAcYrw02Sleep = 0b10000000; + +// Byte 12 +// Bits 4-7 +const uint8_t kHaierAcYrw02ButtonTempUp = 0x0; +const uint8_t kHaierAcYrw02ButtonTempDown = 0x1; +const uint8_t kHaierAcYrw02ButtonSwing = 0x2; +const uint8_t kHaierAcYrw02ButtonFan = 0x4; +const uint8_t kHaierAcYrw02ButtonPower = 0x5; +const uint8_t kHaierAcYrw02ButtonMode = 0x6; +const uint8_t kHaierAcYrw02ButtonHealth = 0x7; +const uint8_t kHaierAcYrw02ButtonTurbo = 0x8; +const uint8_t kHaierAcYrw02ButtonSleep = 0xB; + +// Legacy Haier YRW02 remote defines. +#define HAIER_AC_YRW02_SWING_OFF kHaierAcYrw02SwingOff +#define HAIER_AC_YRW02_SWING_TOP kHaierAcYrw02SwingTop +#define HAIER_AC_YRW02_SWING_MIDDLE kHaierAcYrw02SwingMiddle +#define HAIER_AC_YRW02_SWING_BOTTOM kHaierAcYrw02SwingBottom +#define HAIER_AC_YRW02_SWING_DOWN kHaierAcYrw02SwingDown +#define HAIER_AC_YRW02_SWING_AUTO kHaierAcYrw02SwingAuto +#define HAIER_AC_YRW02_FAN_HIGH kHaierAcYrw02FanHigh +#define HAIER_AC_YRW02_FAN_MED kHaierAcYrw02FanMed +#define HAIER_AC_YRW02_FAN_LOW kHaierAcYrw02FanLow +#define HAIER_AC_YRW02_FAN_AUTO kHaierAcYrw02FanAuto +#define HAIER_AC_YRW02_TURBO_OFF kHaierAcYrw02TurboOff +#define HAIER_AC_YRW02_TURBO_HIGH kHaierAcYrw02TurboHigh +#define HAIER_AC_YRW02_TURBO_LOW kHaierAcYrw02TurboLow +#define HAIER_AC_YRW02_AUTO kHaierAcYrw02Auto +#define HAIER_AC_YRW02_COOL kHaierAcYrw02Cool +#define HAIER_AC_YRW02_DRY kHaierAcYrw02Dry +#define HAIER_AC_YRW02_HEAT kHaierAcYrw02Heat +#define HAIER_AC_YRW02_FAN kHaierAcYrw02Fan +#define HAIER_AC_YRW02_BUTTON_TEMP_UP kHaierAcYrw02ButtonTempUp +#define HAIER_AC_YRW02_BUTTON_TEMP_DOWN kHaierAcYrw02ButtonTempDown +#define HAIER_AC_YRW02_BUTTON_SWING kHaierAcYrw02ButtonSwing +#define HAIER_AC_YRW02_BUTTON_FAN kHaierAcYrw02ButtonFan +#define HAIER_AC_YRW02_BUTTON_POWER kHaierAcYrw02ButtonPower +#define HAIER_AC_YRW02_BUTTON_MODE kHaierAcYrw02ButtonMode +#define HAIER_AC_YRW02_BUTTON_HEALTH kHaierAcYrw02ButtonHealth +#define HAIER_AC_YRW02_BUTTON_TURBO kHaierAcYrw02ButtonTurbo +#define HAIER_AC_YRW02_BUTTON_SLEEP kHaierAcYrw02ButtonSleep + +class IRHaierAC { + public: + explicit IRHaierAC(uint16_t pin); + +#if SEND_HAIER_AC + void send(); +#endif // SEND_HAIER_AC + void begin(); + + void setCommand(const uint8_t command); + uint8_t getCommand(); + + void setTemp(const uint8_t temp); + uint8_t getTemp(); + + void setFan(const uint8_t speed); + uint8_t getFan(); + + uint8_t getMode(); + void setMode(const uint8_t mode); + + bool getSleep(); + void setSleep(const bool state); + bool getHealth(); + void setHealth(const bool state); + + int16_t getOnTimer(); + void setOnTimer(const uint16_t mins); + int16_t getOffTimer(); + void setOffTimer(const uint16_t mins); + void cancelTimers(); + + uint16_t getCurrTime(); + void setCurrTime(const uint16_t mins); + + uint8_t getSwing(); + void setSwing(const uint8_t state); + + uint8_t* getRaw(); + void setRaw(uint8_t new_code[]); + static bool validChecksum(uint8_t state[], + const uint16_t length = kHaierACStateLength); +#ifdef ARDUINO + String toString(); + static String timeToString(const uint16_t nr_mins); +#else + std::string toString(); + static std::string timeToString(const uint16_t nr_mins); +#endif + + private: + uint8_t remote_state[kHaierACStateLength]; + void stateReset(); + void checksum(); + static uint16_t getTime(const uint8_t ptr[]); + static void setTime(uint8_t ptr[], const uint16_t nr_mins); + IRsend _irsend; +}; + +class IRHaierACYRW02 { + public: + explicit IRHaierACYRW02(uint16_t pin); + +#if SEND_HAIER_AC_YRW02 + void send(); +#endif // SEND_HAIER_AC_YRW02 + void begin(); + + void setButton(const uint8_t button); + uint8_t getButton(); + + void setTemp(const uint8_t temp); + uint8_t getTemp(); + + void setFan(const uint8_t speed); + uint8_t getFan(); + + uint8_t getMode(); + void setMode(const uint8_t mode); + + bool getPower(); + void setPower(const bool state); + void on(); + void off(); + + bool getSleep(); + void setSleep(const bool state); + bool getHealth(); + void setHealth(const bool state); + + uint8_t getTurbo(); + void setTurbo(const uint8_t speed); + + uint8_t getSwing(); + void setSwing(const uint8_t state); + + uint8_t* getRaw(); + void setRaw(uint8_t new_code[]); + static bool validChecksum(uint8_t state[], + const uint16_t length = kHaierACYRW02StateLength); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: + uint8_t remote_state[kHaierACYRW02StateLength]; + void stateReset(); + void checksum(); + IRsend _irsend; +}; + +#endif // IR_HAIER_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.cpp new file mode 100644 index 000000000..111051974 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.cpp @@ -0,0 +1,424 @@ +// Copyright 2018 David Conran +// +// Code to emulate Hitachi protocol compatible devices. +// Should be compatible with: +// * Hitachi RAS-35THA6 remote +// + +#include "ir_Hitachi.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRutils.h" + +// HH HH IIIII TTTTTTT AAA CCCCC HH HH IIIII +// HH HH III TTT AAAAA CC C HH HH III +// HHHHHHH III TTT AA AA CC HHHHHHH III +// HH HH III TTT AAAAAAA CC C HH HH III +// HH HH IIIII TTT AA AA CCCCC HH HH IIIII + +// Constants +// Ref: https://github.com/markszabo/IRremoteESP8266/issues/417 +const uint16_t kHitachiAcHdrMark = 3300; +const uint16_t kHitachiAcHdrSpace = 1700; +const uint16_t kHitachiAc1HdrMark = 3400; +const uint16_t kHitachiAc1HdrSpace = 3400; +const uint16_t kHitachiAcBitMark = 400; +const uint16_t kHitachiAcOneSpace = 1250; +const uint16_t kHitachiAcZeroSpace = 500; +const uint32_t kHitachiAcMinGap = 100000; // Completely made up value. + +#if (SEND_HITACHI_AC || SEND_HITACHI_AC2) +// Send a Hitachi A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHitachiAcStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: ALPHA / Untested. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/417 +void IRsend::sendHitachiAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kHitachiAcStateLength) + return; // Not enough bytes to send a proper message. + sendGeneric(kHitachiAcHdrMark, kHitachiAcHdrSpace, kHitachiAcBitMark, + kHitachiAcOneSpace, kHitachiAcBitMark, kHitachiAcZeroSpace, + kHitachiAcBitMark, kHitachiAcMinGap, data, nbytes, 38, true, + repeat, 50); +} +#endif // (SEND_HITACHI_AC || SEND_HITACHI_AC2) + +#if SEND_HITACHI_AC1 +// Send a Hitachi A/C 13-byte message. +// +// For devices: +// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHitachiAc1StateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: BETA / Appears to work. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/453 +// Basically the same as sendHitatchiAC() except different size and header. +void IRsend::sendHitachiAC1(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kHitachiAc1StateLength) + return; // Not enough bytes to send a proper message. + sendGeneric(kHitachiAc1HdrMark, kHitachiAc1HdrSpace, kHitachiAcBitMark, + kHitachiAcOneSpace, kHitachiAcBitMark, kHitachiAcZeroSpace, + kHitachiAcBitMark, kHitachiAcMinGap, data, nbytes, 38, true, + repeat, 50); +} +#endif // SEND_HITACHI_AC1 + +#if SEND_HITACHI_AC2 +// Send a Hitachi A/C 53-byte message. +// +// For devices: +// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kHitachiAc2StateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: BETA / Appears to work. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/417 +// Basically the same as sendHitatchiAC() except different size. +void IRsend::sendHitachiAC2(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kHitachiAc2StateLength) + return; // Not enough bytes to send a proper message. + sendHitachiAC(data, nbytes, repeat); +} +#endif // SEND_HITACHI_AC2 + +// Class for handling the remote control oh a Hitachi 28 byte A/C message. +// Inspired by: +// https://github.com/ToniA/arduino-heatpumpir/blob/master/HitachiHeatpumpIR.cpp + +IRHitachiAc::IRHitachiAc(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRHitachiAc::stateReset() { + remote_state[0] = 0x80; + remote_state[1] = 0x08; + remote_state[2] = 0x0C; + remote_state[3] = 0x02; + remote_state[4] = 0xFD; + remote_state[5] = 0x80; + remote_state[6] = 0x7F; + remote_state[7] = 0x88; + remote_state[8] = 0x48; + remote_state[9] = 0x10; + for (uint8_t i = 10; i < kHitachiAcStateLength; i++) remote_state[i] = 0x00; + remote_state[14] = 0x60; + remote_state[15] = 0x60; + remote_state[24] = 0x80; + setTemp(23); +} + +void IRHitachiAc::begin() { _irsend.begin(); } + +uint8_t IRHitachiAc::calcChecksum(const uint8_t state[], + const uint16_t length) { + int8_t sum = 62; + for (uint16_t i = 0; i < length - 1; i++) sum -= reverseBits(state[i], 8); + return reverseBits((uint8_t)sum, 8); +} + +void IRHitachiAc::checksum(const uint16_t length) { + remote_state[length - 1] = calcChecksum(remote_state, length); +} + +bool IRHitachiAc::validChecksum(const uint8_t state[], const uint16_t length) { + if (length < 2) return true; // Assume true for lengths that are too short. + return (state[length - 1] == calcChecksum(state, length)); +} + +uint8_t *IRHitachiAc::getRaw() { + checksum(); + return remote_state; +} + +void IRHitachiAc::setRaw(const uint8_t new_code[], const uint16_t length) { + for (uint8_t i = 0; i < length && i < kHitachiAcStateLength; i++) + remote_state[i] = new_code[i]; +} + +#if SEND_HITACHI_AC +void IRHitachiAc::send() { + checksum(); + _irsend.sendHitachiAC(remote_state); +} +#endif // SEND_HITACHI_AC + +bool IRHitachiAc::getPower() { return (remote_state[17] & 0x01); } + +void IRHitachiAc::setPower(const bool on) { + if (on) + remote_state[17] |= 0x01; + else + remote_state[17] &= 0xFE; +} + +void IRHitachiAc::on() { setPower(true); } + +void IRHitachiAc::off() { setPower(false); } + +uint8_t IRHitachiAc::getMode() { return reverseBits(remote_state[10], 8); } + +void IRHitachiAc::setMode(const uint8_t mode) { + uint8_t newmode = mode; + switch (mode) { + case kHitachiAcFan: + // Fan mode sets a special temp. + setTemp(64); + break; + case kHitachiAcAuto: + case kHitachiAcHeat: + case kHitachiAcCool: + case kHitachiAcDry: + break; + default: + newmode = kHitachiAcAuto; + } + remote_state[10] = reverseBits(newmode, 8); + if (mode != kHitachiAcFan) setTemp(_previoustemp); + setFan(getFan()); // Reset the fan speed after the mode change. +} + +uint8_t IRHitachiAc::getTemp() { return reverseBits(remote_state[11], 8) >> 1; } + +void IRHitachiAc::setTemp(const uint8_t celsius) { + uint8_t temp; + if (celsius != 64) _previoustemp = celsius; + switch (celsius) { + case 64: + temp = celsius; + break; + default: + temp = std::min(celsius, kHitachiAcMaxTemp); + temp = std::max(temp, kHitachiAcMinTemp); + } + remote_state[11] = reverseBits(temp << 1, 8); + if (temp == kHitachiAcMinTemp) + remote_state[9] = 0x90; + else + remote_state[9] = 0x10; +} + +uint8_t IRHitachiAc::getFan() { return reverseBits(remote_state[13], 8); } + +void IRHitachiAc::setFan(const uint8_t speed) { + uint8_t fanmin = kHitachiAcFanAuto; + uint8_t fanmax = kHitachiAcFanHigh; + switch (getMode()) { + case kHitachiAcDry: // Only 2 x low speeds in Dry mode. + fanmin = kHitachiAcFanLow; + fanmax = kHitachiAcFanLow + 1; + break; + case kHitachiAcFan: + fanmin = kHitachiAcFanLow; // No Auto in Fan mode. + break; + } + uint8_t newspeed = std::max(speed, fanmin); + newspeed = std::min(newspeed, fanmax); + remote_state[13] = reverseBits(newspeed, 8); +} + +bool IRHitachiAc::getSwingVertical() { return remote_state[14] & 0x80; } + +void IRHitachiAc::setSwingVertical(const bool on) { + if (on) + remote_state[14] |= 0x80; + else + remote_state[14] &= 0x7F; +} + +bool IRHitachiAc::getSwingHorizontal() { return remote_state[15] & 0x80; } + +void IRHitachiAc::setSwingHorizontal(const bool on) { + if (on) + remote_state[15] |= 0x80; + else + remote_state[15] &= 0x7F; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRHitachiAc::toString() { + String result = ""; +#else +std::string IRHitachiAc::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kHitachiAcAuto: + result += " (AUTO)"; + break; + case kHitachiAcCool: + result += " (COOL)"; + break; + case kHitachiAcHeat: + result += " (HEAT)"; + break; + case kHitachiAcDry: + result += " (DRY)"; + break; + case kHitachiAcFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kHitachiAcFanAuto: + result += " (AUTO)"; + break; + case kHitachiAcFanLow: + result += " (LOW)"; + break; + case kHitachiAcFanHigh: + result += " (HIGH)"; + break; + default: + result += " (UNKNOWN)"; + break; + } + result += ", Swing (Vertical): "; + if (getSwingVertical()) + result += "On"; + else + result += "Off"; + result += ", Swing (Horizontal): "; + if (getSwingHorizontal()) + result += "On"; + else + result += "Off"; + return result; +} + +#if (DECODE_HITACHI_AC || DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2) +// Decode the supplied Hitachi A/C message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. +// Typically kHitachiAcBits, kHitachiAc1Bits, kHitachiAc2Bits +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +// +// Supported devices: +// Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/417 +// https://github.com/markszabo/IRremoteESP8266/issues/453 +bool IRrecv::decodeHitachiAC(decode_results *results, uint16_t nbits, + bool strict) { + const uint8_t kTolerance = 30; + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid HitachiAC message. + if (strict) { + switch (nbits) { + case kHitachiAcBits: + case kHitachiAc1Bits: + case kHitachiAc2Bits: + break; // Okay to continue. + default: + return false; // Not strictly a Hitachi message. + } + } + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + match_result_t data_result; + + // Header + if (nbits == kHitachiAc1Bits) { + if (!matchMark(results->rawbuf[offset++], kHitachiAc1HdrMark, kTolerance)) + return false; + if (!matchSpace(results->rawbuf[offset++], kHitachiAc1HdrSpace, kTolerance)) + return false; + } else { // Everything else. + if (!matchMark(results->rawbuf[offset++], kHitachiAcHdrMark, kTolerance)) + return false; + if (!matchSpace(results->rawbuf[offset++], kHitachiAcHdrSpace, kTolerance)) + return false; + } + // Data + // Keep reading bytes until we either run out of message or state to fill. + for (uint16_t i = 0; offset <= results->rawlen - 16 && i < nbits / 8; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData(&(results->rawbuf[offset]), 8, kHitachiAcBitMark, + kHitachiAcOneSpace, kHitachiAcBitMark, + kHitachiAcZeroSpace, kTolerance); + if (data_result.success == false) break; // Fail + results->state[i] = (uint8_t)data_result.data; + } + + // Footer + if (!matchMark(results->rawbuf[offset++], kHitachiAcBitMark, kTolerance)) + return false; + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset], kHitachiAcMinGap, kTolerance)) + return false; + + // Compliance + if (strict) { + // Re-check we got the correct size/length due to the way we read the data. + switch (dataBitsSoFar / 8) { + case kHitachiAcStateLength: + case kHitachiAc1StateLength: + case kHitachiAc2StateLength: + break; // Continue + default: + return false; + } + if (dataBitsSoFar / 8 == kHitachiAcStateLength && + !IRHitachiAc::validChecksum(results->state, kHitachiAcStateLength)) + return false; + } + + // Success + switch (dataBitsSoFar) { + case kHitachiAc1Bits: + results->decode_type = HITACHI_AC1; + break; + case kHitachiAc2Bits: + results->decode_type = HITACHI_AC2; + break; + case kHitachiAcBits: + default: + results->decode_type = HITACHI_AC; + } + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // (DECODE_HITACHI_AC || DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2) diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h new file mode 100644 index 000000000..eddab59e4 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h @@ -0,0 +1,76 @@ +// Hitachi A/C +// +// Copyright 2018 David Conran + +#ifndef IR_HITACHI_H_ +#define IR_HITACHI_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// Constants +const uint8_t kHitachiAcAuto = 2; +const uint8_t kHitachiAcHeat = 3; +const uint8_t kHitachiAcCool = 4; +const uint8_t kHitachiAcDry = 5; +const uint8_t kHitachiAcFan = 0xC; +const uint8_t kHitachiAcFanAuto = 1; +const uint8_t kHitachiAcFanLow = 2; +const uint8_t kHitachiAcFanHigh = 5; +const uint8_t kHitachiAcMinTemp = 16; // 16C +const uint8_t kHitachiAcMaxTemp = 32; // 32C +const uint8_t kHitachiAcAutoTemp = 23; // 23C + +// Classes +class IRHitachiAc { + public: + explicit IRHitachiAc(uint16_t pin); + + void stateReset(); +#if SEND_HITACHI_AC + void send(); +#endif // SEND_HITACHI_AC + void begin(); + void on(); + void off(); + void setPower(const bool on); + bool getPower(); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setFan(const uint8_t speed); + uint8_t getFan(); + void setMode(const uint8_t mode); + uint8_t getMode(); + void setSwingVertical(const bool on); + bool getSwingVertical(); + void setSwingHorizontal(const bool on); + bool getSwingHorizontal(); + uint8_t* getRaw(); + void setRaw(const uint8_t new_code[], + const uint16_t length = kHitachiAcStateLength); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kHitachiAcStateLength); + static uint8_t calcChecksum(const uint8_t state[], + const uint16_t length = kHitachiAcStateLength); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: + // The state of the IR remote in IR code form. + uint8_t remote_state[kHitachiAcStateLength]; + void checksum(const uint16_t length = kHitachiAcStateLength); + IRsend _irsend; + uint8_t _previoustemp; +}; + +#endif // IR_HITACHI_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_JVC.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_JVC.cpp similarity index 57% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_JVC.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_JVC.cpp index 194e39250..47df29dc4 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_JVC.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_JVC.cpp @@ -19,31 +19,31 @@ // Constants // Ref: // http://www.sbprojects.com/knowledge/ir/jvc.php -#define JVC_TICK 75U -#define JVC_HDR_MARK_TICKS 112U -#define JVC_HDR_MARK (JVC_HDR_MARK_TICKS * JVC_TICK) -#define JVC_HDR_SPACE_TICKS 56U -#define JVC_HDR_SPACE (JVC_HDR_SPACE_TICKS * JVC_TICK) -#define JVC_BIT_MARK_TICKS 7U -#define JVC_BIT_MARK (JVC_BIT_MARK_TICKS * JVC_TICK) -#define JVC_ONE_SPACE_TICKS 23U -#define JVC_ONE_SPACE (JVC_ONE_SPACE_TICKS * JVC_TICK) -#define JVC_ZERO_SPACE_TICKS 7U -#define JVC_ZERO_SPACE (JVC_ZERO_SPACE_TICKS * JVC_TICK) -#define JVC_RPT_LENGTH_TICKS 800U -#define JVC_RPT_LENGTH (JVC_RPT_LENGTH_TICKS * JVC_TICK) -#define JVC_MIN_GAP_TICKS (JVC_RPT_LENGTH_TICKS - \ - (JVC_HDR_MARK_TICKS + JVC_HDR_SPACE_TICKS + \ - JVC_BITS * (JVC_BIT_MARK_TICKS + JVC_ONE_SPACE_TICKS) + \ - JVC_BIT_MARK_TICKS)) -#define JVC_MIN_GAP (JVC_MIN_GAP_TICKS * JVC_TICK) +const uint16_t kJvcTick = 75; +const uint16_t kJvcHdrMarkTicks = 112; +const uint16_t kJvcHdrMark = kJvcHdrMarkTicks * kJvcTick; +const uint16_t kJvcHdrSpaceTicks = 56; +const uint16_t kJvcHdrSpace = kJvcHdrSpaceTicks * kJvcTick; +const uint16_t kJvcBitMarkTicks = 7; +const uint16_t kJvcBitMark = kJvcBitMarkTicks * kJvcTick; +const uint16_t kJvcOneSpaceTicks = 23; +const uint16_t kJvcOneSpace = kJvcOneSpaceTicks * kJvcTick; +const uint16_t kJvcZeroSpaceTicks = 7; +const uint16_t kJvcZeroSpace = kJvcZeroSpaceTicks * kJvcTick; +const uint16_t kJvcRptLengthTicks = 800; +const uint16_t kJvcRptLength = kJvcRptLengthTicks * kJvcTick; +const uint16_t kJvcMinGapTicks = + kJvcRptLengthTicks - + (kJvcHdrMarkTicks + kJvcHdrSpaceTicks + + kJvcBits * (kJvcBitMarkTicks + kJvcOneSpaceTicks) + kJvcBitMarkTicks); +const uint16_t kJvcMinGap = kJvcMinGapTicks * kJvcTick; #if SEND_JVC // Send a JVC message. // // Args: // data: The contents of the command you want to send. -// nbits: The bit size of the command being sent. (JVC_BITS) +// nbits: The bit size of the command being sent. (kJvcBits) // repeat: The number of times you want the command to be repeated. // // Status: STABLE. @@ -57,18 +57,21 @@ void IRsend::sendJVC(uint64_t data, uint16_t nbits, uint16_t repeat) { IRtimer usecs = IRtimer(); // Header // Only sent for the first message. - mark(JVC_HDR_MARK); - space(JVC_HDR_SPACE); + mark(kJvcHdrMark); + space(kJvcHdrSpace); // We always send the data & footer at least once, hence '<= repeat'. for (uint16_t i = 0; i <= repeat; i++) { - // Data - sendData(JVC_BIT_MARK, JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE, - data, nbits, true); - // Footer - mark(JVC_BIT_MARK); + sendGeneric(0, 0, // No Header + kJvcBitMark, kJvcOneSpace, kJvcBitMark, kJvcZeroSpace, + kJvcBitMark, kJvcMinGap, data, nbits, 38, true, + 0, // Repeats are handles elsewhere. + 33); // Wait till the end of the repeat time window before we send another code. - space(std::max(JVC_MIN_GAP, JVC_RPT_LENGTH - usecs.elapsed())); + uint32_t elapsed = usecs.elapsed(); + // Avoid potential unsigned integer underflow. + // e.g. when elapsed > kJvcRptLength. + if (elapsed < kJvcRptLength) space(kJvcRptLength - elapsed); usecs.reset(); } } @@ -95,7 +98,7 @@ uint16_t IRsend::encodeJVC(uint8_t address, uint8_t command) { // // Args: // results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits of data to expect. Typically JVC_BITS. +// nbits: Nr. of bits of data to expect. Typically kJvcBits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. @@ -106,50 +109,48 @@ uint16_t IRsend::encodeJVC(uint8_t address, uint8_t command) { // JVC repeat codes don't have a header. // Ref: // http://www.sbprojects.com/knowledge/ir/jvc.php -bool IRrecv::decodeJVC(decode_results *results, uint16_t nbits, bool strict) { - if (strict && nbits != JVC_BITS) +bool IRrecv::decodeJVC(decode_results *results, uint16_t nbits, bool strict) { + if (strict && nbits != kJvcBits) return false; // Must be called with the correct nr. of bits. - if (results->rawlen < 2 * nbits + FOOTER - 1) + if (results->rawlen < 2 * nbits + kFooter - 1) return false; // Can't possibly be a valid JVC message. uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; bool isRepeat = true; uint32_t m_tick; uint32_t s_tick; // Header // (Optional as repeat codes don't have the header) - if (matchMark(results->rawbuf[offset], JVC_HDR_MARK)) { + if (matchMark(results->rawbuf[offset], kJvcHdrMark)) { isRepeat = false; - m_tick = results->rawbuf[offset++] * RAWTICK / JVC_HDR_MARK_TICKS; + m_tick = results->rawbuf[offset++] * kRawTick / kJvcHdrMarkTicks; if (results->rawlen < 2 * nbits + 4) return false; // Can't possibly be a valid JVC message with a header. - if (!matchSpace(results->rawbuf[offset], JVC_HDR_SPACE)) - return false; - s_tick = results->rawbuf[offset++] * RAWTICK / JVC_HDR_SPACE_TICKS; + if (!matchSpace(results->rawbuf[offset], kJvcHdrSpace)) return false; + s_tick = results->rawbuf[offset++] * kRawTick / kJvcHdrSpaceTicks; } else { // We can't easily auto-calibrate as there is no header, so assume // the default tick time. - m_tick = JVC_TICK; - s_tick = JVC_TICK; + m_tick = kJvcTick; + s_tick = kJvcTick; } // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - JVC_BIT_MARK_TICKS * m_tick, - JVC_ONE_SPACE_TICKS * s_tick, - JVC_BIT_MARK_TICKS * m_tick, - JVC_ZERO_SPACE_TICKS * s_tick); + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kJvcBitMarkTicks * m_tick, + kJvcOneSpaceTicks * s_tick, kJvcBitMarkTicks * m_tick, + kJvcZeroSpaceTicks * s_tick); if (data_result.success == false) return false; data = data_result.data; offset += data_result.used; // Footer - if (!matchMark(results->rawbuf[offset++], JVC_BIT_MARK_TICKS * m_tick)) + if (!matchMark(results->rawbuf[offset++], kJvcBitMarkTicks * m_tick)) return false; if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], JVC_MIN_GAP_TICKS * s_tick)) + !matchAtLeast(results->rawbuf[offset], kJvcMinGapTicks * s_tick)) return false; // Success @@ -157,7 +158,7 @@ bool IRrecv::decodeJVC(decode_results *results, uint16_t nbits, bool strict) { results->bits = nbits; results->value = data; // command & address are transmitted LSB first, so we need to reverse them. - results->address = reverseBits(data >> 8, 8); // The first 8 bits sent. + results->address = reverseBits(data >> 8, 8); // The first 8 bits sent. results->command = reverseBits(data & 0xFF, 8); // The last 8 bits sent. results->repeat = isRepeat; return true; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.cpp new file mode 100644 index 000000000..ddf61b097 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.cpp @@ -0,0 +1,550 @@ +// Copyright 2016 David Conran +// +// Code to emulate IR Kelvinator YALIF remote control unit, which should control +// at least the following Kelvinator A/C units: +// KSV26CRC, KSV26HRC, KSV35CRC, KSV35HRC, KSV53HRC, KSV62HRC, KSV70CRC, +// KSV70HRC, KSV80HRC. +// +// Note: +// * Unsupported: +// - All Sleep modes. +// - All Timer modes. +// - "I Feel" button & mode. +// - Energy Saving mode. +// - Low Heat mode. +// - Fahrenheit. + +#include "ir_Kelvinator.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// KK KK EEEEEEE LL VV VV IIIII NN NN AAA TTTTTTT OOOOO RRRRRR +// KK KK EE LL VV VV III NNN NN AAAAA TTT OO OO RR RR +// KKKK EEEEE LL VV VV III NN N NN AA AA TTT OO OO RRRRRR +// KK KK EE LL VV VV III NN NNN AAAAAAA TTT OO OO RR RR +// KK KK EEEEEEE LLLLLLL VVV IIIII NN NN AA AA TTT OOOO0 RR RR + +// Constants + +const uint16_t kKelvinatorTick = 85; +const uint16_t kKelvinatorHdrMarkTicks = 106; +const uint16_t kKelvinatorHdrMark = kKelvinatorHdrMarkTicks * kKelvinatorTick; +const uint16_t kKelvinatorHdrSpaceTicks = 53; +const uint16_t kKelvinatorHdrSpace = kKelvinatorHdrSpaceTicks * kKelvinatorTick; +const uint16_t kKelvinatorBitMarkTicks = 8; +const uint16_t kKelvinatorBitMark = kKelvinatorBitMarkTicks * kKelvinatorTick; +const uint16_t kKelvinatorOneSpaceTicks = 18; +const uint16_t kKelvinatorOneSpace = kKelvinatorOneSpaceTicks * kKelvinatorTick; +const uint16_t kKelvinatorZeroSpaceTicks = 6; +const uint16_t kKelvinatorZeroSpace = + kKelvinatorZeroSpaceTicks * kKelvinatorTick; +const uint16_t kKelvinatorGapSpaceTicks = 235; +const uint16_t kKelvinatorGapSpace = kKelvinatorGapSpaceTicks * kKelvinatorTick; + +const uint8_t kKelvinatorCmdFooter = 2; +const uint8_t kKelvinatorCmdFooterBits = 3; + +const uint8_t kKelvinatorPower = 8; +const uint8_t kKelvinatorModeMask = 0xF8; +const uint8_t kKelvinatorFanOffset = 4; +const uint8_t kKelvinatorBasicFanMask = 0xFF ^ (3U << kKelvinatorFanOffset); +const uint8_t kKelvinatorFanMask = 0xFF ^ (7U << kKelvinatorFanOffset); +const uint8_t kKelvinatorChecksumStart = 10; +const uint8_t kKelvinatorVentSwingOffset = 6; +const uint8_t kKelvinatorVentSwing = 1 << kKelvinatorVentSwingOffset; +const uint8_t kKelvinatorVentSwingV = 1; +const uint8_t kKelvinatorVentSwingH = 1 << 4; +const uint8_t kKelvinatorSleep1And3 = 1 << 7; +const uint8_t kKelvinatorQuietOffset = 7; +const uint8_t kKelvinatorQuiet = 1 << kKelvinatorQuietOffset; +const uint8_t kKelvinatorIonFilterOffset = 6; +const uint8_t kKelvinatorIonFilter = 1 << kKelvinatorIonFilterOffset; +const uint8_t kKelvinatorLightOffset = 5; +const uint8_t kKelvinatorLight = 1 << kKelvinatorLightOffset; +const uint8_t kKelvinatorXfanOffset = 7; +const uint8_t kKelvinatorXfan = 1 << kKelvinatorXfanOffset; +const uint8_t kKelvinatorTurboOffset = 4; +const uint8_t kKelvinatorTurbo = 1 << kKelvinatorTurboOffset; + +#if SEND_KELVINATOR +// Send a Kelvinator A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kKelvinatorStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: STABLE / Known working. +// +void IRsend::sendKelvinator(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kKelvinatorStateLength) + return; // Not enough bytes to send a proper message. + + for (uint16_t r = 0; r <= repeat; r++) { + // Command Block #1 (4 bytes) + sendGeneric(kKelvinatorHdrMark, kKelvinatorHdrSpace, kKelvinatorBitMark, + kKelvinatorOneSpace, kKelvinatorBitMark, kKelvinatorZeroSpace, + 0, 0, // No Footer yet. + data, 4, 38, false, 0, 50); + // Send Footer for the command block (3 bits (b010)) + sendGeneric(0, 0, // No Header + kKelvinatorBitMark, kKelvinatorOneSpace, kKelvinatorBitMark, + kKelvinatorZeroSpace, kKelvinatorBitMark, kKelvinatorGapSpace, + kKelvinatorCmdFooter, kKelvinatorCmdFooterBits, 38, false, 0, + 50); + // Data Block #1 (4 bytes) + sendGeneric(0, 0, // No header + kKelvinatorBitMark, kKelvinatorOneSpace, kKelvinatorBitMark, + kKelvinatorZeroSpace, kKelvinatorBitMark, + kKelvinatorGapSpace * 2, data + 4, 4, 38, false, 0, 50); + // Command Block #2 (4 bytes) + sendGeneric(kKelvinatorHdrMark, kKelvinatorHdrSpace, kKelvinatorBitMark, + kKelvinatorOneSpace, kKelvinatorBitMark, kKelvinatorZeroSpace, + 0, 0, // No Footer yet. + data + 8, 4, 38, false, 0, 50); + // Send Footer for the command block (3 bits (B010)) + sendGeneric(0, 0, // No Header + kKelvinatorBitMark, kKelvinatorOneSpace, kKelvinatorBitMark, + kKelvinatorZeroSpace, kKelvinatorBitMark, kKelvinatorGapSpace, + kKelvinatorCmdFooter, kKelvinatorCmdFooterBits, 38, false, 0, + 50); + // Data Block #2 (4 bytes) + sendGeneric(0, 0, // No header + kKelvinatorBitMark, kKelvinatorOneSpace, kKelvinatorBitMark, + kKelvinatorZeroSpace, kKelvinatorBitMark, + kKelvinatorGapSpace * 2, data + 12, 4, 38, false, 0, 50); + } +} +#endif // SEND_KELVINATOR + +IRKelvinatorAC::IRKelvinatorAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRKelvinatorAC::stateReset() { + for (uint8_t i = 0; i < kKelvinatorStateLength; i++) remote_state[i] = 0x0; + remote_state[3] = 0x50; + remote_state[11] = 0x70; +} + +void IRKelvinatorAC::begin() { _irsend.begin(); } + +void IRKelvinatorAC::fixup() { + // X-Fan mode is only valid in COOL or DRY modes. + if (getMode() != kKelvinatorCool && getMode() != kKelvinatorDry) + setXFan(false); + checksum(); // Calculate the checksums +} + +#if SEND_KELVINATOR +void IRKelvinatorAC::send() { + fixup(); // Ensure correct settings before sending. + _irsend.sendKelvinator(remote_state); +} +#endif // SEND_KELVINATOR + +uint8_t *IRKelvinatorAC::getRaw() { + fixup(); // Ensure correct settings before sending. + return remote_state; +} + +void IRKelvinatorAC::setRaw(uint8_t new_code[]) { + for (uint8_t i = 0; i < kKelvinatorStateLength; i++) { + remote_state[i] = new_code[i]; + } +} + +uint8_t IRKelvinatorAC::calcBlockChecksum(const uint8_t *block, + const uint16_t length) { + uint8_t sum = kKelvinatorChecksumStart; + // Sum the lower half of the first 4 bytes of this block. + for (uint8_t i = 0; i < 4 && i < length - 1; i++, block++) + sum += (*block & 0x0FU); + // then sum the upper half of the next 3 bytes. + for (uint8_t i = 4; i < length - 1; i++, block++) sum += (*block >> 4); + // Trim it down to fit into the 4 bits allowed. i.e. Mod 16. + return sum & 0x0FU; +} + +// Many Bothans died to bring us this information. +void IRKelvinatorAC::checksum(const uint16_t length) { + // For each command + options block. + for (uint16_t offset = 0; offset + 7 < length; offset += 8) { + uint8_t sum = calcBlockChecksum(remote_state + offset); + remote_state[7 + offset] = (sum << 4) | (remote_state[7 + offset] & 0xFU); + } +} + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRKelvinatorAC::validChecksum(const uint8_t state[], + const uint16_t length) { + for (uint16_t offset = 0; offset + 7 < length; offset += 8) { + // Top 4 bits of the last byte in the block is the block's checksum. + if (state[offset + 7] >> 4 != calcBlockChecksum(state + offset)) + return false; + } + return true; +} + +void IRKelvinatorAC::on() { + remote_state[0] |= kKelvinatorPower; + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. +} + +void IRKelvinatorAC::off() { + remote_state[0] &= ~kKelvinatorPower; + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. +} + +void IRKelvinatorAC::setPower(bool state) { + if (state) + on(); + else + off(); +} + +bool IRKelvinatorAC::getPower() { + return ((remote_state[0] & kKelvinatorPower) != 0); +} + +// Set the temp. in deg C +void IRKelvinatorAC::setTemp(uint8_t temp) { + temp = std::max(kKelvinatorMinTemp, temp); + temp = std::min(kKelvinatorMaxTemp, temp); + remote_state[1] = (remote_state[1] & 0xF0U) | (temp - kKelvinatorMinTemp); + remote_state[9] = remote_state[1]; // Duplicate to the 2nd command chunk. +} + +// Return the set temp. in deg C +uint8_t IRKelvinatorAC::getTemp() { + return ((remote_state[1] & 0xFU) + kKelvinatorMinTemp); +} + +// Set the speed of the fan, 0-5, 0 is auto, 1-5 is the speed +void IRKelvinatorAC::setFan(uint8_t fan) { + fan = std::min(kKelvinatorFanMax, fan); // Bounds check + + // Only change things if we need to. + if (fan != getFan()) { + // Set the basic fan values. + uint8_t fan_basic = std::min(kKelvinatorBasicFanMax, fan); + remote_state[0] = (remote_state[0] & kKelvinatorBasicFanMask) | + (fan_basic << kKelvinatorFanOffset); + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. + // Set the advanced(?) fan value. + remote_state[14] = + (remote_state[14] & kKelvinatorFanMask) | (fan << kKelvinatorFanOffset); + setTurbo(false); // Turbo mode is turned off if we change the fan settings. + } +} + +uint8_t IRKelvinatorAC::getFan() { + return ((remote_state[14] & ~kKelvinatorFanMask) >> kKelvinatorFanOffset); +} + +uint8_t IRKelvinatorAC::getMode() { + return (remote_state[0] & ~kKelvinatorModeMask); +} + +void IRKelvinatorAC::setMode(uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + if (mode > kKelvinatorHeat) mode = kKelvinatorAuto; + remote_state[0] = (remote_state[0] & kKelvinatorModeMask) | mode; + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. + if (mode == kKelvinatorAuto || kKelvinatorDry) + // When the remote is set to Auto or Dry, it defaults to 25C and doesn't + // show it. + setTemp(kKelvinatorAutoTemp); +} + +void IRKelvinatorAC::setSwingVertical(bool state) { + if (state) { + remote_state[0] |= kKelvinatorVentSwing; + remote_state[4] |= kKelvinatorVentSwingV; + } else { + remote_state[4] &= ~kKelvinatorVentSwingV; + if (!getSwingHorizontal()) remote_state[0] &= ~kKelvinatorVentSwing; + } + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. +} + +bool IRKelvinatorAC::getSwingVertical() { + return ((remote_state[4] & kKelvinatorVentSwingV) != 0); +} + +void IRKelvinatorAC::setSwingHorizontal(bool state) { + if (state) { + remote_state[0] |= kKelvinatorVentSwing; + remote_state[4] |= kKelvinatorVentSwingH; + } else { + remote_state[4] &= ~kKelvinatorVentSwingH; + if (!getSwingVertical()) remote_state[0] &= ~kKelvinatorVentSwing; + } + remote_state[8] = remote_state[0]; // Duplicate to the 2nd command chunk. +} + +bool IRKelvinatorAC::getSwingHorizontal() { + return ((remote_state[4] & kKelvinatorVentSwingH) != 0); +} + +void IRKelvinatorAC::setQuiet(bool state) { + remote_state[12] &= ~kKelvinatorQuiet; + remote_state[12] |= (state << kKelvinatorQuietOffset); +} + +bool IRKelvinatorAC::getQuiet() { + return ((remote_state[12] & kKelvinatorQuiet) != 0); +} + +void IRKelvinatorAC::setIonFilter(bool state) { + remote_state[2] &= ~kKelvinatorIonFilter; + remote_state[2] |= (state << kKelvinatorIonFilterOffset); + remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. +} + +bool IRKelvinatorAC::getIonFilter() { + return ((remote_state[2] & kKelvinatorIonFilter) != 0); +} + +void IRKelvinatorAC::setLight(bool state) { + remote_state[2] &= ~kKelvinatorLight; + remote_state[2] |= (state << kKelvinatorLightOffset); + remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. +} + +bool IRKelvinatorAC::getLight() { + return ((remote_state[2] & kKelvinatorLight) != 0); +} + +// Note: XFan mode is only valid in Cool or Dry mode. +void IRKelvinatorAC::setXFan(bool state) { + remote_state[2] &= ~kKelvinatorXfan; + remote_state[2] |= (state << kKelvinatorXfanOffset); + remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. +} + +bool IRKelvinatorAC::getXFan() { + return ((remote_state[2] & kKelvinatorXfan) != 0); +} + +// Note: Turbo mode is turned off if the fan speed is changed. +void IRKelvinatorAC::setTurbo(bool state) { + remote_state[2] &= ~kKelvinatorTurbo; + remote_state[2] |= (state << kKelvinatorTurboOffset); + remote_state[10] = remote_state[2]; // Duplicate to the 2nd command chunk. +} + +bool IRKelvinatorAC::getTurbo() { + return ((remote_state[2] & kKelvinatorTurbo) != 0); +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRKelvinatorAC::toString() { + String result = ""; +#else +std::string IRKelvinatorAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kKelvinatorAuto: + result += " (AUTO)"; + break; + case kKelvinatorCool: + result += " (COOL)"; + break; + case kKelvinatorHeat: + result += " (HEAT)"; + break; + case kKelvinatorDry: + result += " (DRY)"; + break; + case kKelvinatorFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kKelvinatorFanAuto: + result += " (AUTO)"; + break; + case kKelvinatorFanMax: + result += " (MAX)"; + break; + } + result += ", Turbo: "; + if (getTurbo()) + result += "On"; + else + result += "Off"; + result += ", Quiet: "; + if (getQuiet()) + result += "On"; + else + result += "Off"; + result += ", XFan: "; + if (getXFan()) + result += "On"; + else + result += "Off"; + result += ", IonFilter: "; + if (getIonFilter()) + result += "On"; + else + result += "Off"; + result += ", Light: "; + if (getLight()) + result += "On"; + else + result += "Off"; + result += ", Swing (Horizontal): "; + if (getSwingHorizontal()) + result += "On"; + else + result += "Off"; + result += ", Swing (Vertical): "; + if (getSwingVertical()) + result += "On"; + else + result += "Off"; + return result; +} + +#if DECODE_KELVINATOR +// Decode the supplied Kelvinator message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kKelvinatorBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +bool IRrecv::decodeKelvinator(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < + 2 * (nbits + kKelvinatorCmdFooterBits) + (kHeader + kFooter + 1) * 2 - 1) + return false; // Can't possibly be a valid Kelvinator message. + if (strict && nbits != kKelvinatorBits) + return false; // Not strictly a Kelvinator message. + + uint32_t data; + uint16_t offset = kStartOffset; + + // There are two messages back-to-back in a full Kelvinator IR message + // sequence. + int8_t state_pos = 0; + for (uint8_t s = 0; s < 2; s++) { + match_result_t data_result; + + // Header + if (!matchMark(results->rawbuf[offset], kKelvinatorHdrMark)) return false; + // Calculate how long the lowest tick time is based on the header mark. + uint32_t mark_tick = + results->rawbuf[offset++] * kRawTick / kKelvinatorHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kKelvinatorHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t space_tick = + results->rawbuf[offset++] * kRawTick / kKelvinatorHdrSpaceTicks; + + // Data (Command) (32 bits) + data_result = matchData( + &(results->rawbuf[offset]), 32, kKelvinatorBitMarkTicks * mark_tick, + kKelvinatorOneSpaceTicks * space_tick, + kKelvinatorBitMarkTicks * mark_tick, + kKelvinatorZeroSpaceTicks * space_tick, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Record command data in the state. + for (uint16_t i = 0; i < 4; i++, data >>= 8) + results->state[state_pos + i] = data & 0xFF; + state_pos += 4; + + // Command data footer (3 bits, B010) + data_result = matchData( + &(results->rawbuf[offset]), kKelvinatorCmdFooterBits, + kKelvinatorBitMarkTicks * mark_tick, + kKelvinatorOneSpaceTicks * space_tick, + kKelvinatorBitMarkTicks * mark_tick, + kKelvinatorZeroSpaceTicks * space_tick, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + if (data_result.data != kKelvinatorCmdFooter) return false; + offset += data_result.used; + + // Interdata gap. + if (!matchMark(results->rawbuf[offset++], + kKelvinatorBitMarkTicks * mark_tick)) + return false; + if (!matchSpace(results->rawbuf[offset++], + kKelvinatorGapSpaceTicks * space_tick)) + return false; + + // Data (Options) (32 bits) + data_result = matchData( + &(results->rawbuf[offset]), 32, kKelvinatorBitMarkTicks * mark_tick, + kKelvinatorOneSpaceTicks * space_tick, + kKelvinatorBitMarkTicks * mark_tick, + kKelvinatorZeroSpaceTicks * space_tick, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Record option data in the state. + for (uint16_t i = 0; i < 4; i++, data >>= 8) + results->state[state_pos + i] = data & 0xFF; + state_pos += 4; + + // Inter-sequence gap. (Double length gap) + if (!matchMark(results->rawbuf[offset++], + kKelvinatorBitMarkTicks * mark_tick)) + return false; + if (s == 0) { + if (!matchSpace(results->rawbuf[offset++], + kKelvinatorGapSpaceTicks * space_tick * 2)) + return false; + } else { + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset], + kKelvinatorGapSpaceTicks * 2 * space_tick)) + return false; + } + } + + // Compliance + if (strict) { + // Correct size/length) + if (state_pos != kKelvinatorStateLength) return false; + // Verify the message's checksum is correct. + if (!IRKelvinatorAC::validChecksum(results->state)) return false; + } + + // Success + results->decode_type = KELVINATOR; + results->bits = state_pos * 8; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_KELVINATOR diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.h similarity index 71% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.h rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.h index c15d85c6e..1508d6cdc 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.h +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.h @@ -7,6 +7,11 @@ #define __STDC_LIMIT_MACROS #include +#ifndef UNIT_TEST +#include +#else +#include +#endif #include "IRremoteESP8266.h" #include "IRsend.h" @@ -17,19 +22,33 @@ // KK KK EEEEEEE LLLLLLL VVV IIIII NN NN AA AA TTT OOOO0 RR RR // Constants -#define KELVINATOR_AUTO 0U -#define KELVINATOR_COOL 1U -#define KELVINATOR_DRY 2U -#define KELVINATOR_FAN 3U -#define KELVINATOR_HEAT 4U -#define KELVINATOR_BASIC_FAN_MAX 3U -#define KELVINATOR_FAN_MAX 5U -#define KELVINATOR_MIN_TEMP 16U // 16C -#define KELVINATOR_MAX_TEMP 30U // 30C -#define KELVINATOR_AUTO_TEMP 25U // 25C +const uint8_t kKelvinatorAuto = 0; +const uint8_t kKelvinatorCool = 1; +const uint8_t kKelvinatorDry = 2; +const uint8_t kKelvinatorFan = 3; +const uint8_t kKelvinatorHeat = 4; +const uint8_t kKelvinatorBasicFanMax = 3; +const uint8_t kKelvinatorFanAuto = 0; +const uint8_t kKelvinatorFanMax = 5; +const uint8_t kKelvinatorMinTemp = 16; // 16C +const uint8_t kKelvinatorMaxTemp = 30; // 30C +const uint8_t kKelvinatorAutoTemp = 25; // 25C + +// Legacy defines (Deprecated) +#define KELVINATOR_MIN_TEMP kKelvinatorMinTemp +#define KELVINATOR_MAX_TEMP kKelvinatorMaxTemp +#define KELVINATOR_HEAT kKelvinatorHeat +#define KELVINATOR_FAN_MAX kKelvinatorFanMax +#define KELVINATOR_FAN_AUTO kKelvinatorFanAuto +#define KELVINATOR_FAN kKelvinatorFan +#define KELVINATOR_DRY kKelvinatorDry +#define KELVINATOR_COOL kKelvinatorCool +#define KELVINATOR_BASIC_FAN_MAX kKelvinatorBasicFanMax +#define KELVINATOR_AUTO_TEMP kKelvinatorAutoTemp +#define KELVINATOR_AUTO kKelvinatorAuto /* - Kelvinator AC map + Kelvinator AC map (header mark and space) byte 0 = Basic Modes @@ -104,15 +123,15 @@ b7-4 = checksum of the previous bytes (8-14) */ -#if SEND_KELVINATOR - // Classes class IRKelvinatorAC { public: explicit IRKelvinatorAC(uint16_t pin); void stateReset(); +#if SEND_KELVINATOR void send(); +#endif // SEND_KELVINATOR void begin(); void on(); void off(); @@ -139,14 +158,23 @@ class IRKelvinatorAC { void setTurbo(bool state); bool getTurbo(); uint8_t* getRaw(); + void setRaw(uint8_t new_code[]); + static uint8_t calcBlockChecksum( + const uint8_t* block, const uint16_t length = kKelvinatorStateLength / 2); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kKelvinatorStateLength); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif private: // The state of the IR remote in IR code form. - uint8_t remote_state[KELVINATOR_STATE_LENGTH]; - void checksum(); + uint8_t remote_state[kKelvinatorStateLength]; + void checksum(const uint16_t length = kKelvinatorStateLength); void fixup(); IRsend _irsend; }; -#endif #endif // IR_KELVINATOR_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp new file mode 100644 index 000000000..f9d922fc7 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp @@ -0,0 +1,290 @@ +// Copyright 2015 Darryl Smith +// Copyright 2015 cheaplin +// Copyright 2017, 2018 David Conran + +#include "ir_LG.h" +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// L GGGG +// L G +// L G GG +// L G G +// LLLLL GGG + +// LG decode originally added by Darryl Smith (based on the JVC protocol) +// LG send originally added by https://github.com/chaeplin +// +// Known supported devices: +// IR Remotes: +// 6711A20083V +// AKB74395308 + +// Constants +const uint16_t kLgTick = 50; +const uint16_t kLgHdrMarkTicks = 170; +const uint16_t kLgHdrMark = kLgHdrMarkTicks * kLgTick; // 8500 +const uint16_t kLgHdrSpaceTicks = 85; +const uint16_t kLgHdrSpace = kLgHdrSpaceTicks * kLgTick; // 4250 +const uint16_t kLgBitMarkTicks = 11; +const uint16_t kLgBitMark = kLgBitMarkTicks * kLgTick; // 550 +const uint16_t kLgOneSpaceTicks = 32; +const uint16_t kLgOneSpace = kLgOneSpaceTicks * kLgTick; // 1600 +const uint16_t kLgZeroSpaceTicks = 11; +const uint16_t kLgZeroSpace = kLgZeroSpaceTicks * kLgTick; // 550 +const uint16_t kLgRptSpaceTicks = 45; +const uint16_t kLgRptSpace = kLgRptSpaceTicks * kLgTick; // 2250 +const uint16_t kLgMinGapTicks = 795; +const uint16_t kLgMinGap = kLgMinGapTicks * kLgTick; // 39750 +const uint16_t kLgMinMessageLengthTicks = 2161; +const uint32_t kLgMinMessageLength = kLgMinMessageLengthTicks * kLgTick; + +const uint16_t kLg32HdrMarkTicks = 90; +const uint16_t kLg32HdrMark = kLg32HdrMarkTicks * kLgTick; // 4500 +const uint16_t kLg32HdrSpaceTicks = 89; +const uint16_t kLg32HdrSpace = kLg32HdrSpaceTicks * kLgTick; // 4450 +const uint16_t kLg32RptHdrMarkTicks = 179; +const uint16_t kLg32RptHdrMark = kLg32RptHdrMarkTicks * kLgTick; // 8950 + +const uint16_t kLg2HdrMarkTicks = 64; +const uint16_t kLg2HdrMark = kLg2HdrMarkTicks * kLgTick; // 3200 +const uint16_t kLg2HdrSpaceTicks = 197; +const uint16_t kLg2HdrSpace = kLg2HdrSpaceTicks * kLgTick; // 9850 +const uint16_t kLg2BitMarkTicks = 10; +const uint16_t kLg2BitMark = kLg2BitMarkTicks * kLgTick; // 500 + +#if (SEND_LG || DECODE_LG) +// Calculate the rolling 4-bit wide checksum over all of the data. +// Args: +// data: The value to be checksum'ed. +// Returns: +// A 4-bit checksum. +uint8_t calcLGChecksum(uint16_t data) { + return (((data >> 12) + ((data >> 8) & 0xF) + ((data >> 4) & 0xF) + + (data & 0xF)) & + 0xF); +} +#endif + +#if SEND_LG +// Send an LG formatted message. +// +// Args: +// data: The contents of the message you want to send. +// nbits: The bit size of the message being sent. +// Typically kLgBits or kLg32Bits. +// repeat: The number of times you want the message to be repeated. +// +// Status: Beta / Should be working. +// +// Notes: +// LG has a separate message to indicate a repeat, like NEC does. +// Supports: +// IR Remote models: 6711A20083V +void IRsend::sendLG(uint64_t data, uint16_t nbits, uint16_t repeat) { + uint16_t repeatHeaderMark = 0; + + if (nbits >= kLg32Bits) { + // LG 32bit protocol is near identical to Samsung except for repeats. + sendSAMSUNG(data, nbits, 0); // Send it as a single Samsung message. + repeatHeaderMark = kLg32RptHdrMark; + repeat++; + } else { + // LG (28-bit) protocol. + repeatHeaderMark = kLgHdrMark; + sendGeneric(kLgHdrMark, kLgHdrSpace, kLgBitMark, kLgOneSpace, kLgBitMark, + kLgZeroSpace, kLgBitMark, kLgMinGap, kLgMinMessageLength, data, + nbits, 38, true, 0, // Repeats are handled later. + 50); + } + + // Repeat + // Protocol has a mandatory repeat-specific code sent after every command. + if (repeat) + sendGeneric(repeatHeaderMark, kLgRptSpace, 0, 0, 0, 0, // No data is sent. + kLgBitMark, kLgMinGap, kLgMinMessageLength, 0, 0, // No data. + 38, true, repeat - 1, 50); +} + +// Send an LG Variant-2 formatted message. +// +// Args: +// data: The contents of the message you want to send. +// nbits: The bit size of the message being sent. +// Typically kLgBits or kLg32Bits. +// repeat: The number of times you want the message to be repeated. +// +// Status: Beta / Should be working. +// +// Notes: +// LG has a separate message to indicate a repeat, like NEC does. +// Supports: +// IR Remote models: AKB74395308 +void IRsend::sendLG2(uint64_t data, uint16_t nbits, uint16_t repeat) { + if (nbits >= kLg32Bits) { + // Let the original routine handle it. + sendLG(data, nbits, repeat); // Send it as a single Samsung message. + return; + } + + // LGv2 (28-bit) protocol. + sendGeneric(kLg2HdrMark, kLg2HdrSpace, kLgBitMark, kLgOneSpace, kLgBitMark, + kLgZeroSpace, kLgBitMark, kLgMinGap, kLgMinMessageLength, data, + nbits, 38, true, 0, // Repeats are handled later. + 50); + + // TODO(crackn): Verify the details of what repeat messages look like. + // Repeat + // Protocol has a mandatory repeat-specific code sent after every command. + if (repeat) + sendGeneric(kLg2HdrMark, kLgRptSpace, 0, 0, 0, 0, // No data is sent. + kLgBitMark, kLgMinGap, kLgMinMessageLength, 0, 0, // No data. + 38, true, repeat - 1, 50); +} + +// Construct a raw 28-bit LG message code from the supplied address & command. +// +// Args: +// address: The address code. +// command: The command code. +// Returns: +// A raw 28-bit LG message code suitable for sendLG() etc. +// +// Status: BETA / Should work. +// +// Notes: +// e.g. Sequence of bits = address + command + checksum. +uint32_t IRsend::encodeLG(uint16_t address, uint16_t command) { + return ((address << 20) | (command << 4) | calcLGChecksum(command)); +} +#endif + +#if DECODE_LG +// Decode the supplied LG message. +// LG protocol has a repeat code which is 4 items long. +// Even though the protocol has 28/32 bits of data, only 24/28 bits are +// distinct. +// In transmission order, the 28/32 bits are constructed as follows: +// 8/12 bits of address + 16 bits of command + 4 bits of checksum. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. +// Typically kLgBits or kLg32Bits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Should work. +// +// Note: +// LG 32bit protocol appears near identical to the Samsung protocol. +// They possibly differ on how they repeat and initial HDR mark. +// +// Supports: +// IR Remote models: 6711A20083V, AKB74395308 + +// Ref: +// https://funembedded.wordpress.com/2014/11/08/ir-remote-control-for-lg-conditioner-using-stm32f302-mcu-on-mbed-platform/ +bool IRrecv::decodeLG(decode_results *results, uint16_t nbits, bool strict) { + if (nbits >= kLg32Bits) { + if (results->rawlen < 2 * nbits + 2 * (kHeader + kFooter) - 1) + return false; // Can't possibly be a valid LG32 message. + } else { + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid LG message. + } + if (strict && nbits != kLgBits && nbits != kLg32Bits) + return false; // Doesn't comply with expected LG protocol. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + bool isLg2 = false; + + // Header + uint32_t m_tick; + if (matchMark(results->rawbuf[offset], kLgHdrMark)) { + m_tick = results->rawbuf[offset++] * kRawTick / kLgHdrMarkTicks; + } else if (matchMark(results->rawbuf[offset], kLg2HdrMark)) { + m_tick = results->rawbuf[offset++] * kRawTick / kLg2HdrMarkTicks; + isLg2 = true; + } else if (matchMark(results->rawbuf[offset], kLg32HdrMark)) { + m_tick = results->rawbuf[offset++] * kRawTick / kLg32HdrMarkTicks; + } else { + return false; + } + uint32_t s_tick; + if (isLg2) { + if (matchSpace(results->rawbuf[offset], kLg2HdrSpace)) + s_tick = results->rawbuf[offset++] * kRawTick / kLg2HdrSpaceTicks; + else + return false; + } else { + if (matchSpace(results->rawbuf[offset], kLgHdrSpace)) + s_tick = results->rawbuf[offset++] * kRawTick / kLgHdrSpaceTicks; + else if (matchSpace(results->rawbuf[offset], kLg2HdrSpace)) + s_tick = results->rawbuf[offset++] * kRawTick / kLg32HdrSpaceTicks; + else + return false; + } + + // Set up the expected tick sizes based on variant. + uint16_t bitmarkticks; + if (isLg2) { + bitmarkticks = kLg2BitMarkTicks; + } else { + bitmarkticks = kLgBitMarkTicks; + } + + // Data + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, bitmarkticks * m_tick, + kLgOneSpaceTicks * s_tick, bitmarkticks * m_tick, + kLgZeroSpaceTicks * s_tick, kTolerance, 0); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Footer + if (!matchMark(results->rawbuf[offset++], bitmarkticks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kLgMinGapTicks * s_tick)) + return false; + + // Repeat + if (nbits >= kLg32Bits) { + // If we are expecting the LG 32-bit protocol, there is always + // a repeat message. So, check for it. + offset++; + if (!matchMark(results->rawbuf[offset++], kLg32RptHdrMarkTicks * m_tick)) + return false; + if (!matchSpace(results->rawbuf[offset++], kLgRptSpaceTicks * s_tick)) + return false; + if (!matchMark(results->rawbuf[offset++], bitmarkticks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kLgMinGapTicks * s_tick)) + return false; + } + + // Compliance + uint16_t command = (data >> 4) & 0xFFFF; // The 16 bits before the checksum. + + if (strict && (data & 0xF) != calcLGChecksum(command)) + return false; // The last 4 bits sent are the expected checksum. + + // Success + if (isLg2) + results->decode_type = LG2; + else + results->decode_type = LG; + results->bits = nbits; + results->value = data; + results->command = command; + results->address = data >> 20; // The bits before the command. + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_LG.h similarity index 100% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_LG.h rename to lib/IRremoteESP8266-2.5.2.03/src/ir_LG.h diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Lasertag.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Lasertag.cpp new file mode 100644 index 000000000..7f0b89ae9 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Lasertag.cpp @@ -0,0 +1,122 @@ +// Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// LL AAA SSSSS EEEEEEE RRRRRR TTTTTTT AAA GGGG +// LL AAAAA SS EE RR RR TTT AAAAA GG GG +// LL AA AA SSSSS EEEEE RRRRRR TTT AA AA GG +// LL AAAAAAA SS EE RR RR TTT AAAAAAA GG GG +// LLLLLLL AA AA SSSSS EEEEEEE RR RR TTT AA AA GGGGGG + +// Constants +const uint16_t kLasertagMinSamples = 13; +const uint16_t kLasertagTick = 333; +const uint32_t kLasertagMinGap = 100000; // Completely made up amount. +const uint8_t kLasertagTolerance = 0; // Percentage error margin. +const uint16_t kLasertagExcess = 0; // See kMarkExcess. +const uint16_t kLasertagDelta = 150; // Use instead of Excess and Tolerance. +const int16_t kSpace = 1; +const int16_t kMark = 0; + +#if SEND_LASERTAG +// Send a Lasertag packet. +// This protocol is pretty much just raw Manchester encoding. +// +// Args: +// data: The message you wish to send. +// nbits: Bit size of the protocol you want to send. +// repeat: Nr. of extra times the data will be sent. +// +// Status: STABLE / Working. +// +void IRsend::sendLasertag(uint64_t data, uint16_t nbits, uint16_t repeat) { + if (nbits > sizeof(data) * 8) return; // We can't send something that big. + + // Set 36kHz IR carrier frequency & a 1/4 (25%) duty cycle. + // NOTE: duty cycle is not confirmed. Just guessing based on RC5/6 protocols. + enableIROut(36, 25); + + for (uint16_t i = 0; i <= repeat; i++) { + // Data + for (uint64_t mask = 1ULL << (nbits - 1); mask; mask >>= 1) + if (data & mask) { // 1 + space(kLasertagTick); // 1 is space, then mark. + mark(kLasertagTick); + } else { // 0 + mark(kLasertagTick); // 0 is mark, then space. + space(kLasertagTick); + } + // Footer + space(kLasertagMinGap); + } +} +#endif // SEND_LASERTAG + +#if DECODE_LASERTAG +// Decode the supplied Lasertag message. +// This protocol is pretty much just raw Manchester encoding. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Appears to be working 90% of the time. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/rc5.php +// https://en.wikipedia.org/wiki/RC-5 +// https://en.wikipedia.org/wiki/Manchester_code +bool IRrecv::decodeLasertag(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < kLasertagMinSamples) return false; + + // Compliance + if (strict && nbits != kLasertagBits) return false; + + uint16_t offset = kStartOffset; + uint16_t used = 0; + uint64_t data = 0; + uint16_t actual_bits = 0; + + // No Header + + // Data + for (; offset <= results->rawlen; actual_bits++) { + int16_t levelA = + getRClevel(results, &offset, &used, kLasertagTick, kLasertagTolerance, + kLasertagExcess, kLasertagDelta); + int16_t levelB = + getRClevel(results, &offset, &used, kLasertagTick, kLasertagTolerance, + kLasertagExcess, kLasertagDelta); + if (levelA == kSpace && levelB == kMark) { + data = (data << 1) | 1; // 1 + } else { + if (levelA == kMark && levelB == kSpace) { + data <<= 1; // 0 + } else { + break; + } + } + } + // Footer (None) + + // Compliance + if (actual_bits < nbits) return false; // Less data than we expected. + if (strict && actual_bits != kLasertagBits) return false; + + // Success + results->decode_type = LASERTAG; + results->value = data; + results->address = data & 0xF; // Unit + results->command = data >> 4; // Team + results->repeat = false; + results->bits = actual_bits; + return true; +} +#endif // DECODE_LASERTAG diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Lutron.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Lutron.cpp new file mode 100644 index 000000000..00eb9383b --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Lutron.cpp @@ -0,0 +1,156 @@ +// Copyright 2018 David Conran + +#define __STDC_LIMIT_MACROS +#include +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// LL UU UU TTTTTTT RRRRRR OOOOO NN NN +// LL UU UU TTT RR RR OO OO NNN NN +// LL UU UU TTT RRRRRR OO OO NN N NN +// LL UU UU TTT RR RR OO OO NN NNN +// LLLLLLL UUUUU TTT RR RR OOOO0 NN NN + +// Notes: +// The Lutron protocol uses a sort of Run Length encoding to encode +// its data. There is no header or footer per-se. +// As a mark is the first data we will notice, we always assume the First +// bit of the technically 36-bit protocol is '1'. So it is assumed, and thus +// we only care about the 35 bits of data. + +// Constants +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/515 +const uint16_t kLutronTick = 2288; +const uint32_t kLutronGap = 150000; // Completely made up value. +const uint16_t kLutronDelta = 400; // +/- 300 usecs. + +#if SEND_LUTRON +// Send a Lutron formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The number of bits of the message to be sent. Typically kLutronBits +// repeat: The number of times the command is to be repeated. +// +// Status: Stable / Appears to be working for real devices. + +// Notes: +// Protocol is really 36 bits long, but the first bit is always a 1. +// So, assume the 1 and only have a normal payload of 35 bits. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/515 +void IRsend::sendLutron(uint64_t data, uint16_t nbits, uint16_t repeat) { + enableIROut(40000, 40); // 40Khz & 40% dutycycle. + for (uint16_t r = 0; r <= repeat; r++) { + mark(kLutronTick); // 1st bit is always '1'. + // Send the supplied data in MSB First order. + for (uint64_t mask = 1ULL << (nbits - 1); mask; mask >>= 1) + if (data & mask) + mark(kLutronTick); // Send a 1 + else + space(kLutronTick); // Send a 0 + space(kLutronGap); // Inter-message gap. + } +} +#endif // SEND_LUTRON + +#if DECODE_LUTRON +// Decode the supplied Lutron message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kLutronBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +// +// Notes: +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/515 +bool IRrecv::decodeLutron(decode_results *results, uint16_t nbits, + bool strict) { + // Technically the smallest number of entries for the smallest message is '1'. + // i.e. All the bits set to 1, would produce a single huge mark signal. + // So no minimum length check is required. + if (strict && nbits != kLutronBits) + return false; // Not strictly an Lutron message. + + uint64_t data = 0; + int16_t bitsSoFar = -1; + + if (nbits > sizeof(data) * 8) return false; // To large to store the data. + for (uint16_t offset = kStartOffset; + bitsSoFar < nbits && offset < results->rawlen; offset++) { + uint16_t entry = results->rawbuf[offset]; + // It has to be large enough to qualify as a bit. + if (!matchAtLeast(entry, kLutronTick, 0, kLutronDelta)) { + DPRINTLN("Entry too small. Aborting."); + return false; + } + // Keep reading bits of the same value until we run out. + while (entry != 0 && matchAtLeast(entry, kLutronTick, 0, kLutronDelta)) { + bitsSoFar++; + DPRINT("Bit: "); + DPRINT(bitsSoFar); + if (offset % 2) { // Is Odd? + data = (data << 1) + 1; // Append a '1'. + DPRINTLN(" is a 1."); + } else { // Is it Even? + data <<= 1; // Append a '0'. + DPRINTLN(" is a 0."); + if (bitsSoFar == nbits && matchAtLeast(entry, kLutronGap)) + break; // We've likely reached the end of a message. + } + // Remove a bit length from the current entry. + entry = std::max(entry, (uint16_t)(kLutronTick / kRawTick)) - + kLutronTick / kRawTick; + } + if (offset % 2 && !match(entry, kLutronDelta, 0, kLutronDelta)) { + DPRINT("offset = "); + DPRINTLN(offset); + DPRINT("rawlen = "); + DPRINTLN(results->rawlen); + DPRINT("entry = "); + DPRINTLN(entry); + DPRINTLN("Odd Entry has too much left over. Aborting."); + return false; // Too much left over to be a good value. Reject it. + } + if (offset % 2 == 0 && offset <= results->rawlen - 1 && + !matchAtLeast(entry, kLutronDelta, 0, kLutronDelta)) { + DPRINT("offset = "); + DPRINTLN(offset); + DPRINT("rawlen = "); + DPRINTLN(results->rawlen); + DPRINT("entry = "); + DPRINTLN(entry); + DPRINTLN("Entry has too much left over. Aborting."); + return false; // Too much left over to be a good value. Reject it. + } + } + + // We got too many bits. + if (bitsSoFar > nbits || bitsSoFar < 0) { + DPRINTLN("Wrong number of bits found. Aborting."); + return false; + } + // If we got less bits than we were expecting, we need to pad with zeros + // until we get the correct number of bits. + if (bitsSoFar < nbits) data <<= (nbits - bitsSoFar); + + // Success + DPRINTLN("Lutron Success!"); + results->decode_type = LUTRON; + results->bits = bitsSoFar; + results->value = data ^ (1ULL << nbits); // Mask off the initial '1'. + results->address = 0; + results->command = 0; + return true; +} +#endif // DECODE_LUTRON diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp new file mode 100644 index 000000000..a75e99e3a --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp @@ -0,0 +1,202 @@ +// Copyright 2018 Brett T. Warden +// derived from ir_Lasertag.cpp, Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// MM MM WW WW MM MM +// MMM MMM WW WW MMM MMM +// MM M MM WW W WW MM M MM +// MM MM WWW WWW MM MM +// MM MM WW WW MM MM + +// Constants +const uint16_t kMWMMinSamples = 6; // Msgs are >=3 bytes, bytes have >=2 + // samples +const uint16_t kMWMTick = 417; +const uint32_t kMWMMinGap = 30000; // Typical observed delay b/w commands +const uint8_t kMWMTolerance = 0; // Percentage error margin. +const uint16_t kMWMExcess = 0; // See kMarkExcess. +const uint16_t kMWMDelta = 150; // Use instead of Excess and Tolerance. +const uint8_t kMWMMaxWidth = 9; // Maximum number of successive bits at a + // single level - worst case +const int16_t kSpace = 1; +const int16_t kMark = 0; + +#if SEND_MWM +// Send a MWM packet. +// This protocol is 2400 bps serial, 1 start bit (mark), 1 stop bit (space), no +// parity +// +// Args: +// data: The message you wish to send. +// nbits: Bit size of the protocol you want to send. +// repeat: Nr. of extra times the data will be sent. +// +// Status: Implemented. +// +void IRsend::sendMWM(uint8_t data[], uint16_t nbytes, uint16_t repeat) { + if (nbytes < 3) return; // Shortest possible message is 3 bytes + + // Set 38kHz IR carrier frequency & a 1/4 (25%) duty cycle. + // NOTE: duty cycle is not confirmed. Just guessing based on RC5/6 protocols. + enableIROut(38, 25); + + for (uint16_t r = 0; r <= repeat; r++) { + // Data + for (uint16_t i = 0; i < nbytes; i++) { + uint8_t byte = data[i]; + + // Start bit + mark(kMWMTick); + + // LSB first, space=1 + for (uint8_t mask = 0x1; mask; mask <<= 1) { + if (byte & mask) { // 1 + space(kMWMTick); + } else { // 0 + mark(kMWMTick); + } + } + // Stop bit + space(kMWMTick); + } + // Footer + space(kMWMMinGap); + } +} +#endif // SEND_MWM + +#if DECODE_MWM +// Decode the supplied MWM message. +// This protocol is 2400 bps serial, 1 start bit (mark), 1 stop bit (space), no +// parity +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Implemented. +// +bool IRrecv::decodeMWM(decode_results *results, uint16_t nbits, bool strict) { + DPRINTLN("DEBUG: decodeMWM"); + + // Compliance + if (results->rawlen < kMWMMinSamples) { + DPRINTLN("DEBUG: decodeMWM: too few samples"); + return false; + } + + uint16_t offset = kStartOffset; + uint16_t used = 0; + uint64_t data = 0; + uint16_t frame_bits = 0; + uint16_t data_bits = 0; + + // No Header + + // Data + uint8_t bits_per_frame = 10; + for (; offset < results->rawlen && results->bits < 8 * kStateSizeMax; + frame_bits++) { + DPRINT("DEBUG: decodeMWM: offset = "); + DPRINTLN(uint64ToString(offset)); + int16_t level = getRClevel(results, &offset, &used, kMWMTick, kMWMTolerance, + kMWMExcess, kMWMDelta, kMWMMaxWidth); + if (level < 0) { + DPRINTLN("DEBUG: decodeMWM: getRClevel returned error"); + break; + } + switch (frame_bits % bits_per_frame) { + case 0: + // Start bit + if (level != kMark) { + DPRINTLN("DEBUG: decodeMWM: framing error - invalid start bit"); + goto done; + } + break; + case 9: + // Stop bit + if (level != kSpace) { + DPRINTLN("DEBUG: decodeMWM: framing error - invalid stop bit"); + return false; + } else { + DPRINT("DEBUG: decodeMWM: data_bits = "); + DPRINTLN(data_bits); + DPRINT("DEBUG: decodeMWM: Finished byte: "); + DPRINTLN(data); + results->state[data_bits / 8 - 1] = data & 0xFF; + results->bits = data_bits; + data = 0; + } + break; + default: + // Data bits + DPRINT("DEBUG: decodeMWM: Storing bit: "); + DPRINTLN((level == kSpace)); + // Transmission is LSB-first, space=1 + data |= ((level == kSpace)) << 8; + data >>= 1; + data_bits++; + break; + } + } + +done: + // Footer (None) + + // Compliance + DPRINT("DEBUG: decodeMWM: frame_bits = "); + DPRINTLN(frame_bits); + DPRINT("DEBUG: decodeMWM: data_bits = "); + DPRINTLN(data_bits); + if (data_bits < nbits) { + DPRINT("DEBUG: decodeMWM: too few bits; expected "); + DPRINTLN(nbits); + return false; // Less data than we expected. + } + + uint16_t payload_length = 0; + switch (results->state[0] & 0xf0) { + case 0x90: + case 0xf0: + // Normal commands + payload_length = results->state[0] & 0x0f; + DPRINT("DEBUG: decodeMWM: payload_length = "); + DPRINTLN(payload_length); + break; + default: + if (strict) { + // Show commands + if (results->state[0] != 0x55 && results->state[1] != 0xAA) { + return false; + } + } + break; + } + if (data_bits < (payload_length + 3) * 8) { + DPRINT("DEBUG: decodeMWM: too few bytes; expected "); + DPRINTLN((payload_length + 3)); + return false; + } + if (strict) { + if (payload_length && (data_bits > (payload_length + 3) * 8)) { + DPRINT("DEBUG: decodeMWM: too many bytes; expected "); + DPRINTLN((payload_length + 3)); + return false; + } + } + + // Success + results->decode_type = MWM; + results->repeat = false; + return true; +} +#endif // DECODE_MWM + +// vim: et:ts=2:sw=2 diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.cpp new file mode 100644 index 000000000..863aa0ec3 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.cpp @@ -0,0 +1,166 @@ +// Copyright 2013 mpflaga +// Copyright 2015 kitlaan +// Copyright 2017 Jason kendall, David Conran + +#include "ir_Magiquest.h" +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +#define IS_ZERO(m, s) (((m)*100 / ((m) + (s))) <= kMagiQuestZeroRatio) +#define IS_ONE(m, s) (((m)*100 / ((m) + (s))) >= kMagiQuestOneRatio) + +// Strips taken from: +// https://github.com/kitlaan/Arduino-IRremote/blob/master/ir_Magiquest.cpp +// and +// https://github.com/mpflaga/Arduino-IRremote + +// Source: https://github.com/mpflaga/Arduino-IRremote + +#if SEND_MAGIQUEST +// Send a MagiQuest formatted message. +// +// Args: +// data: The contents of the message you want to send. +// nbits: The bit size of the message being sent. +// Typically kMagiquestBits. +// repeat: The number of times you want the message to be repeated. +// +// Status: Alpha / Should be working. +// +void IRsend::sendMagiQuest(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(0, 0, // No Headers - Technically it's included in the data. + // i.e. 8 zeros. + kMagiQuestMarkOne, kMagiQuestSpaceOne, kMagiQuestMarkZero, + kMagiQuestSpaceZero, + 0, // No footer mark. + kMagiQuestGap, data, nbits, 36, true, repeat, 50); +} + +// Encode a MagiQuest wand_id, and a magnitude into a single 64bit value. +// (Only 48 bits of real data + 8 leading zero bits) +// This is suitable for calling sendMagiQuest() with. +// e.g. sendMagiQuest(encodeMagiQuest(wand_id, magnitude)); +uint64_t IRsend::encodeMagiQuest(uint32_t wand_id, uint16_t magnitude) { + uint64_t result = 0; + result = wand_id; + result <<= 16; + result |= magnitude; + // Shouldn't be needed, but ensure top 8/16 bit are zero. + result &= 0xFFFFFFFFFFFFULL; + return result; +} +#endif + +// Source: +// https://github.com/kitlaan/Arduino-IRremote/blob/master/ir_Magiquest.cpp + +#if DECODE_MAGIQUEST +// Decode the supplied MagiQuest message. +// MagiQuest protocol appears to be a header of 8 'zero' bits, followed +// by 32 bits of "wand ID" and finally 16 bits of "magnitude". +// Even though we describe this protocol as 56 bits, it really only has +// 48 bits of data that matter. +// +// In transmission order, 8 zeros + 32 wand_id + 16 magnitude. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion, inc. the 8 bit header. +// Typically kMagiquestBits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Alpha / Should work. +// +// Ref: +// https://github.com/kitlaan/Arduino-IRremote/blob/master/ir_Magiquest.cpp +bool IRrecv::decodeMagiQuest(decode_results *results, uint16_t nbits, + bool strict) { + uint16_t bits = 0; + uint64_t data = 0; + uint16_t offset = kStartOffset; + + if (results->rawlen < (2 * kMagiquestBits)) { + DPRINT("Not enough bits to be Magiquest - Rawlen: "); + DPRINT(results->rawlen); + DPRINT(" Expected: "); + DPRINTLN((2 * kMagiquestBits)); + return false; + } + + // Compliance + if (strict && nbits != kMagiquestBits) return false; + + // Of six wands as datapoints, so far they all start with 8 ZEROs. + // For example, here is the data from two wands + // 00000000 00100011 01001100 00100110 00000010 00000010 00010111 + // 00000000 00100000 10001000 00110001 00000010 00000010 10110100 + + // Decode the (MARK + SPACE) bits + while (offset + 1 < results->rawlen && bits < nbits - 1) { + uint16_t mark = results->rawbuf[offset]; + uint16_t space = results->rawbuf[offset + 1]; + if (!matchMark(mark + space, kMagiQuestTotalUsec)) { + DPRINT("Not enough time to be Magiquest - Mark: "); + DPRINT(mark); + DPRINT(" Space: "); + DPRINT(space); + DPRINT(" Total: "); + DPRINT(mark + space); + DPRINT("Expected: "); + DPRINTLN(kMagiQuestTotalUsec); + return false; + } + + if (IS_ZERO(mark, space)) + data = (data << 1) | 0; + else if (IS_ONE(mark, space)) + data = (data << 1) | 1; + else + return false; + + bits++; + offset += 2; + + // Compliance + // The first 8 bits of this protocol are supposed to all be 0. + // Exit out early as it is never going to match. + if (strict && bits == 8 && data != 0) return false; + } + + // Last bit is special as the protocol ends with a SPACE, not a MARK. + // Grab the last MARK bit, assuming a good SPACE after it + if (offset < results->rawlen) { + uint16_t mark = results->rawbuf[offset]; + uint16_t space = (kMagiQuestTotalUsec / kRawTick) - mark; + + if (IS_ZERO(mark, space)) + data = (data << 1) | 0; + else if (IS_ONE(mark, space)) + data = (data << 1) | 1; + else + return false; + + bits++; + } + + if (bits != nbits) return false; + + if (strict) { + // The top 8 bits of the 56 bits needs to be 0x00 to be valid. + // i.e. bits 56 to 49 are all zero. + if ((data >> (nbits - 8)) != 0) return false; + } + + // Success + results->decode_type = MAGIQUEST; + results->bits = bits; + results->value = data; + results->address = data >> 16; // Wand ID + results->command = data & 0xFFFF; // Magnitude + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.h new file mode 100644 index 000000000..d2d82d152 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.h @@ -0,0 +1,35 @@ +// Copyright 2013 mpflaga +// Copyright 2015 kitlaan +// Copyright 2017 Jason kendall, David Conran + +#ifndef IR_MAGIQUEST_H_ +#define IR_MAGIQUEST_H_ + +#define __STDC_LIMIT_MACROS +#include +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// MagiQuest packet is both Wand ID and magnitude of swish and flick +union magiquest { + uint64_t llword; + uint8_t byte[8]; + // uint16_t word[4]; + uint32_t lword[2]; + struct { + uint16_t magnitude; + uint32_t wand_id; + uint8_t padding; + uint8_t scrap; + } cmd; +}; + +const uint16_t kMagiQuestTotalUsec = 1150; +const uint8_t kMagiQuestZeroRatio = 30; // usually <= ~25% +const uint8_t kMagiQuestOneRatio = 38; // usually >= ~50% +const uint16_t kMagiQuestMarkZero = 280; +const uint16_t kMagiQuestSpaceZero = 850; +const uint16_t kMagiQuestMarkOne = 580; +const uint16_t kMagiQuestSpaceOne = 600; +const uint32_t kMagiQuestGap = 100000; // A guess of the gap between messages +#endif // IR_MAGIQUEST_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp new file mode 100644 index 000000000..8e55c7d22 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp @@ -0,0 +1,403 @@ +// Copyright 2017 bwze, crankyoldgit + +#include "ir_Midea.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// MM MM IIIII DDDDD EEEEEEE AAA +// MMM MMM III DD DD EE AAAAA +// MM MM MM III DD DD EEEEE AA AA +// MM MM III DD DD EE AAAAAAA +// MM MM IIIII DDDDDD EEEEEEE AA AA + +// Midea A/C added by (send) bwze/crankyoldgit & (decode) crankyoldgit +// +// Equipment it seems compatible with: +// * Pioneer System Model RYBO12GMFILCAD (12K BTU) +// * Pioneer System Model RUBO18GMFILCAD (18K BTU) +// * + +// Ref: +// https://docs.google.com/spreadsheets/d/1TZh4jWrx4h9zzpYUI9aYXMl1fYOiqu-xVuOOMqagxrs/edit?usp=sharing + +// Constants +const uint16_t kMideaTick = 80; +const uint16_t kMideaBitMarkTicks = 7; +const uint16_t kMideaBitMark = kMideaBitMarkTicks * kMideaTick; +const uint16_t kMideaOneSpaceTicks = 21; +const uint16_t kMideaOneSpace = kMideaOneSpaceTicks * kMideaTick; +const uint16_t kMideaZeroSpaceTicks = 7; +const uint16_t kMideaZeroSpace = kMideaZeroSpaceTicks * kMideaTick; +const uint16_t kMideaHdrMarkTicks = 56; +const uint16_t kMideaHdrMark = kMideaHdrMarkTicks * kMideaTick; +const uint16_t kMideaHdrSpaceTicks = 56; +const uint16_t kMideaHdrSpace = kMideaHdrSpaceTicks * kMideaTick; +const uint16_t kMideaMinGapTicks = + kMideaHdrMarkTicks + kMideaZeroSpaceTicks + kMideaBitMarkTicks; +const uint16_t kMideaMinGap = kMideaMinGapTicks * kMideaTick; +const uint8_t kMideaTolerance = 30; // Percent + +#if SEND_MIDEA +// Send a Midea message +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kMideaBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: Alpha / Needs testing against a real device. +// +void IRsend::sendMidea(uint64_t data, uint16_t nbits, uint16_t repeat) { + if (nbits % 8 != 0) return; // nbits is required to be a multiple of 8. + + // Set IR carrier frequency + enableIROut(38); + + for (uint16_t r = 0; r <= repeat; r++) { + // The protcol sends the message, then follows up with an entirely + // inverted payload. + for (size_t inner_loop = 0; inner_loop < 2; inner_loop++) { + // Header + mark(kMideaHdrMark); + space(kMideaHdrSpace); + // Data + // Break data into byte segments, starting at the Most Significant + // Byte. Each byte then being sent normal, then followed inverted. + for (uint16_t i = 8; i <= nbits; i += 8) { + // Grab a bytes worth of data. + uint8_t segment = (data >> (nbits - i)) & 0xFF; + sendData(kMideaBitMark, kMideaOneSpace, kMideaBitMark, kMideaZeroSpace, + segment, 8, true); + } + // Footer + mark(kMideaBitMark); + space(kMideaMinGap); // Pause before repeating + + // Invert the data for the 2nd phase of the message. + // As we get called twice in the inner loop, we will always revert + // to the original 'data' state. + data = ~data; + } + } +} +#endif + +// Code to emulate Midea A/C IR remote control unit. +// Warning: Consider this very alpha code. + +// Initialise the object. +IRMideaAC::IRMideaAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +// Reset the state of the remote to a known good state/sequence. +void IRMideaAC::stateReset() { + // Power On, Mode Auto, Fan Auto, Temp = 25C/77F + remote_state = 0xA1826FFFFF62; +} + +// Configure the pin for output. +void IRMideaAC::begin() { _irsend.begin(); } + +#if SEND_MIDEA +// Send the current desired state to the IR LED. +void IRMideaAC::send() { + checksum(); // Ensure correct checksum before sending. + _irsend.sendMidea(remote_state); +} +#endif // SEND_MIDEA + +// Return a pointer to the internal state date of the remote. +uint64_t IRMideaAC::getRaw() { + checksum(); + return remote_state & kMideaACStateMask; +} + +// Override the internal state with the new state. +void IRMideaAC::setRaw(uint64_t newState) { + remote_state = newState & kMideaACStateMask; +} + +// Set the requested power state of the A/C to off. +void IRMideaAC::on() { remote_state |= kMideaACPower; } + +// Set the requested power state of the A/C to off. +void IRMideaAC::off() { remote_state &= (kMideaACStateMask ^ kMideaACPower); } + +// Set the requested power state of the A/C. +void IRMideaAC::setPower(const bool state) { + if (state) + on(); + else + off(); +} + +// Return the requested power state of the A/C. +bool IRMideaAC::getPower() { return (remote_state & kMideaACPower); } + +// Set the temperature. +// Args: +// temp: Temp. in degrees. +// useCelsius: Degree type to use. Celsius (true) or Fahrenheit (false) +void IRMideaAC::setTemp(const uint8_t temp, const bool useCelsius) { + uint8_t new_temp = temp; + if (useCelsius) { + new_temp = std::max(kMideaACMinTempC, new_temp); + new_temp = std::min(kMideaACMaxTempC, new_temp); + new_temp = (uint8_t)((new_temp * 1.8) + 32.5); // 0.5 so we rounding. + } + new_temp = std::max(kMideaACMinTempF, new_temp); + new_temp = std::min(kMideaACMaxTempF, new_temp); + new_temp -= kMideaACMinTempF; + remote_state &= kMideaACTempMask; + remote_state |= ((uint64_t)new_temp << 24); +} + +// Return the set temp. +// Args: +// useCelsius: Flag indicating if the results are in Celsius or Fahrenheit. +// Returns: +// A uint8_t containing the temperature. +uint8_t IRMideaAC::getTemp(const bool useCelsius) { + uint8_t temp = ((remote_state >> 24) & 0x1F) + kMideaACMinTempF; + if (useCelsius) { + temp = (uint8_t)((temp - 32) / 1.8); + } + return temp; +} + +// Set the speed of the fan, +// 1-3 set the speed, 0 or anything else set it to auto. +void IRMideaAC::setFan(const uint8_t fan) { + uint64_t new_fan; + switch (fan) { + case kMideaACFanLow: + case kMideaACFanMed: + case kMideaACFanHigh: + new_fan = fan; + break; + default: + new_fan = kMideaACFanAuto; + } + remote_state &= kMideaACFanMask; + remote_state |= (new_fan << 35); +} + +// Return the requested state of the unit's fan. +uint8_t IRMideaAC::getFan() { return (remote_state >> 35) & 0b111; } + +// Get the requested climate operation mode of the a/c unit. +// Returns: +// A uint8_t containing the A/C mode. +uint8_t IRMideaAC::getMode() { return ((remote_state >> 32) & 0b111); } + +// Set the requested climate operation mode of the a/c unit. +void IRMideaAC::setMode(const uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + uint64_t new_mode; + switch (mode) { + case kMideaACAuto: + case kMideaACCool: + case kMideaACHeat: + case kMideaACDry: + case kMideaACFan: + new_mode = mode; + break; + default: + new_mode = kMideaACAuto; + } + remote_state &= kMideaACModeMask; + remote_state |= (new_mode << 32); +} + +// Set the Sleep state of the A/C. +void IRMideaAC::setSleep(const bool state) { + if (state) + remote_state |= kMideaACSleep; + else + remote_state &= (kMideaACStateMask ^ kMideaACSleep); +} + +// Return the Sleep state of the A/C. +bool IRMideaAC::getSleep() { return (remote_state & kMideaACSleep); } + +// Calculate the checksum for a given array. +// Args: +// state: The state to calculate the checksum over. +// Returns: +// The 8 bit checksum value. +uint8_t IRMideaAC::calcChecksum(const uint64_t state) { + uint8_t sum = 0; + uint64_t temp_state = state; + + for (uint8_t i = 0; i < 5; i++) { + temp_state >>= 8; + sum += reverseBits((temp_state & 0xFF), 8); + } + sum = 256 - sum; + return reverseBits(sum, 8); +} + +// Verify the checksum is valid for a given state. +// Args: +// state: The state to verify the checksum of. +// Returns: +// A boolean. +bool IRMideaAC::validChecksum(const uint64_t state) { + return ((state & 0xFF) == calcChecksum(state)); +} + +// Calculate & set the checksum for the current internal state of the remote. +void IRMideaAC::checksum() { + // Stored the checksum value in the last byte. + remote_state &= kMideaACChecksumMask; + remote_state |= calcChecksum(remote_state); +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRMideaAC::toString() { + String result = ""; +#else +std::string IRMideaAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kMideaACAuto: + result += " (AUTO)"; + break; + case kMideaACCool: + result += " (COOL)"; + break; + case kMideaACHeat: + result += " (HEAT)"; + break; + case kMideaACDry: + result += " (DRY)"; + break; + case kMideaACFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp(true)) + "C/" + + uint64ToString(getTemp(false)) + "F"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kMideaACFanAuto: + result += " (AUTO)"; + break; + case kMideaACFanLow: + result += " (LOW)"; + break; + case kMideaACFanMed: + result += " (MED)"; + break; + case kMideaACFanHigh: + result += " (HI)"; + break; + } + result += ", Sleep: "; + if (getSleep()) + result += "On"; + else + result += "Off"; + return result; +} + +#if DECODE_MIDEA +// Decode the supplied Midea message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kMideaBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Alpha / Needs testing against a real device. +// +bool IRrecv::decodeMidea(decode_results *results, uint16_t nbits, bool strict) { + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + + uint8_t min_nr_of_messages = 1; + if (strict) { + if (nbits != kMideaBits) return false; // Not strictly a MIDEA message. + min_nr_of_messages = 2; + } + + // The protocol sends the data normal + inverted, alternating on + // each byte. Hence twice the number of expected data bits. + if (results->rawlen < + min_nr_of_messages * (2 * nbits + kHeader + kFooter) - 1) + return false; // Can't possibly be a valid MIDEA message. + + uint64_t data = 0; + uint64_t inverted = 0; + uint16_t offset = kStartOffset; + + if (nbits > sizeof(data) * 8) + return false; // We can't possibly capture a Midea packet that big. + + for (uint8_t i = 0; i < min_nr_of_messages; i++) { + // Header + if (!matchMark(results->rawbuf[offset], kMideaHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kMideaHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kMideaHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kMideaHdrSpaceTicks; + + // Data (Normal) + match_result_t data_result = matchData( + &(results->rawbuf[offset]), nbits, kMideaBitMarkTicks * m_tick, + kMideaOneSpaceTicks * s_tick, kMideaBitMarkTicks * m_tick, + kMideaZeroSpaceTicks * s_tick, kMideaTolerance); + if (data_result.success == false) return false; + offset += data_result.used; + if (i % 2 == 0) + data = data_result.data; + else + inverted = data_result.data; + + // Footer + if (!matchMark(results->rawbuf[offset++], kMideaBitMarkTicks * m_tick, + kMideaTolerance)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kMideaMinGapTicks * s_tick, + kMideaTolerance)) + return false; + } + + // Compliance + if (strict) { + // Protocol requires a second message with all the data bits inverted. + // We should have checked we got a second message in the previous loop. + // Just need to check it's value is an inverted copy of the first message. + uint64_t mask = (1ULL << kMideaBits) - 1; + if ((data & mask) != ((inverted ^ mask) & mask)) return false; + if (!IRMideaAC::validChecksum(data)) return false; + } + + // Success + results->decode_type = MIDEA; + results->bits = nbits; + results->value = data; + results->address = 0; + results->command = 0; + return true; +} +#endif // DECODE_MIDEA diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h new file mode 100644 index 000000000..aa9f94a92 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h @@ -0,0 +1,103 @@ +// Copyright 2017 David Conran +#ifndef IR_MIDEA_H_ +#define IR_MIDEA_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifdef ARDUINO +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// MM MM IIIII DDDDD EEEEEEE AAA +// MMM MMM III DD DD EE AAAAA +// MM MM MM III DD DD EEEEE AA AA +// MM MM III DD DD EE AAAAAAA +// MM MM IIIII DDDDDD EEEEEEE AA AA + +// Midea added by crankyoldgit & bwze +// Ref: +// https://docs.google.com/spreadsheets/d/1TZh4jWrx4h9zzpYUI9aYXMl1fYOiqu-xVuOOMqagxrs/edit?usp=sharing + +// Constants +const uint8_t kMideaACCool = 0; // 0b000 +const uint8_t kMideaACDry = 1; // 0b001 +const uint8_t kMideaACAuto = 2; // 0b010 +const uint8_t kMideaACHeat = 3; // 0b011 +const uint8_t kMideaACFan = 4; // 0b100 +const uint8_t kMideaACFanAuto = 0; // 0b000 +const uint8_t kMideaACFanLow = 1; // 0b001 +const uint8_t kMideaACFanMed = 2; // 0b010 +const uint8_t kMideaACFanHigh = 3; // 0b011 +const uint64_t kMideaACPower = 1ULL << 39; +const uint64_t kMideaACSleep = 1ULL << 38; +const uint8_t kMideaACMinTempF = 62; // Fahrenheit +const uint8_t kMideaACMaxTempF = 86; // Fahrenheit +const uint8_t kMideaACMinTempC = 16; // Celsius +const uint8_t kMideaACMaxTempC = 30; // Celsius +const uint64_t kMideaACStateMask = 0x0000FFFFFFFFFFFF; +const uint64_t kMideaACTempMask = 0x0000FFFFE0FFFFFF; +const uint64_t kMideaACFanMask = 0x0000FFC7FFFFFFFF; +const uint64_t kMideaACModeMask = 0x0000FFF8FFFFFFFF; +const uint64_t kMideaACChecksumMask = 0x0000FFFFFFFFFF00; + +// Legacy defines. (Deprecated) +#define MIDEA_AC_COOL kMideaACCool +#define MIDEA_AC_DRY kMideaACDry +#define MIDEA_AC_AUTO kMideaACAuto +#define MIDEA_AC_HEAT kMideaACHeat +#define MIDEA_AC_FAN kMideaACFan +#define MIDEA_AC_FAN_AUTO kMideaACFanAuto +#define MIDEA_AC_FAN_LOW kMideaACFanLow +#define MIDEA_AC_FAN_MED kMideaACFanMed +#define MIDEA_AC_FAN_HI kMideaACFanHigh +#define MIDEA_AC_POWER kMideaACPower +#define MIDEA_AC_SLEEP kMideaACSleep +#define MIDEA_AC_MIN_TEMP_F kMideaACMinTempF +#define MIDEA_AC_MAX_TEMP_F kMideaACMaxTempF +#define MIDEA_AC_MIN_TEMP_C kMideaACMinTempC +#define MIDEA_AC_MAX_TEMP_C kMideaACMaxTempC + +class IRMideaAC { + public: + explicit IRMideaAC(uint16_t pin); + + void stateReset(); +#if SEND_MIDEA + void send(); +#endif // SEND_MIDEA + void begin(); + void on(); + void off(); + void setPower(const bool state); + bool getPower(); + void setTemp(const uint8_t temp, const bool useCelsius = false); + uint8_t getTemp(const bool useCelsius = false); + void setFan(const uint8_t fan); + uint8_t getFan(); + void setMode(const uint8_t mode); + uint8_t getMode(); + void setRaw(uint64_t newState); + uint64_t getRaw(); + static bool validChecksum(const uint64_t state); + void setSleep(const bool state); + bool getSleep(); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif +#ifndef UNIT_TEST + + private: +#endif + uint64_t remote_state; + void checksum(); + static uint8_t calcChecksum(const uint64_t state); + IRsend _irsend; +}; + +#endif // IR_MIDEA_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.cpp new file mode 100644 index 000000000..b092c27b9 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.cpp @@ -0,0 +1,714 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017-2018 David Conran +// Copyright 2018 Denes Varga + +#include "ir_Mitsubishi.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// MMMMM IIIII TTTTT SSSS U U BBBB IIIII SSSS H H IIIII +// M M M I T S U U B B I S H H I +// M M M I T SSS U U BBBB I SSS HHHHH I +// M M I T S U U B B I S H H I +// M M IIIII T SSSS UUU BBBBB IIIII SSSS H H IIIII + +// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote +// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran + +// Constants +// Mitsubishi TV +// period time is 1/33000Hz = 30.303 uSeconds (T) +// Ref: +// GlobalCache's Control Tower's Mitsubishi TV data. +// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Mitsubishi.cpp +const uint16_t kMitsubishiTick = 30; +const uint16_t kMitsubishiBitMarkTicks = 10; +const uint16_t kMitsubishiBitMark = kMitsubishiBitMarkTicks * kMitsubishiTick; +const uint16_t kMitsubishiOneSpaceTicks = 70; +const uint16_t kMitsubishiOneSpace = kMitsubishiOneSpaceTicks * kMitsubishiTick; +const uint16_t kMitsubishiZeroSpaceTicks = 30; +const uint16_t kMitsubishiZeroSpace = + kMitsubishiZeroSpaceTicks * kMitsubishiTick; +const uint16_t kMitsubishiMinCommandLengthTicks = 1786; +const uint16_t kMitsubishiMinCommandLength = + kMitsubishiMinCommandLengthTicks * kMitsubishiTick; +const uint16_t kMitsubishiMinGapTicks = 936; +const uint16_t kMitsubishiMinGap = kMitsubishiMinGapTicks * kMitsubishiTick; + +// Mitsubishi Projector (HC3000) +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/441 + +const uint16_t kMitsubishi2HdrMark = 8400; +const uint16_t kMitsubishi2HdrSpace = kMitsubishi2HdrMark / 2; +const uint16_t kMitsubishi2BitMark = 560; +const uint16_t kMitsubishi2ZeroSpace = 520; +const uint16_t kMitsubishi2OneSpace = kMitsubishi2ZeroSpace * 3; +const uint16_t kMitsubishi2MinGap = 28500; + +// Mitsubishi A/C +// Ref: +// https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L84 + +const uint16_t kMitsubishiAcHdrMark = 3400; +const uint16_t kMitsubishiAcHdrSpace = 1750; +const uint16_t kMitsubishiAcBitMark = 450; +const uint16_t kMitsubishiAcOneSpace = 1300; +const uint16_t kMitsubishiAcZeroSpace = 420; +const uint16_t kMitsubishiAcRptMark = 440; +const uint16_t kMitsubishiAcRptSpace = 17100; + +#if SEND_MITSUBISHI +// Send a Mitsubishi message +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kMitsubishiBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: ALPHA / untested. +// +// Notes: +// This protocol appears to have no header. +// Ref: +// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Mitsubishi.cpp +// GlobalCache's Control Tower's Mitsubishi TV data. +void IRsend::sendMitsubishi(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(0, 0, // No Header + kMitsubishiBitMark, kMitsubishiOneSpace, kMitsubishiBitMark, + kMitsubishiZeroSpace, kMitsubishiBitMark, kMitsubishiMinGap, + kMitsubishiMinCommandLength, data, nbits, 33, true, repeat, 50); +} +#endif // SEND_MITSUBISHI + +#if DECODE_MITSUBISHI +// Decode the supplied Mitsubishi message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / previously working. +// +// Notes: +// This protocol appears to have no header. +// +// Ref: +// GlobalCache's Control Tower's Mitsubishi TV data. +bool IRrecv::decodeMitsubishi(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + kFooter - 1) + return false; // Shorter than shortest possibly expected. + if (strict && nbits != kMitsubishiBits) + return false; // Request is out of spec. + + uint16_t offset = kStartOffset; + uint64_t data = 0; + + // No Header + // But try to auto-calibrate off the initial mark signal. + if (!matchMark(results->rawbuf[offset], kMitsubishiBitMark, 30)) return false; + // Calculate how long the common tick time is based on the initial mark. + uint32_t tick = results->rawbuf[offset] * kRawTick / kMitsubishiBitMarkTicks; + + // Data + match_result_t data_result = matchData( + &(results->rawbuf[offset]), nbits, kMitsubishiBitMarkTicks * tick, + kMitsubishiOneSpaceTicks * tick, kMitsubishiBitMarkTicks * tick, + kMitsubishiZeroSpaceTicks * tick); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + uint16_t actualBits = data_result.used / 2; + + // Footer + if (!matchMark(results->rawbuf[offset++], kMitsubishiBitMarkTicks * tick, 30)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kMitsubishiMinGapTicks * tick)) + return false; + + // Compliance + if (actualBits < nbits) return false; + if (strict && actualBits != nbits) return false; // Not as we expected. + + // Success + results->decode_type = MITSUBISHI; + results->bits = actualBits; + results->value = data; + results->address = 0; + results->command = 0; + return true; +} +#endif // DECODE_MITSUBISHI + +#if SEND_MITSUBISHI2 +// Send a Mitsubishi2 message +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kMitsubishiBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: ALPHA / untested. +// +// Notes: +// Based on a Mitsubishi HC3000 projector's remote. +// This protocol appears to have a manditory in-protocol repeat. +// That is in *addition* to the entire message needing to be sent twice +// for the device to accept the command. That is separate from the repeat. +// i.e. Allegedly, the real remote requires the "OFF" button pressed twice. +// You will need to add a suitable gap yourself. +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/441 +void IRsend::sendMitsubishi2(uint64_t data, uint16_t nbits, uint16_t repeat) { + for (uint16_t i = 0; i <= repeat; i++) { + // First half of the data. + sendGeneric(kMitsubishi2HdrMark, kMitsubishi2HdrSpace, kMitsubishi2BitMark, + kMitsubishi2OneSpace, kMitsubishi2BitMark, + kMitsubishi2ZeroSpace, kMitsubishi2BitMark, + kMitsubishi2HdrSpace, data >> (nbits / 2), nbits / 2, 33, true, + 0, 50); + // Second half of the data. + sendGeneric(0, 0, // No header for the second data block + kMitsubishi2BitMark, kMitsubishi2OneSpace, kMitsubishi2BitMark, + kMitsubishi2ZeroSpace, kMitsubishi2BitMark, kMitsubishi2MinGap, + data & ((1 << (nbits / 2)) - 1), nbits / 2, 33, true, 0, 50); + } +} +#endif // SEND_MITSUBISHI2 + +#if DECODE_MITSUBISHI2 +// Decode the supplied Mitsubishi2 message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Works with simulated data. +// +// Notes: +// Hardware supported: +// * Mitsubishi HC3000 projector's remote. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/441 +bool IRrecv::decodeMitsubishi2(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + kHeader + (kFooter * 2) - 1) + return false; // Shorter than shortest possibly expected. + if (strict && nbits != kMitsubishiBits) + return false; // Request is out of spec. + + uint16_t offset = kStartOffset; + uint64_t data = 0; + uint16_t actualBits = 0; + + // Header + if (!matchMark(results->rawbuf[offset++], kMitsubishi2HdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kMitsubishi2HdrSpace)) + return false; + for (uint8_t i = 1; i <= 2; i++) { + // Data + match_result_t data_result = matchData( + &(results->rawbuf[offset]), nbits / 2, kMitsubishi2BitMark, + kMitsubishi2OneSpace, kMitsubishi2BitMark, kMitsubishi2ZeroSpace); + if (data_result.success == false) return false; + data <<= nbits / 2; + data += data_result.data; + offset += data_result.used; + actualBits += data_result.used / 2; + + // Footer + if (!matchMark(results->rawbuf[offset++], kMitsubishi2BitMark)) + return false; + if (i % 2) { // Every odd data block, we expect a HDR space. + if (!matchSpace(results->rawbuf[offset++], kMitsubishi2HdrSpace)) + return false; + } else { // Every even data block, we expect Min Gap or end of the message. + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kMitsubishi2MinGap)) + return false; + } + } + + // Compliance + if (actualBits < nbits) return false; + if (strict && actualBits != nbits) return false; // Not as we expected. + + // Success + results->decode_type = MITSUBISHI2; + results->bits = actualBits; + results->value = data; + results->address = data >> actualBits / 2; + results->command = data & ((1 << (actualBits / 2)) - 1); + return true; +} +#endif // DECODE_MITSUBISHI2 + +#if SEND_MITSUBISHI_AC +// Send a Mitsubishi A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kMitsubishiACStateLength) +// repeat: Nr. of times the message is to be repeated. +// (Default = kMitsubishiACMinRepeat). +// +// Status: BETA / Appears to be working. +// +void IRsend::sendMitsubishiAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kMitsubishiACStateLength) + return; // Not enough bytes to send a proper message. + + sendGeneric(kMitsubishiAcHdrMark, kMitsubishiAcHdrSpace, kMitsubishiAcBitMark, + kMitsubishiAcOneSpace, kMitsubishiAcBitMark, + kMitsubishiAcZeroSpace, kMitsubishiAcRptMark, + kMitsubishiAcRptSpace, data, nbytes, 38, false, repeat, 50); +} +#endif // SEND_MITSUBISHI_AC + +#if DECODE_MITSUBISHI_AC +// Decode the supplied Mitsubishi message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Under development +// +// Ref: +// https://www.analysir.com/blog/2015/01/06/reverse-engineering-mitsubishi-ac-infrared-protocol/ +bool IRrecv::decodeMitsubishiAC(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < ((kMitsubishiACBits * 2) + 2)) { + DPRINTLN("Shorter than shortest possibly expected."); + return false; // Shorter than shortest possibly expected. + } + if (strict && nbits != kMitsubishiACBits) { + DPRINTLN("Request is out of spec."); + return false; // Request is out of spec. + } + uint16_t offset = kStartOffset; + for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) { + results->state[i] = 0; + } + bool failure = false; + uint8_t rep = 0; + do { + failure = false; + // Header: + // Somtime happens that junk signals arrives before the real message + bool headerFound = false; + while (!headerFound && + offset < (results->rawlen - (kMitsubishiACBits * 2 + 2))) { + headerFound = + matchMark(results->rawbuf[offset++], kMitsubishiAcHdrMark) && + matchSpace(results->rawbuf[offset++], kMitsubishiAcHdrSpace); + } + if (!headerFound) { + DPRINTLN("Header mark not found."); + failure = true; + } + // Decode byte-by-byte: + match_result_t data_result; + for (uint8_t i = 0; i < kMitsubishiACStateLength && !failure; i++) { + results->state[i] = 0; + data_result = + matchData(&(results->rawbuf[offset]), 8, kMitsubishiAcBitMark, + kMitsubishiAcOneSpace, kMitsubishiAcBitMark, + kMitsubishiAcZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) { + failure = true; + DPRINT("Byte decode failed at #"); + DPRINTLN((uint16_t)i); + } else { + results->state[i] = data_result.data; + offset += data_result.used; + DPRINT((uint16_t)results->state[i]); + DPRINT(","); + } + DPRINTLN(""); + } + // HEADER validation: + if (failure || results->state[0] != 0x23 || results->state[1] != 0xCB || + results->state[2] != 0x26 || results->state[3] != 0x01 || + results->state[4] != 0x00) { + DPRINTLN("Header mismatch."); + failure = true; + } else { + // DATA part: + + // FOOTER checksum: + if (IRMitsubishiAC::calculateChecksum(results->state) != + results->state[kMitsubishiACStateLength - 1]) { + DPRINTLN("Checksum error."); + failure = true; + } + } + if (rep != kMitsubishiACMinRepeat && failure) { + bool repeatMarkFound = false; + while (!repeatMarkFound && + offset < (results->rawlen - (kMitsubishiACBits * 2 + 4))) { + repeatMarkFound = + matchMark(results->rawbuf[offset++], kMitsubishiAcRptMark) && + matchSpace(results->rawbuf[offset++], kMitsubishiAcRptSpace); + } + if (!repeatMarkFound) { + DPRINTLN("First attempt failure and repeat mark not found."); + return false; + } + } + rep++; + // Check if the repeat is correct if we need strict decode: + if (strict && !failure) { + DPRINTLN("Strict repeat check enabled."); + // Repeat mark and space: + if (!matchMark(results->rawbuf[offset++], kMitsubishiAcRptMark) || + !matchSpace(results->rawbuf[offset++], kMitsubishiAcRptSpace)) { + DPRINTLN("Repeat mark error."); + return false; + } + // Header mark and space: + if (!matchMark(results->rawbuf[offset++], kMitsubishiAcHdrMark) || + !matchSpace(results->rawbuf[offset++], kMitsubishiAcHdrSpace)) { + DPRINTLN("Repeat header error."); + return false; + } + // Payload: + for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) { + data_result = + matchData(&(results->rawbuf[offset]), 8, kMitsubishiAcBitMark, + kMitsubishiAcOneSpace, kMitsubishiAcBitMark, + kMitsubishiAcZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false || + data_result.data != results->state[i]) { + DPRINTLN("Repeat payload error."); + return false; + } + offset += data_result.used; + } + } // strict repeat check + } while (failure && rep <= kMitsubishiACMinRepeat); + results->decode_type = MITSUBISHI_AC; + results->bits = kMitsubishiACStateLength * 8; + return true; +} +#endif // DECODE_MITSUBISHI_AC + +// Code to emulate Mitsubishi A/C IR remote control unit. +// Inspired and derived from the work done at: +// https://github.com/r45635/HVAC-IR-Control +// +// Warning: Consider this very alpha code. Seems to work, but not validated. +// +// Equipment it seems compatible with: +// * +// Initialise the object. +IRMitsubishiAC::IRMitsubishiAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +// Reset the state of the remote to a known good state/sequence. +void IRMitsubishiAC::stateReset() { + // The state of the IR remote in IR code form. + // Known good state obtained from: + // https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino#L108 + // Note: Can't use the following because it requires -std=c++11 + // uint8_t known_good_state[kMitsubishiACStateLength] = { + // 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, 0x45, 0x67, 0x00, + // 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; + remote_state[0] = 0x23; + remote_state[1] = 0xCB; + remote_state[2] = 0x26; + remote_state[3] = 0x01; + remote_state[4] = 0x00; + remote_state[5] = 0x20; + remote_state[6] = 0x08; + remote_state[7] = 0x06; + remote_state[8] = 0x30; + remote_state[9] = 0x45; + remote_state[10] = 0x67; + for (uint8_t i = 11; i < kMitsubishiACStateLength - 1; i++) + remote_state[i] = 0; + remote_state[kMitsubishiACStateLength - 1] = 0x1F; + checksum(); // Calculate the checksum +} + +// Configure the pin for output. +void IRMitsubishiAC::begin() { _irsend.begin(); } + +#if SEND_MITSUBISHI_AC +// Send the current desired state to the IR LED. +void IRMitsubishiAC::send() { + checksum(); // Ensure correct checksum before sending. + _irsend.sendMitsubishiAC(remote_state); +} +#endif // SEND_MITSUBISHI_AC + +// Return a pointer to the internal state date of the remote. +uint8_t *IRMitsubishiAC::getRaw() { + checksum(); + return remote_state; +} + +void IRMitsubishiAC::setRaw(uint8_t *data) { + for (uint8_t i = 0; i < (kMitsubishiACStateLength - 1); i++) { + remote_state[i] = data[i]; + } + checksum(); +} + +// Calculate the checksum for the current internal state of the remote. +void IRMitsubishiAC::checksum() { + remote_state[17] = calculateChecksum(remote_state); +} + +uint8_t IRMitsubishiAC::calculateChecksum(uint8_t *data) { + uint8_t sum = 0; + // Checksum is simple addition of all previous bytes stored + // as an 8 bit value. + for (uint8_t i = 0; i < 17; i++) sum += data[i]; + return sum & 0xFFU; +} + +// Set the requested power state of the A/C to off. +void IRMitsubishiAC::on() { + // state = ON; + remote_state[5] |= kMitsubishiAcPower; +} + +// Set the requested power state of the A/C to off. +void IRMitsubishiAC::off() { + // state = OFF; + remote_state[5] &= ~kMitsubishiAcPower; +} + +// Set the requested power state of the A/C. +void IRMitsubishiAC::setPower(bool state) { + if (state) + on(); + else + off(); +} + +// Return the requested power state of the A/C. +bool IRMitsubishiAC::getPower() { + return ((remote_state[5] & kMitsubishiAcPower) != 0); +} + +// Set the temp. in deg C +void IRMitsubishiAC::setTemp(uint8_t temp) { + temp = std::max((uint8_t)kMitsubishiAcMinTemp, temp); + temp = std::min((uint8_t)kMitsubishiAcMaxTemp, temp); + remote_state[7] = temp - kMitsubishiAcMinTemp; +} + +// Return the set temp. in deg C +uint8_t IRMitsubishiAC::getTemp() { + return (remote_state[7] + kMitsubishiAcMinTemp); +} + +// Set the speed of the fan, 0-6. +// 0 is auto, 1-5 is the speed, 6 is silent. +void IRMitsubishiAC::setFan(uint8_t fan) { + // Bounds check + if (fan > kMitsubishiAcFanSilent) + fan = kMitsubishiAcFanMax; // Set the fan to maximum if out of range. + if (fan == kMitsubishiAcFanAuto) { // Automatic is a special case. + remote_state[9] = 0b10000000 | (remote_state[9] & 0b01111000); + return; + } else if (fan >= kMitsubishiAcFanMax) { + fan--; // There is no spoon^H^H^Heed 5 (max), pretend it doesn't exist. + } + remote_state[9] &= 0b01111000; // Clear the previous state + remote_state[9] |= fan; +} + +// Return the requested state of the unit's fan. +uint8_t IRMitsubishiAC::getFan() { + uint8_t fan = remote_state[9] & 0b111; + if (fan == kMitsubishiAcFanMax) return kMitsubishiAcFanSilent; + return fan; +} + +// Return the requested climate operation mode of the a/c unit. +uint8_t IRMitsubishiAC::getMode() { return (remote_state[6]); } + +// Set the requested climate operation mode of the a/c unit. +void IRMitsubishiAC::setMode(uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + switch (mode) { + case kMitsubishiAcAuto: + remote_state[8] = 0b00110000; + break; + case kMitsubishiAcCool: + remote_state[8] = 0b00110110; + break; + case kMitsubishiAcDry: + remote_state[8] = 0b00110010; + break; + case kMitsubishiAcHeat: + remote_state[8] = 0b00110000; + break; + default: + mode = kMitsubishiAcAuto; + remote_state[8] = 0b00110000; + } + remote_state[6] = mode; +} + +// Set the requested vane operation mode of the a/c unit. +void IRMitsubishiAC::setVane(uint8_t mode) { + mode = std::min(mode, (uint8_t)0b111); // bounds check + mode |= 0b1000; + mode <<= 3; + remote_state[9] &= 0b11000111; // Clear the previous setting. + remote_state[9] |= mode; +} + +// Return the requested vane operation mode of the a/c unit. +uint8_t IRMitsubishiAC::getVane() { + return ((remote_state[9] & 0b00111000) >> 3); +} + +// Return the clock setting of the message. 1=1/6 hour. e.g. 4pm = 48 +uint8_t IRMitsubishiAC::getClock() { return remote_state[10]; } + +// Set the current time. 1 = 1/6 hour. e.g. 6am = 36. +void IRMitsubishiAC::setClock(uint8_t clock) { remote_state[10] = clock; } + +// Return the desired start time. 1 = 1/6 hour. e.g. 1am = 6 +uint8_t IRMitsubishiAC::getStartClock() { return remote_state[12]; } + +// Set the desired start tiem of the AC. 1 = 1/6 hour. e.g. 8pm = 120 +void IRMitsubishiAC::setStartClock(uint8_t clock) { remote_state[12] = clock; } + +// Return the desired stop time of the AC. 1 = 1/6 hour. e.g 10pm = 132 +uint8_t IRMitsubishiAC::getStopClock() { return remote_state[11]; } + +// Set the desired stop time of the AC. 1 = 1/6 hour. e.g 10pm = 132 +void IRMitsubishiAC::setStopClock(uint8_t clock) { remote_state[11] = clock; } + +// Return the timer setting. Possible values: kMitsubishiAcNoTimer, +// kMitsubishiAcStartTimer, kMitsubishiAcStopTimer, +// kMitsubishiAcStartStopTimer +uint8_t IRMitsubishiAC::getTimer() { return remote_state[13] & 0b111; } + +// Set the timer setting. Possible values: kMitsubishiAcNoTimer, +// kMitsubishiAcStartTimer, kMitsubishiAcStopTimer, +// kMitsubishiAcStartStopTimer +void IRMitsubishiAC::setTimer(uint8_t timer) { + remote_state[13] = timer & 0b111; +} + +#ifdef ARDUINO +String IRMitsubishiAC::timeToString(uint64_t time) { + String result = ""; +#else +std::string IRMitsubishiAC::timeToString(uint64_t time) { + std::string result = ""; +#endif // ARDUINO + if (time / 6 < 10) result += "0"; + result += uint64ToString(time / 6); + result += ":"; + if (time * 10 % 60 < 10) result += "0"; + result += uint64ToString(time * 10 % 60); + return result; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRMitsubishiAC::toString() { + String result = ""; +#else +std::string IRMitsubishiAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + switch (getMode()) { + case MITSUBISHI_AC_AUTO: + result += " (AUTO)"; + break; + case MITSUBISHI_AC_COOL: + result += " (COOL)"; + break; + case MITSUBISHI_AC_DRY: + result += " (DRY)"; + break; + case MITSUBISHI_AC_HEAT: + result += " (HEAT)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", FAN: "; + switch (getFan()) { + case MITSUBISHI_AC_FAN_AUTO: + result += "AUTO"; + break; + case MITSUBISHI_AC_FAN_MAX: + result += "MAX"; + break; + case MITSUBISHI_AC_FAN_SILENT: + result += "SILENT"; + break; + default: + result += uint64ToString(getFan()); + } + result += ", VANE: "; + switch (getVane()) { + case MITSUBISHI_AC_VANE_AUTO: + result += "AUTO"; + break; + case MITSUBISHI_AC_VANE_AUTO_MOVE: + result += "AUTO MOVE"; + break; + default: + result += uint64ToString(getVane()); + } + result += ", Time: "; + result += timeToString(getClock()); + result += ", On timer: "; + result += timeToString(getStartClock()); + result += ", Off timer: "; + result += timeToString(getStopClock()); + result += ", Timer: "; + switch (getTimer()) { + case kMitsubishiAcNoTimer: + result += "-"; + break; + case kMitsubishiAcStartTimer: + result += "Start"; + break; + case kMitsubishiAcStopTimer: + result += "Stop"; + break; + case kMitsubishiAcStartStopTimer: + result += "Start+Stop"; + break; + default: + result += "? ("; + result += getTimer(); + result += ")\n"; + } + return result; +} diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.h new file mode 100644 index 000000000..7b03efce6 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.h @@ -0,0 +1,109 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017 David Conran +#ifndef IR_MITSUBISHI_H_ +#define IR_MITSUBISHI_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// MMMMM IIIII TTTTT SSSS U U BBBB IIIII SSSS H H IIIII +// M M M I T S U U B B I S H H I +// M M M I T SSS U U BBBB I SSS HHHHH I +// M M I T S U U B B I S H H I +// M M IIIII T SSSS UUU BBBBB IIIII SSSS H H IIIII + +// Mitsubishi (TV) decoding added from https://github.com/z3t0/Arduino-IRremote +// Mitsubishi (TV) sending & Mitsubishi A/C support added by David Conran + +// Constants +const uint8_t kMitsubishiAcAuto = 0x20; +const uint8_t kMitsubishiAcCool = 0x18; +const uint8_t kMitsubishiAcDry = 0x10; +const uint8_t kMitsubishiAcHeat = 0x08; +const uint8_t kMitsubishiAcPower = 0x20; +const uint8_t kMitsubishiAcFanAuto = 0; +const uint8_t kMitsubishiAcFanMax = 5; +const uint8_t kMitsubishiAcFanRealMax = 4; +const uint8_t kMitsubishiAcFanSilent = 6; +const uint8_t kMitsubishiAcMinTemp = 16; // 16C +const uint8_t kMitsubishiAcMaxTemp = 31; // 31C +const uint8_t kMitsubishiAcVaneAuto = 0; +const uint8_t kMitsubishiAcVaneAutoMove = 7; +const uint8_t kMitsubishiAcNoTimer = 0; +const uint8_t kMitsubishiAcStartTimer = 5; +const uint8_t kMitsubishiAcStopTimer = 3; +const uint8_t kMitsubishiAcStartStopTimer = 7; + +// Legacy defines (Deprecated) +#define MITSUBISHI_AC_VANE_AUTO_MOVE kMitsubishiAcVaneAutoMove +#define MITSUBISHI_AC_VANE_AUTO kMitsubishiAcVaneAuto +#define MITSUBISHI_AC_POWER kMitsubishiAcPower +#define MITSUBISHI_AC_MIN_TEMP kMitsubishiAcMinTemp +#define MITSUBISHI_AC_MAX_TEMP kMitsubishiAcMaxTemp +#define MITSUBISHI_AC_HEAT kMitsubishiAcHeat +#define MITSUBISHI_AC_FAN_SILENT kMitsubishiAcFanSilent +#define MITSUBISHI_AC_FAN_REAL_MAX kMitsubishiAcFanRealMax +#define MITSUBISHI_AC_FAN_MAX kMitsubishiAcFanMax +#define MITSUBISHI_AC_FAN_AUTO kMitsubishiAcFanAuto +#define MITSUBISHI_AC_DRY kMitsubishiAcDry +#define MITSUBISHI_AC_COOL kMitsubishiAcCool +#define MITSUBISHI_AC_AUTO kMitsubishiAcAuto + +class IRMitsubishiAC { + public: + explicit IRMitsubishiAC(uint16_t pin); + + static uint8_t calculateChecksum(uint8_t* data); + + void stateReset(); +#if SEND_MITSUBISHI_AC + void send(); +#endif // SEND_MITSUBISHI_AC + void begin(); + void on(); + void off(); + void setPower(bool state); + bool getPower(); + void setTemp(uint8_t temp); + uint8_t getTemp(); + void setFan(uint8_t fan); + uint8_t getFan(); + void setMode(uint8_t mode); + uint8_t getMode(); + void setVane(uint8_t mode); + uint8_t getVane(); + uint8_t* getRaw(); + void setRaw(uint8_t* data); + uint8_t getClock(); + void setClock(uint8_t clock); + uint8_t getStartClock(); + void setStartClock(uint8_t clock); + uint8_t getStopClock(); + void setStopClock(uint8_t clock); + uint8_t getTimer(); + void setTimer(uint8_t timer); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: +#ifdef ARDUINO + String timeToString(uint64_t time); +#else + std::string timeToString(uint64_t time); +#endif + uint8_t remote_state[kMitsubishiACStateLength]; + void checksum(); + IRsend _irsend; +}; + +#endif // IR_MITSUBISHI_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_NEC.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.cpp similarity index 53% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_NEC.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.cpp index a5febe1b8..660b51109 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_NEC.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.cpp @@ -2,11 +2,11 @@ // Copyright 2017 David Conran #define __STDC_LIMIT_MACROS +#include "ir_NEC.h" #include #include #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" #include "IRutils.h" // N N EEEEE CCCC @@ -17,39 +17,13 @@ // NEC originally added from https://github.com/shirriff/Arduino-IRremote/ -// Constants -// Ref: -// http://www.sbprojects.com/knowledge/ir/nec.php -#define NEC_TICK 560U -#define NEC_HDR_MARK_TICKS 16U -#define NEC_HDR_MARK (NEC_HDR_MARK_TICKS * NEC_TICK) -#define NEC_HDR_SPACE_TICKS 8U -#define NEC_HDR_SPACE (NEC_HDR_SPACE_TICKS * NEC_TICK) -#define NEC_BIT_MARK_TICKS 1U -#define NEC_BIT_MARK (NEC_BIT_MARK_TICKS * NEC_TICK) -#define NEC_ONE_SPACE_TICKS 3U -#define NEC_ONE_SPACE (NEC_TICK * NEC_ONE_SPACE_TICKS) -#define NEC_ZERO_SPACE_TICKS 1U -#define NEC_ZERO_SPACE (NEC_TICK * NEC_ZERO_SPACE_TICKS) -#define NEC_RPT_SPACE_TICKS 4U -#define NEC_RPT_SPACE (NEC_RPT_SPACE_TICKS * NEC_TICK) -#define NEC_RPT_LENGTH 4U -#define NEC_MIN_COMMAND_LENGTH_TICKS 193U -#define NEC_MIN_COMMAND_LENGTH (NEC_MIN_COMMAND_LENGTH_TICKS * NEC_TICK) -#define NEC_MIN_GAP (NEC_MIN_COMMAND_LENGTH - \ - (NEC_HDR_MARK + NEC_HDR_SPACE + NEC_BITS * (NEC_BIT_MARK + NEC_ONE_SPACE) \ - + NEC_BIT_MARK)) -#define NEC_MIN_GAP_TICKS (NEC_MIN_COMMAND_LENGTH_TICKS - \ - (NEC_HDR_MARK_TICKS + NEC_HDR_SPACE_TICKS + \ - NEC_BITS * (NEC_BIT_MARK_TICKS + NEC_ONE_SPACE_TICKS) + \ - NEC_BIT_MARK_TICKS)) - -#if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO) +#if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO || \ + SEND_PIONEER) // Send a raw NEC(Renesas) formatted message. // // Args: // data: The message to be sent. -// nbits: The number of bits of the message to be sent. Typically NEC_BITS. +// nbits: The number of bits of the message to be sent. Typically kNECBits. // repeat: The number of times the command is to be repeated. // // Status: STABLE / Known working. @@ -57,29 +31,17 @@ // Ref: // http://www.sbprojects.com/knowledge/ir/nec.php void IRsend::sendNEC(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set 38kHz IR carrier frequency & a 1/3 (33%) duty cycle. - enableIROut(38, 33); - IRtimer usecs = IRtimer(); - // Header - mark(NEC_HDR_MARK); - space(NEC_HDR_SPACE); - // Data - sendData(NEC_BIT_MARK, NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, - data, nbits, true); - // Footer - mark(NEC_BIT_MARK); - // Gap to next command. - space(std::max(NEC_MIN_GAP, NEC_MIN_COMMAND_LENGTH - usecs.elapsed())); - + sendGeneric(kNecHdrMark, kNecHdrSpace, kNecBitMark, kNecOneSpace, kNecBitMark, + kNecZeroSpace, kNecBitMark, kNecMinGap, kNecMinCommandLength, + data, nbits, 38, true, 0, // Repeats are handled later. + 33); // Optional command repeat sequence. - for (uint16_t i = 0; i < repeat; i++) { - usecs.reset(); - mark(NEC_HDR_MARK); - space(NEC_RPT_SPACE); - mark(NEC_BIT_MARK); - // Gap till next command. - space(std::max(NEC_MIN_GAP, NEC_MIN_COMMAND_LENGTH - usecs.elapsed())); - } + if (repeat) + sendGeneric(kNecHdrMark, kNecRptSpace, 0, 0, 0, 0, // No actual data sent. + kNecBitMark, kNecMinGap, kNecMinCommandLength, 0, + 0, // No data to be sent. + 38, true, repeat - 1, // We've already sent a one message. + 33); } // Calculate the raw NEC data based on address and command. @@ -97,8 +59,8 @@ uint32_t IRsend::encodeNEC(uint16_t address, uint16_t command) { command &= 0xFF; // We only want the least significant byte of command. // sendNEC() sends MSB first, but protocol says this is LSB first. command = reverseBits(command, 8); - command = (command << 8) + (command ^ 0xFF); // Calculate the new command. - if (address > 0xFF) { // Is it Extended NEC? + command = (command << 8) + (command ^ 0xFF); // Calculate the new command. + if (address > 0xFF) { // Is it Extended NEC? address = reverseBits(address, 16); return ((address << 16) + command); // Extended. } else { @@ -113,7 +75,7 @@ uint32_t IRsend::encodeNEC(uint16_t address, uint16_t command) { // // Args: // results: Ptr to the data to decode and where to store the decode result. -// nbits: The number of data bits to expect. Typically NEC_BITS. +// nbits: The number of data bits to expect. Typically kNECBits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. @@ -122,34 +84,33 @@ uint32_t IRsend::encodeNEC(uint16_t address, uint16_t command) { // // Notes: // NEC protocol has three varients/forms. -// Normal: a 8 bit address & a 8 bit command in 32 bit data form. +// Normal: an 8 bit address & an 8 bit command in 32 bit data form. // i.e. address + inverted(address) + command + inverted(command) -// Extended: a 16 bit address & a 8 bit command in 32 bit data form. +// Extended: a 16 bit address & an 8 bit command in 32 bit data form. // i.e. address + command + inverted(command) // Repeat: a 0-bit code. i.e. No data bits. Just the header + footer. // // Ref: // http://www.sbprojects.com/knowledge/ir/nec.php bool IRrecv::decodeNEC(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + HEADER + FOOTER - 1 && - results->rawlen != NEC_RPT_LENGTH) + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1 && + results->rawlen != kNecRptLength) return false; // Can't possibly be a valid NEC message. - if (strict && nbits != NEC_BITS) + if (strict && nbits != kNECBits) return false; // Not strictly an NEC message. uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; // Header - if (!matchMark(results->rawbuf[offset], NEC_HDR_MARK)) return false; + if (!matchMark(results->rawbuf[offset], kNecHdrMark)) return false; // Calculate how long the lowest tick time is based on the header mark. - uint32_t mark_tick = results->rawbuf[offset++] * RAWTICK / - NEC_HDR_MARK_TICKS; + uint32_t mark_tick = results->rawbuf[offset++] * kRawTick / kNecHdrMarkTicks; // Check if it is a repeat code. - if (results->rawlen == NEC_RPT_LENGTH && - matchSpace(results->rawbuf[offset], NEC_RPT_SPACE) && - matchMark(results->rawbuf[offset + 1], NEC_BIT_MARK_TICKS * mark_tick)) { - results->value = REPEAT; + if (results->rawlen == kNecRptLength && + matchSpace(results->rawbuf[offset], kNecRptSpace) && + matchMark(results->rawbuf[offset + 1], kNecBitMarkTicks * mark_tick)) { + results->value = kRepeat; results->decode_type = NEC; results->bits = 0; results->address = 0; @@ -159,34 +120,32 @@ bool IRrecv::decodeNEC(decode_results *results, uint16_t nbits, bool strict) { } // Header (cont.) - if (!matchSpace(results->rawbuf[offset], NEC_HDR_SPACE)) return false; + if (!matchSpace(results->rawbuf[offset], kNecHdrSpace)) return false; // Calculate how long the common tick time is based on the header space. - uint32_t space_tick = results->rawbuf[offset++] * RAWTICK / - NEC_HDR_SPACE_TICKS; + uint32_t space_tick = + results->rawbuf[offset++] * kRawTick / kNecHdrSpaceTicks; // Data - match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, - NEC_BIT_MARK_TICKS * mark_tick, - NEC_ONE_SPACE_TICKS * space_tick, - NEC_BIT_MARK_TICKS * mark_tick, - NEC_ZERO_SPACE_TICKS * space_tick); + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kNecBitMarkTicks * mark_tick, + kNecOneSpaceTicks * space_tick, kNecBitMarkTicks * mark_tick, + kNecZeroSpaceTicks * space_tick); if (data_result.success == false) return false; data = data_result.data; offset += data_result.used; // Footer - if (!matchMark(results->rawbuf[offset++], NEC_BIT_MARK_TICKS * mark_tick)) - return false; - if (offset <= results->rawlen && - !matchAtLeast(results->rawbuf[offset], NEC_MIN_GAP_TICKS * space_tick)) + if (!matchMark(results->rawbuf[offset++], kNecBitMarkTicks * mark_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kNecMinGapTicks * space_tick)) return false; // Compliance // Calculate command and optionally enforce integrity checking. - uint8_t command = (data & 0xFF00) >> 8; + uint8_t command = (data & 0xFF00) >> 8; // Command is sent twice, once as plain and then inverted. if ((command ^ 0xFF) != (data & 0xFF)) { - if (strict) - return false; // Command integrity failed. + if (strict) return false; // Command integrity failed. command = 0; // The command value isn't valid, so default to zero. } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.h new file mode 100644 index 000000000..c274c104e --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.h @@ -0,0 +1,46 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017, 2018 David Conran + +#ifndef IR_NEC_H_ +#define IR_NEC_H_ + +#include +#include "IRremoteESP8266.h" + +// N N EEEEE CCCC +// NN N E C +// N N N EEE C +// N NN E C +// N N EEEEE CCCC + +// NEC originally added from https://github.com/shirriff/Arduino-IRremote/ + +// Constants +// Ref: +// http://www.sbprojects.com/knowledge/ir/nec.php +const uint16_t kNecTick = 560; +const uint16_t kNecHdrMarkTicks = 16; +const uint16_t kNecHdrMark = kNecHdrMarkTicks * kNecTick; +const uint16_t kNecHdrSpaceTicks = 8; +const uint16_t kNecHdrSpace = kNecHdrSpaceTicks * kNecTick; +const uint16_t kNecBitMarkTicks = 1; +const uint16_t kNecBitMark = kNecBitMarkTicks * kNecTick; +const uint16_t kNecOneSpaceTicks = 3; +const uint16_t kNecOneSpace = kNecOneSpaceTicks * kNecTick; +const uint16_t kNecZeroSpaceTicks = 1; +const uint16_t kNecZeroSpace = kNecZeroSpaceTicks * kNecTick; +const uint16_t kNecRptSpaceTicks = 4; +const uint16_t kNecRptSpace = kNecRptSpaceTicks * kNecTick; +const uint16_t kNecRptLength = 4; +const uint16_t kNecMinCommandLengthTicks = 193; +const uint32_t kNecMinCommandLength = kNecMinCommandLengthTicks * kNecTick; +const uint32_t kNecMinGap = + kNecMinCommandLength - + (kNecHdrMark + kNecHdrSpace + kNECBits * (kNecBitMark + kNecOneSpace) + + kNecBitMark); +const uint16_t kNecMinGapTicks = + kNecMinCommandLengthTicks - + (kNecHdrMarkTicks + kNecHdrSpaceTicks + + kNECBits * (kNecBitMarkTicks + kNecOneSpaceTicks) + kNecBitMarkTicks); + +#endif // IR_NEC_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Nikai.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Nikai.cpp new file mode 100644 index 000000000..9ac22a849 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Nikai.cpp @@ -0,0 +1,104 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// NN NN IIIII KK KK AAA IIIII +// NNN NN III KK KK AAAAA III +// NN N NN III KKKK AA AA III +// NN NNN III KK KK AAAAAAA III +// NN NN IIIII KK KK AA AA IIIII + +// Constants +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/309 +const uint16_t kNikaiTick = 500; +const uint16_t kNikaiHdrMarkTicks = 8; +const uint16_t kNikaiHdrMark = kNikaiHdrMarkTicks * kNikaiTick; +const uint16_t kNikaiHdrSpaceTicks = 8; +const uint16_t kNikaiHdrSpace = kNikaiHdrSpaceTicks * kNikaiTick; +const uint16_t kNikaiBitMarkTicks = 1; +const uint16_t kNikaiBitMark = kNikaiBitMarkTicks * kNikaiTick; +const uint16_t kNikaiOneSpaceTicks = 2; +const uint16_t kNikaiOneSpace = kNikaiOneSpaceTicks * kNikaiTick; +const uint16_t kNikaiZeroSpaceTicks = 4; +const uint16_t kNikaiZeroSpace = kNikaiZeroSpaceTicks * kNikaiTick; +const uint16_t kNikaiMinGapTicks = 17; +const uint16_t kNikaiMinGap = kNikaiMinGapTicks * kNikaiTick; + +#if SEND_NIKAI +// Send a Nikai TV formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The bit size of the message being sent. typically kNikaiBits. +// repeat: The number of times the message is to be repeated. +// +// Status: STABLE / Working. +// +// Ref: https://github.com/markszabo/IRremoteESP8266/issues/309 +void IRsend::sendNikai(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(kNikaiHdrMark, kNikaiHdrSpace, kNikaiBitMark, kNikaiOneSpace, + kNikaiBitMark, kNikaiZeroSpace, kNikaiBitMark, kNikaiMinGap, data, + nbits, 38, true, repeat, 33); +} +#endif + +#if DECODE_NIKAI +// Decode the supplied Nikai message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. +// Typically kNikaiBits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE / Working. +// +bool IRrecv::decodeNikai(decode_results *results, uint16_t nbits, bool strict) { + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid Nikai message. + if (strict && nbits != kNikaiBits) + return false; // We expect Nikai to be a certain sized message. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + + // Header + if (!matchMark(results->rawbuf[offset], kNikaiHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kNikaiHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kNikaiHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = results->rawbuf[offset++] * kRawTick / kNikaiHdrSpaceTicks; + // Data + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kNikaiBitMarkTicks * m_tick, + kNikaiOneSpaceTicks * s_tick, kNikaiBitMarkTicks * m_tick, + kNikaiZeroSpaceTicks * s_tick); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + // Footer + if (!matchMark(results->rawbuf[offset++], kNikaiBitMarkTicks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kNikaiMinGapTicks * s_tick)) + return false; + + // Compliance + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = NIKAI; + results->command = 0; + results->address = 0; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.cpp new file mode 100644 index 000000000..e79b136a5 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.cpp @@ -0,0 +1,863 @@ +// Copyright 2015 Kristian Lauszus +// Copyright 2017, 2018 David Conran + +#include "ir_Panasonic.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// PPPP AAA N N AAA SSSS OOO N N IIIII CCCC +// P P A A NN N A A S O O NN N I C +// PPPP AAAAA N N N AAAAA SSS O O N N N I C +// P A A N NN A A S O O N NN I C +// P A A N N A A SSSS OOO N N IIIII CCCC + +// Panasonic protocol originally added by Kristian Lauszus from: +// https://github.com/z3t0/Arduino-IRremote +// (Thanks to zenwheel and other people at the original blog post) +// +// Panasonic A/C support add by crankyoldgit but heavily influenced by: +// https://github.com/ToniA/ESPEasy/blob/HeatpumpIR/lib/HeatpumpIR/PanasonicHeatpumpIR.cpp +// Panasonic A/C Clock & Timer support: +// Reverse Engineering by MikkelTb +// Code by crankyoldgit +// Panasonic A/C models supported: +// A/C Series/models: +// JKE, LKE, DKE, CKP, & NKE series. (In theory) +// CS-YW9MKD (confirmed) +// CS-ME14CKPG / CS-ME12CKPG / CS-ME10CKPG +// A/C Remotes: +// A75C3747 (confirmed) +// A75C3704 +// A75C2311 (CKP) + +// Constants +// Ref: +// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152 + +const uint16_t kPanasonicTick = 432; +const uint16_t kPanasonicHdrMarkTicks = 8; +const uint16_t kPanasonicHdrMark = kPanasonicHdrMarkTicks * kPanasonicTick; +const uint16_t kPanasonicHdrSpaceTicks = 4; +const uint16_t kPanasonicHdrSpace = kPanasonicHdrSpaceTicks * kPanasonicTick; +const uint16_t kPanasonicBitMarkTicks = 1; +const uint16_t kPanasonicBitMark = kPanasonicBitMarkTicks * kPanasonicTick; +const uint16_t kPanasonicOneSpaceTicks = 3; +const uint16_t kPanasonicOneSpace = kPanasonicOneSpaceTicks * kPanasonicTick; +const uint16_t kPanasonicZeroSpaceTicks = 1; +const uint16_t kPanasonicZeroSpace = kPanasonicZeroSpaceTicks * kPanasonicTick; +const uint16_t kPanasonicMinCommandLengthTicks = 378; +const uint32_t kPanasonicMinCommandLength = + kPanasonicMinCommandLengthTicks * kPanasonicTick; +const uint16_t kPanasonicEndGap = 5000; // See issue #245 +const uint16_t kPanasonicMinGapTicks = + kPanasonicMinCommandLengthTicks - + (kPanasonicHdrMarkTicks + kPanasonicHdrSpaceTicks + + kPanasonicBits * (kPanasonicBitMarkTicks + kPanasonicOneSpaceTicks) + + kPanasonicBitMarkTicks); +const uint32_t kPanasonicMinGap = kPanasonicMinGapTicks * kPanasonicTick; + +const uint16_t kPanasonicAcSectionGap = 10000; +const uint16_t kPanasonicAcSection1Length = 8; +const uint32_t kPanasonicAcMessageGap = 100000; // A complete guess. + +#if (SEND_PANASONIC || SEND_DENON) +// Send a Panasonic formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The number of bits of the message to be sent. (kPanasonicBits). +// repeat: The number of times the command is to be repeated. +// +// Status: BETA / Should be working. +// +// Note: +// This protocol is a modified version of Kaseikyo. +void IRsend::sendPanasonic64(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(kPanasonicHdrMark, kPanasonicHdrSpace, kPanasonicBitMark, + kPanasonicOneSpace, kPanasonicBitMark, kPanasonicZeroSpace, + kPanasonicBitMark, kPanasonicMinGap, kPanasonicMinCommandLength, + data, nbits, kPanasonicFreq, true, repeat, 50); +} + +// Send a Panasonic formatted message. +// +// Args: +// address: The manufacturer code. +// data: The data portion to be sent. +// nbits: The number of bits of the message to be sent. (kPanasonicBits). +// repeat: The number of times the command is to be repeated. +// +// Status: STABLE. +// +// Note: +// This protocol is a modified version of Kaseikyo. +void IRsend::sendPanasonic(uint16_t address, uint32_t data, uint16_t nbits, + uint16_t repeat) { + sendPanasonic64(((uint64_t)address << 32) | (uint64_t)data, nbits, repeat); +} + +// Calculate the raw Panasonic data based on device, subdevice, & function. +// +// Args: +// manufacturer: A 16-bit manufacturer code. e.g. 0x4004 is Panasonic. +// device: An 8-bit code. +// subdevice: An 8-bit code. +// function: An 8-bit code. +// Returns: +// A raw uint64_t Panasonic message. +// +// Status: BETA / Should be working.. +// +// Note: +// Panasonic 48-bit protocol is a modified version of Kaseikyo. +// Ref: +// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?2615 +uint64_t IRsend::encodePanasonic(uint16_t manufacturer, uint8_t device, + uint8_t subdevice, uint8_t function) { + uint8_t checksum = device ^ subdevice ^ function; + return (((uint64_t)manufacturer << 32) | ((uint64_t)device << 24) | + ((uint64_t)subdevice << 16) | ((uint64_t)function << 8) | checksum); +} +#endif // (SEND_PANASONIC || SEND_DENON) + +#if (DECODE_PANASONIC || DECODE_DENON) +// Decode the supplied Panasonic message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Should be working. +// Note: +// Panasonic 48-bit protocol is a modified version of Kaseikyo. +// Ref: +// http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152 +// http://www.hifi-remote.com/wiki/index.php?title=Panasonic +bool IRrecv::decodePanasonic(decode_results *results, uint16_t nbits, + bool strict, uint32_t manufacturer) { + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Not enough entries to be a Panasonic message. + if (strict && nbits != kPanasonicBits) + return false; // Request is out of spec. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + + // Header + if (!matchMark(results->rawbuf[offset], kPanasonicHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = + results->rawbuf[offset++] * kRawTick / kPanasonicHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kPanasonicHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kPanasonicHdrSpaceTicks; + + // Data + match_result_t data_result = matchData( + &(results->rawbuf[offset]), nbits, kPanasonicBitMarkTicks * m_tick, + kPanasonicOneSpaceTicks * s_tick, kPanasonicBitMarkTicks * m_tick, + kPanasonicZeroSpaceTicks * s_tick); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Footer + if (!match(results->rawbuf[offset++], kPanasonicBitMarkTicks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kPanasonicEndGap)) + return false; + + // Compliance + uint32_t address = data >> 32; + uint32_t command = data & 0xFFFFFFFF; + if (strict) { + if (address != manufacturer) // Verify the Manufacturer code. + return false; + // Verify the checksum. + uint8_t checksumOrig = data & 0xFF; + uint8_t checksumCalc = ((data >> 24) ^ (data >> 16) ^ (data >> 8)) & 0xFF; + if (checksumOrig != checksumCalc) return false; + } + + // Success + results->value = data; + results->address = address; + results->command = command; + results->decode_type = PANASONIC; + results->bits = nbits; + return true; +} +#endif // (DECODE_PANASONIC || DECODE_DENON) + +#if SEND_PANASONIC_AC +// Send a Panasonic A/C message. +// +// Args: +// data: Contents of the message to be sent. (Guessing MSBF order) +// nbits: Nr. of bits of data to be sent. Typically kPanasonicAcBits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: Beta / Appears to work with real device(s). +//: +// Panasonic A/C models supported: +// A/C Series/models: +// JKE, LKE, DKE, & NKE series. +// CS-YW9MKD +// A/C Remotes: +// A75C3747 +// A75C3704 +// +void IRsend::sendPanasonicAC(uint8_t data[], uint16_t nbytes, uint16_t repeat) { + if (nbytes < kPanasonicAcSection1Length) return; + for (uint16_t r = 0; r <= repeat; r++) { + // First section. (8 bytes) + sendGeneric(kPanasonicHdrMark, kPanasonicHdrSpace, kPanasonicBitMark, + kPanasonicOneSpace, kPanasonicBitMark, kPanasonicZeroSpace, + kPanasonicBitMark, kPanasonicAcSectionGap, data, + kPanasonicAcSection1Length, kPanasonicFreq, false, 0, 50); + // First section. (The rest of the data bytes) + sendGeneric(kPanasonicHdrMark, kPanasonicHdrSpace, kPanasonicBitMark, + kPanasonicOneSpace, kPanasonicBitMark, kPanasonicZeroSpace, + kPanasonicBitMark, kPanasonicAcMessageGap, + data + kPanasonicAcSection1Length, + nbytes - kPanasonicAcSection1Length, kPanasonicFreq, false, 0, + 50); + } +} +#endif // SEND_PANASONIC_AC + +IRPanasonicAc::IRPanasonicAc(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRPanasonicAc::stateReset() { + for (uint8_t i = 0; i < kPanasonicAcStateLength; i++) + remote_state[i] = kPanasonicKnownGoodState[i]; + _temp = 25; // An initial saved desired temp. Completely made up. + _swingh = kPanasonicAcSwingHMiddle; // A similar made up value for H Swing. +} + +void IRPanasonicAc::begin() { _irsend.begin(); } + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRPanasonicAc::validChecksum(uint8_t state[], const uint16_t length) { + if (length < 2) return false; // 1 byte of data can't have a checksum. + return (state[length - 1] == + sumBytes(state, length - 1, kPanasonicAcChecksumInit)); +} + +uint8_t IRPanasonicAc::calcChecksum(uint8_t state[], const uint16_t length) { + return sumBytes(state, length - 1, kPanasonicAcChecksumInit); +} + +void IRPanasonicAc::fixChecksum(const uint16_t length) { + remote_state[length - 1] = calcChecksum(remote_state, length); +} + +#if SEND_PANASONIC_AC +void IRPanasonicAc::send() { + fixChecksum(); + _irsend.sendPanasonicAC(remote_state); +} +#endif // SEND_PANASONIC_AC + +void IRPanasonicAc::setModel(const panasonic_ac_remote_model_t model) { + switch (model) { + case kPanasonicDke: + case kPanasonicJke: + case kPanasonicLke: + case kPanasonicNke: + case kPanasonicCkp: + break; + default: // Only proceed if we know what to do. + return; + } + // clear & set the various bits and bytes. + remote_state[13] &= 0xF0; + remote_state[17] = 0x00; + remote_state[21] &= 0b11101111; + remote_state[23] = 0x81; + remote_state[25] = 0x00; + + switch (model) { + case kPanasonicLke: + remote_state[13] |= 0x02; + remote_state[17] = 0x06; + break; + case kPanasonicDke: + remote_state[23] = 0x01; + remote_state[25] = 0x06; + // Has to be done last as setSwingHorizontal has model check built-in + setSwingHorizontal(_swingh); + break; + case kPanasonicNke: + remote_state[17] = 0x06; + break; + case kPanasonicJke: + break; + case kPanasonicCkp: + remote_state[21] |= 0x10; + remote_state[23] = 0x01; + default: + break; + } +} + +panasonic_ac_remote_model_t IRPanasonicAc::getModel() { + if (remote_state[17] == 0x00) { + if ((remote_state[21] & 0x10) && (remote_state[23] & 0x01)) + return kPanasonicCkp; + if (remote_state[23] & 0x80) return kPanasonicJke; + } + if (remote_state[17] == 0x06 && (remote_state[13] & 0x0F) == 0x02) + return kPanasonicLke; + if (remote_state[23] == 0x01) return kPanasonicDke; + if (remote_state[17] == 0x06) return kPanasonicNke; + return kPanasonicUnknown; +} + +uint8_t *IRPanasonicAc::getRaw() { + fixChecksum(); + return remote_state; +} + +void IRPanasonicAc::setRaw(const uint8_t state[]) { + for (uint8_t i = 0; i < kPanasonicAcStateLength; i++) { + remote_state[i] = state[i]; + } +} + +// Control the power state of the A/C unit. +// +// For CKP models, the remote has no memory of the power state the A/C unit +// should be in. For those models setting this on/true will toggle the power +// state of the Panasonic A/C unit with the next meessage. +// e.g. If the A/C unit is already on, setPower(true) will turn it off. +// If the A/C unit is already off, setPower(true) will turn it on. +// setPower(false) will leave the A/C power state as it was. +// +// For all other models, setPower(true) should set the internal state to +// turn it on, and setPower(false) should turn it off. +void IRPanasonicAc::setPower(const bool state) { + if (state) + on(); + else + off(); +} + +// Return the A/C power state of the remote. +// Except for CKP models, where it returns if the power state will be toggled +// on the A/C unit when the next message is sent. +bool IRPanasonicAc::getPower() { + return (remote_state[13] & kPanasonicAcPower) == kPanasonicAcPower; +} + +void IRPanasonicAc::on() { remote_state[13] |= kPanasonicAcPower; } + +void IRPanasonicAc::off() { remote_state[13] &= ~kPanasonicAcPower; } + +uint8_t IRPanasonicAc::getMode() { return remote_state[13] >> 4; } + +void IRPanasonicAc::setMode(const uint8_t desired) { + uint8_t mode = kPanasonicAcAuto; // Default to Auto mode. + switch (desired) { + case kPanasonicAcFan: + // Allegedly Fan mode has a temperature of 27. + setTemp(kPanasonicAcFanModeTemp, false); + mode = desired; + break; + case kPanasonicAcAuto: + case kPanasonicAcCool: + case kPanasonicAcHeat: + case kPanasonicAcDry: + mode = desired; + // Set the temp to the saved temp, just incase our previous mode was Fan. + setTemp(_temp); + break; + } + remote_state[13] &= 0x0F; // Clear the previous mode bits. + remote_state[13] |= mode << 4; +} + +uint8_t IRPanasonicAc::getTemp() { return remote_state[14] >> 1; } + +// Set the desitred temperature in Celcius. +// Args: +// celsius: The temperature to set the A/C unit to. +// remember: A boolean flag for the class to remember the temperature. +// +// Automatically safely limits the temp to the operating range supported. +void IRPanasonicAc::setTemp(const uint8_t celsius, const bool remember) { + uint8_t temperature; + temperature = std::max(celsius, kPanasonicAcMinTemp); + temperature = std::min(temperature, kPanasonicAcMaxTemp); + remote_state[14] = temperature << 1; + if (remember) _temp = temperature; +} + +uint8_t IRPanasonicAc::getSwingVertical() { return remote_state[16] & 0x0F; } + +void IRPanasonicAc::setSwingVertical(const uint8_t desired_elevation) { + uint8_t elevation = desired_elevation; + if (elevation != kPanasonicAcSwingVAuto) { + elevation = std::max(elevation, kPanasonicAcSwingVUp); + elevation = std::min(elevation, kPanasonicAcSwingVDown); + } + remote_state[16] &= 0xF0; + remote_state[16] |= elevation; +} + +uint8_t IRPanasonicAc::getSwingHorizontal() { return remote_state[17]; } + +void IRPanasonicAc::setSwingHorizontal(const uint8_t desired_direction) { + switch (desired_direction) { + case kPanasonicAcSwingHAuto: + case kPanasonicAcSwingHMiddle: + case kPanasonicAcSwingHFullLeft: + case kPanasonicAcSwingHLeft: + case kPanasonicAcSwingHRight: + case kPanasonicAcSwingHFullRight: + break; + default: // Ignore anything that isn't valid. + return; + } + _swingh = desired_direction; // Store the direction for later. + uint8_t direction = desired_direction; + switch (getModel()) { + case kPanasonicDke: + break; + case kPanasonicNke: + case kPanasonicLke: + direction = kPanasonicAcSwingHMiddle; + break; + default: // Ignore everything else. + return; + } + remote_state[17] = direction; +} + +void IRPanasonicAc::setFan(const uint8_t speed) { + if (speed <= kPanasonicAcFanMax || speed == kPanasonicAcFanAuto) + remote_state[16] = + (remote_state[16] & 0x0F) | ((speed + kPanasonicAcFanOffset) << 4); +} + +uint8_t IRPanasonicAc::getFan() { + return (remote_state[16] >> 4) - kPanasonicAcFanOffset; +} + +bool IRPanasonicAc::getQuiet() { + if (getModel() == kPanasonicCkp) + return remote_state[21] & kPanasonicAcQuietCkp; + else + return remote_state[21] & kPanasonicAcQuiet; +} + +void IRPanasonicAc::setQuiet(const bool state) { + uint8_t quiet; + if (getModel() == kPanasonicCkp) + quiet = kPanasonicAcQuietCkp; + else + quiet = kPanasonicAcQuiet; + + if (state) { + setPowerful(false); // Powerful is mutually exclusive. + remote_state[21] |= quiet; + } else { + remote_state[21] &= ~quiet; + } +} + +bool IRPanasonicAc::getPowerful() { + if (getModel() == kPanasonicCkp) + return remote_state[21] & kPanasonicAcPowerfulCkp; + else + return remote_state[21] & kPanasonicAcPowerful; +} + +void IRPanasonicAc::setPowerful(const bool state) { + uint8_t powerful; + if (getModel() == kPanasonicCkp) + powerful = kPanasonicAcPowerfulCkp; + else + powerful = kPanasonicAcPowerful; + + if (state) { + setQuiet(false); // Quiet is mutually exclusive. + remote_state[21] |= powerful; + } else { + remote_state[21] &= ~powerful; + } +} + +uint16_t IRPanasonicAc::encodeTime(const uint8_t hours, const uint8_t mins) { + return std::min(hours, (uint8_t)23) * 60 + std::min(mins, (uint8_t)59); +} + +uint16_t IRPanasonicAc::getClock() { + uint16_t result = ((remote_state[25] & 0b00000111) << 8) + remote_state[24]; + if (result == kPanasonicAcTimeSpecial) return 0; + return result; +} + +void IRPanasonicAc::setClock(const uint16_t mins_since_midnight) { + uint16_t corrected = std::min(mins_since_midnight, kPanasonicAcTimeMax); + if (mins_since_midnight == kPanasonicAcTimeSpecial) + corrected = kPanasonicAcTimeSpecial; + remote_state[24] = corrected & 0xFF; + remote_state[25] &= 0b11111000; + remote_state[25] |= (corrected >> 8); +} + +uint16_t IRPanasonicAc::getOnTimer() { + uint16_t result = ((remote_state[19] & 0b00000111) << 8) + remote_state[18]; + if (result == kPanasonicAcTimeSpecial) return 0; + return result; +} + +void IRPanasonicAc::setOnTimer(const uint16_t mins_since_midnight, + const bool enable) { + // Ensure it's on a 10 minute boundary and no overflow. + uint16_t corrected = std::min(mins_since_midnight, kPanasonicAcTimeMax); + corrected -= corrected % 10; + if (mins_since_midnight == kPanasonicAcTimeSpecial) + corrected = kPanasonicAcTimeSpecial; + + if (enable) + remote_state[13] |= kPanasonicAcOnTimer; // Set the Ontimer flag. + else + remote_state[13] &= ~kPanasonicAcOnTimer; // Clear the Ontimer flag. + // Store the time. + remote_state[18] = corrected & 0xFF; + remote_state[19] &= 0b11111000; + remote_state[19] |= (corrected >> 8); +} + +void IRPanasonicAc::cancelOnTimer() { setOnTimer(0, false); } + +bool IRPanasonicAc::isOnTimerEnabled() { + return remote_state[13] & kPanasonicAcOnTimer; +} + +uint16_t IRPanasonicAc::getOffTimer() { + uint16_t result = + ((remote_state[20] & 0b01111111) << 4) + (remote_state[19] >> 4); + if (result == kPanasonicAcTimeSpecial) return 0; + return result; +} + +void IRPanasonicAc::setOffTimer(const uint16_t mins_since_midnight, + const bool enable) { + // Ensure its on a 10 minute boundary and no overflow. + uint16_t corrected = std::min(mins_since_midnight, kPanasonicAcTimeMax); + corrected -= corrected % 10; + if (mins_since_midnight == kPanasonicAcTimeSpecial) + corrected = kPanasonicAcTimeSpecial; + + if (enable) + remote_state[13] |= kPanasonicAcOffTimer; // Set the OffTimer flag. + else + remote_state[13] &= ~kPanasonicAcOffTimer; // Clear the OffTimer flag. + // Store the time. + remote_state[19] &= 0b00001111; + remote_state[19] |= (corrected & 0b00001111) << 4; + remote_state[20] &= 0b10000000; + remote_state[20] |= corrected >> 4; +} + +void IRPanasonicAc::cancelOffTimer() { setOffTimer(0, false); } + +bool IRPanasonicAc::isOffTimerEnabled() { + return remote_state[13] & kPanasonicAcOffTimer; +} + +#ifdef ARDUINO +String IRPanasonicAc::timeToString(const uint16_t mins_since_midnight) { + String result = ""; +#else +std::string IRPanasonicAc::timeToString(const uint16_t mins_since_midnight) { + std::string result = ""; +#endif // ARDUINO + result += uint64ToString(mins_since_midnight / 60) + ":"; + uint8_t mins = mins_since_midnight % 60; + if (mins < 10) result += "0"; // Zero pad the minutes. + return result + uint64ToString(mins); +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRPanasonicAc::toString() { + String result = ""; +#else +std::string IRPanasonicAc::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Model: " + uint64ToString(getModel()); + switch (getModel()) { + case kPanasonicDke: + result += " (DKE)"; + break; + case kPanasonicJke: + result += " (JKE)"; + break; + case kPanasonicNke: + result += " (NKE)"; + break; + case kPanasonicLke: + result += " (LKE)"; + break; + case kPanasonicCkp: + result += " (CKP)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kPanasonicAcAuto: + result += " (AUTO)"; + break; + case kPanasonicAcCool: + result += " (COOL)"; + break; + case kPanasonicAcHeat: + result += " (HEAT)"; + break; + case kPanasonicAcDry: + result += " (DRY)"; + break; + case kPanasonicAcFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kPanasonicAcFanAuto: + result += " (AUTO)"; + break; + case kPanasonicAcFanMax: + result += " (MAX)"; + break; + case kPanasonicAcFanMin: + result += " (MIN)"; + break; + default: + result += " (UNKNOWN)"; + break; + } + result += ", Swing (Vertical): " + uint64ToString(getSwingVertical()); + switch (getSwingVertical()) { + case kPanasonicAcSwingVAuto: + result += " (AUTO)"; + break; + case kPanasonicAcSwingVUp: + result += " (Full Up)"; + break; + case kPanasonicAcSwingVDown: + result += " (Full Down)"; + break; + case 2: + case 3: + case 4: + break; + default: + result += " (UNKNOWN)"; + break; + } + switch (getModel()) { + case kPanasonicJke: + case kPanasonicCkp: + break; // No Horizontal Swing support. + default: + result += ", Swing (Horizontal): " + uint64ToString(getSwingHorizontal()); + switch (getSwingHorizontal()) { + case kPanasonicAcSwingHAuto: + result += " (AUTO)"; + break; + case kPanasonicAcSwingHFullLeft: + result += " (Full Left)"; + break; + case kPanasonicAcSwingHLeft: + result += " (Left)"; + break; + case kPanasonicAcSwingHMiddle: + result += " (Middle)"; + break; + case kPanasonicAcSwingHFullRight: + result += " (Full Right)"; + break; + case kPanasonicAcSwingHRight: + result += " (Right)"; + break; + default: + result += " (UNKNOWN)"; + break; + } + } + result += ", Quiet: "; + if (getQuiet()) + result += "On"; + else + result += "Off"; + result += ", Powerful: "; + if (getPowerful()) + result += "On"; + else + result += "Off"; + result += ", Clock: " + timeToString(getClock()); + result += ", On Timer: "; + if (isOnTimerEnabled()) + result += timeToString(getOnTimer()); + else + result += "Off"; + result += ", Off Timer: "; + if (isOffTimerEnabled()) + result += timeToString(getOffTimer()); + else + result += "Off"; + return result; +} + +#if DECODE_PANASONIC_AC +// Decode the supplied Panasonic AC message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kPanasonicAcBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Beta / Appears to work with real device(s). +// +// Panasonic A/C models supported: +// A/C Series/models: +// JKE, LKE, DKE, & NKE series. +// CS-YW9MKD +// A/C Remotes: +// A75C3747 (Confirmed) +// A75C3704 +bool IRrecv::decodePanasonicAC(decode_results *results, uint16_t nbits, + bool strict) { + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + + uint8_t min_nr_of_messages = 1; + if (strict) { + if (nbits != kPanasonicAcBits && nbits != kPanasonicAcShortBits) + return false; // Not strictly a PANASONIC_AC message. + } + + if (results->rawlen < + min_nr_of_messages * (2 * nbits + kHeader + kFooter) - 1) + return false; // Can't possibly be a valid PANASONIC_AC message. + + uint16_t dataBitsSoFar = 0; + uint16_t offset = kStartOffset; + match_result_t data_result; + + // Header + if (!matchMark(results->rawbuf[offset], kPanasonicHdrMark, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = + results->rawbuf[offset++] * kRawTick / kPanasonicHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kPanasonicHdrSpace, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kPanasonicHdrSpaceTicks; + + uint16_t i = 0; + // Data (Section #1) + // Keep reading bytes until we either run out of section or state to fill. + for (; offset <= results->rawlen - 16 && i < kPanasonicAcSection1Length; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData( + &(results->rawbuf[offset]), 8, kPanasonicBitMarkTicks * m_tick, + kPanasonicOneSpaceTicks * s_tick, kPanasonicBitMarkTicks * m_tick, + kPanasonicZeroSpaceTicks * s_tick, kPanasonicAcTolerance, + kPanasonicAcExcess, false); + if (data_result.success == false) { + DPRINT("DEBUG: offset = "); + DPRINTLN(offset + data_result.used); + return false; // Fail + } + results->state[i] = data_result.data; + } + // Section footer. + if (!matchMark(results->rawbuf[offset++], kPanasonicBitMarkTicks * m_tick, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + if (!matchSpace(results->rawbuf[offset++], kPanasonicAcSectionGap, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + // Header. + if (!matchMark(results->rawbuf[offset++], kPanasonicHdrMarkTicks * m_tick, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + if (!matchSpace(results->rawbuf[offset++], kPanasonicHdrSpaceTicks * s_tick, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + // Data (Section #2) + // Keep reading bytes until we either run out of data. + for (; offset <= results->rawlen - 16 && i < nbits / 8; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData( + &(results->rawbuf[offset]), 8, kPanasonicBitMarkTicks * m_tick, + kPanasonicOneSpaceTicks * s_tick, kPanasonicBitMarkTicks * m_tick, + kPanasonicZeroSpaceTicks * s_tick, kPanasonicAcTolerance, + kPanasonicAcExcess, false); + if (data_result.success == false) { + DPRINT("DEBUG: offset = "); + DPRINTLN(offset + data_result.used); + return false; // Fail + } + results->state[i] = data_result.data; + } + // Message Footer. + if (!matchMark(results->rawbuf[offset++], kPanasonicBitMarkTicks * m_tick, + kPanasonicAcTolerance, kPanasonicAcExcess)) + return false; + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kPanasonicAcMessageGap)) + return false; + + // Compliance + if (strict) { + // Check the signatures of the section blocks. They start with 0x02& 0x20. + if (results->state[0] != 0x02 || results->state[1] != 0x20 || + results->state[8] != 0x02 || results->state[9] != 0x20) + return false; + if (!IRPanasonicAc::validChecksum(results->state, nbits / 8)) return false; + } + + // Success + results->decode_type = PANASONIC_AC; + results->bits = nbits; + return true; +} +#endif // DECODE_PANASONIC_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.h new file mode 100644 index 000000000..762631fe7 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.h @@ -0,0 +1,145 @@ +// Copyright 2018 David Conran + +#ifndef IR_PANASONIC_H_ +#define IR_PANASONIC_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifdef ARDUINO +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// PPPP AAA N N AAA SSSS OOO N N IIIII CCCC +// P P A A NN N A A S O O NN N I C +// PPPP AAAAA N N N AAAAA SSS O O N N N I C +// P A A N NN A A S O O N NN I C +// P A A N N A A SSSS OOO N N IIIII CCCC + +// Panasonic A/C support heavily influenced by: +// https://github.com/ToniA/ESPEasy/blob/HeatpumpIR/lib/HeatpumpIR/PanasonicHeatpumpIR.cpp + +// Constants +const uint16_t kPanasonicFreq = 36700; +const uint16_t kPanasonicAcExcess = 0; +// Much higher than usual. See issue #540. +const uint16_t kPanasonicAcTolerance = 40; + +const uint8_t kPanasonicAcAuto = 0; // 0b0000 +const uint8_t kPanasonicAcDry = 2; // 0b0010 +const uint8_t kPanasonicAcCool = 3; // 0b0011 +const uint8_t kPanasonicAcHeat = 4; // 0b0010 +const uint8_t kPanasonicAcFan = 6; // 0b0110 +const uint8_t kPanasonicAcFanMin = 0; +const uint8_t kPanasonicAcFanMax = 4; +const uint8_t kPanasonicAcFanAuto = 7; +const uint8_t kPanasonicAcFanOffset = 3; +const uint8_t kPanasonicAcPower = 1; // 0b1 +const uint8_t kPanasonicAcMinTemp = 16; // Celsius +const uint8_t kPanasonicAcMaxTemp = 30; // Celsius +const uint8_t kPanasonicAcFanModeTemp = 27; // Celsius +const uint8_t kPanasonicAcQuiet = 1; // 0b1 +const uint8_t kPanasonicAcPowerful = 0x20; // 0b100000 +// CKP models have Powerful and Quiet bits swapped. +const uint8_t kPanasonicAcQuietCkp = 0x20; // 0b100000 +const uint8_t kPanasonicAcPowerfulCkp = 1; // 0b1 +const uint8_t kPanasonicAcSwingVAuto = 0xF; +const uint8_t kPanasonicAcSwingVUp = 0x1; +const uint8_t kPanasonicAcSwingVDown = 0x5; +const uint8_t kPanasonicAcSwingHAuto = 0xD; +const uint8_t kPanasonicAcSwingHMiddle = 0x6; +const uint8_t kPanasonicAcSwingHFullLeft = 0x9; +const uint8_t kPanasonicAcSwingHLeft = 0xA; +const uint8_t kPanasonicAcSwingHRight = 0xB; +const uint8_t kPanasonicAcSwingHFullRight = 0xC; +const uint8_t kPanasonicAcChecksumInit = 0xF4; +const uint8_t kPanasonicAcOnTimer = 0b00000010; +const uint8_t kPanasonicAcOffTimer = 0b00000100; +const uint16_t kPanasonicAcTimeMax = 23 * 60 + 59; // Mins since midnight. +const uint16_t kPanasonicAcTimeSpecial = 0x600; + +const uint8_t kPanasonicKnownGoodState[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x0E, 0xE0, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00}; + +enum panasonic_ac_remote_model_t { + kPanasonicUnknown = 0, + kPanasonicLke = 1, + kPanasonicNke = 2, + kPanasonicDke = 3, + kPanasonicJke = 4, + kPanasonicCkp = 5, +}; + +class IRPanasonicAc { + public: + explicit IRPanasonicAc(uint16_t pin); + + void stateReset(); +#if SEND_PANASONIC + void send(); +#endif // SEND_PANASONIC + void begin(); + void on(); + void off(); + void setPower(const bool state); + bool getPower(); + void setTemp(const uint8_t temp, const bool remember = true); + uint8_t getTemp(); + void setFan(const uint8_t fan); + uint8_t getFan(); + void setMode(const uint8_t mode); + uint8_t getMode(); + void setRaw(const uint8_t state[]); + uint8_t *getRaw(); + static bool validChecksum(uint8_t *state, + const uint16_t length = kPanasonicAcStateLength); + static uint8_t calcChecksum(uint8_t *state, + const uint16_t length = kPanasonicAcStateLength); + void setQuiet(const bool state); + bool getQuiet(); + void setPowerful(const bool state); + bool getPowerful(); + void setModel(const panasonic_ac_remote_model_t model); + panasonic_ac_remote_model_t getModel(); + void setSwingVertical(const uint8_t elevation); + uint8_t getSwingVertical(); + void setSwingHorizontal(const uint8_t direction); + uint8_t getSwingHorizontal(); + static uint16_t encodeTime(const uint8_t hours, const uint8_t mins); + uint16_t getClock(); + void setClock(const uint16_t mins_since_midnight); + uint16_t getOnTimer(); + void setOnTimer(const uint16_t mins_since_midnight, const bool enable = true); + void cancelOnTimer(); + bool isOnTimerEnabled(); + uint16_t getOffTimer(); + void setOffTimer(const uint16_t mins_since_midnight, + const bool enable = true); + void cancelOffTimer(); + bool isOffTimerEnabled(); +#ifdef ARDUINO + String toString(); + static String timeToString(const uint16_t mins_since_midnight); +#else + std::string toString(); + static std::string timeToString(const uint16_t mins_since_midnight); +#endif +#ifndef UNIT_TEST + + private: +#endif + uint8_t remote_state[kPanasonicAcStateLength]; + uint8_t _swingh; + uint8_t _temp; + void fixChecksum(const uint16_t length = kPanasonicAcStateLength); + static uint8_t calcChecksum(const uint8_t *state, + const uint16_t length = kPanasonicAcStateLength); + IRsend _irsend; +}; + +#endif // IR_PANASONIC_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Pioneer.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Pioneer.cpp new file mode 100644 index 000000000..9134e3696 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Pioneer.cpp @@ -0,0 +1,143 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017, 2018 David Conran +// Copyright 2018 Kamil Palczewski + +#define __STDC_LIMIT_MACROS +#include +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" +#include "ir_NEC.h" + +// PPPP III OOO N N EEEE EEEE RRRR +// P P I O O NN N E E R R +// PPPP I O O N N N EEE EEE RRRR +// P I O O N NN E E R R +// P III OOO N N EEEE EEEE R RR + +// Ref: +// http://adrian-kingston.com/IRFormatPioneer.htm + +#if SEND_PIONEER +// Send a raw Pioneer formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The number of bits of the message to be sent. +// Typically kPioneerBits. +// repeat: The number of times the command is to be repeated. +// +// Status: BETA / Expected to be working. +// +// Ref: +// http://adrian-kingston.com/IRFormatPioneer.htm +void IRsend::sendPioneer(const uint64_t data, const uint16_t nbits, + const uint16_t repeat) { + // If nbits is to big, or is odd, abort. + if (nbits > sizeof(data) * 8 || nbits % 2 == 1) return; + + // send 1st part of the code + sendNEC(data >> (nbits / 2), nbits / 2, 0); + // send 2nd part of the code + sendNEC(data & (((uint64_t)1 << (nbits / 2)) - 1), nbits / 2, repeat); +} + +// Calculate the raw Pioneer data code based on two NEC sub-codes +// Args: +// address A 16-bit "published" NEC value. +// command: A 16-bit "published" NEC value. +// Returns: +// A raw 64-bit Pioneer message code. +// +// Status: BETA / Expected to work. +// +// Note: +// Address & Command can be take from a decode result OR from the spreadsheets +// located at: +// https://www.pioneerelectronics.com/PUSA/Support/Home-Entertainment-Custom-Install/IR+Codes/A+V+Receivers +// where the first part is considered the address, +// and the second the command. +// e.g. +// "A556+AF20" is an Address of 0xA556 & a Command of 0xAF20. +uint64_t IRsend::encodePioneer(const uint16_t address, const uint16_t command) { + return (((uint64_t)encodeNEC(address >> 8, address & 0xFF)) << 32) | + encodeNEC(command >> 8, command & 0xFF); +} +#endif // SEND_PIONEER + +#if DECODE_PIONEER +// Decode the supplied Pioneer message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kPioneerBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Should be working. (Self decodes & real examples) +// +bool IRrecv::decodePioneer(decode_results *results, const uint16_t nbits, + const bool strict) { + if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1) + return false; // Can't possibly be a valid Pioneer message. + if (strict && nbits != kPioneerBits) + return false; // Not strictly an Pioneer message. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + + for (uint16_t section = 0; section < 2; section++) { + // Header + if (!matchMark(results->rawbuf[offset], kNecHdrMark)) return false; + // Calculate how long the lowest tick time is based on the header mark. + uint32_t mark_tick = + results->rawbuf[offset++] * kRawTick / kNecHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kNecHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t space_tick = + results->rawbuf[offset++] * kRawTick / kNecHdrSpaceTicks; + // + // Data + match_result_t data_result = matchData( + &(results->rawbuf[offset]), nbits / 2, kNecBitMarkTicks * mark_tick, + kNecOneSpaceTicks * space_tick, kNecBitMarkTicks * mark_tick, + kNecZeroSpaceTicks * space_tick); + if (data_result.success == false) return false; + uint8_t command = data_result.data >> 8; + uint8_t command_inverted = data_result.data; + uint8_t address = data_result.data >> 24; + uint8_t address_inverted = data_result.data >> 16; + // Compliance + if (strict) { + if (command != (command_inverted ^ 0xFF)) + return false; // Command integrity failed. + if (address != (address_inverted ^ 0xFF)) + return false; // Address integrity failed. + } + data = (data << (nbits / 2)) + data_result.data; + offset += data_result.used; + // NEC-like commands and addresses are technically in LSB first order so the + // final versions have to be reversed. + uint16_t code = reverseBits((command << 8) + address, 16); + if (section) + results->command = code; + else + results->address = code; + + // Footer + if (!matchMark(results->rawbuf[offset++], kNecBitMarkTicks * mark_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kNecMinGapTicks * space_tick)) + return false; + } + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = PIONEER; + return true; +} +#endif // DECODE_PIONEER diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Pronto.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Pronto.cpp similarity index 81% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Pronto.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Pronto.cpp index ca76f0848..9ab5c76d0 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Pronto.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Pronto.cpp @@ -2,7 +2,6 @@ #include #include "IRsend.h" -#include "IRtimer.h" // PPPPPP tt // PP PP rr rr oooo nn nnn tt oooo @@ -11,12 +10,12 @@ // PP rr oooo nn nn tttt oooo // Constants -#define PRONTO_FREQ_FACTOR 0.241246 -#define PRONTO_TYPE_OFFSET 0U -#define PRONTO_FREQ_OFFSET 1U -#define PRONTO_SEQ_1_LEN_OFFSET 2U -#define PRONTO_SEQ_2_LEN_OFFSET 3U -#define PRONTO_DATA_OFFSET 4U +const float kProntoFreqFactor = 0.241246; +const uint16_t kProntoTypeOffset = 0; +const uint16_t kProntoFreqOffset = 1; +const uint16_t kProntoSeq1LenOffset = 2; +const uint16_t kProntoSeq2LenOffset = 3; +const uint16_t kProntoDataOffset = 4; #if SEND_PRONTO // Send a Pronto Code formatted message. @@ -50,29 +49,29 @@ // 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, // 0x0018, 0x03f6}; // // Send the Pronto(Sony) code. Repeat twice as Sony's require that. -// sendPronto(prontoCode, 46, SONY_MIN_REPEAT); +// sendPronto(prontoCode, 46, kSonyMinRepeat); // // Ref: // http://www.etcwiki.org/wiki/Pronto_Infrared_Format // http://www.remotecentral.com/features/irdisp2.htm void IRsend::sendPronto(uint16_t data[], uint16_t len, uint16_t repeat) { // Check we have enough data to work out what to send. - if (len < PRONTO_MIN_LENGTH) return; + if (len < kProntoMinLength) return; // We only know how to deal with 'raw' pronto codes types. Reject all others. - if (data[PRONTO_TYPE_OFFSET] != 0) return; + if (data[kProntoTypeOffset] != 0) return; // Pronto frequency is in Hz. - uint16_t hz = (uint16_t) (1000000U / (data[PRONTO_FREQ_OFFSET] * - PRONTO_FREQ_FACTOR)); + uint16_t hz = + (uint16_t)(1000000U / (data[kProntoFreqOffset] * kProntoFreqFactor)); enableIROut(hz); // Grab the length of the two sequences. - uint16_t seq_1_len = data[PRONTO_SEQ_1_LEN_OFFSET] * 2; - uint16_t seq_2_len = data[PRONTO_SEQ_2_LEN_OFFSET] * 2; + uint16_t seq_1_len = data[kProntoSeq1LenOffset] * 2; + uint16_t seq_2_len = data[kProntoSeq2LenOffset] * 2; // Calculate where each sequence starts in the buffer. - uint16_t seq_1_start = PRONTO_DATA_OFFSET; - uint16_t seq_2_start = PRONTO_DATA_OFFSET + seq_1_len; + uint16_t seq_1_start = kProntoDataOffset; + uint16_t seq_2_start = kProntoDataOffset + seq_1_len; uint32_t periodic_time = calcUSecPeriod(hz, false); diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_RC5_RC6.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_RC5_RC6.cpp similarity index 70% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_RC5_RC6.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_RC5_RC6.cpp index 65aaf88d7..ef1500d60 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_RC5_RC6.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_RC5_RC6.cpp @@ -21,30 +21,31 @@ // Ref: // https://en.wikipedia.org/wiki/RC-5 // http://www.sbprojects.com/knowledge/ir/rc5.php -#define MIN_RC5_SAMPLES 11U -#define MIN_RC6_SAMPLES 1U -#define RC5_T1 889U -#define RC5_MIN_COMMAND_LENGTH 113778UL -#define RC5_MIN_GAP (RC5_MIN_COMMAND_LENGTH - RC5_RAW_BITS * (2 * RC5_T1)) -#define RC5_TOGGLE_MASK 0x800U // (The 12th bit) + +const uint16_t kRc5T1 = 889; +const uint32_t kRc5MinCommandLength = 113778; +const uint32_t kRc5MinGap = kRc5MinCommandLength - kRC5RawBits * (2 * kRc5T1); +const uint16_t kRc5ToggleMask = 0x800; // The 12th bit. +const uint16_t kRc5SamplesMin = 11; + // RC-6 // Ref: // https://en.wikipedia.org/wiki/RC-6 // http://www.pcbheaven.com/userpages/The_Philips_RC6_Protocol/ -#define RC6_TICK 444U -#define RC6_HDR_MARK_TICKS 6U -#define RC6_HDR_MARK (RC6_HDR_MARK_TICKS * RC6_TICK) -#define RC6_HDR_SPACE_TICKS 2U -#define RC6_HDR_SPACE (RC6_HDR_SPACE_TICKS * RC6_TICK) -#define RC6_RPT_LENGTH_TICKS 187U -#define RC6_RPT_LENGTH (RC6_RPT_LENGTH_TICKS * RC6_TICK) -#define RC6_TOGGLE_MASK 0x10000UL // (The 17th bit) -#define RC6_36_TOGGLE_MASK 0x8000U // (The 16th bit) + +const uint16_t kRc6Tick = 444; +const uint16_t kRc6HdrMarkTicks = 6; +const uint16_t kRc6HdrMark = kRc6HdrMarkTicks * kRc6Tick; +const uint16_t kRc6HdrSpaceTicks = 2; +const uint16_t kRc6HdrSpace = kRc6HdrSpaceTicks * kRc6Tick; +const uint16_t kRc6RptLengthTicks = 187; +const uint32_t kRc6RptLength = kRc6RptLengthTicks * kRc6Tick; +const uint32_t kRc6ToggleMask = 0x10000UL; // The 17th bit. +const uint16_t kRc6_36ToggleMask = 0x8000; // The 16th bit. // Common (getRClevel()) -#define MARK 0U -#define SPACE 1U - +const int16_t kMark = 0; +const int16_t kSpace = 1; #if SEND_RC5 // Send a Philips RC-5/RC-5X packet. @@ -68,14 +69,13 @@ // TODO(anyone): // Testing of the RC-5X components. void IRsend::sendRC5(uint64_t data, uint16_t nbits, uint16_t repeat) { - if (nbits > sizeof(data) * 8) - return; // We can't send something that big. + if (nbits > sizeof(data) * 8) return; // We can't send something that big. bool skipSpace = true; bool field_bit = true; // Set 36kHz IR carrier frequency & a 1/4 (25%) duty cycle. enableIROut(36, 25); - if (nbits >= RC5X_BITS) { // Is this a RC-5X message? + if (nbits >= kRC5XBits) { // Is this a RC-5X message? // field bit is the inverted MSB of RC-5X data. field_bit = ((data >> (nbits - 1)) ^ 1) & 1; nbits--; @@ -90,28 +90,28 @@ void IRsend::sendRC5(uint64_t data, uint16_t nbits, uint16_t repeat) { if (skipSpace) skipSpace = false; // First time through, we assume the leading space(). else - space(RC5_T1); - mark(RC5_T1); + space(kRc5T1); + mark(kRc5T1); // Field/Second start bit. if (field_bit) { // Send a 1. Normal for RC-5. - space(RC5_T1); - mark(RC5_T1); + space(kRc5T1); + mark(kRc5T1); } else { // Send a 0. Special case for RC-5X. Means 7th command bit is 1. - mark(RC5_T1); - space(RC5_T1); + mark(kRc5T1); + space(kRc5T1); } // Data for (uint64_t mask = 1ULL << (nbits - 1); mask; mask >>= 1) if (data & mask) { // 1 - space(RC5_T1); // 1 is space, then mark. - mark(RC5_T1); - } else { // 0 - mark(RC5_T1); // 0 is mark, then space. - space(RC5_T1); + space(kRc5T1); // 1 is space, then mark. + mark(kRc5T1); + } else { // 0 + mark(kRc5T1); // 0 is mark, then space. + space(kRc5T1); } // Footer - space(std::max(RC5_MIN_GAP, RC5_MIN_COMMAND_LENGTH - usecTimer.elapsed())); + space(std::max(kRc5MinGap, kRc5MinCommandLength - usecTimer.elapsed())); } } @@ -132,8 +132,7 @@ void IRsend::sendRC5(uint64_t data, uint16_t nbits, uint16_t repeat) { // https://en.wikipedia.org/wiki/RC-5 uint16_t IRsend::encodeRC5(uint8_t address, uint8_t command, bool key_released) { - return (key_released << (RC5_BITS - 1)) | - ((address & 0x1f) << 6) | + return (key_released << (kRC5Bits - 1)) | ((address & 0x1f) << 6) | (command & 0x3F); } @@ -157,8 +156,8 @@ uint16_t IRsend::encodeRC5X(uint8_t address, uint8_t command, // The 2nd start/field bit (MSB of the return value) is the value of the 7th // command bit. bool s2 = (command >> 6) & 1; - return ((uint16_t) s2 << (RC5X_BITS - 1)) | - encodeRC5(address, command, key_released); + return ((uint16_t)s2 << (kRC5XBits - 1)) | + encodeRC5(address, command, key_released); } // Flip the toggle bit of a Philips RC-5/RC-5X data message. @@ -175,9 +174,7 @@ uint16_t IRsend::encodeRC5X(uint8_t address, uint8_t command, // Ref: // http://www.sbprojects.com/knowledge/ir/rc5.php // https://en.wikipedia.org/wiki/RC-5 -uint64_t IRsend::toggleRC5(uint64_t data) { - return data ^ RC5_TOGGLE_MASK; -} +uint64_t IRsend::toggleRC5(uint64_t data) { return data ^ kRc5ToggleMask; } #endif // SEND_RC5 #if SEND_RC6 @@ -199,9 +196,8 @@ uint64_t IRsend::toggleRC5(uint64_t data) { // http://www.sbprojects.com/knowledge/ir/rc6.php // http://www.righto.com/2010/12/64-bit-rc6-codes-arduino-and-xbox.html uint64_t IRsend::toggleRC6(uint64_t data, uint16_t nbits) { - if (nbits == RC6_36_BITS) - return data ^ RC6_36_TOGGLE_MASK; - return data ^ RC6_TOGGLE_MASK; + if (nbits == kRC6_36Bits) return data ^ kRc6_36ToggleMask; + return data ^ kRc6ToggleMask; } // Encode a Philips RC-6 data message. @@ -221,13 +217,12 @@ uint64_t IRsend::toggleRC6(uint64_t data, uint16_t nbits) { // http://www.sbprojects.com/knowledge/ir/rc6.php // http://www.righto.com/2010/12/64-bit-rc6-codes-arduino-and-xbox.html // http://www.pcbheaven.com/userpages/The_Philips_RC6_Protocol/ -uint64_t IRsend::encodeRC6(uint32_t address, uint8_t command, - uint16_t mode) { +uint64_t IRsend::encodeRC6(uint32_t address, uint8_t command, uint16_t mode) { switch (mode) { - case RC6_MODE0_BITS: + case kRC6Mode0Bits: return ((address & 0xFFF) << 8) | (command & 0xFF); - case RC6_36_BITS: - return ((uint64_t) (address & 0xFFFFFFF) << 8) | (command & 0xFF); + case kRC6_36Bits: + return ((uint64_t)(address & 0xFFFFFFF) << 8) | (command & 0xFF); default: return 0; } @@ -250,25 +245,24 @@ uint64_t IRsend::encodeRC6(uint32_t address, uint8_t command, // https://en.wikipedia.org/wiki/Manchester_code void IRsend::sendRC6(uint64_t data, uint16_t nbits, uint16_t repeat) { // Check we can send the number of bits requested. - if (nbits > sizeof(data) * 8) - return; + if (nbits > sizeof(data) * 8) return; // Set 36kHz IR carrier frequency & a 1/3 (33%) duty cycle. enableIROut(36, 33); for (uint16_t r = 0; r <= repeat; r++) { // Header - mark(RC6_HDR_MARK); - space(RC6_HDR_SPACE); + mark(kRc6HdrMark); + space(kRc6HdrSpace); // Start bit. - mark(RC6_TICK); // mark, then space == 0x1. - space(RC6_TICK); + mark(kRc6Tick); // mark, then space == 0x1. + space(kRc6Tick); // Data uint16_t bitTime; for (uint64_t i = 1, mask = 1ULL << (nbits - 1); mask; i++, mask >>= 1) { if (i == 4) // The fourth bit we send is a "double width trailer bit". - bitTime = 2 * RC6_TICK; // double-wide trailer bit + bitTime = 2 * kRc6Tick; // double-wide trailer bit else - bitTime = RC6_TICK; // Normal bit - if (data & mask) { // 1 + bitTime = kRc6Tick; // Normal bit + if (data & mask) { // 1 mark(bitTime); space(bitTime); } else { // 0 @@ -277,12 +271,12 @@ void IRsend::sendRC6(uint64_t data, uint16_t nbits, uint16_t repeat) { } } // Footer - space(RC6_RPT_LENGTH); + space(kRc6RptLength); } } #endif // SEND_RC6 -#if (DECODE_RC5 || DECODE_RC6) +#if (DECODE_RC5 || DECODE_RC6 || DECODE_LASERTAG) // Gets one undecoded level at a time from the raw buffer. // The RC5/6 decoding is easier if the data is broken into time intervals. // E.g. if the buffer has MARK for 2 time intervals and SPACE for 1, @@ -294,47 +288,65 @@ void IRsend::sendRC6(uint64_t data, uint16_t nbits, uint16_t repeat) { // offset: Ptr to the currect offset to the rawbuf. // used: Ptr to the current used counter. // bitTime: Time interval of single bit in microseconds. +// maxwidth: Maximum number of successive levels to find in a single level +// (default 3) // Returns: // int: MARK, SPACE, or -1 for error (The measured time interval is not a // multiple of t1.) // Ref: // https://en.wikipedia.org/wiki/Manchester_code -int16_t IRrecv::getRClevel(decode_results *results, uint16_t *offset, - uint16_t *used, uint16_t bitTime) { - if (*offset >= results->rawlen) - return SPACE; // After end of recorded buffer, assume SPACE. +int16_t IRrecv::getRClevel(decode_results *results, uint16_t *offset, + uint16_t *used, uint16_t bitTime, uint8_t tolerance, + int16_t excess, uint16_t delta, uint8_t maxwidth) { + DPRINT("DEBUG: getRClevel: offset = "); + DPRINTLN(uint64ToString(*offset)); + DPRINT("DEBUG: getRClevel: rawlen = "); + DPRINTLN(uint64ToString(results->rawlen)); + if (*offset >= results->rawlen) { + DPRINTLN("DEBUG: getRClevel: SPACE, past end of rawbuf"); + return kSpace; // After end of recorded buffer, assume SPACE. + } uint16_t width = results->rawbuf[*offset]; // If the value of offset is odd, it's a MARK. Even, it's a SPACE. - uint16_t val = ((*offset) % 2) ? MARK : SPACE; + uint16_t val = ((*offset) % 2) ? kMark : kSpace; // Check to see if we have hit an inter-message gap (> 20ms). - if (val == SPACE && width > 20000) - return SPACE; - int16_t correction = (val == MARK) ? MARK_EXCESS : -MARK_EXCESS; + if (val == kSpace && + (width > 20000 - delta || width > maxwidth * bitTime + delta)) { + DPRINTLN("DEBUG: getRClevel: SPACE, hit end of mesg gap."); + return kSpace; + } + int16_t correction = (val == kMark) ? excess : -excess; // Calculate the look-ahead for our current position in the buffer. uint16_t avail; // Note: We want to match in greedy order as the other way leads to // mismatches due to overlaps induced by the correction and tolerance // values. - if (match(width, 3 * bitTime + correction)) - avail = 3; - else if (match(width, 2 * bitTime + correction)) - avail = 2; - else if (match(width, bitTime + correction)) - avail = 1; - else + for (avail = maxwidth; avail > 0; avail--) { + if (match(width, avail * bitTime + correction, tolerance, delta)) { + break; + } + } + if (!avail) { + DPRINTLN("DEBUG: getRClevel: Unexpected width. Exiting."); return -1; // The width is not what we expected. + } - (*used)++; // Count another one of the avail slots as used. + (*used)++; // Count another one of the avail slots as used. if (*used >= avail) { // Are we out of look-ahead/avail slots? // Yes, so reset the used counter, and move the offset ahead. *used = 0; (*offset)++; } + if (val == kMark) { + DPRINTLN("DEBUG: getRClevel: MARK"); + } else { + DPRINTLN("DEBUG: getRClevel: SPACE"); + } return val; } -#endif // (DECODE_RC5 || DECODE_RC6) +#endif // (DECODE_RC5 || DECODE_RC6 || DECODE_LASERTAG) #if DECODE_RC5 // Decode the supplied RC-5/RC5X message. @@ -358,28 +370,28 @@ int16_t IRrecv::getRClevel(decode_results *results, uint16_t *offset, // TODO(anyone): // Serious testing of the RC-5X and strict aspects needs to be done. bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < MIN_RC5_SAMPLES + HEADER - 1) return false; + if (results->rawlen < kRc5SamplesMin + kHeader - 1) return false; // Compliance - if (strict && nbits != RC5_BITS && nbits != RC5X_BITS) + if (strict && nbits != kRC5Bits && nbits != kRC5XBits) return false; // It's neither RC-5 or RC-5X. - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; uint16_t used = 0; bool is_rc5x = false; uint64_t data = 0; // Header // Get start bit #1. - if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return false; + if (getRClevel(results, &offset, &used, kRc5T1) != kMark) return false; // Get field/start bit #2 (inverted bit-7 of the command if RC-5X protocol) uint16_t actual_bits = 1; - int16_t levelA = getRClevel(results, &offset, &used, RC5_T1); - int16_t levelB = getRClevel(results, &offset, &used, RC5_T1); - if (levelA == SPACE && levelB == MARK) { // Matched a 1. + int16_t levelA = getRClevel(results, &offset, &used, kRc5T1); + int16_t levelB = getRClevel(results, &offset, &used, kRc5T1); + if (levelA == kSpace && levelB == kMark) { // Matched a 1. is_rc5x = false; - } else if (levelA == MARK && levelB == SPACE) { // Matched a 0. - if (nbits <= RC5_BITS) return false; // Field bit must be '1' for RC5. + } else if (levelA == kMark && levelB == kSpace) { // Matched a 0. + if (nbits <= kRC5Bits) return false; // Field bit must be '1' for RC5. is_rc5x = true; data = 1; } else { @@ -388,11 +400,11 @@ bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { // Data for (; offset < results->rawlen; actual_bits++) { - int16_t levelA = getRClevel(results, &offset, &used, RC5_T1); - int16_t levelB = getRClevel(results, &offset, &used, RC5_T1); - if (levelA == SPACE && levelB == MARK) + int16_t levelA = getRClevel(results, &offset, &used, kRc5T1); + int16_t levelB = getRClevel(results, &offset, &used, kRc5T1); + if (levelA == kSpace && levelB == kMark) data = (data << 1) | 1; // 1 - else if (levelA == MARK && levelB == SPACE) + else if (levelA == kMark && levelB == kSpace) data <<= 1; // 0 else break; @@ -401,8 +413,8 @@ bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { // Compliance if (actual_bits < nbits) return false; // Less data than we expected. - if (strict && actual_bits != RC5_BITS && - actual_bits != RC5X_BITS) return false; + if (strict && actual_bits != kRC5Bits && actual_bits != kRC5XBits) + return false; // Success results->value = data; @@ -411,7 +423,7 @@ bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { results->repeat = false; if (is_rc5x) { results->decode_type = RC5X; - results->command |= ((uint32_t) is_rc5x) << 6; + results->command |= ((uint32_t)is_rc5x) << 6; } else { results->decode_type = RC5; actual_bits--; // RC5 doesn't count the field bit as data. @@ -439,7 +451,7 @@ bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { // TODO(anyone): // Testing of the strict compliance aspects. bool IRrecv::decodeRC6(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < HEADER + 2 + 4) // Up to the double-wide T bit. + if (results->rawlen < kHeader + 2 + 4) // Up to the double-wide T bit. return false; // Smaller than absolute smallest possible RC6 message. if (strict) { // Compliance @@ -449,31 +461,31 @@ bool IRrecv::decodeRC6(decode_results *results, uint16_t nbits, bool strict) { // Also due to potential melding with the start bit, we can only count // the start bit as 1, instead of a more typical 2 value. The header still // remains as normal. - if (results->rawlen < nbits + HEADER + 1) + if (results->rawlen < nbits + kHeader + 1) return false; // Don't have enough entries/samples to be valid. switch (nbits) { - case RC6_MODE0_BITS: - case RC6_36_BITS: + case kRC6Mode0Bits: + case kRC6_36Bits: break; default: return false; // Asking for the wrong number of bits. } } - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; // Header - if (!matchMark(results->rawbuf[offset], RC6_HDR_MARK)) return false; + if (!matchMark(results->rawbuf[offset], kRc6HdrMark)) return false; // Calculate how long the common tick time is based on the header mark. - uint32_t tick = results->rawbuf[offset++] * RAWTICK / RC6_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset++], RC6_HDR_SPACE_TICKS * tick)) + uint32_t tick = results->rawbuf[offset++] * kRawTick / kRc6HdrMarkTicks; + if (!matchSpace(results->rawbuf[offset++], kRc6HdrSpaceTicks * tick)) return false; uint16_t used = 0; // Get the start bit. e.g. 1. - if (getRClevel(results, &offset, &used, tick) != MARK) return false; - if (getRClevel(results, &offset, &used, tick) != SPACE) return false; + if (getRClevel(results, &offset, &used, tick) != kMark) return false; + if (getRClevel(results, &offset, &used, tick) != kSpace) return false; uint16_t actual_bits; uint64_t data = 0; @@ -483,17 +495,15 @@ bool IRrecv::decodeRC6(decode_results *results, uint16_t nbits, bool strict) { int16_t levelA, levelB; // Next two levels levelA = getRClevel(results, &offset, &used, tick); // T bit is double wide; make sure second half matches - if (actual_bits == 3 && - levelA != getRClevel(results, &offset, &used, tick)) + if (actual_bits == 3 && levelA != getRClevel(results, &offset, &used, tick)) return false; levelB = getRClevel(results, &offset, &used, tick); // T bit is double wide; make sure second half matches - if (actual_bits == 3 && - levelB != getRClevel(results, &offset, &used, tick)) + if (actual_bits == 3 && levelB != getRClevel(results, &offset, &used, tick)) return false; - if (levelA == MARK && levelB == SPACE) // reversed compared to RC5 - data = (data << 1) | 1; // 1 - else if (levelA == SPACE && levelB == MARK) + if (levelA == kMark && levelB == kSpace) // reversed compared to RC5 + data = (data << 1) | 1; // 1 + else if (levelA == kSpace && levelB == kMark) data <<= 1; // 0 else break; diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_RCMM.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_RCMM.cpp similarity index 58% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_RCMM.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_RCMM.cpp index 362702b66..1b03d2c07 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_RCMM.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_RCMM.cpp @@ -17,28 +17,28 @@ // Constants // Ref: // http://www.sbprojects.com/knowledge/ir/rcmm.php -#define RCMM_TICK 28U // Technically it would be 27.777* -#define RCMM_HDR_MARK_TICKS 15U -#define RCMM_HDR_MARK 416U -#define RCMM_HDR_SPACE_TICKS 10U -#define RCMM_HDR_SPACE 277U -#define RCMM_BIT_MARK_TICKS 6U -#define RCMM_BIT_MARK 166U -#define RCMM_BIT_SPACE_0_TICKS 10U -#define RCMM_BIT_SPACE_0 277U -#define RCMM_BIT_SPACE_1_TICKS 16U -#define RCMM_BIT_SPACE_1 444U -#define RCMM_BIT_SPACE_2_TICKS 22U -#define RCMM_BIT_SPACE_2 611U -#define RCMM_BIT_SPACE_3_TICKS 28U -#define RCMM_BIT_SPACE_3 777U -#define RCMM_RPT_LENGTH_TICKS 992U -#define RCMM_RPT_LENGTH 27778U -#define RCMM_MIN_GAP_TICKS 120U -#define RCMM_MIN_GAP 3360U +const uint16_t kRcmmTick = 28; // Technically it would be 27.777* +const uint16_t kRcmmHdrMarkTicks = 15; +const uint16_t kRcmmHdrMark = 416; +const uint16_t kRcmmHdrSpaceTicks = 10; +const uint16_t kRcmmHdrSpace = 277; +const uint16_t kRcmmBitMarkTicks = 6; +const uint16_t kRcmmBitMark = 166; +const uint16_t kRcmmBitSpace0Ticks = 10; +const uint16_t kRcmmBitSpace0 = 277; +const uint16_t kRcmmBitSpace1Ticks = 16; +const uint16_t kRcmmBitSpace1 = 444; +const uint16_t kRcmmBitSpace2Ticks = 22; +const uint16_t kRcmmBitSpace2 = 611; +const uint16_t kRcmmBitSpace3Ticks = 28; +const uint16_t kRcmmBitSpace3 = 777; +const uint16_t kRcmmRptLengthTicks = 992; +const uint32_t kRcmmRptLength = 27778; +const uint16_t kRcmmMinGapTicks = 120; +const uint32_t kRcmmMinGap = 3360; // Use a tolerance of +/-10% when matching some data spaces. -#define RCMM_TOLERANCE 10U -#define RCMM_EXCESS 50U +const uint8_t kRcmmTolerance = 10; +const uint16_t kRcmmExcess = 50; #if SEND_RCMM // Send a Philips RC-MM packet. @@ -60,27 +60,35 @@ void IRsend::sendRCMM(uint64_t data, uint16_t nbits, uint16_t repeat) { for (uint16_t r = 0; r <= repeat; r++) { usecs.reset(); // Header - mark(RCMM_HDR_MARK); - space(RCMM_HDR_SPACE); + mark(kRcmmHdrMark); + space(kRcmmHdrSpace); // Data uint64_t mask = 0b11ULL << (nbits - 2); // RC-MM sends data 2 bits at a time. for (int32_t i = nbits; i > 0; i -= 2) { - mark(RCMM_BIT_MARK); + mark(kRcmmBitMark); // Grab the next Most Significant Bits to send. switch ((data & mask) >> (i - 2)) { - case 0b00: space(RCMM_BIT_SPACE_0); break; - case 0b01: space(RCMM_BIT_SPACE_1); break; - case 0b10: space(RCMM_BIT_SPACE_2); break; - case 0b11: space(RCMM_BIT_SPACE_3); break; + case 0b00: + space(kRcmmBitSpace0); + break; + case 0b01: + space(kRcmmBitSpace1); + break; + case 0b10: + space(kRcmmBitSpace2); + break; + case 0b11: + space(kRcmmBitSpace3); + break; } mask >>= 2; } // Footer - mark(RCMM_BIT_MARK); - // Protocol requires us to wait at least RCMM_RPT_LENGTH usecs from the - // start or RCMM_MIN_GAP usecs. - space(std::max(RCMM_RPT_LENGTH - usecs.elapsed(), RCMM_MIN_GAP)); + mark(kRcmmBitMark); + // Protocol requires us to wait at least kRcmmRptLength usecs from the + // start or kRcmmMinGap usecs. + space(std::max(kRcmmRptLength - usecs.elapsed(), kRcmmMinGap)); } } #endif @@ -90,7 +98,7 @@ void IRsend::sendRCMM(uint64_t data, uint16_t nbits, uint16_t repeat) { // Places successful decode information in the results pointer. // Args: // results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. Typically RCMM_BITS. +// nbits: Nr. of bits to expect in the data portion. Typically kRCMMBits. // strict: Flag to indicate if we strictly adhere to the specification. // Returns: // boolean: True if it can decode it, false if it can't. @@ -101,67 +109,65 @@ void IRsend::sendRCMM(uint64_t data, uint16_t nbits, uint16_t repeat) { // http://www.sbprojects.com/knowledge/ir/rcmm.php bool IRrecv::decodeRCMM(decode_results *results, uint16_t nbits, bool strict) { uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; if (results->rawlen <= 4) return false; // Not enough entries to ever be RCMM. // Calc the maximum size in bits, the message can be, or that we can accept. - int16_t maxBitSize = std::min((uint16_t) results->rawlen - 4, - (uint16_t) sizeof(data) * 8); + int16_t maxBitSize = + std::min((uint16_t)results->rawlen - 5, (uint16_t)sizeof(data) * 8); // Compliance if (strict) { // Technically the spec says bit sizes should be 12 xor 24. however // 32 bits has been seen from a device. We are going to assume // 12 <= bits <= 32 is the 'required' bit length for the spec. - if (maxBitSize < 12 || maxBitSize > 32) - return false; + if (maxBitSize < 12 || maxBitSize > 32) return false; if (maxBitSize < nbits) return false; // Short cut, we can never reach the expected nr. of bits. } // Header decode - if (!matchMark(results->rawbuf[offset], RCMM_HDR_MARK)) return false; + if (!matchMark(results->rawbuf[offset], kRcmmHdrMark)) return false; // Calculate how long the common tick time is based on the header mark. - uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / RCMM_HDR_MARK_TICKS; - if (!matchSpace(results->rawbuf[offset], RCMM_HDR_SPACE)) return false; + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kRcmmHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kRcmmHdrSpace)) return false; // Calculate how long the common tick time is based on the header space. - uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / RCMM_HDR_SPACE_TICKS; + uint32_t s_tick = results->rawbuf[offset++] * kRawTick / kRcmmHdrSpaceTicks; // Data decode // RC-MM has two bits of data per mark/space pair. uint16_t actualBits; for (actualBits = 0; actualBits < maxBitSize; actualBits += 2, offset++) { - if (!match(results->rawbuf[offset++], RCMM_BIT_MARK_TICKS * m_tick)) + if (!match(results->rawbuf[offset++], kRcmmBitMarkTicks * m_tick)) return false; data <<= 2; // Use non-default tolerance & excess for matching some of the spaces as the // defaults are too generous and causes mis-matches in some cases. - if (match(results->rawbuf[offset], RCMM_BIT_SPACE_0_TICKS * s_tick, - TOLERANCE)) + if (match(results->rawbuf[offset], kRcmmBitSpace0Ticks * s_tick, + kTolerance)) data += 0; - else if (match(results->rawbuf[offset], RCMM_BIT_SPACE_1_TICKS * s_tick, - TOLERANCE)) + else if (match(results->rawbuf[offset], kRcmmBitSpace1Ticks * s_tick, + kTolerance)) data += 1; - else if (match(results->rawbuf[offset], RCMM_BIT_SPACE_2_TICKS * s_tick, - RCMM_TOLERANCE)) + else if (match(results->rawbuf[offset], kRcmmBitSpace2Ticks * s_tick, + kRcmmTolerance)) data += 2; - else if (match(results->rawbuf[offset], RCMM_BIT_SPACE_3_TICKS * s_tick, - RCMM_TOLERANCE)) + else if (match(results->rawbuf[offset], kRcmmBitSpace3Ticks * s_tick, + kRcmmTolerance)) data += 3; else return false; } // Footer decode - if (!match(results->rawbuf[offset++], RCMM_BIT_MARK_TICKS * m_tick)) + if (!match(results->rawbuf[offset++], kRcmmBitMarkTicks * m_tick)) return false; if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], RCMM_MIN_GAP_TICKS * s_tick)) + !matchAtLeast(results->rawbuf[offset], kRcmmMinGapTicks * s_tick)) return false; // Compliance - if (strict && actualBits != nbits) - return false; + if (strict && actualBits != nbits) return false; // Success results->value = data; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.cpp new file mode 100644 index 000000000..d943f8cf9 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.cpp @@ -0,0 +1,590 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017 David Conran + +#include "ir_Samsung.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// SSSS AAA MMM SSSS U U N N GGGG +// S A A M M M S U U NN N G +// SSS AAAAA M M M SSS U U N N N G GG +// S A A M M S U U N NN G G +// SSSS A A M M SSSS UUU N N GGG + +// Samsung originally added from https://github.com/shirriff/Arduino-IRremote/ + +// Constants +// Ref: +// http://elektrolab.wz.cz/katalog/samsung_protocol.pdf +const uint16_t kSamsungTick = 560; +const uint16_t kSamsungHdrMarkTicks = 8; +const uint16_t kSamsungHdrMark = kSamsungHdrMarkTicks * kSamsungTick; +const uint16_t kSamsungHdrSpaceTicks = 8; +const uint16_t kSamsungHdrSpace = kSamsungHdrSpaceTicks * kSamsungTick; +const uint16_t kSamsungBitMarkTicks = 1; +const uint16_t kSamsungBitMark = kSamsungBitMarkTicks * kSamsungTick; +const uint16_t kSamsungOneSpaceTicks = 3; +const uint16_t kSamsungOneSpace = kSamsungOneSpaceTicks * kSamsungTick; +const uint16_t kSamsungZeroSpaceTicks = 1; +const uint16_t kSamsungZeroSpace = kSamsungZeroSpaceTicks * kSamsungTick; +const uint16_t kSamsungRptSpaceTicks = 4; +const uint16_t kSamsungRptSpace = kSamsungRptSpaceTicks * kSamsungTick; +const uint16_t kSamsungMinMessageLengthTicks = 193; +const uint32_t kSamsungMinMessageLength = + kSamsungMinMessageLengthTicks * kSamsungTick; +const uint16_t kSamsungMinGapTicks = + kSamsungMinMessageLengthTicks - + (kSamsungHdrMarkTicks + kSamsungHdrSpaceTicks + + kSamsungBits * (kSamsungBitMarkTicks + kSamsungOneSpaceTicks) + + kSamsungBitMarkTicks); +const uint32_t kSamsungMinGap = kSamsungMinGapTicks * kSamsungTick; + +const uint16_t kSamsungAcHdrMark = 690; +const uint16_t kSamsungAcHdrSpace = 17844; +const uint8_t kSamsungAcSections = 2; +const uint16_t kSamsungAcSectionMark = 3086; +const uint16_t kSamsungAcSectionSpace = 8864; +const uint16_t kSamsungAcSectionGap = 2886; +const uint16_t kSamsungAcBitMark = 586; +const uint16_t kSamsungAcOneSpace = 1432; +const uint16_t kSamsungAcZeroSpace = 436; + +#if SEND_SAMSUNG +// Send a Samsung formatted message. +// Samsung has a separate message to indicate a repeat, like NEC does. +// TODO(crankyoldgit): Confirm that is actually how Samsung sends a repeat. +// The refdoc doesn't indicate it is true. +// +// Args: +// data: The message to be sent. +// nbits: The bit size of the message being sent. typically kSamsungBits. +// repeat: The number of times the message is to be repeated. +// +// Status: BETA / Should be working. +// +// Ref: http://elektrolab.wz.cz/katalog/samsung_protocol.pdf +void IRsend::sendSAMSUNG(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(kSamsungHdrMark, kSamsungHdrSpace, kSamsungBitMark, + kSamsungOneSpace, kSamsungBitMark, kSamsungZeroSpace, + kSamsungBitMark, kSamsungMinGap, kSamsungMinMessageLength, data, + nbits, 38, true, repeat, 33); +} + +// Construct a raw Samsung message from the supplied customer(address) & +// command. +// +// Args: +// customer: The customer code. (aka. Address) +// command: The command code. +// Returns: +// A raw 32-bit Samsung message suitable for sendSAMSUNG(). +// +// Status: BETA / Should be working. +uint32_t IRsend::encodeSAMSUNG(uint8_t customer, uint8_t command) { + customer = reverseBits(customer, sizeof(customer) * 8); + command = reverseBits(command, sizeof(command) * 8); + return ((command ^ 0xFF) | (command << 8) | (customer << 16) | + (customer << 24)); +} +#endif + +#if DECODE_SAMSUNG +// Decode the supplied Samsung message. +// Samsung messages whilst 32 bits in size, only contain 16 bits of distinct +// data. e.g. In transmition order: +// customer_byte + customer_byte(same) + address_byte + invert(address_byte) +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. Typically kSamsungBits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE +// +// Note: +// LG 32bit protocol appears near identical to the Samsung protocol. +// They differ on their compliance criteria and how they repeat. +// Ref: +// http://elektrolab.wz.cz/katalog/samsung_protocol.pdf +bool IRrecv::decodeSAMSUNG(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid Samsung message. + if (strict && nbits != kSamsungBits) + return false; // We expect Samsung to be 32 bits of message. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + + // Header + if (!matchMark(results->rawbuf[offset], kSamsungHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kSamsungHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kSamsungHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kSamsungHdrSpaceTicks; + // Data + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, + kSamsungBitMarkTicks * m_tick, kSamsungOneSpaceTicks * s_tick, + kSamsungBitMarkTicks * m_tick, kSamsungZeroSpaceTicks * s_tick); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + // Footer + if (!matchMark(results->rawbuf[offset++], kSamsungBitMarkTicks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kSamsungMinGapTicks * s_tick)) + return false; + + // Compliance + + // According to the spec, the customer (address) code is the first 8 + // transmitted bits. It's then repeated. Check for that. + uint8_t address = data >> 24; + if (strict && address != ((data >> 16) & 0xFF)) return false; + // Spec says the command code is the 3rd block of transmitted 8-bits, + // followed by the inverted command code. + uint8_t command = (data & 0xFF00) >> 8; + if (strict && command != ((data & 0xFF) ^ 0xFF)) return false; + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = SAMSUNG; + // command & address need to be reversed as they are transmitted LSB first, + results->command = reverseBits(command, sizeof(command) * 8); + results->address = reverseBits(address, sizeof(address) * 8); + return true; +} +#endif + +#if SEND_SAMSUNG_AC +// Send a Samsung A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kSamsungAcStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: ALPHA / Untested. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/505 +void IRsend::sendSamsungAC(uint8_t data[], uint16_t nbytes, uint16_t repeat) { + if (nbytes < kSamsungAcStateLength && nbytes % kSamsungACSectionLength) + return; // Not an appropriate number of bytes to send a proper message. + + enableIROut(38); + for (uint16_t r = 0; r <= repeat; r++) { + // Header + mark(kSamsungAcHdrMark); + space(kSamsungAcHdrSpace); + // Send in 7 byte sections. + for (uint16_t offset = 0; offset < nbytes; + offset += kSamsungACSectionLength) { + sendGeneric(kSamsungAcSectionMark, kSamsungAcSectionSpace, + kSamsungAcBitMark, kSamsungAcOneSpace, kSamsungAcBitMark, + kSamsungAcZeroSpace, kSamsungAcBitMark, kSamsungAcSectionGap, + data + offset, kSamsungACSectionLength, // 7 bytes == 56 bits + 38000, false, 0, 50); // Send in LSBF order + } + // Complete made up guess at inter-message gap. + space(100000 - kSamsungAcSectionGap); + } +} +#endif // SEND_SAMSUNG_AC + +IRSamsungAc::IRSamsungAc(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRSamsungAc::stateReset() { + for (uint8_t i = 0; i < kSamsungAcExtendedStateLength; i++) + remote_state[i] = 0x0; + remote_state[0] = 0x02; + remote_state[1] = 0x92; + remote_state[2] = 0x0F; + remote_state[6] = 0xF0; + remote_state[7] = 0x01; + remote_state[8] = 0x02; + remote_state[9] = 0xAE; + remote_state[10] = 0x71; + remote_state[12] = 0x15; + remote_state[13] = 0xF0; +} + +void IRSamsungAc::begin() { _irsend.begin(); } + +uint8_t IRSamsungAc::calcChecksum(const uint8_t state[], + const uint16_t length) { + uint8_t sum = 0; + uint8_t currentbyte; + // Safety check so we don't go outside the array. + if (length <= 5) return 255; + // Shamelessly inspired by: + // https://github.com/adafruit/Raw-IR-decoder-for-Arduino/pull/3/files + // Count most of the '1' bits after the checksum location. + for (uint8_t i = length - 5; i < length - 1; i++) { + currentbyte = state[i]; + if (i == length - 5) currentbyte = state[length - 5] & 0b11111110; + for (; currentbyte; currentbyte >>= 1) + if (currentbyte & 1) sum++; + } + return (28 - sum) & 0xF; +} + +bool IRSamsungAc::validChecksum(const uint8_t state[], const uint16_t length) { + if (length <= 5) return true; // No checksum to compare with. Assume okay. + return (state[length - 6] >> 4) == calcChecksum(state, length); +} + +// Update the checksum for the internal state. +void IRSamsungAc::checksum(uint16_t length) { + if (length < 9) return; + remote_state[length - 6] &= 0x0F; + remote_state[length - 6] |= (calcChecksum(remote_state, length) << 4); +} + +#if SEND_SAMSUNG_AC +void IRSamsungAc::send(const bool calcchecksum) { + if (calcchecksum) checksum(); + _irsend.sendSamsungAC(remote_state); +} +#endif // SEND_SAMSUNG_AC + +#if SEND_SAMSUNG_AC +void IRSamsungAc::sendExtended(const bool calcchecksum) { + if (calcchecksum) checksum(); + uint8_t extended_state[kSamsungAcExtendedStateLength] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xD2, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + // Copy/convert the internal state to an extended state. + for (uint16_t i = 0; i < kSamsungACSectionLength; i++) + extended_state[i] = remote_state[i]; + for (uint16_t i = kSamsungACSectionLength; i < kSamsungAcStateLength; i++) + extended_state[i + kSamsungACSectionLength] = remote_state[i]; + // Send it. + _irsend.sendSamsungAC(extended_state, kSamsungAcExtendedStateLength); +} +#endif // SEND_SAMSUNG_AC + +uint8_t *IRSamsungAc::getRaw() { + checksum(); + return remote_state; +} + +void IRSamsungAc::setRaw(const uint8_t new_code[], const uint16_t length) { + for (uint8_t i = 0; i < length && i < kSamsungAcExtendedStateLength; i++) { + remote_state[i] = new_code[i]; + } + // Shrink the extended state into a normal state. + if (length > kSamsungAcStateLength) { + for (uint8_t i = kSamsungAcStateLength; i < length; i++) + remote_state[i - kSamsungACSectionLength] = remote_state[i]; + } +} + +void IRSamsungAc::on() { + remote_state[1] &= ~kSamsungAcPowerMask1; + remote_state[6] |= kSamsungAcPowerMask2; +} + +void IRSamsungAc::off() { + remote_state[1] |= kSamsungAcPowerMask1; + remote_state[6] &= ~kSamsungAcPowerMask2; +} + +void IRSamsungAc::setPower(const bool state) { + if (state) + on(); + else + off(); +} + +bool IRSamsungAc::getPower() { + return ((remote_state[6] & kSamsungAcPowerMask2) != 0) && + ((remote_state[1] & kSamsungAcPowerMask1) == 0); +} + +// Set the temp. in deg C +void IRSamsungAc::setTemp(const uint8_t temp) { + uint8_t newtemp = std::max(kSamsungAcMinTemp, temp); + newtemp = std::min(kSamsungAcMaxTemp, newtemp); + remote_state[11] = (remote_state[11] & ~kSamsungAcTempMask) | + ((newtemp - kSamsungAcMinTemp) << 4); +} + +// Return the set temp. in deg C +uint8_t IRSamsungAc::getTemp() { + return ((remote_state[11] & kSamsungAcTempMask) >> 4) + kSamsungAcMinTemp; +} + +void IRSamsungAc::setMode(const uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + uint8_t newmode = mode; + if (newmode > kSamsungAcHeat) newmode = kSamsungAcAuto; + remote_state[12] = (remote_state[12] & ~kSamsungAcModeMask) | (newmode << 4); + + // Auto mode has a special fan setting valid only in auto mode. + if (newmode == kSamsungAcAuto) { + setFan(kSamsungAcFanAuto2); + } else { + if (getFan() == kSamsungAcFanAuto2) // Non-Auto can't have this fan setting + setFan(kSamsungAcFanAuto); // Default to something safe. + } +} + +uint8_t IRSamsungAc::getMode() { + return (remote_state[12] & kSamsungAcModeMask) >> 4; +} + +void IRSamsungAc::setFan(const uint8_t speed) { + switch (speed) { + case kSamsungAcFanAuto: + case kSamsungAcFanLow: + case kSamsungAcFanMed: + case kSamsungAcFanHigh: + case kSamsungAcFanTurbo: + if (getMode() == kSamsungAcAuto) return; // Not valid in Auto mode. + break; + case kSamsungAcFanAuto2: // Special fan setting for when in Auto mode. + if (getMode() != kSamsungAcAuto) return; + break; + default: + return; + } + remote_state[12] = (remote_state[12] & ~kSamsungAcFanMask) | (speed << 1); +} + +uint8_t IRSamsungAc::getFan() { + return ((remote_state[12] & kSamsungAcFanMask) >> 1); +} + +bool IRSamsungAc::getSwing() { + // TODO(Hollako): Explain why sometimes the LSB of remote_state[9] is a 1. + // e.g. 0xAE or 0XAF for swing move. + return ((remote_state[9] & kSamsungAcSwingMask) >> 4) == kSamsungAcSwingMove; +} + +void IRSamsungAc::setSwing(const bool state) { + // TODO(Hollako): Explain why sometimes the LSB of remote_state[9] is a 1. + // e.g. 0xAE or 0XAF for swing move. + remote_state[9] &= ~kSamsungAcSwingMask; // Clear the previous swing state. + if (state) + remote_state[9] |= (kSamsungAcSwingMove << 4); + else + remote_state[9] |= (kSamsungAcSwingStop << 4); +} + +bool IRSamsungAc::getBeep() { return remote_state[13] & kSamsungAcBeepMask; } + +void IRSamsungAc::setBeep(const bool state) { + if (state) + remote_state[13] |= kSamsungAcBeepMask; + else + remote_state[13] &= ~kSamsungAcBeepMask; +} + +bool IRSamsungAc::getClean() { + return (remote_state[10] & kSamsungAcCleanMask10) && + (remote_state[11] & kSamsungAcCleanMask11); +} + +void IRSamsungAc::setClean(const bool state) { + if (state) { + remote_state[10] |= kSamsungAcCleanMask10; + remote_state[11] |= kSamsungAcCleanMask11; + } else { + remote_state[10] &= ~kSamsungAcCleanMask10; + remote_state[11] &= ~kSamsungAcCleanMask11; + } +} + +// Very unsure this is correct. +bool IRSamsungAc::getQuiet() { + return remote_state[11] & kSamsungAcQuietMask11; +} + +// Very unsure this is correct. +void IRSamsungAc::setQuiet(const bool state) { + if (state) { + remote_state[11] |= kSamsungAcQuietMask11; + setFan(kSamsungAcFanAuto); // Quiet mode seems to set fan speed to auto. + } else { + remote_state[11] &= ~kSamsungAcQuietMask11; + } +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRSamsungAc::toString() { + String result = ""; +#else +std::string IRSamsungAc::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kSamsungAcAuto: + result += " (AUTO)"; + break; + case kSamsungAcCool: + result += " (COOL)"; + break; + case kSamsungAcHeat: + result += " (HEAT)"; + break; + case kSamsungAcDry: + result += " (DRY)"; + break; + case kSamsungAcFan: + result += " (FAN)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kSamsungAcFanAuto: + case kSamsungAcFanAuto2: + result += " (AUTO)"; + break; + case kSamsungAcFanLow: + result += " (LOW)"; + break; + case kSamsungAcFanMed: + result += " (MED)"; + break; + case kSamsungAcFanHigh: + result += " (HIGH)"; + break; + case kSamsungAcFanTurbo: + result += " (TURBO)"; + break; + default: + result += " (UNKNOWN)"; + break; + } + result += ", Swing: "; + if (getSwing()) + result += "On"; + else + result += "Off"; + result += ", Beep: "; + if (getBeep()) + result += "On"; + else + result += "Off"; + result += ", Clean: "; + if (getBeep()) + result += "On"; + else + result += "Off"; + result += ", Quiet: "; + if (getQuiet()) + result += "On"; + else + result += "Off"; + return result; +} + +#if DECODE_SAMSUNG_AC +// Decode the supplied Samsung A/C message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kSamsungAcBits +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Appears to mostly work. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/505 +bool IRrecv::decodeSamsungAC(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + kHeader * 3 + kFooter * 2 - 1) + return false; // Can't possibly be a valid Samsung A/C message. + if (nbits != kSamsungAcBits && nbits != kSamsungAcExtendedBits) return false; + + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + match_result_t data_result; + + // Message Header + if (!matchMark(results->rawbuf[offset++], kSamsungAcBitMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kSamsungAcHdrSpace)) return false; + // Section(s) + for (uint16_t pos = kSamsungACSectionLength, i = 0; pos <= nbits / 8; + pos += kSamsungACSectionLength) { + uint64_t sectiondata = 0; + // Section Header + if (!matchMark(results->rawbuf[offset++], kSamsungAcSectionMark)) + return false; + if (!matchSpace(results->rawbuf[offset++], kSamsungAcSectionSpace)) + return false; + // Section Data + // Keep reading bytes until we either run out of section or state to fill. + for (; offset <= results->rawlen - 16 && i < pos; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData(&(results->rawbuf[offset]), 8, kSamsungAcBitMark, + kSamsungAcOneSpace, kSamsungAcBitMark, + kSamsungAcZeroSpace, kTolerance, 0, false); + if (data_result.success == false) { + DPRINT("DEBUG: offset = "); + DPRINTLN(offset + data_result.used); + return false; // Fail + } + results->state[i] = data_result.data; + sectiondata = (sectiondata << 8) + data_result.data; + } + DPRINTLN("DEBUG: sectiondata = 0x" + uint64ToString(sectiondata, 16)); + // Section Footer + if (!matchMark(results->rawbuf[offset++], kSamsungAcBitMark)) return false; + if (pos < nbits / 8) { // Inter-section gap. + if (!matchSpace(results->rawbuf[offset++], kSamsungAcSectionGap)) + return false; + } else { // Last section / End of message gap. + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kSamsungAcSectionGap)) + return false; + } + } + // Compliance + // Re-check we got the correct size/length due to the way we read the data. + if (dataBitsSoFar != nbits) return false; + // Is the signature correct? + DPRINTLN("DEBUG: Checking signature."); + if (results->state[0] != 0x02 || results->state[2] != 0x0F) return false; + if (results->state[1] != 0x92 && results->state[1] != 0xB2) return false; + if (strict) { + // Is the checksum valid? + if (!IRSamsungAc::validChecksum(results->state, nbits / 8)) { + DPRINTLN("DEBUG: Checksum failed!"); + return false; + } + } + // Success + results->decode_type = SAMSUNG_AC; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_SAMSUNG_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h new file mode 100644 index 000000000..f80b47d20 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h @@ -0,0 +1,107 @@ +// Samsung A/C +// +// Copyright 2018 David Conran + +#ifndef IR_SAMSUNG_H_ +#define IR_SAMSUNG_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// SSSS AAA MMM SSSS U U N N GGGG +// S A A M M M S U U NN N G +// SSS AAAAA M M M SSS U U N N N G GG +// S A A M M S U U N NN G G +// SSSS A A M M SSSS UUU N N GGG + +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/505 + +// Constants +const uint8_t kSamsungAcAuto = 0; +const uint8_t kSamsungAcCool = 1; +const uint8_t kSamsungAcDry = 2; +const uint8_t kSamsungAcFan = 3; +const uint8_t kSamsungAcHeat = 4; +const uint8_t kSamsungAcModeMask = 0x70; +const uint8_t kSamsungAcFanAuto = 0; +const uint8_t kSamsungAcFanLow = 2; +const uint8_t kSamsungAcFanMed = 4; +const uint8_t kSamsungAcFanHigh = 5; +const uint8_t kSamsungAcFanAuto2 = 6; +const uint8_t kSamsungAcFanTurbo = 7; +const uint8_t kSamsungAcMinTemp = 16; // 16C +const uint8_t kSamsungAcMaxTemp = 30; // 30C +const uint8_t kSamsungAcAutoTemp = 25; // 25C +const uint8_t kSamsungAcTempMask = 0xF0; +const uint8_t kSamsungAcPowerMask1 = 0x20; +const uint8_t kSamsungAcPowerMask2 = 0x30; +const uint8_t kSamsungAcFanMask = 0x0E; +const uint8_t kSamsungAcSwingMask = 0x70; +const uint8_t kSamsungAcSwingMove = 0b010; +const uint8_t kSamsungAcSwingStop = 0b111; +const uint8_t kSamsungAcBeepMask = 0x02; +const uint8_t kSamsungAcCleanMask10 = 0x80; +const uint8_t kSamsungAcCleanMask11 = 0x02; +const uint8_t kSamsungAcQuietMask11 = 0x01; + +const uint16_t kSamsungACSectionLength = 7; +const uint64_t kSamsungAcPowerSection = 0x1D20F00000000; + +// Classes +class IRSamsungAc { + public: + explicit IRSamsungAc(uint16_t pin); + + void stateReset(); +#if SEND_SAMSUNG_AC + void send(const bool calcchecksum = true); + void sendExtended(const bool calcchecksum = true); +#endif // SEND_SAMSUNG_AC + void begin(); + void on(); + void off(); + void setPower(const bool state); + bool getPower(); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setFan(const uint8_t speed); + uint8_t getFan(); + void setMode(const uint8_t mode); + uint8_t getMode(); + void setSwing(const bool state); + bool getSwing(); + void setBeep(const bool state); + bool getBeep(); + void setClean(const bool state); + bool getClean(); + void setQuiet(const bool state); + bool getQuiet(); + uint8_t* getRaw(); + void setRaw(const uint8_t new_code[], + const uint16_t length = kSamsungAcStateLength); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kSamsungAcStateLength); + static uint8_t calcChecksum(const uint8_t state[], + const uint16_t length = kSamsungAcStateLength); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif + + private: + // The state of the IR remote in IR code form. + uint8_t remote_state[kSamsungAcExtendedStateLength]; + void checksum(const uint16_t length = kSamsungAcStateLength); + IRsend _irsend; +}; + +#endif // IR_SAMSUNG_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sanyo.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sanyo.cpp similarity index 70% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Sanyo.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Sanyo.cpp index cbb13a329..b2b4d7830 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sanyo.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sanyo.cpp @@ -5,7 +5,6 @@ #include #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" // SSSS AAA N N Y Y OOO // S A A NN N Y Y O O @@ -21,31 +20,35 @@ // Sanyo SA 8650B // Ref: // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Sanyo.cpp -#define SANYO_SA8650B_HDR_MARK 3500U // seen range 3500 -#define SANYO_SA8650B_HDR_SPACE 950U // seen 950 -#define SANYO_SA8650B_ONE_MARK 2400U // seen 2400 -#define SANYO_SA8650B_ZERO_MARK 700U // seen 700 + +const uint16_t kSanyoSa8650bHdrMark = 3500; // seen range 3500 +const uint16_t kSanyoSa8650bHdrSpace = 950; // seen 950 +const uint16_t kSanyoSa8650bOneMark = 2400; // seen 2400 +const uint16_t kSanyoSa8650bZeroMark = 700; // seen 700 // usually see 713 - not using ticks as get number wrapround -#define SANYO_SA8650B_DOUBLE_SPACE_USECS 800U -#define SANYO_SA8650B_RPT_LENGTH 45000U +const uint16_t kSanyoSa8650bDoubleSpaceUsecs = 800; +const uint16_t kSanyoSa8650bRptLength = 45000; // Sanyo LC7461 // Ref: // https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Sanyo.cpp // http://slydiman.narod.ru/scr/kb/sanyo.htm // http://pdf.datasheetcatalog.com/datasheet/sanyo/LC7461.pdf -#define SANYO_LC7461_ADDRESS_MASK ((1 << SANYO_LC7461_ADDRESS_BITS) - 1) -#define SANYO_LC7461_COMMAND_MASK ((1 << SANYO_LC7461_COMMAND_BITS) - 1) -#define SANYO_LC7461_HDR_MARK 9000U -#define SANYO_LC7461_HDR_SPACE 4500U -#define SANYO_LC7461_BIT_MARK 560U // 1T -#define SANYO_LC7461_ONE_SPACE 1690U // 3T -#define SANYO_LC7461_ZERO_SPACE 560U // 1T -#define SANYO_LC7461_MIN_COMMAND_LENGTH 108000UL -#define SANYO_LC7461_MIN_GAP SANYO_LC7461_MIN_COMMAND_LENGTH - \ - (SANYO_LC7461_HDR_MARK + SANYO_LC7461_HDR_SPACE + SANYO_LC7461_BITS * \ - (SANYO_LC7461_BIT_MARK + (SANYO_LC7461_ONE_SPACE + \ - SANYO_LC7461_ZERO_SPACE) / 2) \ - + SANYO_LC7461_BIT_MARK) + +const uint16_t kSanyoLc7461AddressMask = (1 << kSanyoLC7461AddressBits) - 1; +const uint16_t kSanyoLc7461CommandMask = (1 << kSanyoLC7461CommandBits) - 1; +const uint16_t kSanyoLc7461HdrMark = 9000; +const uint16_t kSanyoLc7461HdrSpace = 4500; +const uint16_t kSanyoLc7461BitMark = 560; // 1T +const uint16_t kSanyoLc7461OneSpace = 1690; // 3T +const uint16_t kSanyoLc7461ZeroSpace = 560; // 1T +const uint32_t kSanyoLc7461MinCommandLength = 108000; + +const uint16_t kSanyoLc7461MinGap = + kSanyoLc7461MinCommandLength - + (kSanyoLc7461HdrMark + kSanyoLc7461HdrSpace + + kSanyoLC7461Bits * (kSanyoLc7461BitMark + + (kSanyoLc7461OneSpace + kSanyoLc7461ZeroSpace) / 2) + + kSanyoLc7461BitMark); #if SEND_SANYO // Construct a Sanyo LC7461 message. @@ -62,18 +65,18 @@ // According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon uint64_t IRsend::encodeSanyoLC7461(uint16_t address, uint8_t command) { // Mask our input values to ensure the correct bit sizes. - address &= SANYO_LC7461_ADDRESS_MASK; - command &= SANYO_LC7461_COMMAND_MASK; + address &= kSanyoLc7461AddressMask; + command &= kSanyoLc7461CommandMask; uint64_t data = address; - address ^= SANYO_LC7461_ADDRESS_MASK; // Invert the 13 LSBs. + address ^= kSanyoLc7461AddressMask; // Invert the 13 LSBs. // Append the now inverted address. - data = (data << SANYO_LC7461_ADDRESS_BITS) | address; + data = (data << kSanyoLC7461AddressBits) | address; // Append the command. - data = (data << SANYO_LC7461_COMMAND_BITS) | command; - command ^= SANYO_LC7461_COMMAND_MASK; // Invert the command. + data = (data << kSanyoLC7461CommandBits) | command; + command ^= kSanyoLc7461CommandMask; // Invert the command. // Append the now inverted command. - data = (data << SANYO_LC7461_COMMAND_BITS) | command; + data = (data << kSanyoLC7461CommandBits) | command; return data; } @@ -128,31 +131,30 @@ void IRsend::sendSanyoLC7461(uint64_t data, uint16_t nbits, uint16_t repeat) { // http://pdf.datasheetcatalog.com/datasheet/sanyo/LC7461.pdf bool IRrecv::decodeSanyoLC7461(decode_results *results, uint16_t nbits, bool strict) { - if (strict && nbits != SANYO_LC7461_BITS) + if (strict && nbits != kSanyoLC7461Bits) return false; // Not strictly in spec. // This protocol is basically a 42-bit variant of the NEC protocol. if (!decodeNEC(results, nbits, false)) return false; // Didn't match a NEC format (without strict) // Bits 30 to 42+. - uint16_t address = results->value >> (SANYO_LC7461_BITS - - SANYO_LC7461_ADDRESS_BITS); + uint16_t address = + results->value >> (kSanyoLC7461Bits - kSanyoLC7461AddressBits); // Bits 9 to 16. - uint8_t command = (results->value >> SANYO_LC7461_COMMAND_BITS) & - SANYO_LC7461_COMMAND_MASK; + uint8_t command = + (results->value >> kSanyoLC7461CommandBits) & kSanyoLc7461CommandMask; // Compliance if (strict) { - if (results->bits != nbits) - return false; + if (results->bits != nbits) return false; // Bits 17 to 29. uint16_t inverted_address = - (results->value >> (SANYO_LC7461_COMMAND_BITS * 2)) & - SANYO_LC7461_ADDRESS_MASK; + (results->value >> (kSanyoLC7461CommandBits * 2)) & + kSanyoLc7461AddressMask; // Bits 1-8. - uint8_t inverted_command = results->value & SANYO_LC7461_COMMAND_MASK; - if ((address ^ SANYO_LC7461_ADDRESS_MASK) != inverted_address) + uint8_t inverted_command = results->value & kSanyoLc7461CommandMask; + if ((address ^ kSanyoLc7461AddressMask) != inverted_address) return false; // Address integrity check failed. - if ((command ^ SANYO_LC7461_COMMAND_MASK) != inverted_command) + if ((command ^ kSanyoLc7461CommandMask) != inverted_command) return false; // Command integrity check failed. } @@ -183,9 +185,9 @@ bool IRrecv::decodeSanyoLC7461(decode_results *results, uint16_t nbits, // Ref: // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Sanyo.cpp bool IRrecv::decodeSanyo(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + HEADER - 1) + if (results->rawlen < 2 * nbits + kHeader - 1) return false; // Shorter than shortest possible. - if (strict && nbits != SANYO_SA8650B_BITS) + if (strict && nbits != kSanyoSA8650BBits) return false; // Doesn't match the spec. uint16_t offset = 0; @@ -193,9 +195,9 @@ bool IRrecv::decodeSanyo(decode_results *results, uint16_t nbits, bool strict) { // TODO(crankyoldgit): This repeat code looks like garbage, it should never // match or if it does, it won't be reliable. We should probably just // remove it. - if (results->rawbuf[offset++] < SANYO_SA8650B_DOUBLE_SPACE_USECS) { + if (results->rawbuf[offset++] < kSanyoSa8650bDoubleSpaceUsecs) { results->bits = 0; - results->value = REPEAT; + results->value = kRepeat; results->decode_type = SANYO; results->address = 0; results->command = 0; @@ -204,27 +206,27 @@ bool IRrecv::decodeSanyo(decode_results *results, uint16_t nbits, bool strict) { } // Header - if (!matchMark(results->rawbuf[offset++], SANYO_SA8650B_HDR_MARK)) + if (!matchMark(results->rawbuf[offset++], kSanyoSa8650bHdrMark)) return false; // NOTE: These next two lines look very wrong. Treat as suspect. - if (!matchMark(results->rawbuf[offset++], SANYO_SA8650B_HDR_MARK)) + if (!matchMark(results->rawbuf[offset++], kSanyoSa8650bHdrMark)) return false; // Data uint64_t data = 0; while (offset + 1 < results->rawlen) { - if (!matchSpace(results->rawbuf[offset], SANYO_SA8650B_HDR_SPACE)) + if (!matchSpace(results->rawbuf[offset], kSanyoSa8650bHdrSpace)) break; offset++; - if (matchMark(results->rawbuf[offset], SANYO_SA8650B_ONE_MARK)) + if (matchMark(results->rawbuf[offset], kSanyoSa8650bOneMark)) data = (data << 1) | 1; // 1 - else if (matchMark(results->rawbuf[offset], SANYO_SA8650B_ZERO_MARK)) + else if (matchMark(results->rawbuf[offset], kSanyoSa8650bZeroMark)) data <<= 1; // 0 else return false; offset++; } - if (strict && SANYO_SA8650B_BITS > (offset - 1U) / 2U) + if (strict && kSanyoSA8650BBits > (offset - 1U) / 2U) return false; // Success diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sharp.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sharp.cpp similarity index 68% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Sharp.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Sharp.cpp index 1a0bb3556..ae1b59c74 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sharp.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sharp.cpp @@ -4,7 +4,6 @@ #include #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" #include "IRutils.h" // SSSS H H AAA RRRR PPPP @@ -13,32 +12,37 @@ // S H H A A R R P // SSSS H H A A R R P +// Equipment it seems compatible with: +// * Sharp LC-52D62U +// * +// + // Constants // period time = 1/38000Hz = 26.316 microseconds. // Ref: // GlobalCache's IR Control Tower data. // http://www.sbprojects.com/knowledge/ir/sharp.php -#define SHARP_TICK 26U -#define SHARP_BIT_MARK_TICKS 10U -#define SHARP_BIT_MARK (SHARP_BIT_MARK_TICKS * SHARP_TICK) -#define SHARP_ONE_SPACE_TICKS 70U -#define SHARP_ONE_SPACE (SHARP_ONE_SPACE_TICKS * SHARP_TICK) -#define SHARP_ZERO_SPACE_TICKS 30U -#define SHARP_ZERO_SPACE (SHARP_ZERO_SPACE_TICKS * SHARP_TICK) -#define SHARP_GAP_TICKS 1677U -#define SHARP_GAP (SHARP_GAP_TICKS * SHARP_TICK) - +const uint16_t kSharpTick = 26; +const uint16_t kSharpBitMarkTicks = 10; +const uint16_t kSharpBitMark = kSharpBitMarkTicks * kSharpTick; +const uint16_t kSharpOneSpaceTicks = 70; +const uint16_t kSharpOneSpace = kSharpOneSpaceTicks * kSharpTick; +const uint16_t kSharpZeroSpaceTicks = 30; +const uint16_t kSharpZeroSpace = kSharpZeroSpaceTicks * kSharpTick; +const uint16_t kSharpGapTicks = 1677; +const uint16_t kSharpGap = kSharpGapTicks * kSharpTick; // Address(5) + Command(8) + Expansion(1) + Check(1) -#define SHARP_TOGGLE_MASK ((1 << (SHARP_BITS - SHARP_ADDRESS_BITS)) - 1) -#define SHARP_ADDRESS_MASK ((1 << SHARP_ADDRESS_BITS) - 1) -#define SHARP_COMMAND_MASK ((1 << SHARP_COMMAND_BITS) - 1) +const uint64_t kSharpToggleMask = + ((uint64_t)1 << (kSharpBits - kSharpAddressBits)) - 1; +const uint64_t kSharpAddressMask = ((uint64_t)1 << kSharpAddressBits) - 1; +const uint64_t kSharpCommandMask = ((uint64_t)1 << kSharpCommandBits) - 1; #if (SEND_SHARP || SEND_DENON) // Send a (raw) Sharp message // // Args: // data: Contents of the message to be sent. -// nbits: Nr. of bits of data to be sent. Typically SHARP_BITS. +// nbits: Nr. of bits of data to be sent. Typically kSharpBits. // repeat: Nr. of additional times the message is to be sent. // // Status: BETA / Previously working fine. @@ -56,28 +60,20 @@ // http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf // http://www.hifi-remote.com/johnsfine/DecodeIR.html#Sharp void IRsend::sendSharpRaw(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Set 38kHz IR carrier frequency & a 1/3 (33%) duty cycle. - enableIROut(38, 33); - for (uint16_t i = 0; i <= repeat; i++) { // Protocol demands that the data be sent twice; once normally, // then with all but the address bits inverted. // Note: Previously this used to be performed 3 times (normal, inverted, // normal), however all data points to that being incorrect. for (uint8_t n = 0; n < 2; n++) { - // No Header - - // Data - sendData(SHARP_BIT_MARK, SHARP_ONE_SPACE, - SHARP_BIT_MARK, SHARP_ZERO_SPACE, - data, nbits, true); - // Footer - mark(SHARP_BIT_MARK); - space(SHARP_GAP); - + sendGeneric(0, 0, // No Header + kSharpBitMark, kSharpOneSpace, kSharpBitMark, kSharpZeroSpace, + kSharpBitMark, kSharpGap, data, nbits, 38, true, + 0, // Repeats are handled already. + 33); // Invert the data per protocol. This is always called twice, so it's // retured to original upon exiting the inner loop. - data ^= SHARP_TOGGLE_MASK; + data ^= kSharpToggleMask; } } } @@ -110,17 +106,17 @@ uint32_t IRsend::encodeSharp(uint16_t address, uint16_t command, uint16_t expansion, uint16_t check, bool MSBfirst) { // Mask any unexpected bits. - address &= ((1 << SHARP_ADDRESS_BITS) - 1); - command &= ((1 << SHARP_COMMAND_BITS) - 1); + address &= ((1 << kSharpAddressBits) - 1); + command &= ((1 << kSharpCommandBits) - 1); expansion &= 1; check &= 1; if (!MSBfirst) { // Correct bit order if needed. - address = reverseBits(address, SHARP_ADDRESS_BITS); - command = reverseBits(command, SHARP_COMMAND_BITS); + address = reverseBits(address, kSharpAddressBits); + command = reverseBits(command, kSharpCommandBits); } // Concatinate all the bits. - return (address << (SHARP_COMMAND_BITS + 2)) | (command << 2) | + return (address << (kSharpCommandBits + 2)) | (command << 2) | (expansion << 1) | check; } @@ -129,7 +125,7 @@ uint32_t IRsend::encodeSharp(uint16_t address, uint16_t command, // Args: // address: Address value to be sent. // command: Command value to be sent. -// nbits: Nr. of bits of data to be sent. Typically SHARP_BITS. +// nbits: Nr. of bits of data to be sent. Typically kSharpBits. // repeat: Nr. of additional times the message is to be sent. // // Status: DEPRICATED / Previously working fine. @@ -159,13 +155,13 @@ void IRsend::sendSharp(uint16_t address, uint16_t command, uint16_t nbits, // // Args: // results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of data bits to expect. Typically SHARP_BITS. +// nbits: Nr. of data bits to expect. Typically kSharpBits. // strict: Flag indicating if we should perform strict matching. // expansion: Should we expect the expansion bit to be set. Default is true. // Returns: // boolean: True if it can decode it, false if it can't. // -// Status: BETA / Should work okay. +// Status: STABLE / Working fine. // // Note: // This procedure returns a value suitable for use in sendSharpRaw(). @@ -178,90 +174,83 @@ void IRsend::sendSharp(uint16_t address, uint16_t command, uint16_t nbits, // http://www.hifi-remote.com/johnsfine/DecodeIR.html#Sharp bool IRrecv::decodeSharp(decode_results *results, uint16_t nbits, bool strict, bool expansion) { - if (results->rawlen < 2 * nbits + FOOTER - 1) + if (results->rawlen < 2 * nbits + kFooter - 1) return false; // Not enough entries to be a Sharp message. // Compliance if (strict) { - if (nbits != SHARP_BITS) - return false; // Request is out of spec. + if (nbits != kSharpBits) return false; // Request is out of spec. // DISABLED - See TODO #ifdef UNIT_TEST // An in spec message has the data sent normally, then inverted. So we // expect twice as many entries than to just get the results. - if (results->rawlen < 2 * (2 * nbits + FOOTER)) - return false; + if (results->rawlen < 2 * (2 * nbits + kFooter)) return false; #endif } uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; // No header // But try to auto-calibrate off the initial mark signal. - if (!matchMark(results->rawbuf[offset], SHARP_BIT_MARK, 35)) return false; + if (!matchMark(results->rawbuf[offset], kSharpBitMark, 35)) return false; // Calculate how long the common tick time is based on the header mark. - uint32_t tick = results->rawbuf[offset] * RAWTICK / SHARP_BIT_MARK_TICKS; + uint32_t tick = results->rawbuf[offset] * kRawTick / kSharpBitMarkTicks; // Data for (uint16_t i = 0; i < nbits; i++, offset++) { - // Use a higher tolerance value for SHARP_BIT_MARK as it is quite small. - if (!matchMark(results->rawbuf[offset++], SHARP_BIT_MARK_TICKS * tick, 35)) + // Use a higher tolerance value for kSharpBitMark as it is quite small. + if (!matchMark(results->rawbuf[offset++], kSharpBitMarkTicks * tick, 35)) return false; - if (matchSpace(results->rawbuf[offset], SHARP_ONE_SPACE_TICKS * tick)) + if (matchSpace(results->rawbuf[offset], kSharpOneSpaceTicks * tick)) data = (data << 1) | 1; // 1 - else if (matchSpace(results->rawbuf[offset], SHARP_ZERO_SPACE_TICKS * tick)) + else if (matchSpace(results->rawbuf[offset], kSharpZeroSpaceTicks * tick)) data <<= 1; // 0 else return false; } // Footer - if (!match(results->rawbuf[offset++], SHARP_BIT_MARK_TICKS * tick)) + if (!match(results->rawbuf[offset++], kSharpBitMarkTicks * tick)) return false; if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], SHARP_GAP_TICKS * tick)) + !matchAtLeast(results->rawbuf[offset], kSharpGapTicks * tick)) return false; // Compliance if (strict) { // Check the state of the expansion bit is what we expect. - if ((data & 0b10) >> 1 != expansion) - return false; + if ((data & 0b10) >> 1 != expansion) return false; // The check bit should be cleared in a normal message. - if (data & 0b1) - return false; - // DISABLED - See TODO + if (data & 0b1) return false; + // DISABLED - See TODO #ifdef UNIT_TEST // Grab the second copy of the data (i.e. inverted) // Header // i.e. The inter-data/command repeat gap. - if (!matchSpace(results->rawbuf[offset++], SHARP_GAP_TICKS * tick)) + if (!matchSpace(results->rawbuf[offset++], kSharpGapTicks * tick)) return false; // Data uint64_t second_data = 0; for (uint16_t i = 0; i < nbits; i++, offset++) { - // Use a higher tolerance value for SHARP_BIT_MARK as it is quite small. - if (!matchMark(results->rawbuf[offset++], SHARP_BIT_MARK_TICKS * tick, - 35)) + // Use a higher tolerance value for kSharpBitMark as it is quite small. + if (!matchMark(results->rawbuf[offset++], kSharpBitMarkTicks * tick, 35)) return false; - if (matchSpace(results->rawbuf[offset], SHARP_ONE_SPACE_TICKS * tick)) + if (matchSpace(results->rawbuf[offset], kSharpOneSpaceTicks * tick)) second_data = (second_data << 1) | 1; // 1 - else if (matchSpace(results->rawbuf[offset], - SHARP_ZERO_SPACE_TICKS * tick)) + else if (matchSpace(results->rawbuf[offset], kSharpZeroSpaceTicks * tick)) second_data <<= 1; // 0 else return false; } // Footer - if (!match(results->rawbuf[offset++], SHARP_BIT_MARK_TICKS * tick)) + if (!match(results->rawbuf[offset++], kSharpBitMarkTicks * tick)) return false; if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], SHARP_GAP_TICKS * tick)) + !matchAtLeast(results->rawbuf[offset], kSharpGapTicks * tick)) return false; // Check that second_data has been inverted correctly. - if (data != (second_data ^ SHARP_TOGGLE_MASK)) - return false; + if (data != (second_data ^ kSharpToggleMask)) return false; #endif // UNIT_TEST } @@ -270,9 +259,9 @@ bool IRrecv::decodeSharp(decode_results *results, uint16_t nbits, bool strict, results->bits = nbits; results->value = data; // Address & command are actually transmitted in LSB first order. - results->address = reverseBits(data, nbits) & SHARP_ADDRESS_MASK; - results->command = reverseBits((data >> 2) & SHARP_COMMAND_MASK, - SHARP_COMMAND_BITS); + results->address = reverseBits(data, nbits) & kSharpAddressMask; + results->command = + reverseBits((data >> 2) & kSharpCommandMask, kSharpCommandBits); return true; } #endif // (DECODE_SHARP || DECODE_DENON) diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sherwood.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sherwood.cpp similarity index 71% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Sherwood.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Sherwood.cpp index 97e75067a..8af7dfb34 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sherwood.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sherwood.cpp @@ -14,16 +14,15 @@ // // Args: // data: The contents of the command you want to send. -// nbits: The bit size of the command being sent. (SHERWOOD_BITS) +// nbits: The bit size of the command being sent. (kSherwoodBits) // repeat: The nr. of times you want the command to be repeated. (Default: 1) // // Status: STABLE / Known working. // // Note: // Sherwood remote codes appear to be NEC codes with a manditory repeat code. -// i.e. repeat should be >= SHERWOOD_MIN_REPEAT (1). -void IRsend::sendSherwood(uint64_t data, uint16_t nbits, - uint16_t repeat) { - sendNEC(data, nbits, std::max((uint16_t) SHERWOOD_MIN_REPEAT, repeat)); +// i.e. repeat should be >= kSherwoodMinRepeat (1). +void IRsend::sendSherwood(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendNEC(data, nbits, std::max((uint16_t)kSherwoodMinRepeat, repeat)); } #endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sony.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sony.cpp similarity index 62% rename from lib/IRremoteESP8266-2.2.1.02/src/ir_Sony.cpp rename to lib/IRremoteESP8266-2.5.2.03/src/ir_Sony.cpp index fd2652d1d..efa6e6a46 100644 --- a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sony.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Sony.cpp @@ -5,7 +5,6 @@ #include #include "IRrecv.h" #include "IRsend.h" -#include "IRtimer.h" #include "IRutils.h" // SSSS OOO N N Y Y @@ -20,19 +19,19 @@ // Constants // Ref: // http://www.sbprojects.com/knowledge/ir/sirc.php -#define SONY_TICK 200U -#define SONY_HDR_MARK_TICKS 12U -#define SONY_HDR_MARK (SONY_HDR_MARK_TICKS * SONY_TICK) -#define SONY_SPACE_TICKS 3U -#define SONY_SPACE (SONY_SPACE_TICKS * SONY_TICK) -#define SONY_ONE_MARK_TICKS 6U -#define SONY_ONE_MARK (SONY_ONE_MARK_TICKS * SONY_TICK) -#define SONY_ZERO_MARK_TICKS 3U -#define SONY_ZERO_MARK (SONY_ZERO_MARK_TICKS * SONY_TICK) -#define SONY_RPT_LENGTH_TICKS 225U -#define SONY_RPT_LENGTH (SONY_RPT_LENGTH_TICKS * SONY_TICK) -#define SONY_MIN_GAP_TICKS 50U -#define SONY_MIN_GAP (SONY_MIN_GAP_TICKS * SONY_TICK) +const uint16_t kSonyTick = 200; +const uint16_t kSonyHdrMarkTicks = 12; +const uint16_t kSonyHdrMark = kSonyHdrMarkTicks * kSonyTick; +const uint16_t kSonySpaceTicks = 3; +const uint16_t kSonySpace = kSonySpaceTicks * kSonyTick; +const uint16_t kSonyOneMarkTicks = 6; +const uint16_t kSonyOneMark = kSonyOneMarkTicks * kSonyTick; +const uint16_t kSonyZeroMarkTicks = 3; +const uint16_t kSonyZeroMark = kSonyZeroMarkTicks * kSonyTick; +const uint16_t kSonyRptLengthTicks = 225; +const uint16_t kSonyRptLength = kSonyRptLengthTicks * kSonyTick; +const uint16_t kSonyMinGapTicks = 50; +const uint16_t kSonyMinGap = kSonyMinGapTicks * kSonyTick; #if SEND_SONY // Send a Sony/SIRC(Serial Infra-Red Control) message. @@ -51,24 +50,10 @@ // Ref: // http://www.sbprojects.com/knowledge/ir/sirc.php void IRsend::sendSony(uint64_t data, uint16_t nbits, uint16_t repeat) { - // Sony devices use a 40kHz IR carrier frequency & a 1/3 (33%) duty cycle. - enableIROut(40, 33); - IRtimer usecs = IRtimer(); - - for (uint16_t i = 0; i <= repeat; i++) { // Typically loop 3 or more times. - usecs.reset(); - // Header - mark(SONY_HDR_MARK); - space(SONY_SPACE); - // Data - sendData(SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, - data, nbits, true); - // Footer - // The Sony protocol requires us to wait 45ms from start of a code to the - // start of the next one. A 10ms minimum gap is also required. - space(std::max(SONY_MIN_GAP, SONY_RPT_LENGTH - usecs.elapsed())); - } - // A space() is always performed last, so no need to turn off the LED. + sendGeneric(kSonyHdrMark, kSonySpace, kSonyOneMark, kSonySpace, kSonyZeroMark, + kSonySpace, + 0, // No Footer mark. + kSonyMinGap, kSonyRptLength, data, nbits, 40, true, repeat, 33); } // Convert Sony/SIRC command, address, & extended bits into sendSony format. @@ -81,8 +66,8 @@ void IRsend::sendSony(uint64_t data, uint16_t nbits, uint16_t repeat) { // A sendSony compatible data message. // // Status: BETA / Should be working. -uint32_t IRsend::encodeSony(uint16_t nbits, uint16_t command, - uint16_t address, uint16_t extended) { +uint32_t IRsend::encodeSony(uint16_t nbits, uint16_t command, uint16_t address, + uint16_t extended) { uint32_t result = 0; switch (nbits) { case 12: // 5 address bits. @@ -120,7 +105,7 @@ uint32_t IRsend::encodeSony(uint16_t nbits, uint16_t command, // Ref: // http://www.sbprojects.com/knowledge/ir/sirc.php bool IRrecv::decodeSony(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + HEADER - 1) + if (results->rawlen < 2 * nbits + kHeader - 1) return false; // Message is smaller than we expected. // Compliance @@ -136,31 +121,30 @@ bool IRrecv::decodeSony(decode_results *results, uint16_t nbits, bool strict) { } uint64_t data = 0; - uint16_t offset = OFFSET_START; + uint16_t offset = kStartOffset; uint16_t actualBits; uint32_t timeSoFar = 0; // Time in uSecs of the message length. // Header - timeSoFar += results->rawbuf[offset] * RAWTICK; - if (!matchMark(results->rawbuf[offset], SONY_HDR_MARK)) - return false; + timeSoFar += results->rawbuf[offset] * kRawTick; + if (!matchMark(results->rawbuf[offset], kSonyHdrMark)) return false; // Calculate how long the common tick time is based on the header mark. - uint32_t tick = results->rawbuf[offset++] * RAWTICK / SONY_HDR_MARK_TICKS; + uint32_t tick = results->rawbuf[offset++] * kRawTick / kSonyHdrMarkTicks; // Data for (actualBits = 0; offset < results->rawlen - 1; actualBits++, offset++) { - // The gap after a Sony packet for a repeat should be SONY_MIN_GAP or - // (SONY_RPT_LENGTH - timeSoFar) according to the spec. - if (matchSpace(results->rawbuf[offset], SONY_MIN_GAP_TICKS * tick) || - matchAtLeast(results->rawbuf[offset], SONY_RPT_LENGTH - timeSoFar)) + // The gap after a Sony packet for a repeat should be kSonyMinGap or + // (kSonyRptLength - timeSoFar) according to the spec. + if (matchSpace(results->rawbuf[offset], kSonyMinGapTicks * tick) || + matchAtLeast(results->rawbuf[offset], kSonyRptLength - timeSoFar)) break; // Found a repeat space. - timeSoFar += results->rawbuf[offset] * RAWTICK; - if (!matchSpace(results->rawbuf[offset++], SONY_SPACE_TICKS * tick)) + timeSoFar += results->rawbuf[offset] * kRawTick; + if (!matchSpace(results->rawbuf[offset++], kSonySpaceTicks * tick)) return false; - timeSoFar += results->rawbuf[offset] * RAWTICK; - if (matchMark(results->rawbuf[offset], SONY_ONE_MARK_TICKS * tick)) + timeSoFar += results->rawbuf[offset] * kRawTick; + if (matchMark(results->rawbuf[offset], kSonyOneMarkTicks * tick)) data = (data << 1) | 1; - else if (matchMark(results->rawbuf[offset], SONY_ZERO_MARK_TICKS * tick)) + else if (matchMark(results->rawbuf[offset], kSonyZeroMarkTicks * tick)) data <<= 1; else return false; @@ -179,14 +163,14 @@ bool IRrecv::decodeSony(decode_results *results, uint16_t nbits, bool strict) { data = reverseBits(data, actualBits); // Decode the address & command from raw decode value. switch (actualBits) { - case 12: // 7 command bits, 5 address bits. - case 15: // 7 command bits, 8 address bits. + case 12: // 7 command bits, 5 address bits. + case 15: // 7 command bits, 8 address bits. results->command = data & 0x7F; // Bits 0-6 - results->address = data >> 7; // Bits 7-14 + results->address = data >> 7; // Bits 7-14 break; case 20: // 7 command bits, 5 address bits, 8 extended (command) bits. results->command = (data & 0x7F) + ((data >> 12) << 7); // Bits 0-6,12-19 - results->address = (data >> 7) & 0x1F; // Bits 7-11 + results->address = (data >> 7) & 0x1F; // Bits 7-11 break; default: // Shouldn't happen, but just in case. results->address = 0; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.cpp new file mode 100644 index 000000000..817b5fbaa --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.cpp @@ -0,0 +1,340 @@ +// Copyright 2017 David Conran + +#include "ir_Toshiba.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// TTTTTTT OOOOO SSSSS HH HH IIIII BBBBB AAA +// TTT OO OO SS HH HH III BB B AAAAA +// TTT OO OO SSSSS HHHHHHH III BBBBBB AA AA +// TTT OO OO SS HH HH III BB BB AAAAAAA +// TTT OOOO0 SSSSS HH HH IIIII BBBBBB AA AA + +// Toshiba A/C support added by David Conran +// +// Equipment it seems compatible with: +// * Toshiba RAS-B13N3KV2 / Akita EVO II +// * Toshiba RAS-B13N3KVP-E, RAS 18SKP-ES +// * Toshiba WH-TA04NE, WC-L03SE +// * + +// Constants + +// Toshiba A/C +// Ref: +// https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266T.ino#L77 +const uint16_t kToshibaAcHdrMark = 4400; +const uint16_t kToshibaAcHdrSpace = 4300; +const uint16_t kToshibaAcBitMark = 543; +const uint16_t kToshibaAcOneSpace = 1623; +const uint16_t kToshibaAcZeroSpace = 472; +const uint16_t kToshibaAcMinGap = 7048; + +#if SEND_TOSHIBA_AC +// Send a Toshiba A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kToshibaACStateLength) +// repeat: Nr. of times the message is to be repeated. +// (Default = kToshibaACMinRepeat). +// +// Status: StABLE / Working. +// +void IRsend::sendToshibaAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kToshibaACStateLength) + return; // Not enough bytes to send a proper message. + sendGeneric(kToshibaAcHdrMark, kToshibaAcHdrSpace, kToshibaAcBitMark, + kToshibaAcOneSpace, kToshibaAcBitMark, kToshibaAcZeroSpace, + kToshibaAcBitMark, kToshibaAcMinGap, data, nbytes, 38, true, + repeat, 50); +} +#endif // SEND_TOSHIBA_AC + +// Code to emulate Toshiba A/C IR remote control unit. +// Inspired and derived from the work done at: +// https://github.com/r45635/HVAC-IR-Control +// +// Status: STABLE / Working. +// +// Initialise the object. +IRToshibaAC::IRToshibaAC(uint16_t pin) : _irsend(pin) { stateReset(); } + +// Reset the state of the remote to a known good state/sequence. +void IRToshibaAC::stateReset() { + // The state of the IR remote in IR code form. + // Known good state obtained from: + // https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266T.ino#L103 + // Note: Can't use the following because it requires -std=c++11 + // uint8_t remote_state[kToshibaACStateLength] = { + // 0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00 }; + remote_state[0] = 0xF2; + remote_state[1] = 0x0D; + remote_state[2] = 0x03; + remote_state[3] = 0xFC; + remote_state[4] = 0x01; + for (uint8_t i = 5; i < kToshibaACStateLength; i++) remote_state[i] = 0; + mode_state = remote_state[6] & 0b00000011; + checksum(); // Calculate the checksum +} + +// Configure the pin for output. +void IRToshibaAC::begin() { _irsend.begin(); } + +#if SEND_TOSHIBA_AC +// Send the current desired state to the IR LED. +void IRToshibaAC::send() { + checksum(); // Ensure correct checksum before sending. + _irsend.sendToshibaAC(remote_state); +} +#endif // SEND_TOSHIBA_AC + +// Return a pointer to the internal state date of the remote. +uint8_t* IRToshibaAC::getRaw() { + checksum(); + return remote_state; +} + +// Override the internal state with the new state. +void IRToshibaAC::setRaw(uint8_t newState[]) { + for (uint8_t i = 0; i < kToshibaACStateLength; i++) { + remote_state[i] = newState[i]; + } + mode_state = getMode(true); +} + +// Calculate the checksum for a given array. +// Args: +// state: The array to calculate the checksum over. +// length: The size of the array. +// Returns: +// The 8 bit checksum value. +uint8_t IRToshibaAC::calcChecksum(const uint8_t state[], + const uint16_t length) { + uint8_t checksum = 0; + // Only calculate it for valid lengths. + if (length > 1) { + // Checksum is simple XOR of all bytes except the last one. + for (uint8_t i = 0; i < length - 1; i++) checksum ^= state[i]; + } + return checksum; +} + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRToshibaAC::validChecksum(const uint8_t state[], const uint16_t length) { + return (length > 1 && state[length - 1] == calcChecksum(state, length)); +} + +// Calculate & set the checksum for the current internal state of the remote. +void IRToshibaAC::checksum(const uint16_t length) { + // Stored the checksum value in the last byte. + if (length > 1) remote_state[length - 1] = calcChecksum(remote_state, length); +} + +// Set the requested power state of the A/C to off. +void IRToshibaAC::on() { + // state = ON; + remote_state[6] &= ~kToshibaAcPower; + setMode(mode_state); +} + +// Set the requested power state of the A/C to off. +void IRToshibaAC::off() { + // state = OFF; + remote_state[6] |= (kToshibaAcPower | 0b00000011); +} + +// Set the requested power state of the A/C. +void IRToshibaAC::setPower(bool state) { + if (state) + on(); + else + off(); +} + +// Return the requested power state of the A/C. +bool IRToshibaAC::getPower() { + return ((remote_state[6] & kToshibaAcPower) == 0); +} + +// Set the temp. in deg C +void IRToshibaAC::setTemp(uint8_t temp) { + temp = std::max((uint8_t)kToshibaAcMinTemp, temp); + temp = std::min((uint8_t)kToshibaAcMaxTemp, temp); + remote_state[5] = (temp - kToshibaAcMinTemp) << 4; +} + +// Return the set temp. in deg C +uint8_t IRToshibaAC::getTemp() { + return ((remote_state[5] >> 4) + kToshibaAcMinTemp); +} + +// Set the speed of the fan, 0-5. +// 0 is auto, 1-5 is the speed, 5 is Max. +void IRToshibaAC::setFan(uint8_t fan) { + // Bounds check + if (fan > kToshibaAcFanMax) + fan = kToshibaAcFanMax; // Set the fan to maximum if out of range. + if (fan > kToshibaAcFanAuto) fan++; + remote_state[6] &= 0b00011111; // Clear the previous fan state + remote_state[6] |= (fan << 5); +} + +// Return the requested state of the unit's fan. +uint8_t IRToshibaAC::getFan() { + uint8_t fan = remote_state[6] >> 5; + if (fan == kToshibaAcFanAuto) return kToshibaAcFanAuto; + return --fan; +} + +// Get the requested climate operation mode of the a/c unit. +// Args: +// useRaw: Indicate to get the mode from the state array. (Default: false) +// Returns: +// A uint8_t containing the A/C mode. +uint8_t IRToshibaAC::getMode(bool useRaw) { + if (useRaw) + return (remote_state[6] & 0b00000011); + else + return mode_state; +} + +// Set the requested climate operation mode of the a/c unit. +void IRToshibaAC::setMode(uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + switch (mode) { + case kToshibaAcAuto: + break; + case kToshibaAcCool: + break; + case kToshibaAcDry: + break; + case kToshibaAcHeat: + break; + default: + mode = kToshibaAcAuto; + } + mode_state = mode; + // Only adjust the remote_state if we have power set to on. + if (getPower()) { + remote_state[6] &= 0b11111100; // Clear the previous mode. + remote_state[6] |= mode_state; + } +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRToshibaAC::toString() { + String result = ""; +#else +std::string IRToshibaAC::toString() { + std::string result = ""; +#endif // ARDUINO + result += "Power: "; + if (getPower()) + result += "On"; + else + result += "Off"; + result += ", Mode: " + uint64ToString(getMode()); + switch (getMode()) { + case kToshibaAcAuto: + result += " (AUTO)"; + break; + case kToshibaAcCool: + result += " (COOL)"; + break; + case kToshibaAcHeat: + result += " (HEAT)"; + break; + case kToshibaAcDry: + result += " (DRY)"; + break; + default: + result += " (UNKNOWN)"; + } + result += ", Temp: " + uint64ToString(getTemp()) + "C"; + result += ", Fan: " + uint64ToString(getFan()); + switch (getFan()) { + case kToshibaAcFanAuto: + result += " (AUTO)"; + break; + case kToshibaAcFanMax: + result += " (MAX)"; + break; + } + return result; +} + +#if DECODE_TOSHIBA_AC +// Decode a Toshiba AC IR message if possible. +// Places successful decode information in the results pointer. +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kToshibaACBits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE / Working. +// +// Ref: +// +bool IRrecv::decodeToshibaAC(decode_results* results, uint16_t nbits, + bool strict) { + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + + // Have we got enough data to successfully decode? + if (results->rawlen < kToshibaACBits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid message. + + // Compliance + if (strict && nbits != kToshibaACBits) + return false; // Must be called with the correct nr. of bytes. + + // Header + if (!matchMark(results->rawbuf[offset++], kToshibaAcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kToshibaAcHdrSpace)) return false; + + // Data + for (uint8_t i = 0; i < kToshibaACStateLength; i++) { + // Read a byte's worth of data. + match_result_t data_result = + matchData(&(results->rawbuf[offset]), 8, kToshibaAcBitMark, + kToshibaAcOneSpace, kToshibaAcBitMark, kToshibaAcZeroSpace); + if (data_result.success == false) return false; // Fail + dataBitsSoFar += 8; + results->state[i] = (uint8_t)data_result.data; + offset += data_result.used; + } + + // Footer + if (!matchMark(results->rawbuf[offset++], kToshibaAcBitMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kToshibaAcMinGap)) return false; + + // Compliance + if (strict) { + // Check that the checksum of the message is correct. + if (!IRToshibaAC::validChecksum(results->state)) return false; + } + + // Success + results->decode_type = TOSHIBA_AC; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_TOSHIBA_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h new file mode 100644 index 000000000..1a1e6cdc8 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h @@ -0,0 +1,85 @@ +// Copyright 2017 David Conran +#ifndef IR_TOSHIBA_H_ +#define IR_TOSHIBA_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifdef ARDUINO +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// TTTTTTT OOOOO SSSSS HH HH IIIII BBBBB AAA +// TTT OO OO SS HH HH III BB B AAAAA +// TTT OO OO SSSSS HHHHHHH III BBBBBB AA AA +// TTT OO OO SS HH HH III BB BB AAAAAAA +// TTT OOOO0 SSSSS HH HH IIIII BBBBBB AA AA + +// Toshiba A/C support added by David Conran + +// Constants +const uint8_t kToshibaAcAuto = 0; +const uint8_t kToshibaAcCool = 1; +const uint8_t kToshibaAcDry = 2; +const uint8_t kToshibaAcHeat = 3; +const uint8_t kToshibaAcPower = 4; +const uint8_t kToshibaAcFanAuto = 0; +const uint8_t kToshibaAcFanMax = 5; +const uint8_t kToshibaAcMinTemp = 17; // 17C +const uint8_t kToshibaAcMaxTemp = 30; // 30C + +// Legacy defines. (Deperecated) +#define TOSHIBA_AC_AUTO kToshibaAcAuto +#define TOSHIBA_AC_COOL kToshibaAcCool +#define TOSHIBA_AC_DRY kToshibaAcDry +#define TOSHIBA_AC_HEAT kToshibaAcHeat +#define TOSHIBA_AC_POWER kToshibaAcPower +#define TOSHIBA_AC_FAN_AUTO kToshibaAcFanAuto +#define TOSHIBA_AC_FAN_MAX kToshibaAcFanMax +#define TOSHIBA_AC_MIN_TEMP kToshibaAcMinTemp +#define TOSHIBA_AC_MAX_TEMP kToshibaAcMaxTemp + +class IRToshibaAC { + public: + explicit IRToshibaAC(uint16_t pin); + + void stateReset(); +#if SEND_TOSHIBA_AC + void send(); +#endif // SEND_TOSHIBA_AC + void begin(); + void on(); + void off(); + void setPower(bool state); + bool getPower(); + void setTemp(uint8_t temp); + uint8_t getTemp(); + void setFan(uint8_t fan); + uint8_t getFan(); + void setMode(uint8_t mode); + uint8_t getMode(bool useRaw = false); + void setRaw(uint8_t newState[]); + uint8_t* getRaw(); + static bool validChecksum(const uint8_t state[], + const uint16_t length = kToshibaACStateLength); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif +#ifndef UNIT_TEST + + private: +#endif + uint8_t remote_state[kToshibaACStateLength]; + void checksum(const uint16_t length = kToshibaACStateLength); + static uint8_t calcChecksum(const uint8_t state[], + const uint16_t length = kToshibaACStateLength); + uint8_t mode_state; + IRsend _irsend; +}; + +#endif // IR_TOSHIBA_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.cpp new file mode 100644 index 000000000..0bece2664 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.cpp @@ -0,0 +1,127 @@ +// Copyright 2017 stufisher + +#include "ir_Trotec.h" +#include "IRremoteESP8266.h" +#include "IRutils.h" + +// Constants +const uint16_t kTrotecHdrMark = 5952; +const uint16_t kTrotecHdrSpace = 7364; +const uint16_t kTrotecOneMark = 592; +const uint16_t kTrotecOneSpace = 1560; +const uint16_t kTrotecZeroMark = 592; +const uint16_t kTrotecZeroSpace = 592; +const uint16_t kTrotecGap = 6184; +const uint16_t kTrotecGapEnd = 1500; // made up value + +#if SEND_TROTEC + +void IRsend::sendTrotec(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kTrotecStateLength) return; + + for (uint16_t r = 0; r <= repeat; r++) { + sendGeneric(kTrotecHdrMark, kTrotecHdrSpace, kTrotecOneMark, + kTrotecOneSpace, kTrotecZeroMark, kTrotecZeroSpace, + kTrotecOneMark, kTrotecGap, data, nbytes, 36, false, + 0, // Repeats handled elsewhere + 50); + // More footer + enableIROut(36); + mark(kTrotecOneMark); + space(kTrotecGapEnd); + } +} +#endif // SEND_TROTEC + +IRTrotecESP::IRTrotecESP(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRTrotecESP::begin() { _irsend.begin(); } + +#if SEND_TROTEC +void IRTrotecESP::send() { + checksum(); + _irsend.sendTrotec(trotec); +} +#endif // SEND_TROTEC + +void IRTrotecESP::checksum() { + uint8_t sum = 0; + uint8_t i; + + for (i = 2; i < 8; i++) sum += trotec[i]; + + trotec[8] = sum & 0xFF; +} + +void IRTrotecESP::stateReset() { + for (uint8_t i = 2; i < kTrotecStateLength; i++) trotec[i] = 0x0; + + trotec[0] = kTrotecIntro1; + trotec[1] = kTrotecIntro2; + + setPower(false); + setTemp(kTrotecDefTemp); + setSpeed(kTrotecFanMed); + setMode(kTrotecAuto); +} + +uint8_t* IRTrotecESP::getRaw() { + checksum(); + return trotec; +} + +void IRTrotecESP::setPower(bool state) { + if (state) + trotec[2] |= (kTrotecOn << 3); + else + trotec[2] &= ~(kTrotecOn << 3); +} + +uint8_t IRTrotecESP::getPower() { return trotec[2] & (kTrotecOn << 3); } + +void IRTrotecESP::setSpeed(uint8_t speed) { + trotec[2] = (trotec[2] & 0xcf) | (speed << 4); +} + +uint8_t IRTrotecESP::getSpeed() { return trotec[2] & 0x30; } + +void IRTrotecESP::setMode(uint8_t mode) { + trotec[2] = (trotec[2] & 0xfc) | mode; +} + +uint8_t IRTrotecESP::getMode() { return trotec[2] & 0x03; } + +void IRTrotecESP::setTemp(uint8_t temp) { + if (temp < kTrotecMinTemp) + temp = kTrotecMinTemp; + else if (temp > kTrotecMaxTemp) + temp = kTrotecMaxTemp; + + trotec[3] = (trotec[3] & 0x80) | (temp - kTrotecMinTemp); +} + +uint8_t IRTrotecESP::getTemp() { return trotec[3] & 0x7f; } + +void IRTrotecESP::setSleep(bool sleep) { + if (sleep) + trotec[3] |= (kTrotecSleepOn << 7); + else + trotec[3] &= ~(kTrotecSleepOn << 7); +} + +bool IRTrotecESP::getSleep(void) { return trotec[3] & (kTrotecSleepOn << 7); } + +void IRTrotecESP::setTimer(uint8_t timer) { + if (timer > kTrotecMaxTimer) timer = kTrotecMaxTimer; + + if (timer) { + trotec[5] |= (kTrotecTimerOn << 6); + trotec[6] = timer; + } else { + trotec[5] &= ~(kTrotecTimerOn << 6); + trotec[6] = 0; + } +} + +uint8_t IRTrotecESP::getTimer() { return trotec[6]; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h new file mode 100644 index 000000000..040d9a722 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h @@ -0,0 +1,92 @@ +// Copyright 2017 stufisher + +#ifndef IR_TROTEC_H_ +#define IR_TROTEC_H_ + +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// Constants +// Byte 0 +const uint8_t kTrotecIntro1 = 0x12; + +// Byte 1 +const uint8_t kTrotecIntro2 = 0x34; + +// Byte 2 +const uint8_t kTrotecAuto = 0; +const uint8_t kTrotecCool = 1; +const uint8_t kTrotecDry = 2; +const uint8_t kTrotecFan = 3; + +const uint8_t kTrotecOn = 1; +const uint8_t kTrotecOff = 0; + +const uint8_t kTrotecFanLow = 1; +const uint8_t kTrotecFanMed = 2; +const uint8_t kTrotecFanHigh = 3; + +// Byte 3 +const uint8_t kTrotecMinTemp = 18; +const uint8_t kTrotecDefTemp = 25; +const uint8_t kTrotecMaxTemp = 32; + +const uint8_t kTrotecSleepOn = 1; + +// Byte 5 +const uint8_t kTrotecTimerOn = 1; + +// Byte 6 +const uint8_t kTrotecMinTimer = 0; +const uint8_t kTrotecMaxTimer = 23; + +// Legacy defines. (Deperecated) +#define TROTEC_AUTO kTrotecAuto +#define TROTEC_COOL kTrotecCool +#define TROTEC_DRY kTrotecDry +#define TROTEC_FAN kTrotecFan +#define TROTEC_FAN_LOW kTrotecFanLow +#define TROTEC_FAN_MED kTrotecFanMed +#define TROTEC_FAN_HIGH kTrotecFanHigh +#define TROTEC_MIN_TEMP kTrotecMinTemp +#define TROTEC_MAX_TEMP kTrotecMaxTemp +#define TROTEC_MIN_TIMER kTrotecMinTimer +#define TROTEC_MAX_TIMER kTrotecMaxTimer + +class IRTrotecESP { + public: + explicit IRTrotecESP(uint16_t pin); + +#if SEND_TROTEC + void send(); +#endif // SEND_TROTEC + void begin(); + + void setPower(bool state); + uint8_t getPower(); + + void setTemp(uint8_t temp); + uint8_t getTemp(); + + void setSpeed(uint8_t fan); + uint8_t getSpeed(); + + uint8_t getMode(); + void setMode(uint8_t mode); + + bool getSleep(); + void setSleep(bool sleep); + + uint8_t getTimer(); + void setTimer(uint8_t timer); + + uint8_t* getRaw(); + + private: + uint8_t trotec[kTrotecStateLength]; + void stateReset(); + void checksum(); + IRsend _irsend; +}; + +#endif // IR_TROTEC_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Whirlpool.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Whirlpool.cpp new file mode 100644 index 000000000..671513991 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Whirlpool.cpp @@ -0,0 +1,149 @@ +// Copyright 2018 David Conran +// +// Code to emulate Whirlpool protocol compatible devices. +// Should be compatible with: +// * SPIS409L, SPIS412L, SPIW409L, SPIW412L, SPIW418L +// + +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRutils.h" + +// WW WW HH HH IIIII RRRRRR LL PPPPPP OOOOO OOOOO LL +// WW WW HH HH III RR RR LL PP PP OO OO OO OO LL +// WW W WW HHHHHHH III RRRRRR LL PPPPPP OO OO OO OO LL +// WW WWW WW HH HH III RR RR LL PP OO OO OO OO LL +// WW WW HH HH IIIII RR RR LLLLLLL PP OOOO0 OOOO0 LLLLLLL + +// Constants +// Ref: https://github.com/markszabo/IRremoteESP8266/issues/509 +const uint16_t kWhirlpoolAcHdrMark = 8950; +const uint16_t kWhirlpoolAcHdrSpace = 4484; +const uint16_t kWhirlpoolAcBitMark = 597; +const uint16_t kWhirlpoolAcOneSpace = 1649; +const uint16_t kWhirlpoolAcZeroSpace = 533; +const uint16_t kWhirlpoolAcGap = 7920; +const uint32_t kWhirlpoolAcMinGap = 100000; // Completely made up value. +const uint8_t kWhirlpoolAcSections = 3; + +#if SEND_WHIRLPOOL_AC +// Send a Whirlpool A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kWhirlpoolAcStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: ALPHA / Untested. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/509 +void IRsend::sendWhirlpoolAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kWhirlpoolAcStateLength) + return; // Not enough bytes to send a proper message. + for (uint16_t r = 0; r <= repeat; r++) { + // Section 1 + sendGeneric(kWhirlpoolAcHdrMark, kWhirlpoolAcHdrSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcOneSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, kWhirlpoolAcGap, + data, 6, // 6 bytes == 48 bits + 38000, // Complete guess of the modulation frequency. + false, 0, 50); + // Section 2 + sendGeneric(0, 0, kWhirlpoolAcBitMark, kWhirlpoolAcOneSpace, + kWhirlpoolAcBitMark, kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcGap, data + 6, 8, // 8 bytes == 64 bits + 38000, // Complete guess of the modulation frequency. + false, 0, 50); + // Section 3 + sendGeneric(0, 0, kWhirlpoolAcBitMark, kWhirlpoolAcOneSpace, + kWhirlpoolAcBitMark, kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcMinGap, data + 14, 7, // 7 bytes == 56 bits + 38000, // Complete guess of the modulation frequency. + false, 0, 50); + } +} +#endif // SEND_WHIRLPOOL_AC + +#if DECODE_WHIRLPOOL_AC +// Decode the supplied Whirlpool A/C message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kWhirlpoolAcBits +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: ALPHA / Untested. +// +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/509 +bool IRrecv::decodeWhirlpoolAC(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + 4 + kHeader + kFooter - 1) + return false; // Can't possibly be a valid Whirlpool A/C message. + if (strict) { + if (nbits != kWhirlpoolAcBits) return false; + } + + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + uint16_t i = 0; + match_result_t data_result; + uint8_t sectionSize[kWhirlpoolAcSections] = {6, 8, 7}; + + // Header + if (!matchMark(results->rawbuf[offset++], kWhirlpoolAcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kWhirlpoolAcHdrSpace)) + return false; + + // Data Section + // Keep reading bytes until we either run out of section or state to fill. + for (uint8_t section = 0, pos = 0; section < kWhirlpoolAcSections; + section++) { + pos += sectionSize[section]; + for (; offset <= results->rawlen - 16 && i < pos; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = + matchData(&(results->rawbuf[offset]), 8, kWhirlpoolAcBitMark, + kWhirlpoolAcOneSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) break; // Fail + // Data is in LSB order. We need to reverse it. + results->state[i] = (uint8_t)data_result.data; + } + // Section Footer + if (!matchMark(results->rawbuf[offset++], kWhirlpoolAcBitMark)) + return false; + if (section < kWhirlpoolAcSections - 1) { // Inter-section gaps. + if (!matchSpace(results->rawbuf[offset++], kWhirlpoolAcGap)) return false; + } else { // Last section / End of message gap. + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kWhirlpoolAcGap)) + return false; + } + } + + // Compliance + if (strict) { + // Re-check we got the correct size/length due to the way we read the data. + if (dataBitsSoFar != kWhirlpoolAcBits) return false; + } + + // Success + results->decode_type = WHIRLPOOL_AC; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // WHIRLPOOL_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Whynter.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Whynter.cpp new file mode 100644 index 000000000..555c50788 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/src/ir_Whynter.cpp @@ -0,0 +1,135 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// W W H H Y Y N N TTTTT EEEEE RRRRR +// W W H H Y Y NN N T E R R +// W W W HHHHH Y N N N T EEE RRRR +// W W W H H Y N NN T E R R +// WWW H H Y N N T EEEEE R R + +// Whynter A/C ARC-110WD added by Francesco Meschia +// Whynter originally added from https://github.com/shirriff/Arduino-IRremote/ + +// Constants + +const uint16_t kWhynterTick = 50; +const uint16_t kWhynterHdrMarkTicks = 57; +const uint16_t kWhynterHdrMark = kWhynterHdrMarkTicks * kWhynterTick; +const uint16_t kWhynterHdrSpaceTicks = 57; +const uint16_t kWhynterHdrSpace = kWhynterHdrSpaceTicks * kWhynterTick; +const uint16_t kWhynterBitMarkTicks = 15; +const uint16_t kWhynterBitMark = kWhynterBitMarkTicks * kWhynterTick; +const uint16_t kWhynterOneSpaceTicks = 43; +const uint16_t kWhynterOneSpace = kWhynterOneSpaceTicks * kWhynterTick; +const uint16_t kWhynterZeroSpaceTicks = 15; +const uint16_t kWhynterZeroSpace = kWhynterZeroSpaceTicks * kWhynterTick; +const uint16_t kWhynterMinCommandLengthTicks = 2160; // Totally made up value. +const uint32_t kWhynterMinCommandLength = + kWhynterMinCommandLengthTicks * kWhynterTick; +const uint16_t kWhynterMinGapTicks = + kWhynterMinCommandLengthTicks - + (2 * (kWhynterBitMarkTicks + kWhynterZeroSpaceTicks) + + kWhynterBits * (kWhynterBitMarkTicks + kWhynterOneSpaceTicks)); +const uint16_t kWhynterMinGap = kWhynterMinGapTicks * kWhynterTick; + +#if SEND_WHYNTER +// Send a Whynter message. +// +// Args: +// data: message to be sent. +// nbits: Nr. of bits of the message to be sent. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: STABLE +// +// Ref: +// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp +void IRsend::sendWhynter(uint64_t data, uint16_t nbits, uint16_t repeat) { + // Set IR carrier frequency + enableIROut(38); + + for (uint16_t i = 0; i <= repeat; i++) { + // (Pre-)Header + mark(kWhynterBitMark); + space(kWhynterZeroSpace); + sendGeneric( + kWhynterHdrMark, kWhynterHdrSpace, kWhynterBitMark, kWhynterOneSpace, + kWhynterBitMark, kWhynterZeroSpace, kWhynterBitMark, kWhynterMinGap, + kWhynterMinCommandLength - (kWhynterBitMark + kWhynterZeroSpace), data, + nbits, 38, true, 0, // Repeats are already handled. + 50); + } +} +#endif + +#if DECODE_WHYNTER +// Decode the supplied Whynter message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA Strict mode is ALPHA. +// +// Ref: +// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp +bool IRrecv::decodeWhynter(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + 2 * kHeader + kFooter - 1) + return false; // We don't have enough entries to possibly match. + + // Compliance + if (strict && nbits != kWhynterBits) + return false; // Incorrect nr. of bits per spec. + + uint16_t offset = kStartOffset; + + // Header + // Sequence begins with a bit mark and a zero space. + // These are typically small, so we'll prefer to do the calibration + // on the much larger header mark & space that are next. + if (!matchMark(results->rawbuf[offset++], kWhynterBitMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kWhynterZeroSpace)) return false; + // Main header mark and space + if (!matchMark(results->rawbuf[offset], kWhynterHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kWhynterHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kWhynterHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kWhynterHdrSpaceTicks; + + // Data + uint64_t data = 0; + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, + kWhynterBitMarkTicks * m_tick, kWhynterOneSpaceTicks * s_tick, + kWhynterBitMarkTicks * m_tick, kWhynterZeroSpaceTicks * s_tick); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + + // Footer + if (!matchMark(results->rawbuf[offset++], kWhynterBitMarkTicks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kWhynterMinGapTicks * s_tick)) + return false; + + // Success + results->decode_type = WHYNTER; + results->bits = nbits; + results->value = data; + results->address = 0; + results->command = 0; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/test/IRrecv_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.cpp similarity index 68% rename from lib/IRremoteESP8266-2.2.1.02/test/IRrecv_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.cpp index 4b22656f6..85b6685f0 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/IRrecv_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.cpp @@ -1,7 +1,8 @@ // Copyright 2017 David Conran -#include "IRremoteESP8266.h" +#include "IRrecv_test.h" #include "IRrecv.h" +#include "IRremoteESP8266.h" #include "IRsend.h" #include "IRsend_test.h" #include "gtest/gtest.h" @@ -9,7 +10,7 @@ // Tests for the IRrecv object. TEST(TestIRrecv, DefaultBufferSize) { IRrecv irrecv_default(1); - EXPECT_EQ(RAWBUF, irrecv_default.getBufSize()); + EXPECT_EQ(kRawBuf, irrecv_default.getBufSize()); } TEST(TestIRrecv, LargeBufferSize) { @@ -29,7 +30,7 @@ TEST(TestIRrecv, MediumBufferSize) { TEST(TestIRrecv, IRrecvDestructor) { IRrecv *irrecv_ptr = new IRrecv(1); - EXPECT_EQ(RAWBUF, irrecv_ptr->getBufSize()); + EXPECT_EQ(kRawBuf, irrecv_ptr->getBufSize()); delete irrecv_ptr; irrecv_ptr = new IRrecv(1, 1234); @@ -119,7 +120,7 @@ TEST(TestDecode, DecodeNEC) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x807F40BF, irsend.capture.value); } @@ -133,7 +134,7 @@ TEST(TestDecode, DecodeJVC) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); } @@ -147,15 +148,15 @@ TEST(TestDecode, DecodeLG) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG_BITS, irsend.capture.bits); + EXPECT_EQ(kLgBits, irsend.capture.bits); EXPECT_EQ(0x4B4AE51, irsend.capture.value); irsend.reset(); - irsend.sendLG(0xB4B4AE51, LG32_BITS); + irsend.sendLG(0xB4B4AE51, kLg32Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0xB4B4AE51, irsend.capture.value); } @@ -167,9 +168,9 @@ TEST(TestDecode, DecodePanasonic) { irsend.reset(); irsend.sendPanasonic64(0x40040190ED7C); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); EXPECT_EQ(0x40040190ED7C, irsend.capture.value); } @@ -183,7 +184,7 @@ TEST(TestDecode, DecodeSamsung) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); - EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); EXPECT_EQ(0xE0E09966, irsend.capture.value); } @@ -198,7 +199,7 @@ TEST(TestDecode, DecodeSherwood) { ASSERT_TRUE(irrecv.decode(&irsend.capture)); // Sherwood codes are really NEC codes. EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x807F40BF, irsend.capture.value); } @@ -212,7 +213,7 @@ TEST(TestDecode, DecodeWhynter) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); - EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(kWhynterBits, irsend.capture.bits); EXPECT_EQ(0x87654321, irsend.capture.value); } @@ -224,30 +225,29 @@ TEST(TestDecode, DecodeSony) { // Synthesised Normal Sony 20-bit message. irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_20_BITS, 0x1, 0x1, 0x1)); + irsend.sendSony(irsend.encodeSony(kSony20Bits, 0x1, 0x1, 0x1)); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_20_BITS, irsend.capture.bits); + EXPECT_EQ(kSony20Bits, irsend.capture.bits); EXPECT_EQ(0x81080, irsend.capture.value); // Synthesised Normal Sony 15-bit message. irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_15_BITS, 21, 1), SONY_15_BITS); + irsend.sendSony(irsend.encodeSony(kSony15Bits, 21, 1), kSony15Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_15_BITS, irsend.capture.bits); + EXPECT_EQ(kSony15Bits, irsend.capture.bits); EXPECT_EQ(0x5480, irsend.capture.value); - // Synthesised Normal Sony 12-bit message. irsend.reset(); - irsend.sendSony(irsend.encodeSony(SONY_12_BITS, 21, 1), SONY_12_BITS); + irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_12_BITS, irsend.capture.bits); + EXPECT_EQ(kSony12Bits, irsend.capture.bits); EXPECT_EQ(0xA90, irsend.capture.value); } @@ -261,7 +261,7 @@ TEST(TestDecode, DecodeSharp) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x454A, irsend.capture.value); } @@ -275,7 +275,7 @@ TEST(TestDecode, DecodeSanyo) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x2468DCB56A9, irsend.capture.value); } @@ -291,7 +291,7 @@ TEST(TestDecode, DecodeRCMM) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(RCMM, irsend.capture.decode_type); - EXPECT_EQ(RCMM_BITS, irsend.capture.bits); + EXPECT_EQ(kRCMMBits, irsend.capture.bits); EXPECT_EQ(0xe0a600, irsend.capture.value); // Normal RCMM 12-bit message. @@ -323,7 +323,7 @@ TEST(TestDecode, DecodeMitsubishi) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); - EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); } @@ -338,15 +338,15 @@ TEST(TestDecode, DecodeRC5) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); // Synthesised Normal RC-5X 13-bit message. irsend.reset(); - irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), RC5X_BITS); + irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(RC5X, irsend.capture.decode_type); - EXPECT_EQ(RC5X_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5XBits, irsend.capture.bits); EXPECT_EQ(0x1881, irsend.capture.value); } @@ -361,16 +361,16 @@ TEST(TestDecode, DecodeRC6) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); // Normal RC-6 36-bit message. irsend.reset(); - irsend.sendRC6(0xC800F742A, RC6_36_BITS); + irsend.sendRC6(0xC800F742A, kRC6_36Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0xC800F742A, irsend.capture.value); } @@ -384,7 +384,7 @@ TEST(TestDecode, DecodeDish) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(DISH, irsend.capture.decode_type); - EXPECT_EQ(DISH_BITS, irsend.capture.bits); + EXPECT_EQ(kDishBits, irsend.capture.bits); EXPECT_EQ(0x9C00, irsend.capture.value); } @@ -403,7 +403,7 @@ TEST(TestDecode, DecodeDenon) { EXPECT_EQ(0x2278, irsend.capture.value); // Legacy Denon 14-bit message. irsend.reset(); - irsend.sendDenon(0x1278, DENON_LEGACY_BITS); + irsend.sendDenon(0x1278, kDenonLegacyBits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(DENON, irsend.capture.decode_type); @@ -429,7 +429,7 @@ TEST(TestDecode, DecodeCoolix) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); } @@ -443,6 +443,119 @@ TEST(TestDecode, DecodeAiwa) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); - EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7F, irsend.capture.value); } + +// Test matchData() on space encoded data. +TEST(TestMatchData, SpaceEncoded) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + uint16_t space_encoded_raw[11] = {500, 500, 500, 1500, 499, 499, + 501, 1501, 499, 1490, 500}; + match_result_t result; + + irsend.reset(); + irsend.sendRaw(space_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 500, 1500, 500, 500); + ASSERT_TRUE(result.success); + EXPECT_EQ(0b01011, result.data); + EXPECT_EQ(10, result.used); + + irsend.reset(); + irsend.sendRaw(space_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 500, 1000, 500, 500); + ASSERT_FALSE(result.success); +} + +// Test matchData() on mark encoded data. +TEST(TestMatchData, MarkEncoded) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + uint16_t mark_encoded_raw[11] = {500, 500, 1500, 500, 499, 499, + 1501, 501, 1499, 490, 500}; + match_result_t result; + + irsend.reset(); + irsend.sendRaw(mark_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + // MSBF order. + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 500); + ASSERT_TRUE(result.success); + EXPECT_EQ(0b01011, result.data); + EXPECT_EQ(10, result.used); + // LSBF order. + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 500, + kTolerance, kMarkExcess, false); + ASSERT_TRUE(result.success); + EXPECT_EQ(0b11010, result.data); // Bits reversed of the previous test. + EXPECT_EQ(10, result.used); + + irsend.reset(); + irsend.sendRaw(mark_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + // MSBF order. + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 500); + ASSERT_FALSE(result.success); + // LSBF order. + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 500, + kTolerance, kMarkExcess, false); + ASSERT_FALSE(result.success); +} + +// Test matchData() on "equal total bit time" encoded data. +TEST(TestMatchData, EqualTotalBitTimeEncoded) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + uint16_t equal_encoded_raw[11] = {500, 1500, 1500, 500, 499, 1499, + 1501, 501, 1499, 490, 500}; + match_result_t result; + + irsend.reset(); + irsend.sendRaw(equal_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 1500); + ASSERT_TRUE(result.success); + EXPECT_EQ(0b01011, result.data); + EXPECT_EQ(10, result.used); + + irsend.reset(); + irsend.sendRaw(equal_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 1000); + ASSERT_FALSE(result.success); +} + +// Test matchData() on arbitrary encoded data. +TEST(TestMatchData, ArbitraryEncoded) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + uint16_t arbitrary_encoded_raw[11] = {500, 1500, 3000, 1000, 499, 1499, + 3001, 1001, 2999, 990, 500}; + match_result_t result; + + irsend.reset(); + irsend.sendRaw(arbitrary_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + result = + irrecv.matchData(irsend.capture.rawbuf + 1, 5, 3000, 1000, 500, 1500); + ASSERT_TRUE(result.success); + EXPECT_EQ(0b01011, result.data); + EXPECT_EQ(10, result.used); + + irsend.reset(); + irsend.sendRaw(arbitrary_encoded_raw, 11, 38000); + irsend.makeDecodeResult(); + result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1000, 500, 500, 1000); + ASSERT_FALSE(result.success); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.h b/lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.h new file mode 100644 index 000000000..bb366c1ee --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.h @@ -0,0 +1,17 @@ +// Copyright 2017 David Conran + +#ifndef TEST_IRRECV_TEST_H_ +#define TEST_IRRECV_TEST_H_ + +#include +#include +#include +#include "IRutils.h" + +#define EXPECT_STATE_EQ(a, b, c) \ + for (uint8_t i = 0; i < c / 8; ++i) { \ + EXPECT_EQ(a[i], b[i]) << "Expected state " \ + "differs at i = " \ + << uint64ToString(i); \ + } +#endif // TEST_IRRECV_TEST_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.cpp new file mode 100644 index 000000000..353639918 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.cpp @@ -0,0 +1,290 @@ +// Copyright 2017 David Conran + +#include "IRsend_test.h" +#include "IRsend.h" +#include "gtest/gtest.h" + +// Tests sendData(). + +// Test sending zero bits. +TEST(TestSendData, SendZeroBits) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b1, 0, true); + EXPECT_EQ("", irsend.outputStr()); +} + +// Test sending zero and one. +TEST(TestSendData, SendSingleBit) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + EXPECT_EQ("m1s2", irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0b0, 1, true); + EXPECT_EQ("m3s4", irsend.outputStr()); +} + +// Test sending bit order. +TEST(TestSendData, TestingBitSendOrder) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b10, 2, true); + EXPECT_EQ("m1s2m3s4", irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0b10, 2, false); + EXPECT_EQ("m3s4m1s2", irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0b0001, 4, false); + EXPECT_EQ("m1s2m3s4m3s4m3s4", irsend.outputStr()); +} + +// Test sending typical data. +TEST(TestSendData, SendTypicalData) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b1010110011110000, 16, true); + EXPECT_EQ("m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4m3s4", + irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0x1234567890ABCDEF, 64, true); + EXPECT_EQ( + "m3s4m3s4m3s4m1s2m3s4m3s4m1s2m3s4m3s4m3s4m1s2m1s2m3s4m1s2m3s4m3s4" + "m3s4m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4" + "m1s2m3s4m3s4m1s2m3s4m3s4m3s4m3s4m1s2m3s4m1s2m3s4m1s2m3s4m1s2m1s2" + "m1s2m1s2m3s4m3s4m1s2m1s2m3s4m1s2m1s2m1s2m1s2m3s4m1s2m1s2m1s2m1s2", + irsend.outputStr()); +} + +// Test sending more than expected bits. +TEST(TestSendData, SendOverLargeData) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0xFFFFFFFFFFFFFFFF, 70, true); + EXPECT_EQ( + "m3s4m3s4m3s4m3s4m3s4m3s4" + "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" + "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" + "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" + "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2", + irsend.outputStr()); +} + +// Test inverting the output. +TEST(TestIRSend, InvertedOutput) { + IRsendTest irsend(4, true); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + EXPECT_EQ("s1m2", irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0b0, 1, true); + EXPECT_EQ("s3m4", irsend.outputStr()); +} + +// Test typical use of sendRaw(). +TEST(TestSendRaw, GeneralUse) { + IRsendTest irsend(4); + IRrecv irrecv(0); + + irsend.begin(); + // NEC C3E0E0E8 as measured in #204 + uint16_t rawData[67] = { + 8950, 4500, 550, 1650, 600, 1650, 550, 550, 600, 500, 600, 550, + 550, 550, 600, 1650, 550, 1650, 600, 1650, 600, 1650, 550, 1700, + 550, 550, 600, 550, 550, 550, 600, 500, 600, 550, 550, 1650, + 600, 1650, 600, 1650, 550, 550, 600, 500, 600, 500, 600, 550, + 550, 550, 600, 1650, 550, 1650, 600, 1650, 600, 500, 650, 1600, + 600, 500, 600, 550, 550, 550, 600}; + + irsend.sendRaw(rawData, 67, 38); + EXPECT_EQ( + "m8950s4500" + "m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650" + "m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550" + "m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550" + "m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550" + "m600", + irsend.outputStr()); + + irsend.reset(); + irsend.sendRaw(rawData, 67, 38); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, kNECBits, false)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0xC3E0E0E8, irsend.capture.value); + EXPECT_EQ( + "m8950s4500" + "m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650" + "m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550" + "m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550" + "m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550" + "m600", + irsend.outputStr()); +} + +// Incorrect handling of decodes from Raw. i.e. There is no gap recorded at +// the end of a command when using the interrupt code. sendRaw() best emulates +// this for unit testing purposes. sendGC() and sendXXX() will add the trailing +// gap. Users won't see this in normal use. +TEST(TestSendRaw, NoTrailingGap) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[67] = { + 9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, 600, 1650, + 650, 550, 600, 1650, 650, 1650, 650, 1650, 600, 550, 650, 1650, + 650, 1650, 650, 550, 600, 1650, 650, 1650, 650, 550, 650, 550, + 650, 1650, 650, 550, 650, 550, 650, 550, 600, 550, 650, 550, + 650, 550, 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650, + 650, 1650, 650, 1650, 650, 1650, 600}; + irsend.sendRaw(rawData, 67, 38); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); +} + +TEST(TestLowLevelSend, MarkFrequencyModulationAt38kHz) { + IRsendLowLevelTest irsend(0); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(38000, 50); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]10usecs[Off]11usecs[On]10usecs[Off]11usecs[On]10usecs[Off]11usecs" + "[On]10usecs[Off]11usecs[On]10usecs[Off]6usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(38000, 33); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]6usecs[Off]15usecs[On]6usecs[Off]15usecs[On]6usecs[Off]15usecs" + "[On]6usecs[Off]15usecs[On]6usecs[Off]10usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(38000, 100); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, MarkFrequencyModulationAt36_7kHz) { + IRsendLowLevelTest irsend(0); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(36700, 50); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]11usecs[Off]11usecs[On]11usecs[Off]11usecs[On]11usecs[Off]11usecs" + "[On]11usecs[Off]11usecs[On]11usecs[Off]1usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(36700, 33); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]7usecs[Off]15usecs[On]7usecs[Off]15usecs[On]7usecs[Off]15usecs" + "[On]7usecs[Off]15usecs[On]7usecs[Off]5usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(36700, 100); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, MarkFrequencyModulationAt40kHz) { + IRsendLowLevelTest irsend(0); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(40000, 50); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs" + "[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 33); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs" + "[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 100); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, MarkNoModulation) { + IRsendLowLevelTest irsend(0, false, false); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(38000, 50); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(36700, 25); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 75); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, SpaceFrequencyModulation) { + IRsendLowLevelTest irsend(0); + + irsend.reset(); + irsend.enableIROut(38000); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 75); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(38000, 100); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(38000, 33); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, SpaceNoModulation) { + IRsendLowLevelTest irsend(0, false, false); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(38000, 50); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(36700, 25); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 75); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.h b/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.h new file mode 100644 index 000000000..6d9fe51b8 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.h @@ -0,0 +1,135 @@ +// Copyright 2017 David Conran + +#ifndef TEST_IRSEND_TEST_H_ +#define TEST_IRSEND_TEST_H_ + +#define __STDC_LIMIT_MACROS +#include +#include +#include +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtimer.h" + +#define OUTPUT_BUF 10000U +#define RAW_BUF 10000U + +#ifdef UNIT_TEST +// Used to help simulate elapsed time in unit tests. +uint32_t _IRtimer_unittest_now = 0; +#endif // UNIT_TEST + +class IRsendTest : public IRsend { + public: + uint32_t output[OUTPUT_BUF]; + uint16_t last; + uint16_t rawbuf[RAW_BUF]; + decode_results capture; + + explicit IRsendTest(uint16_t x, bool i = false, bool j = true) + : IRsend(x, i, j) { + reset(); + } + + void reset() { + last = 0; + for (uint16_t i = 0; i < OUTPUT_BUF; i++) output[i] = 0; + for (uint16_t i = 0; i < RAW_BUF; i++) rawbuf[i] = 0; + } + + std::string outputStr() { + std::stringstream result; + if (last == 0 && output[0] == 0) return ""; + for (uint16_t i = 0; i <= last; i++) { + if ((i & 1) != outputOff) // Odd XOR outputOff + result << "s"; + else + result << "m"; + result << output[i]; + } + reset(); + return result.str(); + } + + void makeDecodeResult(uint16_t offset = 0) { + capture.decode_type = UNKNOWN; + capture.bits = 0; + capture.rawlen = last + 2 - offset; + capture.overflow = (last - offset >= (int16_t)RAW_BUF); + capture.repeat = false; + capture.address = 0; + capture.command = 0; + capture.value = 0; + capture.rawbuf = rawbuf; + for (uint16_t i = 0; (i < RAW_BUF - 1) && (offset < OUTPUT_BUF); + i++, offset++) + if (output[offset] / kRawTick > UINT16_MAX) + rawbuf[i + 1] = UINT16_MAX; + else + rawbuf[i + 1] = output[offset] / kRawTick; + } + + void dumpRawResult() { + std::cout << std::dec; + if (capture.rawlen == 0) return; + std::cout << "uint16_t rawbuf[" << capture.rawlen - 1 << "] = {"; + for (uint16_t i = 1; i < capture.rawlen; i++) { + if (i % 8 == 1) std::cout << std::endl << " "; + std::cout << (capture.rawbuf[i] * kRawTick); + // std::cout << "(" << capture.rawbuf[i] << ")"; + if (i < capture.rawlen - 1) std::cout << ", "; + } + std::cout << "};" << std::endl; + } + + void addGap(uint32_t usecs) { space(usecs); } + + uint16_t mark(uint16_t usec) { + IRtimer::add(usec); + if (last >= OUTPUT_BUF) return 0; + if (last & 1) // Is odd? (i.e. last call was a space()) + output[++last] = usec; + else + output[last] += usec; + return 0; + } + + void space(uint32_t time) { + IRtimer::add(time); + if (last >= OUTPUT_BUF) return; + if (last & 1) { // Is odd? (i.e. last call was a space()) + output[last] += time; + } else { + output[++last] = time; + } + } +}; + +#ifdef UNIT_TEST +class IRsendLowLevelTest : public IRsend { + public: + std::string low_level_sequence; + + explicit IRsendLowLevelTest(uint16_t x, bool i = false, bool j = true) + : IRsend(x, i, j) { + reset(); + } + + void reset() { low_level_sequence = ""; } + + protected: + void _delayMicroseconds(uint32_t usec) { + _IRtimer_unittest_now += usec; + std::ostringstream Convert; + Convert << usec; + low_level_sequence += Convert.str() + "usecs"; + } + + void ledOff() { low_level_sequence += "[Off]"; } + + void ledOn() { low_level_sequence += "[On]"; } +}; +#endif // UNIT_TEST + +#endif // TEST_IRSEND_TEST_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRutils_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/IRutils_test.cpp new file mode 100644 index 000000000..91cf4725c --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/IRutils_test.cpp @@ -0,0 +1,352 @@ +// Copyright 2017 David Conran + +#include "IRutils.h" +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests reverseBits(). + +// Tests reverseBits for typical use. +TEST(ReverseBitsTest, TypicalUse) { + EXPECT_EQ(0xF, reverseBits(0xF0, 8)); + EXPECT_EQ(0xFFFF, reverseBits(0xFFFF0000, 32)); + EXPECT_EQ(0x555500005555FFFF, reverseBits(0xFFFFAAAA0000AAAA, 64)); + EXPECT_EQ(0, reverseBits(0, 64)); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, reverseBits(0xFFFFFFFFFFFFFFFF, 64)); +} + +// Tests reverseBits for bit size values <= 1 +TEST(ReverseBitsTest, LessThanTwoBitsReversed) { + EXPECT_EQ(0x12345678, reverseBits(0x12345678, 1)); + EXPECT_EQ(1234, reverseBits(1234, 0)); +} + +// Tests reverseBits for bit size larger than a uint64_t. +TEST(ReverseBitsTest, LargerThan64BitsReversed) { + EXPECT_EQ(0, reverseBits(0, 65)); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, reverseBits(0xFFFFFFFFFFFFFFFF, 100)); + EXPECT_EQ(0x555500005555FFFF, reverseBits(0xFFFFAAAA0000AAAA, 3000)); +} + +// Tests reverseBits for bit sizes less than all the data stored. +TEST(ReverseBitsTest, LessBitsReversedThanInputHasSet) { + EXPECT_EQ(0xF8, reverseBits(0xF1, 4)); + EXPECT_EQ(0xF5, reverseBits(0xFA, 4)); + EXPECT_EQ(0x12345678FFFF0000, reverseBits(0x123456780000FFFF, 32)); +} + +// Tests for uint64ToString() + +TEST(TestUint64ToString, TrivialCases) { + EXPECT_EQ("0", uint64ToString(0)); // Default base (10) + EXPECT_EQ("0", uint64ToString(0, 2)); // Base-2 + EXPECT_EQ("0", uint64ToString(0, 8)); // Base-8 + EXPECT_EQ("0", uint64ToString(0, 10)); // Base-10 + EXPECT_EQ("0", uint64ToString(0, 16)); // Base-16 + + EXPECT_EQ("1", uint64ToString(1, 2)); // Base-2 + EXPECT_EQ("2", uint64ToString(2, 8)); // Base-8 + EXPECT_EQ("3", uint64ToString(3, 10)); // Base-10 + EXPECT_EQ("4", uint64ToString(4, 16)); // Base-16 +} + +TEST(TestUint64ToString, NormalUse) { + EXPECT_EQ("12345", uint64ToString(12345)); + EXPECT_EQ("100", uint64ToString(4, 2)); + EXPECT_EQ("3039", uint64ToString(12345, 16)); + EXPECT_EQ("123456", uint64ToString(123456)); + EXPECT_EQ("1E240", uint64ToString(123456, 16)); + EXPECT_EQ("FEEDDEADBEEF", uint64ToString(0xfeeddeadbeef, 16)); +} + +TEST(TestUint64ToString, Max64Bit) { + EXPECT_EQ("18446744073709551615", uint64ToString(UINT64_MAX)); // Default + EXPECT_EQ("1111111111111111111111111111111111111111111111111111111111111111", + uint64ToString(UINT64_MAX, 2)); // Base-2 + EXPECT_EQ("1777777777777777777777", uint64ToString(UINT64_MAX, 8)); // Base-8 + EXPECT_EQ("18446744073709551615", uint64ToString(UINT64_MAX, 10)); // Base-10 + EXPECT_EQ("FFFFFFFFFFFFFFFF", uint64ToString(UINT64_MAX, 16)); // Base-16 +} + +TEST(TestUint64ToString, Max32Bit) { + EXPECT_EQ("4294967295", uint64ToString(UINT32_MAX)); // Default + EXPECT_EQ("37777777777", uint64ToString(UINT32_MAX, 8)); // Base-8 + EXPECT_EQ("4294967295", uint64ToString(UINT32_MAX, 10)); // Base-10 + EXPECT_EQ("FFFFFFFF", uint64ToString(UINT32_MAX, 16)); // Base-16 +} + +TEST(TestUint64ToString, InterestingCases) { + // Previous hacky-code didn't handle leading zeros in the lower 32 bits. + EXPECT_EQ("100000000", uint64ToString(0x100000000, 16)); + EXPECT_EQ("100000001", uint64ToString(0x100000001, 16)); +} + +TEST(TestUint64ToString, SillyBases) { + // If we are given a silly base, we should defer to Base-10. + EXPECT_EQ("12345", uint64ToString(12345, 0)); // Super silly, makes no sense. + EXPECT_EQ("12345", uint64ToString(12345, 1)); // We don't do unary. + EXPECT_EQ("12345", uint64ToString(12345, 100)); // We can't print base-100. + EXPECT_EQ("12345", uint64ToString(12345, 37)); // Base-37 is one to far. + EXPECT_EQ("9IX", uint64ToString(12345, 36)); // But we *can* do base-36. +} + +TEST(TestGetCorrectedRawLength, NoLargeValues) { + IRsendTest irsend(0); + IRrecv irrecv(1); + uint16_t test_data[7] = {1, 2, 3, 4, 5, 6, 7}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(test_data, 7, 38000); + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + EXPECT_EQ(7, getCorrectedRawLength(&irsend.capture)); +} + +TEST(TestGetCorrectedRawLength, WithLargeValues) { + IRsendTest irsend(0); + IRrecv irrecv(1); + uint16_t test_data[7] = {10, 20, 30, 40, 50, 60, 70}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(test_data, 7, 38000); + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + irsend.capture.rawbuf[3] = 60000; + ASSERT_EQ(2, kRawTick); // The following values rely on kRawTick being 2. + EXPECT_EQ(7 + 2, getCorrectedRawLength(&irsend.capture)); + irsend.capture.rawbuf[4] = UINT16_MAX - 1; + EXPECT_EQ(7 + 2 * 2, getCorrectedRawLength(&irsend.capture)); + irsend.capture.rawbuf[4] = UINT16_MAX; + EXPECT_EQ(7 + 2 * 2, getCorrectedRawLength(&irsend.capture)); +} + +TEST(TestResultToSourceCode, SimpleTests) { + IRsendTest irsend(0); + IRrecv irrecv(1); + uint16_t test_data[7] = {10, 20, 30, 40, 50, 60, 70}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(test_data, 7, 38000); + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + EXPECT_EQ( + "uint16_t rawData[7] = {10, 20, 30, 40, 50, 60, 70};" + " // UNKNOWN A5E5F35D\n", + resultToSourceCode(&irsend.capture)); + + // Stick in some large values. + irsend.capture.rawbuf[3] = 60000; + EXPECT_EQ( + "uint16_t rawData[9] = {10, 20, 65535, 0, 54465, 40," + " 50, 60, 70}; // UNKNOWN A5E5F35D\n", + resultToSourceCode(&irsend.capture)); + irsend.capture.rawbuf[5] = UINT16_MAX; + EXPECT_EQ( + "uint16_t rawData[11] = {10, 20, 65535, 0, 54465, 40," + " 65535, 0, 65535, 60, 70}; // UNKNOWN A5E5F35D\n", + resultToSourceCode(&irsend.capture)); + + // Reset and put the large value in a space location. + irsend.reset(); + irsend.sendRaw(test_data, 7, 38000); + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + irsend.capture.rawbuf[4] = UINT16_MAX - 1; + EXPECT_EQ( + "uint16_t rawData[9] = {10, 20, 30, 65535, 0, 65533," + " 50, 60, 70}; // UNKNOWN A5E5F35D\n", + resultToSourceCode(&irsend.capture)); +} + +TEST(TestResultToSourceCode, SimpleProtocols) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + // Generate a code which has address & command values. + irsend.reset(); + irsend.sendNEC(irsend.encodeNEC(0x10, 0x20)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(NEC, irsend.capture.decode_type); + ASSERT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ( + "uint16_t rawData[68] = {8960, 4480, 560, 560, 560, 560, 560, 560, " + "560, 560, 560, 1680, 560, 560, 560, 560, 560, 560, 560, 1680, " + "560, 1680, 560, 1680, 560, 1680, 560, 560, 560, 1680, 560, 1680, " + "560, 1680, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, " + "560, 1680, 560, 560, 560, 560, 560, 1680, 560, 1680, 560, 1680, " + "560, 1680, 560, 1680, 560, 560, 560, 1680, 560, 1680, 560, 40320 " + "}; // NEC 8F704FB\n" + "uint32_t address = 0x10;\n" + "uint32_t command = 0x20;\n" + "uint64_t data = 0x8F704FB;\n", + resultToSourceCode(&irsend.capture)); + + // Generate a code which DOESN'T have address & command values. + irsend.reset(); + irsend.sendNikai(0xD0F2F); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(NIKAI, irsend.capture.decode_type); + ASSERT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ( + "uint16_t rawData[52] = {4000, 4000, 500, 2000, 500, 2000, " + "500, 2000, 500, 2000, 500, 1000, 500, 1000, 500, 2000, 500, 1000, " + "500, 2000, 500, 2000, 500, 2000, 500, 2000, 500, 1000, 500, 1000, " + "500, 1000, 500, 1000, 500, 2000, 500, 2000, 500, 1000, 500, 2000, " + "500, 1000, 500, 1000, 500, 1000, 500, 1000, 500, 8500 };" + " // NIKAI D0F2F\n" + "uint64_t data = 0xD0F2F;\n", + resultToSourceCode(&irsend.capture)); +} + +TEST(TestResultToSourceCode, ComplexProtocols) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + uint8_t state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x01}; + + irsend.reset(); + irsend.sendToshibaAC(state); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + EXPECT_EQ( + "uint16_t rawData[296] = {4400, 4300, 542, 1622, 542, 1622, " + "542, 1622, 542, 1622, 542, 472, 542, 472, 542, 1622, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 1622, 542, 1622, " + "542, 472, 542, 1622, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 1622, 542, 1622, 542, 1622, 542, 1622, " + "542, 1622, 542, 1622, 542, 1622, 542, 1622, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 1622, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 1622, 542, 7048, 4400, 4300, " + "542, 1622, 542, 1622, 542, 1622, 542, 1622, 542, 472, 542, 472, " + "542, 1622, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 1622, 542, 1622, 542, 472, 542, 1622, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 1622, 542, 1622, " + "542, 1622, 542, 1622, 542, 1622, 542, 1622, 542, 1622, 542, 1622, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 1622, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 472, " + "542, 472, 542, 472, 542, 472, 542, 472, 542, 472, 542, 1622, " + "542, 7048 }; // TOSHIBA_AC\n" + "uint8_t state[9] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, " + "0x01};\n", + resultToSourceCode(&irsend.capture)); +} + +TEST(TestResultToTimingInfo, General) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + irsend.reset(); + irsend.sendNEC(irsend.encodeNEC(0x10, 0x20)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(NEC, irsend.capture.decode_type); + ASSERT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ( + "Raw Timing[68]:\n" + " + 8960, - 4480, + 560, - 560, + 560, - 560," + " + 560, - 560, \n" + " + 560, - 560, + 560, - 1680, + 560, - 560," + " + 560, - 560, \n" + " + 560, - 560, + 560, - 1680, + 560, - 1680," + " + 560, - 1680, \n" + " + 560, - 1680, + 560, - 560, + 560, - 1680," + " + 560, - 1680, \n" + " + 560, - 1680, + 560, - 560, + 560, - 560," + " + 560, - 560, \n" + " + 560, - 560, + 560, - 560, + 560, - 1680," + " + 560, - 560, \n" + " + 560, - 560, + 560, - 1680, + 560, - 1680," + " + 560, - 1680, \n" + " + 560, - 1680, + 560, - 1680, + 560, - 560," + " + 560, - 1680, \n" + " + 560, - 1680, + 560, - 40320\n", + resultToTimingInfo(&irsend.capture)); + + irsend.reset(); + uint16_t rawData[9] = {10, 20, 30, 40, 50, 60, 70, 80, 90}; + irsend.sendRaw(rawData, 9, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ( + "Raw Timing[9]:\n" + " + 10, - 20, + 30, - 40, + 50, - 60," + " + 70, - 80, \n" + " + 90\n", + resultToTimingInfo(&irsend.capture)); +} + +TEST(TestResultToHumanReadableBasic, SimpleCodes) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + irsend.reset(); + irsend.sendNEC(irsend.encodeNEC(0x10, 0x20)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(NEC, irsend.capture.decode_type); + ASSERT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ( + "Encoding : NEC\n" + "Code : 8F704FB (32 bits)\n", + resultToHumanReadableBasic(&irsend.capture)); +} + +TEST(TestResultToHumanReadableBasic, ComplexCodes) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + uint8_t state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x01}; + + irsend.reset(); + irsend.sendToshibaAC(state); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + EXPECT_EQ( + "Encoding : TOSHIBA_AC\n" + "Code : F20D03FC0100000001 (72 bits)\n", + resultToHumanReadableBasic(&irsend.capture)); +} + +TEST(TestInvertBits, Normal) { + ASSERT_EQ(0xAAAA5555AAAA5555, invertBits(0x5555AAAA5555AAAA, 64)); + ASSERT_EQ(0xAAAA5555, invertBits(0x5555AAAA, 32)); + ASSERT_EQ(0xFFFFFFFFFFFFFFFF, invertBits(0x0, 64)); + ASSERT_EQ(0x0, invertBits(invertBits(0x0, 64), 64)); + ASSERT_EQ(0x2, invertBits(0x1, 2)); +} + +TEST(TestInvertBits, ZeroBits) { + ASSERT_EQ(0xAAAA5555AAAA5555, invertBits(0xAAAA5555AAAA5555, 0)); + ASSERT_EQ(0x0, invertBits(0x0, 0)); + ASSERT_EQ(0x1, invertBits(0x1, 0)); +} + +TEST(TestInvertBits, MoreThan64Bits) { + ASSERT_EQ(0xAAAA5555AAAA5555, invertBits(0x5555AAAA5555AAAA, 70)); + ASSERT_EQ(0xFFFFFFFFFFFFFFFF, invertBits(0x0, 128)); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/Makefile b/lib/IRremoteESP8266-2.5.2.03/test/Makefile similarity index 63% rename from lib/IRremoteESP8266-2.2.1.02/test/Makefile rename to lib/IRremoteESP8266-2.5.2.03/test/Makefile index 7ffd00053..d53014183 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/Makefile +++ b/lib/IRremoteESP8266-2.5.2.03/test/Makefile @@ -1,8 +1,10 @@ # SYNOPSIS: # -# make [all] - makes everything. -# make TARGET - makes the given target. -# make clean - removes all files generated by make. +# make [all] - makes everything. +# make TARGET - makes the given target. +# make run - makes everything and runs all the tests. +# make clean - removes all files generated by make. +# make install-googletest - install the googletest code suite # Please tweak the following variable definitions as needed by your # project, except GTEST_HEADERS, which you can use in your own targets @@ -30,7 +32,11 @@ TESTS = IRutils_test IRsend_test ir_NEC_test ir_GlobalCache_test \ ir_JVC_test ir_RCMM_test ir_LG_test ir_Mitsubishi_test ir_Sharp_test \ ir_RC5_RC6_test ir_Panasonic_test ir_Dish_test ir_Whynter_test \ ir_Aiwa_test ir_Denon_test ir_Sanyo_test ir_Daikin_test ir_Coolix_test \ - ir_Gree_test IRrecv_test ir_Pronto_test ir_Fujitsu_test ir_Nikai_test + ir_Gree_test IRrecv_test ir_Pronto_test ir_Fujitsu_test ir_Nikai_test \ + ir_Toshiba_test ir_Midea_test ir_Magiquest_test ir_Lasertag_test \ + ir_Carrier_test ir_Haier_test ir_Hitachi_test ir_GICable_test \ + ir_Whirlpool_test ir_Lutron_test ir_Electra_test ir_Pioneer_test \ + ir_MWM_test # All Google Test headers. Usually you shouldn't change this # definition. @@ -56,8 +62,10 @@ run : all echo "PASS: \o/ \o/ All unit tests passed. \o/ \o/"; \ fi +run_tests : run + install-googletest : - git clone https://github.com/google/googletest.git ../lib/googletest + git clone -b v1.8.x https://github.com/google/googletest.git ../lib/googletest # Builds gtest.a and gtest_main.a. @@ -67,17 +75,40 @@ GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) # All the IR protocol object files. PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \ - ir_LG.o ir_Mitsubishi.o ir_Fujitsu.o ir_Sharp.o ir_Sanyo.o ir_Denon.o ir_Dish.o \ - ir_Panasonic.o ir_Whynter.o ir_Coolix.o ir_Aiwa.o ir_Sherwood.o \ - ir_Kelvinator.o ir_Daikin.o ir_Gree.o ir_Pronto.o ir_Nikai.o + ir_LG.o ir_Mitsubishi.o ir_Fujitsu.o ir_Sharp.o ir_Sanyo.o ir_Denon.o ir_Dish.o \ + ir_Panasonic.o ir_Whynter.o ir_Coolix.o ir_Aiwa.o ir_Sherwood.o \ + ir_Kelvinator.o ir_Daikin.o ir_Gree.o ir_Pronto.o ir_Nikai.o ir_Toshiba.o \ + ir_Midea.o ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o \ + ir_Hitachi.o ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o \ + ir_Pioneer.o ir_MWM.o + +# All the IR Protocol header files. +PROTOCOLS_H = $(USER_DIR)/ir_Argo.h \ + $(USER_DIR)/ir_Gree.h \ + $(USER_DIR)/ir_Magiquest.h \ + $(USER_DIR)/ir_Coolix.h \ + $(USER_DIR)/ir_Haier.h \ + $(USER_DIR)/ir_Midea.h \ + $(USER_DIR)/ir_Toshiba.h \ + $(USER_DIR)/ir_Daikin.h \ + $(USER_DIR)/ir_Kelvinator.h \ + $(USER_DIR)/ir_Mitsubishi.h \ + $(USER_DIR)/ir_NEC.h \ + $(USER_DIR)/ir_Samsung.h \ + $(USER_DIR)/ir_Trotec.h \ + $(USER_DIR)/ir_Fujitsu.h \ + $(USER_DIR)/ir_LG.h \ + $(USER_DIR)/ir_Panasonic.h # Common object files COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o ir_GlobalCache.o \ $(PROTOCOLS) gtest_main.a # Common dependencies COMMON_DEPS = $(USER_DIR)/IRrecv.h $(USER_DIR)/IRsend.h $(USER_DIR)/IRtimer.h \ - $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h + $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h \ + $(PROTOCOLS_H) + # Common test dependencies -COMMON_TEST_DEPS = $(COMMON_DEPS) IRsend_test.h +COMMON_TEST_DEPS = $(COMMON_DEPS) IRrecv_test.h IRsend_test.h # For simplicity and to avoid depending on Google Test's # implementation details, the dependencies specified below are @@ -97,17 +128,17 @@ gtest.a : gtest-all.o gtest_main.a : gtest-all.o gtest_main.o $(AR) $(ARFLAGS) $@ $^ -# Builds a our test. A test should link with either gtest.a or +# Builds our test. A test should link with either gtest.a or # gtest_main.a, depending on whether it defines its own main() # function. -IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h +IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRutils.cpp -IRutils_test.o : IRutils_test.cpp $(USER_DIR)/IRutils.h $(GTEST_HEADERS) +IRutils_test.o : IRutils_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c IRutils_test.cpp -IRutils_test : IRutils.o IRutils_test.o gtest_main.a +IRutils_test : IRutils_test.o ir_NEC.o ir_Nikai.o ir_Toshiba.o $(COMMON_OBJ) gtest_main.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ IRtimer.o : $(USER_DIR)/IRtimer.cpp $(USER_DIR)/IRtimer.h @@ -131,7 +162,7 @@ IRrecv_test.o : IRrecv_test.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRrecv.h IRsend IRrecv_test : IRrecv_test.o $(COMMON_OBJ) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ -ir_NEC.o : $(USER_DIR)/ir_NEC.cpp $(COMMON_DEPS) +ir_NEC.o : $(USER_DIR)/ir_NEC.cpp $(USER_DIR)/ir_NEC.h $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_NEC.cpp ir_NEC_test.o : ir_NEC_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) @@ -167,10 +198,10 @@ ir_Sony_test.o : ir_Sony_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) ir_Sony_test : $(COMMON_OBJ) ir_Sony_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ -ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(COMMON_DEPS) +ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(USER_DIR)/ir_Samsung.h $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Samsung.cpp -ir_Samsung_test.o : ir_Samsung_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) +ir_Samsung_test.o : ir_Samsung_test.cpp $(USER_DIR)/ir_Samsung.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Samsung_test.cpp ir_Samsung_test : $(COMMON_OBJ) ir_Samsung_test.o @@ -278,7 +309,7 @@ ir_Whynter_test : $(COMMON_OBJ) ir_Whynter_test.o ir_Coolix.o : $(USER_DIR)/ir_Coolix.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Coolix.cpp -ir_Coolix_test.o : ir_Coolix_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) +ir_Coolix_test.o : ir_Coolix_test.cpp $(USER_DIR)/ir_Coolix.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Coolix_test.cpp ir_Coolix_test : $(COMMON_OBJ) ir_Coolix_test.o @@ -326,7 +357,7 @@ ir_Gree.o : $(USER_DIR)/ir_Gree.cpp $(GTEST_HEADERS) ir_Gree_test.o : ir_Gree_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Gree_test.cpp -ir_Gree_test : $(COMMON_OBJ) ir_Gree_test.o +ir_Gree_test : $(COMMON_OBJ) ir_Gree_test.o ir_Kelvinator.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Pronto.o : $(USER_DIR)/ir_Pronto.cpp $(GTEST_HEADERS) @@ -346,3 +377,120 @@ ir_Nikai_test.o : ir_Nikai_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) ir_Nikai_test : $(COMMON_OBJ) ir_Nikai_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Toshiba.o : $(USER_DIR)/ir_Toshiba.cpp $(USER_DIR)/ir_Toshiba.h $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Toshiba.cpp + +ir_Toshiba_test.o : ir_Toshiba_test.cpp $(USER_DIR)/ir_Toshiba.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Toshiba_test.cpp + +ir_Toshiba_test : $(COMMON_OBJ) ir_Toshiba_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Midea.o : $(USER_DIR)/ir_Midea.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Midea.cpp + +ir_Midea_test.o : ir_Midea_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Midea_test.cpp + +ir_Midea_test : $(COMMON_OBJ) ir_Midea_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Magiquest.o : $(USER_DIR)/ir_Magiquest.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Magiquest.cpp + +ir_Magiquest_test.o : ir_Magiquest_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Magiquest_test.cpp + +ir_Magiquest_test : $(COMMON_OBJ) ir_Magiquest_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Lasertag.o : $(USER_DIR)/ir_Lasertag.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lasertag.cpp + +ir_Lasertag_test.o : ir_Lasertag_test.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Lasertag_test.cpp + +ir_Lasertag_test : $(COMMON_OBJ) ir_Lasertag_test.o ir_RC5_RC6.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Carrier.o : $(USER_DIR)/ir_Carrier.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Carrier.cpp + +ir_Carrier_test.o : ir_Carrier_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Carrier_test.cpp + +ir_Carrier_test : $(COMMON_OBJ) ir_Carrier_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Haier.o : $(USER_DIR)/ir_Haier.cpp $(USER_DIR)/ir_Haier.h $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Haier.cpp + +ir_Haier_test.o : ir_Haier_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Haier_test.cpp + +ir_Haier_test : $(COMMON_OBJ) ir_Haier_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Hitachi.o : $(USER_DIR)/ir_Hitachi.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Hitachi.cpp + +ir_Hitachi_test.o : ir_Hitachi_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Hitachi_test.cpp + +ir_Hitachi_test : $(COMMON_OBJ) ir_Hitachi_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_GICable.o : $(USER_DIR)/ir_GICable.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_GICable.cpp + +ir_GICable_test.o : ir_GICable_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_GICable_test.cpp + +ir_GICable_test : $(COMMON_OBJ) ir_GICable_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Whirlpool.o : $(USER_DIR)/ir_Whirlpool.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whirlpool.cpp + +ir_Whirlpool_test.o : ir_Whirlpool_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Whirlpool_test.cpp + +ir_Whirlpool_test : $(COMMON_OBJ) ir_Whirlpool_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Lutron.o : $(USER_DIR)/ir_Lutron.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lutron.cpp + +ir_Lutron_test.o : ir_Lutron_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Lutron_test.cpp + +ir_Lutron_test : $(COMMON_OBJ) ir_Lutron_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Electra.o : $(USER_DIR)/ir_Electra.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Electra.cpp + +ir_Electra_test.o : ir_Electra_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Electra_test.cpp + +ir_Electra_test : $(COMMON_OBJ) ir_Electra_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Pioneer.o : $(USER_DIR)/ir_Pioneer.cpp $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Pioneer.cpp + +ir_Pioneer_test.o : ir_Pioneer_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Pioneer_test.cpp + +ir_Pioneer_test : $(COMMON_OBJ) ir_Pioneer_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_MWM.o : $(USER_DIR)/ir_MWM.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_MWM.cpp + +ir_MWM_test.o : ir_MWM_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_MWM_test.cpp + +ir_MWM_test : $(COMMON_OBJ) ir_MWM_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Aiwa_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Aiwa_test.cpp similarity index 70% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Aiwa_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Aiwa_test.cpp index a0bb12f86..c5469d4a5 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Aiwa_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Aiwa_test.cpp @@ -20,8 +20,9 @@ TEST(TestSendAiwa, SendDataOnly) { "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); + "m560s1680m560s1680m560s23520" + "m8960s2240m560s96320", + irsend.outputStr()); } // Test sending oversized data. @@ -40,7 +41,7 @@ TEST(TestSendAiwa, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendAiwaRCT501(0x7F, AIWA_RC_T501_BITS, 0); // No repeats. + irsend.sendAiwaRCT501(0x7F, kAiwaRcT501Bits, 0); // No repeats. EXPECT_EQ( "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" @@ -48,9 +49,10 @@ TEST(TestSendAiwa, SendWithRepeats) { "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s108080", irsend.outputStr()); + "m560s1680m560s1680m560s23520", + irsend.outputStr()); irsend.reset(); - irsend.sendAiwaRCT501(0x7F, AIWA_RC_T501_BITS, 1); // 1 repeat. + irsend.sendAiwaRCT501(0x7F, kAiwaRcT501Bits, 1); // 1 repeat. EXPECT_EQ( "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" @@ -58,10 +60,11 @@ TEST(TestSendAiwa, SendWithRepeats) { "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); + "m560s1680m560s1680m560s23520" + "m8960s2240m560s96320", + irsend.outputStr()); irsend.reset(); - irsend.sendAiwaRCT501(0x7F, AIWA_RC_T501_BITS, 2); // 2 repeats. + irsend.sendAiwaRCT501(0x7F, kAiwaRcT501Bits, 2); // 2 repeats. EXPECT_EQ( "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" @@ -69,13 +72,14 @@ TEST(TestSendAiwa, SendWithRepeats) { "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s108080" - "m8960s2240m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); + "m560s1680m560s1680m560s23520" + "m8960s2240m560s96320" + "m8960s2240m560s96320", + irsend.outputStr()); } // Test sending an atypical data size. -TEST(TestSendAiwa, SendUsualSize) { +TEST(TestSendAiwa, SendUnusualSize) { IRsendTest irsend(4); irsend.begin(); @@ -87,8 +91,9 @@ TEST(TestSendAiwa, SendUsualSize) { "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s1680m560s560m560s560" - "m560s1680m560s560m560s1680m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); + "m560s1680m560s560m560s1680m560s36960" + "m8960s2240m560s96320", + irsend.outputStr()); irsend.reset(); irsend.sendAiwaRCT501(0x1234567890, 37); @@ -102,8 +107,9 @@ TEST(TestSendAiwa, SendUsualSize) { "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s560m560s560" "m560s1680m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s1680" "m560s560m560s560m560s1680m560s560m560s560m560s560m560s560m560s1680" - "m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); + "m560s22400" + "m8960s2240m560s96320", + irsend.outputStr()); } // Tests for decodeAiwaRCT501(). @@ -118,10 +124,9 @@ TEST(TestDecodeAiwa, NormalDecodeWithStrict) { irsend.reset(); irsend.sendAiwaRCT501(0x7F); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); - EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7F, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -131,10 +136,9 @@ TEST(TestDecodeAiwa, NormalDecodeWithStrict) { irsend.reset(); irsend.sendAiwaRCT501(0x0); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); - EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -144,10 +148,9 @@ TEST(TestDecodeAiwa, NormalDecodeWithStrict) { irsend.reset(); irsend.sendAiwaRCT501(0x7FFF); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); - EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7FFF, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -162,12 +165,11 @@ TEST(TestDecodeAiwa, NormalDecodeWithRepeatAndStrict) { // Normal Aiwa 15-bit(42bit) message with 2 repeats. irsend.reset(); - irsend.sendAiwaRCT501(0x7F, AIWA_RC_T501_BITS, 2); + irsend.sendAiwaRCT501(0x7F, kAiwaRcT501Bits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); - EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7F, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -182,48 +184,44 @@ TEST(TestDecodeAiwa, DecodeWithNonStrictValues) { irsend.reset(); // Confirm using sendNEC(data, 42, 1) can make a legal Aiwa message. - irsend.sendNEC(0x1D8113F00FF, 42, AIWA_RC_T501_MIN_REPEAT); + irsend.sendNEC(0x1D8113F00FF, 42, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // MUST pass with strict on. - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); ASSERT_EQ(0x7F, irsend.capture.value); irsend.reset(); // Use sendNEC(data, 42) to make/send an illegal value Aiwa message. // Value is illegal due to bad pre & post data. - irsend.sendNEC(0x1234567890A, 42, AIWA_RC_T501_MIN_REPEAT); + irsend.sendNEC(0x1234567890A, 42, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); // Should fail if strict off too. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - false)); + ASSERT_FALSE( + irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, false)); irsend.reset(); // Use sendNEC(data, 42) to make/send an illegal value Aiwa message. // Value is illegal due to bad post data only. - irsend.sendNEC(0x1D8113F00FE, 42, AIWA_RC_T501_MIN_REPEAT); + irsend.sendNEC(0x1D8113F00FE, 42, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); // Should fail if strict off too. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - false)); + ASSERT_FALSE( + irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, false)); irsend.reset(); // Use sendNEC(data, 42) to make/send an illegal value Aiwa message. // Value is illegal due to bad pre data only. - irsend.sendNEC(0x0D8113F00FF, 42, AIWA_RC_T501_MIN_REPEAT); + irsend.sendNEC(0x0D8113F00FF, 42, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); // Should fail if strict off too. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - false)); + ASSERT_FALSE( + irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, false)); } // Decode unsupported Aiwa messages. @@ -236,8 +234,7 @@ TEST(TestDecodeAiwa, DecodeWithNonStrictSizes) { irsend.sendAiwaRCT501(0x0, 8); // Illegal size Aiwa 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, 8, false)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); @@ -248,8 +245,7 @@ TEST(TestDecodeAiwa, DecodeWithNonStrictSizes) { irsend.sendAiwaRCT501(0x12345678, 32); // Illegal size Aiwa 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); // Should fail with strict when we ask for the wrong bit size. ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, 32, true)); @@ -278,7 +274,7 @@ TEST(TestDecodeAiwa, Decode64BitMessages) { // Reconfirm it by sending a true 64bit NEC message with the Aiwa prefix. irsend.reset(); - irsend.sendNEC(0x76044FFFFFFFFFFF, 64, AIWA_RC_T501_MIN_REPEAT); + irsend.sendNEC(0x76044FFFFFFFFFFF, 64, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // Should work with a 'normal' match (not strict) ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, 37, false)); @@ -295,20 +291,19 @@ TEST(TestDecodeAiwa, DecodeGlobalCacheExample) { irsend.reset(); // Aiwa Power Toggle from Global Cache. - uint16_t gc_test[95] = {38000, 1, 89, 342, 171, 21, 21, 21, 64, 21, 64, - 21, 64, 21, 21, 21, 64, 21, 64, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 64, 21, 21, - 21, 21, 21, 21, 21, 64, 21, 21, 21, 21, 21, 64, - 21, 64, 21, 64, 21, 64, 21, 64, 21, 64, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 64, 21, 64, 21, 64, 21, 64, 21, 64, - 21, 64, 21, 64, 21, 64, 21, 875, 342, 171, 21, 3565}; + uint16_t gc_test[95] = { + 38000, 1, 89, 342, 171, 21, 21, 21, 64, 21, 64, 21, 64, 21, 21, 21, + 64, 21, 64, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 64, 21, 21, 21, 21, 21, 21, 21, 64, 21, 21, 21, 21, 21, 64, 21, + 64, 21, 64, 21, 64, 21, 64, 21, 64, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 64, 21, 64, 21, 64, 21, + 64, 21, 64, 21, 64, 21, 64, 21, 64, 21, 875, 342, 171, 21, 3565}; irsend.sendGC(gc_test, 95); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); - EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7F, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -326,13 +321,14 @@ TEST(TestDecodeAiwa, FailToDecodeNonAiwaExample) { irsend.begin(); irsend.reset(); - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, - false)); + ASSERT_FALSE( + irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, false)); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Carrier_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Carrier_test.cpp new file mode 100644 index 000000000..24bdc232a --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Carrier_test.cpp @@ -0,0 +1,225 @@ +// Copyright 2018 David Conran + +#include "IRrecv.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendCarrierAC() + +// Test sending typical data only. +TEST(TestSendCarrierAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendCarrierAC(0x0); + EXPECT_EQ( + "m8532s4228" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320" + "m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320" + "m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320" + "m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320m628s1320" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" + "m628s20000", + irsend.outputStr()); + irsend.reset(); + irsend.sendCarrierAC(0x12345678); + EXPECT_EQ( + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s1320m628s1320m628s1320m628s532m628s1320m628s1320m628s532m628s1320" + "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s1320" + "m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s532m628s1320" + "m628s1320m628s532m628s532m628s532m628s532m628s1320m628s1320m628s1320" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000", + irsend.outputStr()); + + irsend.reset(); + irsend.sendCarrierAC(0x4CCA541D); + EXPECT_EQ( + "m8532s4228" + "m628s532m628s1320m628s532m628s532m628s1320m628s1320m628s532m628s532" + "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s532m628s532m628s1320m628s1320m628s1320m628s532m628s1320" + "m628s20000" + "m8532s4228" + "m628s1320m628s532m628s1320m628s1320m628s532m628s532m628s1320m628s1320" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s1320" + "m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320" + "m628s1320m628s1320m628s1320m628s532m628s532m628s532m628s1320m628s532" + "m628s20000" + "m8532s4228" + "m628s532m628s1320m628s532m628s532m628s1320m628s1320m628s532m628s532" + "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s532m628s532m628s1320m628s1320m628s1320m628s532m628s1320" + "m628s20000", + irsend.outputStr()); +} + +// Test sending typical data only. +TEST(TestSendCarrierAC, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendCarrierAC(0x12345678, kCarrierAcBits, 2); // two repeats. + EXPECT_EQ( + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s1320m628s1320m628s1320m628s532m628s1320m628s1320m628s532m628s1320" + "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s1320" + "m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s532m628s1320" + "m628s1320m628s532m628s532m628s532m628s532m628s1320m628s1320m628s1320" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s1320m628s1320m628s1320m628s532m628s1320m628s1320m628s532m628s1320" + "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s1320" + "m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s532m628s1320" + "m628s1320m628s532m628s532m628s532m628s532m628s1320m628s1320m628s1320" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000" + "m8532s4228" + "m628s1320m628s1320m628s1320m628s532m628s1320m628s1320m628s532m628s1320" + "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s1320" + "m628s1320m628s532m628s1320m628s532m628s1320m628s532m628s532m628s1320" + "m628s1320m628s532m628s532m628s532m628s532m628s1320m628s1320m628s1320" + "m628s20000" + "m8532s4228" + "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" + "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" + "m628s532m628s1320m628s532m628s1320m628s532m628s1320m628s1320m628s532" + "m628s532m628s1320m628s1320m628s1320m628s1320m628s532m628s532m628s532" + "m628s20000", + irsend.outputStr()); +} + +// Tests for decodeCarrierAC(). + +// Decode normal "synthetic" messages. +TEST(TestDecodeCarrierAC, NormalDecodeWithStrict) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendCarrierAC(0x0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeCarrierAC(&irsend.capture, kCarrierAcBits, true)); + EXPECT_EQ(CARRIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kCarrierAcBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendCarrierAC(0xB335ABE2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeCarrierAC(&irsend.capture, kCarrierAcBits, true)); + EXPECT_EQ(CARRIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kCarrierAcBits, irsend.capture.bits); + EXPECT_EQ(0xB335ABE2, irsend.capture.value); + EXPECT_EQ(0xB335, irsend.capture.address); + EXPECT_EQ(0xABE2, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Do the last one again, & use the full decoder, not just protocol specific. + irsend.reset(); + irsend.sendCarrierAC(0xB335ABE2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(CARRIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kCarrierAcBits, irsend.capture.bits); + EXPECT_EQ(0xB335ABE2, irsend.capture.value); +} + +// Decode a "real" example message. +TEST(TestDecodeCarrierAC, RealExamples) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Data from Issue #385 captured by gnkarn + uint16_t rawData[203] = { + 8532, 4216, 628, 1312, 628, 528, 628, 1312, 628, 1312, 628, 528, + 628, 524, 628, 1316, 624, 1316, 628, 524, 628, 528, 628, 1312, + 628, 1316, 624, 528, 628, 1312, 628, 528, 628, 1312, 628, 1312, + 628, 528, 628, 1316, 624, 528, 628, 1312, 628, 528, 628, 1312, + 628, 1316, 624, 1316, 628, 1312, 628, 1316, 628, 524, 628, 528, + 628, 528, 624, 1316, 628, 528, 628, 20064, 8504, 4228, 628, 528, + 628, 1312, 628, 528, 628, 528, 628, 1312, 628, 1316, 624, 532, + 624, 528, 628, 1316, 628, 1312, 628, 528, 628, 528, 628, 1312, + 628, 528, 628, 1316, 628, 528, 624, 528, 628, 1316, 628, 528, + 628, 1316, 624, 528, 628, 1316, 628, 528, 624, 532, 624, 528, + 628, 528, 628, 528, 628, 1316, 624, 1316, 628, 1316, 628, 528, + 624, 1316, 628, 20076, 8528, 4212, 624, 1316, 628, 528, 628, 1316, + 628, 1316, 624, 528, 628, 528, 628, 1316, 628, 1316, 628, 528, + 624, 532, 624, 1316, 628, 1316, 628, 528, 628, 1316, 624, 528, + 628, 1316, 628, 1316, 628, 528, 628, 1316, 624, 532, 624, 1316, + 628, 532, 624, 1316, 628, 1316, 624, 1320, 624, 1316, 628, 1316, + 628, 528, 628, 528, 628, 528, 628, 1316, 624, 532, 624}; + + irsend.sendRaw(rawData, 203, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(CARRIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kCarrierAcBits, irsend.capture.bits); + EXPECT_EQ(0xB335ABE2, irsend.capture.value); + EXPECT_EQ(0xB335, irsend.capture.address); + EXPECT_EQ(0xABE2, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Coolix_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Coolix_test.cpp similarity index 60% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Coolix_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Coolix_test.cpp index 14eb8d661..8b096ffca 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Coolix_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Coolix_test.cpp @@ -1,5 +1,6 @@ -// Copyright 2017 David Conran +// Copyright 2017-2018 David Conran +#include "ir_Coolix.h" #include "IRsend.h" #include "IRsend_test.h" #include "gtest/gtest.h" @@ -21,7 +22,8 @@ TEST(TestSendCoolix, SendDataOnly) { "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s5040", irsend.outputStr()); + "m560s5040", + irsend.outputStr()); irsend.reset(); irsend.sendCOOLIX(0xAA55AA); @@ -33,7 +35,8 @@ TEST(TestSendCoolix, SendDataOnly) { "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s5040", irsend.outputStr()); + "m560s5040", + irsend.outputStr()); irsend.reset(); irsend.sendCOOLIX(0xFFFFFF); @@ -45,7 +48,8 @@ TEST(TestSendCoolix, SendDataOnly) { "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s5040", irsend.outputStr()); + "m560s5040", + irsend.outputStr()); } // Test sending with different repeats. @@ -54,7 +58,7 @@ TEST(TestSendCoolix, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendCOOLIX(0xAA55AA, COOLIX_BITS, 1); // 1 repeat. + irsend.sendCOOLIX(0xAA55AA, kCoolixBits, 1); // 1 repeat. EXPECT_EQ( "m4480s4480" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" @@ -71,8 +75,9 @@ TEST(TestSendCoolix, SendWithRepeats) { "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s5040", irsend.outputStr()); - irsend.sendCOOLIX(0xAA55AA, COOLIX_BITS, 2); // 2 repeats. + "m560s5040", + irsend.outputStr()); + irsend.sendCOOLIX(0xAA55AA, kCoolixBits, 2); // 2 repeats. EXPECT_EQ( "m4480s4480" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" @@ -97,11 +102,12 @@ TEST(TestSendCoolix, SendWithRepeats) { "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" - "m560s5040", irsend.outputStr()); + "m560s5040", + irsend.outputStr()); } // Test sending an atypical data size. -TEST(TestSendCoolix, SendUsualSize) { +TEST(TestSendCoolix, SendUnusualSize) { IRsendTest irsend(4); irsend.begin(); @@ -111,7 +117,8 @@ TEST(TestSendCoolix, SendUsualSize) { "m4480s4480" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s5040", irsend.outputStr()); + "m560s5040", + irsend.outputStr()); irsend.reset(); irsend.sendCOOLIX(0x1234567890ABCDEF, 64); @@ -133,12 +140,13 @@ TEST(TestSendCoolix, SendUsualSize) { "m560s560m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" "m560s560m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" - "m560s5040", irsend.outputStr()); + "m560s5040", + irsend.outputStr()); // Bit sizes must be a multiple of 8. irsend.reset(); irsend.sendCOOLIX(0x0, 17); - EXPECT_EQ("" , irsend.outputStr()); + EXPECT_EQ("", irsend.outputStr()); } // Tests for decodeCOOLIX(). @@ -153,9 +161,9 @@ TEST(TestDecodeCoolix, NormalDecodeWithStrict) { irsend.reset(); irsend.sendCOOLIX(0x123456); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -165,9 +173,9 @@ TEST(TestDecodeCoolix, NormalDecodeWithStrict) { irsend.reset(); irsend.sendCOOLIX(0x0); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -177,9 +185,9 @@ TEST(TestDecodeCoolix, NormalDecodeWithStrict) { irsend.reset(); irsend.sendCOOLIX(0xFFFFFF); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0xFFFFFF, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -194,24 +202,24 @@ TEST(TestDecodeCoolix, NormalDecodeWithRepeatAndStrict) { // Normal Coolix 16-bit message with 2 repeats. irsend.reset(); - irsend.sendCOOLIX(0x123456, COOLIX_BITS, 2); + irsend.sendCOOLIX(0x123456, kCoolixBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); EXPECT_FALSE(irsend.capture.repeat); - irsend.makeDecodeResult(4 * COOLIX_BITS + 4); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + irsend.makeDecodeResult(4 * kCoolixBits + 4); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); - irsend.makeDecodeResult(2 * (4 * COOLIX_BITS + 4)); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + irsend.makeDecodeResult(2 * (4 * kCoolixBits + 4)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); - EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); } @@ -225,7 +233,7 @@ TEST(TestDecodeCoolix, DecodeWithNonStrictSizes) { irsend.sendCOOLIX(0x12, 8); // Illegal value Coolix 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, 8, false)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); @@ -236,7 +244,7 @@ TEST(TestDecodeCoolix, DecodeWithNonStrictSizes) { irsend.sendCOOLIX(0x12345678, 32); // Illegal value Coolix 32-bit message. irsend.makeDecodeResult(); // Shouldn't pass with strict when we ask for less bits than we got. - ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -249,7 +257,7 @@ TEST(TestDecodeCoolix, DecodeWithNonStrictSizes) { // Decode should fail if asked to decode non-multiples of 8 bits. irsend.reset(); - irsend.sendCOOLIX(0x123456, COOLIX_BITS, 2); + irsend.sendCOOLIX(0x123456, kCoolixBits, 2); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, 9, false)); } @@ -279,12 +287,159 @@ TEST(TestDecodeCoolix, FailToDecodeNonCoolixExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, false)); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, false)); +} + +// Tests for the IRCoolixAC class. + +TEST(TestCoolixACClass, SetAndGetRaw) { + IRCoolixAC ircoolix(0); + + ircoolix.setRaw(kCoolixOff); + EXPECT_EQ(kCoolixOff, ircoolix.getRaw()); + ircoolix.setRaw(kCoolixDefaultState); + EXPECT_EQ(kCoolixDefaultState, ircoolix.getRaw()); +} + +TEST(TestCoolixACClass, SetAndGetTemp) { + IRCoolixAC ircoolix(0); + + ircoolix.setTemp(25); + EXPECT_EQ(25, ircoolix.getTemp()); + ircoolix.setTemp(kCoolixTempMin); + EXPECT_EQ(kCoolixTempMin, ircoolix.getTemp()); + ircoolix.setTemp(kCoolixTempMax); + EXPECT_EQ(kCoolixTempMax, ircoolix.getTemp()); + ircoolix.setTemp(kCoolixTempMin - 1); + EXPECT_EQ(kCoolixTempMin, ircoolix.getTemp()); + ircoolix.setTemp(kCoolixTempMax + 1); + EXPECT_EQ(kCoolixTempMax, ircoolix.getTemp()); +} + +TEST(TestCoolixACClass, SetAndGetMode) { + IRCoolixAC ircoolix(0); + + ircoolix.setMode(kCoolixHeat); + EXPECT_EQ(kCoolixHeat, ircoolix.getMode()); + ircoolix.setMode(kCoolixCool); + EXPECT_EQ(kCoolixCool, ircoolix.getMode()); + ircoolix.setMode(kCoolixDry); + EXPECT_EQ(kCoolixDry, ircoolix.getMode()); + ircoolix.setMode(kCoolixAuto); + EXPECT_EQ(kCoolixAuto, ircoolix.getMode()); + ircoolix.setMode(kCoolixFan); + EXPECT_EQ(kCoolixFan, ircoolix.getMode()); +} + +TEST(TestCoolixACClass, SetAndGetFan) { + IRCoolixAC ircoolix(0); + + ircoolix.setFan(kCoolixFanMax); + EXPECT_EQ(kCoolixFanMax, ircoolix.getFan()); + ircoolix.setFan(kCoolixFanMin); + EXPECT_EQ(kCoolixFanMin, ircoolix.getFan()); + ircoolix.setFan(kCoolixFanZoneFollow); + EXPECT_EQ(kCoolixFanZoneFollow, ircoolix.getFan()); + ircoolix.setFan(kCoolixFanAuto); + EXPECT_EQ(kCoolixFanAuto, ircoolix.getFan()); + ircoolix.setFan(kCoolixFanMax); + EXPECT_EQ(kCoolixFanMax, ircoolix.getFan()); + ASSERT_NE(3, kCoolixFanAuto); + // Now try some unexpected value. + ircoolix.setFan(3); + EXPECT_EQ(kCoolixFanAuto, ircoolix.getFan()); +} + +TEST(TestCoolixACClass, SetGetClearSensorTempAndZoneFollow) { + IRCoolixAC ircoolix(0); + + ircoolix.setRaw(kCoolixDefaultState); + EXPECT_FALSE(ircoolix.getZoneFollow()); + EXPECT_LT(kCoolixSensorTempMax, ircoolix.getSensorTemp()); + + ircoolix.setSensorTemp(25); + EXPECT_TRUE(ircoolix.getZoneFollow()); + EXPECT_EQ(25, ircoolix.getSensorTemp()); + + // Lower bounds + ircoolix.setSensorTemp(kCoolixSensorTempMin); + EXPECT_TRUE(ircoolix.getZoneFollow()); + EXPECT_EQ(kCoolixSensorTempMin, ircoolix.getSensorTemp()); + ircoolix.setSensorTemp(kCoolixSensorTempMin - 1); + EXPECT_TRUE(ircoolix.getZoneFollow()); + EXPECT_EQ(kCoolixSensorTempMin, ircoolix.getSensorTemp()); + // Upper bounds + ircoolix.setSensorTemp(kCoolixSensorTempMax); + EXPECT_TRUE(ircoolix.getZoneFollow()); + EXPECT_EQ(kCoolixSensorTempMax, ircoolix.getSensorTemp()); + ircoolix.setSensorTemp(kCoolixSensorTempMax + 1); + EXPECT_TRUE(ircoolix.getZoneFollow()); + EXPECT_EQ(kCoolixSensorTempMax, ircoolix.getSensorTemp()); + // Clearing + ircoolix.clearSensorTemp(); + EXPECT_FALSE(ircoolix.getZoneFollow()); + EXPECT_LT(kCoolixSensorTempMax, ircoolix.getSensorTemp()); +} + +TEST(TestCoolixACClass, SpecialModesAndReset) { + IRCoolixAC ircoolix(0); + ASSERT_NE(kCoolixSwing, ircoolix.getRaw()); + ircoolix.setSwing(); + ASSERT_EQ(kCoolixSwing, ircoolix.getRaw()); + ircoolix.setTurbo(); + ASSERT_EQ(kCoolixTurbo, ircoolix.getRaw()); + ircoolix.setSleep(); + ASSERT_EQ(kCoolixSleep, ircoolix.getRaw()); + ircoolix.setLed(); + ASSERT_EQ(kCoolixLed, ircoolix.getRaw()); + ircoolix.setClean(); + ASSERT_EQ(kCoolixClean, ircoolix.getRaw()); + ircoolix.stateReset(); + ASSERT_NE(kCoolixClean, ircoolix.getRaw()); +} + +TEST(TestCoolixACClass, HumanReadable) { + IRCoolixAC ircoolix(0); + + // Initial starting point. + EXPECT_EQ( + "Power: On, Fan: 5 (AUTO), Mode: 2 (AUTO), Temp: 25C, " + "Zone Follow: Off, Sensor Temp: Ignored", + ircoolix.toString()); + + ircoolix.setSensorTemp(24); + ircoolix.setTemp(22); + ircoolix.setMode(kCoolixCool); + ircoolix.setFan(kCoolixFanMin); + EXPECT_EQ( + "Power: On, Fan: 4 (MIN), Mode: 0 (COOL), Temp: 22C, " + "Zone Follow: On, Sensor Temp: 24C", + ircoolix.toString()); + ircoolix.setSwing(); + EXPECT_EQ("Power: On, Fan: 3 (UNKNOWN), Swing: Toggle", ircoolix.toString()); + ircoolix.setPower(false); + EXPECT_EQ("Power: Off", ircoolix.toString()); +} + +TEST(TestCoolixACClass, KnownExamples) { + IRCoolixAC ircoolix(0); + + ircoolix.setRaw(0b101100101011111111100100); + EXPECT_EQ( + "Power: On, Fan: 5 (AUTO), Mode: 4 (FAN), Zone Follow: Off, " + "Sensor Temp: Ignored", + ircoolix.toString()); + ircoolix.setRaw(0b101100101001111100000000); + EXPECT_EQ( + "Power: On, Fan: 4 (MIN), Mode: 0 (COOL), Temp: 17C, " + "Zone Follow: Off, Sensor Temp: Ignored", + ircoolix.toString()); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Daikin_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Daikin_test.cpp new file mode 100644 index 000000000..c8192fc82 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Daikin_test.cpp @@ -0,0 +1,838 @@ +// Copyright 2017 David Conran +#include "ir_Daikin.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendDaikin(). + +// Test sending typical data only. +TEST(TestSendDaikin, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t daikin_code[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3}; + + irsend.reset(); + irsend.sendDaikin(daikin_code); + EXPECT_EQ( + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" + "m428s29428", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendDaikin, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + uint8_t daikin_code[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3}; + irsend.reset(); + + irsend.sendDaikin(daikin_code, kDaikinStateLength, 1); + EXPECT_EQ( + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" + "m428s29428" + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" + "m428s29428", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendDaikin, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t daikin_short_code[kDaikinStateLength - 1] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00}; + + irsend.reset(); + irsend.sendDaikin(daikin_short_code, kDaikinStateLength - 1); + ASSERT_EQ("", irsend.outputStr()); + + uint8_t daikin_long_code[kDaikinStateLength + 1] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, 0xDA, + 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3, 0x11}; + irsend.reset(); + irsend.sendDaikin(daikin_long_code, kDaikinStateLength + 1); + ASSERT_EQ( + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s29428", + irsend.outputStr()); +} + +// Tests for IRDaikinESP class. + +TEST(TestDaikinClass, Power) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.on(); + EXPECT_TRUE(irdaikin.getPower()); + + irdaikin.off(); + EXPECT_FALSE(irdaikin.getPower()); + + irdaikin.setPower(true); + EXPECT_TRUE(irdaikin.getPower()); + + irdaikin.setPower(false); + EXPECT_FALSE(irdaikin.getPower()); +} + +TEST(TestDaikinClass, Temperature) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setTemp(0); + EXPECT_EQ(kDaikinMinTemp, irdaikin.getTemp()); + + irdaikin.setTemp(255); + EXPECT_EQ(kDaikinMaxTemp, irdaikin.getTemp()); + + irdaikin.setTemp(kDaikinMinTemp); + EXPECT_EQ(kDaikinMinTemp, irdaikin.getTemp()); + + irdaikin.setTemp(kDaikinMaxTemp); + EXPECT_EQ(kDaikinMaxTemp, irdaikin.getTemp()); + + irdaikin.setTemp(kDaikinMinTemp - 1); + EXPECT_EQ(kDaikinMinTemp, irdaikin.getTemp()); + + irdaikin.setTemp(kDaikinMaxTemp + 1); + EXPECT_EQ(kDaikinMaxTemp, irdaikin.getTemp()); + + irdaikin.setTemp(kDaikinMinTemp + 1); + EXPECT_EQ(kDaikinMinTemp + 1, irdaikin.getTemp()); + + irdaikin.setTemp(21); + EXPECT_EQ(21, irdaikin.getTemp()); + + irdaikin.setTemp(25); + EXPECT_EQ(25, irdaikin.getTemp()); + + irdaikin.setTemp(29); + EXPECT_EQ(29, irdaikin.getTemp()); +} + +TEST(TestDaikinClass, OperatingMode) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setMode(kDaikinAuto); + EXPECT_EQ(kDaikinAuto, irdaikin.getMode()); + + irdaikin.setMode(kDaikinCool); + EXPECT_EQ(kDaikinCool, irdaikin.getMode()); + + irdaikin.setMode(kDaikinHeat); + EXPECT_EQ(kDaikinHeat, irdaikin.getMode()); + + irdaikin.setMode(kDaikinDry); + EXPECT_EQ(kDaikinDry, irdaikin.getMode()); + + irdaikin.setMode(kDaikinFan); + EXPECT_EQ(kDaikinFan, irdaikin.getMode()); + + irdaikin.setMode(kDaikinFan + 1); + EXPECT_EQ(kDaikinAuto, irdaikin.getMode()); + + irdaikin.setMode(kDaikinAuto + 1); + EXPECT_EQ(kDaikinAuto, irdaikin.getMode()); + + irdaikin.setMode(255); + EXPECT_EQ(kDaikinAuto, irdaikin.getMode()); +} + +TEST(TestDaikinClass, VaneSwing) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setSwingHorizontal(true); + irdaikin.setSwingVertical(false); + + irdaikin.setSwingHorizontal(true); + EXPECT_TRUE(irdaikin.getSwingHorizontal()); + EXPECT_FALSE(irdaikin.getSwingVertical()); + + irdaikin.setSwingVertical(true); + EXPECT_TRUE(irdaikin.getSwingHorizontal()); + EXPECT_TRUE(irdaikin.getSwingVertical()); + + irdaikin.setSwingHorizontal(false); + EXPECT_FALSE(irdaikin.getSwingHorizontal()); + EXPECT_TRUE(irdaikin.getSwingVertical()); + + irdaikin.setSwingVertical(false); + EXPECT_FALSE(irdaikin.getSwingHorizontal()); + EXPECT_FALSE(irdaikin.getSwingVertical()); +} + +TEST(TestDaikinClass, QuietMode) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setQuiet(true); + EXPECT_TRUE(irdaikin.getQuiet()); + + irdaikin.setQuiet(false); + EXPECT_FALSE(irdaikin.getQuiet()); + + irdaikin.setQuiet(true); + EXPECT_TRUE(irdaikin.getQuiet()); + + // Setting Econo mode should NOT change out of quiet mode. + irdaikin.setEcono(true); + EXPECT_TRUE(irdaikin.getQuiet()); + irdaikin.setEcono(false); + EXPECT_TRUE(irdaikin.getQuiet()); + + // But setting Powerful mode should exit out of quiet mode. + irdaikin.setPowerful(true); + EXPECT_FALSE(irdaikin.getQuiet()); +} + +TEST(TestDaikinClass, PowerfulMode) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setPowerful(true); + EXPECT_TRUE(irdaikin.getPowerful()); + + irdaikin.setPowerful(false); + EXPECT_FALSE(irdaikin.getPowerful()); + + irdaikin.setPowerful(true); + EXPECT_TRUE(irdaikin.getPowerful()); + + irdaikin.setQuiet(true); + EXPECT_FALSE(irdaikin.getPowerful()); + + irdaikin.setPowerful(true); + irdaikin.setEcono(true); + EXPECT_FALSE(irdaikin.getPowerful()); +} + +TEST(TestDaikinClass, EconoMode) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setEcono(true); + EXPECT_TRUE(irdaikin.getEcono()); + + irdaikin.setEcono(false); + EXPECT_FALSE(irdaikin.getEcono()); + + irdaikin.setEcono(true); + EXPECT_TRUE(irdaikin.getEcono()); + + // Setting Quiet mode should NOT change out of Econo mode. + irdaikin.setQuiet(true); + EXPECT_TRUE(irdaikin.getEcono()); + irdaikin.setQuiet(false); + EXPECT_TRUE(irdaikin.getEcono()); + + // But setting Powerful mode should exit out of Econo mode. + irdaikin.setPowerful(true); + EXPECT_FALSE(irdaikin.getEcono()); +} + +TEST(TestDaikinClass, FanSpeed) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + // Unexpected value should default to Auto. + irdaikin.setFan(0); + EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); + + // Unexpected value should default to Auto. + irdaikin.setFan(255); + EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); + + irdaikin.setFan(kDaikinFanMax); + EXPECT_EQ(kDaikinFanMax, irdaikin.getFan()); + + // Beyond Max should default to Auto. + irdaikin.setFan(kDaikinFanMax + 1); + EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); + + irdaikin.setFan(kDaikinFanMax - 1); + EXPECT_EQ(kDaikinFanMax - 1, irdaikin.getFan()); + + irdaikin.setFan(kDaikinFanMin); + EXPECT_EQ(kDaikinFanMin, irdaikin.getFan()); + + irdaikin.setFan(kDaikinFanMin + 1); + EXPECT_EQ(kDaikinFanMin + 1, irdaikin.getFan()); + + // Beyond Min should default to Auto. + irdaikin.setFan(kDaikinFanMin - 1); + EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); + + irdaikin.setFan(3); + EXPECT_EQ(3, irdaikin.getFan()); + + irdaikin.setFan(kDaikinFanAuto); + EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); + + irdaikin.setFan(kDaikinFanQuiet); + EXPECT_EQ(kDaikinFanQuiet, irdaikin.getFan()); +} + +TEST(TestDaikinClass, CurrentTime) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setCurrentTime(0); // 00:00 + EXPECT_EQ(0, irdaikin.getCurrentTime()); + + irdaikin.setCurrentTime(754); // 12:34 + EXPECT_EQ(754, irdaikin.getCurrentTime()); + + irdaikin.setCurrentTime(1439); // 23:59 + EXPECT_EQ(1439, irdaikin.getCurrentTime()); +} + +TEST(TestDaikinClass, OnOffTimers) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + // Both timers turned off. + irdaikin.disableOnTimer(); + irdaikin.disableOffTimer(); + EXPECT_FALSE(irdaikin.getOnTimerEnabled()); + EXPECT_EQ(0x600, irdaikin.getOnTime()); + EXPECT_FALSE(irdaikin.getOffTimerEnabled()); + EXPECT_EQ(0x600, irdaikin.getOffTime()); + + // Turn on just the On Timer. + irdaikin.enableOnTimer(123); + EXPECT_TRUE(irdaikin.getOnTimerEnabled()); + EXPECT_EQ(123, irdaikin.getOnTime()); + EXPECT_FALSE(irdaikin.getOffTimerEnabled()); + EXPECT_EQ(0x600, irdaikin.getOffTime()); + + // Now turn on the Off Timer. + irdaikin.enableOffTimer(754); + EXPECT_TRUE(irdaikin.getOffTimerEnabled()); + EXPECT_EQ(754, irdaikin.getOffTime()); + EXPECT_TRUE(irdaikin.getOnTimerEnabled()); + EXPECT_EQ(123, irdaikin.getOnTime()); + + // Turn off the just the On Timer. + irdaikin.disableOnTimer(); + EXPECT_FALSE(irdaikin.getOnTimerEnabled()); + EXPECT_EQ(0x600, irdaikin.getOnTime()); + EXPECT_TRUE(irdaikin.getOffTimerEnabled()); + EXPECT_EQ(754, irdaikin.getOffTime()); + + // Now turn off the Off Timer. + irdaikin.disableOffTimer(); + EXPECT_FALSE(irdaikin.getOffTimerEnabled()); + EXPECT_EQ(0x600, irdaikin.getOffTime()); + EXPECT_FALSE(irdaikin.getOnTimerEnabled()); + EXPECT_EQ(0x600, irdaikin.getOnTime()); + + // Use some canary values around the timers to ensure no accidental + // bit flips happen. i.e. Neighbouring bytes in the state. + // (Found some during testing on systems with different endian-ness) + // Tests here to make sure it never happens again. + irdaikin.setSwingHorizontal(true); + irdaikin.setPowerful(true); + irdaikin.disableOffTimer(); + irdaikin.disableOnTimer(); + ASSERT_TRUE(irdaikin.getSwingHorizontal()); + ASSERT_TRUE(irdaikin.getPowerful()); + irdaikin.enableOnTimer(123); + irdaikin.enableOffTimer(456); + ASSERT_TRUE(irdaikin.getSwingHorizontal()); + ASSERT_TRUE(irdaikin.getPowerful()); + irdaikin.disableOffTimer(); + irdaikin.disableOnTimer(); + ASSERT_TRUE(irdaikin.getSwingHorizontal()); + ASSERT_TRUE(irdaikin.getPowerful()); + + irdaikin.setSwingHorizontal(false); + irdaikin.setPowerful(false); + irdaikin.disableOffTimer(); + irdaikin.disableOnTimer(); + ASSERT_FALSE(irdaikin.getSwingHorizontal()); + ASSERT_FALSE(irdaikin.getPowerful()); + irdaikin.enableOnTimer(123); + irdaikin.enableOffTimer(456); + ASSERT_FALSE(irdaikin.getSwingHorizontal()); + ASSERT_FALSE(irdaikin.getPowerful()); + irdaikin.disableOffTimer(); + irdaikin.disableOnTimer(); + ASSERT_FALSE(irdaikin.getSwingHorizontal()); + ASSERT_FALSE(irdaikin.getPowerful()); +} + +// Test Eye mode. +TEST(TestDaikinClass, EyeSetting) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + // The Eye setting is stored in the same byte as Econo mode. + // Econo mode tests are there to make sure it isn't harmed and vice-versa. + irdaikin.setEcono(false); + irdaikin.setEye(false); + ASSERT_FALSE(irdaikin.getEye()); + EXPECT_FALSE(irdaikin.getEcono()); + + irdaikin.setEye(true); + ASSERT_TRUE(irdaikin.getEye()); + EXPECT_FALSE(irdaikin.getEcono()); + + irdaikin.setEcono(false); + ASSERT_TRUE(irdaikin.getEye()); + EXPECT_FALSE(irdaikin.getEcono()); + + irdaikin.setEcono(true); + ASSERT_TRUE(irdaikin.getEye()); + EXPECT_TRUE(irdaikin.getEcono()); + + irdaikin.setEye(false); + ASSERT_FALSE(irdaikin.getEye()); + EXPECT_TRUE(irdaikin.getEcono()); +} + +// Test Mold mode. +TEST(TestDaikinClass, MoldSetting) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setMold(false); + ASSERT_FALSE(irdaikin.getMold()); + + irdaikin.setMold(true); + ASSERT_TRUE(irdaikin.getMold()); + + irdaikin.setMold(false); + ASSERT_FALSE(irdaikin.getMold()); +} + +// Test Sensor mode. +TEST(TestDaikinClass, SensorSetting) { + IRDaikinESP irdaikin(0); + irdaikin.begin(); + + irdaikin.setSensor(false); + ASSERT_FALSE(irdaikin.getSensor()); + + irdaikin.setSensor(true); + ASSERT_TRUE(irdaikin.getSensor()); + + irdaikin.setSensor(false); + ASSERT_FALSE(irdaikin.getSensor()); +} + +TEST(TestDaikinClass, RenderTime) { + EXPECT_EQ("0:00", IRDaikinESP::renderTime(0)); + EXPECT_EQ("0:10", IRDaikinESP::renderTime(10)); + EXPECT_EQ("1:00", IRDaikinESP::renderTime(1 * 60 + 0)); + EXPECT_EQ("23:59", IRDaikinESP::renderTime(23 * 60 + 59)); +} + +TEST(TestDaikinClass, SetAndGetRaw) { + IRDaikinESP irdaikin(0); + uint8_t initialState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x00, 0x00, 0x54, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x49, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x4F}; + uint8_t expectedState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x00, 0x00, 0x54, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x48, 0x2A, 0x00, 0xB0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x02, 0x5A}; + + EXPECT_STATE_EQ(initialState, irdaikin.getRaw(), kDaikinBits); + // toggle the power state. + irdaikin.setPower(!irdaikin.getPower()); + irdaikin.setTemp(21); + irdaikin.setMold(true); + EXPECT_STATE_EQ(expectedState, irdaikin.getRaw(), kDaikinBits); + irdaikin.setRaw(initialState); + EXPECT_STATE_EQ(initialState, irdaikin.getRaw(), kDaikinBits); +} + +TEST(TestDaikinClass, ChecksumValidation) { + uint8_t daikin_code[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x02, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE1}; + + EXPECT_TRUE(IRDaikinESP::validChecksum(daikin_code)); + // Change the array so the checksum is invalid. + daikin_code[0] ^= 0xFF; + EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); + // Restore the previous change, and change another byte. + daikin_code[0] ^= 0xFF; + daikin_code[4] ^= 0xFF; + EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); + daikin_code[4] ^= 0xFF; + // Change something in the 2nd block. + daikin_code[10] ^= 0xFF; + EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); + daikin_code[10] ^= 0xFF; + EXPECT_TRUE(IRDaikinESP::validChecksum(daikin_code)); +} + +// Test human readable output. +TEST(TestDaikinClass, HumanReadable) { + IRDaikinESP irdaikin(0); + + EXPECT_EQ( + "Power: On, Mode: 4 (HEAT), Temp: 15C, Fan: 11 (QUIET), " + "Powerful: Off, Quiet: Off, Sensor: Off, Eye: Off, Mold: Off, " + "Swing (Horizontal): Off, Swing (Vertical): Off, " + "Current Time: 0:00, On Time: Off, Off Time: Off", + irdaikin.toString()); + irdaikin.setMode(kDaikinAuto); + irdaikin.setTemp(25); + irdaikin.setFan(kDaikinFanAuto); + irdaikin.setQuiet(true); + irdaikin.setSensor(true); + irdaikin.setEye(true); + irdaikin.setMold(true); + irdaikin.setSwingVertical(true); + irdaikin.setSwingHorizontal(true); + irdaikin.setCurrentTime(9 * 60 + 15); + irdaikin.enableOnTimer(8 * 60 + 0); + irdaikin.enableOffTimer(17 * 60 + 30); + irdaikin.off(); + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 10 (AUTO), " + "Powerful: Off, Quiet: On, Sensor: On, Eye: On, Mold: On, " + "Swing (Horizontal): On, Swing (Vertical): On, " + "Current Time: 9:15, On Time: 8:00, Off Time: 17:30", + irdaikin.toString()); +} + +// Test general message construction after tweaking some settings. +TEST(TestDaikinClass, MessageConstuction) { + IRDaikinESP irdaikin(0); + IRsendTest irsend(4); + irdaikin.begin(); + irsend.begin(); + + irdaikin.setFan(kDaikinFanMin); + irdaikin.setMode(kDaikinCool); + irdaikin.setTemp(27); + irdaikin.setSwingVertical(false); + irdaikin.setSwingHorizontal(true); + irdaikin.setQuiet(false); + irdaikin.setPower(true); + + // Check everything for kicks. + EXPECT_EQ(kDaikinFanMin, irdaikin.getFan()); + EXPECT_EQ(kDaikinCool, irdaikin.getMode()); + EXPECT_EQ(27, irdaikin.getTemp()); + EXPECT_FALSE(irdaikin.getSwingVertical()); + EXPECT_TRUE(irdaikin.getSwingHorizontal()); + EXPECT_FALSE(irdaikin.getQuiet()); + EXPECT_TRUE(irdaikin.getPower()); + + irsend.reset(); + irsend.sendDaikin(irdaikin.getRaw()); + EXPECT_EQ( + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s1280m428s428m428s1280m428s428m428s1280m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s1280m428s1280m428s1280m428s428m428s428" + "m428s428m428s1280m428s1280m428s428m428s1280m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s428" + "m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s1280m428s1280m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s1280m428s1280m428s428m428s428m428s1280m428s1280m428s1280" + "m428s29428", + irsend.outputStr()); +} + +// Tests for decodeDaikin(). + +// Test decoding a message captured from a real IR remote. +TEST(TestDecodeDaikin, RealExample) { + IRDaikinESP irdaikin(0); + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + uint8_t expectedState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x3A, 0x05, 0x93, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x3F, 0x3A, 0x00, 0xA0, 0x00, + 0x0A, 0x25, 0x17, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x32}; + uint16_t rawData[kDaikinRawBits] = { + 416, 446, 416, 446, 416, 446, 418, 446, 416, 446, 416, 25434, + 3436, 1768, 390, 1336, 390, 446, 416, 446, 416, 446, 416, 1336, + 390, 446, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 448, + 416, 1336, 390, 1336, 390, 448, 416, 1336, 390, 1336, 390, 1338, + 388, 1338, 390, 1336, 390, 446, 416, 446, 416, 1336, 390, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 448, + 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, 416, 1336, + 390, 448, 416, 446, 416, 446, 416, 1336, 390, 1336, 390, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 446, 416, 446, 416, 448, 416, 446, 416, 446, 416, 446, + 416, 448, 414, 448, 416, 448, 416, 1336, 390, 1336, 390, 1336, + 390, 446, 414, 1336, 390, 448, 414, 1336, 390, 1336, 390, 34878, + 3436, 1768, 390, 1336, 390, 446, 416, 448, 416, 446, 416, 1336, + 390, 446, 416, 448, 416, 446, 416, 446, 416, 1336, 390, 446, + 416, 1336, 390, 1336, 390, 446, 416, 1336, 390, 1336, 390, 1336, + 390, 1336, 390, 1336, 392, 446, 414, 448, 416, 1336, 390, 446, + 416, 446, 416, 446, 416, 446, 414, 448, 416, 446, 416, 448, + 414, 448, 416, 446, 416, 446, 416, 446, 414, 1336, 390, 448, + 416, 446, 416, 446, 416, 448, 416, 1336, 390, 446, 416, 446, + 416, 1336, 390, 446, 416, 1336, 390, 1336, 390, 1336, 390, 446, + 416, 446, 414, 1338, 390, 446, 416, 1336, 390, 446, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 1336, 390, 1336, 390, 446, + 416, 446, 416, 1336, 390, 446, 416, 446, 416, 1336, 390, 34876, + 3436, 1768, 388, 1336, 390, 446, 416, 446, 416, 448, 416, 1336, + 390, 446, 416, 446, 416, 446, 416, 448, 416, 1336, 390, 448, + 414, 1336, 390, 1336, 390, 446, 416, 1336, 388, 1338, 388, 1336, + 390, 1336, 390, 1336, 390, 446, 416, 446, 416, 1336, 390, 446, + 420, 442, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 448, + 416, 446, 416, 448, 416, 446, 416, 448, 416, 446, 416, 1336, + 390, 1336, 390, 1336, 388, 1338, 390, 1336, 390, 1336, 392, 446, + 416, 446, 416, 448, 416, 1334, 390, 446, 416, 1338, 388, 1336, + 390, 1336, 390, 446, 416, 446, 416, 448, 414, 446, 416, 446, + 416, 446, 416, 448, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, + 416, 1336, 390, 446, 414, 448, 416, 446, 416, 446, 416, 446, + 416, 448, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, + 416, 1336, 390, 446, 416, 446, 416, 446, 416, 448, 416, 1338, + 390, 444, 418, 1336, 390, 448, 416, 446, 416, 1336, 390, 446, + 416, 446, 416, 1336, 390, 1336, 388, 1336, 390, 446, 416, 1336, + 390, 448, 414, 448, 414, 448, 416, 1334, 390, 446, 416, 446, + 416, 446, 416, 448, 416, 446, 416, 446, 416, 448, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 448, 416, 1336, 390, 1336, 390, 446, 416, 446, 416, 446, + 416, 446, 414, 446, 416, 448, 416, 446, 416, 448, 414, 446, + 418, 446, 416, 446, 416, 448, 416, 446, 416, 448, 416, 446, + 416, 448, 416, 446, 416, 1336, 390, 446, 416, 446, 416, 1338, + 390, 1336, 390, 446, 416, 446, 416}; // Captured by @sillyfrog + + irsend.reset(); + irsend.sendRaw(rawData, kDaikinRawBits, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN, irsend.capture.decode_type); + ASSERT_EQ(kDaikinBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decoding a message we entirely constructed based solely on a given state. +TEST(TestDecodeDaikin, SyntheticExample) { + IRDaikinESP irdaikin(0); + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + uint8_t expectedState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x3A, 0x05, 0x93, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x3F, 0x3A, 0x00, 0xA0, 0x00, + 0x0A, 0x25, 0x17, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x32}; + + irsend.reset(); + irsend.sendDaikin(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN, irsend.capture.decode_type); + ASSERT_EQ(kDaikinBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Denon_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Denon_test.cpp similarity index 82% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Denon_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Denon_test.cpp index 32de11b46..911fd7528 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Denon_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Denon_test.cpp @@ -19,7 +19,8 @@ TEST(TestSendDenon, SendDataOnly) { "m260s43602" "m260s780m260s1820m260s780m260s780m260s780m260s780m260s1820m260s1820" "m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); irsend.reset(); // Denon Eco Mode On. (Panasonic/Kaseikyo) @@ -32,7 +33,8 @@ TEST(TestSendDenon, SendDataOnly) { "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" - "m432s129600", irsend.outputStr()); + "m432s98928", + irsend.outputStr()); } // Test sending with different repeats. @@ -54,7 +56,8 @@ TEST(TestSendDenon, SendNormalWithRepeats) { "m260s43602" "m260s780m260s1820m260s780m260s780m260s780m260s780m260s1820m260s1820" "m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); irsend.sendDenon(0x2278, DENON_BITS, 2); // 2 repeats. EXPECT_EQ( "m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780" @@ -74,7 +77,8 @@ TEST(TestSendDenon, SendNormalWithRepeats) { "m260s43602" "m260s780m260s1820m260s780m260s780m260s780m260s780m260s1820m260s1820" "m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } TEST(TestSendDenon, Send48BitWithRepeats) { @@ -91,7 +95,7 @@ TEST(TestSendDenon, Send48BitWithRepeats) { "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" - "m432s129600" + "m432s98928" "m3456s1728" "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" @@ -99,7 +103,8 @@ TEST(TestSendDenon, Send48BitWithRepeats) { "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" - "m432s129600", irsend.outputStr()); + "m432s98928", + irsend.outputStr()); irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS, 2); // 2 repeats. EXPECT_EQ( "m3456s1728" @@ -109,7 +114,7 @@ TEST(TestSendDenon, Send48BitWithRepeats) { "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" - "m432s129600" + "m432s98928" "m3456s1728" "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" @@ -117,7 +122,7 @@ TEST(TestSendDenon, Send48BitWithRepeats) { "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" - "m432s129600" + "m432s98928" "m3456s1728" "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" @@ -125,7 +130,8 @@ TEST(TestSendDenon, Send48BitWithRepeats) { "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" - "m432s129600", irsend.outputStr()); + "m432s98928", + irsend.outputStr()); } // Test sending an atypical data size. @@ -139,7 +145,8 @@ TEST(TestSendDenon, SendUnusualSize) { "m260s780m260s780m260s780m260s1820m260s780m260s780m260s1820m260s780" "m260s43602" "m260s1820m260s1820m260s1820m260s780m260s1820m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); irsend.reset(); irsend.sendDenon(0x1234567890ABCDEF, 64); @@ -153,7 +160,8 @@ TEST(TestSendDenon, SendUnusualSize) { "m432s1296m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296" "m432s1296m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s1296" "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s1296m432s1296" - "m432s129600", irsend.outputStr()); + "m432s74736", + irsend.outputStr()); } // Tests for decodeDenon(). @@ -179,12 +187,12 @@ TEST(TestDecodeDenon, NormalDecodeWithStrict) { // Legacy Denon 14-bit message. irsend.reset(); - irsend.sendDenon(0x1278, DENON_LEGACY_BITS); + irsend.sendDenon(0x1278, kDenonLegacyBits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, DENON_LEGACY_BITS, true)); + ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kDenonLegacyBits, true)); EXPECT_EQ(DENON, irsend.capture.decode_type); - EXPECT_EQ(DENON_LEGACY_BITS, irsend.capture.bits); + EXPECT_EQ(kDenonLegacyBits, irsend.capture.bits); EXPECT_EQ(0x1278, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -211,13 +219,11 @@ TEST(TestDecodeDenon, DecodeGlobalCacheExample) { irsend.reset(); // Denon AVR series Power On code from Global Cache. (Sharp style) - uint16_t gc_test_power[67] = {38000, 1, 1, - 10, 30, 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, - 10, 30, 10, 30, 10, 70, 10, 70, 10, 70, 10, 70, - 10, 30, 10, 30, 10, 30, 10, 1657, - 10, 30, 10, 70, 10, 30, 10, 30, 10, 30, 10, 30, - 10, 70, 10, 70, 10, 30, 10, 30, 10, 30, 10, 30, - 10, 70, 10, 70, 10, 70, 10, 1657}; + uint16_t gc_test_power[67] = { + 38000, 1, 1, 10, 30, 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 30, + 10, 30, 10, 70, 10, 70, 10, 70, 10, 70, 10, 30, 10, 30, 10, 30, 10, + 1657, 10, 30, 10, 70, 10, 30, 10, 30, 10, 30, 10, 30, 10, 70, 10, 70, + 10, 30, 10, 30, 10, 30, 10, 30, 10, 70, 10, 70, 10, 70, 10, 1657}; irsend.sendGC(gc_test_power, 67); irsend.makeDecodeResult(); @@ -230,15 +236,14 @@ TEST(TestDecodeDenon, DecodeGlobalCacheExample) { EXPECT_FALSE(irsend.capture.repeat); // Denon "Eco Mode Auto" code from Global Cache. (Panasonic style) - uint16_t gc_test_eco[103] = {37000, 1, 1, 128, 64, 16, 16, 16, 16, 16, 48, - 16, 16, 16, 48, 16, 16, 16, 48, 16, 16, 16, 16, - 16, 48, 16, 16, 16, 16, 16, 48, 16, 48, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 48, 16, 16, 16, 48, 16, 16, 16, 16, - 16, 16, 16, 48, 16, 48, 16, 16, 16, 48, 16, 16, - 16, 48, 16, 48, 16, 16, 16, 48, 16, 48, 16, 16, - 16, 16, 16, 48, 16, 48, 16, 48, 16, 16, 16, 16, - 16, 16, 16, 48, 16, 48, 16, 2766}; + uint16_t gc_test_eco[103] = { + 37000, 1, 1, 128, 64, 16, 16, 16, 16, 16, 48, 16, 16, 16, 48, + 16, 16, 16, 48, 16, 16, 16, 16, 16, 48, 16, 16, 16, 16, 16, + 48, 16, 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 48, 16, 16, 16, 48, 16, 16, 16, 16, 16, + 16, 16, 48, 16, 48, 16, 16, 16, 48, 16, 16, 16, 48, 16, 48, + 16, 16, 16, 48, 16, 48, 16, 16, 16, 16, 16, 48, 16, 48, 16, + 48, 16, 16, 16, 16, 16, 16, 16, 48, 16, 48, 16, 2766}; irsend.reset(); irsend.sendGC(gc_test_eco, 103); irsend.makeDecodeResult(); @@ -259,14 +264,15 @@ TEST(TestDecodeDenon, FailToDecodeNonDenonExample) { irsend.begin(); irsend.reset(); - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, DENON_LEGACY_BITS, false)); + ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, kDenonLegacyBits, false)); ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, DENON_BITS, false)); ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, DENON_48_BITS, false)); } diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Dish_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Dish_test.cpp similarity index 76% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Dish_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Dish_test.cpp index afd76e8fd..0c58496ce 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Dish_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Dish_test.cpp @@ -26,7 +26,8 @@ TEST(TestSendDish, SendDataOnly) { "m400s6100" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); irsend.reset(); irsend.sendDISH(0x9C00); // Power on. @@ -43,7 +44,8 @@ TEST(TestSendDish, SendDataOnly) { "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); irsend.reset(); irsend.sendDISH(0xFFFF); @@ -60,7 +62,8 @@ TEST(TestSendDish, SendDataOnly) { "m400s6100" "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); } // Test sending with different repeats. @@ -69,15 +72,16 @@ TEST(TestSendDish, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendDISH(0x9C00, DISH_BITS, 0); // 0 repeats. + irsend.sendDISH(0x9C00, kDishBits, 0); // 0 repeats. EXPECT_EQ( "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); irsend.reset(); - irsend.sendDISH(0x9C00, DISH_BITS, 1); // 1 repeat. + irsend.sendDISH(0x9C00, kDishBits, 1); // 1 repeat. EXPECT_EQ( "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" @@ -85,9 +89,10 @@ TEST(TestSendDish, SendWithRepeats) { "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); - irsend.sendDISH(0x9C00, DISH_BITS, 2); // 2 repeats. + irsend.sendDISH(0x9C00, kDishBits, 2); // 2 repeats. EXPECT_EQ( "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" @@ -98,7 +103,8 @@ TEST(TestSendDish, SendWithRepeats) { "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); } // Test sending an atypical data size. @@ -109,15 +115,16 @@ TEST(TestSendDish, SendUnusualSize) { irsend.reset(); irsend.sendDISH(0x0, 8); EXPECT_EQ( - "m400s6100" - "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100" - "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100" - "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100" - "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" - "m400s6100", irsend.outputStr()); + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100", + irsend.outputStr()); irsend.reset(); irsend.sendDISH(0x1234567890ABCDEF, 64); @@ -158,7 +165,8 @@ TEST(TestSendDish, SendUnusualSize) { "m400s1700m400s2800m400s1700m400s2800m400s1700m400s2800m400s1700m400s1700" "m400s1700m400s1700m400s2800m400s2800m400s1700m400s1700m400s2800m400s1700" "m400s1700m400s1700m400s1700m400s2800m400s1700m400s1700m400s1700m400s1700" - "m400s6100", irsend.outputStr()); + "m400s6100", + irsend.outputStr()); } // Tests for decodeDISH(). @@ -173,9 +181,9 @@ TEST(TestDecodeDish, NormalDecodeWithStrict) { irsend.reset(); irsend.sendDISH(0x9C00); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, true)); + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); EXPECT_EQ(DISH, irsend.capture.decode_type); - EXPECT_EQ(DISH_BITS, irsend.capture.bits); + EXPECT_EQ(kDishBits, irsend.capture.bits); EXPECT_EQ(0x9C00, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -192,7 +200,7 @@ TEST(TestDecodeDish, DecodeWithNonStrictSize) { irsend.sendDISH(0x12, 8); // Illegal size Dish message. (smaller) irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, true)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -209,7 +217,7 @@ TEST(TestDecodeDish, DecodeWithNonStrictSize) { irsend.sendDISH(0x12345678, 32); // Illegal size Dish message. (larger) irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, true)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -247,47 +255,45 @@ TEST(TestDecodeDish, DecodeGlobalCacheExample) { IRrecv irrecv(4); irsend.begin(); -/* - irsend.reset(); - // Dish DTV Pal code from Global Cache. - uint16_t gc_test_dtv[27] = {58000, 1, 3, 22, 538, 22, 252, 22, 156, 22, 156, - 22, 156, 22, 156, 22, 252, 22, 252, 22, 252, 22, - 252, 22, 252, 22, 538}; - irsend.sendGC(gc_test_dtv, 27); - irsend.makeDecodeResult(); + /* + irsend.reset(); + // Dish DTV Pal code from Global Cache. + uint16_t gc_test_dtv[27] = {58000, 1, 3, 22, 538, 22, 252, 22, 156, 22, 156, + 22, 156, 22, 156, 22, 252, 22, 252, 22, 252, 22, + 252, 22, 252, 22, 538}; + irsend.sendGC(gc_test_dtv, 27); + irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, true)); - EXPECT_EQ(DISH, irsend.capture.decode_type); - EXPECT_EQ(DISH_BITS, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); + EXPECT_EQ(DISH, irsend.capture.decode_type); + EXPECT_EQ(kDishBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture)); - EXPECT_EQ(DISH, irsend.capture.decode_type); - EXPECT_EQ(DISH_BITS, irsend.capture.bits); - EXPECT_EQ(0x0, irsend.capture.value); - EXPECT_EQ(0x0, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); - EXPECT_FALSE(irsend.capture.repeat); -*/ + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture)); + EXPECT_EQ(DISH, irsend.capture.decode_type); + EXPECT_EQ(kDishBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + */ // Dish Hopper 3 code from Global Cache. - uint16_t gc_test_hopper[73] = {58000, 1, 37, 23, 351, 23, 94, 23, 164, - 23, 164, 23, 94, 23, 94, 23, 94, 23, 164, - 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, - 23, 164, 23, 164, 23, 164, 23, 164, 23, 351, - 23, 94, 23, 164, 23, 164, 23, 94, 23, 94, - 23, 94, 23, 164, 23, 164, 23, 164, 23, 164, - 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, - 23, 164, 23, 351}; + uint16_t gc_test_hopper[73] = { + 58000, 1, 37, 23, 351, 23, 94, 23, 164, 23, 164, 23, 94, 23, 94, 23, + 94, 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, 23, + 164, 23, 164, 23, 164, 23, 351, 23, 94, 23, 164, 23, 164, 23, 94, 23, + 94, 23, 94, 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, 23, 164, 23, + 164, 23, 164, 23, 164, 23, 164, 23, 351}; irsend.reset(); irsend.sendGC(gc_test_hopper, 73); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, true)); + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); EXPECT_EQ(DISH, irsend.capture.decode_type); - EXPECT_EQ(DISH_BITS, irsend.capture.bits); + EXPECT_EQ(kDishBits, irsend.capture.bits); EXPECT_EQ(0x9C00, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -295,7 +301,7 @@ TEST(TestDecodeDish, DecodeGlobalCacheExample) { ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture)); EXPECT_EQ(DISH, irsend.capture.decode_type); - EXPECT_EQ(DISH_BITS, irsend.capture.bits); + EXPECT_EQ(kDishBits, irsend.capture.bits); EXPECT_EQ(0x9C00, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -310,12 +316,13 @@ TEST(TestDecodeDish, FailToDecodeNonDishExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, false)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kDishBits, false)); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Electra_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Electra_test.cpp new file mode 100644 index 000000000..df5dd7a5c --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Electra_test.cpp @@ -0,0 +1,98 @@ +// Copyright 2018 David Conran + +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendElectraAC(). + +// Test sending typical data only. +TEST(TestSendElectraAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + uint8_t data[kElectraAcStateLength] = {0xC3, 0xE1, 0x6F, 0x14, 0x06, + 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0xA0, 0xB0}; + + irsend.sendElectraAC(data); + EXPECT_EQ( + "m9166s4470" + "m646s1647m646s1647m646s547m646s547m646s547m646s547m646s1647m646s1647" + "m646s1647m646s1647m646s1647m646s547m646s547m646s547m646s547m646s1647" + "m646s547m646s1647m646s1647m646s547m646s1647m646s1647m646s1647m646s1647" + "m646s547m646s547m646s547m646s1647m646s547m646s1647m646s547m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s1647m646s1647m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s1647m646s547m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s1647m646s547m646s547" + "m646s547m646s547m646s547m646s547m646s547m646s547m646s547m646s547" + "m646s1647m646s547m646s1647m646s547m646s547m646s547m646s547m646s547" + "m646s1647m646s547m646s1647m646s1647m646s547m646s547m646s547m646s547" + "m646s100000", + irsend.outputStr()); +} + +// Tests for decodeElectraAC(). +// Decode normal ElectraAC messages. + +TEST(TestDecodeElectraAC, SyntheticDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Synthesised Normal ElectraAC message. + irsend.reset(); + uint8_t expectedState[kElectraAcStateLength] = {0xC3, 0xE1, 0x6F, 0x14, 0x06, + 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0xA0, 0xB0}; + irsend.sendElectraAC(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(ELECTRA_AC, irsend.capture.decode_type); + EXPECT_EQ(kElectraAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decode a recorded example +TEST(TestDecodeElectraAC, RealExampleDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Real ElectraAC message. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/527 + uint16_t rawData[211] = { + 9166, 4470, 642, 1632, 642, 1632, 668, 534, 666, 534, 668, 534, + 614, 536, 640, 1636, 640, 1646, 694, 1662, 612, 1628, 642, 1666, + 664, 532, 668, 534, 666, 534, 666, 532, 666, 1644, 642, 532, + 640, 1634, 668, 1632, 642, 538, 666, 1660, 610, 1666, 664, 1632, + 642, 1672, 610, 536, 666, 534, 694, 532, 666, 1636, 614, 538, + 666, 1632, 642, 536, 666, 544, 692, 534, 640, 558, 640, 534, + 640, 540, 666, 534, 638, 1666, 638, 1636, 640, 550, 666, 534, + 640, 540, 666, 534, 640, 540, 666, 536, 638, 540, 666, 536, + 638, 550, 664, 536, 638, 540, 664, 536, 638, 540, 666, 534, + 638, 1640, 664, 536, 692, 546, 664, 536, 664, 536, 664, 536, + 664, 546, 612, 532, 636, 538, 664, 536, 664, 546, 612, 538, + 638, 538, 638, 538, 664, 536, 690, 538, 662, 538, 664, 538, + 662, 548, 664, 536, 662, 538, 662, 562, 638, 564, 636, 564, + 636, 1668, 582, 556, 652, 572, 612, 568, 636, 564, 610, 570, + 636, 556, 616, 550, 656, 566, 610, 570, 632, 578, 608, 1640, + 662, 562, 642, 1686, 582, 570, 634, 566, 604, 576, 636, 566, + 610, 578, 634, 1664, 584, 590, 660, 1636, 610, 1642, 664, 590, + 610, 590, 636, 566, 634, 568, 686}; // UNKNOWN 9AD8CDB5 + uint8_t expectedState[kElectraAcStateLength] = {0xC3, 0xE1, 0x6F, 0x14, 0x06, + 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0xA0, 0xB0}; + + irsend.reset(); + irsend.sendRaw(rawData, 211, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(ELECTRA_AC, irsend.capture.decode_type); + EXPECT_EQ(kElectraAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Fujitsu_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Fujitsu_test.cpp new file mode 100644 index 000000000..23fa3e7a7 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Fujitsu_test.cpp @@ -0,0 +1,555 @@ +// Copyright 2017 Jonny Graham, David Conran + +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "ir_Fujitsu.h" +#include "gtest/gtest.h" + +template +::testing::AssertionResult ArraysMatch(const T (&expected)[size], + const T* actual) { + for (size_t i(0); i < size; ++i) { + if (expected[i] != actual[i]) { + int e = expected[i]; + int a = actual[i]; + return ::testing::AssertionFailure() << "array[" << i + << "] (" << std::hex << a << std::dec << ") != expected[" << i + << "] (" << std::hex << e << std::dec << ")"; + } + } + return ::testing::AssertionSuccess(); +} +// Tests for Fujitsu A/C methods. + +// Test sending typical data only. +TEST(TestIRFujitsuACClass, GetRawDefault) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); // AR-RAH2E + fujitsu.setCmd(kFujitsuAcCmdTurnOn); + fujitsu.setSwing(kFujitsuAcSwingBoth); + fujitsu.setMode(kFujitsuAcModeCool); + fujitsu.setFanSpeed(kFujitsuAcFanHigh); + fujitsu.setTemp(24); + uint8_t expected_arrah2e[16] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x20, 0xFD}; + EXPECT_TRUE(ArraysMatch(expected_arrah2e, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: N/A", fujitsu.toString()); + + uint8_t expected_ardb1[15] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30, + 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x1D}; + fujitsu.setModel(ARDB1); + EXPECT_TRUE(ArraysMatch(expected_ardb1, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: N/A", fujitsu.toString()); +} + +TEST(TestIRFujitsuACClass, GetRawTurnOff) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + fujitsu.setModel(ARRAH2E); + fujitsu.off(); + uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD}; + EXPECT_TRUE(ArraysMatch(expected_arrah2e, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLengthShort, fujitsu.getStateLength()); + EXPECT_EQ("Power: Off, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: N/A", fujitsu.toString()); + + fujitsu.setModel(ARDB1); + uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02}; + EXPECT_TRUE(ArraysMatch(expected_ardb1, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLengthShort - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: Off, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: N/A", fujitsu.toString()); +} + +TEST(TestIRFujitsuACClass, GetRawStepHoriz) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + fujitsu.stepHoriz(); + uint8_t expected[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x79, 0x86}; + EXPECT_TRUE(ArraysMatch(expected, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLengthShort, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: Step vane horizontally", + fujitsu.toString()); +} + +TEST(TestIRFujitsuACClass, GetRawStepVert) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + fujitsu.setModel(ARRAH2E); + fujitsu.stepVert(); + uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x6C, 0x93}; + EXPECT_TRUE(ArraysMatch(expected_arrah2e, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLengthShort, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: Step vane vertically", + fujitsu.toString()); + + fujitsu.setModel(ARDB1); + fujitsu.stepVert(); + uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x6C}; + EXPECT_TRUE(ArraysMatch(expected_ardb1, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLengthShort - 1, + fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: Step vane vertically", + fujitsu.toString()); +} + +TEST(TestIRFujitsuACClass, GetRawWithSwingHoriz) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + fujitsu.setCmd(kFujitsuAcCmdStayOn); + fujitsu.setSwing(kFujitsuAcSwingHoriz); + fujitsu.setMode(kFujitsuAcModeCool); + fujitsu.setFanSpeed(kFujitsuAcFanQuiet); + fujitsu.setTemp(25); + uint8_t expected[16] = {0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30, + 0x90, 0x1, 0x24, 0x0, 0x0, 0x0, 0x20, 0xFB}; + EXPECT_TRUE(ArraysMatch(expected, fujitsu.getRaw())); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 25C, Fan: 4 (QUIET), " + "Swing: Horiz, Command: N/A", + fujitsu.toString()); +} + +TEST(TestIRFujitsuACClass, GetRawWithFan) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + fujitsu.setCmd(kFujitsuAcCmdStayOn); + fujitsu.setSwing(kFujitsuAcSwingHoriz); + fujitsu.setMode(kFujitsuAcModeFan); + fujitsu.setFanSpeed(kFujitsuAcFanMed); + fujitsu.setTemp(20); // temp doesn't matter for fan + // but it is sent by the RC anyway + fujitsu.setModel(ARRAH2E); + uint8_t expected_arrah2e[16] = { + 0x14, 0x63, 0x0, 0x10, 0x10, 0xFE, 0x9, 0x30, + 0x40, 0x3, 0x22, 0x0, 0x0, 0x0, 0x20, 0x4B}; + EXPECT_TRUE(ArraysMatch(expected_arrah2e, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 3 (FAN), Temp: 20C, Fan: 2 (MED), Swing: Horiz, " + "Command: N/A", fujitsu.toString()); + + fujitsu.setModel(ARDB1); + uint8_t expected_ardb1[15] = { + 0x14, 0x63, 0x0, 0x10, 0x10, 0xFC, 0x8, 0x30, + 0x40, 0x3, 0x22, 0x0, 0x0, 0x0, 0x6B}; + EXPECT_TRUE(ArraysMatch(expected_ardb1, fujitsu.getRaw())); + EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 3 (FAN), Temp: 20C, Fan: 2 (MED), Swing: Horiz, " + "Command: N/A", fujitsu.toString()); +} + +TEST(TestIRFujitsuACClass, SetRaw) { + IRFujitsuAC fujitsu = IRFujitsuAC(0); + EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength()); + uint8_t expected_default_arrah2e[kFujitsuAcStateLength] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0x81, 0x01, 0x31, 0x00, 0x00, 0x00, 0x20, 0xFD}; + EXPECT_TRUE(ArraysMatch(expected_default_arrah2e, fujitsu.getRaw())); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 1 (HIGH), " + "Swing: Vert + Horiz, Command: N/A", fujitsu.toString()); + // Now set a new state via setRaw(); + // This state is a real state from an AR-DB1 remote. + uint8_t new_state1[kFujitsuAcStateLength - 1] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x9F}; + fujitsu.setRaw(new_state1, kFujitsuAcStateLength - 1); + EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength()); + EXPECT_TRUE(ArraysMatch(new_state1, fujitsu.getRaw())); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 0 (AUTO), " + "Swing: Off, Command: N/A", fujitsu.toString()); +} + +TEST(TestSendFujitsuAC, GenerateMessage) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + IRsendTest irsend(4); + fujitsu.begin(); + irsend.begin(); + + fujitsu.setCmd(kFujitsuAcCmdStayOn); + fujitsu.setSwing(kFujitsuAcSwingBoth); + fujitsu.setMode(kFujitsuAcModeCool); + fujitsu.setFanSpeed(kFujitsuAcFanHigh); + fujitsu.setTemp(24); + + EXPECT_EQ(kFujitsuAcFanHigh, fujitsu.getFanSpeed()); + EXPECT_EQ(kFujitsuAcModeCool, fujitsu.getMode()); + EXPECT_EQ(24, fujitsu.getTemp()); + EXPECT_EQ(kFujitsuAcSwingBoth, fujitsu.getSwing()); + EXPECT_EQ(kFujitsuAcCmdStayOn, fujitsu.getCmd()); + + irsend.reset(); + irsend.sendFujitsuAC(fujitsu.getRaw(), kFujitsuAcStateLength); + EXPECT_EQ( + "m3324s1574" + "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390" + "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390" + "m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182" + "m448s1182m448s390m448s390m448s1182m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s1182m448s1182m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s1182" + "m448s1182m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s1182m448s390m448s390" + "m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182" + "m448s8100", + irsend.outputStr()); +} + +TEST(TestSendFujitsuAC, GenerateShortMessage) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + IRsendTest irsend(4); + fujitsu.begin(); + irsend.begin(); + + fujitsu.off(); + + EXPECT_EQ(kFujitsuAcCmdTurnOff, fujitsu.getCmd()); + + irsend.reset(); + irsend.sendFujitsuAC(fujitsu.getRaw(), kFujitsuAcStateLengthShort); + EXPECT_EQ( + "m3324s1574m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448" + "s390m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s1182m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s1182m448s390m448s390m448s390m448s390m448s1182m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s1182m448s390m448s1182m448" + "s1182m448s1182m448s1182m448s1182m448s1182m448s8100", + irsend.outputStr()); +} + +// Issue #275 +TEST(TestSendFujitsuAC, Issue275) { + IRFujitsuAC fujitsu = IRFujitsuAC(4); + IRsendTest irsend(4); + fujitsu.begin(); + irsend.begin(); + irsend.reset(); + + fujitsu.setCmd(kFujitsuAcCmdTurnOff); + irsend.sendFujitsuAC(fujitsu.getRaw(), kFujitsuAcStateLengthShort); + EXPECT_EQ( + // Header + "m3324s1574" + // 0 0 1 0 1 0 0 0 (0x28) + "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390" + // 1 1 0 0 0 1 1 0 (0xC6) + "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390" + // 0 0 0 0 0 0 0 0 (0x00) + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + // 0 0 0 0 1 0 0 0 (0x08) + "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390" + // 0 0 0 0 1 0 0 0 (0x08) + "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390" + // 0 1 0 0 0 0 0 0 (0x40) + "m448s390m448s1182m448s390m448s390m448s390m448s390m448s390m448s390" + // 1 0 1 1 1 1 1 1 (0xBF) + "m448s1182m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182" + // Footer + "m448s8100", irsend.outputStr()); + + irsend.reset(); + // Per report in Issue #275 + uint16_t off[115] = { + 3350, 1650, + 450, 400, 450, 450, 450, 1250, 450, 400, 450, 1250, 450, 400, 450, 400, + 450, 400, 450, 1250, 450, 1250, 450, 400, 450, 400, 450, 400, 450, 1250, + 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, + 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, + 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, + 450, 400, 450, 1250, 450, 400, 450, 400, 450, 400, 450, 400, 450, 1250, + 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 400, 450, 1250, + 450, 400, 450, 1250, 450, 1250, 450, 1250, 450, 1250, 450, 1250, + 450, 1250, 450}; + irsend.sendRaw(off, 115, 38); + EXPECT_EQ( + // Header + "m3350s1650" + // 0 0 1 0 1 0 0 0 (0x28) + "m450s400m450s450m450s1250m450s400m450s1250m450s400m450s400m450s400" + // 1 1 0 0 0 1 1 0 (0xC6) + "m450s1250m450s1250m450s400m450s400m450s400m450s1250m450s1250m450s400" + // 0 0 0 0 0 0 0 0 (0x00) + "m450s400m450s400m450s400m450s400m450s400m450s400m450s400m450s400" + // 0 0 0 0 1 0 0 0 (0x08) + "m450s400m450s400m450s400m450s400m450s1250m450s400m450s400m450s400" + // 0 0 0 0 1 0 0 0 (0x08) + "m450s400m450s400m450s400m450s400m450s1250m450s400m450s400m450s400" + // 0 1 0 0 0 0 0 0 (0x40) + "m450s400m450s1250m450s400m450s400m450s400m450s400m450s400m450s400" + // 1 0 1 1 1 1 1 1 (0xBF) + "m450s1250m450s400m450s1250m450s1250m450s1250m450s1250m450s1250m450s1250" + // Footer + "m450", + irsend.outputStr()); +} + +TEST(TestDecodeFujitsuAC, SyntheticShortMessages) { + IRsendTest irsend(0); + IRFujitsuAC fujitsu = IRFujitsuAC(0); + IRrecv irrecv(0); + + irsend.begin(); + irsend.reset(); + + fujitsu.setModel(ARRAH2E); + fujitsu.setCmd(kFujitsuAcCmdTurnOff); + irsend.sendFujitsuAC(fujitsu.getRaw(), fujitsu.getStateLength()); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcMinBits + 8, irsend.capture.bits); + uint8_t expected_arrah2e[7] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02, 0xFD}; + EXPECT_TRUE(ArraysMatch(expected_arrah2e, irsend.capture.state)); + + irsend.reset(); + + fujitsu.setModel(ARDB1); + fujitsu.setCmd(kFujitsuAcCmdTurnOff); + irsend.sendFujitsuAC(fujitsu.getRaw(), fujitsu.getStateLength()); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcMinBits, irsend.capture.bits); + uint8_t expected_ardb1[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02}; + EXPECT_TRUE(ArraysMatch(expected_ardb1, irsend.capture.state)); +} + +TEST(TestDecodeFujitsuAC, SyntheticLongMessages) { + IRsendTest irsend(0); + IRFujitsuAC fujitsu = IRFujitsuAC(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + + fujitsu.setModel(ARRAH2E); + fujitsu.setCmd(kFujitsuAcCmdStayOn); + fujitsu.setSwing(kFujitsuAcSwingVert); + fujitsu.setMode(kFujitsuAcModeCool); + fujitsu.setFanSpeed(kFujitsuAcFanQuiet); + fujitsu.setTemp(18); + irsend.sendFujitsuAC(fujitsu.getRaw(), fujitsu.getStateLength()); + ASSERT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength()); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeFujitsuAC(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits); + uint8_t expected_arrah2e[kFujitsuAcStateLength] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, + 0x20, 0x01, 0x14, 0x00, 0x00, 0x00, 0x20, 0x7B}; + EXPECT_TRUE(ArraysMatch(expected_arrah2e, irsend.capture.state)); + fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 18C, Fan: 4 (QUIET), " + "Swing: Vert, Command: N/A", fujitsu.toString()); + + irsend.reset(); + + fujitsu.setModel(ARDB1); + irsend.sendFujitsuAC(fujitsu.getRaw(), fujitsu.getStateLength()); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits - 8, irsend.capture.bits); + uint8_t expected_ardb1[kFujitsuAcStateLength - 1] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30, + 0x20, 0x01, 0x14, 0x00, 0x00, 0x00, 0x9B}; + EXPECT_TRUE(ArraysMatch(expected_ardb1, irsend.capture.state)); + fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 18C, Fan: 4 (QUIET), " + "Swing: Vert, Command: N/A", fujitsu.toString()); +} + +TEST(TestDecodeFujitsuAC, RealShortARDB1OffExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRFujitsuAC fujitsu = IRFujitsuAC(0); + + irsend.begin(); + + irsend.reset(); + // "Off" Message recorded from an AR-DB1 remote. + uint16_t rawData[99] = { + 3310, 1636, 440, 386, 440, 394, 442, 1210, 442, 390, 414, 1220, + 444, 390, 446, 380, 446, 380, 436, 1216, 438, 1214, 438, 388, + 438, 386, 438, 396, 410, 1222, 440, 1220, 442, 384, 442, 384, + 442, 384, 442, 382, 444, 382, 442, 382, 444, 380, 446, 380, + 446, 380, 444, 380, 436, 390, 436, 388, 436, 388, 438, 1214, + 438, 386, 438, 388, 438, 386, 440, 386, 440, 384, 442, 384, + 442, 384, 442, 1210, 444, 382, 444, 382, 444, 382, 444, 380, + 446, 1206, 436, 390, 436, 388, 436, 388, 438, 388, 438, 396, + 420, 388, 436}; + irsend.sendRaw(rawData, 99, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcMinBits, irsend.capture.bits); + uint8_t expected[6] = {0x14, 0x63, 0x0, 0x10, 0x10, 0x02}; + EXPECT_TRUE(ArraysMatch(expected, irsend.capture.state)); + fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ(kFujitsuAcStateLengthShort - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (AUTO), " + "Swing: Off, Command: N/A", fujitsu.toString()); +} + +TEST(TestDecodeFujitsuAC, RealLongARDB1Example) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRFujitsuAC fujitsu = IRFujitsuAC(0); + + irsend.begin(); + irsend.reset(); + uint16_t rawData1[243] = { + 3316, 1632, 444, 390, 438, 388, 436, 1216, 438, 388, 438, 1214, + 438, 388, 438, 386, 440, 386, 440, 1212, 440, 1210, 442, 392, + 412, 396, 442, 392, 444, 1208, 444, 1208, 444, 380, 444, 380, + 446, 380, 436, 390, 436, 390, 436, 390, 436, 388, 438, 388, + 438, 388, 438, 388, 438, 386, 438, 386, 440, 384, 440, 1210, + 442, 384, 442, 382, 442, 384, 442, 384, 442, 382, 442, 382, + 444, 382, 444, 1208, 444, 382, 444, 380, 446, 380, 436, 390, + 436, 390, 436, 1214, 438, 1214, 438, 1212, 440, 1212, 440, 1220, + 412, 1222, 440, 394, 442, 382, 442, 382, 444, 1208, 444, 382, + 444, 380, 446, 380, 446, 380, 434, 390, 436, 388, 438, 388, + 438, 388, 438, 1214, 438, 1212, 440, 386, 440, 394, 412, 1222, + 440, 394, 442, 384, 442, 384, 442, 382, 442, 1208, 444, 390, + 414, 394, 442, 1216, 446, 380, 436, 390, 436, 390, 436, 388, + 436, 390, 436, 388, 438, 386, 440, 386, 440, 386, 438, 1212, + 440, 386, 440, 384, 440, 384, 442, 392, 412, 396, 440, 394, + 442, 382, 444, 382, 444, 382, 444, 380, 444, 380, 444, 382, + 444, 380, 446, 380, 436, 388, 436, 390, 436, 388, 438, 388, + 438, 388, 438, 388, 438, 386, 440, 386, 440, 386, 442, 384, + 440, 386, 442, 384, 440, 384, 442, 384, 442, 382, 442, 382, + 444, 1208, 444, 382, 444, 1208, 444, 380, 446, 1206, 436, 390, + 436, 1216, 436}; + irsend.sendRaw(rawData1, 243, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits - 8, irsend.capture.bits); + uint8_t expected1[kFujitsuAcStateLength - 1] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30, + 0x21, 0x01, 0x04, 0x00, 0x00, 0x00, 0xAA}; + EXPECT_TRUE(ArraysMatch(expected1, irsend.capture.state)); + fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 18C, Fan: 4 (QUIET), " + "Swing: Off, Command: N/A", fujitsu.toString()); + + irsend.reset(); + uint16_t rawData2[243] = { + 3316, 1630, 436, 398, 438, 386, 438, 1212, 440, 384, 440, 1212, + 442, 384, 442, 392, 414, 394, 442, 1218, 446, 1206, 436, 390, + 436, 388, 438, 388, 438, 1214, 440, 1212, 440, 384, 442, 384, + 442, 384, 442, 382, 444, 382, 444, 382, 444, 380, 446, 380, + 444, 380, 436, 390, 436, 388, 438, 396, 418, 388, 438, 1232, + 410, 396, 440, 394, 442, 384, 442, 384, 442, 382, 442, 392, + 414, 392, 444, 1216, 446, 380, 436, 390, 436, 396, 418, 390, + 436, 398, 438, 1214, 440, 1212, 440, 1210, 442, 1208, 444, 1216, + 416, 1218, 444, 388, 436, 390, 436, 388, 438, 1214, 440, 386, + 438, 386, 440, 386, 440, 384, 442, 384, 442, 384, 442, 382, + 444, 382, 444, 1206, 446, 1206, 436, 390, 436, 388, 438, 388, + 438, 386, 440, 394, 410, 396, 440, 1220, 442, 1210, 442, 392, + 414, 394, 442, 1218, 446, 406, 410, 388, 436, 390, 436, 390, + 436, 388, 438, 386, 440, 386, 440, 386, 440, 386, 440, 384, + 442, 384, 442, 384, 442, 382, 444, 382, 444, 380, 446, 380, + 446, 380, 436, 390, 436, 390, 436, 388, 438, 386, 438, 388, + 438, 386, 440, 386, 440, 384, 442, 384, 442, 384, 442, 384, + 442, 382, 444, 382, 444, 380, 446, 380, 446, 380, 436, 390, + 436, 388, 436, 388, 438, 386, 438, 386, 440, 386, 440, 1212, + 440, 1210, 442, 1210, 442, 1208, 444, 1208, 436, 390, 436, 388, + 436, 1214, 440}; + irsend.sendRaw(rawData2, 243, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits - 8, irsend.capture.bits); + uint8_t expected2[kFujitsuAcStateLength - 1] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFC, 0x08, 0x30, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x9F}; + EXPECT_TRUE(ArraysMatch(expected2, irsend.capture.state)); + fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ(kFujitsuAcStateLength - 1, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 0 (AUTO), " + "Swing: Off, Command: N/A", fujitsu.toString()); +} + +TEST(TestDecodeFujitsuAC, Issue414) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRFujitsuAC fujitsu = IRFujitsuAC(0); + + // Capture as supplied by arpmota + uint16_t rawData[259] = {3352, 1574, 480, 350, 480, 346, 480, 1190, 458, 346, + 508, 1140, 480, 346, 506, 346, 458, 346, 480, 1168, 480, 1192, 452, 374, + 458, 346, 480, 346, 508, 1168, 480, 1140, 480, 346, 506, 346, 458, 346, + 480, 346, 480, 346, 480, 346, 484, 372, 454, 374, 456, 346, 508, 318, + 480, 374, 458, 374, 480, 318, 480, 1196, 452, 346, 480, 346, 484, 342, + 484, 346, 480, 374, 458, 346, 506, 318, 508, 1170, 452, 346, 480, 374, + 458, 346, 506, 318, 480, 1196, 452, 1190, 458, 1162, 480, 1196, 452, + 1170, 480, 1190, 458, 1164, 480, 1196, 480, 318, 508, 346, 456, 1192, + 480, 346, 456, 374, 452, 346, 480, 374, 458, 342, 484, 346, 508, 346, + 456, 342, 512, 1164, 458, 1164, 508, 346, 456, 346, 480, 1190, 456, 342, + 484, 346, 506, 346, 456, 374, 452, 346, 508, 346, 458, 1164, 508, 346, + 458, 374, 452, 1168, 480, 374, 480, 318, 480, 374, 456, 346, 508, 318, + 480, 346, 484, 374, 480, 318, 484, 342, 484, 374, 480, 318, 484, 342, + 484, 346, 508, 318, 508, 346, 458, 346, 506, 318, 480, 374, 458, 346, + 506, 318, 480, 346, 484, 374, 480, 318, 482, 372, 456, 346, 508, 318, + 506, 348, 456, 342, 484, 346, 508, 318, 484, 374, 480, 318, 508, 318, + 484, 346, 508, 318, 480, 374, 456, 346, 508, 346, 480, 318, 480, 346, + 484, 374, 480, 320, 484, 1164, 508, 346, 458, 342, 512, 1164, 458, 1190, + 454, 346, 484, 1164, 508, 346, 458, 1164, 480, 350, 480, 374, 480}; + uint8_t state[16] = { + 0x14, 0x63, 0x00, 0x10, 0x10, 0xFE, 0x09, 0x30, 0x81, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x2B}; + irsend.begin(); + irsend.reset(); + irsend.sendRaw(rawData, 259, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits); + EXPECT_TRUE(ArraysMatch(state, irsend.capture.state)); + fujitsu.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ(kFujitsuAcStateLength, fujitsu.getStateLength()); + EXPECT_EQ("Power: On, Mode: 4 (HEAT), Temp: 24C, Fan: 0 (AUTO), " + "Swing: Off, Command: N/A", fujitsu.toString()); + + // Resend it using the state this time. + irsend.reset(); + irsend.sendFujitsuAC(state, 16); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(FUJITSU_AC, irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits); + EXPECT_TRUE(ArraysMatch(state, irsend.capture.state)); + EXPECT_EQ( + "m3324s1574" + "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390" + "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s1182m448s390m448s390m448s390" + "m448s390m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182m448s1182" + "m448s1182m448s390m448s390m448s1182m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s1182m448s1182m448s390m448s390" + "m448s1182m448s390m448s390m448s390m448s390m448s390m448s390m448s1182" + "m448s390m448s390m448s1182m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" + "m448s390m448s390m448s390m448s390m448s390m448s1182m448s390m448s390" + "m448s1182m448s1182m448s390m448s1182m448s390m448s1182m448s390m448s390" + "m448s8100", irsend.outputStr()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_GICable_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_GICable_test.cpp new file mode 100644 index 000000000..b9bfce997 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_GICable_test.cpp @@ -0,0 +1,161 @@ +// Copyright 2018 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendGICable(). + +// Test sending typical data only. +TEST(TestSendGICable, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + irsend.sendGICable(0); + EXPECT_EQ( + "m9000s4400" + "m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200" + "m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200" + "m550s41650" + "m9000s2200m550s87850", + irsend.outputStr()); + irsend.sendGICable(0x8807); + EXPECT_EQ( + "m9000s4400" + "m550s4400m550s2200m550s2200m550s2200m550s4400m550s2200m550s2200m550s2200" + "m550s2200m550s2200m550s2200m550s2200m550s2200m550s4400m550s4400m550s4400" + "m550s30650" + "m9000s2200m550s87850", + irsend.outputStr()); + irsend.sendGICable(0xFFFF); + EXPECT_EQ( + "m9000s4400" + "m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400" + "m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400" + "m550s6450" + "m9000s2200m550s87850", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendGICable, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + // Send a command with 0 repeats. + irsend.sendGICable(0x8807, kGicableBits, 0); + EXPECT_EQ( + "m9000s4400" + "m550s4400m550s2200m550s2200m550s2200m550s4400m550s2200m550s2200m550s2200" + "m550s2200m550s2200m550s2200m550s2200m550s2200m550s4400m550s4400m550s4400" + "m550s30650", + irsend.outputStr()); + // Send a command with 1 repeat. + irsend.sendGICable(0x8807, kGicableBits, 1); + EXPECT_EQ( + "m9000s4400" + "m550s4400m550s2200m550s2200m550s2200m550s4400m550s2200m550s2200m550s2200" + "m550s2200m550s2200m550s2200m550s2200m550s2200m550s4400m550s4400m550s4400" + "m550s30650" + "m9000s2200m550s87850", + irsend.outputStr()); + // Send a command with 3 repeats. + irsend.sendGICable(0x8807, kGicableBits, 3); + EXPECT_EQ( + "m9000s4400" + "m550s4400m550s2200m550s2200m550s2200m550s4400m550s2200m550s2200m550s2200" + "m550s2200m550s2200m550s2200m550s2200m550s2200m550s4400m550s4400m550s4400" + "m550s30650" + "m9000s2200m550s87850" + "m9000s2200m550s87850" + "m9000s2200m550s87850", + irsend.outputStr()); +} + +// Tests for decodeGICable(). +// Decode normal GICable messages. +TEST(TestDecodeGICable, SyntheticDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Synthesised Normal GICable message. + irsend.reset(); + irsend.sendGICable(0x8807); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GICABLE, irsend.capture.decode_type); + EXPECT_EQ(kGicableBits, irsend.capture.bits); + EXPECT_EQ(0x8807, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +// Decode a recorded example +TEST(TestDecodeGICable, RealExampleDecodeOK) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Real GICable "OK/Select" message. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/447 + uint16_t rawData[39] = {9064, 4408, 580, 4408, 580, 2152, 578, 2150, + 580, 2150, 580, 4408, 580, 2150, 580, 2150, + 580, 2150, 580, 2150, 580, 2150, 580, 2150, + 580, 2150, 580, 2150, 580, 4408, 580, 4408, + 580, 4408, 580, 30622, 9066, 2148, 580}; + irsend.reset(); + irsend.sendRaw(rawData, 39, 39); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GICABLE, irsend.capture.decode_type); + EXPECT_EQ(kGicableBits, irsend.capture.bits); + EXPECT_EQ(0x8807, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +TEST(TestDecodeGICable, RealExampleDecodeLEFT) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Real GICable "LEFT" message. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/447 + uint16_t rawData[39] = {9040, 4434, 554, 2176, 580, 4408, 554, 4434, + 582, 2148, 554, 4434, 580, 4408, 556, 2174, + 580, 2150, 580, 2150, 582, 2148, 556, 2176, + 580, 2150, 580, 4408, 580, 4408, 580, 4408, + 582, 2150, 580, 26078, 9066, 2148, 580}; + irsend.reset(); + irsend.sendRaw(rawData, 39, 39); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GICABLE, irsend.capture.decode_type); + EXPECT_EQ(kGicableBits, irsend.capture.bits); + EXPECT_EQ(0x6C0E, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +TEST(TestDecodeGICable, RealExampleDecodeZEROKey) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Real GICable "Zero Key" message. + // Note: Zero key looks similar to a JVC message, hence this test. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/447 + uint16_t rawData[39] = {9036, 4434, 552, 2178, 552, 2178, 552, 2180, + 550, 2178, 552, 2178, 550, 2180, 552, 2178, + 552, 2178, 550, 2180, 552, 2178, 526, 2204, + 552, 2178, 552, 2178, 526, 2204, 526, 2204, + 526, 2204, 526, 41932, 9036, 2176, 552}; + irsend.reset(); + irsend.sendRaw(rawData, 39, 39); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GICABLE, irsend.capture.decode_type); + EXPECT_EQ(kGicableBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_GlobalCache_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_GlobalCache_test.cpp new file mode 100644 index 000000000..16a556b57 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_GlobalCache_test.cpp @@ -0,0 +1,71 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendGlobalCache(). + +// Test sending a typical command wihtout a repeat. +TEST(TestSendGlobalCache, NonRepeatingCode) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + irsend.reset(); + + // Modified NEC TV "Power On" from Global Cache with no repeats + uint16_t gc_test[71] = {38000, 1, 1, 342, 172, 21, 22, 21, 21, 21, 65, 21, + 21, 21, 22, 21, 22, 21, 21, 21, 22, 21, 65, 21, + 65, 21, 22, 21, 65, 21, 65, 21, 65, 21, 65, 21, + 65, 21, 65, 21, 22, 21, 22, 21, 21, 21, 22, 21, + 22, 21, 65, 21, 22, 21, 21, 21, 65, 21, 65, 21, + 65, 21, 64, 22, 65, 21, 22, 21, 65, 21, 1519}; + irsend.sendGC(gc_test, 71); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x20DF827D, irsend.capture.value); + EXPECT_EQ(0x4, irsend.capture.address); + EXPECT_EQ(0x41, irsend.capture.command); + EXPECT_EQ( + "m8892s4472m546s572m546s546m546s1690m546s546m546s572m546s572" + "m546s546m546s572m546s1690m546s1690m546s572m546s1690m546s1690" + "m546s1690m546s1690m546s1690m546s1690m546s572m546s572m546s546" + "m546s572m546s572m546s1690m546s572m546s546m546s1690m546s1690" + "m546s1690m546s1664m572s1690m546s572m546s1690m546s39494", + irsend.outputStr()); +} + +// Test sending typical command with repeats. +TEST(TestSendGlobalCache, RepeatCode) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + irsend.reset(); + + // Sherwood (NEC-like) "Power On" from Global Cache with 2 repeats + uint16_t gc_test[75] = { + 38000, 2, 69, 341, 171, 21, 64, 21, 64, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 64, 21, 64, 21, 21, 21, 64, 21, 21, 21, + 21, 21, 21, 21, 64, 21, 21, 21, 64, 21, 21, 21, 21, 21, 21, + 21, 64, 21, 21, 21, 21, 21, 21, 21, 21, 21, 64, 21, 64, 21, + 64, 21, 21, 21, 64, 21, 64, 21, 64, 21, 1600, 341, 85, 21, 3647}; + irsend.sendGC(gc_test, 75); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0xC1A28877, irsend.capture.value); + EXPECT_EQ(0x4583, irsend.capture.address); + EXPECT_EQ(0x11, irsend.capture.command); + EXPECT_EQ( + "m8866s4446m546s1664m546s1664m546s546m546s546m546s546m546s546" + "m546s546m546s1664m546s1664m546s546m546s1664m546s546m546s546" + "m546s546m546s1664m546s546m546s1664m546s546m546s546m546s546" + "m546s1664m546s546m546s546m546s546m546s546m546s1664m546s1664" + "m546s1664m546s546m546s1664m546s1664m546s1664m546s41600" + "m8866s2210m546s94822" + "m8866s2210m546s94822", + irsend.outputStr()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Gree_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Gree_test.cpp new file mode 100644 index 000000000..6c7a1f637 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Gree_test.cpp @@ -0,0 +1,527 @@ +// Copyright 2017 David Conran + +#include "ir_Gree.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendGree(). + +// Test sending typical data only. +TEST(TestSendGreeChars, SendData) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t gree_code[kGreeStateLength] = {0x12, 0x34, 0x56, 0x78, + 0x90, 0xAB, 0xCD, 0xEF}; + irsend.reset(); + irsend.sendGree(gree_code); + EXPECT_EQ( + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s19000", + irsend.outputStr()); +} + +TEST(TestSendGreeUint64, SendData) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendGree(0x1234567890ABCDEF); + EXPECT_EQ( + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s19000", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendGreeChars, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + uint8_t gree_code[kGreeStateLength] = {0x12, 0x34, 0x56, 0x78, + 0x90, 0xAB, 0xCD, 0xEF}; + irsend.reset(); + + irsend.sendGree(gree_code, kGreeStateLength, 1); + EXPECT_EQ( + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s19000" + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s19000", + irsend.outputStr()); +} + +TEST(TestSendGreeUint64, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendGree(0x1234567890ABCDEF, kGreeBits, 1); + EXPECT_EQ( + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s19000" + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s19000", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendGreeChars, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t gree_short_code[kGreeStateLength - 1] = {0x12, 0x34, 0x56, 0x78, + 0x90, 0xAB, 0xCD}; + uint8_t gree_long_code[kGreeStateLength + 1] = {0x12, 0x34, 0x56, 0x78, 0x90, + 0xAB, 0xCD, 0xEF, 0x12}; + irsend.reset(); + irsend.sendGree(gree_short_code, kGreeStateLength - 1); + ASSERT_EQ("", irsend.outputStr()); + + irsend.reset(); + irsend.sendGree(gree_long_code, kGreeStateLength + 1); + ASSERT_EQ( + "m9000s4000" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" + "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" + "m620s540m620s540m620s540m620s1600m620s1600m620s1600m620s1600m620s540" + "m620s540m620s1600m620s540" + "m620s19000" + "m620s540m620s540m620s540m620s540m620s1600m620s540m620s540m620s1600" + "m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540m620s1600" + "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" + "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" + "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" + "m620s19000", + irsend.outputStr()); +} + +TEST(TestSendGreeUint64, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendGree(0x1234567890ABCDEF, kGreeBits - 1); + ASSERT_EQ("", irsend.outputStr()); + + irsend.reset(); + irsend.sendGree(0x1234567890ABCDEF, kGreeBits + 1); + ASSERT_EQ("", irsend.outputStr()); +} + +TEST(TestSendGree, CompareUint64ToCharResults) { + IRsendTest irsend_chars(4); + IRsendTest irsend_uint64(0); + + uint8_t gree_code[kGreeStateLength] = {0x12, 0x34, 0x56, 0x78, + 0x90, 0xAB, 0xCD, 0xEF}; + + irsend_chars.begin(); + irsend_uint64.begin(); + + irsend_chars.reset(); + irsend_uint64.reset(); + irsend_chars.sendGree(gree_code); + irsend_uint64.sendGree(0x1234567890ABCDEF); + ASSERT_EQ(irsend_chars.outputStr(), irsend_uint64.outputStr()); + + uint8_t gree_zero_code[kGreeStateLength] = {0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + irsend_chars.reset(); + irsend_uint64.reset(); + irsend_chars.sendGree(gree_zero_code); + irsend_uint64.sendGree((uint64_t)0x0); + ASSERT_EQ(irsend_chars.outputStr(), irsend_uint64.outputStr()); +} + +// Tests for IRGreeAC class. + +TEST(TestGreeClass, Power) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.on(); + EXPECT_TRUE(irgree.getPower()); + + irgree.off(); + EXPECT_FALSE(irgree.getPower()); + + irgree.setPower(true); + EXPECT_TRUE(irgree.getPower()); + + irgree.setPower(false); + EXPECT_FALSE(irgree.getPower()); +} + +TEST(TestGreeClass, Temperature) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setMode(kGreeCool); + + irgree.setTemp(0); + EXPECT_EQ(kGreeMinTemp, irgree.getTemp()); + + irgree.setTemp(255); + EXPECT_EQ(kGreeMaxTemp, irgree.getTemp()); + + irgree.setTemp(kGreeMinTemp); + EXPECT_EQ(kGreeMinTemp, irgree.getTemp()); + + irgree.setTemp(kGreeMaxTemp); + EXPECT_EQ(kGreeMaxTemp, irgree.getTemp()); + + irgree.setTemp(kGreeMinTemp - 1); + EXPECT_EQ(kGreeMinTemp, irgree.getTemp()); + + irgree.setTemp(kGreeMaxTemp + 1); + EXPECT_EQ(kGreeMaxTemp, irgree.getTemp()); + + irgree.setTemp(17); + EXPECT_EQ(17, irgree.getTemp()); + + irgree.setTemp(21); + EXPECT_EQ(21, irgree.getTemp()); + + irgree.setTemp(25); + EXPECT_EQ(25, irgree.getTemp()); + + irgree.setTemp(29); + EXPECT_EQ(29, irgree.getTemp()); +} + +TEST(TestGreeClass, OperatingMode) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setTemp(17); + irgree.setMode(kGreeAuto); // Auto should lock the temp to 25C. + EXPECT_EQ(kGreeAuto, irgree.getMode()); + EXPECT_EQ(25, irgree.getTemp()); + irgree.setTemp(17); + EXPECT_EQ(25, irgree.getTemp()); + + irgree.setMode(kGreeCool); + EXPECT_EQ(kGreeCool, irgree.getMode()); + + irgree.setMode(kGreeHeat); + EXPECT_EQ(kGreeHeat, irgree.getMode()); + + ASSERT_NE(kGreeFanMax, 1); + irgree.setFan(kGreeFanMax); + irgree.setMode(kGreeDry); // Dry should lock the fan to speed 1. + EXPECT_EQ(kGreeDry, irgree.getMode()); + EXPECT_EQ(1, irgree.getFan()); + irgree.setFan(kGreeFanMax); + EXPECT_EQ(1, irgree.getFan()); + + irgree.setMode(kGreeFan); + EXPECT_EQ(kGreeFan, irgree.getMode()); + + irgree.setMode(kGreeHeat + 1); + EXPECT_EQ(kGreeAuto, irgree.getMode()); + + irgree.setMode(255); + EXPECT_EQ(kGreeAuto, irgree.getMode()); +} + +TEST(TestGreeClass, Light) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setLight(true); + EXPECT_TRUE(irgree.getLight()); + + irgree.setLight(false); + EXPECT_FALSE(irgree.getLight()); + + irgree.setLight(true); + EXPECT_TRUE(irgree.getLight()); +} + +TEST(TestGreeClass, XFan) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setXFan(true); + EXPECT_TRUE(irgree.getXFan()); + + irgree.setXFan(false); + EXPECT_FALSE(irgree.getXFan()); + + irgree.setXFan(true); + EXPECT_TRUE(irgree.getXFan()); +} + +TEST(TestGreeClass, Turbo) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setTurbo(true); + EXPECT_TRUE(irgree.getTurbo()); + + irgree.setTurbo(false); + EXPECT_FALSE(irgree.getTurbo()); + + irgree.setTurbo(true); + EXPECT_TRUE(irgree.getTurbo()); +} + +TEST(TestGreeClass, Sleep) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setSleep(true); + EXPECT_TRUE(irgree.getSleep()); + + irgree.setSleep(false); + EXPECT_FALSE(irgree.getSleep()); + + irgree.setSleep(true); + EXPECT_TRUE(irgree.getSleep()); +} + +TEST(TestGreeClass, FanSpeed) { + IRGreeAC irgree(0); + irgree.begin(); + + irgree.setFan(0); + EXPECT_EQ(0, irgree.getFan()); + + irgree.setFan(255); + EXPECT_EQ(kGreeFanMax, irgree.getFan()); + + irgree.setFan(kGreeFanMax); + EXPECT_EQ(kGreeFanMax, irgree.getFan()); + + irgree.setFan(kGreeFanMax + 1); + EXPECT_EQ(kGreeFanMax, irgree.getFan()); + + irgree.setFan(kGreeFanMax - 1); + EXPECT_EQ(kGreeFanMax - 1, irgree.getFan()); + + irgree.setFan(1); + EXPECT_EQ(1, irgree.getFan()); + + irgree.setFan(1); + EXPECT_EQ(1, irgree.getFan()); + + irgree.setFan(3); + EXPECT_EQ(3, irgree.getFan()); +} + +TEST(TestGreeClass, VerticalSwing) { + IRGreeAC irgree(0); + irgree.begin(); + EXPECT_FALSE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingLastPos, irgree.getSwingVerticalPosition()); + + irgree.setSwingVertical(true, kGreeSwingAuto); + EXPECT_TRUE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingAuto, irgree.getSwingVerticalPosition()); + + irgree.setSwingVertical(false, kGreeSwingMiddle); + EXPECT_FALSE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingMiddle, irgree.getSwingVerticalPosition()); + + irgree.setSwingVertical(true, kGreeSwingDownAuto); + EXPECT_TRUE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingDownAuto, irgree.getSwingVerticalPosition()); + + // Out of bounds. + irgree.setSwingVertical(false, 255); + EXPECT_FALSE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingLastPos, irgree.getSwingVerticalPosition()); + irgree.setSwingVertical(false, kGreeSwingAuto); + EXPECT_FALSE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingLastPos, irgree.getSwingVerticalPosition()); + + irgree.setSwingVertical(true, 255); + EXPECT_TRUE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingAuto, irgree.getSwingVerticalPosition()); + irgree.setSwingVertical(true, kGreeSwingDown); + EXPECT_TRUE(irgree.getSwingVerticalAuto()); + EXPECT_EQ(kGreeSwingAuto, irgree.getSwingVerticalPosition()); +} + +TEST(TestGreeClass, SetAndGetRaw) { + IRGreeAC irgree(0); + uint8_t initialState[kGreeStateLength] = {0x00, 0x09, 0x20, 0x50, + 0x00, 0x20, 0x00, 0x50}; + uint8_t expectedState[kGreeStateLength] = {0xA9, 0x05, 0xD0, 0x50, + 0x00, 0x20, 0x00, 0xA0}; + + EXPECT_STATE_EQ(initialState, irgree.getRaw(), kGreeBits); + + // toggle the power state. + irgree.setPower(!irgree.getPower()); + irgree.setMode(kGreeCool); + irgree.setTemp(21); + irgree.setFan(2); + irgree.setLight(false); + irgree.setTurbo(true); + irgree.setSleep(true); + irgree.setXFan(true); + + EXPECT_EQ(kGreeCool, irgree.getMode()); + EXPECT_EQ(21, irgree.getTemp()); + EXPECT_EQ(2, irgree.getFan()); + EXPECT_FALSE(irgree.getLight()); + EXPECT_TRUE(irgree.getTurbo()); + EXPECT_TRUE(irgree.getSleep()); + EXPECT_TRUE(irgree.getXFan()); + + EXPECT_STATE_EQ(expectedState, irgree.getRaw(), kGreeBits); + irgree.setRaw(initialState); + EXPECT_STATE_EQ(initialState, irgree.getRaw(), kGreeBits); +} + +TEST(TestGreeClass, HumanReadable) { + IRGreeAC irgree(0); + + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 0 (AUTO), Turbo: Off, " + "XFan: Off, Light: On, Sleep: Off, Swing Vertical Mode: Manual, " + "Swing Vertical Pos: 0 (Last Pos)", + irgree.toString()); + irgree.on(); + irgree.setMode(kGreeCool); + irgree.setTemp(kGreeMinTemp); + irgree.setFan(kGreeFanMax); + irgree.setXFan(true); + irgree.setSleep(true); + irgree.setLight(false); + irgree.setTurbo(true); + irgree.setSwingVertical(true, kGreeSwingAuto); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 3 (MAX), Turbo: On, " + "XFan: On, Light: Off, Sleep: On, Swing Vertical Mode: Auto, " + "Swing Vertical Pos: 1 (Auto)", + irgree.toString()); +} + +// Tests for decodeGree(). + +// Decode a synthetic Gree message. +TEST(TestDecodeGree, NormalSynthetic) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + uint8_t gree_code[kGreeStateLength] = {0x00, 0x09, 0x20, 0x50, + 0x00, 0x20, 0x00, 0x50}; + + irsend.reset(); + irsend.sendGree(gree_code); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GREE, irsend.capture.decode_type); + ASSERT_EQ(kGreeBits, irsend.capture.bits); + EXPECT_STATE_EQ(gree_code, irsend.capture.state, kGreeBits); +} + +// Decode a synthetic Gree message. +TEST(TestDecodeGree, NormalRealExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + IRGreeAC irgree(4); + irsend.begin(); + + uint8_t gree_code[kGreeStateLength] = {0x19, 0x0A, 0x60, 0x50, + 0x02, 0x23, 0x00, 0xF0}; + + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/386 + uint16_t rawData[139] = { + 9008, 4496, 644, 1660, 676, 530, 648, 558, 672, 1636, 646, 1660, + 644, 556, 650, 584, 626, 560, 644, 580, 628, 1680, 624, 560, + 648, 1662, 644, 582, 648, 536, 674, 530, 646, 580, 628, 560, + 670, 532, 646, 562, 644, 556, 672, 536, 648, 1662, 646, 1660, + 652, 554, 644, 558, 672, 538, 644, 560, 668, 560, 648, 1638, + 668, 536, 644, 1660, 668, 532, 648, 560, 648, 1660, 674, 554, + 622, 19990, 646, 580, 624, 1660, 648, 556, 648, 558, 674, 556, + 622, 560, 644, 564, 668, 536, 646, 1662, 646, 1658, 672, 534, + 648, 558, 644, 562, 648, 1662, 644, 584, 622, 558, 648, 562, + 668, 534, 670, 536, 670, 532, 672, 536, 646, 560, 646, 558, + 648, 558, 670, 534, 650, 558, 646, 560, 646, 560, 668, 1638, + 646, 1662, 646, 1660, 646, 1660, 648}; // Issue #386 + + irsend.reset(); + irsend.sendRaw(rawData, 139, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GREE, irsend.capture.decode_type); + ASSERT_EQ(kGreeBits, irsend.capture.bits); + EXPECT_STATE_EQ(gree_code, irsend.capture.state, kGreeBits); + irgree.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 26C, Fan: 1, Turbo: Off, " + "XFan: Off, Light: On, Sleep: Off, Swing Vertical Mode: Manual, " + "Swing Vertical Pos: 2", + irgree.toString()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Haier_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Haier_test.cpp new file mode 100644 index 000000000..11848e00a --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Haier_test.cpp @@ -0,0 +1,989 @@ +// Copyright 2018 David Conran + +#include "ir_Haier.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendHaierAC() + +// Test sending typical data only. +TEST(TestSendHaierAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + uint8_t haier_zero[kHaierACStateLength] = {0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + + irsend.reset(); + irsend.sendHaierAC(haier_zero); + EXPECT_EQ( + "m3000s3000m3000s4300" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s150000", + irsend.outputStr()); + + uint8_t haier_test[kHaierACStateLength] = {0xA5, 0x01, 0x20, 0x01, 0x00, + 0xC0, 0x20, 0x00, 0xA7}; + irsend.reset(); + irsend.sendHaierAC(haier_test); + EXPECT_EQ( + "m3000s3000m3000s4300" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s1650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s1650m520s1650" + "m520s150000", + irsend.outputStr()); +} + +// Test sending typical data with repeats. +TEST(TestSendHaierAC, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + uint8_t haier_test[kHaierACStateLength] = {0xA5, 0x01, 0x20, 0x01, 0x00, + 0xC0, 0x20, 0x00, 0xA7}; + irsend.reset(); + irsend.sendHaierAC(haier_test, kHaierACStateLength, 2); // two repeats. + EXPECT_EQ( + "m3000s3000m3000s4300" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s1650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s1650m520s1650" + "m520s150000" + "m3000s3000m3000s4300" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s1650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s1650m520s1650" + "m520s150000" + "m3000s3000m3000s4300" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s1650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s1650m520s650m520s650m520s650m520s650m520s650" + "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" + "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s1650m520s1650" + "m520s150000", + irsend.outputStr()); +} + +// Tests for IRHaierAC class. + +TEST(TestHaierACClass, Command) { + IRHaierAC haier(0); + haier.begin(); + + haier.setCommand(kHaierAcCmdOff); + EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); + haier.setCommand(kHaierAcCmdOn); + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + haier.setCommand(kHaierAcCmdMode); + EXPECT_EQ(kHaierAcCmdMode, haier.getCommand()); + haier.setCommand(kHaierAcCmdFan); + EXPECT_EQ(kHaierAcCmdFan, haier.getCommand()); + haier.setCommand(kHaierAcCmdTempUp); + EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); + haier.setCommand(kHaierAcCmdTempDown); + EXPECT_EQ(kHaierAcCmdTempDown, haier.getCommand()); + haier.setCommand(kHaierAcCmdSleep); + EXPECT_EQ(kHaierAcCmdSleep, haier.getCommand()); + haier.setCommand(kHaierAcCmdTimerSet); + EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); + haier.setCommand(kHaierAcCmdTimerCancel); + EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand()); + haier.setCommand(kHaierAcCmdHealth); + EXPECT_EQ(kHaierAcCmdHealth, haier.getCommand()); + haier.setCommand(kHaierAcCmdSwing); + EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); + haier.setCommand(kHaierAcCmdOn); + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + + // Test unexpected values. + haier.setCommand(0b00001110); + EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); + haier.setCommand(0b00001111); + EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); + haier.setCommand(0b00000100); + EXPECT_EQ(kHaierAcCmdOff, haier.getCommand()); +} + +TEST(TestHaierACClass, OperatingMode) { + IRHaierAC haier(0); + haier.begin(); + + haier.setMode(kHaierAcAuto); + EXPECT_EQ(kHaierAcAuto, haier.getMode()); + + haier.setMode(kHaierAcCool); + EXPECT_EQ(kHaierAcCool, haier.getMode()); + + haier.setMode(kHaierAcHeat); + EXPECT_EQ(kHaierAcHeat, haier.getMode()); + + haier.setMode(kHaierAcFan); + EXPECT_EQ(kHaierAcFan, haier.getMode()); + + haier.setMode(kHaierAcDry); + EXPECT_EQ(kHaierAcDry, haier.getMode()); + + haier.setMode(kHaierAcAuto - 1); + EXPECT_EQ(kHaierAcAuto, haier.getMode()); + + haier.setMode(kHaierAcCool); + EXPECT_EQ(kHaierAcCool, haier.getMode()); + + haier.setMode(kHaierAcFan + 1); + EXPECT_EQ(kHaierAcAuto, haier.getMode()); + + haier.setMode(255); + EXPECT_EQ(kHaierAcAuto, haier.getMode()); +} + +TEST(TestHaierACClass, Temperature) { + IRHaierAC haier(0); + haier.begin(); + + haier.setTemp(kHaierAcMinTemp); + EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + + haier.setCommand(kHaierAcCmdOn); + haier.setTemp(kHaierAcMinTemp + 1); + EXPECT_EQ(kHaierAcMinTemp + 1, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); + + haier.setTemp(kHaierAcMaxTemp); + EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); + + haier.setTemp(kHaierAcMinTemp - 1); + EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempDown, haier.getCommand()); + + haier.setTemp(kHaierAcMaxTemp + 1); + EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); + + haier.setTemp(23); + EXPECT_EQ(23, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempDown, haier.getCommand()); + haier.setCommand(kHaierAcCmdOn); + haier.setTemp(23); + EXPECT_EQ(23, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + + haier.setTemp(0); + EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempDown, haier.getCommand()); + + haier.setTemp(255); + EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcCmdTempUp, haier.getCommand()); +} + +TEST(TestHaierACClass, FanSpeed) { + IRHaierAC haier(0); + haier.begin(); + haier.setFan(kHaierAcFanLow); + haier.setCommand(kHaierAcCmdOn); + + haier.setFan(kHaierAcFanAuto); + EXPECT_EQ(kHaierAcFanAuto, haier.getFan()); + EXPECT_EQ(kHaierAcCmdFan, haier.getCommand()); + + haier.setFan(kHaierAcFanLow); + EXPECT_EQ(kHaierAcFanLow, haier.getFan()); + haier.setFan(kHaierAcFanMed); + EXPECT_EQ(kHaierAcFanMed, haier.getFan()); + haier.setFan(kHaierAcFanHigh); + EXPECT_EQ(kHaierAcFanHigh, haier.getFan()); + + haier.setCommand(kHaierAcCmdOn); + haier.setFan(kHaierAcFanHigh); + EXPECT_EQ(kHaierAcFanHigh, haier.getFan()); + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); +} + +TEST(TestHaierACClass, Swing) { + IRHaierAC haier(0); + haier.begin(); + haier.setFan(kHaierAcFanLow); + haier.setCommand(kHaierAcCmdOn); + + haier.setSwing(kHaierAcSwingOff); + EXPECT_EQ(kHaierAcSwingOff, haier.getSwing()); + + haier.setSwing(kHaierAcSwingUp); + EXPECT_EQ(kHaierAcSwingUp, haier.getSwing()); + EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); + + haier.setSwing(kHaierAcSwingDown); + EXPECT_EQ(kHaierAcSwingDown, haier.getSwing()); + EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); + + haier.setSwing(kHaierAcSwingChg); + EXPECT_EQ(kHaierAcSwingChg, haier.getSwing()); + EXPECT_EQ(kHaierAcCmdSwing, haier.getCommand()); +} + +TEST(TestHaierACClass, CurrentTime) { + IRHaierAC haier(0); + haier.begin(); + EXPECT_EQ(0, haier.getCurrTime()); + + haier.setCurrTime(1); + EXPECT_EQ(1, haier.getCurrTime()); + + haier.setCurrTime(60); + EXPECT_EQ(60, haier.getCurrTime()); + + haier.setCurrTime(61); + EXPECT_EQ(61, haier.getCurrTime()); + + haier.setCurrTime(18 * 60 + 34); // 18:34 + EXPECT_EQ(1114, haier.getCurrTime()); + + haier.setCurrTime(23 * 60 + 59); // 23:59 + EXPECT_EQ(kHaierAcMaxTime, haier.getCurrTime()); // 23:59 + + haier.setCurrTime(23 * 60 + 59 + 1); // 24:00 + EXPECT_EQ(kHaierAcMaxTime, haier.getCurrTime()); // 23:59 + + haier.setCurrTime(UINT16_MAX); + EXPECT_EQ(kHaierAcMaxTime, haier.getCurrTime()); // 23:59 +} + +TEST(TestHaierACClass, Timers) { + IRHaierAC haier(0); + haier.begin(); + + haier.setCommand(kHaierAcCmdOn); + + // Off by default. + EXPECT_GT(0, haier.getOnTimer()); + EXPECT_GT(0, haier.getOffTimer()); + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + + // On Timer. + haier.setOnTimer(6 * 60); // 6am + EXPECT_EQ(6 * 60, haier.getOnTimer()); // 6am + EXPECT_GT(0, haier.getOffTimer()); + EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); + + haier.setCommand(kHaierAcCmdOn); + EXPECT_EQ(6 * 60, haier.getOnTimer()); // 6am + EXPECT_GT(0, haier.getOffTimer()); + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + + haier.cancelTimers(); + EXPECT_GT(0, haier.getOnTimer()); + EXPECT_GT(0, haier.getOffTimer()); + EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand()); + + // Off Timer. + haier.setOffTimer(18 * 60 + 30); // 6:30pm + EXPECT_GT(0, haier.getOnTimer()); + EXPECT_EQ(18 * 60 + 30, haier.getOffTimer()); // 6:30pm + EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); + + haier.setCommand(kHaierAcCmdOn); + EXPECT_GT(0, haier.getOnTimer()); + EXPECT_EQ(18 * 60 + 30, haier.getOffTimer()); // 6:30pm + EXPECT_EQ(kHaierAcCmdOn, haier.getCommand()); + + haier.cancelTimers(); + EXPECT_GT(0, haier.getOnTimer()); + EXPECT_GT(0, haier.getOffTimer()); + EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand()); + + // Both Timers. + haier.setOnTimer(6 * 60); // 6am + EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); + haier.setOffTimer(18 * 60 + 30); // 6:30pm + EXPECT_EQ(kHaierAcCmdTimerSet, haier.getCommand()); + EXPECT_EQ(6 * 60, haier.getOnTimer()); // 6am + EXPECT_EQ(18 * 60 + 30, haier.getOffTimer()); // 6:30pm + + haier.cancelTimers(); + EXPECT_GT(0, haier.getOnTimer()); + EXPECT_GT(0, haier.getOffTimer()); + EXPECT_EQ(kHaierAcCmdTimerCancel, haier.getCommand()); +} + +TEST(TestHaierACClass, TimeToString) { + EXPECT_EQ("00:00", IRHaierAC::timeToString(0)); + EXPECT_EQ("00:01", IRHaierAC::timeToString(1)); + EXPECT_EQ("00:10", IRHaierAC::timeToString(10)); + EXPECT_EQ("00:59", IRHaierAC::timeToString(59)); + + EXPECT_EQ("01:00", IRHaierAC::timeToString(60)); + EXPECT_EQ("01:01", IRHaierAC::timeToString(61)); + EXPECT_EQ("01:59", IRHaierAC::timeToString(60 + 59)); + EXPECT_EQ("18:59", IRHaierAC::timeToString(18 * 60 + 59)); + EXPECT_EQ("23:59", IRHaierAC::timeToString(23 * 60 + 59)); +} + +TEST(TestHaierACClass, MessageConstuction) { + IRHaierAC haier(0); + + EXPECT_EQ( + "Command: 1 (On), Mode: 0 (AUTO), Temp: 25C, Fan: 0 (AUTO), " + "Swing: 0 (Off), Sleep: Off, Health: Off, " + "Current Time: 00:00, On Timer: Off, Off Timer: Off", + haier.toString()); + haier.setMode(kHaierAcCool); + haier.setTemp(21); + haier.setFan(kHaierAcFanHigh); + EXPECT_EQ( + "Command: 3 (Fan), Mode: 1 (COOL), Temp: 21C, Fan: 3 (MAX), " + "Swing: 0 (Off), Sleep: Off, Health: Off, " + "Current Time: 00:00, On Timer: Off, Off Timer: Off", + haier.toString()); + haier.setSwing(kHaierAcSwingChg); + haier.setHealth(true); + haier.setSleep(true); + haier.setCurrTime(615); // 10:15am + EXPECT_EQ( + "Command: 8 (Sleep), Mode: 3 (HEAT), Temp: 21C, Fan: 3 (MAX), " + "Swing: 3 (Chg), Sleep: On, Health: On, " + "Current Time: 10:15, On Timer: Off, Off Timer: Off", + haier.toString()); + haier.setOnTimer(800); // 1:20pm + haier.setOffTimer(1125); // 6:45pm + haier.setCommand(kHaierAcCmdOn); + + EXPECT_EQ( + "Command: 1 (On), Mode: 2 (DRY), Temp: 21C, Fan: 2, " + "Swing: 3 (Chg), Sleep: On, Health: On, " + "Current Time: 10:15, On Timer: 13:20, Off Timer: 18:45", + haier.toString()); + + // Now change a few already set things. + haier.setMode(kHaierAcHeat); + EXPECT_EQ( + "Command: 2 (Mode), Mode: 3 (HEAT), Temp: 21C, Fan: 2, " + "Swing: 3 (Chg), Sleep: On, Health: On, " + "Current Time: 10:15, On Timer: 13:52, Off Timer: 18:45", + haier.toString()); + + haier.setTemp(25); + EXPECT_EQ( + "Command: 6 (Temp Up), Mode: 3 (HEAT), Temp: 25C, Fan: 2, " + "Swing: 3 (Chg), Sleep: On, Health: On, " + "Current Time: 10:15, On Timer: 13:52, Off Timer: 18:45", + haier.toString()); + + uint8_t expectedState[kHaierACStateLength] = {0xA5, 0x96, 0xEA, 0xCF, 0x32, + 0x2D, 0x0D, 0x74, 0xD4}; + EXPECT_STATE_EQ(expectedState, haier.getRaw(), kHaierACBits); + + // Check that the checksum is valid. + EXPECT_TRUE(IRHaierAC::validChecksum(haier.getRaw())); + + // Now load up some random data. + uint8_t randomState[kHaierACStateLength] = {0x52, 0x49, 0x50, 0x20, 0x54, + 0x61, 0x6C, 0x69, 0x61}; + EXPECT_FALSE(IRHaierAC::validChecksum(randomState)); + haier.setRaw(randomState); + EXPECT_EQ( + "Command: 9 (Timer Set), Mode: 3 (HEAT), Temp: 20C, Fan: 2, " + "Swing: 1 (Up), Sleep: On, Health: Off, " + "Current Time: 16:32, On Timer: Off, Off Timer: Off", + haier.toString()); + // getRaw() should correct the checksum. + EXPECT_TRUE(IRHaierAC::validChecksum(haier.getRaw())); +} + +// Tests for the IRHaierACYRW02 class. + +TEST(TestHaierACYRW02Class, Button) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setButton(kHaierAcYrw02ButtonPower); + EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + haier.setButton(kHaierAcYrw02ButtonMode); + EXPECT_EQ(kHaierAcYrw02ButtonMode, haier.getButton()); + haier.setButton(kHaierAcYrw02ButtonSleep); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, haier.getButton()); + haier.setButton(kHaierAcYrw02ButtonFan); + + // Test unexpected values. + haier.setButton(0xFF); + EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + haier.setButton(0x10); + EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); +} + +TEST(TestHaierACYRW02Class, OperatingMode) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setButton(kHaierAcYrw02ButtonPower); + haier.setMode(kHaierAcYrw02Auto); + EXPECT_EQ(kHaierAcYrw02Auto, haier.getMode()); + EXPECT_EQ(kHaierAcYrw02ButtonMode, haier.getButton()); + + haier.setMode(kHaierAcYrw02Cool); + EXPECT_EQ(kHaierAcYrw02Cool, haier.getMode()); + + haier.setMode(kHaierAcYrw02Heat); + EXPECT_EQ(kHaierAcYrw02Heat, haier.getMode()); + + haier.setMode(kHaierAcYrw02Fan); + EXPECT_EQ(kHaierAcYrw02Fan, haier.getMode()); + + haier.setMode(kHaierAcYrw02Dry); + EXPECT_EQ(kHaierAcYrw02Dry, haier.getMode()); + + haier.setMode(kHaierAcYrw02Auto - 1); + EXPECT_EQ(kHaierAcYrw02Auto, haier.getMode()); + + haier.setMode(kHaierAcYrw02Cool); + EXPECT_EQ(kHaierAcYrw02Cool, haier.getMode()); + + haier.setMode(kHaierAcYrw02Fan + 1); + EXPECT_EQ(kHaierAcYrw02Auto, haier.getMode()); + + haier.setMode(255); + EXPECT_EQ(kHaierAcYrw02Auto, haier.getMode()); +} + +TEST(TestHaierACYRW02Class, Temperature) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setTemp(kHaierAcMinTemp); + EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + + haier.setButton(kHaierAcYrw02ButtonPower); + haier.setTemp(kHaierAcMinTemp + 1); + EXPECT_EQ(kHaierAcMinTemp + 1, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + + haier.setTemp(kHaierAcMaxTemp); + EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + + haier.setTemp(kHaierAcMinTemp - 1); + EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, haier.getButton()); + + haier.setTemp(kHaierAcMaxTemp + 1); + EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + + haier.setTemp(23); + EXPECT_EQ(23, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, haier.getButton()); + haier.setButton(kHaierAcYrw02ButtonPower); + haier.setTemp(23); + EXPECT_EQ(23, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + + haier.setTemp(0); + EXPECT_EQ(kHaierAcMinTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempDown, haier.getButton()); + + haier.setTemp(255); + EXPECT_EQ(kHaierAcMaxTemp, haier.getTemp()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); +} + +TEST(TestHaierACYRW02Class, HealthMode) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setHealth(true); + EXPECT_TRUE(haier.getHealth()); + EXPECT_EQ(kHaierAcYrw02ButtonHealth, haier.getButton()); + + haier.setButton(kHaierAcYrw02ButtonTempUp); + haier.setHealth(false); + EXPECT_FALSE(haier.getHealth()); + EXPECT_EQ(kHaierAcYrw02ButtonHealth, haier.getButton()); + + haier.setHealth(true); + EXPECT_TRUE(haier.getHealth()); + EXPECT_EQ(kHaierAcYrw02ButtonHealth, haier.getButton()); +} + +TEST(TestHaierACYRW02Class, Power) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setPower(true); + EXPECT_TRUE(haier.getPower()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + + haier.setButton(kHaierAcYrw02ButtonTempUp); + haier.setPower(false); + EXPECT_FALSE(haier.getPower()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + + haier.setPower(true); + EXPECT_TRUE(haier.getPower()); + EXPECT_EQ(kHaierAcYrw02ButtonPower, haier.getButton()); + + haier.off(); + EXPECT_FALSE(haier.getPower()); + haier.on(); + EXPECT_TRUE(haier.getPower()); +} + +TEST(TestHaierACYRW02Class, SleepMode) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setSleep(true); + EXPECT_TRUE(haier.getSleep()); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, haier.getButton()); + + haier.setButton(kHaierAcYrw02ButtonTempUp); + haier.setSleep(false); + EXPECT_FALSE(haier.getSleep()); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, haier.getButton()); + + haier.setSleep(true); + EXPECT_TRUE(haier.getSleep()); + EXPECT_EQ(kHaierAcYrw02ButtonSleep, haier.getButton()); +} + +TEST(TestHaierACYRW02Class, TurboMode) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setTurbo(kHaierAcYrw02TurboOff); + EXPECT_EQ(kHaierAcYrw02TurboOff, haier.getTurbo()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, haier.getButton()); + + haier.setButton(kHaierAcYrw02ButtonTempUp); + + haier.setTurbo(kHaierAcYrw02TurboLow); + EXPECT_EQ(kHaierAcYrw02TurboLow, haier.getTurbo()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, haier.getButton()); + + haier.setTurbo(kHaierAcYrw02TurboHigh); + EXPECT_EQ(kHaierAcYrw02TurboHigh, haier.getTurbo()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, haier.getButton()); + + haier.setTurbo(kHaierAcYrw02TurboOff); + EXPECT_EQ(kHaierAcYrw02TurboOff, haier.getTurbo()); + EXPECT_EQ(kHaierAcYrw02ButtonTurbo, haier.getButton()); +} + +TEST(TestHaierACYRW02Class, Fan) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setFan(kHaierAcYrw02FanAuto); + EXPECT_EQ(kHaierAcYrw02FanAuto, haier.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + + haier.setButton(kHaierAcYrw02ButtonTempUp); + + haier.setFan(kHaierAcYrw02FanLow); + EXPECT_EQ(kHaierAcYrw02FanLow, haier.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + + haier.setFan(kHaierAcYrw02FanHigh); + EXPECT_EQ(kHaierAcYrw02FanHigh, haier.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + + haier.setFan(kHaierAcYrw02FanMed); + EXPECT_EQ(kHaierAcYrw02FanMed, haier.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonFan, haier.getButton()); + + // Test unexpected values. + haier.setButton(kHaierAcYrw02ButtonTempUp); + haier.setFan(0x00); + EXPECT_EQ(kHaierAcYrw02FanMed, haier.getFan()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); +} + +TEST(TestHaierACYRW02Class, Swing) { + IRHaierACYRW02 haier(0); + haier.begin(); + + haier.setSwing(kHaierAcYrw02SwingOff); + EXPECT_EQ(kHaierAcYrw02SwingOff, haier.getSwing()); + EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + + haier.setButton(kHaierAcYrw02ButtonTempUp); + + haier.setSwing(kHaierAcYrw02SwingAuto); + EXPECT_EQ(kHaierAcYrw02SwingAuto, haier.getSwing()); + EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + + haier.setSwing(kHaierAcYrw02SwingTop); + EXPECT_EQ(kHaierAcYrw02SwingTop, haier.getSwing()); + EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + + haier.setSwing(kHaierAcYrw02SwingDown); + EXPECT_EQ(kHaierAcYrw02SwingDown, haier.getSwing()); + EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + + // Test unexpected values. + haier.setButton(kHaierAcYrw02ButtonTempUp); + haier.setSwing(0xFF); + EXPECT_EQ(kHaierAcYrw02SwingDown, haier.getSwing()); + EXPECT_EQ(kHaierAcYrw02ButtonTempUp, haier.getButton()); + + // Test the mode-dependant positions. + haier.setMode(kHaierAcYrw02Auto); + haier.setSwing(kHaierAcYrw02SwingMiddle); + EXPECT_EQ(kHaierAcYrw02SwingMiddle, haier.getSwing()); + EXPECT_EQ(kHaierAcYrw02ButtonSwing, haier.getButton()); + haier.setMode(kHaierAcYrw02Heat); + haier.setSwing(kHaierAcYrw02SwingMiddle); + EXPECT_EQ(kHaierAcYrw02SwingBottom, haier.getSwing()); + haier.setSwing(kHaierAcYrw02SwingAuto); + EXPECT_EQ(kHaierAcYrw02SwingAuto, haier.getSwing()); + haier.setSwing(kHaierAcYrw02SwingBottom); + EXPECT_EQ(kHaierAcYrw02SwingBottom, haier.getSwing()); + haier.setMode(kHaierAcYrw02Cool); + haier.setSwing(kHaierAcYrw02SwingBottom); + EXPECT_EQ(kHaierAcYrw02SwingMiddle, haier.getSwing()); +} + +TEST(TestHaierACYRW02Class, MessageConstuction) { + IRHaierACYRW02 haier(0); + + EXPECT_EQ( + "Power: On, Button: 5 (Power), Mode: 0 (Auto), Temp: 25C," + " Fan: 10 (Auto), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," + " Health: On", + haier.toString()); + haier.setMode(kHaierAcYrw02Cool); + haier.setTemp(21); + haier.setFan(kHaierAcYrw02FanHigh); + EXPECT_EQ( + "Power: On, Button: 4 (Fan), Mode: 2 (Cool), Temp: 21C," + " Fan: 2 (High), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," + " Health: On", + haier.toString()); + + haier.setSwing(kHaierAcYrw02SwingMiddle); + haier.setHealth(false); + haier.setSleep(true); + haier.setTurbo(kHaierAcYrw02TurboHigh); + EXPECT_EQ( + "Power: On, Button: 8 (Turbo), Mode: 2 (Cool), Temp: 21C," + " Fan: 2 (High), Turbo: 1 (High), Swing: 2 (Middle)," + " Sleep: On, Health: Off", + haier.toString()); +} + +// Decode "real" state messages. +TEST(TestHaierACYRW02Class, RealStates) { + uint8_t expectedState1[kHaierACYRW02StateLength] = { + 0xA6, 0xE1, 0x00, 0x00, 0x40, 0x20, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6E}; + + IRHaierACYRW02 haier(0); + haier.setRaw(expectedState1); + EXPECT_EQ( + "Power: On, Button: 7 (Health), Mode: 8 (Heat), Temp: 30C," + " Fan: 2 (High), Turbo: 0 (Off), Swing: 1 (Top), Sleep: Off," + " Health: Off", + haier.toString()); + + uint8_t expectedState2[kHaierACYRW02StateLength] = { + 0xA6, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x05, 0x75}; + haier.setRaw(expectedState2); + EXPECT_EQ( + "Power: Off, Button: 5 (Power), Mode: 8 (Heat), Temp: 30C," + " Fan: 2 (High), Turbo: 0 (Off), Swing: 0 (Off), Sleep: Off," + " Health: Off", + haier.toString()); + + uint8_t expectedState3[kHaierACYRW02StateLength] = { + 0xA6, 0x02, 0x00, 0x02, 0x40, 0x20, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2B}; + haier.setRaw(expectedState3); + EXPECT_EQ( + "Power: On, Button: 1 (Temp Down), Mode: 2 (Cool), Temp: 16C," + " Fan: 2 (High), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off," + " Health: On", + haier.toString()); + + // cool 25, health, fan auto, swing auto, sleep on + uint8_t expectedState4[kHaierACYRW02StateLength] = { + 0xA6, 0x9C, 0x00, 0x02, 0x40, 0xA8, 0x00, + 0x20, 0x80, 0x00, 0x00, 0x00, 0x0B, 0xD7}; + haier.setRaw(expectedState4); + EXPECT_EQ( + "Power: On, Button: 11 (Sleep), Mode: 2 (Cool), Temp: 25C," + " Fan: 10 (Auto), Turbo: 0 (Off), Swing: 12 (Auto), Sleep: On," + " Health: On", + haier.toString()); + + // cool 25, health, fan 3, swing auto, sleep on + uint8_t expectedState5[kHaierACYRW02StateLength] = { + 0xA6, 0x9C, 0x00, 0x02, 0x40, 0x27, 0x36, + 0x20, 0x80, 0x00, 0x00, 0x00, 0x04, 0x85}; + haier.setRaw(expectedState5); + EXPECT_EQ( + "Power: On, Button: 4 (Fan), Mode: 2 (Cool), Temp: 25C," + " Fan: 2 (High), Turbo: 0 (Off), Swing: 12 (Auto), Sleep: On," + " Health: On", + haier.toString()); +} + +// Tests for decodeHaierAC(). + +// Decode normal "synthetic" messages. +TEST(TestDecodeHaierAC, NormalDecodeWithStrict) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t expectedState[kHaierACStateLength] = {0xA5, 0x01, 0x20, 0x01, 0x00, + 0xC0, 0x20, 0x00, 0xA7}; + + // With the specific decoder. + irsend.reset(); + irsend.sendHaierAC(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeHaierAC(&irsend.capture, kHaierACBits, true)); + EXPECT_EQ(HAIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + // With the all the decoders. + irsend.reset(); + irsend.sendHaierAC(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HAIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decode a "real" example message. +TEST(TestDecodeHaierAC, RealExample1) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Data from Issue #404 captured by kuzin2006 + uint16_t rawData[149] = { + 3030, 3044, 3030, 4304, 576, 1694, 550, 582, 552, 1704, 552, 714, 550, + 582, 550, 1706, 552, 582, 550, 1836, 552, 582, 578, 568, 550, 582, + 550, 714, 550, 582, 550, 582, 552, 582, 550, 1836, 552, 582, 552, + 580, 580, 1692, 550, 712, 552, 582, 550, 582, 552, 580, 550, 714, + 552, 582, 550, 582, 552, 582, 578, 698, 552, 580, 552, 582, 552, + 582, 552, 1836, 552, 580, 552, 582, 552, 582, 550, 714, 578, 568, + 550, 582, 550, 582, 552, 714, 550, 1706, 550, 1706, 550, 582, 550, + 714, 552, 582, 580, 566, 552, 582, 550, 714, 552, 580, 552, 580, + 552, 1706, 550, 714, 550, 582, 552, 582, 578, 568, 552, 712, 552, + 582, 550, 582, 550, 582, 550, 712, 552, 582, 550, 582, 552, 582, + 578, 722, 552, 1704, 550, 582, 550, 1706, 550, 736, 550, 582, 550, + 1706, 550, 1704, 552, 1704, 578}; + uint8_t expectedState[kHaierACStateLength] = {0xA5, 0x01, 0x20, 0x01, 0x00, + 0xC0, 0x20, 0x00, 0xA7}; + + irsend.sendRaw(rawData, 149, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(HAIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRHaierAC haier(0); + haier.setRaw(irsend.capture.state); + EXPECT_EQ( + "Command: 1 (On), Mode: 0 (AUTO), Temp: 16C, Fan: 0 (AUTO), " + "Swing: 0 (Off), Sleep: Off, Health: Off, " + "Current Time: 00:01, On Timer: Off, Off Timer: Off", + haier.toString()); +} + +// Decode a "real" example message. +TEST(TestDecodeHaierAC, RealExample2) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Data from Issue #404 captured by kuzin2006 + uint16_t rawData[149] = { + 3028, 3046, 3028, 4304, 576, 1694, 552, 582, 550, 1704, 552, 714, + 550, 582, 552, 1704, 550, 582, 550, 1836, 552, 582, 578, 1690, + 552, 1704, 552, 712, 550, 582, 550, 1706, 550, 1706, 552, 712, + 550, 582, 552, 582, 578, 1690, 552, 714, 552, 580, 552, 582, + 552, 582, 550, 712, 552, 582, 550, 582, 550, 582, 578, 698, + 552, 582, 550, 584, 550, 582, 552, 1836, 550, 582, 550, 582, + 550, 582, 550, 712, 578, 568, 550, 582, 550, 582, 550, 714, + 552, 1706, 550, 1706, 552, 580, 550, 714, 550, 582, 580, 568, + 550, 582, 550, 714, 550, 582, 550, 582, 550, 1706, 552, 712, + 550, 582, 550, 582, 580, 568, 552, 712, 550, 584, 550, 582, + 550, 584, 550, 712, 550, 582, 550, 582, 550, 582, 578, 722, + 550, 582, 552, 580, 552, 582, 550, 738, 550, 1706, 550, 1704, + 552, 582, 550, 582, 578}; + uint8_t expectedState[kHaierACStateLength] = {0xA5, 0x66, 0x20, 0x01, 0x00, + 0xC0, 0x20, 0x00, 0x0C}; + + irsend.sendRaw(rawData, 149, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(HAIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRHaierAC haier(0); + haier.setRaw(irsend.capture.state); + EXPECT_EQ( + "Command: 6 (Temp Up), Mode: 0 (AUTO), Temp: 22C, Fan: 0 (AUTO), " + "Swing: 0 (Off), Sleep: Off, Health: Off, " + "Current Time: 00:01, On Timer: Off, Off Timer: Off", + haier.toString()); +} + +// Decode a "real" example message. +TEST(TestDecodeHaierAC, RealExample3) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Data from Issue #404 captured by kuzin2006 + uint16_t rawData[149] = { + 3030, 3044, 3030, 4302, 578, 1692, 550, 582, 550, 1706, 550, 714, + 550, 582, 552, 1706, 550, 582, 550, 1836, 552, 1706, 578, 1690, + 552, 1704, 552, 714, 550, 1706, 552, 1706, 550, 582, 550, 714, + 552, 582, 550, 582, 578, 1690, 550, 714, 552, 582, 552, 582, + 550, 582, 550, 714, 550, 584, 550, 582, 550, 582, 578, 700, + 552, 1706, 550, 582, 550, 582, 552, 1836, 550, 582, 550, 582, + 552, 1706, 550, 714, 578, 568, 552, 582, 552, 582, 550, 714, + 550, 1706, 550, 1706, 550, 582, 552, 712, 552, 582, 580, 568, + 550, 582, 550, 714, 550, 582, 550, 582, 550, 1706, 550, 714, + 550, 582, 550, 582, 578, 568, 552, 712, 552, 582, 550, 582, + 550, 582, 550, 712, 550, 584, 550, 582, 552, 582, 578, 722, + 552, 1704, 550, 582, 550, 1706, 550, 1862, 550, 1706, 550, 582, + 550, 1704, 552, 582, 578}; + uint8_t expectedState[kHaierACStateLength] = {0xA5, 0xEC, 0x20, 0x09, 0x20, + 0xC0, 0x20, 0x00, 0xBA}; + + irsend.sendRaw(rawData, 149, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(HAIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRHaierAC haier(0); + haier.setRaw(irsend.capture.state); + EXPECT_EQ( + "Command: 12 (Health), Mode: 0 (AUTO), Temp: 30C, Fan: 0 (AUTO), " + "Swing: 0 (Off), Sleep: Off, Health: On, " + "Current Time: 00:09, On Timer: Off, Off Timer: Off", + haier.toString()); +} + +// Decode normal "synthetic" messages. +TEST(TestDecodeHaierAC_YRW02, NormalDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t expectedState[kHaierACYRW02StateLength] = { + 0xA6, 0x12, 0x00, 0x02, 0x40, 0x20, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x3F}; + + irsend.reset(); + irsend.sendHaierACYRW02(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HAIER_AC_YRW02, irsend.capture.decode_type); + EXPECT_EQ(kHaierACYRW02Bits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decode a "real" example message. +TEST(TestDecodeHaierAC_YRW02, RealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Data from Issue #485 captured by non7top + uint16_t rawData[229] = { + 2998, 3086, 2998, 4460, 568, 1640, 596, 492, 514, 1690, 590, 496, + 566, 532, 592, 1596, 570, 1618, 518, 584, 590, 538, 524, 536, + 568, 532, 590, 1596, 516, 612, 568, 538, 522, 1638, 586, 500, + 512, 614, 568, 538, 520, 538, 586, 538, 566, 540, 520, 538, + 586, 538, 522, 538, 588, 538, 568, 538, 520, 538, 586, 538, + 566, 538, 520, 540, 588, 1596, 590, 536, 568, 538, 520, 1592, + 640, 538, 520, 540, 588, 538, 568, 538, 516, 562, 566, 538, + 518, 542, 586, 540, 566, 1596, 590, 538, 566, 538, 516, 544, + 586, 538, 516, 542, 588, 540, 564, 540, 468, 590, 588, 538, + 566, 540, 466, 590, 588, 538, 514, 544, 588, 538, 566, 538, + 468, 1692, 606, 526, 466, 592, 588, 538, 568, 490, 588, 538, + 566, 540, 466, 592, 588, 538, 566, 538, 466, 592, 588, 538, + 568, 492, 586, 540, 566, 540, 468, 590, 588, 538, 568, 516, + 488, 590, 588, 538, 568, 492, 588, 538, 566, 518, 488, 590, + 588, 540, 564, 518, 490, 590, 588, 538, 562, 496, 588, 538, + 566, 518, 488, 590, 588, 538, 562, 522, 488, 588, 590, 538, + 560, 498, 588, 540, 564, 522, 486, 590, 590, 538, 560, 524, + 488, 588, 588, 1598, 514, 608, 564, 1600, 548, 536, 586, 538, + 568, 1594, 590, 1618, 578, 1606, 606, 1582, 590, 1596, 590, 1616, + 580}; + uint8_t expectedState[kHaierACYRW02StateLength] = { + 0xA6, 0x12, 0x00, 0x02, 0x40, 0x20, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x3F}; + + irsend.sendRaw(rawData, 229, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(HAIER_AC_YRW02, irsend.capture.decode_type); + EXPECT_EQ(kHaierACYRW02Bits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRHaierACYRW02 haier(0); + haier.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Button: 5 (Power), Mode: 2 (Cool), Temp: 17C," + " Fan: 2 (High), Turbo: 0 (Off), Swing: 2 (Middle), Sleep: Off," + " Health: On", + haier.toString()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Hitachi_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Hitachi_test.cpp new file mode 100644 index 000000000..de0a4a2a1 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Hitachi_test.cpp @@ -0,0 +1,765 @@ +// Copyright 2018 David Conran + +#include "ir_Hitachi.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendHitachiAC(). + +// Test sending typical data only. +TEST(TestSendHitachiAC, SendData) { + IRsendTest irsend(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC}; + irsend.reset(); + irsend.sendHitachiAC(hitachi_code); + EXPECT_EQ( + "m3300s1700" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s1250m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500m400s1250" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s1250m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s1250m400s500m400s1250m400s1250m400s500m400s500" + "m400s100000", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendHitachiAC, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC}; + irsend.reset(); + + irsend.sendHitachiAC(hitachi_code, kHitachiAcStateLength, 1); + EXPECT_EQ( + "m3300s1700" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s1250m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500m400s1250" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s1250m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s1250m400s500m400s1250m400s1250m400s500m400s500" + "m400s100000" + "m3300s1700" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s1250m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500m400s1250" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s1250m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s1250m400s500m400s1250m400s1250m400s500m400s500" + "m400s100000", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendHitachiAC, SendUnexpectedSizes) { + IRsendTest irsend(0); + irsend.begin(); + + uint8_t hitachi_short_code[kHitachiAcStateLength - 1] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, + 0x80, 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00}; + uint8_t hitachi_long_code[kHitachiAcStateLength + 1] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC, 0xFF}; + irsend.reset(); + irsend.sendHitachiAC(hitachi_short_code, kHitachiAcStateLength - 1); + ASSERT_EQ("", irsend.outputStr()); + + irsend.reset(); + irsend.sendHitachiAC(hitachi_long_code, kHitachiAcStateLength + 1); + ASSERT_EQ( + "m3300s1700" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s1250m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500m400s1250" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s1250m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s1250m400s500m400s1250m400s1250m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s100000", + irsend.outputStr()); +} + +// Tests for IRHitachiAc class. +TEST(TestIRHitachiAcClass, SetAndGetPower) { + IRHitachiAc ac(0); + ac.on(); + EXPECT_TRUE(ac.getPower()); + ac.off(); + EXPECT_FALSE(ac.getPower()); + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestIRHitachiAcClass, SetAndGetSwing) { + IRHitachiAc ac(0); + ac.setSwingVertical(true); + ac.setSwingHorizontal(true); + EXPECT_TRUE(ac.getSwingVertical()); + EXPECT_TRUE(ac.getSwingHorizontal()); + ac.setSwingVertical(false); + EXPECT_FALSE(ac.getSwingVertical()); + EXPECT_TRUE(ac.getSwingHorizontal()); + ac.setSwingVertical(true); + EXPECT_TRUE(ac.getSwingVertical()); + EXPECT_TRUE(ac.getSwingHorizontal()); + ac.setSwingHorizontal(false); + EXPECT_TRUE(ac.getSwingVertical()); + EXPECT_FALSE(ac.getSwingHorizontal()); + ac.setSwingHorizontal(true); + EXPECT_TRUE(ac.getSwingHorizontal()); +} + +TEST(TestIRHitachiAcClass, SetAndGetTemp) { + IRHitachiAc ac(0); + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + ac.setTemp(kHitachiAcMinTemp); + EXPECT_EQ(kHitachiAcMinTemp, ac.getTemp()); + ac.setTemp(kHitachiAcMinTemp - 1); + EXPECT_EQ(kHitachiAcMinTemp, ac.getTemp()); + ac.setTemp(kHitachiAcMaxTemp); + EXPECT_EQ(kHitachiAcMaxTemp, ac.getTemp()); + ac.setTemp(kHitachiAcMaxTemp + 1); + EXPECT_EQ(kHitachiAcMaxTemp, ac.getTemp()); + ac.setTemp(64); + EXPECT_EQ(64, ac.getTemp()); +} + +TEST(TestIRHitachiAcClass, SetAndGetMode) { + IRHitachiAc ac(0); + ac.setMode(kHitachiAcCool); + ac.setFan(kHitachiAcFanAuto); + EXPECT_EQ(kHitachiAcCool, ac.getMode()); + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + EXPECT_EQ(kHitachiAcFanAuto, ac.getFan()); + ac.setMode(kHitachiAcFan); + EXPECT_EQ(kHitachiAcFan, ac.getMode()); + EXPECT_EQ(64, ac.getTemp()); + EXPECT_NE(kHitachiAcFanAuto, ac.getFan()); + ac.setMode(kHitachiAcHeat); + EXPECT_EQ(25, ac.getTemp()); + EXPECT_EQ(kHitachiAcHeat, ac.getMode()); + ac.setMode(kHitachiAcAuto); + ac.setFan(kHitachiAcFanAuto); + EXPECT_EQ(kHitachiAcAuto, ac.getMode()); + ac.setMode(kHitachiAcDry); + EXPECT_EQ(kHitachiAcDry, ac.getMode()); + EXPECT_NE(kHitachiAcFanAuto, ac.getFan()); +} + +TEST(TestIRHitachiAcClass, SetAndGetFan) { + IRHitachiAc ac(0); + ac.setMode(kHitachiAcCool); // All fan options are available in this mode. + ac.setFan(kHitachiAcFanAuto); + EXPECT_EQ(kHitachiAcFanAuto, ac.getFan()); + ac.setFan(kHitachiAcFanLow); + EXPECT_EQ(kHitachiAcFanLow, ac.getFan()); + ac.setFan(kHitachiAcFanHigh); + EXPECT_EQ(kHitachiAcFanHigh, ac.getFan()); + ac.setFan(kHitachiAcFanHigh + 1); + EXPECT_EQ(kHitachiAcFanHigh, ac.getFan()); + ac.setFan(0); + EXPECT_EQ(kHitachiAcFanAuto, ac.getFan()); + + ac.setMode(kHitachiAcFan); // No auto-fan in Fan mode. + EXPECT_EQ(kHitachiAcFanLow, ac.getFan()); + ac.setFan(kHitachiAcFanAuto); + EXPECT_EQ(kHitachiAcFanLow, ac.getFan()); + ac.setFan(kHitachiAcFanHigh); + EXPECT_EQ(kHitachiAcFanHigh, ac.getFan()); + + // Only Low and one higher fan settin in Dry mode. + ac.setMode(kHitachiAcDry); + EXPECT_EQ(kHitachiAcFanLow + 1, ac.getFan()); + ac.setFan(kHitachiAcFanHigh); + EXPECT_EQ(kHitachiAcFanLow + 1, ac.getFan()); + ac.setFan(kHitachiAcFanLow); + EXPECT_EQ(kHitachiAcFanLow, ac.getFan()); + ac.setFan(kHitachiAcFanAuto); + EXPECT_EQ(kHitachiAcFanLow, ac.getFan()); +} + +TEST(TestIRHitachiAcClass, HumanReadable) { + IRHitachiAc ac(0); + + ac.setMode(kHitachiAcHeat); + ac.setTemp(kHitachiAcMaxTemp); + ac.on(); + ac.setFan(kHitachiAcFanHigh); + ac.setSwingVertical(true); + EXPECT_EQ( + "Power: On, Mode: 3 (HEAT), Temp: 32C, Fan: 5 (HIGH), " + "Swing (Vertical): On, Swing (Horizontal): Off", + ac.toString()); + ac.setMode(kHitachiAcCool); + ac.setTemp(kHitachiAcMinTemp); + ac.setFan(kHitachiAcFanLow); + ac.setSwingVertical(false); + ac.setSwingHorizontal(true); + EXPECT_EQ( + "Power: On, Mode: 4 (COOL), Temp: 16C, Fan: 2 (LOW), " + "Swing (Vertical): Off, Swing (Horizontal): On", + ac.toString()); +} + +TEST(TestIRHitachiAcClass, ChecksumCalculation) { + IRHitachiAc ac(0); + + const uint8_t originalstate[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC}; + uint8_t examplestate[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC}; + + EXPECT_TRUE(IRHitachiAc::validChecksum(examplestate)); + EXPECT_EQ(0xAC, IRHitachiAc::calcChecksum(examplestate)); + + examplestate[kHitachiAcStateLength - 1] = + 0x12; // Make the existing checksum invalid + EXPECT_FALSE(IRHitachiAc::validChecksum(examplestate)); + EXPECT_EQ(0xAC, IRHitachiAc::calcChecksum(examplestate)); + ac.setRaw(examplestate); + // Extracting the state from the object should have a correct checksum. + EXPECT_TRUE(IRHitachiAc::validChecksum(ac.getRaw())); + EXPECT_STATE_EQ(originalstate, ac.getRaw(), kHitachiAcBits); + + examplestate[8] = 0x12; // Force a different checksum calc. + EXPECT_FALSE(IRHitachiAc::validChecksum(examplestate)); + EXPECT_EQ(0xFF, IRHitachiAc::calcChecksum(examplestate)); +} + +// Tests for decodeHitachiAC(). + +// Decode a synthetic HitachiAC message. +TEST(TestDecodeHitachiAC, NormalSynthetic) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC}; + + irsend.reset(); + irsend.sendHitachiAC(hitachi_code); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HITACHI_AC, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAcBits); +} + +// Decode a 'real' HitachiAC message. +TEST(TestDecodeHitachiAC, NormalRealExample1) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x80, + 0x20, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xAC}; + + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/417 + // 'On' '16c' 'auto fan' 'cooling mode' + uint16_t rawData[451] = { + 3318, 1720, 400, 1276, 400, 432, 398, 434, 398, 434, 400, 432, + 398, 432, 398, 432, 398, 434, 398, 432, 398, 434, 400, 432, + 398, 434, 398, 1278, 398, 434, 398, 434, 396, 434, 398, 434, + 398, 432, 398, 434, 398, 432, 398, 1276, 426, 1252, 424, 408, + 424, 406, 424, 408, 426, 406, 398, 432, 398, 434, 398, 432, + 400, 432, 398, 1276, 426, 408, 424, 1252, 426, 1252, 424, 1250, + 426, 1252, 428, 1250, 426, 1252, 424, 406, 426, 1248, 428, 1252, + 426, 406, 426, 406, 424, 408, 400, 432, 400, 430, 400, 432, + 400, 430, 400, 432, 400, 1276, 400, 1276, 402, 1276, 400, 1276, + 400, 1276, 400, 1278, 400, 1276, 402, 1276, 402, 428, 402, 430, + 400, 430, 402, 1276, 400, 430, 402, 430, 400, 432, 402, 428, + 402, 1278, 400, 430, 402, 430, 402, 1276, 402, 428, 402, 430, + 402, 430, 400, 1276, 402, 430, 402, 430, 402, 430, 402, 430, + 402, 428, 402, 430, 404, 430, 402, 428, 402, 430, 402, 1276, + 402, 430, 402, 428, 402, 430, 400, 428, 402, 430, 402, 430, + 402, 430, 402, 430, 402, 428, 402, 430, 402, 1274, 402, 428, + 402, 430, 402, 430, 402, 430, 402, 430, 402, 428, 402, 428, + 402, 428, 404, 428, 404, 428, 402, 1276, 400, 430, 402, 430, + 400, 432, 400, 456, 374, 432, 400, 456, 404, 428, 404, 426, + 404, 428, 402, 428, 402, 430, 402, 430, 400, 432, 398, 434, + 376, 454, 378, 454, 380, 452, 378, 452, 404, 428, 406, 424, + 432, 398, 406, 426, 430, 402, 404, 428, 428, 402, 400, 430, + 400, 432, 398, 434, 398, 432, 398, 434, 372, 460, 374, 434, + 398, 432, 398, 434, 396, 434, 376, 456, 376, 456, 376, 456, + 376, 1300, 378, 454, 378, 452, 378, 454, 378, 454, 378, 454, + 378, 452, 378, 454, 400, 432, 402, 430, 402, 430, 402, 430, + 402, 428, 402, 430, 402, 430, 400, 430, 402, 430, 400, 432, + 400, 430, 400, 432, 400, 430, 402, 430, 400, 432, 398, 432, + 400, 430, 400, 432, 398, 432, 398, 434, 398, 432, 398, 432, + 400, 434, 398, 432, 398, 432, 398, 434, 398, 434, 396, 434, + 398, 434, 398, 432, 398, 434, 398, 432, 398, 456, 376, 454, + 376, 436, 396, 454, 376, 454, 378, 454, 376, 454, 376, 456, + 374, 458, 374, 1302, 374, 456, 374, 458, 374, 458, 376, 456, + 374, 456, 374, 456, 374, 456, 376, 456, 376, 456, 374, 458, + 374, 458, 374, 458, 372, 458, 372, 460, 374, 458, 372, 460, + 372, 460, 372, 460, 370, 462, 372, 460, 372, 460, 370, 462, + 370, 462, 356, 1320, 368, 464, 346, 1332, 356, 476, 368, 1310, + 366, 1312, 366, 464, 366, 466, 366}; + + irsend.reset(); + irsend.sendRaw(rawData, 451, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeHitachiAC(&irsend.capture)); + EXPECT_EQ(HITACHI_AC, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAcBits); + IRHitachiAc ac(0); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 4 (COOL), Temp: 16C, Fan: 1 (AUTO), " + "Swing (Vertical): Off, Swing (Horizontal): Off", + ac.toString()); +} + +// Decode another 'real' HitachiAC message. +TEST(TestDecodeHitachiAC, NormalRealExample2) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAcStateLength] = { + 0x80, 0x08, 0x0C, 0x02, 0xFD, 0x80, 0x7F, 0x88, 0x48, 0x10, + 0xC0, 0x02, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xD0}; + + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/417 + // 'On' '32c' 'auto fan' 'heating mode' + uint16_t rawData[451] = { + 3322, 1718, 400, 1278, 398, 432, 402, 430, 400, 430, 402, 430, + 402, 430, 400, 432, 400, 432, 402, 430, 400, 430, 402, 430, + 400, 430, 402, 1276, 402, 430, 400, 430, 402, 430, 402, 430, + 402, 428, 402, 430, 400, 430, 402, 1278, 400, 1274, 402, 430, + 400, 432, 400, 430, 402, 430, 402, 430, 400, 430, 400, 432, + 402, 428, 402, 1276, 404, 428, 402, 1276, 402, 1274, 402, 1274, + 404, 1272, 402, 1274, 402, 1274, 404, 430, 402, 1274, 402, 1274, + 402, 430, 402, 430, 402, 430, 400, 430, 402, 430, 404, 428, + 402, 430, 400, 430, 402, 1274, 402, 1276, 402, 1276, 402, 1276, + 400, 1276, 402, 1272, 404, 1274, 402, 1272, 404, 430, 402, 430, + 402, 430, 402, 1274, 404, 428, 402, 428, 404, 430, 402, 430, + 402, 1274, 402, 430, 402, 430, 402, 1274, 402, 430, 402, 430, + 402, 428, 404, 428, 402, 430, 402, 430, 402, 1272, 406, 430, + 402, 428, 402, 430, 402, 430, 400, 1276, 400, 1276, 402, 430, + 402, 430, 402, 430, 402, 430, 402, 428, 402, 430, 402, 430, + 402, 430, 402, 430, 402, 430, 402, 430, 400, 430, 402, 1272, + 404, 430, 400, 430, 402, 430, 402, 428, 404, 430, 400, 430, + 402, 430, 402, 430, 402, 428, 402, 1276, 402, 428, 402, 1276, + 402, 430, 402, 428, 402, 430, 402, 430, 402, 430, 402, 428, + 402, 430, 402, 430, 402, 430, 402, 430, 402, 428, 402, 428, + 404, 430, 402, 428, 402, 430, 402, 428, 402, 430, 402, 432, + 402, 428, 402, 430, 402, 430, 402, 430, 400, 430, 400, 430, + 402, 430, 402, 430, 402, 426, 404, 430, 402, 430, 400, 428, + 404, 428, 404, 432, 398, 432, 400, 456, 376, 456, 376, 456, + 376, 1276, 402, 454, 378, 456, 376, 454, 378, 454, 402, 430, + 376, 454, 376, 456, 400, 430, 378, 454, 400, 432, 402, 430, + 376, 454, 376, 456, 376, 454, 400, 432, 374, 458, 400, 430, + 398, 434, 374, 456, 374, 456, 374, 458, 374, 458, 374, 456, + 352, 482, 372, 460, 374, 458, 364, 468, 352, 480, 372, 460, + 352, 480, 352, 480, 352, 480, 352, 480, 352, 454, 400, 432, + 376, 480, 374, 456, 374, 456, 378, 430, 404, 452, 376, 430, + 404, 428, 406, 426, 406, 426, 404, 426, 406, 428, 406, 426, + 430, 400, 430, 1244, 408, 424, 434, 398, 432, 400, 406, 424, + 432, 400, 406, 426, 430, 400, 432, 400, 432, 400, 430, 402, + 428, 402, 404, 428, 404, 426, 406, 426, 406, 426, 404, 428, + 428, 402, 404, 428, 404, 428, 402, 428, 404, 428, 402, 428, + 404, 428, 404, 1274, 402, 1274, 404, 428, 400, 1276, 402, 430, + 402, 430, 402, 430, 402, 430, 400}; + + irsend.reset(); + irsend.sendRaw(rawData, 451, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HITACHI_AC, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAcBits); + IRHitachiAc ac(0); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 3 (HEAT), Temp: 32C, Fan: 5 (HIGH), " + "Swing (Vertical): Off, Swing (Horizontal): Off", + ac.toString()); +} + +// Tests for sendHitachiAC1(). + +// Test sending typical data only. +TEST(TestSendHitachiAC1, SendData) { + IRsendTest irsend(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAc1StateLength] = {0xB2, 0xAE, 0x4D, 0x51, 0xF0, + 0x61, 0x84, 0x00, 0x00, 0x00, + 0x00, 0x30, 0xB8}; + irsend.reset(); + irsend.sendHitachiAC1(hitachi_code); + EXPECT_EQ( + "m3400s3400" + "m400s1250m400s500m400s1250m400s1250m400s500m400s500m400s1250m400s500" + "m400s1250m400s500m400s1250m400s500m400s1250m400s1250m400s1250m400s500" + "m400s500m400s1250m400s500m400s500m400s1250m400s1250m400s500m400s1250" + "m400s500m400s1250m400s500m400s1250m400s500m400s500m400s500m400s1250" + "m400s1250m400s1250m400s1250m400s1250m400s500m400s500m400s500m400s500" + "m400s500m400s1250m400s1250m400s500m400s500m400s500m400s500m400s1250" + "m400s1250m400s500m400s500m400s500m400s500m400s1250m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s1250m400s500m400s500m400s500m400s500" + "m400s1250m400s500m400s1250m400s1250m400s1250m400s500m400s500m400s500" + "m400s100000", + irsend.outputStr()); +} + +// Decode a 'real' HitachiAC1 message. +TEST(TestDecodeHitachiAC1, NormalRealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAc1StateLength] = {0xB2, 0xAE, 0x4D, 0x51, 0xF0, + 0x61, 0x84, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x98}; + + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/453 + uint16_t rawData[211] = { + 3400, 3350, 450, 1250, 450, 400, 400, 1300, 400, 1300, 400, 400, + 450, 400, 400, 1300, 400, 400, 400, 1300, 400, 400, 450, 1250, + 400, 450, 400, 1300, 400, 1250, 450, 1250, 450, 400, 400, 450, + 400, 1250, 450, 400, 400, 400, 400, 1300, 400, 1300, 400, 400, + 450, 1250, 450, 400, 400, 1300, 400, 400, 450, 1250, 400, 400, + 450, 400, 400, 400, 450, 1250, 400, 1300, 450, 1250, 450, 1250, + 400, 1300, 400, 400, 450, 400, 400, 450, 350, 450, 400, 400, + 400, 1300, 400, 1300, 400, 400, 450, 400, 400, 400, 450, 400, + 400, 1300, 400, 1250, 450, 400, 400, 400, 450, 400, 400, 400, + 450, 1250, 450, 400, 400, 400, 450, 400, 400, 400, 450, 400, + 400, 400, 450, 400, 400, 400, 450, 400, 400, 400, 400, 450, + 400, 400, 400, 400, 450, 400, 400, 400, 450, 400, 400, 450, + 400, 400, 400, 400, 450, 400, 400, 400, 450, 400, 400, 450, + 400, 400, 400, 400, 400, 450, 400, 400, 400, 400, 450, 400, + 400, 400, 450, 400, 400, 400, 450, 400, 400, 400, 450, 400, + 400, 400, 450, 400, 400, 1300, 400, 400, 450, 400, 400, 400, + 400, 400, 450, 1250, 450, 400, 400, 400, 450, 1250, 450, 1250, + 450, 400, 400, 400, 450, 400, 400}; // UNKNOWN 828A89E1 + + irsend.reset(); + irsend.sendRaw(rawData, 211, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HITACHI_AC1, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAc1Bits, irsend.capture.bits); + EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAc1Bits); +} + +// Tests for sendHitachiAC2(). + +// Test sending typical data only. +TEST(TestSendHitachiAC2, SendData) { + IRsendTest irsend(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAc2StateLength] = { + 0x80, 0x08, 0x00, 0x02, 0xFD, 0xFF, 0x00, 0x33, 0xCC, 0x49, 0xB6, + 0x22, 0xDD, 0x01, 0xFE, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0xCA, 0x35, 0x8F, 0x70, 0x00, 0xFF, 0x00, 0xFF, + 0x01, 0xFE, 0xC0, 0x3F, 0x80, 0x7F, 0x11, 0xEE, 0x00, 0xFF, 0x00, + 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00}; + irsend.reset(); + irsend.sendHitachiAC2(hitachi_code); + EXPECT_EQ( + "m3300s1700" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s1250m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500m400s1250" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s1250m400s500m400s500m400s1250m400s1250" + "m400s1250m400s1250m400s500m400s500m400s1250m400s1250m400s500m400s500" + "m400s500m400s1250m400s500m400s500m400s1250m400s500m400s500m400s1250" + "m400s1250m400s500m400s1250m400s1250m400s500m400s1250m400s1250m400s500" + "m400s500m400s500m400s1250m400s500m400s500m400s500m400s1250m400s500" + "m400s1250m400s1250m400s500m400s1250m400s1250m400s1250m400s500m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s1250" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s1250m400s500m400s500m400s1250m400s500m400s1250m400s500" + "m400s500m400s500m400s1250m400s1250m400s500m400s1250m400s500m400s1250" + "m400s1250m400s500m400s500m400s500m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s1250m400s1250m400s1250m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s1250" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s500" + "m400s1250m400s1250m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s500m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s500m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s1250m400s500m400s500m400s500m400s1250" + "m400s1250m400s1250m400s1250m400s500m400s1250m400s1250m400s1250m400s500" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250m400s1250" + "m400s500m400s500m400s500m400s500m400s500m400s500m400s500m400s500" + "m400s100000", + irsend.outputStr()); +} + +// Decode a synthetic HitachiAC2 message. + +TEST(TestDecodeHitachiAC2, NormalSyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // ON - 32c cool (fan auto) + uint8_t hitachi_code[kHitachiAc2StateLength] = { + 0x80, 0x08, 0x00, 0x02, 0xFD, 0xFF, 0x00, 0x33, 0xCC, 0x49, 0xB6, + 0x22, 0xDD, 0x01, 0xFE, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0xCA, 0x35, 0x8F, 0x70, 0x00, 0xFF, 0x00, 0xFF, + 0x01, 0xFE, 0xC0, 0x3F, 0x80, 0x7F, 0x11, 0xEE, 0x00, 0xFF, 0x00, + 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00}; + + irsend.reset(); + irsend.sendHitachiAC2(hitachi_code); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HITACHI_AC2, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAc2Bits, irsend.capture.bits); + EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAc2Bits); +} + +// Decode a 'real' HitachiAC2 message. +TEST(TestDecodeHitachiAC2, NormalRealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t hitachi_code[kHitachiAc2StateLength] = { + 0x80, 0x08, 0x00, 0x02, 0xFD, 0xFF, 0x00, 0x33, 0xCC, 0x49, 0xB6, + 0x22, 0xDD, 0x01, 0xFE, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0xCA, 0x35, 0x8F, 0x70, 0x00, 0xFF, 0x00, 0xFF, + 0x01, 0xFE, 0xC0, 0x3F, 0x80, 0x7F, 0x11, 0xEE, 0x00, 0xFF, 0x00, + 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00}; + + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/417 + uint16_t rawData[851] = { + // ON - 32c cool (fan auto) + 3432, 1654, 492, 1180, 488, 360, 486, 360, 486, 360, 486, 362, + 486, 362, 460, 360, 486, 362, 486, 362, 486, 360, 486, 362, + 486, 362, 486, 1184, 488, 362, 486, 360, 486, 362, 486, 362, + 486, 362, 460, 362, 486, 362, 486, 362, 484, 362, 486, 362, + 486, 362, 486, 362, 458, 362, 484, 362, 486, 362, 484, 364, + 484, 362, 486, 1184, 486, 362, 486, 1210, 488, 1210, 488, 1184, + 486, 1210, 488, 1210, 488, 1182, 488, 360, 488, 1208, 488, 1208, + 488, 1182, 488, 1208, 488, 1208, 488, 1208, 462, 1208, 490, 1208, + 488, 1208, 490, 332, 488, 360, 488, 360, 488, 360, 486, 360, + 486, 360, 486, 362, 460, 360, 486, 362, 486, 362, 486, 1210, + 488, 1210, 460, 362, 486, 362, 486, 1210, 488, 1210, 488, 1182, + 488, 1210, 488, 362, 486, 360, 488, 1182, 488, 1210, 488, 362, + 486, 362, 486, 360, 486, 1182, 488, 362, 486, 362, 486, 1210, + 488, 360, 486, 336, 486, 1210, 488, 1210, 488, 360, 486, 1182, + 488, 1210, 488, 360, 488, 1208, 488, 1182, 488, 362, 486, 362, + 486, 360, 486, 1210, 460, 362, 486, 360, 486, 362, 486, 1210, + 486, 362, 486, 1184, 488, 1208, 488, 360, 486, 1210, 488, 1184, + 488, 1208, 488, 362, 486, 1208, 462, 360, 486, 360, 486, 362, + 486, 360, 486, 362, 486, 360, 486, 334, 486, 1210, 488, 1208, + 488, 1210, 488, 1182, 488, 1208, 488, 1210, 488, 1182, 488, 1208, + 488, 360, 488, 360, 486, 360, 486, 334, 486, 362, 486, 362, + 486, 362, 486, 362, 486, 362, 486, 1182, 488, 1210, 486, 1210, + 488, 1210, 460, 1210, 488, 1210, 488, 1210, 488, 1184, 488, 360, + 486, 360, 486, 362, 486, 362, 486, 360, 460, 360, 486, 362, + 486, 362, 484, 1210, 488, 1182, 488, 1210, 488, 1210, 488, 1210, + 488, 1182, 488, 1208, 488, 1208, 488, 360, 460, 360, 486, 360, + 486, 360, 488, 360, 486, 362, 486, 362, 486, 334, 486, 1210, + 488, 1208, 488, 1210, 460, 1210, 488, 1208, 488, 1210, 488, 1182, + 488, 1208, 488, 360, 486, 362, 486, 360, 488, 334, 486, 360, + 486, 362, 486, 362, 486, 362, 486, 1210, 460, 1210, 488, 1210, + 488, 1210, 488, 1182, 488, 1210, 488, 1208, 488, 1182, 488, 360, + 486, 360, 486, 362, 486, 362, 486, 360, 486, 362, 460, 360, + 486, 362, 486, 1210, 486, 1212, 486, 1184, 488, 1210, 488, 1208, + 488, 1182, 488, 1208, 488, 1208, 488, 1208, 462, 1208, 488, 360, + 486, 362, 486, 1208, 488, 334, 486, 1208, 488, 360, 486, 360, + 486, 362, 486, 1182, 488, 1210, 488, 360, 486, 1210, 488, 334, + 486, 1208, 488, 1208, 488, 360, 486, 360, 486, 334, 486, 1210, + 488, 1210, 488, 1210, 460, 1210, 488, 360, 486, 1208, 488, 1182, + 490, 1208, 488, 360, 486, 360, 486, 360, 486, 360, 460, 360, + 486, 362, 486, 362, 486, 362, 486, 362, 486, 362, 486, 362, + 458, 362, 486, 1210, 488, 1210, 488, 1182, 488, 1210, 488, 1208, + 488, 1208, 462, 1208, 488, 1208, 488, 360, 486, 360, 486, 334, + 486, 360, 486, 362, 486, 362, 486, 362, 486, 362, 486, 1184, + 488, 1210, 488, 1210, 488, 1208, 462, 1210, 488, 1208, 488, 1208, + 488, 1182, 488, 360, 486, 360, 486, 360, 486, 362, 486, 360, + 460, 362, 486, 360, 488, 1208, 488, 1210, 488, 1184, 488, 1208, + 488, 1210, 488, 1182, 488, 1208, 488, 1208, 488, 360, 488, 1182, + 488, 1208, 488, 360, 488, 360, 488, 360, 486, 334, 486, 360, + 486, 362, 486, 362, 486, 360, 486, 1210, 488, 1182, 488, 1210, + 488, 1210, 488, 1182, 488, 1210, 488, 1210, 488, 360, 488, 334, + 486, 360, 488, 360, 486, 362, 486, 362, 486, 362, 486, 362, + 460, 1210, 488, 1210, 488, 1210, 488, 1184, 488, 1208, 488, 1208, + 490, 1182, 488, 360, 488, 360, 486, 362, 486, 1208, 488, 360, + 460, 362, 486, 362, 486, 1210, 488, 1210, 488, 1182, 488, 1208, + 488, 360, 488, 1208, 488, 1184, 486, 1210, 488, 360, 488, 360, + 486, 360, 460, 362, 486, 362, 486, 362, 486, 362, 484, 362, + 486, 362, 486, 1184, 488, 1210, 488, 1210, 488, 1182, 488, 1210, + 488, 1208, 488, 1208, 462, 1210, 488, 360, 486, 362, 486, 360, + 486, 362, 486, 334, 486, 362, 486, 360, 486, 362, 486, 1208, + 488, 1184, 488, 1208, 488, 1210, 488, 1182, 488, 1208, 488, 1208, + 488, 1208, 488, 1182, 488, 1208, 488, 1208, 488, 1182, 488, 1208, + 488, 1208, 488, 1182, 488, 1208, 488, 360, 488, 360, 486, 360, + 486, 362, 460, 362, 486, 362, 486, 362, 486, 360, 486, 1208, + 488, 1182, 488, 1208, 488, 1210, 488, 1182, 488, 1208, 490, 1208, + 488, 1208, 462, 360, 488, 360, 486, 360, 488, 360, 486, 360, + 486, 360, 486, 336, 486, 362, 486, 1210, 488, 1208, 488, 1182, + 488, 1208, 488, 1208, 488, 1208, 462, 1208, 490, 1206, 490, 360, + 488, 360, 488, 332, 486, 360, 488, 360, 486, 360, 488, 360, + 486, 360, 486, 1182, 488, 1208, 488, 1206, 492, 1208, 462, 1208, + 488, 1208, 488, 1208, 490, 1182, 490, 360, 486, 360, 486, 360, + 488, 360, 488, 360, 460, 360, 486, 362, 486, 360, 488}; + + irsend.reset(); + irsend.sendRaw(rawData, 851, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(HITACHI_AC2, irsend.capture.decode_type); + ASSERT_EQ(kHitachiAc2Bits, irsend.capture.bits); + EXPECT_STATE_EQ(hitachi_code, irsend.capture.state, kHitachiAc2Bits); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_JVC_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_JVC_test.cpp similarity index 76% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_JVC_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_JVC_test.cpp index 0826b2268..c899fa8c6 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_JVC_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_JVC_test.cpp @@ -17,7 +17,8 @@ TEST(TestSendJVC, SendDataOnly) { "m8400s4200" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" - "m525s60000", irsend.outputStr()); + "m525s21675", + irsend.outputStr()); } // Test sending with different repeats. @@ -26,31 +27,33 @@ TEST(TestSendJVC, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendJVC(0xC2B8, JVC_BITS, 1); // 1 repeat. + irsend.sendJVC(0xC2B8, kJvcBits, 1); // 1 repeat. EXPECT_EQ( "m8400s4200" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" - "m525s60000" + "m525s21675" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" - "m525s60000", irsend.outputStr()); - irsend.sendJVC(0xC2B8, JVC_BITS, 2); // 2 repeats. + "m525s34275", + irsend.outputStr()); + irsend.sendJVC(0xC2B8, kJvcBits, 2); // 2 repeats. EXPECT_EQ( "m8400s4200" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" - "m525s60000" + "m525s21675" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" - "m525s60000" + "m525s34275" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" - "m525s60000", irsend.outputStr()); + "m525s34275", + irsend.outputStr()); } // Test sending an atypical data size. -TEST(TestSendJVC, SendUsualSize) { +TEST(TestSendJVC, SendUnusualSize) { IRsendTest irsend(4); irsend.begin(); @@ -59,7 +62,8 @@ TEST(TestSendJVC, SendUsualSize) { EXPECT_EQ( "m8400s4200" "m525s525m525s525m525s525m525s525m525s525m525s525m525s525m525s525" - "m525s60000", irsend.outputStr()); + "m525s38475", + irsend.outputStr()); irsend.reset(); irsend.sendJVC(0x1234567890ABCDEF, 64); @@ -73,7 +77,8 @@ TEST(TestSendJVC, SendUsualSize) { "m525s1725m525s525m525s1725m525s525m525s1725m525s525m525s1725m525s1725" "m525s1725m525s1725m525s525m525s525m525s1725m525s1725m525s525m525s1725" "m525s1725m525s1725m525s1725m525s525m525s1725m525s1725m525s1725m525s1725" - "m525s60000", irsend.outputStr()); + "m525s10875", + irsend.outputStr()); } // Tests for encodeJVC(). @@ -100,9 +105,9 @@ TEST(TestDecodeJVC, NormalDecodeWithStrict) { irsend.reset(); irsend.sendJVC(0xC2B8); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_EQ(0x43, irsend.capture.address); EXPECT_EQ(0x1D, irsend.capture.command); @@ -112,9 +117,9 @@ TEST(TestDecodeJVC, NormalDecodeWithStrict) { irsend.reset(); irsend.sendJVC(irsend.encodeJVC(0x07, 0x99)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xE099, irsend.capture.value); EXPECT_EQ(0x07, irsend.capture.address); EXPECT_EQ(0x99, irsend.capture.command); @@ -124,9 +129,9 @@ TEST(TestDecodeJVC, NormalDecodeWithStrict) { irsend.reset(); irsend.sendJVC(irsend.encodeJVC(0x1, 0x1)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0x8080, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x1, irsend.capture.command); @@ -141,42 +146,42 @@ TEST(TestDecodeJVC, NormalDecodeWithRepeatAndStrict) { // Normal JVC 16-bit message with 2 repeats. irsend.reset(); - irsend.sendJVC(0xC2B8, JVC_BITS, 2); + irsend.sendJVC(0xC2B8, kJvcBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_EQ(0x43, irsend.capture.address); EXPECT_EQ(0x1D, irsend.capture.command); EXPECT_FALSE(irsend.capture.repeat); - irsend.makeDecodeResult(2 * JVC_BITS + 4); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + irsend.makeDecodeResult(2 * kJvcBits + 4); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_TRUE(irsend.capture.repeat); - irsend.makeDecodeResult(2 * JVC_BITS + 4 + 2 * JVC_BITS + 2); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + irsend.makeDecodeResult(2 * kJvcBits + 4 + 2 * kJvcBits + 2); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_TRUE(irsend.capture.repeat); // Simulate 'just' a JVC repeat command. // JVC VCR Power On from Global Cache, but modified to be a repeat message. - uint16_t gc_test[37] = {38000, 1, 1, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 61, 20, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[37] = {38000, 1, 1, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 61, 20, 20, 20, 61, 20, 20, 20, 61, 20, + 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.reset(); irsend.sendGC(gc_test, 37); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_EQ(0x43, irsend.capture.address); EXPECT_EQ(0x1D, irsend.capture.command); @@ -193,7 +198,7 @@ TEST(TestDecodeJVC, DecodeWithNonStrictValues) { irsend.sendJVC(0x0, 8); // Illegal value JVC 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, 8, false)); EXPECT_EQ(JVC, irsend.capture.decode_type); @@ -206,7 +211,7 @@ TEST(TestDecodeJVC, DecodeWithNonStrictValues) { irsend.sendJVC(0x12345678, 32); // Illegal value JVC 32-bit message. irsend.makeDecodeResult(); // Should not pass with strict when we ask for less bits than we got. - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -225,7 +230,7 @@ TEST(TestDecodeJVC, DecodeWithNonStrictValues) { irsend.makeDecodeResult(); // Shouldn't pass if strict off and the wrong expected bits. - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, false)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kJvcBits, false)); // Re-decode with correct bit size. ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, 36, true)); @@ -264,16 +269,17 @@ TEST(TestDecodeJVC, DecodeGlobalCacheExample) { irsend.reset(); // JVC VCR Power On from Global Cache. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 61, 20, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; - // 38000,1,37,320,161,21,59,21,59,21,19,21,19,21,19,21,19,21,59,21,19,21,59,21,59,21,19,21,59,21,19,21,19,21,19,21,19,21,838,21,59,21,59,21,19,21,19,21,19,21,19,21,59,21,19,21,59,21,19,21,59,21,59,21,59,21,19,21,19,21,19,21,850}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 61, 20, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; + // 38000,1,37,320,161,21,59,21,59,21,19,21,19,21,19,21,19,21,59,21,19,21,59,21,59,21,19,21,59,21,19,21,19,21,19,21,19,21,838,21,59,21,59,21,19,21,19,21,19,21,19,21,59,21,19,21,59,21,19,21,59,21,59,21,59,21,19,21,19,21,19,21,850}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture)); EXPECT_EQ(JVC, irsend.capture.decode_type); - EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_EQ(0x43, irsend.capture.address); EXPECT_EQ(0x1D, irsend.capture.command); @@ -288,12 +294,13 @@ TEST(TestDecodeJVC, FailToDecodeNonJVCExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, false)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kJvcBits, false)); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Kelvinator_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Kelvinator_test.cpp new file mode 100644 index 000000000..001f8bcf2 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Kelvinator_test.cpp @@ -0,0 +1,518 @@ +// Copyright 2017 David Conran + +#include "ir_Kelvinator.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendKelvinator(). + +// Test sending typical data only. +TEST(TestSendKelvinator, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t kelv_code[kKelvinatorStateLength] = { + 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, + 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0}; + irsend.reset(); + irsend.sendKelvinator(kelv_code); + EXPECT_EQ( + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530" + "m680s39950" + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s1530" + "m680s39950", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendKelvinator, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + uint8_t kelv_code[kKelvinatorStateLength] = { + 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, + 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0}; + irsend.reset(); + + irsend.sendKelvinator(kelv_code, kKelvinatorStateLength, 1); + EXPECT_EQ( + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530" + "m680s39950" + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s1530" + "m680s39950" + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530" + "m680s39950" + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s1530" + "m680s39950", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendKelvinator, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t kelv_short_code[15] = {0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, + 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10}; + uint8_t kelv_long_code[17] = {0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, + 0x00, 0xE0, 0x19, 0x0B, 0x80, 0x70, + 0x00, 0x00, 0x10, 0xf0, 0x00}; + irsend.reset(); + irsend.sendKelvinator(kelv_short_code, 15); + ASSERT_EQ("", irsend.outputStr()); + + irsend.reset(); + // Shouldn't be different from the SendDataOnly. We just don't send the + // extra data. + irsend.sendKelvinator(kelv_long_code, 17); + ASSERT_EQ( + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530" + "m680s39950" + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s1530" + "m680s39950", + irsend.outputStr()); +} + +// Tests for IRKelvinatorAC class. + +TEST(TestKelvinatorClass, Power) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.on(); + EXPECT_TRUE(irkelv.getPower()); + + irkelv.off(); + EXPECT_FALSE(irkelv.getPower()); + + irkelv.setPower(true); + EXPECT_TRUE(irkelv.getPower()); + + irkelv.setPower(false); + EXPECT_FALSE(irkelv.getPower()); +} + +TEST(TestKelvinatorClass, Temperature) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setTemp(0); + EXPECT_EQ(kKelvinatorMinTemp, irkelv.getTemp()); + + irkelv.setTemp(255); + EXPECT_EQ(kKelvinatorMaxTemp, irkelv.getTemp()); + + irkelv.setTemp(kKelvinatorMinTemp); + EXPECT_EQ(kKelvinatorMinTemp, irkelv.getTemp()); + + irkelv.setTemp(kKelvinatorMaxTemp); + EXPECT_EQ(kKelvinatorMaxTemp, irkelv.getTemp()); + + irkelv.setTemp(kKelvinatorMinTemp - 1); + EXPECT_EQ(kKelvinatorMinTemp, irkelv.getTemp()); + + irkelv.setTemp(kKelvinatorMaxTemp + 1); + EXPECT_EQ(kKelvinatorMaxTemp, irkelv.getTemp()); + + irkelv.setTemp(17); + EXPECT_EQ(17, irkelv.getTemp()); + + irkelv.setTemp(21); + EXPECT_EQ(21, irkelv.getTemp()); + + irkelv.setTemp(25); + EXPECT_EQ(25, irkelv.getTemp()); + + irkelv.setTemp(29); + EXPECT_EQ(29, irkelv.getTemp()); +} + +TEST(TestKelvinatorClass, OperatingMode) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setTemp(24); + irkelv.setMode(kKelvinatorAuto); + EXPECT_EQ(kKelvinatorAuto, irkelv.getMode()); + EXPECT_EQ(kKelvinatorAutoTemp, irkelv.getTemp()); + + irkelv.setMode(kKelvinatorCool); + EXPECT_EQ(kKelvinatorCool, irkelv.getMode()); + + irkelv.setMode(kKelvinatorHeat); + EXPECT_EQ(kKelvinatorHeat, irkelv.getMode()); + + irkelv.setTemp(24); + irkelv.setMode(kKelvinatorDry); + EXPECT_EQ(kKelvinatorDry, irkelv.getMode()); + EXPECT_EQ(kKelvinatorAutoTemp, irkelv.getTemp()); + + irkelv.setMode(kKelvinatorFan); + EXPECT_EQ(kKelvinatorFan, irkelv.getMode()); + + irkelv.setMode(kKelvinatorHeat + 1); + EXPECT_EQ(kKelvinatorAuto, irkelv.getMode()); + + irkelv.setMode(255); + EXPECT_EQ(kKelvinatorAuto, irkelv.getMode()); +} + +TEST(TestKelvinatorClass, VaneSwing) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setSwingHorizontal(true); + irkelv.setSwingVertical(false); + + irkelv.setSwingHorizontal(true); + EXPECT_TRUE(irkelv.getSwingHorizontal()); + EXPECT_FALSE(irkelv.getSwingVertical()); + + irkelv.setSwingVertical(true); + EXPECT_TRUE(irkelv.getSwingHorizontal()); + EXPECT_TRUE(irkelv.getSwingVertical()); + + irkelv.setSwingHorizontal(false); + EXPECT_FALSE(irkelv.getSwingHorizontal()); + EXPECT_TRUE(irkelv.getSwingVertical()); + + irkelv.setSwingVertical(false); + EXPECT_FALSE(irkelv.getSwingHorizontal()); + EXPECT_FALSE(irkelv.getSwingVertical()); +} + +TEST(TestKelvinatorClass, QuietMode) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setQuiet(true); + EXPECT_TRUE(irkelv.getQuiet()); + + irkelv.setQuiet(false); + EXPECT_FALSE(irkelv.getQuiet()); + + irkelv.setQuiet(true); + EXPECT_TRUE(irkelv.getQuiet()); +} + +TEST(TestKelvinatorClass, IonFilter) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setIonFilter(true); + EXPECT_TRUE(irkelv.getIonFilter()); + + irkelv.setIonFilter(false); + EXPECT_FALSE(irkelv.getIonFilter()); + + irkelv.setIonFilter(true); + EXPECT_TRUE(irkelv.getIonFilter()); +} + +TEST(TestKelvinatorClass, Light) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setLight(true); + EXPECT_TRUE(irkelv.getLight()); + + irkelv.setLight(false); + EXPECT_FALSE(irkelv.getLight()); + + irkelv.setLight(true); + EXPECT_TRUE(irkelv.getLight()); +} + +TEST(TestKelvinatorClass, XFan) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setXFan(true); + EXPECT_TRUE(irkelv.getXFan()); + + irkelv.setXFan(false); + EXPECT_FALSE(irkelv.getXFan()); + + irkelv.setXFan(true); + EXPECT_TRUE(irkelv.getXFan()); +} + +TEST(TestKelvinatorClass, TurboFan) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setTurbo(true); + EXPECT_TRUE(irkelv.getTurbo()); + + irkelv.setTurbo(false); + EXPECT_FALSE(irkelv.getTurbo()); + + irkelv.setFan(2); + irkelv.setTurbo(true); + EXPECT_TRUE(irkelv.getTurbo()); + + // Turbo mode is turned off if the temperature is changed. + irkelv.setFan(3); + EXPECT_FALSE(irkelv.getTurbo()); + + // But only when it is changed, not set to the same value again. + irkelv.setTurbo(true); + irkelv.setFan(3); + EXPECT_TRUE(irkelv.getTurbo()); +} + +TEST(TestKelvinatorClass, FanSpeed) { + IRKelvinatorAC irkelv(0); + irkelv.begin(); + + irkelv.setFan(0); + EXPECT_EQ(0, irkelv.getFan()); + + irkelv.setFan(255); + EXPECT_EQ(kKelvinatorFanMax, irkelv.getFan()); + + irkelv.setFan(kKelvinatorFanMax); + EXPECT_EQ(kKelvinatorFanMax, irkelv.getFan()); + + irkelv.setFan(kKelvinatorFanMax + 1); + EXPECT_EQ(kKelvinatorFanMax, irkelv.getFan()); + + irkelv.setFan(kKelvinatorFanMax - 1); + EXPECT_EQ(kKelvinatorFanMax - 1, irkelv.getFan()); + + irkelv.setFan(1); + EXPECT_EQ(1, irkelv.getFan()); + + irkelv.setFan(1); + EXPECT_EQ(1, irkelv.getFan()); + + irkelv.setFan(3); + EXPECT_EQ(3, irkelv.getFan()); +} + +TEST(TestKelvinatorClass, Checksums) { + uint8_t kelv_code[kKelvinatorStateLength] = { + 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, + 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0}; + + EXPECT_TRUE(IRKelvinatorAC::validChecksum(kelv_code)); + // Change the array so the checksum is invalid. + kelv_code[0] ^= 0xFF; + EXPECT_FALSE(IRKelvinatorAC::validChecksum(kelv_code)); + // Restore the previous change, and change another byte. + kelv_code[0] ^= 0xFF; + kelv_code[4] ^= 0xFF; + EXPECT_FALSE(IRKelvinatorAC::validChecksum(kelv_code)); + kelv_code[4] ^= 0xFF; + // Change something in the 2nd block. + kelv_code[10] ^= 0xFF; + EXPECT_FALSE(IRKelvinatorAC::validChecksum(kelv_code)); + kelv_code[10] ^= 0xFF; + EXPECT_TRUE(IRKelvinatorAC::validChecksum(kelv_code)); +} + +TEST(TestKelvinatorClass, SetAndGetRaw) { + IRKelvinatorAC irkelv(0); + uint8_t initialState[kKelvinatorStateLength] = { + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xA0, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xA0}; + uint8_t expectedState[kKelvinatorStateLength] = { + 0x08, 0x05, 0x20, 0x50, 0x00, 0x00, 0x00, 0x70, + 0x08, 0x05, 0x20, 0x70, 0x00, 0x00, 0x00, 0x70}; + + EXPECT_STATE_EQ(initialState, irkelv.getRaw(), kKelvinatorBits); + // toggle the power state. + irkelv.setPower(!irkelv.getPower()); + irkelv.setTemp(21); + irkelv.setLight(true); + EXPECT_STATE_EQ(expectedState, irkelv.getRaw(), kKelvinatorBits); + irkelv.setRaw(initialState); + EXPECT_STATE_EQ(initialState, irkelv.getRaw(), kKelvinatorBits); +} + +TEST(TestKelvinatorClass, HumanReadable) { + IRKelvinatorAC irkelv(0); + + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (AUTO), Turbo: Off, " + "Quiet: Off, XFan: Off, IonFilter: Off, Light: Off, " + "Swing (Horizontal): Off, Swing (Vertical): Off", + irkelv.toString()); + irkelv.on(); + irkelv.setMode(kKelvinatorCool); + irkelv.setTemp(25); + irkelv.setFan(kKelvinatorFanMax); + irkelv.setXFan(true); + irkelv.setIonFilter(true); + irkelv.setLight(true); + irkelv.setSwingHorizontal(true); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 25C, Fan: 5 (MAX), Turbo: Off, " + "Quiet: Off, XFan: On, IonFilter: On, Light: On, " + "Swing (Horizontal): On, Swing (Vertical): Off", + irkelv.toString()); +} + +TEST(TestKelvinatorClass, MessageConstuction) { + IRKelvinatorAC irkelv(0); + IRsendTest irsend(4); + irkelv.begin(); + irsend.begin(); + + irkelv.setFan(1); + irkelv.setMode(kKelvinatorCool); + irkelv.setTemp(27); + irkelv.setSwingVertical(false); + irkelv.setSwingHorizontal(true); + irkelv.setIonFilter(true); + irkelv.setQuiet(false); + irkelv.setLight(false); + irkelv.setPower(true); + irkelv.setTurbo(false); + irkelv.setXFan(true); + + // Check everything for kicks. + EXPECT_EQ(1, irkelv.getFan()); + EXPECT_EQ(kKelvinatorCool, irkelv.getMode()); + EXPECT_EQ(27, irkelv.getTemp()); + EXPECT_FALSE(irkelv.getSwingVertical()); + EXPECT_TRUE(irkelv.getSwingHorizontal()); + EXPECT_TRUE(irkelv.getIonFilter()); + EXPECT_FALSE(irkelv.getQuiet()); + EXPECT_FALSE(irkelv.getLight()); + EXPECT_TRUE(irkelv.getPower()); + EXPECT_FALSE(irkelv.getTurbo()); + EXPECT_TRUE(irkelv.getXFan()); + + irsend.reset(); + irsend.sendKelvinator(irkelv.getRaw()); + EXPECT_EQ( + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s1530m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s1530m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s1530" + "m680s39950" + "m9010s4505" + "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s1530m680s510" + "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s1530m680s1530" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s510" + "m680s510m680s1530m680s510" + "m680s19975" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s510m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s510m680s510m680s510" + "m680s510m680s510m680s510m680s510m680s1530m680s1530m680s1530m680s1530" + "m680s39950", + irsend.outputStr()); +} + +// Decode a synthetic Kelvinator message. +TEST(TestDecodeKelvinator, NormalSynthetic) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + uint8_t kelv_code[kKelvinatorStateLength] = { + 0x19, 0x0B, 0x80, 0x50, 0x00, 0x00, 0x00, 0xE0, + 0x19, 0x0B, 0x80, 0x70, 0x00, 0x00, 0x10, 0xf0}; + irsend.reset(); + irsend.sendKelvinator(kelv_code); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(KELVINATOR, irsend.capture.decode_type); + ASSERT_EQ(kKelvinatorBits, irsend.capture.bits); + EXPECT_STATE_EQ(kelv_code, irsend.capture.state, kKelvinatorBits); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_LG_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_LG_test.cpp similarity index 63% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_LG_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_LG_test.cpp index fbdaf7126..8ab24a731 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_LG_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_LG_test.cpp @@ -1,8 +1,8 @@ // Copyright 2017 David Conran +#include "ir_LG.h" #include "IRsend.h" #include "IRsend_test.h" -#include "ir_LG.h" #include "gtest/gtest.h" // Tests for calcLGChecksum() @@ -30,23 +30,25 @@ TEST(TestSendLG, SendDataOnly) { irsend.reset(); irsend.sendLG(0x4B4AE51); EXPECT_EQ( - "m8000s4000" + "m8500s4250" "m550s550m550s1600m550s550m550s550" "m550s1600m550s550m550s1600m550s1600m550s550m550s1600m550s550m550s550" "m550s1600m550s550m550s1600m550s550m550s1600m550s1600m550s1600m550s550" "m550s550m550s1600m550s550m550s1600m550s550m550s550m550s550m550s1600" - "m550s108050", irsend.outputStr()); + "m550s50300", + irsend.outputStr()); irsend.reset(); - irsend.sendLG(0xB4B4AE51, LG32_BITS); + irsend.sendLG(0xB4B4AE51, kLg32Bits); EXPECT_EQ( "m4480s4480" "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560m560s1680" - "m560s108080" - "m8950s2250m550s108050", irsend.outputStr()); + "m560s44800" + "m8950s2250m550s96300", + irsend.outputStr()); } // Test sending with different repeats. @@ -55,43 +57,46 @@ TEST(TestSendLG, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendLG(0x4B4AE51, LG_BITS, 1); + irsend.sendLG(0x4B4AE51, kLgBits, 1); EXPECT_EQ( - "m8000s4000" + "m8500s4250" "m550s550m550s1600m550s550m550s550" "m550s1600m550s550m550s1600m550s1600m550s550m550s1600m550s550m550s550" "m550s1600m550s550m550s1600m550s550m550s1600m550s1600m550s1600m550s550" "m550s550m550s1600m550s550m550s1600m550s550m550s550m550s550m550s1600" - "m550s108050" - "m8000s2250m550s108050", irsend.outputStr()); + "m550s50300" + "m8500s2250m550s96750", + irsend.outputStr()); irsend.reset(); - irsend.sendLG(0xB4B4AE51, LG32_BITS, 1); + irsend.sendLG(0xB4B4AE51, kLg32Bits, 1); EXPECT_EQ( "m4480s4480" "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560m560s1680" - "m560s108080" - "m8950s2250m550s108050" - "m8950s2250m550s108050", irsend.outputStr()); + "m560s44800" + "m8950s2250m550s96300" + "m8950s2250m550s96300", + irsend.outputStr()); } // Test sending an atypical data size. -TEST(TestSendLG, SendUsualSize) { +TEST(TestSendLG, SendUnusualSize) { IRsendTest irsend(4); irsend.begin(); irsend.reset(); irsend.sendLG(0x0, 31); EXPECT_EQ( - "m8000s4000" + "m8500s4250" "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" "m550s550m550s550m550s550m550s550m550s550m550s550m550s550" - "m550s108050", irsend.outputStr()); + "m550s60650", + irsend.outputStr()); irsend.reset(); irsend.sendLG(0x0, 64); @@ -105,8 +110,9 @@ TEST(TestSendLG, SendUsualSize) { "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s108080" - "m8950s2250m550s108050", irsend.outputStr()); + "m560s26880" + "m8950s2250m550s96300", + irsend.outputStr()); } // Tests for encodeLG(). @@ -132,11 +138,11 @@ TEST(TestDecodeLG, NormalDecodeWithStrict) { // Normal LG 28-bit message. irsend.reset(); - irsend.sendLG(0x4B4AE51, LG_BITS); + irsend.sendLG(0x4B4AE51, kLgBits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG_BITS, irsend.capture.bits); + EXPECT_EQ(kLgBits, irsend.capture.bits); EXPECT_EQ(0x4B4AE51, irsend.capture.value); EXPECT_EQ(0x4B, irsend.capture.address); EXPECT_EQ(0x4AE5, irsend.capture.command); @@ -144,11 +150,11 @@ TEST(TestDecodeLG, NormalDecodeWithStrict) { // Normal LG 32-bit message. irsend.reset(); - irsend.sendLG(0xB4B4AE51, LG32_BITS); + irsend.sendLG(0xB4B4AE51, kLg32Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, false)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0xB4B4AE51, irsend.capture.value); EXPECT_EQ(0xB4B, irsend.capture.address); EXPECT_EQ(0x4AE5, irsend.capture.command); @@ -158,9 +164,9 @@ TEST(TestDecodeLG, NormalDecodeWithStrict) { irsend.reset(); irsend.sendLG(irsend.encodeLG(0x07, 0x99)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG_BITS, irsend.capture.bits); + EXPECT_EQ(kLgBits, irsend.capture.bits); EXPECT_EQ(0x700992, irsend.capture.value); EXPECT_EQ(0x07, irsend.capture.address); EXPECT_EQ(0x99, irsend.capture.command); @@ -168,11 +174,11 @@ TEST(TestDecodeLG, NormalDecodeWithStrict) { // Synthesised Normal LG 32-bit message. irsend.reset(); - irsend.sendLG(irsend.encodeLG(0x800, 0x8000), LG32_BITS); + irsend.sendLG(irsend.encodeLG(0x800, 0x8000), kLg32Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0x80080008, irsend.capture.value); EXPECT_EQ(0x800, irsend.capture.address); EXPECT_EQ(0x8000, irsend.capture.command); @@ -187,11 +193,11 @@ TEST(TestDecodeLG, NormalDecodeWithRepeatAndStrict) { // Normal LG 28-bit message with 2 repeats. irsend.reset(); - irsend.sendLG(irsend.encodeLG(0x07, 0x99), LG_BITS, 2); + irsend.sendLG(irsend.encodeLG(0x07, 0x99), kLgBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG_BITS, irsend.capture.bits); + EXPECT_EQ(kLgBits, irsend.capture.bits); EXPECT_EQ(0x700992, irsend.capture.value); EXPECT_EQ(0x07, irsend.capture.address); EXPECT_EQ(0x99, irsend.capture.command); @@ -199,11 +205,11 @@ TEST(TestDecodeLG, NormalDecodeWithRepeatAndStrict) { // Normal LG 32-bit message with 2 repeats. irsend.reset(); - irsend.sendLG(irsend.encodeLG(0x07, 0x99), LG32_BITS, 2); + irsend.sendLG(irsend.encodeLG(0x07, 0x99), kLg32Bits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0x700992, irsend.capture.value); EXPECT_EQ(0x07, irsend.capture.address); EXPECT_EQ(0x99, irsend.capture.command); @@ -221,30 +227,30 @@ TEST(TestDecodeLG, DecodeWithNonStrictValues) { irsend.reset(); irsend.sendLG(0x1); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, false)); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG_BITS, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); // Illegal LG 32-bit message value. irsend.reset(); - irsend.sendLG(0x1111111, LG32_BITS); + irsend.sendLG(0x1111111, kLg32Bits); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, false)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0x1111111, irsend.capture.value); EXPECT_EQ(0x11, irsend.capture.address); EXPECT_EQ(0x1111, irsend.capture.command); EXPECT_FALSE(irsend.capture.repeat); irsend.reset(); - irsend.sendLG(0x1111111, LG32_BITS); + irsend.sendLG(0x1111111, kLg32Bits); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); } // Decode unsupported LG message sizes. @@ -259,10 +265,10 @@ TEST(TestDecodeLG, DecodeWithNonStrictSizes) { irsend.sendLG(irsend.encodeLG(0x07, 0x99), 16); irsend.makeDecodeResult(); // Should fail when unexpected against different bit sizes. - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, false)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, 16, false)); @@ -277,10 +283,10 @@ TEST(TestDecodeLG, DecodeWithNonStrictSizes) { irsend.sendLG(0x123456789, 36); // Illegal value LG 36-bit message. irsend.makeDecodeResult(); // Should fail when unexpected against different bit sizes. - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, false)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, 36, false)); EXPECT_EQ(LG, irsend.capture.decode_type); @@ -317,22 +323,21 @@ TEST(TestDecodeLG, DecodeGlobalCacheExample) { IRrecv irrecv(4); irsend.begin(); -// TODO(anyone): Find a Global Cache example of the LG 28-bit message. + // TODO(anyone): Find a Global Cache example of the LG 28-bit message. irsend.reset(); // LG (32-bit) code from Global Cache. - uint16_t gc_test[75] = {38000, 1, 69, 341, 170, 21, 64, 21, 21, 21, 64, - 21, 64, 21, 21, 21, 64, 21, 21, 21, 21, 21, 64, - 21, 21, 21, 64, 21, 64, 21, 21, 21, 64, 21, 21, - 21, 21, 21, 64, 21, 21, 21, 64, 21, 21, 21, 64, - 21, 64, 21, 64, 21, 21, 21, 21, 21, 64, 21, 21, - 21, 64, 21, 21, 21, 21, 21, 21, 21, 64, 21, 1517, - 341, 85, 21, 3655}; + uint16_t gc_test[75] = { + 38000, 1, 69, 341, 170, 21, 64, 21, 21, 21, 64, 21, 64, 21, 21, + 21, 64, 21, 21, 21, 21, 21, 64, 21, 21, 21, 64, 21, 64, 21, + 21, 21, 64, 21, 21, 21, 21, 21, 64, 21, 21, 21, 64, 21, 21, + 21, 64, 21, 64, 21, 64, 21, 21, 21, 21, 21, 64, 21, 21, 21, + 64, 21, 21, 21, 21, 21, 21, 21, 64, 21, 1517, 341, 85, 21, 3655}; irsend.sendGC(gc_test, 75); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); - EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0xB4B4AE51, irsend.capture.value); EXPECT_EQ(0xB4B, irsend.capture.address); EXPECT_EQ(0x4AE5, irsend.capture.command); @@ -347,12 +352,71 @@ TEST(TestDecodeLG, FailToDecodeNonLGExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeLG(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); +} + +// Tests for sendLG2(). + +// Test sending typical data only. +TEST(TestSendLG2, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendLG2(0x880094D); + EXPECT_EQ( + "m3200s9850" + "m550s1600m550s550m550s550m550s550m550s1600m550s550m550s550m550s550" + "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" + "m550s1600m550s550m550s550m550s1600m550s550m550s1600m550s550m550s550" + "m550s1600m550s1600m550s550m550s1600" + "m550s55250", + irsend.outputStr()); +} + +TEST(TestDecodeLG2, SyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendLG2(0x880094D); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture)); + ASSERT_EQ(LG2, irsend.capture.decode_type); + EXPECT_EQ(kLgBits, irsend.capture.bits); + EXPECT_EQ(0x880094D, irsend.capture.value); +} + +// Verify decoding of LG variant 2 messages. +TEST(TestDecodeLG2, RealLG2Example) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // From issue #548 + uint16_t rawData[59] = { + 3154, 9834, 520, 1634, 424, 606, 424, 568, 462, 570, 462, 1564, + 508, 568, 458, 544, 500, 546, 508, 530, 508, 532, 506, 566, + 464, 568, 460, 578, 464, 568, 464, 532, 506, 552, 474, 1592, + 506, 568, 460, 570, 462, 1564, 506, 606, 424, 1640, 424, 616, + 422, 570, 462, 1616, 460, 1584, 500, 544, 506, 1598, 490}; // UNKNOWN + // F6D13AE8 + irsend.sendRaw(rawData, 59, 38000); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture)); + ASSERT_EQ(LG2, irsend.capture.decode_type); + EXPECT_EQ(kLgBits, irsend.capture.bits); + EXPECT_EQ(0x880094D, irsend.capture.value); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Lasertag_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Lasertag_test.cpp new file mode 100644 index 000000000..041109fb8 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Lasertag_test.cpp @@ -0,0 +1,342 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// LL AAA SSSSS EEEEEEE RRRRRR TTTTTTT AAA GGGG +// LL AAAAA SS EE RR RR TTT AAAAA GG GG +// LL AA AA SSSSS EEEEE RRRRRR TTT AA AA GG +// LL AAAAAAA SS EE RR RR TTT AAAAAAA GG GG +// LLLLLLL AA AA SSSSS EEEEEEE RR RR TTT AA AA GGGGGG + +// Tests for sendLasertag(). + +// Test sending simplest case data only. +TEST(TestSendLasertag, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendLasertag(0x1); // Red 1 + EXPECT_EQ( + "m333s333m333s333m333s333m333s333m333s333m333s333m333s333m333s333m333" + "s333m333s333m333s333m333s666m333s100000", + irsend.outputStr()); + + irsend.reset(); + irsend.sendLasertag(0x2); // Red 2 + EXPECT_EQ( + "m333s333m333s333m333s333m333s333m333s333m333s333m333s333" + "m333s333m333s333m333s333m333s666m666s100333", + irsend.outputStr()); + + irsend.reset(); + irsend.sendLasertag(0x51); // Green 1 + // Raw: (21) + // m364s364m332s336m384s276m332s364m332s304m416s584m692s724m640s360m304s332m392s612m380, + EXPECT_EQ( + // m364s364m332s336m384s276m332s364m332s304m416s584 + // m692s724m640s360m304s332m392s612m380 + "m333s333m333s333m333s333m333s333m333s333m333s666" + "m666s666m666s333m333s333m333s666m333s100000", + irsend.outputStr()); + + irsend.reset(); + // Raw: (19) + // m332s308m412s280m360s336m332s304m444s248m332s644m744s612m696s692m668s636m360 + irsend.sendLasertag(0x55); // Green 5 + EXPECT_EQ( + // m332s308m412s280m360s336m332s304m444s248m332s644 + // m744s612m696s692m668s636m360 + "m333s333m333s333m333s333m333s333m333s333m333s666" + "m666s666m666s666m666s666m333s100000", + irsend.outputStr()); +} + +TEST(TestSendLasertag, SendDataWithRepeat) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendLasertag(0x1, kLasertagBits, 1); // Red 1, one repeat. + EXPECT_EQ( + "m333s333m333s333m333s333m333s333m333s333m333s333m333s333m333s333" + "m333s333m333s333m333s333m333s666m333s100000" + "m333s333m333s333m333s333m333s333m333s333m333s333m333s333m333s333" + "m333s333m333s333m333s333m333s666m333s100000", + irsend.outputStr()); + + irsend.reset(); + irsend.sendLasertag(0x52, kLasertagBits, 2); // Green 2, two repeats. + EXPECT_EQ( + "m333s333m333s333m333s333m333s333m333s333m333s666m666s666m666s333" + "m333s666m666s100333" + "m333s333m333s333m333s333m333s333m333s333m333s666m666s666m666s333" + "m333s666m666s100333" + "m333s333m333s333m333s333m333s333m333s333m333s666m666s666m666s333" + "m333s666m666s100333", + irsend.outputStr()); +} + +TEST(TestSendLasertag, SmallestMessageSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendLasertag(0x1555); // Alternating bit pattern will be the smallest. + // i.e. 7 actual 'mark' pulses, which is a rawlen of 13. + EXPECT_EQ("m0s333m666s666m666s666m666s666m666s666m666s666m666s666m333s100000", + irsend.outputStr()); +} + +// Tests for decodeLasertag(). + +// Decode normal Lasertag messages. +TEST(TestDecodeLasertag, NormalSyntheticDecodeWithStrict) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Normal Lasertag 13-bit message. + irsend.reset(); + irsend.sendLasertag(0x01); // Red 1 + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x01, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); // Unit 1 + EXPECT_EQ(0x0, irsend.capture.command); // Team Red + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendLasertag(0x02); // Red 2 + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit 2 + EXPECT_EQ(0x0, irsend.capture.command); // Team Red + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendLasertag(0x06); // Red 6 + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x06, irsend.capture.value); + EXPECT_EQ(0x6, irsend.capture.address); // Unit 6 + EXPECT_EQ(0x0, irsend.capture.command); // Team Red + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendLasertag(0x51); // Green 1 + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x51, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); // Unit 1 + EXPECT_EQ(0x5, irsend.capture.command); // Team Green + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendLasertag(0x56); // Green 6 + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x56, irsend.capture.value); + EXPECT_EQ(0x6, irsend.capture.address); // Unit + EXPECT_EQ(0x5, irsend.capture.command); // Team + EXPECT_FALSE(irsend.capture.repeat); +} + +// Example data taken from: https://github.com/z3t0/Arduino-IRremote/issues/532 +TEST(TestDecodeLasertag, RealExamples) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t green3[21] = {360, 364, 272, 360, 420, 248, 360, 360, 332, 308, 388, + 612, 692, 696, 636, 360, 332, 700, 300, 308, 416}; + irsend.sendRaw(green3, 21, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x53, irsend.capture.value); + EXPECT_EQ(0x3, irsend.capture.address); // Unit + EXPECT_EQ(0x5, irsend.capture.command); // Team + + irsend.reset(); + uint16_t green1[21] = {364, 364, 332, 336, 384, 276, 332, 364, 332, 304, 416, + 584, 692, 724, 640, 360, 304, 332, 392, 612, 380}; + irsend.sendRaw(green1, 21, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x51, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); // Unit + EXPECT_EQ(0x5, irsend.capture.command); // Team + + irsend.reset(); + uint16_t green4[19] = {336, 304, 412, 280, 360, 360, 304, 308, 420, 276, + 332, 636, 744, 620, 688, 724, 640, 360, 304}; + irsend.sendRaw(green4, 19, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x54, irsend.capture.value); + EXPECT_EQ(0x4, irsend.capture.address); // Unit + EXPECT_EQ(0x5, irsend.capture.command); // Team + + irsend.reset(); + uint16_t unit15[25] = {280, 360, 360, 308, 332, 388, 308, 332, 360, + 308, 360, 360, 304, 304, 412, 284, 304, 692, + 364, 360, 276, 336, 416, 276, 328}; + irsend.sendRaw(unit15, 25, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x0F, irsend.capture.value); + EXPECT_EQ(0xF, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_1[23] = {406, 262, 384, 374, 256, 354, 306, 366, + 252, 442, 256, 374, 358, 336, 278, 438, + 246, 340, 380, 292, 304, 688, 746}; + irsend.sendRaw(red_unit2_1, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_2[23] = {302, 306, 302, 392, 196, 476, 278, 352, + 304, 348, 278, 438, 226, 382, 328, 366, + 252, 458, 196, 392, 302, 688, 644}; + irsend.sendRaw(red_unit2_2, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_3[23] = {196, 432, 304, 348, 328, 386, 304, 326, + 302, 370, 252, 442, 272, 356, 278, 374, + 276, 438, 274, 352, 302, 668, 622}; + irsend.sendRaw(red_unit2_3, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_4[23] = {304, 390, 328, 324, 324, 346, 350, 364, + 300, 330, 320, 310, 324, 388, 242, 366, + 354, 318, 354, 340, 244, 726, 670}; + irsend.sendRaw(red_unit2_4, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit1_1_issue532[25] = { + 368, 352, 336, 308, 388, 276, 364, 356, 280, 360, 332, 336, 360, + 360, 308, 300, 416, 280, 356, 360, 312, 328, 336, 636, 424}; + irsend.sendRaw(red_unit1_1_issue532, 25, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x01, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit1_2_issue532[25] = { + 328, 400, 272, 360, 388, 280, 360, 364, 272, 364, 332, 336, 332, + 388, 304, 308, 388, 280, 356, 364, 272, 368, 384, 612, 408}; + irsend.sendRaw(red_unit1_2_issue532, 25, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x01, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit1_3_issue532[25] = { + 416, 284, 356, 336, 328, 336, 384, 308, 328, 368, 304, 308, 412, + 280, 328, 368, 272, 368, 376, 312, 332, 392, 276, 700, 272}; + irsend.sendRaw(red_unit1_3_issue532, 25, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x01, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_1_issue532[23] = {308, 340, 408, 284, 332, 388, 276, 336, + 356, 340, 332, 360, 300, 364, 360, 304, + 280, 444, 276, 336, 384, 640, 696}; + irsend.sendRaw(red_unit2_1_issue532, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_2_issue532[23] = {332, 308, 388, 280, 328, 420, 308, 304, + 384, 308, 332, 364, 272, 368, 384, 276, + 364, 360, 308, 332, 384, 612, 696}; + irsend.sendRaw(red_unit2_2_issue532, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team + + irsend.reset(); + uint16_t red_unit2_3_issue532[23] = {392, 332, 340, 272, 448, 276, 364, 328, + 340, 272, 396, 296, 340, 380, 312, 296, + 400, 272, 364, 352, 284, 720, 672}; + irsend.sendRaw(red_unit2_3_issue532, 23, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x02, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); // Unit + EXPECT_EQ(0x0, irsend.capture.command); // Team +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Lutron_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Lutron_test.cpp new file mode 100644 index 000000000..6c99b9904 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Lutron_test.cpp @@ -0,0 +1,143 @@ +// Copyright 2018 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendLutron(). + +// Test sending typical data only. +TEST(TestSendLutron, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + irsend.sendLutron(0); + EXPECT_EQ("m2288s230080", irsend.outputStr()); + irsend.sendLutron(0xAAAAAAAAA); // Longest possible sequence. (I think) + EXPECT_EQ( + "m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288" + "m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288" + "m2288s2288m2288s2288m2288s2288m2288s152288", + irsend.outputStr()); + irsend.sendLutron(0x7FFFFFFFF); + EXPECT_EQ("m82368s150000", irsend.outputStr()); + irsend.sendLutron(0x7F88BD120); + EXPECT_EQ( + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendLutron, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + // Send a command with 0 repeats. + irsend.sendLutron(0x7F88BD120, kLutronBits, 0); + EXPECT_EQ( + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440", + irsend.outputStr()); + // Send a command with 1 repeat. + irsend.sendLutron(0x7F88BD120, kLutronBits, 1); + EXPECT_EQ( + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440" + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440", + irsend.outputStr()); + // Send a command with 3 repeats. + irsend.sendLutron(0x7F88BD120, kLutronBits, 3); + EXPECT_EQ( + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440" + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440" + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440" + "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" + "s161440", + irsend.outputStr()); +} + +// Tests for decodeLutron(). +// Decode normal Lutron messages. +TEST(TestDecodeLutron, SyntheticDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Synthesised Normal Lutron messages. + irsend.reset(); + irsend.sendLutron(0x7F88BD120); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x7F88BD120, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendLutron(0x0DEADBEEF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x0DEADBEEF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendLutron(0x0); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendLutron(0x7FFFFFFFF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x7FFFFFFFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +// Decode a documented example +TEST(TestDecodeLutron, DocumentedExampleFullOff) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Full Off code. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/515 + uint16_t rawData[14] = {20518, 6839, 2280, 6839, 2280, 2280, 9119, + 2280, 2280, 6839, 2280, 4560, 2280, 11399}; + irsend.reset(); + irsend.sendRaw(rawData, 14, 40); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x7F88BD120, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + uint16_t pronto[18] = {0x0000, 0x0069, 0x0007, 0x0000, 0x032a, 0x010e, + 0x005a, 0x010e, 0x005a, 0x005a, 0x0168, 0x005a, + 0x005a, 0x010e, 0x005a, 0x00b4, 0x005a, 0x01c2}; + irsend.reset(); + irsend.sendPronto(pronto, 18); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x7F88BD120, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_MWM_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_MWM_test.cpp new file mode 100644 index 000000000..9ecd0eac1 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_MWM_test.cpp @@ -0,0 +1,124 @@ +// Copyright 2017 David Conran +// Copyright 2018 Brett T. Warden + +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// MM MM WW WW MM MM +// MMM MMM WW WW MMM MMM +// MM M MM WW W WW MM M MM +// MM MM WWW WWW MM MM +// MM MM WW WW MM MM + +// Tests for sendMWM(). + +// Test sending simplest case data only. +TEST(TestSendMWM, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + unsigned char test1[] = {0x96, 0x19, 0x10, 0x24, 0x0A, + 0x6B, 0x20, 0x03, 0x82}; + /* + ++--+-++-- + +-++--+++- + +++++-+++- + +++-++-++- + ++-+-++++- + +--+-+--+- + ++++++-++- + +--++++++- + ++-+++++-- + */ + irsend.sendMWM(test1, sizeof(test1), 0); + EXPECT_EQ( + "m834s834m417s417m834s834" + "m417s417m834s834m1251s417" + "m2085s417m1251s417" + "m1251s417m834s417m834s417" + "m834s417m417s417m1668s417" + "m417s834m417s417m417s834m417s417" + "m2502s417m834s417" + "m417s834m2502s417" + "m834s417m2085s30834", irsend.outputStr()); + + irsend.reset(); + unsigned char test2[] = { + 0x99, 0x26, 0x66, 0x6E, 0xD1, 0x42, 0x06, + 0x20, 0xD0, 0x32, 0xF0, 0x0B + // +-++--++-- + // ++--++-++- + // ++--++--+- + // ++---+--+- + // +-+++-+--- + // ++-++++-+- + // ++--+++++- + // ++++++-++- + // +++++-+--- + // ++-++--++- + // +++++----- + // +--+-++++- + }; + irsend.sendMWM(test2, sizeof(test2), 0); + EXPECT_EQ( + "m417s417m834s834m834s834" + "m834s834m834s417m834s417" + "m834s834m834s834m417s417" + "m834s1251m417s834m417s417" + "m417s417m1251s417m417s1251" + "m834s417m1668s417m417s417" + "m834s834m2085s417" + "m2502s417m834s417" + "m2085s417m417s1251" + "m834s417m834s834m834s417" + "m2085s2085" + "m417s834m417s417m1668s30417", irsend.outputStr()); +} + +// Tests for decodeMWM(). + +// Example data +TEST(TestDecodeMWM, RealExamples) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t short_code[] = { + 915, 793, 488, 366, 915, 793, 427, 366, 915, 793, 1281, 427, + 2136, 366, 1281, 366, 915, 793, 427, 854, 854, 366, 1281, 854, + 1708, 366, 488, 793, 854, 427, 427, 427, 427, 366, 854, 427, + 2563, 366, 488, 793, 2563, 366, 488, 2075, 427, 34057}; + unsigned char short_expected[] = {0x96, 0x19, 0x10, 0x36, 0x0C, + 0x53, 0x02, 0x03, 0xDF}; + irsend.sendRaw(short_code, sizeof(short_code) / sizeof(short_code[0]), 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MWM, irsend.capture.decode_type); + EXPECT_EQ(8 * sizeof(short_expected) / sizeof(short_expected[0]), + irsend.capture.bits); + EXPECT_STATE_EQ(short_expected, irsend.capture.state, irsend.capture.bits); + + irsend.reset(); + uint16_t long_code[] = { + 427, 427, 854, 854, 854, 793, 915, 793, 854, 366, 915, 366, 854, + 854, 854, 793, 488, 366, 915, 1220, 427, 793, 488, 366, 488, 366, + 1281, 427, 427, 1220, 915, 366, 1708, 366, 488, 366, 854, 854, 2136, + 366, 2563, 366, 854, 427, 2136, 366, 488, 1220, 854, 427, 854, 793, + 915, 366, 2136, 2075, 427, 793, 488, 366, 1708, 30517}; + unsigned char long_expected[] = {0x99, 0x26, 0x66, 0x6E, 0xD1, 0x42, + 0x06, 0x20, 0xD0, 0x32, 0xF0, 0x0B}; + irsend.sendRaw(long_code, sizeof(long_code) / sizeof(long_code[0]), 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MWM, irsend.capture.decode_type); + EXPECT_EQ(8 * sizeof(long_expected) / sizeof(long_expected[0]), + irsend.capture.bits); + EXPECT_STATE_EQ(long_expected, irsend.capture.state, irsend.capture.bits); +} + +// vim: et:ts=2:sw=2 diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Magiquest_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Magiquest_test.cpp new file mode 100644 index 000000000..e1c3da83d --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Magiquest_test.cpp @@ -0,0 +1,162 @@ +// Copyright 2017 David Conran + +#include "ir_Magiquest.h" +#include "IRrecv.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for encodeMagiQuest() +TEST(TestEncodeMagiQuest, General) { + IRsendTest irsend(0); + EXPECT_EQ(0x0, irsend.encodeMagiQuest(0x0, 0x0)); + EXPECT_EQ(0x10001, irsend.encodeMagiQuest(0x1, 0x1)); + EXPECT_EQ(0x20003, irsend.encodeMagiQuest(0x2, 0x3)); + EXPECT_EQ(0x123456781234, irsend.encodeMagiQuest(0x12345678, 0x1234)); + EXPECT_EQ(0xFFFFFFFFFFFF, irsend.encodeMagiQuest(0xFFFFFFFF, 0xFFFF)); +} + +// Tests for sendMagiQuest() + +// Test sending typical data only. +TEST(TestSendMagiQuest, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendMagiQuest(0x0); + EXPECT_EQ( + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s100850", + irsend.outputStr()); + irsend.reset(); + irsend.sendMagiQuest(0x123456789ABC); + EXPECT_EQ( + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m580s600m280s850m280s850m580s600m280s850" + "m280s850m280s850m580s600m580s600m280s850m580s600m280s850m280s850" + "m280s850m580s600m280s850m580s600m280s850m580s600m580s600m280s850" + "m280s850m580s600m580s600m580s600m580s600m280s850m280s850m280s850" + "m580s600m280s850m280s850m580s600m580s600m280s850m580s600m280s850" + "m580s600m280s850m580s600m580s600m580s600m580s600m280s850m280s100850", + irsend.outputStr()); +} + +// Test sending typical data only. +TEST(TestSendMagiQuest, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendMagiQuest(0x12345678ABCD, kMagiquestBits, 2); // two repeats. + EXPECT_EQ( + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m580s600m280s850m280s850m580s600m280s850" + "m280s850m280s850m580s600m580s600m280s850m580s600m280s850m280s850" + "m280s850m580s600m280s850m580s600m280s850m580s600m580s600m280s850" + "m280s850m580s600m580s600m580s600m580s600m280s850m280s850m280s850" + "m580s600m280s850m580s600m280s850m580s600m280s850m580s600m580s600" + "m580s600m580s600m280s850m280s850m580s600m580s600m280s850m580s100600" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m580s600m280s850m280s850m580s600m280s850" + "m280s850m280s850m580s600m580s600m280s850m580s600m280s850m280s850" + "m280s850m580s600m280s850m580s600m280s850m580s600m580s600m280s850" + "m280s850m580s600m580s600m580s600m580s600m280s850m280s850m280s850" + "m580s600m280s850m580s600m280s850m580s600m280s850m580s600m580s600" + "m580s600m580s600m280s850m280s850m580s600m580s600m280s850m580s100600" + "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" + "m280s850m280s850m280s850m580s600m280s850m280s850m580s600m280s850" + "m280s850m280s850m580s600m580s600m280s850m580s600m280s850m280s850" + "m280s850m580s600m280s850m580s600m280s850m580s600m580s600m280s850" + "m280s850m580s600m580s600m580s600m580s600m280s850m280s850m280s850" + "m580s600m280s850m580s600m280s850m580s600m280s850m580s600m580s600" + "m580s600m580s600m280s850m280s850m580s600m580s600m280s850m580s100600", + irsend.outputStr()); +} + +// Tests for decodeMagiQuest(). + +// Decode normal "synthetic" messages. +TEST(TestDecodeMagiQuest, NormalDecodeWithStrict) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendMagiQuest(0x0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMagiQuest(&irsend.capture, kMagiquestBits, true)); + EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); + EXPECT_EQ(kMagiquestBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendMagiQuest(irsend.encodeMagiQuest(0x1, 0x1)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMagiQuest(&irsend.capture, kMagiquestBits, true)); + EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); + EXPECT_EQ(kMagiquestBits, irsend.capture.bits); + EXPECT_EQ(0x10001, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x1, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendMagiQuest(irsend.encodeMagiQuest(0x12345678, 0xABCD)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMagiQuest(&irsend.capture, kMagiquestBits, true)); + EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); + EXPECT_EQ(kMagiquestBits, irsend.capture.bits); + EXPECT_EQ(0x12345678ABCD, irsend.capture.value); + EXPECT_EQ(0x12345678, irsend.capture.address); + EXPECT_EQ(0xABCD, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Do the last one again, & use the full decoder, not just protocol specific. + irsend.reset(); + irsend.sendMagiQuest(irsend.encodeMagiQuest(0x12345678, 0xABCD)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); + EXPECT_EQ(kMagiquestBits, irsend.capture.bits); + EXPECT_EQ(0x12345678ABCD, irsend.capture.value); +} + +// Decode a "real" example message. +TEST(TestDecodeMagiQuest, RealExamples) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[111] = {262, 842, 298, 858, 238, 866, 240, 890, 238, 866, + 240, 862, 244, 886, 242, 860, 246, 858, 554, 604, + 264, 840, 560, 622, 266, 836, 552, 604, 556, 626, + 262, 866, 240, 864, 264, 838, 268, 862, 244, 886, + 536, 620, 530, 628, 554, 628, 532, 624, 244, 858, + 552, 604, 264, 840, 268, 862, 266, 838, 268, 888, + 240, 864, 242, 860, 268, 862, 244, 860, 236, 868, + 272, 832, 264, 866, 240, 890, 532, 598, 268, 834, + 294, 836, 270, 834, 262, 866, 272, 858, 238, 866, + 534, 622, 268, 836, 270, 860, 268, 862, 526, 604, + 264, 892, 530, 600, 268, 836, 586, 598, 270, 834, + 556}; // Data from PR #365 captured by coolacid + + irsend.sendRaw(rawData, 111, 36000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); + EXPECT_EQ(kMagiquestBits, irsend.capture.bits); + EXPECT_EQ(0x560F40020455, irsend.capture.value); + EXPECT_EQ(0x560F4002, irsend.capture.address); // Wand ID + EXPECT_EQ(0x0455, irsend.capture.command); // Magnitude + EXPECT_FALSE(irsend.capture.repeat); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Midea_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Midea_test.cpp new file mode 100644 index 000000000..5d5f5e932 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Midea_test.cpp @@ -0,0 +1,651 @@ +// Copyright 2017 David Conran + +#include "ir_Midea.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendMidea(). + +// Test sending typical data only. +TEST(TestSendMidea, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMidea(0x0); + EXPECT_EQ( + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s5600", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMidea(0x55AA55AA55AA); + EXPECT_EQ( + "m4480s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5600", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMidea(0xFFFFFFFFFFFF); + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s5600" + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s5600", + irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendMidea, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMidea(0x55AA55AA55AA, kMideaBits, 1); // 1 repeat. + EXPECT_EQ( + "m4480s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5600" + "m4480s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5600", + irsend.outputStr()); + irsend.sendMidea(0x55AA55AA55AA, kMideaBits, 2); // 2 repeats. + EXPECT_EQ( + "m4480s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5600" + "m4480s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5600" + "m4480s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5600", + irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendMidea, SendUnusualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMidea(0x0, 8); + EXPECT_EQ( + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s5600" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s5600", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMidea(0x1234567890ABCDEF, 64); + EXPECT_EQ( + "m4480s4480" + "m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680m560s560" + "m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s1680m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680" + "m560s1680m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s5600" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s1680" + "m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s1680m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560m560s1680" + "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680" + "m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560" + "m560s560m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" + "m560s560m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" + "m560s5600", + irsend.outputStr()); + + // Bit sizes must be a multiple of 8. + irsend.reset(); + irsend.sendMidea(0x0, 17); + EXPECT_EQ("", irsend.outputStr()); +} + +// Tests for IRMideaAC class. + +// Tests for controlling the power state. +TEST(TestMideaACClass, Power) { + IRMideaAC midea(0); + midea.begin(); + + midea.setRaw(0xA1026FFFFFE2); // Power off. + + midea.on(); + EXPECT_TRUE(midea.getPower()); + + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); + + midea.off(); + EXPECT_FALSE(midea.getPower()); + EXPECT_EQ(0xA1026FFFFFE2, midea.getRaw()); + + midea.setPower(true); + EXPECT_TRUE(midea.getPower()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); + + midea.setPower(false); + EXPECT_FALSE(midea.getPower()); + EXPECT_EQ(0xA1026FFFFFE2, midea.getRaw()); +} + +// Tests for the various Checksum routines. +TEST(TestMideaACClass, Checksums) { + IRMideaAC midea(0); + midea.begin(); + + // Known good states + EXPECT_EQ(0x62, IRMideaAC::calcChecksum(0xA1826FFFFF62)); + EXPECT_EQ(0x70, IRMideaAC::calcChecksum(0xA18177FFFF70)); + // Now without the checksum part. + EXPECT_EQ(0x62, IRMideaAC::calcChecksum(0xA1826FFFFF00)); + EXPECT_EQ(0x70, IRMideaAC::calcChecksum(0xA18177FFFF00)); + // Made up values. + EXPECT_EQ(0x00, IRMideaAC::calcChecksum(0x000000000000)); + EXPECT_EQ(0xDF, IRMideaAC::calcChecksum(0x1234567890AB)); + EXPECT_EQ(0xA0, IRMideaAC::calcChecksum(0xFFFFFFFFFFFF)); + // Larger than expected value (full 64bit) + EXPECT_EQ(0xDF, IRMideaAC::calcChecksum(0xFF1234567890AB)); + EXPECT_EQ(0xDF, IRMideaAC::calcChecksum(0x551234567890AB)); + + // Validity tests. + EXPECT_TRUE(IRMideaAC::validChecksum(0xA1826FFFFF62)); + EXPECT_TRUE(IRMideaAC::validChecksum(0xA18177FFFF70)); + EXPECT_FALSE(IRMideaAC::validChecksum(0x1234567890AB)); + + // Doing a setRaw() with a bad state should make a valid checksum on getRaw(). + midea.setRaw(0xA1826FFFFF00); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); +} + +TEST(TestMideaACClass, OperatingMode) { + IRMideaAC midea(0); + midea.begin(); + + midea.setRaw(0xA1826FFFFF62); // Auto mode already set. + midea.setMode(kMideaACAuto); + EXPECT_EQ(kMideaACAuto, midea.getMode()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); // State shouldn't have changed. + + midea.setMode(kMideaACCool); + EXPECT_EQ(kMideaACCool, midea.getMode()); + EXPECT_EQ(0xA1806FFFFF61, midea.getRaw()); + + midea.setMode(kMideaACAuto); + EXPECT_EQ(kMideaACAuto, midea.getMode()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); + + midea.setMode(kMideaACHeat); + EXPECT_EQ(kMideaACHeat, midea.getMode()); + EXPECT_EQ(0xA1836FFFFF63, midea.getRaw()); + + midea.setMode(kMideaACDry); + EXPECT_EQ(kMideaACDry, midea.getMode()); + EXPECT_EQ(0xA1816FFFFF60, midea.getRaw()); + + midea.setMode(kMideaACFan); + EXPECT_EQ(kMideaACFan, midea.getMode()); + EXPECT_EQ(0xA1846FFFFF66, midea.getRaw()); + + midea.setMode(255); + EXPECT_EQ(kMideaACAuto, midea.getMode()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); +} + +TEST(TestMideaACClass, FanSpeed) { + IRMideaAC midea(0); + midea.begin(); + + midea.setRaw(0xA1826FFFFF62); // Auto mode already set. + EXPECT_EQ(kMideaACFanAuto, midea.getFan()); + + midea.setFan(kMideaACFanLow); + EXPECT_EQ(kMideaACFanLow, midea.getFan()); + EXPECT_EQ(0xA18A6FFFFF6C, midea.getRaw()); + + midea.setFan(255); // Setting an unexpected value defaults to auto. + EXPECT_EQ(kMideaACFanAuto, midea.getFan()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); + + midea.setFan(kMideaACFanMed); + EXPECT_EQ(kMideaACFanMed, midea.getFan()); + EXPECT_EQ(0xA1926FFFFF7C, midea.getRaw()); + + midea.setFan(kMideaACFanHigh); + EXPECT_EQ(kMideaACFanHigh, midea.getFan()); + EXPECT_EQ(0xA19A6FFFFF74, midea.getRaw()); + + midea.setFan(kMideaACFanAuto); + EXPECT_EQ(kMideaACFanAuto, midea.getFan()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); +} + +TEST(TestMideaACClass, Temperature) { + IRMideaAC midea(0); + midea.begin(); + + midea.setRaw(0xA1826FFFFF62); // 77F / 25C + EXPECT_EQ(77, midea.getTemp()); // F + EXPECT_EQ(77, midea.getTemp(false)); // F + EXPECT_EQ(25, midea.getTemp(true)); // F + + midea.setTemp(0); + EXPECT_EQ(kMideaACMinTempF, midea.getTemp()); + EXPECT_EQ(0xA18260FFFF6C, midea.getRaw()); + + midea.setTemp(255); + EXPECT_EQ(kMideaACMaxTempF, midea.getTemp()); + EXPECT_EQ(0xA18278FFFF78, midea.getRaw()); + + midea.setTemp(0, true); + EXPECT_EQ(kMideaACMinTempF, midea.getTemp()); + EXPECT_EQ(0xA18260FFFF6C, midea.getRaw()); + + midea.setTemp(255, true); + EXPECT_EQ(kMideaACMaxTempF, midea.getTemp()); + EXPECT_EQ(0xA18278FFFF78, midea.getRaw()); + + // fahrenheit min/max etc. + midea.setTemp(kMideaACMinTempF); + EXPECT_EQ(kMideaACMinTempF, midea.getTemp()); + + midea.setTemp(kMideaACMaxTempF); + EXPECT_EQ(kMideaACMaxTempF, midea.getTemp()); + + midea.setTemp(kMideaACMinTempF - 1); + EXPECT_EQ(kMideaACMinTempF, midea.getTemp()); + + midea.setTemp(kMideaACMaxTempF + 1); + EXPECT_EQ(kMideaACMaxTempF, midea.getTemp()); + + // celsius min/max etc. + midea.setTemp(kMideaACMinTempC, true); + EXPECT_EQ(kMideaACMinTempC, midea.getTemp(true)); + EXPECT_EQ(kMideaACMinTempF, midea.getTemp(false)); + + midea.setTemp(kMideaACMaxTempC, true); + EXPECT_EQ(kMideaACMaxTempC, midea.getTemp(true)); + EXPECT_EQ(kMideaACMaxTempF, midea.getTemp(false)); + + midea.setTemp(kMideaACMinTempC - 1, true); + EXPECT_EQ(kMideaACMinTempC, midea.getTemp(true)); + + midea.setTemp(kMideaACMaxTempC + 1, true); + EXPECT_EQ(kMideaACMaxTempC, midea.getTemp(true)); + EXPECT_EQ(kMideaACMaxTempF, midea.getTemp(false)); + + // General changes. + midea.setTemp(17, true); // C + EXPECT_EQ(17, midea.getTemp(true)); // C + EXPECT_EQ(63, midea.getTemp(false)); // F + + midea.setTemp(21, true); // C + EXPECT_EQ(21, midea.getTemp(true)); // C + EXPECT_EQ(70, midea.getTemp(false)); // F + + midea.setTemp(25, true); // C + EXPECT_EQ(25, midea.getTemp(true)); // C + EXPECT_EQ(77, midea.getTemp(false)); // F + + midea.setTemp(30, true); // C + EXPECT_EQ(30, midea.getTemp(true)); // C + EXPECT_EQ(86, midea.getTemp(false)); // F + + midea.setTemp(80, false); // F + EXPECT_EQ(26, midea.getTemp(true)); // C + EXPECT_EQ(80, midea.getTemp(false)); // F + + midea.setTemp(70); // F + EXPECT_EQ(21, midea.getTemp(true)); // C + EXPECT_EQ(70, midea.getTemp(false)); // F + EXPECT_EQ(70, midea.getTemp()); // F +} + +// Tests for controlling the sleep state. +TEST(TestMideaACClass, Sleep) { + IRMideaAC midea(0); + midea.begin(); + + midea.setRaw(0xA1826FFFFF62); // Sleep off. + + EXPECT_FALSE(midea.getSleep()); + midea.setSleep(true); + EXPECT_TRUE(midea.getSleep()); + EXPECT_EQ(0xA1C26FFFFF22, midea.getRaw()); + midea.setSleep(false); + EXPECT_FALSE(midea.getSleep()); + EXPECT_EQ(0xA1826FFFFF62, midea.getRaw()); +} + +TEST(TestMideaACClass, HumanReadableOutput) { + IRMideaAC midea(0); + midea.begin(); + + midea.setRaw(0xA1826FFFFF62); + EXPECT_EQ( + "Power: On, Mode: 2 (AUTO), Temp: 25C/77F, Fan: 0 (AUTO), " + "Sleep: Off", + midea.toString()); + midea.off(); + midea.setTemp(25); + midea.setFan(kMideaACFanHigh); + midea.setMode(kMideaACDry); + midea.setSleep(true); + EXPECT_EQ("Power: Off, Mode: 1 (DRY), Temp: 16C/62F, Fan: 3 (HI), Sleep: On", + midea.toString()); + + midea.setRaw(0xA19867FFFF7E); + EXPECT_EQ("Power: On, Mode: 0 (COOL), Temp: 20C/69F, Fan: 3 (HI), Sleep: Off", + midea.toString()); +} + +// Tests for decodeMidea(). + +// Decode normal Midea messages with strict set. +TEST(TestDecodeMidea, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Midea 48-bit message. + irsend.reset(); + irsend.sendMidea(0x1234567890DF); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0x1234567890DF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal Midea 48-bit message. + irsend.reset(); + irsend.sendMidea(0x0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal Midea 48-bit message. + irsend.reset(); + irsend.sendMidea(0xFFFFFFFFFFA0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFA0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Real Midea 48-bit message via just decode(). + // i.e. No conficts with other decoders. + irsend.reset(); + irsend.sendMidea(0xA18263FFFF6E); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal repeated Midea messages. +TEST(TestDecodeMidea, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Midea 48-bit message with 2 repeats. + irsend.reset(); + irsend.sendMidea(0xA18263FFFF6E, kMideaBits, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.makeDecodeResult(2 * (2 * kMideaBits + 4)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); + + irsend.makeDecodeResult(4 * (2 * kMideaBits + 4)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); +} + +// Decode unsupported Midea messages. +TEST(TestDecodeMidea, DecodeWithNonStrictSizes) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMidea(0x12, 8); // Illegal value Midea 8-bit message. + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, 8, false)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0x12, irsend.capture.value); + + irsend.reset(); + irsend.sendMidea(0x12345678, 32); // Illegal value Midea 32-bit message. + irsend.makeDecodeResult(); + // Shouldn't pass with strict when we ask for less bits than we got. + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + + irsend.makeDecodeResult(); + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, 32, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, 32, false)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0x12345678, irsend.capture.value); + + // Decode should fail if asked to decode non-multiples of 8 bits. + irsend.reset(); + irsend.sendMidea(0x123456, kMideaBits, 2); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, 9, false)); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodeMidea, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal size Midea 64-bit message. + irsend.sendMidea(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, 64, false)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); +} + +// Fail to decode a non-Midea example via GlobalCache +TEST(TestDecodeMidea, FailToDecodeNonMideaExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Modified a few entries to unexpected values, based on previous test case. + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; + irsend.sendGC(gc_test, 39); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kMideaBits, false)); +} + +// Decode against a real capture reported by a user. See issue #354 +TEST(TestDecodeMidea, DecodeRealExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + irsend.reset(); + + uint16_t rawData[199] = { + 4366, 4470, 498, 1658, 522, 554, 498, 1658, 496, 580, 498, 580, + 498, 578, 498, 580, 498, 1658, 498, 1658, 498, 578, 498, 578, + 498, 580, 496, 582, 496, 578, 498, 1658, 498, 580, 498, 580, + 498, 1656, 498, 1656, 500, 580, 498, 578, 502, 576, 500, 1656, + 498, 1656, 500, 1654, 500, 1656, 500, 1656, 498, 1658, 498, 1656, + 500, 1658, 498, 1656, 498, 1656, 500, 1656, 500, 1654, 500, 1578, + 578, 1658, 498, 1656, 500, 1658, 498, 1656, 498, 1656, 500, 578, + 498, 1638, 516, 1656, 500, 578, 500, 1656, 500, 1656, 498, 1658, + 522, 554, 500, 5258, 4366, 4472, 498, 580, 498, 1658, 498, 580, + 498, 1656, 500, 1600, 556, 1658, 500, 1656, 500, 578, 498, 578, + 522, 1634, 498, 1588, 568, 1658, 498, 1656, 500, 1654, 498, 580, + 498, 1658, 498, 1658, 498, 580, 496, 578, 500, 1654, 500, 1636, + 518, 1656, 500, 578, 520, 558, 498, 578, 498, 580, 498, 576, + 500, 578, 498, 580, 498, 578, 498, 578, 498, 580, 498, 578, + 498, 580, 498, 580, 520, 556, 498, 580, 496, 580, 498, 578, + 500, 578, 498, 1658, 498, 580, 498, 578, 498, 1656, 500, 578, + 498, 580, 498, 580, 498, 1656, 522}; + irsend.sendRaw(rawData, 199, 38000); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Mitsubishi_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Mitsubishi_test.cpp new file mode 100644 index 000000000..7b8eb2192 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Mitsubishi_test.cpp @@ -0,0 +1,1118 @@ +// Copyright 2017 David Conran +// Copyright 2018 denxhun + +#include "ir_Mitsubishi.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendMitsubishi(). + +// Test sending typical data only. +TEST(TestSendMitsubishi, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMitsubishi(0xE242); + EXPECT_EQ( + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080" + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishi(0x0); + EXPECT_EQ( + "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" + "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" + "m300s34080" + "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" + "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" + "m300s34080", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishi(0x4321); + EXPECT_EQ( + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s2100" + "m300s900m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100" + "m300s28080" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s2100" + "m300s900m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100" + "m300s28080", + irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendMitsubishi, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMitsubishi(0xE242, kMitsubishiBits, 0); // 0 repeat. + EXPECT_EQ( + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishi(0xE242, kMitsubishiBits, 1); // 1 repeat. + EXPECT_EQ( + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080" + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080", + irsend.outputStr()); + irsend.sendMitsubishi(0xE242, kMitsubishiBits, 2); // 2 repeats. + EXPECT_EQ( + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080" + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080" + "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" + "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" + "m300s28080", + irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendMitsubishi, SendUnusualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMitsubishi(0x0, 8); + EXPECT_EQ( + "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" + "m300s43680" + "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" + "m300s43680", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishi(0x1234567890ABCDEF, 64); + EXPECT_EQ( + "m300s900m300s900m300s900m300s2100m300s900m300s900m300s2100m300s900" + "m300s900m300s900m300s2100m300s2100m300s900m300s2100m300s900m300s900" + "m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100m300s900" + "m300s900m300s2100m300s2100m300s2100m300s2100m300s900m300s900m300s900" + "m300s2100m300s900m300s900m300s2100m300s900m300s900m300s900m300s900" + "m300s2100m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100" + "m300s2100m300s2100m300s900m300s900m300s2100m300s2100m300s900m300s2100" + "m300s2100m300s2100m300s2100m300s900m300s2100m300s2100m300s2100m300s2100" + "m300s28080" + "m300s900m300s900m300s900m300s2100m300s900m300s900m300s2100m300s900" + "m300s900m300s900m300s2100m300s2100m300s900m300s2100m300s900m300s900" + "m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100m300s900" + "m300s900m300s2100m300s2100m300s2100m300s2100m300s900m300s900m300s900" + "m300s2100m300s900m300s900m300s2100m300s900m300s900m300s900m300s900" + "m300s2100m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100" + "m300s2100m300s2100m300s900m300s900m300s2100m300s2100m300s900m300s2100" + "m300s2100m300s2100m300s2100m300s900m300s2100m300s2100m300s2100m300s2100" + "m300s28080", + irsend.outputStr()); +} + +// Decode normal Mitsubishi messages. +TEST(TestDecodeMitsubishi, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Mitsubishi 16-bit message. + irsend.reset(); + irsend.sendMitsubishi(0xC2B8); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xC2B8, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendMitsubishi(0x0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendMitsubishi(0xFFFF); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xFFFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Non-standard Mitsubishi sizes should fail with strict. + irsend.reset(); + // 12 bits. + irsend.sendMitsubishi(0xFFF, 12); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 12, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, true)); + + // 32 bits. + irsend.sendMitsubishi(0xFFF, 32); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 12, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, true)); +} + +// Decode normal repeated Mitsubishi messages. +TEST(TestDecodeMitsubishi, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Mitsubishi 16-bit message with 2 repeats. + irsend.reset(); + irsend.sendMitsubishi(0xC2B8, kMitsubishiBits, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xC2B8, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal Mitsubishi 16-bit message with 0 repeats. + irsend.reset(); + irsend.sendMitsubishi(0xC2B8, kMitsubishiBits, 0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xC2B8, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode unsupported Mitsubishi messages. +TEST(TestDecodeMitsubishi, DecodeWithNonStrictValues) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMitsubishi(0x0, 8); // Illegal sized Mitsubishi 8-bit message. + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, 8, false)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, false)); + + irsend.reset(); + // Illegal sized Mitsubishi 64-bit message. + irsend.sendMitsubishi(0xFEDCBA9876543210, 64); + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, 64, false)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFEDCBA9876543210, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + // Should fail when we are after a shorter message than we got. + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 8, false)); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodeMitsubishi, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi "Power On" (16-bit) code from Global Cache. + uint16_t gc_test[37] = {33000, 1, 1, 10, 70, 10, 70, 10, 70, 10, 30, 10, 30, + 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, 10, 30, 10, + 30, 10, 30, 10, 30, 10, 70, 10, 30, 10, 936}; + irsend.sendGC(gc_test, 37); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xE242, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Fail to decode a non-Mitsubishi example via GlobalCache +TEST(TestDecodeMitsubishi, FailToDecodeNonMitsubishiExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Modified a few entries to unexpected values, based on previous test case. + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; + irsend.sendGC(gc_test, 39); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture)); + ASSERT_FALSE( + irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, false)); +} + +// Tests for Mitsubishi A/C methods. + +// Test sending typical data only. +TEST(TestSendMitsubishiAC, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t mitsub_code[kMitsubishiACStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, + 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; + irsend.reset(); + irsend.sendMitsubishiAC(mitsub_code); + EXPECT_EQ( + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m440s17100" + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m440s17100", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendMitsubishiAC, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + uint8_t mitsub_code[kMitsubishiACStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x06, 0x30, + 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}; + + irsend.sendMitsubishiAC(mitsub_code, kMitsubishiACStateLength, 0); + EXPECT_EQ( + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m440s17100", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishiAC(mitsub_code, kMitsubishiACStateLength, 2); + EXPECT_EQ( + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m440s17100" + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m440s17100" + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m440s17100", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendMitsubishiAC, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t mitsub_short_code[17] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, + 0x08, 0x06, 0x30, 0x45, 0x67, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t mitsub_long_code[19] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, + 0x06, 0x30, 0x45, 0x67, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x00}; + irsend.reset(); + irsend.sendMitsubishiAC(mitsub_short_code, 17); + ASSERT_EQ("", irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishiAC(mitsub_long_code, 19); + ASSERT_EQ( + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m440s17100" + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s1300m450s420m450s420m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s1300m450s1300m450s1300m450s1300m450s1300m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m440s17100", + irsend.outputStr()); +} + +// Tests for IRMitsubishiAC class. + +TEST(TestMitsubishiACClass, Power) { + IRMitsubishiAC mitsub(0); + mitsub.begin(); + + mitsub.on(); + EXPECT_TRUE(mitsub.getPower()); + + mitsub.off(); + EXPECT_FALSE(mitsub.getPower()); + + mitsub.setPower(true); + EXPECT_TRUE(mitsub.getPower()); + + mitsub.setPower(false); + EXPECT_FALSE(mitsub.getPower()); +} + +TEST(TestMitsubishiACClass, Temperature) { + IRMitsubishiAC mitsub(0); + mitsub.begin(); + + mitsub.setTemp(0); + EXPECT_EQ(kMitsubishiAcMinTemp, mitsub.getTemp()); + + mitsub.setTemp(255); + EXPECT_EQ(kMitsubishiAcMaxTemp, mitsub.getTemp()); + + mitsub.setTemp(kMitsubishiAcMinTemp); + EXPECT_EQ(kMitsubishiAcMinTemp, mitsub.getTemp()); + + mitsub.setTemp(kMitsubishiAcMaxTemp); + EXPECT_EQ(kMitsubishiAcMaxTemp, mitsub.getTemp()); + + mitsub.setTemp(kMitsubishiAcMinTemp - 1); + EXPECT_EQ(kMitsubishiAcMinTemp, mitsub.getTemp()); + + mitsub.setTemp(kMitsubishiAcMaxTemp + 1); + EXPECT_EQ(kMitsubishiAcMaxTemp, mitsub.getTemp()); + + mitsub.setTemp(17); + EXPECT_EQ(17, mitsub.getTemp()); + + mitsub.setTemp(21); + EXPECT_EQ(21, mitsub.getTemp()); + + mitsub.setTemp(25); + EXPECT_EQ(25, mitsub.getTemp()); + + mitsub.setTemp(30); + EXPECT_EQ(30, mitsub.getTemp()); +} + +TEST(TestMitsubishiACClass, OperatingMode) { + IRMitsubishiAC mitsub(0); + mitsub.begin(); + + mitsub.setMode(kMitsubishiAcAuto); + EXPECT_EQ(kMitsubishiAcAuto, mitsub.getMode()); + + mitsub.setMode(kMitsubishiAcCool); + EXPECT_EQ(kMitsubishiAcCool, mitsub.getMode()); + + mitsub.setMode(kMitsubishiAcHeat); + EXPECT_EQ(kMitsubishiAcHeat, mitsub.getMode()); + + mitsub.setMode(kMitsubishiAcDry); + EXPECT_EQ(kMitsubishiAcDry, mitsub.getMode()); + + mitsub.setMode(kMitsubishiAcAuto + 1); + EXPECT_EQ(kMitsubishiAcAuto, mitsub.getMode()); + + mitsub.setMode(255); + EXPECT_EQ(kMitsubishiAcAuto, mitsub.getMode()); +} + +TEST(TestMitsubishiACClass, VaneMode) { + IRMitsubishiAC mitsub(0); + mitsub.begin(); + + mitsub.setVane(kMitsubishiAcVaneAuto); + EXPECT_EQ(kMitsubishiAcVaneAuto, mitsub.getVane()); + + mitsub.setVane(kMitsubishiAcVaneAuto + 1); + EXPECT_EQ(kMitsubishiAcVaneAuto + 1, mitsub.getVane()); + + mitsub.setVane(kMitsubishiAcVaneAutoMove); + EXPECT_EQ(kMitsubishiAcVaneAutoMove, mitsub.getVane()); + + mitsub.setVane(kMitsubishiAcVaneAutoMove + 1); + EXPECT_EQ(kMitsubishiAcVaneAutoMove, mitsub.getVane()); + + mitsub.setVane(kMitsubishiAcVaneAutoMove - 1); + EXPECT_EQ(kMitsubishiAcVaneAutoMove - 1, mitsub.getVane()); +} + +TEST(TestMitsubishiACClass, FanSpeed) { + IRMitsubishiAC mitsub(0); + mitsub.begin(); + + mitsub.setFan(kMitsubishiAcFanAuto); + EXPECT_EQ(kMitsubishiAcFanAuto, mitsub.getFan()); + + mitsub.setFan(255); + EXPECT_EQ(kMitsubishiAcFanRealMax, mitsub.getFan()); + + mitsub.setFan(kMitsubishiAcFanMax); + EXPECT_EQ(kMitsubishiAcFanRealMax, mitsub.getFan()); + + mitsub.setFan(kMitsubishiAcFanMax - 1); + EXPECT_EQ(kMitsubishiAcFanMax - 1, mitsub.getFan()); + + mitsub.setFan(1); + EXPECT_EQ(1, mitsub.getFan()); + + mitsub.setFan(2); + EXPECT_EQ(2, mitsub.getFan()); + + mitsub.setFan(3); + EXPECT_EQ(3, mitsub.getFan()); + + mitsub.setFan(4); + EXPECT_EQ(4, mitsub.getFan()); + + mitsub.setFan(kMitsubishiAcFanSilent); + EXPECT_EQ(kMitsubishiAcFanSilent, mitsub.getFan()); + + mitsub.setFan(kMitsubishiAcFanSilent + 1); + EXPECT_EQ(kMitsubishiAcFanRealMax, mitsub.getFan()); +} + +TEST(TestMitsubishiACClass, MessageConstuction) { + IRMitsubishiAC mitsub(0); + IRsendTest irsend(4); + mitsub.begin(); + irsend.begin(); + + mitsub.setFan(1); + mitsub.setMode(kMitsubishiAcCool); + mitsub.setTemp(27); + mitsub.setVane(3); + mitsub.on(); + + // Check everything for kicks. + EXPECT_EQ(1, mitsub.getFan()); + EXPECT_EQ(kMitsubishiAcCool, mitsub.getMode()); + EXPECT_EQ(27, mitsub.getTemp()); + EXPECT_EQ(3, mitsub.getVane()); + EXPECT_TRUE(mitsub.getPower()); + + irsend.reset(); + irsend.sendMitsubishiAC(mitsub.getRaw()); + EXPECT_EQ( + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s1300m450s1300m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s420" + "m440s17100" + "m3400s1750" + "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" + "m450s420m450s1300m450s1300m450s420m450s420m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s1300m450s420m450s420" + "m450s420m450s420m450s420m450s1300m450s1300m450s420m450s420m450s420" + "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s420m450s1300m450s1300m450s420m450s420" + "m450s1300m450s420m450s420m450s1300m450s1300m450s420m450s1300m450s420" + "m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s1300m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s420m450s420m450s420m450s420m450s420m450s420m450s420" + "m450s420m450s1300m450s1300m450s1300m450s420m450s420m450s1300m450s420" + "m440s17100", + irsend.outputStr()); +} + +// Tests for decodeMitsubishiAC() with real captured example. +TEST(TestDecodeMitsubishiAC, DecodeRealExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi AC "Power On, 16C, low fan, vane auto move". + uint16_t rawData[583] = { + 3476, 1708, 416, 1264, 420, 1260, 414, 400, 448, 390, 446, 392, + 444, 1236, 440, 400, 446, 392, 446, 1234, 440, 1266, 418, 396, + 442, 1264, 420, 394, 444, 394, 442, 1264, 422, 1260, 414, 398, + 440, 1266, 418, 1264, 420, 392, 446, 392, 444, 1264, 422, 392, + 446, 392, 446, 1260, 414, 400, 448, 390, 446, 392, 444, 394, + 442, 396, 442, 398, 440, 424, 412, 400, 448, 390, 446, 392, + 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, + 448, 390, 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, + 440, 400, 438, 400, 448, 390, 446, 392, 444, 1236, 440, 1266, + 418, 394, 442, 396, 440, 398, 438, 402, 446, 1232, 444, 396, + 440, 1268, 418, 394, 442, 396, 440, 398, 440, 400, 448, 390, + 448, 1232, 442, 1266, 420, 394, 444, 1264, 422, 1260, 416, 396, + 440, 398, 450, 1230, 444, 396, 442, 398, 440, 1266, 418, 1264, + 422, 1258, 416, 1266, 418, 394, 442, 396, 440, 398, 440, 398, + 438, 400, 446, 392, 446, 392, 446, 392, 444, 396, 442, 396, + 440, 398, 438, 398, 438, 400, 448, 392, 446, 392, 444, 394, + 444, 396, 442, 396, 440, 398, 438, 400, 448, 390, 448, 392, + 444, 394, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, + 448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, + 440, 398, 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, + 442, 396, 440, 398, 440, 398, 438, 400, 448, 390, 446, 392, + 444, 394, 444, 394, 442, 396, 440, 398, 438, 400, 438, 400, + 448, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, + 438, 1240, 444, 1264, 422, 390, 446, 392, 446, 1260, 414, 1268, + 418, 1264, 422, 12984, 3478, 1708, 418, 1264, 422, 1234, 442, 398, + 448, 390, 446, 392, 446, 1234, 440, 400, 448, 390, 446, 1234, + 442, 1266, 420, 392, 444, 1264, 420, 392, 446, 394, 444, 1236, + 448, 1260, 416, 398, 440, 1266, 418, 1262, 422, 390, 446, 392, + 444, 1234, 440, 400, 448, 392, 446, 1234, 440, 398, 450, 390, + 446, 392, 444, 394, 444, 394, 442, 396, 442, 398, 440, 400, + 438, 400, 448, 390, 446, 392, 444, 394, 442, 396, 442, 396, + 440, 398, 438, 400, 448, 390, 446, 392, 446, 392, 444, 394, + 442, 396, 442, 396, 440, 398, 438, 400, 448, 416, 420, 392, + 444, 1234, 440, 1240, 446, 394, 442, 396, 440, 398, 438, 400, + 448, 1232, 444, 396, 440, 1240, 446, 394, 442, 396, 440, 398, + 440, 400, 448, 390, 446, 1232, 444, 1238, 446, 394, 444, 1236, + 448, 1232, 442, 396, 440, 398, 448, 1232, 444, 396, 440, 398, + 438, 1242, 444, 1238, 448, 1234, 442, 1240, 444, 394, 442, 396, + 440, 398, 438, 400, 448, 390, 446, 394, 444, 420, 416, 394, + 444, 396, 440, 398, 440, 398, 438, 400, 448, 418, 420, 418, + 418, 394, 442, 396, 442, 396, 440, 424, 412, 400, 448, 390, + 446, 392, 446, 420, 418, 420, 416, 396, 440, 398, 440, 424, + 412, 426, 420, 418, 420, 392, 444, 394, 444, 422, 416, 422, + 414, 398, 440, 426, 422, 388, 448, 416, 420, 418, 418, 422, + 416, 422, 414, 424, 414, 398, 438, 426, 422, 418, 420, 390, + 446, 418, 418, 420, 416, 396, 440, 424, 412, 426, 412, 400, + 446, 418, 420, 420, 418, 420, 416, 422, 414, 422, 414, 424, + 412, 426, 422, 390, 446, 1232, 442, 1240, 446, 394, 444, 394, + 442, 1238, 446, 1234, 440, 1240, 444}; // UNKNOWN F6FDB82B + + irsend.sendRaw(rawData, 583, 33); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI_AC, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiACBits, irsend.capture.bits); + uint8_t expected[kMitsubishiACStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x00, 0x18, 0x0A, 0x36, + 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6}; + EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishiACBits); +} + +// Tests for decodeMitsubishiAC() when the first payload has an error. +TEST(TestDecodeMitsubishiAC, DecodeRealExampleRepeatNeeded) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi AC "Power On, 16C, low fan, vane auto move". + uint16_t rawData[583] = { + 3476, 1708, 416, 1264, 420, 1260, 414, 400, 448, 390, 446, 392, 444, 1236, + 440, 400, 446, 392, 446, 1234, 440, 1266, 418, 396, 442, 1264, 420, 394, + 444, 394, 442, 1264, 422, 1260, 414, 398, 440, 1266, 418, 1264, 420, 392, + 446, 392, 444, 1264, 422, 392, 446, 392, 446, 1260, 414, 400, 448, 390, + 446, 392, 444, 394, 442, 396, 442, 398, 440, 424, 412, 400, 448, 390, 446, + 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, 448, 390, + 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 440, 400, 438, 400, 448, + 390, 446, 392, 444, 1236, 440, 1266, 418, 394, 442, 396, 440, 398, 438, + 402, 446, 1232, 444, 396, 440, 1268, 418, 394, 442, 396, 440, 398, + // space 699 is not recognizable: + 440, 400, 448, 390, 448, 1232, 442, 1266, 420, 394, 444, 1264, 699, 1260, + 416, 396, 440, 398, 450, 1230, 444, 396, 442, 398, 440, 1266, 418, 1264, + 422, 1258, 416, 1266, 418, 394, 442, 396, 440, 398, 440, 398, 438, 400, + 446, 392, 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 438, 398, 438, + 400, 448, 392, 446, 392, 444, 394, 444, 396, 442, 396, 440, 398, 438, 400, + 448, 390, 448, 392, 444, 394, 444, 394, 442, 396, 442, 396, 440, 398, 438, + 400, 448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, + 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, 440, + 398, 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, + 438, 400, 438, 400, 448, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, + 398, 438, 1240, 444, 1264, 422, 390, 446, 392, 446, 1260, 414, 1268, 418, + 1264, 422, 12984, 3478, 1708, 418, 1264, 422, 1234, 442, 398, 448, 390, + 446, 392, 446, 1234, 440, 400, 448, 390, 446, 1234, 442, 1266, 420, 392, + 444, 1264, 420, 392, 446, 394, 444, 1236, 448, 1260, 416, 398, 440, 1266, + 418, 1262, 422, 390, 446, 392, 444, 1234, 440, 400, 448, 392, 446, 1234, + 440, 398, 450, 390, 446, 392, 444, 394, 444, 394, 442, 396, 442, 398, 440, + 400, 438, 400, 448, 390, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, + 438, 400, 448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, + 398, 438, 400, 448, 416, 420, 392, 444, 1234, 440, 1240, 446, 394, 442, + 396, 440, 398, 438, 400, 448, 1232, 444, 396, 440, 1240, 446, 394, 442, + 396, 440, 398, 440, 400, 448, 390, 446, 1232, 444, 1238, 446, 394, 444, + 1236, 448, 1232, 442, 396, 440, 398, 448, 1232, 444, 396, 440, 398, 438, + 1242, 444, 1238, 448, 1234, 442, 1240, 444, 394, 442, 396, 440, 398, 438, + 400, 448, 390, 446, 394, 444, 420, 416, 394, 444, 396, 440, 398, 440, 398, + 438, 400, 448, 418, 420, 418, 418, 394, 442, 396, 442, 396, 440, 424, 412, + 400, 448, 390, 446, 392, 446, 420, 418, 420, 416, 396, 440, 398, 440, 424, + 412, 426, 420, 418, 420, 392, 444, 394, 444, 422, 416, 422, 414, 398, 440, + 426, 422, 388, 448, 416, 420, 418, 418, 422, 416, 422, 414, 424, 414, 398, + 438, 426, 422, 418, 420, 390, 446, 418, 418, 420, 416, 396, 440, 424, 412, + 426, 412, 400, 446, 418, 420, 420, 418, 420, 416, 422, 414, 422, 414, 424, + 412, 426, 422, 390, 446, 1232, 442, 1240, 446, 394, 444, 394, 442, 1238, + 446, 1234, 440, 1240, 444}; // UNKNOWN F6FDB82B + + irsend.sendRaw(rawData, 583, 33); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI_AC, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiACBits, irsend.capture.bits); + uint8_t expected[kMitsubishiACStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x00, 0x18, 0x0A, 0x36, + 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6}; + EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishiACBits); +} + +// Tests for decodeMitsubishiAC() when the repeat mark is wrong. +TEST(TestDecodeMitsubishiAC, DecodeRealExampleRepeatMarkError) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi AC "Power On, 16C, low fan, vane auto move". + uint16_t rawData[583] = { + 3476, 1708, 416, 1264, 420, 1260, 414, 400, 448, 390, 446, 392, 444, 1236, + 440, 400, 446, 392, 446, 1234, 440, 1266, 418, 396, 442, 1264, 420, 394, + 444, 394, 442, 1264, 422, 1260, 414, 398, 440, 1266, 418, 1264, 420, 392, + 446, 392, 444, 1264, 422, 392, 446, 392, 446, 1260, 414, 400, 448, 390, + 446, 392, 444, 394, 442, 396, 442, 398, 440, 424, 412, 400, 448, 390, 446, + 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, 448, 390, + 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 440, 400, 438, 400, 448, + 390, 446, 392, 444, 1236, 440, 1266, 418, 394, 442, 396, 440, 398, 438, + 402, 446, 1232, 444, 396, 440, 1268, 418, 394, 442, 396, 440, 398, 440, + 400, 448, 390, 448, 1232, 442, 1266, 420, 394, 444, 1264, 422, 1260, 416, + 396, 440, 398, 450, 1230, 444, 396, 442, 398, 440, 1266, 418, 1264, 422, + 1258, 416, 1266, 418, 394, 442, 396, 440, 398, 440, 398, 438, 400, 446, + 392, 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 438, 398, 438, 400, + 448, 392, 446, 392, 444, 394, 444, 396, 442, 396, 440, 398, 438, 400, 448, + 390, 448, 392, 444, 394, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, + 448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438, + 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, 440, 398, + 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, 438, + 400, 438, 400, 448, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, + 438, 1240, 444, 1264, 422, 390, 446, 392, 446, + // Repeat mark (1111) wrong: + 1260, 414, 1268, 418, 1264, 422, 1111, 347, 1708, 418, 1264, 422, 1234, + 442, 398, 448, 390, 446, 392, 446, 1234, 440, 400, 448, 390, 446, 1234, + 442, 1266, 420, 392, 444, 1264, 420, 392, 446, 394, 444, 1236, 448, 1260, + 416, 398, 440, 1266, 418, 1262, 422, 390, 446, 392, 444, 1234, 440, 400, + 448, 392, 446, 1234, 440, 398, 450, 390, 446, 392, 444, 394, 444, 394, + 442, 396, 442, 398, 440, 400, 438, 400, 448, 390, 446, 392, 444, 394, 442, + 396, 442, 396, 440, 398, 438, 400, 448, 390, 446, 392, 446, 392, 444, 394, + 442, 396, 442, 396, 440, 398, 438, 400, 448, 416, 420, 392, 444, 1234, + 440, 1240, 446, 394, 442, 396, 440, 398, 438, 400, 448, 1232, 444, 396, + 440, 1240, 446, 394, 442, 396, 440, 398, 440, 400, 448, 390, 446, 1232, + 444, 1238, 446, 394, 444, 1236, 448, 1232, 442, 396, 440, 398, 448, 1232, + 444, 396, 440, 398, 438, 1242, 444, 1238, 448, 1234, 442, 1240, 444, 394, + 442, 396, 440, 398, 438, 400, 448, 390, 446, 394, 444, 420, 416, 394, 444, + 396, 440, 398, 440, 398, 438, 400, 448, 418, 420, 418, 418, 394, 442, 396, + 442, 396, 440, 424, 412, 400, 448, 390, 446, 392, 446, 420, 418, 420, 416, + 396, 440, 398, 440, 424, 412, 426, 420, 418, 420, 392, 444, 394, 444, 422, + 416, 422, 414, 398, 440, 426, 422, 388, 448, 416, 420, 418, 418, 422, 416, + 422, 414, 424, 414, 398, 438, 426, 422, 418, 420, 390, 446, 418, 418, 420, + 416, 396, 440, 424, 412, 426, 412, 400, 446, 418, 420, 420, 418, 420, 416, + 422, 414, 422, 414, 424, 412, 426, 422, 390, 446, 1232, 442, 1240, 446, + 394, 444, 394, 442, 1238, 446, 1234, 440, 1240, 444}; // UNKNOWN F6FDB82B + + irsend.sendRaw(rawData, 583, 33); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI_AC, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiACBits, irsend.capture.bits); + uint8_t expected[kMitsubishiACStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x00, 0x18, 0x0A, 0x36, + 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6}; + EXPECT_STATE_EQ(expected, irsend.capture.state, kMitsubishiACBits); +} + +// Tests for decodeMitsubishiAC() when first payload has an error and the +// repeat mark is wrong. +TEST(TestDecodeMitsubishiAC, DecodeRealExampleRepeatNeededButError) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi AC "Power On, 16C, low fan, vane auto move". + uint16_t rawData[583] = { + 3476, 1708, 416, 1264, 420, 1260, 414, 400, 448, 390, 446, 392, 444, 1236, + 440, 400, 446, 392, 446, 1234, 440, 1266, 418, 396, 442, 1264, 420, 394, + 444, 394, 442, 1264, 422, 1260, 414, 398, 440, 1266, 418, 1264, 420, 392, + 446, 392, 444, 1264, 422, 392, 446, 392, 446, 1260, 414, 400, 448, 390, + 446, 392, 444, 394, 442, 396, 442, 398, 440, 424, 412, 400, 448, 390, 446, + 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, 438, 400, 448, 390, + 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 440, 400, 438, 400, 448, + 390, 446, 392, 444, 1236, 440, 1266, 418, 394, 442, 396, 440, 398, 438, + 402, 446, 1232, 444, 396, 440, 1268, 418, 394, 442, 396, 440, 398, + // space 699 is not recognizable: + 440, 400, 448, 390, 448, 1232, 442, 1266, 420, 394, 444, 1264, 699, 1260, + 416, 396, 440, 398, 450, 1230, 444, 396, 442, 398, 440, 1266, 418, 1264, + 422, 1258, 416, 1266, 418, 394, 442, 396, 440, 398, 440, 398, 438, 400, + 446, 392, 446, 392, 446, 392, 444, 396, 442, 396, 440, 398, 438, 398, 438, + 400, 448, 392, 446, 392, 444, 394, 444, 396, 442, 396, 440, 398, 438, 400, + 448, 390, 448, 392, 444, 394, 444, 394, 442, 396, 442, 396, 440, 398, 438, + 400, 448, 390, 446, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, 398, + 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, 440, + 398, 438, 400, 448, 390, 446, 392, 444, 394, 444, 394, 442, 396, 440, 398, + 438, 400, 438, 400, 448, 392, 446, 392, 444, 394, 442, 396, 442, 396, 440, + 398, 438, 1240, 444, 1264, 422, 390, 446, 392, 446, + // 1111 is not a valid repeat mark: + 1260, 414, 1268, 418, 1264, 422, 1111, 3478, 1708, 418, 1264, 422, 1234, + 442, 398, 448, 390, 446, 392, 446, 1234, 440, 400, 448, 390, 446, 1234, + 442, 1266, 420, 392, 444, 1264, 420, 392, 446, 394, 444, 1236, 448, 1260, + 416, 398, 440, 1266, 418, 1262, 422, 390, 446, 392, 444, 1234, 440, 400, + 448, 392, 446, 1234, 440, 398, 450, 390, 446, 392, 444, 394, 444, 394, + 442, 396, 442, 398, 440, 400, 438, 400, 448, 390, 446, 392, 444, 394, 442, + 396, 442, 396, 440, 398, 438, 400, 448, 390, 446, 392, 446, 392, 444, 394, + 442, 396, 442, 396, 440, 398, 438, 400, 448, 416, 420, 392, 444, 1234, + 440, 1240, 446, 394, 442, 396, 440, 398, 438, 400, 448, 1232, 444, 396, + 440, 1240, 446, 394, 442, 396, 440, 398, 440, 400, 448, 390, 446, 1232, + 444, 1238, 446, 394, 444, 1236, 448, 1232, 442, 396, 440, 398, 448, 1232, + 444, 396, 440, 398, 438, 1242, 444, 1238, 448, 1234, 442, 1240, 444, 394, + 442, 396, 440, 398, 438, 400, 448, 390, 446, 394, 444, 420, 416, 394, 444, + 396, 440, 398, 440, 398, 438, 400, 448, 418, 420, 418, 418, 394, 442, 396, + 442, 396, 440, 424, 412, 400, 448, 390, 446, 392, 446, 420, 418, 420, 416, + 396, 440, 398, 440, 424, 412, 426, 420, 418, 420, 392, 444, 394, 444, 422, + 416, 422, 414, 398, 440, 426, 422, 388, 448, 416, 420, 418, 418, 422, 416, + 422, 414, 424, 414, 398, 438, 426, 422, 418, 420, 390, 446, 418, 418, 420, + 416, 396, 440, 424, 412, 426, 412, 400, 446, 418, 420, 420, 418, 420, 416, + 422, 414, 422, 414, 424, 412, 426, 422, 390, 446, 1232, 442, 1240, 446, + 394, 444, 394, 442, 1238, 446, 1234, 440, 1240, 444}; // UNKNOWN F6FDB82B + + irsend.sendRaw(rawData, 583, 33); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(UNKNOWN, irsend.capture.decode_type); +} + +TEST(TestMitsubishiACClass, HumanReadable) { + IRMitsubishiAC irMitsu(0); + EXPECT_EQ( + "Power: On (HEAT), Temp: 22C, FAN: SILENT, VANE: AUTO, " + "Time: 17:10, On timer: 00:00, Off timer: 00:00, Timer: -", + irMitsu.toString()); +} + +// Test sending typical data only. +TEST(TestSendMitsubishi2, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMitsubishi2(0xF82); + EXPECT_EQ( + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" + "m560s4200" + "m560s1560m560s520m560s520m560s520m560s520m560s520m560s1560m560s520" + "m560s28500" + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" + "m560s4200" + "m560s1560m560s520m560s520m560s520m560s520m560s520m560s1560m560s520" + "m560s28500", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishi2(0x0); + EXPECT_EQ( + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s520m560s520m560s520m560s520" + "m560s4200" + "m560s520m560s520m560s520m560s520m560s520m560s520m560s520m560s520" + "m560s28500" + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s520m560s520m560s520m560s520" + "m560s4200" + "m560s520m560s520m560s520m560s520m560s520m560s520m560s520m560s520" + "m560s28500", + irsend.outputStr()); +} + +// Test sending odd repeats. +TEST(TestSendMitsubishi2, Repeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendMitsubishi2(0xF82, kMitsubishiBits, 0); + EXPECT_EQ( + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" + "m560s4200" + "m560s1560m560s520m560s520m560s520m560s520m560s520m560s1560m560s520" + "m560s28500", + irsend.outputStr()); + + irsend.reset(); + irsend.sendMitsubishi2(0xF82, kMitsubishiBits, 2); + EXPECT_EQ( + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" + "m560s4200" + "m560s1560m560s520m560s520m560s520m560s520m560s520m560s1560m560s520" + "m560s28500" + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" + "m560s4200" + "m560s1560m560s520m560s520m560s520m560s520m560s520m560s1560m560s520" + "m560s28500" + "m8400s4200" + "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" + "m560s4200" + "m560s1560m560s520m560s520m560s520m560s520m560s520m560s1560m560s520" + "m560s28500", + irsend.outputStr()); +} + +// Tests for decodeMitsubishi2(). + +// Decode synthetic examples. +TEST(TestDecodeMitsubishi2, DecodeSyntheticExamples) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi Projector "Power On" (16-bit). + irsend.sendMitsubishi2(0xF82); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI2, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xF82, irsend.capture.value); + EXPECT_EQ(0xF, irsend.capture.address); + EXPECT_EQ(0x82, irsend.capture.command); + + irsend.reset(); + irsend.sendMitsubishi2(0x0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI2, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendMitsubishi2(0x1234); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI2, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + EXPECT_EQ(0x12, irsend.capture.address); + EXPECT_EQ(0x34, irsend.capture.command); +} + +// Decode a 'real' example from Issue #441 +TEST(TestDecodeMitsubishi2, DecodeRealExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Mitsubishi Projector "Power On" (16-bit). + uint16_t rawData[75] = { + 8402, 4172, 554, 490, 562, 484, 560, 514, 532, 512, 534, + 1566, 526, 1572, 526, 1542, 560, 1568, 532, 4192, 534, 1564, + 532, 484, 560, 512, 532, 512, 532, 514, 530, 514, 526, + 1570, 524, 520, 526, 28506, 8454, 4170, 560, 514, 528, 516, + 526, 520, 524, 490, 556, 1572, 534, 1534, 560, 1568, 530, + 1538, 558, 4166, 560, 1538, 558, 490, 560, 512, 530, 514, + 532, 484, 558, 514, 532, 1566, 530, 486, 554}; // UNKNOWN 96A1512F + + irsend.sendRaw(rawData, 75, 33); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI2, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0xF82, irsend.capture.value); + EXPECT_EQ(0xF, irsend.capture.address); + EXPECT_EQ(0x82, irsend.capture.command); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_NEC_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_NEC_test.cpp similarity index 63% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_NEC_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_NEC_test.cpp index 781aa38d7..6b84b0ec9 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_NEC_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_NEC_test.cpp @@ -11,18 +11,21 @@ TEST(TestSendNEC, SendDataOnly) { IRsendTest irsend(4); irsend.begin(); irsend.sendNEC(0); - EXPECT_EQ("m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s108080", irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s58240", + irsend.outputStr()); irsend.sendNEC(0xAA00FF55); - EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s1680m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s560m560s1680m560s108080", - irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s560m560s1680m560s40320", + irsend.outputStr()); } // Test sending different bit lengths. @@ -30,22 +33,26 @@ TEST(TestSendNEC, SendSmallData) { IRsendTest irsend(4); irsend.begin(); irsend.sendNEC(0xA, 4); // Send only 4 data bits. - EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s108080", + EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s87360", irsend.outputStr()); irsend.sendNEC(0, 8); // Send only 8 data bits. - EXPECT_EQ("m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s108080", irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s85120", + irsend.outputStr()); irsend.sendNEC(0x1234567890ABCDEF, 64); // Send 64 data bits. - EXPECT_EQ("m8960s4480m560s560m560s560m560s560m560s1680m560s560m560s560" - "m560s1680m560s560m560s560m560s560m560s1680m560s1680m560s560" - "m560s1680m560s560m560s560m560s560m560s1680m560s560m560s1680" - "m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s1680" - "m560s1680m560s1680m560s560m560s560m560s560m560s1680m560s560" - "m560s560m560s1680m560s560m560s560m560s560m560s560m560s1680m560s560" - "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s1680" - "m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" - "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680" - "m560s1680m560s108080", irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s1680m560s560m560s560m560s560m560s1680m560s1680m560s560" + "m560s1680m560s560m560s560m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s1680" + "m560s1680m560s1680m560s560m560s560m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s560m560s560m560s560m560s1680m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s1680" + "m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680" + "m560s1680m560s22400", + irsend.outputStr()); } // Test sending with repeats. @@ -53,20 +60,24 @@ TEST(TestSendNEC, SendWithRepeats) { IRsendTest irsend(4); irsend.begin(); irsend.sendNEC(0, 8, 0); // Send a command with 0 repeats. - EXPECT_EQ("m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" - "m560s560m560s108080", irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s85120", + irsend.outputStr()); irsend.sendNEC(0xAA, 8, 1); // Send a command with 1 repeat. - EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s108080" - "m8960s2240m560s108080", - irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s80640" + "m8960s2240m560s96320", + irsend.outputStr()); irsend.sendNEC(0xAA, 8, 3); // Send a command with 3 repeats. - EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" - "m560s1680m560s560m560s108080" - "m8960s2240m560s108080" - "m8960s2240m560s108080" - "m8960s2240m560s108080", - irsend.outputStr()); + EXPECT_EQ( + "m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s80640" + "m8960s2240m560s96320" + "m8960s2240m560s96320" + "m8960s2240m560s96320", + irsend.outputStr()); } // Tests for encodeNEC(). @@ -101,7 +112,7 @@ TEST(TestDecodeNEC, NormalNECDecodeWithStrict) { irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x807F40BF, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x2, irsend.capture.command); @@ -112,7 +123,7 @@ TEST(TestDecodeNEC, NormalNECDecodeWithStrict) { irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0xC1A28877, irsend.capture.value); EXPECT_EQ(0x4583, irsend.capture.address); EXPECT_EQ(0x11, irsend.capture.command); @@ -129,7 +140,7 @@ TEST(TestDecodeNEC, NormalNECDecodeWithStrict) { irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x807F40BF, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x2, irsend.capture.command); @@ -146,7 +157,7 @@ TEST(TestDecodeNEC, NormalNECDecodeWithoutStrict) { irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, 32, false)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0, irsend.capture.value); EXPECT_EQ(0, irsend.capture.address); EXPECT_EQ(0, irsend.capture.command); @@ -156,7 +167,7 @@ TEST(TestDecodeNEC, NormalNECDecodeWithoutStrict) { irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, 32, false)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x12345678, irsend.capture.value); EXPECT_EQ(0x2C48, irsend.capture.address); EXPECT_EQ(0, irsend.capture.command); @@ -225,18 +236,18 @@ TEST(TestDecodeNEC, NoTrailingGap_Issue243) { irsend.begin(); irsend.reset(); - uint16_t rawData[67] = {9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, - 600, 1650, 650, 550, 600, 1650, 650, 1650, 650, 1650, - 600, 550, 650, 1650, 650, 1650, 650, 550, 600, 1650, - 650, 1650, 650, 550, 650, 550, 650, 1650, 650, 550, - 650, 550, 650, 550, 600, 550, 650, 550, 650, 550, - 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650, - 650, 1650, 650, 1650, 650, 1650, 600}; + uint16_t rawData[67] = { + 9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, 600, 1650, + 650, 550, 600, 1650, 650, 1650, 650, 1650, 600, 550, 650, 1650, + 650, 1650, 650, 550, 600, 1650, 650, 1650, 650, 550, 650, 550, + 650, 1650, 650, 550, 650, 550, 650, 550, 600, 550, 650, 550, + 650, 550, 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650, + 650, 1650, 650, 1650, 650, 1650, 600}; irsend.sendRaw(rawData, 67, 38); irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x4BB640BF, irsend.capture.value); EXPECT_EQ(0x6DD2, irsend.capture.address); EXPECT_EQ(0x2, irsend.capture.command); @@ -246,16 +257,16 @@ TEST(TestDecodeNEC, NoTrailingGap_Issue243) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x4BB640BF, irsend.capture.value); // Add a zero length space to the message to test how it handles that as - // a end of command gap. + // an end of command gap. irsend.addGap(0); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x4BB640BF, irsend.capture.value); } @@ -270,18 +281,18 @@ TEST(TestDecodeNEC, NonStrictNECDecode_Issue264) { irsend.reset(); // Slightly modified example than reported due to poor timings that are too // far out of spec. - uint16_t rawData[67] = {9150, 4650, 550, 600, 550, 1800, 600, 1750, 600, 1800, - 550, 600, 550, 1800, 550, 1750, 600, 1750, 600, 1750, - 600, 1750, 600, 1700, 600, 600, 600, 600, 550, 600, - 600, 600, 600, 1750, 600, 1750, 600, 600, 550, 1800, - 600, 600, 600, 600, 600, 600, 500, 600, 600, 600, - 600, 600, 600, 1750, 600, 600, 600, 550, 600, 600, - 600, 600, 600, 600, 600, 550, 600}; + uint16_t rawData[67] = { + 9150, 4650, 550, 600, 550, 1800, 600, 1750, 600, 1800, 550, 600, + 550, 1800, 550, 1750, 600, 1750, 600, 1750, 600, 1750, 600, 1700, + 600, 600, 600, 600, 550, 600, 600, 600, 600, 1750, 600, 1750, + 600, 600, 550, 1800, 600, 600, 600, 600, 600, 600, 500, 600, + 600, 600, 600, 600, 600, 1750, 600, 600, 600, 550, 600, 600, + 600, 600, 600, 600, 600, 550, 600}; irsend.sendRaw(rawData, 67, 38); irsend.makeDecodeResult(); EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture)); // Not strictly NEC - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, NEC_BITS, false)); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, kNECBits, false)); EXPECT_EQ(0x77E1A040, irsend.capture.value); // Do it all again, but with a normal decode. @@ -290,7 +301,7 @@ TEST(TestDecodeNEC, NonStrictNECDecode_Issue264) { irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(NEC_LIKE, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x77E1A040, irsend.capture.value); } @@ -303,18 +314,18 @@ TEST(TestDecodeNEC, AutoReceiveCalibration) { // Data from Issue #264, for a remote that is slightly off spec. // Should be matched as a NEC-like message however without self-calibrating // the timings of the short spaces is out. - uint16_t rawData[67] = {9150, 4600, 650, 600, 650, 1650, 650, 1700, 650, 1750, - 650, 600, 650, 1700, 650, 1750, 650, 1750, 650, 1700, - 650, 1700, 650, 1700, 650, 600, 650, 600, 650, 600, - 600, 600, 650, 1750, 650, 1750, 650, 600, 650, 1700, - 600, 600, 700, 550, 650, 550, 650, 600, 650, 600, - 650, 600, 650, 1750, 600, 600, 650, 600, 650, 550, - 650, 600, 650, 600, 650, 600, 600}; + uint16_t rawData[67] = { + 9150, 4600, 650, 600, 650, 1650, 650, 1700, 650, 1750, 650, 600, + 650, 1700, 650, 1750, 650, 1750, 650, 1700, 650, 1700, 650, 1700, + 650, 600, 650, 600, 650, 600, 600, 600, 650, 1750, 650, 1750, + 650, 600, 650, 1700, 600, 600, 700, 550, 650, 550, 650, 600, + 650, 600, 650, 600, 650, 1750, 600, 600, 650, 600, 650, 550, + 650, 600, 650, 600, 650, 600, 600}; irsend.sendRaw(rawData, 67, 38); irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, NEC_BITS, false)); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, kNECBits, false)); EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x77E1A040, irsend.capture.value); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Nikai_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Nikai_test.cpp new file mode 100644 index 000000000..4a4ea05bb --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Nikai_test.cpp @@ -0,0 +1,212 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendNikai(). +// Test sending typical data only. +TEST(TestSendNikai, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendNikai(0xD5F2A); // Nikai TV Power Off. + EXPECT_EQ( + "m4000s4000" + "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" + "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" + "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" + "m500s2000m500s1000m500s2000m500s8500", + irsend.outputStr()); + + irsend.reset(); +} + +// Test sending with different repeats. +TEST(TestSendNikai, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendNikai(0xD5F2A, kNikaiBits, 1); // 1 repeat. + EXPECT_EQ( + "m4000s4000" + "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" + "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" + "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" + "m500s2000m500s1000m500s2000m500s8500" + "m4000s4000" + "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" + "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" + "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" + "m500s2000m500s1000m500s2000m500s8500", + irsend.outputStr()); + irsend.sendNikai(0xD5F2A, kNikaiBits, 2); // 2 repeat. + EXPECT_EQ( + "m4000s4000" + "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" + "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" + "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" + "m500s2000m500s1000m500s2000m500s8500" + "m4000s4000" + "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" + "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" + "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" + "m500s2000m500s1000m500s2000m500s8500" + "m4000s4000" + "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" + "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" + "m500s1000m500s1000m500s2000m500s2000m500s1000m500s2000m500s1000" + "m500s2000m500s1000m500s2000m500s8500", + irsend.outputStr()); +} + +// Tests for decodeNikai(). + +// Decode normal Nikai messages. +TEST(TestDecodeNikai, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Nikai 24-bit message. + irsend.reset(); + irsend.sendNikai(0x123456); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ(0x123456, irsend.capture.value); + + irsend.reset(); + irsend.sendNikai(0x101); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ(0x101, irsend.capture.value); +} + +// Decode normal repeated Nikai messages. +TEST(TestDecodeNikai, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Nikai 24-bit message. + irsend.reset(); + irsend.sendNikai(0xD5F2A, kNikaiBits, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ(0xD5F2A, irsend.capture.value); +} + +TEST(TestDecodeNikai, NormalDecodeWithNonStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Illegal under length (16-bit) message + irsend.reset(); + irsend.sendNikai(0x0, 16); + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + // And it should fail when we expect more bits. + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, false)); + + // Should pass if strict off if we ask for correct nr. of bits sent. + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, 16, false)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(16, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + + // Should fail as we are expecting less bits than there are. + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, 12, false)); +} + +// Decode (non-standard) 64-bit messages. +// Decode unsupported Nikai messages. +TEST(TestDecodeNikai, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal size Nikai 64-bit message. + irsend.sendNikai(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, 64, false)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); +} + +// Decode real example via Issue #309 +TEST(TestDecodeNikai, DecodeExamples) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Nikai TV Power Off from Issue #309 + uint16_t rawdata_off[100] = { + 4060, 3918, 508, 2004, 508, 2002, 510, 2002, 508, 2004, 506, + 1050, 508, 1048, 510, 2004, 508, 1048, 508, 2002, 510, 1050, + 508, 2004, 510, 1048, 508, 1050, 508, 1048, 508, 1050, 508, + 1050, 508, 2004, 508, 2002, 510, 1048, 508, 2004, 508, 1050, + 506, 2004, 508, 1048, 510, 2002, 456, 8446, 3956, 3998, 508, + 2004, 508, 2002, 508, 2004, 508, 1978, 532, 1050, 508, 1050, + 508, 2002, 508, 1050, 508, 2004, 508, 1050, 508, 2002, 510, + 1050, 508, 1050, 508, 1048, 508, 1050, 508, 1050, 508, 2002, + 510, 2002, 508, 1050, 508, 2002, 510, 1050, 508, 2002, 508}; + irsend.sendRaw(rawdata_off, 100, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ(0xD5F2A, irsend.capture.value); + + // Nikai TV Volume Up from Issue #309 + uint16_t rawdata_volup[52] = { + 3972, 4002, 504, 1982, 526, 2010, 502, 2010, 502, 2010, 500, + 1056, 502, 1056, 502, 2010, 500, 1056, 502, 2010, 502, 2010, + 500, 2010, 502, 2010, 502, 1056, 502, 1056, 502, 1056, 500, + 1056, 502, 2010, 502, 2010, 500, 1056, 502, 2008, 502, 1054, + 504, 1054, 504, 1054, 500, 1056, 450}; + + irsend.reset(); + irsend.sendRaw(rawdata_volup, 52, 38); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ(0xD0F2F, irsend.capture.value); +} + +// Fail to decode a non-Nikai example via GlobalCache +TEST(TestDecodeNikai, FailToDecodeNonNikaiExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + uint16_t gc_test[71] = {38000, 1, 1, 172, 172, 22, 64, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 21, 22, 11, 22, 21, 22, 128, 22, + 64, 22, 64, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 64, 22, 21, 22, 21, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 64, 22, 21, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 64, 22, 64, 22, 21, 22, 1820}; + irsend.sendGC(gc_test, 71); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, false)); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Panasonic_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Panasonic_test.cpp new file mode 100644 index 000000000..a1d8a7979 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Panasonic_test.cpp @@ -0,0 +1,1135 @@ +// Copyright 2017, 2018 David Conran + +#include "ir_Panasonic.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "IRutils.h" +#include "gtest/gtest.h" + +// Tests for encodePanasonic(). + +TEST(TestEncodePanasonic, General) { + IRsendTest irsend(4); + EXPECT_EQ(0x0, irsend.encodePanasonic(0, 0, 0, 0)); + EXPECT_EQ(0x101010101, irsend.encodePanasonic(1, 1, 1, 1)); + EXPECT_EQ(0xFFFF, irsend.encodePanasonic(0, 0, 0, 0xFF)); + EXPECT_EQ(0xFF00FF, irsend.encodePanasonic(0, 0, 0xFF, 0)); + EXPECT_EQ(0xFF0000FF, irsend.encodePanasonic(0, 0xFF, 0, 0)); + EXPECT_EQ(0xFFFF00000000, irsend.encodePanasonic(0xFFFF, 0, 0, 0)); + EXPECT_EQ(0xFFFFFFFFFFFF, irsend.encodePanasonic(0xFFFF, 0xFF, 0xFF, 0xFF)); + EXPECT_EQ(0x40040190ED7C, irsend.encodePanasonic(0x4004, 0x01, 0x90, 0xED)); +} + +// Tests for sendPanasonic64(). + +// Test sending typical data only. +TEST(TestSendPanasonic64, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendPanasonic64(0x0); + EXPECT_EQ( + "m3456s1728" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s116208", + irsend.outputStr()); + + irsend.reset(); + irsend.sendPanasonic64(0x40040190ED7C); + EXPECT_EQ( + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384", + irsend.outputStr()); + + irsend.reset(); + irsend.sendPanasonic64(0xFFFFFFFFFFFF); + EXPECT_EQ( + "m3456s1728" + "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" + "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" + "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" + "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" + "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" + "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" + "m432s74736", + irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendPanasonic64, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 0); // 0 repeats. + EXPECT_EQ( + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384", + irsend.outputStr()); + + irsend.reset(); + irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 1); // 1 repeat. + EXPECT_EQ( + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384" + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384", + irsend.outputStr()); + + irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 2); // 2 repeats. + EXPECT_EQ( + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384" + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384" + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" + "m432s102384", + irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendPanasonic64, SendUnusualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendPanasonic64(0x0, 8); + EXPECT_EQ( + "m3456s1728" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s150768", + irsend.outputStr()); + + irsend.reset(); + irsend.sendPanasonic64(0x1234567890ABCDEF, 64); + EXPECT_EQ( + "m3456s1728" + "m432s432m432s432m432s432m432s1296m432s432m432s432m432s1296m432s432" + "m432s432m432s432m432s1296m432s1296m432s432m432s1296m432s432m432s432" + "m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296m432s432" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s432m432s432m432s432" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296" + "m432s1296m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s1296" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s1296m432s1296" + "m432s74736", + irsend.outputStr()); +} + +// Tests for sendPanasonic(). + +TEST(TestSendPanasonic, CompareToSendPanasonic64) { + IRsendTest panasonic(4); + IRsendTest panasonic64(0); + + panasonic.begin(); + panasonic64.begin(); + + panasonic.reset(); + panasonic64.reset(); + + panasonic.sendPanasonic(0x4004, 0x0190ED7C); + panasonic64.sendPanasonic64(0x40040190ED7C); + EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); + + panasonic.sendPanasonic(0x0, 0x0); + panasonic64.sendPanasonic64(0x0); + EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); + + panasonic.sendPanasonic(0x0, 0x0, 8); + panasonic64.sendPanasonic64(0x0, 8); + EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); + + panasonic.sendPanasonic(0x1234, 0x567890AB, 64); + panasonic64.sendPanasonic64(0x1234567890AB, 64); + EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); + + panasonic.sendPanasonic(0x1234, 0x567890AB, kPanasonicBits, 2); + panasonic64.sendPanasonic64(0x1234567890AB, kPanasonicBits, 2); + EXPECT_EQ(panasonic64.outputStr(), panasonic.outputStr()); +} + +// Tests for decodePanasonic(). + +// Decode normal Panasonic messages. +TEST(TestDecodePanasonic, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Panasonic 48-bit message. + irsend.reset(); + irsend.sendPanasonic64(0x40040190ED7C); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x0190ED7C, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Synthesised Normal Panasonic 48-bit message. + irsend.reset(); + irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 0x12, 0x34, 0x56)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x400412345670, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x12345670, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Synthesised Normal Panasonic 48-bit message. + irsend.reset(); + irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 0x1, 0x1, 0x1)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x400401010101, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x1010101, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal repeated Panasonic messages. +TEST(TestDecodePanasonic, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Panasonic 48-bit message with 2 repeats. + irsend.reset(); + irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x190ED7C, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.makeDecodeResult(2 * kPanasonicBits + 4); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); + + irsend.makeDecodeResult(2 * (2 * kPanasonicBits + 4)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); +} + +// Decode Panasonic messages with unsupported values. +TEST(TestDecodePanasonic, DecodeWithNonStrictValues) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendPanasonic64(0x0); // Illegal value Panasonic 48-bit message. + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, false)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + // Illegal address/Manufacturer code. The rest is legal. + irsend.sendPanasonic64(irsend.encodePanasonic(0, 1, 2, 3)); + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, false)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x1020300, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x1020300, irsend.capture.command); +} + +// Decode Panasonic messages with unsupported size/lengths. +TEST(TestDecodePanasonic, DecodeWithNonStrictSize) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendPanasonic64(0x12345678, 32); // Illegal size Panasonic message. + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + + irsend.makeDecodeResult(); + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 32, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 32, false)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0x12345678, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x12345678, irsend.capture.command); + + // Illegal over length (56-bit) message. + irsend.reset(); + irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 1, 2, 3), 56); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + // Shouldn't pass if strict off and wrong bit size. + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, false)); + // Re-decode with correct bit size. + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 56, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 56, false)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(56, irsend.capture.bits); + EXPECT_EQ(0x400401020300, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x01020300, irsend.capture.command); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodePanasonic, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal value & size Panasonic 64-bit message. + irsend.sendPanasonic64(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 64, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 64, false)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); + EXPECT_EQ(0xFFFFFFFF, irsend.capture.address); + EXPECT_EQ(0xFFFFFFFF, irsend.capture.command); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodePanasonic, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Panasonic code from Global Cache. + uint16_t gc_test[103] = { + 37000, 1, 1, 126, 64, 16, 17, 16, 49, 15, 16, 16, 16, 16, 16, + 16, 17, 15, 17, 15, 17, 15, 17, 15, 16, 16, 16, 16, 16, 16, + 17, 15, 49, 16, 16, 16, 16, 16, 17, 15, 17, 15, 17, 15, 17, + 15, 16, 16, 16, 16, 16, 16, 49, 15, 49, 16, 17, 15, 17, 15, + 49, 16, 16, 16, 17, 16, 17, 15, 17, 15, 49, 16, 49, 15, 49, + 16, 17, 16, 49, 15, 49, 16, 17, 15, 48, 16, 16, 16, 49, 15, + 48, 16, 49, 15, 49, 16, 49, 15, 17, 15, 16, 16, 2721}; + irsend.sendGC(gc_test, 103); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x0190ED7C, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x0190ED7C, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Fail to decode a non-Panasonic example via GlobalCache +TEST(TestDecodePanasonic, FailToDecodeNonPanasonicExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Modified a few entries to unexpected values, based on previous test case. + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; + irsend.sendGC(gc_test, 39); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture)); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, false)); +} + +// Failing to decode Panasonic in Issue #245 +TEST(TestDecodePanasonic, DecodeIssue245) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + + uint16_t rawData[100] = { + 3550, 1750, 500, 450, 500, 1300, 500, 450, 500, 450, 500, 450, + 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, + 500, 450, 500, 450, 500, 1300, 500, 450, 500, 450, 500, 450, + 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, + 500, 1300, 500, 450, 500, 450, 500, 450, 500, 450, 500, 450, + 500, 450, 500, 450, 500, 450, 500, 1300, 500, 450, 500, 1300, + 500, 1300, 500, 1300, 500, 1300, 500, 450, 500, 450, 500, 1300, + 500, 450, 500, 1300, 500, 1300, 500, 1300, 500, 1300, 500, 450, + 500, 1300, 500, 5000}; + + irsend.sendRaw(rawData, 100, 37); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040100BCBD, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x100BCBD, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + irsend.reset(); + irsend.sendRaw(rawData, 99, 37); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040100BCBD, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x100BCBD, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Tests for sendPanasonicAC(). + +// Test sending typical data only. +TEST(TestSendPanasonicAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + + uint8_t state[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83}; + irsend.sendPanasonicAC(state); + EXPECT_EQ( + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s1296m432s1296" + "m432s432m432s432m432s1296m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s1296m432s1296m432s432m432s432m432s432m432s432m432s432" + "m432s10000" + "m3456s1728" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s1296m432s1296" + "m432s432m432s432m432s1296m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s1296m432s1296m432s432m432s432" + "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s1296m432s1296m432s1296m432s1296m432s432m432s1296m432s432m432s1296" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s1296m432s1296m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s1296m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s1296m432s1296m432s432m432s432m432s432m432s432m432s432" + "m432s1296m432s1296m432s432m432s432m432s432m432s432m432s432m432s1296" + "m432s100000", + irsend.outputStr()); +} + +// Tests for the IRPanasonicAc class. + +TEST(TestIRPanasonicAcClass, ChecksumCalculation) { + IRPanasonicAc pana(0); + + const uint8_t originalstate[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83}; + uint8_t examplestate[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83}; + + EXPECT_TRUE(IRPanasonicAc::validChecksum(examplestate)); + EXPECT_EQ(0x83, IRPanasonicAc::calcChecksum(examplestate)); + + examplestate[kPanasonicAcStateLength - 1] = 0x0; // Set incoorect checksum. + EXPECT_FALSE(IRPanasonicAc::validChecksum(examplestate)); + EXPECT_EQ(0x83, IRPanasonicAc::calcChecksum(examplestate)); + pana.setRaw(examplestate); + // Extracting the state from the object should have a correct checksum. + EXPECT_TRUE(IRPanasonicAc::validChecksum(pana.getRaw())); + EXPECT_STATE_EQ(originalstate, pana.getRaw(), kPanasonicAcBits); + examplestate[kPanasonicAcStateLength - 1] = 0x83; // Restore old checksum. + + // Change the state to force a different checksum. + examplestate[6] = 0x01; // Should increase checksum by 1. + EXPECT_FALSE(IRPanasonicAc::validChecksum(examplestate)); + EXPECT_EQ(0x84, IRPanasonicAc::calcChecksum(examplestate)); +} + +TEST(TestIRPanasonicAcClass, SetAndGetPower) { + IRPanasonicAc pana(0); + pana.on(); + EXPECT_TRUE(pana.getPower()); + pana.off(); + EXPECT_FALSE(pana.getPower()); + pana.setPower(true); + EXPECT_TRUE(pana.getPower()); + pana.setPower(false); + EXPECT_FALSE(pana.getPower()); +} + +TEST(TestIRPanasonicAcClass, SetAndGetModel) { + IRPanasonicAc pana(0); + EXPECT_EQ(kPanasonicJke, pana.getModel()); + pana.setModel(kPanasonicDke); + EXPECT_EQ(kPanasonicDke, pana.getModel()); + pana.setModel(kPanasonicLke); + EXPECT_EQ(kPanasonicLke, pana.getModel()); + pana.setModel(kPanasonicNke); + EXPECT_EQ(kPanasonicNke, pana.getModel()); + pana.setModel(kPanasonicUnknown); // shouldn't change. + EXPECT_EQ(kPanasonicNke, pana.getModel()); + pana.setModel((panasonic_ac_remote_model_t)255); // shouldn't change. + EXPECT_EQ(kPanasonicNke, pana.getModel()); + pana.setModel(kPanasonicJke); + EXPECT_EQ(kPanasonicJke, pana.getModel()); + + // This state tickled a bug in getModel(). Should read as a JKE. + uint8_t jkeState[27] = {0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x32, 0x2E, 0x80, 0xA2, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x74}; + pana.setModel(kPanasonicDke); // Make sure it isn't somehow set to JKE + pana.setRaw(jkeState); + EXPECT_EQ(kPanasonicJke, pana.getModel()); + EXPECT_STATE_EQ(jkeState, pana.getRaw(), kPanasonicAcBits); + + // This state tickled a bug in getModel(). Should read as CKP. + uint8_t ckpState[27] = {0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x67, 0x2E, 0x80, 0xAF, 0x00, + 0xC0, 0x6B, 0x98, 0x10, 0x00, 0x81, 0x64, 0x05, 0x87}; + pana.setModel(kPanasonicDke); // Make sure it isn't somehow set to CKP + pana.setRaw(ckpState); + EXPECT_EQ(kPanasonicCkp, pana.getModel()); + EXPECT_STATE_EQ(ckpState, pana.getRaw(), kPanasonicAcBits); +} + +TEST(TestIRPanasonicAcClass, SetAndGetMode) { + IRPanasonicAc pana(0); + pana.setMode(kPanasonicAcCool); + pana.setTemp(21); + EXPECT_EQ(kPanasonicAcCool, pana.getMode()); + pana.setMode(kPanasonicAcHeat); + EXPECT_EQ(kPanasonicAcHeat, pana.getMode()); + pana.setMode(kPanasonicAcAuto); + EXPECT_EQ(kPanasonicAcAuto, pana.getMode()); + pana.setMode(kPanasonicAcDry); + EXPECT_EQ(kPanasonicAcDry, pana.getMode()); + EXPECT_EQ(21, pana.getTemp()); // Temp should be unchanged. + pana.setMode(kPanasonicAcFan); + EXPECT_EQ(kPanasonicAcFan, pana.getMode()); + EXPECT_EQ(kPanasonicAcFanModeTemp, pana.getTemp()); // Temp should change. + pana.setMode(kPanasonicAcCool); + EXPECT_EQ(kPanasonicAcCool, pana.getMode()); + // Temp should be unchanged from the last manual change. + EXPECT_EQ(21, pana.getTemp()); +} + +TEST(TestIRPanasonicAcClass, SetAndGetTemp) { + IRPanasonicAc pana(0); + pana.setTemp(25); + EXPECT_EQ(25, pana.getTemp()); + pana.setTemp(kPanasonicAcMinTemp); + EXPECT_EQ(kPanasonicAcMinTemp, pana.getTemp()); + pana.setTemp(kPanasonicAcMinTemp - 1); + EXPECT_EQ(kPanasonicAcMinTemp, pana.getTemp()); + pana.setTemp(kPanasonicAcMaxTemp); + EXPECT_EQ(kPanasonicAcMaxTemp, pana.getTemp()); + pana.setTemp(kPanasonicAcMaxTemp + 1); + EXPECT_EQ(kPanasonicAcMaxTemp, pana.getTemp()); +} + +TEST(TestIRPanasonicAcClass, SetAndGetFan) { + IRPanasonicAc pana(0); + pana.setFan(kPanasonicAcFanAuto); + EXPECT_EQ(kPanasonicAcFanAuto, pana.getFan()); + pana.setFan(kPanasonicAcFanMin); + EXPECT_EQ(kPanasonicAcFanMin, pana.getFan()); + pana.setFan(kPanasonicAcFanMin - 1); + EXPECT_EQ(kPanasonicAcFanMin, pana.getFan()); + pana.setFan(kPanasonicAcFanMin + 1); + EXPECT_EQ(kPanasonicAcFanMin + 1, pana.getFan()); + pana.setFan(kPanasonicAcFanMax); + EXPECT_EQ(kPanasonicAcFanMax, pana.getFan()); + pana.setFan(kPanasonicAcFanMax + 1); + EXPECT_EQ(kPanasonicAcFanMax, pana.getFan()); + pana.setFan(kPanasonicAcFanMax - 1); + EXPECT_EQ(kPanasonicAcFanMax - 1, pana.getFan()); +} + +TEST(TestIRPanasonicAcClass, SetAndGetSwings) { + IRPanasonicAc pana(0); + + // Vertical + pana.setSwingVertical(kPanasonicAcSwingVAuto); + EXPECT_EQ(kPanasonicAcSwingVAuto, pana.getSwingVertical()); + + pana.setSwingVertical(kPanasonicAcSwingVUp); + EXPECT_EQ(kPanasonicAcSwingVUp, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVUp - 1); + EXPECT_EQ(kPanasonicAcSwingVUp, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVUp + 1); + EXPECT_EQ(kPanasonicAcSwingVUp + 1, pana.getSwingVertical()); + + pana.setSwingVertical(kPanasonicAcSwingVDown); + EXPECT_EQ(kPanasonicAcSwingVDown, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVDown + 1); + EXPECT_EQ(kPanasonicAcSwingVDown, pana.getSwingVertical()); + pana.setSwingVertical(kPanasonicAcSwingVDown - 1); + EXPECT_EQ(kPanasonicAcSwingVDown - 1, pana.getSwingVertical()); + + pana.setSwingVertical(kPanasonicAcSwingVAuto); + EXPECT_EQ(kPanasonicAcSwingVAuto, pana.getSwingVertical()); + + // Horizontal is model dependant. + pana.setModel(kPanasonicNke); // NKE is always fixed in the middle. + EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal()); + pana.setSwingHorizontal(kPanasonicAcSwingHAuto); + EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal()); + + pana.setModel(kPanasonicJke); // JKE has no H swing. + EXPECT_EQ(0, pana.getSwingHorizontal()); + pana.setSwingHorizontal(kPanasonicAcSwingHMiddle); + EXPECT_EQ(0, pana.getSwingHorizontal()); + + pana.setModel(kPanasonicLke); // LKE is always fixed in the middle. + EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal()); + pana.setSwingHorizontal(kPanasonicAcSwingHAuto); + EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal()); + + pana.setModel(kPanasonicDke); // DKE has full control. + ASSERT_EQ(kPanasonicDke, pana.getModel()); + // Auto was last requested. + EXPECT_EQ(kPanasonicAcSwingHAuto, pana.getSwingHorizontal()); + pana.setSwingHorizontal(kPanasonicAcSwingHLeft); + EXPECT_EQ(kPanasonicAcSwingHLeft, pana.getSwingHorizontal()); + // Changing models from DKE to something else, then back should not change + // the intended swing. + pana.setModel(kPanasonicLke); + EXPECT_EQ(kPanasonicAcSwingHMiddle, pana.getSwingHorizontal()); + pana.setModel(kPanasonicDke); + EXPECT_EQ(kPanasonicAcSwingHLeft, pana.getSwingHorizontal()); +} + +TEST(TestIRPanasonicAcClass, QuietAndPowerful) { + IRPanasonicAc pana(0); + pana.setQuiet(false); + EXPECT_FALSE(pana.getQuiet()); + pana.setQuiet(true); + EXPECT_TRUE(pana.getQuiet()); + EXPECT_FALSE(pana.getPowerful()); + pana.setPowerful(false); + EXPECT_FALSE(pana.getPowerful()); + EXPECT_TRUE(pana.getQuiet()); + pana.setPowerful(true); + EXPECT_TRUE(pana.getPowerful()); + EXPECT_FALSE(pana.getQuiet()); + pana.setPowerful(false); + EXPECT_FALSE(pana.getPowerful()); + EXPECT_FALSE(pana.getQuiet()); + pana.setPowerful(true); + pana.setQuiet(true); + EXPECT_TRUE(pana.getQuiet()); + EXPECT_FALSE(pana.getPowerful()); +} + +TEST(TestIRPanasonicAcClass, HumanReadable) { + IRPanasonicAc pana(0); + EXPECT_EQ( + "Model: 4 (JKE), Power: Off, Mode: 0 (AUTO), Temp: 0C, " + "Fan: 253 (UNKNOWN), Swing (Vertical): 0 (UNKNOWN), Quiet: Off, " + "Powerful: Off, Clock: 0:00, On Timer: Off, Off Timer: Off", + pana.toString()); + pana.setPower(true); + pana.setTemp(kPanasonicAcMaxTemp); + pana.setMode(kPanasonicAcHeat); + pana.setFan(kPanasonicAcFanMax); + pana.setSwingVertical(kPanasonicAcSwingVAuto); + pana.setPowerful(true); + EXPECT_EQ( + "Model: 4 (JKE), Power: On, Mode: 4 (HEAT), Temp: 30C, " + "Fan: 4 (MAX), Swing (Vertical): 15 (AUTO), Quiet: Off, " + "Powerful: On, Clock: 0:00, On Timer: Off, Off Timer: Off", + pana.toString()); + pana.setQuiet(true); + pana.setModel(kPanasonicLke); + EXPECT_EQ( + "Model: 1 (LKE), Power: Off, Mode: 4 (HEAT), Temp: 30C, " + "Fan: 4 (MAX), Swing (Vertical): 15 (AUTO), " + "Swing (Horizontal): 6 (Middle), Quiet: On, Powerful: Off, " + "Clock: 0:00, On Timer: 0:00, Off Timer: Off", + pana.toString()); + pana.setModel(kPanasonicDke); + pana.setSwingHorizontal(kPanasonicAcSwingHRight); + EXPECT_EQ( + "Model: 3 (DKE), Power: Off, Mode: 4 (HEAT), Temp: 30C, " + "Fan: 4 (MAX), Swing (Vertical): 15 (AUTO), " + "Swing (Horizontal): 11 (Right), Quiet: On, Powerful: Off, " + "Clock: 0:00, On Timer: Off, Off Timer: Off", + pana.toString()); +} + +// Tests for decodePanasonicAC(). + +// Decode normal Panasonic AC messages. +TEST(TestDecodePanasonicAC, RealExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Data from Issue #525 + uint16_t rawData[439] = { + 3582, 1686, 488, 378, 488, 1238, 488, 378, 488, 378, 488, 378, + 488, 378, 488, 378, 488, 384, 488, 378, 488, 378, 488, 378, + 488, 378, 488, 378, 488, 1242, 486, 378, 488, 384, 488, 378, + 488, 378, 488, 380, 486, 382, 484, 382, 484, 1264, 464, 1266, + 460, 1272, 462, 378, 488, 406, 460, 1266, 462, 380, 488, 382, + 484, 388, 478, 406, 462, 410, 462, 404, 462, 406, 462, 396, + 470, 406, 462, 404, 462, 406, 460, 404, 462, 410, 462, 404, + 462, 404, 462, 406, 464, 406, 462, 404, 462, 406, 462, 404, + 462, 410, 462, 404, 462, 406, 462, 404, 462, 404, 462, 404, + 462, 406, 460, 406, 462, 410, 462, 404, 462, 1264, 484, 1244, + 486, 382, 482, 382, 486, 382, 486, 378, 486, 382, 488, 9924, + 3554, 1686, 488, 378, 490, 1240, 486, 378, 488, 378, 488, 378, + 488, 378, 488, 382, 484, 386, 486, 378, 488, 382, 486, 378, + 488, 382, 486, 382, 484, 1242, 486, 380, 488, 386, 484, 382, + 486, 380, 486, 382, 486, 380, 486, 380, 486, 1242, 486, 1242, + 484, 1248, 484, 380, 488, 382, 484, 1242, 486, 382, 484, 382, + 484, 382, 484, 382, 486, 386, 484, 382, 486, 382, 484, 382, + 486, 382, 486, 380, 484, 382, 486, 382, 488, 380, 486, 382, + 484, 380, 462, 406, 488, 376, 484, 1246, 482, 1246, 460, 404, + 480, 392, 484, 386, 482, 1244, 484, 382, 484, 382, 484, 1242, + 482, 1244, 484, 382, 464, 410, 460, 404, 462, 406, 462, 404, + 462, 404, 470, 396, 462, 406, 462, 404, 462, 1286, 460, 1268, + 458, 1268, 460, 1266, 460, 1266, 460, 406, 460, 1266, 462, 406, + 460, 1272, 462, 406, 460, 406, 460, 406, 460, 406, 462, 404, + 462, 406, 460, 406, 462, 410, 462, 404, 462, 406, 460, 406, + 460, 406, 462, 404, 462, 406, 460, 406, 460, 410, 462, 406, + 460, 1268, 460, 1266, 460, 404, 460, 406, 462, 406, 460, 406, + 460, 412, 456, 410, 460, 410, 438, 428, 460, 410, 456, 410, + 456, 1272, 436, 1288, 438, 434, 438, 428, 438, 428, 438, 428, + 438, 428, 438, 428, 438, 428, 438, 428, 438, 434, 438, 428, + 438, 428, 438, 428, 438, 428, 438, 428, 440, 428, 438, 428, + 438, 432, 438, 428, 438, 428, 438, 428, 438, 428, 438, 428, + 438, 428, 438, 430, 438, 1294, 438, 428, 438, 428, 438, 428, + 438, 428, 438, 428, 438, 428, 438, 428, 438, 434, 438, 428, + 438, 1288, 438, 1290, 438, 428, 438, 428, 438, 428, 438, 428, + 438, 432, 438, 1288, 438, 1290, 438, 430, 438, 428, 438, 428, + 438, 428, 438, 428, 438, 1292, 438}; + uint8_t expectedState[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83}; + + irsend.sendRaw(rawData, 439, kPanasonicFreq); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode synthetic Panasonic AC message. +TEST(TestDecodePanasonicAC, SyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Data from Issue #525 + uint8_t expectedState[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x30, 0x32, 0x80, 0xAF, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83}; + + irsend.sendPanasonicAC(expectedState); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + + IRPanasonicAc pana(0); + pana.setRaw(irsend.capture.state); + EXPECT_EQ( + "Model: 4 (JKE), Power: Off, Mode: 3 (COOL), Temp: 25C, " + "Fan: 7 (AUTO), Swing (Vertical): 15 (AUTO), Quiet: Off, " + "Powerful: Off, Clock: 0:00, On Timer: Off, Off Timer: Off", + pana.toString()); +} + +// Tests for general utility functions. +TEST(TestGeneralPanasonic, hasACState) { + EXPECT_TRUE(hasACState(PANASONIC_AC)); + ASSERT_FALSE(hasACState(PANASONIC)); +} + +TEST(TestGeneralPanasonic, typeToString) { + EXPECT_EQ("PANASONIC_AC", typeToString(PANASONIC_AC)); + EXPECT_EQ("PANASONIC", typeToString(PANASONIC)); +} + +// Decode a problematic Panasonic AC message +TEST(TestDecodePanasonicAC, Issue540) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Data from Issue #540 + uint16_t rawData[439] = { + 3512, 1714, 466, 408, 466, 1280, 470, 408, 466, 412, 466, 408, + 466, 412, 462, 412, 466, 414, 466, 408, 466, 412, 462, 412, + 466, 412, 466, 408, 466, 1280, 466, 412, 462, 416, 462, 412, + 466, 408, 466, 412, 462, 416, 462, 412, 462, 1282, 462, 1284, + 462, 1288, 466, 412, 462, 412, 462, 1284, 462, 416, 440, 438, + 462, 412, 462, 412, 462, 416, 466, 412, 462, 412, 462, 412, + 440, 442, 462, 412, 462, 412, 460, 418, 462, 416, 462, 412, + 462, 418, 462, 412, 462, 416, 462, 412, 436, 442, 462, 412, + 460, 418, 462, 416, 462, 412, 460, 412, 462, 420, 436, 438, + 462, 412, 462, 416, 432, 448, 436, 438, 436, 1310, 436, 1310, + 462, 420, 432, 442, 436, 438, 462, 416, 432, 444, 432, 10008, + 3480, 1744, 492, 382, 492, 1254, 492, 386, 488, 390, 492, 382, + 492, 386, 488, 386, 492, 386, 492, 386, 488, 386, 488, 386, + 492, 386, 492, 382, 492, 1258, 488, 386, 488, 390, 492, 386, + 488, 386, 488, 386, 492, 390, 488, 386, 488, 1256, 488, 1258, + 488, 1262, 488, 390, 488, 386, 488, 1258, 488, 390, 488, 392, + 488, 386, 488, 386, 488, 394, 488, 386, 488, 386, 488, 390, + 488, 390, 488, 386, 488, 390, 462, 412, 488, 390, 462, 1282, + 488, 390, 456, 416, 458, 1292, 456, 1288, 488, 1258, 488, 392, + 456, 422, 488, 390, 484, 392, 484, 1262, 458, 420, 484, 1262, + 482, 1262, 488, 392, 484, 394, 484, 416, 436, 442, 458, 416, + 458, 422, 430, 448, 432, 442, 458, 416, 458, 1296, 432, 1314, + 458, 1288, 432, 1312, 432, 1322, 428, 446, 428, 1318, 432, 442, + 432, 1318, 432, 1318, 428, 446, 428, 1318, 428, 1322, 430, 448, + 426, 448, 428, 452, 426, 452, 426, 448, 428, 472, 400, 478, + 402, 478, 402, 472, 402, 476, 402, 472, 402, 478, 402, 472, + 402, 1348, 398, 1348, 398, 1352, 398, 508, 370, 478, 398, 476, + 398, 512, 366, 508, 370, 502, 372, 508, 340, 538, 372, 504, + 344, 1400, 344, 1400, 346, 1434, 314, 560, 316, 588, 290, 560, + 314, 564, 396, 400, 474, 400, 480, 394, 480, 404, 474, 400, + 454, 446, 454, 426, 448, 430, 424, 450, 428, 452, 448, 426, + 426, 452, 424, 1322, 454, 426, 450, 424, 426, 452, 428, 452, + 450, 424, 428, 446, 426, 1322, 454, 426, 422, 450, 454, 426, + 448, 430, 454, 426, 448, 426, 428, 446, 454, 430, 454, 422, + 452, 424, 424, 452, 452, 430, 424, 452, 452, 426, 448, 426, + 426, 456, 448, 426, 448, 1296, 424, 1322, 426, 1326, 450, 1270, + 478, 422, 454, 424, 424, 450, 454}; + uint8_t expectedState[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x39, 0x34, 0x80, 0xAF, 0x0D, + 0x00, 0x0E, 0xE0, 0x00, 0x00, 0x81, 0x00, 0x00, 0x1E}; + + irsend.sendRaw(rawData, 439, kPanasonicFreq); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + IRPanasonicAc pana(0); + pana.setRaw(irsend.capture.state); + // TODO(crankyoldgit): Try to figure out what model this should be. + EXPECT_EQ( + "Model: 0 (UNKNOWN), Power: On, Mode: 3 (COOL), Temp: 26C, " + "Fan: 7 (AUTO), Swing (Vertical): 15 (AUTO), " + "Swing (Horizontal): 13 (AUTO), Quiet: Off, Powerful: Off, " + "Clock: 0:00, On Timer: Off, Off Timer: Off", + pana.toString()); +} + +TEST(TestIRPanasonicAcClass, TimeBasics) { + EXPECT_EQ(0x186, IRPanasonicAc::encodeTime(6, 30)); + EXPECT_EQ(0x3CA, IRPanasonicAc::encodeTime(16, 10)); + EXPECT_EQ(0x448, IRPanasonicAc::encodeTime(18, 16)); + EXPECT_EQ(0, IRPanasonicAc::encodeTime(0, 0)); + EXPECT_EQ(kPanasonicAcTimeMax, IRPanasonicAc::encodeTime(23, 59)); + EXPECT_EQ("16:10", + IRPanasonicAc::timeToString(IRPanasonicAc::encodeTime(16, 10))); + EXPECT_EQ("6:30", + IRPanasonicAc::timeToString(IRPanasonicAc::encodeTime(6, 30))); + EXPECT_EQ("18:16", + IRPanasonicAc::timeToString(IRPanasonicAc::encodeTime(18, 16))); + EXPECT_EQ("1:01", + IRPanasonicAc::timeToString(IRPanasonicAc::encodeTime(1, 1))); + EXPECT_EQ(kPanasonicAcTimeMax, IRPanasonicAc::encodeTime(23, 59)); + EXPECT_EQ(kPanasonicAcTimeMax, IRPanasonicAc::encodeTime(25, 72)); + EXPECT_EQ(59, IRPanasonicAc::encodeTime(0, 72)); + EXPECT_EQ(23 * 60, IRPanasonicAc::encodeTime(27, 0)); + EXPECT_EQ("0:00", IRPanasonicAc::timeToString(0)); + EXPECT_EQ("23:59", IRPanasonicAc::timeToString(kPanasonicAcTimeMax)); +} + +TEST(TestIRPanasonicAcClass, TimersAndClock) { + IRPanasonicAc pana(0); + // Data from Issue #544 + uint8_t state[27] = {0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x4E, 0x2E, 0x80, 0xAF, 0x00, + 0xCA, 0x6B, 0x98, 0x10, 0x00, 0x01, 0x48, 0x04, 0xDB}; + pana.setRaw(state); + EXPECT_TRUE(pana.isOnTimerEnabled()); + EXPECT_EQ(0x3CA, pana.getOnTimer()); + EXPECT_TRUE(pana.isOffTimerEnabled()); + EXPECT_EQ(0x186, pana.getOffTimer()); + EXPECT_EQ(0x448, pana.getClock()); + + pana.cancelOnTimer(); + EXPECT_FALSE(pana.isOnTimerEnabled()); + EXPECT_EQ(0, pana.getOnTimer()); + EXPECT_TRUE(pana.isOffTimerEnabled()); + EXPECT_EQ(0x186, pana.getOffTimer()); + EXPECT_EQ(0x448, pana.getClock()); + + pana.cancelOffTimer(); + EXPECT_FALSE(pana.isOnTimerEnabled()); + EXPECT_EQ(0, pana.getOnTimer()); + EXPECT_FALSE(pana.isOffTimerEnabled()); + EXPECT_EQ(0, pana.getOffTimer()); + EXPECT_EQ(0x448, pana.getClock()); + + pana.setOnTimer(7 * 60 + 50); + EXPECT_TRUE(pana.isOnTimerEnabled()); + EXPECT_EQ(7 * 60 + 50, pana.getOnTimer()); + EXPECT_FALSE(pana.isOffTimerEnabled()); + EXPECT_EQ(0, pana.getOffTimer()); + EXPECT_EQ(0x448, pana.getClock()); + + pana.setOnTimer(7 * 60 + 57); // It should round down. + EXPECT_EQ(7 * 60 + 50, pana.getOnTimer()); + pana.setOnTimer(28 * 60); // It should round down. + EXPECT_EQ(kPanasonicAcTimeMax - 9, pana.getOnTimer()); + pana.setOnTimer(kPanasonicAcTimeSpecial); + EXPECT_EQ(0, pana.getOnTimer()); + + pana.setOnTimer(7 * 60 + 50); + pana.setOffTimer(19 * 60 + 30); + + EXPECT_TRUE(pana.isOnTimerEnabled()); + EXPECT_EQ(7 * 60 + 50, pana.getOnTimer()); + EXPECT_TRUE(pana.isOffTimerEnabled()); + EXPECT_EQ(19 * 60 + 30, pana.getOffTimer()); + EXPECT_EQ(0x448, pana.getClock()); + + pana.setOffTimer(19 * 60 + 57); // It should round down. + EXPECT_EQ(19 * 60 + 50, pana.getOffTimer()); + pana.setOffTimer(28 * 60); // It should round down. + EXPECT_EQ(kPanasonicAcTimeMax - 9, pana.getOffTimer()); + pana.setOffTimer(kPanasonicAcTimeSpecial); + EXPECT_EQ(0, pana.getOffTimer()); + + pana.setClock(0); + EXPECT_EQ(0, pana.getClock()); + pana.setClock(kPanasonicAcTimeMax); + EXPECT_EQ(kPanasonicAcTimeMax, pana.getClock()); + pana.setClock(kPanasonicAcTimeMax - 1); + EXPECT_EQ(kPanasonicAcTimeMax - 1, pana.getClock()); + pana.setClock(kPanasonicAcTimeMax + 1); + EXPECT_EQ(kPanasonicAcTimeMax, pana.getClock()); + pana.setClock(kPanasonicAcTimeSpecial); + EXPECT_EQ(0, pana.getClock()); +} + +// Decode a real short Panasonic AC message +TEST(TestDecodePanasonicAC, RealExampleOfShortMessage) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Data from Issue #544 (Odour Wash) + uint16_t rawData[263] = { + 3496, 1734, 506, 366, 448, 1294, 504, 368, 498, 374, 452, 418, + 448, 424, 444, 428, 450, 422, 446, 426, 450, 420, 448, 424, + 452, 418, 448, 422, 444, 1300, 498, 374, 504, 368, 448, 424, + 452, 418, 448, 424, 444, 428, 450, 422, 446, 1296, 500, 1242, + 502, 1242, 504, 368, 498, 374, 452, 1292, 504, 366, 450, 422, + 444, 426, 450, 420, 446, 424, 452, 418, 448, 424, 444, 428, + 450, 422, 444, 426, 450, 420, 446, 424, 452, 418, 448, 422, + 444, 428, 450, 422, 446, 426, 452, 420, 446, 426, 452, 418, + 448, 424, 442, 428, 448, 422, 444, 426, 450, 420, 446, 426, + 452, 418, 448, 424, 444, 428, 450, 422, 444, 1298, 500, 1244, + 500, 372, 444, 428, 450, 422, 446, 426, 452, 418, 448, 10020, + 3500, 1732, 498, 372, 452, 1290, 506, 366, 450, 422, 446, 426, + 452, 420, 448, 424, 452, 418, 448, 422, 444, 426, 450, 420, + 446, 426, 452, 420, 446, 1296, 500, 370, 444, 428, 450, 422, + 446, 426, 452, 420, 446, 424, 442, 428, 448, 1294, 502, 1240, + 504, 1238, 506, 366, 448, 422, 444, 1298, 498, 374, 452, 418, + 448, 424, 444, 428, 450, 422, 446, 426, 450, 420, 446, 424, + 452, 418, 448, 422, 444, 428, 450, 420, 446, 1298, 498, 1244, + 500, 1242, 502, 368, 446, 1298, 500, 1244, 500, 372, 444, 428, + 450, 1292, 504, 368, 446, 1296, 502, 370, 444, 426, 452, 1290, + 504, 1238, 506, 366, 450, 422, 446, 1298, 498, 1246, 500, 372, + 444, 428, 450, 1294, 452, 420, 446, 1296, 448, 422, 444}; // UNKNOWN + // 1FB51F79 + + uint8_t expectedState[kPanasonicAcStateShortLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, + 0x02, 0x20, 0xE0, 0x04, 0x80, 0x9B, 0x32, 0x53}; + + irsend.sendRaw(rawData, 263, kPanasonicFreq); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicAcShortBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Create and decode a short Panasonic AC message +TEST(TestDecodePanasonicAC, SyntheticShortMessage) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t odourWash[kPanasonicAcStateShortLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, + 0x02, 0x20, 0xE0, 0x04, 0x80, 0x9B, 0x32, 0x53}; + + irsend.sendPanasonicAC(odourWash, kPanasonicAcStateShortLength); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicAcShortBits, irsend.capture.bits); + EXPECT_STATE_EQ(odourWash, irsend.capture.state, irsend.capture.bits); +} +// +// Test for CKP model / see issue #544 +TEST(TestDecodePanasonicAC, CkpModelSpecifics) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Data from Issue #544 + uint8_t ckpPowerfulOn[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x4E, 0x2E, 0x80, 0xAF, 0x00, + 0x00, 0x0E, 0xE0, 0x11, 0x00, 0x01, 0x00, 0x06, 0xB7}; + uint8_t ckpQuietOn[kPanasonicAcStateLength] = { + 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, + 0x20, 0xE0, 0x04, 0x00, 0x4E, 0x2E, 0x80, 0xAF, 0x00, + 0x00, 0x0E, 0xE0, 0x30, 0x00, 0x01, 0x00, 0x06, 0xD6}; + + irsend.sendPanasonicAC(ckpPowerfulOn); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(PANASONIC_AC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(ckpPowerfulOn, irsend.capture.state, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + + IRPanasonicAc pana(0); + pana.setRaw(irsend.capture.state); + EXPECT_EQ( + "Model: 5 (CKP), Power: Off, Mode: 4 (HEAT), Temp: 23C, " + "Fan: 7 (AUTO), Swing (Vertical): 15 (AUTO), Quiet: Off, " + "Powerful: On, Clock: 0:00, On Timer: 0:00, Off Timer: 0:00", + pana.toString()); + + pana.setQuiet(true); + EXPECT_FALSE(pana.getPowerful()); + EXPECT_TRUE(pana.getQuiet()); + EXPECT_EQ(kPanasonicCkp, pana.getModel()); + EXPECT_STATE_EQ(ckpQuietOn, pana.getRaw(), kPanasonicAcBits); + + pana.setPowerful(true); + EXPECT_TRUE(pana.getPowerful()); + EXPECT_FALSE(pana.getQuiet()); + EXPECT_EQ(kPanasonicCkp, pana.getModel()); + EXPECT_STATE_EQ(ckpPowerfulOn, pana.getRaw(), kPanasonicAcBits); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Pioneer_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Pioneer_test.cpp new file mode 100644 index 000000000..b78469add --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Pioneer_test.cpp @@ -0,0 +1,152 @@ +// Copyright 2018 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "IRutils.h" +#include "gtest/gtest.h" + +// Tests for sendPioneer(). + +// Test sending typical data only. +TEST(TestSendPioneer, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + irsend.sendPioneer(0); + EXPECT_EQ( + "m8960s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s58240" + "m8960s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s58240", + irsend.outputStr()); + irsend.sendPioneer(0x55FF00AAAA00FF55); + EXPECT_EQ( + "m8960s4480" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s40320" + "m8960s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s40320", + irsend.outputStr()); +} + +// Tests for IRutils. + +TEST(TestIRUtils, TypeToString) { EXPECT_EQ("PIONEER", typeToString(PIONEER)); } + +// Tests for encodePioneer(). + +TEST(TestEncodePioneer, SimpleEncoding) { + IRsendTest irsend(0); + IRrecv irrecv(0); + + // Spotify button (A556+AF20) + // via + // https://www.pioneerelectronics.com/StaticFiles/PUSA/Files/Home%20Custom%20Install/2015%20Pioneer%20&%20Elite%20AVR%20IR%20with%20Hex_1.xls + EXPECT_EQ(0xA55A6A95F50A04FB, irsend.encodePioneer(0xA556, 0xAF20)); + + // "Source" from + // https://github.com/markszabo/IRremoteESP8266/pull/547#issuecomment-429616582 + EXPECT_EQ(0x659A05FAF50AC53A, irsend.encodePioneer(0xA6A0, 0xAFA3)); +} + +// Tests for decodePioneer(). + +// Synthesised Normal Pioneer message. +TEST(TestDecodePioneer, SyntheticPioneerDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendPioneer(0x659A05FAF50AC53A); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(PIONEER, irsend.capture.decode_type); + EXPECT_EQ(kPioneerBits, irsend.capture.bits); + EXPECT_EQ(0x659A05FAF50AC53A, irsend.capture.value); + EXPECT_EQ(0xA6A0, irsend.capture.address); + EXPECT_EQ(0xAFA3, irsend.capture.command); +} + +// Real long Pioneer message. +TEST(TestDecodePioneer, RealExampleLongDecodeSourceButton) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // "Source" button. + // https://github.com/markszabo/IRremoteESP8266/pull/547#issuecomment-429616582 + uint16_t rawData[135] = { + 8552, 4184, 596, 472, 592, 1524, 594, 1524, 594, 472, 592, 472, + 598, 1520, 596, 472, 594, 1524, 592, 1524, 592, 472, 592, 472, + 596, 1520, 598, 1520, 596, 472, 592, 1524, 592, 472, 592, 476, + 592, 472, 592, 472, 592, 476, 592, 472, 592, 1524, 592, 472, + 598, 1518, 598, 1520, 596, 1520, 596, 1520, 596, 1520, 596, 1520, + 596, 472, 592, 1524, 592, 472, 598, 25282, 8552, 4182, 596, 1520, + 598, 1518, 598, 1520, 596, 1520, 596, 472, 592, 1524, 592, 472, + 598, 1520, 596, 472, 594, 472, 592, 472, 596, 472, 592, 1524, + 592, 472, 592, 1524, 596, 472, 594, 1520, 596, 1520, 598, 472, + 592, 472, 598, 472, 594, 1522, 594, 472, 592, 1524, 594, 472, + 596, 472, 594, 1524, 592, 1524, 592, 1524, 592, 472, 594, 1524, + 598, 472, 592}; + + irsend.sendRaw(rawData, 135, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(PIONEER, irsend.capture.decode_type); + EXPECT_EQ(kPioneerBits, irsend.capture.bits); + EXPECT_EQ(0x659A05FAF50AC53A, irsend.capture.value); + EXPECT_EQ(0xA6A0, irsend.capture.address); + EXPECT_EQ(0xAFA3, irsend.capture.command); +} + +// Synthetic Pioneer message. +// For: +// https://github.com/markszabo/IRremoteESP8266/pull/547#issuecomment-430800734 +TEST(TestDecodePioneer, SyntheticPioneerMessage) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendPioneer(0x659A857AF50A3DC2, 64, 0); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(PIONEER, irsend.capture.decode_type); + EXPECT_EQ(kPioneerBits, irsend.capture.bits); + EXPECT_EQ(0x659A857AF50A3DC2, irsend.capture.value); + EXPECT_EQ(0xA6A1, irsend.capture.address); + EXPECT_EQ(0xAFBC, irsend.capture.command); + + irsend.reset(); + irsend.sendPioneer(0x659A857AF50A3DC2, 64, 0); + EXPECT_EQ( + "m8960s4480" + "m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s560" + "m560s40320" + "m8960s4480" + "m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s560m560s1680" + "m560s560m560s560m560s560m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s1680" + "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s1680m560s560" + "m560s40320", + irsend.outputStr()); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Pronto_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Pronto_test.cpp similarity index 81% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Pronto_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Pronto_test.cpp index 7fbe39554..e52c6dd90 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Pronto_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Pronto_test.cpp @@ -79,8 +79,8 @@ TEST(TestSendPronto, MoreDataThanNeededInBoth) { irsend.reset(); // We should handle when we are given more data than needed. (repeat seq.) - uint16_t pronto_test[10] = {0x0000, 0x0067, 0x0001, 0x0001, - 0x0001, 0x0002, 0x0003, 0x0004, 0x5, 0x6}; + uint16_t pronto_test[10] = {0x0000, 0x0067, 0x0001, 0x0001, 0x0001, + 0x0002, 0x0003, 0x0004, 0x5, 0x6}; irsend.sendPronto(pronto_test, 10); EXPECT_EQ("m25s50", irsend.outputStr()); // Only send the data required. irsend.sendPronto(pronto_test, 10, 1); @@ -110,25 +110,29 @@ TEST(TestSendPronto, NonRepeatingCode) { // It was an example of a poor Pronto code. // It turned out to be a 4 copies of a Sony 12-bit code. Who knew!?! uint16_t pronto_test[108] = { - 0x0000, 0x0067, 0x0034, 0x0000, - 0x0060, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0452, 0x0060, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0452, 0x0060, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0452, 0x0060, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018}; + 0x0000, 0x0067, 0x0034, 0x0000, 0x0060, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0452, 0x0060, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0452, 0x0060, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0452, 0x0060, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0030, + 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018}; // Send the Pronto code without any repeats set. irsend.reset(); irsend.sendPronto(pronto_test, 108); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony12Bits, irsend.capture.bits); + EXPECT_EQ(0x10, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); EXPECT_EQ( "m2400s600" "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" @@ -141,19 +145,20 @@ TEST(TestSendPronto, NonRepeatingCode) { "m600s600m600s600m600s600m600s27650" "m2400s600" "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m600s600m600s600", irsend.outputStr()); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_12_BITS, irsend.capture.bits); - EXPECT_EQ(0x10, irsend.capture.value); - EXPECT_EQ(0x1, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); + "m600s600m600s600m600s600m600s600", + irsend.outputStr()); // Now try repeating it. // As it has no repeat sequence, we shouldn't repeat it. (I think) irsend.reset(); irsend.sendPronto(pronto_test, 108, 3); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony12Bits, irsend.capture.bits); + EXPECT_EQ(0x10, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); EXPECT_EQ( "m2400s600" "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" @@ -166,13 +171,8 @@ TEST(TestSendPronto, NonRepeatingCode) { "m600s600m600s600m600s600m600s27650" "m2400s600" "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" - "m600s600m600s600m600s600m600s600", irsend.outputStr()); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_12_BITS, irsend.capture.bits); - EXPECT_EQ(0x10, irsend.capture.value); - EXPECT_EQ(0x1, irsend.capture.address); - EXPECT_EQ(0x0, irsend.capture.command); + "m600s600m600s600m600s600m600s600", + irsend.outputStr()); } // Test sending a Pronto code that only has a repeat sequence (Sony). @@ -183,34 +183,40 @@ TEST(TestSendPronto, RepeatSequenceOnlyForSony) { // Sony 20-bit command. uint16_t pronto_test[46] = { - 0x0000, 0x0067, 0x0000, 0x0015, - 0x0060, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, 0x0030, 0x0018, - 0x0030, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, - 0x0030, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, + 0x0000, 0x0067, 0x0000, 0x0015, 0x0060, 0x0018, 0x0018, 0x0018, + 0x0030, 0x0018, 0x0030, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, - 0x0018, 0x03f6}; + 0x0018, 0x0018, 0x0030, 0x0018, 0x0030, 0x0018, 0x0030, 0x0018, + 0x0018, 0x0018, 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x0018, + 0x0018, 0x0018, 0x0030, 0x0018, 0x0018, 0x03f6}; // Send the Pronto code without any repeats set. irsend.reset(); irsend.sendPronto(pronto_test, 46); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony20Bits, irsend.capture.bits); + EXPECT_EQ(0x74B92, irsend.capture.value); + EXPECT_EQ(0x1A, irsend.capture.address); + EXPECT_EQ(0x24AE, irsend.capture.command); EXPECT_EQ( "m2400s600" "m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600" "m1200s600m600s600m1200s600m1200s600m1200s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s25350", irsend.outputStr()); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_20_BITS, irsend.capture.bits); - EXPECT_EQ(0x74B92, irsend.capture.value); - EXPECT_EQ(0x1A, irsend.capture.address); - EXPECT_EQ(0x24AE, irsend.capture.command); + "m600s600m600s600m1200s600m600s25350", + irsend.outputStr()); // Send the Pronto code with 2 repeats. irsend.reset(); - irsend.sendPronto(pronto_test, 46, SONY_MIN_REPEAT); + irsend.sendPronto(pronto_test, 46, kSonyMinRepeat); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony20Bits, irsend.capture.bits); + EXPECT_EQ(0x74B92, irsend.capture.value); + EXPECT_EQ(0x1A, irsend.capture.address); + EXPECT_EQ(0x24AE, irsend.capture.command); EXPECT_EQ( "m2400s600" "m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600" @@ -223,14 +229,8 @@ TEST(TestSendPronto, RepeatSequenceOnlyForSony) { "m2400s600" "m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600" "m1200s600m600s600m1200s600m1200s600m1200s600m600s600m600s600m1200s600" - "m600s600m600s600m1200s600m600s25350", irsend.outputStr()); - - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(SONY, irsend.capture.decode_type); - EXPECT_EQ(SONY_20_BITS, irsend.capture.bits); - EXPECT_EQ(0x74B92, irsend.capture.value); - EXPECT_EQ(0x1A, irsend.capture.address); - EXPECT_EQ(0x24AE, irsend.capture.command); + "m600s600m600s600m1200s600m600s25350", + irsend.outputStr()); } // Test sending a Pronto code that only has a repeat sequence (Panasonic). @@ -241,25 +241,29 @@ TEST(TestSendPronto, RepeatSequenceOnlyForPanasonic) { // Panasonic Plasma TV Descrete code (Power On). uint16_t pronto_test[104] = { - 0x0000, 0x0071, 0x0000, 0x0032, - 0x0080, 0x003F, 0x0010, 0x0010, 0x0010, 0x0030, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0030, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0030, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0030, 0x0010, 0x0030, - 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0010, - 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0030, 0x0010, 0x0030, - 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0010, - 0x0010, 0x0030, 0x0010, 0x0A98}; + 0x0000, 0x0071, 0x0000, 0x0032, 0x0080, 0x003F, 0x0010, 0x0010, 0x0010, + 0x0030, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0030, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0030, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, + 0x0030, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0030, + 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, 0x0030, 0x0010, + 0x0010, 0x0010, 0x0030, 0x0010, 0x0A98}; // Send the Pronto code without any repeats set. irsend.reset(); irsend.sendPronto(pronto_test, 104); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x400401007C7D, irsend.capture.value); + EXPECT_EQ(0x4004, irsend.capture.address); + EXPECT_EQ(0x1007C7D, irsend.capture.command); EXPECT_EQ( "m3456s1701" "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" @@ -268,17 +272,10 @@ TEST(TestSendPronto, RepeatSequenceOnlyForPanasonic) { "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s432" "m432s432m432s1296m432s1296m432s1296m432s1296m432s1296m432s432m432s1296" - "m432s73224", irsend.outputStr()); - - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(PANASONIC, irsend.capture.decode_type); - EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); - EXPECT_EQ(0x400401007C7D, irsend.capture.value); - EXPECT_EQ(0x4004, irsend.capture.address); - EXPECT_EQ(0x1007C7D, irsend.capture.command); + "m432s73224", + irsend.outputStr()); } - // Test sending a Pronto code that has a normal & arepeat sequence (NEC). TEST(TestSendPronto, NormalPlusRepeatSequence) { IRsendTest irsend(4); @@ -287,40 +284,45 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) { // NEC 32 bit power on command. uint16_t pronto_test[76] = { - 0x0000, 0x006D, 0x0022, 0x0002, - 0x0156, 0x00AB, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, - 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0015, 0x0015, 0x0015, - 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0040, - 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, - 0x0015, 0x0040, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, - 0x0015, 0x0040, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, - 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0040, - 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0040, - 0x0015, 0x0040, 0x0015, 0x05FD, + 0x0000, 0x006D, 0x0022, 0x0002, 0x0156, 0x00AB, 0x0015, 0x0015, 0x0015, + 0x0015, 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0015, + 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, + 0x0040, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0040, 0x0015, 0x0040, + 0x0015, 0x0040, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, + 0x0040, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, + 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0015, 0x0015, + 0x0040, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x0040, 0x0015, 0x05FD, 0x0156, 0x0055, 0x0015, 0x0E4E}; // Send the Pronto code without any repeats set. irsend.reset(); irsend.sendPronto(pronto_test, 76); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x18E710EF, irsend.capture.value); + EXPECT_EQ(0x18, irsend.capture.address); + EXPECT_EQ(0x8, irsend.capture.command); EXPECT_EQ( "m8892s4446" "m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546" "m546s1664m546s1664m546s1664m546s546m546s546m546s1664m546s1664m546s1664" "m546s546m546s546m546s546m546s1664m546s546m546s546m546s546m546s546" "m546s1664m546s1664m546s1664m546s546m546s1664m546s1664m546s1664m546s1664" - "m546s39858", irsend.outputStr()); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); - EXPECT_EQ(0x18E710EF, irsend.capture.value); - EXPECT_EQ(0x18, irsend.capture.address); - EXPECT_EQ(0x8, irsend.capture.command); + "m546s39858", + irsend.outputStr()); // Send it again with a single repeat. irsend.reset(); irsend.sendPronto(pronto_test, 76, 1); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x18E710EF, irsend.capture.value); + EXPECT_EQ(0x18, irsend.capture.address); + EXPECT_EQ(0x8, irsend.capture.command); EXPECT_EQ( "m8892s4446" "m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546" @@ -328,18 +330,19 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) { "m546s546m546s546m546s546m546s1664m546s546m546s546m546s546m546s546" "m546s1664m546s1664m546s1664m546s546m546s1664m546s1664m546s1664m546s1664" "m546s39858" - "m8892s2210m546s95212", irsend.outputStr()); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); - EXPECT_EQ(0x18E710EF, irsend.capture.value); - EXPECT_EQ(0x18, irsend.capture.address); - EXPECT_EQ(0x8, irsend.capture.command); + "m8892s2210m546s95212", + irsend.outputStr()); // Send it again with a two repeats. irsend.reset(); irsend.sendPronto(pronto_test, 76, 2); irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x18E710EF, irsend.capture.value); + EXPECT_EQ(0x18, irsend.capture.address); + EXPECT_EQ(0x8, irsend.capture.command); EXPECT_EQ( "m8892s4446" "m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546" @@ -348,11 +351,6 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) { "m546s1664m546s1664m546s1664m546s546m546s1664m546s1664m546s1664m546s1664" "m546s39858" "m8892s2210m546s95212" - "m8892s2210m546s95212", irsend.outputStr()); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(NEC_BITS, irsend.capture.bits); - EXPECT_EQ(0x18E710EF, irsend.capture.value); - EXPECT_EQ(0x18, irsend.capture.address); - EXPECT_EQ(0x8, irsend.capture.command); + "m8892s2210m546s95212", + irsend.outputStr()); } diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_RC5_RC6_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_RC5_RC6_test.cpp similarity index 70% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_RC5_RC6_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_RC5_RC6_test.cpp index ef508e40e..e8aa9bfc1 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_RC5_RC6_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_RC5_RC6_test.cpp @@ -77,55 +77,59 @@ TEST(TestSendRC5, SendDataOnly) { irsend.begin(); irsend.reset(); - irsend.sendRC5(0x0, RC5_BITS); + irsend.sendRC5(0x0, kRC5Bits); EXPECT_EQ( "m889s889m1778s889m889s889m889s889m889s889m889s889m889" - "s889m889s889m889s889m889s889m889s889m889s889m889s114667", + "s889m889s889m889s889m889s889m889s889m889s889m889s90664", irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x1AAA, RC5_BITS); + irsend.sendRC5(0x1AAA, kRC5Bits); EXPECT_EQ( "m889s889m889s889m1778s1778m1778s1778m1778s1778" - "m1778s1778m1778s1778m1778s114667", irsend.outputStr()); + "m1778s1778m1778s1778m1778s90664", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x175, RC5_BITS); + irsend.sendRC5(0x175, kRC5Bits); EXPECT_EQ( "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + "m889s889m889s889m1778s1778m1778s1778m889s89775", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x3FFF, RC5_BITS); + irsend.sendRC5(0x3FFF, kRC5Bits); EXPECT_EQ( "m889s889m889s889m889s889m889s889m889s889m889s889m889s889" - "m889s889m889s889m889s889m889s889m889s889m889s889m889s113778", + "m889s889m889s889m889s889m889s889m889s889m889s889m889s89775", irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x0, RC5X_BITS); + irsend.sendRC5(0x0, kRC5XBits); EXPECT_EQ( "m889s889m1778s889m889s889m889s889m889s889m889s889m889" - "s889m889s889m889s889m889s889m889s889m889s889m889s114667", + "s889m889s889m889s889m889s889m889s889m889s889m889s90664", irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x1AAA, RC5X_BITS); + irsend.sendRC5(0x1AAA, kRC5XBits); EXPECT_EQ( "m1778s1778m1778s1778m1778s1778m1778" - "s1778m1778s1778m1778s1778m1778s114667", irsend.outputStr()); + "s1778m1778s1778m1778s1778m1778s90664", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x175, RC5X_BITS); + irsend.sendRC5(0x175, kRC5XBits); EXPECT_EQ( "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + "m889s889m889s889m1778s1778m1778s1778m889s89775", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x3FFF, RC5X_BITS); + irsend.sendRC5(0x3FFF, kRC5XBits); EXPECT_EQ( "m1778s1778m889s889m889s889m889s889m889s889m889s889m889" - "s889m889s889m889s889m889s889m889s889m889s889m889s113778", + "s889m889s889m889s889m889s889m889s889m889s889m889s89775", irsend.outputStr()); } @@ -135,40 +139,44 @@ TEST(TestSendRC5, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendRC5(0x175, RC5_BITS, 1); + irsend.sendRC5(0x175, kRC5Bits, 1); EXPECT_EQ( "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m889s889m1778s1778m1778s1778m889s90664" "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + "m889s889m889s889m1778s1778m1778s1778m889s88886", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x175, RC5_BITS, 2); + irsend.sendRC5(0x175, kRC5Bits, 2); EXPECT_EQ( "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m889s889m1778s1778m1778s1778m889s90664" "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m889s889m1778s1778m1778s1778m889s89775" "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + "m889s889m889s889m1778s1778m1778s1778m889s88886", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x175, RC5X_BITS, 1); + irsend.sendRC5(0x175, kRC5XBits, 1); EXPECT_EQ( "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m889s889m1778s1778m1778s1778m889s90664" "m889s889m1778s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + "m889s889m889s889m1778s1778m1778s1778m889s88886", + irsend.outputStr()); irsend.reset(); - irsend.sendRC5(0x1175, RC5X_BITS, 2); + irsend.sendRC5(0x1175, kRC5XBits, 2); EXPECT_EQ( "m1778s889m889s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m889s889m1778s1778m1778s1778m889s90664" "m1778s889m889s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m889s889m1778s1778m1778s1778m889s89775" "m1778s889m889s889m889s889m889s1778m1778s1778" - "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + "m889s889m889s889m1778s1778m1778s1778m889s88886", + irsend.outputStr()); } // Tests for decodeRC5(). @@ -182,9 +190,9 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRC5(0x175); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x05, irsend.capture.address); EXPECT_EQ(0x35, irsend.capture.command); @@ -194,9 +202,9 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRC5(0x175); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x05, irsend.capture.address); EXPECT_EQ(0x35, irsend.capture.command); @@ -205,11 +213,11 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { // A RC-5X 13-bit message but with a value that is valid for RC-5 decoded // as RC5-X. irsend.reset(); - irsend.sendRC5(0x175, RC5X_BITS); + irsend.sendRC5(0x175, kRC5XBits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x05, irsend.capture.address); EXPECT_EQ(0x35, irsend.capture.command); @@ -219,9 +227,9 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRC5(irsend.encodeRC5(0x00, 0x0B, true)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x80B, irsend.capture.value); EXPECT_EQ(0x00, irsend.capture.address); EXPECT_EQ(0x0B, irsend.capture.command); @@ -229,11 +237,11 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { // Synthesised Normal RC-5X 13-bit message. irsend.reset(); - irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), RC5X_BITS); + irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); EXPECT_EQ(RC5X, irsend.capture.decode_type); - EXPECT_EQ(RC5X_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5XBits, irsend.capture.bits); EXPECT_EQ(0x1881, irsend.capture.value); EXPECT_EQ(0x02, irsend.capture.address); EXPECT_EQ(0x41, irsend.capture.command); @@ -242,9 +250,9 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { // Synthesised Normal RC-5X 13-bit message should fail at being decoded // as a normal RC-5 (12 bit) message. irsend.reset(); - irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), RC5X_BITS); + irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); } // Decode normal repeated RC5 messages. @@ -255,33 +263,33 @@ TEST(TestDecodeRC5, NormalDecodeWithRepeatAndStrict) { // Normal RC-5 12-bit (even) message with one repeat. irsend.reset(); - irsend.sendRC5(0x174, RC5_BITS, 1); + irsend.sendRC5(0x174, kRC5Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); EXPECT_EQ(0x05, irsend.capture.address); EXPECT_EQ(0x34, irsend.capture.command); // Normal RC-5 12-bit (odd) message with one repeat. irsend.reset(); - irsend.sendRC5(0x175, RC5_BITS, 1); + irsend.sendRC5(0x175, kRC5Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); - EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x05, irsend.capture.address); EXPECT_EQ(0x35, irsend.capture.command); // Synthesised Normal RC-5X 13-bit message with 2 repeats. irsend.reset(); - irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), RC5X_BITS, 2); + irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); EXPECT_EQ(RC5X, irsend.capture.decode_type); - EXPECT_EQ(RC5X_BITS, irsend.capture.bits); + EXPECT_EQ(kRC5XBits, irsend.capture.bits); EXPECT_EQ(0x1881, irsend.capture.value); EXPECT_EQ(0x02, irsend.capture.address); EXPECT_EQ(0x41, irsend.capture.command); @@ -297,8 +305,8 @@ TEST(TestDecodeRC5, DecodeWithNonStrictValues) { irsend.sendRC5(0xFA, 8); // Illegal value RC5 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, 8, false)); EXPECT_EQ(RC5, irsend.capture.decode_type); @@ -311,8 +319,8 @@ TEST(TestDecodeRC5, DecodeWithNonStrictValues) { irsend.sendRC5(0x12345678, 32); // Illegal size RC5 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -327,8 +335,8 @@ TEST(TestDecodeRC5, DecodeWithNonStrictValues) { irsend.sendRC5(0x87654321, 32); // Illegal size RC5 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -364,14 +372,15 @@ TEST(TestDecodeRC5, FailToDecodeNonRC5Example) { irsend.begin(); irsend.reset(); - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, false)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, false)); } // RRRRRR CCCCC 666 @@ -383,24 +392,24 @@ TEST(TestDecodeRC5, FailToDecodeNonRC5Example) { // Tests for encodeRC6(). TEST(TestEncodeRC6, Mode0Encoding) { IRsendTest irsend(4); - EXPECT_EQ(0x0, irsend.encodeRC6(0, 0, RC6_MODE0_BITS)); - EXPECT_EQ(0x1234, irsend.encodeRC6(0x12, 0x34, RC6_MODE0_BITS)); - EXPECT_EQ(0x12345, irsend.encodeRC6(0x123, 0x45, RC6_MODE0_BITS)); - EXPECT_EQ(0xFFFFF, irsend.encodeRC6(0xFFF, 0xFF, RC6_MODE0_BITS)); - EXPECT_EQ(0xFFF00, irsend.encodeRC6(0xFFFF, 0x00, RC6_MODE0_BITS)); - EXPECT_EQ(0xFF, irsend.encodeRC6(0x00, 0xFF, RC6_MODE0_BITS)); + EXPECT_EQ(0x0, irsend.encodeRC6(0, 0, kRC6Mode0Bits)); + EXPECT_EQ(0x1234, irsend.encodeRC6(0x12, 0x34, kRC6Mode0Bits)); + EXPECT_EQ(0x12345, irsend.encodeRC6(0x123, 0x45, kRC6Mode0Bits)); + EXPECT_EQ(0xFFFFF, irsend.encodeRC6(0xFFF, 0xFF, kRC6Mode0Bits)); + EXPECT_EQ(0xFFF00, irsend.encodeRC6(0xFFFF, 0x00, kRC6Mode0Bits)); + EXPECT_EQ(0xFF, irsend.encodeRC6(0x00, 0xFF, kRC6Mode0Bits)); } TEST(TestEncodeRC6, 36BitEncoding) { IRsendTest irsend(4); - EXPECT_EQ(0x0, irsend.encodeRC6(0, 0, RC6_36_BITS)); - EXPECT_EQ(0x1234, irsend.encodeRC6(0x12, 0x34, RC6_36_BITS)); - EXPECT_EQ(0x123456789, irsend.encodeRC6(0x1234567, 0x89, RC6_36_BITS)); - EXPECT_EQ(0xFFFFFFFFF, irsend.encodeRC6(0xFFFFFFF, 0xFF, RC6_36_BITS)); - EXPECT_EQ(0xFFFFFFFFF, irsend.encodeRC6(0xFFFFFFFF, 0xFF, RC6_36_BITS)); - EXPECT_EQ(0xFFFFFFF00, irsend.encodeRC6(0xFFFFFFF, 0x00, RC6_36_BITS)); - EXPECT_EQ(0xFF, irsend.encodeRC6(0x0, 0xFF, RC6_36_BITS)); - EXPECT_EQ(0xFFFFFFFFF, irsend.encodeRC6(0xFFFFFFFF, 0xFF, RC6_36_BITS)); + EXPECT_EQ(0x0, irsend.encodeRC6(0, 0, kRC6_36Bits)); + EXPECT_EQ(0x1234, irsend.encodeRC6(0x12, 0x34, kRC6_36Bits)); + EXPECT_EQ(0x123456789, irsend.encodeRC6(0x1234567, 0x89, kRC6_36Bits)); + EXPECT_EQ(0xFFFFFFFFF, irsend.encodeRC6(0xFFFFFFF, 0xFF, kRC6_36Bits)); + EXPECT_EQ(0xFFFFFFFFF, irsend.encodeRC6(0xFFFFFFFF, 0xFF, kRC6_36Bits)); + EXPECT_EQ(0xFFFFFFF00, irsend.encodeRC6(0xFFFFFFF, 0x00, kRC6_36Bits)); + EXPECT_EQ(0xFF, irsend.encodeRC6(0x0, 0xFF, kRC6_36Bits)); + EXPECT_EQ(0xFFFFFFFFF, irsend.encodeRC6(0xFFFFFFFF, 0xFF, kRC6_36Bits)); } // Tests for toggleRC6(). @@ -410,7 +419,7 @@ TEST(TestToggleRC6, Mode0) { IRsendTest irsend(4); EXPECT_EQ(0x10000, irsend.toggleRC6(0x0)); - EXPECT_EQ(irsend.toggleRC6(0x0), irsend.toggleRC6(0x0, RC6_MODE0_BITS)); + EXPECT_EQ(irsend.toggleRC6(0x0), irsend.toggleRC6(0x0, kRC6Mode0Bits)); EXPECT_EQ(0x0, irsend.toggleRC6(0x10000)); EXPECT_EQ(0x0, irsend.toggleRC6(irsend.toggleRC6(0x0))); } @@ -419,10 +428,10 @@ TEST(TestToggleRC6, Mode0) { TEST(TestToggleRC6, 36BitUse) { IRsendTest irsend(4); - EXPECT_EQ(0x8000, irsend.toggleRC6(0x0, RC6_36_BITS)); - EXPECT_EQ(0x0, irsend.toggleRC6(0x8000, RC6_36_BITS)); - EXPECT_EQ(0x0, irsend.toggleRC6(irsend.toggleRC6(0x0, RC6_36_BITS), - RC6_36_BITS)); + EXPECT_EQ(0x8000, irsend.toggleRC6(0x0, kRC6_36Bits)); + EXPECT_EQ(0x0, irsend.toggleRC6(0x8000, kRC6_36Bits)); + EXPECT_EQ(0x0, + irsend.toggleRC6(irsend.toggleRC6(0x0, kRC6_36Bits), kRC6_36Bits)); } // Tests for sendRC6(). @@ -439,7 +448,8 @@ TEST(TestSendRC6, SendMode0DataOnly) { "m444s888m444s444m444s444m444s888m888s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444s444m444" - "s83028", irsend.outputStr()); + "s83028", + irsend.outputStr()); irsend.reset(); irsend.sendRC6(0x1FFFF); @@ -448,7 +458,8 @@ TEST(TestSendRC6, SendMode0DataOnly) { "m444s888m444s444m444s444m1332s888m444s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444" - "s83472", irsend.outputStr()); + "s83472", + irsend.outputStr()); irsend.reset(); irsend.sendRC6(0x15555); @@ -456,7 +467,8 @@ TEST(TestSendRC6, SendMode0DataOnly) { "m2664s888" "m444s888m444s444m444s444m1332s1332m888s888m888s888" "m888s888m888s888m888s888m888s888m888s888m888" - "s83472", irsend.outputStr()); + "s83472", + irsend.outputStr()); } // Test sending typical RC-6 36-bit data only. @@ -465,7 +477,7 @@ TEST(TestSendRC6, Send36BitDataOnly) { irsend.begin(); irsend.reset(); - irsend.sendRC6(0x0, RC6_36_BITS); + irsend.sendRC6(0x0, kRC6_36Bits); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" @@ -474,10 +486,11 @@ TEST(TestSendRC6, Send36BitDataOnly) { "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" - "s83028", irsend.outputStr()); + "s83028", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0xFFFFFFFFF, RC6_36_BITS); + irsend.sendRC6(0xFFFFFFFFF, kRC6_36Bits); EXPECT_EQ( "m2664s888" "m444s444m444s444m444s444m444s444" @@ -486,10 +499,11 @@ TEST(TestSendRC6, Send36BitDataOnly) { "m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" - "s83472", irsend.outputStr()); + "s83472", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0xAAAAAAAAAA, RC6_36_BITS); + irsend.sendRC6(0xAAAAAAAAAA, kRC6_36Bits); EXPECT_EQ( "m2664s888m444s444m444s888m888" "s1332m1332" @@ -498,7 +512,7 @@ TEST(TestSendRC6, Send36BitDataOnly) { irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0xC800F740C, RC6_36_BITS); // Xbox 360 OnOff code + irsend.sendRC6(0xC800F740C, kRC6_36Bits); // Xbox 360 OnOff code EXPECT_EQ( "m2664s888" "m444s444m444s444m444s888m444" @@ -506,10 +520,11 @@ TEST(TestSendRC6, Send36BitDataOnly) { "s888m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m888s444m444s444m444s444m444s888m888s444m444" "s444m444s888m888s888m444s444m444s444m444s444m444s444m444s444m888" - "s444m444s888m444s444m444s83028", irsend.outputStr()); + "s444m444s888m444s444m444s83028", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(irsend.toggleRC6(0xC800F740C, RC6_36_BITS), - RC6_36_BITS); // Xbox 360 OnOff code (toggled) + irsend.sendRC6(irsend.toggleRC6(0xC800F740C, kRC6_36Bits), + kRC6_36Bits); // Xbox 360 OnOff code (toggled) EXPECT_EQ( "m2664s888" "m444s444m444s444m444s888m444" @@ -517,7 +532,8 @@ TEST(TestSendRC6, Send36BitDataOnly) { "s888m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m888s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s888m888s888m444s444m444s444m444s444m444s444m444" - "s444m888s444m444s888m444s444m444s83028", irsend.outputStr()); + "s444m888s444m444s888m444s444m444s83028", + irsend.outputStr()); } // Test sending RC-6 Mode 0 with different repeats. @@ -526,16 +542,17 @@ TEST(TestSendRC6, SendMode0WithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendRC6(0x175, RC6_MODE0_BITS, 0); + irsend.sendRC6(0x175, kRC6Mode0Bits, 0); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" "s888m888" "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" - "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + "s444m444s444m444s888m888s888m888s83472", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0x175, RC6_MODE0_BITS, 1); + irsend.sendRC6(0x175, kRC6Mode0Bits, 1); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" @@ -546,10 +563,11 @@ TEST(TestSendRC6, SendMode0WithRepeats) { "m444s888m444s444m444s444m444" "s888m888" "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" - "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + "s444m444s444m444s888m888s888m888s83472", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0x175, RC6_MODE0_BITS, 2); + irsend.sendRC6(0x175, kRC6Mode0Bits, 2); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" @@ -565,7 +583,8 @@ TEST(TestSendRC6, SendMode0WithRepeats) { "m444s888m444s444m444s444m444" "s888m888" "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" - "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + "s444m444s444m444s888m888s888m888s83472", + irsend.outputStr()); } // Test sending RC-6 36-bit with different repeats. @@ -574,7 +593,7 @@ TEST(TestSendRC6, Send36BitWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendRC6(0x175, RC6_36_BITS, 0); + irsend.sendRC6(0x175, kRC6_36Bits, 0); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" @@ -582,10 +601,11 @@ TEST(TestSendRC6, Send36BitWithRepeats) { "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" - "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + "s444m444s444m444s888m888s888m888s83472", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0x175, RC6_36_BITS, 1); + irsend.sendRC6(0x175, kRC6_36Bits, 1); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" @@ -600,10 +620,11 @@ TEST(TestSendRC6, Send36BitWithRepeats) { "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" - "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + "s444m444s444m444s888m888s888m888s83472", + irsend.outputStr()); irsend.reset(); - irsend.sendRC6(0x175, RC6_36_BITS, 2); + irsend.sendRC6(0x175, kRC6_36Bits, 2); EXPECT_EQ( "m2664s888" "m444s888m444s444m444s444m444" @@ -625,7 +646,8 @@ TEST(TestSendRC6, Send36BitWithRepeats) { "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" - "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + "s444m444s444m444s888m888s888m888s83472", + irsend.outputStr()); } // Tests for decodeRC6(). @@ -640,9 +662,9 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithStrict) { irsend.reset(); irsend.sendRC6(0x175); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x01, irsend.capture.address); EXPECT_EQ(0x75, irsend.capture.command); @@ -650,11 +672,11 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithStrict) { // Normal Synthesised RC-6 Mode 0 (20-bit) message. irsend.reset(); - irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, RC6_MODE0_BITS)); + irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, kRC6Mode0Bits)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x56789, irsend.capture.value); EXPECT_EQ(0x567, irsend.capture.address); EXPECT_EQ(0x89, irsend.capture.command); @@ -662,11 +684,11 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithStrict) { // Same again, but encoded manually. irsend.reset(); - irsend.sendRC6(0x123456789, RC6_MODE0_BITS); + irsend.sendRC6(0x123456789, kRC6Mode0Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x56789, irsend.capture.value); EXPECT_EQ(0x567, irsend.capture.address); EXPECT_EQ(0x89, irsend.capture.command); @@ -681,11 +703,11 @@ TEST(TestDecodeRC6, Normal36BitDecodeWithStrict) { // Normal RC-6 36-bit message. irsend.reset(); - irsend.sendRC6(0x175, RC6_36_BITS); + irsend.sendRC6(0x175, kRC6_36Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x01, irsend.capture.address); EXPECT_EQ(0x75, irsend.capture.command); @@ -693,11 +715,11 @@ TEST(TestDecodeRC6, Normal36BitDecodeWithStrict) { // Normal Synthesised RC-6 36-bit message. irsend.reset(); - irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, RC6_36_BITS), RC6_36_BITS); + irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, kRC6_36Bits), kRC6_36Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x123456789, irsend.capture.value); EXPECT_EQ(0x1234567, irsend.capture.address); EXPECT_EQ(0x89, irsend.capture.command); @@ -712,22 +734,22 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithRepeatAndStrict) { // Normal RC-6 Mode 0 (20-bit) even message with one repeat. irsend.reset(); - irsend.sendRC6(0x174, RC6_MODE0_BITS, 1); + irsend.sendRC6(0x174, kRC6Mode0Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x74, irsend.capture.command); // Normal RC-6 Mode 0 (20-bit) odd message with one repeat. irsend.reset(); - irsend.sendRC6(0x175, RC6_MODE0_BITS, 1); + irsend.sendRC6(0x175, kRC6Mode0Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x75, irsend.capture.command); @@ -741,22 +763,22 @@ TEST(TestDecodeRC6, Normal36BitDecodeWithRepeatAndStrict) { // Normal RC-6 36-bit odd message with one repeat. irsend.reset(); - irsend.sendRC6(0x175, RC6_36_BITS, 1); + irsend.sendRC6(0x175, kRC6_36Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x75, irsend.capture.command); // Normal RC-6 36-bit even message with one repeat. irsend.reset(); - irsend.sendRC6(0x174, RC6_36_BITS, 1); + irsend.sendRC6(0x174, kRC6_36Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x74, irsend.capture.command); @@ -770,11 +792,11 @@ TEST(TestDecodeRC6, NormalDecodeWithoutStrict) { // Normal RC-6 Mode 0 (20-bit) message. irsend.reset(); - irsend.sendRC6(0x175, RC6_MODE0_BITS); + irsend.sendRC6(0x175, kRC6Mode0Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); EXPECT_EQ(0x01, irsend.capture.address); EXPECT_EQ(0x75, irsend.capture.command); @@ -782,11 +804,11 @@ TEST(TestDecodeRC6, NormalDecodeWithoutStrict) { // Normal RC-6 Mode 0 (20-bit) message. irsend.reset(); - irsend.sendRC6(0x174, RC6_MODE0_BITS); + irsend.sendRC6(0x174, kRC6Mode0Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); EXPECT_EQ(0x01, irsend.capture.address); EXPECT_EQ(0x74, irsend.capture.command); @@ -794,11 +816,11 @@ TEST(TestDecodeRC6, NormalDecodeWithoutStrict) { // Normal RC-6 36-bit message. irsend.reset(); - irsend.sendRC6(0x174, RC6_36_BITS); + irsend.sendRC6(0x174, kRC6_36Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); EXPECT_EQ(0x01, irsend.capture.address); EXPECT_EQ(0x74, irsend.capture.command); @@ -806,11 +828,11 @@ TEST(TestDecodeRC6, NormalDecodeWithoutStrict) { // Normal Synthesised RC-6 36-bit message. irsend.reset(); - irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, RC6_36_BITS), RC6_36_BITS); + irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, kRC6_36Bits), kRC6_36Bits); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x123456789, irsend.capture.value); EXPECT_EQ(0x1234567, irsend.capture.address); EXPECT_EQ(0x89, irsend.capture.command); @@ -825,17 +847,17 @@ TEST(TestDecodeRC6, Decode36BitGlobalCacheExample) { irsend.reset(); // Xbox-360 Power On from Global Cache. - uint16_t gc_test[65] = {36000, 1, 1, 96, 32, 16, 16, 16, 16, 16, 32, 16, 32, - 48, 32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 32, 16, 16, 16, - 16, 16, 16, 32, 32, 16, 16, 16, 16, 32, 32, 32, 16, - 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 16, 2476}; + uint16_t gc_test[65] = { + 36000, 1, 1, 96, 32, 16, 16, 16, 16, 16, 32, 16, 32, 48, 32, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 32, 16, 16, 16, 16, 16, 16, 32, 32, 16, 16, 16, 16, 32, 32, 32, + 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 16, 2476}; irsend.sendGC(gc_test, 65); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits)); EXPECT_EQ(RC6, irsend.capture.decode_type); - EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0xC800F742A, irsend.capture.value); EXPECT_EQ(0xC800F74, irsend.capture.address); EXPECT_EQ(0x2A, irsend.capture.command); @@ -849,25 +871,26 @@ TEST(TestDecodeRC5, FailToDecodeNonRC6Example) { irsend.begin(); irsend.reset(); - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, false)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, false)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, false)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, false)); irsend.reset(); irsend.sendRC5(0x0); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, false)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, false)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, false)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, false)); } diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_RCMM_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_RCMM_test.cpp similarity index 72% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_RCMM_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_RCMM_test.cpp index 2115dcb2e..028dbd8b3 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_RCMM_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_RCMM_test.cpp @@ -13,16 +13,20 @@ TEST(TestSendRCMM, SendDataOnly) { irsend.reset(); irsend.sendRCMM(0xe0a600); - EXPECT_EQ("m416s277" - "m166s777m166s611m166s277m166s277" - "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" - "m166s27778", irsend.outputStr()); + EXPECT_EQ( + "m416s277" + "m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s19600", + irsend.outputStr()); irsend.reset(); irsend.sendRCMM(0x28e0a600UL, 32); - EXPECT_EQ("m416s277" - "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" - "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" - "m166s27778", irsend.outputStr()); + EXPECT_EQ( + "m416s277" + "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s17160", + irsend.outputStr()); } // Test sending with different repeats. @@ -32,36 +36,42 @@ TEST(TestSendRCMM, SendWithRepeats) { irsend.reset(); irsend.sendRCMM(0x28e0a600, 32, 2); // 2 repeats. - EXPECT_EQ("m416s277" - "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" - "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" - "m166s27778" - "m416s277" - "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" - "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" - "m166s27778" - "m416s277" - "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" - "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" - "m166s27778", irsend.outputStr()); + EXPECT_EQ( + "m416s277" + "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s17160" + "m416s277" + "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s17160" + "m416s277" + "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s17160", + irsend.outputStr()); } // Test sending an atypical data size. -TEST(TestSendRCMM, SendUsualSize) { +TEST(TestSendRCMM, SendUnusualSize) { IRsendTest irsend(4); irsend.begin(); irsend.reset(); irsend.sendRCMM(0xE0, 8); - EXPECT_EQ("m416s277" - "m166s777m166s611m166s277m166s277" - "m166s27778", irsend.outputStr()); + EXPECT_EQ( + "m416s277" + "m166s777m166s611m166s277m166s277" + "m166s24313", + irsend.outputStr()); irsend.reset(); irsend.sendRCMM(0x28e0a60000UL, 40); - EXPECT_EQ("m416s277" - "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" - "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" - "m166s277m166s277m166s277m166s277m166s27778", irsend.outputStr()); + EXPECT_EQ( + "m416s277" + "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s277m166s277m166s277m166s277m166s15388", + irsend.outputStr()); } // Tests for decodeRCMM(). @@ -76,9 +86,9 @@ TEST(TestDecodeRCMM, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRCMM(0xe0a600); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, RCMM_BITS, true)); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, kRCMMBits, true)); EXPECT_EQ(RCMM, irsend.capture.decode_type); - EXPECT_EQ(RCMM_BITS, irsend.capture.bits); + EXPECT_EQ(kRCMMBits, irsend.capture.bits); EXPECT_EQ(0xe0a600, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -203,14 +213,15 @@ TEST(TestDecodeRCMM, FailToDecodeNonRCMMExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, RCMM_BITS, false)); + ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, kRCMMBits, false)); } // Issue 281 Debugging @@ -220,11 +231,12 @@ TEST(TestDecodeRCMM, DebugIssue281) { irsend.begin(); // Data from Issue #281 (shortened version) - uint16_t rawData[36] = {448, 276, 150, 285, 164, 613, 163, 447, 162, 613, - 164, 445, 164, 776, 167, 278, 163, 280, 163, 280, - 162, 611, 168, 444, 163, 612, 164, 277, 168, 447, - 157, 282, 165, 276, - 165, 65535}; // Last value modified from 89729 + uint16_t + rawData[36] = {448, 276, 150, 285, 164, 613, 163, 447, 162, 613, + 164, 445, 164, 776, 167, 278, 163, 280, 163, 280, + 162, 611, 168, 444, 163, 612, 164, 277, 168, 447, + 157, 282, 165, 276, 165, 65535}; // Last value modified + // from 89729 irsend.reset(); irsend.sendRaw(rawData, 36, 36); diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Samsung_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Samsung_test.cpp new file mode 100644 index 000000000..9ee1fcabb --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Samsung_test.cpp @@ -0,0 +1,907 @@ +// Copyright 2017 David Conran + +#include "ir_Samsung.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendSAMSUNG(). + +// Test sending typical data only. +TEST(TestSendSamsung, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSAMSUNG(0xE0E09966); // Samsung TV Power On. + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s560m560s47040", + irsend.outputStr()); + + irsend.reset(); +} + +// Test sending with different repeats. +TEST(TestSendSamsung, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSAMSUNG(0xE0E09966, kSamsungBits, 1); // 1 repeat. + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s560m560s47040" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s560m560s47040", + irsend.outputStr()); + irsend.sendSAMSUNG(0xE0E09966, kSamsungBits, 2); // 2 repeats. + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s560m560s47040" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s560m560s47040" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s560m560s560m560s1680m560s1680" + "m560s560m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s1680m560s1680m560s560m560s47040", + irsend.outputStr()); +} + +// Tests for encodeSAMSUNG(). + +TEST(TestEncodeSamsung, NormalEncoding) { + IRsendTest irsend(4); + EXPECT_EQ(0xFF, irsend.encodeSAMSUNG(0, 0)); + EXPECT_EQ(0x8080807F, irsend.encodeSAMSUNG(1, 1)); + EXPECT_EQ(0xF8F805FA, irsend.encodeSAMSUNG(0x1F, 0xA0)); + EXPECT_EQ(0xA0A0CC33, irsend.encodeSAMSUNG(0x05, 0x33)); + EXPECT_EQ(0xFFFFFF00, irsend.encodeSAMSUNG(0xFF, 0xFF)); + EXPECT_EQ(0xE0E09966, irsend.encodeSAMSUNG(0x07, 0x99)); +} + +// Tests for decodeSAMSUNG(). + +// Decode normal Samsung messages. +TEST(TestDecodeSamsung, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Samsung 32-bit message. + irsend.reset(); + irsend.sendSAMSUNG(0xE0E09966); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0xE0E09966, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); + + // Synthesised Normal Samsung 32-bit message. + irsend.reset(); + irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x07, 0x99)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0xE0E09966, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); + + // Synthesised Normal Samsung 32-bit message. + irsend.reset(); + irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x1, 0x1)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0x8080807F, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x1, irsend.capture.command); +} + +// Decode normal repeated Samsung messages. +TEST(TestDecodeSamsung, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Samsung 32-bit message. + irsend.reset(); + irsend.sendSAMSUNG(0xE0E09966, kSamsungBits, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0xE0E09966, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); +} + +// Decode unsupported Samsung messages. +TEST(TestDecodeSamsung, DecodeWithNonStrictValues) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSAMSUNG(0x0); // Illegal value Samsung 32-bit message. + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendSAMSUNG(0x12345678); // Illegal value Samsung 32-bit message. + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0x12345678, irsend.capture.value); + EXPECT_EQ(0x48, irsend.capture.address); + EXPECT_EQ(0x6A, irsend.capture.command); + + // Illegal over length (36-bit) message. + irsend.reset(); + irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0, 0), 36); + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + // Shouldn't pass if strict off and wrong expected bit size. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); + // Re-decode with correct bit size. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, 36, true)); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 36, false)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(36, irsend.capture.bits); + EXPECT_EQ(0xFF, irsend.capture.value); // We told it to expect 8 bits less. + EXPECT_EQ(0x00, irsend.capture.address); + EXPECT_EQ(0x00, irsend.capture.command); + + // Illegal under length (16-bit) message + irsend.reset(); + irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x0, 0x0), 16); + irsend.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + // And it should fail when we expect more bits. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); + + // Should pass if strict off if we ask for correct nr. of bits sent. + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 16, false)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(16, irsend.capture.bits); + EXPECT_EQ(0xFF, irsend.capture.value); // We told it to expect 4 bits less. + EXPECT_EQ(0x00, irsend.capture.address); + EXPECT_EQ(0x00, irsend.capture.command); + + // Should fail as we are expecting less bits than there are. + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, 12, false)); +} + +// Decode (non-standard) 64-bit messages. +// Decode unsupported Samsung messages. +TEST(TestDecodeSamsung, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal value & size Samsung 64-bit message. + irsend.sendSAMSUNG(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 64, false)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); + EXPECT_EQ(0xFF, irsend.capture.address); + EXPECT_EQ(0xFF, irsend.capture.command); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodeSamsung, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Samsung TV Power On from Global Cache. + uint16_t gc_test[71] = {38000, 1, 1, 172, 172, 22, 64, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 64, 22, + 64, 22, 64, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 64, 22, 21, 22, 21, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 64, 22, 21, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 64, 22, 64, 22, 21, 22, 1820}; + irsend.sendGC(gc_test, 71); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0xE0E09966, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); +} + +// Fail to decode a non-Samsung example via GlobalCache +TEST(TestDecodeSamsung, FailToDecodeNonSamsungExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Modified a few entries to unexpected values, based on previous test case. + uint16_t gc_test[71] = {38000, 1, 1, 172, 172, 22, 64, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 21, 22, 11, 22, 21, 22, 128, 22, + 64, 22, 64, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 64, 22, 21, 22, 21, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 64, 22, 21, 22, 64, 22, 64, 22, + 21, 22, 21, 22, 64, 22, 64, 22, 21, 22, 1820}; + irsend.sendGC(gc_test, 71); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); +} + +// Tests for sendSamsungAC(). + +// Test sending typical data only. +TEST(TestSendSamsungAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + uint8_t data[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0x02, 0xAF, + 0x71, 0x00, 0x15, 0xF0}; + irsend.sendSamsungAC(data); + EXPECT_EQ( + "m690s17844" + "m3086s8864" + "m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s1432m586s436m586s436m586s1432m586s436m586s436m586s1432" + "m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432" + "m586s2886" + "m3086s8864" + "m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s1432m586s1432m586s1432m586s1432m586s436m586s1432m586s436m586s1432" + "m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s1432m586s436m586s1432m586s436m586s1432m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s1432" + "m586s100000", + irsend.outputStr()); +} + +// Test sending extended data. +TEST(TestSendSamsungAC, SendExtendedData) { + IRsendTest irsend(0); + irsend.begin(); + // "Off" message. + uint8_t data[kSamsungAcExtendedStateLength] = { + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xD2, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0}; + irsend.sendSamsungAC(data, kSamsungAcExtendedStateLength); + EXPECT_EQ( + "m690s17844" + "m3086s8864" + "m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s1432m586s436m586s436m586s1432m586s1432m586s436m586s1432" + "m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s1432m586s1432" + "m586s2886" + "m3086s8864" + "m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s1432m586s436m586s436m586s1432m586s436m586s1432m586s1432" + "m586s1432m586s1432m586s1432m586s1432m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s2886" + "m3086s8864" + "m586s1432m586s436m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436" + "m586s1432m586s1432m586s1432m586s1432m586s1432m586s1432m586s1432m586s1432" + "m586s1432m586s436m586s436m586s436m586s1432m586s1432m586s1432m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s436m586s1432" + "m586s1432m586s436m586s436m586s436m586s1432m586s436m586s436m586s436" + "m586s436m586s436m586s436m586s436m586s436m586s436m586s1432m586s1432" + "m586s100000", + irsend.outputStr()); +} + +// Tests for IRSamsungAc class. + +TEST(TestIRSamsungAcClass, SetAndGetRaw) { + uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0xE2, 0xFE, + 0x71, 0x40, 0x11, 0xF0}; + IRSamsungAc samsung(0); + samsung.setRaw(expectedState); + EXPECT_STATE_EQ(expectedState, samsung.getRaw(), kSamsungAcBits); + uint8_t extendedState[kSamsungAcExtendedStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0xD2, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xE2, 0xFE, 0x71, 0x40, 0x11, 0xF0}; + samsung.setRaw(extendedState, kSamsungAcExtendedStateLength); + // We should NOT get the extended state back. + EXPECT_STATE_EQ(expectedState, samsung.getRaw(), kSamsungAcBits); +} + +TEST(TestIRSamsungAcClass, SetAndGetPower) { + IRSamsungAc samsung(0); + samsung.on(); + EXPECT_TRUE(samsung.getPower()); + samsung.off(); + EXPECT_FALSE(samsung.getPower()); + samsung.setPower(true); + EXPECT_TRUE(samsung.getPower()); + samsung.setPower(false); + EXPECT_FALSE(samsung.getPower()); +} + +TEST(TestIRSamsungAcClass, SetAndGetSwing) { + IRSamsungAc samsung(0); + samsung.setSwing(true); + EXPECT_TRUE(samsung.getSwing()); + samsung.setSwing(false); + EXPECT_FALSE(samsung.getSwing()); + samsung.setSwing(true); + EXPECT_TRUE(samsung.getSwing()); + + // Real examples from: + // https://github.com/markszabo/IRremoteESP8266/issues/505#issuecomment-424036602 + // TODO(Hollako): Explain why state[9] lowest bit changes between on and off. + const uint8_t expected_off[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0}; + samsung.setRaw(expected_off); + EXPECT_FALSE(samsung.getSwing()); + const uint8_t expected_on[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0x02, 0xAF, 0x71, 0x80, 0x11, 0xF0}; + samsung.setRaw(expected_on); + EXPECT_TRUE(samsung.getSwing()); +} + +TEST(TestIRSamsungAcClass, SetAndGetClean) { + IRSamsungAc samsung(0); + samsung.setClean(true); + EXPECT_TRUE(samsung.getClean()); + samsung.setClean(false); + EXPECT_FALSE(samsung.getClean()); + samsung.setClean(true); + EXPECT_TRUE(samsung.getClean()); +} + +TEST(TestIRSamsungAcClass, SetAndGetBeep) { + IRSamsungAc samsung(0); + samsung.setBeep(false); + EXPECT_FALSE(samsung.getBeep()); + samsung.setBeep(true); + EXPECT_TRUE(samsung.getBeep()); + samsung.setBeep(false); + EXPECT_FALSE(samsung.getBeep()); + samsung.setBeep(true); + EXPECT_TRUE(samsung.getBeep()); +} + +TEST(TestIRSamsungAcClass, SetAndGetTemp) { + IRSamsungAc samsung(0); + samsung.setTemp(25); + EXPECT_EQ(25, samsung.getTemp()); + samsung.setTemp(kSamsungAcMinTemp); + EXPECT_EQ(kSamsungAcMinTemp, samsung.getTemp()); + samsung.setTemp(kSamsungAcMinTemp - 1); + EXPECT_EQ(kSamsungAcMinTemp, samsung.getTemp()); + samsung.setTemp(kSamsungAcMaxTemp); + EXPECT_EQ(kSamsungAcMaxTemp, samsung.getTemp()); + samsung.setTemp(kSamsungAcMaxTemp + 1); + EXPECT_EQ(kSamsungAcMaxTemp, samsung.getTemp()); +} + +TEST(TestIRSamsungAcClass, SetAndGetMode) { + IRSamsungAc samsung(0); + samsung.setMode(kSamsungAcCool); + EXPECT_EQ(kSamsungAcCool, samsung.getMode()); + EXPECT_NE(kSamsungAcFanAuto2, samsung.getFan()); + samsung.setMode(kSamsungAcHeat); + EXPECT_EQ(kSamsungAcHeat, samsung.getMode()); + EXPECT_NE(kSamsungAcFanAuto2, samsung.getFan()); + samsung.setMode(kSamsungAcAuto); + EXPECT_EQ(kSamsungAcAuto, samsung.getMode()); + EXPECT_EQ(kSamsungAcFanAuto2, samsung.getFan()); + samsung.setMode(kSamsungAcDry); + EXPECT_EQ(kSamsungAcDry, samsung.getMode()); + EXPECT_NE(kSamsungAcFanAuto2, samsung.getFan()); +} + +TEST(TestIRSamsungAcClass, SetAndGetFan) { + IRSamsungAc samsung(0); + samsung.setMode(kSamsungAcCool); // Most fan modes avail in this setting. + samsung.setFan(kSamsungAcFanAuto); + EXPECT_EQ(kSamsungAcFanAuto, samsung.getFan()); + samsung.setFan(kSamsungAcFanLow); + EXPECT_EQ(kSamsungAcFanLow, samsung.getFan()); + samsung.setFan(kSamsungAcFanAuto2); // Not available in Cool mode. + EXPECT_EQ(kSamsungAcFanLow, samsung.getFan()); // Shouldn't change. + samsung.setMode(kSamsungAcAuto); // Has special fan setting. + EXPECT_EQ(kSamsungAcFanAuto2, samsung.getFan()); + samsung.setFan(kSamsungAcFanLow); // Shouldn't be available in Auto mode. + EXPECT_EQ(kSamsungAcFanAuto2, samsung.getFan()); + samsung.setMode(kSamsungAcHeat); // Most fan modes avail in this setting. + samsung.setFan(kSamsungAcFanHigh); + EXPECT_EQ(kSamsungAcFanHigh, samsung.getFan()); +} + +TEST(TestIRSamsungAcClass, SetAndGetQuiet) { + IRSamsungAc samsung(0); + samsung.setQuiet(false); + EXPECT_FALSE(samsung.getQuiet()); + samsung.setFan(kSamsungAcFanHigh); + samsung.setQuiet(true); + EXPECT_TRUE(samsung.getQuiet()); + EXPECT_EQ(kSamsungAcFanAuto, samsung.getFan()); + samsung.setQuiet(false); + EXPECT_FALSE(samsung.getQuiet()); +} + +TEST(TestIRSamsungAcClass, ChecksumCalculation) { + IRSamsungAc samsung(0); + + const uint8_t originalstate[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0x02, 0xAF, 0x71, 0x00, 0x15, 0xF0}; + uint8_t examplestate[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0x02, 0xAF, + 0x71, 0x00, 0x15, 0xF0}; + + EXPECT_TRUE(IRSamsungAc::validChecksum(examplestate)); + EXPECT_EQ(0, IRSamsungAc::calcChecksum(examplestate)); + + examplestate[8] = 0x12; // Set an incoorect checksum. + EXPECT_FALSE(IRSamsungAc::validChecksum(examplestate)); + EXPECT_EQ(0, IRSamsungAc::calcChecksum(examplestate)); + samsung.setRaw(examplestate); + // Extracting the state from the object should have a correct checksum. + EXPECT_TRUE(IRSamsungAc::validChecksum(samsung.getRaw())); + EXPECT_STATE_EQ(originalstate, samsung.getRaw(), kSamsungAcBits); + examplestate[8] = 0x02; // Restore old checksum value. + + // Change the state to force a different checksum. + examplestate[11] = 0x01; + EXPECT_FALSE(IRSamsungAc::validChecksum(examplestate)); + EXPECT_EQ(0xF, IRSamsungAc::calcChecksum(examplestate)); +} + +TEST(TestIRSamsungAcClass, HumanReadable) { + IRSamsungAc samsung(0); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 2 (LOW), Swing: On, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); + samsung.setTemp(kSamsungAcMaxTemp); + samsung.setMode(kSamsungAcHeat); + samsung.off(); + samsung.setFan(kSamsungAcFanHigh); + samsung.setSwing(false); + samsung.setBeep(true); + samsung.setClean(true); + EXPECT_EQ( + "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 5 (HIGH), Swing: Off, " + "Beep: On, Clean: On, Quiet: Off", + samsung.toString()); + samsung.setQuiet(true); + EXPECT_EQ( + "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 0 (AUTO), Swing: Off, " + "Beep: On, Clean: On, Quiet: On", + samsung.toString()); +} + +TEST(TestIRSamsungAcClass, GeneralConstruction) { + IRSamsungAc samsung(0); + + uint8_t OnCoolFAutoBOffCOffQOffT20Soff[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xE2, 0xFE, 0x71, 0x40, 0x11, 0xF0}; + + samsung.setPower(true); + samsung.setMode(kSamsungAcCool); + samsung.setFan(kSamsungAcFanAuto); + samsung.setSwing(false); + samsung.setBeep(false); + samsung.setClean(false); + samsung.setQuiet(false); + samsung.setTemp(20); + EXPECT_STATE_EQ(OnCoolFAutoBOffCOffQOffT20Soff, samsung.getRaw(), + kSamsungAcBits); + /* Disabled until we understand why LSB bit of the swing byte changes. + // TODO(Hollako): Explain why sometimes the LSB of state[9] is a 1. + // e.g. 0xAE or 0XAF for swing move. + uint8_t OnHeatFAutoBOffCOffQOffT17Son[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0x02, 0xAF, 0x71, 0x10, 0x41, 0xF0}; + samsung.setPower(true); + samsung.setMode(kSamsungAcHeat); + samsung.setFan(kSamsungAcFanAuto); + samsung.setSwing(true); + samsung.setBeep(false); + samsung.setClean(false); + samsung.setQuiet(false); + samsung.setTemp(17); + EXPECT_STATE_EQ(OnHeatFAutoBOffCOffQOffT17Son, samsung.getRaw(), + kSamsungAcBits); + */ +} +// Tests for decodeSamsungAC(). + +// Decode normal SamsungAC messages. +TEST(TestDecodeSamsungAC, SyntheticDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + irsend.reset(); + uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0x02, 0xAF, + 0x71, 0x00, 0x15, 0xF0}; + // Synthesised Normal Samsung A/C message. + irsend.sendSamsungAC(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decode a real Samsung A/C example from Issue #505 +TEST(TestDecodeSamsungAC, DecodeRealExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Samsung A/C example from Issue #505 + uint16_t rawData[233] = { + 690, 17844, 3084, 8864, 606, 406, 586, 1410, 580, 436, 570, 424, + 570, 426, 570, 404, 596, 418, 580, 416, 584, 410, 586, 1402, + 588, 408, 586, 410, 584, 1380, 610, 408, 586, 408, 586, 1404, + 586, 1404, 586, 1408, 594, 1396, 596, 1394, 602, 418, 582, 410, + 586, 408, 584, 408, 586, 408, 586, 410, 586, 408, 586, 410, + 586, 408, 586, 408, 586, 408, 586, 408, 586, 410, 584, 436, + 558, 436, 570, 424, 570, 424, 574, 420, 578, 416, 582, 412, + 586, 410, 586, 408, 584, 410, 586, 408, 586, 410, 584, 410, + 584, 408, 586, 408, 586, 410, 586, 408, 586, 412, 584, 436, + 556, 1410, 592, 1396, 602, 1390, 608, 1384, 608, 2886, 3086, 8858, + 610, 1380, 610, 410, 586, 408, 586, 410, 586, 408, 586, 410, + 586, 408, 586, 436, 558, 436, 554, 1410, 594, 426, 572, 422, + 578, 418, 582, 412, 586, 410, 584, 410, 586, 1380, 610, 1382, + 608, 1404, 586, 1404, 586, 408, 586, 1432, 558, 436, 554, 1414, + 590, 1398, 602, 418, 580, 414, 586, 410, 584, 1382, 606, 1382, + 608, 1382, 608, 408, 586, 408, 586, 408, 586, 408, 586, 410, + 584, 436, 560, 434, 570, 426, 566, 430, 568, 1400, 600, 416, + 584, 1406, 586, 410, 584, 1384, 606, 410, 586, 410, 584, 408, + 586, 408, 586, 408, 586, 408, 588, 410, 584, 1408, 590, 1400, + 592, 1398, 602, 1388, 612}; + uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0x02, 0xAF, + 0x71, 0x00, 0x15, 0xF0}; + + irsend.sendRaw(rawData, 233, 38000); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 16C, Fan: 2 (LOW), Swing: On, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} + +// Decode a real Samsung A/C example from Issue #505 +TEST(TestDecodeSamsungAC, DecodeRealExample2) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Samsung A/C example from Issue #505 + uint16_t rawData[233] = { + 668, 17834, 3092, 8862, 608, 410, 586, 1378, 612, 410, 584, 410, + 586, 410, 584, 410, 586, 408, 586, 408, 586, 410, 586, 1404, + 588, 436, 558, 436, 570, 1398, 592, 424, 576, 420, 578, 1388, + 608, 1382, 610, 1382, 608, 1380, 610, 1384, 606, 408, 586, 408, + 588, 408, 588, 408, 586, 436, 558, 436, 570, 424, 570, 426, + 572, 422, 578, 418, 582, 412, 586, 408, 586, 410, 584, 410, + 584, 410, 584, 410, 586, 410, 586, 408, 586, 408, 586, 408, + 586, 408, 586, 408, 586, 438, 558, 436, 568, 426, 570, 424, + 574, 422, 576, 418, 582, 414, 584, 410, 586, 410, 584, 410, + 586, 1380, 610, 1382, 608, 1404, 586, 1404, 602, 2872, 3096, 8878, + 582, 1432, 570, 426, 568, 426, 574, 420, 578, 416, 582, 412, + 586, 410, 584, 410, 586, 410, 586, 1382, 608, 410, 586, 410, + 586, 408, 586, 1404, 586, 1408, 582, 1410, 590, 428, 568, 1400, + 598, 1394, 606, 1382, 610, 1382, 608, 1378, 612, 1382, 608, 1384, + 606, 1404, 586, 408, 586, 414, 582, 436, 558, 1410, 590, 1422, + 576, 1390, 608, 410, 586, 410, 586, 410, 584, 410, 584, 410, + 586, 410, 586, 410, 584, 410, 586, 1404, 586, 1404, 588, 436, + 560, 436, 486, 510, 566, 1400, 598, 420, 576, 418, 582, 414, + 586, 410, 584, 410, 584, 410, 586, 410, 584, 1382, 608, 1384, + 606, 1384, 606, 1408, 600}; + uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0xE2, 0xFE, + 0x71, 0x80, 0x11, 0xF0}; + + irsend.sendRaw(rawData, 233, 38000); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 0 (AUTO), Swing: Off, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} + +// Decode a real Samsung A/C example from: +// https://github.com/markszabo/IRremoteESP8266/issues/505#issuecomment-424036602 +TEST(TestDecodeSamsungAC, DecodePowerOnSample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[349] = { + 662, 17870, 3026, 8966, 540, 484, 514, 1482, 518, 482, 514, 482, + 518, 482, 516, 510, 490, 508, 490, 508, 572, 428, 576, 1398, + 542, 482, 514, 484, 514, 1460, 540, 482, 518, 482, 516, 1456, + 544, 1480, 518, 1480, 518, 1480, 518, 1484, 514, 510, 566, 432, + 576, 424, 574, 426, 540, 458, 516, 482, 516, 482, 516, 482, + 518, 480, 518, 482, 518, 482, 518, 482, 516, 482, 518, 482, + 516, 482, 518, 480, 516, 508, 492, 508, 490, 508, 572, 428, + 576, 422, 572, 428, 542, 456, 514, 484, 518, 480, 518, 480, + 518, 480, 516, 482, 516, 482, 520, 478, 518, 482, 518, 480, + 518, 1480, 518, 1480, 516, 1484, 594, 1428, 518, 2964, 3032, 8964, + 540, 1458, 542, 480, 518, 480, 520, 480, 518, 482, 520, 480, + 520, 478, 518, 480, 520, 478, 520, 1478, 522, 478, 518, 506, + 494, 1484, 594, 426, 574, 1400, 564, 1434, 540, 1454, 544, 1478, + 520, 1454, 544, 1458, 540, 480, 520, 480, 518, 480, 520, 480, + 518, 508, 490, 506, 568, 432, 572, 426, 576, 424, 544, 454, + 518, 480, 516, 482, 520, 478, 520, 478, 522, 478, 518, 480, + 520, 478, 520, 478, 520, 478, 520, 478, 520, 478, 518, 478, + 522, 506, 494, 504, 566, 432, 576, 424, 576, 424, 570, 428, + 518, 482, 518, 480, 518, 482, 520, 478, 520, 478, 520, 480, + 520, 478, 520, 478, 520, 2964, 3032, 8986, 520, 1478, 520, 506, + 492, 506, 492, 506, 568, 430, 574, 424, 546, 454, 516, 482, + 518, 482, 518, 1456, 544, 478, 546, 452, 520, 478, 544, 1432, + 542, 1478, 520, 1478, 520, 478, 520, 1482, 586, 1412, 598, 1400, + 564, 1432, 540, 1458, 544, 1454, 544, 1454, 544, 1456, 542, 480, + 518, 480, 520, 480, 520, 1462, 536, 1482, 588, 1410, 598, 424, + 572, 426, 542, 456, 518, 482, 520, 478, 520, 478, 522, 478, + 520, 478, 520, 1456, 542, 1458, 540, 478, 520, 478, 520, 478, + 520, 1482, 540, 482, 568, 430, 576, 424, 570, 428, 542, 458, + 518, 480, 520, 480, 520, 1454, 568, 1430, 566, 1432, 566, 1454, + 594}; + uint8_t expectedState[kSamsungAcExtendedStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0xD2, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0}; + + irsend.sendRaw(rawData, 349, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcExtendedBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state, kSamsungAcExtendedStateLength); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 24C, Fan: 0 (AUTO), Swing: Off, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} + +// Decode a real Samsung A/C example from: +// https://github.com/markszabo/IRremoteESP8266/issues/505#issuecomment-424036602 +TEST(TestDecodeSamsungAC, DecodePowerOffSample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[349] = { + 670, 17802, 3096, 8898, 602, 420, 580, 1418, 582, 418, 582, 416, + 582, 416, 584, 442, 550, 448, 568, 430, 570, 430, 576, 1396, + 600, 424, 546, 452, 578, 1394, 604, 1396, 600, 420, 580, 1398, + 602, 1416, 586, 1412, 582, 1420, 576, 1422, 592, 428, 574, 424, + 576, 422, 578, 420, 548, 452, 578, 420, 578, 420, 584, 416, + 580, 418, 580, 418, 582, 418, 580, 418, 582, 414, 584, 414, + 584, 416, 582, 418, 584, 442, 558, 442, 568, 430, 576, 424, + 578, 420, 576, 424, 576, 422, 580, 420, 584, 414, 584, 416, + 584, 414, 582, 418, 580, 418, 582, 416, 582, 416, 584, 414, + 584, 414, 586, 442, 554, 1420, 570, 1452, 578, 2884, 3120, 8898, + 596, 1400, 602, 422, 582, 418, 584, 414, 582, 416, 584, 414, + 584, 416, 582, 416, 584, 416, 584, 1410, 586, 414, 582, 444, + 556, 1420, 590, 432, 572, 1402, 602, 1396, 600, 1398, 606, 1414, + 582, 1394, 604, 1394, 604, 414, 584, 414, 586, 412, 586, 410, + 586, 442, 556, 440, 544, 456, 568, 430, 576, 424, 578, 420, + 578, 420, 576, 424, 584, 412, 586, 412, 586, 412, 584, 414, + 586, 412, 584, 414, 586, 412, 586, 412, 586, 414, 586, 412, + 584, 442, 558, 442, 558, 440, 566, 432, 574, 424, 578, 422, + 576, 422, 578, 420, 586, 414, 586, 414, 586, 412, 584, 414, + 586, 414, 586, 414, 586, 2902, 3096, 8900, 600, 1416, 586, 442, + 556, 442, 558, 440, 564, 434, 572, 428, 578, 420, 580, 420, + 578, 420, 584, 1392, 608, 414, 586, 414, 582, 414, 586, 412, + 586, 412, 586, 414, 584, 1394, 606, 1416, 580, 1418, 568, 1432, + 594, 1402, 602, 1398, 606, 1392, 606, 1390, 608, 1390, 608, 414, + 584, 414, 586, 414, 584, 1412, 586, 1398, 600, 1418, 590, 430, + 566, 432, 576, 422, 578, 420, 578, 422, 582, 416, 586, 414, + 586, 412, 584, 1390, 606, 1392, 608, 414, 586, 412, 584, 412, + 588, 1410, 586, 442, 558, 440, 568, 430, 566, 434, 574, 426, + 578, 420, 578, 420, 582, 416, 586, 412, 586, 1390, 608, 1390, + 608}; + + uint8_t expectedState[kSamsungAcExtendedStateLength] = { + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xD2, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0}; + + irsend.sendRaw(rawData, 349, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcExtendedBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state, kSamsungAcExtendedStateLength); + EXPECT_EQ( + "Power: Off, Mode: 1 (COOL), Temp: 24C, Fan: 0 (AUTO), Swing: Off, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} + +TEST(TestDecodeSamsungAC, DecodeHeatSample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[233] = { + 650, 16260, 3014, 8934, 534, 486, 508, 1478, 514, 484, 510, 486, + 508, 512, 484, 510, 562, 432, 572, 422, 540, 454, 514, 1452, + 534, 486, 510, 484, 510, 1456, 536, 484, 510, 484, 510, 1454, + 536, 1478, 512, 1476, 514, 1482, 508, 1482, 592, 428, 570, 424, + 538, 456, 508, 486, 510, 484, 512, 484, 510, 486, 510, 484, + 510, 484, 510, 486, 510, 484, 510, 484, 510, 484, 510, 484, + 510, 484, 510, 486, 508, 510, 484, 510, 568, 428, 570, 424, + 538, 458, 512, 482, 510, 486, 510, 484, 510, 484, 510, 484, + 510, 484, 510, 484, 510, 484, 510, 484, 510, 484, 510, 484, + 510, 1474, 516, 1502, 534, 1432, 594, 1398, 536, 2954, 3018, 8932, + 536, 1458, 532, 484, 510, 484, 512, 484, 510, 484, 510, 484, + 510, 484, 512, 484, 510, 484, 510, 1480, 508, 510, 530, 464, + 568, 426, 568, 426, 514, 480, 508, 486, 508, 1456, 534, 1478, + 514, 1452, 538, 1478, 512, 484, 510, 1456, 534, 486, 510, 1478, + 512, 1480, 570, 450, 570, 424, 540, 454, 512, 1452, 534, 1458, + 534, 1454, 536, 484, 512, 482, 512, 484, 512, 484, 512, 482, + 512, 1474, 514, 484, 512, 510, 486, 508, 534, 1430, 594, 426, + 512, 482, 512, 482, 510, 484, 512, 482, 512, 1452, 538, 482, + 512, 482, 512, 482, 510, 484, 510, 484, 510, 1478, 512, 1504, + 488, 1480, 560, 1454, 514}; + + uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0x02, 0xAF, + 0x71, 0x10, 0x41, 0xF0}; + + irsend.sendRaw(rawData, 233, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 4 (HEAT), Temp: 17C, Fan: 0 (AUTO), Swing: On, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} + +TEST(TestDecodeSamsungAC, DecodeCoolSample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[233] = { + 690, 17854, 3086, 8862, 610, 410, 584, 1382, 610, 410, 586, 408, + 586, 408, 586, 408, 588, 410, 584, 436, 558, 436, 570, 1396, + 598, 422, 576, 418, 580, 1384, 612, 410, 586, 410, 584, 1380, + 612, 1382, 608, 1384, 606, 1404, 586, 1404, 586, 436, 558, 438, + 566, 428, 568, 426, 570, 424, 576, 418, 578, 416, 584, 410, + 586, 408, 584, 410, 586, 408, 586, 408, 586, 410, 586, 408, + 586, 408, 588, 408, 586, 408, 588, 408, 586, 438, 558, 436, + 568, 426, 568, 428, 568, 426, 576, 418, 578, 416, 584, 412, + 584, 410, 586, 408, 586, 410, 586, 410, 584, 410, 586, 408, + 586, 1384, 606, 1402, 588, 1410, 580, 1410, 608, 2864, 3108, 8864, + 594, 1394, 604, 416, 584, 410, 586, 410, 586, 410, 586, 410, + 584, 410, 586, 410, 586, 408, 586, 1404, 588, 408, 586, 408, + 586, 436, 560, 1408, 592, 1400, 596, 1396, 600, 416, 584, 1382, + 608, 1380, 610, 1404, 586, 1384, 608, 1384, 606, 1402, 588, 1408, + 582, 1410, 564, 452, 568, 428, 572, 424, 576, 1414, 582, 1386, + 608, 1382, 608, 410, 584, 410, 584, 410, 586, 408, 586, 408, + 586, 408, 586, 408, 588, 1408, 582, 436, 540, 1426, 590, 428, + 574, 420, 578, 418, 580, 1384, 610, 410, 584, 410, 584, 410, + 584, 412, 584, 408, 586, 410, 586, 408, 586, 1404, 586, 1408, + 582, 1410, 562, 1426, 610}; + + uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, + 0x00, 0xF0, 0x01, 0xE2, 0xFE, + 0x71, 0x40, 0x11, 0xF0}; + + irsend.sendRaw(rawData, 233, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 20C, Fan: 0 (AUTO), Swing: Off, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sanyo_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sanyo_test.cpp similarity index 63% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Sanyo_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Sanyo_test.cpp index 9442f3db5..14c1c7da0 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sanyo_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sanyo_test.cpp @@ -4,7 +4,6 @@ #include "IRsend_test.h" #include "gtest/gtest.h" - // Tests for encodeSanyoLC7461(). TEST(TestEncodeSanyoLC7461, NormalEncoding) { @@ -34,7 +33,8 @@ TEST(TestEncodeSanyoLC7461, SendDataOnly) { "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s108080", irsend.outputStr()); + "m560s1680m560s1680m560s23520", + irsend.outputStr()); } // Test sending with different repeats. @@ -43,7 +43,7 @@ TEST(TestEncodeSanyoLC7461, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendSanyoLC7461(0x1D8113F00FF, SANYO_LC7461_BITS, 1); // 1 repeat. + irsend.sendSanyoLC7461(0x1D8113F00FF, kSanyoLC7461Bits, 1); // 1 repeat. EXPECT_EQ( "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" @@ -51,8 +51,9 @@ TEST(TestEncodeSanyoLC7461, SendWithRepeats) { "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" - "m560s1680m560s1680m560s108080" - "m8960s2240m560s108080", irsend.outputStr()); + "m560s1680m560s1680m560s23520" + "m8960s2240m560s96320", + irsend.outputStr()); } // Tests for decodeSanyoLC7461(). @@ -67,10 +68,10 @@ TEST(TestDecodeSanyoLC7461, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSanyoLC7461(0x1D8113F00FF); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); EXPECT_EQ(0xEC0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -80,10 +81,10 @@ TEST(TestDecodeSanyoLC7461, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSanyoLC7461(irsend.encodeSanyoLC7461(0x1234, 0x56)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x2468DCB56A9, irsend.capture.value); EXPECT_EQ(0x1234, irsend.capture.address); EXPECT_EQ(0x56, irsend.capture.command); @@ -93,10 +94,10 @@ TEST(TestDecodeSanyoLC7461, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSanyoLC7461(irsend.encodeSanyoLC7461(0x1, 0x1)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x3FFE01FE, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x1, irsend.capture.command); @@ -111,12 +112,12 @@ TEST(TestDecodeSanyoLC7461, NormalDecodeWithRepeatAndStrict) { // Normal Sanyo LC7461 16-bit message with 1 repeat. irsend.reset(); - irsend.sendSanyoLC7461(0x3FFE01FE, SANYO_LC7461_BITS, 1); + irsend.sendSanyoLC7461(0x3FFE01FE, kSanyoLC7461Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x3FFE01FE, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x1, irsend.capture.command); @@ -133,13 +134,13 @@ TEST(TestDecodeSanyoLC7461, DecodeWithNonStrictValues) { irsend.sendSanyoLC7461(0x0); // Illegal value Sanyo LC7461 message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_FALSE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - false)); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, false)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -148,22 +149,20 @@ TEST(TestDecodeSanyoLC7461, DecodeWithNonStrictValues) { // Illegal value Sanyo LC7461 42-bit message. irsend.sendSanyoLC7461(0x1234567890A); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_FALSE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, 32, - true)); - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, 64, - true)); + ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, 64, true)); // And should fail for a bad value. - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - true)); + ASSERT_FALSE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - false)); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, false)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); - EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x1234567890A, irsend.capture.value); EXPECT_EQ(0x91A, irsend.capture.address); EXPECT_EQ(0x89, irsend.capture.command); @@ -193,33 +192,33 @@ TEST(TestDecodeSanyoLC7461, Decode64BitMessages) { // Decode a 'real' example via GlobalCache TEST(TestDecodeSanyoLC7461, DecodeGlobalCacheExample) { -IRsendTest irsend(4); -IRrecv irrecv(4); -irsend.begin(); + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); -irsend.reset(); -uint16_t gc_test[95] = {38000, 1, 89, 342, 171, 21, 21, 21, 64, 21, 64, - 21, 64, 21, 21, 21, 64, 21, 64, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 64, 21, 21, - 21, 21, 21, 21, 21, 64, 21, 21, 21, 21, 21, 64, - 21, 64, 21, 64, 21, 64, 21, 64, 21, 64, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 64, 21, 64, 21, 64, 21, 64, 21, 64, - 21, 64, 21, 64, 21, 64, 21, 875, 342, 171, 21, 3565}; -irsend.sendGC(gc_test, 95); -irsend.makeDecodeResult(); + irsend.reset(); + uint16_t gc_test[95] = { + 38000, 1, 89, 342, 171, 21, 21, 21, 64, 21, 64, 21, 64, 21, 21, 21, + 64, 21, 64, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 64, 21, 21, 21, 21, 21, 21, 21, 64, 21, 21, 21, 21, 21, 64, 21, + 64, 21, 64, 21, 64, 21, 64, 21, 64, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 64, 21, 64, 21, 64, 21, + 64, 21, 64, 21, 64, 21, 64, 21, 64, 21, 875, 342, 171, 21, 3565}; + irsend.sendGC(gc_test, 95); + irsend.makeDecodeResult(); -ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, true)); -EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); -EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); -EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); -EXPECT_EQ(0xEC0, irsend.capture.address); -EXPECT_EQ(0x0, irsend.capture.command); -EXPECT_FALSE(irsend.capture.repeat); + ASSERT_TRUE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); + EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); + EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); + EXPECT_EQ(0xEC0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); -// Confirm what the 42-bit NEC decode is. -ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, 42, false)); -EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); + // Confirm what the 42-bit NEC decode is. + ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, 42, false)); + EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); } // Fail to decode a non-Sanyo LC7461 example via GlobalCache @@ -230,13 +229,14 @@ TEST(TestDecodeSanyoLC7461, FailToDecodeNonSanyoLC7461Example) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, - false)); + ASSERT_FALSE( + irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, false)); } diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sharp_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sharp_test.cpp similarity index 79% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Sharp_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Sharp_test.cpp index 0329b4e27..8481a4649 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sharp_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sharp_test.cpp @@ -37,7 +37,6 @@ TEST(TestEncodeSharp, AdvancedEncoding) { EXPECT_EQ(0x454A, irsend.encodeSharp(0x11, 0x52, 1, 0, true)); } - // Tests for sendSharp(). // Test sending typical data only. @@ -53,7 +52,8 @@ TEST(TestSendSharp, SendDataOnly) { "m260s43602" "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } // Test sending with different repeats. @@ -62,7 +62,7 @@ TEST(TestSendSharp, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendSharp(0x11, 0x52, SHARP_BITS, 1); // 1 repeat. + irsend.sendSharp(0x11, 0x52, kSharpBits, 1); // 1 repeat. EXPECT_EQ( "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" @@ -75,7 +75,8 @@ TEST(TestSendSharp, SendWithRepeats) { "m260s43602" "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } // Test sending an atypical data size. @@ -89,7 +90,8 @@ TEST(TestSendSharp, SendUnusualSize) { "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s780" "m260s43602" "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); irsend.reset(); irsend.sendSharp(0x0, 0x0, 16); @@ -99,7 +101,8 @@ TEST(TestSendSharp, SendUnusualSize) { "m260s43602" "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s1820" "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } // Tests for sendSharpRaw(). @@ -117,7 +120,8 @@ TEST(TestSendSharpRaw, SendDataOnly) { "m260s43602" "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } // Test sending with different repeats. @@ -126,7 +130,7 @@ TEST(TestSendSharpRaw, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendSharpRaw(0x454A, SHARP_BITS, 1); // 1 repeat. + irsend.sendSharpRaw(0x454A, kSharpBits, 1); // 1 repeat. EXPECT_EQ( "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" @@ -139,7 +143,8 @@ TEST(TestSendSharpRaw, SendWithRepeats) { "m260s43602" "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } // Test sending an atypical data size. @@ -153,7 +158,8 @@ TEST(TestSendSharpRaw, SendUnusualSize) { "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s780" "m260s43602" "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); irsend.reset(); irsend.sendSharpRaw(0x2, 16); @@ -163,7 +169,8 @@ TEST(TestSendSharpRaw, SendUnusualSize) { "m260s43602" "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s1820" "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" - "m260s43602", irsend.outputStr()); + "m260s43602", + irsend.outputStr()); } // Tests for decodeSharp(). @@ -178,9 +185,9 @@ TEST(TestDecodeSharp, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSharpRaw(0x454A); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x454A, irsend.capture.value); EXPECT_EQ(0x11, irsend.capture.address); EXPECT_EQ(0x4A, irsend.capture.command); @@ -190,9 +197,9 @@ TEST(TestDecodeSharp, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSharpRaw(irsend.encodeSharp(0x07, 0x99)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x7266, irsend.capture.value); EXPECT_EQ(0x07, irsend.capture.address); EXPECT_EQ(0x99, irsend.capture.command); @@ -202,9 +209,9 @@ TEST(TestDecodeSharp, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSharpRaw(irsend.encodeSharp(0x1, 0x1)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x4202, irsend.capture.value); EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x1, irsend.capture.command); @@ -219,19 +226,19 @@ TEST(TestDecodeSharp, NormalDecodeWithRepeatAndStrict) { // Normal Sharp 15-bit message with 1 repeat. irsend.reset(); - irsend.sendSharpRaw(0x7266, SHARP_BITS, 1); + irsend.sendSharpRaw(0x7266, kSharpBits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x7266, irsend.capture.value); EXPECT_EQ(0x07, irsend.capture.address); EXPECT_EQ(0x99, irsend.capture.command); - irsend.makeDecodeResult(2 * (2 * SHARP_BITS + FOOTER)); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + irsend.makeDecodeResult(2 * (2 * kSharpBits + kFooter)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x7266, irsend.capture.value); } @@ -245,7 +252,7 @@ TEST(TestDecodeSharp, DecodeWithNonStrict) { irsend.sendSharpRaw(0x0, 8); // Illegal length Sharp 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, 8, false)); EXPECT_EQ(SHARP, irsend.capture.decode_type); @@ -258,7 +265,7 @@ TEST(TestDecodeSharp, DecodeWithNonStrict) { irsend.sendSharpRaw(0x12345678, 32); // Illegal length Sharp 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); // Should fail with strict when we ask for the wrong bit size. ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, 32, true)); @@ -298,21 +305,17 @@ TEST(TestDecodeSharp, DecodeGlobalCacheExample) { irsend.reset(); // Sharp Power On from Global Cache. - uint16_t gc_test[67] = {38000, 1, 1, - 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 30, - 10, 70, 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, - 10, 30, 10, 70, 10, 30, - 10, 1657, - 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 70, - 10, 30, 10, 70, 10, 30, 10, 70, 10, 70, 10, 30, - 10, 70, 10, 30, 10, 70, - 10, 1657}; + uint16_t gc_test[67] = { + 38000, 1, 1, 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 30, 10, 70, + 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, 10, 30, 10, 70, 10, 30, 10, + 1657, 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 70, 10, 30, 10, 70, + 10, 30, 10, 70, 10, 70, 10, 30, 10, 70, 10, 30, 10, 70, 10, 1657}; irsend.sendGC(gc_test, 67); irsend.makeDecodeResult(); ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture)); EXPECT_EQ(SHARP, irsend.capture.decode_type); - EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x454A, irsend.capture.value); EXPECT_EQ(0x11, irsend.capture.address); EXPECT_EQ(0x4A, irsend.capture.command); @@ -327,31 +330,25 @@ TEST(TestDecodeSharp, FailToDecodeNonSharpExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[67] = {38000, 1, 1, - 10, 70, 30, 30, 10, 30, 10, 30, 10, 70, 10, 30, - 10, 70, 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, - 10, 30, 10, 70, 10, 30, - 10, 1657, - 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 70, - 10, 30, 10, 60, 10, 30, 10, 70, 10, 70, 10, 30, - 10, 10, 70, 30, 10, 70, - 10, 1657}; + uint16_t gc_test[67] = { + 38000, 1, 1, 10, 70, 30, 30, 10, 30, 10, 30, 10, 70, 10, 30, 10, 70, + 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, 10, 30, 10, 70, 10, 30, 10, + 1657, 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 70, 10, 30, 10, 60, + 10, 30, 10, 70, 10, 70, 10, 30, 10, 10, 70, 30, 10, 70, 10, 1657}; irsend.sendGC(gc_test, 67); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, false)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, false)); // Test only half of a good message, as it is sent (sort of) twice. - uint16_t gc_half[35] = {38000, 1, 1, - 10, 70, 10, 30, 10, 30, 10, 30, 10, 70, 10, 30, - 10, 70, 10, 30, 10, 70, 10, 30, 10, 30, 10, 70, - 10, 30, 10, 70, 10, 30, - 10, 1657}; + uint16_t gc_half[35] = {38000, 1, 1, 10, 70, 10, 30, 10, 30, 10, 30, 10, + 70, 10, 30, 10, 70, 10, 30, 10, 70, 10, 30, 10, + 30, 10, 70, 10, 30, 10, 70, 10, 30, 10, 1657}; irsend.sendGC(gc_half, 35); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, false)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, false)); } diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Sherwood_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sherwood_test.cpp new file mode 100644 index 000000000..22d9ead38 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sherwood_test.cpp @@ -0,0 +1,78 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendSherwood(). + +// Test sending typical data only. +TEST(TestSendSherwood, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSherwood(0xC1A28877); + EXPECT_EQ( + "m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680" + "m560s1680m560s560m560s1680m560s1680m560s1680m560s42560" + "m8960s2240m560s96320", + irsend.outputStr()); +} + +// Test sending typical data with extra repeats. +TEST(TestSendSherwood, SendDataWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSherwood(0xC1A28877, 32, 2); + EXPECT_EQ( + "m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680" + "m560s1680m560s560m560s1680m560s1680m560s1680m560s42560" + "m8960s2240m560s96320" + "m8960s2240m560s96320", + irsend.outputStr()); +} + +// Test sending typical data with explicit no repeats. +TEST(TestSendSherwood, SendDataWithZeroRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSherwood(0xC1A28877, 32, 0); + // Should have a single NEC repeat, as we always send one. + EXPECT_EQ( + "m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680" + "m560s1680m560s560m560s1680m560s1680m560s1680m560s42560" + "m8960s2240m560s96320", + irsend.outputStr()); +} + +// Test that a typical Sherwood send decodes as the appropriate NEC value. +TEST(TestSendSherwood, DecodesAsNEC) { + IRsendTest irsend(4); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendSherwood(0xC1A28877); + irsend.makeDecodeResult(); + + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0xC1A28877, irsend.capture.value); + EXPECT_EQ(0x4583, irsend.capture.address); + EXPECT_EQ(0x11, irsend.capture.command); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Sony_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sony_test.cpp new file mode 100644 index 000000000..c79ff6175 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Sony_test.cpp @@ -0,0 +1,357 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendSony(). + +// Test sending typical data only. +TEST(TestSendSony, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSony(0); + // We expect three 20-bit commands to be sent. + EXPECT_EQ( + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s18600" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s18600" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m600s600m600s600m600s600m600s18600", + irsend.outputStr()); + + irsend.reset(); + irsend.sendSony(0x240C, kSony20Bits); + // We expect three 20-bit commands to be sent. + EXPECT_EQ( + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200", + irsend.outputStr()); + + irsend.reset(); + irsend.sendSony(0x240C, kSony15Bits); + // We expect three 15-bit commands to be sent. + EXPECT_EQ( + "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200" + "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200" + "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" + "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" + "m600s22200", + irsend.outputStr()); + + irsend.reset(); + irsend.sendSony(0xA90, kSony12Bits); + // We expect three 15-bit commands to be sent. + EXPECT_EQ( + "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" + "m600s600m1200s600m600s600m600s600m600s600m600s25800" + "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" + "m600s600m1200s600m600s600m600s600m600s600m600s25800" + "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" + "m600s600m1200s600m600s600m600s600m600s600m600s25800", + irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendSony, SendWithDiffRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSony(0x240C, kSony20Bits, 0); // Send a command with 0 repeats. + EXPECT_EQ( + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200", + irsend.outputStr()); + irsend.sendSony(0x240C, kSony20Bits, 1); // Send a command with 1 repeat. + EXPECT_EQ( + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200", + irsend.outputStr()); + irsend.sendSony(0x240C, kSony20Bits, 3); // Send a command with 3 repeats. + EXPECT_EQ( + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200" + "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" + "m600s600m1200s600m1200s600m600s600m600s16200", + irsend.outputStr()); +} + +// Tests for encodeSony(). + +TEST(TestEncodeSony, NormalSonyEncoding) { + IRsendTest irsend(4); + EXPECT_EQ(0x0, irsend.encodeSony(kSony12Bits, 0, 0)); + EXPECT_EQ(0xA90, irsend.encodeSony(kSony12Bits, 21, 1)); + EXPECT_EQ(0xFFF, irsend.encodeSony(kSony12Bits, 0x7F, 0x1F)); + + EXPECT_EQ(0x0, irsend.encodeSony(kSony15Bits, 0, 0)); + EXPECT_EQ(0x5480, irsend.encodeSony(kSony15Bits, 21, 1)); + EXPECT_EQ(0x5455, irsend.encodeSony(kSony15Bits, 21, 0xAA)); + EXPECT_EQ(0x7FFF, irsend.encodeSony(kSony15Bits, 0x7F, 0xFF)); + + EXPECT_EQ(0x0, irsend.encodeSony(kSony20Bits, 0, 0, 0)); + EXPECT_EQ(0x81080, irsend.encodeSony(kSony20Bits, 1, 1, 1)); + EXPECT_EQ(0xFFFFF, irsend.encodeSony(kSony20Bits, 0x7F, 0x1F, 0xFF)); +} + +TEST(TestEncodeSony, SonyEncodingWithOversizedValues) { + IRsendTest irsend(4); + EXPECT_EQ(0xFFF, irsend.encodeSony(kSony12Bits, 0xFFFF, 0xFFFF)); + + EXPECT_EQ(0x7FFF, irsend.encodeSony(kSony15Bits, 0xFFFF, 0xFFFF)); + + EXPECT_EQ(0xFFFFF, irsend.encodeSony(kSony20Bits, 0xFFFF, 0xFFFF, 0xFFFF)); +} + +// Tests for decodeSony(). + +// Decode normal Sony messages. +TEST(TestDecodeSony, NormalSonyDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Synthesised Normal Sony 20-bit message. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony20Bits, 0x1, 0x1, 0x1)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony20Bits, irsend.capture.bits); + EXPECT_EQ(0x81080, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x81, irsend.capture.command); + + // Synthesised Normal Sony 15-bit message. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony15Bits, 21, 1), kSony15Bits); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony15Bits, irsend.capture.bits); + EXPECT_EQ(0x5480, irsend.capture.value); + EXPECT_EQ(1, irsend.capture.address); + EXPECT_EQ(21, irsend.capture.command); + + // Synthesised Normal Sony 12-bit message. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony12Bits, irsend.capture.bits); + EXPECT_EQ(0xA90, irsend.capture.value); + EXPECT_EQ(1, irsend.capture.address); + EXPECT_EQ(21, irsend.capture.command); +} + +// Decode unexpected Sony messages. i.e longer than minimum etc. +TEST(TestDecodeSony, SonyDecodeWithUnexpectedLegalSize) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Synthesised Normal Sony 20-bit message decoded when looking for 12-bits + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony20Bits, 0x1, 0x1, 0x1)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSonyMinBits)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony20Bits, irsend.capture.bits); + EXPECT_EQ(0x81080, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x81, irsend.capture.command); + + // Synthesised Normal Sony 12-bit message when expecting 20-bits. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony20Bits)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony12Bits, irsend.capture.bits); + EXPECT_EQ(0xA90, irsend.capture.value); + EXPECT_EQ(1, irsend.capture.address); + EXPECT_EQ(21, irsend.capture.command); + + // 12-bit message should be regected when using strict and a different size. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + + // 15-bit message should be regected when using strict and a different size. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony15Bits, 21, 1), kSony15Bits); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + + // 20-bit message should be regected when using strict and a different size. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(kSony20Bits, 1, 1, 1), kSony20Bits); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); +} + +// Decode unsupported Sony messages. i.e non-standard sizes. +TEST(TestDecodeSony, SonyDecodeWithIllegalSize) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSony(0xFF, 8); // Illegal 8-bit Sony-like message. + irsend.makeDecodeResult(); + // Should fail with strict on. + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSonyMinBits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0xFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendSony(0x1FFF, 13); // Illegal 13-bit Sony-like message. + irsend.makeDecodeResult(); + // Should fail with strict on. + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSonyMinBits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(13, irsend.capture.bits); + EXPECT_EQ(0x1FFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendSony(0x1FFFF, 17); // Illegal 17-bit Sony-like message. + irsend.makeDecodeResult(); + // Should fail with strict on. + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSonyMinBits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(17, irsend.capture.bits); + EXPECT_EQ(0x1FFFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendSony(0x1FFFFF, 21); // Illegal 21-bit Sony-like message. + irsend.makeDecodeResult(); + // Should fail with strict on. + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSonyMinBits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(21, irsend.capture.bits); + EXPECT_EQ(0x1FFFFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + // Illegal 64-bit (max) Sony-like message. + irsend.sendSony(0xFFFFFFFFFFFFFFFF, 64, 0); + irsend.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +// Decode unsupported Sony messages. i.e non-standard sizes. +TEST(TestDecodeSony, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Sony "Power On" from Global Cache. + uint16_t gc_test[29] = {40000, 1, 1, 96, 24, 24, 24, 48, 24, 48, + 24, 48, 24, 24, 24, 48, 24, 24, 24, 48, + 24, 24, 24, 24, 24, 24, 24, 24, 1013}; + irsend.sendGC(gc_test, 29); + irsend.makeDecodeResult(); + + // Without strict. + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(12, irsend.capture.bits); + EXPECT_EQ(0x750, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x2E, irsend.capture.command); + // With strict and correct size. + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); +} + +// Encoding & Decode 20 bit Sony messages. Issue #476 +TEST(TestEncodeSony, Issue476) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendSony(0x6AB47, 20); + irsend.makeDecodeResult(); + + // Without strict. + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(20, irsend.capture.bits); + EXPECT_EQ(0x6AB47, irsend.capture.value); // 20 bits + EXPECT_EQ(0x1A, irsend.capture.address); // 5 bits + EXPECT_EQ(0x7156, irsend.capture.command); // 15 bits + EXPECT_EQ(0x56, 0x7156 & 0x7F); // command (lower 7 bits) + EXPECT_EQ(0xE2, (0x7156 >> 7) & 0xFF); // extended (top 8 of 15 bits) + EXPECT_EQ(0x6AB47, irsend.encodeSony(20, 0x56, 0x1A, 0xE2)); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Toshiba_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Toshiba_test.cpp new file mode 100644 index 000000000..b5e1e07a9 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Toshiba_test.cpp @@ -0,0 +1,664 @@ +// Copyright 2017 David Conran +#include "ir_Toshiba.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for Toshiba A/C methods. + +// Test sending typical data only. +TEST(TestSendToshibaAC, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t toshiba_code[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x00}; + irsend.reset(); + irsend.sendToshibaAC(toshiba_code); + EXPECT_EQ( + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s7048" + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s7048", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendToshibaAC, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + uint8_t toshiba_code[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x00}; + + irsend.sendToshibaAC(toshiba_code, kToshibaACStateLength, 0); + EXPECT_EQ( + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s7048", + irsend.outputStr()); + + irsend.reset(); + irsend.sendToshibaAC(toshiba_code, kToshibaACStateLength, 2); + EXPECT_EQ( + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s7048" + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s7048" + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s7048", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendToshibaAC, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t toshiba_short_code[8] = {0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08}; + uint8_t toshiba_long_code[10] = {0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A}; + irsend.reset(); + irsend.sendToshibaAC(toshiba_short_code, kToshibaACStateLength - 1); + ASSERT_EQ("", irsend.outputStr()); + + irsend.reset(); + irsend.sendToshibaAC(toshiba_long_code, kToshibaACStateLength + 1); + ASSERT_EQ( + "m4400s4300" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623m543s1623" + "m543s472m543s472m543s472m543s472m543s1623m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s1623m543s472m543s1623m543s472" + "m543s7048" + "m4400s4300" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623m543s1623" + "m543s472m543s472m543s472m543s472m543s1623m543s472m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s1623m543s472m543s1623m543s472" + "m543s7048", + irsend.outputStr()); +} + +// Tests for IRToshibaAC class. + +TEST(TestToshibaACClass, Power) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + toshiba.on(); + EXPECT_TRUE(toshiba.getPower()); + + toshiba.off(); + EXPECT_FALSE(toshiba.getPower()); + + toshiba.setPower(true); + EXPECT_TRUE(toshiba.getPower()); + + toshiba.setPower(false); + EXPECT_FALSE(toshiba.getPower()); +} + +TEST(TestToshibaACClass, Temperature) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + toshiba.setTemp(0); + EXPECT_EQ(kToshibaAcMinTemp, toshiba.getTemp()); + + toshiba.setTemp(255); + EXPECT_EQ(kToshibaAcMaxTemp, toshiba.getTemp()); + + toshiba.setTemp(kToshibaAcMinTemp); + EXPECT_EQ(kToshibaAcMinTemp, toshiba.getTemp()); + + toshiba.setTemp(kToshibaAcMaxTemp); + EXPECT_EQ(kToshibaAcMaxTemp, toshiba.getTemp()); + + toshiba.setTemp(kToshibaAcMinTemp - 1); + EXPECT_EQ(kToshibaAcMinTemp, toshiba.getTemp()); + + toshiba.setTemp(kToshibaAcMaxTemp + 1); + EXPECT_EQ(kToshibaAcMaxTemp, toshiba.getTemp()); + + toshiba.setTemp(17); + EXPECT_EQ(17, toshiba.getTemp()); + + toshiba.setTemp(21); + EXPECT_EQ(21, toshiba.getTemp()); + + toshiba.setTemp(25); + EXPECT_EQ(25, toshiba.getTemp()); + + toshiba.setTemp(30); + EXPECT_EQ(30, toshiba.getTemp()); +} + +TEST(TestToshibaACClass, OperatingMode) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + toshiba.setMode(kToshibaAcAuto); + EXPECT_EQ(kToshibaAcAuto, toshiba.getMode()); + + toshiba.setMode(kToshibaAcCool); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + + toshiba.setMode(kToshibaAcHeat); + EXPECT_EQ(kToshibaAcHeat, toshiba.getMode()); + + toshiba.setMode(kToshibaAcDry); + EXPECT_EQ(kToshibaAcDry, toshiba.getMode()); + + toshiba.setMode(kToshibaAcHeat + 1); + EXPECT_EQ(kToshibaAcAuto, toshiba.getMode()); + + toshiba.setMode(255); + EXPECT_EQ(kToshibaAcAuto, toshiba.getMode()); + + // Setting the power off changes the underlying mode in the state to heat. + toshiba.setPower(true); + toshiba.setMode(kToshibaAcCool); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode(true)); + toshiba.setPower(false); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + EXPECT_EQ(kToshibaAcHeat, toshiba.getMode(true)); +} + +TEST(TestToshibaACClass, FanSpeed) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + toshiba.setFan(kToshibaAcFanAuto); + EXPECT_EQ(kToshibaAcFanAuto, toshiba.getFan()); + + toshiba.setFan(255); + EXPECT_EQ(kToshibaAcFanMax, toshiba.getFan()); + + toshiba.setFan(kToshibaAcFanMax); + EXPECT_EQ(kToshibaAcFanMax, toshiba.getFan()); + + toshiba.setFan(kToshibaAcFanMax - 1); + EXPECT_EQ(kToshibaAcFanMax - 1, toshiba.getFan()); + + toshiba.setFan(1); + EXPECT_EQ(1, toshiba.getFan()); + + toshiba.setFan(2); + EXPECT_EQ(2, toshiba.getFan()); + + toshiba.setFan(3); + EXPECT_EQ(3, toshiba.getFan()); + + toshiba.setFan(4); + EXPECT_EQ(4, toshiba.getFan()); + + toshiba.setFan(kToshibaAcFanMax + 1); + EXPECT_EQ(kToshibaAcFanMax, toshiba.getFan()); +} + +TEST(TestToshibaACClass, RawState) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + uint8_t initial_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x01}; + uint8_t modified_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0xC1, 0x00, 0xC0}; + + // Verify the starting state. + EXPECT_STATE_EQ(initial_state, toshiba.getRaw(), kToshibaACBits); + EXPECT_TRUE(toshiba.getPower()); + EXPECT_EQ(kToshibaAcAuto, toshiba.getMode()); + EXPECT_EQ(kToshibaAcFanAuto, toshiba.getFan()); + + // Change some settings. + toshiba.setMode(kToshibaAcCool); + toshiba.setFan(kToshibaAcFanMax); + toshiba.setTemp(kToshibaAcMinTemp); + // Verify those were set. + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + EXPECT_EQ(kToshibaAcFanMax, toshiba.getFan()); + EXPECT_EQ(kToshibaAcMinTemp, toshiba.getTemp()); + // Retrieve the modified state. + EXPECT_STATE_EQ(modified_state, toshiba.getRaw(), kToshibaACBits); + + // Set it back to the initial state. + toshiba.setRaw(initial_state); + + // Check the new state was set correctly. + EXPECT_TRUE(toshiba.getPower()); + EXPECT_EQ(kToshibaAcAuto, toshiba.getMode()); + EXPECT_EQ(kToshibaAcFanAuto, toshiba.getFan()); + EXPECT_STATE_EQ(initial_state, toshiba.getRaw(), kToshibaACBits); +} + +TEST(TestToshibaACClass, Checksums) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + uint8_t initial_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x01}; + uint8_t modified_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0xC1, 0x00, 0xC0}; + uint8_t invalid_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x00}; + + EXPECT_EQ(0x01, toshiba.calcChecksum(initial_state)); + EXPECT_EQ(0xC0, toshiba.calcChecksum(modified_state)); + // Check we can call it without instantiating the object. + EXPECT_EQ(0x01, IRToshibaAC::calcChecksum(initial_state)); + // Use different lengths. + EXPECT_EQ(0x01, IRToshibaAC::calcChecksum(initial_state, + kToshibaACStateLength - 1)); + EXPECT_EQ(0xFF, IRToshibaAC::calcChecksum(initial_state, 3)); + // Minimum length that actually means anything. + EXPECT_EQ(0xF2, IRToshibaAC::calcChecksum(initial_state, 2)); + // Technically, there is no such thing as a checksum for a length of < 2 + // But test it anyway + EXPECT_EQ(0x00, IRToshibaAC::calcChecksum(initial_state, 1)); + EXPECT_EQ(0x00, IRToshibaAC::calcChecksum(initial_state, 0)); + + // Validity tests. + EXPECT_TRUE(IRToshibaAC::validChecksum(initial_state)); + EXPECT_TRUE(IRToshibaAC::validChecksum(modified_state)); + EXPECT_FALSE(IRToshibaAC::validChecksum(invalid_state)); + EXPECT_FALSE(IRToshibaAC::validChecksum(initial_state, 0)); + EXPECT_FALSE(IRToshibaAC::validChecksum(initial_state, 1)); + EXPECT_FALSE(IRToshibaAC::validChecksum(initial_state, 2)); +} + +TEST(TestToshibaACClass, HumanReadableOutput) { + IRToshibaAC toshiba(0); + toshiba.begin(); + + uint8_t initial_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x01}; + uint8_t modified_state[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0xC1, 0x00, 0xC0}; + + toshiba.setRaw(initial_state); + EXPECT_EQ("Power: On, Mode: 0 (AUTO), Temp: 17C, Fan: 0 (AUTO)", + toshiba.toString()); + toshiba.setRaw(modified_state); + EXPECT_EQ("Power: On, Mode: 1 (COOL), Temp: 17C, Fan: 5 (MAX)", + toshiba.toString()); + toshiba.off(); + toshiba.setTemp(25); + toshiba.setFan(3); + toshiba.setMode(kToshibaAcDry); + EXPECT_EQ("Power: Off, Mode: 2 (DRY), Temp: 25C, Fan: 3", toshiba.toString()); +} + +TEST(TestToshibaACClass, MessageConstuction) { + IRToshibaAC toshiba(0); + IRsendTest irsend(4); + toshiba.begin(); + irsend.begin(); + + toshiba.setFan(1); + toshiba.setMode(kToshibaAcCool); + toshiba.setTemp(27); + toshiba.on(); + + // Check everything for kicks. + EXPECT_EQ(1, toshiba.getFan()); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + EXPECT_EQ(27, toshiba.getTemp()); + EXPECT_TRUE(toshiba.getPower()); + + irsend.reset(); + irsend.sendToshibaAC(toshiba.getRaw()); + EXPECT_EQ( + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s1623m543s472m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s1623m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s1623m543s1623m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s7048" + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s1623m543s472m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s1623m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s1623m543s1623m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s7048", + irsend.outputStr()); + + // Turn off the power and re-check. + toshiba.setPower(false); + // Check everything for kicks. + EXPECT_EQ(1, toshiba.getFan()); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + EXPECT_EQ(27, toshiba.getTemp()); + EXPECT_FALSE(toshiba.getPower()); + + irsend.reset(); + irsend.sendToshibaAC(toshiba.getRaw()); + EXPECT_EQ( + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s1623m543s472m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s1623m543s472m543s472m543s472m543s1623m543s1623m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s1623m543s472" + "m543s7048" + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s1623m543s472m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s1623m543s472m543s472m543s472m543s1623m543s1623m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s1623m543s472" + "m543s7048", + irsend.outputStr()); + + // Turn the power back on, and check nothing changed. + toshiba.on(); + + EXPECT_EQ(1, toshiba.getFan()); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + EXPECT_EQ(27, toshiba.getTemp()); + EXPECT_TRUE(toshiba.getPower()); + + irsend.reset(); + irsend.sendToshibaAC(toshiba.getRaw()); + EXPECT_EQ( + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s1623m543s472m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s1623m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s1623m543s1623m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s7048" + "m4400s4300" + "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" + "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s1623" + "m543s1623m543s1623m543s1623m543s1623m543s1623m543s1623m543s472m543s472" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s1623m543s472m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s472m543s1623m543s472m543s472m543s472m543s472m543s472m543s1623" + "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s472" + "m543s1623m543s1623m543s1623m543s472m543s472m543s472m543s472m543s472" + "m543s7048", + irsend.outputStr()); +} + +// Decoding a message we entirely constructed based solely on a given state. +TEST(TestDecodeToshibaAC, SyntheticExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + uint8_t expectedState[kToshibaACStateLength] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, + 0x00, 0x00, 0x00, 0x01}; + + irsend.reset(); + irsend.sendToshibaAC(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Test decoding against captures from a real Toshiba A/C remote. +// Recorded by @mwildbolz +TEST(TestDecodeToshibaAC, RealExamples) { + IRToshibaAC toshiba(0); + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + uint16_t rawData1[295] = { + 4442, 4292, 612, 1544, 616, 1544, 616, 1544, 612, 1548, 610, 468, + 612, 468, 662, 1494, 640, 438, 616, 464, 614, 464, 616, 464, + 612, 468, 610, 1544, 616, 1544, 616, 468, 612, 1544, 616, 464, + 694, 386, 616, 464, 612, 468, 612, 468, 636, 444, 610, 1546, + 616, 1544, 612, 1546, 614, 1546, 616, 1546, 740, 1420, 612, 1544, + 616, 1546, 616, 464, 610, 468, 610, 470, 612, 468, 610, 468, + 610, 470, 636, 438, 616, 464, 616, 464, 616, 1546, 636, 442, + 612, 1546, 614, 1544, 616, 464, 614, 464, 610, 468, 612, 468, + 612, 468, 612, 468, 636, 440, 614, 464, 616, 464, 616, 464, + 612, 468, 636, 442, 638, 442, 662, 418, 610, 464, 616, 464, + 616, 464, 610, 468, 612, 468, 636, 444, 610, 468, 638, 438, + 614, 1546, 612, 1548, 612, 470, 610, 468, 636, 442, 612, 468, + 612, 1544, 612, 7396, 4442, 4292, 610, 1546, 616, 1544, 612, 1548, + 612, 1546, 616, 464, 616, 464, 616, 1544, 612, 468, 662, 418, + 610, 468, 638, 442, 638, 438, 616, 1546, 616, 1544, 612, 468, + 610, 1546, 616, 464, 616, 464, 642, 438, 616, 464, 612, 468, + 610, 470, 610, 1546, 616, 1544, 612, 1546, 616, 1546, 614, 1546, + 612, 1550, 610, 1544, 616, 1546, 614, 464, 642, 438, 610, 468, + 612, 468, 612, 468, 612, 468, 610, 468, 638, 438, 614, 464, + 616, 1544, 636, 444, 636, 1520, 616, 1544, 616, 464, 616, 464, + 612, 468, 612, 468, 612, 468, 612, 468, 612, 464, 612, 470, + 636, 442, 638, 442, 612, 470, 692, 384, 614, 464, 616, 464, + 612, 468, 610, 468, 612, 468, 610, 470, 610, 464, 616, 464, + 616, 464, 616, 464, 610, 1550, 610, 1546, 640, 444, 688, 386, + 616, 464, 612, 468, 612, 1544, 642}; + + irsend.reset(); + irsend.sendRaw(rawData1, 295, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + toshiba.setRaw(irsend.capture.state); + EXPECT_TRUE(toshiba.getPower()); + EXPECT_EQ(23, toshiba.getTemp()); + EXPECT_EQ(kToshibaAcFanAuto, toshiba.getFan()); + EXPECT_EQ(kToshibaAcAuto, toshiba.getMode()); + + uint16_t rawData2[295] = { + 4500, 4236, 636, 1520, 642, 1520, 640, 1520, 664, 1492, 642, 440, + 668, 412, 642, 1518, 638, 438, 666, 414, 640, 438, 642, 438, + 638, 442, 642, 1516, 640, 1520, 642, 438, 642, 1520, 636, 438, + 668, 412, 640, 440, 666, 412, 642, 438, 668, 412, 640, 1516, + 668, 1492, 642, 1520, 666, 1494, 638, 1520, 642, 1520, 668, 1490, + 666, 1494, 642, 438, 638, 438, 668, 412, 668, 412, 642, 438, + 642, 438, 664, 412, 642, 438, 642, 438, 642, 1518, 642, 434, + 668, 412, 642, 438, 668, 412, 692, 388, 666, 412, 642, 434, + 642, 438, 642, 1518, 668, 412, 668, 412, 640, 438, 638, 438, + 642, 438, 640, 438, 668, 1492, 642, 440, 666, 412, 640, 438, + 642, 438, 642, 434, 668, 412, 668, 412, 666, 414, 666, 1494, + 640, 438, 642, 434, 668, 412, 642, 438, 642, 438, 668, 412, + 668, 414, 640, 7362, 4474, 4262, 642, 1518, 638, 1520, 640, 1520, + 668, 1494, 640, 434, 642, 438, 640, 1520, 642, 438, 642, 438, + 642, 438, 642, 438, 642, 434, 668, 1494, 642, 1518, 638, 442, + 638, 1520, 642, 438, 642, 438, 668, 414, 664, 408, 642, 438, + 668, 412, 642, 1520, 666, 1494, 642, 1514, 642, 1518, 642, 1520, + 636, 1520, 668, 1494, 666, 1494, 638, 438, 666, 414, 640, 440, + 666, 412, 668, 412, 668, 412, 642, 434, 668, 412, 668, 412, + 668, 1494, 642, 438, 642, 434, 642, 438, 642, 438, 642, 438, + 642, 438, 642, 434, 646, 434, 642, 1518, 668, 412, 642, 438, + 642, 434, 666, 414, 640, 438, 642, 438, 642, 1518, 642, 438, + 642, 434, 668, 412, 642, 438, 642, 438, 642, 438, 642, 438, + 642, 438, 640, 1520, 636, 438, 642, 438, 642, 438, 666, 414, + 668, 412, 642, 440, 640, 438, 640}; + + irsend.reset(); + irsend.sendRaw(rawData2, 295, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + toshiba.setRaw(irsend.capture.state); + EXPECT_TRUE(toshiba.getPower()); + EXPECT_EQ(17, toshiba.getTemp()); + EXPECT_EQ(3, toshiba.getFan()); + EXPECT_EQ(kToshibaAcCool, toshiba.getMode()); + + uint16_t rawData3[295] = { + 4474, 4262, 642, 1514, 642, 1520, 642, 1520, 642, 1514, 642, 438, + 642, 438, 642, 1520, 636, 438, 642, 438, 642, 438, 642, 438, + 642, 438, 640, 1520, 638, 1520, 642, 438, 640, 1520, 642, 438, + 642, 434, 642, 438, 642, 438, 642, 438, 668, 414, 636, 1520, + 642, 1520, 642, 1514, 642, 1520, 642, 1520, 640, 1518, 638, 1520, + 666, 1494, 642, 438, 642, 434, 642, 438, 640, 438, 642, 438, + 642, 440, 640, 434, 642, 438, 642, 438, 642, 1520, 642, 438, + 642, 1514, 642, 1520, 640, 1520, 636, 438, 642, 438, 642, 438, + 666, 414, 642, 1520, 636, 1520, 642, 438, 642, 438, 640, 438, + 642, 434, 642, 1518, 642, 1520, 642, 438, 642, 434, 640, 438, + 642, 438, 642, 438, 642, 440, 642, 438, 668, 408, 642, 1520, + 642, 438, 642, 1520, 638, 1518, 642, 438, 642, 438, 640, 1520, + 640, 438, 642, 7362, 4474, 4262, 642, 1518, 638, 1520, 640, 1520, + 642, 1520, 638, 438, 642, 438, 642, 1518, 642, 438, 638, 438, + 642, 438, 642, 438, 642, 438, 642, 1514, 642, 1520, 642, 438, + 666, 1490, 642, 438, 642, 438, 642, 440, 640, 438, 642, 434, + 640, 438, 642, 1520, 642, 1520, 636, 1520, 642, 1520, 642, 1514, + 642, 1518, 642, 1518, 640, 1516, 642, 438, 642, 438, 642, 438, + 640, 438, 638, 442, 642, 434, 642, 440, 640, 438, 642, 438, + 642, 1518, 642, 438, 642, 1514, 642, 1520, 642, 1518, 642, 438, + 642, 432, 642, 438, 642, 438, 642, 1520, 642, 1514, 642, 438, + 642, 438, 642, 438, 642, 438, 642, 1514, 642, 1520, 642, 438, + 642, 438, 638, 438, 642, 438, 642, 438, 640, 440, 642, 438, + 640, 434, 642, 1520, 642, 438, 640, 1520, 668, 1490, 666, 414, + 640, 438, 642, 1520, 642, 438, 636}; + + irsend.reset(); + irsend.sendRaw(rawData3, 295, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + toshiba.setRaw(irsend.capture.state); + EXPECT_TRUE(toshiba.getPower()); + EXPECT_EQ(24, toshiba.getTemp()); + EXPECT_EQ(kToshibaAcFanMax, toshiba.getFan()); + EXPECT_EQ(kToshibaAcHeat, toshiba.getMode()); + + uint16_t rawData4[295] = { + 4474, 4262, 636, 1520, 640, 1520, 640, 1520, 638, 1518, 642, 438, + 642, 438, 642, 1520, 636, 438, 642, 438, 642, 438, 642, 438, + 636, 444, 636, 1520, 640, 1520, 642, 438, 638, 1524, 638, 438, + 640, 438, 642, 438, 640, 438, 642, 438, 638, 438, 642, 1518, + 642, 1520, 666, 1494, 636, 1520, 640, 1520, 640, 1520, 636, 1524, + 638, 1520, 640, 440, 640, 438, 642, 438, 636, 444, 636, 438, + 642, 438, 640, 440, 640, 438, 642, 438, 642, 1518, 638, 438, + 642, 1518, 642, 438, 640, 1520, 636, 444, 636, 438, 640, 438, + 642, 438, 668, 1494, 640, 438, 642, 1518, 636, 444, 636, 438, + 640, 1520, 642, 1518, 642, 1520, 636, 444, 636, 438, 642, 438, + 642, 438, 640, 440, 640, 438, 640, 440, 640, 438, 640, 1518, + 642, 1520, 636, 1524, 636, 1518, 642, 438, 642, 1518, 642, 1518, + 640, 438, 642, 7364, 4472, 4262, 642, 1518, 642, 1518, 638, 1518, + 642, 1520, 642, 438, 642, 438, 640, 1520, 636, 440, 640, 438, + 642, 438, 640, 438, 642, 438, 642, 1518, 636, 1524, 636, 438, + 640, 1520, 642, 438, 642, 438, 640, 438, 636, 444, 636, 438, + 668, 412, 642, 1518, 642, 1520, 642, 1520, 636, 1518, 642, 1518, + 642, 1520, 636, 1520, 668, 1494, 642, 438, 636, 444, 664, 412, + 642, 438, 668, 412, 642, 438, 636, 442, 638, 442, 638, 438, + 642, 1518, 642, 438, 642, 1518, 638, 438, 642, 1518, 642, 440, + 640, 438, 636, 444, 636, 444, 636, 1520, 642, 438, 642, 1520, + 636, 444, 636, 438, 642, 1520, 640, 1520, 636, 1520, 668, 412, + 642, 438, 642, 438, 642, 438, 638, 442, 636, 438, 642, 438, + 668, 412, 640, 1520, 638, 1524, 636, 1520, 642, 1520, 636, 444, + 638, 1522, 638, 1518, 640, 438, 642}; + + irsend.reset(); + irsend.sendRaw(rawData4, 295, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, irsend.capture.bits); + toshiba.setRaw(irsend.capture.state); + EXPECT_FALSE(toshiba.getPower()); + EXPECT_EQ(22, toshiba.getTemp()); + EXPECT_EQ(4, toshiba.getFan()); + + // Confirming the quirky behaviour that the 'Power OFF' signal + // sets the mode to heat. + // The previous state the remote was in was 'AUTO' just prior to + // sending the power off message. + EXPECT_EQ(kToshibaAcHeat, toshiba.getMode()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Whirlpool_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Whirlpool_test.cpp new file mode 100644 index 000000000..c30cb21d3 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Whirlpool_test.cpp @@ -0,0 +1,118 @@ +// Copyright 2018 David Conran + +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendWhirlpoolAC(). + +// Test sending typical data only. +TEST(TestSendWhirlpoolAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + uint8_t data[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + + irsend.sendWhirlpoolAC(data); + EXPECT_EQ( + "m8950s4484" + "m597s1649m597s1649m597s533m597s533m597s533m597s533m597s533m597s1649" + "m597s533m597s1649m597s1649m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s1649m597s533m597s533m597s533" + "m597s1649m597s533m597s533m597s533m597s1649m597s1649m597s1649m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s7920" + "m597s1649m597s533m597s533m597s533m597s1649m597s533m597s533m597s1649" + "m597s1649m597s1649m597s1649m597s1649m597s1649m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s1649m597s1649m597s1649m597s1649m597s533m597s1649m597s1649m597s1649" + "m597s7920" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s1649m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s1649m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s100000", + irsend.outputStr()); +} + +// Tests for decodeWhirlpoolAC(). +// Decode normal WhirlpoolAC messages. +TEST(TestDecodeWhirlpoolAC, SyntheticDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Synthesised Normal WhirlpoolAC message. + irsend.reset(); + uint8_t expectedState[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + irsend.sendWhirlpoolAC(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(WHIRLPOOL_AC, irsend.capture.decode_type); + EXPECT_EQ(kWhirlpoolAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decode a recorded example +TEST(TestDecodeWhirlpoolAC, RealExampleDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Real WhirlpoolAC message. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/509 + uint16_t rawData[343] = { + 8950, 4484, 598, 1642, 598, 1646, 594, 534, 594, 538, 602, 532, + 598, 540, 600, 542, 598, 1650, 600, 522, 598, 1644, 596, 1650, + 600, 532, 598, 538, 602, 536, 594, 548, 592, 538, 602, 518, + 600, 524, 596, 532, 598, 532, 598, 1654, 596, 544, 596, 544, + 596, 536, 594, 1644, 596, 528, 600, 528, 592, 538, 602, 1648, + 602, 1654, 596, 1664, 598, 534, 594, 526, 594, 530, 598, 528, + 602, 530, 600, 534, 596, 542, 598, 542, 598, 534, 596, 526, + 594, 530, 600, 528, 602, 530, 600, 534, 596, 542, 598, 544, + 596, 518, 602, 7916, 598, 1642, 598, 528, 600, 528, 602, 530, + 600, 1652, 598, 542, 598, 544, 596, 1654, 596, 1644, 596, 1648, + 602, 1644, 596, 1654, 596, 1656, 604, 536, 594, 548, 602, 528, + 600, 520, 600, 524, 596, 532, 598, 532, 596, 538, 602, 536, + 594, 546, 594, 538, 602, 518, 600, 524, 596, 532, 598, 532, + 598, 536, 594, 544, 596, 544, 596, 536, 594, 526, 592, 530, + 600, 528, 600, 530, 602, 532, 596, 542, 598, 542, 598, 534, + 596, 524, 596, 528, 600, 526, 592, 538, 592, 542, 598, 540, + 600, 540, 600, 530, 598, 522, 598, 526, 594, 534, 596, 534, + 594, 540, 602, 536, 592, 548, 592, 538, 600, 1636, 594, 1648, + 602, 1642, 598, 1652, 598, 538, 602, 1680, 570, 1662, 598, 1634, + 596, 7924, 600, 520, 598, 526, 592, 534, 596, 534, 596, 540, + 600, 536, 604, 538, 602, 530, 600, 520, 598, 1640, 600, 528, + 600, 530, 600, 534, 594, 544, 596, 544, 596, 534, 596, 526, + 594, 528, 600, 526, 594, 536, 592, 542, 598, 538, 602, 538, + 602, 528, 600, 520, 600, 524, 596, 530, 600, 532, 598, 534, + 596, 542, 598, 542, 598, 532, 598, 524, 596, 528, 602, 526, + 594, 536, 594, 540, 600, 536, 594, 548, 592, 538, 602, 518, + 602, 522, 596, 530, 600, 530, 600, 534, 596, 542, 598, 544, + 596, 534, 596, 524, 594, 1644, 596, 532, 596, 534, 596, 538, + 602, 536, 594, 546, 594, 520, 600}; + uint8_t expectedState[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + + irsend.reset(); + irsend.sendRaw(rawData, 343, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(WHIRLPOOL_AC, irsend.capture.decode_type); + EXPECT_EQ(kWhirlpoolAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Whynter_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Whynter_test.cpp similarity index 82% rename from lib/IRremoteESP8266-2.2.1.02/test/ir_Whynter_test.cpp rename to lib/IRremoteESP8266-2.5.2.03/test/ir_Whynter_test.cpp index 4978bb6f5..748a4c9bf 100644 --- a/lib/IRremoteESP8266-2.2.1.02/test/ir_Whynter_test.cpp +++ b/lib/IRremoteESP8266-2.5.2.03/test/ir_Whynter_test.cpp @@ -19,7 +19,8 @@ TEST(TestSendWhynter, SendDataOnly) { "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" - "m750s108000", irsend.outputStr()); + "m750s52050", + irsend.outputStr()); irsend.reset(); irsend.sendWhynter(0xFFFFFFFF); @@ -29,7 +30,8 @@ TEST(TestSendWhynter, SendDataOnly) { "m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150" "m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150" "m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150" - "m750s108000", irsend.outputStr()); + "m750s12200", + irsend.outputStr()); irsend.reset(); irsend.sendWhynter(0x87654321); @@ -39,7 +41,8 @@ TEST(TestSendWhynter, SendDataOnly) { "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000", irsend.outputStr()); + "m750s33850", + irsend.outputStr()); } // Test sending with different repeats. @@ -48,50 +51,55 @@ TEST(TestSendWhynter, SendWithRepeats) { irsend.begin(); irsend.reset(); - irsend.sendWhynter(0x87654321, WHYNTER_BITS, 0); // 0 repeats. + irsend.sendWhynter(0x87654321, kWhynterBits, 0); // 0 repeats. EXPECT_EQ( "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000", irsend.outputStr()); + "m750s33850", + irsend.outputStr()); irsend.reset(); - irsend.sendWhynter(0x87654321, WHYNTER_BITS, 1); // 1 repeat. + irsend.sendWhynter(0x87654321, kWhynterBits, 1); // 1 repeat. EXPECT_EQ( "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000" + "m750s33850" "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000", irsend.outputStr()); - irsend.sendWhynter(0x87654321, WHYNTER_BITS, 2); // 2 repeats. + "m750s33850", + irsend.outputStr()); + + irsend.reset(); + irsend.sendWhynter(0x87654321, kWhynterBits, 2); // 2 repeats. EXPECT_EQ( "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000" + "m750s33850" "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000" + "m750s33850" "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" - "m750s108000", irsend.outputStr()); + "m750s33850", + irsend.outputStr()); } // Test sending an atypical data size. @@ -104,7 +112,8 @@ TEST(TestSendWhynter, SendUnusualSize) { EXPECT_EQ( "m750s750m2850s2850" "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" - "m750s108000", irsend.outputStr()); + "m750s88050", + irsend.outputStr()); irsend.reset(); irsend.sendWhynter(0x1234567890ABCDEF, 64); @@ -118,7 +127,8 @@ TEST(TestSendWhynter, SendUnusualSize) { "m750s2150m750s750m750s2150m750s750m750s2150m750s750m750s2150m750s2150" "m750s2150m750s2150m750s750m750s750m750s2150m750s2150m750s750m750s2150" "m750s2150m750s2150m750s2150m750s750m750s2150m750s2150m750s2150m750s2150" - "m750s108000", irsend.outputStr()); + "m750s12200", + irsend.outputStr()); } // Tests for decodeWhynter(). @@ -133,9 +143,9 @@ TEST(TestDecodeWhynter, NormalDecodeWithStrict) { irsend.reset(); irsend.sendWhynter(0x87654321); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); - EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(kWhynterBits, irsend.capture.bits); EXPECT_EQ(0x87654321, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); @@ -150,24 +160,24 @@ TEST(TestDecodeWhynter, NormalDecodeWithRepeatAndStrict) { // Normal Whynter 32-bit message with 2 repeats. irsend.reset(); - irsend.sendWhynter(0x87654321, WHYNTER_BITS, 2); + irsend.sendWhynter(0x87654321, kWhynterBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); - EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(kWhynterBits, irsend.capture.bits); EXPECT_EQ(0x87654321, irsend.capture.value); EXPECT_FALSE(irsend.capture.repeat); - irsend.makeDecodeResult(2 * WHYNTER_BITS + 6); - ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + irsend.makeDecodeResult(2 * kWhynterBits + 6); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); - EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(kWhynterBits, irsend.capture.bits); EXPECT_EQ(0x87654321, irsend.capture.value); - irsend.makeDecodeResult(2 * (2 * WHYNTER_BITS + 6)); - ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + irsend.makeDecodeResult(2 * (2 * kWhynterBits + 6)); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); - EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(kWhynterBits, irsend.capture.bits); EXPECT_EQ(0x87654321, irsend.capture.value); } @@ -181,7 +191,7 @@ TEST(TestDecodeWhynter, DecodeWithNonStrictSizes) { irsend.sendWhynter(0x12, 8); // Illegal sized Whynter 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, 8, true)); // Should pass if strict off. ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, 8, false)); @@ -195,7 +205,7 @@ TEST(TestDecodeWhynter, DecodeWithNonStrictSizes) { irsend.sendWhynter(0x1234567890, 40); // Illegal size Whynter 40-bit message. irsend.makeDecodeResult(); // Shouldn't pass with strict when we ask for less bits than we got. - ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. @@ -236,12 +246,13 @@ TEST(TestDecodeWhynter, FailToDecodeNonWhynterExample) { irsend.reset(); // Modified a few entries to unexpected values, based on previous test case. - uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, 20, 20, 20, - 20, 20, 20, 127, 20, 61, 9, 20, 20, 61, 20, 20, 20, - 61, 20, 61, 20, 61, 20, 20, 20, 20, 20, 20, 20, 884}; + uint16_t gc_test[39] = {38000, 1, 1, 322, 162, 20, 61, 20, 61, 20, + 20, 20, 20, 20, 20, 20, 127, 20, 61, 9, + 20, 20, 61, 20, 20, 20, 61, 20, 61, 20, + 61, 20, 20, 20, 20, 20, 20, 20, 884}; irsend.sendGC(gc_test, 39); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, false)); + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, false)); } diff --git a/lib/IRremoteESP8266-2.2.1.02/tools/Makefile b/lib/IRremoteESP8266-2.5.2.03/tools/Makefile similarity index 63% rename from lib/IRremoteESP8266-2.2.1.02/tools/Makefile rename to lib/IRremoteESP8266-2.5.2.03/tools/Makefile index 84bf6569b..c303e051d 100644 --- a/lib/IRremoteESP8266-2.2.1.02/tools/Makefile +++ b/lib/IRremoteESP8266-2.5.2.03/tools/Makefile @@ -22,10 +22,22 @@ CPPFLAGS += -DUNIT_TEST # Flags passed to the C++ compiler. CXXFLAGS += -g -Wall -Wextra -pthread -all : gc_decode +all : gc_decode mode2_decode + +run_tests : all + failed=""; \ + for py_unittest in *_test.py; do \ + echo "RUNNING: $${py_unittest}"; \ + python ./$${py_unittest} || failed="$${failed} $${py_unittest}"; \ + done; \ + if [ -n "$${failed}" ]; then \ + echo "FAIL: :-( :-( Unit test(s)$${failed} failed! :-( :-("; exit 1; \ + else \ + echo "PASS: \o/ \o/ All unit tests passed. \o/ \o/"; \ + fi clean : - rm -f *.o gc_decode + rm -f *.o *.pyc gc_decode mode2_decode # All the IR protocol object files. @@ -33,9 +45,13 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \ ir_LG.o ir_Mitsubishi.o ir_Fujitsu.o ir_Sharp.o ir_Sanyo.o \ ir_Denon.o ir_Dish.o ir_Panasonic.o ir_Whynter.o ir_Coolix.o \ ir_Aiwa.o ir_Sherwood.o ir_Kelvinator.o ir_Daikin.o ir_Gree.o \ - ir_Pronto.o ir_GlobalCache.o ir_Nikai.o + ir_Pronto.o ir_GlobalCache.o ir_Nikai.o ir_Toshiba.o ir_Midea.o \ + ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o ir_Hitachi.o \ + ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o ir_Pioneer.o \ + ir_MWM.o + # Common object files -COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o $(PROTOCOLS) +COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o $(PROTOCOLS) # Common dependencies COMMON_DEPS = $(USER_DIR)/IRrecv.h $(USER_DIR)/IRsend.h $(USER_DIR)/IRtimer.h \ @@ -49,8 +65,13 @@ gc_decode.o : gc_decode.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) gc_decode : $(COMMON_OBJ) gc_decode.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ +mode2_decode.o : mode2_decode.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -I$(TEST_DIR) -c mode2_decode.cpp -IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h +mode2_decode : $(COMMON_OBJ) mode2_decode.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRutils.cpp IRtimer.o : $(USER_DIR)/IRtimer.cpp $(USER_DIR)/IRtimer.h @@ -75,7 +96,7 @@ ir_Sherwood.o : $(USER_DIR)/ir_Sherwood.cpp $(COMMON_DEPS) ir_Sony.o : $(USER_DIR)/ir_Sony.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sony.cpp -ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(COMMON_DEPS) +ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(USER_DIR)/ir_Samsung.h $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Samsung.cpp ir_Kelvinator.o : $(USER_DIR)/ir_Kelvinator.cpp $(USER_DIR)/ir_Kelvinator.h $(COMMON_DEPS) @@ -134,3 +155,42 @@ ir_Pronto.o : $(USER_DIR)/ir_Pronto.cpp $(GTEST_HEADERS) ir_Nikai.o : $(USER_DIR)/ir_Nikai.cpp $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Nikai.cpp + +ir_Toshiba.o : $(USER_DIR)/ir_Toshiba.h $(USER_DIR)/ir_Toshiba.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Toshiba.cpp + +ir_Midea.o : $(USER_DIR)/ir_Midea.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Midea.cpp + +ir_Magiquest.o : $(USER_DIR)/ir_Magiquest.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Magiquest.cpp + +ir_Lasertag.o : $(USER_DIR)/ir_Lasertag.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lasertag.cpp + +ir_Carrier.o : $(USER_DIR)/ir_Carrier.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Carrier.cpp + +ir_Haier.o : $(USER_DIR)/ir_Haier.cpp $(USER_DIR)/ir_Haier.h $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Haier.cpp + +ir_Hitachi.o : $(USER_DIR)/ir_Hitachi.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Hitachi.cpp + +ir_GICable.o : $(USER_DIR)/ir_GICable.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_GICable.cpp + +ir_Whirlpool.o : $(USER_DIR)/ir_Whirlpool.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whirlpool.cpp + +ir_Lutron.o : $(USER_DIR)/ir_Lutron.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lutron.cpp + +ir_Electra.o : $(USER_DIR)/ir_Electra.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Electra.cpp + +ir_Pioneer.o : $(USER_DIR)/ir_Pioneer.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Pioneer.cpp + +ir_MWM.o : $(USER_DIR)/ir_MWM.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_MWM.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/RawToGlobalCache.sh b/lib/IRremoteESP8266-2.5.2.03/tools/RawToGlobalCache.sh new file mode 100644 index 000000000..e0b0ebe35 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/tools/RawToGlobalCache.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# Convert IRremoteESP8266's rawData output into Global Cache format. + +function isDigits() +{ + [[ "$1" =~ ^[0-9]+$ ]] +} + +function usage() +{ +cat << EOF +Usage: $0 Frequency_in_Hz + Reads an IRremoteESP8266 rawData declaration from STDIN and converts it to + GlobalCache format. + e.g. + uint16_t rawbuf[37] = { + 7930, 3952, 494, 1482, 520, 1482, 494, 1508, + 494, 520, 494, 1482, 494, 520, 494, 1482, + 494, 1482, 494, 3978, 494, 520, 494, 520, + 494, 520, 494, 520, 520, 520, 494, 520, + 494, 520, 494, 520, 494}; +EOF + exit 1 +} + +# We need a frequency argument. +if [[ $# -ne 1 ]]; then + usage +fi +HZ="$1" +# HZ must be a positive number +if ! isDigits "${HZ}"; then + usage +fi +# HZ must not be zero. +if [[ ${HZ} == 0 ]]; then + usage +fi + + +PERIOD_OFFSET=0 +period=$((((1000000 + (${HZ} / 2)) / ${HZ}) + ${PERIOD_OFFSET})) +result="${HZ},1,1" +while read line; do + # Quick and Dirty Removal of any array declaration syntax, and any commas. + line="$(echo ${line} | sed 's/uint.*{//i' | sed 's/,//g' | sed 's/};.*//g')" + for msecs in ${line}; do + if isDigits "${msecs}"; then + result="${result},$((${msecs} / ${period}))" + fi + done +done +echo "GlobalCache code = \"${result}\"" diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data.py b/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data.py new file mode 100644 index 000000000..5fd399807 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data.py @@ -0,0 +1,432 @@ +#!/usr/bin/python +"""Attempt an automatic analysis of IRremoteESP8266's Raw data output. + Makes suggestions on key values and tried to break down the message + into likely chunks.""" +# +# Copyright 2018 David Conran +import argparse +import sys + + +class RawIRMessage(object): + """Basic analyse functions & structure for raw IR messages.""" + + # pylint: disable=too-many-instance-attributes + + def __init__(self, margin, timings, output=sys.stdout, verbose=True): + self.hdr_mark = None + self.hdr_space = None + self.bit_mark = None + self.zero_space = None + self.one_space = None + self.gaps = [] + self.margin = margin + self.marks = [] + self.mark_buckets = {} + self.spaces = [] + self.space_buckets = {} + self.output = output + self.verbose = verbose + if len(timings) <= 3: + raise ValueError("Too few message timings supplied.") + self.timings = timings + self._generate_timing_candidates() + self._calc_values() + + def _generate_timing_candidates(self): + """Determine the likely values from the given data.""" + count = 0 + for usecs in self.timings: + count = count + 1 + if count % 2: + self.marks.append(usecs) + else: + self.spaces.append(usecs) + self.marks, self.mark_buckets = self.reduce_list(self.marks) + self.spaces, self.space_buckets = self.reduce_list(self.spaces) + + def reduce_list(self, items): + """Reduce a list of numbers into buckets that are at least margin apart.""" + result = [] + last = -1 + buckets = {} + for item in sorted(items, reverse=True): + if last == -1 or item < last - self.margin: + result.append(item) + last = item + buckets[last] = [item] + else: + buckets[last].append(item) + return result, buckets + + def _usec_compare(self, seen, expected): + """Compare two usec values and see if they match within a + subtractive margin.""" + return seen <= expected and seen > expected - self.margin + + def _usec_compares(self, usecs, expecteds): + """Compare a usec value to a list of values and return True + if they are within a subtractive margin.""" + for expected in expecteds: + if self._usec_compare(usecs, expected): + return True + return False + + def display_binary(self, binary_str): + """Display common representations of the suppied binary string.""" + num = int(binary_str, 2) + bits = len(binary_str) + rev_binary_str = binary_str[::-1] + rev_num = int(rev_binary_str, 2) + self.output.write("\n Bits: %d\n" + " Hex: %s (MSB first)\n" + " %s (LSB first)\n" + " Dec: %s (MSB first)\n" + " %s (LSB first)\n" + " Bin: 0b%s (MSB first)\n" + " 0b%s (LSB first)\n" % + (bits, "0x{0:0{1}X}".format(num, bits / 4), + "0x{0:0{1}X}".format(rev_num, bits / 4), num, rev_num, + binary_str, rev_binary_str)) + + def add_data_code(self, bin_str, footer=True): + """Add the common "data" sequence of code to send the bulk of a message.""" + # pylint: disable=no-self-use + code = [] + code.append(" // Data") + code.append(" // e.g. data = 0x%X, nbits = %d" % (int(bin_str, 2), + len(bin_str))) + code.append(" sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, " + "nbits, true);") + if footer: + code.append(" // Footer") + code.append(" mark(kBitMark);") + return code + + def _calc_values(self): + """Calculate the values which describe the standard timings + for the protocol.""" + if self.verbose: + self.output.write("Potential Mark Candidates:\n" + "%s\n" + "Potential Space Candidates:\n" + "%s\n" % (str(self.marks), str(self.spaces))) + # Largest mark is likely the kHdrMark + self.hdr_mark = self.marks[0] + # The bit mark is likely to be the smallest mark. + self.bit_mark = self.marks[-1] + + if self.is_space_encoded() and len(self.spaces) >= 3: + if self.verbose and len(self.marks) > 2: + self.output.write("DANGER: Unexpected and unused mark timings!") + # We should have 3 space candidates at least. + # They should be: zero_space (smallest), one_space, & hdr_space (largest) + spaces = list(self.spaces) + self.zero_space = spaces.pop() + self.one_space = spaces.pop() + self.hdr_space = spaces.pop() + # Rest are probably message gaps + self.gaps = spaces + + def is_space_encoded(self): + """Make an educated guess if the message is space encoded.""" + return len(self.spaces) > len(self.marks) + + def is_hdr_mark(self, usec): + """Is usec the header mark?""" + return self._usec_compare(usec, self.hdr_mark) + + def is_hdr_space(self, usec): + """Is usec the header space?""" + return self._usec_compare(usec, self.hdr_space) + + def is_bit_mark(self, usec): + """Is usec the bit mark?""" + return self._usec_compare(usec, self.bit_mark) + + def is_one_space(self, usec): + """Is usec the one space?""" + return self._usec_compare(usec, self.one_space) + + def is_zero_space(self, usec): + """Is usec the zero_space?""" + return self._usec_compare(usec, self.zero_space) + + def is_gap(self, usec): + """Is usec the a space gap?""" + return self._usec_compares(usec, self.gaps) + + +def avg_list(items): + """Return the average of a list of numbers.""" + if items: + return sum(items) / len(items) + return 0 + + +def add_bit(so_far, bit, output=sys.stdout): + """Add a bit to the end of the bits collected so far.""" + if bit == "reset": + return "" + output.write(str(bit)) # This effectively displays in LSB first order. + return so_far + str(bit) # Storing it in MSB first order. + + +def convert_rawdata(data_str): + """Parse a C++ rawdata declaration into a list of values.""" + start = data_str.find('{') + end = data_str.find('}') + if end == -1: + end = len(data_str) + if start > end: + raise ValueError("Raw Data not parsible due to parentheses placement.") + data_str = data_str[start + 1:end] + results = [] + for timing in [x.strip() for x in data_str.split(',')]: + try: + results.append(int(timing)) + except ValueError: + raise ValueError( + "Raw Data contains a non-numeric value of '%s'." % timing) + return results + + +def dump_constants(message, defines, output=sys.stdout): + """Dump the key constants and generate the C++ #defines.""" + hdr_mark = avg_list(message.mark_buckets[message.hdr_mark]) + bit_mark = avg_list(message.mark_buckets[message.bit_mark]) + hdr_space = avg_list(message.space_buckets[message.hdr_space]) + one_space = avg_list(message.space_buckets[message.one_space]) + zero_space = avg_list(message.space_buckets[message.zero_space]) + + output.write("Guessing key value:\n" + "kHdrMark = %d\n" + "kHdrSpace = %d\n" + "kBitMark = %d\n" + "kOneSpace = %d\n" + "kZeroSpace = %d\n" % (hdr_mark, hdr_space, bit_mark, one_space, + zero_space)) + defines.append("const uint16_t kHdrMark = %d;" % hdr_mark) + defines.append("const uint16_t kBitMark = %d;" % bit_mark) + defines.append("const uint16_t kHdrSpace = %d;" % hdr_space) + defines.append("const uint16_t kOneSpace = %d;" % one_space) + defines.append("const uint16_t kZeroSpace = %d;" % zero_space) + + avg_gaps = [avg_list(message.space_buckets[x]) for x in message.gaps] + if len(message.gaps) == 1: + output.write("kSpaceGap = %d\n" % avg_gaps[0]) + defines.append("const uint16_t kSpaceGap = %d;" % avg_gaps[0]) + else: + count = 0 + for gap in avg_gaps: + # We probably (still) have a gap in the protocol. + count = count + 1 + output.write("kSpaceGap%d = %d\n" % (count, gap)) + defines.append("const uint16_t kSpaceGap%d = %d;" % (count, gap)) + + +def parse_and_report(rawdata_str, margin, gen_code=False, output=sys.stdout): + """Analyse the rawdata c++ definition of a IR message.""" + defines = [] + function_code = [] + + # Parse the input. + rawdata = convert_rawdata(rawdata_str) + + output.write("Found %d timing entries.\n" % len(rawdata)) + + message = RawIRMessage(margin, rawdata, output) + output.write("\nGuessing encoding type:\n") + if message.is_space_encoded(): + output.write("Looks like it uses space encoding. Yay!\n\n") + dump_constants(message, defines, output) + else: + output.write("Sorry, it looks like it is Mark encoded. " + "I can't do that yet. Exiting.\n") + sys.exit(1) + total_bits = decode_data(message, defines, function_code, output) + if gen_code: + generate_irsend_code(defines, function_code, total_bits, output) + + +def decode_data(message, defines, function_code, output=sys.stdout): + """Decode the data sequence with the given values in mind.""" + # pylint: disable=too-many-branches,too-many-statements + + # Now we have likely candidates for the key values, go through the original + # sequence and break it up and indicate accordingly. + + output.write("\nDecoding protocol based on analysis so far:\n\n") + state = "" + count = 1 + total_bits = "" + binary_value = add_bit("", "reset") + + function_code.extend([ + "// Function should be safe up to 64 bits.", + "void IRsend::sendXyz(const uint64_t data, const uint16_t" + " nbits, const uint16_t repeat) {", + " enableIROut(38); // A guess. Most common frequency.", + " for (uint16_t r = 0; r <= repeat; r++) {" + ]) + + for usec in message.timings: + if (message.is_hdr_mark(usec) and count % 2 and + not message.is_bit_mark(usec)): + state = "HM" + if binary_value: + message.display_binary(binary_value) + function_code.extend(message.add_data_code(binary_value, False)) + total_bits = total_bits + binary_value + binary_value = add_bit(binary_value, "reset") + output.write("kHdrMark+") + function_code.extend([" // Header", " mark(kHdrMark);"]) + elif message.is_hdr_space(usec) and not message.is_one_space(usec): + if state != "HM": + if binary_value: + message.display_binary(binary_value) + total_bits = total_bits + binary_value + function_code.extend(message.add_data_code(binary_value)) + binary_value = add_bit(binary_value, "reset") + output.write("UNEXPECTED->") + state = "HS" + output.write("kHdrSpace+") + function_code.append(" space(kHdrSpace);") + elif message.is_bit_mark(usec) and count % 2: + if state != "HS" and state != "BS": + output.write("kBitMark(UNEXPECTED)") + state = "BM" + elif message.is_zero_space(usec): + if state != "BM": + output.write("kZeroSpace(UNEXPECTED)") + state = "BS" + binary_value = add_bit(binary_value, 0, output) + elif message.is_one_space(usec): + if state != "BM": + output.write("kOneSpace(UNEXPECTED)") + state = "BS" + binary_value = add_bit(binary_value, 1, output) + elif message.is_gap(usec): + if state != "BM": + output.write("UNEXPECTED->") + state = "GS" + output.write("GAP(%d)" % usec) + if binary_value: + message.display_binary(binary_value) + function_code.extend(message.add_data_code(binary_value)) + else: + function_code.extend([" // Gap", " mark(kBitMark);"]) + function_code.append(" space(kSpaceGap);") + total_bits = total_bits + binary_value + binary_value = add_bit(binary_value, "reset") + else: + output.write("UNKNOWN(%d)" % usec) + state = "UNK" + count = count + 1 + if binary_value: + message.display_binary(binary_value) + function_code.extend(message.add_data_code(binary_value)) + function_code.extend([ + " space(100000); // A 100% made up guess of the gap" + " between messages.", " }", "}" + ]) + + total_bits = total_bits + binary_value + output.write("\nTotal Nr. of suspected bits: %d\n" % len(total_bits)) + defines.append("const uint16_t kXyzBits = %d;" % len(total_bits)) + if len(total_bits) > 64: + defines.append("const uint16_t kXyzStateLength = %d;" % + (len(total_bits) / 8)) + return total_bits + + +def generate_irsend_code(defines, normal, bits_str, output=sys.stdout): + """Output the estimated C++ code to reproduce the IR message.""" + output.write("\nGenerating a VERY rough code outline:\n\n" + "// WARNING: This probably isn't directly usable." + " It's a guide only.\n") + for line in defines: + output.write("%s\n" % line) + + if len(bits_str) > 64: # Will it fit in a uint64_t? + output.write("// DANGER: More than 64 bits detected. A uint64_t for " + "'data' won't work!\n") + # Display the "normal" version's code incase there are some + # oddities in it. + for line in normal: + output.write("%s\n" % line) + + if len(bits_str) > 64: # Will it fit in a uint64_t? + output.write("\n\n// Alternative >64 bit Function\n" + "void IRsend::sendXyz(uint8_t data[], uint16_t nbytes," + " uint16_t repeat) {\n" + " // nbytes should typically be kXyzStateLength\n" + " // data should typically be:\n" + " // uint8_t data[kXyzStateLength] = {0x%s};\n" + " // data[] is assumed to be in MSB order for this code.\n" + " for (uint16_t r = 0; r <= repeat; r++) {\n" + " sendGeneric(kHdrMark, kHdrSpace,\n" + " kBitMark, kOneSpace,\n" + " kBitMark, kZeroSpace,\n" + " kBitMark,\n" + " 100000, // 100%% made-up guess at the" + " message gap.\n" + " data, nbytes,\n" + " 38000, // Complete guess of the modulation" + " frequency.\n" + " true, 0, 50);\n" + " }\n" + "}\n" % ", 0x".join("%02X" % int(bits_str[i:i + 8], 2) + for i in range(0, len(bits_str), 8))) + + +def main(): + """Parse the commandline arguments and call the method.""" + arg_parser = argparse.ArgumentParser( + description="Read an IRremoteESP8266 rawData declaration and tries to " + "analyse it.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + arg_parser.add_argument( + "-g", + "--code", + action="store_true", + default=False, + dest="gen_code", + help="Generate a C++ code outline to aid making an IRsend function.") + arg_group = arg_parser.add_mutually_exclusive_group(required=True) + arg_group.add_argument( + "rawdata", + help="A rawData line from IRrecvDumpV2. e.g. 'uint16_t rawbuf[37] = {" + "7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, " + "520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, " + "494, 520, 520, 520, 494, 520, 494, 520, 494, 520, 494};'", + nargs="?") + arg_group.add_argument( + "-f", "--file", help="Read in a rawData line from the file.") + arg_parser.add_argument( + "-r", + "--range", + type=int, + help="Max number of micro-seconds difference between values to consider" + " it the same value.", + dest="margin", + default=200) + arg_group.add_argument( + "--stdin", + help="Read in a rawData line from STDIN.", + action="store_true", + default=False) + arg_options = arg_parser.parse_args() + + if arg_options.stdin: + data = sys.stdin.read() + elif arg_options.file: + with open(arg_options.file) as input_file: + data = input_file.read() + else: + data = arg_options.rawdata + parse_and_report(data, arg_options.margin, arg_options.gen_code) + + +if __name__ == '__main__': + main() diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data_test.py b/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data_test.py new file mode 100644 index 000000000..681ff5520 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data_test.py @@ -0,0 +1,492 @@ +#!/usr/bin/python +"""Unit tests for auto_analyse_raw_data.py""" +import StringIO +import unittest +import auto_analyse_raw_data as analyse + + +class TestRawIRMessage(unittest.TestCase): + """Unit tests for the RawIRMessage class.""" + + # pylint: disable=too-many-public-methods + + def test_display_binary(self): + """Test the display_binary() method.""" + output = StringIO.StringIO() + message = analyse.RawIRMessage(100, [8000, 4000, 500, 500, 500], output, + False) + self.assertEqual(output.getvalue(), '') + message.display_binary("10101010") + message.display_binary("0000000000000000") + message.display_binary("00010010001101000101011001111000") + self.assertEqual(output.getvalue(), '\n' + ' Bits: 8\n' + ' Hex: 0xAA (MSB first)\n' + ' 0x55 (LSB first)\n' + ' Dec: 170 (MSB first)\n' + ' 85 (LSB first)\n' + ' Bin: 0b10101010 (MSB first)\n' + ' 0b01010101 (LSB first)\n' + '\n' + ' Bits: 16\n' + ' Hex: 0x0000 (MSB first)\n' + ' 0x0000 (LSB first)\n' + ' Dec: 0 (MSB first)\n' + ' 0 (LSB first)\n' + ' Bin: 0b0000000000000000 (MSB first)\n' + ' 0b0000000000000000 (LSB first)\n' + '\n' + ' Bits: 32\n' + ' Hex: 0x12345678 (MSB first)\n' + ' 0x1E6A2C48 (LSB first)\n' + ' Dec: 305419896 (MSB first)\n' + ' 510274632 (LSB first)\n' + ' Bin: 0b00010010001101000101011001111000 (MSB first)\n' + ' 0b00011110011010100010110001001000 (LSB first)\n') + + +class TestAutoAnalyseRawData(unittest.TestCase): + """Unit tests for the functions in AutoAnalyseRawData.""" + + # pylint: disable=too-many-public-methods + + def test_dump_constants_simple(self): + """Simple tests for the dump_constants() function.""" + ignore = StringIO.StringIO() + output = StringIO.StringIO() + defs = [] + message = analyse.RawIRMessage(200, [ + 7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, + 520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, 494, + 520, 520, 520, 494, 520, 494, 520, 494, 1482, 494 + ], ignore) + analyse.dump_constants(message, defs, output) + self.assertEqual(defs, [ + 'const uint16_t kHdrMark = 7930;', 'const uint16_t kBitMark = 496;', + 'const uint16_t kHdrSpace = 3965;', 'const uint16_t kOneSpace = 1485;', + 'const uint16_t kZeroSpace = 520;' + ]) + self.assertEqual(output.getvalue(), 'Guessing key value:\n' + 'kHdrMark = 7930\n' + 'kHdrSpace = 3965\n' + 'kBitMark = 496\n' + 'kOneSpace = 1485\n' + 'kZeroSpace = 520\n') + + def test_dump_constants_aircon(self): + """More complex tests for the dump_constants() function.""" + ignore = StringIO.StringIO() + output = StringIO.StringIO() + defs = [] + message = analyse.RawIRMessage(200, [ + 9008, 4496, 644, 1660, 676, 530, 648, 558, 672, 1636, 646, 1660, 644, + 556, 650, 584, 626, 560, 644, 580, 628, 1680, 624, 560, 648, 1662, 644, + 582, 648, 536, 674, 530, 646, 580, 628, 560, 670, 532, 646, 562, 644, + 556, 672, 536, 648, 1662, 646, 1660, 652, 554, 644, 558, 672, 538, 644, + 560, 668, 560, 648, 1638, 668, 536, 644, 1660, 668, 532, 648, 560, 648, + 1660, 674, 554, 622, 19990, 646, 580, 624, 1660, 648, 556, 648, 558, + 674, 556, 622, 560, 644, 564, 668, 536, 646, 1662, 646, 1658, 672, 534, + 648, 558, 644, 562, 648, 1662, 644, 584, 622, 558, 648, 562, 668, 534, + 670, 536, 670, 532, 672, 536, 646, 560, 646, 558, 648, 558, 670, 534, + 650, 558, 646, 560, 646, 560, 668, 1638, 646, 1662, 646, 1660, 646, + 1660, 648 + ], ignore) + analyse.dump_constants(message, defs, output) + self.assertEqual(defs, [ + 'const uint16_t kHdrMark = 9008;', 'const uint16_t kBitMark = 650;', + 'const uint16_t kHdrSpace = 4496;', 'const uint16_t kOneSpace = 1657;', + 'const uint16_t kZeroSpace = 554;', 'const uint16_t kSpaceGap = 19990;' + ]) + self.assertEqual(output.getvalue(), 'Guessing key value:\n' + 'kHdrMark = 9008\n' + 'kHdrSpace = 4496\n' + 'kBitMark = 650\n' + 'kOneSpace = 1657\n' + 'kZeroSpace = 554\n' + 'kSpaceGap = 19990\n') + + def test_convert_rawdata(self): + """Tests for the convert_rawdata() function.""" + # trivial cases + self.assertEqual(analyse.convert_rawdata("0"), [0]) + with self.assertRaises(ValueError) as context: + analyse.convert_rawdata("") + self.assertEqual(context.exception.message, + "Raw Data contains a non-numeric value of ''.") + + # Single parenthesis + self.assertEqual(analyse.convert_rawdata("foo {10"), [10]) + self.assertEqual(analyse.convert_rawdata("20} bar"), [20]) + + # No parentheses + self.assertEqual(analyse.convert_rawdata("10,20 , 30"), [10, 20, 30]) + + # Dual parentheses + self.assertEqual(analyse.convert_rawdata("{10,20 , 30}"), [10, 20, 30]) + self.assertEqual(analyse.convert_rawdata("foo{10,20}bar"), [10, 20]) + + # Many parentheses + self.assertEqual(analyse.convert_rawdata("foo{10,20}{bar}"), [10, 20]) + self.assertEqual(analyse.convert_rawdata("foo{10,20}{bar}}{"), [10, 20]) + + # Bad parentheses + with self.assertRaises(ValueError) as context: + analyse.convert_rawdata("}10{") + self.assertEqual(context.exception.message, + "Raw Data not parsible due to parentheses placement.") + + # Non base-10 values + with self.assertRaises(ValueError) as context: + analyse.convert_rawdata("10, 20, foo, bar, 30") + self.assertEqual(context.exception.message, + "Raw Data contains a non-numeric value of 'foo'.") + + # A messy usual "good" case. + input_str = """uint16_t rawbuf[6] = { + 9008, 4496, 644, + 1660, 676, + + 530} + ;""" + self.assertEqual( + analyse.convert_rawdata(input_str), [9008, 4496, 644, 1660, 676, 530]) + + def test_parse_and_report(self): + """Tests for the parse_and_report() function.""" + + # Without code generation. + output = StringIO.StringIO() + input_str = """ + uint16_t rawbuf[139] = {9008, 4496, 644, 1660, 676, 530, 648, 558, 672, + 1636, 646, 1660, 644, 556, 650, 584, 626, 560, 644, 580, 628, 1680, + 624, 560, 648, 1662, 644, 582, 648, 536, 674, 530, 646, 580, 628, + 560, 670, 532, 646, 562, 644, 556, 672, 536, 648, 1662, 646, 1660, + 652, 554, 644, 558, 672, 538, 644, 560, 668, 560, 648, 1638, 668, + 536, 644, 1660, 668, 532, 648, 560, 648, 1660, 674, 554, 622, 19990, + 646, 580, 624, 1660, 648, 556, 648, 558, 674, 556, 622, 560, 644, + 564, 668, 536, 646, 1662, 646, 1658, 672, 534, 648, 558, 644, 562, + 648, 1662, 644, 584, 622, 558, 648, 562, 668, 534, 670, 536, 670, + 532, 672, 536, 646, 560, 646, 558, 648, 558, 670, 534, 650, 558, + 646, 560, 646, 560, 668, 1638, 646, 1662, 646, 1660, 646, 1660, + 648};""" + analyse.parse_and_report(input_str, 200, False, output) + self.assertEqual( + output.getvalue(), 'Found 139 timing entries.\n' + 'Potential Mark Candidates:\n' + '[9008, 676]\n' + 'Potential Space Candidates:\n' + '[19990, 4496, 1680, 584]\n' + '\n' + 'Guessing encoding type:\n' + 'Looks like it uses space encoding. Yay!\n' + '\n' + 'Guessing key value:\n' + 'kHdrMark = 9008\n' + 'kHdrSpace = 4496\n' + 'kBitMark = 650\n' + 'kOneSpace = 1657\n' + 'kZeroSpace = 554\n' + 'kSpaceGap = 19990\n' + '\n' + 'Decoding protocol based on analysis so far:\n' + '\n' + 'kHdrMark+kHdrSpace+10011000010100000000011000001010010GAP(19990)\n' + ' Bits: 35\n' + ' Hex: 0x4C2803052 (MSB first)\n' + ' 0x250600A19 (LSB first)\n' + ' Dec: 20443050066 (MSB first)\n' + ' 9938405913 (LSB first)\n' + ' Bin: 0b10011000010100000000011000001010010 (MSB first)\n' + ' 0b01001010000011000000000101000011001 (LSB first)\n' + 'kBitMark(UNEXPECTED)01000000110001000000000000001111\n' + ' Bits: 32\n' + ' Hex: 0x40C4000F (MSB first)\n' + ' 0xF0002302 (LSB first)\n' + ' Dec: 1086586895 (MSB first)\n' + ' 4026540802 (LSB first)\n' + ' Bin: 0b01000000110001000000000000001111 (MSB first)\n' + ' 0b11110000000000000010001100000010 (LSB first)\n' + '\n' + 'Total Nr. of suspected bits: 67\n') + + # With code generation. + output = StringIO.StringIO() + input_str = """ + uint16_t rawbuf[37] = {7930, 3952, 494, 1482, 520, 1482, 494, + 1508, 494, 520, 494, 1482, 494, 520, 494, 1482, 494, 1482, 494, + 3978, 494, 520, 494, 520, 494, 520, 494, 520, 520, 520, 494, 520, + 494, 520, 494, 1482, 494};""" + analyse.parse_and_report(input_str, 200, True, output) + self.assertEqual( + output.getvalue(), 'Found 37 timing entries.\n' + 'Potential Mark Candidates:\n' + '[7930, 520]\n' + 'Potential Space Candidates:\n' + '[3978, 1508, 520]\n' + '\n' + 'Guessing encoding type:\n' + 'Looks like it uses space encoding. Yay!\n' + '\n' + 'Guessing key value:\n' + 'kHdrMark = 7930\n' + 'kHdrSpace = 3965\n' + 'kBitMark = 496\n' + 'kOneSpace = 1485\n' + 'kZeroSpace = 520\n' + '\n' + 'Decoding protocol based on analysis so far:\n' + '\n' + 'kHdrMark+kHdrSpace+11101011\n' + ' Bits: 8\n' + ' Hex: 0xEB (MSB first)\n' + ' 0xD7 (LSB first)\n' + ' Dec: 235 (MSB first)\n' + ' 215 (LSB first)\n' + ' Bin: 0b11101011 (MSB first)\n' + ' 0b11010111 (LSB first)\n' + 'UNEXPECTED->kHdrSpace+00000001\n' + ' Bits: 8\n' + ' Hex: 0x01 (MSB first)\n' + ' 0x80 (LSB first)\n' + ' Dec: 1 (MSB first)\n' + ' 128 (LSB first)\n' + ' Bin: 0b00000001 (MSB first)\n' + ' 0b10000000 (LSB first)\n' + '\n' + 'Total Nr. of suspected bits: 16\n' + '\n' + 'Generating a VERY rough code outline:\n' + '\n' + "// WARNING: This probably isn't directly usable. It's a guide only.\n" + 'const uint16_t kHdrMark = 7930;\n' + 'const uint16_t kBitMark = 496;\n' + 'const uint16_t kHdrSpace = 3965;\n' + 'const uint16_t kOneSpace = 1485;\n' + 'const uint16_t kZeroSpace = 520;\n' + 'const uint16_t kXyzBits = 16;\n' + '// Function should be safe up to 64 bits.\n' + 'void IRsend::sendXyz(const uint64_t data, const uint16_t nbits,' + ' const uint16_t repeat) {\n' + ' enableIROut(38); // A guess. Most common frequency.\n' + ' for (uint16_t r = 0; r <= repeat; r++) {\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Data\n' + ' // e.g. data = 0xEB, nbits = 8\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' + ' true);\n' + ' // Footer\n' + ' mark(kBitMark);\n' + ' space(kHdrSpace);\n' + ' // Data\n' + ' // e.g. data = 0x1, nbits = 8\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' + ' true);\n' + ' // Footer\n' + ' mark(kBitMark);\n' + ' space(100000); // A 100% made up guess of the gap between' + ' messages.\n' + ' }\n' + '}\n') + + def test_unusual_gaps(self): + """Tests for unusual Space Gaps in parse_and_report() function.""" + + # Tests for unusual Gaps. (Issue #482) + output = StringIO.StringIO() + input_str = """ + uint16_t rawbuf[272] = {3485, 3512, 864, 864, 864, 2620, 864, 864, + 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, + 864, 2620, 864, 864, 864, 2620, 864, 2620, 864, 2620, 864, 2620, + 864, 2620, 864, 864, 864, 2620, 864, 864, 864, 864, 864, 864, + 864, 864, 864, 864, 864, 864, 864, 864, 864, 2620, 864, 864, + 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, + 3485, 3512, 864, 864, 864, 2620, 864, 864, 864, 2620, 864, 2620, + 864, 2620, 864, 2620, 864, 2620, 864, 864, 864, 2620, 864, 864, + 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, + 864, 2620, 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, + 864, 864, 864, 864, 2620, 864, 864, 864, 864, 864, 864, 864, 864, + 864, 864, 864, 864, + 3485, 3512, 864, 13996, + 3485, 3512, 864, 864, 864, 864, 864, 2620, 864, 864, 864, 2620, + 864, 2620, 864, 2620, 864, 2620, 864, 864, 864, 864, 864, 2620, + 864, 864, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, + 864, 2620, 864, 2620, 864, 864, 864, 2620, 864, 2620, 864, 864, + 864, 864, 864, 864, 864, 2620, 864, 2620, 864, 864, 864, 2620, + 864, 2620, 864, 864, 864, 864, + 3485, 3512, 864, 864, 864, 864, 864, 2620, 864, 864, 864, 2620, + 864, 2620, 864, 2620, 864, 2620, 864, 864, 864, 864, 864, 2620, + 864, 864, 864, 2620, 864, 2620, 864, 2620, 864, 2620, 864, 864, + 864, 2620, 864, 2620, 864, 864, 864, 2620, 864, 2620, 864, 864, + 864, 864, 864, 864, 864, 2620, 864, 2620, 864, 864, 864, 2620, + 864, 2620, 864, 864, 864, 864, 3485, 3512, 864, 13996};""" + analyse.parse_and_report(input_str, 200, True, output) + self.assertEqual( + output.getvalue(), 'Found 272 timing entries.\n' + 'Potential Mark Candidates:\n' + '[3485, 864]\n' + 'Potential Space Candidates:\n' + '[13996, 3512, 2620, 864]\n' + '\n' + 'Guessing encoding type:\n' + 'Looks like it uses space encoding. Yay!\n' + '\n' + 'Guessing key value:\n' + 'kHdrMark = 3485\n' + 'kHdrSpace = 3512\n' + 'kBitMark = 864\n' + 'kOneSpace = 2620\n' + 'kZeroSpace = 864\n' + 'kSpaceGap = 13996\n' + '\n' + 'Decoding protocol based on analysis so far:\n' + '\n' + 'kHdrMark+kHdrSpace+01011111010111110100000001000000\n' + ' Bits: 32\n' + ' Hex: 0x5F5F4040 (MSB first)\n' + ' 0x0202FAFA (LSB first)\n' + ' Dec: 1600077888 (MSB first)\n' + ' 33749754 (LSB first)\n' + ' Bin: 0b01011111010111110100000001000000 (MSB first)\n' + ' 0b00000010000000101111101011111010 (LSB first)\n' + 'kHdrMark+kHdrSpace+01011111010111110100000001000000\n' + ' Bits: 32\n' + ' Hex: 0x5F5F4040 (MSB first)\n' + ' 0x0202FAFA (LSB first)\n' + ' Dec: 1600077888 (MSB first)\n' + ' 33749754 (LSB first)\n' + ' Bin: 0b01011111010111110100000001000000 (MSB first)\n' + ' 0b00000010000000101111101011111010 (LSB first)\n' + 'kHdrMark+kHdrSpace+GAP(13996)' + 'kHdrMark+kHdrSpace+00101111001011110110110001101100\n' + ' Bits: 32\n' + ' Hex: 0x2F2F6C6C (MSB first)\n' + ' 0x3636F4F4 (LSB first)\n' + ' Dec: 791637100 (MSB first)\n' + ' 909571316 (LSB first)\n' + ' Bin: 0b00101111001011110110110001101100 (MSB first)\n' + ' 0b00110110001101101111010011110100 (LSB first)\n' + 'kHdrMark+kHdrSpace+00101111001011110110110001101100\n' + ' Bits: 32\n' + ' Hex: 0x2F2F6C6C (MSB first)\n' + ' 0x3636F4F4 (LSB first)\n' + ' Dec: 791637100 (MSB first)\n' + ' 909571316 (LSB first)\n' + ' Bin: 0b00101111001011110110110001101100 (MSB first)\n' + ' 0b00110110001101101111010011110100 (LSB first)\n' + 'kHdrMark+kHdrSpace+GAP(13996)\n' + 'Total Nr. of suspected bits: 128\n' + '\n' + 'Generating a VERY rough code outline:\n' + '\n' + "// WARNING: This probably isn't directly usable. It's a guide only.\n" + 'const uint16_t kHdrMark = 3485;\n' + 'const uint16_t kBitMark = 864;\n' + 'const uint16_t kHdrSpace = 3512;\n' + 'const uint16_t kOneSpace = 2620;\n' + 'const uint16_t kZeroSpace = 864;\n' + 'const uint16_t kSpaceGap = 13996;\n' + 'const uint16_t kXyzBits = 128;\n' + 'const uint16_t kXyzStateLength = 16;\n' + "// DANGER: More than 64 bits detected. A uint64_t for 'data' won't" + ' work!\n' + '// Function should be safe up to 64 bits.\n' + 'void IRsend::sendXyz(const uint64_t data, const uint16_t nbits,' + ' const uint16_t repeat) {\n' + ' enableIROut(38); // A guess. Most common frequency.\n' + ' for (uint16_t r = 0; r <= repeat; r++) {\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Data\n' + ' // e.g. data = 0x5F5F4040, nbits = 32\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' + ' true);\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Data\n' + ' // e.g. data = 0x5F5F4040, nbits = 32\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' + ' true);\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Gap\n' + ' mark(kBitMark);\n' + ' space(kSpaceGap);\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Data\n' + ' // e.g. data = 0x2F2F6C6C, nbits = 32\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' + ' true);\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Data\n' + ' // e.g. data = 0x2F2F6C6C, nbits = 32\n' + ' sendData(kBitMark, kOneSpace, kBitMark, kZeroSpace, data, nbits,' + ' true);\n' + ' // Header\n' + ' mark(kHdrMark);\n' + ' space(kHdrSpace);\n' + ' // Gap\n' + ' mark(kBitMark);\n' + ' space(kSpaceGap);\n' + ' space(100000); // A 100% made up guess of the gap between' + ' messages.\n' + ' }\n' + '}\n' + '\n' + '\n' + '// Alternative >64 bit Function\n' + 'void IRsend::sendXyz(uint8_t data[], uint16_t nbytes, uint16_t repeat)' + ' {\n' + ' // nbytes should typically be kXyzStateLength\n' + ' // data should typically be:\n' + ' // uint8_t data[kXyzStateLength] = {0x5F, 0x5F, 0x40, 0x40, 0x5F,' + ' 0x5F, 0x40, 0x40, 0x2F, 0x2F, 0x6C, 0x6C, 0x2F, 0x2F, 0x6C, 0x6C};\n' + ' // data[] is assumed to be in MSB order for this code.\n' + ' for (uint16_t r = 0; r <= repeat; r++) {\n' + ' sendGeneric(kHdrMark, kHdrSpace,\n' + ' kBitMark, kOneSpace,\n' + ' kBitMark, kZeroSpace,\n' + ' kBitMark,\n' + ' 100000, // 100% made-up guess at the message gap.\n' + ' data, nbytes,\n' + ' 38000, // Complete guess of the modulation' + ' frequency.\n' + ' true, 0, 50);\n' + ' }\n' + '}\n') + + def test_reduce_list(self): + """Tests for the reduce_list method.""" + + ignore = StringIO.StringIO() + message = analyse.RawIRMessage(200, [ + 7930, 3952, 494, 1482, 520, 1482, 494, 1508, 494, 520, 494, 1482, 494, + 520, 494, 1482, 494, 1482, 494, 3978, 494, 520, 494, 520, 494, 520, 494, + 520, 520, 520, 494, 520, 494, 520, 494, 1482, 494 + ], ignore) + test_space_data = [4496, 1660, 530, 558, 1636, 1660, 556] + result_list, result_dict = message.reduce_list(test_space_data) + self.assertEqual([4496, 1660, 558], result_list) + self.assertEqual({ + 558: [558, 556, 530], + 1660: [1660, 1660, 1636], + 4496: [4496] + }, result_dict) + + def test_avg_list(self): + """Tests for the avg_list method.""" + + self.assertEqual(0, analyse.avg_list([])) + self.assertEqual(23, analyse.avg_list([10, 20, 40])) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/gc_decode.cpp b/lib/IRremoteESP8266-2.5.2.03/tools/gc_decode.cpp new file mode 100644 index 000000000..52ffd17b7 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/tools/gc_decode.cpp @@ -0,0 +1,109 @@ +// Quick and dirty tool to decode GlobalCache (GC) codes +// and ProntoHex codes +// Copyright 2017 Jorge Cisneros + +#include +#include +#include +#include +#include +#include "IRsend.h" +#include "IRsend_test.h" +#include "IRutils.h" + +const uint16_t kMaxGcCodeLength = 10000; + +void str_to_uint16(char *str, uint16_t *res, uint8_t base) { + char *end; + errno = 0; + intmax_t val = strtoimax(str, &end, base); + if (errno == ERANGE || val < 0 || val > UINT16_MAX || end == str || + *end != '\0') + return; + *res = (uint16_t)val; +} + +void usage_error(char *name) { + std::cerr << "Usage: " << name << " [-raw] " << std::endl + << "Usage: " << name << " -prontohex [-raw] " + << std::endl; +} + +int main(int argc, char *argv[]) { + int argv_offset = 1; + bool dumpraw = false; + bool prontohex = false; + + // Check the invocation/calling usage. + if (argc < 2 || argc > 4) { + usage_error(argv[0]); + return 1; + } + if (strncmp("-prontohex", argv[argv_offset], 10) == 0) { + prontohex = true; + argv_offset++; + } + + if (strncmp("-raw", argv[argv_offset], 4) == 0) { + dumpraw = true; + argv_offset++; + } + if (argc - argv_offset != 1) { + usage_error(argv[0]); + return 1; + } + + uint16_t gc_test[kMaxGcCodeLength]; + int index = 0; + char *pch; + char *saveptr1; + char *sep = const_cast(","); + int codebase = 10; + + if (prontohex) { + sep = const_cast(" "); + codebase = 16; + } + + pch = strtok_r(argv[argv_offset], sep, &saveptr1); + while (pch != NULL && index < kMaxGcCodeLength) { + str_to_uint16(pch, &gc_test[index], codebase); + pch = strtok_r(NULL, sep, &saveptr1); + index++; + } + + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + irsend.reset(); + + if (prontohex) { + irsend.sendPronto(gc_test, index); + } else { + irsend.sendGC(gc_test, index); + } + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + + std::cout << "Code length " << index << std::endl + << "Code type " << irsend.capture.decode_type << " (" + << typeToString(irsend.capture.decode_type) << ")" << std::endl + << "Code bits " << irsend.capture.bits << std::endl; + if (hasACState(irsend.capture.decode_type)) { + std::cout << "State value 0x"; + for (uint16_t i = 0; i < irsend.capture.bits / 8; i++) + printf("%02X", irsend.capture.state[i]); + std::cout << std::endl; + } else { + std::cout << "Code value 0x" << std::hex << irsend.capture.value + << std::endl + << "Code address 0x" << std::hex << irsend.capture.address + << std::endl + << "Code command 0x" << std::hex << irsend.capture.command + << std::endl; + } + + if (dumpraw || irsend.capture.decode_type == UNKNOWN) irsend.dumpRawResult(); + + return 0; +} diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/mkkeywords b/lib/IRremoteESP8266-2.5.2.03/tools/mkkeywords new file mode 100644 index 000000000..a2cdccd9b --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/tools/mkkeywords @@ -0,0 +1,82 @@ +#!/bin/bash +# Generate a keywords.txt for the library that is suitable for the Arduino IDE. +# Expects to run from the top directory of the library. + +# Set the locale for sorting +export LC_ALL=C + +cat << EndOfTextEndOfTextEndOfText +######################################### +# Syntax Coloring Map For IRremoteESP8266 +######################################### + +################################################ +# WARNING: Do NOT edit this file directly. +# It is generated by 'tools/mkkeywords' +# e.g. tools/mkkeywords > keywords.txt +################################################ + +####################################################### +# The Arduino IDE requires the use of a tab separator +# between the name and identifier. Without this tab the +# keyword is not highlighted. +# +# Reference: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords +####################################################### + +####################################### +# Datatypes & Classes (KEYWORD1) +####################################### + +EndOfTextEndOfTextEndOfText + +CLASSES=$(grep "^class " src/*.h | cut -d' ' -f2 | sort -u) +# Manually add typedefs as they are hard to parse out. +CLASSES="${CLASSES} ir_params_t match_result_t" +for i in ${CLASSES}; do + echo -e "${i}\tKEYWORD1" +done | sort -du + +cat << EndOfTextEndOfTextEndOfText + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +EndOfTextEndOfTextEndOfText + +METHODS=$(egrep "^(u?int|void|bool|String|static|match_result_t).*\(" src/*.cpp| + cut -d' ' -f2- | sed 's/^.*:://' | cut -d'(' -f1 | sort -u | + grep -v ICACHE_RAM_ATTR) +for i in ${METHODS}; do + echo -e "${i}\tKEYWORD2" +done | sort -u + +cat << EndOfTextEndOfTextEndOfText + +####################################### +# Constants (LITERAL1) +####################################### + +EndOfTextEndOfTextEndOfText +LITERALS=$(grep "^#define [A-Z]" src/*.cpp src/*.h | + while read ignore define ignore; do + echo ${define}; + done | sort -u | + grep -v [\(\)] | grep -v ^_ | grep -v _\$ | grep -v VIRTUAL) +CONSTS=$(grep "^const " src/*.cpp src/*.h | + sed 's/\[.*\] =.*//;s/ =.*//;s/^.* k/k/') +ENUMS=$(cat src/*.h | while read a b; do + if [[ ${a} == "};" ]]; then + ENUM=0; + fi; + if [[ ${ENUM} -eq 1 ]]; then + echo $a | sed 's/,//g'; + fi; + if [[ ${a} == "enum" ]]; then + ENUM=1; + fi; + done) +for i in ${LITERALS} ${CONSTS} ${ENUMS}; do + echo -e "${i}\tLITERAL1" +done | sort -u diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/mode2_decode.cpp b/lib/IRremoteESP8266-2.5.2.03/tools/mode2_decode.cpp new file mode 100644 index 000000000..63dfa6221 --- /dev/null +++ b/lib/IRremoteESP8266-2.5.2.03/tools/mode2_decode.cpp @@ -0,0 +1,122 @@ +// Quick and dirty tool to decode mode2 data from LIRC +// Copyright 2018 Brett T. Warden +// based on c2_decode.cpp, Copyright 2017 Jorge Cisneros + +// Usage example: +// mode2 -H udp -d 5000 | ./mode2_decode + +/* Sample input (alternating space and pulse durations in microseconds): +space 500000 +pulse 915 +space 793 +pulse 488 +space 366 +pulse 915 +space 793 +pulse 427 +space 500000 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "IRsend.h" +#include "IRsend_test.h" +#include "IRutils.h" + +const uint16_t kMaxGcCodeLength = 10000; + +void str_to_uint16(char *str, uint16_t *res, uint8_t base) { + char *end; + errno = 0; + intmax_t val = strtoimax(str, &end, base); + if (errno == ERANGE || val < 0 || val > UINT16_MAX || end == str || + *end != '\0') + return; + *res = (uint16_t)val; +} + +void usage_error(char *name) { + std::cerr << "Usage: " << name << " [-raw]" << std::endl; +} + +int main(int argc, char *argv[]) { + bool dumpraw = false; + + // Check the invocation/calling usage. + if (argc > 2) { + usage_error(argv[0]); + return 1; + } + + if (argc == 2 && strncmp("-raw", argv[1], 4) == 0) { + dumpraw = true; + } + + int index = 0; + std::string line, type; + std::string pulse = "pulse"; + std::string space = "space"; + int duration; + + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + irsend.reset(); + + while (getline(std::cin, line)) { + std::istringstream iss1(line); + iss1 >> type; + iss1 >> duration; + + // Clamp duration to int16_t + if (duration > 0xFFFF) { + duration = 0xFFFF; + } + if (pulse.compare(type) == 0) { + irsend.mark(duration); + } else if (space.compare(type) == 0) { + irsend.space(duration); + } + index++; + + if (duration > 20000 || index >= kMaxGcCodeLength) { + // Skip long spaces at beginning + if (index > 1) { + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + + std::cout << "Code length " << index << std::endl + << "Code type " << irsend.capture.decode_type << " (" + << typeToString(irsend.capture.decode_type) << ")" + << std::endl + << "Code bits " << irsend.capture.bits << std::endl; + if (hasACState(irsend.capture.decode_type)) { + std::cout << "State value 0x"; + for (uint16_t i = 0; i < irsend.capture.bits / 8; i++) + printf("%02X", irsend.capture.state[i]); + std::cout << std::endl; + } else { + std::cout << "Code value 0x" << std::hex << irsend.capture.value + << std::endl + << "Code address 0x" << std::hex << irsend.capture.address + << std::endl + << "Code command 0x" << std::hex << irsend.capture.command + << std::endl; + } + + if (dumpraw || irsend.capture.decode_type == UNKNOWN) + irsend.dumpRawResult(); + } + + irsend.reset(); + index = 0; + } + } + + return 0; +} diff --git a/sonoff/xplg_ws2812.ino b/sonoff/xplg_ws2812.ino index 3c4c34457..423c834ff 100644 --- a/sonoff/xplg_ws2812.ino +++ b/sonoff/xplg_ws2812.ino @@ -85,7 +85,7 @@ uint8_t kWidth[5] = { 4, // Large 8, // Largest 255 }; // All -uint8_t kRepeat[5] = { +uint8_t kWsRepeat[5] = { 8, // Small 6, // Medium 4, // Large @@ -222,7 +222,7 @@ void Ws2812Gradient(uint8_t schemenr) ColorScheme scheme = kSchemes[schemenr]; if (scheme.count < 2) return; - uint8_t repeat = kRepeat[Settings.light_width]; // number of scheme.count per ledcount + uint8_t repeat = kWsRepeat[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 speed = ((Settings.light_speed * 2) -1) * (STATES / 10); @@ -232,7 +232,7 @@ void Ws2812Gradient(uint8_t schemenr) Ws2812GradientColor(schemenr, &oldColor, range, gradRange, offset); currentColor = oldColor; for (uint16_t i = 0; i < Settings.light_pixels; i++) { - if (kRepeat[Settings.light_width] > 1) { + if (kWsRepeat[Settings.light_width] > 1) { Ws2812GradientColor(schemenr, ¤tColor, range, gradRange, i +offset); } if (Settings.light_speed > 0) { From 89ceb816606c55bff3d1851762738b063cea3aec Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Tue, 20 Nov 2018 17:06:54 +0100 Subject: [PATCH 0529/2222] decode-config.py: add 6.3.0.10 settings - add SetOption56/SetOption57 --- tools/decode-config.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 7e0fef959..22d6262ea 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0008' +VER = '2.1.0009' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -771,12 +771,20 @@ Setting_6_3_0_4.update({ Setting_6_3_0_4['flag3'][0].update ({ 'tuya_apply_o20': (' Date: Wed, 21 Nov 2018 16:36:10 +0100 Subject: [PATCH 0530/2222] Add IR Raw data control * Add command SetOption58 0/1 to enable IR raw data info in JSON message (#2116) * Add command IRSend |0,,,.. to allow raw data transmission (#2116) --- sonoff/_changelog.ino | 2 + sonoff/i18n.h | 3 + sonoff/my_user_config.h | 5 +- sonoff/settings.h | 2 +- sonoff/xdrv_05_irremote.ino | 112 ++++++++++++++++++++++++++++-------- tools/decode-status.py | 3 +- 6 files changed, 101 insertions(+), 26 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index cd44e7dbd..081164712 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,8 @@ * Add delays removed in 6.3.0.9 (#4233) * Allow user definition of defines WIFI_RSSI_THRESHOLD (default 10) and WIFI_RESCAN_MINUTES (default 44) * Add support for Fujitsu HVac and IrRemote (#4387) + * Add command SetOption58 0/1 to enable IR raw data info in JSON message (#2116) + * Add command IRSend |0,,,.. to allow raw data transmission (#2116) * * 6.3.0.10 20181118 * Add command SetOption36 0..255 milliseconds (50 default) to tune main loop dynamic delay diff --git a/sonoff/i18n.h b/sonoff/i18n.h index f53433553..317e78712 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -335,10 +335,13 @@ // Commands xdrv_05_irremote.ino #define D_CMND_IRSEND "IRSend" #define D_JSON_INVALID_JSON "Invalid JSON" + #define D_JSON_INVALID_RAWDATA "Invalid RawData" + #define D_JSON_NO_BUFFER_SPACE "No buffer space" #define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocol not supported" #define D_JSON_IR_PROTOCOL "Protocol" #define D_JSON_IR_BITS "Bits" #define D_JSON_IR_DATA "Data" + #define D_JSON_IR_RAWDATA "RawData" #define D_CMND_IRHVAC "IRHVAC" #define D_JSON_IRHVAC_VENDOR "VENDOR" #define D_JSON_IRHVAC_POWER "POWER" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 004e93a09..86384fdbc 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -367,7 +367,10 @@ // -- Low level interface devices ----------------- #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k3 code, 0k3 mem, 48 iram) // #define USE_IR_HVAC // Support for HVAC (Toshiba, Mitsubishi and LG) system using IR (+3k5 code) - #define USE_IR_RECEIVE // Support for IR receiver (+6k5 code, 264 iram) + #define USE_IR_RECEIVE // Support for IR receiver (+7k2 code, 264 iram) + #define IR_RCV_BUFFER_SIZE 100 // Max number of packets allowed in capture buffer (default 100 (*2 bytes ram)) + #define IR_RCV_TIMEOUT 15 // Number of milli-Seconds of no-more-data before we consider a message ended (default 15) + #define IR_RCV_MIN_UNKNOWN_SIZE 6 // Set the smallest sized "UNKNOWN" message packets we actually care about (default 6) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // #define USE_WS2812_CTYPE NEO_GRB // WS2812 Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW) diff --git a/sonoff/settings.h b/sonoff/settings.h index 14ae43faf..553f9eba3 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -71,7 +71,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t hass_short_discovery_msg : 1; // bit 5 (v6.3.0.7) uint32_t use_wifi_scan : 1; // bit 6 (v6.3.0.10) uint32_t use_wifi_rescan : 1; // bit 7 (v6.3.0.10) - uint32_t spare08 : 1; + uint32_t receive_raw : 1; // bit 8 (v6.3.0.11) uint32_t spare09 : 1; uint32_t spare10 : 1; uint32_t spare11 : 1; diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 8836c4ddf..abf303fb1 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -77,16 +77,21 @@ void IrSendInit(void) * IR Receive \*********************************************************************************************/ +#define IR_RCV_SAVE_BUFFER 0 // 0 = do not use buffer, 1 = use buffer for decoding + +#define IR_TIME_AVOID_DUPLICATE 500 // Milliseconds + #include -#define IR_TIME_AVOID_DUPLICATE 500 // Milliseconds - IRrecv *irrecv = NULL; + unsigned long ir_lasttime = 0; void IrReceiveInit(void) { - irrecv = new IRrecv(pin[GPIO_IRRECV]); // an IR led is at GPIO_IRRECV + // an IR led is at GPIO_IRRECV + irrecv = new IRrecv(pin[GPIO_IRRECV], IR_RCV_BUFFER_SIZE, IR_RCV_TIMEOUT, IR_RCV_SAVE_BUFFER); + irrecv->setUnknownThreshold(IR_RCV_MIN_UNKNOWN_SIZE); irrecv->enableIRIn(); // Start the receiver // AddLog_P(LOG_LEVEL_DEBUG, PSTR("IrReceive initialized")); @@ -102,33 +107,58 @@ void IrReceiveCheck(void) 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); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_IRR "RawLen %d, Overflow %d, Bits %d, Value %08X, Decode %d"), + results.rawlen, results.overflow, 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)) { +// if ((now - ir_lasttime > IR_TIME_AVOID_DUPLICATE) && (UNKNOWN != results.decode_type) && (results.bits > 0)) { + if (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE) { ir_lasttime = now; iridx = results.decode_type; if ((iridx < 0) || (iridx > 14)) { - iridx = 0; + iridx = 0; // UNKNOWN } - if (Settings.flag.ir_receive_decimal) { snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)results.value); } else { snprintf_P(stemp, sizeof(stemp), PSTR("\"%lX\""), (uint32_t)results.value); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s}}"), + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s"), GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, stemp); + if (Settings.flag3.receive_raw) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_IR_RAWDATA "\":["), mqtt_data); + uint16_t i; + for (i = 1; i < results.rawlen; i++) { + if (i > 1) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); } + uint32_t usecs; + for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%d,0,"), mqtt_data, UINT16_MAX); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%d"), mqtt_data, usecs); + if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } // Quit if char string becomes too long + } + uint16_t extended_length = results.rawlen - 1; + for (uint16_t j = 0; j < results.rawlen - 1; j++) { + uint32_t usecs = results.rawbuf[j] * kRawTick; + // Add two extra entries for multiple larger than UINT16_MAX it is. + extended_length += (usecs / (UINT16_MAX + 1)) * 2; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), mqtt_data, extended_length, i -1, results.overflow); + } + + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}}"), mqtt_data); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); - XdrvRulesProcess(); + + if (iridx) { + XdrvRulesProcess(); #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 + 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(); @@ -276,9 +306,9 @@ boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolea 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; } @@ -469,28 +499,64 @@ boolean IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H { "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 IrSendCommand(void) { boolean serviced = true; boolean error = false; - char dataBufUc[XdrvMailbox.data_len]; char protocol_text[20]; const char *protocol; uint32_t bits = 0; uint32_t data = 0; + char dataBufUc[XdrvMailbox.data_len]; UpperCase(dataBufUc, XdrvMailbox.data); if (!strcasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_IRSEND))) { if (XdrvMailbox.data_len) { StaticJsonBuffer<128> jsonBuf; JsonObject &root = jsonBuf.parseObject(dataBufUc); + + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_DONE "\"}")); if (!root.success()) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_INVALID_JSON "\"}")); // JSON decode failed + // IRSend frequency, rawdata, rawdata ... + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + uint16_t freq = atoi(str); + if (!freq) { freq = 38000; } // Default to 38kHz + uint16_t count = 0; + char *q = p; + for (; *q; count += (*q++ == ',')); + if (count) { // At least two raw data values + count++; + uint16_t* raw_array = NULL; + raw_array = reinterpret_cast(malloc(count * sizeof(uint16_t))); + if (raw_array != NULL) { + byte i = 0; + for (str = strtok_r(NULL, ", ", &p); str && i < count; str = strtok_r(NULL, ", ", &p)) { + raw_array[i++] = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input + } + +// snprintf_P(log_data, sizeof(log_data), PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), +// count, freq, raw_array[0], raw_array[count -1]); +// AddLog(LOG_LEVEL_DEBUG); + + irsend->sendRaw(raw_array, count, freq); + free(raw_array); + if (!count) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_FAILED "\"}")); // JSON decode failed and invalid RawData + } + } + else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO_BUFFER_SPACE "\"}")); // JSON decode failed and invalid RawData + } + } + else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_INVALID_RAWDATA "\"}")); // JSON decode failed and invalid RawData + } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_DONE "\"}")); + // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } char parm_uc[10]; + protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], NULL, 0); @@ -556,9 +622,9 @@ boolean IrSendCommand(void) HVAC_FanMode = root[D_JSON_IRHVAC_FANSPEED]; HVAC_Temp = root[D_JSON_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); +// 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); diff --git a/tools/decode-status.py b/tools/decode-status.py index cca379ca6..b1881865f 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -92,7 +92,8 @@ a_setoption = [[ "Use short Hass discovery messages", "Use wifi network scan at restart", "Use wifi network rescan regularly", - "","","","", + "Add IR raw data to JSON message", + "","","", "","","","", "","","","", "","","","", From 25f24cd3187d4ef3fcde09649d31e47b69c75db5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 21 Nov 2018 17:19:06 +0100 Subject: [PATCH 0531/2222] Change default WIFI_CONFIG_TOOL Change default WIFI_CONFIG_TOOL from WIFI_WAIT to WIFI_RETRY in my_user_config.h (#4400) --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 081164712..a840f124b 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,6 +4,7 @@ * Add support for Fujitsu HVac and IrRemote (#4387) * Add command SetOption58 0/1 to enable IR raw data info in JSON message (#2116) * Add command IRSend |0,,,.. to allow raw data transmission (#2116) + * Change default WIFI_CONFIG_TOOL from WIFI_WAIT to WIFI_RETRY in my_user_config.h (#4400) * * 6.3.0.10 20181118 * Add command SetOption36 0..255 milliseconds (50 default) to tune main loop dynamic delay diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 86384fdbc..aa6686736 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -63,7 +63,7 @@ #define STA_PASS1 "" // [Password1] Wifi password #define STA_SSID2 "" // [Ssid2] Optional alternate AP Wifi SSID #define STA_PASS2 "" // [Password2] Optional alternate AP Wifi password -#define WIFI_CONFIG_TOOL WIFI_WAIT // [WifiConfig] Default tool if wifi fails to connect +#define WIFI_CONFIG_TOOL WIFI_RETRY // [WifiConfig] Default tool if wifi fails to connect // (WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL) #define WIFI_CONFIG_NO_SSID WIFI_WPSCONFIG // Default tool if wifi fails to connect and no SSID is configured // (WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_SERIAL) From c32b7b50e982f555047f4634446491e80097a678 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 21 Nov 2018 13:58:10 -0300 Subject: [PATCH 0532/2222] Fix warning when compiling sonoff-sensors.bin --- sonoff/sonoff_post.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 86b2c810d..9e62c4b53 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -107,7 +107,9 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) #define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer +#ifndef TUYA_DIMMER_ID #define TUYA_DIMMER_ID 0 // Default dimmer Id +#endif #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) #define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) #define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) From 4cbbfd8a02dad43c73f13ac003444550f3bfc99c Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 21 Nov 2018 15:13:29 -0300 Subject: [PATCH 0533/2222] Fix PIO Linter Warning This fixes the linter warning for Platformio due to module is defined in platformio.ini and also my_user_config.h If module is not defined in my_user_config.h nor in platformio.ini, sonoff_post.h will make SONOFF_BASIC as the default. This works for both Arduino and Platformio This will work as the same as #define MY_LANGUAGE works. If you define it in my_user_config.h, the compiler will use that language, if not defined, the compiler will use en-GB as the default language. --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index aa6686736..fb700bde2 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -48,7 +48,7 @@ // -- Project ------------------------------------- #define PROJECT "sonoff" // PROJECT is used as the default topic delimiter -#define MODULE SONOFF_BASIC // [Module] Select default model from sonoff_template.h (Should not be changed) +//#define MODULE SONOFF_BASIC // [Module] Select default model from sonoff_template.h. If none is selected the default will be SONOFF_BASIC #define SAVE_DATA 1 // [SaveData] Save changed parameters to Flash (0 = disable, 1 - 3600 seconds) #define SAVE_STATE 1 // [SetOption0] Save changed power state to Flash (0 = disable, 1 = enable) From 0924d7a2e682681b8f712c23c1cf74480aca02b9 Mon Sep 17 00:00:00 2001 From: Staars Date: Wed, 21 Nov 2018 19:13:52 +0100 Subject: [PATCH 0534/2222] first integration of the driver into the TASMOTA-repo --- sonoff/language/en-GB.h | 2 + sonoff/my_user_config.h | 1 + sonoff/sonoff_template.h | 11 +- sonoff/xsns_36_mgc3130.ino | 651 +++++++++++++++++++++++++++++++++++++ 4 files changed, 663 insertions(+), 2 deletions(-) create mode 100644 sonoff/xsns_36_mgc3130.ino diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 1a9304a7d..c276187ab 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 86384fdbc..e1cf92cd3 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -299,6 +299,7 @@ // #define USE_SI1145 // Enable SI1145/46/47 sensor (I2C address 0x60) (+1k code) #define USE_LM75AD // Enable LM75AD sensor (I2C addresses 0x48 - 0x4F) (+0k5 code) // #define USE_APDS9960 // Enable APDS9960 Proximity Sensor (I2C address 0x39). Disables SHT and VEML6070 (+4k7 code) + #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) // #define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) // #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+1k5 code) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index dcc87c27f..3135dd339 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -133,6 +133,8 @@ enum UserSelectablePins { GPIO_RFRECV, // RF receiver GPIO_TUYA_TX, // Tuya Serial interface GPIO_TUYA_RX, // Tuya Serial interface + GPIO_MGC3130_XFER, // MGC3130 Transfer + GPIO_MGC3130_RESET, // MGC3130 Reset GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -190,7 +192,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|" D_SENSOR_TX20_TX "|" D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|" - D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX; + D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|" + D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET; /********************************************************************************************/ @@ -426,7 +429,11 @@ const uint8_t kGpioNiceList[] PROGMEM = { #endif #ifdef USE_TUYA_DIMMER GPIO_TUYA_TX, // Tuya Serial interface - GPIO_TUYA_RX // Tuya Serial interface + GPIO_TUYA_RX, // Tuya Serial interface +#endif +#ifdef USE_MGC3130 + GPIO_MGC3130_XFER, + GPIO_MGC3130_RESET #endif }; diff --git a/sonoff/xsns_36_mgc3130.ino b/sonoff/xsns_36_mgc3130.ino new file mode 100644 index 000000000..05662379c --- /dev/null +++ b/sonoff/xsns_36_mgc3130.ino @@ -0,0 +1,651 @@ +/* + xsns_91_MGC3130.ino - Support for I2C MGC3130 Electric Field Sensor for Sonoff-Tasmota + + Copyright (C) 2018 Christian Baars & Theo Arends + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +//#define USE_MGC3130 + +#ifdef USE_I2C +#ifdef USE_MGC3130 + +#define XSNS_36 36 + +/*********************************************************************************************\ + * MGC3130 - Electric Field Sensor + * + * Adaption for TASMOTA: Christian Baars + * based on various implementations from Pimoroni, jspark311, hoverlabs and scjurgen + * + * I2C Address: 0x42 + * + * Wiring: SDA/SCL as usual plus RESET and TRANSFER -> 4 Wires +\*********************************************************************************************/ + +#warning **** MGC3130: It is recommended to disable all unneeded I2C-drivers **** + +#define MGC3130_I2C_ADDR 0x42 + +#define MGC3130_xfer pin[GPIO_MGC3130_XFER] +#define MGC3130_reset pin[GPIO_MGC3130_RESET] + + +bool MGC3130_type = false; +char MGC3130stype[8]; + + +#define MGC3130_SYSTEM_STATUS 0x15 +#define MGC3130_REQUEST_MSG 0x06 +#define MGC3130_FW_VERSION 0x83 +#define MGC3130_SET_RUNTIME 0xA2 +#define MGC3130_SENSOR_DATA 0x91 + + +#define MGC3130_GESTURE_GARBAGE 1 +#define MGC3130_FLICK_WEST_EAST 2 +#define MGC3130_FLICK_EAST_WEST 3 +#define MGC3130_FLICK_SOUTH_NORTH 4 +#define MGC3130_FLICK_NORTH_SOUTH 5 +#define MGC3130_CIRCLE_CLOCKWISE 6 //not active in airwheel mode +#define MGC3130_CIRCLE_CCLOCKWISE 7 //not active in airwheel mode + +#define MGC3130_MIN_ROTVALUE 0 +#define MGC3130_MAX_ROTVALUE 1023 +#define MGC3130_MIN_ZVALUE 32768 // if we fly under the radar, we do not report anything + + +#ifdef USE_WEBSERVER +const char HTTP_MGC_3130_SNS[] PROGMEM = "%s" + "{s}" "%s" "{m}%s{e}" + "{s}" "HwRev" "{m}%u.%u{e}" + "{s}" "loaderVer" "{m}%u.%u{e}" + "{s}" "platVer" "{m}%u{e}"; // {s} =
          +#endif // USE_WEBSERVER + + +/*********************************************************************************************\ + * MGC3130 + * + * Programmer : MGC3130 Datasheet +\*********************************************************************************************/ +#pragma pack(1) +union MGC3130_Union{ + uint8_t buffer[132]; + struct + { + // header + uint8_t msgSize; // in Bytes + uint8_t flag; //not used + uint8_t counter; // cyclic counter of transmitted messages + uint8_t id; // 0x91 for data output + // payload + struct { + uint8_t DSPStatus:1; + uint8_t gestureInfo:1; + uint8_t touchInfo:1; + uint8_t airWheelInfo:1; + uint8_t xyzPosition:1; + uint8_t noisePower:1; + uint8_t reserved:2; + uint8_t electrodeConfiguration:3; + uint8_t CICData:1; + uint8_t SDData:1; + uint16_t reserved2:3; + } outputConfigMask; + uint8_t timestamp; + struct { + uint8_t positionValid:1; + uint8_t airWheelValid:1; + uint8_t rawDataValid:1; + uint8_t noisePowerValid:1; + uint8_t environmentalNoise:1; + uint8_t clipping:1; + uint8_t reserved:1; + uint8_t DSPRunning:1; + } systemInfo; + uint16_t dspInfo; + struct { + uint8_t gestureCode:8; // 0 -> No Gesture + uint8_t reserved:4; + uint8_t gestureType:4; //garbage, flick or circular + uint8_t edgeFlick:1; + uint16_t reserved2:14; + uint8_t gestureInProgress:1; // If "1" Gesture recognition in progress + } gestureInfo; + struct { + uint8_t touchSouth:1; + uint8_t touchWest:1; //:Bit 01 + uint8_t touchNorth:1; //:Bit 02 + uint8_t touchEast:1; //:Bit 03 + uint8_t touchCentre:1; //:Bit 04 + uint8_t tapSouth:1; //:Bit 05 + uint8_t tapWest:1; //:Bit 06 + uint8_t tapNorth:1; //:Bit 07 + uint8_t tapEast :1; //:Bit 08 + uint8_t tapCentre:1; //:Bit 09 + uint8_t doubleTapSouth:1; //:Bit 10 + uint8_t doubleTapWest:1; //:Bit 11 + uint8_t doubleTapNorth:1; //:Bit 12 + uint8_t doubleTapEast:1; //:Bit 13 + uint8_t doubleTapCentre:1; //:Bit 14 + uint8_t reserved:1; //:Bit 15 + uint8_t touchCounter; //period between the time when the hand starts moving to touch until it is detected + uint8_t reserved2; + } touchInfo; + int8_t airWheel; + uint8_t reserved; + uint16_t x; + uint16_t y; + uint16_t z; + float noisePower; + float CICData[4]; // uncalibrated sensor data + float SDData[4]; // signal deviation + } out; + struct { + uint8_t header[3]; + // payload + uint8_t valid; + uint8_t hwRev[2]; + uint8_t parameterStartAddr; + uint8_t loaderVersion[2]; + uint8_t loaderPlatform; + uint8_t fwStartAddr; + char fwVersion[120]; + } fw; + struct{ + uint8_t id; + uint8_t size; + uint16_t error; + uint32_t reserved; + uint32_t reserved1; + } status; +} MGC_data; +#pragma pack() + +char MGC3130_currentGesture[12]; + +int8_t MGC3130_delta, MGC3130_lastrotation = 0; +int16_t MGC3130_rotValue, MGC3130_lastSentRotValue = 0; + +uint16_t MGC3130_lastSentX, MGC3130_lastSentY, MGC3130_lastSentZ = 0; + +uint8_t hwRev[2], loaderVersion[2], loaderPlatform = 0; +char MGC3130_firmwareInfo[20]; + +uint8_t MGC3130_touchTimeout = 0; +uint16_t MGC3130_touchCounter = 1; // measure how long you touch the surface in loop cycles +uint32_t MGC3130_touchTimeStamp = millis(); +bool MGC3130_triggeredByTouch = false; + +uint8_t MGC3130_mode = 1; // 1-gesture; 2-airwheel; 3-position + + +// predefined messages +uint8_t MGC3130autoCal[] = {0x10, 0x00, 0x00, 0xA2, 0x80, 0x00 , 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; +uint8_t MGC3130disableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; +uint8_t MGC3130enableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; + +void MGC3130_triggerTele(){ + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + #ifdef USE_RULES + RulesTeleperiod(); // Allow rule based HA messages + #endif // USE_RULES + } +} + +void MGC3130_handleSensorData(){ + if ( MGC_data.out.outputConfigMask.touchInfo && MGC3130_touchTimeout == 0){ + if (MGC3130_handleTouch()){ + MGC3130_triggeredByTouch = true; + MGC3130_triggerTele(); + } + } + + if(MGC3130_mode == 1){ + if( MGC_data.out.outputConfigMask.gestureInfo && MGC_data.out.gestureInfo.gestureCode > 0){ + MGC3130_handleGesture(); + MGC3130_triggerTele(); + } + } + if(MGC3130_mode == 2){ + if(MGC_data.out.outputConfigMask.airWheelInfo && MGC_data.out.systemInfo.airWheelValid){ + MGC3130_handleAirWheel(); + MGC3130_triggerTele(); + } + } + if(MGC3130_mode == 3){ + if(MGC_data.out.systemInfo.positionValid && (MGC_data.out.z > MGC3130_MIN_ZVALUE)){ + MGC3130_triggerTele(); + } + } +} + +void MGC3130_sendMessage(uint8_t data[], uint8_t length){ + Wire.beginTransmission(MGC3130_I2C_ADDR); + Wire.write(data,length); + Wire.endTransmission(); + delay(2); + MGC3130_receiveMessage(); +} + + +void MGC3130_handleGesture(){ + //char log[LOGSZ]; + char edge[5]; + if (MGC_data.out.gestureInfo.edgeFlick){ + snprintf_P(edge, sizeof(edge), PSTR("ED_")); + } + else{ + snprintf_P(edge, sizeof(edge), PSTR("")); + } + switch(MGC_data.out.gestureInfo.gestureCode){ + case MGC3130_GESTURE_GARBAGE: + //snprintf_P(log, sizeof(log), PSTR("NONE")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("NONE")); + break; + case MGC3130_FLICK_WEST_EAST: + //snprintf_P(log, sizeof(log), PSTR("%sFL_WE"), edge); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_WE"), edge); + break; + case MGC3130_FLICK_EAST_WEST: + //snprintf_P(log, sizeof(log), PSTR("%sFL_EW"), edge); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_EW"), edge); + break; + case MGC3130_FLICK_SOUTH_NORTH: + //snprintf_P(log, sizeof(log), PSTR("%sFL_SN"), edge); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_SN"), edge); + break; + case MGC3130_FLICK_NORTH_SOUTH: + //snprintf_P(log, sizeof(log), PSTR("%sFL_NS"), edge); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_NS"), edge); + break; + case MGC3130_CIRCLE_CLOCKWISE: + //snprintf_P(log, sizeof(log), PSTR("CW")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CW")); + break; + case MGC3130_CIRCLE_CCLOCKWISE: + //snprintf_P(log, sizeof(log), PSTR("CCW")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CCW")); + break; + } + //AddLog_P(LOG_LEVEL_DEBUG, log); +} + +bool MGC3130_handleTouch(){ + //char log[LOGSZ]; + bool success = false; // if we find a touch of higher order, we are done + if (MGC_data.out.touchInfo.doubleTapCentre && !success){ + //snprintf_P(log, sizeof(log), PSTR("DTAP_CENTRE")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_C")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapEast && !success){ + //snprintf_P(log, sizeof(log), PSTR("DTAP_EAST")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_E")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapNorth && !success){ + //snprintf_P(log, sizeof(log), PSTR("DTAP_NORTH")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_N")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapWest && !success){ + //snprintf_P(log, sizeof(log), PSTR("DTAP_WEST")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_W")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapSouth && !success){ + //snprintf_P(log, sizeof(log), PSTR("DTAP_SOUTH")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_S")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + if (MGC_data.out.touchInfo.tapCentre && !success){ + //snprintf_P(log, sizeof(log), PSTR("TAP_CENTRE")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_C")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapEast && !success){ + //snprintf_P(log, sizeof(log), PSTR("TAP_EAST")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_E")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapNorth && !success){ + //snprintf_P(log, sizeof(log), PSTR("TAP_NORTH")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_N")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapWest && !success){ + //snprintf_P(log, sizeof(log), PSTR("TAP_WEST")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_W")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapSouth && !success){ + //snprintf_P(log, sizeof(log), PSTR("TAP_SOUTH")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_S")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.touchCentre && !success){ + //snprintf_P(log, sizeof(log), PSTR("TOUCH_CENTRE")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_C")); + success = true; + MGC3130_touchCounter++; // This will reset to 0 after touching for approx. 1h and 50 minutes ;) + } + else if (MGC_data.out.touchInfo.touchEast && !success){ + //snprintf_P(log, sizeof(log), PSTR("TOUCH_EAST")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_E")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchNorth && !success){ + //snprintf_P(log, sizeof(log), PSTR("TOUCH_NORTH")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_N")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchWest && !success){ + //snprintf_P(log, sizeof(log), PSTR("TOUCH_WEST")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_W")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchSouth && !success){ + //snprintf_P(log, sizeof(log), PSTR("TOUCH_SOUTH")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_S")); + success = true; + MGC3130_touchCounter++; + } + //AddLog_P(LOG_LEVEL_DEBUG, log); + return success; +} + +void MGC3130_handleAirWheel(){ + MGC3130_delta = MGC_data.out.airWheel - MGC3130_lastrotation; + MGC3130_lastrotation = MGC_data.out.airWheel; + + MGC3130_rotValue = MGC3130_rotValue + MGC3130_delta; + if(MGC3130_rotValue < MGC3130_MIN_ROTVALUE){ + MGC3130_rotValue = MGC3130_MIN_ROTVALUE; + } + if(MGC3130_rotValue > MGC3130_MAX_ROTVALUE){ + MGC3130_rotValue = MGC3130_MAX_ROTVALUE; + } +} + +void MGC3130_handleSystemStatus(){ + //Serial.println("Got System status"); +} + +bool MGC3130_receiveMessage(){ + if(MGC3130_readData()){ + switch(MGC_data.out.id){ + case MGC3130_SENSOR_DATA: + MGC3130_handleSensorData(); + break; + case MGC3130_SYSTEM_STATUS: + MGC3130_handleSystemStatus(); + break; + case MGC3130_FW_VERSION: + hwRev[0] = MGC_data.fw.hwRev[1]; + hwRev[1] = MGC_data.fw.hwRev[0]; + loaderVersion[0] = MGC_data.fw.loaderVersion[0]; + loaderVersion[1] = MGC_data.fw.loaderVersion[1]; + loaderPlatform = MGC_data.fw.loaderPlatform; + snprintf_P(MGC3130_firmwareInfo, sizeof(MGC3130_firmwareInfo), PSTR("FW: %s"), MGC_data.fw.fwVersion); + MGC3130_firmwareInfo[20] = '\0'; + // Serial.print(MGC3130_firmwareInfo); + break; + } + return true; + } + return false; +} + +bool MGC3130_readData() +{ + bool success = false; + if (!digitalRead(MGC3130_xfer)){ + pinMode(MGC3130_xfer, OUTPUT); + digitalWrite(MGC3130_xfer, LOW); + Wire.requestFrom(MGC3130_I2C_ADDR, (uint16_t)32); // request usual data output + + MGC_data.buffer[0] = 4; // read at least header, but update after first read anyway + unsigned char i = 0; + while(Wire.available() && (i < MGC_data.buffer[0])){ + MGC_data.buffer[i] = Wire.read(); + i++; + } + digitalWrite(MGC3130_xfer, HIGH); + pinMode(MGC3130_xfer, INPUT); + success = true; + } + return success; +} + +void MGC3130_nextMode(){ + if (MGC3130_mode < 3){ + MGC3130_mode++; + } + else{ + MGC3130_mode = 1; + } + switch(MGC3130_mode){ // there is more to be done in the future + case 1: + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + case 2: + MGC3130_sendMessage(MGC3130enableAirwheel,16); + break; + case 3: + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + } +} + +void MGC3130_loop() +{ + if(MGC3130_touchTimeout > 0){ + MGC3130_touchTimeout--; + } + MGC3130_receiveMessage(); +} + + +bool MGC3130_detect(void) +{ + if (MGC3130_type){ + return true; + } + + pinMode(MGC3130_xfer, INPUT_PULLUP); + pinMode(MGC3130_reset, OUTPUT); + digitalWrite(MGC3130_reset, LOW); + delay(10); + digitalWrite(MGC3130_reset, HIGH); + delay(50); + + boolean success = false; + success = MGC3130_receiveMessage(); // This should read the firmware info + if (success) { + strcpy_P(MGC3130stype, PSTR("MGC3130")); + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, MGC3130stype, MGC3130_I2C_ADDR); + AddLog(LOG_LEVEL_DEBUG); + MGC3130_currentGesture[0] = '\0'; + MGC3130_type = true; + } else { + snprintf_P(log_data, sizeof(log_data), PSTR("MGC3130 did not respond at address 0x%x"), MGC3130_I2C_ADDR); + AddLog(LOG_LEVEL_DEBUG); + } + return success; +} + +/*********************************************************************************************\ + * Presentation +\*********************************************************************************************/ + +void MGC3130_show(boolean json) +{ + if (!MGC3130_type) { + return; + } + + char status_chr[2]; + if(MGC_data.out.systemInfo.DSPRunning){ + sprintf (status_chr, "1"); + } + else{ + sprintf (status_chr, "0"); + } + + + if (json) { + if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch) + { + if(MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)){ + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), + mqtt_data, MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); + MGC3130_lastSentX = MGC_data.out.x; + MGC3130_lastSentY = MGC_data.out.y; + MGC3130_lastSentZ = MGC_data.out.z; + } + } + MGC3130_triggeredByTouch = false; + + if (MGC3130_mode == 2){ + if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)){ + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"AW\":%i}"), mqtt_data, MGC3130stype, MGC3130_rotValue); + MGC3130_lastSentRotValue = MGC3130_rotValue; + } + } + + if (MGC3130_currentGesture[0] != '\0'){ + if (millis() - MGC3130_touchTimeStamp > 220 ){ + MGC3130_touchCounter = 1; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"%s\":%u}"), mqtt_data, MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); + MGC3130_currentGesture[0] = '\0'; + MGC3130_touchTimeStamp = millis(); + } + } +#ifdef USE_WEBSERVER + else { + if (true){ + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGC_3130_SNS, mqtt_data, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform ); + } +#endif // USE_WEBSERVER +} +} +/*********************************************************************************************\ + * Command Sensor91 + * + * Command | Payload | Description + * ---------|---------|-------------------------- + * Sensor91 | | ... + * Sensor91 | 0 | Next Mode - cycle through the modes + * Sensor91 | 1 | Gesture Mode + * Sensor91 | 2 | Airwheel Mode + * Sensor91 | 3 | Position Mode with x,y,z - z must be higher than half of the max. sensing height +\*********************************************************************************************/ + +bool MGC3130CommandSensor() +{ + boolean serviced = true; + + switch (XdrvMailbox.payload) { + case 0: // cycle through the modes + MGC3130_nextMode(); + break; + case 1: // gesture & touch + MGC3130_mode = 1; + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + case 2: // airwheel & touch + MGC3130_mode = 2; + MGC3130_sendMessage(MGC3130enableAirwheel,16); + break; + case 3: // position & touch + MGC3130_mode = 3; + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + } + return serviced; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +boolean Xsns36(byte function) +{ + boolean result = false; + + if (i2c_flg) { + if ((FUNC_INIT == function) && (pin[GPIO_MGC3130_XFER] < 99) && (pin[GPIO_MGC3130_RESET] < 99)) { + MGC3130_detect(); + } else if (MGC3130_type) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + MGC3130_loop(); + break; + case FUNC_COMMAND: + if (XSNS_36 == XdrvMailbox.index) { + result = MGC3130CommandSensor(); + } + break; + case FUNC_JSON_APPEND: + MGC3130_show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_APPEND: + MGC3130_show(0); + break; +#endif // USE_WEBSERVER + } + } + } + return result; +} +#endif // USE_MGC3130 +#endif // USE_I2C \ No newline at end of file From bee50cba0650756739ed01ce9417e37e8cff97ed Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 18 Nov 2018 15:33:13 +0100 Subject: [PATCH 0535/2222] Add support for sensor discovery --- sonoff/xdrv_10_rules.ino | 8 +- sonoff/xdrv_12_home_assistant.ino | 138 ++++++++++++++++++++++++++++-- sonoff/xsns_interface.ino | 3 +- 3 files changed, 139 insertions(+), 10 deletions(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index e53c3f249..f13d5afd2 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -455,16 +455,18 @@ void RulesEvery50ms(void) } } +uint8_t rules_xsns_index = 0; + void RulesEvery100ms(void) { if (Settings.rule_enabled && (uptime > 4)) { // Any rule enabled and allow 4 seconds start-up time for sensors (#3811) mqtt_data[0] = '\0'; int tele_period_save = tele_period; - tele_period = 2; // Do not allow HA updates during next function call - XsnsNextCall(FUNC_JSON_APPEND); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} + tele_period = 2; // Do not allow HA updates during next function call + XsnsNextCall(FUNC_JSON_APPEND, rules_xsns_index); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} tele_period = tele_period_save; if (strlen(mqtt_data)) { - mqtt_data[0] = '{'; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} + mqtt_data[0] = '{'; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); RulesProcess(); } diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index d33ed78e0..4be4377d7 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -62,6 +62,25 @@ const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = "\"color_temp_state_topic\":\"%s\"," // stat/led2/RESULT "\"color_temp_value_template\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; +const char HASS_DISCOVER_SENSOR[] PROGMEM = + "{\"name\":\"%s\"," // dualr2 1 BTN + "\"state_topic\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") + "\"availability_topic\":\"%s\"," // tele/dualr2/LWT + "\"payload_available\":\"" D_ONLINE "\"," // Online + "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline + +const char HASS_DISCOVER_SENSOR_TEMP[] PROGMEM = + "%s,\"unit_of_measurement\":\"°%c\"," // °C / °F + "\"value_template\":\"{{value_json['%s'].Temperature}}\""; // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Temperature }} + +const char HASS_DISCOVER_SENSOR_HUM[] PROGMEM = + "%s,\"unit_of_measurement\":\"%%\"," // % + "\"value_template\":\"{{value_json['%s'].Humidity}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }} + "\"device_class\":\"humidity\""; // temperature / humidity + +const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = + "%s,\"value_template\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} + const char HASS_DISCOVER_RELAY_SHORT[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 "\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2 @@ -109,6 +128,26 @@ const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = "\"effect_value_template\":\"{{value_json." D_CMND_SCHEME "}}\"," "\"effect_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; // string list with reference to scheme parameter. Currently only supports numbers 0 to 11 as it make the mqtt string too long */ + +const char HASS_DISCOVER_SENSOR_SHORT[] PROGMEM = + "{\"name\":\"%s\"," // dualr2 1 BTN + "\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") + "\"avty_t\":\"%s\"," // tele/dualr2/LWT + "\"pl_avail\":\"" D_ONLINE "\"," // Online + "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline + +const char HASS_DISCOVER_SENSOR_TEMP_SHORT[] PROGMEM = + "%s,\"unit_of_meas\":\"°%c\"," // °C / °F + "\"val_tpl\":\"{{value_json['%s'].Temperature}}\""; // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Temperature }} + +const char HASS_DISCOVER_SENSOR_HUM_SHORT[] PROGMEM = + "%s,\"unit_of_meas\":\"%%\"," // % + "\"val_tpl\":\"{{value_json['%s'].Humidity}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }} + "\"dev_cla\":\"humidity\""; // humidity + +const char HASS_DISCOVER_SENSOR_ANY_SHORT[] PROGMEM = + "%s,\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} + const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM = "%s, \"~\":\"%s\""; @@ -132,7 +171,7 @@ static void Shorten(char** s, char *prefix) } } -void HAssDiscoverRelay(void) +void HAssAnnounceRelayLight(void) { char sidx[8]; char stopic[TOPSZ]; @@ -226,7 +265,7 @@ void HAssDiscoverRelay(void) } } -void HAssDiscoverButton(void) +void HAssAnnounceButton(void) { char sidx[8]; char stopic[TOPSZ]; @@ -287,6 +326,92 @@ void HAssDiscoverButton(void) } } +void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) +{ + char stopic[TOPSZ]; + + // Announce sensor, special handling of temperature and humidity sensors + mqtt_data[0] = '\0'; // Clear retained message + + // Clear or Set topic + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s_%s_%s/config"), + mqtt_topic, sensorname, subsensortype); + + if (Settings.flag.hass_discovery) { + char name[33]; + char _state_topic[TOPSZ]; + char _availability_topic[TOPSZ]; + char prefix[TOPSZ]; + char *state_topic = _state_topic; + char *availability_topic = _availability_topic; + + snprintf_P(name, sizeof(name), PSTR("%s %s %s"), Settings.friendlyname[0], sensorname, subsensortype); + GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + FindPrefix(state_topic, availability_topic, prefix); + if (Settings.flag3.hass_short_discovery_msg) { + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_SHORT:HASS_DISCOVER_SENSOR, + name, state_topic, availability_topic); + if (!strcmp(subsensortype, "Temperature")) { + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_TEMP_SHORT:HASS_DISCOVER_SENSOR_TEMP, + mqtt_data, TempUnit(), sensorname); + } else if (!strcmp(subsensortype, "Humidity")) { + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_HUM_SHORT:HASS_DISCOVER_SENSOR_HUM, + mqtt_data, sensorname); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_ANY_SHORT:HASS_DISCOVER_SENSOR_ANY, + mqtt_data, sensorname, subsensortype); + } + if (Settings.flag3.hass_short_discovery_msg) + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + } + MqttPublish(stopic, true); +} + +void HAssAnnounceSensors(void) +{ + uint8_t hass_xsns_index = 0; + do { + mqtt_data[0] = '\0'; + int tele_period_save = tele_period; + tele_period = 2; // Do not allow HA updates during next function call + XsnsNextCall(FUNC_JSON_APPEND, hass_xsns_index); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} + tele_period = tele_period_save; + + char sensordata[256]; // Copy because we need to write to mqtt_data + strlcpy(sensordata, mqtt_data, sizeof(sensordata)); + + if (strlen(sensordata)) { + sensordata[0] = '{'; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} + snprintf_P(sensordata, sizeof(sensordata), PSTR("%s}"), sensordata); + + StaticJsonBuffer<256> jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(sensordata); + if (!root.success()) { + snprintf_P(log_data, sizeof(log_data), PSTR("HASS: failed to parse '%s'"), sensordata); + AddLog(LOG_LEVEL_ERROR); + continue; + } + for (auto sensor : root) { + const char* sensorname = sensor.key; + JsonObject& sensors = sensor.value.as(); + if (!sensors.success()) { + snprintf_P(log_data, sizeof(log_data), PSTR("HASS: failed to parse '%s'"), sensordata); + AddLog(LOG_LEVEL_ERROR); + continue; + } + for (auto subsensor : sensors) { + HAssAnnounceSensor(sensorname, subsensor.key); + } + } + } + } while (hass_xsns_index != 0); +} + static int string_ends_with(const char * str, const char * suffix) { int str_len = strlen(str); @@ -308,12 +433,15 @@ void HAssDiscovery(uint8_t mode) if (Settings.flag.hass_discovery || (1 == mode)) { // Send info about relays and lights - HAssDiscoverRelay(); + HAssAnnounceRelayLight(); + // Send info about buttons - HAssDiscoverButton(); + HAssAnnounceButton(); + // TODO: Send info about switches - // TODO: Send info about sensors + // Send info about sensors + HAssAnnounceSensors(); } } diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index a7ab6d7a7..221a8b4f4 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -263,13 +263,12 @@ boolean (* const xsns_func_ptr[])(byte) = { // Sensor Function Pointers for sim }; const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); // Number of External Sensors found -uint8_t xsns_index = 0; /*********************************************************************************************\ * Function call to all xsns \*********************************************************************************************/ -boolean XsnsNextCall(byte Function) +boolean XsnsNextCall(byte Function, uint8_t &xsns_index) { xsns_index++; From 855cc53d93c25ab8f1b953c685a292409602ce56 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 20:51:15 +0100 Subject: [PATCH 0536/2222] Disable MGC3130 by default --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index e1cf92cd3..d70a5b013 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -299,7 +299,7 @@ // #define USE_SI1145 // Enable SI1145/46/47 sensor (I2C address 0x60) (+1k code) #define USE_LM75AD // Enable LM75AD sensor (I2C addresses 0x48 - 0x4F) (+0k5 code) // #define USE_APDS9960 // Enable APDS9960 Proximity Sensor (I2C address 0x39). Disables SHT and VEML6070 (+4k7 code) - #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) +// #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) // #define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) // #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+1k5 code) From f4115c17fd87d08c00b0e6ed492419804dc616b6 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 20:59:08 +0100 Subject: [PATCH 0537/2222] Language key for MGC3130 --- sonoff/language/bg-BG.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 1503884c3..3663dfbae 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 039e228cfecfd51ec7c2deec294041476e6a8457 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 20:59:44 +0100 Subject: [PATCH 0538/2222] Language keys for MGC3130 --- sonoff/language/cs-CZ.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 2b667cec1..e545ec0a9 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 9bf5b17351e6c70c082346bea57eb67eb815a2f9 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:01:09 +0100 Subject: [PATCH 0539/2222] Language keys for MGC3130 --- sonoff/language/de-DE.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index f0f9e0f17..17acd9194 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 16e65c15417662ee6f99ac961d80a6aa62197d64 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:01:50 +0100 Subject: [PATCH 0540/2222] Language keys for MGC3130 --- sonoff/language/el-GR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 79558615d..9287d6961 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -530,6 +530,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 4af915ff566a280a2146c8858e39b2df7d22c1a7 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:02:39 +0100 Subject: [PATCH 0541/2222] Language keys for MGC3130 --- sonoff/language/es-AR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index e5c3135fe..77d835604 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From c5223b5af845ef4dd1e465af9a88e71bc9971e55 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:03:16 +0100 Subject: [PATCH 0542/2222] Language keys for MGC3130 --- sonoff/language/fr-FR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 0dfb2929c..6947bfc54 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 70188e0aebf1793291388d3d611c7ad7d9b2f0ac Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:03:41 +0100 Subject: [PATCH 0543/2222] Language keys for MGC3130 --- sonoff/language/he-HE.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index cb041ffba..e6ef65a08 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 65c848e4a25339bf954054465a1fe9e08c31bcc8 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:04:15 +0100 Subject: [PATCH 0544/2222] Language keys for MGC3130 --- sonoff/language/hu-HU.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 5cee46a52..81e4e7756 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 1961e5b9d9ef19cea5704a23dd569ee6447a697c Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:04:41 +0100 Subject: [PATCH 0545/2222] Language keys for MGC3130 --- sonoff/language/it-IT.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 0eaca9337..5cb974df5 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 3c3ae73e606d56992b0d47016d6ebeb6205304c6 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:05:09 +0100 Subject: [PATCH 0546/2222] Language keys for MGC3130 --- sonoff/language/nl-NL.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 0567e0849..875bfd921 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From e08f2126b68fd9e53d2e4ecf1262ce618f402a29 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:05:34 +0100 Subject: [PATCH 0547/2222] Language keys for MGC3130 --- sonoff/language/pl-PL.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 678a7b770..e697966e5 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 87a9d3e0cf662525ac45a7e768dfcdad41770817 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:06:02 +0100 Subject: [PATCH 0548/2222] Language keys for MGC3130 --- sonoff/language/pt-BR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 712ea6a74..0336bac9a 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From ba6433ccf78960f6bc8236d6c2dee65fa7a35450 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:06:32 +0100 Subject: [PATCH 0549/2222] Language keys for MGC3130 --- sonoff/language/pt-PT.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 0bba501bd..7afd0b1bc 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -529,6 +529,9 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" + // Units #define D_UNIT_AMPERE "A" From 20d3343e852a0675ebbafb5829dd77b8c74a9919 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:07:13 +0100 Subject: [PATCH 0550/2222] Language keys for MGC3130 --- sonoff/language/ru-RU.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index f9062a572..bc6383476 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "А" From 08ae15db6f79e23b4bf8584243002c60644141f4 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:07:42 +0100 Subject: [PATCH 0551/2222] Language keys for MGC3130 --- sonoff/language/tr-TR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index f892fafbb..f5bf3ed8f 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 0d6df5ed6155e7a953adddb1e102aaf516704856 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:08:19 +0100 Subject: [PATCH 0552/2222] Language keys for MGC3130 --- sonoff/language/uk-UK.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 4c290613a..c6303e243 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "А" From ae9d66bfa99c2d41f2bc8610755e8edae1187d15 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:08:46 +0100 Subject: [PATCH 0553/2222] Language keys for MGC3130 --- sonoff/language/zh-CN.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index fe6dabe8d..746eb0b86 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "安" From 02dd07cb95cb28f2c31943645cbef8c79db82fe2 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:09:17 +0100 Subject: [PATCH 0554/2222] Language keys for MGC3130 --- sonoff/language/zh-TW.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 92a805587..a6894dc1e 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "安" From d71ae779008ae6c2b988e97280cf5610669c7613 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 22 Nov 2018 12:25:18 +0100 Subject: [PATCH 0555/2222] 6.3.0.12 Change boot delays 6.3.0.12 20181122 * Remove delays introduced in 6.3.0.11 (#4233) * Add additional start-up delay during initial wifi connection * Add support for I2C MGC3130 Electric Field Effect sensor by Christian Baars (#3774, #4404) * Add initial support for Hass sensor discovery (#4380) --- sonoff/_changelog.ino | 8 ++- sonoff/my_user_config.h | 6 +- sonoff/sonoff.ino | 8 ++- sonoff/sonoff_post.h | 1 + sonoff/sonoff_version.h | 2 +- sonoff/xdrv_interface.ino | 2 +- sonoff/xsns_36_mgc3130.ino | 116 ++++++++++++++++--------------------- sonoff/xsns_interface.ino | 5 +- 8 files changed, 74 insertions(+), 74 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index a840f124b..26fea49e6 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,10 @@ -/* 6.3.0.11 20181120 +/* 6.3.0.12 20181122 + * Remove delays introduced in 6.3.0.11 (#4233) + * Add additional start-up delay during initial wifi connection + * Add support for I2C MGC3130 Electric Field Effect sensor by Christian Baars (#3774, #4404) + * Add initial support for Hass sensor discovery (#4380) + * + * 6.3.0.11 20181120 * Add delays removed in 6.3.0.9 (#4233) * Allow user definition of defines WIFI_RSSI_THRESHOLD (default 10) and WIFI_RESCAN_MINUTES (default 44) * Add support for Fujitsu HVac and IrRemote (#4387) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index f6ddd22a3..91b764688 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -48,7 +48,9 @@ // -- Project ------------------------------------- #define PROJECT "sonoff" // PROJECT is used as the default topic delimiter -//#define MODULE SONOFF_BASIC // [Module] Select default model from sonoff_template.h. If none is selected the default will be SONOFF_BASIC + +// If not selected the default will be SONOFF_BASIC +//#define MODULE SONOFF_BASIC // [Module] Select default model from sonoff_template.h #define SAVE_DATA 1 // [SaveData] Save changed parameters to Flash (0 = disable, 1 - 3600 seconds) #define SAVE_STATE 1 // [SetOption0] Save changed power state to Flash (0 = disable, 1 = enable) @@ -299,7 +301,6 @@ // #define USE_SI1145 // Enable SI1145/46/47 sensor (I2C address 0x60) (+1k code) #define USE_LM75AD // Enable LM75AD sensor (I2C addresses 0x48 - 0x4F) (+0k5 code) // #define USE_APDS9960 // Enable APDS9960 Proximity Sensor (I2C address 0x39). Disables SHT and VEML6070 (+4k7 code) -// #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) // #define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) // #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+1k5 code) @@ -312,6 +313,7 @@ // #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) // #define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) // #define USE_RTC_ADDR 0x68 // Default I2C address 0x68 +// #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 949f82cb7..af3b19992 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2778,5 +2778,11 @@ void loop(void) delay(sleep); // https://github.com/esp8266/Arduino/issues/2021 uint32_t my_activity = millis() - my_sleep; - if (my_activity < (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]) { delay((uint32_t)Settings.param[P_LOOP_SLEEP_DELAY] - my_activity); } // Provide time for background tasks like wifi + if (global_state.wifi_down) { + delay(my_activity /2); // Force max of 50% processing vs. yield time while wifi is down + } else { + if (my_activity < (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]) { + delay((uint32_t)Settings.param[P_LOOP_SLEEP_DELAY] - my_activity); // Provide time for background tasks like wifi + } + } } diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 9e62c4b53..1e52a8641 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -91,6 +91,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); //#define USE_CCS811 // Add I2C code for CCS811 sensor (+2k2 code) //#define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) //#define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) +//#define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) #define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) #define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) #ifndef CO2_LOW diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 21ed0ce8f..2648520b4 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0603000B +#define VERSION 0x0603000C #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index c9557ec56..12b9e2711 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -238,7 +238,7 @@ boolean XdrvCall(byte Function) boolean result = false; for (byte x = 0; x < xdrv_present; x++) { - AppDelay(); +// AppDelay(); result = xdrv_func_ptr[x](Function); if (result) break; } diff --git a/sonoff/xsns_36_mgc3130.ino b/sonoff/xsns_36_mgc3130.ino index 05662379c..81f4a72c6 100644 --- a/sonoff/xsns_36_mgc3130.ino +++ b/sonoff/xsns_36_mgc3130.ino @@ -1,37 +1,26 @@ /* - xsns_91_MGC3130.ino - Support for I2C MGC3130 Electric Field Sensor for Sonoff-Tasmota + xsns_36_MGC3130.ino - Support for I2C MGC3130 Electric Field Sensor for Sonoff-Tasmota Copyright (C) 2018 Christian Baars & Theo Arends - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + 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. - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. + 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. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ //#define USE_MGC3130 #ifdef USE_I2C #ifdef USE_MGC3130 - -#define XSNS_36 36 - /*********************************************************************************************\ * MGC3130 - Electric Field Sensor * @@ -43,9 +32,11 @@ * Wiring: SDA/SCL as usual plus RESET and TRANSFER -> 4 Wires \*********************************************************************************************/ +#define XSNS_36 36 + #warning **** MGC3130: It is recommended to disable all unneeded I2C-drivers **** -#define MGC3130_I2C_ADDR 0x42 +#define MGC3130_I2C_ADDR 0x42 #define MGC3130_xfer pin[GPIO_MGC3130_XFER] #define MGC3130_reset pin[GPIO_MGC3130_RESET] @@ -527,25 +518,21 @@ bool MGC3130_detect(void) void MGC3130_show(boolean json) { - if (!MGC3130_type) { - return; - } + if (!MGC3130_type) { return; } char status_chr[2]; - if(MGC_data.out.systemInfo.DSPRunning){ + if (MGC_data.out.systemInfo.DSPRunning) { sprintf (status_chr, "1"); } else{ sprintf (status_chr, "0"); } - if (json) { - if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch) - { - if(MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)){ + if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch) { + if (MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), - mqtt_data, MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); + mqtt_data, MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); MGC3130_lastSentX = MGC_data.out.x; MGC3130_lastSentY = MGC_data.out.y; MGC3130_lastSentZ = MGC_data.out.z; @@ -553,40 +540,38 @@ void MGC3130_show(boolean json) } MGC3130_triggeredByTouch = false; - if (MGC3130_mode == 2){ - if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)){ - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"AW\":%i}"), mqtt_data, MGC3130stype, MGC3130_rotValue); - MGC3130_lastSentRotValue = MGC3130_rotValue; - } + if (MGC3130_mode == 2) { + if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"AW\":%i}"), mqtt_data, MGC3130stype, MGC3130_rotValue); + MGC3130_lastSentRotValue = MGC3130_rotValue; + } } - if (MGC3130_currentGesture[0] != '\0'){ - if (millis() - MGC3130_touchTimeStamp > 220 ){ - MGC3130_touchCounter = 1; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"%s\":%u}"), mqtt_data, MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); - MGC3130_currentGesture[0] = '\0'; - MGC3130_touchTimeStamp = millis(); - } - } -#ifdef USE_WEBSERVER - else { - if (true){ - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGC_3130_SNS, mqtt_data, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform ); + if (MGC3130_currentGesture[0] != '\0') { + if (millis() - MGC3130_touchTimeStamp > 220 ) { + MGC3130_touchCounter = 1; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"%s\":%u}"), mqtt_data, MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); + MGC3130_currentGesture[0] = '\0'; + MGC3130_touchTimeStamp = millis(); } +#ifdef USE_WEBSERVER + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGC_3130_SNS, mqtt_data, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform ); #endif // USE_WEBSERVER + } } -} + /*********************************************************************************************\ - * Command Sensor91 + * Command Sensor36 * * Command | Payload | Description * ---------|---------|-------------------------- - * Sensor91 | | ... - * Sensor91 | 0 | Next Mode - cycle through the modes - * Sensor91 | 1 | Gesture Mode - * Sensor91 | 2 | Airwheel Mode - * Sensor91 | 3 | Position Mode with x,y,z - z must be higher than half of the max. sensing height + * Sensor36 | | ... + * Sensor36 | 0 | Next Mode - cycle through the modes + * Sensor36 | 1 | Gesture Mode + * Sensor36 | 2 | Airwheel Mode + * Sensor36 | 3 | Position Mode with x,y,z - z must be higher than half of the max. sensing height \*********************************************************************************************/ bool MGC3130CommandSensor() @@ -624,19 +609,20 @@ boolean Xsns36(byte function) if (i2c_flg) { if ((FUNC_INIT == function) && (pin[GPIO_MGC3130_XFER] < 99) && (pin[GPIO_MGC3130_RESET] < 99)) { MGC3130_detect(); - } else if (MGC3130_type) { + } + else if (MGC3130_type) { switch (function) { case FUNC_EVERY_50_MSECOND: - MGC3130_loop(); - break; + MGC3130_loop(); + break; case FUNC_COMMAND: - if (XSNS_36 == XdrvMailbox.index) { + if (XSNS_36 == XdrvMailbox.index) { result = MGC3130CommandSensor(); - } - break; + } + break; case FUNC_JSON_APPEND: - MGC3130_show(1); - break; + MGC3130_show(1); + break; #ifdef USE_WEBSERVER case FUNC_WEB_APPEND: MGC3130_show(0); diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index a299171b9..fbe8bf218 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -270,7 +270,6 @@ const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); boolean XsnsNextCall(byte Function, uint8_t &xsns_index) { - xsns_index++; if (xsns_index == xsns_present) { xsns_index = 0; } #ifdef USE_DEBUG_DRIVER @@ -279,7 +278,7 @@ boolean XsnsNextCall(byte Function, uint8_t &xsns_index) if (xsns_index == xsns_present) { xsns_index = 0; } } #endif - AppDelay(); +// AppDelay(); return xsns_func_ptr[xsns_index](Function); } @@ -299,7 +298,7 @@ boolean XsnsCall(byte Function) #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND uint32_t profile_start_millis = millis(); #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND - AppDelay(); +// AppDelay(); result = xsns_func_ptr[x](Function); #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND From 6c87ab205a9cc7d146d9f6ce48b05525d789d9eb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 22 Nov 2018 15:41:30 +0100 Subject: [PATCH 0556/2222] Fix possible strncat buffer overflows Fix possible strncat buffer overflows --- sonoff/_changelog.ino | 1 + sonoff/support.ino | 6 +++--- sonoff/support_features.ino | 4 +++- sonoff/support_rtc.ino | 3 ++- sonoff/xdrv_02_mqtt.ino | 2 +- sonoff/xdrv_07_domoticz.ino | 2 +- sonoff/xdrv_09_timers.ino | 4 ++-- sonoff/xdrv_11_knx.ino | 2 +- sonoff/xdrv_13_display.ino | 6 +++--- sonoff/xdsp_03_matrix.ino | 2 +- sonoff/xsns_34_hx711.ino | 4 ++-- tools/decode-status.py | 2 +- 12 files changed, 21 insertions(+), 17 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 26fea49e6..91e7ebe9c 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Add additional start-up delay during initial wifi connection * Add support for I2C MGC3130 Electric Field Effect sensor by Christian Baars (#3774, #4404) * Add initial support for Hass sensor discovery (#4380) + * Fix possible strncat buffer overflows * * 6.3.0.11 20181120 * Add delays removed in 6.3.0.9 (#4233) diff --git a/sonoff/support.ino b/sonoff/support.ino index f32657c37..234764791 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -452,7 +452,7 @@ char* GetPowerDevice(char* dest, uint8_t idx, size_t size, uint8_t option) strncpy_P(dest, S_RSLT_POWER, size); // POWER if ((devices_present + option) > 1) { snprintf_P(sidx, sizeof(sidx), PSTR("%d"), idx); // x - strncat(dest, sidx, size); // POWERx + strncat(dest, sidx, size - strlen(dest) -1); // POWERx } return dest; } @@ -1030,7 +1030,7 @@ void I2cScan(char *devs, unsigned int devs_len) } } if (any) { - strncat(devs, "\"}", devs_len); + strncat(devs, "\"}", devs_len - strlen(devs) -1); } else { snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_NO_DEVICES_FOUND "\"}")); @@ -1157,7 +1157,7 @@ void AddLog_P(byte loglevel, const char *formatP, const char *formatP2) snprintf_P(log_data, sizeof(log_data), formatP); snprintf_P(message, sizeof(message), formatP2); - strncat(log_data, message, sizeof(log_data)); + strncat(log_data, message, sizeof(log_data) - strlen(log_data) -1); AddLog(loglevel); } diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 826e73090..2e5e894ce 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -358,8 +358,10 @@ void GetFeatures(void) #ifdef USE_TX20_WIND_SENSOR feature_sns2 |= 0x00002000; // xsns_35_tx20.ino #endif +#ifdef USE_MGC3130 + feature_sns2 |= 0x00004000; // xsns_36_mgc3130.ino +#endif -// feature_sns2 |= 0x00004000; // feature_sns2 |= 0x00008000; // feature_sns2 |= 0x00010000; // feature_sns2 |= 0x00020000; diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index b6067bd15..4ba0747a5 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -124,12 +124,13 @@ String GetDateAndTime(byte time_type) tmpTime = RtcTime; } + snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), tmpTime.year, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { // if (Settings.flag3.time_append_timezone && ((DT_LOCAL == time_type) || (DT_ENERGY == time_type))) { - strncat(dt, GetTimeZone().c_str(), sizeof(dt)); + strncat(dt, GetTimeZone().c_str(), sizeof(dt) - strlen(dt) -1); } return String(dt); // 2017-03-07T11:08:02-07:00 diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index b4876d436..34025c5fc 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -925,7 +925,7 @@ boolean Xdrv02(byte function) switch (function) { #ifdef USE_WEBSERVER case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_MQTT, sizeof(mqtt_data)); + strncat_P(mqtt_data, HTTP_BTN_MENU_MQTT, sizeof(mqtt_data) - strlen(mqtt_data) -1); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index a4851a7b8..40c3127ec 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -485,7 +485,7 @@ boolean Xdrv07(byte function) switch (function) { #ifdef USE_WEBSERVER case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_DOMOTICZ, sizeof(mqtt_data)); + strncat_P(mqtt_data, HTTP_BTN_MENU_DOMOTICZ, sizeof(mqtt_data) - strlen(mqtt_data) -1); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration); diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 6fa499efd..fb7c2cef5 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -757,9 +757,9 @@ boolean Xdrv09(byte function) #ifdef USE_TIMERS_WEB case FUNC_WEB_ADD_BUTTON: #ifdef USE_RULES - strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data)); + strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data) - strlen(mqtt_data) -1); #else - if (devices_present) { strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data)); } + if (devices_present) { strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data) - strlen(mqtt_data) -1); } #endif // USE_RULES break; case FUNC_WEB_ADD_HANDLER: diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 5391cd17c..b4fbefc18 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -1290,7 +1290,7 @@ boolean Xdrv11(byte function) #ifdef USE_WEBSERVER #ifdef USE_KNX_WEB_MENU case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_KNX, sizeof(mqtt_data)); + strncat_P(mqtt_data, HTTP_BTN_MENU_KNX, sizeof(mqtt_data) - strlen(mqtt_data) -1); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/kn", HandleKNXConfiguration); diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index fe93fc8ca..93f61c739 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -819,11 +819,11 @@ void DisplayMqttSubscribe(void) if (!strcmp_P(tp, PSTR(MQTT_TOKEN_PREFIX))) { break; } - strncat_P(ntopic, PSTR("+/"), sizeof(ntopic)); // Add single-level wildcards + strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); // Add single-level wildcards tp = strtok(NULL, "/"); } - strncat(ntopic, Settings.mqtt_prefix[2], sizeof(ntopic)); // Subscribe to tele messages - strncat_P(ntopic, PSTR("/#"), sizeof(ntopic)); // Add multi-level wildcard + strncat(ntopic, Settings.mqtt_prefix[2], sizeof(ntopic) - strlen(ntopic) -1); // Subscribe to tele messages + strncat_P(ntopic, PSTR("/#"), sizeof(ntopic) - strlen(ntopic) -1); // Add multi-level wildcard MqttSubscribe(ntopic); disp_subscribed = 1; } else { diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index 7af998470..63222c637 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -251,7 +251,7 @@ void MatrixPrintLog(uint8_t direction) space = 0; } if (space < 2) { - strncat(mtx_buffer, (const char*)txt +i, 1); + strncat(mtx_buffer, (const char*)txt +i, (strlen(mtx_buffer) < sizeof(mtx_buffer) -1) ? 1 : 0); } i++; } diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 0382efc12..400f0991e 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -496,10 +496,10 @@ boolean Xsns34(byte function) break; #ifdef USE_HX711_GUI case FUNC_WEB_ADD_MAIN_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_MAIN_HX711, sizeof(mqtt_data)); + strncat_P(mqtt_data, HTTP_BTN_MENU_MAIN_HX711, sizeof(mqtt_data) - strlen(mqtt_data) -1); break; case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_HX711, sizeof(mqtt_data)); + strncat_P(mqtt_data, HTTP_BTN_MENU_HX711, sizeof(mqtt_data) - strlen(mqtt_data) -1); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); diff --git a/tools/decode-status.py b/tools/decode-status.py index b1881865f..83077e5fd 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -132,7 +132,7 @@ a_features = [[ "USE_MCP230xx","USE_MPR121","USE_CCS811","USE_MPU6050", "USE_MCP230xx_OUTPUT","USE_MCP230xx_DISPLAYOUTPUT","USE_HLW8012","USE_CSE7766", "USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711", - "USE_PZEM_DC","USE_TX20_WIND_SENSOR","","", + "USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","", "","","","", "","","","", "","","","", From c436ed5d3df255f96dc8d88ed432ab786cb59b9f Mon Sep 17 00:00:00 2001 From: andrethomas Date: Thu, 22 Nov 2018 17:13:55 +0200 Subject: [PATCH 0557/2222] Update boot delay code Since the driver boot delay has been removed, this is a better strategy for getting a smoother boot cpu cycle vs loop delay. --- sonoff/sonoff.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index af3b19992..96b0519a8 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2778,11 +2778,11 @@ void loop(void) delay(sleep); // https://github.com/esp8266/Arduino/issues/2021 uint32_t my_activity = millis() - my_sleep; - if (global_state.wifi_down) { - delay(my_activity /2); // Force max of 50% processing vs. yield time while wifi is down + if (my_activity < (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]) { + delay((uint32_t)Settings.param[P_LOOP_SLEEP_DELAY] - my_activity); // Provide time for background tasks like wifi } else { - if (my_activity < (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]) { - delay((uint32_t)Settings.param[P_LOOP_SLEEP_DELAY] - my_activity); // Provide time for background tasks like wifi + if (global_state.wifi_down) { + delay(my_activity /2); // If wifi down and my_activity > setoption36 then force loop delay to 1/3 of my_activity period } } } From 8c1b966004c8bb8f2c040630ee1722785bf1a596 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 22 Nov 2018 17:58:07 +0100 Subject: [PATCH 0558/2222] Move IrSend rawdata to stack Move IrSend rawdata from heap to stack --- sonoff/xdrv_05_irremote.ino | 173 +++++++++++++++++++----------------- 1 file changed, 90 insertions(+), 83 deletions(-) diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index abf303fb1..7cd38c2d5 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -26,6 +26,9 @@ #include +enum IrRemoteCommands { CMND_IRSEND, CMND_IRHVAC }; +const char kIrRemoteCommands[] PROGMEM = D_CMND_IRSEND "|" D_CMND_IRHVAC ; + // 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"; @@ -35,6 +38,9 @@ const char kIrRemoteProtocols[] PROGMEM = #include #include +enum IrHvacVendors { VNDR_TOSHIBA, VNDR_MITSUBISHI, VNDR_LG, VNDR_FUJITSU }; +const char kIrHvacVendors[] PROGMEM = "Toshiba|Mitsubishi|LG|Fujitsu" ; + // HVAC TOSHIBA_ #define HVAC_TOSHIBA_HDR_MARK 4400 #define HVAC_TOSHIBA_HDR_SPACE 4300 @@ -501,22 +507,19 @@ boolean IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H boolean IrSendCommand(void) { + char command [CMDSZ]; boolean serviced = true; boolean error = false; - char protocol_text[20]; - const char *protocol; - uint32_t bits = 0; - uint32_t data = 0; - char dataBufUc[XdrvMailbox.data_len]; - UpperCase(dataBufUc, XdrvMailbox.data); - if (!strcasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_IRSEND))) { + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kIrRemoteCommands); + if (-1 == command_code) { + serviced = false; // Unknown command + } + else if (CMND_IRSEND == command_code) { if (XdrvMailbox.data_len) { - StaticJsonBuffer<128> jsonBuf; - JsonObject &root = jsonBuf.parseObject(dataBufUc); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_DONE "\"}")); - if (!root.success()) { + if (!strstr(XdrvMailbox.data, "{")) { // If no JSON it must be rawdata // IRSend frequency, rawdata, rawdata ... char *p; char *str = strtok_r(XdrvMailbox.data, ", ", &p); @@ -527,69 +530,72 @@ boolean IrSendCommand(void) for (; *q; count += (*q++ == ',')); if (count) { // At least two raw data values count++; - uint16_t* raw_array = NULL; - raw_array = reinterpret_cast(malloc(count * sizeof(uint16_t))); - if (raw_array != NULL) { - byte i = 0; - for (str = strtok_r(NULL, ", ", &p); str && i < count; str = strtok_r(NULL, ", ", &p)) { - raw_array[i++] = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input - } - -// snprintf_P(log_data, sizeof(log_data), PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), -// count, freq, raw_array[0], raw_array[count -1]); -// AddLog(LOG_LEVEL_DEBUG); - - irsend->sendRaw(raw_array, count, freq); - free(raw_array); - if (!count) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_FAILED "\"}")); // JSON decode failed and invalid RawData - } + uint16_t raw_array[count]; // It's safe to use stack for up to 240 packets (limited by mqtt_data length) + byte i = 0; + for (str = strtok_r(NULL, ", ", &p); str && i < count; str = strtok_r(NULL, ", ", &p)) { + raw_array[i++] = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input } - else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO_BUFFER_SPACE "\"}")); // JSON decode failed and invalid RawData + +// DebugFreeMem(); +// snprintf_P(log_data, sizeof(log_data), PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), +// count, freq, raw_array[0], raw_array[count -1]); +// AddLog(LOG_LEVEL_DEBUG); + + irsend->sendRaw(raw_array, count, freq); + if (!count) { + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_FAILED); } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_INVALID_RAWDATA "\"}")); // JSON decode failed and invalid RawData + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_RAWDATA); } } else { - // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } - char parm_uc[10]; - - protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; - bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; - data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], NULL, 0); - if (protocol && bits) { - int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); - - snprintf_P(log_data, sizeof(log_data), PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"), - protocol_text, protocol, bits, data, data, protocol_code); - AddLog(LOG_LEVEL_DEBUG); - - switch (protocol_code) { - case NEC: - irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits); break; - case SONY: - irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, 2); break; - case RC5: - irsend->sendRC5(data, bits); break; - case RC6: - irsend->sendRC6(data, bits); break; - case DISH: - irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits); break; - case JVC: - irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, 1); break; - case SAMSUNG: - irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits); break; - case PANASONIC: - irsend->sendPanasonic(bits, data); break; - default: - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_PROTOCOL_NOT_SUPPORTED "\"}")); - } + char dataBufUc[XdrvMailbox.data_len]; + UpperCase(dataBufUc, XdrvMailbox.data); + StaticJsonBuffer<128> jsonBuf; + JsonObject &root = jsonBuf.parseObject(dataBufUc); + if (!root.success()) { + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); } else { - error = true; + // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } + char parm_uc[10]; + const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; + uint32_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; + uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], NULL, 0); + if (protocol && bits) { + char protocol_text[20]; + int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); + + snprintf_P(log_data, sizeof(log_data), PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"), + protocol_text, protocol, bits, data, data, protocol_code); + AddLog(LOG_LEVEL_DEBUG); + + switch (protocol_code) { + case NEC: + irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits); break; + case SONY: + irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, 2); break; + case RC5: + irsend->sendRC5(data, bits); break; + case RC6: + irsend->sendRC6(data, bits); break; + case DISH: + irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits); break; + case JVC: + irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, 1); break; + case SAMSUNG: + irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits); break; + case PANASONIC: + irsend->sendPanasonic(bits, data); break; + default: + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED); + } + } + else { + error = true; + } } } } @@ -601,7 +607,7 @@ boolean IrSendCommand(void) } } #ifdef USE_IR_HVAC - else if (!strcasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_IRHVAC))) { + else if (CMND_IRHVAC == command_code) { const char *HVAC_Mode; const char *HVAC_FanMode; const char *HVAC_Vendor; @@ -609,13 +615,15 @@ boolean IrSendCommand(void) boolean HVAC_Power = true; if (XdrvMailbox.data_len) { + char dataBufUc[XdrvMailbox.data_len]; + UpperCase(dataBufUc, XdrvMailbox.data); StaticJsonBuffer<164> jsonBufer; JsonObject &root = jsonBufer.parseObject(dataBufUc); if (!root.success()) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_INVALID_JSON "\"}")); // JSON decode failed + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_DONE "\"}")); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); HVAC_Vendor = root[D_JSON_IRHVAC_VENDOR]; HVAC_Power = root[D_JSON_IRHVAC_POWER]; HVAC_Mode = root[D_JSON_IRHVAC_MODE]; @@ -626,20 +634,19 @@ boolean IrSendCommand(void) // 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 if (!strcasecmp_P(HVAC_Vendor, PSTR("LG"))) { - error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); - } - else if (!strcasecmp_P(HVAC_Vendor, PSTR("FUJITSU"))) { - error = IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); - } - else { - error = true; + char vendor[20]; + int vendor_code = GetCommandCode(vendor, sizeof(vendor), HVAC_Vendor, kIrHvacVendors); + switch (vendor_code) { + case VNDR_TOSHIBA: + error = IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; + case VNDR_MITSUBISHI: + error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; + case VNDR_LG: + error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; + case VNDR_FUJITSU: + error = IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; + default: + error = true; } } } @@ -651,7 +658,7 @@ boolean IrSendCommand(void) } } #endif // USE_IR_HVAC - else serviced = false; // Unknown command + else serviced = false; // Unknown command return serviced; } From 763a280903d8692fafa50a867f61db4f1a89aa4a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 23 Nov 2018 11:04:05 +0100 Subject: [PATCH 0559/2222] Fix MPU6050 JSON message Fix MPU6050 JSON message (#4412) --- sonoff/xsns_32_mpu6050.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index 795405688..0c6f50f09 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -152,7 +152,7 @@ void MPU_6050Show(boolean json) snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy); char json_axis_gz[40]; snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s,\"}"), + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), mqtt_data, D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); #ifdef USE_DOMOTICZ DomoticzTempHumSensor(temperature, 0); From 0daf26586d0a25cf2866aa9d2c590580c1565425 Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Fri, 23 Nov 2018 20:03:11 +0200 Subject: [PATCH 0560/2222] Added icon and link to discord --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0bbf1acf1..348c06cb1 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead. [![GitHub version](https://img.shields.io/github/release/arendst/Sonoff-Tasmota.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) [![GitHub download](https://img.shields.io/github/downloads/arendst/Sonoff-Tasmota/total.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) [![License](https://img.shields.io/github/license/arendst/Sonoff-Tasmota.svg)](https://github.com/arendst/Sonoff-Tasmota/blob/development/LICENSE.txt) +[![Chat](https://img.shields.io/discord/479389167382691863.svg)](https://discord.gg/Ks2Kzd4) If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute! From 64d6ef86ceebcfdab82f2bec9946fc66a548c656 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sat, 24 Nov 2018 03:29:32 +0100 Subject: [PATCH 0561/2222] PS_16_DZ: initial support --- sonoff/language/tuya.patch | 13 ++ sonoff/my_user_config.h | 1 + sonoff/sonoff.h | 2 +- sonoff/sonoff_post.h | 1 + sonoff/sonoff_template.h | 22 +++- sonoff/xdrv_04_light.ino | 5 + sonoff/xdrv_19_ps16dz_dimmer.ino | 211 +++++++++++++++++++++++++++++++ 7 files changed, 252 insertions(+), 3 deletions(-) create mode 100644 sonoff/language/tuya.patch create mode 100644 sonoff/xdrv_19_ps16dz_dimmer.ino diff --git a/sonoff/language/tuya.patch b/sonoff/language/tuya.patch new file mode 100644 index 000000000..685f4458c --- /dev/null +++ b/sonoff/language/tuya.patch @@ -0,0 +1,13 @@ +diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h +index 4e3aa00..925080d 100644 +--- a/sonoff/language/en-GB.h ++++ b/sonoff/language/en-GB.h +@@ -527,6 +527,8 @@ + #define D_SENSOR_TX20_TX "TX20" + #define D_SENSOR_RFSEND "RFSend" + #define D_SENSOR_RFRECV "RFrecv" ++#define D_SENSOR_TUYA_TX "Tuya Tx" ++#define D_SENSOR_TUYA_RX "Tuya Rx" + + // Units + #define D_UNIT_AMPERE "A" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 91b764688..dc23003cd 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -360,6 +360,7 @@ #define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer #define TUYA_DIMMER_ID 0 // Default dimmer Id #define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) +#define USE_PS_16_DZ // ADD support for PS-16-DZ Dimmer // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index e53a7c83d..07b87661c 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -231,7 +231,7 @@ enum Ws2812Color { WS_RED, WS_GREEN, WS_BLUE }; enum LightSubtypes { LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC }; // Do not insert new fields enum LightTypes { LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, - LT_NU8, LT_SERIAL1, LT_SERIAL2, LT_WS2812, LT_RGBW, LT_RGBWC, LT_NU14, LT_NU15 }; // Do not insert new fields + LT_NU8, LT_SERIAL1, LT_SERIAL2, LT_WS2812, LT_RGBW, LT_RGBWC, LT_SERIAL3, LT_NU15 }; // Do not insert new fields enum LightSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 1e52a8641..b6fc2c77f 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -111,6 +111,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #ifndef TUYA_DIMMER_ID #define TUYA_DIMMER_ID 0 // Default dimmer Id #endif +#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) #define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) #define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 3135dd339..98e329bdf 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -256,6 +256,7 @@ enum SupportedModules { GOSUND, ARMTRONIX_DIMMERS, SK03_TUYA, + PS_16_DZ, MAXMODULE }; /********************************************************************************************/ @@ -494,7 +495,8 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { AILIGHT, // Light Bulbs PHILIPS, WITTY, // Development Devices - WEMOS + WEMOS, + PS_16_DZ }; // Default module settings @@ -1270,7 +1272,23 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1_INV, // GPIO14 Blue Led (0 = On, 1 = Off) GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) 0, 0 - } + }, + { "PS-16-DZ", // PS-16-DZ Dimmer (ESP8266 w/ separate Nuvoton MCU dimmer) + // https://www.aliexpress.com/item/SM-Smart-WIFI-Wall-Dimmer-Light-Switch-US-Ewelink-APP-Remote-Control-Wi-Fi-Wirele-Work/32871151902.html + GPIO_USER, + GPIO_TXD, // GPIO01 MCU serial control + GPIO_USER, + GPIO_RXD, // GPIO03 MCU serial control + GPIO_USER, + GPIO_USER, + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_USER, + GPIO_USER, + GPIO_USER, + GPIO_USER, + GPIO_USER, + 0 + } }; /* diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 92e19fb57..10caf2472 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -841,6 +841,11 @@ void LightAnimate(void) LightSerial2Duty(cur_col[0],cur_col[1]); } #endif // USE_ARMTRONIX_DIMMERS +#ifdef USE_PS16DZ_DIMMERS + if (light_type == LT_SERIAL3) { + PS16DZSerialDuty(cur_col[0]); + } +#endif // USE_PS16DZ_DIMMERS } } diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino new file mode 100644 index 000000000..82f81eefa --- /dev/null +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -0,0 +1,211 @@ +/* + xdrv_16_ps16dzdimmer.ino - PS16DZ dimmer support for Sonoff-Tasmota + + Copyright (C) 2018 Joel Stein 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 + 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_PS_16_DZ + +#define XDRV_19 19 + +#define PS16DZ_BUFFER_SIZE 256 + +#include + +TasmotaSerial *PS16DZSerial = nullptr; + +boolean ps16dz_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction +int8_t ps16dz_wifi_state = -2; // Keep MCU wifi-status in sync with WifiState() + +boolean ps16dz_power = false; +uint8_t ps16dz_bright = 0; +uint64_t ps16dz_seq = 0; + +char ps16dz_buffer[PS16DZ_BUFFER_SIZE]; // Serial receive buffer +int ps16dz_byte_counter = 0; // Index in serial receive buffer + +/*********************************************************************************************\ + * Internal Functions +\*********************************************************************************************/ + + +boolean PS16DZSetPower(void) +{ + boolean status = false; + + uint8_t rpower = XdrvMailbox.index; + int16_t source = XdrvMailbox.payload; + + if (source != SRC_SWITCH && PS16DZSerial) { // ignore to prevent loop from pushing state from faceplate interaction + + snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "AT+UPDATE=\"sequence\":\"%lld\",\"switch\":\"%s\""), ps16dz_seq++, rpower?"on":"off"); + snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_buffer ); + AddLog(LOG_LEVEL_DEBUG); + + PS16DZSerial->print(ps16dz_buffer); + PS16DZSerial->write(0x1B); + + status = true; + } + return status; +} + +void PS16DZSerialDuty(uint8_t duty) +{ + if (duty > 0 && !ps16dz_ignore_dim && PS16DZSerial) { + if (duty < 25) { + duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself + } + + snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "AT+UPDATE=\"sequence\":\"%lld\",\"bright\":\"%d\""), ps16dz_seq++, duty/(255./100.)); + snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_buffer ); + AddLog(LOG_LEVEL_DEBUG); + + PS16DZSerial->print(ps16dz_buffer); + PS16DZSerial->write(0x1B); + + } else { + ps16dz_ignore_dim = false; // reset flag + + snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send Dim Level skipped due to 0 or already set. Value=%d"), duty); + AddLog(LOG_LEVEL_DEBUG); + + } +} + +void PS16DZResetWifi(void) +{ + if (!Settings.flag.button_restrict) { + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2); + ExecuteCommand(scmnd, SRC_BUTTON); + } +} + +/*********************************************************************************************\ + * API Functions +\*********************************************************************************************/ + +boolean PS16DZModuleSelected(void) +{ + light_type = LT_SERIAL3; + return true; +} + +void PS16DZInit(void) +{ + PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (PS16DZSerial->begin(19200)) { + if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } + } +} + +void PS16DZSerialInput(void) +{ + char scmnd[20]; + String ps16dz_command; + while (PS16DZSerial->available()) { + yield(); + ps16dz_command = PS16DZSerial->readStringUntil(0x1B); + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: command received: %s"), ps16dz_command.c_str()); + AddLog(LOG_LEVEL_DEBUG); + if(ps16dz_command.substring(3,6) == "UPDATE" || ps16dz_command.substring(3,6) == "RESULT"){ + char *end_str; + char *string = strdup(ps16dz_command.substring(10).c_str()); + char* token = strtok_r(string, ",", &end_str); + while (token != NULL) { + char* end_token; + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: token = %s"), token); + AddLog(LOG_LEVEL_DEBUG); + char* token2 = strtok_r(token, ":", &end_token); + char* token3 = strtok_r(NULL, ":", &end_token); + if(!strncmp(token2, "\"switch\"", 8)){ + ps16dz_power = !strncmp(token3, "\"on\"", 4)?true:false; + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: power received: %s"), token3); + AddLog(LOG_LEVEL_DEBUG); + if((power || Settings.light_dimmer > 0) && (power !=ps16dz_power)) { + ExecuteCommandPower(1, ps16dz_power, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction + } + } + else if(!strncmp(token2, "\"bright\"", 8)){ + ps16dz_bright = atoi(token3); + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: brightness received: %d"), ps16dz_bright); + AddLog(LOG_LEVEL_DEBUG); + if(power && ps16dz_bright > 0) { + + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), ps16dz_bright ); + + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: Send CMND_DIMMER_STR=%s"), scmnd ); + AddLog(LOG_LEVEL_DEBUG); + + ps16dz_ignore_dim = true; + ExecuteCommand(scmnd, SRC_SWITCH); + } + + } + else if(!strncmp(token2, "\"sequence\"", 10)){ + ps16dz_seq = strtoull(token3, NULL, 10); + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: sequence received: %lld"), ps16dz_seq); + AddLog(LOG_LEVEL_DEBUG); + } + + token = strtok_r(NULL, ",", &end_str); + } + } + else if(ps16dz_command.substring(3,7) == "SETTING"){ + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: Reset")); + AddLog(LOG_LEVEL_DEBUG); + PS16DZResetWifi(); + } + snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "AT+SEND=ok")); + snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_buffer ); + AddLog(LOG_LEVEL_DEBUG); + + PS16DZSerial->print(ps16dz_buffer); + PS16DZSerial->write(0x1B); + } +} + + + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +boolean Xdrv19(byte function) +{ + boolean result = false; + + if (PS_16_DZ == Settings.module) { + switch (function) { + case FUNC_MODULE_INIT: + result = PS16DZModuleSelected(); + break; + case FUNC_INIT: + PS16DZInit(); + break; + case FUNC_LOOP: + if (PS16DZSerial) { PS16DZSerialInput(); } + break; + case FUNC_SET_DEVICE_POWER: + result = PS16DZSetPower(); + break; + } + } + return result; +} + +#endif // USE_PS_16_DZ From dfc154ab167708860734a3613b46be8a86387382 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sat, 24 Nov 2018 03:38:55 +0100 Subject: [PATCH 0562/2222] PS_16_DZ: remove unwanted file --- sonoff/language/tuya.patch | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 sonoff/language/tuya.patch diff --git a/sonoff/language/tuya.patch b/sonoff/language/tuya.patch deleted file mode 100644 index 685f4458c..000000000 --- a/sonoff/language/tuya.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h -index 4e3aa00..925080d 100644 ---- a/sonoff/language/en-GB.h -+++ b/sonoff/language/en-GB.h -@@ -527,6 +527,8 @@ - #define D_SENSOR_TX20_TX "TX20" - #define D_SENSOR_RFSEND "RFSend" - #define D_SENSOR_RFRECV "RFrecv" -+#define D_SENSOR_TUYA_TX "Tuya Tx" -+#define D_SENSOR_TUYA_RX "Tuya Rx" - - // Units - #define D_UNIT_AMPERE "A" From 55b287d6da7a624f021be6d485d91b368ef6ff88 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sat, 24 Nov 2018 04:09:57 +0100 Subject: [PATCH 0563/2222] PS_16_DZ: fix define in xdrv04 --- sonoff/xdrv_04_light.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 10caf2472..d306bc974 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -841,11 +841,11 @@ void LightAnimate(void) LightSerial2Duty(cur_col[0],cur_col[1]); } #endif // USE_ARMTRONIX_DIMMERS -#ifdef USE_PS16DZ_DIMMERS +#ifdef USE_PS_16_DZ if (light_type == LT_SERIAL3) { PS16DZSerialDuty(cur_col[0]); } -#endif // USE_PS16DZ_DIMMERS +#endif // USE_PS_16_DZ } } From 34da2859ba8afdc10c4ef8ff3f72e0c2b5a5e72f Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sat, 24 Nov 2018 05:08:14 +0100 Subject: [PATCH 0564/2222] PS_16_DZ: fixes --- sonoff/sonoff.h | 2 +- sonoff/xdrv_04_light.ino | 2 +- sonoff/xdrv_19_ps16dz_dimmer.ino | 39 ++++++++++++++++++++++++++++---- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 07b87661c..e53a7c83d 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -231,7 +231,7 @@ enum Ws2812Color { WS_RED, WS_GREEN, WS_BLUE }; enum LightSubtypes { LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC }; // Do not insert new fields enum LightTypes { LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, - LT_NU8, LT_SERIAL1, LT_SERIAL2, LT_WS2812, LT_RGBW, LT_RGBWC, LT_SERIAL3, LT_NU15 }; // Do not insert new fields + LT_NU8, LT_SERIAL1, LT_SERIAL2, LT_WS2812, LT_RGBW, LT_RGBWC, LT_NU14, LT_NU15 }; // Do not insert new fields enum LightSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index d306bc974..455adc4d0 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -842,7 +842,7 @@ void LightAnimate(void) } #endif // USE_ARMTRONIX_DIMMERS #ifdef USE_PS_16_DZ - if (light_type == LT_SERIAL3) { + if (light_type == LT_SERIAL1) { PS16DZSerialDuty(cur_col[0]); } #endif // USE_PS_16_DZ diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 82f81eefa..fb43e31d2 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -1,5 +1,5 @@ /* - xdrv_16_ps16dzdimmer.ino - PS16DZ dimmer support for Sonoff-Tasmota + xdrv_16_ps16dz_dimmer.ino - PS16DZ dimmer support for Sonoff-Tasmota Copyright (C) 2018 Joel Stein and Theo Arends @@ -42,6 +42,31 @@ int ps16dz_byte_counter = 0; // Index in serial receive buffer \*********************************************************************************************/ +size_t print_uint64_t(uint64_t number) +{ + size_t n = 0; + unsigned char buf[21]; + uint8_t i = 0; + + if (number == 0) + { + n += snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "%s%c"), ps16dz_buffer, (char)'0'); + return n; + } + + while (number > 0) + { + uint64_t q = number/10; + buf[i++] = number - q*10; + number = q; + } + + for (; i > 0; i--) + n += snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "%s%c"), ps16dz_buffer, (char) ('0' + buf[i - 1])); + + return n; +} + boolean PS16DZSetPower(void) { boolean status = false; @@ -51,7 +76,9 @@ boolean PS16DZSetPower(void) if (source != SRC_SWITCH && PS16DZSerial) { // ignore to prevent loop from pushing state from faceplate interaction - snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "AT+UPDATE=\"sequence\":\"%lld\",\"switch\":\"%s\""), ps16dz_seq++, rpower?"on":"off"); + snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); + print_uint64_t(ps16dz_seq++); + snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "%s\",\"switch\":\"%s\""), ps16dz_buffer, rpower?"on":"off"); snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_buffer ); AddLog(LOG_LEVEL_DEBUG); @@ -70,7 +97,9 @@ void PS16DZSerialDuty(uint8_t duty) duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself } - snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "AT+UPDATE=\"sequence\":\"%lld\",\"bright\":\"%d\""), ps16dz_seq++, duty/(255./100.)); + snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); + print_uint64_t(ps16dz_seq++); + snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "%s\",\"bright\":\"%d\""), ps16dz_buffer, round(duty * (100. / 255.))); snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_buffer ); AddLog(LOG_LEVEL_DEBUG); @@ -101,7 +130,7 @@ void PS16DZResetWifi(void) boolean PS16DZModuleSelected(void) { - light_type = LT_SERIAL3; + light_type = LT_SERIAL1; return true; } @@ -158,7 +187,7 @@ void PS16DZSerialInput(void) } else if(!strncmp(token2, "\"sequence\"", 10)){ ps16dz_seq = strtoull(token3, NULL, 10); - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: sequence received: %lld"), ps16dz_seq); + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: sequence received: %0ld"), ps16dz_seq/1000000L, ps16dz_seq%1000000L); AddLog(LOG_LEVEL_DEBUG); } From a6983d52f7a877e5b5c286796dd060f01235557a Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 24 Nov 2018 12:46:32 +0200 Subject: [PATCH 0565/2222] Increase delays before web ui is refreshed The current 5-second delay before refreshing web ui after settings were changed is not always sufficient as wifi can take up to 10 seconds to re-connect and be available on some wireless networks, depending on the device's RSSI. This change increases the delay from 5 seconds to 10 seconds which have been tested down to RSSI levels of 25 to be sufficient. This change also increases the refresh delay when a local OTA is uploaded to 20 seconds which allows enough time for the cp: process to complete and the device to reconnected to wifi under >= 25 RSSI conditions. --- sonoff/xdrv_01_webserver.ino | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 09df2dd7d..7c7f60718 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -95,7 +95,12 @@ const char HTTP_SCRIPT_WIFI[] PROGMEM = "}"; const char HTTP_SCRIPT_RELOAD[] PROGMEM = - "setTimeout(function(){location.href='.';},5000);" + "setTimeout(function(){location.href='.';},10000);" + ""; + +// Local OTA upgrade requires more time to complete cp: before web ui should be reloaded +const char HTTP_SCRIPT_RELOAD_OTA[] PROGMEM = + "setTimeout(function(){location.href='.';},20000);" ""; const char HTTP_SCRIPT_CONSOL[] PROGMEM = @@ -1463,7 +1468,7 @@ void HandleUploadDone(void) } else { page += F("green'>" D_SUCCESSFUL "
          "); page += FPSTR(HTTP_MSG_RSTRT); - page.replace(F(""), FPSTR(HTTP_SCRIPT_RELOAD)); + page.replace(F(""), FPSTR(HTTP_SCRIPT_RELOAD_OTA)); // Refesh main web ui after OTA upgrade ShowWebSource(SRC_WEBGUI); restart_flag = 2; // Always restart to re-enable disabled features during update } From ef4e2b297c9f2da3bdf667214de74400771eaad2 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 24 Nov 2018 13:00:45 +0200 Subject: [PATCH 0566/2222] Decrease update webui refresh to 5 seconds Decrease update webui refresh to 5 seconds --- sonoff/xdrv_01_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 7c7f60718..eeebe5861 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -95,7 +95,7 @@ const char HTTP_SCRIPT_WIFI[] PROGMEM = "}"; const char HTTP_SCRIPT_RELOAD[] PROGMEM = - "setTimeout(function(){location.href='.';},10000);" + "setTimeout(function(){location.href='.';},5000);" ""; // Local OTA upgrade requires more time to complete cp: before web ui should be reloaded From 263839a1a05e69a7904ff5b00df8759d3607356c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 24 Nov 2018 12:01:13 +0100 Subject: [PATCH 0567/2222] Fix MqttRetry values above 255 Fix MqttRetry values above 255 seconds (#4424) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_02_mqtt.ino | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 91e7ebe9c..3358fd957 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,6 +4,7 @@ * Add support for I2C MGC3130 Electric Field Effect sensor by Christian Baars (#3774, #4404) * Add initial support for Hass sensor discovery (#4380) * Fix possible strncat buffer overflows + * Fix MqttRetry values above 255 seconds (#4424) * * 6.3.0.11 20181120 * Add delays removed in 6.3.0.9 (#4233) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 34025c5fc..2e026c71f 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -70,7 +70,7 @@ const char kMqttCommands[] PROGMEM = D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|" D_CMND_BUTTONTOPIC "|" D_CMND_SWITCHTOPIC "|" D_CMND_BUTTONRETAIN "|" D_CMND_SWITCHRETAIN "|" D_CMND_POWERRETAIN "|" D_CMND_SENSORRETAIN ; -uint8_t mqtt_retry_counter = 1; // MQTT connection retry counter +uint16_t mqtt_retry_counter = 1; // MQTT connection retry counter uint8_t mqtt_initial_connection_state = 2; // MQTT connection messages state bool mqtt_connected = false; // MQTT virtual connection status From 9608bfd2e5a36211df4ffc796be30f7ea61887e9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 24 Nov 2018 12:04:30 +0100 Subject: [PATCH 0568/2222] Update xdrv_01_webserver.ino --- sonoff/xdrv_01_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index eeebe5861..a6c2a2a1c 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -95,7 +95,7 @@ const char HTTP_SCRIPT_WIFI[] PROGMEM = "}"; const char HTTP_SCRIPT_RELOAD[] PROGMEM = - "setTimeout(function(){location.href='.';},5000);" + "setTimeout(function(){location.href='.';},9000);" ""; // Local OTA upgrade requires more time to complete cp: before web ui should be reloaded From 01db8fa25b10834ac55b1052d582f6ccc6d497d6 Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Sat, 24 Nov 2018 13:28:32 +0200 Subject: [PATCH 0569/2222] Update _changelog.ino --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 3358fd957..312c2855d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -5,6 +5,7 @@ * Add initial support for Hass sensor discovery (#4380) * Fix possible strncat buffer overflows * Fix MqttRetry values above 255 seconds (#4424) + * Increase webui refresh time delay for Save Settings and local OTA Upload (#4423) * * 6.3.0.11 20181120 * Add delays removed in 6.3.0.9 (#4233) From 4b57bff7282962a830460828217002a21e309bb9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 24 Nov 2018 16:08:53 +0100 Subject: [PATCH 0570/2222] Rename Module 45 to Blitzwolf SHP Rename Module 45 to Blitzwolf SHP as it serves both SHP2 and SHP6 (among others) --- RELEASENOTES.md | 2 +- sonoff/sonoff_template.h | 33 ++++++++++++++++++++++----------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 161f03415..254cf32ce 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -66,7 +66,7 @@ Module | Description 42 Zengge WF017 | Zengge WF017 Wifi RGB(W) Led Controller 43 Sonoff Pow R2 | Sonoff Pow R2 Wifi Smart Switch with Energy Monitoring 44 Sonoff iFan02 | Sonoff iFan02 Wifi Smart Ceiling Fan with Light -45 BlitzWolf SHP2 | BlitzWolf BW-SHP2, BW-SHP6, HomeCube SP1, Gosund SP111, Teckin SP22 Wifi Smart Switch with Energy Monitoring +45 BlitzWolf SHP | BlitzWolf BW-SHP2, BW-SHP6, HomeCube SP1, Gosund SP111, Teckin SP22 Wifi Smart Switch with Energy Monitoring 46 Shelly 1 | Shelly 1 Open Source Wifi Relay Module 47 Shelly 2 | Shelly 2 Wifi 2-gang Relay Module with Energy Monitoring 48 Xiaomi Philips | Xiaomi Philips Wifi WW Led Bulb diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 3135dd339..b95e7804e 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -243,7 +243,7 @@ enum SupportedModules { ZENGGE_ZF_WF017, SONOFF_POW_R2, SONOFF_IFAN02, - BLITZWOLF_BWSHP2, + BLITZWOLF_BWSHP, SHELLY1, SHELLY2, PHILIPS, @@ -473,7 +473,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { WION, SHELLY1, SHELLY2, - BLITZWOLF_BWSHP2, // Socket Relay Devices with Energy Monitoring + BLITZWOLF_BWSHP, // Socket Relay Devices with Energy Monitoring TECKIN, APLIC_WDP303075, GOSUND, @@ -1104,10 +1104,11 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL4, // GPIO15 WIFI_O3 Relay 4 (0 = Off, 1 = On) controlling the fan 0, 0 }, - { "BlitzWolf SHP2", // BlitzWolf BW-SHP2 (ESP8285 - BL0937 or HJL-01 Energy Monitoring) + { "BlitzWolf SHP", // BlitzWolf BW-SHP2 and BW-SHP6 (ESP8285 - BL0937 or HJL-01 Energy Monitoring) // https://www.banggood.com/BlitzWolf-BW-SHP2-Smart-WIFI-Socket-EU-Plug-220V-16A-Work-with-Amazon-Alexa-Google-Assistant-p-1292899.html // https://www.amazon.de/Steckdose-Homecube-intelligente-Verbrauchsanzeige-funktioniert/dp/B076Q2LKHG/ref=sr_1_fkmr0_1 // https://www.amazon.de/Intelligente-Stromverbrauch-Fernsteurung-Schaltbare-Energieklasse/dp/B076WZQS4S/ref=sr_1_1 + // https://www.aliexpress.com/store/product/BlitzWolf-BW-SHP6-EU-Plug-Metering-Version-WIFI-Smart-Socket-220V-240V-10A-Work-with-Amazon/1965360_32945504669.html GPIO_LED2_INV, // GPIO00 Red Led (1 = On, 0 = Off) GPIO_USER, // GPIO01 Serial RXD and Optional sensor GPIO_LED1_INV, // GPIO02 Blue Led (1 = On, 0 = Off) @@ -1243,25 +1244,25 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, 0 }, { "ARMTR Dimmer", // ARMTRONIX Dimmer, one or two channel (ESP8266 w/ separate MCU dimmer) - // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-two-triac-board/ - // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-esp8266-one-triac-board-alexaecho/ - GPIO_USER, - GPIO_TXD, // GPIO01 MCU serial control + // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-two-triac-board/ + // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-esp8266-one-triac-board-alexaecho/ GPIO_USER, - GPIO_RXD, // GPIO03 MCU serial control + GPIO_TXD, // GPIO01 MCU serial control + GPIO_USER, + GPIO_RXD, // GPIO03 MCU serial control GPIO_USER, GPIO_USER, 0, 0, 0, 0, 0, 0, // Flash connection GPIO_USER, GPIO_USER, - GPIO_USER, + GPIO_USER, GPIO_USER, GPIO_USER, 0 }, { "SK03 Outdoor", // Outdoor smart plug with power monitoring HLW8012 chip - https://www.amazon.com/gp/product/B07CG7MBPV GPIO_KEY1, // GPIO00 Button - 0, 0, 0, + 0, 0, 0, GPIO_HLW_CF, // GPIO04 HLW8012 CF power GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 current / voltage 0, 0, 0, 0, 0, 0, // Flash connection @@ -1270,7 +1271,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1_INV, // GPIO14 Blue Led (0 = On, 1 = Off) GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) 0, 0 - } + } }; /* @@ -1385,6 +1386,16 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO16 (D16) 0 // ADC0 Analog input (A0) } + + { "Delock 11826", // Delock 11826 (ESP8285) = Sonoff Basic + GPIO_KEY1, // GPIO00 Button + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) + 0, 0, 0, 0 + } + */ #endif // _SONOFF_TEMPLATE_H_ From 9574fc7c65dc755494b2d10297c16de114381476 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sat, 24 Nov 2018 16:24:44 +0100 Subject: [PATCH 0571/2222] PS_16_DZ: fixes --- sonoff/xdrv_19_ps16dz_dimmer.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index fb43e31d2..ce8ce7267 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -1,5 +1,5 @@ /* - xdrv_16_ps16dz_dimmer.ino - PS16DZ dimmer support for Sonoff-Tasmota + xdrv_19_ps16dz_dimmer.ino - PS_16_DZ dimmer support for Sonoff-Tasmota Copyright (C) 2018 Joel Stein and Theo Arends From f391c0fd651afe2f8037145f36995310df0711c6 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sat, 24 Nov 2018 16:32:09 +0100 Subject: [PATCH 0572/2222] OBI: make UART user configurable --- sonoff/sonoff_template.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 3135dd339..8332e7881 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1177,7 +1177,9 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { }, { "OBI Socket", // OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko/p/2291706 GPIO_USER, // GPIO00 - 0,0,0, + GPIO_USER, // GPIO01 Serial RXD + 0, + GPIO_USER, // GPIO03 Serial TXD GPIO_LED1, // GPIO04 Blue LED GPIO_REL1, // GPIO05 (Relay OFF, but used as Relay Switch) 0, 0, 0, 0, 0, 0, // Flash connection From 0e56044eb5049d17fdbc48500c9fb214a435ab89 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 24 Nov 2018 18:12:49 +0200 Subject: [PATCH 0573/2222] Add main loop load average Add main loop avarage duty cycle measured against setoption36 value to telemetry data as LoadAvg --- sonoff/sonoff.ino | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 96b0519a8..b1a279b47 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -190,6 +190,7 @@ char mqtt_data[MESSZ]; // MQTT publish buffer and web page char log_data[LOGSZ]; // Logging char web_log[WEB_LOG_SIZE] = {'\0'}; // Web log buffer String backlog[MAX_BACKLOG]; // Command backlog +uint32_t loop_load_avg = 0; // Indicative loop load average /********************************************************************************************/ @@ -1575,6 +1576,8 @@ void MqttShowState(void) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VCC "\":%s"), mqtt_data, stemp1); #endif + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LoadAvg\":%u"), mqtt_data, loop_load_avg); + for (byte i = 0; i < devices_present; i++) { if (i == light_device -1) { LightState(1); @@ -2579,6 +2582,15 @@ void GpioInit(void) XdrvCall(FUNC_PRE_INIT); } + +void update_loop_load_avg(uint32_t loop_activity) +{ + uint32_t loops_per_second = 1000 / (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]; // We need to keep track of this many loops per second + uint32_t this_cycle_ratio = 100 * loop_activity / (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]; + uint32_t new_load_avg = loop_load_avg-(loop_load_avg/loops_per_second); // Take away one loop average + new_load_avg = new_load_avg + this_cycle_ratio; + loop_load_avg = new_load_avg; +} extern "C" { extern struct rst_info resetInfo; @@ -2785,4 +2797,9 @@ void loop(void) delay(my_activity /2); // If wifi down and my_activity > setoption36 then force loop delay to 1/3 of my_activity period } } + if (my_activity < (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]) { + update_loop_load_avg(my_activity); + } else { + update_loop_load_avg((uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]); // Assume 100% loop cycle ratio + } } From 4700e49d705cdd29da6a05cadfe0fa9ca0fa9f8b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 24 Nov 2018 17:16:27 +0100 Subject: [PATCH 0574/2222] Update sonoff.ino --- sonoff/sonoff.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index b1a279b47..f461b6de0 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -125,6 +125,7 @@ int wifi_state_flag = WIFI_RESTART; // Wifi state flag int tele_period = 1; // Tele period timer int blinks = 201; // Number of LED blinks uint32_t uptime = 0; // Counting every second until 4294967295 = 130 year +uint32_t loop_load_avg = 0; // Indicative loop load average uint32_t global_update = 0; // Timestamp of last global temperature and humidity update float global_temperature = 0; // Provide a global temperature to be used by some sensors float global_humidity = 0; // Provide a global humidity to be used by some sensors @@ -190,7 +191,7 @@ char mqtt_data[MESSZ]; // MQTT publish buffer and web page char log_data[LOGSZ]; // Logging char web_log[WEB_LOG_SIZE] = {'\0'}; // Web log buffer String backlog[MAX_BACKLOG]; // Command backlog -uint32_t loop_load_avg = 0; // Indicative loop load average + /********************************************************************************************/ From 164db4e12b4789aea0594303834e3d74d0293519 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 24 Nov 2018 17:22:06 +0100 Subject: [PATCH 0575/2222] Clean up Clean up --- sonoff/support.ino | 9 --------- sonoff/support_wifi.ino | 8 ++++++++ sonoff/xdrv_interface.ino | 2 +- sonoff/xsns_interface.ino | 4 ++-- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 234764791..540191855 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -767,15 +767,6 @@ uint8_t ValidGPIO(uint8_t pin, uint8_t gpio) return result; } -void AppDelay(void) -{ - if (APP_BAUDRATE == baudrate) { // When baudrate too low it will fail on Sonoff Pow R2 and S31 serial interface initialization - if (global_state.wifi_down) { - delay(DRIVER_BOOT_DELAY); - } - } -} - /*********************************************************************************************\ * Sleep aware time scheduler functions borrowed from ESPEasy \*********************************************************************************************/ diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 4a7902303..87ff4e21b 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -584,3 +584,11 @@ void EspRestart(void) } */ +void WifiAddDelayWhenDisconnected(void) +{ + if (APP_BAUDRATE == baudrate) { // When baudrate too low it will fail on Sonoff Pow R2 and S31 serial interface initialization + if (global_state.wifi_down) { + delay(DRIVER_BOOT_DELAY); + } + } +} diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 12b9e2711..0ec3696d9 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -238,7 +238,7 @@ boolean XdrvCall(byte Function) boolean result = false; for (byte x = 0; x < xdrv_present; x++) { -// AppDelay(); +// WifiAddDelayWhenDisconnected(); result = xdrv_func_ptr[x](Function); if (result) break; } diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index fbe8bf218..d39995be9 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -278,7 +278,7 @@ boolean XsnsNextCall(byte Function, uint8_t &xsns_index) if (xsns_index == xsns_present) { xsns_index = 0; } } #endif -// AppDelay(); +// WifiAddDelayWhenDisconnected(); return xsns_func_ptr[xsns_index](Function); } @@ -298,7 +298,7 @@ boolean XsnsCall(byte Function) #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND uint32_t profile_start_millis = millis(); #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND -// AppDelay(); +// WifiAddDelayWhenDisconnected(); result = xsns_func_ptr[x](Function); #ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND From 52eeef95f0f4b4a8421871723322ebeb0ed93295 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 24 Nov 2018 17:43:18 +0100 Subject: [PATCH 0576/2222] Add CPU average load Add CPU average load to state message (#4431) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 15 +++++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 312c2855d..7e38a6aed 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -6,6 +6,7 @@ * Fix possible strncat buffer overflows * Fix MqttRetry values above 255 seconds (#4424) * Increase webui refresh time delay for Save Settings and local OTA Upload (#4423) + * Add CPU average load to state message (#4431) * * 6.3.0.11 20181120 * Add delays removed in 6.3.0.9 (#4233) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index f461b6de0..8bc6113cb 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2583,14 +2583,13 @@ void GpioInit(void) XdrvCall(FUNC_PRE_INIT); } - -void update_loop_load_avg(uint32_t loop_activity) + +void UpdateLoopLoadAvg(uint32_t loop_activity) { - uint32_t loops_per_second = 1000 / (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]; // We need to keep track of this many loops per second + uint32_t loops_per_second = 1000 / (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]; // We need to keep track of this many loops per second uint32_t this_cycle_ratio = 100 * loop_activity / (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]; - uint32_t new_load_avg = loop_load_avg-(loop_load_avg/loops_per_second); // Take away one loop average - new_load_avg = new_load_avg + this_cycle_ratio; - loop_load_avg = new_load_avg; + uint32_t new_load_avg = loop_load_avg - (loop_load_avg / loops_per_second); // Take away one loop average + loop_load_avg = new_load_avg + this_cycle_ratio;; } extern "C" { @@ -2799,8 +2798,8 @@ void loop(void) } } if (my_activity < (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]) { - update_loop_load_avg(my_activity); + UpdateLoopLoadAvg(my_activity); } else { - update_loop_load_avg((uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]); // Assume 100% loop cycle ratio + UpdateLoopLoadAvg((uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]); // Assume 100% loop cycle ratio } } From c22fcc2a3abe04d8fa395ca81bb7b7e5781b2902 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 24 Nov 2018 19:00:42 +0200 Subject: [PATCH 0577/2222] Update CPU average load function Remove unnecessary manipulations :) --- sonoff/sonoff.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 8bc6113cb..5045c7af5 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2588,8 +2588,7 @@ void UpdateLoopLoadAvg(uint32_t loop_activity) { uint32_t loops_per_second = 1000 / (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]; // We need to keep track of this many loops per second uint32_t this_cycle_ratio = 100 * loop_activity / (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]; - uint32_t new_load_avg = loop_load_avg - (loop_load_avg / loops_per_second); // Take away one loop average - loop_load_avg = new_load_avg + this_cycle_ratio;; + loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + this_cycle_ratio; // Take away one loop average away and add the new one } extern "C" { From 7c84f892fc6403433021f2570fc86a8e9ac557c7 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 25 Nov 2018 14:29:53 +0200 Subject: [PATCH 0578/2222] Add target loop delay to telemetry --- sonoff/sonoff.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 5045c7af5..deabbd1cf 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1577,7 +1577,8 @@ void MqttShowState(void) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VCC "\":%s"), mqtt_data, stemp1); #endif - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LoadAvg\":%u"), mqtt_data, loop_load_avg); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LoopSet\":%u"), mqtt_data, (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]); // Add current loop delay target to telemetry + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LoadAvg\":%u"), mqtt_data, loop_load_avg); // Add LoadAvg to telemetry data for (byte i = 0; i < devices_present; i++) { if (i == light_device -1) { From 05be1ee21cf5fcec5da2424c6c7290cafd82c907 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 25 Nov 2018 16:41:29 +0100 Subject: [PATCH 0579/2222] Fix exception due to divide by 0 Fix exception due to divide by 0 --- sonoff/sonoff.ino | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index deabbd1cf..9e32caf0b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2587,9 +2587,11 @@ void GpioInit(void) void UpdateLoopLoadAvg(uint32_t loop_activity) { - uint32_t loops_per_second = 1000 / (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]; // We need to keep track of this many loops per second - uint32_t this_cycle_ratio = 100 * loop_activity / (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]; - loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + this_cycle_ratio; // Take away one loop average away and add the new one + uint32_t loop_delay = Settings.param[P_LOOP_SLEEP_DELAY]; + if (!loop_delay) { loop_delay = 1; } // We cannot devide by 0 + uint32_t loops_per_second = 1000 / loop_delay; // We need to keep track of this many loops per second + uint32_t this_cycle_ratio = 100 * loop_activity / loop_delay; + loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + this_cycle_ratio; // Take away one loop average away and add the new one } extern "C" { From 0b14a95082a4c69e21b9a3fbe7e2a936e44c1a79 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 25 Nov 2018 17:52:07 +0200 Subject: [PATCH 0580/2222] Remove assumption of 100% to report correctly Remove the assumption of 100% loop duty cycle as we want an accurate loop load average and not a percentage as such - so if it overshoots the value stored for setoption36 this should be known by looking at the load average and not be distorted by reducing it to 100 basis points on the assumption that my_acitivity took as long as setoption36. --- sonoff/sonoff.ino | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 9e32caf0b..43f5d99ad 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2799,9 +2799,5 @@ void loop(void) delay(my_activity /2); // If wifi down and my_activity > setoption36 then force loop delay to 1/3 of my_activity period } } - if (my_activity < (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]) { - UpdateLoopLoadAvg(my_activity); - } else { - UpdateLoopLoadAvg((uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]); // Assume 100% loop cycle ratio - } + UpdateLoopLoadAvg(my_activity); } From 243ec16d80d5040cb647b74ace3cd98b9e19d6aa Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 25 Nov 2018 17:31:53 +0100 Subject: [PATCH 0581/2222] Fix another calcuation error Fix another calcuation error --- sonoff/sonoff.ino | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 43f5d99ad..c86c91d59 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2585,15 +2585,6 @@ void GpioInit(void) XdrvCall(FUNC_PRE_INIT); } -void UpdateLoopLoadAvg(uint32_t loop_activity) -{ - uint32_t loop_delay = Settings.param[P_LOOP_SLEEP_DELAY]; - if (!loop_delay) { loop_delay = 1; } // We cannot devide by 0 - uint32_t loops_per_second = 1000 / loop_delay; // We need to keep track of this many loops per second - uint32_t this_cycle_ratio = 100 * loop_activity / loop_delay; - loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + this_cycle_ratio; // Take away one loop average away and add the new one -} - extern "C" { extern struct rst_info resetInfo; } @@ -2799,5 +2790,11 @@ void loop(void) delay(my_activity /2); // If wifi down and my_activity > setoption36 then force loop delay to 1/3 of my_activity period } } - UpdateLoopLoadAvg(my_activity); + + if (!my_activity) { my_activity++; } // We cannot divide by 0 + uint32_t loop_delay = Settings.param[P_LOOP_SLEEP_DELAY]; + if (!loop_delay) { loop_delay++; } // We cannot divide by 0 + uint32_t loops_per_second = 1000 / loop_delay; // We need to keep track of this many loops per second + uint32_t this_cycle_ratio = 100 * my_activity / loop_delay; + loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + this_cycle_ratio; // Take away one loop average away and add the new one } From 3af44ab81f0e065cc07868c6756ee9cd97fb8fb6 Mon Sep 17 00:00:00 2001 From: Nick Galfas Date: Sun, 25 Nov 2018 20:19:20 +0200 Subject: [PATCH 0582/2222] Update el-GR.h Improved Greek translation including the latest versions text fields --- sonoff/language/el-GR.h | 443 ++++++++++++++++++++-------------------- 1 file changed, 221 insertions(+), 222 deletions(-) diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 9287d6961..4a8e84a7a 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -1,8 +1,7 @@ - /* el-GR.h - localization for Greek - Greece for Sonoff-Tasmota - Copyright (C) 2018 Kan3Nas + Copyright (C) 2018 Theo Arends (translated by Nick Galfas) 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 @@ -29,10 +28,10 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v5.12.0n + * Updated until v6.3.0 \*********************************************************************/ -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) #define LANGUAGE_LCID 1032 // HTML (ISO 639-1) Language Code @@ -52,218 +51,218 @@ #define D_DECIMAL_SEPARATOR "," // Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Ποιότητα Αέρα" +#define D_ADMIN "Διαχειριστής" +#define D_AIR_QUALITY "Ποιότητα αέρα" #define D_AP "AP" // Access Point -#define D_AS "as" +#define D_AS "ως" #define D_AUTO "ΑΥΤΟΜΑΤΟ" -#define D_BLINK "Αναβοσβήνει" -#define D_BLINKOFF "Δεν αναβοσβήνει" -#define D_BOOT_COUNT "Αριθμός εκκινήσεων" -#define D_BRIGHTLIGHT "Λαμπερό" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Καταμέτρηση εκκινήσεων" +#define D_BRIGHTLIGHT "Φωτεινό" #define D_BSSID "BSSId" -#define D_BUTTON "Κουμπί" +#define D_BUTTON "Πλήκτρο" #define D_BY "από" // Written by me #define D_BYTES "Bytes" #define D_CELSIUS "Κελσίου" -#define D_CHANNEL "Channel" +#define D_CHANNEL "Κανάλι" #define D_CO2 "Διοξείδιο του άνθρακα" #define D_CODE "κώδικας" // Button code -#define D_COLDLIGHT "Ψυχρός" +#define D_COLDLIGHT "Ψυχρό" #define D_COMMAND "Εντολή" #define D_CONNECTED "Συνδεδεμένο" -#define D_COUNT "Μέτρημα" +#define D_COUNT "Μέτρηση" #define D_COUNTER "Μετρητής" -#define D_CURRENT "Τάση ρεύματος" // As in Voltage and Current +#define D_CURRENT "Τάση" // As in Voltage and Current #define D_DATA "Δεδομένα" -#define D_DARKLIGHT "Σκούρο" +#define D_DARKLIGHT "Σκοτεινό" #define D_DEBUG "Debug" -#define D_DISABLED "Απενεργοποιημένο" -#define D_DISTANCE "Distance" +#define D_DISABLED "Ανενεργό" +#define D_DISTANCE "Απόσταση" #define D_DNS_SERVER "Διακομιστής DNS" -#define D_DONE "Εγινε" +#define D_DONE "Ολοκληρώθηκε" #define D_DST_TIME "DST" #define D_ECO2 "eCO2" -#define D_EMULATION "Emulation" +#define D_EMULATION "Εξομoίωση" #define D_ENABLED "Ενεργό" -#define D_ERASE "Σβήσιμο" +#define D_ERASE "Διαγραφή" #define D_ERROR "Σφάλμα" #define D_FAHRENHEIT "Φαρενάιτ" -#define D_FAILED "Αποτυχία" -#define D_FALLBACK "Εφεδρικό" -#define D_FALLBACK_TOPIC "Εφεδρικό θέμα" -#define D_FALSE "Λάθος" +#define D_FAILED "Απέτυχε" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback Topic" +#define D_FALSE "Ψευδές" #define D_FILE "Αρχείο" -#define D_FREE_MEMORY "Ελεύθερη Μνήμη" -#define D_FREQUENCY "Frequency" -#define D_GAS "Γκάζι" +#define D_FREE_MEMORY "Ελεύθερη μνήμη" +#define D_FREQUENCY "Συχνότητα" +#define D_GAS "Αέριο" #define D_GATEWAY "Πύλη" #define D_GROUP "Ομάδα" #define D_HOST "Host" #define D_HOSTNAME "Hostname" #define D_HUMIDITY "Υγρασία" -#define D_ILLUMINANCE "Illuminance" -#define D_IMMEDIATE "Φωτεινότητα" // Button immediate +#define D_ILLUMINANCE "Φωτεινότητα" +#define D_IMMEDIATE "άμεσο" // Button immediate #define D_INDEX "Κατάλογος" #define D_INFO "Πληροφορίες" -#define D_INFRARED "Infrared" -#define D_INITIALIZED "Αρχικό" -#define D_IP_ADDRESS "IP Address" -#define D_LIGHT "Light" +#define D_INFRARED "Υπέρυθρο" +#define D_INITIALIZED "Αρχικοποιήθηκε" +#define D_IP_ADDRESS "Διεύθυνση IP" +#define D_LIGHT "Φως" #define D_LWT "LWT" -#define D_MODULE "Module" +#define D_MODULE "Μονάδα" #define D_MQTT "MQTT" -#define D_MULTI_PRESS "πολλαπλή πίεση" -#define D_NOISE "θόρυβος" +#define D_MULTI_PRESS "ανίχνευση για πολλαπλά πατήματα" +#define D_NOISE "Θόρυβος" #define D_NONE "Κανένα" -#define D_OFF "Κλειστό" +#define D_OFF "Off" #define D_OFFLINE "Offline" #define D_OK "Ok" -#define D_ON "Ανοιχτό" +#define D_ON "On" #define D_ONLINE "Online" -#define D_PASSWORD "ΚωδικόςPassword" -#define D_PORT "Πόρτα" -#define D_POWER_FACTOR "Παράγοντας ισχύος" -#define D_POWERUSAGE "Ισχύης" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_PASSWORD "Κωδικός" +#define D_PORT "Θύρα" +#define D_POWER_FACTOR "Συντελεστής Ισχύος" +#define D_POWERUSAGE "Ισχύς" +#define D_POWERUSAGE_ACTIVE "Ενεργός ισχύς" +#define D_POWERUSAGE_APPARENT "Φαινόμενη ισχύς" +#define D_POWERUSAGE_REACTIVE "Άεργη ισχύς" #define D_PRESSURE "Πίεση" -#define D_PRESSUREATSEALEVEL "Πίεση στην επιφάνεια της Θάλασσας" -#define D_PROGRAM_FLASH_SIZE "Μέγεθος Προγράμματος Flash" -#define D_PROGRAM_SIZE "Μέγεθος Προγράμματος" +#define D_PRESSUREATSEALEVEL "Πίεση στo επίπεδο θάλασσας" +#define D_PROGRAM_FLASH_SIZE "Μέγεθος προγράμματος στη Flash" +#define D_PROGRAM_SIZE "Μέγεθος προγράμματος" #define D_PROJECT "Έργο" -#define D_RECEIVED "Λήψη" +#define D_RECEIVED "Ελήφθη" #define D_RESTART "Επανεκκίνηση" -#define D_RESTARTING "Επανεκκίνηση" -#define D_RESTART_REASON "Λόγος Επανεκκίνησης" +#define D_RESTARTING "Επανεκκινεί" +#define D_RESTART_REASON "Αιτία επανεκκίνησης" #define D_RESTORE "επαναφορά" -#define D_RETAINED "διατηρούνται" +#define D_RETAINED "διακράτηση" #define D_RULE "Κανόνας" #define D_SAVE "Αποθήκευση" -#define D_SENSOR "Σένσορας" +#define D_SENSOR "Αισθητήρας" #define D_SSID "SSId" -#define D_START "Έναρξη" +#define D_START "Εκκίνηση" #define D_STD_TIME "STD" -#define D_STOP "Στοπ" +#define D_STOP "Τερματισμός" #define D_SUBNET_MASK "Μάσκα υποδικτύου" #define D_SUBSCRIBE_TO "Εγγραφή στο" -#define D_SUCCESSFUL "Επιτυχής" +#define D_SUCCESSFUL "Επιτυχές" #define D_SUNRISE "Σούρουπο" #define D_SUNSET "Ηλιοβασίλεμα" #define D_TEMPERATURE "Θερμοκρασία" -#define D_TO "στο" +#define D_TO "έως" #define D_TOGGLE "Εναλλαγή" -#define D_TOPIC "Θέμα" +#define D_TOPIC "Topic" #define D_TRANSMIT "Μετάδοση" -#define D_TRUE "Σωστό" +#define D_TRUE "Αληθές" #define D_TVOC "TVOC" #define D_UPGRADE "αναβάθμιση" #define D_UPLOAD "Ανέβασμα" -#define D_UPTIME "Uptime" +#define D_UPTIME "Χρόνος λειτουργίας" #define D_USER "Χρήστης" #define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX "Δείκτης UV" +#define D_UV_INDEX_1 "Χαμηλό" +#define D_UV_INDEX_2 "Μέτριο" +#define D_UV_INDEX_3 "Υψηλό" +#define D_UV_INDEX_4 "Κίνδυνος" +#define D_UV_INDEX_5 "Έγκαυμα L1/2" +#define D_UV_INDEX_6 "Έγκαυμα L3" #define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "Επίπεδο UV" -#define D_UV_POWER "UV Power" +#define D_UV_POWER "Ένταση UV" #define D_VERSION "Έκδοση" #define D_VOLTAGE "Τάση" -#define D_WEIGHT "Weight" -#define D_WARMLIGHT "Ζεστό" -#define D_WEB_SERVER "Web διακομιστής" +#define D_WEIGHT "Βάρος" +#define D_WARMLIGHT "Θερμό" +#define D_WEB_SERVER "Διακομιστής Web" // sonoff.ino #define D_WARNING_MINIMAL_VERSION "ΠΡΟΕΙΔΟΠΟΙΗΣΗ Αυτή η έκδοση δεν αποθηκεύει τις ρυθμίσεις" #define D_LEVEL_10 "επίπεδο 1-0" #define D_LEVEL_01 "επίπεδο 0-1" -#define D_SERIAL_LOGGING_DISABLED "Η σειριακής καταγραφή απενεργοποιήθηκε" -#define D_SYSLOG_LOGGING_REENABLED "Η καταγραφή Syslog είναι ενεργοποιημένη" +#define D_SERIAL_LOGGING_DISABLED "Η καταγραφή σειριακής θύρας είναι απενεργοποιημένη" +#define D_SYSLOG_LOGGING_REENABLED "Η καταγραφή Syslog επαναενεργοποιήθηκε" -#define D_SET_BAUDRATE_TO "Ρύθμιση Baudrate σε" -#define D_RECEIVED_TOPIC "Λήψη θεμάτων" +#define D_SET_BAUDRATE_TO "Ορισμός Baudrate σε" +#define D_RECEIVED_TOPIC "Received Topic" #define D_DATA_SIZE "Μέγεθος δεδομένων" #define D_ANALOG_INPUT "Αναλογικό" // support.ino #define D_OSWATCH "osWatch" #define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" -#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes" -#define D_FAILED_TO_START "failed to start" +#define D_WPS_FAILED_WITH_STATUS "Το WPSconfig ΑΠΕΤΥΧΕ με status" +#define D_ACTIVE_FOR_3_MINUTES "ενεργό για 3 λεπτά" +#define D_FAILED_TO_START "απέτυχε να εκκινήσει" #define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "Connecting to AP" -#define D_IN_MODE "in mode" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connect failed as no IP address received" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Connect failed as AP cannot be reached" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Connect failed with AP incorrect password" -#define D_CONNECT_FAILED_AP_TIMEOUT "Connect failed with AP timeout" -#define D_ATTEMPTING_CONNECTION "Attempting connection..." -#define D_CHECKING_CONNECTION "Checking connection..." -#define D_QUERY_DONE "Query done. MQTT services found" -#define D_MQTT_SERVICE_FOUND "MQTT service found on" -#define D_FOUND_AT "found at" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host not found" +#define D_CONNECTING_TO_AP "Συνδέεται στο AP" +#define D_IN_MODE "σε mode" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Αποτυχία σύνδεσης, δεν απονεμήθηκε διεύθυνση IP" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Αποτυχία σύνδεσης, δεν ανταποκρίνεται το AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Αποτυχία σύνδεσης, λάθος κωδικός για το AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Αποτυχία σύνδεσης, λήξη ορίου απόκρισης από το AP" +#define D_ATTEMPTING_CONNECTION "Προσπάθεια για σύνδεση..." +#define D_CHECKING_CONNECTION "Έλεγχος σύνδεσης..." +#define D_QUERY_DONE "Ολοκλήρωση ερωτήματος. Βρέθηκε υπηρεσία MQTT" +#define D_MQTT_SERVICE_FOUND "Βρέθηκε υπηρεσία MQTT στο" +#define D_FOUND_AT "βρέθηκε στο" +#define D_SYSLOG_HOST_NOT_FOUND "Δε βρέθηκε Syslog Host" // settings.ino -#define D_SAVED_TO_FLASH_AT "Εγινε flash στην θέση" -#define D_LOADED_FROM_FLASH_AT "Φορτώθηκε από την flash στην θέση" +#define D_SAVED_TO_FLASH_AT "Αποθηκεύτηκε από τη Flash στο" +#define D_LOADED_FROM_FLASH_AT "Φορτώθηκε από τη Flash στο" #define D_USE_DEFAULTS "Χρήση προεπιλογών" -#define D_ERASED_SECTOR "Διαγραμμένος τομέας" +#define D_ERASED_SECTOR "Διαγραφή τομέα" -// xdrv_02_webserver.ino +// webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - παρακαλώ αναβαθμήστε" -#define D_WEBSERVER_ACTIVE_ON "Web διακομιστής ενεργός" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - παρακαλώ αναβαθμίστε" +#define D_WEBSERVER_ACTIVE_ON "Ενεργός διακομιστής Web στο" #define D_WITH_IP_ADDRESS "με διεύθυνση IP" -#define D_WEBSERVER_STOPPED "Web διακομιστής σταμάτησε" -#define D_FILE_NOT_FOUND "Το αρχείο δεν βρέθηκε" -#define D_REDIRECTED "Ανακατεύθυνση σε captive portal" +#define D_WEBSERVER_STOPPED "Ο διακομιστής Web σταμάτησε" +#define D_FILE_NOT_FOUND "Δε βρέθηκε το αρχείο" +#define D_REDIRECTED "Ανακατεύθυνση στο captive portal" #define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" #define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" -#define D_TRYING_TO_CONNECT "Προσπάθεια σύνδεσης της συσκευής στο δίκτυο" +#define D_TRYING_TO_CONNECT "Προσπάθεια σύνδεσης της συσκευής σε ασύρματο δίκτυο" #define D_RESTART_IN "Επανεκκίνηση σε" #define D_SECONDS "δευτερόλεπτα" -#define D_DEVICE_WILL_RESTART "Η συσκευή θα ξεκινήσει ξανά σε λίγα δευτερόλεπτα" +#define D_DEVICE_WILL_RESTART "Η συσκευή θα επανεκκινήσει σε λίγα δευτερόλεπτα" #define D_BUTTON_TOGGLE "Εναλλαγή" -#define D_CONFIGURATION "Ρύθμιση" +#define D_CONFIGURATION "Ρυθμίσεις" #define D_INFORMATION "Πληροφορίες" #define D_FIRMWARE_UPGRADE "Αναβάθμιση Firmware" #define D_CONSOLE "Κονσόλα" -#define D_CONFIRM_RESTART "Επιβεβαίωση Επανεκκίνησης" +#define D_CONFIRM_RESTART "Επιβεβαίωση επανεκκίνησης" -#define D_CONFIGURE_MODULE "Ρύθμιση Module" -#define D_CONFIGURE_WIFI "Ρύθμιση WiFi" -#define D_CONFIGURE_MQTT "Ρύθμιση MQTT" -#define D_CONFIGURE_DOMOTICZ "Ρύθμιση Domoticz" -#define D_CONFIGURE_LOGGING "Ρύθμιση καταγραφής" -#define D_CONFIGURE_OTHER "Άλλες Ρυθμίσεις" -#define D_CONFIRM_RESET_CONFIGURATION "Confirm Reset Configuration" -#define D_RESET_CONFIGURATION "Επαναφορά Ρυθμίσεων" -#define D_BACKUP_CONFIGURATION "Αντίγραφα Ασφαλείας Ρυθμίσεων" -#define D_RESTORE_CONFIGURATION "Επαναφορά Ρυθμίσεων" -#define D_MAIN_MENU "Κεντρικό Μενού" +#define D_CONFIGURE_MODULE "Ρυθμίσεις μονάδας" +#define D_CONFIGURE_WIFI "Ρυθμίσεις WiFi" +#define D_CONFIGURE_MQTT "Ρυθμίσεις MQTT" +#define D_CONFIGURE_DOMOTICZ "Ρυθμίσεις Domoticz" +#define D_CONFIGURE_LOGGING "Ρυθμίσεις καταγραφής" +#define D_CONFIGURE_OTHER "Άλλες ρυθμίσεις" +#define D_CONFIRM_RESET_CONFIGURATION "Επιβεβαίωση αρχικοποίησης στις προεπιλεγμένες ρυθμίσεις" +#define D_RESET_CONFIGURATION "Αρχικοποίηση-reset ρυθμίσεων" +#define D_BACKUP_CONFIGURATION "Αποθήκευση ρυθμίσεων" +#define D_RESTORE_CONFIGURATION "Επαναφορά ρυθμίσεων" +#define D_MAIN_MENU "Κεντρικό μενού" -#define D_MODULE_PARAMETERS "Παράμετροι Module" -#define D_MODULE_TYPE "Είδος Module" +#define D_MODULE_PARAMETERS "Παράμετροι μονάδας" +#define D_MODULE_TYPE "Τύπος μονάδας" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial In" #define D_SERIAL_OUT "Serial Out" #define D_WIFI_PARAMETERS "Παράμετροι Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Σάρωση για δίκτυα wifi" -#define D_SCAN_DONE "Ολοκλήρωση σάρωσης" -#define D_NO_NETWORKS_FOUND "Δεν βρέθηκαν δίκτυα" -#define D_REFRESH_TO_SCAN_AGAIN "Ανανέωση για επανάληψη σάρωσης" -#define D_DUPLICATE_ACCESSPOINT "Duplicate AccessPoint" -#define D_SKIPPING_LOW_QUALITY "Παράλειψη λόγω χαμηλού σήματος" +#define D_SCAN_FOR_WIFI_NETWORKS "Σάρωση για δίκτυα Wifi" +#define D_SCAN_DONE "Η σάρωση ολοκληρώθηκε" +#define D_NO_NETWORKS_FOUND "Δε βρέθηκαν δίκτυα" +#define D_REFRESH_TO_SCAN_AGAIN "Πατήστε ανανέωση για μια νέα σάρωση" +#define D_DUPLICATE_ACCESSPOINT "Διπλότυπο AccessPoint" +#define D_SKIPPING_LOW_QUALITY "Παράκαμψη λόγω χαμηλής ποιότητας" #define D_RSSI "RSSI" #define D_WEP "WEP" #define D_WPA_PSK "WPA PSK" @@ -273,41 +272,41 @@ #define D_AP2_SSID "AP2 SSId" #define D_AP2_PASSWORD "AP2 Κωδικός" -#define D_MQTT_PARAMETERS "MQTT Παράμετροι" +#define D_MQTT_PARAMETERS "Παράμετροι MQTT" #define D_CLIENT "Πελάτης" #define D_FULL_TOPIC "Full Topic" #define D_LOGGING_PARAMETERS "Παράμετροι καταγραφής" -#define D_SERIAL_LOG_LEVEL "Επίπεδο καταγραφής Serial" +#define D_SERIAL_LOG_LEVEL "Επίπεδο καταγραφής Σειριακής" #define D_WEB_LOG_LEVEL "Επίπεδο καταγραφής Web" #define D_SYS_LOG_LEVEL "Επίπεδο καταγραφής Syslog" -#define D_MORE_DEBUG "Επιπλέον debug" -#define D_SYSLOG_HOST "Υπολογιστής Syslog" -#define D_SYSLOG_PORT "Πόρτα Syslog" -#define D_TELEMETRY_PERIOD "Χρόνος τηλεμετρίας" +#define D_MORE_DEBUG "More debug" +#define D_SYSLOG_HOST "Εξυπηρετητής Syslog" +#define D_SYSLOG_PORT "Θύρα Syslog" +#define D_TELEMETRY_PERIOD "Περίοδος τηλεμετρίας" -#define D_OTHER_PARAMETERS "Άλλες Παράμετροι" -#define D_WEB_ADMIN_PASSWORD "Web Admin Κωδικός" -#define D_MQTT_ENABLE "MQTT Ενεργό" -#define D_FRIENDLY_NAME "Φιλικό Όνομα" +#define D_OTHER_PARAMETERS "Άλλες παράμετροι" +#define D_WEB_ADMIN_PASSWORD "Κωδικός διαχειριστή" +#define D_MQTT_ENABLE "Ενεργοποίηση MQTT" +#define D_FRIENDLY_NAME "Φιλική ονομασία" #define D_BELKIN_WEMO "Belkin WeMo" #define D_HUE_BRIDGE "Hue Bridge" #define D_SINGLE_DEVICE "μονή συσκευή" -#define D_MULTI_DEVICE "πολλαπλή συσκευή" +#define D_MULTI_DEVICE "πολλαπλές συσκευές" -#define D_SAVE_CONFIGURATION "Αποθήκευση Ρυθμίσεων" +#define D_SAVE_CONFIGURATION "Αποθήκευση ρυθμίσεων" #define D_CONFIGURATION_SAVED "Οι ρυθμίσεις αποθηκεύτηκαν" #define D_CONFIGURATION_RESET "Επαναφορά ρυθμίσεων" -#define D_PROGRAM_VERSION "Εκδοση προγράμματος" -#define D_BUILD_DATE_AND_TIME "Ημερομηνία και Ώρα Build" -#define D_CORE_AND_SDK_VERSION "Core/SDK Version" -#define D_FLASH_WRITE_COUNT "Μετρητής εγγραφών Flash" +#define D_PROGRAM_VERSION "Έκδοση προγράμματος" +#define D_BUILD_DATE_AND_TIME "Ημερομηνία έκδοσης" +#define D_CORE_AND_SDK_VERSION "Έκδοση Core/SDK" +#define D_FLASH_WRITE_COUNT "Καταμέτρηση εγγραφών στη Flash" #define D_MAC_ADDRESS "MAC Address" -#define D_MQTT_HOST "MQTT Host" -#define D_MQTT_PORT "MQTT Port" -#define D_MQTT_CLIENT "MQTT Client" -#define D_MQTT_USER "MQTT User" +#define D_MQTT_HOST "MQTT Διακομιστής" +#define D_MQTT_PORT "MQTT Θύρα" +#define D_MQTT_CLIENT "MQTT Πελάτης" +#define D_MQTT_USER "MQTT Χρήστης" #define D_MQTT_TOPIC "MQTT Topic" #define D_MQTT_GROUP_TOPIC "MQTT Group Topic" #define D_MQTT_FULL_TOPIC "MQTT Full Topic" @@ -316,47 +315,47 @@ #define D_ESP_CHIP_ID "ESP Chip Id" #define D_FLASH_CHIP_ID "Flash Chip Id" #define D_FLASH_CHIP_SIZE "Μέγεθος Flash" -#define D_FREE_PROGRAM_SPACE "Ελεύθερος Χώρος Προγράμματος" +#define D_FREE_PROGRAM_SPACE "Ελεύθερος χώρος προγράμματος" -#define D_UPGRADE_BY_WEBSERVER "αναβάθμιση από τον διακομιστή web" -#define D_OTA_URL "OTA Url" +#define D_UPGRADE_BY_WEBSERVER "Αναβάθμιση μέσω web server" +#define D_OTA_URL "OTA URL" #define D_START_UPGRADE "Εκκίνηση αναβάθμισης" -#define D_UPGRADE_BY_FILE_UPLOAD "Αναβάθμιση με ανέβασμα αρχείου" -#define D_UPLOAD_STARTED "Το ανέβασμα ξεκίνησε" +#define D_UPGRADE_BY_FILE_UPLOAD "Αναβάθμιση μέσω μεταφόρτωσης αρχείου" +#define D_UPLOAD_STARTED "Η μεταφόρτωση ξεκίνησε" #define D_UPGRADE_STARTED "Η αναβάθμιση ξεκίνησε" -#define D_UPLOAD_DONE "Το ανέβασμα ολοκληρώθηκε" +#define D_UPLOAD_DONE "Η μεταφόρτωση ολοκληρώθηκε" #define D_UPLOAD_ERR_1 "Δεν έχει επιλεγεί αρχείο" -#define D_UPLOAD_ERR_2 "Δεν υπάρχει αρκετός χώρος" -#define D_UPLOAD_ERR_3 "Magic byte δεν είναι 0xE9" -#define D_UPLOAD_ERR_4 "Το μέγεθος του προγράμματος flash είναι μεγαλύτερο από το πραγματικό μέγεθος του flash" +#define D_UPLOAD_ERR_2 "Δεν υπάρχει επαρκής χώρος" +#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" +#define D_UPLOAD_ERR_4 "Το μέγεθος προγράμματος είναι μεγαλύτερο από την πραγματική μνήμη Flash" #define D_UPLOAD_ERR_5 "Upload buffer miscompare" -#define D_UPLOAD_ERR_6 "Το ανέβασμα απέτυχε. Επιλέξτε επίπεδο καταγραφής 3" -#define D_UPLOAD_ERR_7 "Το ανεβάσμα διακόπηκε" +#define D_UPLOAD_ERR_6 "Η μεταφόρτωση απέτυχε. Επιλέξτε επίπεδο καταγραφής 3" +#define D_UPLOAD_ERR_7 "Η μεταφόρτωση ματαιώθηκε" #define D_UPLOAD_ERR_8 "Μη έγκυρο αρχείο" -#define D_UPLOAD_ERR_9 "Το αρχείο είναι πολύ μεγάλο" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_9 "Πολύ μεγάλο αρχείο" +#define D_UPLOAD_ERR_10 "Αποτυχία αρχικοποίησης RF chip" +#define D_UPLOAD_ERR_11 "Αποτυχία σβησίματος στο RF chip" +#define D_UPLOAD_ERR_12 "Αποτυχία εγγραφής στο RF chip" #define D_UPLOAD_ERR_13 "Failed to decode RF firmware" -#define D_UPLOAD_ERROR_CODE "Κωδικός λάθους ανεβάσματος" +#define D_UPLOAD_ERROR_CODE "Κωδικός λάθους στη μεταφόρτωση" #define D_ENTER_COMMAND "Εισαγωγή εντολής" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Ενεργοποιήστε το weblog 2 αν περιμένετε απάντηση" -#define D_NEED_USER_AND_PASSWORD "Χρειάζεστε user=<όνομα χρήστη>&password=<κωδικό χρήστη>" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Ενεργοποιήστε το weblog 2 εαν περιμένετε απόκριση" +#define D_NEED_USER_AND_PASSWORD "Χρειάζεται user=&password=" // xdrv_01_mqtt.ino -#define D_FINGERPRINT "Επαλήθευση TLS fingerprint..." -#define D_TLS_CONNECT_FAILED_TO "Αποτυχία TLS σύνδεσης" -#define D_RETRY_IN "Επανάληψη σε" -#define D_VERIFIED "Επαλήθευση με Fingerprint" -#define D_INSECURE "Μη ασφαλής σύνδεση λόγο ακατάλληλου Fingerprint" +#define D_FINGERPRINT "Επιβεβαίωση αποτυπώματος TLS..." +#define D_TLS_CONNECT_FAILED_TO "Αποτυχία σύνδεσης TLS στο" +#define D_RETRY_IN "Νέα προσπάθεια σε" +#define D_VERIFIED "Επιβεβαιώθηκε με χρήση αποτυπώματος TLS" +#define D_INSECURE "Επισφαλής σύνδεση λόγω άκυρου αποτυπώματος TLS" #define D_CONNECT_FAILED_TO "Αποτυχία σύνδεσης στο" // xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast απενεργοποιημένο" -#define D_MULTICAST_REJOINED "Multicast επανασύνδεση" +#define D_MULTICAST_DISABLED "Απενεργοποιημένο Multicast" +#define D_MULTICAST_REJOINED "Επανασύνδεση Multicast" #define D_MULTICAST_JOIN_FAILED "Αποτυχία σύνδεσης Multicast" -#define D_FAILED_TO_SEND_RESPONSE "Αποτυχία αποστολής απάντησης" +#define D_FAILED_TO_SEND_RESPONSE "Αποτυχία αποστολής απόκρισης" #define D_WEMO "WeMo" #define D_WEMO_BASIC_EVENT "WeMo βασικό event" @@ -367,13 +366,13 @@ #define D_HUE "Hue" #define D_HUE_BRIDGE_SETUP "Hue ρυθμίσεις" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API δεν έχει υλοποιηθεί" +#define D_HUE_API_NOT_IMPLEMENTED "Δε βρέθηκε εφαρμογή Hue API" #define D_HUE_API "Hue API" #define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3πλο πακέτο απάντησεης στάλθηκε" +#define D_3_RESPONSE_PACKETS_SENT "Στάλθηκαν 3 πακέτα απόκρισης" // xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz παράμετροι" +#define D_DOMOTICZ_PARAMETERS "Ρυθμίσεις Domoticz" #define D_DOMOTICZ_IDX "Idx" #define D_DOMOTICZ_KEY_IDX "Key idx" #define D_DOMOTICZ_SWITCH_IDX "Switch idx" @@ -386,27 +385,27 @@ #define D_DOMOTICZ_COUNT "Count/PM1" #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "Ποιότητα Αέρα" -#define D_DOMOTICZ_UPDATE_TIMER "Ενημέρωση" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" +#define D_DOMOTICZ_UPDATE_TIMER "Update timer" // xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Ρυθμίσεις Χρόνου" -#define D_TIMER_PARAMETERS "Χρονικοί παράμετροι" -#define D_TIMER_ENABLE "Ενεργοποιημένο Χρονικοί" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "Ωρα" +#define D_CONFIGURE_TIMER "Ρυθμίσεις Χρονικών" +#define D_TIMER_PARAMETERS "Παράμετροι χρονικών" +#define D_TIMER_ENABLE "Ενεργοποίηση χρονικών" +#define D_TIMER_ARM "Οπλισμένο" +#define D_TIMER_TIME "Ώρα" #define D_TIMER_DAYS "Μέρες" #define D_TIMER_REPEAT "Επανάληψη" -#define D_TIMER_OUTPUT "Αποτέλεσμα" -#define D_TIMER_ACTION "Εντολή" +#define D_TIMER_OUTPUT "Έξοδος" +#define D_TIMER_ACTION "Λειτουργία" // xdrv_10_knx.ino #define D_CONFIGURE_KNX "Ρυθμίσεις KNX" -#define D_KNX_PARAMETERS "KNX Παράμετροι" +#define D_KNX_PARAMETERS "Παράμετροι KNX" #define D_KNX_GENERAL_CONFIG "Γενικά" #define D_KNX_PHYSICAL_ADDRESS "Διεύθυνση Μνήμης" #define D_KNX_PHYSICAL_ADDRESS_NOTE "( Πρέπει να είναι μοναδική στο KNX δίκτυο )" -#define D_KNX_ENABLE "Ενεργοποιημένο KNX" +#define D_KNX_ENABLE "Ενεργοποίηση KNX" #define D_KNX_GROUP_ADDRESS_TO_WRITE "Αποστολή δεδομένων σε Ομάδα Διευθύνσεων" #define D_ADD "Προσθήκη" #define D_DELETE "Διαγραφή" @@ -416,32 +415,32 @@ #define D_RECEIVED_FROM "Στάλθηκε από" #define D_KNX_COMMAND_WRITE "Εγγραφή" #define D_KNX_COMMAND_READ "Ανάγνωση" -#define D_KNX_COMMAND_OTHER "Αλλο" +#define D_KNX_COMMAND_OTHER "Άλλο" #define D_SENT_TO "αποστολή σε" #define D_KNX_WARNING "Η Ομάδα Διευθύνσεων ( 0 / 0 / 0 ) είναι δεσμευμένη και δεν μπορεί να χρησιμοποιηθεί." -#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_ENHANCEMENT "Βελτίωση επικοινωνίας" #define D_KNX_TX_SLOT "KNX TX" #define D_KNX_RX_SLOT "KNX RX" // xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energy Σήμερα" -#define D_ENERGY_YESTERDAY "Energy Χτες" -#define D_ENERGY_TOTAL "Energy Συνολικά" +#define D_ENERGY_TODAY "Ενέργεια σήμερα" +#define D_ENERGY_YESTERDAY "Ενέργεια χθες" +#define D_ENERGY_TOTAL "Ενέργεια συνολικά" // xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Απασχολημένος Σένσορας" -#define D_SENSOR_CRC_ERROR "CRC λάθος σένσορα" -#define D_SENSORS_FOUND "Βρέθηκε σένσορας" +#define D_SENSOR_BUSY "Ο αισθητήρας είναι απασχολημένος" +#define D_SENSOR_CRC_ERROR "Σφάλμα CRC αισθητήρα" +#define D_SENSORS_FOUND "Βρέθηκαν αισθητήρες" // xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Timeout περιμένετε για" -#define D_START_SIGNAL_LOW "εκκίνηση με χαμηλό σήμα" -#define D_START_SIGNAL_HIGH "εκκίνηση με υψηλό σήμα" +#define D_TIMEOUT_WAITING_FOR "Αναμονή Timeout για" +#define D_START_SIGNAL_LOW "χαμηλό αρχικό σήμα" +#define D_START_SIGNAL_HIGH "υψηλό αρχικό σήμα" #define D_PULSE "παλμός" #define D_CHECKSUM_FAILURE "Αποτυχία Checksum" // xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Ο σένσορας δεν έλαβε την εντολή ACK" +#define D_SENSOR_DID_NOT_ACK_COMMAND "Ο αισθητήρας δεν έστειλε εντολή ACK" #define D_SHT1X_FOUND "Βρέθηκε SHT1X" // xsns_18_pms5003.ino @@ -458,30 +457,30 @@ #define D_GZ_AXIS "Gyro Z-Axis" // xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" +#define D_HX_CAL_REMOVE "Απομακρύνετε το βαρίδιο" +#define D_HX_CAL_REFERENCE "Τοποθετήστε το βαρίδιο αναφοράς" +#define D_HX_CAL_DONE "Βαθμονομήθηκε" +#define D_HX_CAL_FAIL "Αποτυχία βαθμονόμησης" +#define D_RESET_HX711 "Αρχικοποίηση ζυγαριάς" +#define D_CONFIGURE_HX711 "Ρύθμιση ζυγαριάς" +#define D_HX711_PARAMETERS "Παράμετροι ζυγαριάς" +#define D_ITEM_WEIGHT "Βάρος αντικειμένου" +#define D_REFERENCE_WEIGHT "Βάρος αναφοράς" +#define D_CALIBRATE "Βαθμονόμησε" +#define D_CALIBRATION "Βαθμονόμηση" //xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" +#define D_TX20_WIND_DIRECTION "Κατεύθυνση ανέμου" +#define D_TX20_WIND_SPEED "Ταχύτητα ανέμου" +#define D_TX20_WIND_SPEED_AVG "Μέση ταχύτητα ανέμου" +#define D_TX20_WIND_SPEED_MAX "Μέγιστη ταχύτητα ανέμου" +#define D_TX20_NORTH "Β" +#define D_TX20_EAST "Α" +#define D_TX20_SOUTH "Ν" +#define D_TX20_WEST "Δ" // sonoff_template.h -#define D_SENSOR_NONE "Κανένας" +#define D_SENSOR_NONE "Κανένα" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" @@ -491,11 +490,11 @@ #define D_SENSOR_WS2812 "WS2812" #define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Διακόπτης" // Suffix "1" -#define D_SENSOR_BUTTON "Κουμπί" // Suffix "1" -#define D_SENSOR_RELAY "Ρελέ" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_SWITCH "Διακόπτης" // Suffix "1" +#define D_SENSOR_BUTTON "Κουμπί" // Suffix "1" +#define D_SENSOR_RELAY "Ρελέ" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_PWM "PWM" // Suffix "1" #define D_SENSOR_COUNTER "Μετρητής" // Suffix "1" #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" @@ -589,4 +588,4 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi -#endif // _LANGUAGE_EN_GB_H_ +#endif // _LANGUAGE_EL_GR_H_ From eda60b61244cbc9e068bd22be3278f1ca0dc84cb Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 25 Nov 2018 21:27:19 +0100 Subject: [PATCH 0583/2222] Support sending tele/STATUS as state/RESULT --- sonoff/settings.h | 2 +- sonoff/sonoff.ino | 6 +++++- sonoff/xdrv_12_home_assistant.ino | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 553f9eba3..39642e4a9 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -72,7 +72,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t use_wifi_scan : 1; // bit 6 (v6.3.0.10) uint32_t use_wifi_rescan : 1; // bit 7 (v6.3.0.10) uint32_t receive_raw : 1; // bit 8 (v6.3.0.11) - uint32_t spare09 : 1; + uint32_t hass_tele_as_result : 1; // bit 9 uint32_t spare10 : 1; uint32_t spare11 : 1; uint32_t spare12 : 1; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c86c91d59..f0439f0a2 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1681,7 +1681,11 @@ void PerformEverySecond(void) mqtt_data[0] = '\0'; MqttShowState(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); + if (Settings.flag3.hass_tele_as_result) { + MqttPublishPrefixTopic_P(STAT, S_RSLT_RESULT, MQTT_TELE_RETAIN); + } else { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); + } mqtt_data[0] = '\0'; if (MqttShowSensor()) { diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 4be4377d7..20e03fd99 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -424,8 +424,9 @@ void HAssDiscovery(uint8_t mode) { // Configure Tasmota for default Home Assistant parameters to keep discovery message as short as possible if (Settings.flag.hass_discovery) { - Settings.flag.mqtt_response = 0; // Response always as RESULT and not as uppercase command - Settings.flag.decimal_text = 1; // Respond with decimal color values + Settings.flag.mqtt_response = 0; // Response always as RESULT and not as uppercase command + Settings.flag.decimal_text = 1; // Respond with decimal color values + Settings.flag3.hass_tele_as_result = 1; // send tele/STATE message as stat/RESULT // Settings.light_scheme = 0; // To just control color it needs to be Scheme 0 if (!string_ends_with(Settings.mqtt_fulltopic, "%prefix%/")) strncpy_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"), sizeof(Settings.mqtt_fulltopic)); From 5ce19fc3f77370cc49d36d0d444a25f3e31adea7 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sun, 25 Nov 2018 22:43:28 +0100 Subject: [PATCH 0584/2222] PS_16_DZ: don't use String class --- sonoff/xdrv_19_ps16dz_dimmer.ino | 143 ++++++++++++++++--------------- 1 file changed, 75 insertions(+), 68 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index ce8ce7267..d1cb69221 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -28,14 +28,14 @@ TasmotaSerial *PS16DZSerial = nullptr; boolean ps16dz_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction -int8_t ps16dz_wifi_state = -2; // Keep MCU wifi-status in sync with WifiState() boolean ps16dz_power = false; uint8_t ps16dz_bright = 0; uint64_t ps16dz_seq = 0; -char ps16dz_buffer[PS16DZ_BUFFER_SIZE]; // Serial receive buffer -int ps16dz_byte_counter = 0; // Index in serial receive buffer +char ps16dz_tx_buffer[PS16DZ_BUFFER_SIZE]; // Serial transmit buffer +char ps16dz_rx_buffer[PS16DZ_BUFFER_SIZE]; // Serial receive buffer +int ps16dz_byte_counter = 0; /*********************************************************************************************\ * Internal Functions @@ -50,7 +50,7 @@ size_t print_uint64_t(uint64_t number) if (number == 0) { - n += snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "%s%c"), ps16dz_buffer, (char)'0'); + n += snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s%c"), ps16dz_tx_buffer, (char)'0'); return n; } @@ -62,7 +62,7 @@ size_t print_uint64_t(uint64_t number) } for (; i > 0; i--) - n += snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "%s%c"), ps16dz_buffer, (char) ('0' + buf[i - 1])); + n += snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s%c"), ps16dz_tx_buffer, (char) ('0' + buf[i - 1])); return n; } @@ -76,13 +76,13 @@ boolean PS16DZSetPower(void) if (source != SRC_SWITCH && PS16DZSerial) { // ignore to prevent loop from pushing state from faceplate interaction - snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); + snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); print_uint64_t(ps16dz_seq++); - snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "%s\",\"switch\":\"%s\""), ps16dz_buffer, rpower?"on":"off"); - snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_buffer ); + snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, rpower?"on":"off"); + snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); - PS16DZSerial->print(ps16dz_buffer); + PS16DZSerial->print(ps16dz_tx_buffer); PS16DZSerial->write(0x1B); status = true; @@ -97,13 +97,13 @@ void PS16DZSerialDuty(uint8_t duty) duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself } - snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); + snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); print_uint64_t(ps16dz_seq++); - snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "%s\",\"bright\":\"%d\""), ps16dz_buffer, round(duty * (100. / 255.))); - snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_buffer ); + snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"bright\":\"%d\""), ps16dz_tx_buffer, round(duty * (100. / 255.))); + snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); - PS16DZSerial->print(ps16dz_buffer); + PS16DZSerial->print(ps16dz_tx_buffer); PS16DZSerial->write(0x1B); } else { @@ -145,66 +145,73 @@ void PS16DZInit(void) void PS16DZSerialInput(void) { char scmnd[20]; - String ps16dz_command; while (PS16DZSerial->available()) { yield(); - ps16dz_command = PS16DZSerial->readStringUntil(0x1B); - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: command received: %s"), ps16dz_command.c_str()); - AddLog(LOG_LEVEL_DEBUG); - if(ps16dz_command.substring(3,6) == "UPDATE" || ps16dz_command.substring(3,6) == "RESULT"){ - char *end_str; - char *string = strdup(ps16dz_command.substring(10).c_str()); - char* token = strtok_r(string, ",", &end_str); - while (token != NULL) { - char* end_token; - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: token = %s"), token); - AddLog(LOG_LEVEL_DEBUG); - char* token2 = strtok_r(token, ":", &end_token); - char* token3 = strtok_r(NULL, ":", &end_token); - if(!strncmp(token2, "\"switch\"", 8)){ - ps16dz_power = !strncmp(token3, "\"on\"", 4)?true:false; - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: power received: %s"), token3); - AddLog(LOG_LEVEL_DEBUG); - if((power || Settings.light_dimmer > 0) && (power !=ps16dz_power)) { - ExecuteCommandPower(1, ps16dz_power, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction - } - } - else if(!strncmp(token2, "\"bright\"", 8)){ - ps16dz_bright = atoi(token3); - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: brightness received: %d"), ps16dz_bright); - AddLog(LOG_LEVEL_DEBUG); - if(power && ps16dz_bright > 0) { - - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), ps16dz_bright ); - - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: Send CMND_DIMMER_STR=%s"), scmnd ); - AddLog(LOG_LEVEL_DEBUG); - - ps16dz_ignore_dim = true; - ExecuteCommand(scmnd, SRC_SWITCH); - } - - } - else if(!strncmp(token2, "\"sequence\"", 10)){ - ps16dz_seq = strtoull(token3, NULL, 10); - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: sequence received: %0ld"), ps16dz_seq/1000000L, ps16dz_seq%1000000L); - AddLog(LOG_LEVEL_DEBUG); - } - - token = strtok_r(NULL, ",", &end_str); - } + //ps16dz_command = PS16DZSerial->readStringUntil(0x1B); + byte serial_in_byte = PS16DZSerial->read(); + if (serial_in_byte != 0x1B){ + ps16dz_rx_buffer[ps16dz_byte_counter++] = serial_in_byte; } - else if(ps16dz_command.substring(3,7) == "SETTING"){ - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: Reset")); + else { + ps16dz_rx_buffer[ps16dz_byte_counter++] = 0x00; + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: command received: %s"), ps16dz_rx_buffer); AddLog(LOG_LEVEL_DEBUG); - PS16DZResetWifi(); + if(!strncmp(ps16dz_rx_buffer+3, "UPDATE", 6) || !strncmp(ps16dz_rx_buffer+3, "RESULT", 6)) { + char *end_str; + char *string = ps16dz_rx_buffer+10; + char* token = strtok_r(string, ",", &end_str); + while (token != NULL) { + char* end_token; + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: token = %s"), token); + AddLog(LOG_LEVEL_DEBUG); + char* token2 = strtok_r(token, ":", &end_token); + char* token3 = strtok_r(NULL, ":", &end_token); + if(!strncmp(token2, "\"switch\"", 8)){ + ps16dz_power = !strncmp(token3, "\"on\"", 4)?true:false; + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: power received: %s"), token3); + AddLog(LOG_LEVEL_DEBUG); + if((power || Settings.light_dimmer > 0) && (power !=ps16dz_power)) { + ExecuteCommandPower(1, ps16dz_power, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction + } + } + else if(!strncmp(token2, "\"bright\"", 8)){ + ps16dz_bright = atoi(token3); + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: brightness received: %d"), ps16dz_bright); + AddLog(LOG_LEVEL_DEBUG); + if(power && ps16dz_bright > 0) { + + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), ps16dz_bright ); + + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: Send CMND_DIMMER_STR=%s"), scmnd ); + AddLog(LOG_LEVEL_DEBUG); + + ps16dz_ignore_dim = true; + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + else if(!strncmp(token2, "\"sequence\"", 10)){ + ps16dz_seq = strtoull(token3, NULL, 10); + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: sequence received: %0ld"), ps16dz_seq/1000000L, ps16dz_seq%1000000L); + AddLog(LOG_LEVEL_DEBUG); + } + token = strtok_r(NULL, ",", &end_str); + } + } + else if(!strncmp(ps16dz_rx_buffer+3, "SETTING", 7)) { + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: Reset")); + AddLog(LOG_LEVEL_DEBUG); + PS16DZResetWifi(); + } + memset(ps16dz_rx_buffer, 0, sizeof(ps16dz_rx_buffer)); + ps16dz_byte_counter = 0; + + snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+SEND=ok")); + snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_tx_buffer ); + AddLog(LOG_LEVEL_DEBUG); + + PS16DZSerial->print(ps16dz_tx_buffer); + PS16DZSerial->write(0x1B); } - snprintf_P(ps16dz_buffer, sizeof(ps16dz_buffer), PSTR( "AT+SEND=ok")); - snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_buffer ); - AddLog(LOG_LEVEL_DEBUG); - - PS16DZSerial->print(ps16dz_buffer); - PS16DZSerial->write(0x1B); } } From e024ca3bebcbaa94e441962be31aa6ded16bf983 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sun, 25 Nov 2018 23:09:58 +0100 Subject: [PATCH 0585/2222] PS_16_DZ: start sequence with 1529000000000 --- sonoff/xdrv_19_ps16dz_dimmer.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index d1cb69221..030f59f04 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -31,7 +31,7 @@ boolean ps16dz_ignore_dim = false; // Flag to skip serial send to pre boolean ps16dz_power = false; uint8_t ps16dz_bright = 0; -uint64_t ps16dz_seq = 0; +uint64_t ps16dz_seq = 1529000000000; char ps16dz_tx_buffer[PS16DZ_BUFFER_SIZE]; // Serial transmit buffer char ps16dz_rx_buffer[PS16DZ_BUFFER_SIZE]; // Serial receive buffer From 0f2ea2800eb75627b347480247846fd82819636b Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sun, 25 Nov 2018 23:39:44 +0100 Subject: [PATCH 0586/2222] PS_16_DZ: start must be 'A' --- sonoff/xdrv_19_ps16dz_dimmer.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 030f59f04..271af64d3 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -150,6 +150,7 @@ void PS16DZSerialInput(void) //ps16dz_command = PS16DZSerial->readStringUntil(0x1B); byte serial_in_byte = PS16DZSerial->read(); if (serial_in_byte != 0x1B){ + if (ps16dz_byte_counter || (!ps16dz_byte_counter && serial_in_byte = 'A')); ps16dz_rx_buffer[ps16dz_byte_counter++] = serial_in_byte; } else { From 977822f131d0def8be63a94df7661ef012bdc86c Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sun, 25 Nov 2018 23:41:11 +0100 Subject: [PATCH 0587/2222] PS_16_DZ: start must be 'A' --- sonoff/xdrv_19_ps16dz_dimmer.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 271af64d3..78e2f7cfb 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -150,7 +150,7 @@ void PS16DZSerialInput(void) //ps16dz_command = PS16DZSerial->readStringUntil(0x1B); byte serial_in_byte = PS16DZSerial->read(); if (serial_in_byte != 0x1B){ - if (ps16dz_byte_counter || (!ps16dz_byte_counter && serial_in_byte = 'A')); + if (ps16dz_byte_counter || (!ps16dz_byte_counter && serial_in_byte == 'A')); ps16dz_rx_buffer[ps16dz_byte_counter++] = serial_in_byte; } else { From b7a18f7bcc4b2ea8e98f0476ba7a67cea5a06d9c Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Mon, 26 Nov 2018 00:31:45 +0100 Subject: [PATCH 0588/2222] PS_16_DZ: tryfix dimming --- sonoff/xdrv_04_light.ino | 4 ++-- sonoff/xdrv_19_ps16dz_dimmer.ino | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 455adc4d0..b4f10a148 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -832,7 +832,7 @@ void LightAnimate(void) LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); } #ifdef USE_TUYA_DIMMER - if (light_type == LT_SERIAL1) { + if (light_type == LT_SERIAL1 && Settings.module == TUYA_DIMMER ) { LightSerialDuty(cur_col[0]); } #endif // USE_TUYA_DIMMER @@ -842,7 +842,7 @@ void LightAnimate(void) } #endif // USE_ARMTRONIX_DIMMERS #ifdef USE_PS_16_DZ - if (light_type == LT_SERIAL1) { + if (light_type == LT_SERIAL1 && Settings.module == PS_16_DZ) { PS16DZSerialDuty(cur_col[0]); } #endif // USE_PS_16_DZ diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 78e2f7cfb..f3f219d60 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -31,7 +31,8 @@ boolean ps16dz_ignore_dim = false; // Flag to skip serial send to pre boolean ps16dz_power = false; uint8_t ps16dz_bright = 0; -uint64_t ps16dz_seq = 1529000000000; +//uint64_t ps16dz_seq = 1529000000000; +uint64_t ps16dz_seq = 0; char ps16dz_tx_buffer[PS16DZ_BUFFER_SIZE]; // Serial transmit buffer char ps16dz_rx_buffer[PS16DZ_BUFFER_SIZE]; // Serial receive buffer From 985db96f91a6656f39655c68011078009904e1b5 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Mon, 26 Nov 2018 00:47:00 +0100 Subject: [PATCH 0589/2222] PS_16_DZ: print correct sequence --- sonoff/xdrv_19_ps16dz_dimmer.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index f3f219d60..887f89a1e 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -193,7 +193,7 @@ void PS16DZSerialInput(void) } else if(!strncmp(token2, "\"sequence\"", 10)){ ps16dz_seq = strtoull(token3, NULL, 10); - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: sequence received: %0ld"), ps16dz_seq/1000000L, ps16dz_seq%1000000L); + snprintf_P(log_data, sizeof(log_data), PSTR("PSD: sequence received: %s"), token3); AddLog(LOG_LEVEL_DEBUG); } token = strtok_r(NULL, ",", &end_str); From 283f023f29caf209b0204a865660c7037000ed08 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Mon, 26 Nov 2018 01:19:09 +0100 Subject: [PATCH 0590/2222] PS_16_DZ: move in nicelist --- sonoff/sonoff_template.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 98e329bdf..da7d99656 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -482,8 +482,9 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { NEO_COOLCAM, // Socket Relay Devices OBI, ESP_SWITCH, // Switch Devices - TUYA_DIMMER, // Dimmer Devices + TUYA_DIMMER, // Dimmer Devices ARMTRONIX_DIMMERS, + PS_16_DZ, H801, // Light Devices MAGICHOME, ARILUX_LC01, @@ -495,8 +496,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { AILIGHT, // Light Bulbs PHILIPS, WITTY, // Development Devices - WEMOS, - PS_16_DZ + WEMOS }; // Default module settings From 1dc7a5847c45aa2238b1ed6e97e7121964bef0ae Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Mon, 26 Nov 2018 02:22:18 +0100 Subject: [PATCH 0591/2222] PS_16_DZ: correctly parse sequence --- sonoff/xdrv_19_ps16dz_dimmer.ino | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 887f89a1e..b165d66a1 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -31,8 +31,7 @@ boolean ps16dz_ignore_dim = false; // Flag to skip serial send to pre boolean ps16dz_power = false; uint8_t ps16dz_bright = 0; -//uint64_t ps16dz_seq = 1529000000000; -uint64_t ps16dz_seq = 0; +uint64_t ps16dz_seq = 1530000000000; char ps16dz_tx_buffer[PS16DZ_BUFFER_SIZE]; // Serial transmit buffer char ps16dz_rx_buffer[PS16DZ_BUFFER_SIZE]; // Serial receive buffer @@ -192,7 +191,7 @@ void PS16DZSerialInput(void) } } else if(!strncmp(token2, "\"sequence\"", 10)){ - ps16dz_seq = strtoull(token3, NULL, 10); + ps16dz_seq = strtoull(token3+1, NULL, 10); snprintf_P(log_data, sizeof(log_data), PSTR("PSD: sequence received: %s"), token3); AddLog(LOG_LEVEL_DEBUG); } From 7203d6ad03e2aa57b9b82dfb014365b48ee91604 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Mon, 26 Nov 2018 03:20:15 +0100 Subject: [PATCH 0592/2222] PS_16_DZ: wait for acknoledgement before sending more commands --- sonoff/xdrv_19_ps16dz_dimmer.ino | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index b165d66a1..862283d25 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -32,6 +32,7 @@ boolean ps16dz_ignore_dim = false; // Flag to skip serial send to pre boolean ps16dz_power = false; uint8_t ps16dz_bright = 0; uint64_t ps16dz_seq = 1530000000000; +boolean ps16dz_synced = true; char ps16dz_tx_buffer[PS16DZ_BUFFER_SIZE]; // Serial transmit buffer char ps16dz_rx_buffer[PS16DZ_BUFFER_SIZE]; // Serial receive buffer @@ -74,8 +75,9 @@ boolean PS16DZSetPower(void) uint8_t rpower = XdrvMailbox.index; int16_t source = XdrvMailbox.payload; - if (source != SRC_SWITCH && PS16DZSerial) { // ignore to prevent loop from pushing state from faceplate interaction + if (source != SRC_SWITCH && PS16DZSerial && ps16dz_synced) { // ignore to prevent loop from pushing state from faceplate interaction + ps16dz_synced = false; snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); print_uint64_t(ps16dz_seq++); snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, rpower?"on":"off"); @@ -92,11 +94,12 @@ boolean PS16DZSetPower(void) void PS16DZSerialDuty(uint8_t duty) { - if (duty > 0 && !ps16dz_ignore_dim && PS16DZSerial) { + if (duty > 0 && !ps16dz_ignore_dim && PS16DZSerial && ps16dz_synced) { if (duty < 25) { duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself } + ps16dz_synced = false; snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); print_uint64_t(ps16dz_seq++); snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"bright\":\"%d\""), ps16dz_tx_buffer, round(duty * (100. / 255.))); @@ -191,9 +194,13 @@ void PS16DZSerialInput(void) } } else if(!strncmp(token2, "\"sequence\"", 10)){ - ps16dz_seq = strtoull(token3+1, NULL, 10); + uint64_t ps16dz_seq_tmp = strtoull(token3+1, NULL, 10); snprintf_P(log_data, sizeof(log_data), PSTR("PSD: sequence received: %s"), token3); AddLog(LOG_LEVEL_DEBUG); + if(ps16dz_seq_tmp >= ps16dz_seq){ + ps16dz_synced = true; + ps16dz_seq = ps16dz_seq_tmp; + } } token = strtok_r(NULL, ",", &end_str); } From acdbd39124ee28053e5a02acfb8ac6fc5b1587b6 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 26 Nov 2018 11:37:15 +0200 Subject: [PATCH 0593/2222] Fix math in LoadAvg Fix the math in LoadAvg calculation. To keep average we take away one Nth of loops and add one Nth of current cycle ration to the average. Now the math makes more sense... maximum load average on setoption36 0/1 = 999 (as it should be) --- sonoff/sonoff.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c86c91d59..5aac837c7 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2796,5 +2796,5 @@ void loop(void) if (!loop_delay) { loop_delay++; } // We cannot divide by 0 uint32_t loops_per_second = 1000 / loop_delay; // We need to keep track of this many loops per second uint32_t this_cycle_ratio = 100 * my_activity / loop_delay; - loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + this_cycle_ratio; // Take away one loop average away and add the new one + loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + (this_cycle_ratio / loops_per_second); // Take away one loop average away and add the new one } From b4e2fe0439f2739b146202f5d5bffdd4b09834d5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 26 Nov 2018 13:01:42 +0100 Subject: [PATCH 0594/2222] 6.3.0.13 Add command SetOption59 6.3.0.13 20181126 * Add command SetOption59 0/1 to change state topic from tele/STATE to stat/RESULT (#4450) --- sonoff/_changelog.ino | 5 ++++- sonoff/settings.h | 2 +- sonoff/sonoff_version.h | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 7e38a6aed..f548a76da 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.3.0.12 20181122 +/* 6.3.0.13 20181126 + * Add command SetOption59 0/1 to change state topic from tele/STATE to stat/RESULT (#4450) + * + * 6.3.0.12 20181122 * Remove delays introduced in 6.3.0.11 (#4233) * Add additional start-up delay during initial wifi connection * Add support for I2C MGC3130 Electric Field Effect sensor by Christian Baars (#3774, #4404) diff --git a/sonoff/settings.h b/sonoff/settings.h index 39642e4a9..9eb95a64c 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -72,7 +72,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t use_wifi_scan : 1; // bit 6 (v6.3.0.10) uint32_t use_wifi_rescan : 1; // bit 7 (v6.3.0.10) uint32_t receive_raw : 1; // bit 8 (v6.3.0.11) - uint32_t hass_tele_as_result : 1; // bit 9 + uint32_t hass_tele_as_result : 1; // bit 9 (v6.3.0.13) uint32_t spare10 : 1; uint32_t spare11 : 1; uint32_t spare12 : 1; diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 2648520b4..cd5a77a08 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0603000C +#define VERSION 0x0603000D #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" From a6124c376ec601d31bcacc8f314ff139dcf39925 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Mon, 26 Nov 2018 13:27:30 +0100 Subject: [PATCH 0595/2222] Revert "PS_16_DZ: wait for acknoledgement before sending more commands" This reverts commit 7203d6ad03e2aa57b9b82dfb014365b48ee91604. --- sonoff/xdrv_19_ps16dz_dimmer.ino | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 862283d25..b165d66a1 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -32,7 +32,6 @@ boolean ps16dz_ignore_dim = false; // Flag to skip serial send to pre boolean ps16dz_power = false; uint8_t ps16dz_bright = 0; uint64_t ps16dz_seq = 1530000000000; -boolean ps16dz_synced = true; char ps16dz_tx_buffer[PS16DZ_BUFFER_SIZE]; // Serial transmit buffer char ps16dz_rx_buffer[PS16DZ_BUFFER_SIZE]; // Serial receive buffer @@ -75,9 +74,8 @@ boolean PS16DZSetPower(void) uint8_t rpower = XdrvMailbox.index; int16_t source = XdrvMailbox.payload; - if (source != SRC_SWITCH && PS16DZSerial && ps16dz_synced) { // ignore to prevent loop from pushing state from faceplate interaction + if (source != SRC_SWITCH && PS16DZSerial) { // ignore to prevent loop from pushing state from faceplate interaction - ps16dz_synced = false; snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); print_uint64_t(ps16dz_seq++); snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, rpower?"on":"off"); @@ -94,12 +92,11 @@ boolean PS16DZSetPower(void) void PS16DZSerialDuty(uint8_t duty) { - if (duty > 0 && !ps16dz_ignore_dim && PS16DZSerial && ps16dz_synced) { + if (duty > 0 && !ps16dz_ignore_dim && PS16DZSerial) { if (duty < 25) { duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself } - ps16dz_synced = false; snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); print_uint64_t(ps16dz_seq++); snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"bright\":\"%d\""), ps16dz_tx_buffer, round(duty * (100. / 255.))); @@ -194,13 +191,9 @@ void PS16DZSerialInput(void) } } else if(!strncmp(token2, "\"sequence\"", 10)){ - uint64_t ps16dz_seq_tmp = strtoull(token3+1, NULL, 10); + ps16dz_seq = strtoull(token3+1, NULL, 10); snprintf_P(log_data, sizeof(log_data), PSTR("PSD: sequence received: %s"), token3); AddLog(LOG_LEVEL_DEBUG); - if(ps16dz_seq_tmp >= ps16dz_seq){ - ps16dz_synced = true; - ps16dz_seq = ps16dz_seq_tmp; - } } token = strtok_r(NULL, ",", &end_str); } From 41ddab2cbe6220900f3c1a21cad2f9fdcaeb67c1 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Mon, 26 Nov 2018 13:29:00 +0100 Subject: [PATCH 0596/2222] PS_16_DZ: flush serial after sending command --- sonoff/xdrv_19_ps16dz_dimmer.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index b165d66a1..a2d77c992 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -84,6 +84,7 @@ boolean PS16DZSetPower(void) PS16DZSerial->print(ps16dz_tx_buffer); PS16DZSerial->write(0x1B); + PS16DZSerial->flush(); status = true; } @@ -105,6 +106,7 @@ void PS16DZSerialDuty(uint8_t duty) PS16DZSerial->print(ps16dz_tx_buffer); PS16DZSerial->write(0x1B); + PS16DZSerial->flush(); } else { ps16dz_ignore_dim = false; // reset flag @@ -212,6 +214,7 @@ void PS16DZSerialInput(void) PS16DZSerial->print(ps16dz_tx_buffer); PS16DZSerial->write(0x1B); + PS16DZSerial->flush(); } } } From 3650ab5fd3de3dc62a3d5ee145d22844c8f404b7 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Mon, 26 Nov 2018 13:49:21 +0100 Subject: [PATCH 0597/2222] PS_16_DZ: use unix-timestamp as sequence --- sonoff/xdrv_19_ps16dz_dimmer.ino | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index a2d77c992..fcfe3eb1e 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -67,6 +67,11 @@ size_t print_uint64_t(uint64_t number) return n; } +uint64_t getTimestamp(void) +{ + return (((uint64_t)LocalTime()) * 1000) + (millis()%1000); +} + boolean PS16DZSetPower(void) { boolean status = false; @@ -77,7 +82,8 @@ boolean PS16DZSetPower(void) if (source != SRC_SWITCH && PS16DZSerial) { // ignore to prevent loop from pushing state from faceplate interaction snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); - print_uint64_t(ps16dz_seq++); + ps16dz_seq = getTimestamp(); + print_uint64_t(ps16dz_seq); snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, rpower?"on":"off"); snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); @@ -99,7 +105,8 @@ void PS16DZSerialDuty(uint8_t duty) } snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); - print_uint64_t(ps16dz_seq++); + ps16dz_seq = getTimestamp(); + print_uint64_t(ps16dz_seq); snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"bright\":\"%d\""), ps16dz_tx_buffer, round(duty * (100. / 255.))); snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); @@ -193,7 +200,7 @@ void PS16DZSerialInput(void) } } else if(!strncmp(token2, "\"sequence\"", 10)){ - ps16dz_seq = strtoull(token3+1, NULL, 10); + //ps16dz_seq = strtoull(token3+1, NULL, 10); snprintf_P(log_data, sizeof(log_data), PSTR("PSD: sequence received: %s"), token3); AddLog(LOG_LEVEL_DEBUG); } From 87d7609b970a7056ad6d8daaf4e8575357c25fd2 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Mon, 26 Nov 2018 13:53:33 +0100 Subject: [PATCH 0598/2222] PS_16_DZ: init sequence as 0 --- sonoff/xdrv_19_ps16dz_dimmer.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index fcfe3eb1e..a4a966e0b 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -31,7 +31,7 @@ boolean ps16dz_ignore_dim = false; // Flag to skip serial send to pre boolean ps16dz_power = false; uint8_t ps16dz_bright = 0; -uint64_t ps16dz_seq = 1530000000000; +uint64_t ps16dz_seq = 0; char ps16dz_tx_buffer[PS16DZ_BUFFER_SIZE]; // Serial transmit buffer char ps16dz_rx_buffer[PS16DZ_BUFFER_SIZE]; // Serial receive buffer From 6f6e4382ec2a51dfd053855d8c60435166f07e6b Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Mon, 26 Nov 2018 15:27:51 +0100 Subject: [PATCH 0599/2222] PS_16_DZ: change logprefix to PSZ --- sonoff/xdrv_19_ps16dz_dimmer.ino | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index a4a966e0b..e7e547e1c 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -85,7 +85,7 @@ boolean PS16DZSetPower(void) ps16dz_seq = getTimestamp(); print_uint64_t(ps16dz_seq); snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, rpower?"on":"off"); - snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_tx_buffer ); + snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); PS16DZSerial->print(ps16dz_tx_buffer); @@ -108,7 +108,7 @@ void PS16DZSerialDuty(uint8_t duty) ps16dz_seq = getTimestamp(); print_uint64_t(ps16dz_seq); snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"bright\":\"%d\""), ps16dz_tx_buffer, round(duty * (100. / 255.))); - snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_tx_buffer ); + snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); PS16DZSerial->print(ps16dz_tx_buffer); @@ -118,7 +118,7 @@ void PS16DZSerialDuty(uint8_t duty) } else { ps16dz_ignore_dim = false; // reset flag - snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send Dim Level skipped due to 0 or already set. Value=%d"), duty); + snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send Dim Level skipped due to 0 or already set. Value=%d"), duty); AddLog(LOG_LEVEL_DEBUG); } @@ -164,7 +164,7 @@ void PS16DZSerialInput(void) } else { ps16dz_rx_buffer[ps16dz_byte_counter++] = 0x00; - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: command received: %s"), ps16dz_rx_buffer); + snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: command received: %s"), ps16dz_rx_buffer); AddLog(LOG_LEVEL_DEBUG); if(!strncmp(ps16dz_rx_buffer+3, "UPDATE", 6) || !strncmp(ps16dz_rx_buffer+3, "RESULT", 6)) { char *end_str; @@ -172,13 +172,13 @@ void PS16DZSerialInput(void) char* token = strtok_r(string, ",", &end_str); while (token != NULL) { char* end_token; - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: token = %s"), token); + snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: token = %s"), token); AddLog(LOG_LEVEL_DEBUG); char* token2 = strtok_r(token, ":", &end_token); char* token3 = strtok_r(NULL, ":", &end_token); if(!strncmp(token2, "\"switch\"", 8)){ ps16dz_power = !strncmp(token3, "\"on\"", 4)?true:false; - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: power received: %s"), token3); + snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: power received: %s"), token3); AddLog(LOG_LEVEL_DEBUG); if((power || Settings.light_dimmer > 0) && (power !=ps16dz_power)) { ExecuteCommandPower(1, ps16dz_power, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction @@ -186,13 +186,13 @@ void PS16DZSerialInput(void) } else if(!strncmp(token2, "\"bright\"", 8)){ ps16dz_bright = atoi(token3); - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: brightness received: %d"), ps16dz_bright); + snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: brightness received: %d"), ps16dz_bright); AddLog(LOG_LEVEL_DEBUG); if(power && ps16dz_bright > 0) { snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), ps16dz_bright ); - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: Send CMND_DIMMER_STR=%s"), scmnd ); + snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: Send CMND_DIMMER_STR=%s"), scmnd ); AddLog(LOG_LEVEL_DEBUG); ps16dz_ignore_dim = true; @@ -201,14 +201,14 @@ void PS16DZSerialInput(void) } else if(!strncmp(token2, "\"sequence\"", 10)){ //ps16dz_seq = strtoull(token3+1, NULL, 10); - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: sequence received: %s"), token3); + snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: sequence received: %s"), token3); AddLog(LOG_LEVEL_DEBUG); } token = strtok_r(NULL, ",", &end_str); } } else if(!strncmp(ps16dz_rx_buffer+3, "SETTING", 7)) { - snprintf_P(log_data, sizeof(log_data), PSTR("PSD: Reset")); + snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: Reset")); AddLog(LOG_LEVEL_DEBUG); PS16DZResetWifi(); } @@ -216,7 +216,7 @@ void PS16DZSerialInput(void) ps16dz_byte_counter = 0; snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+SEND=ok")); - snprintf_P(log_data, sizeof(log_data), PSTR( "PSD: Send serial command: %s"), ps16dz_tx_buffer ); + snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); PS16DZSerial->print(ps16dz_tx_buffer); From c3f07f0bd25a55affcb84bf53f51ad6066945626 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 26 Nov 2018 17:00:18 +0100 Subject: [PATCH 0600/2222] Fix WifiManager functionality Fix WifiManager functionality on initial installation (#4433) --- sonoff/_changelog.ino | 3 ++- sonoff/xdrv_01_webserver.ino | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index f548a76da..2351beb8c 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.3.0.13 20181126 * Add command SetOption59 0/1 to change state topic from tele/STATE to stat/RESULT (#4450) - * + * Fix WifiManager functionality on initial installation (#4433) + * * 6.3.0.12 20181122 * Remove delays introduced in 6.3.0.11 (#4233) * Add additional start-up delay during initial wifi connection diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index a6c2a2a1c..cd0204a48 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -25,12 +25,14 @@ * Based on source by AlexT (https://github.com/tzapu) \*********************************************************************************************/ -#define XDRV_01 1 +#define XDRV_01 1 -#define HTTP_REFRESH_TIME 2345 // milliseconds +#define HTTP_REFRESH_TIME 2345 // milliseconds +#define HTTP_RESTART_RECONNECT_TIME 9000 // milliseconds +#define HTTP_OTA_RESTART_RECONNECT_TIME 20000 // milliseconds -#include // WifiManager, Webserver -#include // WifiManager +#include +#include #ifdef USE_RF_FLASH uint8_t *efm8bb1_update = NULL; @@ -95,12 +97,12 @@ const char HTTP_SCRIPT_WIFI[] PROGMEM = "}"; const char HTTP_SCRIPT_RELOAD[] PROGMEM = - "setTimeout(function(){location.href='.';},9000);" + "setTimeout(function(){location.href='.';}," STR(HTTP_RESTART_RECONNECT_TIME) ");" ""; // Local OTA upgrade requires more time to complete cp: before web ui should be reloaded const char HTTP_SCRIPT_RELOAD_OTA[] PROGMEM = - "setTimeout(function(){location.href='.';},20000);" + "setTimeout(function(){location.href='.';}," STR(HTTP_OTA_RESTART_RECONNECT_TIME) ");" ""; const char HTTP_SCRIPT_CONSOL[] PROGMEM = @@ -1417,7 +1419,7 @@ void HandleUpgradeFirmwareStart(void) page += F("
          " D_UPGRADE_STARTED " ...
          "); page += FPSTR(HTTP_MSG_RSTRT); page += FPSTR(HTTP_BTN_MAIN); -// page.replace(F(""), FPSTR(HTTP_SCRIPT_RELOAD)); + page.replace(F(""), FPSTR(HTTP_SCRIPT_RELOAD_OTA)); ShowPage(page); snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_UPGRADE " 1")); @@ -2063,12 +2065,10 @@ boolean Xdrv01(byte function) switch (function) { case FUNC_LOOP: - if (!global_state.wifi_down) { - PollDnsWebserver(); + PollDnsWebserver(); #ifdef USE_EMULATION - if (Settings.flag2.emulation) PollUdp(); + if (Settings.flag2.emulation) PollUdp(); #endif // USE_EMULATION - } break; case FUNC_COMMAND: result = WebCommand(); From 7931b3433a49b4c618db05e7537f4e57092b478b Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Tue, 27 Nov 2018 01:07:57 +0100 Subject: [PATCH 0601/2222] PS_16_DZ: bright as int --- sonoff/xdrv_19_ps16dz_dimmer.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index e7e547e1c..b62d35eca 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -107,7 +107,7 @@ void PS16DZSerialDuty(uint8_t duty) snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); ps16dz_seq = getTimestamp(); print_uint64_t(ps16dz_seq); - snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"bright\":\"%d\""), ps16dz_tx_buffer, round(duty * (100. / 255.))); + snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"bright\":%d"), ps16dz_tx_buffer, round(duty * (100. / 255.))); snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); From 0b988c561bdf0c539c46d0bb17ed95fb8436fe8e Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 26 Nov 2018 21:14:12 -0300 Subject: [PATCH 0602/2222] Added command CalcRes --- sonoff/my_user_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 91b764688..ae5707c40 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -174,6 +174,7 @@ #define SWITCH_DEBOUNCE_TIME 50 // [SwitchDebounce] Number of mSeconds switch press debounce time #define SWITCH_MODE TOGGLE // [SwitchMode] TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE (the wall switch state) #define WS2812_LEDS 30 // [Pixels] Number of WS2812 LEDs to start with (max is 512) +#define CALC_RESOLUTION 3 // [CalcRes] Maximum number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE #define TEMP_CONVERSION 0 // [SetOption8] Return temperature in (0 = Celsius or 1 = Fahrenheit) #define PRESSURE_CONVERSION 0 // [SetOption24] Return pressure in (0 = hPa or 1 = mmHg) From c51e657ed98c4110094e6a99b7c6e9ed94c63e8c Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 26 Nov 2018 21:16:09 -0300 Subject: [PATCH 0603/2222] Added command CalcRes --- sonoff/settings.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 9eb95a64c..033071668 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -107,9 +107,7 @@ typedef union { uint32_t spare03 : 1; uint32_t spare04 : 1; uint32_t spare05 : 1; - uint32_t spare06 : 1; - uint32_t spare07 : 1; - uint32_t spare08 : 1; + uint32_t calc_resolution : 3; uint32_t weight_resolution : 2; uint32_t frequency_resolution : 2; uint32_t axis_resolution : 2; From 5d11a4f444d06517acf92eb3caadfcbeefc14a65 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 26 Nov 2018 21:16:47 -0300 Subject: [PATCH 0604/2222] Added command CalcRes --- sonoff/settings.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 2a346feb7..6d3263f41 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -576,6 +576,7 @@ void SettingsDefaultSet2(void) // Settings.rule_enabled = 0; // Settings.rule_once = 0; // for (byte i = 1; i < MAX_RULE_SETS; i++) { Settings.rules[i][0] = '\0'; } + Settings.flag2.calc_resolution = CALC_RESOLUTION; // Home Assistant Settings.flag.hass_discovery = HOME_ASSISTANT_DISCOVERY_ENABLE; From f7a8f39f8975ba5a34cda18b917f7ab6fd4330c6 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 26 Nov 2018 21:22:44 -0300 Subject: [PATCH 0605/2222] Added command CalcRes --- sonoff/xdrv_10_rules.ino | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index f13d5afd2..160c4e305 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -74,11 +74,12 @@ #define D_CMND_SUB "Sub" #define D_CMND_MULT "Mult" #define D_CMND_SCALE "Scale" +#define D_CMND_CALC_RESOLUTION "CalcRes" #define D_JSON_INITIATED "Initiated" -enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM, CMND_ADD, CMND_SUB, CMND_MULT, CMND_SCALE }; -const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM "|" D_CMND_ADD "|" D_CMND_SUB "|" D_CMND_MULT "|" D_CMND_SCALE ; +enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM, CMND_ADD, CMND_SUB, CMND_MULT, CMND_SCALE, CMND_CALC_RESOLUTION }; +const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM "|" D_CMND_ADD "|" D_CMND_SUB "|" D_CMND_MULT "|" D_CMND_SCALE "|" D_CMND_CALC_RESOLUTION ; String rules_event_value; unsigned long rules_timer[MAX_RULE_TIMERS] = { 0 }; @@ -593,24 +594,30 @@ boolean RulesCommand(void) } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]); } + else if (CMND_CALC_RESOLUTION == command_code) { + if ((payload >= 0) && (payload <= 7)) { + Settings.flag2.calc_resolution = payload; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.calc_resolution); + } else if ((CMND_ADD == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { double tempvar = CharToDouble(vars[index -1]) + CharToDouble(XdrvMailbox.data); - dtostrfd(tempvar, 2, vars[index -1]); + dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } else if ((CMND_SUB == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { double tempvar = CharToDouble(vars[index -1]) - CharToDouble(XdrvMailbox.data); - dtostrfd(tempvar, 2, vars[index -1]); + dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } else if ((CMND_MULT == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { double tempvar = CharToDouble(vars[index -1]) * CharToDouble(XdrvMailbox.data); - dtostrfd(tempvar, 2, vars[index -1]); + dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } @@ -625,7 +632,7 @@ boolean RulesCommand(void) double toLow = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 4)); double toHigh = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 5)); double value = map_double(valueIN, fromLow, fromHigh, toLow, toHigh); - dtostrfd(value, 2, vars[index -1]); + dtostrfd(value, Settings.flag2.calc_resolution, vars[index -1]); } } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); From 2ce7862594ad61c6097134b6db7dc7f271a28452 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 26 Nov 2018 21:25:57 -0300 Subject: [PATCH 0606/2222] 6.3.0.14 Added Calc Resolution --- tools/decode-config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/decode-config.py b/tools/decode-config.py index 22d6262ea..71e46f152 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -534,6 +534,7 @@ Setting_5_10_0 = { 'energy_kWhtotal': (' Date: Mon, 26 Nov 2018 21:27:07 -0300 Subject: [PATCH 0607/2222] 6.3.0.14 Added Calc Resolution --- sonoff/sonoff_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index cd5a77a08..d3df8d797 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0603000D +#define VERSION 0x0603000E #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" From e46a81c193953c3b78c43b064e39f97354e8b5d9 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 26 Nov 2018 21:29:06 -0300 Subject: [PATCH 0608/2222] 6.3.0.14 Added command CalcRes --- sonoff/_changelog.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 2351beb8c..3de9daa3c 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.3.0.13 20181126 +/* 6.3.0.14 20181127 + * Add Command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420) + * + * 6.3.0.13 20181126 * Add command SetOption59 0/1 to change state topic from tele/STATE to stat/RESULT (#4450) * Fix WifiManager functionality on initial installation (#4433) * From 7e34f402c94b6298e77f9a07fa7e6b8c76b5b9f3 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Tue, 27 Nov 2018 01:30:05 +0100 Subject: [PATCH 0609/2222] PS_16_DZ: GPIO13 => LED1 --- sonoff/sonoff_template.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 150539abc..5b12a5ded 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1281,12 +1281,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, GPIO_TXD, // GPIO01 MCU serial control GPIO_USER, - GPIO_RXD, // GPIO03 MCU serial control + GPIO_RXD, // GPIO03 MCU serial control GPIO_USER, GPIO_USER, 0, 0, 0, 0, 0, 0, // Flash connection GPIO_USER, - GPIO_USER, + GPIO_LED1, // GPIO13 WiFi LED GPIO_USER, GPIO_USER, GPIO_USER, From 281166841b74a1519fc1d424e16d7460eb2ce26f Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Tue, 27 Nov 2018 02:04:59 +0100 Subject: [PATCH 0610/2222] PS_16_DZ: cleanup code --- sonoff/xdrv_19_ps16dz_dimmer.ino | 39 ++++---------------------------- 1 file changed, 5 insertions(+), 34 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index b62d35eca..aa6336bd6 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -31,7 +31,7 @@ boolean ps16dz_ignore_dim = false; // Flag to skip serial send to pre boolean ps16dz_power = false; uint8_t ps16dz_bright = 0; -uint64_t ps16dz_seq = 0; +//uint64_t ps16dz_seq = 0; char ps16dz_tx_buffer[PS16DZ_BUFFER_SIZE]; // Serial transmit buffer char ps16dz_rx_buffer[PS16DZ_BUFFER_SIZE]; // Serial receive buffer @@ -41,35 +41,9 @@ int ps16dz_byte_counter = 0; * Internal Functions \*********************************************************************************************/ - -size_t print_uint64_t(uint64_t number) +void printTimestamp(void) { - size_t n = 0; - unsigned char buf[21]; - uint8_t i = 0; - - if (number == 0) - { - n += snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s%c"), ps16dz_tx_buffer, (char)'0'); - return n; - } - - while (number > 0) - { - uint64_t q = number/10; - buf[i++] = number - q*10; - number = q; - } - - for (; i > 0; i--) - n += snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s%c"), ps16dz_tx_buffer, (char) ('0' + buf[i - 1])); - - return n; -} - -uint64_t getTimestamp(void) -{ - return (((uint64_t)LocalTime()) * 1000) + (millis()%1000); + snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s%d%03d"), ps16dz_tx_buffer, LocalTime(), millis()%1000); } boolean PS16DZSetPower(void) @@ -82,8 +56,7 @@ boolean PS16DZSetPower(void) if (source != SRC_SWITCH && PS16DZSerial) { // ignore to prevent loop from pushing state from faceplate interaction snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); - ps16dz_seq = getTimestamp(); - print_uint64_t(ps16dz_seq); + printTimestamp(); snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, rpower?"on":"off"); snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); @@ -105,8 +78,7 @@ void PS16DZSerialDuty(uint8_t duty) } snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); - ps16dz_seq = getTimestamp(); - print_uint64_t(ps16dz_seq); + printTimestamp(); snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"bright\":%d"), ps16dz_tx_buffer, round(duty * (100. / 255.))); snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); @@ -156,7 +128,6 @@ void PS16DZSerialInput(void) char scmnd[20]; while (PS16DZSerial->available()) { yield(); - //ps16dz_command = PS16DZSerial->readStringUntil(0x1B); byte serial_in_byte = PS16DZSerial->read(); if (serial_in_byte != 0x1B){ if (ps16dz_byte_counter || (!ps16dz_byte_counter && serial_in_byte == 'A')); From e3d1971e5138574b192e0bba0f0b00170e0353c5 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 26 Nov 2018 23:08:23 -0300 Subject: [PATCH 0611/2222] Add Command CalcRes --- sonoff/xdrv_10_rules.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 160c4e305..1fde3dff7 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -595,8 +595,8 @@ boolean RulesCommand(void) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]); } else if (CMND_CALC_RESOLUTION == command_code) { - if ((payload >= 0) && (payload <= 7)) { - Settings.flag2.calc_resolution = payload; + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 7)) { + Settings.flag2.calc_resolution = XdrvMailbox.payload; } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.calc_resolution); } From 101cf83d7d235a7ccc11003e447d06d485b5fc4e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 27 Nov 2018 10:54:34 +0100 Subject: [PATCH 0612/2222] Update settings.ino --- sonoff/settings.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 6d3263f41..99e81230d 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -858,6 +858,9 @@ void SettingsDelta(void) if (Settings.version < 0x0603000A) { Settings.param[P_LOOP_SLEEP_DELAY] = LOOP_SLEEP_DELAY; } + if (Settings.version < 0x0603000E) { + Settings.flag2.calc_resolution = CALC_RESOLUTION; + } Settings.version = VERSION; SettingsSave(1); From 6a46354880dd8c2f5673a9b581110274a5aeb3e4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 27 Nov 2018 11:00:15 +0100 Subject: [PATCH 0613/2222] Update decode-config.py --- tools/decode-config.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 71e46f152..22d6262ea 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -534,7 +534,6 @@ Setting_5_10_0 = { 'energy_kWhtotal': (' Date: Tue, 27 Nov 2018 11:04:45 +0100 Subject: [PATCH 0614/2222] Add SetOption59 info Add SetOption59 info --- tools/decode-status.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/decode-status.py b/tools/decode-status.py index 83077e5fd..2ab37a642 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -93,7 +93,8 @@ a_setoption = [[ "Use wifi network scan at restart", "Use wifi network rescan regularly", "Add IR raw data to JSON message", - "","","", + "Change state topic from tele/STATE to stat/RESULT", + "","", "","","","", "","","","", "","","","", From 3470d4712f17ca773843c1c580c574347241ed06 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Tue, 27 Nov 2018 11:24:19 +0100 Subject: [PATCH 0615/2222] decode-config.py: add 6.3.0.11 to .14 settings --- tools/decode-config.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 22d6262ea..287f221ef 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0009' +VER = '2.1.0010' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -783,7 +783,25 @@ Setting_6_3_0_10['flag3'][0].update ({ 'use_wifi_rescan': (' Date: Tue, 27 Nov 2018 11:55:54 +0100 Subject: [PATCH 0616/2222] Add dynamic buffer space Make serial buffer space reservation dynamic --- sonoff/xdrv_16_tuyadimmer.ino | 19 +++++++++++-------- sonoff/xdrv_19_ps16dz_dimmer.ino | 22 ++++++++++++++-------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index 1322da33a..15db69747 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -53,7 +53,7 @@ uint8_t tuya_cmd_checksum = 0; // Checksum of tuya command uint8_t tuya_data_len = 0; // Data lenght of command int8_t tuya_wifi_state = -2; // Keep MCU wifi-status in sync with WifiState() -char tuya_buffer[TUYA_BUFFER_SIZE]; // Serial receive buffer +char *tuya_buffer = NULL; // Serial receive buffer int tuya_byte_counter = 0; // Index in serial receive buffer /*********************************************************************************************\ @@ -285,14 +285,17 @@ void TuyaInit(void) if (!Settings.param[P_TUYA_DIMMER_ID]) { Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID; } - TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); - if (TuyaSerial->begin(9600)) { - if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } - // Get MCU Configuration - snprintf_P(log_data, sizeof(log_data), "TYA: Request MCU configuration"); - AddLog(LOG_LEVEL_DEBUG); + tuya_buffer = reinterpret_cast(malloc(TUYA_BUFFER_SIZE)); + if (tuya_buffer != NULL) { + TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); + if (TuyaSerial->begin(9600)) { + if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } + // Get MCU Configuration + snprintf_P(log_data, sizeof(log_data), "TYA: Request MCU configuration"); + AddLog(LOG_LEVEL_DEBUG); - TuyaSendCmd(TUYA_CMD_MCU_CONF); + TuyaSendCmd(TUYA_CMD_MCU_CONF); + } } } diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index aa6336bd6..f4780f78e 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -33,8 +33,8 @@ boolean ps16dz_power = false; uint8_t ps16dz_bright = 0; //uint64_t ps16dz_seq = 0; -char ps16dz_tx_buffer[PS16DZ_BUFFER_SIZE]; // Serial transmit buffer -char ps16dz_rx_buffer[PS16DZ_BUFFER_SIZE]; // Serial receive buffer +char *ps16dz_tx_buffer = NULL; // Serial transmit buffer +char *ps16dz_rx_buffer = NULL; // Serial receive buffer int ps16dz_byte_counter = 0; /*********************************************************************************************\ @@ -60,7 +60,7 @@ boolean PS16DZSetPower(void) snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, rpower?"on":"off"); snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); - + PS16DZSerial->print(ps16dz_tx_buffer); PS16DZSerial->write(0x1B); PS16DZSerial->flush(); @@ -82,7 +82,7 @@ void PS16DZSerialDuty(uint8_t duty) snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"bright\":%d"), ps16dz_tx_buffer, round(duty * (100. / 255.))); snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); - + PS16DZSerial->print(ps16dz_tx_buffer); PS16DZSerial->write(0x1B); PS16DZSerial->flush(); @@ -117,9 +117,15 @@ boolean PS16DZModuleSelected(void) void PS16DZInit(void) { - PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); - if (PS16DZSerial->begin(19200)) { - if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } + ps16dz_tx_buffer = reinterpret_cast(malloc(PS16DZ_BUFFER_SIZE)); + if (ps16dz_tx_buffer != NULL) { + ps16dz_rx_buffer = reinterpret_cast(malloc(PS16DZ_BUFFER_SIZE)); + if (ps16dz_rx_buffer != NULL) { + PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (PS16DZSerial->begin(19200)) { + if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } + } + } } } @@ -174,7 +180,7 @@ void PS16DZSerialInput(void) //ps16dz_seq = strtoull(token3+1, NULL, 10); snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: sequence received: %s"), token3); AddLog(LOG_LEVEL_DEBUG); - } + } token = strtok_r(NULL, ",", &end_str); } } From 3f33e3efa87b3d9543b0c3f681c788e5beb8b6ba Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 27 Nov 2018 12:09:36 +0100 Subject: [PATCH 0617/2222] Add dynamic buffer space Add dynamic buffer space --- sonoff/xdrv_08_serial_bridge.ino | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 3d28e49bc..d1c8e81aa 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -36,7 +36,7 @@ TasmotaSerial *SerialBridgeSerial; uint8_t serial_bridge_active = 1; uint8_t serial_bridge_in_byte_counter = 0; unsigned long serial_bridge_polling_window = 0; -char serial_bridge_buffer[SERIAL_BRIDGE_BUFFER_SIZE]; +char *serial_bridge_buffer = NULL; void SerialBridgeInput(void) { @@ -75,10 +75,13 @@ void SerialBridgeInit(void) { serial_bridge_active = 0; if ((pin[GPIO_SBR_RX] < 99) && (pin[GPIO_SBR_TX] < 99)) { - SerialBridgeSerial = new TasmotaSerial(pin[GPIO_SBR_RX], pin[GPIO_SBR_TX]); - if (SerialBridgeSerial->begin(Settings.sbaudrate * 1200)) { // Baud rate is stored div 1200 so it fits into one byte - serial_bridge_active = 1; - SerialBridgeSerial->flush(); + serial_bridge_buffer = (char*)(malloc(SERIAL_BRIDGE_BUFFER_SIZE)); + if (serial_bridge_buffer != NULL) { + SerialBridgeSerial = new TasmotaSerial(pin[GPIO_SBR_RX], pin[GPIO_SBR_TX]); + if (SerialBridgeSerial->begin(Settings.sbaudrate * 1200)) { // Baud rate is stored div 1200 so it fits into one byte + serial_bridge_active = 1; + SerialBridgeSerial->flush(); + } } } } @@ -122,7 +125,7 @@ boolean SerialBridgeCommand(void) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_LVALUE, command, Settings.sbaudrate * 1200); } else serviced = false; // Unknown command - + return serviced; } From 0df7df9b0892dae795d964c3396e2b2099908c1b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 27 Nov 2018 12:18:27 +0100 Subject: [PATCH 0618/2222] Fix dynamic buffer handling Fix dynamic buffer handling --- sonoff/xdrv_08_serial_bridge.ino | 2 +- sonoff/xdrv_16_tuyadimmer.ino | 2 +- sonoff/xdrv_19_ps16dz_dimmer.ino | 18 +++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index d1c8e81aa..e901e9958 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -50,7 +50,7 @@ void SerialBridgeInput(void) return; } if (serial_in_byte) { - if ((serial_in_byte_counter < sizeof(serial_bridge_buffer) -1) && (serial_in_byte != Settings.serial_delimiter)) { // add char to string if it still fits + if ((serial_in_byte_counter < SERIAL_BRIDGE_BUFFER_SIZE -1) && (serial_in_byte != Settings.serial_delimiter)) { // add char to string if it still fits serial_bridge_buffer[serial_bridge_in_byte_counter++] = serial_in_byte; serial_bridge_polling_window = millis(); // Wait for more data } else { diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index 15db69747..1312a7199 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -285,7 +285,7 @@ void TuyaInit(void) if (!Settings.param[P_TUYA_DIMMER_ID]) { Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID; } - tuya_buffer = reinterpret_cast(malloc(TUYA_BUFFER_SIZE)); + tuya_buffer = (char*)(malloc(TUYA_BUFFER_SIZE)); if (tuya_buffer != NULL) { TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); if (TuyaSerial->begin(9600)) { diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index f4780f78e..04c9a1099 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -43,7 +43,7 @@ int ps16dz_byte_counter = 0; void printTimestamp(void) { - snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s%d%03d"), ps16dz_tx_buffer, LocalTime(), millis()%1000); + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "%s%d%03d"), ps16dz_tx_buffer, LocalTime(), millis()%1000); } boolean PS16DZSetPower(void) @@ -55,9 +55,9 @@ boolean PS16DZSetPower(void) if (source != SRC_SWITCH && PS16DZSerial) { // ignore to prevent loop from pushing state from faceplate interaction - snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "AT+UPDATE=\"sequence\":\"")); printTimestamp(); - snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, rpower?"on":"off"); + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, rpower?"on":"off"); snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); @@ -77,9 +77,9 @@ void PS16DZSerialDuty(uint8_t duty) duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself } - snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+UPDATE=\"sequence\":\"")); + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "AT+UPDATE=\"sequence\":\"")); printTimestamp(); - snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "%s\",\"bright\":%d"), ps16dz_tx_buffer, round(duty * (100. / 255.))); + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "%s\",\"bright\":%d"), ps16dz_tx_buffer, round(duty * (100. / 255.))); snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); @@ -117,9 +117,9 @@ boolean PS16DZModuleSelected(void) void PS16DZInit(void) { - ps16dz_tx_buffer = reinterpret_cast(malloc(PS16DZ_BUFFER_SIZE)); + ps16dz_tx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); if (ps16dz_tx_buffer != NULL) { - ps16dz_rx_buffer = reinterpret_cast(malloc(PS16DZ_BUFFER_SIZE)); + ps16dz_rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); if (ps16dz_rx_buffer != NULL) { PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); if (PS16DZSerial->begin(19200)) { @@ -189,10 +189,10 @@ void PS16DZSerialInput(void) AddLog(LOG_LEVEL_DEBUG); PS16DZResetWifi(); } - memset(ps16dz_rx_buffer, 0, sizeof(ps16dz_rx_buffer)); + memset(ps16dz_rx_buffer, 0, PS16DZ_BUFFER_SIZE); ps16dz_byte_counter = 0; - snprintf_P(ps16dz_tx_buffer, sizeof(ps16dz_tx_buffer), PSTR( "AT+SEND=ok")); + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "AT+SEND=ok")); snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); AddLog(LOG_LEVEL_DEBUG); From fd20706ef79665e5fede9d58cdb15f9f89c8bc80 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 27 Nov 2018 14:38:09 +0100 Subject: [PATCH 0619/2222] Move static to dynamic buffers * Add support for SM Smart Wifi Dimmer PS-16-DZ (#4465) * Move some static (serial) buffers to dynamic buffers --- sonoff/_changelog.ino | 2 ++ sonoff/my_user_config.h | 2 +- sonoff/xdrv_05_irremote.ino | 17 ++++++++------- sonoff/xdsp_03_matrix.ino | 41 +++++++++++++++++++++---------------- 4 files changed, 34 insertions(+), 28 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 3de9daa3c..1d0eee7fe 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,7 @@ /* 6.3.0.14 20181127 * Add Command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420) + * Add support for SM Smart Wifi Dimmer PS-16-DZ (#4465) + * Move some static (serial) buffers to dynamic buffers * * 6.3.0.13 20181126 * Add command SetOption59 0/1 to change state topic from tele/STATE to stat/RESULT (#4450) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 510827497..d3244669c 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -174,7 +174,6 @@ #define SWITCH_DEBOUNCE_TIME 50 // [SwitchDebounce] Number of mSeconds switch press debounce time #define SWITCH_MODE TOGGLE // [SwitchMode] TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE (the wall switch state) #define WS2812_LEDS 30 // [Pixels] Number of WS2812 LEDs to start with (max is 512) -#define CALC_RESOLUTION 3 // [CalcRes] Maximum number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE #define TEMP_CONVERSION 0 // [SetOption8] Return temperature in (0 = Celsius or 1 = Fahrenheit) #define PRESSURE_CONVERSION 0 // [SetOption24] Return pressure in (0 = hPa or 1 = mmHg) @@ -182,6 +181,7 @@ #define HUMIDITY_RESOLUTION 1 // [HumRes] Maximum number of decimals (0 - 3) showing sensor Humidity #define PRESSURE_RESOLUTION 1 // [PressRes] Maximum number of decimals (0 - 3) showing sensor Pressure #define ENERGY_RESOLUTION 3 // [EnergyRes] Maximum number of decimals (0 - 5) showing energy usage in kWh +#define CALC_RESOLUTION 3 // [CalcRes] Maximum number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE /*********************************************************************************************\ * END OF SECTION 1 diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 7cd38c2d5..ef02e61ba 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -379,8 +379,8 @@ boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_P hvacOn = true; } - snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: HvacMode %s, ModeVal %d, Code %d"), p, mode, data[3]); - AddLog(LOG_LEVEL_DEBUG); +// snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: HvacMode %s, ModeVal %d, Code %d"), p, mode, data[3]); +// AddLog(LOG_LEVEL_DEBUG); // Set code for HVAC temperature - data[4] if (HVAC_Temp > 30) { @@ -412,8 +412,8 @@ boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_P data[5] = (mode * 2) - 2; // Low = 0x00, Mid = 0x02, High = 0x04 } - snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: FanMode %s, ModeVal %d, Code %d"), p, mode, data[5]); - AddLog(LOG_LEVEL_DEBUG); +// snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: FanMode %s, ModeVal %d, Code %d"), p, mode, data[5]); +// AddLog(LOG_LEVEL_DEBUG); // Set CRC code - data[6] data[6] = (data[3] + data[4] + data[5]) & 0x0f; // CRC @@ -426,8 +426,8 @@ boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_P } LG_Code = LG_Code + data[6]; - snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: LG_Code %d"), LG_Code); - AddLog(LOG_LEVEL_DEBUG); +// snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: LG_Code %d"), LG_Code); +// AddLog(LOG_LEVEL_DEBUG); // Send LG IR Code noInterrupts(); @@ -446,8 +446,8 @@ boolean IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H { const char kFujitsuHvacModeOptions[] = "HDCAF"; - char stemp[64]; - snprintf_P(stemp, sizeof(stemp), PSTR("FUJITSU: mode:%s, fan:%s, power:%u, temp:%u"), HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); +// snprintf_P(log_data, sizeof(log_data), PSTR("FUJITSU: mode:%s, fan:%s, power:%u, temp:%u"), HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); +// AddLog(LOG_LEVEL_DEBUG); IRFujitsuAC ac(pin[GPIO_IRSEND]); @@ -536,7 +536,6 @@ boolean IrSendCommand(void) raw_array[i++] = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input } -// DebugFreeMem(); // snprintf_P(log_data, sizeof(log_data), PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), // count, freq, raw_array[0], raw_array[count -1]); // AddLog(LOG_LEVEL_DEBUG); diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index 63222c637..da458cb15 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -36,7 +36,9 @@ uint8_t mtx_counter = 0; int16_t mtx_x = 0; int16_t mtx_y = 0; -char mtx_buffer[MTX_MAX_SCREEN_BUFFER]; +//char mtx_buffer[MTX_MAX_SCREEN_BUFFER]; +char *mtx_buffer = NULL; + uint8_t mtx_mode = 0; uint8_t mtx_loop = 0; uint8_t mtx_done = 0; @@ -194,24 +196,27 @@ void MatrixInit(uint8_t mode) void MatrixInitDriver(void) { - if (!Settings.display_model) { - if (I2cDevice(Settings.display_address[1])) { - Settings.display_model = XDSP_03; - } - } - - if (XDSP_03 == Settings.display_model) { - mtx_state = 1; - for (mtx_matrices = 0; mtx_matrices < 8; mtx_matrices++) { - if (Settings.display_address[mtx_matrices]) { - matrix[mtx_matrices] = new Adafruit_8x8matrix(); - matrix[mtx_matrices]->begin(Settings.display_address[mtx_matrices]); - } else { - break; + mtx_buffer = (char*)(malloc(MTX_MAX_SCREEN_BUFFER)); + if (mtx_buffer != NULL) { + if (!Settings.display_model) { + if (I2cDevice(Settings.display_address[1])) { + Settings.display_model = XDSP_03; } } - MatrixInitMode(); + if (XDSP_03 == Settings.display_model) { + mtx_state = 1; + for (mtx_matrices = 0; mtx_matrices < 8; mtx_matrices++) { + if (Settings.display_address[mtx_matrices]) { + matrix[mtx_matrices] = new Adafruit_8x8matrix(); + matrix[mtx_matrices]->begin(Settings.display_address[mtx_matrices]); + } else { + break; + } + } + + MatrixInitMode(); + } } } @@ -222,7 +227,7 @@ void MatrixOnOff(void) void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) { - snprintf(mtx_buffer, sizeof(mtx_buffer), str); + snprintf(mtx_buffer, MTX_MAX_SCREEN_BUFFER, str); mtx_mode = x &1; // Use x for selecting scroll up (0) or scroll left (1) mtx_loop = y &1; // Use y for selecting no loop (0) or loop (1) if (!mtx_state) { mtx_state = 1; } @@ -251,7 +256,7 @@ void MatrixPrintLog(uint8_t direction) space = 0; } if (space < 2) { - strncat(mtx_buffer, (const char*)txt +i, (strlen(mtx_buffer) < sizeof(mtx_buffer) -1) ? 1 : 0); + strncat(mtx_buffer, (const char*)txt +i, (strlen(mtx_buffer) < MTX_MAX_SCREEN_BUFFER -1) ? 1 : 0); } i++; } From be358b3314ce3fc0dca41d6dce6e6d925f56a768 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 27 Nov 2018 15:11:10 +0100 Subject: [PATCH 0620/2222] Prep for Software SPI Prep for Software SPI used by some displays --- sonoff/language/bg-BG.h | 5 +++++ sonoff/language/cs-CZ.h | 5 +++++ sonoff/language/de-DE.h | 5 +++++ sonoff/language/el-GR.h | 5 +++++ sonoff/language/en-GB.h | 6 ++++++ sonoff/language/es-AR.h | 5 +++++ sonoff/language/fr-FR.h | 5 +++++ sonoff/language/he-HE.h | 5 +++++ sonoff/language/hu-HU.h | 5 +++++ sonoff/language/it-IT.h | 5 +++++ sonoff/language/nl-NL.h | 5 +++++ sonoff/language/pl-PL.h | 5 +++++ sonoff/language/pt-BR.h | 5 +++++ sonoff/language/pt-PT.h | 5 +++++ sonoff/language/ru-RU.h | 5 +++++ sonoff/language/tr-TR.h | 5 +++++ sonoff/language/uk-UK.h | 5 +++++ sonoff/language/zh-CN.h | 5 +++++ sonoff/language/zh-TW.h | 5 +++++ sonoff/sonoff_template.h | 15 +++++++++++++-- 20 files changed, 109 insertions(+), 2 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 3663dfbae..0707317f5 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index e545ec0a9..49e0991bb 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 17acd9194..e497bcf45 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 4a8e84a7a..591c7f414 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index c276187ab..aeb61103d 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -531,6 +531,12 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" + // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 77d835604..c90a20b09 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 6947bfc54..0936f6069 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index e6ef65a08..ea0e4c6df 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 81e4e7756..0ac020605 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 5cb974df5..3dc9d811b 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 875bfd921..e288e7196 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index e697966e5..aee1b99a0 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 0336bac9a..1c94a784d 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 7afd0b1bc..5b1f77811 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index bc6383476..3d470bfdd 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index f5bf3ed8f..fa9a41d18 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index c6303e243..d6bb5e074 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 746eb0b86..2f18d2581 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index a6894dc1e..0084fa038 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -531,6 +531,11 @@ #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" #define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 5b12a5ded..1f1cadb09 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -135,6 +135,11 @@ enum UserSelectablePins { GPIO_TUYA_RX, // Tuya Serial interface GPIO_MGC3130_XFER, // MGC3130 Transfer GPIO_MGC3130_RESET, // MGC3130 Reset + GPIO_SSPI_MISO, // Software SPI Master Input Slave Output + GPIO_SSPI_MOSI, // Software SPI Master Output Slave Input + GPIO_SSPI_SCLK, // Software SPI Serial Clock + GPIO_SSPI_CS, // Software SPI Chip Select + GPIO_SSPI_DC, // Software SPI Data or Command GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -193,7 +198,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_TX20_TX "|" D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|" D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|" - D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET; + D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET "|" + D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC; /********************************************************************************************/ @@ -349,6 +355,11 @@ const uint8_t kGpioNiceList[] PROGMEM = { #ifdef USE_SPI GPIO_SPI_CS, // SPI Chip Select GPIO_SPI_DC, // SPI Data Direction + GPIO_SSPI_MISO, // Software SPI Master Input Slave Output + GPIO_SSPI_MOSI, // Software SPI Master Output Slave Input + GPIO_SSPI_SCLK, // Software SPI Serial Clock + GPIO_SSPI_CS, // Software SPI Chip Select + GPIO_SSPI_DC, // Software SPI Data or Command #endif #ifdef USE_DISPLAY GPIO_BACKLIGHT, // Display backlight control @@ -1276,7 +1287,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) 0, 0 }, - { "PS-16-DZ", // PS-16-DZ Dimmer (ESP8266 w/ separate Nuvoton MCU dimmer) + { "PS-16-DZ", // PS-16-DZ Dimmer (ESP8266 w/ separate Nuvoton MCU dimmer) // https://www.aliexpress.com/item/SM-Smart-WIFI-Wall-Dimmer-Light-Switch-US-Ewelink-APP-Remote-Control-Wi-Fi-Wirele-Work/32871151902.html GPIO_USER, GPIO_TXD, // GPIO01 MCU serial control From 7a2c5154aa7ee6838aaa64006fac3ef59788a274 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Tue, 27 Nov 2018 16:11:14 +0100 Subject: [PATCH 0621/2222] PS_16_DZ: only update brightness if it actually changed --- sonoff/xdrv_19_ps16dz_dimmer.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 04c9a1099..8f569278f 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -165,7 +165,7 @@ void PS16DZSerialInput(void) ps16dz_bright = atoi(token3); snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: brightness received: %d"), ps16dz_bright); AddLog(LOG_LEVEL_DEBUG); - if(power && ps16dz_bright > 0) { + if(power && ps16dz_bright > 0 && ps16dz_bright != Settings.light_dimmer) { snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), ps16dz_bright ); From 5099d8f20d7176e0c5e4f797351898568bda86d2 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Tue, 27 Nov 2018 16:52:09 +0100 Subject: [PATCH 0622/2222] PS_16_DZ: reduce buffer-size and actually check for overflow --- sonoff/xdrv_19_ps16dz_dimmer.ino | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 8f569278f..755390029 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -21,7 +21,7 @@ #define XDRV_19 19 -#define PS16DZ_BUFFER_SIZE 256 +#define PS16DZ_BUFFER_SIZE 80 #include @@ -29,8 +29,6 @@ TasmotaSerial *PS16DZSerial = nullptr; boolean ps16dz_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction -boolean ps16dz_power = false; -uint8_t ps16dz_bright = 0; //uint64_t ps16dz_seq = 0; char *ps16dz_tx_buffer = NULL; // Serial transmit buffer @@ -136,6 +134,10 @@ void PS16DZSerialInput(void) yield(); byte serial_in_byte = PS16DZSerial->read(); if (serial_in_byte != 0x1B){ + if (ps16dz_byte_counter >= PS16DZ_BUFFER_SIZE) { + memset(ps16dz_rx_buffer, 0, PS16DZ_BUFFER_SIZE); + ps16dz_byte_counter = 0; + } if (ps16dz_byte_counter || (!ps16dz_byte_counter && serial_in_byte == 'A')); ps16dz_rx_buffer[ps16dz_byte_counter++] = serial_in_byte; } @@ -154,7 +156,7 @@ void PS16DZSerialInput(void) char* token2 = strtok_r(token, ":", &end_token); char* token3 = strtok_r(NULL, ":", &end_token); if(!strncmp(token2, "\"switch\"", 8)){ - ps16dz_power = !strncmp(token3, "\"on\"", 4)?true:false; + boolean ps16dz_power = !strncmp(token3, "\"on\"", 4)?true:false; snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: power received: %s"), token3); AddLog(LOG_LEVEL_DEBUG); if((power || Settings.light_dimmer > 0) && (power !=ps16dz_power)) { @@ -162,7 +164,7 @@ void PS16DZSerialInput(void) } } else if(!strncmp(token2, "\"bright\"", 8)){ - ps16dz_bright = atoi(token3); + uint8_t ps16dz_bright = atoi(token3); snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: brightness received: %d"), ps16dz_bright); AddLog(LOG_LEVEL_DEBUG); if(power && ps16dz_bright > 0 && ps16dz_bright != Settings.light_dimmer) { From 6825b781537af678e1b111d54c792e21df3f4d57 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Tue, 27 Nov 2018 17:18:41 +0100 Subject: [PATCH 0623/2222] PS_16_DZ: optimize for size --- sonoff/xdrv_19_ps16dz_dimmer.ino | 58 ++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 755390029..c77aaf554 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -23,6 +23,10 @@ #define PS16DZ_BUFFER_SIZE 80 +#define PS16DZ_TYPE_ACK 0 +#define PS16DZ_TYPE_PWR 1 +#define PS16DZ_TYPE_DIM 2 + #include TasmotaSerial *PS16DZSerial = nullptr; @@ -44,6 +48,32 @@ void printTimestamp(void) snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "%s%d%03d"), ps16dz_tx_buffer, LocalTime(), millis()%1000); } +void PS16DZSendCommand(char type = 0, uint8_t value = 0) +{ + switch(type){ + case PS16DZ_TYPE_ACK: + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "AT+SEND=ok")); + break; + case PS16DZ_TYPE_PWR: + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "AT+UPDATE=\"sequence\":\"")); + printTimestamp(); + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, value?"on":"off"); + break; + case PS16DZ_TYPE_DIM: + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "AT+UPDATE=\"sequence\":\"")); + printTimestamp(); + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "%s\",\"bright\":%d"), ps16dz_tx_buffer, round(value * (100. / 255.))); + break; + } + + snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); + AddLog(LOG_LEVEL_DEBUG); + + PS16DZSerial->print(ps16dz_tx_buffer); + PS16DZSerial->write(0x1B); + PS16DZSerial->flush(); +} + boolean PS16DZSetPower(void) { boolean status = false; @@ -53,15 +83,7 @@ boolean PS16DZSetPower(void) if (source != SRC_SWITCH && PS16DZSerial) { // ignore to prevent loop from pushing state from faceplate interaction - snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "AT+UPDATE=\"sequence\":\"")); - printTimestamp(); - snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, rpower?"on":"off"); - snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); - AddLog(LOG_LEVEL_DEBUG); - - PS16DZSerial->print(ps16dz_tx_buffer); - PS16DZSerial->write(0x1B); - PS16DZSerial->flush(); + PS16DZSendCommand(PS16DZ_TYPE_PWR, rpower); status = true; } @@ -75,15 +97,7 @@ void PS16DZSerialDuty(uint8_t duty) duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself } - snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "AT+UPDATE=\"sequence\":\"")); - printTimestamp(); - snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "%s\",\"bright\":%d"), ps16dz_tx_buffer, round(duty * (100. / 255.))); - snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); - AddLog(LOG_LEVEL_DEBUG); - - PS16DZSerial->print(ps16dz_tx_buffer); - PS16DZSerial->write(0x1B); - PS16DZSerial->flush(); + PS16DZSendCommand(PS16DZ_TYPE_DIM, duty); } else { ps16dz_ignore_dim = false; // reset flag @@ -194,13 +208,7 @@ void PS16DZSerialInput(void) memset(ps16dz_rx_buffer, 0, PS16DZ_BUFFER_SIZE); ps16dz_byte_counter = 0; - snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "AT+SEND=ok")); - snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); - AddLog(LOG_LEVEL_DEBUG); - - PS16DZSerial->print(ps16dz_tx_buffer); - PS16DZSerial->write(0x1B); - PS16DZSerial->flush(); + PS16DZSendCommand(); } } } From 49403243d50e4c34180a4e7a79bf83472b96326a Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Tue, 27 Nov 2018 18:02:00 +0100 Subject: [PATCH 0624/2222] PS_16_DZ: further optimization --- sonoff/xdrv_19_ps16dz_dimmer.ino | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index c77aaf554..6a57b4686 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -55,14 +55,15 @@ void PS16DZSendCommand(char type = 0, uint8_t value = 0) snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "AT+SEND=ok")); break; case PS16DZ_TYPE_PWR: - snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "AT+UPDATE=\"sequence\":\"")); - printTimestamp(); - snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, value?"on":"off"); - break; case PS16DZ_TYPE_DIM: snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "AT+UPDATE=\"sequence\":\"")); printTimestamp(); - snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "%s\",\"bright\":%d"), ps16dz_tx_buffer, round(value * (100. / 255.))); + if ( type == PS16DZ_TYPE_PWR) { + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "%s\",\"switch\":\"%s\""), ps16dz_tx_buffer, value?"on":"off"); + } + else if ( type == PS16DZ_TYPE_DIM) { + snprintf_P(ps16dz_tx_buffer, PS16DZ_BUFFER_SIZE, PSTR( "%s\",\"bright\":%d"), ps16dz_tx_buffer, round(value * (100. / 255.))); + } break; } From f75c4a27add655d37f55e323c659a11075a1d5c1 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Tue, 27 Nov 2018 19:01:06 +0100 Subject: [PATCH 0625/2222] PS_16_DZ: leave space for trailing 0-byte --- sonoff/xdrv_19_ps16dz_dimmer.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 6a57b4686..72f9ea287 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -149,7 +149,7 @@ void PS16DZSerialInput(void) yield(); byte serial_in_byte = PS16DZSerial->read(); if (serial_in_byte != 0x1B){ - if (ps16dz_byte_counter >= PS16DZ_BUFFER_SIZE) { + if (ps16dz_byte_counter >= PS16DZ_BUFFER_SIZE - 1) { memset(ps16dz_rx_buffer, 0, PS16DZ_BUFFER_SIZE); ps16dz_byte_counter = 0; } From 6d3223f962f7cfda1131ee7e9e0a7545fd9b32df Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 27 Nov 2018 19:31:45 +0100 Subject: [PATCH 0626/2222] Hass: Restart if topic is changed --- sonoff/xdrv_12_home_assistant.ino | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 20e03fd99..e5f5a5324 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -428,8 +428,10 @@ void HAssDiscovery(uint8_t mode) Settings.flag.decimal_text = 1; // Respond with decimal color values Settings.flag3.hass_tele_as_result = 1; // send tele/STATE message as stat/RESULT // Settings.light_scheme = 0; // To just control color it needs to be Scheme 0 - if (!string_ends_with(Settings.mqtt_fulltopic, "%prefix%/")) + if (!string_ends_with(Settings.mqtt_fulltopic, "%prefix%/")) { strncpy_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"), sizeof(Settings.mqtt_fulltopic)); + restart_flag = 2; + } } if (Settings.flag.hass_discovery || (1 == mode)) { From 0ce7537371322a3d7a59908baeec8263450ec3fc Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Wed, 28 Nov 2018 00:04:06 +0100 Subject: [PATCH 0627/2222] PS_16_DZ: cleanup --- sonoff/xdrv_19_ps16dz_dimmer.ino | 2 -- 1 file changed, 2 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 72f9ea287..d8c8138e1 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -166,8 +166,6 @@ void PS16DZSerialInput(void) char* token = strtok_r(string, ",", &end_str); while (token != NULL) { char* end_token; - snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: token = %s"), token); - AddLog(LOG_LEVEL_DEBUG); char* token2 = strtok_r(token, ":", &end_token); char* token3 = strtok_r(NULL, ":", &end_token); if(!strncmp(token2, "\"switch\"", 8)){ From e3bff56092d2a3e0a30a49d696e7d951b6a86602 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 28 Nov 2018 14:06:02 +0100 Subject: [PATCH 0628/2222] Fix possible overflow situation Fix possible overflow situation --- sonoff/xnrg_03_pzem004t.ino | 6 ++++-- sonoff/xnrg_05_pzem_ac.ino | 8 +++++--- sonoff/xnrg_06_pzem_dc.ino | 8 +++++--- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index d30b769c2..850131762 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -181,8 +181,10 @@ void PzemEvery200ms(void) break; case 4: // Total energy as 99999Wh if (!energy_start || (value < energy_start)) energy_start = value; // Init after restart and hanlde roll-over if any - energy_kWhtoday += (value - energy_start) * 100; - energy_start = value; + if (value != energy_start) { + energy_kWhtoday += (unsigned long)((value - energy_start) * 100); + energy_start = value; + } EnergyUpdateToday(); break; } diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index 6bbabdaa9..7c145384a 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -62,9 +62,11 @@ void PzemAcEverySecond(void) energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00 float energy = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh - if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any - energy_kWhtoday += (energy - energy_start) * 100; - energy_start = energy; + if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and handle roll-over if any + if (energy != energy_start) { + energy_kWhtoday += (unsigned long)((energy - energy_start) * 100); + energy_start = energy; + } EnergyUpdateToday(); } } diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index 3dcaf8332..c12f401d4 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -60,9 +60,11 @@ void PzemDcEverySecond(void) energy_active_power = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W float energy = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh - if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any - energy_kWhtoday += (energy - energy_start) * 100; - energy_start = energy; + if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and handle roll-over if any + if (energy != energy_start) { + energy_kWhtoday += (unsigned long)((energy - energy_start) * 100); + energy_start = energy; + } EnergyUpdateToday(); } } From 259d9f5f6ccf1b4f100c21fd80cb2ef0bc92e460 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 28 Nov 2018 20:43:36 +0100 Subject: [PATCH 0629/2222] Small improvements to Hass MQTT discovery --- sonoff/xdrv_12_home_assistant.ino | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index e5f5a5324..4a7a0ea92 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -54,8 +54,7 @@ const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = "%s,\"rgb_command_topic\":\"%s2\"," // cmnd/led2/Color2 "\"rgb_state_topic\":\"%s\"," // stat/led2/RESULT - "\"rgb_value_template\":\"{{value_json." D_CMND_COLOR "}}\""; -// "\"rgb_value_template\":\"{{value_json." D_CMND_COLOR " | join(',')}}\""; + "\"rgb_value_template\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = "%s,\"color_temp_command_topic\":\"%s\"," // cmnd/led2/CT @@ -115,19 +114,17 @@ const char HASS_DISCOVER_LIGHT_COLOR_SHORT[] PROGMEM = "%s,\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2 "\"rgb_stat_t\":\"%s\"," // stat/led2/RESULT "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; -// "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR " | join(',')}}\""; const char HASS_DISCOVER_LIGHT_CT_SHORT[] PROGMEM = "%s,\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT "\"clr_temp_stat_t\":\"%s\"," // stat/led2/RESULT "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; -/* -const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = - "%s,\"effect_command_topic\":\"%s\"," // cmnd/led2/Scheme - "\"effect_state_topic\":\"%s\"," // stat/led2/RESULT - "\"effect_value_template\":\"{{value_json." D_CMND_SCHEME "}}\"," - "\"effect_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; // string list with reference to scheme parameter. Currently only supports numbers 0 to 11 as it make the mqtt string too long -*/ + +const char HASS_DISCOVER_LIGHT_SCHEME_SHORT[] PROGMEM = + "%s,\"fx_cmd_t\":\"%s\"," // cmnd/led2/Scheme + "\"fx_stat_t\":\"%s\"," // stat/led2/RESULT + "\"fx_val_tpl\":\"{{value_json." D_CMND_SCHEME "}}\"," + "\"fx_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; // string list with reference to scheme parameter. const char HASS_DISCOVER_SENSOR_SHORT[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 BTN @@ -239,12 +236,15 @@ void HAssAnnounceRelayLight(void) Shorten(&rgb_command_topic, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_COLOR_SHORT:HASS_DISCOVER_LIGHT_COLOR, mqtt_data, rgb_command_topic, state_topic); -/* - char effect_command_topic[TOPSZ]; + char _effect_command_topic[TOPSZ]; + char *effect_command_topic = _effect_command_topic; GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_SCHEME, mqtt_data, effect_command_topic, state_topic); -*/ + if (Settings.flag3.hass_short_discovery_msg) { + Shorten(&effect_command_topic, prefix); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_SCHEME_SHORT, mqtt_data, effect_command_topic, state_topic); + } + } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { char _color_temp_command_topic[TOPSZ]; From 7383ab4f45398375e871e96eae1f8008b52cdc24 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 29 Nov 2018 15:13:28 +0100 Subject: [PATCH 0630/2222] Add support for Teckin US Add support for Teckin US Wifi Smart Switch with Energy Monitoring (#4481) --- RELEASENOTES.md | 21 ++++++++++++++++++++- sonoff/sonoff_template.h | 19 ++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 254cf32ce..cf4e0d6ee 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -76,7 +76,26 @@ Module | Description 52 Teckin | Teckin SP20 Wifi Smart Switch with Energy Monitoring 53 AplicWDP303075 | Aplic WDP 303075 CSL Wifi Smart Switch with Energy Monitoring 54 Tuya Dimmer | MIUO (and other Tuya based) Wifi Dimmer for Incandescent Lights and Led -55 Gosund SP1_v23 | Gosund SP1 v2.3 Wifi Smart Switch with Energy Monitoring +55 Gosund SP1 v23 | Gosund SP1 v2.3 Wifi Smart Switch with Energy Monitoring +56 ARMTR Dimmer | ARMtronix Wifi dimmer for Incandescent Lights and Led +57 SK03 Outdoor | SK03 Outdoor Wifi Smart Switch with Energy Monitoring +58 PS-16-DZ | PS-16-DZ Wifi dimmer for Incandescent Lights and Led +59 Teckin US | Teckin US and ZooZee SA102 Wifi Smart Switch with Energy Monitoring + +## Supported Smart Switch with Energy Monitoring GPIO usage +Module | GPIO00 | GPIO01 | GPIO02 | GPIO03 | GPIO04 | GPIO05 | GPIO12 | GPIO13 | GPIO14 | GPIO15 +-------|--------|--------|--------|--------|--------|--------|--------|--------|--------|-------- +Sonoff Pow | KEY1 | - | - | - | - | NRG_SEL | REL1 | NRG_CF1 | HLW_CF | LED1 +Sonoff Pow R2 | KEY1 | RXD | - | TXD | - | - | REL1 | LED1_INV | - | - +Shelly 2 | - | RXD | - | TXD | REL1 | REL2 | SWT1 | - | SWT2 | - +Huafan SS | LED1_INV | - | - | LED2_INV | KEY1 | REL1_INV | NRG_CF1 | NRG_SEL | HLW_CF | - +KMC 70011 | KEY1 | - | - | - | HLW_CF | NRG_CF1 | NRG_SEL | LED1_INV | REL1 | - +Teckin | - | KEY1 | - | LED2_INV | HJL_CF | NRG_CF1 | NRG_SEL_INV | LED1_INV | REL1 | - +AplicWDP303075 | - | - | - | KEY1 | HLW_CF | NRG_CF1 | NRG_SEL_INV | LED1_INV | REL1 | - +Gosund SP1 v23 | - | LED1_INV | - | KEY1 | HJL_CF | NRG_CF1 | NRG_SEL_INV | LED2_INV | REL1 | - +SK03 Outdoor | KEY1 | - | - | - | HLW_CF | NRG_CF1 | NRG_SEL_INV | LED2_INV | LED1_INV | REL1 +BlitzWolf SHP | LED2_INV | - | LED1_INV | - | - | HJL_CF | NRG_SEL_INV | KEY1 | NRG_CF1 | REL1 +Teckin US | LED2_INV | - | LED1_INV | - | REL1 | HJL_CF | NRG_SEL_INV | KEY1 | NRG_CF1 | - ## Provided Binary Downloads The following binary downloads have been compiled with ESP8266/Arduino library version **2.3.0** diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 1f1cadb09..c4fcfb377 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -263,6 +263,7 @@ enum SupportedModules { ARMTRONIX_DIMMERS, SK03_TUYA, PS_16_DZ, + TECKIN_US, MAXMODULE }; /********************************************************************************************/ @@ -487,6 +488,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { SHELLY2, BLITZWOLF_BWSHP, // Socket Relay Devices with Energy Monitoring TECKIN, + TECKIN_US, APLIC_WDP303075, GOSUND, SK03_TUYA, @@ -1245,7 +1247,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, 0 }, - { "Gosund SP1_v23", // https://www.amazon.de/gp/product/B0777BWS1P + { "Gosund SP1 v23", // https://www.amazon.de/gp/product/B0777BWS1P 0, GPIO_LED1_INV, // GPIO01 Serial RXD and LED1 (blue) inv 0, @@ -1302,6 +1304,21 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, GPIO_USER, 0 + }, + { "Teckin US", // Teckin SP20 US with Energy Monitoring + // https://www.amazon.com/Outlet-Compatible-Monitoring-Function-Required/dp/B079Q5W22B + // https://www.amazon.com/Outlet-ZOOZEE-Monitoring-Function-Compatible/dp/B07J2LR5KN + GPIO_LED2_INV, // GPIO00 Red Led (1 = On, 0 = Off) + 0, + GPIO_LED1_INV, // GPIO02 Blue Led (1 = On, 0 = Off) + 0, + GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) + GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_KEY1, // GPIO13 Button + GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage + 0, 0, 0 } }; From 8b5bbd773e49a375b565bf414eaa54ee8dc21121 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 29 Nov 2018 17:50:45 +0100 Subject: [PATCH 0631/2222] Update display and epaper drivers Update display and epaper drivers --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 2 +- sonoff/support_features.ino | 2 +- sonoff/xdrv_13_display.ino | 4 +- ...sp_05_epaper.ino => xdsp_05_epaper_29.ino} | 99 +++++++++++++++++-- 5 files changed, 95 insertions(+), 13 deletions(-) rename sonoff/{xdsp_05_epaper.ino => xdsp_05_epaper_29.ino} (67%) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 1d0eee7fe..d230ff02f 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Add Command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420) * Add support for SM Smart Wifi Dimmer PS-16-DZ (#4465) * Move some static (serial) buffers to dynamic buffers + * Update display and epaper drivers * * 6.3.0.13 20181126 * Add command SetOption59 0/1 to change state topic from tele/STATE to stat/RESULT (#4450) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index d3244669c..6d615b0a7 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -340,7 +340,7 @@ #define USE_DISPLAY // Add SPI Display support for 320x240 and 480x320 TFT #endif #define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display (+19k code) -// #define USE_DISPLAY_EPAPER // [DisplayModel 5] Enable e-paper display (+19k code) +// #define USE_DISPLAY_EPAPER_29 // [DisplayModel 5] Enable e-paper 2.9 inch display (+19k code) #endif // USE_SPI // -- Serial sensors ------------------------------ diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 2e5e894ce..8859cca55 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -156,7 +156,7 @@ void GetFeatures(void) #ifdef USE_DISPLAY_ILI9341 feature_drv2 |= 0x00000400; // xdsp_04_ili9341.ino #endif -#ifdef USE_DISPLAY_EPAPER +#ifdef USE_DISPLAY_EPAPER_29 feature_drv2 |= 0x00000800; // xdsp_05_epaper.ino #endif #ifdef USE_DISPLAY_SH1106 diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 93f61c739..f585f842c 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -23,7 +23,7 @@ #define XDRV_13 13 #define DISPLAY_MAX_DRIVERS 16 // Max number of display drivers/models supported by xdsp_interface.ino -#define DISPLAY_MAX_COLS 40 // Max number of columns allowed with command DisplayCols +#define DISPLAY_MAX_COLS 44 // Max number of columns allowed with command DisplayCols #define DISPLAY_MAX_ROWS 32 // Max number of lines allowed with command DisplayRows #define DISPLAY_LOG_ROWS 32 // Number of lines in display log buffer @@ -1066,7 +1066,7 @@ boolean Xdrv13(byte function) { boolean result = false; - if ((i2c_flg || spi_flg) && XdspPresent()) { + if ((i2c_flg || spi_flg || soft_spi_flg) && XdspPresent()) { switch (function) { case FUNC_PRE_INIT: DisplayInitDriver(); diff --git a/sonoff/xdsp_05_epaper.ino b/sonoff/xdsp_05_epaper_29.ino similarity index 67% rename from sonoff/xdsp_05_epaper.ino rename to sonoff/xdsp_05_epaper_29.ino index 3d5c5b4e6..24bb19655 100644 --- a/sonoff/xdsp_05_epaper.ino +++ b/sonoff/xdsp_05_epaper_29.ino @@ -1,5 +1,5 @@ /* - xdsp_05_epaper.ino - Display e-paper support for Sonoff-Tasmota + xdsp_05_epaper_29.ino - 2.9 Inch display e-paper support for Sonoff-Tasmota Copyright (C) 2018 Theo Arends, Gerhard Mutz and Waveshare @@ -23,6 +23,9 @@ #define XDSP_05 5 +#define EPD_TOP 12 +#define EPD_FONT_HEIGTH 12 + #define COLORED 0 #define UNCOLORED 1 @@ -39,6 +42,8 @@ Paint paint(image, EPD_WIDTH, EPD_HEIGHT); // width should be the multiple of Epd epd; sFONT *selected_font; +uint16_t epd_scroll; + /*********************************************************************************************/ void EpdInitMode(void) @@ -70,6 +75,8 @@ void EpdInitMode(void) delay(1000); */ paint.Clear(UNCOLORED); + + epd_scroll = EPD_TOP; } void EpdInitPartial(void) @@ -111,11 +118,18 @@ void EpdInitDriver(void) } if (XDSP_05 == Settings.display_model) { - epd.cs_pin = pin[GPIO_SPI_CS]; - epd.mosi_pin = pin[GPIO_SPI_MOSI]; // 13 - epd.sclk_pin = pin[GPIO_SPI_CLK]; // 14 - - EpdInitMode(); + if ((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CLK] < 99) && (pin[GPIO_SPI_MOSI] < 99)) { + epd.cs_pin = pin[GPIO_SPI_CS]; + epd.sclk_pin = pin[GPIO_SPI_CLK]; // 14 + epd.mosi_pin = pin[GPIO_SPI_MOSI]; // 13 + EpdInitMode(); + } + else if ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_MOSI] < 99)) { + epd.cs_pin = pin[GPIO_SSPI_CS]; + epd.sclk_pin = pin[GPIO_SSPI_SCLK]; + epd.mosi_pin = pin[GPIO_SSPI_MOSI]; + EpdInitMode(); + } } } @@ -143,6 +157,12 @@ void EpdSetFont(uint8_t font) } } +void EpdDisplayFrame(void) +{ + epd.SetFrameMemory(paint.GetImage(), 0, 0, paint.GetWidth(), paint.GetHeight()); + epd.DisplayFrame(); +} + void EpdDrawStringAt(uint16_t x, uint16_t y, char *str, uint8_t color, uint8_t flag) { if (!flag) { @@ -167,10 +187,72 @@ void EpdOnOff(void) #ifdef USE_DISPLAY_MODES1TO5 +void EpdPrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (Settings.display_rotate) { + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + } + + char* txt = DisplayLogBuffer('\040'); + if (txt != NULL) { + byte size = Settings.display_size; + uint16_t theight = size * EPD_FONT_HEIGTH; + + EpdSetFont(size); + uint8_t last_row = Settings.display_rows -1; + +// epd_scroll = theight; // Start below header + epd_scroll = 0; // Start at top with no header + for (byte i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + EpdDrawStringAt(0, epd_scroll, disp_screen_buffer[i], COLORED, 0); + epd_scroll += theight; + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + EpdDrawStringAt(0, epd_scroll, disp_screen_buffer[last_row], COLORED, 0); +// EpdDisplayFrame(); + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "[%s]"), txt); + AddLog(LOG_LEVEL_DEBUG); + } + } +} + void EpdRefresh(void) // Every second { if (Settings.display_mode) { // Mode 0 is User text +/* + char tftdt[Settings.display_cols[0] +1]; + char date4[11]; // 24-04-2017 + char space[Settings.display_cols[0] - 17]; + char time[9]; // 13:45:43 + EpdSetFont(1); + + snprintf_P(date4, sizeof(date4), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + memset(space, 0x20, sizeof(space)); + space[sizeof(space) -1] = '\0'; + snprintf_P(time, sizeof(time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + snprintf_P(tftdt, sizeof(tftdt), PSTR("%s%s%s"), date4, space, time); + + EpdDrawStringAt(0, 0, tftdt, COLORED, 0); +*/ + switch (Settings.display_mode) { + case 1: // Text + case 2: // Local + case 3: // Local + case 4: // Mqtt + case 5: // Mqtt + EpdPrintLog(); + EpdDisplayFrame(); + break; + } + +// EpdDisplayFrame(); } } @@ -184,7 +266,7 @@ boolean Xdsp05(byte function) { boolean result = false; - if (spi_flg) { + if (spi_flg || soft_spi_flg) { if (FUNC_DISPLAY_INIT_DRIVER == function) { EpdInitDriver(); } @@ -227,8 +309,7 @@ boolean Xdsp05(byte function) paint.DrawFilledRectangle(dsp_x, dsp_y, dsp_x + dsp_x2, dsp_y + dsp_y2, dsp_color); break; case FUNC_DISPLAY_DRAW_FRAME: - epd.SetFrameMemory(paint.GetImage(), 0, 0, paint.GetWidth(), paint.GetHeight()); - epd.DisplayFrame(); + EpdDisplayFrame(); break; case FUNC_DISPLAY_TEXT_SIZE: // EpdSetFontorSize(Settings.display_size); From b03c761eeed624dd70cfd506095f82265073fa64 Mon Sep 17 00:00:00 2001 From: Winston Ametsitsi Date: Wed, 28 Nov 2018 01:33:59 -0800 Subject: [PATCH 0632/2222] switch to using NewPing lib directly for sr04 add NewPing-1.9.1 lib --- lib/NewPing-1.9.1/README.md | 3 + .../NewPing15SensorsTimer.pde | 78 ++++ .../NewPing3Sensors/NewPing3Sensors.pde | 29 ++ .../NewPingEventTimer/NewPingEventTimer.pde | 46 +++ .../NewPingExample/NewPingExample.pde | 22 ++ .../NewPingTimerMedian/NewPingTimerMedian.pde | 60 +++ .../examples/TimerExample/TimerExample.pde | 25 ++ lib/NewPing-1.9.1/keywords.txt | 31 ++ lib/NewPing-1.9.1/library.properties | 10 + lib/NewPing-1.9.1/src/NewPing.cpp | 365 ++++++++++++++++++ lib/NewPing-1.9.1/src/NewPing.h | 275 +++++++++++++ sonoff/xsns_22_sr04.ino | 113 +----- 12 files changed, 962 insertions(+), 95 deletions(-) create mode 100644 lib/NewPing-1.9.1/README.md create mode 100644 lib/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde create mode 100644 lib/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde create mode 100644 lib/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde create mode 100644 lib/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde create mode 100644 lib/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde create mode 100644 lib/NewPing-1.9.1/examples/TimerExample/TimerExample.pde create mode 100644 lib/NewPing-1.9.1/keywords.txt create mode 100644 lib/NewPing-1.9.1/library.properties create mode 100644 lib/NewPing-1.9.1/src/NewPing.cpp create mode 100644 lib/NewPing-1.9.1/src/NewPing.h diff --git a/lib/NewPing-1.9.1/README.md b/lib/NewPing-1.9.1/README.md new file mode 100644 index 000000000..fe014a466 --- /dev/null +++ b/lib/NewPing-1.9.1/README.md @@ -0,0 +1,3 @@ +# NewPing Arduino Library for Arduino + +## See the [NewPing Wiki](https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home) for documentation \ No newline at end of file diff --git a/lib/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde b/lib/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde new file mode 100644 index 000000000..b555c0be7 --- /dev/null +++ b/lib/NewPing-1.9.1/examples/NewPing15SensorsTimer/NewPing15SensorsTimer.pde @@ -0,0 +1,78 @@ +// --------------------------------------------------------------------------- +// Before attempting to use this sketch, please read the "Help with 15 Sensors Example Sketch": +// https://bitbucket.org/teckel12/arduino-new-ping/wiki/Help%20with%2015%20Sensors%20Example%20Sketch +// +// This example code was used to successfully communicate with 15 ultrasonic sensors. You can adjust +// the number of sensors in your project by changing SONAR_NUM and the number of NewPing objects in the +// "sonar" array. You also need to change the pins for each sensor for the NewPing objects. Each sensor +// is pinged at 33ms intervals. So, one cycle of all sensors takes 495ms (33 * 15 = 495ms). The results +// are sent to the "oneSensorCycle" function which currently just displays the distance data. Your project +// would normally process the sensor results in this function (for example, decide if a robot needs to +// turn and call the turn function). Keep in mind this example is event-driven. Your complete sketch needs +// to be written so there's no "delay" commands and the loop() cycles at faster than a 33ms rate. If other +// processes take longer than 33ms, you'll need to increase PING_INTERVAL so it doesn't get behind. +// --------------------------------------------------------------------------- +#include + +#define SONAR_NUM 15 // Number of sensors. +#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping. +#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo). + +unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor. +unsigned int cm[SONAR_NUM]; // Where the ping distances are stored. +uint8_t currentSensor = 0; // Keeps track of which sensor is active. + +NewPing sonar[SONAR_NUM] = { // Sensor object array. + NewPing(41, 42, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping. + NewPing(43, 44, MAX_DISTANCE), + NewPing(45, 20, MAX_DISTANCE), + NewPing(21, 22, MAX_DISTANCE), + NewPing(23, 24, MAX_DISTANCE), + NewPing(25, 26, MAX_DISTANCE), + NewPing(27, 28, MAX_DISTANCE), + NewPing(29, 30, MAX_DISTANCE), + NewPing(31, 32, MAX_DISTANCE), + NewPing(34, 33, MAX_DISTANCE), + NewPing(35, 36, MAX_DISTANCE), + NewPing(37, 38, MAX_DISTANCE), + NewPing(39, 40, MAX_DISTANCE), + NewPing(50, 51, MAX_DISTANCE), + NewPing(52, 53, MAX_DISTANCE) +}; + +void setup() { + Serial.begin(115200); + pingTimer[0] = millis() + 75; // First ping starts at 75ms, gives time for the Arduino to chill before starting. + for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor. + pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL; +} + +void loop() { + for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors. + if (millis() >= pingTimer[i]) { // Is it this sensor's time to ping? + pingTimer[i] += PING_INTERVAL * SONAR_NUM; // Set next time this sensor will be pinged. + if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results. + sonar[currentSensor].timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance). + currentSensor = i; // Sensor being accessed. + cm[currentSensor] = 0; // Make distance zero in case there's no ping echo for this sensor. + sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo). + } + } + // Other code that *DOESN'T* analyze ping results can go here. +} + +void echoCheck() { // If ping received, set the sensor distance to array. + if (sonar[currentSensor].check_timer()) + cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM; +} + +void oneSensorCycle() { // Sensor ping cycle complete, do something with the results. + // The following code would be replaced with your code that does something with the ping results. + for (uint8_t i = 0; i < SONAR_NUM; i++) { + Serial.print(i); + Serial.print("="); + Serial.print(cm[i]); + Serial.print("cm "); + } + Serial.println(); +} \ No newline at end of file diff --git a/lib/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde b/lib/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde new file mode 100644 index 000000000..4429fd850 --- /dev/null +++ b/lib/NewPing-1.9.1/examples/NewPing3Sensors/NewPing3Sensors.pde @@ -0,0 +1,29 @@ +// --------------------------------------------------------------------------- +// Example NewPing library sketch that pings 3 sensors 20 times a second. +// --------------------------------------------------------------------------- + +#include + +#define SONAR_NUM 3 // Number of sensors. +#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping. + +NewPing sonar[SONAR_NUM] = { // Sensor object array. + NewPing(4, 5, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping. + NewPing(6, 7, MAX_DISTANCE), + NewPing(8, 9, MAX_DISTANCE) +}; + +void setup() { + Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results. +} + +void loop() { + for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through each sensor and display results. + delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings. + Serial.print(i); + Serial.print("="); + Serial.print(sonar[i].ping_cm()); + Serial.print("cm "); + } + Serial.println(); +} \ No newline at end of file diff --git a/lib/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde b/lib/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde new file mode 100644 index 000000000..d9d26673e --- /dev/null +++ b/lib/NewPing-1.9.1/examples/NewPingEventTimer/NewPingEventTimer.pde @@ -0,0 +1,46 @@ +// --------------------------------------------------------------------------- +// This example shows how to use NewPing's ping_timer method which uses the Timer2 interrupt to get the +// ping time. The advantage of using this method over the standard ping method is that it permits a more +// event-driven sketch which allows you to appear to do two things at once. An example would be to ping +// an ultrasonic sensor for a possible collision while at the same time navigating. This allows a +// properly developed sketch to multitask. Be aware that because the ping_timer method uses Timer2, +// other features or libraries that also use Timer2 would be effected. For example, the PWM function on +// pins 3 & 11 on Arduino Uno (pins 9 and 11 on Arduino Mega) and the Tone library. Note, only the PWM +// functionality of the pins is lost (as they use Timer2 to do PWM), the pins are still available to use. +// NOTE: For Teensy/Leonardo (ATmega32U4) the library uses Timer4 instead of Timer2. +// --------------------------------------------------------------------------- +#include + +#define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on ping sensor. +#define ECHO_PIN 11 // Arduino pin tied to echo pin on ping sensor. +#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. + +NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. + +unsigned int pingSpeed = 50; // How frequently are we going to send out a ping (in milliseconds). 50ms would be 20 times a second. +unsigned long pingTimer; // Holds the next ping time. + +void setup() { + Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results. + pingTimer = millis(); // Start now. +} + +void loop() { + // Notice how there's no delays in this sketch to allow you to do other processing in-line while doing distance pings. + if (millis() >= pingTimer) { // pingSpeed milliseconds since last ping, do another ping. + pingTimer += pingSpeed; // Set the next ping time. + sonar.ping_timer(echoCheck); // Send out the ping, calls "echoCheck" function every 24uS where you can check the ping status. + } + // Do other stuff here, really. Think of it as multi-tasking. +} + +void echoCheck() { // Timer2 interrupt calls this function every 24uS where you can check the ping status. + // Don't do anything here! + if (sonar.check_timer()) { // This is how you check to see if the ping was received. + // Here's where you can add code. + Serial.print("Ping: "); + Serial.print(sonar.ping_result / US_ROUNDTRIP_CM); // Ping returned, uS result in ping_result, convert to cm with US_ROUNDTRIP_CM. + Serial.println("cm"); + } + // Don't do anything here! +} \ No newline at end of file diff --git a/lib/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde b/lib/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde new file mode 100644 index 000000000..12f6fdaaf --- /dev/null +++ b/lib/NewPing-1.9.1/examples/NewPingExample/NewPingExample.pde @@ -0,0 +1,22 @@ +// --------------------------------------------------------------------------- +// Example NewPing library sketch that does a ping about 20 times per second. +// --------------------------------------------------------------------------- + +#include + +#define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic sensor. +#define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic sensor. +#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. + +NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. + +void setup() { + Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results. +} + +void loop() { + delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings. + Serial.print("Ping: "); + Serial.print(sonar.ping_cm()); // Send ping, get distance in cm and print result (0 = outside set distance range) + Serial.println("cm"); +} \ No newline at end of file diff --git a/lib/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde b/lib/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde new file mode 100644 index 000000000..93027afd7 --- /dev/null +++ b/lib/NewPing-1.9.1/examples/NewPingTimerMedian/NewPingTimerMedian.pde @@ -0,0 +1,60 @@ +// --------------------------------------------------------------------------- +// Calculate a ping median using the ping_timer() method. +// --------------------------------------------------------------------------- + +#include + +#define ITERATIONS 5 // Number of iterations. +#define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on ping sensor. +#define ECHO_PIN 11 // Arduino pin tied to echo pin on ping sensor. +#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping. +#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo). + +unsigned long pingTimer[ITERATIONS]; // Holds the times when the next ping should happen for each iteration. +unsigned int cm[ITERATIONS]; // Where the ping distances are stored. +uint8_t currentIteration = 0; // Keeps track of iteration step. + +NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance. + +void setup() { + Serial.begin(115200); + pingTimer[0] = millis() + 75; // First ping starts at 75ms, gives time for the Arduino to chill before starting. + for (uint8_t i = 1; i < ITERATIONS; i++) // Set the starting time for each iteration. + pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL; +} + +void loop() { + for (uint8_t i = 0; i < ITERATIONS; i++) { // Loop through all the iterations. + if (millis() >= pingTimer[i]) { // Is it this iteration's time to ping? + pingTimer[i] += PING_INTERVAL * ITERATIONS; // Set next time this sensor will be pinged. + if (i == 0 && currentIteration == ITERATIONS - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results. + sonar.timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance). + currentIteration = i; // Sensor being accessed. + cm[currentIteration] = 0; // Make distance zero in case there's no ping echo for this iteration. + sonar.ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo). + } + } + // Other code that *DOESN'T* analyze ping results can go here. +} + +void echoCheck() { // If ping received, set the sensor distance to array. + if (sonar.check_timer()) + cm[currentIteration] = sonar.ping_result / US_ROUNDTRIP_CM; +} + +void oneSensorCycle() { // All iterations complete, calculate the median. + unsigned int uS[ITERATIONS]; + uint8_t j, it = ITERATIONS; + uS[0] = NO_ECHO; + for (uint8_t i = 0; i < it; i++) { // Loop through iteration results. + if (cm[i] != NO_ECHO) { // Ping in range, include as part of median. + if (i > 0) { // Don't start sort till second ping. + for (j = i; j > 0 && uS[j - 1] < cm[i]; j--) // Insertion sort loop. + uS[j] = uS[j - 1]; // Shift ping array to correct position for sort insertion. + } else j = 0; // First ping is sort starting point. + uS[j] = cm[i]; // Add last ping to array in sorted position. + } else it--; // Ping out of range, skip and don't include as part of median. + } + Serial.print(uS[it >> 1]); + Serial.println("cm"); +} \ No newline at end of file diff --git a/lib/NewPing-1.9.1/examples/TimerExample/TimerExample.pde b/lib/NewPing-1.9.1/examples/TimerExample/TimerExample.pde new file mode 100644 index 000000000..ea66039ee --- /dev/null +++ b/lib/NewPing-1.9.1/examples/TimerExample/TimerExample.pde @@ -0,0 +1,25 @@ +// --------------------------------------------------------------------------- +// While the NewPing library's primary goal is to interface with ultrasonic sensors, interfacing with +// the Timer2 interrupt was a result of creating an interrupt-based ping method. Since these Timer2 +// interrupt methods were built, the library may as well provide the functionality to use these methods +// in your sketches. This shows how simple it is (no ultrasonic sensor required). Keep in mind that +// these methods use Timer2, as does NewPing's ping_timer method for using ultrasonic sensors. You +// can't use ping_timer at the same time you're using timer_ms or timer_us as all use the same timer. +// --------------------------------------------------------------------------- + +#include + +#define LED_PIN 13 // Pin with LED attached. + +void setup() { + pinMode(LED_PIN, OUTPUT); + NewPing::timer_ms(500, toggleLED); // Create a Timer2 interrupt that calls toggleLED in your sketch once every 500 milliseconds. +} + +void loop() { + // Do anything here, the Timer2 interrupt will take care of the flashing LED without your intervention. +} + +void toggleLED() { + digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Toggle the LED. +} \ No newline at end of file diff --git a/lib/NewPing-1.9.1/keywords.txt b/lib/NewPing-1.9.1/keywords.txt new file mode 100644 index 000000000..dde5a73d1 --- /dev/null +++ b/lib/NewPing-1.9.1/keywords.txt @@ -0,0 +1,31 @@ +################################### +# Syntax Coloring Map For NewPing +################################### + +################################### +# Datatypes (KEYWORD1) +################################### + +NewPing KEYWORD1 + +################################### +# Methods and Functions (KEYWORD2) +################################### + +ping KEYWORD2 +ping_in KEYWORD2 +ping_cm KEYWORD2 +ping_median KEYWORD2 +ping_timer KEYWORD2 +check_timer KEYWORD2 +ping_result KEYWORD2 +timer_us KEYWORD2 +timer_ms KEYWORD2 +timer_stop KEYWORD2 +convert_in KEYWORD2 +convert_cm KEYWORD2 + +################################### +# Constants (LITERAL1) +################################### + diff --git a/lib/NewPing-1.9.1/library.properties b/lib/NewPing-1.9.1/library.properties new file mode 100644 index 000000000..2accb6c86 --- /dev/null +++ b/lib/NewPing-1.9.1/library.properties @@ -0,0 +1,10 @@ +name=NewPing +version=1.9.1 +author=Tim Eckel +maintainer=Tim Eckel +sentence=A library that makes working with ultrasonic sensors easy. +paragraph=When I first received an ultrasonic sensor I was not happy with how poorly it performed. I soon realized the problem was not the sensor, it was the available ping and ultrasonic libraries causing the problem. The NewPing library totally fixes these problems, adds many new features, and breathes new life into these very affordable distance sensors. +category=Sensors +url=https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home +architectures=avr,arm +includes=NewPing.h \ No newline at end of file diff --git a/lib/NewPing-1.9.1/src/NewPing.cpp b/lib/NewPing-1.9.1/src/NewPing.cpp new file mode 100644 index 000000000..ac0d397a4 --- /dev/null +++ b/lib/NewPing-1.9.1/src/NewPing.cpp @@ -0,0 +1,365 @@ +// --------------------------------------------------------------------------- +// Created by Tim Eckel - teckel@leethost.com +// +// See NewPing.h for license, purpose, syntax, version history, links, etc. +// --------------------------------------------------------------------------- + +#include "NewPing.h" + + +// --------------------------------------------------------------------------- +// NewPing constructor +// --------------------------------------------------------------------------- + +NewPing::NewPing(uint8_t trigger_pin, uint8_t echo_pin, unsigned int max_cm_distance) { +#if DO_BITWISE == true + _triggerBit = digitalPinToBitMask(trigger_pin); // Get the port register bitmask for the trigger pin. + _echoBit = digitalPinToBitMask(echo_pin); // Get the port register bitmask for the echo pin. + + _triggerOutput = portOutputRegister(digitalPinToPort(trigger_pin)); // Get the output port register for the trigger pin. + _echoInput = portInputRegister(digitalPinToPort(echo_pin)); // Get the input port register for the echo pin. + + _triggerMode = (uint8_t *) portModeRegister(digitalPinToPort(trigger_pin)); // Get the port mode register for the trigger pin. +#else + _triggerPin = trigger_pin; + _echoPin = echo_pin; +#endif + + set_max_distance(max_cm_distance); // Call function to set the max sensor distance. + +#if (defined (__arm__) && (defined (TEENSYDUINO) || defined(PARTICLE))) || DO_BITWISE != true + pinMode(echo_pin, INPUT); // Set echo pin to input (on Teensy 3.x (ARM), pins default to disabled, at least one pinMode() is needed for GPIO mode). + pinMode(trigger_pin, OUTPUT); // Set trigger pin to output (on Teensy 3.x (ARM), pins default to disabled, at least one pinMode() is needed for GPIO mode). +#endif + +#if defined (ARDUINO_AVR_YUN) + pinMode(echo_pin, INPUT); // Set echo pin to input for the Arduino Yun, not sure why it doesn't default this way. +#endif + +#if ONE_PIN_ENABLED != true && DO_BITWISE == true + *_triggerMode |= _triggerBit; // Set trigger pin to output. +#endif +} + + +// --------------------------------------------------------------------------- +// Standard ping methods +// --------------------------------------------------------------------------- + +unsigned int NewPing::ping(unsigned int max_cm_distance) { + if (max_cm_distance > 0) set_max_distance(max_cm_distance); // Call function to set a new max sensor distance. + + if (!ping_trigger()) return NO_ECHO; // Trigger a ping, if it returns false, return NO_ECHO to the calling function. + +#if URM37_ENABLED == true + #if DO_BITWISE == true + while (!(*_echoInput & _echoBit)) // Wait for the ping echo. + #else + while (!digitalRead(_echoPin)) // Wait for the ping echo. + #endif + if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance. +#else + #if DO_BITWISE == true + while (*_echoInput & _echoBit) // Wait for the ping echo. + #else + while (digitalRead(_echoPin)) // Wait for the ping echo. + #endif + if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance. +#endif + + return (micros() - (_max_time - _maxEchoTime) - PING_OVERHEAD); // Calculate ping time, include overhead. +} + + +unsigned long NewPing::ping_cm(unsigned int max_cm_distance) { + unsigned long echoTime = NewPing::ping(max_cm_distance); // Calls the ping method and returns with the ping echo distance in uS. +#if ROUNDING_ENABLED == false + return (echoTime / US_ROUNDTRIP_CM); // Call the ping method and returns the distance in centimeters (no rounding). +#else + return NewPingConvert(echoTime, US_ROUNDTRIP_CM); // Convert uS to centimeters. +#endif +} + + +unsigned long NewPing::ping_in(unsigned int max_cm_distance) { + unsigned long echoTime = NewPing::ping(max_cm_distance); // Calls the ping method and returns with the ping echo distance in uS. +#if ROUNDING_ENABLED == false + return (echoTime / US_ROUNDTRIP_IN); // Call the ping method and returns the distance in inches (no rounding). +#else + return NewPingConvert(echoTime, US_ROUNDTRIP_IN); // Convert uS to inches. +#endif +} + + +unsigned long NewPing::ping_median(uint8_t it, unsigned int max_cm_distance) { + unsigned int uS[it], last; + uint8_t j, i = 0; + unsigned long t; + uS[0] = NO_ECHO; + + while (i < it) { + t = micros(); // Start ping timestamp. + last = ping(max_cm_distance); // Send ping. + + if (last != NO_ECHO) { // Ping in range, include as part of median. + if (i > 0) { // Don't start sort till second ping. + for (j = i; j > 0 && uS[j - 1] < last; j--) // Insertion sort loop. + uS[j] = uS[j - 1]; // Shift ping array to correct position for sort insertion. + } else j = 0; // First ping is sort starting point. + uS[j] = last; // Add last ping to array in sorted position. + i++; // Move to next ping. + } else it--; // Ping out of range, skip and don't include as part of median. + + if (i < it && micros() - t < PING_MEDIAN_DELAY) + delay((PING_MEDIAN_DELAY + t - micros()) / 1000); // Millisecond delay between pings. + + } + return (uS[it >> 1]); // Return the ping distance median. +} + + +// --------------------------------------------------------------------------- +// Standard and timer interrupt ping method support functions (not called directly) +// --------------------------------------------------------------------------- + +boolean NewPing::ping_trigger() { +#if DO_BITWISE == true + #if ONE_PIN_ENABLED == true + *_triggerMode |= _triggerBit; // Set trigger pin to output. + #endif + + *_triggerOutput &= ~_triggerBit; // Set the trigger pin low, should already be low, but this will make sure it is. + delayMicroseconds(4); // Wait for pin to go low. + *_triggerOutput |= _triggerBit; // Set trigger pin high, this tells the sensor to send out a ping. + delayMicroseconds(10); // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10uS. + *_triggerOutput &= ~_triggerBit; // Set trigger pin back to low. + + #if ONE_PIN_ENABLED == true + *_triggerMode &= ~_triggerBit; // Set trigger pin to input (when using one Arduino pin, this is technically setting the echo pin to input as both are tied to the same Arduino pin). + #endif + + #if URM37_ENABLED == true + if (!(*_echoInput & _echoBit)) return false; // Previous ping hasn't finished, abort. + _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!) + while (*_echoInput & _echoBit) // Wait for ping to start. + if (micros() > _max_time) return false; // Took too long to start, abort. + #else + if (*_echoInput & _echoBit) return false; // Previous ping hasn't finished, abort. + _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!) + while (!(*_echoInput & _echoBit)) // Wait for ping to start. + if (micros() > _max_time) return false; // Took too long to start, abort. + #endif +#else + #if ONE_PIN_ENABLED == true + pinMode(_triggerPin, OUTPUT); // Set trigger pin to output. + #endif + + digitalWrite(_triggerPin, LOW); // Set the trigger pin low, should already be low, but this will make sure it is. + delayMicroseconds(4); // Wait for pin to go low. + digitalWrite(_triggerPin, HIGH); // Set trigger pin high, this tells the sensor to send out a ping. + delayMicroseconds(10); // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10uS. + digitalWrite(_triggerPin, LOW); // Set trigger pin back to low. + + #if ONE_PIN_ENABLED == true + pinMode(_triggerPin, INPUT); // Set trigger pin to input (when using one Arduino pin, this is technically setting the echo pin to input as both are tied to the same Arduino pin). + #endif + + #if URM37_ENABLED == true + if (!digitalRead(_echoPin)) return false; // Previous ping hasn't finished, abort. + _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!) + while (digitalRead(_echoPin)) // Wait for ping to start. + if (micros() > _max_time) return false; // Took too long to start, abort. + #else + if (digitalRead(_echoPin)) return false; // Previous ping hasn't finished, abort. + _max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!) + while (!digitalRead(_echoPin)) // Wait for ping to start. + if (micros() > _max_time) return false; // Took too long to start, abort. + #endif +#endif + + _max_time = micros() + _maxEchoTime; // Ping started, set the time-out. + return true; // Ping started successfully. +} + + +void NewPing::set_max_distance(unsigned int max_cm_distance) { +#if ROUNDING_ENABLED == false + _maxEchoTime = min(max_cm_distance + 1, (unsigned int) MAX_SENSOR_DISTANCE + 1) * US_ROUNDTRIP_CM; // Calculate the maximum distance in uS (no rounding). +#else + _maxEchoTime = min(max_cm_distance, (unsigned int) MAX_SENSOR_DISTANCE) * US_ROUNDTRIP_CM + (US_ROUNDTRIP_CM / 2); // Calculate the maximum distance in uS. +#endif +} + + +#if TIMER_ENABLED == true && DO_BITWISE == true + + // --------------------------------------------------------------------------- + // Timer interrupt ping methods (won't work with ATmega128, ATtiny and most non-AVR microcontrollers) + // --------------------------------------------------------------------------- + + void NewPing::ping_timer(void (*userFunc)(void), unsigned int max_cm_distance) { + if (max_cm_distance > 0) set_max_distance(max_cm_distance); // Call function to set a new max sensor distance. + + if (!ping_trigger()) return; // Trigger a ping, if it returns false, return without starting the echo timer. + timer_us(ECHO_TIMER_FREQ, userFunc); // Set ping echo timer check every ECHO_TIMER_FREQ uS. + } + + + boolean NewPing::check_timer() { + if (micros() > _max_time) { // Outside the time-out limit. + timer_stop(); // Disable timer interrupt + return false; // Cancel ping timer. + } + + #if URM37_ENABLED == false + if (!(*_echoInput & _echoBit)) { // Ping echo received. + #else + if (*_echoInput & _echoBit) { // Ping echo received. + #endif + timer_stop(); // Disable timer interrupt + ping_result = (micros() - (_max_time - _maxEchoTime) - PING_TIMER_OVERHEAD); // Calculate ping time including overhead. + return true; // Return ping echo true. + } + + return false; // Return false because there's no ping echo yet. + } + + + // --------------------------------------------------------------------------- + // Timer2/Timer4 interrupt methods (can be used for non-ultrasonic needs) + // --------------------------------------------------------------------------- + + // Variables used for timer functions + void (*intFunc)(); + void (*intFunc2)(); + unsigned long _ms_cnt_reset; + volatile unsigned long _ms_cnt; + #if defined(__arm__) && (defined (TEENSYDUINO) || defined(PARTICLE)) + IntervalTimer itimer; + #endif + + + void NewPing::timer_us(unsigned int frequency, void (*userFunc)(void)) { + intFunc = userFunc; // User's function to call when there's a timer event. + timer_setup(); // Configure the timer interrupt. + + #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo). + OCR4C = min((frequency>>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit. + TIMSK4 = (1<>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit. + TIMSK2 |= (1<= 100 + #include + #else + #include + #if defined (PARTICLE) + #include + #else + #include + #endif + #endif + + #if defined (__AVR__) + #include + #include + #endif + + // Shouldn't need to change these values unless you have a specific need to do so. + #define MAX_SENSOR_DISTANCE 500 // Maximum sensor distance can be as high as 500cm, no reason to wait for ping longer than sound takes to travel this distance and back. Default=500 + #define US_ROUNDTRIP_CM 57 // Microseconds (uS) it takes sound to travel round-trip 1cm (2cm total), uses integer to save compiled code space. Default=57 + #define US_ROUNDTRIP_IN 146 // Microseconds (uS) it takes sound to travel round-trip 1 inch (2 inches total), uses integer to save compiled code space. Defalult=146 + #define ONE_PIN_ENABLED true // Set to "false" to disable one pin mode which saves around 14-26 bytes of binary size. Default=true + #define ROUNDING_ENABLED false // Set to "true" to enable distance rounding which also adds 64 bytes to binary size. Default=false + #define URM37_ENABLED false // Set to "true" to enable support for the URM37 sensor in PWM mode. Default=false + #define TIMER_ENABLED true // Set to "false" to disable the timer ISR (if getting "__vector_7" compile errors set this to false). Default=true + + // Probably shouldn't change these values unless you really know what you're doing. + #define NO_ECHO 0 // Value returned if there's no ping echo within the specified MAX_SENSOR_DISTANCE or max_cm_distance. Default=0 + #define MAX_SENSOR_DELAY 5800 // Maximum uS it takes for sensor to start the ping. Default=5800 + #define ECHO_TIMER_FREQ 24 // Frequency to check for a ping echo (every 24uS is about 0.4cm accuracy). Default=24 + #define PING_MEDIAN_DELAY 29000 // Microsecond delay between pings in the ping_median method. Default=29000 + #define PING_OVERHEAD 5 // Ping overhead in microseconds (uS). Default=5 + #define PING_TIMER_OVERHEAD 13 // Ping timer overhead in microseconds (uS). Default=13 + #if URM37_ENABLED == true + #undef US_ROUNDTRIP_CM + #undef US_ROUNDTRIP_IN + #define US_ROUNDTRIP_CM 50 // Every 50uS PWM signal is low indicates 1cm distance. Default=50 + #define US_ROUNDTRIP_IN 127 // If 50uS is 1cm, 1 inch would be 127uS (50 x 2.54 = 127). Default=127 + #endif + + // Conversion from uS to distance (round result to nearest cm or inch). + #define NewPingConvert(echoTime, conversionFactor) (max(((unsigned int)echoTime + conversionFactor / 2) / conversionFactor, (echoTime ? 1 : 0))) + + // Detect non-AVR microcontrollers (Teensy 3.x, Arduino DUE, etc.) and don't use port registers or timer interrupts as required. + #if (defined (__arm__) && (defined (TEENSYDUINO) || defined (PARTICLE))) + #undef PING_OVERHEAD + #define PING_OVERHEAD 1 + #undef PING_TIMER_OVERHEAD + #define PING_TIMER_OVERHEAD 1 + #define DO_BITWISE true + #elif !defined (__AVR__) + #undef PING_OVERHEAD + #define PING_OVERHEAD 1 + #undef PING_TIMER_OVERHEAD + #define PING_TIMER_OVERHEAD 1 + #undef TIMER_ENABLED + #define TIMER_ENABLED false + #define DO_BITWISE false + #else + #define DO_BITWISE true + #endif + + // Disable the timer interrupts when using ATmega128 and all ATtiny microcontrollers. + #if defined (__AVR_ATmega128__) || defined (__AVR_ATtiny24__) || defined (__AVR_ATtiny44__) || defined (__AVR_ATtiny441__) || defined (__AVR_ATtiny84__) || defined (__AVR_ATtiny841__) || defined (__AVR_ATtiny25__) || defined (__AVR_ATtiny45__) || defined (__AVR_ATtiny85__) || defined (__AVR_ATtiny261__) || defined (__AVR_ATtiny461__) || defined (__AVR_ATtiny861__) || defined (__AVR_ATtiny43U__) + #undef TIMER_ENABLED + #define TIMER_ENABLED false + #endif + + // Define timers when using ATmega8, ATmega16, ATmega32 and ATmega8535 microcontrollers. + #if defined (__AVR_ATmega8__) || defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega8535__) + #define OCR2A OCR2 + #define TIMSK2 TIMSK + #define OCIE2A OCIE2 + #endif + + class NewPing { + public: + NewPing(uint8_t trigger_pin, uint8_t echo_pin, unsigned int max_cm_distance = MAX_SENSOR_DISTANCE); + unsigned int ping(unsigned int max_cm_distance = 0); + unsigned long ping_cm(unsigned int max_cm_distance = 0); + unsigned long ping_in(unsigned int max_cm_distance = 0); + unsigned long ping_median(uint8_t it = 5, unsigned int max_cm_distance = 0); + static unsigned int convert_cm(unsigned int echoTime); + static unsigned int convert_in(unsigned int echoTime); + #if TIMER_ENABLED == true + void ping_timer(void (*userFunc)(void), unsigned int max_cm_distance = 0); + boolean check_timer(); + unsigned long ping_result; + static void timer_us(unsigned int frequency, void (*userFunc)(void)); + static void timer_ms(unsigned long frequency, void (*userFunc)(void)); + static void timer_stop(); + #endif + private: + boolean ping_trigger(); + void set_max_distance(unsigned int max_cm_distance); + #if TIMER_ENABLED == true + boolean ping_trigger_timer(unsigned int trigger_delay); + boolean ping_wait_timer(); + static void timer_setup(); + static void timer_ms_cntdwn(); + #endif + #if DO_BITWISE == true + uint8_t _triggerBit; + uint8_t _echoBit; + #if defined(PARTICLE) + #if !defined(portModeRegister) + #if defined (STM32F10X_MD) + #define portModeRegister(port) ( &(port->CRL) ) + #elif defined (STM32F2XX) + #define portModeRegister(port) ( &(port->MODER) ) + #endif + #endif + volatile uint32_t *_triggerOutput; + volatile uint32_t *_echoInput; + volatile uint32_t *_triggerMode; + #else + volatile uint8_t *_triggerOutput; + volatile uint8_t *_echoInput; + volatile uint8_t *_triggerMode; + #endif + #else + uint8_t _triggerPin; + uint8_t _echoPin; + #endif + unsigned int _maxEchoTime; + unsigned long _max_time; + }; + + +#endif diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index b361b7e96..32f09bd20 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -18,6 +18,8 @@ */ #ifdef USE_SR04 + +#include /*********************************************************************************************\ * HC-SR04, HC-SR04+, JSN-SR04T - Ultrasonic distance sensor * @@ -26,124 +28,43 @@ * - https://www.dfrobot.com/wiki/index.php/Weather-proof_Ultrasonic_Sensor_SKU_:_SEN0207 \*********************************************************************************************/ -#define XSNS_22 22 - uint8_t sr04_echo_pin = 0; uint8_t sr04_trig_pin = 0; +real64_t distance; -/*********************************************************************************************\ - * Embedded stripped and tuned NewPing library from Tim Eckel - teckel@leethost.com - * https://bitbucket.org/teckel12/arduino-new-ping -\*********************************************************************************************/ -#define US_ROUNDTRIP_CM 58 // Microseconds (uS) it takes sound to travel round-trip 1cm (2cm total), uses integer to save compiled code space. Default: 58 -#define US_ROUNDTRIP_IN 148 // Microseconds (uS) it takes sound to travel round-trip 1 inch (2 inches total), uses integer to save compiled code space. Default: 148 -#define PING_MEDIAN_DELAY 29000 -#define MAX_SENSOR_DISTANCE 500 -#define PING_OVERHEAD 5 +NewPing* sonar = NULL; -// Conversion from uS to distance (round result to nearest cm or inch). -#define EchoConvert(echoTime, conversionFactor) (tmax(((unsigned int)echoTime + conversionFactor / 2) / conversionFactor, (echoTime ? 1 : 0))) - -/********************************************************************************************/ - -void Sr04Init(void) +void Sr04Init() { sr04_echo_pin = pin[GPIO_SR04_ECHO]; sr04_trig_pin = pin[GPIO_SR04_TRIG]; - pinMode(sr04_trig_pin, OUTPUT); - pinMode(sr04_echo_pin, INPUT_PULLUP); -} - -boolean Sr04Read(uint16_t *distance) -{ - uint16_t duration = 0; - - *distance = 0; - - /* Send ping and get delay */ - duration = Sr04GetSamples(9, 250); - - /* Calculate the distance (in cm) based on the speed of sound. */ - *distance = EchoConvert(duration, US_ROUNDTRIP_CM); - - return 1; -} - -uint16_t Sr04Ping(uint16_t max_cm_distance) -{ - uint16_t duration = 0; - uint16_t maxEchoTime; - - maxEchoTime = tmin(max_cm_distance + 1, (uint16_t) MAX_SENSOR_DISTANCE + 1) * US_ROUNDTRIP_CM; - - /* The following trigPin/echoPin cycle is used to determine the - distance of the nearest object by bouncing soundwaves off of it. */ - digitalWrite(sr04_trig_pin, LOW); - delayMicroseconds(2); - digitalWrite(sr04_trig_pin, HIGH); - delayMicroseconds(10); - digitalWrite(sr04_trig_pin, LOW); - - /* Wait for the echo */ - duration = pulseIn(sr04_echo_pin, HIGH, 26000) - PING_OVERHEAD; - - return (duration > maxEchoTime) ? 0 : duration; -} - -uint16_t Sr04GetSamples(uint8_t it, uint16_t max_cm_distance) -{ - uint16_t uS[it]; - uint16_t last; - uint8_t j; - uint8_t i = 0; - uint16_t t; - uS[0] = 0; - - while (i < it) { - t = micros(); - last = Sr04Ping(max_cm_distance); - - if (last != 0) { - if (i > 0) { - for (j = i; j > 0 && uS[j - 1] < last; j--) { - uS[j] = uS[j - 1]; - } - } else { - j = 0; - } - uS[j] = last; - i++; - } else { - it--; - } - if (i < it && micros() - t < PING_MEDIAN_DELAY) { - delay((PING_MEDIAN_DELAY + t - micros()) / 1000); - } - } - - return (uS[1]); // Return the ping distance from the 2nd highest reading + sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300); } #ifdef USE_WEBSERVER const char HTTP_SNS_DISTANCE[] PROGMEM = - "%s{s}SR04 " D_DISTANCE "{m}%d" D_UNIT_CENTIMETER "{e}"; // {s} =
          + "%s{s}SR04 " D_DISTANCE "{m}%s" D_UNIT_CENTIMETER "{e}"; // {s} = #endif // USE_WEBSERVER void Sr04Show(boolean json) { - uint16_t distance; + distance = (real64_t)(sonar->ping_median(5))/ US_ROUNDTRIP_CM; + + if (distance != 0) { // Check if read failed + char distance_chr[10]; + + dtostrfd(distance, 3, distance_chr); - if (Sr04Read(&distance)) { // Check if read failed if(json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SR04\":{\"" D_JSON_DISTANCE "\":%d}"), mqtt_data, distance); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), mqtt_data, distance_chr); #ifdef USE_DOMOTICZ if (0 == tele_period) { - DomoticzSensor(DZ_COUNT, distance); // Send distance as Domoticz Counter value + DomoticzSensor(DZ_COUNT, distance_chr); // Send distance as Domoticz Counter value } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_DISTANCE, mqtt_data, distance); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_DISTANCE, mqtt_data, distance_chr); #endif // USE_WEBSERVER } } @@ -153,6 +74,8 @@ void Sr04Show(boolean json) * Interface \*********************************************************************************************/ +#define XSNS_22 + boolean Xsns22(byte function) { boolean result = false; From d7df73784fc47d23540d403cc686b835084cc509 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 30 Nov 2018 12:04:17 +0100 Subject: [PATCH 0633/2222] Housekeeping --- REFERENCE.md | 17 +++++++++++++++++ RELEASENOTES.md | 15 --------------- sonoff/_changelog.ino | 2 ++ 3 files changed, 19 insertions(+), 15 deletions(-) create mode 100644 REFERENCE.md diff --git a/REFERENCE.md b/REFERENCE.md new file mode 100644 index 000000000..22bd77899 --- /dev/null +++ b/REFERENCE.md @@ -0,0 +1,17 @@ +## Tasmota Reference +Tasmota backgound information. + +## Supported Smart Switch with Energy Monitoring GPIO usage +Module | GPIO00 | GPIO01 | GPIO02 | GPIO03 | GPIO04 | GPIO05 | GPIO12 | GPIO13 | GPIO14 | GPIO15 +-------|--------|--------|--------|--------|--------|--------|--------|--------|--------|-------- +Sonoff Pow | KEY1 | - | - | - | - | NRG_SEL | REL1 | NRG_CF1 | HLW_CF | LED1 +Sonoff Pow R2 | KEY1 | RXD | - | TXD | - | - | REL1 | LED1_INV | - | - +Shelly 2 | - | RXD | - | TXD | REL1 | REL2 | SWT1 | - | SWT2 | - +Huafan SS | LED1_INV | - | - | LED2_INV | KEY1 | REL1_INV | NRG_CF1 | NRG_SEL | HLW_CF | - +KMC 70011 | KEY1 | - | - | - | HLW_CF | NRG_CF1 | NRG_SEL | LED1_INV | REL1 | - +Teckin | - | KEY1 | - | LED2_INV | HJL_CF | NRG_CF1 | NRG_SEL_INV | LED1_INV | REL1 | - +AplicWDP303075 | - | - | - | KEY1 | HLW_CF | NRG_CF1 | NRG_SEL_INV | LED1_INV | REL1 | - +Gosund SP1 v23 | - | LED1_INV | - | KEY1 | HJL_CF | NRG_CF1 | NRG_SEL_INV | LED2_INV | REL1 | - +SK03 Outdoor | KEY1 | - | - | - | HLW_CF | NRG_CF1 | NRG_SEL_INV | LED2_INV | LED1_INV | REL1 +BlitzWolf SHP | LED2_INV | - | LED1_INV | - | - | HJL_CF | NRG_SEL_INV | KEY1 | NRG_CF1 | REL1 +Teckin US | LED2_INV | - | LED1_INV | - | REL1 | HJL_CF | NRG_SEL_INV | KEY1 | NRG_CF1 | - diff --git a/RELEASENOTES.md b/RELEASENOTES.md index cf4e0d6ee..3b032de02 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -82,21 +82,6 @@ Module | Description 58 PS-16-DZ | PS-16-DZ Wifi dimmer for Incandescent Lights and Led 59 Teckin US | Teckin US and ZooZee SA102 Wifi Smart Switch with Energy Monitoring -## Supported Smart Switch with Energy Monitoring GPIO usage -Module | GPIO00 | GPIO01 | GPIO02 | GPIO03 | GPIO04 | GPIO05 | GPIO12 | GPIO13 | GPIO14 | GPIO15 --------|--------|--------|--------|--------|--------|--------|--------|--------|--------|-------- -Sonoff Pow | KEY1 | - | - | - | - | NRG_SEL | REL1 | NRG_CF1 | HLW_CF | LED1 -Sonoff Pow R2 | KEY1 | RXD | - | TXD | - | - | REL1 | LED1_INV | - | - -Shelly 2 | - | RXD | - | TXD | REL1 | REL2 | SWT1 | - | SWT2 | - -Huafan SS | LED1_INV | - | - | LED2_INV | KEY1 | REL1_INV | NRG_CF1 | NRG_SEL | HLW_CF | - -KMC 70011 | KEY1 | - | - | - | HLW_CF | NRG_CF1 | NRG_SEL | LED1_INV | REL1 | - -Teckin | - | KEY1 | - | LED2_INV | HJL_CF | NRG_CF1 | NRG_SEL_INV | LED1_INV | REL1 | - -AplicWDP303075 | - | - | - | KEY1 | HLW_CF | NRG_CF1 | NRG_SEL_INV | LED1_INV | REL1 | - -Gosund SP1 v23 | - | LED1_INV | - | KEY1 | HJL_CF | NRG_CF1 | NRG_SEL_INV | LED2_INV | REL1 | - -SK03 Outdoor | KEY1 | - | - | - | HLW_CF | NRG_CF1 | NRG_SEL_INV | LED2_INV | LED1_INV | REL1 -BlitzWolf SHP | LED2_INV | - | LED1_INV | - | - | HJL_CF | NRG_SEL_INV | KEY1 | NRG_CF1 | REL1 -Teckin US | LED2_INV | - | LED1_INV | - | REL1 | HJL_CF | NRG_SEL_INV | KEY1 | NRG_CF1 | - - ## Provided Binary Downloads The following binary downloads have been compiled with ESP8266/Arduino library version **2.3.0** diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index d230ff02f..cbfb2b767 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,8 @@ * Add support for SM Smart Wifi Dimmer PS-16-DZ (#4465) * Move some static (serial) buffers to dynamic buffers * Update display and epaper drivers + * Fix intermittent Pzem sensor energy overflow calculation error + * Add support for Teckin US Power Socket with Energy Monitoring (#4481) * * 6.3.0.13 20181126 * Add command SetOption59 0/1 to change state topic from tele/STATE to stat/RESULT (#4450) From 33f85b20238cd058ed363867fb20160732f362fa Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 30 Nov 2018 19:55:22 +0200 Subject: [PATCH 0634/2222] Upd settings.ino - set sleep=0 when SetOption36>0 Update settings.ino - set sleep=0 when SetOption36>0 --- sonoff/settings.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 99e81230d..cf49c0719 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -857,6 +857,7 @@ void SettingsDelta(void) } if (Settings.version < 0x0603000A) { Settings.param[P_LOOP_SLEEP_DELAY] = LOOP_SLEEP_DELAY; + Settings.sleep = 0; // We do not want sleep enabled when SetOption36 is active } if (Settings.version < 0x0603000E) { Settings.flag2.calc_resolution = CALC_RESOLUTION; From 3613946f185297da71a765be9ef0a83d26c7bbb8 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 30 Nov 2018 20:00:20 +0200 Subject: [PATCH 0635/2222] Prevent sleep and SetOption36 being used concurrently Prevent sleep and SetOption36 being used concurrently --- sonoff/sonoff.ino | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 30188056c..960d9cf25 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -587,6 +587,11 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } else if (CMND_SLEEP == command_code) { if ((payload >= 0) && (payload < 251)) { + if (payload > 0) { + snprintf_P(log_data, sizeof(log_data), PSTR("*** WARNING *** - Disabling SetOption36 (Dynamic Sleep) in favour of sleep")); + AddLog(LOG_LEVEL_INFO); + Settings.param[P_LOOP_SLEEP_DELAY] = 0; // We do not want SetOption36 to be active along with traditional sleep + } Settings.sleep = payload; sleep = payload; WiFiSetSleepMode(); @@ -756,6 +761,12 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) param_low = 1; param_high = 250; break; + case P_LOOP_SLEEP_DELAY: + if (payload > 0) { + snprintf_P(log_data, sizeof(log_data), PSTR("*** WARNING *** - Disabling sleep in favour of SetOption36 (Dynamic Sleep)")); + AddLog(LOG_LEVEL_INFO); + Settings.sleep = 0; // We do not want traditional sleep to be enabled along side SetOption36 + } } if ((payload >= param_low) && (payload <= param_high)) { Settings.param[pindex] = payload; From 5f402c8f34affc9eaafce6fccef8e902bc9b79fd Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 1 Dec 2018 00:18:08 +0200 Subject: [PATCH 0636/2222] Fix sleep->SetOption36 transition --- sonoff/sonoff.ino | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 960d9cf25..2dfb7e213 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -766,6 +766,8 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) snprintf_P(log_data, sizeof(log_data), PSTR("*** WARNING *** - Disabling sleep in favour of SetOption36 (Dynamic Sleep)")); AddLog(LOG_LEVEL_INFO); Settings.sleep = 0; // We do not want traditional sleep to be enabled along side SetOption36 + sleep = 0; + WiFiSetSleepMode(); } } if ((payload >= param_low) && (payload <= param_high)) { @@ -1588,8 +1590,12 @@ void MqttShowState(void) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VCC "\":%s"), mqtt_data, stemp1); #endif - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LoopSet\":%u"), mqtt_data, (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]); // Add current loop delay target to telemetry - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LoadAvg\":%u"), mqtt_data, loop_load_avg); // Add LoadAvg to telemetry data + if (Settings.param[P_LOOP_SLEEP_DELAY]) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LoopSet\":%u"), mqtt_data, (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]); // Add current loop delay target to telemetry + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LoadAvg\":%u"), mqtt_data, loop_load_avg); // Add LoadAvg to telemetry data + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"Sleep\":%u"), mqtt_data, (uint32_t)sleep); // Add current sleep setting so we know Dynamic Sleep is not enabled + } for (byte i = 0; i < devices_present; i++) { if (i == light_device -1) { From be86811628208cba885a2f61867aa36bc61ff253 Mon Sep 17 00:00:00 2001 From: Xavier MULLER <33861984+localhost61@users.noreply.github.com> Date: Sat, 1 Dec 2018 02:48:10 +0100 Subject: [PATCH 0637/2222] Update fr-FR.h Synced with changes since v6.2.1.7 --- sonoff/language/fr-FR.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 0936f6069..78afd01d1 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.2.1.7 + * Updated until v6.3.0.14 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -174,7 +174,7 @@ #define D_UV_POWER "Puissance UV" #define D_VERSION "Version" #define D_VOLTAGE "Tension" -#define D_WEIGHT "Weight" +#define D_WEIGHT "Poids" #define D_WARMLIGHT "Chaud" #define D_WEB_SERVER "Serveur web" @@ -457,27 +457,27 @@ #define D_GZ_AXIS "Gyro Axe-Z" // xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" +#define D_HX_CAL_REMOVE "Retirer la charge" +#define D_HX_CAL_REFERENCE "Charger l'étalon de poids" +#define D_HX_CAL_DONE "Étalonné" +#define D_HX_CAL_FAIL "L'étalonnage a échoué" +#define D_RESET_HX711 "Réinitialiser le capteur" +#define D_CONFIGURE_HX711 "Configurer le capteur" +#define D_HX711_PARAMETERS "Paramètres capteur" +#define D_ITEM_WEIGHT "Poids de l'objet" +#define D_REFERENCE_WEIGHT "Poids de référence" +#define D_CALIBRATE "Étalonner" +#define D_CALIBRATION "Étalonnage" //xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_WIND_DIRECTION "Direction du vent" +#define D_TX20_WIND_SPEED "Vitesse du vent" +#define D_TX20_WIND_SPEED_AVG "Vitesse Moy." +#define D_TX20_WIND_SPEED_MAX "Vitesse Max" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" #define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" +#define D_TX20_WEST "O" // sonoff_template.h #define D_SENSOR_NONE "Aucun" @@ -544,7 +544,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" From 6050cd40f3856043aae828058bc9485c6ab1b78c Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 1 Dec 2018 18:47:25 +0200 Subject: [PATCH 0638/2222] Merge sleep command --- sonoff/settings.h | 2 +- sonoff/settings.ino | 8 +++--- sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 56 +++++++++++++++++++++-------------------- sonoff/support_wifi.ino | 5 ++++ 5 files changed, 40 insertions(+), 33 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 033071668..10f40cdb7 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -73,7 +73,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t use_wifi_rescan : 1; // bit 7 (v6.3.0.10) uint32_t receive_raw : 1; // bit 8 (v6.3.0.11) uint32_t hass_tele_as_result : 1; // bit 9 (v6.3.0.13) - uint32_t spare10 : 1; + uint32_t sleep_normal : 1; // SetOption60 - Enable normal sleep instead of dynamic sleep uint32_t spare11 : 1; uint32_t spare12 : 1; uint32_t spare13 : 1; diff --git a/sonoff/settings.ino b/sonoff/settings.ino index cf49c0719..960ee019c 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -417,7 +417,6 @@ void SettingsDefaultSet2(void) // Settings.flag.stop_flash_rotate = 0; Settings.save_data = SAVE_DATA; Settings.sleep = APP_SLEEP; - Settings.param[P_LOOP_SLEEP_DELAY] = LOOP_SLEEP_DELAY; // Module // Settings.flag.interlock = 0; @@ -855,9 +854,10 @@ void SettingsDelta(void) if (Settings.version < 0x06030004) { memset(&Settings.drivers, 0xFF, 32); // Enable all possible monitors, displays, drivers and sensors } - if (Settings.version < 0x0603000A) { - Settings.param[P_LOOP_SLEEP_DELAY] = LOOP_SLEEP_DELAY; - Settings.sleep = 0; // We do not want sleep enabled when SetOption36 is active + if (Settings.version < 0x0603000F) { + if (Settings.sleep < 50) { + Settings.sleep = 50; // Default to 50 for sleep, for now + } } if (Settings.version < 0x0603000E) { Settings.flag2.calc_resolution = CALC_RESOLUTION; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index e53a7c83d..fd8beca70 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -222,7 +222,7 @@ enum ButtonStates { PRESSED, NOT_PRESSED }; enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; -enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_LOOP_SLEEP_DELAY, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 +enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_MAX_SENSORS}; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 2dfb7e213..126524291 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -587,11 +587,6 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } else if (CMND_SLEEP == command_code) { if ((payload >= 0) && (payload < 251)) { - if (payload > 0) { - snprintf_P(log_data, sizeof(log_data), PSTR("*** WARNING *** - Disabling SetOption36 (Dynamic Sleep) in favour of sleep")); - AddLog(LOG_LEVEL_INFO); - Settings.param[P_LOOP_SLEEP_DELAY] = 0; // We do not want SetOption36 to be active along with traditional sleep - } Settings.sleep = payload; sleep = payload; WiFiSetSleepMode(); @@ -750,6 +745,13 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) else if (1 == ptype) { // SetOption50 .. 81 if (payload <= 1) { bitWrite(Settings.flag3.data, pindex, payload); + if (60 == ptype) { // SetOption60 enable or disable traditional sleep + if (payload == 0) { // Dynamic Sleep + WiFiSetSleepMode(); // Update WiFi sleep mode accordingly + } else { // Traditional Sleep //AT + WiFiSetSleepMode(); // Update WiFi sleep mode accordingly + } + } } } else { // SetOption32 .. 49 @@ -761,14 +763,6 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) param_low = 1; param_high = 250; break; - case P_LOOP_SLEEP_DELAY: - if (payload > 0) { - snprintf_P(log_data, sizeof(log_data), PSTR("*** WARNING *** - Disabling sleep in favour of SetOption36 (Dynamic Sleep)")); - AddLog(LOG_LEVEL_INFO); - Settings.sleep = 0; // We do not want traditional sleep to be enabled along side SetOption36 - sleep = 0; - WiFiSetSleepMode(); - } } if ((payload >= param_low) && (payload <= param_high)) { Settings.param[pindex] = payload; @@ -1590,13 +1584,16 @@ void MqttShowState(void) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VCC "\":%s"), mqtt_data, stemp1); #endif - if (Settings.param[P_LOOP_SLEEP_DELAY]) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LoopSet\":%u"), mqtt_data, (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]); // Add current loop delay target to telemetry - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LoadAvg\":%u"), mqtt_data, loop_load_avg); // Add LoadAvg to telemetry data + char _sleepmode[8]; + if (Settings.flag3.sleep_normal) { + sprintf(_sleepmode,"Normal"); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"Sleep\":%u"), mqtt_data, (uint32_t)sleep); // Add current sleep setting so we know Dynamic Sleep is not enabled + sprintf(_sleepmode,"Dynamic"); } - + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SleepMode\":\"%s\""), mqtt_data, _sleepmode); // Add current sleep mode setting to telemetry + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"Sleep\":%u"), mqtt_data, sleep); // Add current sleep setting to telemetry + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LoadAvg\":%u"), mqtt_data, loop_load_avg); // Add LoadAvg to telemetry + for (byte i = 0; i < devices_present; i++) { if (i == light_device -1) { LightState(1); @@ -2758,6 +2755,8 @@ void setup(void) XsnsCall(FUNC_INIT); } +uint32_t _counter = 0; + void loop(void) { uint32_t my_sleep = millis(); @@ -2800,22 +2799,25 @@ void loop(void) while (arduino_ota_triggered) ArduinoOTA.handle(); #endif // USE_ARDUINO_OTA -// yield(); // yield == delay(0), delay contains yield, auto yield in loop - delay(sleep); // https://github.com/esp8266/Arduino/issues/2021 - uint32_t my_activity = millis() - my_sleep; - if (my_activity < (uint32_t)Settings.param[P_LOOP_SLEEP_DELAY]) { - delay((uint32_t)Settings.param[P_LOOP_SLEEP_DELAY] - my_activity); // Provide time for background tasks like wifi + + if (Settings.flag3.sleep_normal) { + // yield(); // yield == delay(0), delay contains yield, auto yield in loop + delay(sleep); // https://github.com/esp8266/Arduino/issues/2021 } else { - if (global_state.wifi_down) { - delay(my_activity /2); // If wifi down and my_activity > setoption36 then force loop delay to 1/3 of my_activity period + if (my_activity < (uint32_t)sleep) { + delay((uint32_t)sleep - my_activity); // Provide time for background tasks like wifi + } else { + if (global_state.wifi_down) { + delay(my_activity /2); // If wifi down and my_activity > setoption36 then force loop delay to 1/3 of my_activity period + } } } if (!my_activity) { my_activity++; } // We cannot divide by 0 - uint32_t loop_delay = Settings.param[P_LOOP_SLEEP_DELAY]; + uint32_t loop_delay = sleep; if (!loop_delay) { loop_delay++; } // We cannot divide by 0 uint32_t loops_per_second = 1000 / loop_delay; // We need to keep track of this many loops per second uint32_t this_cycle_ratio = 100 * my_activity / loop_delay; - loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + (this_cycle_ratio / loops_per_second); // Take away one loop average away and add the new one + loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + (this_cycle_ratio / loops_per_second); // Take away one loop average away and add the new one } diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 87ff4e21b..2dce4bce2 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -181,6 +181,11 @@ void WiFiSetSleepMode(void) #if defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) #else // Enabled in 2.3.0, 2.4.0 and stage if (sleep) { + if (Settings.flag3.sleep_normal) { + WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times + } else { + WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default) + } WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times } else { WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default) From a1c464d34ce4b4666ae6ea1af8703ea8256c7d2d Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 1 Dec 2018 18:55:06 +0200 Subject: [PATCH 0639/2222] Bump version to 0x0603000F Bump version to 0x0603000F to make sure new sleep command takes effect on 50 as default for upgrades where sleep is < 50. --- sonoff/sonoff_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index d3df8d797..d6b82d881 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0603000E +#define VERSION 0x0603000F #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" From 0bd4ac8eea39181f14462eb820858069cf6e9e4f Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sat, 1 Dec 2018 18:58:26 +0200 Subject: [PATCH 0640/2222] Update support_wifi.ino --- sonoff/support_wifi.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 2dce4bce2..2a1ef27d6 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -186,7 +186,6 @@ void WiFiSetSleepMode(void) } else { WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default) } - WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times } else { WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default) } From eb3c1a327dcc804ef2a2e75c7f460a05ef52fff1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 1 Dec 2018 18:53:42 +0100 Subject: [PATCH 0641/2222] 6.3.0.15 Update dynamic sleep 6.3.0.15 20181201 * Removed command SetOption36 (#4497) * Add command SetOption60 0/1 to select dynamic sleep (0) or sleep (1) (#4497) --- sonoff/_changelog.ino | 6 +++++- sonoff/settings.h | 2 +- sonoff/settings.ino | 13 ++++++++----- sonoff/sonoff.ino | 18 +++++++----------- sonoff/support_wifi.ino | 8 ++------ 5 files changed, 23 insertions(+), 24 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index cbfb2b767..04c9afe93 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ -/* 6.3.0.14 20181127 +/* 6.3.0.15 20181201 + * Removed command SetOption36 (#4497) + * Add command SetOption60 0/1 to select dynamic sleep (0) or sleep (1) (#4497) + * + * 6.3.0.14 20181127 * Add Command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420) * Add support for SM Smart Wifi Dimmer PS-16-DZ (#4465) * Move some static (serial) buffers to dynamic buffers diff --git a/sonoff/settings.h b/sonoff/settings.h index 10f40cdb7..39d8f5979 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -73,7 +73,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t use_wifi_rescan : 1; // bit 7 (v6.3.0.10) uint32_t receive_raw : 1; // bit 8 (v6.3.0.11) uint32_t hass_tele_as_result : 1; // bit 9 (v6.3.0.13) - uint32_t sleep_normal : 1; // SetOption60 - Enable normal sleep instead of dynamic sleep + uint32_t sleep_normal : 1; // bit 10 (v6.3.0.15) - SetOption60 - Enable normal sleep instead of dynamic sleep uint32_t spare11 : 1; uint32_t spare12 : 1; uint32_t spare13 : 1; diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 960ee019c..7f065b626 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -417,6 +417,9 @@ void SettingsDefaultSet2(void) // Settings.flag.stop_flash_rotate = 0; Settings.save_data = SAVE_DATA; Settings.sleep = APP_SLEEP; + if (Settings.sleep < 50) { + Settings.sleep = 50; // Default to 50 for sleep, for now + } // Module // Settings.flag.interlock = 0; @@ -854,14 +857,14 @@ void SettingsDelta(void) if (Settings.version < 0x06030004) { memset(&Settings.drivers, 0xFF, 32); // Enable all possible monitors, displays, drivers and sensors } - if (Settings.version < 0x0603000F) { - if (Settings.sleep < 50) { - Settings.sleep = 50; // Default to 50 for sleep, for now - } - } if (Settings.version < 0x0603000E) { Settings.flag2.calc_resolution = CALC_RESOLUTION; } + if (Settings.version < 0x0603000F) { + if (Settings.sleep < 50) { + Settings.sleep = 50; // Default to 50 for sleep, for now + } + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 126524291..068c7a4a9 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -89,6 +89,8 @@ const char kTasmotaCommands[] PROGMEM = D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER "|" D_CMND_DRIVER; +const char kSleepMode[] PROGMEM = "Dynamic|Normal"; + const uint8_t kIFan02Speed[4][3] = {{6,6,6}, {7,6,6}, {7,7,6}, {7,6,7}}; // Global variables @@ -1579,21 +1581,15 @@ void MqttShowState(void) char stemp1[33]; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\""), mqtt_data, GetDateAndTime(DT_LOCAL).c_str(), GetUptime().c_str()); + #ifdef USE_ADC_VCC dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VCC "\":%s"), mqtt_data, stemp1); #endif - char _sleepmode[8]; - if (Settings.flag3.sleep_normal) { - sprintf(_sleepmode,"Normal"); - } else { - sprintf(_sleepmode,"Dynamic"); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SleepMode\":\"%s\""), mqtt_data, _sleepmode); // Add current sleep mode setting to telemetry - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"Sleep\":%u"), mqtt_data, sleep); // Add current sleep setting to telemetry - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LoadAvg\":%u"), mqtt_data, loop_load_avg); // Add LoadAvg to telemetry - + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u"), + mqtt_data, GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), sleep, loop_load_avg); + for (byte i = 0; i < devices_present; i++) { if (i == light_device -1) { LightState(1); @@ -2800,7 +2796,7 @@ void loop(void) #endif // USE_ARDUINO_OTA uint32_t my_activity = millis() - my_sleep; - + if (Settings.flag3.sleep_normal) { // yield(); // yield == delay(0), delay contains yield, auto yield in loop delay(sleep); // https://github.com/esp8266/Arduino/issues/2021 diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 2a1ef27d6..7f2771dde 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -180,12 +180,8 @@ void WiFiSetSleepMode(void) // Sleep explanation: https://github.com/esp8266/Arduino/blob/3f0c601cfe81439ce17e9bd5d28994a7ed144482/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp#L255 #if defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) #else // Enabled in 2.3.0, 2.4.0 and stage - if (sleep) { - if (Settings.flag3.sleep_normal) { - WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times - } else { - WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default) - } + if (sleep && Settings.flag3.sleep_normal) { + WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times } else { WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default) } From 2367834a64e9ac6831c4f5fe206fcd105e2e95bf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 1 Dec 2018 18:58:30 +0100 Subject: [PATCH 0642/2222] Update with dynamic sleep flag --- tools/decode-status.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/decode-status.py b/tools/decode-status.py index 2ab37a642..3de4dfca3 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -94,7 +94,8 @@ a_setoption = [[ "Use wifi network rescan regularly", "Add IR raw data to JSON message", "Change state topic from tele/STATE to stat/RESULT", - "","", + "Enable normal sleep instead of dynamic sleep", + "", "","","","", "","","","", "","","","", From 98a2e6e175053edb73c9edefd48a98c0516a9008 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sat, 1 Dec 2018 16:26:15 -0300 Subject: [PATCH 0643/2222] Added Support for ButtonN and SwitchN --- sonoff/xdrv_11_knx.ino | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index b4fbefc18..665583767 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -483,6 +483,14 @@ void KNX_INIT(void) { if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } } + for (int i = GPIO_SWT1_NP; i < GPIO_SWT4_NP + 1; ++i) + { + if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_SWT1_NP + 8].show = true; } + } + for (int i = GPIO_KEY1_NP; i < GPIO_KEY4_NP + 1; ++i) + { + if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_KEY1_NP + 8].show = true; } + } if (GetUsedInModule(GPIO_DHT11, my_module.gp.io)) { device_param[KNX_TEMPERATURE-1].show = true; } if (GetUsedInModule(GPIO_DHT22, my_module.gp.io)) { device_param[KNX_TEMPERATURE-1].show = true; } if (GetUsedInModule(GPIO_SI7021, my_module.gp.io)) { device_param[KNX_TEMPERATURE-1].show = true; } From 7f2b3643f54930b14080271bbd7ca127a12e26d3 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sat, 1 Dec 2018 18:12:33 -0300 Subject: [PATCH 0644/2222] RULES: Added BREAK as an alternative ENDON RULES: Added BREAK as an alternative ENDON that will stop the execution of the following rules. If a rule that ends with BREAK, is triggered, then the following rules of that set will not be executed. This is useful for cases like: https://github.com/arendst/Sonoff-Tasmota/issues/4477 --- sonoff/xdrv_10_rules.ino | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 1fde3dff7..251c91e47 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -264,6 +264,8 @@ bool RuleSetProcess(byte rule_set, String &event_saved) rules_trigger_count[rule_set] = 0; int plen = 0; + int plen2 = 0; + bool stop_all_rules = false; while (true) { rules = rules.substring(plen); // Select relative to last rule rules.trim(); @@ -278,7 +280,14 @@ bool RuleSetProcess(byte rule_set, String &event_saved) String event_trigger = rule.substring(3, pevt); // "INA219#CURRENT>0.100" plen = rule.indexOf(" ENDON"); - if (plen == -1) { return serviced; } // Bad syntax - No endon + plen2 = rule.indexOf(" BREAK"); + if ((plen == -1) && (plen2 == -1)) { return serviced; } // Bad syntax - No ENDON neither BREAK + + if (plen == -1) { plen = 9999; } + if (plen2 == -1) { plen2 = 9999; } + plen = min(plen, plen2); + if (plen == plen2) { stop_all_rules = true; } // If BREAK was used, Stop execution of this rule set + String commands = rules.substring(pevt +4, plen); // "Backlog Dimmer 10;Color 100000" plen += 6; rules_event_value = ""; @@ -320,6 +329,7 @@ bool RuleSetProcess(byte rule_set, String &event_saved) ExecuteCommand(command, SRC_RULE); serviced = true; + if (stop_all_rules) { return serviced; } // If BREAK was used, Stop execution of this rule set } rules_trigger_count[rule_set]++; } From e37dbd1f6a0d47c002108c3b156a069fe71e74d0 Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Sat, 1 Dec 2018 23:15:19 +0200 Subject: [PATCH 0645/2222] Update xsns_22_sr04.ino --- sonoff/xsns_22_sr04.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index 32f09bd20..77ea5e829 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -34,7 +34,7 @@ real64_t distance; NewPing* sonar = NULL; -void Sr04Init() +void Sr04Init(void) { sr04_echo_pin = pin[GPIO_SR04_ECHO]; sr04_trig_pin = pin[GPIO_SR04_TRIG]; From c68fe7e7ada34f248eeb0c2ed51a8049ac5bcc64 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sat, 1 Dec 2018 19:00:34 -0300 Subject: [PATCH 0646/2222] RULES: Added BREAK as an alternative ENDON --- sonoff/xdrv_10_rules.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 251c91e47..0a06fe149 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -285,7 +285,7 @@ bool RuleSetProcess(byte rule_set, String &event_saved) if (plen == -1) { plen = 9999; } if (plen2 == -1) { plen2 = 9999; } - plen = min(plen, plen2); + plen = tmin(plen, plen2); if (plen == plen2) { stop_all_rules = true; } // If BREAK was used, Stop execution of this rule set String commands = rules.substring(pevt +4, plen); // "Backlog Dimmer 10;Color 100000" From 7e09195083979a09624c7b64e946961a0f7698c7 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sat, 1 Dec 2018 19:16:32 -0300 Subject: [PATCH 0647/2222] Delete duplicated min and max functions --- sonoff/xplg_wemohue.ino | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 6c031fd94..64ac969ae 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -17,8 +17,8 @@ along with this program. If not, see . */ -#define min(a,b) ((a)<(b)?(a):(b)) -#define max(a,b) ((a)>(b)?(a):(b)) +//#define min(a,b) ((a)<(b)?(a):(b)) +//#define max(a,b) ((a)>(b)?(a):(b)) #if defined(USE_WEBSERVER) && defined(USE_EMULATION) /*********************************************************************************************\ @@ -692,8 +692,8 @@ void HueLights(String *path) if (hue_json.containsKey("bri")) { // Brightness is a scale from 1 (the minimum the light is capable of) to 254 (the maximum). Note: a brightness of 1 is not off. tmp = hue_json["bri"]; - tmp = max(tmp, 1); - tmp = min(tmp, 254); + tmp = tmax(tmp, 1); + tmp = tmin(tmp, 254); bri = (float)tmp / 254.0f; if (resp) { response += ","; @@ -721,8 +721,8 @@ void HueLights(String *path) } if (hue_json.containsKey("sat")) { // Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white). tmp = hue_json["sat"]; - tmp = max(tmp, 0); - tmp = min(tmp, 254); + tmp = tmax(tmp, 0); + tmp = tmin(tmp, 254); sat = (float)tmp / 254.0f; if (resp) { response += ","; From 2e950c589a55b83a62fabce90b84aa1e337fd401 Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Sun, 2 Dec 2018 11:00:01 +0200 Subject: [PATCH 0648/2222] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 348c06cb1..f98d92b50 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,7 @@ Libraries used with Sonoff-Tasmota are: - [OneWire](https://github.com/PaulStoffregen/OneWire) - [PubSubClient](https://github.com/knolleary/pubsubclient) - [rc-switch](https://github.com/sui77/rc-switch) +- [NewPing](https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home) #### People inspiring me People helping to keep the show on the road: From f3d625d06d530ad56a620a5e6ee002f4ec37d712 Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Sun, 2 Dec 2018 11:18:29 +0200 Subject: [PATCH 0649/2222] Update _changelog.ino --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 04c9afe93..535d386dd 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.3.0.15 20181201 * Removed command SetOption36 (#4497) * Add command SetOption60 0/1 to select dynamic sleep (0) or sleep (1) (#4497) + * Update SR-04 driver to use NewPing library (#4488) * * 6.3.0.14 20181127 * Add Command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420) From 74172f14d3c69e5c420d40f4038c7a18fdbd99e2 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 2 Dec 2018 15:23:25 +0100 Subject: [PATCH 0650/2222] Further improve Hass auto discovery --- sonoff/settings.h | 2 +- sonoff/sonoff.ino | 14 +++++++++----- sonoff/xdrv_04_light.ino | 5 +++++ sonoff/xdrv_12_home_assistant.ino | 5 +++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 39d8f5979..10e67e6a2 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -72,7 +72,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t use_wifi_scan : 1; // bit 6 (v6.3.0.10) uint32_t use_wifi_rescan : 1; // bit 7 (v6.3.0.10) uint32_t receive_raw : 1; // bit 8 (v6.3.0.11) - uint32_t hass_tele_as_result : 1; // bit 9 (v6.3.0.13) + uint32_t hass_tele_on_power : 1; // bit 9 (v6.3.0.13) uint32_t sleep_normal : 1; // bit 10 (v6.3.0.15) - SetOption60 - Enable normal sleep instead of dynamic sleep uint32_t spare11 : 1; uint32_t spare12 : 1; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 068c7a4a9..be7006286 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -586,6 +586,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) else if (CMND_STATE == command_code) { mqtt_data[0] = '\0'; MqttShowState(); + if (Settings.flag3.hass_tele_on_power) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); + } } else if (CMND_SLEEP == command_code) { if ((payload >= 0) && (payload < 251)) { @@ -1393,6 +1396,11 @@ void ExecuteCommandPower(byte device, byte state, int source) #ifdef USE_KNX KnxUpdatePowerState(device, power); #endif // USE_KNX + if (publish_power && Settings.flag3.hass_tele_on_power) { + mqtt_data[0] = '\0'; + MqttShowState(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); + } if (device <= MAX_PULSETIMERS) { // Restart PulseTime if powered On SetPulseTimer(device -1, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[device -1] : 0); } @@ -1691,11 +1699,7 @@ void PerformEverySecond(void) mqtt_data[0] = '\0'; MqttShowState(); - if (Settings.flag3.hass_tele_as_result) { - MqttPublishPrefixTopic_P(STAT, S_RSLT_RESULT, MQTT_TELE_RETAIN); - } else { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); - } + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); mqtt_data[0] = '\0'; if (MqttShowSensor()) { diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index b4f10a148..829374d08 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -624,6 +624,11 @@ void LightPreparePower(void) #ifdef USE_DOMOTICZ DomoticzUpdatePowerState(light_device); #endif // USE_DOMOTICZ + if (Settings.flag3.hass_tele_on_power) { + mqtt_data[0] = '\0'; + MqttShowState(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); + } LightState(0); } diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 4a7a0ea92..78b8b4841 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -206,7 +206,8 @@ void HAssAnnounceRelayLight(void) } GetPowerDevice(value_template, i, sizeof(value_template), Settings.flag.device_index_enable); GetTopic_P(command_topic, CMND, mqtt_topic, value_template); - GetTopic_P(state_topic, STAT, mqtt_topic, S_RSLT_RESULT); + //GetTopic_P(state_topic, STAT, mqtt_topic, S_RSLT_RESULT); + GetTopic_P(state_topic, TELE, mqtt_topic, D_RSLT_STATE); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); FindPrefix(command_topic, state_topic, prefix); if (Settings.flag3.hass_short_discovery_msg) { @@ -426,7 +427,7 @@ void HAssDiscovery(uint8_t mode) if (Settings.flag.hass_discovery) { Settings.flag.mqtt_response = 0; // Response always as RESULT and not as uppercase command Settings.flag.decimal_text = 1; // Respond with decimal color values - Settings.flag3.hass_tele_as_result = 1; // send tele/STATE message as stat/RESULT + Settings.flag3.hass_tele_on_power = 1; // send tele/STATE message as stat/RESULT // Settings.light_scheme = 0; // To just control color it needs to be Scheme 0 if (!string_ends_with(Settings.mqtt_fulltopic, "%prefix%/")) { strncpy_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"), sizeof(Settings.mqtt_fulltopic)); From a2e865bb44a7806db851abc44a89bc06c955f98a Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Sun, 2 Dec 2018 18:53:49 +0200 Subject: [PATCH 0651/2222] Add dummy soft_spi_flg to satisfy compiler @arendst Just adding this, for now, to satisfy the compiler until you get time to merge the rest of the Software SPI support. --- sonoff/sonoff.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index be7006286..0772e76f2 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -167,6 +167,7 @@ uint8_t dht_flg = 0; // DHT configured uint8_t energy_flg = 0; // Energy monitor configured uint8_t i2c_flg = 0; // I2C configured uint8_t spi_flg = 0; // SPI configured +uint8_t soft_spi_flg = 0; // Software SPI ** Temporary fix to satisfy compiler ** uint8_t light_type = 0; // Light types uint8_t ntp_force_sync = 0; // Force NTP sync byte serial_in_byte; // Received byte From 3cd89330aacdd78e8c9ae49d8d38f004991ea7ea Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Mon, 3 Dec 2018 08:33:21 +0100 Subject: [PATCH 0652/2222] decode-config.py: add new settings - add 6.3.0.15 setting change - adapt 6.3.0.13 setting change --- tools/decode-config.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 287f221ef..1850e2aea 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0010' +VER = '2.1.0011' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -790,7 +790,7 @@ Setting_6_3_0_11['flag3'][0].update ({ # ====================================================================== Setting_6_3_0_13 = copy.deepcopy(Setting_6_3_0_11) Setting_6_3_0_13['flag3'][0].update ({ - 'hass_tele_as_result': (' Date: Mon, 3 Dec 2018 17:30:06 +0200 Subject: [PATCH 0653/2222] Add GPIO2 for Sonoff Basic Template Add GPIO2 for Sonoff Basic Template --- sonoff/sonoff_template.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index c4fcfb377..225d3767a 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -517,7 +517,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "Sonoff Basic", // Sonoff Basic (ESP8266) GPIO_KEY1, // GPIO00 Button GPIO_USER, // GPIO01 Serial RXD and Optional sensor - 0, // GPIO02 + GPIO_USER, // GPIO02 Only available on newer Sonoff Basic R2 V1 GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor 0, // GPIO05 From dcaf6164d443cd3cdb113f1c346944bdad542009 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 3 Dec 2018 17:34:35 +0200 Subject: [PATCH 0654/2222] Add support for GPIO02 for newer Sonoff Basic Add support for GPIO02 for newer Sonoff Basic --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 535d386dd..3709195fe 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Removed command SetOption36 (#4497) * Add command SetOption60 0/1 to select dynamic sleep (0) or sleep (1) (#4497) * Update SR-04 driver to use NewPing library (#4488) + * Add support for GPIO02 for newer Sonoff Basic (#4518) * * 6.3.0.14 20181127 * Add Command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420) From 24ef9ab6b87dbf6f2e5106e4b1bb57a42d1bf84e Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 3 Dec 2018 17:38:31 -0300 Subject: [PATCH 0655/2222] Fix Compilation issue with STAGE Core Now the Stage core has the the same STR macro defined in sonoff.h. --- sonoff/sonoff.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index fd8beca70..4a54f81be 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -152,7 +152,9 @@ typedef unsigned long power_t; // Power (Relay) type #define tmax(a,b) ((a)>(b)?(a):(b)) #define STR_HELPER(x) #x +#ifndef STR #define STR(x) STR_HELPER(x) +#endif //enum ws2812NeopixelbusFeature { NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_3LED, NEO_RGBW, NEO_GRBW }; // Doesn't work #define NEO_RGB 0 // Neopixel RGB leds From abb6d5ee2e9eed2818ff4c9a7e5b953cf00bd633 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Tue, 4 Dec 2018 20:52:56 +0100 Subject: [PATCH 0656/2222] Create RF-Bridge-EFM8BB1-20181127.hex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ignore RF pulses < 100µs, increased uart RX buffer -> stopp red led flashing --- tools/RF-Bridge-EFM8BB1-20181127.hex | 506 +++++++++++++++++++++++++++ 1 file changed, 506 insertions(+) create mode 100644 tools/RF-Bridge-EFM8BB1-20181127.hex diff --git a/tools/RF-Bridge-EFM8BB1-20181127.hex b/tools/RF-Bridge-EFM8BB1-20181127.hex new file mode 100644 index 000000000..8008a0146 --- /dev/null +++ b/tools/RF-Bridge-EFM8BB1-20181127.hex @@ -0,0 +1,506 @@ +:020000040000FA +:1000000002166B8E258F26121D12AA06AB079000D2 +:1000100076E0FCA3E0FDAF26AE25121CC7EF24FF5F +:100020002222220215DB7597A522220219CB8E5BB4 +:100030008F5C8C5D8D5E121B02121D9AE55E24BFE3 +:100040009000FAF0E55D34FF9000F9F09000F5E5DE +:100050005BF0A3E55CF043910422220216FA121E23 +:100060003453D87853DAFE121DFFE4900082F02258 +:10007000D2DE22021A1ED201121C79C290C296C28E +:1000800080E4FBFD7F10121DE612068A74A4F0D2F4 +:10009000AF1219B2D2969000F2E004F07006900010 +:1000A000F1E004F09000F1E0B427E9A3E0B410E43B +:1000B000C296120026300109121BBD8E3E8F3F8072 +:1000C00006753E01753F00E53F7004E53E64017032 +:1000D000469000DAE070061219B302029A9000F11D +:1000E000E475F001120A85FED3E5F09410EE942732 +:1000F0004002D296D39000F2E094309000F1E09468 +:1001000075500302029AE4F0A3F09000DAF0900038 +:1001100095F0C29602029A1219B29000DAE01460C9 +:100120002A14700302026C14700302022A14700372 +:100130000202402404600302029AE53F64AA6003BD +:1001400002029A9000DA04F002029AE53F900095CC +:10015000F09000DA7402F0E53F120BBB0214A0012C +:1001600081A10191A501B8A601C6A701CFA801EE02 +:10017000A901D5B001DEB101A9C0029AFF000002B9 +:100180001F120641E4900094F0900074F07FA1806B +:100190006D12005E9000DA7404F09000F07408F0C4 +:1001A000E4F54175400902029A9000DA7404F0E423 +:1001B000F54175400202029A12199D7FA61206BAF5 +:1001C00074A6F002029A12068A74A4F002029A90AF +:1001D00000F07408F09000DA7403F002029A9000C4 +:1001E000747401F07FB11206BAEFF002029A12069F +:1001F00041900094E09000EFF012199D7FA9121B2E +:100200008690007AEFF07D307C757F017E00121CB5 +:100210005002029A12069C90007AEFF0E48005E406 +:10022000900095F09000DAF08070E4F541E53FF53C +:1002300040E540D394009000DA402C7404F0805ADA +:1002400074032541F582E43400F583E53FF0054170 +:10025000E541B540059000DA800DE541C39470405A +:10026000397540709000DA7402F0802EE53F6455D5 +:1002700070289000DAF0C201900095E024606018C8 +:1002800024FC600F24FE600B14600824F660042434 +:100290001070077FA0121D81D201900095E0120B13 +:1002A000BB02C3A102EDA402FFA503A4A603BEA83E +:1002B0000580A905B7B0062AB10371C00392FF00FB +:1002C0000000B2900081E030E70F7DC87C0012068C +:1002D000737FA3121ABD02059A121DF74003020094 +:1002E000B27DE87C031206737FA202062290008191 +:1002F000E020E7030200B27FA4121ABD0203B69009 +:1003000000DAE060030200B21219BA60432405600B +:10031000030200B21206C1900005E0FAA3E0FBFF61 +:10032000AE021219A9900007E0F8A3E08883858344 +:1003300049F54A85834BF54C900005E0F54DA3E067 +:10034000F54EE4F54F755018F551755206020552F9 +:100350009000F0E060111219C1500302056E120600 +:10036000A5121E2202056E12069CC2807FA0020604 +:10037000229000DAE060030200B21219A97F017E28 +:1003800000121C50D296121E22C2967FA0121D810E +:10039000800A7F02121D81E49000DAF0D201120679 +:1003A000B10200B2900081E020E7030200B2547F66 +:1003B000FD7FA6121A71E4900081F00200B2900055 +:1003C000DAE060030200B21219BA70030205582481 +:1003D0000560030200B2900003E0FF248070057501 +:1003E00042FF80028F421206C1900003E0648060E9 +:1003F0000302047BA3E0FCA3E0FD900008E0FAA365 +:10040000E0FBFFAE021209E8C006C007900006E05C +:10041000FCA3E0FDAF03AE021209E8C006C00790DE +:10042000000AE0FF7E00900008E0FCA3E0FD120956 +:10043000E8C006C00790000B121996C007C00690CE +:10044000000C121996AA06AB0790000D1219968E91 +:100450004D8F4E8A4B8B4CD049D04A90000EE0F520 +:100460004FA3E0F550A3E0F55175520ED003D00232 +:10047000D005D004D007D006020552E542F470033F +:100480000205E212198F2445F582E4341EF583E457 +:1004900093FF7E0012198F2448F582E4341EF58301 +:1004A000E493FA740193FDAC021209E8C006C00798 +:1004B00012198F2446F582E4341EF583E493121951 +:1004C00097C006C00712198F244AF582E4341E1221 +:1004D000196FC006C00712198F244BF582E4341E31 +:1004E00012196FC007C00612198F244CF582E4342C +:1004F0001E12196FAA06AB0712198F244DF582E45C +:10050000341E12196F12198F2447F582E4341EF538 +:1005100083E493FD12198F244EF582E4341EF58393 +:10052000E493FC12198F2451F582E4341EF583E420 +:1005300093F5518C508D4F8E4D8F4E8A4B8B4CD0F6 +:1005400049D04A755201D003D002D005D004D0075B +:10055000D00612177F0200B29000F0E06018E5426A +:10056000F4600B1219C140061206A5121E22E49077 +:100570000082F00200B21206B1C2807FA002062201 +:10058000900081E030E71D7DC87C00120654900089 +:1005900081E0547FFD7FAB121A71E4900081F0D2AC +:1005A000010200B2121DF740030200B27DE87C0395 +:1005B0001206547FAA806B9000DAE060030200B25A +:1005C0001219BA6051240560030200B212005E9055 +:1005D0000003E025E0900000F06007E540C39404CC +:1005E0005008E4900095F00200B2900000E0FF2473 +:1005F00005F9E43400754601F5478948C3E5409F95 +:1006000024FEF549900004E0F54A7B017A00790563 +:100610001218FF0200B290007AE0FF121B86C2801F +:100620007FA0121D81D2010200B2900081E020E77C +:10063000030200B27FB1121803E4900081F00200BF +:10064000B27D327C007F017E00121C50D296121EB9 +:1006500022C296227F017E00121C50D296121E22C8 +:10066000C2969000EFE0900094F090007AE0FF12C4 +:100670001B86227F017E00121C50D296121E22C2BF +:100680009690007AE0FF121B8622E4900094F0908E +:100690000074F07FA4121B8690007A2290007AE00A +:1006A000FF121B8622EFFD7C007F017E00121C5092 +:1006B0002290007AE0FF121B8622121B8690007A9D +:1006C000229000F0E014F012005E22EC4D6011E880 +:1006D000497017ED33EC3304600DE4FCFFFEFD229E +:1006E000E933E8330470F802099412095F58046092 +:1006F00009E4CC2481500628500902099E284003B1 +:1007000002099BC0E0EB4A7044B98006D0E0FB02CE +:10071000098AEF4E701CBD8008EBFFEAFEE9FD8000 +:10072000EBE98DF0A4FEE5F00207B4E9CDF9EAFEAD +:10073000EBFFEF89F0A4FCE5F0CE89F0A42EFFE4F6 +:1007400035F0CD89F0A42DFEE435F08067EF4E70D2 +:1007500005BD80D780C3EF8BF0A4ACF0EE8BF0A486 +:100760002CFCE435F0F8EF8AF0A42CE5F038FCE43A +:1007700033CB8DF0A42CFCE5F03BF8EE8AF0A42CF2 +:10078000FCE5F038F8E433CF89F0A42CFCE5F03830 +:10079000CF3400CE89F0A42FFFE5F03EFEE433C94C +:1007A0008DF0A42EFEE5F039CD8AF0A42FFFE5F000 +:1007B0003EFEE43DFD33D0E0FB50070BBB000F02D3 +:1007C000099EEC2CFCEF33FFEE33FEED33FD020906 +:1007D0007602099EEC5D046005E859047003020985 +:1007E0009412095F580460F6EC4860F2EC7004FD66 +:1007F000FEFF22C860DB2481C85009C39860025004 +:100800000602099B9850CAF582E9294B4A7005AB4C +:100810008202098A75F0007C1A7880C3EF9BEE9AF9 +:10082000ED99400DC3EF9BFFEE9AFEED99FDE84276 +:10083000F0DC23ACF0D0E0FFD0E0FED0E0FDAB82F6 +:1008400020E7101BEB60BAEC2CFCEF33FFEE33FE1D +:10085000ED33FD020976E803F830E705C0F075F0E6 +:1008600000EF2FFFEE33FEED33FD40B830E7C280DE +:10087000AA74F8CC6480CCC86480C8F58204604F48 +:10088000C3EB9FF5F0EA9E42F0E99D42F0E89C45FB +:10089000F0603C501DE5825FFFE582D313CB5BCB5C +:1008A000F42B5582FB50280ABA002409B90020080D +:1008B000801DE5825BFBE582D313CF5FCFF4C313CA +:1008C0002F5582FF50090EBE00050DBD00010CC35F +:1008D000EB9FF5F0EA9E42F0E99D42F0E89C45F07E +:1008E0006007CC4820E701B3EC2275F020800E753C +:1008F000F010800575F0087D007E007F003392D5F2 +:1009000030D503120BA1EC334010EF33FFEE33FE72 +:10091000ED33FDEC33FCD5F0ED22E5F0247EA2D5DD +:1009200013CC92E7CDCEFF22EDD2E7CD33EC33925C +:10093000D524814006E4FFFEFDFC22FCE4CFCECDB1 +:10094000CC24E0501174FF80EDC3CC13CCCD13CD7B +:10095000CE13CECF13CF0470F030D5DE020BA1E959 +:10096000D2E7C933E833F892D5EDD2E7CD33EC3393 +:10097000FC5002B2D522EC30E7100FBF000C0EBEC7 +:1009800000080DBD00040BEB6014A2D5EB13FCEDC9 +:1009900092E7FD2274FFFCFDFEFF22E480F8A2D561 +:1009A00074FF13FC7D80E480EFBB010CE58229F528 +:1009B00082E5833AF583E0225006E92582F8E622B3 +:1009C000BBFE06E92582F8E222E58229F582E5836D +:1009D0003AF583E49322BB010689828A83F0225090 +:1009E00002F722BBFE01F322EF8DF0A4A8F0CF8C1A +:1009F000F0A428CE8DF0A42EFE22BC000BBE002950 +:100A0000EF8DF084FFADF022E4CCF875F008EF2F05 +:100A1000FFEE33FEEC33FCEE9DEC984005FCEE9DC2 +:100A2000FE0FD5F0E9E4CEFD22EDF8F5F0EE8420DE +:100A3000D21CFEADF075F008EF2FFFED33FD40073F +:100A4000985006D5F0F222C398FD0FD5F0EA22C2E5 +:100A5000D5EC30E709B2D5E4C39DFDE49CFCEE3053 +:100A6000E715B2D5E4C39FFFE49EFE1209FAC3E482 +:100A70009DFDE49CFC80031209FA30D507C3E49F76 +:100A8000FFE49EFE22C5F0F8A3E028F0C5F0F8E5EB +:100A900082158270021583E038F022BB0110E582D6 +:100AA00029F582E5833AF583E0F5F0A3E0225009C9 +:100AB000E92582F886F008E622BBFE0AE92582F8DD +:100AC000E2F5F008E222E5832AF583E993F5F0A345 +:100AD000E9932275F008758200EF2FFFEE33FECD0B +:100AE00033CDCC33CCC58233C5829BED9AEC99E5EE +:100AF0008298400CF582EE9BFEED9AFDEC99FC0F7E +:100B0000D5F0D6E4CEFBE4CDFAE4CCF9A88222B845 +:100B100000C1B90059BA002DEC8BF084CFCECDFCCA +:100B2000E5F0CBF97818EF2FFFEE33FEED33FDEC57 +:100B300033FCEB33FB10D703994004EB99FB0FD840 +:100B4000E5E4F9FA227818EF2FFFEE33FEED33FDDE +:100B5000EC33FCC933C910D7059BE99A4007EC9BDD +:100B6000FCE99AF90FD8E0E4C9FAE4CCFB2275F06D +:100B700010EF2FFFEE33FEED33FDCC33CCC833C87E +:100B800010D7079BEC9AE899400AED9BFDEC9AFC84 +:100B9000E899F80FD5F0DAE4CDFBE4CCFAE4C8F933 +:100BA00022C3E49FFFE49EFEE49DFDE49CFC22EC56 +:100BB000F0A3EDF0A3EEF0A3EFF022D083D082F803 +:100BC000E4937012740193700DA3A393F8740193CE +:100BD000F5828883E4737402936860EFA3A3A38013 +:100BE000DFEF4E6012EF60010EEDBB010B89828AD0 +:100BF00083F0A3DFFCDEFA2289F05007F709DFFC5F +:100C0000A9F022BBFEFCF309DFFCA9F0228C228DA7 +:100C1000238A248B25AE07900082E0147003020C17 +:100C2000A2046003020E9EC290900081E060030265 +:100C30000E9EC3E5239414E5229405500EC3E525CA +:100C40009414E52494055003020E9E900094E0FF56 +:100C5000AD0685242C85252DAB23AA22121B469098 +:100C6000007FEFF064807003020E9E900001E52487 +:100C7000F0A3E525F09000857408F0E4900075F08D +:100C800090007CF0F508F509FE7F70FD7B017A008D +:100C90007903120BE1E490007BF0D2909000820483 +:100CA000F02290007FE0FD75F00DA424B7F582E4FA +:100CB000341E12108F1210B0FC7401931211379071 +:100CC000007FE075F00DA424AFF582E4341EF583B7 +:100CD000E493FFD39400400B90007CE09F5004E02D +:100CE00004F02290007FE0F96051FD121084121090 +:100CF000B012118E9000DF12110B24B3F582E43490 +:100D00001E12108F1209E89000E112110B24B4F5A5 +:100D100082E4341E12108FE91210B112118E90006D +:100D2000E312110B24B5F582E4341E12108F120960 +:100D3000E89000E5EEF0A3EFF0803E900078E0FE52 +:100D4000A3E0FF9000DFEEF0A3EFF0900083E0FC63 +:100D5000A3E0FD9000E1ECF0A3EDF0A3ECF0A3ED37 +:100D6000F0A312110B24B7F582E4341E12108F90F9 +:100D70000078E0FCA3E0121137900085E014F090B9 +:100D80000075E004F0AE22AF23E4FCFD9000E71212 +:100D90000BAFAE24AF25E4FCFD9000EB120BAF12BD +:100DA00011479000DF120E9F500E9000EB12114A77 +:100DB0009000E1120E9F400CC312117A50201210C5 +:100DC00097B5071A900078E522F0A3E523F0C290CA +:100DD000D312117C4066852208852309805E12119A +:100DE000479000E3120EB7500E9000EB12114A909C +:100DF00000E5120EB7400CD312117A40331210974F +:100E00006F702D900083E522F0A3E523F0D29012BD +:100E100010EEC083C082E0FF900085E0FE7401A860 +:100E200006088002C333D8FC4FD082D083F0800CF8 +:100E3000E4900081F0C290A312119822900085E006 +:100E400070161210EEE0FF90007BE06FFF121D3570 +:100E5000EFF09000857408F01210976F7040121D2B +:100E6000EF5005E4900080F0900080E0FF90007B60 +:100E7000E06F6023121DFF7D207C037F017E001246 +:100E80001C2790007BE0900080F090007FE09000B5 +:100E900081F04480121198C290E4900082F022FF09 +:100EA000E0FCA3E0FDC3EF9DFFEE9CFE121DB2C36C +:100EB000EF9527EE952622FFE0FCA3E0FDC3EF9D12 +:100EC000FFEE9CFE121DB2C3EF9527EE9526228EF3 +:100ED000228F23900082E024FE6034146068147036 +:100EE00003020FC22404600302105DC290900081CF +:100EF000E0600302105DAF23AE22121D73400302B7 +:100F0000105D90007612116D9000827402F0221232 +:100F1000105E501890007DE09402405CD290E4A3F3 +:100F2000F0900000F09000827403F022C3900077EC +:100F3000E09523900076E09522500412116D2290E6 +:100F4000007DE004F02212105E5030900000E0942A +:100F500000402890007EE0FF90007DE0B50719C2B8 +:100F600090E4900073F09000857404F0E490007BAE +:100F7000F09000827404F022021005C3E52394640B +:100F8000E5229400400790007EE0B4FF0280769056 +:100F9000007EE004F01211A0121540500302105D13 +:100FA000900000E0121069E522F0A3E523F0900024 +:100FB00000E004F0E0D39407500302105DE4F00277 +:100FC0001059B2901211A01214A3503C900085E069 +:100FD000B40410E524C454F0121075EFF0E490004E +:100FE00085F022121076E0FFE524540FFEEF4EF05C +:100FF000900073E004F09000857404F0900073E0BA +:10100000D394704058E48051AF23AE2212000350B5 +:1010100047900081E0703C900085E07019121076D6 +:10102000C083C082E0FF900000E0540FFEEF4ED07E +:1010300082D083F0800E900000E0C454F0440F1280 +:101040001075EFF0900073E0FF1211C3900081E083 +:101050004480F0C290E48001E4900082F022AF234B +:10106000AE2212000322FCE52A25E02486F582E464 +:101070003400F58322FF900073E02403F582E4340A +:1010800000F5832275F00DA424B2F582E4341EF538 +:1010900083E493FF7E002290007FE075F00DA4248E +:1010A000B6F582E4341EF583E493FF900075E022E8 +:1010B000ED75F00DA424B0F582E4341EF583E493BD +:1010C00022EF75F00DA424B9F582E4341EF583E413 +:1010D0009322AC3CAD3DE41208EFE4FBFA79C8780A +:1010E000421207D4E4FBFA792078410206CB900043 +:1010F00075E024FFFFE434FFFE7C007D08120A4FF8 +:1011000074032FF58274003EF58322EEF0A3EFF016 +:10111000E975F00DA422E0FCA3E0FDEC547FFAD3C6 +:10112000ED9400EA940022AC38AD391209E8AC061F +:10113000AD07AB3BAA3A22FD1209E87C007D6412A0 +:1011400009FA8E268F27229000E7A3A3E0FEA3E0F2 +:1011500022AB46AA47A948854C827583000209A99B +:10116000852C34852D35AB2BAA2AAD2922E522F01A +:10117000A3E523F0E490007DF022E5239509E52224 +:10118000950822AFFBAEFC7C007D0A0209E8FA74E8 +:101190000193FDAC020209E8F090007F7480F02218 +:1011A0007B007A007924AF23AE2222E53075F00D62 +:1011B000A422E0FEA3E0FFC322EC4480AF05F0A32D +:1011C000EFF0228F25E4F527F526E5252401FFE43D +:1011D00033FEC3E5269FEE6480F87480985039741E +:1011E00003252612107CE0C4540FFF12106912115F +:1011F000164007EF1210691211B974032526121058 +:101200007CE0540FFF1210691211164007EF121004 +:10121000691211B9052680B2E4F526900000E0FFBE +:10122000E526C39F40030212DFE526121069E03075 +:10123000E7030212D1AF26900000E0FEEFC39E400C +:10124000030212CDEF25E02488F582E43400F58313 +:10125000E0FCA3E0FDEF121069ECF0A3EDF0E4FE7A +:10126000E5252401FDE433FCEEC39DEC6480F874B5 +:101270008098505574032E12107CE0F9C4540FFD71 +:10128000EF2401FBE433FAEDB50316E4B50212E9ED +:10129000540FFDEFC454F04DFD74032E12107CED7D +:1012A000F0EF2401FDE433FC74032E12107CE0F90E +:1012B000540FB50511E4B5040DE954F04FFD740366 +:1012C0002E12107CEDF00E80970F0212370527804A +:1012D00009E526121069E0547FF0052602121B90E2 +:1012E0000000E0C39527F0228F308A328B33E4F57B +:1012F00036F5371210C16D6006E5365537FF22E529 +:10130000307014901EAE93FD7C00AE34AF351209E0 +:10131000FA8E388F39800CE5301210B1F53874012F +:1013200093F5391211AB24ADF582E4341EF583E454 +:1013300093D394004021AF33AE321213C324ADF5E2 +:1013400082E4341E12108F121127AF33AE32121CFA +:10135000C7EF60037536011211AB24AEF582E43499 +:101360001EF583E493D394004021AF35AE341213BD +:10137000C324AEF582E4341E12108F121127AF354C +:10138000AE34121CC7EF6003753701E5365537FBE5 +:101390006401702CE530121084AC38AD391209E8C4 +:1013A000900078EEF0A3EFF01211AB24B4F582E4D4 +:1013B000341E12108F1209E8900083EEF0A3EFF0B4 +:1013C000AF0322121D128E3A8F3BE53075F00DA44B +:1013D00022D3E50B9400E50A9400401F121183C349 +:1013E000EF950BFFEE950A9000DDF0A3EFF0AFFB59 +:1013F000AEFC1209E88E0A8F0B80081211838E0A48 +:101400008F0B229000DD1211B29464EE9400501103 +:10141000121199E4F50CF50DF50EF50F900082F020 +:101420002230933C8E0E8F0F900074E014602B04DA +:101430007070E50D450C606AE50F450E6064900024 +:101440007FE0FF648060071210C164016054AB0F3D +:10145000AA0EAD0DAC0CE4FF803EAF0FAE0E803F88 +:101460009000DDE0F50CA3E0F50D900074E0146051 +:101470002A04702EE50D450C6028E50F450E60220C +:1014800090007FE0FF648060051210C16014AB0D16 +:10149000AA0CAD0FAC0E7F01020C0DAF0DAE0C12FD +:1014A0000ECF228E2B8F2C8B2D8A2E892FE4F53098 +:1014B000900000E0FFE530C39F400302153EE52C9D +:1014C000AE2B7803CEC313CE13D8F9FDAC06E52CB2 +:1014D000AE2B7802CEC313CE13D8F92DF532EE3CE5 +:1014E000F531E5301210691211B29532EE95315096 +:1014F000028004AE31AF328E318F32E53012106986 +:101500001211B29532FDEE9531FCC3ED952CEC95A0 +:101510002B5026E5322FFFE5313EFEC3E52C9FE53B +:101520002B9E5015E52F452E452D600BAB2DAA2E79 +:10153000A92FE5301209D6D32205300214B0C322F8 +:101540008E258F268B278A2889291214A3500122E1 +:10155000E4F52A900000E0FFE52AC39F507B1210BB +:1015600067E0FCA3E0FDAE047803CEC313CE13D82E +:10157000F9FBAA06EDAE047802CEC313CE13D8F958 +:101580002BFDEE3A121066E0C4F854F0C868FEA3D2 +:10159000E0C4540F482DFFEC3EFEC3E5269FFDE559 +:1015A000259E121066E0FAA3E0FBD39DEA9C40243E +:1015B000E5262FFFE5253EFEC3EB9FEA9E5015E58D +:1015C0002945284527600BAB27AA28A929E52A1217 +:1015D00009D6D322052A021553C322C0E0C0F0C0A9 +:1015E00083C082C0D075D000C000C001C002C0035B +:1015F000C004C005C006C007E5985403F55FF45267 +:1016000098E55F30E017121E3D9000D9121CBCEF28 +:10161000F09000D9E004F0E0B44002E4F0E55F307F +:10162000E12E9000DCE0D39400401A9000D8E02432 +:1016300060F8E6FF121E3A9000D8E004F09000DC5B +:10164000E014F08002D2009000D8E0B42002E4F070 +:10165000D007D006D005D004D003D002D001D000EE +:10166000D0D0D082D083D0F0D0E032120022787F68 +:10167000E4F6D8FD75817F0216B5020076E493A3E7 +:10168000F8E493A34003F68001F208DFF48029E434 +:1016900093A3F85407240CC8C333C4540F4420C880 +:1016A000834004F456800146F6DFE4800B01020417 +:1016B0000810204080901885E47E019360BCA3FF51 +:1016C000543F30E509541FFEE493A360010ECF544C +:1016D000C025E060A840B8E493A3FAE493A3F8E43B +:1016E00093A3C8C582C8CAC583CAF0A3C8C582C8A7 +:1016F000CAC583CADFE9DEE780BEC0E0C0F0C083B0 +:10170000C082C0D075D000C000C001C002C003C0FC +:1017100004C005C006C007E5D85487F521F452D8A7 +:10172000E5F730E508E5F730E60312005A53F7DF36 +:10173000E52130E708E5D930E00312002AE5213041 +:10174000E008E5DA30E0031213D1E52130E108E5E5 +:10175000DB30E003121E43E52130E208E5DC30E037 +:1017600003121E44D007D006D005D004D003D00207 +:10177000D001D000D0D0D082D083D0F0D0E0328A57 +:10178000478B488D828C83AD07AC068552547555C6 +:1017900080AB82AA83AF51121BF3E54FD394004074 +:1017A0001BE4F553E553C3954F5011AB4EAA4DAD15 +:1017B0004CAC4BAF51121BF3055380E8E4F553E5F5 +:1017C00053C3955050347403255412107CE0555582 +:1017D000600AAB4EAA4DAD4CAC4B8008AB4AAA494F +:1017E000AD48AC47AF51121BF3E555C313F5557027 +:1017F000050554755580055380C5C29090008274CC +:1018000005F022AE07E4F543121CA0900000E004AE +:10181000FF121CF612187E900000E0FFE543C39F04 +:101820005012121CB0121CF2121CB0F583121CAA2A +:10183000054380E3900076E0FF121CF690007612DC +:101840001CAA12187EE4F543900073E02401FFE423 +:1018500033FEC3E5439FEE6480F87480985017749C +:10186000032543121CED0543E543541F70DA121E95 +:1018700037121E3080D27F55121CF6021E37121E00 +:1018800037121E30224200F700004200F3000042EF +:1018900000F900004200F500004100810041008293 +:1018A00000410094804100740041007F8041007A33 +:1018B0000042000100004200830000420078000066 +:1018C000410085004100750041007C00410073002B +:1018D0004100800041007B00410000004100D90030 +:1018E0004100DB004100D7004100D8004100DC008E +:1018F0004100D600C1004100DA0041009500008B94 +:10190000438A448945754B01E4F54CE54CC3954940 +:10191000502B121151C4540FFF640F600912194D5E +:1019200070027F018F4B121151FF540F640F600939 +:1019300012194D70027F018F4B054C80CEAF4A15B6 +:101940004AEF70C1C2909000827405F022AB43AAA6 +:1019500044A945EF540775F002A4F58285F083127F +:101960000A9BFDACF0AF4B121D62E54B7F0022F5E8 +:1019700083E493FF7E00E54275F00DA42448F582D0 +:10198000E4341EF583E493FC740193FD0209E8E559 +:101990004275F00DA422E0FF7E000209E890009459 +:1019A0007480F0E4900074F022900003E0FCA3E067 +:1019B000FD22E49000F1F0A3F022900082E024FBED +:1019C00022901E50E493FFD3940022C0E0C083C055 +:1019D00082C0D075D000C004C005C006C00753C87F +:1019E0007F9000F7E0FEA3E0FF4E700353C8FB902A +:1019F00000F3121B3B50099000F7E4F0A3F0800DB8 +:101A0000C39000F8E09DF09000F7E09CF0D007D084 +:101A100006D005D004D0D0D082D083D0E032C0E050 +:101A2000C083C082C0D075D000C004C005C006C04D +:101A30000753917F9000F9E0FEA3E0FF4E7003533F +:101A400091FB9000F5121B3B50099000F9E4F0A3C4 +:101A5000F0800DC39000FAE09DF09000F9E09CF05A +:101A6000D007D006D005D004D0D0D082D083D0E02B +:101A700032AE05AD07E4FCFB7FAA121CF6AF0512DF +:101A80001CF6EE75F00DA4241EF582E4341FF583D8 +:101A9000E493FFECC39F500774082CFC0B80F4EB1D +:101AA00004FF121CA2E4FCECC39B500974032C122B +:101AB0001CED0C80F27F55121CF6021E37AE07E4B7 +:101AC000FDF543121CA0900001E0FF121CF69000EF +:101AD00001121CAA900078E0FF121CF69000781208 +:101AE0001CAA900083E0FF121CF6900083121CAA2F +:101AF00074032D121CED0DBD03F67F55121CF6026A +:101B00001E37AB07AA06E4F9F87F407E427D0FFC42 +:101B1000120B0FA804A905AA06AB077F207ED77D6C +:101B2000757C01120B0FC3E49FFFE49EFE22AB07FE +:101B3000AA06E4F9F87FE87E03FD22E0FCA3E0FDBD +:101B4000C3EF9DEE9C228F288D298A2A8B2B752E20 +:101B500080E5282480701EE4F52F121160AF2F124B +:101B600012E8EF6005852F2E8019052FE52FC3940D +:101B70000840E7800E121160AF281212E8EF6003F0 +:101B800085282EAF2E228F4390007AE0F5447F0BFC +:101B9000121E4043DA011200707D0A7C007F017E34 +:101BA00000121C50121E22E4900082F0900081F07E +:101BB000900095E543F090007AF0AF44229000D970 +:101BC000E0FF9000D7E0B507057E017F002290007E +:101BD000D7121CBCE0FD7C009000D7E004F0E0B41C +:101BE0004002E4F09000D6E0FEEE4204E4F0AE04E1 +:101BF000AF05228F568C578D588A598B5AD290E553 +:101C000056640124FF92807F0A7E0012002E121E6D +:101C100022C290E55624FF9280AD5AAC597F0A7ECD +:101C20000012002E021E228E288F298C2A8D2B1244 +:101C30001B2E121B0F121D8E9000F7E52AF0A3E554 +:101C40002BF09000F3E528F0A3E529F043C8042227 +:101C50008E458F468C478D48121B2E121B0F121D6E +:101C60009A9000F9E547F0A3E548F09000F5E545C6 +:101C7000F0A3E546F043910422120021121E061241 +:101C80001E0D121DBE121E28121D4C121DDC121D2F +:101C9000C8121DD2121DA6121E14121E2C021E1BCB +:101CA0007FAA121CF6AF06021CF6A3E0FF021CF688 +:101CB000E54325E02486F582E4340022E02496F50D +:101CC00082E43400F58322C3ED9BF582EC9AF58320 +:101CD000C3E5829FE5839E5011ED2BFDEC3AFCC3DA +:101CE000EF9DEE9C50047F0180027F0022F582E48C +:101CF0003400F583E0FFC2009000DBE0B42002E492 +:101D0000F09000DBE02460F8A607E004F0A3E00414 +:101D1000F0228E3C8F3D1210D2E4FBFA79FA784320 +:101D20001208715009E4FFFE7DFA7C438003121013 +:101D3000D2120928227E1DE4FDEF30E70625E06E71 +:101D4000FF8004EF25E0FF0DBD08EE22AF88538829 +:101D5000AF758CA0758DCBEF5440FEEF54104E4202 +:101D60008822D290EF24FF92807F0A7E0012002EFC +:101D7000021E22C3EF9414EE94054003D38001C3E6 +:101D800022AE07121CA07F55121CF6021E37AD07AB +:101D9000AC06ECF5CBAF058FCA22AD07AC06ECF56F +:101DA00093AF058F9222C2DE75D90575F9FF75963E +:101DB0000122EE30E707C3E49FFFE49EFE2275E3B5 +:101DC0004075E10175E20122E59154045391FB4213 +:101DD0009122758E5475892243885022E5C8540497 +:101DE00053C8FB42C82253984FEB4F4DF59822E55C +:101DF000C8C320E201D322E591C320E201D32253DC +:101E0000C8FB53C87F2275A41175D4CF2275A54194 +:101E100075D5772253F77F75DA302275E69075A86D +:101E2000B022E59120E2FB22E4F5A922439810229A +:101E30003000FD22C2DE22D299228F9922AF992250 +:101E40008F8C222222011F00015E01030301183C36 +:101E500000000D0400017201020201283C08000884 +:101E60001700018601030301183C00001F0A00014E +:101E70002C01030301183C0000003B0701F403029E +:101E80000102403C00000712000190010303011809 +:101E90003C000017010001C201020201183C0001D0 +:101EA00024010000D2010202010C3C0001011F00CC +:101EB000015E01030301183C00000D0400017201E2 +:101EC000020201283C0800081700018601030301F3 +:101ED000183C00001F0A00012C01030301183C00FC +:101EE00000003B0701F403020102403C000007121E +:101EF00000019001030301183C000017010001C21A +:101F000001020201183C000124010000D20102027A +:101F1000010C3C0001011F00015E01030301183C9C +:101F200000000D0400017201020201283C080008B3 +:101F30001700018601030301183C00001F0A00017D +:101F40002C01030301183C0000003B0701F40302CD +:101F50000102403C00000712000190010303011838 +:101F60003C000017010001C201020201183C0001FF +:0D1F700024010000D2010202010C3C00011E +:00000001FF From be19af15e2ed65d4c9b445f159a458557289c362 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 4 Dec 2018 21:31:23 +0100 Subject: [PATCH 0657/2222] Announce switches --- sonoff/sonoff.ino | 3 +- sonoff/xdrv_12_home_assistant.ino | 137 ++++++++++++++++++++---------- 2 files changed, 92 insertions(+), 48 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 0772e76f2..947f5d165 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1310,7 +1310,8 @@ boolean SendKey(byte key, byte device, byte state) Format(key_topic, tmp, sizeof(key_topic)); if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { if (!key && (device > devices_present)) device = 1; // Only allow number of buttons up to number of devices - GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), key)); // cmnd/switchtopic/POWERx + GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), + Settings.flag.device_index_enable)); // cmnd/switchtopic/POWERx if (9 == state) { mqtt_data[0] = '\0'; } else { diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 78b8b4841..b002049a2 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -33,16 +33,21 @@ const char HASS_DISCOVER_RELAY[] PROGMEM = "\"payload_available\":\"" D_ONLINE "\"," // Online "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline -const char HASS_DISCOVER_BUTTON[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 BTN "\"state_topic\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") // "\"value_template\":\"{{value_json.%s}}\"," // POWER2 - "\"payload_on\":\"%s\"," // TOGGLE + "\"payload_on\":\"%s\"," // TOGGLE / ON // "\"optimistic\":\"false\"," // false is Hass default when state_topic is set "\"availability_topic\":\"%s\"," // tele/dualr2/LWT "\"payload_available\":\"" D_ONLINE "\"," // Online - "\"payload_not_available\":\"" D_OFFLINE "\"," // Offline - "\"force_update\":true"; + "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline + +const char HASS_DISCOVER_BUTTON[] PROGMEM = + "%s,\"force_update\":true"; + +const char HASS_DISCOVER_SWITCH[] PROGMEM = + "%s,\"payload_off\":\"%s\""; // OFF const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = "%s,\"brightness_command_topic\":\"%s\"," // cmnd/led2/Dimmer @@ -92,7 +97,7 @@ const char HASS_DISCOVER_RELAY_SHORT[] PROGMEM = "\"pl_avail\":\"" D_ONLINE "\"," // Online "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline -const char HASS_DISCOVER_BUTTON_SHORT[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH_SHORT[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 BTN "\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") // "\"value_template\":\"{{value_json.%s}}\"," // POWER2 @@ -100,8 +105,14 @@ const char HASS_DISCOVER_BUTTON_SHORT[] PROGMEM = // "\"optimistic\":\"false\"," // false is Hass default when state_topic is set "\"avty_t\":\"%s\"," // tele/dualr2/LWT "\"pl_avail\":\"" D_ONLINE "\"," // Online - "\"pl_not_avail\":\"" D_OFFLINE "\"," // Offline - "\"frc_upd\":true"; + "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline + +const char HASS_DISCOVER_BUTTON_SHORT[] PROGMEM = + "%s,\"frc_upd\":true"; + +const char HASS_DISCOVER_SWITCH_SHORT[] PROGMEM = + "%s,\"pl_off\":\"%s\""; // OFF + const char HASS_DISCOVER_LIGHT_DIMMER_SHORT[] PROGMEM = "%s,\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer @@ -266,9 +277,75 @@ void HAssAnnounceRelayLight(void) } } -void HAssAnnounceButton(void) +void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key) { + char stopic[TOPSZ]; char sidx[8]; + + mqtt_data[0] = '\0'; // Clear retained message + + // Clear or Set topic + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s_%s_%d/config"), + topic, key?"BTN":"SW",device+1); + + if (Settings.flag.hass_discovery && present) { + char name[33]; + char value_template[33]; + char _state_topic[TOPSZ]; + char _availability_topic[TOPSZ]; + char prefix[TOPSZ]; + char *state_topic = _state_topic; + char *availability_topic = _availability_topic; + + if (device+1 > MAX_FRIENDLYNAMES) { + snprintf_P(name, sizeof(name), PSTR("%s %s %d"), Settings.friendlyname[0], key?"BTN":"SW", device+1); + } else { + snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[device], key?"BTN":"SW"); + } + GetPowerDevice(value_template, device+1, sizeof(value_template), Settings.flag.device_index_enable); + GetTopic_P(state_topic, CMND, topic, value_template); // State of button is sent as CMND TOGGLE, state of switch is sent as ON/OFF + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + FindPrefix(state_topic, availability_topic, prefix); + if (Settings.flag3.hass_short_discovery_msg) { + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_SHORT:HASS_DISCOVER_BUTTON_SWITCH, + name, state_topic, Settings.state_text[key?2:1], availability_topic); + if (key) snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SHORT:HASS_DISCOVER_BUTTON, + mqtt_data); + else snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SWITCH_SHORT:HASS_DISCOVER_SWITCH, + mqtt_data, Settings.state_text[0]); + + if (Settings.flag3.hass_short_discovery_msg) + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + } + MqttPublish(stopic, true); +} + +void HAssAnnounceSwitches(void) +{ + char sw_topic[sizeof(Settings.switch_topic)]; + + // Send info about buttons + char *tmp = Settings.switch_topic; + Format(sw_topic, tmp, sizeof(sw_topic)); + if ((strlen(sw_topic) != 0) && strcmp(sw_topic, "0")) { + for (byte switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) { + uint8_t switch_present = 0; + + if ((pin[GPIO_SWT1 + switch_index] < 99) || (pin[GPIO_SWT1_NP + switch_index] < 99)) { + switch_present = 1; + } + + HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 0); + } + } +} + +void HAssAnnounceButtons(void) +{ char stopic[TOPSZ]; char key_topic[sizeof(Settings.button_topic)]; @@ -282,47 +359,12 @@ void HAssAnnounceButton(void) if (!button_index && ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module))) { button_present = 1; } else { - if (pin[GPIO_KEY1 + button_index] < 99) { + if ((pin[GPIO_KEY1 + button_index] < 99) || (pin[GPIO_KEY1_NP + button_index] < 99)) { button_present = 1; } } - mqtt_data[0] = '\0'; // Clear retained message - - // Clear or Set topic - snprintf_P(sidx, sizeof(sidx), PSTR("_%d"), button_index+1); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s%s/config"), "binary_sensor", key_topic, sidx); - - if (Settings.flag.hass_discovery && button_present) { - char name[33]; - char value_template[33]; - char _state_topic[TOPSZ]; - char _availability_topic[TOPSZ]; - char prefix[TOPSZ]; - char *state_topic = _state_topic; - char *availability_topic = _availability_topic; - - if (button_index+1 > MAX_FRIENDLYNAMES) { - snprintf_P(name, sizeof(name), PSTR("%s %d BTN"), Settings.friendlyname[0], button_index+1); - } else { - snprintf_P(name, sizeof(name), PSTR("%s BTN"), Settings.friendlyname[button_index]); - } - GetPowerDevice(value_template, button_index+1, sizeof(value_template), Settings.flag.device_index_enable); - GetTopic_P(state_topic, CMND, key_topic, value_template); // State of button is sent as CMND TOGGLE - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - FindPrefix(state_topic, availability_topic, prefix); - if (Settings.flag3.hass_short_discovery_msg) { - Shorten(&state_topic, prefix); - Shorten(&availability_topic, prefix); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SHORT:HASS_DISCOVER_BUTTON, - name, state_topic, Settings.state_text[2], availability_topic); - - if (Settings.flag3.hass_short_discovery_msg) - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); - } - MqttPublish(stopic, true); + HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 1); } } } @@ -440,9 +482,10 @@ void HAssDiscovery(uint8_t mode) HAssAnnounceRelayLight(); // Send info about buttons - HAssAnnounceButton(); + HAssAnnounceButtons(); - // TODO: Send info about switches + // Send info about switches + HAssAnnounceSwitches(); // Send info about sensors HAssAnnounceSensors(); From 4b287ab4cbf3f4537c93131695b4f4121678a528 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 5 Dec 2018 12:23:42 +0100 Subject: [PATCH 0658/2222] Final fix compile error (#4509) Final fix soft_spi_flg compile error (#4509) --- sonoff/sonoff.ino | 3 ++- tools/{ => fw_efm8bb1}/RF-Bridge-EFM8BB1-20181127.hex | 0 2 files changed, 2 insertions(+), 1 deletion(-) rename tools/{ => fw_efm8bb1}/RF-Bridge-EFM8BB1-20181127.hex (100%) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 0772e76f2..869eaf7eb 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -167,7 +167,7 @@ uint8_t dht_flg = 0; // DHT configured uint8_t energy_flg = 0; // Energy monitor configured uint8_t i2c_flg = 0; // I2C configured uint8_t spi_flg = 0; // SPI configured -uint8_t soft_spi_flg = 0; // Software SPI ** Temporary fix to satisfy compiler ** +uint8_t soft_spi_flg = 0; // Software SPI configured uint8_t light_type = 0; // Light types uint8_t ntp_force_sync = 0; // Force NTP sync byte serial_in_byte; // Received byte @@ -2498,6 +2498,7 @@ void GpioInit(void) my_module.gp.io[14] = GPIO_SPI_CLK; pin[GPIO_SPI_CLK] = 14; } + soft_spi_flg = ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && ((pin[GPIO_SSPI_MOSI] < 99) || (pin[GPIO_SSPI_MOSI] < 99))); #endif // USE_SPI #ifdef USE_I2C diff --git a/tools/RF-Bridge-EFM8BB1-20181127.hex b/tools/fw_efm8bb1/RF-Bridge-EFM8BB1-20181127.hex similarity index 100% rename from tools/RF-Bridge-EFM8BB1-20181127.hex rename to tools/fw_efm8bb1/RF-Bridge-EFM8BB1-20181127.hex From 94786d32177c62521489af25a1349a50350316d6 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 5 Dec 2018 20:20:36 +0100 Subject: [PATCH 0659/2222] Fix logic for ON/OFF vs TOGGLE --- sonoff/xdrv_12_home_assistant.ino | 41 ++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index b002049a2..b5d0c076c 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -43,10 +43,10 @@ const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = "\"payload_available\":\"" D_ONLINE "\"," // Online "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline -const char HASS_DISCOVER_BUTTON[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE[] PROGMEM = "%s,\"force_update\":true"; -const char HASS_DISCOVER_SWITCH[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = "%s,\"payload_off\":\"%s\""; // OFF const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = @@ -107,10 +107,10 @@ const char HASS_DISCOVER_BUTTON_SWITCH_SHORT[] PROGMEM = "\"pl_avail\":\"" D_ONLINE "\"," // Online "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline -const char HASS_DISCOVER_BUTTON_SHORT[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT[] PROGMEM = "%s,\"frc_upd\":true"; -const char HASS_DISCOVER_SWITCH_SHORT[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT[] PROGMEM = "%s,\"pl_off\":\"%s\""; // OFF @@ -277,7 +277,7 @@ void HAssAnnounceRelayLight(void) } } -void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key) +void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, byte toggle) { char stopic[TOPSZ]; char sidx[8]; @@ -311,10 +311,12 @@ void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key) Shorten(&availability_topic, prefix); } snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_SHORT:HASS_DISCOVER_BUTTON_SWITCH, - name, state_topic, Settings.state_text[key?2:1], availability_topic); - if (key) snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SHORT:HASS_DISCOVER_BUTTON, + name, state_topic, Settings.state_text[toggle?2:1], availability_topic); + if (toggle) snprintf_P(mqtt_data, sizeof(mqtt_data), + Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT:HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, mqtt_data); - else snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SWITCH_SHORT:HASS_DISCOVER_SWITCH, + else snprintf_P(mqtt_data, sizeof(mqtt_data), + Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT:HASS_DISCOVER_BUTTON_SWITCH_ONOFF, mqtt_data, Settings.state_text[0]); if (Settings.flag3.hass_short_discovery_msg) @@ -333,13 +335,21 @@ void HAssAnnounceSwitches(void) Format(sw_topic, tmp, sizeof(sw_topic)); if ((strlen(sw_topic) != 0) && strcmp(sw_topic, "0")) { for (byte switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) { - uint8_t switch_present = 0; + byte switch_present = 0; + byte toggle = 1; if ((pin[GPIO_SWT1 + switch_index] < 99) || (pin[GPIO_SWT1_NP + switch_index] < 99)) { switch_present = 1; } - HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 0); + // Check if MQTT message will be ON/OFF or TOGGLE + if (Settings.switchmode[switch_index] == FOLLOW || Settings.switchmode[switch_index] == FOLLOW_INV || + !strcmp(mqtt_topic, sw_topic) || !strcmp(Settings.mqtt_grptopic, sw_topic)) + { + toggle = 0; + } + + HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 0, toggle); } } } @@ -354,7 +364,8 @@ void HAssAnnounceButtons(void) Format(key_topic, tmp, sizeof(key_topic)); if ((strlen(key_topic) != 0) && strcmp(key_topic, "0")) { for (byte button_index = 0; button_index < MAX_KEYS; button_index++) { - uint8_t button_present = 0; + byte button_present = 0; + byte toggle = 1; if (!button_index && ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module))) { button_present = 1; @@ -364,7 +375,13 @@ void HAssAnnounceButtons(void) } } - HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 1); + // Check if MQTT message will be ON/OFF or TOGGLE + if (!strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) + { + toggle = 0; + } + + HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 1, toggle); } } } From a36ead52fa547ea31b6c269770eb2da67f2537b1 Mon Sep 17 00:00:00 2001 From: Gunnar Norin Date: Wed, 5 Dec 2018 23:25:25 +0100 Subject: [PATCH 0660/2222] Initial translation to Swedish --- sonoff/language/sv-SE.h | 597 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 597 insertions(+) create mode 100644 sonoff/language/sv-SE.h diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h new file mode 100644 index 000000000..271f3d649 --- /dev/null +++ b/sonoff/language/sv-SE.h @@ -0,0 +1,597 @@ +/* + sv-SE.h - localization for Swedish - Svenska for Sonoff-Tasmota + + Copyright (C) 2018 Gunnar Norin + + 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_SV_SE_H_ +#define _LANGUAGE_SV_SE_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. + * + * Updated until v6.2.1.11 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) +// https://www.science.co.il/language/Locale-codes.php +#define LANGUAGE_LCID 1053 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "sv" + +// "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 "MånTisOnsTorFreLörSön" +#define D_MONTH3LIST "JanFebMarAprMajJunJulAugSepOktNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Luftkvalitet" +#define D_AP "AP" // Access Point +#define D_AS "som" +#define D_AUTO "AUTO" +#define D_BLINK "Blinka" +#define D_BLINKOFF "BlinkaAv" +#define D_BOOT_COUNT "Uppstartsräknare" +#define D_BRIGHTLIGHT "Ljust" +#define D_BSSID "BSSId" +#define D_BUTTON "Knapp" +#define D_BY "av" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Kanal" +#define D_CO2 "Koldioxid" +#define D_CODE "kod" // Button code +#define D_COLDLIGHT "Kallt" +#define D_COMMAND "Kommando" +#define D_CONNECTED "Ansluten" +#define D_COUNT "Räkna" +#define D_COUNTER "Räknare" +#define D_CURRENT "Ström" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Mörkt" +#define D_DEBUG "Debug" +#define D_DISABLED "Inaktiverad" +#define D_DISTANCE "Distans" +#define D_DNS_SERVER "DNS-server" +#define D_DONE "Gjort" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulation" +#define D_ENABLED "Aktiverad" +#define D_ERASE "Ta bort" +#define D_ERROR "Fel" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Misslyckades" +#define D_FALLBACK "Reserv" +#define D_FALLBACK_TOPIC "Reservämne" +#define D_FALSE "Falskt" +#define D_FILE "Fil" +#define D_FREE_MEMORY "Ledigt minne" +#define D_FREQUENCY "Frekvens" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Grupp" +#define D_HOST "Värd" +#define D_HOSTNAME "Värdnamn" +#define D_HUMIDITY "Fuktighet" +#define D_ILLUMINANCE "Belysnings" +#define D_IMMEDIATE "Omedelbar" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infraröd" +#define D_INITIALIZED "Initialiserad" +#define D_IP_ADDRESS "IP-adress" +#define D_LIGHT "Ljus" +#define D_LWT "LWT" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "fler tryck" +#define D_NOISE "Oväsen" +#define D_NONE "Ingen" +#define D_OFF "Av" +#define D_OFFLINE "Off-line" +#define D_OK "Ok" +#define D_ON "På" +#define D_ONLINE "Ansluten" +#define D_PASSWORD "Lösenord" +#define D_PORT "Port" +#define D_POWER_FACTOR "Spänningsfaktor" +#define D_POWERUSAGE "Spänning" +#define D_POWERUSAGE_ACTIVE "Aktiv spänning" +#define D_POWERUSAGE_APPARENT "Skenbar spänning" +#define D_POWERUSAGE_REACTIVE "Responsiv spänning" +#define D_PRESSURE "Tryck" +#define D_PRESSUREATSEALEVEL "Havstryck" +#define D_PROGRAM_FLASH_SIZE "Program-flashstorlek" +#define D_PROGRAM_SIZE "Programstorlek" +#define D_PROJECT "Projekt" +#define D_RECEIVED "Mottagen" +#define D_RESTART "Omstart" +#define D_RESTARTING "Startar om" +#define D_RESTART_REASON "Restart Reason" +#define D_RESTORE "återställ" +#define D_RETAINED "bevarad" +#define D_RULE "Regel" +#define D_SAVE "Spara" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Starta" +#define D_STD_TIME "STD" +#define D_STOP "Stoppa" +#define D_SUBNET_MASK "Nätmask" +#define D_SUBSCRIBE_TO "Prenumera på" +#define D_SUCCESSFUL "Lyckat" +#define D_SUNRISE "Soluppgång" +#define D_SUNSET "Solnedgång" +#define D_TEMPERATURE "Temperatur" +#define D_TO "till" +#define D_TOGGLE "Växla" +#define D_TOPIC "Ämne" +#define D_TRANSMIT "Sänd" +#define D_TRUE "Sant" +#define D_TVOC "TVOC" +#define D_UPGRADE "uppgradera" +#define D_UPLOAD "Ladda upp" +#define D_UPTIME "Upptid" +#define D_USER "Användare" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Låg" +#define D_UV_INDEX_2 "Med" +#define D_UV_INDEX_3 "Hög" +#define D_UV_INDEX_4 "Farligt" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" // Out of Range +#define D_UV_LEVEL "UV nivå" +#define D_UV_POWER "UV kraft" +#define D_VERSION "Version" +#define D_VOLTAGE "Voltage" +#define D_WEIGHT "Vikt" +#define D_WARMLIGHT "Varm" +#define D_WEB_SERVER "Webbserver" + +// sonoff.ino +#define D_WARNING_MINIMAL_VERSION "VARNING Denna version supporterar inte beständiga inställningar" +#define D_LEVEL_10 "nivå 1-0" +#define D_LEVEL_01 "nivå 0-1" +#define D_SERIAL_LOGGING_DISABLED "Seriell loggning inaktiverad" +#define D_SYSLOG_LOGGING_REENABLED "Syslog återaktiverad" + +#define D_SET_BAUDRATE_TO "Ange Baudrate till" +#define D_RECEIVED_TOPIC "Mottaget ämne" +#define D_DATA_SIZE "Datastorlek" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blockerad loop" +#define D_WPS_FAILED_WITH_STATUS "WPS-konfigurering MISSLYCKADES med status" +#define D_ACTIVE_FOR_3_MINUTES "aktiv för 3 minuter" +#define D_FAILED_TO_START "misslyckades att starta" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "Ansluter till AP" +#define D_IN_MODE "i läge" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Anslutning misslyckades mottog ingen IP-adress" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Anslutning misslyckades, kunde inte nå AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Anslutning misslyckades, fel lösenord för AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Anslutning misslyckadess med AP, timeout" +#define D_ATTEMPTING_CONNECTION "Försöker ansluta..." +#define D_CHECKING_CONNECTION "Kontrollerar anslutning..." +#define D_QUERY_DONE "Fråga utförd. MQTT-tjänster hittades" +#define D_MQTT_SERVICE_FOUND "MQTT-tjänst hittades på" +#define D_FOUND_AT "hittades vid" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog-värd hittades inte" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Sparade till flash vid" +#define D_LOADED_FROM_FLASH_AT "Laddade från flash vid" +#define D_USE_DEFAULTS "Använd standard" +#define D_ERASED_SECTOR "Rensade sektor" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "För att använda Tasmota, aktivera JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - var god uppgradera" +#define D_WEBSERVER_ACTIVE_ON "Webbserver aktiv på" +#define D_WITH_IP_ADDRESS "med IP-adress" +#define D_WEBSERVER_STOPPED "Webbserver stoppad" +#define D_FILE_NOT_FOUND "Filen hittades inte" +#define D_REDIRECTED "Omdirigerad till fångstportal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifihanterare ange accesspunkt och behåll station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifihanterare ange accesspunkt" +#define D_TRYING_TO_CONNECT "Försöker att ansluta enheten till nätverk" + +#define D_RESTART_IN "Omstart om" +#define D_SECONDS "sekunder" +#define D_DEVICE_WILL_RESTART "Enheten kommer att starta om inom ett antal sekunder" +#define D_BUTTON_TOGGLE "Växla" +#define D_CONFIGURATION "Konfigurering" +#define D_INFORMATION "Information" +#define D_FIRMWARE_UPGRADE "Uppgradera firmware" +#define D_CONSOLE "Konsol" +#define D_CONFIRM_RESTART "Bekräfta omstart" + +#define D_CONFIGURE_MODULE "Konfigurera modul" +#define D_CONFIGURE_WIFI "Konfigurera WiFi" +#define D_CONFIGURE_MQTT "Konfigurera MQTT" +#define D_CONFIGURE_DOMOTICZ "Konfigurera Domoticz" +#define D_CONFIGURE_LOGGING "Konfigurera loggning" +#define D_CONFIGURE_OTHER "Konfigurera annat" +#define D_CONFIRM_RESET_CONFIGURATION "Bekräfta nollställning av konfiguration" +#define D_RESET_CONFIGURATION "Nollställ konfiguration" +#define D_BACKUP_CONFIGURATION "Säkerhetskopiera konfiguration" +#define D_RESTORE_CONFIGURATION "Återställ konfiguration" +#define D_MAIN_MENU "Huvudmeny" + +#define D_MODULE_PARAMETERS "Modulparameterar" +#define D_MODULE_TYPE "Modultyp" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Seriell in" +#define D_SERIAL_OUT "Seriell ut" + +#define D_WIFI_PARAMETERS "Wifi-parameterar" +#define D_SCAN_FOR_WIFI_NETWORKS "Skanna efter wifi-nätverk" +#define D_SCAN_DONE "Skanning slutförd" +#define D_NO_NETWORKS_FOUND "Inga nätverk hittades" +#define D_REFRESH_TO_SCAN_AGAIN "Uppdatera för att skanna igen" +#define D_DUPLICATE_ACCESSPOINT "Dubblett accesspunkt" +#define D_SKIPPING_LOW_QUALITY "Hoppa över pga dålig kvalitet" +#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 lösenord" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 lösenord" + +#define D_MQTT_PARAMETERS "MQTT-parameterar" +#define D_CLIENT "Klient" +#define D_FULL_TOPIC "Fullt ämne" + +#define D_LOGGING_PARAMETERS "Loggningsparametrar" +#define D_SERIAL_LOG_LEVEL "Seriell loggnivå" +#define D_WEB_LOG_LEVEL "Webb loggnivå" +#define D_SYS_LOG_LEVEL "Syslog-nivp" +#define D_MORE_DEBUG "Mer debugging" +#define D_SYSLOG_HOST "Syslog-värd" +#define D_SYSLOG_PORT "Syslog-port" +#define D_TELEMETRY_PERIOD "Telemetriperiod" + +#define D_OTHER_PARAMETERS "Andra parametrar" +#define D_WEB_ADMIN_PASSWORD "Webbadmin-lösenord" +#define D_MQTT_ENABLE "MQTT aktivera" +#define D_FRIENDLY_NAME "Läsbart namn" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "soloenhet" +#define D_MULTI_DEVICE "multienhet" + +#define D_SAVE_CONFIGURATION "Spara konfiguration" +#define D_CONFIGURATION_SAVED "Konfiguration sparad" +#define D_CONFIGURATION_RESET "Konfiguration nollställd" + +#define D_PROGRAM_VERSION "Programversion" +#define D_BUILD_DATE_AND_TIME "Build datum & tid" +#define D_CORE_AND_SDK_VERSION "Core/SDK Version" +#define D_FLASH_WRITE_COUNT "Flash-skrivningsräknare" +#define D_MAC_ADDRESS "MAC-adress" +#define D_MQTT_HOST "MQTT-värd" +#define D_MQTT_PORT "MQTT-port" +#define D_MQTT_CLIENT "MQTT-klient" +#define D_MQTT_USER "MQTT-användare" +#define D_MQTT_TOPIC "MQTT-ämne" +#define D_MQTT_GROUP_TOPIC "MQTT gruppämne" +#define D_MQTT_FULL_TOPIC "MQTT fullt ämne" +#define D_MDNS_DISCOVERY "mDNS upptäckning" +#define D_MDNS_ADVERTISE "mDNS annonsering" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Flash-storlek" +#define D_FREE_PROGRAM_SPACE "Ledigt programutrymme" + +#define D_UPGRADE_BY_WEBSERVER "Uppgradering via webbserver" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Starta uppdatering" +#define D_UPGRADE_BY_FILE_UPLOAD "Uppgradering via filuppladdning" +#define D_UPLOAD_STARTED "Uppladdning startad" +#define D_UPGRADE_STARTED "Uppgradeing startad" +#define D_UPLOAD_DONE "Uppladdning klar" +#define D_UPLOAD_ERR_1 "Ingen fil vald" +#define D_UPLOAD_ERR_2 "Inte tillräckligt med ledigt utrymme" +#define D_UPLOAD_ERR_3 "Magisk byte är inte 0xE9" +#define D_UPLOAD_ERR_4 "Programmets flashstorlek är större än den verkliga flashstorleken" +#define D_UPLOAD_ERR_5 "Uppladdningbuffert stämmer inte överens" +#define D_UPLOAD_ERR_6 "Uppladdning misslyckad. Aktivera loggning 3" +#define D_UPLOAD_ERR_7 "Uppladdning avbruten" +#define D_UPLOAD_ERR_8 "Ogiltig fil" +#define D_UPLOAD_ERR_9 "För stor fil" +#define D_UPLOAD_ERR_10 "Misslyckades initera RF chip" +#define D_UPLOAD_ERR_11 "Misslyckades rensa RF chip" +#define D_UPLOAD_ERR_12 "Misslyckades skriva till RF chip" +#define D_UPLOAD_ERR_13 "Misslyckades avkoda RF firmware" +#define D_UPLOAD_ERROR_CODE "Upladdningsfelkod" + +#define D_ENTER_COMMAND "Ange kommando" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Aktivera weblog 2 om svar förväntas" +#define D_NEED_USER_AND_PASSWORD "Behöver användarnamn=&lösenord=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifierar TLS fingeravtryck..." +#define D_TLS_CONNECT_FAILED_TO "TLS-anslutning misslyckades" +#define D_RETRY_IN "Försöker igen om" +#define D_VERIFIED "Verifierad med fingeravtryck" +#define D_INSECURE "Osäker anslutning pga ogiltigt fingeravtryck" +#define D_CONNECT_FAILED_TO "Anslutning misslyckades" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast inaktiverad" +#define D_MULTICAST_REJOINED "Multicast (åter)anslöt" +#define D_MULTICAST_JOIN_FAILED "Multicast anslutning misslyckades" +#define D_FAILED_TO_SEND_RESPONSE "Misslyckades skicka svar" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo standardhändelse" +#define D_WEMO_EVENT_SERVICE "WeMo händelsetjänst" +#define D_WEMO_META_SERVICE "WeMo metatjänst" +#define D_WEMO_SETUP "WeMo installation" +#define D_RESPONSE_SENT "Svar skickat" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue installation" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API inte implementerat" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 svarspaket skickade" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz parametetrar" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Nyckel 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,Fuk" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Fuk,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Spänning,Energi" + #define D_DOMOTICZ_ILLUMINANCE "Belysningsstyrka" + #define D_DOMOTICZ_COUNT "Antal/PM1" + #define D_DOMOTICZ_VOLTAGE "Volt/PM2.5" + #define D_DOMOTICZ_CURRENT "Ström/PM10" + #define D_DOMOTICZ_AIRQUALITY "Luftkvalitet" +#define D_DOMOTICZ_UPDATE_TIMER "Uppdatera timer" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Konfigurera timer" +#define D_TIMER_PARAMETERS "timerparametrar" +#define D_TIMER_ENABLE "Aktivera timer" +#define D_TIMER_ARM "Aktivera" +#define D_TIMER_TIME "Tid" +#define D_TIMER_DAYS "Dagar" +#define D_TIMER_REPEAT "Repetera" +#define D_TIMER_OUTPUT "Output" +#define D_TIMER_ACTION "Action" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Konfigurera KNX" +#define D_KNX_PARAMETERS "KNX Parametrar" +#define D_KNX_GENERAL_CONFIG "Allmänt" +#define D_KNX_PHYSICAL_ADDRESS "Fysisk adress" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Måste vara unik på KNX-nätverket )" +#define D_KNX_ENABLE "Aktivera KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data att skicka till gruppadresser" +#define D_ADD "Lägg till" +#define D_DELETE "Ta bort" +#define D_REPLY "Svara" +#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppadresser att ta emot data från" +#define D_LOG_KNX "KNX: " +#define D_RECEIVED_FROM "Mottagen från" +#define D_KNX_COMMAND_WRITE "Skriv" +#define D_KNX_COMMAND_READ "Läs" +#define D_KNX_COMMAND_OTHER "Andra" +#define D_SENT_TO "skickad till" +#define D_KNX_WARNING "Gruppadressen ( 0 / 0 / 0 ) är reserverad och kan inte användas." +#define D_KNX_ENHANCEMENT "Kommuniceringsförbättring" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energi idag" +#define D_ENERGY_YESTERDAY "Energi igår" +#define D_ENERGY_TOTAL "Energi totalt" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor upptagen" +#define D_SENSOR_CRC_ERROR "Sensor CRC-fel" +#define D_SENSORS_FOUND "Sensorer hittades" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Timeout under väntan +#define D_START_SIGNAL_LOW "startsignal låg +#define D_START_SIGNAL_HIGH "startsignal hög +#define D_PULSE "puls" +#define D_CHECKSUM_FAILURE "Fel kontrollsumma + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor besvarade inte med ACK kommando +#define D_SHT1X_FOUND "SHT1X hittades" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Partiklar" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axel" +#define D_AY_AXIS "Accel. Y-Axel" +#define D_AZ_AXIS "Accel. Z-Axel" +#define D_GX_AXIS "Gyro X-Axel" +#define D_GY_AXIS "Gyro Y-Axel" +#define D_GZ_AXIS "Gyro Z-Axel" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Ta bort vikter" +#define D_HX_CAL_REFERENCE "Ladda referensvikt" +#define D_HX_CAL_DONE "Kalibrerad" +#define D_HX_CAL_FAIL "Kalibrering misslyckad" +#define D_RESET_HX711 "Återställ våg" +#define D_CONFIGURE_HX711 "Konfigurera våg" +#define D_HX711_PARAMETERS "Vågparametrar" +#define D_ITEM_WEIGHT "Objektsvikt" +#define D_REFERENCE_WEIGHT "Referensvikt" +#define D_CALIBRATE "Kalibrera" +#define D_CALIBRATION "Kalibrering" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Vindriktning" +#define D_TX20_WIND_SPEED "Vindstyrka" +#define D_TX20_WIND_SPEED_AVG "Vindstyrka medel" +#define D_TX20_WIND_SPEED_MAX "Vindstyrka max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// sonoff_template.h +#define D_SENSOR_NONE "Ingen" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3-spelare" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Omkopplare" // Suffix "1" +#define D_SENSOR_BUTTON "Knapp" // Suffix "1" +#define D_SENSOR_RELAY "Relä" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Räknare" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_BACKLIGHT "BkLight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri" +#define D_SENSOR_SR04_ECHO "SR04 Ech" +#define D_SENSOR_SDM120_TX "SDM120 Tx" +#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" + + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sek" +#define D_UNIT_SECTORS "sektorer" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +// Log message prefix +#define D_LOG_APPLICATION "APP: " // Application +#define D_LOG_BRIDGE "BRG: " // Bridge +#define D_LOG_CONFIG "CFG: " // Settings +#define D_LOG_COMMAND "CMD: " // Command +#define D_LOG_DEBUG "DBG: " // Debug +#define D_LOG_DHT "DHT: " // DHT sensor +#define D_LOG_DOMOTICZ "DOM: " // Domoticz +#define D_LOG_DSB "DSB: " // DS18xB20 sensor +#define D_LOG_HTTP "HTP: " // HTTP webserver +#define D_LOG_I2C "I2C: " // I2C +#define D_LOG_IRR "IRR: " // Infra Red Received +#define D_LOG_LOG "LOG: " // Logging +#define D_LOG_MODULE "MOD: " // Module +#define D_LOG_MDNS "DNS: " // mDNS +#define D_LOG_MQTT "MQT: " // MQTT +#define D_LOG_OTHER "OTH: " // Other +#define D_LOG_RESULT "RSL: " // Result +#define D_LOG_RFR "RFR: " // RF Received +#define D_LOG_SERIAL "SER: " // Serial +#define D_LOG_SHT1 "SHT: " // SHT1x sensor +#define D_LOG_UPLOAD "UPL: " // Upload +#define D_LOG_UPNP "UPP: " // UPnP +#define D_LOG_WIFI "WIF: " // Wifi + +#endif // _LANGUAGE_SV_SE_H_ From eda86acaa048bca2f111c94a0d2e9817b892161d Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Wed, 5 Dec 2018 20:01:45 -0300 Subject: [PATCH 0661/2222] Added Key to select Swedish Translation --- sonoff/my_user_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index e1f6e364a..288c80d30 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -205,6 +205,7 @@ //#define MY_LANGUAGE pt-BR // Portuguese in Brazil //#define MY_LANGUAGE pt-PT // Portuguese in Portugal //#define MY_LANGUAGE ru-RU // Russian in Russia +//#define MY_LANGUAGE sv-SE // Swedish in Sweden //#define MY_LANGUAGE tr-TR // Turkish in Turkey //#define MY_LANGUAGE uk-UK // Ukrainian in Ukrain //#define MY_LANGUAGE zh-CN // Chinese (Simplified) in China From 33f27feb5fe7d249867d7f6b0a49fd2d3f6aca3d Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Wed, 5 Dec 2018 20:04:22 -0300 Subject: [PATCH 0662/2222] Added Swedish to Precompiled bins --- platformio.ini | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/platformio.ini b/platformio.ini index bb68e981f..fe4893b69 100644 --- a/platformio.ini +++ b/platformio.ini @@ -33,6 +33,7 @@ env_default = sonoff ;env_default = sonoff-PL ;env_default = sonoff-PT ;env_default = sonoff-RU +;env_default = sonoff-SV ;env_default = sonoff-TR ;env_default = sonoff-TW ;env_default = sonoff-UK @@ -409,6 +410,20 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} +[env:sonoff-SV] +platform = ${common.platform} +framework = ${common.framework} +board = ${common.board} +board_build.flash_mode = ${common.board_build.flash_mode} +board_build.f_cpu = ${common.board_build.f_cpu} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} -DMY_LANGUAGE=sv-SE +monitor_speed = ${common.monitor_speed} +upload_port = ${common.upload_port} +upload_resetmethod = ${common.upload_resetmethod} +upload_speed = ${common.upload_speed} +extra_scripts = ${common.extra_scripts} + [env:sonoff-TR] platform = ${common.platform} framework = ${common.framework} From 5f35f7ebae89c99c49a298201b1f0deac0771a3a Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Wed, 5 Dec 2018 20:11:54 -0300 Subject: [PATCH 0663/2222] Added missing " --- sonoff/language/sv-SE.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 271f3d649..bcffdab58 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -433,14 +433,14 @@ #define D_SENSORS_FOUND "Sensorer hittades" // xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Timeout under väntan -#define D_START_SIGNAL_LOW "startsignal låg -#define D_START_SIGNAL_HIGH "startsignal hög +#define D_TIMEOUT_WAITING_FOR "Timeout under väntan" +#define D_START_SIGNAL_LOW "startsignal låg" +#define D_START_SIGNAL_HIGH "startsignal hög" #define D_PULSE "puls" -#define D_CHECKSUM_FAILURE "Fel kontrollsumma +#define D_CHECKSUM_FAILURE "Fel kontrollsumma" // xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor besvarade inte med ACK kommando +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor besvarade inte med ACK kommando" #define D_SHT1X_FOUND "SHT1X hittades" // xsns_18_pms5003.ino From 3b68d606ab21fbadae7bb91aaf5f3ff6446e497c Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Wed, 5 Dec 2018 20:14:11 -0300 Subject: [PATCH 0664/2222] Matched the order of days with Tasmota Timers --- sonoff/language/sv-SE.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index bcffdab58..db8f663a1 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -44,7 +44,7 @@ #define D_HOUR_MINUTE_SEPARATOR ":" #define D_MINUTE_SECOND_SEPARATOR ":" -#define D_DAY3LIST "MånTisOnsTorFreLörSön" +#define D_DAY3LIST "SönMånTisOnsTorFreLör" #define D_MONTH3LIST "JanFebMarAprMajJunJulAugSepOktNovDec" // Non JSON decimal separator From 9af72977db26f40540635eea3c1505d06fc00c95 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Thu, 6 Dec 2018 08:48:20 +0100 Subject: [PATCH 0665/2222] Update platformio.ini Support for enable / disable exceptions code in firmware for esp8266 core 2.5.0 (stage) or up --- platformio.ini | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/platformio.ini b/platformio.ini index bb68e981f..0a9bb65b9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -80,6 +80,15 @@ build_flags = ; VTABLES in IRAM ; -DVTABLES_IN_IRAM +; if using esp8266 core 2.5.0 (stage) or up +; enable one option set -> No exception recommended +; No exception code in firmware +; -fno-exceptions +; -lstdc++-nox +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++ + ; *** Serial Monitor options monitor_speed = 115200 From 3777dbe45c965c87a9ac2ed80b5664f825a91acb Mon Sep 17 00:00:00 2001 From: Andrzej Date: Thu, 6 Dec 2018 09:52:02 +0100 Subject: [PATCH 0666/2222] localization for Polish - KNX, timers, etc. --- sonoff/language/pl-PL.h | 130 ++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index aee1b99a0..f2ef0c05c 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -62,10 +62,10 @@ #define D_BRIGHTLIGHT "Jasny" #define D_BSSID "BSSId" #define D_BUTTON "Przycisk" -#define D_BY "by" // Written by me +#define D_BY "przez" // Written by me #define D_BYTES "Bajtow" #define D_CELSIUS "Celsiusza" -#define D_CHANNEL "Channel" +#define D_CHANNEL "Kanał" #define D_CO2 "Dwutlenku węgla" #define D_CODE "kod" // Button code #define D_COLDLIGHT "Zimny" @@ -78,8 +78,8 @@ #define D_DARKLIGHT "Ciemny" #define D_DEBUG "Debug" #define D_DISABLED "Zablokowany" -#define D_DISTANCE "Distance" -#define D_DNS_SERVER "Server DNS" +#define D_DISTANCE "Odległość" +#define D_DNS_SERVER "Serwer DNS" #define D_DONE "Wykonane" #define D_DST_TIME "DST" #define D_ECO2 "eCO2" @@ -105,7 +105,7 @@ #define D_IMMEDIATE "Natychmiastowe" // Button immediate #define D_INDEX "Indeks" #define D_INFO "Informacja" -#define D_INFRARED "Infrared" +#define D_INFRARED "Podczerwień" #define D_INITIALIZED "Zainicjowany" #define D_IP_ADDRESS "Adres IP" #define D_LIGHT "Światło" @@ -124,9 +124,9 @@ #define D_PORT "Port" #define D_POWER_FACTOR "Współczynik mocy" #define D_POWERUSAGE "Moc" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_POWERUSAGE_ACTIVE "Czynna Moc" +#define D_POWERUSAGE_APPARENT "Pozorna Moc" +#define D_POWERUSAGE_REACTIVE "Reaktywna Moc" #define D_PRESSURE "Ciśnienie" #define D_PRESSUREATSEALEVEL "Ciśnienie na poziomie morza" #define D_PROGRAM_FLASH_SIZE "Wielkość programu flash" @@ -148,8 +148,8 @@ #define D_SUBNET_MASK "Maska podsieci" #define D_SUBSCRIBE_TO "Subskrybuj do" #define D_SUCCESSFUL "Powodzenie" -#define D_SUNRISE "Sunrise" -#define D_SUNSET "Sunset" +#define D_SUNRISE "Wschód słońca" +#define D_SUNSET "Zachód słońca" #define D_TEMPERATURE "Temperatura" #define D_TO "do" #define D_TOGGLE "Przełącz" @@ -159,14 +159,14 @@ #define D_TVOC "TVOC" #define D_UPGRADE "aktualizacji" #define D_UPLOAD "Wgraj" -#define D_UPTIME "Uptime" +#define D_UPTIME "Czas pracy" #define D_USER "Użytkownik" #define D_UTC_TIME "UTC" #define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_1 "Niski" +#define D_UV_INDEX_2 "Średni" +#define D_UV_INDEX_3 "Wysoki" +#define D_UV_INDEX_4 "Niebezpieczny" #define D_UV_INDEX_5 "BurnL1/2" #define D_UV_INDEX_6 "BurnL3" #define D_UV_INDEX_7 "OoR" @@ -176,10 +176,10 @@ #define D_VOLTAGE "Napięcie" #define D_WEIGHT "Weight" #define D_WARMLIGHT "Nagrzanie" -#define D_WEB_SERVER "Web Server" +#define D_WEB_SERVER "Web Serwer" // sonoff.ino -#define D_WARNING_MINIMAL_VERSION "WARNING This version does not support persistent settings" +#define D_WARNING_MINIMAL_VERSION "UWAGA Ta wersja nie obsługuje zapisu ustawień" #define D_LEVEL_10 "poziom 1-0" #define D_LEVEL_01 "poziom 0-1" #define D_SERIAL_LOGGING_DISABLED "Wyłączony dziennik na porcie szeregowym" @@ -217,7 +217,7 @@ #define D_ERASED_SECTOR "Wymazany sektor" // xdrv_02_webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_NOSCRIPT "Aby korzystać z Tasmota, włącz obsługę JavaScript" #define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL - proszę uaktualnić" #define D_WEBSERVER_ACTIVE_ON "Aktywny serwer Web" #define D_WITH_IP_ADDRESS "z adresem IP" @@ -333,10 +333,10 @@ #define D_UPLOAD_ERR_7 "Wgrywanie przerwane" #define D_UPLOAD_ERR_8 "Błędny plik" #define D_UPLOAD_ERR_9 "Plik jest za duży" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERR_10 "Błąd inicjacji układu RF" +#define D_UPLOAD_ERR_11 "Błąd kasowania układu RF" +#define D_UPLOAD_ERR_12 "Błąd zapisu układu RF" +#define D_UPLOAD_ERR_13 "Błąd dekodowania oprrogramowania układu RF" #define D_UPLOAD_ERROR_CODE "Błąd wgrywania" #define D_ENTER_COMMAND "Wprowadź polecenie" @@ -389,36 +389,36 @@ #define D_DOMOTICZ_UPDATE_TIMER "Zaktualizuj czasomierz" // xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configure Timer" -#define D_TIMER_PARAMETERS "Timer parameters" -#define D_TIMER_ENABLE "Enable Timers" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "Time" -#define D_TIMER_DAYS "Days" -#define D_TIMER_REPEAT "Repeat" -#define D_TIMER_OUTPUT "Output" -#define D_TIMER_ACTION "Action" +#define D_CONFIGURE_TIMER "Skonfiguruj harmonogram" +#define D_TIMER_PARAMETERS "Parametry harmonogramów" +#define D_TIMER_ENABLE "Włącz Harmonogramy" +#define D_TIMER_ARM "Włącz" +#define D_TIMER_TIME "Czas" +#define D_TIMER_DAYS "Dni" +#define D_TIMER_REPEAT "Powtarzaj" +#define D_TIMER_OUTPUT "Wyjście" +#define D_TIMER_ACTION "Akcja" // xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configure KNX" -#define D_KNX_PARAMETERS "KNX Parameters" -#define D_KNX_GENERAL_CONFIG "General" -#define D_KNX_PHYSICAL_ADDRESS "Physical Address" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "Enable KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" -#define D_ADD "Add" -#define D_DELETE "Delete" -#define D_REPLY "Reply" -#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" +#define D_CONFIGURE_KNX "Skonfiguruj KNX" +#define D_KNX_PARAMETERS "Parametry KNX" +#define D_KNX_GENERAL_CONFIG "Ogólne" +#define D_KNX_PHYSICAL_ADDRESS "Adres Fizyczny" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Musi być unikalny w sieci KNX )" +#define D_KNX_ENABLE "Włącz KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dane do wysłania do adresów grupowych" +#define D_ADD "Dodaj" +#define D_DELETE "Usuń" +#define D_REPLY "Odpowiedz" +#define D_KNX_GROUP_ADDRESS_TO_READ "Adresy grupowe do odbioru danych z" #define D_LOG_KNX "KNX: " -#define D_RECEIVED_FROM "Received from" -#define D_KNX_COMMAND_WRITE "Write" -#define D_KNX_COMMAND_READ "Read" -#define D_KNX_COMMAND_OTHER "Other" -#define D_SENT_TO "sent to" -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_RECEIVED_FROM "Otrzymane od" +#define D_KNX_COMMAND_WRITE "Zapisz" +#define D_KNX_COMMAND_READ "Czytaj" +#define D_KNX_COMMAND_OTHER "Inne" +#define D_SENT_TO "wysłane do" +#define D_KNX_WARNING "Adres grupy (0/0/0) jest zarezerwowany i nie można go użyć." +#define D_KNX_ENHANCEMENT "Usprawnienie Komunikacji" #define D_KNX_TX_SLOT "KNX TX" #define D_KNX_RX_SLOT "KNX RX" @@ -446,7 +446,7 @@ // xsns_18_pms5003.ino #define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter #define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particals" +#define D_PARTICALS_BEYOND "Cząstki" // xsns_32_mpu6050.ino #define D_AX_AXIS "Accel. X-Axis" @@ -457,23 +457,23 @@ #define D_GZ_AXIS "Gyro Z-Axis" // xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" +#define D_HX_CAL_REMOVE "Usuń wagę" +#define D_HX_CAL_REFERENCE "Załaduj masę referencyjną" +#define D_HX_CAL_DONE "Skalibrowany" +#define D_HX_CAL_FAIL "Błąd Kalibracji" +#define D_RESET_HX711 "Zresetuj Skalę" +#define D_CONFIGURE_HX711 "Skonfiguruj Skalę" +#define D_HX711_PARAMETERS "Parametry Skali" +#define D_ITEM_WEIGHT "Waga przedmiotu" +#define D_REFERENCE_WEIGHT "Waga referencyjna" +#define D_CALIBRATE "Skalibruj" +#define D_CALIBRATION "Kalibrowanie" //xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_WIND_DIRECTION "Kierunek wiatru" +#define D_TX20_WIND_SPEED "Prędkość wiatru" +#define D_TX20_WIND_SPEED_AVG "Średnia prędkość wiatru" +#define D_TX20_WIND_SPEED_MAX "Maksymalna prędkość wiatru" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" #define D_TX20_SOUTH "S" From dfa0d2ef11d539c5c78bcf5d8d1bfaf76c3b6aca Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 6 Dec 2018 10:49:49 +0100 Subject: [PATCH 0667/2222] Add Domoticz Selector for Fanspeed Add support for iFan02 Fanspeed in Domoticz using a selector (#4517) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.h | 8 ++++-- sonoff/sonoff.ino | 10 +++----- sonoff/xdrv_01_webserver.ino | 2 +- sonoff/xdrv_02_mqtt.ino | 2 +- sonoff/xdrv_07_domoticz.ino | 49 ++++++++++++++++++++++++++---------- 6 files changed, 49 insertions(+), 23 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 3709195fe..22641b3bc 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Add command SetOption60 0/1 to select dynamic sleep (0) or sleep (1) (#4497) * Update SR-04 driver to use NewPing library (#4488) * Add support for GPIO02 for newer Sonoff Basic (#4518) + * Add support for iFan02 Fanspeed in Domoticz using a selector (#4517) * * 6.3.0.14 20181127 * Add Command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 4a54f81be..71c761b28 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -74,6 +74,8 @@ typedef unsigned long power_t; // Power (Relay) type #define MAX_RULE_TIMERS 8 // Max number of rule timers (4 bytes / timer) #define MAX_RULE_VARS 5 // Max number of rule variables (10 bytes / variable) +#define MAX_FAN_SPEED 4 // Max number of iFan02 fan speeds (0 .. 3) + #define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x] #define MQTT_TOKEN_TOPIC "%topic%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic #define MQTT_TOKEN_HOSTNAME "%hostname%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic @@ -245,12 +247,14 @@ enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUN FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED, FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER}; -const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; - enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER, SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_MAX }; const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|Timer|Rule|MaxPower|MaxEnergy|Light|Knx|Display|Wemo|Hue|Retry"; +const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; + +const uint8_t kIFan02Speed[MAX_FAN_SPEED][3] = {{6,6,6}, {7,6,6}, {7,7,6}, {7,6,7}}; // Do not use PROGMEM as it fails + /*********************************************************************************************\ * Extern global variables \*********************************************************************************************/ diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 869eaf7eb..379cc1d12 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -91,8 +91,6 @@ const char kTasmotaCommands[] PROGMEM = const char kSleepMode[] PROGMEM = "Dynamic|Normal"; -const uint8_t kIFan02Speed[4][3] = {{6,6,6}, {7,6,6}, {7,7,6}, {7,6,7}}; - // Global variables SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit @@ -390,7 +388,7 @@ uint8_t GetFanspeed(void) void SetFanspeed(uint8_t fanspeed) { - for (byte i = 0; i < 3; i++) { + for (byte i = 0; i < MAX_FAN_SPEED -1; i++) { uint8_t state = kIFan02Speed[fanspeed][i]; // uint8_t state = pgm_read_byte(kIFan02Speed +(speed *3) +i); ExecuteCommandPower(i +2, state, SRC_IGNORE); // Use relay 2, 3 and 4 @@ -566,14 +564,14 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if (data_len > 0) { if ('-' == dataBuf[0]) { payload = (int16_t)GetFanspeed() -1; - if (payload < 0) { payload = 3; } + if (payload < 0) { payload = MAX_FAN_SPEED -1; } } else if ('+' == dataBuf[0]) { payload = GetFanspeed() +1; - if (payload > 3) { payload = 0; } + if (payload > MAX_FAN_SPEED -1) { payload = 0; } } } - if ((payload >= 0) && (payload <= 3) && (payload != GetFanspeed())) { + if ((payload >= 0) && (payload < MAX_FAN_SPEED) && (payload != GetFanspeed())) { SetFanspeed(payload); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, GetFanspeed()); diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index cd0204a48..b5c73aea5 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -628,7 +628,7 @@ void HandleRoot(void) if (SONOFF_IFAN02 == Settings.module) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); page += mqtt_data; - for (byte i = 0; i < 4; i++) { + for (byte i = 0; i < MAX_FAN_SPEED; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 16, i +2, stemp, ""); page += mqtt_data; diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 2e026c71f..77153abfd 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -334,7 +334,7 @@ void MqttPublishPowerState(byte device) if ((device < 1) || (device > devices_present)) { device = 1; } if ((SONOFF_IFAN02 == Settings.module) && (device > 1)) { - if (GetFanspeed() < 4) { // 4 occurs when fanspeed is 3 and RC button 2 is pressed + if (GetFanspeed() < MAX_FAN_SPEED) { // 4 occurs when fanspeed is 3 and RC button 2 is pressed snprintf_P(scommand, sizeof(scommand), PSTR(D_CMND_FANSPEED)); GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, scommand, GetFanspeed()); diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 40c3127ec..3e2170701 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -73,16 +73,25 @@ int DomoticzRssiQuality(void) void MqttPublishDomoticzPowerState(byte device) { - char sdimmer[8]; + char svalue[8]; // Dimmer or Fanspeed value - 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), DOMOTICZ_MESSAGE, - Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? sdimmer : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); - MqttPublish(domoticz_in_topic); + if (Settings.flag.mqtt_enabled) { + if ((device < 1) || (device > devices_present)) { device = 1; } + if ((SONOFF_IFAN02 == Settings.module) && Settings.domoticz_relay_idx[1] && (device > 1)) { // device (relay) 1 handled below + if (4 == device) { // Wait for device (relay) 4 to get valid GetFanspeed + uint8_t fan_speed = GetFanspeed(); + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), (int)fan_speed * 10); + snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE, + Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); + MqttPublish(domoticz_in_topic); + } + } + else if (Settings.domoticz_relay_idx[device -1]) { + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); + snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE, + Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); + MqttPublish(domoticz_in_topic); + } } } @@ -182,7 +191,18 @@ boolean DomoticzMqttData(void) if (idx == Settings.domoticz_relay_idx[i]) { bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); - if (iscolordimmer && 10 == nvalue) { // Color_SetColor + if ((SONOFF_IFAN02 == Settings.module) && (1 == i)) { // Idx 2 is fanspeed + int16_t svalue = 0; + if (domoticz.containsKey("svalue1")) { + svalue = domoticz["svalue1"]; + } else { + return 1; + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), (nvalue == 2) ? svalue / 10 : 0); + found = 1; + } + else if (iscolordimmer && 10 == nvalue) { // Color_SetColor JsonObject& color = domoticz["Color"]; uint16_t level = nvalue = domoticz["svalue1"]; uint16_t r = color["r"]; r = r * level / 100; @@ -193,8 +213,9 @@ boolean DomoticzMqttData(void) snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR)); snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww); found = 1; - } else if ((!iscolordimmer && 2 == nvalue) || // gswitch_sSetLevel - (iscolordimmer && 15 == nvalue)) { // Color_SetBrightnessLevel + } + else if ((!iscolordimmer && 2 == nvalue) || // gswitch_sSetLevel + (iscolordimmer && 15 == nvalue)) { // Color_SetBrightnessLevel if (domoticz.containsKey("svalue1")) { nvalue = domoticz["svalue1"]; } else { @@ -206,7 +227,8 @@ boolean DomoticzMqttData(void) snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); found = 1; - } else if (1 == nvalue || 0 == nvalue) { + } + else if (1 == nvalue || 0 == nvalue) { if (((power >> i) &1) == (power_t)nvalue) { return 1; } @@ -422,6 +444,7 @@ void HandleDomoticzConfiguration(void) page.replace("{4", String((int)Settings.domoticz_switch_idx[i])); } page.replace("{1", String(i +1)); + if ((SONOFF_IFAN02 == Settings.module) && (1 == i)) { break; } } for (int i = 0; i < DZ_MAX_SENSORS; i++) { page += FPSTR(HTTP_FORM_DOMOTICZ_SENSOR); From e64c8d61c92d9fcd3e3963948fad040f3b607681 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 6 Dec 2018 11:01:57 +0100 Subject: [PATCH 0668/2222] Update sonoff.ino --- sonoff/sonoff.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 947f5d165..2132a09b2 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1311,7 +1311,7 @@ boolean SendKey(byte key, byte device, byte state) if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { if (!key && (device > devices_present)) device = 1; // Only allow number of buttons up to number of devices GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), - Settings.flag.device_index_enable)); // cmnd/switchtopic/POWERx + (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx if (9 == state) { mqtt_data[0] = '\0'; } else { From 61aa428646b50fba4bf4d7a80ab9dd2683faaf4b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 6 Dec 2018 11:17:25 +0100 Subject: [PATCH 0669/2222] 6.3.0.16 - Bump version 6.3.0.16 20181201 * Add support for iFan02 Fanspeed in Domoticz using a selector (#4517) * Add Announce Switches to MQTT Discovery (#4531) --- sonoff/_changelog.ino | 9 ++++++--- sonoff/sonoff.ino | 6 +++--- sonoff/sonoff_version.h | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 22641b3bc..b962b13de 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,12 +1,15 @@ -/* 6.3.0.15 20181201 +/* 6.3.0.16 20181201 + * Add support for iFan02 Fanspeed in Domoticz using a selector (#4517) + * Add Announce Switches to MQTT Discovery (#4531) + * + * 6.3.0.15 20181201 * Removed command SetOption36 (#4497) * Add command SetOption60 0/1 to select dynamic sleep (0) or sleep (1) (#4497) * Update SR-04 driver to use NewPing library (#4488) * Add support for GPIO02 for newer Sonoff Basic (#4518) - * Add support for iFan02 Fanspeed in Domoticz using a selector (#4517) * * 6.3.0.14 20181127 - * Add Command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420) + * Add command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420) * Add support for SM Smart Wifi Dimmer PS-16-DZ (#4465) * Move some static (serial) buffers to dynamic buffers * Update display and epaper drivers diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c9882902a..5260900a3 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1307,9 +1307,9 @@ boolean SendKey(byte key, byte device, byte state) char *tmp = (key) ? Settings.switch_topic : Settings.button_topic; Format(key_topic, tmp, sizeof(key_topic)); if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { - if (!key && (device > devices_present)) device = 1; // Only allow number of buttons up to number of devices - GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), - (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx + if (!key && (device > devices_present)) { device = 1; } // Only allow number of buttons up to number of devices + GetTopic_P(stopic, CMND, key_topic, + GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx if (9 == state) { mqtt_data[0] = '\0'; } else { diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index d6b82d881..9c41f0220 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0603000F +#define VERSION 0x06030010 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" From 9a3c3895fbc9cf1d98e3ca795a2d029b5e744c9c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 6 Dec 2018 15:03:42 +0100 Subject: [PATCH 0670/2222] Fix Domoticz Fanspeed Fix Domoticz Fanspeed --- sonoff/sonoff.ino | 3 ++ sonoff/xdrv_02_mqtt.ino | 5 ++- sonoff/xdrv_07_domoticz.ino | 67 +++++++++++++++++++++++++++---------- 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 5260900a3..f979e15c5 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -393,6 +393,9 @@ void SetFanspeed(uint8_t fanspeed) // uint8_t state = pgm_read_byte(kIFan02Speed +(speed *3) +i); ExecuteCommandPower(i +2, state, SRC_IGNORE); // Use relay 2, 3 and 4 } +#ifdef USE_DOMOTICZ + DomoticzUpdateFanState(); // Command FanSpeed feedback +#endif // USE_DOMOTICZ } void SetPulseTimer(uint8_t index, uint16_t time) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 77153abfd..bc969d3f2 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -335,6 +335,9 @@ void MqttPublishPowerState(byte device) if ((SONOFF_IFAN02 == Settings.module) && (device > 1)) { if (GetFanspeed() < MAX_FAN_SPEED) { // 4 occurs when fanspeed is 3 and RC button 2 is pressed +#ifdef USE_DOMOTICZ + DomoticzUpdateFanState(); // RC Button feedback +#endif // USE_DOMOTICZ snprintf_P(scommand, sizeof(scommand), PSTR(D_CMND_FANSPEED)); GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, scommand, GetFanspeed()); @@ -425,7 +428,7 @@ void MqttConnected(void) MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); for (byte i = 1; i <= devices_present; i++) { MqttPublishPowerState(i); - if (SONOFF_IFAN02 == Settings.module) { break; } // Only report status of light relay + if (SONOFF_IFAN02 == Settings.module) { break; } // Report status of light relay only } if (Settings.tele_period) { tele_period = Settings.tele_period -9; } // Enable TelePeriod in 9 seconds rules_flag.system_boot = 1; diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 3e2170701..3eb3fa275 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -42,8 +42,9 @@ char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; char domoticz_out_topic[] = DOMOTICZ_OUT_TOPIC; boolean domoticz_subscribe = false; -int domoticz_update_timer = 0; byte domoticz_update_flag = 1; +int domoticz_update_timer = 0; +unsigned long fan_debounce = 0; // iFan02 state debounce timer int DomoticzBatteryQuality(void) { @@ -71,27 +72,45 @@ int DomoticzRssiQuality(void) return WifiGetRssiAsQuality(WiFi.RSSI()) / 10; } +void MqttPublishDomoticzFanState() +{ + if (Settings.flag.mqtt_enabled && Settings.domoticz_relay_idx[1]) { + char svalue[8]; // Fanspeed value + + int fan_speed = GetFanspeed(); + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fan_speed * 10); + snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE, + Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); + MqttPublish(domoticz_in_topic); + + fan_debounce = millis(); + } +} + +void DomoticzUpdateFanState() +{ + if (domoticz_update_flag) { + MqttPublishDomoticzFanState(); + } + domoticz_update_flag = 1; +} + void MqttPublishDomoticzPowerState(byte device) { - char svalue[8]; // Dimmer or Fanspeed value - if (Settings.flag.mqtt_enabled) { if ((device < 1) || (device > devices_present)) { device = 1; } - if ((SONOFF_IFAN02 == Settings.module) && Settings.domoticz_relay_idx[1] && (device > 1)) { // device (relay) 1 handled below - if (4 == device) { // Wait for device (relay) 4 to get valid GetFanspeed - uint8_t fan_speed = GetFanspeed(); - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), (int)fan_speed * 10); + if (Settings.domoticz_relay_idx[device -1]) { + if ((SONOFF_IFAN02 == Settings.module) && (device > 1)) { + // Fan handled by MqttPublishDomoticzFanState + } else { + char svalue[8]; // Dimmer value + + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE, - Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); + Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); MqttPublish(domoticz_in_topic); } } - else if (Settings.domoticz_relay_idx[device -1]) { - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); - snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE, - Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); - MqttPublish(domoticz_in_topic); - } } } @@ -110,7 +129,12 @@ void DomoticzMqttUpdate(void) if (domoticz_update_timer <= 0) { domoticz_update_timer = Settings.domoticz_update_timer; for (byte i = 1; i <= devices_present; i++) { - MqttPublishDomoticzPowerState(i); + if ((SONOFF_IFAN02 == Settings.module) && (i > 1)) { + MqttPublishDomoticzFanState(); + break; + } else { + MqttPublishDomoticzPowerState(i); + } } } } @@ -192,14 +216,21 @@ boolean DomoticzMqttData(void) bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); if ((SONOFF_IFAN02 == Settings.module) && (1 == i)) { // Idx 2 is fanspeed - int16_t svalue = 0; + uint8_t svalue = 0; if (domoticz.containsKey("svalue1")) { svalue = domoticz["svalue1"]; } else { return 1; } + svalue = (nvalue == 2) ? svalue / 10 : 0; + if (GetFanspeed() == svalue) { + return 1; // Stop loop as already set + } + if (TimePassedSince(fan_debounce) < 1000) { + return 1; // Stop loop if device in limbo + } snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), (nvalue == 2) ? svalue / 10 : 0); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue); found = 1; } else if (iscolordimmer && 10 == nvalue) { // Color_SetColor @@ -230,7 +261,7 @@ boolean DomoticzMqttData(void) } else if (1 == nvalue || 0 == nvalue) { if (((power >> i) &1) == (power_t)nvalue) { - return 1; + return 1; // Stop loop } snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : ""); snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); From 46816f2f07e930011fc4470756598d75908aa53b Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 7 Dec 2018 00:55:44 +0200 Subject: [PATCH 0671/2222] MCP230xx - Add Interrupt Retain --- sonoff/settings.h | 2 +- sonoff/xsns_29_mcp230xx.ino | 84 +++++++++++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 10e67e6a2..c773b3b86 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -156,7 +156,7 @@ typedef union { uint16_t int_report_mode : 2; // Interrupt reporting mode 0 = immediate telemetry & event, 1 = immediate event only, 2 = immediate telemetry only uint16_t int_report_defer : 4; // Number of interrupts to ignore until reporting (default 0, max 15) uint16_t int_count_en : 1; // Enable interrupt counter for this pin - uint16_t spare12 : 1; + uint16_t int_retain_flag : 1; // Report if interrupt occured for pin in next teleperiod uint16_t spare13 : 1; uint16_t spare14 : 1; uint16_t spare15 : 1; diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 867fa54ec..64f3351a5 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -47,12 +47,15 @@ uint8_t mcp230xx_pincount = 0; uint8_t mcp230xx_int_en = 0; uint8_t mcp230xx_int_prio_counter = 0; uint8_t mcp230xx_int_counter_en = 0; +uint8_t mcp230xx_int_retainer_en = 0; uint8_t mcp230xx_int_sec_counter = 0; uint8_t mcp230xx_int_report_defer_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint16_t mcp230xx_int_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +uint8_t mcp230xx_int_retainer[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // Used to store if an interrupt occured that needs to be retained until teleperiod + unsigned long int_millis[16]; // To keep track of millis() since last interrupt const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL_UP\":\"%s\",\"INT_MODE\":\"%s\",\"STATE\":\"%s\"}}"; @@ -79,6 +82,20 @@ void MCP230xx_CheckForIntCounter(void) { } } +void MCP230xx_CheckForIntRetainer(void) { + uint8_t en = 0; + for (uint8_t ca=0;ca<16;ca++) { + if (Settings.mcp230xx_config[ca].int_retain_flag) { + en=1; + } + } + mcp230xx_int_retainer_en=en; + if (!mcp230xx_int_retainer_en) { // Interrupt counters are disabled, so we clear all the counters + for (uint8_t ca=0;ca<16;ca++) { + mcp230xx_int_retainer[ca] = 0; + } + } +} const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) { #ifdef USE_MCP230xx_OUTPUT @@ -177,7 +194,8 @@ void MCP230xx_ApplySettings(void) { int_millis[idx]=millis(); } mcp230xx_int_en = int_en; - MCP230xx_CheckForIntCounter(); // update register on whether or not we should be counting interrupts + MCP230xx_CheckForIntCounter(); // update register on whether or not we should be counting interrupts + MCP230xx_CheckForIntRetainer(); // update register on whether or not we should be retaining interrupt events for teleperiod } void MCP230xx_Detect(void) @@ -258,6 +276,13 @@ void MCP230xx_CheckForInterrupt(void) { } } } + // check if interrupt retain is used, if it is for this pin then we do not report immediately as it will be reported in teleperiod + if (report_int) { + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_retain_flag) { + mcp230xx_int_retainer[intp+(mcp230xx_port*8)] = 1; + report_int = 0; // do not report for now + } + } if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { // We do not want to report via tele or event if counting is enabled report_int = 0; } @@ -382,8 +407,8 @@ void MCP230xx_Reset(uint8_t pinmode) { Settings.mcp230xx_config[pinx].int_report_mode=3; // Disabled for pinmode 1, 5 and 6 (No interrupts there) } Settings.mcp230xx_config[pinx].int_report_defer=0; // Disabled - Settings.mcp230xx_config[pinx].int_count_en=0; // Disabled - Settings.mcp230xx_config[pinx].spare12=0; + Settings.mcp230xx_config[pinx].int_count_en=0; // Disabled by default + Settings.mcp230xx_config[pinx].int_retain_flag=0; // Disabled by default Settings.mcp230xx_config[pinx].spare13=0; Settings.mcp230xx_config[pinx].spare14=0; Settings.mcp230xx_config[pinx].spare15=0; @@ -544,6 +569,41 @@ bool MCP230xx_Command(void) { } } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTRETAIN")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (pin < mcp230xx_pincount) { + if (pin == 0) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; + } else { + validpin = true; + } + } + if (validpin) { + if (paramcount > 2) { + uint8_t int_retain = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((int_retain >= 0) && (int_retain <= 1)) { + Settings.mcp230xx_config[pin].int_retain_flag=int_retain; + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); + MCP230xx_CheckForIntRetainer(); + return serviced; + } else { + serviced=false; + return serviced; + } + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); + return serviced; + } + } + serviced = false; + return serviced; + } else { + serviced = false; + return serviced; + } + } + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); if (pin < mcp230xx_pincount) { @@ -703,6 +763,19 @@ void MCP230xx_Interrupt_Counter_Report(void) { mcp230xx_int_sec_counter = 0; } +void MCP230xx_Interrupt_Retain_Report(void) { + uint16_t retainresult = 0; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP_INTRETAIN\": {"), GetDateAndTime(DT_LOCAL).c_str()); + for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].int_retain_flag) { + snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"D%i\":%i,"),mqtt_data,pinx,mcp230xx_int_retainer[pinx]); + retainresult |= (((mcp230xx_int_retainer[pinx])&1) << pinx); + mcp230xx_int_retainer[pinx]=0; + } + } + snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"Value\":%u}}"),mqtt_data,retainresult); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +} /*********************************************************************************************\ Interface @@ -724,6 +797,11 @@ boolean Xsns29(byte function) MCP230xx_Interrupt_Counter_Report(); } } + if (tele_period == 0) { + if (mcp230xx_int_retainer_en) { // We have pins configured for interrupt retain reporting + MCP230xx_Interrupt_Retain_Report(); + } + } #ifdef USE_MCP230xx_OUTPUT if (tele_period == 0) { MCP230xx_OutputTelemetry(); From 99e6d7f2ffbdbb6460ad23762fcb10a44657d1e0 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Fri, 7 Dec 2018 01:09:33 +0200 Subject: [PATCH 0672/2222] MCP230xx driver - add interrupt retention MCP230xx driver - add interrupt retention over teleperiod. --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b962b13de..cbad2b3c2 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.3.0.16 20181201 * Add support for iFan02 Fanspeed in Domoticz using a selector (#4517) * Add Announce Switches to MQTT Discovery (#4531) + * Update MCP230xx driver to support interrupt retention over teleperiod (#4547) * * 6.3.0.15 20181201 * Removed command SetOption36 (#4497) From fe9103eb684dd28cf8c16a88a51c0dc2c8e6e599 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 7 Dec 2018 17:19:14 +0100 Subject: [PATCH 0673/2222] Fix HASS discovery of switches --- sonoff/xdrv_12_home_assistant.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index b5d0c076c..2972d39ea 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -302,7 +302,8 @@ void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, } else { snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[device], key?"BTN":"SW"); } - GetPowerDevice(value_template, device+1, sizeof(value_template), Settings.flag.device_index_enable); + GetPowerDevice(value_template, device+1, sizeof(value_template), + key + Settings.flag.device_index_enable); // Force index for Switch 1, Index on Button1 is controlled by Settings.flag.device_index_enable GetTopic_P(state_topic, CMND, topic, value_template); // State of button is sent as CMND TOGGLE, state of switch is sent as ON/OFF GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); FindPrefix(state_topic, availability_topic, prefix); From d8cf001304fbdba5f5f4898fc7cb90bfaacbad7f Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 7 Dec 2018 21:32:01 +0100 Subject: [PATCH 0674/2222] Announce RGBW light, add 'White' command --- sonoff/i18n.h | 1 + sonoff/xdrv_04_light.ino | 12 +++++++++--- sonoff/xdrv_12_home_assistant.ino | 22 ++++++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 317e78712..40312fc5c 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -330,6 +330,7 @@ #define D_CMND_SPEED "Speed" #define D_CMND_WAKEUP "Wakeup" #define D_CMND_WAKEUPDURATION "WakeUpDuration" +#define D_CMND_WHITE "White" #define D_CMND_WIDTH "Width" // Commands xdrv_05_irremote.ino diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 829374d08..919657f56 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -58,11 +58,11 @@ enum LightCommands { CMND_COLOR, CMND_COLORTEMPERATURE, CMND_DIMMER, CMND_LED, CMND_LEDTABLE, CMND_FADE, CMND_PIXELS, CMND_RGBWWTABLE, CMND_ROTATION, CMND_SCHEME, CMND_SPEED, CMND_WAKEUP, CMND_WAKEUPDURATION, - CMND_WIDTH, CMND_CHANNEL, CMND_HSBCOLOR, CMND_UNDOCA }; + CMND_WHITE, CMND_WIDTH, CMND_CHANNEL, CMND_HSBCOLOR, 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_RGBWWTABLE "|" D_CMND_ROTATION "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" - D_CMND_WIDTH "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ; + D_CMND_WHITE "|" D_CMND_WIDTH "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ; struct LRgbColor { uint8_t R, G, B; @@ -1098,7 +1098,13 @@ boolean LightCommand(void) if (-1 == command_code) { serviced = false; // Unknown command } - else if ((CMND_COLOR == command_code) && (light_subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { + else if ((CMND_WHITE == command_code) && (light_subtype == LST_RGBW) && (XdrvMailbox.index == 1)) { + command_code = CMND_COLOR; + uint8_t value = atoi(XdrvMailbox.data); + snprintf_P(scolor, sizeof(scolor), PSTR("0,0,0,%d"), value*255/100); + XdrvMailbox.data = scolor; + } + if ((CMND_COLOR == command_code) && (light_subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { if (XdrvMailbox.data_len > 0) { valid_entry = LightColorEntry(XdrvMailbox.data, XdrvMailbox.data_len); if (valid_entry) { diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 2972d39ea..b000f0460 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -61,6 +61,12 @@ const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = "\"rgb_state_topic\":\"%s\"," // stat/led2/RESULT "\"rgb_value_template\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; +const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = + "%s,\"white_value_command_topic\":\"%s\"," // cmnd/led2/White + "\"white_value_state_topic\":\"%s\"," // stat/led2/RESULT + "\"white_value_scale\":100," + "\"white_value_template\":\"{{ value_json.Channel[3] }}\""; + const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = "%s,\"color_temp_command_topic\":\"%s\"," // cmnd/led2/CT "\"color_temp_state_topic\":\"%s\"," // stat/led2/RESULT @@ -126,6 +132,12 @@ const char HASS_DISCOVER_LIGHT_COLOR_SHORT[] PROGMEM = "\"rgb_stat_t\":\"%s\"," // stat/led2/RESULT "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; +const char HASS_DISCOVER_LIGHT_WHITE_SHORT[] PROGMEM = + "%s,\"whit_val_cmd_t\":\"%s\"," // cmnd/led2/White + "\"whit_val_stat_t\":\"%s\"," // stat/led2/RESULT + "\"white_value_scale\":100," // (No abbreviation defined) + "\"whit_val_tpl\":\"{{ value_json.Channel[3] }}\""; + const char HASS_DISCOVER_LIGHT_CT_SHORT[] PROGMEM = "%s,\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT "\"clr_temp_stat_t\":\"%s\"," // stat/led2/RESULT @@ -258,6 +270,16 @@ void HAssAnnounceRelayLight(void) } } + if (LST_RGBW == light_subtype) { + char _white_temp_command_topic[TOPSZ]; + char *white_temp_command_topic = _white_temp_command_topic; + + GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); + if (Settings.flag3.hass_short_discovery_msg) + Shorten(&white_temp_command_topic, prefix); + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_WHITE_SHORT:HASS_DISCOVER_LIGHT_WHITE, + mqtt_data, white_temp_command_topic, state_topic); + } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { char _color_temp_command_topic[TOPSZ]; char *color_temp_command_topic = _color_temp_command_topic; From a65041fee50f960026d4f4dcd0efd826f01f0c62 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 8 Dec 2018 08:44:59 +0100 Subject: [PATCH 0675/2222] Enabled forced local operation when button- or switchtopic is set --- sonoff/my_user_config.h | 1 + sonoff/settings.h | 2 +- sonoff/settings.ino | 1 + sonoff/sonoff.ino | 4 ++-- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index ef81066f3..043a81111 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -96,6 +96,7 @@ #define MQTT_BUTTON_RETAIN 0 // [ButtonRetain] Button may send retain flag (0 = off, 1 = on) #define MQTT_POWER_RETAIN 0 // [PowerRetain] Power status message may send retain flag (0 = off, 1 = on) #define MQTT_SWITCH_RETAIN 0 // [SwitchRetain] Switch may send retain flag (0 = off, 1 = on) +#define MQTT_BUTTON_SWITCH_FORCE_LOCAL 0 // [SetOption61] Force local operation when button/switch topic is set (0 = off, 1 = on) #define MQTT_STATUS_OFF "OFF" // [StateText1] Command or Status result when turned off (needs to be a string like "0" or "Off") #define MQTT_STATUS_ON "ON" // [StateText2] Command or Status result when turned on (needs to be a string like "1" or "On") diff --git a/sonoff/settings.h b/sonoff/settings.h index c773b3b86..d18ab6886 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -74,7 +74,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t receive_raw : 1; // bit 8 (v6.3.0.11) uint32_t hass_tele_on_power : 1; // bit 9 (v6.3.0.13) uint32_t sleep_normal : 1; // bit 10 (v6.3.0.15) - SetOption60 - Enable normal sleep instead of dynamic sleep - uint32_t spare11 : 1; + uint32_t button_switch_force_local : 1;// bit 11 uint32_t spare12 : 1; uint32_t spare13 : 1; uint32_t spare14 : 1; diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 7f065b626..46c1d849d 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -486,6 +486,7 @@ void SettingsDefaultSet2(void) Settings.flag.mqtt_power_retain = MQTT_POWER_RETAIN; Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN; Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; + Settings.flag3.button_switch_force_local = MQTT_BUTTON_SWITCH_FORCE_LOCAL; // Settings.flag.mqtt_sensor_retain = 0; // Settings.flag.mqtt_offline = 0; // Settings.flag.mqtt_serial = 0; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index f979e15c5..ad14aeccd 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1316,7 +1316,7 @@ boolean SendKey(byte key, byte device, byte state) if (9 == state) { mqtt_data[0] = '\0'; } else { - if ((!strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) && (2 == state)) { + if ((Settings.flag3.button_switch_force_local || !strcmp(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)); @@ -1328,7 +1328,7 @@ boolean SendKey(byte key, byte device, byte state) #else MqttPublishDirect(stopic, (key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain); #endif // USE_DOMOTICZ - result = true; + result = !Settings.flag3.button_switch_force_local; } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); result = XdrvRulesProcess(); From ebf74ab424efc07624e28ffcf400f79d2b52929f Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 8 Dec 2018 09:43:48 +0100 Subject: [PATCH 0676/2222] Update Hass discovery --- sonoff/xdrv_12_home_assistant.ino | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 2972d39ea..a57de717b 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -345,9 +345,10 @@ void HAssAnnounceSwitches(void) // Check if MQTT message will be ON/OFF or TOGGLE if (Settings.switchmode[switch_index] == FOLLOW || Settings.switchmode[switch_index] == FOLLOW_INV || + Settings.flag3.button_switch_force_local || !strcmp(mqtt_topic, sw_topic) || !strcmp(Settings.mqtt_grptopic, sw_topic)) { - toggle = 0; + toggle = 0; // MQTT message will be ON/OFF } HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 0, toggle); @@ -377,9 +378,10 @@ void HAssAnnounceButtons(void) } // Check if MQTT message will be ON/OFF or TOGGLE - if (!strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) + if (Settings.flag3.button_switch_force_local || + !strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) { - toggle = 0; + toggle = 0; // MQTT message will be ON/OFF } HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 1, toggle); From ee35a949ca09fe627730f8419ef99d05a7fdcd18 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Sat, 8 Dec 2018 10:28:12 +0100 Subject: [PATCH 0677/2222] v2.1.0012 decode-config.py: add new settings - add 6.3.0.16 setting change --- tools/decode-config.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 1850e2aea..1691b455b 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0011' +VER = '2.1.0012' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -803,7 +803,13 @@ Setting_6_3_0_15['flag3'][0].update ({ 'sleep_normal': (' Date: Sat, 8 Dec 2018 10:28:12 +0100 Subject: [PATCH 0678/2222] decode-config.py: add new settings - add 6.3.0.16 setting change --- tools/decode-config.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 1850e2aea..1691b455b 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0011' +VER = '2.1.0012' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -803,7 +803,13 @@ Setting_6_3_0_15['flag3'][0].update ({ 'sleep_normal': (' Date: Sat, 8 Dec 2018 15:24:16 +0100 Subject: [PATCH 0679/2222] Fix reversed logic when announcing buttons / switches --- sonoff/xdrv_12_home_assistant.ino | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 00492463e..a3b9bb659 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -301,6 +301,8 @@ void HAssAnnounceRelayLight(void) void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, byte toggle) { +// key 0 = button +// key 1 = switch char stopic[TOPSZ]; char sidx[8]; @@ -308,7 +310,7 @@ void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, // Clear or Set topic snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s_%s_%d/config"), - topic, key?"BTN":"SW",device+1); + topic, key?"SW":"BTN",device+1); if (Settings.flag.hass_discovery && present) { char name[33]; @@ -320,9 +322,9 @@ void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, char *availability_topic = _availability_topic; if (device+1 > MAX_FRIENDLYNAMES) { - snprintf_P(name, sizeof(name), PSTR("%s %s %d"), Settings.friendlyname[0], key?"BTN":"SW", device+1); + snprintf_P(name, sizeof(name), PSTR("%s %s %d"), Settings.friendlyname[0], key?"SW":"BTN", device+1); } else { - snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[device], key?"BTN":"SW"); + snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[device], key?"SW":"BTN"); } GetPowerDevice(value_template, device+1, sizeof(value_template), key + Settings.flag.device_index_enable); // Force index for Switch 1, Index on Button1 is controlled by Settings.flag.device_index_enable @@ -373,7 +375,7 @@ void HAssAnnounceSwitches(void) toggle = 0; // MQTT message will be ON/OFF } - HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 0, toggle); + HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 1, toggle); } } } @@ -406,7 +408,7 @@ void HAssAnnounceButtons(void) toggle = 0; // MQTT message will be ON/OFF } - HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 1, toggle); + HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 0, toggle); } } } From 140aa8780ac73d4b216fd731416238fe74478ae0 Mon Sep 17 00:00:00 2001 From: Staars Date: Sun, 9 Dec 2018 09:34:22 +0100 Subject: [PATCH 0680/2222] add DMP mode to MPU-6050 --- sonoff/xsns_32_mpu6050.ino | 82 +++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 14 deletions(-) diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index 0c6f50f09..7115800dd 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -19,6 +19,7 @@ #ifdef USE_I2C #ifdef USE_MPU6050 +#define USE_MPU6050_DMP // Use the DMP on the chip, should create better results /*********************************************************************************************\ * MPU6050 3 axis gyroscope and temperature sensor * @@ -42,11 +43,49 @@ int16_t MPU_6050_ax = 0, MPU_6050_ay = 0, MPU_6050_az = 0; int16_t MPU_6050_gx = 0, MPU_6050_gy = 0, MPU_6050_gz = 0; int16_t MPU_6050_temperature = 0; -#include +#ifdef USE_MPU6050_DMP + #include "MPU6050_6Axis_MotionApps20.h" + #include "I2Cdev.h" + #include + typedef struct MPU6050_DMP{ + uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) + uint16_t packetSize; // expected DMP packet size (default is 42 bytes) + uint16_t fifoCount; // count of all bytes currently in FIFO + uint8_t fifoBuffer[64]; // FIFO storage buffer + Quaternion q; // [w, x, y, z] quaternion container + VectorInt16 aa; // [x, y, z] accel sensor measurements + VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements + VectorFloat gravity; // [x, y, z] gravity vector + float euler[3]; // [psi, theta, phi] Euler angle container + } MPU6050_DMP; + + MPU6050_DMP MPU6050_dmp; +#else + #include +#endif //USE_MPU6050_DMP MPU6050 mpu6050; void MPU_6050PerformReading(void) { +#ifdef USE_MPU6050_DMP + mpu6050.resetFIFO(); // with a default dampling rate of 200Hz, we create a delay of approx. 5ms with a complete read cycle + MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); + while (MPU6050_dmp.fifoCount < MPU6050_dmp.packetSize) MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); + mpu6050.getFIFOBytes(MPU6050_dmp.fifoBuffer, MPU6050_dmp.packetSize); + MPU6050_dmp.fifoCount -= MPU6050_dmp.packetSize; + // calculate euler and acceleration with the DMP + mpu6050.dmpGetQuaternion(&MPU6050_dmp.q, MPU6050_dmp.fifoBuffer); + mpu6050.dmpGetEuler(MPU6050_dmp.euler, &MPU6050_dmp.q); + mpu6050.dmpGetAccel(&MPU6050_dmp.aa, MPU6050_dmp.fifoBuffer); + mpu6050.dmpGetGravity(&MPU6050_dmp.gravity, &MPU6050_dmp.q); + mpu6050.dmpGetLinearAccel(&MPU6050_dmp.aaReal, &MPU6050_dmp.aa, &MPU6050_dmp.gravity); + MPU_6050_gx = MPU6050_dmp.euler[0] * 180/M_PI; + MPU_6050_gy = MPU6050_dmp.euler[1] * 180/M_PI; + MPU_6050_gz = MPU6050_dmp.euler[2] * 180/M_PI; + MPU_6050_ax = MPU6050_dmp.aaReal.x; + MPU_6050_ay = MPU6050_dmp.aaReal.y; + MPU_6050_az = MPU6050_dmp.aaReal.z; +#else mpu6050.getMotion6( &MPU_6050_ax, &MPU_6050_ay, @@ -55,7 +94,7 @@ void MPU_6050PerformReading(void) &MPU_6050_gy, &MPU_6050_gz ); - +#endif //USE_MPU6050_DMP MPU_6050_temperature = mpu6050.getTemperature(); } @@ -84,14 +123,30 @@ void MPU_6050Detect(void) for (byte i = 0; i < sizeof(MPU_6050_addresses); i++) { + if(!I2cDevice(MPU_6050_addresses[i])) + { + break; + } MPU_6050_address = MPU_6050_addresses[i]; + mpu6050.setAddr(MPU_6050_addresses[i]); - mpu6050.setAddr(MPU_6050_address); +#ifdef USE_MPU6050_DMP + MPU6050_dmp.devStatus = mpu6050.dmpInitialize(); + mpu6050.setXGyroOffset(220); + mpu6050.setYGyroOffset(76); + mpu6050.setZGyroOffset(-85); + mpu6050.setZAccelOffset(1788); + if (MPU6050_dmp.devStatus == 0) { + mpu6050.setDMPEnabled(true); + MPU6050_dmp.packetSize = mpu6050.dmpGetFIFOPacketSize(); + MPU_6050_found = true; + } +#else mpu6050.initialize(); - + MPU_6050_found = mpu6050.testConnection(); +#endif //USE_MPU6050_DMP Settings.flag2.axis_resolution = 2; // Need to be services by command Sensor32 - MPU_6050_found = mpu6050.testConnection(); } if (MPU_6050_found) @@ -119,11 +174,10 @@ const char HTTP_SNS_GZ_AXIS[] PROGMEM = "%s{s}%s " D_GZ_AXIS "{m}%s{e}"; void MPU_6050Show(boolean json) { - double tempConv = (MPU_6050_temperature / 340.0 + 35.53); - if (MPU_6050_found) { MPU_6050PerformReading(); + double tempConv = (MPU_6050_temperature / 340.0 + 35.53); char temperature[10]; dtostrfd(tempConv, Settings.flag2.temperature_resolution, temperature); char axis_ax[10]; @@ -140,20 +194,20 @@ void MPU_6050Show(boolean json) dtostrfd(MPU_6050_gz, Settings.flag2.axis_resolution, axis_gz); if (json) { - char json_axis_ax[40]; + char json_axis_ax[25]; snprintf_P(json_axis_ax, sizeof(json_axis_ax), PSTR(",\"" D_JSON_AXIS_AX "\":%s"), axis_ax); - char json_axis_ay[40]; + char json_axis_ay[25]; snprintf_P(json_axis_ay, sizeof(json_axis_ay), PSTR(",\"" D_JSON_AXIS_AY "\":%s"), axis_ay); - char json_axis_az[40]; + char json_axis_az[25]; snprintf_P(json_axis_az, sizeof(json_axis_az), PSTR(",\"" D_JSON_AXIS_AZ "\":%s"), axis_az); - char json_axis_gx[40]; + char json_axis_gx[25]; snprintf_P(json_axis_gx, sizeof(json_axis_gx), PSTR(",\"" D_JSON_AXIS_GX "\":%s"), axis_gx); - char json_axis_gy[40]; + char json_axis_gy[25]; snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy); - char json_axis_gz[40]; + char json_axis_gz[25]; snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), - mqtt_data, D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); + mqtt_data, D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); #ifdef USE_DOMOTICZ DomoticzTempHumSensor(temperature, 0); #endif // USE_DOMOTICZ From aab716798a2abe1c83bac0b6eab2b0f4f6094970 Mon Sep 17 00:00:00 2001 From: Staars Date: Sun, 9 Dec 2018 09:35:23 +0100 Subject: [PATCH 0681/2222] fix compile issue on ESP8266 --- lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h b/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h index 1f7b88589..46920438a 100644 --- a/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h @@ -46,7 +46,11 @@ THE SOFTWARE. // Tom Carpenter's conditional PROGMEM code // http://forum.arduino.cc/index.php?topic=129407.0 #ifndef __arm__ - #include + #if (defined(__AVR__)) + #include + #else + #include + #endif #else // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen #ifndef __PGMSPACE_H_ @@ -402,7 +406,7 @@ uint8_t MPU6050::dmpInitialize() { setIntEnabled(0x12); DEBUG_PRINTLN(F("Setting sample rate to 200Hz...")); - setRate(4); // 1khz / (1 + 4) = 200 Hz + setRate(1); // 1khz / (1 + 4) = 200 Hz DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]...")); setExternalFrameSync(MPU6050_EXT_SYNC_TEMP_OUT_L); From a516b25c1bb6452ab7d5c31882936eb011784050 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 9 Dec 2018 16:45:26 +0100 Subject: [PATCH 0682/2222] Clean and shrink lights Clean and shrink lights --- sonoff/xdrv_04_light.ino | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 919657f56..6fad79fe3 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -590,7 +590,7 @@ void LightState(uint8_t append) // Add status for each channel snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_CHANNEL "\":[" ), mqtt_data); for (byte i = 0; i < light_subtype; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d" ), mqtt_data, (i > 0 ? "," : ""), round(light_current_color[i]/2.55)); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d" ), mqtt_data, (i > 0 ? "," : ""), light_current_color[i] * 100 / 255); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]" ), mqtt_data); } @@ -1084,7 +1084,6 @@ boolean LightColorEntry(char *buffer, uint8_t buffer_length) /********************************************************************************************/ -//boolean LightCommand(char *type, uint16_t index, char *dataBuf, uint16_t XdrvMailbox.data_len, int16_t XdrvMailbox.payload) boolean LightCommand(void) { char command [CMDSZ]; @@ -1098,13 +1097,17 @@ boolean LightCommand(void) if (-1 == command_code) { serviced = false; // Unknown command } - else if ((CMND_WHITE == command_code) && (light_subtype == LST_RGBW) && (XdrvMailbox.index == 1)) { - command_code = CMND_COLOR; - uint8_t value = atoi(XdrvMailbox.data); - snprintf_P(scolor, sizeof(scolor), PSTR("0,0,0,%d"), value*255/100); - XdrvMailbox.data = scolor; - } - if ((CMND_COLOR == command_code) && (light_subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { + else if (((CMND_COLOR == command_code) && (light_subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) || + ((CMND_WHITE == command_code) && (light_subtype == LST_RGBW) && (XdrvMailbox.index == 1))) { + if (CMND_WHITE == command_code) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + snprintf_P(scolor, sizeof(scolor), PSTR("0,0,0,%d"), XdrvMailbox.payload * 255 / 100); + XdrvMailbox.data = scolor; + XdrvMailbox.data_len = strlen(scolor); + } else { + XdrvMailbox.data_len = 0; + } + } if (XdrvMailbox.data_len > 0) { valid_entry = LightColorEntry(XdrvMailbox.data, XdrvMailbox.data_len); if (valid_entry) { @@ -1142,12 +1145,11 @@ boolean LightCommand(void) else if ((CMND_CHANNEL == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= light_subtype ) ) { // Set "Channel" directly - this allows Color and Direct PWM control to coexist if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - uint8_t level = XdrvMailbox.payload; - light_current_color[XdrvMailbox.index-1] = round(level * 2.55); + light_current_color[XdrvMailbox.index-1] = XdrvMailbox.payload * 255 / 100; LightSetColor(); coldim = true; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, round(light_current_color[XdrvMailbox.index -1] / 2.55)); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, light_current_color[XdrvMailbox.index -1] * 100 / 255); } else if ((CMND_HSBCOLOR == command_code) && ( light_subtype >= LST_RGB)) { bool validHSB = (XdrvMailbox.data_len > 0); From 9f515c6c08e02931f94f38cacb1a450a0f282baf Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 10 Dec 2018 19:51:47 +0100 Subject: [PATCH 0683/2222] Add support for device registry --- sonoff/xdrv_12_home_assistant.ino | 113 +++++++++++++++++------------- 1 file changed, 66 insertions(+), 47 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index a3b9bb659..c21749dc2 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -44,7 +44,7 @@ const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE[] PROGMEM = - "%s,\"force_update\":true"; + "%s,\"off_delay\":1"; const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = "%s,\"payload_off\":\"%s\""; // OFF @@ -114,7 +114,7 @@ const char HASS_DISCOVER_BUTTON_SWITCH_SHORT[] PROGMEM = "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT[] PROGMEM = - "%s,\"frc_upd\":true"; + "%s,\"off_delay\":1"; const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT[] PROGMEM = "%s,\"pl_off\":\"%s\""; // OFF @@ -168,6 +168,14 @@ const char HASS_DISCOVER_SENSOR_HUM_SHORT[] PROGMEM = const char HASS_DISCOVER_SENSOR_ANY_SHORT[] PROGMEM = "%s,\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} +const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = + "%s,\"uniq_id\":\"%s\"," + "\"device\":{\"identifiers\":[\"%06X\"]," + "\"name\":\"%s\"," + "\"model\":\"%s\"," + "\"sw_version\":\"%s%s\"," + "\"manufacturer\":\"%s\"}"; + const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM = "%s, \"~\":\"%s\""; @@ -193,8 +201,11 @@ static void Shorten(char** s, char *prefix) void HAssAnnounceRelayLight(void) { - char sidx[8]; char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char stemp3[TOPSZ]; + char unique_id[30]; bool is_light = false; bool is_topic_light = false; @@ -204,23 +215,21 @@ void HAssAnnounceRelayLight(void) mqtt_data[0] = '\0'; // Clear retained message - snprintf_P(sidx, sizeof(sidx), PSTR("_%d"), i); - // Clear "other" topic first in case the device has been reconfigured - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s%s/config"), (is_topic_light) ? "switch" : "light", mqtt_topic, sidx); + // Clear "other" topic first in case the device has been reconfigured from ligth to switch or vice versa + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "RL" : "LI", i); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), (is_topic_light) ? "switch" : "light", unique_id); MqttPublish(stopic, true); // Clear or Set topic - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s%s/config"), (is_topic_light) ? "light" : "switch", mqtt_topic, sidx); + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "LI" : "RL", i); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), (is_topic_light) ? "light" : "switch", unique_id); if (Settings.flag.hass_discovery && (i <= devices_present)) { char name[33]; char value_template[33]; - char _command_topic[TOPSZ]; - char _state_topic[TOPSZ]; - char _availability_topic[TOPSZ]; char prefix[TOPSZ]; - char *command_topic = _command_topic; - char *state_topic = _state_topic; - char *availability_topic = _availability_topic; + char *command_topic = stemp1; + char *state_topic = stemp2; + char *availability_topic = stemp3; if (i > MAX_FRIENDLYNAMES) { snprintf_P(name, sizeof(name), PSTR("%s %d"), Settings.friendlyname[0], i); @@ -242,8 +251,7 @@ void HAssAnnounceRelayLight(void) name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); if (is_light) { - char _brightness_command_topic[TOPSZ]; - char *brightness_command_topic = _brightness_command_topic; + char *brightness_command_topic = stemp1; GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); if (Settings.flag3.hass_short_discovery_msg) @@ -252,8 +260,7 @@ void HAssAnnounceRelayLight(void) mqtt_data, brightness_command_topic, state_topic); if (light_subtype >= LST_RGB) { - char _rgb_command_topic[TOPSZ]; - char *rgb_command_topic = _rgb_command_topic; + char *rgb_command_topic = stemp1; GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); if (Settings.flag3.hass_short_discovery_msg) @@ -261,8 +268,7 @@ void HAssAnnounceRelayLight(void) snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_COLOR_SHORT:HASS_DISCOVER_LIGHT_COLOR, mqtt_data, rgb_command_topic, state_topic); - char _effect_command_topic[TOPSZ]; - char *effect_command_topic = _effect_command_topic; + char *effect_command_topic = stemp1; GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); if (Settings.flag3.hass_short_discovery_msg) { Shorten(&effect_command_topic, prefix); @@ -271,8 +277,7 @@ void HAssAnnounceRelayLight(void) } if (LST_RGBW == light_subtype) { - char _white_temp_command_topic[TOPSZ]; - char *white_temp_command_topic = _white_temp_command_topic; + char *white_temp_command_topic = stemp1; GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); if (Settings.flag3.hass_short_discovery_msg) @@ -281,8 +286,7 @@ void HAssAnnounceRelayLight(void) mqtt_data, white_temp_command_topic, state_topic); } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { - char _color_temp_command_topic[TOPSZ]; - char *color_temp_command_topic = _color_temp_command_topic; + char *color_temp_command_topic = stemp1; GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); if (Settings.flag3.hass_short_discovery_msg) @@ -291,8 +295,13 @@ void HAssAnnounceRelayLight(void) mqtt_data, color_temp_command_topic, state_topic); } } - if (Settings.flag3.hass_short_discovery_msg) + if (Settings.flag3.hass_short_discovery_msg) { + snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, + unique_id, ESP.getChipId(), + Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } MqttPublish(stopic, true); @@ -304,22 +313,22 @@ void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, // key 0 = button // key 1 = switch char stopic[TOPSZ]; - char sidx[8]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; mqtt_data[0] = '\0'; // Clear retained message // Clear or Set topic - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s_%s_%d/config"), - topic, key?"SW":"BTN",device+1); + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), key?"SW":"BTN", device+1); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); if (Settings.flag.hass_discovery && present) { char name[33]; char value_template[33]; - char _state_topic[TOPSZ]; - char _availability_topic[TOPSZ]; char prefix[TOPSZ]; - char *state_topic = _state_topic; - char *availability_topic = _availability_topic; + char *state_topic = stemp1; + char *availability_topic = stemp2; if (device+1 > MAX_FRIENDLYNAMES) { snprintf_P(name, sizeof(name), PSTR("%s %s %d"), Settings.friendlyname[0], key?"SW":"BTN", device+1); @@ -338,14 +347,19 @@ void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_SHORT:HASS_DISCOVER_BUTTON_SWITCH, name, state_topic, Settings.state_text[toggle?2:1], availability_topic); if (toggle) snprintf_P(mqtt_data, sizeof(mqtt_data), - Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT:HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, - mqtt_data); - else snprintf_P(mqtt_data, sizeof(mqtt_data), - Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT:HASS_DISCOVER_BUTTON_SWITCH_ONOFF, - mqtt_data, Settings.state_text[0]); + Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT:HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, + mqtt_data); + if (!toggle) snprintf_P(mqtt_data, sizeof(mqtt_data), + Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT:HASS_DISCOVER_BUTTON_SWITCH_ONOFF, + mqtt_data, Settings.state_text[0]); - if (Settings.flag3.hass_short_discovery_msg) + if (Settings.flag3.hass_short_discovery_msg) { + snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, + unique_id, ESP.getChipId(), + Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } MqttPublish(stopic, true); @@ -382,7 +396,6 @@ void HAssAnnounceSwitches(void) void HAssAnnounceButtons(void) { - char stopic[TOPSZ]; char key_topic[sizeof(Settings.button_topic)]; // Send info about buttons @@ -416,21 +429,22 @@ void HAssAnnounceButtons(void) void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) { char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; // Announce sensor, special handling of temperature and humidity sensors mqtt_data[0] = '\0'; // Clear retained message // Clear or Set topic - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s_%s_%s/config"), - mqtt_topic, sensorname, subsensortype); + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP.getChipId(), sensorname, subsensortype); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); if (Settings.flag.hass_discovery) { char name[33]; - char _state_topic[TOPSZ]; - char _availability_topic[TOPSZ]; char prefix[TOPSZ]; - char *state_topic = _state_topic; - char *availability_topic = _availability_topic; + char *state_topic = stemp1; + char *availability_topic = stemp2; snprintf_P(name, sizeof(name), PSTR("%s %s %s"), Settings.friendlyname[0], sensorname, subsensortype); GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); @@ -442,18 +456,23 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) } snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_SHORT:HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); - if (!strcmp(subsensortype, "Temperature")) { + if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_TEMP_SHORT:HASS_DISCOVER_SENSOR_TEMP, mqtt_data, TempUnit(), sensorname); - } else if (!strcmp(subsensortype, "Humidity")) { + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_HUM_SHORT:HASS_DISCOVER_SENSOR_HUM, mqtt_data, sensorname); } else { snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_ANY_SHORT:HASS_DISCOVER_SENSOR_ANY, mqtt_data, sensorname, subsensortype); } - if (Settings.flag3.hass_short_discovery_msg) + if (Settings.flag3.hass_short_discovery_msg) { + snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, + unique_id, ESP.getChipId(), + Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } MqttPublish(stopic, true); From 4fb6773ffbed6a1f6f00cf8cc76e913a8320d5f6 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Mon, 10 Dec 2018 19:28:22 +0000 Subject: [PATCH 0684/2222] Update my_user_config.h --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index ef81066f3..cade32e94 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -312,7 +312,7 @@ // #define USE_PCA9685_FREQ 50 // Define default PWM frequency in Hz to be used (must be within 24 to 1526) - If other value is used, it will rever to 50Hz // #define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code) // #define USE_CCS811 // Enable CCS811 sensor (I2C address 0x5A) (+2k2 code) -// #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) +// #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+12KB of code and 188 Bytes RAM) // #define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) // #define USE_RTC_ADDR 0x68 // Default I2C address 0x68 // #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) From a75bc93634dd54a8b6b2b3f0b3c05394e2c6aaf0 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Mon, 10 Dec 2018 19:43:19 +0000 Subject: [PATCH 0685/2222] Fix Warning in Platformio if building MPU and KNX together --- lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h b/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h index 46920438a..90704f0c7 100644 --- a/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/lib/I2Cdevlib-MPU6050/MPU6050_6Axis_MotionApps20.h @@ -113,11 +113,19 @@ THE SOFTWARE. #define DEBUG_PRINTLN(x) Serial.println(x) #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) #else +#ifndef DEBUG_PRINT #define DEBUG_PRINT(x) +#endif +#ifndef DEBUG_PRINTF #define DEBUG_PRINTF(x, y) +#endif +#ifndef DEBUG_PRINTLN #define DEBUG_PRINTLN(x) +#endif +#ifndef DEBUG_PRINTLNF #define DEBUG_PRINTLNF(x, y) #endif +#endif #define MPU6050_DMP_CODE_SIZE 1929 // dmpMemory[] #define MPU6050_DMP_CONFIG_SIZE 192 // dmpConfig[] From 384cc5cb16838e4845a4ade9bf792a117eafd716 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Mon, 10 Dec 2018 20:03:36 +0000 Subject: [PATCH 0686/2222] USE_MPU6050_DMP moved to my_user_config.h --- sonoff/my_user_config.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index cade32e94..048519bb2 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -312,7 +312,8 @@ // #define USE_PCA9685_FREQ 50 // Define default PWM frequency in Hz to be used (must be within 24 to 1526) - If other value is used, it will rever to 50Hz // #define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code) // #define USE_CCS811 // Enable CCS811 sensor (I2C address 0x5A) (+2k2 code) -// #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+12KB of code and 188 Bytes RAM) +// #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+3K3 of code and 188 Bytes of RAM) +// #define USE_MPU6050_DMP // Enable in MPU6050 to use the DMP on the chip, should create better results (+8k6 of code) // #define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) // #define USE_RTC_ADDR 0x68 // Default I2C address 0x68 // #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) From e5d3c3b793680e16cde728a149c2bc7efc339955 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Mon, 10 Dec 2018 20:04:48 +0000 Subject: [PATCH 0687/2222] USE_MPU6050_DMP moved to my_user_config.h --- sonoff/xsns_32_mpu6050.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index 7115800dd..6a6d5a1df 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -19,7 +19,6 @@ #ifdef USE_I2C #ifdef USE_MPU6050 -#define USE_MPU6050_DMP // Use the DMP on the chip, should create better results /*********************************************************************************************\ * MPU6050 3 axis gyroscope and temperature sensor * From bc30a18adee249703847a0a4a143dd5cea430dc2 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Tue, 11 Dec 2018 00:57:41 +0000 Subject: [PATCH 0688/2222] Corrected Domoticz Temp published from MPU6050 --- sonoff/xsns_32_mpu6050.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index 6a6d5a1df..b80366194 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -208,7 +208,7 @@ void MPU_6050Show(boolean json) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), mqtt_data, D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); #ifdef USE_DOMOTICZ - DomoticzTempHumSensor(temperature, 0); + DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { From 9c69701af3fb401f3044cf529f3d169c9b58b117 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Tue, 11 Dec 2018 08:19:04 +0100 Subject: [PATCH 0689/2222] decode-config.py: add new settings - add SetOption61 from PR #4562 --- tools/decode-config.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 1691b455b..d03e9eaee 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0012' +VER = '2.1.0013' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -807,6 +807,9 @@ Setting_6_3_0_16 = copy.deepcopy(Setting_6_3_0_15) Setting_6_3_0_16['mcp230xx_config'][0].update ({ 'int_retain_flag': (' Date: Tue, 11 Dec 2018 13:12:19 +0100 Subject: [PATCH 0690/2222] Update my_user_config.h --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 987b3ca32..24c35a91b 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -354,7 +354,7 @@ #define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) #define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) -#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) +//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) #define SDM120_SPEED 9600 // SDM120-Modbus RS485 serial speed (default: 2400 baud) #define USE_SDM220 // add extra parameters for SDM220 (+0k1 code) //#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) From a913c4459aa39d41186504bc9e6fd6ec69d697bc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 11 Dec 2018 13:58:37 +0100 Subject: [PATCH 0691/2222] Fix language file Fix language file --- sonoff/language/sv-SE.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index db8f663a1..abaa994db 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -515,8 +515,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -594,4 +594,13 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + #endif // _LANGUAGE_SV_SE_H_ From 67ec0678a3ea07c8b3d5aca1fecdbe30bd54bb16 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 11 Dec 2018 14:24:52 +0100 Subject: [PATCH 0692/2222] 6.3.0.17 Add features 6.3.0.17 20181211 * Add support for TheoV2 sensors as documented on https://sidweb.nl * Add support for SDM220 (#3610) * Enhance support for MPU6050 using DMP (#4581) --- sonoff/_changelog.ino | 7 +- sonoff/i18n.h | 13 +- sonoff/language/bg-BG.h | 1 + sonoff/language/cs-CZ.h | 1 + sonoff/language/de-DE.h | 1 + sonoff/language/el-GR.h | 1 + sonoff/language/en-GB.h | 3 +- sonoff/language/es-AR.h | 1 + sonoff/language/fr-FR.h | 1 + sonoff/language/he-HE.h | 1 + sonoff/language/hu-HU.h | 1 + sonoff/language/it-IT.h | 1 + sonoff/language/nl-NL.h | 1 + sonoff/language/pl-PL.h | 1 + sonoff/language/pt-BR.h | 1 + sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 1 + sonoff/language/sv-SE.h | 3 +- sonoff/language/tr-TR.h | 1 + sonoff/language/uk-UK.h | 1 + sonoff/language/zh-CN.h | 1 + sonoff/language/zh-TW.h | 1 + sonoff/my_user_config.h | 6 +- sonoff/sonoff.ino | 1 + sonoff/sonoff_template.h | 7 +- sonoff/sonoff_version.h | 2 +- sonoff/support_features.ino | 13 +- sonoff/support_rtc.ino | 40 +-- sonoff/xsns_10_bh1750.ino | 5 - sonoff/xsns_37_rfsensor.ino | 634 ++++++++++++++++++++++++++++++++++++ tools/decode-status.py | 4 +- 31 files changed, 714 insertions(+), 43 deletions(-) create mode 100644 sonoff/xsns_37_rfsensor.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index cbad2b3c2..4ca0e0dd7 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,9 @@ -/* 6.3.0.16 20181201 +/* 6.3.0.17 20181211 + * Add support for TheoV2 sensors as documented on https://sidweb.nl + * Add support for SDM220 (#3610) + * Enhance support for MPU6050 using DMP (#4581) + * + * 6.3.0.16 20181201 * Add support for iFan02 Fanspeed in Domoticz using a selector (#4517) * Add Announce Switches to MQTT Discovery (#4531) * Update MCP230xx driver to support interrupt retention over teleperiod (#4547) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 66ee5e490..b1bec3289 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -49,12 +49,6 @@ #define D_JSON_COUNT "Count" #define D_JSON_COUNTER "Counter" #define D_JSON_CURRENT "Current" // As in Voltage and Current -#define D_JSON_PHASE_ANGLE "Phase angle" -#define D_JSON_IMPORT_ACTIVE "Import Active Power" -#define D_JSON_EXPORT_ACTIVE "Export Active Power" -#define D_JSON_IMPORT_REACTIVE "Import Reactive Power" -#define D_JSON_EXPORT_REACTIVE "Export Reactive Power" -#define D_JSON_TOTAL_REACTIVE "Total Reactive Power" #define D_JSON_DATA "Data" #define D_JSON_DISTANCE "Distance" #define D_JSON_DNSSERVER "DNSServer" @@ -65,6 +59,8 @@ #define D_JSON_ERASE "Erase" #define D_JSON_ERROR "Error" #define D_JSON_EVERY "Every" +#define D_JSON_EXPORT_ACTIVE "ExportActivePower" +#define D_JSON_EXPORT_REACTIVE "ExportReactivePower" #define D_JSON_FAILED "Failed" #define D_JSON_FALLBACKTOPIC "FallbackTopic" #define D_JSON_FEATURES "Features" @@ -86,6 +82,8 @@ #define D_JSON_I2CSCAN_NO_DEVICES_FOUND "No devices found" #define D_JSON_ID "Id" #define D_JSON_ILLUMINANCE "Illuminance" +#define D_JSON_IMPORT_ACTIVE "ImportActivePower" +#define D_JSON_IMPORT_REACTIVE "ImportReactivePower" #define D_JSON_INFRARED "Infrared" #define D_JSON_UNKNOWN "Unknown" #define D_JSON_LIGHT "Light" @@ -99,6 +97,7 @@ #define D_JSON_NONE "None" #define D_JSON_OR "or" #define D_JSON_PERIOD "Period" +#define D_JSON_PHASE_ANGLE "PhaseAngle" #define D_JSON_POWERFACTOR "Factor" #define D_JSON_POWERUSAGE "Power" #define D_JSON_ACTIVE_POWERUSAGE "ActivePower" @@ -135,6 +134,7 @@ #define D_JSON_TIME "Time" #define D_JSON_TODAY "Today" #define D_JSON_TOTAL "Total" +#define D_JSON_TOTAL_REACTIVE "TotalReactivePower" #define D_JSON_TOTAL_START_TIME "TotalStartTime" #define D_JSON_TVOC "TVOC" #define D_JSON_TYPE "Type" @@ -546,6 +546,7 @@ const char HTTP_SNS_HUM[] PROGMEM = "%s{s}%s " D_HUMIDITY "{m}%s%%{e}"; const char HTTP_SNS_PRESSURE[] PROGMEM = "%s{s}%s " D_PRESSURE "{m}%s %s{e}"; // {s} = const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}"; // {s} = const char HTTP_SNS_ANALOG[] PROGMEM = "%s{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = +const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = #if defined(USE_MHZ19) || defined(USE_SENSEAIR) const char HTTP_SNS_CO2[] PROGMEM = "%s{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 9cad9f63f..9ed4734a8 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index ffd69a714..8bcde604b 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 69f12e56e..21f7e5dd8 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index bafc460c4..e59855a24 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 4cb1d381e..a38664d2f 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -536,7 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" - +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" @@ -594,6 +594,7 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 #define D_PHASE_ANGLE "Phase Angle" #define D_IMPORT_ACTIVE "Import Active" #define D_EXPORT_ACTIVE "Export Active" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index c0d8885a5..7039d66a6 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index b6dc5132f..a038153c9 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 2039683a4..6f3612fb7 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 8fefbfa7d..82c911fb1 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index da2f91107..b971d1c02 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index c8a32a463..73a201448 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 2a26afa78..e4728bda8 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 4bad901e7..487f4793d 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index a0ec3643b..4b2366758 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -536,7 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" - +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index ac7b5ea16..e2e6079cd 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index abaa994db..9ec54c62b 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -536,7 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" - +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" @@ -594,6 +594,7 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 #define D_PHASE_ANGLE "Phase Angle" #define D_IMPORT_ACTIVE "Import Active" #define D_EXPORT_ACTIVE "Export Active" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index cee31869f..4425431ee 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 281975c07..82449858e 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index f882765a5..f1ba0c93d 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 6a9b9bd52..3a9d12336 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -536,6 +536,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index a9caabdb8..3a35b7d33 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -357,7 +357,7 @@ #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) //#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) #define SDM120_SPEED 9600 // SDM120-Modbus RS485 serial speed (default: 2400 baud) - #define USE_SDM220 // add extra parameters for SDM220 (+0k1 code) + #define USE_SDM220 // Add extra parameters for SDM220 (+0k1 code) //#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) //#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop @@ -399,6 +399,10 @@ #define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram) +//#define USE_RF_SENSOR // Add support for RF (434MHz or 868MHz) receiver (+2k code) +// #define USE_THEO_V2 // Add support for 434MHz Theo V2 sensors as documented on https://sidweb.nl +// #define USE_ALECTO_V2 // Add support for 868MHz Alecto V2 sensors like ACH2010, WS3000 and DKW2012 + /*********************************************************************************************\ * Debug features are only supported in development branch \*********************************************************************************************/ diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ad14aeccd..8e4006ca1 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2766,6 +2766,7 @@ void loop(void) uint32_t my_sleep = millis(); XdrvCall(FUNC_LOOP); + XsnsCall(FUNC_LOOP); OsWatchLoop(); diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 225d3767a..f3b366d38 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -140,6 +140,7 @@ enum UserSelectablePins { GPIO_SSPI_SCLK, // Software SPI Serial Clock GPIO_SSPI_CS, // Software SPI Chip Select GPIO_SSPI_DC, // Software SPI Data or Command + GPIO_RF_SENSOR, // Rf receiver with sensor decoding GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -199,7 +200,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|" D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|" D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET "|" - D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC; + D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC "|" + D_SENSOR_RF_SENSOR; /********************************************************************************************/ @@ -382,6 +384,9 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_RFSEND, // RF transmitter GPIO_RFRECV, // RF receiver #endif +#ifdef USE_RF_SENSOR + GPIO_RF_SENSOR, // Rf receiver with sensor decoding +#endif #ifdef USE_SR04 GPIO_SR04_TRIG, // SR04 Trigger pin GPIO_SR04_ECHO, // SR04 Echo pin diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 9c41f0220..ed771e734 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06030010 +#define VERSION 0x06030011 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 8859cca55..652116b2f 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -361,10 +361,15 @@ void GetFeatures(void) #ifdef USE_MGC3130 feature_sns2 |= 0x00004000; // xsns_36_mgc3130.ino #endif - -// feature_sns2 |= 0x00008000; -// feature_sns2 |= 0x00010000; -// feature_sns2 |= 0x00020000; +#ifdef USE_RF_SENSOR + feature_sns2 |= 0x00008000; // xsns_37_rfsensor.ino +#endif +#ifdef USE_THEO_V2 + feature_sns2 |= 0x00010000; +#endif +#ifdef USE_ALECTO_V2 + feature_sns2 |= 0x00020000; +#endif // feature_sns2 |= 0x00040000; // feature_sns2 |= 0x00080000; // feature_sns2 |= 0x00100000; diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index 4ba0747a5..b09c593e2 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -87,6 +87,20 @@ String GetTimeZone(void) return String(tz); // -03:45 } +String GetDT(uint32_t time) +{ + // "2017-03-07T11:08:02" - ISO8601:2004 + + char dt[20]; + TIME_T tmpTime; + + BreakTime(time, tmpTime); + snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), + tmpTime.year +1970, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); + + return String(dt); // 2017-03-07T11:08:02 +} + /* * timestamps in https://en.wikipedia.org/wiki/ISO_8601 format * @@ -101,39 +115,27 @@ String GetTimeZone(void) String GetDateAndTime(byte time_type) { // "2017-03-07T11:08:02-07:00" - ISO8601:2004 - char dt[27]; - TIME_T tmpTime; + uint32_t time = local_time; switch (time_type) { case DT_ENERGY: - BreakTime(Settings.energy_kWhtotal_time, tmpTime); - tmpTime.year += 1970; + time = Settings.energy_kWhtotal_time; break; case DT_UTC: - BreakTime(utc_time, tmpTime); - tmpTime.year += 1970; + time = utc_time; break; case DT_RESTART: if (restart_time == 0) { return ""; } - BreakTime(restart_time, tmpTime); - tmpTime.year += 1970; + time = restart_time; break; - default: - tmpTime = RtcTime; } - - - snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), - tmpTime.year, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); - + String dt = GetDT(time); // 2017-03-07T11:08:02 if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { -// if (Settings.flag3.time_append_timezone && ((DT_LOCAL == time_type) || (DT_ENERGY == time_type))) { - strncat(dt, GetTimeZone().c_str(), sizeof(dt) - strlen(dt) -1); + dt += GetTimeZone(); // 2017-03-07T11:08:02-07:00 } - - return String(dt); // 2017-03-07T11:08:02-07:00 + return dt; // 2017-03-07T11:08:02-07:00 } String GetTime(int type) diff --git a/sonoff/xsns_10_bh1750.ino b/sonoff/xsns_10_bh1750.ino index c93a3513f..af0d1aebb 100644 --- a/sonoff/xsns_10_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -89,11 +89,6 @@ void Bh1750EverySecond(void) } } -#ifdef USE_WEBSERVER -const char HTTP_SNS_ILLUMINANCE[] PROGMEM = - "%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = -#endif // USE_WEBSERVER - void Bh1750Show(boolean json) { if (bh1750_valid) { diff --git a/sonoff/xsns_37_rfsensor.ino b/sonoff/xsns_37_rfsensor.ino new file mode 100644 index 000000000..63c567839 --- /dev/null +++ b/sonoff/xsns_37_rfsensor.ino @@ -0,0 +1,634 @@ +/* + xsns_37_rfsensor.ino - RF sensor receiver for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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_RF_SENSOR +/*********************************************************************************************\ + * RF receive based on work by Paul Tonkes (www.nodo-domotica.nl) + * + * USE_THEO_V2 Add support for 434MHz Theo V2 sensors as documented on https://sidweb.nl + * USE_ALECTO_V2 Add support for 868MHz Alecto V2 sensors like ACH2010, WS3000 and DKW2012 +\*********************************************************************************************/ + +#define XSNS_37 37 + +//#define USE_THEO_V2 // Add support for 434MHz Theo V2 sensors as documented on https://sidweb.nl +//#define USE_ALECTO_V2 // Add support for 868MHz Alecto V2 sensors like ACH2010, WS3000 and DKW2012 + +#define RFSNS_VALID_WINDOW 1800 // Number of seconds for sensor to respond (1800 = 30 minutes) + +#define RFSNS_LOOPS_PER_MILLI 1900 // (345 voor 16MHz ATMega) Voor 80MHz NodeMCU (ESP-12E). Getest met TheoV2 Protocol. +#define RFSNS_RAW_BUFFER_SIZE 180 // (256) Maximum number of RF pulses that can be captured +#define RFSNS_MIN_RAW_PULSES 112 // (16) =8 bits. Minimaal aantal ontvangen bits*2 alvorens cpu tijd wordt besteed aan decodering, etc. + // Zet zo hoog mogelijk om CPU-tijd te sparen en minder 'onzin' te ontvangen. +#define RFSNS_MIN_PULSE_LENGTH 300 // (50) Pulsen korter dan deze tijd uSec. worden als stoorpulsen beschouwd. +#define RFSNS_RAWSIGNAL_SAMPLE 50 // Sample grootte / Resolutie in uSec waarmee ontvangen Rawsignalen pulsen worden opgeslagen +#define RFSNS_SIGNAL_TIMEOUT 10 // Pulse timings in mSec. Beyond this value indicate end of message +#define RFSNS_SIGNAL_REPEAT_TIME 500 // (500) Tijd in mSec. waarbinnen hetzelfde event niet nogmaals via RF mag binnenkomen. Onderdrukt ongewenste herhalingen van signaal + +struct RawSignalStruct // Variabelen geplaatst in struct zodat deze later eenvoudig kunnen worden weggeschreven naar SDCard +{ + int Number; // aantal bits, maal twee omdat iedere bit een mark en een space heeft. + byte Repeats; // Aantal maal dat de pulsreeks verzonden moet worden bij een zendactie. + byte Multiply; // Pulses[] * Multiply is de echte tijd van een puls in microseconden + unsigned long Time; // Tijdstempel wanneer signaal is binnengekomen (millis()) + byte Pulses[RFSNS_RAW_BUFFER_SIZE+2]; // Tabel met de gemeten pulsen in microseconden gedeeld door rfsns_raw_signal.Multiply. Dit scheelt helft aan RAM geheugen. + // Om legacy redenen zit de eerste puls in element 1. Element 0 wordt dus niet gebruikt. +} rfsns_raw_signal = {0, 0, 0, 0L}; + +uint8_t rfsns_rf_bit; +uint8_t rfsns_rf_port; + +/*********************************************************************************************\ + * Fetch signals from RF pin +\*********************************************************************************************/ + +boolean RfSnsFetchSignal(byte DataPin, boolean StateSignal) +{ + uint8_t Fbit = digitalPinToBitMask(DataPin); + uint8_t Fport = digitalPinToPort(DataPin); + uint8_t FstateMask = (StateSignal ? Fbit : 0); + + if ((*portInputRegister(Fport) & Fbit) == FstateMask) { // Als er signaal is + const unsigned long LoopsPerMilli = RFSNS_LOOPS_PER_MILLI; + + // Als het een herhalend signaal is, dan is de kans groot dat we binnen hele korte tijd weer in deze + // routine terugkomen en dan midden in de volgende herhaling terecht komen. Daarom wordt er in dit + // geval gewacht totdat de pulsen voorbij zijn en we met het capturen van data beginnen na een korte + // rust tussen de signalen. Op deze wijze wordt het aantal zinloze captures teruggebracht. + + unsigned long PulseLength = 0; + if (rfsns_raw_signal.Time) { // Eerst een snelle check, want dit bevindt zich in een tijdkritisch deel... + if (rfsns_raw_signal.Repeats && (rfsns_raw_signal.Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) { // ...want deze check duurt enkele micro's langer! + PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; // Wachttijd + while (((rfsns_raw_signal.Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && (PulseLength > micros())) { + if ((*portInputRegister(Fport) & Fbit) == FstateMask) { + PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; + } + } + while (((rfsns_raw_signal.Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && ((*portInputRegister(Fport) & Fbit) != FstateMask)); + } + } + + int RawCodeLength = 1; // We starten bij 1, dit om legacy redenen. Vroeger had element 0 een speciaal doel. + bool Ftoggle = false; + unsigned long numloops = 0; + unsigned long maxloops = RFSNS_SIGNAL_TIMEOUT * LoopsPerMilli; + rfsns_raw_signal.Multiply = RFSNS_RAWSIGNAL_SAMPLE; // Ingestelde sample groote. + do { // lees de pulsen in microseconden en plaats deze in de tijdelijke buffer rfsns_raw_signal + numloops = 0; + while(((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) { // while() loop *A* + if (numloops++ == maxloops) { break; } // timeout opgetreden + } + PulseLength = (numloops *1000) / LoopsPerMilli; // Bevat nu de pulslengte in microseconden + if (PulseLength < RFSNS_MIN_PULSE_LENGTH) { break; } + Ftoggle = !Ftoggle; + rfsns_raw_signal.Pulses[RawCodeLength++] = PulseLength / (unsigned long)rfsns_raw_signal.Multiply; // sla op in de tabel rfsns_raw_signal + } + while(RawCodeLength < RFSNS_RAW_BUFFER_SIZE && numloops <= maxloops); // Zolang nog ruimte in de buffer, geen timeout en geen stoorpuls + + if ((RawCodeLength >= RFSNS_MIN_RAW_PULSES) && (RawCodeLength < RFSNS_RAW_BUFFER_SIZE -1)) { + rfsns_raw_signal.Repeats = 0; // Op dit moment weten we nog niet het type signaal, maar de variabele niet ongedefinieerd laten. + rfsns_raw_signal.Number = RawCodeLength -1; // Aantal ontvangen tijden (pulsen *2) + rfsns_raw_signal.Pulses[rfsns_raw_signal.Number] = 0; // Laatste element bevat de timeout. Niet relevant. + rfsns_raw_signal.Time = millis(); + return true; + } + else + rfsns_raw_signal.Number = 0; + } + + return false; +} + +#ifdef USE_THEO_V2 +/*********************************************************************************************\ + * Theo V2 protocol + * Dit protocol zorgt voor ontvangst van Theo sensoren met protocol V2 + * + * Auteur : Theo Arends + * Support : www.sidweb.nl + * Datum : 17 Apr 2014 + * Versie : 0.1 - Initiele versie + ********************************************************************************************** + * Technische informatie: + * + * Theo Sensor V2 type 1 Message Format (7 Bytes, 57 bits): + * Checksum Type Chl BsVoltag Temperature Light + * S AAAAAAAA BBBBBCCC DEFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH HHHHHHHH + * idx: 0 1 2 3 4 5 6 + * + * Theo Sensor V2 type 2 Message Format (7 Bytes, 57 bits): + * Checksum Type Chl BsVoltag Temperature Humidity + * S AAAAAAAA BBBBBCCC DEFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH HHHHHHHH + * idx: 0 1 2 3 4 5 6 +\*********************************************************************************************/ + +#define RFSNS_THEOV2_MAX_CHANNEL 2 // Max number of ATTiny sensor channels supported + +#define RFSNS_THEOV2_PULSECOUNT 114 +#define RFSNS_THEOV2_RF_PULSE_MID 1000 // PWM: Pulsen langer zijn '1' + +typedef struct { + uint32_t time; + int16_t temp; + uint16_t lux; + uint8_t volt; +} theo_v2_t1_t; + +theo_v2_t1_t rfsns_theo_v2_t1[RFSNS_THEOV2_MAX_CHANNEL]; + +typedef struct { + uint32_t time; + int16_t temp; + uint16_t hum; + uint8_t volt; +} theo_v2_t2_t; + +theo_v2_t2_t rfsns_theo_v2_t2[RFSNS_THEOV2_MAX_CHANNEL]; + +boolean RfSnsAnalyzeTheov2(void) +{ + if (rfsns_raw_signal.Number != RFSNS_THEOV2_PULSECOUNT) return false; + + byte Checksum; // 8 bits Checksum over following bytes + byte Channel; // 3 bits channel + byte Type; // 5 bits type + byte Voltage; // 8 bits Vcc like 45 = 4.5V, bit 8 is batt low + int Payload1; // 16 bits + int Payload2; // 16 bits + + byte b, bytes, bits, id; + char log[128]; + + byte idx = 3; + byte chksum = 0; + for (bytes = 0; bytes < 7; bytes++) { + b = 0; + for (bits = 0; bits <= 7; bits++) + { + if ((rfsns_raw_signal.Pulses[idx] * rfsns_raw_signal.Multiply) > RFSNS_THEOV2_RF_PULSE_MID) { + b |= 1 << bits; + } + idx += 2; + } + if (bytes > 0) { chksum += b; } // bereken checksum + + switch (bytes) { + case 0: + Checksum = b; + break; + case 1: + id = b; + Channel = b & 0x7; + Type = (b >> 3) & 0x1f; + break; + case 2: + Voltage = b; + break; + case 3: + Payload1 = b; + break; + case 4: + Payload1 = (b << 8) | Payload1; + break; + case 5: + Payload2 = b; + break; + case 6: + Payload2 = (b << 8) | Payload2; + break; + } + } + + if (Checksum != chksum) { return false; } + if (Channel == 0) { return false; } + + rfsns_raw_signal.Repeats = 1; // het is een herhalend signaal. Bij ontvangst herhalingen onderdukken + + int Payload3 = Voltage & 0x3f; + Channel--; + + switch (Type) { + case 1: // Temp / Lux + rfsns_theo_v2_t1[Channel].time = LocalTime(); + rfsns_theo_v2_t1[Channel].volt = Payload3; + rfsns_theo_v2_t1[Channel].temp = Payload1; + rfsns_theo_v2_t1[Channel].lux = Payload2; + break; + case 2: // Temp / Hum + rfsns_theo_v2_t2[Channel].time = LocalTime(); + rfsns_theo_v2_t2[Channel].volt = Payload3; + rfsns_theo_v2_t2[Channel].temp = Payload1; + rfsns_theo_v2_t2[Channel].hum = Payload2; + break; + } + + snprintf_P(log_data, sizeof(log_data), PSTR("RFS: TheoV2, ChkCalc %d, Chksum %d, id %d, Type %d, Ch %d, Volt %d, BattLo %d, Pld1 %d, Pld2 %d"), + chksum, Checksum, id, Type, Channel +1, Payload3, (Voltage & 0x80) >> 7, Payload1, Payload2); + AddLog(LOG_LEVEL_DEBUG); + + return true; +} + +void RfSnsTheoV2Show(boolean json) +{ + bool sensor_once = false; + + for (uint8_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { + if (rfsns_theo_v2_t1[i].time) { + char sensor[10]; + snprintf_P(sensor, sizeof(sensor), PSTR("TV2T1C%d"), i +1); + char voltage[10]; + dtostrfd((float)rfsns_theo_v2_t1[i].volt / 10, 1, voltage); + + if (rfsns_theo_v2_t1[i].time < LocalTime() - RFSNS_VALID_WINDOW) { + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), + mqtt_data, sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage); + } + } else { + char temperature[10]; + dtostrfd(ConvertTemp((float)rfsns_theo_v2_t1[i].temp / 100), Settings.flag2.temperature_resolution, temperature); + + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"), + mqtt_data, sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && !sensor_once) { + DomoticzSensor(DZ_TEMP, temperature); + DomoticzSensor(DZ_ILLUMINANCE, rfsns_theo_v2_t1[i].lux); + sensor_once = true; + } +#endif // USE_DOMOTICZ +#ifdef USE_WEBSERVER + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sensor, temperature, TempUnit()); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE, mqtt_data, sensor, rfsns_theo_v2_t1[i].lux); +#endif // USE_WEBSERVER + } + } + } + } + + sensor_once = false; + for (uint8_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { + if (rfsns_theo_v2_t2[i].time) { + char sensor[10]; + snprintf_P(sensor, sizeof(sensor), PSTR("TV2T2C%d"), i +1); + char voltage[10]; + dtostrfd((float)rfsns_theo_v2_t2[i].volt / 10, 1, voltage); + + if (rfsns_theo_v2_t2[i].time < LocalTime() - RFSNS_VALID_WINDOW) { + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_RFRECEIVED" \":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), + mqtt_data, sensor, GetDT(rfsns_theo_v2_t2[i].time).c_str(), voltage); + } + } else { + float temp = ConvertTemp((float)rfsns_theo_v2_t2[i].temp / 100); + char temperature[10]; + dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); + float humi = (float)rfsns_theo_v2_t2[i].hum / 100; + char humidity[10]; + dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); + + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_VOLTAGE "\":%s}"), + mqtt_data, sensor, temperature, humidity, voltage); + if ((0 == tele_period) && !sensor_once) { +#ifdef USE_DOMOTICZ + DomoticzTempHumSensor(temperature, humidity); +#endif // USE_DOMOTICZ +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, temp); + KnxSensor(KNX_HUMIDITY, humi); +#endif // USE_KNX + sensor_once = true; + } +#ifdef USE_WEBSERVER + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sensor, temperature, TempUnit()); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, sensor, humidity); +#endif // USE_WEBSERVER + } + } + } + } +} + +#endif // USE_THEO_V2 ************************************************************************ + +#ifdef USE_ALECTO_V2 +/*********************************************************************************************\ + * Alecto V2 protocol + * Dit protocol zorgt voor ontvangst van Alecto weerstation buitensensoren + * + * Auteur : Nodo-team (Martinus van den Broek) www.nodo-domotica.nl + * Support ACH2010 en code optimalisatie door forumlid: Arendst + * Support : www.nodo-domotica.nl + * Datum : 25 Jan 2013 + * Versie : 1.3 + ********************************************************************************************** + * Technische informatie: + * DKW2012 Message Format: (11 Bytes, 88 bits): + * AAAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE FFFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH IIIIIIII + * Temperature Humidity Windspd_ Windgust Rain____ ________ Winddir Checksum + * A = start/unknown, first 8 bits are always 11111111 + * B = Rolling code + * C = Temperature (10 bit value with -400 base) + * D = Humidity + * E = windspeed (* 0.3 m/s, correction for webapp = 3600/1000 * 0.3 * 100 = 108)) + * F = windgust (* 0.3 m/s, correction for webapp = 3600/1000 * 0.3 * 100 = 108)) + * G = Rain ( * 0.3 mm) + * H = winddirection (0 = north, 4 = east, 8 = south 12 = west) + * I = Checksum, calculation is still under investigation + * + * WS3000 and ACH2010 systems have no winddirection, message format is 8 bit shorter + * Message Format: (10 Bytes, 80 bits): + * AAAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE FFFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH + * Temperature Humidity Windspd_ Windgust Rain____ ________ Checksum + * + * DCF Time Message Format: (NOT DECODED!) + * AAAAAAAA BBBBCCCC DDDDDDDD EFFFFFFF GGGGGGGG HHHHHHHH IIIIIIII JJJJJJJJ KKKKKKKK LLLLLLLL MMMMMMMM + * 11 Hours Minutes Seconds Year Month Day ? Checksum + * B = 11 = DCF + * C = ? + * D = ? + * E = ? + * F = Hours BCD format (7 bits only for this byte, MSB could be '1') + * G = Minutes BCD format + * H = Seconds BCD format + * I = Year BCD format (only two digits!) + * J = Month BCD format + * K = Day BCD format + * L = ? + * M = Checksum +\*********************************************************************************************/ + +#define RFSNS_DKW2012_PULSECOUNT 176 +#define RFSNS_ACH2010_MIN_PULSECOUNT 160 // reduce this value (144?) in case of bad reception +#define RFSNS_ACH2010_MAX_PULSECOUNT 160 + +typedef struct { + uint32_t time; + float temp; + float rain; + float wind; + float gust; + uint8_t type; + uint8_t humi; + uint8_t wdir; +} alecto_v2_t; + +alecto_v2_t rfsns_alecto_v2; + +uint16_t rfsns_alecto_rain_base = 0; +//unsigned long rfsns_alecto_time = 60000; + +boolean RfSnsAnalyzeAlectov2() +{ + if (!(((rfsns_raw_signal.Number >= RFSNS_ACH2010_MIN_PULSECOUNT) && + (rfsns_raw_signal.Number <= RFSNS_ACH2010_MAX_PULSECOUNT)) || (rfsns_raw_signal.Number == RFSNS_DKW2012_PULSECOUNT))) { return false; } + + byte c = 0; + byte rfbit; + byte data[9]; + byte msgtype = 0; + byte rc = 0; + int temp; + byte checksum = 0; + byte checksumcalc = 0; + byte maxidx = 8; + unsigned long atime; + float factor; + char buf1[16]; + + if (rfsns_raw_signal.Number > RFSNS_ACH2010_MAX_PULSECOUNT) { maxidx = 9; } + // Get message back to front as the header is almost never received complete for ACH2010 + byte idx = maxidx; + for (byte x = rfsns_raw_signal.Number; x > 0; x = x-2) { + if (rfsns_raw_signal.Pulses[x-1] * rfsns_raw_signal.Multiply < 0x300) { + rfbit = 0x80; + } else { + rfbit = 0; + } + data[idx] = (data[idx] >> 1) | rfbit; + c++; + if (c == 8) { + if (idx == 0) { break; } + c = 0; + idx--; + } + } + + checksum = data[maxidx]; + checksumcalc = RfSnsAlectoCRC8(data, maxidx); + + msgtype = (data[0] >> 4) & 0xf; + rc = (data[0] << 4) | (data[1] >> 4); + + if (checksum != checksumcalc) { return false; } + if ((msgtype != 10) && (msgtype != 5)) { return true; } + + rfsns_raw_signal.Repeats = 1; // het is een herhalend signaal. Bij ontvangst herhalingen onderdukken + + factor = 1.22; // (1.08) +// atime = rfsns_raw_signal.Time - rfsns_alecto_time; +// if ((atime > 10000) && (atime < 60000)) factor = (float)60000 / atime; +// rfsns_alecto_time = rfsns_raw_signal.Time; +// Serial.printf("atime %d, rfsns_alecto_time %d\n", atime, rfsns_alecto_time); + + rfsns_alecto_v2.time = LocalTime(); + rfsns_alecto_v2.type = (rfsns_raw_signal.Number == RFSNS_DKW2012_PULSECOUNT); + rfsns_alecto_v2.temp = (float)(((data[1] & 0x3) * 256 + data[2]) - 400) / 10; + rfsns_alecto_v2.humi = data[3]; + uint16_t rain = (data[6] * 256) + data[7]; + // check if rain unit has been reset! + if (rain < rfsns_alecto_rain_base) { rfsns_alecto_rain_base = rain; } + if (rfsns_alecto_rain_base > 0) { + rfsns_alecto_v2.rain += ((float)rain - rfsns_alecto_rain_base) * 0.30; + } + rfsns_alecto_rain_base = rain; + rfsns_alecto_v2.wind = (float)data[4] * factor; + rfsns_alecto_v2.gust = (float)data[5] * factor; + if (rfsns_alecto_v2.type) { + rfsns_alecto_v2.wdir = data[8] & 0xf; + } + + snprintf_P(log_data, sizeof(log_data), PSTR("RFS: AlectoV2, ChkCalc %d, Chksum %d, rc %d, Temp %d, Hum %d, Rain %d, Wind %d, Gust %d, Dir %d, Factor %s"), + checksumcalc, checksum, rc, ((data[1] & 0x3) * 256 + data[2]) - 400, data[3], (data[6] * 256) + data[7], data[4], data[5], data[8] & 0xf, dtostrfd(factor, 3, buf1)); + AddLog(LOG_LEVEL_DEBUG); + + return true; +} + +void RfSnsAlectoResetRain(void) +{ + if ((RtcTime.hour == 0) && (RtcTime.minute == 0) && (RtcTime.second == 5)) { + rfsns_alecto_v2.rain = 0; // Reset Rain + } +} + +/*********************************************************************************************\ + * Calculates CRC-8 checksum + * reference http://lucsmall.com/2012/04/29/weather-station-hacking-part-2/ + * http://lucsmall.com/2012/04/30/weather-station-hacking-part-3/ + * https://github.com/lucsmall/WH2-Weather-Sensor-Library-for-Arduino/blob/master/WeatherSensorWH2.cpp + \*********************************************************************************************/ +uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len) +{ + uint8_t crc = 0; + while (len--) { + uint8_t inbyte = *addr++; + for (uint8_t i = 8; i; i--) { + uint8_t mix = (crc ^ inbyte) & 0x80; + crc <<= 1; + if (mix) { crc ^= 0x31; } + inbyte <<= 1; + } + } + return crc; +} + +void RfSnsAlectoV2Show(boolean json) +{ + if (rfsns_alecto_v2.time) { + char sensor[10]; + snprintf_P(sensor, sizeof(sensor), PSTR("AlectoV2")); + + if (rfsns_alecto_v2.time < LocalTime() - RFSNS_VALID_WINDOW) { + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), + mqtt_data, sensor, GetDT(rfsns_alecto_v2.time).c_str()); + } + } else { + float temp = ConvertTemp(rfsns_alecto_v2.temp); + char temperature[10]; + dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); + float humi = (float)rfsns_alecto_v2.humi; + char humidity[10]; + dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); + char rain[10]; + dtostrfd(rfsns_alecto_v2.rain, 2, rain); + char wind[10]; + dtostrfd(rfsns_alecto_v2.wind, 2, wind); + char gust[10]; + dtostrfd(rfsns_alecto_v2.gust, 2, gust); + + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s, \"Rain\":%s,\"Wind\":%s,\"Gust\":%s}"), + mqtt_data, sensor, temperature, humidity, rain, wind, gust); + if (0 == tele_period) { +#ifdef USE_DOMOTICZ + DomoticzTempHumSensor(temperature, humidity); +#endif // USE_DOMOTICZ +#ifdef USE_KNX +// KnxSensor(KNX_TEMPERATURE, temp); +// KnxSensor(KNX_HUMIDITY, humi); +#endif // USE_KNX + } +#ifdef USE_WEBSERVER + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sensor, temperature, TempUnit()); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, sensor, humidity); +#endif // USE_WEBSERVER + } + } + } +} +#endif // USE_ALECTO_V2 ********************************************************************** + +void RfSnsInit(void) +{ + rfsns_rf_bit = digitalPinToBitMask(pin[GPIO_RF_SENSOR]); + rfsns_rf_port = digitalPinToPort(pin[GPIO_RF_SENSOR]); + pinMode(pin[GPIO_RF_SENSOR], INPUT); +} + +void RfSnsAnalyzeRawSignal(void) +{ + snprintf_P(log_data, sizeof(log_data), PSTR("RFS: Pulses %d"), (int)rfsns_raw_signal.Number); + AddLog(LOG_LEVEL_DEBUG); + +// if (Settings.flag3.rf_type) { +#ifdef USE_THEO_V2 + RfSnsAnalyzeTheov2(); +#endif +// } else { +#ifdef USE_ALECTO_V2 + RfSnsAnalyzeAlectov2(); +#endif +// } +} + +void RfSnsEverySecond(void) +{ +#ifdef USE_ALECTO_V2 + RfSnsAlectoResetRain(); +#endif +} + +void RfSnsShow(boolean json) +{ +#ifdef USE_THEO_V2 + RfSnsTheoV2Show(json); +#endif + +#ifdef USE_ALECTO_V2 + RfSnsAlectoV2Show(json); +#endif +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +boolean Xsns37(byte function) +{ + boolean result = false; + + if (pin[GPIO_RF_SENSOR] < 99) { + switch (function) { + case FUNC_INIT: + RfSnsInit(); + break; + case FUNC_LOOP: + if ((*portInputRegister(rfsns_rf_port) &rfsns_rf_bit) == rfsns_rf_bit) { + if (RfSnsFetchSignal(pin[GPIO_RF_SENSOR], HIGH)) { + RfSnsAnalyzeRawSignal(); + } + } + sleep = 0; + break; + case FUNC_EVERY_SECOND: + RfSnsEverySecond(); + break; + case FUNC_JSON_APPEND: + RfSnsShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_APPEND: + RfSnsShow(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_RF_SENSOR diff --git a/tools/decode-status.py b/tools/decode-status.py index 3de4dfca3..fa108bc02 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -134,8 +134,8 @@ a_features = [[ "USE_MCP230xx","USE_MPR121","USE_CCS811","USE_MPU6050", "USE_MCP230xx_OUTPUT","USE_MCP230xx_DISPLAYOUTPUT","USE_HLW8012","USE_CSE7766", "USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711", - "USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","", - "","","","", + "USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","USE_RF_SENSOR", + "USE_THEO_V2","USE_ALECTO_V2","","", "","","","", "","","","", "","","",""]] From 808e2c073fd011382b8a5fa7b7b0eabc1f36135e Mon Sep 17 00:00:00 2001 From: Ikarulus Date: Tue, 11 Dec 2018 14:49:58 +0100 Subject: [PATCH 0693/2222] add manzuko "power strip" --- sonoff/sonoff_template.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index f3b366d38..1177d0f3d 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -266,6 +266,7 @@ enum SupportedModules { SK03_TUYA, PS_16_DZ, TECKIN_US, + MANZOKU_EU_4, MAXMODULE }; /********************************************************************************************/ @@ -499,6 +500,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { SK03_TUYA, NEO_COOLCAM, // Socket Relay Devices OBI, + MANZOKU_EU_4, ESP_SWITCH, // Switch Devices TUYA_DIMMER, // Dimmer Devices ARMTRONIX_DIMMERS, @@ -1324,6 +1326,21 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY1, // GPIO13 Button GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage 0, 0, 0 + }, + { "Manzoku strip", // "MANZOKU" labeled power strip, EU version + 0, // GPIO00 + 0, // GPIO01 Serial RXD + 0, + GPIO_KEY1, // GPIO03 Serial TXD + Button + GPIO_REL2, // GPIO04 Relay 2 + GPIO_REL1, // GPIO05 Relay 1 + 0, 0, 0, 0, 0, 0, + GPIO_REL3, // GPIO12 Relay 3 + GPIO_REL4, // GPIO13 Relay 4 + GPIO_USER, // GPIO14 + 0, + GPIO_USER, // GPIO16 + 0 } }; From b3e5e35cea6d6e05e8ddd1a14d569d983f44cf98 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 11 Dec 2018 18:00:12 +0100 Subject: [PATCH 0694/2222] Add more support * Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver * Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver * Add support for Manzoku Power Strip (#4590) --- sonoff/_changelog.ino | 4 ++- sonoff/language/bg-BG.h | 2 ++ sonoff/language/cs-CZ.h | 2 ++ sonoff/language/de-DE.h | 2 ++ sonoff/language/el-GR.h | 2 ++ sonoff/language/en-GB.h | 2 ++ sonoff/language/es-AR.h | 2 ++ sonoff/language/fr-FR.h | 2 ++ sonoff/language/he-HE.h | 2 ++ sonoff/language/hu-HU.h | 2 ++ sonoff/language/it-IT.h | 2 ++ sonoff/language/nl-NL.h | 2 ++ sonoff/language/pl-PL.h | 2 ++ sonoff/language/pt-BR.h | 2 ++ sonoff/language/pt-PT.h | 2 ++ sonoff/language/ru-RU.h | 2 ++ sonoff/language/sv-SE.h | 2 ++ sonoff/language/tr-TR.h | 2 ++ sonoff/language/uk-UK.h | 2 ++ sonoff/language/zh-CN.h | 2 ++ sonoff/language/zh-TW.h | 2 ++ sonoff/my_user_config.h | 6 ++-- sonoff/sonoff_template.h | 6 ++-- sonoff/xsns_37_rfsensor.ino | 71 +++++++++++++++++++++++++++---------- 24 files changed, 103 insertions(+), 24 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 4ca0e0dd7..0f601ec0b 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,8 @@ /* 6.3.0.17 20181211 - * Add support for TheoV2 sensors as documented on https://sidweb.nl + * Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver + * Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver * Add support for SDM220 (#3610) + * Add support for Manzoku Power Strip (#4590) * Enhance support for MPU6050 using DMP (#4581) * * 6.3.0.16 20181201 diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 9ed4734a8..621a0fdb7 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Размер на флаш паметта за програми" #define D_PROGRAM_SIZE "Размер на програмата" #define D_PROJECT "Проект" +#define D_RAIN "Rain" #define D_RECEIVED "Получено" #define D_RESTART "Рестарт" #define D_RESTARTING "Рестартиране" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "µm" #define D_UNIT_MICROSECOND "µs" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "min" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 8bcde604b..461de3a4d 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Velikost paměti flash" #define D_PROGRAM_SIZE "Velikost programu" #define D_PROJECT "Projekt" +#define D_RAIN "Rain" #define D_RECEIVED "Přijatý" #define D_RESTART "Restart" #define D_RESTARTING "Restartování" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "min" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 21f7e5dd8..16c3f886f 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Ges. Flash Speicher" #define D_PROGRAM_SIZE "Ben. Flash Speicher" #define D_PROJECT "Projekt" +#define D_RAIN "Regen" #define D_RECEIVED "erhalten" #define D_RESTART "Neustart" #define D_RESTARTING "starte neu" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "µm" #define D_UNIT_MICROSECOND "µs" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "min" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index e59855a24..2148baf42 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Μέγεθος προγράμματος στη Flash" #define D_PROGRAM_SIZE "Μέγεθος προγράμματος" #define D_PROJECT "Έργο" +#define D_RAIN "Rain" #define D_RECEIVED "Ελήφθη" #define D_RESTART "Επανεκκίνηση" #define D_RESTARTING "Επανεκκινεί" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "Min" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index a38664d2f..70825c5e3 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Program Flash Size" #define D_PROGRAM_SIZE "Program Size" #define D_PROJECT "Project" +#define D_RAIN "Rain" #define D_RECEIVED "Received" #define D_RESTART "Restart" #define D_RESTARTING "Restarting" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "Min" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 7039d66a6..2ad9551e7 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Tamaño de Flash de Programa" #define D_PROGRAM_SIZE "Tamaño Programa" #define D_PROJECT "Proyecto" +#define D_RAIN "Rain" #define D_RECEIVED "Recibido" #define D_RESTART "Reiniciar" #define D_RESTARTING "Reiniciando" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "Min" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index a038153c9..312c5d015 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Taille Flash Programme" #define D_PROGRAM_SIZE "Taille programme" #define D_PROJECT "Projet" +#define D_RAIN "Plui" #define D_RECEIVED "Reçu" #define D_RESTART "Redémarrage" #define D_RESTARTING "Redémarre" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "µm" #define D_UNIT_MICROSECOND "µs" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "Min" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 6f3612fb7..7dc8585db 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "גודל תוכנית פלאש" #define D_PROGRAM_SIZE "גודל תוכנית" #define D_PROJECT "פרויקט" +#define D_RAIN "Rain" #define D_RECEIVED "התקבל" #define D_RESTART "איתחול" #define D_RESTARTING "הפעלה מחדש" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "Min" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 82c911fb1..707bb24ec 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Program Flash Méret" #define D_PROGRAM_SIZE "Program Méret" #define D_PROJECT "Projekt" +#define D_RAIN "Rain" #define D_RECEIVED "Érkezett" #define D_RESTART "Újraindítás" #define D_RESTARTING "Újraindítás" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "µs" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "p" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index b971d1c02..4e1481cec 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Dimensione Flash Programma" #define D_PROGRAM_SIZE "Dimensione Programma" #define D_PROJECT "Progetto" +#define D_RAIN "Rain" #define D_RECEIVED "Ricevuto" #define D_RESTART "Riavvio" #define D_RESTARTING "Riavviando" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "Min" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 73a201448..3383228ed 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Programma Flash Grootte" #define D_PROGRAM_SIZE "Programma Grootte" #define D_PROJECT "Project" +#define D_RAIN "Regen" #define D_RECEIVED "Ontvangen" #define D_RESTART "Herstart" #define D_RESTARTING "Herstarten" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "Min" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index e4728bda8..0019c8d53 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Wielkość programu flash" #define D_PROGRAM_SIZE "Wielkość programu" #define D_PROJECT "Projekt" +#define D_RAIN "Rain" #define D_RECEIVED "Otrzymany" #define D_RESTART "Restart" #define D_RESTARTING "Restartowanie" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "Min" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 487f4793d..e8e536606 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Tamanho do programa na memória" #define D_PROGRAM_SIZE "Tamanho do programa" #define D_PROJECT "Projeto" +#define D_RAIN "Rain" #define D_RECEIVED "Recebido" #define D_RESTART "Reiniciar" #define D_RESTARTING "Reiniciando" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "M" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 4b2366758..58a39fff0 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Tamanho do Programa na Flash" #define D_PROGRAM_SIZE "Tamanho do Programa" #define D_PROJECT "Projeto" +#define D_RAIN "Rain" #define D_RECEIVED "Recebido" #define D_RESTART "Reiniciar" #define D_RESTARTING "A reiniciar" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "Min" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index e2e6079cd..85813373a 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Размер Flash для программ" #define D_PROGRAM_SIZE "Размер программы " #define D_PROJECT "Проект" +#define D_RAIN "Rain" #define D_RECEIVED "Получено" #define D_RESTART "Перезапуск" #define D_RESTARTING "Перезапуск" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "мкм" #define D_UNIT_MICROSECOND "мкс" #define D_UNIT_MILLIAMPERE "мА" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "мм рт.ст." #define D_UNIT_MILLISECOND "мс" #define D_UNIT_MINUTE "мин" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 9ec54c62b..4ae68e78c 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Program-flashstorlek" #define D_PROGRAM_SIZE "Programstorlek" #define D_PROJECT "Projekt" +#define D_RAIN "Rain" #define D_RECEIVED "Mottagen" #define D_RESTART "Omstart" #define D_RESTARTING "Startar om" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "Min" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 4425431ee..43acbaa77 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Yazılım Flash Boyutu" #define D_PROGRAM_SIZE "Yazılım Boyutu" #define D_PROJECT "Proje" +#define D_RAIN "Rain" #define D_RECEIVED "Alınan" #define D_RESTART "Yeniden Başlat" #define D_RESTARTING "Yeniden Başlatılıyor" @@ -552,6 +553,7 @@ #define D_UNIT_MICROMETER "um" #define D_UNIT_MICROSECOND "us" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "Min" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 82449858e..a924a6cf4 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Розмір Flash для програм" #define D_PROGRAM_SIZE "Розмір програм " #define D_PROJECT "Проект" +#define D_RAIN "Rain" #define D_RECEIVED "Отримано" #define D_RESTART "Перезавантаження" #define D_RESTARTING "Перезавантаження" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "мкм" #define D_UNIT_MICROSECOND "мкс" #define D_UNIT_MILLIAMPERE "мА" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "мс" #define D_UNIT_MINUTE "хв" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index f1ba0c93d..dfd5662e0 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "固件 Flash 大小" #define D_PROGRAM_SIZE "固件大小" #define D_PROJECT "项目:" +#define D_RAIN "Rain" #define D_RECEIVED "已接收" #define D_RESTART "重启" #define D_RESTARTING "正在重启" @@ -552,6 +553,7 @@ #define D_UNIT_MICROMETER "微米" #define D_UNIT_MICROSECOND "微秒" #define D_UNIT_MILLIAMPERE "毫安" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "毫秒" #define D_UNIT_MINUTE "分" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 3a9d12336..abc3df93d 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -132,6 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "韌體 Flash 大小" #define D_PROGRAM_SIZE "韌體大小" #define D_PROJECT "項目:" +#define D_RAIN "Rain" #define D_RECEIVED "已接收" #define D_RESTART "重啟" #define D_RESTARTING "正在重啟" @@ -553,6 +554,7 @@ #define D_UNIT_MICROMETER "微米" #define D_UNIT_MICROSECOND "微秒" #define D_UNIT_MILLIAMPERE "毫安" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "毫秒" #define D_UNIT_MINUTE "分" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 3a35b7d33..32821365f 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -399,9 +399,9 @@ #define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram) -//#define USE_RF_SENSOR // Add support for RF (434MHz or 868MHz) receiver (+2k code) -// #define USE_THEO_V2 // Add support for 434MHz Theo V2 sensors as documented on https://sidweb.nl -// #define USE_ALECTO_V2 // Add support for 868MHz Alecto V2 sensors like ACH2010, WS3000 and DKW2012 +//#define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +// #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) +// #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code) /*********************************************************************************************\ * Debug features are only supported in development branch diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 1177d0f3d..91eec21c7 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1327,14 +1327,16 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage 0, 0, 0 }, - { "Manzoku strip", // "MANZOKU" labeled power strip, EU version + { "Manzoku strip", // "MANZOKU" labeled power strip, EU version + // https://www.amazon.de/Steckdosenleiste-AOFO-Mehrfachsteckdose-Überspannungsschutz-Sprachsteuerung/dp/B07GBSD11P/ + // https://www.amazon.de/Steckdosenleiste-Geekbes-USB-Anschluss-Kompatibel-gesteuert/dp/B078W23BW9/ 0, // GPIO00 0, // GPIO01 Serial RXD 0, GPIO_KEY1, // GPIO03 Serial TXD + Button GPIO_REL2, // GPIO04 Relay 2 GPIO_REL1, // GPIO05 Relay 1 - 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, // Flash connection GPIO_REL3, // GPIO12 Relay 3 GPIO_REL4, // GPIO13 Relay 4 GPIO_USER, // GPIO14 diff --git a/sonoff/xsns_37_rfsensor.ino b/sonoff/xsns_37_rfsensor.ino index 63c567839..4829a71b1 100644 --- a/sonoff/xsns_37_rfsensor.ino +++ b/sonoff/xsns_37_rfsensor.ino @@ -312,7 +312,7 @@ void RfSnsTheoV2Show(boolean json) mqtt_data, sensor, temperature, humidity, voltage); if ((0 == tele_period) && !sensor_once) { #ifdef USE_DOMOTICZ - DomoticzTempHumSensor(temperature, humidity); + DomoticzTempHumSensor(temperature, humidity); // #endif // USE_DOMOTICZ #ifdef USE_KNX KnxSensor(KNX_TEMPERATURE, temp); @@ -384,6 +384,25 @@ void RfSnsTheoV2Show(boolean json) #define RFSNS_ACH2010_MIN_PULSECOUNT 160 // reduce this value (144?) in case of bad reception #define RFSNS_ACH2010_MAX_PULSECOUNT 160 +#define D_ALECTOV2 "AlectoV2" + +const char kAlectoV2Directions[] PROGMEM = D_TX20_NORTH "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" + D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST "|" + D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST "|" + D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; + typedef struct { uint32_t time; float temp; @@ -407,7 +426,7 @@ boolean RfSnsAnalyzeAlectov2() byte c = 0; byte rfbit; - byte data[9]; + byte data[9] = { 0 }; byte msgtype = 0; byte rc = 0; int temp; @@ -447,6 +466,10 @@ boolean RfSnsAnalyzeAlectov2() rfsns_raw_signal.Repeats = 1; // het is een herhalend signaal. Bij ontvangst herhalingen onderdukken +// Test set +// rfsns_raw_signal.Number = RFSNS_DKW2012_PULSECOUNT; // DKW2012 +// data[8] = 11; // WSW + factor = 1.22; // (1.08) // atime = rfsns_raw_signal.Time - rfsns_alecto_time; // if ((atime > 10000) && (atime < 60000)) factor = (float)60000 / atime; @@ -454,7 +477,7 @@ boolean RfSnsAnalyzeAlectov2() // Serial.printf("atime %d, rfsns_alecto_time %d\n", atime, rfsns_alecto_time); rfsns_alecto_v2.time = LocalTime(); - rfsns_alecto_v2.type = (rfsns_raw_signal.Number == RFSNS_DKW2012_PULSECOUNT); + rfsns_alecto_v2.type = (RFSNS_DKW2012_PULSECOUNT == rfsns_raw_signal.Number); rfsns_alecto_v2.temp = (float)(((data[1] & 0x3) * 256 + data[2]) - 400) / 10; rfsns_alecto_v2.humi = data[3]; uint16_t rain = (data[6] * 256) + data[7]; @@ -470,7 +493,7 @@ boolean RfSnsAnalyzeAlectov2() rfsns_alecto_v2.wdir = data[8] & 0xf; } - snprintf_P(log_data, sizeof(log_data), PSTR("RFS: AlectoV2, ChkCalc %d, Chksum %d, rc %d, Temp %d, Hum %d, Rain %d, Wind %d, Gust %d, Dir %d, Factor %s"), + snprintf_P(log_data, sizeof(log_data), PSTR("RFS: " D_ALECTOV2 ", ChkCalc %d, Chksum %d, rc %d, Temp %d, Hum %d, Rain %d, Wind %d, Gust %d, Dir %d, Factor %s"), checksumcalc, checksum, rc, ((data[1] & 0x3) * 256 + data[2]) - 400, data[3], (data[6] * 256) + data[7], data[4], data[5], data[8] & 0xf, dtostrfd(factor, 3, buf1)); AddLog(LOG_LEVEL_DEBUG); @@ -505,16 +528,22 @@ uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len) return crc; } +#ifdef USE_WEBSERVER +const char HTTP_SNS_ALECTOV2[] PROGMEM = "%s" + "{s}" D_ALECTOV2 " " D_RAIN "{m}%s " D_UNIT_MILLIMETER "{e}" + "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"; +const char HTTP_SNS_ALECTOV2_WDIR[] PROGMEM = "%s" + "{s}" D_ALECTOV2 " " D_TX20_WIND_DIRECTION "{m}%s{e}"; +#endif + void RfSnsAlectoV2Show(boolean json) { if (rfsns_alecto_v2.time) { - char sensor[10]; - snprintf_P(sensor, sizeof(sensor), PSTR("AlectoV2")); - if (rfsns_alecto_v2.time < LocalTime() - RFSNS_VALID_WINDOW) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), - mqtt_data, sensor, GetDT(rfsns_alecto_v2.time).c_str()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_ALECTOV2 "\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), + mqtt_data, GetDT(rfsns_alecto_v2.time).c_str()); } } else { float temp = ConvertTemp(rfsns_alecto_v2.temp); @@ -529,23 +558,29 @@ void RfSnsAlectoV2Show(boolean json) dtostrfd(rfsns_alecto_v2.wind, 2, wind); char gust[10]; dtostrfd(rfsns_alecto_v2.gust, 2, gust); + char wdir[4]; + char direction[20]; + if (rfsns_alecto_v2.type) { + GetTextIndexed(wdir, sizeof(wdir), rfsns_alecto_v2.wdir, kAlectoV2Directions); + snprintf_P(direction, sizeof(direction), PSTR(",\"Direction\":\"%s\""), wdir); + } if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s, \"Rain\":%s,\"Wind\":%s,\"Gust\":%s}"), - mqtt_data, sensor, temperature, humidity, rain, wind, gust); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_ALECTOV2 "\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), + mqtt_data, temperature, humidity, rain, wind, gust, (rfsns_alecto_v2.type) ? direction : ""); if (0 == tele_period) { #ifdef USE_DOMOTICZ - DomoticzTempHumSensor(temperature, humidity); + // Use a rule #endif // USE_DOMOTICZ -#ifdef USE_KNX -// KnxSensor(KNX_TEMPERATURE, temp); -// KnxSensor(KNX_HUMIDITY, humi); -#endif // USE_KNX } #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sensor, temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, sensor, humidity); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, D_ALECTOV2, temperature, TempUnit()); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, D_ALECTOV2, humidity); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ALECTOV2, mqtt_data, rain, wind, gust); + if (rfsns_alecto_v2.type) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ALECTOV2_WDIR, mqtt_data, wdir); + } #endif // USE_WEBSERVER } } From 0c90db5d857ba213445f8a283b0689b3b375b714 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 11 Dec 2018 17:30:51 +0000 Subject: [PATCH 0695/2222] Updated Spanish Translation --- sonoff/language/es-AR.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 2ad9551e7..011c7a248 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.2.1.11 + * Updated until v6.3.0.17 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -132,7 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "Tamaño de Flash de Programa" #define D_PROGRAM_SIZE "Tamaño Programa" #define D_PROJECT "Proyecto" -#define D_RAIN "Rain" +#define D_RAIN "Lluvia" #define D_RECEIVED "Recibido" #define D_RESTART "Reiniciar" #define D_RESTARTING "Reiniciando" @@ -438,7 +438,7 @@ #define D_START_SIGNAL_LOW "iniciar señal baja" #define D_START_SIGNAL_HIGH "iniciar señal alta" #define D_PULSE "pulso" -#define D_CHECKSUM_FAILURE "Checksum fallido" +#define D_CHECKSUM_FAILURE "Falló Checksum" // xsns_07_sht1x.ino #define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor no ha enviado el comando ACK" @@ -597,13 +597,13 @@ #define D_LOG_WIFI "WIF: " // Wifi //SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" +#define D_PHASE_ANGLE "Ángulo de Fase" +#define D_IMPORT_ACTIVE "P. Activa Entrante" +#define D_EXPORT_ACTIVE "P. Activa Saliente" +#define D_IMPORT_REACTIVE "P. Reactiva Entrante" +#define D_EXPORT_REACTIVE "P. Reactiva Saliente" +#define D_TOTAL_REACTIVE "P. Reactiva Total" +#define D_UNIT_KWARH "kVArH" +#define D_UNIT_ANGLE "Grados" #endif // _LANGUAGE_ES_AR_H_ From 4df23beab1f18cec0bbf8a77bbe59a408c5d4ced Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Tue, 11 Dec 2018 20:27:37 +0100 Subject: [PATCH 0696/2222] Update de-DE.h --- sonoff/language/de-DE.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 16c3f886f..293de0830 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v5.12.0l + * Updated until v6.3.0.17 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -597,13 +597,13 @@ #define D_LOG_WIFI "WIF: " // Wifi //SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" +#define D_PHASE_ANGLE "Phasenwinkel" +#define D_IMPORT_ACTIVE "Importiere Wirk" +#define D_EXPORT_ACTIVE "Exportiere Wirk" +#define D_IMPORT_REACTIVE "Importiere Blind" +#define D_EXPORT_REACTIVE "Exportiere Blind" +#define D_TOTAL_REACTIVE "Total Blind" #define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" +#define D_UNIT_ANGLE "Grad" #endif // _LANGUAGE_DE_DE_H_ From 85c515cc973472c64301f0f6e582734d85b6f95a Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 11 Dec 2018 22:00:34 +0100 Subject: [PATCH 0697/2222] More tweak of Hass switch/button --- sonoff/xdrv_12_home_assistant.ino | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index c21749dc2..20c2a9038 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -44,10 +44,11 @@ const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE[] PROGMEM = - "%s,\"off_delay\":1"; + "%s,\"off_delay\":1"; // Hass has no support for TOGGLE, fake it by resetting to OFF after 1s const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = - "%s,\"payload_off\":\"%s\""; // OFF + "%s,\"force_update\":true," // In ON/OFF case, enable force_update to make automations work + "\"payload_off\":\"%s\""; // OFF const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = "%s,\"brightness_command_topic\":\"%s\"," // cmnd/led2/Dimmer @@ -114,10 +115,11 @@ const char HASS_DISCOVER_BUTTON_SWITCH_SHORT[] PROGMEM = "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT[] PROGMEM = - "%s,\"off_delay\":1"; + "%s,\"off_delay\":1"; // Hass has no support for TOGGLE, fake it by resetting to OFF after 1s const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT[] PROGMEM = - "%s,\"pl_off\":\"%s\""; // OFF + "%s,\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work + "\"pl_off\":\"%s\""; // OFF const char HASS_DISCOVER_LIGHT_DIMMER_SHORT[] PROGMEM = From 276c11fe4e2fd90f0c113dcecbde556cc464bc67 Mon Sep 17 00:00:00 2001 From: Xavier MULLER <33861984+localhost61@users.noreply.github.com> Date: Wed, 12 Dec 2018 02:44:07 +0100 Subject: [PATCH 0698/2222] Update fr-FR.h Added SDM220 new strings --- sonoff/language/fr-FR.h | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 78afd01d1..717fdc265 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.3.0.14 + * Updated until v6.3.0.17 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -124,14 +124,15 @@ #define D_PORT "Port" #define D_POWER_FACTOR "Facteur de puissance" #define D_POWERUSAGE "Puissance" -#define D_POWERUSAGE_ACTIVE "Puissance Active" -#define D_POWERUSAGE_APPARENT "Puissance Apparente" -#define D_POWERUSAGE_REACTIVE "Puissance Réactive" +#define D_POWERUSAGE_ACTIVE "Puissance active" +#define D_POWERUSAGE_APPARENT "Puissance apparente" +#define D_POWERUSAGE_REACTIVE "Puissance réactive" #define D_PRESSURE "Pression" #define D_PRESSUREATSEALEVEL "PressionMer" #define D_PROGRAM_FLASH_SIZE "Taille Flash Programme" #define D_PROGRAM_SIZE "Taille programme" #define D_PROJECT "Projet" +#define D_RAIN "Pluie" #define D_RECEIVED "Reçu" #define D_RESTART "Redémarrage" #define D_RESTARTING "Redémarre" @@ -244,7 +245,7 @@ #define D_CONFIGURE_DOMOTICZ "Configuration Domoticz" #define D_CONFIGURE_LOGGING "Configuration du journal" #define D_CONFIGURE_OTHER "Autre configuration" -#define D_CONFIRM_RESET_CONFIGURATION "Confirmer réinitialisation configuration" +#define D_CONFIRM_RESET_CONFIGURATION "Confirmer la réinit. de la config." #define D_RESET_CONFIGURATION "Configuration par défaut" #define D_BACKUP_CONFIGURATION "Sauvegarde de la config." #define D_RESTORE_CONFIGURATION "Restauration de la config." @@ -515,8 +516,8 @@ #define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_ECHO "SR04 Ech" -#define D_SENSOR_SDM120_TX "SDM120 Tx" -#define D_SENSOR_SDM120_RX "SDM120 Rx" +#define D_SENSOR_SDM120_TX "SDM120/220 Tx" +#define D_SENSOR_SDM120_RX "SDM120/220 Rx" #define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_TM1638_CLK "TM16 CLK" @@ -536,6 +537,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" // Units #define D_UNIT_AMPERE "A" @@ -552,6 +554,7 @@ #define D_UNIT_MICROMETER "µm" #define D_UNIT_MICROSECOND "µs" #define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" #define D_UNIT_MILLIMETER_MERCURY "mmHg" #define D_UNIT_MILLISECOND "ms" #define D_UNIT_MINUTE "Min" @@ -593,4 +596,14 @@ #define D_LOG_UPNP "UPP: " // UPnP #define D_LOG_WIFI "WIF: " // Wifi +//SDM220 +#define D_PHASE_ANGLE "Angle de phase" +#define D_IMPORT_ACTIVE "P active importée" +#define D_EXPORT_ACTIVE "P active exportée" +#define D_IMPORT_REACTIVE "P réactive importée" +#define D_EXPORT_REACTIVE "P réactive exportée" +#define D_TOTAL_REACTIVE "P réactive total" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "°" + #endif // _LANGUAGE_FR_FR_H_ From b7610aab6f73039c7650ef69a9224e45c8b9436c Mon Sep 17 00:00:00 2001 From: Xavier MULLER <33861984+localhost61@users.noreply.github.com> Date: Wed, 12 Dec 2018 05:14:00 +0100 Subject: [PATCH 0699/2222] Update fr-FR.h SDM220 strings reworked to fit in the space available --- sonoff/language/fr-FR.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 717fdc265..642b4686d 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -122,11 +122,11 @@ #define D_ONLINE "Connecté" #define D_PASSWORD "Mot de passe" #define D_PORT "Port" -#define D_POWER_FACTOR "Facteur de puissance" +#define D_POWER_FACTOR "Fact de puiss" #define D_POWERUSAGE "Puissance" -#define D_POWERUSAGE_ACTIVE "Puissance active" -#define D_POWERUSAGE_APPARENT "Puissance apparente" -#define D_POWERUSAGE_REACTIVE "Puissance réactive" +#define D_POWERUSAGE_ACTIVE "Puiss act" +#define D_POWERUSAGE_APPARENT "Puiss app" +#define D_POWERUSAGE_REACTIVE "Puiss réactive" #define D_PRESSURE "Pression" #define D_PRESSUREATSEALEVEL "PressionMer" #define D_PROGRAM_FLASH_SIZE "Taille Flash Programme" @@ -598,11 +598,11 @@ //SDM220 #define D_PHASE_ANGLE "Angle de phase" -#define D_IMPORT_ACTIVE "P active importée" -#define D_EXPORT_ACTIVE "P active exportée" -#define D_IMPORT_REACTIVE "P réactive importée" -#define D_EXPORT_REACTIVE "P réactive exportée" -#define D_TOTAL_REACTIVE "P réactive total" +#define D_IMPORT_ACTIVE "Puiss act conso" +#define D_EXPORT_ACTIVE "Puiss act fournie" +#define D_IMPORT_REACTIVE "Puiss réa conso" +#define D_EXPORT_REACTIVE "Puiss réa fournie" +#define D_TOTAL_REACTIVE "Puiss réa totale" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "°" From b6165e9a811889e9b1bfab577b3cc6a4c01be813 Mon Sep 17 00:00:00 2001 From: Staars Date: Wed, 12 Dec 2018 10:03:58 +0100 Subject: [PATCH 0700/2222] initial work on range-support --- sonoff/xsns_15_mhz19.ino | 54 +++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 21f5d8a15..04f27bee3 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -72,13 +72,18 @@ TasmotaSerial *MhzSerial; const char kMhzTypes[] PROGMEM = "MHZ19|MHZ19B"; -enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET }; -const uint8_t kMhzCommands[][2] PROGMEM = { - {0x86,0x00}, // mhz_cmnd_read_ppm - {0x79,0xA0}, // mhz_cmnd_abc_enable - {0x79,0x00}, // mhz_cmnd_abc_disable - {0x87,0x00}, // mhz_cmnd_zeropoint - {0x8D,0x00}}; // mhz_cmnd_reset +enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; +const uint8_t kMhzCommands[][4] PROGMEM = { +// 2 3 6 7 + {0x86,0x00,0x00,0x00}, // mhz_cmnd_read_ppm + {0x79,0xA0,0x00,0x00}, // mhz_cmnd_abc_enable + {0x79,0x00,0x00,0x00}, // mhz_cmnd_abc_disable + {0x87,0x00,0x00,0x00}, // mhz_cmnd_zeropoint + {0x8D,0x00,0x00,0x00}, // mhz_cmnd_reset + {0x99,0x00,0x03,0xE8}, // mhz_cmnd_set_range_1000 + {0x99,0x00,0x07,0xD0}, // mhz_cmnd_set_range_2000 + {0x99,0x00,0x0B,0xB8}, // mhz_cmnd_set_range_3000 + {0x99,0x00,0x13,0x88}}; // mhz_cmnd_set_range_5000 uint8_t mhz_type = 1; uint16_t mhz_last_ppm = 0; @@ -110,13 +115,12 @@ size_t MhzSendCmd(byte command_id) mhz_send[0] = 0xFF; // Start byte, fixed mhz_send[1] = 0x01; // Sensor number, 0x01 by default - memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(kMhzCommands[0])); + memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(kMhzCommands[2])); /* mhz_send[4] = 0x00; mhz_send[5] = 0x00; - mhz_send[6] = 0x00; - mhz_send[7] = 0x00; */ + memcpy_P(&mhz_send[6], kMhzCommands[command_id] + sizeof(kMhzCommands[2]), sizeof(kMhzCommands[2])); mhz_send[8] = MhzCalculateChecksum(mhz_send); return MhzSerial->write(mhz_send, sizeof(mhz_send)); @@ -246,11 +250,15 @@ void MhzEverySecond(void) /*********************************************************************************************\ * Command Sensor15 * - * 0 - (Not implemented) ABC Off - * 1 - (Not implemented) ABC On - * 2 - Manual start = ABC Off - * 3 - (Not implemented) Optional filter settings - * 9 - Reset + * 0 - (Not implemented) ABC Off + * 1 - (Not implemented) ABC On + * 2 - Manual start = ABC Off + * 3 - (Not implemented) Optional filter settings + * 9 - Reset + * 1000 - Range + * 2000 - Range + * 3000 - Range + * 5000 - Range \*********************************************************************************************/ bool MhzCommandSensor(void) @@ -266,6 +274,22 @@ bool MhzCommandSensor(void) MhzSendCmd(MHZ_CMND_RESET); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); break; + case 1000: + MhzSendCmd(MHZ_CMND_RANGE_1000); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); // not done yet + break; + case 2000: + MhzSendCmd(MHZ_CMND_RANGE_2000); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); // not done yet + break; + case 3000: + MhzSendCmd(MHZ_CMND_RANGE_3000); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); // not done yet + break; + case 5000: + MhzSendCmd(MHZ_CMND_RANGE_5000); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); // not done yet + break; default: serviced = false; } From 5c613040a1c861ec4600a309459df878d0b25eb5 Mon Sep 17 00:00:00 2001 From: Staars Date: Wed, 12 Dec 2018 10:11:19 +0100 Subject: [PATCH 0701/2222] mqtt messages updated --- sonoff/xsns_15_mhz19.ino | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 04f27bee3..6ddcb251a 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -261,6 +261,11 @@ void MhzEverySecond(void) * 5000 - Range \*********************************************************************************************/ +#define D_JSON_RANGE_1000 "1000 ppm range" +#define D_JSON_RANGE_2000 "2000 ppm range" +#define D_JSON_RANGE_3000 "3000 ppm range" +#define D_JSON_RANGE_5000 "5000 ppm range" + bool MhzCommandSensor(void) { boolean serviced = true; @@ -276,19 +281,19 @@ bool MhzCommandSensor(void) break; case 1000: MhzSendCmd(MHZ_CMND_RANGE_1000); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); // not done yet + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_1000); break; case 2000: MhzSendCmd(MHZ_CMND_RANGE_2000); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); // not done yet + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_2000); break; case 3000: MhzSendCmd(MHZ_CMND_RANGE_3000); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); // not done yet + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_3000); break; case 5000: MhzSendCmd(MHZ_CMND_RANGE_5000); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); // not done yet + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); break; default: serviced = false; From d3ccd668b080cba466ac10c62aa499e98b28df45 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 12 Dec 2018 20:32:10 +0100 Subject: [PATCH 0702/2222] Publish state message when changing effect --- sonoff/xdrv_04_light.ino | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 6fad79fe3..52eba7d2d 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -1260,6 +1260,12 @@ boolean LightCommand(void) } LightPowerOn(); strip_timer_counter = 0; + // Publish state message for Hass + if (Settings.flag3.hass_tele_on_power) { + mqtt_data[0] = '\0'; + MqttShowState(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); + } } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_scheme); } From 20a4b1bdc300d33fde2900e8ababd28e495e1a6d Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Thu, 13 Dec 2018 06:57:44 +0100 Subject: [PATCH 0703/2222] decode-config.py: Fix `@v` filename template (#4609) - fix restore filename auto extension --- tools/decode-config.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index d03e9eaee..b53dbaae9 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0013' +VER = '2.1.0014' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -1178,14 +1178,7 @@ def MakeFilename(filename, filetype, configmapping): if device_hostname is None: device_hostname = '' - filename = filename.replace('@v', config_version) - filename = filename.replace('@f', config_friendlyname ) - filename = filename.replace('@h', config_hostname ) - filename = filename.replace('@H', device_hostname ) - - dirname = basename = ext = '' - name = filename # split file parts dirname = os.path.normpath(os.path.dirname(filename)) @@ -1217,6 +1210,11 @@ def MakeFilename(filename, filetype, configmapping): except: pass + filename = filename.replace('@v', config_version) + filename = filename.replace('@f', config_friendlyname ) + filename = filename.replace('@h', config_hostname ) + filename = filename.replace('@H', device_hostname ) + return filename @@ -2371,7 +2369,6 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configmapping): config data mapppings """ - backupfileformat = args.backupfileformat name, ext = os.path.splitext(backupfile) if ext.lower() == '.'+FileType.BIN.lower(): backupfileformat = FileType.BIN @@ -2434,12 +2431,14 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configmapping): message("Backup successful from {} '{}' to file '{}' ({} format)".format(srctype, src, backup_filename, fileformat), typ=LogType.INFO) -def Restore(restorefile, encode_cfg, decode_cfg, configmapping): +def Restore(restorefile, backupfileformat, encode_cfg, decode_cfg, configmapping): """ Restore from file @param encode_cfg: binary config data (encrypted) + @param backupfileformat: + Backup file format @param decode_cfg: binary config data (decrypted) @param configmapping: @@ -2448,7 +2447,14 @@ def Restore(restorefile, encode_cfg, decode_cfg, configmapping): new_encode_cfg = None - restorefilename = MakeFilename(restorefile, None, configmapping) + restorefileformat = None + if backupfileformat.lower() == 'bin': + restorefileformat = FileType.BIN + elif backupfileformat.lower() == 'dmp': + restorefileformat = FileType.DMP + elif backupfileformat.lower() == 'json': + restorefileformat = FileType.JSON + restorefilename = MakeFilename(restorefile, restorefileformat, configmapping) filetype = GetFileType(restorefilename) if filetype == FileType.DMP: @@ -2817,7 +2823,7 @@ if __name__ == "__main__": # restore from file if args.restorefile is not None: - Restore(args.restorefile, encode_cfg, decode_cfg, configmapping) + Restore(args.restorefile, args.backupfileformat, encode_cfg, decode_cfg, configmapping) # json screen output if (args.backupfile is None and args.restorefile is None) or args.output: From 47629a9d61c92c3a80cd6c9b5544ba331b0c62e8 Mon Sep 17 00:00:00 2001 From: Staars Date: Thu, 13 Dec 2018 12:34:51 +0100 Subject: [PATCH 0704/2222] add debug code to show final command sequence --- sonoff/xsns_15_mhz19.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 6ddcb251a..594a47106 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -123,6 +123,9 @@ size_t MhzSendCmd(byte command_id) memcpy_P(&mhz_send[6], kMhzCommands[command_id] + sizeof(kMhzCommands[2]), sizeof(kMhzCommands[2])); mhz_send[8] = MhzCalculateChecksum(mhz_send); + snprintf_P(log_data, sizeof(log_data), PSTR("Final MhzCommand: %x %x %x %x %x %x %x %x %x"),mhz_send[0],mhz_send[1],mhz_send[2],mhz_send[3],mhz_send[4],mhz_send[5],mhz_send[6],mhz_send[7],mhz_send[8]); + AddLog(LOG_LEVEL_DEBUG); + return MhzSerial->write(mhz_send, sizeof(mhz_send)); } From df4f305e3ae502e37f94ca61750683388c30d2fb Mon Sep 17 00:00:00 2001 From: Staars Date: Thu, 13 Dec 2018 13:46:59 +0100 Subject: [PATCH 0705/2222] correcting memcpy calls --- sonoff/xsns_15_mhz19.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 594a47106..523dd3a66 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -115,12 +115,12 @@ size_t MhzSendCmd(byte command_id) mhz_send[0] = 0xFF; // Start byte, fixed mhz_send[1] = 0x01; // Sensor number, 0x01 by default - memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(kMhzCommands[2])); + memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(uint16_t)); /* mhz_send[4] = 0x00; mhz_send[5] = 0x00; */ - memcpy_P(&mhz_send[6], kMhzCommands[command_id] + sizeof(kMhzCommands[2]), sizeof(kMhzCommands[2])); + memcpy_P(&mhz_send[6], kMhzCommands[command_id] + sizeof(uint16_t), sizeof(uint16_t)); mhz_send[8] = MhzCalculateChecksum(mhz_send); snprintf_P(log_data, sizeof(log_data), PSTR("Final MhzCommand: %x %x %x %x %x %x %x %x %x"),mhz_send[0],mhz_send[1],mhz_send[2],mhz_send[3],mhz_send[4],mhz_send[5],mhz_send[6],mhz_send[7],mhz_send[8]); From 3a0ac29b194df78d078c780b028ba181d4b128d9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 13 Dec 2018 16:44:03 +0100 Subject: [PATCH 0706/2222] Add TheoV2 sensor source Add TheoV2 sensor source and information used with Rf Sensor --- .../TheoV2Sensor1/TheoV2Sensor1.ino | 280 +++++++++++++++++ .../TheoV2Sensor2/TheoV2Sensor2.ino | 286 ++++++++++++++++++ tools/theov2_attiny85/info.txt | 15 + 3 files changed, 581 insertions(+) create mode 100644 tools/theov2_attiny85/TheoV2Sensor1/TheoV2Sensor1.ino create mode 100644 tools/theov2_attiny85/TheoV2Sensor2/TheoV2Sensor2.ino create mode 100644 tools/theov2_attiny85/info.txt diff --git a/tools/theov2_attiny85/TheoV2Sensor1/TheoV2Sensor1.ino b/tools/theov2_attiny85/TheoV2Sensor1/TheoV2Sensor1.ino new file mode 100644 index 000000000..540733341 --- /dev/null +++ b/tools/theov2_attiny85/TheoV2Sensor1/TheoV2Sensor1.ino @@ -0,0 +1,280 @@ +/****************************************************************************************************************************\ +* Arduino project "TheoTinySensor" Copyright 2013 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. +****************************************************************************************************************************** + +/***************************************************************************************************************\ +* Purpose : Arduino Source code for Sensor based on Atmel ATTiny85, running on 8MHz +* Version : R109 - DS18B20 and BH1750 and Vcc test +* Date : 20140502 +* +* This code turns an Atmel ATTiny85 chip into a Sensor using the TheoV2 protocol. +* This code is not of any use without running a Unit within RF range to receive sensor data. +\***************************************************************************************************************/ + +#define SENSOR_TYPE 1 // 1 = DS18B20 and BH1750 sensor + +// Uncomment for test purpose +//#define THEO_TEST + +//***************************************************************************** + +#ifdef THEO_TEST + #define CHANNEL 0 // 0 - 7, 0 discard by plugin + #define SEND_DELAY 2 // Send Delay in multiples of 4 seconds, so 2 = 2x4=8 seconds + #define VCC_LOOP 2 +#else + #define CHANNEL 1 // 0 - 7, 0 discard by plugin + #define SEND_DELAY 30 // Send Delay in multiples of 4 seconds, so 70 = 70x4=280 seconds + #define VCC_LOOP 24 // Send Vcc once every hour +#endif + +#define VREF_35 10885 // Measured value for Vref at 3.5V Vcc * 10 (Chip dependent) +#define BATT_LOW 30 // 3.0V Battery low warning voltage * 10 (Functionality dependent) + +//***************************************************************************** + +#define DALLAS_PIN 1 // data to DS18B20, fysieke pin 6 on ATTiny85 +#define BH1750_ADDRESS 0x23 // i2c address BH1750 + +#define RF_TransmitDataPin 4 // data to RF Transmitter, fysieke pin 3 on ATTiny85 + +// ATMEL ATTINY85 +// AI=Analog Input +// o-\/-+ +// reset 1| |8 VCC +// Pin 3 (AI 3) PB3 2| |7 PB2 (AI 1) Pin 2 - SCL +// Pin 4 (AI 2) PB4 3| |6 PB1 PWM Pin 1 - PCINT1 +// GND 4| |5 PB0 PWM Pin 0 - SDA +// +----+ + +// Used by DS18B20 +#include // http://www.pjrc.com/teensy/arduino_libraries/OneWire.zip + +// Used by BH1750 +// Prepare library TinyWireM for 8MHz by editing the following files: +// 1) file USI_TWI_Master.cpp define F_CPU from 1000000UL to 8000000UL +// 2) file USI_TWI_Master.h define SYS_CLK from 1000.0 to 8000.0 +#include // http://playground.arduino.cc/Code/USIi2c + +byte VccTest; +byte Voltage; + +//***************************************************************************** +// Setup stuff +//***************************************************************************** +void setup() +{ + VccTest = VCC_LOOP; + + pinMode(RF_TransmitDataPin,OUTPUT); + + TinyWireM.begin(); + + Watchdog_setup(8); // Setup watchdog to notify us every 4 seconds +} + +//***************************************************************************** +// Main loop +//***************************************************************************** +void loop() +{ + int payload1 = 0; + int payload2 = 0; + + VccTest++; + + if (GetPayload(payload1, payload2) == 0) + SendData(payload1, payload2); + + Watchdog_sleep(SEND_DELAY + CHANNEL); // Go to deep sleep mode for some time +} + +//***************************************************************************** +// Sleep stuff +//***************************************************************************** +#include +#include + +void Watchdog_setup(int ii) +{ + // 0=16ms, 1=32ms, 2=64ms, 3=125ms, 4=250ms, 5=500ms, 6=1s, 7=2s, 8=4s, 9=8s + // The prescale value is held in bits 5,2,1,0 + // This block moves ii into these bits + byte bb; + if (ii > 9 ) ii=9; + bb=ii & 7; + if (ii > 7) bb|= (1<<5); + bb|= (1<= VCC_LOOP) // Do not run the Vcc test too often to save Battery power + { + VccTest = 0; + Voltage = ReadVcc(); + if (Voltage <= BATT_LOW) + Voltage |= 0x80; + } + DataBlock.Voltage = Voltage; + DataBlock.Payload1 = payload1; + DataBlock.Payload2 = payload2; + byte c = 0, *B = (byte*)&DataBlock; // bereken checksum: crc-8 uit bovenstaande bytes in de struct + for (byte x = 1; x < Size; x++) + c +=*(B+x); + DataBlock.Checksum = c; + + pinMode(RF_TransmitDataPin, OUTPUT); + digitalWrite(RF_TransmitDataPin, LOW); // 0 + for (byte y = 0; y < TransmitRepeat; y++) // herhaal verzenden RF code + { + digitalWrite(RF_TransmitDataPin, HIGH); // 1 + delayMicroseconds(RF_PULSE_1 * 4); + digitalWrite(RF_TransmitDataPin, LOW); // 0 + delayMicroseconds(RF_SPACE * 2); + for (byte x = 0; x < Size; x++) + { + for (byte Bit = 0; Bit <= 7; Bit++) + { + digitalWrite(RF_TransmitDataPin, HIGH); // 1 + if ((*(B + x) >> Bit) & 1) + delayMicroseconds(RF_PULSE_1); + else + delayMicroseconds(RF_PULSE_0); + digitalWrite(RF_TransmitDataPin, LOW); // 0 + delayMicroseconds(RF_SPACE); + } + } + delayMicroseconds(RF_PULSE_1 * 10); + } +} + +//***************************************************************************** +// Measure battery voltage using internal bandgap voltage +//***************************************************************************** +byte ReadVcc() +{ + int result; + + bitSet(ADCSRA, ADEN); // switch Analog to Digital converter ON + ADMUX = 0x0C; // use VCC and internal bandgap (ATTiny85) + delayMicroseconds(250); // delay substantially improves accuracy + bitSet(ADCSRA, ADSC); // start conversion + while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC is clear + bitClear(ADCSRA, ADEN); // Switch Analog to Digital converter OFF + result = ADCW; + return result ? VREF_35 / result : 0; // 35 = 3.5V +} + +//***************************************************************************** +// DS18B20 Temperature Sensor and BH1750 light sensor support +//***************************************************************************** +byte GetPayload(int &temperature, int &light) +{ + if (GetDS18B20(temperature) != 0) return 1; + if (GetBH1750(light) != 0) return 1; + return 0; +} + +//***************************************************************************** +// DS18B20 Temperature +//***************************************************************************** +byte GetDS18B20(int &temperature) +{ + byte msb, lsb; + int temp; + + OneWire ds(DALLAS_PIN); // Setup a oneWire instance + ds.reset(); + ds.skip(); + ds.write(0x44); // Start conversion + Watchdog_delay(6); // Wait 750ms. Here 1 second + ds.reset(); // Read DS18B20 + ds.skip(); + ds.write(0xBE); // Read scratchpad + lsb = ds.read(); + msb = ds.read(); + ds.reset(); + temp = (msb<< 8) | lsb; + temperature = ((((6 * temp) + temp / 4) + 5) / 10) * 10; // multiply by (100 * 0.0625) or 6.25 and round to tenth + return 0; +} + +//***************************************************************************** +// BH1750 light +//***************************************************************************** +byte GetBH1750(int &light) +{ + byte msb, lsb; + unsigned int value; + + TinyWireM.beginTransmission(BH1750_ADDRESS); // Setup BH1750 + TinyWireM.send(0x20); // One time high resolution low power + TinyWireM.endTransmission(); + Watchdog_delay(4); // Wait 160-180ms. Here 250ms + TinyWireM.beginTransmission(BH1750_ADDRESS); // Read BH1750 + TinyWireM.requestFrom(BH1750_ADDRESS, 2); + msb = TinyWireM.receive(); + lsb = TinyWireM.receive(); + value = (msb<<8 | lsb) / 1.2; + if (value > 0x7fff) value = 0x7fff; + light = int(value); + return 0; +} diff --git a/tools/theov2_attiny85/TheoV2Sensor2/TheoV2Sensor2.ino b/tools/theov2_attiny85/TheoV2Sensor2/TheoV2Sensor2.ino new file mode 100644 index 000000000..1ab3ecc30 --- /dev/null +++ b/tools/theov2_attiny85/TheoV2Sensor2/TheoV2Sensor2.ino @@ -0,0 +1,286 @@ +/****************************************************************************************************************************\ +* Arduino project "TheoTinySensor" Copyright 2013 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. +****************************************************************************************************************************** + +**************************************************************************************************************** +* Purpose : Arduino Source code for Sensor based on Atmel ATTiny85, running on 8MHz +* Version : R201 - DHT11 or DHT22 and Vcc test +* Date : 20140414 +* 20140507 - R202 - Verwijdering VCC_LOOP +* +* This code turns an Atmel ATTiny85 chip into a Sensor using the TheoV2 protocol. +* This code is not of any use without running a Unit within RF range to receive sensor data. +\***************************************************************************************************************/ + +#define SENSOR_TYPE 2 // 2 = DHT22 or DHT11 sensor +#define DHT22 // DHT22 Temperatuur en luchtvochtigheid +//#define DHT11 // DHT11 Temperatuur en luchtvochtigheid + +// Uncomment for test purpose +//#define THEO_TEST + +//***************************************************************************** + +#ifdef THEO_TEST + #define CHANNEL 0 // 0 - 7, 0 discard by plugin + #define SEND_DELAY 2 // Max Send Delay in multiples of 4.4 seconds, so 2 = 2x4.4=9 seconds +#else + #define CHANNEL 1 // 0 - 7, 0 discard by plugin + #define SEND_DELAY 32 // Max Send Delay in multiples of 4.4 seconds, so 32 = 32x4.4=141 seconds +#endif + +#define VREF_35 10675 // Measured value for Vref at 3.5V Vcc * 10 (Chip dependent) +#define BATT_LOW 33 // 3.3V Battery low warning voltage * 10 (Functionality dependent) + +//***************************************************************************** + +#define DHT_PIN 1 // data to DHT11, fysieke pin 6 on ATTiny85 + +#define RF_TransmitDataPin 4 // data to RF Transmitter, fysieke pin 3 on ATTiny85 + +// ATMEL ATTINY85 +// AI=Analog Input +// o-\/-+ +// reset 1| |8 VCC +// Pin 3 (AI 3) PB3 2| |7 +// Pin 4 (AI 2) PB4 3| |6 PB1 PWM Pin 1 - PCINT1 +// GND 4| |5 +// +----+ + +byte VccTest; +byte Voltage; + +//***************************************************************************** +// Setup stuff +//***************************************************************************** +void setup() +{ + VccTest = 255; + + pinMode(RF_TransmitDataPin,OUTPUT); + + pinMode(DHT_PIN, OUTPUT); + digitalWrite(DHT_PIN, HIGH); // Pull high + delay(3000); + + Watchdog_setup(8); // Setup watchdog to notify us every 4.4 seconds +} + +//***************************************************************************** +// Main loop +//***************************************************************************** +void loop() +{ + int payload1 = 0; + int payload2 = 0; + + VccTest++; + if (VccTest == 0) // Do not run the Vcc test too often to save Battery power + { + Voltage = ReadVcc(); + if (Voltage <= BATT_LOW) + Voltage |= 0x80; + } + + if (GetPayload(payload1, payload2) == 0) + SendData(payload1, payload2); + +// Watchdog_sleep(SEND_DELAY + CHANNEL); // Go to deep sleep mode for some time + Watchdog_sleep(SEND_DELAY - SENSOR_TYPE - CHANNEL); // Go to deep sleep mode for some time but not longer than 150 sec +} + +//***************************************************************************** +// Sleep stuff +//***************************************************************************** +#include +#include + +void Watchdog_setup(int ii) +{ + // 0=16ms, 1=32ms, 2=64ms, 3=125ms, 4=250ms, 5=500ms, 6=1s, 7=2s, 8=4s, 9=8s + // The prescale value is held in bits 5,2,1,0 + // This block moves ii into these bits + byte bb; + if (ii > 9 ) ii=9; + bb=ii & 7; + if (ii > 7) bb|= (1<<5); + bb|= (1<> Bit) & 1) + delayMicroseconds(RF_PULSE_1); + else + delayMicroseconds(RF_PULSE_0); + digitalWrite(RF_TransmitDataPin, LOW); // 0 + delayMicroseconds(RF_SPACE); + } + } + delayMicroseconds(RF_PULSE_1 * 10); + } +} + +//***************************************************************************** +// Measure battery voltage using internal bandgap voltage +//***************************************************************************** +byte ReadVcc() +{ + int result; + + bitSet(ADCSRA, ADEN); // switch Analog to Digital converter ON + ADMUX = 0x0C; // use VCC and internal bandgap (ATTiny85) + delayMicroseconds(250); // delay substantially improves accuracy + bitSet(ADCSRA, ADSC); // start conversion + while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC is clear + bitClear(ADCSRA, ADEN); // Switch Analog to Digital converter OFF + result = ADCW; + return result ? VREF_35 / result : 0; // 35 = 3.5V +} + +//***************************************************************************** +// DHT11 or DHT22 Temperature and humidity sensor support +//***************************************************************************** +byte GetPayload(int &temperature, int &humidity) +{ + return GetDHT(temperature, humidity); +} + +//***************************************************************************** +// DHT11 or DHT22 Temperature and humidity +// http://forums.adafruit.com/viewtopic.php?f=25&t=43933 +// https://github.com/markruys/arduino-DHT +//***************************************************************************** +byte GetDHT(int &temperature, int &humidity) +{ + unsigned long startTime = millis(); + word rawHumidity; + word rawTemperature; + word data; + + digitalWrite(DHT_PIN, LOW); // Send start signal + pinMode(DHT_PIN, OUTPUT); +#ifdef DHT22 + delayMicroseconds(800); +#else + delay(18); +#endif + pinMode(DHT_PIN, INPUT); + digitalWrite(DHT_PIN, HIGH); // Switch bus to receive data + // We're going to read 83 edges: + // - First a FALLING, RISING, and FALLING edge for the start bit + // - Then 40 bits: RISING and then a FALLING edge per bit + // To keep our code simple, we accept any HIGH or LOW reading if it's max 85 usecs long + for (int8_t i = -3 ; i < 2 * 40; i++) + { + byte age; + + startTime = micros(); + do + { + age = (unsigned long)(micros() - startTime); + if (age > 90) return 1; + } + while (digitalRead(DHT_PIN) == (i & 1) ? HIGH : LOW); + if (i >= 0 && (i & 1)) + { + data <<= 1; // Now we are being fed our 40 bits + if (age > 30) data |= 1; // A zero max 30 usecs, a one at least 68 usecs. We got a one + } + switch (i) + { + case 31: + rawHumidity = data; + break; + case 63: + rawTemperature = data; + data = 0; + break; + } + } + // Verify checksum + if ((byte)(((byte)rawHumidity) + (rawHumidity >> 8) + ((byte)rawTemperature) + (rawTemperature >> 8)) != data) + return 2; +#ifdef DHT22 + int t = (rawTemperature & 0x7fff) * 10; + temperature = rawTemperature & 0x8000 ? - t : t; +// humidity = (rawHumidity / 10) * 100; // round to whole + humidity = rawHumidity * 10; +#else + humidity = (rawHumidity >> 8) * 100; + temperature = (rawTemperature >> 8) * 100; +#endif + return 0; +} + \ No newline at end of file diff --git a/tools/theov2_attiny85/info.txt b/tools/theov2_attiny85/info.txt new file mode 100644 index 000000000..fc93b2057 --- /dev/null +++ b/tools/theov2_attiny85/info.txt @@ -0,0 +1,15 @@ +These files provide Arduino code for ATTiny85 battery powered sensor hardware. + +Tasmota can receive and decode them when defines USE_RF_SENSOR and USE_THEO_V2 are enabled + + +TheoV2Sensor1 - Light and Temperature +Uses BH1750 and DS18B20 +Uses 1 x 3.6V Lithium battery lasting at least 3 years +See https://sidweb.nl/cms3/en/projects/mcs51/attiny85-lichtsensor + + +TheoV2Sensor2 - Temperature and Humidity +Uses DHT22 +Uses 3 x AAA battery lasting at least 3 years +See https://sidweb.nl/cms3/en/projects/mcs51/vocht-en-tempsensor \ No newline at end of file From d8c383eb10e4fce90095118a34171a633a4e02b2 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Thu, 13 Dec 2018 17:12:03 +0100 Subject: [PATCH 0707/2222] Add LwIP 2 no features (Low Flash) --- platformio.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platformio.ini b/platformio.ini index 39440fa66..2d89a6daf 100644 --- a/platformio.ini +++ b/platformio.ini @@ -74,6 +74,10 @@ build_flags = ; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY ; lwIP 2 - Higher Bandwitdh -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwitdh no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; lwIP 2 - Higher Bandwitdh Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH ; VTABLES in Flash (default) -DVTABLES_IN_FLASH ; VTABLES in Heap From dcbf5a8c94dd1ec32eb6717ecfdf0dd2664d5dbb Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 13 Dec 2018 23:04:48 +0000 Subject: [PATCH 0708/2222] Fix ArduinoOTA for Core 2.5.0 (fix is backwards compatible) https://github.com/arendst/Sonoff-Tasmota/issues/4619 --- sonoff/sonoff.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 8e4006ca1..362b48ced 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2215,7 +2215,7 @@ uint16_t arduino_ota_progress_dot_count = 0; void ArduinoOTAInit(void) { ArduinoOTA.setPort(8266); - ArduinoOTA.setHostname(Settings.hostname); + ArduinoOTA.setHostname(my_hostname); if (Settings.web_password[0] !=0) ArduinoOTA.setPassword(Settings.web_password); ArduinoOTA.onStart([]() @@ -2799,6 +2799,7 @@ void loop(void) if (!serial_local) SerialInput(); #ifdef USE_ARDUINO_OTA + MDNS.update(); ArduinoOTA.handle(); // Once OTA is triggered, only handle that and dont do other stuff. (otherwise it fails) while (arduino_ota_triggered) ArduinoOTA.handle(); From 5f560bae13054057d87d63af45b243b6d0c0e6a2 Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Fri, 14 Dec 2018 01:10:10 +0200 Subject: [PATCH 0709/2222] Fix ArduinoOTA for Core 2.5.0 Fix ArduinoOTA for Core 2.5.0 --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0f601ec0b..39f5fc4b7 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,6 +4,7 @@ * Add support for SDM220 (#3610) * Add support for Manzoku Power Strip (#4590) * Enhance support for MPU6050 using DMP (#4581) + * Fix ArduinoOTA for Core 2.5.0 (fix is backwards compatible) (#4620) * * 6.3.0.16 20181201 * Add support for iFan02 Fanspeed in Domoticz using a selector (#4517) From 3795667f36ac339b013b4039263830889968d685 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 14 Dec 2018 23:57:12 -0300 Subject: [PATCH 0710/2222] Fix HomeAssistant Temp Sensor AutoDiscovery https://github.com/arendst/Sonoff-Tasmota/issues/4627 --- sonoff/xdrv_12_home_assistant.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 20c2a9038..ad9e71a4c 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -458,7 +458,7 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) } snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_SHORT:HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); - if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { + if (!strcmp_P(subsensortype, PSTR(D_JSON_TEMPERATURE))) { snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_TEMP_SHORT:HASS_DISCOVER_SENSOR_TEMP, mqtt_data, TempUnit(), sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { From cccaf445598e489673849a9388ad619eabfcc3ab Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Sat, 15 Dec 2018 10:45:05 +0200 Subject: [PATCH 0711/2222] New 2.5.0-2 toolchain does not like uncast bitwise The new toolchain (2.5.0-2) used from core 2.5.0 does not want bitwise operations to be performed on non-integer variables so we cast the double used in send_2byte_float() to a (long) as it should be. --- lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp b/lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp index 23ee319e6..ae5e9fabc 100644 --- a/lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp +++ b/lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp @@ -133,7 +133,7 @@ void ESPKNXIP::send_2byte_float(address_t const &receiver, knx_command_type_t ct ++e; for (; v > 2047.0f; v /= 2) ++e; - long m = round(v) & 0x7FF; + long m = (long)round(v) & 0x7FF; short msb = (short) (e << 3 | m >> 8); if (val < 0.0f) msb |= 0x80; From b16c14cecf5503989041c547e2b57344aac7afb3 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Sat, 15 Dec 2018 10:56:35 +0200 Subject: [PATCH 0712/2222] Fix NewPing-1.9.1 library.properties Fix NewPing-1.9.1 library.properties to avoid compiler warning about possibly not supporting ESP8266 whereas we know now that it does. This causes the compiler warning (which may alarm some users unnecessarily) that NewPing claims to run on avr and stm32. --- lib/NewPing-1.9.1/library.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/NewPing-1.9.1/library.properties b/lib/NewPing-1.9.1/library.properties index 2accb6c86..0719a1b4c 100644 --- a/lib/NewPing-1.9.1/library.properties +++ b/lib/NewPing-1.9.1/library.properties @@ -6,5 +6,5 @@ sentence=A library that makes working with ultrasonic sensors easy. paragraph=When I first received an ultrasonic sensor I was not happy with how poorly it performed. I soon realized the problem was not the sensor, it was the available ping and ultrasonic libraries causing the problem. The NewPing library totally fixes these problems, adds many new features, and breathes new life into these very affordable distance sensors. category=Sensors url=https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home -architectures=avr,arm -includes=NewPing.h \ No newline at end of file +architectures=avr,arm,esp8266 +includes=NewPing.h From a7bc97a5afd36c855774c9608deac6b01f61afbf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 15 Dec 2018 17:02:05 +0100 Subject: [PATCH 0713/2222] Prep for release Prep for release --- sonoff/my_user_config.h | 2 +- sonoff/sonoff_post.h | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 32821365f..bb680c8ad 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -365,7 +365,7 @@ #define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer #define TUYA_DIMMER_ID 0 // Default dimmer Id #define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) -#define USE_PS_16_DZ // ADD support for PS-16-DZ Dimmer +#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index b6fc2c77f..f8798e454 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -132,6 +132,9 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (+3k code) #define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code) #define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram) +#define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +// #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) + #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code) #endif // USE_SENSORS /*********************************************************************************************\ @@ -153,6 +156,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef MQTT_LIBRARY_TYPE #define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library #undef USE_ARDUINO_OTA // Disable support for Arduino OTA +//#undef USE_DOMOTICZ // Disable Domoticz +#undef USE_HOME_ASSISTANT // Disable Home Assistant #undef USE_KNX // Disable KNX IP Protocol Support #undef USE_CUSTOM // Disable Custom features #undef USE_TIMERS // Disable support for up to 16 timers @@ -168,11 +173,14 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_PZEM004T // Disable PZEM004T energy sensor #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor +#undef USE_MCP39F501 // Disable support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) #undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter #undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop #undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer +#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) +#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer #undef USE_IR_REMOTE // Disable IR remote commands using library IRremoteESP8266 and ArduinoJson #undef USE_IR_RECEIVE // Disable support for IR receiver #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller @@ -182,6 +190,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch +#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // USE_CLASSIC @@ -214,6 +223,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) #undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) +#undef USE_DOMOTICZ // Disable Domoticz +#undef USE_HOME_ASSISTANT // Disable Home Assistant #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) #define USE_DISPLAY // Add I2C Display Support (+2k code) @@ -224,6 +235,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_SPI // Hardware SPI using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK) in addition to two user selectable GPIOs(CS and DC) #define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display (+19k code) + #define USE_DISPLAY_EPAPER_29 // [DisplayModel 5] Enable e-paper 2.9 inch display (+19k code) #undef USE_ARILUX_RF // Remove support for Arilux RF remote controller (-0k8 code, 252 iram (non 2.3.0)) #undef USE_RF_FLASH // Remove support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (-3k code) @@ -283,6 +295,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter #undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop //#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer +#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) +#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer #undef USE_PZEM004T // Disable PZEM004T energy sensor #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor @@ -296,6 +310,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch +#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // USE_BASIC @@ -342,6 +357,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter #undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop #undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer +#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) +#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer #undef USE_PZEM004T // Disable PZEM004T energy sensor #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor @@ -355,6 +372,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch +#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // BE_MINIMAL From f494c488a4efa7f28f82385870d051bdea2cc82f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 16 Dec 2018 13:04:46 +0100 Subject: [PATCH 0714/2222] Prep for release Prep for release --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 2d89a6daf..309b1e12e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -33,7 +33,7 @@ env_default = sonoff ;env_default = sonoff-PL ;env_default = sonoff-PT ;env_default = sonoff-RU -;env_default = sonoff-SV +;env_default = sonoff-SE ;env_default = sonoff-TR ;env_default = sonoff-TW ;env_default = sonoff-UK @@ -423,7 +423,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-SV] +[env:sonoff-SE] platform = ${common.platform} framework = ${common.framework} board = ${common.board} From 44b45e15b37fa6982bb3f552c7bc7318b03b9de0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 16 Dec 2018 16:14:56 +0100 Subject: [PATCH 0715/2222] Prep for merge --- sonoff/xdrv_99_debug.ino | 540 --------------------------------------- sonoff/zzzz_debug.ino | 309 ---------------------- 2 files changed, 849 deletions(-) delete mode 100644 sonoff/xdrv_99_debug.ino delete mode 100644 sonoff/zzzz_debug.ino diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_99_debug.ino deleted file mode 100644 index 30e51121f..000000000 --- a/sonoff/xdrv_99_debug.ino +++ /dev/null @@ -1,540 +0,0 @@ -/* - xdrv_99_debug.ino - debug support for Sonoff-Tasmota - - Copyright (C) 2018 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - 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 . -*/ - -//#define USE_DEBUG_DRIVER - -#ifdef DEBUG_THEO -#ifndef USE_DEBUG_DRIVER -#define USE_DEBUG_DRIVER -#endif // USE_DEBUG_DRIVER -#endif // DEBUG_THEO - -#ifdef USE_DEBUG_DRIVER -/*********************************************************************************************\ - * Virtual debugging support - Part1 - * - * Needs file zzzz_debug.ino due to DEFINE processing -\*********************************************************************************************/ - -#define XDRV_99 99 - -#ifndef CPU_LOAD_CHECK -#define CPU_LOAD_CHECK 1 // Seconds between each CPU_LOAD log -#endif - -/*********************************************************************************************\ - * Debug commands -\*********************************************************************************************/ - -#define D_CMND_CFGDUMP "CfgDump" -#define D_CMND_CFGPOKE "CfgPoke" -#define D_CMND_CFGPEEK "CfgPeek" -#define D_CMND_CFGSHOW "CfgShow" -#define D_CMND_CFGXOR "CfgXor" -#define D_CMND_CPUCHECK "CpuChk" -#define D_CMND_EXCEPTION "Exception" -#define D_CMND_FREEMEM "FreeMem" -#define D_CMND_RTCDUMP "RtcDump" -#define D_CMND_HELP "Help" -#define D_CMND_SETSENSOR "SetSensor" -#define D_CMND_FLASHMODE "FlashMode" - -enum DebugCommands { - CMND_CFGDUMP, CMND_CFGPEEK, CMND_CFGPOKE, CMND_CFGSHOW, CMND_CFGXOR, - CMND_CPUCHECK, CMND_EXCEPTION, CMND_FREEMEM, CMND_RTCDUMP, CMND_SETSENSOR, CMND_FLASHMODE, CMND_HELP }; -const char kDebugCommands[] PROGMEM = - D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" D_CMND_CFGSHOW "|" D_CMND_CFGXOR "|" - D_CMND_CPUCHECK "|" D_CMND_EXCEPTION "|" D_CMND_FREEMEM "|" D_CMND_RTCDUMP "|" D_CMND_SETSENSOR "|" D_CMND_FLASHMODE "|" D_CMND_HELP; - -uint32_t CPU_loops = 0; -uint32_t CPU_last_millis = 0; -uint32_t CPU_last_loop_time = 0; -uint8_t CPU_load_check = 0; -uint8_t CPU_show_freemem = 0; - -/*******************************************************************************************/ - -#ifdef DEBUG_THEO -void ExceptionTest(byte type) -{ -/* -Exception (28): -epc1=0x4000bf64 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000007 depc=0x00000000 - -ctx: cont -sp: 3fff1f30 end: 3fff2840 offset: 01a0 - ->>>stack>>> -3fff20d0: 202c3573 756f7247 2c302070 646e4920 -3fff20e0: 40236a6e 7954202c 45206570 00454358 -3fff20f0: 00000010 00000007 00000000 3fff2180 -3fff2100: 3fff2190 40107bfc 3fff3e4c 3fff22c0 -3fff2110: 40261934 000000f0 3fff22c0 401004d8 -3fff2120: 40238fcf 00000050 3fff2100 4021fc10 -3fff2130: 3fff32bc 4021680c 3ffeade1 4021ff7d -3fff2140: 3fff2190 3fff2180 0000000c 7fffffff -3fff2150: 00000019 00000000 00000000 3fff21c0 -3fff2160: 3fff23f3 3ffe8e08 00000000 4021ffb4 -3fff2170: 3fff2190 3fff2180 0000000c 40201118 -3fff2180: 3fff21c0 0000003c 3ffef840 00000007 -3fff2190: 00000000 00000000 00000000 40201128 -3fff21a0: 3fff23f3 000000f1 3fff23ec 4020fafb -3fff21b0: 3fff23f3 3fff21c0 3fff21d0 3fff23f6 -3fff21c0: 00000000 3fff23fb 4022321b 00000000 - -Exception 28: LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads -Decoding 14 results -0x40236a6e: ets_vsnprintf at ?? line ? -0x40107bfc: vsnprintf at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/libc_replacements.c line 387 -0x40261934: bignum_exptmod at ?? line ? -0x401004d8: malloc at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\umm_malloc/umm_malloc.c line 1664 -0x40238fcf: wifi_station_get_connect_status at ?? line ? -0x4021fc10: operator new[](unsigned int) at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/abi.cpp line 57 -0x4021680c: ESP8266WiFiSTAClass::status() at C:\Data2\Arduino\arduino-1.8.1-esp-2.3.0\portable\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src/ESP8266WiFiSTA.cpp line 569 -0x4021ff7d: vsnprintf_P(char*, unsigned int, char const*, __va_list_tag) 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 -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: MqttDataHandler(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"} -*/ - if (1 == type) { - char svalue[10]; - snprintf_P(svalue, sizeof(svalue), PSTR("%s"), 7); // Exception 28 as number in string (7 in excvaddr) - } -/* -14:50:52 osWatch: FreeRam 25896, rssi 68, last_run 0 -14:51:02 osWatch: FreeRam 25896, rssi 58, last_run 0 -14:51:03 CMND: exception 2 -14:51:12 osWatch: FreeRam 25360, rssi 60, last_run 8771 -14:51:22 osWatch: FreeRam 25360, rssi 62, last_run 18771 -14:51:32 osWatch: FreeRam 25360, rssi 62, last_run 28771 -14:51:42 osWatch: FreeRam 25360, rssi 62, last_run 38771 -14:51:42 osWatch: Warning, loop blocked. Restart now -*/ - if (2 == type) { - while(1) delay(1000); // this will trigger the os watch - } -} - -#endif // DEBUG_THEO - -/*******************************************************************************************/ - -void CpuLoadLoop(void) -{ - CPU_last_loop_time = millis(); - if (CPU_load_check && CPU_last_millis) { - CPU_loops ++; - if ((CPU_last_millis + (CPU_load_check *1000)) <= CPU_last_loop_time) { -#if defined(F_CPU) && (F_CPU == 160000000L) - int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *800) ); - CPU_loops = CPU_loops / CPU_load_check; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(160MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); -#else - int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *400) ); - CPU_loops = CPU_loops / CPU_load_check; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(80MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); -#endif - AddLog(LOG_LEVEL_DEBUG); - CPU_last_millis = CPU_last_loop_time; - CPU_loops = 0; - } - } -} - -/*******************************************************************************************/ - -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) -// All version before core 2.4.2 -// https://github.com/esp8266/Arduino/issues/2557 - -extern "C" { -#include - extern cont_t g_cont; -} - -void DebugFreeMem(void) -{ - register uint32_t *sp asm("a1"); - -// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d, UnmodifiedStack %d (%s)"), -// ESP.getFreeHeap(), 4 * (sp - g_cont.stack), cont_get_free_stack(&g_cont), XdrvMailbox.data); - - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), - ESP.getFreeHeap(), 4 * (sp - g_cont.stack), XdrvMailbox.data); - AddLog(LOG_LEVEL_DEBUG); -} - -#else -// All version from core 2.4.2 -// https://github.com/esp8266/Arduino/pull/5018 -// https://github.com/esp8266/Arduino/pull/4553 - -extern "C" { -#include - extern cont_t* g_pcont; -} - -void DebugFreeMem(void) -{ - register uint32_t *sp asm("a1"); - - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), - ESP.getFreeHeap(), 4 * (sp - g_pcont->stack), XdrvMailbox.data); - AddLog(LOG_LEVEL_DEBUG); -} - -#endif // ARDUINO_ESP8266_RELEASE_2_x_x - -/*******************************************************************************************/ - -void DebugRtcDump(char* parms) -{ - #define CFG_COLS 16 - - uint16_t idx; - uint16_t maxrow; - uint16_t row; - uint16_t col; - char *p; - - // |<--SDK data (256 bytes)-->|<--User data (512 bytes)-->| - // 000 - 0FF: SDK - // 000 - 01B: SDK rst_info - // 100 - 2FF: User - // 280 - 283: Tasmota RtcReboot (Offset 100 (x 4bytes) - sizeof(RTCRBT) (x 4bytes)) - // 290 - 2EB: Tasmota RtcSettings (Offset 100 (x 4bytes)) - - uint8_t buffer[768]; -// ESP.rtcUserMemoryRead(0, (uint32_t*)&buffer, sizeof(buffer)); - system_rtc_mem_read(0, (uint32_t*)&buffer, sizeof(buffer)); - - maxrow = ((sizeof(buffer)+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); - - if (0 == mrow) { // Default only 8 lines - mrow = 8; - } - if (srow > maxrow) { - srow = maxrow - mrow; - } - if (mrow < (maxrow - srow)) { - maxrow = srow + mrow; - } - - for (row = srow; row < maxrow; row++) { - idx = row * CFG_COLS; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); - for (col = 0; col < CFG_COLS; col++) { - if (!(col%4)) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (col = 0; col < CFG_COLS; col++) { -// if (!(col%4)) { -// snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); -// } - 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); - } -} - -/*******************************************************************************************/ - -void DebugCfgDump(char* parms) -{ - #define CFG_COLS 16 - - uint16_t idx; - uint16_t maxrow; - uint16_t row; - uint16_t col; - char *p; - - 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); - - if (0 == mrow) { // Default only 8 lines - mrow = 8; - } - if (srow > maxrow) { - srow = maxrow - mrow; - } - if (mrow < (maxrow - srow)) { - maxrow = srow + mrow; - } - - for (row = srow; row < maxrow; row++) { - idx = row * CFG_COLS; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); - for (col = 0; col < CFG_COLS; col++) { - if (!(col%4)) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (col = 0; col < CFG_COLS; col++) { -// if (!(col%4)) { -// snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); -// } - 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); - delay(1); - } -} - -void DebugCfgPeek(char* parms) -{ - char *p; - - uint16_t address = strtol(parms, &p, 16); - if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; - address = (address >> 2) << 2; - - uint8_t *buffer = (uint8_t *) &Settings; - uint8_t data8 = buffer[address]; - uint16_t data16 = (buffer[address +1] << 8) + buffer[address]; - uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + data16; - - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), address); - for (byte i = 0; i < 4; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[address +i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (byte i = 0; i < 4; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[address +i] > 0x20) && (buffer[address +i] < 0x7F)) ? (char)buffer[address +i] : ' '); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s| 0x%02X (%d), 0x%04X (%d), 0x%0LX (%lu)"), log_data, data8, data8, data16, data16, data32, data32); - AddLog(LOG_LEVEL_INFO); -} - -void DebugCfgPoke(char* parms) -{ - char *p; - - uint16_t address = strtol(parms, &p, 16); - if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; - address = (address >> 2) << 2; - - uint32_t data = strtol(p, &p, 16); - - uint8_t *buffer = (uint8_t *) &Settings; - uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; - - uint8_t *nbuffer = (uint8_t *) &data; - for (byte i = 0; i < 4; i++) { buffer[address +i] = nbuffer[+i]; } - - uint32_t ndata32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; - - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: 0x%0LX (%lu) poked to 0x%0LX (%lu)"), address, data32, data32, ndata32, ndata32); - AddLog(LOG_LEVEL_INFO); -} - -void DebugCfgShow(uint8_t more) -{ - uint8_t *SetAddr; - SetAddr = (uint8_t *)&Settings; - - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: Hostname (%d) [%s]"), (uint8_t *)&Settings.hostname - SetAddr, sizeof(Settings.hostname)-1, Settings.hostname); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: SSids (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_ssid - SetAddr, sizeof(Settings.sta_ssid[0])-1, Settings.sta_ssid[0], Settings.sta_ssid[1]); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: Friendlynames (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.friendlyname - SetAddr, sizeof(Settings.friendlyname[0])-1, Settings.friendlyname[0], Settings.friendlyname[1], Settings.friendlyname[2], Settings.friendlyname[3]); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: OTA Url (%d) [%s]"), (uint8_t *)&Settings.ota_url - SetAddr, sizeof(Settings.ota_url)-1, Settings.ota_url); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: StateText (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.state_text - SetAddr, sizeof(Settings.state_text[0])-1, Settings.state_text[0], Settings.state_text[1], Settings.state_text[2], Settings.state_text[3]); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: Syslog Host (%d) [%s]"), (uint8_t *)&Settings.syslog_host - SetAddr, sizeof(Settings.syslog_host)-1, Settings.syslog_host); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: NTP Servers (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.ntp_server - SetAddr, sizeof(Settings.ntp_server[0])-1, Settings.ntp_server[0], Settings.ntp_server[1], Settings.ntp_server[2]); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Host (%d) [%s]"), (uint8_t *)&Settings.mqtt_host - SetAddr, sizeof(Settings.mqtt_host)-1, Settings.mqtt_host); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Client (%d) [%s]"), (uint8_t *)&Settings.mqtt_client - SetAddr, sizeof(Settings.mqtt_client)-1, Settings.mqtt_client); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT User (%d) [%s]"), (uint8_t *)&Settings.mqtt_user - SetAddr, sizeof(Settings.mqtt_user)-1, Settings.mqtt_user); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT FullTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_fulltopic - SetAddr, sizeof(Settings.mqtt_fulltopic)-1, Settings.mqtt_fulltopic); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Topic (%d) [%s]"), (uint8_t *)&Settings.mqtt_topic - SetAddr, sizeof(Settings.mqtt_topic)-1, Settings.mqtt_topic); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT GroupTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_grptopic - SetAddr, sizeof(Settings.mqtt_grptopic)-1, Settings.mqtt_grptopic); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT ButtonTopic (%d) [%s]"), (uint8_t *)&Settings.button_topic - SetAddr, sizeof(Settings.button_topic)-1, Settings.button_topic); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT SwitchTopic (%d) [%s]"), (uint8_t *)&Settings.switch_topic - SetAddr, sizeof(Settings.switch_topic)-1, Settings.switch_topic); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Prefixes (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.mqtt_prefix - SetAddr, sizeof(Settings.mqtt_prefix[0])-1, Settings.mqtt_prefix[0], Settings.mqtt_prefix[1], Settings.mqtt_prefix[2]); - AddLog(LOG_LEVEL_INFO); - if (17 == more) { - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: AP Passwords (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_pwd - SetAddr, sizeof(Settings.sta_pwd[0])-1, Settings.sta_pwd[0], Settings.sta_pwd[1]); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Password (%d) [%s]"), (uint8_t *)&Settings.mqtt_pwd - SetAddr, sizeof(Settings.mqtt_pwd)-1, Settings.mqtt_pwd); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: Web Password (%d) [%s]"), (uint8_t *)&Settings.web_password - SetAddr, sizeof(Settings.web_password)-1, Settings.web_password); - AddLog(LOG_LEVEL_INFO); - } -} - -void SetFlashMode(uint8_t mode) -{ - uint8_t *_buffer; - uint32_t address; - - address = 0; - _buffer = new uint8_t[FLASH_SECTOR_SIZE]; - - if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) { - if (_buffer[2] != mode) { // DOUT - _buffer[2] = mode; - if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); - } - } - delete[] _buffer; -} - -/*******************************************************************************************/ - -boolean DebugCommand(void) -{ - char command[CMDSZ]; - boolean serviced = true; - - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kDebugCommands); - if (-1 == command_code) { - serviced = false; // Unknown command - } - else if (CMND_HELP == command_code) { - snprintf_P(log_data, sizeof(log_data), kDebugCommands); - AddLog(LOG_LEVEL_INFO); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - } - else if (CMND_RTCDUMP == command_code) { - DebugRtcDump(XdrvMailbox.data); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - } - else if (CMND_CFGDUMP == command_code) { - DebugCfgDump(XdrvMailbox.data); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - } - else if (CMND_CFGPEEK == command_code) { - DebugCfgPeek(XdrvMailbox.data); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - } - else if (CMND_CFGPOKE == command_code) { - DebugCfgPoke(XdrvMailbox.data); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - } - else if (CMND_CFGSHOW == command_code) { - DebugCfgShow(XdrvMailbox.payload); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - } -#ifdef USE_WEBSERVER - else if (CMND_CFGXOR == command_code) { - if (XdrvMailbox.data_len > 0) { - config_xor_on_set = XdrvMailbox.payload; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, config_xor_on_set); - } -#endif // USE_WEBSERVER -#ifdef DEBUG_THEO - else if (CMND_EXCEPTION == command_code) { - if (XdrvMailbox.data_len > 0) ExceptionTest(XdrvMailbox.payload); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - } -#endif // DEBUG_THEO - else if (CMND_CPUCHECK == command_code) { - if (XdrvMailbox.data_len > 0) { - CPU_load_check = XdrvMailbox.payload; - CPU_last_millis = CPU_last_loop_time; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, CPU_load_check); - } - else if (CMND_FREEMEM == command_code) { - if (XdrvMailbox.data_len > 0) { - CPU_show_freemem = XdrvMailbox.payload; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, CPU_show_freemem); - } - else if ((CMND_SETSENSOR == command_code) && (XdrvMailbox.index < MAX_XSNS_DRIVERS)) { - if ((XdrvMailbox.payload >= 0) && XsnsPresent(XdrvMailbox.index)) { - bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); - if (1 == XdrvMailbox.payload) { restart_flag = 2; } // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, XsnsGetSensors().c_str()); - } - else if (CMND_FLASHMODE == command_code) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - SetFlashMode(XdrvMailbox.payload); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, ESP.getFlashChipMode()); - } - else serviced = false; // Unknown command - - return serviced; -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -boolean Xdrv99(byte function) -{ - boolean result = false; - - switch (function) { - case FUNC_PRE_INIT: - CPU_last_millis = millis(); - break; - case FUNC_LOOP: - CpuLoadLoop(); - break; - case FUNC_COMMAND: - result = DebugCommand(); - break; - case FUNC_FREE_MEM: - if (CPU_show_freemem) { DebugFreeMem(); } - break; - } - return result; -} - -#endif // USE_DEBUG_DRIVER \ No newline at end of file diff --git a/sonoff/zzzz_debug.ino b/sonoff/zzzz_debug.ino deleted file mode 100644 index 3d159b922..000000000 --- a/sonoff/zzzz_debug.ino +++ /dev/null @@ -1,309 +0,0 @@ -/* - zzzz_debug.ino - debug support for Sonoff-Tasmota - - Copyright (C) 2018 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - 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_DEBUG_DRIVER -/*********************************************************************************************\ - * Virtual debugging support - Part 2 - * - * Needs to be the last alphabetical file due to DEFINE compile order -\*********************************************************************************************/ - -/*********************************************************************************************\ - * Xsns available list -\*********************************************************************************************/ - -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kXsnsList[] PROGMEM = { -#else -const uint8_t kXsnsList[] = { -#endif - -#ifdef XSNS_01 - XSNS_01, -#endif - -#ifdef XSNS_02 - XSNS_02, -#endif - -#ifdef XSNS_03 - XSNS_03, -#endif - -#ifdef XSNS_04 - XSNS_04, -#endif - -#ifdef XSNS_05 - XSNS_05, -#endif - -#ifdef XSNS_06 - XSNS_06, -#endif - -#ifdef XSNS_07 - XSNS_07, -#endif - -#ifdef XSNS_08 - XSNS_08, -#endif - -#ifdef XSNS_09 - XSNS_09, -#endif - -#ifdef XSNS_10 - XSNS_10, -#endif - -#ifdef XSNS_11 - XSNS_11, -#endif - -#ifdef XSNS_12 - XSNS_12, -#endif - -#ifdef XSNS_13 - XSNS_13, -#endif - -#ifdef XSNS_14 - XSNS_14, -#endif - -#ifdef XSNS_15 - XSNS_15, -#endif - -#ifdef XSNS_16 - XSNS_16, -#endif - -#ifdef XSNS_17 - XSNS_17, -#endif - -#ifdef XSNS_18 - XSNS_18, -#endif - -#ifdef XSNS_19 - XSNS_19, -#endif - -#ifdef XSNS_20 - XSNS_20, -#endif - -#ifdef XSNS_21 - XSNS_21, -#endif - -#ifdef XSNS_22 - XSNS_22, -#endif - -#ifdef XSNS_23 - XSNS_23, -#endif - -#ifdef XSNS_24 - XSNS_24, -#endif - -#ifdef XSNS_25 - XSNS_25, -#endif - -#ifdef XSNS_26 - XSNS_26, -#endif - -#ifdef XSNS_27 - XSNS_27, -#endif - -#ifdef XSNS_28 - XSNS_28, -#endif - -#ifdef XSNS_29 - XSNS_29, -#endif - -#ifdef XSNS_30 - XSNS_30, -#endif - -#ifdef XSNS_31 - XSNS_31, -#endif - -#ifdef XSNS_32 - XSNS_32, -#endif - -#ifdef XSNS_33 - XSNS_33, -#endif - -#ifdef XSNS_34 - XSNS_34, -#endif - -#ifdef XSNS_35 - XSNS_35, -#endif - -#ifdef XSNS_36 - XSNS_36, -#endif - -#ifdef XSNS_37 - XSNS_37, -#endif - -#ifdef XSNS_38 - XSNS_38, -#endif - -#ifdef XSNS_39 - XSNS_39, -#endif - -#ifdef XSNS_40 - XSNS_40, -#endif - -#ifdef XSNS_41 - XSNS_41, -#endif - -#ifdef XSNS_42 - XSNS_42, -#endif - -#ifdef XSNS_43 - XSNS_43, -#endif - -#ifdef XSNS_44 - XSNS_44, -#endif - -#ifdef XSNS_45 - XSNS_45, -#endif - -#ifdef XSNS_46 - XSNS_46, -#endif - -#ifdef XSNS_47 - XSNS_47, -#endif - -#ifdef XSNS_48 - XSNS_48, -#endif - -#ifdef XSNS_49 - XSNS_49, -#endif - -#ifdef XSNS_50 - XSNS_50, -#endif - -// Optional user defined sensors in range 91 - 99 - -#ifdef XSNS_91 - XSNS_91, -#endif - -#ifdef XSNS_92 - XSNS_92, -#endif - -#ifdef XSNS_93 - XSNS_93, -#endif - -#ifdef XSNS_94 - XSNS_94, -#endif - -#ifdef XSNS_95 - XSNS_95 -#endif -}; - -/*********************************************************************************************\ - * Xsns sensor control -\*********************************************************************************************/ - -boolean XsnsEnabled(byte sns_index) -{ - if (sns_index < sizeof(kXsnsList)) { -#ifdef XFUNC_PTR_IN_ROM - uint8_t index = pgm_read_byte(kXsnsList + sns_index); -#else - uint8_t index = kXsnsList[sns_index]; -#endif - return bitRead(Settings.sensors[index / 32], index % 32); - } - return 1; -} - -boolean XsnsPresent(byte sns_index) -{ - uint8_t index = 0; - for (byte i = 0; i < sizeof(kXsnsList); i++) { -#ifdef XFUNC_PTR_IN_ROM - index = pgm_read_byte(kXsnsList + i); -#else - index = kXsnsList[i]; -#endif - if (index == sns_index) { return true; } - } - return false; -} - -String XsnsGetSensors(void) -{ - char state[2] = { 0 }; - - String data = F("["); - for (byte i = 0; i < MAX_XSNS_DRIVERS; i++) { - if (i && (!(i % 16))) { data += F(","); } - if (!(i % 16)) { data += F("\""); } - state[0] = '-'; - if (XsnsPresent(i)) { state[0] = bitRead(Settings.sensors[i / 32], i % 32) ? '1' : '0'; } - data += String(state); - if (i && (!((i +1) % 16))) { data += F("\""); } - } - data += F("]"); - - return data; -} - -#endif // USE_DEBUG_DRIVER \ No newline at end of file From 8792ea48a9dd9b70100e0f824087a5797ad31c94 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 16 Dec 2018 16:26:40 +0100 Subject: [PATCH 0716/2222] 6.4.0.1 New dev release --- Doxyfile | 2489 ++++++++++++++++++++++++++++++++++++++ sonoff/_changelog.ino | 5 +- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_99_debug.ino | 540 +++++++++ sonoff/zzzz_debug.ino | 309 +++++ updateDocs.sh | 9 + 6 files changed, 3352 insertions(+), 2 deletions(-) create mode 100644 Doxyfile create mode 100644 sonoff/xdrv_99_debug.ino create mode 100644 sonoff/zzzz_debug.ino create mode 100644 updateDocs.sh diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 000000000..2df4d1c2c --- /dev/null +++ b/Doxyfile @@ -0,0 +1,2489 @@ +# Doxyfile 1.8.14 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = Sonoff-Tasmota + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "Provide ESP8266 based itead Sonoff with Web, MQTT and OTA firmware using Arduino IDE or PlatformIO" + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = ./ + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = YES + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = NO + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. + +ALIASES = "abstract=" \ + "access=" \ + "subpackage=" \ + "license=copyright" \ + "description=" \ + "see=" + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = ino=C + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 0. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = NO + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = YES + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = sonoff \ + lib + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.ino \ + *.qsf + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = */.git* + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .xhtml + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/ + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , / const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = -#if defined(USE_MHZ19) || defined(USE_SENSEAIR) +#if defined(USE_MHZ19) || defined(USE_SENSEAIR) || defined(USE_AZ7798) const char HTTP_SNS_CO2[] PROGMEM = "%s{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = #endif // USE_WEBSERVER diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 621a0fdb7..66793ea7e 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 461de3a4d..45f55af6a 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 293de0830..23d8de9ed 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 2148baf42..a8b48ed35 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 70825c5e3..2ea9c249a 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 011c7a248..435f230ad 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 642b4686d..0638b408a 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 7dc8585db..cd1b0e92e 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 707bb24ec..244d55776 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index d2e277a8c..a6d0d693c 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 3383228ed..b3bf10989 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 0019c8d53..d80826751 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index e8e536606..7add978f0 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 58a39fff0..9869762b8 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 85813373a..d0a3f6933 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index a01fa1b3e..f46372426 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Senzor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 4ae68e78c..f36162a4b 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 43acbaa77..06d82b9cb 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index a924a6cf4..509c90753 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index dfd5662e0..05bedca81 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index abc3df93d..2780181aa 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -538,6 +538,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index cbc7a7790..7e9f16a36 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -283,7 +283,7 @@ // #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors // -- I2C sensors --------------------------------- -#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) +//#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) #ifdef USE_I2C #define USE_SHT // Enable SHT1X sensor (+1k4 code) @@ -348,12 +348,12 @@ #endif // USE_SPI // -- Serial sensors ------------------------------ -#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) -#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) +//#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) +//#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) #define CO2_LOW 800 // Below this CO2 value show green light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) -#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) -#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) +//#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) +//#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) #define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) //#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) @@ -363,35 +363,35 @@ #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) //#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) -#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer +//#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer #define TUYA_DIMMER_ID 0 // Default dimmer Id -#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) -#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer - +//#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) +//#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer +#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code) // Power monitoring sensors ----------------------- -#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) -#define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) -#define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) -#define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) +//#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) +//#define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) +//#define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) +//#define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) // -- Low level interface devices ----------------- -#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k3 code, 0k3 mem, 48 iram) +//#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k3 code, 0k3 mem, 48 iram) // #define USE_IR_HVAC // Support for HVAC (Toshiba, Mitsubishi and LG) system using IR (+3k5 code) - #define USE_IR_RECEIVE // Support for IR receiver (+7k2 code, 264 iram) +// #define USE_IR_RECEIVE // Support for IR receiver (+7k2 code, 264 iram) #define IR_RCV_BUFFER_SIZE 100 // Max number of packets allowed in capture buffer (default 100 (*2 bytes ram)) #define IR_RCV_TIMEOUT 15 // Number of milli-Seconds of no-more-data before we consider a message ended (default 15) #define IR_RCV_MIN_UNKNOWN_SIZE 6 // Set the smallest sized "UNKNOWN" message packets we actually care about (default 6) -#define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // - #define USE_WS2812_CTYPE NEO_GRB // WS2812 Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW) +//#define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // +// #define USE_WS2812_CTYPE NEO_GRB // WS2812 Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW) // #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial RXD) (+1k mem). When USE_WS2812_DMA is enabled expect Exceptions on Pow -#define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) +//#define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) -#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) +//#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) //#define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code) -#define USE_HX711 // Add support for HX711 load cell (+1k5 code) +//#define USE_HX711 // Add support for HX711 load cell (+1k5 code) // #define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) #define USE_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (+3k code) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index f8798e454..38ae7e223 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -135,6 +135,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code) +#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger #endif // USE_SENSORS /*********************************************************************************************\ @@ -193,6 +194,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code +#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger #endif // USE_CLASSIC /*********************************************************************************************\ @@ -313,6 +315,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code +#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger #endif // USE_BASIC /*********************************************************************************************\ @@ -375,6 +378,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code +#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger #endif // BE_MINIMAL /*********************************************************************************************\ diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 91eec21c7..48af9cf4b 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -141,6 +141,8 @@ enum UserSelectablePins { GPIO_SSPI_CS, // Software SPI Chip Select GPIO_SSPI_DC, // Software SPI Data or Command GPIO_RF_SENSOR, // Rf receiver with sensor decoding + GPIO_AZ_TXD, // AZ-Instrument 7798 Serial interface + GPIO_AZ_RXD, // AZ-Instrument 7798 Serial interface GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -201,7 +203,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|" D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET "|" D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC "|" - D_SENSOR_RF_SENSOR; + D_SENSOR_RF_SENSOR "|" + D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX; /********************************************************************************************/ @@ -454,6 +457,10 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_MGC3130_XFER, GPIO_MGC3130_RESET #endif +#ifdef USE_AZ7798 + GPIO_AZ_TXD, // AZ-Instrument 7798 CO2 datalogger Serial interface + GPIO_AZ_RXD // AZ-Instrument 7798 CO2 datalogger Serial interface +#endif }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 652116b2f..75ddaf327 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -370,7 +370,9 @@ void GetFeatures(void) #ifdef USE_ALECTO_V2 feature_sns2 |= 0x00020000; #endif -// feature_sns2 |= 0x00040000; +#ifdef USE_AZ7798 + feature_sns2 |= 0x00040000; +#endif // feature_sns2 |= 0x00080000; // feature_sns2 |= 0x00100000; // feature_sns2 |= 0x00200000; diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino new file mode 100644 index 000000000..fa1880398 --- /dev/null +++ b/sonoff/xsns_38_az7798.ino @@ -0,0 +1,306 @@ +/* + xsns_38_az7798.ino - AZ_Instrument 7798 CO2/temperature/humidity meter support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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_AZ7798 + +#define XSNS_38 38 + +/*********************************************************************************************\ + * CO2, temperature and humidity meter and data logger + * Known by different names (brief survey 2018-12-16): + * - AZ-Instrument 7798 (http://www.az-instrument.com.tw) + * - co2meter.com AZ-0004 + * - Extech CO200 + * - BES CO7788 (https://www.aliexpress.com) + * - AZ CO87 (https://www.aliexpress.com) + * - no doubt there are more ... + * + * Hardware Serial will be selected if GPIO1 = [AZ Tx] and GPIO3 = [AZ Rx] + * + * Inside the meter, the serial comms wire with the red stripe goes to GPIO1. + * The other one therefore to GPIO3. + * WeMos D1 Mini is powered from the incoming 5V. + * + * This implementation was derived from xsns_15_mhz19.ino from + * Sonoff-Tasmota-6.3.0 by Arthur de Beun. + * + * The serial comms protocol is not publicly documented, that I could find. + * The info below was obtained by reverse-engineering. + * Port settings: 9600 8N1 + * The suppied USB interface has a CP20x USB-serial bridge. + * The 3-way, 2.5mm jack has tip=RxD, middle=TxD and base=0V + * The TxD output swing is 3V3. + * + * There is never a space before the 0x0d, but the other spaces are there. + * + * serial number / ID + * request: I 0x0d + * response: i 12345678 7798V3.4 0x0d + * + * log info + * request: M 0x0d + * response: m 45 1 C 1af4 0cf4 0x0d + * + * 45 = number of records, but there are only 15 lines of 3 values each) + * 1 = sample rate in seconds + * C = celcius, F + * 1af4 0cf4 = seconds since 2000-01-01 00:00:00 + * + * start time 2014-04-30 19:35:16 + * end time 2014-04-30 19:35:30 + * + * download log data + * request: D 0x0d + * response: m 45 1 C 1af4 0cf4 0x0d + * d 174 955 698 0x0d + * 174 = temp in [C * 10] + * 955 = CO2 [ppm] + * 698 = RH in [% * 10] + * d 174 990 694 0x0d + * ... + * d 173 929 654 0x0d + * + * 15 lines in total, 1 second apart + * + * Sync datalogger time with PC + * request: C 452295746 0x0d + * response: > 0x0d + * + * 452295746 = seconds since 2000-01-01 00:00:00 + * + * Identifier: + * request: J -------- 1 0x0d + * + * the characters (dashes) in the above become the first part of the response to the I command (12345678 above) + * + * Set sample rate + * request: S 10 0x0d + * response: m 12 10 C 1af5 7be1 0x0d + * + * Other characters that seem to give a response: + * A responds with > + * so is similar to the response to C, so other characters may be required + * A is the beep alarm perhaps? + * parameters would be CO2 level and on/off, as per front panel P1.3 setting? + * + * L responds with > + * L perhaps sets the limits for the good and normal levels (P1.1 and P1.2)? + * + * Q responds with > + * Q is reset maybe (P4.1)? + * + * : responds with : T19.9C:C2167ppm:H57.4% + * This one gives the current readings. + ********************************************************************************************** + +/*********************************************************************************************/ + +#include + +#ifndef CO2_LOW +#define CO2_LOW 800 // Below this CO2 value show green light +#endif +#ifndef CO2_HIGH +#define CO2_HIGH 1200 // Above this CO2 value show red light +#endif + +#define AZ_READ_TIMEOUT 400 // Must be way less than 1000 but enough to read 9 bytes at 9600 bps + +TasmotaSerial *AzSerial; + +const char ktype[] = "AZ7798"; +uint8_t az_type = 1; +uint16_t az_co2 = 0; +double az_temperature = 0; +double az_humidity = 0; +uint8_t az_received = 0; +uint8_t az_state = 0; + +/*********************************************************************************************/ + +void AzEverySecond() +{ + az_state++; + if (5 == az_state) { // every 5 seconds + az_state = 0; + + AzSerial->flush(); // sync reception + AzSerial->write(":\r", 2); + az_received = 0; + + uint8_t az_response[32]; + unsigned long start = millis(); + uint8_t counter = 0; + uint8_t i, j; + uint8_t response_substr[16]; + + do { + if (AzSerial->available() > 0) { + az_response[counter] = AzSerial->read(); + if(az_response[counter] == 0x0d) { az_received = 1; } + counter++; + } else { + delay(5); + } + } while(((millis() - start) < AZ_READ_TIMEOUT) && (counter < sizeof(az_response)) && !az_received); + + AddLogSerial(LOG_LEVEL_DEBUG_MORE, az_response, counter); + + if (!az_received) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 comms timeout")); + return; + } + + i = 0; + while((az_response[i] != 'T') && (i < counter)) {i++;} // find the start of response + if(az_response[i] != 'T') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find start of response")); + return; + } + i++; // advance to start of temperature value + j = 0; + // find the end of temperature + while((az_response[i] != 'C') && (az_response[i] != 'F') && (i < counter)) { + response_substr[j++] = az_response[i++]; + } + if((az_response[i] != 'C') && (az_response[i] != 'F')){ + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of temperature")); + return; + } + response_substr[j] = 0; // add null terminator + az_temperature = CharToDouble((char*)response_substr); // units (C or F) depends on meter setting + if(az_response[i] == 'C') { // meter transmits in degC + az_temperature = ConvertTemp((float)az_temperature); // convert to degF, depending on settings + } else { // meter transmits in degF + if(!Settings.flag.temperature_conversion) { + az_temperature = (az_temperature - 32) / 1.8; // convert to degC + } + } + i++; // advance to first delimiter + if(az_response[i] != ':') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error first delimiter")); + return; + } + i++; // advance to start of CO2 + if(az_response[i] != 'C') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of CO2")); + return; + } + i++; // advance to start of CO2 value + j = 0; + // find the end of CO2 + while((az_response[i] != 'p') && (i < counter)) { + response_substr[j++] = az_response[i++]; + } + if(az_response[i] != 'p') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of CO2")); + return; + } + response_substr[j] = 0; // add null terminator + az_co2 = atoi((char*)response_substr); + LightSetSignal(CO2_LOW, CO2_HIGH, az_co2); + i += 3; // advance to second delimiter + if(az_response[i] != ':') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error second delimiter")); + return; + } + i++; // advance to start of humidity + if(az_response[i] != 'H') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of humidity")); + return; + } + i++; // advance to start of humidity value + j = 0; + // find the end of humidity + while((az_response[i] != '%') && (i < counter)) { + response_substr[j++] = az_response[i++]; + } + if(az_response[i] != '%') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of humidity")); + return; + } + response_substr[j] = 0; // add null terminator + az_humidity = CharToDouble((char*)response_substr); + } +} + +/*********************************************************************************************/ + +void AzInit() +{ + az_type = 0; + if ((pin[GPIO_AZ_RXD] < 99) && (pin[GPIO_AZ_TXD] < 99)) { + AzSerial = new TasmotaSerial(pin[GPIO_AZ_RXD], pin[GPIO_AZ_TXD], 1); + if (AzSerial->begin(9600)) { + if (AzSerial->hardwareSerial()) { ClaimSerial(); } + az_type = 1; + } + } +} + +void AzShow(boolean json) +{ + char temperature[10], humidity[10]; + dtostrfd(az_temperature, Settings.flag2.temperature_resolution, temperature); + dtostrfd(az_humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), mqtt_data, ktype, az_co2, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, az_co2); +#endif // USE_DOMOTICZ +#ifdef USE_WEBSERVER + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CO2, mqtt_data, ktype, az_co2); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, ktype, temperature, TempUnit()); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, ktype, humidity); +#endif // USE_WEBSERVER + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +boolean Xsns36(byte function) +{ + boolean result = false; + + if(az_type){ + switch (function) { + case FUNC_INIT: + AzInit(); + break; + case FUNC_EVERY_SECOND: + AzEverySecond(); + break; + case FUNC_JSON_APPEND: + AzShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_APPEND: + AzShow(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_AZ7798 diff --git a/tools/decode-status.py b/tools/decode-status.py index fa108bc02..ce8be9131 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -135,7 +135,7 @@ a_features = [[ "USE_MCP230xx_OUTPUT","USE_MCP230xx_DISPLAYOUTPUT","USE_HLW8012","USE_CSE7766", "USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711", "USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","USE_RF_SENSOR", - "USE_THEO_V2","USE_ALECTO_V2","","", + "USE_THEO_V2","USE_ALECTO_V2","USE_AZ7798","", "","","","", "","","","", "","","",""]] From db65b9c23a9bfae6cd67fd9e5d839f9fe55f3f70 Mon Sep 17 00:00:00 2001 From: Arthur de Beun Date: Tue, 18 Dec 2018 22:32:34 +1300 Subject: [PATCH 0733/2222] Add support for AZ-Instrument 7798 CO2 meter/datalogger. --- sonoff/xsns_38_az7798.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino index fa1880398..a31465655 100644 --- a/sonoff/xsns_38_az7798.ino +++ b/sonoff/xsns_38_az7798.ino @@ -278,7 +278,7 @@ void AzShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns36(byte function) +boolean Xsns38(byte function) { boolean result = false; From 2b0987da4728edd38b73661f7baf956820a00517 Mon Sep 17 00:00:00 2001 From: Arthur de Beun Date: Wed, 19 Dec 2018 06:36:53 +1300 Subject: [PATCH 0734/2222] Revert platformio.ini and my_user_config to original version, adding line for new sensor but leaving it commented out. --- RELEASENOTES.md | 2 +- platformio.ini | 194 ++++++++++------------------------------ sonoff/my_user_config.h | 42 ++++----- sonoff/sonoff_post.h | 2 +- 4 files changed, 68 insertions(+), 172 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 86fd21508..c2b62bdc3 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -182,7 +182,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_RC_SWITCH | - | - | - | x | x | x | | USE_RF_SENSOR | - | - | - | - | - | x | AlectoV2 only | USE_DISPLAY | - | - | - | - | - | - | -| USE_AZ7798 | - | - | - | x | x | x | +| USE_AZ7798 | - | - | - | - | - | - | ## Changelog Version 6.4.0 20181217 diff --git a/platformio.ini b/platformio.ini index 91fffea5d..14e554263 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,132 +34,67 @@ src_dir = sonoff ;env_default = sonoff-PT ;env_default = sonoff-RU ;env_default = sonoff-SE -;env_default = sonoff-SK ;env_default = sonoff-TR ;env_default = sonoff-TW ;env_default = sonoff-UK -[esp82xx_defaults] -build_flags = -D NDEBUG - -mtarget-align - -Wl,-Map,firmware.map - -[core_2_3_0] +[common] ; ************************************************************ ; *** Esp8266 core for Arduino version 2.3.0 -platform = espressif8266@1.5.0 -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Tesp8266.flash.1m0.ld - -[core_2_4_2] +;platform = espressif8266@1.5.0 ; *** Esp8266 core for Arduino version 2.4.2 -platform = espressif8266@1.8.0 -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m0.ld - -lstdc++ -lsupc++ -; lwIP 1.4 (Default) -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH - -DVTABLES_IN_FLASH - -[core_2_5_0] -; *** Esp8266 core for Arduino version Core 2.5.0 beta tested for Tasmota -platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld -; lwIP 1.4 (Default) -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH - -DVTABLES_IN_FLASH - -fno-exceptions - -lstdc++-nox - -[core_stage] +platform = espressif8266@1.8.0 ; *** Esp8266 core for Arduino version latest beta -platform = https://github.com/platformio/platform-espressif8266.git#feature/stage -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld -; lwIP 1.4 (Default) -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwitdh Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwitdh no Features - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; VTABLES in Flash (default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++-nox -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++ +;platform = https://github.com/platformio/platform-espressif8266.git#feature/stage +; *** Esp8266 core for Arduino current version (located in %USERPROFILE%\.platformio\platforms\espressif8266) +;platform = espressif8266 -[core_active] -; Select one core set for platform and build_flags -;platform = ${core_2_3_0.platform} -;build_flags = ${core_2_3_0.build_flags} -platform = ${core_2_4_2.platform} -build_flags = ${core_2_4_2.build_flags} -;platform = ${core_2_5_0.platform} -;build_flags = ${core_2_5_0.build_flags} -;platform = ${core_stage.platform} -;build_flags = ${core_stage.build_flags} - -[common] -framework = arduino -board = esp01_1m -board_build.flash_mode = dout - -platform = ${core_active.platform} -build_flags = ${core_active.build_flags} -; -DUSE_CLASSIC -; -DBE_MINIMAL -; -DUSE_SENSORS -; -DUSE_BASIC -; -DUSE_KNX_NO_EMULATION -; -DUSE_DISPLAYS -; -DUSE_CONFIG_OVERRIDE - -; *** Fix espressif8266@1.7.0 induced undesired all warnings -build_unflags = -Wall +framework = arduino +board = esp01_1m +board_build.flash_mode = dout ; set CPU frequency to 80MHz (default) or 160MHz -board_build.f_cpu = 80000000L -;board_build.f_cpu = 160000000L +board_build.f_cpu = 80000000L +;board_build.f_cpu = 160000000L -monitor_speed = 115200 -upload_speed = 115200 -upload_resetmethod = nodemcu +; *** Fix espressif8266@1.7.0 induced undesired all warnings +build_unflags = -Wall + +build_flags = +; if using esp8266 core 2.5.0 (stage) or up +; -Wl,-Tesp8266.flash.1m.ld -Wl,-Map,firmware.map +; if using esp8266 core < 2.5.0 + -Wl,-Tesp8266.flash.1m0.ld -Wl,-Map,firmware.map + -mtarget-align +; -DUSE_CONFIG_OVERRIDE +; lwIP 2 - Higher Bandwitdh (core 2.4.2) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwitdh no Features (core 2.5.0) +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH + -DVTABLES_IN_FLASH + +; if using esp8266 core 2.5.0 (stage) or up +; No exception code in firmware +; -fno-exceptions +; -lstdc++-nox + +; *** Serial Monitor options +monitor_speed = 115200 ; *** Upload Serial reset method for Wemos and NodeMCU -upload_port = /dev/ttyUSB1 -extra_scripts = pio/strip-floats.py +upload_speed = 115200 +upload_resetmethod = nodemcu +upload_port = COM5 + +; *** Fix Esp/Arduino core 2.4.x induced Tasmota unused floating point includes +extra_scripts = pio/strip-floats.py ; *** Upload file to OTA server using SCP -;upload_port = user@host:/path -;extra_scripts = pio/strip-floats.py, pio/sftp-uploader.py +;upload_port = user@host:/path +;extra_scripts = pio/strip-floats.py, pio/sftp-uploader.py -; *** Upload file to OTA server in folder api/arduino using HTTP -;upload_port = domus1:80/api/upload-arduino.php -;extra_scripts = pio/strip-floats.py, pio/http-uploader.py +; *** Upload file to OTA server using HTTP +;upload_port = domus1:80/api/upload-arduino.php +;extra_scripts = pio/strip-floats.py, pio/http-uploader.py ; ********************************************************************* @@ -485,20 +420,6 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-SK] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=sk-SK -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - [env:sonoff-TR] platform = ${common.platform} framework = ${common.framework} @@ -540,28 +461,3 @@ upload_port = ${common.upload_port} upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} - -[env:wemos-d1-mini] -platform = espressif8266 -framework = arduino -board = esp01_1m -board_build.flash_mode = dout -build_flags = -Wl,-Tesp8266.flash.1m0.ld -DMQTT_MAX_PACKET_SIZE=1000 -lib_deps = PubSubClient, NeoPixelBus, IRremoteESP8266, ArduinoJSON -extra_scripts = pio/strip-floats.py - -; *** Serial Monitor options -monitor_speed = 115200 - -; *** Upload Serial reset method for Wemos and NodeMCU -upload_resetmethod = nodemcu -upload_speed = 115200 -upload_port = /dev/ttyUSB1 - -; *** Upload file to OTA server using SCP -;upload_port = user@host:/path -;extra_scripts = pio/strip-floats.py, pio/sftp-uploader.py - -; *** Upload file to OTA server using HTTP -;upload_port = domus1:80/api/upload-arduino.php -;extra_scripts = pio/strip-floats.py, pio/http-uploader.py diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 7e9f16a36..b2909f89a 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -209,7 +209,6 @@ //#define MY_LANGUAGE pt-BR // Portuguese in Brazil //#define MY_LANGUAGE pt-PT // Portuguese in Portugal //#define MY_LANGUAGE ru-RU // Russian in Russia -//#define MY_LANGUAGE sk-SK // Slovak in Slovakia //#define MY_LANGUAGE sv-SE // Swedish in Sweden //#define MY_LANGUAGE tr-TR // Turkish in Turkey //#define MY_LANGUAGE uk-UK // Ukrainian in Ukrain @@ -283,7 +282,7 @@ // #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors // -- I2C sensors --------------------------------- -//#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) +#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) #ifdef USE_I2C #define USE_SHT // Enable SHT1X sensor (+1k4 code) @@ -348,12 +347,12 @@ #endif // USE_SPI // -- Serial sensors ------------------------------ -//#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) -//#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) +#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) +#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) #define CO2_LOW 800 // Below this CO2 value show green light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) -//#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) -//#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) +#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) +#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) #define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) //#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) @@ -363,35 +362,36 @@ #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) //#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) -//#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer +#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer #define TUYA_DIMMER_ID 0 // Default dimmer Id -//#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) -//#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer -#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code) +#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) +#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer +//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code) + // Power monitoring sensors ----------------------- -//#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) -//#define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) -//#define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) -//#define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) +#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) +#define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) +#define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) +#define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) // -- Low level interface devices ----------------- -//#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k3 code, 0k3 mem, 48 iram) +#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k3 code, 0k3 mem, 48 iram) // #define USE_IR_HVAC // Support for HVAC (Toshiba, Mitsubishi and LG) system using IR (+3k5 code) -// #define USE_IR_RECEIVE // Support for IR receiver (+7k2 code, 264 iram) + #define USE_IR_RECEIVE // Support for IR receiver (+7k2 code, 264 iram) #define IR_RCV_BUFFER_SIZE 100 // Max number of packets allowed in capture buffer (default 100 (*2 bytes ram)) #define IR_RCV_TIMEOUT 15 // Number of milli-Seconds of no-more-data before we consider a message ended (default 15) #define IR_RCV_MIN_UNKNOWN_SIZE 6 // Set the smallest sized "UNKNOWN" message packets we actually care about (default 6) -//#define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // -// #define USE_WS2812_CTYPE NEO_GRB // WS2812 Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW) +#define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // + #define USE_WS2812_CTYPE NEO_GRB // WS2812 Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW) // #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial RXD) (+1k mem). When USE_WS2812_DMA is enabled expect Exceptions on Pow -//#define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) +#define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) -//#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) +#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) //#define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code) -//#define USE_HX711 // Add support for HX711 load cell (+1k5 code) +#define USE_HX711 // Add support for HX711 load cell (+1k5 code) // #define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) #define USE_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (+3k code) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 38ae7e223..8eddeea5b 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -135,7 +135,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code) -#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger +//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger #endif // USE_SENSORS /*********************************************************************************************\ From ff1e51613e87f004bc3564109366d9d921f468c5 Mon Sep 17 00:00:00 2001 From: Arthur de Beun Date: Wed, 19 Dec 2018 06:51:13 +1300 Subject: [PATCH 0735/2222] Include changes from original into sonoff/language/bg-BG.h --- sonoff/language/bg-BG.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 66793ea7e..222c62b58 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.2.1.20 + * Updated until v6.4.0.1 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -77,14 +77,14 @@ #define D_DATA "Данни" #define D_DARKLIGHT "Тъмна" #define D_DEBUG "Дебъгване" -#define D_DISABLED "Деактивиран" +#define D_DISABLED "Забранен" #define D_DISTANCE "Разстояние" #define D_DNS_SERVER "DNS Сървър" #define D_DONE "Изпълнено" -#define D_DST_TIME "DST" +#define D_DST_TIME "Лятно време" #define D_ECO2 "eCO₂" #define D_EMULATION "Емулация" -#define D_ENABLED "Активиран" +#define D_ENABLED "Разрешен" #define D_ERASE "Изтриване" #define D_ERROR "Грешка" #define D_FAHRENHEIT "Фаренхайт" @@ -128,11 +128,11 @@ #define D_POWERUSAGE_APPARENT "Пълна мощност" #define D_POWERUSAGE_REACTIVE "Реактивна мощност" #define D_PRESSURE "Налягане" -#define D_PRESSUREATSEALEVEL "Налягане на морското ниво" +#define D_PRESSUREATSEALEVEL "Налягане при морското ниво" #define D_PROGRAM_FLASH_SIZE "Размер на флаш паметта за програми" #define D_PROGRAM_SIZE "Размер на програмата" #define D_PROJECT "Проект" -#define D_RAIN "Rain" +#define D_RAIN "Дъжд" #define D_RECEIVED "Получено" #define D_RESTART "Рестарт" #define D_RESTARTING "Рестартиране" @@ -393,7 +393,7 @@ #define D_CONFIGURE_TIMER "Конфигуриране на таймер" #define D_TIMER_PARAMETERS "Параметри на таймера" #define D_TIMER_ENABLE "Активиране на таймера" -#define D_TIMER_ARM "Arm" +#define D_TIMER_ARM "Активиран" #define D_TIMER_TIME "Време" #define D_TIMER_DAYS "Дни" #define D_TIMER_REPEAT "Повтори" @@ -537,7 +537,7 @@ #define D_SENSOR_SSPI_SCLK "SSPI SCLK" #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_RF_SENSOR "RF датчик" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" @@ -599,13 +599,13 @@ #define D_LOG_WIFI "WIF: " // Wifi //SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" +#define D_PHASE_ANGLE "Фазов ъгъл" +#define D_IMPORT_ACTIVE "Входна активна мощност" +#define D_EXPORT_ACTIVE "Изходна активна мощност" +#define D_IMPORT_REACTIVE "Входна реактивна мощност" +#define D_EXPORT_REACTIVE "Изходна реактивна мощност" +#define D_TOTAL_REACTIVE "Общо реактивна мощност" #define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" +#define D_UNIT_ANGLE "°" #endif // _LANGUAGE_BG_BG_H_ From 6185a08d8988ebe4b25107944a97a483c1b4f6f5 Mon Sep 17 00:00:00 2001 From: Arthur de Beun Date: Wed, 19 Dec 2018 06:57:37 +1300 Subject: [PATCH 0736/2222] Updated from originals: platformio.ini, sonoff/my_user_config.h. --- platformio.ini | 165 +++++++++++++++++++++++++++++----------- sonoff/my_user_config.h | 1 + 2 files changed, 123 insertions(+), 43 deletions(-) diff --git a/platformio.ini b/platformio.ini index 14e554263..2546e6864 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,67 +34,132 @@ src_dir = sonoff ;env_default = sonoff-PT ;env_default = sonoff-RU ;env_default = sonoff-SE +;env_default = sonoff-SK ;env_default = sonoff-TR ;env_default = sonoff-TW ;env_default = sonoff-UK -[common] ; ************************************************************ +[esp82xx_defaults] +build_flags = -D NDEBUG + -mtarget-align + -Wl,-Map,firmware.map + +[core_2_3_0] ; *** Esp8266 core for Arduino version 2.3.0 -;platform = espressif8266@1.5.0 +platform = espressif8266@1.5.0 +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Tesp8266.flash.1m0.ld + +[core_2_4_2] ; *** Esp8266 core for Arduino version 2.4.2 -platform = espressif8266@1.8.0 +platform = espressif8266@1.8.0 +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m0.ld + -lstdc++ -lsupc++ +; lwIP 1.4 (Default) +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH + -DVTABLES_IN_FLASH + +[core_2_5_0] +; *** Esp8266 core for Arduino version Core 2.5.0 beta tested for Tasmota +platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld +; lwIP 1.4 (Default) +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH + -DVTABLES_IN_FLASH + -fno-exceptions + -lstdc++-nox + +[core_stage] ; *** Esp8266 core for Arduino version latest beta -;platform = https://github.com/platformio/platform-espressif8266.git#feature/stage -; *** Esp8266 core for Arduino current version (located in %USERPROFILE%\.platformio\platforms\espressif8266) -;platform = espressif8266 +platform = https://github.com/platformio/platform-espressif8266.git#feature/stage +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld +; lwIP 1.4 (Default) +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwitdh Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwitdh no Features + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; VTABLES in Flash (default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++-nox +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++ -framework = arduino -board = esp01_1m -board_build.flash_mode = dout +[core_active] +; Select one core set for platform and build_flags +;platform = ${core_2_3_0.platform} +;build_flags = ${core_2_3_0.build_flags} +platform = ${core_2_4_2.platform} +build_flags = ${core_2_4_2.build_flags} +;platform = ${core_2_5_0.platform} +;build_flags = ${core_2_5_0.build_flags} +;platform = ${core_stage.platform} +;build_flags = ${core_stage.build_flags} -; set CPU frequency to 80MHz (default) or 160MHz -board_build.f_cpu = 80000000L -;board_build.f_cpu = 160000000L +[common] +framework = arduino +board = esp01_1m +board_build.flash_mode = dout + +platform = ${core_active.platform} +build_flags = ${core_active.build_flags} +; -DUSE_CLASSIC +; -DBE_MINIMAL +; -DUSE_SENSORS +; -DUSE_BASIC +; -DUSE_KNX_NO_EMULATION +; -DUSE_DISPLAYS +; -DUSE_CONFIG_OVERRIDE ; *** Fix espressif8266@1.7.0 induced undesired all warnings -build_unflags = -Wall +build_unflags = -Wall -build_flags = -; if using esp8266 core 2.5.0 (stage) or up -; -Wl,-Tesp8266.flash.1m.ld -Wl,-Map,firmware.map -; if using esp8266 core < 2.5.0 - -Wl,-Tesp8266.flash.1m0.ld -Wl,-Map,firmware.map - -mtarget-align -; -DUSE_CONFIG_OVERRIDE -; lwIP 2 - Higher Bandwitdh (core 2.4.2) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwitdh no Features (core 2.5.0) -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH - -DVTABLES_IN_FLASH +; set CPU frequency to 80MHz (default) or 160MHz +board_build.f_cpu = 80000000L +;board_build.f_cpu = 160000000L -; if using esp8266 core 2.5.0 (stage) or up -; No exception code in firmware -; -fno-exceptions -; -lstdc++-nox - -; *** Serial Monitor options -monitor_speed = 115200 +monitor_speed = 115200 +upload_speed = 115200 +upload_resetmethod = nodemcu ; *** Upload Serial reset method for Wemos and NodeMCU -upload_speed = 115200 -upload_resetmethod = nodemcu -upload_port = COM5 - -; *** Fix Esp/Arduino core 2.4.x induced Tasmota unused floating point includes -extra_scripts = pio/strip-floats.py +upload_port = COM5 +extra_scripts = pio/strip-floats.py ; *** Upload file to OTA server using SCP -;upload_port = user@host:/path -;extra_scripts = pio/strip-floats.py, pio/sftp-uploader.py +;upload_port = user@host:/path +;extra_scripts = pio/strip-floats.py, pio/sftp-uploader.py -; *** Upload file to OTA server using HTTP -;upload_port = domus1:80/api/upload-arduino.php -;extra_scripts = pio/strip-floats.py, pio/http-uploader.py +; *** Upload file to OTA server in folder api/arduino using HTTP +;upload_port = domus1:80/api/upload-arduino.php +;extra_scripts = pio/strip-floats.py, pio/http-uploader.py ; ********************************************************************* @@ -420,6 +485,20 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} +[env:sonoff-SK] +platform = ${common.platform} +framework = ${common.framework} +board = ${common.board} +board_build.flash_mode = ${common.board_build.flash_mode} +board_build.f_cpu = ${common.board_build.f_cpu} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} -DMY_LANGUAGE=sk-SK +monitor_speed = ${common.monitor_speed} +upload_port = ${common.upload_port} +upload_resetmethod = ${common.upload_resetmethod} +upload_speed = ${common.upload_speed} +extra_scripts = ${common.extra_scripts} + [env:sonoff-TR] platform = ${common.platform} framework = ${common.framework} diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index b2909f89a..aa92cba85 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -209,6 +209,7 @@ //#define MY_LANGUAGE pt-BR // Portuguese in Brazil //#define MY_LANGUAGE pt-PT // Portuguese in Portugal //#define MY_LANGUAGE ru-RU // Russian in Russia +//#define MY_LANGUAGE sk-SK // Slovak in Slovakia //#define MY_LANGUAGE sv-SE // Swedish in Sweden //#define MY_LANGUAGE tr-TR // Turkish in Turkey //#define MY_LANGUAGE uk-UK // Ukrainian in Ukrain From c506c48965d8da1f1cdaaf561dda0f7c83f52b44 Mon Sep 17 00:00:00 2001 From: Arthur de Beun Date: Wed, 19 Dec 2018 08:03:09 +1300 Subject: [PATCH 0737/2222] Revert to original RELEASENOTES.md. --- RELEASENOTES.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c2b62bdc3..973658a4c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -182,7 +182,6 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_RC_SWITCH | - | - | - | x | x | x | | USE_RF_SENSOR | - | - | - | - | - | x | AlectoV2 only | USE_DISPLAY | - | - | - | - | - | - | -| USE_AZ7798 | - | - | - | - | - | - | ## Changelog Version 6.4.0 20181217 @@ -245,4 +244,3 @@ Version 6.4.0 20181217 * Add support for GPIO02 for newer Sonoff Basic (#4518) * Add Announce Switches to MQTT Discovery (#4531) * Add support for Manzoku Power Strip (#4590) - * Add support for AZ-Instrument 7798 CO2 meter/datalogger From 201baa3513c7d0f5a02b217fc36616d0bcd5ff4b Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Tue, 18 Dec 2018 21:14:55 +0200 Subject: [PATCH 0738/2222] Add void to functions without parameters --- sonoff/xsns_38_az7798.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino index a31465655..8052b304f 100644 --- a/sonoff/xsns_38_az7798.ino +++ b/sonoff/xsns_38_az7798.ino @@ -134,7 +134,7 @@ uint8_t az_state = 0; /*********************************************************************************************/ -void AzEverySecond() +void AzEverySecond(void) { az_state++; if (5 == az_state) { // every 5 seconds @@ -242,7 +242,7 @@ void AzEverySecond() /*********************************************************************************************/ -void AzInit() +void AzInit(void) { az_type = 0; if ((pin[GPIO_AZ_RXD] < 99) && (pin[GPIO_AZ_TXD] < 99)) { From a6a927b24ba4ed87ade4d90d5eafb13d2962e01a Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Tue, 18 Dec 2018 21:31:00 +0200 Subject: [PATCH 0739/2222] Fix temperature conversion Fix temperature conversion to still use ConvertTemp() even if meter sends the value in F --- sonoff/xsns_38_az7798.ino | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino index 8052b304f..6491be885 100644 --- a/sonoff/xsns_38_az7798.ino +++ b/sonoff/xsns_38_az7798.ino @@ -188,9 +188,7 @@ void AzEverySecond(void) if(az_response[i] == 'C') { // meter transmits in degC az_temperature = ConvertTemp((float)az_temperature); // convert to degF, depending on settings } else { // meter transmits in degF - if(!Settings.flag.temperature_conversion) { - az_temperature = (az_temperature - 32) / 1.8; // convert to degC - } + az_temperature = ConvertTemp((az_temperature - 32) / 1.8); // convert to degC and then C or F depending on setting } i++; // advance to first delimiter if(az_response[i] != ':') { From 8a7dd3e06d235d744aac62f111a38b5037a3d797 Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Wed, 19 Dec 2018 00:00:19 +0200 Subject: [PATCH 0740/2222] Add support for AZ-Instrument 7798 CO2 Add support for AZ-Instrument 7798 CO2 meter/datalogger --- sonoff/_changelog.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index c182ab074..227bb32c7 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,5 @@ /* 6.4.0.1 20181217 - * New release + * Add support for AZ-Instrument 7798 CO2 meter/datalogger (#4672) * * 6.4.0 20181217 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% From 1fb4e8bc2352631c3e8749e31149a4cd3314b511 Mon Sep 17 00:00:00 2001 From: dcandi Date: Wed, 19 Dec 2018 20:51:39 +0100 Subject: [PATCH 0741/2222] pressure unit of measure reporting Added a dedicated pressure sensor management to report back as pressure sensor and not fallback as a generic sensor in HA autodiscovery process --- sonoff/xdrv_12_home_assistant.ino | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index ad9e71a4c..9a29f3562 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -89,6 +89,11 @@ const char HASS_DISCOVER_SENSOR_HUM[] PROGMEM = "\"value_template\":\"{{value_json['%s'].Humidity}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }} "\"device_class\":\"humidity\""; // temperature / humidity +const char HASS_DISCOVER_SENSOR_PRESS[] PROGMEM = + "%s,\"unit_of_measurement\":\"%s\"," // PressureUnit() setting + "\"value_template\":\"{{value_json['%s'].Pressure}}\"," // "BME280":{"Temperature":19.7,"Humidity":27.8,"Pressure":990.1} -> {{ value_json['BME280'].Pressure }} + "\"device_class\":\"pressure\""; // pressure + const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = "%s,\"value_template\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} @@ -167,6 +172,11 @@ const char HASS_DISCOVER_SENSOR_HUM_SHORT[] PROGMEM = "\"val_tpl\":\"{{value_json['%s'].Humidity}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }} "\"dev_cla\":\"humidity\""; // humidity +const char HASS_DISCOVER_SENSOR_PRESS_SHORT[] PROGMEM = + "%s,\"unit_of_meas\":\"%s\"," // PressureUnit() setting + "\"val_tpl\":\"{{value_json['%s'].Pressure}}\"," // "BME280":{"Temperature":19.7,"Humidity":27.8,"Pressure":990.1} -> {{ value_json['BME280'].Pressure }} + "\"dev_cla\":\"pressure\""; // pressure + const char HASS_DISCOVER_SENSOR_ANY_SHORT[] PROGMEM = "%s,\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} @@ -464,7 +474,11 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) } else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_HUM_SHORT:HASS_DISCOVER_SENSOR_HUM, mqtt_data, sensorname); - } else { + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE))) { + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_PRESS_SHORT:HASS_DISCOVER_SENSOR_PRESS, + mqtt_data, PressureUnit().c_str(), sensorname); + } + else { snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_ANY_SHORT:HASS_DISCOVER_SENSOR_ANY, mqtt_data, sensorname, subsensortype); } From c1e098403cea54482c7e0eb84ae7161aa83960dc Mon Sep 17 00:00:00 2001 From: reey <23506385+reey@users.noreply.github.com> Date: Thu, 20 Dec 2018 23:06:56 +0100 Subject: [PATCH 0742/2222] add missing units of measurements for energy --- sonoff/xdrv_12_home_assistant.ino | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 9a29f3562..c12d86e4f 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -94,6 +94,23 @@ const char HASS_DISCOVER_SENSOR_PRESS[] PROGMEM = "\"value_template\":\"{{value_json['%s'].Pressure}}\"," // "BME280":{"Temperature":19.7,"Humidity":27.8,"Pressure":990.1} -> {{ value_json['BME280'].Pressure }} "\"device_class\":\"pressure\""; // pressure +//ENERGY +const char HASS_DISCOVER_SENSOR_KWH[] PROGMEM = + "%s,\"unit_of_measurement\":\"°%kWh\"," // kWh + "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Total/Yesterday/Today }} + +const char HASS_DISCOVER_SENSOR_WATT[] PROGMEM = + "%s,\"unit_of_measurement\":\"°%W\"," // W + "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].POWER }} + +const char HASS_DISCOVER_SENSOR_VOLTAGE[] PROGMEM = + "%s,\"unit_of_measurement\":\"°%V\"," // V + "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Voltage }} + +const char HASS_DISCOVER_SENSOR_AMPERE[] PROGMEM = + "%s,\"unit_of_measurement\":\"°%A\"," // A + "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Current }} + const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = "%s,\"value_template\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} @@ -177,6 +194,23 @@ const char HASS_DISCOVER_SENSOR_PRESS_SHORT[] PROGMEM = "\"val_tpl\":\"{{value_json['%s'].Pressure}}\"," // "BME280":{"Temperature":19.7,"Humidity":27.8,"Pressure":990.1} -> {{ value_json['BME280'].Pressure }} "\"dev_cla\":\"pressure\""; // pressure +//ENERGY +const char HASS_DISCOVER_SENSOR_KWH_SHORT[] PROGMEM = + "%s,\"unit_of_meas\":\"°%kWh\"," // kWh + "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Total/Yesterday/Today }} + +const char HASS_DISCOVER_SENSOR_WATT_SHORT[] PROGMEM = + "%s,\"unit_of_meas\":\"°%W\"," // W + "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].POWER }} + +const char HASS_DISCOVER_SENSOR_VOLTAGE_SHORT[] PROGMEM = + "%s,\"unit_of_meas\":\"°%V\"," // V + "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Voltage }} + +const char HASS_DISCOVER_SENSOR_AMPERE_SHORT[] PROGMEM = + "%s,\"unit_of_meas\":\"°%A\"," // A + "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Current }} + const char HASS_DISCOVER_SENSOR_ANY_SHORT[] PROGMEM = "%s,\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} @@ -477,6 +511,18 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE))) { snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_PRESS_SHORT:HASS_DISCOVER_SENSOR_PRESS, mqtt_data, PressureUnit().c_str(), sensorname); + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL)) || !strcmp_P(subsensortype, PSTR(D_JSON_TODAY)) || !strcmp_P(subsensortype, PSTR(D_JSON_YESTERDAY))){ + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_KWH_SHORT:HASS_DISCOVER_SENSOR_KWH, + mqtt_data, sensorname, subsensortype); + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_POWERUSAGE))){ + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_WATT_SHORT:HASS_DISCOVER_SENSOR_WATT, + mqtt_data, sensorname, subsensortype); + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_VOLTAGE))){ + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_VOLTAGE_SHORT:HASS_DISCOVER_SENSOR_VOLTAGE, + mqtt_data, sensorname, subsensortype); + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_CURRENT))){ + snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_AMPERE_SHORT:HASS_DISCOVER_SENSOR_AMPERE, + mqtt_data, sensorname, subsensortype); } else { snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_ANY_SHORT:HASS_DISCOVER_SENSOR_ANY, From 6c158434ee2e4b31eb15e790042afa4e06465772 Mon Sep 17 00:00:00 2001 From: reey <23506385+reey@users.noreply.github.com> Date: Thu, 20 Dec 2018 23:27:05 +0100 Subject: [PATCH 0743/2222] removed some errors from copy pasting.. --- sonoff/xdrv_12_home_assistant.ino | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index c12d86e4f..5902928c8 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -96,19 +96,19 @@ const char HASS_DISCOVER_SENSOR_PRESS[] PROGMEM = //ENERGY const char HASS_DISCOVER_SENSOR_KWH[] PROGMEM = - "%s,\"unit_of_measurement\":\"°%kWh\"," // kWh + "%s,\"unit_of_measurement\":\"kWh\"," // kWh "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Total/Yesterday/Today }} const char HASS_DISCOVER_SENSOR_WATT[] PROGMEM = - "%s,\"unit_of_measurement\":\"°%W\"," // W + "%s,\"unit_of_measurement\":\"W\"," // W "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].POWER }} const char HASS_DISCOVER_SENSOR_VOLTAGE[] PROGMEM = - "%s,\"unit_of_measurement\":\"°%V\"," // V + "%s,\"unit_of_measurement\":\"V\"," // V "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Voltage }} const char HASS_DISCOVER_SENSOR_AMPERE[] PROGMEM = - "%s,\"unit_of_measurement\":\"°%A\"," // A + "%s,\"unit_of_measurement\":\"A\"," // A "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Current }} const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = @@ -196,19 +196,19 @@ const char HASS_DISCOVER_SENSOR_PRESS_SHORT[] PROGMEM = //ENERGY const char HASS_DISCOVER_SENSOR_KWH_SHORT[] PROGMEM = - "%s,\"unit_of_meas\":\"°%kWh\"," // kWh + "%s,\"unit_of_meas\":\"kWh\"," // kWh "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Total/Yesterday/Today }} const char HASS_DISCOVER_SENSOR_WATT_SHORT[] PROGMEM = - "%s,\"unit_of_meas\":\"°%W\"," // W + "%s,\"unit_of_meas\":\"W\"," // W "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].POWER }} const char HASS_DISCOVER_SENSOR_VOLTAGE_SHORT[] PROGMEM = - "%s,\"unit_of_meas\":\"°%V\"," // V + "%s,\"unit_of_meas\":\"V\"," // V "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Voltage }} const char HASS_DISCOVER_SENSOR_AMPERE_SHORT[] PROGMEM = - "%s,\"unit_of_meas\":\"°%A\"," // A + "%s,\"unit_of_meas\":\"A\"," // A "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Current }} const char HASS_DISCOVER_SENSOR_ANY_SHORT[] PROGMEM = From ebd12235c4f77b497fa46935139ce3d9aaf1047e Mon Sep 17 00:00:00 2001 From: reey <23506385+reey@users.noreply.github.com> Date: Fri, 21 Dec 2018 10:38:44 +0100 Subject: [PATCH 0744/2222] add empty unit of measurement for any sensors --- sonoff/xdrv_12_home_assistant.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 5902928c8..01c5eb60c 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -112,7 +112,8 @@ const char HASS_DISCOVER_SENSOR_AMPERE[] PROGMEM = "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Current }} const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = - "%s,\"value_template\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} + "%s,\"unit_of_measurement\":\" \"," // " " As unit of measurement to get a value graph in Hass + "\"value_template\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} const char HASS_DISCOVER_RELAY_SHORT[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 @@ -212,7 +213,8 @@ const char HASS_DISCOVER_SENSOR_AMPERE_SHORT[] PROGMEM = "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Current }} const char HASS_DISCOVER_SENSOR_ANY_SHORT[] PROGMEM = - "%s,\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} + "%s,\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass + "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = "%s,\"uniq_id\":\"%s\"," From 435b3afde7979db1e2b12bd6797f142a69e8c98a Mon Sep 17 00:00:00 2001 From: Frank Meies <19324766+fmeies@users.noreply.github.com> Date: Fri, 21 Dec 2018 11:28:47 +0100 Subject: [PATCH 0745/2222] Added option for checking mqtt tls against root ca Signed-off-by: Frank Meies <19324766+fmeies@users.noreply.github.com> --- sonoff/my_user_config.h | 74 +++++++++++++++++++++++++++++++++++++++++ sonoff/xdrv_02_mqtt.ino | 10 ++++++ 2 files changed, 84 insertions(+) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index aa92cba85..884c47694 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -248,6 +248,80 @@ // -- MQTT - TLS ---------------------------------- // !!! TLS uses a LOT OF MEMORY so be careful to enable other options at the same time !!! //#define USE_MQTT_TLS // Use TLS for MQTT connection (+53k code, +15k mem) +//#define USE_MQTT_TLS_ROOTCERT +#define MQTT_TLS_ROOT_CA_LENGTH 846 // Letsencrypt +#define MQTT_TLS_ROOT_CA { \ + 0x30, 0x82, 0x03, 0x4a, 0x30, 0x82, 0x02, 0x32, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x10, 0x44, 0xaf, 0xb0, 0x80, 0xd6, 0xa3, 0x27, 0xba, 0x89, \ + 0x30, 0x39, 0x86, 0x2e, 0xf8, 0x40, 0x6b, 0x30, 0x0d, 0x06, 0x09, 0x2a, \ + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3f, \ + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 0x44, \ + 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, \ + 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, \ + 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ + 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, \ + 0x20, 0x58, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x39, 0x33, \ + 0x30, 0x32, 0x31, 0x31, 0x32, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x31, \ + 0x30, 0x39, 0x33, 0x30, 0x31, 0x34, 0x30, 0x31, 0x31, 0x35, 0x5a, 0x30, \ + 0x3f, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, \ + 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, \ + 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, \ + 0x43, 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, \ + 0x13, 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, \ + 0x41, 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, \ + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, \ + 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, \ + 0x00, 0xdf, 0xaf, 0xe9, 0x97, 0x50, 0x08, 0x83, 0x57, 0xb4, 0xcc, 0x62, \ + 0x65, 0xf6, 0x90, 0x82, 0xec, 0xc7, 0xd3, 0x2c, 0x6b, 0x30, 0xca, 0x5b, \ + 0xec, 0xd9, 0xc3, 0x7d, 0xc7, 0x40, 0xc1, 0x18, 0x14, 0x8b, 0xe0, 0xe8, \ + 0x33, 0x76, 0x49, 0x2a, 0xe3, 0x3f, 0x21, 0x49, 0x93, 0xac, 0x4e, 0x0e, \ + 0xaf, 0x3e, 0x48, 0xcb, 0x65, 0xee, 0xfc, 0xd3, 0x21, 0x0f, 0x65, 0xd2, \ + 0x2a, 0xd9, 0x32, 0x8f, 0x8c, 0xe5, 0xf7, 0x77, 0xb0, 0x12, 0x7b, 0xb5, \ + 0x95, 0xc0, 0x89, 0xa3, 0xa9, 0xba, 0xed, 0x73, 0x2e, 0x7a, 0x0c, 0x06, \ + 0x32, 0x83, 0xa2, 0x7e, 0x8a, 0x14, 0x30, 0xcd, 0x11, 0xa0, 0xe1, 0x2a, \ + 0x38, 0xb9, 0x79, 0x0a, 0x31, 0xfd, 0x50, 0xbd, 0x80, 0x65, 0xdf, 0xb7, \ + 0x51, 0x63, 0x83, 0xc8, 0xe2, 0x88, 0x61, 0xea, 0x4b, 0x61, 0x81, 0xec, \ + 0x52, 0x6b, 0xb9, 0xa2, 0xe2, 0x4b, 0x1a, 0x28, 0x9f, 0x48, 0xa3, 0x9e, \ + 0x0c, 0xda, 0x09, 0x8e, 0x3e, 0x17, 0x2e, 0x1e, 0xdd, 0x20, 0xdf, 0x5b, \ + 0xc6, 0x2a, 0x8a, 0xab, 0x2e, 0xbd, 0x70, 0xad, 0xc5, 0x0b, 0x1a, 0x25, \ + 0x90, 0x74, 0x72, 0xc5, 0x7b, 0x6a, 0xab, 0x34, 0xd6, 0x30, 0x89, 0xff, \ + 0xe5, 0x68, 0x13, 0x7b, 0x54, 0x0b, 0xc8, 0xd6, 0xae, 0xec, 0x5a, 0x9c, \ + 0x92, 0x1e, 0x3d, 0x64, 0xb3, 0x8c, 0xc6, 0xdf, 0xbf, 0xc9, 0x41, 0x70, \ + 0xec, 0x16, 0x72, 0xd5, 0x26, 0xec, 0x38, 0x55, 0x39, 0x43, 0xd0, 0xfc, \ + 0xfd, 0x18, 0x5c, 0x40, 0xf1, 0x97, 0xeb, 0xd5, 0x9a, 0x9b, 0x8d, 0x1d, \ + 0xba, 0xda, 0x25, 0xb9, 0xc6, 0xd8, 0xdf, 0xc1, 0x15, 0x02, 0x3a, 0xab, \ + 0xda, 0x6e, 0xf1, 0x3e, 0x2e, 0xf5, 0x5c, 0x08, 0x9c, 0x3c, 0xd6, 0x83, \ + 0x69, 0xe4, 0x10, 0x9b, 0x19, 0x2a, 0xb6, 0x29, 0x57, 0xe3, 0xe5, 0x3d, \ + 0x9b, 0x9f, 0xf0, 0x02, 0x5d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, \ + 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, \ + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, \ + 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, \ + 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc4, 0xa7, \ + 0xb1, 0xa4, 0x7b, 0x2c, 0x71, 0xfa, 0xdb, 0xe1, 0x4b, 0x90, 0x75, 0xff, \ + 0xc4, 0x15, 0x60, 0x85, 0x89, 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, \ + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, \ + 0x01, 0x00, 0xa3, 0x1a, 0x2c, 0x9b, 0x17, 0x00, 0x5c, 0xa9, 0x1e, 0xee, \ + 0x28, 0x66, 0x37, 0x3a, 0xbf, 0x83, 0xc7, 0x3f, 0x4b, 0xc3, 0x09, 0xa0, \ + 0x95, 0x20, 0x5d, 0xe3, 0xd9, 0x59, 0x44, 0xd2, 0x3e, 0x0d, 0x3e, 0xbd, \ + 0x8a, 0x4b, 0xa0, 0x74, 0x1f, 0xce, 0x10, 0x82, 0x9c, 0x74, 0x1a, 0x1d, \ + 0x7e, 0x98, 0x1a, 0xdd, 0xcb, 0x13, 0x4b, 0xb3, 0x20, 0x44, 0xe4, 0x91, \ + 0xe9, 0xcc, 0xfc, 0x7d, 0xa5, 0xdb, 0x6a, 0xe5, 0xfe, 0xe6, 0xfd, 0xe0, \ + 0x4e, 0xdd, 0xb7, 0x00, 0x3a, 0xb5, 0x70, 0x49, 0xaf, 0xf2, 0xe5, 0xeb, \ + 0x02, 0xf1, 0xd1, 0x02, 0x8b, 0x19, 0xcb, 0x94, 0x3a, 0x5e, 0x48, 0xc4, \ + 0x18, 0x1e, 0x58, 0x19, 0x5f, 0x1e, 0x02, 0x5a, 0xf0, 0x0c, 0xf1, 0xb1, \ + 0xad, 0xa9, 0xdc, 0x59, 0x86, 0x8b, 0x6e, 0xe9, 0x91, 0xf5, 0x86, 0xca, \ + 0xfa, 0xb9, 0x66, 0x33, 0xaa, 0x59, 0x5b, 0xce, 0xe2, 0xa7, 0x16, 0x73, \ + 0x47, 0xcb, 0x2b, 0xcc, 0x99, 0xb0, 0x37, 0x48, 0xcf, 0xe3, 0x56, 0x4b, \ + 0xf5, 0xcf, 0x0f, 0x0c, 0x72, 0x32, 0x87, 0xc6, 0xf0, 0x44, 0xbb, 0x53, \ + 0x72, 0x6d, 0x43, 0xf5, 0x26, 0x48, 0x9a, 0x52, 0x67, 0xb7, 0x58, 0xab, \ + 0xfe, 0x67, 0x76, 0x71, 0x78, 0xdb, 0x0d, 0xa2, 0x56, 0x14, 0x13, 0x39, \ + 0x24, 0x31, 0x85, 0xa2, 0xa8, 0x02, 0x5a, 0x30, 0x47, 0xe1, 0xdd, 0x50, \ + 0x07, 0xbc, 0x02, 0x09, 0x90, 0x00, 0xeb, 0x64, 0x63, 0x60, 0x9b, 0x16, \ + 0xbc, 0x88, 0xc9, 0x12, 0xe6, 0xd2, 0x7d, 0x91, 0x8b, 0xf9, 0x3d, 0x32, \ + 0x8d, 0x65, 0xb4, 0xe9, 0x7c, 0xb1, 0x57, 0x76, 0xea, 0xc5, 0xb6, 0x28, \ + 0x39, 0xbf, 0x15, 0x65, 0x1c, 0xc8, 0xf6, 0x77, 0x96, 0x6a, 0x0a, 0x8d, \ + 0x77, 0x0b, 0xd8, 0x91, 0x0b, 0x04, 0x8e, 0x07, 0xdb, 0x29, 0xb6, 0x0a, \ + 0xee, 0x9d, 0x82, 0x35, 0x35, 0x10 } // -- KNX IP Protocol ----------------------------- //#define USE_KNX // Enable KNX IP Protocol Support (+9.4k code, +3k7 mem) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index bc969d3f2..e072e9825 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -467,6 +467,15 @@ boolean MqttCheckTls(void) Settings.mqtt_host, Settings.mqtt_port, mqtt_retry_counter); AddLog(LOG_LEVEL_DEBUG); } else { +#ifdef USE_MQTT_TLS_ROOTCERT + unsigned char tls_root_ca[] = MQTT_TLS_ROOT_CA; + if(EspClient.setCACert(tls_root_ca, MQTT_TLS_ROOT_CA_LENGTH)) { + if (EspClient.verifyCertChain(Settings.mqtt_host)) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "CA")); + result = true; + } + } +#else if (EspClient.verify(fingerprint1, Settings.mqtt_host)) { AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "1")); result = true; @@ -475,6 +484,7 @@ boolean MqttCheckTls(void) AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "2")); result = true; } +#endif } if (!result) AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_FAILED)); EspClient.stop(); From ec931fe5fe4749569c5b1e4b2882149d6d773c90 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 21 Dec 2018 11:36:55 +0100 Subject: [PATCH 0746/2222] Change RAM usage BMP/BME Change RAM usage BMP/BME I2C sensors --- sonoff/_changelog.ino | 1 + sonoff/xsns_09_bmp.ino | 58 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 227bb32c7..2950e4094 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.4.0.1 20181217 * Add support for AZ-Instrument 7798 CO2 meter/datalogger (#4672) + * Change RAM usage BMP/BME I2C sensors * * 6.4.0 20181217 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index 68eef5c14..f5767a246 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -42,11 +42,8 @@ #define BMP_MAX_SENSORS 2 const char kBmpTypes[] PROGMEM = "BMP180|BMP280|BME280|BME680"; -uint8_t bmp_addresses[] = { BMP_ADDR1, BMP_ADDR2 }; -uint8_t bmp_count = 0; -uint8_t bmp_once = 1; -struct BMPSTRUCT { +typedef struct { uint8_t bmp_address; // I2C bus address char bmp_name[7]; // Sensor name - "BMPXXX" uint8_t bmp_type = 0; @@ -58,7 +55,13 @@ struct BMPSTRUCT { float bmp_temperature = 0.0; float bmp_pressure = 0.0; float bmp_humidity = 0.0; -} bmp_sensors[BMP_MAX_SENSORS]; +} bmp_sensors_t; + +uint8_t bmp_addresses[] = { BMP_ADDR1, BMP_ADDR2 }; +uint8_t bmp_count = 0; +uint8_t bmp_once = 1; + +bmp_sensors_t *bmp_sensors = NULL; /*********************************************************************************************\ * BMP085 and BME180 @@ -83,7 +86,7 @@ struct BMPSTRUCT { #define BMP180_OSS 3 -struct BMP180CALIBDATA { +typedef struct { int16_t cal_ac1; int16_t cal_ac2; int16_t cal_ac3; @@ -94,10 +97,17 @@ struct BMP180CALIBDATA { uint16_t cal_ac4; uint16_t cal_ac5; uint16_t cal_ac6; -} bmp180_cal_data[BMP_MAX_SENSORS]; +} bmp180_cal_data_t; + +bmp180_cal_data_t *bmp180_cal_data = NULL; boolean Bmp180Calibration(uint8_t bmp_idx) { + if (!bmp180_cal_data) { + bmp180_cal_data = (bmp180_cal_data_t*)malloc(BMP_MAX_SENSORS * sizeof(bmp180_cal_data_t)); + } + if (!bmp180_cal_data) { return false; } + bmp180_cal_data[bmp_idx].cal_ac1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC1); bmp180_cal_data[bmp_idx].cal_ac2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC2); bmp180_cal_data[bmp_idx].cal_ac3 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC3); @@ -140,6 +150,8 @@ boolean Bmp180Calibration(uint8_t bmp_idx) void Bmp180Read(uint8_t bmp_idx) { + if (!bmp180_cal_data) { return; } + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_TEMPERATURE); delay(5); // 5ms conversion time int ut = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); @@ -211,8 +223,7 @@ void Bmp180Read(uint8_t bmp_idx) #define BME280_REGISTER_DIG_H5 0xE5 #define BME280_REGISTER_DIG_H6 0xE7 -struct BME280CALIBDATA -{ +typedef struct { uint16_t dig_T1; int16_t dig_T2; int16_t dig_T3; @@ -231,12 +242,19 @@ struct BME280CALIBDATA uint8_t dig_H1; uint8_t dig_H3; int8_t dig_H6; -} Bme280CalibrationData[BMP_MAX_SENSORS]; +} Bme280CalibrationData_t; + +Bme280CalibrationData_t *Bme280CalibrationData = NULL; boolean Bmx280Calibrate(uint8_t bmp_idx) { // if (I2cRead8(bmp_address, BMP_REGISTER_CHIPID) != BME280_CHIPID) return false; + if (!Bme280CalibrationData) { + Bme280CalibrationData = (Bme280CalibrationData_t*)malloc(BMP_MAX_SENSORS * sizeof(Bme280CalibrationData_t)); + } + if (!Bme280CalibrationData) { return false; } + Bme280CalibrationData[bmp_idx].dig_T1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T1); Bme280CalibrationData[bmp_idx].dig_T2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T2); Bme280CalibrationData[bmp_idx].dig_T3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T3); @@ -270,6 +288,8 @@ boolean Bmx280Calibrate(uint8_t bmp_idx) void Bme280Read(uint8_t bmp_idx) { + if (!Bme280CalibrationData) { return; } + int32_t adc_T = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_TEMPDATA); adc_T >>= 4; @@ -324,7 +344,7 @@ void Bme280Read(uint8_t bmp_idx) #include -struct bme680_dev gas_sensor[BMP_MAX_SENSORS]; +struct bme680_dev *gas_sensor = NULL; static void BmeDelayMs(uint32_t ms) { @@ -333,6 +353,11 @@ static void BmeDelayMs(uint32_t ms) boolean Bme680Init(uint8_t bmp_idx) { + if (!gas_sensor) { + gas_sensor = (bme680_dev*)malloc(BMP_MAX_SENSORS * sizeof(bme680_dev)); + } + if (!gas_sensor) { return false; } + gas_sensor[bmp_idx].dev_id = bmp_sensors[bmp_idx].bmp_address; gas_sensor[bmp_idx].intf = BME680_I2C_INTF; gas_sensor[bmp_idx].read = &I2cReadBuffer; @@ -377,6 +402,8 @@ boolean Bme680Init(uint8_t bmp_idx) void Bme680Read(uint8_t bmp_idx) { + if (!gas_sensor) { return; } + int8_t rslt = BME680_OK; if (BME680_CHIPID == bmp_sensors[bmp_idx].bmp_type) { @@ -421,6 +448,11 @@ void BmpDetect(void) { if (bmp_count) return; + if (!bmp_sensors) { + bmp_sensors = (bmp_sensors_t*)malloc(BMP_MAX_SENSORS * sizeof(bmp_sensors_t)); + } + if (!bmp_sensors) { return; } + for (byte i = 0; i < BMP_MAX_SENSORS; i++) { uint8_t bmp_type = I2cRead8(bmp_addresses[i], BMP_REGISTER_CHIPID); if (bmp_type) { @@ -458,6 +490,8 @@ void BmpDetect(void) void BmpRead(void) { + if (!bmp_sensors) { return; } + for (byte bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { switch (bmp_sensors[bmp_idx].bmp_type) { case BMP180_CHIPID: @@ -491,6 +525,8 @@ void BmpEverySecond(void) void BmpShow(boolean json) { + if (!bmp_sensors) { return; } + for (byte bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { if (bmp_sensors[bmp_idx].bmp_type) { float bmp_sealevel = 0.0; From a17a40b5f3b9cf9840238b41b13f53e6717d2410 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 21 Dec 2018 12:33:30 +0100 Subject: [PATCH 0747/2222] Update Arduino IDE core 2.5.0 files Update Arduino IDE core 2.5.0 files --- arduino/version 2.5.0/boards.txt | 9 +++++++++ arduino/version 2.5.0/platform.txt | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/arduino/version 2.5.0/boards.txt b/arduino/version 2.5.0/boards.txt index 567c699d8..2334302b8 100644 --- a/arduino/version 2.5.0/boards.txt +++ b/arduino/version 2.5.0/boards.txt @@ -6,6 +6,7 @@ menu.BoardModel=Model menu.baud=Upload Speed +menu.UploadTool=Upload Using menu.xtal=CPU Frequency menu.CrystalFreq=Crystal Frequency menu.eesz=Flash Size @@ -36,6 +37,13 @@ generic.build.variant=generic generic.build.spiffs_pagesize=256 generic.build.debug_port= generic.build.debug_level= + +generic.menu.UploadTool.esptool=Serial +generic.menu.UploadTool.esptool.upload.tool=esptool +generic.menu.UploadTool.esptool.upload.verbose=-vv +generic.menu.UploadTool.espupload=OTA_upload +generic.menu.UploadTool.espupload.upload.tool=espupload + generic.menu.xtal.80=80 MHz generic.menu.xtal.80.build.f_cpu=80000000L generic.menu.xtal.160=160 MHz @@ -6075,3 +6083,4 @@ espectro.menu.baud.512000.windows=512000 espectro.menu.baud.512000.upload.speed=512000 espectro.menu.baud.921600=921600 espectro.menu.baud.921600.upload.speed=921600 + diff --git a/arduino/version 2.5.0/platform.txt b/arduino/version 2.5.0/platform.txt index 1cd2ded2c..39988668a 100644 --- a/arduino/version 2.5.0/platform.txt +++ b/arduino/version 2.5.0/platform.txt @@ -24,9 +24,12 @@ build.lwip_flags=-DLWIP_OPEN_SRC build.vtable_flags=-DVTABLES_IN_FLASH +#build.exception_flags=-fexceptions build.exception_flags=-fno-exceptions +#build.stdcpp_lib=-lstdc++ build.stdcpp_lib=-lstdc++-nox +#build.float=-u _printf_float -u _scanf_float build.float= build.led= @@ -143,3 +146,11 @@ tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/to tools.mkspiffs.cmd=mkspiffs tools.mkspiffs.cmd.windows=mkspiffs.exe tools.mkspiffs.path={runtime.tools.mkspiffs.path} + +tools.espupload.cmd=python +tools.espupload.cmd.windows=python.exe +tools.espupload.path={runtime.platform.path}/tools +tools.espupload.upload.protocol=espupload +tools.espupload.upload.params.verbose= +tools.espupload.upload.params.quiet= +tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin" From a80fcd98d74f4a8816763cb4cd793994070af6ce Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 21 Dec 2018 13:53:38 +0100 Subject: [PATCH 0748/2222] Fix wifi strongest signal detection Fix wifi strongest signal detection (#4704) --- sonoff/_changelog.ino | 1 + sonoff/support_wifi.ino | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 2950e4094..159f434d4 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.4.0.1 20181217 * Add support for AZ-Instrument 7798 CO2 meter/datalogger (#4672) * Change RAM usage BMP/BME I2C sensors + * Fix wifi strongest signal detection (#4704) * * 6.4.0 20181217 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 7f2771dde..8e45f58ea 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -249,7 +249,7 @@ void WifiBeginAfterScan() uint8_t* bssid = WiFi.BSSID(); // Get current bssid memcpy((void*) &wifi_bssid, (void*) bssid, sizeof(wifi_bssid)); best_network_db = WiFi.RSSI(); // Get current rssi and add threshold - if (best_network_db < -WIFI_RSSI_THRESHOLD) { best_network_db +WIFI_RSSI_THRESHOLD; } + if (best_network_db < -WIFI_RSSI_THRESHOLD) { best_network_db += WIFI_RSSI_THRESHOLD; } wifi_scan_state = 3; } // Init scan From c1102a48638742d4fd565b1c5d56df2877e50927 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 21 Dec 2018 16:17:06 +0100 Subject: [PATCH 0749/2222] 6.4.0.2 Fix possible dtostrf bos 6.4.0.2 20181221 * Fix possible dtostrf buffer overflows by increasing buffers --- sonoff/_changelog.ino | 5 +++- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_03_energy.ino | 30 ++++++++++----------- sonoff/xdrv_09_timers.ino | 4 +-- sonoff/xdrv_10_rules.ino | 2 +- sonoff/xdrv_11_knx.ino | 2 +- sonoff/xsns_01_counter.ino | 2 +- sonoff/xsns_04_snfsc.ino | 6 ++--- sonoff/xsns_05_ds18b20.ino | 3 +-- sonoff/xsns_05_ds18x20.ino | 3 +-- sonoff/xsns_05_ds18x20_legacy.ino | 2 +- sonoff/xsns_06_dht.ino | 5 ++-- sonoff/xsns_07_sht1x.ino | 5 ++-- sonoff/xsns_08_htu21.ino | 5 ++-- sonoff/xsns_09_bmp.ino | 38 +++++++++++++------------- sonoff/xsns_11_veml6070.ino | 6 ++--- sonoff/xsns_13_ina219.ino | 7 +++-- sonoff/xsns_14_sht3x.ino | 4 +-- sonoff/xsns_15_mhz19.ino | 2 +- sonoff/xsns_17_senseair.ino | 4 +-- sonoff/xsns_19_mgs.ino | 2 +- sonoff/xsns_20_novasds.ino | 4 +-- sonoff/xsns_22_sr04.ino | 3 +-- sonoff/xsns_23_sdm120.ino | 45 +++++++++++++++---------------- sonoff/xsns_25_sdm630.ino | 33 +++++++++++------------ sonoff/xsns_26_lm75ad.ino | 3 +-- sonoff/xsns_32_mpu6050.ino | 14 +++++----- sonoff/xsns_34_hx711.ino | 9 +++---- sonoff/xsns_35_tx20.ino | 9 +++---- sonoff/xsns_37_rfsensor.ino | 23 ++++++++-------- sonoff/xsns_38_az7798.ino | 3 ++- 31 files changed, 137 insertions(+), 148 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 159f434d4..e1414882a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.0.1 20181217 +/* 6.4.0.2 20181221 + * Fix possible dtostrf buffer overflows by increasing buffers + * + * 6.4.0.1 20181217 * Add support for AZ-Instrument 7798 CO2 meter/datalogger (#4672) * Change RAM usage BMP/BME I2C sensors * Fix wifi strongest signal detection (#4704) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 1ed638d75..c1c974eaf 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040001 +#define VERSION 0x06040002 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 1c54c12e5..b97c53fc2 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -402,12 +402,11 @@ boolean EnergyCommand(void) break; } } - char energy_yesterday_chr[10]; - char energy_daily_chr[10]; - char energy_total_chr[10]; - + char energy_total_chr[33]; dtostrfd(energy_total, Settings.flag2.energy_resolution, energy_total_chr); + char energy_daily_chr[33]; dtostrfd(energy_daily, Settings.flag2.energy_resolution, energy_daily_chr); + char energy_yesterday_chr[33]; dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s}}"), @@ -549,18 +548,6 @@ const char HTTP_ENERGY_SNS4[] PROGMEM = "%s" void EnergyShow(boolean json) { - char voltage_chr[10]; - char current_chr[10]; - char active_power_chr[10]; - char apparent_power_chr[10]; - char reactive_power_chr[10]; - char power_factor_chr[10]; - char frequency_chr[10]; - char energy_daily_chr[10]; - char energy_period_chr[10]; - char energy_yesterday_chr[10]; - char energy_total_chr[10]; - char speriod[20]; char sfrequency[20]; @@ -568,6 +555,10 @@ void EnergyShow(boolean json) float power_factor = energy_power_factor; + char apparent_power_chr[33]; + char reactive_power_chr[33]; + char power_factor_chr[33]; + char frequency_chr[33]; if (!energy_type_dc) { float apparent_power = energy_apparent_power; if (isnan(apparent_power)) { @@ -602,14 +593,21 @@ void EnergyShow(boolean json) } } + char voltage_chr[33]; dtostrfd(energy_voltage, Settings.flag2.voltage_resolution, voltage_chr); + char current_chr[33]; dtostrfd(energy_current, Settings.flag2.current_resolution, current_chr); + char active_power_chr[33]; dtostrfd(energy_active_power, Settings.flag2.wattage_resolution, active_power_chr); + char energy_daily_chr[33]; dtostrfd(energy_daily, Settings.flag2.energy_resolution, energy_daily_chr); + char energy_yesterday_chr[33]; dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); + char energy_total_chr[33]; dtostrfd(energy_total, Settings.flag2.energy_resolution, energy_total_chr); float energy = 0; + char energy_period_chr[33]; if (show_energy_period) { if (energy_period) energy = (float)(energy_kWhtoday - energy_period) / 100; energy_period = energy_kWhtoday; diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index fb7c2cef5..8273201d5 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -488,7 +488,7 @@ boolean TimerCommand(void) if (XdrvMailbox.data_len) { Settings.longitude = (int)(CharToDouble(XdrvMailbox.data) *1000000); } - char lbuff[32]; + char lbuff[33]; dtostrfd(((double)Settings.longitude) /1000000, 6, lbuff); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, lbuff); } @@ -496,7 +496,7 @@ boolean TimerCommand(void) if (XdrvMailbox.data_len) { Settings.latitude = (int)(CharToDouble(XdrvMailbox.data) *1000000); } - char lbuff[32]; + char lbuff[33]; dtostrfd(((double)Settings.latitude) /1000000, 6, lbuff); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, lbuff); } diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 0a06fe149..c9d880128 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -94,7 +94,7 @@ uint8_t rules_trigger_count[MAX_RULE_SETS] = { 0 }; uint8_t rules_teleperiod = 0; char event_data[100]; -char vars[MAX_RULE_VARS][10] = { 0 }; +char vars[MAX_RULE_VARS][33] = { 0 }; /*******************************************************************************************/ diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 665583767..9095b4efc 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -551,7 +551,7 @@ void KNX_CB_Action(message_t const &msg, void *arg) device_parameters_t *chan = (device_parameters_t *)arg; if (!(Settings.flag.knx_enabled)) { return; } - char tempchar[25]; + char tempchar[33]; if (msg.data_len == 1) { // COMMAND diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index 4f3b7d0f4..6b501d49f 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -93,12 +93,12 @@ const char HTTP_SNS_COUNTER[] PROGMEM = void CounterShow(boolean json) { char stemp[10]; - char counter[16]; byte dsxflg = 0; byte header = 0; for (byte i = 0; i < MAX_COUNTERS; i++) { if (pin[GPIO_CNTR1 +i] < 99) { + char counter[33]; if (bitRead(Settings.pulse_counter_type, i)) { dtostrfd((double)RtcSettings.pulse_counter[i] / 1000000, 6, counter); } else { diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index d31f6b5bb..d3329e3e5 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -113,12 +113,12 @@ const char HTTP_SNS_SCPLUS[] PROGMEM = void SonoffScShow(boolean json) { if (sc_value[0] > 0) { - char temperature[10]; - char humidity[10]; - float t = ConvertTemp(sc_value[1]); float h = sc_value[0]; + + char temperature[33]; dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; dtostrfd(h, Settings.flag2.humidity_resolution, humidity); if (json) { diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index 864e03f51..dfd4394dd 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -190,8 +190,7 @@ void Ds18b20EverySecond(void) void Ds18b20Show(boolean json) { if (ds18b20_valid) { // Check for valid temperature - char temperature[10]; - + char temperature[33]; dtostrfd(ds18b20_temperature, Settings.flag2.temperature_resolution, temperature); if(json) { snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMP, mqtt_data, ds18b20_types, temperature); diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index 09f656730..1061df86d 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -424,12 +424,11 @@ void Ds18x20EverySecond(void) void Ds18x20Show(boolean json) { - char temperature[10]; - for (uint8_t i = 0; i < ds18x20_sensors; i++) { uint8_t index = ds18x20_sensor[i].index; if (ds18x20_sensor[index].valid) { // Check for valid temperature + char temperature[33]; dtostrfd(ds18x20_sensor[index].temperature, Settings.flag2.temperature_resolution, temperature); Ds18x20Name(i); diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index dda92f831..5a89a0abe 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -170,7 +170,6 @@ void Ds18x20Type(uint8_t sensor) void Ds18x20Show(boolean json) { - char temperature[10]; char stemp[10]; float t; @@ -178,6 +177,7 @@ void Ds18x20Show(boolean json) for (byte i = 0; i < Ds18x20Sensors(); i++) { if (Ds18x20Read(i, t)) { // Check if read failed Ds18x20Type(i); + char temperature[33]; dtostrfd(t, Settings.flag2.temperature_resolution, temperature); if (json) { diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index fa91e1f9b..72f94edd7 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -207,11 +207,10 @@ void DhtEverySecond(void) void DhtShow(boolean json) { - char temperature[10]; - char humidity[10]; - for (byte i = 0; i < dht_sensors; i++) { + char temperature[33]; dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); if (json) { diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index fdb06328a..0bf2d774c 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -188,10 +188,9 @@ void ShtEverySecond(void) void ShtShow(boolean json) { if (sht_valid) { - char temperature[10]; - char humidity[10]; - + char temperature[33]; dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity); if (json) { diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index 87332287a..3e22c17f3 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -249,10 +249,9 @@ void HtuEverySecond(void) void HtuShow(boolean json) { if (htu_valid) { - char temperature[10]; - char humidity[10]; - + char temperature[33]; dtostrfd(htu_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; dtostrfd(htu_humidity, Settings.flag2.humidity_resolution, humidity); if (json) { diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index f5767a246..6023ba5cc 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -46,15 +46,15 @@ const char kBmpTypes[] PROGMEM = "BMP180|BMP280|BME280|BME680"; typedef struct { uint8_t bmp_address; // I2C bus address char bmp_name[7]; // Sensor name - "BMPXXX" - uint8_t bmp_type = 0; - uint8_t bmp_model = 0; + uint8_t bmp_type; + uint8_t bmp_model; #ifdef USE_BME680 - uint8_t bme680_state = 0; - float bmp_gas_resistance = 0.0; + uint8_t bme680_state; + float bmp_gas_resistance; #endif // USE_BME680 - float bmp_temperature = 0.0; - float bmp_pressure = 0.0; - float bmp_humidity = 0.0; + float bmp_temperature; + float bmp_pressure; + float bmp_humidity; } bmp_sensors_t; uint8_t bmp_addresses[] = { BMP_ADDR1, BMP_ADDR2 }; @@ -448,10 +448,12 @@ void BmpDetect(void) { if (bmp_count) return; + int bmp_sensor_size = BMP_MAX_SENSORS * sizeof(bmp_sensors_t); if (!bmp_sensors) { - bmp_sensors = (bmp_sensors_t*)malloc(BMP_MAX_SENSORS * sizeof(bmp_sensors_t)); + bmp_sensors = (bmp_sensors_t*)malloc(bmp_sensor_size); } if (!bmp_sensors) { return; } + memset(bmp_sensors, 0, bmp_sensor_size); // Init defaults to 0 for (byte i = 0; i < BMP_MAX_SENSORS; i++) { uint8_t bmp_type = I2cRead8(bmp_addresses[i], BMP_REGISTER_CHIPID); @@ -530,12 +532,6 @@ void BmpShow(boolean json) for (byte bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { if (bmp_sensors[bmp_idx].bmp_type) { float bmp_sealevel = 0.0; - char temperature[10]; - char pressure[10]; - char sea_pressure[10]; - char humidity[10]; - char name[10]; - if (bmp_sensors[bmp_idx].bmp_pressure != 0.0) { bmp_sealevel = (bmp_sensors[bmp_idx].bmp_pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; bmp_sealevel = ConvertPressure(bmp_sealevel); @@ -543,17 +539,22 @@ void BmpShow(boolean json) float bmp_temperature = ConvertTemp(bmp_sensors[bmp_idx].bmp_temperature); float bmp_pressure = ConvertPressure(bmp_sensors[bmp_idx].bmp_pressure); + char name[10]; snprintf(name, sizeof(name), bmp_sensors[bmp_idx].bmp_name); if (bmp_count > 1) { snprintf_P(name, sizeof(name), PSTR("%s-%02X"), name, bmp_sensors[bmp_idx].bmp_address); // BMXXXX-XX } + char temperature[33]; dtostrfd(bmp_temperature, Settings.flag2.temperature_resolution, temperature); + char pressure[33]; dtostrfd(bmp_pressure, Settings.flag2.pressure_resolution, pressure); + char sea_pressure[33]; dtostrfd(bmp_sealevel, Settings.flag2.pressure_resolution, sea_pressure); + char humidity[33]; dtostrfd(bmp_sensors[bmp_idx].bmp_humidity, Settings.flag2.humidity_resolution, humidity); #ifdef USE_BME680 - char gas_resistance[10]; + char gas_resistance[33]; dtostrfd(bmp_sensors[bmp_idx].bmp_gas_resistance, 2, gas_resistance); #endif // USE_BME680 @@ -566,17 +567,14 @@ void BmpShow(boolean json) char json_gas[40]; snprintf_P(json_gas, sizeof(json_gas), PSTR(",\"" D_JSON_GAS "\":%s"), gas_resistance); - snprintf_P(mqtt_data, - sizeof(mqtt_data), - PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), mqtt_data, name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : "", - (bmp_sensors[bmp_idx].bmp_model >= 3) ? json_gas : "" - ); + (bmp_sensors[bmp_idx].bmp_model >= 3) ? json_gas : ""); #else snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), mqtt_data, name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index 590f61300..0177fcc63 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -273,12 +273,12 @@ double Veml6070UvPower(double uvrisk) void Veml6070Show(boolean json) { if (veml6070_type) { - char str_uvlevel[6]; // e.g. 99999 inc = UVLevel - char str_uvrisk[6]; // e.g. 25.99 text = UvIndex - char str_uvpower[6]; // e.g. 0.399 W/m² = UvPower // convert double values to string + char str_uvlevel[33]; // e.g. 99999 inc = UVLevel dtostrfd((double)uvlevel, 0, str_uvlevel); + char str_uvrisk[33]; // e.g. 25.99 text = UvIndex dtostrfd(uvrisk, 2, str_uvrisk); + char str_uvpower[33]; // e.g. 0.399 W/m² = UvPower dtostrfd(uvpower, 3, str_uvpower); if (json) { #ifdef USE_VEML6070_SHOW_RAW diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index 2ca2f0288..ae5999a7e 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -232,13 +232,12 @@ const char HTTP_SNS_INA219_DATA[] PROGMEM = "%s" void Ina219Show(boolean json) { if (ina219_valid) { - char voltage[10]; - char current[10]; - char power[10]; - float fpower = ina219_voltage * ina219_current; + char voltage[33]; dtostrfd(ina219_voltage, Settings.flag2.voltage_resolution, voltage); + char power[33]; dtostrfd(fpower, Settings.flag2.wattage_resolution, power); + char current[33]; dtostrfd(ina219_current, Settings.flag2.current_resolution, current); if (json) { diff --git a/sonoff/xsns_14_sht3x.ino b/sonoff/xsns_14_sht3x.ino index 84bc86be8..6738b866a 100755 --- a/sonoff/xsns_14_sht3x.ino +++ b/sonoff/xsns_14_sht3x.ino @@ -98,15 +98,15 @@ void Sht3xShow(boolean json) if (sht3x_count) { float t; float h; - char temperature[10]; - char humidity[10]; char types[11]; for (byte i = 0; i < sht3x_count; i++) { if (Sht3xRead(t, h, sht3x_sensors[i].address)) { if (0 == i) { SetGlobalValues(t, h); } + char temperature[33]; dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; dtostrfd(h, Settings.flag2.humidity_resolution, humidity); snprintf_P(types, sizeof(types), PSTR("%s-0x%02X"), sht3x_sensors[i].types, sht3x_sensors[i].address); // "SHT3X-0xXX" diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 523dd3a66..968c0d021 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -322,7 +322,7 @@ void MhzInit(void) void MhzShow(boolean json) { - char temperature[10]; + char temperature[33]; dtostrfd(mhz_temperature, Settings.flag2.temperature_resolution, temperature); GetTextIndexed(mhz_types, sizeof(mhz_types), mhz_type -1, kMhzTypes); diff --git a/sonoff/xsns_17_senseair.ino b/sonoff/xsns_17_senseair.ino index 04360457f..967563972 100644 --- a/sonoff/xsns_17_senseair.ino +++ b/sonoff/xsns_17_senseair.ino @@ -147,9 +147,9 @@ void SenseairInit(void) void SenseairShow(boolean json) { - char temperature[10]; - char humidity[10]; + char temperature[33]; dtostrfd(senseair_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; dtostrfd(senseair_humidity, Settings.flag2.temperature_resolution, humidity); GetTextIndexed(senseair_types, sizeof(senseair_types), senseair_type -1, kSenseairTypes); diff --git a/sonoff/xsns_19_mgs.ino b/sonoff/xsns_19_mgs.ino index a9fdf7d9e..36ce969f7 100644 --- a/sonoff/xsns_19_mgs.ino +++ b/sonoff/xsns_19_mgs.ino @@ -63,7 +63,7 @@ const char HTTP_MGS_GAS[] PROGMEM = "%s{s}MGS %s{m}%s " D_UNIT_PARTS_PER_MILLION void MGSShow(boolean json) { - char buffer[25]; + char buffer[33]; if (json) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MGS\":{\"NH3\":%s"), mqtt_data, measure_gas(NH3, buffer)); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"CO\":%s"), mqtt_data, measure_gas(CO, buffer)); diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 909711472..dfb08ac5a 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -189,11 +189,11 @@ const char HTTP_SDS0X1_SNS[] PROGMEM = "%s" void NovaSdsShow(boolean json) { if (novasds_valid) { - char pm10[10]; - char pm2_5[10]; float pm10f = (float)(novasds_data.pm100) / 10.0f; float pm2_5f = (float)(novasds_data.pm25) / 10.0f; + char pm10[33]; dtostrfd(pm10f, 1, pm10); + char pm2_5[33]; dtostrfd(pm2_5f, 1, pm2_5); if (json) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), mqtt_data, pm2_5, pm10); diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index 77ea5e829..0278011e1 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -51,8 +51,7 @@ void Sr04Show(boolean json) distance = (real64_t)(sonar->ping_median(5))/ US_ROUNDTRIP_CM; if (distance != 0) { // Check if read failed - char distance_chr[10]; - + char distance_chr[33]; dtostrfd(distance, 3, distance_chr); if(json) { diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino index 7ec23d55d..9f27927e8 100644 --- a/sonoff/xsns_23_sdm120.ino +++ b/sonoff/xsns_23_sdm120.ino @@ -203,28 +203,28 @@ void SDM120250ms(void) // Every 250 mSec #ifdef USE_SDM220 case 8: sdm120_phase_angle = value; - break; - + break; + case 9: sdm120_import_active = value; - break; + break; case 10: sdm120_export_active = value; - break; + break; case 11: sdm120_import_reactive = value; - break; + break; case 12: sdm120_export_reactive = value; - break; + break; case 13: sdm120_total_reactive = value; - break; -#endif // USE_SDM220 + break; +#endif // USE_SDM220 } // end switch sdm120_read_state++; @@ -283,35 +283,34 @@ const char HTTP_SNS_SDM120_DATA[] PROGMEM = "%s" void SDM120Show(boolean json) { - char voltage[10]; - char current[10]; - char active_power[10]; - char apparent_power[10]; - char reactive_power[10]; - char power_factor[10]; - char frequency[10]; - char energy_total[10]; - char phase_angle[10]; - char import_active[10]; - char export_active[10]; - char import_reactive[10]; - char export_reactive[10]; - char total_reactive[10]; - + char voltage[33]; dtostrfd(sdm120_voltage, Settings.flag2.voltage_resolution, voltage); + char current[33]; dtostrfd(sdm120_current, Settings.flag2.current_resolution, current); + char active_power[33]; dtostrfd(sdm120_active_power, Settings.flag2.wattage_resolution, active_power); + char apparent_power[33]; dtostrfd(sdm120_apparent_power, Settings.flag2.wattage_resolution, apparent_power); + char reactive_power[33]; dtostrfd(sdm120_reactive_power, Settings.flag2.wattage_resolution, reactive_power); + char power_factor[33]; dtostrfd(sdm120_power_factor, 2, power_factor); + char frequency[33]; dtostrfd(sdm120_frequency, Settings.flag2.frequency_resolution, frequency); + char energy_total[33]; dtostrfd(sdm120_energy_total, Settings.flag2.energy_resolution, energy_total); #ifdef USE_SDM220 + char phase_angle[33]; dtostrfd(sdm120_phase_angle, 2, phase_angle); + char import_active[33]; dtostrfd(sdm120_import_active, Settings.flag2.wattage_resolution, import_active); + char export_active[33]; dtostrfd(sdm120_export_active, Settings.flag2.wattage_resolution, export_active); + char import_reactive[33]; dtostrfd(sdm120_import_reactive,Settings.flag2.wattage_resolution, import_reactive); + char export_reactive[33]; dtostrfd(sdm120_export_reactive,Settings.flag2.wattage_resolution, export_reactive); + char total_reactive[33]; dtostrfd(sdm120_total_reactive, Settings.flag2.wattage_resolution, total_reactive); #endif // USE_SDM220 if (json) { diff --git a/sonoff/xsns_25_sdm630.ino b/sonoff/xsns_25_sdm630.ino index 39614efc5..9060444b3 100644 --- a/sonoff/xsns_25_sdm630.ino +++ b/sonoff/xsns_25_sdm630.ino @@ -269,38 +269,37 @@ const char HTTP_SNS_SDM630_DATA[] PROGMEM = "%s" void SDM630Show(boolean json) { - char voltage_l1[10]; - char voltage_l2[10]; - char voltage_l3[10]; - char current_l1[10]; - char current_l2[10]; - char current_l3[10]; - char active_power_l1[10]; - char active_power_l2[10]; - char active_power_l3[10]; - char reactive_power_l1[10]; - char reactive_power_l2[10]; - char reactive_power_l3[10]; - char power_factor_l1[10]; - char power_factor_l2[10]; - char power_factor_l3[10]; - char energy_total[10]; - + char voltage_l1[33]; dtostrfd(sdm630_voltage[0], Settings.flag2.voltage_resolution, voltage_l1); + char voltage_l2[33]; dtostrfd(sdm630_voltage[1], Settings.flag2.voltage_resolution, voltage_l2); + char voltage_l3[33]; dtostrfd(sdm630_voltage[2], Settings.flag2.voltage_resolution, voltage_l3); + char current_l1[33]; dtostrfd(sdm630_current[0], Settings.flag2.current_resolution, current_l1); + char current_l2[33]; dtostrfd(sdm630_current[1], Settings.flag2.current_resolution, current_l2); + char current_l3[33]; dtostrfd(sdm630_current[2], Settings.flag2.current_resolution, current_l3); + char active_power_l1[33]; dtostrfd(sdm630_active_power[0], Settings.flag2.wattage_resolution, active_power_l1); + char active_power_l2[33]; dtostrfd(sdm630_active_power[1], Settings.flag2.wattage_resolution, active_power_l2); + char active_power_l3[33]; dtostrfd(sdm630_active_power[2], Settings.flag2.wattage_resolution, active_power_l3); + char reactive_power_l1[33]; dtostrfd(sdm630_reactive_power[0], Settings.flag2.wattage_resolution, reactive_power_l1); + char reactive_power_l2[33]; dtostrfd(sdm630_reactive_power[1], Settings.flag2.wattage_resolution, reactive_power_l2); + char reactive_power_l3[33]; dtostrfd(sdm630_reactive_power[2], Settings.flag2.wattage_resolution, reactive_power_l3); + char power_factor_l1[33]; dtostrfd(sdm630_power_factor[0], 2, power_factor_l1); + char power_factor_l2[33]; dtostrfd(sdm630_power_factor[1], 2, power_factor_l2); + char power_factor_l3[33]; dtostrfd(sdm630_power_factor[2], 2, power_factor_l3); + char energy_total[33]; dtostrfd(sdm630_energy_total, Settings.flag2.energy_resolution, energy_total); if (json) { diff --git a/sonoff/xsns_26_lm75ad.ino b/sonoff/xsns_26_lm75ad.ino index ba2f39b16..3b548fa8f 100644 --- a/sonoff/xsns_26_lm75ad.ino +++ b/sonoff/xsns_26_lm75ad.ino @@ -81,9 +81,8 @@ float LM75ADGetTemp(void) { void LM75ADShow(boolean json) { if (lm75ad_type) { - char temperature[10]; - float t = LM75ADGetTemp(); + char temperature[33]; dtostrfd(t, Settings.flag2.temperature_resolution, temperature); if (json) { diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index b80366194..8fbdfc6f3 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -177,19 +177,19 @@ void MPU_6050Show(boolean json) MPU_6050PerformReading(); double tempConv = (MPU_6050_temperature / 340.0 + 35.53); - char temperature[10]; + char temperature[33]; dtostrfd(tempConv, Settings.flag2.temperature_resolution, temperature); - char axis_ax[10]; + char axis_ax[33]; dtostrfd(MPU_6050_ax, Settings.flag2.axis_resolution, axis_ax); - char axis_ay[10]; + char axis_ay[33]; dtostrfd(MPU_6050_ay, Settings.flag2.axis_resolution, axis_ay); - char axis_az[10]; + char axis_az[33]; dtostrfd(MPU_6050_az, Settings.flag2.axis_resolution, axis_az); - char axis_gx[10]; + char axis_gx[33]; dtostrfd(MPU_6050_gx, Settings.flag2.axis_resolution, axis_gx); - char axis_gy[10]; + char axis_gy[33]; dtostrfd(MPU_6050_gy, Settings.flag2.axis_resolution, axis_gy); - char axis_gz[10]; + char axis_gz[33]; dtostrfd(MPU_6050_gz, Settings.flag2.axis_resolution, axis_gz); if (json) { diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 400f0991e..c3f10ded9 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -204,7 +204,7 @@ bool HxCommand(void) } if (show_parms) { - char item[10]; + char item[33]; dtostrfd((float)Settings.weight_item / 10, 1, item); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" D_JSON_WEIGHT_ITEM "\":%s}}"), Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, item); @@ -331,7 +331,6 @@ const char HTTP_HX711_CAL[] PROGMEM = "%s" void HxShow(boolean json) { - char weight_chr[10]; char scount[30] = { 0 }; uint16_t count = 0; @@ -345,6 +344,7 @@ void HxShow(boolean json) } weight = (float)hx_weight / 1000; // kilograms } + char weight_chr[33]; dtostrfd(weight, Settings.flag2.weight_resolution, weight_chr); if (json) { @@ -452,10 +452,9 @@ void HxSaveSettings(void) void HxLogUpdates(void) { - char weigth_ref_chr[10]; - char weigth_item_chr[10]; - + char weigth_ref_chr[33]; dtostrfd((float)Settings.weight_reference / 1000, Settings.flag2.weight_resolution, weigth_ref_chr); + char weigth_item_chr[33]; dtostrfd((float)Settings.weight_item / 10000, 4, weigth_item_chr); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_JSON_WEIGHT_REF " %s, " D_JSON_WEIGHT_ITEM " %s"), diff --git a/sonoff/xsns_35_tx20.ino b/sonoff/xsns_35_tx20.ino index 8ab868b45..a198c766f 100644 --- a/sonoff/xsns_35_tx20.ino +++ b/sonoff/xsns_35_tx20.ino @@ -172,14 +172,13 @@ void Tx20Init(void) { void Tx20Show(boolean json) { - char wind_speed_string[10]; - char wind_speed_max_string[10]; - char wind_speed_avg_string[10]; - char wind_direction_string[4]; - + char wind_speed_string[33]; dtostrfd(tx20_wind_speed_kmh, 2, wind_speed_string); + char wind_speed_max_string[33]; dtostrfd(tx20_wind_speed_max, 2, wind_speed_max_string); + char wind_speed_avg_string[33]; dtostrfd(tx20_wind_speed_avg, 2, wind_speed_avg_string); + char wind_direction_string[4]; GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx20_wind_direction, kTx20Directions); if (json) { diff --git a/sonoff/xsns_37_rfsensor.ino b/sonoff/xsns_37_rfsensor.ino index 9c6ebb38b..efb864924 100644 --- a/sonoff/xsns_37_rfsensor.ino +++ b/sonoff/xsns_37_rfsensor.ino @@ -264,7 +264,7 @@ void RfSnsTheoV2Show(bool json) if (rfsns_theo_v2_t1[i].time) { char sensor[10]; snprintf_P(sensor, sizeof(sensor), PSTR("TV2T1C%d"), i +1); - char voltage[10]; + char voltage[33]; dtostrfd((float)rfsns_theo_v2_t1[i].volt / 10, 1, voltage); if (rfsns_theo_v2_t1[i].time < LocalTime() - RFSNS_VALID_WINDOW) { @@ -273,7 +273,7 @@ void RfSnsTheoV2Show(bool json) mqtt_data, sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage); } } else { - char temperature[10]; + char temperature[33]; dtostrfd(ConvertTemp((float)rfsns_theo_v2_t1[i].temp / 100), Settings.flag2.temperature_resolution, temperature); if (json) { @@ -301,7 +301,7 @@ void RfSnsTheoV2Show(bool json) if (rfsns_theo_v2_t2[i].time) { char sensor[10]; snprintf_P(sensor, sizeof(sensor), PSTR("TV2T2C%d"), i +1); - char voltage[10]; + char voltage[33]; dtostrfd((float)rfsns_theo_v2_t2[i].volt / 10, 1, voltage); if (rfsns_theo_v2_t2[i].time < LocalTime() - RFSNS_VALID_WINDOW) { @@ -311,10 +311,10 @@ void RfSnsTheoV2Show(bool json) } } else { float temp = ConvertTemp((float)rfsns_theo_v2_t2[i].temp / 100); - char temperature[10]; - dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); float humi = (float)rfsns_theo_v2_t2[i].hum / 100; - char humidity[10]; + char temperature[33]; + dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); if (json) { @@ -559,16 +559,16 @@ void RfSnsAlectoV2Show(bool json) } } else { float temp = ConvertTemp(rfsns_alecto_v2->temp); - char temperature[10]; + char temperature[33]; dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); float humi = (float)rfsns_alecto_v2->humi; - char humidity[10]; + char humidity[33]; dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); - char rain[10]; + char rain[33]; dtostrfd(rfsns_alecto_v2->rain, 2, rain); - char wind[10]; + char wind[33]; dtostrfd(rfsns_alecto_v2->wind, 2, wind); - char gust[10]; + char gust[33]; dtostrfd(rfsns_alecto_v2->gust, 2, gust); char wdir[4]; char direction[20]; @@ -607,6 +607,7 @@ void RfSnsInit(void) { rfsns_raw_signal = (raw_signal_t*)(malloc(sizeof(raw_signal_t))); if (rfsns_raw_signal) { + memset(rfsns_raw_signal, 0, sizeof(raw_signal_t)); // Init defaults to 0 #ifdef USE_THEO_V2 RfSnsInitTheoV2(); #endif diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino index 6491be885..f909bb061 100644 --- a/sonoff/xsns_38_az7798.ino +++ b/sonoff/xsns_38_az7798.ino @@ -254,8 +254,9 @@ void AzInit(void) void AzShow(boolean json) { - char temperature[10], humidity[10]; + char temperature[33]; dtostrfd(az_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; dtostrfd(az_humidity, Settings.flag2.humidity_resolution, humidity); if (json) { From 893f64cfb6595ea80d427a25ba5e2fcc84be3883 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 21 Dec 2018 17:56:09 +0100 Subject: [PATCH 0750/2222] Still need patched PWM for core 2.5.0 Still need patched PWM for core 2.5.0 --- sonoff/core_esp8266_timer.c | 6 ++++-- sonoff/core_esp8266_wiring_digital.c | 6 ++++-- sonoff/core_esp8266_wiring_pwm.c | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/sonoff/core_esp8266_timer.c b/sonoff/core_esp8266_timer.c index fdc7342e5..81c3a76e0 100644 --- a/sonoff/core_esp8266_timer.c +++ b/sonoff/core_esp8266_timer.c @@ -18,8 +18,10 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +// Use PWM from core 2.4.0 as all other version produce LED flickering when settings are saved to flash. Still true for 2.5.0 //#include -//#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 +//#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) //#warning **** Tasmota is using v2.4.0 timer.c as planned **** #include "wiring_private.h" @@ -106,4 +108,4 @@ void ICACHE_RAM_ATTR timer0_detachInterrupt(void) { ETS_CCOMPARE0_DISABLE(); } -//#endif // ARDUINO_ESP8266_RELEASE_2_3_0 +//#endif // ARDUINO_ESP8266_RELEASE diff --git a/sonoff/core_esp8266_wiring_digital.c b/sonoff/core_esp8266_wiring_digital.c index b51a85aad..33de53c75 100644 --- a/sonoff/core_esp8266_wiring_digital.c +++ b/sonoff/core_esp8266_wiring_digital.c @@ -18,8 +18,10 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +// Use PWM from core 2.4.0 as all other version produce LED flickering when settings are saved to flash. Still true for 2.5.0 //#include -//#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 +//#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) //#warning **** Tasmota is using v2.4.0 wiring_digital.c as planned **** #define ARDUINO_MAIN @@ -212,4 +214,4 @@ extern int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead") extern void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterrupt"))); extern void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt"))); -//#endif // ARDUINO_ESP8266_RELEASE_2_3_0 +//#endif // ARDUINO_ESP8266_RELEASE diff --git a/sonoff/core_esp8266_wiring_pwm.c b/sonoff/core_esp8266_wiring_pwm.c index 92d73a4b7..780190059 100644 --- a/sonoff/core_esp8266_wiring_pwm.c +++ b/sonoff/core_esp8266_wiring_pwm.c @@ -18,8 +18,10 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +// Use PWM from core 2.4.0 as all other version produce flicker when settings are saved to flash. Still true for 2.5.0 //#include -//#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 +//#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) //#warning **** Tasmota is using v2.4.0 wiring_pwm.c as planned **** #include "wiring_private.h" @@ -224,4 +226,4 @@ extern void analogWrite(uint8_t pin, int val) __attribute__ ((weak, alias("__ana extern void analogWriteFreq(uint32_t freq) __attribute__ ((weak, alias("__analogWriteFreq"))); extern void analogWriteRange(uint32_t range) __attribute__ ((weak, alias("__analogWriteRange"))); -//#endif // ARDUINO_ESP8266_RELEASE_2_3_0 +//#endif // ARDUINO_ESP8266_RELEASE From d722387344de3294a1567c4f3c6abaca105119aa Mon Sep 17 00:00:00 2001 From: Frank Meies <19324766+fmeies@users.noreply.github.com> Date: Fri, 21 Dec 2018 22:49:46 +0100 Subject: [PATCH 0751/2222] Check for core version when enabling tls ca cert Signed-off-by: Frank Meies <19324766+fmeies@users.noreply.github.com> --- sonoff/my_user_config.h | 152 +++++++++++++++++++++------------------- sonoff/xdrv_02_mqtt.ino | 6 +- 2 files changed, 81 insertions(+), 77 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 884c47694..c4c03d43f 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -248,80 +248,80 @@ // -- MQTT - TLS ---------------------------------- // !!! TLS uses a LOT OF MEMORY so be careful to enable other options at the same time !!! //#define USE_MQTT_TLS // Use TLS for MQTT connection (+53k code, +15k mem) -//#define USE_MQTT_TLS_ROOTCERT -#define MQTT_TLS_ROOT_CA_LENGTH 846 // Letsencrypt -#define MQTT_TLS_ROOT_CA { \ - 0x30, 0x82, 0x03, 0x4a, 0x30, 0x82, 0x02, 0x32, 0xa0, 0x03, 0x02, 0x01, \ - 0x02, 0x02, 0x10, 0x44, 0xaf, 0xb0, 0x80, 0xd6, 0xa3, 0x27, 0xba, 0x89, \ - 0x30, 0x39, 0x86, 0x2e, 0xf8, 0x40, 0x6b, 0x30, 0x0d, 0x06, 0x09, 0x2a, \ - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3f, \ - 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 0x44, \ - 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, \ - 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, \ - 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ - 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, \ - 0x20, 0x58, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x39, 0x33, \ - 0x30, 0x32, 0x31, 0x31, 0x32, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x31, \ - 0x30, 0x39, 0x33, 0x30, 0x31, 0x34, 0x30, 0x31, 0x31, 0x35, 0x5a, 0x30, \ - 0x3f, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, \ - 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, \ - 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, \ - 0x43, 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, \ - 0x13, 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, \ - 0x41, 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, \ - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, \ - 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, \ - 0x00, 0xdf, 0xaf, 0xe9, 0x97, 0x50, 0x08, 0x83, 0x57, 0xb4, 0xcc, 0x62, \ - 0x65, 0xf6, 0x90, 0x82, 0xec, 0xc7, 0xd3, 0x2c, 0x6b, 0x30, 0xca, 0x5b, \ - 0xec, 0xd9, 0xc3, 0x7d, 0xc7, 0x40, 0xc1, 0x18, 0x14, 0x8b, 0xe0, 0xe8, \ - 0x33, 0x76, 0x49, 0x2a, 0xe3, 0x3f, 0x21, 0x49, 0x93, 0xac, 0x4e, 0x0e, \ - 0xaf, 0x3e, 0x48, 0xcb, 0x65, 0xee, 0xfc, 0xd3, 0x21, 0x0f, 0x65, 0xd2, \ - 0x2a, 0xd9, 0x32, 0x8f, 0x8c, 0xe5, 0xf7, 0x77, 0xb0, 0x12, 0x7b, 0xb5, \ - 0x95, 0xc0, 0x89, 0xa3, 0xa9, 0xba, 0xed, 0x73, 0x2e, 0x7a, 0x0c, 0x06, \ - 0x32, 0x83, 0xa2, 0x7e, 0x8a, 0x14, 0x30, 0xcd, 0x11, 0xa0, 0xe1, 0x2a, \ - 0x38, 0xb9, 0x79, 0x0a, 0x31, 0xfd, 0x50, 0xbd, 0x80, 0x65, 0xdf, 0xb7, \ - 0x51, 0x63, 0x83, 0xc8, 0xe2, 0x88, 0x61, 0xea, 0x4b, 0x61, 0x81, 0xec, \ - 0x52, 0x6b, 0xb9, 0xa2, 0xe2, 0x4b, 0x1a, 0x28, 0x9f, 0x48, 0xa3, 0x9e, \ - 0x0c, 0xda, 0x09, 0x8e, 0x3e, 0x17, 0x2e, 0x1e, 0xdd, 0x20, 0xdf, 0x5b, \ - 0xc6, 0x2a, 0x8a, 0xab, 0x2e, 0xbd, 0x70, 0xad, 0xc5, 0x0b, 0x1a, 0x25, \ - 0x90, 0x74, 0x72, 0xc5, 0x7b, 0x6a, 0xab, 0x34, 0xd6, 0x30, 0x89, 0xff, \ - 0xe5, 0x68, 0x13, 0x7b, 0x54, 0x0b, 0xc8, 0xd6, 0xae, 0xec, 0x5a, 0x9c, \ - 0x92, 0x1e, 0x3d, 0x64, 0xb3, 0x8c, 0xc6, 0xdf, 0xbf, 0xc9, 0x41, 0x70, \ - 0xec, 0x16, 0x72, 0xd5, 0x26, 0xec, 0x38, 0x55, 0x39, 0x43, 0xd0, 0xfc, \ - 0xfd, 0x18, 0x5c, 0x40, 0xf1, 0x97, 0xeb, 0xd5, 0x9a, 0x9b, 0x8d, 0x1d, \ - 0xba, 0xda, 0x25, 0xb9, 0xc6, 0xd8, 0xdf, 0xc1, 0x15, 0x02, 0x3a, 0xab, \ - 0xda, 0x6e, 0xf1, 0x3e, 0x2e, 0xf5, 0x5c, 0x08, 0x9c, 0x3c, 0xd6, 0x83, \ - 0x69, 0xe4, 0x10, 0x9b, 0x19, 0x2a, 0xb6, 0x29, 0x57, 0xe3, 0xe5, 0x3d, \ - 0x9b, 0x9f, 0xf0, 0x02, 0x5d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, \ - 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, \ - 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, \ - 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, \ - 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc4, 0xa7, \ - 0xb1, 0xa4, 0x7b, 0x2c, 0x71, 0xfa, 0xdb, 0xe1, 0x4b, 0x90, 0x75, 0xff, \ - 0xc4, 0x15, 0x60, 0x85, 0x89, 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, \ - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, \ - 0x01, 0x00, 0xa3, 0x1a, 0x2c, 0x9b, 0x17, 0x00, 0x5c, 0xa9, 0x1e, 0xee, \ - 0x28, 0x66, 0x37, 0x3a, 0xbf, 0x83, 0xc7, 0x3f, 0x4b, 0xc3, 0x09, 0xa0, \ - 0x95, 0x20, 0x5d, 0xe3, 0xd9, 0x59, 0x44, 0xd2, 0x3e, 0x0d, 0x3e, 0xbd, \ - 0x8a, 0x4b, 0xa0, 0x74, 0x1f, 0xce, 0x10, 0x82, 0x9c, 0x74, 0x1a, 0x1d, \ - 0x7e, 0x98, 0x1a, 0xdd, 0xcb, 0x13, 0x4b, 0xb3, 0x20, 0x44, 0xe4, 0x91, \ - 0xe9, 0xcc, 0xfc, 0x7d, 0xa5, 0xdb, 0x6a, 0xe5, 0xfe, 0xe6, 0xfd, 0xe0, \ - 0x4e, 0xdd, 0xb7, 0x00, 0x3a, 0xb5, 0x70, 0x49, 0xaf, 0xf2, 0xe5, 0xeb, \ - 0x02, 0xf1, 0xd1, 0x02, 0x8b, 0x19, 0xcb, 0x94, 0x3a, 0x5e, 0x48, 0xc4, \ - 0x18, 0x1e, 0x58, 0x19, 0x5f, 0x1e, 0x02, 0x5a, 0xf0, 0x0c, 0xf1, 0xb1, \ - 0xad, 0xa9, 0xdc, 0x59, 0x86, 0x8b, 0x6e, 0xe9, 0x91, 0xf5, 0x86, 0xca, \ - 0xfa, 0xb9, 0x66, 0x33, 0xaa, 0x59, 0x5b, 0xce, 0xe2, 0xa7, 0x16, 0x73, \ - 0x47, 0xcb, 0x2b, 0xcc, 0x99, 0xb0, 0x37, 0x48, 0xcf, 0xe3, 0x56, 0x4b, \ - 0xf5, 0xcf, 0x0f, 0x0c, 0x72, 0x32, 0x87, 0xc6, 0xf0, 0x44, 0xbb, 0x53, \ - 0x72, 0x6d, 0x43, 0xf5, 0x26, 0x48, 0x9a, 0x52, 0x67, 0xb7, 0x58, 0xab, \ - 0xfe, 0x67, 0x76, 0x71, 0x78, 0xdb, 0x0d, 0xa2, 0x56, 0x14, 0x13, 0x39, \ - 0x24, 0x31, 0x85, 0xa2, 0xa8, 0x02, 0x5a, 0x30, 0x47, 0xe1, 0xdd, 0x50, \ - 0x07, 0xbc, 0x02, 0x09, 0x90, 0x00, 0xeb, 0x64, 0x63, 0x60, 0x9b, 0x16, \ - 0xbc, 0x88, 0xc9, 0x12, 0xe6, 0xd2, 0x7d, 0x91, 0x8b, 0xf9, 0x3d, 0x32, \ - 0x8d, 0x65, 0xb4, 0xe9, 0x7c, 0xb1, 0x57, 0x76, 0xea, 0xc5, 0xb6, 0x28, \ - 0x39, 0xbf, 0x15, 0x65, 0x1c, 0xc8, 0xf6, 0x77, 0x96, 0x6a, 0x0a, 0x8d, \ - 0x77, 0x0b, 0xd8, 0x91, 0x0b, 0x04, 0x8e, 0x07, 0xdb, 0x29, 0xb6, 0x0a, \ - 0xee, 0x9d, 0x82, 0x35, 0x35, 0x10 } + #define USE_MQTT_TLS_CA_CERT + #define MQTT_TLS_CA_CERT_LENGTH 846 // Letsencrypt + #define MQTT_TLS_CA_CERT { \ + 0x30, 0x82, 0x03, 0x4a, 0x30, 0x82, 0x02, 0x32, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x10, 0x44, 0xaf, 0xb0, 0x80, 0xd6, 0xa3, 0x27, 0xba, 0x89, \ + 0x30, 0x39, 0x86, 0x2e, 0xf8, 0x40, 0x6b, 0x30, 0x0d, 0x06, 0x09, 0x2a, \ + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3f, \ + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 0x44, \ + 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, \ + 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, \ + 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ + 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, \ + 0x20, 0x58, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x39, 0x33, \ + 0x30, 0x32, 0x31, 0x31, 0x32, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x31, \ + 0x30, 0x39, 0x33, 0x30, 0x31, 0x34, 0x30, 0x31, 0x31, 0x35, 0x5a, 0x30, \ + 0x3f, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, \ + 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, \ + 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, \ + 0x43, 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, \ + 0x13, 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, \ + 0x41, 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, \ + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, \ + 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, \ + 0x00, 0xdf, 0xaf, 0xe9, 0x97, 0x50, 0x08, 0x83, 0x57, 0xb4, 0xcc, 0x62, \ + 0x65, 0xf6, 0x90, 0x82, 0xec, 0xc7, 0xd3, 0x2c, 0x6b, 0x30, 0xca, 0x5b, \ + 0xec, 0xd9, 0xc3, 0x7d, 0xc7, 0x40, 0xc1, 0x18, 0x14, 0x8b, 0xe0, 0xe8, \ + 0x33, 0x76, 0x49, 0x2a, 0xe3, 0x3f, 0x21, 0x49, 0x93, 0xac, 0x4e, 0x0e, \ + 0xaf, 0x3e, 0x48, 0xcb, 0x65, 0xee, 0xfc, 0xd3, 0x21, 0x0f, 0x65, 0xd2, \ + 0x2a, 0xd9, 0x32, 0x8f, 0x8c, 0xe5, 0xf7, 0x77, 0xb0, 0x12, 0x7b, 0xb5, \ + 0x95, 0xc0, 0x89, 0xa3, 0xa9, 0xba, 0xed, 0x73, 0x2e, 0x7a, 0x0c, 0x06, \ + 0x32, 0x83, 0xa2, 0x7e, 0x8a, 0x14, 0x30, 0xcd, 0x11, 0xa0, 0xe1, 0x2a, \ + 0x38, 0xb9, 0x79, 0x0a, 0x31, 0xfd, 0x50, 0xbd, 0x80, 0x65, 0xdf, 0xb7, \ + 0x51, 0x63, 0x83, 0xc8, 0xe2, 0x88, 0x61, 0xea, 0x4b, 0x61, 0x81, 0xec, \ + 0x52, 0x6b, 0xb9, 0xa2, 0xe2, 0x4b, 0x1a, 0x28, 0x9f, 0x48, 0xa3, 0x9e, \ + 0x0c, 0xda, 0x09, 0x8e, 0x3e, 0x17, 0x2e, 0x1e, 0xdd, 0x20, 0xdf, 0x5b, \ + 0xc6, 0x2a, 0x8a, 0xab, 0x2e, 0xbd, 0x70, 0xad, 0xc5, 0x0b, 0x1a, 0x25, \ + 0x90, 0x74, 0x72, 0xc5, 0x7b, 0x6a, 0xab, 0x34, 0xd6, 0x30, 0x89, 0xff, \ + 0xe5, 0x68, 0x13, 0x7b, 0x54, 0x0b, 0xc8, 0xd6, 0xae, 0xec, 0x5a, 0x9c, \ + 0x92, 0x1e, 0x3d, 0x64, 0xb3, 0x8c, 0xc6, 0xdf, 0xbf, 0xc9, 0x41, 0x70, \ + 0xec, 0x16, 0x72, 0xd5, 0x26, 0xec, 0x38, 0x55, 0x39, 0x43, 0xd0, 0xfc, \ + 0xfd, 0x18, 0x5c, 0x40, 0xf1, 0x97, 0xeb, 0xd5, 0x9a, 0x9b, 0x8d, 0x1d, \ + 0xba, 0xda, 0x25, 0xb9, 0xc6, 0xd8, 0xdf, 0xc1, 0x15, 0x02, 0x3a, 0xab, \ + 0xda, 0x6e, 0xf1, 0x3e, 0x2e, 0xf5, 0x5c, 0x08, 0x9c, 0x3c, 0xd6, 0x83, \ + 0x69, 0xe4, 0x10, 0x9b, 0x19, 0x2a, 0xb6, 0x29, 0x57, 0xe3, 0xe5, 0x3d, \ + 0x9b, 0x9f, 0xf0, 0x02, 0x5d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, \ + 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, \ + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, \ + 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, \ + 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc4, 0xa7, \ + 0xb1, 0xa4, 0x7b, 0x2c, 0x71, 0xfa, 0xdb, 0xe1, 0x4b, 0x90, 0x75, 0xff, \ + 0xc4, 0x15, 0x60, 0x85, 0x89, 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, \ + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, \ + 0x01, 0x00, 0xa3, 0x1a, 0x2c, 0x9b, 0x17, 0x00, 0x5c, 0xa9, 0x1e, 0xee, \ + 0x28, 0x66, 0x37, 0x3a, 0xbf, 0x83, 0xc7, 0x3f, 0x4b, 0xc3, 0x09, 0xa0, \ + 0x95, 0x20, 0x5d, 0xe3, 0xd9, 0x59, 0x44, 0xd2, 0x3e, 0x0d, 0x3e, 0xbd, \ + 0x8a, 0x4b, 0xa0, 0x74, 0x1f, 0xce, 0x10, 0x82, 0x9c, 0x74, 0x1a, 0x1d, \ + 0x7e, 0x98, 0x1a, 0xdd, 0xcb, 0x13, 0x4b, 0xb3, 0x20, 0x44, 0xe4, 0x91, \ + 0xe9, 0xcc, 0xfc, 0x7d, 0xa5, 0xdb, 0x6a, 0xe5, 0xfe, 0xe6, 0xfd, 0xe0, \ + 0x4e, 0xdd, 0xb7, 0x00, 0x3a, 0xb5, 0x70, 0x49, 0xaf, 0xf2, 0xe5, 0xeb, \ + 0x02, 0xf1, 0xd1, 0x02, 0x8b, 0x19, 0xcb, 0x94, 0x3a, 0x5e, 0x48, 0xc4, \ + 0x18, 0x1e, 0x58, 0x19, 0x5f, 0x1e, 0x02, 0x5a, 0xf0, 0x0c, 0xf1, 0xb1, \ + 0xad, 0xa9, 0xdc, 0x59, 0x86, 0x8b, 0x6e, 0xe9, 0x91, 0xf5, 0x86, 0xca, \ + 0xfa, 0xb9, 0x66, 0x33, 0xaa, 0x59, 0x5b, 0xce, 0xe2, 0xa7, 0x16, 0x73, \ + 0x47, 0xcb, 0x2b, 0xcc, 0x99, 0xb0, 0x37, 0x48, 0xcf, 0xe3, 0x56, 0x4b, \ + 0xf5, 0xcf, 0x0f, 0x0c, 0x72, 0x32, 0x87, 0xc6, 0xf0, 0x44, 0xbb, 0x53, \ + 0x72, 0x6d, 0x43, 0xf5, 0x26, 0x48, 0x9a, 0x52, 0x67, 0xb7, 0x58, 0xab, \ + 0xfe, 0x67, 0x76, 0x71, 0x78, 0xdb, 0x0d, 0xa2, 0x56, 0x14, 0x13, 0x39, \ + 0x24, 0x31, 0x85, 0xa2, 0xa8, 0x02, 0x5a, 0x30, 0x47, 0xe1, 0xdd, 0x50, \ + 0x07, 0xbc, 0x02, 0x09, 0x90, 0x00, 0xeb, 0x64, 0x63, 0x60, 0x9b, 0x16, \ + 0xbc, 0x88, 0xc9, 0x12, 0xe6, 0xd2, 0x7d, 0x91, 0x8b, 0xf9, 0x3d, 0x32, \ + 0x8d, 0x65, 0xb4, 0xe9, 0x7c, 0xb1, 0x57, 0x76, 0xea, 0xc5, 0xb6, 0x28, \ + 0x39, 0xbf, 0x15, 0x65, 0x1c, 0xc8, 0xf6, 0x77, 0x96, 0x6a, 0x0a, 0x8d, \ + 0x77, 0x0b, 0xd8, 0x91, 0x0b, 0x04, 0x8e, 0x07, 0xdb, 0x29, 0xb6, 0x0a, \ + 0xee, 0x9d, 0x82, 0x35, 0x35, 0x10 } // -- KNX IP Protocol ----------------------------- //#define USE_KNX // Enable KNX IP Protocol Support (+9.4k code, +3k7 mem) @@ -506,4 +506,8 @@ #error "Select either USE_MQTT_TLS or USE_WEBSERVER as there is just not enough memory to play with" #endif +#if defined(USE_MQTT_TLS_ROOTCERT) && defined(ARDUINO_ESP8266_RELEASE_2_3_0) + #error "USE_MQTT_TLS_ROOTCERT does not work with core version 2.3.0"" +#endif + #endif // _MY_USER_CONFIG_H_ diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index e072e9825..96d98e66e 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -467,9 +467,9 @@ boolean MqttCheckTls(void) Settings.mqtt_host, Settings.mqtt_port, mqtt_retry_counter); AddLog(LOG_LEVEL_DEBUG); } else { -#ifdef USE_MQTT_TLS_ROOTCERT - unsigned char tls_root_ca[] = MQTT_TLS_ROOT_CA; - if(EspClient.setCACert(tls_root_ca, MQTT_TLS_ROOT_CA_LENGTH)) { +#ifdef USE_MQTT_TLS_CA_CERT + unsigned char tls_ca_cert[] = MQTT_TLS_CA_CERT; + if(EspClient.setCACert(tls_ca_cert, MQTT_TLS_CA_CERT_LENGTH)) { if (EspClient.verifyCertChain(Settings.mqtt_host)) { AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "CA")); result = true; From 59056935f9c15daaeae2906acf1273c99e9b527b Mon Sep 17 00:00:00 2001 From: Frank Meies <19324766+fmeies@users.noreply.github.com> Date: Fri, 21 Dec 2018 22:54:42 +0100 Subject: [PATCH 0752/2222] Check for core version when enabling tls ca cert, changed names of defines Signed-off-by: Frank Meies <19324766+fmeies@users.noreply.github.com> --- sonoff/my_user_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index c4c03d43f..c2cadb513 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -506,8 +506,8 @@ #error "Select either USE_MQTT_TLS or USE_WEBSERVER as there is just not enough memory to play with" #endif -#if defined(USE_MQTT_TLS_ROOTCERT) && defined(ARDUINO_ESP8266_RELEASE_2_3_0) - #error "USE_MQTT_TLS_ROOTCERT does not work with core version 2.3.0"" +#if defined(USE_MQTT_TLS_CA_CERT) && defined(ARDUINO_ESP8266_RELEASE_2_3_0) + #error "USE_MQTT_TLS_CA_CERT does not work with core version 2.3.0"" #endif #endif // _MY_USER_CONFIG_H_ From fd965eba09302c0cb93968641d2584664f86d936 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 22 Dec 2018 13:15:55 +0100 Subject: [PATCH 0753/2222] Remove SetOption55 (hass_short_discovery_msg) --- sonoff/settings.h | 2 +- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_12_home_assistant.ino | 211 +++++++----------------------- 3 files changed, 48 insertions(+), 167 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index d18ab6886..4de813d18 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -68,7 +68,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t time_append_timezone : 1; // bit 2 (v6.2.1.2) uint32_t gui_hostname_ip : 1; // bit 3 (v6.2.1.20) uint32_t tuya_apply_o20 : 1; // bit 4 (v6.3.0.4) - uint32_t hass_short_discovery_msg : 1; // bit 5 (v6.3.0.7) + uint32_t spare5 : 1; uint32_t use_wifi_scan : 1; // bit 6 (v6.3.0.10) uint32_t use_wifi_rescan : 1; // bit 7 (v6.3.0.10) uint32_t receive_raw : 1; // bit 8 (v6.3.0.11) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index c1c974eaf..32b9dbd83 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040002 +#define VERSION 0x06040003 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 01c5eb60c..1e4f90e4d 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -21,100 +21,6 @@ #define XDRV_12 12 -const char HASS_DISCOVER_RELAY[] PROGMEM = - "{\"name\":\"%s\"," // dualr2 1 - "\"command_topic\":\"%s\"," // cmnd/dualr2/POWER2 - "\"state_topic\":\"%s\"," // stat/dualr2/RESULT (implies "\"optimistic\":\"false\",") - "\"value_template\":\"{{value_json.%s}}\"," // POWER2 - "\"payload_off\":\"%s\"," // OFF - "\"payload_on\":\"%s\"," // ON -// "\"optimistic\":\"false\"," // false is Hass default when state_topic is set - "\"availability_topic\":\"%s\"," // tele/dualr2/LWT - "\"payload_available\":\"" D_ONLINE "\"," // Online - "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline - -const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = - "{\"name\":\"%s\"," // dualr2 1 BTN - "\"state_topic\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") -// "\"value_template\":\"{{value_json.%s}}\"," // POWER2 - "\"payload_on\":\"%s\"," // TOGGLE / ON -// "\"optimistic\":\"false\"," // false is Hass default when state_topic is set - "\"availability_topic\":\"%s\"," // tele/dualr2/LWT - "\"payload_available\":\"" D_ONLINE "\"," // Online - "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline - -const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE[] PROGMEM = - "%s,\"off_delay\":1"; // Hass has no support for TOGGLE, fake it by resetting to OFF after 1s - -const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = - "%s,\"force_update\":true," // In ON/OFF case, enable force_update to make automations work - "\"payload_off\":\"%s\""; // OFF - -const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = - "%s,\"brightness_command_topic\":\"%s\"," // cmnd/led2/Dimmer - "\"brightness_state_topic\":\"%s\"," // stat/led2/RESULT - "\"brightness_scale\":100," // 100% - "\"on_command_type\":\"brightness\"," // power on (first), power on (last), no power on (brightness) - "\"brightness_value_template\":\"{{value_json." D_CMND_DIMMER "}}\""; - -const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = - "%s,\"rgb_command_topic\":\"%s2\"," // cmnd/led2/Color2 - "\"rgb_state_topic\":\"%s\"," // stat/led2/RESULT - "\"rgb_value_template\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; - -const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = - "%s,\"white_value_command_topic\":\"%s\"," // cmnd/led2/White - "\"white_value_state_topic\":\"%s\"," // stat/led2/RESULT - "\"white_value_scale\":100," - "\"white_value_template\":\"{{ value_json.Channel[3] }}\""; - -const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = - "%s,\"color_temp_command_topic\":\"%s\"," // cmnd/led2/CT - "\"color_temp_state_topic\":\"%s\"," // stat/led2/RESULT - "\"color_temp_value_template\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; - -const char HASS_DISCOVER_SENSOR[] PROGMEM = - "{\"name\":\"%s\"," // dualr2 1 BTN - "\"state_topic\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") - "\"availability_topic\":\"%s\"," // tele/dualr2/LWT - "\"payload_available\":\"" D_ONLINE "\"," // Online - "\"payload_not_available\":\"" D_OFFLINE "\""; // Offline - -const char HASS_DISCOVER_SENSOR_TEMP[] PROGMEM = - "%s,\"unit_of_measurement\":\"°%c\"," // °C / °F - "\"value_template\":\"{{value_json['%s'].Temperature}}\""; // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Temperature }} - -const char HASS_DISCOVER_SENSOR_HUM[] PROGMEM = - "%s,\"unit_of_measurement\":\"%%\"," // % - "\"value_template\":\"{{value_json['%s'].Humidity}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }} - "\"device_class\":\"humidity\""; // temperature / humidity - -const char HASS_DISCOVER_SENSOR_PRESS[] PROGMEM = - "%s,\"unit_of_measurement\":\"%s\"," // PressureUnit() setting - "\"value_template\":\"{{value_json['%s'].Pressure}}\"," // "BME280":{"Temperature":19.7,"Humidity":27.8,"Pressure":990.1} -> {{ value_json['BME280'].Pressure }} - "\"device_class\":\"pressure\""; // pressure - -//ENERGY -const char HASS_DISCOVER_SENSOR_KWH[] PROGMEM = - "%s,\"unit_of_measurement\":\"kWh\"," // kWh - "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Total/Yesterday/Today }} - -const char HASS_DISCOVER_SENSOR_WATT[] PROGMEM = - "%s,\"unit_of_measurement\":\"W\"," // W - "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].POWER }} - -const char HASS_DISCOVER_SENSOR_VOLTAGE[] PROGMEM = - "%s,\"unit_of_measurement\":\"V\"," // V - "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Voltage }} - -const char HASS_DISCOVER_SENSOR_AMPERE[] PROGMEM = - "%s,\"unit_of_measurement\":\"A\"," // A - "\"value_template\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Current }} - -const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = - "%s,\"unit_of_measurement\":\" \"," // " " As unit of measurement to get a value graph in Hass - "\"value_template\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} - const char HASS_DISCOVER_RELAY_SHORT[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 "\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2 @@ -290,66 +196,52 @@ void HAssAnnounceRelayLight(void) GetTopic_P(state_topic, TELE, mqtt_topic, D_RSLT_STATE); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); FindPrefix(command_topic, state_topic, prefix); - if (Settings.flag3.hass_short_discovery_msg) { - Shorten(&command_topic, prefix); - Shorten(&state_topic, prefix); - Shorten(&availability_topic, prefix); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_RELAY_SHORT:HASS_DISCOVER_RELAY, + Shorten(&command_topic, prefix); + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_RELAY_SHORT, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); if (is_light) { char *brightness_command_topic = stemp1; GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); - if (Settings.flag3.hass_short_discovery_msg) - Shorten(&brightness_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_DIMMER_SHORT:HASS_DISCOVER_LIGHT_DIMMER, - mqtt_data, brightness_command_topic, state_topic); + Shorten(&brightness_command_topic, prefix); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_DIMMER_SHORT, mqtt_data, brightness_command_topic, state_topic); if (light_subtype >= LST_RGB) { char *rgb_command_topic = stemp1; GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); - if (Settings.flag3.hass_short_discovery_msg) - Shorten(&rgb_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_COLOR_SHORT:HASS_DISCOVER_LIGHT_COLOR, - mqtt_data, rgb_command_topic, state_topic); + Shorten(&rgb_command_topic, prefix); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_COLOR_SHORT, mqtt_data, rgb_command_topic, state_topic); char *effect_command_topic = stemp1; GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); - if (Settings.flag3.hass_short_discovery_msg) { - Shorten(&effect_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_SCHEME_SHORT, mqtt_data, effect_command_topic, state_topic); - } + Shorten(&effect_command_topic, prefix); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_SCHEME_SHORT, mqtt_data, effect_command_topic, state_topic); } if (LST_RGBW == light_subtype) { char *white_temp_command_topic = stemp1; GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); - if (Settings.flag3.hass_short_discovery_msg) - Shorten(&white_temp_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_WHITE_SHORT:HASS_DISCOVER_LIGHT_WHITE, - mqtt_data, white_temp_command_topic, state_topic); + Shorten(&white_temp_command_topic, prefix); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_WHITE_SHORT, mqtt_data, white_temp_command_topic, state_topic); } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { char *color_temp_command_topic = stemp1; GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); - if (Settings.flag3.hass_short_discovery_msg) - Shorten(&color_temp_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_LIGHT_CT_SHORT:HASS_DISCOVER_LIGHT_CT, - mqtt_data, color_temp_command_topic, state_topic); + Shorten(&color_temp_command_topic, prefix); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_CT_SHORT, mqtt_data, color_temp_command_topic, state_topic); } } - if (Settings.flag3.hass_short_discovery_msg) { - snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, - unique_id, ESP.getChipId(), - Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); - } + snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, + unique_id, ESP.getChipId(), + Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } MqttPublish(stopic, true); @@ -388,26 +280,18 @@ void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, GetTopic_P(state_topic, CMND, topic, value_template); // State of button is sent as CMND TOGGLE, state of switch is sent as ON/OFF GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); FindPrefix(state_topic, availability_topic, prefix); - if (Settings.flag3.hass_short_discovery_msg) { - Shorten(&state_topic, prefix); - Shorten(&availability_topic, prefix); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_SHORT:HASS_DISCOVER_BUTTON_SWITCH, + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_SHORT, name, state_topic, Settings.state_text[toggle?2:1], availability_topic); - if (toggle) snprintf_P(mqtt_data, sizeof(mqtt_data), - Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT:HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, - mqtt_data); - if (!toggle) snprintf_P(mqtt_data, sizeof(mqtt_data), - Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT:HASS_DISCOVER_BUTTON_SWITCH_ONOFF, - mqtt_data, Settings.state_text[0]); + if (toggle) snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT, mqtt_data); + else snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT, mqtt_data, Settings.state_text[0]); - if (Settings.flag3.hass_short_discovery_msg) { - snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, - unique_id, ESP.getChipId(), - Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); - } + snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, + unique_id, ESP.getChipId(), + Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } MqttPublish(stopic, true); @@ -498,45 +382,42 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); FindPrefix(state_topic, availability_topic, prefix); - if (Settings.flag3.hass_short_discovery_msg) { - Shorten(&state_topic, prefix); - Shorten(&availability_topic, prefix); - } - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_SHORT:HASS_DISCOVER_SENSOR, + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_SHORT, name, state_topic, availability_topic); if (!strcmp_P(subsensortype, PSTR(D_JSON_TEMPERATURE))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_TEMP_SHORT:HASS_DISCOVER_SENSOR_TEMP, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_TEMP_SHORT, mqtt_data, TempUnit(), sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_HUM_SHORT:HASS_DISCOVER_SENSOR_HUM, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_HUM_SHORT, mqtt_data, sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_PRESS_SHORT:HASS_DISCOVER_SENSOR_PRESS, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_PRESS_SHORT, mqtt_data, PressureUnit().c_str(), sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL)) || !strcmp_P(subsensortype, PSTR(D_JSON_TODAY)) || !strcmp_P(subsensortype, PSTR(D_JSON_YESTERDAY))){ - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_KWH_SHORT:HASS_DISCOVER_SENSOR_KWH, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_KWH_SHORT, mqtt_data, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_POWERUSAGE))){ - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_WATT_SHORT:HASS_DISCOVER_SENSOR_WATT, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_WATT_SHORT, mqtt_data, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_VOLTAGE))){ - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_VOLTAGE_SHORT:HASS_DISCOVER_SENSOR_VOLTAGE, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_VOLTAGE_SHORT, mqtt_data, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_CURRENT))){ - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_AMPERE_SHORT:HASS_DISCOVER_SENSOR_AMPERE, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_AMPERE_SHORT, mqtt_data, sensorname, subsensortype); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_SENSOR_ANY_SHORT:HASS_DISCOVER_SENSOR_ANY, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_ANY_SHORT, mqtt_data, sensorname, subsensortype); } - if (Settings.flag3.hass_short_discovery_msg) { - snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, - unique_id, ESP.getChipId(), - Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); - } + snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, + unique_id, ESP.getChipId(), + Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } MqttPublish(stopic, true); From c348848200934a70080a5b125991090d7927aaa0 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 22 Dec 2018 13:21:04 +0100 Subject: [PATCH 0754/2222] Rename HASS discovery string constants --- sonoff/xdrv_12_home_assistant.ino | 80 +++++++++++++++---------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 1e4f90e4d..350fe1ca6 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -21,7 +21,7 @@ #define XDRV_12 12 -const char HASS_DISCOVER_RELAY_SHORT[] PROGMEM = +const char HASS_DISCOVER_RELAY[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 "\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2 "\"stat_t\":\"%s\"," // stat/dualr2/RESULT (implies "\"optimistic\":\"false\",") @@ -33,7 +33,7 @@ const char HASS_DISCOVER_RELAY_SHORT[] PROGMEM = "\"pl_avail\":\"" D_ONLINE "\"," // Online "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline -const char HASS_DISCOVER_BUTTON_SWITCH_SHORT[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 BTN "\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") // "\"value_template\":\"{{value_json.%s}}\"," // POWER2 @@ -43,86 +43,86 @@ const char HASS_DISCOVER_BUTTON_SWITCH_SHORT[] PROGMEM = "\"pl_avail\":\"" D_ONLINE "\"," // Online "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline -const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE[] PROGMEM = "%s,\"off_delay\":1"; // Hass has no support for TOGGLE, fake it by resetting to OFF after 1s -const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT[] PROGMEM = +const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = "%s,\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work "\"pl_off\":\"%s\""; // OFF -const char HASS_DISCOVER_LIGHT_DIMMER_SHORT[] PROGMEM = +const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = "%s,\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer "\"bri_stat_t\":\"%s\"," // stat/led2/RESULT "\"bri_scl\":100," // 100% "\"on_cmd_type\":\"brightness\"," // power on (first), power on (last), no power on (brightness) "\"bri_val_tpl\":\"{{value_json." D_CMND_DIMMER "}}\""; -const char HASS_DISCOVER_LIGHT_COLOR_SHORT[] PROGMEM = +const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = "%s,\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2 "\"rgb_stat_t\":\"%s\"," // stat/led2/RESULT "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; -const char HASS_DISCOVER_LIGHT_WHITE_SHORT[] PROGMEM = +const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = "%s,\"whit_val_cmd_t\":\"%s\"," // cmnd/led2/White "\"whit_val_stat_t\":\"%s\"," // stat/led2/RESULT "\"white_value_scale\":100," // (No abbreviation defined) "\"whit_val_tpl\":\"{{ value_json.Channel[3] }}\""; -const char HASS_DISCOVER_LIGHT_CT_SHORT[] PROGMEM = +const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = "%s,\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT "\"clr_temp_stat_t\":\"%s\"," // stat/led2/RESULT "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; -const char HASS_DISCOVER_LIGHT_SCHEME_SHORT[] PROGMEM = +const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = "%s,\"fx_cmd_t\":\"%s\"," // cmnd/led2/Scheme "\"fx_stat_t\":\"%s\"," // stat/led2/RESULT "\"fx_val_tpl\":\"{{value_json." D_CMND_SCHEME "}}\"," "\"fx_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; // string list with reference to scheme parameter. -const char HASS_DISCOVER_SENSOR_SHORT[] PROGMEM = +const char HASS_DISCOVER_SENSOR[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 BTN "\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") "\"avty_t\":\"%s\"," // tele/dualr2/LWT "\"pl_avail\":\"" D_ONLINE "\"," // Online "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline -const char HASS_DISCOVER_SENSOR_TEMP_SHORT[] PROGMEM = +const char HASS_DISCOVER_SENSOR_TEMP[] PROGMEM = "%s,\"unit_of_meas\":\"°%c\"," // °C / °F "\"val_tpl\":\"{{value_json['%s'].Temperature}}\""; // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Temperature }} -const char HASS_DISCOVER_SENSOR_HUM_SHORT[] PROGMEM = +const char HASS_DISCOVER_SENSOR_HUM[] PROGMEM = "%s,\"unit_of_meas\":\"%%\"," // % "\"val_tpl\":\"{{value_json['%s'].Humidity}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }} "\"dev_cla\":\"humidity\""; // humidity -const char HASS_DISCOVER_SENSOR_PRESS_SHORT[] PROGMEM = +const char HASS_DISCOVER_SENSOR_PRESS[] PROGMEM = "%s,\"unit_of_meas\":\"%s\"," // PressureUnit() setting "\"val_tpl\":\"{{value_json['%s'].Pressure}}\"," // "BME280":{"Temperature":19.7,"Humidity":27.8,"Pressure":990.1} -> {{ value_json['BME280'].Pressure }} "\"dev_cla\":\"pressure\""; // pressure //ENERGY -const char HASS_DISCOVER_SENSOR_KWH_SHORT[] PROGMEM = +const char HASS_DISCOVER_SENSOR_KWH[] PROGMEM = "%s,\"unit_of_meas\":\"kWh\"," // kWh "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Total/Yesterday/Today }} -const char HASS_DISCOVER_SENSOR_WATT_SHORT[] PROGMEM = +const char HASS_DISCOVER_SENSOR_WATT[] PROGMEM = "%s,\"unit_of_meas\":\"W\"," // W "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].POWER }} -const char HASS_DISCOVER_SENSOR_VOLTAGE_SHORT[] PROGMEM = +const char HASS_DISCOVER_SENSOR_VOLTAGE[] PROGMEM = "%s,\"unit_of_meas\":\"V\"," // V "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Voltage }} -const char HASS_DISCOVER_SENSOR_AMPERE_SHORT[] PROGMEM = +const char HASS_DISCOVER_SENSOR_AMPERE[] PROGMEM = "%s,\"unit_of_meas\":\"A\"," // A "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Current }} -const char HASS_DISCOVER_SENSOR_ANY_SHORT[] PROGMEM = +const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = "%s,\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} -const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = +const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = "%s,\"uniq_id\":\"%s\"," "\"device\":{\"identifiers\":[\"%06X\"]," "\"name\":\"%s\"," @@ -199,7 +199,7 @@ void HAssAnnounceRelayLight(void) Shorten(&command_topic, prefix); Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_RELAY_SHORT, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); if (is_light) { @@ -207,19 +207,19 @@ void HAssAnnounceRelayLight(void) GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); Shorten(&brightness_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_DIMMER_SHORT, mqtt_data, brightness_command_topic, state_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_DIMMER, mqtt_data, brightness_command_topic, state_topic); if (light_subtype >= LST_RGB) { char *rgb_command_topic = stemp1; GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); Shorten(&rgb_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_COLOR_SHORT, mqtt_data, rgb_command_topic, state_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_COLOR, mqtt_data, rgb_command_topic, state_topic); char *effect_command_topic = stemp1; GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); Shorten(&effect_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_SCHEME_SHORT, mqtt_data, effect_command_topic, state_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_SCHEME, mqtt_data, effect_command_topic, state_topic); } if (LST_RGBW == light_subtype) { @@ -227,18 +227,18 @@ void HAssAnnounceRelayLight(void) GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); Shorten(&white_temp_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_WHITE_SHORT, mqtt_data, white_temp_command_topic, state_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_WHITE, mqtt_data, white_temp_command_topic, state_topic); } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { char *color_temp_command_topic = stemp1; GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); Shorten(&color_temp_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_CT_SHORT, mqtt_data, color_temp_command_topic, state_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_CT, mqtt_data, color_temp_command_topic, state_topic); } } snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data, unique_id, ESP.getChipId(), Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); @@ -282,13 +282,13 @@ void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, FindPrefix(state_topic, availability_topic, prefix); Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_SHORT, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH, name, state_topic, Settings.state_text[toggle?2:1], availability_topic); - if (toggle) snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT, mqtt_data); - else snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT, mqtt_data, Settings.state_text[0]); + if (toggle) snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, mqtt_data); + else snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_ONOFF, mqtt_data, Settings.state_text[0]); snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data, unique_id, ESP.getChipId(), Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); @@ -385,36 +385,36 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_SHORT, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); if (!strcmp_P(subsensortype, PSTR(D_JSON_TEMPERATURE))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_TEMP_SHORT, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_TEMP, mqtt_data, TempUnit(), sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_HUM_SHORT, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_HUM, mqtt_data, sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_PRESS_SHORT, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_PRESS, mqtt_data, PressureUnit().c_str(), sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL)) || !strcmp_P(subsensortype, PSTR(D_JSON_TODAY)) || !strcmp_P(subsensortype, PSTR(D_JSON_YESTERDAY))){ - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_KWH_SHORT, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_KWH, mqtt_data, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_POWERUSAGE))){ - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_WATT_SHORT, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_WATT, mqtt_data, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_VOLTAGE))){ - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_VOLTAGE_SHORT, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_VOLTAGE, mqtt_data, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_CURRENT))){ - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_AMPERE_SHORT, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_AMPERE, mqtt_data, sensorname, subsensortype); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_ANY_SHORT, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_ANY, mqtt_data, sensorname, subsensortype); } snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, + snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data, unique_id, ESP.getChipId(), Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); From 6702113308778ab00f10c4332a51cf884261b433 Mon Sep 17 00:00:00 2001 From: gourry Date: Sat, 22 Dec 2018 14:56:14 +0100 Subject: [PATCH 0755/2222] Remove Alexa message "this value is outside the range of the device" --- sonoff/xplg_wemohue.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 64ac969ae..143d0e6ba 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -568,7 +568,7 @@ void HueLightStatus1(byte device, String *response) { float hue = 0; float sat = 0; - float bri = 0; + float bri = 254; uint16_t ct = 500; if (light_type) { From e2cd656286f2182fbfb1fd6cab255c9c0d5a2e38 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 22 Dec 2018 16:13:07 +0100 Subject: [PATCH 0756/2222] 6.4.0.3 Hass and Alexa fixes 6.4.0.3 20181222 * Change Hass discovery to short MQTT messages as used by Hass 0.81 and up (#4711) * Change FallbackTopic detection (#4706) * Add define WIFI_SOFT_AP_CHANNEL in my_user_config.h to set Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI (#4673) * Fix Alexa "this value is outside the range of the device". Needs power cycle and Alexa deletion/discovery cycle. (#3159, #4712) --- sonoff/_changelog.ino | 10 ++++++++-- sonoff/my_user_config.h | 1 + sonoff/sonoff.ino | 3 ++- sonoff/xdrv_01_webserver.ino | 10 +++++++++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e1414882a..53c7895c3 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,12 @@ -/* 6.4.0.2 20181221 +/* 6.4.0.3 20181222 + * Change Hass discovery to short MQTT messages as used by Hass 0.81 and up (#4711) + * Change FallbackTopic detection (#4706) + * Add define WIFI_SOFT_AP_CHANNEL in my_user_config.h to set Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI (#4673) + * Fix Alexa "this value is outside the range of the device". Needs power cycle and Alexa deletion/discovery cycle. (#3159, #4712) + * + * 6.4.0.2 20181221 * Fix possible dtostrf buffer overflows by increasing buffers - * + * * 6.4.0.1 20181217 * Add support for AZ-Instrument 7798 CO2 meter/datalogger (#4672) * Change RAM usage BMP/BME I2C sensors diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index aa92cba85..c0fcf3d3f 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -217,6 +217,7 @@ //#define MY_LANGUAGE zh-TW // Chinese (Traditional) in Taiwan // -- Wifi Config tools --------------------------- +#define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI //#define USE_WPS // Add support for WPS as initial wifi configuration tool (+33k code, 1k mem (5k mem with core v2.4.2+)) //#define USE_SMARTCONFIG // Add support for Wifi SmartConfig as initial wifi configuration tool (+23k code, +0.6k mem) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 362b48ced..b262c7d9b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -467,7 +467,8 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if (XdrvMqttData(topicBuf, sizeof(topicBuf), dataBuf, sizeof(dataBuf))) return; grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != NULL); - fallback_topic_flag = (strstr(topicBuf, mqtt_client) != NULL); + snprintf_P(stemp1, sizeof(stemp1), PSTR(D_CMND "/%s/"), mqtt_client); // Full Fallback topic = cmnd/DVES_xxxxxxxx + fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type) index = 1; diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 959a42353..bd76b3c0e 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -27,6 +27,10 @@ #define XDRV_01 1 +#ifndef WIFI_SOFT_AP_CHANNEL +#define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by SmartConfig web GUI +#endif + #define HTTP_REFRESH_TIME 2345 // milliseconds #define HTTP_RESTART_RECONNECT_TIME 9000 // milliseconds #define HTTP_OTA_RESTART_RECONNECT_TIME 20000 // milliseconds @@ -441,7 +445,11 @@ void WifiManagerBegin(void) StopWebserver(); DnsServer = new DNSServer(); - WiFi.softAP(my_hostname); + + int channel = WIFI_SOFT_AP_CHANNEL; + if ((channel < 1) || (channel > 13)) { channel = 1; } + WiFi.softAP(my_hostname, NULL, channel); + delay(500); // Without delay I've seen the IP address blank /* Setup the DNS server redirecting all the domains to the apIP */ DnsServer->setErrorReplyCode(DNSReplyCode::NoError); From ed6e411f7fbda71efe8a0b6be6544d927aea5c6f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 22 Dec 2018 18:09:27 +0100 Subject: [PATCH 0757/2222] Add optional TLS_CA_CERT Add define USE_MQTT_TLS_CA_CERT for checking MQTT TLS against root ca using Let's Encrypt cert from sonoff_letsencrypt.h - not supported with core 2.3.0 (#4703) --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 79 +--------------------------- sonoff/sonoff_letsencrypt.h | 102 ++++++++++++++++++++++++++++++++++++ sonoff/sonoff_post.h | 4 ++ sonoff/xdrv_02_mqtt.ino | 9 ++-- 5 files changed, 114 insertions(+), 81 deletions(-) create mode 100644 sonoff/sonoff_letsencrypt.h diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 53c7895c3..65385f746 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Change FallbackTopic detection (#4706) * Add define WIFI_SOFT_AP_CHANNEL in my_user_config.h to set Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI (#4673) * Fix Alexa "this value is outside the range of the device". Needs power cycle and Alexa deletion/discovery cycle. (#3159, #4712) + * Add define USE_MQTT_TLS_CA_CERT for checking MQTT TLS against root ca using Let's Encrypt cert from sonoff_letsencrypt.h - not supported with core 2.3.0 (#4703) * * 6.4.0.2 20181221 * Fix possible dtostrf buffer overflows by increasing buffers diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index f1e3669e0..5fcbecabf 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -249,80 +249,7 @@ // -- MQTT - TLS ---------------------------------- // !!! TLS uses a LOT OF MEMORY so be careful to enable other options at the same time !!! //#define USE_MQTT_TLS // Use TLS for MQTT connection (+53k code, +15k mem) - #define USE_MQTT_TLS_CA_CERT - #define MQTT_TLS_CA_CERT_LENGTH 846 // Letsencrypt - #define MQTT_TLS_CA_CERT { \ - 0x30, 0x82, 0x03, 0x4a, 0x30, 0x82, 0x02, 0x32, 0xa0, 0x03, 0x02, 0x01, \ - 0x02, 0x02, 0x10, 0x44, 0xaf, 0xb0, 0x80, 0xd6, 0xa3, 0x27, 0xba, 0x89, \ - 0x30, 0x39, 0x86, 0x2e, 0xf8, 0x40, 0x6b, 0x30, 0x0d, 0x06, 0x09, 0x2a, \ - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3f, \ - 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 0x44, \ - 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, \ - 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, \ - 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ - 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, \ - 0x20, 0x58, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x39, 0x33, \ - 0x30, 0x32, 0x31, 0x31, 0x32, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x31, \ - 0x30, 0x39, 0x33, 0x30, 0x31, 0x34, 0x30, 0x31, 0x31, 0x35, 0x5a, 0x30, \ - 0x3f, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, \ - 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, \ - 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, \ - 0x43, 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, \ - 0x13, 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, \ - 0x41, 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, \ - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, \ - 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, \ - 0x00, 0xdf, 0xaf, 0xe9, 0x97, 0x50, 0x08, 0x83, 0x57, 0xb4, 0xcc, 0x62, \ - 0x65, 0xf6, 0x90, 0x82, 0xec, 0xc7, 0xd3, 0x2c, 0x6b, 0x30, 0xca, 0x5b, \ - 0xec, 0xd9, 0xc3, 0x7d, 0xc7, 0x40, 0xc1, 0x18, 0x14, 0x8b, 0xe0, 0xe8, \ - 0x33, 0x76, 0x49, 0x2a, 0xe3, 0x3f, 0x21, 0x49, 0x93, 0xac, 0x4e, 0x0e, \ - 0xaf, 0x3e, 0x48, 0xcb, 0x65, 0xee, 0xfc, 0xd3, 0x21, 0x0f, 0x65, 0xd2, \ - 0x2a, 0xd9, 0x32, 0x8f, 0x8c, 0xe5, 0xf7, 0x77, 0xb0, 0x12, 0x7b, 0xb5, \ - 0x95, 0xc0, 0x89, 0xa3, 0xa9, 0xba, 0xed, 0x73, 0x2e, 0x7a, 0x0c, 0x06, \ - 0x32, 0x83, 0xa2, 0x7e, 0x8a, 0x14, 0x30, 0xcd, 0x11, 0xa0, 0xe1, 0x2a, \ - 0x38, 0xb9, 0x79, 0x0a, 0x31, 0xfd, 0x50, 0xbd, 0x80, 0x65, 0xdf, 0xb7, \ - 0x51, 0x63, 0x83, 0xc8, 0xe2, 0x88, 0x61, 0xea, 0x4b, 0x61, 0x81, 0xec, \ - 0x52, 0x6b, 0xb9, 0xa2, 0xe2, 0x4b, 0x1a, 0x28, 0x9f, 0x48, 0xa3, 0x9e, \ - 0x0c, 0xda, 0x09, 0x8e, 0x3e, 0x17, 0x2e, 0x1e, 0xdd, 0x20, 0xdf, 0x5b, \ - 0xc6, 0x2a, 0x8a, 0xab, 0x2e, 0xbd, 0x70, 0xad, 0xc5, 0x0b, 0x1a, 0x25, \ - 0x90, 0x74, 0x72, 0xc5, 0x7b, 0x6a, 0xab, 0x34, 0xd6, 0x30, 0x89, 0xff, \ - 0xe5, 0x68, 0x13, 0x7b, 0x54, 0x0b, 0xc8, 0xd6, 0xae, 0xec, 0x5a, 0x9c, \ - 0x92, 0x1e, 0x3d, 0x64, 0xb3, 0x8c, 0xc6, 0xdf, 0xbf, 0xc9, 0x41, 0x70, \ - 0xec, 0x16, 0x72, 0xd5, 0x26, 0xec, 0x38, 0x55, 0x39, 0x43, 0xd0, 0xfc, \ - 0xfd, 0x18, 0x5c, 0x40, 0xf1, 0x97, 0xeb, 0xd5, 0x9a, 0x9b, 0x8d, 0x1d, \ - 0xba, 0xda, 0x25, 0xb9, 0xc6, 0xd8, 0xdf, 0xc1, 0x15, 0x02, 0x3a, 0xab, \ - 0xda, 0x6e, 0xf1, 0x3e, 0x2e, 0xf5, 0x5c, 0x08, 0x9c, 0x3c, 0xd6, 0x83, \ - 0x69, 0xe4, 0x10, 0x9b, 0x19, 0x2a, 0xb6, 0x29, 0x57, 0xe3, 0xe5, 0x3d, \ - 0x9b, 0x9f, 0xf0, 0x02, 0x5d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, \ - 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, \ - 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, \ - 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, \ - 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc4, 0xa7, \ - 0xb1, 0xa4, 0x7b, 0x2c, 0x71, 0xfa, 0xdb, 0xe1, 0x4b, 0x90, 0x75, 0xff, \ - 0xc4, 0x15, 0x60, 0x85, 0x89, 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, \ - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, \ - 0x01, 0x00, 0xa3, 0x1a, 0x2c, 0x9b, 0x17, 0x00, 0x5c, 0xa9, 0x1e, 0xee, \ - 0x28, 0x66, 0x37, 0x3a, 0xbf, 0x83, 0xc7, 0x3f, 0x4b, 0xc3, 0x09, 0xa0, \ - 0x95, 0x20, 0x5d, 0xe3, 0xd9, 0x59, 0x44, 0xd2, 0x3e, 0x0d, 0x3e, 0xbd, \ - 0x8a, 0x4b, 0xa0, 0x74, 0x1f, 0xce, 0x10, 0x82, 0x9c, 0x74, 0x1a, 0x1d, \ - 0x7e, 0x98, 0x1a, 0xdd, 0xcb, 0x13, 0x4b, 0xb3, 0x20, 0x44, 0xe4, 0x91, \ - 0xe9, 0xcc, 0xfc, 0x7d, 0xa5, 0xdb, 0x6a, 0xe5, 0xfe, 0xe6, 0xfd, 0xe0, \ - 0x4e, 0xdd, 0xb7, 0x00, 0x3a, 0xb5, 0x70, 0x49, 0xaf, 0xf2, 0xe5, 0xeb, \ - 0x02, 0xf1, 0xd1, 0x02, 0x8b, 0x19, 0xcb, 0x94, 0x3a, 0x5e, 0x48, 0xc4, \ - 0x18, 0x1e, 0x58, 0x19, 0x5f, 0x1e, 0x02, 0x5a, 0xf0, 0x0c, 0xf1, 0xb1, \ - 0xad, 0xa9, 0xdc, 0x59, 0x86, 0x8b, 0x6e, 0xe9, 0x91, 0xf5, 0x86, 0xca, \ - 0xfa, 0xb9, 0x66, 0x33, 0xaa, 0x59, 0x5b, 0xce, 0xe2, 0xa7, 0x16, 0x73, \ - 0x47, 0xcb, 0x2b, 0xcc, 0x99, 0xb0, 0x37, 0x48, 0xcf, 0xe3, 0x56, 0x4b, \ - 0xf5, 0xcf, 0x0f, 0x0c, 0x72, 0x32, 0x87, 0xc6, 0xf0, 0x44, 0xbb, 0x53, \ - 0x72, 0x6d, 0x43, 0xf5, 0x26, 0x48, 0x9a, 0x52, 0x67, 0xb7, 0x58, 0xab, \ - 0xfe, 0x67, 0x76, 0x71, 0x78, 0xdb, 0x0d, 0xa2, 0x56, 0x14, 0x13, 0x39, \ - 0x24, 0x31, 0x85, 0xa2, 0xa8, 0x02, 0x5a, 0x30, 0x47, 0xe1, 0xdd, 0x50, \ - 0x07, 0xbc, 0x02, 0x09, 0x90, 0x00, 0xeb, 0x64, 0x63, 0x60, 0x9b, 0x16, \ - 0xbc, 0x88, 0xc9, 0x12, 0xe6, 0xd2, 0x7d, 0x91, 0x8b, 0xf9, 0x3d, 0x32, \ - 0x8d, 0x65, 0xb4, 0xe9, 0x7c, 0xb1, 0x57, 0x76, 0xea, 0xc5, 0xb6, 0x28, \ - 0x39, 0xbf, 0x15, 0x65, 0x1c, 0xc8, 0xf6, 0x77, 0x96, 0x6a, 0x0a, 0x8d, \ - 0x77, 0x0b, 0xd8, 0x91, 0x0b, 0x04, 0x8e, 0x07, 0xdb, 0x29, 0xb6, 0x0a, \ - 0xee, 0x9d, 0x82, 0x35, 0x35, 0x10 } +// #define USE_MQTT_TLS_CA_CERT // Use LetsEncrypt Certificate from sonoff_letsencrypt.h - Not supported with core 2.3.0 // -- KNX IP Protocol ----------------------------- //#define USE_KNX // Enable KNX IP Protocol Support (+9.4k code, +3k7 mem) @@ -507,8 +434,4 @@ #error "Select either USE_MQTT_TLS or USE_WEBSERVER as there is just not enough memory to play with" #endif -#if defined(USE_MQTT_TLS_CA_CERT) && defined(ARDUINO_ESP8266_RELEASE_2_3_0) - #error "USE_MQTT_TLS_CA_CERT does not work with core version 2.3.0"" -#endif - #endif // _MY_USER_CONFIG_H_ diff --git a/sonoff/sonoff_letsencrypt.h b/sonoff/sonoff_letsencrypt.h new file mode 100644 index 000000000..fa00c9f29 --- /dev/null +++ b/sonoff/sonoff_letsencrypt.h @@ -0,0 +1,102 @@ +/* + sonoff_letsencrypt.h - TLS Lets Encrypt certificate for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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_MQTT_TLS_CA_CERT +/*********************************************************************************************\ + * LetsEncrypt IdenTrust DST Root CA X3 certificate valid until 20210930 + * + * https://letsencrypt.org/certificates/ + * Downloaded from https://www.identrust.com/support/downloads +\*********************************************************************************************/ + +#define MQTT_TLS_CA_CERT_LENGTH 846 // Letsencrypt +#define MQTT_TLS_CA_CERT { \ + 0x30, 0x82, 0x03, 0x4a, 0x30, 0x82, 0x02, 0x32, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x10, 0x44, 0xaf, 0xb0, 0x80, 0xd6, 0xa3, 0x27, 0xba, 0x89, \ + 0x30, 0x39, 0x86, 0x2e, 0xf8, 0x40, 0x6b, 0x30, 0x0d, 0x06, 0x09, 0x2a, \ + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3f, \ + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 0x44, \ + 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, \ + 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, \ + 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ + 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, \ + 0x20, 0x58, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x39, 0x33, \ + 0x30, 0x32, 0x31, 0x31, 0x32, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x31, \ + 0x30, 0x39, 0x33, 0x30, 0x31, 0x34, 0x30, 0x31, 0x31, 0x35, 0x5a, 0x30, \ + 0x3f, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, \ + 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, \ + 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, \ + 0x43, 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, \ + 0x13, 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, \ + 0x41, 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, \ + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, \ + 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, \ + 0x00, 0xdf, 0xaf, 0xe9, 0x97, 0x50, 0x08, 0x83, 0x57, 0xb4, 0xcc, 0x62, \ + 0x65, 0xf6, 0x90, 0x82, 0xec, 0xc7, 0xd3, 0x2c, 0x6b, 0x30, 0xca, 0x5b, \ + 0xec, 0xd9, 0xc3, 0x7d, 0xc7, 0x40, 0xc1, 0x18, 0x14, 0x8b, 0xe0, 0xe8, \ + 0x33, 0x76, 0x49, 0x2a, 0xe3, 0x3f, 0x21, 0x49, 0x93, 0xac, 0x4e, 0x0e, \ + 0xaf, 0x3e, 0x48, 0xcb, 0x65, 0xee, 0xfc, 0xd3, 0x21, 0x0f, 0x65, 0xd2, \ + 0x2a, 0xd9, 0x32, 0x8f, 0x8c, 0xe5, 0xf7, 0x77, 0xb0, 0x12, 0x7b, 0xb5, \ + 0x95, 0xc0, 0x89, 0xa3, 0xa9, 0xba, 0xed, 0x73, 0x2e, 0x7a, 0x0c, 0x06, \ + 0x32, 0x83, 0xa2, 0x7e, 0x8a, 0x14, 0x30, 0xcd, 0x11, 0xa0, 0xe1, 0x2a, \ + 0x38, 0xb9, 0x79, 0x0a, 0x31, 0xfd, 0x50, 0xbd, 0x80, 0x65, 0xdf, 0xb7, \ + 0x51, 0x63, 0x83, 0xc8, 0xe2, 0x88, 0x61, 0xea, 0x4b, 0x61, 0x81, 0xec, \ + 0x52, 0x6b, 0xb9, 0xa2, 0xe2, 0x4b, 0x1a, 0x28, 0x9f, 0x48, 0xa3, 0x9e, \ + 0x0c, 0xda, 0x09, 0x8e, 0x3e, 0x17, 0x2e, 0x1e, 0xdd, 0x20, 0xdf, 0x5b, \ + 0xc6, 0x2a, 0x8a, 0xab, 0x2e, 0xbd, 0x70, 0xad, 0xc5, 0x0b, 0x1a, 0x25, \ + 0x90, 0x74, 0x72, 0xc5, 0x7b, 0x6a, 0xab, 0x34, 0xd6, 0x30, 0x89, 0xff, \ + 0xe5, 0x68, 0x13, 0x7b, 0x54, 0x0b, 0xc8, 0xd6, 0xae, 0xec, 0x5a, 0x9c, \ + 0x92, 0x1e, 0x3d, 0x64, 0xb3, 0x8c, 0xc6, 0xdf, 0xbf, 0xc9, 0x41, 0x70, \ + 0xec, 0x16, 0x72, 0xd5, 0x26, 0xec, 0x38, 0x55, 0x39, 0x43, 0xd0, 0xfc, \ + 0xfd, 0x18, 0x5c, 0x40, 0xf1, 0x97, 0xeb, 0xd5, 0x9a, 0x9b, 0x8d, 0x1d, \ + 0xba, 0xda, 0x25, 0xb9, 0xc6, 0xd8, 0xdf, 0xc1, 0x15, 0x02, 0x3a, 0xab, \ + 0xda, 0x6e, 0xf1, 0x3e, 0x2e, 0xf5, 0x5c, 0x08, 0x9c, 0x3c, 0xd6, 0x83, \ + 0x69, 0xe4, 0x10, 0x9b, 0x19, 0x2a, 0xb6, 0x29, 0x57, 0xe3, 0xe5, 0x3d, \ + 0x9b, 0x9f, 0xf0, 0x02, 0x5d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, \ + 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, \ + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, \ + 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, \ + 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc4, 0xa7, \ + 0xb1, 0xa4, 0x7b, 0x2c, 0x71, 0xfa, 0xdb, 0xe1, 0x4b, 0x90, 0x75, 0xff, \ + 0xc4, 0x15, 0x60, 0x85, 0x89, 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, \ + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, \ + 0x01, 0x00, 0xa3, 0x1a, 0x2c, 0x9b, 0x17, 0x00, 0x5c, 0xa9, 0x1e, 0xee, \ + 0x28, 0x66, 0x37, 0x3a, 0xbf, 0x83, 0xc7, 0x3f, 0x4b, 0xc3, 0x09, 0xa0, \ + 0x95, 0x20, 0x5d, 0xe3, 0xd9, 0x59, 0x44, 0xd2, 0x3e, 0x0d, 0x3e, 0xbd, \ + 0x8a, 0x4b, 0xa0, 0x74, 0x1f, 0xce, 0x10, 0x82, 0x9c, 0x74, 0x1a, 0x1d, \ + 0x7e, 0x98, 0x1a, 0xdd, 0xcb, 0x13, 0x4b, 0xb3, 0x20, 0x44, 0xe4, 0x91, \ + 0xe9, 0xcc, 0xfc, 0x7d, 0xa5, 0xdb, 0x6a, 0xe5, 0xfe, 0xe6, 0xfd, 0xe0, \ + 0x4e, 0xdd, 0xb7, 0x00, 0x3a, 0xb5, 0x70, 0x49, 0xaf, 0xf2, 0xe5, 0xeb, \ + 0x02, 0xf1, 0xd1, 0x02, 0x8b, 0x19, 0xcb, 0x94, 0x3a, 0x5e, 0x48, 0xc4, \ + 0x18, 0x1e, 0x58, 0x19, 0x5f, 0x1e, 0x02, 0x5a, 0xf0, 0x0c, 0xf1, 0xb1, \ + 0xad, 0xa9, 0xdc, 0x59, 0x86, 0x8b, 0x6e, 0xe9, 0x91, 0xf5, 0x86, 0xca, \ + 0xfa, 0xb9, 0x66, 0x33, 0xaa, 0x59, 0x5b, 0xce, 0xe2, 0xa7, 0x16, 0x73, \ + 0x47, 0xcb, 0x2b, 0xcc, 0x99, 0xb0, 0x37, 0x48, 0xcf, 0xe3, 0x56, 0x4b, \ + 0xf5, 0xcf, 0x0f, 0x0c, 0x72, 0x32, 0x87, 0xc6, 0xf0, 0x44, 0xbb, 0x53, \ + 0x72, 0x6d, 0x43, 0xf5, 0x26, 0x48, 0x9a, 0x52, 0x67, 0xb7, 0x58, 0xab, \ + 0xfe, 0x67, 0x76, 0x71, 0x78, 0xdb, 0x0d, 0xa2, 0x56, 0x14, 0x13, 0x39, \ + 0x24, 0x31, 0x85, 0xa2, 0xa8, 0x02, 0x5a, 0x30, 0x47, 0xe1, 0xdd, 0x50, \ + 0x07, 0xbc, 0x02, 0x09, 0x90, 0x00, 0xeb, 0x64, 0x63, 0x60, 0x9b, 0x16, \ + 0xbc, 0x88, 0xc9, 0x12, 0xe6, 0xd2, 0x7d, 0x91, 0x8b, 0xf9, 0x3d, 0x32, \ + 0x8d, 0x65, 0xb4, 0xe9, 0x7c, 0xb1, 0x57, 0x76, 0xea, 0xc5, 0xb6, 0x28, \ + 0x39, 0xbf, 0x15, 0x65, 0x1c, 0xc8, 0xf6, 0x77, 0x96, 0x6a, 0x0a, 0x8d, \ + 0x77, 0x0b, 0xd8, 0x91, 0x0b, 0x04, 0x8e, 0x07, 0xdb, 0x29, 0xb6, 0x0a, \ + 0xee, 0x9d, 0x82, 0x35, 0x35, 0x10 } + +#endif // USE_MQTT_TLS_CA_CERT diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 8eddeea5b..12a68fe47 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -426,4 +426,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define ARDUINO_ESP8266_RELEASE "STAGE" #endif +#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 // Disable not supported features in core 2.3.0 +#undef USE_MQTT_TLS_CA_CERT +#endif + #endif // _SONOFF_POST_H_ diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 96d98e66e..a19f80f82 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -51,11 +51,14 @@ #define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library as it only supports TLS #endif -#endif +#endif // USE_MQTT_TLS /*********************************************************************************************/ #ifdef USE_MQTT_TLS +#ifdef USE_MQTT_TLS_CA_CERT + #include "sonoff_letsencrypt.h" // LetsEncrypt certificate +#endif WiFiClientSecure EspClient; // Wifi Secure Client #else WiFiClient EspClient; // Wifi Client @@ -469,13 +472,13 @@ boolean MqttCheckTls(void) } else { #ifdef USE_MQTT_TLS_CA_CERT unsigned char tls_ca_cert[] = MQTT_TLS_CA_CERT; - if(EspClient.setCACert(tls_ca_cert, MQTT_TLS_CA_CERT_LENGTH)) { + if (EspClient.setCACert(tls_ca_cert, MQTT_TLS_CA_CERT_LENGTH)) { if (EspClient.verifyCertChain(Settings.mqtt_host)) { AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "CA")); result = true; } } -#else +#else if (EspClient.verify(fingerprint1, Settings.mqtt_host)) { AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "1")); result = true; From d9f2e2193d43600b673ba9d549bb4402f6e27f86 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Sun, 23 Dec 2018 13:38:38 +0100 Subject: [PATCH 0758/2222] decode-config.py: adapt settings change - remove SetOption55 (hass_short_discovery_msg) --- tools/decode-config.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index b53dbaae9..d1daccf22 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0014' +VER = '2.1.0015' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -811,7 +811,11 @@ Setting_6_3_0_16['flag3'][0].update ({ 'button_switch_force_local':(' Date: Sun, 23 Dec 2018 14:48:57 +0100 Subject: [PATCH 0759/2222] Change FallbackTopic Change FallbackTopic from cmnd// to cmnd/_fb/ to discriminate from Topic (#1528) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 24 +++++++++++++++++++----- sonoff/xdrv_01_webserver.ino | 7 +++---- sonoff/xdrv_02_mqtt.ino | 7 +++---- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 65385f746..ee9fb5155 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,6 +4,7 @@ * Add define WIFI_SOFT_AP_CHANNEL in my_user_config.h to set Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI (#4673) * Fix Alexa "this value is outside the range of the device". Needs power cycle and Alexa deletion/discovery cycle. (#3159, #4712) * Add define USE_MQTT_TLS_CA_CERT for checking MQTT TLS against root ca using Let's Encrypt cert from sonoff_letsencrypt.h - not supported with core 2.3.0 (#4703) + * Change FallbackTopic from cmnd// to cmnd/_fb/ to discriminate from Topic (#1528) * * 6.4.0.2 20181221 * Fix possible dtostrf buffer overflows by increasing buffers diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index b262c7d9b..be5964a94 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -245,20 +245,25 @@ char* GetOtaUrl(char *otaurl, size_t otaurl_size) return otaurl; } -void GetTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic) +char* GetTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic) { /* prefix 0 = Cmnd prefix 1 = Stat prefix 2 = Tele + prefix 4 = Cmnd fallback + prefix 5 = Stat fallback + prefix 6 = Tele fallback */ char romram[CMDSZ]; String fulltopic; snprintf_P(romram, sizeof(romram), subtopic); - if (fallback_topic_flag) { + if (fallback_topic_flag || (prefix > 3)) { + prefix &= 3; fulltopic = FPSTR(kPrefixes[prefix]); fulltopic += F("/"); fulltopic += mqtt_client; + fulltopic += F("_fb"); // cmnd/_fb } else { fulltopic = Settings.mqtt_fulltopic; if ((0 == prefix) && (-1 == fulltopic.indexOf(F(MQTT_TOKEN_PREFIX)))) { @@ -280,6 +285,12 @@ void GetTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic) fulltopic.replace(F("//"), "/"); if (!fulltopic.endsWith("/")) fulltopic += "/"; snprintf_P(stopic, TOPSZ, PSTR("%s%s"), fulltopic.c_str(), romram); + return stopic; +} + +char* GetFallbackTopic_P(char *stopic, byte prefix, const char* subtopic) +{ + return GetTopic_P(stopic, prefix +4, NULL, subtopic); } char* GetStateText(byte state) @@ -467,8 +478,10 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if (XdrvMqttData(topicBuf, sizeof(topicBuf), dataBuf, sizeof(dataBuf))) return; grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != NULL); - snprintf_P(stemp1, sizeof(stemp1), PSTR(D_CMND "/%s/"), mqtt_client); // Full Fallback topic = cmnd/DVES_xxxxxxxx + + GetFallbackTopic_P(stemp1, CMND, ""); // Full Fallback topic = cmnd/DVES_xxxxxxxx_fb/ fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); + type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type) index = 1; @@ -2742,8 +2755,9 @@ void setup(void) } blink_powersave = power; - 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%s-" ARDUINO_ESP8266_RELEASE), - PROJECT, Settings.friendlyname[0], mqtt_topic, mqtt_client, Settings.mqtt_grptopic, my_version, my_image); + char stopic[TOPSZ]; + snprintf_P(log_data, sizeof(log_data), PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), + PROJECT, Settings.friendlyname[0], my_version, my_image); AddLog(LOG_LEVEL_INFO); #ifdef BE_MINIMAL snprintf_P(log_data, sizeof(log_data), PSTR(D_WARNING_MINIMAL_VERSION)); diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index bd76b3c0e..046181283 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1323,13 +1323,12 @@ void HandleInformation(void) 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_CLIENT "}2"); func += mqtt_client; 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, CMND, mqtt_topic, ""); - func += F("}1" D_MQTT_FULL_TOPIC "}2"); func += stopic; - + func += F("}1" D_MQTT_FULL_TOPIC "}2"); func += GetTopic_P(stopic, CMND, mqtt_topic, ""); + func += F("}1" D_MQTT " " D_FALLBACK_TOPIC "}2"); func += GetFallbackTopic_P(stopic, CMND, ""); } else { func += F("}1" D_MQTT "}2" D_DISABLED); } diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index a19f80f82..e3f848ce8 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -406,9 +406,7 @@ void MqttConnected(void) if (strstr(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != NULL) { GetTopic_P(stopic, CMND, Settings.mqtt_grptopic, PSTR("#")); MqttSubscribe(stopic); - fallback_topic_flag = 1; - GetTopic_P(stopic, CMND, mqtt_client, PSTR("#")); - fallback_topic_flag = 0; + GetFallbackTopic_P(stopic, CMND, PSTR("#")); MqttSubscribe(stopic); } @@ -417,7 +415,8 @@ void MqttConnected(void) if (mqtt_initial_connection_state) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), - my_module.name, my_version, my_image, mqtt_client, Settings.mqtt_grptopic); + my_module.name, my_version, my_image, GetFallbackTopic_P(stopic, CMND, ""), Settings.mqtt_grptopic); +// my_module.name, my_version, my_image, mqtt_client, Settings.mqtt_grptopic); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); #ifdef USE_WEBSERVER if (Settings.webserver) { From a013f4de8241b67c8892ebc69f6113c2858a8b06 Mon Sep 17 00:00:00 2001 From: Joel Stein Date: Sun, 23 Dec 2018 21:06:10 +0100 Subject: [PATCH 0760/2222] PS_16_DZ: fix broken if-statement --- sonoff/xdrv_19_ps16dz_dimmer.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 3c895cf98..7671249eb 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -159,8 +159,9 @@ void PS16DZSerialInput(void) memset(ps16dz_rx_buffer, 0, PS16DZ_BUFFER_SIZE); ps16dz_byte_counter = 0; } - if (ps16dz_byte_counter || (!ps16dz_byte_counter && serial_in_byte == 'A')); - ps16dz_rx_buffer[ps16dz_byte_counter++] = serial_in_byte; + if (ps16dz_byte_counter || (!ps16dz_byte_counter && serial_in_byte == 'A')) { + ps16dz_rx_buffer[ps16dz_byte_counter++] = serial_in_byte; + } } else { ps16dz_rx_buffer[ps16dz_byte_counter++] = 0x00; From 0539775cf085409fd71cd83840c7b174228cacaa Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 24 Dec 2018 14:31:34 +0100 Subject: [PATCH 0761/2222] Change MQTT GUI password handling Change MQTT GUI password handling (#4723) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_02_mqtt.ino | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index ee9fb5155..0e1fb1075 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -5,6 +5,7 @@ * Fix Alexa "this value is outside the range of the device". Needs power cycle and Alexa deletion/discovery cycle. (#3159, #4712) * Add define USE_MQTT_TLS_CA_CERT for checking MQTT TLS against root ca using Let's Encrypt cert from sonoff_letsencrypt.h - not supported with core 2.3.0 (#4703) * Change FallbackTopic from cmnd// to cmnd/_fb/ to discriminate from Topic (#1528) + * Change MQTT GUI password handling (#4723) * * 6.4.0.2 20181221 * Fix possible dtostrf buffer overflows by increasing buffers diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index e3f848ce8..7ba5cf47a 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -858,7 +858,7 @@ const char HTTP_FORM_MQTT[] PROGMEM = "
          " D_PORT " (" STR(MQTT_PORT) ")

          " "
          " D_CLIENT " ({m0)

          " "
          " D_USER " (" MQTT_USER ")

          " - "
          " D_PASSWORD "

          " + "
          " D_PASSWORD "

          " "
          " D_TOPIC " = %topic% (" MQTT_TOPIC ")

          " "
          " D_FULL_TOPIC " (" MQTT_FULLTOPIC ")

          "; @@ -885,7 +885,6 @@ void HandleMqttConfiguration(void) page.replace(F("{m2"), String(Settings.mqtt_port)); page.replace(F("{m3"), Settings.mqtt_client); page.replace(F("{m4"), (Settings.mqtt_user[0] == '\0')?"0":Settings.mqtt_user); - page.replace(F("{m5"), (Settings.mqtt_pwd[0] == '\0')?"0":Settings.mqtt_pwd); page.replace(F("{m6"), Settings.mqtt_topic); page.replace(F("{m7"), Settings.mqtt_fulltopic); @@ -921,9 +920,9 @@ void MqttSaveSettings(void) WebGetArg("mu", tmp, sizeof(tmp)); strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user)); WebGetArg("mp", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? MQTT_PASS : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_pwd)); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_MQTTPASSWORD " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), - Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_pwd, Settings.mqtt_topic, Settings.mqtt_fulltopic); + strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.mqtt_pwd : tmp, sizeof(Settings.mqtt_pwd)); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), + Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_topic, Settings.mqtt_fulltopic); AddLog(LOG_LEVEL_INFO); } #endif // USE_WEBSERVER From 87ddbd8f38154e26e02eeea5a50294a076a2a5e0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 24 Dec 2018 16:45:41 +0100 Subject: [PATCH 0762/2222] Release 6.4.1 --- README.md | 2 +- RELEASENOTES.md | 15 +++++++++++++++ sonoff/_changelog.ino | 25 +++++++++++-------------- sonoff/sonoff_version.h | 2 +- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index cc0b83367..09354028a 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest) the binaries can also be OTA downloaded from http://thehackbox.org/tasmota/release/ ### Development -[![Dev Version](https://img.shields.io/badge/development%20version-6.4.0.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-6.4.1.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 973658a4c..1198a6165 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -168,6 +168,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_TUYA_DIMMER | - | x | - | x | x | x | | USE_ARMTRONIX_DIMMERS | - | x | - | x | x | x | | USE_PS_16_DZ | - | x | - | x | x | x | +| USE_AZ7798 | - | - | - | - | - | - | | USE_IR_REMOTE | - | - | - | x | x | x | | USE_IR_HVAC | - | - | - | - | - | x | | USE_IR_RECEIVE | - | - | - | x | x | x | @@ -184,6 +185,20 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_DISPLAY | - | - | - | - | - | - | ## Changelog +Version 6.4.1 20181225 + * Change RAM usage BMP/BME I2C sensors + * Change FallbackTopic from cmnd/\/ to cmnd/\_fb/ to discriminate from Topic (#1528) + * Change FallbackTopic detection (#4706) + * Change Hass discovery to short MQTT messages as used by Hass 0.81 and up (#4711) + * Change MQTT GUI password handling (#4723) + * Fix possible dtostrf buffer overflows by increasing buffers + * Fix wifi strongest signal detection (#4704) + * Fix Alexa "this value is outside the range of the device". Needs power cycle and Alexa deletion/discovery cycle. (#3159, #4712) + * Add Slovak language file (#4663) + * Add support for AZ-Instrument 7798 CO2 meter/datalogger (#4672) + * Add define WIFI_SOFT_AP_CHANNEL in my_user_config.h to set Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI (#4673) + * Add define USE_MQTT_TLS_CA_CERT for checking MQTT TLS against root ca using Let's Encrypt cert from sonoff_letsencrypt.h - not supported with core 2.3.0 (#4703) + Version 6.4.0 20181217 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40%. In case of web page errors clear your browser cache or do Page Reload (F5 or Ctrl+R) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0e1fb1075..1c96f7d5e 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,19 +1,16 @@ -/* 6.4.0.3 20181222 - * Change Hass discovery to short MQTT messages as used by Hass 0.81 and up (#4711) - * Change FallbackTopic detection (#4706) - * Add define WIFI_SOFT_AP_CHANNEL in my_user_config.h to set Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI (#4673) - * Fix Alexa "this value is outside the range of the device". Needs power cycle and Alexa deletion/discovery cycle. (#3159, #4712) - * Add define USE_MQTT_TLS_CA_CERT for checking MQTT TLS against root ca using Let's Encrypt cert from sonoff_letsencrypt.h - not supported with core 2.3.0 (#4703) - * Change FallbackTopic from cmnd// to cmnd/_fb/ to discriminate from Topic (#1528) - * Change MQTT GUI password handling (#4723) - * - * 6.4.0.2 20181221 - * Fix possible dtostrf buffer overflows by increasing buffers - * - * 6.4.0.1 20181217 - * Add support for AZ-Instrument 7798 CO2 meter/datalogger (#4672) +/* 6.4.1 20181225 * Change RAM usage BMP/BME I2C sensors + * Change FallbackTopic from cmnd// to cmnd/_fb/ to discriminate from Topic (#1528) + * Change FallbackTopic detection (#4706) + * Change Hass discovery to short MQTT messages as used by Hass 0.81 and up (#4711) + * Change MQTT GUI password handling (#4723) + * Fix possible dtostrf buffer overflows by increasing buffers * Fix wifi strongest signal detection (#4704) + * Fix Alexa "this value is outside the range of the device". Needs power cycle and Alexa deletion/discovery cycle. (#3159, #4712) + * Add Slovak language file (#4663) + * Add support for AZ-Instrument 7798 CO2 meter/datalogger (#4672) + * Add define WIFI_SOFT_AP_CHANNEL in my_user_config.h to set Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI (#4673) + * Add define USE_MQTT_TLS_CA_CERT for checking MQTT TLS against root ca using Let's Encrypt cert from sonoff_letsencrypt.h - not supported with core 2.3.0 (#4703) * * 6.4.0 20181217 * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40% diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 32b9dbd83..6e635a341 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040003 +#define VERSION 0x06040100 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" From 0b10f48e41d0db17aea48bb9805f03fe3864c6bb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 24 Dec 2018 18:14:25 +0100 Subject: [PATCH 0763/2222] 6.4.1.1 Fix most compiler warnings 6.4.1.1 20181224 * Fix most compiler warnings --- lib/TasmotaModbus-1.1.0/src/TasmotaModbus.cpp | 1 - sonoff/_changelog.ino | 5 ++++- sonoff/sonoff.ino | 5 +---- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 2 +- sonoff/xdrv_01_webserver.ino | 2 +- sonoff/xdrv_04_light.ino | 1 - sonoff/xdrv_06_snfbridge.ino | 4 ++-- sonoff/xdrv_08_serial_bridge.ino | 2 +- sonoff/xdrv_09_timers.ino | 1 - sonoff/xdrv_18_armtronix_dimmers.ino | 4 ++-- sonoff/xnrg_02_cse7766.ino | 2 +- sonoff/xsns_05_ds18x20.ino | 4 +++- sonoff/xsns_34_hx711.ino | 6 +++--- sonoff/xsns_38_az7798.ino | 4 +--- 15 files changed, 21 insertions(+), 24 deletions(-) diff --git a/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.cpp b/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.cpp index 0be2c9de3..207fc07f8 100644 --- a/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.cpp +++ b/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.cpp @@ -27,7 +27,6 @@ TasmotaModbus::TasmotaModbus(int receive_pin, int transmit_pin) : TasmotaSerial( uint16_t CalculateCRC(uint8_t *frame, uint8_t num) { uint16_t crc = 0xFFFF; - uint16_t flag; for (uint8_t i = 0; i < num; i++) { crc ^= frame[i]; diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 1c96f7d5e..90cdb32ea 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1 20181225 +/* 6.4.1.1 20181224 + * Fix most compiler warnings + * + * 6.4.1 20181224 * Change RAM usage BMP/BME I2C sensors * Change FallbackTopic from cmnd// to cmnd/_fb/ to discriminate from Topic (#1528) * Change FallbackTopic detection (#4706) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index be5964a94..422049b73 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1026,7 +1026,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) Serial.printf("%s\n", dataBuf); // "Hello Tiger\n" } else if (2 == index || 4 == index) { - for (int i = 0; i < data_len; i++) { + for (uint16_t i = 0; i < data_len; i++) { Serial.write(dataBuf[i]); // "Hello Tiger" or "A0" } } @@ -2627,8 +2627,6 @@ extern struct rst_info resetInfo; void setup(void) { - byte idx; - RtcRebootLoad(); if (!RtcRebootValid()) { RtcReboot.fast_reboot_count = 0; } RtcReboot.fast_reboot_count++; @@ -2755,7 +2753,6 @@ void setup(void) } blink_powersave = power; - char stopic[TOPSZ]; snprintf_P(log_data, sizeof(log_data), PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), PROJECT, Settings.friendlyname[0], my_version, my_image); AddLog(LOG_LEVEL_INFO); diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 6e635a341..532547a63 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040100 +#define VERSION 0x06040101 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index 5c80651e9..ceb080408 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -140,7 +140,7 @@ size_t strchrspn(const char *str1, int character) char* subStr(char* dest, char* str, const char *delim, int index) { char *act; - char *sub; + char *sub = NULL; char *ptr; int i; diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 046181283..7d36ce8e1 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1591,7 +1591,7 @@ void HandleUploadLoop(void) upload_error = abs(result); return; } else if (result > 0) { - if (result > upload.currentSize) { + if ((size_t)result > upload.currentSize) { // Offset is larger than the buffer supplied, this should not happen upload_error = 9; // File too large - Failed to decode RF firmware return; diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index ae6644dda..8aac13f69 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -1319,7 +1319,6 @@ boolean LightCommand(void) bool validtable = (XdrvMailbox.data_len > 0); char scolor[25]; if (validtable) { - uint16_t HSB[3]; if (strstr(XdrvMailbox.data, ",")) { // Command with up to 5 comma separated parameters for (int i = 0; i < LST_RGBWC; i++) { char *substr; diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 30bd6e4f0..8e6b62641 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -56,7 +56,7 @@ unsigned long sonoff_bridge_last_learn_time = 0; ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size) { - for (int i = 0; i < size; i++) { + for (size_t i = 0; i < size; i++) { if (buf[i] == ':') { return i; } @@ -66,7 +66,7 @@ ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size) ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size) { - for (ssize_t i = 0; i < size; i++) { + for (size_t i = 0; i < size; i++) { if (buf[i] == '\n') { return i; } diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index e901e9958..b29bb7393 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -122,7 +122,7 @@ boolean SerialBridgeCommand(void) Settings.sbaudrate = (1 == XdrvMailbox.payload) ? SOFT_BAUDRATE / 1200 : baud; SerialBridgeSerial->begin(Settings.sbaudrate * 1200); // Reinitialize serial port with new baud rate } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_LVALUE, command, Settings.sbaudrate * 1200); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.sbaudrate * 1200); } else serviced = false; // Unknown command diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 8273201d5..820125e3d 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -135,7 +135,6 @@ void DuskTillDawn(uint8_t *hour_up,uint8_t *minute_up, uint8_t *hour_down, uint8 // double Zeitzone = 2.0; //Sommerzeit double Zeitzone = ((double)time_timezone) / 60; double Zeitgleichung = BerechneZeitgleichung(&DK, T); - double Minuten = Zeitgleichung * 60.0; double Zeitdifferenz = 12.0*acos((sin(h) - sin(B)*sin(DK)) / (cos(B)*cos(DK)))/pi; double AufgangOrtszeit = 12.0 - Zeitdifferenz - Zeitgleichung; double UntergangOrtszeit = 12.0 + Zeitdifferenz - Zeitgleichung; diff --git a/sonoff/xdrv_18_armtronix_dimmers.ino b/sonoff/xdrv_18_armtronix_dimmers.ino index 795149bff..9e0e9c7f9 100644 --- a/sonoff/xdrv_18_armtronix_dimmers.ino +++ b/sonoff/xdrv_18_armtronix_dimmers.ino @@ -155,11 +155,11 @@ void ArmtronixSetWifiLed(void) snprintf_P(log_data, sizeof(log_data), "ARM: Set WiFi LED to state %d (%d)", wifi_state, WifiState()); AddLog(LOG_LEVEL_DEBUG); - char state = '0' + (wifi_state & 1 > 0); + char state = '0' + ((wifi_state & 1) > 0); ArmtronixSerial->print("Setled:"); ArmtronixSerial->write(state); ArmtronixSerial->write(','); - state = '0' + (wifi_state & 2 > 0); + state = '0' + ((wifi_state & 2) > 0); ArmtronixSerial->write(state); ArmtronixSerial->write(10); armtronix_wifi_state = WifiState(); diff --git a/sonoff/xnrg_02_cse7766.ino b/sonoff/xnrg_02_cse7766.ino index 318fb02a7..2286a6fa3 100644 --- a/sonoff/xnrg_02_cse7766.ino +++ b/sonoff/xnrg_02_cse7766.ino @@ -41,7 +41,7 @@ uint8_t cse_receive_flag = 0; long voltage_cycle = 0; long current_cycle = 0; long power_cycle = 0; -unsigned long power_cycle_first = 0; +long power_cycle_first = 0; long cf_pulses = 0; long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; uint8_t cse_power_invalid = CSE_MAX_INVALID_POWER; diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index 1061df86d..ba7752741 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -261,7 +261,9 @@ void Ds18x20Init(void) ds18x20_pin = pin[GPIO_DSB]; OneWireResetSearch(); - for (ds18x20_sensors = 0; ds18x20_sensors < DS18X20_MAX_SENSORS; ds18x20_sensors) { + + ds18x20_sensors = 0; + while (ds18x20_sensors < DS18X20_MAX_SENSORS) { if (!OneWireSearch(ds18x20_sensor[ds18x20_sensors].address)) { break; } diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index c3f10ded9..75a06e7de 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -270,7 +270,7 @@ void HxEvery100mSecond(void) } else if (HX_CAL_RESET == hx_calibrate_step) { // Wait for stable reset if (hx_calibrate_timer) { - if (hx_weight < Settings.weight_reference) { + if (hx_weight < (long)Settings.weight_reference) { hx_calibrate_step--; hx_calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); HxCalibrationStateTextJson(2); @@ -281,7 +281,7 @@ void HxEvery100mSecond(void) } else if (HX_CAL_FIRST == hx_calibrate_step) { // Wait for first reference weight if (hx_calibrate_timer) { - if (hx_weight > Settings.weight_reference) { + if (hx_weight > (long)Settings.weight_reference) { hx_calibrate_step--; } } else { @@ -289,7 +289,7 @@ void HxEvery100mSecond(void) } } else if (HX_CAL_DONE == hx_calibrate_step) { // Second stable reference weight - if (hx_weight > Settings.weight_reference) { + if (hx_weight > (long)Settings.weight_reference) { hx_calibrate_step = HX_CAL_FINISH; // Calibration done Settings.weight_calibration = hx_weight / Settings.weight_reference; hx_weight = 0; // Reset calibration value diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino index f909bb061..b9ac0a012 100644 --- a/sonoff/xsns_38_az7798.ino +++ b/sonoff/xsns_38_az7798.ino @@ -107,9 +107,7 @@ * * : responds with : T19.9C:C2167ppm:H57.4% * This one gives the current readings. - ********************************************************************************************** - -/*********************************************************************************************/ +\*********************************************************************************************/ #include From 7291f7d2f7c992e09b9dc6d773394c4e12eab0f3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 24 Dec 2018 18:35:13 +0100 Subject: [PATCH 0764/2222] Fix compiler warning Fix compiler warning --- sonoff/xdrv_07_domoticz.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 3eb3fa275..80155925c 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -80,7 +80,7 @@ void MqttPublishDomoticzFanState() int fan_speed = GetFanspeed(); snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fan_speed * 10); snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE, - Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); + (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); MqttPublish(domoticz_in_topic); fan_debounce = millis(); @@ -107,7 +107,7 @@ void MqttPublishDomoticzPowerState(byte device) snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE, - Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); + (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); MqttPublish(domoticz_in_topic); } } From 96409313457c96361e25c63818daa9b13b57077d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 26 Dec 2018 14:21:00 +0100 Subject: [PATCH 0765/2222] Change switch debounce Change switch input detection by optimizing switch debounce (#4724) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 66 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 90cdb32ea..35be41b13 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.4.1.1 20181224 * Fix most compiler warnings + * Change switch input detection by optimizing switch debounce (#4724) * * 6.4.1 20181224 * Change RAM usage BMP/BME I2C sensors diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 422049b73..561709f51 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -127,6 +127,7 @@ int blinks = 201; // Number of LED blinks uint32_t uptime = 0; // Counting every second until 4294967295 = 130 year uint32_t loop_load_avg = 0; // Indicative loop load average uint32_t global_update = 0; // Timestamp of last global temperature and humidity update +uint32_t switch_change[MAX_SWITCHES]; // Timestamp of last switch change float global_temperature = 0; // Provide a global temperature to be used by some sensors float global_humidity = 0; // Provide a global humidity to be used by some sensors char *ota_url; // OTA url string pointer @@ -1898,7 +1899,7 @@ void SwitchHandler(byte mode) uint16_t loops_per_second = 1000 / Settings.switch_debounce; for (byte i = 0; i < MAX_SWITCHES; i++) { - if ((pin[GPIO_SWT1 +i] < 99) || (mode)) { + if (((pin[GPIO_SWT1 +i] < 99) && (TimePassedSince(switch_change[i]) > Settings.switch_debounce)) || (mode)) { if (holdwallswitch[i]) { holdwallswitch[i]--; @@ -2405,21 +2406,60 @@ void SerialInput(void) } /********************************************************************************************/ +void SwitchChange(byte index) +{ + switch_change[index] = millis(); +} + +void SwitchChange1(void) +{ + SwitchChange(0); +} + +void SwitchChange2(void) +{ + SwitchChange(1); +} + +void SwitchChange3(void) +{ + SwitchChange(2); +} + +void SwitchChange4(void) +{ + SwitchChange(3); +} + +void SwitchChange5(void) +{ + SwitchChange(4); +} + +void SwitchChange6(void) +{ + SwitchChange(5); +} + +void SwitchChange7(void) +{ + SwitchChange(6); +} + +void SwitchChange8(void) +{ + SwitchChange(7); +} + void GpioSwitchPinMode(uint8_t index) { - if (pin[GPIO_SWT1 +index] < 99) { + if ((pin[GPIO_SWT1 +index] < 99) && (index < MAX_SWITCHES)) { pinMode(pin[GPIO_SWT1 +index], (16 == pin[GPIO_SWT1 +index]) ? INPUT_PULLDOWN_16 : bitRead(switch_no_pullup, index) ? INPUT : INPUT_PULLUP); -/* - // Re-enable pull-up on Shelly2 as of 20181110 (#4255) - uint8_t no_pullup = bitRead(switch_no_pullup, index); // 0 = INPUT_PULLUP, 1 = INPUT - if (no_pullup) { - if (SHELLY2 == Settings.module) { - // Switchmodes : TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION - no_pullup = (Settings.switchmode[index] < PUSHBUTTON); // INPUT on TOGGLE, FOLLOW and FOLLOW_INV. INPUT_PULLUP on anything else - } - } - pinMode(pin[GPIO_SWT1 +index], (16 == pin[GPIO_SWT1 +index]) ? INPUT_PULLDOWN_16 : (no_pullup) ? INPUT : INPUT_PULLUP); -*/ + + typedef void (*function)(void) ; + function switch_callbacks[MAX_SWITCHES] = { SwitchChange1, SwitchChange2, SwitchChange3, SwitchChange4, SwitchChange5, SwitchChange6, SwitchChange7, SwitchChange8 }; + detachInterrupt(pin[GPIO_SWT1 +index]); + attachInterrupt(pin[GPIO_SWT1 +index], switch_callbacks[index], CHANGE); } } From 8ce6b5a01d4e765708a1f8e75b054d4c47038958 Mon Sep 17 00:00:00 2001 From: "K.C. Budd" Date: Wed, 26 Dec 2018 12:10:47 -0800 Subject: [PATCH 0766/2222] Add INPUT_PULLUP option for single DS18B20 --- sonoff/my_user_config.h | 1 + sonoff/xsns_05_ds18b20.ino | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 5fcbecabf..8684ac7a0 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -283,6 +283,7 @@ //#define USE_DS18x20_LEGACY // Optional for more than one DS18x20 sensors with dynamic scan using library OneWire (+1k5 code) #define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) // #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors +// #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistors for single DS18B20 // -- I2C sensors --------------------------------- #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index dfd4394dd..9951ee0d0 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -42,7 +42,11 @@ uint8_t OneWireReset(void) uint8_t retries = 125; //noInterrupts(); +#ifdef DS18B20_INTERNAL_PULLUP + pinMode(ds18x20_pin, INPUT_PULLUP); +#else pinMode(ds18x20_pin, INPUT); +#endif do { if (--retries == 0) { return 0; @@ -52,7 +56,11 @@ uint8_t OneWireReset(void) pinMode(ds18x20_pin, OUTPUT); digitalWrite(ds18x20_pin, LOW); delayMicroseconds(480); +#ifdef DS18B20_INTERNAL_PULLUP + pinMode(ds18x20_pin, INPUT_PULLUP); +#else pinMode(ds18x20_pin, INPUT); +#endif delayMicroseconds(70); uint8_t r = !digitalRead(ds18x20_pin); //interrupts(); @@ -81,7 +89,11 @@ uint8_t OneWireReadBit(void) pinMode(ds18x20_pin, OUTPUT); digitalWrite(ds18x20_pin, LOW); delayMicroseconds(3); +#ifdef DS18B20_INTERNAL_PULLUP + pinMode(ds18x20_pin, INPUT_PULLUP); +#else pinMode(ds18x20_pin, INPUT); +#endif delayMicroseconds(10); uint8_t r = digitalRead(ds18x20_pin); //interrupts(); From 4fcbaf99be07a4b1cdfbe6cd56b3d1baa58ad77d Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 27 Dec 2018 14:57:27 -0300 Subject: [PATCH 0767/2222] Add variable %timestamp% to be used in rules This PR adds a new variable %timestamp% to be used in a rule to allow the user to include the Time Stamp as Tasmota has for Status, Sensors, etc, for example: Command: publish stat/topic/sensor {"Time":"%timestamp%","mysensor":"%var1%"} Output: {"Time":"2018-12-27T12:52:57","mysensor":"1"} (https://github.com/arendst/Sonoff-Tasmota/issues/4734) --- sonoff/xdrv_10_rules.ino | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index c9d880128..cc0bb5b67 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -167,6 +167,10 @@ bool RulesRuleMatch(byte rule_set, String &event, String &rule) if (rule_param.startsWith(stemp)) { rule_param = String(GetMinutesUptime()); } + snprintf_P(stemp, sizeof(stemp), PSTR("%%TIMESTAMP%%")); + if (rule_param.startsWith(stemp)) { + rule_param = GetDateAndTime(DT_LOCAL).c_str(); + } #if defined(USE_TIMERS) && defined(USE_SUNRISE) snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNRISE%%")); if (rule_param.startsWith(stemp)) { @@ -313,6 +317,7 @@ bool RuleSetProcess(byte rule_set, String &event_saved) } commands.replace(F("%time%"), String(GetMinutesPastMidnight())); commands.replace(F("%uptime%"), String(GetMinutesUptime())); + commands.replace(F("%timestamp%"), GetDateAndTime(DT_LOCAL).c_str()); #if defined(USE_TIMERS) && defined(USE_SUNRISE) commands.replace(F("%sunrise%"), String(GetSunMinutes(0))); commands.replace(F("%sunset%"), String(GetSunMinutes(1))); From 5a44b12870ccc62b91165c3c437111e54f77e0c5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 28 Dec 2018 16:35:19 +0100 Subject: [PATCH 0768/2222] 6.4.1.2 Rewrite Switch driver 6.4.1.2 20181228 * Change switch driver making it modular and introduce input filter (#4665, #4724) * Add define DS18B20_INTERNAL_PULLUP to select internal input pullup when only one DS18B20 sensor is connected eliminating external resistor (#4738) * Add variable %timestamp% to rules (#4749) --- sonoff/_changelog.ino | 7 +- sonoff/sonoff.ino | 173 ++------------------------------ sonoff/sonoff_version.h | 2 +- sonoff/support_switch.ino | 202 ++++++++++++++++++++++++++++++++++++++ sonoff/xdrv_10_rules.ino | 4 +- sonoff/xsns_28_tm1638.ino | 4 +- 6 files changed, 221 insertions(+), 171 deletions(-) create mode 100644 sonoff/support_switch.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 35be41b13..981557afa 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,9 @@ -/* 6.4.1.1 20181224 +/* 6.4.1.2 20181228 + * Change switch driver making it modular and introduce input filter (#4665, #4724) + * Add define DS18B20_INTERNAL_PULLUP to select internal input pullup when only one DS18B20 sensor is connected eliminating external resistor (#4738) + * Add variable %timestamp% to rules (#4749) + * + * 6.4.1.1 20181224 * Fix most compiler warnings * Change switch input detection by optimizing switch debounce (#4724) * diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 561709f51..da6efe8cb 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -109,7 +109,6 @@ unsigned long pulse_timer[MAX_PULSETIMERS] = { 0 }; // Power off timer unsigned long blink_timer = 0; // Power cycle timer unsigned long backlog_delay = 0; // Command backlog delay unsigned long button_debounce = 0; // Button debounce timer -unsigned long switch_debounce = 0; // Switch debounce timer power_t power = 0; // Current copy of Settings.power power_t blink_power; // Blink power state power_t blink_mask = 0; // Blink relay active mask @@ -127,7 +126,6 @@ int blinks = 201; // Number of LED blinks uint32_t uptime = 0; // Counting every second until 4294967295 = 130 year uint32_t loop_load_avg = 0; // Indicative loop load average uint32_t global_update = 0; // Timestamp of last global temperature and humidity update -uint32_t switch_change[MAX_SWITCHES]; // Timestamp of last switch change float global_temperature = 0; // Provide a global temperature to be used by some sensors float global_humidity = 0; // Provide a global humidity to be used by some sensors char *ota_url; // OTA url string pointer @@ -137,7 +135,6 @@ uint16_t blink_counter = 0; // Number of blink cycles uint16_t seriallog_timer = 0; // Timer to disable Seriallog uint16_t syslog_timer = 0; // Timer to re-enable syslog_level uint16_t holdbutton[MAX_KEYS] = { 0 }; // Timer for button hold -uint16_t switch_no_pullup = 0; // Switch pull-up bitmask flags int16_t save_data_counter; // Counter and flag for config save to Flash RulesBitfield rules_flag; // Rule state flags (16 bits) uint8_t serial_local = 0; // Handle serial locally; @@ -155,9 +152,6 @@ uint8_t blinkspeed = 1; // LED blink rate uint8_t lastbutton[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states 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 -uint8_t virtualswitch[MAX_SWITCHES]; // Virtual switch states uint8_t pin[GPIO_MAX]; // Possible pin configurations uint8_t led_inverted = 0; // LED inverted flag (1 = (0 = On, 1 = Off)) uint8_t pwm_inverted = 0; // PWM inverted flag (1 = inverted) @@ -1163,7 +1157,6 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) else if ((CMND_SWITCHMODE == command_code) && (index > 0) && (index <= MAX_SWITCHES)) { if ((payload >= 0) && (payload < MAX_SWITCH_OPTION)) { Settings.switchmode[index -1] = payload; - GpioSwitchPinMode(index -1); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, index, Settings.switchmode[index-1]); } @@ -1648,7 +1641,7 @@ boolean MqttShowSensor(void) if (pin[GPIO_SWT1 +i] < 99) { #endif // USE_TM1638 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_JSON_SWITCH "%d\":\"%s\""), mqtt_data, i +1, GetStateText(swm ^ lastwallswitch[i])); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_SWITCH "%d\":\"%s\""), mqtt_data, i +1, GetStateText(swm ^ SwitchLastState(i))); } } XsnsCall(FUNC_JSON_APPEND); @@ -1888,93 +1881,6 @@ void ButtonHandler(void) } } -/*********************************************************************************************\ - * Switch handler -\*********************************************************************************************/ - -void SwitchHandler(byte mode) -{ - uint8_t button = NOT_PRESSED; - uint8_t switchflag; - uint16_t loops_per_second = 1000 / Settings.switch_debounce; - - for (byte i = 0; i < MAX_SWITCHES; i++) { - if (((pin[GPIO_SWT1 +i] < 99) && (TimePassedSince(switch_change[i]) > Settings.switch_debounce)) || (mode)) { - - if (holdwallswitch[i]) { - holdwallswitch[i]--; - if (0 == holdwallswitch[i]) { - SendKey(1, i +1, 3); // Execute command via MQTT - } - } - - if (mode) { - button = virtualswitch[i]; - } else { - if (!((uptime < 4) && (0 == pin[GPIO_SWT1 +i]))) { // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit - button = digitalRead(pin[GPIO_SWT1 +i]); - } - } - - if (button != lastwallswitch[i]) { - switchflag = 3; - switch (Settings.switchmode[i]) { - case TOGGLE: - switchflag = 2; // Toggle - break; - case FOLLOW: - switchflag = button &1; // Follow wall switch state - break; - case FOLLOW_INV: - switchflag = ~button &1; // Follow inverted wall switch state - break; - case PUSHBUTTON: - if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) { - switchflag = 2; // Toggle with pushbutton to Gnd - } - break; - case PUSHBUTTON_INV: - if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) { - switchflag = 2; // Toggle with releasing pushbutton from Gnd - } - break; - case PUSHBUTTON_TOGGLE: - if (button != lastwallswitch[i]) { - switchflag = 2; // Toggle with any pushbutton change - } - break; - case PUSHBUTTONHOLD: - if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) { - holdwallswitch[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) { - holdwallswitch[i] = 0; - switchflag = 2; // Toggle with pushbutton to Gnd - } - break; - case PUSHBUTTONHOLD_INV: - if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) { - holdwallswitch[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) { - holdwallswitch[i] = 0; - switchflag = 2; // Toggle with pushbutton to Gnd - } - break; - } - - if (switchflag < 3) { - if (!SendKey(1, i +1, switchflag)) { // Execute command via MQTT - ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < devices_present) - } - } - - lastwallswitch[i] = button; - } - } - } -} - /*********************************************************************************************\ * State loops \*********************************************************************************************/ @@ -2404,65 +2310,9 @@ void SerialInput(void) serial_in_byte_counter = 0; } } + /********************************************************************************************/ -void SwitchChange(byte index) -{ - switch_change[index] = millis(); -} - -void SwitchChange1(void) -{ - SwitchChange(0); -} - -void SwitchChange2(void) -{ - SwitchChange(1); -} - -void SwitchChange3(void) -{ - SwitchChange(2); -} - -void SwitchChange4(void) -{ - SwitchChange(3); -} - -void SwitchChange5(void) -{ - SwitchChange(4); -} - -void SwitchChange6(void) -{ - SwitchChange(5); -} - -void SwitchChange7(void) -{ - SwitchChange(6); -} - -void SwitchChange8(void) -{ - SwitchChange(7); -} - -void GpioSwitchPinMode(uint8_t index) -{ - if ((pin[GPIO_SWT1 +index] < 99) && (index < MAX_SWITCHES)) { - pinMode(pin[GPIO_SWT1 +index], (16 == pin[GPIO_SWT1 +index]) ? INPUT_PULLDOWN_16 : bitRead(switch_no_pullup, index) ? INPUT : INPUT_PULLUP); - - typedef void (*function)(void) ; - function switch_callbacks[MAX_SWITCHES] = { SwitchChange1, SwitchChange2, SwitchChange3, SwitchChange4, SwitchChange5, SwitchChange6, SwitchChange7, SwitchChange8 }; - detachInterrupt(pin[GPIO_SWT1 +index]); - attachInterrupt(pin[GPIO_SWT1 +index], switch_callbacks[index], CHANGE); - } -} - void GpioInit(void) { uint8_t mpin; @@ -2499,7 +2349,7 @@ void GpioInit(void) if (mpin) { if ((mpin >= GPIO_SWT1_NP) && (mpin < (GPIO_SWT1_NP + MAX_SWITCHES))) { - bitSet(switch_no_pullup, mpin - GPIO_SWT1_NP); + SwitchPullupFlag(mpin - GPIO_SWT1_NP); mpin -= (GPIO_SWT1_NP - GPIO_SWT1); } else if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) { @@ -2631,14 +2481,8 @@ void GpioInit(void) digitalWrite(pin[GPIO_LED1 +i], bitRead(led_inverted, i)); } } - for (byte i = 0; i < MAX_SWITCHES; i++) { - lastwallswitch[i] = 1; // Init global to virtual switch state; - if (pin[GPIO_SWT1 +i] < 99) { - GpioSwitchPinMode(i); - lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // Set global now so doesn't change the saved power state on first switch check - } - virtualswitch[i] = lastwallswitch[i]; - } + + SwitchInit(); #ifdef USE_WS2812 if (!light_type && (pin[GPIO_WS2812] < 99)) { // RGB led @@ -2826,10 +2670,9 @@ void loop(void) SetNextTimeInterval(button_debounce, Settings.button_debounce); ButtonHandler(); } - if (TimeReached(switch_debounce)) { - SetNextTimeInterval(switch_debounce, Settings.switch_debounce); - SwitchHandler(0); - } + + SwitchLoop(); + if (TimeReached(state_50msecond)) { SetNextTimeInterval(state_50msecond, 50); XdrvCall(FUNC_EVERY_50_MSECOND); diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 532547a63..490491e1c 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040101 +#define VERSION 0x06040102 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino new file mode 100644 index 000000000..7e53cffb1 --- /dev/null +++ b/sonoff/support_switch.ino @@ -0,0 +1,202 @@ +/* + support_switch.ino - switch support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 . +*/ + +#define SWITCH_V2 +#ifdef SWITCH_V2 +/*********************************************************************************************\ + * Switch support with input filter + * + * Inspired by (https://github.com/OLIMEX/olimex-iot-firmware-esp8266/blob/master/olimex/user/user_switch2.c) +\*********************************************************************************************/ + +#define SWITCH_STATE_FILTER 5 + +#include + +Ticker TickerSwitch; + +unsigned long switch_debounce = 0; // Switch debounce timer +uint16_t switch_no_pullup = 0; // Switch pull-up bitmask flags +uint8_t switch_state_buf[MAX_SWITCHES] = { SWITCH_STATE_FILTER / 2 }; +uint8_t lastwallswitch[MAX_SWITCHES]; // Last wall switch states +uint8_t holdwallswitch[MAX_SWITCHES] = { 0 }; // Timer for wallswitch push button hold +uint8_t switch_virtual[MAX_SWITCHES]; // Virtual switch states +uint8_t switches_found = 0; + +/********************************************************************************************/ + +void SwitchPullupFlag(uint16 switch_bit) +{ + bitSet(switch_no_pullup, switch_bit); +} + +uint8_t SwitchLastState(uint8_t index) +{ + return lastwallswitch[index]; +} + +void SwitchSetVirtual(uint8_t index, uint8_t state) +{ + switch_virtual[index] = state; +} + +uint8_t SwitchGetVirtual(uint8_t index) +{ + return switch_virtual[index]; +} + +/*********************************************************************************************/ + +void SwitchProbe(void) +{ + for (byte i = 0; i < MAX_SWITCHES; i++) { + if (pin[GPIO_SWT1 +i] < 99) { + if (!((uptime < 4) && (0 == pin[GPIO_SWT1 +i]))) { // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit + // Olimex user_switch2.c code to fix 50Hz induced pulses + if (1 == digitalRead(pin[GPIO_SWT1 +i])) { + if (switch_state_buf[i] < SWITCH_STATE_FILTER) { + switch_state_buf[i]++; + if (SWITCH_STATE_FILTER == switch_state_buf[i]) { + switch_virtual[i] = 1; + } + } + } else { + if (switch_state_buf[i] > 0) { + switch_state_buf[i]--; + if (0 == switch_state_buf[i]) { + switch_virtual[i] = 0; + } + } + } + } + } + } + TickerSwitch.attach_ms(10, SwitchProbe); // Re-arm as core 2.3.0 does only support ONCE mode +} + +void SwitchInit(void) +{ + switches_found = 0; + for (byte i = 0; i < MAX_SWITCHES; i++) { + lastwallswitch[i] = 1; // Init global to virtual switch state; + if (pin[GPIO_SWT1 +i] < 99) { + switches_found++; + pinMode(pin[GPIO_SWT1 +i], (16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 : bitRead(switch_no_pullup, i) ? INPUT : INPUT_PULLUP); + lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // Set global now so doesn't change the saved power state on first switch check + } + switch_virtual[i] = lastwallswitch[i]; + } + if (switches_found) { TickerSwitch.attach_ms(10, SwitchProbe); } +} + +/*********************************************************************************************\ + * Switch handler +\*********************************************************************************************/ + +void SwitchHandler(byte mode) +{ + uint8_t button = NOT_PRESSED; + uint8_t switchflag; + uint16_t loops_per_second = 1000 / Settings.switch_debounce; + + for (byte i = 0; i < MAX_SWITCHES; i++) { + if ((pin[GPIO_SWT1 +i] < 99) || (mode)) { + + + if (holdwallswitch[i]) { + holdwallswitch[i]--; + if (0 == holdwallswitch[i]) { + SendKey(1, i +1, 3); // Execute command via MQTT + } + } + + button = switch_virtual[i]; + +// enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION}; + + if (button != lastwallswitch[i]) { + switchflag = 3; + switch (Settings.switchmode[i]) { + case TOGGLE: + switchflag = 2; // Toggle + break; + case FOLLOW: + switchflag = button &1; // Follow wall switch state + break; + case FOLLOW_INV: + switchflag = ~button &1; // Follow inverted wall switch state + break; + case PUSHBUTTON: + if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) { + switchflag = 2; // Toggle with pushbutton to Gnd + } + break; + case PUSHBUTTON_INV: + if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) { + switchflag = 2; // Toggle with releasing pushbutton from Gnd + } + break; + case PUSHBUTTON_TOGGLE: + if (button != lastwallswitch[i]) { + switchflag = 2; // Toggle with any pushbutton change + } + break; + case PUSHBUTTONHOLD: + if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) { + holdwallswitch[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) { + holdwallswitch[i] = 0; + switchflag = 2; // Toggle with pushbutton to Gnd + } + break; + case PUSHBUTTONHOLD_INV: + if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) { + holdwallswitch[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) { + holdwallswitch[i] = 0; + switchflag = 2; // Toggle with pushbutton to Gnd + } + break; + } + + if (switchflag < 3) { + if (!SendKey(1, i +1, switchflag)) { // Execute command via MQTT + ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < devices_present) + } + } + + lastwallswitch[i] = button; + } + } + } +} + +void SwitchLoop(void) +{ + if (switches_found) { + if (TimeReached(switch_debounce)) { + SetNextTimeInterval(switch_debounce, Settings.switch_debounce); + SwitchHandler(0); + } + } +} + +#endif // SWITCH_V2 diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index cc0bb5b67..3125ef8fa 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -317,7 +317,7 @@ bool RuleSetProcess(byte rule_set, String &event_saved) } commands.replace(F("%time%"), String(GetMinutesPastMidnight())); commands.replace(F("%uptime%"), String(GetMinutesUptime())); - commands.replace(F("%timestamp%"), GetDateAndTime(DT_LOCAL).c_str()); + commands.replace(F("%timestamp%"), GetDateAndTime(DT_LOCAL).c_str()); #if defined(USE_TIMERS) && defined(USE_SUNRISE) commands.replace(F("%sunrise%"), String(GetSunMinutes(0))); commands.replace(F("%sunset%"), String(GetSunMinutes(1))); @@ -410,7 +410,7 @@ void RulesEvery50ms(void) if (pin[GPIO_SWT1 +i] < 99) { #endif // USE_TM1638 boolean swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); - snprintf_P(json_event, sizeof(json_event), PSTR("{\"" D_JSON_SWITCH "%d\":{\"Boot\":%d}}"), i +1, (swm ^ lastwallswitch[i])); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"" D_JSON_SWITCH "%d\":{\"Boot\":%d}}"), i +1, (swm ^ SwitchLastState(i))); RulesProcessEvent(json_event); } } diff --git a/sonoff/xsns_28_tm1638.ino b/sonoff/xsns_28_tm1638.ino index 61852b40d..b446fa97b 100644 --- a/sonoff/xsns_28_tm1638.ino +++ b/sonoff/xsns_28_tm1638.ino @@ -176,8 +176,8 @@ void TmLoop(void) if (tm1638_state) { byte buttons = Tm1638GetButtons(); for (byte i = 0; i < MAX_SWITCHES; i++) { - virtualswitch[i] = (buttons &1) ^1; - byte color = (virtualswitch[i]) ? TM1638_COLOR_NONE : TM1638_COLOR_RED; + SwitchSetVirtual(i, (buttons &1) ^1); + byte color = (SwitchGetVirtual(i)) ? TM1638_COLOR_NONE : TM1638_COLOR_RED; Tm1638SetLED(color, i); buttons >>= 1; } From 5026cbd38ded6aea4aedab57e2a138b8c4ce264a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 28 Dec 2018 17:30:32 +0100 Subject: [PATCH 0769/2222] Update platformio.ini with stage Update platformio.ini with latest stage option --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 2546e6864..461ca61ea 100644 --- a/platformio.ini +++ b/platformio.ini @@ -107,10 +107,10 @@ build_flags = ${esp82xx_defaults.build_flags} ; enable one option set -> No exception recommended ; No exception code in firmware -fno-exceptions - -lstdc++-nox + -lstdc++ ; Exception code in firmware /needs much space! 90k ; -fexceptions -; -lstdc++ +; -lstdc++-exc [core_active] ; Select one core set for platform and build_flags From afe83a3460d069ee982fa4899b7d837da6b2481b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 29 Dec 2018 17:19:13 +0100 Subject: [PATCH 0770/2222] Prep for template tuning --- sonoff/sonoff.ino | 46 +++++++++++++++---------------- sonoff/support.ino | 15 ++++++++++ sonoff/xdrv_01_webserver.ino | 31 ++++++++++----------- sonoff/xdrv_02_mqtt.ino | 3 +- sonoff/xdrv_04_light.ino | 6 ++-- sonoff/xdrv_11_knx.ino | 26 ++++++++--------- sonoff/xdrv_12_home_assistant.ino | 9 ++---- 7 files changed, 72 insertions(+), 64 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index da6efe8cb..0deb833dd 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -175,7 +175,7 @@ byte mdns_delayed_start = 0; // mDNS delayed start boolean latest_uptime_flag = true; // Signal latest uptime boolean pwm_present = false; // Any PWM channel configured with SetOption15 0 boolean mdns_begun = false; // mDNS active -mytmplt my_module; // Active copy of Module name and GPIOs (23 x 8 bits) +myio my_module; // Active copy of Module GPIOs (18 x 8 bits) StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits) char my_version[33]; // Composed version string char my_image[33]; // Code image and/or commit @@ -856,8 +856,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } restart_flag = 2; } - 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); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.module +1, ModuleName().c_str()); } else if (CMND_MODULES == command_code) { for (byte i = 0; i < MAXMODULE; i++) { @@ -867,8 +866,7 @@ void MqttDataHandler(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), kModules[i].name); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, i +1, stemp1); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, i +1, AnyModuleName(i).c_str()); if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == MAXMODULE -1)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]}"), mqtt_data); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); @@ -879,9 +877,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) mqtt_data[0] = '\0'; } else if ((CMND_GPIO == command_code) && (index < MAX_GPIO_PIN)) { - mytmplt cmodule; - memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); - if ((GPIO_USER == ValidGPIO(index, cmodule.gp.io[index])) && (payload >= 0) && (payload < GPIO_SENSOR_END)) { + myio cmodule; + ModuleGpios(&cmodule); + if ((GPIO_USER == ValidGPIO(index, cmodule.io[index])) && (payload >= 0) && (payload < GPIO_SENSOR_END)) { bool present = false; for (byte i = 0; i < sizeof(kGpioNiceList); i++) { uint8_t midx = pgm_read_byte(kGpioNiceList + i); @@ -889,7 +887,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } if (present) { for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if ((GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) && (Settings.my_gp.io[i] == payload)) { + if ((GPIO_USER == ValidGPIO(i, cmodule.io[i])) && (Settings.my_gp.io[i] == payload)) { Settings.my_gp.io[i] = 0; } } @@ -899,7 +897,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { + if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { if (jsflg) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); jsflg = 1; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_GPIO "%d\":\"%d (%s)\""), @@ -913,12 +911,12 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } } else if (CMND_GPIOS == command_code) { - mytmplt cmodule; - memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); + myio cmodule; + ModuleGpios(&cmodule); uint8_t midx; for (byte i = 0; i < sizeof(kGpioNiceList); i++) { midx = pgm_read_byte(kGpioNiceList + i); - if (!GetUsedInModule(midx, cmodule.gp.io)) { + if (!GetUsedInModule(midx, cmodule.io)) { if (!jsflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_GPIOS "%d\":["), lines); @@ -2317,7 +2315,6 @@ void GpioInit(void) { uint8_t mpin; uint8_t key_no_pullup = 0; - mytmplt def_module; if (Settings.module >= MAXMODULE) { Settings.module = MODULE; @@ -2327,14 +2324,17 @@ void GpioInit(void) baudrate = APP_BAUDRATE; } - memcpy_P(&def_module, &kModules[Settings.module], sizeof(def_module)); - strlcpy(my_module.name, def_module.name, sizeof(my_module.name)); + myio def_gp; + ModuleGpios(&def_gp); + +// AddLogSerial(LOG_LEVEL_DEBUG, (uint8_t *)&def_gp, sizeof(def_gp)); + for (byte i = 0; i < MAX_GPIO_PIN; i++) { if (Settings.my_gp.io[i] > GPIO_NONE) { - my_module.gp.io[i] = Settings.my_gp.io[i]; + my_module.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]; + if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < GPIO_USER)) { + my_module.io[i] = def_gp.io[i]; } } @@ -2342,7 +2342,7 @@ void GpioInit(void) pin[i] = 99; } for (byte i = 0; i < MAX_GPIO_PIN; i++) { - mpin = ValidGPIO(i, my_module.gp.io[i]); + mpin = ValidGPIO(i, my_module.io[i]); // snprintf_P(log_data, sizeof(log_data), PSTR("DBG: gpio pin %d, mpin %d"), i, mpin); // AddLog(LOG_LEVEL_DEBUG); @@ -2397,11 +2397,11 @@ void GpioInit(void) for (byte i = 0; i < GPIO_MAX; i++) { if ((pin[i] >= 12) && (pin[i] <=14)) pin[i] = 99; } - my_module.gp.io[12] = GPIO_SPI_MISO; + my_module.io[12] = GPIO_SPI_MISO; pin[GPIO_SPI_MISO] = 12; - my_module.gp.io[13] = GPIO_SPI_MOSI; + my_module.io[13] = GPIO_SPI_MOSI; pin[GPIO_SPI_MOSI] = 13; - my_module.gp.io[14] = GPIO_SPI_CLK; + my_module.io[14] = GPIO_SPI_CLK; pin[GPIO_SPI_CLK] = 14; } soft_spi_flg = ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && ((pin[GPIO_SSPI_MOSI] < 99) || (pin[GPIO_SSPI_MOSI] < 99))); diff --git a/sonoff/support.ino b/sonoff/support.ino index ceb080408..77b23eb5d 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -492,6 +492,21 @@ String PressureUnit(void) return (Settings.flag.pressure_conversion) ? String(D_UNIT_MILLIMETER_MERCURY) : String(D_UNIT_PRESSURE); } +String AnyModuleName(uint8_t index) +{ + return FPSTR(kModules[index].name); +} + +String ModuleName() +{ + return FPSTR(kModules[Settings.module].name); +} + +void ModuleGpios(myio *gp) +{ + memcpy_P(gp, &kModules[Settings.module].gp, 18); +} + void SetGlobalValues(float temperature, float humidity) { global_update = uptime; diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 7d36ce8e1..16201c2a1 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -169,7 +169,7 @@ const char HTTP_SCRIPT_MODULE2[] PROGMEM = "x.send();" "}"; const char HTTP_SCRIPT_MODULE3[] PROGMEM = - "}1'%d'>%s (%02d)}2"; // "}1" and "}2" means do not use "}x" in Module name and Sensor name + "}1'%d'>%s (%d)}2"; // "}1" and "}2" means do not use "}x" in Module name and Sensor name const char HTTP_SCRIPT_INFO_BEGIN[] PROGMEM = "function i(){" @@ -492,7 +492,7 @@ void ShowPage(String &page, bool auth) } page.replace(F("{a}"), String(Settings.web_refresh)); - page.replace(F("{ha"), my_module.name); + page.replace(F("{ha"), ModuleName()); page.replace(F("{h}"), Settings.friendlyname[0]); String info = ""; @@ -798,21 +798,20 @@ void HandleModuleConfiguration(void) char stemp[20]; uint8_t midx; - mytmplt cmodule; - memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); + myio cmodule; + ModuleGpios(&cmodule); if (WebServer->hasArg("m")) { String page = ""; for (byte i = 0; i < MAXMODULE; i++) { midx = pgm_read_byte(kModuleNiceList + i); - snprintf_P(stemp, sizeof(stemp), kModules[midx].name); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE3, midx, stemp, midx +1); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE3, midx, AnyModuleName(midx).c_str(), midx +1); page += mqtt_data; } page += "}3"; // String separator means do not use "}3" in Module name and Sensor name for (byte j = 0; j < sizeof(kGpioNiceList); j++) { midx = pgm_read_byte(kGpioNiceList + j); - if (!GetUsedInModule(midx, cmodule.gp.io)) { + if (!GetUsedInModule(midx, cmodule.io)) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE3, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); page += mqtt_data; } @@ -828,8 +827,8 @@ void HandleModuleConfiguration(void) page += FPSTR(HTTP_SCRIPT_MODULE1); page.replace(F("}4"), String(Settings.module)); for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,%d);"), my_module.gp.io[i], i); // g0 - g16 + if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,%d);"), my_module.io[i], i); // g0 - g16 page += mqtt_data; } } @@ -837,11 +836,10 @@ void HandleModuleConfiguration(void) page += FPSTR(HTTP_HEAD_STYLE); page.replace(F(""), F("")); page += FPSTR(HTTP_FORM_MODULE); - snprintf_P(stemp, sizeof(stemp), kModules[MODULE].name); - page.replace(F("{mt"), stemp); + page.replace(F("{mt"), AnyModuleName(MODULE)); page += F("
          " D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ")
          GAfnum / GAarea / GAfdef -> {optex}
          , {m} = , {e} =
          , {m} = , {e} =
          , {m} = , {e} =
          , {m} = , {e} =
          , {m} = , {e} =
          , {m} = , {e} =
          , {m} = , {e} =
          , {m} = , {e} =
          , {m} = , {e} =
          , {m} = , {e} =
          , {m} = , {e} =
          , {m} = , {e} =
          "); for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { + if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), (WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "ESP8285" :(10==i)? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); @@ -863,14 +861,14 @@ void ModuleSaveSettings(void) byte new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); Settings.last_module = Settings.module; Settings.module = new_module; - mytmplt cmodule; - memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); + myio cmodule; + ModuleGpios(&cmodule); String gpios = ""; for (byte i = 0; i < MAX_GPIO_PIN; i++) { if (Settings.last_module != new_module) { Settings.my_gp.io[i] = 0; } else { - if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { + if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), i); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); @@ -878,8 +876,7 @@ void ModuleSaveSettings(void) } } } - snprintf_P(stemp, sizeof(stemp), kModules[Settings.module].name); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), stemp, gpios.c_str()); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), ModuleName().c_str(), gpios.c_str()); AddLog(LOG_LEVEL_INFO); } diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 7ba5cf47a..a621ef100 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -415,8 +415,7 @@ void MqttConnected(void) if (mqtt_initial_connection_state) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), - my_module.name, my_version, my_image, GetFallbackTopic_P(stopic, CMND, ""), Settings.mqtt_grptopic); -// my_module.name, my_version, my_image, mqtt_client, Settings.mqtt_grptopic); + ModuleName().c_str(), my_version, my_image, GetFallbackTopic_P(stopic, CMND, ""), Settings.mqtt_grptopic); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); #ifdef USE_WEBSERVER if (Settings.webserver) { diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 8aac13f69..8134ba19c 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -373,15 +373,15 @@ void LightInit(void) } } if (SONOFF_LED == Settings.module) { // Fix Sonoff Led instabilities - if (!my_module.gp.io[4]) { + if (!my_module.io[4]) { pinMode(4, OUTPUT); // Stop floating outputs digitalWrite(4, LOW); } - if (!my_module.gp.io[5]) { + if (!my_module.io[5]) { pinMode(5, OUTPUT); // Stop floating outputs digitalWrite(5, LOW); } - if (!my_module.gp.io[14]) { + if (!my_module.io[14]) { pinMode(14, OUTPUT); // Stop floating outputs digitalWrite(14, LOW); } diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 9095b4efc..03a77744c 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -465,11 +465,11 @@ void KNX_INIT(void) // and activate options according to the hardware /*for (int i = GPIO_REL1; i < GPIO_REL8 + 1; ++i) { - if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_REL1].show = true; } + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_REL1].show = true; } } for (int i = GPIO_REL1_INV; i < GPIO_REL8_INV + 1; ++i) { - if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_REL1_INV].show = true; } + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_REL1_INV].show = true; } }*/ for (int i = 0; i < devices_present; ++i) { @@ -477,27 +477,27 @@ void KNX_INIT(void) } for (int i = GPIO_SWT1; i < GPIO_SWT4 + 1; ++i) { - if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } } for (int i = GPIO_KEY1; i < GPIO_KEY4 + 1; ++i) { - if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } } for (int i = GPIO_SWT1_NP; i < GPIO_SWT4_NP + 1; ++i) { - if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_SWT1_NP + 8].show = true; } + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1_NP + 8].show = true; } } for (int i = GPIO_KEY1_NP; i < GPIO_KEY4_NP + 1; ++i) { - if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_KEY1_NP + 8].show = true; } + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1_NP + 8].show = true; } } - if (GetUsedInModule(GPIO_DHT11, my_module.gp.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_DHT22, my_module.gp.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_SI7021, my_module.gp.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_DSB, my_module.gp.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_DHT11, my_module.gp.io)) { device_param[KNX_HUMIDITY-1].show = true; } - if (GetUsedInModule(GPIO_DHT22, my_module.gp.io)) { device_param[KNX_HUMIDITY-1].show = true; } - if (GetUsedInModule(GPIO_SI7021, my_module.gp.io)) { device_param[KNX_HUMIDITY-1].show = true; } + if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_DSB, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } // Sonoff 31 or Sonoff Pow or any HLW8012 based device or Sonoff POW R2 or Any device with a Pzem004T if ( ( SONOFF_S31 == Settings.module ) || ( SONOFF_POW_R2 == Settings.module ) || ( energy_flg != ENERGY_NONE ) ) { diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 350fe1ca6..233144e4b 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -237,10 +237,9 @@ void HAssAnnounceRelayLight(void) snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_CT, mqtt_data, color_temp_command_topic, state_topic); } } - snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data, unique_id, ESP.getChipId(), - Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); + Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image, "Tasmota"); snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } @@ -287,10 +286,9 @@ void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, if (toggle) snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, mqtt_data); else snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_ONOFF, mqtt_data, Settings.state_text[0]); - snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data, unique_id, ESP.getChipId(), - Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); + Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image, "Tasmota"); snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } @@ -413,10 +411,9 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_ANY, mqtt_data, sensorname, subsensortype); } - snprintf_P(stemp1, sizeof(stemp1), kModules[Settings.module].name); snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data, unique_id, ESP.getChipId(), - Settings.friendlyname[0], stemp1, my_version, my_image, "Tasmota"); + Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image, "Tasmota"); snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } From 7ebb7a6067de6cb842fad1233e33abdb81789890 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 29 Dec 2018 19:46:28 +0100 Subject: [PATCH 0771/2222] 6.4.1.3 Change sonoff_template.h 6.4.1.3 20181229 * Change sonoff_template.h module lay-out by removing non-configurable GPIOs --- sonoff/_changelog.ino | 5 +- sonoff/settings.ino | 6 +- sonoff/sonoff.ino | 19 +- sonoff/sonoff_template.h | 546 ++++++++++++++++++++++++++-------- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 24 +- sonoff/xdrv_01_webserver.ino | 6 +- sonoff/xdrv_16_tuyadimmer.ino | 2 +- 8 files changed, 473 insertions(+), 137 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 981557afa..2e65c4a16 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.2 20181228 +/* 6.4.1.3 20181229 + * Change sonoff_template.h module lay-out by removing non-configurable GPIOs + * + * 6.4.1.2 20181228 * Change switch driver making it modular and introduce input filter (#4665, #4724) * Add define DS18B20_INTERNAL_PULLUP to select internal input pullup when only one DS18B20 sensor is connected eliminating external resistor (#4738) * Add variable %timestamp% to rules (#4749) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 46c1d849d..3c6a6465e 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -424,7 +424,7 @@ void SettingsDefaultSet2(void) // Module // Settings.flag.interlock = 0; Settings.module = MODULE; -// for (byte i = 0; i < MAX_GPIO_PIN; i++) { Settings.my_gp.io[i] = 0; } +// for (byte i = 0; i < sizeof(Settings.my_gp); i++) { Settings.my_gp.io[i] = GPIO_NONE; } 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])); @@ -742,7 +742,7 @@ void SettingsDelta(void) Settings.altitude = 0; } if (Settings.version < 0x0508000B) { - for (byte i = 0; i < MAX_GPIO_PIN; i++) { // Move GPIO_LEDs + for (byte i = 0; i < sizeof(Settings.my_gp); 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 } @@ -829,7 +829,7 @@ void SettingsDelta(void) Settings.switchmode[i] = SWITCH_MODE; } } - for (byte i = 0; i < MAX_GPIO_PIN; i++) { + for (byte i = 0; i < sizeof(Settings.my_gp); i++) { if (Settings.my_gp.io[i] >= GPIO_SWT5) { // Move up from GPIO_SWT5 to GPIO_KEY1 Settings.my_gp.io[i] += 4; } diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 0deb833dd..e1d796c57 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -850,8 +850,8 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) Settings.last_module = Settings.module; Settings.module = payload; if (Settings.last_module != payload) { - for (byte i = 0; i < MAX_GPIO_PIN; i++) { - Settings.my_gp.io[i] = 0; + for (byte i = 0; i < sizeof(Settings.my_gp); i++) { + Settings.my_gp.io[i] = GPIO_NONE; } } restart_flag = 2; @@ -876,7 +876,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } mqtt_data[0] = '\0'; } - else if ((CMND_GPIO == command_code) && (index < MAX_GPIO_PIN)) { + else if ((CMND_GPIO == command_code) && (index < sizeof(Settings.my_gp))) { myio cmodule; ModuleGpios(&cmodule); if ((GPIO_USER == ValidGPIO(index, cmodule.io[index])) && (payload >= 0) && (payload < GPIO_SENSOR_END)) { @@ -886,9 +886,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if (midx == payload) { present = true; } } if (present) { - for (byte i = 0; i < MAX_GPIO_PIN; i++) { + for (byte i = 0; i < sizeof(Settings.my_gp); i++) { if ((GPIO_USER == ValidGPIO(i, cmodule.io[i])) && (Settings.my_gp.io[i] == payload)) { - Settings.my_gp.io[i] = 0; + Settings.my_gp.io[i] = GPIO_NONE; } } Settings.my_gp.io[index] = payload; @@ -896,7 +896,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); - for (byte i = 0; i < MAX_GPIO_PIN; i++) { + for (byte i = 0; i < sizeof(Settings.my_gp); i++) { if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { if (jsflg) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); jsflg = 1; @@ -2327,9 +2327,8 @@ void GpioInit(void) myio def_gp; ModuleGpios(&def_gp); -// AddLogSerial(LOG_LEVEL_DEBUG, (uint8_t *)&def_gp, sizeof(def_gp)); - for (byte i = 0; i < MAX_GPIO_PIN; i++) { + for (byte i = 0; i < sizeof(Settings.my_gp); i++) { if (Settings.my_gp.io[i] > GPIO_NONE) { my_module.io[i] = Settings.my_gp.io[i]; } @@ -2341,7 +2340,7 @@ void GpioInit(void) for (byte i = 0; i < GPIO_MAX; i++) { pin[i] = 99; } - for (byte i = 0; i < MAX_GPIO_PIN; i++) { + for (byte i = 0; i < sizeof(my_module.io); i++) { mpin = ValidGPIO(i, my_module.io[i]); // snprintf_P(log_data, sizeof(log_data), PSTR("DBG: gpio pin %d, mpin %d"), i, mpin); @@ -2567,7 +2566,7 @@ void setup(void) if (RtcReboot.fast_reboot_count > 4) { // Restarted 5 times Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic // Settings.last_module = SONOFF_BASIC; - for (byte i = 0; i < MAX_GPIO_PIN; i++) { + for (byte i = 0; i < sizeof(Settings.my_gp); i++) { Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors } } diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 48af9cf4b..bc14adb9a 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -275,6 +275,7 @@ enum SupportedModules { /********************************************************************************************/ #define MAX_GPIO_PIN 18 // Number of supported GPIO +#define MIN_FLASH_PINS 4 // Number of flash chip pins unusable for configuration (GPIO6, 7, 8 and 11) const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcFLFLolD6D7D5D8D0A0"; @@ -282,9 +283,13 @@ typedef struct MYIO { uint8_t io[MAX_GPIO_PIN]; } myio; +typedef struct MYCFGIO { + uint8_t io[MAX_GPIO_PIN - MIN_FLASH_PINS]; +} mycfgio; + typedef struct MYTMPLT { char name[15]; - myio gp; + mycfgio gp; } mytmplt; const uint8_t kGpioNiceList[] PROGMEM = { @@ -535,12 +540,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor 0, // GPIO05 - 0, // GPIO06 (SD_CLK Flash) - 0, // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - 0, // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO) - 0, // GPIO10 (SD_DATA3 Flash QIO) - 0, // GPIO11 (SD_CMD Flash) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) GPIO_USER, // GPIO14 Optional sensor @@ -555,7 +560,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) GPIO_USER, // GPIO14 Optional sensor @@ -568,7 +578,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor GPIO_USER, // GPIO05 Optional sensor - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) GPIO_USER, // GPIO14 Optional sensor @@ -582,7 +597,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) GPIO_USER, // GPIO14 Optional sensor @@ -595,7 +615,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_RXD, // GPIO03 Relay control GPIO_USER, // GPIO04 Optional sensor 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 0, GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) GPIO_USER, // GPIO14 Optional sensor @@ -605,7 +630,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY1, // GPIO00 Button 0, 0, 0, 0, GPIO_NRG_SEL, // GPIO05 HLW8012 Sel output (1 = Voltage) - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_NRG_CF1, // GPIO13 HLW8012 CF1 voltage / current GPIO_HLW_CF, // GPIO14 HLW8012 CF power @@ -619,10 +649,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_REL3, // GPIO04 Sonoff 4CH Red Led and Relay 3 (0 = Off, 1 = On) GPIO_REL2, // GPIO05 Sonoff 4CH Red Led and Relay 2 (0 = Off, 1 = On) - 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) GPIO_KEY2, // GPIO09 Button 2 GPIO_KEY3, // GPIO10 Button 3 - 0, // Flash connection + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay 1 (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) GPIO_KEY4, // GPIO14 Button 4 @@ -635,7 +667,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO02 Optional sensor GPIO_USER, // GPIO03 Serial TXD and Optional sensor 0, 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green/Blue Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -646,7 +683,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, GPIO_USER, // GPIO03 Serial TXD and Optional sensor 0, 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -657,9 +699,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, GPIO_USER, // GPIO03 Serial TXD and Optional sensor 0, 0, - 0, 0, 0, // Flash connection - 0, 0, - 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -669,7 +714,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, 0, GPIO_USER, // GPIO04 Optional sensor (PWM3 Green) GPIO_USER, // GPIO05 Optional sensor (PWM2 Red) - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_PWM1, // GPIO12 Cold light (PWM0 Cold) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) GPIO_PWM2, // GPIO14 Warm light (PWM1 Warm) @@ -679,7 +729,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "1 Channel", // 1 Channel Inching/Latching Relay using (PSA-B01 - ESP8266 and PSF-B01 - ESP8285) GPIO_KEY1, // GPIO00 Button 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -690,7 +745,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, GPIO_RXD, // GPIO03 Relay control 0, 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 0, GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -698,7 +758,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "Motor C/AC", // Motor Clockwise / Anti clockwise (PSA-B01 - ESP8266) GPIO_KEY1, // GPIO00 Button 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -710,7 +775,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor GPIO_USER, // GPIO05 Optional sensor - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL2, // GPIO12 Red Led and Relay 2 (0 = Off, 1 = On) GPIO_REL1, // GPIO13 Red Led and Relay 1 (0 = Off, 1 = On) GPIO_USER, // GPIO14 Optional sensor @@ -728,7 +798,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 UART0_RXD V3.1 Module Pin 3 GPIO_USER, // GPIO04 V3.1 Module Pin 10 - V5.0 Module Pin 2 GPIO_USER, // GPIO05 V3.1 Module Pin 9 - V5.0 Module Pin 1 - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Relay1 ( 1 = Off) GPIO_REL2, // GPIO13 Relay1 ( 1 = On) GPIO_USER, // GPIO14 V3.1 Module Pin 5 - V5.0 GPIO_REL3_INV Relay2 ( 1 = Off) @@ -742,7 +817,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, GPIO_LED1, // GPIO02 Green Led (1 = On, 0 = Off) 0, 0, 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_USER, // GPIO12 Optional sensor (pm data) GPIO_KEY1, // GPIO13 Button 0, @@ -756,10 +836,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor GPIO_USER, // GPIO04 D2 Wemos I2C SDA GPIO_USER, // GPIO05 D1 Wemos I2C SCL / Wemos Relay Shield (0 = Off, 1 = On) / Wemos WS2812B RGB led Shield - 0, 0, 0, // Flash connection - GPIO_USER, // Flash connection or GPIO09 on ESP8285 only! - GPIO_USER, // Flash connection or GPIO10 on ESP8285 only! - 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_USER, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + GPIO_USER, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_USER, // GPIO12 D6 GPIO_USER, // GPIO13 D7 GPIO_USER, // GPIO14 D5 @@ -774,7 +856,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor GPIO_USER, // GPIO05 Optional sensor - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_USER, // GPIO12 GPIO_USER, // GPIO13 BLUE LED GPIO_USER, // GPIO14 Optional sensor @@ -789,7 +876,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 RX and Optional sensor - Pin next to GND on the PCB GPIO_PWM5, // GPIO04 W2 - PWM5 GPIO_LED2_INV, // GPIO05 Red LED - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_PWM3, // GPIO12 Blue GPIO_PWM2, // GPIO13 Green GPIO_PWM4, // GPIO14 W1 - PWM4 @@ -802,16 +894,24 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO02 Optional sensor GPIO_RXD, // GPIO03 TXD to ATMEGA328P 0, 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 0, GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) 0, 0, 0, 0 }, { "Sonoff BN-SZ", // Sonoff BN-SZ01 Ceiling led (ESP8285) 0, 0, 0, 0, 0, 0, - 0, 0, 0, // Flash connection - 0, 0, - 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) GPIO_PWM1, // GPIO12 Light GPIO_LED1_INV, // GPIO13 Red Led (0 = On, 1 = Off) 0, 0, @@ -824,10 +924,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_REL3, // GPIO04 Sonoff 4CH Red Led and Relay 3 (0 = Off, 1 = On) GPIO_REL2, // GPIO05 Sonoff 4CH Red Led and Relay 2 (0 = Off, 1 = On) - 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) GPIO_KEY2, // GPIO09 Button 2 GPIO_KEY3, // GPIO10 Button 3 - 0, // Flash connection + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay 1 (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) GPIO_KEY4, // GPIO14 Button 4 @@ -835,12 +937,17 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0 }, { "Huafan SS", // Hua Fan Smart Socket (ESP8266) - like Sonoff Pow - GPIO_LED1_INV, // GPIO0 Blue Led (0 = On, 1 = Off) + GPIO_LED1_INV, // GPIO00 Blue Led (0 = On, 1 = Off) 0, 0, - GPIO_LED2_INV, // GPIO3 Red Led (0 = On, 1 = Off) - GPIO_KEY1, // GPIO4 Button - GPIO_REL1_INV, // GPIO5 Relay (0 = On, 1 = Off) - 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_LED2_INV, // GPIO03 Red Led (0 = On, 1 = Off) + GPIO_KEY1, // GPIO04 Button + GPIO_REL1_INV, // GPIO05 Relay (0 = On, 1 = Off) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_NRG_CF1, // GPIO12 HLW8012 CF1 voltage / current GPIO_NRG_SEL, // GPIO13 HLW8012 Sel output (1 = Voltage) GPIO_HLW_CF, // GPIO14 HLW8012 CF power @@ -853,9 +960,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_RXD, // GPIO03 RF bridge control GPIO_USER, // GPIO04 Optional sensor GPIO_USER, // GPIO05 Optional sensor - 0, 0, 0, // Flash connection - 0, 0, - 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) 0, GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -866,9 +976,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO02 Optional sensor SDA pad GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad 0, 0, - 0, 0, 0, // Flash connection - 0, 0, - 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) GPIO_DI, // GPIO12 my9231 DI 0, GPIO_DCKI, // GPIO14 my9231 DCKI @@ -880,9 +993,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO02 Optional sensor SDA pad GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad 0, 0, - 0, 0, 0, // Flash connection - 0, 0, - 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 0, GPIO_DI, // GPIO13 my9291 DI 0, @@ -895,9 +1011,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO02 Optional Sensor (J3 Pin 5) GPIO_USER, // GPIO03 Serial TXD and Optional sensor 0, 0, - 0, 0, 0, // Flash connection - 0, 0, - 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -909,10 +1028,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor 0, GPIO_REL2, // GPIO05 Blue Led and Relay 2 (0 = Off, 1 = On) - 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) GPIO_KEY2, // GPIO09 Button 2 - 0, - 0, // Flash connection + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -924,10 +1045,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_REL3, // GPIO04 Blue Led and Relay 3 (0 = Off, 1 = On) GPIO_REL2, // GPIO05 Blue Led and Relay 2 (0 = Off, 1 = On) - 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) GPIO_KEY2, // GPIO09 Button 2 GPIO_KEY3, // GPIO10 Button 3 - 0, // Flash connection + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -940,7 +1063,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_KEY1, // GPIO04 Button 1 GPIO_REL1, // GPIO05 Relay 1 (0 = Off, 1 = On) - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_USER, // GPIO12 Optional sensor GPIO_REL2, // GPIO13 Relay 2 (0 = Off, 1 = On) GPIO_USER, // GPIO14 Optional sensor @@ -956,7 +1084,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_KEY1, // GPIO04 D2 push button on ESP-12F board GPIO_USER, // GPIO05 D1 optional sensor - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_PWM2, // GPIO12 D6 RGB LED Green GPIO_PWM3, // GPIO13 D7 RGB LED Blue GPIO_USER, // GPIO14 D5 optional sensor @@ -973,7 +1106,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor - Module Pin 3 GPIO_REL1, // GPIO04 Red Led and Relay (0 = Off, 1 = On) - Module Pin 10 GPIO_KEY1, // GPIO05 Blue Led and OptoCoupler input - Module Pin 9 - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 0, 0, 0, 0, 0 }, { "MagicHome", // Magic Home (aka Flux-light) (ESP8266) and Arilux LC10 (ESP8285) @@ -984,7 +1122,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional) (Arilux LC10) GPIO_PWM2, // GPIO05 RGB LED Green - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_PWM3, // GPIO12 RGB LED Blue GPIO_USER, // GPIO13 RGBW LED White (optional - set to PWM4 for Cold White or Warm White as used on Arilux LC10) GPIO_PWM1, // GPIO14 RGB LED Red @@ -999,7 +1142,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 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 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 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 @@ -1013,7 +1161,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, 0, GPIO_HLW_CF, // GPIO04 HLW8012 CF power GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 voltage / current - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_NRG_SEL, // GPIO12 HLW8012 SEL (1 = Voltage) GPIO_LED1_INV, // GPIO13 Green Led GPIO_REL1, // GPIO14 Relay @@ -1028,7 +1181,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional) GPIO_PWM1, // GPIO05 RGB LED Red - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 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) @@ -1043,7 +1201,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_PWM2, // GPIO04 RGB LED Green GPIO_PWM1, // GPIO05 RGB LED Red - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_PWM5, // GPIO12 RGBCW LED Warm GPIO_PWM4, // GPIO13 RGBW LED Cold GPIO_PWM3, // GPIO14 RGB LED Blue @@ -1057,10 +1220,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor 0, GPIO_REL2, // GPIO05 Relay 2 (0 = Off, 1 = On) - 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) GPIO_USER, // GPIO09 Button 1 on header (0 = On, 1 = Off) GPIO_KEY1, // GPIO10 Button on casing - 0, // Flash connection + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Relay 1 (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -1073,7 +1238,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 W2 - PWM5 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_PWM2, // GPIO12 RGB LED Green GPIO_PWM3, // GPIO13 RGB LED Blue GPIO_PWM1, // GPIO14 RGB LED Red @@ -1086,7 +1256,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, // GPIO03 Serial TXD 0, 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -1099,7 +1274,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, GPIO_USER, // GPIO04 W2 - PWM5 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_PWM2, // GPIO12 RGB LED Green GPIO_PWM1, // GPIO13 RGB LED Red GPIO_PWM3, // GPIO14 RGB LED Blue @@ -1111,7 +1291,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, // GPIO03 Serial TXD 0, 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0, 0 @@ -1123,10 +1308,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 ESP_RXD Serial TXD and Optional sensor GPIO_REL3, // GPIO04 WIFI_O2 Relay 3 (0 = Off, 1 = On) controlling the fan GPIO_REL2, // GPIO05 WIFI_O1 Relay 2 (0 = Off, 1 = On) controlling the fan - 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) GPIO_KEY2, // GPIO09 WIFI_KEY1 Virtual button 2 as feedback from RC GPIO_KEY3, // GPIO10 WIFI_KEY2 Virtual button 3 as feedback from RC - 0, // Flash connection + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 WIFI_O0 Relay 1 (0 = Off, 1 = On) controlling the light GPIO_LED1_INV, // GPIO13 WIFI_CHK Blue Led on PCA (0 = On, 1 = Off) GPIO_KEY4, // GPIO14 WIFI_KEY3 Virtual button 4 as feedback from RC @@ -1144,37 +1331,57 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor 0, GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) GPIO_KEY1, // GPIO13 Button GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) 0, 0 }, - { "Shelly 1", // Shelly1 Open Source (ESP8266 - 2MB) - https://shelly.cloud/shelly1-open-source/ + { "Shelly 1", // Shelly1 Open Source (ESP8266 - 2MB) - https://shelly.cloud/shelly1-open-source/ 0, 0, 0, 0, - GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) - GPIO_SWT1_NP, // GPIO05 SW pin - 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) + GPIO_SWT1_NP, // GPIO05 SW pin + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 0, 0, 0, 0, 0, 0 }, - { "Shelly 2", // Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ + { "Shelly 2", // Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ 0, - GPIO_TXD, // GPIO01 MCP39F501 Serial input + GPIO_TXD, // GPIO01 MCP39F501 Serial input 0, - GPIO_RXD, // GPIO03 MCP39F501 Serial output - GPIO_REL1, // GPIO04 - GPIO_REL2, // GPIO05 - 0, 0, 0, 0, 0, 0, // Flash connection - GPIO_SWT1, // GPIO12 + GPIO_RXD, // GPIO03 MCP39F501 Serial output + GPIO_REL1, // GPIO04 + GPIO_REL2, // GPIO05 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_SWT1, // GPIO12 0, - GPIO_SWT2, // GPIO14 - 0, // GPIO15 MCP39F501 Reset + GPIO_SWT2, // GPIO14 + 0, // GPIO15 MCP39F501 Reset 0, 0 }, { "Xiaomi Philips", // Xiaomi Philips bulb (ESP8266) 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_PWM2, // GPIO12 cold/warm light 0, 0, GPIO_PWM1, // GPIO15 light intensity @@ -1185,7 +1392,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, 0, 0, GPIO_LED1_INV, // GPIO04 Red Led (0 = On, 1 = Off) 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_KEY1, // GPIO13 Button 0, 0, 0, 0 @@ -1198,7 +1410,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_KEY1, // GPIO04 Button 1 GPIO_REL2_INV, // GPIO05 Red Led 2 (0 = On, 1 = Off) - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL4_INV, // GPIO12 Blue Led 4 (0 = On, 1 = Off) GPIO_KEY4, // GPIO13 Button 4 GPIO_KEY3, // GPIO14 Button 3 @@ -1212,7 +1429,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD GPIO_LED1, // GPIO04 Blue LED GPIO_REL1, // GPIO05 (Relay OFF, but used as Relay Switch) - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_LED2, // GPIO12 (Relay ON, but set to LOW, so we can switch with GPIO05) GPIO_USER, // GPIO13 GPIO_KEY1, // GPIO14 Button @@ -1227,7 +1449,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED2_INV, // GPIO03 Serial RXD and Red Led (0 = On, 1 = Off) GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) @@ -1239,7 +1466,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY1, // GPIO03 Button GPIO_HLW_CF, // GPIO04 HLW8012 CF power GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 current / voltage - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage) GPIO_LED1_INV, // GPIO13 LED (0 = On, 1 = Off) GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On ) @@ -1253,7 +1485,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 MCU serial control GPIO_USER, GPIO_USER, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_USER, GPIO_USER, GPIO_USER, // GPIO14 Green Led @@ -1268,22 +1505,32 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY1, // GPIO03 Serial TXD and Button GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) GPIO_LED2_INV, // GPIO13 LED2 (red) inv GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) 0, 0, 0 }, - { "ARMTR Dimmer", // ARMTRONIX Dimmer, one or two channel (ESP8266 w/ separate MCU dimmer) - // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-two-triac-board/ - // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-esp8266-one-triac-board-alexaecho/ + { "ARMTR Dimmer", // ARMTRONIX Dimmer, one or two channel (ESP8266 w/ separate MCU dimmer) + // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-two-triac-board/ + // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-esp8266-one-triac-board-alexaecho/ GPIO_USER, - GPIO_TXD, // GPIO01 MCU serial control + GPIO_TXD, // GPIO01 MCU serial control GPIO_USER, - GPIO_RXD, // GPIO03 MCU serial control + GPIO_RXD, // GPIO03 MCU serial control GPIO_USER, GPIO_USER, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_USER, GPIO_USER, GPIO_USER, @@ -1296,7 +1543,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, 0, GPIO_HLW_CF, // GPIO04 HLW8012 CF power GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 current / voltage - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage) GPIO_LED2_INV, // GPIO13 Red Led (0 = On, 1 = Off) GPIO_LED1_INV, // GPIO14 Blue Led (0 = On, 1 = Off) @@ -1311,7 +1563,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_RXD, // GPIO03 MCU serial control GPIO_USER, GPIO_USER, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_USER, GPIO_LED1, // GPIO13 WiFi LED GPIO_USER, @@ -1328,7 +1585,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) GPIO_KEY1, // GPIO13 Button GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage @@ -1343,7 +1605,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY1, // GPIO03 Serial TXD + Button GPIO_REL2, // GPIO04 Relay 2 GPIO_REL1, // GPIO05 Relay 1 - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL3, // GPIO12 Relay 3 GPIO_REL4, // GPIO13 Relay 4 GPIO_USER, // GPIO14 @@ -1364,7 +1631,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 IR receiver (optional) GPIO_PWM2, // GPIO05 RGB LED Green - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 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 @@ -1380,7 +1652,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 Serial TXD and Optional sensor0 GPIO_ARIRFRCV, // GPIO04 RF receiver input GPIO_PWM2, // GPIO05 RGB LED Green - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_PWM3, // GPIO12 RGB LED Blue GPIO_PWM4, // GPIO13 RGBW LED White GPIO_PWM1, // GPIO14 RGB LED Red @@ -1393,7 +1670,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY2, // GPIO03 Serial TXD and Optional sensor GPIO_REL2, // GPIO04 Relay 2 GPIO_KEY3, // GPIO05 Input 2 - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_KEY1, // GPIO12 Key input GPIO_REL1, // GPIO13 Relay 1 0, @@ -1405,7 +1687,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, 0, 0, GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_KEY1, // GPIO12 Button 0, 0, GPIO_LED1, // GPIO15 Led (1 = On, 0 = Off) @@ -1416,7 +1703,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, 0, 0, GPIO_LED1_INV, // GPIO04 Blue Led (0 = On, 1 = Off) 0, // GPIO05 IR or RF receiver (optional) - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Relay and Red Led (0 = Off, 1 = On) GPIO_KEY1, // GPIO13 Button 0, 0, 0, 0 @@ -1429,7 +1721,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 GPIO_LED1_INV, // GPIO04 Blue LED GPIO_REL1, // GPIO05 Red LED and relay - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) 0, GPIO_KEY1, // GPIO13 Button (normally GPIO00) GPIO_USER, // GPIO14 @@ -1442,7 +1739,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, GPIO_USER, // GPIO04 IR receiver (optional) GPIO_PWM2, // GPIO05 RGB LED Green - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_PWM1, // GPIO12 RGB LED Red GPIO_PWM3, // GPIO13 RGB LED Blue 0, @@ -1457,7 +1759,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 (D8) Serial TXD GPIO_USER, // GPIO04 (D4) 4 x WS2812 Leds, (DOUT) Extents WS2812 string GPIO_USER, // GPIO05 (D5) Blue Led - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_USER, // GPIO12 (D12) GPIO_USER, // GPIO13 (D13) GPIO_USER, // GPIO14 (D14) @@ -1469,7 +1776,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "Delock 11826", // Delock 11826 (ESP8285) = Sonoff Basic GPIO_KEY1, // GPIO00 Button 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, // Flash connection + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) 0, 0, 0, 0 diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 490491e1c..8bb04be1a 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040102 +#define VERSION 0x06040103 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index 77b23eb5d..77e2223c0 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -504,7 +504,29 @@ String ModuleName() void ModuleGpios(myio *gp) { - memcpy_P(gp, &kModules[Settings.module].gp, 18); + uint8_t *dest = (uint8_t *)gp; + memset(dest, GPIO_NONE, sizeof(myio)); + + uint8_t src[sizeof(mycfgio)]; + memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio)); + // 11 85 00 85 85 00 00 00 15 38 85 00 00 81 + +// AddLogSerial(LOG_LEVEL_DEBUG, (uint8_t *)&src, sizeof(mycfgio)); + + for (uint8_t i = 0; i < sizeof(mycfgio); i++) { + if (i < 6) { + dest[i] = src[i]; // GPIO00 - GPIO05 + } + else if (i < 8) { + dest[i +3] = src[i]; // GPIO09 - GPIO10 + } + else { + dest[i +4] = src[i]; // GPIO12 - GPIO16 and ADC0 + } + } + // 11 85 00 85 85 00 00 00 00 00 00 00 15 38 85 00 00 81 + +// AddLogSerial(LOG_LEVEL_DEBUG, (uint8_t *)gp, sizeof(myio)); } void SetGlobalValues(float temperature, float humidity) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 16201c2a1..a62e8ea47 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -826,7 +826,7 @@ void HandleModuleConfiguration(void) page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE)); page += FPSTR(HTTP_SCRIPT_MODULE1); page.replace(F("}4"), String(Settings.module)); - for (byte i = 0; i < MAX_GPIO_PIN; i++) { + for (byte i = 0; i < sizeof(cmodule); i++) { if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,%d);"), my_module.io[i], i); // g0 - g16 page += mqtt_data; @@ -838,7 +838,7 @@ void HandleModuleConfiguration(void) page += FPSTR(HTTP_FORM_MODULE); page.replace(F("{mt"), AnyModuleName(MODULE)); page += F("
          %s " D_GPIO "%d %s
          "); - for (byte i = 0; i < MAX_GPIO_PIN; i++) { + for (byte i = 0; i < sizeof(cmodule); i++) { if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), @@ -864,7 +864,7 @@ void ModuleSaveSettings(void) myio cmodule; ModuleGpios(&cmodule); String gpios = ""; - for (byte i = 0; i < MAX_GPIO_PIN; i++) { + for (byte i = 0; i < sizeof(cmodule); i++) { if (Settings.last_module != new_module) { Settings.my_gp.io[i] = 0; } else { diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index eb564a8e8..d0ab215a5 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -248,7 +248,7 @@ void TuyaPacketProcess(void) uint8_t key1_gpio = tuya_buffer[7]; boolean key1_set = false; boolean led1_set = false; - for (byte i = 0; i < MAX_GPIO_PIN; i++) { + for (byte i = 0; i < sizeof(Settings.my_gp); i++) { if (Settings.my_gp.io[i] == GPIO_LED1) led1_set = true; else if (Settings.my_gp.io[i] == GPIO_KEY1) key1_set = true; } From aa4c58a26661c102da54596d6f7e2cba0104999e Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Sat, 29 Dec 2018 22:45:32 -0300 Subject: [PATCH 0772/2222] Fix Typo in Spanish Translation --- sonoff/language/es-AR.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 435f230ad..fc50b9d6f 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -462,7 +462,7 @@ #define D_HX_CAL_REFERENCE "Poner Peso de Referencia" #define D_HX_CAL_DONE "Calibrado" #define D_HX_CAL_FAIL "Falló Calibración" -#define D_RESET_HX711 "Restableces Escala" +#define D_RESET_HX711 "Restablecer Escala" #define D_CONFIGURE_HX711 "Configurar Escala" #define D_HX711_PARAMETERS "Parámetros de Escala" #define D_ITEM_WEIGHT "Peso" From 5737665a2f3445deccd611567e424f3243929dd7 Mon Sep 17 00:00:00 2001 From: Markus Past Date: Sun, 30 Dec 2018 11:45:21 +0100 Subject: [PATCH 0773/2222] MAX31855 driver for Sonoff-Tasmota - Initial commit --- sonoff/i18n.h | 2 + sonoff/language/en-GB.h | 3 + sonoff/my_user_config.h | 3 + sonoff/sonoff_template.h | 11 ++- sonoff/xsns_39_max31855.ino | 163 ++++++++++++++++++++++++++++++++++++ 5 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 sonoff/xsns_39_max31855.ino diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 2347cba22..a4de6d1bd 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -106,8 +106,10 @@ #define D_JSON_PRESSURE "Pressure" #define D_JSON_PRESSUREATSEALEVEL "SeaPressure" #define D_JSON_PRESSURE_UNIT "PressureUnit" +#define D_JSON_PROBETEMPERATURE "ProbeTemperature" #define D_JSON_PROGRAMFLASHSIZE "ProgramFlashSize" #define D_JSON_PROGRAMSIZE "ProgramSize" +#define D_JSON_REFERENCETEMPERATURE "ReferenceTemperature" #define D_JSON_RESET "Reset" #define D_JSON_RESTARTING "Restarting" #define D_JSON_RESTARTREASON "RestartReason" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 2ea9c249a..20b4f8ddb 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 8684ac7a0..69f21dec7 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -285,6 +285,9 @@ // #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors // #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistors for single DS18B20 +// -- SPI sensors ---------------------------------- +#define USE_MAX31855 // Enable MAX31855 K-Type thermocouple sensor + // -- I2C sensors --------------------------------- #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 48af9cf4b..d8a9296e7 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -143,6 +143,9 @@ enum UserSelectablePins { GPIO_RF_SENSOR, // Rf receiver with sensor decoding GPIO_AZ_TXD, // AZ-Instrument 7798 Serial interface GPIO_AZ_RXD, // AZ-Instrument 7798 Serial interface + GPIO_MAX31855CS, // MAX31855 Serial interface + GPIO_MAX31855CLK, // MAX31855 Serial interface + GPIO_MAX31855DO, // MAX31855 Serial interface GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -204,7 +207,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET "|" D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC "|" D_SENSOR_RF_SENSOR "|" - D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX; + D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX "|" + D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO; /********************************************************************************************/ @@ -461,6 +465,11 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_AZ_TXD, // AZ-Instrument 7798 CO2 datalogger Serial interface GPIO_AZ_RXD // AZ-Instrument 7798 CO2 datalogger Serial interface #endif +#ifdef USE_MAX31855 + GPIO_MAX31855CS, // MAX31855 Serial interface + GPIO_MAX31855CLK, // MAX31855 Serial interface + GPIO_MAX31855DO, // MAX31855 Serial interface +#endif }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { diff --git a/sonoff/xsns_39_max31855.ino b/sonoff/xsns_39_max31855.ino new file mode 100644 index 000000000..2668f914c --- /dev/null +++ b/sonoff/xsns_39_max31855.ino @@ -0,0 +1,163 @@ +/* + xsns_39_max31855.ino - MAX31855 thermocouple sensor support for Sonoff-Tasmota + + Copyright (C) 2018 Markus Past + + 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 . +*/ + +//#define USE_MAX31855 + +#ifdef USE_MAX31855 + +#define XSNS_39 39 + +bool initialized = false; + +struct MAX31855_ResultStruct{ + uint8_t ErrorCode; + float ProbeTemperature; + float ReferenceTemperature; +} MAX31855_Result; + +void MAX31855_Init(void){ + if(initialized) + return; + + pinMode(pin[GPIO_MAX31855CS], OUTPUT); + pinMode(pin[GPIO_MAX31855CLK], OUTPUT); + pinMode(pin[GPIO_MAX31855DO], INPUT); + digitalWrite(pin[GPIO_MAX31855CS], HIGH); + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + + initialized = true; +} + +void MAX31855_GetResult(void){ + int32_t RawData = MAX31855_ShiftIn(32); + uint8_t probeerror = RawData & 0x7; + + MAX31855_Result.ErrorCode = probeerror; + MAX31855_Result.ReferenceTemperature = MAX31855_GetReferenceTemperature(RawData); + if(probeerror) + MAX31855_Result.ProbeTemperature = NAN; + else + MAX31855_Result.ProbeTemperature = MAX31855_GetProbeTemperature(RawData); +} + +float MAX31855_GetProbeTemperature(int32_t RawData){ + if(RawData & 0x80000000) + RawData = (RawData >> 18) | 0xFFFFC000; + else + RawData >>= 18; + + float result = (RawData * 0.25); + + return (Settings.flag.temperature_conversion) ? ConvertTemp(result) : result; +} + +float MAX31855_GetReferenceTemperature(int32_t RawData){ + if(RawData & 0x8000) + RawData = (RawData >> 4) | 0xFFFFF000; + else + RawData = (RawData >> 4) & 0x00000FFF; + + float result = (RawData * 0.0625); + + return (Settings.flag.temperature_conversion) ? ConvertTemp(result) : result; +} + +int32_t MAX31855_ShiftIn(uint8_t Length){ + int32_t dataIn = 0; + + digitalWrite(pin[GPIO_MAX31855CS], LOW); + delayMicroseconds(1); + + for(uint8_t i = 0; i < Length; i++) + { + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + delayMicroseconds(1); + dataIn <<= 1; + if(digitalRead(pin[GPIO_MAX31855DO])) + dataIn |= 1; + digitalWrite(pin[GPIO_MAX31855CLK], HIGH); + delayMicroseconds(1); + } + + digitalWrite(pin[GPIO_MAX31855CS], HIGH); + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + return dataIn; +} + +void MAX31855_Show(bool Json){ + char probetemp[33]; + char referencetemp[33]; + dtostrfd(MAX31855_Result.ProbeTemperature, Settings.flag2.temperature_resolution, probetemp); + dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); + + if(Json){ + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ + mqtt_data, "MAX31855", probetemp, referencetemp, MAX31855_Result.ErrorCode); + } else { +#ifdef USE_WEBSERVER + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "MAX31855", probetemp, TempUnit()); +#endif // USE_WEBSERVER + } +} + + +// void MAX31855_ShowDebug(void){ +// char probetemp[33]; +// char referencetemp[33]; +// dtostrfd(MAX31855_Result.ProbeTemperature, Settings.flag2.temperature_resolution, probetemp); +// dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); + +// snprintf_P(mqtt_data, sizeof(mqtt_data), "%s %d %s %d %s %d %s %d %s %d %s %s %s %s %s %d", \ +// "CS:", pin[GPIO_MAX31855CS], "CLK:", pin[GPIO_MAX31855CLK], "DO:", pin[GPIO_MAX31855DO], \ +// "DO-State:", digitalRead(pin[GPIO_MAX31855DO]), \ +// "RAW-Data:", MAX31855_ShiftIn(32), \ +// "Probe-Temp:", probetemp, "Internal-Temp:", referencetemp, "Error:", MAX31855_Result.ErrorCode); +// } + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +boolean Xsns39(byte function) +{ + boolean result = false; + if((pin[GPIO_MAX31855CS] < 99) && (pin[GPIO_MAX31855CLK] < 99) && (pin[GPIO_MAX31855DO] < 99)){ + + switch (function) { + case FUNC_INIT: + MAX31855_Init(); + break; + case FUNC_EVERY_SECOND: + MAX31855_GetResult(); + break; + case FUNC_JSON_APPEND: + //MAX31855_ShowDebug(); + MAX31855_Show(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_APPEND: + MAX31855_Show(false); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_MAX31855 \ No newline at end of file From 8b84ec35f77b898ee8202795cc3c4f0a8fbad1a9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Dec 2018 12:30:01 +0100 Subject: [PATCH 0774/2222] Fix MGC3130/AZ7798 compile error --- sonoff/sonoff_template.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index bc14adb9a..7c590085e 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -456,15 +456,15 @@ const uint8_t kGpioNiceList[] PROGMEM = { #endif #ifdef USE_TUYA_DIMMER GPIO_TUYA_TX, // Tuya Serial interface - GPIO_TUYA_RX, // Tuya Serial interface + GPIO_TUYA_RX, // Tuya Serial interface #endif #ifdef USE_MGC3130 GPIO_MGC3130_XFER, - GPIO_MGC3130_RESET + GPIO_MGC3130_RESET, #endif #ifdef USE_AZ7798 GPIO_AZ_TXD, // AZ-Instrument 7798 CO2 datalogger Serial interface - GPIO_AZ_RXD // AZ-Instrument 7798 CO2 datalogger Serial interface + GPIO_AZ_RXD, // AZ-Instrument 7798 CO2 datalogger Serial interface #endif }; From 1e125fc4c6160785a93b7dd821f8b640d7a9884a Mon Sep 17 00:00:00 2001 From: Markus Past Date: Sun, 30 Dec 2018 12:47:59 +0100 Subject: [PATCH 0775/2222] added some comments --- sonoff/xsns_39_max31855.ino | 83 +++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/sonoff/xsns_39_max31855.ino b/sonoff/xsns_39_max31855.ino index 2668f914c..02288ca4b 100644 --- a/sonoff/xsns_39_max31855.ino +++ b/sonoff/xsns_39_max31855.ino @@ -17,8 +17,6 @@ along with this program. If not, see . */ -//#define USE_MAX31855 - #ifdef USE_MAX31855 #define XSNS_39 39 @@ -26,76 +24,96 @@ bool initialized = false; struct MAX31855_ResultStruct{ - uint8_t ErrorCode; - float ProbeTemperature; - float ReferenceTemperature; + uint8_t ErrorCode; // Error Codes: 0 = No Error / 1 = TC open circuit / 2 = TC short to GND / 4 = TC short to VCC + float ProbeTemperature; // Measured temperature of the 'hot' TC junction (probe temp) + float ReferenceTemperature; // Measured temperature of the 'cold' TC junction (reference temp) } MAX31855_Result; void MAX31855_Init(void){ if(initialized) return; + // Set GPIO modes for SW-SPI pinMode(pin[GPIO_MAX31855CS], OUTPUT); pinMode(pin[GPIO_MAX31855CLK], OUTPUT); pinMode(pin[GPIO_MAX31855DO], INPUT); + + // Chip not selected / Clock low digitalWrite(pin[GPIO_MAX31855CS], HIGH); digitalWrite(pin[GPIO_MAX31855CLK], LOW); initialized = true; } +/* +* MAX31855_GetResult(void) +* Acquires the raw data via SPI, checks for MAX31855 errors and fills result structure +*/ void MAX31855_GetResult(void){ int32_t RawData = MAX31855_ShiftIn(32); uint8_t probeerror = RawData & 0x7; MAX31855_Result.ErrorCode = probeerror; MAX31855_Result.ReferenceTemperature = MAX31855_GetReferenceTemperature(RawData); - if(probeerror) - MAX31855_Result.ProbeTemperature = NAN; + if(probeerror) + MAX31855_Result.ProbeTemperature = NAN; // Return NaN if MAX31855 reports an error else MAX31855_Result.ProbeTemperature = MAX31855_GetProbeTemperature(RawData); } + +/* +* MAX31855_GetProbeTemperature(int32_t RawData) +* Decodes and returns the temperature of TCs 'hot' junction from RawData +*/ float MAX31855_GetProbeTemperature(int32_t RawData){ if(RawData & 0x80000000) - RawData = (RawData >> 18) | 0xFFFFC000; + RawData = (RawData >> 18) | 0xFFFFC000; // Negative value - Drop lower 18 bits and extend to negative number else - RawData >>= 18; + RawData >>= 18; // Positiv value - Drop lower 18 bits - float result = (RawData * 0.25); + float result = (RawData * 0.25); // MAX31855 LSB resolution is 0.25°C for probe temperature - return (Settings.flag.temperature_conversion) ? ConvertTemp(result) : result; + return (Settings.flag.temperature_conversion) ? ConvertTemp(result) : result; // Check if we have to convert to Fahrenheit } +/* +* MAX31855_GetReferenceTemperature(int32_t RawData) +* Decodes and returns the temperature of TCs 'cold' junction from RawData +*/ float MAX31855_GetReferenceTemperature(int32_t RawData){ if(RawData & 0x8000) - RawData = (RawData >> 4) | 0xFFFFF000; + RawData = (RawData >> 4) | 0xFFFFF000; // Negative value - Drop lower 4 bits and extend to negative number else - RawData = (RawData >> 4) & 0x00000FFF; + RawData = (RawData >> 4) & 0x00000FFF; // Positiv value - Drop lower 4 bits and mask out remaining bits (probe temp, error bit, etc.) - float result = (RawData * 0.0625); + float result = (RawData * 0.0625); // MAX31855 LSB resolution is 0.0625°C for reference temperature - return (Settings.flag.temperature_conversion) ? ConvertTemp(result) : result; + return (Settings.flag.temperature_conversion) ? ConvertTemp(result) : result; // Check if we have to convert to Fahrenheit } +/* +* MAX31855_ShiftIn(uint8_t Length) +* Communicates with MAX31855 via SW-SPI and returns the raw data read from the chip +*/ int32_t MAX31855_ShiftIn(uint8_t Length){ int32_t dataIn = 0; - digitalWrite(pin[GPIO_MAX31855CS], LOW); - delayMicroseconds(1); + digitalWrite(pin[GPIO_MAX31855CS], LOW); // CS = LOW -> Start SPI communication + delayMicroseconds(1); // CS fall to output enable = max. 100ns for(uint8_t i = 0; i < Length; i++) { digitalWrite(pin[GPIO_MAX31855CLK], LOW); - delayMicroseconds(1); + delayMicroseconds(1); // CLK pulse width low = min. 100ns / CLK fall to output valid = max. 40ns dataIn <<= 1; if(digitalRead(pin[GPIO_MAX31855DO])) dataIn |= 1; digitalWrite(pin[GPIO_MAX31855CLK], HIGH); - delayMicroseconds(1); + delayMicroseconds(1); // CLK pulse width high = min. 100ns } - digitalWrite(pin[GPIO_MAX31855CS], HIGH); + digitalWrite(pin[GPIO_MAX31855CS], HIGH); // CS = HIGH -> End SPI communication digitalWrite(pin[GPIO_MAX31855CLK], LOW); return dataIn; } @@ -109,6 +127,16 @@ void MAX31855_Show(bool Json){ if(Json){ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ mqtt_data, "MAX31855", probetemp, referencetemp, MAX31855_Result.ErrorCode); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, probetemp); + } +#endif // USE_DOMOTICZ +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, MAX31855_Result.ProbeTemperature); + } +#endif // USE_KNX } else { #ifdef USE_WEBSERVER snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "MAX31855", probetemp, TempUnit()); @@ -116,20 +144,6 @@ void MAX31855_Show(bool Json){ } } - -// void MAX31855_ShowDebug(void){ -// char probetemp[33]; -// char referencetemp[33]; -// dtostrfd(MAX31855_Result.ProbeTemperature, Settings.flag2.temperature_resolution, probetemp); -// dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); - -// snprintf_P(mqtt_data, sizeof(mqtt_data), "%s %d %s %d %s %d %s %d %s %d %s %s %s %s %s %d", \ -// "CS:", pin[GPIO_MAX31855CS], "CLK:", pin[GPIO_MAX31855CLK], "DO:", pin[GPIO_MAX31855DO], \ -// "DO-State:", digitalRead(pin[GPIO_MAX31855DO]), \ -// "RAW-Data:", MAX31855_ShiftIn(32), \ -// "Probe-Temp:", probetemp, "Internal-Temp:", referencetemp, "Error:", MAX31855_Result.ErrorCode); -// } - /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -147,7 +161,6 @@ boolean Xsns39(byte function) MAX31855_GetResult(); break; case FUNC_JSON_APPEND: - //MAX31855_ShowDebug(); MAX31855_Show(true); break; #ifdef USE_WEBSERVER From 9d62f3cb49429c4de8cd8d3080625d981ae438d7 Mon Sep 17 00:00:00 2001 From: Markus Past Date: Sun, 30 Dec 2018 13:34:20 +0100 Subject: [PATCH 0776/2222] added missing languages --- sonoff/language/bg-BG.h | 3 +++ sonoff/language/cs-CZ.h | 3 +++ sonoff/language/de-DE.h | 3 +++ sonoff/language/el-GR.h | 3 +++ sonoff/language/es-AR.h | 3 +++ sonoff/language/fr-FR.h | 3 +++ sonoff/language/he-HE.h | 3 +++ sonoff/language/hu-HU.h | 3 +++ sonoff/language/it-IT.h | 3 +++ sonoff/language/nl-NL.h | 3 +++ sonoff/language/pl-PL.h | 3 +++ sonoff/language/pt-BR.h | 3 +++ sonoff/language/pt-PT.h | 3 +++ sonoff/language/ru-RU.h | 3 +++ sonoff/language/sk-SK.h | 3 +++ sonoff/language/sv-SE.h | 3 +++ sonoff/language/tr-TR.h | 3 +++ sonoff/language/uk-UK.h | 3 +++ sonoff/language/zh-CN.h | 3 +++ sonoff/language/zh-TW.h | 3 +++ 20 files changed, 60 insertions(+) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 222c62b58..cf899685f 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF датчик" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 45f55af6a..21366053b 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 23d8de9ed..80ea03d1e 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index a8b48ed35..b36efe3b4 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index fc50b9d6f..dbf69404f 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 0638b408a..1a3cfae5f 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index cd1b0e92e..cbfacad14 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 244d55776..ea2f65ea0 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index a6d0d693c..b497ef04b 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index b3bf10989..df9d4dcb1 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index d80826751..7a42aff61 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 7add978f0..c62816af8 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 9869762b8..5e2b13255 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index d0a3f6933..ef8aaccef 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index f46372426..16da51d32 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Senzor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index f36162a4b..7f1b4ba5a 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 06d82b9cb..4ff68c52f 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 509c90753..5043c857c 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 05bedca81..858d45186 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 2780181aa..b1a46d3a4 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -540,6 +540,9 @@ #define D_SENSOR_RF_SENSOR "RF Sensor" #define D_SENSOR_AZ_RX "AZ Rx" #define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MAX31855 CS" +#define D_SENSOR_MAX31855_CLK "MAX31855 CLK" +#define D_SENSOR_MAX31855_DO "MAX31855 DO" // Units #define D_UNIT_AMPERE "安" From e5c38da52ce0d0133d0f4dbed8fa71bfb45c4515 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Dec 2018 14:04:32 +0100 Subject: [PATCH 0777/2222] Add debugging options to Switch Add more debugging options to Switch using SwitchDebounce --- sonoff/support_switch.ino | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino index 7e53cffb1..57794db1a 100644 --- a/sonoff/support_switch.ino +++ b/sonoff/support_switch.ino @@ -25,7 +25,7 @@ * Inspired by (https://github.com/OLIMEX/olimex-iot-firmware-esp8266/blob/master/olimex/user/user_switch2.c) \*********************************************************************************************/ -#define SWITCH_STATE_FILTER 5 +#define SWITCH_PROBE_INTERVAL 10 // Time in milliseconds between switch input probe #include @@ -33,7 +33,7 @@ Ticker TickerSwitch; unsigned long switch_debounce = 0; // Switch debounce timer uint16_t switch_no_pullup = 0; // Switch pull-up bitmask flags -uint8_t switch_state_buf[MAX_SWITCHES] = { SWITCH_STATE_FILTER / 2 }; +uint8_t switch_state_buf[MAX_SWITCHES] = { 0 }; uint8_t lastwallswitch[MAX_SWITCHES]; // Last wall switch states uint8_t holdwallswitch[MAX_SWITCHES] = { 0 }; // Timer for wallswitch push button hold uint8_t switch_virtual[MAX_SWITCHES]; // Virtual switch states @@ -65,29 +65,47 @@ uint8_t SwitchGetVirtual(uint8_t index) void SwitchProbe(void) { + uint8_t state_filter = Settings.switch_debounce / SWITCH_PROBE_INTERVAL; // 5, 10, 15 + uint8_t force_high = (Settings.switch_debounce % 50) &1; // 51, 101, 151 etc + uint8_t force_low = (Settings.switch_debounce % 50) &2; // 52, 102, 152 etc + for (byte i = 0; i < MAX_SWITCHES; i++) { if (pin[GPIO_SWT1 +i] < 99) { if (!((uptime < 4) && (0 == pin[GPIO_SWT1 +i]))) { // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit // Olimex user_switch2.c code to fix 50Hz induced pulses if (1 == digitalRead(pin[GPIO_SWT1 +i])) { - if (switch_state_buf[i] < SWITCH_STATE_FILTER) { + + if (force_high) { // Enabled with SwitchDebounce x1 + if (1 == switch_virtual[i]) { + switch_state_buf[i] = state_filter; // With noisy input keep current state 1 unless constant 0 + } + } + + if (switch_state_buf[i] < state_filter) { switch_state_buf[i]++; - if (SWITCH_STATE_FILTER == switch_state_buf[i]) { + if (state_filter == switch_state_buf[i]) { switch_virtual[i] = 1; } } } else { + + if (force_low) { // Enabled with SwitchDebounce x2 + if (0 == switch_virtual[i]) { + switch_state_buf[i] = 0; // With noisy input keep current state 0 unless constant 1 + } + } + if (switch_state_buf[i] > 0) { switch_state_buf[i]--; if (0 == switch_state_buf[i]) { - switch_virtual[i] = 0; + switch_virtual[i] = 0; } } } } } } - TickerSwitch.attach_ms(10, SwitchProbe); // Re-arm as core 2.3.0 does only support ONCE mode + TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); // Re-arm as core 2.3.0 does only support ONCE mode } void SwitchInit(void) @@ -102,7 +120,7 @@ void SwitchInit(void) } switch_virtual[i] = lastwallswitch[i]; } - if (switches_found) { TickerSwitch.attach_ms(10, SwitchProbe); } + if (switches_found) { TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); } } /*********************************************************************************************\ From fb4fe0fd55487400c7e3bb6160e475276fb871e0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Dec 2018 14:28:16 +0100 Subject: [PATCH 0778/2222] Fix DS3231 driver Fix DS3231 driver breaking function chain (#4759) --- sonoff/xsns_33_ds3231.ino | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/sonoff/xsns_33_ds3231.ino b/sonoff/xsns_33_ds3231.ino index 48cb12553..d98f7163b 100644 --- a/sonoff/xsns_33_ds3231.ino +++ b/sonoff/xsns_33_ds3231.ino @@ -62,27 +62,23 @@ #define HR1224 6 //Hours register 12 or 24 hour mode (24 hour mode==0) #define CENTURY 7 //Century bit in Month register #define DYDT 6 //Day/Date flag bit in alarm Day/Date registers -boolean ds3231ReadStatus = false , ds3231WriteStatus = false; //flag, we want to wriet/write to DS3231 onlu once -boolean DS3231chipDetected; - +boolean ds3231ReadStatus = false; +boolean ds3231WriteStatus = false; //flag, we want to wriet/write to DS3231 onlu once +boolean DS3231chipDetected = false; /*----------------------------------------------------------------------* Detect the DS3231 Chip ----------------------------------------------------------------------*/ -boolean DS3231Detect(void) +void DS3231Detect(void) { - if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) - { + DS3231chipDetected = false; + if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) { snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "DS3231", USE_RTC_ADDR); - AddLog(LOG_LEVEL_INFO); - return true; - } - else - { + DS3231chipDetected = true; + } else { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s *NOT* " D_FOUND_AT " 0x%x"), "DS3231", USE_RTC_ADDR); - AddLog(LOG_LEVEL_INFO); - return false; } + AddLog(LOG_LEVEL_INFO); } /*----------------------------------------------------------------------* @@ -143,10 +139,8 @@ boolean Xsns33(byte function) if (i2c_flg) { switch (function) { case FUNC_INIT: - DS3231chipDetected = DS3231Detect(); - result = DS3231chipDetected; + DS3231Detect(); break; - case FUNC_EVERY_SECOND: TIME_T tmpTime; if (!ds3231ReadStatus && DS3231chipDetected && utc_time < 1451602800 ) { // We still did not sync with NTP (time not valid) , so, read time from DS3231 @@ -169,7 +163,6 @@ boolean Xsns33(byte function) } else { rules_flag.time_set = 1; } - result = true; } else if (!ds3231WriteStatus && DS3231chipDetected && utc_time > 1451602800 && abs(utc_time - ReadFromDS3231()) > 60) {//if time is valid and is drift from RTC in more that 60 second snprintf_P(log_data, sizeof(log_data), PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), @@ -178,9 +171,6 @@ boolean Xsns33(byte function) SetDS3231Time (utc_time); //update the DS3231 time ds3231WriteStatus = true; } - else { - result = false; - } break; } } From 8fe61f6a11e789a590e0d8c8ae4a9044d22ccdf7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Dec 2018 14:40:06 +0100 Subject: [PATCH 0779/2222] Disable unused feature --- sonoff/xsns_interface.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index d39995be9..aab61fac7 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -311,7 +311,8 @@ boolean XsnsCall(byte Function) } #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND - if (result) break; +// if (result) break; // This feature is currently not used + #ifdef USE_DEBUG_DRIVER } #endif From 0a22261e36e12e70c0c1ef87e3230c2fd2daf865 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Dec 2018 14:47:17 +0100 Subject: [PATCH 0780/2222] Revert "Disable unused feature" This reverts commit 8fe61f6a11e789a590e0d8c8ae4a9044d22ccdf7. --- sonoff/xsns_interface.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index aab61fac7..d39995be9 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -311,8 +311,7 @@ boolean XsnsCall(byte Function) } #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND -// if (result) break; // This feature is currently not used - + if (result) break; #ifdef USE_DEBUG_DRIVER } #endif From 850d240d2e2889b1f1b5f4e98512405c61c19eea Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Dec 2018 14:56:50 +0100 Subject: [PATCH 0781/2222] Add test for result usage --- sonoff/xsns_interface.ino | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index d39995be9..1c02787db 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -311,7 +311,9 @@ boolean XsnsCall(byte Function) } #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND - if (result) break; + if (result && (FUNC_COMMAND == Function)) { + break; + } #ifdef USE_DEBUG_DRIVER } #endif From c67922241c0202e104c04146b9db25c8d05346f1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Dec 2018 15:32:53 +0100 Subject: [PATCH 0782/2222] Add tests for result --- sonoff/xdrv_interface.ino | 13 ++++++++++++- sonoff/xdsp_interface.ino | 9 ++++++++- sonoff/xnrg_interface.ino | 11 ++++++++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 0ec3696d9..1500f184b 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -240,7 +240,18 @@ boolean XdrvCall(byte Function) for (byte x = 0; x < xdrv_present; x++) { // WifiAddDelayWhenDisconnected(); result = xdrv_func_ptr[x](Function); - if (result) break; + + if (result && ((FUNC_COMMAND == Function) || + (FUNC_MQTT_DATA == Function) || + (FUNC_RULES_PROCESS == Function) || + (FUNC_BUTTON_PRESSED == Function) || + (FUNC_SERIAL == Function) || + (FUNC_MODULE_INIT == Function) || + (FUNC_SET_CHANNELS == Function) || + (FUNC_SET_DEVICE_POWER == Function) + )) { + break; + } } return result; diff --git a/sonoff/xdsp_interface.ino b/sonoff/xdsp_interface.ino index e2847d85e..01e4424dd 100644 --- a/sonoff/xdsp_interface.ino +++ b/sonoff/xdsp_interface.ino @@ -17,6 +17,8 @@ along with this program. If not, see . */ +#ifdef USE_DISPLAY + #ifdef XFUNC_PTR_IN_ROM boolean (* const xdsp_func_ptr[])(byte) PROGMEM = { // Display Function Pointers #else @@ -123,8 +125,13 @@ boolean XdspCall(byte Function) for (byte x = 0; x < xdsp_present; x++) { result = xdsp_func_ptr[x](Function); - if (result) break; + + if (result && (FUNC_DISPLAY_MODEL == Function)) { + break; + } } return result; } + +#endif // USE_DISPLAY diff --git a/sonoff/xnrg_interface.ino b/sonoff/xnrg_interface.ino index cea14e47c..32af6451c 100644 --- a/sonoff/xnrg_interface.ino +++ b/sonoff/xnrg_interface.ino @@ -17,6 +17,8 @@ along with this program. If not, see . */ +#ifdef USE_ENERGY_SENSOR + #ifdef XFUNC_PTR_IN_ROM int (* const xnrg_func_ptr[])(byte) PROGMEM = { // Energy driver Function Pointers #else @@ -96,7 +98,14 @@ int XnrgCall(byte Function) for (byte x = 0; x < xnrg_present; x++) { result = xnrg_func_ptr[x](Function); - if (result) break; + + if (result && ((FUNC_SERIAL == Function) || + (FUNC_COMMAND == Function) + )) { + break; + } } return result; } + +#endif // USE_ENERGY_SENSOR From f12261e4fa053fa0a4112a8af7d0adfc0f0a79ec Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 1 Jan 2019 13:45:44 +0100 Subject: [PATCH 0783/2222] Add support for MAX31855 Add support for MAX31855 K-Type thermocouple sensor using softSPI (#4764) --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 5 ++--- sonoff/sonoff_post.h | 4 ++++ sonoff/support_features.ino | 10 ++++++---- tools/decode-status.py | 2 +- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 2e65c4a16..22e837301 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.4.1.3 20181229 * Change sonoff_template.h module lay-out by removing non-configurable GPIOs + * Add support for MAX31855 K-Type thermocouple sensor using softSPI (#4764) * * 6.4.1.2 20181228 * Change switch driver making it modular and introduce input filter (#4665, #4724) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 69f21dec7..bf71c6222 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -285,9 +285,6 @@ // #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors // #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistors for single DS18B20 -// -- SPI sensors ---------------------------------- -#define USE_MAX31855 // Enable MAX31855 K-Type thermocouple sensor - // -- I2C sensors --------------------------------- #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) @@ -382,6 +379,8 @@ #define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) // -- Low level interface devices ----------------- +//#define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI + #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k3 code, 0k3 mem, 48 iram) // #define USE_IR_HVAC // Support for HVAC (Toshiba, Mitsubishi and LG) system using IR (+3k5 code) #define USE_IR_RECEIVE // Support for IR receiver (+7k2 code, 264 iram) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 12a68fe47..b73c4e4f0 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -116,6 +116,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) #define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) #define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) +#define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) @@ -182,6 +183,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer +#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI #undef USE_IR_REMOTE // Disable IR remote commands using library IRremoteESP8266 and ArduinoJson #undef USE_IR_RECEIVE // Disable support for IR receiver #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller @@ -303,6 +305,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor //#undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 +#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI #undef USE_IR_REMOTE // Disable IR driver #undef USE_WS2812 // Disable WS2812 Led string #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller @@ -366,6 +369,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor #undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 +#undef USE_MAX31855 // DIsable MAX31855 K-Type thermocouple sensor using softSPI #undef USE_IR_REMOTE // Disable IR driver #undef USE_WS2812 // Disable WS2812 Led string #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 75ddaf327..15e9ecf86 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -365,15 +365,17 @@ void GetFeatures(void) feature_sns2 |= 0x00008000; // xsns_37_rfsensor.ino #endif #ifdef USE_THEO_V2 - feature_sns2 |= 0x00010000; + feature_sns2 |= 0x00010000; // xsns_37_rfsensor.ino #endif #ifdef USE_ALECTO_V2 - feature_sns2 |= 0x00020000; + feature_sns2 |= 0x00020000; // xsns_37_rfsensor.ino #endif #ifdef USE_AZ7798 - feature_sns2 |= 0x00040000; + feature_sns2 |= 0x00040000; // xsns_38_az7798.ino +#endif +#ifdef USE_MAX31855 + feature_sns2 |= 0x00080000; // xsns_39_max31855.ino #endif -// feature_sns2 |= 0x00080000; // feature_sns2 |= 0x00100000; // feature_sns2 |= 0x00200000; // feature_sns2 |= 0x00400000; diff --git a/tools/decode-status.py b/tools/decode-status.py index ce8be9131..c96ddf401 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -135,7 +135,7 @@ a_features = [[ "USE_MCP230xx_OUTPUT","USE_MCP230xx_DISPLAYOUTPUT","USE_HLW8012","USE_CSE7766", "USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711", "USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","USE_RF_SENSOR", - "USE_THEO_V2","USE_ALECTO_V2","USE_AZ7798","", + "USE_THEO_V2","USE_ALECTO_V2","USE_AZ7798","USE_MAX31855", "","","","", "","","","", "","","",""]] From 447ec6256eb6e277a350ea94a387e5c7755f5693 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 1 Jan 2019 13:55:01 +0100 Subject: [PATCH 0784/2222] 6.4.1.4 Update Copyright (C) 2019 6.4.1.4 20190101 * Update Copyright (C) 2019 --- sonoff/_changelog.ino | 5 ++++- sonoff/i18n.h | 2 +- sonoff/language/bg-BG.h | 2 +- sonoff/language/cs-CZ.h | 2 +- sonoff/language/de-DE.h | 2 +- sonoff/language/el-GR.h | 2 +- sonoff/language/en-GB.h | 2 +- sonoff/language/es-AR.h | 2 +- sonoff/language/fr-FR.h | 2 +- sonoff/language/he-HE.h | 2 +- sonoff/language/hu-HU.h | 2 +- sonoff/language/it-IT.h | 2 +- sonoff/language/nl-NL.h | 2 +- sonoff/language/pl-PL.h | 2 +- sonoff/language/pt-BR.h | 2 +- sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 2 +- sonoff/language/sk-SK.h | 2 +- sonoff/language/sv-SE.h | 2 +- sonoff/language/tr-TR.h | 2 +- sonoff/language/uk-UK.h | 2 +- sonoff/language/zh-CN.h | 2 +- sonoff/language/zh-TW.h | 2 +- sonoff/my_user_config.h | 2 +- sonoff/settings.h | 2 +- sonoff/settings.ino | 2 +- sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 2 +- sonoff/sonoff_letsencrypt.h | 2 +- sonoff/sonoff_post.h | 2 +- sonoff/sonoff_template.h | 2 +- sonoff/sonoff_version.h | 4 ++-- sonoff/support.ino | 2 +- sonoff/support_features.ino | 2 +- sonoff/support_rtc.ino | 2 +- sonoff/support_switch.ino | 4 ++-- sonoff/support_wifi.ino | 2 +- sonoff/user_config_override_sample.h | 2 +- sonoff/xdrv_01_webserver.ino | 2 +- sonoff/xdrv_02_mqtt.ino | 2 +- sonoff/xdrv_03_energy.ino | 2 +- sonoff/xdrv_04_light.ino | 2 +- sonoff/xdrv_05_irremote.ino | 2 +- sonoff/xdrv_06_snfbridge.ino | 2 +- sonoff/xdrv_07_domoticz.ino | 2 +- sonoff/xdrv_08_serial_bridge.ino | 2 +- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_10_rules.ino | 2 +- sonoff/xdrv_11_knx.ino | 2 +- sonoff/xdrv_12_home_assistant.ino | 2 +- sonoff/xdrv_13_display.ino | 2 +- sonoff/xdrv_14_mp3.ino | 2 +- sonoff/xdrv_15_pca9685.ino | 2 +- sonoff/xdrv_16_tuyadimmer.ino | 2 +- sonoff/xdrv_17_rcswitch.ino | 2 +- sonoff/xdrv_18_armtronix_dimmers.ino | 2 +- sonoff/xdrv_19_ps16dz_dimmer.ino | 2 +- sonoff/xdrv_99_debug.ino | 2 +- sonoff/xdrv_interface.ino | 2 +- sonoff/xdsp_01_lcd.ino | 2 +- sonoff/xdsp_02_ssd1306.ino | 2 +- sonoff/xdsp_03_matrix.ino | 2 +- sonoff/xdsp_04_ili9341.ino | 2 +- sonoff/xdsp_05_epaper_29.ino | 2 +- sonoff/xdsp_interface.ino | 2 +- sonoff/xnrg_01_hlw8012.ino | 2 +- sonoff/xnrg_02_cse7766.ino | 2 +- sonoff/xnrg_03_pzem004t.ino | 2 +- sonoff/xnrg_04_mcp39f501.ino | 2 +- sonoff/xnrg_05_pzem_ac.ino | 2 +- sonoff/xnrg_06_pzem_dc.ino | 2 +- sonoff/xnrg_interface.ino | 2 +- sonoff/xplg_wemohue.ino | 2 +- sonoff/xplg_ws2812.ino | 2 +- sonoff/xsns_01_counter.ino | 2 +- sonoff/xsns_02_analog.ino | 2 +- sonoff/xsns_04_snfsc.ino | 2 +- sonoff/xsns_05_ds18b20.ino | 2 +- sonoff/xsns_05_ds18x20.ino | 2 +- sonoff/xsns_05_ds18x20_legacy.ino | 2 +- sonoff/xsns_06_dht.ino | 2 +- sonoff/xsns_07_sht1x.ino | 2 +- sonoff/xsns_08_htu21.ino | 2 +- sonoff/xsns_09_bmp.ino | 2 +- sonoff/xsns_10_bh1750.ino | 2 +- sonoff/xsns_11_veml6070.ino | 2 +- sonoff/xsns_12_ads1115.ino | 2 +- sonoff/xsns_12_ads1115_i2cdev.ino | 2 +- sonoff/xsns_13_ina219.ino | 2 +- sonoff/xsns_14_sht3x.ino | 2 +- sonoff/xsns_15_mhz19.ino | 2 +- sonoff/xsns_16_tsl2561.ino | 2 +- sonoff/xsns_17_senseair.ino | 2 +- sonoff/xsns_18_pms5003.ino | 2 +- sonoff/xsns_19_mgs.ino | 2 +- sonoff/xsns_20_novasds.ino | 2 +- sonoff/xsns_21_sgp30.ino | 2 +- sonoff/xsns_22_sr04.ino | 2 +- sonoff/xsns_23_sdm120.ino | 2 +- sonoff/xsns_24_si1145.ino | 2 +- sonoff/xsns_25_sdm630.ino | 2 +- sonoff/xsns_26_lm75ad.ino | 2 +- sonoff/xsns_27_apds9960.ino | 2 +- sonoff/xsns_28_tm1638.ino | 2 +- sonoff/xsns_29_mcp230xx.ino | 2 +- sonoff/xsns_31_ccs811.ino | 2 +- sonoff/xsns_32_mpu6050.ino | 2 +- sonoff/xsns_33_ds3231.ino | 2 +- sonoff/xsns_34_hx711.ino | 2 +- sonoff/xsns_35_tx20.ino | 2 +- sonoff/xsns_36_mgc3130.ino | 2 +- sonoff/xsns_37_rfsensor.ino | 2 +- sonoff/xsns_38_az7798.ino | 2 +- sonoff/xsns_39_max31855.ino | 2 +- sonoff/xsns_interface.ino | 2 +- sonoff/zzzz_debug.ino | 2 +- tools/decode-config.py | 2 +- tools/decode-status.py | 2 +- tools/fw_server/fw-server.py | 2 +- 119 files changed, 124 insertions(+), 121 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 22e837301..a79d21d35 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.3 20181229 +/* 6.4.1.4 20190101 + * Update Copyright (C) 2019 + * + * 6.4.1.3 20181229 * Change sonoff_template.h module lay-out by removing non-configurable GPIOs * Add support for MAX31855 K-Type thermocouple sensor using softSPI (#4764) * diff --git a/sonoff/i18n.h b/sonoff/i18n.h index a4de6d1bd..a90028e8d 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -1,7 +1,7 @@ /* i18n.h - internationalization for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index cf899685f..d6ba96985 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -1,7 +1,7 @@ /* bg-BG.h - localization for Bulgaria - Bulgarian for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 21366053b..b30f94520 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -1,7 +1,7 @@ /* cs-CZ.h - localization for Czech with diacritics - Czech for Sonoff-Tasmota - Copyright (C) 2018 Vladimír Synek + Copyright (C) 2019 Vladimír Synek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 80ea03d1e..d3650b2d3 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -1,7 +1,7 @@ /* de-DE.h - localization for German - Germany for Sonoff-Tasmota - Copyright (C) 2018 VinceMasuka + Copyright (C) 2019 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 diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index b36efe3b4..268513060 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -1,7 +1,7 @@ /* el-GR.h - localization for Greek - Greece for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends (translated by Nick Galfas) + Copyright (C) 2019 Theo Arends (translated by Nick Galfas) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 20b4f8ddb..f250e2d24 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -1,7 +1,7 @@ /* en-GB.h - localization for English - United Kingdom for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index dbf69404f..00bbc10a8 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -1,7 +1,7 @@ /* es-AR.h - localization for Spanish - Argentina for Sonoff-Tasmota - Copyright (C) 2018 Adrian Scillato + Copyright (C) 2019 Adrian Scillato This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 1a3cfae5f..1bea80a9a 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -1,7 +1,7 @@ /* fr-FR.h - localization for French - France for Sonoff-Tasmota - Copyright (C) 2018 Olivier Francais + Copyright (C) 2019 Olivier Francais This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index cbfacad14..eb2e42152 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -1,7 +1,7 @@ /* he-HE.h - localization for Hebrew - Israel for Sonoff-Tasmota - Copyright (C) 2018 Yuval Mejahez + Copyright (C) 2019 Yuval Mejahez This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index ea2f65ea0..d6c880603 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -1,7 +1,7 @@ /* hu-HU.h - localization for Hungarian in Hungary for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index b497ef04b..58130173f 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -1,7 +1,7 @@ /* it-IT.h - localization for Italian - Italy for Sonoff-Tasmota - Copyright (C) 2018 Gennaro Tortone - some mods by Antonio Fragola + Copyright (C) 2019 Gennaro Tortone - some mods by Antonio Fragola This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index df9d4dcb1..62b40fa9c 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -1,7 +1,7 @@ /* nl-NL.h - localization for Dutch - Nederland for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 7a42aff61..2fd04d93a 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -1,7 +1,7 @@ /* pl-PL-d.h - localization for Polish with diacritics - Poland for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends (translated by roblad - Robert L., upgraded by R. Turala) + Copyright (C) 2019 Theo Arends (translated by roblad - Robert L., upgraded by R. Turala) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index c62816af8..9daa847d3 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -1,7 +1,7 @@ /* pt-BR.h - localization for Portuguese - Brazil for Sonoff-Tasmota - Copyright (C) 2018 Fabiano Bovo + Copyright (C) 2019 Fabiano Bovo This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 5e2b13255..73d148c7c 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -1,7 +1,7 @@ /* pt-PT.h - localization for Portuguese - Portugal for Sonoff-Tasmota - Copyright (C) 2018 Paulo Paiva + Copyright (C) 2019 Paulo Paiva This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index ef8aaccef..fa698eddd 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -1,7 +1,7 @@ /* ru-RU.h - localization for Russian - Rissia for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends / roman-vn + Copyright (C) 2019 Theo Arends / roman-vn This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 16da51d32..492fc7d5a 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -1,7 +1,7 @@ /* sk-SK.h - localization for Slovak with diacritics - Slovak for Sonoff-Tasmota - Copyright (C) 2018 Vladimír Jendroľ + Copyright (C) 2019 Vladimír Jendroľ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 7f1b4ba5a..6f5f82b0e 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -1,7 +1,7 @@ /* sv-SE.h - localization for Swedish - Svenska for Sonoff-Tasmota - Copyright (C) 2018 Gunnar Norin + Copyright (C) 2019 Gunnar Norin This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 4ff68c52f..9d66169a9 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -1,7 +1,7 @@ /* tr-TR.h - localization for Turkish - Turkey for Sonoff-Tasmota - Copyright (C) 2018 Ali Sait Teke and Theo Arends + Copyright (C) 2019 Ali Sait Teke 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 diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 5043c857c..b6e870e8f 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -1,7 +1,7 @@ /* uk-UK.h - localization for Ukrainian - Ukrain for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends / vadym-adik + Copyright (C) 2019 Theo Arends / vadym-adik This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 858d45186..c02722897 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -1,7 +1,7 @@ /* zh-CN.h - localization for Chinese (Simplified) - China for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends (translated by killadm) + Copyright (C) 2019 Theo Arends (translated by killadm) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index b1a46d3a4..d2524da4f 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -1,7 +1,7 @@ /* zh-TW.h - localization for Chinese (Traditional) - Taiwan for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends (translated by dannydu) + Copyright (C) 2019 Theo Arends (translated by dannydu) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index bf71c6222..0e4d95f89 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -1,7 +1,7 @@ /* my_user_config.h - user specific configuration for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/settings.h b/sonoff/settings.h index 4de813d18..6397d2d13 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -1,7 +1,7 @@ /* settings.h - setting variables for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 3c6a6465e..03d7ef08e 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -1,7 +1,7 @@ /* settings.ino - user settings for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 7c2de21e6..59b7a96f2 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -1,7 +1,7 @@ /* sonoff.h - Master header file for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index e1d796c57..c05c11626 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1,7 +1,7 @@ /* sonoff.ino - Sonoff-Tasmota firmware for iTead Sonoff, Wemos and NodeMCU hardware - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/sonoff_letsencrypt.h b/sonoff/sonoff_letsencrypt.h index fa00c9f29..24735b2bd 100644 --- a/sonoff/sonoff_letsencrypt.h +++ b/sonoff/sonoff_letsencrypt.h @@ -1,7 +1,7 @@ /* sonoff_letsencrypt.h - TLS Lets Encrypt certificate for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index b73c4e4f0..a265627fc 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -1,7 +1,7 @@ /* sonoff_post.h - Post header file for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 2ab1eaaf8..7b9740b7c 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1,7 +1,7 @@ /* sonoff_template.h - template settings for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 8bb04be1a..af8d59cd7 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -1,7 +1,7 @@ /* sonoff_version.h - Version header file for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 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 @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040103 +#define VERSION 0x06040104 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index 77e2223c0..43f36565e 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1,7 +1,7 @@ /* support.ino - support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 15e9ecf86..299f0aedd 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -1,7 +1,7 @@ /* support_features.ino - feature support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index b09c593e2..e5f302de3 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -1,7 +1,7 @@ /* support_rtc.ino - Real Time Clock support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino index 57794db1a..444ba9475 100644 --- a/sonoff/support_switch.ino +++ b/sonoff/support_switch.ino @@ -1,7 +1,7 @@ /* support_switch.ino - switch support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 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 @@ -98,7 +98,7 @@ void SwitchProbe(void) if (switch_state_buf[i] > 0) { switch_state_buf[i]--; if (0 == switch_state_buf[i]) { - switch_virtual[i] = 0; + switch_virtual[i] = 0; } } } diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 8e45f58ea..6b6041764 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -1,7 +1,7 @@ /* support_wifi.ino - wifi support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/user_config_override_sample.h b/sonoff/user_config_override_sample.h index 8d0abb22f..678ad922e 100644 --- a/sonoff/user_config_override_sample.h +++ b/sonoff/user_config_override_sample.h @@ -1,7 +1,7 @@ /* user_config_override.h - user configuration overrides my_user_config.h for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index a62e8ea47..b81624bd7 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1,7 +1,7 @@ /* xdrv_01_webserver.ino - webserver for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index a621ef100..1a3525cbc 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -1,7 +1,7 @@ /* xdrv_02_mqtt.ino - mqtt support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index b97c53fc2..50e4f3d69 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -1,7 +1,7 @@ /* xdrv_03_energy.ino - Energy sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 8134ba19c..cbead5e4c 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -1,7 +1,7 @@ /* xdrv_04_light.ino - PWM, WS2812 and sonoff led support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index ef02e61ba..16dda3010 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -1,7 +1,7 @@ /* xdrv_05_irremote.ino - infra red support for Sonoff-Tasmota - Copyright (C) 2018 Heiko Krupp, Lazar Obradovic and Theo Arends + Copyright (C) 2019 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 diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 8e6b62641..55218bcbc 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -1,7 +1,7 @@ /* xdrv_06_snfbridge.ino - sonoff RF bridge 433 support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends and Erik Andrén Zachrisson (fw update) + Copyright (C) 2019 Theo Arends and Erik Andrén Zachrisson (fw update) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 80155925c..38f6535b2 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -1,7 +1,7 @@ /* xdrv_07_domoticz.ino - domoticz support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index b29bb7393..08a4f7211 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -1,7 +1,7 @@ /* xdrv_08_serial_bridge.ino - serial bridge support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends and Dániel Zoltán Tolnai + Copyright (C) 2019 Theo Arends and Dániel Zoltán Tolnai This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 820125e3d..f950c5ce0 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -1,7 +1,7 @@ /* xdrv_09_timers.ino - timer support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 3125ef8fa..d96ae6d61 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -1,7 +1,7 @@ /* xdrv_10_rules.ino - rule support for Sonoff-Tasmota - Copyright (C) 2018 ESP Easy Group and Theo Arends + Copyright (C) 2019 ESP Easy Group 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 diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 03a77744c..1f9d702dd 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -1,7 +1,7 @@ /* xdrv_11_knx.ino - KNX IP Protocol support for Sonoff-Tasmota - Copyright (C) 2018 Adrian Scillato (https://github.com/ascillato) + Copyright (C) 2019 Adrian Scillato (https://github.com/ascillato) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 233144e4b..26609d1d7 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -1,7 +1,7 @@ /* xdrv_12_home_assistant.ino - home assistant support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index f585f842c..a3034bca2 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -1,7 +1,7 @@ /* xdrv_13_display.ino - Display support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_14_mp3.ino b/sonoff/xdrv_14_mp3.ino index 973c3fe5e..5e7ca23e1 100644 --- a/sonoff/xdrv_14_mp3.ino +++ b/sonoff/xdrv_14_mp3.ino @@ -1,7 +1,7 @@ /* xdrv_14_mp3.ino - MP3 support for Sonoff-Tasmota - Copyright (C) 2018 gemu2015, mike2nl and Theo Arends + Copyright (C) 2019 gemu2015, mike2nl 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 diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index b29e85a5b..c55581dc9 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -1,7 +1,7 @@ /* xdrv_15_pca9685.ino - Support for I2C PCA9685 12bit 16 pin hardware PWM driver - Copyright (C) 2018 Andre Thomas and Theo Arends + Copyright (C) 2019 Andre Thomas 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 diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index d0ab215a5..da03b2c79 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -1,7 +1,7 @@ /* xdrv_16_tuyadimmer.ino - Tuya dimmer support for Sonoff-Tasmota - Copyright (C) 2018 digiblur, Joel Stein and Theo Arends + Copyright (C) 2019 digiblur, Joel Stein 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 diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index cb972e87d..4f992180e 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -1,7 +1,7 @@ /* xdrv_17_rcswitch.ino - RF transceiver using RcSwitch library for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_18_armtronix_dimmers.ino b/sonoff/xdrv_18_armtronix_dimmers.ino index 9e0e9c7f9..3484ed8e6 100644 --- a/sonoff/xdrv_18_armtronix_dimmers.ino +++ b/sonoff/xdrv_18_armtronix_dimmers.ino @@ -1,7 +1,7 @@ /* xdrv_18_armtronix_dimmers.ino - Armtronix dimmers support for Sonoff-Tasmota - Copyright (C) 2018 wvdv2002 and Theo Arends + Copyright (C) 2019 wvdv2002 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 diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 7671249eb..33fb72ab6 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -1,7 +1,7 @@ /* xdrv_19_ps16dz_dimmer.ino - PS_16_DZ dimmer support for Sonoff-Tasmota - Copyright (C) 2018 Joel Stein and Theo Arends + Copyright (C) 2019 Joel Stein 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 diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_99_debug.ino index 30e51121f..13b420d2e 100644 --- a/sonoff/xdrv_99_debug.ino +++ b/sonoff/xdrv_99_debug.ino @@ -1,7 +1,7 @@ /* xdrv_99_debug.ino - debug support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 1500f184b..9f60731d6 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -1,7 +1,7 @@ /* xdrv_interface.ino - Driver interface support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends inspired by ESPEasy + Copyright (C) 2019 Theo Arends inspired by ESPEasy This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdsp_01_lcd.ino b/sonoff/xdsp_01_lcd.ino index 60fe0bab6..107bae676 100644 --- a/sonoff/xdsp_01_lcd.ino +++ b/sonoff/xdsp_01_lcd.ino @@ -1,7 +1,7 @@ /* xdsp_01_lcd.ino - Display LCD support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends and Adafruit + Copyright (C) 2019 Theo Arends and Adafruit This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdsp_02_ssd1306.ino b/sonoff/xdsp_02_ssd1306.ino index 4ccdcd9c9..eb8f34701 100644 --- a/sonoff/xdsp_02_ssd1306.ino +++ b/sonoff/xdsp_02_ssd1306.ino @@ -1,7 +1,7 @@ /* xdsp_02_ssd1306.ino - Display Oled ssd1306 support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends and Adafruit + Copyright (C) 2019 Theo Arends and Adafruit This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index da458cb15..39c40ac39 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -1,7 +1,7 @@ /* xdsp_03_matrix.ino - Display 8x8 matrix support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends and Adafruit + Copyright (C) 2019 Theo Arends and Adafruit This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdsp_04_ili9341.ino b/sonoff/xdsp_04_ili9341.ino index b4149035e..ba94eece2 100644 --- a/sonoff/xdsp_04_ili9341.ino +++ b/sonoff/xdsp_04_ili9341.ino @@ -1,7 +1,7 @@ /* xdsp_04_ili9341.ino - Display Tft Ili9341 support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends and Adafruit + Copyright (C) 2019 Theo Arends and Adafruit This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdsp_05_epaper_29.ino b/sonoff/xdsp_05_epaper_29.ino index 24bb19655..2a7daeb90 100644 --- a/sonoff/xdsp_05_epaper_29.ino +++ b/sonoff/xdsp_05_epaper_29.ino @@ -1,7 +1,7 @@ /* xdsp_05_epaper_29.ino - 2.9 Inch display e-paper support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends, Gerhard Mutz and Waveshare + Copyright (C) 2019 Theo Arends, Gerhard Mutz and Waveshare This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xdsp_interface.ino b/sonoff/xdsp_interface.ino index 01e4424dd..b0d760a37 100644 --- a/sonoff/xdsp_interface.ino +++ b/sonoff/xdsp_interface.ino @@ -1,7 +1,7 @@ /* xdsp_interface.ino - Display interface support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 0a4419498..e336d805c 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -1,7 +1,7 @@ /* xnrg_01_hlw8012.ino - HLW8012 (Sonoff Pow) energy sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xnrg_02_cse7766.ino b/sonoff/xnrg_02_cse7766.ino index 2286a6fa3..2dc6b2674 100644 --- a/sonoff/xnrg_02_cse7766.ino +++ b/sonoff/xnrg_02_cse7766.ino @@ -1,7 +1,7 @@ /* xnrg_02_cse7766.ino - CSE7766 energy sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index 850131762..846c14431 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -1,7 +1,7 @@ /* xnrg_03_pzem004t.ino - PZEM004T energy sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index d962ef204..0301bf040 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -1,7 +1,7 @@ /* xnrg_04_mcp39f501.ino - MCP39F501 energy sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index 7c145384a..a171b4079 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -1,7 +1,7 @@ /* xnrg_05_pzem_ac.ino - PZEM-014,016 Modbus AC energy sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index c12f401d4..2adda5092 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -1,7 +1,7 @@ /* xnrg_06_pzem_dc.ino - PZEM-003,017 Modbus DC energy sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xnrg_interface.ino b/sonoff/xnrg_interface.ino index 32af6451c..0d3953398 100644 --- a/sonoff/xnrg_interface.ino +++ b/sonoff/xnrg_interface.ino @@ -1,7 +1,7 @@ /* xnrg_interface.ino - Energy driver interface support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends inspired by ESPEasy + Copyright (C) 2019 Theo Arends inspired by ESPEasy This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 143d0e6ba..156a95770 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -1,7 +1,7 @@ /* xplg_wemohue.ino - wemo and hue support for Sonoff-Tasmota - Copyright (C) 2018 Heiko Krupp and Theo Arends + Copyright (C) 2019 Heiko Krupp 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 diff --git a/sonoff/xplg_ws2812.ino b/sonoff/xplg_ws2812.ino index 423c834ff..1d66558d6 100644 --- a/sonoff/xplg_ws2812.ino +++ b/sonoff/xplg_ws2812.ino @@ -1,7 +1,7 @@ /* xplg_ws2812.ino - ws2812 led string support for Sonoff-Tasmota - Copyright (C) 2018 Heiko Krupp and Theo Arends + Copyright (C) 2019 Heiko Krupp 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 diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index 6b501d49f..2b031f20e 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -1,7 +1,7 @@ /* xsns_01_counter.ino - Counter sensors (water meters, electricity meters etc.) sensor support for Sonoff-Tasmota - Copyright (C) 2018 Maarten Damen and Theo Arends + Copyright (C) 2019 Maarten Damen 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 diff --git a/sonoff/xsns_02_analog.ino b/sonoff/xsns_02_analog.ino index cb4e794f1..bb47757d3 100644 --- a/sonoff/xsns_02_analog.ino +++ b/sonoff/xsns_02_analog.ino @@ -1,7 +1,7 @@ /* xsns_02_analog.ino - ESP8266 ADC support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index d3329e3e5..ef72a01e6 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -1,7 +1,7 @@ /* xsns_04_snfsc.ino - sonoff SC support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index 9951ee0d0..713c10a81 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -1,7 +1,7 @@ /* xsns_05_ds18b20.ino - DS18B20 temperature sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index ba7752741..c2367abe1 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -1,7 +1,7 @@ /* xsns_05_ds18x20.ino - DS18x20 temperature sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index 5a89a0abe..8e61aef84 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -1,7 +1,7 @@ /* xsns_05_ds18x20_legacy.ino - DS18x20 temperature sensor support for Sonoff-Tasmota - Copyright (C) 2018 Heiko Krupp and Theo Arends + Copyright (C) 2019 Heiko Krupp 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 diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index 72f94edd7..2178e2617 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -1,7 +1,7 @@ /* xsns_06_dht.ino - DHTxx, AM23xx and SI7021 temperature and humidity sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index 0bf2d774c..3e1452ab6 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -1,7 +1,7 @@ /* xsns_07_sht1x.ino - SHT1x temperature and sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index 3e22c17f3..30040f7e1 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -1,7 +1,7 @@ /* xsns_08_htu21.ino - HTU21 temperature and humidity sensor support for Sonoff-Tasmota - Copyright (C) 2018 Heiko Krupp and Theo Arends + Copyright (C) 2019 Heiko Krupp 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 diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index 6023ba5cc..6c7bbc31b 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -1,7 +1,7 @@ /* xsns_09_bmp.ino - BMP pressure, temperature, humidity and gas sensor support for Sonoff-Tasmota - Copyright (C) 2018 Heiko Krupp and Theo Arends + Copyright (C) 2019 Heiko Krupp 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 diff --git a/sonoff/xsns_10_bh1750.ino b/sonoff/xsns_10_bh1750.ino index af0d1aebb..23775abb1 100644 --- a/sonoff/xsns_10_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -1,7 +1,7 @@ /* xsns_10_bh1750.ino - BH1750 ambient light sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index 0177fcc63..b2512c56b 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -1,7 +1,7 @@ /* xsns_11_veml6070.ino - VEML6070 ultra violet light sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index d07831725..7ba59f2bb 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -1,7 +1,7 @@ /* xsns_12_ads1115_ada.ino - ADS1115 A/D Converter support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/sonoff/xsns_12_ads1115_i2cdev.ino index 96c2f7006..4de6650ac 100644 --- a/sonoff/xsns_12_ads1115_i2cdev.ino +++ b/sonoff/xsns_12_ads1115_i2cdev.ino @@ -1,7 +1,7 @@ /* xsns_12_ads1115.ino - ADS1x15 A/D Converter support for Sonoff-Tasmota - Copyright (C) 2018 Stefan Bode and Theo Arends + Copyright (C) 2019 Stefan Bode 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 diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index ae5999a7e..2b812f05d 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -1,7 +1,7 @@ /* xsns_13_ina219.ino - INA219 Current Sensor support for Sonoff-Tasmota - Copyright (C) 2018 Stefan Bode and Theo Arends + Copyright (C) 2019 Stefan Bode 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 diff --git a/sonoff/xsns_14_sht3x.ino b/sonoff/xsns_14_sht3x.ino index 6738b866a..25901d934 100755 --- a/sonoff/xsns_14_sht3x.ino +++ b/sonoff/xsns_14_sht3x.ino @@ -1,7 +1,7 @@ /* xsns_14_sht3x.ino - SHT3X temperature and humidity sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 968c0d021..9c2839c18 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -1,7 +1,7 @@ /* xsns_15_mhz19.ino - MH-Z19(B) CO2 sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index 0285c55e0..063adfb87 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -1,7 +1,7 @@ /* xsns_16_tsl2561.ino - TSL2561 light sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends and Joachim Banzhaf + Copyright (C) 2019 Theo Arends and Joachim Banzhaf This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_17_senseair.ino b/sonoff/xsns_17_senseair.ino index 967563972..375d705b4 100644 --- a/sonoff/xsns_17_senseair.ino +++ b/sonoff/xsns_17_senseair.ino @@ -1,7 +1,7 @@ /* xsns_17_senseair.ino - SenseAir CO2 sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_18_pms5003.ino b/sonoff/xsns_18_pms5003.ino index 271b94301..50ad9f7af 100644 --- a/sonoff/xsns_18_pms5003.ino +++ b/sonoff/xsns_18_pms5003.ino @@ -1,7 +1,7 @@ /* xsns_18_pms5003.ino - PMS5003-7003 particle concentration sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_19_mgs.ino b/sonoff/xsns_19_mgs.ino index 36ce969f7..e4ce80643 100644 --- a/sonoff/xsns_19_mgs.ino +++ b/sonoff/xsns_19_mgs.ino @@ -1,7 +1,7 @@ /* xsns_19_mgs.ino - Xadow and Grove Mutichannel Gas sensor support for Sonoff-Tasmota - Copyright (C) 2018 Palich2000 and Theo Arends + Copyright (C) 2019 Palich2000 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 diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index dfb08ac5a..e3e1e48e9 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -1,7 +1,7 @@ /* xsns_20_novasds.ino - Nova SDS011/SDS021 particle concentration sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_21_sgp30.ino b/sonoff/xsns_21_sgp30.ino index 7c22da514..0394b12bf 100644 --- a/sonoff/xsns_21_sgp30.ino +++ b/sonoff/xsns_21_sgp30.ino @@ -1,7 +1,7 @@ /* xsns_21_sgp30.ino - SGP30 gas and air quality sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index 0278011e1..9fa9f7322 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -1,7 +1,7 @@ /* xsns_22_sr04.ino - SR04 ultrasonic sensor support for Sonoff-Tasmota - Copyright (C) 2018 Nuno Ferreira and Theo Arends + Copyright (C) 2019 Nuno Ferreira 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 diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino index 9f27927e8..e162d9cad 100644 --- a/sonoff/xsns_23_sdm120.ino +++ b/sonoff/xsns_23_sdm120.ino @@ -1,7 +1,7 @@ /* xsns_23_sdm120.ino - Eastron SDM120-Modbus energy meter support for Sonoff-Tasmota - Copyright (C) 2018 Gennaro Tortone + Copyright (C) 2019 Gennaro Tortone This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_24_si1145.ino b/sonoff/xsns_24_si1145.ino index 7b051ebe0..547c25110 100644 --- a/sonoff/xsns_24_si1145.ino +++ b/sonoff/xsns_24_si1145.ino @@ -1,7 +1,7 @@ /* xsns_24_si1145.ino - SI1145/46/47 UV Index / IR / Visible light sensor support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_25_sdm630.ino b/sonoff/xsns_25_sdm630.ino index 9060444b3..631596fff 100644 --- a/sonoff/xsns_25_sdm630.ino +++ b/sonoff/xsns_25_sdm630.ino @@ -1,7 +1,7 @@ /* xsns_25_sdm630.ino - Eastron SDM630-Modbus energy meter support for Sonoff-Tasmota - Copyright (C) 2018 Gennaro Tortone + Copyright (C) 2019 Gennaro Tortone This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_26_lm75ad.ino b/sonoff/xsns_26_lm75ad.ino index 3b548fa8f..dc41fd526 100644 --- a/sonoff/xsns_26_lm75ad.ino +++ b/sonoff/xsns_26_lm75ad.ino @@ -1,7 +1,7 @@ /* xsns_26_lm75ad.ino - Support for I2C LM75AD Temperature Sensor - Copyright (C) 2018 Andre Thomas and Theo Arends + Copyright (C) 2019 Andre Thomas 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 diff --git a/sonoff/xsns_27_apds9960.ino b/sonoff/xsns_27_apds9960.ino index 33b98a5d2..063f519be 100644 --- a/sonoff/xsns_27_apds9960.ino +++ b/sonoff/xsns_27_apds9960.ino @@ -1,7 +1,7 @@ /* xsns_27_apds9960.ino - Support for I2C APDS9960 Proximity Sensor for Sonoff-Tasmota - Copyright (C) 2018 Shawn Hymel/Sparkfun and Theo Arends + Copyright (C) 2019 Shawn Hymel/Sparkfun and Theo Arends Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/sonoff/xsns_28_tm1638.ino b/sonoff/xsns_28_tm1638.ino index b446fa97b..54f89548c 100644 --- a/sonoff/xsns_28_tm1638.ino +++ b/sonoff/xsns_28_tm1638.ino @@ -1,7 +1,7 @@ /* xsns_28_tm1638.ino - TM1638 8 switch, led and 7 segment unit support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 64f3351a5..7a223b945 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -1,7 +1,7 @@ /* xsns_29_mcp230xx.ino - Support for I2C MCP23008/MCP23017 GPIO Expander - Copyright (C) 2018 Andre Thomas and Theo Arends + Copyright (C) 2019 Andre Thomas 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 diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index 624dac34e..f68c14905 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -1,7 +1,7 @@ /* xsns_31_ccs811.ino - CCS811 gas and air quality sensor support for Sonoff-Tasmota - Copyright (C) 2018 Gerhard Mutz and Theo Arends + Copyright (C) 2019 Gerhard Mutz 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 diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index 8fbdfc6f3..bdc546e53 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -1,7 +1,7 @@ /* xsns_32_mpu6050.ino - MPU6050 gyroscope and temperature sensor support for Sonoff-Tasmota - Copyright (C) 2018 Oliver Welter + Copyright (C) 2019 Oliver Welter This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_33_ds3231.ino b/sonoff/xsns_33_ds3231.ino index d98f7163b..0e8e5c8f6 100644 --- a/sonoff/xsns_33_ds3231.ino +++ b/sonoff/xsns_33_ds3231.ino @@ -1,7 +1,7 @@ /* xsns_33_ds3231.ino - ds3231 RTC chip, act like sensor support for Sonoff-Tasmota - Copyright (C) 2018 Guy Elgabsi (guy.elg AT gmail.com) + Copyright (C) 2019 Guy Elgabsi (guy.elg AT gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 75a06e7de..e57b49c44 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -1,7 +1,7 @@ /* xsns_34_hx711.ino - HX711 load cell support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_35_tx20.ino b/sonoff/xsns_35_tx20.ino index a198c766f..ae2f05926 100644 --- a/sonoff/xsns_35_tx20.ino +++ b/sonoff/xsns_35_tx20.ino @@ -1,7 +1,7 @@ /* xsns_35_Tx20.ino - La Crosse Tx20 wind sensor support for Sonoff-Tasmota - Copyright (C) 2018 Thomas Eckerstorfer and Theo Arends + Copyright (C) 2019 Thomas Eckerstorfer 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 diff --git a/sonoff/xsns_36_mgc3130.ino b/sonoff/xsns_36_mgc3130.ino index 81f4a72c6..6def4d917 100644 --- a/sonoff/xsns_36_mgc3130.ino +++ b/sonoff/xsns_36_mgc3130.ino @@ -1,7 +1,7 @@ /* xsns_36_MGC3130.ino - Support for I2C MGC3130 Electric Field Sensor for Sonoff-Tasmota - Copyright (C) 2018 Christian Baars & Theo Arends + Copyright (C) 2019 Christian Baars & Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_37_rfsensor.ino b/sonoff/xsns_37_rfsensor.ino index efb864924..df6aeaf35 100644 --- a/sonoff/xsns_37_rfsensor.ino +++ b/sonoff/xsns_37_rfsensor.ino @@ -1,7 +1,7 @@ /* xsns_37_rfsensor.ino - RF sensor receiver for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino index b9ac0a012..d53b657c7 100644 --- a/sonoff/xsns_38_az7798.ino +++ b/sonoff/xsns_38_az7798.ino @@ -1,7 +1,7 @@ /* xsns_38_az7798.ino - AZ_Instrument 7798 CO2/temperature/humidity meter support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_39_max31855.ino b/sonoff/xsns_39_max31855.ino index 02288ca4b..724dcbb29 100644 --- a/sonoff/xsns_39_max31855.ino +++ b/sonoff/xsns_39_max31855.ino @@ -1,7 +1,7 @@ /* xsns_39_max31855.ino - MAX31855 thermocouple sensor support for Sonoff-Tasmota - Copyright (C) 2018 Markus Past + Copyright (C) 2019 Markus Past This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index 1c02787db..25747b90e 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -1,7 +1,7 @@ /* xsns_interface.ino - Sensor interface support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends inspired by ESPEasy + Copyright (C) 2019 Theo Arends inspired by ESPEasy This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sonoff/zzzz_debug.ino b/sonoff/zzzz_debug.ino index 3d159b922..674d4acc8 100644 --- a/sonoff/zzzz_debug.ino +++ b/sonoff/zzzz_debug.ino @@ -1,7 +1,7 @@ /* zzzz_debug.ino - debug support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/tools/decode-config.py b/tools/decode-config.py index d1daccf22..52cb63673 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -5,7 +5,7 @@ VER = '2.1.0015' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data - Copyright (C) 2018 Norbert Richter + Copyright (C) 2019 Norbert Richter This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/tools/decode-status.py b/tools/decode-status.py index c96ddf401..ddd94cb36 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -3,7 +3,7 @@ """ decode-status.py - decode status for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/tools/fw_server/fw-server.py b/tools/fw_server/fw-server.py index a9cbdf347..4d70f0f5e 100644 --- a/tools/fw_server/fw-server.py +++ b/tools/fw_server/fw-server.py @@ -3,7 +3,7 @@ """ fw-server.py - firmware server for Sonoff-Tasmota OTA upgrade -Copyright (C) 2018 Gennaro Tortone +Copyright (C) 2019 Gennaro Tortone 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 From 1fb7993d66844f692b5da07f2c4787cfb550d9b9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 2 Jan 2019 17:18:47 +0100 Subject: [PATCH 0785/2222] Fix epaper driver (#4785) Fix epaper driver (#4785) --- sonoff/_changelog.ino | 1 + sonoff/xdsp_05_epaper_29.ino | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index a79d21d35..0aa205aef 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.4.1.4 20190101 * Update Copyright (C) 2019 + * Fix epaper driver (#4785) * * 6.4.1.3 20181229 * Change sonoff_template.h module lay-out by removing non-configurable GPIOs diff --git a/sonoff/xdsp_05_epaper_29.ino b/sonoff/xdsp_05_epaper_29.ino index 2a7daeb90..3904cb97f 100644 --- a/sonoff/xdsp_05_epaper_29.ino +++ b/sonoff/xdsp_05_epaper_29.ino @@ -19,7 +19,7 @@ #ifdef USE_SPI #ifdef USE_DISPLAY -#ifdef USE_DISPLAY_EPAPER +#ifdef USE_DISPLAY_EPAPER_29 #define XDSP_05 5 @@ -123,12 +123,16 @@ void EpdInitDriver(void) epd.sclk_pin = pin[GPIO_SPI_CLK]; // 14 epd.mosi_pin = pin[GPIO_SPI_MOSI]; // 13 EpdInitMode(); + snprintf_P(log_data, sizeof(log_data), PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"), epd.cs_pin, epd.sclk_pin, epd.mosi_pin); + AddLog(LOG_LEVEL_DEBUG); } else if ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_MOSI] < 99)) { epd.cs_pin = pin[GPIO_SSPI_CS]; epd.sclk_pin = pin[GPIO_SSPI_SCLK]; epd.mosi_pin = pin[GPIO_SSPI_MOSI]; EpdInitMode(); + snprintf_P(log_data, sizeof(log_data), PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"), epd.cs_pin, epd.sclk_pin, epd.mosi_pin); + AddLog(LOG_LEVEL_DEBUG); } } } @@ -337,6 +341,6 @@ boolean Xdsp05(byte function) return result; } -#endif // USE_DISPLAY_EPAPER +#endif // USE_DISPLAY_EPAPER_29 #endif // USE_DISPLAY #endif // USE_SPI From 5ec7249ecef8b38aa5ed577f9368b91f19532c46 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Wed, 2 Jan 2019 22:04:33 +0200 Subject: [PATCH 0786/2222] Add support for PN532 NFC --- sonoff/my_user_config.h | 1 + sonoff/xsns_40_pn532_i2c.ino | 326 +++++++++++++++++++++++++++++++++++ 2 files changed, 327 insertions(+) create mode 100644 sonoff/xsns_40_pn532_i2c.ino diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 0e4d95f89..4f7c97dc8 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -322,6 +322,7 @@ // #define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) // #define USE_RTC_ADDR 0x68 // Default I2C address 0x68 // #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) +// #define USE_PN532_I2C // Enable PN532 - Near Field Communication (NFC) controller (+1k6 code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino new file mode 100644 index 000000000..64c7a4dde --- /dev/null +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -0,0 +1,326 @@ +/* + xsns_40_pn532.ino - Support for PN532 (I2C) NFC Tag Reader + + Copyright (C) 2019 Andre Thomas 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 + 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_PN532_I2C + +/*********************************************************************************************\ + * PN532 - Near Field Communication (NFC) controller + * + * Datasheet at https://www.nxp.com/docs/en/nxp/data-sheets/PN532_C1.pdf + * + * I2C Address: 0x24 +\*********************************************************************************************/ + +#define XSNS_40 40 + +#define PN532_I2C_ADDRESS 0x24 + +#define PN532_COMMAND_GETFIRMWAREVERSION 0x02 +#define PN532_COMMAND_SAMCONFIGURATION 0x14 +#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A + +#define PN532_PREAMBLE 0x00 +#define PN532_STARTCODE1 0x00 +#define PN532_STARTCODE2 0xFF +#define PN532_POSTAMBLE 0x00 + +#define PN532_HOSTTOPN532 0xD4 +#define PN532_PN532TOHOST 0xD5 + +#define PN532_INVALID_ACK -1 +#define PN532_TIMEOUT -2 +#define PN532_INVALID_FRAME -3 +#define PN532_NO_SPACE -4 + +#define PN532_MIFARE_ISO14443A 0x00 + +uint8_t pn532_i2c_detected = 0; +uint8_t pn532_i2c_packetbuffer[64]; +uint8_t pn532_i2c_scan_defer_report = 0; // If a valid card was found we will not scan for one again in the same two seconds so we set this to 19 if a card was found + +uint8_t pn532_i2c_command; + +int16_t PN532_getResponseLength(uint8_t buf[], uint8_t len, uint16_t timeout) { + const uint8_t PN532_NACK[] = {0, 0, 0xFF, 0xFF, 0, 0}; + uint16_t time = 0; + do { + if (Wire.requestFrom(PN532_I2C_ADDRESS, 6)) { + if (Wire.read() & 1) { // check first byte --- status + break; // PN532 is ready + } + } + delay(1); + time++; + if ((0 != timeout) && (time > timeout)) { + return -1; + } + } while (1); + + if ((0x00 != Wire.read()) || (0x00 != Wire.read()) || (0xFF != Wire.read())) { // PREAMBLE || STARTCODE1 || STARTCODE2 + return PN532_INVALID_FRAME; + } + + uint8_t length = Wire.read(); + + // request for last respond msg again + Wire.beginTransmission(PN532_I2C_ADDRESS); + for (uint16_t i = 0;i < sizeof(PN532_NACK); ++i) { + Wire.write(PN532_NACK[i]); + } + Wire.endTransmission(); + return length; +} + + +int16_t PN532_readResponse(uint8_t buf[], uint8_t len) +{ + uint16_t time = 0; + uint8_t length; + uint8_t timeout = 10; + + length = PN532_getResponseLength(buf, len, timeout); + + // [RDY] 00 00 FF LEN LCS (TFI PD0 ... PDn) DCS 00 + + do { + if (Wire.requestFrom(PN532_I2C_ADDRESS, 6 + length + 2)) { + if (Wire.read() & 1) { // check first byte --- status + break; // PN532 is ready + } + } + delay(1); + time++; + if ((0 != timeout) && (time > timeout)) { + return -1; + } + } while (1); + + if ((0x00 != Wire.read()) || (0x00 != Wire.read()) || (0xFF != Wire.read())) { // PREAMBLE || STARTCODE1 || STARTCODE2 + return PN532_INVALID_FRAME; + } + + length = Wire.read(); + + if (0 != (uint8_t)(length + Wire.read())) { // checksum of length + return PN532_INVALID_FRAME; + } + + uint8_t cmd = pn532_i2c_command + 1; // response command + if ((PN532_PN532TOHOST != Wire.read()) || ((cmd) != Wire.read())) { + return PN532_INVALID_FRAME; + } + length -= 2; + if (length > len) { + return PN532_NO_SPACE; // not enough space + } + uint8_t sum = PN532_PN532TOHOST + cmd; + for (uint8_t i = 0; i < length; i++) { + buf[i] = Wire.read(); + sum += buf[i]; + } + uint8_t checksum = Wire.read(); + if (0 != (uint8_t)(sum + checksum)) { + return PN532_INVALID_FRAME; + } + Wire.read(); // POSTAMBLE + return length; +} + + +int8_t PN532_readAckFrame() +{ + const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; + uint8_t ackBuf[sizeof(PN532_ACK)]; + + uint16_t time = 0; + + do { + if (Wire.requestFrom(PN532_I2C_ADDRESS, sizeof(PN532_ACK) + 1)) { + if (Wire.read() & 1) { // check first byte --- status + break; // PN532 is ready + } + } + delay(1); + time++; + if (time > 10) { // We time out after 10ms + return PN532_TIMEOUT; + } + } while (1); + + for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) { + ackBuf[i] = Wire.read(); + } + + if (memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK))) { + return PN532_INVALID_ACK; + } + + return 0; +} + +int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen) +{ + pn532_i2c_command = header[0]; + Wire.beginTransmission(PN532_I2C_ADDRESS); + Wire.write(PN532_PREAMBLE); + Wire.write(PN532_STARTCODE1); + Wire.write(PN532_STARTCODE2); + uint8_t length = hlen + 1; // TFI + DATA + Wire.write(length); + Wire.write(~length + 1); // checksum of length + Wire.write(PN532_HOSTTOPN532); + uint8_t sum = PN532_HOSTTOPN532; // Sum of TFI + DATA + for (uint8_t i = 0; i < hlen; i++) { + if (Wire.write(header[i])) { + sum += header[i]; + } else { + return PN532_INVALID_FRAME; + } + } + uint8_t checksum = ~sum + 1; // Checksum of TFI + DATA + Wire.write(checksum); + Wire.write(PN532_POSTAMBLE); + Wire.endTransmission(); + return PN532_readAckFrame(); +} + +uint32_t PN532_getFirmwareVersion(void) +{ + uint32_t response; + pn532_i2c_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION; + if (PN532_writeCommand(pn532_i2c_packetbuffer, 1)) { + return 0; + } + int16_t status = PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)); + if (0 > status) { + return 0; + } + response = pn532_i2c_packetbuffer[0]; + response <<= 8; + response |= pn532_i2c_packetbuffer[1]; + response <<= 8; + response |= pn532_i2c_packetbuffer[2]; + response <<= 8; + response |= pn532_i2c_packetbuffer[3]; + return response; +} + +bool PN532_SAMConfig(void) +{ + pn532_i2c_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; + pn532_i2c_packetbuffer[1] = 0x01; // normal mode; + pn532_i2c_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second + pn532_i2c_packetbuffer[3] = 0x01; // use IRQ pin! + + if (PN532_writeCommand(pn532_i2c_packetbuffer, 4)) + return false; + + return (0 < PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer))); +} + +void PN532_Detect(void) +{ + if (pn532_i2c_detected) { return; } + + uint32_t ver = PN532_getFirmwareVersion(); + if (ver) { + pn532_i2c_detected = 1; + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "PN532 NFC Reader (V%u.%u)", PN532_I2C_ADDRESS); + snprintf_P(log_data, sizeof(log_data), log_data, (ver>>16) & 0xFF, (ver>>8) & 0xFF); + AddLog(LOG_LEVEL_DEBUG); + PN532_SAMConfig(); + } +} + +boolean PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength) +{ + pn532_i2c_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; + pn532_i2c_packetbuffer[1] = 1; + pn532_i2c_packetbuffer[2] = cardbaudrate; + + if (PN532_writeCommand(pn532_i2c_packetbuffer, 3)) { + return false; // command failed + } + + if (PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)) < 0) { // No data packet so no tag was found + Wire.beginTransmission(PN532_I2C_ADDRESS); + Wire.endTransmission(); + return false; + } + + if (pn532_i2c_packetbuffer[0] != 1) { return false; } // Not a valid tag + + *uidLength = pn532_i2c_packetbuffer[5]; + for (uint8_t i = 0;i < pn532_i2c_packetbuffer[5]; i++) { + uid[i] = pn532_i2c_packetbuffer[6 + i]; + } + return true; +} + +void PN532_ScanForTag(void) +{ + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; + uint8_t uid_len = 0; + if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) { + if (pn532_i2c_scan_defer_report > 0) { + pn532_i2c_scan_defer_report--; + } else { + char uids[15]; + sprintf(uids,""); + for (uint8_t i = 0;i < uid_len;i++) { + sprintf(uids,"%s%X",uids,uid[i]); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + char command[15]; + sprintf(command,"event PN532=%s",uids); + ExecuteCommand(command, SRC_RULE); + pn532_i2c_scan_defer_report = 19; + } + } else { + if (pn532_i2c_scan_defer_report > 0) { pn532_i2c_scan_defer_report--; } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +boolean Xsns40(byte function) +{ + boolean result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_EVERY_100_MSECOND: + if (pn532_i2c_detected) { + PN532_ScanForTag(); + } + case FUNC_EVERY_SECOND: + PN532_Detect(); + break; + } + } + return result; +} + +#endif // USE_PN532_I2C +#endif // USE_I2C From 149b335a4bb8f2afbec89ef5008f6a2291b23591 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Wed, 2 Jan 2019 22:25:20 +0200 Subject: [PATCH 0787/2222] Add support for PN532 NFC --- sonoff/xsns_40_pn532_i2c.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index 64c7a4dde..6ef9896e6 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -290,7 +290,7 @@ void PN532_ScanForTag(void) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - char command[15]; + char command[27]; sprintf(command,"event PN532=%s",uids); ExecuteCommand(command, SRC_RULE); pn532_i2c_scan_defer_report = 19; From 3608baf7f8d5ff04df6681a9859c788aaaf845f5 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Wed, 2 Jan 2019 23:17:38 +0200 Subject: [PATCH 0788/2222] Add support for PN532 NFC --- sonoff/xsns_40_pn532_i2c.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index 6ef9896e6..ec6b959ab 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -314,6 +314,7 @@ boolean Xsns40(byte function) if (pn532_i2c_detected) { PN532_ScanForTag(); } + break; case FUNC_EVERY_SECOND: PN532_Detect(); break; From 375441f23e07ce4391bff557dfa59774916e5754 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Thu, 3 Jan 2019 09:27:40 +0100 Subject: [PATCH 0789/2222] Support PN532 --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0aa205aef..6f68d76f4 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.4.1.4 20190101 * Update Copyright (C) 2019 * Fix epaper driver (#4785) + * Add support for Near Field Communication (NFC) controller PN532 using I2C (#4791) * * 6.4.1.3 20181229 * Change sonoff_template.h module lay-out by removing non-configurable GPIOs From 32c167d208b623b6e721112effe40ae804bd12e5 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Thu, 3 Jan 2019 11:09:49 +0200 Subject: [PATCH 0790/2222] PN532 - Housekeeping --- sonoff/support_features.ino | 4 +++- sonoff/xsns_40_pn532_i2c.ino | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 299f0aedd..21d67178b 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -376,7 +376,9 @@ void GetFeatures(void) #ifdef USE_MAX31855 feature_sns2 |= 0x00080000; // xsns_39_max31855.ino #endif -// feature_sns2 |= 0x00100000; +#ifdef USE_PN532_I2C + feature_sns2 |= 0x00100000; // xsns_40_pn532_i2c.ino +#endif // feature_sns2 |= 0x00200000; // feature_sns2 |= 0x00400000; // feature_sns2 |= 0x00800000; diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index ec6b959ab..656e7fff3 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -144,7 +144,7 @@ int16_t PN532_readResponse(uint8_t buf[], uint8_t len) } -int8_t PN532_readAckFrame() +int8_t PN532_readAckFrame(void) { const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; uint8_t ackBuf[sizeof(PN532_ACK)]; From cf5c82d22556bf2c4eb3af4c903d5bf2104d1f4b Mon Sep 17 00:00:00 2001 From: andrethomas Date: Thu, 3 Jan 2019 15:29:41 +0200 Subject: [PATCH 0791/2222] PN532 Store timeout in PROGMEM --- sonoff/xsns_40_pn532_i2c.ino | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index 656e7fff3..5ad0e4d03 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -54,12 +54,13 @@ uint8_t pn532_i2c_detected = 0; uint8_t pn532_i2c_packetbuffer[64]; uint8_t pn532_i2c_scan_defer_report = 0; // If a valid card was found we will not scan for one again in the same two seconds so we set this to 19 if a card was found +uint8_t pn532_i2c_command = 0; -uint8_t pn532_i2c_command; +const uint8_t PROGMEM pn532_global_timeout = 10; -int16_t PN532_getResponseLength(uint8_t buf[], uint8_t len, uint16_t timeout) { +int16_t PN532_getResponseLength(uint8_t buf[], uint8_t len) { const uint8_t PN532_NACK[] = {0, 0, 0xFF, 0xFF, 0, 0}; - uint16_t time = 0; + uint8_t time = 0; do { if (Wire.requestFrom(PN532_I2C_ADDRESS, 6)) { if (Wire.read() & 1) { // check first byte --- status @@ -68,7 +69,7 @@ int16_t PN532_getResponseLength(uint8_t buf[], uint8_t len, uint16_t timeout) { } delay(1); time++; - if ((0 != timeout) && (time > timeout)) { + if (time > pn532_global_timeout) { return -1; } } while (1); @@ -91,11 +92,10 @@ int16_t PN532_getResponseLength(uint8_t buf[], uint8_t len, uint16_t timeout) { int16_t PN532_readResponse(uint8_t buf[], uint8_t len) { - uint16_t time = 0; + uint8_t time = 0; uint8_t length; - uint8_t timeout = 10; - length = PN532_getResponseLength(buf, len, timeout); + length = PN532_getResponseLength(buf, len); // [RDY] 00 00 FF LEN LCS (TFI PD0 ... PDn) DCS 00 @@ -107,7 +107,7 @@ int16_t PN532_readResponse(uint8_t buf[], uint8_t len) } delay(1); time++; - if ((0 != timeout) && (time > timeout)) { + if (time > pn532_global_timeout) { return -1; } } while (1); @@ -149,7 +149,7 @@ int8_t PN532_readAckFrame(void) const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; uint8_t ackBuf[sizeof(PN532_ACK)]; - uint16_t time = 0; + uint8_t time = 0; do { if (Wire.requestFrom(PN532_I2C_ADDRESS, sizeof(PN532_ACK) + 1)) { From b584bb0760fb4a56c85f7efca868d3f005533988 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 3 Jan 2019 15:38:15 +0100 Subject: [PATCH 0792/2222] Housekeeping --- sonoff/sonoff_post.h | 1 + tools/decode-status.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index a265627fc..5defb494d 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -92,6 +92,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); //#define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) //#define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) //#define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) +//#define USE_PN532_I2C // Enable PN532 - Near Field Communication (NFC) controller (+1k6 code) #define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) #define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) #ifndef CO2_LOW diff --git a/tools/decode-status.py b/tools/decode-status.py index ddd94cb36..b45cb245a 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -136,7 +136,7 @@ a_features = [[ "USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711", "USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","USE_RF_SENSOR", "USE_THEO_V2","USE_ALECTO_V2","USE_AZ7798","USE_MAX31855", - "","","","", + "USE_PN532_I2C","","","", "","","","", "","","",""]] From edc245e5c6f69a067f125a09eeaebfcfb1f21acd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 3 Jan 2019 15:44:16 +0100 Subject: [PATCH 0793/2222] Housekeeping --- sonoff/xsns_15_mhz19.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 9c2839c18..d04d5a0c5 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -123,8 +123,8 @@ size_t MhzSendCmd(byte command_id) memcpy_P(&mhz_send[6], kMhzCommands[command_id] + sizeof(uint16_t), sizeof(uint16_t)); mhz_send[8] = MhzCalculateChecksum(mhz_send); - snprintf_P(log_data, sizeof(log_data), PSTR("Final MhzCommand: %x %x %x %x %x %x %x %x %x"),mhz_send[0],mhz_send[1],mhz_send[2],mhz_send[3],mhz_send[4],mhz_send[5],mhz_send[6],mhz_send[7],mhz_send[8]); - AddLog(LOG_LEVEL_DEBUG); +// snprintf_P(log_data, sizeof(log_data), PSTR("Final MhzCommand: %x %x %x %x %x %x %x %x %x"),mhz_send[0],mhz_send[1],mhz_send[2],mhz_send[3],mhz_send[4],mhz_send[5],mhz_send[6],mhz_send[7],mhz_send[8]); +// AddLog(LOG_LEVEL_DEBUG); return MhzSerial->write(mhz_send, sizeof(mhz_send)); } From 67cf1dbbcf33044dcbf631f0e4b8aa413b00c3a1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 3 Jan 2019 17:30:54 +0100 Subject: [PATCH 0794/2222] 6.4.1.5 Add mDns user control 6.4.1.5 20190103 * Remove command SetOption35 0-255 for mDNS start-up delay (#4793) * Add command SetOption55 0/1 to disable/enable mDNS (#4793) --- sonoff/_changelog.ino | 10 +++++++--- sonoff/settings.h | 2 +- sonoff/settings.ino | 4 ++++ sonoff/sonoff.ino | 15 ++++++++------- sonoff/sonoff_version.h | 2 +- sonoff/support_wifi.ino | 20 +++++++++++--------- 6 files changed, 32 insertions(+), 21 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 6f68d76f4..b5bb0e5a2 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,8 +1,12 @@ -/* 6.4.1.4 20190101 - * Update Copyright (C) 2019 +/* 6.4.1.5 20190103 + * Remove command SetOption35 0-255 for mDNS start-up delay (#4793) + * Add command SetOption55 0/1 to disable/enable mDNS (#4793) + * + * 6.4.1.4 20190101 + * Update Copyright (C) 2019 * Fix epaper driver (#4785) * Add support for Near Field Communication (NFC) controller PN532 using I2C (#4791) - * + * * 6.4.1.3 20181229 * Change sonoff_template.h module lay-out by removing non-configurable GPIOs * Add support for MAX31855 K-Type thermocouple sensor using softSPI (#4764) diff --git a/sonoff/settings.h b/sonoff/settings.h index 6397d2d13..66ab6645c 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -68,7 +68,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t time_append_timezone : 1; // bit 2 (v6.2.1.2) uint32_t gui_hostname_ip : 1; // bit 3 (v6.2.1.20) uint32_t tuya_apply_o20 : 1; // bit 4 (v6.3.0.4) - uint32_t spare5 : 1; + uint32_t mdns_enabled : 1; // bit 5 (v6.4.1.4) - SetOption55 uint32_t use_wifi_scan : 1; // bit 6 (v6.3.0.10) uint32_t use_wifi_rescan : 1; // bit 7 (v6.3.0.10) uint32_t receive_raw : 1; // bit 8 (v6.3.0.11) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 03d7ef08e..2624167c1 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -866,6 +866,10 @@ void SettingsDelta(void) Settings.sleep = 50; // Default to 50 for sleep, for now } } + if (Settings.version < 0x06040105) { + Settings.flag3.mdns_enabled = 0; + Settings.param[P_MDNS_DELAYED_START] = 0; + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c05c11626..a281ee97f 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -171,7 +171,7 @@ byte reset_web_log_flag = 0; // Reset web console log byte devices_present = 0; // Max number of devices supported byte seriallog_level; // Current copy of Settings.seriallog_level byte syslog_level; // Current copy of Settings.syslog_level -byte mdns_delayed_start = 0; // mDNS delayed start +//byte mdns_delayed_start = 0; // mDNS delayed start boolean latest_uptime_flag = true; // Signal latest uptime boolean pwm_present = false; // Any PWM channel configured with SetOption15 0 boolean mdns_begun = false; // mDNS active @@ -761,13 +761,14 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) else if (1 == ptype) { // SetOption50 .. 81 if (payload <= 1) { bitWrite(Settings.flag3.data, pindex, payload); - if (60 == ptype) { // SetOption60 enable or disable traditional sleep - if (payload == 0) { // Dynamic Sleep - WiFiSetSleepMode(); // Update WiFi sleep mode accordingly - } else { // Traditional Sleep //AT - WiFiSetSleepMode(); // Update WiFi sleep mode accordingly + if (5 == pindex) { // SetOption55 + if (0 == payload) { + restart_flag = 2; // Disable mDNS needs restart } } + if (10 == pindex) { // SetOption60 enable or disable traditional sleep + WiFiSetSleepMode(); // Update WiFi sleep mode accordingly + } } } else { // SetOption32 .. 49 @@ -2539,7 +2540,7 @@ void setup(void) } baudrate = Settings.baudrate * 1200; - mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; +// mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; seriallog_level = Settings.seriallog_level; seriallog_timer = SERIALLOG_TIMER; syslog_level = Settings.syslog_level; diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index af8d59cd7..242eb5fbd 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040104 +#define VERSION 0x06040105 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 6b6041764..817577900 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -485,15 +485,17 @@ void WifiCheck(uint8_t param) #endif // BE_MINIMAL #ifdef USE_DISCOVERY - if (!mdns_begun) { - if (mdns_delayed_start) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_ATTEMPTING_CONNECTION)); - mdns_delayed_start--; - } else { - mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; - mdns_begun = MDNS.begin(my_hostname); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS "%s"), (mdns_begun) ? D_INITIALIZED : D_FAILED); - AddLog(LOG_LEVEL_INFO); + if (Settings.flag3.mdns_enabled) { + if (!mdns_begun) { +// if (mdns_delayed_start) { +// AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_ATTEMPTING_CONNECTION)); +// mdns_delayed_start--; +// } else { +// mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; + mdns_begun = MDNS.begin(my_hostname); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MDNS "%s"), (mdns_begun) ? D_INITIALIZED : D_FAILED); + AddLog(LOG_LEVEL_INFO); +// } } } #endif // USE_DISCOVERY From f66de3111e88ac4900165773fe8883400c8b2ab4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 3 Jan 2019 18:07:03 +0100 Subject: [PATCH 0795/2222] Housekeeping --- sonoff/xdrv_01_webserver.ino | 13 ++++++++----- tools/decode-status.py | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index b81624bd7..d4d950b77 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1345,16 +1345,19 @@ void HandleInformation(void) #else func += F(D_DISABLED); #endif // USE_EMULATION - func += F("}1" D_MDNS_DISCOVERY "}2"); #ifdef USE_DISCOVERY - func += F(D_ENABLED); - func += F("}1" D_MDNS_ADVERTISE "}2"); + if (Settings.flag3.mdns_enabled) { + func += F(D_ENABLED); + func += F("}1" D_MDNS_ADVERTISE "}2"); #ifdef WEBSERVER_ADVERTISE - func += F(D_WEB_SERVER); + func += F(D_WEB_SERVER); #else - func += F(D_DISABLED); + func += F(D_DISABLED); #endif // WEBSERVER_ADVERTISE + } else { + func += F(D_DISABLED); + } #else func += F(D_DISABLED); #endif // USE_DISCOVERY diff --git a/tools/decode-status.py b/tools/decode-status.py index b45cb245a..63655f5a6 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -89,13 +89,13 @@ a_setoption = [[ "Add UTC time offset to JSON message", "Show hostname and IP address in GUI", "Apply SetOption20 to Tuya", - "Use short Hass discovery messages", + "mDNS enabled", "Use wifi network scan at restart", "Use wifi network rescan regularly", "Add IR raw data to JSON message", "Change state topic from tele/STATE to stat/RESULT", "Enable normal sleep instead of dynamic sleep", - "", + "Force local operation when button/switch topic is set", "","","","", "","","","", "","","","", From 2bf4b7c60e475cb8b0e91a1d1c9793f7e94dc0a9 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Fri, 4 Jan 2019 10:24:46 +0100 Subject: [PATCH 0796/2222] decode-config.py: adapt settings, fix warning - add SetOption55 (mdns_enabled) - fix string warning - change file handling --- tools/decode-config.py | 120 ++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 68 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 52cb63673..7816ff728 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,11 +1,11 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0015' +VER = '2.1.0016' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data - Copyright (C) 2019 Norbert Richter + Copyright (C) 2018 Norbert Richter 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 @@ -814,7 +814,13 @@ Setting_6_3_0_16['flag3'][0].update ({ Setting_6_4_0_2 = copy.deepcopy(Setting_6_3_0_16) Setting_6_4_0_2['flag3'][0].pop('hass_short_discovery_msg',None) # ====================================================================== +Setting_6_4_1_4 = copy.deepcopy(Setting_6_4_0_2) +Setting_6_4_1_4['flag3'][0].update ({ + 'mdns_enabled': (' Date: Fri, 4 Jan 2019 11:26:29 +0100 Subject: [PATCH 0797/2222] Update decode-config.py --- tools/decode-config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 7816ff728..7343adc17 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -5,7 +5,7 @@ VER = '2.1.0016' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data - Copyright (C) 2018 Norbert Richter + Copyright (C) 2019 Norbert Richter 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 From 44e80c262683706545c3157b0a373d8a78f89e95 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 4 Jan 2019 14:15:10 +0200 Subject: [PATCH 0798/2222] PN532 - Disable before restart --- sonoff/xsns_40_pn532_i2c.ino | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index 5ad0e4d03..42fb24e1e 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -55,6 +55,7 @@ uint8_t pn532_i2c_detected = 0; uint8_t pn532_i2c_packetbuffer[64]; uint8_t pn532_i2c_scan_defer_report = 0; // If a valid card was found we will not scan for one again in the same two seconds so we set this to 19 if a card was found uint8_t pn532_i2c_command = 0; +uint8_t pn532_i2c_disable = 0; const uint8_t PROGMEM pn532_global_timeout = 10; @@ -237,7 +238,7 @@ bool PN532_SAMConfig(void) void PN532_Detect(void) { - if (pn532_i2c_detected) { return; } + if ((pn532_i2c_detected) || (pn532_i2c_disable)) { return; } uint32_t ver = PN532_getFirmwareVersion(); if (ver) { @@ -276,6 +277,7 @@ boolean PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *u void PN532_ScanForTag(void) { + if (pn532_i2c_disable) { return; } uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; uint8_t uid_len = 0; if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) { @@ -318,6 +320,15 @@ boolean Xsns40(byte function) case FUNC_EVERY_SECOND: PN532_Detect(); break; + case FUNC_SAVE_BEFORE_RESTART: + if (!pn532_i2c_disable) { + pn532_i2c_disable = 1; + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "PN532 NFC Reader - Disabling for reboot", PN532_I2C_ADDRESS); + AddLog(LOG_LEVEL_DEBUG); + } + break; + default: + break; } } return result; From 458b0305985d9b47ce6e14aaf5a20e58516501c3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 4 Jan 2019 16:05:52 +0100 Subject: [PATCH 0799/2222] Add Eeprom support Add initial Eeprom support --- sonoff/settings.ino | 155 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 153 insertions(+), 2 deletions(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 2624167c1..055b35566 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -171,6 +171,139 @@ extern "C" uint32_t _SPIFFS_end; // Version 5.2 allow for more flash space #define CFG_ROTATES 8 // Number of flash sectors used (handles uploads) +/*********************************************************************************************\ + * EEPROM support based on EEPROM library and tuned for Tasmota +\*********************************************************************************************/ + +uint32_t eeprom_sector = SPIFFS_END; +uint8_t* eeprom_data = 0; +size_t eeprom_size = 0; +bool eeprom_dirty = false; + +void EepromBegin(size_t size) +{ + if (size <= 0) { return; } + if (size > SPI_FLASH_SEC_SIZE - sizeof(Settings) -4) { size = SPI_FLASH_SEC_SIZE - sizeof(Settings) -4; } + size = (size + 3) & (~3); + + // In case begin() is called a 2nd+ time, don't reallocate if size is the same + if (eeprom_data && size != eeprom_size) { + delete[] eeprom_data; + eeprom_data = new uint8_t[size]; + } else if (!eeprom_data) { + eeprom_data = new uint8_t[size]; + } + eeprom_size = size; + + size_t flash_offset = SPI_FLASH_SEC_SIZE - eeprom_size; + uint8_t* flash_buffer; + flash_buffer = new uint8_t[SPI_FLASH_SEC_SIZE]; + noInterrupts(); + spi_flash_read(eeprom_sector * SPI_FLASH_SEC_SIZE, reinterpret_cast(flash_buffer), SPI_FLASH_SEC_SIZE); + interrupts(); + memcpy(eeprom_data, flash_buffer + flash_offset, eeprom_size); + delete[] flash_buffer; + + eeprom_dirty = false; // make sure dirty is cleared in case begin() is called 2nd+ time +} + +size_t EepromLength(void) +{ + return eeprom_size; +} + +uint8_t EepromRead(int const address) +{ + if (address < 0 || (size_t)address >= eeprom_size) { return 0; } + if (!eeprom_data) { return 0; } + + return eeprom_data[address]; +} + +// Prototype needed for Arduino IDE - https://forum.arduino.cc/index.php?topic=406509.0 +template T EepromGet(int const address, T &t); +template T EepromGet(int const address, T &t) +{ + if (address < 0 || address + sizeof(T) > eeprom_size) { return t; } + if (!eeprom_data) { return 0; } + + memcpy((uint8_t*) &t, eeprom_data + address, sizeof(T)); + return t; +} + +void EepromWrite(int const address, uint8_t const value) +{ + if (address < 0 || (size_t)address >= eeprom_size) { return; } + if (!eeprom_data) { return; } + + // Optimise eeprom_dirty. Only flagged if data written is different. + uint8_t* pData = &eeprom_data[address]; + if (*pData != value) { + *pData = value; + eeprom_dirty = true; + } +} + +// Prototype needed for Arduino IDE - https://forum.arduino.cc/index.php?topic=406509.0 +template void EepromPut(int const address, const T &t); +template void EepromPut(int const address, const T &t) +{ + if (address < 0 || address + sizeof(T) > eeprom_size) { return; } + if (!eeprom_data) { return; } + + // Optimise eeprom_dirty. Only flagged if data written is different. + if (memcmp(eeprom_data + address, (const uint8_t*)&t, sizeof(T)) != 0) { + eeprom_dirty = true; + memcpy(eeprom_data + address, (const uint8_t*)&t, sizeof(T)); + } +} + +bool EepromCommit(void) +{ + bool ret = false; + if (!eeprom_size) { return false; } + if (!eeprom_dirty) { return true; } + if (!eeprom_data) { return false; } + + size_t flash_offset = SPI_FLASH_SEC_SIZE - eeprom_size; + uint8_t* flash_buffer; + flash_buffer = new uint8_t[SPI_FLASH_SEC_SIZE]; + noInterrupts(); + spi_flash_read(eeprom_sector * SPI_FLASH_SEC_SIZE, reinterpret_cast(flash_buffer), SPI_FLASH_SEC_SIZE); + memcpy(flash_buffer + flash_offset, eeprom_data, eeprom_size); + if (spi_flash_erase_sector(eeprom_sector) == SPI_FLASH_RESULT_OK) { + if (spi_flash_write(eeprom_sector * SPI_FLASH_SEC_SIZE, reinterpret_cast(flash_buffer), SPI_FLASH_SEC_SIZE) == SPI_FLASH_RESULT_OK) { + eeprom_dirty = false; + ret = true; + } + } + interrupts(); + delete[] flash_buffer; + + return ret; +} + +uint8_t * EepromGetDataPtr() +{ + eeprom_dirty = true; + return &eeprom_data[0]; +} + +void EepromEnd(void) +{ + if (!eeprom_size) { return; } + + EepromCommit(); + if (eeprom_data) { + delete[] eeprom_data; + } + eeprom_data = 0; + eeprom_size = 0; + eeprom_dirty = false; +} + +/********************************************************************************************/ + uint16_t settings_crc = 0; uint32_t settings_location = SETTINGS_LOCATION; uint8_t *settings_buffer = NULL; @@ -235,6 +368,7 @@ void SettingsSaveAll(void) Settings.power = 0; } XsnsCall(FUNC_SAVE_BEFORE_RESTART); + EepromCommit(); SettingsSave(0); } @@ -276,8 +410,25 @@ void SettingsSave(byte rotate) Settings.save_flag++; Settings.cfg_size = sizeof(SYSCFG); Settings.cfg_crc = GetSettingsCrc(); - ESP.flashEraseSector(settings_location); - ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + + if (SPIFFS_END == settings_location) { + uint8_t* flash_buffer; + flash_buffer = new uint8_t[SPI_FLASH_SEC_SIZE]; + if (eeprom_data && eeprom_size) { + size_t flash_offset = SPI_FLASH_SEC_SIZE - eeprom_size; + memcpy(flash_buffer + flash_offset, eeprom_data, eeprom_size); // Write dirty EEPROM data + } else { + ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)flash_buffer, SPI_FLASH_SEC_SIZE); // Read EEPROM area + } + memcpy(flash_buffer, &Settings, sizeof(Settings)); + ESP.flashEraseSector(settings_location); + ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)flash_buffer, SPI_FLASH_SEC_SIZE); + delete[] flash_buffer; + } else { + ESP.flashEraseSector(settings_location); + ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + } + if (!stop_flash_rotate && rotate) { for (byte i = 1; i < CFG_ROTATES; i++) { ESP.flashEraseSector(settings_location -i); // Delete previous configurations by resetting to 0xFF From c63ccd7cbda914b6e692e5d9ac2b4633a034fa7f Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 4 Jan 2019 21:20:38 +0200 Subject: [PATCH 0800/2222] PN532 - Timing tuning --- sonoff/xsns_40_pn532_i2c.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index 42fb24e1e..e41ba60ba 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -160,7 +160,7 @@ int8_t PN532_readAckFrame(void) } delay(1); time++; - if (time > 10) { // We time out after 10ms + if (time > pn532_global_timeout) { // We time out after 10ms return PN532_TIMEOUT; } } while (1); @@ -295,7 +295,7 @@ void PN532_ScanForTag(void) char command[27]; sprintf(command,"event PN532=%s",uids); ExecuteCommand(command, SRC_RULE); - pn532_i2c_scan_defer_report = 19; + pn532_i2c_scan_defer_report = 7; // Ignore tags found for two seconds } } else { if (pn532_i2c_scan_defer_report > 0) { pn532_i2c_scan_defer_report--; } @@ -312,7 +312,7 @@ boolean Xsns40(byte function) if (i2c_flg) { switch (function) { - case FUNC_EVERY_100_MSECOND: + case FUNC_EVERY_250_MSECOND: if (pn532_i2c_detected) { PN532_ScanForTag(); } From 1d23c0b0c5df2e696a86806868f833ed10f0b27b Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 4 Jan 2019 16:26:37 -0300 Subject: [PATCH 0801/2222] New Triggers for Rules: VARx#STATE and MEMx#STATE Added new triggers for rules: `VARx#STATE` and `MEMx#STATE` These new triggers allows to execute commands when VARs or MEMs change their values. This is useful for automations where the parameter sent to Tasmota by MQTT is a SetPoint for example. Before these triggers, the approach was using an `EVENT` to store a value but some components in home automation softwares can't use `cmnd/sonofftopic/EVENT SETVAR=25`, where `cmnd/sonofftopic/EVENT` is the mqtt message and `SETVAR=25` is the payload. With this new triggers, it will be as simple as `cmnd/sonofftopic/VAR 25` so any automation software can use it. _(Using `cmnd/sonofftopic/EVENT SETVAR=` as mqtt message and `25` as payload is not understood by Tasmota)_ --- sonoff/xdrv_10_rules.ino | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index d96ae6d61..df2db9748 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -95,6 +95,14 @@ uint8_t rules_teleperiod = 0; char event_data[100]; char vars[MAX_RULE_VARS][33] = { 0 }; +#if (MAX_RULE_VARS>8) +#error MAX_RULE_VARS is bigger than 8 +#endif +#if (MAX_RULE_MEMS>8) +#error MAX_RULE_MEMS is bigger than 8 +#endif +uint8_t vars_event = 0; +uint8_t mems_event = 0; /*******************************************************************************************/ @@ -445,6 +453,26 @@ void RulesEvery50ms(void) event_data[0] ='\0'; } } + else if (vars_event) { + for (byte i = 0; i < MAX_RULE_VARS-1; i++) { + if (bitRead(vars_event, i)) { + bitClear(vars_event, i); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Var%d\":{\"State\":%s}}"), i+1, vars[i]); + RulesProcessEvent(json_event); + break; + } + } + } + else if (mems_event) { + for (byte i = 0; i < MAX_RULE_MEMS-1; i++) { + if (bitRead(mems_event, i)) { + bitClear(mems_event, i); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Mem%d\":{\"State\":%s}}"), i+1, Settings.mems[i]); + RulesProcessEvent(json_event); + break; + } + } + } else if (rules_flag.data) { uint16_t mask = 1; for (byte i = 0; i < MAX_RULES_FLAG; i++) { @@ -600,12 +628,14 @@ boolean RulesCommand(void) else if ((CMND_VAR == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { strlcpy(vars[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(vars[index -1])); + bitSet(vars_event, index -1); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } else if ((CMND_MEM == command_code) && (index > 0) && (index <= MAX_RULE_MEMS)) { if (XdrvMailbox.data_len > 0) { strlcpy(Settings.mems[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[index -1])); + bitSet(mems_event, index -1); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]); } @@ -619,6 +649,7 @@ boolean RulesCommand(void) if (XdrvMailbox.data_len > 0) { double tempvar = CharToDouble(vars[index -1]) + CharToDouble(XdrvMailbox.data); dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]); + bitSet(vars_event, index -1); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } @@ -626,6 +657,7 @@ boolean RulesCommand(void) if (XdrvMailbox.data_len > 0) { double tempvar = CharToDouble(vars[index -1]) - CharToDouble(XdrvMailbox.data); dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]); + bitSet(vars_event, index -1); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } @@ -633,6 +665,7 @@ boolean RulesCommand(void) if (XdrvMailbox.data_len > 0) { double tempvar = CharToDouble(vars[index -1]) * CharToDouble(XdrvMailbox.data); dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]); + bitSet(vars_event, index -1); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } @@ -648,6 +681,7 @@ boolean RulesCommand(void) double toHigh = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 5)); double value = map_double(valueIN, fromLow, fromHigh, toLow, toHigh); dtostrfd(value, Settings.flag2.calc_resolution, vars[index -1]); + bitSet(vars_event, index -1); } } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); From 34966913e20f51199f94c2626b017f7e88ef5c75 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 4 Jan 2019 17:10:17 -0300 Subject: [PATCH 0802/2222] Add GPIO2 to Sonoff RF R2 template https://github.com/arendst/Sonoff-Tasmota/issues/4820 --- sonoff/sonoff_template.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 7b9740b7c..5ac7388d9 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -565,7 +565,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "Sonoff RF", // Sonoff RF (ESP8266) GPIO_KEY1, // GPIO00 Button GPIO_USER, // GPIO01 Serial RXD and Optional sensor - 0, + GPIO_USER, // GPIO02 Optional sensor GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor 0, From 41351001f5f9d29ff21ec97218a52f273ea5c6c4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 5 Jan 2019 15:39:56 +0100 Subject: [PATCH 0803/2222] 6.4.1.6 Re-introduce Cal commands 6.4.1.6 20190105 * Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors --- sonoff/_changelog.ino | 5 ++++- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_03_energy.ino | 32 +++++++++++++++++++++++++++----- sonoff/xnrg_01_hlw8012.ino | 5 ++++- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b5bb0e5a2..99a637454 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.5 20190103 +/* 6.4.1.6 20190105 + * Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors + * + * 6.4.1.5 20190103 * Remove command SetOption35 0-255 for mDNS start-up delay (#4793) * Add command SetOption55 0/1 to disable/enable mDNS (#4793) * diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 242eb5fbd..4d8bc85e1 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040105 +#define VERSION 0x06040106 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 50e4f3d69..773f50bc0 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -31,9 +31,14 @@ #include +#define D_CMND_POWERCAL "PowerCal" +#define D_CMND_VOLTAGECAL "VoltageCal" +#define D_CMND_CURRENTCAL "CurrentCal" + enum EnergyCommands { CMND_POWERDELTA, CMND_POWERLOW, CMND_POWERHIGH, CMND_VOLTAGELOW, CMND_VOLTAGEHIGH, CMND_CURRENTLOW, CMND_CURRENTHIGH, + CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL, CMND_POWERSET, CMND_VOLTAGESET, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_ENERGYRESET, CMND_MAXENERGY, CMND_MAXENERGYSTART, CMND_MAXPOWER, CMND_MAXPOWERHOLD, CMND_MAXPOWERWINDOW, @@ -41,6 +46,7 @@ enum EnergyCommands { const char kEnergyCommands[] PROGMEM = D_CMND_POWERDELTA "|" D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|" + D_CMND_POWERCAL "|" D_CMND_VOLTAGECAL "|" D_CMND_CURRENTCAL "|" D_CMND_POWERSET "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" D_CMND_ENERGYRESET "|" D_CMND_MAXENERGY "|" D_CMND_MAXENERGYSTART "|" D_CMND_MAXPOWER "|" D_CMND_MAXPOWERHOLD "|" D_CMND_MAXPOWERWINDOW "|" @@ -413,21 +419,36 @@ boolean EnergyCommand(void) command, energy_total_chr, energy_yesterday_chr, energy_daily_chr); status_flag = 1; } - else if ((CMND_POWERSET == command_code) && XnrgCall(FUNC_COMMAND)) { // Watt + else if ((CMND_POWERCAL == command_code) && XnrgCall(FUNC_COMMAND)) { // microseconds + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { Settings.energy_power_calibration = XdrvMailbox.payload; } nvalue = Settings.energy_power_calibration; unit = UNIT_MICROSECOND; } - else if ((CMND_VOLTAGESET == command_code) && XnrgCall(FUNC_COMMAND)) { // Volt + else if ((CMND_VOLTAGECAL == command_code) && XnrgCall(FUNC_COMMAND)) { // microseconds + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { Settings.energy_voltage_calibration = XdrvMailbox.payload; } nvalue = Settings.energy_voltage_calibration; unit = UNIT_MICROSECOND; } - else if ((CMND_CURRENTSET == command_code) && XnrgCall(FUNC_COMMAND)) { // milliAmpere + else if ((CMND_CURRENTCAL == command_code) && XnrgCall(FUNC_COMMAND)) { // microseconds + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { Settings.energy_current_calibration = XdrvMailbox.payload; } nvalue = Settings.energy_current_calibration; unit = UNIT_MICROSECOND; } + else if ((CMND_POWERSET == command_code) && XnrgCall(FUNC_COMMAND)) { // Watt + nvalue = Settings.energy_power_calibration; + unit = UNIT_MILLISECOND; + } + else if ((CMND_VOLTAGESET == command_code) && XnrgCall(FUNC_COMMAND)) { // Volt + nvalue = Settings.energy_voltage_calibration; + unit = UNIT_MILLISECOND; + } + else if ((CMND_CURRENTSET == command_code) && XnrgCall(FUNC_COMMAND)) { // milliAmpere + nvalue = Settings.energy_current_calibration; + unit = UNIT_MILLISECOND; + } else if ((CMND_FREQUENCYSET == command_code) && XnrgCall(FUNC_COMMAND)) { // Hz nvalue = Settings.energy_frequency_calibration; - unit = UNIT_MICROSECOND; + unit = UNIT_MILLISECOND; } #if FEATURE_POWER_LIMIT @@ -493,8 +514,9 @@ boolean EnergyCommand(void) if (serviced && !status_flag) { - if (UNIT_MICROSECOND == unit) { + if (UNIT_MILLISECOND == unit) { snprintf_P(command, sizeof(command), PSTR("%sCal"), command); + unit = UNIT_MICROSECOND; } if (Settings.flag.value_units) { diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index e336d805c..95560216a 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -237,7 +237,10 @@ boolean HlwCommand(void) { boolean serviced = true; - if (CMND_POWERSET == energy_command_code) { + if ((CMND_POWERCAL == energy_command_code) || (CMND_VOLTAGECAL == energy_command_code) || (CMND_CURRENTCAL == energy_command_code)) { + // Service in xdrv_03_energy.ino + } + else if (CMND_POWERSET == energy_command_code) { if (XdrvMailbox.data_len && hlw_cf_pulse_length) { Settings.energy_power_calibration = ((unsigned long)(CharToDouble(XdrvMailbox.data) * 10) * hlw_cf_pulse_length) / hlw_power_ratio; } From 9da900dfb8bc9d55427500cc919f1e102b8ecb4e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 5 Jan 2019 18:40:33 +0100 Subject: [PATCH 0804/2222] Stabilize current SHP6 --- sonoff/xnrg_01_hlw8012.ino | 72 +++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 95560216a..bf2ba5e68 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -38,6 +38,7 @@ #define HJL_IREF 3300 #define HLW_POWER_PROBE_TIME 10 // Number of seconds to probe for power before deciding none used +#define HLW_PROBE_COUNT 10 // Max number of probes per cycle byte hlw_select_ui_flag; byte hlw_ui_flag = 1; @@ -46,12 +47,17 @@ byte hlw_load_off; byte hlw_cf1_timer; unsigned long hlw_cf_pulse_length; unsigned long hlw_cf_pulse_last_time; +unsigned long hlw_cf_summed_pulse_length; +unsigned long hlw_cf_pulse_counter; +unsigned long hlw_cf_power_pulse_length; + 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_period_counter; unsigned long hlw_power_ratio = 0; @@ -61,6 +67,8 @@ unsigned long hlw_current_ratio = 0; unsigned long hlw_cf1_voltage_max_pulse_counter; unsigned long hlw_cf1_current_max_pulse_counter; +//unsigned long hlw_debug[HLW_PROBE_COUNT]; + #ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception void HlwCfInterrupt(void) ICACHE_RAM_ATTR; void HlwCf1Interrupt(void) ICACHE_RAM_ATTR; @@ -76,6 +84,10 @@ void HlwCfInterrupt(void) // Service Power } else { hlw_cf_pulse_length = us - hlw_cf_pulse_last_time; hlw_cf_pulse_last_time = us; + + hlw_cf_summed_pulse_length += hlw_cf_pulse_length; + hlw_cf_pulse_counter++; + hlw_energy_period_counter++; } } @@ -88,9 +100,12 @@ void HlwCf1Interrupt(void) // Service Voltage and Current 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_summed_pulse_length += hlw_cf1_pulse_length; + +// hlw_debug[hlw_cf1_pulse_counter] = 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) + if (HLW_PROBE_COUNT == hlw_cf1_pulse_counter) { + hlw_cf1_timer = 8; // We need up to HLW_PROBE_COUNT samples within 1 second (low current could take up to 0.3 second) } } } @@ -99,21 +114,25 @@ void HlwCf1Interrupt(void) // Service Voltage and Current void HlwEvery200ms(void) { + unsigned long cf1_pulse_length = 0; unsigned long hlw_w = 0; unsigned long hlw_u = 0; unsigned long hlw_i = 0; if (micros() - hlw_cf_pulse_last_time > (HLW_POWER_PROBE_TIME * 1000000)) { - hlw_cf_pulse_length = 0; // No load for some time + hlw_cf_pulse_counter = 0; // No load for some time hlw_load_off = 1; } - if (hlw_cf_pulse_length && energy_power_on && !hlw_load_off) { - hlw_w = (hlw_power_ratio * Settings.energy_power_calibration) / hlw_cf_pulse_length; + if (hlw_cf_pulse_counter && energy_power_on && !hlw_load_off) { + hlw_cf_power_pulse_length = hlw_cf_summed_pulse_length / hlw_cf_pulse_counter; + hlw_w = (hlw_power_ratio * Settings.energy_power_calibration) / hlw_cf_power_pulse_length; energy_active_power = (float)hlw_w / 10; } else { energy_active_power = 0; } + hlw_cf_summed_pulse_length = 0; + hlw_cf_pulse_counter = 0; hlw_cf1_timer++; if (hlw_cf1_timer >= 8) { @@ -122,12 +141,31 @@ void HlwEvery200ms(void) digitalWrite(pin[GPIO_NRG_SEL], hlw_select_ui_flag); if (hlw_cf1_pulse_counter) { - hlw_cf1_pulse_length = hlw_cf1_summed_pulse_length / hlw_cf1_pulse_counter; - } else { - hlw_cf1_pulse_length = 0; + cf1_pulse_length = hlw_cf1_summed_pulse_length / hlw_cf1_pulse_counter; } + +/* + // Debugging for calculating mean and median + char stemp[100]; + stemp[0] = '\0'; + for (uint8_t i = 0; i < hlw_cf1_pulse_counter; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, hlw_debug[i]); + } + for (uint8_t i = 0; i < hlw_cf1_pulse_counter; i++) { + for (uint8_t j = i + 1; j < hlw_cf1_pulse_counter; j++) { + if (hlw_debug[i] > hlw_debug[j]) { // Sort ascending + std::swap(hlw_debug[i], hlw_debug[j]); + } + } + } + unsigned long median = hlw_debug[(hlw_cf1_pulse_counter +1) / 2]; + snprintf_P(log_data, sizeof(log_data), PSTR("NRG: power %d, ui %d, count %d, samples%s, sum %d, mean %d, median %d"), + hlw_cf_power_pulse_length, hlw_select_ui_flag, hlw_cf1_pulse_counter, stemp, hlw_cf1_summed_pulse_length, cf1_pulse_length, median); + AddLog(LOG_LEVEL_DEBUG); +*/ + if (hlw_select_ui_flag == hlw_ui_flag) { - hlw_cf1_voltage_pulse_length = hlw_cf1_pulse_length; + hlw_cf1_voltage_pulse_length = cf1_pulse_length; hlw_cf1_voltage_max_pulse_counter = hlw_cf1_pulse_counter; if (hlw_cf1_voltage_pulse_length && energy_power_on) { // If powered on always provide voltage @@ -138,7 +176,7 @@ void HlwEvery200ms(void) } } else { - hlw_cf1_current_pulse_length = hlw_cf1_pulse_length; + hlw_cf1_current_pulse_length = cf1_pulse_length; hlw_cf1_current_max_pulse_counter = hlw_cf1_pulse_counter; if (hlw_cf1_current_pulse_length && energy_active_power) { // No current if no power being consumed @@ -186,8 +224,8 @@ void HlwSnsInit(void) hlw_current_ratio = HLW_IREF; } - hlw_cf_pulse_length = 0; hlw_cf_pulse_last_time = 0; + hlw_cf_power_pulse_length = 0; hlw_cf1_pulse_length = 0; hlw_cf1_pulse_last_time = 0; hlw_cf1_voltage_pulse_length = 0; @@ -213,18 +251,18 @@ void HlwSnsInit(void) void HlwDrvInit(void) { if (!energy_flg) { - hlw_model_type = 0; + hlw_model_type = 0; // HLW8012 if (pin[GPIO_HJL_CF] < 99) { pin[GPIO_HLW_CF] = pin[GPIO_HJL_CF]; pin[GPIO_HJL_CF] = 99; - hlw_model_type = 1; + hlw_model_type = 1; // HJL-01/BL0937 } - hlw_ui_flag = 1; + hlw_ui_flag = 1; // Voltage on high if (pin[GPIO_NRG_SEL_INV] < 99) { pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV]; pin[GPIO_NRG_SEL_INV] = 99; - hlw_ui_flag = 0; + hlw_ui_flag = 0; // Voltage on low } if ((pin[GPIO_NRG_SEL] < 99) && (pin[GPIO_NRG_CF1] < 99) && (pin[GPIO_HLW_CF] < 99)) { // HLW8012 or HJL-01 based device @@ -241,8 +279,8 @@ boolean HlwCommand(void) // Service in xdrv_03_energy.ino } else if (CMND_POWERSET == energy_command_code) { - if (XdrvMailbox.data_len && hlw_cf_pulse_length) { - Settings.energy_power_calibration = ((unsigned long)(CharToDouble(XdrvMailbox.data) * 10) * hlw_cf_pulse_length) / hlw_power_ratio; + if (XdrvMailbox.data_len && hlw_cf_power_pulse_length) { + Settings.energy_power_calibration = ((unsigned long)(CharToDouble(XdrvMailbox.data) * 10) * hlw_cf_power_pulse_length) / hlw_power_ratio; } } else if (CMND_VOLTAGESET == energy_command_code) { From 8d1dee8929c428045d9b50a56169280771b4d4af Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Sat, 5 Jan 2019 22:05:53 +0200 Subject: [PATCH 0805/2222] PN532: Enable 1ms ClockStretch Enable 1ms clock stretch as per datasheet Table 12.25 (Timing for the I2C interface) --- sonoff/xsns_40_pn532_i2c.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index e41ba60ba..3c246a7d1 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -239,6 +239,8 @@ bool PN532_SAMConfig(void) void PN532_Detect(void) { if ((pn532_i2c_detected) || (pn532_i2c_disable)) { return; } + + Wire.setClockStretchLimit(1000); // Enable 1ms clock stretch as per datasheet Table 12.25 (Timing for the I2C interface) uint32_t ver = PN532_getFirmwareVersion(); if (ver) { From cb8963a7bff8463f061e6435bd07a2d1409f8cd0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 6 Jan 2019 12:29:38 +0100 Subject: [PATCH 0806/2222] 6.4.1.7 Fix regression energy sensors 6.4.1.7 20190106 * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6 --- sonoff/_changelog.ino | 5 ++++- sonoff/sonoff_version.h | 2 +- sonoff/xnrg_01_hlw8012.ino | 16 +++++----------- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 99a637454..7da32cbe1 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.6 20190105 +/* 6.4.1.7 20190106 + * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6 + * + * 6.4.1.6 20190105 * Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors * * 6.4.1.5 20190103 diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 4d8bc85e1..56193708d 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040106 +#define VERSION 0x06040107 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index bf2ba5e68..305b1cab8 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -47,8 +47,6 @@ byte hlw_load_off; byte hlw_cf1_timer; unsigned long hlw_cf_pulse_length; unsigned long hlw_cf_pulse_last_time; -unsigned long hlw_cf_summed_pulse_length; -unsigned long hlw_cf_pulse_counter; unsigned long hlw_cf_power_pulse_length; unsigned long hlw_cf1_pulse_length; @@ -84,10 +82,6 @@ void HlwCfInterrupt(void) // Service Power } else { hlw_cf_pulse_length = us - hlw_cf_pulse_last_time; hlw_cf_pulse_last_time = us; - - hlw_cf_summed_pulse_length += hlw_cf_pulse_length; - hlw_cf_pulse_counter++; - hlw_energy_period_counter++; } } @@ -119,20 +113,19 @@ void HlwEvery200ms(void) unsigned long hlw_u = 0; unsigned long hlw_i = 0; + if (micros() - hlw_cf_pulse_last_time > (HLW_POWER_PROBE_TIME * 1000000)) { - hlw_cf_pulse_counter = 0; // No load for some time + hlw_cf_pulse_length = 0; // No load for some time hlw_load_off = 1; } + hlw_cf_power_pulse_length = hlw_cf_pulse_length; - if (hlw_cf_pulse_counter && energy_power_on && !hlw_load_off) { - hlw_cf_power_pulse_length = hlw_cf_summed_pulse_length / hlw_cf_pulse_counter; + if (hlw_cf_power_pulse_length && energy_power_on && !hlw_load_off) { hlw_w = (hlw_power_ratio * Settings.energy_power_calibration) / hlw_cf_power_pulse_length; energy_active_power = (float)hlw_w / 10; } else { energy_active_power = 0; } - hlw_cf_summed_pulse_length = 0; - hlw_cf_pulse_counter = 0; hlw_cf1_timer++; if (hlw_cf1_timer >= 8) { @@ -224,6 +217,7 @@ void HlwSnsInit(void) hlw_current_ratio = HLW_IREF; } + hlw_cf_pulse_length = 0; hlw_cf_pulse_last_time = 0; hlw_cf_power_pulse_length = 0; hlw_cf1_pulse_length = 0; From e9c687cf099cab6a7105e7781d45e5206a5a4bc4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 6 Jan 2019 15:17:22 +0100 Subject: [PATCH 0807/2222] Housekeeping - Documentation --- sonoff/xnrg_01_hlw8012.ino | 113 +++++++++++++++---------------------- 1 file changed, 47 insertions(+), 66 deletions(-) diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 305b1cab8..ddfb847b9 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -37,35 +37,36 @@ #define HJL_UREF 822 #define HJL_IREF 3300 -#define HLW_POWER_PROBE_TIME 10 // Number of seconds to probe for power before deciding none used -#define HLW_PROBE_COUNT 10 // Max number of probes per cycle +#define HLW_POWER_PROBE_TIME 10 // Number of seconds to probe for power before deciding none used (low power pulse can take up to 10 seconds) +#define HLW_SAMPLE_COUNT 10 // Max number of samples per cycle -byte hlw_select_ui_flag; -byte hlw_ui_flag = 1; -byte hlw_model_type = 0; -byte hlw_load_off; -byte hlw_cf1_timer; -unsigned long hlw_cf_pulse_length; -unsigned long hlw_cf_pulse_last_time; -unsigned long hlw_cf_power_pulse_length; +//#define HLW_DEBUG +#ifdef HLW_DEBUG +unsigned long hlw_debug[HLW_SAMPLE_COUNT]; +#endif -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_cf_pulse_length = 0; +unsigned long hlw_cf_pulse_last_time = 0; +unsigned long hlw_cf_power_pulse_length = 0; -unsigned long hlw_energy_period_counter; +unsigned long hlw_cf1_pulse_length = 0; +unsigned long hlw_cf1_pulse_last_time = 0; +unsigned long hlw_cf1_summed_pulse_length = 0; +unsigned long hlw_cf1_pulse_counter = 0; +unsigned long hlw_cf1_voltage_pulse_length = 0; +unsigned long hlw_cf1_current_pulse_length = 0; + +unsigned long hlw_energy_period_counter = 0; unsigned long hlw_power_ratio = 0; unsigned long hlw_voltage_ratio = 0; unsigned long hlw_current_ratio = 0; -unsigned long hlw_cf1_voltage_max_pulse_counter; -unsigned long hlw_cf1_current_max_pulse_counter; - -//unsigned long hlw_debug[HLW_PROBE_COUNT]; +byte hlw_select_ui_flag = 0; +byte hlw_ui_flag = 1; +byte hlw_model_type = 0; +byte hlw_load_off = 1; +byte hlw_cf1_timer = 0; #ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception void HlwCfInterrupt(void) ICACHE_RAM_ATTR; @@ -94,12 +95,12 @@ void HlwCf1Interrupt(void) // Service Voltage and Current 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_summed_pulse_length += hlw_cf1_pulse_length; - -// hlw_debug[hlw_cf1_pulse_counter] = hlw_cf1_pulse_length; - +#ifdef HLW_DEBUG + hlw_debug[hlw_cf1_pulse_counter] = hlw_cf1_pulse_length; +#endif hlw_cf1_pulse_counter++; - if (HLW_PROBE_COUNT == hlw_cf1_pulse_counter) { - hlw_cf1_timer = 8; // We need up to HLW_PROBE_COUNT samples within 1 second (low current could take up to 0.3 second) + if (HLW_SAMPLE_COUNT == hlw_cf1_pulse_counter) { + hlw_cf1_timer = 8; // We need up to HLW_SAMPLE_COUNT samples within 1 second (low current could take up to 0.3 second) } } } @@ -113,7 +114,6 @@ void HlwEvery200ms(void) unsigned long hlw_u = 0; unsigned long hlw_i = 0; - 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; @@ -121,7 +121,7 @@ void HlwEvery200ms(void) hlw_cf_power_pulse_length = hlw_cf_pulse_length; if (hlw_cf_power_pulse_length && energy_power_on && !hlw_load_off) { - hlw_w = (hlw_power_ratio * Settings.energy_power_calibration) / hlw_cf_power_pulse_length; + hlw_w = (hlw_power_ratio * Settings.energy_power_calibration) / hlw_cf_power_pulse_length; // W *10 energy_active_power = (float)hlw_w / 10; } else { energy_active_power = 0; @@ -137,32 +137,31 @@ void HlwEvery200ms(void) cf1_pulse_length = hlw_cf1_summed_pulse_length / hlw_cf1_pulse_counter; } -/* - // Debugging for calculating mean and median - char stemp[100]; - stemp[0] = '\0'; - for (uint8_t i = 0; i < hlw_cf1_pulse_counter; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, hlw_debug[i]); - } - for (uint8_t i = 0; i < hlw_cf1_pulse_counter; i++) { - for (uint8_t j = i + 1; j < hlw_cf1_pulse_counter; j++) { - if (hlw_debug[i] > hlw_debug[j]) { // Sort ascending - std::swap(hlw_debug[i], hlw_debug[j]); +#ifdef HLW_DEBUG + // Debugging for calculating mean and median + char stemp[100]; + stemp[0] = '\0'; + for (uint8_t i = 0; i < hlw_cf1_pulse_counter; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, hlw_debug[i]); + } + for (uint8_t i = 0; i < hlw_cf1_pulse_counter; i++) { + for (uint8_t j = i + 1; j < hlw_cf1_pulse_counter; j++) { + if (hlw_debug[i] > hlw_debug[j]) { // Sort ascending + std::swap(hlw_debug[i], hlw_debug[j]); + } } } - } - unsigned long median = hlw_debug[(hlw_cf1_pulse_counter +1) / 2]; - snprintf_P(log_data, sizeof(log_data), PSTR("NRG: power %d, ui %d, count %d, samples%s, sum %d, mean %d, median %d"), - hlw_cf_power_pulse_length, hlw_select_ui_flag, hlw_cf1_pulse_counter, stemp, hlw_cf1_summed_pulse_length, cf1_pulse_length, median); - AddLog(LOG_LEVEL_DEBUG); -*/ + unsigned long median = hlw_debug[(hlw_cf1_pulse_counter +1) / 2]; + snprintf_P(log_data, sizeof(log_data), PSTR("NRG: power %d, ui %d, cnt %d, smpl%s, sum %d, mean %d, median %d"), + hlw_cf_power_pulse_length, hlw_select_ui_flag, hlw_cf1_pulse_counter, stemp, hlw_cf1_summed_pulse_length, cf1_pulse_length, median); + AddLog(LOG_LEVEL_DEBUG); +#endif if (hlw_select_ui_flag == hlw_ui_flag) { hlw_cf1_voltage_pulse_length = cf1_pulse_length; - hlw_cf1_voltage_max_pulse_counter = hlw_cf1_pulse_counter; if (hlw_cf1_voltage_pulse_length && energy_power_on) { // If powered on always provide voltage - hlw_u = (hlw_voltage_ratio * Settings.energy_voltage_calibration) / hlw_cf1_voltage_pulse_length; + hlw_u = (hlw_voltage_ratio * Settings.energy_voltage_calibration) / hlw_cf1_voltage_pulse_length; // V *10 energy_voltage = (float)hlw_u / 10; } else { energy_voltage = 0; @@ -170,10 +169,9 @@ void HlwEvery200ms(void) } else { hlw_cf1_current_pulse_length = cf1_pulse_length; - hlw_cf1_current_max_pulse_counter = hlw_cf1_pulse_counter; if (hlw_cf1_current_pulse_length && energy_active_power) { // No current if no power being consumed - hlw_i = (hlw_current_ratio * Settings.energy_current_calibration) / hlw_cf1_current_pulse_length; + hlw_i = (hlw_current_ratio * Settings.energy_current_calibration) / hlw_cf1_current_pulse_length; // mA energy_current = (float)hlw_i / 1000; } else { energy_current = 0; @@ -217,29 +215,12 @@ void HlwSnsInit(void) hlw_current_ratio = HLW_IREF; } - hlw_cf_pulse_length = 0; - hlw_cf_pulse_last_time = 0; - hlw_cf_power_pulse_length = 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_energy_period_counter = 0; - - hlw_select_ui_flag = 0; // Voltage; - pinMode(pin[GPIO_NRG_SEL], OUTPUT); digitalWrite(pin[GPIO_NRG_SEL], hlw_select_ui_flag); pinMode(pin[GPIO_NRG_CF1], INPUT_PULLUP); attachInterrupt(pin[GPIO_NRG_CF1], HlwCf1Interrupt, FALLING); pinMode(pin[GPIO_HLW_CF], INPUT_PULLUP); attachInterrupt(pin[GPIO_HLW_CF], HlwCfInterrupt, FALLING); - - hlw_cf1_timer = 0; } void HlwDrvInit(void) From 64ba6fcf8d916c254b9a16b73791b8fed17bf706 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Sun, 6 Jan 2019 16:32:50 +0200 Subject: [PATCH 0808/2222] PN532: Fix hex formatting to 2 char len per byte PN532: Fix hex formatting to 2 char len per byte --- sonoff/xsns_40_pn532_i2c.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index 3c246a7d1..787f48faa 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -289,7 +289,7 @@ void PN532_ScanForTag(void) char uids[15]; sprintf(uids,""); for (uint8_t i = 0;i < uid_len;i++) { - sprintf(uids,"%s%X",uids,uid[i]); + sprintf(uids,"%s%02X",uids,uid[i]); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids); From 0195cabbd6157279e0bde0c876a89807161afc8f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 6 Jan 2019 18:02:21 +0100 Subject: [PATCH 0809/2222] Add relay status functionality to LED2 Add relay status functionality to LED2 when configured leaving LED1 for (wifi/mqtt) status indication --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 18 ++++++++++++++++-- sonoff/sonoff_template.h | 14 +++++++------- sonoff/xdrv_04_light.ino | 12 ++++++------ 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 7da32cbe1..6076bcff0 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.4.1.7 20190106 * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6 + * Add relay status functionality to LED2 when configured leaving LED1 for (wifi/mqtt) status indication * * 6.4.1.6 20190105 * Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index a281ee97f..0974c47e7 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -370,6 +370,15 @@ void SetDevicePower(power_t rpower, int source) } void SetLedPower(uint8_t state) +{ + if (state) state = 1; + + uint8_t led_pin = 0; + if (pin[GPIO_LED2] < 99) { led_pin = 1; } + digitalWrite(pin[GPIO_LED1 + led_pin], (bitRead(led_inverted, led_pin)) ? !state : state); +} + +void SetLedWifi(uint8_t state) { if (state) state = 1; digitalWrite(pin[GPIO_LED1], (bitRead(led_inverted, 0)) ? !state : state); @@ -1276,7 +1285,10 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) else if (CMND_LEDSTATE == command_code) { if ((payload >= 0) && (payload < MAX_LED_OPTION)) { Settings.ledstate = payload; - if (!Settings.ledstate) SetLedPower(0); + if (!Settings.ledstate) { + SetLedPower(0); + SetLedWifi(0); + } } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.ledstate); } @@ -1966,7 +1978,8 @@ void Every250mSeconds(void) } if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) { // if ( (!Settings.flag.global_state && global_state.data) || ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) ) { - SetLedPower(blinkstate); // Set led on or off +// SetLedPower(blinkstate); // Set led on or off + SetLedWifi(blinkstate); // Set led on or off } if (!blinkstate) { blinks--; @@ -2501,6 +2514,7 @@ void GpioInit(void) } SetLedPower(Settings.ledstate &8); + SetLedWifi(Settings.ledstate &8); XdrvCall(FUNC_PRE_INIT); } diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 5ac7388d9..943e7548e 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -473,7 +473,7 @@ const uint8_t kGpioNiceList[] PROGMEM = { #ifdef USE_MAX31855 GPIO_MAX31855CS, // MAX31855 Serial interface GPIO_MAX31855CLK, // MAX31855 Serial interface - GPIO_MAX31855DO, // MAX31855 Serial interface + GPIO_MAX31855DO, // MAX31855 Serial interface #endif }; @@ -565,7 +565,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "Sonoff RF", // Sonoff RF (ESP8266) GPIO_KEY1, // GPIO00 Button GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_USER, // GPIO02 Optional sensor + GPIO_USER, // GPIO02 Optional sensor GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_USER, // GPIO04 Optional sensor 0, @@ -1140,7 +1140,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_PWM3, // GPIO12 RGB LED Blue GPIO_USER, // GPIO13 RGBW LED White (optional - set to PWM4 for Cold White or Warm White as used on Arilux LC10) GPIO_PWM1, // GPIO14 RGB LED Red - GPIO_LED2_INV, // GPIO15 RF receiver control (Arilux LC10) + GPIO_LED4_INV, // GPIO15 RF receiver control (Arilux LC10) 0, 0 }, { "Luani HVIO", // ESP8266_HVIO @@ -1186,7 +1186,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { // (PwmFrequency 1111Hz) GPIO_KEY1, // GPIO00 Optional Button GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_LED2_INV, // GPIO02 RF receiver control + GPIO_LED4_INV, // GPIO02 RF receiver control GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional) GPIO_PWM1, // GPIO05 RGB LED Red @@ -1206,7 +1206,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { // (PwmFrequency 540Hz) GPIO_KEY1, // GPIO00 Optional Button GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_LED2_INV, // GPIO02 RF receiver control + GPIO_LED4_INV, // GPIO02 RF receiver control GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_PWM2, // GPIO04 RGB LED Green GPIO_PWM1, // GPIO05 RGB LED Red @@ -1444,7 +1444,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) // GPIO11 (SD_CMD Flash) - GPIO_LED2, // GPIO12 (Relay ON, but set to LOW, so we can switch with GPIO05) + GPIO_LED3, // GPIO12 (Relay ON, but set to LOW, so we can switch with GPIO05) GPIO_USER, // GPIO13 GPIO_KEY1, // GPIO14 Button 0, @@ -1670,7 +1670,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_PWM3, // GPIO12 RGB LED Blue GPIO_PWM4, // GPIO13 RGBW LED White GPIO_PWM1, // GPIO14 RGB LED Red - GPIO_LED2_INV, // GPIO15 RF receiver control + GPIO_LED4_INV, // GPIO15 RF receiver control 0, 0 } diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index cbead5e4c..9265e4f67 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -247,23 +247,23 @@ void AriluxRfHandler(void) void AriluxRfInit(void) { - if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_LED2] < 99)) { + if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_LED4] < 99)) { if (Settings.last_module != Settings.module) { Settings.rf_code[1][6] = 0; Settings.rf_code[1][7] = 0; Settings.last_module = Settings.module; } arilux_rf_received_value = 0; - digitalWrite(pin[GPIO_LED2], !bitRead(led_inverted, 1)); // Turn on RF + digitalWrite(pin[GPIO_LED4], !bitRead(led_inverted, 3)); // Turn on RF attachInterrupt(pin[GPIO_ARIRFRCV], AriluxRfInterrupt, CHANGE); } } void AriluxRfDisable(void) { - if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_LED2] < 99)) { + if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_LED4] < 99)) { detachInterrupt(pin[GPIO_ARIRFRCV]); - digitalWrite(pin[GPIO_LED2], bitRead(led_inverted, 1)); // Turn off RF + digitalWrite(pin[GPIO_LED4], bitRead(led_inverted, 3)); // Turn off RF } } #endif // USE_ARILUX_RF @@ -387,8 +387,8 @@ void LightInit(void) } } if (pin[GPIO_ARIRFRCV] < 99) { - if (pin[GPIO_LED2] < 99) { - digitalWrite(pin[GPIO_LED2], bitRead(led_inverted, 1)); // Turn off RF + if (pin[GPIO_LED4] < 99) { + digitalWrite(pin[GPIO_LED4], bitRead(led_inverted, 3)); // Turn off RF } } } From e1d903eab39bedaf9b76cccca8eda9e8946c1ddc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 6 Jan 2019 18:50:56 +0100 Subject: [PATCH 0810/2222] Add no pull-up control to Shelly 2 Add no pull-up control to Shelly 2 module (default is pull-up, change GPIO2 to Switch3n for no pull-up) (#4841) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 3 ++- sonoff/sonoff_template.h | 4 ++-- sonoff/support_switch.ino | 4 ++++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 6076bcff0..269408383 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.4.1.7 20190106 * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6 * Add relay status functionality to LED2 when configured leaving LED1 for (wifi/mqtt) status indication + * Add no pull-up control to Shelly 2 module (default is pull-up, change GPIO2 to Switch3n for no pull-up) (#4841) * * 6.4.1.6 20190105 * Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 0974c47e7..16205b458 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1775,7 +1775,8 @@ void ButtonHandler(void) } } else { if (pin[GPIO_KEY1 +button_index] < 99) { - if (!((uptime < 4) && (0 == pin[GPIO_KEY1 +button_index]))) { // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit +// if (!((uptime < 4) && (0 == pin[GPIO_KEY1 +button_index]))) { // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit + if (uptime > 3) { // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit button_present = 1; button = digitalRead(pin[GPIO_KEY1 +button_index]); } diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 943e7548e..b5e47d745 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1367,7 +1367,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "Shelly 2", // Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ 0, GPIO_TXD, // GPIO01 MCP39F501 Serial input - 0, + GPIO_USER, // GPIO02 Decide if we use (no) pull-up GPIO_RXD, // GPIO03 MCP39F501 Serial output GPIO_REL1, // GPIO04 GPIO_REL2, // GPIO05 @@ -1378,7 +1378,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) // GPIO11 (SD_CMD Flash) GPIO_SWT1, // GPIO12 - 0, + 0, // GPIO13 GPIO_SWT2, // GPIO14 0, // GPIO15 MCP39F501 Reset 0, 0 diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino index 444ba9475..cc32eb0bb 100644 --- a/sonoff/support_switch.ino +++ b/sonoff/support_switch.ino @@ -110,6 +110,10 @@ void SwitchProbe(void) void SwitchInit(void) { + if (SHELLY2 == Settings.module) { + if (switch_no_pullup > 0) { switch_no_pullup = 0xffff; } // If any switch is no pull-up make them all no pull-up + } + switches_found = 0; for (byte i = 0; i < MAX_SWITCHES; i++) { lastwallswitch[i] = 1; // Init global to virtual switch state; From d3020223d74edcc7c393cee1f031a2a5930f8843 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 6 Jan 2019 18:57:51 +0100 Subject: [PATCH 0811/2222] Update _changelog.ino --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 269408383..fc023ec1c 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6 * Add relay status functionality to LED2 when configured leaving LED1 for (wifi/mqtt) status indication * Add no pull-up control to Shelly 2 module (default is pull-up, change GPIO2 to Switch3n for no pull-up) (#4841) + * Add 4 seconds startup delay to button control (#4829) * * 6.4.1.6 20190105 * Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors From 122ae1ee27275588ba5912f8d8d882df2b986347 Mon Sep 17 00:00:00 2001 From: engrbm87 Date: Sun, 6 Jan 2019 20:26:42 +0200 Subject: [PATCH 0812/2222] fix empty prefix issue When switchtopic is set to a different topic the prefix will be empty so its length will be zero. In the Shorten function the strncmp will give a zero result because the prefixlen is zero and will add '~' even though there is no prefix. Adding prefixlen != 0 in the if condition fixes the issue. Also skip adding the prefix "~" on line 292 by checking if the prefix length is greater than zero. --- sonoff/xdrv_12_home_assistant.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 26609d1d7..59a7b519e 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -147,7 +147,7 @@ static void Shorten(char** s, char *prefix) { size_t len = strlen(*s); size_t prefixlen = strlen(prefix); - if (len > prefixlen && !strncmp(*s, prefix, prefixlen)) { + if (len > prefixlen && prefixlen != 0 && !strncmp(*s, prefix, prefixlen)) { *s += prefixlen-1; *s[0] = '~'; } @@ -289,7 +289,7 @@ void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data, unique_id, ESP.getChipId(), Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image, "Tasmota"); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + if (strlen(prefix) > 0 ) snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } MqttPublish(stopic, true); From 3d31dd1457ce18d463456eeb346ba888ef109e47 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 7 Jan 2019 10:15:00 +0100 Subject: [PATCH 0813/2222] Disable Button/Switch 4 seconds Disable both Buttons and Switches 4 seconds after power on to workaround Wemos and Obi startup issues. --- sonoff/sonoff.ino | 9 ++++---- sonoff/support_switch.ino | 44 +++++++++++++++++++-------------------- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 16205b458..af7a0c6e6 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1750,6 +1750,8 @@ void PerformEverySecond(void) void ButtonHandler(void) { + if (uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit + uint8_t button = NOT_PRESSED; uint8_t button_present = 0; uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; // Extent hold time factor in case of iminnent Reset command @@ -1775,11 +1777,8 @@ void ButtonHandler(void) } } else { if (pin[GPIO_KEY1 +button_index] < 99) { -// if (!((uptime < 4) && (0 == pin[GPIO_KEY1 +button_index]))) { // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit - if (uptime > 3) { // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit - button_present = 1; - button = digitalRead(pin[GPIO_KEY1 +button_index]); - } + button_present = 1; + button = digitalRead(pin[GPIO_KEY1 +button_index]); } } diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino index cc32eb0bb..5f3685a7a 100644 --- a/sonoff/support_switch.ino +++ b/sonoff/support_switch.ino @@ -65,41 +65,41 @@ uint8_t SwitchGetVirtual(uint8_t index) void SwitchProbe(void) { + if (uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit + uint8_t state_filter = Settings.switch_debounce / SWITCH_PROBE_INTERVAL; // 5, 10, 15 uint8_t force_high = (Settings.switch_debounce % 50) &1; // 51, 101, 151 etc uint8_t force_low = (Settings.switch_debounce % 50) &2; // 52, 102, 152 etc for (byte i = 0; i < MAX_SWITCHES; i++) { if (pin[GPIO_SWT1 +i] < 99) { - if (!((uptime < 4) && (0 == pin[GPIO_SWT1 +i]))) { // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit - // Olimex user_switch2.c code to fix 50Hz induced pulses - if (1 == digitalRead(pin[GPIO_SWT1 +i])) { + // Olimex user_switch2.c code to fix 50Hz induced pulses + if (1 == digitalRead(pin[GPIO_SWT1 +i])) { - if (force_high) { // Enabled with SwitchDebounce x1 - if (1 == switch_virtual[i]) { - switch_state_buf[i] = state_filter; // With noisy input keep current state 1 unless constant 0 - } + if (force_high) { // Enabled with SwitchDebounce x1 + if (1 == switch_virtual[i]) { + switch_state_buf[i] = state_filter; // With noisy input keep current state 1 unless constant 0 } + } - if (switch_state_buf[i] < state_filter) { - switch_state_buf[i]++; - if (state_filter == switch_state_buf[i]) { - switch_virtual[i] = 1; - } + if (switch_state_buf[i] < state_filter) { + switch_state_buf[i]++; + if (state_filter == switch_state_buf[i]) { + switch_virtual[i] = 1; } - } else { + } + } else { - if (force_low) { // Enabled with SwitchDebounce x2 - if (0 == switch_virtual[i]) { - switch_state_buf[i] = 0; // With noisy input keep current state 0 unless constant 1 - } + if (force_low) { // Enabled with SwitchDebounce x2 + if (0 == switch_virtual[i]) { + switch_state_buf[i] = 0; // With noisy input keep current state 0 unless constant 1 } + } - if (switch_state_buf[i] > 0) { - switch_state_buf[i]--; - if (0 == switch_state_buf[i]) { - switch_virtual[i] = 0; - } + if (switch_state_buf[i] > 0) { + switch_state_buf[i]--; + if (0 == switch_state_buf[i]) { + switch_virtual[i] = 0; } } } From 95f39be2ef66c611560f9268beb20da9b3aeb1b7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 7 Jan 2019 12:38:47 +0100 Subject: [PATCH 0814/2222] Change button driver making it modular Change button driver making it modular --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 187 +----------------------------- sonoff/support_button.ino | 236 ++++++++++++++++++++++++++++++++++++++ sonoff/support_switch.ino | 3 +- 4 files changed, 243 insertions(+), 184 deletions(-) create mode 100644 sonoff/support_button.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index fc023ec1c..3d802f705 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Add relay status functionality to LED2 when configured leaving LED1 for (wifi/mqtt) status indication * Add no pull-up control to Shelly 2 module (default is pull-up, change GPIO2 to Switch3n for no pull-up) (#4841) * Add 4 seconds startup delay to button control (#4829) + * Change button driver making it modular * * 6.4.1.6 20190105 * Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index af7a0c6e6..c2ede5d03 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -108,7 +108,6 @@ unsigned long state_250msecond = 0; // State 250msecond timer unsigned long pulse_timer[MAX_PULSETIMERS] = { 0 }; // Power off timer unsigned long blink_timer = 0; // Power cycle timer unsigned long backlog_delay = 0; // Command backlog delay -unsigned long button_debounce = 0; // Button debounce timer power_t power = 0; // Current copy of Settings.power power_t blink_power; // Blink power state power_t blink_mask = 0; // Blink relay active mask @@ -129,12 +128,10 @@ uint32_t global_update = 0; // Timestamp of last global temperat float global_temperature = 0; // Provide a global temperature to be used by some sensors float global_humidity = 0; // Provide a global humidity to be used by some sensors char *ota_url; // OTA url string pointer -uint16_t dual_button_code = 0; // Sonoff dual received code uint16_t mqtt_cmnd_publish = 0; // ignore flag for publish command uint16_t blink_counter = 0; // Number of blink cycles uint16_t seriallog_timer = 0; // Timer to disable Seriallog uint16_t syslog_timer = 0; // Timer to re-enable syslog_level -uint16_t holdbutton[MAX_KEYS] = { 0 }; // Timer for button hold int16_t save_data_counter; // Counter and flag for config save to Flash RulesBitfield rules_flag; // Rule state flags (16 bits) uint8_t serial_local = 0; // Handle serial locally; @@ -149,9 +146,6 @@ uint8_t sleep; // Current copy of Settings.sleep uint8_t stop_flash_rotate = 0; // Allow flash configuration rotation uint8_t blinkstate = 0; // LED state uint8_t blinkspeed = 1; // LED blink rate -uint8_t lastbutton[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states -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 pin[GPIO_MAX]; // Possible pin configurations uint8_t led_inverted = 0; // LED inverted flag (1 = (0 = On, 1 = Off)) uint8_t pwm_inverted = 0; // PWM inverted flag (1 = inverted) @@ -164,7 +158,6 @@ uint8_t soft_spi_flg = 0; // Software SPI configured uint8_t light_type = 0; // Light types uint8_t ntp_force_sync = 0; // Force NTP sync byte serial_in_byte; // Received byte -byte dual_hex_code = 0; // Sonoff dual input flag byte ota_retry_counter = OTA_ATTEMPTS; // OTA retry counter byte web_log_index = 1; // Index in Web log buffer (should never be 0) byte reset_web_log_flag = 0; // Reset web console log @@ -1744,154 +1737,6 @@ void PerformEverySecond(void) if ((3 == RtcTime.minute) && !latest_uptime_flag) latest_uptime_flag = true; } -/*********************************************************************************************\ - * Button handler with single press only or multi-press and hold on all buttons -\*********************************************************************************************/ - -void ButtonHandler(void) -{ - if (uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit - - uint8_t button = NOT_PRESSED; - uint8_t button_present = 0; - uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; // Extent hold time factor in case of iminnent Reset command - uint16_t loops_per_second = 1000 / Settings.button_debounce; - char scmnd[20]; - - uint8_t maxdev = (devices_present > MAX_KEYS) ? MAX_KEYS : devices_present; - for (byte button_index = 0; button_index < maxdev; button_index++) { - button = NOT_PRESSED; - button_present = 0; - - if (!button_index && ((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 == dual_button_code) { // Button hold - holdbutton[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; - hold_time_extent = 1; - } - dual_button_code = 0; - } - } else { - if (pin[GPIO_KEY1 +button_index] < 99) { - button_present = 1; - button = digitalRead(pin[GPIO_KEY1 +button_index]); - } - } - - if (button_present) { - XdrvMailbox.index = button_index; - XdrvMailbox.payload = button; - if (XdrvCall(FUNC_BUTTON_PRESSED)) { - // Serviced - } - else if (SONOFF_4CHPRO == Settings.module) { - if (holdbutton[button_index]) { holdbutton[button_index]--; } - - boolean button_pressed = false; - if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); - AddLog(LOG_LEVEL_DEBUG); - holdbutton[button_index] = loops_per_second; - button_pressed = true; - } - if ((NOT_PRESSED == button) && (PRESSED == lastbutton[button_index])) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_01), button_index +1); - AddLog(LOG_LEVEL_DEBUG); - if (!holdbutton[button_index]) { button_pressed = true; } // Do not allow within 1 second - } - if (button_pressed) { - if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set - ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally - } - } - } - else { - if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { - 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), button_index +1); - AddLog(LOG_LEVEL_DEBUG); - if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set - ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally - } - } else { - multipress[button_index] = (multiwindow[button_index]) ? multipress[button_index] +1 : 1; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, multipress[button_index]); - AddLog(LOG_LEVEL_DEBUG); - multiwindow[button_index] = loops_per_second / 2; // 0.5 second multi press window - } - blinks = 201; - } - - if (NOT_PRESSED == button) { - holdbutton[button_index] = 0; - } else { - holdbutton[button_index]++; - if (Settings.flag.button_single) { // Allow only single button press for immediate action - if (holdbutton[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // Button held for factor times longer -// Settings.flag.button_single = 0; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); // Disable single press only - ExecuteCommand(scmnd, SRC_BUTTON); - } - } else { - if (Settings.flag.button_restrict) { // Button restriction - if (holdbutton[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // Button hold - multipress[button_index] = 0; - SendKey(0, button_index +1, 3); // Execute Hold command via MQTT if ButtonTopic is set - } - } else { - if (holdbutton[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // Button held for factor times longer - multipress[button_index] = 0; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - } - } - - if (!Settings.flag.button_single) { // Allow multi-press - if (multiwindow[button_index]) { - multiwindow[button_index]--; - } else { - if (!restart_flag && !holdbutton[button_index] && (multipress[button_index] > 0) && (multipress[button_index] < MAX_BUTTON_COMMANDS +3)) { - boolean single_press = false; - if (multipress[button_index] < 3) { // Single or Double press - if ((SONOFF_DUAL_R2 == Settings.module) || (SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { - single_press = true; - } else { - single_press = (Settings.flag.button_swap +1 == multipress[button_index]); - multipress[button_index] = 1; - } - } - if (single_press && SendKey(0, button_index + multipress[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set - // Success - } else { - if (multipress[button_index] < 3) { // Single or Double press - if (WifiState() > WIFI_RESTART) { // WPSconfig, Smartconfig or Wifimanager active - restart_flag = 1; - } else { - ExecuteCommandPower(button_index + multipress[button_index], POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally - } - } else { // 3 - 7 press - if (!Settings.flag.button_restrict) { - snprintf_P(scmnd, sizeof(scmnd), kCommands[multipress[button_index] -3]); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - } - multipress[button_index] = 0; - } - } - } - } - } - lastbutton[button_index] = button; - } -} - /*********************************************************************************************\ * State loops \*********************************************************************************************/ @@ -2224,22 +2069,7 @@ void SerialInput(void) * Sonoff dual and ch4 19200 baud serial interface \*-------------------------------------------------------------------------------------------*/ if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { - 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 (serial_in_byte != 0xA1) { - dual_button_code = 0; // 0xA1 - End of Sonoff dual button code - } - } - } - if (0xA0 == serial_in_byte) { // 0xA0 - Start of Sonoff dual button code - serial_in_byte = 0; - dual_button_code = 0; - dual_hex_code = 3; - } + serial_in_byte = ButtonSerial(serial_in_byte); } /*-------------------------------------------------------------------------------------------*/ @@ -2328,7 +2158,6 @@ void SerialInput(void) void GpioInit(void) { uint8_t mpin; - uint8_t key_no_pullup = 0; if (Settings.module >= MAXMODULE) { Settings.module = MODULE; @@ -2366,7 +2195,7 @@ void GpioInit(void) mpin -= (GPIO_SWT1_NP - GPIO_SWT1); } else if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) { - bitSet(key_no_pullup, mpin - GPIO_KEY1_NP); + ButtonPullupFlag(mpin - GPIO_KEY1_NP); mpin -= (GPIO_KEY1_NP - GPIO_KEY1); } else if ((mpin >= GPIO_REL1_INV) && (mpin < (GPIO_REL1_INV + MAX_RELAYS))) { @@ -2483,11 +2312,6 @@ void GpioInit(void) } } - 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 : bitRead(key_no_pullup, i) ? INPUT : INPUT_PULLUP); - } - } for (byte i = 0; i < MAX_LEDS; i++) { if (pin[GPIO_LED1 +i] < 99) { pinMode(pin[GPIO_LED1 +i], OUTPUT); @@ -2495,6 +2319,7 @@ void GpioInit(void) } } + ButtonInit(); SwitchInit(); #ifdef USE_WS2812 @@ -2680,11 +2505,7 @@ void loop(void) OsWatchLoop(); - if (TimeReached(button_debounce)) { - SetNextTimeInterval(button_debounce, Settings.button_debounce); - ButtonHandler(); - } - + ButtonLoop(); SwitchLoop(); if (TimeReached(state_50msecond)) { diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino new file mode 100644 index 000000000..aebbf30be --- /dev/null +++ b/sonoff/support_button.ino @@ -0,0 +1,236 @@ +/* + support_button.ino - button support for Sonoff-Tasmota + + Copyright (C) 2019 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 . +*/ + +#define BUTTON_V1 +#ifdef BUTTON_V1 +/*********************************************************************************************\ + * Button support +\*********************************************************************************************/ + +unsigned long button_debounce = 0; // Button debounce timer +uint16_t holdbutton[MAX_KEYS] = { 0 }; // Timer for button hold +uint16_t dual_button_code = 0; // Sonoff dual received code + +uint8_t lastbutton[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states +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 dual_hex_code = 0; // Sonoff dual input flag +uint8_t key_no_pullup = 0; +uint8_t buttons_found = 0; + +/********************************************************************************************/ + +void ButtonPullupFlag(uint8 button_bit) +{ + bitSet(key_no_pullup, button_bit); +} + +void ButtonInit(void) +{ + buttons_found = 0; + for (byte i = 0; i < MAX_KEYS; i++) { + if (pin[GPIO_KEY1 +i] < 99) { + buttons_found++; + pinMode(pin[GPIO_KEY1 +i], (16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : bitRead(key_no_pullup, i) ? INPUT : INPUT_PULLUP); + } + } +} + +byte ButtonSerial(byte serial_in_byte) +{ + 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 (serial_in_byte != 0xA1) { + dual_button_code = 0; // 0xA1 - End of Sonoff dual button code + } + } + } + if (0xA0 == serial_in_byte) { // 0xA0 - Start of Sonoff dual button code + serial_in_byte = 0; + dual_button_code = 0; + dual_hex_code = 3; + } + + return serial_in_byte; +} + +/*********************************************************************************************\ + * Button handler with single press only or multi-press and hold on all buttons +\*********************************************************************************************/ + +void ButtonHandler(void) +{ + if (uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit + + uint8_t button = NOT_PRESSED; + uint8_t button_present = 0; + uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; // Extent hold time factor in case of iminnent Reset command + uint16_t loops_per_second = 1000 / Settings.button_debounce; + char scmnd[20]; + + uint8_t maxdev = (devices_present > MAX_KEYS) ? MAX_KEYS : devices_present; + for (byte button_index = 0; button_index < maxdev; button_index++) { + button = NOT_PRESSED; + button_present = 0; + + if (!button_index && ((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 == dual_button_code) { // Button hold + holdbutton[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; + hold_time_extent = 1; + } + dual_button_code = 0; + } + } else { + if (pin[GPIO_KEY1 +button_index] < 99) { + button_present = 1; + button = digitalRead(pin[GPIO_KEY1 +button_index]); + } + } + + if (button_present) { + XdrvMailbox.index = button_index; + XdrvMailbox.payload = button; + if (XdrvCall(FUNC_BUTTON_PRESSED)) { + // Serviced + } + else if (SONOFF_4CHPRO == Settings.module) { + if (holdbutton[button_index]) { holdbutton[button_index]--; } + + boolean button_pressed = false; + if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); + AddLog(LOG_LEVEL_DEBUG); + holdbutton[button_index] = loops_per_second; + button_pressed = true; + } + if ((NOT_PRESSED == button) && (PRESSED == lastbutton[button_index])) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_01), button_index +1); + AddLog(LOG_LEVEL_DEBUG); + if (!holdbutton[button_index]) { button_pressed = true; } // Do not allow within 1 second + } + if (button_pressed) { + if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set + ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally + } + } + } + else { + if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { + 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), button_index +1); + AddLog(LOG_LEVEL_DEBUG); + if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set + ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally + } + } else { + multipress[button_index] = (multiwindow[button_index]) ? multipress[button_index] +1 : 1; + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, multipress[button_index]); + AddLog(LOG_LEVEL_DEBUG); + multiwindow[button_index] = loops_per_second / 2; // 0.5 second multi press window + } + blinks = 201; + } + + if (NOT_PRESSED == button) { + holdbutton[button_index] = 0; + } else { + holdbutton[button_index]++; + if (Settings.flag.button_single) { // Allow only single button press for immediate action + if (holdbutton[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // Button held for factor times longer +// Settings.flag.button_single = 0; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); // Disable single press only + ExecuteCommand(scmnd, SRC_BUTTON); + } + } else { + if (Settings.flag.button_restrict) { // Button restriction + if (holdbutton[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // Button hold + multipress[button_index] = 0; + SendKey(0, button_index +1, 3); // Execute Hold command via MQTT if ButtonTopic is set + } + } else { + if (holdbutton[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // Button held for factor times longer + multipress[button_index] = 0; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } + } + } + + if (!Settings.flag.button_single) { // Allow multi-press + if (multiwindow[button_index]) { + multiwindow[button_index]--; + } else { + if (!restart_flag && !holdbutton[button_index] && (multipress[button_index] > 0) && (multipress[button_index] < MAX_BUTTON_COMMANDS +3)) { + boolean single_press = false; + if (multipress[button_index] < 3) { // Single or Double press + if ((SONOFF_DUAL_R2 == Settings.module) || (SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { + single_press = true; + } else { + single_press = (Settings.flag.button_swap +1 == multipress[button_index]); + multipress[button_index] = 1; + } + } + if (single_press && SendKey(0, button_index + multipress[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set + // Success + } else { + if (multipress[button_index] < 3) { // Single or Double press + if (WifiState() > WIFI_RESTART) { // WPSconfig, Smartconfig or Wifimanager active + restart_flag = 1; + } else { + ExecuteCommandPower(button_index + multipress[button_index], POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally + } + } else { // 3 - 7 press + if (!Settings.flag.button_restrict) { + snprintf_P(scmnd, sizeof(scmnd), kCommands[multipress[button_index] -3]); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } + } + multipress[button_index] = 0; + } + } + } + } + } + lastbutton[button_index] = button; + } +} + +void ButtonLoop(void) +{ + if (buttons_found) { + if (TimeReached(button_debounce)) { + SetNextTimeInterval(button_debounce, Settings.button_debounce); + ButtonHandler(); + } + } +} + +#endif // BUTTON_V1 diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino index 5f3685a7a..60d48d0e4 100644 --- a/sonoff/support_switch.ino +++ b/sonoff/support_switch.ino @@ -133,6 +133,8 @@ void SwitchInit(void) void SwitchHandler(byte mode) { + if (uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit + uint8_t button = NOT_PRESSED; uint8_t switchflag; uint16_t loops_per_second = 1000 / Settings.switch_debounce; @@ -140,7 +142,6 @@ void SwitchHandler(byte mode) for (byte i = 0; i < MAX_SWITCHES; i++) { if ((pin[GPIO_SWT1 +i] < 99) || (mode)) { - if (holdwallswitch[i]) { holdwallswitch[i]--; if (0 == holdwallswitch[i]) { From a23f01080b9888bf86bcf25e605b52c7b0df07f3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 7 Jan 2019 16:33:18 +0100 Subject: [PATCH 0815/2222] 6.4.1.8 Add template flags 6.4.1.8 20190107 * Change sonoff_template.h layout regarding optional module flags like ADC0 * Add command SetOption62 1 to force no Button/Switch pullup on dedicated modules. Currently only supported on Shelly2 (#4841) --- sonoff/_changelog.ino | 6 ++++- sonoff/language/bg-BG.h | 1 + sonoff/language/cs-CZ.h | 1 + sonoff/language/de-DE.h | 1 + sonoff/language/el-GR.h | 1 + sonoff/language/en-GB.h | 1 + sonoff/language/es-AR.h | 1 + sonoff/language/fr-FR.h | 1 + sonoff/language/he-HE.h | 1 + sonoff/language/hu-HU.h | 1 + sonoff/language/it-IT.h | 1 + sonoff/language/nl-NL.h | 1 + sonoff/language/pl-PL.h | 1 + sonoff/language/pt-BR.h | 1 + sonoff/language/pt-PT.h | 1 + sonoff/language/ru-RU.h | 1 + sonoff/language/sk-SK.h | 1 + sonoff/language/sv-SE.h | 1 + sonoff/language/tr-TR.h | 1 + sonoff/language/uk-UK.h | 1 + sonoff/language/zh-CN.h | 1 + sonoff/language/zh-TW.h | 1 + sonoff/settings.h | 5 +++- sonoff/sonoff.ino | 10 ++++--- sonoff/sonoff_template.h | 51 +++++++++++++++++++++++++++--------- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 8 ++++++ sonoff/support_button.ino | 6 +++++ sonoff/support_switch.ino | 6 +++-- sonoff/xdrv_01_webserver.ino | 16 +++++++++++ sonoff/xsns_02_analog.ino | 2 +- 31 files changed, 110 insertions(+), 23 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 3d802f705..65d731706 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ -/* 6.4.1.7 20190106 +/* 6.4.1.8 20190107 + * Change sonoff_template.h layout regarding optional module flags like ADC0 + * Add command SetOption62 1 to force no Button/Switch pullup on dedicated modules. Currently only supported on Shelly2 (#4841) + * + * 6.4.1.7 20190106 * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6 * Add relay status functionality to LED2 when configured leaving LED1 for (wifi/mqtt) status indication * Add no pull-up control to Shelly 2 module (default is pull-up, change GPIO2 to Switch3n for no pull-up) (#4841) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index d6ba96985..d7d812385 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Параметри на модула" #define D_MODULE_TYPE "Тип на модула" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Сериен вход" #define D_SERIAL_OUT "Сериен изход" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index b30f94520..e10ec2c4f 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Nastavení modulu" #define D_MODULE_TYPE "Typ modulu" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial In" #define D_SERIAL_OUT "Serial Out" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index d3650b2d3..6fead9321 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Geräte-Einstellungen" #define D_MODULE_TYPE "Gerätetyp" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "serieller Eingang [serial in]" #define D_SERIAL_OUT "serieller Ausgang [serial out]" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 268513060..8a4402538 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Παράμετροι μονάδας" #define D_MODULE_TYPE "Τύπος μονάδας" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial In" #define D_SERIAL_OUT "Serial Out" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index f250e2d24..4ac9186e5 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Module parameters" #define D_MODULE_TYPE "Module type" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial In" #define D_SERIAL_OUT "Serial Out" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 00bbc10a8..105b69895 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Parámetros del módulo" #define D_MODULE_TYPE "Tipo de módulo" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial In" #define D_SERIAL_OUT "Serial Out" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 1bea80a9a..aca69fac6 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Paramètres module" #define D_MODULE_TYPE "Type de module" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Entrée série" #define D_SERIAL_OUT "Sortie série" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index eb2e42152..d4b41f0b5 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "מודול פרמטרים" #define D_MODULE_TYPE "סוג מודול" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO " רגל " #define D_SERIAL_IN "כניסת סריאל" #define D_SERIAL_OUT "יציאת סריאל" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index d6c880603..e3668ce1d 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Modul paraméterek" #define D_MODULE_TYPE "Modul típus" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial In" #define D_SERIAL_OUT "Serial Out" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 58130173f..5ebef743d 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Parametri del modulo" #define D_MODULE_TYPE "Tipo modulo" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial In" #define D_SERIAL_OUT "Serial Out" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 62b40fa9c..1235ab26d 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Module parameters" #define D_MODULE_TYPE "Module soort" +#define D_PULLUP_ENABLE "Geen schakelaar pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serieel In" #define D_SERIAL_OUT "Serieel Uit" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 2fd04d93a..6327f87d0 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Parametery modułu" #define D_MODULE_TYPE "Typ modułu" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial In" #define D_SERIAL_OUT "Serial Out" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 9daa847d3..8f1364771 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Parâmetros do módulo" #define D_MODULE_TYPE "Tipo de módulo" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Entrada serial" #define D_SERIAL_OUT "Saída serial" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 73d148c7c..f863a2148 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Parametros do Módulo" #define D_MODULE_TYPE "Tipo de Módulo" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial Entrada" #define D_SERIAL_OUT "Serial Saída" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index fa698eddd..20f9a2d9f 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Параметры модуля" #define D_MODULE_TYPE "Тип модуля" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial вход" #define D_SERIAL_OUT "Serial выход" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 492fc7d5a..0edd9bea0 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Nastavenia modulu" #define D_MODULE_TYPE "Typ modulu" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial In" #define D_SERIAL_OUT "Serial Out" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 6f5f82b0e..c36440ac7 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Modulparameterar" #define D_MODULE_TYPE "Modultyp" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Seriell in" #define D_SERIAL_OUT "Seriell ut" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 9d66169a9..3ef7dd3f5 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Modül parametreleri" #define D_MODULE_TYPE "Modul türü" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial In" #define D_SERIAL_OUT "Serial Out" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index b6e870e8f..59d9ab8b4 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "Параметри модулю" #define D_MODULE_TYPE "Тип модулю" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Serial вхід" #define D_SERIAL_OUT "Serial вихід" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index c02722897..c64c1b5c3 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "模块设置" #define D_MODULE_TYPE "模块类型" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "串口输入(RX)" #define D_SERIAL_OUT "串口输出(TX)" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index d2524da4f..3560ddf34 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -253,6 +253,7 @@ #define D_MODULE_PARAMETERS "模塊設置" #define D_MODULE_TYPE "模塊類型" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "串口輸入(RX)" #define D_SERIAL_OUT "串口輸出(TX)" diff --git a/sonoff/settings.h b/sonoff/settings.h index 66ab6645c..3c88725e0 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -75,7 +75,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t hass_tele_on_power : 1; // bit 9 (v6.3.0.13) uint32_t sleep_normal : 1; // bit 10 (v6.3.0.15) - SetOption60 - Enable normal sleep instead of dynamic sleep uint32_t button_switch_force_local : 1;// bit 11 - uint32_t spare12 : 1; + uint32_t no_pullup : 1; // bit 12 (v6.4.1.7) - SetOption62 - Force no pull-up (0 = default pull-up, 1 = no pull-up) uint32_t spare13 : 1; uint32_t spare14 : 1; uint32_t spare15 : 1; @@ -271,6 +271,9 @@ struct SYSCFG { uint8_t ws_color[4][3]; // 475 uint8_t ws_width[3]; // 481 myio my_gp; // 484 + + byte free_495[1]; // 495 + uint16_t light_pixels; // 496 uint8_t light_color[5]; // 498 uint8_t light_correction; // 49D diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c2ede5d03..6076fd796 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -168,7 +168,8 @@ byte syslog_level; // Current copy of Settings.syslog_l boolean latest_uptime_flag = true; // Signal latest uptime boolean pwm_present = false; // Any PWM channel configured with SetOption15 0 boolean mdns_begun = false; // mDNS active -myio my_module; // Active copy of Module GPIOs (18 x 8 bits) +myio my_module; // Active copy of Module GPIOs (17 x 8 bits) +gpio_flag my_module_flag; // Active copy of Module GPIO flags StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits) char my_version[33]; // Composed version string char my_image[33]; // Code image and/or commit @@ -181,7 +182,6 @@ char log_data[LOGSZ]; // Logging char web_log[WEB_LOG_SIZE] = {'\0'}; // Web log buffer String backlog[MAX_BACKLOG]; // Command backlog - /********************************************************************************************/ char* Format(char* output, const char* input, int size) @@ -771,6 +771,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if (10 == pindex) { // SetOption60 enable or disable traditional sleep WiFiSetSleepMode(); // Update WiFi sleep mode accordingly } + if (12 == pindex) { // SetOption62 change input pull-up + restart_flag = 2; + } } } else { // SetOption32 .. 49 @@ -2169,8 +2172,6 @@ void GpioInit(void) myio def_gp; ModuleGpios(&def_gp); - - for (byte i = 0; i < sizeof(Settings.my_gp); i++) { if (Settings.my_gp.io[i] > GPIO_NONE) { my_module.io[i] = Settings.my_gp.io[i]; @@ -2179,6 +2180,7 @@ void GpioInit(void) my_module.io[i] = def_gp.io[i]; } } + my_module_flag = ModuleFlag(); for (byte i = 0; i < GPIO_MAX; i++) { pin[i] = 99; diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index b5e47d745..17131fdbb 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -160,7 +160,6 @@ enum ProgramSelectablePins { GPIO_NRG_CF1, // HLW8012/HLJ-01 CF1 voltage / current GPIO_HLW_CF, // HLW8012 CF power GPIO_HJL_CF, // HJL-01/BL0937 CF power - GPIO_ADC0, // ADC GPIO_DI, // my92x1 PWM input GPIO_DCKI, // my92x1 CLK input GPIO_ARIRFRCV, // AliLux RF Receive input @@ -278,7 +277,7 @@ enum SupportedModules { /********************************************************************************************/ -#define MAX_GPIO_PIN 18 // Number of supported GPIO +#define MAX_GPIO_PIN 17 // Number of supported GPIO #define MIN_FLASH_PINS 4 // Number of flash chip pins unusable for configuration (GPIO6, 7, 8 and 11) const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcFLFLolD6D7D5D8D0A0"; @@ -291,9 +290,33 @@ typedef struct MYCFGIO { uint8_t io[MAX_GPIO_PIN - MIN_FLASH_PINS]; } mycfgio; +#define GPIO_FLAG_ADC0 1 // Allow ADC0 when define USE_ADC_VCC is disabled +#define GPIO_FLAG_PULLUP 2 // Allow input pull-up control using SetOption62 +#define GPIO_FLAG_SPARE02 4 +#define GPIO_FLAG_SPARE03 8 +#define GPIO_FLAG_SPARE04 16 +#define GPIO_FLAG_SPARE05 32 +#define GPIO_FLAG_SPARE06 64 +#define GPIO_FLAG_SPARE07 128 + +typedef union { + uint8_t data; + struct { + uint8_t adc0 : 1; // Allow ADC0 when define USE_ADC_VCC is disabled + uint8_t pullup : 1; // Allow input pull-up control using SetOption62 + uint8_t spare02 : 1; + uint8_t spare03 : 1; + uint8_t spare04 : 1; + uint8_t spare05 : 1; + uint8_t spare06 : 1; + uint8_t spare07 : 1; + }; +} gpio_flag; + typedef struct MYTMPLT { char name[15]; mycfgio gp; + gpio_flag flag; } mytmplt; const uint8_t kGpioNiceList[] PROGMEM = { @@ -597,7 +620,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) GPIO_USER, // GPIO14 Optional sensor 0, 0, - GPIO_ADC0 // ADC0 Analog input + GPIO_FLAG_ADC0 // ADC0 Analog input }, { "Sonoff TH", // Sonoff TH10/16 (ESP8266) GPIO_KEY1, // GPIO00 Button @@ -795,7 +818,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO14 Optional sensor GPIO_USER, // GPIO15 Optional sensor GPIO_LED1, // GPIO16 Green/Blue Led (1 = On, 0 = Off) - GPIO_ADC0 // ADC0 A0 Analog input + GPIO_FLAG_ADC0 // ADC0 A0 Analog input }, { "EXS Relay(s)", // ES-Store Latching relay(s) (ESP8266) // https://ex-store.de/ESP8266-WiFi-Relay-V31 @@ -856,7 +879,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO14 D5 GPIO_USER, // GPIO15 D8 GPIO_USER, // GPIO16 D0 Wemos Wake - GPIO_ADC0 // ADC0 A0 Analog input + GPIO_FLAG_ADC0 // ADC0 A0 Analog input +// + GPIO_FLAG_PULLUP // Allow input pull-up control }, { "Sonoff Dev", // Sonoff Dev (ESP8266) GPIO_KEY1, // GPIO00 E-FW Button @@ -876,7 +900,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO14 Optional sensor 0, // GPIO15 0, // GPIO16 - GPIO_ADC0 // ADC0 A0 Analog input + GPIO_FLAG_ADC0 // ADC0 A0 Analog input }, { "H801", // Lixada H801 Wifi (ESP8266) GPIO_USER, // GPIO00 E-FW Button @@ -1083,7 +1107,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO14 Optional sensor 0, GPIO_LED1, // GPIO16 Led (1 = On, 0 = Off) - GPIO_ADC0 // ADC0 A0 Analog input + GPIO_FLAG_ADC0 // ADC0 A0 Analog input }, { "Witty Cloud", // Witty Cloud Dev Board (ESP8266) // https://www.aliexpress.com/item/ESP8266-serial-WIFI-Witty-cloud-Development-Board-ESP-12F-module-MINI-nodemcu/32643464555.html @@ -1104,7 +1128,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO14 D5 optional sensor 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 + GPIO_FLAG_ADC0 // ADC0 A0 Light sensor / Requires USE_ADC_VCC in user_config.h to be disabled }, { "Yunshan Relay", // Yunshan Wifi Relay (ESP8266) // https://www.ebay.com/p/Esp8266-220v-10a-Network-Relay-WiFi-Module/1369583381 @@ -1162,7 +1186,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO14 Optional sensor / I2C SCL pad GPIO_LED1, // GPIO15 Led (1 = On, 0 = Off) 0, - GPIO_ADC0 // ADC0 A0 Analog input + GPIO_FLAG_ADC0 // ADC0 A0 Analog input }, { "KMC 70011", // KMC 70011 // https://www.amazon.com/KMC-Timing-Monitoring-Network-125V-240V/dp/B06XRX2GTQ @@ -1367,7 +1391,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "Shelly 2", // Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ 0, GPIO_TXD, // GPIO01 MCP39F501 Serial input - GPIO_USER, // GPIO02 Decide if we use (no) pull-up + 0, GPIO_RXD, // GPIO03 MCP39F501 Serial output GPIO_REL1, // GPIO04 GPIO_REL2, // GPIO05 @@ -1378,10 +1402,11 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) // GPIO11 (SD_CMD Flash) GPIO_SWT1, // GPIO12 - 0, // GPIO13 + 0, GPIO_SWT2, // GPIO14 0, // GPIO15 MCP39F501 Reset - 0, 0 + 0, + GPIO_FLAG_PULLUP // Allow input pull-up control }, { "Xiaomi Philips", // Xiaomi Philips bulb (ESP8266) 0, 0, 0, 0, 0, 0, @@ -1449,7 +1474,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY1, // GPIO14 Button 0, GPIO_USER, // GPIO16 - GPIO_ADC0 // ADC0 A0 Analog input + GPIO_FLAG_ADC0 // ADC0 A0 Analog input }, { "Teckin", // https://www.amazon.de/gp/product/B07D5V139R 0, diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 56193708d..f371936aa 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040107 +#define VERSION 0x06040108 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index 43f36565e..55be05df7 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -529,6 +529,14 @@ void ModuleGpios(myio *gp) // AddLogSerial(LOG_LEVEL_DEBUG, (uint8_t *)gp, sizeof(myio)); } +gpio_flag ModuleFlag() +{ + gpio_flag flag; + + memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag)); + return flag; +} + void SetGlobalValues(float temperature, float humidity) { global_update = uptime; diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index aebbf30be..880f354d1 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -44,6 +44,12 @@ void ButtonPullupFlag(uint8 button_bit) void ButtonInit(void) { + if (my_module_flag.pullup) { + if (Settings.flag3.no_pullup) { + key_no_pullup = 0xff; + } + } + buttons_found = 0; for (byte i = 0; i < MAX_KEYS; i++) { if (pin[GPIO_KEY1 +i] < 99) { diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino index 60d48d0e4..7a085347e 100644 --- a/sonoff/support_switch.ino +++ b/sonoff/support_switch.ino @@ -110,8 +110,10 @@ void SwitchProbe(void) void SwitchInit(void) { - if (SHELLY2 == Settings.module) { - if (switch_no_pullup > 0) { switch_no_pullup = 0xffff; } // If any switch is no pull-up make them all no pull-up + if (my_module_flag.pullup) { + if (Settings.flag3.no_pullup) { + switch_no_pullup = 0xffff; + } } switches_found = 0; diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index d4d950b77..6072f20fd 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -255,6 +255,10 @@ const char HTTP_BTN_CONF[] PROGMEM = const char HTTP_FORM_MODULE[] PROGMEM = "
           " D_MODULE_PARAMETERS " 
          " "
          " D_MODULE_TYPE " ({mt)

          "; + +const char HTTP_FORM_MODULE_PULLUP[] PROGMEM = + "
          " D_PULLUP_ENABLE "
          "; + const char HTTP_LNK_ITEM[] PROGMEM = "
          {v} ({w}) {i} {r}%
          "; const char HTTP_LNK_SCAN[] PROGMEM = @@ -837,6 +841,12 @@ void HandleModuleConfiguration(void) page.replace(F(""), F("")); page += FPSTR(HTTP_FORM_MODULE); page.replace(F("{mt"), AnyModuleName(MODULE)); + + if (my_module_flag.pullup) { + page += FPSTR(HTTP_FORM_MODULE_PULLUP); + page.replace(F("{r1"), (Settings.flag3.no_pullup) ? F(" checked") : F("")); + } + page += F("
          %s " D_GPIO "%d %s
          "); for (byte i = 0; i < sizeof(cmodule); i++) { if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { @@ -861,6 +871,11 @@ void ModuleSaveSettings(void) byte new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); Settings.last_module = Settings.module; Settings.module = new_module; + if (Settings.last_module == new_module) { + if (my_module_flag.pullup) { + Settings.flag3.no_pullup = WebServer->hasArg("b1"); + } + } myio cmodule; ModuleGpios(&cmodule); String gpios = ""; @@ -1123,6 +1138,7 @@ void HandleOtherConfiguration(void) page += FPSTR(HTTP_HEAD_STYLE); page += FPSTR(HTTP_FORM_OTHER); page.replace(F("{r1"), (Settings.flag.mqtt_enabled) ? F(" checked") : F("")); + uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; if (SONOFF_IFAN02 == Settings.module) { maxfn = 1; } for (byte i = 0; i < maxfn; i++) { diff --git a/sonoff/xsns_02_analog.ino b/sonoff/xsns_02_analog.ino index bb47757d3..e72641a85 100644 --- a/sonoff/xsns_02_analog.ino +++ b/sonoff/xsns_02_analog.ino @@ -71,7 +71,7 @@ boolean Xsns02(byte function) { boolean result = false; - if (pin[GPIO_ADC0] < 99) { + if (my_module_flag.adc0) { switch (function) { #ifdef USE_RULES case FUNC_EVERY_250_MSECOND: From 70619ed6105a00fc8d8174c6b7de38131211930b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 7 Jan 2019 16:43:03 +0100 Subject: [PATCH 0816/2222] Housekeeping --- sonoff/settings.h | 6 +++--- tools/decode-status.py | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 3c88725e0..618cc03f2 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -68,14 +68,14 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t time_append_timezone : 1; // bit 2 (v6.2.1.2) uint32_t gui_hostname_ip : 1; // bit 3 (v6.2.1.20) uint32_t tuya_apply_o20 : 1; // bit 4 (v6.3.0.4) - uint32_t mdns_enabled : 1; // bit 5 (v6.4.1.4) - SetOption55 + uint32_t mdns_enabled : 1; // bit 5 (v6.4.1.4) - SetOption55 uint32_t use_wifi_scan : 1; // bit 6 (v6.3.0.10) uint32_t use_wifi_rescan : 1; // bit 7 (v6.3.0.10) uint32_t receive_raw : 1; // bit 8 (v6.3.0.11) uint32_t hass_tele_on_power : 1; // bit 9 (v6.3.0.13) uint32_t sleep_normal : 1; // bit 10 (v6.3.0.15) - SetOption60 - Enable normal sleep instead of dynamic sleep - uint32_t button_switch_force_local : 1;// bit 11 - uint32_t no_pullup : 1; // bit 12 (v6.4.1.7) - SetOption62 - Force no pull-up (0 = default pull-up, 1 = no pull-up) + uint32_t button_switch_force_local : 1;// bit 11 (v6.3.0.16) - SetOption61 - Force local operation when button/switch topic is set + uint32_t no_pullup : 1; // bit 12 (v6.4.1.7) - SetOption62 - Force no pull-up (0 = (no)pull-up, 1 = no pull-up) uint32_t spare13 : 1; uint32_t spare14 : 1; uint32_t spare15 : 1; diff --git a/tools/decode-status.py b/tools/decode-status.py index 63655f5a6..04b549465 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -96,7 +96,8 @@ a_setoption = [[ "Change state topic from tele/STATE to stat/RESULT", "Enable normal sleep instead of dynamic sleep", "Force local operation when button/switch topic is set", - "","","","", + "Force no pull-up", + "","","", "","","","", "","","","", "","","","", From 148fe4aec0e47d33df660f0a4654d8932ecf6e4d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 7 Jan 2019 16:58:44 +0100 Subject: [PATCH 0817/2222] Only restart if module supports it --- sonoff/sonoff.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 6076fd796..33ea9b025 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -771,8 +771,8 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if (10 == pindex) { // SetOption60 enable or disable traditional sleep WiFiSetSleepMode(); // Update WiFi sleep mode accordingly } - if (12 == pindex) { // SetOption62 change input pull-up - restart_flag = 2; + if ((12 == pindex) && (my_module_flag.pullup)) { // SetOption62 change input pull-up + restart_flag = 2; // Only restart if module supports it } } } From 3dc643d9d083d56c4d1eb687dd3c3ae451dd4eac Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 7 Jan 2019 17:44:30 +0100 Subject: [PATCH 0818/2222] Update sonoff_template.h --- sonoff/sonoff_template.h | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 17131fdbb..f90691a84 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1657,6 +1657,43 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { /* Optionals + { "KA10", // SMANERGY KA10 (ESP8285 - BL0937 Energy Monitoring) - https://www.amazon.es/dp/B07MBTCH2Y + 0, // GPIO00 + GPIO_LED2_INV, // GPIO01 Blue LED + 0, // GPIO02 + GPIO_KEY1, // GPIO03 Button + GPIO_HJL_CF, // GPIO04 BL0937 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 CF1 voltage / current + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage) + GPIO_LED1, // GPIO13 Red LED + GPIO_REL1, // GPIO14 Relay 1 + 0, 0, 0 + } + + { "OBI Socket 2", // OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko-2-stueck-weiss/p/4077673 + 0, // GPIO00 + 0, // GPIO01 Serial RXD + 0, + 0, // GPIO03 Serial TXD + GPIO_REL1, // GPIO04 Relay 1 + GPIO_KEY1, // GPIO05 Button + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_LED2, // GPIO12 Green LED + GPIO_LED1, // GPIO13 Red LED + 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, @@ -1675,7 +1712,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 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 - }, + } + { "Arilux LC10", // Arilux LC10 (ESP8285), RGBW + RF // https://github.com/arendst/Sonoff-Tasmota/wiki/MagicHome-with-ESP8285 // https://www.aliexpress.com/item/DC5-24V-Wireless-WIFI-LED-RGB-Controller-RGBW-Controller-IR-RF-Remote-Control-IOS-Android-for/32827253255.html From f2835d0ae590ef9b3ed40b31144282d70a62f5f5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 7 Jan 2019 17:47:36 +0100 Subject: [PATCH 0819/2222] Update sonoff_template.h --- sonoff/sonoff_template.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index f90691a84..620542432 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1659,7 +1659,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "KA10", // SMANERGY KA10 (ESP8285 - BL0937 Energy Monitoring) - https://www.amazon.es/dp/B07MBTCH2Y 0, // GPIO00 - GPIO_LED2_INV, // GPIO01 Blue LED + GPIO_LED1_INV, // GPIO01 Blue LED 0, // GPIO02 GPIO_KEY1, // GPIO03 Button GPIO_HJL_CF, // GPIO04 BL0937 CF power @@ -1671,7 +1671,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) // GPIO11 (SD_CMD Flash) GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage) - GPIO_LED1, // GPIO13 Red LED + GPIO_LED2, // GPIO13 Red LED GPIO_REL1, // GPIO14 Relay 1 0, 0, 0 } @@ -1689,8 +1689,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) // GPIO11 (SD_CMD Flash) - GPIO_LED2, // GPIO12 Green LED - GPIO_LED1, // GPIO13 Red LED + GPIO_LED1, // GPIO12 Green LED + GPIO_LED2, // GPIO13 Red LED 0, 0, 0, 0 } From c9df630b30c83c05b4e08c4aaa37555b355e6125 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Mon, 7 Jan 2019 18:15:11 +0100 Subject: [PATCH 0820/2222] decode-config.py: adapt settings - add SetOption62 (no_pullup) - revise desc md/html files --- tools/decode-config.html | 39 +++++++++++++++++++------------------ tools/decode-config.md | 42 ++++++++++++++++++++-------------------- tools/decode-config.py | 8 +++++++- 3 files changed, 48 insertions(+), 41 deletions(-) diff --git a/tools/decode-config.html b/tools/decode-config.html index dd24495b7..68968f00d 100644 --- a/tools/decode-config.html +++ b/tools/decode-config.html @@ -1,10 +1,10 @@

          decode-config.py

          decode-config.py is able to backup and restore Sonoff-Tasmota configuration.

          -

          In contrast to the Tasmota build-in "Backup/Restore Configuration" function,

          +

          In comparison with the Tasmota build-in "Backup/Restore Configuration" function decode-config.py

            -
          • decode-config.py uses human readable and editable JSON-format for backup/restore,
          • -
          • decode-config.py can restore previous backuped and changed JSON-format files,
          • -
          • decode-config.py is able to create Tasmota commands based on given configuration
          • +
          • uses human readable and editable JSON-format for backup/restore,
          • +
          • can restore previously backup and changed JSON-format files,
          • +
          • is able to create Tasmota compatible command list with related config parameter

          Comparing backup files created by decode-config.py and *.dmp files created by Tasmota "Backup/Restore Configuration":

          @@ -38,7 +38,7 @@
          -

          decode-config.py is able to handle Tasmota configurations for release version starting from 5.10.0 up to now.

          +

          decode-config.py is compatible with Tasmota version from v5.10.0 up to now.

          Content

          Prerequisite

            -
          • Python)
            This program is written in Python) so you need to install a python environment (for details see Python Setup and Usage)

            +
          • Python)
            This program is written in Python) so you need to install a working python environment (for details see Python Setup and Usage)

          • Sonoff-Tasmota Firmware with Web-Server enabled:

              -
            • To backup or restore configurations from/to a Sonoff-Tasmota device you need a firmare with enabled web-server in admin mode (command WebServer 2).
            • +
            • To backup or restore configurations from or to a Sonoff-Tasmota device you need a firmare with enabled web-server in admin mode (command WebServer 2). This is the Tasmota default.
            • If using your own compiled firmware be aware to enable the web-server (#define USE_WEBSERVER and #define WEB_SERVER 2).
          • @@ -89,19 +89,20 @@

            .dmp Format

            Configuration data as used by Tasmota "Backup/Restore Configuration" web interface.
            This format is binary and encrypted.

            .json Format

            -

            Configuration data in JSON-format.
            This format is decrypted, human readable and editable and can also be used for the --restore-file command.
            This file will becreated by decode-config.py using --backup-file with --backup-type json parameter (default).

            +

            Configuration data in JSON-format.
            This format is decrypted, human readable and editable and can also be used for the --restore-file parameter.
            This file will be created by decode-config.py using the --backup-file with --backup-type json parameter, this is the default.

            .bin Format

            -

            Configuration data in binary format.
            This format is binary decryptet, editable (e.g. using a hex editor) and can also be used for --restore-file command.
            It will be created by decode-config.py using --backup-file with --backup-type bin.
            Note:
            This file is 4 byte longer than an original .dmp file due to an prefix header at the beginning. The file data starting at address position 4 are containing the same as the struct SYSCFG from Tasmota settings.h in decrypted format.

            +

            Configuration data in binary format.
            This format is binary decryptet, editable (e.g. using a hex editor) and can also be used for --restore-file command.
            It will be created by decode-config.py using --backup-file with --backup-type bin.
            Note:
            The .bin file contains the same information as the original .dmp file from Tasmota "Backup/Restore Configuration" but it is decrpted and 4 byte longer than an original (it is a prefix header at the beginning). .bin file data starting at address 4 contains the same as the struct SYSCFG from Tasmota settings.h in decrypted format.

            File extensions

            -

            decode-config.py uses auto extension as default for backup filenames; you don't need to append extensions to your backup file, it will be selected based on --backup-type argument.
            If you want using your own extension use the --no-extension argument.

            +

            You don't need to append exensions for your file name as decode-config.py uses auto extension as default. The extension will be choose based on file contents and --backup-type parameter. +If you do not want using auto extensions use the --no-extension parameter.

            Usage

            -

            After download don't forget to set exec flag under linux with chmod +x decode-config.py or call the program using python decode-config.py....

            +

            After download don't forget to set the executable flag under linux with chmod +x decode-config.py or call the program using python decode-config.py....

            Basics

            At least pass a source where you want to read the configuration data from using -f <filename> or -d <host>:

            The source can be either

              -
            • a Tasmota device hostname or IP by passing it using the -d <host> arg
            • -
            • or a previously stored Tasmota *.dmp configuration file by passing the filename using -f <filename> arg
            • +
            • a Tasmota device hostname or IP using the -d <host> parameter
            • +
            • a Tasmota *.dmp configuration file using -f <filename> parameter

            Example:

            decode-config.py -d sonoff-4281
            @@ -119,22 +120,22 @@
               ]
             }
             

            Save backup file

            -

            To save the output as backup file --backup-file <filename>, you can use placeholder for Version, Friendlyname and Hostname:

            +

            To save the output as backup file use --backup-file <filename>, you can use placeholder for Version, Friendlyname and Hostname:

            decode-config.py -d sonoff-4281 --backup-file Config_@f_@v
             

            If you have setup a WebPassword within Tasmota, use

            decode-config.py -d sonoff-4281 -p <yourpassword> --backup-file Config_@f_@v
            -

            will create a file like Config_Sonoff_x.x.x.json. Because it is in JSON format, you can read and edit the file with any raw text editor.

            +

            will create a file like Config_Sonoff_6.4.0.json (the part Sonoff and 6.4.0 will choosen related to your device configuration). Because the default backup file format is JSON, you can read and change it with any raw text editor.

            Restore backup file

            -

            Reading back a saved (and possible changed) backup file use the --restore-file <filename> arg. This will read the (changed) configuration data from this file and send it back to the source device or filename.

            +

            Reading back a saved (and possible changed) backup file use the --restore-file <filename> parameter. This will read the (changed) configuration data from this file and send it back to the source device or filename.

            To restore the previously save backup file Config_Sonoff_6.2.1.json to device sonoff-4281 use:

            decode-config.py -d sonoff-4281 --restore-file Config_Sonoff_6.2.1.json
             

            with password set by WebPassword:

            decode-config.py -d sonoff-4281 -p <yourpassword> --restore-file Config_Sonoff_6.2.1.json
             

            Output to screen

            -

            Output to screen is default enabled when calling the program with a source arg but without a backup or restore arg.

            -

            --output arg will force screen output even if you use backup or restore arg.

            +

            To force screen output use the --output parameter.

            +

            Output to screen is default enabled when calling the program with a source parameter (-f or -d) but without any backup or restore parameter.

            JSON output

            -

            The default output format is JSON. You can force JSON output with --output-format json arg.

            +

            The default output format is JSON. You can force JSON output using the --output-format json parameter.

            Example:

            decode-config.py -d sonoff-4281 -c my.conf -x Wifi --output-format json
             
            diff --git a/tools/decode-config.md b/tools/decode-config.md
            index 97978114a..ca70d36e9 100644
            --- a/tools/decode-config.md
            +++ b/tools/decode-config.md
            @@ -1,10 +1,10 @@
             # decode-config.py
             _decode-config.py_ is able to backup and restore Sonoff-Tasmota configuration.
             
            -In contrast to the Tasmota build-in "Backup/Restore Configuration" function,
            -* _decode-config.py_ uses human readable and editable [JSON](http://www.json.org/)-format for backup/restore,
            -* _decode-config.py_ can restore previous backuped and changed [JSON](http://www.json.org/)-format files,
            -* _decode-config.py_ is able to create Tasmota commands based on given configuration
            +In comparison with the Tasmota build-in "Backup/Restore Configuration" function _decode-config.py_
            +* uses human readable and editable [JSON](http://www.json.org/)-format for backup/restore,
            +* can restore previously backup and changed [JSON](http://www.json.org/)-format files,
            +* is able to create Tasmota compatible command list with related config parameter
             
             Comparing backup files created by *decode-config.py* and *.dmp files created by Tasmota "Backup/Restore Configuration":  
             
            @@ -15,7 +15,7 @@ Comparing backup files created by *decode-config.py* and *.dmp files created by
             | Simply editable         |               Yes               |                  No                 |
             | Simply batch processing |               Yes               |                  No                 |
             
            -_decode-config.py_ is able to handle Tasmota configurations for release version starting from 5.10.0 up to now.
            +_decode-config.py_ is compatible with Tasmota version from v5.10.0 up to now.
             
             # Content
             * [Prerequisite](decode-config.md#prerequisite)
            @@ -42,10 +42,10 @@ _decode-config.py_ is able to handle Tasmota configurations for release version
             
             ## Prerequisite
             * [Python](https://en.wikipedia.org/wiki/Python_(programming_language))  
            -  This program is written in [Python](https://en.wikipedia.org/wiki/Python_(programming_language)) so you need to install a python environment (for details see [Python Setup and Usage](https://docs.python.org/2.7/using/index.html))
            +  This program is written in [Python](https://en.wikipedia.org/wiki/Python_(programming_language)) so you need to install a working python environment (for details see [Python Setup and Usage](https://docs.python.org/2.7/using/index.html))
             
             * [Sonoff-Tasmota](https://github.com/arendst/Sonoff-Tasmota) [Firmware](https://github.com/arendst/Sonoff-Tasmota/releases) with Web-Server enabled:
            -  * To backup or restore configurations from/to a Sonoff-Tasmota device you need a firmare with enabled web-server in admin mode (command [WebServer 2](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands#wifi)).
            +  * To backup or restore configurations from or to a Sonoff-Tasmota device you need a firmare with enabled web-server in admin mode (command [WebServer 2](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands#wifi)). This is the Tasmota default.
               * If using your own compiled firmware be aware to enable the web-server (`#define USE_WEBSERVER` and `#define WEB_SERVER 2`).
             
             ## File Types
            @@ -55,28 +55,28 @@ Configuration data as used by Tasmota "Backup/Restore Configuration" web interfa
             This format is binary and encrypted.
             ### .json Format
             Configuration data in [JSON](http://www.json.org/)-format.  
            -This format is decrypted, human readable and editable and can also be used for the `--restore-file` command.  
            -This file will becreated by _decode-config.py_ using `--backup-file` with `--backup-type json` parameter (default).
            +This format is decrypted, human readable and editable and can also be used for the `--restore-file` parameter.  
            +This file will be created by _decode-config.py_ using the `--backup-file` with `--backup-type json` parameter, this is the default.
             ### .bin Format
             Configuration data in binary format.  
             This format is binary decryptet, editable (e.g. using a hex editor) and can also be used for `--restore-file` command.  
             It will be created by _decode-config.py_ using `--backup-file` with `--backup-type bin`.  
             Note:  
            -This file is 4 byte longer than an original .dmp file due to an prefix header at the beginning. The file data starting at address position 4 are containing the same as the **struct SYSCFG** from Tasmota [settings.h](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/settings.h) in decrypted format.
            +The .bin file contains the same information as the original .dmp file from Tasmota "Backup/Restore Configuration" but it is decrpted and  4 byte longer than an original (it is a prefix header at the beginning). .bin file data starting at address 4 contains the same as the **struct SYSCFG** from Tasmota [settings.h](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/settings.h) in decrypted format.
             
             #### File extensions
            -_decode-config.py_ uses auto extension as default for backup filenames; you don't need to append extensions to your backup file, it will be selected based on `--backup-type` argument.  
            -If you want using your own extension use the `--no-extension` argument.
            +You don't need to append exensions for your file name as _decode-config.py_ uses auto extension as default. The extension will be choose based on file contents and `--backup-type` parameter.
            +If you do not want using auto extensions use the `--no-extension` parameter.
             
             ## Usage
            -After download don't forget to set exec flag under linux with `chmod +x decode-config.py` or call the program using `python decode-config.py...`.
            +After download don't forget to set the executable flag under linux with `chmod +x decode-config.py` or call the program using `python decode-config.py...`.
             
             ### Basics
             At least pass a source where you want to read the configuration data from using `-f ` or `-d `:
             
             The source can be either 
            -* a Tasmota device hostname or IP by passing it using the `-d ` arg
            -* or a previously stored Tasmota `*.dmp` configuration file by passing the filename using `-f ` arg
            +* a Tasmota device hostname or IP using the `-d ` parameter
            +* a Tasmota `*.dmp` configuration file using `-f ` parameter
             
             Example:  
             
            @@ -99,7 +99,7 @@ will output a human readable configuration in [JSON](http://www.json.org/)-forma
             
             
             ### Save backup file
            -To save the output as backup file `--backup-file `, you can use placeholder for Version, Friendlyname and Hostname:  
            +To save the output as backup file use `--backup-file `, you can use placeholder for Version, Friendlyname and Hostname:  
             
                 decode-config.py -d sonoff-4281 --backup-file Config_@f_@v
                 
            @@ -107,10 +107,10 @@ If you have setup a WebPassword within Tasmota, use
             
                 decode-config.py -d sonoff-4281 -p  --backup-file Config_@f_@v
             
            -will create a file like `Config_Sonoff_x.x.x.json`. Because it is in JSON format, you can read and edit the file with any raw text editor.
            +will create a file like `Config_Sonoff_6.4.0.json` (the part `Sonoff` and `6.4.0` will choosen related to your device configuration). Because the default backup file format is JSON, you can read and change it with any raw text editor.
             
             ### Restore backup file
            -Reading back a saved (and possible changed) backup file use the `--restore-file ` arg. This will read the (changed) configuration data from this file and send it back to the source device or filename.
            +Reading back a saved (and possible changed) backup file use the `--restore-file ` parameter. This will read the (changed) configuration data from this file and send it back to the source device or filename.
             
             To restore the previously save backup file `Config_Sonoff_6.2.1.json` to device `sonoff-4281` use:  
             
            @@ -121,12 +121,12 @@ with password set by WebPassword:
                 decode-config.py -d sonoff-4281 -p  --restore-file Config_Sonoff_6.2.1.json
             
             ### Output to screen
            -Output to screen is default enabled when calling the program with a source arg but without a backup or restore arg.
            +To force screen output use the `--output` parameter.
             
            -`--output` arg will force screen output even if you use backup or restore arg.
            +Output to screen is default enabled when calling the program with a source parameter (-f or -d) but without any backup or restore parameter.
             
             #### JSON output
            -The default output format is JSON. You can force JSON output with `--output-format json` arg.
            +The default output format is [JSON](decode-config.md#-json-format). You can force JSON output using the `--output-format json` parameter.
             
             Example:
             
            diff --git a/tools/decode-config.py b/tools/decode-config.py
            index 7343adc17..53481b791 100755
            --- a/tools/decode-config.py
            +++ b/tools/decode-config.py
            @@ -1,6 +1,6 @@
             #!/usr/bin/env python
             # -*- coding: utf-8 -*-
            -VER = '2.1.0016'
            +VER = '2.1.0017'
             
             """
                 decode-config.py - Backup/Restore Sonoff-Tasmota configuration data
            @@ -819,7 +819,13 @@ Setting_6_4_1_4['flag3'][0].update ({
                     'mdns_enabled':             ('
            Date: Mon, 7 Jan 2019 19:13:11 +0100
            Subject: [PATCH 0821/2222] Update de-DE.h
            
            ---
             sonoff/language/de-DE.h | 2 +-
             1 file changed, 1 insertion(+), 1 deletion(-)
            
            diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h
            index 6fead9321..bea56f0f6 100644
            --- a/sonoff/language/de-DE.h
            +++ b/sonoff/language/de-DE.h
            @@ -253,7 +253,7 @@
             
             #define D_MODULE_PARAMETERS "Geräte-Einstellungen"
             #define D_MODULE_TYPE "Gerätetyp"
            -#define D_PULLUP_ENABLE "No Button/Switch pull-up"
            +#define D_PULLUP_ENABLE "Kein Taster/Schalter Pull-up"
             #define D_GPIO "GPIO"
             #define D_SERIAL_IN "serieller Eingang [serial in]"
             #define D_SERIAL_OUT "serieller Ausgang [serial out]"
            
            From a38750bf66906ebb0221d414e0fc6358376a6200 Mon Sep 17 00:00:00 2001
            From: Adrian Scillato <35405447+ascillato@users.noreply.github.com>
            Date: Mon, 7 Jan 2019 18:55:26 -0300
            Subject: [PATCH 0822/2222] Updated Spanish Translation
            
            ---
             sonoff/language/es-AR.h | 2 +-
             1 file changed, 1 insertion(+), 1 deletion(-)
            
            diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h
            index 105b69895..8add1a3ba 100644
            --- a/sonoff/language/es-AR.h
            +++ b/sonoff/language/es-AR.h
            @@ -253,7 +253,7 @@
             
             #define D_MODULE_PARAMETERS "Parámetros del módulo"
             #define D_MODULE_TYPE "Tipo de módulo"
            -#define D_PULLUP_ENABLE "No Button/Switch pull-up"
            +#define D_PULLUP_ENABLE "Botón/Llave sin pull-up"
             #define D_GPIO "GPIO"
             #define D_SERIAL_IN "Serial In"
             #define D_SERIAL_OUT "Serial Out"
            
            From 23fa3c624a623379edf923f7bd1bde6840b80147 Mon Sep 17 00:00:00 2001
            From: Theo Arends <11044339+arendst@users.noreply.github.com>
            Date: Tue, 8 Jan 2019 11:44:45 +0100
            Subject: [PATCH 0823/2222] Clarify Link/Power LED selection
            
            Clarify Link/Power LED selection
            ---
             sonoff/_changelog.ino    |   2 +-
             sonoff/sonoff.ino        |   8 +--
             sonoff/sonoff_template.h | 122 +++++++++++++++++++--------------------
             3 files changed, 66 insertions(+), 66 deletions(-)
            
            diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino
            index 65d731706..18af24ac2 100644
            --- a/sonoff/_changelog.ino
            +++ b/sonoff/_changelog.ino
            @@ -4,7 +4,7 @@
              *
              * 6.4.1.7 20190106
              * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6
            - * Add relay status functionality to LED2 when configured leaving LED1 for (wifi/mqtt) status indication
            + * Add Power status functionality to LED2 when configured leaving LED1 for Link status indication
              * Add no pull-up control to Shelly 2 module (default is pull-up, change GPIO2 to Switch3n for no pull-up) (#4841)
              * Add 4 seconds startup delay to button control (#4829)
              * Change button driver making it modular
            diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino
            index 33ea9b025..404403d5a 100755
            --- a/sonoff/sonoff.ino
            +++ b/sonoff/sonoff.ino
            @@ -371,7 +371,7 @@ void SetLedPower(uint8_t state)
               digitalWrite(pin[GPIO_LED1 + led_pin], (bitRead(led_inverted, led_pin)) ? !state : state);
             }
             
            -void SetLedWifi(uint8_t state)
            +void SetLedLink(uint8_t state)
             {
               if (state) state = 1;
               digitalWrite(pin[GPIO_LED1], (bitRead(led_inverted, 0)) ? !state : state);
            @@ -1283,7 +1283,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
                     Settings.ledstate = payload;
                     if (!Settings.ledstate) {
                       SetLedPower(0);
            -          SetLedWifi(0);
            +          SetLedLink(0);
                     }
                   }
                   snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.ledstate);
            @@ -1827,7 +1827,7 @@ void Every250mSeconds(void)
                 if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) {
             //    if ( (!Settings.flag.global_state && global_state.data) || ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) ) {
             //      SetLedPower(blinkstate);                            // Set led on or off
            -      SetLedWifi(blinkstate);                            // Set led on or off
            +      SetLedLink(blinkstate);                            // Set led on or off
                 }
                 if (!blinkstate) {
                   blinks--;
            @@ -2341,7 +2341,7 @@ void GpioInit(void)
               }
             
               SetLedPower(Settings.ledstate &8);
            -  SetLedWifi(Settings.ledstate &8);
            +  SetLedLink(Settings.ledstate &8);
             
               XdrvCall(FUNC_PRE_INIT);
             }
            diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h
            index 620542432..7346a3035 100644
            --- a/sonoff/sonoff_template.h
            +++ b/sonoff/sonoff_template.h
            @@ -579,7 +579,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status
                  GPIO_USER,        // GPIO14 Optional sensor
                  0,                // GPIO15
                  0,                // GPIO16
            @@ -599,7 +599,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status
                  GPIO_USER,        // GPIO14 Optional sensor
                  0, 0, 0
               },
            @@ -617,7 +617,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status
                  GPIO_USER,        // GPIO14 Optional sensor
                  0, 0,
                  GPIO_FLAG_ADC0    // ADC0 Analog input
            @@ -636,7 +636,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status
                  GPIO_USER,        // GPIO14 Optional sensor
                  0, 0, 0
               },
            @@ -654,7 +654,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  0,
            -     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status
                  GPIO_USER,        // GPIO14 Optional sensor
                  0, 0, 0
               },
            @@ -671,7 +671,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
                  GPIO_NRG_CF1,     // GPIO13 HLW8012 CF1 voltage / current
                  GPIO_HLW_CF,      // GPIO14 HLW8012 CF power
            -     GPIO_LED1,        // GPIO15 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1,        // GPIO15 Blue Led (0 = On, 1 = Off) - Link and Power status
                  0, 0
               },
               { "Sonoff 4CH",      // Sonoff 4CH (ESP8285)
            @@ -687,7 +687,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_KEY2,        // GPIO09 Button 2
                  GPIO_KEY3,        // GPIO10 Button 3
                                    // GPIO11 (SD_CMD   Flash)
            -     GPIO_REL1,        // GPIO12 Red Led and Relay 1 (0 = Off, 1 = On)
            +     GPIO_REL1,        // GPIO12 Red Led and Relay 1 (0 = Off, 1 = On) - Link and Power status
                  GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
                  GPIO_KEY4,        // GPIO14 Button 4
                  GPIO_REL4,        // GPIO15 Red Led and Relay 4 (0 = Off, 1 = On)
            @@ -705,7 +705,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO09 (SD_DATA2 Flash QIO or ESP8285)
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
            -     GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
            +     GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On) - Link and Power status
                  GPIO_LED1_INV,    // GPIO13 Green/Blue Led (0 = On, 1 = Off)
                  0, 0, 0, 0
               },
            @@ -722,7 +722,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               },
               { "Sonoff Touch",    // Sonoff Touch (ESP8285)
            @@ -737,7 +737,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO09
                  0,                // GPIO10
                                    // GPIO11 (SD_CMD   Flash)
            -     GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
            +     GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On) - Link and Power status
                  GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
                  0, 0, 0, 0
               },
            @@ -753,7 +753,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_PWM1,        // GPIO12 Cold light (PWM0 Cold)
            -     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status
                  GPIO_PWM2,        // GPIO14 Warm light (PWM1 Warm)
                  GPIO_USER,        // GPIO15 Optional sensor (PWM4 Blue)
                  0, 0
            @@ -768,7 +768,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               },
               { "4 Channel",       // 4 Channel Inching/Latching Relays (ESP8266)
            @@ -784,7 +784,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  0,
            -     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               },
               { "Motor C/AC",      // Motor Clockwise / Anti clockwise (PSA-B01 - ESP8266)
            @@ -797,7 +797,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               },
               { "ElectroDragon",   // ElectroDragon IoT Relay Board (ESP8266)
            @@ -817,7 +817,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_REL1,        // GPIO13 Red Led and Relay 1 (0 = Off, 1 = On)
                  GPIO_USER,        // GPIO14 Optional sensor
                  GPIO_USER,        // GPIO15 Optional sensor
            -     GPIO_LED1,        // GPIO16 Green/Blue Led (1 = On, 0 = Off)
            +     GPIO_LED1,        // GPIO16 Green/Blue Led (1 = On, 0 = Off) - Link and Power status
                  GPIO_FLAG_ADC0    // ADC0   A0 Analog input
               },
               { "EXS Relay(s)",    // ES-Store Latching relay(s) (ESP8266)
            @@ -839,7 +839,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_REL1,        // GPIO12 Relay1 ( 1 = Off)
                  GPIO_REL2,        // GPIO13 Relay1 ( 1 = On)
                  GPIO_USER,        // GPIO14 V3.1 Module Pin 5 - V5.0 GPIO_REL3_INV Relay2 ( 1 = Off)
            -     GPIO_LED1,        // GPIO15 V5.0 LED1
            +     GPIO_LED1,        // GPIO15 V5.0 LED1 - Link and Power status
                  GPIO_USER,        // GPIO16 V3.1 Module Pin 4 - V5.0 GPIO_REL4_INV Relay2 ( 1 = On)
                  0
               },
            @@ -847,7 +847,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                                    // https://www.amazon.com/gp/product/B00ZYLUBJU/ref=s9_acsd_al_bw_c_x_3_w
                  GPIO_USER,        // GPIO00 Optional sensor (pm clock)
                  0,
            -     GPIO_LED1,        // GPIO02 Green Led (1 = On, 0 = Off)
            +     GPIO_LED1,        // GPIO02 Green Led (1 = On, 0 = Off) - Link and Power status
                  0, 0, 0,
                                    // GPIO06 (SD_CLK   Flash)
                                    // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT)
            @@ -904,7 +904,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
               },
               { "H801",            // Lixada H801 Wifi (ESP8266)
                  GPIO_USER,        // GPIO00 E-FW Button
            -     GPIO_LED1,        // GPIO01 Green LED
            +     GPIO_LED1,        // GPIO01 Green LED - Link and Power status
                  GPIO_USER,        // GPIO02 TX and Optional sensor - Pin next to TX on the PCB
                  GPIO_USER,        // GPIO03 RX and Optional sensor - Pin next to GND on the PCB
                  GPIO_PWM5,        // GPIO04 W2 - PWM5
            @@ -934,7 +934,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  0,
            -     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               },
               { "Sonoff BN-SZ",    // Sonoff BN-SZ01 Ceiling led (ESP8285)
            @@ -946,7 +946,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_PWM1,        // GPIO12 Light
            -     GPIO_LED1_INV,    // GPIO13 Red Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Red Led (0 = On, 1 = Off) - Link and Power status
                  0, 0,
                  0, 0
               },
            @@ -964,15 +964,15 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_KEY3,        // GPIO10 Button 3
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Red Led and Relay 1 (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status
                  GPIO_KEY4,        // GPIO14 Button 4
                  GPIO_REL4,        // GPIO15 Red Led and Relay 4 (0 = Off, 1 = On)
                  0, 0
               },
               { "Huafan SS",       // Hua Fan Smart Socket (ESP8266) - like Sonoff Pow
            -     GPIO_LED1_INV,    // GPIO00 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO00 Blue Led (0 = On, 1 = Off) - Link status
                  0, 0,
            -     GPIO_LED2_INV,    // GPIO03 Red Led (0 = On, 1 = Off)
            +     GPIO_LED2_INV,    // GPIO03 Red Led (0 = On, 1 = Off) - Power status
                  GPIO_KEY1,        // GPIO04 Button
                  GPIO_REL1_INV,    // GPIO05 Relay (0 = On, 1 = Off)
                                    // GPIO06 (SD_CLK   Flash)
            @@ -1000,7 +1000,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10
                                    // GPIO11 (SD_CMD   Flash)
                  0,
            -     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               },
               { "Sonoff B1",       // Sonoff B1 (ESP8285 - my9231)
            @@ -1051,7 +1051,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               },
               { "Sonoff T1 2CH",   // Sonoff T1 2CH (ESP8285)
            @@ -1068,7 +1068,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               },
               { "Sonoff T1 3CH",   // Sonoff T1 3CH (ESP8285)
            @@ -1085,7 +1085,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_KEY3,        // GPIO10 Button 3
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               },
               { "Supla Espablo",   // Supla Espablo (ESP8266)
            @@ -1106,14 +1106,14 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_REL2,        // GPIO13 Relay 2 (0 = Off, 1 = On)
                  GPIO_USER,        // GPIO14 Optional sensor
                  0,
            -     GPIO_LED1,        // GPIO16 Led (1 = On, 0 = Off)
            +     GPIO_LED1,        // GPIO16 Led (1 = On, 0 = Off) - Link and Power status
                  GPIO_FLAG_ADC0    // ADC0 A0 Analog input
               },
               { "Witty Cloud",     // Witty Cloud Dev Board (ESP8266)
                                    // https://www.aliexpress.com/item/ESP8266-serial-WIFI-Witty-cloud-Development-Board-ESP-12F-module-MINI-nodemcu/32643464555.html
                  GPIO_USER,        // GPIO00 D3 flash push button on interface board
                  GPIO_USER,        // GPIO01 Serial RXD and Optional sensor
            -     GPIO_LED1_INV,    // GPIO02 D4 Blue Led (0 = On, 1 = Off) on ESP-12F
            +     GPIO_LED1_INV,    // GPIO02 D4 Blue Led (0 = On, 1 = Off) on ESP-12F - Link and Power status
                  GPIO_USER,        // GPIO03 Serial TXD and Optional sensor
                  GPIO_KEY1,        // GPIO04 D2 push button on ESP-12F board
                  GPIO_USER,        // GPIO05 D1 optional sensor
            @@ -1135,7 +1135,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                                    // Schematics and Info https://ucexperiment.wordpress.com/2016/12/18/yunshan-esp8266-250v-15a-acdc-network-wifi-relay-module/
                  0,                // GPIO00 Flash jumper - Module Pin 8
                  GPIO_USER,        // GPIO01 Serial RXD and Optional sensor - Module Pin 2
            -     GPIO_LED1_INV,    // GPIO02 Blue Led (0 = On, 1 = Off) on ESP-12F - Module Pin 7
            +     GPIO_LED1_INV,    // GPIO02 Blue Led (0 = On, 1 = Off) on ESP-12F - Module Pin 7 - Link and Power status
                  GPIO_USER,        // GPIO03 Serial TXD and Optional sensor - Module Pin 3
                  GPIO_REL1,        // GPIO04 Red Led and Relay (0 = Off, 1 = On) - Module Pin 10
                  GPIO_KEY1,        // GPIO05 Blue Led and OptoCoupler input - Module Pin 9
            @@ -1151,7 +1151,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                                    // https://www.aliexpress.com/item/Magic-Home-Mini-RGB-RGBW-Wifi-Controller-For-Led-Strip-Panel-light-Timing-Function-16million-colors/32686853650.html
                  0,
                  GPIO_USER,        // GPIO01 Serial RXD and Optional sensor
            -     GPIO_LED1_INV,    // GPIO02 Blue onboard LED
            +     GPIO_LED1_INV,    // GPIO02 Blue onboard LED - Link and Power status
                  GPIO_USER,        // GPIO03 Serial TXD and Optional sensor
                  GPIO_ARIRFRCV,    // GPIO04 IR or RF receiver (optional) (Arilux LC10)
                  GPIO_PWM2,        // GPIO05 RGB LED Green
            @@ -1184,7 +1184,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  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)
            +     GPIO_LED1,        // GPIO15 Led (1 = On, 0 = Off) - Link and Power status
                  0,
                  GPIO_FLAG_ADC0    // ADC0 A0 Analog input
               },
            @@ -1201,7 +1201,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_NRG_SEL,     // GPIO12 HLW8012 SEL (1 = Voltage)
            -     GPIO_LED1_INV,    // GPIO13 Green Led
            +     GPIO_LED1_INV,    // GPIO13 Green Led - Link and Power status
                  GPIO_REL1,        // GPIO14 Relay
                  0, 0, 0
               },
            @@ -1260,7 +1260,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_KEY1,        // GPIO10 Button on casing
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Relay 1 (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               },
               { "Arilux LC06",     // Arilux AL-LC06 (ESP8285)
            @@ -1296,7 +1296,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               },
               { "Zengge WF017",    // Zenggee ZJ-WF017-A (ESP12S))
            @@ -1331,7 +1331,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               },
               { "Sonoff iFan02",   // Sonoff iFan02 (ESP8285)
            @@ -1348,7 +1348,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_KEY3,        // GPIO10 WIFI_KEY2 Virtual button 3 as feedback from RC
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 WIFI_O0 Relay 1 (0 = Off, 1 = On) controlling the light
            -     GPIO_LED1_INV,    // GPIO13 WIFI_CHK Blue Led on PCA (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 WIFI_CHK Blue Led on PCA (0 = On, 1 = Off) - Link and Power status
                  GPIO_KEY4,        // GPIO14 WIFI_KEY3 Virtual button 4 as feedback from RC
                  GPIO_REL4,        // GPIO15 WIFI_O3 Relay 4 (0 = Off, 1 = On) controlling the fan
                  0, 0
            @@ -1358,9 +1358,9 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                                    // https://www.amazon.de/Steckdose-Homecube-intelligente-Verbrauchsanzeige-funktioniert/dp/B076Q2LKHG/ref=sr_1_fkmr0_1
                                    // https://www.amazon.de/Intelligente-Stromverbrauch-Fernsteurung-Schaltbare-Energieklasse/dp/B076WZQS4S/ref=sr_1_1
                                    // https://www.aliexpress.com/store/product/BlitzWolf-BW-SHP6-EU-Plug-Metering-Version-WIFI-Smart-Socket-220V-240V-10A-Work-with-Amazon/1965360_32945504669.html
            -     GPIO_LED2_INV,    // GPIO00 Red Led (1 = On, 0 = Off)
            +     GPIO_LED2_INV,    // GPIO00 Red Led (1 = On, 0 = Off) - Power status
                  GPIO_USER,        // GPIO01 Serial RXD and Optional sensor
            -     GPIO_LED1_INV,    // GPIO02 Blue Led (1 = On, 0 = Off)
            +     GPIO_LED1_INV,    // GPIO02 Blue Led (1 = On, 0 = Off) - Link status
                  GPIO_USER,        // GPIO03 Serial TXD and Optional sensor
                  0,
                  GPIO_HJL_CF,      // GPIO05 BL0937 or HJL-01 CF power
            @@ -1424,7 +1424,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
               { "Neo Coolcam",     // Neo Coolcam (ESP8266)
                                    // https://www.banggood.com/NEO-COOLCAM-WiFi-Mini-Smart-Plug-APP-Remote-Control-Timing-Smart-Socket-EU-Plug-p-1288562.html?cur_warehouse=CN
                  0, 0, 0, 0,
            -     GPIO_LED1_INV,    // GPIO04 Red Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO04 Red Led (0 = On, 1 = Off) - Link and Power status
                  0,
                                    // GPIO06 (SD_CLK   Flash)
                                    // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT)
            @@ -1461,7 +1461,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_USER,        // GPIO01 Serial RXD
                  0,
                  GPIO_USER,        // GPIO03 Serial TXD
            -     GPIO_LED1,        // GPIO04 Blue LED
            +     GPIO_LED1,        // GPIO04 Blue LED - Link and Power status
                  GPIO_REL1,        // GPIO05 (Relay OFF, but used as Relay Switch)
                                    // GPIO06 (SD_CLK   Flash)
                                    // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT)
            @@ -1480,7 +1480,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,
                  GPIO_KEY1,        // GPIO01 Serial TXD and Button
                  0,
            -     GPIO_LED2_INV,    // GPIO03 Serial RXD and Red Led (0 = On, 1 = Off)
            +     GPIO_LED2_INV,    // GPIO03 Serial RXD and Red Led (0 = On, 1 = Off) - Power status
                  GPIO_HJL_CF,      // GPIO04 BL0937 or HJL-01 CF power
                  GPIO_NRG_CF1,     // GPIO05 BL0937 or HJL-01 CF1 current / voltage
                                    // GPIO06 (SD_CLK   Flash)
            @@ -1490,7 +1490,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage)
            -     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Blue Led (0 = On, 1 = Off) - Link status
                  GPIO_REL1,        // GPIO14 Relay (0 = Off, 1 = On)
                  0, 0, 0
               },
            @@ -1507,7 +1507,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage)
            -     GPIO_LED1_INV,    // GPIO13 LED (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 LED (0 = On, 1 = Off) - Link and Power status
                  GPIO_REL1,        // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On )
                  0, 0, 0
               },
            @@ -1534,7 +1534,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
               },
               { "Gosund SP1 v23",  // https://www.amazon.de/gp/product/B0777BWS1P
                  0,
            -     GPIO_LED1_INV,    // GPIO01 Serial RXD and LED1 (blue) inv
            +     GPIO_LED1_INV,    // GPIO01 Serial RXD and LED1 (blue) inv - Link status
                  0,
                  GPIO_KEY1,        // GPIO03 Serial TXD and Button
                  GPIO_HJL_CF,      // GPIO04 BL0937 or HJL-01 CF power
            @@ -1546,7 +1546,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage)
            -     GPIO_LED2_INV,    // GPIO13 LED2 (red) inv
            +     GPIO_LED2_INV,    // GPIO13 LED2 (red) inv - Power status
                  GPIO_REL1,        // GPIO14 Relay (0 = Off, 1 = On)
                  0, 0, 0
               },
            @@ -1584,8 +1584,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage)
            -     GPIO_LED2_INV,    // GPIO13 Red Led (0 = On, 1 = Off)
            -     GPIO_LED1_INV,    // GPIO14 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED2_INV,    // GPIO13 Red Led (0 = On, 1 = Off) - Power status
            +     GPIO_LED1_INV,    // GPIO14 Blue Led (0 = On, 1 = Off) - Link status
                  GPIO_REL1,        // GPIO15 Relay (0 = Off, 1 = On)
                  0, 0
               },
            @@ -1604,7 +1604,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_USER,
            -     GPIO_LED1,        // GPIO13 WiFi LED
            +     GPIO_LED1,        // GPIO13 WiFi LED - Link and Power status
                  GPIO_USER,
                  GPIO_USER,
                  GPIO_USER,
            @@ -1613,9 +1613,9 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
               { "Teckin US",       // Teckin SP20 US with Energy Monitoring
                                    // https://www.amazon.com/Outlet-Compatible-Monitoring-Function-Required/dp/B079Q5W22B
                                    // https://www.amazon.com/Outlet-ZOOZEE-Monitoring-Function-Compatible/dp/B07J2LR5KN
            -     GPIO_LED2_INV,    // GPIO00 Red Led (1 = On, 0 = Off)
            +     GPIO_LED2_INV,    // GPIO00 Red Led (1 = On, 0 = Off) - Power status
                  0,
            -     GPIO_LED1_INV,    // GPIO02 Blue Led (1 = On, 0 = Off)
            +     GPIO_LED1_INV,    // GPIO02 Blue Led (1 = On, 0 = Off) - Link status
                  0,
                  GPIO_REL1,        // GPIO04 Relay (0 = Off, 1 = On)
                  GPIO_HJL_CF,      // GPIO05 BL0937 or HJL-01 CF power
            @@ -1659,7 +1659,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
             
               { "KA10",            // SMANERGY KA10 (ESP8285 - BL0937 Energy Monitoring) - https://www.amazon.es/dp/B07MBTCH2Y
                  0,                // GPIO00
            -     GPIO_LED1_INV,    // GPIO01 Blue LED
            +     GPIO_LED1_INV,    // GPIO01 Blue LED - Link status
                  0,                // GPIO02
                  GPIO_KEY1,        // GPIO03 Button
                  GPIO_HJL_CF,      // GPIO04 BL0937 CF power
            @@ -1671,7 +1671,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage)
            -     GPIO_LED2,        // GPIO13 Red LED
            +     GPIO_LED2,        // GPIO13 Red LED - Power status
                  GPIO_REL1,        // GPIO14 Relay 1
                  0, 0, 0
               }
            @@ -1689,8 +1689,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO09 (SD_DATA2 Flash QIO or ESP8285)
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
            -     GPIO_LED1,        // GPIO12 Green LED
            -     GPIO_LED2,        // GPIO13 Red LED
            +     GPIO_LED1,        // GPIO12 Green LED - Link status
            +     GPIO_LED2,        // GPIO13 Red LED - Power status
                  0, 0, 0, 0
               }
             
            @@ -1698,7 +1698,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                                    // https://www.aliexpress.com/item/Magic-Home-Mini-RGB-RGBW-Wifi-Controller-For-Led-Strip-Panel-light-Timing-Function-16million-colors/32686853650.html
                  0,
                  GPIO_USER,        // GPIO01 Serial RXD and Optional sensor
            -     GPIO_LED1_INV,    // GPIO02 Blue onboard LED
            +     GPIO_LED1_INV,    // GPIO02 Blue onboard LED - Link and Power status
                  GPIO_USER,        // GPIO03 Serial TXD and Optional sensor
                  GPIO_USER,        // GPIO04 IR receiver (optional)
                  GPIO_PWM2,        // GPIO05 RGB LED Green
            @@ -1767,13 +1767,13 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_KEY1,        // GPIO12 Button
                  0, 0,
            -     GPIO_LED1,        // GPIO15 Led (1 = On, 0 = Off)
            +     GPIO_LED1,        // GPIO15 Led (1 = On, 0 = Off) - Link and Power status
                  0, 0
               }
             
               { "SMPW701E",        // SM-PW701E WLAN Socket (#1190)
                  0, 0, 0, 0,
            -     GPIO_LED1_INV,    // GPIO04 Blue Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO04 Blue Led (0 = On, 1 = Off) - Link and Power status
                  0,                // GPIO05 IR or RF receiver (optional)
                                    // GPIO06 (SD_CLK   Flash)
                                    // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT)
            @@ -1791,7 +1791,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_USER,        // GPIO01
                  0,
                  GPIO_USER,        // GPIO03
            -     GPIO_LED1_INV,    // GPIO04 Blue LED
            +     GPIO_LED1_INV,    // GPIO04 Blue LED - Link and Power status
                  GPIO_REL1,        // GPIO05 Red LED and relay
                                    // GPIO06 (SD_CLK   Flash)
                                    // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT)
            @@ -1807,7 +1807,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
             
               { "MagicHome v2.3",  // Magic Home (aka Flux-light) (ESP8266) (#1353)
                  0, 0,
            -     GPIO_LED1_INV,    // GPIO02 Blue onboard LED
            +     GPIO_LED1_INV,    // GPIO02 Blue onboard LED - Link and Power status
                  0,
                  GPIO_USER,        // GPIO04 IR receiver (optional)
                  GPIO_PWM2,        // GPIO05 RGB LED Green
            @@ -1855,7 +1855,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_REL1,        // GPIO12 Red Led and Relay (0 = Off, 1 = On)
            -     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off)
            +     GPIO_LED1_INV,    // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status
                  0, 0, 0, 0
               }
             
            
            From 9730df7adce9526d078a11545eeddec81ef5bfbf Mon Sep 17 00:00:00 2001
            From: Theo Arends <11044339+arendst@users.noreply.github.com>
            Date: Tue, 8 Jan 2019 14:22:45 +0100
            Subject: [PATCH 0824/2222] Fix exception 28 in display driver
            
            ---
             sonoff/xdrv_13_display.ino | 12 +++++++++---
             1 file changed, 9 insertions(+), 3 deletions(-)
            
            diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino
            index a3034bca2..fe9805af6 100644
            --- a/sonoff/xdrv_13_display.ino
            +++ b/sonoff/xdrv_13_display.ino
            @@ -785,14 +785,20 @@ void DisplayAnalyzeJson(char *topic, char *json)
                       if (value2.is()) {
                         JsonObject& Object3 = value2;
                         for (JsonObject::iterator it3 = Object3.begin(); it3 != Object3.end(); ++it3) {
            -              DisplayJsonValue(topic, it->key, it3->key, it3->value.as());  // Sensor 56%
            +              if (it3->value != NULL) {   // "DHT11":{"Temperature":null,"Humidity":null} - ignore as it will raise exception 28
            +                DisplayJsonValue(topic, it->key, it3->key, it3->value.as());  // Sensor 56%
            +              }
                         }
                       } else {
            -            DisplayJsonValue(topic, it->key, it2->key, it2->value.as());  // Sensor  56%
            +            if (it2->value != NULL) {   // "DHT11":{"Temperature":null,"Humidity":null} - ignore as it will raise exception 28
            +              DisplayJsonValue(topic, it->key, it2->key, it2->value.as());  // Sensor  56%
            +            }
                       }
                     }
                   } else {
            -        DisplayJsonValue(topic, it->key, it->key, it->value.as());  // Topic  56%
            +        if (it->value != NULL) {   // "DHT11":{"Temperature":null,"Humidity":null} - ignore as it will raise exception 28
            +          DisplayJsonValue(topic, it->key, it->key, it->value.as());  // Topic  56%
            +        }
                   }
                 }
               }
            
            From 53b8f1f877f7bf9ac535f448c8b1f6b0dd3cd8d8 Mon Sep 17 00:00:00 2001
            From: Theo Arends <11044339+arendst@users.noreply.github.com>
            Date: Tue, 8 Jan 2019 15:25:12 +0100
            Subject: [PATCH 0825/2222] Fix HAss Sensor Software Watchdog
            
            Fix Home Assistant Sensor Discovery Software Watchdog restart (#4831)
            ---
             sonoff/_changelog.ino             |  2 ++
             sonoff/xdrv_12_home_assistant.ino | 13 +++++++------
             2 files changed, 9 insertions(+), 6 deletions(-)
            
            diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino
            index 18af24ac2..1daabeaca 100644
            --- a/sonoff/_changelog.ino
            +++ b/sonoff/_changelog.ino
            @@ -1,6 +1,8 @@
             /* 6.4.1.8 20190107
              * Change sonoff_template.h layout regarding optional module flags like ADC0
              * Add command SetOption62 1 to force no Button/Switch pullup on dedicated modules. Currently only supported on Shelly2 (#4841)
            + * Fix Display exception 28 when JSON value is NULL received
            + * Fix Home Assistant Sensor Discovery Software Watchdog restart (#4831)
              *
              * 6.4.1.7 20190106
              * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6
            diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino
            index 59a7b519e..fd276bdcb 100644
            --- a/sonoff/xdrv_12_home_assistant.ino
            +++ b/sonoff/xdrv_12_home_assistant.ino
            @@ -128,7 +128,7 @@ const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM =
               "\"name\":\"%s\","
               "\"model\":\"%s\","
               "\"sw_version\":\"%s%s\","
            -  "\"manufacturer\":\"%s\"}";
            +  "\"manufacturer\":\"Tasmota\"}";
             
             const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM =
               "%s, \"~\":\"%s\"";
            @@ -239,7 +239,7 @@ void HAssAnnounceRelayLight(void)
                   }
                   snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data,
                              unique_id, ESP.getChipId(),
            -                 Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image, "Tasmota");
            +                 Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image);
                   snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix);
                   snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
                 }
            @@ -288,7 +288,7 @@ void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key,
             
                 snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data,
                            unique_id, ESP.getChipId(),
            -               Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image, "Tasmota");
            +               Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image);
                 if (strlen(prefix) > 0 ) snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix);
                 snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
               }
            @@ -307,7 +307,7 @@ void HAssAnnounceSwitches(void)
                   byte switch_present = 0;
                   byte toggle = 1;
             
            -      if ((pin[GPIO_SWT1 + switch_index] < 99) || (pin[GPIO_SWT1_NP + switch_index] < 99)) {
            +      if (pin[GPIO_SWT1 + switch_index] < 99) {
                     switch_present = 1;
                   }
             
            @@ -339,7 +339,7 @@ void HAssAnnounceButtons(void)
                   if (!button_index && ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module))) {
                     button_present = 1;
                   } else {
            -        if ((pin[GPIO_KEY1 + button_index] < 99) || (pin[GPIO_KEY1_NP + button_index] < 99)) {
            +        if (pin[GPIO_KEY1 + button_index] < 99) {
                       button_present = 1;
                     }
                   }
            @@ -413,7 +413,7 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype)
                 }
                 snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data,
                            unique_id, ESP.getChipId(),
            -               Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image, "Tasmota");
            +               Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image);
                 snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix);
                 snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
               }
            @@ -457,6 +457,7 @@ void HAssAnnounceSensors(void)
                     }
                   }
                 }
            +    yield();
               } while (hass_xsns_index != 0);
             }
             
            
            From efbc74b2a290bcf4ae7ae2526d55a4521a57b28a Mon Sep 17 00:00:00 2001
            From: Theo Arends <11044339+arendst@users.noreply.github.com>
            Date: Tue, 8 Jan 2019 15:58:35 +0100
            Subject: [PATCH 0826/2222] Add GPIOs to 12V DC Shelly 1
            
            Add user GPIOs to Shelly 1 only to be used when Shelly is connected to 12V DC (#4854)
            ---
             sonoff/sonoff_template.h | 5 ++++-
             1 file changed, 4 insertions(+), 1 deletion(-)
            
            diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h
            index 7346a3035..2ac21b2b3 100644
            --- a/sonoff/sonoff_template.h
            +++ b/sonoff/sonoff_template.h
            @@ -1377,7 +1377,10 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0, 0
               },
               { "Shelly 1",        // Shelly1 Open Source (ESP8266 - 2MB) - https://shelly.cloud/shelly1-open-source/
            -     0, 0, 0, 0,
            +     GPIO_USER,        // GPIO00 - Only to be used when Shelly is connected to 12V DC
            +     GPIO_USER,        // GPIO01 Serial RXD - Only to be used when Shelly is connected to 12V DC
            +     0,
            +     GPIO_USER,        // GPIO03 Serial TXD - Only to be used when Shelly is connected to 12V DC
                  GPIO_REL1,        // GPIO04 Relay (0 = Off, 1 = On)
                  GPIO_SWT1_NP,     // GPIO05 SW pin
                                    // GPIO06 (SD_CLK   Flash)
            
            From c5f68235700b4447198a9508b709c3e254676114 Mon Sep 17 00:00:00 2001
            From: Theo Arends <11044339+arendst@users.noreply.github.com>
            Date: Tue, 8 Jan 2019 16:27:16 +0100
            Subject: [PATCH 0827/2222] Add two modules
            
            * Add support for OBI Power Socket 2 (#4829)
            * Add support for YTF IR Bridge (#4855)
            ---
             sonoff/_changelog.ino    |  2 ++
             sonoff/sonoff_template.h | 57 +++++++++++++++++++++++++++-------------
             2 files changed, 41 insertions(+), 18 deletions(-)
            
            diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino
            index 1daabeaca..00e3701f4 100644
            --- a/sonoff/_changelog.ino
            +++ b/sonoff/_changelog.ino
            @@ -3,6 +3,8 @@
              * Add command SetOption62 1 to force no Button/Switch pullup on dedicated modules. Currently only supported on Shelly2 (#4841)
              * Fix Display exception 28 when JSON value is NULL received
              * Fix Home Assistant Sensor Discovery Software Watchdog restart (#4831)
            + * Add support for OBI Power Socket 2 (#4829)
            + * Add support for YTF IR Bridge (#4855)
              *
              * 6.4.1.7 20190106
              * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6
            diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h
            index 2ac21b2b3..761817e2a 100644
            --- a/sonoff/sonoff_template.h
            +++ b/sonoff/sonoff_template.h
            @@ -273,6 +273,8 @@ enum SupportedModules {
               PS_16_DZ,
               TECKIN_US,
               MANZOKU_EU_4,
            +  OBI2,
            +  YTF_IR_BRIDGE,
               MAXMODULE };
             
             /********************************************************************************************/
            @@ -544,6 +546,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
               SK03_TUYA,
               NEO_COOLCAM,        // Socket Relay Devices
               OBI,
            +  OBI2,
               MANZOKU_EU_4,
               ESP_SWITCH,         // Switch Devices
               TUYA_DIMMER,        // Dimmer Devices
            @@ -559,6 +562,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
               KMC_70011,
               AILIGHT,            // Light Bulbs
               PHILIPS,
            +  YTF_IR_BRIDGE,
               WITTY,              // Development Devices
               WEMOS
             };
            @@ -1654,6 +1658,41 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,
                  GPIO_USER,        // GPIO16
                  0
            +  },
            +  { "OBI Socket 2",    // OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko-2-stueck-weiss/p/4077673
            +     0,                // GPIO00
            +     0,                // GPIO01 Serial RXD
            +     0,
            +     0,                // GPIO03 Serial TXD
            +     GPIO_REL1,        // GPIO04 Relay 1
            +     GPIO_KEY1,        // GPIO05 Button
            +                       // GPIO06 (SD_CLK   Flash)
            +                       // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT)
            +                       // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT)
            +     0,                // GPIO09 (SD_DATA2 Flash QIO or ESP8285)
            +     0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
            +                       // GPIO11 (SD_CMD   Flash)
            +     GPIO_LED1,        // GPIO12 Green LED - Link status
            +     GPIO_LED2,        // GPIO13 Red LED - Power status
            +     0, 0, 0, 0
            +  },
            +  { "YTF IR Bridge",   // https://www.aliexpress.com/item/Tuya-universal-Smart-IR-Hub-remote-control-Voice-Control-AC-TV-Work-With-Alexa-Google-Home/32951202513.html
            +     GPIO_USER,        // GPIO00
            +     GPIO_USER,        // GPIO01 Serial RXD
            +     GPIO_USER,        // GPIO02
            +     GPIO_USER,        // GPIO03 Serial TXD
            +     GPIO_LED1_INV,    // GPIO04 Blue Led - Link status
            +     GPIO_IRRECV,      // GPIO05 IR Receiver
            +                       // GPIO06 (SD_CLK   Flash)
            +                       // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT)
            +                       // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT)
            +     0,                // GPIO09 (SD_DATA2 Flash QIO or ESP8285)
            +     0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
            +                       // GPIO11 (SD_CMD   Flash)
            +     0,                // GPIO12
            +     GPIO_KEY1,        // GPIO13 Button
            +     GPIO_IRSEND,      // GPIO14 IR Transmitter
            +     0, 0, 0
               }
             };
             
            @@ -1679,24 +1718,6 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0, 0, 0
               }
             
            -  { "OBI Socket 2",    // OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko-2-stueck-weiss/p/4077673
            -     0,                // GPIO00
            -     0,                // GPIO01 Serial RXD
            -     0,
            -     0,                // GPIO03 Serial TXD
            -     GPIO_REL1,        // GPIO04 Relay 1
            -     GPIO_KEY1,        // GPIO05 Button
            -                       // GPIO06 (SD_CLK   Flash)
            -                       // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT)
            -                       // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT)
            -     0,                // GPIO09 (SD_DATA2 Flash QIO or ESP8285)
            -     0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
            -                       // GPIO11 (SD_CMD   Flash)
            -     GPIO_LED1,        // GPIO12 Green LED - Link status
            -     GPIO_LED2,        // GPIO13 Red LED - Power status
            -     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,
            
            From 549080b8509e8e17b6eb7e718ab1089f0eee66a3 Mon Sep 17 00:00:00 2001
            From: andrethomas 
            Date: Tue, 8 Jan 2019 20:53:09 +0200
            Subject: [PATCH 0828/2222] PN532: Add Read/Write Data support
            
            ---
             sonoff/my_user_config.h      |   3 +-
             sonoff/xsns_40_pn532_i2c.ino | 209 ++++++++++++++++++++++++++++++++++-
             2 files changed, 206 insertions(+), 6 deletions(-)
            
            diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h
            index 4f7c97dc8..73ccb9669 100644
            --- a/sonoff/my_user_config.h
            +++ b/sonoff/my_user_config.h
            @@ -322,7 +322,8 @@
             //  #define USE_DS3231                             // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code)
             //    #define USE_RTC_ADDR  0x68                   // Default I2C address 0x68
             //  #define USE_MGC3130                            // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem)
            -//  #define USE_PN532_I2C                          // Enable PN532 - Near Field Communication (NFC) controller (+1k6 code)
            +//  #define USE_PN532_I2C                          // Enable PN532 - Near Field Communication (NFC) controller (+3k3 code, 508 bytes of mem)
            +//    #define USE_PN532_CAUSE_EVENTS               // Enable PN532 driver to cause event's on card read in addition to immediate telemetry
             
             //  #define USE_DISPLAY                            // Add I2C Display Support (+2k code)
                 #define USE_DISPLAY_MODES1TO5                // Enable display mode 1 to 5 in addition to mode 0
            diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino
            index 787f48faa..853faefef 100644
            --- a/sonoff/xsns_40_pn532_i2c.ino
            +++ b/sonoff/xsns_40_pn532_i2c.ino
            @@ -34,8 +34,14 @@
             
             #define PN532_COMMAND_GETFIRMWAREVERSION  0x02
             #define PN532_COMMAND_SAMCONFIGURATION    0x14
            +#define PN532_COMMAND_INDATAEXCHANGE      0x40
             #define PN532_COMMAND_INLISTPASSIVETARGET 0x4A
             
            +#define MIFARE_CMD_READ                   0x30
            +#define MIFARE_CMD_AUTH_A                 0x60
            +#define MIFARE_CMD_AUTH_B                 0x61
            +#define MIFARE_CMD_WRITE                  0xA0
            +
             #define PN532_PREAMBLE                    0x00
             #define PN532_STARTCODE1                  0x00
             #define PN532_STARTCODE2                  0xFF
            @@ -56,6 +62,8 @@ uint8_t pn532_i2c_packetbuffer[64];
             uint8_t pn532_i2c_scan_defer_report = 0;         // If a valid card was found we will not scan for one again in the same two seconds so we set this to 19 if a card was found
             uint8_t pn532_i2c_command = 0;
             uint8_t pn532_i2c_disable = 0;
            +uint8_t pn532_i2c_function = 0;
            +uint8_t pn532_i2c_newdata[16];
             
             const uint8_t PROGMEM pn532_global_timeout = 10;
             
            @@ -227,8 +235,8 @@ bool PN532_SAMConfig(void)
             {
                 pn532_i2c_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
                 pn532_i2c_packetbuffer[1] = 0x01; // normal mode;
            -    pn532_i2c_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
            -    pn532_i2c_packetbuffer[3] = 0x01; // use IRQ pin!
            +    pn532_i2c_packetbuffer[2] = 0x01; // timeout 50ms * 1 = 50ms
            +    pn532_i2c_packetbuffer[3] = 0x01; // Disable IRQ pin
             
                 if (PN532_writeCommand(pn532_i2c_packetbuffer, 4))
                     return false;
            @@ -277,26 +285,170 @@ boolean PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *u
               return true;
             }
             
            +uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData)
            +{
            +    uint8_t i;
            +    uint8_t _key[6];
            +    uint8_t _uid[7];
            +    uint8_t _uidLen;
            +
            +    // Hang on to the key and uid data
            +    memcpy (_key, keyData, 6);
            +    memcpy (_uid, uid, uidLen);
            +    _uidLen = uidLen;
            +
            +    // Prepare the authentication command //
            +    pn532_i2c_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;   /* Data Exchange Header */
            +    pn532_i2c_packetbuffer[1] = 1;                              /* Max card numbers */
            +    pn532_i2c_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
            +    pn532_i2c_packetbuffer[3] = blockNumber;                    /* Block Number (1K = 0..63, 4K = 0..255 */
            +    memcpy (&pn532_i2c_packetbuffer[4], _key, 6);
            +    for (i = 0; i < _uidLen; i++) {
            +        pn532_i2c_packetbuffer[10 + i] = _uid[i];              /* 4 bytes card ID */
            +    }
            +
            +    if (PN532_writeCommand(pn532_i2c_packetbuffer, 10 + _uidLen))
            +        return 0;
            +
            +    // Read the response packet
            +    PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer));
            +
            +    // Check if the response is valid and we are authenticated???
            +    // for an auth success it should be bytes 5-7: 0xD5 0x41 0x00
            +    // Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good
            +    if (pn532_i2c_packetbuffer[0] != 0x00) {
            +        // Authentification failed
            +        return 0;
            +    }
            +
            +    return 1;
            +}
            +
            +uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data)
            +{
            +    /* Prepare the command */
            +    pn532_i2c_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
            +    pn532_i2c_packetbuffer[1] = 1;                      /* Card number */
            +    pn532_i2c_packetbuffer[2] = MIFARE_CMD_READ;        /* Mifare Read command = 0x30 */
            +    pn532_i2c_packetbuffer[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */
            +
            +    /* Send the command */
            +    if (PN532_writeCommand(pn532_i2c_packetbuffer, 4)) {
            +        return 0;
            +    }
            +
            +    /* Read the response packet */
            +    PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer));
            +
            +    /* If byte 8 isn't 0x00 we probably have an error */
            +    if (pn532_i2c_packetbuffer[0] != 0x00) {
            +        return 0;
            +    }
            +
            +    /* Copy the 16 data bytes to the output buffer        */
            +    /* Block content starts at byte 9 of a valid response */
            +    memcpy (data, &pn532_i2c_packetbuffer[1], 16);
            +
            +    return 1;
            +}
            +
            +uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data)
            +{
            +    /* Prepare the first command */
            +    pn532_i2c_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
            +    pn532_i2c_packetbuffer[1] = 1;                      /* Card number */
            +    pn532_i2c_packetbuffer[2] = MIFARE_CMD_WRITE;       /* Mifare Write command = 0xA0 */
            +    pn532_i2c_packetbuffer[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */
            +    memcpy(&pn532_i2c_packetbuffer[4], data, 16);       /* Data Payload */
            +
            +    /* Send the command */
            +    if (PN532_writeCommand(pn532_i2c_packetbuffer, 20)) {
            +        return 0;
            +    }
            +
            +    /* Read the response packet */
            +    return (0 < PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)));
            +}
            +
            +
             void PN532_ScanForTag(void)
             {
               if (pn532_i2c_disable) { return; }
               uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
               uint8_t uid_len = 0;
            +  uint8_t card_data[16];
            +  boolean erase_success = false;
            +  boolean set_success = false;
               if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) {
                 if (pn532_i2c_scan_defer_report > 0) {
                   pn532_i2c_scan_defer_report--;
                 } else {
                   char uids[15];
            +      char card_datas[34];
                   sprintf(uids,"");
                   for (uint8_t i = 0;i < uid_len;i++) {
                     sprintf(uids,"%s%02X",uids,uid[i]);
                   }
            +      if (uid_len == 4) { // Lets try to read block 0 of the mifare classic card for more information
            +        uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
            +        if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) {
            +          if (mifareclassic_ReadDataBlock(1, card_data)) {
            +            memcpy(&card_datas,card_data,sizeof(card_data)); // Cast block 0 to a string
            +          }
            +          if (pn532_i2c_function == 1) { // erase block 1 of card
            +            for (uint8_t i = 0;i<16;i++) {
            +              card_data[i] = 0x00;
            +            }
            +            if (mifareclassic_WriteDataBlock(1, card_data)) {
            +              erase_success = true;
            +              snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Erase success");
            +              AddLog(LOG_LEVEL_INFO);
            +              memcpy(&card_datas,card_data,sizeof(card_data)); // Cast block 0 to a string
            +            }
            +          }
            +          if (pn532_i2c_function == 2) {
            +            memcpy(&card_data,&pn532_i2c_newdata,sizeof(card_data));
            +            if (mifareclassic_WriteDataBlock(1, card_data)) {
            +              set_success = true;
            +              snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful");
            +              AddLog(LOG_LEVEL_INFO);
            +              memcpy(&card_datas,card_data,sizeof(card_data)); // Cast block 0 to a string
            +            }
            +          }
            +        } else {
            +          sprintf(card_datas,"AUTHFAIL");
            +        }
            +      }
            +      switch (pn532_i2c_function) {
            +        case 0x01:
            +          if (!erase_success) {
            +            snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Erase fail - exiting erase mode");
            +            AddLog(LOG_LEVEL_INFO);
            +          }
            +          break;
            +        case 0x02:
            +          if (!set_success) {
            +            snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Write failed - exiting set mode");
            +            AddLog(LOG_LEVEL_INFO);
            +          }
            +        default:
            +          break;
            +      }
            +      pn532_i2c_function = 0;
                   snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
            -      snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids);
            +      snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), mqtt_data, uids, card_datas);
                   MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
            -      char command[27];
            -      sprintf(command,"event PN532=%s",uids);
            +
            +#ifdef USE_PN532_CAUSE_EVENTS      
            +
            +      char command[64];
            +      sprintf(command,"event PN532_UID=%s",uids);
                   ExecuteCommand(command, SRC_RULE);
            +      sprintf(command,"event PN532_DATA=%s",card_datas);
            +      ExecuteCommand(command, SRC_RULE);
            +
            +#endif
            +      
                   pn532_i2c_scan_defer_report = 7; // Ignore tags found for two seconds
                 }
               } else {
            @@ -304,6 +456,48 @@ void PN532_ScanForTag(void)
               }
             }
             
            +boolean PN532_Command(void)
            +{
            +  boolean serviced = true;
            +  uint8_t paramcount = 0;
            +  if (XdrvMailbox.data_len > 0) {
            +    paramcount=1;
            +  } else {
            +    serviced = false;
            +    return serviced;
            +  }
            +  char sub_string[XdrvMailbox.data_len];
            +  char sub_string_tmp[XdrvMailbox.data_len];
            +  for (uint8_t ca=0;ca 1) {
            +      sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2));
            +      uint8_t dlen = strlen(sub_string_tmp);
            +      if (dlen > 15) { dlen = 15; }
            +      memcpy(&pn532_i2c_newdata,&sub_string_tmp,dlen);
            +      pn532_i2c_newdata[dlen] = 0x00; // Null terminate the string
            +      pn532_i2c_function = 2;
            +      snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Next scanned tag data block 1 will be set to '%s'",pn532_i2c_newdata);
            +      AddLog(LOG_LEVEL_INFO);
            +      snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
            +      snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"S\"\"}}"), mqtt_data);
            +      return serviced;
            +    }
            +  }
            +}
            +
             /*********************************************************************************************\
              * Interface
             \*********************************************************************************************/
            @@ -322,6 +516,11 @@ boolean Xsns40(byte function)
                   case FUNC_EVERY_SECOND:
                     PN532_Detect();
                     break;
            +      case FUNC_COMMAND:
            +        if (XSNS_40 == XdrvMailbox.index) {
            +          result = PN532_Command();
            +        }
            +        break;
                   case FUNC_SAVE_BEFORE_RESTART:
                     if (!pn532_i2c_disable) {
                       pn532_i2c_disable = 1;
            
            From 4f568fc36564b36fd087ee99b132a7b9ffb4c594 Mon Sep 17 00:00:00 2001
            From: Andre Thomas 
            Date: Tue, 8 Jan 2019 21:15:14 +0200
            Subject: [PATCH 0829/2222] Update xsns_40_pn532_i2c.ino
            
            ---
             sonoff/xsns_40_pn532_i2c.ino | 2 +-
             1 file changed, 1 insertion(+), 1 deletion(-)
            
            diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino
            index 853faefef..1c4a193e1 100644
            --- a/sonoff/xsns_40_pn532_i2c.ino
            +++ b/sonoff/xsns_40_pn532_i2c.ino
            @@ -236,7 +236,7 @@ bool PN532_SAMConfig(void)
                 pn532_i2c_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
                 pn532_i2c_packetbuffer[1] = 0x01; // normal mode;
                 pn532_i2c_packetbuffer[2] = 0x01; // timeout 50ms * 1 = 50ms
            -    pn532_i2c_packetbuffer[3] = 0x01; // Disable IRQ pin
            +    pn532_i2c_packetbuffer[3] = 0x00; // Disable IRQ pin
             
                 if (PN532_writeCommand(pn532_i2c_packetbuffer, 4))
                     return false;
            
            From 15041873c2cbdf987098f1c8f61cd2f5bed805ac Mon Sep 17 00:00:00 2001
            From: blittan 
            Date: Tue, 8 Jan 2019 22:12:09 +0100
            Subject: [PATCH 0830/2222] Clearer meaning of Static or DHCP
            
            ---
             sonoff/my_user_config.h              | 2 +-
             sonoff/user_config_override_sample.h | 2 +-
             2 files changed, 2 insertions(+), 2 deletions(-)
            
            diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h
            index 4f7c97dc8..dd06af48d 100644
            --- a/sonoff/my_user_config.h
            +++ b/sonoff/my_user_config.h
            @@ -56,7 +56,7 @@
             #define SAVE_STATE             1                 // [SetOption0] Save changed power state to Flash (0 = disable, 1 = enable)
             
             // -- Wifi ----------------------------------------
            -#define WIFI_IP_ADDRESS        "0.0.0.0"         // [IpAddress1] Set to 0.0.0.0 for using DHCP or IP address
            +#define WIFI_IP_ADDRESS        "0.0.0.0"         // [IpAddress1] Set to 0.0.0.0 for using DHCP or enter a static IP address
             #define WIFI_GATEWAY           "192.168.1.1"     // [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.1.1"     // [IpAddress4] If not using DHCP set DNS IP address (might be equal to WIFI_GATEWAY)
            diff --git a/sonoff/user_config_override_sample.h b/sonoff/user_config_override_sample.h
            index 678ad922e..b2b403e1a 100644
            --- a/sonoff/user_config_override_sample.h
            +++ b/sonoff/user_config_override_sample.h
            @@ -74,7 +74,7 @@ Examples :
             
             #ifdef MY_IP
             #undef  WIFI_IP_ADDRESS
            -#define WIFI_IP_ADDRESS   MY_IP                  // Set to 0.0.0.0 for using DHCP or IP address
            +#define WIFI_IP_ADDRESS   MY_IP                  // Set to 0.0.0.0 for using DHCP or enter a static IP address
             #endif
             
             #ifdef MY_GW
            
            From faa3e9a741ff58a63f5eabc4c2bcc0cd0e8c1cb0 Mon Sep 17 00:00:00 2001
            From: blittan 
            Date: Tue, 8 Jan 2019 23:05:54 +0100
            Subject: [PATCH 0831/2222] Updated Swedish translation
            
            ---
             sonoff/language/sv-SE.h | 54 ++++++++++++++++++++---------------------
             1 file changed, 27 insertions(+), 27 deletions(-)
            
            diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h
            index c36440ac7..21246a8f3 100644
            --- a/sonoff/language/sv-SE.h
            +++ b/sonoff/language/sv-SE.h
            @@ -132,11 +132,11 @@
             #define D_PROGRAM_FLASH_SIZE "Program-flashstorlek"
             #define D_PROGRAM_SIZE "Programstorlek"
             #define D_PROJECT "Projekt"
            -#define D_RAIN "Rain"
            +#define D_RAIN "Regn"
             #define D_RECEIVED "Mottagen"
             #define D_RESTART "Omstart"
             #define D_RESTARTING "Startar om"
            -#define D_RESTART_REASON "Restart Reason"
            +#define D_RESTART_REASON "Omstartsorsak"
             #define D_RESTORE "återställ"
             #define D_RETAINED "bevarad"
             #define D_RULE "Regel"
            @@ -168,13 +168,13 @@
             #define D_UV_INDEX_2 "Med"
             #define D_UV_INDEX_3 "Hög"
             #define D_UV_INDEX_4 "Farligt"
            -#define D_UV_INDEX_5 "BurnL1/2"
            -#define D_UV_INDEX_6 "BurnL3"
            -#define D_UV_INDEX_7 "OoR"         // Out of Range
            +#define D_UV_INDEX_5 "Skadligt"
            +#define D_UV_INDEX_6 "Extremt"
            +#define D_UV_INDEX_7 "UO"         // Out of Range
             #define D_UV_LEVEL "UV nivå"
             #define D_UV_POWER "UV kraft"
             #define D_VERSION "Version"
            -#define D_VOLTAGE "Voltage"
            +#define D_VOLTAGE "Volttal"
             #define D_WEIGHT "Vikt"
             #define D_WARMLIGHT "Varm"
             #define D_WEB_SERVER "Webbserver"
            @@ -197,7 +197,7 @@
             #define D_WPS_FAILED_WITH_STATUS "WPS-konfigurering MISSLYCKADES med status"
             #define D_ACTIVE_FOR_3_MINUTES "aktiv för 3 minuter"
             #define D_FAILED_TO_START "misslyckades att starta"
            -#define D_PATCH_ISSUE_2186 "Patch issue 2186"
            +#define D_PATCH_ISSUE_2186 "Laga problem 2186"
             #define D_CONNECTING_TO_AP "Ansluter till AP"
             #define D_IN_MODE "i läge"
             #define D_CONNECT_FAILED_NO_IP_ADDRESS "Anslutning misslyckades mottog ingen IP-adress"
            @@ -253,7 +253,7 @@
             
             #define D_MODULE_PARAMETERS "Modulparameterar"
             #define D_MODULE_TYPE "Modultyp"
            -#define D_PULLUP_ENABLE "No Button/Switch pull-up"
            +#define D_PULLUP_ENABLE "Ingen knapp/brytare pull-up"
             #define D_GPIO "GPIO"
             #define D_SERIAL_IN "Seriell in"
             #define D_SERIAL_OUT "Seriell ut"
            @@ -281,7 +281,7 @@
             #define D_LOGGING_PARAMETERS "Loggningsparametrar"
             #define D_SERIAL_LOG_LEVEL "Seriell loggnivå"
             #define D_WEB_LOG_LEVEL "Webb loggnivå"
            -#define D_SYS_LOG_LEVEL "Syslog-nivp"
            +#define D_SYS_LOG_LEVEL "Syslog-nivå"
             #define D_MORE_DEBUG "Mer debugging"
             #define D_SYSLOG_HOST "Syslog-värd"
             #define D_SYSLOG_PORT "Syslog-port"
            @@ -301,8 +301,8 @@
             #define D_CONFIGURATION_RESET "Konfiguration nollställd"
             
             #define D_PROGRAM_VERSION "Programversion"
            -#define D_BUILD_DATE_AND_TIME "Build datum & tid"
            -#define D_CORE_AND_SDK_VERSION "Core/SDK Version"
            +#define D_BUILD_DATE_AND_TIME "Kompilerings datum & tid"
            +#define D_CORE_AND_SDK_VERSION "Core/SDK version"
             #define D_FLASH_WRITE_COUNT "Flash-skrivningsräknare"
             #define D_MAC_ADDRESS "MAC-adress"
             #define D_MQTT_HOST "MQTT-värd"
            @@ -339,11 +339,11 @@
             #define D_UPLOAD_ERR_11 "Misslyckades rensa RF chip"
             #define D_UPLOAD_ERR_12 "Misslyckades skriva till RF chip"
             #define D_UPLOAD_ERR_13 "Misslyckades avkoda RF firmware"
            -#define D_UPLOAD_ERROR_CODE "Upladdningsfelkod"
            +#define D_UPLOAD_ERROR_CODE "Uppladdningsfelkod"
             
             #define D_ENTER_COMMAND "Ange kommando"
            -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Aktivera weblog 2 om svar förväntas"
            -#define D_NEED_USER_AND_PASSWORD "Behöver användarnamn=&lösenord="
            +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Aktivera webblogg 2 om svar förväntas"
            +#define D_NEED_USER_AND_PASSWORD "Behöver user=&password="
             
             // xdrv_01_mqtt.ino
             #define D_FINGERPRINT "Verifierar TLS fingeravtryck..."
            @@ -392,14 +392,14 @@
             
             // xdrv_09_timers.ino
             #define D_CONFIGURE_TIMER "Konfigurera timer"
            -#define D_TIMER_PARAMETERS "timerparametrar"
            +#define D_TIMER_PARAMETERS "Timerparametrar"
             #define D_TIMER_ENABLE "Aktivera timer"
             #define D_TIMER_ARM "Aktivera"
             #define D_TIMER_TIME "Tid"
             #define D_TIMER_DAYS "Dagar"
             #define D_TIMER_REPEAT "Repetera"
            -#define D_TIMER_OUTPUT "Output"
            -#define D_TIMER_ACTION "Action"
            +#define D_TIMER_OUTPUT "Utgång"
            +#define D_TIMER_ACTION "Åtgärd"
             
             // xdrv_10_knx.ino
             #define D_CONFIGURE_KNX "Konfigurera KNX"
            @@ -477,9 +477,9 @@
             #define D_TX20_WIND_SPEED_AVG "Vindstyrka medel"
             #define D_TX20_WIND_SPEED_MAX "Vindstyrka max"
             #define D_TX20_NORTH "N"
            -#define D_TX20_EAST "E"
            +#define D_TX20_EAST "Ö"
             #define D_TX20_SOUTH "S"
            -#define D_TX20_WEST "W"
            +#define D_TX20_WEST "V"
             
             // sonoff_template.h
             #define D_SENSOR_NONE     "Ingen"
            @@ -549,8 +549,8 @@
             #define D_UNIT_AMPERE "A"
             #define D_UNIT_CENTIMETER "cm"
             #define D_UNIT_HERTZ "Hz"
            -#define D_UNIT_HOUR "Hr"
            -#define D_UNIT_INCREMENTS "inc"
            +#define D_UNIT_HOUR "Tim"
            +#define D_UNIT_INCREMENTS "ink"
             #define D_UNIT_KILOGRAM "kg"
             #define D_UNIT_KILOMETER_PER_HOUR "km/h"  // or "km/h"
             #define D_UNIT_KILOOHM "kOhm"
            @@ -603,12 +603,12 @@
             #define D_LOG_WIFI "WIF: "         // Wifi
             
             //SDM220
            -#define D_PHASE_ANGLE     "Phase Angle"
            -#define D_IMPORT_ACTIVE   "Import Active"
            -#define D_EXPORT_ACTIVE   "Export Active"
            -#define D_IMPORT_REACTIVE "Import Reactive"
            -#define D_EXPORT_REACTIVE "Export Reactive"
            -#define D_TOTAL_REACTIVE  "Total Reactive"
            +#define D_PHASE_ANGLE     "Fasvinkel"
            +#define D_IMPORT_ACTIVE   "Import aktiv"
            +#define D_EXPORT_ACTIVE   "Export aktiv"
            +#define D_IMPORT_REACTIVE "Import reaktiv"
            +#define D_EXPORT_REACTIVE "Export reaktiv"
            +#define D_TOTAL_REACTIVE  "Total reaktiv"
             #define D_UNIT_KWARH      "kVArh"
             #define D_UNIT_ANGLE      "Deg"
             
            
            From b7f361ebbfdbabd3dabb593a90b64af0f73a9473 Mon Sep 17 00:00:00 2001
            From: Andre Thomas 
            Date: Wed, 9 Jan 2019 12:29:12 +0200
            Subject: [PATCH 0832/2222] PN532: Queue events through backlog
            
            ---
             sonoff/xsns_40_pn532_i2c.ino | 8 +++-----
             1 file changed, 3 insertions(+), 5 deletions(-)
            
            diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino
            index 1c4a193e1..b02c68591 100644
            --- a/sonoff/xsns_40_pn532_i2c.ino
            +++ b/sonoff/xsns_40_pn532_i2c.ino
            @@ -441,12 +441,10 @@ void PN532_ScanForTag(void)
             
             #ifdef USE_PN532_CAUSE_EVENTS      
             
            -      char command[64];
            -      sprintf(command,"event PN532_UID=%s",uids);
            +      char command[71];
            +      sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas);
                   ExecuteCommand(command, SRC_RULE);
            -      sprintf(command,"event PN532_DATA=%s",card_datas);
            -      ExecuteCommand(command, SRC_RULE);
            -
            +      
             #endif
                   
                   pn532_i2c_scan_defer_report = 7; // Ignore tags found for two seconds
            
            From b69f173706a15d92c9df18dad18e30b6e770c6f8 Mon Sep 17 00:00:00 2001
            From: Theo Arends <11044339+arendst@users.noreply.github.com>
            Date: Wed, 9 Jan 2019 14:14:55 +0100
            Subject: [PATCH 0833/2222] Fix display t (time) and add T (date)
            
            Fix display t (time) and add T (date)
            ---
             sonoff/xdrv_13_display.ino | 13 +++++++++----
             1 file changed, 9 insertions(+), 4 deletions(-)
            
            diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino
            index fe9805af6..b15fed5e5 100644
            --- a/sonoff/xdrv_13_display.ino
            +++ b/sonoff/xdrv_13_display.ino
            @@ -427,13 +427,18 @@ void DisplayText(void)
                         cp += var;
                         DisplayDrawFilledRectangle(disp_xpos, disp_ypos, temp, temp1, color);
                         break;
            -          case 't': {
            +          case 't':
                         if (dp < (linebuf + DISPLAY_BUFFER_COLS) -5) {
            -              snprintf_P(dp, 5, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute);
            +              snprintf_P(dp, 6, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute);
                           dp += 5;
                         }
                         break;
            -          }
            +          case 'T':
            +            if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) {
            +              snprintf_P(dp, 9, PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year%2000);
            +              dp += 8;
            +            }
            +            break;
                       case 'd':
                         // force draw grafics buffer
                         DisplayDrawFrame();
            @@ -465,7 +470,7 @@ void DisplayText(void)
                         break;
                     }
                   }
            -    }
            +    } 
               }
               exit:
               // now draw buffer
            
            From 24fd7653eb3930e61e4000a2727fc1408731fab7 Mon Sep 17 00:00:00 2001
            From: Theo Arends <11044339+arendst@users.noreply.github.com>
            Date: Wed, 9 Jan 2019 14:56:16 +0100
            Subject: [PATCH 0834/2222] Fix missed JSON sensors
            
            Fix missed JSON sensors in DisplayMode > 0
            ---
             sonoff/xdrv_13_display.ino | 17 ++++++++++-------
             1 file changed, 10 insertions(+), 7 deletions(-)
            
            diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino
            index b15fed5e5..b5545e256 100644
            --- a/sonoff/xdrv_13_display.ino
            +++ b/sonoff/xdrv_13_display.ino
            @@ -470,7 +470,7 @@ void DisplayText(void)
                         break;
                     }
                   }
            -    } 
            +    }
               }
               exit:
               // now draw buffer
            @@ -790,19 +790,22 @@ void DisplayAnalyzeJson(char *topic, char *json)
                       if (value2.is()) {
                         JsonObject& Object3 = value2;
                         for (JsonObject::iterator it3 = Object3.begin(); it3 != Object3.end(); ++it3) {
            -              if (it3->value != NULL) {   // "DHT11":{"Temperature":null,"Humidity":null} - ignore as it will raise exception 28
            -                DisplayJsonValue(topic, it->key, it3->key, it3->value.as());  // Sensor 56%
            +              const char* value = it3->value;
            +              if (value != nullptr) {  // "DHT11":{"Temperature":null,"Humidity":null} - ignore null as it will raise exception 28
            +                DisplayJsonValue(topic, it->key, it3->key, value);  // Sensor 56%
                           }
                         }
                       } else {
            -            if (it2->value != NULL) {   // "DHT11":{"Temperature":null,"Humidity":null} - ignore as it will raise exception 28
            -              DisplayJsonValue(topic, it->key, it2->key, it2->value.as());  // Sensor  56%
            +            const char* value = it2->value;
            +            if (value != nullptr) {
            +              DisplayJsonValue(topic, it->key, it2->key, value);  // Sensor  56%
                         }
                       }
                     }
                   } else {
            -        if (it->value != NULL) {   // "DHT11":{"Temperature":null,"Humidity":null} - ignore as it will raise exception 28
            -          DisplayJsonValue(topic, it->key, it->key, it->value.as());  // Topic  56%
            +        const char* value = it->value;
            +        if (value != nullptr) {
            +          DisplayJsonValue(topic, it->key, it->key, value);  // Topic  56%
                     }
                   }
                 }
            
            From fa5711eaaa79ec47a1981c8b1ecfbd3321e3ce0b Mon Sep 17 00:00:00 2001
            From: Theo Arends <11044339+arendst@users.noreply.github.com>
            Date: Wed, 9 Jan 2019 15:32:43 +0100
            Subject: [PATCH 0835/2222] Update ArduinoJson to 5.13.4
            
            Update ArduinoJson to 5.13.4
            ---
             lib/ArduinoJson-5.11.2/ArduinoJson.h          |   8 -
             lib/ArduinoJson-5.11.2/README.md              | 130 -------
             .../JsonHttpClient/JsonHttpClient.ino         | 184 ----------
             .../examples/JsonServer/JsonServer.ino        |  76 -----
             .../examples/JsonUdpBeacon/JsonUdpBeacon.ino  |  57 ----
             lib/ArduinoJson-5.11.2/library.properties     |   9 -
             lib/ArduinoJson-5.11.2/src/ArduinoJson.h      |  12 -
             .../src/ArduinoJson/Data/ValueSetter.hpp      |  51 ---
             .../src/ArduinoJson/Polyfills/isInteger.hpp   |  22 --
             .../src/ArduinoJson/RawJson.hpp               |  23 --
             .../TypeTraits/IsSignedIntegral.hpp           |  33 --
             .../TypeTraits/IsUnsignedIntegral.hpp         |  33 --
             lib/ArduinoJson-5.13.4/ArduinoJson.h          |   5 +
             .../CHANGELOG.md                              | 317 ++++++++----------
             .../LICENSE.md                                |   2 +-
             lib/ArduinoJson-5.13.4/README.md              | 110 ++++++
             .../JsonConfigFile/JsonConfigFile.ino         | 144 ++++++++
             .../JsonGeneratorExample.ino                  |  29 +-
             .../JsonHttpClient/JsonHttpClient.ino         | 112 +++++++
             .../JsonParserExample/JsonParserExample.ino   |  31 +-
             .../examples/JsonServer/JsonServer.ino        | 109 ++++++
             .../examples/JsonUdpBeacon/JsonUdpBeacon.ino  | 101 ++++++
             .../ProgmemExample/ProgmemExample.ino         |  38 ++-
             .../examples/StringExample/StringExample.ino  |  33 +-
             .../keywords.txt                              |   0
             lib/ArduinoJson-5.13.4/library.properties     |  11 +
             lib/ArduinoJson-5.13.4/src/ArduinoJson.h      |  17 +
             .../src/ArduinoJson.hpp                       |   9 +-
             .../src/ArduinoJson/Configuration.hpp         |  10 +-
             .../src/ArduinoJson/Data/Encoding.hpp         |   7 +-
             .../ArduinoJson/Data/JsonBufferAllocated.hpp  |   7 +-
             .../src/ArduinoJson/Data/JsonFloat.hpp        |   7 +-
             .../src/ArduinoJson/Data/JsonInteger.hpp      |   7 +-
             .../src/ArduinoJson/Data/JsonVariantAs.hpp    |   7 +-
             .../ArduinoJson/Data/JsonVariantContent.hpp   |   7 +-
             .../ArduinoJson/Data/JsonVariantDefault.hpp   |   7 +-
             .../src/ArduinoJson/Data/JsonVariantType.hpp  |   7 +-
             .../src/ArduinoJson/Data/List.hpp             |   7 +-
             .../ArduinoJson/Data/ListConstIterator.hpp    |   7 +-
             .../src/ArduinoJson/Data/ListIterator.hpp     |   7 +-
             .../src/ArduinoJson/Data/ListNode.hpp         |   7 +-
             .../src/ArduinoJson/Data/NonCopyable.hpp      |   7 +-
             .../src/ArduinoJson/Data/ReferenceType.hpp    |   7 +-
             .../src/ArduinoJson/Data/ValueSaver.hpp       |  52 +++
             .../ArduinoJson/Deserialization/Comments.hpp  |   7 +-
             .../Deserialization/JsonParser.hpp            |  29 +-
             .../Deserialization/JsonParserImpl.hpp        |  35 +-
             .../Deserialization/StringWriter.hpp          |   7 +-
             .../src/ArduinoJson/DynamicJsonBuffer.hpp     |  12 +-
             .../src/ArduinoJson/JsonArray.hpp             |  48 ++-
             .../src/ArduinoJson/JsonArrayImpl.hpp         |   7 +-
             .../src/ArduinoJson/JsonArraySubscript.hpp    |  61 ++--
             .../src/ArduinoJson/JsonBuffer.hpp            |  24 +-
             .../src/ArduinoJson/JsonBufferBase.hpp        |  21 +-
             .../src/ArduinoJson/JsonBufferImpl.hpp        |   7 +-
             .../src/ArduinoJson/JsonObject.hpp            | 195 +++++------
             .../src/ArduinoJson/JsonObjectImpl.hpp        |   7 +-
             .../src/ArduinoJson/JsonObjectSubscript.hpp   |  41 +--
             .../src/ArduinoJson/JsonPair.hpp              |   7 +-
             .../src/ArduinoJson/JsonVariant.hpp           | 115 ++++---
             .../src/ArduinoJson/JsonVariantBase.hpp       |  15 +-
             .../src/ArduinoJson/JsonVariantCasts.hpp      |   9 +-
             .../ArduinoJson/JsonVariantComparisons.hpp    |  41 +--
             .../src/ArduinoJson/JsonVariantImpl.hpp       |  15 +-
             .../src/ArduinoJson/JsonVariantOr.hpp         |  52 +++
             .../src/ArduinoJson/JsonVariantSubscripts.hpp |  35 +-
             .../src/ArduinoJson/Polyfills/attributes.hpp  |   9 +-
             .../src/ArduinoJson/Polyfills/ctype.hpp       |   9 +-
             .../src/ArduinoJson/Polyfills/isFloat.hpp     |   9 +-
             .../src/ArduinoJson/Polyfills/isInteger.hpp   |  19 ++
             .../src/ArduinoJson/Polyfills/math.hpp        |   9 +-
             .../src/ArduinoJson/Polyfills/parseFloat.hpp  |  11 +-
             .../ArduinoJson/Polyfills/parseInteger.hpp    |   9 +-
             .../src/ArduinoJson/RawJson.hpp               |  46 +++
             .../ArduinoJson/Serialization/DummyPrint.hpp  |   7 +-
             .../Serialization/DynamicStringBuilder.hpp    |   7 +-
             .../ArduinoJson/Serialization/FloatParts.hpp  |   9 +-
             .../Serialization/IndentedPrint.hpp           |   7 +-
             .../Serialization/JsonPrintable.hpp           |  21 +-
             .../Serialization/JsonSerializer.hpp          |  14 +-
             .../Serialization/JsonSerializerImpl.hpp      |   7 +-
             .../ArduinoJson/Serialization/JsonWriter.hpp  |  11 +-
             .../ArduinoJson/Serialization/Prettyfier.hpp  |   7 +-
             .../Serialization/StaticStringBuilder.hpp     |   7 +-
             .../Serialization/StreamPrintAdapter.hpp      |   7 +-
             .../src/ArduinoJson/StaticJsonBuffer.hpp      |  14 +-
             .../StringTraits/ArduinoStream.hpp            |  20 +-
             .../ArduinoJson/StringTraits/CharPointer.hpp  |  32 +-
             .../ArduinoJson/StringTraits/FlashString.hpp  |  25 +-
             .../ArduinoJson/StringTraits/StdStream.hpp    |  20 +-
             .../ArduinoJson/StringTraits/StdString.hpp    |  27 +-
             .../ArduinoJson/StringTraits/StringTraits.hpp |  28 +-
             .../src/ArduinoJson/TypeTraits/EnableIf.hpp   |   9 +-
             .../ArduinoJson/TypeTraits/FloatTraits.hpp    |  54 ++-
             .../src/ArduinoJson/TypeTraits/IsArray.hpp    |   9 +-
             .../src/ArduinoJson/TypeTraits/IsBaseOf.hpp   |   9 +-
             .../src/ArduinoJson/TypeTraits/IsChar.hpp     |   9 +-
             .../src/ArduinoJson/TypeTraits/IsConst.hpp    |   9 +-
             .../TypeTraits/IsFloatingPoint.hpp            |   9 +-
             .../src/ArduinoJson/TypeTraits/IsIntegral.hpp |  15 +-
             .../src/ArduinoJson/TypeTraits/IsSame.hpp     |   9 +-
             .../TypeTraits/IsSignedIntegral.hpp           |  28 ++
             .../TypeTraits/IsUnsignedIntegral.hpp         |  28 ++
             .../src/ArduinoJson/TypeTraits/IsVariant.hpp  |   9 +-
             .../ArduinoJson/TypeTraits/RemoveConst.hpp    |   9 +-
             .../TypeTraits/RemoveReference.hpp            |   9 +-
             .../src/ArduinoJson/version.hpp               |  10 +
             107 files changed, 1652 insertions(+), 1620 deletions(-)
             delete mode 100644 lib/ArduinoJson-5.11.2/ArduinoJson.h
             delete mode 100644 lib/ArduinoJson-5.11.2/README.md
             delete mode 100644 lib/ArduinoJson-5.11.2/examples/JsonHttpClient/JsonHttpClient.ino
             delete mode 100644 lib/ArduinoJson-5.11.2/examples/JsonServer/JsonServer.ino
             delete mode 100644 lib/ArduinoJson-5.11.2/examples/JsonUdpBeacon/JsonUdpBeacon.ino
             delete mode 100644 lib/ArduinoJson-5.11.2/library.properties
             delete mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson.h
             delete mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ValueSetter.hpp
             delete mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isInteger.hpp
             delete mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/RawJson.hpp
             delete mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSignedIntegral.hpp
             delete mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp
             create mode 100644 lib/ArduinoJson-5.13.4/ArduinoJson.h
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/CHANGELOG.md (68%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/LICENSE.md (96%)
             create mode 100644 lib/ArduinoJson-5.13.4/README.md
             create mode 100644 lib/ArduinoJson-5.13.4/examples/JsonConfigFile/JsonConfigFile.ino
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/examples/JsonGeneratorExample/JsonGeneratorExample.ino (63%)
             create mode 100644 lib/ArduinoJson-5.13.4/examples/JsonHttpClient/JsonHttpClient.ino
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/examples/JsonParserExample/JsonParserExample.ino (61%)
             create mode 100644 lib/ArduinoJson-5.13.4/examples/JsonServer/JsonServer.ino
             create mode 100644 lib/ArduinoJson-5.13.4/examples/JsonUdpBeacon/JsonUdpBeacon.ino
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/examples/ProgmemExample/ProgmemExample.ino (52%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/examples/StringExample/StringExample.ino (67%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/keywords.txt (100%)
             create mode 100644 lib/ArduinoJson-5.13.4/library.properties
             create mode 100644 lib/ArduinoJson-5.13.4/src/ArduinoJson.h
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson.hpp (75%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Configuration.hpp (94%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/Encoding.hpp (80%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/JsonBufferAllocated.hpp (68%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/JsonFloat.hpp (56%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/JsonInteger.hpp (70%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/JsonVariantAs.hpp (80%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/JsonVariantContent.hpp (79%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/JsonVariantDefault.hpp (68%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/JsonVariantType.hpp (84%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/List.hpp (93%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/ListConstIterator.hpp (85%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/ListIterator.hpp (86%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/ListNode.hpp (70%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/NonCopyable.hpp (67%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Data/ReferenceType.hpp (74%)
             create mode 100644 lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ValueSaver.hpp
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Deserialization/Comments.hpp (88%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Deserialization/JsonParser.hpp (77%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Deserialization/JsonParserImpl.hpp (85%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Deserialization/StringWriter.hpp (79%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/DynamicJsonBuffer.hpp (94%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonArray.hpp (82%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonArrayImpl.hpp (75%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonArraySubscript.hpp (69%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonBuffer.hpp (74%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonBufferBase.hpp (88%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonBufferImpl.hpp (72%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonObject.hpp (57%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonObjectImpl.hpp (79%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonObjectSubscript.hpp (66%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonPair.hpp (53%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonVariant.hpp (72%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonVariantBase.hpp (59%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonVariantCasts.hpp (89%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonVariantComparisons.hpp (75%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonVariantImpl.hpp (87%)
             create mode 100644 lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantOr.hpp
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/JsonVariantSubscripts.hpp (70%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Polyfills/attributes.hpp (74%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Polyfills/ctype.hpp (50%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Polyfills/isFloat.hpp (75%)
             create mode 100644 lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/isInteger.hpp
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Polyfills/math.hpp (52%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Polyfills/parseFloat.hpp (89%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Polyfills/parseInteger.hpp (75%)
             create mode 100644 lib/ArduinoJson-5.13.4/src/ArduinoJson/RawJson.hpp
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Serialization/DummyPrint.hpp (64%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Serialization/DynamicStringBuilder.hpp (80%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Serialization/FloatParts.hpp (91%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Serialization/IndentedPrint.hpp (89%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Serialization/JsonPrintable.hpp (80%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Serialization/JsonSerializer.hpp (79%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp (94%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Serialization/JsonWriter.hpp (91%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Serialization/Prettyfier.hpp (93%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Serialization/StaticStringBuilder.hpp (77%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/Serialization/StreamPrintAdapter.hpp (77%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/StaticJsonBuffer.hpp (89%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/StringTraits/ArduinoStream.hpp (64%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/StringTraits/CharPointer.hpp (54%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/StringTraits/FlashString.hpp (64%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/StringTraits/StdStream.hpp (63%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/StringTraits/StdString.hpp (70%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/StringTraits/StringTraits.hpp (55%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/TypeTraits/EnableIf.hpp (58%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/TypeTraits/FloatTraits.hpp (68%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/TypeTraits/IsArray.hpp (67%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/TypeTraits/IsBaseOf.hpp (73%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/TypeTraits/IsChar.hpp (69%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/TypeTraits/IsConst.hpp (61%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/TypeTraits/IsFloatingPoint.hpp (60%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/TypeTraits/IsIntegral.hpp (50%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/TypeTraits/IsSame.hpp (62%)
             create mode 100644 lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsSignedIntegral.hpp
             create mode 100644 lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/TypeTraits/IsVariant.hpp (50%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/TypeTraits/RemoveConst.hpp (59%)
             rename lib/{ArduinoJson-5.11.2 => ArduinoJson-5.13.4}/src/ArduinoJson/TypeTraits/RemoveReference.hpp (60%)
             create mode 100644 lib/ArduinoJson-5.13.4/src/ArduinoJson/version.hpp
            
            diff --git a/lib/ArduinoJson-5.11.2/ArduinoJson.h b/lib/ArduinoJson-5.11.2/ArduinoJson.h
            deleted file mode 100644
            index 896503a6c..000000000
            --- a/lib/ArduinoJson-5.11.2/ArduinoJson.h
            +++ /dev/null
            @@ -1,8 +0,0 @@
            -// Copyright Benoit Blanchon 2014-2017
            -// MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
            -
            -#include "src/ArduinoJson.h"
            diff --git a/lib/ArduinoJson-5.11.2/README.md b/lib/ArduinoJson-5.11.2/README.md
            deleted file mode 100644
            index 6ee8a37a6..000000000
            --- a/lib/ArduinoJson-5.11.2/README.md
            +++ /dev/null
            @@ -1,130 +0,0 @@
            -[![Build status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/master?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master) [![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=master)](https://travis-ci.org/bblanchon/ArduinoJson) [![Coverage Status](https://img.shields.io/coveralls/bblanchon/ArduinoJson.svg)](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master) [![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson)
            -
            -![ArduinoJson's logo](banner.svg)
            -
            -ArduinoJson - C++ JSON library for IoT
            -====================
            -
            -*An elegant and efficient JSON library for embedded systems.*
            -
            -It's designed to have the most intuitive API, the smallest footprint and is able to work without any allocation on the heap (no malloc).
            -
            -It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
            -For instance, it supports Aduino's `String` and `Stream`, but also `std::string`, `std::istream` and `std::ostream`.
            -
            -Features
            ---------
            -
            -* JSON decoding (comments are supported)
            -* JSON encoding (with optional indentation)
            -* Elegant API, very easy to use
            -* Fixed memory allocation (zero malloc)
            -* No data duplication (zero copy)
            -* Portable (written in C++98)
            -* Self-contained (no external dependency)
            -* Small footprint
            -* Header-only library
            -* MIT License
            -
            -Works on
            ---------
            -
            -* Arduino boards: Uno, Due, Mini, Micro, Yun...
            -* ESP8266, ESP32
            -* Teensy
            -* RedBearLab boards (BLE Nano...)
            -* Intel Edison and Galileo
            -* WeMos boards: D1...
            -* Computers: Windows, Linux, OSX...
            -* PlatformIO
            -* Particle
            -* Energia
            -
            -Quick start
            ------------
            -
            -#### Decoding / Parsing
            -
            -```c++
            -char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
            -
            -StaticJsonBuffer<200> jsonBuffer;
            -
            -JsonObject& root = jsonBuffer.parseObject(json);
            -
            -const char* sensor = root["sensor"];
            -long time          = root["time"];
            -double latitude    = root["data"][0];
            -double longitude   = root["data"][1];
            -```
            -
            -[See JsonParserExample.ino](examples/JsonParserExample/JsonParserExample.ino)
            -
            -Use [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/) to compute the buffer size.
            -
            -#### Encoding / Generating
            -
            -```c++
            -StaticJsonBuffer<200> jsonBuffer;
            -
            -JsonObject& root = jsonBuffer.createObject();
            -root["sensor"] = "gps";
            -root["time"] = 1351824120;
            -
            -JsonArray& data = root.createNestedArray("data");
            -data.add(48.756080);
            -data.add(2.302038);
            -
            -root.printTo(Serial);
            -// This prints:
            -// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
            -```
            -
            -[See JsonGeneratorExample.ino](examples/JsonGeneratorExample/JsonGeneratorExample.ino)
            -
            -Use [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/) to compute the buffer size.
            -
            -
            -Documentation
            --------------
            -
            -The documentation is available online in the [ArduinoJson Website](https://bblanchon.github.io/ArduinoJson/).
            -
            -The [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/) helps you get started with the library.
            -
            -
            -Donators
            ---------
            -
            -Special thanks to the following persons and companies who made generous donations to the library author:
            -
            -* Robert Murphy USA
            -* Surge Communications USA
            -* Alex Scott United Kingdom
            -* Firepick Services LLC USA
            -* A B Doodkorte Netherlands
            -* Scott Smith USA
            -* Johann Stieger Austria
            -* Gustavo Donizeti Gini Brazil
            -* Charles-Henri Hallard France
            -* Martijn van den Burg Netherlands
            -* Nick Koumaris Greece
            -* Jon Williams USA
            -* Kestutis Liaugminas Lithuania
            -* Darlington Adibe Nigeria
            -* Yoeri Kroon Netherlands
            -* Andrew Melvin United Kingdom
            -* Doanh Luong Vietnam
            -* Christoph Schmidt Germany
            -* OpenEVSE LLC USA
            -* Prokhoryatov Alexey Russia
            -* Google Inc. USA
            -* Charles Haynes Australia
            -* Charles Walker USA
            -* Günther Jehle Liechtenstein
            -* Patrick Elliott
            -
            -
            ----
            -
            -Found this library useful? Please star this project or [help me back with a donation!](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=donate%40benoitblanchon%2efr&lc=GB&item_name=Benoit%20Blanchon&item_number=Arduino%20JSON¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) :smile:
            diff --git a/lib/ArduinoJson-5.11.2/examples/JsonHttpClient/JsonHttpClient.ino b/lib/ArduinoJson-5.11.2/examples/JsonHttpClient/JsonHttpClient.ino
            deleted file mode 100644
            index 5edb817f1..000000000
            --- a/lib/ArduinoJson-5.11.2/examples/JsonHttpClient/JsonHttpClient.ino
            +++ /dev/null
            @@ -1,184 +0,0 @@
            -// Sample Arduino Json Web Client
            -// Downloads and parse http://jsonplaceholder.typicode.com/users/1
            -//
            -// Copyright Benoit Blanchon 2014-2017
            -// MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
            -
            -#include 
            -#include 
            -#include 
            -
            -EthernetClient client;
            -
            -const char* server = "jsonplaceholder.typicode.com";  // server's address
            -const char* resource = "/users/1";                    // http resource
            -const unsigned long BAUD_RATE = 9600;                 // serial connection speed
            -const unsigned long HTTP_TIMEOUT = 10000;  // max respone time from server
            -const size_t MAX_CONTENT_SIZE = 512;       // max size of the HTTP response
            -
            -// The type of data that we want to extract from the page
            -struct UserData {
            -  char name[32];
            -  char company[32];
            -};
            -
            -// ARDUINO entry point #1: runs once when you press reset or power the board
            -void setup() {
            -  initSerial();
            -  initEthernet();
            -}
            -
            -// ARDUINO entry point #2: runs over and over again forever
            -void loop() {
            -  if (connect(server)) {
            -    if (sendRequest(server, resource) && skipResponseHeaders()) {
            -      UserData userData;
            -      if (readReponseContent(&userData)) {
            -        printUserData(&userData);
            -      }
            -    }
            -  }
            -  disconnect();
            -  wait();
            -}
            -
            -// Initialize Serial port
            -void initSerial() {
            -  Serial.begin(BAUD_RATE);
            -  while (!Serial) {
            -    ;  // wait for serial port to initialize
            -  }
            -  Serial.println("Serial ready");
            -}
            -
            -// Initialize Ethernet library
            -void initEthernet() {
            -  byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
            -  if (!Ethernet.begin(mac)) {
            -    Serial.println("Failed to configure Ethernet");
            -    return;
            -  }
            -  Serial.println("Ethernet ready");
            -  delay(1000);
            -}
            -
            -// Open connection to the HTTP server
            -bool connect(const char* hostName) {
            -  Serial.print("Connect to ");
            -  Serial.println(hostName);
            -
            -  bool ok = client.connect(hostName, 80);
            -
            -  Serial.println(ok ? "Connected" : "Connection Failed!");
            -  return ok;
            -}
            -
            -// Send the HTTP GET request to the server
            -bool sendRequest(const char* host, const char* resource) {
            -  Serial.print("GET ");
            -  Serial.println(resource);
            -
            -  client.print("GET ");
            -  client.print(resource);
            -  client.println(" HTTP/1.0");
            -  client.print("Host: ");
            -  client.println(host);
            -  client.println("Connection: close");
            -  client.println();
            -
            -  return true;
            -}
            -
            -// Skip HTTP headers so that we are at the beginning of the response's body
            -bool skipResponseHeaders() {
            -  // HTTP headers end with an empty line
            -  char endOfHeaders[] = "\r\n\r\n";
            -
            -  client.setTimeout(HTTP_TIMEOUT);
            -  bool ok = client.find(endOfHeaders);
            -
            -  if (!ok) {
            -    Serial.println("No response or invalid response!");
            -  }
            -
            -  return ok;
            -}
            -
            -// Parse the JSON from the input string and extract the interesting values
            -// Here is the JSON we need to parse
            -// {
            -//   "id": 1,
            -//   "name": "Leanne Graham",
            -//   "username": "Bret",
            -//   "email": "Sincere@april.biz",
            -//   "address": {
            -//     "street": "Kulas Light",
            -//     "suite": "Apt. 556",
            -//     "city": "Gwenborough",
            -//     "zipcode": "92998-3874",
            -//     "geo": {
            -//       "lat": "-37.3159",
            -//       "lng": "81.1496"
            -//     }
            -//   },
            -//   "phone": "1-770-736-8031 x56442",
            -//   "website": "hildegard.org",
            -//   "company": {
            -//     "name": "Romaguera-Crona",
            -//     "catchPhrase": "Multi-layered client-server neural-net",
            -//     "bs": "harness real-time e-markets"
            -//   }
            -// }
            -bool readReponseContent(struct UserData* userData) {
            -  // Compute optimal size of the JSON buffer according to what we need to parse.
            -  // See https://bblanchon.github.io/ArduinoJson/assistant/
            -  const size_t BUFFER_SIZE =
            -      JSON_OBJECT_SIZE(8)    // the root object has 8 elements
            -      + JSON_OBJECT_SIZE(5)  // the "address" object has 5 elements
            -      + JSON_OBJECT_SIZE(2)  // the "geo" object has 2 elements
            -      + JSON_OBJECT_SIZE(3)  // the "company" object has 3 elements
            -      + MAX_CONTENT_SIZE;    // additional space for strings
            -
            -  // Allocate a temporary memory pool
            -  DynamicJsonBuffer jsonBuffer(BUFFER_SIZE);
            -
            -  JsonObject& root = jsonBuffer.parseObject(client);
            -
            -  if (!root.success()) {
            -    Serial.println("JSON parsing failed!");
            -    return false;
            -  }
            -
            -  // Here were copy the strings we're interested in
            -  strcpy(userData->name, root["name"]);
            -  strcpy(userData->company, root["company"]["name"]);
            -  // It's not mandatory to make a copy, you could just use the pointers
            -  // Since, they are pointing inside the "content" buffer, so you need to make
            -  // sure it's still in memory when you read the string
            -
            -  return true;
            -}
            -
            -// Print the data extracted from the JSON
            -void printUserData(const struct UserData* userData) {
            -  Serial.print("Name = ");
            -  Serial.println(userData->name);
            -  Serial.print("Company = ");
            -  Serial.println(userData->company);
            -}
            -
            -// Close the connection with the HTTP server
            -void disconnect() {
            -  Serial.println("Disconnect");
            -  client.stop();
            -}
            -
            -// Pause for a 1 minute
            -void wait() {
            -  Serial.println("Wait 60 seconds");
            -  delay(60000);
            -}
            diff --git a/lib/ArduinoJson-5.11.2/examples/JsonServer/JsonServer.ino b/lib/ArduinoJson-5.11.2/examples/JsonServer/JsonServer.ino
            deleted file mode 100644
            index 555842b82..000000000
            --- a/lib/ArduinoJson-5.11.2/examples/JsonServer/JsonServer.ino
            +++ /dev/null
            @@ -1,76 +0,0 @@
            -// Sample Arduino Json Web Server
            -// Created by Benoit Blanchon.
            -// Heavily inspired by "Web Server" from David A. Mellis and Tom Igoe
            -
            -#include 
            -#include 
            -#include 
            -
            -byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
            -IPAddress ip(192, 168, 0, 177);
            -EthernetServer server(80);
            -
            -bool readRequest(EthernetClient& client) {
            -  bool currentLineIsBlank = true;
            -  while (client.connected()) {
            -    if (client.available()) {
            -      char c = client.read();
            -      if (c == '\n' && currentLineIsBlank) {
            -        return true;
            -      } else if (c == '\n') {
            -        currentLineIsBlank = true;
            -      } else if (c != '\r') {
            -        currentLineIsBlank = false;
            -      }
            -    }
            -  }
            -  return false;
            -}
            -
            -JsonObject& prepareResponse(JsonBuffer& jsonBuffer) {
            -  JsonObject& root = jsonBuffer.createObject();
            -
            -  JsonArray& analogValues = root.createNestedArray("analog");
            -  for (int pin = 0; pin < 6; pin++) {
            -    int value = analogRead(pin);
            -    analogValues.add(value);
            -  }
            -
            -  JsonArray& digitalValues = root.createNestedArray("digital");
            -  for (int pin = 0; pin < 14; pin++) {
            -    int value = digitalRead(pin);
            -    digitalValues.add(value);
            -  }
            -
            -  return root;
            -}
            -
            -void writeResponse(EthernetClient& client, JsonObject& json) {
            -  client.println("HTTP/1.1 200 OK");
            -  client.println("Content-Type: application/json");
            -  client.println("Connection: close");
            -  client.println();
            -
            -  json.prettyPrintTo(client);
            -}
            -
            -void setup() {
            -  Ethernet.begin(mac, ip);
            -  server.begin();
            -}
            -
            -void loop() {
            -  EthernetClient client = server.available();
            -  if (client) {
            -    bool success = readRequest(client);
            -    if (success) {
            -      // Use https://bblanchon.github.io/ArduinoJson/assistant/ to
            -      // compute the right size for the buffer
            -      StaticJsonBuffer<500> jsonBuffer;
            -      JsonObject& json = prepareResponse(jsonBuffer);
            -      writeResponse(client, json);
            -    }
            -    delay(1);
            -    client.stop();
            -  }
            -}
            diff --git a/lib/ArduinoJson-5.11.2/examples/JsonUdpBeacon/JsonUdpBeacon.ino b/lib/ArduinoJson-5.11.2/examples/JsonUdpBeacon/JsonUdpBeacon.ino
            deleted file mode 100644
            index b3bd5fc50..000000000
            --- a/lib/ArduinoJson-5.11.2/examples/JsonUdpBeacon/JsonUdpBeacon.ino
            +++ /dev/null
            @@ -1,57 +0,0 @@
            -// Send a JSON object on UDP at regular interval
            -//
            -// You can easily test this program with netcat:
            -// $ nc -ulp 8888
            -//
            -// by Benoit Blanchon, MIT License 2015-2017
            -
            -#include 
            -#include 
            -#include 
            -
            -byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
            -IPAddress localIp(192, 168, 0, 177);
            -IPAddress remoteIp(192, 168, 0, 109);
            -unsigned int remotePort = 8888;
            -unsigned localPort = 8888;
            -EthernetUDP udp;
            -
            -JsonObject& buildJson(JsonBuffer& jsonBuffer) {
            -  JsonObject& root = jsonBuffer.createObject();
            -
            -  JsonArray& analogValues = root.createNestedArray("analog");
            -  for (int pin = 0; pin < 6; pin++) {
            -    int value = analogRead(pin);
            -    analogValues.add(value);
            -  }
            -
            -  JsonArray& digitalValues = root.createNestedArray("digital");
            -  for (int pin = 0; pin < 14; pin++) {
            -    int value = digitalRead(pin);
            -    digitalValues.add(value);
            -  }
            -
            -  return root;
            -}
            -
            -void sendJson(JsonObject& json) {
            -  udp.beginPacket(remoteIp, remotePort);
            -  json.printTo(udp);
            -  udp.println();
            -  udp.endPacket();
            -}
            -
            -void setup() {
            -  Ethernet.begin(mac, localIp);
            -  udp.begin(localPort);
            -}
            -
            -void loop() {
            -  delay(1000);
            -
            -  // Use https://bblanchon.github.io/ArduinoJson/assistant/ to
            -  // compute the right size for the buffer
            -  StaticJsonBuffer<300> jsonBuffer;
            -  JsonObject& json = buildJson(jsonBuffer);
            -  sendJson(json);
            -}
            diff --git a/lib/ArduinoJson-5.11.2/library.properties b/lib/ArduinoJson-5.11.2/library.properties
            deleted file mode 100644
            index 9809a3c0b..000000000
            --- a/lib/ArduinoJson-5.11.2/library.properties
            +++ /dev/null
            @@ -1,9 +0,0 @@
            -name=ArduinoJson
            -version=5.11.2
            -author=Benoit Blanchon 
            -maintainer=Benoit Blanchon 
            -sentence=An efficient and elegant JSON library for Arduino.
            -paragraph=Like this project? Please star it on GitHub!
            -category=Data Processing
            -url=https://bblanchon.github.io/ArduinoJson/
            -architectures=*
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson.h b/lib/ArduinoJson-5.11.2/src/ArduinoJson.h
            deleted file mode 100644
            index c1ec7c02f..000000000
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson.h
            +++ /dev/null
            @@ -1,12 +0,0 @@
            -// Copyright Benoit Blanchon 2014-2017
            -// MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
            -
            -#pragma once
            -
            -#include "ArduinoJson.hpp"
            -
            -using namespace ArduinoJson;
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ValueSetter.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ValueSetter.hpp
            deleted file mode 100644
            index 7eb3ed63b..000000000
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ValueSetter.hpp
            +++ /dev/null
            @@ -1,51 +0,0 @@
            -// Copyright Benoit Blanchon 2014-2017
            -// MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
            -
            -#pragma once
            -
            -#include "../JsonBuffer.hpp"
            -#include "../JsonVariant.hpp"
            -#include "../StringTraits/StringTraits.hpp"
            -#include "../TypeTraits/EnableIf.hpp"
            -
            -namespace ArduinoJson {
            -namespace Internals {
            -
            -template 
            -struct ValueSetter {
            -  template 
            -  static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) {
            -    destination = source;
            -    return true;
            -  }
            -};
            -
            -template 
            -struct ValueSetter::should_duplicate>::type> {
            -  template 
            -  static bool set(JsonBuffer* buffer, TDestination& destination,
            -                  TSourceRef source) {
            -    const char* copy = buffer->strdup(source);
            -    if (!copy) return false;
            -    destination = copy;
            -    return true;
            -  }
            -};
            -
            -template 
            -struct ValueSetter::should_duplicate>::type> {
            -  template 
            -  static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) {
            -    // unsigned char* -> char*
            -    destination = reinterpret_cast(source);
            -    return true;
            -  }
            -};
            -}
            -}
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isInteger.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isInteger.hpp
            deleted file mode 100644
            index ea39f2a63..000000000
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isInteger.hpp
            +++ /dev/null
            @@ -1,22 +0,0 @@
            -// Copyright Benoit Blanchon 2014-2017
            -// MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
            -
            -#pragma once
            -
            -#include "./ctype.hpp"
            -
            -namespace ArduinoJson {
            -namespace Polyfills {
            -
            -inline bool isInteger(const char* s) {
            -  if (!s) return false;
            -  if (issign(*s)) s++;
            -  while (isdigit(*s)) s++;
            -  return *s == '\0';
            -}
            -}
            -}
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/RawJson.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/RawJson.hpp
            deleted file mode 100644
            index 6db195c32..000000000
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/RawJson.hpp
            +++ /dev/null
            @@ -1,23 +0,0 @@
            -// Copyright Benoit Blanchon 2014-2017
            -// MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
            -
            -#pragma once
            -
            -namespace ArduinoJson {
            -
            -// A special type of data that can be used to insert pregenerated JSON portions.
            -class RawJson {
            - public:
            -  explicit RawJson(const char* str) : _str(str) {}
            -  operator const char*() const {
            -    return _str;
            -  }
            -
            - private:
            -  const char* _str;
            -};
            -}
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSignedIntegral.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSignedIntegral.hpp
            deleted file mode 100644
            index fde6e13b0..000000000
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSignedIntegral.hpp
            +++ /dev/null
            @@ -1,33 +0,0 @@
            -// Copyright Benoit Blanchon 2014-2017
            -// MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
            -
            -#pragma once
            -
            -#include "../Configuration.hpp"
            -#include "IsSame.hpp"
            -
            -namespace ArduinoJson {
            -namespace TypeTraits {
            -
            -// A meta-function that returns true if T is an integral type.
            -template 
            -struct IsSignedIntegral {
            -  static const bool value = TypeTraits::IsSame::value ||
            -                            TypeTraits::IsSame::value ||
            -                            TypeTraits::IsSame::value ||
            -                            TypeTraits::IsSame::value ||
            -#if ARDUINOJSON_USE_LONG_LONG
            -                            TypeTraits::IsSame::value ||
            -#endif
            -
            -#if ARDUINOJSON_USE_INT64
            -                            TypeTraits::IsSame::value ||
            -#endif
            -                            false;
            -};
            -}
            -}
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp
            deleted file mode 100644
            index 173763e05..000000000
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp
            +++ /dev/null
            @@ -1,33 +0,0 @@
            -// Copyright Benoit Blanchon 2014-2017
            -// MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
            -
            -#pragma once
            -
            -#include "../Configuration.hpp"
            -#include "IsSame.hpp"
            -
            -namespace ArduinoJson {
            -namespace TypeTraits {
            -
            -// A meta-function that returns true if T is an integral type.
            -template 
            -struct IsUnsignedIntegral {
            -  static const bool value = TypeTraits::IsSame::value ||
            -                            TypeTraits::IsSame::value ||
            -                            TypeTraits::IsSame::value ||
            -                            TypeTraits::IsSame::value ||
            -#if ARDUINOJSON_USE_LONG_LONG
            -                            TypeTraits::IsSame::value ||
            -#endif
            -
            -#if ARDUINOJSON_USE_INT64
            -                            TypeTraits::IsSame::value ||
            -#endif
            -                            false;
            -};
            -}
            -}
            diff --git a/lib/ArduinoJson-5.13.4/ArduinoJson.h b/lib/ArduinoJson-5.13.4/ArduinoJson.h
            new file mode 100644
            index 000000000..9f78b9f18
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/ArduinoJson.h
            @@ -0,0 +1,5 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +
            +#include "src/ArduinoJson.h"
            diff --git a/lib/ArduinoJson-5.11.2/CHANGELOG.md b/lib/ArduinoJson-5.13.4/CHANGELOG.md
            similarity index 68%
            rename from lib/ArduinoJson-5.11.2/CHANGELOG.md
            rename to lib/ArduinoJson-5.13.4/CHANGELOG.md
            index 490e25c8c..3616b176a 100644
            --- a/lib/ArduinoJson-5.11.2/CHANGELOG.md
            +++ b/lib/ArduinoJson-5.13.4/CHANGELOG.md
            @@ -1,6 +1,78 @@
             ArduinoJson: change log
             =======================
             
            +v5.13.4
            +-------
            +
            +* Removed spurious files in the Particle library
            +
            +v5.13.3
            +-------
            +
            +* Improved float serialization when `-fsingle-precision-constant` is used
            +* Fixed `JsonVariant::is()` that returned true for empty strings
            +* Fixed `JsonVariant::is()` (closes #763)
            +
            +v5.13.2
            +-------
            +
            +* Fixed `JsonBuffer::parse()` not respecting nesting limit correctly (issue #693)
            +* Fixed inconsistencies in nesting level counting (PR #695 from Zhenyu Wu)
            +* Fixed null values that could be pass to `strcmp()` (PR #745 from Mike Karlesky)
            +* Added macros `ARDUINOJSON_VERSION`, `ARDUINOJSON_VERSION_MAJOR`...
            +
            +v5.13.1
            +-------
            +
            +* Fixed `JsonVariant::operator|(int)` that returned the default value if the variant contained a double (issue #675)
            +* Allowed non-quoted key to contain underscores (issue #665)
            +
            +v5.13.0
            +-------
            +
            +* Changed the rules of string duplication (issue #658)
            +* `RawJson()` accepts any kind of string and obeys to the same rules for duplication
            +* Changed the return type of `strdup()` to `const char*` to prevent double duplication
            +* Marked `strdup()` as deprecated
            +
            +> ### New rules for string duplication
            +>
            +> | type                       | duplication |
            +> |:---------------------------|:------------|
            +> | const char*                | no          |
            +> | char*                      | ~~no~~ yes  |
            +> | String                     | yes         |
            +> | std::string                | yes         |
            +> | const __FlashStringHelper* | yes         |
            +>
            +> These new rules make `JsonBuffer::strdup()` useless.
            +
            +v5.12.0
            +-------
            +
            +* Added `JsonVariant::operator|` to return a default value (see below)
            +* Added a clear error message when compiled as C instead of C++ (issue #629)
            +* Added detection of MPLAB XC compiler (issue #629)
            +* Added detection of Keil ARM Compiler (issue #629)
            +* Added an example that shows how to save and load a configuration file
            +* Reworked all other examples
            +
            +> ### How to use the new feature?
            +>
            +> If you have a block like this:
            +>
            +> ```c++
            +> const char* ssid = root["ssid"];
            +> if (!ssid)
            +>   ssid = "default ssid";
            +> ```
            +>
            +> You can simplify like that:
            +>
            +> ```c++
            +> const char* ssid = root["ssid"] | "default ssid";
            +> ```
            +
             v5.11.2
             -------
             
            @@ -42,27 +114,26 @@ v5.10.0
             * Fixed error `IsBaseOf is not a member of ArduinoJson::TypeTraits` (issue #495)
             * Fixed error `forming reference to reference` (issue #495)
             
            -### BREAKING CHANGES :warning:
            -
            -| Old syntax                      | New syntax          |
            -|---------------------------------|---------------------|
            -| `double_with_n_digits(3.14, 2)` | `3.14`              |
            -| `float_with_n_digits(3.14, 2)`  | `3.14f`             |
            -| `obj.set("key", 3.14, 2)`       | `obj["key"] = 3.14` |
            -| `arr.add(3.14, 2)`              | `arr.add(3.14)`     |
            -
            -| Input     | Old output | New output |
            -|-----------|------------|------------|
            -| `3.14159` | `3.14`     | `3.14159`  |
            -| `42.0`    | `42.00`    | `42`       |
            -| `0.0`     | `0.00`     | `0`        |
            -
            -| Expression                     | Old result | New result |
            -|--------------------------------|------------|------------|
            -| `JsonVariant(42).is()`    | `true`     | `true`     |
            -| `JsonVariant(42).is()`  | `false`    | `true`     |
            -| `JsonVariant(42).is()` | `false`    | `true`     |
            -
            +> ### BREAKING CHANGES :warning:
            +>
            +> | Old syntax                      | New syntax          |
            +> |:--------------------------------|:--------------------|
            +> | `double_with_n_digits(3.14, 2)` | `3.14`              |
            +> | `float_with_n_digits(3.14, 2)`  | `3.14f`             |
            +> | `obj.set("key", 3.14, 2)`       | `obj["key"] = 3.14` |
            +> | `arr.add(3.14, 2)`              | `arr.add(3.14)`     |
            +>
            +> | Input     | Old output | New output |
            +> |:----------|:-----------|:-----------|
            +> | `3.14159` | `3.14`     | `3.14159`  |
            +> | `42.0`    | `42.00`    | `42`       |
            +> | `0.0`     | `0.00`     | `0`        |
            +>
            +> | Expression                     | Old result | New result |
            +> |:-------------------------------|:-----------|:-----------|
            +> | `JsonVariant(42).is()`    | `true`     | `true`     |
            +> | `JsonVariant(42).is()`  | `false`    | `true`     |
            +> | `JsonVariant(42).is()` | `false`    | `true`     |
             
             v5.9.0
             ------
            @@ -116,24 +187,23 @@ v5.8.0
             * Added support for `Stream` (issue #300)
             * Reduced memory consumption by not duplicating spaces and comments
             
            -### BREAKING CHANGES :warning:
            -
            -`JsonBuffer::parseObject()` and  `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`.
            -
            -This means that if you have code like:
            -
            -```c++
            -void myFunction(JsonBuffer& jsonBuffer);
            -```
            -
            -you need to replace it with one of the following:
            -
            -```c++
            -void myFunction(DynamicJsonBuffer& jsonBuffer);
            -void myFunction(StaticJsonBufferBase& jsonBuffer);
            -template void myFunction(TJsonBuffer& jsonBuffer);
            -```
            -
            +> ### BREAKING CHANGES :warning:
            +>
            +> `JsonBuffer::parseObject()` and  `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`.
            +>
            +> This means that if you have code like:
            +>
            +> ```c++
            +> void myFunction(JsonBuffer& jsonBuffer);
            +> ```
            +>
            +> you need to replace it with one of the following:
            +>
            +> ```c++
            +> void myFunction(DynamicJsonBuffer& jsonBuffer);
            +> void myFunction(StaticJsonBufferBase& jsonBuffer);
            +> template void myFunction(TJsonBuffer& jsonBuffer);
            +> ```
             
             v5.7.3
             ------
            @@ -166,27 +236,26 @@ v5.7.0
             * Added example `StringExample.ino` to show where `String` can be used
             * Increased default nesting limit to 50 when compiled for a computer (issue #349)
             
            -### BREAKING CHANGES :warning:
            -
            -The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return.
            -
            -Old code:
            -
            -```c++
            -#define ARDUINOJSON_USE_ARDUINO_STRING 0
            -JsonVariant value1 = myObject.get("myKey");
            -JsonVariant value2 = myArray.get(0);
            -```
            -
            -New code:
            -
            -```c++
            -#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
            -#define ARDUINOJSON_ENABLE_STD_STRING 1
            -JsonVariant value1 = myObject.get("myKey");
            -JsonVariant value2 = myArray.get(0);
            -```
            -
            +> ### BREAKING CHANGES :warning:
            +>
            +> The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return.
            +>
            +> Old code:
            +>
            +> ```c++
            +> #define ARDUINOJSON_USE_ARDUINO_STRING 0
            +> JsonVariant value1 = myObject.get("myKey");
            +> JsonVariant value2 = myArray.get(0);
            +> ```
            +>
            +> New code:
            +>
            +> ```c++
            +> #define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
            +> #define ARDUINOJSON_ENABLE_STD_STRING 1
            +> JsonVariant value1 = myObject.get("myKey");
            +> JsonVariant value2 = myArray.get(0);
            +> ```
             
             v5.6.7
             ------
            @@ -278,8 +347,9 @@ v5.1.0
             * Added support of `long long` (issue #171)
             * Moved all build settings to `ArduinoJson/Configuration.hpp`
             
            -**BREAKING CHANGE**:
            -If you defined `ARDUINOJSON_ENABLE_STD_STREAM`, you now need to define it to `1`.
            +> ### BREAKING CHANGE :warning:
            +>
            +> If you defined `ARDUINOJSON_ENABLE_STD_STREAM`, you now need to define it to `1`.
             
             v5.0.8
             ------
            @@ -293,10 +363,10 @@ v5.0.7
             * Made library easier to use from a CMake project: simply `add_subdirectory(ArduinoJson/src)`
             * Changed `String` to be a `typedef` of `std::string` (issues #142 and #161)
             
            -### BREAKING CHANGES :warning:
            -
            -- `JsonVariant(true).as()` now returns `"true"` instead of `"1"`
            -- `JsonVariant(false).as()` now returns `"false"` instead of `"0"`
            +> ### BREAKING CHANGES :warning:
            +>
            +> - `JsonVariant(true).as()` now returns `"true"` instead of `"1"`
            +> - `JsonVariant(false).as()` now returns `"false"` instead of `"0"`
             
             v5.0.6
             ------
            @@ -350,11 +420,11 @@ v5.0.0
             * Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66)
             * Switched to new the library layout (requires Arduino 1.0.6 or above)
             
            -### BREAKING CHANGES :warning:
            -
            -- `JsonObject::add()` was renamed to `set()`
            -- `JsonArray::at()` and `JsonObject::at()` were renamed to `get()`
            -- Number of digits of floating point value are now set with `double_with_n_digits()`
            +> ### BREAKING CHANGES :warning:
            +>
            +> - `JsonObject::add()` was renamed to `set()`
            +> - `JsonArray::at()` and `JsonObject::at()` were renamed to `get()`
            +> - Number of digits of floating point value are now set with `double_with_n_digits()`
             
             **Personal note about the `String` class**:
             Support of the `String` class has been added to the library because many people use it in their programs.
            @@ -407,106 +477,7 @@ v4.0
             * Unified parser and generator API (issue #23)
             * Updated library layout, now requires Arduino 1.0.6 or newer
             
            -**BREAKING CHANGE**: API changed significantly, see [Migrating code to the new API](https://github.com/bblanchon/ArduinoJson/wiki/Migrating-code-to-the-new-API).
            +> ### BREAKING CHANGES :warning:
            +>
            +> API changed significantly since v3, see [Migrating code to the new API](https://arduinojson.org/doc/migration/).
             
            -
            -v3.4
            -----
            -
            -* Fixed escaped char parsing (issue #16)
            -
            -
            -v3.3
            -----
            -
            -* Added indented output for the JSON generator (issue #11), see example bellow.
            -* Added `IndentedPrint`, a decorator for `Print` to allow indented output
            -
            -Example:
            -
            -    JsonOject<2> json;
            -    json["key"] = "value";
            -    json.prettyPrintTo(Serial);
            -
            -v3.2
            -----
            -
            -* Fixed a bug when adding nested object in `JsonArray` (bug introduced in v3.1).
            -
            -v3.1
            -----
            -
            -* Calling `Generator::JsonObject::add()` twice with the same `key` now replaces the `value`
            -* Added `Generator::JsonObject::operator[]`, see bellow the new API
            -* Added `Generator::JsonObject::remove()` (issue #9)
            -
            -Old generator API:
            -
            -	JsonObject<3> root;
            -    root.add("sensor", "gps");
            -    root.add("time", 1351824120);
            -    root.add("data", array);
            -
            -New generator API:
            -
            -	JsonObject<3> root;
            -    root["sensor"] = "gps";
            -    root["time"] = 1351824120;
            -    root["data"] = array;
            -
            -v3.0
            -----
            -
            -* New parser API, see bellow
            -* Renamed `JsonHashTable` into `JsonObject`
            -* Added iterators for `JsonArray` and `JsonObject` (issue #4)
            -
            -Old parser API:
            -
            -    JsonHashTable root = parser.parseHashTable(json);
            -
            -	char*  sensor    = root.getString("sensor");
            -	long   time      = root.getLong("time");
            -	double latitude  = root.getArray("data").getDouble(0);
            -    double longitude = root.getArray("data").getDouble(1);
            -
            -New parser API:
            -
            -	JsonObject root = parser.parse(json);
            -
            -	char*  sensor    = root["sensor"];
            -    long   time      = root["time"];
            -    double latitude  = root["data"][0];
            -    double longitude = root["data"][1];
            -
            -v2.1
            -----
            -
            -* Fixed case `#include "jsmn.cpp"` which caused an error in Linux (issue #6)
            -* Fixed a buffer overrun in JSON Parser (issue #5)
            -
            -v2.0
            -----
            -
            -* Added JSON encoding (issue #2)
            -* Renamed the library `ArduinoJsonParser` becomes `ArduinoJson`
            -
            -**Breaking change**: you need to add the following line at the top of your program.
            -
            -	using namespace ArduinoJson::Parser;
            -
            -v1.2
            -----
            -
            -* Fixed error in JSON parser example (issue #1)
            -
            -v1.1
            -----
            -
            -* Example: changed `char* json` into `char[] json` so that the bytes are not write protected
            -* Fixed parsing bug when the JSON contains multi-dimensional arrays
            -
            -v1.0
            -----
            -
            -Initial release
            diff --git a/lib/ArduinoJson-5.11.2/LICENSE.md b/lib/ArduinoJson-5.13.4/LICENSE.md
            similarity index 96%
            rename from lib/ArduinoJson-5.11.2/LICENSE.md
            rename to lib/ArduinoJson-5.13.4/LICENSE.md
            index 9f35ed446..f0c4b5ae7 100644
            --- a/lib/ArduinoJson-5.11.2/LICENSE.md
            +++ b/lib/ArduinoJson-5.13.4/LICENSE.md
            @@ -1,7 +1,7 @@
             The MIT License (MIT)
             ---------------------
             
            -Copyright © 2014-2017 Benoit BLANCHON
            +Copyright © 2014-2018 Benoit BLANCHON
             
             Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
             
            diff --git a/lib/ArduinoJson-5.13.4/README.md b/lib/ArduinoJson-5.13.4/README.md
            new file mode 100644
            index 000000000..8ddc698fc
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/README.md
            @@ -0,0 +1,110 @@
            +![ArduinoJson](banner.svg)
            +
            +---
            +
            +[![Build status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/master?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master) [![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=master)](https://travis-ci.org/bblanchon/ArduinoJson) [![Coverage Status](https://img.shields.io/coveralls/bblanchon/ArduinoJson.svg)](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master) [![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson)
            +
            +ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
            +
            +## Features
            +
            +* JSON decoding (comments are supported)
            +* JSON encoding (with optional indentation)
            +* Elegant API, easy to use
            +* Fixed memory allocation (zero malloc)
            +* No data duplication (zero copy)
            +* Portable (written in C++98, can be used in any C++ project)
            +* Self-contained (no external dependency)
            +* Small footprint
            +* Input and output streams
            +* [100% code coverage](https://coveralls.io/github/bblanchon/ArduinoJson)
            +* [Header-only library](https://en.wikipedia.org/wiki/Header-only)
            +* [MIT License](https://en.wikipedia.org/wiki/MIT_License)
            +* [Comprehensive documentation](https://arduinojson.org?utm_source=github&utm_medium=readme)
            +
            +## Compatibility
            +
            +ArduinoJson works on the following hardware:
            +
            +*  Arduino boards: [Uno](https://www.arduino.cc/en/Main/ArduinoBoardUno), [Due](https://www.arduino.cc/en/Main/ArduinoBoardDue), [Mini](https://www.arduino.cc/en/Main/ArduinoBoardMini), [Micro](https://www.arduino.cc/en/Main/ArduinoBoardMicro), [Yun](https://www.arduino.cc/en/Main/ArduinoBoardYun)...
            +*  Espressif chips: [ESP8266](https://en.wikipedia.org/wiki/ESP8266), [ESP32](https://en.wikipedia.org/wiki/ESP32)
            +*  WeMos boards: [D1](https://wiki.wemos.cc/products:d1:d1), [D1 mini](https://wiki.wemos.cc/products:d1:d1_mini),  ...
            +*  RedBearLab boards: [BLE Nano](http://redbearlab.com/blenano/), [BLE Mini](http://redbearlab.com/blemini/), [WiFi Micro](https://redbear.cc/product/wifi/wifi-micro.html), [LOLIN32](https://wiki.wemos.cc/products:lolin32:lolin32)...
            +*  [Teensy](https://www.pjrc.com/teensy/) boards
            +*  Intel boards: Edison, Galileo...
            +*  Particle boards: [Photon](https://www.particle.io/products/hardware/photon-wifi-dev-kit), [Electron](https://www.particle.io/products/hardware/electron-cellular-dev-kit)...
            +*  Texas Instruments boards: [MSP430](http://www.ti.com/microcontrollers/msp430-ultra-low-power-mcus/overview/overview.html)...
            +
            +ArduinoJson compiles with zero warning on the following compilers, IDEs, and platforms:
            +
            +*  [Arduino IDE](https://www.arduino.cc/en/Main/Software)
            +*  [PlatformIO](http://platformio.org/)
            +*  [Energia](http://energia.nu/)
            +*  [Visual Micro](http://www.visualmicro.com/)
            +*  [Atmel Studio](http://www.atmel.com/microsite/atmel-studio/)
            +*  [IAR Embedded Workbench](https://www.iar.com/iar-embedded-workbench/)
            +*  [Atollic TrueSTUDIO](https://atollic.com/truestudio/)
            +*  [Keil uVision](http://www.keil.com/)
            +*  [MPLAB X IDE](http://www.microchip.com/mplab/mplab-x-ide)
            +*  [GCC](https://gcc.gnu.org/)
            +*  [Clang](https://clang.llvm.org/)
            +*  [Visual Studio](https://www.visualstudio.com/)
            +
            +## Quickstart
            +
            +### Deserialization
            +
            +Here is a program that parses a JSON document with ArduinoJson.
            +
            +```c++
            +char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
            +
            +StaticJsonBuffer<200> jsonBuffer;
            +
            +JsonObject& root = jsonBuffer.parseObject(json);
            +
            +const char* sensor = root["sensor"];
            +long time          = root["time"];
            +double latitude    = root["data"][0];
            +double longitude   = root["data"][1];
            +```
            +
            +See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_source=github&utm_medium=readme)
            +
            +### Serialization
            +
            +Here is a program that generates a JSON document with ArduinoJson:
            +
            +```c++
            +StaticJsonBuffer<200> jsonBuffer;
            +
            +JsonObject& root = jsonBuffer.createObject();
            +root["sensor"] = "gps";
            +root["time"] = 1351824120;
            +
            +JsonArray& data = root.createNestedArray("data");
            +data.add(48.756080);
            +data.add(2.302038);
            +
            +root.printTo(Serial);
            +// This prints:
            +// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
            +```
            +
            +See the [tutorial on arduinojson.org](https://arduinojson.org/doc/encoding/?utm_source=github&utm_medium=readme)
            +
            +## Documentation
            +
            +The documentation is available on [arduinojson.org](https://arduinojson.org/?utm_source=github&utm_medium=readme), here are some shortcuts:
            +
            +* The [Examples](https://arduinojson.org/example/?utm_source=github&utm_medium=readme) show how to use the library in various situations.
            +* The [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=readme) contains the description of each class and function.
            +* The [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=readme) has the answer to virtually every question.
            +* The [ArduinoJson Assistant](https://arduinojson.org/assistant/?utm_source=github&utm_medium=readme) writes programs for you!
            +
            +---
            +
            +Do you like this library? Please [star this project on GitHub](https://github.com/bblanchon/ArduinoJson/stargazers)!
            +
            +What? You don't like it but you *love* it?
            +We don't take donations anymore, but [we sell a book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme), so you can help and learn at the same time!
            \ No newline at end of file
            diff --git a/lib/ArduinoJson-5.13.4/examples/JsonConfigFile/JsonConfigFile.ino b/lib/ArduinoJson-5.13.4/examples/JsonConfigFile/JsonConfigFile.ino
            new file mode 100644
            index 000000000..2ccf7d673
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/examples/JsonConfigFile/JsonConfigFile.ino
            @@ -0,0 +1,144 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +//
            +// This example shows how to store your project configuration in a file.
            +// It uses the SD library but can be easily modified for any other file-system.
            +//
            +// The file contains a JSON document with the following content:
            +// {
            +//   "hostname": "examples.com",
            +//   "port": 2731
            +// }
            +
            +#include 
            +#include 
            +#include 
            +
            +// Configuration that we'll store on disk
            +struct Config {
            +  char hostname[64];
            +  int port;
            +};
            +
            +const char *filename = "/config.txt";  // <- SD library uses 8.3 filenames
            +Config config;                         // <- global configuration object
            +
            +// Loads the configuration from a file
            +void loadConfiguration(const char *filename, Config &config) {
            +  // Open file for reading
            +  File file = SD.open(filename);
            +
            +  // Allocate the memory pool on the stack.
            +  // Don't forget to change the capacity to match your JSON document.
            +  // Use arduinojson.org/assistant to compute the capacity.
            +  StaticJsonBuffer<512> jsonBuffer;
            +
            +  // Parse the root object
            +  JsonObject &root = jsonBuffer.parseObject(file);
            +
            +  if (!root.success())
            +    Serial.println(F("Failed to read file, using default configuration"));
            +
            +  // Copy values from the JsonObject to the Config
            +  config.port = root["port"] | 2731;
            +  strlcpy(config.hostname,                   // <- destination
            +          root["hostname"] | "example.com",  // <- source
            +          sizeof(config.hostname));          // <- destination's capacity
            +
            +  // Close the file (File's destructor doesn't close the file)
            +  file.close();
            +}
            +
            +// Saves the configuration to a file
            +void saveConfiguration(const char *filename, const Config &config) {
            +  // Delete existing file, otherwise the configuration is appended to the file
            +  SD.remove(filename);
            +
            +  // Open file for writing
            +  File file = SD.open(filename, FILE_WRITE);
            +  if (!file) {
            +    Serial.println(F("Failed to create file"));
            +    return;
            +  }
            +
            +  // Allocate the memory pool on the stack
            +  // Don't forget to change the capacity to match your JSON document.
            +  // Use https://arduinojson.org/assistant/ to compute the capacity.
            +  StaticJsonBuffer<256> jsonBuffer;
            +
            +  // Parse the root object
            +  JsonObject &root = jsonBuffer.createObject();
            +
            +  // Set the values
            +  root["hostname"] = config.hostname;
            +  root["port"] = config.port;
            +
            +  // Serialize JSON to file
            +  if (root.printTo(file) == 0) {
            +    Serial.println(F("Failed to write to file"));
            +  }
            +
            +  // Close the file (File's destructor doesn't close the file)
            +  file.close();
            +}
            +
            +// Prints the content of a file to the Serial
            +void printFile(const char *filename) {
            +  // Open file for reading
            +  File file = SD.open(filename);
            +  if (!file) {
            +    Serial.println(F("Failed to read file"));
            +    return;
            +  }
            +
            +  // Extract each characters by one by one
            +  while (file.available()) {
            +    Serial.print((char)file.read());
            +  }
            +  Serial.println();
            +
            +  // Close the file (File's destructor doesn't close the file)
            +  file.close();
            +}
            +
            +void setup() {
            +  // Initialize serial port
            +  Serial.begin(9600);
            +  while (!Serial) continue;
            +
            +  // Initialize SD library
            +  while (!SD.begin()) {
            +    Serial.println(F("Failed to initialize SD library"));
            +    delay(1000);
            +  }
            +
            +  // Should load default config if run for the first time
            +  Serial.println(F("Loading configuration..."));
            +  loadConfiguration(filename, config);
            +
            +  // Create configuration file
            +  Serial.println(F("Saving configuration..."));
            +  saveConfiguration(filename, config);
            +
            +  // Dump config file
            +  Serial.println(F("Print config file..."));
            +  printFile(filename);
            +}
            +
            +void loop() {
            +  // not used in this example
            +}
            +
            +// See also
            +// --------
            +//
            +// https://arduinojson.org/ contains the documentation for all the functions
            +// used above. It also includes an FAQ that will help you solve any
            +// serialization or deserialization problem.
            +//
            +// The book "Mastering ArduinoJson" contains a case study of a project that has
            +// a complex configuration with nested members.
            +// Contrary to this example, the project in the book uses the SPIFFS filesystem.
            +// Learn more at https://arduinojson.org/book/
            +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
            diff --git a/lib/ArduinoJson-5.11.2/examples/JsonGeneratorExample/JsonGeneratorExample.ino b/lib/ArduinoJson-5.13.4/examples/JsonGeneratorExample/JsonGeneratorExample.ino
            similarity index 63%
            rename from lib/ArduinoJson-5.11.2/examples/JsonGeneratorExample/JsonGeneratorExample.ino
            rename to lib/ArduinoJson-5.13.4/examples/JsonGeneratorExample/JsonGeneratorExample.ino
            index 0f636faf8..7b38227b3 100644
            --- a/lib/ArduinoJson-5.11.2/examples/JsonGeneratorExample/JsonGeneratorExample.ino
            +++ b/lib/ArduinoJson-5.13.4/examples/JsonGeneratorExample/JsonGeneratorExample.ino
            @@ -1,23 +1,21 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
             //
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
            +// This example shows how to generate a JSON document with ArduinoJson.
             
             #include 
             
             void setup() {
            +  // Initialize Serial port
               Serial.begin(9600);
            -  while (!Serial) {
            -    // wait serial port initialization
            -  }
            +  while (!Serial) continue;
             
               // Memory pool for JSON object tree.
               //
               // Inside the brackets, 200 is the size of the pool in bytes.
            -  // If the JSON object is more complex, you need to increase that value.
            -  // See https://bblanchon.github.io/ArduinoJson/assistant/
            +  // Don't forget to change this value to match your JSON document.
            +  // Use arduinojson.org/assistant to compute the capacity.
               StaticJsonBuffer<200> jsonBuffer;
             
               // StaticJsonBuffer allocates memory on the stack, it can be
            @@ -68,3 +66,16 @@ void setup() {
             void loop() {
               // not used in this example
             }
            +
            +// See also
            +// --------
            +//
            +// https://arduinojson.org/ contains the documentation for all the functions
            +// used above. It also includes an FAQ that will help you solve any
            +// serialization problem.
            +//
            +// The book "Mastering ArduinoJson" contains a tutorial on serialization.
            +// It begins with a simple example, like the one above, and then adds more
            +// features like serializing directly to a file or an HTTP request.
            +// Learn more at https://arduinojson.org/book/
            +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
            diff --git a/lib/ArduinoJson-5.13.4/examples/JsonHttpClient/JsonHttpClient.ino b/lib/ArduinoJson-5.13.4/examples/JsonHttpClient/JsonHttpClient.ino
            new file mode 100644
            index 000000000..4ce1c20d1
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/examples/JsonHttpClient/JsonHttpClient.ino
            @@ -0,0 +1,112 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +//
            +// This example shows how to parse a JSON document in an HTTP response.
            +// It uses the Ethernet library, but can be easily adapted for Wifi.
            +//
            +// It performs a GET resquest on arduinojson.org/example.json
            +// Here is the expected response:
            +// {
            +//   "sensor": "gps",
            +//   "time": 1351824120,
            +//   "data": [
            +//     48.756080,
            +//     2.302038
            +//   ]
            +// }
            +
            +#include 
            +#include 
            +#include 
            +
            +void setup() {
            +  // Initialize Serial port
            +  Serial.begin(9600);
            +  while (!Serial) continue;
            +
            +  // Initialize Ethernet library
            +  byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
            +  if (!Ethernet.begin(mac)) {
            +    Serial.println(F("Failed to configure Ethernet"));
            +    return;
            +  }
            +  delay(1000);
            +
            +  Serial.println(F("Connecting..."));
            +
            +  // Connect to HTTP server
            +  EthernetClient client;
            +  client.setTimeout(10000);
            +  if (!client.connect("arduinojson.org", 80)) {
            +    Serial.println(F("Connection failed"));
            +    return;
            +  }
            +
            +  Serial.println(F("Connected!"));
            +
            +  // Send HTTP request
            +  client.println(F("GET /example.json HTTP/1.0"));
            +  client.println(F("Host: arduinojson.org"));
            +  client.println(F("Connection: close"));
            +  if (client.println() == 0) {
            +    Serial.println(F("Failed to send request"));
            +    return;
            +  }
            +
            +  // Check HTTP status
            +  char status[32] = {0};
            +  client.readBytesUntil('\r', status, sizeof(status));
            +  if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
            +    Serial.print(F("Unexpected response: "));
            +    Serial.println(status);
            +    return;
            +  }
            +
            +  // Skip HTTP headers
            +  char endOfHeaders[] = "\r\n\r\n";
            +  if (!client.find(endOfHeaders)) {
            +    Serial.println(F("Invalid response"));
            +    return;
            +  }
            +
            +  // Allocate JsonBuffer
            +  // Use arduinojson.org/assistant to compute the capacity.
            +  const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
            +  DynamicJsonBuffer jsonBuffer(capacity);
            +
            +  // Parse JSON object
            +  JsonObject& root = jsonBuffer.parseObject(client);
            +  if (!root.success()) {
            +    Serial.println(F("Parsing failed!"));
            +    return;
            +  }
            +
            +  // Extract values
            +  Serial.println(F("Response:"));
            +  Serial.println(root["sensor"].as());
            +  Serial.println(root["time"].as());
            +  Serial.println(root["data"][0].as());
            +  Serial.println(root["data"][1].as());
            +
            +  // Disconnect
            +  client.stop();
            +}
            +
            +void loop() {
            +  // not used in this example
            +}
            +
            +// See also
            +// --------
            +//
            +// https://arduinojson.org/ contains the documentation for all the functions
            +// used above. It also includes an FAQ that will help you solve any
            +// serialization  problem.
            +//
            +// The book "Mastering ArduinoJson" contains a tutorial on deserialization
            +// showing how to parse the response from Yahoo Weather. In the last chapter,
            +// it shows how to parse the huge documents from OpenWeatherMap
            +// and Weather Underground.
            +// Learn more at https://arduinojson.org/book/
            +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
            diff --git a/lib/ArduinoJson-5.11.2/examples/JsonParserExample/JsonParserExample.ino b/lib/ArduinoJson-5.13.4/examples/JsonParserExample/JsonParserExample.ino
            similarity index 61%
            rename from lib/ArduinoJson-5.11.2/examples/JsonParserExample/JsonParserExample.ino
            rename to lib/ArduinoJson-5.13.4/examples/JsonParserExample/JsonParserExample.ino
            index 719d2ee28..6c16211b5 100644
            --- a/lib/ArduinoJson-5.11.2/examples/JsonParserExample/JsonParserExample.ino
            +++ b/lib/ArduinoJson-5.13.4/examples/JsonParserExample/JsonParserExample.ino
            @@ -1,23 +1,21 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
             //
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
            +// This example shows how to deserialize a JSON document with ArduinoJson.
             
             #include 
             
             void setup() {
            +  // Initialize serial port
               Serial.begin(9600);
            -  while (!Serial) {
            -    // wait serial port initialization
            -  }
            +  while (!Serial) continue;
             
               // Memory pool for JSON object tree.
               //
            -  // Inside the brackets, 200 is the size of the pool in bytes,
            -  // If the JSON object is more complex, you need to increase that value.
            -  // See https://bblanchon.github.io/ArduinoJson/assistant/
            +  // Inside the brackets, 200 is the size of the pool in bytes.
            +  // Don't forget to change this value to match your JSON document.
            +  // Use arduinojson.org/assistant to compute the capacity.
               StaticJsonBuffer<200> jsonBuffer;
             
               // StaticJsonBuffer allocates memory on the stack, it can be
            @@ -65,3 +63,16 @@ void setup() {
             void loop() {
               // not used in this example
             }
            +
            +// See also
            +// --------
            +//
            +// https://arduinojson.org/ contains the documentation for all the functions
            +// used above. It also includes an FAQ that will help you solve any
            +// deserialization problem.
            +//
            +// The book "Mastering ArduinoJson" contains a tutorial on deserialization.
            +// It begins with a simple example, like the one above, and then adds more
            +// features like deserializing directly from a file or an HTTP request.
            +// Learn more at https://arduinojson.org/book/
            +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
            diff --git a/lib/ArduinoJson-5.13.4/examples/JsonServer/JsonServer.ino b/lib/ArduinoJson-5.13.4/examples/JsonServer/JsonServer.ino
            new file mode 100644
            index 000000000..e693ae176
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/examples/JsonServer/JsonServer.ino
            @@ -0,0 +1,109 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +//
            +// This example shows how to implement an HTTP server that sends JSON document
            +// in the responses.
            +// It uses the Ethernet library but can be easily adapted for Wifi.
            +//
            +// It sends the value of the analog and digital pins.
            +// The JSON document looks like the following:
            +// {
            +//   "analog": [ 0, 1, 2, 3, 4, 5 ],
            +//   "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
            +// }
            +
            +#include 
            +#include 
            +#include 
            +
            +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
            +EthernetServer server(80);
            +
            +void setup() {
            +  // Initialize serial port
            +  Serial.begin(9600);
            +  while (!Serial) continue;
            +
            +  // Initialize Ethernet libary
            +  if (!Ethernet.begin(mac)) {
            +    Serial.println(F("Failed to initialize Ethernet library"));
            +    return;
            +  }
            +
            +  // Start to listen
            +  server.begin();
            +
            +  Serial.println(F("Server is ready."));
            +  Serial.print(F("Please connect to http://"));
            +  Serial.println(Ethernet.localIP());
            +}
            +
            +void loop() {
            +  // Wait for an incomming connection
            +  EthernetClient client = server.available();
            +
            +  // Do we have a client?
            +  if (!client) return;
            +
            +  Serial.println(F("New client"));
            +
            +  // Read the request (we ignore the content in this example)
            +  while (client.available()) client.read();
            +
            +  // Allocate JsonBuffer
            +  // Use arduinojson.org/assistant to compute the capacity.
            +  StaticJsonBuffer<500> jsonBuffer;
            +
            +  // Create the root object
            +  JsonObject& root = jsonBuffer.createObject();
            +
            +  // Create the "analog" array
            +  JsonArray& analogValues = root.createNestedArray("analog");
            +  for (int pin = 0; pin < 6; pin++) {
            +    // Read the analog input
            +    int value = analogRead(pin);
            +
            +    // Add the value at the end of the array
            +    analogValues.add(value);
            +  }
            +
            +  // Create the "digital" array
            +  JsonArray& digitalValues = root.createNestedArray("digital");
            +  for (int pin = 0; pin < 14; pin++) {
            +    // Read the digital input
            +    int value = digitalRead(pin);
            +
            +    // Add the value at the end of the array
            +    digitalValues.add(value);
            +  }
            +
            +  Serial.print(F("Sending: "));
            +  root.printTo(Serial);
            +  Serial.println();
            +
            +  // Write response headers
            +  client.println("HTTP/1.0 200 OK");
            +  client.println("Content-Type: application/json");
            +  client.println("Connection: close");
            +  client.println();
            +
            +  // Write JSON document
            +  root.prettyPrintTo(client);
            +
            +  // Disconnect
            +  client.stop();
            +}
            +
            +// See also
            +// --------
            +//
            +// https://arduinojson.org/ contains the documentation for all the functions
            +// used above. It also includes an FAQ that will help you solve any
            +// serialization problem.
            +//
            +// The book "Mastering ArduinoJson" contains a tutorial on serialization.
            +// It begins with a simple example, then adds more features like serializing
            +// directly to a file or an HTTP client.
            +// Learn more at https://arduinojson.org/book/
            +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
            diff --git a/lib/ArduinoJson-5.13.4/examples/JsonUdpBeacon/JsonUdpBeacon.ino b/lib/ArduinoJson-5.13.4/examples/JsonUdpBeacon/JsonUdpBeacon.ino
            new file mode 100644
            index 000000000..b2328a62d
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/examples/JsonUdpBeacon/JsonUdpBeacon.ino
            @@ -0,0 +1,101 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +//
            +// This example shows how to send a JSON document to a UDP socket.
            +// At regular interval, it sends a UDP packet that contains the status of
            +// analog and digital pins.
            +// The JSON document looks like the following:
            +// {
            +//   "analog": [ 0, 1, 2, 3, 4, 5 ],
            +//   "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
            +// }
            +//
            +// If you want to test this program, you need to be able to receive the UDP
            +// packets.
            +// For example, you can run netcat on your computer
            +// $ ncat -ulp 8888
            +// See https://nmap.org/ncat/
            +
            +#include 
            +#include 
            +#include 
            +
            +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
            +IPAddress remoteIp(192, 168, 0, 108);  // <- EDIT!!!!
            +unsigned short remotePort = 8888;
            +unsigned short localPort = 8888;
            +EthernetUDP udp;
            +
            +void setup() {
            +  // Initialize serial port
            +  Serial.begin(9600);
            +  while (!Serial) continue;
            +
            +  // Initialize Ethernet libary
            +  if (!Ethernet.begin(mac)) {
            +    Serial.println(F("Failed to initialize Ethernet library"));
            +    return;
            +  }
            +
            +  // Enable UDP
            +  udp.begin(localPort);
            +}
            +
            +void loop() {
            +  // Allocate JsonBuffer
            +  // Use arduinojson.org/assistant to compute the capacity.
            +  StaticJsonBuffer<500> jsonBuffer;
            +
            +  // Create the root object
            +  JsonObject& root = jsonBuffer.createObject();
            +
            +  // Create the "analog" array
            +  JsonArray& analogValues = root.createNestedArray("analog");
            +  for (int pin = 0; pin < 6; pin++) {
            +    // Read the analog input
            +    int value = analogRead(pin);
            +
            +    // Add the value at the end of the array
            +    analogValues.add(value);
            +  }
            +
            +  // Create the "digital" array
            +  JsonArray& digitalValues = root.createNestedArray("digital");
            +  for (int pin = 0; pin < 14; pin++) {
            +    // Read the digital input
            +    int value = digitalRead(pin);
            +
            +    // Add the value at the end of the array
            +    digitalValues.add(value);
            +  }
            +
            +  // Log
            +  Serial.print(F("Sending to "));
            +  Serial.print(remoteIp);
            +  Serial.print(F(" on port "));
            +  Serial.println(remotePort);
            +  root.printTo(Serial);
            +
            +  // Send UDP packet
            +  udp.beginPacket(remoteIp, remotePort);
            +  root.printTo(udp);
            +  udp.println();
            +  udp.endPacket();
            +
            +  // Wait
            +  delay(10000);
            +}
            +
            +// See also
            +// --------
            +//
            +// https://arduinojson.org/ contains the documentation for all the functions
            +// used above. It also includes an FAQ that will help you solve any
            +// serialization problem.
            +//
            +// The book "Mastering ArduinoJson" contains a tutorial on serialization.
            +// It begins with a simple example, then adds more features like serializing
            +// directly to a file or any stream.
            +// Learn more at https://arduinojson.org/book/
            +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
            diff --git a/lib/ArduinoJson-5.11.2/examples/ProgmemExample/ProgmemExample.ino b/lib/ArduinoJson-5.13.4/examples/ProgmemExample/ProgmemExample.ino
            similarity index 52%
            rename from lib/ArduinoJson-5.11.2/examples/ProgmemExample/ProgmemExample.ino
            rename to lib/ArduinoJson-5.13.4/examples/ProgmemExample/ProgmemExample.ino
            index 195b014fb..ddde8fd1d 100644
            --- a/lib/ArduinoJson-5.11.2/examples/ProgmemExample/ProgmemExample.ino
            +++ b/lib/ArduinoJson-5.13.4/examples/ProgmemExample/ProgmemExample.ino
            @@ -1,21 +1,19 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
             //
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
            +// This example shows the different ways you can use Flash strings with
            +// ArduinoJson.
            +//
            +// Use Flash strings sparingly, because ArduinoJson duplicates them in the
            +// JsonBuffer. Prefer plain old char*, as they are more efficient in term of
            +// code size, speed, and memory usage.
             
             #include 
             
            -// About
            -// -----
            -// This example shows the different ways you can use PROGMEM with ArduinoJson.
            -// Please don't see this as an invitation to use PROGMEM.
            -// On the contrary, you should always use char[] when possible, it's much more
            -// efficient in term of code size, speed and memory usage.
            -
             void setup() {
            -#ifdef PROGMEM
            +#ifdef PROGMEM  // <- check that Flash strings are supported
            +
               DynamicJsonBuffer jsonBuffer;
             
               // You can use a Flash String as your JSON input.
            @@ -39,6 +37,9 @@ void setup() {
               // JsonBuffer.
               root["sensor"] = F("gps");
             
            +  // It works with RawJson too:
            +  root["sensor"] = RawJson(F("\"gps\""));
            +
               // You can compare the content of a JsonVariant to a Flash String
               if (root["sensor"] == F("gps")) {
                 // ...
            @@ -54,3 +55,16 @@ void setup() {
             void loop() {
               // not used in this example
             }
            +
            +// See also
            +// --------
            +//
            +// https://arduinojson.org/ contains the documentation for all the functions
            +// used above. It also includes an FAQ that will help you solve any memory
            +// problem.
            +//
            +// The book "Mastering ArduinoJson" contains a quick C++ course that explains
            +// how your microcontroller stores strings in memory. It also tells why you
            +// should not abuse Flash strings with ArduinoJson.
            +// Learn more at https://arduinojson.org/book/
            +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
            diff --git a/lib/ArduinoJson-5.11.2/examples/StringExample/StringExample.ino b/lib/ArduinoJson-5.13.4/examples/StringExample/StringExample.ino
            similarity index 67%
            rename from lib/ArduinoJson-5.11.2/examples/StringExample/StringExample.ino
            rename to lib/ArduinoJson-5.13.4/examples/StringExample/StringExample.ino
            index 50b8db6ec..fc7503d0e 100644
            --- a/lib/ArduinoJson-5.11.2/examples/StringExample/StringExample.ino
            +++ b/lib/ArduinoJson-5.13.4/examples/StringExample/StringExample.ino
            @@ -1,19 +1,15 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
             //
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
            +// This example shows the different ways you can use String with ArduinoJson.
            +//
            +// Use String objects sparingly, because ArduinoJson duplicates them in the
            +// JsonBuffer. Prefer plain old char[], as they are more efficient in term of
            +// code size, speed, and memory usage.
             
             #include 
             
            -// About
            -// -----
            -// This example shows the different ways you can use String with ArduinoJson.
            -// Please don't see this as an invitation to use String.
            -// On the contrary, you should always use char[] when possible, it's much more
            -// efficient in term of code size, speed and memory usage.
            -
             void setup() {
               DynamicJsonBuffer jsonBuffer;
             
            @@ -44,6 +40,9 @@ void setup() {
               // WARNING: the content of the String will be duplicated in the JsonBuffer.
               root["sensor"] = sensor;
             
            +  // It works with RawJson too:
            +  root["sensor"] = RawJson(sensor);
            +
               // You can also concatenate strings
               // WARNING: the content of the String will be duplicated in the JsonBuffer.
               root[String("sen") + "sor"] = String("gp") + "s";
            @@ -61,3 +60,15 @@ void setup() {
             void loop() {
               // not used in this example
             }
            +
            +// See also
            +// --------
            +//
            +// https://arduinojson.org/ contains the documentation for all the functions
            +// used above. It also includes an FAQ that will help you solve any problem.
            +//
            +// The book "Mastering ArduinoJson" contains a quick C++ course that explains
            +// how your microcontroller stores strings in memory. On several occasions, it
            +// shows how you can avoid String in your program.
            +// Learn more at https://arduinojson.org/book/
            +// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
            diff --git a/lib/ArduinoJson-5.11.2/keywords.txt b/lib/ArduinoJson-5.13.4/keywords.txt
            similarity index 100%
            rename from lib/ArduinoJson-5.11.2/keywords.txt
            rename to lib/ArduinoJson-5.13.4/keywords.txt
            diff --git a/lib/ArduinoJson-5.13.4/library.properties b/lib/ArduinoJson-5.13.4/library.properties
            new file mode 100644
            index 000000000..67ccbb95e
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/library.properties
            @@ -0,0 +1,11 @@
            +name=ArduinoJson
            +version=5.13.4
            +author=Benoit Blanchon 
            +maintainer=Benoit Blanchon 
            +sentence=An efficient and elegant JSON library for Arduino.
            +paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ fixed allocation, ✔ zero-copy, ✔ streams, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation.
            +category=Data Processing
            +url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
            +architectures=*
            +repository=https://github.com/bblanchon/ArduinoJson.git
            +license=MIT
            diff --git a/lib/ArduinoJson-5.13.4/src/ArduinoJson.h b/lib/ArduinoJson-5.13.4/src/ArduinoJson.h
            new file mode 100644
            index 000000000..3782aeabc
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson.h
            @@ -0,0 +1,17 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +
            +#pragma once
            +
            +#ifdef __cplusplus
            +
            +#include "ArduinoJson.hpp"
            +
            +using namespace ArduinoJson;
            +
            +#else
            +
            +#error ArduinoJson requires a C++ compiler, please change file extension to .cc or .cpp
            +
            +#endif
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson.hpp
            similarity index 75%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson.hpp
            index 949fa5ca0..c493c06a9 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson.hpp
            @@ -1,12 +1,11 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            +#include "ArduinoJson/version.hpp"
            +
             #include "ArduinoJson/DynamicJsonBuffer.hpp"
             #include "ArduinoJson/JsonArray.hpp"
             #include "ArduinoJson/JsonObject.hpp"
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Configuration.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Configuration.hpp
            similarity index 94%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Configuration.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Configuration.hpp
            index a1015a6f3..82483adfa 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Configuration.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Configuration.hpp
            @@ -1,15 +1,13 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             // Small or big machine?
             #ifndef ARDUINOJSON_EMBEDDED_MODE
            -#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__)
            +#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) || defined(__XC) || \
            +    defined(__ARMCC_VERSION)
             #define ARDUINOJSON_EMBEDDED_MODE 1
             #else
             #define ARDUINOJSON_EMBEDDED_MODE 0
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/Encoding.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/Encoding.hpp
            similarity index 80%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/Encoding.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/Encoding.hpp
            index dba785aae..a0efa2c74 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/Encoding.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/Encoding.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonBufferAllocated.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonBufferAllocated.hpp
            similarity index 68%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonBufferAllocated.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonBufferAllocated.hpp
            index ff74adc55..443aae4df 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonBufferAllocated.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonBufferAllocated.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonFloat.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonFloat.hpp
            similarity index 56%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonFloat.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonFloat.hpp
            index a4a8e937f..0ed42140f 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonFloat.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonFloat.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonInteger.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonInteger.hpp
            similarity index 70%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonInteger.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonInteger.hpp
            index 574a5e109..c8ddd00b4 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonInteger.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonInteger.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantAs.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonVariantAs.hpp
            similarity index 80%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantAs.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonVariantAs.hpp
            index 3f19fd23a..8f202c5eb 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantAs.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonVariantAs.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantContent.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonVariantContent.hpp
            similarity index 79%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantContent.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonVariantContent.hpp
            index b27716299..c525a6060 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantContent.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonVariantContent.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantDefault.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonVariantDefault.hpp
            similarity index 68%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantDefault.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonVariantDefault.hpp
            index a59fd46c9..57ecc83ee 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantDefault.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonVariantDefault.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantType.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonVariantType.hpp
            similarity index 84%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantType.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonVariantType.hpp
            index ba6a24999..21f890e52 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantType.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/JsonVariantType.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/List.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/List.hpp
            similarity index 93%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/List.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/List.hpp
            index 8a24666ec..506308cc3 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/List.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/List.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListConstIterator.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ListConstIterator.hpp
            similarity index 85%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListConstIterator.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ListConstIterator.hpp
            index bce1bfa5e..a6af685e5 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListConstIterator.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ListConstIterator.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListIterator.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ListIterator.hpp
            similarity index 86%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListIterator.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ListIterator.hpp
            index a491866f0..01fa287f7 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListIterator.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ListIterator.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListNode.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ListNode.hpp
            similarity index 70%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListNode.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ListNode.hpp
            index 712e15e1f..c0907120e 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListNode.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ListNode.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/NonCopyable.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/NonCopyable.hpp
            similarity index 67%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/NonCopyable.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/NonCopyable.hpp
            index 98ebd8fb3..73f3d8edb 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/NonCopyable.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/NonCopyable.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ReferenceType.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ReferenceType.hpp
            similarity index 74%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ReferenceType.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ReferenceType.hpp
            index bbc9046be..1e491172f 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ReferenceType.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ReferenceType.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ValueSaver.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ValueSaver.hpp
            new file mode 100644
            index 000000000..9750f1ac5
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Data/ValueSaver.hpp
            @@ -0,0 +1,52 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +
            +#pragma once
            +
            +#include "../JsonBuffer.hpp"
            +#include "../JsonVariant.hpp"
            +#include "../StringTraits/StringTraits.hpp"
            +#include "../TypeTraits/EnableIf.hpp"
            +
            +namespace ArduinoJson {
            +namespace Internals {
            +
            +template 
            +struct ValueSaver {
            +  template 
            +  static bool save(JsonBuffer*, Destination& destination, Source source) {
            +    destination = source;
            +    return true;
            +  }
            +};
            +
            +template 
            +struct ValueSaver<
            +    Source, typename EnableIf::should_duplicate>::type> {
            +  template 
            +  static bool save(JsonBuffer* buffer, Destination& dest, Source source) {
            +    if (!StringTraits::is_null(source)) {
            +      typename StringTraits::duplicate_t dup =
            +          StringTraits::duplicate(source, buffer);
            +      if (!dup) return false;
            +      dest = dup;
            +    } else {
            +      dest = reinterpret_cast(0);
            +    }
            +    return true;
            +  }
            +};
            +
            +// const char*, const signed char*, const unsigned char*
            +template 
            +struct ValueSaver<
            +    Char*, typename EnableIf::should_duplicate>::type> {
            +  template 
            +  static bool save(JsonBuffer*, Destination& dest, Char* source) {
            +    dest = reinterpret_cast(source);
            +    return true;
            +  }
            +};
            +}
            +}
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/Comments.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Deserialization/Comments.hpp
            similarity index 88%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/Comments.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Deserialization/Comments.hpp
            index 9f281da49..c2c48ebcc 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/Comments.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Deserialization/Comments.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParser.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Deserialization/JsonParser.hpp
            similarity index 77%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParser.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Deserialization/JsonParser.hpp
            index 3e605ef25..4cbaf454c 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParser.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Deserialization/JsonParser.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -47,19 +44,18 @@ class JsonParser {
             
               const char *parseString();
               bool parseAnythingTo(JsonVariant *destination);
            -  FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
             
               inline bool parseArrayTo(JsonVariant *destination);
               inline bool parseObjectTo(JsonVariant *destination);
               inline bool parseStringTo(JsonVariant *destination);
             
            -  static inline bool isInRange(char c, char min, char max) {
            +  static inline bool isBetween(char c, char min, char max) {
                 return min <= c && c <= max;
               }
             
            -  static inline bool isLetterOrNumber(char c) {
            -    return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') ||
            -           isInRange(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
            +  static inline bool canBeInNonQuotedString(char c) {
            +    return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
            +           isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
               }
             
               static inline bool isQuote(char c) {
            @@ -74,7 +70,7 @@ class JsonParser {
             
             template 
             struct JsonParserBuilder {
            -  typedef typename Internals::StringTraits::Reader InputReader;
            +  typedef typename StringTraits::Reader InputReader;
               typedef JsonParser TParser;
             
               static TParser makeParser(TJsonBuffer *buffer, TString &json,
            @@ -84,10 +80,9 @@ struct JsonParserBuilder {
             };
             
             template 
            -struct JsonParserBuilder<
            -    TJsonBuffer, TChar *,
            -    typename TypeTraits::EnableIf::value>::type> {
            -  typedef typename Internals::StringTraits::Reader TReader;
            +struct JsonParserBuilder::value>::type> {
            +  typedef typename StringTraits::Reader TReader;
               typedef StringWriter TWriter;
               typedef JsonParser TParser;
             
            @@ -103,5 +98,5 @@ inline typename JsonParserBuilder::TParser makeParser(
               return JsonParserBuilder::makeParser(buffer, json,
                                                                          nestingLimit);
             }
            -}
            -}
            +}  // namespace Internals
            +}  // namespace ArduinoJson
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParserImpl.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Deserialization/JsonParserImpl.hpp
            similarity index 85%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParserImpl.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Deserialization/JsonParserImpl.hpp
            index 1c41bdaac..504267355 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParserImpl.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Deserialization/JsonParserImpl.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -20,18 +17,9 @@ inline bool ArduinoJson::Internals::JsonParser::eat(
             }
             
             template 
            -inline bool ArduinoJson::Internals::JsonParser<
            -    TReader, TWriter>::parseAnythingTo(JsonVariant *destination) {
            -  if (_nestingLimit == 0) return false;
            -  _nestingLimit--;
            -  bool success = parseAnythingToUnsafe(destination);
            -  _nestingLimit++;
            -  return success;
            -}
            -
            -template 
            -inline bool ArduinoJson::Internals::JsonParser<
            -    TReader, TWriter>::parseAnythingToUnsafe(JsonVariant *destination) {
            +inline bool
            +ArduinoJson::Internals::JsonParser::parseAnythingTo(
            +    JsonVariant *destination) {
               skipSpacesAndComments(_reader);
             
               switch (_reader.current()) {
            @@ -49,6 +37,9 @@ inline bool ArduinoJson::Internals::JsonParser<
             template 
             inline ArduinoJson::JsonArray &
             ArduinoJson::Internals::JsonParser::parseArray() {
            +  if (_nestingLimit == 0) return JsonArray::invalid();
            +  _nestingLimit--;
            +
               // Create an empty array
               JsonArray &array = _buffer->createArray();
             
            @@ -70,6 +61,7 @@ ArduinoJson::Internals::JsonParser::parseArray() {
             
             SUCCESS_EMPTY_ARRAY:
             SUCCES_NON_EMPTY_ARRAY:
            +  _nestingLimit++;
               return array;
             
             ERROR_INVALID_VALUE:
            @@ -92,6 +84,9 @@ inline bool ArduinoJson::Internals::JsonParser::parseArrayTo(
             template 
             inline ArduinoJson::JsonObject &
             ArduinoJson::Internals::JsonParser::parseObject() {
            +  if (_nestingLimit == 0) return JsonObject::invalid();
            +  _nestingLimit--;
            +
               // Create an empty object
               JsonObject &object = _buffer->createObject();
             
            @@ -118,6 +113,7 @@ ArduinoJson::Internals::JsonParser::parseObject() {
             
             SUCCESS_EMPTY_OBJECT:
             SUCCESS_NON_EMPTY_OBJECT:
            +  _nestingLimit++;
               return object;
             
             ERROR_INVALID_KEY:
            @@ -142,8 +138,7 @@ inline bool ArduinoJson::Internals::JsonParser::parseObjectTo(
             template 
             inline const char *
             ArduinoJson::Internals::JsonParser::parseString() {
            -  typename TypeTraits::RemoveReference::type::String str =
            -      _writer.startString();
            +  typename RemoveReference::type::String str = _writer.startString();
             
               skipSpacesAndComments(_reader);
               char c = _reader.current();
            @@ -169,7 +164,7 @@ ArduinoJson::Internals::JsonParser::parseString() {
                 }
               } else {  // no quotes
                 for (;;) {
            -      if (!isLetterOrNumber(c)) break;
            +      if (!canBeInNonQuotedString(c)) break;
                   _reader.move();
                   str.append(c);
                   c = _reader.current();
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/StringWriter.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Deserialization/StringWriter.hpp
            similarity index 79%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/StringWriter.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Deserialization/StringWriter.hpp
            index 42ee640d8..fd5507ea5 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/StringWriter.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Deserialization/StringWriter.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/DynamicJsonBuffer.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/DynamicJsonBuffer.hpp
            similarity index 94%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/DynamicJsonBuffer.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/DynamicJsonBuffer.hpp
            index 65e744bf2..bdbd5dd90 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/DynamicJsonBuffer.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/DynamicJsonBuffer.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -22,6 +19,7 @@
             #endif
             
             namespace ArduinoJson {
            +namespace Internals {
             class DefaultAllocator {
              public:
               void* allocate(size_t size) {
            @@ -154,6 +152,7 @@ class DynamicJsonBufferBase
               Block* _head;
               size_t _nextBlockCapacity;
             };
            +}
             
             #if defined(__clang__)
             #pragma clang diagnostic pop
            @@ -166,5 +165,6 @@ class DynamicJsonBufferBase
             // Implements a JsonBuffer with dynamic memory allocation.
             // You are strongly encouraged to consider using StaticJsonBuffer which is much
             // more suitable for embedded systems.
            -typedef DynamicJsonBufferBase DynamicJsonBuffer;
            +typedef Internals::DynamicJsonBufferBase
            +    DynamicJsonBuffer;
             }
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArray.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonArray.hpp
            similarity index 82%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArray.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonArray.hpp
            index 27404fb7b..2acd2a1a5 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArray.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonArray.hpp
            @@ -1,16 +1,13 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             #include "Data/JsonBufferAllocated.hpp"
             #include "Data/List.hpp"
             #include "Data/ReferenceType.hpp"
            -#include "Data/ValueSetter.hpp"
            +#include "Data/ValueSaver.hpp"
             #include "JsonVariant.hpp"
             #include "Serialization/JsonPrintable.hpp"
             #include "StringTraits/StringTraits.hpp"
            @@ -29,7 +26,9 @@ namespace ArduinoJson {
             // Forward declarations
             class JsonObject;
             class JsonBuffer;
            +namespace Internals {
             class JsonArraySubscript;
            +}
             
             // An array of JsonVariant.
             //
            @@ -50,28 +49,26 @@ class JsonArray : public Internals::JsonPrintable,
                   : Internals::List(buffer) {}
             
               // Gets the value at the specified index
            -  const JsonArraySubscript operator[](size_t index) const;
            +  const Internals::JsonArraySubscript operator[](size_t index) const;
             
               // Gets or sets the value at specified index
            -  JsonArraySubscript operator[](size_t index);
            +  Internals::JsonArraySubscript operator[](size_t index);
             
               // Adds the specified value at the end of the array.
               //
               // bool add(TValue);
               // TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
            -  //          const std::string&, const String&,
            -  //          const JsonArray&, const JsonObject&
            +  //          std::string, String, JsonArray, JsonObject
               template 
            -  typename TypeTraits::EnableIf::value, bool>::type add(
            -      const T &value) {
            +  bool add(const T &value) {
                 return add_impl(value);
               }
               //
               // bool add(TValue);
            -  // TValue = const char*, const char[N], const FlashStringHelper*
            +  // TValue = char*, const char*, const FlashStringHelper*
               template 
            -  bool add(const T *value) {
            -    return add_impl(value);
            +  bool add(T *value) {
            +    return add_impl(value);
               }
               //
               // bool add(TValue value, uint8_t decimals);
            @@ -84,28 +81,25 @@ class JsonArray : public Internals::JsonPrintable,
             
               // Sets the value at specified index.
               //
            -  // bool add(size_t index, TValue);
            +  // bool add(size_t index, const TValue&);
               // TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
            -  //          const std::string&, const String&,
            -  //          const JsonArray&, const JsonObject&
            +  //          std::string, String, JsonArray, JsonObject
               template 
            -  typename TypeTraits::EnableIf::value, bool>::type set(
            -      size_t index, const T &value) {
            +  bool set(size_t index, const T &value) {
                 return set_impl(index, value);
               }
               //
               // bool add(size_t index, TValue);
            -  // TValue = const char*, const char[N], const FlashStringHelper*
            +  // TValue = char*, const char*, const FlashStringHelper*
               template 
            -  bool set(size_t index, const T *value) {
            -    return set_impl(index, value);
            +  bool set(size_t index, T *value) {
            +    return set_impl(index, value);
               }
               //
               // bool set(size_t index, TValue value, uint8_t decimals);
               // TValue = float, double
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                bool>::type
            +  typename Internals::EnableIf::value, bool>::type
               set(size_t index, T value, uint8_t decimals) {
                 return set_impl(index, JsonVariant(value, decimals));
               }
            @@ -211,14 +205,14 @@ class JsonArray : public Internals::JsonPrintable,
               bool set_impl(size_t index, TValueRef value) {
                 iterator it = begin() += index;
                 if (it == end()) return false;
            -    return Internals::ValueSetter::set(_buffer, *it, value);
            +    return Internals::ValueSaver::save(_buffer, *it, value);
               }
             
               template 
               bool add_impl(TValueRef value) {
                 iterator it = Internals::List::add();
                 if (it == end()) return false;
            -    return Internals::ValueSetter::set(_buffer, *it, value);
            +    return Internals::ValueSaver::save(_buffer, *it, value);
               }
             };
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArrayImpl.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonArrayImpl.hpp
            similarity index 75%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArrayImpl.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonArrayImpl.hpp
            index 6ebd39baa..924b7ea7a 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArrayImpl.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonArrayImpl.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArraySubscript.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonArraySubscript.hpp
            similarity index 69%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArraySubscript.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonArraySubscript.hpp
            index 5bd6208a5..afb4dc1ec 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArraySubscript.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonArraySubscript.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -16,6 +13,7 @@
             #endif
             
             namespace ArduinoJson {
            +namespace Internals {
             class JsonArraySubscript : public JsonVariantBase {
              public:
               FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
            @@ -28,10 +26,9 @@ class JsonArraySubscript : public JsonVariantBase {
             
               // Replaces the value
               //
            -  // operator=(TValue)
            +  // operator=(const TValue&)
               // TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
            -  //          const std::string&, const String&,
            -  //          const JsonArray&, const JsonObject&
            +  //          std::string, String, JsonArray, JsonObject
               template 
               FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
                 _array.set(_index, src);
            @@ -39,9 +36,9 @@ class JsonArraySubscript : public JsonVariantBase {
               }
               //
               // operator=(TValue)
            -  // TValue = const char*, const char[N], const FlashStringHelper*
            +  // TValue = char*, const char*, const FlashStringHelper*
               template 
            -  FORCE_INLINE JsonArraySubscript& operator=(const T* src) {
            +  FORCE_INLINE JsonArraySubscript& operator=(T* src) {
                 _array.set(_index, src);
                 return *this;
               }
            @@ -51,7 +48,7 @@ class JsonArraySubscript : public JsonVariantBase {
               }
             
               template 
            -  FORCE_INLINE typename Internals::JsonVariantAs::type as() const {
            +  FORCE_INLINE typename JsonVariantAs::type as() const {
                 return _array.get(_index);
               }
             
            @@ -62,19 +59,18 @@ class JsonArraySubscript : public JsonVariantBase {
             
               // Replaces the value
               //
            -  // bool set(TValue)
            +  // bool set(const TValue&)
               // TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
            -  //          const std::string&, const String&,
            -  //          const JsonArray&, const JsonObject&
            +  //          std::string, String, JsonArray, JsonObject
               template 
               FORCE_INLINE bool set(const TValue& value) {
                 return _array.set(_index, value);
               }
               //
               // bool set(TValue)
            -  // TValue = const char*, const char[N], const FlashStringHelper*
            +  // TValue = char*, const char*, const FlashStringHelper*
               template 
            -  FORCE_INLINE bool set(const TValue* value) {
            +  FORCE_INLINE bool set(TValue* value) {
                 return _array.set(_index, value);
               }
               //
            @@ -91,21 +87,6 @@ class JsonArraySubscript : public JsonVariantBase {
               const size_t _index;
             };
             
            -#if ARDUINOJSON_ENABLE_STD_STREAM
            -inline std::ostream& operator<<(std::ostream& os,
            -                                const JsonArraySubscript& source) {
            -  return source.printTo(os);
            -}
            -#endif
            -
            -inline JsonArraySubscript JsonArray::operator[](size_t index) {
            -  return JsonArraySubscript(*this, index);
            -}
            -
            -inline const JsonArraySubscript JsonArray::operator[](size_t index) const {
            -  return JsonArraySubscript(*const_cast(this), index);
            -}
            -
             template 
             inline JsonArraySubscript JsonVariantSubscripts::operator[](
                 size_t index) {
            @@ -118,7 +99,23 @@ inline const JsonArraySubscript JsonVariantSubscripts::operator[](
               return impl()->template as()[index];
             }
             
            -}  // namespace ArduinoJson
            +#if ARDUINOJSON_ENABLE_STD_STREAM
            +inline std::ostream& operator<<(std::ostream& os,
            +                                const JsonArraySubscript& source) {
            +  return source.printTo(os);
            +}
            +#endif
            +}
            +
            +inline Internals::JsonArraySubscript JsonArray::operator[](size_t index) {
            +  return Internals::JsonArraySubscript(*this, index);
            +}
            +
            +inline const Internals::JsonArraySubscript JsonArray::operator[](
            +    size_t index) const {
            +  return Internals::JsonArraySubscript(*const_cast(this), index);
            +}
            +}
             
             #ifdef _MSC_VER
             #pragma warning(pop)
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBuffer.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonBuffer.hpp
            similarity index 74%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBuffer.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonBuffer.hpp
            index 06bda0ef4..26101e086 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBuffer.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonBuffer.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -41,20 +38,21 @@ class JsonBuffer : Internals::NonCopyable {
             
               // Duplicates a string
               //
            -  // char* strdup(TValue);
            +  // const char* strdup(TValue);
               // TValue = const std::string&, const String&,
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                char *>::type
            -  strdup(const TString &src) {
            +  DEPRECATED("char* are duplicated, you don't need strdup() anymore")
            +  typename Internals::EnableIf::value,
            +                               const char *>::type strdup(const TString &src) {
                 return Internals::StringTraits::duplicate(src, this);
               }
               //
            -  // char* strdup(TValue);
            -  // TValue = const char*, const char[N], const FlashStringHelper*
            +  // const char* strdup(TValue);
            +  // TValue = char*, const char*, const FlashStringHelper*
               template 
            -  char *strdup(const TString *src) {
            -    return Internals::StringTraits::duplicate(src, this);
            +  DEPRECATED("char* are duplicated, you don't need strdup() anymore")
            +  const char *strdup(TString *src) {
            +    return Internals::StringTraits::duplicate(src, this);
               }
             
               // Allocates n bytes in the JsonBuffer.
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferBase.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonBufferBase.hpp
            similarity index 88%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferBase.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonBufferBase.hpp
            index 480cd8307..1e771bfdb 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferBase.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonBufferBase.hpp
            @@ -1,15 +1,13 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             #include "Deserialization/JsonParser.hpp"
             
             namespace ArduinoJson {
            +namespace Internals {
             template 
             class JsonBufferBase : public JsonBuffer {
              public:
            @@ -28,8 +26,8 @@ class JsonBufferBase : public JsonBuffer {
               // JsonArray& parseArray(TString);
               // TString = const std::string&, const String&
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                JsonArray &>::type
            +  typename Internals::EnableIf::value,
            +                               JsonArray &>::type
               parseArray(const TString &json,
                          uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
                 return Internals::makeParser(that(), json, nestingLimit).parseArray();
            @@ -65,8 +63,8 @@ class JsonBufferBase : public JsonBuffer {
               // JsonObject& parseObject(TString);
               // TString = const std::string&, const String&
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                JsonObject &>::type
            +  typename Internals::EnableIf::value,
            +                               JsonObject &>::type
               parseObject(const TString &json,
                           uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
                 return Internals::makeParser(that(), json, nestingLimit).parseObject();
            @@ -94,8 +92,8 @@ class JsonBufferBase : public JsonBuffer {
               // JsonVariant parse(TString);
               // TString = const std::string&, const String&
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                JsonVariant>::type
            +  typename Internals::EnableIf::value,
            +                               JsonVariant>::type
               parse(const TString &json,
                     uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
                 return Internals::makeParser(that(), json, nestingLimit).parseVariant();
            @@ -126,3 +124,4 @@ class JsonBufferBase : public JsonBuffer {
               }
             };
             }
            +}
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferImpl.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonBufferImpl.hpp
            similarity index 72%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferImpl.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonBufferImpl.hpp
            index 98d5de595..cdea374bb 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferImpl.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonBufferImpl.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObject.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonObject.hpp
            similarity index 57%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObject.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonObject.hpp
            index a3e30ab27..caf698a3e 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObject.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonObject.hpp
            @@ -1,16 +1,13 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             #include "Data/JsonBufferAllocated.hpp"
             #include "Data/List.hpp"
             #include "Data/ReferenceType.hpp"
            -#include "Data/ValueSetter.hpp"
            +#include "Data/ValueSaver.hpp"
             #include "JsonPair.hpp"
             #include "Serialization/JsonPrintable.hpp"
             #include "StringTraits/StringTraits.hpp"
            @@ -29,6 +26,10 @@ namespace ArduinoJson {
             // Forward declarations
             class JsonArray;
             class JsonBuffer;
            +namespace Internals {
            +template 
            +class JsonObjectSubscript;
            +}
             
             // A dictionary of JsonVariant indexed by string (char*)
             //
            @@ -45,25 +46,24 @@ class JsonObject : public Internals::JsonPrintable,
               // Create an empty JsonArray attached to the specified JsonBuffer.
               // You should not use this constructor directly.
               // Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
            -  explicit JsonObject(JsonBuffer* buffer) throw() 
            -    : Internals::List(buffer) {}
            +  explicit JsonObject(JsonBuffer* buffer) throw()
            +      : Internals::List(buffer) {}
             
               // Gets or sets the value associated with the specified key.
               //
               // JsonObjectSubscript operator[](TKey)
               // TKey = const std::string&, const String&
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                JsonObjectSubscript >::type
            -  operator[](const TString& key) {
            -    return JsonObjectSubscript(*this, key);
            +  Internals::JsonObjectSubscript operator[](
            +      const TString& key) {
            +    return Internals::JsonObjectSubscript(*this, key);
               }
               //
               // JsonObjectSubscript operator[](TKey)
            -  // TKey = const char*, const char[N], const FlashStringHelper*
            +  // TKey = char*, const char*, char[], const char[N], const FlashStringHelper*
               template 
            -  JsonObjectSubscript operator[](const TString* key) {
            -    return JsonObjectSubscript(*this, key);
            +  Internals::JsonObjectSubscript operator[](TString* key) {
            +    return Internals::JsonObjectSubscript(*this, key);
               }
             
               // Gets the value associated with the specified key.
            @@ -71,21 +71,19 @@ class JsonObject : public Internals::JsonPrintable,
               // const JsonObjectSubscript operator[](TKey) const;
               // TKey = const std::string&, const String&
               template 
            -  typename TypeTraits::EnableIf<
            -      !TypeTraits::IsArray::value,
            -      const JsonObjectSubscript >::type
            -  operator[](const TString& key) const {
            -    return JsonObjectSubscript(*const_cast(this),
            -                                               key);
            +  const Internals::JsonObjectSubscript operator[](
            +      const TString& key) const {
            +    return Internals::JsonObjectSubscript(
            +        *const_cast(this), key);
               }
               //
               // const JsonObjectSubscript operator[](TKey) const;
               // TKey = const char*, const char[N], const FlashStringHelper*
               template 
            -  const JsonObjectSubscript operator[](
            -      const TString* key) const {
            -    return JsonObjectSubscript(*const_cast(this),
            -                                               key);
            +  const Internals::JsonObjectSubscript operator[](
            +      TString* key) const {
            +    return Internals::JsonObjectSubscript(
            +        *const_cast(this), key);
               }
             
               // Sets the specified key with the specified value.
            @@ -93,43 +91,35 @@ class JsonObject : public Internals::JsonPrintable,
               // bool set(TKey, TValue);
               // TKey = const std::string&, const String&
               // TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
            -  //          const std::string&, const String&,
            -  //          const JsonArray&, const JsonObject&
            +  //          std::string, String, JsonArray, JsonObject
               template 
            -  typename TypeTraits::EnableIf::value &&
            -                                    !TypeTraits::IsArray::value,
            -                                bool>::type
            -  set(const TString& key, const TValue& value) {
            +  bool set(const TString& key, const TValue& value) {
                 return set_impl(key, value);
               }
               //
               // bool set(TKey, TValue);
               // TKey = const std::string&, const String&
            -  // TValue = const char*, const char[N], const FlashStringHelper*
            +  // TValue = char*, const char*, const FlashStringHelper*
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                bool>::type
            -  set(const TString& key, const TValue* value) {
            -    return set_impl(key, value);
            +  bool set(const TString& key, TValue* value) {
            +    return set_impl(key, value);
               }
               //
            -  // bool set(TKey, TValue);
            -  // TKey = const char*, const char[N], const FlashStringHelper*
            +  // bool set(TKey, const TValue&);
            +  // TKey = char*, const char*, const FlashStringHelper*
               // TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
            -  //          const std::string&, const String&,
            -  //          const JsonArray&, const JsonObject&
            +  //          std::string, String, JsonArray, JsonObject
               template 
            -  typename TypeTraits::EnableIf::value, bool>::type
            -  set(const TString* key, const TValue& value) {
            -    return set_impl(key, value);
            +  bool set(TString* key, const TValue& value) {
            +    return set_impl(key, value);
               }
               //
               // bool set(TKey, TValue);
            -  // TKey = const char*, const char[N], const FlashStringHelper*
            -  // TValue = const char*, const char[N], const FlashStringHelper*
            +  // TKey = char*, const char*, const FlashStringHelper*
            +  // TValue = char*, const char*, const FlashStringHelper*
               template 
            -  bool set(const TString* key, const TValue* value) {
            -    return set_impl(key, value);
            +  bool set(TString* key, TValue* value) {
            +    return set_impl(key, value);
               }
               //
               // bool set(TKey, TValue, uint8_t decimals);
            @@ -137,50 +127,43 @@ class JsonObject : public Internals::JsonPrintable,
               // TValue = float, double
               template 
               DEPRECATED("Second argument is not supported anymore")
            -  typename TypeTraits::EnableIf::value &&
            -                                    !TypeTraits::IsArray::value,
            -                                bool>::type
            +  typename Internals::EnableIf::value,
            +                               bool>::type
                   set(const TString& key, TValue value, uint8_t) {
                 return set_impl(key,
                                                                     JsonVariant(value));
               }
               //
               // bool set(TKey, TValue, uint8_t decimals);
            -  // TKey = const char*, const char[N], const FlashStringHelper*
            +  // TKey = char*, const char*, const FlashStringHelper*
               // TValue = float, double
               template 
               DEPRECATED("Second argument is not supported anymore")
            -  typename TypeTraits::EnableIf::value,
            -                                bool>::type
            -      set(const TString* key, TValue value, uint8_t) {
            -    return set_impl(key,
            -                                                        JsonVariant(value));
            +  typename Internals::EnableIf::value,
            +                               bool>::type
            +      set(TString* key, TValue value, uint8_t) {
            +    return set_impl(key, JsonVariant(value));
               }
             
               // Gets the value associated with the specified key.
               //
            -  // TValue get(TKey);
            +  // TValue get(TKey) const;
               // TKey = const std::string&, const String&
               // TValue = bool, char, long, int, short, float, double,
            -  //          const std::string&, const String&,
            -  //          const JsonArray&, const JsonObject&
            +  //          std::string, String, JsonArray, JsonObject
               template 
            -  typename TypeTraits::EnableIf<
            -      !TypeTraits::IsArray::value,
            -      typename Internals::JsonVariantAs::type>::type
            -  get(const TString& key) const {
            +  typename Internals::JsonVariantAs::type get(
            +      const TString& key) const {
                 return get_impl(key);
               }
               //
            -  // TValue get(TKey);
            -  // TKey = const char*, const char[N], const FlashStringHelper*
            +  // TValue get(TKey) const;
            +  // TKey = char*, const char*, const FlashStringHelper*
               // TValue = bool, char, long, int, short, float, double,
            -  //          const std::string&, const String&,
            -  //          const JsonArray&, const JsonObject&
            +  //          std::string, String, JsonArray, JsonObject
               template 
            -  typename Internals::JsonVariantAs::type get(
            -      const TString* key) const {
            -    return get_impl(key);
            +  typename Internals::JsonVariantAs::type get(TString* key) const {
            +    return get_impl(key);
               }
             
               // Checks the type of the value associated with the specified key.
            @@ -189,23 +172,19 @@ class JsonObject : public Internals::JsonPrintable,
               // bool is(TKey) const;
               // TKey = const std::string&, const String&
               // TValue = bool, char, long, int, short, float, double,
            -  //          const std::string&, const String&,
            -  //          const JsonArray&, const JsonObject&
            +  //          std::string, String, JsonArray, JsonObject
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                bool>::type
            -  is(const TString& key) const {
            +  bool is(const TString& key) const {
                 return is_impl(key);
               }
               //
               // bool is(TKey) const;
            -  // TKey = const char*, const char[N], const FlashStringHelper*
            +  // TKey = char*, const char*, const FlashStringHelper*
               // TValue = bool, char, long, int, short, float, double,
            -  //          const std::string&, const String&,
            -  //          const JsonArray&, const JsonObject&
            +  //          std::string, String, JsonArray, JsonObject
               template 
            -  bool is(const TString* key) const {
            -    return is_impl(key);
            +  bool is(TString* key) const {
            +    return is_impl(key);
               }
             
               // Creates and adds a JsonArray.
            @@ -213,16 +192,14 @@ class JsonObject : public Internals::JsonPrintable,
               // JsonArray& createNestedArray(TKey);
               // TKey = const std::string&, const String&
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                JsonArray&>::type
            -  createNestedArray(const TString& key) {
            +  JsonArray& createNestedArray(const TString& key) {
                 return createNestedArray_impl(key);
               }
               // JsonArray& createNestedArray(TKey);
            -  // TKey = const char*, const char[N], const FlashStringHelper*
            +  // TKey = char*, const char*, char[], const char[], const FlashStringHelper*
               template 
            -  JsonArray& createNestedArray(const TString* key) {
            -    return createNestedArray_impl(key);
            +  JsonArray& createNestedArray(TString* key) {
            +    return createNestedArray_impl(key);
               }
             
               // Creates and adds a JsonObject.
            @@ -230,17 +207,15 @@ class JsonObject : public Internals::JsonPrintable,
               // JsonObject& createNestedObject(TKey);
               // TKey = const std::string&, const String&
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                JsonObject&>::type
            -  createNestedObject(const TString& key) {
            +  JsonObject& createNestedObject(const TString& key) {
                 return createNestedObject_impl(key);
               }
               //
               // JsonObject& createNestedObject(TKey);
            -  // TKey = const char*, const char[N], const FlashStringHelper*
            +  // TKey = char*, const char*, char[], const char[], const FlashStringHelper*
               template 
            -  JsonObject& createNestedObject(const TString* key) {
            -    return createNestedObject_impl(key);
            +  JsonObject& createNestedObject(TString* key) {
            +    return createNestedObject_impl(key);
               }
             
               // Tells weither the specified key is present and associated with a value.
            @@ -248,17 +223,15 @@ class JsonObject : public Internals::JsonPrintable,
               // bool containsKey(TKey);
               // TKey = const std::string&, const String&
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                bool>::type
            -  containsKey(const TString& key) const {
            +  bool containsKey(const TString& key) const {
                 return findKey(key) != end();
               }
               //
               // bool containsKey(TKey);
            -  // TKey = const char*, const char[N], const FlashStringHelper*
            +  // TKey = char*, const char*, char[], const char[], const FlashStringHelper*
               template 
            -  bool containsKey(const TString* key) const {
            -    return findKey(key) != end();
            +  bool containsKey(TString* key) const {
            +    return findKey(key) != end();
               }
             
               // Removes the specified key and the associated value.
            @@ -266,17 +239,15 @@ class JsonObject : public Internals::JsonPrintable,
               // void remove(TKey);
               // TKey = const std::string&, const String&
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                void>::type
            -  remove(const TString& key) {
            +  void remove(const TString& key) {
                 remove(findKey(key));
               }
               //
               // void remove(TKey);
            -  // TKey = const char*, const char[N], const FlashStringHelper*
            +  // TKey = char*, const char*, char[], const char[], const FlashStringHelper*
               template 
            -  void remove(const TString* key) {
            -    remove(findKey(key));
            +  void remove(TString* key) {
            +    remove(findKey(key));
               }
               //
               // void remove(iterator)
            @@ -315,16 +286,22 @@ class JsonObject : public Internals::JsonPrintable,
             
               template 
               bool set_impl(TStringRef key, TValueRef value) {
            +    // ignore null key
            +    if (Internals::StringTraits::is_null(key)) return false;
            +
            +    // search a matching key
                 iterator it = findKey(key);
                 if (it == end()) {
            +      // add the key
                   it = Internals::List::add();
                   if (it == end()) return false;
            -
                   bool key_ok =
            -          Internals::ValueSetter::set(_buffer, it->key, key);
            +          Internals::ValueSaver::save(_buffer, it->key, key);
                   if (!key_ok) return false;
                 }
            -    return Internals::ValueSetter::set(_buffer, it->value, value);
            +
            +    // save the value
            +    return Internals::ValueSaver::save(_buffer, it->value, value);
               }
             
               template 
            @@ -347,5 +324,5 @@ struct JsonVariantDefault {
                 return JsonObject::invalid();
               }
             };
            -}
            -}
            +}  // namespace Internals
            +}  // namespace ArduinoJson
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectImpl.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonObjectImpl.hpp
            similarity index 79%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectImpl.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonObjectImpl.hpp
            index 9741bfadd..e7689b507 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectImpl.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonObjectImpl.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectSubscript.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonObjectSubscript.hpp
            similarity index 66%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectSubscript.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonObjectSubscript.hpp
            index 99dfe7cd0..6ac476370 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectSubscript.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonObjectSubscript.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -17,6 +14,7 @@
             #endif
             
             namespace ArduinoJson {
            +namespace Internals {
             
             template 
             class JsonObjectSubscript
            @@ -34,23 +32,20 @@ class JsonObjectSubscript
             
               // Set the specified value
               //
            -  // operator=(TValue);
            +  // operator=(const TValue&);
               // TValue = bool, char, long, int, short, float, double,
            -  //          const std::string&, const String&,
            -  //          const JsonArray&, const JsonObject&
            +  //          std::string, String, JsonArray, JsonObject
               template 
            -  FORCE_INLINE
            -      typename TypeTraits::EnableIf::value,
            -                                    this_type&>::type
            -      operator=(const TValue& src) {
            +  FORCE_INLINE typename EnableIf::value, this_type&>::type
            +  operator=(const TValue& src) {
                 _object.set(_key, src);
                 return *this;
               }
               //
               // operator=(TValue);
            -  // TValue = const char*, const char[N], const FlashStringHelper*
            +  // TValue = char*, const char*, const FlashStringHelper*
               template 
            -  FORCE_INLINE this_type& operator=(const TValue* src) {
            +  FORCE_INLINE this_type& operator=(TValue* src) {
                 _object.set(_key, src);
                 return *this;
               }
            @@ -60,7 +55,7 @@ class JsonObjectSubscript
               }
             
               template 
            -  FORCE_INLINE typename Internals::JsonVariantAs::type as() const {
            +  FORCE_INLINE typename JsonVariantAs::type as() const {
                 return _object.get(_key);
               }
             
            @@ -71,20 +66,17 @@ class JsonObjectSubscript
             
               // Sets the specified value.
               //
            -  // bool set(TValue);
            +  // bool set(const TValue&);
               // TValue = bool, char, long, int, short, float, double, RawJson, JsonVariant,
            -  //          const std::string&, const String&,
            -  //          const JsonArray&, const JsonObject&
            +  //          std::string, String, JsonArray, JsonObject
               template 
            -  FORCE_INLINE
            -      typename TypeTraits::EnableIf::value,
            -                                    bool>::type
            -      set(const TValue& value) {
            +  FORCE_INLINE typename EnableIf::value, bool>::type set(
            +      const TValue& value) {
                 return _object.set(_key, value);
               }
               //
               // bool set(TValue);
            -  // TValue = const char*, const char[N], const FlashStringHelper*
            +  // TValue = char*, const char, const FlashStringHelper*
               template 
               FORCE_INLINE bool set(const TValue* value) {
                 return _object.set(_key, value);
            @@ -110,7 +102,8 @@ inline std::ostream& operator<<(std::ostream& os,
               return source.printTo(os);
             }
             #endif
            -}  // namespace ArduinoJson
            +}
            +}
             
             #ifdef _MSC_VER
             #pragma warning(pop)
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonPair.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonPair.hpp
            similarity index 53%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonPair.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonPair.hpp
            index 5a32601c0..417243045 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonPair.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonPair.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariant.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariant.hpp
            similarity index 72%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariant.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariant.hpp
            index 9037d54d1..43c51b770 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariant.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariant.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -39,7 +36,7 @@ class JsonObject;
             // - a char, short, int or a long (signed or unsigned)
             // - a string (const char*)
             // - a reference to a JsonArray or JsonObject
            -class JsonVariant : public JsonVariantBase {
            +class JsonVariant : public Internals::JsonVariantBase {
               template 
               friend class Internals::JsonSerializer;
             
            @@ -59,8 +56,8 @@ class JsonVariant : public JsonVariantBase {
               // JsonVariant(double value);
               // JsonVariant(float value);
               template 
            -  JsonVariant(T value, typename TypeTraits::EnableIf<
            -                           TypeTraits::IsFloatingPoint::value>::type * = 0) {
            +  JsonVariant(T value, typename Internals::EnableIf<
            +                           Internals::IsFloatingPoint::value>::type * = 0) {
                 using namespace Internals;
                 _type = JSON_FLOAT;
                 _content.asFloat = static_cast(value);
            @@ -68,8 +65,8 @@ class JsonVariant : public JsonVariantBase {
               template 
               DEPRECATED("Second argument is not supported anymore")
               JsonVariant(T value, uint8_t,
            -              typename TypeTraits::EnableIf<
            -                  TypeTraits::IsFloatingPoint::value>::type * = 0) {
            +              typename Internals::EnableIf<
            +                  Internals::IsFloatingPoint::value>::type * = 0) {
                 using namespace Internals;
                 _type = JSON_FLOAT;
                 _content.asFloat = static_cast(value);
            @@ -82,9 +79,11 @@ class JsonVariant : public JsonVariantBase {
               // JsonVariant(signed long)
               // JsonVariant(signed char)
               template 
            -  JsonVariant(T value, typename TypeTraits::EnableIf<
            -                           TypeTraits::IsSignedIntegral::value ||
            -                           TypeTraits::IsSame::value>::type * = 0) {
            +  JsonVariant(
            +      T value,
            +      typename Internals::EnableIf::value ||
            +                                   Internals::IsSame::value>::type * =
            +          0) {
                 using namespace Internals;
                 if (value >= 0) {
                   _type = JSON_POSITIVE_INTEGER;
            @@ -99,8 +98,8 @@ class JsonVariant : public JsonVariantBase {
               // JsonVariant(unsigned long)
               template 
               JsonVariant(T value,
            -              typename TypeTraits::EnableIf<
            -                  TypeTraits::IsUnsignedIntegral::value>::type * = 0) {
            +              typename Internals::EnableIf<
            +                  Internals::IsUnsignedIntegral::value>::type * = 0) {
                 using namespace Internals;
                 _type = JSON_POSITIVE_INTEGER;
                 _content.asInteger = static_cast(value);
            @@ -113,14 +112,14 @@ class JsonVariant : public JsonVariantBase {
               template 
               JsonVariant(
                   const TChar *value,
            -      typename TypeTraits::EnableIf::value>::type * =
            +      typename Internals::EnableIf::value>::type * =
                       0) {
                 _type = Internals::JSON_STRING;
                 _content.asString = reinterpret_cast(value);
               }
             
               // Create a JsonVariant containing an unparsed string
            -  JsonVariant(RawJson value) {
            +  JsonVariant(Internals::RawJsonString value) {
                 _type = Internals::JSON_UNPARSED;
                 _content.asString = value;
               }
            @@ -147,14 +146,13 @@ class JsonVariant : public JsonVariantBase {
               // unsigned int as() const;
               // unsigned long as() const;
               template 
            -  const typename TypeTraits::EnableIf::value, T>::type
            +  const typename Internals::EnableIf::value, T>::type
               as() const {
                 return variantAsInteger();
               }
               // bool as() const
               template 
            -  const typename TypeTraits::EnableIf::value,
            -                                      T>::type
            +  const typename Internals::EnableIf::value, T>::type
               as() const {
                 return variantAsInteger() != 0;
               }
            @@ -162,8 +160,8 @@ class JsonVariant : public JsonVariantBase {
               // double as() const;
               // float as() const;
               template 
            -  const typename TypeTraits::EnableIf::value,
            -                                      T>::type
            +  const typename Internals::EnableIf::value,
            +                                     T>::type
               as() const {
                 return variantAsFloat();
               }
            @@ -171,9 +169,9 @@ class JsonVariant : public JsonVariantBase {
               // const char* as() const;
               // const char* as() const;
               template 
            -  typename TypeTraits::EnableIf::value ||
            -                                    TypeTraits::IsSame::value,
            -                                const char *>::type
            +  typename Internals::EnableIf::value ||
            +                                   Internals::IsSame::value,
            +                               const char *>::type
               as() const {
                 return variantAsString();
               }
            @@ -181,7 +179,7 @@ class JsonVariant : public JsonVariantBase {
               // std::string as() const;
               // String as() const;
               template 
            -  typename TypeTraits::EnableIf::has_append, T>::type
            +  typename Internals::EnableIf::has_append, T>::type
               as() const {
                 const char *cstr = variantAsString();
                 if (cstr) return T(cstr);
            @@ -193,9 +191,9 @@ class JsonVariant : public JsonVariantBase {
               // JsonArray& as const;
               // JsonArray& as const;
               template 
            -  typename TypeTraits::EnableIf<
            -      TypeTraits::IsSame::type,
            -                         JsonArray>::value,
            +  typename Internals::EnableIf<
            +      Internals::IsSame::type,
            +                        JsonArray>::value,
                   JsonArray &>::type
               as() const {
                 return variantAsArray();
            @@ -203,9 +201,9 @@ class JsonVariant : public JsonVariantBase {
               //
               // const JsonArray& as const;
               template 
            -  typename TypeTraits::EnableIf<
            -      TypeTraits::IsSame::type,
            -                         const JsonArray>::value,
            +  typename Internals::EnableIf<
            +      Internals::IsSame::type,
            +                        const JsonArray>::value,
                   const JsonArray &>::type
               as() const {
                 return variantAsArray();
            @@ -214,9 +212,9 @@ class JsonVariant : public JsonVariantBase {
               // JsonObject& as const;
               // JsonObject& as const;
               template 
            -  typename TypeTraits::EnableIf<
            -      TypeTraits::IsSame::type,
            -                         JsonObject>::value,
            +  typename Internals::EnableIf<
            +      Internals::IsSame::type,
            +                        JsonObject>::value,
                   JsonObject &>::type
               as() const {
                 return variantAsObject();
            @@ -225,9 +223,9 @@ class JsonVariant : public JsonVariantBase {
               // JsonObject& as const;
               // JsonObject& as const;
               template 
            -  typename TypeTraits::EnableIf<
            -      TypeTraits::IsSame::type,
            -                         const JsonObject>::value,
            +  typename Internals::EnableIf<
            +      Internals::IsSame::type,
            +                        const JsonObject>::value,
                   const JsonObject &>::type
               as() const {
                 return variantAsObject();
            @@ -235,8 +233,8 @@ class JsonVariant : public JsonVariantBase {
               //
               // JsonVariant as const;
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                T>::type
            +  typename Internals::EnableIf::value,
            +                               T>::type
               as() const {
                 return *this;
               }
            @@ -254,33 +252,34 @@ class JsonVariant : public JsonVariantBase {
               // bool is() const;
               // bool is() const;
               template 
            -  typename TypeTraits::EnableIf::value, bool>::type
            -  is() const {
            +  typename Internals::EnableIf::value, bool>::type is()
            +      const {
                 return variantIsInteger();
               }
               //
               // bool is() const;
               // bool is() const;
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                bool>::type
            +  typename Internals::EnableIf::value, bool>::type
               is() const {
                 return variantIsFloat();
               }
               //
               // bool is() const
               template 
            -  typename TypeTraits::EnableIf::value, bool>::type
            +  typename Internals::EnableIf::value, bool>::type
               is() const {
                 return variantIsBoolean();
               }
               //
               // bool is() const;
               // bool is() const;
            +  // bool is() const;
               template 
            -  typename TypeTraits::EnableIf::value ||
            -                                    TypeTraits::IsSame::value,
            -                                bool>::type
            +  typename Internals::EnableIf::value ||
            +                                   Internals::IsSame::value ||
            +                                   Internals::StringTraits::has_append,
            +                               bool>::type
               is() const {
                 return variantIsString();
               }
            @@ -289,11 +288,10 @@ class JsonVariant : public JsonVariantBase {
               // bool is const;
               // bool is const;
               template 
            -  typename TypeTraits::EnableIf<
            -      TypeTraits::IsSame<
            -          typename TypeTraits::RemoveConst<
            -              typename TypeTraits::RemoveReference::type>::type,
            -          JsonArray>::value,
            +  typename Internals::EnableIf<
            +      Internals::IsSame::type>::type,
            +                        JsonArray>::value,
                   bool>::type
               is() const {
                 return variantIsArray();
            @@ -303,11 +301,10 @@ class JsonVariant : public JsonVariantBase {
               // bool is const;
               // bool is const;
               template 
            -  typename TypeTraits::EnableIf<
            -      TypeTraits::IsSame<
            -          typename TypeTraits::RemoveConst<
            -              typename TypeTraits::RemoveReference::type>::type,
            -          JsonObject>::value,
            +  typename Internals::EnableIf<
            +      Internals::IsSame::type>::type,
            +                        JsonObject>::value,
                   bool>::type
               is() const {
                 return variantIsObject();
            @@ -357,4 +354,4 @@ DEPRECATED("Decimal places are ignored, use the double value instead")
             inline JsonVariant double_with_n_digits(double value, uint8_t) {
               return JsonVariant(value);
             }
            -}
            +}  // namespace ArduinoJson
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantBase.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantBase.hpp
            similarity index 59%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantBase.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantBase.hpp
            index a010e253f..44acf2e14 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantBase.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantBase.hpp
            @@ -1,23 +1,24 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             #include "JsonVariantCasts.hpp"
             #include "JsonVariantComparisons.hpp"
            +#include "JsonVariantOr.hpp"
             #include "JsonVariantSubscripts.hpp"
             #include "Serialization/JsonPrintable.hpp"
             
             namespace ArduinoJson {
            +namespace Internals {
             
             template 
            -class JsonVariantBase : public Internals::JsonPrintable,
            +class JsonVariantBase : public JsonPrintable,
                                     public JsonVariantCasts,
                                     public JsonVariantComparisons,
            +                        public JsonVariantOr,
                                     public JsonVariantSubscripts,
            -                        public TypeTraits::JsonVariantTag {};
            +                        public JsonVariantTag {};
            +}
             }
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantCasts.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantCasts.hpp
            similarity index 89%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantCasts.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantCasts.hpp
            index b3b41b4ba..68f5bd7dd 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantCasts.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantCasts.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -11,6 +8,7 @@
             #include "Polyfills/attributes.hpp"
             
             namespace ArduinoJson {
            +namespace Internals {
             
             template 
             class JsonVariantCasts {
            @@ -58,3 +56,4 @@ class JsonVariantCasts {
               }
             };
             }
            +}
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantComparisons.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantComparisons.hpp
            similarity index 75%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantComparisons.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantComparisons.hpp
            index eb0ef5c2c..47f9d6322 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantComparisons.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantComparisons.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -12,6 +9,7 @@
             #include "TypeTraits/IsVariant.hpp"
             
             namespace ArduinoJson {
            +namespace Internals {
             
             template 
             class JsonVariantComparisons {
            @@ -23,10 +21,8 @@ class JsonVariantComparisons {
               }
             
               template 
            -  friend
            -      typename TypeTraits::EnableIf::value,
            -                                    bool>::type
            -      operator==(TComparand comparand, const JsonVariantComparisons &variant) {
            +  friend typename EnableIf::value, bool>::type
            +  operator==(TComparand comparand, const JsonVariantComparisons &variant) {
                 return variant.equals(comparand);
               }
             
            @@ -37,10 +33,8 @@ class JsonVariantComparisons {
               }
             
               template 
            -  friend
            -      typename TypeTraits::EnableIf::value,
            -                                    bool>::type
            -      operator!=(TComparand comparand, const JsonVariantComparisons &variant) {
            +  friend typename EnableIf::value, bool>::type
            +  operator!=(TComparand comparand, const JsonVariantComparisons &variant) {
                 return !variant.equals(comparand);
               }
             
            @@ -97,7 +91,7 @@ class JsonVariantComparisons {
               }
             
               template 
            -  const typename Internals::JsonVariantAs::type as() const {
            +  const typename JsonVariantAs::type as() const {
                 return impl()->template as();
               }
             
            @@ -107,17 +101,16 @@ class JsonVariantComparisons {
               }
             
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                bool>::type
            -  equals(const TString &comparand) const {
            +  typename EnableIf::has_equals, bool>::type equals(
            +      const TString &comparand) const {
                 const char *value = as();
            -    return Internals::StringTraits::equals(comparand, value);
            +    return StringTraits::equals(comparand, value);
               }
             
               template 
            -  typename TypeTraits::EnableIf::value &&
            -                                    !TypeTraits::IsString::value,
            -                                bool>::type
            +  typename EnableIf::value &&
            +                        !StringTraits::has_equals,
            +                    bool>::type
               equals(const TComparand &comparand) const {
                 return as() == comparand;
               }
            @@ -136,9 +129,11 @@ class JsonVariantComparisons {
                 if (is() && right.template is())
                   return as() == right.template as();
                 if (is() && right.template is())
            -      return strcmp(as(), right.template as()) == 0;
            +      return StringTraits::equals(as(),
            +                                                right.template as());
             
                 return false;
               }
             };
            -}
            +}  // namespace Internals
            +}  // namespace ArduinoJson
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantImpl.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantImpl.hpp
            similarity index 87%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantImpl.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantImpl.hpp
            index eb6a4735d..31f96ce1a 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantImpl.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantImpl.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -61,7 +58,7 @@ inline T JsonVariant::variantAsInteger() const {
                   return T(~_content.asInteger + 1);
                 case JSON_STRING:
                 case JSON_UNPARSED:
            -      return Polyfills::parseInteger(_content.asString);
            +      return parseInteger(_content.asString);
                 default:
                   return T(_content.asFloat);
               }
            @@ -89,7 +86,7 @@ inline T JsonVariant::variantAsFloat() const {
                   return -static_cast(_content.asInteger);
                 case JSON_STRING:
                 case JSON_UNPARSED:
            -      return Polyfills::parseFloat(_content.asString);
            +      return parseFloat(_content.asString);
                 default:
                   return static_cast(_content.asFloat);
               }
            @@ -109,7 +106,7 @@ inline bool JsonVariant::variantIsInteger() const {
               using namespace Internals;
             
               return _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER ||
            -         (_type == JSON_UNPARSED && Polyfills::isInteger(_content.asString));
            +         (_type == JSON_UNPARSED && isInteger(_content.asString));
             }
             
             inline bool JsonVariant::variantIsFloat() const {
            @@ -117,7 +114,7 @@ inline bool JsonVariant::variantIsFloat() const {
             
               return _type == JSON_FLOAT || _type == JSON_POSITIVE_INTEGER ||
                      _type == JSON_NEGATIVE_INTEGER ||
            -         (_type == JSON_UNPARSED && Polyfills::isFloat(_content.asString));
            +         (_type == JSON_UNPARSED && isFloat(_content.asString));
             }
             
             #if ARDUINOJSON_ENABLE_STD_STREAM
            diff --git a/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantOr.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantOr.hpp
            new file mode 100644
            index 000000000..d8022fcb2
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantOr.hpp
            @@ -0,0 +1,52 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +
            +#pragma once
            +
            +#include "Data/JsonVariantAs.hpp"
            +#include "Polyfills/attributes.hpp"
            +#include "TypeTraits/EnableIf.hpp"
            +#include "TypeTraits/IsIntegral.hpp"
            +
            +namespace ArduinoJson {
            +namespace Internals {
            +
            +template 
            +class JsonVariantOr {
            + public:
            +  // Returns the default value if the JsonVariant is undefined of incompatible
            +  template 
            +  typename EnableIf::value, T>::type operator|(
            +      const T &defaultValue) const {
            +    if (impl()->template is())
            +      return impl()->template as();
            +    else
            +      return defaultValue;
            +  }
            +
            +  // Returns the default value if the JsonVariant is undefined of incompatible
            +  // Special case for string: null is treated as undefined
            +  const char *operator|(const char *defaultValue) const {
            +    const char *value = impl()->template as();
            +    return value ? value : defaultValue;
            +  }
            +
            +  // Returns the default value if the JsonVariant is undefined of incompatible
            +  // Special case for integers: we also accept double
            +  template 
            +  typename EnableIf::value, Integer>::type operator|(
            +      const Integer &defaultValue) const {
            +    if (impl()->template is())
            +      return impl()->template as();
            +    else
            +      return defaultValue;
            +  }
            +
            + private:
            +  const TImpl *impl() const {
            +    return static_cast(this);
            +  }
            +};
            +}  // namespace Internals
            +}  // namespace ArduinoJson
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantSubscripts.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantSubscripts.hpp
            similarity index 70%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantSubscripts.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantSubscripts.hpp
            index 2143236a6..279ee019f 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantSubscripts.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/JsonVariantSubscripts.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -13,6 +10,7 @@
             #include "TypeTraits/EnableIf.hpp"
             
             namespace ArduinoJson {
            +namespace Internals {
             
             // Forward declarations.
             class JsonArraySubscript;
            @@ -44,19 +42,18 @@ class JsonVariantSubscripts {
               // const JsonObjectSubscript operator[](TKey) const;
               // TKey = const std::string&, const String&
               template 
            -  FORCE_INLINE typename TypeTraits::EnableIf<
            -      Internals::StringTraits::has_equals,
            -      const JsonObjectSubscript >::type
            -  operator[](const TString &key) const {
            +  FORCE_INLINE
            +      typename EnableIf::has_equals,
            +                        const JsonObjectSubscript >::type
            +      operator[](const TString &key) const {
                 return impl()->template as()[key];
               }
               //
               // const JsonObjectSubscript operator[](TKey) const;
               // TKey = const std::string&, const String&
               template 
            -  FORCE_INLINE typename TypeTraits::EnableIf<
            -      Internals::StringTraits::has_equals,
            -      JsonObjectSubscript >::type
            +  FORCE_INLINE typename EnableIf::has_equals,
            +                                 JsonObjectSubscript >::type
               operator[](const TString &key) {
                 return impl()->template as()[key];
               }
            @@ -64,9 +61,8 @@ class JsonVariantSubscripts {
               // JsonObjectSubscript operator[](TKey);
               // TKey = const char*, const char[N], const FlashStringHelper*
               template 
            -  FORCE_INLINE typename TypeTraits::EnableIf<
            -      Internals::StringTraits::has_equals,
            -      JsonObjectSubscript >::type
            +  FORCE_INLINE typename EnableIf::has_equals,
            +                                 JsonObjectSubscript >::type
               operator[](const TString *key) {
                 return impl()->template as()[key];
               }
            @@ -74,10 +70,10 @@ class JsonVariantSubscripts {
               // JsonObjectSubscript operator[](TKey);
               // TKey = const char*, const char[N], const FlashStringHelper*
               template 
            -  FORCE_INLINE typename TypeTraits::EnableIf<
            -      Internals::StringTraits::has_equals,
            -      const JsonObjectSubscript >::type
            -  operator[](const TString *key) const {
            +  FORCE_INLINE
            +      typename EnableIf::has_equals,
            +                        const JsonObjectSubscript >::type
            +      operator[](const TString *key) const {
                 return impl()->template as()[key];
               }
             
            @@ -87,3 +83,4 @@ class JsonVariantSubscripts {
               }
             };
             }
            +}
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/attributes.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/attributes.hpp
            similarity index 74%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/attributes.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/attributes.hpp
            index e4f9406ac..b49091ddc 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/attributes.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/attributes.hpp
            @@ -1,15 +1,12 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             #ifdef _MSC_VER  // Visual Studio
             
            -#define FORCE_INLINE __forceinline
            +#define FORCE_INLINE  // __forceinline causes C4714 when returning std::string
             #define NO_INLINE __declspec(noinline)
             #define DEPRECATED(msg) __declspec(deprecated(msg))
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/ctype.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/ctype.hpp
            similarity index 50%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/ctype.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/ctype.hpp
            index f13e3edf6..2d52703cd 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/ctype.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/ctype.hpp
            @@ -1,14 +1,11 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             namespace ArduinoJson {
            -namespace Polyfills {
            +namespace Internals {
             
             inline bool isdigit(char c) {
               return '0' <= c && c <= '9';
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isFloat.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/isFloat.hpp
            similarity index 75%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isFloat.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/isFloat.hpp
            index f6b9c97d9..973b89fe9 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isFloat.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/isFloat.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -11,7 +8,7 @@
             #include "./ctype.hpp"
             
             namespace ArduinoJson {
            -namespace Polyfills {
            +namespace Internals {
             
             inline bool isFloat(const char* s) {
               if (!s) return false;
            diff --git a/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/isInteger.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/isInteger.hpp
            new file mode 100644
            index 000000000..8049079a7
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/isInteger.hpp
            @@ -0,0 +1,19 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +
            +#pragma once
            +
            +#include "./ctype.hpp"
            +
            +namespace ArduinoJson {
            +namespace Internals {
            +
            +inline bool isInteger(const char* s) {
            +  if (!s || !*s) return false;
            +  if (issign(*s)) s++;
            +  while (isdigit(*s)) s++;
            +  return *s == '\0';
            +}
            +}  // namespace Internals
            +}  // namespace ArduinoJson
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/math.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/math.hpp
            similarity index 52%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/math.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/math.hpp
            index 9dbd161d6..48773edd2 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/math.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/math.hpp
            @@ -1,14 +1,11 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             namespace ArduinoJson {
            -namespace Polyfills {
            +namespace Internals {
             template 
             bool isNaN(T x) {
               return x != x;
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseFloat.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/parseFloat.hpp
            similarity index 89%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseFloat.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/parseFloat.hpp
            index e5d99f1bf..49b0f6fcd 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseFloat.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/parseFloat.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -12,11 +9,11 @@
             #include "./math.hpp"
             
             namespace ArduinoJson {
            -namespace Polyfills {
            +namespace Internals {
             
             template 
             inline T parseFloat(const char* s) {
            -  typedef TypeTraits::FloatTraits traits;
            +  typedef FloatTraits traits;
               typedef typename traits::mantissa_type mantissa_t;
               typedef typename traits::exponent_type exponent_t;
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseInteger.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/parseInteger.hpp
            similarity index 75%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseInteger.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/parseInteger.hpp
            index 023d7bcbd..e8f197494 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseInteger.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Polyfills/parseInteger.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -13,7 +10,7 @@
             #include "./ctype.hpp"
             
             namespace ArduinoJson {
            -namespace Polyfills {
            +namespace Internals {
             template 
             T parseInteger(const char *s) {
               if (!s) return 0;  // NULL
            diff --git a/lib/ArduinoJson-5.13.4/src/ArduinoJson/RawJson.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/RawJson.hpp
            new file mode 100644
            index 000000000..4beb980ee
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/RawJson.hpp
            @@ -0,0 +1,46 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +
            +#pragma once
            +
            +namespace ArduinoJson {
            +
            +namespace Internals {
            +// A special type of data that can be used to insert pregenerated JSON portions.
            +template 
            +class RawJsonString {
            + public:
            +  explicit RawJsonString(T str) : _str(str) {}
            +  operator T() const {
            +    return _str;
            +  }
            +
            + private:
            +  T _str;
            +};
            +
            +template 
            +struct StringTraits, void> {
            +  static bool is_null(RawJsonString source) {
            +    return StringTraits::is_null(static_cast(source));
            +  }
            +
            +  typedef RawJsonString duplicate_t;
            +
            +  template 
            +  static duplicate_t duplicate(RawJsonString source, Buffer* buffer) {
            +    return duplicate_t(StringTraits::duplicate(source, buffer));
            +  }
            +
            +  static const bool has_append = false;
            +  static const bool has_equals = false;
            +  static const bool should_duplicate = StringTraits::should_duplicate;
            +};
            +}
            +
            +template 
            +inline Internals::RawJsonString RawJson(T str) {
            +  return Internals::RawJsonString(str);
            +}
            +}
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DummyPrint.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/DummyPrint.hpp
            similarity index 64%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DummyPrint.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/DummyPrint.hpp
            index 656aa9ed6..9fdf2d6a0 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DummyPrint.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/DummyPrint.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DynamicStringBuilder.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/DynamicStringBuilder.hpp
            similarity index 80%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DynamicStringBuilder.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/DynamicStringBuilder.hpp
            index a344588de..41be6392c 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DynamicStringBuilder.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/DynamicStringBuilder.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/FloatParts.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/FloatParts.hpp
            similarity index 91%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/FloatParts.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/FloatParts.hpp
            index fa650723d..c14e3b553 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/FloatParts.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/FloatParts.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -59,7 +56,7 @@ struct FloatParts {
               }
             
               static int16_t normalize(TFloat& value) {
            -    typedef TypeTraits::FloatTraits traits;
            +    typedef FloatTraits traits;
                 int16_t powersOf10 = 0;
             
                 int8_t index = sizeof(TFloat) == 8 ? 8 : 5;
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/IndentedPrint.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/IndentedPrint.hpp
            similarity index 89%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/IndentedPrint.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/IndentedPrint.hpp
            index 66ca6ac2f..864f9aaa4 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/IndentedPrint.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/IndentedPrint.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonPrintable.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/JsonPrintable.hpp
            similarity index 80%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonPrintable.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/JsonPrintable.hpp
            index f33e5584e..43d413a85 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonPrintable.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/JsonPrintable.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -32,9 +29,8 @@ template 
             class JsonPrintable {
              public:
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                size_t>::type
            -  printTo(Print &print) const {
            +  typename EnableIf::has_append, size_t>::type printTo(
            +      Print &print) const {
                 JsonWriter writer(print);
                 JsonSerializer >::serialize(downcast(), writer);
                 return writer.bytesWritten();
            @@ -59,8 +55,8 @@ class JsonPrintable {
               }
             
               template 
            -  typename TypeTraits::EnableIf::has_append, size_t>::type
            -  printTo(TString &str) const {
            +  typename EnableIf::has_append, size_t>::type printTo(
            +      TString &str) const {
                 DynamicStringBuilder sb(str);
                 return printTo(sb);
               }
            @@ -82,15 +78,14 @@ class JsonPrintable {
               }
             
               template 
            -  typename TypeTraits::EnableIf::value,
            -                                size_t>::type
            +  typename EnableIf::has_append, size_t>::type
               prettyPrintTo(Print &print) const {
                 IndentedPrint indentedPrint(print);
                 return prettyPrintTo(indentedPrint);
               }
             
               template 
            -  typename TypeTraits::EnableIf::has_append, size_t>::type
            +  typename EnableIf::has_append, size_t>::type
               prettyPrintTo(TString &str) const {
                 DynamicStringBuilder sb(str);
                 return prettyPrintTo(sb);
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializer.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/JsonSerializer.hpp
            similarity index 79%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializer.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/JsonSerializer.hpp
            index 86ed73ee1..0cb537f7d 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializer.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/JsonSerializer.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -12,14 +9,15 @@
             namespace ArduinoJson {
             
             class JsonArray;
            -class JsonArraySubscript;
             class JsonObject;
            -template 
            -class JsonObjectSubscript;
             class JsonVariant;
             
             namespace Internals {
             
            +class JsonArraySubscript;
            +template 
            +class JsonObjectSubscript;
            +
             template 
             class JsonSerializer {
              public:
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp
            similarity index 94%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp
            index f544488af..0faae2769 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonWriter.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/JsonWriter.hpp
            similarity index 91%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonWriter.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/JsonWriter.hpp
            index 2d54a2a0b..146d51dcb 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonWriter.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/JsonWriter.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -82,14 +79,14 @@ class JsonWriter {
             
               template 
               void writeFloat(TFloat value) {
            -    if (Polyfills::isNaN(value)) return writeRaw("NaN");
            +    if (isNaN(value)) return writeRaw("NaN");
             
                 if (value < 0.0) {
                   writeRaw('-');
                   value = -value;
                 }
             
            -    if (Polyfills::isInfinity(value)) return writeRaw("Infinity");
            +    if (isInfinity(value)) return writeRaw("Infinity");
             
                 FloatParts parts(value);
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/Prettyfier.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/Prettyfier.hpp
            similarity index 93%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/Prettyfier.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/Prettyfier.hpp
            index 377138b4f..8b4f0d2eb 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/Prettyfier.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/Prettyfier.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StaticStringBuilder.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/StaticStringBuilder.hpp
            similarity index 77%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StaticStringBuilder.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/StaticStringBuilder.hpp
            index 2df932fd4..9617bbd97 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StaticStringBuilder.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/StaticStringBuilder.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StreamPrintAdapter.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/StreamPrintAdapter.hpp
            similarity index 77%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StreamPrintAdapter.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/StreamPrintAdapter.hpp
            index 9c2f86fd7..60f0af4a3 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StreamPrintAdapter.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/Serialization/StreamPrintAdapter.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StaticJsonBuffer.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StaticJsonBuffer.hpp
            similarity index 89%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/StaticJsonBuffer.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/StaticJsonBuffer.hpp
            index 8eaa4bb53..267d9d018 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StaticJsonBuffer.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StaticJsonBuffer.hpp
            @@ -1,15 +1,13 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             #include "JsonBufferBase.hpp"
             
             namespace ArduinoJson {
            +namespace Internals {
             
             class StaticJsonBufferBase : public JsonBufferBase {
              public:
            @@ -93,6 +91,7 @@ class StaticJsonBufferBase : public JsonBufferBase {
               size_t _capacity;
               size_t _size;
             };
            +}
             
             #if defined(__clang__)
             #pragma clang diagnostic push
            @@ -108,9 +107,10 @@ class StaticJsonBufferBase : public JsonBufferBase {
             // The template paramenter CAPACITY specifies the capacity of the buffer in
             // bytes.
             template 
            -class StaticJsonBuffer : public StaticJsonBufferBase {
            +class StaticJsonBuffer : public Internals::StaticJsonBufferBase {
              public:
            -  explicit StaticJsonBuffer() : StaticJsonBufferBase(_buffer, CAPACITY) {}
            +  explicit StaticJsonBuffer()
            +      : Internals::StaticJsonBufferBase(_buffer, CAPACITY) {}
             
              private:
               char _buffer[CAPACITY];
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/ArduinoStream.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/ArduinoStream.hpp
            similarity index 64%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/ArduinoStream.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/ArduinoStream.hpp
            index 87d1672d5..5db0852b8 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/ArduinoStream.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/ArduinoStream.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -46,14 +43,17 @@ struct ArduinoStreamTraits {
                   return c;
                 }
               };
            +
            +  static const bool has_append = false;
            +  static const bool has_equals = false;
             };
             
             template 
            -struct StringTraits::type>::value>::type>
            +struct StringTraits<
            +    TStream,
            +    // match any type that is derived from Stream:
            +    typename EnableIf<
            +        IsBaseOf::type>::value>::type>
                 : ArduinoStreamTraits {};
             }
             }
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/CharPointer.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/CharPointer.hpp
            similarity index 54%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/CharPointer.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/CharPointer.hpp
            index 203e3924e..98896ccfb 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/CharPointer.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/CharPointer.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -33,26 +30,35 @@ struct CharPointerTraits {
               };
             
               static bool equals(const TChar* str, const char* expected) {
            -    return strcmp(reinterpret_cast(str), expected) == 0;
            +    const char* actual = reinterpret_cast(str);
            +    if (!actual || !expected) return actual == expected;
            +    return strcmp(actual, expected) == 0;
               }
             
            +  static bool is_null(const TChar* str) {
            +    return !str;
            +  }
            +
            +  typedef const char* duplicate_t;
            +
               template 
            -  static char* duplicate(const TChar* str, Buffer* buffer) {
            +  static duplicate_t duplicate(const TChar* str, Buffer* buffer) {
                 if (!str) return NULL;
                 size_t size = strlen(reinterpret_cast(str)) + 1;
                 void* dup = buffer->alloc(size);
                 if (dup != NULL) memcpy(dup, str, size);
            -    return static_cast(dup);
            +    return static_cast(dup);
               }
             
               static const bool has_append = false;
               static const bool has_equals = true;
            -  static const bool should_duplicate = false;
            +  static const bool should_duplicate = !IsConst::value;
             };
             
            +// char*, unsigned char*, signed char*
            +// const char*, const unsigned char*, const signed char*
             template 
            -struct StringTraits::value>::type>
            +struct StringTraits::value>::type>
                 : CharPointerTraits {};
            -}
            -}
            +}  // namespace Internals
            +}  // namespace ArduinoJson
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/FlashString.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/FlashString.hpp
            similarity index 64%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/FlashString.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/FlashString.hpp
            index 37e36b8d2..0701b9ba2 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/FlashString.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/FlashString.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -34,23 +31,31 @@ struct StringTraits {
               };
             
               static bool equals(const __FlashStringHelper* str, const char* expected) {
            -    return strcmp_P(expected, (const char*)str) == 0;
            +    const char* actual = reinterpret_cast(str);
            +    if (!actual || !expected) return actual == expected;
            +    return strcmp_P(expected, actual) == 0;
               }
             
            +  static bool is_null(const __FlashStringHelper* str) {
            +    return !str;
            +  }
            +
            +  typedef const char* duplicate_t;
            +
               template 
            -  static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) {
            +  static duplicate_t duplicate(const __FlashStringHelper* str, Buffer* buffer) {
                 if (!str) return NULL;
                 size_t size = strlen_P((const char*)str) + 1;
                 void* dup = buffer->alloc(size);
                 if (dup != NULL) memcpy_P(dup, (const char*)str, size);
            -    return static_cast(dup);
            +    return static_cast(dup);
               }
             
               static const bool has_append = false;
               static const bool has_equals = true;
               static const bool should_duplicate = true;
             };
            -}
            -}
            +}  // namespace Internals
            +}  // namespace ArduinoJson
             
             #endif
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdStream.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/StdStream.hpp
            similarity index 63%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdStream.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/StdStream.hpp
            index 35049d941..227c74406 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdStream.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/StdStream.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -45,14 +42,17 @@ struct StdStreamTraits {
                   return _stream.eof() ? '\0' : static_cast(_stream.get());
                 }
               };
            +
            +  static const bool has_append = false;
            +  static const bool has_equals = false;
             };
             
             template 
            -struct StringTraits::type>::value>::type>
            +struct StringTraits<
            +    TStream,
            +    // match any type that is derived from std::istream:
            +    typename EnableIf::type>::value>::type>
                 : StdStreamTraits {};
             }
             }
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdString.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/StdString.hpp
            similarity index 70%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdString.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/StdString.hpp
            index 959c47466..35f4461d8 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdString.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/StdString.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -22,13 +19,20 @@ namespace Internals {
             
             template 
             struct StdStringTraits {
            +  typedef const char* duplicate_t;
            +
               template 
            -  static char* duplicate(const TString& str, Buffer* buffer) {
            +  static duplicate_t duplicate(const TString& str, Buffer* buffer) {
                 if (!str.c_str()) return NULL;  // <- Arduino string can return NULL
                 size_t size = str.length() + 1;
                 void* dup = buffer->alloc(size);
                 if (dup != NULL) memcpy(dup, str.c_str(), size);
            -    return static_cast(dup);
            +    return static_cast(dup);
            +  }
            +
            +  static bool is_null(const TString& str) {
            +    // Arduino's String::c_str() can return NULL
            +    return !str.c_str();
               }
             
               struct Reader : CharPointerTraits::Reader {
            @@ -36,7 +40,10 @@ struct StdStringTraits {
               };
             
               static bool equals(const TString& str, const char* expected) {
            -    return 0 == strcmp(str.c_str(), expected);
            +    // Arduino's String::c_str() can return NULL
            +    const char* actual = str.c_str();
            +    if (!actual || !expected) return actual == expected;
            +    return 0 == strcmp(actual, expected);
               }
             
               static void append(TString& str, char c) {
            @@ -64,7 +71,7 @@ struct StringTraits : StdStringTraits {
             template <>
             struct StringTraits : StdStringTraits {};
             #endif
            -}
            -}
            +}  // namespace Internals
            +}  // namespace ArduinoJson
             
             #endif
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StringTraits.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/StringTraits.hpp
            similarity index 55%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StringTraits.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/StringTraits.hpp
            index 55bacca26..dd5694b2e 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StringTraits.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/StringTraits/StringTraits.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -12,13 +9,17 @@
             #include "../TypeTraits/EnableIf.hpp"
             #include "../TypeTraits/IsBaseOf.hpp"
             #include "../TypeTraits/IsChar.hpp"
            +#include "../TypeTraits/IsConst.hpp"
             #include "../TypeTraits/RemoveReference.hpp"
             
             namespace ArduinoJson {
             namespace Internals {
             
             template 
            -struct StringTraits {};
            +struct StringTraits {
            +  static const bool has_append = false;
            +  static const bool has_equals = false;
            +};
             
             template 
             struct StringTraits : StringTraits {};
            @@ -33,18 +34,3 @@ struct StringTraits : StringTraits {};
             #include "FlashString.hpp"
             #include "StdStream.hpp"
             #include "StdString.hpp"
            -
            -namespace ArduinoJson {
            -namespace TypeTraits {
            -template 
            -struct IsString {
            -  static const bool value = false;
            -};
            -
            -template 
            -struct IsString::has_equals>::type> {
            -  static const bool value = Internals::StringTraits::has_equals;
            -};
            -}
            -}
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/EnableIf.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/EnableIf.hpp
            similarity index 58%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/EnableIf.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/EnableIf.hpp
            index 654b308e6..83fc5e07f 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/EnableIf.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/EnableIf.hpp
            @@ -1,14 +1,11 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             namespace ArduinoJson {
            -namespace TypeTraits {
            +namespace Internals {
             
             // A meta-function that return the type T if Condition is true.
             template 
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/FloatTraits.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/FloatTraits.hpp
            similarity index 68%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/FloatTraits.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/FloatTraits.hpp
            index a52e1e879..648cc82fd 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/FloatTraits.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/FloatTraits.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -13,7 +10,7 @@
             #include "../Polyfills/math.hpp"
             
             namespace ArduinoJson {
            -namespace TypeTraits {
            +namespace Internals {
             
             template 
             struct FloatTraits {};
            @@ -47,28 +44,46 @@ struct FloatTraits {
             
               static T positiveBinaryPowerOfTen(int index) {
                 static T factors[] = {
            -        1e1, 1e2, 1e4, 1e8, 1e16, 1e32,
            -        // workaround to support platforms with single precision literals
            -        forge(0x4D384F03, 0xE93FF9F5), forge(0x5A827748, 0xF9301D32),
            -        forge(0x75154FDD, 0x7F73BF3C)};
            +        1e1,
            +        1e2,
            +        1e4,
            +        1e8,
            +        1e16,
            +        forge(0x4693B8B5, 0xB5056E17),  // 1e32
            +        forge(0x4D384F03, 0xE93FF9F5),  // 1e64
            +        forge(0x5A827748, 0xF9301D32),  // 1e128
            +        forge(0x75154FDD, 0x7F73BF3C)   // 1e256
            +    };
                 return factors[index];
               }
             
               static T negativeBinaryPowerOfTen(int index) {
                 static T factors[] = {
            -        1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32,
            -        // workaround to support platforms with single precision literals
            -        forge(0x32A50FFD, 0x44F4A73D), forge(0x255BBA08, 0xCF8C979D),
            -        forge(0x0AC80628, 0x64AC6F43)};
            +        forge(0x3FB99999, 0x9999999A),  // 1e-1
            +        forge(0x3F847AE1, 0x47AE147B),  // 1e-2
            +        forge(0x3F1A36E2, 0xEB1C432D),  // 1e-4
            +        forge(0x3E45798E, 0xE2308C3A),  // 1e-8
            +        forge(0x3C9CD2B2, 0x97D889BC),  // 1e-16
            +        forge(0x3949F623, 0xD5A8A733),  // 1e-32
            +        forge(0x32A50FFD, 0x44F4A73D),  // 1e-64
            +        forge(0x255BBA08, 0xCF8C979D),  // 1e-128
            +        forge(0x0AC80628, 0x64AC6F43)   // 1e-256
            +    };
                 return factors[index];
               }
             
               static T negativeBinaryPowerOfTenPlusOne(int index) {
                 static T factors[] = {
            -        1e0, 1e-1, 1e-3, 1e-7, 1e-15, 1e-31,
            -        // workaround to support platforms with single precision literals
            -        forge(0x32DA53FC, 0x9631D10D), forge(0x25915445, 0x81B7DEC2),
            -        forge(0x0AFE07B2, 0x7DD78B14)};
            +        1e0,
            +        forge(0x3FB99999, 0x9999999A),  // 1e-1
            +        forge(0x3F50624D, 0xD2F1A9FC),  // 1e-3
            +        forge(0x3E7AD7F2, 0x9ABCAF48),  // 1e-7
            +        forge(0x3CD203AF, 0x9EE75616),  // 1e-15
            +        forge(0x398039D6, 0x65896880),  // 1e-31
            +        forge(0x32DA53FC, 0x9631D10D),  // 1e-63
            +        forge(0x25915445, 0x81B7DEC2),  // 1e-127
            +        forge(0x0AFE07B2, 0x7DD78B14)   // 1e-255
            +    };
                 return factors[index];
               }
             
            @@ -80,6 +95,9 @@ struct FloatTraits {
                 return forge(0x7ff00000, 0x00000000);
               }
             
            +  // constructs a double floating point values from its binary representation
            +  // we use this function to workaround platforms with single precision literals
            +  // (for example, when -fsingle-precision-constant is passed to GCC)
               static T forge(uint32_t msb, uint32_t lsb) {
                 union {
                   uint64_t integerBits;
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsArray.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsArray.hpp
            similarity index 67%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsArray.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsArray.hpp
            index 713808aed..259923115 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsArray.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsArray.hpp
            @@ -1,14 +1,11 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             namespace ArduinoJson {
            -namespace TypeTraits {
            +namespace Internals {
             
             // A meta-function that return the type T without the const modifier
             template 
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsBaseOf.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsBaseOf.hpp
            similarity index 73%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsBaseOf.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsBaseOf.hpp
            index 9e68debc3..bf24e965e 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsBaseOf.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsBaseOf.hpp
            @@ -1,14 +1,11 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             namespace ArduinoJson {
            -namespace TypeTraits {
            +namespace Internals {
             
             // A meta-function that returns true if Derived inherits from TBase is an
             // integral type.
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsChar.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsChar.hpp
            similarity index 69%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsChar.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsChar.hpp
            index bd1b5fdd5..d97cec213 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsChar.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsChar.hpp
            @@ -1,16 +1,13 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             #include "IsSame.hpp"
             
             namespace ArduinoJson {
            -namespace TypeTraits {
            +namespace Internals {
             
             // A meta-function that returns true if T is a charater
             template 
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsConst.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsConst.hpp
            similarity index 61%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsConst.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsConst.hpp
            index 7ffed8443..512ee5ca0 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsConst.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsConst.hpp
            @@ -1,14 +1,11 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             namespace ArduinoJson {
            -namespace TypeTraits {
            +namespace Internals {
             
             // A meta-function that return the type T without the const modifier
             template 
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsFloatingPoint.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsFloatingPoint.hpp
            similarity index 60%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsFloatingPoint.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsFloatingPoint.hpp
            index c04ce2a63..e41a6824c 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsFloatingPoint.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsFloatingPoint.hpp
            @@ -1,16 +1,13 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             #include "IsSame.hpp"
             
             namespace ArduinoJson {
            -namespace TypeTraits {
            +namespace Internals {
             
             // A meta-function that returns true if T is a floating point type
             template 
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsIntegral.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsIntegral.hpp
            similarity index 50%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsIntegral.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsIntegral.hpp
            index e34add52e..17ae5f284 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsIntegral.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsIntegral.hpp
            @@ -1,9 +1,6 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
            @@ -12,14 +9,14 @@
             #include "IsUnsignedIntegral.hpp"
             
             namespace ArduinoJson {
            -namespace TypeTraits {
            +namespace Internals {
             
             // A meta-function that returns true if T is an integral type.
             template 
             struct IsIntegral {
            -  static const bool value = TypeTraits::IsSignedIntegral::value ||
            -                            TypeTraits::IsUnsignedIntegral::value ||
            -                            TypeTraits::IsSame::value;
            +  static const bool value = IsSignedIntegral::value ||
            +                            IsUnsignedIntegral::value ||
            +                            IsSame::value;
               // CAUTION: differs from std::is_integral as it doesn't include bool
             };
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSame.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsSame.hpp
            similarity index 62%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSame.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsSame.hpp
            index d96a5b554..06567c93b 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSame.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsSame.hpp
            @@ -1,14 +1,11 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             namespace ArduinoJson {
            -namespace TypeTraits {
            +namespace Internals {
             
             // A meta-function that returns true if types T and U are the same.
             template 
            diff --git a/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsSignedIntegral.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsSignedIntegral.hpp
            new file mode 100644
            index 000000000..7334eb9c7
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsSignedIntegral.hpp
            @@ -0,0 +1,28 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +
            +#pragma once
            +
            +#include "../Configuration.hpp"
            +#include "IsSame.hpp"
            +
            +namespace ArduinoJson {
            +namespace Internals {
            +
            +// A meta-function that returns true if T is an integral type.
            +template 
            +struct IsSignedIntegral {
            +  static const bool value =
            +      IsSame::value || IsSame::value ||
            +      IsSame::value || IsSame::value ||
            +#if ARDUINOJSON_USE_LONG_LONG
            +      IsSame::value ||
            +#endif
            +#if ARDUINOJSON_USE_INT64
            +      IsSame::value ||
            +#endif
            +      false;
            +};
            +}
            +}
            diff --git a/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp
            new file mode 100644
            index 000000000..938423f5c
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp
            @@ -0,0 +1,28 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +
            +#pragma once
            +
            +#include "../Configuration.hpp"
            +#include "IsSame.hpp"
            +
            +namespace ArduinoJson {
            +namespace Internals {
            +
            +// A meta-function that returns true if T is an integral type.
            +template 
            +struct IsUnsignedIntegral {
            +  static const bool value =
            +      IsSame::value || IsSame::value ||
            +      IsSame::value || IsSame::value ||
            +#if ARDUINOJSON_USE_LONG_LONG
            +      IsSame::value ||
            +#endif
            +#if ARDUINOJSON_USE_INT64
            +      IsSame::value ||
            +#endif
            +      false;
            +};
            +}
            +}
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsVariant.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsVariant.hpp
            similarity index 50%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsVariant.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsVariant.hpp
            index 8297cf5cd..f8b299f7a 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsVariant.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/IsVariant.hpp
            @@ -1,16 +1,13 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             #include "IsBaseOf.hpp"
             
             namespace ArduinoJson {
            -namespace TypeTraits {
            +namespace Internals {
             
             class JsonVariantTag {};
             
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveConst.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/RemoveConst.hpp
            similarity index 59%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveConst.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/RemoveConst.hpp
            index 0186234ef..39d4cb5a5 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveConst.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/RemoveConst.hpp
            @@ -1,14 +1,11 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             namespace ArduinoJson {
            -namespace TypeTraits {
            +namespace Internals {
             
             // A meta-function that return the type T without the const modifier
             template 
            diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveReference.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/RemoveReference.hpp
            similarity index 60%
            rename from lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveReference.hpp
            rename to lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/RemoveReference.hpp
            index 4968997e7..395a12889 100644
            --- a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveReference.hpp
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/TypeTraits/RemoveReference.hpp
            @@ -1,14 +1,11 @@
            -// Copyright Benoit Blanchon 2014-2017
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
             // MIT License
            -//
            -// Arduino JSON library
            -// https://bblanchon.github.io/ArduinoJson/
            -// If you like this project, please add a star!
             
             #pragma once
             
             namespace ArduinoJson {
            -namespace TypeTraits {
            +namespace Internals {
             
             // A meta-function that return the type T without the reference modifier.
             template 
            diff --git a/lib/ArduinoJson-5.13.4/src/ArduinoJson/version.hpp b/lib/ArduinoJson-5.13.4/src/ArduinoJson/version.hpp
            new file mode 100644
            index 000000000..34c78461d
            --- /dev/null
            +++ b/lib/ArduinoJson-5.13.4/src/ArduinoJson/version.hpp
            @@ -0,0 +1,10 @@
            +// ArduinoJson - arduinojson.org
            +// Copyright Benoit Blanchon 2014-2018
            +// MIT License
            +
            +#pragma once
            +
            +#define ARDUINOJSON_VERSION "5.13.4"
            +#define ARDUINOJSON_VERSION_MAJOR 5
            +#define ARDUINOJSON_VERSION_MINOR 13
            +#define ARDUINOJSON_VERSION_REVISION 4
            
            From c8043e2f5b6b385f8318f0d2049eeb94c48ccd39 Mon Sep 17 00:00:00 2001
            From: Donat Marko 
            Date: Thu, 10 Jan 2019 00:07:43 +0100
            Subject: [PATCH 0836/2222] :label: Improves Hungarian (hu-HU) translation
             :hungary:
            
            ---
             sonoff/language/hu-HU.h | 508 ++++++++++++++++++++--------------------
             1 file changed, 254 insertions(+), 254 deletions(-)
            
            diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h
            index e3668ce1d..ee071da54 100644
            --- a/sonoff/language/hu-HU.h
            +++ b/sonoff/language/hu-HU.h
            @@ -52,36 +52,36 @@
             
             // Common
             #define D_ADMIN "Admin"
            -#define D_AIR_QUALITY "Levegő minőség"
            +#define D_AIR_QUALITY "Levegőminőség"
             #define D_AP "AP"                    // Access Point
             #define D_AS "mint"
             #define D_AUTO "AUTO"
             #define D_BLINK "Villogás"
            -#define D_BLINKOFF "Villogás Ki"
            -#define D_BOOT_COUNT "Bootolások száma"
            +#define D_BLINKOFF "Villogás ki"
            +#define D_BOOT_COUNT "Újraindulások száma"
             #define D_BRIGHTLIGHT "Max. fényerő"
            -#define D_BSSID "BSSId"
            +#define D_BSSID "BSSID"
             #define D_BUTTON "Gomb"
            -#define D_BY "tőle:"                    // Written by me
            +#define D_BY "by"                    // Written by me
             #define D_BYTES "Byte-ok"
             #define D_CELSIUS "Celsius"
            -#define D_CHANNEL "Channel"
            +#define D_CHANNEL "Csatorna"
             #define D_CO2 "Szén-dioxid"
             #define D_CODE "kód"                // Button code
            -#define D_COLDLIGHT "Hideg"
            +#define D_COLDLIGHT "Hideg fény"
             #define D_COMMAND "Parancs"
            -#define D_CONNECTED "Csatlakozva"
            +#define D_CONNECTED "Csatlakoztatva"
             #define D_COUNT "Szám"
             #define D_COUNTER "Számláló"
            -#define D_CURRENT "Áram"          // As in Voltage and Current
            +#define D_CURRENT "Áramerősség"          // As in Voltage and Current
             #define D_DATA "Adat"
             #define D_DARKLIGHT "Min. fényerő"
             #define D_DEBUG "Debug"
             #define D_DISABLED "Letiltva"
            -#define D_DISTANCE "Distance"
            -#define D_DNS_SERVER "DNS Szerver"
            +#define D_DISTANCE "Távolság"
            +#define D_DNS_SERVER "DNS szerver"
             #define D_DONE "Kész"
            -#define D_DST_TIME "DST"
            +#define D_DST_TIME "nyári idő"
             #define D_ECO2 "eCO2"
             #define D_EMULATION "Emuláció"
             #define D_ENABLED "Engedélyezve"
            @@ -90,24 +90,24 @@
             #define D_FAHRENHEIT "Fahrenheit"
             #define D_FAILED "Sikertelen"
             #define D_FALLBACK "Fallback"
            -#define D_FALLBACK_TOPIC "Fallback Téma"
            +#define D_FALLBACK_TOPIC "fallback topik"
             #define D_FALSE "Hamis"
            -#define D_FILE "File"
            -#define D_FREE_MEMORY "Szabad Memória"
            -#define D_FREQUENCY "Frequency"
            +#define D_FILE "Fájl"
            +#define D_FREE_MEMORY "Szabad memória"
            +#define D_FREQUENCY "Frekvencia"
             #define D_GAS "Gáz"
            -#define D_GATEWAY "Gateway"
            +#define D_GATEWAY "Átjáró"
             #define D_GROUP "Csoport"
            -#define D_HOST "Host"
            -#define D_HOSTNAME "Hostname"
            +#define D_HOST "Hoszt"
            +#define D_HOSTNAME "Hosztnév"
             #define D_HUMIDITY "Páratartalom"
             #define D_ILLUMINANCE "Megvilágítás"
             #define D_IMMEDIATE "azonnali"      // Button immediate
             #define D_INDEX "Index"
             #define D_INFO "Info"
            -#define D_INFRARED "Infrared"
            +#define D_INFRARED "Infravörös"
             #define D_INITIALIZED "Inicializálva"
            -#define D_IP_ADDRESS "IP Cím"
            +#define D_IP_ADDRESS "IP cím"
             #define D_LIGHT "Fény"
             #define D_LWT "LWT"
             #define D_MODULE "Modul"
            @@ -117,89 +117,89 @@
             #define D_NONE "nincs"
             #define D_OFF "Ki"
             #define D_OFFLINE "Offline"
            -#define D_OK "Ok"
            +#define D_OK "OK"
             #define D_ON "Be"
             #define D_ONLINE "Online"
             #define D_PASSWORD "Jelszó"
             #define D_PORT "Port"
            -#define D_POWER_FACTOR "Teljesítmény tényező"
            +#define D_POWER_FACTOR "Teljesítménytényező"
             #define D_POWERUSAGE "Energiafelhasználás"
            -#define D_POWERUSAGE_ACTIVE "Active Power"
            -#define D_POWERUSAGE_APPARENT "Apparent Power"
            -#define D_POWERUSAGE_REACTIVE "Reactive Power"
            +#define D_POWERUSAGE_ACTIVE "Aktív teljesítmény"
            +#define D_POWERUSAGE_APPARENT "Látszólagos teljesítmény"
            +#define D_POWERUSAGE_REACTIVE "Reaktív teljesítmény"
             #define D_PRESSURE "Nyomás"
             #define D_PRESSUREATSEALEVEL "Tengerszinti nyomás"
            -#define D_PROGRAM_FLASH_SIZE "Program Flash Méret"
            -#define D_PROGRAM_SIZE "Program Méret"
            +#define D_PROGRAM_FLASH_SIZE "Program flash méret"
            +#define D_PROGRAM_SIZE "Program méret"
             #define D_PROJECT "Projekt"
            -#define D_RAIN "Rain"
            +#define D_RAIN "Eső"
             #define D_RECEIVED "Érkezett"
             #define D_RESTART "Újraindítás"
             #define D_RESTARTING "Újraindítás"
            -#define D_RESTART_REASON "Újraindítás oka:"
            +#define D_RESTART_REASON "Utolsó újraindulás oka"
             #define D_RESTORE "Visszaállítás"
            -#define D_RETAINED "mentve"
            -#define D_RULE "Rule"
            +#define D_RETAINED "retained"
            +#define D_RULE "Szabály"
             #define D_SAVE "Mentés"
             #define D_SENSOR "Szenzor"
            -#define D_SSID "SSId"
            +#define D_SSID "SSID"
             #define D_START ""
             #define D_STD_TIME "STD"
             #define D_STOP "Leállítás"
            -#define D_SUBNET_MASK "Subnet Mask"
            -#define D_SUBSCRIBE_TO "Feliratkozás a"
            +#define D_SUBNET_MASK "Alhálózati maszk"
            +#define D_SUBSCRIBE_TO "Feliratkozás a(z)"
             #define D_SUCCESSFUL "Sikeres"
            -#define D_SUNRISE "Sunrise"
            -#define D_SUNSET "Sunset"
            +#define D_SUNRISE "Napkelte"
            +#define D_SUNSET "Napnyugta"
             #define D_TEMPERATURE "Hőmérséklet"
             #define D_TO "-nak"
            -#define D_TOGGLE "Toggle"
            -#define D_TOPIC "Téma"
            +#define D_TOGGLE "Megfordítás"
            +#define D_TOPIC "Topic"
             #define D_TRANSMIT "Továbbít"
             #define D_TRUE "Igaz"
             #define D_TVOC "TVOC"
            -#define D_UPGRADE "frissítés"
            +#define D_UPGRADE "Frissítés"
             #define D_UPLOAD "Feltöltés"
             #define D_UPTIME "Üzemidő"
             #define D_USER "Felhasználó"
             #define D_UTC_TIME "UTC"
            -#define D_UV_INDEX "UV Index"
            -#define D_UV_INDEX_1 "Low"
            -#define D_UV_INDEX_2 "Mid"
            -#define D_UV_INDEX_3 "High"
            -#define D_UV_INDEX_4 "Danger"
            -#define D_UV_INDEX_5 "BurnL1/2"
            -#define D_UV_INDEX_6 "BurnL3"
            -#define D_UV_INDEX_7 "OoR"
            -#define D_UV_LEVEL "UV Szint"
            -#define D_UV_POWER "UV Power"
            +#define D_UV_INDEX "UV index"
            +#define D_UV_INDEX_1 "alacsony"
            +#define D_UV_INDEX_2 "közepes"
            +#define D_UV_INDEX_3 "magas"
            +#define D_UV_INDEX_4 "veszélyes"
            +#define D_UV_INDEX_5 "égés L1/2"
            +#define D_UV_INDEX_6 "égés L3"
            +#define D_UV_INDEX_7 "tartományon kívül"
            +#define D_UV_LEVEL "UV szint"
            +#define D_UV_POWER "UV teljesítmény"
             #define D_VERSION "Verzió"
             #define D_VOLTAGE "Feszültség"
            -#define D_WEIGHT "Weight"
            -#define D_WARMLIGHT "Meleg"
            -#define D_WEB_SERVER "Web Szerver"
            +#define D_WEIGHT "Tömeg"
            +#define D_WARMLIGHT "Meleg fény"
            +#define D_WEB_SERVER "Webszerver"
             
             // sonoff.ino
            -#define D_WARNING_MINIMAL_VERSION "VIGYÁZZ Ez a verzió nem támogat tartós beállításokat"
            +#define D_WARNING_MINIMAL_VERSION "VIGYÁZZ! Ez a verzió nem támogat tartós beállításokat"
             #define D_LEVEL_10 "szint 1-0"
             #define D_LEVEL_01 "szint 0-1"
            -#define D_SERIAL_LOGGING_DISABLED "Serial logolás kikapcsolva"
            -#define D_SYSLOG_LOGGING_REENABLED "Syslog logolás újra-engedélyezve"
            +#define D_SERIAL_LOGGING_DISABLED "Soros naplózás kikapcsolva"
            +#define D_SYSLOG_LOGGING_REENABLED "Syslog logolás újraengedélyezve"
             
             #define D_SET_BAUDRATE_TO "Baudrate beállítása"
            -#define D_RECEIVED_TOPIC "Érkezett Téma"
            -#define D_DATA_SIZE "Adat Méret"
            +#define D_RECEIVED_TOPIC "Érkezett topic"
            +#define D_DATA_SIZE "Adatméret"
             #define D_ANALOG_INPUT "Analóg"
             
             // support.ino
             #define D_OSWATCH "osWatch"
            -#define D_BLOCKED_LOOP "Blocked Loop"
            +#define D_BLOCKED_LOOP "Tiltott hurok"
             #define D_WPS_FAILED_WITH_STATUS "WPSconfig SIKERTELEN státusz:"
             #define D_ACTIVE_FOR_3_MINUTES "aktválás 3 percre"
             #define D_FAILED_TO_START "sikertelen indítás"
             #define D_PATCH_ISSUE_2186 "Patch issue 2186"
            -#define D_CONNECTING_TO_AP "Csatlakozás az (AP): "
            -#define D_IN_MODE "be mód"
            +#define D_CONNECTING_TO_AP "AP-hoz csatlakozás:"
            +#define D_IN_MODE "mód:"
             #define D_CONNECT_FAILED_NO_IP_ADDRESS "Sikertelen csatlakozás, nincs kiosztott IP cím"
             #define D_CONNECT_FAILED_AP_NOT_REACHED "Sikertelen csatlakozás, AP nem elérhető"
             #define D_CONNECT_FAILED_WRONG_PASSWORD "Sikertelen csatlakozás, hibás AP jelszó"
            @@ -207,151 +207,151 @@
             #define D_ATTEMPTING_CONNECTION "Csatlakozás..."
             #define D_CHECKING_CONNECTION "Kapcsolat ellenőrzése..."
             #define D_QUERY_DONE "Lekérés kész. MQTT szolgáltatás aktív"
            -#define D_MQTT_SERVICE_FOUND "élő MQTT szolgáltatás a"
            -#define D_FOUND_AT "a"
            -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nem található"
            +#define D_MQTT_SERVICE_FOUND "élő MQTT szolgáltatás a(z)"
            +#define D_FOUND_AT "a(z)"
            +#define D_SYSLOG_HOST_NOT_FOUND "Syslog hoszt nem található"
             
             // settings.ino
            -#define D_SAVED_TO_FLASH_AT "Flash-re mentve a"
            -#define D_LOADED_FROM_FLASH_AT "Flash-ről betöltve a"
            +#define D_SAVED_TO_FLASH_AT "Flash-re mentve a(z)"
            +#define D_LOADED_FROM_FLASH_AT "Flash-ről betöltve a(z)"
             #define D_USE_DEFAULTS "Alapértelmezett beáll. használata"
             #define D_ERASED_SECTOR "Szektor törlése"
             
             // xdrv_02_webserver.ino
            -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript"
            -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - frissítsd!"
            -#define D_WEBSERVER_ACTIVE_ON "Web szerver aktív a"
            -#define D_WITH_IP_ADDRESS "IP címe:"
            -#define D_WEBSERVER_STOPPED "Webs zerver leállítva"
            -#define D_FILE_NOT_FOUND "File Nem Található"
            +#define D_NOSCRIPT "A Tasmota használatához engedélyezd a Javascriptet!"
            +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware - frissítsd!"
            +#define D_WEBSERVER_ACTIVE_ON "Webszerver aktív:"
            +#define D_WITH_IP_ADDRESS "IP cím:"
            +#define D_WEBSERVER_STOPPED "Webszerver leállítva"
            +#define D_FILE_NOT_FOUND "Fájl nem található"
             #define D_REDIRECTED "Átírányítás captive portálra"
            -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager AccessPoint(AP) és Station(ST) beállítása"
            +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "WifiManager AccessPoint(AP) és Station(ST) beállítása"
             #define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager AccessPoint(AP) beállítása"
             #define D_TRYING_TO_CONNECT "Csatlakozás a hálózatra..."
             
             #define D_RESTART_IN "Újraindítás..."
             #define D_SECONDS "másodperc"
            -#define D_DEVICE_WILL_RESTART "Az eszköz hamarosan újraindul"
            -#define D_BUTTON_TOGGLE "Toggle"
            -#define D_CONFIGURATION "Konfigurációk"
            +#define D_DEVICE_WILL_RESTART "Az eszköz hamarosan újraindul..."
            +#define D_BUTTON_TOGGLE "Megfordítás"
            +#define D_CONFIGURATION "Beállítások"
             #define D_INFORMATION "Információ"
            -#define D_FIRMWARE_UPGRADE "Firmware Frissítés"
            +#define D_FIRMWARE_UPGRADE "Firmware frissítés"
             #define D_CONSOLE "Konzol"
            -#define D_CONFIRM_RESTART "Újraindítás megerősítése"
            +#define D_CONFIRM_RESTART "Biztosan újraindítsam a modult?"
             
            -#define D_CONFIGURE_MODULE "Eszköz konfiguráció"
            +#define D_CONFIGURE_MODULE "Eszközbeállítások"
             #define D_CONFIGURE_WIFI "WiFi konfiguráció"
             #define D_CONFIGURE_MQTT "MQTT konfiguráció"
             #define D_CONFIGURE_DOMOTICZ "Domoticz konfiguráció"
            -#define D_CONFIGURE_LOGGING "Logolás konfiguráció"
            -#define D_CONFIGURE_OTHER "Egyéb konfiguráció"
            -#define D_CONFIRM_RESET_CONFIGURATION "Konfig resetelés megerősítve?"
            -#define D_RESET_CONFIGURATION "Konfiguráció reset"
            -#define D_BACKUP_CONFIGURATION "Konfiguráció backup"
            -#define D_RESTORE_CONFIGURATION "Konfiguráció visszaállítás"
            +#define D_CONFIGURE_LOGGING "Naplózás beállításai"
            +#define D_CONFIGURE_OTHER "Egyéb beállítások"
            +#define D_CONFIRM_RESET_CONFIGURATION "Biztosan töröljem a beállításokat?"
            +#define D_RESET_CONFIGURATION "Beállítások törlése"
            +#define D_BACKUP_CONFIGURATION "Beállítások mentése"
            +#define D_RESTORE_CONFIGURATION "Beállítások visszatöltése"
             #define D_MAIN_MENU "Menü"
             
             #define D_MODULE_PARAMETERS "Modul paraméterek"
            -#define D_MODULE_TYPE "Modul típus"
            -#define D_PULLUP_ENABLE "No Button/Switch pull-up"
            +#define D_MODULE_TYPE "Alkalmazott modul"
            +#define D_PULLUP_ENABLE "Nincs felhúzó ellenállás"
             #define D_GPIO "GPIO"
            -#define D_SERIAL_IN "Serial In"
            -#define D_SERIAL_OUT "Serial Out"
            +#define D_SERIAL_IN "Soros BE"
            +#define D_SERIAL_OUT "Soros KI"
             
            -#define D_WIFI_PARAMETERS "Wifi paraméterek"
            -#define D_SCAN_FOR_WIFI_NETWORKS "Wifi hálózat keresése"
            +#define D_WIFI_PARAMETERS "WiFi paraméterek"
            +#define D_SCAN_FOR_WIFI_NETWORKS "WiFi hálózat keresése"
             #define D_SCAN_DONE "Keresés kész"
             #define D_NO_NETWORKS_FOUND "Nincs elérhető hálózat"
            -#define D_REFRESH_TO_SCAN_AGAIN "Frissíts az újra kereséshez"
            -#define D_DUPLICATE_ACCESSPOINT "Duplicate AccessPoint"
            -#define D_SKIPPING_LOW_QUALITY "Kihagyás, alacsony jelminőség"
            +#define D_REFRESH_TO_SCAN_AGAIN "Frissíts az újrakereséshez"
            +#define D_DUPLICATE_ACCESSPOINT "Duplikált access point"
            +#define D_SKIPPING_LOW_QUALITY "Rossz, alacsony jelminőség"
             #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 Jelszó"
            +#define D_AP1_PASSWORD "AP1 megosztott kulcs"
             #define D_AP2_SSID "AP2 SSID"
            -#define D_AP2_PASSWORD "AP2 Jelszó"
            +#define D_AP2_PASSWORD "AP2 megosztott kulcs"
             
             #define D_MQTT_PARAMETERS "MQTT paraméterek"
             #define D_CLIENT "Kliens"
            -#define D_FULL_TOPIC "Teljes téma"
            +#define D_FULL_TOPIC "Teljes topic"
             
            -#define D_LOGGING_PARAMETERS "Logolás paraméterek"
            -#define D_SERIAL_LOG_LEVEL "Serial logolás szint"
            -#define D_WEB_LOG_LEVEL "Web logolás szint"
            +#define D_LOGGING_PARAMETERS "Naplózási paraméterek"
            +#define D_SERIAL_LOG_LEVEL "Soros naplózási szint"
            +#define D_WEB_LOG_LEVEL "Web naplózási szint"
             #define D_SYS_LOG_LEVEL "Syslog szint"
            -#define D_MORE_DEBUG "Részletes debug"
            -#define D_SYSLOG_HOST "Syslog host"
            +#define D_MORE_DEBUG "Részletes hibakeresés"
            +#define D_SYSLOG_HOST "Syslog hoszt"
             #define D_SYSLOG_PORT "Syslog port"
            -#define D_TELEMETRY_PERIOD "Telemetria (sec)"
            +#define D_TELEMETRY_PERIOD "Telemetria (mp.)"
             
            -#define D_OTHER_PARAMETERS "Egyéb paraméterek"
            -#define D_WEB_ADMIN_PASSWORD "Web Admin Jelszó"
            -#define D_MQTT_ENABLE "MQTT engedélyezés"
            +#define D_OTHER_PARAMETERS "Egyéb beállítások"
            +#define D_WEB_ADMIN_PASSWORD "Web admin jelszó"
            +#define D_MQTT_ENABLE "MQTT engedélyezése"
             #define D_FRIENDLY_NAME "Név"
             #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 "Konfiguráció mentése"
            -#define D_CONFIGURATION_SAVED "Konfiguráció elmentve"
            -#define D_CONFIGURATION_RESET "Konfiguráció visszaállítása"
            +#define D_SAVE_CONFIGURATION "Beállítások mentése"
            +#define D_CONFIGURATION_SAVED "Beállítások elmentve"
            +#define D_CONFIGURATION_RESET "Beállítások visszaállítása"
             
            -#define D_PROGRAM_VERSION "Program Verzió"
            -#define D_BUILD_DATE_AND_TIME "Build Dátum & Idő"
            -#define D_CORE_AND_SDK_VERSION "Core/SDK Verzió"
            -#define D_FLASH_WRITE_COUNT "Flashelések száma"
            -#define D_MAC_ADDRESS "MAC Cím"
            -#define D_MQTT_HOST "MQTT Host"
            -#define D_MQTT_PORT "MQTT Port"
            -#define D_MQTT_CLIENT "MQTT Cliens"
            -#define D_MQTT_USER "MQTT Felhasználó"
            -#define D_MQTT_TOPIC "MQTT Téma"
            -#define D_MQTT_GROUP_TOPIC "MQTT Csoport Téma"
            -#define D_MQTT_FULL_TOPIC "MQTT Teljes téma"
            -#define D_MDNS_DISCOVERY "mDNS Láthatóság"
            -#define D_MDNS_ADVERTISE "mDNS Hírdetés"
            -#define D_ESP_CHIP_ID "ESP Chip Id"
            -#define D_FLASH_CHIP_ID "Flash Chip Id"
            -#define D_FLASH_CHIP_SIZE "Flash Méret"
            -#define D_FREE_PROGRAM_SPACE "Szabad Program Hely"
            +#define D_PROGRAM_VERSION "Program verzió"
            +#define D_BUILD_DATE_AND_TIME "Build ideje"
            +#define D_CORE_AND_SDK_VERSION "Core/SDK verzió"
            +#define D_FLASH_WRITE_COUNT "Flash írások száma"
            +#define D_MAC_ADDRESS "MAC cím"
            +#define D_MQTT_HOST "MQTT hoszt"
            +#define D_MQTT_PORT "MQTT port"
            +#define D_MQTT_CLIENT "MQTT kliens"
            +#define D_MQTT_USER "MQTT felhasználó"
            +#define D_MQTT_TOPIC "MQTT topic"
            +#define D_MQTT_GROUP_TOPIC "MQTT csoport topic"
            +#define D_MQTT_FULL_TOPIC "MQTT teljes topic"
            +#define D_MDNS_DISCOVERY "mDNS láthatóság"
            +#define D_MDNS_ADVERTISE "mDNS hirdetés"
            +#define D_ESP_CHIP_ID "ESP chip ID"
            +#define D_FLASH_CHIP_ID "Flash chip ID"
            +#define D_FLASH_CHIP_SIZE "Flash mérete"
            +#define D_FREE_PROGRAM_SPACE "Szabad programhely"
             
            -#define D_UPGRADE_BY_WEBSERVER "Frissítés web szerverrel"
            -#define D_OTA_URL "OTA Url"
            +#define D_UPGRADE_BY_WEBSERVER "Frissítés távoli szerverről"
            +#define D_OTA_URL "OTA URL"
             #define D_START_UPGRADE "Frissítés"
            -#define D_UPGRADE_BY_FILE_UPLOAD "Frissítés file feltöltéssel"
            +#define D_UPGRADE_BY_FILE_UPLOAD "Frissítés helyi fájllal"
             #define D_UPLOAD_STARTED "Feltöltés elindítva"
             #define D_UPGRADE_STARTED "Frissítés elindítva"
             #define D_UPLOAD_DONE "Feltöltés kész"
            -#define D_UPLOAD_ERR_1 "Nincs file kijelölve"
            +#define D_UPLOAD_ERR_1 "Nincs fájl kijelölve"
             #define D_UPLOAD_ERR_2 "Nincs elég memória"
            -#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9"
            -#define D_UPLOAD_ERR_4 "Program flash méret nagyobb a valós flash méretnél"
            -#define D_UPLOAD_ERR_5 "Feltöltés buffer hiba"
            -#define D_UPLOAD_ERR_6 "Feltöltés sikertelen. Endegélyezz 3-mas logolást"
            +#define D_UPLOAD_ERR_3 "A \"magic byte\" nem 0xE9"
            +#define D_UPLOAD_ERR_4 "A program flashméret nagyobb a valós flashméretnél"
            +#define D_UPLOAD_ERR_5 "Feltöltési buffer hiba"
            +#define D_UPLOAD_ERR_6 "Feltöltés sikertelen. Endegélyezd a 3. szintű naplózást"
             #define D_UPLOAD_ERR_7 "Feltöltés megszakítva"
            -#define D_UPLOAD_ERR_8 "Érvénytelen file"
            -#define D_UPLOAD_ERR_9 "File túl nagy"
            -#define D_UPLOAD_ERR_10 "Failed to init RF chip"
            -#define D_UPLOAD_ERR_11 "Failed to erase RF chip"
            -#define D_UPLOAD_ERR_12 "Failed to write to RF chip"
            -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware"
            -#define D_UPLOAD_ERROR_CODE "Feltöltés hiba kód"
            +#define D_UPLOAD_ERR_8 "Érvénytelen fájl"
            +#define D_UPLOAD_ERR_9 "A fájl túl nagy"
            +#define D_UPLOAD_ERR_10 "Az RF chip inicializálása sikertelen"
            +#define D_UPLOAD_ERR_11 "Az RF chip törlése sikertelen"
            +#define D_UPLOAD_ERR_12 "Az RF chip írása sikertelen"
            +#define D_UPLOAD_ERR_13 "Az RF firmware dekódolása sikertelen"
            +#define D_UPLOAD_ERROR_CODE "Feltöltési hibakód"
             
            -#define D_ENTER_COMMAND "Parancsolj"
            -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Engedélyezz 2-es weblogolást több információért"
            -#define D_NEED_USER_AND_PASSWORD "Kell felhasználó=&jelszó="
            +#define D_ENTER_COMMAND "Kérem a parancsot..."
            +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Engedélyezz 2-es szintű webnaplózást több információért"
            +#define D_NEED_USER_AND_PASSWORD "Szükséges a user=&password= paraméter"
             
             // xdrv_01_mqtt.ino
             #define D_FINGERPRINT "TLS fingerprint hitelesítése..."
            -#define D_TLS_CONNECT_FAILED_TO "TLS Csatlakozás sikertelen a"
            +#define D_TLS_CONNECT_FAILED_TO "TLS csatlakozás sikertelen a(z)"
             #define D_RETRY_IN "Újrapróbálás"
            -#define D_VERIFIED "Hitelesítve Fingerprint"
            -#define D_INSECURE "Nem biztonságos kapcsolat érvénytelen Fingerprint miatt"
            -#define D_CONNECT_FAILED_TO "Sikertelen csatlakozás a"
            +#define D_VERIFIED "Fingerprint hitelesítve"
            +#define D_INSECURE "Nem biztonságos kapcsolat érvénytelen fingerprint miatt"
            +#define D_CONNECT_FAILED_TO "Sikertelen csatlakozás a(z)"
             
             // xplg_wemohue.ino
             #define D_MULTICAST_DISABLED "Multicast kikapcsolva"
            @@ -370,8 +370,8 @@
             #define D_HUE_BRIDGE_SETUP "Hue beállítás"
             #define D_HUE_API_NOT_IMPLEMENTED "Hue API nincs implementálva"
             #define D_HUE_API "Hue API"
            -#define D_HUE_POST_ARGS "Hue POST args"
            -#define D_3_RESPONSE_PACKETS_SENT "3 válaszcsomagok elküldve"
            +#define D_HUE_POST_ARGS "Hue POST argumentumok"
            +#define D_3_RESPONSE_PACKETS_SENT "3 válaszcsomag elküldve"
             
             // xdrv_07_domoticz.ino
             #define D_DOMOTICZ_PARAMETERS "Domoticz paraméterek"
            @@ -379,71 +379,71 @@
             #define D_DOMOTICZ_KEY_IDX "Key idx"
             #define D_DOMOTICZ_SWITCH_IDX "Kapcsoló idx"
             #define D_DOMOTICZ_SENSOR_IDX "Szenzor idx"
            -  #define D_DOMOTICZ_TEMP "Temp"
            -  #define D_DOMOTICZ_TEMP_HUM "Hőm,Párat"
            -  #define D_DOMOTICZ_TEMP_HUM_BARO "Hőm,Párat,Légny"
            -  #define D_DOMOTICZ_POWER_ENERGY "Teljesítmény,Energia"
            +  #define D_DOMOTICZ_TEMP "Hőmérséklet"
            +  #define D_DOMOTICZ_TEMP_HUM "Hőmérséklet, páratartalom"
            +  #define D_DOMOTICZ_TEMP_HUM_BARO "Hőmérséklet, páratartalom, légnyomás"
            +  #define D_DOMOTICZ_POWER_ENERGY "Teljesítmény, energia"
               #define D_DOMOTICZ_ILLUMINANCE "Fényerő"
               #define D_DOMOTICZ_COUNT "Szám/PM1"
               #define D_DOMOTICZ_VOLTAGE "Feszültség/PM2.5"
               #define D_DOMOTICZ_CURRENT "Áram/PM10"
               #define D_DOMOTICZ_AIRQUALITY "Légminőség"
            -#define D_DOMOTICZ_UPDATE_TIMER "Update időzítő"
            +#define D_DOMOTICZ_UPDATE_TIMER "Frissítési időzítő"
             
             // xdrv_09_timers.ino
            -#define D_CONFIGURE_TIMER "Configure Timer"
            -#define D_TIMER_PARAMETERS "Timer parameters"
            -#define D_TIMER_ENABLE "Enable Timers"
            -#define D_TIMER_ARM "Arm"
            -#define D_TIMER_TIME "Time"
            -#define D_TIMER_DAYS "Days"
            -#define D_TIMER_REPEAT "Repeat"
            -#define D_TIMER_OUTPUT "Output"
            -#define D_TIMER_ACTION "Action"
            +#define D_CONFIGURE_TIMER "Időzítő beállításai"
            +#define D_TIMER_PARAMETERS "Időzítő paraméterei"
            +#define D_TIMER_ENABLE "Időzítők engedélyezve"
            +#define D_TIMER_ARM "Be"
            +#define D_TIMER_TIME "Idő"
            +#define D_TIMER_DAYS "Napok"
            +#define D_TIMER_REPEAT "Ismétlés"
            +#define D_TIMER_OUTPUT "Kimenet"
            +#define D_TIMER_ACTION "Művelet"
             
             // xdrv_10_knx.ino
            -#define D_CONFIGURE_KNX "Configure KNX"
            -#define D_KNX_PARAMETERS "KNX Parameters"
            -#define D_KNX_GENERAL_CONFIG "General"
            -#define D_KNX_PHYSICAL_ADDRESS "Physical Address"
            -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )"
            -#define D_KNX_ENABLE "Enable KNX"
            -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses"
            -#define D_ADD "Add"
            -#define D_DELETE "Delete"
            -#define D_REPLY "Reply"
            -#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from"
            +#define D_CONFIGURE_KNX "KNX beállításai"
            +#define D_KNX_PARAMETERS "KNX paraméterei"
            +#define D_KNX_GENERAL_CONFIG "Általános"
            +#define D_KNX_PHYSICAL_ADDRESS "Fizikai cím"
            +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(egyedinek kell lennie a KNX hálózaton)"
            +#define D_KNX_ENABLE "KNX engedélyezése"
            +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Íráshoz használt csoportcímek"
            +#define D_ADD "Hozzáadás"
            +#define D_DELETE "Törlés"
            +#define D_REPLY "Válasz"
            +#define D_KNX_GROUP_ADDRESS_TO_READ "Fogadáshoz használt csoportcímek"
             #define D_LOG_KNX "KNX: "
            -#define D_RECEIVED_FROM "Received from"
            -#define D_KNX_COMMAND_WRITE "Write"
            -#define D_KNX_COMMAND_READ "Read"
            -#define D_KNX_COMMAND_OTHER "Other"
            -#define D_SENT_TO "sent to"
            -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used."
            +#define D_RECEIVED_FROM "Fogadva tőle:"
            +#define D_KNX_COMMAND_WRITE "Írás"
            +#define D_KNX_COMMAND_READ "Olvasás"
            +#define D_KNX_COMMAND_OTHER "Egyáb"
            +#define D_SENT_TO "küldve neki:"
            +#define D_KNX_WARNING "A csoportcím ( 0 / 0 / 0 ) fenntartott és nem használható."
             #define D_KNX_ENHANCEMENT "Communication Enhancement"
             #define D_KNX_TX_SLOT "KNX TX"
             #define D_KNX_RX_SLOT "KNX RX"
             
             // xdrv_03_energy.ino
            -#define D_ENERGY_TODAY "Mai Energia"
            -#define D_ENERGY_YESTERDAY "Tegnapi Energia"
            -#define D_ENERGY_TOTAL "Összes Energia"
            +#define D_ENERGY_TODAY "Mai energia"
            +#define D_ENERGY_YESTERDAY "Tegnapi energia"
            +#define D_ENERGY_TOTAL "Összes energia"
             
             // xsns_05_ds18b20.ino
            -#define D_SENSOR_BUSY "Szenzor elfoglalt"
            +#define D_SENSOR_BUSY "Szenzor foglalt"
             #define D_SENSOR_CRC_ERROR "Szenzor CRC hiba"
             #define D_SENSORS_FOUND "Szenzorok megtalálva"
             
             // xsns_06_dht.ino
            -#define D_TIMEOUT_WAITING_FOR "Timeout waiting for"
            -#define D_START_SIGNAL_LOW "start signal low"
            -#define D_START_SIGNAL_HIGH "start signal high"
            -#define D_PULSE "pulse"
            -#define D_CHECKSUM_FAILURE "Checksum failure"
            +#define D_TIMEOUT_WAITING_FOR "Időtúllépés, várakozás"
            +#define D_START_SIGNAL_LOW "startjel alacsony"
            +#define D_START_SIGNAL_HIGH "startjel magas"
            +#define D_PULSE "impulzus"
            +#define D_CHECKSUM_FAILURE "Checksum hiba"
             
             // xsns_07_sht1x.ino
            -#define D_SENSOR_DID_NOT_ACK_COMMAND "Szenzor nem ismerte el(ACK) a parancsot"
            -#define D_SHT1X_FOUND "SHT1X found"
            +#define D_SENSOR_DID_NOT_ACK_COMMAND "A szenzor nem nyugtázta a parancsot"
            +#define D_SHT1X_FOUND "SHT1X megtalálva"
             
             // xsns_18_pms5003.ino
             #define D_STANDARD_CONCENTRATION "CF-1 PM"     // Standard Particle CF-1 Particle Matter
            @@ -451,35 +451,35 @@
             #define D_PARTICALS_BEYOND "Részecskék"
             
             // xsns_32_mpu6050.ino
            -#define D_AX_AXIS "Accel. X-Axis"
            -#define D_AY_AXIS "Accel. Y-Axis"
            -#define D_AZ_AXIS "Accel. Z-Axis"
            -#define D_GX_AXIS "Gyro X-Axis"
            -#define D_GY_AXIS "Gyro Y-Axis"
            -#define D_GZ_AXIS "Gyro Z-Axis"
            +#define D_AX_AXIS "Gyorsulásm. X-tengely"
            +#define D_AY_AXIS "Gyorsulásm. Y-tengely"
            +#define D_AZ_AXIS "Gyorsulásm. Z-tengely"
            +#define D_GX_AXIS "Giroszkóp X-tengely"
            +#define D_GY_AXIS "Giroszkóp Y-tengely"
            +#define D_GZ_AXIS "Giroszkóp Z-tengely"
             
             // xsns_34_hx711.ino
            -#define D_HX_CAL_REMOVE "Remove weigth"
            -#define D_HX_CAL_REFERENCE "Load reference weigth"
            -#define D_HX_CAL_DONE "Calibrated"
            -#define D_HX_CAL_FAIL "Calibration failed"
            -#define D_RESET_HX711 "Reset Scale"
            -#define D_CONFIGURE_HX711 "Configure Scale"
            -#define D_HX711_PARAMETERS "Scale parameters"
            -#define D_ITEM_WEIGHT "Item weight"
            -#define D_REFERENCE_WEIGHT "Reference weigth"
            -#define D_CALIBRATE "Calibrate"
            -#define D_CALIBRATION "Calibration"
            +#define D_HX_CAL_REMOVE "Távolítsa el a súlyt"
            +#define D_HX_CAL_REFERENCE "Helyezze fel a referenciasúlyt"
            +#define D_HX_CAL_DONE "Kalibrálva"
            +#define D_HX_CAL_FAIL "Kalibrálási hiba"
            +#define D_RESET_HX711 "Skála újrabeállítása"
            +#define D_CONFIGURE_HX711 "Skála konfigurálása"
            +#define D_HX711_PARAMETERS "Skálaparaméterek"
            +#define D_ITEM_WEIGHT "Tárgy tömege"
            +#define D_REFERENCE_WEIGHT "Referenciatömeg"
            +#define D_CALIBRATE "Kalibrálás"
            +#define D_CALIBRATION "Kalibrálás"
             
             //xsns_35_tx20.ino
            -#define D_TX20_WIND_DIRECTION "Wind Direction"
            -#define D_TX20_WIND_SPEED "Wind Speed"
            -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg"
            -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max"
            -#define D_TX20_NORTH "N"
            -#define D_TX20_EAST "E"
            -#define D_TX20_SOUTH "S"
            -#define D_TX20_WEST "W"
            +#define D_TX20_WIND_DIRECTION "Szélirány"
            +#define D_TX20_WIND_SPEED "Szélsebesség"
            +#define D_TX20_WIND_SPEED_AVG "Átlag szélsebesség"
            +#define D_TX20_WIND_SPEED_MAX "Max. szélsebesség"
            +#define D_TX20_NORTH "É"
            +#define D_TX20_EAST "K"
            +#define D_TX20_SOUTH "D"
            +#define D_TX20_WEST "NY"
             
             // sonoff_template.h
             #define D_SENSOR_NONE     "Nincs"
            @@ -490,47 +490,47 @@
             #define D_SENSOR_I2C_SCL  "I2C SCL"
             #define D_SENSOR_I2C_SDA  "I2C SDA"
             #define D_SENSOR_WS2812   "WS2812"
            -#define D_SENSOR_DFR562   "MP3 Player"
            -#define D_SENSOR_IRSEND   "IRadó"
            +#define D_SENSOR_DFR562   "MP3 lejátszó"
            +#define D_SENSOR_IRSEND   "IR adó"
             #define D_SENSOR_SWITCH   "Kapcsoló"   // Suffix "1"
             #define D_SENSOR_BUTTON   "Gomb"   // Suffix "1"
             #define D_SENSOR_RELAY    "Relé"    // Suffix "1i"
            -#define D_SENSOR_LED      "Led"      // Suffix "1i"
            +#define D_SENSOR_LED      "LED"      // Suffix "1i"
             #define D_SENSOR_PWM      "PWM"      // Suffix "1"
             #define D_SENSOR_COUNTER  "Számláló"  // Suffix "1"
            -#define D_SENSOR_IRRECV   "IRvevő"
            -#define D_SENSOR_MHZ_RX   "MHZ Rx"
            -#define D_SENSOR_MHZ_TX   "MHZ Tx"
            -#define D_SENSOR_PZEM004_RX  "PZEM004 Rx"
            -#define D_SENSOR_PZEM016_RX  "PZEM016 Rx"
            -#define D_SENSOR_PZEM017_RX  "PZEM017 Rx"
            -#define D_SENSOR_PZEM0XX_TX  "PZEM0XX Tx"
            -#define D_SENSOR_SAIR_RX  "SAir Rx"
            -#define D_SENSOR_SAIR_TX  "SAir Tx"
            +#define D_SENSOR_IRRECV   "IR vevő"
            +#define D_SENSOR_MHZ_RX   "MHZ RX"
            +#define D_SENSOR_MHZ_TX   "MHZ TX"
            +#define D_SENSOR_PZEM004_RX  "PZEM004 RX"
            +#define D_SENSOR_PZEM016_RX  "PZEM016 RX"
            +#define D_SENSOR_PZEM017_RX  "PZEM017 RX"
            +#define D_SENSOR_PZEM0XX_TX  "PZEM0XX TX"
            +#define D_SENSOR_SAIR_RX  "SAir RX"
            +#define D_SENSOR_SAIR_TX  "SAir TX"
             #define D_SENSOR_SPI_CS   "SPI CS"
             #define D_SENSOR_SPI_DC   "SPI DC"
            -#define D_SENSOR_BACKLIGHT "Háttérvil"
            +#define D_SENSOR_BACKLIGHT "Háttérfény"
             #define D_SENSOR_PMS5003  "PMS5003"
            -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
            -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
            -#define D_SENSOR_SBR_RX   "SerBr Rx"
            -#define D_SENSOR_SBR_TX   "SerBr Tx"
            +#define D_SENSOR_SDS0X1_RX "SDS0X1 RX"
            +#define D_SENSOR_SDS0X1_TX "SDS0X1 TX"
            +#define D_SENSOR_SBR_RX   "SerBr RX"
            +#define D_SENSOR_SBR_TX   "SerBr TX"
             #define D_SENSOR_SR04_TRIG "SR04 Tri"
             #define D_SENSOR_SR04_ECHO "SR04 Ech"
            -#define D_SENSOR_SDM120_TX "SDM120/220 Tx"
            -#define D_SENSOR_SDM120_RX "SDM120/220 Rx"
            -#define D_SENSOR_SDM630_TX "SDM630 Tx"
            -#define D_SENSOR_SDM630_RX "SDM630 Rx"
            +#define D_SENSOR_SDM120_TX "SDM120/220 TX"
            +#define D_SENSOR_SDM120_RX "SDM120/220 RX"
            +#define D_SENSOR_SDM630_TX "SDM630 TX"
            +#define D_SENSOR_SDM630_RX "SDM630 RX"
             #define D_SENSOR_TM1638_CLK "TM16 CLK"
             #define D_SENSOR_TM1638_DIO "TM16 DIO"
             #define D_SENSOR_TM1638_STB "TM16 STB"
             #define D_SENSOR_HX711_SCK "HX711 SCK"
             #define D_SENSOR_HX711_DAT "HX711 DAT"
             #define D_SENSOR_TX20_TX "TX20"
            -#define D_SENSOR_RFSEND "RFSend"
            +#define D_SENSOR_RFSEND "RFsend"
             #define D_SENSOR_RFRECV "RFrecv"
            -#define D_SENSOR_TUYA_TX "Tuya Tx"
            -#define D_SENSOR_TUYA_RX "Tuya Rx"
            +#define D_SENSOR_TUYA_TX "Tuya TX"
            +#define D_SENSOR_TUYA_RX "Tuya RX"
             #define D_SENSOR_MGC3130_XFER "MGC3130 Xfer"
             #define D_SENSOR_MGC3130_RESET "MGC3130 Reset"
             #define D_SENSOR_SSPI_MISO "SSPI MISO"
            @@ -539,8 +539,8 @@
             #define D_SENSOR_SSPI_CS   "SSPI CS"
             #define D_SENSOR_SSPI_DC   "SSPI DC"
             #define D_SENSOR_RF_SENSOR "RF Sensor"
            -#define D_SENSOR_AZ_RX   "AZ Rx"
            -#define D_SENSOR_AZ_TX   "AZ Tx"
            +#define D_SENSOR_AZ_RX   "AZ RX"
            +#define D_SENSOR_AZ_TX   "AZ TX"
             #define D_SENSOR_MAX31855_CS  "MAX31855 CS"
             #define D_SENSOR_MAX31855_CLK "MAX31855 CLK"
             #define D_SENSOR_MAX31855_DO  "MAX31855 DO"
            @@ -549,7 +549,7 @@
             #define D_UNIT_AMPERE "A"
             #define D_UNIT_CENTIMETER "cm"
             #define D_UNIT_HERTZ "Hz"
            -#define D_UNIT_HOUR "ó"
            +#define D_UNIT_HOUR "h"
             #define D_UNIT_INCREMENTS "inc"
             #define D_UNIT_KILOGRAM "kg"
             #define D_UNIT_KILOMETER_PER_HOUR "km/h"  // or "km/h"
            @@ -563,12 +563,12 @@
             #define D_UNIT_MILLIMETER "mm"
             #define D_UNIT_MILLIMETER_MERCURY "mmHg"
             #define D_UNIT_MILLISECOND "ms"
            -#define D_UNIT_MINUTE "p"
            +#define D_UNIT_MINUTE "min"
             #define D_UNIT_PARTS_PER_BILLION "ppb"
             #define D_UNIT_PARTS_PER_DECILITER "ppd"
             #define D_UNIT_PARTS_PER_MILLION "ppm"
             #define D_UNIT_PRESSURE "hPa"
            -#define D_UNIT_SECOND "m"
            +#define D_UNIT_SECOND "s"
             #define D_UNIT_SECTORS "szektorok"
             #define D_UNIT_VA "VA"
             #define D_UNIT_VAR "VAr"
            @@ -603,13 +603,13 @@
             #define D_LOG_WIFI "WIF: "         // Wifi
             
             //SDM220
            -#define D_PHASE_ANGLE     "Phase Angle"
            -#define D_IMPORT_ACTIVE   "Import Active"
            -#define D_EXPORT_ACTIVE   "Export Active"
            -#define D_IMPORT_REACTIVE "Import Reactive"
            -#define D_EXPORT_REACTIVE "Export Reactive"
            -#define D_TOTAL_REACTIVE  "Total Reactive"
            +#define D_PHASE_ANGLE     "Fázisszög"
            +#define D_IMPORT_ACTIVE   "Bejövő aktív"
            +#define D_EXPORT_ACTIVE   "Kimenő aktív"
            +#define D_IMPORT_REACTIVE "Bejövő reaktív"
            +#define D_EXPORT_REACTIVE "Kimenő reaktív"
            +#define D_TOTAL_REACTIVE  "Összes reaktív"
             #define D_UNIT_KWARH      "kVArh"
            -#define D_UNIT_ANGLE      "Deg"
            +#define D_UNIT_ANGLE      "fok"
             
             #endif  // _LANGUAGE_HU_HU_H_
            
            From 5776faf857ccc399c3c7652aa87bc15cc4e1b280 Mon Sep 17 00:00:00 2001
            From: Theo Arends <11044339+arendst@users.noreply.github.com>
            Date: Thu, 10 Jan 2019 11:59:18 +0100
            Subject: [PATCH 0837/2222] Update sonoff_template.h
            
            ---
             sonoff/sonoff_template.h | 24 +++++++++++++++++++++---
             1 file changed, 21 insertions(+), 3 deletions(-)
            
            diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h
            index 761817e2a..aaa50b2dc 100644
            --- a/sonoff/sonoff_template.h
            +++ b/sonoff/sonoff_template.h
            @@ -951,8 +951,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                                    // GPIO11 (SD_CMD   Flash)
                  GPIO_PWM1,        // GPIO12 Light
                  GPIO_LED1_INV,    // GPIO13 Red Led (0 = On, 1 = Off) - Link and Power status
            -     0, 0,
            -     0, 0
            +     0, 0, 0, 0
               },
               { "Sonoff 4CH Pro",  // Sonoff 4CH Pro (ESP8285)
                  GPIO_KEY1,        // GPIO00 Button 1
            @@ -1149,7 +1148,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0,                // GPIO09 (SD_DATA2 Flash QIO or ESP8285)
                  0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
                                    // GPIO11 (SD_CMD   Flash)
            -     0, 0, 0, 0, 0
            +     0, 0, 0, 0, 0, 0
               },
               { "MagicHome",       // Magic Home (aka Flux-light) (ESP8266) and Arilux LC10 (ESP8285)
                                    // https://www.aliexpress.com/item/Magic-Home-Mini-RGB-RGBW-Wifi-Controller-For-Led-Strip-Panel-light-Timing-Function-16million-colors/32686853650.html
            @@ -1462,6 +1461,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_KEY3,        // GPIO14 Button 3
                  GPIO_LED1,        // GPIO15 Optional sensor
                  GPIO_REL1_INV,    // GPIO16 Green Led 1 (0 = On, 1 = Off)
            +     0
               },
               { "OBI Socket",      // OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko/p/2291706
                  GPIO_USER,        // GPIO00
            @@ -1718,6 +1718,24 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  0, 0, 0
               }
             
            +  { "N0DY Relay",      // N0DY Wifi Dual Relay (ESP-07)
            +                       // https://www.n0dy.com/product/web-controlled-dual-relay/
            +                       // https://www.amazon.com/dp/B072MKV8ZM
            +     GPIO_KEY1,        // GPIO00 PROG Button
            +     GPIO_USER,        // GPIO01 Serial RXD or Optional sensor on J2 RXD (if not using serial io)
            +     0,                // GPIO02 
            +     GPIO_USER,        // GPIO03 Serial TXD or Optional sensor on J2 TXD (if not using serial io)
            +     GPIO_REL2_INV,    // GPIO04 Relay 2 (active low)
            +     GPIO_REL1_INV,    // GPIO05 Relay 1 (active low)
            +                       // GPIO06 (SD_CLK   Flash)
            +                       // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT)
            +                       // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT)
            +     0,                // GPIO09 (SD_DATA2 Flash QIO or ESP8285)
            +     0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
            +                       // GPIO11 (SD_CMD   Flash)
            +     0, 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,
            
            From 2e101839a457ead0bd6d4ede0856902000d3b65c Mon Sep 17 00:00:00 2001
            From: Theo Arends <11044339+arendst@users.noreply.github.com>
            Date: Thu, 10 Jan 2019 12:57:42 +0100
            Subject: [PATCH 0838/2222] Change web authentication
            
            Change web authentication (#4865)
            ---
             sonoff/_changelog.ino        |  3 +-
             sonoff/xdrv_01_webserver.ino | 71 +++++++++++++++++++-----------------
             sonoff/xdrv_02_mqtt.ino      |  4 +-
             sonoff/xdrv_07_domoticz.ino  |  4 +-
             sonoff/xdrv_09_timers.ino    |  4 +-
             sonoff/xdrv_11_knx.ino       |  4 +-
             sonoff/xsns_34_hx711.ino     |  4 +-
             7 files changed, 49 insertions(+), 45 deletions(-)
            
            diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino
            index 00e3701f4..2bb633598 100644
            --- a/sonoff/_changelog.ino
            +++ b/sonoff/_changelog.ino
            @@ -5,7 +5,8 @@
              * Fix Home Assistant Sensor Discovery Software Watchdog restart (#4831)
              * Add support for OBI Power Socket 2 (#4829)
              * Add support for YTF IR Bridge (#4855)
            - *
            + * Change web authentication (#4865)
            + * 
              * 6.4.1.7 20190106
              * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6
              * Add Power status functionality to LED2 when configured leaving LED1 for Link status indication
            diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino
            index 6072f20fd..9c62a7561 100644
            --- a/sonoff/xdrv_01_webserver.ino
            +++ b/sonoff/xdrv_01_webserver.ino
            @@ -755,11 +755,17 @@ void HandleAjaxStatusRefresh(void)
               WebServer->send(200, FPSTR(HDR_CTYPE_HTML), mqtt_data);
             }
             
            -boolean HttpUser(void)
            +boolean HttpCheckPriviledgedAccess(boolean autorequestauth = true)
             {
            -  boolean status = (HTTP_USER == webserver_state);
            -  if (status) { HandleRoot(); }
            -  return status;
            +  if (HTTP_USER == webserver_state) {
            +    HandleRoot();
            +    return false;
            +  }
            +  if (autorequestauth && !WebAuthenticate()) {
            +    WebServer->requestAuthentication();
            +    return false;
            +  }
            +  return true;
             }
             
             /*-------------------------------------------------------------------------------------------*/
            @@ -768,8 +774,8 @@ boolean HttpUser(void)
             
             void HandleConfiguration(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURATION);
             
               String page = FPSTR(HTTP_HEAD);
            @@ -791,8 +797,7 @@ void HandleConfiguration(void)
             
             void HandleModuleConfiguration(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
             
               if (WebServer->hasArg("save")) {
                 ModuleSaveSettings();
            @@ -910,8 +915,7 @@ String htmlEscape(String s)
             
             void HandleWifiConfiguration(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
             
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI);
             
            @@ -1038,8 +1042,8 @@ void WifiSaveSettings(void)
             
             void HandleLoggingConfiguration(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_LOGGING);
             
               if (WebServer->hasArg("save")) {
            @@ -1121,8 +1125,8 @@ void LoggingSaveSettings(void)
             
             void HandleOtherConfiguration(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_OTHER);
             
               if (WebServer->hasArg("save")) {
            @@ -1193,8 +1197,8 @@ void OtherSaveSettings(void)
             
             void HandleBackupConfiguration(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_BACKUP_CONFIGURATION));
             
               if (!SettingsBufferAlloc()) { return; }
            @@ -1237,8 +1241,7 @@ void HandleBackupConfiguration(void)
             
             void HandleResetConfiguration(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
             
               char svalue[33];
             
            @@ -1258,8 +1261,8 @@ void HandleResetConfiguration(void)
             
             void HandleRestoreConfiguration(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTORE_CONFIGURATION);
             
               String page = FPSTR(HTTP_HEAD);
            @@ -1279,8 +1282,8 @@ void HandleRestoreConfiguration(void)
             
             void HandleInformation(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_INFORMATION);
             
               char stopic[TOPSZ];
            @@ -1402,8 +1405,8 @@ void HandleInformation(void)
             
             void HandleUpgradeFirmware(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_FIRMWARE_UPGRADE);
             
               String page = FPSTR(HTTP_HEAD);
            @@ -1422,8 +1425,8 @@ void HandleUpgradeFirmware(void)
             
             void HandleUpgradeFirmwareStart(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               char svalue[100];
             
               AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPGRADE_STARTED));
            @@ -1451,8 +1454,8 @@ void HandleUpgradeFirmwareStart(void)
             
             void HandleUploadDone(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPLOAD_DONE));
             
               char error[100];
            @@ -1709,8 +1712,8 @@ void HandlePreflightRequest(void)
             
             void HandleHttpCommand(void)
             {
            -  if (HttpUser()) { return; }
            -//  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess(false)) { return; }
            +
               char svalue[INPUT_BUFFER_SIZE];  // Large to serve Backlog
             
               AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_COMMAND));
            @@ -1769,8 +1772,8 @@ void HandleHttpCommand(void)
             
             void HandleConsole(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONSOLE);
             
               String page = FPSTR(HTTP_HEAD);
            @@ -1785,8 +1788,8 @@ void HandleConsole(void)
             
             void HandleAjaxConsoleRefresh(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               char svalue[INPUT_BUFFER_SIZE];  // Large to serve Backlog
               byte cflg = 1;
               byte counter = 0;                // Initial start, should never be 0 again
            diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino
            index 1a3525cbc..1d3c3a4b8 100644
            --- a/sonoff/xdrv_02_mqtt.ino
            +++ b/sonoff/xdrv_02_mqtt.ino
            @@ -863,8 +863,8 @@ const char HTTP_FORM_MQTT[] PROGMEM =
             
             void HandleMqttConfiguration(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT);
             
               if (WebServer->hasArg("save")) {
            diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino
            index 38f6535b2..b36b3efc2 100644
            --- a/sonoff/xdrv_07_domoticz.ino
            +++ b/sonoff/xdrv_07_domoticz.ino
            @@ -448,8 +448,8 @@ const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM =
             
             void HandleDomoticzConfiguration(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_DOMOTICZ);
             
               if (WebServer->hasArg("save")) {
            diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino
            index f950c5ce0..ded49e857 100644
            --- a/sonoff/xdrv_09_timers.ino
            +++ b/sonoff/xdrv_09_timers.ino
            @@ -682,8 +682,8 @@ const char HTTP_FORM_TIMER1[] PROGMEM =
             
             void HandleTimerConfiguration(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TIMER);
             
               if (WebServer->hasArg("save")) {
            diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino
            index 1f9d702dd..8286443d8 100644
            --- a/sonoff/xdrv_11_knx.ino
            +++ b/sonoff/xdrv_11_knx.ino
            @@ -805,8 +805,8 @@ const char HTTP_FORM_KNX_ADD_TABLE_ROW2[] PROGMEM =
             
             void HandleKNXConfiguration(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_KNX);
             
               char tmp[100];
            diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino
            index e57b49c44..f46e69359 100644
            --- a/sonoff/xsns_34_hx711.ino
            +++ b/sonoff/xsns_34_hx711.ino
            @@ -393,8 +393,8 @@ const char HTTP_FORM_HX711[] PROGMEM =
             
             void HandleHxAction(void)
             {
            -  if (HttpUser()) { return; }
            -  if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
            +  if (!HttpCheckPriviledgedAccess()) { return; }
            +
               AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_HX711);
             
               if (WebServer->hasArg("save")) {
            
            From abce4f1a139477c50560b8d0b175ab46dc2a30ff Mon Sep 17 00:00:00 2001
            From: andrethomas 
            Date: Thu, 10 Jan 2019 18:11:49 +0200
            Subject: [PATCH 0839/2222] PN532: Prevent exception for S,
            
            ---
             sonoff/xsns_40_pn532_i2c.ino | 4 ++++
             1 file changed, 4 insertions(+)
            
            diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino
            index b02c68591..2c34d0473 100644
            --- a/sonoff/xsns_40_pn532_i2c.ino
            +++ b/sonoff/xsns_40_pn532_i2c.ino
            @@ -481,6 +481,10 @@ boolean PN532_Command(void)
               }
               if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"S")) {
                 if (paramcount > 1) {
            +      if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') {
            +        serviced = false;
            +        return serviced;
            +      }
                   sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2));
                   uint8_t dlen = strlen(sub_string_tmp);
                   if (dlen > 15) { dlen = 15; }
            
            From 5f1d6aa4de276fd1fa22aa2fd9c20ab10e081082 Mon Sep 17 00:00:00 2001
            From: andrethomas 
            Date: Thu, 10 Jan 2019 18:19:53 +0200
            Subject: [PATCH 0840/2222] PN532: Fix memcpy bugs
            
            ---
             sonoff/xsns_40_pn532_i2c.ino | 6 +++---
             1 file changed, 3 insertions(+), 3 deletions(-)
            
            diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino
            index 2c34d0473..e0985c0d0 100644
            --- a/sonoff/xsns_40_pn532_i2c.ino
            +++ b/sonoff/xsns_40_pn532_i2c.ino
            @@ -393,7 +393,7 @@ void PN532_ScanForTag(void)
                     uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
                     if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) {
                       if (mifareclassic_ReadDataBlock(1, card_data)) {
            -            memcpy(&card_datas,card_data,sizeof(card_data)); // Cast block 0 to a string
            +            memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 0 to a string
                       }
                       if (pn532_i2c_function == 1) { // erase block 1 of card
                         for (uint8_t i = 0;i<16;i++) {
            @@ -403,7 +403,7 @@ void PN532_ScanForTag(void)
                           erase_success = true;
                           snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Erase success");
                           AddLog(LOG_LEVEL_INFO);
            -              memcpy(&card_datas,card_data,sizeof(card_data)); // Cast block 0 to a string
            +              memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 0 to a string
                         }
                       }
                       if (pn532_i2c_function == 2) {
            @@ -412,7 +412,7 @@ void PN532_ScanForTag(void)
                           set_success = true;
                           snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful");
                           AddLog(LOG_LEVEL_INFO);
            -              memcpy(&card_datas,card_data,sizeof(card_data)); // Cast block 0 to a string
            +              memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 0 to a string
                         }
                       }
                     } else {
            
            From 63b01ec67459a58732af12fcdae9e5cfe9dc4dee Mon Sep 17 00:00:00 2001
            From: Andre Thomas 
            Date: Thu, 10 Jan 2019 18:22:38 +0200
            Subject: [PATCH 0841/2222] Update xsns_40_pn532_i2c.ino
            
            ---
             sonoff/xsns_40_pn532_i2c.ino | 6 +++---
             1 file changed, 3 insertions(+), 3 deletions(-)
            
            diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino
            index e0985c0d0..567b19a77 100644
            --- a/sonoff/xsns_40_pn532_i2c.ino
            +++ b/sonoff/xsns_40_pn532_i2c.ino
            @@ -393,7 +393,7 @@ void PN532_ScanForTag(void)
                     uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
                     if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) {
                       if (mifareclassic_ReadDataBlock(1, card_data)) {
            -            memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 0 to a string
            +            memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
                       }
                       if (pn532_i2c_function == 1) { // erase block 1 of card
                         for (uint8_t i = 0;i<16;i++) {
            @@ -403,7 +403,7 @@ void PN532_ScanForTag(void)
                           erase_success = true;
                           snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Erase success");
                           AddLog(LOG_LEVEL_INFO);
            -              memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 0 to a string
            +              memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
                         }
                       }
                       if (pn532_i2c_function == 2) {
            @@ -412,7 +412,7 @@ void PN532_ScanForTag(void)
                           set_success = true;
                           snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful");
                           AddLog(LOG_LEVEL_INFO);
            -              memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 0 to a string
            +              memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
                         }
                       }
                     } else {
            
            From 54763329f86d846b516e5a302018df44fa2d984e Mon Sep 17 00:00:00 2001
            From: netpok 
            Date: Thu, 10 Jan 2019 21:41:36 +0100
            Subject: [PATCH 0842/2222] Fix GPIO16 Pull-down
            
            ---
             sonoff/support_button.ino | 2 +-
             sonoff/support_switch.ino | 2 +-
             2 files changed, 2 insertions(+), 2 deletions(-)
            
            diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino
            index 880f354d1..ed5cecce6 100644
            --- a/sonoff/support_button.ino
            +++ b/sonoff/support_button.ino
            @@ -54,7 +54,7 @@ void ButtonInit(void)
               for (byte i = 0; i < MAX_KEYS; i++) {
                 if (pin[GPIO_KEY1 +i] < 99) {
                   buttons_found++;
            -      pinMode(pin[GPIO_KEY1 +i], (16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : bitRead(key_no_pullup, i) ? INPUT : INPUT_PULLUP);
            +      pinMode(pin[GPIO_KEY1 +i], bitRead(key_no_pullup, i) ? INPUT : ((16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP));
                 }
               }
             }
            diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino
            index 7a085347e..cb685cb81 100644
            --- a/sonoff/support_switch.ino
            +++ b/sonoff/support_switch.ino
            @@ -121,7 +121,7 @@ void SwitchInit(void)
                 lastwallswitch[i] = 1;  // Init global to virtual switch state;
                 if (pin[GPIO_SWT1 +i] < 99) {
                   switches_found++;
            -      pinMode(pin[GPIO_SWT1 +i], (16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 : bitRead(switch_no_pullup, i) ? INPUT : INPUT_PULLUP);
            +      pinMode(pin[GPIO_SWT1 +i], bitRead(switch_no_pullup, i) ? INPUT : ((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
                 }
                 switch_virtual[i] = lastwallswitch[i];
            
            From a12452901511ee0033bacb8bed155de42a0d4aaa Mon Sep 17 00:00:00 2001
            From: Theo Arends <11044339+arendst@users.noreply.github.com>
            Date: Fri, 11 Jan 2019 14:29:54 +0100
            Subject: [PATCH 0843/2222] Add support for Digoo DG-SP202
            
            Add support for Digoo DG-SP202 Smart Socket (#4891)
            ---
             sonoff/_changelog.ino    |  3 ++-
             sonoff/sonoff_template.h | 25 ++++++++++++++++++++++++-
             2 files changed, 26 insertions(+), 2 deletions(-)
            
            diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino
            index 2bb633598..bf5c80438 100644
            --- a/sonoff/_changelog.ino
            +++ b/sonoff/_changelog.ino
            @@ -6,7 +6,8 @@
              * Add support for OBI Power Socket 2 (#4829)
              * Add support for YTF IR Bridge (#4855)
              * Change web authentication (#4865)
            - * 
            + * Add support for Digoo DG-SP202 Smart Socket (#4891)
            + *
              * 6.4.1.7 20190106
              * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6
              * Add Power status functionality to LED2 when configured leaving LED1 for Link status indication
            diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h
            index aaa50b2dc..38fbd5f9b 100644
            --- a/sonoff/sonoff_template.h
            +++ b/sonoff/sonoff_template.h
            @@ -275,6 +275,7 @@ enum SupportedModules {
               MANZOKU_EU_4,
               OBI2,
               YTF_IR_BRIDGE,
            +  DIGOO,
               MAXMODULE };
             
             /********************************************************************************************/
            @@ -544,6 +545,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
               APLIC_WDP303075,
               GOSUND,
               SK03_TUYA,
            +  DIGOO,
               NEO_COOLCAM,        // Socket Relay Devices
               OBI,
               OBI2,
            @@ -1693,6 +1695,27 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_KEY1,        // GPIO13 Button
                  GPIO_IRSEND,      // GPIO14 IR Transmitter
                  0, 0, 0
            +  },
            +  { "Digoo DG-SP202",  // Digoo DG-SP202
            +                       // https://www.banggood.com/DIGOO-DG-SP202-Dual-EU-Plug-Smart-WIFI-Socket-Individual-Controllable-Energy-Monitor-Remote-Control-Timing-Smart-Home-Outlet-let-p-1375323.html
            +     GPIO_KEY1,        // GPIO00 Button1
            +     0,                // GPIO01 Serial RXD
            +     0,                // GPIO02
            +     0,                // GPIO03 Serial TXD
            +     GPIO_HJL_CF,      // GPIO04 BL0937 or HJL-01 CF power
            +     GPIO_NRG_CF1,     // GPIO05 BL0937 or HJL-01 CF1 current / voltage
            +                       // GPIO06 (SD_CLK   Flash)
            +                       // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT)
            +                       // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT)
            +     0,                // GPIO09 (SD_DATA2 Flash QIO or ESP8285)
            +     0,                // GPIO10 (SD_DATA3 Flash QIO or ESP8285)
            +                       // GPIO11 (SD_CMD   Flash)
            +     GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage)
            +     GPIO_LED1,        // GPIO13 Blue Leds - Link Status
            +     GPIO_REL2,        // GPIO14 Relay2 (0 = Off, 1 = On) and Red Led
            +     GPIO_REL1,        // GPIO15 Relay1 (0 = Off, 1 = On) and Red Led
            +     GPIO_KEY2_NP,     // GPIO16 Button2, externally pulled up
            +     0
               }
             };
             
            @@ -1723,7 +1746,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                                    // https://www.amazon.com/dp/B072MKV8ZM
                  GPIO_KEY1,        // GPIO00 PROG Button
                  GPIO_USER,        // GPIO01 Serial RXD or Optional sensor on J2 RXD (if not using serial io)
            -     0,                // GPIO02 
            +     0,                // GPIO02
                  GPIO_USER,        // GPIO03 Serial TXD or Optional sensor on J2 TXD (if not using serial io)
                  GPIO_REL2_INV,    // GPIO04 Relay 2 (active low)
                  GPIO_REL1_INV,    // GPIO05 Relay 1 (active low)
            
            From 72bc9b81078ef384f751a64e8d62db30c40b5f58 Mon Sep 17 00:00:00 2001
            From: Theo Arends <11044339+arendst@users.noreply.github.com>
            Date: Sat, 12 Jan 2019 15:16:37 +0100
            Subject: [PATCH 0844/2222] Add support for Smanergy KA10
            
            Add support for Smanergy KA10 Smart Wall Socket with Energy monitoring
            ---
             sonoff/_changelog.ino    |  3 ++-
             sonoff/sonoff_template.h | 33 +++++++++++++++++----------------
             2 files changed, 19 insertions(+), 17 deletions(-)
            
            diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino
            index bf5c80438..8c65c845b 100644
            --- a/sonoff/_changelog.ino
            +++ b/sonoff/_changelog.ino
            @@ -6,7 +6,8 @@
              * Add support for OBI Power Socket 2 (#4829)
              * Add support for YTF IR Bridge (#4855)
              * Change web authentication (#4865)
            - * Add support for Digoo DG-SP202 Smart Socket (#4891)
            + * Add support for Digoo DG-SP202 Smart Socket with Energy monitoring (#4891)
            + * Add support for Smanergy KA10 Smart Wall Socket with Energy monitoring
              *
              * 6.4.1.7 20190106
              * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6
            diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h
            index 38fbd5f9b..e15fb9a99 100644
            --- a/sonoff/sonoff_template.h
            +++ b/sonoff/sonoff_template.h
            @@ -276,6 +276,7 @@ enum SupportedModules {
               OBI2,
               YTF_IR_BRIDGE,
               DIGOO,
            +  KA10,
               MAXMODULE };
             
             /********************************************************************************************/
            @@ -497,9 +498,9 @@ const uint8_t kGpioNiceList[] PROGMEM = {
               GPIO_AZ_RXD,         // AZ-Instrument 7798 CO2 datalogger Serial interface
             #endif
             #ifdef USE_MAX31855
            -  GPIO_MAX31855CS,   // MAX31855 Serial interface
            -  GPIO_MAX31855CLK,  // MAX31855 Serial interface
            -  GPIO_MAX31855DO,   // MAX31855 Serial interface
            +  GPIO_MAX31855CS,     // MAX31855 Serial interface
            +  GPIO_MAX31855CLK,    // MAX31855 Serial interface
            +  GPIO_MAX31855DO,     // MAX31855 Serial interface
             #endif
             };
             
            @@ -539,22 +540,23 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
               WION,
               SHELLY1,
               SHELLY2,
            -  BLITZWOLF_BWSHP,    // Socket Relay Devices with Energy Monitoring
            +  BLITZWOLF_BWSHP,     // Socket Relay Devices with Energy Monitoring
               TECKIN,
               TECKIN_US,
               APLIC_WDP303075,
               GOSUND,
               SK03_TUYA,
               DIGOO,
            -  NEO_COOLCAM,        // Socket Relay Devices
            +  KA10,
            +  NEO_COOLCAM,         // Socket Relay Devices
               OBI,
               OBI2,
               MANZOKU_EU_4,
            -  ESP_SWITCH,         // Switch Devices
            -  TUYA_DIMMER,        // Dimmer Devices
            +  ESP_SWITCH,          // Switch Devices
            +  TUYA_DIMMER,         // Dimmer Devices
               ARMTRONIX_DIMMERS,
               PS_16_DZ,
            -  H801,               // Light Devices
            +  H801,                // Light Devices
               MAGICHOME,
               ARILUX_LC01,
               ARILUX_LC06,
            @@ -562,10 +564,10 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
               ZENGGE_ZF_WF017,
               HUAFAN_SS,
               KMC_70011,
            -  AILIGHT,            // Light Bulbs
            +  AILIGHT,             // Light Bulbs
               PHILIPS,
               YTF_IR_BRIDGE,
            -  WITTY,              // Development Devices
            +  WITTY,               // Development Devices
               WEMOS
             };
             
            @@ -1716,12 +1718,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_REL1,        // GPIO15 Relay1 (0 = Off, 1 = On) and Red Led
                  GPIO_KEY2_NP,     // GPIO16 Button2, externally pulled up
                  0
            -  }
            -};
            -
            -/*
            -  Optionals
            -
            +  },
               { "KA10",            // SMANERGY KA10 (ESP8285 - BL0937 Energy Monitoring) - https://www.amazon.es/dp/B07MBTCH2Y
                  0,                // GPIO00
                  GPIO_LED1_INV,    // GPIO01 Blue LED - Link status
            @@ -1740,6 +1737,10 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
                  GPIO_REL1,        // GPIO14 Relay 1
                  0, 0, 0
               }
            +};
            +
            +/*
            +  Optionals
             
               { "N0DY Relay",      // N0DY Wifi Dual Relay (ESP-07)
                                    // https://www.n0dy.com/product/web-controlled-dual-relay/
            
            From 5b7ba95b0c7d1844f5af87ad9bbf7db50d44a619 Mon Sep 17 00:00:00 2001
            From: Louis Lagendijk 
            Date: Sat, 12 Jan 2019 22:09:50 +0100
            Subject: [PATCH 0845/2222] Added Max44009 support
            
            ---
             sonoff/i18n.h               |   1 +
             sonoff/xsns_91_max44009.ino | 166 ++++++++++++++++++++++++++++++++++++
             2 files changed, 167 insertions(+)
             create mode 100644 sonoff/xsns_91_max44009.ino
            
            diff --git a/sonoff/i18n.h b/sonoff/i18n.h
            index a90028e8d..4469ae006 100644
            --- a/sonoff/i18n.h
            +++ b/sonoff/i18n.h
            @@ -549,6 +549,7 @@ const char HTTP_SNS_PRESSURE[] PROGMEM = "%s{s}%s " D_PRESSURE "{m}%s %s{e}";
             const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}";                   // {s} = 
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
"); - for (byte i = 0; i < sizeof(cmodule); i++) { + for (uint8_t i = 0; i < sizeof(cmodule); i++) { if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), @@ -873,7 +873,7 @@ void ModuleSaveSettings(void) char stemp[TOPSZ]; WebGetArg("g99", tmp, sizeof(tmp)); - byte new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); + uint8_t new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); Settings.last_module = Settings.module; Settings.module = new_module; if (Settings.last_module == new_module) { @@ -884,7 +884,7 @@ void ModuleSaveSettings(void) myio cmodule; ModuleGpios(&cmodule); String gpios = ""; - for (byte i = 0; i < sizeof(cmodule); i++) { + for (uint8_t i = 0; i < sizeof(cmodule); i++) { if (Settings.last_module != new_module) { Settings.my_gp.io[i] = 0; } else { @@ -1057,14 +1057,14 @@ void HandleLoggingConfiguration(void) page += FPSTR(HTTP_HEAD_STYLE); page += FPSTR(HTTP_FORM_LOG1); - for (byte idx = 0; idx < 3; idx++) { + for (uint8_t idx = 0; idx < 3; idx++) { page += FPSTR(HTTP_FORM_LOG2); switch (idx) { case 0: page.replace(F("{b0"), F(D_SERIAL_LOG_LEVEL)); page.replace(F("{b1"), STR(SERIAL_LOG_LEVEL)); page.replace(F("{b2"), F("ls")); - for (byte i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { + for (uint8_t i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { page.replace("{a" + String(i), (i == Settings.seriallog_level) ? F(" selected ") : F(" ")); } break; @@ -1072,7 +1072,7 @@ void HandleLoggingConfiguration(void) page.replace(F("{b0"), F(D_WEB_LOG_LEVEL)); page.replace(F("{b1"), STR(WEB_LOG_LEVEL)); page.replace(F("{b2"), F("lw")); - for (byte i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { + for (uint8_t i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { page.replace("{a" + String(i), (i == Settings.weblog_level) ? F(" selected ") : F(" ")); } break; @@ -1080,7 +1080,7 @@ void HandleLoggingConfiguration(void) page.replace(F("{b0"), F(D_SYS_LOG_LEVEL)); page.replace(F("{b1"), STR(SYS_LOG_LEVEL)); page.replace(F("{b2"), F("ll")); - for (byte i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { + for (uint8_t i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { page.replace("{a" + String(i), (i == Settings.syslog_level) ? F(" selected ") : F(" ")); } break; @@ -1145,7 +1145,7 @@ void HandleOtherConfiguration(void) uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; if (SONOFF_IFAN02 == Settings.module) { maxfn = 1; } - for (byte i = 0; i < maxfn; i++) { + for (uint8_t i = 0; i < maxfn; i++) { page += FPSTR(HTTP_FORM_OTHER2); page.replace(F("{1"), String(i +1)); snprintf_P(stemp, sizeof(stemp), PSTR(FRIENDLY_NAME"%d"), i +1); @@ -1154,7 +1154,7 @@ void HandleOtherConfiguration(void) } #ifdef USE_EMULATION page += FPSTR(HTTP_FORM_OTHER3a); - for (byte i = 0; i < EMUL_MAX; i++) { + for (uint8_t i = 0; i < EMUL_MAX; i++) { page += FPSTR(HTTP_FORM_OTHER3b); page.replace(F("{1"), String(i)); page.replace(F("{2"), (i == Settings.flag2.emulation) ? F(" checked") : F("")); @@ -1183,7 +1183,7 @@ void OtherSaveSettings(void) Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); #endif // USE_EMULATION snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); - for (byte i = 0; i < MAX_FRIENDLYNAMES; i++) { + for (uint8_t i = 0; i < MAX_FRIENDLYNAMES; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("a%d"), i +1); WebGetArg(stemp, tmp, sizeof(tmp)); snprintf_P(stemp2, sizeof(stemp2), PSTR(FRIENDLY_NAME"%d"), i +1); @@ -1313,7 +1313,7 @@ void HandleInformation(void) func += F("}1" D_RESTART_REASON "}2"); func += GetResetReason(); uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present; if (SONOFF_IFAN02 == Settings.module) { maxfn = 1; } - for (byte i = 0; i < maxfn; i++) { + for (uint8_t i = 0; i < maxfn; i++) { func += F("}1" D_FRIENDLY_NAME " "); func += i +1; func += F("}2"); func += Settings.friendlyname[i]; } @@ -1509,7 +1509,7 @@ void HandleUploadDone(void) void HandleUploadLoop(void) { // Based on ESP8266HTTPUpdateServer.cpp uses ESP8266WebServer Parsing.cpp and Cores Updater.cpp (Update) - boolean _serialoutput = (LOG_LEVEL_DEBUG <= seriallog_level); + bool _serialoutput = (LOG_LEVEL_DEBUG <= seriallog_level); if (HTTP_USER == webserver_state) { return; } if (upload_error) { @@ -1729,13 +1729,13 @@ void HandleHttpCommand(void) String message = F("{\"" D_RSLT_WARNING "\":\""); if (valid) { - byte curridx = web_log_index; + uint8_t curridx = web_log_index; WebGetArg("cmnd", svalue, sizeof(svalue)); if (strlen(svalue)) { ExecuteWebCommand(svalue, SRC_WEBCOMMAND); if (web_log_index != curridx) { - byte counter = curridx; + uint8_t counter = curridx; message = F("{"); do { char* tmp; @@ -1791,8 +1791,8 @@ void HandleAjaxConsoleRefresh(void) if (!HttpCheckPriviledgedAccess()) { return; } char svalue[INPUT_BUFFER_SIZE]; // Large to serve Backlog - byte cflg = 1; - byte counter = 0; // Initial start, should never be 0 again + bool cflg = true; + uint8_t counter = 0; // Initial start, should never be 0 again WebGetArg("c1", svalue, sizeof(svalue)); if (strlen(svalue)) { @@ -1804,16 +1804,16 @@ void HandleAjaxConsoleRefresh(void) WebGetArg("c2", svalue, sizeof(svalue)); if (strlen(svalue)) { counter = atoi(svalue); } - byte last_reset_web_log_flag = reset_web_log_flag; + bool last_reset_web_log_flag = reset_web_log_flag; String message = F("}9"); // Cannot load mqtt_data here as <> will be encoded by replacements below if (!reset_web_log_flag) { counter = 0; - reset_web_log_flag = 1; + reset_web_log_flag = true; } if (counter != web_log_index) { if (!counter) { counter = web_log_index; - cflg = 0; + cflg = false; } do { char* tmp; @@ -1823,7 +1823,7 @@ void HandleAjaxConsoleRefresh(void) if (cflg) { message += F("\n"); } else { - cflg = 1; + cflg = true; } strlcpy(mqtt_data, tmp, len); message += mqtt_data; @@ -1870,7 +1870,7 @@ void HandleNotFound(void) } /* 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(void) +bool CaptivePortal(void) { if ((HTTP_MANAGER == webserver_state) && !ValidIpAddress(WebServer->hostHeader())) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); @@ -1884,7 +1884,7 @@ boolean CaptivePortal(void) } /** Is this an IP? */ -boolean ValidIpAddress(String str) +bool ValidIpAddress(String str) { for (uint16_t i = 0; i < str.length(); i++) { int c = str.charAt(i); @@ -1984,7 +1984,7 @@ int WebSend(char *buffer) WiFiClient client; bool connected = false; - byte retry = 2; + uint8_t retry = 2; while ((retry > 0) && !connected) { --retry; connected = client.connect(host_ip, nport); @@ -2085,9 +2085,9 @@ bool WebCommand(void) * Interface \*********************************************************************************************/ -boolean Xdrv01(byte function) +bool Xdrv01(uint8_t function) { - boolean result = false; + bool result = false; switch (function) { case FUNC_LOOP: diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index b6ceec2f6..df06da5d2 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -84,7 +84,7 @@ bool mqtt_allowed = false; // MQTT enabled and parameters valid * bool MqttIsConnected() * void MqttDisconnect() * void MqttSubscribeLib(char *topic) - * bool MqttPublishLib(const char* topic, boolean retained) + * bool MqttPublishLib(const char* topic, bool retained) * void MqttLoop() \*********************************************************************************************/ @@ -115,7 +115,7 @@ void MqttSubscribeLib(char *topic) MqttClient.loop(); // Solve LmacRxBlk:1 messages } -bool MqttPublishLib(const char* topic, boolean retained) +bool MqttPublishLib(const char* topic, bool retained) { bool result = MqttClient.publish(topic, mqtt_data, retained); yield(); // #3313 @@ -152,7 +152,7 @@ void MqttSubscribeLib(char *topic) MqttClient.Subscribe(topic, 0); } -bool MqttPublishLib(const char* topic, boolean retained) +bool MqttPublishLib(const char* topic, bool retained) { return MqttClient.Publish(topic, mqtt_data, strlen(mqtt_data), 0, retained); } @@ -180,13 +180,13 @@ void MqttDisconnect(void) void MqttMyDataCb(MQTTClient* client, char* topic, char* data, int data_len) //void MqttMyDataCb(MQTTClient *client, char topic[], char data[], int data_len) { -// MqttDataHandler((char*)topic, (byte*)data, data_len); +// MqttDataHandler((char*)topic, (uint8_t*)data, data_len); } */ void MqttMyDataCb(String &topic, String &data) { - MqttDataHandler((char*)topic.c_str(), (byte*)data.c_str(), data.length()); + MqttDataHandler((char*)topic.c_str(), (uint8_t*)data.c_str(), data.length()); } void MqttSubscribeLib(char *topic) @@ -194,7 +194,7 @@ void MqttSubscribeLib(char *topic) MqttClient.subscribe(topic, 0); } -bool MqttPublishLib(const char* topic, boolean retained) +bool MqttPublishLib(const char* topic, bool retained) { return MqttClient.publish(topic, mqtt_data, strlen(mqtt_data), retained, 0); } @@ -257,7 +257,7 @@ void MqttSubscribe(char *topic) MqttSubscribeLib(topic); } -void MqttPublishDirect(const char* topic, boolean retained) +void MqttPublishDirect(const char* topic, bool retained) { char sretained[CMDSZ]; char slog_type[10]; @@ -291,7 +291,7 @@ void MqttPublishDirect(const char* topic, boolean retained) } } -void MqttPublish(const char* topic, boolean retained) +void MqttPublish(const char* topic, bool retained) { char *me; @@ -309,7 +309,7 @@ void MqttPublish(const char* topic) MqttPublish(topic, false); } -void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic, boolean retained) +void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic, bool retained) { /* prefix 0 = cmnd using subtopic * prefix 1 = stat using subtopic @@ -322,7 +322,7 @@ void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic, boolean reta char stopic[TOPSZ]; snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings.flag.mqtt_response) ? S_RSLT_RESULT : subtopic); - for (byte i = 0; i < strlen(romram); i++) { + for (uint8_t i = 0; i < strlen(romram); i++) { romram[i] = toupper(romram[i]); } prefix &= 3; @@ -335,7 +335,7 @@ void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic) MqttPublishPrefixTopic_P(prefix, subtopic, false); } -void MqttPublishPowerState(byte device) +void MqttPublishPowerState(uint8_t device) { char stopic[TOPSZ]; char scommand[33]; @@ -364,7 +364,7 @@ void MqttPublishPowerState(byte device) } } -void MqttPublishPowerBlinkState(byte device) +void MqttPublishPowerBlinkState(uint8_t device) { char scommand[33]; @@ -433,7 +433,7 @@ void MqttConnected(void) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), (GetResetReason() == "Exception") ? ESP.getResetInfo().c_str() : GetResetReason().c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); - for (byte i = 1; i <= devices_present; i++) { + for (uint8_t i = 1; i <= devices_present; i++) { MqttPublishPowerState(i); if (SONOFF_IFAN02 == Settings.module) { break; } // Report status of light relay only } @@ -450,15 +450,15 @@ void MqttConnected(void) } #ifdef USE_MQTT_TLS -boolean MqttCheckTls(void) +bool MqttCheckTls(void) { char fingerprint1[60]; char fingerprint2[60]; - boolean result = false; + bool result = false; fingerprint1[0] = '\0'; fingerprint2[0] = '\0'; - for (byte i = 0; i < sizeof(Settings.mqtt_fingerprint[0]); i++) { + for (uint8_t i = 0; i < sizeof(Settings.mqtt_fingerprint[0]); i++) { snprintf_P(fingerprint1, sizeof(fingerprint1), PSTR("%s%s%02X"), fingerprint1, (i) ? " " : "", Settings.mqtt_fingerprint[0][i]); snprintf_P(fingerprint2, sizeof(fingerprint2), PSTR("%s%s%02X"), fingerprint2, (i) ? " " : "", Settings.mqtt_fingerprint[1][i]); } @@ -638,7 +638,7 @@ bool MqttCommand(void) uint16_t data_len = XdrvMailbox.data_len; uint16_t payload16 = XdrvMailbox.payload16; int16_t payload = XdrvMailbox.payload; - uint8_t grpflg = XdrvMailbox.grpflg; + bool grpflg = XdrvMailbox.grpflg; char *type = XdrvMailbox.topic; char *dataBuf = XdrvMailbox.data; @@ -682,13 +682,13 @@ bool MqttCommand(void) if ((data_len > 0) && (data_len < sizeof(fingerprint))) { strlcpy(fingerprint, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? (1 == index) ? MQTT_FINGERPRINT1 : MQTT_FINGERPRINT2 : dataBuf, sizeof(fingerprint)); char *p = fingerprint; - for (byte i = 0; i < 20; i++) { + for (uint8_t i = 0; i < 20; i++) { Settings.mqtt_fingerprint[index -1][i] = strtol(p, &p, 16); } restart_flag = 2; } fingerprint[0] = '\0'; - for (byte i = 0; i < sizeof(Settings.mqtt_fingerprint[index -1]); i++) { + for (uint8_t i = 0; i < sizeof(Settings.mqtt_fingerprint[index -1]); i++) { snprintf_P(fingerprint, sizeof(fingerprint), PSTR("%s%s%02X"), fingerprint, (i) ? " " : "", Settings.mqtt_fingerprint[index -1][i]); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, fingerprint); @@ -949,9 +949,9 @@ void MqttSaveSettings(void) * Interface \*********************************************************************************************/ -boolean Xdrv02(byte function) +bool Xdrv02(uint8_t function) { - boolean result = false; + bool result = false; if (Settings.flag.mqtt_enabled) { switch (function) { diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 773f50bc0..4662fec3d 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -72,24 +72,23 @@ uint8_t energy_power_delta = 0; bool energy_type_dc = false; bool energy_power_on = true; +bool energy_min_power_flag = false; +bool energy_max_power_flag = false; +bool energy_min_voltage_flag = false; +bool energy_max_voltage_flag = false; +bool energy_min_current_flag = false; +bool energy_max_current_flag = false; -byte energy_min_power_flag = 0; -byte energy_max_power_flag = 0; -byte energy_min_voltage_flag = 0; -byte energy_max_voltage_flag = 0; -byte energy_min_current_flag = 0; -byte energy_max_current_flag = 0; - -byte energy_power_steady_cntr = 8; // Allow for power on stabilization -byte energy_max_energy_state = 0; +uint8_t energy_power_steady_cntr = 8; // Allow for power on stabilization +uint8_t energy_max_energy_state = 0; #if FEATURE_POWER_LIMIT -byte energy_mplr_counter = 0; +uint8_t energy_mplr_counter = 0; uint16_t energy_mplh_counter = 0; uint16_t energy_mplw_counter = 0; #endif // FEATURE_POWER_LIMIT -byte energy_fifth_second = 0; +uint8_t energy_fifth_second = 0; Ticker ticker_energy; int energy_command_code = 0; @@ -147,9 +146,9 @@ void EnergySaveState(void) Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; } -boolean EnergyMargin(byte type, uint16_t margin, uint16_t value, byte &flag, byte &save_flag) +bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag) { - byte change; + bool change; if (!margin) return false; change = save_flag; @@ -173,8 +172,8 @@ void EnergyMarginCheck(void) uint16_t energy_power_u = 0; uint16_t energy_voltage_u = 0; uint16_t energy_current_u = 0; - boolean flag; - boolean jsonflg; + bool flag; + bool jsonflg; if (energy_power_steady_cntr) { energy_power_steady_cntr--; @@ -204,30 +203,30 @@ void EnergyMarginCheck(void) // AddLog(LOG_LEVEL_DEBUG); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); - jsonflg = 0; - if (EnergyMargin(0, Settings.energy_min_power, energy_power_u, flag, energy_min_power_flag)) { + jsonflg = false; + if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, energy_min_power_flag)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_POWERLOW "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); - jsonflg = 1; + jsonflg = true; } - if (EnergyMargin(1, Settings.energy_max_power, energy_power_u, flag, energy_max_power_flag)) { + if (EnergyMargin(true, Settings.energy_max_power, energy_power_u, flag, energy_max_power_flag)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_POWERHIGH "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); - jsonflg = 1; + jsonflg = true; } - if (EnergyMargin(0, Settings.energy_min_voltage, energy_voltage_u, flag, energy_min_voltage_flag)) { + if (EnergyMargin(false, Settings.energy_min_voltage, energy_voltage_u, flag, energy_min_voltage_flag)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); - jsonflg = 1; + jsonflg = true; } - if (EnergyMargin(1, Settings.energy_max_voltage, energy_voltage_u, flag, energy_max_voltage_flag)) { + if (EnergyMargin(true, Settings.energy_max_voltage, energy_voltage_u, flag, energy_max_voltage_flag)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); - jsonflg = 1; + jsonflg = true; } - if (EnergyMargin(0, Settings.energy_min_current, energy_current_u, flag, energy_min_current_flag)) { + if (EnergyMargin(false, Settings.energy_min_current, energy_current_u, flag, energy_min_current_flag)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_CURRENTLOW "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); - jsonflg = 1; + jsonflg = true; } - if (EnergyMargin(1, Settings.energy_max_current, energy_current_u, flag, energy_max_current_flag)) { + if (EnergyMargin(true, Settings.energy_max_current, energy_current_u, flag, energy_max_current_flag)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); - jsonflg = 1; + jsonflg = true; } if (jsonflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); @@ -310,7 +309,7 @@ void EnergyMqttShow(void) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); int tele_period_save = tele_period; tele_period = 2; - EnergyShow(1); + EnergyShow(true); tele_period = tele_period_save; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); @@ -321,12 +320,12 @@ void EnergyMqttShow(void) * Commands \*********************************************************************************************/ -boolean EnergyCommand(void) +bool EnergyCommand(void) { char command [CMDSZ]; char sunit[CMDSZ]; - boolean serviced = true; - uint8_t status_flag = 0; + bool serviced = true; + bool status_flag = false; uint8_t unit = 0; unsigned long nvalue = 0; @@ -417,7 +416,7 @@ boolean EnergyCommand(void) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s}}"), command, energy_total_chr, energy_yesterday_chr, energy_daily_chr); - status_flag = 1; + status_flag = true; } else if ((CMND_POWERCAL == command_code) && XnrgCall(FUNC_COMMAND)) { // microseconds if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { Settings.energy_power_calibration = XdrvMailbox.payload; } @@ -568,7 +567,7 @@ const char HTTP_ENERGY_SNS4[] PROGMEM = "%s" "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; // {s} = #endif // USE_WEBSERVER -void EnergyShow(boolean json) +void EnergyShow(bool json) { char speriod[20]; char sfrequency[20]; @@ -681,9 +680,9 @@ void EnergyShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xdrv03(byte function) +bool Xdrv03(uint8_t function) { - boolean result = false; + bool result = false; if (FUNC_PRE_INIT == function) { EnergyDrvInit(); @@ -704,9 +703,9 @@ boolean Xdrv03(byte function) return result; } -boolean Xsns03(byte function) +bool Xsns03(uint8_t function) { - boolean result = false; + bool result = false; if (energy_flg) { switch (function) { @@ -717,11 +716,11 @@ boolean Xsns03(byte function) EnergyMarginCheck(); break; case FUNC_JSON_APPEND: - EnergyShow(1); + EnergyShow(true); break; #ifdef USE_WEBSERVER case FUNC_WEB_APPEND: - EnergyShow(0); + EnergyShow(false); break; #endif // USE_WEBSERVER case FUNC_SAVE_BEFORE_RESTART: diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 4a1d19478..9d8740ccb 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -367,7 +367,7 @@ void LightInit(void) Settings.light_color[0] = 255; // One channel only supports Dimmer but needs max color } if (light_type < LT_PWM6) { // PWM - for (byte i = 0; i < light_type; i++) { + for (uint8_t i = 0; i < light_type; i++) { Settings.pwm_value[i] = 0; // Disable direct PWM control if (pin[GPIO_PWM1 +i] < 99) { pinMode(pin[GPIO_PWM1 +i], OUTPUT); @@ -487,7 +487,7 @@ void LightSetDimmer(uint8_t myDimmer) Settings.light_color[0] = 255; // One PWM channel only supports Dimmer but needs max color } float dimmer = 100 / (float)myDimmer; - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t i = 0; i < light_subtype; i++) { if (Settings.flag.light_signal) { temp = (float)light_signal_color[i] / dimmer; } else { @@ -501,7 +501,7 @@ void LightSetColor(void) { uint8_t highest = 0; - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t i = 0; i < light_subtype; i++) { if (highest < light_current_color[i]) { highest = light_current_color[i]; } @@ -509,7 +509,7 @@ void LightSetColor(void) float mDim = (float)highest / 2.55; Settings.light_dimmer = (uint8_t)mDim; float dimmer = 100 / mDim; - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t i = 0; i < light_subtype; i++) { float temp = (float)light_current_color[i] * dimmer; Settings.light_color[i] = (uint8_t)temp; } @@ -547,7 +547,7 @@ char* LightGetColor(uint8_t type, char* scolor) { LightSetDimmer(Settings.light_dimmer); scolor[0] = '\0'; - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t 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 { @@ -590,7 +590,7 @@ void LightState(uint8_t append) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), mqtt_data, h,s,b); // Add status for each channel snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_CHANNEL "\":[" ), mqtt_data); - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t i = 0; i < light_subtype; i++) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d" ), mqtt_data, (i > 0 ? "," : ""), light_current_color[i] * 100 / 255); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]" ), mqtt_data); @@ -637,7 +637,7 @@ void LightPreparePower(void) void LightFade(void) { if (0 == Settings.light_fade) { - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t i = 0; i < light_subtype; i++) { light_new_color[i] = light_current_color[i]; } } else { @@ -646,7 +646,7 @@ void LightFade(void) shift = (strip_timer_counter % (Settings.light_speed -6)) ? 0 : 8; } if (shift) { - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t 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; @@ -681,7 +681,7 @@ void LightWheel(uint8_t wheel_pos) 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++) { + for (uint8_t i = 0; i < LST_RGB; i++) { float temp = (float)light_entry_color[i] / dimmer; light_entry_color[i] = (uint8_t)temp; } @@ -700,7 +700,7 @@ void LightCycleColor(int8_t direction) void LightRandomColor(void) { uint8_t light_update = 0; - for (byte i = 0; i < LST_RGB; i++) { + for (uint8_t i = 0; i < LST_RGB; i++) { if (light_new_color[i] != light_current_color[i]) { light_update = 1; } @@ -736,7 +736,7 @@ void LightAnimate(void) if (!light_power) { // Power Off sleep = Settings.sleep; strip_timer_counter = 0; - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t 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)) { @@ -744,13 +744,13 @@ void LightAnimate(void) if (speed > 6) { speed = 6; } - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t 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++) { + for (uint8_t i = 0; i < light_subtype; i++) { light_new_color[i] = 0; } } @@ -765,7 +765,7 @@ void LightAnimate(void) case LS_WAKEUP: if (2 == light_wakeup_active) { light_wakeup_active = 1; - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t i = 0; i < light_subtype; i++) { light_new_color[i] = 0; } light_wakeup_counter = 0; @@ -777,7 +777,7 @@ void LightAnimate(void) light_wakeup_dimmer++; if (light_wakeup_dimmer <= Settings.light_dimmer) { LightSetDimmer(light_wakeup_dimmer); - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t i = 0; i < light_subtype; i++) { light_new_color[i] = light_current_color[i]; } } else { @@ -807,14 +807,14 @@ void LightAnimate(void) } if ((Settings.light_scheme < LS_MAX) || !light_power) { - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t i = 0; i < light_subtype; i++) { if (light_last_color[i] != light_new_color[i]) { light_update = 1; } } if (light_update) { light_update = 0; - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t i = 0; i < light_subtype; i++) { light_last_color[i] = light_new_color[i]; cur_col[i] = light_last_color[i]*Settings.rgbwwTable[i]/255; cur_col[i] = (Settings.light_correction) ? ledTable[cur_col[i]] : cur_col[i]; @@ -1012,7 +1012,7 @@ void LightSetHsb(float hue, float sat, float bri, uint16_t ct, bool gotct) * Commands \*********************************************************************************************/ -boolean LightColorEntry(char *buffer, uint8_t buffer_length) +bool LightColorEntry(char *buffer, uint8_t buffer_length) { char scolor[10]; char *p; @@ -1048,7 +1048,7 @@ boolean LightColorEntry(char *buffer, uint8_t buffer_length) entry_type = 2; // Decimal } else if (((2 * light_subtype) == buffer_length) || (buffer_length > 3)) { // Hexadecimal entry - for (byte i = 0; i < buffer_length / 2; i++) { + for (uint8_t i = 0; i < buffer_length / 2; i++) { strlcpy(scolor, buffer + (i *2), 3); light_entry_color[i] = (uint8_t)strtol(scolor, &p, 16); } @@ -1081,12 +1081,12 @@ boolean LightColorEntry(char *buffer, uint8_t buffer_length) /********************************************************************************************/ -boolean LightCommand(void) +bool LightCommand(void) { char command [CMDSZ]; - boolean serviced = true; - boolean coldim = false; - boolean valid_entry = false; + bool serviced = true; + bool coldim = false; + bool valid_entry = false; char scolor[25]; char option = (1 == XdrvMailbox.data_len) ? XdrvMailbox.data[0] : '\0'; @@ -1118,7 +1118,7 @@ boolean LightCommand(void) Settings.light_scheme = 0; coldim = true; } else { // Color3, 4, 5 and 6 - for (byte i = 0; i < LST_RGB; i++) { + for (uint8_t i = 0; i < LST_RGB; i++) { Settings.ws_color[XdrvMailbox.index -3][i] = light_entry_color[i]; } } @@ -1129,7 +1129,7 @@ boolean LightCommand(void) } if (XdrvMailbox.index >= 3) { scolor[0] = '\0'; - for (byte i = 0; i < LST_RGB; i++) { + for (uint8_t 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[XdrvMailbox.index -3][i]); } else { @@ -1343,7 +1343,7 @@ boolean LightCommand(void) light_update = 1; } scolor[0] = '\0'; - for (byte i = 0; i < LST_RGBWC; i++) { + for (uint8_t i = 0; i < LST_RGBWC; i++) { snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor); @@ -1402,9 +1402,9 @@ boolean LightCommand(void) * Interface \*********************************************************************************************/ -boolean Xdrv04(byte function) +bool Xdrv04(uint8_t function) { - boolean result = false; + bool result = false; if (light_type) { switch (function) { diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 16dda3010..9265671df 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -181,10 +181,10 @@ void IrReceiveCheck(void) TOSHIBA ********************/ -boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) +bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) { uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; - byte data[HVAC_TOSHIBA_DATALEN] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}; + uint8_t data[HVAC_TOSHIBA_DATALEN] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}; char *p; uint8_t mode; @@ -201,7 +201,7 @@ boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H 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] = (uint8_t)0x07; // Turn OFF HVAC } if (HVAC_FanMode == NULL) { @@ -220,7 +220,7 @@ boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H mode = mode << 5; // AUTO = 0x00, SPEED = 0x40, 0x60, 0x80, 0xA0, 0xC0, SILENT = 0x00 data[6] = data[6] | mode; - byte Temp; + uint8_t Temp; if (HVAC_Temp > 30) { Temp = 30; } @@ -230,15 +230,15 @@ boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H else { Temp = HVAC_Temp; } - data[5] = (byte)(Temp - 17) << 4; + data[5] = (uint8_t)(Temp - 17) << 4; 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] = (uint8_t)data[x] ^ data[HVAC_TOSHIBA_DATALEN - 1]; // CRC is a simple bits addition } int i = 0; - byte mask = 1; + uint8_t mask = 1; //header rawdata[i++] = HVAC_TOSHIBA_HDR_MARK; @@ -275,7 +275,7 @@ boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H MITSUBISHI ********************/ -boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) +bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) { char *p; uint8_t mode; @@ -324,14 +324,14 @@ boolean IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, boolea LG ********************/ -boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) +bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) { uint32_t LG_Code; - byte data[HVAC_LG_DATALEN]; - static boolean hvacOn = false; + uint8_t data[HVAC_LG_DATALEN]; + static bool hvacOn = false; char *p; uint8_t mode; - byte Temp; + uint8_t Temp; // Constant data data[0] = 0x08; @@ -339,11 +339,11 @@ boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_P data[2] = 0x00; if (!HVAC_Power) { - data[2] = (byte)0x0C; // Turn OFF HVAC, code 0x88C0051 - data[3] = (byte)0x00; - data[4] = (byte)0x00; - data[5] = (byte)0x05; - data[6] = (byte)0x01; + data[2] = (uint8_t)0x0C; // Turn OFF HVAC, code 0x88C0051 + data[3] = (uint8_t)0x00; + data[4] = (uint8_t)0x00; + data[5] = (uint8_t)0x05; + data[6] = (uint8_t)0x01; hvacOn = false; } @@ -392,7 +392,7 @@ boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_P else { Temp = HVAC_Temp; } - data[4] = (byte)(Temp - 15); + data[4] = (uint8_t)(Temp - 15); // Set code for HVAC fan mode - data[5] if (HVAC_FanMode == NULL) { @@ -442,7 +442,7 @@ boolean IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_P Fujitsu ********************/ -boolean IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) +bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) { const char kFujitsuHvacModeOptions[] = "HDCAF"; @@ -457,8 +457,8 @@ boolean IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H return false; } - byte modes[5] = {FUJITSU_AC_MODE_HEAT, FUJITSU_AC_MODE_DRY, FUJITSU_AC_MODE_COOL, FUJITSU_AC_MODE_AUTO, FUJITSU_AC_MODE_FAN}; - byte fanModes[7] = {FUJITSU_AC_FAN_AUTO, FUJITSU_AC_FAN_LOW, FUJITSU_AC_FAN_MED, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_QUIET}; + uint8_t modes[5] = {FUJITSU_AC_MODE_HEAT, FUJITSU_AC_MODE_DRY, FUJITSU_AC_MODE_COOL, FUJITSU_AC_MODE_AUTO, FUJITSU_AC_MODE_FAN}; + uint8_t fanModes[7] = {FUJITSU_AC_FAN_AUTO, FUJITSU_AC_FAN_LOW, FUJITSU_AC_FAN_MED, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_QUIET}; ac.setCmd(FUJITSU_AC_CMD_TURN_ON); ac.setSwing(FUJITSU_AC_SWING_VERT); @@ -505,11 +505,11 @@ boolean IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, boolean H { "Vendor": "", "Power": <0|1>, "Mode": "", "FanSpeed": "<1|2|3|4|5|Auto|Silence>", "Temp": <17..30> } */ -boolean IrSendCommand(void) +bool IrSendCommand(void) { char command [CMDSZ]; - boolean serviced = true; - boolean error = false; + bool serviced = true; + bool error = false; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kIrRemoteCommands); if (-1 == command_code) { @@ -531,7 +531,7 @@ boolean IrSendCommand(void) if (count) { // At least two raw data values count++; uint16_t raw_array[count]; // It's safe to use stack for up to 240 packets (limited by mqtt_data length) - byte i = 0; + uint8_t i = 0; for (str = strtok_r(NULL, ", ", &p); str && i < count; str = strtok_r(NULL, ", ", &p)) { raw_array[i++] = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input } @@ -611,7 +611,7 @@ boolean IrSendCommand(void) const char *HVAC_FanMode; const char *HVAC_Vendor; int HVAC_Temp = 21; - boolean HVAC_Power = true; + bool HVAC_Power = true; if (XdrvMailbox.data_len) { char dataBufUc[XdrvMailbox.data_len]; @@ -666,9 +666,9 @@ boolean IrSendCommand(void) * Interface \*********************************************************************************************/ -boolean Xdrv05(byte function) +bool Xdrv05(uint8_t function) { - boolean result = false; + bool result = false; if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { switch (function) { diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 55218bcbc..6a38b2854 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -251,7 +251,7 @@ void SonoffBridgeReceived(void) 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++) { + for (uint8_t 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), S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_JSON_LEARNED); @@ -274,7 +274,7 @@ void SonoffBridgeReceived(void) sonoff_bridge_last_received_id = received_id; sonoff_bridge_last_time = now; strncpy_P(rfkey, PSTR("\"" D_JSON_NONE "\""), sizeof(rfkey)); - for (byte i = 1; i <= 16; i++) { + for (uint8_t 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) { @@ -300,7 +300,7 @@ void SonoffBridgeReceived(void) } } -boolean SonoffBridgeSerialInput(void) +bool SonoffBridgeSerialInput(void) { // iTead Rf Universal Transceiver Module Serial Protocol Version 1.0 (20170420) static int8_t receive_len = 0; @@ -352,7 +352,7 @@ boolean SonoffBridgeSerialInput(void) return 0; } -void SonoffBridgeSendCommand(byte code) +void SonoffBridgeSendCommand(uint8_t code) { Serial.write(0xAA); // Start of Text Serial.write(code); // Command or Acknowledge @@ -370,7 +370,7 @@ void SonoffBridgeSendCode(uint32_t code) { Serial.write(0xAA); // Start of Text Serial.write(0xA5); // Send following code - for (byte i = 0; i < 6; i++) { + for (uint8_t i = 0; i < 6; i++) { Serial.write(Settings.rf_code[0][i]); } Serial.write((code >> 16) & 0xff); @@ -387,7 +387,7 @@ void SonoffBridgeSend(uint8_t idx, uint8_t key) key--; // Support 1 to 16 Serial.write(0xAA); // Start of Text Serial.write(0xA5); // Send following code - for (byte i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { Serial.write(Settings.rf_code[idx][i]); } if (0 == idx) { @@ -418,10 +418,10 @@ void SonoffBridgeLearn(uint8_t key) * Commands \*********************************************************************************************/ -boolean SonoffBridgeCommand(void) +bool SonoffBridgeCommand(void) { char command [CMDSZ]; - boolean serviced = true; + bool serviced = true; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kSonoffBridgeCommands); if (-1 == command_code) { @@ -485,7 +485,7 @@ boolean SonoffBridgeCommand(void) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_SET_TO_DEFAULT); } else if (4 == XdrvMailbox.payload) { // Save RF data provided by RFSync, RfLow, RfHigh and last RfCode - for (byte i = 0; i < 6; i++) { + for (uint8_t i = 0; i < 6; i++) { Settings.rf_code[XdrvMailbox.index][i] = Settings.rf_code[0][i]; } Settings.rf_code[XdrvMailbox.index][6] = (sonoff_bridge_last_send_code >> 16) & 0xff; @@ -566,9 +566,9 @@ void SonoffBridgeInit(void) * Interface \*********************************************************************************************/ -boolean Xdrv06(byte function) +bool Xdrv06(uint8_t function) { - boolean result = false; + bool result = false; if (SONOFF_BRIDGE == Settings.module) { switch (function) { diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index b36b3efc2..416a0cd9e 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -41,8 +41,8 @@ const char S_JSON_DOMOTICZ_COMMAND_INDEX_LVALUE[] PROGMEM = "{\"" D_CMND_DOMOTIC char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; char domoticz_out_topic[] = DOMOTICZ_OUT_TOPIC; -boolean domoticz_subscribe = false; -byte domoticz_update_flag = 1; +bool domoticz_subscribe = false; +uint8_t domoticz_update_flag = 1; int domoticz_update_timer = 0; unsigned long fan_debounce = 0; // iFan02 state debounce timer @@ -95,7 +95,7 @@ void DomoticzUpdateFanState() domoticz_update_flag = 1; } -void MqttPublishDomoticzPowerState(byte device) +void MqttPublishDomoticzPowerState(uint8_t device) { if (Settings.flag.mqtt_enabled) { if ((device < 1) || (device > devices_present)) { device = 1; } @@ -114,7 +114,7 @@ void MqttPublishDomoticzPowerState(byte device) } } -void DomoticzUpdatePowerState(byte device) +void DomoticzUpdatePowerState(uint8_t device) { if (domoticz_update_flag) { MqttPublishDomoticzPowerState(device); @@ -128,7 +128,7 @@ void DomoticzMqttUpdate(void) domoticz_update_timer--; if (domoticz_update_timer <= 0) { domoticz_update_timer = Settings.domoticz_update_timer; - for (byte i = 1; i <= devices_present; i++) { + for (uint8_t i = 1; i <= devices_present; i++) { if ((SONOFF_IFAN02 == Settings.module) && (i > 1)) { MqttPublishDomoticzFanState(); break; @@ -143,7 +143,7 @@ void DomoticzMqttUpdate(void) void DomoticzMqttSubscribe(void) { uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; - for (byte i = 0; i < maxdev; i++) { + for (uint8_t i = 0; i < maxdev; i++) { if (Settings.domoticz_relay_idx[i]) { domoticz_subscribe = true; } @@ -181,7 +181,7 @@ void DomoticzMqttSubscribe(void) } */ -boolean DomoticzMqttData(void) +bool DomoticzMqttData(void) { char stemp1[10]; unsigned long idx = 0; @@ -211,7 +211,7 @@ boolean DomoticzMqttData(void) if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) { uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; - for (byte i = 0; i < maxdev; i++) { + for (uint8_t i = 0; i < maxdev; i++) { if (idx == Settings.domoticz_relay_idx[i]) { bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); @@ -287,10 +287,10 @@ boolean DomoticzMqttData(void) * Commands \*********************************************************************************************/ -boolean DomoticzCommand(void) +bool DomoticzCommand(void) { char command [CMDSZ]; - boolean serviced = true; + bool serviced = true; uint8_t dmtcz_len = strlen(D_CMND_DOMOTICZ); // Prep for string length change if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_DOMOTICZ), dmtcz_len)) { // Prefix @@ -336,9 +336,9 @@ boolean DomoticzCommand(void) return serviced; } -boolean DomoticzSendKey(byte key, byte device, byte state, byte svalflg) +bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg) { - boolean result = 0; + bool result = 0; if (device <= MAX_DOMOTICZ_IDX) { if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) { @@ -374,7 +374,7 @@ uint8_t DomoticzHumidityState(char *hum) return (!h) ? 0 : (h < 40) ? 2 : (h > 70) ? 3 : 1; } -void DomoticzSensor(byte idx, char *data) +void DomoticzSensor(uint8_t idx, char *data) { if (Settings.domoticz_sensor_idx[idx]) { char dmess[90]; @@ -392,7 +392,7 @@ void DomoticzSensor(byte idx, char *data) } } -void DomoticzSensor(byte idx, uint32_t value) +void DomoticzSensor(uint8_t idx, uint32_t value) { char data[16]; snprintf_P(data, sizeof(data), PSTR("%d"), value); @@ -497,7 +497,7 @@ void DomoticzSaveSettings(void) char ssensor_indices[6 * MAX_DOMOTICZ_SNS_IDX]; char tmp[100]; - for (byte i = 0; i < MAX_DOMOTICZ_IDX; i++) { + for (uint8_t i = 0; i < MAX_DOMOTICZ_IDX; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("r%d"), i +1); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.domoticz_relay_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); @@ -509,7 +509,7 @@ void DomoticzSaveSettings(void) Settings.domoticz_switch_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); } ssensor_indices[0] = '\0'; - for (byte i = 0; i < DZ_MAX_SENSORS; i++) { + for (uint8_t i = 0; i < DZ_MAX_SENSORS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("l%d"), i +1); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.domoticz_sensor_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); @@ -531,9 +531,9 @@ void DomoticzSaveSettings(void) * Interface \*********************************************************************************************/ -boolean Xdrv07(byte function) +bool Xdrv07(uint8_t function) { - boolean result = false; + bool result = false; if (Settings.flag.mqtt_enabled) { switch (function) { diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 80ec37178..bb2abab63 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -42,7 +42,7 @@ void SerialBridgeInput(void) { while (SerialBridgeSerial->available()) { yield(); - uint8_t serial_in_byte = SerialBridgeSerial->read(); + uint8_t serial_in_uint8_t = SerialBridgeSerial->read(); if (serial_in_byte > 127) { // binary data... serial_bridge_in_byte_counter = 0; @@ -90,10 +90,10 @@ void SerialBridgeInit(void) * Commands \*********************************************************************************************/ -boolean SerialBridgeCommand(void) +bool SerialBridgeCommand(void) { char command [CMDSZ]; - boolean serviced = true; + bool serviced = true; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kSerialBridgeCommands); if (-1 == command_code) { @@ -149,9 +149,9 @@ boolean SerialBridgeCommand(void) * Interface \*********************************************************************************************/ -boolean Xdrv08(byte function) +bool Xdrv08(uint8_t function) { - boolean result = false; + bool result = false; if (serial_bridge_active) { switch (function) { diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index ded49e857..2fefe4d70 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -219,7 +219,7 @@ void ApplyTimerOffsets(Timer *duskdawn) duskdawn->time = timeBuffer; } -String GetSun(byte dawn) +String GetSun(uint8_t dawn) { char stime[6]; @@ -232,7 +232,7 @@ String GetSun(byte dawn) return String(stime); } -uint16_t GetSunMinutes(byte dawn) +uint16_t GetSunMinutes(uint8_t dawn) { uint8_t hour[2]; uint8_t minute[2]; @@ -246,7 +246,7 @@ uint16_t GetSunMinutes(byte dawn) /*******************************************************************************************/ -void TimerSetRandomWindow(byte index) +void TimerSetRandomWindow(uint8_t index) { timer_window[index] = 0; if (Settings.timer[index].window) { @@ -256,7 +256,7 @@ void TimerSetRandomWindow(byte index) void TimerSetRandomWindows(void) { - for (byte i = 0; i < MAX_TIMERS; i++) { TimerSetRandomWindow(i); } + for (uint8_t i = 0; i < MAX_TIMERS; i++) { TimerSetRandomWindow(i); } } void TimerEverySecond(void) @@ -268,7 +268,7 @@ void TimerEverySecond(void) int16_t time = (RtcTime.hour *60) + RtcTime.minute; uint8_t days = 1 << (RtcTime.day_of_week -1); - for (byte i = 0; i < MAX_TIMERS; i++) { + for (uint8_t i = 0; i < MAX_TIMERS; i++) { // if (Settings.timer[i].device >= devices_present) Settings.timer[i].data = 0; // Reset timer due to change in devices present Timer xtimer = Settings.timer[i]; uint16_t set_time = xtimer.time; @@ -308,7 +308,7 @@ void PrepShowTimer(uint8_t index) Timer xtimer = Settings.timer[index -1]; - for (byte i = 0; i < 7; i++) { + for (uint8_t i = 0; i < 7; i++) { uint8_t mask = 1 << i; snprintf(days, sizeof(days), "%s%d", days, ((xtimer.days & mask) > 0)); } @@ -337,11 +337,11 @@ void PrepShowTimer(uint8_t index) * Commands \*********************************************************************************************/ -boolean TimerCommand(void) +bool TimerCommand(void) { char command[CMDSZ]; char dataBufUc[XdrvMailbox.data_len]; - boolean serviced = true; + bool serviced = true; uint8_t index = XdrvMailbox.index; UpperCase(dataBufUc, XdrvMailbox.data); @@ -464,9 +464,9 @@ boolean TimerCommand(void) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag3.timers_enable)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, command); - byte jsflg = 0; - byte lines = 1; - for (byte i = 0; i < MAX_TIMERS; i++) { + uint8_t jsflg = 0; + uint8_t lines = 1; + for (uint8_t i = 0; i < MAX_TIMERS; i++) { if (!jsflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_TIMERS "%d\":{"), lines++); } else { @@ -699,7 +699,7 @@ void HandleTimerConfiguration(void) page.replace(F(""), FPSTR(HTTP_TIMER_STYLE)); page += FPSTR(HTTP_FORM_TIMER); page.replace(F("{e0"), (Settings.flag3.timers_enable) ? F(" checked") : F("")); - for (byte i = 0; i < MAX_TIMERS; i++) { + for (uint8_t i = 0; i < MAX_TIMERS; i++) { if (i > 0) { page += F(","); } page += String(Settings.timer[i].data); } @@ -725,7 +725,7 @@ void TimerSaveSettings(void) WebGetArg("t0", tmp, sizeof(tmp)); char *p = tmp; snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_TIMERS " %d"), Settings.flag3.timers_enable); - for (byte i = 0; i < MAX_TIMERS; i++) { + for (uint8_t i = 0; i < MAX_TIMERS; i++) { timer.data = strtol(p, &p, 10); p++; // Skip comma if (timer.time < 1440) { @@ -744,9 +744,9 @@ void TimerSaveSettings(void) * Interface \*********************************************************************************************/ -boolean Xdrv09(byte function) +bool Xdrv09(uint8_t function) { - boolean result = false; + bool result = false; switch (function) { case FUNC_PRE_INIT: diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 5c43db43c..0ea47c369 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -106,7 +106,7 @@ uint8_t mems_event = 0; /*******************************************************************************************/ -bool RulesRuleMatch(byte rule_set, String &event, String &rule) +bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) { // event = {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}} // event = {"System":{"Boot":1}} @@ -153,14 +153,14 @@ bool RulesRuleMatch(byte rule_set, String &event, String &rule) double rule_value = 0; if (pos > 0) { String rule_param = rule_name.substring(pos + 1); - for (byte i = 0; i < MAX_RULE_VARS; i++) { + for (uint8_t i = 0; i < MAX_RULE_VARS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%%VAR%d%%"), i +1); if (rule_param.startsWith(stemp)) { rule_param = vars[i]; break; } } - for (byte i = 0; i < MAX_RULE_MEMS; i++) { + for (uint8_t i = 0; i < MAX_RULE_MEMS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1); if (rule_param.startsWith(stemp)) { rule_param = Settings.mems[i]; @@ -262,7 +262,7 @@ bool RulesRuleMatch(byte rule_set, String &event, String &rule) /*******************************************************************************************/ -bool RuleSetProcess(byte rule_set, String &event_saved) +bool RuleSetProcess(uint8_t rule_set, String &event_saved) { bool serviced = false; char stemp[10]; @@ -315,11 +315,11 @@ bool RuleSetProcess(byte rule_set, String &event_saved) // if (!ucommand.startsWith("BACKLOG")) { commands = "backlog " + commands; } // Always use Backlog to prevent power race exception if (ucommand.indexOf("EVENT ") != -1) { commands = "backlog " + commands; } // Always use Backlog with event to prevent rule event loop exception commands.replace(F("%value%"), rules_event_value); - for (byte i = 0; i < MAX_RULE_VARS; i++) { + for (uint8_t i = 0; i < MAX_RULE_VARS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%%var%d%%"), i +1); commands.replace(stemp, vars[i]); } - for (byte i = 0; i < MAX_RULE_MEMS; i++) { + for (uint8_t i = 0; i < MAX_RULE_MEMS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%%mem%d%%"), i +1); commands.replace(stemp, Settings.mems[i]); } @@ -363,7 +363,7 @@ bool RulesProcessEvent(char *json_event) //snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Event %s"), event_saved.c_str()); //AddLog(LOG_LEVEL_DEBUG); - for (byte i = 0; i < MAX_RULE_SETS; i++) { + for (uint8_t i = 0; i < MAX_RULE_SETS; i++) { if (strlen(Settings.rules[i]) && bitRead(Settings.rule_enabled, i)) { if (RuleSetProcess(i, event_saved)) { serviced = true; } } @@ -379,7 +379,7 @@ bool RulesProcess(void) void RulesInit(void) { rules_flag.data = 0; - for (byte i = 0; i < MAX_RULE_SETS; i++) { + for (uint8_t i = 0; i < MAX_RULE_SETS; i++) { if (Settings.rules[i][0] == '\0') { bitWrite(Settings.rule_enabled, i, 0); bitWrite(Settings.rule_once, i, 0); @@ -396,7 +396,7 @@ void RulesEvery50ms(void) if (-1 == rules_new_power) { rules_new_power = power; } if (rules_new_power != rules_old_power) { if (rules_old_power != -1) { - for (byte i = 0; i < devices_present; i++) { + for (uint8_t i = 0; i < devices_present; i++) { uint8_t new_state = (rules_new_power >> i) &1; if (new_state != ((rules_old_power >> i) &1)) { snprintf_P(json_event, sizeof(json_event), PSTR("{\"Power%d\":{\"State\":%d}}"), i +1, new_state); @@ -405,19 +405,19 @@ void RulesEvery50ms(void) } } else { // Boot time POWER OUTPUTS (Relays) Status - for (byte i = 0; i < devices_present; i++) { + for (uint8_t i = 0; i < devices_present; i++) { uint8_t new_state = (rules_new_power >> i) &1; snprintf_P(json_event, sizeof(json_event), PSTR("{\"Power%d\":{\"Boot\":%d}}"), i +1, new_state); RulesProcessEvent(json_event); } // Boot time SWITCHES Status - for (byte i = 0; i < MAX_SWITCHES; i++) { + for (uint8_t i = 0; i < MAX_SWITCHES; i++) { #ifdef USE_TM1638 if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { #else if (pin[GPIO_SWT1 +i] < 99) { #endif // USE_TM1638 - boolean swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); + bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); snprintf_P(json_event, sizeof(json_event), PSTR("{\"" D_JSON_SWITCH "%d\":{\"Boot\":%d}}"), i +1, (swm ^ SwitchLastState(i))); RulesProcessEvent(json_event); } @@ -454,7 +454,7 @@ void RulesEvery50ms(void) } } else if (vars_event) { - for (byte i = 0; i < MAX_RULE_VARS-1; i++) { + for (uint8_t i = 0; i < MAX_RULE_VARS-1; i++) { if (bitRead(vars_event, i)) { bitClear(vars_event, i); snprintf_P(json_event, sizeof(json_event), PSTR("{\"Var%d\":{\"State\":%s}}"), i+1, vars[i]); @@ -464,7 +464,7 @@ void RulesEvery50ms(void) } } else if (mems_event) { - for (byte i = 0; i < MAX_RULE_MEMS-1; i++) { + for (uint8_t i = 0; i < MAX_RULE_MEMS-1; i++) { if (bitRead(mems_event, i)) { bitClear(mems_event, i); snprintf_P(json_event, sizeof(json_event), PSTR("{\"Mem%d\":{\"State\":%s}}"), i+1, Settings.mems[i]); @@ -475,7 +475,7 @@ void RulesEvery50ms(void) } else if (rules_flag.data) { uint16_t mask = 1; - for (byte i = 0; i < MAX_RULES_FLAG; i++) { + for (uint8_t i = 0; i < MAX_RULES_FLAG; i++) { if (rules_flag.data & mask) { rules_flag.data ^= mask; json_event[0] = '\0'; @@ -529,7 +529,7 @@ void RulesEverySecond(void) RulesProcessEvent(json_event); } } - for (byte i = 0; i < MAX_RULE_TIMERS; i++) { + for (uint8_t i = 0; i < MAX_RULE_TIMERS; i++) { if (rules_timer[i] != 0L) { // Timer active? if (TimeReached(rules_timer[i])) { // Timer finished? rules_timer[i] = 0L; // Turn off this timer @@ -553,10 +553,10 @@ void RulesTeleperiod(void) rules_teleperiod = 0; } -boolean RulesCommand(void) +bool RulesCommand(void) { char command[CMDSZ]; - boolean serviced = true; + bool serviced = true; uint8_t index = XdrvMailbox.index; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kRulesCommands); @@ -614,7 +614,7 @@ boolean RulesCommand(void) rules_timer[index -1] = (XdrvMailbox.payload > 0) ? millis() + (1000 * XdrvMailbox.payload) : 0; } mqtt_data[0] = '\0'; - for (byte i = 0; i < MAX_RULE_TIMERS; i++) { + for (uint8_t i = 0; i < MAX_RULE_TIMERS; i++) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%c\"T%d\":%d"), mqtt_data, (i) ? ',' : '{', i +1, (rules_timer[i]) ? (rules_timer[i] - millis()) / 1000 : 0); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); @@ -700,9 +700,9 @@ double map_double(double x, double in_min, double in_max, double out_min, double * Interface \*********************************************************************************************/ -boolean Xdrv10(byte function) +bool Xdrv10(uint8_t function) { - boolean result = false; + bool result = false; switch (function) { case FUNC_PRE_INIT: diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 8286443d8..d6d33e197 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -39,12 +39,12 @@ Variables in settings.h bool Settings.flag.knx_enabled Enable/Disable KNX Protocol uint16_t Settings.knx_physsical_addr Physical KNX address of this device -byte Settings.knx_GA_registered Number of group address to read -byte Settings.knx_CB_registered Number of group address to write +uint8_t Settings.knx_GA_registered Number of group address to read +uint8_t Settings.knx_CB_registered Number of group address to write uint16_t Settings.knx_GA_addr[MAX_KNX_GA] Group address to read uint16_t Settings.knx_CB_addr[MAX_KNX_CB] Group address to write -byte Settings.knx_GA_param[MAX_KNX_GA] Type of Input (relay changed, button pressed, sensor read) -byte Settings.knx_CB_param[MAX_KNX_CB] Type of Output (set relay, toggle relay, reply sensor value) +uint8_t Settings.knx_GA_param[MAX_KNX_GA] Type of Input (relay changed, button pressed, sensor read) +uint8_t Settings.knx_CB_param[MAX_KNX_CB] Type of Output (set relay, toggle relay, reply sensor value) \*********************************************************************************************/ @@ -61,11 +61,11 @@ address_t KNX_addr; // KNX Address converter variable float last_temp; float last_hum; -byte toggle_inhibit; +uint8_t toggle_inhibit; typedef struct __device_parameters { - byte type; // PARAMETER_ID. Used as type of GA = relay, button, sensor, etc, (INPUTS) + uint8_t type; // PARAMETER_ID. Used as type of GA = relay, button, sensor, etc, (INPUTS) // used when an action on device triggers a MSG to send on KNX // Needed because this is the value that the ESP_KNX_IP library will pass as parameter // to identify the action to perform when a MSG is received @@ -200,9 +200,9 @@ enum KnxCommands { CMND_KNXTXCMND, CMND_KNXTXVAL, CMND_KNX_ENABLED, CMND_KNX_ENH const char kKnxCommands[] PROGMEM = D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL "|" D_CMND_KNX_ENABLED "|" D_CMND_KNX_ENHANCED "|" D_CMND_KNX_PA "|" D_CMND_KNX_GA "|" D_CMND_KNX_CB ; -byte KNX_GA_Search( byte param, byte start = 0 ) +uint8_t KNX_GA_Search( uint8_t param, uint8_t start = 0 ) { - for (byte i = start; i < Settings.knx_GA_registered; ++i) + for (uint8_t i = start; i < Settings.knx_GA_registered; ++i) { if ( Settings.knx_GA_param[i] == param ) { @@ -216,9 +216,9 @@ byte KNX_GA_Search( byte param, byte start = 0 ) } -byte KNX_CB_Search( byte param, byte start = 0 ) +uint8_t KNX_CB_Search( uint8_t param, uint8_t start = 0 ) { - for (byte i = start; i < Settings.knx_CB_registered; ++i) + for (uint8_t i = start; i < Settings.knx_CB_registered; ++i) { if ( Settings.knx_CB_param[i] == param ) { @@ -232,7 +232,7 @@ byte KNX_CB_Search( byte param, byte start = 0 ) } -void KNX_ADD_GA( byte GAop, byte GA_FNUM, byte GA_AREA, byte GA_FDEF ) +void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF ) { // Check if all GA were assigned. If yes-> return if ( Settings.knx_GA_registered >= MAX_KNX_GA ) { return; } @@ -255,12 +255,12 @@ void KNX_ADD_GA( byte GAop, byte GA_FNUM, byte GA_AREA, byte GA_FDEF ) } -void KNX_DEL_GA( byte GAnum ) +void KNX_DEL_GA( uint8_t GAnum ) { - byte dest_offset = 0; - byte src_offset = 0; - byte len = 0; + uint8_t dest_offset = 0; + uint8_t src_offset = 0; + uint8_t len = 0; // Delete GA Settings.knx_GA_param[GAnum-1] = 0; @@ -291,7 +291,7 @@ void KNX_DEL_GA( byte GAnum ) if (len > 0) { - memmove(Settings.knx_GA_param + dest_offset, Settings.knx_GA_param + src_offset, len * sizeof(byte)); + memmove(Settings.knx_GA_param + dest_offset, Settings.knx_GA_param + src_offset, len * sizeof(uint8_t)); memmove(Settings.knx_GA_addr + dest_offset, Settings.knx_GA_addr + src_offset, len * sizeof(uint16_t)); } @@ -303,7 +303,7 @@ void KNX_DEL_GA( byte GAnum ) } -void KNX_ADD_CB( byte CBop, byte CB_FNUM, byte CB_AREA, byte CB_FDEF ) +void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF ) { // Check if all callbacks were assigned. If yes-> return if ( Settings.knx_CB_registered >= MAX_KNX_CB ) { return; } @@ -338,12 +338,12 @@ void KNX_ADD_CB( byte CBop, byte CB_FNUM, byte CB_AREA, byte CB_FDEF ) } -void KNX_DEL_CB( byte CBnum ) +void KNX_DEL_CB( uint8_t CBnum ) { - byte oldparam = Settings.knx_CB_param[CBnum-1]; - byte dest_offset = 0; - byte src_offset = 0; - byte len = 0; + uint8_t oldparam = Settings.knx_CB_param[CBnum-1]; + uint8_t dest_offset = 0; + uint8_t src_offset = 0; + uint8_t len = 0; // Delete assigment knx.callback_unassign(CBnum-1); @@ -375,7 +375,7 @@ void KNX_DEL_CB( byte CBnum ) if (len > 0) { - memmove(Settings.knx_CB_param + dest_offset, Settings.knx_CB_param + src_offset, len * sizeof(byte)); + memmove(Settings.knx_CB_param + dest_offset, Settings.knx_CB_param + src_offset, len * sizeof(uint8_t)); memmove(Settings.knx_CB_addr + dest_offset, Settings.knx_CB_addr + src_offset, len * sizeof(uint16_t)); } @@ -395,7 +395,7 @@ void KNX_DEL_CB( byte CBnum ) bool KNX_CONFIG_NOT_MATCH(void) { // Check for configured parameters that the device does not have (module changed) - for (byte i = 0; i < KNX_MAX_device_param; ++i) + for (uint8_t i = 0; i < KNX_MAX_device_param; ++i) { if ( !device_param[i].show ) { // device has this parameter ? // if not, search for all registered group address to this parameter for deletion @@ -417,7 +417,7 @@ bool KNX_CONFIG_NOT_MATCH(void) } // Check for invalid or erroneous configuration (tasmota flashed without clearing the memory) - for (byte i = 0; i < Settings.knx_GA_registered; ++i) + for (uint8_t i = 0; i < Settings.knx_GA_registered; ++i) { if ( Settings.knx_GA_param[i] != 0 ) // the GA[i] have a parameter defined? { @@ -427,7 +427,7 @@ bool KNX_CONFIG_NOT_MATCH(void) } } } - for (byte i = 0; i < Settings.knx_CB_registered; ++i) + for (uint8_t i = 0; i < Settings.knx_CB_registered; ++i) { if ( Settings.knx_CB_param[i] != 0 ) // the CB[i] have a parameter defined? { @@ -529,8 +529,8 @@ void KNX_INIT(void) // Register Group Addresses to listen to // Search on the settings if there is a group address set for receive KNX messages for the type: device_param[j].type // If there is, register the group address on the KNX_IP Library to Receive data for Executing Callbacks - byte j; - for (byte i = 0; i < Settings.knx_CB_registered; ++i) + uint8_t j; + for (uint8_t i = 0; i < Settings.knx_CB_registered; ++i) { j = Settings.knx_CB_param[i]; if ( j > 0 ) @@ -652,14 +652,14 @@ void KNX_CB_Action(message_t const &msg, void *arg) } -void KnxUpdatePowerState(byte device, power_t state) +void KnxUpdatePowerState(uint8_t device, power_t state) { if (!(Settings.flag.knx_enabled)) { return; } device_param[device -1].last_state = bitRead(state, device -1); // power state (on/off) // Search all the registered GA that has that output (variable: device) as parameter - byte i = KNX_GA_Search(device); + uint8_t i = KNX_GA_Search(device); while ( i != KNX_Empty ) { KNX_addr.value = Settings.knx_GA_addr[i]; knx.write_1bit(KNX_addr, device_param[device -1].last_state); @@ -678,7 +678,7 @@ void KnxUpdatePowerState(byte device, power_t state) } -void KnxSendButtonPower(byte key, byte device, byte state) +void KnxSendButtonPower(uint8_t key, uint8_t device, uint8_t state) { // key 0 = button_topic // key 1 = switch_topic @@ -692,7 +692,7 @@ void KnxSendButtonPower(byte key, byte device, byte state) // { // Search all the registered GA that has that output (variable: device) as parameter - byte i = KNX_GA_Search(device + 8); + uint8_t i = KNX_GA_Search(device + 8); while ( i != KNX_Empty ) { KNX_addr.value = Settings.knx_GA_addr[i]; knx.write_1bit(KNX_addr, !(state == 0)); @@ -712,7 +712,7 @@ void KnxSendButtonPower(byte key, byte device, byte state) } -void KnxSensor(byte sensor_type, float value) +void KnxSensor(uint8_t sensor_type, float value) { if (sensor_type == KNX_TEMPERATURE) { @@ -724,7 +724,7 @@ void KnxSensor(byte sensor_type, float value) if (!(Settings.flag.knx_enabled)) { return; } - byte i = KNX_GA_Search(sensor_type); + uint8_t i = KNX_GA_Search(sensor_type); while ( i != KNX_Empty ) { KNX_addr.value = Settings.knx_GA_addr[i]; knx.write_2byte_float(KNX_addr, value); @@ -822,13 +822,13 @@ void HandleKNXConfiguration(void) if ( WebServer->arg("btn_add") == "1" ) { stmp = WebServer->arg("GAop"); //option selected - byte GAop = stmp.toInt(); + uint8_t GAop = stmp.toInt(); stmp = WebServer->arg("GA_FNUM"); - byte GA_FNUM = stmp.toInt(); + uint8_t GA_FNUM = stmp.toInt(); stmp = WebServer->arg("GA_AREA"); - byte GA_AREA = stmp.toInt(); + uint8_t GA_AREA = stmp.toInt(); stmp = WebServer->arg("GA_FDEF"); - byte GA_FDEF = stmp.toInt(); + uint8_t GA_FDEF = stmp.toInt(); if (GAop) { KNX_ADD_GA( GAop, GA_FNUM, GA_AREA, GA_FDEF ); @@ -838,13 +838,13 @@ void HandleKNXConfiguration(void) { stmp = WebServer->arg("CBop"); //option selected - byte CBop = stmp.toInt(); + uint8_t CBop = stmp.toInt(); stmp = WebServer->arg("CB_FNUM"); - byte CB_FNUM = stmp.toInt(); + uint8_t CB_FNUM = stmp.toInt(); stmp = WebServer->arg("CB_AREA"); - byte CB_AREA = stmp.toInt(); + uint8_t CB_AREA = stmp.toInt(); stmp = WebServer->arg("CB_FDEF"); - byte CB_FDEF = stmp.toInt(); + uint8_t CB_FDEF = stmp.toInt(); if (CBop) { KNX_ADD_CB( CBop, CB_FNUM, CB_AREA, CB_FDEF ); @@ -855,7 +855,7 @@ void HandleKNXConfiguration(void) { stmp = WebServer->arg("btn_del_ga"); - byte GA_NUM = stmp.toInt(); + uint8_t GA_NUM = stmp.toInt(); KNX_DEL_GA(GA_NUM); @@ -864,7 +864,7 @@ void HandleKNXConfiguration(void) { stmp = WebServer->arg("btn_del_cb"); - byte CB_NUM = stmp.toInt(); + uint8_t CB_NUM = stmp.toInt(); KNX_DEL_CB(CB_NUM); @@ -884,7 +884,7 @@ void HandleKNXConfiguration(void) if ( Settings.flag.knx_enable_enhancement ) { page += F(" checked"); } page += FPSTR(HTTP_FORM_KNX2); - for (byte i = 0; i < KNX_MAX_device_param ; i++) + for (uint8_t i = 0; i < KNX_MAX_device_param ; i++) { if ( device_param[i].show ) { @@ -911,7 +911,7 @@ void HandleKNXConfiguration(void) page.replace(F("btndis"), F("disabled")); } page.replace(F("fncbtnadd"), F("GAwarning")); - for (byte i = 0; i < Settings.knx_GA_registered ; ++i) + for (uint8_t i = 0; i < Settings.knx_GA_registered ; ++i) { if ( Settings.knx_GA_param[i] ) { @@ -934,8 +934,8 @@ void HandleKNXConfiguration(void) page.replace(F("GAarea"), F("CB_AREA")); page.replace(F("GAfdef"), F("CB_FDEF")); page += FPSTR(HTTP_FORM_KNX4); - byte j; - for (byte i = 0; i < KNX_MAX_device_param ; i++) + uint8_t j; + for (uint8_t i = 0; i < KNX_MAX_device_param ; i++) { // Check How many Relays are available and add: RelayX and TogleRelayX if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; } @@ -959,7 +959,7 @@ void HandleKNXConfiguration(void) } page.replace(F("fncbtnadd"), F("CBwarning")); - for (byte i = 0; i < Settings.knx_CB_registered ; ++i) + for (uint8_t i = 0; i < Settings.knx_CB_registered ; ++i) { if ( Settings.knx_CB_param[i] ) { @@ -1028,7 +1028,7 @@ void KNX_Save_Settings(void) snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "GA: %d"), Settings.knx_GA_registered ); AddLog(LOG_LEVEL_DEBUG); - for (byte i = 0; i < Settings.knx_GA_registered ; ++i) + for (uint8_t i = 0; i < Settings.knx_GA_registered ; ++i) { KNX_addr.value = Settings.knx_GA_addr[i]; snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "GA #%d: %s " D_TO " %d/%d/%d"), @@ -1040,7 +1040,7 @@ void KNX_Save_Settings(void) snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "CB: %d"), Settings.knx_CB_registered ); AddLog(LOG_LEVEL_DEBUG); - for (byte i = 0; i < Settings.knx_CB_registered ; ++i) + for (uint8_t i = 0; i < Settings.knx_CB_registered ; ++i) { KNX_addr.value = Settings.knx_CB_addr[i]; snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "CB #%d: %d/%d/%d " D_TO " %s"), @@ -1055,7 +1055,7 @@ void KNX_Save_Settings(void) #endif // USE_WEBSERVER -boolean KnxCommand(void) +bool KnxCommand(void) { char command[CMDSZ]; uint8_t index = XdrvMailbox.index; @@ -1068,7 +1068,7 @@ boolean KnxCommand(void) // XdrvMailbox.payload <- data to send if (!(Settings.flag.knx_enabled)) { return false; } // Search all the registered GA that has that output (variable: KNX SLOTx) as parameter - byte i = KNX_GA_Search(index + KNX_SLOT1 -1); + uint8_t i = KNX_GA_Search(index + KNX_SLOT1 -1); while ( i != KNX_Empty ) { KNX_addr.value = Settings.knx_GA_addr[i]; knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); @@ -1093,7 +1093,7 @@ boolean KnxCommand(void) // XdrvMailbox.payload <- data to send if (!(Settings.flag.knx_enabled)) { return false; } // Search all the registered GA that has that output (variable: KNX SLOTx) as parameter - byte i = KNX_GA_Search(index + KNX_SLOT1 -1); + uint8_t i = KNX_GA_Search(index + KNX_SLOT1 -1); while ( i != KNX_Empty ) { KNX_addr.value = Settings.knx_GA_addr[i]; @@ -1288,9 +1288,9 @@ boolean KnxCommand(void) * Interface \*********************************************************************************************/ -boolean Xdrv11(byte function) +bool Xdrv11(uint8_t function) { - boolean result = false; + bool result = false; switch (function) { case FUNC_PRE_INIT: KNX_INIT(); diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index cbab0d2c5..80c5b4ebe 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -250,7 +250,7 @@ void HAssAnnounceRelayLight(void) } } -void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, byte toggle) +void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint8_t key, uint8_t toggle) { // key 0 = button // key 1 = switch @@ -306,9 +306,9 @@ void HAssAnnounceSwitches(void) char *tmp = Settings.switch_topic; Format(sw_topic, tmp, sizeof(sw_topic)); if ((strlen(sw_topic) != 0) && strcmp(sw_topic, "0")) { - for (byte switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) { - byte switch_present = 0; - byte toggle = 1; + for (uint8_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) { + uint8_t switch_present = 0; + uint8_t toggle = 1; if (pin[GPIO_SWT1 + switch_index] < 99) { switch_present = 1; @@ -335,9 +335,9 @@ void HAssAnnounceButtons(void) char *tmp = Settings.button_topic; Format(key_topic, tmp, sizeof(key_topic)); if ((strlen(key_topic) != 0) && strcmp(key_topic, "0")) { - for (byte button_index = 0; button_index < MAX_KEYS; button_index++) { - byte button_present = 0; - byte toggle = 1; + for (uint8_t button_index = 0; button_index < MAX_KEYS; button_index++) { + uint8_t button_present = 0; + uint8_t toggle = 1; if (!button_index && ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module))) { button_present = 1; @@ -509,9 +509,9 @@ void HAssDiscover(void) * Interface \*********************************************************************************************/ -boolean Xdrv12(byte function) +bool Xdrv12(uint8_t function) { - boolean result = false; + bool result = false; if (Settings.flag.mqtt_enabled) { switch (function) { diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index b5545e256..95822403e 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -495,7 +495,7 @@ void DisplayText(void) void DisplayClearScreenBuffer(void) { if (disp_screen_buffer_cols) { - for (byte i = 0; i < disp_screen_buffer_rows; i++) { + for (uint8_t i = 0; i < disp_screen_buffer_rows; i++) { memset(disp_screen_buffer[i], 0, disp_screen_buffer_cols); } } @@ -504,7 +504,7 @@ void DisplayClearScreenBuffer(void) void DisplayFreeScreenBuffer(void) { if (disp_screen_buffer != NULL) { - for (byte i = 0; i < disp_screen_buffer_rows; i++) { + for (uint8_t i = 0; i < disp_screen_buffer_rows; i++) { if (disp_screen_buffer[i] != NULL) { free(disp_screen_buffer[i]); } } free(disp_screen_buffer); @@ -519,7 +519,7 @@ void DisplayAllocScreenBuffer(void) disp_screen_buffer_rows = Settings.display_rows; disp_screen_buffer = (char**)malloc(sizeof(*disp_screen_buffer) * disp_screen_buffer_rows); if (disp_screen_buffer != NULL) { - for (byte i = 0; i < disp_screen_buffer_rows; i++) { + for (uint8_t i = 0; i < disp_screen_buffer_rows; i++) { disp_screen_buffer[i] = (char*)malloc(sizeof(*disp_screen_buffer[i]) * (Settings.display_cols[0] +1)); if (disp_screen_buffer[i] == NULL) { DisplayFreeScreenBuffer(); @@ -542,7 +542,7 @@ void DisplayReAllocScreenBuffer(void) void DisplayFillScreen(uint8_t line) { - byte len = disp_screen_buffer_cols - strlen(disp_screen_buffer[line]); + uint8_t len = disp_screen_buffer_cols - strlen(disp_screen_buffer[line]); if (len) { memset(disp_screen_buffer[line] + strlen(disp_screen_buffer[line]), 0x20, len); disp_screen_buffer[line][disp_screen_buffer_cols -1] = 0; @@ -554,7 +554,7 @@ void DisplayFillScreen(uint8_t line) void DisplayClearLogBuffer(void) { if (disp_log_buffer_cols) { - for (byte i = 0; i < DISPLAY_LOG_ROWS; i++) { + for (uint8_t i = 0; i < DISPLAY_LOG_ROWS; i++) { memset(disp_log_buffer[i], 0, disp_log_buffer_cols); } } @@ -563,7 +563,7 @@ void DisplayClearLogBuffer(void) void DisplayFreeLogBuffer(void) { if (disp_log_buffer != NULL) { - for (byte i = 0; i < DISPLAY_LOG_ROWS; i++) { + for (uint8_t i = 0; i < DISPLAY_LOG_ROWS; i++) { if (disp_log_buffer[i] != NULL) { free(disp_log_buffer[i]); } } free(disp_log_buffer); @@ -576,7 +576,7 @@ void DisplayAllocLogBuffer(void) if (!disp_log_buffer_cols) { disp_log_buffer = (char**)malloc(sizeof(*disp_log_buffer) * DISPLAY_LOG_ROWS); if (disp_log_buffer != NULL) { - for (byte i = 0; i < DISPLAY_LOG_ROWS; i++) { + for (uint8_t i = 0; i < DISPLAY_LOG_ROWS; i++) { disp_log_buffer[i] = (char*)malloc(sizeof(*disp_log_buffer[i]) * (Settings.display_cols[0] +1)); if (disp_log_buffer[i] == NULL) { DisplayFreeLogBuffer(); @@ -845,7 +845,7 @@ void DisplayMqttSubscribe(void) } } -boolean DisplayMqttData(void) +bool DisplayMqttData(void) { if (disp_subscribed) { char stopic[TOPSZ]; @@ -908,10 +908,10 @@ void DisplaySetPower(void) * Commands \*********************************************************************************************/ -boolean DisplayCommand(void) +bool DisplayCommand(void) { char command [CMDSZ]; - boolean serviced = true; + bool serviced = true; uint8_t disp_len = strlen(D_CMND_DISPLAY); // Prep for string length change if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_DISPLAY), disp_len)) { // Prefix @@ -1076,9 +1076,9 @@ boolean DisplayCommand(void) * Interface \*********************************************************************************************/ -boolean Xdrv13(byte function) +bool Xdrv13(uint8_t function) { - boolean result = false; + bool result = false; if ((i2c_flg || spi_flg || soft_spi_flg) && XdspPresent()) { switch (function) { diff --git a/sonoff/xdrv_14_mp3.ino b/sonoff/xdrv_14_mp3.ino index 5e7ca23e1..4e55cddc5 100644 --- a/sonoff/xdrv_14_mp3.ino +++ b/sonoff/xdrv_14_mp3.ino @@ -178,9 +178,9 @@ void MP3_CMD(uint8_t mp3cmd,uint16_t val) { * check the MP3 commands \*********************************************************************************************/ -boolean MP3PlayerCmd(void) { +bool MP3PlayerCmd(void) { char command[CMDSZ]; - boolean serviced = true; + bool serviced = true; uint8_t disp_len = strlen(D_CMND_MP3); if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { // prefix @@ -226,9 +226,9 @@ boolean MP3PlayerCmd(void) { * Interface \*********************************************************************************************/ -boolean Xdrv14(byte function) +bool Xdrv14(uint8_t function) { - boolean result = false; + bool result = false; if (pin[GPIO_MP3_DFR562] < 99) { switch (function) { diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index c55581dc9..14eaf8a07 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -103,8 +103,8 @@ void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted) { bool PCA9685_Command(void) { - boolean serviced = true; - boolean validpin = false; + bool serviced = true; + bool validpin = false; uint8_t paramcount = 0; if (XdrvMailbox.data_len > 0) { paramcount=1; @@ -178,9 +178,9 @@ void PCA9685_OutputTelemetry(bool telemetry) { } } -boolean Xdrv15(byte function) +bool Xdrv15(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index da03b2c79..dbac0d644 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -47,7 +47,7 @@ TasmotaSerial *TuyaSerial = nullptr; uint8_t tuya_new_dim = 0; // Tuya dimmer value temp -boolean tuya_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction +bool tuya_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction uint8_t tuya_cmd_status = 0; // Current status of serial-read uint8_t tuya_cmd_checksum = 0; // Checksum of tuya command uint8_t tuya_data_len = 0; // Data lenght of command @@ -106,17 +106,17 @@ void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value){ TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); } -void TuyaSendBool(uint8_t id, boolean value){ - TuyaSendState(id, TUYA_TYPE_BOOL, &value); +void TuyaSendBool(uint8_t id, bool value){ + TuyaSendState(id, TUYA_TYPE_BOOL, (uint8_t*)&value); } void TuyaSendValue(uint8_t id, uint32_t value){ TuyaSendState(id, TUYA_TYPE_VALUE, (uint8_t*)(&value)); } -boolean TuyaSetPower(void) +bool TuyaSetPower(void) { - boolean status = false; + bool status = false; uint8_t rpower = XdrvMailbox.index; int16_t source = XdrvMailbox.payload; @@ -133,7 +133,7 @@ boolean TuyaSetPower(void) return status; } -boolean TuyaSetChannels(void) +bool TuyaSetChannels(void) { LightSerialDuty(((uint8_t*)XdrvMailbox.data)[0]); return true; @@ -246,9 +246,9 @@ void TuyaPacketProcess(void) if (tuya_buffer[5] == 2) { uint8_t led1_gpio = tuya_buffer[6]; uint8_t key1_gpio = tuya_buffer[7]; - boolean key1_set = false; - boolean led1_set = false; - for (byte i = 0; i < sizeof(Settings.my_gp); i++) { + bool key1_set = false; + bool led1_set = false; + for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { if (Settings.my_gp.io[i] == GPIO_LED1) led1_set = true; else if (Settings.my_gp.io[i] == GPIO_KEY1) key1_set = true; } @@ -273,7 +273,7 @@ void TuyaPacketProcess(void) * API Functions \*********************************************************************************************/ -boolean TuyaModuleSelected(void) +bool TuyaModuleSelected(void) { if (!(pin[GPIO_TUYA_RX] < 99) || !(pin[GPIO_TUYA_TX] < 99)) { // fallback to hardware-serial if not explicitly selected pin[GPIO_TUYA_TX] = 1; @@ -309,7 +309,7 @@ void TuyaSerialInput(void) { while (TuyaSerial->available()) { yield(); - byte serial_in_byte = TuyaSerial->read(); + uint8_t serial_in_byte = TuyaSerial->read(); if (serial_in_byte == 0x55) { // Start TUYA Packet tuya_cmd_status = 1; @@ -361,7 +361,7 @@ void TuyaSerialInput(void) } -boolean TuyaButtonPressed(void) +bool TuyaButtonPressed(void) { if (!XdrvMailbox.index && ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == lastbutton[XdrvMailbox.index]))) { snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Reset GPIO triggered")); @@ -398,9 +398,9 @@ void TuyaSetWifiLed(void){ * Interface \*********************************************************************************************/ -boolean Xdrv16(byte function) +bool Xdrv16(uint8_t function) { - boolean result = false; + bool result = false; if (TUYA_DIMMER == Settings.module) { switch (function) { diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index 4f992180e..7689f3d1c 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -88,10 +88,10 @@ void RfInit(void) * Commands \*********************************************************************************************/ -boolean RfSendCommand(void) +bool RfSendCommand(void) { - boolean serviced = true; - boolean error = false; + bool serviced = true; + bool error = false; if (!strcasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_RFSEND))) { if (XdrvMailbox.data_len) { @@ -116,7 +116,7 @@ boolean RfSendCommand(void) } else { // RFsend data, bits, protocol, repeat, pulse char *p; - byte i = 0; + uint8_t i = 0; for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 5; str = strtok_r(NULL, ", ", &p)) { switch (i++) { case 0: @@ -166,9 +166,9 @@ boolean RfSendCommand(void) * Interface \*********************************************************************************************/ -boolean Xdrv17(byte function) +bool Xdrv17(uint8_t function) { - boolean result = false; + bool result = false; if ((pin[GPIO_RFSEND] < 99) || (pin[GPIO_RFRECV] < 99)) { switch (function) { diff --git a/sonoff/xdrv_18_armtronix_dimmers.ino b/sonoff/xdrv_18_armtronix_dimmers.ino index 3484ed8e6..f27f37fc8 100644 --- a/sonoff/xdrv_18_armtronix_dimmers.ino +++ b/sonoff/xdrv_18_armtronix_dimmers.ino @@ -31,7 +31,7 @@ TasmotaSerial *ArmtronixSerial = nullptr; -boolean armtronix_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction +bool armtronix_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction int8_t armtronix_wifi_state = -2; // Keep MCU wifi-status in sync with WifiState() int8_t armtronix_dimState[2]; // Dimmer state values. int8_t armtronix_knobState[2]; // Dimmer state values. @@ -40,7 +40,7 @@ int8_t armtronix_knobState[2]; // Dimmer state values. * Internal Functions \*********************************************************************************************/ -boolean ArmtronixSetChannels(void) +bool ArmtronixSetChannels(void) { LightSerial2Duty(((uint8_t*)XdrvMailbox.data)[0], ((uint8_t*)XdrvMailbox.data)[1]); return true; @@ -84,7 +84,7 @@ void ArmtronixRequestState(void) * API Functions \*********************************************************************************************/ -boolean ArmtronixModuleSelected(void) +bool ArmtronixModuleSelected(void) { light_type = LT_SERIAL2; return true; @@ -169,9 +169,9 @@ void ArmtronixSetWifiLed(void) * Interface \*********************************************************************************************/ -boolean Xdrv18(byte function) +bool Xdrv18(uint8_t function) { - boolean result = false; + bool result = false; if (ARMTRONIX_DIMMERS == Settings.module) { switch (function) { diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 33fb72ab6..ce8339502 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -31,7 +31,7 @@ TasmotaSerial *PS16DZSerial = nullptr; -boolean ps16dz_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction +bool ps16dz_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction //uint64_t ps16dz_seq = 0; @@ -75,9 +75,9 @@ void PS16DZSendCommand(char type = 0, uint8_t value = 0) PS16DZSerial->flush(); } -boolean PS16DZSetPower(void) +bool PS16DZSetPower(void) { - boolean status = false; + bool status = false; uint8_t rpower = XdrvMailbox.index; int16_t source = XdrvMailbox.payload; @@ -91,7 +91,7 @@ boolean PS16DZSetPower(void) return status; } -boolean PS16DZSetChannels(void) +bool PS16DZSetChannels(void) { PS16DZSerialDuty(((uint8_t*)XdrvMailbox.data)[0]); return true; @@ -128,7 +128,7 @@ void PS16DZResetWifi(void) * API Functions \*********************************************************************************************/ -boolean PS16DZModuleSelected(void) +bool PS16DZModuleSelected(void) { light_type = LT_SERIAL1; return true; @@ -153,7 +153,7 @@ void PS16DZSerialInput(void) char scmnd[20]; while (PS16DZSerial->available()) { yield(); - byte serial_in_byte = PS16DZSerial->read(); + uint8_t serial_in_byte = PS16DZSerial->read(); if (serial_in_byte != 0x1B){ if (ps16dz_byte_counter >= PS16DZ_BUFFER_SIZE - 1) { memset(ps16dz_rx_buffer, 0, PS16DZ_BUFFER_SIZE); @@ -176,7 +176,7 @@ void PS16DZSerialInput(void) char* token2 = strtok_r(token, ":", &end_token); char* token3 = strtok_r(NULL, ":", &end_token); if(!strncmp(token2, "\"switch\"", 8)){ - boolean ps16dz_power = !strncmp(token3, "\"on\"", 4)?true:false; + bool ps16dz_power = !strncmp(token3, "\"on\"", 4)?true:false; snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: power received: %s"), token3); AddLog(LOG_LEVEL_DEBUG); if((power || Settings.light_dimmer > 0) && (power !=ps16dz_power)) { @@ -225,9 +225,9 @@ void PS16DZSerialInput(void) * Interface \*********************************************************************************************/ -boolean Xdrv19(byte function) +bool Xdrv19(uint8_t function) { - boolean result = false; + bool result = false; if (PS_16_DZ == Settings.module) { switch (function) { diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_99_debug.ino index 13b420d2e..113fc7ce4 100644 --- a/sonoff/xdrv_99_debug.ino +++ b/sonoff/xdrv_99_debug.ino @@ -71,7 +71,7 @@ uint8_t CPU_show_freemem = 0; /*******************************************************************************************/ #ifdef DEBUG_THEO -void ExceptionTest(byte type) +void ExceptionTest(uint8_t type) { /* Exception (28): @@ -334,11 +334,11 @@ void DebugCfgPeek(char* parms) uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + data16; snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), address); - for (byte i = 0; i < 4; i++) { + for (uint8_t i = 0; i < 4; i++) { snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[address +i]); } snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (byte i = 0; i < 4; i++) { + for (uint8_t i = 0; i < 4; i++) { snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[address +i] > 0x20) && (buffer[address +i] < 0x7F)) ? (char)buffer[address +i] : ' '); } snprintf_P(log_data, sizeof(log_data), PSTR("%s| 0x%02X (%d), 0x%04X (%d), 0x%0LX (%lu)"), log_data, data8, data8, data16, data16, data32, data32); @@ -359,7 +359,7 @@ void DebugCfgPoke(char* parms) uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; uint8_t *nbuffer = (uint8_t *) &data; - for (byte i = 0; i < 4; i++) { buffer[address +i] = nbuffer[+i]; } + for (uint8_t i = 0; i < 4; i++) { buffer[address +i] = nbuffer[+i]; } uint32_t ndata32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; @@ -433,10 +433,10 @@ void SetFlashMode(uint8_t mode) /*******************************************************************************************/ -boolean DebugCommand(void) +bool DebugCommand(void) { char command[CMDSZ]; - boolean serviced = true; + bool serviced = true; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kDebugCommands); if (-1 == command_code) { @@ -516,9 +516,9 @@ boolean DebugCommand(void) * Interface \*********************************************************************************************/ -boolean Xdrv99(byte function) +bool Xdrv99(uint8_t function) { - boolean result = false; + bool result = false; switch (function) { case FUNC_PRE_INIT: diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 9f60731d6..7c3a31c25 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -18,9 +18,9 @@ */ #ifdef XFUNC_PTR_IN_ROM -boolean (* const xdrv_func_ptr[])(byte) PROGMEM = { // Driver Function Pointers +bool (* const xdrv_func_ptr[])(uint8_t) PROGMEM = { // Driver Function Pointers #else -boolean (* const xdrv_func_ptr[])(byte) = { // Driver Function Pointers +bool (* const xdrv_func_ptr[])(uint8_t) = { // Driver Function Pointers #endif #ifdef XDRV_01 @@ -192,7 +192,7 @@ boolean (* const xdrv_func_ptr[])(byte) = { // Driver Function Pointers const uint8_t xdrv_present = sizeof(xdrv_func_ptr) / sizeof(xdrv_func_ptr[0]); // Number of drivers found -boolean XdrvCommand(uint8_t grpflg, char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload, uint16_t payload16) +bool XdrvCommand(bool grpflg, char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload, uint16_t payload16) { // XdrvMailbox.valid = 1; XdrvMailbox.index = index; @@ -206,7 +206,7 @@ boolean XdrvCommand(uint8_t grpflg, char *type, uint16_t index, char *dataBuf, u return XdrvCall(FUNC_COMMAND); } -boolean XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t sdataBuf) +bool XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t sdataBuf) { XdrvMailbox.index = stopicBuf; XdrvMailbox.data_len = sdataBuf; @@ -216,7 +216,7 @@ boolean XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t return XdrvCall(FUNC_MQTT_DATA); } -boolean XdrvRulesProcess(void) +bool XdrvRulesProcess(void) { return XdrvCall(FUNC_RULES_PROCESS); } @@ -233,11 +233,11 @@ void ShowFreeMem(const char *where) * Function call to all xdrv \*********************************************************************************************/ -boolean XdrvCall(byte Function) +bool XdrvCall(uint8_t Function) { - boolean result = false; + bool result = false; - for (byte x = 0; x < xdrv_present; x++) { + for (uint8_t x = 0; x < xdrv_present; x++) { // WifiAddDelayWhenDisconnected(); result = xdrv_func_ptr[x](Function); diff --git a/sonoff/xdsp_01_lcd.ino b/sonoff/xdsp_01_lcd.ino index 107bae676..0cfced507 100644 --- a/sonoff/xdsp_01_lcd.ino +++ b/sonoff/xdsp_01_lcd.ino @@ -97,7 +97,7 @@ void LcdDisplayOnOff(uint8_t on) #ifdef USE_DISPLAY_MODES1TO5 -void LcdCenter(byte row, char* txt) +void LcdCenter(uint8_t row, char* txt) { int offset; int len; @@ -112,9 +112,9 @@ void LcdCenter(byte row, char* txt) lcd->print(line); } -boolean LcdPrintLog(void) +bool LcdPrintLog(void) { - boolean result = false; + bool result = false; disp_refresh--; if (!disp_refresh) { @@ -125,7 +125,7 @@ boolean LcdPrintLog(void) if (txt != NULL) { uint8_t last_row = Settings.display_rows -1; - for (byte i = 0; i < last_row; i++) { + for (uint8_t i = 0; i < last_row; i++) { strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); lcd->setCursor(0, i); // Col 0, Row i lcd->print(disp_screen_buffer[i +1]); @@ -181,9 +181,9 @@ void LcdRefresh(void) // Every second * Interface \*********************************************************************************************/ -boolean Xdsp01(byte function) +bool Xdsp01(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { if (FUNC_DISPLAY_INIT_DRIVER == function) { diff --git a/sonoff/xdsp_02_ssd1306.ino b/sonoff/xdsp_02_ssd1306.ino index eb8f34701..e7952b65e 100644 --- a/sonoff/xdsp_02_ssd1306.ino +++ b/sonoff/xdsp_02_ssd1306.ino @@ -147,7 +147,7 @@ void Ssd1306PrintLog(void) oled->clearDisplay(); oled->setTextSize(Settings.display_size); oled->setCursor(0,0); - for (byte i = 0; i < last_row; i++) { + for (uint8_t i = 0; i < last_row; i++) { strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); oled->println(disp_screen_buffer[i]); } @@ -200,9 +200,9 @@ void Ssd1306Refresh(void) // Every second * Interface \*********************************************************************************************/ -boolean Xdsp02(byte function) +bool Xdsp02(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { if (FUNC_DISPLAY_INIT_DRIVER == function) { diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index 39c40ac39..8af7c50c2 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -47,14 +47,14 @@ uint8_t mtx_done = 0; void MatrixWrite(void) { - for (byte i = 0; i < mtx_matrices; i++) { + for (uint8_t i = 0; i < mtx_matrices; i++) { matrix[i]->writeDisplay(); } } void MatrixClear(void) { - for (byte i = 0; i < mtx_matrices; i++) { + for (uint8_t i = 0; i < mtx_matrices; i++) { matrix[i]->clear(); } MatrixWrite(); @@ -62,7 +62,7 @@ void MatrixClear(void) void MatrixFixed(char* txt) { - for (byte i = 0; i < mtx_matrices; i++) { + for (uint8_t i = 0; i < mtx_matrices; i++) { matrix[i]->clear(); matrix[i]->setCursor(-i *8, 0); matrix[i]->print(txt); @@ -77,7 +77,7 @@ void MatrixCenter(char* txt) int len = strlen(txt); offset = (len < 8) ? offset = ((mtx_matrices *8) - (len *6)) / 2 : 0; - for (byte i = 0; i < mtx_matrices; i++) { + for (uint8_t i = 0; i < mtx_matrices; i++) { matrix[i]->clear(); matrix[i]->setCursor(-(i *8)+offset, 0); matrix[i]->print(txt); @@ -102,7 +102,7 @@ void MatrixScrollLeft(char* txt, int loop) disp_refresh--; if (!disp_refresh) { disp_refresh = Settings.display_refresh; - for (byte i = 0; i < mtx_matrices; i++) { + for (uint8_t i = 0; i < mtx_matrices; i++) { matrix[i]->clear(); matrix[i]->setCursor(mtx_x - i *8, 0); matrix[i]->print(txt); @@ -145,9 +145,9 @@ void MatrixScrollUp(char* txt, int loop) words[wordcounter++] = p; p = strtok(NULL, separators); } - for (byte i = 0; i < mtx_matrices; i++) { + for (uint8_t i = 0; i < mtx_matrices; i++) { matrix[i]->clear(); - for (byte j = 0; j < wordcounter; j++) { + for (uint8_t j = 0; j < wordcounter; j++) { matrix[i]->setCursor(-i *8, mtx_y + (j *8)); matrix[i]->println(words[j]); } @@ -170,7 +170,7 @@ void MatrixScrollUp(char* txt, int loop) void MatrixInitMode(void) { - for (byte i = 0; i < mtx_matrices; i++) { + for (uint8_t i = 0; i < mtx_matrices; i++) { matrix[i]->setRotation(Settings.display_rotate); // 1 matrix[i]->setBrightness(Settings.display_dimmer); matrix[i]->blinkRate(0); // 0 - 3 @@ -327,9 +327,9 @@ void MatrixRefresh(void) // Every second * Interface \*********************************************************************************************/ -boolean Xdsp03(byte function) +bool Xdsp03(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { if (FUNC_DISPLAY_INIT_DRIVER == function) { diff --git a/sonoff/xdsp_04_ili9341.ino b/sonoff/xdsp_04_ili9341.ino index ba94eece2..6b6511c62 100644 --- a/sonoff/xdsp_04_ili9341.ino +++ b/sonoff/xdsp_04_ili9341.ino @@ -148,7 +148,7 @@ void Ili9341PrintLog(void) char* txt = DisplayLogBuffer('\370'); if (txt != NULL) { - byte size = Settings.display_size; + uint8_t size = Settings.display_size; uint16_t theight = size * TFT_FONT_HEIGTH; tft->setTextSize(size); @@ -167,7 +167,7 @@ void Ili9341PrintLog(void) tft_scroll = theight; // Start below header tft->setCursor(0, tft_scroll); - for (byte i = 0; i < last_row; i++) { + for (uint8_t i = 0; i < last_row; i++) { strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); // tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK); // Erase line tft->print(disp_screen_buffer[i]); @@ -222,9 +222,9 @@ void Ili9341Refresh(void) // Every second * Interface \*********************************************************************************************/ -boolean Xdsp04(byte function) +bool Xdsp04(uint8_t function) { - boolean result = false; + bool result = false; if (spi_flg) { if (FUNC_DISPLAY_INIT_DRIVER == function) { diff --git a/sonoff/xdsp_05_epaper_29.ino b/sonoff/xdsp_05_epaper_29.ino index 3904cb97f..50495a1db 100644 --- a/sonoff/xdsp_05_epaper_29.ino +++ b/sonoff/xdsp_05_epaper_29.ino @@ -165,6 +165,7 @@ void EpdDisplayFrame(void) { epd.SetFrameMemory(paint.GetImage(), 0, 0, paint.GetWidth(), paint.GetHeight()); epd.DisplayFrame(); + epd.Sleep(); } void EpdDrawStringAt(uint16_t x, uint16_t y, char *str, uint8_t color, uint8_t flag) @@ -202,7 +203,7 @@ void EpdPrintLog(void) char* txt = DisplayLogBuffer('\040'); if (txt != NULL) { - byte size = Settings.display_size; + uint8_t size = Settings.display_size; uint16_t theight = size * EPD_FONT_HEIGTH; EpdSetFont(size); @@ -210,7 +211,7 @@ void EpdPrintLog(void) // epd_scroll = theight; // Start below header epd_scroll = 0; // Start at top with no header - for (byte i = 0; i < last_row; i++) { + for (uint8_t i = 0; i < last_row; i++) { strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); EpdDrawStringAt(0, epd_scroll, disp_screen_buffer[i], COLORED, 0); epd_scroll += theight; @@ -266,9 +267,9 @@ void EpdRefresh(void) // Every second * Interface \*********************************************************************************************/ -boolean Xdsp05(byte function) +bool Xdsp05(uint8_t function) { - boolean result = false; + bool result = false; if (spi_flg || soft_spi_flg) { if (FUNC_DISPLAY_INIT_DRIVER == function) { diff --git a/sonoff/xdsp_interface.ino b/sonoff/xdsp_interface.ino index b0d760a37..1f7becf88 100644 --- a/sonoff/xdsp_interface.ino +++ b/sonoff/xdsp_interface.ino @@ -20,9 +20,9 @@ #ifdef USE_DISPLAY #ifdef XFUNC_PTR_IN_ROM -boolean (* const xdsp_func_ptr[])(byte) PROGMEM = { // Display Function Pointers +bool (* const xdsp_func_ptr[])(uint8_t) PROGMEM = { // Display Function Pointers #else -boolean (* const xdsp_func_ptr[])(byte) = { // Display Function Pointers +bool (* const xdsp_func_ptr[])(uint8_t) = { // Display Function Pointers #endif #ifdef XDSP_01 @@ -119,11 +119,11 @@ uint8_t XdspPresent(void) return xdsp_present; } -boolean XdspCall(byte Function) +bool XdspCall(uint8_t Function) { - boolean result = false; + bool result = false; - for (byte x = 0; x < xdsp_present; x++) { + for (uint8_t x = 0; x < xdsp_present; x++) { result = xdsp_func_ptr[x](Function); if (result && (FUNC_DISPLAY_MODEL == Function)) { diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index ddfb847b9..778b49b36 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -62,11 +62,11 @@ unsigned long hlw_power_ratio = 0; unsigned long hlw_voltage_ratio = 0; unsigned long hlw_current_ratio = 0; -byte hlw_select_ui_flag = 0; -byte hlw_ui_flag = 1; -byte hlw_model_type = 0; -byte hlw_load_off = 1; -byte hlw_cf1_timer = 0; +uint8_t hlw_select_ui_flag = 0; +uint8_t hlw_ui_flag = 1; +uint8_t hlw_model_type = 0; +uint8_t hlw_load_off = 1; +uint8_t hlw_cf1_timer = 0; #ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception void HlwCfInterrupt(void) ICACHE_RAM_ATTR; @@ -246,9 +246,9 @@ void HlwDrvInit(void) } } -boolean HlwCommand(void) +bool HlwCommand(void) { - boolean serviced = true; + bool serviced = true; if ((CMND_POWERCAL == energy_command_code) || (CMND_VOLTAGECAL == energy_command_code) || (CMND_CURRENTCAL == energy_command_code)) { // Service in xdrv_03_energy.ino @@ -277,7 +277,7 @@ boolean HlwCommand(void) * Interface \*********************************************************************************************/ -int Xnrg01(byte function) +int Xnrg01(uint8_t function) { int result = 0; diff --git a/sonoff/xnrg_02_cse7766.ino b/sonoff/xnrg_02_cse7766.ino index 2dc6b2674..cbc2b9bc2 100644 --- a/sonoff/xnrg_02_cse7766.ino +++ b/sonoff/xnrg_02_cse7766.ino @@ -137,7 +137,7 @@ bool CseSerialInput(void) AddLogSerial(LOG_LEVEL_DEBUG_MORE); uint8_t checksum = 0; - for (byte i = 2; i < 23; i++) { checksum += serial_in_buffer[i]; } + for (uint8_t i = 2; i < 23; i++) { checksum += serial_in_buffer[i]; } if (checksum == serial_in_buffer[23]) { CseReceived(); cse_receive_flag = 0; @@ -199,9 +199,9 @@ void CseDrvInit(void) } } -boolean CseCommand(void) +bool CseCommand(void) { - boolean serviced = true; + bool serviced = true; if (CMND_POWERSET == energy_command_code) { if (XdrvMailbox.data_len && power_cycle) { @@ -227,7 +227,7 @@ boolean CseCommand(void) * Interface \*********************************************************************************************/ -int Xnrg02(byte function) +int Xnrg02(uint8_t function) { int result = 0; diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index 34bff43fe..e0b6327bd 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -226,7 +226,7 @@ void PzemDrvInit(void) * Interface \*********************************************************************************************/ -int Xnrg03(byte function) +int Xnrg03(uint8_t function) { int result = 0; diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index 1ff04fb7d..a528d448f 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -112,7 +112,7 @@ uint8_t McpChecksum(uint8_t *data) uint8_t offset = 0; uint8_t len = data[1] -1; - for (byte i = offset; i < len; i++) { checksum += data[i]; } + for (uint8_t i = offset; i < len; i++) { checksum += data[i]; } return checksum; } @@ -121,7 +121,7 @@ unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size) unsigned long result = 0; unsigned long pow = 1; - for (byte i = 0; i < size; i++) { + for (uint8_t i = 0; i < size; i++) { result = result + (uint8_t)data[offset + i] * pow; pow = pow * 256; } @@ -130,7 +130,7 @@ unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size) void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size) { - for (byte i = 0; i < size; i++) { + for (uint8_t i = 0; i < size; i++) { data[offset + i] = ((value >> (i * 8)) & 0xFF); } } @@ -145,7 +145,7 @@ void McpSend(uint8_t *data) // AddLogBuffer(LOG_LEVEL_DEBUG_MORE, data, data[1]); - for (byte i = 0; i < data[1]; i++) { + for (uint8_t i = 0; i < data[1]; i++) { Serial.write(data[i]); } } @@ -562,9 +562,9 @@ void McpDrvInit(void) } } -boolean McpCommand(void) +bool McpCommand(void) { - boolean serviced = true; + bool serviced = true; unsigned long value = 0; if (CMND_POWERSET == energy_command_code) { @@ -616,7 +616,7 @@ boolean McpCommand(void) * Interface \*********************************************************************************************/ -int Xnrg04(byte function) +int Xnrg04(uint8_t function) { int result = 0; diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index f01ebad3e..375b2e2cc 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -104,7 +104,7 @@ void PzemAcDrvInit(void) * Interface \*********************************************************************************************/ -int Xnrg05(byte function) +int Xnrg05(uint8_t function) { int result = 0; diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index 536cb4b97..1c3713c8f 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -103,7 +103,7 @@ void PzemDcDrvInit(void) * Interface \*********************************************************************************************/ -int Xnrg06(byte function) +int Xnrg06(uint8_t function) { int result = 0; diff --git a/sonoff/xnrg_interface.ino b/sonoff/xnrg_interface.ino index 0d3953398..61ff34e24 100644 --- a/sonoff/xnrg_interface.ino +++ b/sonoff/xnrg_interface.ino @@ -20,9 +20,9 @@ #ifdef USE_ENERGY_SENSOR #ifdef XFUNC_PTR_IN_ROM -int (* const xnrg_func_ptr[])(byte) PROGMEM = { // Energy driver Function Pointers +int (* const xnrg_func_ptr[])(uint8_t) PROGMEM = { // Energy driver Function Pointers #else -int (* const xnrg_func_ptr[])(byte) = { // Energy driver Function Pointers +int (* const xnrg_func_ptr[])(uint8_t) = { // Energy driver Function Pointers #endif #ifdef XNRG_01 @@ -92,11 +92,11 @@ int (* const xnrg_func_ptr[])(byte) = { // Energy driver Function Pointers const uint8_t xnrg_present = sizeof(xnrg_func_ptr) / sizeof(xnrg_func_ptr[0]); // Number of drivers found -int XnrgCall(byte Function) +int XnrgCall(uint8_t Function) { int result = 0; - for (byte x = 0; x < xnrg_present; x++) { + for (uint8_t x = 0; x < xnrg_present; x++) { result = xnrg_func_ptr[x](Function); if (result && ((FUNC_SERIAL == Function) || diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 156a95770..ad3bdbef5 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -31,7 +31,7 @@ #include Ticker TickerMSearch; -boolean udp_connected = false; +bool udp_connected = false; char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP packet IPAddress ipMulticast(239,255,255,250); // Simple Service Discovery Protocol (SSDP) @@ -197,7 +197,7 @@ void HueRespondToMSearch(void) * Belkin WeMo and Philips Hue bridge UDP multicast support \*********************************************************************************************/ -boolean UdpDisconnect(void) +bool UdpDisconnect(void) { if (udp_connected) { WiFiUDP::stopAll(); @@ -207,7 +207,7 @@ boolean UdpDisconnect(void) return udp_connected; } -boolean UdpConnect(void) +bool UdpConnect(void) { if (!udp_connected) { if (PortUdp.beginMulticast(WiFi.localIP(), ipMulticast, port_multicast)) { @@ -302,7 +302,7 @@ const char WEMO_EVENTSERVICE_XML[] PROGMEM = "" "" "BinaryState" - "Boolean" + "bool" "0" "" "" @@ -564,7 +564,7 @@ void HueConfig(String *path) bool g_gotct = false; -void HueLightStatus1(byte device, String *response) +void HueLightStatus1(uint8_t device, String *response) { float hue = 0; float sat = 0; @@ -584,7 +584,7 @@ void HueLightStatus1(byte device, String *response) response->replace("{m}", g_gotct?"ct":"hs"); } -void HueLightStatus2(byte device, String *response) +void HueLightStatus2(uint8_t device, String *response) { *response += FPSTR(HUE_LIGHTS_STATUS_JSON2); response->replace("{j1", Settings.friendlyname[device-1]); diff --git a/sonoff/xplg_ws2812.ino b/sonoff/xplg_ws2812.ino index 1d66558d6..ab4ba1c35 100644 --- a/sonoff/xplg_ws2812.ino +++ b/sonoff/xplg_ws2812.ino @@ -172,7 +172,7 @@ void Ws2812Clock(void) Ws2812UpdateHand((RtcTime.minute * 1000) / clksize, WS_MINUTE); Ws2812UpdateHand(((RtcTime.hour % 12) * (5000 / clksize)) + ((RtcTime.minute * 1000) / (12 * clksize)), WS_HOUR); if (Settings.ws_color[WS_MARKER][WS_RED] + Settings.ws_color[WS_MARKER][WS_GREEN] + Settings.ws_color[WS_MARKER][WS_BLUE]) { - for (byte i = 0; i < 12; i++) { + for (uint8_t i = 0; i < 12; i++) { Ws2812UpdateHand((i * 5000) / clksize, WS_MARKER); } } @@ -395,7 +395,7 @@ char* Ws2812GetColor(uint16_t led, char* scolor) sl_ledcolor[1] = lcolor.G; sl_ledcolor[2] = lcolor.B; scolor[0] = '\0'; - for (byte i = 0; i < light_subtype; i++) { + for (uint8_t i = 0; i < light_subtype; i++) { if (Settings.flag.decimal_text) { snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", sl_ledcolor[i]); } else { diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index 2b031f20e..d62885cc5 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -25,7 +25,7 @@ unsigned long last_counter_timer[MAX_COUNTERS]; // Last counter time in micro seconds -void CounterUpdate(byte index) +void CounterUpdate(uint8_t index) { unsigned long counter_debounce_time = micros() - last_counter_timer[index -1]; if (counter_debounce_time > Settings.pulse_counter_debounce * 1000) { @@ -65,7 +65,7 @@ void CounterUpdate4(void) void CounterSaveState(void) { - for (byte i = 0; i < MAX_COUNTERS; i++) { + for (uint8_t i = 0; i < MAX_COUNTERS; i++) { if (pin[GPIO_CNTR1 +i] < 99) { Settings.pulse_counter[i] = RtcSettings.pulse_counter[i]; } @@ -77,7 +77,7 @@ void CounterInit(void) typedef void (*function) () ; function counter_callbacks[] = { CounterUpdate1, CounterUpdate2, CounterUpdate3, CounterUpdate4 }; - for (byte i = 0; i < MAX_COUNTERS; i++) { + for (uint8_t i = 0; i < MAX_COUNTERS; i++) { if (pin[GPIO_CNTR1 +i] < 99) { pinMode(pin[GPIO_CNTR1 +i], bitRead(counter_no_pullup, i) ? INPUT : INPUT_PULLUP); attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); @@ -90,13 +90,13 @@ const char HTTP_SNS_COUNTER[] PROGMEM = "%s{s}" D_COUNTER "%d{m}%s%s{e}"; // {s} = #endif // USE_WEBSERVER -void CounterShow(boolean json) +void CounterShow(bool json) { char stemp[10]; - byte dsxflg = 0; - byte header = 0; - for (byte i = 0; i < MAX_COUNTERS; i++) { + uint8_t dsxflg = 0; + uint8_t header = 0; + for (uint8_t i = 0; i < MAX_COUNTERS; i++) { if (pin[GPIO_CNTR1 +i] < 99) { char counter[33]; if (bitRead(Settings.pulse_counter_type, i)) { @@ -141,9 +141,9 @@ void CounterShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns01(byte function) +bool Xsns01(uint8_t function) { - boolean result = false; + bool result = false; switch (function) { case FUNC_INIT: diff --git a/sonoff/xsns_02_analog.ino b/sonoff/xsns_02_analog.ino index e72641a85..e75160697 100644 --- a/sonoff/xsns_02_analog.ino +++ b/sonoff/xsns_02_analog.ino @@ -29,7 +29,7 @@ uint16_t adc_last_value = 0; uint16_t AdcRead(void) { uint16_t analog = 0; - for (byte i = 0; i < 32; i++) { + for (uint8_t i = 0; i < 32; i++) { analog += analogRead(A0); delay(1); } @@ -50,7 +50,7 @@ void AdcEvery250ms(void) } #endif // USE_RULES -void AdcShow(boolean json) +void AdcShow(bool json) { uint16_t analog = AdcRead(); @@ -67,9 +67,9 @@ void AdcShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns02(byte function) +bool Xsns02(uint8_t function) { - boolean result = false; + bool result = false; if (my_module_flag.adc0) { switch (function) { diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index ef72a01e6..5f3695292 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -87,7 +87,7 @@ void SonoffScSerialInput(char *rcvstat) value[i++] = atoi(str); } if (value[0] > 0) { - for (byte i = 0; i < 5; i++) { + for (uint8_t i = 0; i < 5; i++) { sc_value[i] = value[i]; } sc_value[2] = (11 - sc_value[2]) * 10; // Invert light level @@ -110,7 +110,7 @@ const char HTTP_SNS_SCPLUS[] PROGMEM = "%s{s}" D_LIGHT "{m}%d%%{e}{s}" D_NOISE "{m}%d%%{e}{s}" D_AIR_QUALITY "{m}%d%%{e}"; // {s} = #endif // USE_WEBSERVER -void SonoffScShow(boolean json) +void SonoffScShow(bool json) { if (sc_value[0] > 0) { float t = ConvertTemp(sc_value[1]); @@ -154,9 +154,9 @@ void SonoffScShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns04(byte function) +bool Xsns04(uint8_t function) { - boolean result = false; + bool result = false; if (SONOFF_SC == Settings.module) { switch (function) { diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index 713c10a81..f5d4bd03d 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -120,7 +120,7 @@ uint8_t OneWireRead(void) return r; } -boolean OneWireCrc8(uint8_t *addr) +bool OneWireCrc8(uint8_t *addr) { uint8_t crc = 0; uint8_t len = 8; @@ -149,7 +149,7 @@ void Ds18b20Convert(void) // delay(750); // 750ms should be enough for 12bit conv } -boolean Ds18b20Read(void) +bool Ds18b20Read(void) { uint8_t data[9]; int8_t sign = 1; @@ -199,7 +199,7 @@ void Ds18b20EverySecond(void) } } -void Ds18b20Show(boolean json) +void Ds18b20Show(bool json) { if (ds18b20_valid) { // Check for valid temperature char temperature[33]; @@ -228,9 +228,9 @@ void Ds18b20Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns05(byte function) +bool Xsns05(uint8_t function) { - boolean result = false; + bool result = false; if (pin[GPIO_DSB] < 99) { switch (function) { diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index c2367abe1..d8cbd7189 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -233,7 +233,7 @@ uint8_t OneWireSearch(uint8_t *newAddr) return search_result; } -boolean OneWireCrc8(uint8_t *addr) +bool OneWireCrc8(uint8_t *addr) { uint8_t crc = 0; uint8_t len = 8; @@ -424,7 +424,7 @@ void Ds18x20EverySecond(void) } } -void Ds18x20Show(boolean json) +void Ds18x20Show(bool json) { for (uint8_t i = 0; i < ds18x20_sensors; i++) { uint8_t index = ds18x20_sensor[i].index; @@ -440,7 +440,7 @@ void Ds18x20Show(boolean json) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, ds18x20_types, temperature); } else { char address[17]; - for (byte j = 0; j < 6; j++) { + for (uint8_t j = 0; j < 6; j++) { sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); // Skip sensor type and crc } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, ds18x20_types, address, temperature); @@ -468,9 +468,9 @@ void Ds18x20Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns05(byte function) +bool Xsns05(uint8_t function) { - boolean result = false; + bool result = false; if (pin[GPIO_DSB] < 99) { switch (function) { diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index 8e61aef84..3f6474044 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -65,11 +65,11 @@ void Ds18x20Search(void) num_sensors++; } } - for (byte i = 0; i < num_sensors; i++) { + for (uint8_t i = 0; i < num_sensors; i++) { ds18x20_index[i] = i; } - for (byte i = 0; i < num_sensors; i++) { - for (byte j = i + 1; j < num_sensors; j++) { + for (uint8_t i = 0; i < num_sensors; i++) { + for (uint8_t 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]); } @@ -87,7 +87,7 @@ String Ds18x20Addresses(uint8_t sensor) { char address[20]; - for (byte i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { sprintf(address+2*i, "%02X", ds18x20_address[ds18x20_index[sensor]][i]); } return String(address); @@ -101,9 +101,9 @@ void Ds18x20Convert(void) // delay(750); // 750ms should be enough for 12bit conv } -boolean Ds18x20Read(uint8_t sensor, float &t) +bool Ds18x20Read(uint8_t sensor, float &t) { - byte data[12]; + uint8_t data[12]; int8_t sign = 1; uint16_t temp12 = 0; int16_t temp14 = 0; @@ -116,7 +116,7 @@ boolean Ds18x20Read(uint8_t sensor, float &t) ds->select(ds18x20_address[ds18x20_index[sensor]]); ds->write(W1_READ_SCRATCHPAD); // Read Scratchpad - for (byte i = 0; i < 9; i++) { + for (uint8_t i = 0; i < 9; i++) { data[i] = ds->read(); } if (OneWire::crc8(data, 8) == data[8]) { @@ -168,13 +168,13 @@ void Ds18x20Type(uint8_t sensor) } } -void Ds18x20Show(boolean json) +void Ds18x20Show(bool json) { char stemp[10]; float t; - byte dsxflg = 0; - for (byte i = 0; i < Ds18x20Sensors(); i++) { + uint8_t dsxflg = 0; + for (uint8_t i = 0; i < Ds18x20Sensors(); i++) { if (Ds18x20Read(i, t)) { // Check if read failed Ds18x20Type(i); char temperature[33]; @@ -220,9 +220,9 @@ void Ds18x20Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns05(byte function) +bool Xsns05(uint8_t function) { - boolean result = false; + bool result = false; if (pin[GPIO_DSB] < 99) { switch (function) { diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index 2178e2617..47993bea9 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -33,11 +33,11 @@ uint32_t dht_max_cycles; uint8_t dht_data[5]; -byte dht_sensors = 0; +uint8_t dht_sensors = 0; struct DHTSTRUCT { - byte pin; - byte type; + uint8_t pin; + uint8_t type; char stype[12]; uint32_t lastreadtime; uint8_t lastresult; @@ -47,12 +47,12 @@ struct DHTSTRUCT { void DhtReadPrep(void) { - for (byte i = 0; i < dht_sensors; i++) { + for (uint8_t i = 0; i < dht_sensors; i++) { digitalWrite(Dht[i].pin, HIGH); } } -int32_t DhtExpectPulse(byte sensor, bool level) +int32_t DhtExpectPulse(uint8_t sensor, bool level) { int32_t count = 0; @@ -64,7 +64,7 @@ int32_t DhtExpectPulse(byte sensor, bool level) return count; } -boolean DhtRead(byte sensor) +bool DhtRead(uint8_t sensor) { int32_t cycles[80]; uint8_t error = 0; @@ -134,7 +134,7 @@ boolean DhtRead(byte sensor) return true; } -void DhtReadTempHum(byte sensor) +void DhtReadTempHum(uint8_t sensor) { if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { // Reset after 8 misses Dht[sensor].t = NAN; @@ -162,9 +162,9 @@ void DhtReadTempHum(byte sensor) } } -boolean DhtSetup(byte pin, byte type) +bool DhtSetup(uint8_t pin, uint8_t type) { - boolean success = false; + bool success = false; if (dht_sensors < DHT_MAX_SENSORS) { Dht[dht_sensors].pin = pin; @@ -181,7 +181,7 @@ void DhtInit(void) { dht_max_cycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for reading pulses from DHT sensor. - for (byte i = 0; i < dht_sensors; i++) { + for (uint8_t i = 0; i < dht_sensors; i++) { pinMode(Dht[i].pin, INPUT_PULLUP); Dht[i].lastreadtime = 0; Dht[i].lastresult = 0; @@ -198,16 +198,16 @@ void DhtEverySecond(void) // <1mS DhtReadPrep(); } else { - for (byte i = 0; i < dht_sensors; i++) { + for (uint8_t i = 0; i < dht_sensors; i++) { // DHT11 and AM2301 25mS per sensor, SI7021 5mS per sensor DhtReadTempHum(i); } } } -void DhtShow(boolean json) +void DhtShow(bool json) { - for (byte i = 0; i < dht_sensors; i++) { + for (uint8_t i = 0; i < dht_sensors; i++) { char temperature[33]; dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); char humidity[33]; @@ -239,9 +239,9 @@ void DhtShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns06(byte function) +bool Xsns06(uint8_t function) { - boolean result = false; + bool result = false; if (dht_flg) { switch (function) { diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index 3e1452ab6..51351bdf5 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -44,21 +44,21 @@ uint8_t sht_valid = 0; float sht_temperature = 0; float sht_humidity = 0; -boolean ShtReset(void) +bool ShtReset(void) { pinMode(sht_sda_pin, INPUT_PULLUP); pinMode(sht_scl_pin, OUTPUT); delay(11); - for (byte i = 0; i < 9; i++) { + for (uint8_t i = 0; i < 9; i++) { digitalWrite(sht_scl_pin, HIGH); digitalWrite(sht_scl_pin, LOW); } - boolean success = ShtSendCommand(SHT1X_CMD_SOFT_RESET); + bool success = ShtSendCommand(SHT1X_CMD_SOFT_RESET); delay(11); return success; } -boolean ShtSendCommand(const byte cmd) +bool ShtSendCommand(const uint8_t cmd) { pinMode(sht_sda_pin, OUTPUT); // Transmission Start sequence @@ -72,7 +72,7 @@ boolean ShtSendCommand(const byte cmd) // Send the command (address must be 000b) shiftOut(sht_sda_pin, sht_scl_pin, MSBFIRST, cmd); // Wait for ACK - boolean ackerror = false; + bool ackerror = false; digitalWrite(sht_scl_pin, HIGH); pinMode(sht_sda_pin, INPUT_PULLUP); if (digitalRead(sht_sda_pin) != LOW) { @@ -90,10 +90,10 @@ boolean ShtSendCommand(const byte cmd) return (!ackerror); } -boolean ShtAwaitResult(void) +bool ShtAwaitResult(void) { // Maximum 320ms for 14 bit measurement - for (byte i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { if (LOW == digitalRead(sht_sda_pin)) { return true; } @@ -125,7 +125,7 @@ int ShtReadData(void) return val; } -boolean ShtRead(void) +bool ShtRead(void) { if (sht_valid) { sht_valid--; } if (!ShtReset()) { return false; } @@ -185,7 +185,7 @@ void ShtEverySecond(void) } } -void ShtShow(boolean json) +void ShtShow(bool json) { if (sht_valid) { char temperature[33]; @@ -219,9 +219,9 @@ void ShtShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns07(byte function) +bool Xsns07(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index 30040f7e1..2120129de 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -140,7 +140,7 @@ void HtuInit(void) HtuSetResolution(HTU21_RES_RH12_T14); } -boolean HtuRead(void) +bool HtuRead(void) { uint8_t checksum = 0; uint16_t sensorval = 0; @@ -246,7 +246,7 @@ void HtuEverySecond(void) } } -void HtuShow(boolean json) +void HtuShow(bool json) { if (htu_valid) { char temperature[33]; @@ -280,9 +280,9 @@ void HtuShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns08(byte function) +bool Xsns08(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index 6c7bbc31b..60e43c09c 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -101,7 +101,7 @@ typedef struct { bmp180_cal_data_t *bmp180_cal_data = NULL; -boolean Bmp180Calibration(uint8_t bmp_idx) +bool Bmp180Calibration(uint8_t bmp_idx) { if (!bmp180_cal_data) { bmp180_cal_data = (bmp180_cal_data_t*)malloc(BMP_MAX_SENSORS * sizeof(bmp180_cal_data_t)); @@ -246,7 +246,7 @@ typedef struct { Bme280CalibrationData_t *Bme280CalibrationData = NULL; -boolean Bmx280Calibrate(uint8_t bmp_idx) +bool Bmx280Calibrate(uint8_t bmp_idx) { // if (I2cRead8(bmp_address, BMP_REGISTER_CHIPID) != BME280_CHIPID) return false; @@ -351,7 +351,7 @@ static void BmeDelayMs(uint32_t ms) delay(ms); } -boolean Bme680Init(uint8_t bmp_idx) +bool Bme680Init(uint8_t bmp_idx) { if (!gas_sensor) { gas_sensor = (bme680_dev*)malloc(BMP_MAX_SENSORS * sizeof(bme680_dev)); @@ -455,14 +455,14 @@ void BmpDetect(void) if (!bmp_sensors) { return; } memset(bmp_sensors, 0, bmp_sensor_size); // Init defaults to 0 - for (byte i = 0; i < BMP_MAX_SENSORS; i++) { + for (uint8_t i = 0; i < BMP_MAX_SENSORS; i++) { uint8_t bmp_type = I2cRead8(bmp_addresses[i], BMP_REGISTER_CHIPID); if (bmp_type) { bmp_sensors[bmp_count].bmp_address = bmp_addresses[i]; bmp_sensors[bmp_count].bmp_type = bmp_type; bmp_sensors[bmp_count].bmp_model = 0; - boolean success = false; + bool success = false; switch (bmp_type) { case BMP180_CHIPID: success = Bmp180Calibration(bmp_count); @@ -494,7 +494,7 @@ void BmpRead(void) { if (!bmp_sensors) { return; } - for (byte bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + for (uint8_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { switch (bmp_sensors[bmp_idx].bmp_type) { case BMP180_CHIPID: Bmp180Read(bmp_idx); @@ -525,11 +525,11 @@ void BmpEverySecond(void) } } -void BmpShow(boolean json) +void BmpShow(bool json) { if (!bmp_sensors) { return; } - for (byte bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + for (uint8_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { if (bmp_sensors[bmp_idx].bmp_type) { float bmp_sealevel = 0.0; if (bmp_sensors[bmp_idx].bmp_pressure != 0.0) { @@ -621,9 +621,9 @@ void BmpShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns09(byte function) +bool Xsns09(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_10_bh1750.ino b/sonoff/xsns_10_bh1750.ino index 23775abb1..5dd791397 100644 --- a/sonoff/xsns_10_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -44,8 +44,8 @@ bool Bh1750Read(void) if (bh1750_valid) { bh1750_valid--; } if (2 != Wire.requestFrom(bh1750_address, (uint8_t)2)) { return false; } - byte msb = Wire.read(); - byte lsb = Wire.read(); + uint8_t msb = Wire.read(); + uint8_t lsb = Wire.read(); bh1750_illuminance = ((msb << 8) | lsb) / 1.2; bh1750_valid = SENSOR_MAX_MISS; return true; @@ -59,7 +59,7 @@ void Bh1750Detect(void) return; } - for (byte i = 0; i < sizeof(bh1750_addresses); i++) { + for (uint8_t i = 0; i < sizeof(bh1750_addresses); i++) { bh1750_address = bh1750_addresses[i]; Wire.beginTransmission(bh1750_address); Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE); @@ -89,7 +89,7 @@ void Bh1750EverySecond(void) } } -void Bh1750Show(boolean json) +void Bh1750Show(bool json) { if (bh1750_valid) { if (json) { @@ -111,9 +111,9 @@ void Bh1750Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns10(byte function) +bool Xsns10(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index b2512c56b..276b90d9f 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -187,7 +187,7 @@ void Veml6070EverySecond(void) /********************************************************************************************/ -void Veml6070ModeCmd(boolean mode_cmd) +void Veml6070ModeCmd(bool mode_cmd) { // mode_cmd 1 = on = 1[ms] // mode_cmd 0 = off = 2[ms] @@ -270,7 +270,7 @@ double Veml6070UvPower(double uvrisk) /********************************************************************************************/ -void Veml6070Show(boolean json) +void Veml6070Show(bool json) { if (veml6070_type) { // convert double values to string @@ -307,9 +307,9 @@ void Veml6070Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns11(byte function) +bool Xsns11(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index 7ba59f2bb..f75baa3e8 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -165,7 +165,7 @@ void Ads1115Detect(void) return; } - for (byte i = 0; i < sizeof(ads1115_addresses); i++) { + for (uint8_t i = 0; i < sizeof(ads1115_addresses); i++) { ads1115_address = ads1115_addresses[i]; if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT)) { Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); @@ -177,13 +177,13 @@ void Ads1115Detect(void) } } -void Ads1115Show(boolean json) +void Ads1115Show(bool json) { if (ads1115_type) { char stemp[10]; - byte dsxflg = 0; - for (byte i = 0; i < 4; i++) { + uint8_t dsxflg = 0; + for (uint8_t i = 0; i < 4; i++) { int16_t adc_value = Ads1115GetConversion(i); if (json) { @@ -212,9 +212,9 @@ void Ads1115Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns12(byte function) +bool Xsns12(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/sonoff/xsns_12_ads1115_i2cdev.ino index 4de6650ac..2e0bd0ab7 100644 --- a/sonoff/xsns_12_ads1115_i2cdev.ino +++ b/sonoff/xsns_12_ads1115_i2cdev.ino @@ -55,7 +55,7 @@ uint8_t ads1115_addresses[] = { ADS1115_ADDRESS_ADDR_SCL // address pin tied to SCL pin }; -int16_t Ads1115GetConversion(byte channel) +int16_t Ads1115GetConversion(uint8_t channel) { switch (channel) { case 0: @@ -81,7 +81,7 @@ void Ads1115Detect(void) return; } - for (byte i = 0; i < sizeof(ads1115_addresses); i++) { + for (uint8_t i = 0; i < sizeof(ads1115_addresses); i++) { ads1115_address = ads1115_addresses[i]; ADS1115 adc0(ads1115_address); if (adc0.testConnection()) { @@ -97,13 +97,13 @@ void Ads1115Detect(void) } } -void Ads1115Show(boolean json) +void Ads1115Show(bool json) { if (ads1115_type) { char stemp[10]; - byte dsxflg = 0; - for (byte i = 0; i < 4; i++) { + uint8_t dsxflg = 0; + for (uint8_t i = 0; i < 4; i++) { int16_t adc_value = Ads1115GetConversion(i); if (json) { @@ -132,9 +132,9 @@ void Ads1115Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns12(byte function) +bool Xsns12(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index 2b812f05d..6b25e8bac 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -177,7 +177,7 @@ bool Ina219Read(void) bool Ina219CommandSensor(void) { - boolean serviced = true; + bool serviced = true; if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { Settings.ina219_mode = XdrvMailbox.payload; @@ -194,7 +194,7 @@ void Ina219Detect(void) { if (ina219_type) { return; } - for (byte i = 0; i < sizeof(ina219_addresses); i++) { + for (uint8_t i = 0; i < sizeof(ina219_addresses); i++) { ina219_address = ina219_addresses[i]; if (Ina219SetCalibration(Settings.ina219_mode)) { ina219_type = 1; @@ -229,7 +229,7 @@ const char HTTP_SNS_INA219_DATA[] PROGMEM = "%s" "{s}INA219 " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; #endif // USE_WEBSERVER -void Ina219Show(boolean json) +void Ina219Show(bool json) { if (ina219_valid) { float fpower = ina219_voltage * ina219_current; @@ -261,9 +261,9 @@ void Ina219Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns13(byte function) +bool Xsns13(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_14_sht3x.ino b/sonoff/xsns_14_sht3x.ino index 25901d934..531e93ceb 100755 --- a/sonoff/xsns_14_sht3x.ino +++ b/sonoff/xsns_14_sht3x.ino @@ -82,7 +82,7 @@ void Sht3xDetect(void) float t; float h; - for (byte i = 0; i < SHT3X_MAX_SENSORS; i++) { + for (uint8_t i = 0; i < SHT3X_MAX_SENSORS; i++) { if (Sht3xRead(t, h, sht3x_addresses[i])) { sht3x_sensors[sht3x_count].address = sht3x_addresses[i]; GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), i, kShtTypes); @@ -93,13 +93,13 @@ void Sht3xDetect(void) } } -void Sht3xShow(boolean json) +void Sht3xShow(bool json) { if (sht3x_count) { float t; float h; char types[11]; - for (byte i = 0; i < sht3x_count; i++) { + for (uint8_t i = 0; i < sht3x_count; i++) { if (Sht3xRead(t, h, sht3x_sensors[i].address)) { if (0 == i) { SetGlobalValues(t, h); } @@ -140,9 +140,9 @@ void Sht3xShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns14(byte function) +bool Xsns14(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 7585ff3d9..509f9e0bc 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -98,17 +98,17 @@ uint8_t mhz_state = 0; /*********************************************************************************************/ -byte MhzCalculateChecksum(byte *array) +uint8_t MhzCalculateChecksum(uint8_t *array) { - byte checksum = 0; - for (byte i = 1; i < 8; i++) { + uint8_t checksum = 0; + for (uint8_t i = 1; i < 8; i++) { checksum += array[i]; } checksum = 255 - checksum; return (checksum +1); } -size_t MhzSendCmd(byte command_id) +size_t MhzSendCmd(uint8_t command_id) { uint8_t mhz_send[9] = { 0 }; @@ -204,7 +204,7 @@ void MhzEverySecond(void) return; } - byte crc = MhzCalculateChecksum(mhz_response); + uint8_t crc = MhzCalculateChecksum(mhz_response); if (mhz_response[8] != crc) { // AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "MH-Z19 crc error")); return; @@ -270,7 +270,7 @@ void MhzEverySecond(void) bool MhzCommandSensor(void) { - boolean serviced = true; + bool serviced = true; switch (XdrvMailbox.payload) { case 2: @@ -319,7 +319,7 @@ void MhzInit(void) } } -void MhzShow(boolean json) +void MhzShow(bool json) { char types[7] = "MHZ19B"; // MHZ19B for legacy reasons. Prefered is MHZ19 char temperature[33]; @@ -344,9 +344,9 @@ void MhzShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns15(byte function) +bool Xsns15(uint8_t function) { - boolean result = false; + bool result = false; if (mhz_type) { switch (function) { diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index 07c95941e..0dbaf7141 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -97,7 +97,7 @@ const char HTTP_SNS_TSL2561[] PROGMEM = "%s{s}TSL2561 " D_ILLUMINANCE "{m}%u.%03u " D_UNIT_LUX "{e}"; // {s} = #endif // USE_WEBSERVER -void Tsl2561Show(boolean json) +void Tsl2561Show(bool json) { if (tsl2561_valid) { if (json) { @@ -118,9 +118,9 @@ void Tsl2561Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns16(byte function) +bool Xsns16(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_17_senseair.ino b/sonoff/xsns_17_senseair.ino index 375d705b4..4758b454b 100644 --- a/sonoff/xsns_17_senseair.ino +++ b/sonoff/xsns_17_senseair.ino @@ -145,7 +145,7 @@ void SenseairInit(void) } } -void SenseairShow(boolean json) +void SenseairShow(bool json) { char temperature[33]; dtostrfd(senseair_temperature, Settings.flag2.temperature_resolution, temperature); @@ -177,9 +177,9 @@ void SenseairShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns17(byte function) +bool Xsns17(uint8_t function) { - boolean result = false; + bool result = false; if (senseair_type) { switch (function) { diff --git a/sonoff/xsns_18_pms5003.ino b/sonoff/xsns_18_pms5003.ino index 1f048134a..82959ff88 100644 --- a/sonoff/xsns_18_pms5003.ino +++ b/sonoff/xsns_18_pms5003.ino @@ -45,7 +45,7 @@ struct pms5003data { /*********************************************************************************************/ -boolean PmsReadData(void) +bool PmsReadData(void) { if (! PmsSerial->available()) { return false; @@ -128,7 +128,7 @@ const char HTTP_PMS5003_SNS[] PROGMEM = "%s" "{s}PMS5003 " D_PARTICALS_BEYOND " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"; // {s} = #endif // USE_WEBSERVER -void PmsShow(boolean json) +void PmsShow(bool json) { if (pms_valid) { if (json) { @@ -158,9 +158,9 @@ void PmsShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns18(byte function) +bool Xsns18(uint8_t function) { - boolean result = false; + bool result = false; if (pms_type) { switch (function) { diff --git a/sonoff/xsns_19_mgs.ino b/sonoff/xsns_19_mgs.ino index e4ce80643..13ab99bd6 100644 --- a/sonoff/xsns_19_mgs.ino +++ b/sonoff/xsns_19_mgs.ino @@ -38,7 +38,7 @@ void MGSInit(void) { gas.begin(MGS_SENSOR_ADDR); } -boolean MGSPrepare(void) +bool MGSPrepare(void) { gas.begin(MGS_SENSOR_ADDR); if (!gas.isError()) { @@ -61,7 +61,7 @@ char* measure_gas(int gas_type, char* buffer) const char HTTP_MGS_GAS[] PROGMEM = "%s{s}MGS %s{m}%s " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = #endif // USE_WEBSERVER -void MGSShow(boolean json) +void MGSShow(bool json) { char buffer[33]; if (json) { @@ -91,9 +91,9 @@ void MGSShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns19(byte function) +bool Xsns19(uint8_t function) { - boolean result = false; + bool result = false; static int detected = false; if (i2c_flg) { diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 1f94dea6a..72843f169 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -21,7 +21,7 @@ /*********************************************************************************************\ * Nova Fitness SDS011 (and possibly SDS021) particle concentration sensor * For background information see http://aqicn.org/sensor/sds011/ - * For protocol specification see + * For protocol specification see * https://cdn.sparkfun.com/assets/parts/1/2/2/7/5/Laser_Dust_Sensor_Control_Protocol_V1.3.pdf * * Hardware Serial will be selected if GPIO3 = [SDS0X01] @@ -74,12 +74,12 @@ struct sds011data { #define NOVA_SDS_SLEEP 1 // Subcmnd "sleep mode" -bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, byte *buffer) +bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer) { uint8_t novasds_cmnd[19] = {0xAA, 0xB4, byte1, byte2, byte3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (uint8_t)(sensorid & 0xFF), (uint8_t)((sensorid>>8) & 0xFF), 0x00, 0xAB}; // calc crc - for (byte i = 2; i < 17; i++) { + for (uint8_t i = 2; i < 17; i++) { novasds_cmnd[17] += novasds_cmnd[i]; } //~ snprintf_P(log_data, sizeof(log_data), PSTR("SDS: Send %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X"), @@ -97,7 +97,7 @@ bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensor // timeout return false; } - byte recbuf[10]; + uint8_t recbuf[10]; memset(recbuf, 0, sizeof(recbuf)); // sync to 0xAA header while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( NovaSdsSerial->available() > 0) && (0xAA != (recbuf[0] = NovaSdsSerial->read())) ); @@ -134,7 +134,7 @@ void NovaSdsSetWorkPeriod(void) bool NovaSdsReadData(void) { - byte d[10]; + uint8_t d[10]; if ( ! NovaSdsCommand(NOVA_SDS_QUERY_DATA, 0, 0, NOVA_SDS_DEVICE_ID, d) ) { return false; } @@ -186,7 +186,7 @@ const char HTTP_SDS0X1_SNS[] PROGMEM = "%s" "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; // {s} = #endif // USE_WEBSERVER -void NovaSdsShow(boolean json) +void NovaSdsShow(bool json) { if (novasds_valid) { float pm10f = (float)(novasds_data.pm100) / 10.0f; @@ -215,9 +215,9 @@ void NovaSdsShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns20(byte function) +bool Xsns20(uint8_t function) { - boolean result = false; + bool result = false; if (novasds_type) { switch (function) { diff --git a/sonoff/xsns_21_sgp30.ino b/sonoff/xsns_21_sgp30.ino index 0394b12bf..2f7bf4673 100644 --- a/sonoff/xsns_21_sgp30.ino +++ b/sonoff/xsns_21_sgp30.ino @@ -70,7 +70,7 @@ const char HTTP_SNS_SGP30[] PROGMEM = "%s" "{s}SGP30 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" // {s} = "{s}SGP30 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; -void Sgp30Show(boolean json) +void Sgp30Show(bool json) { if (sgp30_ready) { if (json) { @@ -90,9 +90,9 @@ void Sgp30Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns21(byte function) +bool Xsns21(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index 9fa9f7322..ee4939bba 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -46,7 +46,7 @@ const char HTTP_SNS_DISTANCE[] PROGMEM = "%s{s}SR04 " D_DISTANCE "{m}%s" D_UNIT_CENTIMETER "{e}"; // {s} = #endif // USE_WEBSERVER -void Sr04Show(boolean json) +void Sr04Show(bool json) { distance = (real64_t)(sonar->ping_median(5))/ US_ROUNDTRIP_CM; @@ -75,9 +75,9 @@ void Sr04Show(boolean json) #define XSNS_22 -boolean Xsns22(byte function) +bool Xsns22(uint8_t function) { - boolean result = false; + bool result = false; if ((pin[GPIO_SR04_ECHO] < 99) && (pin[GPIO_SR04_TRIG] < 99)) { switch (function) { diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino index e162d9cad..ec4891183 100644 --- a/sonoff/xsns_23_sdm120.ino +++ b/sonoff/xsns_23_sdm120.ino @@ -281,7 +281,7 @@ const char HTTP_SNS_SDM120_DATA[] PROGMEM = "%s" ; #endif // USE_WEBSERVER -void SDM120Show(boolean json) +void SDM120Show(bool json) { char voltage[33]; dtostrfd(sdm120_voltage, Settings.flag2.voltage_resolution, voltage); @@ -343,9 +343,9 @@ void SDM120Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns23(byte function) +bool Xsns23(uint8_t function) { - boolean result = false; + bool result = false; if (sdm120_type) { switch (function) { diff --git a/sonoff/xsns_24_si1145.ino b/sonoff/xsns_24_si1145.ino index 547c25110..85f2297aa 100644 --- a/sonoff/xsns_24_si1145.ino +++ b/sonoff/xsns_24_si1145.ino @@ -276,7 +276,7 @@ void Si1145DeInit(void) Si1145WriteByte(SI114X_COMMAND, SI114X_PSALS_AUTO); } -boolean Si1145Begin(void) +bool Si1145Begin(void) { if (!Si1145Present()) { return false; } @@ -323,14 +323,14 @@ const char HTTP_SNS_SI1145[] PROGMEM = "%s" "{s}SI1145 " D_UV_INDEX "{m}%d.%d{e}"; #endif // USE_WEBSERVER -void Si1145Show(boolean json) +void Si1145Show(bool json) { if (si1145_type && Si1145Present()) { uint16_t visible = Si1145ReadVisible(); uint16_t infrared = Si1145ReadIR(); uint16_t uvindex = Si1145ReadUV(); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UVINDEX "\":%d.%d}"), + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), mqtt_data, visible, infrared, uvindex /100, uvindex %100); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, visible); @@ -349,9 +349,9 @@ void Si1145Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns24(byte function) +bool Xsns24(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_25_sdm630.ino b/sonoff/xsns_25_sdm630.ino index 631596fff..41f83ec93 100644 --- a/sonoff/xsns_25_sdm630.ino +++ b/sonoff/xsns_25_sdm630.ino @@ -267,7 +267,7 @@ const char HTTP_SNS_SDM630_DATA[] PROGMEM = "%s" "{s}SDM630 " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; #endif // USE_WEBSERVER -void SDM630Show(boolean json) +void SDM630Show(bool json) { char voltage_l1[33]; dtostrfd(sdm630_voltage[0], Settings.flag2.voltage_resolution, voltage_l1); @@ -326,9 +326,9 @@ void SDM630Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns25(byte function) +bool Xsns25(uint8_t function) { - boolean result = false; + bool result = false; if (sdm630_type) { switch (function) { diff --git a/sonoff/xsns_26_lm75ad.ino b/sonoff/xsns_26_lm75ad.ino index dc41fd526..31aba77b8 100644 --- a/sonoff/xsns_26_lm75ad.ino +++ b/sonoff/xsns_26_lm75ad.ino @@ -53,7 +53,7 @@ void LM75ADDetect(void) if (lm75ad_type) { return; } uint16_t buffer; - for (byte i = 0; i < sizeof(lm75ad_addresses); i++) { + for (uint8_t i = 0; i < sizeof(lm75ad_addresses); i++) { lm75ad_address = lm75ad_addresses[i]; if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) { if (buffer == 0x4B00) { @@ -78,7 +78,7 @@ float LM75ADGetTemp(void) { return ConvertTemp(sign * t * 0.125); } -void LM75ADShow(boolean json) +void LM75ADShow(bool json) { if (lm75ad_type) { float t = LM75ADGetTemp(); @@ -102,9 +102,9 @@ void LM75ADShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns26(byte function) +bool Xsns26(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_27_apds9960.ino b/sonoff/xsns_27_apds9960.ino index 063f519be..90978db7f 100644 --- a/sonoff/xsns_27_apds9960.ino +++ b/sonoff/xsns_27_apds9960.ino @@ -1903,7 +1903,7 @@ bool APDS9960_detect(void) return true; } - boolean success = false; + bool success = false; APDS9960type = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ID); if (APDS9960type == APDS9960_CHIPID_1 || APDS9960type == APDS9960_CHIPID_2) { @@ -1935,7 +1935,7 @@ bool APDS9960_detect(void) * Presentation \*********************************************************************************************/ -void APDS9960_show(boolean json) +void APDS9960_show(bool json) { if (!APDS9960type) { return; @@ -1993,7 +1993,7 @@ void APDS9960_show(boolean json) bool APDS9960CommandSensor(void) { - boolean serviced = true; + bool serviced = true; switch (XdrvMailbox.payload) { case 0: // Off @@ -2039,9 +2039,9 @@ bool APDS9960CommandSensor(void) * Interface \*********************************************************************************************/ -boolean Xsns27(byte function) +bool Xsns27(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { if (FUNC_INIT == function) { diff --git a/sonoff/xsns_28_tm1638.ino b/sonoff/xsns_28_tm1638.ino index 54f89548c..590432dfd 100644 --- a/sonoff/xsns_28_tm1638.ino +++ b/sonoff/xsns_28_tm1638.ino @@ -46,7 +46,7 @@ uint8_t tm1638_state = 0; * and from library https://github.com/MartyMacGyver/TM1638-demos-and-examples \*********************************************************************************************/ -void Tm16XXSend(byte data) +void Tm16XXSend(uint8_t data) { for (uint8_t i = 0; i < 8; i++) { digitalWrite(tm1638_data_pin, !!(data & (1 << i))); @@ -56,14 +56,14 @@ void Tm16XXSend(byte data) } } -void Tm16XXSendCommand(byte cmd) +void Tm16XXSendCommand(uint8_t cmd) { digitalWrite(tm1638_strobe_pin, LOW); Tm16XXSend(cmd); digitalWrite(tm1638_strobe_pin, HIGH); } -void TM16XXSendData(byte address, byte data) +void TM16XXSendData(uint8_t address, uint8_t data) { Tm16XXSendCommand(0x44); digitalWrite(tm1638_strobe_pin, LOW); @@ -72,9 +72,9 @@ void TM16XXSendData(byte address, byte data) digitalWrite(tm1638_strobe_pin, HIGH); } -byte Tm16XXReceive(void) +uint8_t Tm16XXReceive(void) { - byte temp = 0; + uint8_t temp = 0; // Pull-up on pinMode(tm1638_data_pin, INPUT); @@ -103,7 +103,7 @@ void Tm16XXClearDisplay(void) } } -void Tm1638SetLED(byte color, byte pos) +void Tm1638SetLED(uint8_t color, uint8_t pos) { TM16XXSendData((pos << 1) + 1, color); } @@ -111,7 +111,7 @@ void Tm1638SetLED(byte color, byte pos) void Tm1638SetLEDs(word leds) { for (int i = 0; i < tm1638_displays; i++) { - byte color = 0; + uint8_t color = 0; if ((leds & (1 << i)) != 0) { color |= TM1638_COLOR_RED; @@ -125,9 +125,9 @@ void Tm1638SetLEDs(word leds) } } -byte Tm1638GetButtons(void) +uint8_t Tm1638GetButtons(void) { - byte keys = 0; + uint8_t keys = 0; digitalWrite(tm1638_strobe_pin, LOW); Tm16XXSend(0x42); @@ -174,10 +174,10 @@ void TmInit(void) void TmLoop(void) { if (tm1638_state) { - byte buttons = Tm1638GetButtons(); - for (byte i = 0; i < MAX_SWITCHES; i++) { + uint8_t buttons = Tm1638GetButtons(); + for (uint8_t i = 0; i < MAX_SWITCHES; i++) { SwitchSetVirtual(i, (buttons &1) ^1); - byte color = (SwitchGetVirtual(i)) ? TM1638_COLOR_NONE : TM1638_COLOR_RED; + uint8_t color = (SwitchGetVirtual(i)) ? TM1638_COLOR_NONE : TM1638_COLOR_RED; Tm1638SetLED(color, i); buttons >>= 1; } @@ -186,7 +186,7 @@ void TmLoop(void) } /* -void TmShow(boolean json) +void TmShow(bool json) { if (tm1638_type) { @@ -198,9 +198,9 @@ void TmShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns28(byte function) +bool Xsns28(uint8_t function) { - boolean result = false; + bool result = false; if (tm1638_type) { switch (function) { diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 7a223b945..559b3e809 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -325,7 +325,7 @@ void MCP230xx_CheckForInterrupt(void) { } } -void MCP230xx_Show(boolean json) +void MCP230xx_Show(bool json) { if (mcp230xx_type) { if (json) { @@ -426,8 +426,8 @@ void MCP230xx_Reset(uint8_t pinmode) { } bool MCP230xx_Command(void) { - boolean serviced = true; - boolean validpin = false; + bool serviced = true; + bool validpin = false; uint8_t paramcount = 0; if (XdrvMailbox.data_len > 0) { paramcount=1; @@ -781,9 +781,9 @@ void MCP230xx_Interrupt_Retain_Report(void) { Interface \*********************************************************************************************/ -boolean Xsns29(byte function) +bool Xsns29(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_30_mpr121.ino b/sonoff/xsns_30_mpr121.ino index 4021247a6..e9dbfad4f 100644 --- a/sonoff/xsns_30_mpr121.ino +++ b/sonoff/xsns_30_mpr121.ino @@ -318,7 +318,7 @@ void Mpr121Init(struct mpr121 *pS) * @post None. * */ -void Mpr121Show(struct mpr121 *pS, byte function) +void Mpr121Show(struct mpr121 *pS, uint8_t function) { // Loop through sensors @@ -384,7 +384,7 @@ void Mpr121Show(struct mpr121 *pS, byte function) } } // if->running } // for-loop i -} // void Mpr121Show(byte function) +} // void Mpr121Show(uint8_t function) /*********************************************************************************************\ * Interface @@ -400,15 +400,15 @@ void Mpr121Show(struct mpr121 *pS, byte function) * FUNC_WEB_APPEND for displaying data in the Tasmota web-interface * * @param byte function Tasmota function ID. - * @return boolean ??? + * @return bool ??? * @pre None. * @post None. * */ -boolean Xsns30(byte function) +bool Xsns30(uint8_t function) { // ??? - boolean result = false; + bool result = false; // Sensor state/data struct static struct mpr121 mpr121; @@ -440,7 +440,7 @@ boolean Xsns30(byte function) #endif // USE_WEBSERVER } } - // Return boolean result + // Return bool result return result; } diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index f68c14905..75dca5451 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -83,7 +83,7 @@ const char HTTP_SNS_CCS811[] PROGMEM = "%s" "{s}CCS811 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" // {s} = "{s}CCS811 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; -void CCS811Show(boolean json) +void CCS811Show(bool json) { if (CCS811_ready) { if (json) { @@ -103,9 +103,9 @@ void CCS811Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns31(byte function) +bool Xsns31(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index bdc546e53..9556c5fe4 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -120,7 +120,7 @@ void MPU_6050Detect(void) return; } - for (byte i = 0; i < sizeof(MPU_6050_addresses); i++) + for (uint8_t i = 0; i < sizeof(MPU_6050_addresses); i++) { if(!I2cDevice(MPU_6050_addresses[i])) { @@ -171,7 +171,7 @@ const char HTTP_SNS_GZ_AXIS[] PROGMEM = "%s{s}%s " D_GZ_AXIS "{m}%s{e}"; #define D_JSON_AXIS_GY "GyroYAxis" #define D_JSON_AXIS_GZ "GyroZAxis" -void MPU_6050Show(boolean json) +void MPU_6050Show(bool json) { if (MPU_6050_found) { MPU_6050PerformReading(); @@ -228,9 +228,9 @@ void MPU_6050Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns32(byte function) +bool Xsns32(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_33_ds3231.ino b/sonoff/xsns_33_ds3231.ino index 0e8e5c8f6..2e4586489 100644 --- a/sonoff/xsns_33_ds3231.ino +++ b/sonoff/xsns_33_ds3231.ino @@ -62,9 +62,9 @@ #define HR1224 6 //Hours register 12 or 24 hour mode (24 hour mode==0) #define CENTURY 7 //Century bit in Month register #define DYDT 6 //Day/Date flag bit in alarm Day/Date registers -boolean ds3231ReadStatus = false; -boolean ds3231WriteStatus = false; //flag, we want to wriet/write to DS3231 onlu once -boolean DS3231chipDetected = false; +bool ds3231ReadStatus = false; +bool ds3231WriteStatus = false; //flag, we want to wriet/write to DS3231 onlu once +bool DS3231chipDetected = false; /*----------------------------------------------------------------------* Detect the DS3231 Chip @@ -132,9 +132,9 @@ void SetDS3231Time (uint32_t epoch_time) { Interface \*********************************************************************************************/ -boolean Xsns33(byte function) +bool Xsns33(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { @@ -144,7 +144,7 @@ boolean Xsns33(byte function) case FUNC_EVERY_SECOND: TIME_T tmpTime; if (!ds3231ReadStatus && DS3231chipDetected && utc_time < 1451602800 ) { // We still did not sync with NTP (time not valid) , so, read time from DS3231 - ntp_force_sync = 1; //force to sync with ntp + ntp_force_sync = true; //force to sync with ntp utc_time = ReadFromDS3231(); //we read UTC TIME from DS3231 // from this line, we just copy the function from "void RtcSecond()" at the support.ino ,line 2143 and above // We need it to set rules etc. diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index f46e69359..d9063b779 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -67,12 +67,12 @@ long hx_offset = 0; long hx_scale = 1; uint8_t hx_type = 1; uint8_t hx_sample_count = 0; -uint8_t hx_tare_flg = 0; uint8_t hx_calibrate_step = HX_CAL_END; uint8_t hx_calibrate_timer = 0; uint8_t hx_calibrate_msg = 0; uint8_t hx_pin_sck; uint8_t hx_pin_dout; +bool hx_tare_flg = false; /*********************************************************************************************/ @@ -118,7 +118,7 @@ long HxRead() void HxReset(void) { - hx_tare_flg = 1; + hx_tare_flg = true; hx_sum_weight = 0; hx_sample_count = 0; } @@ -155,7 +155,7 @@ bool HxCommand(void) bool show_parms = false; char sub_string[XdrvMailbox.data_len +1]; - for (byte ca = 0; ca < XdrvMailbox.data_len; ca++) { + for (uint8_t ca = 0; ca < XdrvMailbox.data_len; ca++) { if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; } } @@ -257,7 +257,7 @@ void HxEvery100mSecond(void) if (hx_weight < 0) { hx_weight = 0; } if (hx_tare_flg) { - hx_tare_flg = 0; + hx_tare_flg = false; hx_offset = average; // grams } @@ -301,7 +301,7 @@ void HxEvery100mSecond(void) if (HX_CAL_FAIL == hx_calibrate_step) { // Calibration failed hx_calibrate_step--; - hx_tare_flg = 1; // Perform a reset using old scale + hx_tare_flg = true; // Perform a reset using old scale HxCalibrationStateTextJson(0); } if (HX_CAL_FINISH == hx_calibrate_step) { // Calibration finished @@ -329,7 +329,7 @@ const char HTTP_HX711_CAL[] PROGMEM = "%s" "{s}HX711 %s{m}{e}"; #endif // USE_WEBSERVER -void HxShow(boolean json) +void HxShow(bool json) { char scount[30] = { 0 }; @@ -469,9 +469,9 @@ void HxLogUpdates(void) * Interface \*********************************************************************************************/ -boolean Xsns34(byte function) +bool Xsns34(uint8_t function) { - boolean result = false; + bool result = false; if (hx_type) { switch (function) { diff --git a/sonoff/xsns_35_tx20.ino b/sonoff/xsns_35_tx20.ino index ae2f05926..bae2e9532 100644 --- a/sonoff/xsns_35_tx20.ino +++ b/sonoff/xsns_35_tx20.ino @@ -78,7 +78,7 @@ float tx20_wind_sum = 0; int tx20_count = 0; uint8_t tx20_wind_direction = 0; -boolean tx20_available = false; +bool tx20_available = false; void Tx20StartRead(void) { @@ -170,7 +170,7 @@ void Tx20Init(void) { attachInterrupt(pin[GPIO_TX20_TXD_BLACK], Tx20StartRead, RISING); } -void Tx20Show(boolean json) +void Tx20Show(bool json) { char wind_speed_string[33]; dtostrfd(tx20_wind_speed_kmh, 2, wind_speed_string); @@ -195,9 +195,9 @@ void Tx20Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns35(byte function) +bool Xsns35(uint8_t function) { - boolean result = false; + bool result = false; if (pin[GPIO_TX20_TXD_BLACK] < 99) { switch (function) { diff --git a/sonoff/xsns_36_mgc3130.ino b/sonoff/xsns_36_mgc3130.ino index 6def4d917..760330a8a 100644 --- a/sonoff/xsns_36_mgc3130.ino +++ b/sonoff/xsns_36_mgc3130.ino @@ -497,7 +497,7 @@ bool MGC3130_detect(void) digitalWrite(MGC3130_reset, HIGH); delay(50); - boolean success = false; + bool success = false; success = MGC3130_receiveMessage(); // This should read the firmware info if (success) { strcpy_P(MGC3130stype, PSTR("MGC3130")); @@ -516,7 +516,7 @@ bool MGC3130_detect(void) * Presentation \*********************************************************************************************/ -void MGC3130_show(boolean json) +void MGC3130_show(bool json) { if (!MGC3130_type) { return; } @@ -576,7 +576,7 @@ void MGC3130_show(boolean json) bool MGC3130CommandSensor() { - boolean serviced = true; + bool serviced = true; switch (XdrvMailbox.payload) { case 0: // cycle through the modes @@ -602,9 +602,9 @@ bool MGC3130CommandSensor() * Interface \*********************************************************************************************/ -boolean Xsns36(byte function) +bool Xsns36(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { if ((FUNC_INIT == function) && (pin[GPIO_MGC3130_XFER] < 99) && (pin[GPIO_MGC3130_RESET] < 99)) { diff --git a/sonoff/xsns_37_rfsensor.ino b/sonoff/xsns_37_rfsensor.ino index df6aeaf35..66a7688ce 100644 --- a/sonoff/xsns_37_rfsensor.ino +++ b/sonoff/xsns_37_rfsensor.ino @@ -49,10 +49,10 @@ typedef struct RawSignalStruct // Variabelen geplaatst in struct zodat deze later eenvoudig kunnen worden weggeschreven naar SDCard { int Number; // aantal bits, maal twee omdat iedere bit een mark en een space heeft. - byte Repeats; // Aantal maal dat de pulsreeks verzonden moet worden bij een zendactie. - byte Multiply; // Pulses[] * Multiply is de echte tijd van een puls in microseconden + uint8_t Repeats; // Aantal maal dat de pulsreeks verzonden moet worden bij een zendactie. + uint8_t Multiply; // Pulses[] * Multiply is de echte tijd van een puls in microseconden unsigned long Time; // Tijdstempel wanneer signaal is binnengekomen (millis()) - byte Pulses[RFSNS_RAW_BUFFER_SIZE+2]; // Tabel met de gemeten pulsen in microseconden gedeeld door rfsns_raw_signal->Multiply. Dit scheelt helft aan RAM geheugen. + uint8_t Pulses[RFSNS_RAW_BUFFER_SIZE+2]; // Tabel met de gemeten pulsen in microseconden gedeeld door rfsns_raw_signal->Multiply. Dit scheelt helft aan RAM geheugen. // Om legacy redenen zit de eerste puls in element 1. Element 0 wordt dus niet gebruikt. } raw_signal_t; @@ -65,7 +65,7 @@ uint8_t rfsns_any_sensor = 0; * Fetch signals from RF pin \*********************************************************************************************/ -bool RfSnsFetchSignal(byte DataPin, bool StateSignal) +bool RfSnsFetchSignal(uint8_t DataPin, bool StateSignal) { uint8_t Fbit = digitalPinToBitMask(DataPin); uint8_t Fport = digitalPinToPort(DataPin); @@ -179,17 +179,17 @@ void RfSnsAnalyzeTheov2(void) { if (rfsns_raw_signal->Number != RFSNS_THEOV2_PULSECOUNT) { return; } - byte Checksum; // 8 bits Checksum over following bytes - byte Channel; // 3 bits channel - byte Type; // 5 bits type - byte Voltage; // 8 bits Vcc like 45 = 4.5V, bit 8 is batt low + uint8_t Checksum; // 8 bits Checksum over following bytes + uint8_t Channel; // 3 bits channel + uint8_t Type; // 5 bits type + uint8_t Voltage; // 8 bits Vcc like 45 = 4.5V, bit 8 is batt low int Payload1; // 16 bits int Payload2; // 16 bits - byte b, bytes, bits, id; + uint8_t b, bytes, bits, id; - byte idx = 3; - byte chksum = 0; + uint8_t idx = 3; + uint8_t chksum = 0; for (bytes = 0; bytes < 7; bytes++) { b = 0; for (bits = 0; bits <= 7; bits++) @@ -438,23 +438,23 @@ void RfSnsAnalyzeAlectov2() if (!(((rfsns_raw_signal->Number >= RFSNS_ACH2010_MIN_PULSECOUNT) && (rfsns_raw_signal->Number <= RFSNS_ACH2010_MAX_PULSECOUNT)) || (rfsns_raw_signal->Number == RFSNS_DKW2012_PULSECOUNT))) { return; } - byte c = 0; - byte rfbit; - byte data[9] = { 0 }; - byte msgtype = 0; - byte rc = 0; + uint8_t c = 0; + uint8_t rfbit; + uint8_t data[9] = { 0 }; + uint8_t msgtype = 0; + uint8_t rc = 0; int temp; - byte checksum = 0; - byte checksumcalc = 0; - byte maxidx = 8; + uint8_t checksum = 0; + uint8_t checksumcalc = 0; + uint8_t maxidx = 8; unsigned long atime; float factor; char buf1[16]; if (rfsns_raw_signal->Number > RFSNS_ACH2010_MAX_PULSECOUNT) { maxidx = 9; } // Get message back to front as the header is almost never received complete for ACH2010 - byte idx = maxidx; - for (byte x = rfsns_raw_signal->Number; x > 0; x = x-2) { + uint8_t idx = maxidx; + for (uint8_t x = rfsns_raw_signal->Number; x > 0; x = x-2) { if (rfsns_raw_signal->Pulses[x-1] * rfsns_raw_signal->Multiply < 0x300) { rfbit = 0x80; } else { @@ -659,7 +659,7 @@ void RfSnsShow(bool json) * Interface \*********************************************************************************************/ -boolean Xsns37(byte function) +bool Xsns37(uint8_t function) { bool result = false; diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino index 433b380b0..3ec73085e 100644 --- a/sonoff/xsns_38_az7798.ino +++ b/sonoff/xsns_38_az7798.ino @@ -250,7 +250,7 @@ void AzInit(void) } } -void AzShow(boolean json) +void AzShow(bool json) { char temperature[33]; dtostrfd(az_temperature, Settings.flag2.temperature_resolution, temperature); @@ -275,9 +275,9 @@ void AzShow(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns38(byte function) +bool Xsns38(uint8_t function) { - boolean result = false; + bool result = false; if(az_type){ switch (function) { diff --git a/sonoff/xsns_39_max31855.ino b/sonoff/xsns_39_max31855.ino index 724dcbb29..10630e171 100644 --- a/sonoff/xsns_39_max31855.ino +++ b/sonoff/xsns_39_max31855.ino @@ -148,9 +148,9 @@ void MAX31855_Show(bool Json){ * Interface \*********************************************************************************************/ -boolean Xsns39(byte function) +bool Xsns39(uint8_t function) { - boolean result = false; + bool result = false; if((pin[GPIO_MAX31855CS] < 99) && (pin[GPIO_MAX31855CLK] < 99) && (pin[GPIO_MAX31855DO] < 99)){ switch (function) { diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index 212a98905..6718ffc4e 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -265,7 +265,7 @@ void PN532_Detect(void) } } -boolean PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength) +bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength) { pn532_i2c_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; pn532_i2c_packetbuffer[1] = 1; @@ -385,8 +385,8 @@ void PN532_ScanForTag(void) uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; uint8_t uid_len = 0; uint8_t card_data[16]; - boolean erase_success = false; - boolean set_success = false; + bool erase_success = false; + bool set_success = false; if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) { if (pn532_i2c_scan_defer_report > 0) { pn532_i2c_scan_defer_report--; @@ -439,7 +439,7 @@ void PN532_ScanForTag(void) memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string } #else - boolean IsAlphaNumeric = true; + bool IsAlphaNumeric = true; for (uint8_t i = 0;i < pn532_i2c_newdata_len;i++) { if ((!isalpha(pn532_i2c_newdata[i])) || (!isdigit(pn532_i2c_newdata[i]))) { IsAlphaNumeric = false; @@ -511,9 +511,9 @@ void PN532_ScanForTag(void) #ifdef USE_PN532_DATA_FUNCTION -boolean PN532_Command(void) +bool PN532_Command(void) { - boolean serviced = true; + bool serviced = true; uint8_t paramcount = 0; if (XdrvMailbox.data_len > 0) { paramcount=1; @@ -563,9 +563,9 @@ boolean PN532_Command(void) * Interface \*********************************************************************************************/ -boolean Xsns40(byte function) +bool Xsns40(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_41_max44009.ino b/sonoff/xsns_41_max44009.ino index 92bd7d8a7..25d415222 100644 --- a/sonoff/xsns_41_max44009.ino +++ b/sonoff/xsns_41_max44009.ino @@ -65,7 +65,7 @@ bool Max4409Read_lum(void) void Max4409Detect(void) { - byte reg[8]; + uint8_t reg[8]; bool failed = false; if (max44009_found) { @@ -74,7 +74,7 @@ void Max4409Detect(void) uint8_t buffer1; uint8_t buffer2; - for (byte i = 0; 0 != max44009_addresses[i]; i++) { + for (uint8_t i = 0; 0 != max44009_addresses[i]; i++) { max44009_address = max44009_addresses[i]; @@ -110,7 +110,7 @@ void Max4409EverySecond(void) } } -void Max4409Show(boolean json) +void Max4409Show(bool json) { char illum_str[8]; @@ -151,9 +151,9 @@ void Max4409Show(boolean json) * Interface \*********************************************************************************************/ -boolean Xsns41(byte function) +bool Xsns41(uint8_t function) { - boolean result = false; + bool result = false; if (i2c_flg) { switch (function) { diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index 25747b90e..589e95adb 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -18,9 +18,9 @@ */ #ifdef XFUNC_PTR_IN_ROM -boolean (* const xsns_func_ptr[])(byte) PROGMEM = { // Sensor Function Pointers for simple implementation of sensors +bool (* const xsns_func_ptr[])(uint8_t) PROGMEM = { // Sensor Function Pointers for simple implementation of sensors #else -boolean (* const xsns_func_ptr[])(byte) = { // Sensor Function Pointers for simple implementation of sensors +bool (* const xsns_func_ptr[])(uint8_t) = { // Sensor Function Pointers for simple implementation of sensors #endif #ifdef XSNS_01 @@ -268,7 +268,7 @@ const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); * Function call to all xsns \*********************************************************************************************/ -boolean XsnsNextCall(byte Function, uint8_t &xsns_index) +bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index) { xsns_index++; if (xsns_index == xsns_present) { xsns_index = 0; } @@ -282,15 +282,15 @@ boolean XsnsNextCall(byte Function, uint8_t &xsns_index) return xsns_func_ptr[xsns_index](Function); } -boolean XsnsCall(byte Function) +bool XsnsCall(uint8_t Function) { - boolean result = false; + bool result = false; #ifdef PROFILE_XSNS_EVERY_SECOND uint32_t profile_start_millis = millis(); #endif // PROFILE_XSNS_EVERY_SECOND - for (byte x = 0; x < xsns_present; x++) { + for (uint8_t x = 0; x < xsns_present; x++) { #ifdef USE_DEBUG_DRIVER if (XsnsEnabled(x)) { #endif diff --git a/sonoff/zzzz_debug.ino b/sonoff/zzzz_debug.ino index 674d4acc8..d7b4c4c75 100644 --- a/sonoff/zzzz_debug.ino +++ b/sonoff/zzzz_debug.ino @@ -261,7 +261,7 @@ const uint8_t kXsnsList[] = { * Xsns sensor control \*********************************************************************************************/ -boolean XsnsEnabled(byte sns_index) +bool XsnsEnabled(uint8_t sns_index) { if (sns_index < sizeof(kXsnsList)) { #ifdef XFUNC_PTR_IN_ROM @@ -274,10 +274,10 @@ boolean XsnsEnabled(byte sns_index) return 1; } -boolean XsnsPresent(byte sns_index) +bool XsnsPresent(uint8_t sns_index) { uint8_t index = 0; - for (byte i = 0; i < sizeof(kXsnsList); i++) { + for (uint8_t i = 0; i < sizeof(kXsnsList); i++) { #ifdef XFUNC_PTR_IN_ROM index = pgm_read_byte(kXsnsList + i); #else @@ -293,7 +293,7 @@ String XsnsGetSensors(void) char state[2] = { 0 }; String data = F("["); - for (byte i = 0; i < MAX_XSNS_DRIVERS; i++) { + for (uint8_t i = 0; i < MAX_XSNS_DRIVERS; i++) { if (i && (!(i % 16))) { data += F(","); } if (!(i % 16)) { data += F("\""); } state[0] = '-'; From 15c5e15f7c2250a20e1dc38dcdab94966a827129 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 28 Jan 2019 15:13:14 +0100 Subject: [PATCH 0906/2222] Update support_wifi.ino Add TLS remarks (#4952) --- sonoff/support_wifi.ino | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 50f2895b0..730ac595f 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -32,6 +32,21 @@ #define WIFI_CHECK_SEC 20 // seconds #define WIFI_RETRY_OFFSET_SEC 20 // seconds +/* +// This worked for 2_5_0_BETA2 but fails since then. Waiting for a solution from core team (#4952) +#ifdef USE_MQTT_TLS +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) +#else +#define USING_AXTLS +#include +// force use of AxTLS (BearSSL is now default) which uses less memory (#4952) +#include +using namespace axTLS; +#endif // ARDUINO_ESP8266_RELEASE prior to 2_5_0 +#else +#include // Wifi, MQTT, Ota, WifiManager +#endif // USE_MQTT_TLS +*/ #include // Wifi, MQTT, Ota, WifiManager uint8_t wifi_counter; From 448a7852e12337f31cfd780a5c0d82abe521580a Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Mon, 28 Jan 2019 16:40:46 +0100 Subject: [PATCH 0907/2222] decode-config.py: adapt settings - add Interlock (interlock) - remove SetOption63 (split_interlock) --- tools/decode-config.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 739314710..397741b27 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0018' +VER = '2.1.0019' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -829,7 +829,14 @@ Setting_6_4_1_8['flag3'][0].update ({ 'split_interlock': (' Date: Mon, 28 Jan 2019 17:53:25 +0100 Subject: [PATCH 0908/2222] Fix Alexa bug in Core 2.4.2. Use patched Parsing.cpp only for Core 2.4.2 to fix Alexa bug --- sonoff/Parsing.cpp | 623 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 623 insertions(+) create mode 100644 sonoff/Parsing.cpp diff --git a/sonoff/Parsing.cpp b/sonoff/Parsing.cpp new file mode 100644 index 000000000..525277c74 --- /dev/null +++ b/sonoff/Parsing.cpp @@ -0,0 +1,623 @@ +/* + Parsing.cpp - HTTP request parsing. + + Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) +*/ + +// Use patched Parsing.cpp to fix ALEXA parsing issue in v2.4.2 +#include +#if defined(ARDUINO_ESP8266_RELEASE_2_4_2) +#warning **** Tasmota is using v2.4.2 patched Parsing.cpp as planned **** + +#include +#include "WiFiServer.h" +#include "WiFiClient.h" +#include "ESP8266WebServer.h" +#include "detail/mimetable.h" + +//#define DEBUG_ESP_HTTP_SERVER +#ifdef DEBUG_ESP_PORT +#define DEBUG_OUTPUT DEBUG_ESP_PORT +#else +#define DEBUG_OUTPUT Serial +#endif + +static const char Content_Type[] PROGMEM = "Content-Type"; +static const char filename[] PROGMEM = "filename"; + +static char* readBytesWithTimeout(WiFiClient& client, size_t maxLength, size_t& dataLength, int timeout_ms) +{ + char *buf = nullptr; + dataLength = 0; + while (dataLength < maxLength) { + int tries = timeout_ms; + size_t newLength; + while (!(newLength = client.available()) && tries--) delay(1); + if (!newLength) { + break; + } + if (!buf) { + buf = (char *) malloc(newLength + 1); + if (!buf) { + return nullptr; + } + } + else { + char* newBuf = (char *) realloc(buf, dataLength + newLength + 1); + if (!newBuf) { + free(buf); + return nullptr; + } + buf = newBuf; + } + client.readBytes(buf + dataLength, newLength); + dataLength += newLength; + buf[dataLength] = '\0'; + } + return buf; +} + +bool ESP8266WebServer::_parseRequest(WiFiClient& client) { + // Read the first line of HTTP request + String req = client.readStringUntil('\r'); + client.readStringUntil('\n'); + //reset header value + for (int i = 0; i < _headerKeysCount; ++i) { + _currentHeaders[i].value =String(); + } + + // First line of HTTP request looks like "GET /path HTTP/1.1" + // Retrieve the "/path" part by finding the spaces + int addr_start = req.indexOf(' '); + int addr_end = req.indexOf(' ', addr_start + 1); + if (addr_start == -1 || addr_end == -1) { +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("Invalid request: "); + DEBUG_OUTPUT.println(req); +#endif + return false; + } + + String methodStr = req.substring(0, addr_start); + String url = req.substring(addr_start + 1, addr_end); + String versionEnd = req.substring(addr_end + 8); + _currentVersion = atoi(versionEnd.c_str()); + String searchStr = ""; + int hasSearch = url.indexOf('?'); + if (hasSearch != -1){ + searchStr = url.substring(hasSearch + 1); + url = url.substring(0, hasSearch); + } + _currentUri = url; + _chunked = false; + + HTTPMethod method = HTTP_GET; + if (methodStr == F("POST")) { + method = HTTP_POST; + } else if (methodStr == F("DELETE")) { + method = HTTP_DELETE; + } else if (methodStr == F("OPTIONS")) { + method = HTTP_OPTIONS; + } else if (methodStr == F("PUT")) { + method = HTTP_PUT; + } else if (methodStr == F("PATCH")) { + method = HTTP_PATCH; + } + _currentMethod = method; + +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("method: "); + DEBUG_OUTPUT.print(methodStr); + DEBUG_OUTPUT.print(" url: "); + DEBUG_OUTPUT.print(url); + DEBUG_OUTPUT.print(" search: "); + DEBUG_OUTPUT.println(searchStr); +#endif + + //attach handler + RequestHandler* handler; + for (handler = _firstHandler; handler; handler = handler->next()) { + if (handler->canHandle(_currentMethod, _currentUri)) + break; + } + _currentHandler = handler; + + String formData; + // below is needed only when POST type request + if (method == HTTP_POST || method == HTTP_PUT || method == HTTP_PATCH || method == HTTP_DELETE){ + String boundaryStr; + String headerName; + String headerValue; + bool isForm = false; + bool isEncoded = false; + uint32_t contentLength = 0; + //parse headers + while(1){ + req = client.readStringUntil('\r'); + client.readStringUntil('\n'); + if (req == "") break;//no moar headers + int headerDiv = req.indexOf(':'); + if (headerDiv == -1){ + break; + } + headerName = req.substring(0, headerDiv); + headerValue = req.substring(headerDiv + 1); + headerValue.trim(); + _collectHeader(headerName.c_str(),headerValue.c_str()); + + #ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("headerName: "); + DEBUG_OUTPUT.println(headerName); + DEBUG_OUTPUT.print("headerValue: "); + DEBUG_OUTPUT.println(headerValue); + #endif + + if (headerName.equalsIgnoreCase(FPSTR(Content_Type))){ + using namespace mime; + if (headerValue.startsWith(FPSTR(mimeTable[txt].mimeType))){ + isForm = false; + } else if (headerValue.startsWith(F("application/x-www-form-urlencoded"))){ + isForm = false; + isEncoded = true; + } else if (headerValue.startsWith(F("multipart/"))){ + boundaryStr = headerValue.substring(headerValue.indexOf('=') + 1); + boundaryStr.replace("\"",""); + isForm = true; + } + } else if (headerName.equalsIgnoreCase(F("Content-Length"))){ + contentLength = headerValue.toInt(); + } else if (headerName.equalsIgnoreCase(F("Host"))){ + _hostHeader = headerValue; + } + } + + if (!isForm){ + size_t plainLength; + char* plainBuf = readBytesWithTimeout(client, contentLength, plainLength, HTTP_MAX_POST_WAIT); + if (plainLength < contentLength) { + free(plainBuf); + return false; + } + if (contentLength > 0) { + if(isEncoded){ + //url encoded form + if (searchStr != "") searchStr += '&'; + searchStr += plainBuf; + } + _parseArguments(searchStr); + if(!isEncoded||(0==_currentArgCount)){ // @20180124OF01: Workarround for Alexa Bug + //plain post json or other data + RequestArgument& arg = _currentArgs[_currentArgCount++]; + arg.key = F("plain"); + arg.value = String(plainBuf); + } + + #ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("Plain: "); + DEBUG_OUTPUT.println(plainBuf); + #endif + free(plainBuf); + } else { + // No content - but we can still have arguments in the URL. + _parseArguments(searchStr); + } + } + + if (isForm){ + _parseArguments(searchStr); + if (!_parseForm(client, boundaryStr, contentLength)) { + return false; + } + } + } else { + String headerName; + String headerValue; + //parse headers + while(1){ + req = client.readStringUntil('\r'); + client.readStringUntil('\n'); + if (req == "") break;//no moar headers + int headerDiv = req.indexOf(':'); + if (headerDiv == -1){ + break; + } + headerName = req.substring(0, headerDiv); + headerValue = req.substring(headerDiv + 2); + _collectHeader(headerName.c_str(),headerValue.c_str()); + + #ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("headerName: "); + DEBUG_OUTPUT.println(headerName); + DEBUG_OUTPUT.print("headerValue: "); + DEBUG_OUTPUT.println(headerValue); + #endif + + if (headerName.equalsIgnoreCase("Host")){ + _hostHeader = headerValue; + } + } + _parseArguments(searchStr); + } + client.flush(); + +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("Request: "); + DEBUG_OUTPUT.println(url); + DEBUG_OUTPUT.print(" Arguments: "); + DEBUG_OUTPUT.println(searchStr); +#endif + + return true; +} + +bool ESP8266WebServer::_collectHeader(const char* headerName, const char* headerValue) { + for (int i = 0; i < _headerKeysCount; i++) { + if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) { + _currentHeaders[i].value=headerValue; + return true; + } + } + return false; +} + +void ESP8266WebServer::_parseArguments(String data) { +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("args: "); + DEBUG_OUTPUT.println(data); +#endif + if (_currentArgs) + delete[] _currentArgs; + _currentArgs = 0; + if (data.length() == 0) { + _currentArgCount = 0; + _currentArgs = new RequestArgument[1]; + return; + } + _currentArgCount = 1; + + for (int i = 0; i < (int)data.length(); ) { + i = data.indexOf('&', i); + if (i == -1) + break; + ++i; + ++_currentArgCount; + } +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("args count: "); + DEBUG_OUTPUT.println(_currentArgCount); +#endif + + _currentArgs = new RequestArgument[_currentArgCount+1]; + int pos = 0; + int iarg; + for (iarg = 0; iarg < _currentArgCount;) { + int equal_sign_index = data.indexOf('=', pos); + int next_arg_index = data.indexOf('&', pos); +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("pos "); + DEBUG_OUTPUT.print(pos); + DEBUG_OUTPUT.print("=@ "); + DEBUG_OUTPUT.print(equal_sign_index); + DEBUG_OUTPUT.print(" &@ "); + DEBUG_OUTPUT.println(next_arg_index); +#endif + if ((equal_sign_index == -1) || ((equal_sign_index > next_arg_index) && (next_arg_index != -1))) { +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("arg missing value: "); + DEBUG_OUTPUT.println(iarg); +#endif + if (next_arg_index == -1) + break; + pos = next_arg_index + 1; + continue; + } + RequestArgument& arg = _currentArgs[iarg]; + arg.key = urlDecode(data.substring(pos, equal_sign_index)); + arg.value = urlDecode(data.substring(equal_sign_index + 1, next_arg_index)); +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("arg "); + DEBUG_OUTPUT.print(iarg); + DEBUG_OUTPUT.print(" key: "); + DEBUG_OUTPUT.print(arg.key); + DEBUG_OUTPUT.print(" value: "); + DEBUG_OUTPUT.println(arg.value); +#endif + ++iarg; + if (next_arg_index == -1) + break; + pos = next_arg_index + 1; + } + _currentArgCount = iarg; +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("args count: "); + DEBUG_OUTPUT.println(_currentArgCount); +#endif + +} + +void ESP8266WebServer::_uploadWriteByte(uint8_t b){ + if (_currentUpload->currentSize == HTTP_UPLOAD_BUFLEN){ + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, *_currentUpload); + _currentUpload->totalSize += _currentUpload->currentSize; + _currentUpload->currentSize = 0; + } + _currentUpload->buf[_currentUpload->currentSize++] = b; +} + +uint8_t ESP8266WebServer::_uploadReadByte(WiFiClient& client){ + int res = client.read(); + if(res == -1){ + while(!client.available() && client.connected()) + yield(); + res = client.read(); + } + return (uint8_t)res; +} + +bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t len){ + (void) len; +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("Parse Form: Boundary: "); + DEBUG_OUTPUT.print(boundary); + DEBUG_OUTPUT.print(" Length: "); + DEBUG_OUTPUT.println(len); +#endif + String line; + int retry = 0; + do { + line = client.readStringUntil('\r'); + ++retry; + } while (line.length() == 0 && retry < 3); + + client.readStringUntil('\n'); + //start reading the form + if (line == ("--"+boundary)){ + RequestArgument* postArgs = new RequestArgument[32]; + int postArgsLen = 0; + while(1){ + String argName; + String argValue; + String argType; + String argFilename; + bool argIsFile = false; + + line = client.readStringUntil('\r'); + client.readStringUntil('\n'); + if (line.length() > 19 && line.substring(0, 19).equalsIgnoreCase(F("Content-Disposition"))){ + int nameStart = line.indexOf('='); + if (nameStart != -1){ + argName = line.substring(nameStart+2); + nameStart = argName.indexOf('='); + if (nameStart == -1){ + argName = argName.substring(0, argName.length() - 1); + } else { + argFilename = argName.substring(nameStart+2, argName.length() - 1); + argName = argName.substring(0, argName.indexOf('"')); + argIsFile = true; +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("PostArg FileName: "); + DEBUG_OUTPUT.println(argFilename); +#endif + //use GET to set the filename if uploading using blob + if (argFilename == F("blob") && hasArg(FPSTR(filename))) + argFilename = arg(FPSTR(filename)); + } +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("PostArg Name: "); + DEBUG_OUTPUT.println(argName); +#endif + using namespace mime; + argType = FPSTR(mimeTable[txt].mimeType); + line = client.readStringUntil('\r'); + client.readStringUntil('\n'); + if (line.length() > 12 && line.substring(0, 12).equalsIgnoreCase(FPSTR(Content_Type))){ + argType = line.substring(line.indexOf(':')+2); + //skip next line + client.readStringUntil('\r'); + client.readStringUntil('\n'); + } +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("PostArg Type: "); + DEBUG_OUTPUT.println(argType); +#endif + if (!argIsFile){ + while(1){ + line = client.readStringUntil('\r'); + client.readStringUntil('\n'); + if (line.startsWith("--"+boundary)) break; + if (argValue.length() > 0) argValue += "\n"; + argValue += line; + } +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("PostArg Value: "); + DEBUG_OUTPUT.println(argValue); + DEBUG_OUTPUT.println(); +#endif + + RequestArgument& arg = postArgs[postArgsLen++]; + arg.key = argName; + arg.value = argValue; + + if (line == ("--"+boundary+"--")){ +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.println("Done Parsing POST"); +#endif + break; + } + } else { + _currentUpload.reset(new HTTPUpload()); + _currentUpload->status = UPLOAD_FILE_START; + _currentUpload->name = argName; + _currentUpload->filename = argFilename; + _currentUpload->type = argType; + _currentUpload->totalSize = 0; + _currentUpload->currentSize = 0; +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("Start File: "); + DEBUG_OUTPUT.print(_currentUpload->filename); + DEBUG_OUTPUT.print(" Type: "); + DEBUG_OUTPUT.println(_currentUpload->type); +#endif + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, *_currentUpload); + _currentUpload->status = UPLOAD_FILE_WRITE; + uint8_t argByte = _uploadReadByte(client); +readfile: + while(argByte != 0x0D){ + if (!client.connected()) return _parseFormUploadAborted(); + _uploadWriteByte(argByte); + argByte = _uploadReadByte(client); + } + + argByte = _uploadReadByte(client); + if (!client.connected()) return _parseFormUploadAborted(); + if (argByte == 0x0A){ + argByte = _uploadReadByte(client); + if (!client.connected()) return _parseFormUploadAborted(); + if ((char)argByte != '-'){ + //continue reading the file + _uploadWriteByte(0x0D); + _uploadWriteByte(0x0A); + goto readfile; + } else { + argByte = _uploadReadByte(client); + if (!client.connected()) return _parseFormUploadAborted(); + if ((char)argByte != '-'){ + //continue reading the file + _uploadWriteByte(0x0D); + _uploadWriteByte(0x0A); + _uploadWriteByte((uint8_t)('-')); + goto readfile; + } + } + + uint8_t endBuf[boundary.length()]; + client.readBytes(endBuf, boundary.length()); + + if (strstr((const char*)endBuf, boundary.c_str()) != NULL){ + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, *_currentUpload); + _currentUpload->totalSize += _currentUpload->currentSize; + _currentUpload->status = UPLOAD_FILE_END; + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, *_currentUpload); +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("End File: "); + DEBUG_OUTPUT.print(_currentUpload->filename); + DEBUG_OUTPUT.print(" Type: "); + DEBUG_OUTPUT.print(_currentUpload->type); + DEBUG_OUTPUT.print(" Size: "); + DEBUG_OUTPUT.println(_currentUpload->totalSize); +#endif + line = client.readStringUntil(0x0D); + client.readStringUntil(0x0A); + if (line == "--"){ +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.println("Done Parsing POST"); +#endif + break; + } + continue; + } else { + _uploadWriteByte(0x0D); + _uploadWriteByte(0x0A); + _uploadWriteByte((uint8_t)('-')); + _uploadWriteByte((uint8_t)('-')); + uint32_t i = 0; + while(i < boundary.length()){ + _uploadWriteByte(endBuf[i++]); + } + argByte = _uploadReadByte(client); + goto readfile; + } + } else { + _uploadWriteByte(0x0D); + goto readfile; + } + break; + } + } + } + } + + int iarg; + int totalArgs = ((32 - postArgsLen) < _currentArgCount)?(32 - postArgsLen):_currentArgCount; + for (iarg = 0; iarg < totalArgs; iarg++){ + RequestArgument& arg = postArgs[postArgsLen++]; + arg.key = _currentArgs[iarg].key; + arg.value = _currentArgs[iarg].value; + } + if (_currentArgs) delete[] _currentArgs; + _currentArgs = new RequestArgument[postArgsLen]; + for (iarg = 0; iarg < postArgsLen; iarg++){ + RequestArgument& arg = _currentArgs[iarg]; + arg.key = postArgs[iarg].key; + arg.value = postArgs[iarg].value; + } + _currentArgCount = iarg; + if (postArgs) + delete[] postArgs; + return true; + } +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print("Error: line: "); + DEBUG_OUTPUT.println(line); +#endif + return false; +} + +String ESP8266WebServer::urlDecode(const String& text) +{ + String decoded = ""; + char temp[] = "0x00"; + unsigned int len = text.length(); + unsigned int i = 0; + while (i < len) + { + char decodedChar; + char encodedChar = text.charAt(i++); + if ((encodedChar == '%') && (i + 1 < len)) + { + temp[2] = text.charAt(i++); + temp[3] = text.charAt(i++); + + decodedChar = strtol(temp, NULL, 16); + } + else { + if (encodedChar == '+') + { + decodedChar = ' '; + } + else { + decodedChar = encodedChar; // normal ascii char + } + } + decoded += decodedChar; + } + return decoded; +} + +bool ESP8266WebServer::_parseFormUploadAborted(){ + _currentUpload->status = UPLOAD_FILE_ABORTED; + if(_currentHandler && _currentHandler->canUpload(_currentUri)) + _currentHandler->upload(*this, _currentUri, *_currentUpload); + return false; +} + +#endif // ARDUINO_ESP8266_RELEASE \ No newline at end of file From 4509019d646325a323fc6f3c5d1439da48a029de Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 28 Jan 2019 18:04:33 +0100 Subject: [PATCH 0909/2222] Fix valid button range check Fix valid button range check --- sonoff/support.ino | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sonoff/support.ino b/sonoff/support.ino index 91d1f7633..b2e74addc 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -713,6 +713,12 @@ bool GetUsedInModule(uint8_t val, uint8_t *arr) if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) { offset = -(GPIO_KEY1_NP - GPIO_KEY1); } + if ((val >= GPIO_KEY1_INV) && (val < GPIO_KEY1_INV + MAX_KEYS)) { + offset = -(GPIO_KEY1_INV - GPIO_KEY1); + } + if ((val >= GPIO_KEY1_INV_NP) && (val < GPIO_KEY1_INV_NP + MAX_KEYS)) { + offset = -(GPIO_KEY1_INV_NP - GPIO_KEY1); + } if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) { offset = (GPIO_SWT1_NP - GPIO_SWT1); From a770f54e9022a45b6a3b538f375ed4a23b293550 Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Tue, 29 Jan 2019 06:58:52 +0000 Subject: [PATCH 0910/2222] misplaced #endif fixed --- sonoff/xdrv_20_sm16717.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_20_sm16717.ino b/sonoff/xdrv_20_sm16717.ino index 7b367fc2f..0016efc2e 100644 --- a/sonoff/xdrv_20_sm16717.ino +++ b/sonoff/xdrv_20_sm16717.ino @@ -369,8 +369,8 @@ boolean Xdrv20(byte function) snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_COMMAND")); AddLog(LOG_LEVEL_DEBUG); - return SM16716_Command(); #endif + return SM16716_Command(); //case FUNC_SET_POWER: case FUNC_SET_DEVICE_POWER: From 34692eeef3e0d15552b7fe4a986f9d50c72422c4 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Tue, 29 Jan 2019 11:48:20 +0100 Subject: [PATCH 0911/2222] Device support add note that mainly sonoff devices are supported. NOT all --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 1d2ad635b..be308c54d 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocu We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site. +### Note +Please dont ask too add devices where you cant provide a basic working configuration (other than sonoff). Since there are thousands of them.. + ### Quick Install Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki. From c1012e32b51dab109e7dee68f689c9bd75bec195 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Tue, 29 Jan 2019 11:52:18 +0100 Subject: [PATCH 0912/2222] Add Note Not all devices can be supported. Focus sonoff --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 1d2ad635b..be308c54d 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocu We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site. +### Note +Please dont ask too add devices where you cant provide a basic working configuration (other than sonoff). Since there are thousands of them.. + ### Quick Install Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki. From a370f85a8bb5ed057deb14a446284024f0365dca Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 29 Jan 2019 13:37:59 +0100 Subject: [PATCH 0913/2222] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index be308c54d..0184e7cc5 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocu We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site. ### Note -Please dont ask too add devices where you cant provide a basic working configuration (other than sonoff). Since there are thousands of them.. +Please do not ask to add devices where you can't provide a basic working configuration (other than sonoff). Since there are thousands of them.. ### Quick Install Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki. From e2d80403382c08d6ff06e104ddc7512dd8f9781a Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Wed, 30 Jan 2019 07:05:38 +0000 Subject: [PATCH 0914/2222] Type changed from boolean to bool applied to xdrv_20_sm16716.ino as well The upstream commit that changed the types in the interface: commit 304ac6fe44c9ba9aca4478036555e9eaa442dc9b Author: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon Jan 28 14:08:33 2019 +0100 6.4.1.12 code changes (byte/boolean) --- sonoff/xdrv_20_sm16717.ino | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sonoff/xdrv_20_sm16717.ino b/sonoff/xdrv_20_sm16717.ino index 0016efc2e..1dada4c9c 100644 --- a/sonoff/xdrv_20_sm16717.ino +++ b/sonoff/xdrv_20_sm16717.ino @@ -40,8 +40,8 @@ const char k_SM16716_Commands[] PROGMEM = uint8_t sm16716_pin_clk = 100; uint8_t sm16716_pin_dat = 100; -boolean sm16716_is_selected = false; -boolean sm16716_is_on = false; +bool sm16716_is_selected = false; +bool sm16716_is_on = false; uint8_t sm16716_color[3] = {0, 0, 0}; int8_t sm16716_color_preset = 0; @@ -83,7 +83,7 @@ void SM16716_Append_JSON(void) /*********************************************************************************************/ -boolean SM16716_Show_State(void) +bool SM16716_Show_State(void) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_COLOR "\":\"%02x%02x%02x\"}"), @@ -127,7 +127,7 @@ void SM16716_Update() /*********************************************************************************************/ -boolean SM16716_ModuleSelected(void) +bool SM16716_ModuleSelected(void) { sm16716_pin_clk = pin[GPIO_SM16716_CLK]; sm16716_pin_dat = pin[GPIO_SM16716_DAT]; @@ -143,7 +143,7 @@ boolean SM16716_ModuleSelected(void) /*********************************************************************************************/ -boolean SM16716_Init(void) +bool SM16716_Init(void) { uint8_t t_init; @@ -169,7 +169,7 @@ boolean SM16716_Init(void) /* Try to parse a string as 'RRGGBB' hex-encoded color value * Accept only exact match (i.e. there can be no leftover chars) */ -boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { +bool SM16716_Parse_RRGGBB(const char *data, int data_len) { char component[3]; char *endptr = NULL; uint8_t candidate[3]; @@ -214,7 +214,7 @@ boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { /*********************************************************************************************/ -boolean SM16716_Parse_Color(char *data, int data_len) { +bool SM16716_Parse_Color(char *data, int data_len) { /* NOTE: Very similar to 'LightColorEntry', but can't reuse it here, because * 'light_type' must be PWM, and then it won't parse the color components. */ @@ -345,7 +345,7 @@ bool SM16716_Command(void) /*********************************************************************************************\ * Interface \*********************************************************************************************/ -boolean Xdrv20(byte function) +bool Xdrv20(uint8_t function) { if (function == FUNC_MODULE_INIT) { return SM16716_ModuleSelected(); From cb13e8b05e6a486285e07d3490f44d8ba674361d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Jan 2019 14:33:20 +0100 Subject: [PATCH 0915/2222] Update xdrv_12_home_assistant.ino Minor gain in string length --- sonoff/xdrv_12_home_assistant.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 80c5b4ebe..6b6d1bff3 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -67,7 +67,7 @@ const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = "%s,\"whit_val_cmd_t\":\"%s\"," // cmnd/led2/White "\"whit_val_stat_t\":\"%s\"," // stat/led2/RESULT "\"white_value_scale\":100," // (No abbreviation defined) - "\"whit_val_tpl\":\"{{ value_json.Channel[3] }}\""; + "\"whit_val_tpl\":\"{{value_json.Channel[3]}}\""; const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = "%s,\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT From 2c164a8b4b80d4c4d355bdfcbb84831f2c009011 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Jan 2019 14:34:31 +0100 Subject: [PATCH 0916/2222] 6.4.1.13 Add boot loop offset 6.4.1.13 20190130 * Add command SetOption36 to control boot loop default restoration (#4645, #5063) --- sonoff/_changelog.ino | 5 ++++- sonoff/my_user_config.h | 1 + sonoff/settings.ino | 3 +++ sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 42 +++++++++++++++++++++-------------------- sonoff/sonoff_version.h | 2 +- 6 files changed, 32 insertions(+), 23 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 78200f2d8..d35493110 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.12 20190128 +/* 6.4.1.13 20190130 + * Add command SetOption36 to control boot loop default restoration (#4645, #5063) + * + * 6.4.1.12 20190128 * Change code use of boolean to bool and byte to uint8_t * Change code uint8_t flags to bool flags * diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 83bbb7b65..c9c6505d5 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -54,6 +54,7 @@ #define SAVE_DATA 1 // [SaveData] Save changed parameters to Flash (0 = disable, 1 - 3600 seconds) #define SAVE_STATE 1 // [SetOption0] Save changed power state to Flash (0 = disable, 1 = enable) +#define BOOT_LOOP_OFFSET 1 // [SetOption36] Number of boot loops before starting restoring defaults (0 = disable, 1..200 = boot loops offset) // -- Wifi ---------------------------------------- #define WIFI_IP_ADDRESS "0.0.0.0" // [IpAddress1] Set to 0.0.0.0 for using DHCP or enter a static IP address diff --git a/sonoff/settings.ino b/sonoff/settings.ino index c1b84cafa..8f5107858 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -1027,6 +1027,9 @@ void SettingsDelta(void) Settings.interlock[0] = 0xFF; // Legacy support using all relays in one interlock group for (uint8_t i = 1; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } } + if (Settings.version < 0x0604010D) { + Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 699d8c819..9ba91f091 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -227,7 +227,7 @@ enum ButtonStates { PRESSED, NOT_PRESSED }; enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; -enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 +enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_MAX_SENSORS}; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 936f7930e..88e0ee3ce 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2484,30 +2484,32 @@ void setup(void) Settings.flag2.emulation = 0; #endif // USE_EMULATION - // Disable functionality as possible cause of fast restart within BOOT_LOOP_TIME seconds (Exception, WDT or restarts) - if (RtcReboot.fast_reboot_count > 1) { // Restart twice - Settings.flag3.user_esp8285_enable = 0; // Disable ESP8285 Generic GPIOs interfering with flash SPI - if (RtcReboot.fast_reboot_count > 2) { // Restart 3 times - for (uint8_t i = 0; i < MAX_RULE_SETS; i++) { - if (bitRead(Settings.rule_stop, i)) { - bitWrite(Settings.rule_enabled, i, 0); // Disable rules causing boot loop + if (Settings.param[P_BOOT_LOOP_OFFSET]) { + // Disable functionality as possible cause of fast restart within BOOT_LOOP_TIME seconds (Exception, WDT or restarts) + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET]) { // Restart twice + Settings.flag3.user_esp8285_enable = 0; // Disable ESP8285 Generic GPIOs interfering with flash SPI + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +1) { // Restart 3 times + for (uint8_t i = 0; i < MAX_RULE_SETS; i++) { + if (bitRead(Settings.rule_stop, i)) { + bitWrite(Settings.rule_enabled, i, 0); // Disable rules causing boot loop + } } } - } - if (RtcReboot.fast_reboot_count > 3) { // Restarted 4 times - Settings.rule_enabled = 0; // Disable all rules - } - if (RtcReboot.fast_reboot_count > 4) { // Restarted 5 times - for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { - Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +2) { // Restarted 4 times + Settings.rule_enabled = 0; // Disable all rules } + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +3) { // Restarted 5 times + for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { + Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors + } + } + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { // Restarted 6 times + Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic + // Settings.last_module = SONOFF_BASIC; + } + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); + AddLog(LOG_LEVEL_DEBUG); } - if (RtcReboot.fast_reboot_count > 5) { // Restarted 6 times - Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic -// Settings.last_module = SONOFF_BASIC; - } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); - AddLog(LOG_LEVEL_DEBUG); } Format(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 83db36b91..099c8955f 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0604010C +#define VERSION 0x0604010D #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" From 0007df121aeedcfcb59708fb4660fe448c2d96a2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Jan 2019 15:14:24 +0100 Subject: [PATCH 0917/2222] Update settings.ino Fix for new installs --- sonoff/settings.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 8f5107858..03003d5c3 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -567,6 +567,7 @@ void SettingsDefaultSet2(void) // Settings.flag.value_units = 0; // Settings.flag.stop_flash_rotate = 0; Settings.save_data = SAVE_DATA; + Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; Settings.sleep = APP_SLEEP; if (Settings.sleep < 50) { Settings.sleep = 50; // Default to 50 for sleep, for now From 9825d6ffb6ff9e516e1b9c9dcd4c91a29088bde3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Jan 2019 16:27:17 +0100 Subject: [PATCH 0918/2222] Add resiliency to saved Settings Add resiliency to saved Settings (#5065) --- sonoff/_changelog.ino | 1 + sonoff/settings.ino | 45 ++++++++++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index d35493110..ab986d522 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.4.1.13 20190130 * Add command SetOption36 to control boot loop default restoration (#4645, #5063) + * Add resiliency to saved Settings (#5065) * * 6.4.1.12 20190128 * Change code use of boolean to bool and byte to uint8_t diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 03003d5c3..13634d541 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -447,31 +447,50 @@ void SettingsSave(uint8_t rotate) void SettingsLoad(void) { -/* Load configuration from eeprom or one of 7 slots below if first load does not stop_flash_rotate - */ + // Load configuration from eeprom or one of 7 slots below if first valid load does not stop_flash_rotate struct SYSCFGH { uint16_t cfg_holder; // 000 uint16_t cfg_size; // 002 unsigned long save_flag; // 004 } _SettingsH; + unsigned long save_flag = 0; - bool bad_crc = false; - settings_location = SETTINGS_LOCATION +1; + settings_location = 0; + uint32_t flash_location = SETTINGS_LOCATION +1; for (uint8_t i = 0; i < CFG_ROTATES; i++) { - settings_location--; - ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - ESP.flashRead((settings_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); - if (Settings.version > 0x06000000) { bad_crc = (Settings.cfg_crc != GetSettingsCrc()); } - if (Settings.flag.stop_flash_rotate || bad_crc || (Settings.cfg_holder != _SettingsH.cfg_holder) || (Settings.save_flag > _SettingsH.save_flag)) { - break; + flash_location--; + ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + + bool valid = false; + if (Settings.version > 0x06000000) { + valid = (Settings.cfg_crc == GetSettingsCrc()); + } else { + ESP.flashRead((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); + valid = (Settings.cfg_holder == _SettingsH.cfg_holder); } + if (valid) { + if (Settings.save_flag > save_flag) { + save_flag = Settings.save_flag; + settings_location = flash_location; + if (Settings.flag.stop_flash_rotate) { + break; + } + } + } + delay(1); } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %d"), settings_location, Settings.save_flag); - AddLog(LOG_LEVEL_DEBUG); + if (settings_location > 0) { + ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %d"), + settings_location, Settings.save_flag); + AddLog(LOG_LEVEL_DEBUG); + } #ifndef BE_MINIMAL - if (bad_crc || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { SettingsDefault(); } + if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { // Init defaults if cfg_holder differs from user settings in my_user_config.h + SettingsDefault(); + } settings_crc = GetSettingsCrc(); #endif // BE_MINIMAL From ed41370d24d9c94fa8bf1a820e6fb5495e1ca630 Mon Sep 17 00:00:00 2001 From: netpok Date: Wed, 30 Jan 2019 19:44:48 +0100 Subject: [PATCH 0919/2222] Add Tuya SP10 --- sonoff/sonoff_template.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 3385930f4..99f4d1458 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -292,6 +292,7 @@ enum SupportedModules { KA10, ZX2820, MI_DESK_LAMP, + SP10, MAXMODULE }; /********************************************************************************************/ @@ -572,6 +573,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { SK03_TUYA, DIGOO, KA10, + SP10, NEO_COOLCAM, // Socket Relay Devices OBI, OBI2, @@ -1793,6 +1795,25 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_ROT_A, // GPIO12 Rotary switch A pin GPIO_ROT_B, // GPIO13 Rotary switch B pin 0, 0, 0, 0 + }, + { "SP10", // Tuya SP10 (ESP8285 - BL0937 Energy Monitoring) + // https://www.aliexpress.com/item/Smart-Mini-WiFi-Plug-Outlet-Switch-Work-With-ForEcho-Alexa-Google-Home-Remote-EU-Smart-Socket/32963670423.html + 0, // GPIO00 + GPIO_PWM1, // GPIO01 Nightlight + 0, // GPIO02 + GPIO_KEY1, // GPIO03 Button + GPIO_HJL_CF, // GPIO04 BL0937 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 CF1 voltage / current + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage) + GPIO_LED1, // GPIO13 Blue LED - Link status + GPIO_REL1, // GPIO14 Relay 1 and red LED + 0, 0, 0 } }; From 3a43050d93fdf1afce468cd7f0c3c8bb15d374a0 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 17:19:40 -0500 Subject: [PATCH 0920/2222] Integrated Gabor's SM16716 code into the light driver code Removed redundant processing and variables Added new light type to distinguish SM16716 devices --- sonoff/sonoff.ino | 6 + sonoff/xdrv_04_light.ino | 106 ++++++++++ sonoff/xdrv_20_sm16717.ino | 400 ------------------------------------- 3 files changed, 112 insertions(+), 400 deletions(-) delete mode 100644 sonoff/xdrv_20_sm16717.ino diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 936f7930e..fbf256134 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2422,6 +2422,12 @@ void GpioInit(void) light_type = LT_WS2812; } #endif // USE_WS2812 +#ifdef USE_SM16716 + if (SM16716_ModuleSelected()) { + light_type += 3; + light_type |= 16; + } +#endif // ifdef USE_SM16716 if (!light_type) { for (uint8_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only if (pin[GPIO_PWM1 +i] < 99) { diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 9d8740ccb..2dc098c80 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -32,6 +32,9 @@ * 11 +WS2812 RGB(W) no (One WS2812 RGB or RGBW ledstrip) * 12 AiLight RGBW no * 13 Sonoff B1 RGBCW yes + * 19 SM16716 RGB no + * 20 SM16716+W RGBW no + * 21 SM16716+CW RGBCW yes * * light_scheme WS2812 3+ Colors 1+2 Colors Effect * ------------ ------ --------- ---------- ----------------- @@ -354,6 +357,99 @@ void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t dut os_delay_us(12); // TStop > 12us. } +#ifdef USE_SM16716 +/*********************************************************************************************\ + * SM16716 - Controlling RGB over a synchronous serial line + * Copyright (C) 2019 Gabor Simon + * + * Source: https://community.home-assistant.io/t/cheap-uk-wifi-bulbs-with-tasmota-teardown-help-tywe3s/40508/27 + * +\*********************************************************************************************/ + +// Enable this for debug logging +//#define D_LOG_SM16716 "SM16716: " + +uint8_t sm16716_pin_clk = 100; +uint8_t sm16716_pin_dat = 100; + +void SM16716_SendBit(uint8_t v) +{ + /* NOTE: + * According to the spec sheet, max freq is 30 MHz, that is 16.6 ns per high/low half of the + * clk square wave. That is less than the overhead of 'digitalWrite' at this clock rate, + * so no additional delays are needed yet. */ + + digitalWrite(sm16716_pin_dat, (v != 0) ? HIGH : LOW); + //delayMicroseconds(1); + digitalWrite(sm16716_pin_clk, HIGH); + //delayMicroseconds(1); + digitalWrite(sm16716_pin_clk, LOW); +} + +void SM16716_SendByte(uint8_t v) +{ + uint8_t mask; + + for (mask = 0x80; mask; mask >>= 1) { + SM16716_SendBit(v & mask); + } +} + +void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) +{ +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), + duty_r, duty_g, duty_b); + AddLog(LOG_LEVEL_DEBUG); +#endif // D_LOG_SM16716 + + // send start bit + SM16716_SendBit(1); + // send 24-bit rgb data + SM16716_SendByte(duty_r); + SM16716_SendByte(duty_g); + SM16716_SendByte(duty_g); + // send a 'do it' pulse + // (if multiple chips are chained, each one processes the 1st '1rgb' 25-bit block and + // passes on the rest, right until the one starting with 0) + SM16716_SendBit(0); + SM16716_SendByte(0); + SM16716_SendByte(0); + SM16716_SendByte(0); + SM16716_Show_State(); +} + +bool SM16716_ModuleSelected(void) +{ + sm16716_pin_clk = pin[GPIO_SM16716_CLK]; + sm16716_pin_dat = pin[GPIO_SM16716_DAT]; +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), + sm16716_pin_clk, sm16716_pin_dat); + AddLog(LOG_LEVEL_DEBUG); +#endif // D_LOG_SM16716 + return (sm16716_pin_clk < 99) && (sm16716_pin_dat < 99); +} + +bool SM16716_Init(void) +{ + uint8_t t_init; + + pinMode(sm16716_pin_clk, OUTPUT); + digitalWrite(sm16716_pin_clk, LOW); + + pinMode(sm16716_pin_dat, OUTPUT); + digitalWrite(sm16716_pin_dat, LOW); + + for (t_init = 0; t_init < 50; ++t_init) { + SM16716_SendBit(0); + } + + return true; +} + /********************************************************************************************/ void LightInit(void) @@ -402,6 +498,11 @@ void LightInit(void) max_scheme = LS_MAX + WS2812_SCHEMES; } #endif // USE_WS2812 ************************************************************************ +#ifdef USE_SM16716 + else if (16 & light_type) { + SM16716_Init(); + } +#endif // ifdef USE_SM16716 else { light_pdi_pin = pin[GPIO_DI]; light_pdcki_pin = pin[GPIO_DCKI]; @@ -844,6 +945,11 @@ void LightAnimate(void) Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2], cur_col[3]); } #endif // USE_ES2812 ************************************************************************ +#ifdef USE_SM16716 + else if (16 & light_type) { + SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); + } +#endif // ifdef USE_SM16716 else if (light_type > LT_WS2812) { LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); } diff --git a/sonoff/xdrv_20_sm16717.ino b/sonoff/xdrv_20_sm16717.ino deleted file mode 100644 index 1dada4c9c..000000000 --- a/sonoff/xdrv_20_sm16717.ino +++ /dev/null @@ -1,400 +0,0 @@ -/* - xdrv_20_sm16716.ino - SM16716 RGB led controller support for Sonoff-Tasmota - - Copyright (C) 2019 Gabor Simon - - 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_SM16716 - -/*********************************************************************************************\ - * SM16716 - Controlling RGB over a synchronous serial line - * - * Source: https://community.home-assistant.io/t/cheap-uk-wifi-bulbs-with-tasmota-teardown-help-tywe3s/40508/27 - * -\*********************************************************************************************/ - -#define XDRV_20 20 - -// Enable this for debug logging -//#define D_LOG_SM16716 "SM16716: " - -enum SM16716_Commands { - CMND_SM16716_COLOR }; - -const char k_SM16716_Commands[] PROGMEM = - D_CMND_COLOR ; - -uint8_t sm16716_pin_clk = 100; -uint8_t sm16716_pin_dat = 100; - -bool sm16716_is_selected = false; -bool sm16716_is_on = false; -uint8_t sm16716_color[3] = {0, 0, 0}; -int8_t sm16716_color_preset = 0; - - -/*********************************************************************************************/ -void SM16716_SendBit(uint8_t v) -{ - /* NOTE: - * According to the spec sheet, max freq is 30 MHz, that is 16.6 ns per high/low half of the - * clk square wave. That is less than the overhead of 'digitalWrite' at this clock rate, - * so no additional delays are needed yet. */ - - digitalWrite(sm16716_pin_dat, (v != 0) ? HIGH : LOW); - //delayMicroseconds(1); - digitalWrite(sm16716_pin_clk, HIGH); - //delayMicroseconds(1); - digitalWrite(sm16716_pin_clk, LOW); -} - - -/*********************************************************************************************/ -void SM16716_SendByte(uint8_t v) -{ - uint8_t mask; - - for (mask = 0x80; mask; mask >>= 1) { - SM16716_SendBit(v & mask); - } -} - - -/*********************************************************************************************/ -void SM16716_Append_JSON(void) -{ - snprintf_P(mqtt_data, sizeof(mqtt_data), - PSTR("%s,\"SM16716\":{\"Red\":%d,\"Green\":%d,\"Blue\":%d}"), - mqtt_data, sm16716_color[0], sm16716_color[1], sm16716_color[2]); -} - - -/*********************************************************************************************/ -bool SM16716_Show_State(void) -{ - snprintf_P(mqtt_data, sizeof(mqtt_data), - PSTR("{\"" D_CMND_COLOR "\":\"%02x%02x%02x\"}"), - sm16716_color[0], sm16716_color[1], sm16716_color[2]); - return true; -} - - -/*********************************************************************************************/ -void SM16716_Update() -{ -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Update; pwr=%02x, rgb=%02x%02x%02x"), - sm16716_is_on, sm16716_color[0], sm16716_color[1], sm16716_color[2]); - AddLog(LOG_LEVEL_DEBUG); -#endif // D_LOG_SM16716 - - // send start bit - SM16716_SendBit(1); - // send 24-bit rgb data - if (sm16716_is_on) { - SM16716_SendByte(sm16716_color[0]); - SM16716_SendByte(sm16716_color[1]); - SM16716_SendByte(sm16716_color[2]); - } - else { - SM16716_SendByte(0); - SM16716_SendByte(0); - SM16716_SendByte(0); - } - // send a 'do it' pulse - // (if multiple chips are chained, each one processes the 1st '1rgb' 25-bit block and - // passes on the rest, right until the one starting with 0) - SM16716_SendBit(0); - SM16716_SendByte(0); - SM16716_SendByte(0); - SM16716_SendByte(0); - SM16716_Show_State(); -} - - -/*********************************************************************************************/ -bool SM16716_ModuleSelected(void) -{ - sm16716_pin_clk = pin[GPIO_SM16716_CLK]; - sm16716_pin_dat = pin[GPIO_SM16716_DAT]; -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), - sm16716_pin_clk, sm16716_pin_dat); - AddLog(LOG_LEVEL_DEBUG); -#endif // D_LOG_SM16716 - sm16716_is_selected = (sm16716_pin_clk < 99) && (sm16716_pin_dat < 99); - return sm16716_is_selected; -} - - -/*********************************************************************************************/ -bool SM16716_Init(void) -{ - uint8_t t_init; - - if (!SM16716_ModuleSelected()) { - return false; - } - - pinMode(sm16716_pin_clk, OUTPUT); - digitalWrite(sm16716_pin_clk, LOW); - - pinMode(sm16716_pin_dat, OUTPUT); - digitalWrite(sm16716_pin_dat, LOW); - - for (t_init = 0; t_init < 50; ++t_init) { - SM16716_SendBit(0); - } - - return true; -} - - -/*********************************************************************************************/ -/* Try to parse a string as 'RRGGBB' hex-encoded color value - * Accept only exact match (i.e. there can be no leftover chars) - */ -bool SM16716_Parse_RRGGBB(const char *data, int data_len) { - char component[3]; - char *endptr = NULL; - uint8_t candidate[3]; - int i; - -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Parse_RRGGBB; data='%s', data_len=%d"), - data, data_len); - AddLog(LOG_LEVEL_DEBUG); -#endif // D_LOG_SM16716 - - if (data_len != 6) { - // too long or too short - return false; - } - - // a component is exactly 3 chars, so terminate the string now - component[2] = '\0'; - - // try to parse 3 components - for (i = 0; i < 3; ++i) { - // copy the value to the temp string - component[0] = data[0]; - component[1] = data[1]; - // try to interpret it as a hex number - candidate[i] = (uint8_t)strtoul(component, &endptr, 16); - if (!endptr || *endptr) { - // not a valid hex number - return false; - } - // advance to the next 2 characters - data += 2; - } - - // now that we have all 3, we may change sm16716_color[] - sm16716_color[0] = candidate[0]; - sm16716_color[1] = candidate[1]; - sm16716_color[2] = candidate[2]; - return true; -} - - -/*********************************************************************************************/ -bool SM16716_Parse_Color(char *data, int data_len) { - /* NOTE: Very similar to 'LightColorEntry', but can't reuse it here, because - * 'light_type' must be PWM, and then it won't parse the color components. */ - -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Parse_Color; data='%s', data_len=%d"), - data, data_len); - AddLog(LOG_LEVEL_DEBUG); -#endif // D_LOG_SM16716 - - if (data_len < 3) { // too short for color literal: try to interpret as a color preset - // check for '+' and '-' commands first - switch (data[0]) { - case '+': // advance to the next preset, handle wrap-around - ++sm16716_color_preset; - if (sm16716_color_preset >= MAX_FIXED_COLOR) { - sm16716_color_preset = 0; - } - break; - - case '-': // return to the previous preset, handle wrap-around - --sm16716_color_preset; - if (sm16716_color_preset < 0) { - sm16716_color_preset = MAX_FIXED_COLOR - 1; - } - break; - - default: - // try to interpret it as a decimal integer - { - char *endptr = NULL; - uint8_t candidate = (uint8_t)strtoul(data, &endptr, 10); - if (!endptr || *endptr || (candidate < 0) || (MAX_FIXED_COLOR <= candidate)) { - // it's not a valid integer (and nothing else), or the number is not a valid preset index - return false; - } - // we have the requested preset index - sm16716_color_preset = candidate; - } - break; - } - -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Parse_Color; preset=%d"), - sm16716_color_preset); - AddLog(LOG_LEVEL_DEBUG); -#endif // D_LOG_SM16716 - - // copy the requested preset values - memcpy_P(sm16716_color, &kFixedColor[sm16716_color_preset], 3); - } - else if (data[0] == '#') { // starts with #, so try to interpret as #RRGGBB - if (!SM16716_Parse_RRGGBB(data + 1, data_len - 1)) { - // not a valid RRGGBB after the # - return false; - } - } - // two more formats left: RRGGBB (without #) and comma separated color components - else if (SM16716_Parse_RRGGBB(data, data_len)) { // try to interpret as RRGGBB - // parsed successfully as RRGGBB, nothing more to do - } - else { // try to interpret as rrr,g,bb - uint8_t candidate[3]; - char *tok, *last, *endptr = NULL; - int i; - - // try to parse the first 3 comma-separated tokens - for (i = 0; i < 3; ++i) { - // try to isolate the next token - tok = strtok_r(data, ",", &last); - if (!tok) { - // we're beyond the end of string: there were too few tokens - return false; - } - // try to interpret the token as integer - candidate[i] = (uint8_t)strtoul(tok, &endptr, 0); - if (!endptr || *endptr) { - // not a valid integer - return false; - } - // in the next cycle just continue this token-processing session - data = NULL; - } - // there shouldn't be any leftover characters (i.e. we need exactly 3 components) - tok = strtok_r(NULL, ",", &last); - if (tok) { - // too many components - return false; - } - // now that we have all 3 components, we may change sm16716_color - sm16716_color[0] = candidate[0]; - sm16716_color[1] = candidate[1]; - sm16716_color[2] = candidate[2]; - } - return true; -} - - -/*********************************************************************************************/ -bool SM16716_Command(void) -{ - char command [CMDSZ]; - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, k_SM16716_Commands); - -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Command; topic='%s', data_len=%d, data='%s', code=%d"), - XdrvMailbox.topic, XdrvMailbox.data_len, XdrvMailbox.data, command_code); - AddLog(LOG_LEVEL_DEBUG); -#endif // D_LOG_SM16716 - - switch (command_code) { - case CMND_SM16716_COLOR: - if (XdrvMailbox.data_len == 0) { - return SM16716_Show_State(); - } - if (!SM16716_Parse_Color(XdrvMailbox.data, XdrvMailbox.data_len)) { - return false; - } - SM16716_Update(); - return true; - } - return false; // Unknown command -} - - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ -bool Xdrv20(uint8_t function) -{ - if (function == FUNC_MODULE_INIT) { - return SM16716_ModuleSelected(); - } - - if (!sm16716_is_selected) { - return false; - } - - switch (function) { - case FUNC_INIT: -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Entry; function=FUNC_INIT")); - AddLog(LOG_LEVEL_DEBUG); -#endif - return SM16716_Init(); - - case FUNC_COMMAND: -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Entry; function=FUNC_COMMAND")); - AddLog(LOG_LEVEL_DEBUG); -#endif - return SM16716_Command(); - - //case FUNC_SET_POWER: - case FUNC_SET_DEVICE_POWER: -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Entry; function=FUNC_SET_DEVICE_POWER, index=%02x, payload=%02x"), - XdrvMailbox.index, XdrvMailbox.payload); - AddLog(LOG_LEVEL_DEBUG); -#endif - sm16716_is_on = (XdrvMailbox.index != 0); - SM16716_Update(); - return false; // don't catch the event - - case FUNC_JSON_APPEND: -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Entry; function=FUNC_JSON_APPEND")); - AddLog(LOG_LEVEL_DEBUG); -#endif - SM16716_Append_JSON(); - break; - } - return false; -} - -#endif // USE_SM16716 -// vim: set ft=c sw=2 ts=2 et: From fa7440fb9afca4baa2db8fb6d83d622e8ebc90ef Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 17:28:25 -0500 Subject: [PATCH 0921/2222] Allow PWM while SM16716 is enabled, for mixed control devices --- sonoff/xdrv_04_light.ino | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 2dc098c80..90ef446ae 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -500,6 +500,13 @@ void LightInit(void) #endif // USE_WS2812 ************************************************************************ #ifdef USE_SM16716 else if (16 & light_type) { + // init PWM + for (uint8_t i = 0; i < light_subtype; i++) { + Settings.pwm_value[i] = 0; // Disable direct PWM control + if (pin[GPIO_PWM1 +i] < 99) { + pinMode(pin[GPIO_PWM1 +i], OUTPUT); + } + } SM16716_Init(); } #endif // ifdef USE_SM16716 @@ -919,7 +926,7 @@ void LightAnimate(void) light_last_color[i] = light_new_color[i]; cur_col[i] = light_last_color[i]*Settings.rgbwwTable[i]/255; cur_col[i] = (Settings.light_correction) ? ledTable[cur_col[i]] : cur_col[i]; - if (light_type < LT_PWM6) { + if (light_type < LT_PWM6 || light_type & 16) { if (pin[GPIO_PWM1 +i] < 99) { if (cur_col[i] > 0xFC) { cur_col[i] = 0xFC; // Fix unwanted blinking and PWM watchdog errors for values close to pwm_range (H801, Arilux and BN-SZ01) From ec984ab841d605225d33c723682da5de6f715d53 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 17:32:17 -0500 Subject: [PATCH 0922/2222] Fixed compiler errors Missing #endif oops Vestigial function call --- sonoff/xdrv_04_light.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 90ef446ae..b60d0e64b 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -417,7 +417,6 @@ void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) SM16716_SendByte(0); SM16716_SendByte(0); SM16716_SendByte(0); - SM16716_Show_State(); } bool SM16716_ModuleSelected(void) @@ -450,6 +449,8 @@ bool SM16716_Init(void) return true; } +#endif // ifdef USE_SM16716 + /********************************************************************************************/ void LightInit(void) From adcfeeaed5923307c857a5d7b87f5df9a1d6f0b1 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 17:57:47 -0500 Subject: [PATCH 0923/2222] Fixed bug in web config page caused by merge from dev --- sonoff/sonoff_template.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index e050dc882..809b0e390 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -221,7 +221,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX "|" D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO "|" D_SENSOR_BUTTON "1i|" D_SENSOR_BUTTON "2i|" D_SENSOR_BUTTON "3i|" D_SENSOR_BUTTON "4i|" - D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in" + D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in|" D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT ; From 4b6ddfb76f3a188a12618ecf95e0a95a66bfa939 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 18:15:25 -0500 Subject: [PATCH 0924/2222] Moved PWM control to its own block while using SM16716 to skip RGB values --- sonoff/xdrv_04_light.ino | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index b60d0e64b..d58207331 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -367,7 +367,7 @@ void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t dut \*********************************************************************************************/ // Enable this for debug logging -//#define D_LOG_SM16716 "SM16716: " +#define D_LOG_SM16716 "SM16716: " uint8_t sm16716_pin_clk = 100; uint8_t sm16716_pin_dat = 100; @@ -927,7 +927,7 @@ void LightAnimate(void) light_last_color[i] = light_new_color[i]; cur_col[i] = light_last_color[i]*Settings.rgbwwTable[i]/255; cur_col[i] = (Settings.light_correction) ? ledTable[cur_col[i]] : cur_col[i]; - if (light_type < LT_PWM6 || light_type & 16) { + if (light_type < LT_PWM6) { if (pin[GPIO_PWM1 +i] < 99) { if (cur_col[i] > 0xFC) { cur_col[i] = 0xFC; // Fix unwanted blinking and PWM watchdog errors for values close to pwm_range (H801, Arilux and BN-SZ01) @@ -956,6 +956,17 @@ void LightAnimate(void) #ifdef USE_SM16716 else if (16 & light_type) { SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); + for (uint8_t i = 3; i < light_subtype; i++) { + if (pin[GPIO_PWM1 +i-3] < 99) { + if (cur_col[i] > 0xFC) { + cur_col[i] = 0xFC; // Fix unwanted blinking and PWM watchdog errors for values close to pwm_range (H801, Arilux and BN-SZ01) + } + 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-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - curcol : curcol); + } + } } #endif // ifdef USE_SM16716 else if (light_type > LT_WS2812) { From f60dd3c06aff4612f0fd663e4717d5af77ddcf0a Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 18:32:37 -0500 Subject: [PATCH 0925/2222] Moved pin mode selection for sm16716 out of init function Made void Call SM16716_Init before setting the color --- sonoff/xdrv_04_light.ino | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index d58207331..0591da5bb 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -432,21 +432,11 @@ bool SM16716_ModuleSelected(void) return (sm16716_pin_clk < 99) && (sm16716_pin_dat < 99); } -bool SM16716_Init(void) +void SM16716_Init(void) { - uint8_t t_init; - - pinMode(sm16716_pin_clk, OUTPUT); - digitalWrite(sm16716_pin_clk, LOW); - - pinMode(sm16716_pin_dat, OUTPUT); - digitalWrite(sm16716_pin_dat, LOW); - - for (t_init = 0; t_init < 50; ++t_init) { + for (uint8_t t_init = 0; t_init < 50; ++t_init) { SM16716_SendBit(0); } - - return true; } #endif // ifdef USE_SM16716 @@ -508,6 +498,13 @@ void LightInit(void) pinMode(pin[GPIO_PWM1 +i], OUTPUT); } } + // init sm16716 + pinMode(sm16716_pin_clk, OUTPUT); + digitalWrite(sm16716_pin_clk, LOW); + + pinMode(sm16716_pin_dat, OUTPUT); + digitalWrite(sm16716_pin_dat, LOW); + SM16716_Init(); } #endif // ifdef USE_SM16716 @@ -955,7 +952,6 @@ void LightAnimate(void) #endif // USE_ES2812 ************************************************************************ #ifdef USE_SM16716 else if (16 & light_type) { - SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); for (uint8_t i = 3; i < light_subtype; i++) { if (pin[GPIO_PWM1 +i-3] < 99) { if (cur_col[i] > 0xFC) { @@ -967,6 +963,10 @@ void LightAnimate(void) analogWrite(pin[GPIO_PWM1 +i-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - curcol : curcol); } } + if(cur_col[0] | cur_col[1] | cur_col[2]){ + SM16716_Init(); + } + SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); } #endif // ifdef USE_SM16716 else if (light_type > LT_WS2812) { From 1c76991c7fb3c89d7ca5b1dd4349bd47a0e54e68 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Thu, 31 Jan 2019 13:28:38 -0500 Subject: [PATCH 0926/2222] Added sm16716 select to the pin definitions --- sonoff/language/bg-BG.h | 1 + sonoff/language/cs-CZ.h | 1 + sonoff/language/de-DE.h | 1 + sonoff/language/el-GR.h | 1 + sonoff/language/en-GB.h | 1 + sonoff/language/es-AR.h | 1 + sonoff/language/fr-FR.h | 1 + sonoff/language/he-HE.h | 1 + sonoff/language/hu-HU.h | 1 + sonoff/language/it-IT.h | 1 + sonoff/language/nl-NL.h | 1 + sonoff/language/pl-PL.h | 1 + sonoff/language/pt-BR.h | 1 + sonoff/language/pt-PT.h | 1 + sonoff/language/ru-RU.h | 1 + sonoff/language/sk-SK.h | 1 + sonoff/language/sv-SE.h | 1 + sonoff/language/tr-TR.h | 1 + sonoff/language/uk-UK.h | 1 + sonoff/language/zh-CN.h | 1 + sonoff/language/zh-TW.h | 1 + sonoff/sonoff_template.h | 12 +++++++----- 22 files changed, 28 insertions(+), 5 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 03c1b9f32..6c3f4556a 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index c87260f71..38c80d158 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 692c74e17..607c781da 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 81a017a0b..0a385a966 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 9644e8b4d..34dc71c4a 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index a2f8bcf8a..597be23db 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index b9fa0d423..41da8c895 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 22f9677b5..96c14b0e5 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index b6dd5b55a..628a12770 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index fa3c0b533..90a967057 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 684545acf..cb3c9913c 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 8e677b554..1e50d2f6b 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 1d708f072..f86addf8e 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index baa0e28a5..8d8f1bb8d 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 19c09a7fc..9064b1407 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index e2551f9bc..b778d45a5 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 2b7b672a4..495564051 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index bdab28afb..d55b02899 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 4e3c255d5..8c6d82a10 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index d4ff8eba8..0d8a4012d 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 186c5bae3..cd1e503ec 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 809b0e390..0ad920b27 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -154,8 +154,9 @@ enum UserSelectablePins { GPIO_KEY2_INV_NP, GPIO_KEY3_INV_NP, GPIO_KEY4_INV_NP, - GPIO_SM16716_CLK, // SM16716 CLK - GPIO_SM16716_DAT, // SM16716 DAT + GPIO_SM16716_CLK, // SM16716 CLOCK + GPIO_SM16716_DAT, // SM16716 DATA + GPIO_SM16716_SEL, // SM16716 SELECT GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -222,7 +223,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO "|" D_SENSOR_BUTTON "1i|" D_SENSOR_BUTTON "2i|" D_SENSOR_BUTTON "3i|" D_SENSOR_BUTTON "4i|" D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in|" - D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT + D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT "|" D_SENSOR_SM16716_SEL ; /********************************************************************************************/ @@ -530,8 +531,9 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_MAX31855DO, // MAX31855 Serial interface #endif #ifdef USE_SM16716 - GPIO_SM16716_CLK, // SM16716 CLK - GPIO_SM16716_DAT, // SM16716 DAT + GPIO_SM16716_CLK, // SM16716 CLOCK + GPIO_SM16716_DAT, // SM16716 DATA + GPIO_SM16716_SEL, // SM16716 SELECT #endif // USE_SM16716 }; From 12361df7053008242f325f43e8cd9c89e6fbe3f5 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Thu, 31 Jan 2019 22:03:47 +0200 Subject: [PATCH 0927/2222] PN532: Fix regression --- sonoff/xsns_40_pn532_i2c.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index 6718ffc4e..640e21c6e 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -432,6 +432,7 @@ void PN532_ScanForTag(void) } if (pn532_i2c_function == 2) { #ifdef USE_PN532_DATA_RAW + memcpy(&card_data,&pn532_i2c_newdata,sizeof(card_data)); if (mifareclassic_WriteDataBlock(1, card_data)) { set_success = true; snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful"); @@ -441,13 +442,14 @@ void PN532_ScanForTag(void) #else bool IsAlphaNumeric = true; for (uint8_t i = 0;i < pn532_i2c_newdata_len;i++) { - if ((!isalpha(pn532_i2c_newdata[i])) || (!isdigit(pn532_i2c_newdata[i]))) { + if ((!isalpha(pn532_i2c_newdata[i])) && (!isdigit(pn532_i2c_newdata[i]))) { IsAlphaNumeric = false; } } if (IsAlphaNumeric) { + memcpy(&card_data,&pn532_i2c_newdata,pn532_i2c_newdata_len); + card_data[pn532_i2c_newdata_len] = '\0'; // Enforce null termination if (mifareclassic_WriteDataBlock(1, card_data)) { - memcpy(&card_data,&pn532_i2c_newdata,sizeof(card_data)); set_success = true; snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful"); AddLog(LOG_LEVEL_INFO); From 04f1ed1659240092e1cfc987d0f5e811c5310884 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Thu, 31 Jan 2019 17:17:01 -0500 Subject: [PATCH 0928/2222] Implemented sm16716 select If SM16716_SEL is specified, it will toggle it on/off depending on whether or not there is color data --- sonoff/xdrv_04_light.ino | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 0591da5bb..9cb22d698 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -371,6 +371,7 @@ void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t dut uint8_t sm16716_pin_clk = 100; uint8_t sm16716_pin_dat = 100; +uint8_t sm16716_pin_sel = 100; void SM16716_SendBit(uint8_t v) { @@ -397,6 +398,23 @@ void SM16716_SendByte(uint8_t v) void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) { + if (sm16716_pin_sel < 99) { + if (duty_r | duty_g | duty_b) { +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "turning color on")); + AddLog(LOG_LEVEL_DEBUG); +#endif // D_LOG_SM16716 + digitalWrite(sm16716_pin_sel, HIGH); + delayMicroseconds(20); + SM16716_Init(); + } else { +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "turning color off")); + AddLog(LOG_LEVEL_DEBUG); +#endif // D_LOG_SM16716 + digitalWrite(sm16716_pin_sel, LOW); + } + } #ifdef D_LOG_SM16716 snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), @@ -409,10 +427,11 @@ void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) // send 24-bit rgb data SM16716_SendByte(duty_r); SM16716_SendByte(duty_g); - SM16716_SendByte(duty_g); + SM16716_SendByte(duty_b); // send a 'do it' pulse // (if multiple chips are chained, each one processes the 1st '1rgb' 25-bit block and // passes on the rest, right until the one starting with 0) + //SM16716_Init(); SM16716_SendBit(0); SM16716_SendByte(0); SM16716_SendByte(0); @@ -423,6 +442,7 @@ bool SM16716_ModuleSelected(void) { sm16716_pin_clk = pin[GPIO_SM16716_CLK]; sm16716_pin_dat = pin[GPIO_SM16716_DAT]; + sm16716_pin_sel = pin[GPIO_SM16716_SEL]; #ifdef D_LOG_SM16716 snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), @@ -505,6 +525,11 @@ void LightInit(void) pinMode(sm16716_pin_dat, OUTPUT); digitalWrite(sm16716_pin_dat, LOW); + if (sm16716_pin_sel < 99) { + pinMode(sm16716_pin_sel, OUTPUT); + digitalWrite(sm16716_pin_sel, LOW); + } + SM16716_Init(); } #endif // ifdef USE_SM16716 @@ -963,9 +988,6 @@ void LightAnimate(void) analogWrite(pin[GPIO_PWM1 +i-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - curcol : curcol); } } - if(cur_col[0] | cur_col[1] | cur_col[2]){ - SM16716_Init(); - } SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); } #endif // ifdef USE_SM16716 From 8be3da63e1ba7bf58eec5481887e9a5abfc1e459 Mon Sep 17 00:00:00 2001 From: Kevin Baluha Date: Thu, 31 Jan 2019 20:13:23 -0700 Subject: [PATCH 0929/2222] add functionality to use multiple ads1115's on one i2cbus --- sonoff/xsns_12_ads1115.ino | 77 +++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index f75baa3e8..f2cfda028 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -119,7 +119,8 @@ CONFIG REGISTER uint8_t ads1115_type = 0; uint8_t ads1115_address; uint8_t ads1115_addresses[] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL }; - +uint8_t ads1115_found[] = {false,false,false,false}; +int16_t ads1115_values[4]; //Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE); //Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN); void Ads1115StartComparator(uint8_t channel, uint16_t mode) @@ -161,51 +162,83 @@ void Ads1115Detect(void) { uint16_t buffer; - if (ads1115_type) { - return; - } + //if (ads1115_type) { + //return; + //} for (uint8_t i = 0; i < sizeof(ads1115_addresses); i++) { ads1115_address = ads1115_addresses[i]; if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT)) { Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); ads1115_type = 1; + ads1115_found[i] = 1; snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); AddLog(LOG_LEVEL_DEBUG); - break; + //break; } } } +void Ads1115GetValues(uint8_t address) { + uint8_t old_address = ads1115_address; + ads1115_address = address; + for (uint8_t i = 0; i < 4; i++) { + ads1115_values[i] = Ads1115GetConversion(i); + snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x (%i) = %i", address, i, ads1115_values[i] ); + AddLog(LOG_LEVEL_INFO); + } + ads1115_address = old_address; +} + +void Ads1115toJSON(char *comma_j) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s{"), mqtt_data,comma_j); + char *comma = (char*)""; + for (uint8_t i = 0; i < 4; i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, comma, i, ads1115_values[i]); + comma = (char*)","; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); +} + +void Ads1115toString(uint8_t address) { + char label[15]; + snprintf_P(label, sizeof(label), "ADS1115(%02x)", address); + + for (uint8_t i = 0; i < 4; i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, label, i, ads1115_values[i]); + } +} + void Ads1115Show(bool json) { - if (ads1115_type) { - char stemp[10]; + if (!ads1115_type) + return; - uint8_t dsxflg = 0; - for (uint8_t i = 0; i < 4; i++) { - int16_t adc_value = Ads1115GetConversion(i); + if (json) + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":["), mqtt_data); + char *comma = (char*)""; + + for (uint8_t t = 0; t < sizeof(ads1115_addresses); t++) { + snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x", ads1115_addresses[t]); + AddLog(LOG_LEVEL_INFO); + if (ads1115_found[t]) { + Ads1115GetValues(ads1115_addresses[t]); if (json) { - if (!dsxflg ) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":{"), mqtt_data); - stemp[0] = '\0'; + Ads1115toJSON(comma); + comma = (char*)","; } - dsxflg++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, stemp, i, adc_value); - strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_WEBSERVER - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value); + else { + Ads1115toString(ads1115_addresses[t]); + } #endif // USE_WEBSERVER } } + if (json) { - if (dsxflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]"), mqtt_data); } - } - } } /*********************************************************************************************\ From ef40aff62a25f86a32888abe485743b6ba1779e9 Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Fri, 1 Feb 2019 04:37:22 +0000 Subject: [PATCH 0930/2222] Added SM16716_SEL pin to SYF05 template, enabled SM16716 support --- sonoff/my_user_config.h | 2 ++ sonoff/sonoff_template.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 83bbb7b65..92f2a6d86 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -416,6 +416,8 @@ // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) // #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver (+1k7 code) +#define USE_SM16716 // Add support for SM16716 RGB LED controller + /*********************************************************************************************\ * Debug features are only supported in development branch \*********************************************************************************************/ diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 0ad920b27..115e999cf 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1822,7 +1822,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO10 // GPIO11 GPIO_PWM2, // GPIO12 Warm White - GPIO_USER, // GPIO13 N.C. (used as LED if you add it) + GPIO_SM16716_SEL, // GPIO13 GPIO_SM16716_DAT, // GPIO14 0, // GPIO15 wired to GND GPIO_USER, // GPIO16 N.C. From 25856c323a834cead4d412402ed77563adfc236f Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 1 Feb 2019 00:59:53 -0500 Subject: [PATCH 0931/2222] Track sm16716 select pin state so we don't waste cycles continuously enabling/disabling color Added some comments; disabled sm16716 debug messages by default Removed delay after setting select pin; didn't seem to help anyway --- sonoff/xdrv_04_light.ino | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 9cb22d698..4a6c21389 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -367,11 +367,12 @@ void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t dut \*********************************************************************************************/ // Enable this for debug logging -#define D_LOG_SM16716 "SM16716: " +//#define D_LOG_SM16716 "SM16716: " uint8_t sm16716_pin_clk = 100; uint8_t sm16716_pin_dat = 100; uint8_t sm16716_pin_sel = 100; +uint8_t sm16716_enabled = 0; void SM16716_SendBit(uint8_t v) { @@ -399,19 +400,23 @@ void SM16716_SendByte(uint8_t v) void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) { if (sm16716_pin_sel < 99) { - if (duty_r | duty_g | duty_b) { + uint8_t sm16716_should_enable = (duty_r | duty_g | duty_b); + if (!sm16716_enabled && sm16716_should_enable) { #ifdef D_LOG_SM16716 snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "turning color on")); AddLog(LOG_LEVEL_DEBUG); #endif // D_LOG_SM16716 + sm16716_enabled = 1; digitalWrite(sm16716_pin_sel, HIGH); - delayMicroseconds(20); + //delayMicroseconds(20); SM16716_Init(); - } else { + } + else if (sm16716_enabled && !sm16716_should_enable) { #ifdef D_LOG_SM16716 snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "turning color off")); AddLog(LOG_LEVEL_DEBUG); #endif // D_LOG_SM16716 + sm16716_enabled = 0; digitalWrite(sm16716_pin_sel, LOW); } } @@ -977,6 +982,7 @@ void LightAnimate(void) #endif // USE_ES2812 ************************************************************************ #ifdef USE_SM16716 else if (16 & light_type) { + // handle any PWM pins, skipping the first 3 values for sm16716 for (uint8_t i = 3; i < light_subtype; i++) { if (pin[GPIO_PWM1 +i-3] < 99) { if (cur_col[i] > 0xFC) { @@ -988,6 +994,7 @@ void LightAnimate(void) analogWrite(pin[GPIO_PWM1 +i-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - curcol : curcol); } } + // handle sm16716 update SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); } #endif // ifdef USE_SM16716 From de41a88becf7485e563ef3ea07a14a6cb9ba2a89 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 1 Feb 2019 14:05:55 +0100 Subject: [PATCH 0932/2222] Fix stop flash rotate functionality Fix stop flash rotate functionality --- sonoff/settings.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 13634d541..55a73fc56 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -472,7 +472,7 @@ void SettingsLoad(void) if (Settings.save_flag > save_flag) { save_flag = Settings.save_flag; settings_location = flash_location; - if (Settings.flag.stop_flash_rotate) { + if (Settings.flag.stop_flash_rotate && (0 == i)) { // Stop only if eeprom area should be used and it is valid break; } } From edb0cf8f699c6e2a9f07cb2020ee0fac042ec8d7 Mon Sep 17 00:00:00 2001 From: netpok Date: Fri, 1 Feb 2019 14:54:35 +0100 Subject: [PATCH 0933/2222] Add WAGA life CHCZ02MB device --- sonoff/sonoff_template.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 99f4d1458..08d731b5e 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -293,6 +293,7 @@ enum SupportedModules { ZX2820, MI_DESK_LAMP, SP10, + WAGA, MAXMODULE }; /********************************************************************************************/ @@ -574,6 +575,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { DIGOO, KA10, SP10, + WAGA, NEO_COOLCAM, // Socket Relay Devices OBI, OBI2, @@ -1814,6 +1816,26 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1, // GPIO13 Blue LED - Link status GPIO_REL1, // GPIO14 Relay 1 and red LED 0, 0, 0 + }, + { "WAGA CHCZ02MB", // WAGA life CHCZ02MB (HJL-01 Energy Monitoring) + // https://www.ebay.com/itm/332595697006 + GPIO_LED1, // GPIO00 Red LED + 0, // GPIO01 Serial TX + 0, // GPIO02 + GPIO_NRG_SEL_INV, // GPIO03 HJL-01 Sel output (1 = Voltage) + 0, // GPIO04 + GPIO_HJL_CF, // GPIO05 HJL-01 CF power + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Relay + GPIO_KEY1, // GPIO13 Button + GPIO_NRG_CF1, // GPIO14 HJL-01 CF1 voltage / current + GPIO_LED2, // GPIO15 Blue LED - Link status + 0, 0 } }; From 1bb22c06a6c15198a6f3ff6fa442e1eef2b8f107 Mon Sep 17 00:00:00 2001 From: netpok Date: Fri, 1 Feb 2019 14:55:33 +0100 Subject: [PATCH 0934/2222] Update SP10 descriptions --- sonoff/sonoff_template.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 08d731b5e..598d03e80 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1798,7 +1798,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_ROT_B, // GPIO13 Rotary switch B pin 0, 0, 0, 0 }, - { "SP10", // Tuya SP10 (ESP8285 - BL0937 Energy Monitoring) + { "SP10", // Tuya SP10 (BL0937 Energy Monitoring) // https://www.aliexpress.com/item/Smart-Mini-WiFi-Plug-Outlet-Switch-Work-With-ForEcho-Alexa-Google-Home-Remote-EU-Smart-Socket/32963670423.html 0, // GPIO00 GPIO_PWM1, // GPIO01 Nightlight @@ -1814,7 +1814,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { // GPIO11 (SD_CMD Flash) GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage) GPIO_LED1, // GPIO13 Blue LED - Link status - GPIO_REL1, // GPIO14 Relay 1 and red LED + GPIO_REL1, // GPIO14 Relay and red LED 0, 0, 0 }, { "WAGA CHCZ02MB", // WAGA life CHCZ02MB (HJL-01 Energy Monitoring) From b927237aad9e6a828f77f934b7dc18d7c93a3451 Mon Sep 17 00:00:00 2001 From: netpok Date: Fri, 1 Feb 2019 15:01:45 +0100 Subject: [PATCH 0935/2222] Fix LED numbering --- sonoff/sonoff_template.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 598d03e80..fa7d7d546 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1819,7 +1819,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { }, { "WAGA CHCZ02MB", // WAGA life CHCZ02MB (HJL-01 Energy Monitoring) // https://www.ebay.com/itm/332595697006 - GPIO_LED1, // GPIO00 Red LED + GPIO_LED2, // GPIO00 Red LED 0, // GPIO01 Serial TX 0, // GPIO02 GPIO_NRG_SEL_INV, // GPIO03 HJL-01 Sel output (1 = Voltage) @@ -1834,7 +1834,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL1, // GPIO12 Relay GPIO_KEY1, // GPIO13 Button GPIO_NRG_CF1, // GPIO14 HJL-01 CF1 voltage / current - GPIO_LED2, // GPIO15 Blue LED - Link status + GPIO_LED1, // GPIO15 Blue LED - Link status 0, 0 } }; From 7e56dc538dda9eb2ea08a72ce265ed79e92dd6ed Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 1 Feb 2019 18:46:37 +0200 Subject: [PATCH 0936/2222] MHZ19: Allow enable and disable of ABC --- sonoff/settings.h | 17 +++++++++++++++-- sonoff/xsns_15_mhz19.ino | 37 ++++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 83a26e311..22f6d940d 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -163,6 +163,20 @@ typedef union { }; } Mcp230xxCfg; +typedef union { + uint8_t data; + struct { + uint8_t spare0 : 1; + uint8_t spare1 : 1; + uint8_t spare2 : 1; + uint8_t spare3 : 1; + uint8_t spare4 : 1; + uint8_t spare5 : 1; + uint8_t spare6 : 1; + uint8_t mhz19b_abc_disable : 1; // Disable ABC (Automatic Baseline Correction for MHZ19(B) (0 = Enabled (default), 1 = Disabled with Sensor15 command) + }; +} SensorCfg1; + /* struct SYSCFG { unsigned long cfg_holder; // 000 Pre v6 header @@ -311,8 +325,7 @@ struct SYSCFG { uint8_t knx_CB_param[MAX_KNX_CB]; // 6EC Type of Output (set relay, toggle relay, reply sensor value) Mcp230xxCfg mcp230xx_config[16]; // 6F6 uint8_t mcp230xx_int_prio; // 716 - - uint8_t free_717[1]; // 717 + SensorCfg1 SensorBits1; // 717 On/Off settings used by Sensor Commands uint16_t mcp230xx_int_timer; // 718 uint8_t rgbwwTable[5]; // 71A diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 509f9e0bc..747a8125f 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -39,7 +39,10 @@ enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILT /*********************************************************************************************\ * Source: http://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf * - * Automatic Baseline Correction (ABC logic function) + * Automatic Baseline Correction (ABC logic function) is enabled by default but may be disabled with command + * Sensor15 0 + * and enabled again with command + * Sensor15 1 * * ABC logic function refers to that sensor itself do zero point judgment and automatic calibration procedure * intelligently after a continuous operation period. The automatic calibration cycle is every 24 hours after powered on. @@ -52,10 +55,6 @@ enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILT * Please do zero calibration timely, such as manual or commend calibration. \*********************************************************************************************/ -#define MHZ19_ABC_ENABLE 1 // Automatic Baseline Correction (0 = off, 1 = on (default)) - -/*********************************************************************************************/ - #include #ifndef CO2_LOW @@ -72,6 +71,9 @@ TasmotaSerial *MhzSerial; const char kMhzModels[] PROGMEM = "|B"; +const char ABC_ENABLED[] PROGMEM = "ABC is Enabled"; +const char ABC_DISABLED[] PROGMEM = "ABC is Enabled"; + enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; const uint8_t kMhzCommands[][4] PROGMEM = { // 2 3 6 7 @@ -88,7 +90,6 @@ const uint8_t kMhzCommands[][4] PROGMEM = { uint8_t mhz_type = 1; uint16_t mhz_last_ppm = 0; uint8_t mhz_filter = MHZ19_FILTER_OPTION; -bool mhz_abc_enable = MHZ19_ABC_ENABLE; bool mhz_abc_must_apply = false; float mhz_temperature = 0; @@ -218,7 +219,7 @@ void MhzEverySecond(void) uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; if (15000 == u) { // During (and only ever at) sensor boot, 'u' is reported as 15000 - if (!mhz_abc_enable) { + if (Settings.SensorBits1.mhz19b_abc_disable) { // After bootup of the sensor the ABC will be enabled. // Thus only actively disable after bootup. mhz_abc_must_apply = true; @@ -235,7 +236,7 @@ void MhzEverySecond(void) if (0 == s || 64 == s) { // Reading is stable. if (mhz_abc_must_apply) { mhz_abc_must_apply = false; - if (mhz_abc_enable) { + if (!Settings.SensorBits1.mhz19b_abc_disable) { MhzSendCmd(MHZ_CMND_ABCENABLE); } else { MhzSendCmd(MHZ_CMND_ABCDISABLE); @@ -252,8 +253,8 @@ void MhzEverySecond(void) /*********************************************************************************************\ * Command Sensor15 * - * 0 - (Not implemented) ABC Off - * 1 - (Not implemented) ABC On + * 0 - ABC Off + * 1 - ABC On (Default) * 2 - Manual start = ABC Off * 3 - (Not implemented) Optional filter settings * 9 - Reset @@ -273,6 +274,16 @@ bool MhzCommandSensor(void) bool serviced = true; switch (XdrvMailbox.payload) { + case 0: + Settings.SensorBits1.mhz19b_abc_disable = true; + MhzSendCmd(MHZ_CMND_ABCDISABLE); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + break; + case 1: + Settings.SensorBits1.mhz19b_abc_disable = false; + MhzSendCmd(MHZ_CMND_ABCENABLE); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + break; case 2: MhzSendCmd(MHZ_CMND_ZEROPOINT); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); @@ -298,7 +309,11 @@ bool MhzCommandSensor(void) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); break; default: - serviced = false; + if (!Settings.SensorBits1.mhz19b_abc_disable) { + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + } } return serviced; From 99b027852b145e27b93a7f7fdd3f933d95d01c22 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 1 Feb 2019 17:33:21 -0500 Subject: [PATCH 0937/2222] Fixed first color command failing; need to wait for chip to power up --- sonoff/xdrv_04_light.ino | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 4a6c21389..ba12ac3db 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -408,7 +408,9 @@ void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) #endif // D_LOG_SM16716 sm16716_enabled = 1; digitalWrite(sm16716_pin_sel, HIGH); - //delayMicroseconds(20); + // in testing I found it takes a minimum of ~380us to wake up the chip + // tested on a Merkury RGBW with an SM726EB + delayMicroseconds(400); SM16716_Init(); } else if (sm16716_enabled && !sm16716_should_enable) { From 817d0af598d887c7105e7d023f840d4f23762d87 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 1 Feb 2019 17:37:37 -0500 Subject: [PATCH 0938/2222] No need (and pointless) to call SM16716_Init until color updates, iff using sel pin --- sonoff/xdrv_04_light.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index ba12ac3db..f65dd43da 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -535,9 +535,11 @@ void LightInit(void) if (sm16716_pin_sel < 99) { pinMode(sm16716_pin_sel, OUTPUT); digitalWrite(sm16716_pin_sel, LOW); + // no need to call SM16716_Init here, it will be called after sel goes HIGH + } else { + // no sel pin means you have an 'always on' chip, so init right away + SM16716_Init(); } - - SM16716_Init(); } #endif // ifdef USE_SM16716 else { From 4dc1d2f26004554a94df60b72f4a5b0aaa394b6f Mon Sep 17 00:00:00 2001 From: netpok Date: Sat, 2 Feb 2019 01:10:35 +0100 Subject: [PATCH 0939/2222] Fix led polarity --- sonoff/sonoff_template.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index fa7d7d546..1fbf50bf1 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1819,7 +1819,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { }, { "WAGA CHCZ02MB", // WAGA life CHCZ02MB (HJL-01 Energy Monitoring) // https://www.ebay.com/itm/332595697006 - GPIO_LED2, // GPIO00 Red LED + GPIO_LED2_INV, // GPIO00 Red LED 0, // GPIO01 Serial TX 0, // GPIO02 GPIO_NRG_SEL_INV, // GPIO03 HJL-01 Sel output (1 = Voltage) @@ -1834,7 +1834,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL1, // GPIO12 Relay GPIO_KEY1, // GPIO13 Button GPIO_NRG_CF1, // GPIO14 HJL-01 CF1 voltage / current - GPIO_LED1, // GPIO15 Blue LED - Link status + GPIO_LED1_INV, // GPIO15 Blue LED - Link status 0, 0 } }; From 6d19a9c998eb6a4da0692836d420628b96d6ccfc Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 1 Feb 2019 19:28:16 -0500 Subject: [PATCH 0940/2222] Generalize the SYF05 a tiny bit so it can be easily adapted to similar bulbs --- sonoff/sonoff_template.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 80155a7c1..e57cd54cf 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1827,6 +1827,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, 0 }, { "SYF05", // Sunyesmart SYF05 (a.k.a. Fcmila) = TYWE3S + SM16726 + // Also works with Merkury 904 RGBW Bulbs with 13 set to GPIO_SM16716_SEL // https://www.flipkart.com/fc-mila-bxav-xs-ad-smart-bulb/p/itmf85zgs45fzr7n // https://docs.tuya.com/en/hardware/WiFi-module/wifi-e3s-module.html // http://www.datasheet-pdf.com/PDF/SM16716-Datasheet-Sunmoon-932771 @@ -1834,17 +1835,17 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, GPIO_USER, // GPIO02 N.C. 0, - GPIO_SM16716_CLK, // GPIO04 - GPIO_PWM1, // GPIO05 Cold White + GPIO_SM16716_CLK, // GPIO04 SM16716 Clock + GPIO_PWM1, // GPIO05 White // GPIO06 // GPIO07 // GPIO08 0, // GPIO09 0, // GPIO10 // GPIO11 - GPIO_PWM2, // GPIO12 Warm White - GPIO_SM16716_SEL, // GPIO13 - GPIO_SM16716_DAT, // GPIO14 + GPIO_USER, // GPIO12 Alt. White on some devices + GPIO_USER, // GPIO13 SM16716 Select on some devices + GPIO_SM16716_DAT, // GPIO14 SM16716 Data 0, // GPIO15 wired to GND GPIO_USER, // GPIO16 N.C. GPIO_FLAG_ADC0 // ADC0 A0 Analog input From d7b8a6453dbea52a6006d1e2c62593365dd39376 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 1 Feb 2019 19:41:12 -0500 Subject: [PATCH 0941/2222] Added preprocessor constant for LT_SM16716 for improved code readability Note that this differs from other LT_* in that it's not an enum Ensure the SM16716 codepath is only taken when the top half of light_type is LT_SM16716 --- sonoff/sonoff.h | 2 ++ sonoff/sonoff.ino | 2 +- sonoff/xdrv_04_light.ino | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 9ba91f091..b54a32f3c 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -168,6 +168,8 @@ typedef unsigned long power_t; // Power (Relay) type #define NEO_RGBW 5 // Neopixel RGBW leds #define NEO_GRBW 6 // Neopixel GRBW leds +#define LT_SM16716 16 // Lights that use SM16716 will have this bit set in light_type + #define MQTT_PUBSUBCLIENT 1 // Mqtt PubSubClient library #define MQTT_TASMOTAMQTT 2 // Mqtt TasmotaMqtt library based on esp-mqtt-arduino - soon obsolete #define MQTT_ESPMQTTARDUINO 3 // Mqtt esp-mqtt-arduino library by Ingo Randolf - obsolete but define is present for debugging purposes diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 694f7d4c9..7be59f746 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2425,7 +2425,7 @@ void GpioInit(void) #ifdef USE_SM16716 if (SM16716_ModuleSelected()) { light_type += 3; - light_type |= 16; + light_type |= LT_SM16716; } #endif // ifdef USE_SM16716 if (!light_type) { diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index f65dd43da..bc4a9b91c 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -517,7 +517,7 @@ void LightInit(void) } #endif // USE_WS2812 ************************************************************************ #ifdef USE_SM16716 - else if (16 & light_type) { + else if (LT_SM16716 == light_type - light_subtype) { // init PWM for (uint8_t i = 0; i < light_subtype; i++) { Settings.pwm_value[i] = 0; // Disable direct PWM control @@ -985,7 +985,7 @@ void LightAnimate(void) } #endif // USE_ES2812 ************************************************************************ #ifdef USE_SM16716 - else if (16 & light_type) { + else if (LT_SM16716 == light_type - light_subtype) { // handle any PWM pins, skipping the first 3 values for sm16716 for (uint8_t i = 3; i < light_subtype; i++) { if (pin[GPIO_PWM1 +i-3] < 99) { From 35060dfa45cb84c248c1930f522dc51f0f23b41e Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 1 Feb 2019 20:12:13 -0500 Subject: [PATCH 0942/2222] Measured impact of USE_SM16716 on binary filesize --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index c914e5567..d06b0c854 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -417,7 +417,7 @@ // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) // #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver (+1k7 code) -#define USE_SM16716 // Add support for SM16716 RGB LED controller +#define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) /*********************************************************************************************\ * Debug features are only supported in development branch From 0c747a74991ed0c257c97809909673c6f55109ae Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 2 Feb 2019 15:16:35 +0100 Subject: [PATCH 0943/2222] Split module and GPIO ajax list Split module and GPIO ajax list --- sonoff/xdrv_01_webserver.ino | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 1974e9128..daf45be9f 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -145,28 +145,31 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "return false;" "}" ""; - const char HTTP_SCRIPT_MODULE1[] PROGMEM = "var os;" "function sk(s,g){" // s = value, g = id and name - "var o=os.replace(\"value='\"+s+\"'\",\"selected value='\"+s+\"'\");" + "var o=os.replace(/}1/g,\""), + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), (WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "ESP8285" :(10==i)? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); page += mqtt_data; } diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 4662fec3d..62e445c91 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -695,6 +695,9 @@ bool Xdrv03(uint8_t function) case FUNC_SET_POWER: EnergySetPowerSteadyCounter(); break; + case FUNC_LOOP: + XnrgCall(FUNC_LOOP); + break; case FUNC_SERIAL: result = XnrgCall(FUNC_SERIAL); break; diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index 4c58dfa90..53034a73c 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -63,6 +63,11 @@ #define MCP_FREQUENCY_GAIN_BASE 0x00AE #define MCP_FREQUENCY_LEN 4 +#define MCP_BUFFER_SIZE 60 + +#include +TasmotaSerial *McpSerial; + typedef struct mcp_cal_registers_type { uint16_t gain_current_rms; uint16_t gain_voltage_rms; @@ -86,6 +91,9 @@ typedef struct mcp_cal_registers_type { uint16_t accumulation_interval; } mcp_cal_registers_type; +char *mcp_buffer = NULL; // Serial receive buffer +int mcp_byte_counter = 0; // Index in serial receive buffer + unsigned long mcp_kWhcounter = 0; uint32_t mcp_system_configuration = 0x03000000; uint32_t mcp_active_power; @@ -146,7 +154,7 @@ void McpSend(uint8_t *data) // AddLogBuffer(LOG_LEVEL_DEBUG_MORE, data, data[1]); for (uint8_t i = 0; i < data[1]; i++) { - Serial.write(data[i]); + McpSerial->write(data[i]); } } @@ -162,7 +170,7 @@ void McpGetAddress(void) void McpAddressReceive(void) { // 06 05 004D 58 - mcp_address = serial_in_buffer[3]; + mcp_address = mcp_buffer[3]; } /********************************************************************************************/ @@ -183,26 +191,26 @@ void McpParseCalibration(void) mcp_cal_registers_type cal_registers; // 06 37 C882 B6AD 0781 9273 06000000 00000000 00000000 0000 D3FF 0300 00000003 9204 120C1300 204E0000 9808 E0AB0000 D9940000 0200 24 - cal_registers.gain_current_rms = McpExtractInt(serial_in_buffer, 2, 2); - cal_registers.gain_voltage_rms = McpExtractInt(serial_in_buffer, 4, 2); - cal_registers.gain_active_power = McpExtractInt(serial_in_buffer, 6, 2); - cal_registers.gain_reactive_power = McpExtractInt(serial_in_buffer, 8, 2); - cal_registers.offset_current_rms = McpExtractInt(serial_in_buffer, 10, 4); - cal_registers.offset_active_power = McpExtractInt(serial_in_buffer, 14, 4); - cal_registers.offset_reactive_power = McpExtractInt(serial_in_buffer, 18, 4); - cal_registers.dc_offset_current = McpExtractInt(serial_in_buffer, 22, 2); - cal_registers.phase_compensation = McpExtractInt(serial_in_buffer, 24, 2); - cal_registers.apparent_power_divisor = McpExtractInt(serial_in_buffer, 26, 2); + cal_registers.gain_current_rms = McpExtractInt(mcp_buffer, 2, 2); + cal_registers.gain_voltage_rms = McpExtractInt(mcp_buffer, 4, 2); + cal_registers.gain_active_power = McpExtractInt(mcp_buffer, 6, 2); + cal_registers.gain_reactive_power = McpExtractInt(mcp_buffer, 8, 2); + cal_registers.offset_current_rms = McpExtractInt(mcp_buffer, 10, 4); + cal_registers.offset_active_power = McpExtractInt(mcp_buffer, 14, 4); + cal_registers.offset_reactive_power = McpExtractInt(mcp_buffer, 18, 4); + cal_registers.dc_offset_current = McpExtractInt(mcp_buffer, 22, 2); + cal_registers.phase_compensation = McpExtractInt(mcp_buffer, 24, 2); + cal_registers.apparent_power_divisor = McpExtractInt(mcp_buffer, 26, 2); - cal_registers.system_configuration = McpExtractInt(serial_in_buffer, 28, 4); - cal_registers.dio_configuration = McpExtractInt(serial_in_buffer, 32, 2); - cal_registers.range = McpExtractInt(serial_in_buffer, 34, 4); + cal_registers.system_configuration = McpExtractInt(mcp_buffer, 28, 4); + cal_registers.dio_configuration = McpExtractInt(mcp_buffer, 32, 2); + cal_registers.range = McpExtractInt(mcp_buffer, 34, 4); - cal_registers.calibration_current = McpExtractInt(serial_in_buffer, 38, 4); - cal_registers.calibration_voltage = McpExtractInt(serial_in_buffer, 42, 2); - cal_registers.calibration_active_power = McpExtractInt(serial_in_buffer, 44, 4); - cal_registers.calibration_reactive_power = McpExtractInt(serial_in_buffer, 48, 4); - cal_registers.accumulation_interval = McpExtractInt(serial_in_buffer, 52, 2); + cal_registers.calibration_current = McpExtractInt(mcp_buffer, 38, 4); + cal_registers.calibration_voltage = McpExtractInt(mcp_buffer, 42, 2); + cal_registers.calibration_active_power = McpExtractInt(mcp_buffer, 44, 4); + cal_registers.calibration_reactive_power = McpExtractInt(mcp_buffer, 48, 4); + cal_registers.accumulation_interval = McpExtractInt(mcp_buffer, 52, 2); if (mcp_calibrate & MCP_CALIBRATE_POWER) { cal_registers.calibration_active_power = Settings.energy_power_calibration; @@ -373,8 +381,8 @@ void McpGetFrequency(void) void McpParseFrequency(void) { // 06 07 C350 8000 A0 - uint16_t line_frequency_ref = serial_in_buffer[2] * 256 + serial_in_buffer[3]; - uint16_t gain_line_frequency = serial_in_buffer[4] * 256 + serial_in_buffer[5]; + uint16_t line_frequency_ref = mcp_buffer[2] * 256 + mcp_buffer[3]; + uint16_t gain_line_frequency = mcp_buffer[4] * 256 + mcp_buffer[5]; if (mcp_calibrate & MCP_CALIBRATE_FREQUENCY) { line_frequency_ref = Settings.energy_frequency_calibration; @@ -438,12 +446,12 @@ void McpParseData(void) // 06 19 CE 18 00 00 F2 08 3A 38 00 00 66 00 00 00 93 38 00 00 36 7F 9A C6 B7 // Ak Ln Current---- Volt- ActivePower ReActivePow ApparentPow Factr Frequ Ck - mcp_current_rms = McpExtractInt(serial_in_buffer, 2, 4); - mcp_voltage_rms = McpExtractInt(serial_in_buffer, 6, 2); - mcp_active_power = McpExtractInt(serial_in_buffer, 8, 4); -// mcp_reactive_power = McpExtractInt(serial_in_buffer, 12, 4); -// mcp_power_factor = McpExtractInt(serial_in_buffer, 20, 2); - mcp_line_frequency = McpExtractInt(serial_in_buffer, 22, 2); + mcp_current_rms = McpExtractInt(mcp_buffer, 2, 4); + mcp_voltage_rms = McpExtractInt(mcp_buffer, 6, 2); + mcp_active_power = McpExtractInt(mcp_buffer, 8, 4); +// mcp_reactive_power = McpExtractInt(mcp_buffer, 12, 4); +// mcp_power_factor = McpExtractInt(mcp_buffer, 20, 2); + mcp_line_frequency = McpExtractInt(mcp_buffer, 22, 2); if (energy_power_on) { // Powered on energy_frequency = (float)mcp_line_frequency / 1000; @@ -464,49 +472,52 @@ void McpParseData(void) /********************************************************************************************/ -bool McpSerialInput(void) +void McpSerialInput(void) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - unsigned long start = millis(); - while (millis() - start < 20) { - yield(); - if (Serial.available()) { - serial_in_buffer[serial_in_byte_counter++] = Serial.read(); - start = millis(); - } - } - - AddLogSerial(LOG_LEVEL_DEBUG_MORE); - - if (1 == serial_in_byte_counter) { - if (MCP_ERROR_CRC == serial_in_buffer[0]) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Send " D_CHECKSUM_FAILURE)); - mcp_timeout = 0; - } - else if (MCP_ERROR_NAK == serial_in_buffer[0]) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: NAck")); - mcp_timeout = 0; - } - } - else if (MCP_ACK_FRAME == serial_in_buffer[0]) { - if (serial_in_byte_counter == serial_in_buffer[1]) { - - if (McpChecksum((uint8_t *)serial_in_buffer) != serial_in_buffer[serial_in_byte_counter -1]) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); - } else { - if (5 == serial_in_buffer[1]) { McpAddressReceive(); } - if (25 == serial_in_buffer[1]) { McpParseData(); } - if (MCP_CALIBRATION_LEN + 3 == serial_in_buffer[1]) { McpParseCalibration(); } - if (MCP_FREQUENCY_LEN + 3 == serial_in_buffer[1]) { McpParseFrequency(); } + if (McpSerial->available()) { + unsigned long start = millis(); + while (millis() - start < 20) { + yield(); + if (McpSerial->available()) { + mcp_buffer[mcp_byte_counter++] = McpSerial->read(); + start = millis(); } - } - mcp_timeout = 0; + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)mcp_buffer, mcp_byte_counter); + + if (1 == mcp_byte_counter) { + if (MCP_ERROR_CRC == mcp_buffer[0]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Send " D_CHECKSUM_FAILURE)); + mcp_timeout = 0; + } + else if (MCP_ERROR_NAK == mcp_buffer[0]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: NAck")); + mcp_timeout = 0; + } + } + else if (MCP_ACK_FRAME == mcp_buffer[0]) { + if (mcp_byte_counter == mcp_buffer[1]) { + + if (McpChecksum((uint8_t *)mcp_buffer) != mcp_buffer[mcp_byte_counter -1]) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); + } else { + if (5 == mcp_buffer[1]) { McpAddressReceive(); } + if (25 == mcp_buffer[1]) { McpParseData(); } + if (MCP_CALIBRATION_LEN + 3 == mcp_buffer[1]) { McpParseCalibration(); } + if (MCP_FREQUENCY_LEN + 3 == mcp_buffer[1]) { McpParseFrequency(); } + } + + } + mcp_timeout = 0; + } + else if (MCP_SINGLE_WIRE == mcp_buffer[0]) { + mcp_timeout = 0; + } + + mcp_byte_counter = 0; + McpSerial->flush(); } - else if (MCP_SINGLE_WIRE == serial_in_buffer[0]) { - mcp_timeout = 0; - } - return 1; } /********************************************************************************************/ @@ -543,25 +554,33 @@ void McpEverySecond(void) void McpSnsInit(void) { - SetSeriallog(LOG_LEVEL_NONE); // Free serial interface from logging interference - if (pin[GPIO_MCP39_RST] < 99) { - digitalWrite(pin[GPIO_MCP39_RST], 1); // MCP enable + // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions + McpSerial = new TasmotaSerial(pin[GPIO_MCP39F5_RX], pin[GPIO_MCP39F5_TX], 1); + if (McpSerial->begin(4800)) { + if (McpSerial->hardwareSerial()) { ClaimSerial(); } + if (pin[GPIO_MCP39F5_RST] < 99) { + digitalWrite(pin[GPIO_MCP39F5_RST], 1); // MCP enable + } + } else { + energy_flg = ENERGY_NONE; } } void McpDrvInit(void) { if (!energy_flg) { - if ((pin[GPIO_MCP39_RX] < 99) && (pin[GPIO_MCP39_TX] < 99)) { - if (pin[GPIO_MCP39_RST] < 99) { - pinMode(pin[GPIO_MCP39_RST], OUTPUT); - digitalWrite(pin[GPIO_MCP39_RST], 0); // MCP disable - Reset Delta Sigma ADC's + if ((pin[GPIO_MCP39F5_RX] < 99) && (pin[GPIO_MCP39F5_TX] < 99)) { + mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); + if (mcp_buffer != NULL) { + if (pin[GPIO_MCP39F5_RST] < 99) { + pinMode(pin[GPIO_MCP39F5_RST], OUTPUT); + digitalWrite(pin[GPIO_MCP39F5_RST], 0); // MCP disable - Reset Delta Sigma ADC's + } + mcp_calibrate = 0; + mcp_timeout = 2; // Initial wait + mcp_init = 2; // Initial setup steps + energy_flg = XNRG_04; } - baudrate = 4800; - mcp_calibrate = 0; - mcp_timeout = 2; // Initial wait - mcp_init = 2; // Initial setup steps - energy_flg = XNRG_04; } } } @@ -632,15 +651,15 @@ int Xnrg04(uint8_t function) case FUNC_INIT: McpSnsInit(); break; + case FUNC_LOOP: + McpSerialInput(); + break; case FUNC_EVERY_SECOND: McpEverySecond(); break; case FUNC_COMMAND: result = McpCommand(); break; - case FUNC_SERIAL: - result = McpSerialInput(); - break; } } return result; From 48faabc1cf299bbfb0797f60814ba4e52a19fca0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 4 Feb 2019 18:17:50 +0100 Subject: [PATCH 0952/2222] Revert "Add user configuration of MCP39F501" This reverts commit c340e2b8bd3f6189b7ec0b5c5038effc15a7dcd5. --- sonoff/_changelog.ino | 3 +- sonoff/sonoff_template.h | 62 ++++++------ sonoff/xdrv_01_webserver.ino | 2 +- sonoff/xdrv_03_energy.ino | 3 - sonoff/xnrg_04_mcp39f501.ino | 185 ++++++++++++++++------------------- 5 files changed, 113 insertions(+), 142 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 339ae2bfe..42de29186 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,8 +2,7 @@ * Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name * Add Resolution property to Status 3 report providing previous SetOption second value property * Fix IR local echo - * Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring as used in Sonoff S31, Pow Ra and many Tuya based devices - * Add user configuration of MCP39F501 Energy Monitoring as used in Shelly2 + * Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring * * 6.4.1.13 20190130 * Add command SetOption36 to control boot loop default restoration (#4645, #5063) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index f86a6725d..668dd02c5 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -159,9 +159,6 @@ enum UserSelectablePins { GPIO_NRG_CF1, // HLW8012/HLJ-01 CF1 voltage / current GPIO_HLW_CF, // HLW8012 CF power GPIO_HJL_CF, // HJL-01/BL0937 CF power - GPIO_MCP39F5_TX, // MCP39F501 Serial interface (Shelly2) - GPIO_MCP39F5_RX, // MCP39F501 Serial interface (Shelly2) - GPIO_MCP39F5_RST, // MCP39F501 Reset (Shelly2) GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -178,6 +175,9 @@ enum ProgramSelectablePins { GPIO_ROT_B, // Rotary switch B Pin GPIO_CSE7766_TX, // CSE7766 Serial interface (S31 and Pow R2) GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2) + GPIO_MCP39_TX, // MCP39F501 Serial interface (Shelly2) + GPIO_MCP39_RX, // MCP39F501 Serial interface (Shelly2) + GPIO_MCP39_RST, // MCP39F501 Reset (Shelly2) GPIO_USER, // User configurable GPIO_MAX }; @@ -225,8 +225,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO "|" D_SENSOR_BUTTON "1i|" D_SENSOR_BUTTON "2i|" D_SENSOR_BUTTON "3i|" D_SENSOR_BUTTON "4i|" D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in|" - D_SENSOR_NRG_SEL "|" D_SENSOR_NRG_SEL "i|" D_SENSOR_NRG_CF1 "|" D_SENSOR_HLW_CF "|" D_SENSOR_HJL_CF "|" - D_SENSOR_MCP39F5_TX "|" D_SENSOR_MCP39F5_RX "|" D_SENSOR_MCP39F5_RST + D_SENSOR_NRG_SEL "|" D_SENSOR_NRG_SEL "i|" D_SENSOR_NRG_CF1 "|" D_SENSOR_HLW_CF "|" D_SENSOR_HJL_CF ; /********************************************************************************************/ @@ -472,17 +471,21 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_HX711_SCK, // HX711 Load Cell clock GPIO_HX711_DAT, // HX711 Load Cell data #endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_HLW8012) - GPIO_NRG_SEL, // HLW8012/HLJ-01 Sel output (1 = Voltage) - GPIO_NRG_SEL_INV, // HLW8012/HLJ-01 Sel output (0 = Voltage) - GPIO_NRG_CF1, // HLW8012/HLJ-01 CF1 voltage / current - GPIO_HLW_CF, // HLW8012 CF power - GPIO_HJL_CF, // HJL-01/BL0937 CF power +#ifdef USE_SERIAL_BRIDGE + GPIO_SBR_TX, // Serial Bridge Serial interface + GPIO_SBR_RX, // Serial Bridge Serial interface #endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_MCP39F501) - GPIO_MCP39F5_TX, // MCP39F501 Serial interface (Shelly2) - GPIO_MCP39F5_RX, // MCP39F501 Serial interface (Shelly2) - GPIO_MCP39F5_RST, // MCP39F501 Reset (Shelly2) +#ifdef USE_MHZ19 + GPIO_MHZ_TXD, // MH-Z19 Serial interface + GPIO_MHZ_RXD, // MH-Z19 Serial interface +#endif +#ifdef USE_SENSEAIR + GPIO_SAIR_TX, // SenseAir Serial interface + GPIO_SAIR_RX, // SenseAir Serial interface +#endif +#ifdef USE_NOVA_SDS + GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface + GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface #endif #if defined(USE_PZEM004T) || defined(USE_PZEM_AC) || defined(USE_PZEM_DC) GPIO_PZEM0XX_TX, // PZEM0XX Serial interface @@ -504,22 +507,6 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_SDM630_TX, // SDM630 Serial interface GPIO_SDM630_RX, // SDM630 Serial interface #endif -#ifdef USE_SERIAL_BRIDGE - GPIO_SBR_TX, // Serial Bridge Serial interface - GPIO_SBR_RX, // Serial Bridge Serial interface -#endif -#ifdef USE_MHZ19 - GPIO_MHZ_TXD, // MH-Z19 Serial interface - GPIO_MHZ_RXD, // MH-Z19 Serial interface -#endif -#ifdef USE_SENSEAIR - GPIO_SAIR_TX, // SenseAir Serial interface - GPIO_SAIR_RX, // SenseAir Serial interface -#endif -#ifdef USE_NOVA_SDS - GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface - GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface -#endif #ifdef USE_PMS5003 GPIO_PMS5003, // Plantower PMS5003 Serial interface #endif @@ -546,6 +533,13 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface #endif +#if defined(USE_ENERGY_SENSOR) && defined(USE_HLW8012) + GPIO_NRG_SEL, // HLW8012/HLJ-01 Sel output (1 = Voltage) + GPIO_NRG_SEL_INV, // HLW8012/HLJ-01 Sel output (0 = Voltage) + GPIO_NRG_CF1, // HLW8012/HLJ-01 CF1 voltage / current + GPIO_HLW_CF, // HLW8012 CF power + GPIO_HJL_CF, // HJL-01/BL0937 CF power +#endif }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { @@ -1448,9 +1442,9 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { }, { "Shelly 2", // Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ 0, - GPIO_MCP39F5_TX, // GPIO01 MCP39F501 Serial input + GPIO_MCP39_TX, // GPIO01 MCP39F501 Serial input 0, - GPIO_MCP39F5_RX, // GPIO03 MCP39F501 Serial output + GPIO_MCP39_RX, // GPIO03 MCP39F501 Serial output GPIO_REL1, // GPIO04 GPIO_REL2, // GPIO05 // GPIO06 (SD_CLK Flash) @@ -1462,7 +1456,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_SWT1, // GPIO12 0, GPIO_SWT2, // GPIO14 - GPIO_MCP39F5_RST, // GPIO15 MCP39F501 Reset + GPIO_MCP39_RST, // GPIO15 MCP39F501 Reset 0, GPIO_FLAG_PULLUP // Allow input pull-up control }, diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 51498abb4..daf45be9f 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -864,7 +864,7 @@ void HandleModuleConfiguration(void) for (uint8_t i = 0; i < sizeof(cmodule); i++) { if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), (WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "ESP8285" :(10==i)? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); page += mqtt_data; } diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 62e445c91..4662fec3d 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -695,9 +695,6 @@ bool Xdrv03(uint8_t function) case FUNC_SET_POWER: EnergySetPowerSteadyCounter(); break; - case FUNC_LOOP: - XnrgCall(FUNC_LOOP); - break; case FUNC_SERIAL: result = XnrgCall(FUNC_SERIAL); break; diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index 53034a73c..4c58dfa90 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -63,11 +63,6 @@ #define MCP_FREQUENCY_GAIN_BASE 0x00AE #define MCP_FREQUENCY_LEN 4 -#define MCP_BUFFER_SIZE 60 - -#include -TasmotaSerial *McpSerial; - typedef struct mcp_cal_registers_type { uint16_t gain_current_rms; uint16_t gain_voltage_rms; @@ -91,9 +86,6 @@ typedef struct mcp_cal_registers_type { uint16_t accumulation_interval; } mcp_cal_registers_type; -char *mcp_buffer = NULL; // Serial receive buffer -int mcp_byte_counter = 0; // Index in serial receive buffer - unsigned long mcp_kWhcounter = 0; uint32_t mcp_system_configuration = 0x03000000; uint32_t mcp_active_power; @@ -154,7 +146,7 @@ void McpSend(uint8_t *data) // AddLogBuffer(LOG_LEVEL_DEBUG_MORE, data, data[1]); for (uint8_t i = 0; i < data[1]; i++) { - McpSerial->write(data[i]); + Serial.write(data[i]); } } @@ -170,7 +162,7 @@ void McpGetAddress(void) void McpAddressReceive(void) { // 06 05 004D 58 - mcp_address = mcp_buffer[3]; + mcp_address = serial_in_buffer[3]; } /********************************************************************************************/ @@ -191,26 +183,26 @@ void McpParseCalibration(void) mcp_cal_registers_type cal_registers; // 06 37 C882 B6AD 0781 9273 06000000 00000000 00000000 0000 D3FF 0300 00000003 9204 120C1300 204E0000 9808 E0AB0000 D9940000 0200 24 - cal_registers.gain_current_rms = McpExtractInt(mcp_buffer, 2, 2); - cal_registers.gain_voltage_rms = McpExtractInt(mcp_buffer, 4, 2); - cal_registers.gain_active_power = McpExtractInt(mcp_buffer, 6, 2); - cal_registers.gain_reactive_power = McpExtractInt(mcp_buffer, 8, 2); - cal_registers.offset_current_rms = McpExtractInt(mcp_buffer, 10, 4); - cal_registers.offset_active_power = McpExtractInt(mcp_buffer, 14, 4); - cal_registers.offset_reactive_power = McpExtractInt(mcp_buffer, 18, 4); - cal_registers.dc_offset_current = McpExtractInt(mcp_buffer, 22, 2); - cal_registers.phase_compensation = McpExtractInt(mcp_buffer, 24, 2); - cal_registers.apparent_power_divisor = McpExtractInt(mcp_buffer, 26, 2); + cal_registers.gain_current_rms = McpExtractInt(serial_in_buffer, 2, 2); + cal_registers.gain_voltage_rms = McpExtractInt(serial_in_buffer, 4, 2); + cal_registers.gain_active_power = McpExtractInt(serial_in_buffer, 6, 2); + cal_registers.gain_reactive_power = McpExtractInt(serial_in_buffer, 8, 2); + cal_registers.offset_current_rms = McpExtractInt(serial_in_buffer, 10, 4); + cal_registers.offset_active_power = McpExtractInt(serial_in_buffer, 14, 4); + cal_registers.offset_reactive_power = McpExtractInt(serial_in_buffer, 18, 4); + cal_registers.dc_offset_current = McpExtractInt(serial_in_buffer, 22, 2); + cal_registers.phase_compensation = McpExtractInt(serial_in_buffer, 24, 2); + cal_registers.apparent_power_divisor = McpExtractInt(serial_in_buffer, 26, 2); - cal_registers.system_configuration = McpExtractInt(mcp_buffer, 28, 4); - cal_registers.dio_configuration = McpExtractInt(mcp_buffer, 32, 2); - cal_registers.range = McpExtractInt(mcp_buffer, 34, 4); + cal_registers.system_configuration = McpExtractInt(serial_in_buffer, 28, 4); + cal_registers.dio_configuration = McpExtractInt(serial_in_buffer, 32, 2); + cal_registers.range = McpExtractInt(serial_in_buffer, 34, 4); - cal_registers.calibration_current = McpExtractInt(mcp_buffer, 38, 4); - cal_registers.calibration_voltage = McpExtractInt(mcp_buffer, 42, 2); - cal_registers.calibration_active_power = McpExtractInt(mcp_buffer, 44, 4); - cal_registers.calibration_reactive_power = McpExtractInt(mcp_buffer, 48, 4); - cal_registers.accumulation_interval = McpExtractInt(mcp_buffer, 52, 2); + cal_registers.calibration_current = McpExtractInt(serial_in_buffer, 38, 4); + cal_registers.calibration_voltage = McpExtractInt(serial_in_buffer, 42, 2); + cal_registers.calibration_active_power = McpExtractInt(serial_in_buffer, 44, 4); + cal_registers.calibration_reactive_power = McpExtractInt(serial_in_buffer, 48, 4); + cal_registers.accumulation_interval = McpExtractInt(serial_in_buffer, 52, 2); if (mcp_calibrate & MCP_CALIBRATE_POWER) { cal_registers.calibration_active_power = Settings.energy_power_calibration; @@ -381,8 +373,8 @@ void McpGetFrequency(void) void McpParseFrequency(void) { // 06 07 C350 8000 A0 - uint16_t line_frequency_ref = mcp_buffer[2] * 256 + mcp_buffer[3]; - uint16_t gain_line_frequency = mcp_buffer[4] * 256 + mcp_buffer[5]; + uint16_t line_frequency_ref = serial_in_buffer[2] * 256 + serial_in_buffer[3]; + uint16_t gain_line_frequency = serial_in_buffer[4] * 256 + serial_in_buffer[5]; if (mcp_calibrate & MCP_CALIBRATE_FREQUENCY) { line_frequency_ref = Settings.energy_frequency_calibration; @@ -446,12 +438,12 @@ void McpParseData(void) // 06 19 CE 18 00 00 F2 08 3A 38 00 00 66 00 00 00 93 38 00 00 36 7F 9A C6 B7 // Ak Ln Current---- Volt- ActivePower ReActivePow ApparentPow Factr Frequ Ck - mcp_current_rms = McpExtractInt(mcp_buffer, 2, 4); - mcp_voltage_rms = McpExtractInt(mcp_buffer, 6, 2); - mcp_active_power = McpExtractInt(mcp_buffer, 8, 4); -// mcp_reactive_power = McpExtractInt(mcp_buffer, 12, 4); -// mcp_power_factor = McpExtractInt(mcp_buffer, 20, 2); - mcp_line_frequency = McpExtractInt(mcp_buffer, 22, 2); + mcp_current_rms = McpExtractInt(serial_in_buffer, 2, 4); + mcp_voltage_rms = McpExtractInt(serial_in_buffer, 6, 2); + mcp_active_power = McpExtractInt(serial_in_buffer, 8, 4); +// mcp_reactive_power = McpExtractInt(serial_in_buffer, 12, 4); +// mcp_power_factor = McpExtractInt(serial_in_buffer, 20, 2); + mcp_line_frequency = McpExtractInt(serial_in_buffer, 22, 2); if (energy_power_on) { // Powered on energy_frequency = (float)mcp_line_frequency / 1000; @@ -472,52 +464,49 @@ void McpParseData(void) /********************************************************************************************/ -void McpSerialInput(void) +bool McpSerialInput(void) { - if (McpSerial->available()) { - unsigned long start = millis(); - while (millis() - start < 20) { - yield(); - if (McpSerial->available()) { - mcp_buffer[mcp_byte_counter++] = McpSerial->read(); - start = millis(); - } + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + unsigned long start = millis(); + while (millis() - start < 20) { + yield(); + if (Serial.available()) { + serial_in_buffer[serial_in_byte_counter++] = Serial.read(); + start = millis(); } - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)mcp_buffer, mcp_byte_counter); - - if (1 == mcp_byte_counter) { - if (MCP_ERROR_CRC == mcp_buffer[0]) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Send " D_CHECKSUM_FAILURE)); - mcp_timeout = 0; - } - else if (MCP_ERROR_NAK == mcp_buffer[0]) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: NAck")); - mcp_timeout = 0; - } - } - else if (MCP_ACK_FRAME == mcp_buffer[0]) { - if (mcp_byte_counter == mcp_buffer[1]) { - - if (McpChecksum((uint8_t *)mcp_buffer) != mcp_buffer[mcp_byte_counter -1]) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); - } else { - if (5 == mcp_buffer[1]) { McpAddressReceive(); } - if (25 == mcp_buffer[1]) { McpParseData(); } - if (MCP_CALIBRATION_LEN + 3 == mcp_buffer[1]) { McpParseCalibration(); } - if (MCP_FREQUENCY_LEN + 3 == mcp_buffer[1]) { McpParseFrequency(); } - } - - } - mcp_timeout = 0; - } - else if (MCP_SINGLE_WIRE == mcp_buffer[0]) { - mcp_timeout = 0; - } - - mcp_byte_counter = 0; - McpSerial->flush(); } + + AddLogSerial(LOG_LEVEL_DEBUG_MORE); + + if (1 == serial_in_byte_counter) { + if (MCP_ERROR_CRC == serial_in_buffer[0]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Send " D_CHECKSUM_FAILURE)); + mcp_timeout = 0; + } + else if (MCP_ERROR_NAK == serial_in_buffer[0]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: NAck")); + mcp_timeout = 0; + } + } + else if (MCP_ACK_FRAME == serial_in_buffer[0]) { + if (serial_in_byte_counter == serial_in_buffer[1]) { + + if (McpChecksum((uint8_t *)serial_in_buffer) != serial_in_buffer[serial_in_byte_counter -1]) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); + } else { + if (5 == serial_in_buffer[1]) { McpAddressReceive(); } + if (25 == serial_in_buffer[1]) { McpParseData(); } + if (MCP_CALIBRATION_LEN + 3 == serial_in_buffer[1]) { McpParseCalibration(); } + if (MCP_FREQUENCY_LEN + 3 == serial_in_buffer[1]) { McpParseFrequency(); } + } + + } + mcp_timeout = 0; + } + else if (MCP_SINGLE_WIRE == serial_in_buffer[0]) { + mcp_timeout = 0; + } + return 1; } /********************************************************************************************/ @@ -554,33 +543,25 @@ void McpEverySecond(void) void McpSnsInit(void) { - // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions - McpSerial = new TasmotaSerial(pin[GPIO_MCP39F5_RX], pin[GPIO_MCP39F5_TX], 1); - if (McpSerial->begin(4800)) { - if (McpSerial->hardwareSerial()) { ClaimSerial(); } - if (pin[GPIO_MCP39F5_RST] < 99) { - digitalWrite(pin[GPIO_MCP39F5_RST], 1); // MCP enable - } - } else { - energy_flg = ENERGY_NONE; + SetSeriallog(LOG_LEVEL_NONE); // Free serial interface from logging interference + if (pin[GPIO_MCP39_RST] < 99) { + digitalWrite(pin[GPIO_MCP39_RST], 1); // MCP enable } } void McpDrvInit(void) { if (!energy_flg) { - if ((pin[GPIO_MCP39F5_RX] < 99) && (pin[GPIO_MCP39F5_TX] < 99)) { - mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); - if (mcp_buffer != NULL) { - if (pin[GPIO_MCP39F5_RST] < 99) { - pinMode(pin[GPIO_MCP39F5_RST], OUTPUT); - digitalWrite(pin[GPIO_MCP39F5_RST], 0); // MCP disable - Reset Delta Sigma ADC's - } - mcp_calibrate = 0; - mcp_timeout = 2; // Initial wait - mcp_init = 2; // Initial setup steps - energy_flg = XNRG_04; + if ((pin[GPIO_MCP39_RX] < 99) && (pin[GPIO_MCP39_TX] < 99)) { + if (pin[GPIO_MCP39_RST] < 99) { + pinMode(pin[GPIO_MCP39_RST], OUTPUT); + digitalWrite(pin[GPIO_MCP39_RST], 0); // MCP disable - Reset Delta Sigma ADC's } + baudrate = 4800; + mcp_calibrate = 0; + mcp_timeout = 2; // Initial wait + mcp_init = 2; // Initial setup steps + energy_flg = XNRG_04; } } } @@ -651,15 +632,15 @@ int Xnrg04(uint8_t function) case FUNC_INIT: McpSnsInit(); break; - case FUNC_LOOP: - McpSerialInput(); - break; case FUNC_EVERY_SECOND: McpEverySecond(); break; case FUNC_COMMAND: result = McpCommand(); break; + case FUNC_SERIAL: + result = McpSerialInput(); + break; } } return result; From b839d7e80e962adcc21ac0103b58024e80f17030 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 4 Feb 2019 18:18:47 +0100 Subject: [PATCH 0953/2222] Add user configuration of MCP39F501 Add user configuration of MCP39F501 Energy Monitoring as used in Shelly2 --- sonoff/_changelog.ino | 3 +- sonoff/language/bg-BG.h | 5 + sonoff/language/cs-CZ.h | 5 + sonoff/language/de-DE.h | 5 + sonoff/language/el-GR.h | 5 + sonoff/language/en-GB.h | 5 + sonoff/language/es-AR.h | 5 + sonoff/language/fr-FR.h | 5 + sonoff/language/he-HE.h | 5 + sonoff/language/hu-HU.h | 5 + sonoff/language/it-IT.h | 5 + sonoff/language/nl-NL.h | 5 + sonoff/language/pl-PL.h | 5 + sonoff/language/pt-BR.h | 5 + sonoff/language/pt-PT.h | 5 + sonoff/language/ru-RU.h | 5 + sonoff/language/sk-SK.h | 5 + sonoff/language/sv-SE.h | 5 + sonoff/language/tr-TR.h | 5 + sonoff/language/uk-UK.h | 5 + sonoff/language/zh-CN.h | 5 + sonoff/language/zh-TW.h | 5 + sonoff/sonoff_template.h | 62 ++++++------ sonoff/xdrv_01_webserver.ino | 2 +- sonoff/xdrv_03_energy.ino | 3 + sonoff/xnrg_04_mcp39f501.ino | 183 +++++++++++++++++++---------------- 26 files changed, 246 insertions(+), 112 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 42de29186..339ae2bfe 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,7 +2,8 @@ * Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name * Add Resolution property to Status 3 report providing previous SetOption second value property * Fix IR local echo - * Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring + * Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring as used in Sonoff S31, Pow Ra and many Tuya based devices + * Add user configuration of MCP39F501 Energy Monitoring as used in Shelly2 * * 6.4.1.13 20190130 * Add command SetOption36 to control boot loop default restoration (#4645, #5063) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 94ff982e2..a490f8e6e 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index f03eb4122..b16ccf37f 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 5154a531d..8ad86d173 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index caaba43cf..f5f281ca4 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 381f2552b..7c03e76f4 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 2c7707456..73ec924c8 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 4a24c1955..09b7ef831 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 88fb9661b..64e6aeae3 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 3fc9fccdd..6a6a21020 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 46f8b7392..145b6064c 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 69cb48614..cef56fb2e 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 55f122747..dba0726e4 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index c9b0aefe8..f8d037e83 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 5e8849da6..aeed10329 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index bc636f3c0..aaa457ec7 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 8f489907f..e1ecafd63 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 76c459665..5a7934d71 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 95dd7e77c..344e65b58 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 1767015d5..be8f0530a 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index a9f170648..fbdc82207 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 23a5c88de..008c33a10 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -548,6 +548,11 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 668dd02c5..f86a6725d 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -159,6 +159,9 @@ enum UserSelectablePins { GPIO_NRG_CF1, // HLW8012/HLJ-01 CF1 voltage / current GPIO_HLW_CF, // HLW8012 CF power GPIO_HJL_CF, // HJL-01/BL0937 CF power + GPIO_MCP39F5_TX, // MCP39F501 Serial interface (Shelly2) + GPIO_MCP39F5_RX, // MCP39F501 Serial interface (Shelly2) + GPIO_MCP39F5_RST, // MCP39F501 Reset (Shelly2) GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -175,9 +178,6 @@ enum ProgramSelectablePins { GPIO_ROT_B, // Rotary switch B Pin GPIO_CSE7766_TX, // CSE7766 Serial interface (S31 and Pow R2) GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2) - GPIO_MCP39_TX, // MCP39F501 Serial interface (Shelly2) - GPIO_MCP39_RX, // MCP39F501 Serial interface (Shelly2) - GPIO_MCP39_RST, // MCP39F501 Reset (Shelly2) GPIO_USER, // User configurable GPIO_MAX }; @@ -225,7 +225,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO "|" D_SENSOR_BUTTON "1i|" D_SENSOR_BUTTON "2i|" D_SENSOR_BUTTON "3i|" D_SENSOR_BUTTON "4i|" D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in|" - D_SENSOR_NRG_SEL "|" D_SENSOR_NRG_SEL "i|" D_SENSOR_NRG_CF1 "|" D_SENSOR_HLW_CF "|" D_SENSOR_HJL_CF + D_SENSOR_NRG_SEL "|" D_SENSOR_NRG_SEL "i|" D_SENSOR_NRG_CF1 "|" D_SENSOR_HLW_CF "|" D_SENSOR_HJL_CF "|" + D_SENSOR_MCP39F5_TX "|" D_SENSOR_MCP39F5_RX "|" D_SENSOR_MCP39F5_RST ; /********************************************************************************************/ @@ -471,21 +472,17 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_HX711_SCK, // HX711 Load Cell clock GPIO_HX711_DAT, // HX711 Load Cell data #endif -#ifdef USE_SERIAL_BRIDGE - GPIO_SBR_TX, // Serial Bridge Serial interface - GPIO_SBR_RX, // Serial Bridge Serial interface +#if defined(USE_ENERGY_SENSOR) && defined(USE_HLW8012) + GPIO_NRG_SEL, // HLW8012/HLJ-01 Sel output (1 = Voltage) + GPIO_NRG_SEL_INV, // HLW8012/HLJ-01 Sel output (0 = Voltage) + GPIO_NRG_CF1, // HLW8012/HLJ-01 CF1 voltage / current + GPIO_HLW_CF, // HLW8012 CF power + GPIO_HJL_CF, // HJL-01/BL0937 CF power #endif -#ifdef USE_MHZ19 - GPIO_MHZ_TXD, // MH-Z19 Serial interface - GPIO_MHZ_RXD, // MH-Z19 Serial interface -#endif -#ifdef USE_SENSEAIR - GPIO_SAIR_TX, // SenseAir Serial interface - GPIO_SAIR_RX, // SenseAir Serial interface -#endif -#ifdef USE_NOVA_SDS - GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface - GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface +#if defined(USE_ENERGY_SENSOR) && defined(USE_MCP39F501) + GPIO_MCP39F5_TX, // MCP39F501 Serial interface (Shelly2) + GPIO_MCP39F5_RX, // MCP39F501 Serial interface (Shelly2) + GPIO_MCP39F5_RST, // MCP39F501 Reset (Shelly2) #endif #if defined(USE_PZEM004T) || defined(USE_PZEM_AC) || defined(USE_PZEM_DC) GPIO_PZEM0XX_TX, // PZEM0XX Serial interface @@ -507,6 +504,22 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_SDM630_TX, // SDM630 Serial interface GPIO_SDM630_RX, // SDM630 Serial interface #endif +#ifdef USE_SERIAL_BRIDGE + GPIO_SBR_TX, // Serial Bridge Serial interface + GPIO_SBR_RX, // Serial Bridge Serial interface +#endif +#ifdef USE_MHZ19 + GPIO_MHZ_TXD, // MH-Z19 Serial interface + GPIO_MHZ_RXD, // MH-Z19 Serial interface +#endif +#ifdef USE_SENSEAIR + GPIO_SAIR_TX, // SenseAir Serial interface + GPIO_SAIR_RX, // SenseAir Serial interface +#endif +#ifdef USE_NOVA_SDS + GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface + GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface +#endif #ifdef USE_PMS5003 GPIO_PMS5003, // Plantower PMS5003 Serial interface #endif @@ -533,13 +546,6 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface #endif -#if defined(USE_ENERGY_SENSOR) && defined(USE_HLW8012) - GPIO_NRG_SEL, // HLW8012/HLJ-01 Sel output (1 = Voltage) - GPIO_NRG_SEL_INV, // HLW8012/HLJ-01 Sel output (0 = Voltage) - GPIO_NRG_CF1, // HLW8012/HLJ-01 CF1 voltage / current - GPIO_HLW_CF, // HLW8012 CF power - GPIO_HJL_CF, // HJL-01/BL0937 CF power -#endif }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { @@ -1442,9 +1448,9 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { }, { "Shelly 2", // Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ 0, - GPIO_MCP39_TX, // GPIO01 MCP39F501 Serial input + GPIO_MCP39F5_TX, // GPIO01 MCP39F501 Serial input 0, - GPIO_MCP39_RX, // GPIO03 MCP39F501 Serial output + GPIO_MCP39F5_RX, // GPIO03 MCP39F501 Serial output GPIO_REL1, // GPIO04 GPIO_REL2, // GPIO05 // GPIO06 (SD_CLK Flash) @@ -1456,7 +1462,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_SWT1, // GPIO12 0, GPIO_SWT2, // GPIO14 - GPIO_MCP39_RST, // GPIO15 MCP39F501 Reset + GPIO_MCP39F5_RST, // GPIO15 MCP39F501 Reset 0, GPIO_FLAG_PULLUP // Allow input pull-up control }, diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index daf45be9f..51498abb4 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -864,7 +864,7 @@ void HandleModuleConfiguration(void) for (uint8_t i = 0; i < sizeof(cmodule); i++) { if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), (WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "ESP8285" :(10==i)? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); page += mqtt_data; } diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 4662fec3d..62e445c91 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -695,6 +695,9 @@ bool Xdrv03(uint8_t function) case FUNC_SET_POWER: EnergySetPowerSteadyCounter(); break; + case FUNC_LOOP: + XnrgCall(FUNC_LOOP); + break; case FUNC_SERIAL: result = XnrgCall(FUNC_SERIAL); break; diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index 4c58dfa90..53034a73c 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -63,6 +63,11 @@ #define MCP_FREQUENCY_GAIN_BASE 0x00AE #define MCP_FREQUENCY_LEN 4 +#define MCP_BUFFER_SIZE 60 + +#include +TasmotaSerial *McpSerial; + typedef struct mcp_cal_registers_type { uint16_t gain_current_rms; uint16_t gain_voltage_rms; @@ -86,6 +91,9 @@ typedef struct mcp_cal_registers_type { uint16_t accumulation_interval; } mcp_cal_registers_type; +char *mcp_buffer = NULL; // Serial receive buffer +int mcp_byte_counter = 0; // Index in serial receive buffer + unsigned long mcp_kWhcounter = 0; uint32_t mcp_system_configuration = 0x03000000; uint32_t mcp_active_power; @@ -146,7 +154,7 @@ void McpSend(uint8_t *data) // AddLogBuffer(LOG_LEVEL_DEBUG_MORE, data, data[1]); for (uint8_t i = 0; i < data[1]; i++) { - Serial.write(data[i]); + McpSerial->write(data[i]); } } @@ -162,7 +170,7 @@ void McpGetAddress(void) void McpAddressReceive(void) { // 06 05 004D 58 - mcp_address = serial_in_buffer[3]; + mcp_address = mcp_buffer[3]; } /********************************************************************************************/ @@ -183,26 +191,26 @@ void McpParseCalibration(void) mcp_cal_registers_type cal_registers; // 06 37 C882 B6AD 0781 9273 06000000 00000000 00000000 0000 D3FF 0300 00000003 9204 120C1300 204E0000 9808 E0AB0000 D9940000 0200 24 - cal_registers.gain_current_rms = McpExtractInt(serial_in_buffer, 2, 2); - cal_registers.gain_voltage_rms = McpExtractInt(serial_in_buffer, 4, 2); - cal_registers.gain_active_power = McpExtractInt(serial_in_buffer, 6, 2); - cal_registers.gain_reactive_power = McpExtractInt(serial_in_buffer, 8, 2); - cal_registers.offset_current_rms = McpExtractInt(serial_in_buffer, 10, 4); - cal_registers.offset_active_power = McpExtractInt(serial_in_buffer, 14, 4); - cal_registers.offset_reactive_power = McpExtractInt(serial_in_buffer, 18, 4); - cal_registers.dc_offset_current = McpExtractInt(serial_in_buffer, 22, 2); - cal_registers.phase_compensation = McpExtractInt(serial_in_buffer, 24, 2); - cal_registers.apparent_power_divisor = McpExtractInt(serial_in_buffer, 26, 2); + cal_registers.gain_current_rms = McpExtractInt(mcp_buffer, 2, 2); + cal_registers.gain_voltage_rms = McpExtractInt(mcp_buffer, 4, 2); + cal_registers.gain_active_power = McpExtractInt(mcp_buffer, 6, 2); + cal_registers.gain_reactive_power = McpExtractInt(mcp_buffer, 8, 2); + cal_registers.offset_current_rms = McpExtractInt(mcp_buffer, 10, 4); + cal_registers.offset_active_power = McpExtractInt(mcp_buffer, 14, 4); + cal_registers.offset_reactive_power = McpExtractInt(mcp_buffer, 18, 4); + cal_registers.dc_offset_current = McpExtractInt(mcp_buffer, 22, 2); + cal_registers.phase_compensation = McpExtractInt(mcp_buffer, 24, 2); + cal_registers.apparent_power_divisor = McpExtractInt(mcp_buffer, 26, 2); - cal_registers.system_configuration = McpExtractInt(serial_in_buffer, 28, 4); - cal_registers.dio_configuration = McpExtractInt(serial_in_buffer, 32, 2); - cal_registers.range = McpExtractInt(serial_in_buffer, 34, 4); + cal_registers.system_configuration = McpExtractInt(mcp_buffer, 28, 4); + cal_registers.dio_configuration = McpExtractInt(mcp_buffer, 32, 2); + cal_registers.range = McpExtractInt(mcp_buffer, 34, 4); - cal_registers.calibration_current = McpExtractInt(serial_in_buffer, 38, 4); - cal_registers.calibration_voltage = McpExtractInt(serial_in_buffer, 42, 2); - cal_registers.calibration_active_power = McpExtractInt(serial_in_buffer, 44, 4); - cal_registers.calibration_reactive_power = McpExtractInt(serial_in_buffer, 48, 4); - cal_registers.accumulation_interval = McpExtractInt(serial_in_buffer, 52, 2); + cal_registers.calibration_current = McpExtractInt(mcp_buffer, 38, 4); + cal_registers.calibration_voltage = McpExtractInt(mcp_buffer, 42, 2); + cal_registers.calibration_active_power = McpExtractInt(mcp_buffer, 44, 4); + cal_registers.calibration_reactive_power = McpExtractInt(mcp_buffer, 48, 4); + cal_registers.accumulation_interval = McpExtractInt(mcp_buffer, 52, 2); if (mcp_calibrate & MCP_CALIBRATE_POWER) { cal_registers.calibration_active_power = Settings.energy_power_calibration; @@ -373,8 +381,8 @@ void McpGetFrequency(void) void McpParseFrequency(void) { // 06 07 C350 8000 A0 - uint16_t line_frequency_ref = serial_in_buffer[2] * 256 + serial_in_buffer[3]; - uint16_t gain_line_frequency = serial_in_buffer[4] * 256 + serial_in_buffer[5]; + uint16_t line_frequency_ref = mcp_buffer[2] * 256 + mcp_buffer[3]; + uint16_t gain_line_frequency = mcp_buffer[4] * 256 + mcp_buffer[5]; if (mcp_calibrate & MCP_CALIBRATE_FREQUENCY) { line_frequency_ref = Settings.energy_frequency_calibration; @@ -438,12 +446,12 @@ void McpParseData(void) // 06 19 CE 18 00 00 F2 08 3A 38 00 00 66 00 00 00 93 38 00 00 36 7F 9A C6 B7 // Ak Ln Current---- Volt- ActivePower ReActivePow ApparentPow Factr Frequ Ck - mcp_current_rms = McpExtractInt(serial_in_buffer, 2, 4); - mcp_voltage_rms = McpExtractInt(serial_in_buffer, 6, 2); - mcp_active_power = McpExtractInt(serial_in_buffer, 8, 4); -// mcp_reactive_power = McpExtractInt(serial_in_buffer, 12, 4); -// mcp_power_factor = McpExtractInt(serial_in_buffer, 20, 2); - mcp_line_frequency = McpExtractInt(serial_in_buffer, 22, 2); + mcp_current_rms = McpExtractInt(mcp_buffer, 2, 4); + mcp_voltage_rms = McpExtractInt(mcp_buffer, 6, 2); + mcp_active_power = McpExtractInt(mcp_buffer, 8, 4); +// mcp_reactive_power = McpExtractInt(mcp_buffer, 12, 4); +// mcp_power_factor = McpExtractInt(mcp_buffer, 20, 2); + mcp_line_frequency = McpExtractInt(mcp_buffer, 22, 2); if (energy_power_on) { // Powered on energy_frequency = (float)mcp_line_frequency / 1000; @@ -464,49 +472,52 @@ void McpParseData(void) /********************************************************************************************/ -bool McpSerialInput(void) +void McpSerialInput(void) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - unsigned long start = millis(); - while (millis() - start < 20) { - yield(); - if (Serial.available()) { - serial_in_buffer[serial_in_byte_counter++] = Serial.read(); - start = millis(); - } - } - - AddLogSerial(LOG_LEVEL_DEBUG_MORE); - - if (1 == serial_in_byte_counter) { - if (MCP_ERROR_CRC == serial_in_buffer[0]) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Send " D_CHECKSUM_FAILURE)); - mcp_timeout = 0; - } - else if (MCP_ERROR_NAK == serial_in_buffer[0]) { -// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: NAck")); - mcp_timeout = 0; - } - } - else if (MCP_ACK_FRAME == serial_in_buffer[0]) { - if (serial_in_byte_counter == serial_in_buffer[1]) { - - if (McpChecksum((uint8_t *)serial_in_buffer) != serial_in_buffer[serial_in_byte_counter -1]) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); - } else { - if (5 == serial_in_buffer[1]) { McpAddressReceive(); } - if (25 == serial_in_buffer[1]) { McpParseData(); } - if (MCP_CALIBRATION_LEN + 3 == serial_in_buffer[1]) { McpParseCalibration(); } - if (MCP_FREQUENCY_LEN + 3 == serial_in_buffer[1]) { McpParseFrequency(); } + if (McpSerial->available()) { + unsigned long start = millis(); + while (millis() - start < 20) { + yield(); + if (McpSerial->available()) { + mcp_buffer[mcp_byte_counter++] = McpSerial->read(); + start = millis(); } - } - mcp_timeout = 0; + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)mcp_buffer, mcp_byte_counter); + + if (1 == mcp_byte_counter) { + if (MCP_ERROR_CRC == mcp_buffer[0]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Send " D_CHECKSUM_FAILURE)); + mcp_timeout = 0; + } + else if (MCP_ERROR_NAK == mcp_buffer[0]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: NAck")); + mcp_timeout = 0; + } + } + else if (MCP_ACK_FRAME == mcp_buffer[0]) { + if (mcp_byte_counter == mcp_buffer[1]) { + + if (McpChecksum((uint8_t *)mcp_buffer) != mcp_buffer[mcp_byte_counter -1]) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); + } else { + if (5 == mcp_buffer[1]) { McpAddressReceive(); } + if (25 == mcp_buffer[1]) { McpParseData(); } + if (MCP_CALIBRATION_LEN + 3 == mcp_buffer[1]) { McpParseCalibration(); } + if (MCP_FREQUENCY_LEN + 3 == mcp_buffer[1]) { McpParseFrequency(); } + } + + } + mcp_timeout = 0; + } + else if (MCP_SINGLE_WIRE == mcp_buffer[0]) { + mcp_timeout = 0; + } + + mcp_byte_counter = 0; + McpSerial->flush(); } - else if (MCP_SINGLE_WIRE == serial_in_buffer[0]) { - mcp_timeout = 0; - } - return 1; } /********************************************************************************************/ @@ -543,25 +554,33 @@ void McpEverySecond(void) void McpSnsInit(void) { - SetSeriallog(LOG_LEVEL_NONE); // Free serial interface from logging interference - if (pin[GPIO_MCP39_RST] < 99) { - digitalWrite(pin[GPIO_MCP39_RST], 1); // MCP enable + // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions + McpSerial = new TasmotaSerial(pin[GPIO_MCP39F5_RX], pin[GPIO_MCP39F5_TX], 1); + if (McpSerial->begin(4800)) { + if (McpSerial->hardwareSerial()) { ClaimSerial(); } + if (pin[GPIO_MCP39F5_RST] < 99) { + digitalWrite(pin[GPIO_MCP39F5_RST], 1); // MCP enable + } + } else { + energy_flg = ENERGY_NONE; } } void McpDrvInit(void) { if (!energy_flg) { - if ((pin[GPIO_MCP39_RX] < 99) && (pin[GPIO_MCP39_TX] < 99)) { - if (pin[GPIO_MCP39_RST] < 99) { - pinMode(pin[GPIO_MCP39_RST], OUTPUT); - digitalWrite(pin[GPIO_MCP39_RST], 0); // MCP disable - Reset Delta Sigma ADC's + if ((pin[GPIO_MCP39F5_RX] < 99) && (pin[GPIO_MCP39F5_TX] < 99)) { + mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); + if (mcp_buffer != NULL) { + if (pin[GPIO_MCP39F5_RST] < 99) { + pinMode(pin[GPIO_MCP39F5_RST], OUTPUT); + digitalWrite(pin[GPIO_MCP39F5_RST], 0); // MCP disable - Reset Delta Sigma ADC's + } + mcp_calibrate = 0; + mcp_timeout = 2; // Initial wait + mcp_init = 2; // Initial setup steps + energy_flg = XNRG_04; } - baudrate = 4800; - mcp_calibrate = 0; - mcp_timeout = 2; // Initial wait - mcp_init = 2; // Initial setup steps - energy_flg = XNRG_04; } } } @@ -632,15 +651,15 @@ int Xnrg04(uint8_t function) case FUNC_INIT: McpSnsInit(); break; + case FUNC_LOOP: + McpSerialInput(); + break; case FUNC_EVERY_SECOND: McpEverySecond(); break; case FUNC_COMMAND: result = McpCommand(); break; - case FUNC_SERIAL: - result = McpSerialInput(); - break; } } return result; From e9ad78c616c525ac70d9214c029b190723475d01 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 5 Feb 2019 10:13:22 +0100 Subject: [PATCH 0954/2222] Update xnrg_04_mcp39f501.ino Fix Exception 9 (Buffer overflow) --- sonoff/xnrg_04_mcp39f501.ino | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index 53034a73c..5247488e1 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -28,6 +28,7 @@ #define XNRG_04 4 +#define MCP_BAUDRATE 4800 #define MCP_TIMEOUT 4 #define MCP_CALIBRATION_TIMEOUT 2 @@ -66,7 +67,7 @@ #define MCP_BUFFER_SIZE 60 #include -TasmotaSerial *McpSerial; +TasmotaSerial *McpSerial = NULL; typedef struct mcp_cal_registers_type { uint16_t gain_current_rms; @@ -92,7 +93,6 @@ typedef struct mcp_cal_registers_type { } mcp_cal_registers_type; char *mcp_buffer = NULL; // Serial receive buffer -int mcp_byte_counter = 0; // Index in serial receive buffer unsigned long mcp_kWhcounter = 0; uint32_t mcp_system_configuration = 0x03000000; @@ -475,8 +475,10 @@ void McpParseData(void) void McpSerialInput(void) { if (McpSerial->available()) { + int mcp_byte_counter = 0; + unsigned long start = millis(); - while (millis() - start < 20) { + while ((millis() - start < (24000 / MCP_BAUDRATE) +1) && (mcp_byte_counter < MCP_BUFFER_SIZE)) { yield(); if (McpSerial->available()) { mcp_buffer[mcp_byte_counter++] = McpSerial->read(); @@ -515,7 +517,6 @@ void McpSerialInput(void) mcp_timeout = 0; } - mcp_byte_counter = 0; McpSerial->flush(); } } @@ -556,7 +557,7 @@ void McpSnsInit(void) { // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions McpSerial = new TasmotaSerial(pin[GPIO_MCP39F5_RX], pin[GPIO_MCP39F5_TX], 1); - if (McpSerial->begin(4800)) { + if (McpSerial->begin(MCP_BAUDRATE)) { if (McpSerial->hardwareSerial()) { ClaimSerial(); } if (pin[GPIO_MCP39F5_RST] < 99) { digitalWrite(pin[GPIO_MCP39F5_RST], 1); // MCP enable @@ -652,10 +653,10 @@ int Xnrg04(uint8_t function) McpSnsInit(); break; case FUNC_LOOP: - McpSerialInput(); + if (McpSerial) { McpSerialInput(); } break; case FUNC_EVERY_SECOND: - McpEverySecond(); + if (McpSerial) { McpEverySecond(); } break; case FUNC_COMMAND: result = McpCommand(); From adecf6a9ce2d751064f5bd55b6179039cc86d32a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 5 Feb 2019 12:21:31 +0100 Subject: [PATCH 0955/2222] Fixes and Tuning Fixes and Tuning --- sonoff/xnrg_03_pzem004t.ino | 4 +-- sonoff/xnrg_04_mcp39f501.ino | 53 +++++++++++++++++++----------------- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index e0b6327bd..a15d61ba1 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -32,7 +32,7 @@ #include -TasmotaSerial *PzemSerial; +TasmotaSerial *PzemSerial = NULL; #define PZEM_VOLTAGE (uint8_t)0xB0 #define RESP_VOLTAGE (uint8_t)0xA0 @@ -239,7 +239,7 @@ int Xnrg03(uint8_t function) PzemSnsInit(); break; case FUNC_EVERY_200_MSECOND: - PzemEvery200ms(); + if (PzemSerial) { PzemEvery200ms(); } break; } } diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index 5247488e1..d878d9e8b 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -92,8 +92,8 @@ typedef struct mcp_cal_registers_type { uint16_t accumulation_interval; } mcp_cal_registers_type; -char *mcp_buffer = NULL; // Serial receive buffer - +char *mcp_buffer = NULL; +unsigned long mcp_window = 0; unsigned long mcp_kWhcounter = 0; uint32_t mcp_system_configuration = 0x03000000; uint32_t mcp_active_power; @@ -108,6 +108,7 @@ uint8_t mcp_calibration_active = 0; uint8_t mcp_init = 0; uint8_t mcp_timeout = 0; uint8_t mcp_calibrate = 0; +uint8_t mcp_byte_counter = 0; /*********************************************************************************************\ * Olimex tools @@ -474,21 +475,20 @@ void McpParseData(void) void McpSerialInput(void) { - if (McpSerial->available()) { - int mcp_byte_counter = 0; - - unsigned long start = millis(); - while ((millis() - start < (24000 / MCP_BAUDRATE) +1) && (mcp_byte_counter < MCP_BUFFER_SIZE)) { - yield(); - if (McpSerial->available()) { - mcp_buffer[mcp_byte_counter++] = McpSerial->read(); - start = millis(); - } - } + while ((McpSerial->available()) && (mcp_byte_counter < MCP_BUFFER_SIZE)) { + yield(); + mcp_buffer[mcp_byte_counter++] = McpSerial->read(); + mcp_window = millis(); + } + // Ignore until non received after 2 chars (= 12 bits/char) time + if ((mcp_byte_counter) && (millis() - mcp_window > (24000 / MCP_BAUDRATE) +1)) { AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)mcp_buffer, mcp_byte_counter); - if (1 == mcp_byte_counter) { + if (MCP_BUFFER_SIZE == mcp_byte_counter) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Overflow")); + } + else if (1 == mcp_byte_counter) { if (MCP_ERROR_CRC == mcp_buffer[0]) { // AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Send " D_CHECKSUM_FAILURE)); mcp_timeout = 0; @@ -517,6 +517,7 @@ void McpSerialInput(void) mcp_timeout = 0; } + mcp_byte_counter = 0; McpSerial->flush(); } } @@ -558,7 +559,12 @@ void McpSnsInit(void) // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions McpSerial = new TasmotaSerial(pin[GPIO_MCP39F5_RX], pin[GPIO_MCP39F5_TX], 1); if (McpSerial->begin(MCP_BAUDRATE)) { - if (McpSerial->hardwareSerial()) { ClaimSerial(); } + if (McpSerial->hardwareSerial()) { + ClaimSerial(); + mcp_buffer = serial_in_buffer; // Use idle serial buffer to save RAM + } else { + mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); + } if (pin[GPIO_MCP39F5_RST] < 99) { digitalWrite(pin[GPIO_MCP39F5_RST], 1); // MCP enable } @@ -571,17 +577,14 @@ void McpDrvInit(void) { if (!energy_flg) { if ((pin[GPIO_MCP39F5_RX] < 99) && (pin[GPIO_MCP39F5_TX] < 99)) { - mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); - if (mcp_buffer != NULL) { - if (pin[GPIO_MCP39F5_RST] < 99) { - pinMode(pin[GPIO_MCP39F5_RST], OUTPUT); - digitalWrite(pin[GPIO_MCP39F5_RST], 0); // MCP disable - Reset Delta Sigma ADC's - } - mcp_calibrate = 0; - mcp_timeout = 2; // Initial wait - mcp_init = 2; // Initial setup steps - energy_flg = XNRG_04; + if (pin[GPIO_MCP39F5_RST] < 99) { + pinMode(pin[GPIO_MCP39F5_RST], OUTPUT); + digitalWrite(pin[GPIO_MCP39F5_RST], 0); // MCP disable - Reset Delta Sigma ADC's } + mcp_calibrate = 0; + mcp_timeout = 2; // Initial wait + mcp_init = 2; // Initial setup steps + energy_flg = XNRG_04; } } } From 9c8af6428ee9ce3ad6060e65d2774ebfa40e575d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 5 Feb 2019 14:13:53 +0100 Subject: [PATCH 0956/2222] Update xdrv_08_serial_bridge.ino Fix regression --- sonoff/xdrv_08_serial_bridge.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index bb2abab63..74915935c 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -42,7 +42,7 @@ void SerialBridgeInput(void) { while (SerialBridgeSerial->available()) { yield(); - uint8_t serial_in_uint8_t = SerialBridgeSerial->read(); + uint8_t serial_in_byte = SerialBridgeSerial->read(); if (serial_in_byte > 127) { // binary data... serial_bridge_in_byte_counter = 0; From c998760deb15caa37b3abcc079e007daab2e0669 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 5 Feb 2019 15:05:40 +0100 Subject: [PATCH 0957/2222] Update TasmotaSerial to 2.3.0 Update TasmotaSerial to 2.3.0 --- .../README.md | 0 .../examples/swsertest/swsertest.ino | 0 .../keywords.txt | 1 + .../library.json | 2 +- .../library.properties | 2 +- .../src/TasmotaSerial.cpp | 8 ++++---- .../src/TasmotaSerial.h | 4 ++-- 7 files changed, 9 insertions(+), 8 deletions(-) rename lib/{TasmotaSerial-2.2.0 => TasmotaSerial-2.3.0}/README.md (100%) rename lib/{TasmotaSerial-2.2.0 => TasmotaSerial-2.3.0}/examples/swsertest/swsertest.ino (100%) rename lib/{TasmotaSerial-2.2.0 => TasmotaSerial-2.3.0}/keywords.txt (95%) rename lib/{TasmotaSerial-2.2.0 => TasmotaSerial-2.3.0}/library.json (94%) rename lib/{TasmotaSerial-2.2.0 => TasmotaSerial-2.3.0}/library.properties (94%) rename lib/{TasmotaSerial-2.2.0 => TasmotaSerial-2.3.0}/src/TasmotaSerial.cpp (97%) rename lib/{TasmotaSerial-2.2.0 => TasmotaSerial-2.3.0}/src/TasmotaSerial.h (96%) diff --git a/lib/TasmotaSerial-2.2.0/README.md b/lib/TasmotaSerial-2.3.0/README.md similarity index 100% rename from lib/TasmotaSerial-2.2.0/README.md rename to lib/TasmotaSerial-2.3.0/README.md diff --git a/lib/TasmotaSerial-2.2.0/examples/swsertest/swsertest.ino b/lib/TasmotaSerial-2.3.0/examples/swsertest/swsertest.ino similarity index 100% rename from lib/TasmotaSerial-2.2.0/examples/swsertest/swsertest.ino rename to lib/TasmotaSerial-2.3.0/examples/swsertest/swsertest.ino diff --git a/lib/TasmotaSerial-2.2.0/keywords.txt b/lib/TasmotaSerial-2.3.0/keywords.txt similarity index 95% rename from lib/TasmotaSerial-2.2.0/keywords.txt rename to lib/TasmotaSerial-2.3.0/keywords.txt index 87974971e..9cf6d825c 100644 --- a/lib/TasmotaSerial-2.2.0/keywords.txt +++ b/lib/TasmotaSerial-2.3.0/keywords.txt @@ -14,6 +14,7 @@ TasmotaSerial KEYWORD1 ####################################### begin KEYWORD2 +hardwareSerial KEYWORD2 read KEYWORD2 write KEYWORD2 available KEYWORD2 diff --git a/lib/TasmotaSerial-2.2.0/library.json b/lib/TasmotaSerial-2.3.0/library.json similarity index 94% rename from lib/TasmotaSerial-2.2.0/library.json rename to lib/TasmotaSerial-2.3.0/library.json index 23a2ddab9..fad36bcc6 100644 --- a/lib/TasmotaSerial-2.2.0/library.json +++ b/lib/TasmotaSerial-2.3.0/library.json @@ -1,6 +1,6 @@ { "name": "TasmotaSerial", - "version": "2.2.0", + "version": "2.3.0", "keywords": [ "serial", "io", "TasmotaSerial" ], diff --git a/lib/TasmotaSerial-2.2.0/library.properties b/lib/TasmotaSerial-2.3.0/library.properties similarity index 94% rename from lib/TasmotaSerial-2.2.0/library.properties rename to lib/TasmotaSerial-2.3.0/library.properties index 54c79e218..095077d8e 100644 --- a/lib/TasmotaSerial-2.2.0/library.properties +++ b/lib/TasmotaSerial-2.3.0/library.properties @@ -1,5 +1,5 @@ name=TasmotaSerial -version=2.2.0 +version=2.3.0 author=Theo Arends maintainer=Theo Arends sentence=Implementation of software serial with hardware serial fallback for ESP8266. diff --git a/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-2.3.0/src/TasmotaSerial.cpp similarity index 97% rename from lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp rename to lib/TasmotaSerial-2.3.0/src/TasmotaSerial.cpp index 3df42f834..eecdeb124 100644 --- a/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-2.3.0/src/TasmotaSerial.cpp @@ -1,7 +1,7 @@ /* TasmotaSerial.cpp - Minimal implementation of software serial for Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -100,7 +100,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal m_buffer = (uint8_t*)malloc(TM_SERIAL_BUFFER_SIZE); if (m_buffer == NULL) return; // Use getCycleCount() loop to get as exact timing as possible - m_bit_time = ESP.getCpuFreqMHz() *1000000 /TM_SERIAL_BAUDRATE; + m_bit_time = F_CPU / TM_SERIAL_BAUDRATE; pinMode(m_rx_pin, INPUT); tms_obj_list[m_rx_pin] = this; attachInterrupt(m_rx_pin, ISRList[m_rx_pin], FALLING); @@ -145,7 +145,7 @@ bool TasmotaSerial::begin(long speed, int stop_bits) { } } else { // Use getCycleCount() loop to get as exact timing as possible - m_bit_time = ESP.getCpuFreqMHz() *1000000 /speed; + m_bit_time = F_CPU / speed; m_high_speed = (speed > 9600); } return m_valid; @@ -257,7 +257,7 @@ void TasmotaSerial::rxRead() TM_SERIAL_WAIT; } // Store the received value in the buffer unless we have an overflow - int next = (m_in_pos+1) % TM_SERIAL_BUFFER_SIZE; + unsigned int next = (m_in_pos+1) % TM_SERIAL_BUFFER_SIZE; if (next != (int)m_out_pos) { m_buffer[m_in_pos] = rec; m_in_pos = next; diff --git a/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h b/lib/TasmotaSerial-2.3.0/src/TasmotaSerial.h similarity index 96% rename from lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h rename to lib/TasmotaSerial-2.3.0/src/TasmotaSerial.h index de991526a..9481ef370 100644 --- a/lib/TasmotaSerial-2.2.0/src/TasmotaSerial.h +++ b/lib/TasmotaSerial-2.3.0/src/TasmotaSerial.h @@ -1,7 +1,7 @@ /* TasmotaSerial.h - Minimal implementation of software serial for Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2019 Theo Arends This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,7 +22,7 @@ /*********************************************************************************************\ * TasmotaSerial supports up to 115200 baud with fixed buffer size of 64 bytes using optional no iram * - * Based on EspSoftwareSerial v3.3.1 by Peter Lerup (https://github.com/plerup/espsoftwareserial) + * Based on EspSoftwareSerial v3.4.3 by Peter Lerup (https://github.com/plerup/espsoftwareserial) \*********************************************************************************************/ #define TM_SERIAL_BAUDRATE 9600 // Default baudrate From 09732c9f2d116885ec3c748867e14f72820df947 Mon Sep 17 00:00:00 2001 From: Laurent Dong Date: Tue, 5 Feb 2019 09:34:17 -0500 Subject: [PATCH 0958/2222] Add new compare operators ("==", "!=" ,">=" and "<=") for rule Introduce new compare operators for rules and did some optimization as well. The new "==" operator act as a real number comparison instead of the previous "=" operator which is doing string comparison which result in FALSE for "1 + 1 = 2". For example: rule1 on event#test do backlog var1 1;add1 1; event CompareWith2=2 endon on event#CompareWith2=%var1% do ledpower on endon ledpower off rule1 on event test --- .gitignore | 1 + sonoff/xdrv_10_rules.ino | 82 ++++++++++++++++++++++++---------------- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index 028a76667..7e89f6cd2 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ build .vscode/.browse.c_cpp.db* .vscode/c_cpp_properties.json .vscode/launch.json +*.bak diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 0ea47c369..d1f7c43b2 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -78,6 +78,27 @@ #define D_JSON_INITIATED "Initiated" +#define COMPARE_OPERATOR_NONE -1 +#define COMPARE_OPERATOR_EQUAL 0 +#define COMPARE_OPERATOR_BIGGER 1 +#define COMPARE_OPERATOR_SMALLER 2 +#define COMPARE_OPERATOR_EXACT_DIVISION 3 +#define COMPARE_OPERATOR_NUMBER_EQUAL 4 +#define COMPARE_OPERATOR_NOT_EQUAL 5 +#define COMPARE_OPERATOR_BIGGER_EQUAL 6 +#define COMPARE_OPERATOR_SMALLER_EQUAL 7 +#define MAXIMUM_COMPARE_OPERATOR COMPARE_OPERATOR_SMALLER_EQUAL +char* compare_operators[] = { + "=", + ">", + "<", + "|", + "==", + "!=", + ">=", + "<=" +}; + enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM, CMND_ADD, CMND_SUB, CMND_MULT, CMND_SCALE, CMND_CALC_RESOLUTION }; const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM "|" D_CMND_ADD "|" D_CMND_SUB "|" D_CMND_MULT "|" D_CMND_SCALE "|" D_CMND_CALC_RESOLUTION ; @@ -128,31 +149,18 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) String rule_name = rule.substring(pos +1); // "CURRENT>0.100" or "BOOT" or "%var1%" or "MINUTE|5" - char compare = ' '; - pos = rule_name.indexOf(">"); - if (pos > 0) { - compare = '>'; - } else { - pos = rule_name.indexOf("<"); - if (pos > 0) { - compare = '<'; - } else { - pos = rule_name.indexOf("="); - if (pos > 0) { - compare = '='; - } else { - pos = rule_name.indexOf("|"); // Modulo, cannot use % easily as it is used for variable detection - if (pos > 0) { - compare = '%'; - } - } + int8_t compare = COMPARE_OPERATOR_NONE; + for (int8_t i=MAXIMUM_COMPARE_OPERATOR; i>=0; i--) { + if ((pos = rule_name.indexOf(compare_operators[i])) > 0) { + compare = i; + break; } } char rule_svalue[CMDSZ] = { 0 }; double rule_value = 0; - if (pos > 0) { - String rule_param = rule_name.substring(pos + 1); + if (compare != COMPARE_OPERATOR_NONE) { + String rule_param = rule_name.substring(pos + strlen(compare_operators[compare])); for (uint8_t i = 0; i < MAX_RULE_VARS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%%VAR%d%%"), i +1); if (rule_param.startsWith(stemp)) { @@ -224,24 +232,32 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) int int_value = int(value); int int_rule_value = int(rule_value); switch (compare) { - case '%': - if ((int_value > 0) && (int_rule_value > 0)) { - if ((int_value % int_rule_value) == 0) { match = true; } - } + case COMPARE_OPERATOR_EXACT_DIVISION: + match = (int_rule_value && (int_value % int_rule_value) == 0); break; - case '>': - if (value > rule_value) { match = true; } + case COMPARE_OPERATOR_EQUAL: + match = (!strcasecmp(str_value, rule_svalue)); // Compare strings - this also works for hexadecimals break; - case '<': - if (value < rule_value) { match = true; } + case COMPARE_OPERATOR_BIGGER: + match = (value > rule_value); break; - case '=': -// if (value == rule_value) { match = true; } // Compare values - only decimals or partly hexadecimals - if (!strcasecmp(str_value, rule_svalue)) { match = true; } // Compare strings - this also works for hexadecimals + case COMPARE_OPERATOR_SMALLER: + match = (value < rule_value); break; - case ' ': - match = true; // Json value but not needed + case COMPARE_OPERATOR_NUMBER_EQUAL: + match = (value == rule_value); break; + case COMPARE_OPERATOR_NOT_EQUAL: + match = (value != rule_value); + break; + case COMPARE_OPERATOR_BIGGER_EQUAL: + match = (value >= rule_value); + break; + case COMPARE_OPERATOR_SMALLER_EQUAL: + match = (value <= rule_value); + break; + default: + match = true; } } else match = true; From ee2660b2bc332bf900897b1558bfb4f4c5a291cb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 5 Feb 2019 17:45:35 +0100 Subject: [PATCH 0959/2222] Update xdrv_10_rules.ino Move const to flash --- sonoff/xdrv_10_rules.ino | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index d1f7c43b2..327c128dc 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -78,26 +78,17 @@ #define D_JSON_INITIATED "Initiated" -#define COMPARE_OPERATOR_NONE -1 -#define COMPARE_OPERATOR_EQUAL 0 -#define COMPARE_OPERATOR_BIGGER 1 -#define COMPARE_OPERATOR_SMALLER 2 +#define COMPARE_OPERATOR_NONE -1 +#define COMPARE_OPERATOR_EQUAL 0 +#define COMPARE_OPERATOR_BIGGER 1 +#define COMPARE_OPERATOR_SMALLER 2 #define COMPARE_OPERATOR_EXACT_DIVISION 3 #define COMPARE_OPERATOR_NUMBER_EQUAL 4 #define COMPARE_OPERATOR_NOT_EQUAL 5 #define COMPARE_OPERATOR_BIGGER_EQUAL 6 #define COMPARE_OPERATOR_SMALLER_EQUAL 7 #define MAXIMUM_COMPARE_OPERATOR COMPARE_OPERATOR_SMALLER_EQUAL -char* compare_operators[] = { - "=", - ">", - "<", - "|", - "==", - "!=", - ">=", - "<=" -}; +const char kCompareOperators[] PROGMEM = "=\0>\0<\0|\0==!=>=<="; enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM, CMND_ADD, CMND_SUB, CMND_MULT, CMND_SCALE, CMND_CALC_RESOLUTION }; const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM "|" D_CMND_ADD "|" D_CMND_SUB "|" D_CMND_MULT "|" D_CMND_SCALE "|" D_CMND_CALC_RESOLUTION ; @@ -149,9 +140,11 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) String rule_name = rule.substring(pos +1); // "CURRENT>0.100" or "BOOT" or "%var1%" or "MINUTE|5" + char compare_operator[3]; int8_t compare = COMPARE_OPERATOR_NONE; - for (int8_t i=MAXIMUM_COMPARE_OPERATOR; i>=0; i--) { - if ((pos = rule_name.indexOf(compare_operators[i])) > 0) { + for (int8_t i = MAXIMUM_COMPARE_OPERATOR; i >= 0; i--) { + snprintf_P(compare_operator, sizeof(compare_operator), kCompareOperators + (i *2)); + if ((pos = rule_name.indexOf(compare_operator)) > 0) { compare = i; break; } @@ -160,7 +153,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) char rule_svalue[CMDSZ] = { 0 }; double rule_value = 0; if (compare != COMPARE_OPERATOR_NONE) { - String rule_param = rule_name.substring(pos + strlen(compare_operators[compare])); + String rule_param = rule_name.substring(pos + strlen(compare_operator)); for (uint8_t i = 0; i < MAX_RULE_VARS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%%VAR%d%%"), i +1); if (rule_param.startsWith(stemp)) { From b430a22e0ca931164b691aa3515990322d26aacc Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Wed, 6 Feb 2019 19:57:11 +0100 Subject: [PATCH 0960/2222] Core 2.5.0 Release Changed core 2.5.0 beta3 to Release. --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 6b6176db0..5631982dd 100644 --- a/platformio.ini +++ b/platformio.ini @@ -65,7 +65,7 @@ build_flags = ${esp82xx_defaults.build_flags} -DVTABLES_IN_FLASH [core_2_5_0] -; *** Esp8266 core for Arduino version Core 2.5.0 beta3 tested for Tasmota +; *** Esp8266 core for Arduino version 2.5.0 release (still not available via platformio) platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld From 3281055438bc6c17cfa379332e465bae81b51e19 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 6 Feb 2019 20:07:28 +0100 Subject: [PATCH 0961/2222] Add HASS status sensor --- sonoff/i18n.h | 1 + sonoff/xdrv_12_home_assistant.ino | 162 +++++++++++++++++++++++------- 2 files changed, 127 insertions(+), 36 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 3f9725772..7eace1215 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -160,6 +160,7 @@ #define D_JSON_ZERO_POINT_CALIBRATION "Zero Point Calibration" #define D_RSLT_ENERGY "ENERGY" +#define D_RSLT_HASS_STATE "HASS_STATE" #define D_RSLT_INFO "INFO" #define D_RSLT_MARGINS "MARGINS" #define D_RSLT_POWER "POWER" diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 6b6d1bff3..155ee05a2 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -122,6 +122,11 @@ const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = "%s,\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} +const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = + "%s,\"json_attributes_topic\":\"%s\"," + "\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass + "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\"";// "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} + const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = "%s,\"uniq_id\":\"%s\"," "\"device\":{\"identifiers\":[\"%06X\"]," @@ -130,11 +135,16 @@ const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = "\"sw_version\":\"%s%s\"," "\"manufacturer\":\"Tasmota\"}"; +const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = + "%s,\"uniq_id\":\"%s\"," + "\"device\":{\"identifiers\":[\"%06X\"]}"; + const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM = "%s, \"~\":\"%s\""; uint8_t hass_init_step = 0; uint8_t hass_mode = 0; +int hass_tele_period = 0; static void FindPrefix(char* s1, char* s2, char* out) { @@ -156,6 +166,23 @@ static void Shorten(char** s, char *prefix) } } +int try_snprintf_P(char *s, size_t n, const char *format, ... ) +{ + va_list args; + va_start(args, format); + int len = vsnprintf_P(NULL, 0, format, args); + if (len >= n) { + snprintf_P(log_data, sizeof(log_data), + PSTR("ERROR: MQTT discovery failed due to too long topic or friendly name. \ + Please shorten topic and friendly name.")); + AddLog(LOG_LEVEL_ERROR); + } else { + va_start(args, format); + vsnprintf_P(s, n, format, args); + } + va_end(args); +} + void HAssAnnounceRelayLight(void) { char stopic[TOPSZ]; @@ -174,11 +201,13 @@ void HAssAnnounceRelayLight(void) // Clear "other" topic first in case the device has been reconfigured from ligth to switch or vice versa snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "RL" : "LI", i); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), (is_topic_light) ? "switch" : "light", unique_id); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), + (is_topic_light) ? "switch" : "light", unique_id); MqttPublish(stopic, true); // Clear or Set topic snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "LI" : "RL", i); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), (is_topic_light) ? "light" : "switch", unique_id); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), + (is_topic_light) ? "light" : "switch", unique_id); if (Settings.flag.hass_discovery && (i <= devices_present)) { char name[33]; @@ -202,27 +231,30 @@ void HAssAnnounceRelayLight(void) Shorten(&command_topic, prefix); Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_RELAY, + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, + unique_id, ESP.getChipId()); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); if (is_light) { char *brightness_command_topic = stemp1; GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); Shorten(&brightness_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_DIMMER, mqtt_data, brightness_command_topic, state_topic); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_DIMMER, mqtt_data, brightness_command_topic, state_topic); if (light_subtype >= LST_RGB) { char *rgb_command_topic = stemp1; GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); Shorten(&rgb_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_COLOR, mqtt_data, rgb_command_topic, state_topic); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_COLOR, mqtt_data, rgb_command_topic, state_topic); char *effect_command_topic = stemp1; GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); Shorten(&effect_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_SCHEME, mqtt_data, effect_command_topic, state_topic); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_SCHEME, mqtt_data, effect_command_topic, state_topic); } if (LST_RGBW == light_subtype) { @@ -230,21 +262,17 @@ void HAssAnnounceRelayLight(void) GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); Shorten(&white_temp_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_WHITE, mqtt_data, white_temp_command_topic, state_topic); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_WHITE, mqtt_data, white_temp_command_topic, state_topic); } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { char *color_temp_command_topic = stemp1; GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); Shorten(&color_temp_command_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_CT, mqtt_data, color_temp_command_topic, state_topic); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_CT, mqtt_data, color_temp_command_topic, state_topic); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data, - unique_id, ESP.getChipId(), - Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } MqttPublish(stopic, true); } @@ -284,16 +312,15 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint FindPrefix(state_topic, availability_topic, prefix); Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH, + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH, name, state_topic, Settings.state_text[toggle?2:1], availability_topic); - if (toggle) snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, mqtt_data); - else snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_ONOFF, mqtt_data, Settings.state_text[0]); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, + unique_id, ESP.getChipId()); + if (strlen(prefix) > 0 ) try_snprintf_P(mqtt_data-1, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + if (toggle) try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, mqtt_data); + else try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH_ONOFF, mqtt_data, Settings.state_text[0]); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data, - unique_id, ESP.getChipId(), - Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image); - if (strlen(prefix) > 0 ) snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } MqttPublish(stopic, true); } @@ -386,39 +413,40 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR, + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, + unique_id, ESP.getChipId()); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); if (!strcmp_P(subsensortype, PSTR(D_JSON_TEMPERATURE))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_TEMP, + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_TEMP, mqtt_data, TempUnit(), sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_HUM, + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_HUM, mqtt_data, sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_PRESS, + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_PRESS, mqtt_data, PressureUnit().c_str(), sensorname); - } else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL)) || !strcmp_P(subsensortype, PSTR(D_JSON_TODAY)) || !strcmp_P(subsensortype, PSTR(D_JSON_YESTERDAY))){ - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_KWH, + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL)) + || !strcmp_P(subsensortype, PSTR(D_JSON_TODAY)) + || !strcmp_P(subsensortype, PSTR(D_JSON_YESTERDAY))){ + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_KWH, mqtt_data, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_POWERUSAGE))){ - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_WATT, + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_WATT, mqtt_data, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_VOLTAGE))){ - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_VOLTAGE, + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_VOLTAGE, mqtt_data, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_CURRENT))){ - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_AMPERE, + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_AMPERE, mqtt_data, sensorname, subsensortype); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_ANY, + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_ANY, mqtt_data, sensorname, subsensortype); } - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data, - unique_id, ESP.getChipId(), - Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image); - snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } MqttPublish(stopic, true); } @@ -469,6 +497,57 @@ void HAssAnnounceSensors(void) } while (hass_xsns_index != 0); } +void HAssAnnounceStatusSensor(void) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + + // Announce sensor + mqtt_data[0] = '\0'; // Clear retained message + + // Clear or Set topic + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s"), ESP.getChipId(), "status"); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); + + if (Settings.flag.hass_discovery) { + char name[33]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + + snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[0], "status"); + GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + FindPrefix(state_topic, availability_topic, prefix); + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR, + name, state_topic, availability_topic); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_HASS_STATUS, + mqtt_data, state_topic); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO, mqtt_data, + unique_id, ESP.getChipId(), + Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + } + MqttPublish(stopic, true); +} + +void HAssPublishStatus(void) +{ + snprintf_P(mqtt_data, sizeof(mqtt_data), + PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" + D_JSON_UPTIME "\":\"%s\",\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" + D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_RSSI "\":\"%d\",\"LoadAvg\":%lu}"), + my_version, my_image, ModuleName().c_str(), GetResetReason().c_str(), GetUptime().c_str(), Settings.bootcount, + Settings.save_flag, WiFi.localIP().toString().c_str(), WifiGetRssiAsQuality(WiFi.RSSI()), loop_load_avg); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE)); +} + void HAssDiscovery(void) { // Configure Tasmota for default Home Assistant parameters to keep discovery message as short as possible @@ -496,6 +575,9 @@ void HAssDiscovery(void) // Send info about sensors HAssAnnounceSensors(); + + // Send info about status sensor + HAssAnnounceStatusSensor(); } } @@ -525,6 +607,14 @@ bool Xdrv12(uint8_t function) if (!hass_init_step) { HAssDiscovery(); // Scheduled discovery using available resources } + } else if (Settings.flag.hass_discovery && Settings.tele_period) { + hass_tele_period++; + if (hass_tele_period >= Settings.tele_period) { + hass_tele_period = 0; + + mqtt_data[0] = '\0'; + HAssPublishStatus(); + } } break; } From 08314bd9f8398c2497b7f67ad3c37eff17aa55f9 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Wed, 6 Feb 2019 22:34:41 +0100 Subject: [PATCH 0962/2222] Rf Bridge Gpio12 / 14 selectable Add GPIO12 and GPIO14 in Rf Bridge as GpioUser. This Gpio are not used and easy reachable via solder pads --- sonoff/sonoff_template.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index f86a6725d..1e5e1a573 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1054,9 +1054,10 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO09 0, // GPIO10 // GPIO11 (SD_CMD Flash) - 0, + GPIO_USER, // GPIO12 Optional sensor GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + GPIO_USER, // GPIO14 Optional sensor + 0, 0, 0 }, { "Sonoff B1", // Sonoff B1 (ESP8285 - my9231) GPIO_KEY1, // GPIO00 Pad From 1bf7d32544884fea76a509de219bc60cc34cad41 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 6 Feb 2019 18:51:54 -0500 Subject: [PATCH 0963/2222] Renamed SM16716 Select to SM16716 Enable to avoid confusion with a SM16726 feature also called select --- sonoff/language/bg-BG.h | 2 +- sonoff/language/cs-CZ.h | 2 +- sonoff/language/de-DE.h | 2 +- sonoff/language/el-GR.h | 2 +- sonoff/language/en-GB.h | 2 +- sonoff/language/es-AR.h | 2 +- sonoff/language/fr-FR.h | 2 +- sonoff/language/he-HE.h | 2 +- sonoff/language/hu-HU.h | 2 +- sonoff/language/it-IT.h | 2 +- sonoff/language/nl-NL.h | 2 +- sonoff/language/pl-PL.h | 2 +- sonoff/language/pt-BR.h | 2 +- sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 2 +- sonoff/language/sk-SK.h | 2 +- sonoff/language/sv-SE.h | 2 +- sonoff/language/tr-TR.h | 2 +- sonoff/language/uk-UK.h | 2 +- sonoff/language/zh-CN.h | 2 +- sonoff/language/zh-TW.h | 2 +- sonoff/sonoff_template.h | 4 ++-- 22 files changed, 23 insertions(+), 23 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 3b0aa8a20..b04271a7f 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Активиране на SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index c7cfcd99f..caf213296 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Povol SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 74be66eac..2c2b48d5e 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "SM16716 aktivieren" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 03bc7dc4e..faa5f0ec2 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Ενεργοποίηση SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 249bb66c5..a4acbf38d 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Enable SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 19988b248..075c8bbf5 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Habilitar SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 27623806d..a75205c26 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Activer SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index a4cee77c5..031635c15 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Enable SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 89adb73e6..3d8cc8850 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "SM16716 engedélyezése" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 7b0801056..c2b3a60c3 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Abilita SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 6aa5ee7c3..c9a0e4715 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -556,7 +556,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "SM16716 inschakelen" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index fa38c7887..1ad8e5546 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -556,7 +556,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Włącz SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index af3d10974..e3f61775a 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Habilitar SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index e868601cb..e9b3c470e 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Enable SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index b7e079a76..a0a0953e9 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Enable SM16716" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 4b14e8c3d..f1e6495c9 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -556,7 +556,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Povoľ SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index fe8f4231b..961637b35 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Aktivera SM16716" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index a307f84f1..1302595cf 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "SM16716 Aktif" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 1ddea2efd..5a2aad11b 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Увімкнений SM16716" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index c362fd86a..3f24ab2ae 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "启用 SM16716" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 105ca749f..be91648d2 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -555,7 +555,7 @@ #define D_SENSOR_CSE7766_RX "CSE7766 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_SEL "SM16716 SEL" +#define D_SENSOR_SM16716_POWER "Enable SM16716" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 561750a71..12f9a9241 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -230,7 +230,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in|" D_SENSOR_NRG_SEL "|" D_SENSOR_NRG_SEL "i|" D_SENSOR_NRG_CF1 "|" D_SENSOR_HLW_CF "|" D_SENSOR_HJL_CF "|" D_SENSOR_MCP39F5_TX "|" D_SENSOR_MCP39F5_RX "|" D_SENSOR_MCP39F5_RST "|" - D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT "|" D_SENSOR_SM16716_SEL + D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT "|" D_SENSOR_SM16716_POWER ; /********************************************************************************************/ @@ -1892,7 +1892,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO10 // GPIO11 GPIO_USER, // GPIO12 Alt. White on some devices - GPIO_USER, // GPIO13 SM16716 Select on some devices + GPIO_USER, // GPIO13 SM16716 Enable on some devices GPIO_SM16716_DAT, // GPIO14 SM16716 Data 0, // GPIO15 wired to GND GPIO_USER, // GPIO16 N.C. From 4dc4f3832391ee35e312d64e00f3d0605a6298f6 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Mon, 4 Feb 2019 01:08:29 -0500 Subject: [PATCH 0964/2222] Added USE_SM16716 to the feature list --- sonoff/support_features.ino | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 6c1abf97a..1dc19e172 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -177,8 +177,10 @@ void GetFeatures(void) #ifdef USE_ARMTRONIX_DIMMERS feature_drv2 |= 0x00020000; // xdrv_18_armtronixdimmer.ino #endif +#ifdef USE_SM16716 + feature_drv2 |= 0x00040000; // xdrv_04_light.ino +#endif -// feature_drv2 |= 0x00040000; // feature_drv2 |= 0x00080000; // feature_drv2 |= 0x00100000; // feature_drv2 |= 0x00200000; From a1ef7b254ed8b9c906c53532b1920c36c08f0ce9 Mon Sep 17 00:00:00 2001 From: Kevin Baluha Date: Thu, 7 Feb 2019 03:08:13 -0700 Subject: [PATCH 0965/2222] check if TSL2561::begin returns true to prevent false positives --- sonoff/xsns_12_ads1115.ino | 13 ++++++++----- sonoff/xsns_16_tsl2561.ino | 3 +-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index f2cfda028..fa321a85c 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -161,6 +161,7 @@ int16_t Ads1115GetConversion(uint8_t channel) void Ads1115Detect(void) { uint16_t buffer; + uint16_t conf_buffer; //if (ads1115_type) { //return; @@ -168,7 +169,9 @@ void Ads1115Detect(void) for (uint8_t i = 0; i < sizeof(ads1115_addresses); i++) { ads1115_address = ads1115_addresses[i]; - if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT)) { + if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT) && + I2cValidRead16(&conf_buffer, ads1115_address, ADS1115_REG_POINTER_CONFIG)) { + Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); ads1115_type = 1; ads1115_found[i] = 1; @@ -184,8 +187,8 @@ void Ads1115GetValues(uint8_t address) { ads1115_address = address; for (uint8_t i = 0; i < 4; i++) { ads1115_values[i] = Ads1115GetConversion(i); - snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x (%i) = %i", address, i, ads1115_values[i] ); - AddLog(LOG_LEVEL_INFO); + //snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x (%i) = %i", address, i, ads1115_values[i] ); + //AddLog(LOG_LEVEL_INFO); } ads1115_address = old_address; } @@ -220,8 +223,8 @@ void Ads1115Show(bool json) char *comma = (char*)""; for (uint8_t t = 0; t < sizeof(ads1115_addresses); t++) { - snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x", ads1115_addresses[t]); - AddLog(LOG_LEVEL_INFO); + //snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x", ads1115_addresses[t]); + //AddLog(LOG_LEVEL_INFO); if (ads1115_found[t]) { Ads1115GetValues(ads1115_addresses[t]); if (json) { diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index 0dbaf7141..a31debac6 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -65,8 +65,7 @@ void Tsl2561Detect(void) { if (tsl2561_type) { return; } - if (I2cDevice(0x29) || I2cDevice(0x39) || I2cDevice(0x49)) { - Tsl.begin(); + if ((I2cDevice(0x29) || I2cDevice(0x39) || I2cDevice(0x49))&&Tsl.begin()) { if (Tsl.on()) { tsl2561_type = 1; snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, tsl2561_types, Tsl.address()); From 58c7fac140ccdee8a53acb06a7a017ea3ca2ab1e Mon Sep 17 00:00:00 2001 From: Kevin Baluha Date: Thu, 7 Feb 2019 03:40:44 -0700 Subject: [PATCH 0966/2222] check id reg --- sonoff/xsns_16_tsl2561.ino | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index a31debac6..fecedd26e 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -64,11 +64,14 @@ bool Tsl2561Read(void) void Tsl2561Detect(void) { if (tsl2561_type) { return; } + uint8_t id; - if ((I2cDevice(0x29) || I2cDevice(0x39) || I2cDevice(0x49))&&Tsl.begin()) { + if (I2cDevice(0x29) || I2cDevice(0x39) || I2cDevice(0x49)) { + if (!Tsl.id(&id)) return; + Tsl.begin(); if (Tsl.on()) { tsl2561_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, tsl2561_types, Tsl.address()); + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, tsl2561_types, Tsl.address(), id); AddLog(LOG_LEVEL_DEBUG); } } From da3f4bcab7fea864d2f34741e7244dd9ba888725 Mon Sep 17 00:00:00 2001 From: Kevin Baluha Date: Thu, 7 Feb 2019 03:54:56 -0700 Subject: [PATCH 0967/2222] add a check for TLS2561 to prevent false positives --- sonoff/xsns_16_tsl2561.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index fecedd26e..f7777cf18 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -67,7 +67,7 @@ void Tsl2561Detect(void) uint8_t id; if (I2cDevice(0x29) || I2cDevice(0x39) || I2cDevice(0x49)) { - if (!Tsl.id(&id)) return; + if (!Tsl.id(id)) return; Tsl.begin(); if (Tsl.on()) { tsl2561_type = 1; From fd9f66ed6e04464d6bc66c8579e1716ff600ef4e Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Thu, 7 Feb 2019 19:09:49 +0200 Subject: [PATCH 0968/2222] ADS1115: Housekeeping --- sonoff/xsns_12_ads1115.ino | 73 ++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index fa321a85c..51cbb6c43 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -161,64 +161,61 @@ int16_t Ads1115GetConversion(uint8_t channel) void Ads1115Detect(void) { uint16_t buffer; - uint16_t conf_buffer; - - //if (ads1115_type) { - //return; - //} - for (uint8_t i = 0; i < sizeof(ads1115_addresses); i++) { - ads1115_address = ads1115_addresses[i]; - if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT) && - I2cValidRead16(&conf_buffer, ads1115_address, ADS1115_REG_POINTER_CONFIG)) { - - Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); - ads1115_type = 1; - ads1115_found[i] = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); - AddLog(LOG_LEVEL_DEBUG); - //break; + if (!ads1115_found[i]) { + ads1115_address = ads1115_addresses[i]; + if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT) && + I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONFIG)) { + Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); + ads1115_type = 1; + ads1115_found[i] = 1; + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); + AddLog(LOG_LEVEL_DEBUG); + } } } } -void Ads1115GetValues(uint8_t address) { - uint8_t old_address = ads1115_address; - ads1115_address = address; - for (uint8_t i = 0; i < 4; i++) { - ads1115_values[i] = Ads1115GetConversion(i); - //snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x (%i) = %i", address, i, ads1115_values[i] ); - //AddLog(LOG_LEVEL_INFO); - } - ads1115_address = old_address; +void Ads1115GetValues(uint8_t address) +{ + uint8_t old_address = ads1115_address; + ads1115_address = address; + for (uint8_t i = 0; i < 4; i++) { + ads1115_values[i] = Ads1115GetConversion(i); + //snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x (%i) = %i", address, i, ads1115_values[i] ); + //AddLog(LOG_LEVEL_INFO); + } + ads1115_address = old_address; } -void Ads1115toJSON(char *comma_j) { +void Ads1115toJSON(char *comma_j) +{ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s{"), mqtt_data,comma_j); char *comma = (char*)""; for (uint8_t i = 0; i < 4; i++) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, comma, i, ads1115_values[i]); comma = (char*)","; - } + } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); } -void Ads1115toString(uint8_t address) { +void Ads1115toString(uint8_t address) +{ char label[15]; snprintf_P(label, sizeof(label), "ADS1115(%02x)", address); for (uint8_t i = 0; i < 4; i++) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, label, i, ads1115_values[i]); - } + } } void Ads1115Show(bool json) { - if (!ads1115_type) - return; + if (!ads1115_type) { return; } - if (json) + if (json) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":["), mqtt_data); + } char *comma = (char*)""; @@ -230,18 +227,18 @@ void Ads1115Show(bool json) if (json) { Ads1115toJSON(comma); comma = (char*)","; - } + } #ifdef USE_WEBSERVER else { Ads1115toString(ads1115_addresses[t]); - } + } #endif // USE_WEBSERVER - } } + } - if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]"), mqtt_data); - } + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]"), mqtt_data); + } } /*********************************************************************************************\ From afe797fd6ec9679c157ea2073f3d310e6a905234 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 7 Feb 2019 20:41:38 +0100 Subject: [PATCH 0969/2222] Improve weblog robustness --- sonoff/xdrv_01_webserver.ino | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 51498abb4..316553130 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -129,11 +129,11 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "x.onreadystatechange=function(){" "if(x.readyState==4&&x.status==200){" "var z,d;" - "d=x.responseXML;" - "id=d.getElementsByTagName('i')[0].childNodes[0].nodeValue;" - "if(d.getElementsByTagName('j')[0].childNodes[0].nodeValue==0){t.value='';}" - "z=d.getElementsByTagName('l')[0].childNodes;" - "if(z.length>0){t.value+=decodeURIComponent(z[0].nodeValue);}" + "d=x.responseText.split(/\1/);" + "id=d.shift();" + "if(d.shift()==0){t.value='';}" + "z=d.shift();" + "if(z.length>0){t.value+=z;}" "t.scrollTop=99999;" "sn=t.scrollTop;" "}" @@ -1813,7 +1813,9 @@ void HandleAjaxConsoleRefresh(void) if (strlen(svalue)) { counter = atoi(svalue); } bool last_reset_web_log_flag = reset_web_log_flag; - String message = F("}9"); // Cannot load mqtt_data here as <> will be encoded by replacements below + // mqtt_data used as scratch space + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%d\1%d\1"), web_log_index, last_reset_web_log_flag); + String message = mqtt_data; if (!reset_web_log_flag) { counter = 0; reset_web_log_flag = true; @@ -1834,20 +1836,13 @@ void HandleAjaxConsoleRefresh(void) cflg = true; } strlcpy(mqtt_data, tmp, len); - message += mqtt_data; + message += mqtt_data; // mqtt_data used as scratch space } counter++; - if (!counter) { counter++; } // Skip 0 as it is not allowed + if (!counter) { counter++; } // Skip log index 0 as it is not allowed } while (counter != web_log_index); - // XML encoding to fix blank console log in concert with javascript decodeURIComponent - message.replace(F("%"), F("%25")); // Needs to be done first as otherwise the % in %26 will also be converted - message.replace(F("&"), F("%26")); - message.replace(F("<"), F("%3C")); - message.replace(F(">"), F("%3E")); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%d%d"), web_log_index, last_reset_web_log_flag); - message.replace(F("}9"), mqtt_data); // Save to load here - message += F(""); + message += F("\1"); WebServer->send(200, FPSTR(HDR_CTYPE_XML), message); } From 6f4e658f03541f579e2a0db6d623d1e2a5597b22 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 7 Feb 2019 20:54:30 +0100 Subject: [PATCH 0970/2222] Increase length of name in HA AD msg. --- sonoff/xdrv_12_home_assistant.ino | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 155ee05a2..b6e6af299 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -173,8 +173,11 @@ int try_snprintf_P(char *s, size_t n, const char *format, ... ) int len = vsnprintf_P(NULL, 0, format, args); if (len >= n) { snprintf_P(log_data, sizeof(log_data), - PSTR("ERROR: MQTT discovery failed due to too long topic or friendly name. \ - Please shorten topic and friendly name.")); + PSTR("ERROR: MQTT discovery failed due to too long topic or friendly name. " + "Please shorten topic and friendly name. Failed to format(%u/%u):"), len, n); + AddLog(LOG_LEVEL_ERROR); + va_start(args, format); + vsnprintf_P(log_data, sizeof(log_data), format, args); AddLog(LOG_LEVEL_ERROR); } else { va_start(args, format); @@ -210,7 +213,7 @@ void HAssAnnounceRelayLight(void) (is_topic_light) ? "light" : "switch", unique_id); if (Settings.flag.hass_discovery && (i <= devices_present)) { - char name[33]; + char name[33+2]; // friendlyname(33) + " " + index char value_template[33]; char prefix[TOPSZ]; char *command_topic = stemp1; @@ -294,7 +297,7 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); if (Settings.flag.hass_discovery && present) { - char name[33]; + char name[33+6]; // friendlyname(33) + " " + "BTN" + " " + index char value_template[33]; char prefix[TOPSZ]; char *state_topic = stemp1; @@ -401,7 +404,7 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); if (Settings.flag.hass_discovery) { - char name[33]; + char name[33+42]; // friendlyname(33) + " " + sensorname(20?) + " " + sensortype(20?) char prefix[TOPSZ]; char *state_topic = stemp1; char *availability_topic = stemp2; @@ -512,7 +515,7 @@ void HAssAnnounceStatusSensor(void) snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); if (Settings.flag.hass_discovery) { - char name[33]; + char name[33+7]; // friendlyname(33) + " " + "status" char prefix[TOPSZ]; char *state_topic = stemp1; char *availability_topic = stemp2; From b76b615a6e3435517a10ea64ebc91605db931152 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 8 Feb 2019 00:41:46 +0200 Subject: [PATCH 0971/2222] PN532: Deprecate I2C support --- sonoff/my_user_config.h | 3 - sonoff/xsns_40_pn532.ino | 0 sonoff/xsns_40_pn532_i2c.ino | 606 ----------------------------------- 3 files changed, 609 deletions(-) create mode 100644 sonoff/xsns_40_pn532.ino delete mode 100644 sonoff/xsns_40_pn532_i2c.ino diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index c9c6505d5..f9aaf25d7 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -326,9 +326,6 @@ // #define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) // #define USE_RTC_ADDR 0x68 // Default I2C address 0x68 // #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) -// #define USE_PN532_I2C // Enable PN532 - Near Field Communication (NFC) controller (+1k7 code, 164 bytes of mem) -// #define USE_PN532_DATA_FUNCTION // Enable PN532 DATA Usage using Sensor15 command (+1k6 code, 316 bytes of mem) -// #define USE_PN532_CAUSE_EVENTS // Enable PN532 driver to cause event's on card read in addition to immediate telemetry (+64 bytes code, 48 bytes mem) // #define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) diff --git a/sonoff/xsns_40_pn532.ino b/sonoff/xsns_40_pn532.ino new file mode 100644 index 000000000..e69de29bb diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino deleted file mode 100644 index 640e21c6e..000000000 --- a/sonoff/xsns_40_pn532_i2c.ino +++ /dev/null @@ -1,606 +0,0 @@ -/* - xsns_40_pn532.ino - Support for PN532 (I2C) NFC Tag Reader - - Copyright (C) 2019 Andre Thomas 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 - 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_PN532_I2C - -/*********************************************************************************************\ - * PN532 - Near Field Communication (NFC) controller - * - * Datasheet at https://www.nxp.com/docs/en/nxp/data-sheets/PN532_C1.pdf - * - * I2C Address: 0x24 -\*********************************************************************************************/ - -#define XSNS_40 40 - -#define PN532_I2C_ADDRESS 0x24 - -#define PN532_COMMAND_GETFIRMWAREVERSION 0x02 -#define PN532_COMMAND_SAMCONFIGURATION 0x14 -#define PN532_COMMAND_INDATAEXCHANGE 0x40 -#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A - -#define MIFARE_CMD_READ 0x30 -#define MIFARE_CMD_AUTH_A 0x60 -#define MIFARE_CMD_AUTH_B 0x61 -#define MIFARE_CMD_WRITE 0xA0 - -#define PN532_PREAMBLE 0x00 -#define PN532_STARTCODE1 0x00 -#define PN532_STARTCODE2 0xFF -#define PN532_POSTAMBLE 0x00 - -#define PN532_HOSTTOPN532 0xD4 -#define PN532_PN532TOHOST 0xD5 - -#define PN532_INVALID_ACK -1 -#define PN532_TIMEOUT -2 -#define PN532_INVALID_FRAME -3 -#define PN532_NO_SPACE -4 - -#define PN532_MIFARE_ISO14443A 0x00 - -uint8_t pn532_i2c_detected = 0; -uint8_t pn532_i2c_packetbuffer[64]; -uint8_t pn532_i2c_scan_defer_report = 0; // If a valid card was found we will not scan for one again in the same two seconds so we set this to 19 if a card was found -uint8_t pn532_i2c_command = 0; - -uint8_t pn532_i2c_disable = 0; - -#ifdef USE_PN532_DATA_FUNCTION -uint8_t pn532_i2c_function = 0; -uint8_t pn532_i2c_newdata[16]; -uint8_t pn532_i2c_newdata_len = 0; -#endif // USE_PN532_DATA_FUNCTION - -const uint8_t PROGMEM pn532_global_timeout = 10; - -int16_t PN532_getResponseLength(uint8_t buf[], uint8_t len) { - const uint8_t PN532_NACK[] = {0, 0, 0xFF, 0xFF, 0, 0}; - uint8_t time = 0; - do { - if (Wire.requestFrom(PN532_I2C_ADDRESS, 6)) { - if (Wire.read() & 1) { // check first byte --- status - break; // PN532 is ready - } - } - delay(1); - time++; - if (time > pn532_global_timeout) { - return -1; - } - } while (1); - - if ((0x00 != Wire.read()) || (0x00 != Wire.read()) || (0xFF != Wire.read())) { // PREAMBLE || STARTCODE1 || STARTCODE2 - return PN532_INVALID_FRAME; - } - - uint8_t length = Wire.read(); - - // request for last respond msg again - Wire.beginTransmission(PN532_I2C_ADDRESS); - for (uint16_t i = 0;i < sizeof(PN532_NACK); ++i) { - Wire.write(PN532_NACK[i]); - } - Wire.endTransmission(); - return length; -} - - -int16_t PN532_readResponse(uint8_t buf[], uint8_t len) -{ - uint8_t time = 0; - uint8_t length; - - length = PN532_getResponseLength(buf, len); - - // [RDY] 00 00 FF LEN LCS (TFI PD0 ... PDn) DCS 00 - - do { - if (Wire.requestFrom(PN532_I2C_ADDRESS, 6 + length + 2)) { - if (Wire.read() & 1) { // check first byte --- status - break; // PN532 is ready - } - } - delay(1); - time++; - if (time > pn532_global_timeout) { - return -1; - } - } while (1); - - if ((0x00 != Wire.read()) || (0x00 != Wire.read()) || (0xFF != Wire.read())) { // PREAMBLE || STARTCODE1 || STARTCODE2 - return PN532_INVALID_FRAME; - } - - length = Wire.read(); - - if (0 != (uint8_t)(length + Wire.read())) { // checksum of length - return PN532_INVALID_FRAME; - } - - uint8_t cmd = pn532_i2c_command + 1; // response command - if ((PN532_PN532TOHOST != Wire.read()) || ((cmd) != Wire.read())) { - return PN532_INVALID_FRAME; - } - length -= 2; - if (length > len) { - return PN532_NO_SPACE; // not enough space - } - uint8_t sum = PN532_PN532TOHOST + cmd; - for (uint8_t i = 0; i < length; i++) { - buf[i] = Wire.read(); - sum += buf[i]; - } - uint8_t checksum = Wire.read(); - if (0 != (uint8_t)(sum + checksum)) { - return PN532_INVALID_FRAME; - } - Wire.read(); // POSTAMBLE - return length; -} - - -int8_t PN532_readAckFrame(void) -{ - const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; - uint8_t ackBuf[sizeof(PN532_ACK)]; - - uint8_t time = 0; - - do { - if (Wire.requestFrom(PN532_I2C_ADDRESS, sizeof(PN532_ACK) + 1)) { - if (Wire.read() & 1) { // check first byte --- status - break; // PN532 is ready - } - } - delay(1); - time++; - if (time > pn532_global_timeout) { // We time out after 10ms - return PN532_TIMEOUT; - } - } while (1); - - for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) { - ackBuf[i] = Wire.read(); - } - - if (memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK))) { - return PN532_INVALID_ACK; - } - - return 0; -} - -int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen) -{ - pn532_i2c_command = header[0]; - Wire.beginTransmission(PN532_I2C_ADDRESS); - Wire.write(PN532_PREAMBLE); - Wire.write(PN532_STARTCODE1); - Wire.write(PN532_STARTCODE2); - uint8_t length = hlen + 1; // TFI + DATA - Wire.write(length); - Wire.write(~length + 1); // checksum of length - Wire.write(PN532_HOSTTOPN532); - uint8_t sum = PN532_HOSTTOPN532; // Sum of TFI + DATA - for (uint8_t i = 0; i < hlen; i++) { - if (Wire.write(header[i])) { - sum += header[i]; - } else { - return PN532_INVALID_FRAME; - } - } - uint8_t checksum = ~sum + 1; // Checksum of TFI + DATA - Wire.write(checksum); - Wire.write(PN532_POSTAMBLE); - Wire.endTransmission(); - return PN532_readAckFrame(); -} - -uint32_t PN532_getFirmwareVersion(void) -{ - uint32_t response; - pn532_i2c_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION; - if (PN532_writeCommand(pn532_i2c_packetbuffer, 1)) { - return 0; - } - int16_t status = PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)); - if (0 > status) { - return 0; - } - response = pn532_i2c_packetbuffer[0]; - response <<= 8; - response |= pn532_i2c_packetbuffer[1]; - response <<= 8; - response |= pn532_i2c_packetbuffer[2]; - response <<= 8; - response |= pn532_i2c_packetbuffer[3]; - return response; -} - -bool PN532_SAMConfig(void) -{ - pn532_i2c_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; - pn532_i2c_packetbuffer[1] = 0x01; // normal mode; - pn532_i2c_packetbuffer[2] = 0x01; // timeout 50ms * 1 = 50ms - pn532_i2c_packetbuffer[3] = 0x00; // Disable IRQ pin - - if (PN532_writeCommand(pn532_i2c_packetbuffer, 4)) - return false; - - return (0 < PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer))); -} - -void PN532_Detect(void) -{ - if ((pn532_i2c_detected) || (pn532_i2c_disable)) { return; } - - Wire.setClockStretchLimit(1000); // Enable 1ms clock stretch as per datasheet Table 12.25 (Timing for the I2C interface) - - uint32_t ver = PN532_getFirmwareVersion(); - if (ver) { - pn532_i2c_detected = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "PN532 NFC Reader (V%u.%u)", PN532_I2C_ADDRESS); - snprintf_P(log_data, sizeof(log_data), log_data, (ver>>16) & 0xFF, (ver>>8) & 0xFF); - AddLog(LOG_LEVEL_DEBUG); - PN532_SAMConfig(); - } -} - -bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength) -{ - pn532_i2c_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; - pn532_i2c_packetbuffer[1] = 1; - pn532_i2c_packetbuffer[2] = cardbaudrate; - - if (PN532_writeCommand(pn532_i2c_packetbuffer, 3)) { - return false; // command failed - } - - if (PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)) < 0) { // No data packet so no tag was found - Wire.beginTransmission(PN532_I2C_ADDRESS); - Wire.endTransmission(); - return false; - } - - if (pn532_i2c_packetbuffer[0] != 1) { return false; } // Not a valid tag - - *uidLength = pn532_i2c_packetbuffer[5]; - for (uint8_t i = 0;i < pn532_i2c_packetbuffer[5]; i++) { - uid[i] = pn532_i2c_packetbuffer[6 + i]; - } - return true; -} - -#ifdef USE_PN532_DATA_FUNCTION - -uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData) -{ - uint8_t i; - uint8_t _key[6]; - uint8_t _uid[7]; - uint8_t _uidLen; - - // Hang on to the key and uid data - memcpy (_key, keyData, 6); - memcpy (_uid, uid, uidLen); - _uidLen = uidLen; - - // Prepare the authentication command // - pn532_i2c_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */ - pn532_i2c_packetbuffer[1] = 1; /* Max card numbers */ - pn532_i2c_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; - pn532_i2c_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */ - memcpy (&pn532_i2c_packetbuffer[4], _key, 6); - for (i = 0; i < _uidLen; i++) { - pn532_i2c_packetbuffer[10 + i] = _uid[i]; /* 4 bytes card ID */ - } - - if (PN532_writeCommand(pn532_i2c_packetbuffer, 10 + _uidLen)) - return 0; - - // Read the response packet - PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)); - - // Check if the response is valid and we are authenticated??? - // for an auth success it should be bytes 5-7: 0xD5 0x41 0x00 - // Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good - if (pn532_i2c_packetbuffer[0] != 0x00) { - // Authentification failed - return 0; - } - - return 1; -} - -uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data) -{ - /* Prepare the command */ - pn532_i2c_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; - pn532_i2c_packetbuffer[1] = 1; /* Card number */ - pn532_i2c_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ - pn532_i2c_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ - - /* Send the command */ - if (PN532_writeCommand(pn532_i2c_packetbuffer, 4)) { - return 0; - } - - /* Read the response packet */ - PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)); - - /* If byte 8 isn't 0x00 we probably have an error */ - if (pn532_i2c_packetbuffer[0] != 0x00) { - return 0; - } - - /* Copy the 16 data bytes to the output buffer */ - /* Block content starts at byte 9 of a valid response */ - memcpy (data, &pn532_i2c_packetbuffer[1], 16); - - return 1; -} - -uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data) -{ - /* Prepare the first command */ - pn532_i2c_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; - pn532_i2c_packetbuffer[1] = 1; /* Card number */ - pn532_i2c_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */ - pn532_i2c_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ - memcpy(&pn532_i2c_packetbuffer[4], data, 16); /* Data Payload */ - - /* Send the command */ - if (PN532_writeCommand(pn532_i2c_packetbuffer, 20)) { - return 0; - } - - /* Read the response packet */ - return (0 < PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer))); -} - -#endif // USE_PN532_DATA_FUNCTION - -void PN532_ScanForTag(void) -{ - if (pn532_i2c_disable) { return; } - uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; - uint8_t uid_len = 0; - uint8_t card_data[16]; - bool erase_success = false; - bool set_success = false; - if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) { - if (pn532_i2c_scan_defer_report > 0) { - pn532_i2c_scan_defer_report--; - } else { - char uids[15]; - -#ifdef USE_PN532_DATA_FUNCTION - char card_datas[34]; -#endif // USE_PN532_DATA_FUNCTION - - sprintf(uids,""); - for (uint8_t i = 0;i < uid_len;i++) { - sprintf(uids,"%s%02X",uids,uid[i]); - } - -#ifdef USE_PN532_DATA_FUNCTION - if (uid_len == 4) { // Lets try to read block 0 of the mifare classic card for more information - uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) { - if (mifareclassic_ReadDataBlock(1, card_data)) { -#ifdef USE_PN532_DATA_RAW - memcpy(&card_datas,&card_data,sizeof(card_data)); -#else - for (uint8_t i = 0;i < sizeof(card_data);i++) { - if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) { - card_datas[i] = char(card_data[i]); - } else { - card_datas[i] = '\0'; - } - } -#endif // USE_PN532_DATA_RAW - } - if (pn532_i2c_function == 1) { // erase block 1 of card - for (uint8_t i = 0;i<16;i++) { - card_data[i] = 0x00; - } - if (mifareclassic_WriteDataBlock(1, card_data)) { - erase_success = true; - snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Erase success"); - AddLog(LOG_LEVEL_INFO); - memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string - } - } - if (pn532_i2c_function == 2) { -#ifdef USE_PN532_DATA_RAW - memcpy(&card_data,&pn532_i2c_newdata,sizeof(card_data)); - if (mifareclassic_WriteDataBlock(1, card_data)) { - set_success = true; - snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful"); - AddLog(LOG_LEVEL_INFO); - memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string - } -#else - bool IsAlphaNumeric = true; - for (uint8_t i = 0;i < pn532_i2c_newdata_len;i++) { - if ((!isalpha(pn532_i2c_newdata[i])) && (!isdigit(pn532_i2c_newdata[i]))) { - IsAlphaNumeric = false; - } - } - if (IsAlphaNumeric) { - memcpy(&card_data,&pn532_i2c_newdata,pn532_i2c_newdata_len); - card_data[pn532_i2c_newdata_len] = '\0'; // Enforce null termination - if (mifareclassic_WriteDataBlock(1, card_data)) { - set_success = true; - snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful"); - AddLog(LOG_LEVEL_INFO); - memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string - } - } else { - snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data must be alphanumeric"); - AddLog(LOG_LEVEL_INFO); - } -#endif // USE_PN532_DATA_RAW - } - } else { - sprintf(card_datas,"AUTHFAIL"); - } - } - switch (pn532_i2c_function) { - case 0x01: - if (!erase_success) { - snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Erase fail - exiting erase mode"); - AddLog(LOG_LEVEL_INFO); - } - break; - case 0x02: - if (!set_success) { - snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Write failed - exiting set mode"); - AddLog(LOG_LEVEL_INFO); - } - default: - break; - } - pn532_i2c_function = 0; -#endif // USE_PN532_DATA_FUNCTION - - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - -#ifdef USE_PN532_DATA_FUNCTION - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), mqtt_data, uids, card_datas); -#else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids); -#endif // USE_PN532_DATA_FUNCTION - - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - -#ifdef USE_PN532_CAUSE_EVENTS - - char command[71]; -#ifdef USE_PN532_DATA_FUNCTION - sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas); -#else - sprintf(command,"event PN532_UID=%s",uids); -#endif // USE_PN532_DATA_FUNCTION - ExecuteCommand(command, SRC_RULE); -#endif // USE_PN532_CAUSE_EVENTS - - pn532_i2c_scan_defer_report = 7; // Ignore tags found for two seconds - } - } else { - if (pn532_i2c_scan_defer_report > 0) { pn532_i2c_scan_defer_report--; } - } -} - -#ifdef USE_PN532_DATA_FUNCTION - -bool PN532_Command(void) -{ - bool serviced = true; - uint8_t paramcount = 0; - if (XdrvMailbox.data_len > 0) { - paramcount=1; - } else { - serviced = false; - return serviced; - } - char sub_string[XdrvMailbox.data_len]; - char sub_string_tmp[XdrvMailbox.data_len]; - for (uint8_t ca=0;ca 1) { - if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') { - serviced = false; - return serviced; - } - sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2)); - pn532_i2c_newdata_len = strlen(sub_string_tmp); - if (pn532_i2c_newdata_len > 15) { pn532_i2c_newdata_len = 15; } - memcpy(&pn532_i2c_newdata,&sub_string_tmp,pn532_i2c_newdata_len); - pn532_i2c_newdata[pn532_i2c_newdata_len] = 0x00; // Null terminate the string - pn532_i2c_function = 2; - snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Next scanned tag data block 1 will be set to '%s'",pn532_i2c_newdata); - AddLog(LOG_LEVEL_INFO); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"S\"\"}}"), mqtt_data); - return serviced; - } - } -} - -#endif // USE_PN532_DATA_FUNCTION - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xsns40(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (pn532_i2c_detected) { - PN532_ScanForTag(); - } - break; - case FUNC_EVERY_SECOND: - PN532_Detect(); - break; - -#ifdef USE_PN532_DATA_FUNCTION - case FUNC_COMMAND: - if (XSNS_40 == XdrvMailbox.index) { - result = PN532_Command(); - } - break; -#endif // USE_PN532_DATA_FUNCTION - - case FUNC_SAVE_BEFORE_RESTART: - if (!pn532_i2c_disable) { - pn532_i2c_disable = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "PN532 NFC Reader - Disabling for reboot", PN532_I2C_ADDRESS); - AddLog(LOG_LEVEL_DEBUG); - } - break; - default: - break; - } - } - return result; -} - -#endif // USE_PN532_I2C -#endif // USE_I2C From 707b51f292c08ef94ad9aa7908ead56e66d71ab9 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 8 Feb 2019 01:06:54 +0200 Subject: [PATCH 0972/2222] PN532: Implement HSU (Serial) --- sonoff/language/bg-BG.h | 2 + sonoff/language/cs-CZ.h | 2 + sonoff/language/de-DE.h | 2 + sonoff/language/el-GR.h | 2 + sonoff/language/en-GB.h | 2 + sonoff/language/es-AR.h | 2 + sonoff/language/fr-FR.h | 2 + sonoff/language/he-HE.h | 2 + sonoff/language/hu-HU.h | 2 + sonoff/language/it-IT.h | 2 + sonoff/language/nl-NL.h | 2 + sonoff/language/pl-PL.h | 2 + sonoff/language/pt-BR.h | 2 + sonoff/language/pt-PT.h | 2 + sonoff/language/ru-RU.h | 2 + sonoff/language/sk-SK.h | 2 + sonoff/language/sv-SE.h | 2 + sonoff/language/tr-TR.h | 2 + sonoff/language/uk-UK.h | 2 + sonoff/language/zh-CN.h | 2 + sonoff/language/zh-TW.h | 2 + sonoff/my_user_config.h | 3 + sonoff/sonoff_template.h | 7 + sonoff/xsns_40_pn532.ino | 615 +++++++++++++++++++++++++++++++++++++++ 24 files changed, 667 insertions(+) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index a490f8e6e..dec628ae1 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index b16ccf37f..d6c73baa9 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 8ad86d173..a9d85ba3c 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index f5f281ca4..b6b9dfa9d 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 7c03e76f4..0a85d6a8b 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 73ec924c8..4503c4e57 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 09b7ef831..89a863810 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 64e6aeae3..7e2deacab 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 6a6a21020..a7db58513 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 145b6064c..a5ffca743 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index cef56fb2e..773442714 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index dba0726e4..63a15c5a5 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index f8d037e83..1b0c34b16 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index aeed10329..b969449d2 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index aaa457ec7..b2ad0a1d8 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index e1ecafd63..49430c31e 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 5a7934d71..61ab33b57 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 344e65b58..cfad17ca0 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index be8f0530a..ce72f093f 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index fbdc82207..a022f7939 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 008c33a10..06274c41b 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -553,6 +553,8 @@ #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" #define D_SENSOR_CSE7766_TX "CSE7766 Tx" #define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index f9aaf25d7..0d50b580b 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -375,6 +375,9 @@ #define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code) +//#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+3k7 code, 280 bytes mem) +// #define USE_PN532_DATA_FUNCTION // Add sensor40 command support for erase, setting data block content (+1k7 code, 356 bytes mem) +// #define USE_PN532_DATA_RAW // Allow DATA block to be used by non-alpha-numberic data (-0k2 code, -32 bytes ram) // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 1e5e1a573..ff2ba6401 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -162,6 +162,8 @@ enum UserSelectablePins { GPIO_MCP39F5_TX, // MCP39F501 Serial interface (Shelly2) GPIO_MCP39F5_RX, // MCP39F501 Serial interface (Shelly2) GPIO_MCP39F5_RST, // MCP39F501 Reset (Shelly2) + GPIO_PN532_RXD, // PN532 NFC Serial Rx + GPIO_PN532_TXD, // PN532 NFC Serial Tx GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -227,6 +229,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in|" D_SENSOR_NRG_SEL "|" D_SENSOR_NRG_SEL "i|" D_SENSOR_NRG_CF1 "|" D_SENSOR_HLW_CF "|" D_SENSOR_HJL_CF "|" D_SENSOR_MCP39F5_TX "|" D_SENSOR_MCP39F5_RX "|" D_SENSOR_MCP39F5_RST + D_SENSOR_PN532_TX "|" D_SENSOR_PN532_RX ; /********************************************************************************************/ @@ -546,6 +549,10 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface #endif +#ifdef USE_PN532_HSU + GPIO_PN532_RXD, // PN532 HSU Rx + GPIO_PN532_TXD, // PN532 HSU Tx +#endif }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { diff --git a/sonoff/xsns_40_pn532.ino b/sonoff/xsns_40_pn532.ino index e69de29bb..af00720b2 100644 --- a/sonoff/xsns_40_pn532.ino +++ b/sonoff/xsns_40_pn532.ino @@ -0,0 +1,615 @@ +/* + xsns_40_pn532.ino - Support for PN532 (HSU) NFC Tag Reader + + Copyright (C) 2019 Andre Thomas 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 + 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_PN532_HSU + +#define XSNS_40 40 + +#include + +TasmotaSerial *PN532_Serial; + +#define PN532_INVALID_ACK -1 +#define PN532_TIMEOUT -2 +#define PN532_INVALID_FRAME -3 +#define PN532_NO_SPACE -4 + +#define PN532_PREAMBLE 0x00 +#define PN532_STARTCODE1 0x00 +#define PN532_STARTCODE2 0xFF +#define PN532_POSTAMBLE 0x00 + +#define PN532_HOSTTOPN532 0xD4 +#define PN532_PN532TOHOST 0xD5 + +#define PN532_ACK_WAIT_TIME 0x0A + +#define PN532_COMMAND_GETFIRMWAREVERSION 0x02 +#define PN532_COMMAND_SAMCONFIGURATION 0x14 +#define PN532_COMMAND_RFCONFIGURATION 0x32 +#define PN532_COMMAND_INDATAEXCHANGE 0x40 +#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A + +#define PN532_MIFARE_ISO14443A 0x00 +#define MIFARE_CMD_READ 0x30 +#define MIFARE_CMD_AUTH_A 0x60 +#define MIFARE_CMD_AUTH_B 0x61 +#define MIFARE_CMD_WRITE 0xA0 + +uint8_t pn532_model = 0; // Used to maintain detection flag +uint8_t pn532_command = 0; // Used to carry command code between functions +uint8_t pn532_scantimer = 0; // Used to prevent multiple successful reads within 2 second window + +uint8_t pn532_packetbuffer[64]; // Global buffer used to store packet + +#ifdef USE_PN532_DATA_FUNCTION +uint8_t pn532_function = 0; +uint8_t pn532_newdata[16]; +uint8_t pn532_newdata_len = 0; +#endif // USE_PN532_DATA_FUNCTION + +void PN532_Init(void) +{ + if ((pin[GPIO_PN532_RXD] < 99) && (pin[GPIO_PN532_TXD] < 99)) { + PN532_Serial = new TasmotaSerial(pin[GPIO_PN532_RXD], pin[GPIO_PN532_TXD], 1); + if (PN532_Serial->begin(115200)) { + if (PN532_Serial->hardwareSerial()) { ClaimSerial(); } + PN532_wakeup(); + uint32_t ver = PN532_getFirmwareVersion(); + if (ver) { + PN532_setPassiveActivationRetries(0xFF); + PN532_SAMConfig(); + pn532_model = 1; + snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC Reader detected (V%u.%u)",(ver>>16) & 0xFF, (ver>>8) & 0xFF); + AddLog(LOG_LEVEL_INFO); + } + } + } +} + +int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout) +{ + int read_bytes = 0; + int ret; + unsigned long start_millis; + while (read_bytes < len) { + start_millis = millis(); + do { + ret = PN532_Serial->read(); + if (ret >= 0) { + break; + } + } while((timeout == 0) || ((millis()- start_millis ) < timeout)); + + if (ret < 0) { + if (read_bytes) { + return read_bytes; + } else { + return PN532_TIMEOUT; + } + } + buf[read_bytes] = (uint8_t)ret; + read_bytes++; + } + return read_bytes; +} + +int8_t PN532_readAckFrame(void) +{ + const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; + uint8_t ackBuf[sizeof(PN532_ACK)]; + + if (PN532_receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0) { + return PN532_TIMEOUT; + } + + if (memcmp(&ackBuf, &PN532_ACK, sizeof(PN532_ACK))) { + return PN532_INVALID_ACK; + } + return 0; +} + +int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) +{ + // Clear the serial buffer just in case + while(PN532_Serial->available()) { PN532_Serial->read(); } + + pn532_command = header[0]; + PN532_Serial->write((uint8_t)PN532_PREAMBLE); + PN532_Serial->write((uint8_t)PN532_STARTCODE1); + PN532_Serial->write(PN532_STARTCODE2); + + uint8_t length = hlen + blen + 1; // length of data field: TFI + DATA + PN532_Serial->write(length); + PN532_Serial->write(~length + 1); // checksum of length + + PN532_Serial->write(PN532_HOSTTOPN532); + uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA + + PN532_Serial->write(header, hlen); + for (uint8_t i = 0; i < hlen; i++) { + sum += header[i]; + } + + PN532_Serial->write(body, blen); + for (uint8_t i = 0; i < blen; i++) { + sum += body[i]; + } + + uint8_t checksum = ~sum + 1; // checksum of TFI + DATA + PN532_Serial->write(checksum); + PN532_Serial->write((uint8_t)PN532_POSTAMBLE); + + return PN532_readAckFrame(); +} + +int16_t PN532_readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 50) +{ + uint8_t tmp[3]; + + // Read preamble and start code + if (PN532_receive(tmp, 3, timeout)<=0) { + return PN532_TIMEOUT; + } + if (0 != tmp[0] || 0!= tmp[1] || 0xFF != tmp[2]) { + return PN532_INVALID_FRAME; + } + + // Get length of data to be received + uint8_t length[2]; + if (PN532_receive(length, 2, timeout) <= 0) { + return PN532_TIMEOUT; + } + // Validate that frame is valid + if (0 != (uint8_t)(length[0] + length[1])) { + return PN532_INVALID_FRAME; + } + length[0] -= 2; + if (length[0] > len) { // If this happens, then pn532_packetbuffer is not large enough + return PN532_NO_SPACE; + } + + // Get the command byte + uint8_t cmd = pn532_command + 1; + if (PN532_receive(tmp, 2, timeout) <= 0) { // Time out while receiving + return PN532_TIMEOUT; + } + if (PN532_PN532TOHOST != tmp[0] || cmd != tmp[1]) { // Invalid frame received + return PN532_INVALID_FRAME; + } + + if (PN532_receive(buf, length[0], timeout) != length[0]) { // Timed out + return PN532_TIMEOUT; + } + + uint8_t sum = PN532_PN532TOHOST + cmd; + for (uint8_t i=0; i status) { + return 0; + } + + response = pn532_packetbuffer[0]; + response <<= 8; + response |= pn532_packetbuffer[1]; + response <<= 8; + response |= pn532_packetbuffer[2]; + response <<= 8; + response |= pn532_packetbuffer[3]; + + return response; +} + +void PN532_wakeup(void) +{ + uint8_t wakeup[5] = {0x55, 0x55, 0, 0, 0 }; + PN532_Serial->write(wakeup,sizeof(wakeup)); + + // Flush the serial buffer just in case there's garbage in there + while(PN532_Serial->available()) { PN532_Serial->read(); } +} + +bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 50) +{ + pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; + pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later) + pn532_packetbuffer[2] = cardbaudrate; + if (PN532_writeCommand(pn532_packetbuffer, 3)) { + return 0x0; // command failed + } + // read data packet + if (PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) { + return 0x0; + } + + /* Check some basic stuff + b0 Tags Found + b1 Tag Number (only one used in this example) + b2..3 SENS_RES + b4 SEL_RES + b5 NFCID Length + b6..NFCIDLen NFCID + */ + + if (pn532_packetbuffer[0] != 1) { + return 0; + } + + uint16_t sens_res = pn532_packetbuffer[2]; + sens_res <<= 8; + sens_res |= pn532_packetbuffer[3]; + + /* Card appears to be Mifare Classic */ + *uidLength = pn532_packetbuffer[5]; + + for (uint8_t i = 0; i < pn532_packetbuffer[5]; i++) { + uid[i] = pn532_packetbuffer[6 + i]; + } + + return 1; +} + +bool PN532_setPassiveActivationRetries(uint8_t maxRetries) +{ + pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; + pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries) + pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF) + pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01) + pn532_packetbuffer[4] = maxRetries; + if (PN532_writeCommand(pn532_packetbuffer, 5)) { + return 0; // no ACK + } + return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +bool PN532_SAMConfig(void) +{ + pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; + pn532_packetbuffer[1] = 0x01; // normal mode + pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second + pn532_packetbuffer[3] = 0x00; // we don't need the external IRQ pin + if (PN532_writeCommand(pn532_packetbuffer, 4)) { + return false; + } + return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +#ifdef USE_PN532_DATA_FUNCTION + +uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData) +{ + uint8_t i; + uint8_t _key[6]; + uint8_t _uid[7]; + uint8_t _uidLen; + + // Hang on to the key and uid data + memcpy(&_key, keyData, 6); + memcpy(&_uid, uid, uidLen); + _uidLen = uidLen; + + // Prepare the authentication command // + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */ + pn532_packetbuffer[1] = 1; /* Max card numbers */ + pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; + pn532_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */ + memcpy(&pn532_packetbuffer[4], &_key, 6); + for (i = 0; i < _uidLen; i++) { + pn532_packetbuffer[10 + i] = _uid[i]; /* 4 bytes card ID */ + } + + if (PN532_writeCommand(pn532_packetbuffer, 10 + _uidLen)) { return 0; } + + // Read the response packet + PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + + // Check if the response is valid and we are authenticated??? + // for an auth success it should be bytes 5-7: 0xD5 0x41 0x00 + // Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good + if (pn532_packetbuffer[0] != 0x00) { + // Authentification failed + return 0; + } + + return 1; +} + +uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data) +{ + /* Prepare the command */ + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; /* Card number */ + pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */ + pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ + + /* Send the command */ + if (PN532_writeCommand(pn532_packetbuffer, 4)) { + return 0; + } + + /* Read the response packet */ + PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + + /* If byte 8 isn't 0x00 we probably have an error */ + if (pn532_packetbuffer[0] != 0x00) { + return 0; + } + + /* Copy the 16 data bytes to the output buffer */ + /* Block content starts at byte 9 of a valid response */ + memcpy (data, &pn532_packetbuffer[1], 16); + + return 1; +} + +uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data) +{ + /* Prepare the first command */ + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; /* Card number */ + pn532_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */ + pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */ + memcpy(&pn532_packetbuffer[4], data, 16); /* Data Payload */ + + /* Send the command */ + if (PN532_writeCommand(pn532_packetbuffer, 20)) { + return 0; + } + + /* Read the response packet */ + return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +#endif // USE_PN532_DATA_FUNCTION + +void PN532_ScanForTag(void) +{ + if (!pn532_model) { return; } + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; + uint8_t uid_len = 0; + uint8_t card_data[16]; + bool erase_success = false; + bool set_success = false; + if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) { + char uids[15]; + +#ifdef USE_PN532_DATA_FUNCTION + char card_datas[34]; +#endif // USE_PN532_DATA_FUNCTION + + sprintf(uids,""); + for (uint8_t i = 0;i < uid_len;i++) { + sprintf(uids,"%s%02X",uids,uid[i]); + } + +#ifdef USE_PN532_DATA_FUNCTION + if (uid_len == 4) { // Lets try to read block 1 of the mifare classic card for more information + uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) { + if (mifareclassic_ReadDataBlock(1, card_data)) { +#ifdef USE_PN532_DATA_RAW + memcpy(&card_datas,&card_data,sizeof(card_data)); +#else + for (uint8_t i = 0;i < sizeof(card_data);i++) { + if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) { + card_datas[i] = char(card_data[i]); + } else { + card_datas[i] = '\0'; + } + } +#endif // USE_PN532_DATA_RAW + } + if (pn532_function == 1) { // erase block 1 of card + for (uint8_t i = 0;i<16;i++) { + card_data[i] = 0x00; + } + if (mifareclassic_WriteDataBlock(1, card_data)) { + erase_success = true; + snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Erase success"); + AddLog(LOG_LEVEL_INFO); + memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string + } + } + if (pn532_function == 2) { +#ifdef USE_PN532_DATA_RAW + memcpy(&card_data,&pn532_newdata,sizeof(card_data)); + if (mifareclassic_WriteDataBlock(1, card_data)) { + set_success = true; + snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Data write successful"); + AddLog(LOG_LEVEL_INFO); + memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string + } +#else + bool IsAlphaNumeric = true; + for (uint8_t i = 0;i < pn532_newdata_len;i++) { + if ((!isalpha(pn532_newdata[i])) && (!isdigit(pn532_newdata[i]))) { + IsAlphaNumeric = false; + } + } + if (IsAlphaNumeric) { + memcpy(&card_data,&pn532_newdata,pn532_newdata_len); + card_data[pn532_newdata_len] = '\0'; // Enforce null termination + if (mifareclassic_WriteDataBlock(1, card_data)) { + set_success = true; + snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Data write successful"); + AddLog(LOG_LEVEL_INFO); + memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string + } + } else { + snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Data must be alphanumeric"); + AddLog(LOG_LEVEL_INFO); + } +#endif // USE_PN532_DATA_RAW + } + } else { + sprintf(card_datas,"AUTHFAIL"); + } + } + switch (pn532_function) { + case 0x01: + if (!erase_success) { + snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Erase fail - exiting erase mode"); + AddLog(LOG_LEVEL_INFO); + } + break; + case 0x02: + if (!set_success) { + snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Write failed - exiting set mode"); + AddLog(LOG_LEVEL_INFO); + } + default: + break; + } + pn532_function = 0; +#endif // USE_PN532_DATA_FUNCTION + + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + +#ifdef USE_PN532_DATA_FUNCTION + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), mqtt_data, uids, card_datas); +#else + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids); +#endif // USE_PN532_DATA_FUNCTION + + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + +#ifdef USE_PN532_CAUSE_EVENTS + + char command[71]; +#ifdef USE_PN532_DATA_FUNCTION + sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas); +#else + sprintf(command,"event PN532_UID=%s",uids); +#endif // USE_PN532_DATA_FUNCTION + ExecuteCommand(command, SRC_RULE); +#endif // USE_PN532_CAUSE_EVENTS + + pn532_scantimer = 7; // Ignore tags found for two seconds + } +} + +#ifdef USE_PN532_DATA_FUNCTION + +bool PN532_Command(void) +{ + bool serviced = true; + uint8_t paramcount = 0; + if (XdrvMailbox.data_len > 0) { + paramcount=1; + } else { + serviced = false; + return serviced; + } + char sub_string[XdrvMailbox.data_len]; + char sub_string_tmp[XdrvMailbox.data_len]; + for (uint8_t ca=0;ca 1) { + if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') { + serviced = false; + return serviced; + } + sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2)); + pn532_newdata_len = strlen(sub_string_tmp); + if (pn532_newdata_len > 15) { pn532_newdata_len = 15; } + memcpy(&pn532_newdata,&sub_string_tmp,pn532_newdata_len); + pn532_newdata[pn532_newdata_len] = 0x00; // Null terminate the string + pn532_function = 2; + snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'",pn532_newdata); + AddLog(LOG_LEVEL_INFO); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"S\"\"}}"), mqtt_data); + return serviced; + } + } +} + +#endif // USE_PN532_DATA_FUNCTION + +bool Xsns40(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_INIT: + PN532_Init(); + result = true; + break; + case FUNC_EVERY_50_MSECOND: + break; + case FUNC_EVERY_100_MSECOND: + break; + case FUNC_EVERY_250_MSECOND: + if (pn532_scantimer > 0) { + pn532_scantimer--; + } else { + PN532_ScanForTag(); + } + break; + case FUNC_EVERY_SECOND: + break; +#ifdef USE_PN532_DATA_FUNCTION + case FUNC_COMMAND: + if (XSNS_40 == XdrvMailbox.index) { + result = PN532_Command(); + } + break; +#endif + } + return result; +} + +#endif // USE_PN532_HSU From 567b12e1ce4fe31351c6ff26e2a4640e9c542b9b Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Fri, 8 Feb 2019 09:59:33 +0200 Subject: [PATCH 0973/2222] PN532: Update resource requirements in config PN532: Update resource requirements in my_user_config.h --- sonoff/my_user_config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 0d50b580b..c719f3c40 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -375,9 +375,9 @@ #define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code) -//#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+3k7 code, 280 bytes mem) -// #define USE_PN532_DATA_FUNCTION // Add sensor40 command support for erase, setting data block content (+1k7 code, 356 bytes mem) -// #define USE_PN532_DATA_RAW // Allow DATA block to be used by non-alpha-numberic data (-0k2 code, -32 bytes ram) +//#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) +// #define USE_PN532_DATA_FUNCTION // Add sensor40 command support for erase, setting data block content (+1k7 code, 388 bytes mem) +// #define USE_PN532_DATA_RAW // Allow DATA block to be used by non-alpha-numberic data (+ 80 bytes code, 48 bytes ram) // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) From e7f67f9b88578e54e75b05af05b4815e220598bf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 8 Feb 2019 12:46:07 +0100 Subject: [PATCH 0974/2222] Update sonoff_template.h Fix PN532 compile error --- sonoff/sonoff_template.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index ff2ba6401..f6ae3aced 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -162,8 +162,8 @@ enum UserSelectablePins { GPIO_MCP39F5_TX, // MCP39F501 Serial interface (Shelly2) GPIO_MCP39F5_RX, // MCP39F501 Serial interface (Shelly2) GPIO_MCP39F5_RST, // MCP39F501 Reset (Shelly2) - GPIO_PN532_RXD, // PN532 NFC Serial Rx GPIO_PN532_TXD, // PN532 NFC Serial Tx + GPIO_PN532_RXD, // PN532 NFC Serial Rx GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -228,7 +228,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_BUTTON "1i|" D_SENSOR_BUTTON "2i|" D_SENSOR_BUTTON "3i|" D_SENSOR_BUTTON "4i|" D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in|" D_SENSOR_NRG_SEL "|" D_SENSOR_NRG_SEL "i|" D_SENSOR_NRG_CF1 "|" D_SENSOR_HLW_CF "|" D_SENSOR_HJL_CF "|" - D_SENSOR_MCP39F5_TX "|" D_SENSOR_MCP39F5_RX "|" D_SENSOR_MCP39F5_RST + D_SENSOR_MCP39F5_TX "|" D_SENSOR_MCP39F5_RX "|" D_SENSOR_MCP39F5_RST "|" D_SENSOR_PN532_TX "|" D_SENSOR_PN532_RX ; @@ -536,23 +536,23 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_TUYA_TX, // Tuya Serial interface GPIO_TUYA_RX, // Tuya Serial interface #endif -#ifdef USE_MGC3130 - GPIO_MGC3130_XFER, - GPIO_MGC3130_RESET, -#endif #ifdef USE_AZ7798 GPIO_AZ_TXD, // AZ-Instrument 7798 CO2 datalogger Serial interface GPIO_AZ_RXD, // AZ-Instrument 7798 CO2 datalogger Serial interface #endif +#ifdef USE_PN532_HSU + GPIO_PN532_TXD, // PN532 HSU Tx + GPIO_PN532_RXD, // PN532 HSU Rx +#endif +#ifdef USE_MGC3130 + GPIO_MGC3130_XFER, + GPIO_MGC3130_RESET, +#endif #ifdef USE_MAX31855 GPIO_MAX31855CS, // MAX31855 Serial interface GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface #endif -#ifdef USE_PN532_HSU - GPIO_PN532_RXD, // PN532 HSU Rx - GPIO_PN532_TXD, // PN532 HSU Tx -#endif }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { From 776486f390f4e28fe505b3e4636525f53095bedd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 8 Feb 2019 13:00:11 +0100 Subject: [PATCH 0975/2222] Add MHZ19 Temperature to Domoticz Add MHZ19 Temperature as Domoticz Temperature selection (#5128) --- sonoff/_changelog.ino | 6 ++++++ sonoff/xsns_15_mhz19.ino | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 339ae2bfe..4b328ca2b 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,6 +4,12 @@ * Fix IR local echo * Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring as used in Sonoff S31, Pow Ra and many Tuya based devices * Add user configuration of MCP39F501 Energy Monitoring as used in Shelly2 + * Add support for multiple ADS1115 I2C devices (#5083) + * Add rule support for "==", "!=" ">=" and "<=" (#5122) + * Add Hass status sensor (#5139) + * Change GUI weblog solving possible empty screens (#5154) + * Change PN532 support from I2C to Serial for more stability (#5162) + * Add MHZ19 Temperature as Domoticz Temperature selection (#5128) * * 6.4.1.13 20190130 * Add command SetOption36 to control boot loop default restoration (#4645, #5063) diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 747a8125f..8558a9cd9 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -345,7 +345,10 @@ void MhzShow(bool json) if (json) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, types, model, mhz_last_ppm, temperature); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm); + if (0 == tele_period) { + DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm); + DomoticzSensor(DZ_TEMP, temperature); + } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { From bfcc35757349c1408c9edb839f2c5c5ceb733951 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 8 Feb 2019 14:25:46 +0100 Subject: [PATCH 0976/2222] Housekeeping Housekeeping --- sonoff/sonoff_post.h | 21 ++++++++++++--------- sonoff/support_features.ino | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index e6eb186a5..a9891385d 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -92,7 +92,6 @@ void KNX_CB_Action(message_t const &msg, void *arg); //#define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) //#define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) //#define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) -//#define USE_PN532_I2C // Enable PN532 - Near Field Communication (NFC) controller (+1k6 code) //#define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code) #define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) #define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) @@ -114,6 +113,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define TUYA_DIMMER_ID 0 // Default dimmer Id #endif #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer +//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger +#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) #define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) #define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) @@ -138,7 +139,6 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code) -//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger #endif // USE_SENSORS /*********************************************************************************************\ @@ -174,10 +174,6 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor #undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor #undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor -#undef USE_PZEM004T // Disable PZEM004T energy sensor -#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor -#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor -#undef USE_MCP39F501 // Disable support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) #undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter @@ -185,6 +181,12 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer +#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger +#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) +#undef USE_PZEM004T // Disable PZEM004T energy sensor +#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor +#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor +#undef USE_MCP39F501 // Disable support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI #undef USE_IR_REMOTE // Disable IR remote commands using library IRremoteESP8266 and ArduinoJson #undef USE_IR_RECEIVE // Disable support for IR receiver @@ -198,7 +200,6 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code -#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger #endif // USE_CLASSIC /*********************************************************************************************\ @@ -307,6 +308,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); //#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer +#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger +#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) #undef USE_PZEM004T // Disable PZEM004T energy sensor #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor @@ -324,7 +327,6 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code -#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger #endif // USE_BASIC /*********************************************************************************************\ @@ -371,6 +373,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer +#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger +#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) #undef USE_PZEM004T // Disable PZEM004T energy sensor #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor @@ -388,7 +392,6 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code -#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger #endif // BE_MINIMAL /*********************************************************************************************\ diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 6c1abf97a..4c43f1dda 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -376,8 +376,8 @@ void GetFeatures(void) #ifdef USE_MAX31855 feature_sns2 |= 0x00080000; // xsns_39_max31855.ino #endif -#ifdef USE_PN532_I2C - feature_sns2 |= 0x00100000; // xsns_40_pn532_i2c.ino +#ifdef USE_PN532_HSU + feature_sns2 |= 0x00100000; // xsns_40_pn532.ino #endif #ifdef USE_MAX44009 feature_sns2 |= 0x00200000; From ae277f59cf38f208f7848aeee7e4d9848d3c0a14 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 8 Feb 2019 14:55:45 +0100 Subject: [PATCH 0977/2222] Change image defines 6.4.1.15 20190208 * Change image name BE_MINIMAL to FIRMWARE_MINIMAL (#5106) * Change image names USE_xyz to FIRMWARE_xyz (#5106) --- platformio.ini | 24 ++++++++++++------------ sonoff/_changelog.ino | 6 +++++- sonoff/my_user_config.h | 12 ++++++------ sonoff/settings.ino | 12 ++++++------ sonoff/sonoff.ino | 12 ++++++------ sonoff/sonoff_post.h | 26 +++++++++++++------------- sonoff/sonoff_version.h | 2 +- sonoff/support_features.ino | 8 ++++---- sonoff/support_wifi.ino | 4 ++-- sonoff/xdrv_01_webserver.ino | 20 ++++++++++---------- tools/decode-status.py | 4 ++-- 11 files changed, 67 insertions(+), 63 deletions(-) diff --git a/platformio.ini b/platformio.ini index 5631982dd..f5d958ebf 100644 --- a/platformio.ini +++ b/platformio.ini @@ -130,12 +130,12 @@ board_build.flash_mode = dout platform = ${core_active.platform} build_flags = ${core_active.build_flags} -; -DUSE_CLASSIC -; -DBE_MINIMAL -; -DUSE_SENSORS -; -DUSE_BASIC -; -DUSE_KNX_NO_EMULATION -; -DUSE_DISPLAYS +; -DFIRMWARE_CLASSIC +; -DFIRMWARE_MINIMAL +; -DFIRMWARE_SENSORS +; -DFIRMWARE_BASIC +; -DFIRMWARE_KNX_NO_EMULATION +; -DFIRMWARE_DISPLAYS ; -DUSE_CONFIG_OVERRIDE ; *** Fix espressif8266@1.7.0 induced undesired all warnings @@ -184,7 +184,7 @@ board = ${common.board} board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_cpu = ${common.board_build.f_cpu} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DBE_MINIMAL +build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL monitor_speed = ${common.monitor_speed} upload_port = ${common.upload_port} upload_resetmethod = ${common.upload_resetmethod} @@ -198,7 +198,7 @@ board = ${common.board} board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_cpu = ${common.board_build.f_cpu} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DUSE_BASIC +build_flags = ${common.build_flags} -DFIRMWARE_BASIC monitor_speed = ${common.monitor_speed} upload_port = ${common.upload_port} upload_resetmethod = ${common.upload_resetmethod} @@ -212,7 +212,7 @@ board = ${common.board} board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_cpu = ${common.board_build.f_cpu} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DUSE_CLASSIC +build_flags = ${common.build_flags} -DFIRMWARE_CLASSIC monitor_speed = ${common.monitor_speed} upload_port = ${common.upload_port} upload_resetmethod = ${common.upload_resetmethod} @@ -226,7 +226,7 @@ board = ${common.board} board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_cpu = ${common.board_build.f_cpu} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DUSE_KNX_NO_EMULATION +build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION monitor_speed = ${common.monitor_speed} upload_port = ${common.upload_port} upload_resetmethod = ${common.upload_resetmethod} @@ -240,7 +240,7 @@ board = ${common.board} board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_cpu = ${common.board_build.f_cpu} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DUSE_SENSORS +build_flags = ${common.build_flags} -DFIRMWARE_SENSORS monitor_speed = ${common.monitor_speed} upload_port = ${common.upload_port} upload_resetmethod = ${common.upload_resetmethod} @@ -254,7 +254,7 @@ board = ${common.board} board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_cpu = ${common.board_build.f_cpu} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DUSE_DISPLAYS +build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS monitor_speed = ${common.monitor_speed} upload_port = ${common.upload_port} upload_resetmethod = ${common.upload_resetmethod} diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 4b328ca2b..80c79746f 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ -/* 6.4.1.14 20190203 +/* 6.4.1.15 20190208 + * Change image name BE_MINIMAL to FIRMWARE_MINIMAL (#5106) + * Change image names USE_xyz to FIRMWARE_xyz (#5106) + * + * 6.4.1.14 20190203 * Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name * Add Resolution property to Status 3 report providing previous SetOption second value property * Fix IR local echo diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index c719f3c40..d782a9e2d 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -429,12 +429,12 @@ * See RELEASENOTES.md for selected features \*********************************************************************************************/ -//#define USE_CLASSIC // Create sonoff-classic with initial configuration tools WPS, SmartConfig and WifiManager -//#define USE_BASIC // Create sonoff-basic with no sensors -//#define USE_SENSORS // Create sonoff-sensors with useful sensors enabled -//#define USE_KNX_NO_EMULATION // Create sonoff-knx with KNX but without Emulation -//#define USE_DISPLAYS // Create sonoff-display with display drivers enabled -//#define BE_MINIMAL // Create sonoff-minimal as intermediate firmware for OTA-MAGIC +//#define FIRMWARE_CLASSIC // Create sonoff-classic with initial configuration tools WPS, SmartConfig and WifiManager +//#define FIRMWARE_BASIC // Create sonoff-basic with no sensors +//#define FIRMWARE_SENSORS // Create sonoff-sensors with useful sensors enabled +//#define FIRMWARE_KNX_NO_EMULATION // Create sonoff-knx with KNX but without Emulation +//#define FIRMWARE_DISPLAYS // Create sonoff-display with display drivers enabled +//#define FIRMWARE_MINIMAL // Create sonoff-minimal as intermediate firmware for OTA-MAGIC /*********************************************************************************************\ * No user configurable items below diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 55a73fc56..b3192d50a 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -391,7 +391,7 @@ void SettingsSave(uint8_t rotate) * stop_flash_rotate 0 = Allow flash slot rotation (SetOption12 0) * stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1) */ -#ifndef BE_MINIMAL +#ifndef FIRMWARE_MINIMAL if ((GetSettingsCrc() != settings_crc) || rotate) { if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade) stop_flash_rotate = 1; @@ -441,7 +441,7 @@ void SettingsSave(uint8_t rotate) settings_crc = Settings.cfg_crc; } -#endif // BE_MINIMAL +#endif // FIRMWARE_MINIMAL RtcSettingsSave(); } @@ -487,12 +487,12 @@ void SettingsLoad(void) AddLog(LOG_LEVEL_DEBUG); } -#ifndef BE_MINIMAL +#ifndef FIRMWARE_MINIMAL if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { // Init defaults if cfg_holder differs from user settings in my_user_config.h SettingsDefault(); } settings_crc = GetSettingsCrc(); -#endif // BE_MINIMAL +#endif // FIRMWARE_MINIMAL RtcSettingsLoad(); } @@ -504,7 +504,7 @@ void SettingsErase(uint8_t type) 1 = Erase SDK parameter area at end of linker memory model (0x0FDxxx - 0x0FFFFF) solving possible wifi errors */ -#ifndef BE_MINIMAL +#ifndef FIRMWARE_MINIMAL bool result; uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; @@ -533,7 +533,7 @@ void SettingsErase(uint8_t type) } OsWatchLoop(); } -#endif // BE_MINIMAL +#endif // FIRMWARE_MINIMAL } // Copied from 2.4.0 as 2.3.0 is incomplete diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 0a96acd05..8f220eb7a 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1957,7 +1957,7 @@ void Every250mSeconds(void) ota_retry_counter--; if (ota_retry_counter) { strlcpy(mqtt_data, GetOtaUrl(log_data, sizeof(log_data)), sizeof(mqtt_data)); -#ifndef BE_MINIMAL +#ifndef FIRMWARE_MINIMAL if (RtcSettings.ota_loader) { char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it char *pch = strrchr((bch != NULL) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin @@ -1969,7 +1969,7 @@ void Every250mSeconds(void) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ech); // Minimal filename must be filename-minimal } } -#endif // BE_MINIMAL +#endif // FIRMWARE_MINIMAL snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "%s"), mqtt_data); AddLog(LOG_LEVEL_DEBUG); #if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) @@ -1980,14 +1980,14 @@ void Every250mSeconds(void) ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); #endif if (!ota_result) { -#ifndef BE_MINIMAL +#ifndef FIRMWARE_MINIMAL int ota_error = ESPhttpUpdate.getLastError(); // snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Ota error %d"), ota_error); // AddLog(LOG_LEVEL_DEBUG); if ((HTTP_UE_TOO_LESS_SPACE == ota_error) || (HTTP_UE_BIN_FOR_WRONG_FLASH == ota_error)) { RtcSettings.ota_loader = 1; // Try minimal image next } -#endif // BE_MINIMAL +#endif // FIRMWARE_MINIMAL ota_state_flag = 2; // Upgrade failed - retry } } @@ -2584,10 +2584,10 @@ void setup(void) snprintf_P(log_data, sizeof(log_data), PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), PROJECT, Settings.friendlyname[0], my_version, my_image); AddLog(LOG_LEVEL_INFO); -#ifdef BE_MINIMAL +#ifdef FIRMWARE_MINIMAL snprintf_P(log_data, sizeof(log_data), PSTR(D_WARNING_MINIMAL_VERSION)); AddLog(LOG_LEVEL_INFO); -#endif // BE_MINIMAL +#endif // FIRMWARE_MINIMAL RtcInit(); diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index a9891385d..06bd3688b 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -55,7 +55,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); * Provide an image with useful supported sensors enabled \*********************************************************************************************/ -#ifdef USE_SENSORS +#ifdef FIRMWARE_SENSORS #undef CODE_IMAGE #define CODE_IMAGE 3 @@ -139,14 +139,14 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code) -#endif // USE_SENSORS +#endif // FIRMWARE_SENSORS /*********************************************************************************************\ * [sonoff-classic.bin] * Provide an image close to version 5.12.0 but still within 499k program space to allow one time OTA \*********************************************************************************************/ -#ifdef USE_CLASSIC +#ifdef FIRMWARE_CLASSIC #undef CODE_IMAGE #define CODE_IMAGE 2 @@ -200,14 +200,14 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code -#endif // USE_CLASSIC +#endif // FIRMWARE_CLASSIC /*********************************************************************************************\ * [sonoff-knx.bin] * Provide a dedicated KNX image allowing enough code and memory space \*********************************************************************************************/ -#ifdef USE_KNX_NO_EMULATION +#ifdef FIRMWARE_KNX_NO_EMULATION #undef CODE_IMAGE #define CODE_IMAGE 4 @@ -216,14 +216,14 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_KNX // Enable KNX IP Protocol Support (+23k code, +3k3 mem) #endif #undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) -#endif // USE_KNX_NO_EMULATION +#endif // FIRMWARE_KNX_NO_EMULATION /*********************************************************************************************\ * [sonoff-display.bin] * Provide an image with display drivers enabled \*********************************************************************************************/ -#ifdef USE_DISPLAYS +#ifdef FIRMWARE_DISPLAYS #undef CODE_IMAGE #define CODE_IMAGE 6 @@ -250,7 +250,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_ARILUX_RF // Remove support for Arilux RF remote controller (-0k8 code, 252 iram (non 2.3.0)) #undef USE_RF_FLASH // Remove support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (-3k code) -#endif // USE_DISPLAYS +#endif // FIRMWARE_DISPLAYS /*********************************************************************************************\ * Mandatory define for DS18x20 if changed by above image selections @@ -266,13 +266,13 @@ void KNX_CB_Action(message_t const &msg, void *arg); * Provide an image without sensors \*********************************************************************************************/ -#ifdef USE_BASIC +#ifdef FIRMWARE_BASIC #undef CODE_IMAGE #define CODE_IMAGE 5 #undef APP_SLEEP -#define APP_SLEEP 1 // Default to sleep = 1 for USE_BASIC +#define APP_SLEEP 1 // Default to sleep = 1 for FIRMWARE_BASIC //#undef USE_ENERGY_SENSOR // Disable energy sensors #undef USE_ARDUINO_OTA // Disable support for Arduino OTA @@ -327,14 +327,14 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code -#endif // USE_BASIC +#endif // FIRMWARE_BASIC /*********************************************************************************************\ * [sonoff-minimal.bin] * Provide the smallest image possible while still enabling a webserver for intermediate image load \*********************************************************************************************/ -#ifdef BE_MINIMAL +#ifdef FIRMWARE_MINIMAL #undef CODE_IMAGE #define CODE_IMAGE 1 @@ -392,7 +392,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code -#endif // BE_MINIMAL +#endif // FIRMWARE_MINIMAL /*********************************************************************************************\ * Mandatory defines satisfying possible disabled defines diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 5aaa62872..9afa3f2b2 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0604010E +#define VERSION 0x0604010F #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 4c43f1dda..09d5d140c 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -126,16 +126,16 @@ void GetFeatures(void) #ifdef USE_CONFIG_OVERRIDE feature_drv2 |= 0x00000001; // user_config(_override).h #endif -#ifdef BE_MINIMAL +#ifdef FIRMWARE_MINIMAL feature_drv2 |= 0x00000002; // user_config(_override).h #endif -#ifdef USE_SENSORS +#ifdef FIRMWARE_SENSORS feature_drv2 |= 0x00000004; // user_config(_override).h #endif -#ifdef USE_CLASSIC +#ifdef FIRMWARE_CLASSIC feature_drv2 |= 0x00000008; // user_config(_override).h #endif -#ifdef USE_KNX_NO_EMULATION +#ifdef FIRMWARE_KNX_NO_EMULATION feature_drv2 |= 0x00000010; // user_config(_override).h #endif #ifdef USE_DISPLAY_MODES1TO5 diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 730ac595f..90f0584b7 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -501,12 +501,12 @@ void WifiCheck(uint8_t param) } } -#ifdef BE_MINIMAL +#ifdef FIRMWARE_MINIMAL if (1 == RtcSettings.ota_loader) { RtcSettings.ota_loader = 0; ota_state_flag = 3; } -#endif // BE_MINIMAL +#endif // FIRMWARE_MINIMAL #ifdef USE_DISCOVERY if (Settings.flag3.mdns_enabled) { diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 316553130..449ae6e35 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -208,7 +208,7 @@ const char HTTP_HEAD_STYLE[] PROGMEM = "" "" "
" -#ifdef BE_MINIMAL +#ifdef FIRMWARE_MINIMAL "

" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "

" #endif "
" @@ -227,7 +227,7 @@ const char HTTP_MSG_SLIDER2[] PROGMEM = const char HTTP_MSG_RSTRT[] PROGMEM = "
" D_DEVICE_WILL_RESTART "

"; const char HTTP_BTN_MENU1[] PROGMEM = -#ifndef BE_MINIMAL +#ifndef FIRMWARE_MINIMAL "
" "
" #endif @@ -401,7 +401,7 @@ void StartWebserver(int type, IPAddress ipweb) WebServer->on("/ay", HandleAjaxStatusRefresh); WebServer->on("/cm", HandleHttpCommand); WebServer->onNotFound(HandleNotFound); -#ifndef BE_MINIMAL +#ifndef FIRMWARE_MINIMAL WebServer->on("/cn", HandleConfiguration); WebServer->on("/md", HandleModuleConfiguration); WebServer->on("/wi", HandleWifiConfiguration); @@ -416,7 +416,7 @@ void StartWebserver(int type, IPAddress ipweb) #endif // USE_EMULATION XdrvCall(FUNC_WEB_ADD_HANDLER); XsnsCall(FUNC_WEB_ADD_HANDLER); -#endif // Not BE_MINIMAL +#endif // Not FIRMWARE_MINIMAL } reset_web_log_flag = false; WebServer->begin(); // Web server start @@ -601,7 +601,7 @@ void HandleRoot(void) } if (HTTP_MANAGER == webserver_state) { -#ifndef BE_MINIMAL +#ifndef FIRMWARE_MINIMAL if ((Settings.web_password[0] != 0) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1"))) { HandleWifiLogin(); } else { @@ -619,7 +619,7 @@ void HandleRoot(void) HandleWifiLogin(); } } -#endif // Not BE_MINIMAL +#endif // Not FIRMWARE_MINIMAL } else { char stemp[10]; String page = FPSTR(HTTP_HEAD); @@ -673,12 +673,12 @@ void HandleRoot(void) page += F("
%s " D_GPIO "%d %s
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
, {m} = , {e} =
%s " D_GPIO "%d %s
%s " D_GPIO "%d %s
%s " D_GPIO "%d %s
%s " D_GPIO "%d %s
%s " D_GPIO "%d %s
%s " D_GPIO "%d %s
"); } -#ifndef BE_MINIMAL +#ifndef FIRMWARE_MINIMAL mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); page += String(mqtt_data); -#endif // Not BE_MINIMAL +#endif // Not FIRMWARE_MINIMAL if (HTTP_ADMIN == webserver_state) { page += FPSTR(HTTP_BTN_MENU1); @@ -773,7 +773,7 @@ bool HttpCheckPriviledgedAccess(bool autorequestauth = true) /*-------------------------------------------------------------------------------------------*/ -#ifndef BE_MINIMAL +#ifndef FIRMWARE_MINIMAL void HandleConfiguration(void) { @@ -1407,7 +1407,7 @@ void HandleInformation(void) page += FPSTR(HTTP_BTN_MAIN); ShowPage(page); } -#endif // Not BE_MINIMAL +#endif // Not FIRMWARE_MINIMAL /*-------------------------------------------------------------------------------------------*/ diff --git a/tools/decode-status.py b/tools/decode-status.py index 2d105bc96..dd90d1669 100644 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -123,8 +123,8 @@ a_features = [[ "USE_TIMERS","USE_SUNRISE","USE_TIMERS_WEB","USE_RULES", "USE_KNX","USE_WPS","USE_SMARTCONFIG","MQTT_ARDUINOMQTT" ],[ - "USE_CONFIG_OVERRIDE","BE_MINIMAL","USE_SENSORS","USE_CLASSIC", - "USE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD", + "USE_CONFIG_OVERRIDE","FIRMWARE_MINIMAL","FIRMWARE_SENSORS","FIRMWARE_CLASSIC", + "FIRMWARE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD", "USE_DISPLAY_SSD1306","USE_DISPLAY_MATRIX","USE_DISPLAY_ILI9341","USE_DISPLAY_EPAPER", "USE_DISPLAY_SH1106","USE_MP3_PLAYER","USE_PCA9685","USE_TUYA_DIMMER", "USE_RC_SWITCH","USE_ARMTRONIX_DIMMERS","","", From 953bcd26af4069094ea9a41299b0ca97c25f7edb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 8 Feb 2019 15:35:28 +0100 Subject: [PATCH 0978/2222] Update xsns_40_pn532.ino Cleanup and use flush --- sonoff/xsns_40_pn532.ino | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/sonoff/xsns_40_pn532.ino b/sonoff/xsns_40_pn532.ino index af00720b2..c1daef96e 100644 --- a/sonoff/xsns_40_pn532.ino +++ b/sonoff/xsns_40_pn532.ino @@ -96,7 +96,7 @@ int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout) break; } } while((timeout == 0) || ((millis()- start_millis ) < timeout)); - + if (ret < 0) { if (read_bytes) { return read_bytes; @@ -114,7 +114,7 @@ int8_t PN532_readAckFrame(void) { const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; uint8_t ackBuf[sizeof(PN532_ACK)]; - + if (PN532_receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0) { return PN532_TIMEOUT; } @@ -128,7 +128,7 @@ int8_t PN532_readAckFrame(void) int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) { // Clear the serial buffer just in case - while(PN532_Serial->available()) { PN532_Serial->read(); } + PN532_Serial->flush(); pn532_command = header[0]; PN532_Serial->write((uint8_t)PN532_PREAMBLE); @@ -155,7 +155,7 @@ int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *bo uint8_t checksum = ~sum + 1; // checksum of TFI + DATA PN532_Serial->write(checksum); PN532_Serial->write((uint8_t)PN532_POSTAMBLE); - + return PN532_readAckFrame(); } @@ -197,7 +197,7 @@ int16_t PN532_readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 50) if (PN532_receive(buf, length[0], timeout) != length[0]) { // Timed out return PN532_TIMEOUT; } - + uint8_t sum = PN532_PN532TOHOST + cmd; for (uint8_t i=0; iwrite(wakeup,sizeof(wakeup)); // Flush the serial buffer just in case there's garbage in there - while(PN532_Serial->available()) { PN532_Serial->read(); } + PN532_Serial->flush(); } bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 50) @@ -413,17 +413,17 @@ void PN532_ScanForTag(void) bool set_success = false; if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) { char uids[15]; - -#ifdef USE_PN532_DATA_FUNCTION + +#ifdef USE_PN532_DATA_FUNCTION char card_datas[34]; -#endif // USE_PN532_DATA_FUNCTION +#endif // USE_PN532_DATA_FUNCTION sprintf(uids,""); for (uint8_t i = 0;i < uid_len;i++) { sprintf(uids,"%s%02X",uids,uid[i]); } - -#ifdef USE_PN532_DATA_FUNCTION + +#ifdef USE_PN532_DATA_FUNCTION if (uid_len == 4) { // Lets try to read block 1 of the mifare classic card for more information uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) { @@ -502,15 +502,15 @@ void PN532_ScanForTag(void) break; } pn532_function = 0; -#endif // USE_PN532_DATA_FUNCTION - +#endif // USE_PN532_DATA_FUNCTION + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); #ifdef USE_PN532_DATA_FUNCTION snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), mqtt_data, uids, card_datas); #else snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids); -#endif // USE_PN532_DATA_FUNCTION +#endif // USE_PN532_DATA_FUNCTION MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); @@ -521,10 +521,10 @@ void PN532_ScanForTag(void) sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas); #else sprintf(command,"event PN532_UID=%s",uids); -#endif // USE_PN532_DATA_FUNCTION +#endif // USE_PN532_DATA_FUNCTION ExecuteCommand(command, SRC_RULE); #endif // USE_PN532_CAUSE_EVENTS - + pn532_scantimer = 7; // Ignore tags found for two seconds } } @@ -582,7 +582,7 @@ bool PN532_Command(void) bool Xsns40(uint8_t function) { bool result = false; - + switch (function) { case FUNC_INIT: PN532_Init(); @@ -601,13 +601,13 @@ bool Xsns40(uint8_t function) break; case FUNC_EVERY_SECOND: break; -#ifdef USE_PN532_DATA_FUNCTION +#ifdef USE_PN532_DATA_FUNCTION case FUNC_COMMAND: if (XSNS_40 == XdrvMailbox.index) { result = PN532_Command(); } break; -#endif +#endif } return result; } From f1247a61e5872c13be19ef9968e0e1f2a44c133d Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 8 Feb 2019 12:10:01 -0500 Subject: [PATCH 0979/2222] Renamed SM16716 PWR as per https://github.com/arendst/Sonoff-Tasmota/pull/4991#pullrequestreview-201622697 --- sonoff/language/bg-BG.h | 2 +- sonoff/language/cs-CZ.h | 2 +- sonoff/language/de-DE.h | 2 +- sonoff/language/el-GR.h | 2 +- sonoff/language/en-GB.h | 2 +- sonoff/language/es-AR.h | 2 +- sonoff/language/fr-FR.h | 2 +- sonoff/language/he-HE.h | 2 +- sonoff/language/hu-HU.h | 2 +- sonoff/language/it-IT.h | 2 +- sonoff/language/nl-NL.h | 2 +- sonoff/language/pl-PL.h | 2 +- sonoff/language/pt-BR.h | 2 +- sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 2 +- sonoff/language/sk-SK.h | 2 +- sonoff/language/sv-SE.h | 2 +- sonoff/language/tr-TR.h | 2 +- sonoff/language/uk-UK.h | 2 +- sonoff/language/zh-CN.h | 2 +- sonoff/language/zh-TW.h | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index c0195039b..292a61b18 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Активиране на SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 48c78ed96..48e34a4c3 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Povol SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index c82602d0c..98d3cf16f 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 aktivieren" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 4a711959e..8acf24fa7 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Ενεργοποίηση SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 6b4ebcbd2..2d07be421 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Enable SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 2e8bf6fbc..b8b2f5950 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Habilitar SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 59292bd44..2b71e0066 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Activer SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 62c23386a..eb4feb449 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Enable SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 6a96b2501..cf924b2ac 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 engedélyezése" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 94aac6e22..3698bc57d 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Abilita SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index eb4ed10f7..e33a5cf90 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -558,7 +558,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 inschakelen" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index ee8de5739..b2847923b 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -558,7 +558,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Włącz SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index c88fdd0c4..d66ed8589 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Habilitar SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 94b5923cf..a9d22221f 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Enable SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index d88f9e6e4..762bfe1f5 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Enable SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 31d9a021e..0c8d0f428 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -558,7 +558,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Povoľ SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index ea0b507b6..2c36c1d8b 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Aktivera SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 557b057c9..b41e57f10 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 Aktif" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index e227203a7..47b62987b 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Увімкнений SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 3a882e424..5a581d0da 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "启用 SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index b5154a03e..602ecbe4d 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -557,7 +557,7 @@ #define D_SENSOR_PN532_RX "PN532 Rx" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "Enable SM16716" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" // Units #define D_UNIT_AMPERE "安" From c254410723c7243f88f3d127db148ff7459e9250 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Fri, 8 Feb 2019 19:26:02 +0200 Subject: [PATCH 0980/2222] PN532: Add // #define USE_PN532_CAUSE_EVENTS PN532: Add // #define USE_PN532_CAUSE_EVENTS Forgot to include it in the my_user_config.h --- sonoff/my_user_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index d782a9e2d..182957209 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -376,6 +376,7 @@ #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code) //#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) +// #define USE_PN532_CAUSE_EVENTS // Cause event execution for PN532_UID= and PN532_DATA=[if defined] (+ 30 bytes code) // #define USE_PN532_DATA_FUNCTION // Add sensor40 command support for erase, setting data block content (+1k7 code, 388 bytes mem) // #define USE_PN532_DATA_RAW // Allow DATA block to be used by non-alpha-numberic data (+ 80 bytes code, 48 bytes ram) From 10802d11dcdd80796ccd60fd9fc3a9df10b4cdfa Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 9 Feb 2019 13:24:35 +0100 Subject: [PATCH 0981/2222] Update sonoff_template.h Housekeeping --- sonoff/sonoff_template.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index a400d2afd..84d0c3c1d 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -638,10 +638,10 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { KMC_70011, AILIGHT, // Light Bulbs PHILIPS, + SYF05, YTF_IR_BRIDGE, WITTY, // Development Devices - WEMOS, - SYF05 + WEMOS }; // Default module settings From ab11096f3a14f2b4ff6c32fe3a05443c29671072 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 9 Feb 2019 13:25:15 +0100 Subject: [PATCH 0982/2222] Add command SerialDelimiter 128 Add command SerialDelimiter 128 to filter reception of only characters between ASCII 32 and 127 (#5131) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 80c79746f..4b4bbb015 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.4.1.15 20190208 * Change image name BE_MINIMAL to FIRMWARE_MINIMAL (#5106) * Change image names USE_xyz to FIRMWARE_xyz (#5106) + * Add command SerialDelimiter 128 to filter reception of only characters between ASCII 32 and 127 (#5131) * * 6.4.1.14 20190203 * Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 17f9bdf4a..77bcc37b8 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2171,27 +2171,29 @@ void SerialInput(void) /*-------------------------------------------------------------------------------------------*/ - if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // binary data... + if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // Discard binary data above 127 if no raw reception allowed serial_in_byte_counter = 0; Serial.flush(); return; } - if (!Settings.flag.mqtt_serial) { - if (isprint(serial_in_byte)) { - if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // add char to string if it still fits + if (!Settings.flag.mqtt_serial) { // SerialSend active + if (isprint(serial_in_byte)) { // Any char between 32 and 127 + if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // Add char to string if it still fits serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; } else { serial_in_byte_counter = 0; } } } else { - if (serial_in_byte || Settings.flag.mqtt_serial_raw) { - if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && - ((serial_in_byte != Settings.serial_delimiter) || Settings.flag.mqtt_serial_raw)) { // add char to string if it still fits + if (serial_in_byte || Settings.flag.mqtt_serial_raw) { // Any char between 1 and 127 or any char (0 - 255) + if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && // Add char to string if it still fits and ... + ((isprint(serial_in_byte) && (128 == Settings.serial_delimiter)) || // Any char between 32 and 127 + (serial_in_byte != Settings.serial_delimiter) || // Any char between 1 and 127 and not being delimiter + Settings.flag.mqtt_serial_raw)) { // Any char between 0 and 255 serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; serial_polling_window = millis(); } else { - serial_polling_window = 0; + serial_polling_window = 0; // Reception done - send mqtt break; } } @@ -2201,8 +2203,8 @@ void SerialInput(void) * Sonoff SC 19200 baud serial interface \*-------------------------------------------------------------------------------------------*/ if (SONOFF_SC == Settings.module) { - if (serial_in_byte == '\x1B') { // Sonoff SC status from ATMEGA328P - serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed + 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(); @@ -2213,7 +2215,7 @@ void SerialInput(void) /*-------------------------------------------------------------------------------------------*/ else if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) { - serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed + serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)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); @@ -2226,7 +2228,7 @@ void SerialInput(void) } if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { - serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed + serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed if (!Settings.flag.mqtt_serial_raw) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer); } else { From 3a5908437726017874d95499225f3a0b2b585a99 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 9 Feb 2019 13:37:27 +0100 Subject: [PATCH 0983/2222] Enable group status messages Add status message to former declined group commands (#5145) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 4 ++-- sonoff/xdrv_02_mqtt.ino | 12 ++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 4b4bbb015..b14bbbf60 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Change image name BE_MINIMAL to FIRMWARE_MINIMAL (#5106) * Change image names USE_xyz to FIRMWARE_xyz (#5106) * Add command SerialDelimiter 128 to filter reception of only characters between ASCII 32 and 127 (#5131) + * Add status message to former declined group commands (#5145) * * 6.4.1.14 20190203 * Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 77bcc37b8..26f03a096 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1126,8 +1126,8 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_ASTERIX, command, index); } } - else if ((CMND_HOSTNAME == command_code) && !grpflg) { - if ((data_len > 0) && (data_len < sizeof(Settings.hostname))) { + else if (CMND_HOSTNAME == command_code) { + if (!grpflg && (data_len > 0) && (data_len < sizeof(Settings.hostname))) { strlcpy(Settings.hostname, (SC_DEFAULT == Shortcut(dataBuf)) ? WIFI_HOSTNAME : dataBuf, sizeof(Settings.hostname)); if (strstr(Settings.hostname,"%")) { strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index df06da5d2..5abc4f329 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -694,8 +694,8 @@ bool MqttCommand(void) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, fingerprint); } #endif - else if ((CMND_MQTTCLIENT == command_code) && !grpflg) { - if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_client))) { + else if (CMND_MQTTCLIENT == command_code) { + if (!grpflg && (data_len > 0) && (data_len < sizeof(Settings.mqtt_client))) { strlcpy(Settings.mqtt_client, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_CLIENT_ID : dataBuf, sizeof(Settings.mqtt_client)); restart_flag = 2; } @@ -766,8 +766,8 @@ bool MqttCommand(void) } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_grptopic); } - else if ((CMND_TOPIC == command_code) && !grpflg) { - if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_topic))) { + else if (CMND_TOPIC == command_code) { + if (!grpflg && (data_len > 0) && (data_len < sizeof(Settings.mqtt_topic))) { MakeValidMqtt(0, dataBuf); if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT); strlcpy(stemp1, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_TOPIC : dataBuf, sizeof(stemp1)); @@ -780,8 +780,8 @@ bool MqttCommand(void) } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_topic); } - else if ((CMND_BUTTONTOPIC == command_code) && !grpflg) { - if ((data_len > 0) && (data_len < sizeof(Settings.button_topic))) { + else if (CMND_BUTTONTOPIC == command_code) { + if (!grpflg && (data_len > 0) && (data_len < sizeof(Settings.button_topic))) { MakeValidMqtt(0, dataBuf); if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT); switch (Shortcut(dataBuf)) { From b3d6857f6a28f8b7753cba13a68e27a51a6c49c9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 9 Feb 2019 15:04:58 +0100 Subject: [PATCH 0984/2222] Remove duplicates Remove duplicates --- sonoff/sonoff_template.h | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 84d0c3c1d..ed1172e84 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -563,13 +563,6 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_SM16716_DAT, // SM16716 DATA GPIO_SM16716_SEL, // SM16716 SELECT #endif // USE_SM16716 -#if defined(USE_ENERGY_SENSOR) && defined(USE_HLW8012) - GPIO_NRG_SEL, // HLW8012/HLJ-01 Sel output (1 = Voltage) - GPIO_NRG_SEL_INV, // HLW8012/HLJ-01 Sel output (0 = Voltage) - GPIO_NRG_CF1, // HLW8012/HLJ-01 CF1 voltage / current - GPIO_HLW_CF, // HLW8012 CF power - GPIO_HJL_CF, // HJL-01/BL0937 CF power -#endif }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { @@ -1865,7 +1858,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { { "WAGA CHCZ02MB", // WAGA life CHCZ02MB (HJL-01 Energy Monitoring) // https://www.ebay.com/itm/332595697006 GPIO_LED2_INV, // GPIO00 Red LED - 0, // GPIO01 Serial TX + 0, // GPIO01 Serial RXD 0, // GPIO02 GPIO_NRG_SEL_INV, // GPIO03 HJL-01 Sel output (1 = Voltage) 0, // GPIO04 @@ -1888,24 +1881,23 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { // https://docs.tuya.com/en/hardware/WiFi-module/wifi-e3s-module.html // http://www.datasheet-pdf.com/PDF/SM16716-Datasheet-Sunmoon-932771 GPIO_USER, // GPIO00 N.C. - 0, + 0, // GPIO01 Serial RXD GPIO_USER, // GPIO02 N.C. - 0, + 0, // GPIO03 Serial TXD GPIO_SM16716_CLK, // GPIO04 SM16716 Clock GPIO_PWM1, // GPIO05 White - // GPIO06 - // GPIO07 - // GPIO08 - 0, // GPIO09 - 0, // GPIO10 - // GPIO11 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) GPIO_USER, // GPIO12 Alt. White on some devices GPIO_USER, // GPIO13 SM16716 Enable on some devices GPIO_SM16716_DAT, // GPIO14 SM16716 Data 0, // GPIO15 wired to GND GPIO_USER, // GPIO16 N.C. GPIO_FLAG_ADC0 // ADC0 A0 Analog input -// + GPIO_FLAG_PULLUP // Allow input pull-up control } }; From cc8c13b240f98bba7653447e62087d2c662a2155 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 9 Feb 2019 16:08:09 +0100 Subject: [PATCH 0985/2222] Update xdrv_08_serial_bridge.ino SerialBridge revisited --- sonoff/xdrv_08_serial_bridge.ino | 69 ++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 74915935c..ba83f11ec 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -31,12 +31,13 @@ enum SerialBridgeCommands { CMND_SSERIALSEND, CMND_SBAUDRATE }; const char kSerialBridgeCommands[] PROGMEM = D_CMND_SSERIALSEND "|" D_CMND_SBAUDRATE; -TasmotaSerial *SerialBridgeSerial; +TasmotaSerial *SerialBridgeSerial = NULL; -uint8_t serial_bridge_active = 1; -uint8_t serial_bridge_in_byte_counter = 0; unsigned long serial_bridge_polling_window = 0; char *serial_bridge_buffer = NULL; +int serial_bridge_in_byte_counter = 0; +bool serial_bridge_active = true; +bool serial_bridge_raw = false; void SerialBridgeInput(void) { @@ -44,25 +45,37 @@ void SerialBridgeInput(void) yield(); uint8_t serial_in_byte = SerialBridgeSerial->read(); - if (serial_in_byte > 127) { // binary data... + if ((serial_in_byte > 127) && !serial_bridge_raw) { // Discard binary data above 127 if no raw reception allowed serial_bridge_in_byte_counter = 0; SerialBridgeSerial->flush(); return; } - if (serial_in_byte) { - if ((serial_in_byte_counter < SERIAL_BRIDGE_BUFFER_SIZE -1) && (serial_in_byte != Settings.serial_delimiter)) { // add char to string if it still fits + if (serial_in_byte || serial_bridge_raw) { // Any char between 1 and 127 or any char (0 - 255) + + if ((serial_bridge_in_byte_counter < SERIAL_BRIDGE_BUFFER_SIZE -1) && // Add char to string if it still fits and ... + ((isprint(serial_in_byte) && (128 == Settings.serial_delimiter)) || // Any char between 32 and 127 + (serial_in_byte != Settings.serial_delimiter) || // Any char between 1 and 127 and not being delimiter + serial_bridge_raw)) { // Any char between 0 and 255 serial_bridge_buffer[serial_bridge_in_byte_counter++] = serial_in_byte; - serial_bridge_polling_window = millis(); // Wait for more data + serial_bridge_polling_window = millis(); // Wait for more data } else { - serial_bridge_polling_window = 0; // Publish now + serial_bridge_polling_window = 0; // Publish now break; } } } if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) { - serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // serial data completed - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), serial_bridge_buffer); + serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // Serial data completed + if (!serial_bridge_raw) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), serial_bridge_buffer); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"")); + for (int i = 0; i < serial_bridge_in_byte_counter; i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_bridge_buffer[i]); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); + } MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); // XdrvRulesProcess(); serial_bridge_in_byte_counter = 0; @@ -73,15 +86,18 @@ void SerialBridgeInput(void) void SerialBridgeInit(void) { - serial_bridge_active = 0; + serial_bridge_active = false; if ((pin[GPIO_SBR_RX] < 99) && (pin[GPIO_SBR_TX] < 99)) { - serial_bridge_buffer = (char*)(malloc(SERIAL_BRIDGE_BUFFER_SIZE)); - if (serial_bridge_buffer != NULL) { - SerialBridgeSerial = new TasmotaSerial(pin[GPIO_SBR_RX], pin[GPIO_SBR_TX]); - if (SerialBridgeSerial->begin(Settings.sbaudrate * 1200)) { // Baud rate is stored div 1200 so it fits into one byte - serial_bridge_active = 1; - SerialBridgeSerial->flush(); + SerialBridgeSerial = new TasmotaSerial(pin[GPIO_SBR_RX], pin[GPIO_SBR_TX]); + if (SerialBridgeSerial->begin(Settings.sbaudrate * 1200)) { // Baud rate is stored div 1200 so it fits into one byte + if (SerialBridgeSerial->hardwareSerial()) { + ClaimSerial(); + serial_bridge_buffer = serial_in_buffer; // Use idle serial buffer to save RAM + } else { + serial_bridge_buffer = (char*)(malloc(SERIAL_BRIDGE_BUFFER_SIZE)); } + serial_bridge_active = true; + SerialBridgeSerial->flush(); } } } @@ -100,18 +116,19 @@ bool SerialBridgeCommand(void) serviced = false; // Unknown command } else if ((CMND_SSERIALSEND == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { - if (XdrvMailbox.data_len > 0) { // "Hello Tiger\n" + serial_bridge_raw = (XdrvMailbox.index > 3); + if (XdrvMailbox.data_len > 0) { if (1 == XdrvMailbox.index) { - SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); - SerialBridgeSerial->write("\n"); + SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); // "Hello Tiger" + SerialBridgeSerial->write("\n"); // "\n" } - else if ((2 == XdrvMailbox.index) || (4 == XdrvMailbox.index)) { // "Hello Tiger" or "A0" - SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); + else if ((2 == XdrvMailbox.index) || (4 == XdrvMailbox.index)) { + SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); // "Hello Tiger" or "A0" } - else if (3 == XdrvMailbox.index) { // "Hello\f" + else if (3 == XdrvMailbox.index) { // "Hello\f" SerialBridgeSerial->write(Unescape(XdrvMailbox.data, &XdrvMailbox.data_len), XdrvMailbox.data_len); } - else if (5 == XdrvMailbox.index) { // "AA004566" as hex values + else if (5 == XdrvMailbox.index) { char *p; char stemp[3]; uint8_t code; @@ -122,7 +139,7 @@ bool SerialBridgeCommand(void) while (size > 0) { snprintf(stemp, sizeof(stemp), codes); code = strtol(stemp, &p, 16); - SerialBridgeSerial->write(code); + SerialBridgeSerial->write(code); // "AA004566" as hex values size -= 2; codes += 2; } @@ -159,7 +176,7 @@ bool Xdrv08(uint8_t function) SerialBridgeInit(); break; case FUNC_LOOP: - SerialBridgeInput(); + if (SerialBridgeSerial) { SerialBridgeInput(); } break; case FUNC_COMMAND: result = SerialBridgeCommand(); From e18263d796caecd68caa14b98b70209ca641c2d5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 9 Feb 2019 17:01:44 +0100 Subject: [PATCH 0986/2222] Add optional smart plug Add optional smart plug (#5171, #5175) --- sonoff/sonoff_template.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index ed1172e84..64681ea91 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1904,6 +1904,28 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { /* Optionals + { "RGB Smart Plug", // Tuya based smart plug with power monitoring and RGB light + // https://www.aliexpress.com/item/ET-Smart-Plug-Wifi-Socket-With-Switch-Phone-APP-Voice-Remote-Control-Monitor-Smart-Timing-Switch/32964036349.html?spm=a2g0s.9042311.0.0.439c4c4d4N8N2Q + // https://xiangshangcn.en.alibaba.com/product/60844251239-807590977/RGB_wifi_smart_plug_smart_socket_smart_outlet_EU_works_with_Amazon_alexa_google_home_mobile_app_tuya_solution_smart_life.html?spm=a2700.icbuShop.41413.24.4e996767oFAAmO + GPIO_PWM1, // GPIO00 Red + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_PWM3, // GPIO02 Blue + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_PWM2, // GPIO04 Green + GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_KEY1, // GPIO13 Button + GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage + GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) + 0, 0 + } + { "ESP RGBWWC", // esp rgbww controller https://github.com/pljakobs/esp_rgbww_controller/tree/v2.3 GPIO_KEY1, // GPIO00 Button GPIO_USER, // GPIO01 Serial RXD and Optional sensor From 2d892f64cddc7ca83c112ec2d730663a01c8bb55 Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Sun, 10 Feb 2019 08:33:05 +0000 Subject: [PATCH 0987/2222] Init delay of SM16716 increased to 1 ms As per measurements by @damondins: https://github.com/gsimon75/Sonoff-Tasmota/pull/3#issuecomment-462059310 --- sonoff/xdrv_04_light.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index bc4a9b91c..0c5c3cc58 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -410,7 +410,7 @@ void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) digitalWrite(sm16716_pin_sel, HIGH); // in testing I found it takes a minimum of ~380us to wake up the chip // tested on a Merkury RGBW with an SM726EB - delayMicroseconds(400); + delayMicroseconds(1000); SM16716_Init(); } else if (sm16716_enabled && !sm16716_should_enable) { From 7146b5fd4da571e365ab73c4eec77ecfcdbecbde Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 11 Feb 2019 15:43:02 +0100 Subject: [PATCH 0988/2222] Fix LCD clipped center text Fix LCD clipped center text (#5193) --- sonoff/xdsp_01_lcd.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdsp_01_lcd.ino b/sonoff/xdsp_01_lcd.ino index 0cfced507..190c8732b 100644 --- a/sonoff/xdsp_01_lcd.ino +++ b/sonoff/xdsp_01_lcd.ino @@ -107,7 +107,7 @@ void LcdCenter(uint8_t row, char* txt) line[Settings.display_cols[0]] = 0; len = strlen(txt); offset = (len < Settings.display_cols[0]) ? offset = (Settings.display_cols[0] - len) / 2 : 0; - strlcpy(line +offset, txt, len); + strlcpy(line +offset, txt, len +1); lcd->setCursor(0, row); lcd->print(line); } From de5023fb43ee69e7d37c518400d89a42a5cfcda9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 11 Feb 2019 16:53:46 +0100 Subject: [PATCH 0989/2222] Fix LCD center text Fix LCD center text (#5195) --- sonoff/xdsp_01_lcd.ino | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sonoff/xdsp_01_lcd.ino b/sonoff/xdsp_01_lcd.ino index 190c8732b..e0b72618f 100644 --- a/sonoff/xdsp_01_lcd.ino +++ b/sonoff/xdsp_01_lcd.ino @@ -99,15 +99,20 @@ void LcdDisplayOnOff(uint8_t on) void LcdCenter(uint8_t row, char* txt) { - int offset; - int len; char line[Settings.display_cols[0] +2]; + int len = strlen(txt); + int offset = 0; + if (len >= Settings.display_cols[0]) { + len = Settings.display_cols[0] + } else { + offset = (Settings.display_cols[0] - len) / 2; + } memset(line, 0x20, Settings.display_cols[0]); line[Settings.display_cols[0]] = 0; - len = strlen(txt); - offset = (len < Settings.display_cols[0]) ? offset = (Settings.display_cols[0] - len) / 2 : 0; - strlcpy(line +offset, txt, len +1); + for (uint8_t i = 0; i < len; i++) { + line[offset +i] = txt[i]; + } lcd->setCursor(0, row); lcd->print(line); } From 98ae3eaf547d69f3042cbf6ad6850de3965b7c6e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 11 Feb 2019 19:21:49 +0100 Subject: [PATCH 0990/2222] 6.4.1.16 Online template change 6.4.1.16 20190211 * Initial support for online template change using command Template (#5177) --- sonoff/_changelog.ino | 5 +- sonoff/i18n.h | 8 +- sonoff/language/bg-BG.h | 6 + sonoff/language/cs-CZ.h | 6 + sonoff/language/de-DE.h | 6 + sonoff/language/el-GR.h | 6 + sonoff/language/en-GB.h | 6 + sonoff/language/es-AR.h | 6 + sonoff/language/fr-FR.h | 6 + sonoff/language/he-HE.h | 6 + sonoff/language/hu-HU.h | 6 + sonoff/language/it-IT.h | 6 + sonoff/language/nl-NL.h | 7 +- sonoff/language/pl-PL.h | 7 +- sonoff/language/pt-BR.h | 6 + sonoff/language/pt-PT.h | 6 + sonoff/language/ru-RU.h | 6 + sonoff/language/sk-SK.h | 7 +- sonoff/language/sv-SE.h | 6 + sonoff/language/tr-TR.h | 6 + sonoff/language/uk-UK.h | 6 + sonoff/language/zh-CN.h | 6 + sonoff/language/zh-TW.h | 6 + sonoff/settings.h | 7 +- sonoff/settings.ino | 4 + sonoff/sonoff.ino | 173 ++++++++++++++++------ sonoff/sonoff_template.h | 48 +++++-- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 207 ++++++++++++++++----------- sonoff/support_button.ino | 8 +- sonoff/support_rotary.ino | 22 +-- sonoff/xdrv_01_webserver.ino | 41 ++++-- sonoff/xdrv_02_mqtt.ino | 4 +- sonoff/xdrv_04_light.ino | 6 +- sonoff/xdrv_06_snfbridge.ino | 2 +- sonoff/xdrv_07_domoticz.ino | 8 +- sonoff/xdrv_12_home_assistant.ino | 2 +- sonoff/xdrv_16_tuyadimmer.ino | 2 +- sonoff/xdrv_18_armtronix_dimmers.ino | 2 +- sonoff/xdrv_19_ps16dz_dimmer.ino | 2 +- sonoff/xsns_04_snfsc.ino | 2 +- 41 files changed, 494 insertions(+), 190 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b14bbbf60..12e639ddc 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.15 20190208 +/* 6.4.1.16 20190211 + * Initial support for online template change using command Template (#5177) + * + * 6.4.1.15 20190208 * Change image name BE_MINIMAL to FIRMWARE_MINIMAL (#5106) * Change image names USE_xyz to FIRMWARE_xyz (#5106) * Add command SerialDelimiter 128 to filter reception of only characters between ASCII 32 and 127 (#5131) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 7eace1215..b4b3b1df7 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -170,6 +170,8 @@ #define D_RSLT_UPTIME "UPTIME" #define D_RSLT_WARNING "WARNING" +#define D_LOG_SOME_SETTINGS_RESET "Some settings have been reset" + // Commands sonoff.ino #define D_CMND_BACKLOG "Backlog" #define D_CMND_DELAY "Delay" @@ -261,7 +263,11 @@ #define D_CMND_SERIALSEND "SerialSend" #define D_CMND_SERIALDELIMITER "SerialDelimiter" #define D_CMND_BAUDRATE "Baudrate" -#define D_LOG_SOME_SETTINGS_RESET "Some settings have been reset" +#define D_CMND_TEMPLATE "Template" + #define D_JSON_NAME "NAME" + #define D_JSON_GPIO "GPIO" + #define D_JSON_FLAG "FLAG" + #define D_JSON_BASE "BASE" // Commands xdrv_01_mqtt.ino #define D_CMND_MQTTHOST "MqttHost" diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 292a61b18..176d45fb9 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 48e34a4c3..6f298912d 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 98d3cf16f..a71b01406 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 8acf24fa7..316421146 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 2d07be421..156117bac 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index b8b2f5950..68bacd865 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 2b71e0066..0e0a9ed99 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index eb4feb449..23e2f784a 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index cf924b2ac..8a093ccb3 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 3698bc57d..411087ea3 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index e33a5cf90..a5de69158 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -481,7 +481,6 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" - // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Geen" #define D_SENSOR_DHT11 "DHT11" @@ -559,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index b2847923b..a501ac2fd 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -481,7 +481,6 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" - // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Brak" #define D_SENSOR_DHT11 "DHT11" @@ -559,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index d66ed8589..f94c0724b 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index a9d22221f..9f5516661 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 762bfe1f5..ec8ef8543 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 0c8d0f428..6be3edf86 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -481,7 +481,6 @@ #define D_TX20_SOUTH "J" #define D_TX20_WEST "Z" - // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Žiaden" #define D_SENSOR_DHT11 "DHT11" @@ -559,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 2c36c1d8b..ec0c9bc98 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index b41e57f10..f41f89f5a 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 47b62987b..c571a1593 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 5a581d0da..50804d307 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 602ecbe4d..46527a789 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -558,6 +558,12 @@ #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/settings.h b/sonoff/settings.h index 22f6d940d..1698c582e 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -176,7 +176,7 @@ typedef union { uint8_t mhz19b_abc_disable : 1; // Disable ABC (Automatic Baseline Correction for MHZ19(B) (0 = Enabled (default), 1 = Disabled with Sensor15 command) }; } SensorCfg1; - + /* struct SYSCFG { unsigned long cfg_holder; // 000 Pre v6 header @@ -326,11 +326,12 @@ struct SYSCFG { Mcp230xxCfg mcp230xx_config[16]; // 6F6 uint8_t mcp230xx_int_prio; // 716 SensorCfg1 SensorBits1; // 717 On/Off settings used by Sensor Commands - uint16_t mcp230xx_int_timer; // 718 uint8_t rgbwwTable[5]; // 71A + uint8_t user_template_base; // 71F + mytmplt user_template; // 720 29 bytes - uint8_t free_71F[117]; // 71F + uint8_t free_73D[87]; // 73D uint32_t drivers[3]; // 794 uint32_t monitors; // 7A0 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index b3192d50a..e15701e0b 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -596,6 +596,7 @@ void SettingsDefaultSet2(void) // Settings.flag.interlock = 0; Settings.interlock[0] = 0xFF; // Legacy support using all relays in one interlock group Settings.module = MODULE; + ModuleDefault(WEMOS); // for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { Settings.my_gp.io[i] = GPIO_NONE; } strlcpy(Settings.friendlyname[0], FRIENDLY_NAME, sizeof(Settings.friendlyname[0])); strlcpy(Settings.friendlyname[1], FRIENDLY_NAME"2", sizeof(Settings.friendlyname[1])); @@ -1050,6 +1051,9 @@ void SettingsDelta(void) if (Settings.version < 0x0604010D) { Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; } + if (Settings.version < 0x06040110) { + ModuleDefault(WEMOS); + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 26f03a096..f496b82e6 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -75,7 +75,7 @@ enum TasmotaCommands { CMND_MODULE, CMND_MODULES, CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE, CMND_COUNTERDEBOUNCE, CMND_BUTTONDEBOUNCE, CMND_SWITCHDEBOUNCE, 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_INTERLOCK, + CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_INTERLOCK, CMND_TEMPLATE, CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_TIMESTD, CMND_TIMEDST, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER, CMND_DRIVER }; const char kTasmotaCommands[] PROGMEM = @@ -85,7 +85,7 @@ const char kTasmotaCommands[] PROGMEM = 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_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" 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_INTERLOCK "|" + D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TEMPLATE "|" D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER "|" D_CMND_DRIVER; @@ -152,6 +152,7 @@ uint8_t web_log_index = 1; // Index in Web log buffer (should n uint8_t devices_present = 0; // Max number of devices supported uint8_t seriallog_level; // Current copy of Settings.seriallog_level uint8_t syslog_level; // Current copy of Settings.syslog_level +uint8_t my_module_type; // Current copy of Settings.module or user template type //uint8_t mdns_delayed_start = 0; // mDNS delayed start bool serial_local = false; // Handle serial locally; bool fallback_topic_flag = false; // Use Topic or FallbackTopic @@ -343,7 +344,7 @@ void SetDevicePower(power_t rpower, int source) if (XdrvCall(FUNC_SET_DEVICE_POWER)) { // Set power state and stop if serviced // Serviced } - else if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { + else if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { Serial.write(0xA0); Serial.write(0x04); Serial.write(rpower &0xFF); @@ -351,7 +352,7 @@ void SetDevicePower(power_t rpower, int source) Serial.write('\n'); Serial.flush(); } - else if (EXS_RELAY == Settings.module) { + else if (EXS_RELAY == my_module_type) { SetLatchingRelay(rpower, 1); } else { @@ -384,7 +385,7 @@ uint8_t GetFanspeed(void) { uint8_t fanspeed = 0; -// if (SONOFF_IFAN02 == Settings.module) { +// if (SONOFF_IFAN02 == my_module_type) { /* Fanspeed is controlled by relay 2, 3 and 4 as in Sonoff 4CH. 000x = 0 001x = 1 @@ -577,7 +578,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) fallback_topic_flag = false; return; } - else if ((CMND_FANSPEED == command_code) && (SONOFF_IFAN02 == Settings.module)) { + else if ((CMND_FANSPEED == command_code) && (SONOFF_IFAN02 == my_module_type)) { if (data_len > 0) { if ('-' == dataBuf[0]) { payload = (int16_t)GetFanspeed() -1; @@ -653,7 +654,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_ONE_TO_RESTART); } } - else if ((CMND_POWERONSTATE == command_code) && (Settings.module != MOTOR)) { + else if ((CMND_POWERONSTATE == command_code) && (my_module_type != MOTOR)) { /* 0 = Keep relays off after power on * 1 = Turn relays on after power on, if PulseTime set wait for PulseTime seconds, and turn relays off * 2 = Toggle relays after power on @@ -855,10 +856,12 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.weight_resolution); } else if (CMND_MODULE == command_code) { - if ((payload > 0) && (payload <= MAXMODULE)) { + if ((payload >= 0) && (payload <= MAXMODULE)) { + if (0 == payload) { payload = 256; } payload--; Settings.last_module = Settings.module; Settings.module = payload; + SetModuleType(); if (Settings.last_module != payload) { for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { Settings.my_gp.io[i] = GPIO_NONE; @@ -866,18 +869,22 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.module +1, ModuleName().c_str()); + uint8_t module = Settings.module; + if (USER_MODULE == Settings.module) { module = 0; } else { module++; } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, module, ModuleName().c_str()); } else if (CMND_MODULES == command_code) { - for (uint8_t i = 0; i < MAXMODULE; i++) { + for (uint8_t i = 0; i <= MAXMODULE; i++) { if (!jsflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULES "%d\":["), lines); } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); } jsflg = true; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, i +1, AnyModuleName(i).c_str()); - if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == MAXMODULE -1)) { + uint8_t j = i; + if (0 == i) { j = USER_MODULE; } else { j--; } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, i, AnyModuleName(j).c_str()); + if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == MAXMODULE)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]}"), mqtt_data); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); jsflg = false; @@ -889,7 +896,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) else if ((CMND_GPIO == command_code) && (index < sizeof(Settings.my_gp))) { myio cmodule; ModuleGpios(&cmodule); - if ((GPIO_USER == ValidGPIO(index, cmodule.io[index])) && (payload >= 0) && (payload < GPIO_SENSOR_END)) { + if (ValidGPIO(index, cmodule.io[index]) && (payload >= 0) && (payload < GPIO_SENSOR_END)) { bool present = false; for (uint8_t i = 0; i < sizeof(kGpioNiceList); i++) { uint8_t midx = pgm_read_byte(kGpioNiceList + i); @@ -897,7 +904,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } if (present) { for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { - if ((GPIO_USER == ValidGPIO(i, cmodule.io[i])) && (Settings.my_gp.io[i] == payload)) { + if (ValidGPIO(i, cmodule.io[i]) && (Settings.my_gp.io[i] == payload)) { Settings.my_gp.io[i] = GPIO_NONE; } } @@ -907,7 +914,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { + if (ValidGPIO(i, cmodule.io[i])) { if (jsflg) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); jsflg = true; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_GPIO "%d\":\"%d (%s)\""), @@ -927,7 +934,6 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) for (uint8_t i = 0; i < sizeof(kGpioNiceList); i++) { midx = pgm_read_byte(kGpioNiceList + i); if (!GetUsedInModule(midx, cmodule.io)) { - if (!jsflg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_GPIOS "%d\":["), lines); } else { @@ -943,9 +949,89 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } } } - mqtt_data[0] = '\0'; } + else if (CMND_TEMPLATE == command_code) { + // {"NAME":"Generic","GPIO":[17,254,29,254,7,254,254,254,138,254,139,254,254],"FLAG":1,"TYPE":255} + bool error = false; + if (!strstr(dataBuf, "{")) { // If no JSON it must be parameter + bool update = false; + if ((payload > 0) && (payload <= MAXMODULE)) { + ModuleDefault(payload -1); // Copy template module + if (USER_MODULE == Settings.module) { restart_flag = 2; } + } + else if (0 == payload) { // Copy current module with user configured GPIO + if (Settings.module < USER_MODULE) { + ModuleDefault(Settings.module); + update = true; + } + } + if (USER_MODULE == Settings.module) { // Update with latest changes + update = true; + } + if (update) { + uint8_t src = 0; + for (uint8_t dst = 0; dst < sizeof(mycfgio); dst++) { + if (6 == dst) { src = 9; } + if (8 == dst) { src = 12; } + if (Settings.my_gp.io[src] > GPIO_NONE) { + if (Settings.user_template.gp.io[dst] != Settings.my_gp.io[src]) { + Settings.user_template.gp.io[dst] = Settings.my_gp.io[src]; + if (USER_MODULE == Settings.module) { restart_flag = 2; } + } + } + src++; + } + } + } + else if (data_len > 9) { // Workaround exception if empty JSON like {} - Needs checks + StaticJsonBuffer<350> jb; // 331 from https://arduinojson.org/v5/assistant/ + JsonObject& obj = jb.parseObject(dataBuf); + if (!obj.success()) { + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); + error = true; + } else { + // All parameters are optional allowing for partial changes + const char* name = obj[D_JSON_NAME]; + if (name != nullptr) { + strlcpy(Settings.user_template.name, name, sizeof(Settings.user_template.name)); + } + if (obj[D_JSON_GPIO].success()) { + for (uint8_t i = 0; i < sizeof(mycfgio); i++) { + Settings.user_template.gp.io[i] = obj[D_JSON_GPIO][i] | 0; + } + } + if (obj[D_JSON_FLAG].success()) { + uint8_t flag = obj[D_JSON_FLAG] | 0; + memcpy(&Settings.user_template.flag, &flag, sizeof(gpio_flag)); + } + if (obj[D_JSON_BASE].success()) { + uint8_t base = obj[D_JSON_BASE]; + if ((0 == base) || (base >= MAXMODULE)) { base = 17; } else { base--; } + Settings.user_template_base = base; // Default WEMOS + } + + // Validate GPIO +// for (uint8_t i = 0; i < sizeof(mycfgio); i++) { + // For now do not allow non-user configurable GPIO +// if ((Settings.user_template.gp.io[i] > GPIO_FIX_START) && (Settings.user_template.gp.io[i] < GPIO_USER)) { +// Settings.user_template.gp.io[i] = GPIO_NONE; +// }; +// } + if (USER_MODULE == Settings.module) { restart_flag = 2; } + } + } + if (!error) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); + for (uint8_t i = 0; i < sizeof(Settings.user_template.gp); i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", Settings.user_template.gp.io[i]); + } +// snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":\"%d (%s)\"}"), +// mqtt_data, Settings.user_template.flag, Settings.user_template_base +1, AnyModuleName(Settings.user_template_base).c_str()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), + mqtt_data, Settings.user_template.flag, Settings.user_template_base +1); + } + } else if ((CMND_PWM == command_code) && pwm_present && (index > 0) && (index <= MAX_PWMS)) { if ((payload >= 0) && (payload <= Settings.pwm_range) && (pin[GPIO_PWM1 + index -1] < 99)) { Settings.pwm_value[index -1] = payload; @@ -1440,7 +1526,7 @@ void ExecuteCommandPower(uint8_t device, uint8_t state, int source) // ShowSource(source); - if (SONOFF_IFAN02 == Settings.module) { + if (SONOFF_IFAN02 == my_module_type) { blink_mask &= 1; // No blinking on the fan relays Settings.flag.interlock = 0; // No interlock mode as it is already done by the microcontroller Settings.pulse_timer[1] = 0; // No pulsetimers on the fan relays @@ -1576,7 +1662,7 @@ void PublishStatus(uint8_t payload) if ((0 == payload) || (99 == payload)) { uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; - if (SONOFF_IFAN02 == Settings.module) { maxfn = 1; } + if (SONOFF_IFAN02 == my_module_type) { maxfn = 1; } stemp[0] = '\0'; for (uint8_t i = 0; i < maxfn; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%s%s\"%s\"" ), stemp, (i > 0 ? "," : ""), Settings.friendlyname[i]); @@ -1586,7 +1672,7 @@ void PublishStatus(uint8_t payload) snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%d" ), stemp2, (i > 0 ? "," : ""), Settings.switchmode[i]); } 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_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), - Settings.module +1, stemp, mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, Settings.save_data, Settings.flag.save_state, Settings.switch_topic, stemp2, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_switch_retain, Settings.flag.mqtt_sensor_retain, Settings.flag.mqtt_power_retain); + (USER_MODULE == Settings.module)?0:Settings.module +1, stemp, mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, Settings.save_data, Settings.flag.save_state, Settings.switch_topic, stemp2, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_switch_retain, Settings.flag.mqtt_sensor_retain, Settings.flag.mqtt_power_retain); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS)); } @@ -1707,7 +1793,7 @@ void MqttShowState(void) LightState(1); } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":\"%s\""), mqtt_data, GetPowerDevice(stemp1, i +1, sizeof(stemp1), Settings.flag.device_index_enable), GetStateText(bitRead(power, i))); - if (SONOFF_IFAN02 == Settings.module) { + if (SONOFF_IFAN02 == my_module_type) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_FANSPEED "\":%d"), mqtt_data, GetFanspeed()); break; } @@ -1766,7 +1852,7 @@ void PerformEverySecond(void) AddLog(LOG_LEVEL_DEBUG); } - if ((4 == uptime) && (SONOFF_IFAN02 == Settings.module)) { // Microcontroller needs 3 seconds before accepting commands + if ((4 == uptime) && (SONOFF_IFAN02 == my_module_type)) { // Microcontroller needs 3 seconds before accepting commands SetDevicePower(1, SRC_RETRY); // Sync with default power on state microcontroller being Light ON and Fan OFF SetDevicePower(power, SRC_RETRY); // Set required power on state } @@ -1922,7 +2008,7 @@ void Every250mSeconds(void) } else if (Settings.ledstate &1) { bool tstate = power; - if ((SONOFF_TOUCH == Settings.module) || (SONOFF_T11 == Settings.module) || (SONOFF_T12 == Settings.module) || (SONOFF_T13 == Settings.module)) { + if ((SONOFF_TOUCH == my_module_type) || (SONOFF_T11 == my_module_type) || (SONOFF_T12 == my_module_type) || (SONOFF_T13 == my_module_type)) { tstate = (!power) ? 1 : 0; // As requested invert signal for Touch devices to find them in the dark } SetLedPower(tstate); @@ -2157,7 +2243,7 @@ void SerialInput(void) /*-------------------------------------------------------------------------------------------*\ * Sonoff dual and ch4 19200 baud serial interface \*-------------------------------------------------------------------------------------------*/ - if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { + if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { serial_in_byte = ButtonSerial(serial_in_byte); } @@ -2202,7 +2288,7 @@ void SerialInput(void) /*-------------------------------------------------------------------------------------------*\ * Sonoff SC 19200 baud serial interface \*-------------------------------------------------------------------------------------------*/ - if (SONOFF_SC == Settings.module) { + if (SONOFF_SC == my_module_type) { 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); @@ -2250,10 +2336,12 @@ void GpioInit(void) { uint8_t mpin; - if (Settings.module >= MAXMODULE) { + if ((Settings.module >= MAXMODULE) && (Settings.module < USER_MODULE)) { Settings.module = MODULE; Settings.last_module = MODULE; } + SetModuleType(); + if (Settings.module != Settings.last_module) { baudrate = APP_BAUDRATE; } @@ -2266,15 +2354,18 @@ void GpioInit(void) } if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < GPIO_USER)) { my_module.io[i] = def_gp.io[i]; + if (USER_MODULE == Settings.module) { + Settings.my_gp.io[i] = def_gp.io[i]; // Copy user template settings + } } } my_module_flag = ModuleFlag(); - for (uint8_t i = 0; i < GPIO_MAX; i++) { + for (uint16_t i = 0; i < GPIO_MAX; i++) { pin[i] = 99; } for (uint8_t i = 0; i < sizeof(my_module.io); i++) { - mpin = ValidGPIO(i, my_module.io[i]); + mpin = ValidPin(i, my_module.io[i]); // snprintf_P(log_data, sizeof(log_data), PSTR("DBG: gpio pin %d, mpin %d"), i, mpin); // AddLog(LOG_LEVEL_DEBUG); @@ -2327,7 +2418,7 @@ void GpioInit(void) if (mpin) pin[mpin] = i; } - if ((2 == pin[GPIO_TXD]) || (H801 == Settings.module)) { Serial.set_tx(2); } + if ((2 == pin[GPIO_TXD]) || (H801 == my_module_type)) { Serial.set_tx(2); } analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) @@ -2335,7 +2426,7 @@ void GpioInit(void) #ifdef USE_SPI spi_flg = ((((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CS] > 14)) || (pin[GPIO_SPI_CS] < 12)) || (((pin[GPIO_SPI_DC] < 99) && (pin[GPIO_SPI_DC] > 14)) || (pin[GPIO_SPI_DC] < 12))); if (spi_flg) { - for (uint8_t i = 0; i < GPIO_MAX; i++) { + for (uint16_t i = 0; i < GPIO_MAX; i++) { if ((pin[i] >= 12) && (pin[i] <=14)) pin[i] = 99; } my_module.io[12] = GPIO_SPI_MISO; @@ -2362,7 +2453,7 @@ void GpioInit(void) } } - if (SONOFF_BRIDGE == Settings.module) { + if (SONOFF_BRIDGE == my_module_type) { Settings.flag.mqtt_serial = 0; baudrate = 19200; } @@ -2370,34 +2461,34 @@ void GpioInit(void) if (XdrvCall(FUNC_MODULE_INIT)) { // Serviced } - else if (YTF_IR_BRIDGE == Settings.module) { + else if (YTF_IR_BRIDGE == my_module_type) { ClaimSerial(); // Stop serial loopback mode } - else if (SONOFF_DUAL == Settings.module) { + else if (SONOFF_DUAL == my_module_type) { Settings.flag.mqtt_serial = 0; devices_present = 2; baudrate = 19200; } - else if (CH4 == Settings.module) { + else if (CH4 == my_module_type) { Settings.flag.mqtt_serial = 0; devices_present = 4; baudrate = 19200; } - else if (SONOFF_SC == Settings.module) { + else if (SONOFF_SC == my_module_type) { Settings.flag.mqtt_serial = 0; devices_present = 0; baudrate = 19200; } - else if (SONOFF_BN == Settings.module) { // PWM Single color led (White) + else if (SONOFF_BN == my_module_type) { // PWM Single color led (White) light_type = LT_PWM1; } - else if (SONOFF_LED == Settings.module) { // PWM Dual color led (White warm and cold) + else if (SONOFF_LED == my_module_type) { // PWM Dual color led (White warm and cold) light_type = LT_PWM2; } - else if (AILIGHT == Settings.module) { // RGBW led + else if (AILIGHT == my_module_type) { // RGBW led light_type = LT_RGBW; } - else if (SONOFF_B1 == Settings.module) { // RGBWC led + else if (SONOFF_B1 == my_module_type) { // RGBWC led light_type = LT_RGBWC; } else { @@ -2406,7 +2497,7 @@ void GpioInit(void) if (pin[GPIO_REL1 +i] < 99) { pinMode(pin[GPIO_REL1 +i], OUTPUT); devices_present++; - if (EXS_RELAY == Settings.module) { + if (EXS_RELAY == my_module_type) { digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? 1 : 0); if (i &1) { devices_present--; } } @@ -2542,7 +2633,7 @@ void setup(void) WifiConnect(); - if (MOTOR == Settings.module) { Settings.poweronstate = POWER_ALL_ON; } // Needs always on else in limbo! + if (MOTOR == my_module_type) { Settings.poweronstate = POWER_ALL_ON; } // Needs always on else in limbo! if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { SetDevicePower(1, SRC_RESTART); } else { diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 64681ea91..6d48cded2 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -167,23 +167,26 @@ enum UserSelectablePins { GPIO_SM16716_CLK, // SM16716 CLOCK GPIO_SM16716_DAT, // SM16716 DATA GPIO_SM16716_SEL, // SM16716 SELECT + GPIO_DI, // my92x1 PWM input + GPIO_DCKI, // my92x1 CLK input + GPIO_CSE7766_TX, // CSE7766 Serial interface (S31 and Pow R2) + GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2) + GPIO_ARIRFRCV, // AliLux RF Receive input + GPIO_TXD, // Serial interface + GPIO_RXD, // Serial interface + GPIO_ROT1A, // Rotary switch1 A Pin + GPIO_ROT1B, // Rotary switch1 B Pin + GPIO_ROT2A, // Rotary switch2 A Pin + GPIO_ROT2B, // Rotary switch2 B Pin GPIO_SENSOR_END }; -// Programmer selectable GPIO functionality offset by user selectable GPIOs +// Programmer selectable GPIO functionality enum ProgramSelectablePins { - GPIO_RXD = GPIO_SENSOR_END, // Serial interface - GPIO_TXD, // Serial interface + GPIO_FIX_START = 251, GPIO_SPI_MISO, // SPI MISO library fixed pin GPIO12 GPIO_SPI_MOSI, // SPI MOSI library fixed pin GPIO13 GPIO_SPI_CLK, // SPI Clk library fixed pin GPIO14 - GPIO_DI, // my92x1 PWM input - GPIO_DCKI, // my92x1 CLK input - GPIO_ARIRFRCV, // AliLux RF Receive input - GPIO_ROT_A, // Rotary switch A Pin - GPIO_ROT_B, // Rotary switch B Pin - GPIO_CSE7766_TX, // CSE7766 Serial interface (S31 and Pow R2) - GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2) - GPIO_USER, // User configurable + GPIO_USER, // User configurable needs to be 255 GPIO_MAX }; // Text in webpage Module Parameters and commands GPIOS and GPIO @@ -233,7 +236,11 @@ const char kSensorNames[] PROGMEM = D_SENSOR_NRG_SEL "|" D_SENSOR_NRG_SEL "i|" D_SENSOR_NRG_CF1 "|" D_SENSOR_HLW_CF "|" D_SENSOR_HJL_CF "|" D_SENSOR_MCP39F5_TX "|" D_SENSOR_MCP39F5_RX "|" D_SENSOR_MCP39F5_RST "|" D_SENSOR_PN532_TX "|" D_SENSOR_PN532_RX "|" - D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT "|" D_SENSOR_SM16716_POWER + D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT "|" D_SENSOR_SM16716_POWER "|" + D_SENSOR_MY92X1_DI "|" D_SENSOR_MY92X1_DCKI "|" + D_SENSOR_CSE7766_TX "|" D_SENSOR_CSE7766_RX "|" + D_SENSOR_ARIRFRCV "|" D_SENSOR_TXD "|" D_SENSOR_RXD "|" + D_SENSOR_ROTARY "1a|" D_SENSOR_ROTARY "1b|" D_SENSOR_ROTARY "2a|" D_SENSOR_ROTARY "2b|" ; /********************************************************************************************/ @@ -311,6 +318,8 @@ enum SupportedModules { SYF05, MAXMODULE }; +#define USER_MODULE 255 + /********************************************************************************************/ #define MAX_GPIO_PIN 17 // Number of supported GPIO @@ -431,6 +440,8 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_CNTR3_NP, GPIO_CNTR4, GPIO_CNTR4_NP, + GPIO_TXD, // Serial interface + GPIO_RXD, // Serial interface #ifdef USE_I2C GPIO_I2C_SCL, // I2C SCL GPIO_I2C_SDA, // I2C SDA @@ -487,6 +498,8 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_HLW_CF, // HLW8012 CF power GPIO_HJL_CF, // HJL-01/BL0937 CF power #endif + GPIO_CSE7766_TX, // CSE7766 Serial interface (S31 and Pow R2) + GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2) #if defined(USE_ENERGY_SENSOR) && defined(USE_MCP39F501) GPIO_MCP39F5_TX, // MCP39F501 Serial interface (Shelly2) GPIO_MCP39F5_RX, // MCP39F501 Serial interface (Shelly2) @@ -558,11 +571,18 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface #endif + GPIO_DI, // my92x1 PWM input + GPIO_DCKI, // my92x1 CLK input #ifdef USE_SM16716 GPIO_SM16716_CLK, // SM16716 CLOCK GPIO_SM16716_DAT, // SM16716 DATA GPIO_SM16716_SEL, // SM16716 SELECT #endif // USE_SM16716 + GPIO_ROT1A, // Rotary switch1 A Pin + GPIO_ROT1B, // Rotary switch1 B Pin + GPIO_ROT2A, // Rotary switch2 A Pin + GPIO_ROT2B, // Rotary switch2 B Pin + GPIO_ARIRFRCV // AliLux RF Receive input }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { @@ -1832,8 +1852,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) // GPIO11 (SD_CMD Flash) - GPIO_ROT_A, // GPIO12 Rotary switch A pin - GPIO_ROT_B, // GPIO13 Rotary switch B pin + GPIO_ROT1A, // GPIO12 Rotary switch A pin + GPIO_ROT1B, // GPIO13 Rotary switch B pin 0, 0, 0, 0 }, { "SP10", // Tuya SP10 (BL0937 Energy Monitoring) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 9afa3f2b2..2c221bd1b 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0604010F +#define VERSION 0x06040110 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index b2e74addc..d915832aa 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -507,12 +507,16 @@ String PressureUnit(void) String AnyModuleName(uint8_t index) { - return FPSTR(kModules[index].name); + if (USER_MODULE == index) { + return String(Settings.user_template.name); + } else { + return FPSTR(kModules[index].name); + } } String ModuleName() { - return FPSTR(kModules[Settings.module].name); + return AnyModuleName(Settings.module); } void ModuleGpios(myio *gp) @@ -521,21 +525,22 @@ void ModuleGpios(myio *gp) memset(dest, GPIO_NONE, sizeof(myio)); uint8_t src[sizeof(mycfgio)]; - memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio)); + if (USER_MODULE == Settings.module) { +// src = Settings.user_template.gp; + memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio)); + } else { + memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio)); + } // 11 85 00 85 85 00 00 00 15 38 85 00 00 81 // AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)&src, sizeof(mycfgio)); + uint8_t j = 0; for (uint8_t i = 0; i < sizeof(mycfgio); i++) { - if (i < 6) { - dest[i] = src[i]; // GPIO00 - GPIO05 - } - else if (i < 8) { - dest[i +3] = src[i]; // GPIO09 - GPIO10 - } - else { - dest[i +4] = src[i]; // GPIO12 - GPIO16 and ADC0 - } + if (6 == i) { j = 9; } + if (8 == i) { j = 12; } + dest[j] = src[i]; + j++; } // 11 85 00 85 85 00 00 00 00 00 00 00 15 38 85 00 00 81 @@ -546,10 +551,116 @@ gpio_flag ModuleFlag() { gpio_flag flag; - memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag)); + if (USER_MODULE == Settings.module) { + flag = Settings.user_template.flag; + } else { + memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag)); + } + return flag; } +void ModuleDefault(uint8_t module) +{ + if (USER_MODULE == module) { module = WEMOS; } // Generic + Settings.user_template_base = module; + memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt)); +} + +void SetModuleType() +{ + my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module; +} + +uint8_t ValidPin(uint8_t pin, uint8_t gpio) +{ + uint8_t result = gpio; + if ((pin > 5) && (pin < 12)) { + result = GPIO_NONE; // Disable all flash pins + } + if (Settings.flag3.user_esp8285_enable) { + if ((pin == 9) || (pin == 10)) { + result = gpio; // Allow optional flash pins + } + } + return result; +} + +bool ValidGPIO(uint8_t pin, uint8_t gpio) +{ + bool result = false; + + if (USER_MODULE == Settings.module) { + result = (ValidPin(pin, gpio) > GPIO_NONE); // Allow any pin + } else { + result = (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins + } + return result; +} + +bool GetUsedInModule(uint8_t val, uint8_t *arr) +{ + int offset = 0; + + if (USER_MODULE == Settings.module) { return false; } + + if (!val) { return false; } // None + + if ((val >= GPIO_KEY1) && (val < GPIO_KEY1 + MAX_KEYS)) { + offset = (GPIO_KEY1_NP - GPIO_KEY1); + } + if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) { + offset = -(GPIO_KEY1_NP - GPIO_KEY1); + } + if ((val >= GPIO_KEY1_INV) && (val < GPIO_KEY1_INV + MAX_KEYS)) { + offset = -(GPIO_KEY1_INV - GPIO_KEY1); + } + if ((val >= GPIO_KEY1_INV_NP) && (val < GPIO_KEY1_INV_NP + MAX_KEYS)) { + offset = -(GPIO_KEY1_INV_NP - GPIO_KEY1); + } + + if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) { + offset = (GPIO_SWT1_NP - GPIO_SWT1); + } + if ((val >= GPIO_SWT1_NP) && (val < GPIO_SWT1_NP + MAX_SWITCHES)) { + offset = -(GPIO_SWT1_NP - GPIO_SWT1); + } + + if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { + offset = (GPIO_REL1_INV - GPIO_REL1); + } + if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) { + offset = -(GPIO_REL1_INV - GPIO_REL1); + } + + if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) { + offset = (GPIO_LED1_INV - GPIO_LED1); + } + if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) { + offset = -(GPIO_LED1_INV - GPIO_LED1); + } + + if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) { + offset = (GPIO_PWM1_INV - GPIO_PWM1); + } + if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) { + offset = -(GPIO_PWM1_INV - GPIO_PWM1); + } + + if ((val >= GPIO_CNTR1) && (val < GPIO_CNTR1 + MAX_COUNTERS)) { + offset = (GPIO_CNTR1_NP - GPIO_CNTR1); + } + if ((val >= GPIO_CNTR1_NP) && (val < GPIO_CNTR1_NP + MAX_COUNTERS)) { + offset = -(GPIO_CNTR1_NP - GPIO_CNTR1); + } + + for (uint8_t i = 0; i < MAX_GPIO_PIN; i++) { + if (arr[i] == val) { return true; } + if (arr[i] == val + offset) { return true; } + } + return false; +} + void SetGlobalValues(float temperature, float humidity) { global_update = uptime; @@ -701,67 +812,6 @@ int GetStateNumber(char *state_text) return state_number; } -bool GetUsedInModule(uint8_t val, uint8_t *arr) -{ - int offset = 0; - - if (!val) { return false; } // None - - if ((val >= GPIO_KEY1) && (val < GPIO_KEY1 + MAX_KEYS)) { - offset = (GPIO_KEY1_NP - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) { - offset = -(GPIO_KEY1_NP - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_INV) && (val < GPIO_KEY1_INV + MAX_KEYS)) { - offset = -(GPIO_KEY1_INV - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_INV_NP) && (val < GPIO_KEY1_INV_NP + MAX_KEYS)) { - offset = -(GPIO_KEY1_INV_NP - GPIO_KEY1); - } - - if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) { - offset = (GPIO_SWT1_NP - GPIO_SWT1); - } - if ((val >= GPIO_SWT1_NP) && (val < GPIO_SWT1_NP + MAX_SWITCHES)) { - offset = -(GPIO_SWT1_NP - GPIO_SWT1); - } - - if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { - offset = (GPIO_REL1_INV - GPIO_REL1); - } - if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) { - offset = -(GPIO_REL1_INV - GPIO_REL1); - } - - if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) { - offset = (GPIO_LED1_INV - GPIO_LED1); - } - if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) { - offset = -(GPIO_LED1_INV - GPIO_LED1); - } - - if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) { - offset = (GPIO_PWM1_INV - GPIO_PWM1); - } - if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) { - offset = -(GPIO_PWM1_INV - GPIO_PWM1); - } - - if ((val >= GPIO_CNTR1) && (val < GPIO_CNTR1 + MAX_COUNTERS)) { - offset = (GPIO_CNTR1_NP - GPIO_CNTR1); - } - if ((val >= GPIO_CNTR1_NP) && (val < GPIO_CNTR1_NP + MAX_COUNTERS)) { - offset = -(GPIO_CNTR1_NP - GPIO_CNTR1); - } - - for (uint8_t i = 0; i < MAX_GPIO_PIN; i++) { - if (arr[i] == val) { return true; } - if (arr[i] == val + offset) { return true; } - } - return false; -} - void SetSerialBaudrate(int baudrate) { Settings.baudrate = baudrate / 1200; @@ -822,15 +872,6 @@ void ShowSource(int source) } } -uint8_t ValidGPIO(uint8_t pin, uint8_t gpio) -{ - uint8_t result = gpio; - if ((WEMOS == Settings.module) && (!Settings.flag3.user_esp8285_enable)) { - if ((pin == 9) || (pin == 10)) { result = GPIO_NONE; } // Disable possible flash GPIO9 and GPIO10 - } - return result; -} - /*********************************************************************************************\ * Sleep aware time scheduler functions borrowed from ESPEasy \*********************************************************************************************/ diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index 4ed30b469..b0e6e695c 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -106,7 +106,7 @@ void ButtonHandler(void) button = NOT_PRESSED; button_present = 0; - if (!button_index && ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module))) { + if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { 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); @@ -131,7 +131,7 @@ void ButtonHandler(void) if (XdrvCall(FUNC_BUTTON_PRESSED)) { // Serviced } - else if (SONOFF_4CHPRO == Settings.module) { + else if (SONOFF_4CHPRO == my_module_type) { if (holdbutton[button_index]) { holdbutton[button_index]--; } bool button_pressed = false; @@ -202,14 +202,14 @@ void ButtonHandler(void) if (!restart_flag && !holdbutton[button_index] && (multipress[button_index] > 0) && (multipress[button_index] < MAX_BUTTON_COMMANDS +3)) { bool single_press = false; if (multipress[button_index] < 3) { // Single or Double press - if ((SONOFF_DUAL_R2 == Settings.module) || (SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { + if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { single_press = true; } else { single_press = (Settings.flag.button_swap +1 == multipress[button_index]); multipress[button_index] = 1; } } - if ((MI_DESK_LAMP == Settings.module) && (button_index == 0) && (rotary_changed) && (light_power)) { + if ((MI_DESK_LAMP == my_module_type) && (button_index == 0) && (rotary_changed) && (light_power)) { rotary_changed = 0; // Color temp changed, no need to turn of the light } else { if (single_press && SendKey(0, button_index + multipress[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set diff --git a/sonoff/support_rotary.ino b/sonoff/support_rotary.ino index 726f45379..c8178586a 100644 --- a/sonoff/support_rotary.ino +++ b/sonoff/support_rotary.ino @@ -42,8 +42,8 @@ void update_position(void) */ s = rotary_state & 3; - if (digitalRead(pin[GPIO_ROT_A])) s |= 4; - if (digitalRead(pin[GPIO_ROT_B])) s |= 8; + if (digitalRead(pin[GPIO_ROT1A])) s |= 4; + if (digitalRead(pin[GPIO_ROT1B])) s |= 8; switch (s) { case 0: case 5: case 10: case 15: break; @@ -61,7 +61,7 @@ void update_position(void) void update_rotary(void) { - if (MI_DESK_LAMP == Settings.module){ + if (MI_DESK_LAMP == my_module_type){ if (light_power) { update_position(); } @@ -71,20 +71,20 @@ void update_rotary(void) void RotaryInit(void) { rotaries_found = 0; - if ((pin[GPIO_ROT_A] < 99) && (pin[GPIO_ROT_B] < 99)) { + if ((pin[GPIO_ROT1A] < 99) && (pin[GPIO_ROT1B] < 99)) { rotaries_found++; - pinMode(pin[GPIO_ROT_A], INPUT_PULLUP); - pinMode(pin[GPIO_ROT_B], INPUT_PULLUP); + pinMode(pin[GPIO_ROT1A], INPUT_PULLUP); + pinMode(pin[GPIO_ROT1B], INPUT_PULLUP); // GPIO6-GPIO11 are typically used to interface with the flash memory IC on // most esp8266 modules, so we should avoid adding interrupts to these pins. - if ((pin[GPIO_ROT_A] < 6) || (pin[GPIO_ROT_A] > 11)) { - attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT_A]), update_rotary, CHANGE); + if ((pin[GPIO_ROT1A] < 6) || (pin[GPIO_ROT1A] > 11)) { + attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1A]), update_rotary, CHANGE); interrupts_in_use++; } - if ((pin[GPIO_ROT_B] < 6) || (pin[GPIO_ROT_B] > 11)) { - attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT_B]), update_rotary, CHANGE); + if ((pin[GPIO_ROT1B] < 6) || (pin[GPIO_ROT1B] > 11)) { + attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1B]), update_rotary, CHANGE); interrupts_in_use++; } } @@ -103,7 +103,7 @@ void RotaryHandler(void) noInterrupts(); } if (rotary_last_position != rotary_position) { - if (MI_DESK_LAMP == Settings.module) { // Mi Desk lamp + if (MI_DESK_LAMP == my_module_type) { // Mi Desk lamp if (holdbutton[0]) { rotary_changed = 1; // button1 is pressed: set color temperature diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 449ae6e35..756805425 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -640,7 +640,7 @@ void HandleRoot(void) } page += FPSTR(HTTP_TABLE100); page += F(""); - if (SONOFF_IFAN02 == Settings.module) { + if (SONOFF_IFAN02 == my_module_type) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); page += mqtt_data; for (uint8_t i = 0; i < MAX_FAN_SPEED; i++) { @@ -658,7 +658,7 @@ void HandleRoot(void) } page += F(""); } - if (SONOFF_BRIDGE == Settings.module) { + if (SONOFF_BRIDGE == my_module_type) { page += FPSTR(HTTP_TABLE100); page += F(""); uint8_t idx = 0; @@ -699,7 +699,7 @@ void HandleAjaxStatusRefresh(void) if (strlen(tmp)) { ShowWebSource(SRC_WEBGUI); uint8_t device = atoi(tmp); - if (SONOFF_IFAN02 == Settings.module) { + if (SONOFF_IFAN02 == my_module_type) { if (device < 2) { ExecuteCommandPower(1, POWER_TOGGLE, SRC_IGNORE); } else { @@ -739,7 +739,7 @@ void HandleAjaxStatusRefresh(void) if (devices_present) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{t}"), mqtt_data); uint8_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32; - if (SONOFF_IFAN02 == Settings.module) { + if (SONOFF_IFAN02 == my_module_type) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_STATE, mqtt_data, 36, (bitRead(power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(power, 0))); uint8_t fanspeed = GetFanspeed(); @@ -815,11 +815,25 @@ void HandleModuleConfiguration(void) if (WebServer->hasArg("m")) { String page = ""; - for (uint8_t i = 0; i < MAXMODULE; i++) { +/* + for (uint8_t i = 0; i < MAXMODULE; i++) { // "}1'%d'>%s (%d)}2" - "}1'0'>Sonoff Basic (1)}2" midx = pgm_read_byte(kModuleNiceList + i); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE3, midx, AnyModuleName(midx).c_str(), midx +1); page += mqtt_data; } +*/ + uint8_t vidx = 0; + for (uint8_t i = 0; i <= MAXMODULE; i++) { // "}1'%d'>%s (%d)}2" - "}1'255'>UserTemplate (0)}2" - "}1'0'>Sonoff Basic (1)}2" + if (0 == i) { + midx = USER_MODULE; + vidx = 0; + } else { + midx = pgm_read_byte(kModuleNiceList + i -1); + vidx = midx +1; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE3, midx, AnyModuleName(midx).c_str(), vidx); + page += mqtt_data; + } WebServer->send(200, FPSTR(HDR_CTYPE_PLAIN), page); return; } @@ -844,7 +858,7 @@ void HandleModuleConfiguration(void) page += FPSTR(HTTP_SCRIPT_MODULE1); page.replace(F("}4"), String(Settings.module)); for (uint8_t i = 0; i < sizeof(cmodule); i++) { - if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { + if (ValidGPIO(i, cmodule.io[i])) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,%d);"), my_module.io[i], i); // g0 - g16 page += mqtt_data; } @@ -862,10 +876,10 @@ void HandleModuleConfiguration(void) page += F("
"); for (uint8_t i = 0; i < sizeof(cmodule); i++) { - if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { + if (ValidGPIO(i, cmodule.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), - (WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "ESP8285" :(10==i)? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); + (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "ESP8285" :(10==i)? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); page += mqtt_data; } } @@ -884,6 +898,7 @@ void ModuleSaveSettings(void) uint8_t new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); Settings.last_module = Settings.module; Settings.module = new_module; + SetModuleType(); if (Settings.last_module == new_module) { if (my_module_flag.pullup) { Settings.flag3.no_pullup = WebServer->hasArg("b1"); @@ -894,9 +909,9 @@ void ModuleSaveSettings(void) String gpios = ""; for (uint8_t i = 0; i < sizeof(cmodule); i++) { if (Settings.last_module != new_module) { - Settings.my_gp.io[i] = 0; + Settings.my_gp.io[i] = GPIO_NONE; } else { - if (GPIO_USER == ValidGPIO(i, cmodule.io[i])) { + if (ValidGPIO(i, cmodule.io[i])) { snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), i); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); @@ -1152,7 +1167,7 @@ void HandleOtherConfiguration(void) page.replace(F("{r1"), (Settings.flag.mqtt_enabled) ? F(" checked") : F("")); uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; - if (SONOFF_IFAN02 == Settings.module) { maxfn = 1; } + if (SONOFF_IFAN02 == my_module_type) { maxfn = 1; } for (uint8_t i = 0; i < maxfn; i++) { page += FPSTR(HTTP_FORM_OTHER2); page.replace(F("{1"), String(i +1)); @@ -1320,7 +1335,7 @@ void HandleInformation(void) 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; - if (SONOFF_IFAN02 == Settings.module) { maxfn = 1; } + if (SONOFF_IFAN02 == my_module_type) { maxfn = 1; } for (uint8_t i = 0; i < maxfn; i++) { func += F("}1" D_FRIENDLY_NAME " "); func += i +1; func += F("}2"); func += Settings.friendlyname[i]; } @@ -1570,7 +1585,7 @@ void HandleUploadLoop(void) } else { #ifdef USE_RF_FLASH - if ((SONOFF_BRIDGE == Settings.module) && (upload.buf[0] == ':')) { // Check if this is a RF bridge FW file + if ((SONOFF_BRIDGE == my_module_type) && (upload.buf[0] == ':')) { // Check if this is a RF bridge FW file Update.end(); // End esp8266 update session upload_file_type = UPL_EFM8BB1; diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 5abc4f329..8440b5cd6 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -342,7 +342,7 @@ void MqttPublishPowerState(uint8_t device) if ((device < 1) || (device > devices_present)) { device = 1; } - if ((SONOFF_IFAN02 == Settings.module) && (device > 1)) { + if ((SONOFF_IFAN02 == my_module_type) && (device > 1)) { if (GetFanspeed() < MAX_FAN_SPEED) { // 4 occurs when fanspeed is 3 and RC button 2 is pressed #ifdef USE_DOMOTICZ DomoticzUpdateFanState(); // RC Button feedback @@ -435,7 +435,7 @@ void MqttConnected(void) MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); for (uint8_t i = 1; i <= devices_present; i++) { MqttPublishPowerState(i); - if (SONOFF_IFAN02 == Settings.module) { break; } // Report status of light relay only + if (SONOFF_IFAN02 == my_module_type) { break; } // Report status of light relay only } if (Settings.tele_period) { tele_period = Settings.tele_period -9; } // Enable TelePeriod in 9 seconds rules_flag.system_boot = 1; diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 0c5c3cc58..0b027335b 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -487,7 +487,7 @@ void LightInit(void) pinMode(pin[GPIO_PWM1 +i], OUTPUT); } } - if (SONOFF_LED == Settings.module) { // Fix Sonoff Led instabilities + if (SONOFF_LED == my_module_type) { // Fix Sonoff Led instabilities if (!my_module.io[4]) { pinMode(4, OUTPUT); // Stop floating outputs digitalWrite(4, LOW); @@ -578,7 +578,7 @@ void LightSetColorTemp(uint16_t ct) } uint16_t icold = (100 * (347 - my_ct)) / 136; uint16_t iwarm = (100 * my_ct) / 136; - if (PHILIPS == Settings.module) { + if (PHILIPS == my_module_type) { // Xiaomi Philips bulbs follow a different scheme: // channel 0=intensity, channel2=temperature Settings.light_color[1] = (uint8_t)icold; @@ -614,7 +614,7 @@ void LightSetDimmer(uint8_t myDimmer) { float temp; - if (PHILIPS == Settings.module) { + if (PHILIPS == my_module_type) { // Xiaomi Philips bulbs use two PWM channels with a different scheme: float dimmer = 100 / (float)myDimmer; temp = (float)Settings.light_color[0] / dimmer; // channel 1 is intensity diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 6a38b2854..c4b4d209b 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -570,7 +570,7 @@ bool Xdrv06(uint8_t function) { bool result = false; - if (SONOFF_BRIDGE == Settings.module) { + if (SONOFF_BRIDGE == my_module_type) { switch (function) { case FUNC_INIT: SonoffBridgeInit(); diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 416a0cd9e..2e4611246 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -100,7 +100,7 @@ void MqttPublishDomoticzPowerState(uint8_t device) if (Settings.flag.mqtt_enabled) { if ((device < 1) || (device > devices_present)) { device = 1; } if (Settings.domoticz_relay_idx[device -1]) { - if ((SONOFF_IFAN02 == Settings.module) && (device > 1)) { + if ((SONOFF_IFAN02 == my_module_type) && (device > 1)) { // Fan handled by MqttPublishDomoticzFanState } else { char svalue[8]; // Dimmer value @@ -129,7 +129,7 @@ void DomoticzMqttUpdate(void) if (domoticz_update_timer <= 0) { domoticz_update_timer = Settings.domoticz_update_timer; for (uint8_t i = 1; i <= devices_present; i++) { - if ((SONOFF_IFAN02 == Settings.module) && (i > 1)) { + if ((SONOFF_IFAN02 == my_module_type) && (i > 1)) { MqttPublishDomoticzFanState(); break; } else { @@ -215,7 +215,7 @@ bool DomoticzMqttData(void) if (idx == Settings.domoticz_relay_idx[i]) { bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); - if ((SONOFF_IFAN02 == Settings.module) && (1 == i)) { // Idx 2 is fanspeed + if ((SONOFF_IFAN02 == my_module_type) && (1 == i)) { // Idx 2 is fanspeed uint8_t svalue = 0; if (domoticz.containsKey("svalue1")) { svalue = domoticz["svalue1"]; @@ -475,7 +475,7 @@ void HandleDomoticzConfiguration(void) page.replace("{4", String((int)Settings.domoticz_switch_idx[i])); } page.replace("{1", String(i +1)); - if ((SONOFF_IFAN02 == Settings.module) && (1 == i)) { break; } + if ((SONOFF_IFAN02 == my_module_type) && (1 == i)) { break; } } for (int i = 0; i < DZ_MAX_SENSORS; i++) { page += FPSTR(HTTP_FORM_DOMOTICZ_SENSOR); diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index b6e6af299..d815eacb2 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -369,7 +369,7 @@ void HAssAnnounceButtons(void) uint8_t button_present = 0; uint8_t toggle = 1; - if (!button_index && ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module))) { + if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { button_present = 1; } else { if (pin[GPIO_KEY1 + button_index] < 99) { diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index dbac0d644..d2eca8383 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -402,7 +402,7 @@ bool Xdrv16(uint8_t function) { bool result = false; - if (TUYA_DIMMER == Settings.module) { + if (TUYA_DIMMER == my_module_type) { switch (function) { case FUNC_MODULE_INIT: result = TuyaModuleSelected(); diff --git a/sonoff/xdrv_18_armtronix_dimmers.ino b/sonoff/xdrv_18_armtronix_dimmers.ino index f27f37fc8..a22a5a973 100644 --- a/sonoff/xdrv_18_armtronix_dimmers.ino +++ b/sonoff/xdrv_18_armtronix_dimmers.ino @@ -173,7 +173,7 @@ bool Xdrv18(uint8_t function) { bool result = false; - if (ARMTRONIX_DIMMERS == Settings.module) { + if (ARMTRONIX_DIMMERS == my_module_type) { switch (function) { case FUNC_MODULE_INIT: result = ArmtronixModuleSelected(); diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index ce8339502..baa4e5dfa 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -229,7 +229,7 @@ bool Xdrv19(uint8_t function) { bool result = false; - if (PS_16_DZ == Settings.module) { + if (PS_16_DZ == my_module_type) { switch (function) { case FUNC_MODULE_INIT: result = PS16DZModuleSelected(); diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index 5f3695292..4d881bd01 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -158,7 +158,7 @@ bool Xsns04(uint8_t function) { bool result = false; - if (SONOFF_SC == Settings.module) { + if (SONOFF_SC == my_module_type) { switch (function) { case FUNC_INIT: SonoffScInit(); From 86a56b7b7174b65b618839f028bb12b290a7a872 Mon Sep 17 00:00:00 2001 From: Kevin Baluha Date: Mon, 11 Feb 2019 11:22:14 -0700 Subject: [PATCH 0991/2222] verify that tsl2561 works with new ads1115 --- sonoff/xsns_16_tsl2561.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index f7777cf18..ab923f2e8 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -67,8 +67,8 @@ void Tsl2561Detect(void) uint8_t id; if (I2cDevice(0x29) || I2cDevice(0x39) || I2cDevice(0x49)) { - if (!Tsl.id(id)) return; Tsl.begin(); + if (!Tsl.id(id)) return; if (Tsl.on()) { tsl2561_type = 1; snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, tsl2561_types, Tsl.address(), id); From 9dc445f949ea11de69bc9af17ff31b465073c74b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 11 Feb 2019 21:30:30 +0100 Subject: [PATCH 0992/2222] Update xdsp_01_lcd.ino --- sonoff/xdsp_01_lcd.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdsp_01_lcd.ino b/sonoff/xdsp_01_lcd.ino index e0b72618f..8a37342a3 100644 --- a/sonoff/xdsp_01_lcd.ino +++ b/sonoff/xdsp_01_lcd.ino @@ -104,7 +104,7 @@ void LcdCenter(uint8_t row, char* txt) int len = strlen(txt); int offset = 0; if (len >= Settings.display_cols[0]) { - len = Settings.display_cols[0] + len = Settings.display_cols[0]; } else { offset = (Settings.display_cols[0] - len) / 2; } From c05e42f56371e79faf2a76c5961854d7ebf2e337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20R=2E=20Weimar?= Date: Tue, 12 Feb 2019 11:22:46 +0100 Subject: [PATCH 0993/2222] Changed ws2812 clock to local time instead of UTC --- sonoff/xplg_ws2812.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/xplg_ws2812.ino b/sonoff/xplg_ws2812.ino index ab4ba1c35..e7eb16dd8 100644 --- a/sonoff/xplg_ws2812.ino +++ b/sonoff/xplg_ws2812.ino @@ -170,7 +170,8 @@ void Ws2812Clock(void) Ws2812UpdateHand((RtcTime.second * 1000) / clksize, WS_SECOND); Ws2812UpdateHand((RtcTime.minute * 1000) / clksize, WS_MINUTE); - Ws2812UpdateHand(((RtcTime.hour % 12) * (5000 / clksize)) + ((RtcTime.minute * 1000) / (12 * clksize)), WS_HOUR); + uint32_t local_hour = (LocalTime()/3600)%12; // RtcTime.hour is UTC timezone, not local. + Ws2812UpdateHand(((local_hour % 12) * (5000 / clksize)) + ((RtcTime.minute * 1000) / (12 * clksize)), WS_HOUR); if (Settings.ws_color[WS_MARKER][WS_RED] + Settings.ws_color[WS_MARKER][WS_GREEN] + Settings.ws_color[WS_MARKER][WS_BLUE]) { for (uint8_t i = 0; i < 12; i++) { Ws2812UpdateHand((i * 5000) / clksize, WS_MARKER); From 567bc936233a1e6e81f7100629a3391925e44ee6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Feb 2019 11:55:47 +0100 Subject: [PATCH 0994/2222] Add Template GUI update Initial support for online template change using command Template or GUI Configure Other (#5177) --- sonoff/_changelog.ino | 2 +- sonoff/language/bg-BG.h | 1 + sonoff/language/cs-CZ.h | 1 + sonoff/language/de-DE.h | 1 + sonoff/language/el-GR.h | 1 + sonoff/language/en-GB.h | 1 + sonoff/language/es-AR.h | 1 + sonoff/language/fr-FR.h | 1 + sonoff/language/he-HE.h | 1 + sonoff/language/hu-HU.h | 1 + sonoff/language/it-IT.h | 1 + sonoff/language/nl-NL.h | 1 + sonoff/language/pl-PL.h | 1 + sonoff/language/pt-BR.h | 1 + sonoff/language/pt-PT.h | 1 + sonoff/language/ru-RU.h | 1 + sonoff/language/sk-SK.h | 1 + sonoff/language/sv-SE.h | 1 + sonoff/language/tr-TR.h | 1 + sonoff/language/uk-UK.h | 1 + sonoff/language/zh-CN.h | 1 + sonoff/language/zh-TW.h | 1 + sonoff/sonoff.ino | 13 +- sonoff/support.ino | 349 +++++++++++++++++------------------ sonoff/xdrv_01_webserver.ino | 14 +- 25 files changed, 207 insertions(+), 192 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 12e639ddc..371cbeb7f 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,5 @@ /* 6.4.1.16 20190211 - * Initial support for online template change using command Template (#5177) + * Initial support for online template change using command Template or GUI Configure Other (#5177) * * 6.4.1.15 20190208 * Change image name BE_MINIMAL to FIRMWARE_MINIMAL (#5106) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 176d45fb9..da1636422 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Период на телеметрия" #define D_OTHER_PARAMETERS "Други параметри" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Парола на уеб администратора" #define D_MQTT_ENABLE "Активиране на MQTT" #define D_FRIENDLY_NAME "Приятелско име" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 6f298912d..17d2df484 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Interval telemetrie" #define D_OTHER_PARAMETERS "Další nastavení" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora" #define D_MQTT_ENABLE "MQTT aktivní" #define D_FRIENDLY_NAME "Friendly Name" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index a71b01406..335a2892f 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Telemetrieperiode" #define D_OTHER_PARAMETERS "Sonstige Einstellungen" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Passwort für Web Oberfläche" #define D_MQTT_ENABLE "MQTT aktivieren" #define D_FRIENDLY_NAME "Name [friendly name]" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 316421146..3775135b5 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Περίοδος τηλεμετρίας" #define D_OTHER_PARAMETERS "Άλλες παράμετροι" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Κωδικός διαχειριστή" #define D_MQTT_ENABLE "Ενεργοποίηση MQTT" #define D_FRIENDLY_NAME "Φιλική ονομασία" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 156117bac..587f8c0f2 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Telemetry period" #define D_OTHER_PARAMETERS "Other parameters" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Web Admin Password" #define D_MQTT_ENABLE "MQTT enable" #define D_FRIENDLY_NAME "Friendly Name" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 68bacd865..4a4f7d2c6 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Período de Telemetría" #define D_OTHER_PARAMETERS "Otros parámetros" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Clave Administrador Web" #define D_MQTT_ENABLE "Habilitar MQTT" #define D_FRIENDLY_NAME "Nombre Amigable" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 0e0a9ed99..4b30de366 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Période télémétrie" #define D_OTHER_PARAMETERS "Autres paramètres" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Mot de passe Web Admin" #define D_MQTT_ENABLE "MQTT activé" #define D_FRIENDLY_NAME "Surnom" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 23e2f784a..6fc333a7b 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Telemetry period" #define D_OTHER_PARAMETERS "פרמטרים שונים" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "סיסמת מנהל - אתר" #define D_MQTT_ENABLE "MQTT אפשר" #define D_FRIENDLY_NAME "שם ידידותי" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 8a093ccb3..43e6a51db 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Telemetria (mp.)" #define D_OTHER_PARAMETERS "Egyéb beállítások" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Web admin jelszó" #define D_MQTT_ENABLE "MQTT engedélyezése" #define D_FRIENDLY_NAME "Név" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 411087ea3..ec1e57aba 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Periodo Telemetria" #define D_OTHER_PARAMETERS "Altri parametri" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Password Amministratore Web" #define D_MQTT_ENABLE "Abilita MQTT" #define D_FRIENDLY_NAME "Nome confidenziale" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index a5de69158..a27c76720 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Telemetry periode" #define D_OTHER_PARAMETERS "Overige parameters" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Web Admin Wachtwoord" #define D_MQTT_ENABLE "MQTT ingeschakeld" #define D_FRIENDLY_NAME "Beschrijvende naam" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index a501ac2fd..cf68a65b4 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Okres telemetrii" #define D_OTHER_PARAMETERS "Inne parametry" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Hasło administratora Web" #define D_MQTT_ENABLE "MQTT aktywne" #define D_FRIENDLY_NAME "Twoja nazwa" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index f94c0724b..4bc29d00f 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Período de telemetria" #define D_OTHER_PARAMETERS "Outros parâmetros" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin" #define D_MQTT_ENABLE "MQTT habilitado" #define D_FRIENDLY_NAME "Nome amigável" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 9f5516661..3ad605076 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Periodo de Telemetria" #define D_OTHER_PARAMETERS "Outros parametros" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Palavra Chave de WEB Admin" #define D_MQTT_ENABLE "MQTT habilitado" #define D_FRIENDLY_NAME "Nome amigável" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index ec8ef8543..908e3f2c8 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Период телеметрии" #define D_OTHER_PARAMETERS "Параметры Прочие" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Пароль Web администратора" #define D_MQTT_ENABLE "MQTT активен" #define D_FRIENDLY_NAME "Дружественное Имя" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 6be3edf86..42f398a99 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Interval telemetrie" #define D_OTHER_PARAMETERS "Ostatné nastavenia" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora" #define D_MQTT_ENABLE "MQTT aktívne" #define D_FRIENDLY_NAME "Friendly Name" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index ec0c9bc98..088238d37 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Telemetriperiod" #define D_OTHER_PARAMETERS "Andra parametrar" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Webbadmin-lösenord" #define D_MQTT_ENABLE "MQTT aktivera" #define D_FRIENDLY_NAME "Läsbart namn" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index f41f89f5a..73ca99fb5 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Telemetri peryodu" #define D_OTHER_PARAMETERS "Diğer parametreler" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Web Yönetici Şifresi" #define D_MQTT_ENABLE "MQTT aktif" #define D_FRIENDLY_NAME "Kullanıcı Dostu İsim" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index c571a1593..f6c080c1e 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "Період телеметрії" #define D_OTHER_PARAMETERS "Параметри Інше" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "Гасло Web адміністратора" #define D_MQTT_ENABLE "MQTT активний" #define D_FRIENDLY_NAME "Дружнє Ім'я" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 50804d307..646db7a91 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "上报周期" #define D_OTHER_PARAMETERS "其他设置" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "WEB 管理密码" #define D_MQTT_ENABLE "启用MQTT" #define D_FRIENDLY_NAME "昵称" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 46527a789..22bec6b99 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -288,6 +288,7 @@ #define D_TELEMETRY_PERIOD "上報周期" #define D_OTHER_PARAMETERS "其他設置" +#define D_TEMPLATE "Template" #define D_WEB_ADMIN_PASSWORD "WEB管理密碼" #define D_MQTT_ENABLE "啟用MQTT" #define D_FRIENDLY_NAME "昵稱" diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index f496b82e6..34c422d20 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -952,7 +952,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) mqtt_data[0] = '\0'; } else if (CMND_TEMPLATE == command_code) { - // {"NAME":"Generic","GPIO":[17,254,29,254,7,254,254,254,138,254,139,254,254],"FLAG":1,"TYPE":255} + // {"NAME":"Generic","GPIO":[17,254,29,254,7,254,254,254,138,254,139,254,254],"FLAG":1,"BASE":255} bool error = false; if (!strstr(dataBuf, "{")) { // If no JSON it must be parameter bool update = false; @@ -1021,16 +1021,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (USER_MODULE == Settings.module) { restart_flag = 2; } } } - if (!error) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); - for (uint8_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", Settings.user_template.gp.io[i]); - } -// snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":\"%d (%s)\"}"), -// mqtt_data, Settings.user_template.flag, Settings.user_template_base +1, AnyModuleName(Settings.user_template_base).c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), - mqtt_data, Settings.user_template.flag, Settings.user_template_base +1); - } + if (!error) { TemplateJson(); } } else if ((CMND_PWM == command_code) && pwm_present && (index > 0) && (index <= MAX_PWMS)) { if ((payload >= 0) && (payload <= Settings.pwm_range) && (pin[GPIO_PWM1 + index -1] < 99)) { diff --git a/sonoff/support.ino b/sonoff/support.ino index d915832aa..c728d28eb 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -305,27 +305,6 @@ char* UpperCase_P(char* dest, const char* source) return dest; } -/* -char* LTrim(char* p) -{ - while ((*p != '\0') && (isblank(*p))) { - p++; // Trim leading spaces - } - return p; -} - -char* RTrim(char* p) -{ - char* q = p + strlen(p) -1; - while ((q >= p) && (isblank(*q))) { - q--; // Trim trailing spaces - } - q++; - *q = '\0'; - return p; -} -*/ - char* Trim(char* p) { while ((*p != '\0') && isblank(*p)) { p++; } // Trim leading spaces @@ -505,162 +484,6 @@ String PressureUnit(void) return (Settings.flag.pressure_conversion) ? String(D_UNIT_MILLIMETER_MERCURY) : String(D_UNIT_PRESSURE); } -String AnyModuleName(uint8_t index) -{ - if (USER_MODULE == index) { - return String(Settings.user_template.name); - } else { - return FPSTR(kModules[index].name); - } -} - -String ModuleName() -{ - return AnyModuleName(Settings.module); -} - -void ModuleGpios(myio *gp) -{ - uint8_t *dest = (uint8_t *)gp; - memset(dest, GPIO_NONE, sizeof(myio)); - - uint8_t src[sizeof(mycfgio)]; - if (USER_MODULE == Settings.module) { -// src = Settings.user_template.gp; - memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio)); - } else { - memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio)); - } - // 11 85 00 85 85 00 00 00 15 38 85 00 00 81 - -// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)&src, sizeof(mycfgio)); - - uint8_t j = 0; - for (uint8_t i = 0; i < sizeof(mycfgio); i++) { - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - dest[j] = src[i]; - j++; - } - // 11 85 00 85 85 00 00 00 00 00 00 00 15 38 85 00 00 81 - -// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)gp, sizeof(myio)); -} - -gpio_flag ModuleFlag() -{ - gpio_flag flag; - - if (USER_MODULE == Settings.module) { - flag = Settings.user_template.flag; - } else { - memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag)); - } - - return flag; -} - -void ModuleDefault(uint8_t module) -{ - if (USER_MODULE == module) { module = WEMOS; } // Generic - Settings.user_template_base = module; - memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt)); -} - -void SetModuleType() -{ - my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module; -} - -uint8_t ValidPin(uint8_t pin, uint8_t gpio) -{ - uint8_t result = gpio; - if ((pin > 5) && (pin < 12)) { - result = GPIO_NONE; // Disable all flash pins - } - if (Settings.flag3.user_esp8285_enable) { - if ((pin == 9) || (pin == 10)) { - result = gpio; // Allow optional flash pins - } - } - return result; -} - -bool ValidGPIO(uint8_t pin, uint8_t gpio) -{ - bool result = false; - - if (USER_MODULE == Settings.module) { - result = (ValidPin(pin, gpio) > GPIO_NONE); // Allow any pin - } else { - result = (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins - } - return result; -} - -bool GetUsedInModule(uint8_t val, uint8_t *arr) -{ - int offset = 0; - - if (USER_MODULE == Settings.module) { return false; } - - if (!val) { return false; } // None - - if ((val >= GPIO_KEY1) && (val < GPIO_KEY1 + MAX_KEYS)) { - offset = (GPIO_KEY1_NP - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) { - offset = -(GPIO_KEY1_NP - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_INV) && (val < GPIO_KEY1_INV + MAX_KEYS)) { - offset = -(GPIO_KEY1_INV - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_INV_NP) && (val < GPIO_KEY1_INV_NP + MAX_KEYS)) { - offset = -(GPIO_KEY1_INV_NP - GPIO_KEY1); - } - - if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) { - offset = (GPIO_SWT1_NP - GPIO_SWT1); - } - if ((val >= GPIO_SWT1_NP) && (val < GPIO_SWT1_NP + MAX_SWITCHES)) { - offset = -(GPIO_SWT1_NP - GPIO_SWT1); - } - - if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { - offset = (GPIO_REL1_INV - GPIO_REL1); - } - if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) { - offset = -(GPIO_REL1_INV - GPIO_REL1); - } - - if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) { - offset = (GPIO_LED1_INV - GPIO_LED1); - } - if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) { - offset = -(GPIO_LED1_INV - GPIO_LED1); - } - - if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) { - offset = (GPIO_PWM1_INV - GPIO_PWM1); - } - if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) { - offset = -(GPIO_PWM1_INV - GPIO_PWM1); - } - - if ((val >= GPIO_CNTR1) && (val < GPIO_CNTR1 + MAX_COUNTERS)) { - offset = (GPIO_CNTR1_NP - GPIO_CNTR1); - } - if ((val >= GPIO_CNTR1_NP) && (val < GPIO_CNTR1_NP + MAX_COUNTERS)) { - offset = -(GPIO_CNTR1_NP - GPIO_CNTR1); - } - - for (uint8_t i = 0; i < MAX_GPIO_PIN; i++) { - if (arr[i] == val) { return true; } - if (arr[i] == val + offset) { return true; } - } - return false; -} - void SetGlobalValues(float temperature, float humidity) { global_update = uptime; @@ -872,6 +695,178 @@ void ShowSource(int source) } } +/*********************************************************************************************\ + * GPIO Module and Template management +\*********************************************************************************************/ + +String AnyModuleName(uint8_t index) +{ + if (USER_MODULE == index) { + return String(Settings.user_template.name); + } else { + return FPSTR(kModules[index].name); + } +} + +String ModuleName() +{ + return AnyModuleName(Settings.module); +} + +void ModuleGpios(myio *gp) +{ + uint8_t *dest = (uint8_t *)gp; + memset(dest, GPIO_NONE, sizeof(myio)); + + uint8_t src[sizeof(mycfgio)]; + if (USER_MODULE == Settings.module) { +// src = Settings.user_template.gp; + memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio)); + } else { + memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio)); + } + // 11 85 00 85 85 00 00 00 15 38 85 00 00 81 + +// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)&src, sizeof(mycfgio)); + + uint8_t j = 0; + for (uint8_t i = 0; i < sizeof(mycfgio); i++) { + if (6 == i) { j = 9; } + if (8 == i) { j = 12; } + dest[j] = src[i]; + j++; + } + // 11 85 00 85 85 00 00 00 00 00 00 00 15 38 85 00 00 81 + +// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)gp, sizeof(myio)); +} + +gpio_flag ModuleFlag() +{ + gpio_flag flag; + + if (USER_MODULE == Settings.module) { + flag = Settings.user_template.flag; + } else { + memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag)); + } + + return flag; +} + +void ModuleDefault(uint8_t module) +{ + if (USER_MODULE == module) { module = WEMOS; } // Generic + Settings.user_template_base = module; + memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt)); +} + +void SetModuleType() +{ + my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module; +} + +uint8_t ValidPin(uint8_t pin, uint8_t gpio) +{ + uint8_t result = gpio; + if ((pin > 5) && (pin < 12)) { + result = GPIO_NONE; // Disable all flash pins + } + if (Settings.flag3.user_esp8285_enable) { + if ((pin == 9) || (pin == 10)) { + result = gpio; // Allow optional flash pins + } + } + return result; +} + +bool ValidGPIO(uint8_t pin, uint8_t gpio) +{ + bool result = false; + + if (USER_MODULE == Settings.module) { + result = (ValidPin(pin, gpio) > GPIO_NONE); // Allow any pin + } else { + result = (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins + } + return result; +} + +bool GetUsedInModule(uint8_t val, uint8_t *arr) +{ + int offset = 0; + + if (USER_MODULE == Settings.module) { return false; } + + if (!val) { return false; } // None + + if ((val >= GPIO_KEY1) && (val < GPIO_KEY1 + MAX_KEYS)) { + offset = (GPIO_KEY1_NP - GPIO_KEY1); + } + if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) { + offset = -(GPIO_KEY1_NP - GPIO_KEY1); + } + if ((val >= GPIO_KEY1_INV) && (val < GPIO_KEY1_INV + MAX_KEYS)) { + offset = -(GPIO_KEY1_INV - GPIO_KEY1); + } + if ((val >= GPIO_KEY1_INV_NP) && (val < GPIO_KEY1_INV_NP + MAX_KEYS)) { + offset = -(GPIO_KEY1_INV_NP - GPIO_KEY1); + } + + if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) { + offset = (GPIO_SWT1_NP - GPIO_SWT1); + } + if ((val >= GPIO_SWT1_NP) && (val < GPIO_SWT1_NP + MAX_SWITCHES)) { + offset = -(GPIO_SWT1_NP - GPIO_SWT1); + } + + if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { + offset = (GPIO_REL1_INV - GPIO_REL1); + } + if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) { + offset = -(GPIO_REL1_INV - GPIO_REL1); + } + + if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) { + offset = (GPIO_LED1_INV - GPIO_LED1); + } + if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) { + offset = -(GPIO_LED1_INV - GPIO_LED1); + } + + if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) { + offset = (GPIO_PWM1_INV - GPIO_PWM1); + } + if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) { + offset = -(GPIO_PWM1_INV - GPIO_PWM1); + } + + if ((val >= GPIO_CNTR1) && (val < GPIO_CNTR1 + MAX_COUNTERS)) { + offset = (GPIO_CNTR1_NP - GPIO_CNTR1); + } + if ((val >= GPIO_CNTR1_NP) && (val < GPIO_CNTR1_NP + MAX_COUNTERS)) { + offset = -(GPIO_CNTR1_NP - GPIO_CNTR1); + } + + for (uint8_t i = 0; i < MAX_GPIO_PIN; i++) { + if (arr[i] == val) { return true; } + if (arr[i] == val + offset) { return true; } + } + return false; +} + +void TemplateJson() +{ + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); + for (uint8_t i = 0; i < sizeof(Settings.user_template.gp); i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", Settings.user_template.gp.io[i]); + } +// snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":\"%d (%s)\"}"), +// mqtt_data, Settings.user_template.flag, Settings.user_template_base +1, AnyModuleName(Settings.user_template_base).c_str()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), + mqtt_data, Settings.user_template.flag, Settings.user_template_base +1); +} + /*********************************************************************************************\ * Sleep aware time scheduler functions borrowed from ESPEasy \*********************************************************************************************/ diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 756805425..8001e507e 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -289,7 +289,7 @@ const char HTTP_FORM_LOG3[] PROGMEM = "
" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

"; const char HTTP_FORM_OTHER[] PROGMEM = "
 " D_OTHER_PARAMETERS " 
" -// "" + "
" D_TEMPLATE "

" "
" D_WEB_ADMIN_PASSWORD "

" "
" D_MQTT_ENABLE "
"; const char HTTP_FORM_OTHER2[] PROGMEM = @@ -309,7 +309,7 @@ const char HTTP_FORM_UPG[] PROGMEM = "
" "
 " D_UPGRADE_BY_WEBSERVER " " "" - "
" D_OTA_URL "

" + "
" D_OTA_URL "

" "
" "


" "
 " D_UPGRADE_BY_FILE_UPLOAD " "; @@ -1164,6 +1164,8 @@ void HandleOtherConfiguration(void) page.replace(F("{v}"), FPSTR(S_CONFIGURE_OTHER)); page += FPSTR(HTTP_HEAD_STYLE); page += FPSTR(HTTP_FORM_OTHER); + TemplateJson(); + page.replace(F("{t1"), mqtt_data); page.replace(F("{r1"), (Settings.flag.mqtt_enabled) ? F(" checked") : F("")); uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; @@ -1194,7 +1196,7 @@ void HandleOtherConfiguration(void) void OtherSaveSettings(void) { - char tmp[100]; + char tmp[128]; char stemp[TOPSZ]; char stemp2[TOPSZ]; @@ -1214,6 +1216,12 @@ void OtherSaveSettings(void) snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", Settings.friendlyname[i]); } AddLog(LOG_LEVEL_INFO); + WebGetArg("t1", tmp, sizeof(tmp)); + if (strlen(tmp)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255} + char svalue[128]; + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } } /*-------------------------------------------------------------------------------------------*/ From e8df8c4fa6c1e74156746bdb05c64eda7fbbca5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20R=2E=20Weimar?= Date: Tue, 12 Feb 2019 15:28:45 +0100 Subject: [PATCH 0995/2222] corrected sliding hour rounding for pixels < 60 --- sonoff/xplg_ws2812.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sonoff/xplg_ws2812.ino b/sonoff/xplg_ws2812.ino index e7eb16dd8..5fdc68f82 100644 --- a/sonoff/xplg_ws2812.ino +++ b/sonoff/xplg_ws2812.ino @@ -170,8 +170,7 @@ void Ws2812Clock(void) Ws2812UpdateHand((RtcTime.second * 1000) / clksize, WS_SECOND); Ws2812UpdateHand((RtcTime.minute * 1000) / clksize, WS_MINUTE); - uint32_t local_hour = (LocalTime()/3600)%12; // RtcTime.hour is UTC timezone, not local. - Ws2812UpdateHand(((local_hour % 12) * (5000 / clksize)) + ((RtcTime.minute * 1000) / (12 * clksize)), WS_HOUR); + Ws2812UpdateHand((((RtcTime.hour % 12) * 5000) + ((RtcTime.minute * 1000) / 12 )) / clksize, WS_HOUR); if (Settings.ws_color[WS_MARKER][WS_RED] + Settings.ws_color[WS_MARKER][WS_GREEN] + Settings.ws_color[WS_MARKER][WS_BLUE]) { for (uint8_t i = 0; i < 12; i++) { Ws2812UpdateHand((i * 5000) / clksize, WS_MARKER); From e779c7bdca373bec25039b97b363c809f2c217c3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Feb 2019 15:40:46 +0100 Subject: [PATCH 0996/2222] Provide template information Provide template information --- TEMPLATE.md | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 TEMPLATE.md diff --git a/TEMPLATE.md b/TEMPLATE.md new file mode 100644 index 000000000..91bd8d293 --- /dev/null +++ b/TEMPLATE.md @@ -0,0 +1,86 @@ +## Sonoff-Tasmota template information +Sonoff-Tasmota uses Device or Module information to control peripherals connected to GPIOs. This information is stored in the ``sonoff_template.h`` file as a device specific template. The template contains information about what GPIO should be connected to what peripheral and what GPIO may be configured online using the ``GPIO`` command or GUI Configure Module menu. In addition a device may need specific coding to process the data from these peripherals. The module number as provided by the ``Modules`` command is used to select this coding. + +Starting with version 6.4.1.16 Sonoff-Tasmota Modules can be extended by users online using a template. To provide easy processing by Sonoff-Tasmota a user template is written as JSON text and could look like this: + +{"NAME":"UserModule1","GPIO":[17,243,29,244,7,201,255,255,138,255,139,255,255],"FLAG":0,"BASE":18} + +The four properties with UPPERCASE property names have the following functionality: + +Property name | Property value description +--------------|------------------------------------------------------------------------------------------------------------------- +NAME | Up to 14 characters for the Module name +GPIO | Up to 13 decimal numbers from 0 to 255 representing GPIO0 to GPIO5, GPIO09, GPIO10 and GPIO12 to GPIO16 +FLAG | 8 bit mask flag register +BASE | Module number of a hard-coded device to be used when device specific functionality is needed + +The above example, based on the Generic Module does not allow ADC0 input. + +## GPIO functionality +The GPIO functionality numbers are the same is shown by command ``GPIOs``. In addition code 255 is added to select a GPIO as user configurable via the GUI Configure Module menu. + +## FLAG functionality +The FLAG value is an 8-bit mask where each bit controls a features. Add FLAG values to set multiple bits. + +FLAG | Mask | Feature description +-----|----------|------------------------------ + 1 | xxxxxxx1 | Allowing to use Analog0 (ADC0) as input if define USE_ADC_VCC in ``my_user_config.h`` is disabled + 2 | xxxxxx1x | Enable GUI pull-up control message + 4 | xxxxx1xx | Not used + 8 | xxxx1xxx | Not used + 16 | xxx1xxxx | Not used + 32 | xx1xxxxx | Not used + 64 | x1xxxxxx | Not used + 128 | 1xxxxxxx | Not used + +## BASE functionality +The following table lists hard-coded device specific functionality. Notice that not all device modules need special handling. + +BASE | Module | Description +-----|----------------|---------------------------------------------- + 4 | Sonoff Dual | Process relay and button via hardware serial interface using GPIO01 and GPIO03. Change baudrate to 19200 bps. Process buttons as single press only + 9 | Sonoff Touch | Invert ledstate 1 functionality + 10 | Sonoff LED | Set light type to 2 PWM channels disregarding SetOption15. Fix device specific LED instabilities by disabling GPIO04, GPIO5 and GPIO14 + 12 | 4 Channel | See 4 + 13 | Motor C/AC | Force all relays ON at Power On and disable command ``PowerOnState`` + 15 | EXS Relay(s) | Enable pulse latching using even/odd numbered relay pairs + 18 | Generic | Show Wemos specific pin information in GUI + 19 | H801 | Change hardware UART Tx from GPIO01 to GPIO02 + 20 | Sonoff SC | Enable and Process data via hardware serial interface using GPIO01 and GPIO03. Change baudrate to 19200 bps + 21 | Sonoff BN-SZ | Set light type to 1 PWM channel disregarding SetOption15 + 22 | Sonoff 4CH Pro | Button handling disregarding SetOption13 only allowing single press to enable RF learning while holding the button + 24 | Sonoff Bridge | Enable and Process data via hardware serial interface using GPIO01 and GPIO03. Change baudrate to 19200 bps. Process 16 buttons in web GUI. Enable EFM8BB1 firmware upload + 25 | Sonoff B1 | Set light type to RGBWC using MY92x1 + 26 | AiLight | Set light type to RGBW using MY92x1 + 27 | Sonoff T1 1CH | See 9 + 28 | Sonoff T1 2CH | See 9 + 29 | Sonoff T1 3CH | See 9 + 38 | Sonoff Dual R2 | Process buttons as single press only + 43 | Sonoff iFan02 | Enable command ``Fanspeed``. Disable Interlock and PulseTime. Tune status information, MQTT data and GUI. Sync with microcontroller. Process Domoticz Fan state + 47 | Xiaomi Philips | Process Color Temperature using PWM2 and Intensity using PWM1 + 53 | Tuya Dimmer | Enable and Process data via software or hardware serial interface using GPIO 148 and 149 or forced GPIO01 and GPIO03. Change baudrate to 9600 bps. Process all Buttons + 55 | ARMTR Dimmer | Enable and Process data via software or hardware serial interface using GPIO 148 and 149. Change baudrate to 115200 bps. + 57 | PS-16-DZ | Enable and Process data via software or hardware serial interface using GPIO 148 and 149. Change baudrate to 19200 bps. + 61 | YTF IR Bridge | Disable serial interface to stop loopback + 65 | Mi Desk Lamp | Process rotary and Button1 data specific to this device + +## Usage +A user provided template can be stored in Sonoff-Tasmota using the ``Template`` command. It has the following options. + +Command | Payload | Description +---------|----------|--------------------------------------- +Template | | Show current user template +Template | 0 | Copy active module template to user template +Template | 1 .. 69 | Copy hard-coded module template to user template + +The following command will store a complete template based on the Generic module +``Template {"NAME":"UserModule1","GPIO":[17,243,29,244,7,201,255,255,138,255,139,255,255],"FLAG":0,"BASE":18}`` + +The following command will update the name of a stored template +``Template {"NAME":"UserModule2"}`` + +The following command will update the flag of a stored template +``Template {"FLAG":1}`` + +The following command will update the base of a stored template to Generic +``Template {"BASE":0}`` \ No newline at end of file From 4b4b3709ad1bfc1a78af205c4f48ebd8d6f77003 Mon Sep 17 00:00:00 2001 From: Laurent <44267323+laurentdong@users.noreply.github.com> Date: Tue, 12 Feb 2019 21:46:42 -0500 Subject: [PATCH 0997/2222] Introduce Expression in Rules Support use an expression as paramter in some rule commands, include Var, Mem and Ruletimer. Expression is constructed by constants (float number), variables (var, mem, Time, Uptime, Sunrise, Sunset), operators and round brackets. Currently support 6 operators, order by priority from high to low: ^ (power) % (modulo) *, / +, - Commands examples: Var1 3.14 * (MEM1 * (10 + VAR2 ^2) - 100) % 10 + uptime / (2 + MEM2) Ruletimer4 Time - Sunrise + MEM2/2 --- lib/LinkedList-1.2.3/LICENSE.txt | 21 ++ lib/LinkedList-1.2.3/LinkedList.h | 325 +++++++++++++++++ lib/LinkedList-1.2.3/README.md | 171 +++++++++ .../examples/ClassList/ClassList.pde | 81 +++++ .../SimpleIntegerList/SimpleIntegerList.pde | 58 +++ lib/LinkedList-1.2.3/keywords.txt | 28 ++ lib/LinkedList-1.2.3/library.json | 12 + lib/LinkedList-1.2.3/library.properties | 9 + sonoff/my_user_config.h | 3 + sonoff/sonoff.ino | 4 +- sonoff/support.ino | 2 +- sonoff/xdrv_10_rules.ino | 330 ++++++++++++++++++ 12 files changed, 1042 insertions(+), 2 deletions(-) create mode 100644 lib/LinkedList-1.2.3/LICENSE.txt create mode 100644 lib/LinkedList-1.2.3/LinkedList.h create mode 100644 lib/LinkedList-1.2.3/README.md create mode 100644 lib/LinkedList-1.2.3/examples/ClassList/ClassList.pde create mode 100644 lib/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde create mode 100644 lib/LinkedList-1.2.3/keywords.txt create mode 100644 lib/LinkedList-1.2.3/library.json create mode 100644 lib/LinkedList-1.2.3/library.properties diff --git a/lib/LinkedList-1.2.3/LICENSE.txt b/lib/LinkedList-1.2.3/LICENSE.txt new file mode 100644 index 000000000..5c02604a0 --- /dev/null +++ b/lib/LinkedList-1.2.3/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Ivan Seidel + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/LinkedList-1.2.3/LinkedList.h b/lib/LinkedList-1.2.3/LinkedList.h new file mode 100644 index 000000000..371b14ac7 --- /dev/null +++ b/lib/LinkedList-1.2.3/LinkedList.h @@ -0,0 +1,325 @@ +/* + LinkedList.h - V1.1 - Generic LinkedList implementation + Works better with FIFO, because LIFO will need to + search the entire List to find the last one; + + For instructions, go to https://github.com/ivanseidel/LinkedList + + Created by Ivan Seidel Gomes, March, 2013. + Released into the public domain. +*/ + + +#ifndef LinkedList_h +#define LinkedList_h + +#include + +template +struct ListNode +{ + T data; + ListNode *next; +}; + +template +class LinkedList{ + +protected: + int _size; + ListNode *root; + ListNode *last; + + // Helps "get" method, by saving last position + ListNode *lastNodeGot; + int lastIndexGot; + // isCached should be set to FALSE + // everytime the list suffer changes + bool isCached; + + ListNode* getNode(int index); + +public: + LinkedList(); + ~LinkedList(); + + /* + Returns current size of LinkedList + */ + virtual int size(); + /* + Adds a T object in the specified index; + Unlink and link the LinkedList correcly; + Increment _size + */ + virtual bool add(int index, T); + /* + Adds a T object in the end of the LinkedList; + Increment _size; + */ + virtual bool add(T); + /* + Adds a T object in the start of the LinkedList; + Increment _size; + */ + virtual bool unshift(T); + /* + Set the object at index, with T; + Increment _size; + */ + virtual bool set(int index, T); + /* + Remove object at index; + If index is not reachable, returns false; + else, decrement _size + */ + virtual T remove(int index); + /* + Remove last object; + */ + virtual T pop(); + /* + Remove first object; + */ + virtual T shift(); + /* + Get the index'th element on the list; + Return Element if accessible, + else, return false; + */ + virtual T get(int index); + + /* + Clear the entire array + */ + virtual void clear(); + +}; + +// Initialize LinkedList with false values +template +LinkedList::LinkedList() +{ + root=NULL; + last=NULL; + _size=0; + + lastNodeGot = root; + lastIndexGot = 0; + isCached = false; +} + +// Clear Nodes and free Memory +template +LinkedList::~LinkedList() +{ + ListNode* tmp; + while(root!=NULL) + { + tmp=root; + root=root->next; + delete tmp; + } + last = NULL; + _size=0; + isCached = false; +} + +/* + Actualy "logic" coding +*/ + +template +ListNode* LinkedList::getNode(int index){ + + int _pos = 0; + ListNode* current = root; + + // Check if the node trying to get is + // immediatly AFTER the previous got one + if(isCached && lastIndexGot <= index){ + _pos = lastIndexGot; + current = lastNodeGot; + } + + while(_pos < index && current){ + current = current->next; + + _pos++; + } + + // Check if the object index got is the same as the required + if(_pos == index){ + isCached = true; + lastIndexGot = index; + lastNodeGot = current; + + return current; + } + + return false; +} + +template +int LinkedList::size(){ + return _size; +} + +template +bool LinkedList::add(int index, T _t){ + + if(index >= _size) + return add(_t); + + if(index == 0) + return unshift(_t); + + ListNode *tmp = new ListNode(), + *_prev = getNode(index-1); + tmp->data = _t; + tmp->next = _prev->next; + _prev->next = tmp; + + _size++; + isCached = false; + + return true; +} + +template +bool LinkedList::add(T _t){ + + ListNode *tmp = new ListNode(); + tmp->data = _t; + tmp->next = NULL; + + if(root){ + // Already have elements inserted + last->next = tmp; + last = tmp; + }else{ + // First element being inserted + root = tmp; + last = tmp; + } + + _size++; + isCached = false; + + return true; +} + +template +bool LinkedList::unshift(T _t){ + + if(_size == 0) + return add(_t); + + ListNode *tmp = new ListNode(); + tmp->next = root; + tmp->data = _t; + root = tmp; + + _size++; + isCached = false; + + return true; +} + +template +bool LinkedList::set(int index, T _t){ + // Check if index position is in bounds + if(index < 0 || index >= _size) + return false; + + getNode(index)->data = _t; + return true; +} + +template +T LinkedList::pop(){ + if(_size <= 0) + return T(); + + isCached = false; + + if(_size >= 2){ + ListNode *tmp = getNode(_size - 2); + T ret = tmp->next->data; + delete(tmp->next); + tmp->next = NULL; + last = tmp; + _size--; + return ret; + }else{ + // Only one element left on the list + T ret = root->data; + delete(root); + root = NULL; + last = NULL; + _size = 0; + return ret; + } +} + +template +T LinkedList::shift(){ + if(_size <= 0) + return T(); + + if(_size > 1){ + ListNode *_next = root->next; + T ret = root->data; + delete(root); + root = _next; + _size --; + isCached = false; + + return ret; + }else{ + // Only one left, then pop() + return pop(); + } + +} + +template +T LinkedList::remove(int index){ + if (index < 0 || index >= _size) + { + return T(); + } + + if(index == 0) + return shift(); + + if (index == _size-1) + { + return pop(); + } + + ListNode *tmp = getNode(index - 1); + ListNode *toDelete = tmp->next; + T ret = toDelete->data; + tmp->next = tmp->next->next; + delete(toDelete); + _size--; + isCached = false; + return ret; +} + + +template +T LinkedList::get(int index){ + ListNode *tmp = getNode(index); + + return (tmp ? tmp->data : T()); +} + +template +void LinkedList::clear(){ + while(size() > 0) + shift(); +} + +#endif diff --git a/lib/LinkedList-1.2.3/README.md b/lib/LinkedList-1.2.3/README.md new file mode 100644 index 000000000..bdb16fdbd --- /dev/null +++ b/lib/LinkedList-1.2.3/README.md @@ -0,0 +1,171 @@ +# LinkedList + +This library was developed targeting **`Arduino`** applications. However, works just great with any C++. + +Implementing a buffer for objects takes time. If we are not in the mood, we just create an `array[1000]` with enough size. + +The objective of this library is to create a pattern for projects. +If you need to use a List of: `int`, `float`, `objects`, `Lists` or `Wales`. **This is what you are looking for.** + +With a simple but powerful caching algorithm, you can get subsequent objects much faster than usual. Tested without any problems with Lists bigger than 2000 members. + +## Installation + +1. [Download](https://github.com/ivanseidel/LinkedList/archive/master.zip) the Latest release from gitHub. +2. Unzip and modify the Folder name to "LinkedList" (Remove the '-version') +3. Paste the modified folder on your Library folder (On your `Libraries` folder inside Sketchbooks or Arduino software). +4. Reopen the Arduino software. + +**If you are here, because another Library requires this class, just don't waste time reading bellow. Install and ready.** + +------------------------- + +## Getting started + +### The `LinkedList` class + +In case you don't know what a LinkedList is and what it's used for, take a quick look at [Wikipedia::LinkedList](https://en.wikipedia.org/wiki/Linked_list) before continuing. + +#### To declare a LinkedList object +```c++ +// Instantiate a LinkedList that will hold 'integer' +LinkedList myLinkedList = LinkedList(); + +// Or just this +LinkedList myLinkedList; + +// But if you are instantiating a pointer LinkedList... +LinkedList *myLinkedList = new LinkedList(); + +// If you want a LinkedList with any other type such as 'MyClass' +// Make sure you call delete(MyClass) when you remove! +LinkedList *myLinkedList = new LinkedList(); +``` + +#### Getting the size of the linked list +```c++ +// To get the size of a linked list, make use of the size() method +int theSize = myList.size(); + +// Notice that if it's pointer to the linked list, you should use -> instead +int theSize = myList->size(); +``` + +#### Adding elements + +```c++ +// add(obj) method will insert at the END of the list +myList.add(myObject); + +// add(index, obj) method will try to insert the object at the specified index +myList.add(0, myObject); // Add at the beginning +myList.add(3, myObject); // Add at index 3 + +// unshift(obj) method will insert the object at the beginning +myList.unshift(myObject); +``` + +#### Getting elements + +```c++ +// get(index) will return the element at index +// (notice that the start element is 0, not 1) + +// Get the FIRST element +myObject = myList.get(0); + +// Get the third element +myObject = myList.get(2); + +// Get the LAST element +myObject = myList.get(myList.size() - 1); +``` + +#### Changing elements +```c++ +// set(index, obj) method will change the object at index to obj + +// Change the first element to myObject +myList.set(0, myObject); + +// Change the third element to myObject +myList.set(2, myObject); + +// Change the LAST element of the list +myList.set(myList.size() - 1, myObject); +``` + +#### Removing elements +```c++ +// remove(index) will remove and return the element at index + +// Remove the first object +myList.remove(0); + +// Get and Delete the third element +myDeletedObject = myList.remove(2); + +// pop() will remove and return the LAST element +myDeletedObject = myList.pop(); + +// shift() will remove and return the FIRST element +myDeletedObject = myList.shift(); + +// clear() will erase the entire list, leaving it with 0 elements +// NOTE: Clear wont DELETE/FREE memory from Pointers, if you +// are using Classes/Poiners, manualy delete and free those. +myList.clear(); +``` + +------------------------ + +## Library Reference + +### `ListNode` struct + +- `T` `ListNode::data` - The object data + +- `ListNode` `*next` - Pointer to the next Node + +### `LinkedList` class + +**`boolean` methods returns if succeeded** + +- `LinkedList::LinkedList()` - Constructor. + +- `LinkedList::~LinkedList()` - Destructor. Clear Nodes to minimize memory. Does not free pointer memory. + +- `int` `LinkedList::size()` - Returns the current size of the list. + +- `bool` `LinkedList::add(T)` - Add element T at the END of the list. + +- `bool` `LinkedList::add(int index, T)` - Add element T at `index` of the list. + +- `bool` `LinkedList::unshift(T)` - Add element T at the BEGINNING of the list. + +- `bool` `LinkedList::set(int index, T)` - Set the element at `index` to T. + +- `T` `LinkedList::remove(int index)` - Remove element at `index`. Return the removed element. Does not free pointer memory + +- `T` `LinkedList::pop()` - Remove the LAST element. Return the removed element. + +- `T` `LinkedList::shift()` - Remove the FIRST element. Return the removed element. + +- `T` `LinkedList::get(int index)` - Return the element at `index`. + +- `void` `LinkedList::clear()` - Removes all elements. Does not free pointer memory. + +- **protected** `int` `LinkedList::_size` - Holds the cached size of the list. + +- **protected** `ListNode` `LinkedList::*root` - Holds the root node of the list. + +- **protected** `ListNode` `LinkedList::*last` - Holds the last node of the list. + +- **protected** `ListNode*` `LinkedList::getNode(int index)` - Returns the `index` node of the list. + +### Version History + +* `1.1 (2013-07-20)`: Cache implemented. Getting subsequent objects is now O(N). Before, O(N^2). +* `1.0 (2013-07-20)`: Original release + +![LinkedList](https://d2weczhvl823v0.cloudfront.net/ivanseidel/LinkedList/trend.png) diff --git a/lib/LinkedList-1.2.3/examples/ClassList/ClassList.pde b/lib/LinkedList-1.2.3/examples/ClassList/ClassList.pde new file mode 100644 index 000000000..9a8ea9d99 --- /dev/null +++ b/lib/LinkedList-1.2.3/examples/ClassList/ClassList.pde @@ -0,0 +1,81 @@ +/* + LinkedList Example + Link: http://github.com/ivanseidel/LinkedList + + Example Created by + Tom Stewart, github.com/tastewar + + Edited by: + Ivan Seidel, github.com/ivanseidel +*/ + +#include + +// Let's define a new class +class Animal { + public: + char *name; + bool isMammal; +}; + +char catname[]="kitty"; +char dogname[]="doggie"; +char emuname[]="emu"; + +LinkedList myAnimalList = LinkedList(); + +void setup() +{ + + Serial.begin(9600); + Serial.println("Hello!" ); + + // Create a Cat + Animal *cat = new Animal(); + cat->name = catname; + cat->isMammal = true; + + // Create a dog + Animal *dog = new Animal(); + dog->name = dogname; + dog->isMammal = true; + + // Create a emu + Animal *emu = new Animal(); + emu->name = emuname; + emu->isMammal = false; // just an example; no offense to pig lovers + + // Add animals to list + myAnimalList.add(cat); + myAnimalList.add(emu); + myAnimalList.add(dog); +} + +void loop() { + + Serial.print("There are "); + Serial.print(myAnimalList.size()); + Serial.print(" animals in the list. The mammals are: "); + + int current = 0; + Animal *animal; + for(int i = 0; i < myAnimalList.size(); i++){ + + // Get animal from list + animal = myAnimalList.get(i); + + // If its a mammal, then print it's name + if(animal->isMammal){ + + // Avoid printing spacer on the first element + if(current++) + Serial.print(", "); + + // Print animal name + Serial.print(animal->name); + } + } + Serial.println("."); + + while (true); // nothing else to do, loop forever +} \ No newline at end of file diff --git a/lib/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde b/lib/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde new file mode 100644 index 000000000..1bcbe9c37 --- /dev/null +++ b/lib/LinkedList-1.2.3/examples/SimpleIntegerList/SimpleIntegerList.pde @@ -0,0 +1,58 @@ +/* + LinkedList Example + Link: http://github.com/ivanseidel/LinkedList + + Example Created by + Tom Stewart, github.com/tastewar + + Edited by: + Ivan Seidel, github.com/ivanseidel +*/ +#include + +LinkedList myList = LinkedList(); + +void setup() +{ + + Serial.begin(9600); + Serial.println("Hello!"); + + // Add some stuff to the list + int k = -240, + l = 123, + m = -2, + n = 222; + myList.add(n); + myList.add(0); + myList.add(l); + myList.add(17); + myList.add(k); + myList.add(m); +} + +void loop() { + + int listSize = myList.size(); + + Serial.print("There are "); + Serial.print(listSize); + Serial.print(" integers in the list. The negative ones are: "); + + // Print Negative numbers + for (int h = 0; h < listSize; h++) { + + // Get value from list + int val = myList.get(h); + + // If the value is negative, print it + if (val < 0) { + Serial.print(" "); + Serial.print(val); + } + } + + while (true); // nothing else to do, loop forever +} + + diff --git a/lib/LinkedList-1.2.3/keywords.txt b/lib/LinkedList-1.2.3/keywords.txt new file mode 100644 index 000000000..3ae496859 --- /dev/null +++ b/lib/LinkedList-1.2.3/keywords.txt @@ -0,0 +1,28 @@ +####################################### +# Syntax Coloring +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +LinkedList KEYWORD1 +ListNode KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +size KEYWORD2 +add KEYWORD2 +unshift KEYWORD2 +set KEYWORD2 +remove KEYWORD2 +pop KEYWORD2 +shift KEYWORD2 +get KEYWORD2 +clear KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/lib/LinkedList-1.2.3/library.json b/lib/LinkedList-1.2.3/library.json new file mode 100644 index 000000000..4179b248d --- /dev/null +++ b/lib/LinkedList-1.2.3/library.json @@ -0,0 +1,12 @@ +{ + "name": "LinkedList", + "keywords": "pattern", + "description": "A fully implemented LinkedList (int, float, objects, Lists or Wales) made to work with Arduino projects", + "repository": + { + "type": "git", + "url": "https://github.com/ivanseidel/LinkedList.git" + }, + "frameworks": "arduino", + "platforms": "*" +} diff --git a/lib/LinkedList-1.2.3/library.properties b/lib/LinkedList-1.2.3/library.properties new file mode 100644 index 000000000..77b1423c0 --- /dev/null +++ b/lib/LinkedList-1.2.3/library.properties @@ -0,0 +1,9 @@ +name=LinkedList +version=1.2.3 +author=Ivan Seidel +maintainer=Ivan Seidel +sentence=A fully implemented LinkedList made to work with Arduino projects +paragraph=The objective of this library is to create a pattern for projects. If you need to use a List of: int, float, objects, Lists or Wales. This is what you are looking for. +category=Data Processing +url=https://github.com/ivanseidel/LinkedList +architectures=* diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 3029a3dc4..aa666cfd5 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -278,6 +278,9 @@ // -- Rules --------------------------------------- #define USE_RULES // Add support for rules (+4k4 code) +#ifdef USE_RULES + #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k1 code, +28 bytes mem) +#endif // -- Internal Analog input ----------------------- #define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 34c422d20..b03f1a335 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -64,7 +64,9 @@ #ifdef USE_SPI #include // SPI support, TFT #endif // USE_SPI - +#ifdef USE_EXPRESSION + #include // Import LinkedList library +#endif // Structs #include "settings.h" diff --git a/sonoff/support.ino b/sonoff/support.ino index c728d28eb..9cc18b8b4 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -154,7 +154,7 @@ char* subStr(char* dest, char* str, const char *delim, int index) return sub; } -double CharToDouble(char *str) +double CharToDouble(const char *str) { // simple ascii to double, because atof or strtod are too large char strbuf[24]; diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 327c128dc..18679ada0 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -90,6 +90,19 @@ #define MAXIMUM_COMPARE_OPERATOR COMPARE_OPERATOR_SMALLER_EQUAL const char kCompareOperators[] PROGMEM = "=\0>\0<\0|\0==!=>=<="; +#ifdef USE_EXPRESSION + const char kExpressionOperators[] PROGMEM = "+-*/%^"; + #define EXPRESSION_OPERATOR_ADD 0 + #define EXPRESSION_OPERATOR_SUBTRACT 1 + #define EXPRESSION_OPERATOR_MULTIPLY 2 + #define EXPRESSION_OPERATOR_DIVIDEDBY 3 + #define EXPRESSION_OPERATOR_MODULO 4 + #define EXPRESSION_OPERATOR_POWER 5 + + const uint8_t kExpressionOperatorsPriorities[] PROGMEM = {1, 1, 2, 2, 3, 4}; + #define MAX_EXPRESSION_OPERATOR_PRIORITY 4 +#endif //USE_EXPRESSION + enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM, CMND_ADD, CMND_SUB, CMND_MULT, CMND_SCALE, CMND_CALC_RESOLUTION }; const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM "|" D_CMND_ADD "|" D_CMND_SUB "|" D_CMND_MULT "|" D_CMND_SCALE "|" D_CMND_CALC_RESOLUTION ; @@ -562,6 +575,310 @@ void RulesTeleperiod(void) rules_teleperiod = 0; } +#ifdef USE_EXPRESSION +/********************************************************************************************/ +/* + * Parse a number value + * Input: + * pNumber - A char pointer point to a digit started string (guaranteed) + * value - Reference a double variable used to accept the result + * Output: + * pNumber - Pointer forward to next character after the number + * value - double type, the result value + * Return: + * true - succeed + * false - failed + */ +bool findNextNumber(char * &pNumber, double &value) +{ + bool bSucceed = false; + String sNumber = ""; + while (*pNumber) { + if (isdigit(*pNumber) || (*pNumber == '.')) { + sNumber += *pNumber; + pNumber++; + } else { + break; + } + } + if (sNumber.length() > 0) { + value = CharToDouble(sNumber.c_str()); + bSucceed = true; + } + return bSucceed; +} + +/********************************************************************************************/ +/* + * Parse a variable (like VAR1, MEM3) and get its value (double type) + * Input: + * pVarname - A char pointer point to a variable name string + * value - Reference a double variable used to accept the result + * Output: + * pVarname - Pointer forward to next character after the variable + * value - double type, the result value + * Return: + * true - succeed + * false - failed + */ +bool findNextVariableValue(char * &pVarname, double &value) +{ + bool succeed = false; + value = 0; + String sVarName = ""; + while (*pVarname) { + if (isalpha(*pVarname) || isdigit(*pVarname)) { + sVarName.concat(*pVarname); + pVarname++; + } else { + break; + } + } + sVarName.toUpperCase(); + if (sVarName.startsWith("VAR")) { + int index = sVarName.substring(3).toInt(); + if (index > 0 && index <= MAX_RULE_VARS) { + value = CharToDouble(vars[index -1]); + succeed = true; + } + } else if (sVarName.startsWith("MEM")) { + int index = sVarName.substring(3).toInt(); + if (index > 0 && index <= MAX_RULE_MEMS) { + value = CharToDouble(Settings.mems[index -1]); + succeed = true; + } + } else if (sVarName.equals("TIME")) { + value = GetMinutesPastMidnight(); + succeed = true; + } else if (sVarName.equals("UPTIME")) { + value = GetMinutesUptime(); + succeed = true; +#if defined(USE_TIMERS) && defined(USE_SUNRISE) + } else if (sVarName.equals("SUNRISE")) { + value = GetSunMinutes(0); + succeed = true; + } else if (sVarName.equals("SUNSET")) { + value = GetSunMinutes(1); + succeed = true; +#endif + } + + return succeed; +} + +/********************************************************************************************/ +/* + * Find next object in expression and evaluate it + * An object could be: + * - A float number start with a digit, like 0.787 + * - A variable name, like VAR1, MEM3 + * - An expression enclosed with a pair of round brackets, (.....) + * Input: + * pointer - A char pointer point to a place of the expression string + * value - Reference a double variable used to accept the result + * Output: + * pointer - Pointer forward to next character after next object + * value - double type, the result value + * Return: + * true - succeed + * false - failed + */ +bool findNextObjectValue(char * &pointer, double &value) +{ + bool bSucceed = false; + while (*pointer) + { + if (isspace(*pointer)) { //Skip leading spaces + pointer++; + continue; + } + if (isdigit(*pointer)) { //This object is a number + bSucceed = findNextNumber(pointer, value); + break; + } else if (isalpha(*pointer)) { //Should be a variable like VAR12, MEM1 + bSucceed = findNextVariableValue(pointer, value); + break; + } else if (*pointer == '(') { //It is a sub expression bracketed with () + pointer++; + char * sub_exp_start = pointer; //Find out the sub expression between a pair of parenthesis. "()" + unsigned int sub_exp_len = 0; + //Look for the matched closure parenthesis.")" + bool bFindClosures = false; + uint8_t matchClosures = 1; + while (*pointer) + { + if (*pointer == ')') { + matchClosures--; + if (matchClosures == 0) { + sub_exp_len = pointer - sub_exp_start; + bFindClosures = true; + break; + } + } else if (*pointer == '(') { + matchClosures++; + } + pointer++; + } + if (bFindClosures) { + value = evaluateExpression(sub_exp_start, sub_exp_len); + bSucceed = true; + } + break; + } else { //No number, no variable, no expression, then invalid object. + break; + } + } + return bSucceed; +} + +/********************************************************************************************/ +/* + * Find next operator in expression + * An operator could be: +, - , * , / , %, ^ + * Input: + * pointer - A char pointer point to a place of the expression string + * op - Reference to a variable used to accept the result + * Output: + * pointer - Pointer forward to next character after next operator + * op - The operator. 0, 1, 2, 3, 4, 5 + * Return: + * true - succeed + * false - failed + */ +bool findNextOperator(char * &pointer, int8_t &op) +{ + bool bSucceed = false; + while (*pointer) + { + if (isspace(*pointer)) { //Skip leading spaces + pointer++; + continue; + } + if (char *pch = strchr(kExpressionOperators, *pointer)) { //If it is an operator + op = (int8_t)(pch - kExpressionOperators); + pointer++; + bSucceed = true; + } + break; + } + return bSucceed; +} +/********************************************************************************************/ +/* + * Calculate a simple expression composed by 2 value and 1 operator, like 2 * 3 + * Input: + * pointer - A char pointer point to a place of the expression string + * value - Reference a double variable used to accept the result + * Output: + * pointer - Pointer forward to next character after next object + * value - double type, the result value + * Return: + * true - succeed + * false - failed + */ +double calculateTwoValues(double v1, double v2, uint8_t op) +{ + switch (op) + { + case EXPRESSION_OPERATOR_ADD: + return v1 + v2; + case EXPRESSION_OPERATOR_SUBTRACT: + return v1 - v2; + case EXPRESSION_OPERATOR_MULTIPLY: + return v1 * v2; + case EXPRESSION_OPERATOR_DIVIDEDBY: + return (0 == v2) ? 0 : (v1 / v2); + case EXPRESSION_OPERATOR_MODULO: + return (0 == v2) ? 0 : (int(v1) % int(v2)); + case EXPRESSION_OPERATOR_POWER: + return FastPrecisePow(v1, v2); + } + return 0; +} + +/********************************************************************************************/ +/* + * Parse and evaluate an expression. + * For example: "10 * ( MEM2 + 1) / 2" + * Right now, only support operators listed here: (order by priority) + * Priority 4: ^ (power) + * Priority 3: % (modulo, always get integer result) + * Priority 2: *, / + * Priority 1: +, - + * Input: + * expression - The expression to be evaluated + * len - Length of the expression + * Return: + * double - result. + * 0 - if the expression is invalid + * An example: + * MEM1 = 3, MEM2 = 6, VAR2 = 15, VAR10 = 80 + * At beginning, the expression might be complicated like: 3.14 * (MEM1 * (10 + VAR2 ^2) - 100) % 10 + VAR10 / (2 + MEM2) + * We are going to scan the whole expression, evaluate each object. + * Finally we will have a value list:. + * Order Object Value + * 0 3.14 3.14 + * 1 (MEM1 * (10 + VAR2 ^2) - 100) 605 + * 2 10 10 + * 3 VAR10 80 + * 4 (2 + MEM2) 8 + * And an operator list: + * Order Operator Priority + * 0 * 2 + * 1 % 3 + * 2 + 1 + * 3 / 2 + */ +double evaluateExpression(const char * expression, unsigned int len) +{ + char expbuf[len + 1]; + memcpy(expbuf, expression, len); + expbuf[len] = '\0'; + char * scan_pointer = expbuf; + + LinkedList object_values; + LinkedList operators; + int8_t op; + double va; + //Find and add the value of first object + if (findNextObjectValue(scan_pointer, va)) { + object_values.add(va); + } else { + return 0; + } + while (*scan_pointer) + { + if (findNextOperator(scan_pointer, op) + && *scan_pointer + && findNextObjectValue(scan_pointer, va)) + { + operators.add(op); + object_values.add(va); + } else { + //No operator followed or no more object after this operator, we done. + break; + } + } + + //Going to evaluate the whole expression + //Calculate by order of operator priorities. Looking for all operators with specified priority (from High to Low) + for (int8_t priority = MAX_EXPRESSION_OPERATOR_PRIORITY; priority>0; priority--) { + int index = 0; + while (index < operators.size()) { + if (priority == kExpressionOperatorsPriorities[(operators.get(index))]) { //need to calculate the operator first + //get current object value and remove the next object with current operator + va = calculateTwoValues(object_values.get(index), object_values.remove(index + 1), operators.remove(index)); + //Replace the current value with the result + object_values.set(index, va); + } else { + index++; + } + } + } + return object_values.get(0); +} +#endif //USE_EXPRESSION + bool RulesCommand(void) { char command[CMDSZ]; @@ -620,7 +937,12 @@ bool RulesCommand(void) } else if ((CMND_RULETIMER == command_code) && (index > 0) && (index <= MAX_RULE_TIMERS)) { if (XdrvMailbox.data_len > 0) { +#ifdef USE_EXPRESSION + double timer_set = evaluateExpression(XdrvMailbox.data, XdrvMailbox.data_len); + rules_timer[index -1] = (timer_set > 0) ? millis() + (1000 * timer_set) : 0; +#else rules_timer[index -1] = (XdrvMailbox.payload > 0) ? millis() + (1000 * XdrvMailbox.payload) : 0; +#endif //USE_EXPRESSION } mqtt_data[0] = '\0'; for (uint8_t i = 0; i < MAX_RULE_TIMERS; i++) { @@ -636,14 +958,22 @@ bool RulesCommand(void) } else if ((CMND_VAR == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { +#ifdef USE_EXPRESSION + dtostrfd(evaluateExpression(XdrvMailbox.data, XdrvMailbox.data_len), Settings.flag2.calc_resolution, vars[index -1]); +#else strlcpy(vars[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(vars[index -1])); +#endif //USE_EXPRESSION bitSet(vars_event, index -1); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } else if ((CMND_MEM == command_code) && (index > 0) && (index <= MAX_RULE_MEMS)) { if (XdrvMailbox.data_len > 0) { +#ifdef USE_EXPRESSION + dtostrfd(evaluateExpression(XdrvMailbox.data, XdrvMailbox.data_len), Settings.flag2.calc_resolution, Settings.mems[index -1]); +#else strlcpy(Settings.mems[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[index -1])); +#endif //USE_EXPRESSION bitSet(mems_event, index -1); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]); From b9f6bf402adfe5c3d1ec47b8f6aa1906bebec40b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 13 Feb 2019 10:50:02 +0100 Subject: [PATCH 0998/2222] Add CFG_HOLDER to status 1 Add parameter CFG_HOLDER to status 1 message (#5206) --- sonoff/_changelog.ino | 1 + sonoff/i18n.h | 1 + sonoff/sonoff.ino | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 371cbeb7f..5fd97a3cc 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.4.1.16 20190211 * Initial support for online template change using command Template or GUI Configure Other (#5177) + * Add parameter CFG_HOLDER to status 1 message (#5206) * * 6.4.1.15 20190208 * Change image name BE_MINIMAL to FIRMWARE_MINIMAL (#5106) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index b4b3b1df7..fa921afed 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -44,6 +44,7 @@ #define D_JSON_CHANNEL "Channel" #define D_JSON_CO2 "CarbonDioxide" #define D_JSON_COMMAND "Command" +#define D_JSON_CONFIG_HOLDER "CfgHolder" #define D_JSON_CONNECT_FAILED "Connect failed" #define D_JSON_COREVERSION "Core" #define D_JSON_COUNT "Count" diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 34c422d20..c3c0e3095 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1668,8 +1668,8 @@ void PublishStatus(uint8_t payload) } if ((0 == payload) || (1 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), - baudrate, Settings.mqtt_grptopic, Settings.ota_url, GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.bootcount, Settings.save_flag, GetSettingsAddress()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), + baudrate, Settings.mqtt_grptopic, Settings.ota_url, GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.cfg_holder, Settings.bootcount, Settings.save_flag, GetSettingsAddress()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); } From c39e2da6b5431989abe4fcd7e07d563c762ac238 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 13 Feb 2019 16:05:25 +0100 Subject: [PATCH 0999/2222] Update GUI Update GUI --- sonoff/_changelog.ino | 1 + sonoff/xdrv_01_webserver.ino | 124 ++++++++++++++++++++++------------- sonoff/xdrv_02_mqtt.ino | 19 +++--- sonoff/xdrv_07_domoticz.ino | 8 ++- sonoff/xdrv_09_timers.ino | 16 ++--- sonoff/xdrv_11_knx.ino | 9 +-- sonoff/xsns_34_hx711.ino | 8 +-- 7 files changed, 112 insertions(+), 73 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 5fd97a3cc..35e16eda8 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.4.1.16 20190211 * Initial support for online template change using command Template or GUI Configure Other (#5177) * Add parameter CFG_HOLDER to status 1 message (#5206) + * Update GUI * * 6.4.1.15 20190208 * Change image name BE_MINIMAL to FIRMWARE_MINIMAL (#5106) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 8001e507e..c74548ef9 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -189,7 +189,10 @@ const char HTTP_HEAD_STYLE[] PROGMEM = ""; const char HTTP_FORM_TIMER[] PROGMEM = "
" " " D_TIMER_PARAMETERS " " "
" - "
" D_TIMER_ENABLE "


" + "
" D_TIMER_ENABLE "


" "



" "

" "
" - "" D_TIMER_ARM " " - "" D_TIMER_REPEAT "" + "" D_TIMER_ARM " " + "" D_TIMER_REPEAT "" "

" "
" #ifdef USE_SUNRISE - "
" + "
" // 299 used in page.replace(F("299") "" D_TIMER_TIME "
" "" D_SUNRISE " (}8)
" "" D_SUNSET " (}9)
" "
" + "

" "" " " #else diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 1dc380d21..72dea970c 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -752,20 +752,21 @@ void KnxSensor(uint8_t sensor_type, float value) const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX; const char HTTP_BTN_MENU_KNX[] PROGMEM = - "
"; + "

"; const char HTTP_FORM_KNX[] PROGMEM = - "
 " D_KNX_PARAMETERS " 
" + "
 " D_KNX_PARAMETERS " " + "" "
" "" D_KNX_PHYSICAL_ADDRESS " " " . " " . " "" "

" D_KNX_PHYSICAL_ADDRESS_NOTE "

" - "" D_KNX_ENABLE " " D_KNX_ENABLE "

" diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index d9063b779..148f7f860 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -377,19 +377,19 @@ const char HTTP_BTN_MENU_MAIN_HX711[] PROGMEM = "
"; const char HTTP_BTN_MENU_HX711[] PROGMEM = - "
"; + "

"; const char HTTP_FORM_HX711[] PROGMEM = "
 " D_CALIBRATION " " "
" - "
" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" - "

" + "

" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" + "
" "" "


" "
 " D_HX711_PARAMETERS " " "
" - "
" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; + "

" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; void HandleHxAction(void) { From 74affa1440fe6b27df200eee1d9206b0d6f00551 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 13 Feb 2019 16:26:16 +0100 Subject: [PATCH 1000/2222] Fix Edge and Safari margins Fix Edge and Safari margins --- sonoff/xdrv_01_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index c74548ef9..a3185875f 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -190,7 +190,7 @@ const char HTTP_HEAD_STYLE[] PROGMEM = ""; const char HTTP_FORM_TIMER[] PROGMEM = "
" From 4af4ff681d99790ac12634b413928d4905c98efd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 14 Feb 2019 11:04:11 +0100 Subject: [PATCH 1004/2222] Hide templated GPIOs Hide templated GPIOs in user template too (#5222) --- sonoff/support.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index c728d28eb..cfbce4548 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -783,12 +783,15 @@ uint8_t ValidPin(uint8_t pin, uint8_t gpio) bool ValidGPIO(uint8_t pin, uint8_t gpio) { bool result = false; - +/* if (USER_MODULE == Settings.module) { result = (ValidPin(pin, gpio) > GPIO_NONE); // Allow any pin } else { result = (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins } +*/ + result = (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins + return result; } From 166a625eb8f82b00cde691410cad065a27c2b333 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 14 Feb 2019 11:13:47 +0100 Subject: [PATCH 1005/2222] Revert "Hide templated GPIOs" This reverts commit 4af4ff681d99790ac12634b413928d4905c98efd. --- sonoff/support.ino | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index cfbce4548..c728d28eb 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -783,15 +783,12 @@ uint8_t ValidPin(uint8_t pin, uint8_t gpio) bool ValidGPIO(uint8_t pin, uint8_t gpio) { bool result = false; -/* + if (USER_MODULE == Settings.module) { result = (ValidPin(pin, gpio) > GPIO_NONE); // Allow any pin } else { result = (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins } -*/ - result = (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins - return result; } From 77db7ba0ffe2d8b8051c2f16240bdc9054d51588 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 14 Feb 2019 16:48:28 +0100 Subject: [PATCH 1006/2222] 6.4.1.17 Change template stability 6.4.1.17 20190214 * Change template update by removing possibility to add user module config keeping template as defined (#5222) --- sonoff/_changelog.ino | 5 ++++- sonoff/sonoff.ino | 14 ++++++++++++++ sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 7 ++++++- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 35e16eda8..0461104e5 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.16 20190211 +/* 6.4.1.17 20190214 + * Change template update by removing possibility to add user module config keeping template as defined (#5222) + * + * 6.4.1.16 20190211 * Initial support for online template change using command Template or GUI Configure Other (#5177) * Add parameter CFG_HOLDER to status 1 message (#5206) * Update GUI diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c3c0e3095..8f9f93d62 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -954,7 +954,10 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) else if (CMND_TEMPLATE == command_code) { // {"NAME":"Generic","GPIO":[17,254,29,254,7,254,254,254,138,254,139,254,254],"FLAG":1,"BASE":255} bool error = false; + if (!strstr(dataBuf, "{")) { // If no JSON it must be parameter +/* + // Version 6.4.1.16 - Add user module config data to template bool update = false; if ((payload > 0) && (payload <= MAXMODULE)) { ModuleDefault(payload -1); // Copy template module @@ -983,6 +986,17 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) src++; } } +*/ + // Version 6.4.1.17 use template as defined + if ((payload > 0) && (payload <= MAXMODULE)) { + ModuleDefault(payload -1); // Copy template module + if (USER_MODULE == Settings.module) { restart_flag = 2; } + } + else if (0 == payload) { // Copy current module with user configured GPIO + if (Settings.module != USER_MODULE) { + ModuleDefault(Settings.module); + } + } } else if (data_len > 9) { // Workaround exception if empty JSON like {} - Needs checks StaticJsonBuffer<350> jb; // 331 from https://arduinojson.org/v5/assistant/ diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 2c221bd1b..3816029fd 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040110 +#define VERSION 0x06040111 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index c728d28eb..80c1c53e3 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -783,12 +783,17 @@ uint8_t ValidPin(uint8_t pin, uint8_t gpio) bool ValidGPIO(uint8_t pin, uint8_t gpio) { bool result = false; - +/* + // Version 6.4.1.16 - Use user module config in template if (USER_MODULE == Settings.module) { result = (ValidPin(pin, gpio) > GPIO_NONE); // Allow any pin } else { result = (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins } +*/ + // Version 6.4.1.17 - Use template as defined + result = (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins + return result; } From b4b1ee9177202f58a68f52d6acce6e795a27ac54 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 14 Feb 2019 16:52:55 +0100 Subject: [PATCH 1007/2222] Update TEMPLATE.md Fix to real life --- TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TEMPLATE.md b/TEMPLATE.md index 91bd8d293..67431f651 100644 --- a/TEMPLATE.md +++ b/TEMPLATE.md @@ -3,7 +3,7 @@ Sonoff-Tasmota uses Device or Module information to control peripherals connecte Starting with version 6.4.1.16 Sonoff-Tasmota Modules can be extended by users online using a template. To provide easy processing by Sonoff-Tasmota a user template is written as JSON text and could look like this: -{"NAME":"UserModule1","GPIO":[17,243,29,244,7,201,255,255,138,255,139,255,255],"FLAG":0,"BASE":18} +{"NAME":"UserModule1","GPIO":[17,148,29,149,7,255,255,255,138,255,139,255,255],"FLAG":0,"BASE":18} The four properties with UPPERCASE property names have the following functionality: @@ -74,7 +74,7 @@ Template | 0 | Copy active module template to user template Template | 1 .. 69 | Copy hard-coded module template to user template The following command will store a complete template based on the Generic module -``Template {"NAME":"UserModule1","GPIO":[17,243,29,244,7,201,255,255,138,255,139,255,255],"FLAG":0,"BASE":18}`` +``Template {"NAME":"UserModule1","GPIO":[17,148,29,149,7,255,255,255,138,255,139,255,255],"FLAG":0,"BASE":18}`` The following command will update the name of a stored template ``Template {"NAME":"UserModule2"}`` From 26b91d5d0505854413cc930eecefa20f74be2a01 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Fri, 15 Feb 2019 18:35:29 +0100 Subject: [PATCH 1008/2222] decode-config.py: adapt settings; add Template --- tools/decode-config.py | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index f0779279a..642c31954 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0020' +VER = '2.1.0021' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -841,9 +841,37 @@ Setting_6_4_1_13.update ({ 'mhz19b_abc_disable': ('B', (0x717,1, 7), (None, None, ('Sensor', '"Sensor15 {}".format($)')) ), }, 0x717, (None, None, ('*', None)), (None, False) ), }) - +# ====================================================================== +Setting_6_4_1_16 = copy.deepcopy(Setting_6_4_1_13) +Setting_6_4_1_16.update({ + 'user_template_base': ('B', 0x71F, (None, None, ('Management', '"Template {}".format($)')), ('$ + 1','$ - 1') ), + 'user_template': ({ + 'name': ('15s', 0x720, (None, None, ('Management', '"Template {{\\\"NAME\\\":\\\"{}\\\"}}".format($)' )) ), + 'gpio00': ('B', 0x72F, (None, None, ('Management', '"Template {{\\\"GPIO\\\":[{},{},{},{},{},{},{},{},{},{},{},{},{}]}}".format(@["user_template"]["gpio00"],@["user_template"]["gpio01"],@["user_template"]["gpio02"],@["user_template"]["gpio03"],@["user_template"]["gpio04"],@["user_template"]["gpio05"],@["user_template"]["gpio09"],@["user_template"]["gpio10"],@["user_template"]["gpio12"],@["user_template"]["gpio13"],@["user_template"]["gpio14"],@["user_template"]["gpio15"],@["user_template"]["gpio16"])')) ), + 'gpio01': ('B', 0x730, (None, None, ('Management', None)) ), + 'gpio02': ('B', 0x731, (None, None, ('Management', None)) ), + 'gpio03': ('B', 0x732, (None, None, ('Management', None)) ), + 'gpio04': ('B', 0x733, (None, None, ('Management', None)) ), + 'gpio05': ('B', 0x734, (None, None, ('Management', None)) ), + 'gpio09': ('B', 0x735, (None, None, ('Management', None)) ), + 'gpio10': ('B', 0x736, (None, None, ('Management', None)) ), + 'gpio12': ('B', 0x737, (None, None, ('Management', None)) ), + 'gpio13': ('B', 0x738, (None, None, ('Management', None)) ), + 'gpio14': ('B', 0x739, (None, None, ('Management', None)) ), + 'gpio15': ('B', 0x73A, (None, None, ('Management', None)) ), + 'gpio16': ('B', 0x73B, (None, None, ('Management', None)) ), + 'flag': ({ + 'value': ('B', 0x73C , (None, None, ('Management', '"Template {{\\\"FLAG\\\":{}}}".format($)')) ), + 'adc0': ('B', (0x73C,1,0), (None, None, ('Management', None)) ), + 'pullup': ('B', (0x73C,1,1), (None, None, ('Management', None)) ), + }, 0x73C, (None, None, ('Management', None)) + ), + }, 0x720, (None, None, ('Management', '"Template GPIO:{}".format(@["user_template"]["gp"][0])')) + ), +}) # ====================================================================== Settings = [ + (0x6040110, 0xe00, Setting_6_4_1_16), (0x604010D, 0xe00, Setting_6_4_1_13), (0x604010B, 0xe00, Setting_6_4_1_11), (0x6040108, 0xe00, Setting_6_4_1_8), @@ -2850,4 +2878,4 @@ if __name__ == "__main__": tasmotacmnds = Mapping2Cmnd(decode_cfg, configmapping) OutputTasmotaCmnds(tasmotacmnds) - sys.exit(exitcode) \ No newline at end of file + sys.exit(exitcode) From 1fde362998c86c6f9d9bb259afd2252de0cd67e7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 16 Feb 2019 11:33:29 +0100 Subject: [PATCH 1009/2222] Fix regression from 6.4.1.16 Fix regression from 6.4.1.16 where GPIO9 and GPIO10 connected devices did not work (#5197) --- sonoff/_changelog.ino | 1 + sonoff/support.ino | 25 ++++++------------------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0461104e5..4d1919c86 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.4.1.17 20190214 * Change template update by removing possibility to add user module config keeping template as defined (#5222) + * Fix regression from 6.4.1.16 where GPIO9 and GPIO10 connected devices did not work (#5197) * * 6.4.1.16 20190211 * Initial support for online template change using command Template or GUI Configure Other (#5177) diff --git a/sonoff/support.ino b/sonoff/support.ino index 80c1c53e3..f03c131ef 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -769,32 +769,19 @@ void SetModuleType() uint8_t ValidPin(uint8_t pin, uint8_t gpio) { uint8_t result = gpio; - if ((pin > 5) && (pin < 12)) { - result = GPIO_NONE; // Disable all flash pins + + if (((pin > 5) && (pin < 9)) || (11 == pin)) { + result = GPIO_NONE; // Disable flash pins GPIO6, GPIO7, GPIO8 and GPIO11 } - if (Settings.flag3.user_esp8285_enable) { - if ((pin == 9) || (pin == 10)) { - result = gpio; // Allow optional flash pins - } + if ((WEMOS == Settings.module) && (!Settings.flag3.user_esp8285_enable)) { + if ((pin == 9) || (pin == 10)) { result = GPIO_NONE; } // Disable possible flash GPIO9 and GPIO10 } return result; } bool ValidGPIO(uint8_t pin, uint8_t gpio) { - bool result = false; -/* - // Version 6.4.1.16 - Use user module config in template - if (USER_MODULE == Settings.module) { - result = (ValidPin(pin, gpio) > GPIO_NONE); // Allow any pin - } else { - result = (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins - } -*/ - // Version 6.4.1.17 - Use template as defined - result = (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins - - return result; + return (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins } bool GetUsedInModule(uint8_t val, uint8_t *arr) From 02f10524405e317a06eabe5d96d2867b4264243c Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 16 Feb 2019 12:48:16 +0000 Subject: [PATCH 1010/2222] Amended wifi password UI to show "****". Only store passwords which are not equal to "****". Removes previous behaviour where wifi password with an asterisk was ignored. --- sonoff/i18n.h | 1 + sonoff/xdrv_01_webserver.ino | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index fa921afed..f910ba015 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -419,6 +419,7 @@ /********************************************************************************************/ #define D_ASTERIX "********" +#define D_ASTERISK_PWD "****" #ifndef MY_LANGUAGE #include "language/en-GB.h" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index ab16ae8fd..87165586b 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -280,9 +280,9 @@ const char HTTP_FORM_WIFI[] PROGMEM = "
 " D_WIFI_PARAMETERS " " "" "

" D_AP1_SSID " (" STA_SSID1 ")

" - "

" D_AP1_PASSWORD "

" + "

" D_AP1_PASSWORD "

" "

" D_AP2_SSID " (" STA_SSID2 ")

" - "

" D_AP2_PASSWORD "

" + "

" D_AP2_PASSWORD "

" "

" D_HOSTNAME " (" WIFI_HOSTNAME ")

"; const char HTTP_FORM_LOG1[] PROGMEM = @@ -1082,9 +1082,9 @@ void WifiSaveSettings(void) WebGetArg("s2", tmp, sizeof(tmp)); strlcpy(Settings.sta_ssid[1], (!strlen(tmp)) ? STA_SSID2 : tmp, sizeof(Settings.sta_ssid[1])); WebGetArg("p1", tmp, sizeof(tmp)); - strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); + strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (!strcmp(tmp,D_ASTERISK_PWD)) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); WebGetArg("p2", tmp, sizeof(tmp)); - strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); + strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (!strcmp(tmp,D_ASTERISK_PWD)) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s"), Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1]); AddLog(LOG_LEVEL_INFO); From e6029e18bea9b988aaa70924f0114c3356b13915 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 16 Feb 2019 12:51:43 +0000 Subject: [PATCH 1011/2222] Fix typos. --- sonoff/xdrv_01_webserver.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 87165586b..87116d8f6 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -280,9 +280,9 @@ const char HTTP_FORM_WIFI[] PROGMEM = "
 " D_WIFI_PARAMETERS " " "" "

" D_AP1_SSID " (" STA_SSID1 ")

" - "

" D_AP1_PASSWORD "

" + "

" D_AP1_PASSWORD "

" "

" D_AP2_SSID " (" STA_SSID2 ")

" - "

" D_AP2_PASSWORD "

" + "

" D_AP2_PASSWORD "

" "

" D_HOSTNAME " (" WIFI_HOSTNAME ")

"; const char HTTP_FORM_LOG1[] PROGMEM = From 14d5f7fb54980be83b020c699c608c9b39e09099 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 16 Feb 2019 16:17:17 +0100 Subject: [PATCH 1012/2222] Fix GUI password and Add rule expression * Fix GUI wifi password acception starting with asteriks (*) (#5231, #5242) * Add rule expression enabled by define USE_EXPRESSION in my_user_config.h (#5210) --- sonoff/_changelog.ino | 2 ++ sonoff/my_user_config.h | 4 +--- sonoff/sonoff.ino | 3 --- sonoff/xdrv_10_rules.ino | 16 +++++++++------- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 4d1919c86..0b9d3db75 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,8 @@ /* 6.4.1.17 20190214 * Change template update by removing possibility to add user module config keeping template as defined (#5222) * Fix regression from 6.4.1.16 where GPIO9 and GPIO10 connected devices did not work (#5197) + * Fix GUI wifi password acception starting with asteriks (*) (#5231, #5242) + * Add rule expression enabled by define USE_EXPRESSION in my_user_config.h (#5210) * * 6.4.1.16 20190211 * Initial support for online template change using command Template or GUI Configure Other (#5177) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index aa666cfd5..5a7f3a14a 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -278,9 +278,7 @@ // -- Rules --------------------------------------- #define USE_RULES // Add support for rules (+4k4 code) -#ifdef USE_RULES - #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k1 code, +28 bytes mem) -#endif + #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) // -- Internal Analog input ----------------------- #define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 22415b1da..ce7afb89a 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -64,9 +64,6 @@ #ifdef USE_SPI #include // SPI support, TFT #endif // USE_SPI -#ifdef USE_EXPRESSION - #include // Import LinkedList library -#endif // Structs #include "settings.h" diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 18679ada0..9603e549b 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -91,6 +91,8 @@ const char kCompareOperators[] PROGMEM = "=\0>\0<\0|\0==!=>=<="; #ifdef USE_EXPRESSION + #include // Import LinkedList library + const char kExpressionOperators[] PROGMEM = "+-*/%^"; #define EXPRESSION_OPERATOR_ADD 0 #define EXPRESSION_OPERATOR_SUBTRACT 1 @@ -101,7 +103,7 @@ const char kCompareOperators[] PROGMEM = "=\0>\0<\0|\0==!=>=<="; const uint8_t kExpressionOperatorsPriorities[] PROGMEM = {1, 1, 2, 2, 3, 4}; #define MAX_EXPRESSION_OPERATOR_PRIORITY 4 -#endif //USE_EXPRESSION +#endif // USE_EXPRESSION enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM, CMND_ADD, CMND_SUB, CMND_MULT, CMND_SCALE, CMND_CALC_RESOLUTION }; const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM "|" D_CMND_ADD "|" D_CMND_SUB "|" D_CMND_MULT "|" D_CMND_SCALE "|" D_CMND_CALC_RESOLUTION ; @@ -686,7 +688,7 @@ bool findNextVariableValue(char * &pVarname, double &value) bool findNextObjectValue(char * &pointer, double &value) { bool bSucceed = false; - while (*pointer) + while (*pointer) { if (isspace(*pointer)) { //Skip leading spaces pointer++; @@ -748,7 +750,7 @@ bool findNextObjectValue(char * &pointer, double &value) bool findNextOperator(char * &pointer, int8_t &op) { bool bSucceed = false; - while (*pointer) + while (*pointer) { if (isspace(*pointer)) { //Skip leading spaces pointer++; @@ -809,7 +811,7 @@ double calculateTwoValues(double v1, double v2, uint8_t op) * expression - The expression to be evaluated * len - Length of the expression * Return: - * double - result. + * double - result. * 0 - if the expression is invalid * An example: * MEM1 = 3, MEM2 = 6, VAR2 = 15, VAR10 = 80 @@ -848,15 +850,15 @@ double evaluateExpression(const char * expression, unsigned int len) } while (*scan_pointer) { - if (findNextOperator(scan_pointer, op) + if (findNextOperator(scan_pointer, op) && *scan_pointer - && findNextObjectValue(scan_pointer, va)) + && findNextObjectValue(scan_pointer, va)) { operators.add(op); object_values.add(va); } else { //No operator followed or no more object after this operator, we done. - break; + break; } } From ed0d50a3aa6b98c8ec83fd43639a56735d6574a8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 16 Feb 2019 18:01:54 +0100 Subject: [PATCH 1013/2222] Fix template support Fix template support --- sonoff/support.ino | 2 -- 1 file changed, 2 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 5c76b137b..d37185e3f 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -788,8 +788,6 @@ bool GetUsedInModule(uint8_t val, uint8_t *arr) { int offset = 0; - if (USER_MODULE == Settings.module) { return false; } - if (!val) { return false; } // None if ((val >= GPIO_KEY1) && (val < GPIO_KEY1 + MAX_KEYS)) { From 4ed82140af3f6571a6cc04458695351ed930b33c Mon Sep 17 00:00:00 2001 From: Xavier MULLER <33861984+localhost61@users.noreply.github.com> Date: Sun, 17 Feb 2019 01:01:26 +0100 Subject: [PATCH 1014/2222] Update fr-FR.h --- sonoff/language/fr-FR.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index cd168850d..8825d287e 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -138,7 +138,7 @@ #define D_RESTARTING "Redémarre" #define D_RESTART_REASON "Raison du redémarrage" #define D_RESTORE "restaurer" -#define D_RETAINED "retenu" +#define D_RETAINED "persistant" // MQTT #define D_RULE "Règle" #define D_SAVE "Enregistrer" #define D_SENSOR "Capteur" @@ -253,7 +253,7 @@ #define D_MODULE_PARAMETERS "Paramètres module" #define D_MODULE_TYPE "Type de module" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_PULLUP_ENABLE "Inter. sans pull-up" #define D_GPIO "GPIO" #define D_SERIAL_IN "Entrée série" #define D_SERIAL_OUT "Sortie série" @@ -288,8 +288,8 @@ #define D_TELEMETRY_PERIOD "Période télémétrie" #define D_OTHER_PARAMETERS "Autres paramètres" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" +#define D_TEMPLATE "Modèle" +#define D_ACTIVATE "Activer" #define D_WEB_ADMIN_PASSWORD "Mot de passe Web Admin" #define D_MQTT_ENABLE "MQTT activé" #define D_FRIENDLY_NAME "Surnom" From f94c2245afefd63b646107063eaa43e532c0ca05 Mon Sep 17 00:00:00 2001 From: Xavier MULLER <33861984+localhost61@users.noreply.github.com> Date: Sun, 17 Feb 2019 01:02:52 +0100 Subject: [PATCH 1015/2222] Update fr-FR.h --- sonoff/language/fr-FR.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 8825d287e..b2f0f289e 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.3.0.17 + * Updated until v6.4.1.17 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) From e2540f0afe539ababf0070227e4e32bfce1a75b9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 17 Feb 2019 10:42:55 +0100 Subject: [PATCH 1016/2222] Update sonoff.ino Prep for template menu --- sonoff/sonoff.ino | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ce7afb89a..9efbd9be7 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -64,6 +64,7 @@ #ifdef USE_SPI #include // SPI support, TFT #endif // USE_SPI + // Structs #include "settings.h" @@ -955,38 +956,6 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) bool error = false; if (!strstr(dataBuf, "{")) { // If no JSON it must be parameter -/* - // Version 6.4.1.16 - Add user module config data to template - bool update = false; - if ((payload > 0) && (payload <= MAXMODULE)) { - ModuleDefault(payload -1); // Copy template module - if (USER_MODULE == Settings.module) { restart_flag = 2; } - } - else if (0 == payload) { // Copy current module with user configured GPIO - if (Settings.module < USER_MODULE) { - ModuleDefault(Settings.module); - update = true; - } - } - if (USER_MODULE == Settings.module) { // Update with latest changes - update = true; - } - if (update) { - uint8_t src = 0; - for (uint8_t dst = 0; dst < sizeof(mycfgio); dst++) { - if (6 == dst) { src = 9; } - if (8 == dst) { src = 12; } - if (Settings.my_gp.io[src] > GPIO_NONE) { - if (Settings.user_template.gp.io[dst] != Settings.my_gp.io[src]) { - Settings.user_template.gp.io[dst] = Settings.my_gp.io[src]; - if (USER_MODULE == Settings.module) { restart_flag = 2; } - } - } - src++; - } - } -*/ - // Version 6.4.1.17 use template as defined if ((payload > 0) && (payload <= MAXMODULE)) { ModuleDefault(payload -1); // Copy template module if (USER_MODULE == Settings.module) { restart_flag = 2; } From 577791440e2018308f27e4a01d698bab4661b44b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 17 Feb 2019 11:32:53 +0100 Subject: [PATCH 1017/2222] Add Configure Template menu option Add Configure Template menu option to GUI (#5222) --- sonoff/_changelog.ino | 1 + sonoff/i18n.h | 1 + sonoff/language/bg-BG.h | 9 ++ sonoff/language/cs-CZ.h | 9 ++ sonoff/language/de-DE.h | 9 ++ sonoff/language/el-GR.h | 9 ++ sonoff/language/en-GB.h | 9 ++ sonoff/language/es-AR.h | 9 ++ sonoff/language/fr-FR.h | 9 ++ sonoff/language/he-HE.h | 9 ++ sonoff/language/hu-HU.h | 9 ++ sonoff/language/it-IT.h | 9 ++ sonoff/language/nl-NL.h | 9 ++ sonoff/language/pl-PL.h | 9 ++ sonoff/language/pt-BR.h | 9 ++ sonoff/language/pt-PT.h | 9 ++ sonoff/language/ru-RU.h | 9 ++ sonoff/language/sk-SK.h | 9 ++ sonoff/language/sv-SE.h | 9 ++ sonoff/language/tr-TR.h | 9 ++ sonoff/language/uk-UK.h | 9 ++ sonoff/language/zh-CN.h | 9 ++ sonoff/language/zh-TW.h | 9 ++ sonoff/xdrv_01_webserver.ino | 223 +++++++++++++++++++++++++++++++---- 24 files changed, 389 insertions(+), 25 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0b9d3db75..fd3c2845f 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Fix regression from 6.4.1.16 where GPIO9 and GPIO10 connected devices did not work (#5197) * Fix GUI wifi password acception starting with asteriks (*) (#5231, #5242) * Add rule expression enabled by define USE_EXPRESSION in my_user_config.h (#5210) + * Add Configure Template menu option to GUI (#5222) * * 6.4.1.16 20190211 * Initial support for online template change using command Template or GUI Configure Other (#5177) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index f910ba015..a35161433 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -569,6 +569,7 @@ const char HTTP_SNS_CO2[] PROGMEM = "%s{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_M const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU; const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION; +const char S_CONFIGURE_TEMPLATE[] PROGMEM = D_CONFIGURE_TEMPLATE; const char S_CONFIGURE_MODULE[] PROGMEM = D_CONFIGURE_MODULE; const char S_CONFIGURE_WIFI[] PROGMEM = D_CONFIGURE_WIFI; const char S_NO_NETWORKS_FOUND[] PROGMEM = D_NO_NETWORKS_FOUND; diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 4f0393e25..d8b54ddea 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "Единично" #define D_MULTI_DEVICE "Мулти" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Запазване на конфигурацията" #define D_CONFIGURATION_SAVED "Конфигурацията е запазена" #define D_CONFIGURATION_RESET "Конфигурацията е изчистена" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Няма" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 127971d2e..769acfd0d 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "single device" #define D_MULTI_DEVICE "multi device" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Ulož nastavení" #define D_CONFIGURATION_SAVED "Nastavení uloženo" #define D_CONFIGURATION_RESET "Nastavení resetováno" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Není" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index a1d5192c9..07ba04792 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "Einzelnes Gerät" #define D_MULTI_DEVICE "Mehrfachgerät" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Konfiguration speichern" #define D_CONFIGURATION_SAVED "Konfiguration gespeichert" #define D_CONFIGURATION_RESET "Konfiguration zurücksetzen" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 6385bb3fd..3d96d4744 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "μονή συσκευή" #define D_MULTI_DEVICE "πολλαπλές συσκευές" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Αποθήκευση ρυθμίσεων" #define D_CONFIGURATION_SAVED "Οι ρυθμίσεις αποθηκεύτηκαν" #define D_CONFIGURATION_RESET "Επαναφορά ρυθμίσεων" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Κανένα" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index c7e0b3672..7d8f32e6b 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "single device" #define D_MULTI_DEVICE "multi device" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Save configuration" #define D_CONFIGURATION_SAVED "Configuration saved" #define D_CONFIGURATION_RESET "Configuration reset" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index b8202394a..1bc0f064c 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "dispositivo simple" #define D_MULTI_DEVICE "dispositivo múltiple" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Grabar configuración" #define D_CONFIGURATION_SAVED "Configuración grabada" #define D_CONFIGURATION_RESET "Configuración restablecida" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Ninguno" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index b2f0f289e..5a809d7d6 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "module unique" #define D_MULTI_DEVICE "multi module" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Enregistrer la configuration" #define D_CONFIGURATION_SAVED "Configuration enregistrée" #define D_CONFIGURATION_RESET "Configuration réinitialisée" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Aucun" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 3c16594b5..deca89d18 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "התקן בודד" #define D_MULTI_DEVICE "התקנים" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "שמירת הגדרות" #define D_CONFIGURATION_SAVED "הגדרות נשמרו" #define D_CONFIGURATION_RESET "איפוס הגדרות" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 96be81f5d..e9eed8025 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "single device" #define D_MULTI_DEVICE "multi device" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Beállítások mentése" #define D_CONFIGURATION_SAVED "Beállítások elmentve" #define D_CONFIGURATION_RESET "Beállítások visszaállítása" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nincs" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index f33c5aacb..8269441ae 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "dispositivo singolo" #define D_MULTI_DEVICE "dispositivo multiplo" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Salva configurazione" #define D_CONFIGURATION_SAVED "Configurazione salvata" #define D_CONFIGURATION_RESET "Configurazione azzerata" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nessuno" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index a44d722a6..00d658d0c 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "een apparaat" #define D_MULTI_DEVICE "meer apparaten" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Bewaar configuratie" #define D_CONFIGURATION_SAVED "Configuratie opgeslagen" #define D_CONFIGURATION_RESET "Configuratie ge-reset" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Geen" +#define D_SENSOR_USER "Gebruiker" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index b95cbc8ee..14161f0be 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "single device" #define D_MULTI_DEVICE "multi device" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Zapisz ustawienia" #define D_CONFIGURATION_SAVED "Ustawienia zapisane" #define D_CONFIGURATION_RESET "Ustawienia zresetowane" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Brak" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 57c38ad22..013768607 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "Dispositivo único" #define D_MULTI_DEVICE "Múltiplos dispositivos" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Gravar configuração" #define D_CONFIGURATION_SAVED "Configuração gravada" #define D_CONFIGURATION_RESET "Reinicialização da configuração" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nenhum" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index f5609728e..11f10f750 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "dispositivo único" #define D_MULTI_DEVICE "multiplos dispositivos" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Salvar configuração" #define D_CONFIGURATION_SAVED "Configuração guardada" #define D_CONFIGURATION_RESET "Reinicialização da configuração" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nenhum" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 9f10d9cae..b3641c647 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "одиночное" #define D_MULTI_DEVICE "мульти" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Сохранить конфигурацию" #define D_CONFIGURATION_SAVED "Конфигурация сохранена " #define D_CONFIGURATION_RESET "Конфигурация сброшена" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "-нет-" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index b3d2a3316..76fa89e7a 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "single device" #define D_MULTI_DEVICE "multi device" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Ulož nastavenia" #define D_CONFIGURATION_SAVED "Nastavenia uložené" #define D_CONFIGURATION_RESET "Nastavenia resetované" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Žiaden" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 5d37447a3..eca87b7c7 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "soloenhet" #define D_MULTI_DEVICE "multienhet" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Spara konfiguration" #define D_CONFIGURATION_SAVED "Konfiguration sparad" #define D_CONFIGURATION_RESET "Konfiguration nollställd" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Ingen" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 2a0bd3d55..bb9aa1a4c 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "tekli cihaz" #define D_MULTI_DEVICE "çoklu cihaz" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Ayarları Kaydet" #define D_CONFIGURATION_SAVED "Ayarlar kaydedildi" #define D_CONFIGURATION_RESET "Ayarlar resetlendi" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 2371f6a19..289e9292c 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "одиночне" #define D_MULTI_DEVICE "мульти" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "Зберегти конфігурацію" #define D_CONFIGURATION_SAVED "Конфігурація збережена " #define D_CONFIGURATION_RESET "Конфігурація скинута" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "-відсутньо-" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 547e38292..f37a127de 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "单设备" #define D_MULTI_DEVICE "多设备" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "保存设置" #define D_CONFIGURATION_SAVED "设置已保存" #define D_CONFIGURATION_RESET "设置已重置" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "无" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 220c1e2ae..5188db09b 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -298,6 +298,14 @@ #define D_SINGLE_DEVICE "單設備" #define D_MULTI_DEVICE "多設備" +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Flags" +#define D_ALLOW_ADC0 "ADC0 input" +#define D_ALLOW_PULLUP "User pull-up selection" + #define D_SAVE_CONFIGURATION "保存設置" #define D_CONFIGURATION_SAVED "設置已保存" #define D_CONFIGURATION_RESET "設置已重置" @@ -485,6 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 87116d8f6..b796de246 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -66,6 +66,7 @@ const char HTTP_SCRIPT_COUNTER[] PROGMEM = "setTimeout(u,1000);" "}" "}" + "window.onload=u;" ""; const char HTTP_SCRIPT_ROOT[] PROGMEM = @@ -92,7 +93,8 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "}" "function lc(p){" "la('?t='+p);" // ?t related to WebGetArg("t", tmp, sizeof(tmp)); - "}"; + "}" + "window.onload=la;"; const char HTTP_SCRIPT_WIFI[] PROGMEM = "function c(l){" @@ -144,13 +146,63 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "lt=setTimeout(l,{a});" "return false;" "}" + "window.onload=l;" ""; -const char HTTP_SCRIPT_MODULE1[] PROGMEM = + +const char HTTP_SCRIPT_MODULE_TEMPLATE[] PROGMEM = "var os;" - "function sk(s,g){" // s = value, g = id and name + "function sk(s,g){" // s = value, g = id and name "var o=os.replace(/}1/g,\"
"), - (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "ESP8285" :(10==i)? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); + (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); page += mqtt_data; } } @@ -1460,7 +1635,6 @@ void HandleInformation(void) func += F("
%s " D_GPIO "%d %s
\").replace(/}2/g,\"\");" "eb('i').innerHTML=s;" "}" + "window.onload=i;" ""; const char HTTP_HEAD_STYLE[] PROGMEM = @@ -247,6 +301,7 @@ const char HTTP_BTN_MENU_MODULE[] PROGMEM = const char HTTP_BTN_MENU4[] PROGMEM = "

" "

" + "

" "
" "
" "

" @@ -266,8 +321,21 @@ const char HTTP_BTN_CONF[] PROGMEM = "
" "
"; +const char HTTP_FORM_TEMPLATE[] PROGMEM = + "
 " D_TEMPLATE_PARAMETERS " " + "
" + "

" D_TEMPLATE_NAME "

" + "

" D_BASE_TYPE "

"; +const char HTTP_FORM_TEMPLATE_FLAG[] PROGMEM = + "

" // Keep close so do not use
+ "
 " D_TEMPLATE_FLAGS " 

" + "" D_ALLOW_ADC0 "
" + "" D_ALLOW_PULLUP "
" + "

"; + const char HTTP_FORM_MODULE[] PROGMEM = - "
 " D_MODULE_PARAMETERS " " + "
 " D_MODULE_PARAMETERS " " + "" "

" D_MODULE_TYPE " ({mt)

"; const char HTTP_FORM_MODULE_PULLUP[] PROGMEM = "
" D_PULLUP_ENABLE "
"; @@ -435,6 +503,7 @@ void StartWebserver(int type, IPAddress ipweb) WebServer->on("/md", HandleModuleConfiguration); WebServer->on("/wi", HandleWifiConfiguration); WebServer->on("/lg", HandleLoggingConfiguration); + WebServer->on("/tp", HandleTemplateConfiguration); WebServer->on("/co", HandleOtherConfiguration); WebServer->on("/dl", HandleBackupConfiguration); WebServer->on("/rs", HandleRestoreConfiguration); @@ -552,7 +621,6 @@ void ShowPage(String &page, bool auth) if (HTTP_MANAGER == webserver_state) { if (WifiConfigCounter()) { page.replace(F(""), FPSTR(HTTP_SCRIPT_COUNTER)); - page.replace(F(""), F("")); page += FPSTR(HTTP_COUNTER); } } @@ -634,13 +702,6 @@ void HandleRoot(void) if ((Settings.web_password[0] != 0) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1"))) { HandleWifiLogin(); } else { -/* - char tmp1[100]; - WebGetArg("USER1", tmp1, sizeof(tmp1)); - char tmp2[100]; - WebGetArg("PASS1", tmp2, sizeof(tmp2)); - if (!(Settings.web_password[0] != 0) || (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, Settings.web_password)))) { -*/ if (!(Settings.web_password[0] != 0) || ((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == Settings.web_password ))) { HandleWifiConfiguration(); } else { @@ -655,7 +716,6 @@ void HandleRoot(void) page.replace(F("{v}"), FPSTR(S_MAIN_MENU)); page += FPSTR(HTTP_SCRIPT_ROOT); page += FPSTR(HTTP_HEAD_STYLE); - page.replace(F(""), F("")); page += F("
"); if (devices_present) { @@ -827,6 +887,128 @@ void HandleConfiguration(void) /*-------------------------------------------------------------------------------------------*/ +void HandleTemplateConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("save")) { + TemplateSaveSettings(); + if (USER_MODULE == Settings.module) { + WebRestart(1); + } + return; + } + + char stemp[20]; + + if (WebServer->hasArg("m")) { + String page = ""; + for (uint8_t i = 0; i < MAXMODULE; i++) { // "}1'%d'>%s (%d)}2" - "}1'0'>Sonoff Basic (1)}2" + uint8_t midx = pgm_read_byte(kModuleNiceList + i); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE3, midx, AnyModuleName(midx).c_str(), midx +1); + page += mqtt_data; + } + WebServer->send(200, FPSTR(HDR_CTYPE_PLAIN), page); + return; + } + + WebGetArg("t", stemp, sizeof(stemp)); + if (strlen(stemp)) { + uint8_t module = atoi(stemp); + uint8_t module_save = Settings.module; + Settings.module = module; + myio cmodule; + ModuleGpios(&cmodule); + gpio_flag flag = ModuleFlag(); + Settings.module = module_save; + + String page = AnyModuleName(module); // NAME: Generic + +// page += F("}1'255'>" D_SENSOR_USER " (255)}2"); // GPIO: }1'255'>User (255)}2 + for (uint8_t i = 0; i < sizeof(kGpioNiceList); i++) { // GPIO: }1'0'>None (0)}2}1'17'>Button1 (17)}2... + + if (1 == i) { + page += F("}1'255'>" D_SENSOR_USER " (255)}2"); // }1'255'>User (255)}2 + } + + uint8_t midx = pgm_read_byte(kGpioNiceList + i); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE3, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); + page += mqtt_data; + } + page += F("}3"); // }3 + + mqtt_data[0] = '\0'; + for (uint8_t i = 0; i < sizeof(cmodule); i++) { // 17,148,29,149,7,255,255,255,138,255,139,255,255 + if ((i < 6) || ((i > 8) && (i < 11)) || (i > 11)) { // Ignore flash pins GPIO06, 7, 8 and 11 + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", cmodule.io[i]); + } + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,%d,%d"), mqtt_data, flag, Settings.user_template_base); // FLAG: ,1 BASE: ,17 + page += mqtt_data; + + WebServer->send(200, FPSTR(HDR_CTYPE_PLAIN), page); + return; + } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TEMPLATE); + + String page = FPSTR(HTTP_HEAD); + page.replace(F("{v}"), FPSTR(S_CONFIGURE_TEMPLATE)); + page += FPSTR(HTTP_SCRIPT_MODULE_TEMPLATE); + page += FPSTR(HTTP_SCRIPT_TEMPLATE); + page += FPSTR(HTTP_HEAD_STYLE); + page += FPSTR(HTTP_FORM_TEMPLATE); + page += F("
"); + for (uint8_t i = 0; i < 17; i++) { + if ((i < 6) || ((i > 8) && (i < 11)) || (i > 11)) { // Ignore flash pins GPIO06, 7, 8 and 11 + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("" D_GPIO "%d"), + (0==i)?" style='width:80px'":"", i, ((9==i)||(10==i))? "ESP8285" :"", (0==i)?" style='width:176px'":"", i, i); + page += mqtt_data; + } + } + page += F("
%s
"); + page += FPSTR(HTTP_FORM_TEMPLATE_FLAG); + page += FPSTR(HTTP_FORM_END); + page += FPSTR(HTTP_BTN_CONF); + ShowPage(page); +} + +void TemplateSaveSettings(void) +{ + char svalue[128]; + char tmp[100]; + char stemp[20]; + + WebGetArg("s1", tmp, sizeof(tmp)); // NAME + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp); + + uint8_t j = 0; + for (uint8_t i = 0; i < sizeof(Settings.user_template.gp); i++) { + if (6 == i) { j = 9; } + if (8 == i) { j = 12; } + snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), j); + WebGetArg(stemp, tmp, sizeof(tmp)); // GPIO + uint8_t gpio = atoi(tmp); + snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", gpio); + j++; + } + + uint8_t flag = 0; + for (uint8_t i = 0; i < 2; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("c%d"), i); + uint8_t state = WebServer->hasArg(stemp) << i; // FLAG + flag += state; + } + WebGetArg("g99", tmp, sizeof(tmp)); // BASE + uint8_t base = atoi(tmp) +1; + + snprintf_P(svalue, sizeof(svalue), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), + svalue, flag, base); + ExecuteWebCommand(svalue, SRC_WEBGUI); +} + +/*-------------------------------------------------------------------------------------------*/ + void HandleModuleConfiguration(void) { if (!HttpCheckPriviledgedAccess()) { return; } @@ -844,13 +1026,6 @@ void HandleModuleConfiguration(void) if (WebServer->hasArg("m")) { String page = ""; -/* - for (uint8_t i = 0; i < MAXMODULE; i++) { // "}1'%d'>%s (%d)}2" - "}1'0'>Sonoff Basic (1)}2" - midx = pgm_read_byte(kModuleNiceList + i); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE3, midx, AnyModuleName(midx).c_str(), midx +1); - page += mqtt_data; - } -*/ uint8_t vidx = 0; for (uint8_t i = 0; i <= MAXMODULE; i++) { // "}1'%d'>%s (%d)}2" - "}1'255'>UserTemplate (0)}2" - "}1'0'>Sonoff Basic (1)}2" if (0 == i) { @@ -884,6 +1059,7 @@ void HandleModuleConfiguration(void) String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE)); + page += FPSTR(HTTP_SCRIPT_MODULE_TEMPLATE); page += FPSTR(HTTP_SCRIPT_MODULE1); page.replace(F("}4"), String(Settings.module)); for (uint8_t i = 0; i < sizeof(cmodule); i++) { @@ -894,7 +1070,6 @@ void HandleModuleConfiguration(void) } page += FPSTR(HTTP_SCRIPT_MODULE2); page += FPSTR(HTTP_HEAD_STYLE); - page.replace(F(""), F("")); page += FPSTR(HTTP_FORM_MODULE); page.replace(F("{mt"), AnyModuleName(MODULE)); @@ -908,7 +1083,7 @@ void HandleModuleConfiguration(void) if (ValidGPIO(i, cmodule.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("
%s " D_GPIO "%d %s
"); func += FPSTR(HTTP_SCRIPT_INFO_END); page.replace(F(""), func); - page.replace(F(""), F("")); // page += F("
"); page += FPSTR(HTTP_BTN_MAIN); @@ -1847,7 +2021,6 @@ void HandleConsole(void) page.replace(F("{v}"), FPSTR(S_CONSOLE)); page += FPSTR(HTTP_HEAD_STYLE); page.replace(F(""), FPSTR(HTTP_SCRIPT_CONSOL)); - page.replace(F(""), F("")); page += FPSTR(HTTP_FORM_CMND); page += FPSTR(HTTP_BTN_MAIN); ShowPage(page); From 94f16836167c9186b37ff7d663bc85579f0a8a14 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sun, 17 Feb 2019 12:32:46 +0100 Subject: [PATCH 1018/2222] Update de-DE.h Template changes --- sonoff/language/de-DE.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 07ba04792..1bc7b2ea7 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.3.0.17 + * Updated until v6.4.1.17 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -298,13 +298,13 @@ #define D_SINGLE_DEVICE "Einzelnes Gerät" #define D_MULTI_DEVICE "Mehrfachgerät" -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_CONFIGURE_TEMPLATE "Vorlage konfigurieren" +#define D_TEMPLATE_PARAMETERS "Vorlage Parameter" #define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" +#define D_BASE_TYPE "basiert auf" #define D_TEMPLATE_FLAGS "Flags" #define D_ALLOW_ADC0 "ADC0 input" -#define D_ALLOW_PULLUP "User pull-up selection" +#define D_ALLOW_PULLUP "Nutzer pull-up Auswahl" #define D_SAVE_CONFIGURATION "Konfiguration speichern" #define D_CONFIGURATION_SAVED "Konfiguration gespeichert" From 027ef777472542faa980c182d0ccee314196a5f5 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sun, 17 Feb 2019 12:46:08 +0100 Subject: [PATCH 1019/2222] Create boards.txt --- arduino/version 2.5.0/boards.txt | 6121 ++++++++++++++++++++++++++++++ 1 file changed, 6121 insertions(+) create mode 100644 arduino/version 2.5.0/boards.txt diff --git a/arduino/version 2.5.0/boards.txt b/arduino/version 2.5.0/boards.txt new file mode 100644 index 000000000..300a608c4 --- /dev/null +++ b/arduino/version 2.5.0/boards.txt @@ -0,0 +1,6121 @@ +# +# Do not create pull-requests for this file only, CI will not accept them. +# You *must* edit/modify/run boards.txt.py to regenerate boards.txt. +# All modified files after running with option "--allgen" must be included in the pull-request. +# + +menu.BoardModel=Model +menu.baud=Upload Speed +menu.UploadTool=Upload Using +menu.xtal=CPU Frequency +menu.CrystalFreq=Crystal Frequency +menu.eesz=Flash Size +menu.FlashMode=Flash Mode +menu.FlashFreq=Flash Frequency +menu.ResetMethod=Reset Method +menu.ESPModule=Module +menu.dbg=Debug port +menu.lvl=Debug Level +menu.ip=lwIP Variant +menu.vt=VTables +menu.exception=Exceptions +menu.led=Builtin Led +menu.wipe=Erase Flash + +############################################################## +generic.name=Generic ESP8266 Module +generic.build.board=ESP8266_GENERIC +generic.upload.tool=esptool +generic.upload.maximum_data_size=81920 +generic.upload.wait_for_upload_port=true +generic.upload.erase_cmd= +generic.serial.disableDTR=true +generic.serial.disableRTS=true +generic.build.mcu=esp8266 +generic.build.core=esp8266 +generic.build.variant=generic +generic.build.spiffs_pagesize=256 +generic.build.debug_port= +generic.build.debug_level= + +generic.menu.UploadTool.esptool=Serial +generic.menu.UploadTool.esptool.upload.tool=esptool +generic.menu.UploadTool.esptool.upload.verbose=-vv +generic.menu.UploadTool.espupload=OTA_upload +generic.menu.UploadTool.espupload.upload.tool=espupload + +generic.menu.xtal.80=80 MHz +generic.menu.xtal.80.build.f_cpu=80000000L +generic.menu.xtal.160=160 MHz +generic.menu.xtal.160.build.f_cpu=160000000L +generic.menu.vt.flash=Flash +generic.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +generic.menu.vt.heap=Heap +generic.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +generic.menu.vt.iram=IRAM +generic.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +generic.menu.exception.disabled=Disabled +generic.menu.exception.disabled.build.exception_flags=-fno-exceptions +generic.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +generic.menu.exception.enabled=Enabled +generic.menu.exception.enabled.build.exception_flags=-fexceptions +generic.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +generic.menu.ResetMethod.ck=ck +generic.menu.ResetMethod.ck.upload.resetmethod=ck +generic.menu.ResetMethod.nodemcu=nodemcu +generic.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +generic.menu.ResetMethod.none=none +generic.menu.ResetMethod.none.upload.resetmethod=none +generic.menu.ResetMethod.dtrset=dtrset +generic.menu.ResetMethod.dtrset.upload.resetmethod=dtrset +generic.menu.CrystalFreq.26=26 MHz +generic.menu.CrystalFreq.40=40 MHz +generic.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +generic.menu.FlashFreq.40=40MHz +generic.menu.FlashFreq.40.build.flash_freq=40 +generic.menu.FlashFreq.80=80MHz +generic.menu.FlashFreq.80.build.flash_freq=80 +generic.menu.FlashMode.dout=DOUT (compatible) +generic.menu.FlashMode.dout.build.flash_mode=dout +generic.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT +generic.menu.FlashMode.dio=DIO +generic.menu.FlashMode.dio.build.flash_mode=dio +generic.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO +generic.menu.FlashMode.qout=QOUT +generic.menu.FlashMode.qout.build.flash_mode=qout +generic.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT +generic.menu.FlashMode.qio=QIO (fast) +generic.menu.FlashMode.qio.build.flash_mode=qio +generic.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO +generic.menu.eesz.512K=512K (no SPIFFS) +generic.menu.eesz.512K.build.flash_size=512K +generic.menu.eesz.512K.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +generic.menu.eesz.512K.build.spiffs_pagesize=256 +generic.menu.eesz.512K.upload.maximum_size=499696 +generic.menu.eesz.512K.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K32=512K (32K SPIFFS) +generic.menu.eesz.512K32.build.flash_size=512K +generic.menu.eesz.512K32.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +generic.menu.eesz.512K32.build.spiffs_pagesize=256 +generic.menu.eesz.512K32.upload.maximum_size=466928 +generic.menu.eesz.512K32.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K32.build.spiffs_start=0x73000 +generic.menu.eesz.512K32.build.spiffs_end=0x7B000 +generic.menu.eesz.512K32.build.spiffs_blocksize=4096 +generic.menu.eesz.512K64=512K (64K SPIFFS) +generic.menu.eesz.512K64.build.flash_size=512K +generic.menu.eesz.512K64.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +generic.menu.eesz.512K64.build.spiffs_pagesize=256 +generic.menu.eesz.512K64.upload.maximum_size=434160 +generic.menu.eesz.512K64.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K64.build.spiffs_start=0x6B000 +generic.menu.eesz.512K64.build.spiffs_end=0x7B000 +generic.menu.eesz.512K64.build.spiffs_blocksize=4096 +generic.menu.eesz.512K128=512K (128K SPIFFS) +generic.menu.eesz.512K128.build.flash_size=512K +generic.menu.eesz.512K128.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +generic.menu.eesz.512K128.build.spiffs_pagesize=256 +generic.menu.eesz.512K128.upload.maximum_size=368624 +generic.menu.eesz.512K128.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K128.build.spiffs_start=0x5B000 +generic.menu.eesz.512K128.build.spiffs_end=0x7B000 +generic.menu.eesz.512K128.build.spiffs_blocksize=4096 +generic.menu.eesz.1M=1M (no SPIFFS) +generic.menu.eesz.1M.build.flash_size=1M +generic.menu.eesz.1M.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +generic.menu.eesz.1M.build.spiffs_pagesize=256 +generic.menu.eesz.1M.upload.maximum_size=1023984 +generic.menu.eesz.1M.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M64=1M (64K SPIFFS) +generic.menu.eesz.1M64.build.flash_size=1M +generic.menu.eesz.1M64.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +generic.menu.eesz.1M64.build.spiffs_pagesize=256 +generic.menu.eesz.1M64.upload.maximum_size=958448 +generic.menu.eesz.1M64.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M64.build.spiffs_start=0xEB000 +generic.menu.eesz.1M64.build.spiffs_end=0xFB000 +generic.menu.eesz.1M64.build.spiffs_blocksize=4096 +generic.menu.eesz.1M128=1M (128K SPIFFS) +generic.menu.eesz.1M128.build.flash_size=1M +generic.menu.eesz.1M128.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +generic.menu.eesz.1M128.build.spiffs_pagesize=256 +generic.menu.eesz.1M128.upload.maximum_size=892912 +generic.menu.eesz.1M128.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M128.build.spiffs_start=0xDB000 +generic.menu.eesz.1M128.build.spiffs_end=0xFB000 +generic.menu.eesz.1M128.build.spiffs_blocksize=4096 +generic.menu.eesz.1M144=1M (144K SPIFFS) +generic.menu.eesz.1M144.build.flash_size=1M +generic.menu.eesz.1M144.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +generic.menu.eesz.1M144.build.spiffs_pagesize=256 +generic.menu.eesz.1M144.upload.maximum_size=876528 +generic.menu.eesz.1M144.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M144.build.spiffs_start=0xD7000 +generic.menu.eesz.1M144.build.spiffs_end=0xFB000 +generic.menu.eesz.1M144.build.spiffs_blocksize=4096 +generic.menu.eesz.1M160=1M (160K SPIFFS) +generic.menu.eesz.1M160.build.flash_size=1M +generic.menu.eesz.1M160.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +generic.menu.eesz.1M160.build.spiffs_pagesize=256 +generic.menu.eesz.1M160.upload.maximum_size=860144 +generic.menu.eesz.1M160.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M160.build.spiffs_start=0xD3000 +generic.menu.eesz.1M160.build.spiffs_end=0xFB000 +generic.menu.eesz.1M160.build.spiffs_blocksize=4096 +generic.menu.eesz.1M192=1M (192K SPIFFS) +generic.menu.eesz.1M192.build.flash_size=1M +generic.menu.eesz.1M192.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +generic.menu.eesz.1M192.build.spiffs_pagesize=256 +generic.menu.eesz.1M192.upload.maximum_size=827376 +generic.menu.eesz.1M192.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M192.build.spiffs_start=0xCB000 +generic.menu.eesz.1M192.build.spiffs_end=0xFB000 +generic.menu.eesz.1M192.build.spiffs_blocksize=4096 +generic.menu.eesz.1M256=1M (256K SPIFFS) +generic.menu.eesz.1M256.build.flash_size=1M +generic.menu.eesz.1M256.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +generic.menu.eesz.1M256.build.spiffs_pagesize=256 +generic.menu.eesz.1M256.upload.maximum_size=761840 +generic.menu.eesz.1M256.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M256.build.spiffs_start=0xBB000 +generic.menu.eesz.1M256.build.spiffs_end=0xFB000 +generic.menu.eesz.1M256.build.spiffs_blocksize=4096 +generic.menu.eesz.1M512=1M (512K SPIFFS) +generic.menu.eesz.1M512.build.flash_size=1M +generic.menu.eesz.1M512.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +generic.menu.eesz.1M512.build.spiffs_pagesize=256 +generic.menu.eesz.1M512.upload.maximum_size=499696 +generic.menu.eesz.1M512.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M512.build.spiffs_start=0x7B000 +generic.menu.eesz.1M512.build.spiffs_end=0xFB000 +generic.menu.eesz.1M512.build.spiffs_blocksize=4096 +generic.menu.eesz.2M=2M (no SPIFFS) +generic.menu.eesz.2M.build.flash_size=2M +generic.menu.eesz.2M.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld +generic.menu.eesz.2M.build.spiffs_pagesize=256 +generic.menu.eesz.2M.upload.maximum_size=1044464 +generic.menu.eesz.2M.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M128=2M (128K SPIFFS) +generic.menu.eesz.2M128.build.flash_size=2M +generic.menu.eesz.2M128.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld +generic.menu.eesz.2M128.build.spiffs_pagesize=256 +generic.menu.eesz.2M128.upload.maximum_size=1044464 +generic.menu.eesz.2M128.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M128.build.spiffs_start=0x1E0000 +generic.menu.eesz.2M128.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M128.build.spiffs_blocksize=4096 +generic.menu.eesz.2M256=2M (256K SPIFFS) +generic.menu.eesz.2M256.build.flash_size=2M +generic.menu.eesz.2M256.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld +generic.menu.eesz.2M256.build.spiffs_pagesize=256 +generic.menu.eesz.2M256.upload.maximum_size=1044464 +generic.menu.eesz.2M256.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M256.build.spiffs_start=0x1C0000 +generic.menu.eesz.2M256.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M256.build.spiffs_blocksize=4096 +generic.menu.eesz.2M512=2M (512K SPIFFS) +generic.menu.eesz.2M512.build.flash_size=2M +generic.menu.eesz.2M512.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld +generic.menu.eesz.2M512.build.spiffs_pagesize=256 +generic.menu.eesz.2M512.upload.maximum_size=1044464 +generic.menu.eesz.2M512.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M512.build.spiffs_start=0x180000 +generic.menu.eesz.2M512.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M512.build.spiffs_blocksize=8192 +generic.menu.eesz.2M1M=2M (1M SPIFFS) +generic.menu.eesz.2M1M.build.flash_size=2M +generic.menu.eesz.2M1M.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld +generic.menu.eesz.2M1M.build.spiffs_pagesize=256 +generic.menu.eesz.2M1M.upload.maximum_size=1044464 +generic.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M1M.build.spiffs_start=0x100000 +generic.menu.eesz.2M1M.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M1M.build.spiffs_blocksize=8192 +generic.menu.eesz.4M=4M (no SPIFFS) +generic.menu.eesz.4M.build.flash_size=4M +generic.menu.eesz.4M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +generic.menu.eesz.4M.build.spiffs_pagesize=256 +generic.menu.eesz.4M.upload.maximum_size=1044464 +generic.menu.eesz.4M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M1M=4M (1M SPIFFS) +generic.menu.eesz.4M1M.build.flash_size=4M +generic.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +generic.menu.eesz.4M1M.build.spiffs_pagesize=256 +generic.menu.eesz.4M1M.upload.maximum_size=1044464 +generic.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M1M.build.spiffs_start=0x300000 +generic.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +generic.menu.eesz.4M1M.build.spiffs_blocksize=8192 +generic.menu.eesz.4M2M=4M (2M SPIFFS) +generic.menu.eesz.4M2M.build.flash_size=4M +generic.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +generic.menu.eesz.4M2M.build.spiffs_pagesize=256 +generic.menu.eesz.4M2M.upload.maximum_size=1044464 +generic.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M2M.build.spiffs_start=0x200000 +generic.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +generic.menu.eesz.4M2M.build.spiffs_blocksize=8192 +generic.menu.eesz.4M3M=4M (3M SPIFFS) +generic.menu.eesz.4M3M.build.flash_size=4M +generic.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +generic.menu.eesz.4M3M.build.spiffs_pagesize=256 +generic.menu.eesz.4M3M.upload.maximum_size=1044464 +generic.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M3M.build.spiffs_start=0x100000 +generic.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +generic.menu.eesz.4M3M.build.spiffs_blocksize=8192 +generic.menu.eesz.8M6M=8M (6M SPIFFS) +generic.menu.eesz.8M6M.build.flash_size=8M +generic.menu.eesz.8M6M.build.flash_size_bytes=0x800000 +generic.menu.eesz.8M6M.build.flash_ld=eagle.flash.8m6m.ld +generic.menu.eesz.8M6M.build.spiffs_pagesize=256 +generic.menu.eesz.8M6M.upload.maximum_size=1044464 +generic.menu.eesz.8M6M.build.rfcal_addr=0x7FC000 +generic.menu.eesz.8M6M.build.spiffs_start=0x200000 +generic.menu.eesz.8M6M.build.spiffs_end=0x7FB000 +generic.menu.eesz.8M6M.build.spiffs_blocksize=8192 +generic.menu.eesz.8M7M=8M (7M SPIFFS) +generic.menu.eesz.8M7M.build.flash_size=8M +generic.menu.eesz.8M7M.build.flash_size_bytes=0x800000 +generic.menu.eesz.8M7M.build.flash_ld=eagle.flash.8m7m.ld +generic.menu.eesz.8M7M.build.spiffs_pagesize=256 +generic.menu.eesz.8M7M.upload.maximum_size=1044464 +generic.menu.eesz.8M7M.build.rfcal_addr=0x7FC000 +generic.menu.eesz.8M7M.build.spiffs_start=0x100000 +generic.menu.eesz.8M7M.build.spiffs_end=0x7FB000 +generic.menu.eesz.8M7M.build.spiffs_blocksize=8192 +generic.menu.eesz.16M14M=16M (14M SPIFFS) +generic.menu.eesz.16M14M.build.flash_size=16M +generic.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 +generic.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld +generic.menu.eesz.16M14M.build.spiffs_pagesize=256 +generic.menu.eesz.16M14M.upload.maximum_size=1044464 +generic.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 +generic.menu.eesz.16M14M.build.spiffs_start=0x200000 +generic.menu.eesz.16M14M.build.spiffs_end=0xFFB000 +generic.menu.eesz.16M14M.build.spiffs_blocksize=8192 +generic.menu.eesz.16M15M=16M (15M SPIFFS) +generic.menu.eesz.16M15M.build.flash_size=16M +generic.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 +generic.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld +generic.menu.eesz.16M15M.build.spiffs_pagesize=256 +generic.menu.eesz.16M15M.upload.maximum_size=1044464 +generic.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 +generic.menu.eesz.16M15M.build.spiffs_start=0x100000 +generic.menu.eesz.16M15M.build.spiffs_end=0xFFB000 +generic.menu.eesz.16M15M.build.spiffs_blocksize=8192 +generic.menu.led.2=2 +generic.menu.led.2.build.led=-DLED_BUILTIN=2 +generic.menu.led.0=0 +generic.menu.led.0.build.led=-DLED_BUILTIN=0 +generic.menu.led.1=1 +generic.menu.led.1.build.led=-DLED_BUILTIN=1 +generic.menu.led.3=3 +generic.menu.led.3.build.led=-DLED_BUILTIN=3 +generic.menu.led.4=4 +generic.menu.led.4.build.led=-DLED_BUILTIN=4 +generic.menu.led.5=5 +generic.menu.led.5.build.led=-DLED_BUILTIN=5 +generic.menu.led.6=6 +generic.menu.led.6.build.led=-DLED_BUILTIN=6 +generic.menu.led.7=7 +generic.menu.led.7.build.led=-DLED_BUILTIN=7 +generic.menu.led.8=8 +generic.menu.led.8.build.led=-DLED_BUILTIN=8 +generic.menu.led.9=9 +generic.menu.led.9.build.led=-DLED_BUILTIN=9 +generic.menu.led.10=10 +generic.menu.led.10.build.led=-DLED_BUILTIN=10 +generic.menu.led.11=11 +generic.menu.led.11.build.led=-DLED_BUILTIN=11 +generic.menu.led.12=12 +generic.menu.led.12.build.led=-DLED_BUILTIN=12 +generic.menu.led.13=13 +generic.menu.led.13.build.led=-DLED_BUILTIN=13 +generic.menu.led.14=14 +generic.menu.led.14.build.led=-DLED_BUILTIN=14 +generic.menu.led.15=15 +generic.menu.led.15.build.led=-DLED_BUILTIN=15 +generic.menu.ip.lm2f=v2 Lower Memory +generic.menu.ip.lm2f.build.lwip_include=lwip2/include +generic.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +generic.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +generic.menu.ip.hb2f=v2 Higher Bandwidth +generic.menu.ip.hb2f.build.lwip_include=lwip2/include +generic.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +generic.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +generic.menu.ip.lm2n=v2 Lower Memory (no features) +generic.menu.ip.lm2n.build.lwip_include=lwip2/include +generic.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +generic.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +generic.menu.ip.hb2n=v2 Higher Bandwidth (no features) +generic.menu.ip.hb2n.build.lwip_include=lwip2/include +generic.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +generic.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +generic.menu.ip.lm6f=v2 IPv6 Lower Memory +generic.menu.ip.lm6f.build.lwip_include=lwip2/include +generic.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +generic.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +generic.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +generic.menu.ip.hb6f.build.lwip_include=lwip2/include +generic.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +generic.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +generic.menu.ip.hb1=v1.4 Higher Bandwidth +generic.menu.ip.hb1.build.lwip_lib=-llwip_gcc +generic.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +generic.menu.ip.src=v1.4 Compile from source +generic.menu.ip.src.build.lwip_lib=-llwip_src +generic.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +generic.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +generic.menu.dbg.Disabled=Disabled +generic.menu.dbg.Disabled.build.debug_port= +generic.menu.dbg.Serial=Serial +generic.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +generic.menu.dbg.Serial1=Serial1 +generic.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +generic.menu.lvl.None____=None +generic.menu.lvl.None____.build.debug_level= +generic.menu.lvl.SSL=SSL +generic.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +generic.menu.lvl.TLS_MEM=TLS_MEM +generic.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +generic.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +generic.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.HTTP_SERVER=HTTP_SERVER +generic.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +generic.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +generic.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +generic.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +generic.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +generic.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.CORE=CORE +generic.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +generic.menu.lvl.WIFI=WIFI +generic.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +generic.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +generic.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +generic.menu.lvl.UPDATER=UPDATER +generic.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +generic.menu.lvl.OTA=OTA +generic.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +generic.menu.lvl.OOM=OOM +generic.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +generic.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +generic.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +generic.menu.wipe.none=Only Sketch +generic.menu.wipe.none.upload.erase_cmd= +generic.menu.wipe.sdk=Sketch + WiFi Settings +generic.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +generic.menu.wipe.all=All Flash Contents +generic.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +generic.menu.baud.115200=115200 +generic.menu.baud.115200.upload.speed=115200 +generic.menu.baud.9600=9600 +generic.menu.baud.9600.upload.speed=9600 +generic.menu.baud.57600=57600 +generic.menu.baud.57600.upload.speed=57600 +generic.menu.baud.230400.linux=230400 +generic.menu.baud.230400.macosx=230400 +generic.menu.baud.230400.upload.speed=230400 +generic.menu.baud.256000.windows=256000 +generic.menu.baud.256000.upload.speed=256000 +generic.menu.baud.460800.linux=460800 +generic.menu.baud.460800.macosx=460800 +generic.menu.baud.460800.upload.speed=460800 +generic.menu.baud.512000.windows=512000 +generic.menu.baud.512000.upload.speed=512000 +generic.menu.baud.921600=921600 +generic.menu.baud.921600.upload.speed=921600 + +############################################################## +esp8285.name=Generic ESP8285 Module +esp8285.build.board=ESP8266_ESP01 +esp8285.build.variant=esp8285 +esp8285.upload.tool=esptool +esp8285.upload.maximum_data_size=81920 +esp8285.upload.wait_for_upload_port=true +esp8285.upload.erase_cmd= +esp8285.serial.disableDTR=true +esp8285.serial.disableRTS=true +esp8285.build.mcu=esp8266 +esp8285.build.core=esp8266 +esp8285.build.spiffs_pagesize=256 +esp8285.build.debug_port= +esp8285.build.debug_level= +esp8285.menu.xtal.80=80 MHz +esp8285.menu.xtal.80.build.f_cpu=80000000L +esp8285.menu.xtal.160=160 MHz +esp8285.menu.xtal.160.build.f_cpu=160000000L +esp8285.menu.vt.flash=Flash +esp8285.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +esp8285.menu.vt.heap=Heap +esp8285.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +esp8285.menu.vt.iram=IRAM +esp8285.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +esp8285.menu.exception.disabled=Disabled +esp8285.menu.exception.disabled.build.exception_flags=-fno-exceptions +esp8285.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +esp8285.menu.exception.enabled=Enabled +esp8285.menu.exception.enabled.build.exception_flags=-fexceptions +esp8285.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +esp8285.menu.ResetMethod.ck=ck +esp8285.menu.ResetMethod.ck.upload.resetmethod=ck +esp8285.menu.ResetMethod.nodemcu=nodemcu +esp8285.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +esp8285.menu.ResetMethod.none=none +esp8285.menu.ResetMethod.none.upload.resetmethod=none +esp8285.menu.ResetMethod.dtrset=dtrset +esp8285.menu.ResetMethod.dtrset.upload.resetmethod=dtrset +esp8285.menu.CrystalFreq.26=26 MHz +esp8285.menu.CrystalFreq.40=40 MHz +esp8285.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +esp8285.build.flash_mode=dout +esp8285.build.flash_flags=-DFLASHMODE_DOUT +esp8285.build.flash_freq=40 +esp8285.menu.eesz.1M=1M (no SPIFFS) +esp8285.menu.eesz.1M.build.flash_size=1M +esp8285.menu.eesz.1M.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +esp8285.menu.eesz.1M.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M.upload.maximum_size=1023984 +esp8285.menu.eesz.1M.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M64=1M (64K SPIFFS) +esp8285.menu.eesz.1M64.build.flash_size=1M +esp8285.menu.eesz.1M64.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +esp8285.menu.eesz.1M64.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M64.upload.maximum_size=958448 +esp8285.menu.eesz.1M64.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M64.build.spiffs_start=0xEB000 +esp8285.menu.eesz.1M64.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M64.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M128=1M (128K SPIFFS) +esp8285.menu.eesz.1M128.build.flash_size=1M +esp8285.menu.eesz.1M128.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +esp8285.menu.eesz.1M128.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M128.upload.maximum_size=892912 +esp8285.menu.eesz.1M128.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M128.build.spiffs_start=0xDB000 +esp8285.menu.eesz.1M128.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M128.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M144=1M (144K SPIFFS) +esp8285.menu.eesz.1M144.build.flash_size=1M +esp8285.menu.eesz.1M144.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +esp8285.menu.eesz.1M144.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M144.upload.maximum_size=876528 +esp8285.menu.eesz.1M144.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M144.build.spiffs_start=0xD7000 +esp8285.menu.eesz.1M144.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M144.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M160=1M (160K SPIFFS) +esp8285.menu.eesz.1M160.build.flash_size=1M +esp8285.menu.eesz.1M160.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +esp8285.menu.eesz.1M160.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M160.upload.maximum_size=860144 +esp8285.menu.eesz.1M160.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M160.build.spiffs_start=0xD3000 +esp8285.menu.eesz.1M160.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M160.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M192=1M (192K SPIFFS) +esp8285.menu.eesz.1M192.build.flash_size=1M +esp8285.menu.eesz.1M192.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +esp8285.menu.eesz.1M192.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M192.upload.maximum_size=827376 +esp8285.menu.eesz.1M192.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M192.build.spiffs_start=0xCB000 +esp8285.menu.eesz.1M192.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M192.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M256=1M (256K SPIFFS) +esp8285.menu.eesz.1M256.build.flash_size=1M +esp8285.menu.eesz.1M256.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +esp8285.menu.eesz.1M256.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M256.upload.maximum_size=761840 +esp8285.menu.eesz.1M256.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M256.build.spiffs_start=0xBB000 +esp8285.menu.eesz.1M256.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M256.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M512=1M (512K SPIFFS) +esp8285.menu.eesz.1M512.build.flash_size=1M +esp8285.menu.eesz.1M512.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +esp8285.menu.eesz.1M512.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M512.upload.maximum_size=499696 +esp8285.menu.eesz.1M512.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M512.build.spiffs_start=0x7B000 +esp8285.menu.eesz.1M512.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M512.build.spiffs_blocksize=4096 +esp8285.menu.led.2=2 +esp8285.menu.led.2.build.led=-DLED_BUILTIN=2 +esp8285.menu.led.0=0 +esp8285.menu.led.0.build.led=-DLED_BUILTIN=0 +esp8285.menu.led.1=1 +esp8285.menu.led.1.build.led=-DLED_BUILTIN=1 +esp8285.menu.led.3=3 +esp8285.menu.led.3.build.led=-DLED_BUILTIN=3 +esp8285.menu.led.4=4 +esp8285.menu.led.4.build.led=-DLED_BUILTIN=4 +esp8285.menu.led.5=5 +esp8285.menu.led.5.build.led=-DLED_BUILTIN=5 +esp8285.menu.led.6=6 +esp8285.menu.led.6.build.led=-DLED_BUILTIN=6 +esp8285.menu.led.7=7 +esp8285.menu.led.7.build.led=-DLED_BUILTIN=7 +esp8285.menu.led.8=8 +esp8285.menu.led.8.build.led=-DLED_BUILTIN=8 +esp8285.menu.led.9=9 +esp8285.menu.led.9.build.led=-DLED_BUILTIN=9 +esp8285.menu.led.10=10 +esp8285.menu.led.10.build.led=-DLED_BUILTIN=10 +esp8285.menu.led.11=11 +esp8285.menu.led.11.build.led=-DLED_BUILTIN=11 +esp8285.menu.led.12=12 +esp8285.menu.led.12.build.led=-DLED_BUILTIN=12 +esp8285.menu.led.13=13 +esp8285.menu.led.13.build.led=-DLED_BUILTIN=13 +esp8285.menu.led.14=14 +esp8285.menu.led.14.build.led=-DLED_BUILTIN=14 +esp8285.menu.led.15=15 +esp8285.menu.led.15.build.led=-DLED_BUILTIN=15 +esp8285.menu.ip.lm2f=v2 Lower Memory +esp8285.menu.ip.lm2f.build.lwip_include=lwip2/include +esp8285.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +esp8285.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp8285.menu.ip.hb2f=v2 Higher Bandwidth +esp8285.menu.ip.hb2f.build.lwip_include=lwip2/include +esp8285.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +esp8285.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp8285.menu.ip.lm2n=v2 Lower Memory (no features) +esp8285.menu.ip.lm2n.build.lwip_include=lwip2/include +esp8285.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +esp8285.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp8285.menu.ip.hb2n=v2 Higher Bandwidth (no features) +esp8285.menu.ip.hb2n.build.lwip_include=lwip2/include +esp8285.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +esp8285.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp8285.menu.ip.lm6f=v2 IPv6 Lower Memory +esp8285.menu.ip.lm6f.build.lwip_include=lwip2/include +esp8285.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +esp8285.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp8285.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +esp8285.menu.ip.hb6f.build.lwip_include=lwip2/include +esp8285.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +esp8285.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp8285.menu.ip.hb1=v1.4 Higher Bandwidth +esp8285.menu.ip.hb1.build.lwip_lib=-llwip_gcc +esp8285.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +esp8285.menu.ip.src=v1.4 Compile from source +esp8285.menu.ip.src.build.lwip_lib=-llwip_src +esp8285.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +esp8285.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +esp8285.menu.dbg.Disabled=Disabled +esp8285.menu.dbg.Disabled.build.debug_port= +esp8285.menu.dbg.Serial=Serial +esp8285.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +esp8285.menu.dbg.Serial1=Serial1 +esp8285.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +esp8285.menu.lvl.None____=None +esp8285.menu.lvl.None____.build.debug_level= +esp8285.menu.lvl.SSL=SSL +esp8285.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +esp8285.menu.lvl.TLS_MEM=TLS_MEM +esp8285.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +esp8285.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +esp8285.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.HTTP_SERVER=HTTP_SERVER +esp8285.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +esp8285.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +esp8285.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +esp8285.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +esp8285.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +esp8285.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.CORE=CORE +esp8285.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +esp8285.menu.lvl.WIFI=WIFI +esp8285.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +esp8285.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +esp8285.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +esp8285.menu.lvl.UPDATER=UPDATER +esp8285.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +esp8285.menu.lvl.OTA=OTA +esp8285.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +esp8285.menu.lvl.OOM=OOM +esp8285.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +esp8285.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +esp8285.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +esp8285.menu.wipe.none=Only Sketch +esp8285.menu.wipe.none.upload.erase_cmd= +esp8285.menu.wipe.sdk=Sketch + WiFi Settings +esp8285.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +esp8285.menu.wipe.all=All Flash Contents +esp8285.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +esp8285.menu.baud.115200=115200 +esp8285.menu.baud.115200.upload.speed=115200 +esp8285.menu.baud.9600=9600 +esp8285.menu.baud.9600.upload.speed=9600 +esp8285.menu.baud.57600=57600 +esp8285.menu.baud.57600.upload.speed=57600 +esp8285.menu.baud.230400.linux=230400 +esp8285.menu.baud.230400.macosx=230400 +esp8285.menu.baud.230400.upload.speed=230400 +esp8285.menu.baud.256000.windows=256000 +esp8285.menu.baud.256000.upload.speed=256000 +esp8285.menu.baud.460800.linux=460800 +esp8285.menu.baud.460800.macosx=460800 +esp8285.menu.baud.460800.upload.speed=460800 +esp8285.menu.baud.512000.windows=512000 +esp8285.menu.baud.512000.upload.speed=512000 +esp8285.menu.baud.921600=921600 +esp8285.menu.baud.921600.upload.speed=921600 + +############################################################## +espduino.name=ESPDuino (ESP-13 Module) +espduino.build.board=ESP8266_ESP13 +espduino.build.variant=ESPDuino +espduino.menu.ResetMethod.v2=ESPduino-V2 +espduino.menu.ResetMethod.v2.upload.resetmethod=nodemcu +espduino.menu.ResetMethod.v1=ESPduino-V1 +espduino.menu.ResetMethod.v1.upload.resetmethod=ck +espduino.menu.UploadTool.esptool=Serial +espduino.menu.UploadTool.esptool.upload.tool=esptool +espduino.menu.UploadTool.esptool.upload.verbose=-vv +espduino.menu.UploadTool.espota=OTA +espduino.menu.UploadTool.espota.upload.tool=espota +espduino.upload.tool=esptool +espduino.upload.maximum_data_size=81920 +espduino.upload.wait_for_upload_port=true +espduino.upload.erase_cmd= +espduino.serial.disableDTR=true +espduino.serial.disableRTS=true +espduino.build.mcu=esp8266 +espduino.build.core=esp8266 +espduino.build.spiffs_pagesize=256 +espduino.build.debug_port= +espduino.build.debug_level= +espduino.menu.xtal.80=80 MHz +espduino.menu.xtal.80.build.f_cpu=80000000L +espduino.menu.xtal.160=160 MHz +espduino.menu.xtal.160.build.f_cpu=160000000L +espduino.menu.vt.flash=Flash +espduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espduino.menu.vt.heap=Heap +espduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espduino.menu.vt.iram=IRAM +espduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espduino.menu.exception.disabled=Disabled +espduino.menu.exception.disabled.build.exception_flags=-fno-exceptions +espduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espduino.menu.exception.enabled=Enabled +espduino.menu.exception.enabled.build.exception_flags=-fexceptions +espduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espduino.build.flash_mode=dio +espduino.build.flash_flags=-DFLASHMODE_DIO +espduino.build.flash_freq=40 +espduino.menu.eesz.4M=4M (no SPIFFS) +espduino.menu.eesz.4M.build.flash_size=4M +espduino.menu.eesz.4M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espduino.menu.eesz.4M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M.upload.maximum_size=1044464 +espduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M1M=4M (1M SPIFFS) +espduino.menu.eesz.4M1M.build.flash_size=4M +espduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espduino.menu.eesz.4M1M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M1M.upload.maximum_size=1044464 +espduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M1M.build.spiffs_start=0x300000 +espduino.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +espduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espduino.menu.eesz.4M2M=4M (2M SPIFFS) +espduino.menu.eesz.4M2M.build.flash_size=4M +espduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espduino.menu.eesz.4M2M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M2M.upload.maximum_size=1044464 +espduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M2M.build.spiffs_start=0x200000 +espduino.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +espduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espduino.menu.eesz.4M3M=4M (3M SPIFFS) +espduino.menu.eesz.4M3M.build.flash_size=4M +espduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espduino.menu.eesz.4M3M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M3M.upload.maximum_size=1044464 +espduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M3M.build.spiffs_start=0x100000 +espduino.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +espduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espduino.menu.ip.lm2f=v2 Lower Memory +espduino.menu.ip.lm2f.build.lwip_include=lwip2/include +espduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espduino.menu.ip.hb2f=v2 Higher Bandwidth +espduino.menu.ip.hb2f.build.lwip_include=lwip2/include +espduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espduino.menu.ip.lm2n=v2 Lower Memory (no features) +espduino.menu.ip.lm2n.build.lwip_include=lwip2/include +espduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espduino.menu.ip.hb2n.build.lwip_include=lwip2/include +espduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espduino.menu.ip.lm6f=v2 IPv6 Lower Memory +espduino.menu.ip.lm6f.build.lwip_include=lwip2/include +espduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espduino.menu.ip.hb6f.build.lwip_include=lwip2/include +espduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espduino.menu.ip.hb1=v1.4 Higher Bandwidth +espduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espduino.menu.ip.src=v1.4 Compile from source +espduino.menu.ip.src.build.lwip_lib=-llwip_src +espduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espduino.menu.dbg.Disabled=Disabled +espduino.menu.dbg.Disabled.build.debug_port= +espduino.menu.dbg.Serial=Serial +espduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espduino.menu.dbg.Serial1=Serial1 +espduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espduino.menu.lvl.None____=None +espduino.menu.lvl.None____.build.debug_level= +espduino.menu.lvl.SSL=SSL +espduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espduino.menu.lvl.TLS_MEM=TLS_MEM +espduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.HTTP_SERVER=HTTP_SERVER +espduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.CORE=CORE +espduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espduino.menu.lvl.WIFI=WIFI +espduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espduino.menu.lvl.UPDATER=UPDATER +espduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espduino.menu.lvl.OTA=OTA +espduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espduino.menu.lvl.OOM=OOM +espduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espduino.menu.wipe.none=Only Sketch +espduino.menu.wipe.none.upload.erase_cmd= +espduino.menu.wipe.sdk=Sketch + WiFi Settings +espduino.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +espduino.menu.wipe.all=All Flash Contents +espduino.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +espduino.menu.baud.115200=115200 +espduino.menu.baud.115200.upload.speed=115200 +espduino.menu.baud.9600=9600 +espduino.menu.baud.9600.upload.speed=9600 +espduino.menu.baud.57600=57600 +espduino.menu.baud.57600.upload.speed=57600 +espduino.menu.baud.230400.linux=230400 +espduino.menu.baud.230400.macosx=230400 +espduino.menu.baud.230400.upload.speed=230400 +espduino.menu.baud.256000.windows=256000 +espduino.menu.baud.256000.upload.speed=256000 +espduino.menu.baud.460800.linux=460800 +espduino.menu.baud.460800.macosx=460800 +espduino.menu.baud.460800.upload.speed=460800 +espduino.menu.baud.512000.windows=512000 +espduino.menu.baud.512000.upload.speed=512000 +espduino.menu.baud.921600=921600 +espduino.menu.baud.921600.upload.speed=921600 + +############################################################## +huzzah.name=Adafruit Feather HUZZAH ESP8266 +huzzah.build.board=ESP8266_ESP12 +huzzah.build.variant=adafruit +huzzah.upload.tool=esptool +huzzah.upload.maximum_data_size=81920 +huzzah.upload.wait_for_upload_port=true +huzzah.upload.erase_cmd= +huzzah.serial.disableDTR=true +huzzah.serial.disableRTS=true +huzzah.build.mcu=esp8266 +huzzah.build.core=esp8266 +huzzah.build.spiffs_pagesize=256 +huzzah.build.debug_port= +huzzah.build.debug_level= +huzzah.menu.xtal.80=80 MHz +huzzah.menu.xtal.80.build.f_cpu=80000000L +huzzah.menu.xtal.160=160 MHz +huzzah.menu.xtal.160.build.f_cpu=160000000L +huzzah.menu.vt.flash=Flash +huzzah.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +huzzah.menu.vt.heap=Heap +huzzah.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +huzzah.menu.vt.iram=IRAM +huzzah.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +huzzah.menu.exception.disabled=Disabled +huzzah.menu.exception.disabled.build.exception_flags=-fno-exceptions +huzzah.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +huzzah.menu.exception.enabled=Enabled +huzzah.menu.exception.enabled.build.exception_flags=-fexceptions +huzzah.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +huzzah.upload.resetmethod=nodemcu +huzzah.build.flash_mode=qio +huzzah.build.flash_flags=-DFLASHMODE_QIO +huzzah.build.flash_freq=40 +huzzah.menu.eesz.4M=4M (no SPIFFS) +huzzah.menu.eesz.4M.build.flash_size=4M +huzzah.menu.eesz.4M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +huzzah.menu.eesz.4M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M1M=4M (1M SPIFFS) +huzzah.menu.eesz.4M1M.build.flash_size=4M +huzzah.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +huzzah.menu.eesz.4M1M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M1M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M1M.build.spiffs_start=0x300000 +huzzah.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +huzzah.menu.eesz.4M1M.build.spiffs_blocksize=8192 +huzzah.menu.eesz.4M2M=4M (2M SPIFFS) +huzzah.menu.eesz.4M2M.build.flash_size=4M +huzzah.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +huzzah.menu.eesz.4M2M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M2M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M2M.build.spiffs_start=0x200000 +huzzah.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +huzzah.menu.eesz.4M2M.build.spiffs_blocksize=8192 +huzzah.menu.eesz.4M3M=4M (3M SPIFFS) +huzzah.menu.eesz.4M3M.build.flash_size=4M +huzzah.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +huzzah.menu.eesz.4M3M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M3M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M3M.build.spiffs_start=0x100000 +huzzah.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +huzzah.menu.eesz.4M3M.build.spiffs_blocksize=8192 +huzzah.menu.ip.lm2f=v2 Lower Memory +huzzah.menu.ip.lm2f.build.lwip_include=lwip2/include +huzzah.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +huzzah.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +huzzah.menu.ip.hb2f=v2 Higher Bandwidth +huzzah.menu.ip.hb2f.build.lwip_include=lwip2/include +huzzah.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +huzzah.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +huzzah.menu.ip.lm2n=v2 Lower Memory (no features) +huzzah.menu.ip.lm2n.build.lwip_include=lwip2/include +huzzah.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +huzzah.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +huzzah.menu.ip.hb2n=v2 Higher Bandwidth (no features) +huzzah.menu.ip.hb2n.build.lwip_include=lwip2/include +huzzah.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +huzzah.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +huzzah.menu.ip.lm6f=v2 IPv6 Lower Memory +huzzah.menu.ip.lm6f.build.lwip_include=lwip2/include +huzzah.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +huzzah.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +huzzah.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +huzzah.menu.ip.hb6f.build.lwip_include=lwip2/include +huzzah.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +huzzah.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +huzzah.menu.ip.hb1=v1.4 Higher Bandwidth +huzzah.menu.ip.hb1.build.lwip_lib=-llwip_gcc +huzzah.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +huzzah.menu.ip.src=v1.4 Compile from source +huzzah.menu.ip.src.build.lwip_lib=-llwip_src +huzzah.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +huzzah.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +huzzah.menu.dbg.Disabled=Disabled +huzzah.menu.dbg.Disabled.build.debug_port= +huzzah.menu.dbg.Serial=Serial +huzzah.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +huzzah.menu.dbg.Serial1=Serial1 +huzzah.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +huzzah.menu.lvl.None____=None +huzzah.menu.lvl.None____.build.debug_level= +huzzah.menu.lvl.SSL=SSL +huzzah.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +huzzah.menu.lvl.TLS_MEM=TLS_MEM +huzzah.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +huzzah.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +huzzah.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.HTTP_SERVER=HTTP_SERVER +huzzah.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +huzzah.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +huzzah.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +huzzah.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +huzzah.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +huzzah.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.CORE=CORE +huzzah.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +huzzah.menu.lvl.WIFI=WIFI +huzzah.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +huzzah.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +huzzah.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +huzzah.menu.lvl.UPDATER=UPDATER +huzzah.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +huzzah.menu.lvl.OTA=OTA +huzzah.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +huzzah.menu.lvl.OOM=OOM +huzzah.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +huzzah.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +huzzah.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +huzzah.menu.wipe.none=Only Sketch +huzzah.menu.wipe.none.upload.erase_cmd= +huzzah.menu.wipe.sdk=Sketch + WiFi Settings +huzzah.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +huzzah.menu.wipe.all=All Flash Contents +huzzah.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +huzzah.menu.baud.115200=115200 +huzzah.menu.baud.115200.upload.speed=115200 +huzzah.menu.baud.9600=9600 +huzzah.menu.baud.9600.upload.speed=9600 +huzzah.menu.baud.57600=57600 +huzzah.menu.baud.57600.upload.speed=57600 +huzzah.menu.baud.230400.linux=230400 +huzzah.menu.baud.230400.macosx=230400 +huzzah.menu.baud.230400.upload.speed=230400 +huzzah.menu.baud.256000.windows=256000 +huzzah.menu.baud.256000.upload.speed=256000 +huzzah.menu.baud.460800.linux=460800 +huzzah.menu.baud.460800.macosx=460800 +huzzah.menu.baud.460800.upload.speed=460800 +huzzah.menu.baud.512000.windows=512000 +huzzah.menu.baud.512000.upload.speed=512000 +huzzah.menu.baud.921600=921600 +huzzah.menu.baud.921600.upload.speed=921600 + +############################################################## +inventone.name=Invent One +inventone.build.board=ESP8266_GENERIC +inventone.build.variant=inventone +inventone.upload.tool=esptool +inventone.upload.maximum_data_size=81920 +inventone.upload.wait_for_upload_port=true +inventone.upload.erase_cmd= +inventone.serial.disableDTR=true +inventone.serial.disableRTS=true +inventone.build.mcu=esp8266 +inventone.build.core=esp8266 +inventone.build.spiffs_pagesize=256 +inventone.build.debug_port= +inventone.build.debug_level= +inventone.menu.xtal.80=80 MHz +inventone.menu.xtal.80.build.f_cpu=80000000L +inventone.menu.xtal.160=160 MHz +inventone.menu.xtal.160.build.f_cpu=160000000L +inventone.menu.vt.flash=Flash +inventone.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +inventone.menu.vt.heap=Heap +inventone.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +inventone.menu.vt.iram=IRAM +inventone.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +inventone.menu.exception.disabled=Disabled +inventone.menu.exception.disabled.build.exception_flags=-fno-exceptions +inventone.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +inventone.menu.exception.enabled=Enabled +inventone.menu.exception.enabled.build.exception_flags=-fexceptions +inventone.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +inventone.upload.resetmethod=nodemcu +inventone.build.flash_mode=dio +inventone.build.flash_flags=-DFLASHMODE_DIO +inventone.build.flash_freq=40 +inventone.menu.eesz.4M=4M (no SPIFFS) +inventone.menu.eesz.4M.build.flash_size=4M +inventone.menu.eesz.4M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +inventone.menu.eesz.4M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M.upload.maximum_size=1044464 +inventone.menu.eesz.4M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M1M=4M (1M SPIFFS) +inventone.menu.eesz.4M1M.build.flash_size=4M +inventone.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +inventone.menu.eesz.4M1M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M1M.upload.maximum_size=1044464 +inventone.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M1M.build.spiffs_start=0x300000 +inventone.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +inventone.menu.eesz.4M1M.build.spiffs_blocksize=8192 +inventone.menu.eesz.4M2M=4M (2M SPIFFS) +inventone.menu.eesz.4M2M.build.flash_size=4M +inventone.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +inventone.menu.eesz.4M2M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M2M.upload.maximum_size=1044464 +inventone.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M2M.build.spiffs_start=0x200000 +inventone.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +inventone.menu.eesz.4M2M.build.spiffs_blocksize=8192 +inventone.menu.eesz.4M3M=4M (3M SPIFFS) +inventone.menu.eesz.4M3M.build.flash_size=4M +inventone.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +inventone.menu.eesz.4M3M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M3M.upload.maximum_size=1044464 +inventone.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M3M.build.spiffs_start=0x100000 +inventone.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +inventone.menu.eesz.4M3M.build.spiffs_blocksize=8192 +inventone.menu.ip.lm2f=v2 Lower Memory +inventone.menu.ip.lm2f.build.lwip_include=lwip2/include +inventone.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +inventone.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +inventone.menu.ip.hb2f=v2 Higher Bandwidth +inventone.menu.ip.hb2f.build.lwip_include=lwip2/include +inventone.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +inventone.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +inventone.menu.ip.lm2n=v2 Lower Memory (no features) +inventone.menu.ip.lm2n.build.lwip_include=lwip2/include +inventone.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +inventone.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +inventone.menu.ip.hb2n=v2 Higher Bandwidth (no features) +inventone.menu.ip.hb2n.build.lwip_include=lwip2/include +inventone.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +inventone.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +inventone.menu.ip.lm6f=v2 IPv6 Lower Memory +inventone.menu.ip.lm6f.build.lwip_include=lwip2/include +inventone.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +inventone.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +inventone.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +inventone.menu.ip.hb6f.build.lwip_include=lwip2/include +inventone.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +inventone.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +inventone.menu.ip.hb1=v1.4 Higher Bandwidth +inventone.menu.ip.hb1.build.lwip_lib=-llwip_gcc +inventone.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +inventone.menu.ip.src=v1.4 Compile from source +inventone.menu.ip.src.build.lwip_lib=-llwip_src +inventone.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +inventone.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +inventone.menu.dbg.Disabled=Disabled +inventone.menu.dbg.Disabled.build.debug_port= +inventone.menu.dbg.Serial=Serial +inventone.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +inventone.menu.dbg.Serial1=Serial1 +inventone.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +inventone.menu.lvl.None____=None +inventone.menu.lvl.None____.build.debug_level= +inventone.menu.lvl.SSL=SSL +inventone.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +inventone.menu.lvl.TLS_MEM=TLS_MEM +inventone.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +inventone.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +inventone.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.HTTP_SERVER=HTTP_SERVER +inventone.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +inventone.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +inventone.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +inventone.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +inventone.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +inventone.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.CORE=CORE +inventone.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +inventone.menu.lvl.WIFI=WIFI +inventone.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +inventone.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +inventone.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +inventone.menu.lvl.UPDATER=UPDATER +inventone.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +inventone.menu.lvl.OTA=OTA +inventone.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +inventone.menu.lvl.OOM=OOM +inventone.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +inventone.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +inventone.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +inventone.menu.wipe.none=Only Sketch +inventone.menu.wipe.none.upload.erase_cmd= +inventone.menu.wipe.sdk=Sketch + WiFi Settings +inventone.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +inventone.menu.wipe.all=All Flash Contents +inventone.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +inventone.menu.baud.115200=115200 +inventone.menu.baud.115200.upload.speed=115200 +inventone.menu.baud.9600=9600 +inventone.menu.baud.9600.upload.speed=9600 +inventone.menu.baud.57600=57600 +inventone.menu.baud.57600.upload.speed=57600 +inventone.menu.baud.230400.linux=230400 +inventone.menu.baud.230400.macosx=230400 +inventone.menu.baud.230400.upload.speed=230400 +inventone.menu.baud.256000.windows=256000 +inventone.menu.baud.256000.upload.speed=256000 +inventone.menu.baud.460800.linux=460800 +inventone.menu.baud.460800.macosx=460800 +inventone.menu.baud.460800.upload.speed=460800 +inventone.menu.baud.512000.windows=512000 +inventone.menu.baud.512000.upload.speed=512000 +inventone.menu.baud.921600=921600 +inventone.menu.baud.921600.upload.speed=921600 + +############################################################## +cw01.name=XinaBox CW01 +cw01.build.board=ESP8266_GENERIC +cw01.build.variant=xinabox +cw01.upload.tool=esptool +cw01.upload.maximum_data_size=81920 +cw01.upload.wait_for_upload_port=true +cw01.upload.erase_cmd= +cw01.serial.disableDTR=true +cw01.serial.disableRTS=true +cw01.build.mcu=esp8266 +cw01.build.core=esp8266 +cw01.build.spiffs_pagesize=256 +cw01.build.debug_port= +cw01.build.debug_level= +cw01.menu.xtal.80=80 MHz +cw01.menu.xtal.80.build.f_cpu=80000000L +cw01.menu.xtal.160=160 MHz +cw01.menu.xtal.160.build.f_cpu=160000000L +cw01.menu.vt.flash=Flash +cw01.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +cw01.menu.vt.heap=Heap +cw01.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +cw01.menu.vt.iram=IRAM +cw01.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +cw01.menu.exception.disabled=Disabled +cw01.menu.exception.disabled.build.exception_flags=-fno-exceptions +cw01.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +cw01.menu.exception.enabled=Enabled +cw01.menu.exception.enabled.build.exception_flags=-fexceptions +cw01.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +cw01.upload.resetmethod=nodemcu +cw01.menu.CrystalFreq.26=26 MHz +cw01.menu.CrystalFreq.40=40 MHz +cw01.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +cw01.build.flash_mode=dio +cw01.build.flash_flags=-DFLASHMODE_DIO +cw01.build.flash_freq=40 +cw01.menu.eesz.4M=4M (no SPIFFS) +cw01.menu.eesz.4M.build.flash_size=4M +cw01.menu.eesz.4M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +cw01.menu.eesz.4M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M.upload.maximum_size=1044464 +cw01.menu.eesz.4M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M1M=4M (1M SPIFFS) +cw01.menu.eesz.4M1M.build.flash_size=4M +cw01.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +cw01.menu.eesz.4M1M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M1M.upload.maximum_size=1044464 +cw01.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M1M.build.spiffs_start=0x300000 +cw01.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +cw01.menu.eesz.4M1M.build.spiffs_blocksize=8192 +cw01.menu.eesz.4M2M=4M (2M SPIFFS) +cw01.menu.eesz.4M2M.build.flash_size=4M +cw01.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +cw01.menu.eesz.4M2M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M2M.upload.maximum_size=1044464 +cw01.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M2M.build.spiffs_start=0x200000 +cw01.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +cw01.menu.eesz.4M2M.build.spiffs_blocksize=8192 +cw01.menu.eesz.4M3M=4M (3M SPIFFS) +cw01.menu.eesz.4M3M.build.flash_size=4M +cw01.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +cw01.menu.eesz.4M3M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M3M.upload.maximum_size=1044464 +cw01.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M3M.build.spiffs_start=0x100000 +cw01.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +cw01.menu.eesz.4M3M.build.spiffs_blocksize=8192 +cw01.menu.ip.lm2f=v2 Lower Memory +cw01.menu.ip.lm2f.build.lwip_include=lwip2/include +cw01.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +cw01.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +cw01.menu.ip.hb2f=v2 Higher Bandwidth +cw01.menu.ip.hb2f.build.lwip_include=lwip2/include +cw01.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +cw01.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +cw01.menu.ip.lm2n=v2 Lower Memory (no features) +cw01.menu.ip.lm2n.build.lwip_include=lwip2/include +cw01.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +cw01.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +cw01.menu.ip.hb2n=v2 Higher Bandwidth (no features) +cw01.menu.ip.hb2n.build.lwip_include=lwip2/include +cw01.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +cw01.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +cw01.menu.ip.lm6f=v2 IPv6 Lower Memory +cw01.menu.ip.lm6f.build.lwip_include=lwip2/include +cw01.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +cw01.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +cw01.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +cw01.menu.ip.hb6f.build.lwip_include=lwip2/include +cw01.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +cw01.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +cw01.menu.ip.hb1=v1.4 Higher Bandwidth +cw01.menu.ip.hb1.build.lwip_lib=-llwip_gcc +cw01.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +cw01.menu.ip.src=v1.4 Compile from source +cw01.menu.ip.src.build.lwip_lib=-llwip_src +cw01.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +cw01.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +cw01.menu.dbg.Disabled=Disabled +cw01.menu.dbg.Disabled.build.debug_port= +cw01.menu.dbg.Serial=Serial +cw01.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +cw01.menu.dbg.Serial1=Serial1 +cw01.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +cw01.menu.lvl.None____=None +cw01.menu.lvl.None____.build.debug_level= +cw01.menu.lvl.SSL=SSL +cw01.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +cw01.menu.lvl.TLS_MEM=TLS_MEM +cw01.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +cw01.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +cw01.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.HTTP_SERVER=HTTP_SERVER +cw01.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +cw01.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +cw01.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +cw01.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +cw01.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +cw01.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.CORE=CORE +cw01.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +cw01.menu.lvl.WIFI=WIFI +cw01.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +cw01.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +cw01.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +cw01.menu.lvl.UPDATER=UPDATER +cw01.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +cw01.menu.lvl.OTA=OTA +cw01.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +cw01.menu.lvl.OOM=OOM +cw01.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +cw01.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +cw01.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +cw01.menu.wipe.none=Only Sketch +cw01.menu.wipe.none.upload.erase_cmd= +cw01.menu.wipe.sdk=Sketch + WiFi Settings +cw01.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +cw01.menu.wipe.all=All Flash Contents +cw01.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +cw01.menu.baud.115200=115200 +cw01.menu.baud.115200.upload.speed=115200 +cw01.menu.baud.9600=9600 +cw01.menu.baud.9600.upload.speed=9600 +cw01.menu.baud.57600=57600 +cw01.menu.baud.57600.upload.speed=57600 +cw01.menu.baud.230400.linux=230400 +cw01.menu.baud.230400.macosx=230400 +cw01.menu.baud.230400.upload.speed=230400 +cw01.menu.baud.256000.windows=256000 +cw01.menu.baud.256000.upload.speed=256000 +cw01.menu.baud.460800.linux=460800 +cw01.menu.baud.460800.macosx=460800 +cw01.menu.baud.460800.upload.speed=460800 +cw01.menu.baud.512000.windows=512000 +cw01.menu.baud.512000.upload.speed=512000 +cw01.menu.baud.921600=921600 +cw01.menu.baud.921600.upload.speed=921600 + +############################################################## +espresso_lite_v1.name=ESPresso Lite 1.0 +espresso_lite_v1.build.board=ESP8266_ESPRESSO_LITE_V1 +espresso_lite_v1.build.variant=espresso_lite_v1 +espresso_lite_v1.upload.tool=esptool +espresso_lite_v1.upload.maximum_data_size=81920 +espresso_lite_v1.upload.wait_for_upload_port=true +espresso_lite_v1.upload.erase_cmd= +espresso_lite_v1.serial.disableDTR=true +espresso_lite_v1.serial.disableRTS=true +espresso_lite_v1.build.mcu=esp8266 +espresso_lite_v1.build.core=esp8266 +espresso_lite_v1.build.spiffs_pagesize=256 +espresso_lite_v1.build.debug_port= +espresso_lite_v1.build.debug_level= +espresso_lite_v1.menu.xtal.80=80 MHz +espresso_lite_v1.menu.xtal.80.build.f_cpu=80000000L +espresso_lite_v1.menu.xtal.160=160 MHz +espresso_lite_v1.menu.xtal.160.build.f_cpu=160000000L +espresso_lite_v1.menu.vt.flash=Flash +espresso_lite_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espresso_lite_v1.menu.vt.heap=Heap +espresso_lite_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espresso_lite_v1.menu.vt.iram=IRAM +espresso_lite_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espresso_lite_v1.menu.exception.disabled=Disabled +espresso_lite_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions +espresso_lite_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espresso_lite_v1.menu.exception.enabled=Enabled +espresso_lite_v1.menu.exception.enabled.build.exception_flags=-fexceptions +espresso_lite_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espresso_lite_v1.build.flash_mode=dio +espresso_lite_v1.build.flash_flags=-DFLASHMODE_DIO +espresso_lite_v1.build.flash_freq=40 +espresso_lite_v1.menu.eesz.4M=4M (no SPIFFS) +espresso_lite_v1.menu.eesz.4M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espresso_lite_v1.menu.eesz.4M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M1M=4M (1M SPIFFS) +espresso_lite_v1.menu.eesz.4M1M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M1M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espresso_lite_v1.menu.eesz.4M2M=4M (2M SPIFFS) +espresso_lite_v1.menu.eesz.4M2M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M2M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espresso_lite_v1.menu.eesz.4M3M=4M (3M SPIFFS) +espresso_lite_v1.menu.eesz.4M3M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M3M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espresso_lite_v1.menu.ResetMethod.ck=ck +espresso_lite_v1.menu.ResetMethod.ck.upload.resetmethod=ck +espresso_lite_v1.menu.ResetMethod.nodemcu=nodemcu +espresso_lite_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +espresso_lite_v1.menu.ip.lm2f=v2 Lower Memory +espresso_lite_v1.menu.ip.lm2f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espresso_lite_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.hb2f=v2 Higher Bandwidth +espresso_lite_v1.menu.ip.hb2f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espresso_lite_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.lm2n=v2 Lower Memory (no features) +espresso_lite_v1.menu.ip.lm2n.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espresso_lite_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espresso_lite_v1.menu.ip.hb2n.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espresso_lite_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.lm6f=v2 IPv6 Lower Memory +espresso_lite_v1.menu.ip.lm6f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espresso_lite_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espresso_lite_v1.menu.ip.hb6f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espresso_lite_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v1.menu.ip.hb1=v1.4 Higher Bandwidth +espresso_lite_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espresso_lite_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v1.menu.ip.src=v1.4 Compile from source +espresso_lite_v1.menu.ip.src.build.lwip_lib=-llwip_src +espresso_lite_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espresso_lite_v1.menu.dbg.Disabled=Disabled +espresso_lite_v1.menu.dbg.Disabled.build.debug_port= +espresso_lite_v1.menu.dbg.Serial=Serial +espresso_lite_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espresso_lite_v1.menu.dbg.Serial1=Serial1 +espresso_lite_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espresso_lite_v1.menu.lvl.None____=None +espresso_lite_v1.menu.lvl.None____.build.debug_level= +espresso_lite_v1.menu.lvl.SSL=SSL +espresso_lite_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espresso_lite_v1.menu.lvl.TLS_MEM=TLS_MEM +espresso_lite_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espresso_lite_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espresso_lite_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER +espresso_lite_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espresso_lite_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.CORE=CORE +espresso_lite_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espresso_lite_v1.menu.lvl.WIFI=WIFI +espresso_lite_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espresso_lite_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espresso_lite_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espresso_lite_v1.menu.lvl.UPDATER=UPDATER +espresso_lite_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espresso_lite_v1.menu.lvl.OTA=OTA +espresso_lite_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espresso_lite_v1.menu.lvl.OOM=OOM +espresso_lite_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espresso_lite_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espresso_lite_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espresso_lite_v1.menu.wipe.none=Only Sketch +espresso_lite_v1.menu.wipe.none.upload.erase_cmd= +espresso_lite_v1.menu.wipe.sdk=Sketch + WiFi Settings +espresso_lite_v1.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +espresso_lite_v1.menu.wipe.all=All Flash Contents +espresso_lite_v1.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +espresso_lite_v1.menu.baud.115200=115200 +espresso_lite_v1.menu.baud.115200.upload.speed=115200 +espresso_lite_v1.menu.baud.9600=9600 +espresso_lite_v1.menu.baud.9600.upload.speed=9600 +espresso_lite_v1.menu.baud.57600=57600 +espresso_lite_v1.menu.baud.57600.upload.speed=57600 +espresso_lite_v1.menu.baud.230400.linux=230400 +espresso_lite_v1.menu.baud.230400.macosx=230400 +espresso_lite_v1.menu.baud.230400.upload.speed=230400 +espresso_lite_v1.menu.baud.256000.windows=256000 +espresso_lite_v1.menu.baud.256000.upload.speed=256000 +espresso_lite_v1.menu.baud.460800.linux=460800 +espresso_lite_v1.menu.baud.460800.macosx=460800 +espresso_lite_v1.menu.baud.460800.upload.speed=460800 +espresso_lite_v1.menu.baud.512000.windows=512000 +espresso_lite_v1.menu.baud.512000.upload.speed=512000 +espresso_lite_v1.menu.baud.921600=921600 +espresso_lite_v1.menu.baud.921600.upload.speed=921600 + +############################################################## +espresso_lite_v2.name=ESPresso Lite 2.0 +espresso_lite_v2.build.board=ESP8266_ESPRESSO_LITE_V2 +espresso_lite_v2.build.variant=espresso_lite_v2 +espresso_lite_v2.upload.tool=esptool +espresso_lite_v2.upload.maximum_data_size=81920 +espresso_lite_v2.upload.wait_for_upload_port=true +espresso_lite_v2.upload.erase_cmd= +espresso_lite_v2.serial.disableDTR=true +espresso_lite_v2.serial.disableRTS=true +espresso_lite_v2.build.mcu=esp8266 +espresso_lite_v2.build.core=esp8266 +espresso_lite_v2.build.spiffs_pagesize=256 +espresso_lite_v2.build.debug_port= +espresso_lite_v2.build.debug_level= +espresso_lite_v2.menu.xtal.80=80 MHz +espresso_lite_v2.menu.xtal.80.build.f_cpu=80000000L +espresso_lite_v2.menu.xtal.160=160 MHz +espresso_lite_v2.menu.xtal.160.build.f_cpu=160000000L +espresso_lite_v2.menu.vt.flash=Flash +espresso_lite_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espresso_lite_v2.menu.vt.heap=Heap +espresso_lite_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espresso_lite_v2.menu.vt.iram=IRAM +espresso_lite_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espresso_lite_v2.menu.exception.disabled=Disabled +espresso_lite_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions +espresso_lite_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espresso_lite_v2.menu.exception.enabled=Enabled +espresso_lite_v2.menu.exception.enabled.build.exception_flags=-fexceptions +espresso_lite_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espresso_lite_v2.build.flash_mode=dio +espresso_lite_v2.build.flash_flags=-DFLASHMODE_DIO +espresso_lite_v2.build.flash_freq=40 +espresso_lite_v2.menu.eesz.4M=4M (no SPIFFS) +espresso_lite_v2.menu.eesz.4M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espresso_lite_v2.menu.eesz.4M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M1M=4M (1M SPIFFS) +espresso_lite_v2.menu.eesz.4M1M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M1M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espresso_lite_v2.menu.eesz.4M2M=4M (2M SPIFFS) +espresso_lite_v2.menu.eesz.4M2M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M2M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espresso_lite_v2.menu.eesz.4M3M=4M (3M SPIFFS) +espresso_lite_v2.menu.eesz.4M3M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M3M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espresso_lite_v2.menu.ResetMethod.ck=ck +espresso_lite_v2.menu.ResetMethod.ck.upload.resetmethod=ck +espresso_lite_v2.menu.ResetMethod.nodemcu=nodemcu +espresso_lite_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +espresso_lite_v2.menu.ip.lm2f=v2 Lower Memory +espresso_lite_v2.menu.ip.lm2f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espresso_lite_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.hb2f=v2 Higher Bandwidth +espresso_lite_v2.menu.ip.hb2f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espresso_lite_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.lm2n=v2 Lower Memory (no features) +espresso_lite_v2.menu.ip.lm2n.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espresso_lite_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espresso_lite_v2.menu.ip.hb2n.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espresso_lite_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.lm6f=v2 IPv6 Lower Memory +espresso_lite_v2.menu.ip.lm6f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espresso_lite_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espresso_lite_v2.menu.ip.hb6f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espresso_lite_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v2.menu.ip.hb1=v1.4 Higher Bandwidth +espresso_lite_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espresso_lite_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v2.menu.ip.src=v1.4 Compile from source +espresso_lite_v2.menu.ip.src.build.lwip_lib=-llwip_src +espresso_lite_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espresso_lite_v2.menu.dbg.Disabled=Disabled +espresso_lite_v2.menu.dbg.Disabled.build.debug_port= +espresso_lite_v2.menu.dbg.Serial=Serial +espresso_lite_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espresso_lite_v2.menu.dbg.Serial1=Serial1 +espresso_lite_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espresso_lite_v2.menu.lvl.None____=None +espresso_lite_v2.menu.lvl.None____.build.debug_level= +espresso_lite_v2.menu.lvl.SSL=SSL +espresso_lite_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espresso_lite_v2.menu.lvl.TLS_MEM=TLS_MEM +espresso_lite_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espresso_lite_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espresso_lite_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER +espresso_lite_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espresso_lite_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.CORE=CORE +espresso_lite_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espresso_lite_v2.menu.lvl.WIFI=WIFI +espresso_lite_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espresso_lite_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espresso_lite_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espresso_lite_v2.menu.lvl.UPDATER=UPDATER +espresso_lite_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espresso_lite_v2.menu.lvl.OTA=OTA +espresso_lite_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espresso_lite_v2.menu.lvl.OOM=OOM +espresso_lite_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espresso_lite_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espresso_lite_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espresso_lite_v2.menu.wipe.none=Only Sketch +espresso_lite_v2.menu.wipe.none.upload.erase_cmd= +espresso_lite_v2.menu.wipe.sdk=Sketch + WiFi Settings +espresso_lite_v2.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +espresso_lite_v2.menu.wipe.all=All Flash Contents +espresso_lite_v2.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +espresso_lite_v2.menu.baud.115200=115200 +espresso_lite_v2.menu.baud.115200.upload.speed=115200 +espresso_lite_v2.menu.baud.9600=9600 +espresso_lite_v2.menu.baud.9600.upload.speed=9600 +espresso_lite_v2.menu.baud.57600=57600 +espresso_lite_v2.menu.baud.57600.upload.speed=57600 +espresso_lite_v2.menu.baud.230400.linux=230400 +espresso_lite_v2.menu.baud.230400.macosx=230400 +espresso_lite_v2.menu.baud.230400.upload.speed=230400 +espresso_lite_v2.menu.baud.256000.windows=256000 +espresso_lite_v2.menu.baud.256000.upload.speed=256000 +espresso_lite_v2.menu.baud.460800.linux=460800 +espresso_lite_v2.menu.baud.460800.macosx=460800 +espresso_lite_v2.menu.baud.460800.upload.speed=460800 +espresso_lite_v2.menu.baud.512000.windows=512000 +espresso_lite_v2.menu.baud.512000.upload.speed=512000 +espresso_lite_v2.menu.baud.921600=921600 +espresso_lite_v2.menu.baud.921600.upload.speed=921600 + +############################################################## +phoenix_v1.name=Phoenix 1.0 +phoenix_v1.build.board=ESP8266_PHOENIX_V1 +phoenix_v1.build.variant=phoenix_v1 +phoenix_v1.upload.tool=esptool +phoenix_v1.upload.maximum_data_size=81920 +phoenix_v1.upload.wait_for_upload_port=true +phoenix_v1.upload.erase_cmd= +phoenix_v1.serial.disableDTR=true +phoenix_v1.serial.disableRTS=true +phoenix_v1.build.mcu=esp8266 +phoenix_v1.build.core=esp8266 +phoenix_v1.build.spiffs_pagesize=256 +phoenix_v1.build.debug_port= +phoenix_v1.build.debug_level= +phoenix_v1.menu.xtal.80=80 MHz +phoenix_v1.menu.xtal.80.build.f_cpu=80000000L +phoenix_v1.menu.xtal.160=160 MHz +phoenix_v1.menu.xtal.160.build.f_cpu=160000000L +phoenix_v1.menu.vt.flash=Flash +phoenix_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +phoenix_v1.menu.vt.heap=Heap +phoenix_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +phoenix_v1.menu.vt.iram=IRAM +phoenix_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +phoenix_v1.menu.exception.disabled=Disabled +phoenix_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions +phoenix_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +phoenix_v1.menu.exception.enabled=Enabled +phoenix_v1.menu.exception.enabled.build.exception_flags=-fexceptions +phoenix_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +phoenix_v1.build.flash_mode=dio +phoenix_v1.build.flash_flags=-DFLASHMODE_DIO +phoenix_v1.build.flash_freq=40 +phoenix_v1.menu.eesz.4M=4M (no SPIFFS) +phoenix_v1.menu.eesz.4M.build.flash_size=4M +phoenix_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +phoenix_v1.menu.eesz.4M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M1M=4M (1M SPIFFS) +phoenix_v1.menu.eesz.4M1M.build.flash_size=4M +phoenix_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +phoenix_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M1M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 +phoenix_v1.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +phoenix_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 +phoenix_v1.menu.eesz.4M2M=4M (2M SPIFFS) +phoenix_v1.menu.eesz.4M2M.build.flash_size=4M +phoenix_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +phoenix_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M2M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 +phoenix_v1.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +phoenix_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 +phoenix_v1.menu.eesz.4M3M=4M (3M SPIFFS) +phoenix_v1.menu.eesz.4M3M.build.flash_size=4M +phoenix_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +phoenix_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M3M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 +phoenix_v1.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +phoenix_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 +phoenix_v1.menu.ResetMethod.ck=ck +phoenix_v1.menu.ResetMethod.ck.upload.resetmethod=ck +phoenix_v1.menu.ResetMethod.nodemcu=nodemcu +phoenix_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +phoenix_v1.menu.ip.lm2f=v2 Lower Memory +phoenix_v1.menu.ip.lm2f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +phoenix_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.hb2f=v2 Higher Bandwidth +phoenix_v1.menu.ip.hb2f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +phoenix_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.lm2n=v2 Lower Memory (no features) +phoenix_v1.menu.ip.lm2n.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +phoenix_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) +phoenix_v1.menu.ip.hb2n.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +phoenix_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.lm6f=v2 IPv6 Lower Memory +phoenix_v1.menu.ip.lm6f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +phoenix_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +phoenix_v1.menu.ip.hb6f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +phoenix_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v1.menu.ip.hb1=v1.4 Higher Bandwidth +phoenix_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc +phoenix_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v1.menu.ip.src=v1.4 Compile from source +phoenix_v1.menu.ip.src.build.lwip_lib=-llwip_src +phoenix_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +phoenix_v1.menu.dbg.Disabled=Disabled +phoenix_v1.menu.dbg.Disabled.build.debug_port= +phoenix_v1.menu.dbg.Serial=Serial +phoenix_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +phoenix_v1.menu.dbg.Serial1=Serial1 +phoenix_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +phoenix_v1.menu.lvl.None____=None +phoenix_v1.menu.lvl.None____.build.debug_level= +phoenix_v1.menu.lvl.SSL=SSL +phoenix_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +phoenix_v1.menu.lvl.TLS_MEM=TLS_MEM +phoenix_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +phoenix_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +phoenix_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER +phoenix_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +phoenix_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +phoenix_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +phoenix_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +phoenix_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.CORE=CORE +phoenix_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +phoenix_v1.menu.lvl.WIFI=WIFI +phoenix_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +phoenix_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +phoenix_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +phoenix_v1.menu.lvl.UPDATER=UPDATER +phoenix_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +phoenix_v1.menu.lvl.OTA=OTA +phoenix_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +phoenix_v1.menu.lvl.OOM=OOM +phoenix_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +phoenix_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +phoenix_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +phoenix_v1.menu.wipe.none=Only Sketch +phoenix_v1.menu.wipe.none.upload.erase_cmd= +phoenix_v1.menu.wipe.sdk=Sketch + WiFi Settings +phoenix_v1.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +phoenix_v1.menu.wipe.all=All Flash Contents +phoenix_v1.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +phoenix_v1.menu.baud.115200=115200 +phoenix_v1.menu.baud.115200.upload.speed=115200 +phoenix_v1.menu.baud.9600=9600 +phoenix_v1.menu.baud.9600.upload.speed=9600 +phoenix_v1.menu.baud.57600=57600 +phoenix_v1.menu.baud.57600.upload.speed=57600 +phoenix_v1.menu.baud.230400.linux=230400 +phoenix_v1.menu.baud.230400.macosx=230400 +phoenix_v1.menu.baud.230400.upload.speed=230400 +phoenix_v1.menu.baud.256000.windows=256000 +phoenix_v1.menu.baud.256000.upload.speed=256000 +phoenix_v1.menu.baud.460800.linux=460800 +phoenix_v1.menu.baud.460800.macosx=460800 +phoenix_v1.menu.baud.460800.upload.speed=460800 +phoenix_v1.menu.baud.512000.windows=512000 +phoenix_v1.menu.baud.512000.upload.speed=512000 +phoenix_v1.menu.baud.921600=921600 +phoenix_v1.menu.baud.921600.upload.speed=921600 + +############################################################## +phoenix_v2.name=Phoenix 2.0 +phoenix_v2.build.board=ESP8266_PHOENIX_V2 +phoenix_v2.build.variant=phoenix_v2 +phoenix_v2.upload.tool=esptool +phoenix_v2.upload.maximum_data_size=81920 +phoenix_v2.upload.wait_for_upload_port=true +phoenix_v2.upload.erase_cmd= +phoenix_v2.serial.disableDTR=true +phoenix_v2.serial.disableRTS=true +phoenix_v2.build.mcu=esp8266 +phoenix_v2.build.core=esp8266 +phoenix_v2.build.spiffs_pagesize=256 +phoenix_v2.build.debug_port= +phoenix_v2.build.debug_level= +phoenix_v2.menu.xtal.80=80 MHz +phoenix_v2.menu.xtal.80.build.f_cpu=80000000L +phoenix_v2.menu.xtal.160=160 MHz +phoenix_v2.menu.xtal.160.build.f_cpu=160000000L +phoenix_v2.menu.vt.flash=Flash +phoenix_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +phoenix_v2.menu.vt.heap=Heap +phoenix_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +phoenix_v2.menu.vt.iram=IRAM +phoenix_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +phoenix_v2.menu.exception.disabled=Disabled +phoenix_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions +phoenix_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +phoenix_v2.menu.exception.enabled=Enabled +phoenix_v2.menu.exception.enabled.build.exception_flags=-fexceptions +phoenix_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +phoenix_v2.build.flash_mode=dio +phoenix_v2.build.flash_flags=-DFLASHMODE_DIO +phoenix_v2.build.flash_freq=40 +phoenix_v2.menu.eesz.4M=4M (no SPIFFS) +phoenix_v2.menu.eesz.4M.build.flash_size=4M +phoenix_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +phoenix_v2.menu.eesz.4M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M1M=4M (1M SPIFFS) +phoenix_v2.menu.eesz.4M1M.build.flash_size=4M +phoenix_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +phoenix_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M1M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 +phoenix_v2.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +phoenix_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 +phoenix_v2.menu.eesz.4M2M=4M (2M SPIFFS) +phoenix_v2.menu.eesz.4M2M.build.flash_size=4M +phoenix_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +phoenix_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M2M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 +phoenix_v2.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +phoenix_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 +phoenix_v2.menu.eesz.4M3M=4M (3M SPIFFS) +phoenix_v2.menu.eesz.4M3M.build.flash_size=4M +phoenix_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +phoenix_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M3M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 +phoenix_v2.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +phoenix_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 +phoenix_v2.menu.ResetMethod.ck=ck +phoenix_v2.menu.ResetMethod.ck.upload.resetmethod=ck +phoenix_v2.menu.ResetMethod.nodemcu=nodemcu +phoenix_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +phoenix_v2.menu.ip.lm2f=v2 Lower Memory +phoenix_v2.menu.ip.lm2f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +phoenix_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.hb2f=v2 Higher Bandwidth +phoenix_v2.menu.ip.hb2f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +phoenix_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.lm2n=v2 Lower Memory (no features) +phoenix_v2.menu.ip.lm2n.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +phoenix_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) +phoenix_v2.menu.ip.hb2n.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +phoenix_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.lm6f=v2 IPv6 Lower Memory +phoenix_v2.menu.ip.lm6f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +phoenix_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +phoenix_v2.menu.ip.hb6f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +phoenix_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v2.menu.ip.hb1=v1.4 Higher Bandwidth +phoenix_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc +phoenix_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v2.menu.ip.src=v1.4 Compile from source +phoenix_v2.menu.ip.src.build.lwip_lib=-llwip_src +phoenix_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +phoenix_v2.menu.dbg.Disabled=Disabled +phoenix_v2.menu.dbg.Disabled.build.debug_port= +phoenix_v2.menu.dbg.Serial=Serial +phoenix_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +phoenix_v2.menu.dbg.Serial1=Serial1 +phoenix_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +phoenix_v2.menu.lvl.None____=None +phoenix_v2.menu.lvl.None____.build.debug_level= +phoenix_v2.menu.lvl.SSL=SSL +phoenix_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +phoenix_v2.menu.lvl.TLS_MEM=TLS_MEM +phoenix_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +phoenix_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +phoenix_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER +phoenix_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +phoenix_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +phoenix_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +phoenix_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +phoenix_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.CORE=CORE +phoenix_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +phoenix_v2.menu.lvl.WIFI=WIFI +phoenix_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +phoenix_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +phoenix_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +phoenix_v2.menu.lvl.UPDATER=UPDATER +phoenix_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +phoenix_v2.menu.lvl.OTA=OTA +phoenix_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +phoenix_v2.menu.lvl.OOM=OOM +phoenix_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +phoenix_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +phoenix_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +phoenix_v2.menu.wipe.none=Only Sketch +phoenix_v2.menu.wipe.none.upload.erase_cmd= +phoenix_v2.menu.wipe.sdk=Sketch + WiFi Settings +phoenix_v2.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +phoenix_v2.menu.wipe.all=All Flash Contents +phoenix_v2.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +phoenix_v2.menu.baud.115200=115200 +phoenix_v2.menu.baud.115200.upload.speed=115200 +phoenix_v2.menu.baud.9600=9600 +phoenix_v2.menu.baud.9600.upload.speed=9600 +phoenix_v2.menu.baud.57600=57600 +phoenix_v2.menu.baud.57600.upload.speed=57600 +phoenix_v2.menu.baud.230400.linux=230400 +phoenix_v2.menu.baud.230400.macosx=230400 +phoenix_v2.menu.baud.230400.upload.speed=230400 +phoenix_v2.menu.baud.256000.windows=256000 +phoenix_v2.menu.baud.256000.upload.speed=256000 +phoenix_v2.menu.baud.460800.linux=460800 +phoenix_v2.menu.baud.460800.macosx=460800 +phoenix_v2.menu.baud.460800.upload.speed=460800 +phoenix_v2.menu.baud.512000.windows=512000 +phoenix_v2.menu.baud.512000.upload.speed=512000 +phoenix_v2.menu.baud.921600=921600 +phoenix_v2.menu.baud.921600.upload.speed=921600 + +############################################################## +nodemcu.name=NodeMCU 0.9 (ESP-12 Module) +nodemcu.build.board=ESP8266_NODEMCU +nodemcu.build.variant=nodemcu +nodemcu.upload.tool=esptool +nodemcu.upload.maximum_data_size=81920 +nodemcu.upload.wait_for_upload_port=true +nodemcu.upload.erase_cmd= +nodemcu.serial.disableDTR=true +nodemcu.serial.disableRTS=true +nodemcu.build.mcu=esp8266 +nodemcu.build.core=esp8266 +nodemcu.build.spiffs_pagesize=256 +nodemcu.build.debug_port= +nodemcu.build.debug_level= +nodemcu.menu.xtal.80=80 MHz +nodemcu.menu.xtal.80.build.f_cpu=80000000L +nodemcu.menu.xtal.160=160 MHz +nodemcu.menu.xtal.160.build.f_cpu=160000000L +nodemcu.menu.vt.flash=Flash +nodemcu.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +nodemcu.menu.vt.heap=Heap +nodemcu.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +nodemcu.menu.vt.iram=IRAM +nodemcu.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +nodemcu.menu.exception.disabled=Disabled +nodemcu.menu.exception.disabled.build.exception_flags=-fno-exceptions +nodemcu.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +nodemcu.menu.exception.enabled=Enabled +nodemcu.menu.exception.enabled.build.exception_flags=-fexceptions +nodemcu.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +nodemcu.upload.resetmethod=nodemcu +nodemcu.build.flash_mode=qio +nodemcu.build.flash_flags=-DFLASHMODE_QIO +nodemcu.build.flash_freq=40 +nodemcu.menu.eesz.4M=4M (no SPIFFS) +nodemcu.menu.eesz.4M.build.flash_size=4M +nodemcu.menu.eesz.4M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +nodemcu.menu.eesz.4M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M1M=4M (1M SPIFFS) +nodemcu.menu.eesz.4M1M.build.flash_size=4M +nodemcu.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +nodemcu.menu.eesz.4M1M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M1M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M1M.build.spiffs_start=0x300000 +nodemcu.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +nodemcu.menu.eesz.4M1M.build.spiffs_blocksize=8192 +nodemcu.menu.eesz.4M2M=4M (2M SPIFFS) +nodemcu.menu.eesz.4M2M.build.flash_size=4M +nodemcu.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +nodemcu.menu.eesz.4M2M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M2M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M2M.build.spiffs_start=0x200000 +nodemcu.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +nodemcu.menu.eesz.4M2M.build.spiffs_blocksize=8192 +nodemcu.menu.eesz.4M3M=4M (3M SPIFFS) +nodemcu.menu.eesz.4M3M.build.flash_size=4M +nodemcu.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +nodemcu.menu.eesz.4M3M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M3M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M3M.build.spiffs_start=0x100000 +nodemcu.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +nodemcu.menu.eesz.4M3M.build.spiffs_blocksize=8192 +nodemcu.menu.ip.lm2f=v2 Lower Memory +nodemcu.menu.ip.lm2f.build.lwip_include=lwip2/include +nodemcu.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +nodemcu.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcu.menu.ip.hb2f=v2 Higher Bandwidth +nodemcu.menu.ip.hb2f.build.lwip_include=lwip2/include +nodemcu.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +nodemcu.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcu.menu.ip.lm2n=v2 Lower Memory (no features) +nodemcu.menu.ip.lm2n.build.lwip_include=lwip2/include +nodemcu.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +nodemcu.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcu.menu.ip.hb2n=v2 Higher Bandwidth (no features) +nodemcu.menu.ip.hb2n.build.lwip_include=lwip2/include +nodemcu.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +nodemcu.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcu.menu.ip.lm6f=v2 IPv6 Lower Memory +nodemcu.menu.ip.lm6f.build.lwip_include=lwip2/include +nodemcu.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +nodemcu.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcu.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +nodemcu.menu.ip.hb6f.build.lwip_include=lwip2/include +nodemcu.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +nodemcu.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcu.menu.ip.hb1=v1.4 Higher Bandwidth +nodemcu.menu.ip.hb1.build.lwip_lib=-llwip_gcc +nodemcu.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcu.menu.ip.src=v1.4 Compile from source +nodemcu.menu.ip.src.build.lwip_lib=-llwip_src +nodemcu.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcu.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +nodemcu.menu.dbg.Disabled=Disabled +nodemcu.menu.dbg.Disabled.build.debug_port= +nodemcu.menu.dbg.Serial=Serial +nodemcu.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +nodemcu.menu.dbg.Serial1=Serial1 +nodemcu.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +nodemcu.menu.lvl.None____=None +nodemcu.menu.lvl.None____.build.debug_level= +nodemcu.menu.lvl.SSL=SSL +nodemcu.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +nodemcu.menu.lvl.TLS_MEM=TLS_MEM +nodemcu.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +nodemcu.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +nodemcu.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.HTTP_SERVER=HTTP_SERVER +nodemcu.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +nodemcu.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +nodemcu.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +nodemcu.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +nodemcu.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.CORE=CORE +nodemcu.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +nodemcu.menu.lvl.WIFI=WIFI +nodemcu.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +nodemcu.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +nodemcu.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +nodemcu.menu.lvl.UPDATER=UPDATER +nodemcu.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +nodemcu.menu.lvl.OTA=OTA +nodemcu.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +nodemcu.menu.lvl.OOM=OOM +nodemcu.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +nodemcu.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +nodemcu.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +nodemcu.menu.wipe.none=Only Sketch +nodemcu.menu.wipe.none.upload.erase_cmd= +nodemcu.menu.wipe.sdk=Sketch + WiFi Settings +nodemcu.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +nodemcu.menu.wipe.all=All Flash Contents +nodemcu.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +nodemcu.menu.baud.115200=115200 +nodemcu.menu.baud.115200.upload.speed=115200 +nodemcu.menu.baud.9600=9600 +nodemcu.menu.baud.9600.upload.speed=9600 +nodemcu.menu.baud.57600=57600 +nodemcu.menu.baud.57600.upload.speed=57600 +nodemcu.menu.baud.230400.linux=230400 +nodemcu.menu.baud.230400.macosx=230400 +nodemcu.menu.baud.230400.upload.speed=230400 +nodemcu.menu.baud.256000.windows=256000 +nodemcu.menu.baud.256000.upload.speed=256000 +nodemcu.menu.baud.460800.linux=460800 +nodemcu.menu.baud.460800.macosx=460800 +nodemcu.menu.baud.460800.upload.speed=460800 +nodemcu.menu.baud.512000.windows=512000 +nodemcu.menu.baud.512000.upload.speed=512000 +nodemcu.menu.baud.921600=921600 +nodemcu.menu.baud.921600.upload.speed=921600 + +############################################################## +nodemcuv2.name=NodeMCU 1.0 (ESP-12E Module) +nodemcuv2.build.board=ESP8266_NODEMCU +nodemcuv2.build.variant=nodemcu +nodemcuv2.upload.tool=esptool +nodemcuv2.upload.maximum_data_size=81920 +nodemcuv2.upload.wait_for_upload_port=true +nodemcuv2.upload.erase_cmd= +nodemcuv2.serial.disableDTR=true +nodemcuv2.serial.disableRTS=true +nodemcuv2.build.mcu=esp8266 +nodemcuv2.build.core=esp8266 +nodemcuv2.build.spiffs_pagesize=256 +nodemcuv2.build.debug_port= +nodemcuv2.build.debug_level= +nodemcuv2.menu.xtal.80=80 MHz +nodemcuv2.menu.xtal.80.build.f_cpu=80000000L +nodemcuv2.menu.xtal.160=160 MHz +nodemcuv2.menu.xtal.160.build.f_cpu=160000000L +nodemcuv2.menu.vt.flash=Flash +nodemcuv2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +nodemcuv2.menu.vt.heap=Heap +nodemcuv2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +nodemcuv2.menu.vt.iram=IRAM +nodemcuv2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +nodemcuv2.menu.exception.disabled=Disabled +nodemcuv2.menu.exception.disabled.build.exception_flags=-fno-exceptions +nodemcuv2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +nodemcuv2.menu.exception.enabled=Enabled +nodemcuv2.menu.exception.enabled.build.exception_flags=-fexceptions +nodemcuv2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +nodemcuv2.upload.resetmethod=nodemcu +nodemcuv2.build.flash_mode=dio +nodemcuv2.build.flash_flags=-DFLASHMODE_DIO +nodemcuv2.build.flash_freq=40 +nodemcuv2.menu.eesz.4M=4M (no SPIFFS) +nodemcuv2.menu.eesz.4M.build.flash_size=4M +nodemcuv2.menu.eesz.4M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +nodemcuv2.menu.eesz.4M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M1M=4M (1M SPIFFS) +nodemcuv2.menu.eesz.4M1M.build.flash_size=4M +nodemcuv2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +nodemcuv2.menu.eesz.4M1M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M1M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M1M.build.spiffs_start=0x300000 +nodemcuv2.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +nodemcuv2.menu.eesz.4M1M.build.spiffs_blocksize=8192 +nodemcuv2.menu.eesz.4M2M=4M (2M SPIFFS) +nodemcuv2.menu.eesz.4M2M.build.flash_size=4M +nodemcuv2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +nodemcuv2.menu.eesz.4M2M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M2M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M2M.build.spiffs_start=0x200000 +nodemcuv2.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +nodemcuv2.menu.eesz.4M2M.build.spiffs_blocksize=8192 +nodemcuv2.menu.eesz.4M3M=4M (3M SPIFFS) +nodemcuv2.menu.eesz.4M3M.build.flash_size=4M +nodemcuv2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +nodemcuv2.menu.eesz.4M3M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M3M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M3M.build.spiffs_start=0x100000 +nodemcuv2.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +nodemcuv2.menu.eesz.4M3M.build.spiffs_blocksize=8192 +nodemcuv2.menu.ip.lm2f=v2 Lower Memory +nodemcuv2.menu.ip.lm2f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +nodemcuv2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.hb2f=v2 Higher Bandwidth +nodemcuv2.menu.ip.hb2f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +nodemcuv2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.lm2n=v2 Lower Memory (no features) +nodemcuv2.menu.ip.lm2n.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +nodemcuv2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.hb2n=v2 Higher Bandwidth (no features) +nodemcuv2.menu.ip.hb2n.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +nodemcuv2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.lm6f=v2 IPv6 Lower Memory +nodemcuv2.menu.ip.lm6f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +nodemcuv2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcuv2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +nodemcuv2.menu.ip.hb6f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +nodemcuv2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcuv2.menu.ip.hb1=v1.4 Higher Bandwidth +nodemcuv2.menu.ip.hb1.build.lwip_lib=-llwip_gcc +nodemcuv2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcuv2.menu.ip.src=v1.4 Compile from source +nodemcuv2.menu.ip.src.build.lwip_lib=-llwip_src +nodemcuv2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcuv2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +nodemcuv2.menu.dbg.Disabled=Disabled +nodemcuv2.menu.dbg.Disabled.build.debug_port= +nodemcuv2.menu.dbg.Serial=Serial +nodemcuv2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +nodemcuv2.menu.dbg.Serial1=Serial1 +nodemcuv2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +nodemcuv2.menu.lvl.None____=None +nodemcuv2.menu.lvl.None____.build.debug_level= +nodemcuv2.menu.lvl.SSL=SSL +nodemcuv2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +nodemcuv2.menu.lvl.TLS_MEM=TLS_MEM +nodemcuv2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +nodemcuv2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +nodemcuv2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.HTTP_SERVER=HTTP_SERVER +nodemcuv2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +nodemcuv2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +nodemcuv2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +nodemcuv2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +nodemcuv2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.CORE=CORE +nodemcuv2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +nodemcuv2.menu.lvl.WIFI=WIFI +nodemcuv2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +nodemcuv2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +nodemcuv2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +nodemcuv2.menu.lvl.UPDATER=UPDATER +nodemcuv2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +nodemcuv2.menu.lvl.OTA=OTA +nodemcuv2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +nodemcuv2.menu.lvl.OOM=OOM +nodemcuv2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +nodemcuv2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +nodemcuv2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +nodemcuv2.menu.wipe.none=Only Sketch +nodemcuv2.menu.wipe.none.upload.erase_cmd= +nodemcuv2.menu.wipe.sdk=Sketch + WiFi Settings +nodemcuv2.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +nodemcuv2.menu.wipe.all=All Flash Contents +nodemcuv2.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +nodemcuv2.menu.baud.115200=115200 +nodemcuv2.menu.baud.115200.upload.speed=115200 +nodemcuv2.menu.baud.9600=9600 +nodemcuv2.menu.baud.9600.upload.speed=9600 +nodemcuv2.menu.baud.57600=57600 +nodemcuv2.menu.baud.57600.upload.speed=57600 +nodemcuv2.menu.baud.230400.linux=230400 +nodemcuv2.menu.baud.230400.macosx=230400 +nodemcuv2.menu.baud.230400.upload.speed=230400 +nodemcuv2.menu.baud.256000.windows=256000 +nodemcuv2.menu.baud.256000.upload.speed=256000 +nodemcuv2.menu.baud.460800.linux=460800 +nodemcuv2.menu.baud.460800.macosx=460800 +nodemcuv2.menu.baud.460800.upload.speed=460800 +nodemcuv2.menu.baud.512000.windows=512000 +nodemcuv2.menu.baud.512000.upload.speed=512000 +nodemcuv2.menu.baud.921600=921600 +nodemcuv2.menu.baud.921600.upload.speed=921600 + +############################################################## +modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV) +modwifi.build.board=MOD_WIFI_ESP8266 +modwifi.build.variant=modwifi +modwifi.upload.tool=esptool +modwifi.upload.maximum_data_size=81920 +modwifi.upload.wait_for_upload_port=true +modwifi.upload.erase_cmd= +modwifi.serial.disableDTR=true +modwifi.serial.disableRTS=true +modwifi.build.mcu=esp8266 +modwifi.build.core=esp8266 +modwifi.build.spiffs_pagesize=256 +modwifi.build.debug_port= +modwifi.build.debug_level= +modwifi.menu.xtal.80=80 MHz +modwifi.menu.xtal.80.build.f_cpu=80000000L +modwifi.menu.xtal.160=160 MHz +modwifi.menu.xtal.160.build.f_cpu=160000000L +modwifi.menu.vt.flash=Flash +modwifi.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +modwifi.menu.vt.heap=Heap +modwifi.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +modwifi.menu.vt.iram=IRAM +modwifi.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +modwifi.menu.exception.disabled=Disabled +modwifi.menu.exception.disabled.build.exception_flags=-fno-exceptions +modwifi.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +modwifi.menu.exception.enabled=Enabled +modwifi.menu.exception.enabled.build.exception_flags=-fexceptions +modwifi.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +modwifi.upload.resetmethod=ck +modwifi.build.flash_mode=qio +modwifi.build.flash_flags=-DFLASHMODE_QIO +modwifi.build.flash_freq=40 +modwifi.menu.eesz.2M=2M (no SPIFFS) +modwifi.menu.eesz.2M.build.flash_size=2M +modwifi.menu.eesz.2M.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld +modwifi.menu.eesz.2M.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M.upload.maximum_size=1044464 +modwifi.menu.eesz.2M.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M128=2M (128K SPIFFS) +modwifi.menu.eesz.2M128.build.flash_size=2M +modwifi.menu.eesz.2M128.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld +modwifi.menu.eesz.2M128.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M128.upload.maximum_size=1044464 +modwifi.menu.eesz.2M128.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M128.build.spiffs_start=0x1E0000 +modwifi.menu.eesz.2M128.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M128.build.spiffs_blocksize=4096 +modwifi.menu.eesz.2M256=2M (256K SPIFFS) +modwifi.menu.eesz.2M256.build.flash_size=2M +modwifi.menu.eesz.2M256.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld +modwifi.menu.eesz.2M256.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M256.upload.maximum_size=1044464 +modwifi.menu.eesz.2M256.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M256.build.spiffs_start=0x1C0000 +modwifi.menu.eesz.2M256.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M256.build.spiffs_blocksize=4096 +modwifi.menu.eesz.2M512=2M (512K SPIFFS) +modwifi.menu.eesz.2M512.build.flash_size=2M +modwifi.menu.eesz.2M512.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld +modwifi.menu.eesz.2M512.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M512.upload.maximum_size=1044464 +modwifi.menu.eesz.2M512.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M512.build.spiffs_start=0x180000 +modwifi.menu.eesz.2M512.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M512.build.spiffs_blocksize=8192 +modwifi.menu.eesz.2M1M=2M (1M SPIFFS) +modwifi.menu.eesz.2M1M.build.flash_size=2M +modwifi.menu.eesz.2M1M.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld +modwifi.menu.eesz.2M1M.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M1M.upload.maximum_size=1044464 +modwifi.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M1M.build.spiffs_start=0x100000 +modwifi.menu.eesz.2M1M.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M1M.build.spiffs_blocksize=8192 +modwifi.menu.ip.lm2f=v2 Lower Memory +modwifi.menu.ip.lm2f.build.lwip_include=lwip2/include +modwifi.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +modwifi.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +modwifi.menu.ip.hb2f=v2 Higher Bandwidth +modwifi.menu.ip.hb2f.build.lwip_include=lwip2/include +modwifi.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +modwifi.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +modwifi.menu.ip.lm2n=v2 Lower Memory (no features) +modwifi.menu.ip.lm2n.build.lwip_include=lwip2/include +modwifi.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +modwifi.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +modwifi.menu.ip.hb2n=v2 Higher Bandwidth (no features) +modwifi.menu.ip.hb2n.build.lwip_include=lwip2/include +modwifi.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +modwifi.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +modwifi.menu.ip.lm6f=v2 IPv6 Lower Memory +modwifi.menu.ip.lm6f.build.lwip_include=lwip2/include +modwifi.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +modwifi.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +modwifi.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +modwifi.menu.ip.hb6f.build.lwip_include=lwip2/include +modwifi.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +modwifi.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +modwifi.menu.ip.hb1=v1.4 Higher Bandwidth +modwifi.menu.ip.hb1.build.lwip_lib=-llwip_gcc +modwifi.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +modwifi.menu.ip.src=v1.4 Compile from source +modwifi.menu.ip.src.build.lwip_lib=-llwip_src +modwifi.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +modwifi.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +modwifi.menu.dbg.Disabled=Disabled +modwifi.menu.dbg.Disabled.build.debug_port= +modwifi.menu.dbg.Serial=Serial +modwifi.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +modwifi.menu.dbg.Serial1=Serial1 +modwifi.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +modwifi.menu.lvl.None____=None +modwifi.menu.lvl.None____.build.debug_level= +modwifi.menu.lvl.SSL=SSL +modwifi.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +modwifi.menu.lvl.TLS_MEM=TLS_MEM +modwifi.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +modwifi.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +modwifi.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.HTTP_SERVER=HTTP_SERVER +modwifi.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +modwifi.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +modwifi.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +modwifi.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +modwifi.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +modwifi.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.CORE=CORE +modwifi.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +modwifi.menu.lvl.WIFI=WIFI +modwifi.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +modwifi.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +modwifi.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +modwifi.menu.lvl.UPDATER=UPDATER +modwifi.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +modwifi.menu.lvl.OTA=OTA +modwifi.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +modwifi.menu.lvl.OOM=OOM +modwifi.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +modwifi.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +modwifi.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +modwifi.menu.wipe.none=Only Sketch +modwifi.menu.wipe.none.upload.erase_cmd= +modwifi.menu.wipe.sdk=Sketch + WiFi Settings +modwifi.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +modwifi.menu.wipe.all=All Flash Contents +modwifi.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +modwifi.menu.baud.115200=115200 +modwifi.menu.baud.115200.upload.speed=115200 +modwifi.menu.baud.9600=9600 +modwifi.menu.baud.9600.upload.speed=9600 +modwifi.menu.baud.57600=57600 +modwifi.menu.baud.57600.upload.speed=57600 +modwifi.menu.baud.230400.linux=230400 +modwifi.menu.baud.230400.macosx=230400 +modwifi.menu.baud.230400.upload.speed=230400 +modwifi.menu.baud.256000.windows=256000 +modwifi.menu.baud.256000.upload.speed=256000 +modwifi.menu.baud.460800.linux=460800 +modwifi.menu.baud.460800.macosx=460800 +modwifi.menu.baud.460800.upload.speed=460800 +modwifi.menu.baud.512000.windows=512000 +modwifi.menu.baud.512000.upload.speed=512000 +modwifi.menu.baud.921600=921600 +modwifi.menu.baud.921600.upload.speed=921600 + +############################################################## +thing.name=SparkFun ESP8266 Thing +thing.build.board=ESP8266_THING +thing.build.variant=thing +thing.upload.tool=esptool +thing.upload.maximum_data_size=81920 +thing.upload.wait_for_upload_port=true +thing.upload.erase_cmd= +thing.serial.disableDTR=true +thing.serial.disableRTS=true +thing.build.mcu=esp8266 +thing.build.core=esp8266 +thing.build.spiffs_pagesize=256 +thing.build.debug_port= +thing.build.debug_level= +thing.menu.xtal.80=80 MHz +thing.menu.xtal.80.build.f_cpu=80000000L +thing.menu.xtal.160=160 MHz +thing.menu.xtal.160.build.f_cpu=160000000L +thing.menu.vt.flash=Flash +thing.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +thing.menu.vt.heap=Heap +thing.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +thing.menu.vt.iram=IRAM +thing.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +thing.menu.exception.disabled=Disabled +thing.menu.exception.disabled.build.exception_flags=-fno-exceptions +thing.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +thing.menu.exception.enabled=Enabled +thing.menu.exception.enabled.build.exception_flags=-fexceptions +thing.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +thing.upload.resetmethod=ck +thing.build.flash_mode=qio +thing.build.flash_flags=-DFLASHMODE_QIO +thing.build.flash_freq=40 +thing.menu.eesz.512K=512K (no SPIFFS) +thing.menu.eesz.512K.build.flash_size=512K +thing.menu.eesz.512K.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +thing.menu.eesz.512K.build.spiffs_pagesize=256 +thing.menu.eesz.512K.upload.maximum_size=499696 +thing.menu.eesz.512K.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K32=512K (32K SPIFFS) +thing.menu.eesz.512K32.build.flash_size=512K +thing.menu.eesz.512K32.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +thing.menu.eesz.512K32.build.spiffs_pagesize=256 +thing.menu.eesz.512K32.upload.maximum_size=466928 +thing.menu.eesz.512K32.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K32.build.spiffs_start=0x73000 +thing.menu.eesz.512K32.build.spiffs_end=0x7B000 +thing.menu.eesz.512K32.build.spiffs_blocksize=4096 +thing.menu.eesz.512K64=512K (64K SPIFFS) +thing.menu.eesz.512K64.build.flash_size=512K +thing.menu.eesz.512K64.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +thing.menu.eesz.512K64.build.spiffs_pagesize=256 +thing.menu.eesz.512K64.upload.maximum_size=434160 +thing.menu.eesz.512K64.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K64.build.spiffs_start=0x6B000 +thing.menu.eesz.512K64.build.spiffs_end=0x7B000 +thing.menu.eesz.512K64.build.spiffs_blocksize=4096 +thing.menu.eesz.512K128=512K (128K SPIFFS) +thing.menu.eesz.512K128.build.flash_size=512K +thing.menu.eesz.512K128.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +thing.menu.eesz.512K128.build.spiffs_pagesize=256 +thing.menu.eesz.512K128.upload.maximum_size=368624 +thing.menu.eesz.512K128.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K128.build.spiffs_start=0x5B000 +thing.menu.eesz.512K128.build.spiffs_end=0x7B000 +thing.menu.eesz.512K128.build.spiffs_blocksize=4096 +thing.menu.ip.lm2f=v2 Lower Memory +thing.menu.ip.lm2f.build.lwip_include=lwip2/include +thing.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +thing.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thing.menu.ip.hb2f=v2 Higher Bandwidth +thing.menu.ip.hb2f.build.lwip_include=lwip2/include +thing.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +thing.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thing.menu.ip.lm2n=v2 Lower Memory (no features) +thing.menu.ip.lm2n.build.lwip_include=lwip2/include +thing.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +thing.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thing.menu.ip.hb2n=v2 Higher Bandwidth (no features) +thing.menu.ip.hb2n.build.lwip_include=lwip2/include +thing.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +thing.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thing.menu.ip.lm6f=v2 IPv6 Lower Memory +thing.menu.ip.lm6f.build.lwip_include=lwip2/include +thing.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +thing.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thing.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +thing.menu.ip.hb6f.build.lwip_include=lwip2/include +thing.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +thing.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thing.menu.ip.hb1=v1.4 Higher Bandwidth +thing.menu.ip.hb1.build.lwip_lib=-llwip_gcc +thing.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +thing.menu.ip.src=v1.4 Compile from source +thing.menu.ip.src.build.lwip_lib=-llwip_src +thing.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +thing.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +thing.menu.dbg.Disabled=Disabled +thing.menu.dbg.Disabled.build.debug_port= +thing.menu.dbg.Serial=Serial +thing.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +thing.menu.dbg.Serial1=Serial1 +thing.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +thing.menu.lvl.None____=None +thing.menu.lvl.None____.build.debug_level= +thing.menu.lvl.SSL=SSL +thing.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +thing.menu.lvl.TLS_MEM=TLS_MEM +thing.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +thing.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +thing.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.HTTP_SERVER=HTTP_SERVER +thing.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +thing.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +thing.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +thing.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +thing.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +thing.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.CORE=CORE +thing.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +thing.menu.lvl.WIFI=WIFI +thing.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +thing.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +thing.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +thing.menu.lvl.UPDATER=UPDATER +thing.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +thing.menu.lvl.OTA=OTA +thing.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +thing.menu.lvl.OOM=OOM +thing.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +thing.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +thing.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +thing.menu.wipe.none=Only Sketch +thing.menu.wipe.none.upload.erase_cmd= +thing.menu.wipe.sdk=Sketch + WiFi Settings +thing.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +thing.menu.wipe.all=All Flash Contents +thing.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +thing.menu.baud.115200=115200 +thing.menu.baud.115200.upload.speed=115200 +thing.menu.baud.9600=9600 +thing.menu.baud.9600.upload.speed=9600 +thing.menu.baud.57600=57600 +thing.menu.baud.57600.upload.speed=57600 +thing.menu.baud.230400.linux=230400 +thing.menu.baud.230400.macosx=230400 +thing.menu.baud.230400.upload.speed=230400 +thing.menu.baud.256000.windows=256000 +thing.menu.baud.256000.upload.speed=256000 +thing.menu.baud.460800.linux=460800 +thing.menu.baud.460800.macosx=460800 +thing.menu.baud.460800.upload.speed=460800 +thing.menu.baud.512000.windows=512000 +thing.menu.baud.512000.upload.speed=512000 +thing.menu.baud.921600=921600 +thing.menu.baud.921600.upload.speed=921600 + +############################################################## +thingdev.name=SparkFun ESP8266 Thing Dev +thingdev.build.board=ESP8266_THING_DEV +thingdev.build.variant=thing +thingdev.upload.tool=esptool +thingdev.upload.maximum_data_size=81920 +thingdev.upload.wait_for_upload_port=true +thingdev.upload.erase_cmd= +thingdev.serial.disableDTR=true +thingdev.serial.disableRTS=true +thingdev.build.mcu=esp8266 +thingdev.build.core=esp8266 +thingdev.build.spiffs_pagesize=256 +thingdev.build.debug_port= +thingdev.build.debug_level= +thingdev.menu.xtal.80=80 MHz +thingdev.menu.xtal.80.build.f_cpu=80000000L +thingdev.menu.xtal.160=160 MHz +thingdev.menu.xtal.160.build.f_cpu=160000000L +thingdev.menu.vt.flash=Flash +thingdev.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +thingdev.menu.vt.heap=Heap +thingdev.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +thingdev.menu.vt.iram=IRAM +thingdev.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +thingdev.menu.exception.disabled=Disabled +thingdev.menu.exception.disabled.build.exception_flags=-fno-exceptions +thingdev.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +thingdev.menu.exception.enabled=Enabled +thingdev.menu.exception.enabled.build.exception_flags=-fexceptions +thingdev.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +thingdev.upload.resetmethod=nodemcu +thingdev.build.flash_mode=dio +thingdev.build.flash_flags=-DFLASHMODE_DIO +thingdev.build.flash_freq=40 +thingdev.menu.eesz.512K=512K (no SPIFFS) +thingdev.menu.eesz.512K.build.flash_size=512K +thingdev.menu.eesz.512K.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +thingdev.menu.eesz.512K.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K.upload.maximum_size=499696 +thingdev.menu.eesz.512K.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K32=512K (32K SPIFFS) +thingdev.menu.eesz.512K32.build.flash_size=512K +thingdev.menu.eesz.512K32.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +thingdev.menu.eesz.512K32.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K32.upload.maximum_size=466928 +thingdev.menu.eesz.512K32.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K32.build.spiffs_start=0x73000 +thingdev.menu.eesz.512K32.build.spiffs_end=0x7B000 +thingdev.menu.eesz.512K32.build.spiffs_blocksize=4096 +thingdev.menu.eesz.512K64=512K (64K SPIFFS) +thingdev.menu.eesz.512K64.build.flash_size=512K +thingdev.menu.eesz.512K64.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +thingdev.menu.eesz.512K64.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K64.upload.maximum_size=434160 +thingdev.menu.eesz.512K64.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K64.build.spiffs_start=0x6B000 +thingdev.menu.eesz.512K64.build.spiffs_end=0x7B000 +thingdev.menu.eesz.512K64.build.spiffs_blocksize=4096 +thingdev.menu.eesz.512K128=512K (128K SPIFFS) +thingdev.menu.eesz.512K128.build.flash_size=512K +thingdev.menu.eesz.512K128.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +thingdev.menu.eesz.512K128.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K128.upload.maximum_size=368624 +thingdev.menu.eesz.512K128.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K128.build.spiffs_start=0x5B000 +thingdev.menu.eesz.512K128.build.spiffs_end=0x7B000 +thingdev.menu.eesz.512K128.build.spiffs_blocksize=4096 +thingdev.menu.ip.lm2f=v2 Lower Memory +thingdev.menu.ip.lm2f.build.lwip_include=lwip2/include +thingdev.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +thingdev.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thingdev.menu.ip.hb2f=v2 Higher Bandwidth +thingdev.menu.ip.hb2f.build.lwip_include=lwip2/include +thingdev.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +thingdev.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thingdev.menu.ip.lm2n=v2 Lower Memory (no features) +thingdev.menu.ip.lm2n.build.lwip_include=lwip2/include +thingdev.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +thingdev.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thingdev.menu.ip.hb2n=v2 Higher Bandwidth (no features) +thingdev.menu.ip.hb2n.build.lwip_include=lwip2/include +thingdev.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +thingdev.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thingdev.menu.ip.lm6f=v2 IPv6 Lower Memory +thingdev.menu.ip.lm6f.build.lwip_include=lwip2/include +thingdev.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +thingdev.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thingdev.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +thingdev.menu.ip.hb6f.build.lwip_include=lwip2/include +thingdev.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +thingdev.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thingdev.menu.ip.hb1=v1.4 Higher Bandwidth +thingdev.menu.ip.hb1.build.lwip_lib=-llwip_gcc +thingdev.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +thingdev.menu.ip.src=v1.4 Compile from source +thingdev.menu.ip.src.build.lwip_lib=-llwip_src +thingdev.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +thingdev.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +thingdev.menu.dbg.Disabled=Disabled +thingdev.menu.dbg.Disabled.build.debug_port= +thingdev.menu.dbg.Serial=Serial +thingdev.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +thingdev.menu.dbg.Serial1=Serial1 +thingdev.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +thingdev.menu.lvl.None____=None +thingdev.menu.lvl.None____.build.debug_level= +thingdev.menu.lvl.SSL=SSL +thingdev.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +thingdev.menu.lvl.TLS_MEM=TLS_MEM +thingdev.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +thingdev.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +thingdev.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.HTTP_SERVER=HTTP_SERVER +thingdev.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +thingdev.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +thingdev.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +thingdev.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +thingdev.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +thingdev.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.CORE=CORE +thingdev.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +thingdev.menu.lvl.WIFI=WIFI +thingdev.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +thingdev.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +thingdev.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +thingdev.menu.lvl.UPDATER=UPDATER +thingdev.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +thingdev.menu.lvl.OTA=OTA +thingdev.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +thingdev.menu.lvl.OOM=OOM +thingdev.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +thingdev.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +thingdev.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +thingdev.menu.wipe.none=Only Sketch +thingdev.menu.wipe.none.upload.erase_cmd= +thingdev.menu.wipe.sdk=Sketch + WiFi Settings +thingdev.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +thingdev.menu.wipe.all=All Flash Contents +thingdev.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +thingdev.menu.baud.115200=115200 +thingdev.menu.baud.115200.upload.speed=115200 +thingdev.menu.baud.9600=9600 +thingdev.menu.baud.9600.upload.speed=9600 +thingdev.menu.baud.57600=57600 +thingdev.menu.baud.57600.upload.speed=57600 +thingdev.menu.baud.230400.linux=230400 +thingdev.menu.baud.230400.macosx=230400 +thingdev.menu.baud.230400.upload.speed=230400 +thingdev.menu.baud.256000.windows=256000 +thingdev.menu.baud.256000.upload.speed=256000 +thingdev.menu.baud.460800.linux=460800 +thingdev.menu.baud.460800.macosx=460800 +thingdev.menu.baud.460800.upload.speed=460800 +thingdev.menu.baud.512000.windows=512000 +thingdev.menu.baud.512000.upload.speed=512000 +thingdev.menu.baud.921600=921600 +thingdev.menu.baud.921600.upload.speed=921600 + +############################################################## +esp210.name=SweetPea ESP-210 +esp210.build.board=ESP8266_ESP210 +esp210.upload.tool=esptool +esp210.upload.maximum_data_size=81920 +esp210.upload.wait_for_upload_port=true +esp210.upload.erase_cmd= +esp210.serial.disableDTR=true +esp210.serial.disableRTS=true +esp210.build.mcu=esp8266 +esp210.build.core=esp8266 +esp210.build.variant=generic +esp210.build.spiffs_pagesize=256 +esp210.build.debug_port= +esp210.build.debug_level= +esp210.menu.xtal.80=80 MHz +esp210.menu.xtal.80.build.f_cpu=80000000L +esp210.menu.xtal.160=160 MHz +esp210.menu.xtal.160.build.f_cpu=160000000L +esp210.menu.vt.flash=Flash +esp210.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +esp210.menu.vt.heap=Heap +esp210.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +esp210.menu.vt.iram=IRAM +esp210.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +esp210.menu.exception.disabled=Disabled +esp210.menu.exception.disabled.build.exception_flags=-fno-exceptions +esp210.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +esp210.menu.exception.enabled=Enabled +esp210.menu.exception.enabled.build.exception_flags=-fexceptions +esp210.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +esp210.upload.resetmethod=ck +esp210.build.flash_mode=qio +esp210.build.flash_flags=-DFLASHMODE_QIO +esp210.build.flash_freq=40 +esp210.menu.eesz.4M=4M (no SPIFFS) +esp210.menu.eesz.4M.build.flash_size=4M +esp210.menu.eesz.4M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +esp210.menu.eesz.4M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M.upload.maximum_size=1044464 +esp210.menu.eesz.4M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M1M=4M (1M SPIFFS) +esp210.menu.eesz.4M1M.build.flash_size=4M +esp210.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +esp210.menu.eesz.4M1M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M1M.upload.maximum_size=1044464 +esp210.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M1M.build.spiffs_start=0x300000 +esp210.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +esp210.menu.eesz.4M1M.build.spiffs_blocksize=8192 +esp210.menu.eesz.4M2M=4M (2M SPIFFS) +esp210.menu.eesz.4M2M.build.flash_size=4M +esp210.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +esp210.menu.eesz.4M2M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M2M.upload.maximum_size=1044464 +esp210.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M2M.build.spiffs_start=0x200000 +esp210.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +esp210.menu.eesz.4M2M.build.spiffs_blocksize=8192 +esp210.menu.eesz.4M3M=4M (3M SPIFFS) +esp210.menu.eesz.4M3M.build.flash_size=4M +esp210.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +esp210.menu.eesz.4M3M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M3M.upload.maximum_size=1044464 +esp210.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M3M.build.spiffs_start=0x100000 +esp210.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +esp210.menu.eesz.4M3M.build.spiffs_blocksize=8192 +esp210.menu.ip.lm2f=v2 Lower Memory +esp210.menu.ip.lm2f.build.lwip_include=lwip2/include +esp210.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +esp210.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp210.menu.ip.hb2f=v2 Higher Bandwidth +esp210.menu.ip.hb2f.build.lwip_include=lwip2/include +esp210.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +esp210.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp210.menu.ip.lm2n=v2 Lower Memory (no features) +esp210.menu.ip.lm2n.build.lwip_include=lwip2/include +esp210.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +esp210.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp210.menu.ip.hb2n=v2 Higher Bandwidth (no features) +esp210.menu.ip.hb2n.build.lwip_include=lwip2/include +esp210.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +esp210.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp210.menu.ip.lm6f=v2 IPv6 Lower Memory +esp210.menu.ip.lm6f.build.lwip_include=lwip2/include +esp210.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +esp210.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp210.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +esp210.menu.ip.hb6f.build.lwip_include=lwip2/include +esp210.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +esp210.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp210.menu.ip.hb1=v1.4 Higher Bandwidth +esp210.menu.ip.hb1.build.lwip_lib=-llwip_gcc +esp210.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +esp210.menu.ip.src=v1.4 Compile from source +esp210.menu.ip.src.build.lwip_lib=-llwip_src +esp210.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +esp210.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +esp210.menu.dbg.Disabled=Disabled +esp210.menu.dbg.Disabled.build.debug_port= +esp210.menu.dbg.Serial=Serial +esp210.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +esp210.menu.dbg.Serial1=Serial1 +esp210.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +esp210.menu.lvl.None____=None +esp210.menu.lvl.None____.build.debug_level= +esp210.menu.lvl.SSL=SSL +esp210.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +esp210.menu.lvl.TLS_MEM=TLS_MEM +esp210.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +esp210.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +esp210.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.HTTP_SERVER=HTTP_SERVER +esp210.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +esp210.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +esp210.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +esp210.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +esp210.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +esp210.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.CORE=CORE +esp210.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +esp210.menu.lvl.WIFI=WIFI +esp210.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +esp210.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +esp210.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +esp210.menu.lvl.UPDATER=UPDATER +esp210.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +esp210.menu.lvl.OTA=OTA +esp210.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +esp210.menu.lvl.OOM=OOM +esp210.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +esp210.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +esp210.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +esp210.menu.wipe.none=Only Sketch +esp210.menu.wipe.none.upload.erase_cmd= +esp210.menu.wipe.sdk=Sketch + WiFi Settings +esp210.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +esp210.menu.wipe.all=All Flash Contents +esp210.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +esp210.menu.baud.57600=57600 +esp210.menu.baud.57600.upload.speed=57600 +esp210.menu.baud.9600=9600 +esp210.menu.baud.9600.upload.speed=9600 +esp210.menu.baud.115200=115200 +esp210.menu.baud.115200.upload.speed=115200 +esp210.menu.baud.230400.linux=230400 +esp210.menu.baud.230400.macosx=230400 +esp210.menu.baud.230400.upload.speed=230400 +esp210.menu.baud.256000.windows=256000 +esp210.menu.baud.256000.upload.speed=256000 +esp210.menu.baud.460800.linux=460800 +esp210.menu.baud.460800.macosx=460800 +esp210.menu.baud.460800.upload.speed=460800 +esp210.menu.baud.512000.windows=512000 +esp210.menu.baud.512000.upload.speed=512000 +esp210.menu.baud.921600=921600 +esp210.menu.baud.921600.upload.speed=921600 + +############################################################## +d1_mini.name=LOLIN(WEMOS) D1 R2 & mini +d1_mini.build.board=ESP8266_WEMOS_D1MINI +d1_mini.build.variant=d1_mini +d1_mini.upload.tool=esptool +d1_mini.upload.maximum_data_size=81920 +d1_mini.upload.wait_for_upload_port=true +d1_mini.upload.erase_cmd= +d1_mini.serial.disableDTR=true +d1_mini.serial.disableRTS=true +d1_mini.build.mcu=esp8266 +d1_mini.build.core=esp8266 +d1_mini.build.spiffs_pagesize=256 +d1_mini.build.debug_port= +d1_mini.build.debug_level= +d1_mini.menu.xtal.80=80 MHz +d1_mini.menu.xtal.80.build.f_cpu=80000000L +d1_mini.menu.xtal.160=160 MHz +d1_mini.menu.xtal.160.build.f_cpu=160000000L +d1_mini.menu.vt.flash=Flash +d1_mini.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1_mini.menu.vt.heap=Heap +d1_mini.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1_mini.menu.vt.iram=IRAM +d1_mini.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1_mini.menu.exception.disabled=Disabled +d1_mini.menu.exception.disabled.build.exception_flags=-fno-exceptions +d1_mini.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1_mini.menu.exception.enabled=Enabled +d1_mini.menu.exception.enabled.build.exception_flags=-fexceptions +d1_mini.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1_mini.upload.resetmethod=nodemcu +d1_mini.build.flash_mode=dio +d1_mini.build.flash_flags=-DFLASHMODE_DIO +d1_mini.build.flash_freq=40 +d1_mini.menu.eesz.4M=4M (no SPIFFS) +d1_mini.menu.eesz.4M.build.flash_size=4M +d1_mini.menu.eesz.4M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +d1_mini.menu.eesz.4M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M1M=4M (1M SPIFFS) +d1_mini.menu.eesz.4M1M.build.flash_size=4M +d1_mini.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +d1_mini.menu.eesz.4M1M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M1M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M1M.build.spiffs_start=0x300000 +d1_mini.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +d1_mini.menu.eesz.4M1M.build.spiffs_blocksize=8192 +d1_mini.menu.eesz.4M2M=4M (2M SPIFFS) +d1_mini.menu.eesz.4M2M.build.flash_size=4M +d1_mini.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +d1_mini.menu.eesz.4M2M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M2M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M2M.build.spiffs_start=0x200000 +d1_mini.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +d1_mini.menu.eesz.4M2M.build.spiffs_blocksize=8192 +d1_mini.menu.eesz.4M3M=4M (3M SPIFFS) +d1_mini.menu.eesz.4M3M.build.flash_size=4M +d1_mini.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +d1_mini.menu.eesz.4M3M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M3M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M3M.build.spiffs_start=0x100000 +d1_mini.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +d1_mini.menu.eesz.4M3M.build.spiffs_blocksize=8192 +d1_mini.menu.ip.lm2f=v2 Lower Memory +d1_mini.menu.ip.lm2f.build.lwip_include=lwip2/include +d1_mini.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1_mini.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini.menu.ip.hb2f=v2 Higher Bandwidth +d1_mini.menu.ip.hb2f.build.lwip_include=lwip2/include +d1_mini.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1_mini.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini.menu.ip.lm2n=v2 Lower Memory (no features) +d1_mini.menu.ip.lm2n.build.lwip_include=lwip2/include +d1_mini.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1_mini.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1_mini.menu.ip.hb2n.build.lwip_include=lwip2/include +d1_mini.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1_mini.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini.menu.ip.lm6f=v2 IPv6 Lower Memory +d1_mini.menu.ip.lm6f.build.lwip_include=lwip2/include +d1_mini.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1_mini.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1_mini.menu.ip.hb6f.build.lwip_include=lwip2/include +d1_mini.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1_mini.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini.menu.ip.hb1=v1.4 Higher Bandwidth +d1_mini.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1_mini.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini.menu.ip.src=v1.4 Compile from source +d1_mini.menu.ip.src.build.lwip_lib=-llwip_src +d1_mini.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1_mini.menu.dbg.Disabled=Disabled +d1_mini.menu.dbg.Disabled.build.debug_port= +d1_mini.menu.dbg.Serial=Serial +d1_mini.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1_mini.menu.dbg.Serial1=Serial1 +d1_mini.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1_mini.menu.lvl.None____=None +d1_mini.menu.lvl.None____.build.debug_level= +d1_mini.menu.lvl.SSL=SSL +d1_mini.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1_mini.menu.lvl.TLS_MEM=TLS_MEM +d1_mini.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1_mini.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1_mini.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1_mini.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1_mini.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1_mini.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1_mini.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1_mini.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.CORE=CORE +d1_mini.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1_mini.menu.lvl.WIFI=WIFI +d1_mini.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1_mini.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1_mini.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1_mini.menu.lvl.UPDATER=UPDATER +d1_mini.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1_mini.menu.lvl.OTA=OTA +d1_mini.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1_mini.menu.lvl.OOM=OOM +d1_mini.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1_mini.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1_mini.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1_mini.menu.wipe.none=Only Sketch +d1_mini.menu.wipe.none.upload.erase_cmd= +d1_mini.menu.wipe.sdk=Sketch + WiFi Settings +d1_mini.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +d1_mini.menu.wipe.all=All Flash Contents +d1_mini.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +d1_mini.menu.baud.921600=921600 +d1_mini.menu.baud.921600.upload.speed=921600 +d1_mini.menu.baud.9600=9600 +d1_mini.menu.baud.9600.upload.speed=9600 +d1_mini.menu.baud.57600=57600 +d1_mini.menu.baud.57600.upload.speed=57600 +d1_mini.menu.baud.115200=115200 +d1_mini.menu.baud.115200.upload.speed=115200 +d1_mini.menu.baud.230400.linux=230400 +d1_mini.menu.baud.230400.macosx=230400 +d1_mini.menu.baud.230400.upload.speed=230400 +d1_mini.menu.baud.256000.windows=256000 +d1_mini.menu.baud.256000.upload.speed=256000 +d1_mini.menu.baud.460800.linux=460800 +d1_mini.menu.baud.460800.macosx=460800 +d1_mini.menu.baud.460800.upload.speed=460800 +d1_mini.menu.baud.512000.windows=512000 +d1_mini.menu.baud.512000.upload.speed=512000 + +############################################################## +d1_mini_pro.name=LOLIN(WEMOS) D1 mini Pro +d1_mini_pro.build.board=ESP8266_WEMOS_D1MINIPRO +d1_mini_pro.build.variant=d1_mini +d1_mini_pro.upload.tool=esptool +d1_mini_pro.upload.maximum_data_size=81920 +d1_mini_pro.upload.wait_for_upload_port=true +d1_mini_pro.upload.erase_cmd= +d1_mini_pro.serial.disableDTR=true +d1_mini_pro.serial.disableRTS=true +d1_mini_pro.build.mcu=esp8266 +d1_mini_pro.build.core=esp8266 +d1_mini_pro.build.spiffs_pagesize=256 +d1_mini_pro.build.debug_port= +d1_mini_pro.build.debug_level= +d1_mini_pro.menu.xtal.80=80 MHz +d1_mini_pro.menu.xtal.80.build.f_cpu=80000000L +d1_mini_pro.menu.xtal.160=160 MHz +d1_mini_pro.menu.xtal.160.build.f_cpu=160000000L +d1_mini_pro.menu.vt.flash=Flash +d1_mini_pro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1_mini_pro.menu.vt.heap=Heap +d1_mini_pro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1_mini_pro.menu.vt.iram=IRAM +d1_mini_pro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1_mini_pro.menu.exception.disabled=Disabled +d1_mini_pro.menu.exception.disabled.build.exception_flags=-fno-exceptions +d1_mini_pro.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1_mini_pro.menu.exception.enabled=Enabled +d1_mini_pro.menu.exception.enabled.build.exception_flags=-fexceptions +d1_mini_pro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1_mini_pro.upload.resetmethod=nodemcu +d1_mini_pro.build.flash_mode=dio +d1_mini_pro.build.flash_flags=-DFLASHMODE_DIO +d1_mini_pro.build.flash_freq=40 +d1_mini_pro.menu.eesz.16M14M=16M (14M SPIFFS) +d1_mini_pro.menu.eesz.16M14M.build.flash_size=16M +d1_mini_pro.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 +d1_mini_pro.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld +d1_mini_pro.menu.eesz.16M14M.build.spiffs_pagesize=256 +d1_mini_pro.menu.eesz.16M14M.upload.maximum_size=1044464 +d1_mini_pro.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 +d1_mini_pro.menu.eesz.16M14M.build.spiffs_start=0x200000 +d1_mini_pro.menu.eesz.16M14M.build.spiffs_end=0xFFB000 +d1_mini_pro.menu.eesz.16M14M.build.spiffs_blocksize=8192 +d1_mini_pro.menu.eesz.16M15M=16M (15M SPIFFS) +d1_mini_pro.menu.eesz.16M15M.build.flash_size=16M +d1_mini_pro.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 +d1_mini_pro.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld +d1_mini_pro.menu.eesz.16M15M.build.spiffs_pagesize=256 +d1_mini_pro.menu.eesz.16M15M.upload.maximum_size=1044464 +d1_mini_pro.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 +d1_mini_pro.menu.eesz.16M15M.build.spiffs_start=0x100000 +d1_mini_pro.menu.eesz.16M15M.build.spiffs_end=0xFFB000 +d1_mini_pro.menu.eesz.16M15M.build.spiffs_blocksize=8192 +d1_mini_pro.menu.ip.lm2f=v2 Lower Memory +d1_mini_pro.menu.ip.lm2f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1_mini_pro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.hb2f=v2 Higher Bandwidth +d1_mini_pro.menu.ip.hb2f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1_mini_pro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.lm2n=v2 Lower Memory (no features) +d1_mini_pro.menu.ip.lm2n.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1_mini_pro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1_mini_pro.menu.ip.hb2n.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1_mini_pro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.lm6f=v2 IPv6 Lower Memory +d1_mini_pro.menu.ip.lm6f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1_mini_pro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_pro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1_mini_pro.menu.ip.hb6f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1_mini_pro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_pro.menu.ip.hb1=v1.4 Higher Bandwidth +d1_mini_pro.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1_mini_pro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_pro.menu.ip.src=v1.4 Compile from source +d1_mini_pro.menu.ip.src.build.lwip_lib=-llwip_src +d1_mini_pro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_pro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1_mini_pro.menu.dbg.Disabled=Disabled +d1_mini_pro.menu.dbg.Disabled.build.debug_port= +d1_mini_pro.menu.dbg.Serial=Serial +d1_mini_pro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1_mini_pro.menu.dbg.Serial1=Serial1 +d1_mini_pro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1_mini_pro.menu.lvl.None____=None +d1_mini_pro.menu.lvl.None____.build.debug_level= +d1_mini_pro.menu.lvl.SSL=SSL +d1_mini_pro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1_mini_pro.menu.lvl.TLS_MEM=TLS_MEM +d1_mini_pro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1_mini_pro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1_mini_pro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1_mini_pro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1_mini_pro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1_mini_pro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.CORE=CORE +d1_mini_pro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1_mini_pro.menu.lvl.WIFI=WIFI +d1_mini_pro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1_mini_pro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1_mini_pro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1_mini_pro.menu.lvl.UPDATER=UPDATER +d1_mini_pro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1_mini_pro.menu.lvl.OTA=OTA +d1_mini_pro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1_mini_pro.menu.lvl.OOM=OOM +d1_mini_pro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1_mini_pro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1_mini_pro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1_mini_pro.menu.wipe.none=Only Sketch +d1_mini_pro.menu.wipe.none.upload.erase_cmd= +d1_mini_pro.menu.wipe.sdk=Sketch + WiFi Settings +d1_mini_pro.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +d1_mini_pro.menu.wipe.all=All Flash Contents +d1_mini_pro.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +d1_mini_pro.menu.baud.921600=921600 +d1_mini_pro.menu.baud.921600.upload.speed=921600 +d1_mini_pro.menu.baud.9600=9600 +d1_mini_pro.menu.baud.9600.upload.speed=9600 +d1_mini_pro.menu.baud.57600=57600 +d1_mini_pro.menu.baud.57600.upload.speed=57600 +d1_mini_pro.menu.baud.115200=115200 +d1_mini_pro.menu.baud.115200.upload.speed=115200 +d1_mini_pro.menu.baud.230400.linux=230400 +d1_mini_pro.menu.baud.230400.macosx=230400 +d1_mini_pro.menu.baud.230400.upload.speed=230400 +d1_mini_pro.menu.baud.256000.windows=256000 +d1_mini_pro.menu.baud.256000.upload.speed=256000 +d1_mini_pro.menu.baud.460800.linux=460800 +d1_mini_pro.menu.baud.460800.macosx=460800 +d1_mini_pro.menu.baud.460800.upload.speed=460800 +d1_mini_pro.menu.baud.512000.windows=512000 +d1_mini_pro.menu.baud.512000.upload.speed=512000 + +############################################################## +d1_mini_lite.name=LOLIN(WEMOS) D1 mini Lite +d1_mini_lite.build.board=ESP8266_WEMOS_D1MINILITE +d1_mini_lite.build.variant=d1_mini +d1_mini_lite.upload.tool=esptool +d1_mini_lite.upload.maximum_data_size=81920 +d1_mini_lite.upload.wait_for_upload_port=true +d1_mini_lite.upload.erase_cmd= +d1_mini_lite.serial.disableDTR=true +d1_mini_lite.serial.disableRTS=true +d1_mini_lite.build.mcu=esp8266 +d1_mini_lite.build.core=esp8266 +d1_mini_lite.build.spiffs_pagesize=256 +d1_mini_lite.build.debug_port= +d1_mini_lite.build.debug_level= +d1_mini_lite.menu.xtal.80=80 MHz +d1_mini_lite.menu.xtal.80.build.f_cpu=80000000L +d1_mini_lite.menu.xtal.160=160 MHz +d1_mini_lite.menu.xtal.160.build.f_cpu=160000000L +d1_mini_lite.menu.vt.flash=Flash +d1_mini_lite.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1_mini_lite.menu.vt.heap=Heap +d1_mini_lite.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1_mini_lite.menu.vt.iram=IRAM +d1_mini_lite.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1_mini_lite.menu.exception.disabled=Disabled +d1_mini_lite.menu.exception.disabled.build.exception_flags=-fno-exceptions +d1_mini_lite.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1_mini_lite.menu.exception.enabled=Enabled +d1_mini_lite.menu.exception.enabled.build.exception_flags=-fexceptions +d1_mini_lite.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1_mini_lite.upload.resetmethod=nodemcu +d1_mini_lite.build.flash_mode=dout +d1_mini_lite.build.flash_flags=-DFLASHMODE_DOUT +d1_mini_lite.build.flash_freq=40 +d1_mini_lite.menu.eesz.1M=1M (no SPIFFS) +d1_mini_lite.menu.eesz.1M.build.flash_size=1M +d1_mini_lite.menu.eesz.1M.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +d1_mini_lite.menu.eesz.1M.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M.upload.maximum_size=1023984 +d1_mini_lite.menu.eesz.1M.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M64=1M (64K SPIFFS) +d1_mini_lite.menu.eesz.1M64.build.flash_size=1M +d1_mini_lite.menu.eesz.1M64.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +d1_mini_lite.menu.eesz.1M64.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M64.upload.maximum_size=958448 +d1_mini_lite.menu.eesz.1M64.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M64.build.spiffs_start=0xEB000 +d1_mini_lite.menu.eesz.1M64.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M64.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M128=1M (128K SPIFFS) +d1_mini_lite.menu.eesz.1M128.build.flash_size=1M +d1_mini_lite.menu.eesz.1M128.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +d1_mini_lite.menu.eesz.1M128.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M128.upload.maximum_size=892912 +d1_mini_lite.menu.eesz.1M128.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M128.build.spiffs_start=0xDB000 +d1_mini_lite.menu.eesz.1M128.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M128.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M144=1M (144K SPIFFS) +d1_mini_lite.menu.eesz.1M144.build.flash_size=1M +d1_mini_lite.menu.eesz.1M144.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +d1_mini_lite.menu.eesz.1M144.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M144.upload.maximum_size=876528 +d1_mini_lite.menu.eesz.1M144.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M144.build.spiffs_start=0xD7000 +d1_mini_lite.menu.eesz.1M144.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M144.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M160=1M (160K SPIFFS) +d1_mini_lite.menu.eesz.1M160.build.flash_size=1M +d1_mini_lite.menu.eesz.1M160.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +d1_mini_lite.menu.eesz.1M160.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M160.upload.maximum_size=860144 +d1_mini_lite.menu.eesz.1M160.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M160.build.spiffs_start=0xD3000 +d1_mini_lite.menu.eesz.1M160.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M160.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M192=1M (192K SPIFFS) +d1_mini_lite.menu.eesz.1M192.build.flash_size=1M +d1_mini_lite.menu.eesz.1M192.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +d1_mini_lite.menu.eesz.1M192.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M192.upload.maximum_size=827376 +d1_mini_lite.menu.eesz.1M192.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M192.build.spiffs_start=0xCB000 +d1_mini_lite.menu.eesz.1M192.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M192.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M256=1M (256K SPIFFS) +d1_mini_lite.menu.eesz.1M256.build.flash_size=1M +d1_mini_lite.menu.eesz.1M256.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +d1_mini_lite.menu.eesz.1M256.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M256.upload.maximum_size=761840 +d1_mini_lite.menu.eesz.1M256.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M256.build.spiffs_start=0xBB000 +d1_mini_lite.menu.eesz.1M256.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M256.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M512=1M (512K SPIFFS) +d1_mini_lite.menu.eesz.1M512.build.flash_size=1M +d1_mini_lite.menu.eesz.1M512.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +d1_mini_lite.menu.eesz.1M512.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M512.upload.maximum_size=499696 +d1_mini_lite.menu.eesz.1M512.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M512.build.spiffs_start=0x7B000 +d1_mini_lite.menu.eesz.1M512.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M512.build.spiffs_blocksize=4096 +d1_mini_lite.menu.ip.lm2f=v2 Lower Memory +d1_mini_lite.menu.ip.lm2f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1_mini_lite.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.hb2f=v2 Higher Bandwidth +d1_mini_lite.menu.ip.hb2f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1_mini_lite.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.lm2n=v2 Lower Memory (no features) +d1_mini_lite.menu.ip.lm2n.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1_mini_lite.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1_mini_lite.menu.ip.hb2n.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1_mini_lite.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.lm6f=v2 IPv6 Lower Memory +d1_mini_lite.menu.ip.lm6f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1_mini_lite.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_lite.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1_mini_lite.menu.ip.hb6f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1_mini_lite.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_lite.menu.ip.hb1=v1.4 Higher Bandwidth +d1_mini_lite.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1_mini_lite.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_lite.menu.ip.src=v1.4 Compile from source +d1_mini_lite.menu.ip.src.build.lwip_lib=-llwip_src +d1_mini_lite.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_lite.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1_mini_lite.menu.dbg.Disabled=Disabled +d1_mini_lite.menu.dbg.Disabled.build.debug_port= +d1_mini_lite.menu.dbg.Serial=Serial +d1_mini_lite.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1_mini_lite.menu.dbg.Serial1=Serial1 +d1_mini_lite.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1_mini_lite.menu.lvl.None____=None +d1_mini_lite.menu.lvl.None____.build.debug_level= +d1_mini_lite.menu.lvl.SSL=SSL +d1_mini_lite.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1_mini_lite.menu.lvl.TLS_MEM=TLS_MEM +d1_mini_lite.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1_mini_lite.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1_mini_lite.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1_mini_lite.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1_mini_lite.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1_mini_lite.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.CORE=CORE +d1_mini_lite.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1_mini_lite.menu.lvl.WIFI=WIFI +d1_mini_lite.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1_mini_lite.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1_mini_lite.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1_mini_lite.menu.lvl.UPDATER=UPDATER +d1_mini_lite.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1_mini_lite.menu.lvl.OTA=OTA +d1_mini_lite.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1_mini_lite.menu.lvl.OOM=OOM +d1_mini_lite.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1_mini_lite.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1_mini_lite.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1_mini_lite.menu.wipe.none=Only Sketch +d1_mini_lite.menu.wipe.none.upload.erase_cmd= +d1_mini_lite.menu.wipe.sdk=Sketch + WiFi Settings +d1_mini_lite.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +d1_mini_lite.menu.wipe.all=All Flash Contents +d1_mini_lite.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +d1_mini_lite.menu.baud.921600=921600 +d1_mini_lite.menu.baud.921600.upload.speed=921600 +d1_mini_lite.menu.baud.9600=9600 +d1_mini_lite.menu.baud.9600.upload.speed=9600 +d1_mini_lite.menu.baud.57600=57600 +d1_mini_lite.menu.baud.57600.upload.speed=57600 +d1_mini_lite.menu.baud.115200=115200 +d1_mini_lite.menu.baud.115200.upload.speed=115200 +d1_mini_lite.menu.baud.230400.linux=230400 +d1_mini_lite.menu.baud.230400.macosx=230400 +d1_mini_lite.menu.baud.230400.upload.speed=230400 +d1_mini_lite.menu.baud.256000.windows=256000 +d1_mini_lite.menu.baud.256000.upload.speed=256000 +d1_mini_lite.menu.baud.460800.linux=460800 +d1_mini_lite.menu.baud.460800.macosx=460800 +d1_mini_lite.menu.baud.460800.upload.speed=460800 +d1_mini_lite.menu.baud.512000.windows=512000 +d1_mini_lite.menu.baud.512000.upload.speed=512000 + +############################################################## +d1.name=WeMos D1 R1 +d1.build.board=ESP8266_WEMOS_D1R1 +d1.build.variant=d1 +d1.upload.tool=esptool +d1.upload.maximum_data_size=81920 +d1.upload.wait_for_upload_port=true +d1.upload.erase_cmd= +d1.serial.disableDTR=true +d1.serial.disableRTS=true +d1.build.mcu=esp8266 +d1.build.core=esp8266 +d1.build.spiffs_pagesize=256 +d1.build.debug_port= +d1.build.debug_level= +d1.menu.xtal.80=80 MHz +d1.menu.xtal.80.build.f_cpu=80000000L +d1.menu.xtal.160=160 MHz +d1.menu.xtal.160.build.f_cpu=160000000L +d1.menu.vt.flash=Flash +d1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1.menu.vt.heap=Heap +d1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1.menu.vt.iram=IRAM +d1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1.menu.exception.disabled=Disabled +d1.menu.exception.disabled.build.exception_flags=-fno-exceptions +d1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1.menu.exception.enabled=Enabled +d1.menu.exception.enabled.build.exception_flags=-fexceptions +d1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1.upload.resetmethod=nodemcu +d1.build.flash_mode=dio +d1.build.flash_flags=-DFLASHMODE_DIO +d1.build.flash_freq=40 +d1.menu.eesz.4M=4M (no SPIFFS) +d1.menu.eesz.4M.build.flash_size=4M +d1.menu.eesz.4M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +d1.menu.eesz.4M.build.spiffs_pagesize=256 +d1.menu.eesz.4M.upload.maximum_size=1044464 +d1.menu.eesz.4M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M1M=4M (1M SPIFFS) +d1.menu.eesz.4M1M.build.flash_size=4M +d1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +d1.menu.eesz.4M1M.build.spiffs_pagesize=256 +d1.menu.eesz.4M1M.upload.maximum_size=1044464 +d1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M1M.build.spiffs_start=0x300000 +d1.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +d1.menu.eesz.4M1M.build.spiffs_blocksize=8192 +d1.menu.eesz.4M2M=4M (2M SPIFFS) +d1.menu.eesz.4M2M.build.flash_size=4M +d1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +d1.menu.eesz.4M2M.build.spiffs_pagesize=256 +d1.menu.eesz.4M2M.upload.maximum_size=1044464 +d1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M2M.build.spiffs_start=0x200000 +d1.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +d1.menu.eesz.4M2M.build.spiffs_blocksize=8192 +d1.menu.eesz.4M3M=4M (3M SPIFFS) +d1.menu.eesz.4M3M.build.flash_size=4M +d1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +d1.menu.eesz.4M3M.build.spiffs_pagesize=256 +d1.menu.eesz.4M3M.upload.maximum_size=1044464 +d1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M3M.build.spiffs_start=0x100000 +d1.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +d1.menu.eesz.4M3M.build.spiffs_blocksize=8192 +d1.menu.ip.lm2f=v2 Lower Memory +d1.menu.ip.lm2f.build.lwip_include=lwip2/include +d1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1.menu.ip.hb2f=v2 Higher Bandwidth +d1.menu.ip.hb2f.build.lwip_include=lwip2/include +d1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1.menu.ip.lm2n=v2 Lower Memory (no features) +d1.menu.ip.lm2n.build.lwip_include=lwip2/include +d1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1.menu.ip.hb2n.build.lwip_include=lwip2/include +d1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1.menu.ip.lm6f=v2 IPv6 Lower Memory +d1.menu.ip.lm6f.build.lwip_include=lwip2/include +d1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1.menu.ip.hb6f.build.lwip_include=lwip2/include +d1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1.menu.ip.hb1=v1.4 Higher Bandwidth +d1.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1.menu.ip.src=v1.4 Compile from source +d1.menu.ip.src.build.lwip_lib=-llwip_src +d1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1.menu.dbg.Disabled=Disabled +d1.menu.dbg.Disabled.build.debug_port= +d1.menu.dbg.Serial=Serial +d1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1.menu.dbg.Serial1=Serial1 +d1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1.menu.lvl.None____=None +d1.menu.lvl.None____.build.debug_level= +d1.menu.lvl.SSL=SSL +d1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1.menu.lvl.TLS_MEM=TLS_MEM +d1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.CORE=CORE +d1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1.menu.lvl.WIFI=WIFI +d1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1.menu.lvl.UPDATER=UPDATER +d1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1.menu.lvl.OTA=OTA +d1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1.menu.lvl.OOM=OOM +d1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +d1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1.menu.wipe.none=Only Sketch +d1.menu.wipe.none.upload.erase_cmd= +d1.menu.wipe.sdk=Sketch + WiFi Settings +d1.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +d1.menu.wipe.all=All Flash Contents +d1.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +d1.menu.baud.921600=921600 +d1.menu.baud.921600.upload.speed=921600 +d1.menu.baud.9600=9600 +d1.menu.baud.9600.upload.speed=9600 +d1.menu.baud.57600=57600 +d1.menu.baud.57600.upload.speed=57600 +d1.menu.baud.115200=115200 +d1.menu.baud.115200.upload.speed=115200 +d1.menu.baud.230400.linux=230400 +d1.menu.baud.230400.macosx=230400 +d1.menu.baud.230400.upload.speed=230400 +d1.menu.baud.256000.windows=256000 +d1.menu.baud.256000.upload.speed=256000 +d1.menu.baud.460800.linux=460800 +d1.menu.baud.460800.macosx=460800 +d1.menu.baud.460800.upload.speed=460800 +d1.menu.baud.512000.windows=512000 +d1.menu.baud.512000.upload.speed=512000 + +############################################################## +espino.name=ESPino (ESP-12 Module) +espino.build.board=ESP8266_ESP12 +espino.build.variant=espino +espino.upload.tool=esptool +espino.upload.maximum_data_size=81920 +espino.upload.wait_for_upload_port=true +espino.upload.erase_cmd= +espino.serial.disableDTR=true +espino.serial.disableRTS=true +espino.build.mcu=esp8266 +espino.build.core=esp8266 +espino.build.spiffs_pagesize=256 +espino.build.debug_port= +espino.build.debug_level= +espino.menu.xtal.80=80 MHz +espino.menu.xtal.80.build.f_cpu=80000000L +espino.menu.xtal.160=160 MHz +espino.menu.xtal.160.build.f_cpu=160000000L +espino.menu.vt.flash=Flash +espino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espino.menu.vt.heap=Heap +espino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espino.menu.vt.iram=IRAM +espino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espino.menu.exception.disabled=Disabled +espino.menu.exception.disabled.build.exception_flags=-fno-exceptions +espino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espino.menu.exception.enabled=Enabled +espino.menu.exception.enabled.build.exception_flags=-fexceptions +espino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espino.menu.ResetMethod.ck=ck +espino.menu.ResetMethod.ck.upload.resetmethod=ck +espino.menu.ResetMethod.nodemcu=nodemcu +espino.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +espino.build.flash_mode=qio +espino.build.flash_flags=-DFLASHMODE_QIO +espino.build.flash_freq=40 +espino.menu.eesz.4M=4M (no SPIFFS) +espino.menu.eesz.4M.build.flash_size=4M +espino.menu.eesz.4M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espino.menu.eesz.4M.build.spiffs_pagesize=256 +espino.menu.eesz.4M.upload.maximum_size=1044464 +espino.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M1M=4M (1M SPIFFS) +espino.menu.eesz.4M1M.build.flash_size=4M +espino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espino.menu.eesz.4M1M.build.spiffs_pagesize=256 +espino.menu.eesz.4M1M.upload.maximum_size=1044464 +espino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M1M.build.spiffs_start=0x300000 +espino.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +espino.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espino.menu.eesz.4M2M=4M (2M SPIFFS) +espino.menu.eesz.4M2M.build.flash_size=4M +espino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espino.menu.eesz.4M2M.build.spiffs_pagesize=256 +espino.menu.eesz.4M2M.upload.maximum_size=1044464 +espino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M2M.build.spiffs_start=0x200000 +espino.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +espino.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espino.menu.eesz.4M3M=4M (3M SPIFFS) +espino.menu.eesz.4M3M.build.flash_size=4M +espino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espino.menu.eesz.4M3M.build.spiffs_pagesize=256 +espino.menu.eesz.4M3M.upload.maximum_size=1044464 +espino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M3M.build.spiffs_start=0x100000 +espino.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +espino.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espino.menu.ip.lm2f=v2 Lower Memory +espino.menu.ip.lm2f.build.lwip_include=lwip2/include +espino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espino.menu.ip.hb2f=v2 Higher Bandwidth +espino.menu.ip.hb2f.build.lwip_include=lwip2/include +espino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espino.menu.ip.lm2n=v2 Lower Memory (no features) +espino.menu.ip.lm2n.build.lwip_include=lwip2/include +espino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espino.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espino.menu.ip.hb2n.build.lwip_include=lwip2/include +espino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espino.menu.ip.lm6f=v2 IPv6 Lower Memory +espino.menu.ip.lm6f.build.lwip_include=lwip2/include +espino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espino.menu.ip.hb6f.build.lwip_include=lwip2/include +espino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espino.menu.ip.hb1=v1.4 Higher Bandwidth +espino.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espino.menu.ip.src=v1.4 Compile from source +espino.menu.ip.src.build.lwip_lib=-llwip_src +espino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espino.menu.dbg.Disabled=Disabled +espino.menu.dbg.Disabled.build.debug_port= +espino.menu.dbg.Serial=Serial +espino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espino.menu.dbg.Serial1=Serial1 +espino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espino.menu.lvl.None____=None +espino.menu.lvl.None____.build.debug_level= +espino.menu.lvl.SSL=SSL +espino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espino.menu.lvl.TLS_MEM=TLS_MEM +espino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.HTTP_SERVER=HTTP_SERVER +espino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.CORE=CORE +espino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espino.menu.lvl.WIFI=WIFI +espino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espino.menu.lvl.UPDATER=UPDATER +espino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espino.menu.lvl.OTA=OTA +espino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espino.menu.lvl.OOM=OOM +espino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espino.menu.wipe.none=Only Sketch +espino.menu.wipe.none.upload.erase_cmd= +espino.menu.wipe.sdk=Sketch + WiFi Settings +espino.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +espino.menu.wipe.all=All Flash Contents +espino.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +espino.menu.baud.115200=115200 +espino.menu.baud.115200.upload.speed=115200 +espino.menu.baud.9600=9600 +espino.menu.baud.9600.upload.speed=9600 +espino.menu.baud.57600=57600 +espino.menu.baud.57600.upload.speed=57600 +espino.menu.baud.230400.linux=230400 +espino.menu.baud.230400.macosx=230400 +espino.menu.baud.230400.upload.speed=230400 +espino.menu.baud.256000.windows=256000 +espino.menu.baud.256000.upload.speed=256000 +espino.menu.baud.460800.linux=460800 +espino.menu.baud.460800.macosx=460800 +espino.menu.baud.460800.upload.speed=460800 +espino.menu.baud.512000.windows=512000 +espino.menu.baud.512000.upload.speed=512000 +espino.menu.baud.921600=921600 +espino.menu.baud.921600.upload.speed=921600 + +############################################################## +espinotee.name=ThaiEasyElec's ESPino +espinotee.build.board=ESP8266_ESP13 +espinotee.build.variant=espinotee +espinotee.upload.tool=esptool +espinotee.upload.maximum_data_size=81920 +espinotee.upload.wait_for_upload_port=true +espinotee.upload.erase_cmd= +espinotee.serial.disableDTR=true +espinotee.serial.disableRTS=true +espinotee.build.mcu=esp8266 +espinotee.build.core=esp8266 +espinotee.build.spiffs_pagesize=256 +espinotee.build.debug_port= +espinotee.build.debug_level= +espinotee.menu.xtal.80=80 MHz +espinotee.menu.xtal.80.build.f_cpu=80000000L +espinotee.menu.xtal.160=160 MHz +espinotee.menu.xtal.160.build.f_cpu=160000000L +espinotee.menu.vt.flash=Flash +espinotee.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espinotee.menu.vt.heap=Heap +espinotee.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espinotee.menu.vt.iram=IRAM +espinotee.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espinotee.menu.exception.disabled=Disabled +espinotee.menu.exception.disabled.build.exception_flags=-fno-exceptions +espinotee.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espinotee.menu.exception.enabled=Enabled +espinotee.menu.exception.enabled.build.exception_flags=-fexceptions +espinotee.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espinotee.upload.resetmethod=nodemcu +espinotee.build.flash_mode=qio +espinotee.build.flash_flags=-DFLASHMODE_QIO +espinotee.build.flash_freq=40 +espinotee.menu.eesz.4M=4M (no SPIFFS) +espinotee.menu.eesz.4M.build.flash_size=4M +espinotee.menu.eesz.4M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espinotee.menu.eesz.4M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M1M=4M (1M SPIFFS) +espinotee.menu.eesz.4M1M.build.flash_size=4M +espinotee.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espinotee.menu.eesz.4M1M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M1M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M1M.build.spiffs_start=0x300000 +espinotee.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +espinotee.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espinotee.menu.eesz.4M2M=4M (2M SPIFFS) +espinotee.menu.eesz.4M2M.build.flash_size=4M +espinotee.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espinotee.menu.eesz.4M2M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M2M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M2M.build.spiffs_start=0x200000 +espinotee.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +espinotee.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espinotee.menu.eesz.4M3M=4M (3M SPIFFS) +espinotee.menu.eesz.4M3M.build.flash_size=4M +espinotee.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espinotee.menu.eesz.4M3M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M3M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M3M.build.spiffs_start=0x100000 +espinotee.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +espinotee.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espinotee.menu.ip.lm2f=v2 Lower Memory +espinotee.menu.ip.lm2f.build.lwip_include=lwip2/include +espinotee.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espinotee.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espinotee.menu.ip.hb2f=v2 Higher Bandwidth +espinotee.menu.ip.hb2f.build.lwip_include=lwip2/include +espinotee.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espinotee.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espinotee.menu.ip.lm2n=v2 Lower Memory (no features) +espinotee.menu.ip.lm2n.build.lwip_include=lwip2/include +espinotee.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espinotee.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espinotee.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espinotee.menu.ip.hb2n.build.lwip_include=lwip2/include +espinotee.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espinotee.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espinotee.menu.ip.lm6f=v2 IPv6 Lower Memory +espinotee.menu.ip.lm6f.build.lwip_include=lwip2/include +espinotee.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espinotee.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espinotee.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espinotee.menu.ip.hb6f.build.lwip_include=lwip2/include +espinotee.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espinotee.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espinotee.menu.ip.hb1=v1.4 Higher Bandwidth +espinotee.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espinotee.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espinotee.menu.ip.src=v1.4 Compile from source +espinotee.menu.ip.src.build.lwip_lib=-llwip_src +espinotee.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espinotee.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espinotee.menu.dbg.Disabled=Disabled +espinotee.menu.dbg.Disabled.build.debug_port= +espinotee.menu.dbg.Serial=Serial +espinotee.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espinotee.menu.dbg.Serial1=Serial1 +espinotee.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espinotee.menu.lvl.None____=None +espinotee.menu.lvl.None____.build.debug_level= +espinotee.menu.lvl.SSL=SSL +espinotee.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espinotee.menu.lvl.TLS_MEM=TLS_MEM +espinotee.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espinotee.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espinotee.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.HTTP_SERVER=HTTP_SERVER +espinotee.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espinotee.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espinotee.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espinotee.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espinotee.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espinotee.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.CORE=CORE +espinotee.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espinotee.menu.lvl.WIFI=WIFI +espinotee.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espinotee.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espinotee.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espinotee.menu.lvl.UPDATER=UPDATER +espinotee.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espinotee.menu.lvl.OTA=OTA +espinotee.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espinotee.menu.lvl.OOM=OOM +espinotee.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espinotee.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espinotee.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espinotee.menu.wipe.none=Only Sketch +espinotee.menu.wipe.none.upload.erase_cmd= +espinotee.menu.wipe.sdk=Sketch + WiFi Settings +espinotee.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +espinotee.menu.wipe.all=All Flash Contents +espinotee.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +espinotee.menu.baud.115200=115200 +espinotee.menu.baud.115200.upload.speed=115200 +espinotee.menu.baud.9600=9600 +espinotee.menu.baud.9600.upload.speed=9600 +espinotee.menu.baud.57600=57600 +espinotee.menu.baud.57600.upload.speed=57600 +espinotee.menu.baud.230400.linux=230400 +espinotee.menu.baud.230400.macosx=230400 +espinotee.menu.baud.230400.upload.speed=230400 +espinotee.menu.baud.256000.windows=256000 +espinotee.menu.baud.256000.upload.speed=256000 +espinotee.menu.baud.460800.linux=460800 +espinotee.menu.baud.460800.macosx=460800 +espinotee.menu.baud.460800.upload.speed=460800 +espinotee.menu.baud.512000.windows=512000 +espinotee.menu.baud.512000.upload.speed=512000 +espinotee.menu.baud.921600=921600 +espinotee.menu.baud.921600.upload.speed=921600 + +############################################################## +wifinfo.name=WifInfo +wifinfo.menu.ESPModule.ESP12.build.board=ESP8266_ESP12 +wifinfo.menu.ESPModule.ESP12.upload.maximum_size=1044464 +wifinfo.menu.ESPModule.ESP12.build.spiffs_pagesize=256 +wifinfo.menu.ESPModule.ESP12.build.flash_ld=eagle.flash.4m1m.ld +wifinfo.menu.ESPModule.ESP07192.build.spiffs_blocksize=4096 +wifinfo.menu.ESPModule.ESP07192.build.spiffs_end=0xFB000 +wifinfo.menu.ESPModule.ESP12=ESP12 (4M/1M SPIFFS) +wifinfo.menu.ESPModule.ESP12.build.spiffs_start=0x300000 +wifinfo.menu.ESPModule.ESP12.build.spiffs_end=0x3FB000 +wifinfo.menu.ESPModule.ESP07192.build.spiffs_start=0xCB000 +wifinfo.menu.ESPModule.ESP07192.build.board=ESP8266_ESP07 +wifinfo.menu.ESPModule.ESP12.build.spiffs_blocksize=8192 +wifinfo.menu.ESPModule.ESP12.build.flash_size=4M +wifinfo.build.board=WIFINFO +wifinfo.build.variant=wifinfo +wifinfo.menu.ESPModule.ESP07192.build.flash_ld=eagle.flash.1m192.ld +wifinfo.menu.ESPModule.ESP07192.build.flash_size=1M +wifinfo.menu.ESPModule.ESP07192=ESP07 (1M/192K SPIFFS) +wifinfo.menu.ESPModule.ESP07192.upload.maximum_size=827376 +wifinfo.upload.tool=esptool +wifinfo.upload.maximum_data_size=81920 +wifinfo.upload.wait_for_upload_port=true +wifinfo.upload.erase_cmd= +wifinfo.serial.disableDTR=true +wifinfo.serial.disableRTS=true +wifinfo.build.mcu=esp8266 +wifinfo.build.core=esp8266 +wifinfo.build.spiffs_pagesize=256 +wifinfo.build.debug_port= +wifinfo.build.debug_level= +wifinfo.menu.xtal.80=80 MHz +wifinfo.menu.xtal.80.build.f_cpu=80000000L +wifinfo.menu.xtal.160=160 MHz +wifinfo.menu.xtal.160.build.f_cpu=160000000L +wifinfo.menu.vt.flash=Flash +wifinfo.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wifinfo.menu.vt.heap=Heap +wifinfo.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wifinfo.menu.vt.iram=IRAM +wifinfo.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wifinfo.menu.exception.disabled=Disabled +wifinfo.menu.exception.disabled.build.exception_flags=-fno-exceptions +wifinfo.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wifinfo.menu.exception.enabled=Enabled +wifinfo.menu.exception.enabled.build.exception_flags=-fexceptions +wifinfo.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wifinfo.upload.resetmethod=nodemcu +wifinfo.build.flash_mode=qio +wifinfo.build.flash_flags=-DFLASHMODE_QIO +wifinfo.menu.FlashFreq.40=40MHz +wifinfo.menu.FlashFreq.40.build.flash_freq=40 +wifinfo.menu.FlashFreq.80=80MHz +wifinfo.menu.FlashFreq.80.build.flash_freq=80 +wifinfo.menu.eesz.1M=1M (no SPIFFS) +wifinfo.menu.eesz.1M.build.flash_size=1M +wifinfo.menu.eesz.1M.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +wifinfo.menu.eesz.1M.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M.upload.maximum_size=1023984 +wifinfo.menu.eesz.1M.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M64=1M (64K SPIFFS) +wifinfo.menu.eesz.1M64.build.flash_size=1M +wifinfo.menu.eesz.1M64.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +wifinfo.menu.eesz.1M64.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M64.upload.maximum_size=958448 +wifinfo.menu.eesz.1M64.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M64.build.spiffs_start=0xEB000 +wifinfo.menu.eesz.1M64.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M64.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M128=1M (128K SPIFFS) +wifinfo.menu.eesz.1M128.build.flash_size=1M +wifinfo.menu.eesz.1M128.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +wifinfo.menu.eesz.1M128.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M128.upload.maximum_size=892912 +wifinfo.menu.eesz.1M128.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M128.build.spiffs_start=0xDB000 +wifinfo.menu.eesz.1M128.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M128.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M144=1M (144K SPIFFS) +wifinfo.menu.eesz.1M144.build.flash_size=1M +wifinfo.menu.eesz.1M144.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +wifinfo.menu.eesz.1M144.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M144.upload.maximum_size=876528 +wifinfo.menu.eesz.1M144.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M144.build.spiffs_start=0xD7000 +wifinfo.menu.eesz.1M144.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M144.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M160=1M (160K SPIFFS) +wifinfo.menu.eesz.1M160.build.flash_size=1M +wifinfo.menu.eesz.1M160.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +wifinfo.menu.eesz.1M160.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M160.upload.maximum_size=860144 +wifinfo.menu.eesz.1M160.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M160.build.spiffs_start=0xD3000 +wifinfo.menu.eesz.1M160.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M160.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M192=1M (192K SPIFFS) +wifinfo.menu.eesz.1M192.build.flash_size=1M +wifinfo.menu.eesz.1M192.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +wifinfo.menu.eesz.1M192.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M192.upload.maximum_size=827376 +wifinfo.menu.eesz.1M192.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M192.build.spiffs_start=0xCB000 +wifinfo.menu.eesz.1M192.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M192.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M256=1M (256K SPIFFS) +wifinfo.menu.eesz.1M256.build.flash_size=1M +wifinfo.menu.eesz.1M256.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +wifinfo.menu.eesz.1M256.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M256.upload.maximum_size=761840 +wifinfo.menu.eesz.1M256.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M256.build.spiffs_start=0xBB000 +wifinfo.menu.eesz.1M256.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M256.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M512=1M (512K SPIFFS) +wifinfo.menu.eesz.1M512.build.flash_size=1M +wifinfo.menu.eesz.1M512.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +wifinfo.menu.eesz.1M512.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M512.upload.maximum_size=499696 +wifinfo.menu.eesz.1M512.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M512.build.spiffs_start=0x7B000 +wifinfo.menu.eesz.1M512.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M512.build.spiffs_blocksize=4096 +wifinfo.menu.ip.lm2f=v2 Lower Memory +wifinfo.menu.ip.lm2f.build.lwip_include=lwip2/include +wifinfo.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wifinfo.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifinfo.menu.ip.hb2f=v2 Higher Bandwidth +wifinfo.menu.ip.hb2f.build.lwip_include=lwip2/include +wifinfo.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wifinfo.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifinfo.menu.ip.lm2n=v2 Lower Memory (no features) +wifinfo.menu.ip.lm2n.build.lwip_include=lwip2/include +wifinfo.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wifinfo.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifinfo.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wifinfo.menu.ip.hb2n.build.lwip_include=lwip2/include +wifinfo.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wifinfo.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifinfo.menu.ip.lm6f=v2 IPv6 Lower Memory +wifinfo.menu.ip.lm6f.build.lwip_include=lwip2/include +wifinfo.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wifinfo.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifinfo.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wifinfo.menu.ip.hb6f.build.lwip_include=lwip2/include +wifinfo.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wifinfo.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifinfo.menu.ip.hb1=v1.4 Higher Bandwidth +wifinfo.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wifinfo.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wifinfo.menu.ip.src=v1.4 Compile from source +wifinfo.menu.ip.src.build.lwip_lib=-llwip_src +wifinfo.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wifinfo.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wifinfo.menu.dbg.Disabled=Disabled +wifinfo.menu.dbg.Disabled.build.debug_port= +wifinfo.menu.dbg.Serial=Serial +wifinfo.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wifinfo.menu.dbg.Serial1=Serial1 +wifinfo.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wifinfo.menu.lvl.None____=None +wifinfo.menu.lvl.None____.build.debug_level= +wifinfo.menu.lvl.SSL=SSL +wifinfo.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wifinfo.menu.lvl.TLS_MEM=TLS_MEM +wifinfo.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wifinfo.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wifinfo.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.HTTP_SERVER=HTTP_SERVER +wifinfo.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wifinfo.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wifinfo.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wifinfo.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wifinfo.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.CORE=CORE +wifinfo.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wifinfo.menu.lvl.WIFI=WIFI +wifinfo.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wifinfo.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wifinfo.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wifinfo.menu.lvl.UPDATER=UPDATER +wifinfo.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wifinfo.menu.lvl.OTA=OTA +wifinfo.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wifinfo.menu.lvl.OOM=OOM +wifinfo.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wifinfo.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wifinfo.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wifinfo.menu.wipe.none=Only Sketch +wifinfo.menu.wipe.none.upload.erase_cmd= +wifinfo.menu.wipe.sdk=Sketch + WiFi Settings +wifinfo.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +wifinfo.menu.wipe.all=All Flash Contents +wifinfo.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +wifinfo.menu.baud.115200=115200 +wifinfo.menu.baud.115200.upload.speed=115200 +wifinfo.menu.baud.9600=9600 +wifinfo.menu.baud.9600.upload.speed=9600 +wifinfo.menu.baud.57600=57600 +wifinfo.menu.baud.57600.upload.speed=57600 +wifinfo.menu.baud.230400.linux=230400 +wifinfo.menu.baud.230400.macosx=230400 +wifinfo.menu.baud.230400.upload.speed=230400 +wifinfo.menu.baud.256000.windows=256000 +wifinfo.menu.baud.256000.upload.speed=256000 +wifinfo.menu.baud.460800.linux=460800 +wifinfo.menu.baud.460800.macosx=460800 +wifinfo.menu.baud.460800.upload.speed=460800 +wifinfo.menu.baud.512000.windows=512000 +wifinfo.menu.baud.512000.upload.speed=512000 +wifinfo.menu.baud.921600=921600 +wifinfo.menu.baud.921600.upload.speed=921600 + +############################################################## +arduino-esp8266.name=Arduino +arduino-esp8266.menu.BoardModel.starottodeved.build.board=ESP8266_ARDUINO_STAR_OTTO +arduino-esp8266.menu.BoardModel.primo.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +arduino-esp8266.menu.BoardModel.starottodeved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +arduino-esp8266.menu.BoardModel.starottodeved.build.variant=arduino_uart +arduino-esp8266.menu.BoardModel.unowifideved.build.board=ESP8266_ARDUINO_UNOWIFI +arduino-esp8266.menu.BoardModel.unowifideved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +arduino-esp8266.menu.BoardModel.primo=Primo +arduino-esp8266.menu.BoardModel.unowifideved.build.variant=arduino_uart +arduino-esp8266.menu.BoardModel.primo.build.variant=arduino_spi +arduino-esp8266.menu.BoardModel.starottodeved=Star OTTO +arduino-esp8266.build.board=ESP8266_ARDUINO +arduino-esp8266.menu.BoardModel.primo.build.board=ESP8266_ARDUINO_PRIMO +arduino-esp8266.menu.BoardModel.unowifideved=Uno WiFi +arduino-esp8266.upload.tool=esptool +arduino-esp8266.upload.maximum_data_size=81920 +arduino-esp8266.upload.wait_for_upload_port=true +arduino-esp8266.upload.erase_cmd= +arduino-esp8266.serial.disableDTR=true +arduino-esp8266.serial.disableRTS=true +arduino-esp8266.build.mcu=esp8266 +arduino-esp8266.build.core=esp8266 +arduino-esp8266.build.variant=generic +arduino-esp8266.build.spiffs_pagesize=256 +arduino-esp8266.build.debug_port= +arduino-esp8266.build.debug_level= +arduino-esp8266.menu.xtal.80=80 MHz +arduino-esp8266.menu.xtal.80.build.f_cpu=80000000L +arduino-esp8266.menu.xtal.160=160 MHz +arduino-esp8266.menu.xtal.160.build.f_cpu=160000000L +arduino-esp8266.menu.vt.flash=Flash +arduino-esp8266.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +arduino-esp8266.menu.vt.heap=Heap +arduino-esp8266.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +arduino-esp8266.menu.vt.iram=IRAM +arduino-esp8266.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +arduino-esp8266.menu.exception.disabled=Disabled +arduino-esp8266.menu.exception.disabled.build.exception_flags=-fno-exceptions +arduino-esp8266.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +arduino-esp8266.menu.exception.enabled=Enabled +arduino-esp8266.menu.exception.enabled.build.exception_flags=-fexceptions +arduino-esp8266.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +arduino-esp8266.upload.resetmethod=ck +arduino-esp8266.build.flash_mode=qio +arduino-esp8266.build.flash_flags=-DFLASHMODE_QIO +arduino-esp8266.build.flash_freq=40 +arduino-esp8266.menu.eesz.4M=4M (no SPIFFS) +arduino-esp8266.menu.eesz.4M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +arduino-esp8266.menu.eesz.4M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M1M=4M (1M SPIFFS) +arduino-esp8266.menu.eesz.4M1M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +arduino-esp8266.menu.eesz.4M1M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M1M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M1M.build.spiffs_start=0x300000 +arduino-esp8266.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +arduino-esp8266.menu.eesz.4M1M.build.spiffs_blocksize=8192 +arduino-esp8266.menu.eesz.4M2M=4M (2M SPIFFS) +arduino-esp8266.menu.eesz.4M2M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +arduino-esp8266.menu.eesz.4M2M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M2M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M2M.build.spiffs_start=0x200000 +arduino-esp8266.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +arduino-esp8266.menu.eesz.4M2M.build.spiffs_blocksize=8192 +arduino-esp8266.menu.eesz.4M3M=4M (3M SPIFFS) +arduino-esp8266.menu.eesz.4M3M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +arduino-esp8266.menu.eesz.4M3M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M3M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M3M.build.spiffs_start=0x100000 +arduino-esp8266.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +arduino-esp8266.menu.eesz.4M3M.build.spiffs_blocksize=8192 +arduino-esp8266.menu.ip.lm2f=v2 Lower Memory +arduino-esp8266.menu.ip.lm2f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +arduino-esp8266.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.hb2f=v2 Higher Bandwidth +arduino-esp8266.menu.ip.hb2f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +arduino-esp8266.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.lm2n=v2 Lower Memory (no features) +arduino-esp8266.menu.ip.lm2n.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +arduino-esp8266.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.hb2n=v2 Higher Bandwidth (no features) +arduino-esp8266.menu.ip.hb2n.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +arduino-esp8266.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.lm6f=v2 IPv6 Lower Memory +arduino-esp8266.menu.ip.lm6f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +arduino-esp8266.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +arduino-esp8266.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +arduino-esp8266.menu.ip.hb6f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +arduino-esp8266.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +arduino-esp8266.menu.ip.hb1=v1.4 Higher Bandwidth +arduino-esp8266.menu.ip.hb1.build.lwip_lib=-llwip_gcc +arduino-esp8266.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +arduino-esp8266.menu.ip.src=v1.4 Compile from source +arduino-esp8266.menu.ip.src.build.lwip_lib=-llwip_src +arduino-esp8266.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +arduino-esp8266.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +arduino-esp8266.menu.dbg.Disabled=Disabled +arduino-esp8266.menu.dbg.Disabled.build.debug_port= +arduino-esp8266.menu.dbg.Serial=Serial +arduino-esp8266.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +arduino-esp8266.menu.dbg.Serial1=Serial1 +arduino-esp8266.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +arduino-esp8266.menu.lvl.None____=None +arduino-esp8266.menu.lvl.None____.build.debug_level= +arduino-esp8266.menu.lvl.SSL=SSL +arduino-esp8266.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +arduino-esp8266.menu.lvl.TLS_MEM=TLS_MEM +arduino-esp8266.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +arduino-esp8266.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +arduino-esp8266.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.HTTP_SERVER=HTTP_SERVER +arduino-esp8266.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +arduino-esp8266.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +arduino-esp8266.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.CORE=CORE +arduino-esp8266.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +arduino-esp8266.menu.lvl.WIFI=WIFI +arduino-esp8266.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +arduino-esp8266.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +arduino-esp8266.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +arduino-esp8266.menu.lvl.UPDATER=UPDATER +arduino-esp8266.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +arduino-esp8266.menu.lvl.OTA=OTA +arduino-esp8266.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +arduino-esp8266.menu.lvl.OOM=OOM +arduino-esp8266.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +arduino-esp8266.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +arduino-esp8266.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +arduino-esp8266.menu.wipe.none=Only Sketch +arduino-esp8266.menu.wipe.none.upload.erase_cmd= +arduino-esp8266.menu.wipe.sdk=Sketch + WiFi Settings +arduino-esp8266.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +arduino-esp8266.menu.wipe.all=All Flash Contents +arduino-esp8266.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +arduino-esp8266.menu.baud.115200=115200 +arduino-esp8266.menu.baud.115200.upload.speed=115200 +arduino-esp8266.menu.baud.9600=9600 +arduino-esp8266.menu.baud.9600.upload.speed=9600 +arduino-esp8266.menu.baud.57600=57600 +arduino-esp8266.menu.baud.57600.upload.speed=57600 +arduino-esp8266.menu.baud.230400.linux=230400 +arduino-esp8266.menu.baud.230400.macosx=230400 +arduino-esp8266.menu.baud.230400.upload.speed=230400 +arduino-esp8266.menu.baud.256000.windows=256000 +arduino-esp8266.menu.baud.256000.upload.speed=256000 +arduino-esp8266.menu.baud.460800.linux=460800 +arduino-esp8266.menu.baud.460800.macosx=460800 +arduino-esp8266.menu.baud.460800.upload.speed=460800 +arduino-esp8266.menu.baud.512000.windows=512000 +arduino-esp8266.menu.baud.512000.upload.speed=512000 +arduino-esp8266.menu.baud.921600=921600 +arduino-esp8266.menu.baud.921600.upload.speed=921600 + +############################################################## +gen4iod.name=4D Systems gen4 IoD Range +gen4iod.build.board=GEN4_IOD +gen4iod.build.f_cpu=160000000L +gen4iod.build.variant=generic +gen4iod.upload.tool=esptool +gen4iod.upload.maximum_data_size=81920 +gen4iod.upload.wait_for_upload_port=true +gen4iod.upload.erase_cmd= +gen4iod.serial.disableDTR=true +gen4iod.serial.disableRTS=true +gen4iod.build.mcu=esp8266 +gen4iod.build.core=esp8266 +gen4iod.build.spiffs_pagesize=256 +gen4iod.build.debug_port= +gen4iod.build.debug_level= +gen4iod.menu.xtal.80=80 MHz +gen4iod.menu.xtal.80.build.f_cpu=80000000L +gen4iod.menu.xtal.160=160 MHz +gen4iod.menu.xtal.160.build.f_cpu=160000000L +gen4iod.menu.vt.flash=Flash +gen4iod.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +gen4iod.menu.vt.heap=Heap +gen4iod.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +gen4iod.menu.vt.iram=IRAM +gen4iod.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +gen4iod.menu.exception.disabled=Disabled +gen4iod.menu.exception.disabled.build.exception_flags=-fno-exceptions +gen4iod.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +gen4iod.menu.exception.enabled=Enabled +gen4iod.menu.exception.enabled.build.exception_flags=-fexceptions +gen4iod.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +gen4iod.upload.resetmethod=nodemcu +gen4iod.build.flash_mode=dio +gen4iod.build.flash_flags=-DFLASHMODE_DIO +gen4iod.build.flash_freq=80 +gen4iod.menu.eesz.512K=512K (no SPIFFS) +gen4iod.menu.eesz.512K.build.flash_size=512K +gen4iod.menu.eesz.512K.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +gen4iod.menu.eesz.512K.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K.upload.maximum_size=499696 +gen4iod.menu.eesz.512K.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K32=512K (32K SPIFFS) +gen4iod.menu.eesz.512K32.build.flash_size=512K +gen4iod.menu.eesz.512K32.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +gen4iod.menu.eesz.512K32.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K32.upload.maximum_size=466928 +gen4iod.menu.eesz.512K32.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K32.build.spiffs_start=0x73000 +gen4iod.menu.eesz.512K32.build.spiffs_end=0x7B000 +gen4iod.menu.eesz.512K32.build.spiffs_blocksize=4096 +gen4iod.menu.eesz.512K64=512K (64K SPIFFS) +gen4iod.menu.eesz.512K64.build.flash_size=512K +gen4iod.menu.eesz.512K64.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +gen4iod.menu.eesz.512K64.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K64.upload.maximum_size=434160 +gen4iod.menu.eesz.512K64.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K64.build.spiffs_start=0x6B000 +gen4iod.menu.eesz.512K64.build.spiffs_end=0x7B000 +gen4iod.menu.eesz.512K64.build.spiffs_blocksize=4096 +gen4iod.menu.eesz.512K128=512K (128K SPIFFS) +gen4iod.menu.eesz.512K128.build.flash_size=512K +gen4iod.menu.eesz.512K128.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +gen4iod.menu.eesz.512K128.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K128.upload.maximum_size=368624 +gen4iod.menu.eesz.512K128.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K128.build.spiffs_start=0x5B000 +gen4iod.menu.eesz.512K128.build.spiffs_end=0x7B000 +gen4iod.menu.eesz.512K128.build.spiffs_blocksize=4096 +gen4iod.menu.ip.lm2f=v2 Lower Memory +gen4iod.menu.ip.lm2f.build.lwip_include=lwip2/include +gen4iod.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +gen4iod.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +gen4iod.menu.ip.hb2f=v2 Higher Bandwidth +gen4iod.menu.ip.hb2f.build.lwip_include=lwip2/include +gen4iod.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +gen4iod.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +gen4iod.menu.ip.lm2n=v2 Lower Memory (no features) +gen4iod.menu.ip.lm2n.build.lwip_include=lwip2/include +gen4iod.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +gen4iod.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +gen4iod.menu.ip.hb2n=v2 Higher Bandwidth (no features) +gen4iod.menu.ip.hb2n.build.lwip_include=lwip2/include +gen4iod.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +gen4iod.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +gen4iod.menu.ip.lm6f=v2 IPv6 Lower Memory +gen4iod.menu.ip.lm6f.build.lwip_include=lwip2/include +gen4iod.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +gen4iod.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +gen4iod.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +gen4iod.menu.ip.hb6f.build.lwip_include=lwip2/include +gen4iod.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +gen4iod.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +gen4iod.menu.ip.hb1=v1.4 Higher Bandwidth +gen4iod.menu.ip.hb1.build.lwip_lib=-llwip_gcc +gen4iod.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +gen4iod.menu.ip.src=v1.4 Compile from source +gen4iod.menu.ip.src.build.lwip_lib=-llwip_src +gen4iod.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +gen4iod.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +gen4iod.menu.dbg.Disabled=Disabled +gen4iod.menu.dbg.Disabled.build.debug_port= +gen4iod.menu.dbg.Serial=Serial +gen4iod.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +gen4iod.menu.dbg.Serial1=Serial1 +gen4iod.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +gen4iod.menu.lvl.None____=None +gen4iod.menu.lvl.None____.build.debug_level= +gen4iod.menu.lvl.SSL=SSL +gen4iod.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +gen4iod.menu.lvl.TLS_MEM=TLS_MEM +gen4iod.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +gen4iod.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +gen4iod.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.HTTP_SERVER=HTTP_SERVER +gen4iod.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +gen4iod.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +gen4iod.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +gen4iod.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +gen4iod.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.CORE=CORE +gen4iod.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +gen4iod.menu.lvl.WIFI=WIFI +gen4iod.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +gen4iod.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +gen4iod.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +gen4iod.menu.lvl.UPDATER=UPDATER +gen4iod.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +gen4iod.menu.lvl.OTA=OTA +gen4iod.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +gen4iod.menu.lvl.OOM=OOM +gen4iod.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +gen4iod.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +gen4iod.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +gen4iod.menu.wipe.none=Only Sketch +gen4iod.menu.wipe.none.upload.erase_cmd= +gen4iod.menu.wipe.sdk=Sketch + WiFi Settings +gen4iod.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +gen4iod.menu.wipe.all=All Flash Contents +gen4iod.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +gen4iod.menu.baud.115200=115200 +gen4iod.menu.baud.115200.upload.speed=115200 +gen4iod.menu.baud.9600=9600 +gen4iod.menu.baud.9600.upload.speed=9600 +gen4iod.menu.baud.57600=57600 +gen4iod.menu.baud.57600.upload.speed=57600 +gen4iod.menu.baud.230400.linux=230400 +gen4iod.menu.baud.230400.macosx=230400 +gen4iod.menu.baud.230400.upload.speed=230400 +gen4iod.menu.baud.256000.windows=256000 +gen4iod.menu.baud.256000.upload.speed=256000 +gen4iod.menu.baud.460800.linux=460800 +gen4iod.menu.baud.460800.macosx=460800 +gen4iod.menu.baud.460800.upload.speed=460800 +gen4iod.menu.baud.512000.windows=512000 +gen4iod.menu.baud.512000.upload.speed=512000 +gen4iod.menu.baud.921600=921600 +gen4iod.menu.baud.921600.upload.speed=921600 + +############################################################## +oak.name=Digistump Oak +oak.build.board=ESP8266_OAK +oak.build.variant=oak +oak.upload.maximum_size=1040368 +oak.upload.tool=esptool +oak.upload.maximum_data_size=81920 +oak.upload.wait_for_upload_port=true +oak.upload.erase_cmd= +oak.serial.disableDTR=true +oak.serial.disableRTS=true +oak.build.mcu=esp8266 +oak.build.core=esp8266 +oak.build.spiffs_pagesize=256 +oak.build.debug_port= +oak.build.debug_level= +oak.menu.xtal.80=80 MHz +oak.menu.xtal.80.build.f_cpu=80000000L +oak.menu.xtal.160=160 MHz +oak.menu.xtal.160.build.f_cpu=160000000L +oak.menu.vt.flash=Flash +oak.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +oak.menu.vt.heap=Heap +oak.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +oak.menu.vt.iram=IRAM +oak.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +oak.menu.exception.disabled=Disabled +oak.menu.exception.disabled.build.exception_flags=-fno-exceptions +oak.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +oak.menu.exception.enabled=Enabled +oak.menu.exception.enabled.build.exception_flags=-fexceptions +oak.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +oak.upload.resetmethod=none +oak.build.flash_mode=dio +oak.build.flash_flags=-DFLASHMODE_DIO +oak.build.flash_freq=40 +oak.menu.eesz.4M=4M (no SPIFFS) +oak.menu.eesz.4M.build.flash_size=4M +oak.menu.eesz.4M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +oak.menu.eesz.4M.build.spiffs_pagesize=256 +oak.menu.eesz.4M.upload.maximum_size=1044464 +oak.menu.eesz.4M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M1M=4M (1M SPIFFS) +oak.menu.eesz.4M1M.build.flash_size=4M +oak.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +oak.menu.eesz.4M1M.build.spiffs_pagesize=256 +oak.menu.eesz.4M1M.upload.maximum_size=1044464 +oak.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M1M.build.spiffs_start=0x300000 +oak.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +oak.menu.eesz.4M1M.build.spiffs_blocksize=8192 +oak.menu.eesz.4M2M=4M (2M SPIFFS) +oak.menu.eesz.4M2M.build.flash_size=4M +oak.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +oak.menu.eesz.4M2M.build.spiffs_pagesize=256 +oak.menu.eesz.4M2M.upload.maximum_size=1044464 +oak.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M2M.build.spiffs_start=0x200000 +oak.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +oak.menu.eesz.4M2M.build.spiffs_blocksize=8192 +oak.menu.eesz.4M3M=4M (3M SPIFFS) +oak.menu.eesz.4M3M.build.flash_size=4M +oak.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +oak.menu.eesz.4M3M.build.spiffs_pagesize=256 +oak.menu.eesz.4M3M.upload.maximum_size=1044464 +oak.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M3M.build.spiffs_start=0x100000 +oak.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +oak.menu.eesz.4M3M.build.spiffs_blocksize=8192 +oak.menu.ip.lm2f=v2 Lower Memory +oak.menu.ip.lm2f.build.lwip_include=lwip2/include +oak.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +oak.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +oak.menu.ip.hb2f=v2 Higher Bandwidth +oak.menu.ip.hb2f.build.lwip_include=lwip2/include +oak.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +oak.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +oak.menu.ip.lm2n=v2 Lower Memory (no features) +oak.menu.ip.lm2n.build.lwip_include=lwip2/include +oak.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +oak.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +oak.menu.ip.hb2n=v2 Higher Bandwidth (no features) +oak.menu.ip.hb2n.build.lwip_include=lwip2/include +oak.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +oak.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +oak.menu.ip.lm6f=v2 IPv6 Lower Memory +oak.menu.ip.lm6f.build.lwip_include=lwip2/include +oak.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +oak.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +oak.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +oak.menu.ip.hb6f.build.lwip_include=lwip2/include +oak.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +oak.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +oak.menu.ip.hb1=v1.4 Higher Bandwidth +oak.menu.ip.hb1.build.lwip_lib=-llwip_gcc +oak.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +oak.menu.ip.src=v1.4 Compile from source +oak.menu.ip.src.build.lwip_lib=-llwip_src +oak.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +oak.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +oak.menu.dbg.Disabled=Disabled +oak.menu.dbg.Disabled.build.debug_port= +oak.menu.dbg.Serial=Serial +oak.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +oak.menu.dbg.Serial1=Serial1 +oak.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +oak.menu.lvl.None____=None +oak.menu.lvl.None____.build.debug_level= +oak.menu.lvl.SSL=SSL +oak.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +oak.menu.lvl.TLS_MEM=TLS_MEM +oak.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +oak.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +oak.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.HTTP_SERVER=HTTP_SERVER +oak.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +oak.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +oak.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +oak.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +oak.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +oak.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.CORE=CORE +oak.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +oak.menu.lvl.WIFI=WIFI +oak.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +oak.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +oak.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +oak.menu.lvl.UPDATER=UPDATER +oak.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +oak.menu.lvl.OTA=OTA +oak.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +oak.menu.lvl.OOM=OOM +oak.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +oak.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +oak.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +oak.menu.wipe.none=Only Sketch +oak.menu.wipe.none.upload.erase_cmd= +oak.menu.wipe.sdk=Sketch + WiFi Settings +oak.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +oak.menu.wipe.all=All Flash Contents +oak.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +oak.menu.baud.921600=921600 +oak.menu.baud.921600.upload.speed=921600 +oak.menu.baud.9600=9600 +oak.menu.baud.9600.upload.speed=9600 +oak.menu.baud.57600=57600 +oak.menu.baud.57600.upload.speed=57600 +oak.menu.baud.115200=115200 +oak.menu.baud.115200.upload.speed=115200 +oak.menu.baud.230400.linux=230400 +oak.menu.baud.230400.macosx=230400 +oak.menu.baud.230400.upload.speed=230400 +oak.menu.baud.256000.windows=256000 +oak.menu.baud.256000.upload.speed=256000 +oak.menu.baud.460800.linux=460800 +oak.menu.baud.460800.macosx=460800 +oak.menu.baud.460800.upload.speed=460800 +oak.menu.baud.512000.windows=512000 +oak.menu.baud.512000.upload.speed=512000 + +############################################################## +wifiduino.name=WiFiduino +wifiduino.build.board=WIFIDUINO_ESP8266 +wifiduino.build.variant=wifiduino +wifiduino.upload.tool=esptool +wifiduino.upload.maximum_data_size=81920 +wifiduino.upload.wait_for_upload_port=true +wifiduino.upload.erase_cmd= +wifiduino.serial.disableDTR=true +wifiduino.serial.disableRTS=true +wifiduino.build.mcu=esp8266 +wifiduino.build.core=esp8266 +wifiduino.build.spiffs_pagesize=256 +wifiduino.build.debug_port= +wifiduino.build.debug_level= +wifiduino.menu.xtal.80=80 MHz +wifiduino.menu.xtal.80.build.f_cpu=80000000L +wifiduino.menu.xtal.160=160 MHz +wifiduino.menu.xtal.160.build.f_cpu=160000000L +wifiduino.menu.vt.flash=Flash +wifiduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wifiduino.menu.vt.heap=Heap +wifiduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wifiduino.menu.vt.iram=IRAM +wifiduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wifiduino.menu.exception.disabled=Disabled +wifiduino.menu.exception.disabled.build.exception_flags=-fno-exceptions +wifiduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wifiduino.menu.exception.enabled=Enabled +wifiduino.menu.exception.enabled.build.exception_flags=-fexceptions +wifiduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wifiduino.upload.resetmethod=nodemcu +wifiduino.build.flash_mode=dio +wifiduino.build.flash_flags=-DFLASHMODE_DIO +wifiduino.build.flash_freq=40 +wifiduino.menu.eesz.4M=4M (no SPIFFS) +wifiduino.menu.eesz.4M.build.flash_size=4M +wifiduino.menu.eesz.4M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +wifiduino.menu.eesz.4M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M1M=4M (1M SPIFFS) +wifiduino.menu.eesz.4M1M.build.flash_size=4M +wifiduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +wifiduino.menu.eesz.4M1M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M1M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M1M.build.spiffs_start=0x300000 +wifiduino.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +wifiduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 +wifiduino.menu.eesz.4M2M=4M (2M SPIFFS) +wifiduino.menu.eesz.4M2M.build.flash_size=4M +wifiduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +wifiduino.menu.eesz.4M2M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M2M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M2M.build.spiffs_start=0x200000 +wifiduino.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +wifiduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 +wifiduino.menu.eesz.4M3M=4M (3M SPIFFS) +wifiduino.menu.eesz.4M3M.build.flash_size=4M +wifiduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +wifiduino.menu.eesz.4M3M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M3M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M3M.build.spiffs_start=0x100000 +wifiduino.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +wifiduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 +wifiduino.menu.ip.lm2f=v2 Lower Memory +wifiduino.menu.ip.lm2f.build.lwip_include=lwip2/include +wifiduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wifiduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifiduino.menu.ip.hb2f=v2 Higher Bandwidth +wifiduino.menu.ip.hb2f.build.lwip_include=lwip2/include +wifiduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wifiduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifiduino.menu.ip.lm2n=v2 Lower Memory (no features) +wifiduino.menu.ip.lm2n.build.lwip_include=lwip2/include +wifiduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wifiduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifiduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wifiduino.menu.ip.hb2n.build.lwip_include=lwip2/include +wifiduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wifiduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifiduino.menu.ip.lm6f=v2 IPv6 Lower Memory +wifiduino.menu.ip.lm6f.build.lwip_include=lwip2/include +wifiduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wifiduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifiduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wifiduino.menu.ip.hb6f.build.lwip_include=lwip2/include +wifiduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wifiduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifiduino.menu.ip.hb1=v1.4 Higher Bandwidth +wifiduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wifiduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wifiduino.menu.ip.src=v1.4 Compile from source +wifiduino.menu.ip.src.build.lwip_lib=-llwip_src +wifiduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wifiduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wifiduino.menu.dbg.Disabled=Disabled +wifiduino.menu.dbg.Disabled.build.debug_port= +wifiduino.menu.dbg.Serial=Serial +wifiduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wifiduino.menu.dbg.Serial1=Serial1 +wifiduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wifiduino.menu.lvl.None____=None +wifiduino.menu.lvl.None____.build.debug_level= +wifiduino.menu.lvl.SSL=SSL +wifiduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wifiduino.menu.lvl.TLS_MEM=TLS_MEM +wifiduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wifiduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wifiduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.HTTP_SERVER=HTTP_SERVER +wifiduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wifiduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wifiduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wifiduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wifiduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.CORE=CORE +wifiduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wifiduino.menu.lvl.WIFI=WIFI +wifiduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wifiduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wifiduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wifiduino.menu.lvl.UPDATER=UPDATER +wifiduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wifiduino.menu.lvl.OTA=OTA +wifiduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wifiduino.menu.lvl.OOM=OOM +wifiduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wifiduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wifiduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wifiduino.menu.wipe.none=Only Sketch +wifiduino.menu.wipe.none.upload.erase_cmd= +wifiduino.menu.wipe.sdk=Sketch + WiFi Settings +wifiduino.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +wifiduino.menu.wipe.all=All Flash Contents +wifiduino.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +wifiduino.menu.baud.921600=921600 +wifiduino.menu.baud.921600.upload.speed=921600 +wifiduino.menu.baud.9600=9600 +wifiduino.menu.baud.9600.upload.speed=9600 +wifiduino.menu.baud.57600=57600 +wifiduino.menu.baud.57600.upload.speed=57600 +wifiduino.menu.baud.115200=115200 +wifiduino.menu.baud.115200.upload.speed=115200 +wifiduino.menu.baud.230400.linux=230400 +wifiduino.menu.baud.230400.macosx=230400 +wifiduino.menu.baud.230400.upload.speed=230400 +wifiduino.menu.baud.256000.windows=256000 +wifiduino.menu.baud.256000.upload.speed=256000 +wifiduino.menu.baud.460800.linux=460800 +wifiduino.menu.baud.460800.macosx=460800 +wifiduino.menu.baud.460800.upload.speed=460800 +wifiduino.menu.baud.512000.windows=512000 +wifiduino.menu.baud.512000.upload.speed=512000 + +############################################################## +wifi_slot.name=Amperka WiFi Slot +wifi_slot.build.board=AMPERKA_WIFI_SLOT +wifi_slot.build.variant=wifi_slot +wifi_slot.upload.tool=esptool +wifi_slot.upload.maximum_data_size=81920 +wifi_slot.upload.wait_for_upload_port=true +wifi_slot.upload.erase_cmd= +wifi_slot.serial.disableDTR=true +wifi_slot.serial.disableRTS=true +wifi_slot.build.mcu=esp8266 +wifi_slot.build.core=esp8266 +wifi_slot.build.spiffs_pagesize=256 +wifi_slot.build.debug_port= +wifi_slot.build.debug_level= +wifi_slot.menu.xtal.80=80 MHz +wifi_slot.menu.xtal.80.build.f_cpu=80000000L +wifi_slot.menu.xtal.160=160 MHz +wifi_slot.menu.xtal.160.build.f_cpu=160000000L +wifi_slot.menu.vt.flash=Flash +wifi_slot.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wifi_slot.menu.vt.heap=Heap +wifi_slot.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wifi_slot.menu.vt.iram=IRAM +wifi_slot.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wifi_slot.menu.exception.disabled=Disabled +wifi_slot.menu.exception.disabled.build.exception_flags=-fno-exceptions +wifi_slot.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wifi_slot.menu.exception.enabled=Enabled +wifi_slot.menu.exception.enabled.build.exception_flags=-fexceptions +wifi_slot.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wifi_slot.upload.resetmethod=nodemcu +wifi_slot.menu.FlashFreq.40=40MHz +wifi_slot.menu.FlashFreq.40.build.flash_freq=40 +wifi_slot.menu.FlashFreq.80=80MHz +wifi_slot.menu.FlashFreq.80.build.flash_freq=80 +wifi_slot.menu.FlashMode.dout=DOUT (compatible) +wifi_slot.menu.FlashMode.dout.build.flash_mode=dout +wifi_slot.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT +wifi_slot.menu.FlashMode.dio=DIO +wifi_slot.menu.FlashMode.dio.build.flash_mode=dio +wifi_slot.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO +wifi_slot.menu.FlashMode.qout=QOUT +wifi_slot.menu.FlashMode.qout.build.flash_mode=qout +wifi_slot.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT +wifi_slot.menu.FlashMode.qio=QIO (fast) +wifi_slot.menu.FlashMode.qio.build.flash_mode=qio +wifi_slot.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO +wifi_slot.menu.eesz.1M=1M (no SPIFFS) +wifi_slot.menu.eesz.1M.build.flash_size=1M +wifi_slot.menu.eesz.1M.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +wifi_slot.menu.eesz.1M.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M.upload.maximum_size=1023984 +wifi_slot.menu.eesz.1M.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M64=1M (64K SPIFFS) +wifi_slot.menu.eesz.1M64.build.flash_size=1M +wifi_slot.menu.eesz.1M64.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +wifi_slot.menu.eesz.1M64.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M64.upload.maximum_size=958448 +wifi_slot.menu.eesz.1M64.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M64.build.spiffs_start=0xEB000 +wifi_slot.menu.eesz.1M64.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M64.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M128=1M (128K SPIFFS) +wifi_slot.menu.eesz.1M128.build.flash_size=1M +wifi_slot.menu.eesz.1M128.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +wifi_slot.menu.eesz.1M128.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M128.upload.maximum_size=892912 +wifi_slot.menu.eesz.1M128.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M128.build.spiffs_start=0xDB000 +wifi_slot.menu.eesz.1M128.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M128.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M144=1M (144K SPIFFS) +wifi_slot.menu.eesz.1M144.build.flash_size=1M +wifi_slot.menu.eesz.1M144.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +wifi_slot.menu.eesz.1M144.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M144.upload.maximum_size=876528 +wifi_slot.menu.eesz.1M144.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M144.build.spiffs_start=0xD7000 +wifi_slot.menu.eesz.1M144.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M144.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M160=1M (160K SPIFFS) +wifi_slot.menu.eesz.1M160.build.flash_size=1M +wifi_slot.menu.eesz.1M160.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +wifi_slot.menu.eesz.1M160.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M160.upload.maximum_size=860144 +wifi_slot.menu.eesz.1M160.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M160.build.spiffs_start=0xD3000 +wifi_slot.menu.eesz.1M160.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M160.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M192=1M (192K SPIFFS) +wifi_slot.menu.eesz.1M192.build.flash_size=1M +wifi_slot.menu.eesz.1M192.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +wifi_slot.menu.eesz.1M192.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M192.upload.maximum_size=827376 +wifi_slot.menu.eesz.1M192.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M192.build.spiffs_start=0xCB000 +wifi_slot.menu.eesz.1M192.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M192.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M256=1M (256K SPIFFS) +wifi_slot.menu.eesz.1M256.build.flash_size=1M +wifi_slot.menu.eesz.1M256.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +wifi_slot.menu.eesz.1M256.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M256.upload.maximum_size=761840 +wifi_slot.menu.eesz.1M256.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M256.build.spiffs_start=0xBB000 +wifi_slot.menu.eesz.1M256.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M256.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M512=1M (512K SPIFFS) +wifi_slot.menu.eesz.1M512.build.flash_size=1M +wifi_slot.menu.eesz.1M512.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +wifi_slot.menu.eesz.1M512.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M512.upload.maximum_size=499696 +wifi_slot.menu.eesz.1M512.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M512.build.spiffs_start=0x7B000 +wifi_slot.menu.eesz.1M512.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M512.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.2M=2M (no SPIFFS) +wifi_slot.menu.eesz.2M.build.flash_size=2M +wifi_slot.menu.eesz.2M.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld +wifi_slot.menu.eesz.2M.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M128=2M (128K SPIFFS) +wifi_slot.menu.eesz.2M128.build.flash_size=2M +wifi_slot.menu.eesz.2M128.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld +wifi_slot.menu.eesz.2M128.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M128.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M128.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M128.build.spiffs_start=0x1E0000 +wifi_slot.menu.eesz.2M128.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M128.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.2M256=2M (256K SPIFFS) +wifi_slot.menu.eesz.2M256.build.flash_size=2M +wifi_slot.menu.eesz.2M256.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld +wifi_slot.menu.eesz.2M256.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M256.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M256.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M256.build.spiffs_start=0x1C0000 +wifi_slot.menu.eesz.2M256.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M256.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.2M512=2M (512K SPIFFS) +wifi_slot.menu.eesz.2M512.build.flash_size=2M +wifi_slot.menu.eesz.2M512.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld +wifi_slot.menu.eesz.2M512.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M512.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M512.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M512.build.spiffs_start=0x180000 +wifi_slot.menu.eesz.2M512.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M512.build.spiffs_blocksize=8192 +wifi_slot.menu.eesz.2M1M=2M (1M SPIFFS) +wifi_slot.menu.eesz.2M1M.build.flash_size=2M +wifi_slot.menu.eesz.2M1M.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld +wifi_slot.menu.eesz.2M1M.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M1M.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M1M.build.spiffs_start=0x100000 +wifi_slot.menu.eesz.2M1M.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M1M.build.spiffs_blocksize=8192 +wifi_slot.menu.ip.lm2f=v2 Lower Memory +wifi_slot.menu.ip.lm2f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wifi_slot.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifi_slot.menu.ip.hb2f=v2 Higher Bandwidth +wifi_slot.menu.ip.hb2f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wifi_slot.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifi_slot.menu.ip.lm2n=v2 Lower Memory (no features) +wifi_slot.menu.ip.lm2n.build.lwip_include=lwip2/include +wifi_slot.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wifi_slot.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifi_slot.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wifi_slot.menu.ip.hb2n.build.lwip_include=lwip2/include +wifi_slot.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wifi_slot.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifi_slot.menu.ip.lm6f=v2 IPv6 Lower Memory +wifi_slot.menu.ip.lm6f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wifi_slot.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifi_slot.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wifi_slot.menu.ip.hb6f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wifi_slot.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifi_slot.menu.ip.hb1=v1.4 Higher Bandwidth +wifi_slot.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wifi_slot.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wifi_slot.menu.ip.src=v1.4 Compile from source +wifi_slot.menu.ip.src.build.lwip_lib=-llwip_src +wifi_slot.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wifi_slot.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wifi_slot.menu.dbg.Disabled=Disabled +wifi_slot.menu.dbg.Disabled.build.debug_port= +wifi_slot.menu.dbg.Serial=Serial +wifi_slot.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wifi_slot.menu.dbg.Serial1=Serial1 +wifi_slot.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wifi_slot.menu.lvl.None____=None +wifi_slot.menu.lvl.None____.build.debug_level= +wifi_slot.menu.lvl.SSL=SSL +wifi_slot.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wifi_slot.menu.lvl.TLS_MEM=TLS_MEM +wifi_slot.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wifi_slot.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wifi_slot.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.HTTP_SERVER=HTTP_SERVER +wifi_slot.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wifi_slot.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wifi_slot.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wifi_slot.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wifi_slot.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.CORE=CORE +wifi_slot.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wifi_slot.menu.lvl.WIFI=WIFI +wifi_slot.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wifi_slot.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wifi_slot.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wifi_slot.menu.lvl.UPDATER=UPDATER +wifi_slot.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wifi_slot.menu.lvl.OTA=OTA +wifi_slot.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wifi_slot.menu.lvl.OOM=OOM +wifi_slot.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wifi_slot.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wifi_slot.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wifi_slot.menu.wipe.none=Only Sketch +wifi_slot.menu.wipe.none.upload.erase_cmd= +wifi_slot.menu.wipe.sdk=Sketch + WiFi Settings +wifi_slot.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +wifi_slot.menu.wipe.all=All Flash Contents +wifi_slot.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +wifi_slot.menu.baud.115200=115200 +wifi_slot.menu.baud.115200.upload.speed=115200 +wifi_slot.menu.baud.9600=9600 +wifi_slot.menu.baud.9600.upload.speed=9600 +wifi_slot.menu.baud.57600=57600 +wifi_slot.menu.baud.57600.upload.speed=57600 +wifi_slot.menu.baud.230400.linux=230400 +wifi_slot.menu.baud.230400.macosx=230400 +wifi_slot.menu.baud.230400.upload.speed=230400 +wifi_slot.menu.baud.256000.windows=256000 +wifi_slot.menu.baud.256000.upload.speed=256000 +wifi_slot.menu.baud.460800.linux=460800 +wifi_slot.menu.baud.460800.macosx=460800 +wifi_slot.menu.baud.460800.upload.speed=460800 +wifi_slot.menu.baud.512000.windows=512000 +wifi_slot.menu.baud.512000.upload.speed=512000 +wifi_slot.menu.baud.921600=921600 +wifi_slot.menu.baud.921600.upload.speed=921600 + +############################################################## +wiolink.name=Seeed Wio Link +wiolink.build.board=ESP8266_WIO_LINK +wiolink.build.variant=wiolink +wiolink.upload.tool=esptool +wiolink.upload.maximum_data_size=81920 +wiolink.upload.wait_for_upload_port=true +wiolink.upload.erase_cmd= +wiolink.serial.disableDTR=true +wiolink.serial.disableRTS=true +wiolink.build.mcu=esp8266 +wiolink.build.core=esp8266 +wiolink.build.spiffs_pagesize=256 +wiolink.build.debug_port= +wiolink.build.debug_level= +wiolink.menu.xtal.80=80 MHz +wiolink.menu.xtal.80.build.f_cpu=80000000L +wiolink.menu.xtal.160=160 MHz +wiolink.menu.xtal.160.build.f_cpu=160000000L +wiolink.menu.vt.flash=Flash +wiolink.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wiolink.menu.vt.heap=Heap +wiolink.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wiolink.menu.vt.iram=IRAM +wiolink.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wiolink.menu.exception.disabled=Disabled +wiolink.menu.exception.disabled.build.exception_flags=-fno-exceptions +wiolink.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wiolink.menu.exception.enabled=Enabled +wiolink.menu.exception.enabled.build.exception_flags=-fexceptions +wiolink.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wiolink.upload.resetmethod=nodemcu +wiolink.build.flash_mode=qio +wiolink.build.flash_flags=-DFLASHMODE_QIO +wiolink.build.flash_freq=40 +wiolink.menu.eesz.4M=4M (no SPIFFS) +wiolink.menu.eesz.4M.build.flash_size=4M +wiolink.menu.eesz.4M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +wiolink.menu.eesz.4M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M1M=4M (1M SPIFFS) +wiolink.menu.eesz.4M1M.build.flash_size=4M +wiolink.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +wiolink.menu.eesz.4M1M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M1M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M1M.build.spiffs_start=0x300000 +wiolink.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +wiolink.menu.eesz.4M1M.build.spiffs_blocksize=8192 +wiolink.menu.eesz.4M2M=4M (2M SPIFFS) +wiolink.menu.eesz.4M2M.build.flash_size=4M +wiolink.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +wiolink.menu.eesz.4M2M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M2M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M2M.build.spiffs_start=0x200000 +wiolink.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +wiolink.menu.eesz.4M2M.build.spiffs_blocksize=8192 +wiolink.menu.eesz.4M3M=4M (3M SPIFFS) +wiolink.menu.eesz.4M3M.build.flash_size=4M +wiolink.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +wiolink.menu.eesz.4M3M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M3M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M3M.build.spiffs_start=0x100000 +wiolink.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +wiolink.menu.eesz.4M3M.build.spiffs_blocksize=8192 +wiolink.menu.ip.lm2f=v2 Lower Memory +wiolink.menu.ip.lm2f.build.lwip_include=lwip2/include +wiolink.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wiolink.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wiolink.menu.ip.hb2f=v2 Higher Bandwidth +wiolink.menu.ip.hb2f.build.lwip_include=lwip2/include +wiolink.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wiolink.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wiolink.menu.ip.lm2n=v2 Lower Memory (no features) +wiolink.menu.ip.lm2n.build.lwip_include=lwip2/include +wiolink.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wiolink.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wiolink.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wiolink.menu.ip.hb2n.build.lwip_include=lwip2/include +wiolink.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wiolink.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wiolink.menu.ip.lm6f=v2 IPv6 Lower Memory +wiolink.menu.ip.lm6f.build.lwip_include=lwip2/include +wiolink.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wiolink.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wiolink.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wiolink.menu.ip.hb6f.build.lwip_include=lwip2/include +wiolink.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wiolink.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wiolink.menu.ip.hb1=v1.4 Higher Bandwidth +wiolink.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wiolink.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wiolink.menu.ip.src=v1.4 Compile from source +wiolink.menu.ip.src.build.lwip_lib=-llwip_src +wiolink.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wiolink.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wiolink.menu.dbg.Disabled=Disabled +wiolink.menu.dbg.Disabled.build.debug_port= +wiolink.menu.dbg.Serial=Serial +wiolink.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wiolink.menu.dbg.Serial1=Serial1 +wiolink.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wiolink.menu.lvl.None____=None +wiolink.menu.lvl.None____.build.debug_level= +wiolink.menu.lvl.SSL=SSL +wiolink.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wiolink.menu.lvl.TLS_MEM=TLS_MEM +wiolink.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wiolink.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wiolink.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.HTTP_SERVER=HTTP_SERVER +wiolink.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wiolink.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wiolink.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wiolink.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wiolink.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wiolink.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.CORE=CORE +wiolink.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wiolink.menu.lvl.WIFI=WIFI +wiolink.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wiolink.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wiolink.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wiolink.menu.lvl.UPDATER=UPDATER +wiolink.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wiolink.menu.lvl.OTA=OTA +wiolink.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wiolink.menu.lvl.OOM=OOM +wiolink.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +wiolink.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wiolink.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wiolink.menu.wipe.none=Only Sketch +wiolink.menu.wipe.none.upload.erase_cmd= +wiolink.menu.wipe.sdk=Sketch + WiFi Settings +wiolink.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +wiolink.menu.wipe.all=All Flash Contents +wiolink.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +wiolink.menu.baud.115200=115200 +wiolink.menu.baud.115200.upload.speed=115200 +wiolink.menu.baud.9600=9600 +wiolink.menu.baud.9600.upload.speed=9600 +wiolink.menu.baud.57600=57600 +wiolink.menu.baud.57600.upload.speed=57600 +wiolink.menu.baud.230400.linux=230400 +wiolink.menu.baud.230400.macosx=230400 +wiolink.menu.baud.230400.upload.speed=230400 +wiolink.menu.baud.256000.windows=256000 +wiolink.menu.baud.256000.upload.speed=256000 +wiolink.menu.baud.460800.linux=460800 +wiolink.menu.baud.460800.macosx=460800 +wiolink.menu.baud.460800.upload.speed=460800 +wiolink.menu.baud.512000.windows=512000 +wiolink.menu.baud.512000.upload.speed=512000 +wiolink.menu.baud.921600=921600 +wiolink.menu.baud.921600.upload.speed=921600 + +############################################################## +espectro.name=ESPectro Core +espectro.build.board=ESP8266_ESPECTRO_CORE +espectro.build.variant=espectro +espectro.upload.tool=esptool +espectro.upload.maximum_data_size=81920 +espectro.upload.wait_for_upload_port=true +espectro.upload.erase_cmd= +espectro.serial.disableDTR=true +espectro.serial.disableRTS=true +espectro.build.mcu=esp8266 +espectro.build.core=esp8266 +espectro.build.spiffs_pagesize=256 +espectro.build.debug_port= +espectro.build.debug_level= +espectro.menu.xtal.80=80 MHz +espectro.menu.xtal.80.build.f_cpu=80000000L +espectro.menu.xtal.160=160 MHz +espectro.menu.xtal.160.build.f_cpu=160000000L +espectro.menu.vt.flash=Flash +espectro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espectro.menu.vt.heap=Heap +espectro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espectro.menu.vt.iram=IRAM +espectro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espectro.menu.exception.disabled=Disabled +espectro.menu.exception.disabled.build.exception_flags=-fno-exceptions +espectro.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espectro.menu.exception.enabled=Enabled +espectro.menu.exception.enabled.build.exception_flags=-fexceptions +espectro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espectro.upload.resetmethod=nodemcu +espectro.build.flash_mode=dio +espectro.build.flash_flags=-DFLASHMODE_DIO +espectro.build.flash_freq=40 +espectro.menu.eesz.4M=4M (no SPIFFS) +espectro.menu.eesz.4M.build.flash_size=4M +espectro.menu.eesz.4M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espectro.menu.eesz.4M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M.upload.maximum_size=1044464 +espectro.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M1M=4M (1M SPIFFS) +espectro.menu.eesz.4M1M.build.flash_size=4M +espectro.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espectro.menu.eesz.4M1M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M1M.upload.maximum_size=1044464 +espectro.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M1M.build.spiffs_start=0x300000 +espectro.menu.eesz.4M1M.build.spiffs_end=0x3FB000 +espectro.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espectro.menu.eesz.4M2M=4M (2M SPIFFS) +espectro.menu.eesz.4M2M.build.flash_size=4M +espectro.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espectro.menu.eesz.4M2M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M2M.upload.maximum_size=1044464 +espectro.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M2M.build.spiffs_start=0x200000 +espectro.menu.eesz.4M2M.build.spiffs_end=0x3FB000 +espectro.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espectro.menu.eesz.4M3M=4M (3M SPIFFS) +espectro.menu.eesz.4M3M.build.flash_size=4M +espectro.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espectro.menu.eesz.4M3M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M3M.upload.maximum_size=1044464 +espectro.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M3M.build.spiffs_start=0x100000 +espectro.menu.eesz.4M3M.build.spiffs_end=0x3FB000 +espectro.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espectro.menu.ip.lm2f=v2 Lower Memory +espectro.menu.ip.lm2f.build.lwip_include=lwip2/include +espectro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espectro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espectro.menu.ip.hb2f=v2 Higher Bandwidth +espectro.menu.ip.hb2f.build.lwip_include=lwip2/include +espectro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espectro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espectro.menu.ip.lm2n=v2 Lower Memory (no features) +espectro.menu.ip.lm2n.build.lwip_include=lwip2/include +espectro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espectro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espectro.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espectro.menu.ip.hb2n.build.lwip_include=lwip2/include +espectro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espectro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espectro.menu.ip.lm6f=v2 IPv6 Lower Memory +espectro.menu.ip.lm6f.build.lwip_include=lwip2/include +espectro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espectro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espectro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espectro.menu.ip.hb6f.build.lwip_include=lwip2/include +espectro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espectro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espectro.menu.ip.hb1=v1.4 Higher Bandwidth +espectro.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espectro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espectro.menu.ip.src=v1.4 Compile from source +espectro.menu.ip.src.build.lwip_lib=-llwip_src +espectro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espectro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espectro.menu.dbg.Disabled=Disabled +espectro.menu.dbg.Disabled.build.debug_port= +espectro.menu.dbg.Serial=Serial +espectro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espectro.menu.dbg.Serial1=Serial1 +espectro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espectro.menu.lvl.None____=None +espectro.menu.lvl.None____.build.debug_level= +espectro.menu.lvl.SSL=SSL +espectro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espectro.menu.lvl.TLS_MEM=TLS_MEM +espectro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espectro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espectro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.HTTP_SERVER=HTTP_SERVER +espectro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espectro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espectro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espectro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espectro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espectro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.CORE=CORE +espectro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espectro.menu.lvl.WIFI=WIFI +espectro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espectro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espectro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espectro.menu.lvl.UPDATER=UPDATER +espectro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espectro.menu.lvl.OTA=OTA +espectro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espectro.menu.lvl.OOM=OOM +espectro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM +espectro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espectro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espectro.menu.wipe.none=Only Sketch +espectro.menu.wipe.none.upload.erase_cmd= +espectro.menu.wipe.sdk=Sketch + WiFi Settings +espectro.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 +espectro.menu.wipe.all=All Flash Contents +espectro.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" +espectro.menu.baud.115200=115200 +espectro.menu.baud.115200.upload.speed=115200 +espectro.menu.baud.9600=9600 +espectro.menu.baud.9600.upload.speed=9600 +espectro.menu.baud.57600=57600 +espectro.menu.baud.57600.upload.speed=57600 +espectro.menu.baud.230400.linux=230400 +espectro.menu.baud.230400.macosx=230400 +espectro.menu.baud.230400.upload.speed=230400 +espectro.menu.baud.256000.windows=256000 +espectro.menu.baud.256000.upload.speed=256000 +espectro.menu.baud.460800.linux=460800 +espectro.menu.baud.460800.macosx=460800 +espectro.menu.baud.460800.upload.speed=460800 +espectro.menu.baud.512000.windows=512000 +espectro.menu.baud.512000.upload.speed=512000 +espectro.menu.baud.921600=921600 +espectro.menu.baud.921600.upload.speed=921600 From dbacfdd9b9d5dc5ac07c879d18c2151eae53b4ff Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sun, 17 Feb 2019 12:47:21 +0100 Subject: [PATCH 1020/2222] Add files via upload --- arduino/version 2.5.0/platform.txt | 155 +++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 arduino/version 2.5.0/platform.txt diff --git a/arduino/version 2.5.0/platform.txt b/arduino/version 2.5.0/platform.txt new file mode 100644 index 000000000..caa408904 --- /dev/null +++ b/arduino/version 2.5.0/platform.txt @@ -0,0 +1,155 @@ + +# ESP8266 platform +# ------------------------------ + +# For more info: +# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification + +name=ESP8266 Boards (2.5.0) +version=2.5.0 + +runtime.tools.xtensa-lx106-elf-gcc.path={runtime.platform.path}/tools/xtensa-lx106-elf +runtime.tools.esptool.path={runtime.platform.path}/tools/esptool +runtime.tools.signing={runtime.platform.path}/tools/signing.py + +compiler.warning_flags=-w +compiler.warning_flags.none=-w +compiler.warning_flags.default= +compiler.warning_flags.more=-Wall +compiler.warning_flags.all=-Wall -Wextra + +build.lwip_lib=-llwip_gcc +build.lwip_include=lwip/include +build.lwip_flags=-DLWIP_OPEN_SRC + +build.vtable_flags=-DVTABLES_IN_FLASH + +build.exception_flags=-fno-exceptions +build.stdcpp_lib=-lstdc++ + +#build.float=-u _printf_float -u _scanf_float +build.float= +build.led= + +compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/ +compiler.sdk.path={runtime.platform.path}/tools/sdk +compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf +compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" + +compiler.c.cmd=xtensa-lx106-elf-gcc +compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} + +compiler.S.cmd=xtensa-lx106-elf-gcc +compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls + +compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read + +compiler.c.elf.cmd=xtensa-lx106-elf-gcc +compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc + +compiler.cpp.cmd=xtensa-lx106-elf-g++ +compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections {build.exception_flags} + +compiler.as.cmd=xtensa-lx106-elf-as + +compiler.ar.cmd=xtensa-lx106-elf-ar +compiler.ar.flags=cru + +compiler.elf2hex.cmd=esptool +compiler.elf2hex.flags= + +compiler.size.cmd=xtensa-lx106-elf-size + +compiler.esptool.cmd=esptool +compiler.esptool.cmd.windows=esptool.exe + +# This can be overriden in boards.txt +build.extra_flags=-DESP8266 + +# These can be overridden in platform.local.txt +compiler.c.extra_flags= +compiler.c.elf.extra_flags= +compiler.S.extra_flags= +compiler.cpp.extra_flags= +compiler.ar.extra_flags= +compiler.objcopy.eep.extra_flags= +compiler.elf2hex.extra_flags= + +## generate file with git version number +## needs bash, git, and echo +recipe.hooks.core.prebuild.1.pattern=python "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h" +recipe.hooks.core.prebuild.2.pattern=bash -c "mkdir -p {build.path}/core && echo \#define ARDUINO_ESP8266_GIT_VER 0x`git --git-dir {runtime.platform.path}/.git rev-parse --short=8 HEAD 2>/dev/null || echo ffffffff` >{build.path}/core/core_version.h" +recipe.hooks.core.prebuild.3.pattern=bash -c "mkdir -p {build.path}/core && echo \#define ARDUINO_ESP8266_GIT_DESC `cd "{runtime.platform.path}"; git describe --tags 2>/dev/null || echo unix-{version}` >>{build.path}/core/core_version.h" + +## windows-compatible version without git +recipe.hooks.core.prebuild.1.pattern.windows=cmd.exe /c rem cannot sign on windows +recipe.hooks.core.prebuild.2.pattern.windows=cmd.exe /c mkdir {build.path}\core & (echo #define ARDUINO_ESP8266_GIT_VER 0x00000000 & echo #define ARDUINO_ESP8266_GIT_DESC win-{version} ) > {build.path}\core\core_version.h +recipe.hooks.core.prebuild.3.pattern.windows=cmd.exe /c if exist {build.source.path}\public.key echo #error Cannot automatically build signed binaries on Windows > {build.path}\core\Updater_Signing.h + +## Build the app.ld linker file +recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld" + +## Compile c files +recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Compile c++ files +recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Compile S files +recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Create archives +recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" + +## Combine gc-sections, archives, and objects +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" + +## Create eeprom +recipe.objcopy.eep.pattern= + +## Create hex +#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" + +recipe.objcopy.hex.1.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec +recipe.objcopy.hex.2.pattern=python "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed" + +# No signing on Windows +recipe.objcopy.hex.1.pattern.windows="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec +recipe.objcopy.hex.2.pattern.windows= + +## Save hex +recipe.output.tmp_file={build.project_name}.bin +recipe.output.save_file={build.project_name}.{build.variant}.bin + +## Compute size +recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" +recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).* +recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* +#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* + +# ------------------------------ + +tools.esptool.cmd=esptool +tools.esptool.cmd.windows=esptool.exe +tools.esptool.path={runtime.tools.esptool.path} +tools.esptool.network_cmd=python +tools.esptool.network_cmd.windows=python.exe + +tools.esptool.upload.protocol=esp +tools.esptool.upload.params.verbose=-vv +tools.esptool.upload.params.quiet= +tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin" +tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" + +tools.mkspiffs.cmd=mkspiffs +tools.mkspiffs.cmd.windows=mkspiffs.exe +tools.mkspiffs.path={runtime.tools.mkspiffs.path} + +tools.espupload.cmd=python +tools.espupload.cmd.windows=python.exe +tools.espupload.path={runtime.platform.path}/tools +tools.espupload.upload.protocol=espupload +tools.espupload.upload.params.verbose= +tools.espupload.upload.params.quiet= +tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin" + From a8e4baafacc257c89b95fd8a1d70a1902896ac21 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sun, 17 Feb 2019 12:49:13 +0100 Subject: [PATCH 1021/2222] Delete boards.txt --- arduino/version 2.5.0-beta2/boards.txt | 6086 ------------------------ 1 file changed, 6086 deletions(-) delete mode 100644 arduino/version 2.5.0-beta2/boards.txt diff --git a/arduino/version 2.5.0-beta2/boards.txt b/arduino/version 2.5.0-beta2/boards.txt deleted file mode 100644 index 2334302b8..000000000 --- a/arduino/version 2.5.0-beta2/boards.txt +++ /dev/null @@ -1,6086 +0,0 @@ -# -# Do not create pull-requests for this file only, CI will not accept them. -# You *must* edit/modify/run boards.txt.py to regenerate boards.txt. -# All modified files after running with option "--allgen" must be included in the pull-request. -# - -menu.BoardModel=Model -menu.baud=Upload Speed -menu.UploadTool=Upload Using -menu.xtal=CPU Frequency -menu.CrystalFreq=Crystal Frequency -menu.eesz=Flash Size -menu.FlashMode=Flash Mode -menu.FlashFreq=Flash Frequency -menu.ResetMethod=Reset Method -menu.ESPModule=Module -menu.dbg=Debug port -menu.lvl=Debug Level -menu.ip=lwIP Variant -menu.vt=VTables -menu.exception=Exceptions -menu.led=Builtin Led -menu.wipe=Erase Flash - -############################################################## -generic.name=Generic ESP8266 Module -generic.build.board=ESP8266_GENERIC -generic.upload.tool=esptool -generic.upload.maximum_data_size=81920 -generic.upload.wait_for_upload_port=true -generic.upload.erase_cmd= -generic.serial.disableDTR=true -generic.serial.disableRTS=true -generic.build.mcu=esp8266 -generic.build.core=esp8266 -generic.build.variant=generic -generic.build.spiffs_pagesize=256 -generic.build.debug_port= -generic.build.debug_level= - -generic.menu.UploadTool.esptool=Serial -generic.menu.UploadTool.esptool.upload.tool=esptool -generic.menu.UploadTool.esptool.upload.verbose=-vv -generic.menu.UploadTool.espupload=OTA_upload -generic.menu.UploadTool.espupload.upload.tool=espupload - -generic.menu.xtal.80=80 MHz -generic.menu.xtal.80.build.f_cpu=80000000L -generic.menu.xtal.160=160 MHz -generic.menu.xtal.160.build.f_cpu=160000000L -generic.menu.vt.flash=Flash -generic.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -generic.menu.vt.heap=Heap -generic.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -generic.menu.vt.iram=IRAM -generic.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -generic.menu.exception.enabled=Enabled -generic.menu.exception.enabled.build.exception_flags=-fexceptions -generic.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -generic.menu.exception.disabled=Disabled -generic.menu.exception.disabled.build.exception_flags=-fno-exceptions -generic.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -generic.menu.ResetMethod.ck=ck -generic.menu.ResetMethod.ck.upload.resetmethod=ck -generic.menu.ResetMethod.nodemcu=nodemcu -generic.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -generic.menu.ResetMethod.none=none -generic.menu.ResetMethod.none.upload.resetmethod=none -generic.menu.ResetMethod.dtrset=dtrset -generic.menu.ResetMethod.dtrset.upload.resetmethod=dtrset -generic.menu.CrystalFreq.26=26 MHz -generic.menu.CrystalFreq.40=40 MHz -generic.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -generic.menu.FlashFreq.40=40MHz -generic.menu.FlashFreq.40.build.flash_freq=40 -generic.menu.FlashFreq.80=80MHz -generic.menu.FlashFreq.80.build.flash_freq=80 -generic.menu.FlashMode.qio=QIO -generic.menu.FlashMode.qio.build.flash_mode=qio -generic.menu.FlashMode.qout=QOUT -generic.menu.FlashMode.qout.build.flash_mode=qout -generic.menu.FlashMode.dio=DIO -generic.menu.FlashMode.dio.build.flash_mode=dio -generic.menu.FlashMode.dout=DOUT -generic.menu.FlashMode.dout.build.flash_mode=dout -generic.menu.eesz.512K=512K (no SPIFFS) -generic.menu.eesz.512K.build.flash_size=512K -generic.menu.eesz.512K.build.flash_size_bytes=0x80000 -generic.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld -generic.menu.eesz.512K.build.spiffs_pagesize=256 -generic.menu.eesz.512K.upload.maximum_size=499696 -generic.menu.eesz.512K.build.rfcal_addr=0x7C000 -generic.menu.eesz.512K32=512K (32K SPIFFS) -generic.menu.eesz.512K32.build.flash_size=512K -generic.menu.eesz.512K32.build.flash_size_bytes=0x80000 -generic.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld -generic.menu.eesz.512K32.build.spiffs_pagesize=256 -generic.menu.eesz.512K32.upload.maximum_size=466928 -generic.menu.eesz.512K32.build.rfcal_addr=0x7C000 -generic.menu.eesz.512K32.build.spiffs_start=0x73000 -generic.menu.eesz.512K32.build.spiffs_end=0x7B000 -generic.menu.eesz.512K32.build.spiffs_blocksize=4096 -generic.menu.eesz.512K64=512K (64K SPIFFS) -generic.menu.eesz.512K64.build.flash_size=512K -generic.menu.eesz.512K64.build.flash_size_bytes=0x80000 -generic.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld -generic.menu.eesz.512K64.build.spiffs_pagesize=256 -generic.menu.eesz.512K64.upload.maximum_size=434160 -generic.menu.eesz.512K64.build.rfcal_addr=0x7C000 -generic.menu.eesz.512K64.build.spiffs_start=0x6B000 -generic.menu.eesz.512K64.build.spiffs_end=0x7B000 -generic.menu.eesz.512K64.build.spiffs_blocksize=4096 -generic.menu.eesz.512K128=512K (128K SPIFFS) -generic.menu.eesz.512K128.build.flash_size=512K -generic.menu.eesz.512K128.build.flash_size_bytes=0x80000 -generic.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld -generic.menu.eesz.512K128.build.spiffs_pagesize=256 -generic.menu.eesz.512K128.upload.maximum_size=368624 -generic.menu.eesz.512K128.build.rfcal_addr=0x7C000 -generic.menu.eesz.512K128.build.spiffs_start=0x5B000 -generic.menu.eesz.512K128.build.spiffs_end=0x7B000 -generic.menu.eesz.512K128.build.spiffs_blocksize=4096 -generic.menu.eesz.1M=1M (no SPIFFS) -generic.menu.eesz.1M.build.flash_size=1M -generic.menu.eesz.1M.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -generic.menu.eesz.1M.build.spiffs_pagesize=256 -generic.menu.eesz.1M.upload.maximum_size=1023984 -generic.menu.eesz.1M.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M64=1M (64K SPIFFS) -generic.menu.eesz.1M64.build.flash_size=1M -generic.menu.eesz.1M64.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -generic.menu.eesz.1M64.build.spiffs_pagesize=256 -generic.menu.eesz.1M64.upload.maximum_size=958448 -generic.menu.eesz.1M64.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M64.build.spiffs_start=0xEB000 -generic.menu.eesz.1M64.build.spiffs_end=0xFB000 -generic.menu.eesz.1M64.build.spiffs_blocksize=4096 -generic.menu.eesz.1M128=1M (128K SPIFFS) -generic.menu.eesz.1M128.build.flash_size=1M -generic.menu.eesz.1M128.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -generic.menu.eesz.1M128.build.spiffs_pagesize=256 -generic.menu.eesz.1M128.upload.maximum_size=892912 -generic.menu.eesz.1M128.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M128.build.spiffs_start=0xDB000 -generic.menu.eesz.1M128.build.spiffs_end=0xFB000 -generic.menu.eesz.1M128.build.spiffs_blocksize=4096 -generic.menu.eesz.1M144=1M (144K SPIFFS) -generic.menu.eesz.1M144.build.flash_size=1M -generic.menu.eesz.1M144.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -generic.menu.eesz.1M144.build.spiffs_pagesize=256 -generic.menu.eesz.1M144.upload.maximum_size=876528 -generic.menu.eesz.1M144.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M144.build.spiffs_start=0xD7000 -generic.menu.eesz.1M144.build.spiffs_end=0xFB000 -generic.menu.eesz.1M144.build.spiffs_blocksize=4096 -generic.menu.eesz.1M160=1M (160K SPIFFS) -generic.menu.eesz.1M160.build.flash_size=1M -generic.menu.eesz.1M160.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -generic.menu.eesz.1M160.build.spiffs_pagesize=256 -generic.menu.eesz.1M160.upload.maximum_size=860144 -generic.menu.eesz.1M160.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M160.build.spiffs_start=0xD3000 -generic.menu.eesz.1M160.build.spiffs_end=0xFB000 -generic.menu.eesz.1M160.build.spiffs_blocksize=4096 -generic.menu.eesz.1M192=1M (192K SPIFFS) -generic.menu.eesz.1M192.build.flash_size=1M -generic.menu.eesz.1M192.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -generic.menu.eesz.1M192.build.spiffs_pagesize=256 -generic.menu.eesz.1M192.upload.maximum_size=827376 -generic.menu.eesz.1M192.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M192.build.spiffs_start=0xCB000 -generic.menu.eesz.1M192.build.spiffs_end=0xFB000 -generic.menu.eesz.1M192.build.spiffs_blocksize=4096 -generic.menu.eesz.1M256=1M (256K SPIFFS) -generic.menu.eesz.1M256.build.flash_size=1M -generic.menu.eesz.1M256.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -generic.menu.eesz.1M256.build.spiffs_pagesize=256 -generic.menu.eesz.1M256.upload.maximum_size=761840 -generic.menu.eesz.1M256.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M256.build.spiffs_start=0xBB000 -generic.menu.eesz.1M256.build.spiffs_end=0xFB000 -generic.menu.eesz.1M256.build.spiffs_blocksize=4096 -generic.menu.eesz.1M512=1M (512K SPIFFS) -generic.menu.eesz.1M512.build.flash_size=1M -generic.menu.eesz.1M512.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -generic.menu.eesz.1M512.build.spiffs_pagesize=256 -generic.menu.eesz.1M512.upload.maximum_size=499696 -generic.menu.eesz.1M512.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M512.build.spiffs_start=0x7B000 -generic.menu.eesz.1M512.build.spiffs_end=0xFB000 -generic.menu.eesz.1M512.build.spiffs_blocksize=4096 -generic.menu.eesz.2M=2M (no SPIFFS) -generic.menu.eesz.2M.build.flash_size=2M -generic.menu.eesz.2M.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld -generic.menu.eesz.2M.build.spiffs_pagesize=256 -generic.menu.eesz.2M.upload.maximum_size=1044464 -generic.menu.eesz.2M.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M128=2M (128K SPIFFS) -generic.menu.eesz.2M128.build.flash_size=2M -generic.menu.eesz.2M128.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld -generic.menu.eesz.2M128.build.spiffs_pagesize=256 -generic.menu.eesz.2M128.upload.maximum_size=1044464 -generic.menu.eesz.2M128.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M128.build.spiffs_start=0x1E0000 -generic.menu.eesz.2M128.build.spiffs_end=0x1FB000 -generic.menu.eesz.2M128.build.spiffs_blocksize=4096 -generic.menu.eesz.2M256=2M (256K SPIFFS) -generic.menu.eesz.2M256.build.flash_size=2M -generic.menu.eesz.2M256.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld -generic.menu.eesz.2M256.build.spiffs_pagesize=256 -generic.menu.eesz.2M256.upload.maximum_size=1044464 -generic.menu.eesz.2M256.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M256.build.spiffs_start=0x1C0000 -generic.menu.eesz.2M256.build.spiffs_end=0x1FB000 -generic.menu.eesz.2M256.build.spiffs_blocksize=4096 -generic.menu.eesz.2M512=2M (512K SPIFFS) -generic.menu.eesz.2M512.build.flash_size=2M -generic.menu.eesz.2M512.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld -generic.menu.eesz.2M512.build.spiffs_pagesize=256 -generic.menu.eesz.2M512.upload.maximum_size=1044464 -generic.menu.eesz.2M512.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M512.build.spiffs_start=0x180000 -generic.menu.eesz.2M512.build.spiffs_end=0x1FB000 -generic.menu.eesz.2M512.build.spiffs_blocksize=8192 -generic.menu.eesz.2M1M=2M (1M SPIFFS) -generic.menu.eesz.2M1M.build.flash_size=2M -generic.menu.eesz.2M1M.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld -generic.menu.eesz.2M1M.build.spiffs_pagesize=256 -generic.menu.eesz.2M1M.upload.maximum_size=1044464 -generic.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M1M.build.spiffs_start=0x100000 -generic.menu.eesz.2M1M.build.spiffs_end=0x1FB000 -generic.menu.eesz.2M1M.build.spiffs_blocksize=8192 -generic.menu.eesz.4M=4M (no SPIFFS) -generic.menu.eesz.4M.build.flash_size=4M -generic.menu.eesz.4M.build.flash_size_bytes=0x400000 -generic.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -generic.menu.eesz.4M.build.spiffs_pagesize=256 -generic.menu.eesz.4M.upload.maximum_size=1044464 -generic.menu.eesz.4M.build.rfcal_addr=0x3FC000 -generic.menu.eesz.4M1M=4M (1M SPIFFS) -generic.menu.eesz.4M1M.build.flash_size=4M -generic.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -generic.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -generic.menu.eesz.4M1M.build.spiffs_pagesize=256 -generic.menu.eesz.4M1M.upload.maximum_size=1044464 -generic.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -generic.menu.eesz.4M1M.build.spiffs_start=0x300000 -generic.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -generic.menu.eesz.4M1M.build.spiffs_blocksize=8192 -generic.menu.eesz.4M2M=4M (2M SPIFFS) -generic.menu.eesz.4M2M.build.flash_size=4M -generic.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -generic.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -generic.menu.eesz.4M2M.build.spiffs_pagesize=256 -generic.menu.eesz.4M2M.upload.maximum_size=1044464 -generic.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -generic.menu.eesz.4M2M.build.spiffs_start=0x200000 -generic.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -generic.menu.eesz.4M2M.build.spiffs_blocksize=8192 -generic.menu.eesz.4M3M=4M (3M SPIFFS) -generic.menu.eesz.4M3M.build.flash_size=4M -generic.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -generic.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -generic.menu.eesz.4M3M.build.spiffs_pagesize=256 -generic.menu.eesz.4M3M.upload.maximum_size=1044464 -generic.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -generic.menu.eesz.4M3M.build.spiffs_start=0x100000 -generic.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -generic.menu.eesz.4M3M.build.spiffs_blocksize=8192 -generic.menu.eesz.8M6M=8M (6M SPIFFS) -generic.menu.eesz.8M6M.build.flash_size=8M -generic.menu.eesz.8M6M.build.flash_size_bytes=0x800000 -generic.menu.eesz.8M6M.build.flash_ld=eagle.flash.8m6m.ld -generic.menu.eesz.8M6M.build.spiffs_pagesize=256 -generic.menu.eesz.8M6M.upload.maximum_size=1044464 -generic.menu.eesz.8M6M.build.rfcal_addr=0x7FC000 -generic.menu.eesz.8M6M.build.spiffs_start=0x200000 -generic.menu.eesz.8M6M.build.spiffs_end=0x7FB000 -generic.menu.eesz.8M6M.build.spiffs_blocksize=8192 -generic.menu.eesz.8M7M=8M (7M SPIFFS) -generic.menu.eesz.8M7M.build.flash_size=8M -generic.menu.eesz.8M7M.build.flash_size_bytes=0x800000 -generic.menu.eesz.8M7M.build.flash_ld=eagle.flash.8m7m.ld -generic.menu.eesz.8M7M.build.spiffs_pagesize=256 -generic.menu.eesz.8M7M.upload.maximum_size=1044464 -generic.menu.eesz.8M7M.build.rfcal_addr=0x7FC000 -generic.menu.eesz.8M7M.build.spiffs_start=0x100000 -generic.menu.eesz.8M7M.build.spiffs_end=0x7FB000 -generic.menu.eesz.8M7M.build.spiffs_blocksize=8192 -generic.menu.eesz.16M14M=16M (14M SPIFFS) -generic.menu.eesz.16M14M.build.flash_size=16M -generic.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 -generic.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld -generic.menu.eesz.16M14M.build.spiffs_pagesize=256 -generic.menu.eesz.16M14M.upload.maximum_size=1044464 -generic.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 -generic.menu.eesz.16M14M.build.spiffs_start=0x200000 -generic.menu.eesz.16M14M.build.spiffs_end=0xFFB000 -generic.menu.eesz.16M14M.build.spiffs_blocksize=8192 -generic.menu.eesz.16M15M=16M (15M SPIFFS) -generic.menu.eesz.16M15M.build.flash_size=16M -generic.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 -generic.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld -generic.menu.eesz.16M15M.build.spiffs_pagesize=256 -generic.menu.eesz.16M15M.upload.maximum_size=1044464 -generic.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 -generic.menu.eesz.16M15M.build.spiffs_start=0x100000 -generic.menu.eesz.16M15M.build.spiffs_end=0xFFB000 -generic.menu.eesz.16M15M.build.spiffs_blocksize=8192 -generic.menu.led.2=2 -generic.menu.led.2.build.led=-DLED_BUILTIN=2 -generic.menu.led.0=0 -generic.menu.led.0.build.led=-DLED_BUILTIN=0 -generic.menu.led.1=1 -generic.menu.led.1.build.led=-DLED_BUILTIN=1 -generic.menu.led.3=3 -generic.menu.led.3.build.led=-DLED_BUILTIN=3 -generic.menu.led.4=4 -generic.menu.led.4.build.led=-DLED_BUILTIN=4 -generic.menu.led.5=5 -generic.menu.led.5.build.led=-DLED_BUILTIN=5 -generic.menu.led.6=6 -generic.menu.led.6.build.led=-DLED_BUILTIN=6 -generic.menu.led.7=7 -generic.menu.led.7.build.led=-DLED_BUILTIN=7 -generic.menu.led.8=8 -generic.menu.led.8.build.led=-DLED_BUILTIN=8 -generic.menu.led.9=9 -generic.menu.led.9.build.led=-DLED_BUILTIN=9 -generic.menu.led.10=10 -generic.menu.led.10.build.led=-DLED_BUILTIN=10 -generic.menu.led.11=11 -generic.menu.led.11.build.led=-DLED_BUILTIN=11 -generic.menu.led.12=12 -generic.menu.led.12.build.led=-DLED_BUILTIN=12 -generic.menu.led.13=13 -generic.menu.led.13.build.led=-DLED_BUILTIN=13 -generic.menu.led.14=14 -generic.menu.led.14.build.led=-DLED_BUILTIN=14 -generic.menu.led.15=15 -generic.menu.led.15.build.led=-DLED_BUILTIN=15 -generic.menu.ip.lm2f=v2 Lower Memory -generic.menu.ip.lm2f.build.lwip_include=lwip2/include -generic.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -generic.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -generic.menu.ip.hb2f=v2 Higher Bandwidth -generic.menu.ip.hb2f.build.lwip_include=lwip2/include -generic.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -generic.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -generic.menu.ip.lm2n=v2 Lower Memory (no features) -generic.menu.ip.lm2n.build.lwip_include=lwip2/include -generic.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -generic.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -generic.menu.ip.hb2n=v2 Higher Bandwidth (no features) -generic.menu.ip.hb2n.build.lwip_include=lwip2/include -generic.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -generic.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -generic.menu.ip.lm6f=v2 IPv6 Lower Memory -generic.menu.ip.lm6f.build.lwip_include=lwip2/include -generic.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -generic.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -generic.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -generic.menu.ip.hb6f.build.lwip_include=lwip2/include -generic.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -generic.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -generic.menu.ip.hb1=v1.4 Higher Bandwidth -generic.menu.ip.hb1.build.lwip_lib=-llwip_gcc -generic.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -generic.menu.ip.src=v1.4 Compile from source -generic.menu.ip.src.build.lwip_lib=-llwip_src -generic.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -generic.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -generic.menu.dbg.Disabled=Disabled -generic.menu.dbg.Disabled.build.debug_port= -generic.menu.dbg.Serial=Serial -generic.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -generic.menu.dbg.Serial1=Serial1 -generic.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -generic.menu.lvl.None____=None -generic.menu.lvl.None____.build.debug_level= -generic.menu.lvl.SSL=SSL -generic.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -generic.menu.lvl.TLS_MEM=TLS_MEM -generic.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -generic.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -generic.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -generic.menu.lvl.HTTP_SERVER=HTTP_SERVER -generic.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -generic.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -generic.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -generic.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -generic.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -generic.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -generic.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -generic.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -generic.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -generic.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -generic.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -generic.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.CORE=CORE -generic.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -generic.menu.lvl.WIFI=WIFI -generic.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -generic.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -generic.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -generic.menu.lvl.UPDATER=UPDATER -generic.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -generic.menu.lvl.OTA=OTA -generic.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -generic.menu.lvl.OOM=OOM -generic.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -generic.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -generic.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -generic.menu.wipe.none=Only Sketch -generic.menu.wipe.none.upload.erase_cmd= -generic.menu.wipe.sdk=Sketch + WiFi Settings -generic.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -generic.menu.wipe.all=All Flash Contents -generic.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -generic.menu.baud.115200=115200 -generic.menu.baud.115200.upload.speed=115200 -generic.menu.baud.9600=9600 -generic.menu.baud.9600.upload.speed=9600 -generic.menu.baud.57600=57600 -generic.menu.baud.57600.upload.speed=57600 -generic.menu.baud.230400.linux=230400 -generic.menu.baud.230400.macosx=230400 -generic.menu.baud.230400.upload.speed=230400 -generic.menu.baud.256000.windows=256000 -generic.menu.baud.256000.upload.speed=256000 -generic.menu.baud.460800.linux=460800 -generic.menu.baud.460800.macosx=460800 -generic.menu.baud.460800.upload.speed=460800 -generic.menu.baud.512000.windows=512000 -generic.menu.baud.512000.upload.speed=512000 -generic.menu.baud.921600=921600 -generic.menu.baud.921600.upload.speed=921600 - -############################################################## -esp8285.name=Generic ESP8285 Module -esp8285.build.board=ESP8266_ESP01 -esp8285.build.variant=esp8285 -esp8285.upload.tool=esptool -esp8285.upload.maximum_data_size=81920 -esp8285.upload.wait_for_upload_port=true -esp8285.upload.erase_cmd= -esp8285.serial.disableDTR=true -esp8285.serial.disableRTS=true -esp8285.build.mcu=esp8266 -esp8285.build.core=esp8266 -esp8285.build.spiffs_pagesize=256 -esp8285.build.debug_port= -esp8285.build.debug_level= -esp8285.menu.xtal.80=80 MHz -esp8285.menu.xtal.80.build.f_cpu=80000000L -esp8285.menu.xtal.160=160 MHz -esp8285.menu.xtal.160.build.f_cpu=160000000L -esp8285.menu.vt.flash=Flash -esp8285.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -esp8285.menu.vt.heap=Heap -esp8285.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -esp8285.menu.vt.iram=IRAM -esp8285.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -esp8285.menu.exception.enabled=Enabled -esp8285.menu.exception.enabled.build.exception_flags=-fexceptions -esp8285.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -esp8285.menu.exception.disabled=Disabled -esp8285.menu.exception.disabled.build.exception_flags=-fno-exceptions -esp8285.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -esp8285.menu.ResetMethod.ck=ck -esp8285.menu.ResetMethod.ck.upload.resetmethod=ck -esp8285.menu.ResetMethod.nodemcu=nodemcu -esp8285.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -esp8285.menu.ResetMethod.none=none -esp8285.menu.ResetMethod.none.upload.resetmethod=none -esp8285.menu.ResetMethod.dtrset=dtrset -esp8285.menu.ResetMethod.dtrset.upload.resetmethod=dtrset -esp8285.menu.CrystalFreq.26=26 MHz -esp8285.menu.CrystalFreq.40=40 MHz -esp8285.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -esp8285.build.flash_mode=dout -esp8285.build.flash_freq=40 -esp8285.menu.eesz.1M=1M (no SPIFFS) -esp8285.menu.eesz.1M.build.flash_size=1M -esp8285.menu.eesz.1M.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -esp8285.menu.eesz.1M.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M.upload.maximum_size=1023984 -esp8285.menu.eesz.1M.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M64=1M (64K SPIFFS) -esp8285.menu.eesz.1M64.build.flash_size=1M -esp8285.menu.eesz.1M64.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -esp8285.menu.eesz.1M64.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M64.upload.maximum_size=958448 -esp8285.menu.eesz.1M64.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M64.build.spiffs_start=0xEB000 -esp8285.menu.eesz.1M64.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M64.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M128=1M (128K SPIFFS) -esp8285.menu.eesz.1M128.build.flash_size=1M -esp8285.menu.eesz.1M128.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -esp8285.menu.eesz.1M128.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M128.upload.maximum_size=892912 -esp8285.menu.eesz.1M128.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M128.build.spiffs_start=0xDB000 -esp8285.menu.eesz.1M128.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M128.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M144=1M (144K SPIFFS) -esp8285.menu.eesz.1M144.build.flash_size=1M -esp8285.menu.eesz.1M144.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -esp8285.menu.eesz.1M144.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M144.upload.maximum_size=876528 -esp8285.menu.eesz.1M144.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M144.build.spiffs_start=0xD7000 -esp8285.menu.eesz.1M144.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M144.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M160=1M (160K SPIFFS) -esp8285.menu.eesz.1M160.build.flash_size=1M -esp8285.menu.eesz.1M160.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -esp8285.menu.eesz.1M160.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M160.upload.maximum_size=860144 -esp8285.menu.eesz.1M160.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M160.build.spiffs_start=0xD3000 -esp8285.menu.eesz.1M160.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M160.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M192=1M (192K SPIFFS) -esp8285.menu.eesz.1M192.build.flash_size=1M -esp8285.menu.eesz.1M192.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -esp8285.menu.eesz.1M192.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M192.upload.maximum_size=827376 -esp8285.menu.eesz.1M192.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M192.build.spiffs_start=0xCB000 -esp8285.menu.eesz.1M192.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M192.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M256=1M (256K SPIFFS) -esp8285.menu.eesz.1M256.build.flash_size=1M -esp8285.menu.eesz.1M256.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -esp8285.menu.eesz.1M256.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M256.upload.maximum_size=761840 -esp8285.menu.eesz.1M256.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M256.build.spiffs_start=0xBB000 -esp8285.menu.eesz.1M256.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M256.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M512=1M (512K SPIFFS) -esp8285.menu.eesz.1M512.build.flash_size=1M -esp8285.menu.eesz.1M512.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -esp8285.menu.eesz.1M512.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M512.upload.maximum_size=499696 -esp8285.menu.eesz.1M512.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M512.build.spiffs_start=0x7B000 -esp8285.menu.eesz.1M512.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M512.build.spiffs_blocksize=4096 -esp8285.menu.led.2=2 -esp8285.menu.led.2.build.led=-DLED_BUILTIN=2 -esp8285.menu.led.0=0 -esp8285.menu.led.0.build.led=-DLED_BUILTIN=0 -esp8285.menu.led.1=1 -esp8285.menu.led.1.build.led=-DLED_BUILTIN=1 -esp8285.menu.led.3=3 -esp8285.menu.led.3.build.led=-DLED_BUILTIN=3 -esp8285.menu.led.4=4 -esp8285.menu.led.4.build.led=-DLED_BUILTIN=4 -esp8285.menu.led.5=5 -esp8285.menu.led.5.build.led=-DLED_BUILTIN=5 -esp8285.menu.led.6=6 -esp8285.menu.led.6.build.led=-DLED_BUILTIN=6 -esp8285.menu.led.7=7 -esp8285.menu.led.7.build.led=-DLED_BUILTIN=7 -esp8285.menu.led.8=8 -esp8285.menu.led.8.build.led=-DLED_BUILTIN=8 -esp8285.menu.led.9=9 -esp8285.menu.led.9.build.led=-DLED_BUILTIN=9 -esp8285.menu.led.10=10 -esp8285.menu.led.10.build.led=-DLED_BUILTIN=10 -esp8285.menu.led.11=11 -esp8285.menu.led.11.build.led=-DLED_BUILTIN=11 -esp8285.menu.led.12=12 -esp8285.menu.led.12.build.led=-DLED_BUILTIN=12 -esp8285.menu.led.13=13 -esp8285.menu.led.13.build.led=-DLED_BUILTIN=13 -esp8285.menu.led.14=14 -esp8285.menu.led.14.build.led=-DLED_BUILTIN=14 -esp8285.menu.led.15=15 -esp8285.menu.led.15.build.led=-DLED_BUILTIN=15 -esp8285.menu.ip.lm2f=v2 Lower Memory -esp8285.menu.ip.lm2f.build.lwip_include=lwip2/include -esp8285.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -esp8285.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -esp8285.menu.ip.hb2f=v2 Higher Bandwidth -esp8285.menu.ip.hb2f.build.lwip_include=lwip2/include -esp8285.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -esp8285.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -esp8285.menu.ip.lm2n=v2 Lower Memory (no features) -esp8285.menu.ip.lm2n.build.lwip_include=lwip2/include -esp8285.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -esp8285.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -esp8285.menu.ip.hb2n=v2 Higher Bandwidth (no features) -esp8285.menu.ip.hb2n.build.lwip_include=lwip2/include -esp8285.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -esp8285.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -esp8285.menu.ip.lm6f=v2 IPv6 Lower Memory -esp8285.menu.ip.lm6f.build.lwip_include=lwip2/include -esp8285.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -esp8285.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -esp8285.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -esp8285.menu.ip.hb6f.build.lwip_include=lwip2/include -esp8285.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -esp8285.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -esp8285.menu.ip.hb1=v1.4 Higher Bandwidth -esp8285.menu.ip.hb1.build.lwip_lib=-llwip_gcc -esp8285.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -esp8285.menu.ip.src=v1.4 Compile from source -esp8285.menu.ip.src.build.lwip_lib=-llwip_src -esp8285.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -esp8285.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -esp8285.menu.dbg.Disabled=Disabled -esp8285.menu.dbg.Disabled.build.debug_port= -esp8285.menu.dbg.Serial=Serial -esp8285.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -esp8285.menu.dbg.Serial1=Serial1 -esp8285.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -esp8285.menu.lvl.None____=None -esp8285.menu.lvl.None____.build.debug_level= -esp8285.menu.lvl.SSL=SSL -esp8285.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -esp8285.menu.lvl.TLS_MEM=TLS_MEM -esp8285.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -esp8285.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -esp8285.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.lvl.HTTP_SERVER=HTTP_SERVER -esp8285.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -esp8285.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -esp8285.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -esp8285.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -esp8285.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -esp8285.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -esp8285.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.CORE=CORE -esp8285.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -esp8285.menu.lvl.WIFI=WIFI -esp8285.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -esp8285.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -esp8285.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -esp8285.menu.lvl.UPDATER=UPDATER -esp8285.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -esp8285.menu.lvl.OTA=OTA -esp8285.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -esp8285.menu.lvl.OOM=OOM -esp8285.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -esp8285.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -esp8285.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -esp8285.menu.wipe.none=Only Sketch -esp8285.menu.wipe.none.upload.erase_cmd= -esp8285.menu.wipe.sdk=Sketch + WiFi Settings -esp8285.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -esp8285.menu.wipe.all=All Flash Contents -esp8285.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -esp8285.menu.baud.115200=115200 -esp8285.menu.baud.115200.upload.speed=115200 -esp8285.menu.baud.9600=9600 -esp8285.menu.baud.9600.upload.speed=9600 -esp8285.menu.baud.57600=57600 -esp8285.menu.baud.57600.upload.speed=57600 -esp8285.menu.baud.230400.linux=230400 -esp8285.menu.baud.230400.macosx=230400 -esp8285.menu.baud.230400.upload.speed=230400 -esp8285.menu.baud.256000.windows=256000 -esp8285.menu.baud.256000.upload.speed=256000 -esp8285.menu.baud.460800.linux=460800 -esp8285.menu.baud.460800.macosx=460800 -esp8285.menu.baud.460800.upload.speed=460800 -esp8285.menu.baud.512000.windows=512000 -esp8285.menu.baud.512000.upload.speed=512000 -esp8285.menu.baud.921600=921600 -esp8285.menu.baud.921600.upload.speed=921600 - -############################################################## -espduino.name=ESPDuino (ESP-13 Module) -espduino.build.board=ESP8266_ESP13 -espduino.build.variant=ESPDuino -espduino.menu.ResetMethod.v2=ESPduino-V2 -espduino.menu.ResetMethod.v2.upload.resetmethod=nodemcu -espduino.menu.ResetMethod.v1=ESPduino-V1 -espduino.menu.ResetMethod.v1.upload.resetmethod=ck -espduino.menu.UploadTool.esptool=Serial -espduino.menu.UploadTool.esptool.upload.tool=esptool -espduino.menu.UploadTool.esptool.upload.verbose=-vv -espduino.menu.UploadTool.espota=OTA -espduino.menu.UploadTool.espota.upload.tool=espota -espduino.upload.tool=esptool -espduino.upload.maximum_data_size=81920 -espduino.upload.wait_for_upload_port=true -espduino.upload.erase_cmd= -espduino.serial.disableDTR=true -espduino.serial.disableRTS=true -espduino.build.mcu=esp8266 -espduino.build.core=esp8266 -espduino.build.spiffs_pagesize=256 -espduino.build.debug_port= -espduino.build.debug_level= -espduino.menu.xtal.80=80 MHz -espduino.menu.xtal.80.build.f_cpu=80000000L -espduino.menu.xtal.160=160 MHz -espduino.menu.xtal.160.build.f_cpu=160000000L -espduino.menu.vt.flash=Flash -espduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espduino.menu.vt.heap=Heap -espduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espduino.menu.vt.iram=IRAM -espduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espduino.menu.exception.enabled=Enabled -espduino.menu.exception.enabled.build.exception_flags=-fexceptions -espduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -espduino.menu.exception.disabled=Disabled -espduino.menu.exception.disabled.build.exception_flags=-fno-exceptions -espduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -espduino.build.flash_mode=dio -espduino.build.flash_freq=40 -espduino.menu.eesz.4M=4M (no SPIFFS) -espduino.menu.eesz.4M.build.flash_size=4M -espduino.menu.eesz.4M.build.flash_size_bytes=0x400000 -espduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espduino.menu.eesz.4M.build.spiffs_pagesize=256 -espduino.menu.eesz.4M.upload.maximum_size=1044464 -espduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espduino.menu.eesz.4M1M=4M (1M SPIFFS) -espduino.menu.eesz.4M1M.build.flash_size=4M -espduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espduino.menu.eesz.4M1M.build.spiffs_pagesize=256 -espduino.menu.eesz.4M1M.upload.maximum_size=1044464 -espduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espduino.menu.eesz.4M1M.build.spiffs_start=0x300000 -espduino.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -espduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espduino.menu.eesz.4M2M=4M (2M SPIFFS) -espduino.menu.eesz.4M2M.build.flash_size=4M -espduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espduino.menu.eesz.4M2M.build.spiffs_pagesize=256 -espduino.menu.eesz.4M2M.upload.maximum_size=1044464 -espduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espduino.menu.eesz.4M2M.build.spiffs_start=0x200000 -espduino.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -espduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espduino.menu.eesz.4M3M=4M (3M SPIFFS) -espduino.menu.eesz.4M3M.build.flash_size=4M -espduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espduino.menu.eesz.4M3M.build.spiffs_pagesize=256 -espduino.menu.eesz.4M3M.upload.maximum_size=1044464 -espduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espduino.menu.eesz.4M3M.build.spiffs_start=0x100000 -espduino.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -espduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espduino.menu.ip.lm2f=v2 Lower Memory -espduino.menu.ip.lm2f.build.lwip_include=lwip2/include -espduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espduino.menu.ip.hb2f=v2 Higher Bandwidth -espduino.menu.ip.hb2f.build.lwip_include=lwip2/include -espduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espduino.menu.ip.lm2n=v2 Lower Memory (no features) -espduino.menu.ip.lm2n.build.lwip_include=lwip2/include -espduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espduino.menu.ip.hb2n.build.lwip_include=lwip2/include -espduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espduino.menu.ip.lm6f=v2 IPv6 Lower Memory -espduino.menu.ip.lm6f.build.lwip_include=lwip2/include -espduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espduino.menu.ip.hb6f.build.lwip_include=lwip2/include -espduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espduino.menu.ip.hb1=v1.4 Higher Bandwidth -espduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espduino.menu.ip.src=v1.4 Compile from source -espduino.menu.ip.src.build.lwip_lib=-llwip_src -espduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espduino.menu.dbg.Disabled=Disabled -espduino.menu.dbg.Disabled.build.debug_port= -espduino.menu.dbg.Serial=Serial -espduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espduino.menu.dbg.Serial1=Serial1 -espduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espduino.menu.lvl.None____=None -espduino.menu.lvl.None____.build.debug_level= -espduino.menu.lvl.SSL=SSL -espduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espduino.menu.lvl.TLS_MEM=TLS_MEM -espduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.lvl.HTTP_SERVER=HTTP_SERVER -espduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.CORE=CORE -espduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espduino.menu.lvl.WIFI=WIFI -espduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espduino.menu.lvl.UPDATER=UPDATER -espduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espduino.menu.lvl.OTA=OTA -espduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espduino.menu.lvl.OOM=OOM -espduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espduino.menu.wipe.none=Only Sketch -espduino.menu.wipe.none.upload.erase_cmd= -espduino.menu.wipe.sdk=Sketch + WiFi Settings -espduino.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espduino.menu.wipe.all=All Flash Contents -espduino.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espduino.menu.baud.115200=115200 -espduino.menu.baud.115200.upload.speed=115200 -espduino.menu.baud.9600=9600 -espduino.menu.baud.9600.upload.speed=9600 -espduino.menu.baud.57600=57600 -espduino.menu.baud.57600.upload.speed=57600 -espduino.menu.baud.230400.linux=230400 -espduino.menu.baud.230400.macosx=230400 -espduino.menu.baud.230400.upload.speed=230400 -espduino.menu.baud.256000.windows=256000 -espduino.menu.baud.256000.upload.speed=256000 -espduino.menu.baud.460800.linux=460800 -espduino.menu.baud.460800.macosx=460800 -espduino.menu.baud.460800.upload.speed=460800 -espduino.menu.baud.512000.windows=512000 -espduino.menu.baud.512000.upload.speed=512000 -espduino.menu.baud.921600=921600 -espduino.menu.baud.921600.upload.speed=921600 - -############################################################## -huzzah.name=Adafruit Feather HUZZAH ESP8266 -huzzah.build.board=ESP8266_ESP12 -huzzah.build.variant=adafruit -huzzah.upload.tool=esptool -huzzah.upload.maximum_data_size=81920 -huzzah.upload.wait_for_upload_port=true -huzzah.upload.erase_cmd= -huzzah.serial.disableDTR=true -huzzah.serial.disableRTS=true -huzzah.build.mcu=esp8266 -huzzah.build.core=esp8266 -huzzah.build.spiffs_pagesize=256 -huzzah.build.debug_port= -huzzah.build.debug_level= -huzzah.menu.xtal.80=80 MHz -huzzah.menu.xtal.80.build.f_cpu=80000000L -huzzah.menu.xtal.160=160 MHz -huzzah.menu.xtal.160.build.f_cpu=160000000L -huzzah.menu.vt.flash=Flash -huzzah.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -huzzah.menu.vt.heap=Heap -huzzah.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -huzzah.menu.vt.iram=IRAM -huzzah.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -huzzah.menu.exception.enabled=Enabled -huzzah.menu.exception.enabled.build.exception_flags=-fexceptions -huzzah.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -huzzah.menu.exception.disabled=Disabled -huzzah.menu.exception.disabled.build.exception_flags=-fno-exceptions -huzzah.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -huzzah.upload.resetmethod=nodemcu -huzzah.build.flash_mode=qio -huzzah.build.flash_freq=40 -huzzah.menu.eesz.4M=4M (no SPIFFS) -huzzah.menu.eesz.4M.build.flash_size=4M -huzzah.menu.eesz.4M.build.flash_size_bytes=0x400000 -huzzah.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -huzzah.menu.eesz.4M.build.spiffs_pagesize=256 -huzzah.menu.eesz.4M.upload.maximum_size=1044464 -huzzah.menu.eesz.4M.build.rfcal_addr=0x3FC000 -huzzah.menu.eesz.4M1M=4M (1M SPIFFS) -huzzah.menu.eesz.4M1M.build.flash_size=4M -huzzah.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -huzzah.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -huzzah.menu.eesz.4M1M.build.spiffs_pagesize=256 -huzzah.menu.eesz.4M1M.upload.maximum_size=1044464 -huzzah.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -huzzah.menu.eesz.4M1M.build.spiffs_start=0x300000 -huzzah.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -huzzah.menu.eesz.4M1M.build.spiffs_blocksize=8192 -huzzah.menu.eesz.4M2M=4M (2M SPIFFS) -huzzah.menu.eesz.4M2M.build.flash_size=4M -huzzah.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -huzzah.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -huzzah.menu.eesz.4M2M.build.spiffs_pagesize=256 -huzzah.menu.eesz.4M2M.upload.maximum_size=1044464 -huzzah.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -huzzah.menu.eesz.4M2M.build.spiffs_start=0x200000 -huzzah.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -huzzah.menu.eesz.4M2M.build.spiffs_blocksize=8192 -huzzah.menu.eesz.4M3M=4M (3M SPIFFS) -huzzah.menu.eesz.4M3M.build.flash_size=4M -huzzah.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -huzzah.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -huzzah.menu.eesz.4M3M.build.spiffs_pagesize=256 -huzzah.menu.eesz.4M3M.upload.maximum_size=1044464 -huzzah.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -huzzah.menu.eesz.4M3M.build.spiffs_start=0x100000 -huzzah.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -huzzah.menu.eesz.4M3M.build.spiffs_blocksize=8192 -huzzah.menu.ip.lm2f=v2 Lower Memory -huzzah.menu.ip.lm2f.build.lwip_include=lwip2/include -huzzah.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -huzzah.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -huzzah.menu.ip.hb2f=v2 Higher Bandwidth -huzzah.menu.ip.hb2f.build.lwip_include=lwip2/include -huzzah.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -huzzah.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -huzzah.menu.ip.lm2n=v2 Lower Memory (no features) -huzzah.menu.ip.lm2n.build.lwip_include=lwip2/include -huzzah.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -huzzah.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -huzzah.menu.ip.hb2n=v2 Higher Bandwidth (no features) -huzzah.menu.ip.hb2n.build.lwip_include=lwip2/include -huzzah.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -huzzah.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -huzzah.menu.ip.lm6f=v2 IPv6 Lower Memory -huzzah.menu.ip.lm6f.build.lwip_include=lwip2/include -huzzah.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -huzzah.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -huzzah.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -huzzah.menu.ip.hb6f.build.lwip_include=lwip2/include -huzzah.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -huzzah.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -huzzah.menu.ip.hb1=v1.4 Higher Bandwidth -huzzah.menu.ip.hb1.build.lwip_lib=-llwip_gcc -huzzah.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -huzzah.menu.ip.src=v1.4 Compile from source -huzzah.menu.ip.src.build.lwip_lib=-llwip_src -huzzah.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -huzzah.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -huzzah.menu.dbg.Disabled=Disabled -huzzah.menu.dbg.Disabled.build.debug_port= -huzzah.menu.dbg.Serial=Serial -huzzah.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -huzzah.menu.dbg.Serial1=Serial1 -huzzah.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -huzzah.menu.lvl.None____=None -huzzah.menu.lvl.None____.build.debug_level= -huzzah.menu.lvl.SSL=SSL -huzzah.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -huzzah.menu.lvl.TLS_MEM=TLS_MEM -huzzah.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -huzzah.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -huzzah.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.lvl.HTTP_SERVER=HTTP_SERVER -huzzah.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -huzzah.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -huzzah.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -huzzah.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -huzzah.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -huzzah.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -huzzah.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.CORE=CORE -huzzah.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -huzzah.menu.lvl.WIFI=WIFI -huzzah.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -huzzah.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -huzzah.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -huzzah.menu.lvl.UPDATER=UPDATER -huzzah.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -huzzah.menu.lvl.OTA=OTA -huzzah.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -huzzah.menu.lvl.OOM=OOM -huzzah.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -huzzah.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -huzzah.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -huzzah.menu.wipe.none=Only Sketch -huzzah.menu.wipe.none.upload.erase_cmd= -huzzah.menu.wipe.sdk=Sketch + WiFi Settings -huzzah.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -huzzah.menu.wipe.all=All Flash Contents -huzzah.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -huzzah.menu.baud.115200=115200 -huzzah.menu.baud.115200.upload.speed=115200 -huzzah.menu.baud.9600=9600 -huzzah.menu.baud.9600.upload.speed=9600 -huzzah.menu.baud.57600=57600 -huzzah.menu.baud.57600.upload.speed=57600 -huzzah.menu.baud.230400.linux=230400 -huzzah.menu.baud.230400.macosx=230400 -huzzah.menu.baud.230400.upload.speed=230400 -huzzah.menu.baud.256000.windows=256000 -huzzah.menu.baud.256000.upload.speed=256000 -huzzah.menu.baud.460800.linux=460800 -huzzah.menu.baud.460800.macosx=460800 -huzzah.menu.baud.460800.upload.speed=460800 -huzzah.menu.baud.512000.windows=512000 -huzzah.menu.baud.512000.upload.speed=512000 -huzzah.menu.baud.921600=921600 -huzzah.menu.baud.921600.upload.speed=921600 - -############################################################## -inventone.name=Invent One -inventone.build.board=ESP8266_GENERIC -inventone.build.variant=inventone -inventone.upload.tool=esptool -inventone.upload.maximum_data_size=81920 -inventone.upload.wait_for_upload_port=true -inventone.upload.erase_cmd= -inventone.serial.disableDTR=true -inventone.serial.disableRTS=true -inventone.build.mcu=esp8266 -inventone.build.core=esp8266 -inventone.build.spiffs_pagesize=256 -inventone.build.debug_port= -inventone.build.debug_level= -inventone.menu.xtal.80=80 MHz -inventone.menu.xtal.80.build.f_cpu=80000000L -inventone.menu.xtal.160=160 MHz -inventone.menu.xtal.160.build.f_cpu=160000000L -inventone.menu.vt.flash=Flash -inventone.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -inventone.menu.vt.heap=Heap -inventone.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -inventone.menu.vt.iram=IRAM -inventone.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -inventone.menu.exception.enabled=Enabled -inventone.menu.exception.enabled.build.exception_flags=-fexceptions -inventone.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -inventone.menu.exception.disabled=Disabled -inventone.menu.exception.disabled.build.exception_flags=-fno-exceptions -inventone.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -inventone.upload.resetmethod=nodemcu -inventone.build.flash_mode=dio -inventone.build.flash_freq=40 -inventone.menu.eesz.4M=4M (no SPIFFS) -inventone.menu.eesz.4M.build.flash_size=4M -inventone.menu.eesz.4M.build.flash_size_bytes=0x400000 -inventone.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -inventone.menu.eesz.4M.build.spiffs_pagesize=256 -inventone.menu.eesz.4M.upload.maximum_size=1044464 -inventone.menu.eesz.4M.build.rfcal_addr=0x3FC000 -inventone.menu.eesz.4M1M=4M (1M SPIFFS) -inventone.menu.eesz.4M1M.build.flash_size=4M -inventone.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -inventone.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -inventone.menu.eesz.4M1M.build.spiffs_pagesize=256 -inventone.menu.eesz.4M1M.upload.maximum_size=1044464 -inventone.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -inventone.menu.eesz.4M1M.build.spiffs_start=0x300000 -inventone.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -inventone.menu.eesz.4M1M.build.spiffs_blocksize=8192 -inventone.menu.eesz.4M2M=4M (2M SPIFFS) -inventone.menu.eesz.4M2M.build.flash_size=4M -inventone.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -inventone.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -inventone.menu.eesz.4M2M.build.spiffs_pagesize=256 -inventone.menu.eesz.4M2M.upload.maximum_size=1044464 -inventone.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -inventone.menu.eesz.4M2M.build.spiffs_start=0x200000 -inventone.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -inventone.menu.eesz.4M2M.build.spiffs_blocksize=8192 -inventone.menu.eesz.4M3M=4M (3M SPIFFS) -inventone.menu.eesz.4M3M.build.flash_size=4M -inventone.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -inventone.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -inventone.menu.eesz.4M3M.build.spiffs_pagesize=256 -inventone.menu.eesz.4M3M.upload.maximum_size=1044464 -inventone.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -inventone.menu.eesz.4M3M.build.spiffs_start=0x100000 -inventone.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -inventone.menu.eesz.4M3M.build.spiffs_blocksize=8192 -inventone.menu.ip.lm2f=v2 Lower Memory -inventone.menu.ip.lm2f.build.lwip_include=lwip2/include -inventone.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -inventone.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -inventone.menu.ip.hb2f=v2 Higher Bandwidth -inventone.menu.ip.hb2f.build.lwip_include=lwip2/include -inventone.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -inventone.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -inventone.menu.ip.lm2n=v2 Lower Memory (no features) -inventone.menu.ip.lm2n.build.lwip_include=lwip2/include -inventone.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -inventone.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -inventone.menu.ip.hb2n=v2 Higher Bandwidth (no features) -inventone.menu.ip.hb2n.build.lwip_include=lwip2/include -inventone.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -inventone.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -inventone.menu.ip.lm6f=v2 IPv6 Lower Memory -inventone.menu.ip.lm6f.build.lwip_include=lwip2/include -inventone.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -inventone.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -inventone.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -inventone.menu.ip.hb6f.build.lwip_include=lwip2/include -inventone.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -inventone.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -inventone.menu.ip.hb1=v1.4 Higher Bandwidth -inventone.menu.ip.hb1.build.lwip_lib=-llwip_gcc -inventone.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -inventone.menu.ip.src=v1.4 Compile from source -inventone.menu.ip.src.build.lwip_lib=-llwip_src -inventone.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -inventone.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -inventone.menu.dbg.Disabled=Disabled -inventone.menu.dbg.Disabled.build.debug_port= -inventone.menu.dbg.Serial=Serial -inventone.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -inventone.menu.dbg.Serial1=Serial1 -inventone.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -inventone.menu.lvl.None____=None -inventone.menu.lvl.None____.build.debug_level= -inventone.menu.lvl.SSL=SSL -inventone.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -inventone.menu.lvl.TLS_MEM=TLS_MEM -inventone.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -inventone.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -inventone.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -inventone.menu.lvl.HTTP_SERVER=HTTP_SERVER -inventone.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -inventone.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -inventone.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -inventone.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -inventone.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -inventone.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -inventone.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -inventone.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -inventone.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.CORE=CORE -inventone.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -inventone.menu.lvl.WIFI=WIFI -inventone.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -inventone.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -inventone.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -inventone.menu.lvl.UPDATER=UPDATER -inventone.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -inventone.menu.lvl.OTA=OTA -inventone.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -inventone.menu.lvl.OOM=OOM -inventone.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -inventone.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -inventone.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -inventone.menu.wipe.none=Only Sketch -inventone.menu.wipe.none.upload.erase_cmd= -inventone.menu.wipe.sdk=Sketch + WiFi Settings -inventone.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -inventone.menu.wipe.all=All Flash Contents -inventone.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -inventone.menu.baud.115200=115200 -inventone.menu.baud.115200.upload.speed=115200 -inventone.menu.baud.9600=9600 -inventone.menu.baud.9600.upload.speed=9600 -inventone.menu.baud.57600=57600 -inventone.menu.baud.57600.upload.speed=57600 -inventone.menu.baud.230400.linux=230400 -inventone.menu.baud.230400.macosx=230400 -inventone.menu.baud.230400.upload.speed=230400 -inventone.menu.baud.256000.windows=256000 -inventone.menu.baud.256000.upload.speed=256000 -inventone.menu.baud.460800.linux=460800 -inventone.menu.baud.460800.macosx=460800 -inventone.menu.baud.460800.upload.speed=460800 -inventone.menu.baud.512000.windows=512000 -inventone.menu.baud.512000.upload.speed=512000 -inventone.menu.baud.921600=921600 -inventone.menu.baud.921600.upload.speed=921600 - -############################################################## -cw01.name=XinaBox CW01 -cw01.build.board=ESP8266_GENERIC -cw01.build.variant=xinabox -cw01.upload.tool=esptool -cw01.upload.maximum_data_size=81920 -cw01.upload.wait_for_upload_port=true -cw01.upload.erase_cmd= -cw01.serial.disableDTR=true -cw01.serial.disableRTS=true -cw01.build.mcu=esp8266 -cw01.build.core=esp8266 -cw01.build.spiffs_pagesize=256 -cw01.build.debug_port= -cw01.build.debug_level= -cw01.menu.xtal.80=80 MHz -cw01.menu.xtal.80.build.f_cpu=80000000L -cw01.menu.xtal.160=160 MHz -cw01.menu.xtal.160.build.f_cpu=160000000L -cw01.menu.vt.flash=Flash -cw01.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -cw01.menu.vt.heap=Heap -cw01.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -cw01.menu.vt.iram=IRAM -cw01.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -cw01.menu.exception.enabled=Enabled -cw01.menu.exception.enabled.build.exception_flags=-fexceptions -cw01.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -cw01.menu.exception.disabled=Disabled -cw01.menu.exception.disabled.build.exception_flags=-fno-exceptions -cw01.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -cw01.upload.resetmethod=nodemcu -cw01.menu.CrystalFreq.26=26 MHz -cw01.menu.CrystalFreq.40=40 MHz -cw01.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -cw01.build.flash_mode=qio -cw01.build.flash_freq=40 -cw01.menu.eesz.4M=4M (no SPIFFS) -cw01.menu.eesz.4M.build.flash_size=4M -cw01.menu.eesz.4M.build.flash_size_bytes=0x400000 -cw01.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -cw01.menu.eesz.4M.build.spiffs_pagesize=256 -cw01.menu.eesz.4M.upload.maximum_size=1044464 -cw01.menu.eesz.4M.build.rfcal_addr=0x3FC000 -cw01.menu.eesz.4M1M=4M (1M SPIFFS) -cw01.menu.eesz.4M1M.build.flash_size=4M -cw01.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -cw01.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -cw01.menu.eesz.4M1M.build.spiffs_pagesize=256 -cw01.menu.eesz.4M1M.upload.maximum_size=1044464 -cw01.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -cw01.menu.eesz.4M1M.build.spiffs_start=0x300000 -cw01.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -cw01.menu.eesz.4M1M.build.spiffs_blocksize=8192 -cw01.menu.eesz.4M2M=4M (2M SPIFFS) -cw01.menu.eesz.4M2M.build.flash_size=4M -cw01.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -cw01.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -cw01.menu.eesz.4M2M.build.spiffs_pagesize=256 -cw01.menu.eesz.4M2M.upload.maximum_size=1044464 -cw01.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -cw01.menu.eesz.4M2M.build.spiffs_start=0x200000 -cw01.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -cw01.menu.eesz.4M2M.build.spiffs_blocksize=8192 -cw01.menu.eesz.4M3M=4M (3M SPIFFS) -cw01.menu.eesz.4M3M.build.flash_size=4M -cw01.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -cw01.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -cw01.menu.eesz.4M3M.build.spiffs_pagesize=256 -cw01.menu.eesz.4M3M.upload.maximum_size=1044464 -cw01.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -cw01.menu.eesz.4M3M.build.spiffs_start=0x100000 -cw01.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -cw01.menu.eesz.4M3M.build.spiffs_blocksize=8192 -cw01.menu.ip.lm2f=v2 Lower Memory -cw01.menu.ip.lm2f.build.lwip_include=lwip2/include -cw01.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -cw01.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -cw01.menu.ip.hb2f=v2 Higher Bandwidth -cw01.menu.ip.hb2f.build.lwip_include=lwip2/include -cw01.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -cw01.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -cw01.menu.ip.lm2n=v2 Lower Memory (no features) -cw01.menu.ip.lm2n.build.lwip_include=lwip2/include -cw01.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -cw01.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -cw01.menu.ip.hb2n=v2 Higher Bandwidth (no features) -cw01.menu.ip.hb2n.build.lwip_include=lwip2/include -cw01.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -cw01.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -cw01.menu.ip.lm6f=v2 IPv6 Lower Memory -cw01.menu.ip.lm6f.build.lwip_include=lwip2/include -cw01.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -cw01.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -cw01.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -cw01.menu.ip.hb6f.build.lwip_include=lwip2/include -cw01.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -cw01.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -cw01.menu.ip.hb1=v1.4 Higher Bandwidth -cw01.menu.ip.hb1.build.lwip_lib=-llwip_gcc -cw01.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -cw01.menu.ip.src=v1.4 Compile from source -cw01.menu.ip.src.build.lwip_lib=-llwip_src -cw01.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -cw01.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -cw01.menu.dbg.Disabled=Disabled -cw01.menu.dbg.Disabled.build.debug_port= -cw01.menu.dbg.Serial=Serial -cw01.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -cw01.menu.dbg.Serial1=Serial1 -cw01.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -cw01.menu.lvl.None____=None -cw01.menu.lvl.None____.build.debug_level= -cw01.menu.lvl.SSL=SSL -cw01.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -cw01.menu.lvl.TLS_MEM=TLS_MEM -cw01.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -cw01.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -cw01.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.lvl.HTTP_SERVER=HTTP_SERVER -cw01.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -cw01.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -cw01.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -cw01.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -cw01.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -cw01.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -cw01.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.CORE=CORE -cw01.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -cw01.menu.lvl.WIFI=WIFI -cw01.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -cw01.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -cw01.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -cw01.menu.lvl.UPDATER=UPDATER -cw01.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -cw01.menu.lvl.OTA=OTA -cw01.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -cw01.menu.lvl.OOM=OOM -cw01.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -cw01.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -cw01.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -cw01.menu.wipe.none=Only Sketch -cw01.menu.wipe.none.upload.erase_cmd= -cw01.menu.wipe.sdk=Sketch + WiFi Settings -cw01.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -cw01.menu.wipe.all=All Flash Contents -cw01.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -cw01.menu.baud.115200=115200 -cw01.menu.baud.115200.upload.speed=115200 -cw01.menu.baud.9600=9600 -cw01.menu.baud.9600.upload.speed=9600 -cw01.menu.baud.57600=57600 -cw01.menu.baud.57600.upload.speed=57600 -cw01.menu.baud.230400.linux=230400 -cw01.menu.baud.230400.macosx=230400 -cw01.menu.baud.230400.upload.speed=230400 -cw01.menu.baud.256000.windows=256000 -cw01.menu.baud.256000.upload.speed=256000 -cw01.menu.baud.460800.linux=460800 -cw01.menu.baud.460800.macosx=460800 -cw01.menu.baud.460800.upload.speed=460800 -cw01.menu.baud.512000.windows=512000 -cw01.menu.baud.512000.upload.speed=512000 -cw01.menu.baud.921600=921600 -cw01.menu.baud.921600.upload.speed=921600 - -############################################################## -espresso_lite_v1.name=ESPresso Lite 1.0 -espresso_lite_v1.build.board=ESP8266_ESPRESSO_LITE_V1 -espresso_lite_v1.build.variant=espresso_lite_v1 -espresso_lite_v1.upload.tool=esptool -espresso_lite_v1.upload.maximum_data_size=81920 -espresso_lite_v1.upload.wait_for_upload_port=true -espresso_lite_v1.upload.erase_cmd= -espresso_lite_v1.serial.disableDTR=true -espresso_lite_v1.serial.disableRTS=true -espresso_lite_v1.build.mcu=esp8266 -espresso_lite_v1.build.core=esp8266 -espresso_lite_v1.build.spiffs_pagesize=256 -espresso_lite_v1.build.debug_port= -espresso_lite_v1.build.debug_level= -espresso_lite_v1.menu.xtal.80=80 MHz -espresso_lite_v1.menu.xtal.80.build.f_cpu=80000000L -espresso_lite_v1.menu.xtal.160=160 MHz -espresso_lite_v1.menu.xtal.160.build.f_cpu=160000000L -espresso_lite_v1.menu.vt.flash=Flash -espresso_lite_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espresso_lite_v1.menu.vt.heap=Heap -espresso_lite_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espresso_lite_v1.menu.vt.iram=IRAM -espresso_lite_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espresso_lite_v1.menu.exception.enabled=Enabled -espresso_lite_v1.menu.exception.enabled.build.exception_flags=-fexceptions -espresso_lite_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -espresso_lite_v1.menu.exception.disabled=Disabled -espresso_lite_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions -espresso_lite_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -espresso_lite_v1.build.flash_mode=dio -espresso_lite_v1.build.flash_freq=40 -espresso_lite_v1.menu.eesz.4M=4M (no SPIFFS) -espresso_lite_v1.menu.eesz.4M.build.flash_size=4M -espresso_lite_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v1.menu.eesz.4M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.eesz.4M.upload.maximum_size=1044464 -espresso_lite_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.eesz.4M1M=4M (1M SPIFFS) -espresso_lite_v1.menu.eesz.4M1M.build.flash_size=4M -espresso_lite_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.eesz.4M1M.upload.maximum_size=1044464 -espresso_lite_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 -espresso_lite_v1.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.eesz.4M2M=4M (2M SPIFFS) -espresso_lite_v1.menu.eesz.4M2M.build.flash_size=4M -espresso_lite_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espresso_lite_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.eesz.4M2M.upload.maximum_size=1044464 -espresso_lite_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 -espresso_lite_v1.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.eesz.4M3M=4M (3M SPIFFS) -espresso_lite_v1.menu.eesz.4M3M.build.flash_size=4M -espresso_lite_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espresso_lite_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.eesz.4M3M.upload.maximum_size=1044464 -espresso_lite_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 -espresso_lite_v1.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.ResetMethod.ck=ck -espresso_lite_v1.menu.ResetMethod.ck.upload.resetmethod=ck -espresso_lite_v1.menu.ResetMethod.nodemcu=nodemcu -espresso_lite_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espresso_lite_v1.menu.ip.lm2f=v2 Lower Memory -espresso_lite_v1.menu.ip.lm2f.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espresso_lite_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espresso_lite_v1.menu.ip.hb2f=v2 Higher Bandwidth -espresso_lite_v1.menu.ip.hb2f.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espresso_lite_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espresso_lite_v1.menu.ip.lm2n=v2 Lower Memory (no features) -espresso_lite_v1.menu.ip.lm2n.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espresso_lite_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espresso_lite_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espresso_lite_v1.menu.ip.hb2n.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espresso_lite_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espresso_lite_v1.menu.ip.lm6f=v2 IPv6 Lower Memory -espresso_lite_v1.menu.ip.lm6f.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espresso_lite_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espresso_lite_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espresso_lite_v1.menu.ip.hb6f.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espresso_lite_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espresso_lite_v1.menu.ip.hb1=v1.4 Higher Bandwidth -espresso_lite_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espresso_lite_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v1.menu.ip.src=v1.4 Compile from source -espresso_lite_v1.menu.ip.src.build.lwip_lib=-llwip_src -espresso_lite_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espresso_lite_v1.menu.dbg.Disabled=Disabled -espresso_lite_v1.menu.dbg.Disabled.build.debug_port= -espresso_lite_v1.menu.dbg.Serial=Serial -espresso_lite_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v1.menu.dbg.Serial1=Serial1 -espresso_lite_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espresso_lite_v1.menu.lvl.None____=None -espresso_lite_v1.menu.lvl.None____.build.debug_level= -espresso_lite_v1.menu.lvl.SSL=SSL -espresso_lite_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espresso_lite_v1.menu.lvl.TLS_MEM=TLS_MEM -espresso_lite_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espresso_lite_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espresso_lite_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER -espresso_lite_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espresso_lite_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.CORE=CORE -espresso_lite_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espresso_lite_v1.menu.lvl.WIFI=WIFI -espresso_lite_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espresso_lite_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espresso_lite_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v1.menu.lvl.UPDATER=UPDATER -espresso_lite_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espresso_lite_v1.menu.lvl.OTA=OTA -espresso_lite_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espresso_lite_v1.menu.lvl.OOM=OOM -espresso_lite_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espresso_lite_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espresso_lite_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espresso_lite_v1.menu.wipe.none=Only Sketch -espresso_lite_v1.menu.wipe.none.upload.erase_cmd= -espresso_lite_v1.menu.wipe.sdk=Sketch + WiFi Settings -espresso_lite_v1.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espresso_lite_v1.menu.wipe.all=All Flash Contents -espresso_lite_v1.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espresso_lite_v1.menu.baud.115200=115200 -espresso_lite_v1.menu.baud.115200.upload.speed=115200 -espresso_lite_v1.menu.baud.9600=9600 -espresso_lite_v1.menu.baud.9600.upload.speed=9600 -espresso_lite_v1.menu.baud.57600=57600 -espresso_lite_v1.menu.baud.57600.upload.speed=57600 -espresso_lite_v1.menu.baud.230400.linux=230400 -espresso_lite_v1.menu.baud.230400.macosx=230400 -espresso_lite_v1.menu.baud.230400.upload.speed=230400 -espresso_lite_v1.menu.baud.256000.windows=256000 -espresso_lite_v1.menu.baud.256000.upload.speed=256000 -espresso_lite_v1.menu.baud.460800.linux=460800 -espresso_lite_v1.menu.baud.460800.macosx=460800 -espresso_lite_v1.menu.baud.460800.upload.speed=460800 -espresso_lite_v1.menu.baud.512000.windows=512000 -espresso_lite_v1.menu.baud.512000.upload.speed=512000 -espresso_lite_v1.menu.baud.921600=921600 -espresso_lite_v1.menu.baud.921600.upload.speed=921600 - -############################################################## -espresso_lite_v2.name=ESPresso Lite 2.0 -espresso_lite_v2.build.board=ESP8266_ESPRESSO_LITE_V2 -espresso_lite_v2.build.variant=espresso_lite_v2 -espresso_lite_v2.upload.tool=esptool -espresso_lite_v2.upload.maximum_data_size=81920 -espresso_lite_v2.upload.wait_for_upload_port=true -espresso_lite_v2.upload.erase_cmd= -espresso_lite_v2.serial.disableDTR=true -espresso_lite_v2.serial.disableRTS=true -espresso_lite_v2.build.mcu=esp8266 -espresso_lite_v2.build.core=esp8266 -espresso_lite_v2.build.spiffs_pagesize=256 -espresso_lite_v2.build.debug_port= -espresso_lite_v2.build.debug_level= -espresso_lite_v2.menu.xtal.80=80 MHz -espresso_lite_v2.menu.xtal.80.build.f_cpu=80000000L -espresso_lite_v2.menu.xtal.160=160 MHz -espresso_lite_v2.menu.xtal.160.build.f_cpu=160000000L -espresso_lite_v2.menu.vt.flash=Flash -espresso_lite_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espresso_lite_v2.menu.vt.heap=Heap -espresso_lite_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espresso_lite_v2.menu.vt.iram=IRAM -espresso_lite_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espresso_lite_v2.menu.exception.enabled=Enabled -espresso_lite_v2.menu.exception.enabled.build.exception_flags=-fexceptions -espresso_lite_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -espresso_lite_v2.menu.exception.disabled=Disabled -espresso_lite_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions -espresso_lite_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -espresso_lite_v2.build.flash_mode=dio -espresso_lite_v2.build.flash_freq=40 -espresso_lite_v2.menu.eesz.4M=4M (no SPIFFS) -espresso_lite_v2.menu.eesz.4M.build.flash_size=4M -espresso_lite_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v2.menu.eesz.4M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.eesz.4M.upload.maximum_size=1044464 -espresso_lite_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.eesz.4M1M=4M (1M SPIFFS) -espresso_lite_v2.menu.eesz.4M1M.build.flash_size=4M -espresso_lite_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.eesz.4M1M.upload.maximum_size=1044464 -espresso_lite_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 -espresso_lite_v2.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.eesz.4M2M=4M (2M SPIFFS) -espresso_lite_v2.menu.eesz.4M2M.build.flash_size=4M -espresso_lite_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espresso_lite_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.eesz.4M2M.upload.maximum_size=1044464 -espresso_lite_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 -espresso_lite_v2.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.eesz.4M3M=4M (3M SPIFFS) -espresso_lite_v2.menu.eesz.4M3M.build.flash_size=4M -espresso_lite_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espresso_lite_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.eesz.4M3M.upload.maximum_size=1044464 -espresso_lite_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 -espresso_lite_v2.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.ResetMethod.ck=ck -espresso_lite_v2.menu.ResetMethod.ck.upload.resetmethod=ck -espresso_lite_v2.menu.ResetMethod.nodemcu=nodemcu -espresso_lite_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espresso_lite_v2.menu.ip.lm2f=v2 Lower Memory -espresso_lite_v2.menu.ip.lm2f.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espresso_lite_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espresso_lite_v2.menu.ip.hb2f=v2 Higher Bandwidth -espresso_lite_v2.menu.ip.hb2f.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espresso_lite_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espresso_lite_v2.menu.ip.lm2n=v2 Lower Memory (no features) -espresso_lite_v2.menu.ip.lm2n.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espresso_lite_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espresso_lite_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espresso_lite_v2.menu.ip.hb2n.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espresso_lite_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espresso_lite_v2.menu.ip.lm6f=v2 IPv6 Lower Memory -espresso_lite_v2.menu.ip.lm6f.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espresso_lite_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espresso_lite_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espresso_lite_v2.menu.ip.hb6f.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espresso_lite_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espresso_lite_v2.menu.ip.hb1=v1.4 Higher Bandwidth -espresso_lite_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espresso_lite_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v2.menu.ip.src=v1.4 Compile from source -espresso_lite_v2.menu.ip.src.build.lwip_lib=-llwip_src -espresso_lite_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espresso_lite_v2.menu.dbg.Disabled=Disabled -espresso_lite_v2.menu.dbg.Disabled.build.debug_port= -espresso_lite_v2.menu.dbg.Serial=Serial -espresso_lite_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v2.menu.dbg.Serial1=Serial1 -espresso_lite_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espresso_lite_v2.menu.lvl.None____=None -espresso_lite_v2.menu.lvl.None____.build.debug_level= -espresso_lite_v2.menu.lvl.SSL=SSL -espresso_lite_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espresso_lite_v2.menu.lvl.TLS_MEM=TLS_MEM -espresso_lite_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espresso_lite_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espresso_lite_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER -espresso_lite_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espresso_lite_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.CORE=CORE -espresso_lite_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espresso_lite_v2.menu.lvl.WIFI=WIFI -espresso_lite_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espresso_lite_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espresso_lite_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v2.menu.lvl.UPDATER=UPDATER -espresso_lite_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espresso_lite_v2.menu.lvl.OTA=OTA -espresso_lite_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espresso_lite_v2.menu.lvl.OOM=OOM -espresso_lite_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espresso_lite_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espresso_lite_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espresso_lite_v2.menu.wipe.none=Only Sketch -espresso_lite_v2.menu.wipe.none.upload.erase_cmd= -espresso_lite_v2.menu.wipe.sdk=Sketch + WiFi Settings -espresso_lite_v2.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espresso_lite_v2.menu.wipe.all=All Flash Contents -espresso_lite_v2.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espresso_lite_v2.menu.baud.115200=115200 -espresso_lite_v2.menu.baud.115200.upload.speed=115200 -espresso_lite_v2.menu.baud.9600=9600 -espresso_lite_v2.menu.baud.9600.upload.speed=9600 -espresso_lite_v2.menu.baud.57600=57600 -espresso_lite_v2.menu.baud.57600.upload.speed=57600 -espresso_lite_v2.menu.baud.230400.linux=230400 -espresso_lite_v2.menu.baud.230400.macosx=230400 -espresso_lite_v2.menu.baud.230400.upload.speed=230400 -espresso_lite_v2.menu.baud.256000.windows=256000 -espresso_lite_v2.menu.baud.256000.upload.speed=256000 -espresso_lite_v2.menu.baud.460800.linux=460800 -espresso_lite_v2.menu.baud.460800.macosx=460800 -espresso_lite_v2.menu.baud.460800.upload.speed=460800 -espresso_lite_v2.menu.baud.512000.windows=512000 -espresso_lite_v2.menu.baud.512000.upload.speed=512000 -espresso_lite_v2.menu.baud.921600=921600 -espresso_lite_v2.menu.baud.921600.upload.speed=921600 - -############################################################## -phoenix_v1.name=Phoenix 1.0 -phoenix_v1.build.board=ESP8266_PHOENIX_V1 -phoenix_v1.build.variant=phoenix_v1 -phoenix_v1.upload.tool=esptool -phoenix_v1.upload.maximum_data_size=81920 -phoenix_v1.upload.wait_for_upload_port=true -phoenix_v1.upload.erase_cmd= -phoenix_v1.serial.disableDTR=true -phoenix_v1.serial.disableRTS=true -phoenix_v1.build.mcu=esp8266 -phoenix_v1.build.core=esp8266 -phoenix_v1.build.spiffs_pagesize=256 -phoenix_v1.build.debug_port= -phoenix_v1.build.debug_level= -phoenix_v1.menu.xtal.80=80 MHz -phoenix_v1.menu.xtal.80.build.f_cpu=80000000L -phoenix_v1.menu.xtal.160=160 MHz -phoenix_v1.menu.xtal.160.build.f_cpu=160000000L -phoenix_v1.menu.vt.flash=Flash -phoenix_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -phoenix_v1.menu.vt.heap=Heap -phoenix_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -phoenix_v1.menu.vt.iram=IRAM -phoenix_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -phoenix_v1.menu.exception.enabled=Enabled -phoenix_v1.menu.exception.enabled.build.exception_flags=-fexceptions -phoenix_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -phoenix_v1.menu.exception.disabled=Disabled -phoenix_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions -phoenix_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -phoenix_v1.build.flash_mode=dio -phoenix_v1.build.flash_freq=40 -phoenix_v1.menu.eesz.4M=4M (no SPIFFS) -phoenix_v1.menu.eesz.4M.build.flash_size=4M -phoenix_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -phoenix_v1.menu.eesz.4M.build.spiffs_pagesize=256 -phoenix_v1.menu.eesz.4M.upload.maximum_size=1044464 -phoenix_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.eesz.4M1M=4M (1M SPIFFS) -phoenix_v1.menu.eesz.4M1M.build.flash_size=4M -phoenix_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 -phoenix_v1.menu.eesz.4M1M.upload.maximum_size=1044464 -phoenix_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 -phoenix_v1.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 -phoenix_v1.menu.eesz.4M2M=4M (2M SPIFFS) -phoenix_v1.menu.eesz.4M2M.build.flash_size=4M -phoenix_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -phoenix_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 -phoenix_v1.menu.eesz.4M2M.upload.maximum_size=1044464 -phoenix_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 -phoenix_v1.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 -phoenix_v1.menu.eesz.4M3M=4M (3M SPIFFS) -phoenix_v1.menu.eesz.4M3M.build.flash_size=4M -phoenix_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -phoenix_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 -phoenix_v1.menu.eesz.4M3M.upload.maximum_size=1044464 -phoenix_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 -phoenix_v1.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 -phoenix_v1.menu.ResetMethod.ck=ck -phoenix_v1.menu.ResetMethod.ck.upload.resetmethod=ck -phoenix_v1.menu.ResetMethod.nodemcu=nodemcu -phoenix_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -phoenix_v1.menu.ip.lm2f=v2 Lower Memory -phoenix_v1.menu.ip.lm2f.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -phoenix_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -phoenix_v1.menu.ip.hb2f=v2 Higher Bandwidth -phoenix_v1.menu.ip.hb2f.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -phoenix_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -phoenix_v1.menu.ip.lm2n=v2 Lower Memory (no features) -phoenix_v1.menu.ip.lm2n.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -phoenix_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -phoenix_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) -phoenix_v1.menu.ip.hb2n.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -phoenix_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -phoenix_v1.menu.ip.lm6f=v2 IPv6 Lower Memory -phoenix_v1.menu.ip.lm6f.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -phoenix_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -phoenix_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -phoenix_v1.menu.ip.hb6f.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -phoenix_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -phoenix_v1.menu.ip.hb1=v1.4 Higher Bandwidth -phoenix_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc -phoenix_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v1.menu.ip.src=v1.4 Compile from source -phoenix_v1.menu.ip.src.build.lwip_lib=-llwip_src -phoenix_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -phoenix_v1.menu.dbg.Disabled=Disabled -phoenix_v1.menu.dbg.Disabled.build.debug_port= -phoenix_v1.menu.dbg.Serial=Serial -phoenix_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v1.menu.dbg.Serial1=Serial1 -phoenix_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -phoenix_v1.menu.lvl.None____=None -phoenix_v1.menu.lvl.None____.build.debug_level= -phoenix_v1.menu.lvl.SSL=SSL -phoenix_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -phoenix_v1.menu.lvl.TLS_MEM=TLS_MEM -phoenix_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -phoenix_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -phoenix_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER -phoenix_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -phoenix_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -phoenix_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -phoenix_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -phoenix_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.CORE=CORE -phoenix_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -phoenix_v1.menu.lvl.WIFI=WIFI -phoenix_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -phoenix_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -phoenix_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -phoenix_v1.menu.lvl.UPDATER=UPDATER -phoenix_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -phoenix_v1.menu.lvl.OTA=OTA -phoenix_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -phoenix_v1.menu.lvl.OOM=OOM -phoenix_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -phoenix_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -phoenix_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -phoenix_v1.menu.wipe.none=Only Sketch -phoenix_v1.menu.wipe.none.upload.erase_cmd= -phoenix_v1.menu.wipe.sdk=Sketch + WiFi Settings -phoenix_v1.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -phoenix_v1.menu.wipe.all=All Flash Contents -phoenix_v1.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -phoenix_v1.menu.baud.115200=115200 -phoenix_v1.menu.baud.115200.upload.speed=115200 -phoenix_v1.menu.baud.9600=9600 -phoenix_v1.menu.baud.9600.upload.speed=9600 -phoenix_v1.menu.baud.57600=57600 -phoenix_v1.menu.baud.57600.upload.speed=57600 -phoenix_v1.menu.baud.230400.linux=230400 -phoenix_v1.menu.baud.230400.macosx=230400 -phoenix_v1.menu.baud.230400.upload.speed=230400 -phoenix_v1.menu.baud.256000.windows=256000 -phoenix_v1.menu.baud.256000.upload.speed=256000 -phoenix_v1.menu.baud.460800.linux=460800 -phoenix_v1.menu.baud.460800.macosx=460800 -phoenix_v1.menu.baud.460800.upload.speed=460800 -phoenix_v1.menu.baud.512000.windows=512000 -phoenix_v1.menu.baud.512000.upload.speed=512000 -phoenix_v1.menu.baud.921600=921600 -phoenix_v1.menu.baud.921600.upload.speed=921600 - -############################################################## -phoenix_v2.name=Phoenix 2.0 -phoenix_v2.build.board=ESP8266_PHOENIX_V2 -phoenix_v2.build.variant=phoenix_v2 -phoenix_v2.upload.tool=esptool -phoenix_v2.upload.maximum_data_size=81920 -phoenix_v2.upload.wait_for_upload_port=true -phoenix_v2.upload.erase_cmd= -phoenix_v2.serial.disableDTR=true -phoenix_v2.serial.disableRTS=true -phoenix_v2.build.mcu=esp8266 -phoenix_v2.build.core=esp8266 -phoenix_v2.build.spiffs_pagesize=256 -phoenix_v2.build.debug_port= -phoenix_v2.build.debug_level= -phoenix_v2.menu.xtal.80=80 MHz -phoenix_v2.menu.xtal.80.build.f_cpu=80000000L -phoenix_v2.menu.xtal.160=160 MHz -phoenix_v2.menu.xtal.160.build.f_cpu=160000000L -phoenix_v2.menu.vt.flash=Flash -phoenix_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -phoenix_v2.menu.vt.heap=Heap -phoenix_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -phoenix_v2.menu.vt.iram=IRAM -phoenix_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -phoenix_v2.menu.exception.enabled=Enabled -phoenix_v2.menu.exception.enabled.build.exception_flags=-fexceptions -phoenix_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -phoenix_v2.menu.exception.disabled=Disabled -phoenix_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions -phoenix_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -phoenix_v2.build.flash_mode=dio -phoenix_v2.build.flash_freq=40 -phoenix_v2.menu.eesz.4M=4M (no SPIFFS) -phoenix_v2.menu.eesz.4M.build.flash_size=4M -phoenix_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -phoenix_v2.menu.eesz.4M.build.spiffs_pagesize=256 -phoenix_v2.menu.eesz.4M.upload.maximum_size=1044464 -phoenix_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.eesz.4M1M=4M (1M SPIFFS) -phoenix_v2.menu.eesz.4M1M.build.flash_size=4M -phoenix_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 -phoenix_v2.menu.eesz.4M1M.upload.maximum_size=1044464 -phoenix_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 -phoenix_v2.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 -phoenix_v2.menu.eesz.4M2M=4M (2M SPIFFS) -phoenix_v2.menu.eesz.4M2M.build.flash_size=4M -phoenix_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -phoenix_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 -phoenix_v2.menu.eesz.4M2M.upload.maximum_size=1044464 -phoenix_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 -phoenix_v2.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 -phoenix_v2.menu.eesz.4M3M=4M (3M SPIFFS) -phoenix_v2.menu.eesz.4M3M.build.flash_size=4M -phoenix_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -phoenix_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 -phoenix_v2.menu.eesz.4M3M.upload.maximum_size=1044464 -phoenix_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 -phoenix_v2.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 -phoenix_v2.menu.ResetMethod.ck=ck -phoenix_v2.menu.ResetMethod.ck.upload.resetmethod=ck -phoenix_v2.menu.ResetMethod.nodemcu=nodemcu -phoenix_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -phoenix_v2.menu.ip.lm2f=v2 Lower Memory -phoenix_v2.menu.ip.lm2f.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -phoenix_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -phoenix_v2.menu.ip.hb2f=v2 Higher Bandwidth -phoenix_v2.menu.ip.hb2f.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -phoenix_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -phoenix_v2.menu.ip.lm2n=v2 Lower Memory (no features) -phoenix_v2.menu.ip.lm2n.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -phoenix_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -phoenix_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) -phoenix_v2.menu.ip.hb2n.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -phoenix_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -phoenix_v2.menu.ip.lm6f=v2 IPv6 Lower Memory -phoenix_v2.menu.ip.lm6f.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -phoenix_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -phoenix_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -phoenix_v2.menu.ip.hb6f.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -phoenix_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -phoenix_v2.menu.ip.hb1=v1.4 Higher Bandwidth -phoenix_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc -phoenix_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v2.menu.ip.src=v1.4 Compile from source -phoenix_v2.menu.ip.src.build.lwip_lib=-llwip_src -phoenix_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -phoenix_v2.menu.dbg.Disabled=Disabled -phoenix_v2.menu.dbg.Disabled.build.debug_port= -phoenix_v2.menu.dbg.Serial=Serial -phoenix_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v2.menu.dbg.Serial1=Serial1 -phoenix_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -phoenix_v2.menu.lvl.None____=None -phoenix_v2.menu.lvl.None____.build.debug_level= -phoenix_v2.menu.lvl.SSL=SSL -phoenix_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -phoenix_v2.menu.lvl.TLS_MEM=TLS_MEM -phoenix_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -phoenix_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -phoenix_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER -phoenix_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -phoenix_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -phoenix_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -phoenix_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -phoenix_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.CORE=CORE -phoenix_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -phoenix_v2.menu.lvl.WIFI=WIFI -phoenix_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -phoenix_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -phoenix_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -phoenix_v2.menu.lvl.UPDATER=UPDATER -phoenix_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -phoenix_v2.menu.lvl.OTA=OTA -phoenix_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -phoenix_v2.menu.lvl.OOM=OOM -phoenix_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -phoenix_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -phoenix_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -phoenix_v2.menu.wipe.none=Only Sketch -phoenix_v2.menu.wipe.none.upload.erase_cmd= -phoenix_v2.menu.wipe.sdk=Sketch + WiFi Settings -phoenix_v2.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -phoenix_v2.menu.wipe.all=All Flash Contents -phoenix_v2.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -phoenix_v2.menu.baud.115200=115200 -phoenix_v2.menu.baud.115200.upload.speed=115200 -phoenix_v2.menu.baud.9600=9600 -phoenix_v2.menu.baud.9600.upload.speed=9600 -phoenix_v2.menu.baud.57600=57600 -phoenix_v2.menu.baud.57600.upload.speed=57600 -phoenix_v2.menu.baud.230400.linux=230400 -phoenix_v2.menu.baud.230400.macosx=230400 -phoenix_v2.menu.baud.230400.upload.speed=230400 -phoenix_v2.menu.baud.256000.windows=256000 -phoenix_v2.menu.baud.256000.upload.speed=256000 -phoenix_v2.menu.baud.460800.linux=460800 -phoenix_v2.menu.baud.460800.macosx=460800 -phoenix_v2.menu.baud.460800.upload.speed=460800 -phoenix_v2.menu.baud.512000.windows=512000 -phoenix_v2.menu.baud.512000.upload.speed=512000 -phoenix_v2.menu.baud.921600=921600 -phoenix_v2.menu.baud.921600.upload.speed=921600 - -############################################################## -nodemcu.name=NodeMCU 0.9 (ESP-12 Module) -nodemcu.build.board=ESP8266_NODEMCU -nodemcu.build.variant=nodemcu -nodemcu.upload.tool=esptool -nodemcu.upload.maximum_data_size=81920 -nodemcu.upload.wait_for_upload_port=true -nodemcu.upload.erase_cmd= -nodemcu.serial.disableDTR=true -nodemcu.serial.disableRTS=true -nodemcu.build.mcu=esp8266 -nodemcu.build.core=esp8266 -nodemcu.build.spiffs_pagesize=256 -nodemcu.build.debug_port= -nodemcu.build.debug_level= -nodemcu.menu.xtal.80=80 MHz -nodemcu.menu.xtal.80.build.f_cpu=80000000L -nodemcu.menu.xtal.160=160 MHz -nodemcu.menu.xtal.160.build.f_cpu=160000000L -nodemcu.menu.vt.flash=Flash -nodemcu.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -nodemcu.menu.vt.heap=Heap -nodemcu.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -nodemcu.menu.vt.iram=IRAM -nodemcu.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -nodemcu.menu.exception.enabled=Enabled -nodemcu.menu.exception.enabled.build.exception_flags=-fexceptions -nodemcu.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -nodemcu.menu.exception.disabled=Disabled -nodemcu.menu.exception.disabled.build.exception_flags=-fno-exceptions -nodemcu.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -nodemcu.upload.resetmethod=nodemcu -nodemcu.build.flash_mode=qio -nodemcu.build.flash_freq=40 -nodemcu.menu.eesz.4M=4M (no SPIFFS) -nodemcu.menu.eesz.4M.build.flash_size=4M -nodemcu.menu.eesz.4M.build.flash_size_bytes=0x400000 -nodemcu.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -nodemcu.menu.eesz.4M.build.spiffs_pagesize=256 -nodemcu.menu.eesz.4M.upload.maximum_size=1044464 -nodemcu.menu.eesz.4M.build.rfcal_addr=0x3FC000 -nodemcu.menu.eesz.4M1M=4M (1M SPIFFS) -nodemcu.menu.eesz.4M1M.build.flash_size=4M -nodemcu.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -nodemcu.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcu.menu.eesz.4M1M.build.spiffs_pagesize=256 -nodemcu.menu.eesz.4M1M.upload.maximum_size=1044464 -nodemcu.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -nodemcu.menu.eesz.4M1M.build.spiffs_start=0x300000 -nodemcu.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -nodemcu.menu.eesz.4M1M.build.spiffs_blocksize=8192 -nodemcu.menu.eesz.4M2M=4M (2M SPIFFS) -nodemcu.menu.eesz.4M2M.build.flash_size=4M -nodemcu.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -nodemcu.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -nodemcu.menu.eesz.4M2M.build.spiffs_pagesize=256 -nodemcu.menu.eesz.4M2M.upload.maximum_size=1044464 -nodemcu.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -nodemcu.menu.eesz.4M2M.build.spiffs_start=0x200000 -nodemcu.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -nodemcu.menu.eesz.4M2M.build.spiffs_blocksize=8192 -nodemcu.menu.eesz.4M3M=4M (3M SPIFFS) -nodemcu.menu.eesz.4M3M.build.flash_size=4M -nodemcu.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -nodemcu.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -nodemcu.menu.eesz.4M3M.build.spiffs_pagesize=256 -nodemcu.menu.eesz.4M3M.upload.maximum_size=1044464 -nodemcu.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -nodemcu.menu.eesz.4M3M.build.spiffs_start=0x100000 -nodemcu.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -nodemcu.menu.eesz.4M3M.build.spiffs_blocksize=8192 -nodemcu.menu.ip.lm2f=v2 Lower Memory -nodemcu.menu.ip.lm2f.build.lwip_include=lwip2/include -nodemcu.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -nodemcu.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -nodemcu.menu.ip.hb2f=v2 Higher Bandwidth -nodemcu.menu.ip.hb2f.build.lwip_include=lwip2/include -nodemcu.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -nodemcu.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -nodemcu.menu.ip.lm2n=v2 Lower Memory (no features) -nodemcu.menu.ip.lm2n.build.lwip_include=lwip2/include -nodemcu.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -nodemcu.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -nodemcu.menu.ip.hb2n=v2 Higher Bandwidth (no features) -nodemcu.menu.ip.hb2n.build.lwip_include=lwip2/include -nodemcu.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -nodemcu.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -nodemcu.menu.ip.lm6f=v2 IPv6 Lower Memory -nodemcu.menu.ip.lm6f.build.lwip_include=lwip2/include -nodemcu.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -nodemcu.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -nodemcu.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -nodemcu.menu.ip.hb6f.build.lwip_include=lwip2/include -nodemcu.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -nodemcu.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -nodemcu.menu.ip.hb1=v1.4 Higher Bandwidth -nodemcu.menu.ip.hb1.build.lwip_lib=-llwip_gcc -nodemcu.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcu.menu.ip.src=v1.4 Compile from source -nodemcu.menu.ip.src.build.lwip_lib=-llwip_src -nodemcu.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcu.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -nodemcu.menu.dbg.Disabled=Disabled -nodemcu.menu.dbg.Disabled.build.debug_port= -nodemcu.menu.dbg.Serial=Serial -nodemcu.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -nodemcu.menu.dbg.Serial1=Serial1 -nodemcu.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -nodemcu.menu.lvl.None____=None -nodemcu.menu.lvl.None____.build.debug_level= -nodemcu.menu.lvl.SSL=SSL -nodemcu.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -nodemcu.menu.lvl.TLS_MEM=TLS_MEM -nodemcu.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -nodemcu.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -nodemcu.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.lvl.HTTP_SERVER=HTTP_SERVER -nodemcu.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -nodemcu.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -nodemcu.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -nodemcu.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -nodemcu.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -nodemcu.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.CORE=CORE -nodemcu.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -nodemcu.menu.lvl.WIFI=WIFI -nodemcu.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -nodemcu.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -nodemcu.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -nodemcu.menu.lvl.UPDATER=UPDATER -nodemcu.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -nodemcu.menu.lvl.OTA=OTA -nodemcu.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -nodemcu.menu.lvl.OOM=OOM -nodemcu.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -nodemcu.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -nodemcu.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -nodemcu.menu.wipe.none=Only Sketch -nodemcu.menu.wipe.none.upload.erase_cmd= -nodemcu.menu.wipe.sdk=Sketch + WiFi Settings -nodemcu.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -nodemcu.menu.wipe.all=All Flash Contents -nodemcu.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -nodemcu.menu.baud.115200=115200 -nodemcu.menu.baud.115200.upload.speed=115200 -nodemcu.menu.baud.9600=9600 -nodemcu.menu.baud.9600.upload.speed=9600 -nodemcu.menu.baud.57600=57600 -nodemcu.menu.baud.57600.upload.speed=57600 -nodemcu.menu.baud.230400.linux=230400 -nodemcu.menu.baud.230400.macosx=230400 -nodemcu.menu.baud.230400.upload.speed=230400 -nodemcu.menu.baud.256000.windows=256000 -nodemcu.menu.baud.256000.upload.speed=256000 -nodemcu.menu.baud.460800.linux=460800 -nodemcu.menu.baud.460800.macosx=460800 -nodemcu.menu.baud.460800.upload.speed=460800 -nodemcu.menu.baud.512000.windows=512000 -nodemcu.menu.baud.512000.upload.speed=512000 -nodemcu.menu.baud.921600=921600 -nodemcu.menu.baud.921600.upload.speed=921600 - -############################################################## -nodemcuv2.name=NodeMCU 1.0 (ESP-12E Module) -nodemcuv2.build.board=ESP8266_NODEMCU -nodemcuv2.build.variant=nodemcu -nodemcuv2.upload.tool=esptool -nodemcuv2.upload.maximum_data_size=81920 -nodemcuv2.upload.wait_for_upload_port=true -nodemcuv2.upload.erase_cmd= -nodemcuv2.serial.disableDTR=true -nodemcuv2.serial.disableRTS=true -nodemcuv2.build.mcu=esp8266 -nodemcuv2.build.core=esp8266 -nodemcuv2.build.spiffs_pagesize=256 -nodemcuv2.build.debug_port= -nodemcuv2.build.debug_level= -nodemcuv2.menu.xtal.80=80 MHz -nodemcuv2.menu.xtal.80.build.f_cpu=80000000L -nodemcuv2.menu.xtal.160=160 MHz -nodemcuv2.menu.xtal.160.build.f_cpu=160000000L -nodemcuv2.menu.vt.flash=Flash -nodemcuv2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -nodemcuv2.menu.vt.heap=Heap -nodemcuv2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -nodemcuv2.menu.vt.iram=IRAM -nodemcuv2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -nodemcuv2.menu.exception.enabled=Enabled -nodemcuv2.menu.exception.enabled.build.exception_flags=-fexceptions -nodemcuv2.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -nodemcuv2.menu.exception.disabled=Disabled -nodemcuv2.menu.exception.disabled.build.exception_flags=-fno-exceptions -nodemcuv2.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -nodemcuv2.upload.resetmethod=nodemcu -nodemcuv2.build.flash_mode=dio -nodemcuv2.build.flash_freq=40 -nodemcuv2.menu.eesz.4M=4M (no SPIFFS) -nodemcuv2.menu.eesz.4M.build.flash_size=4M -nodemcuv2.menu.eesz.4M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -nodemcuv2.menu.eesz.4M.build.spiffs_pagesize=256 -nodemcuv2.menu.eesz.4M.upload.maximum_size=1044464 -nodemcuv2.menu.eesz.4M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.eesz.4M1M=4M (1M SPIFFS) -nodemcuv2.menu.eesz.4M1M.build.flash_size=4M -nodemcuv2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcuv2.menu.eesz.4M1M.build.spiffs_pagesize=256 -nodemcuv2.menu.eesz.4M1M.upload.maximum_size=1044464 -nodemcuv2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.eesz.4M1M.build.spiffs_start=0x300000 -nodemcuv2.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.eesz.4M1M.build.spiffs_blocksize=8192 -nodemcuv2.menu.eesz.4M2M=4M (2M SPIFFS) -nodemcuv2.menu.eesz.4M2M.build.flash_size=4M -nodemcuv2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -nodemcuv2.menu.eesz.4M2M.build.spiffs_pagesize=256 -nodemcuv2.menu.eesz.4M2M.upload.maximum_size=1044464 -nodemcuv2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.eesz.4M2M.build.spiffs_start=0x200000 -nodemcuv2.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.eesz.4M2M.build.spiffs_blocksize=8192 -nodemcuv2.menu.eesz.4M3M=4M (3M SPIFFS) -nodemcuv2.menu.eesz.4M3M.build.flash_size=4M -nodemcuv2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -nodemcuv2.menu.eesz.4M3M.build.spiffs_pagesize=256 -nodemcuv2.menu.eesz.4M3M.upload.maximum_size=1044464 -nodemcuv2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.eesz.4M3M.build.spiffs_start=0x100000 -nodemcuv2.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.eesz.4M3M.build.spiffs_blocksize=8192 -nodemcuv2.menu.ip.lm2f=v2 Lower Memory -nodemcuv2.menu.ip.lm2f.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -nodemcuv2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -nodemcuv2.menu.ip.hb2f=v2 Higher Bandwidth -nodemcuv2.menu.ip.hb2f.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -nodemcuv2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -nodemcuv2.menu.ip.lm2n=v2 Lower Memory (no features) -nodemcuv2.menu.ip.lm2n.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -nodemcuv2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -nodemcuv2.menu.ip.hb2n=v2 Higher Bandwidth (no features) -nodemcuv2.menu.ip.hb2n.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -nodemcuv2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -nodemcuv2.menu.ip.lm6f=v2 IPv6 Lower Memory -nodemcuv2.menu.ip.lm6f.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -nodemcuv2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -nodemcuv2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -nodemcuv2.menu.ip.hb6f.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -nodemcuv2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -nodemcuv2.menu.ip.hb1=v1.4 Higher Bandwidth -nodemcuv2.menu.ip.hb1.build.lwip_lib=-llwip_gcc -nodemcuv2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcuv2.menu.ip.src=v1.4 Compile from source -nodemcuv2.menu.ip.src.build.lwip_lib=-llwip_src -nodemcuv2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcuv2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -nodemcuv2.menu.dbg.Disabled=Disabled -nodemcuv2.menu.dbg.Disabled.build.debug_port= -nodemcuv2.menu.dbg.Serial=Serial -nodemcuv2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -nodemcuv2.menu.dbg.Serial1=Serial1 -nodemcuv2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -nodemcuv2.menu.lvl.None____=None -nodemcuv2.menu.lvl.None____.build.debug_level= -nodemcuv2.menu.lvl.SSL=SSL -nodemcuv2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -nodemcuv2.menu.lvl.TLS_MEM=TLS_MEM -nodemcuv2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -nodemcuv2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -nodemcuv2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.lvl.HTTP_SERVER=HTTP_SERVER -nodemcuv2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -nodemcuv2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -nodemcuv2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -nodemcuv2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -nodemcuv2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.CORE=CORE -nodemcuv2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -nodemcuv2.menu.lvl.WIFI=WIFI -nodemcuv2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -nodemcuv2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -nodemcuv2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -nodemcuv2.menu.lvl.UPDATER=UPDATER -nodemcuv2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -nodemcuv2.menu.lvl.OTA=OTA -nodemcuv2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -nodemcuv2.menu.lvl.OOM=OOM -nodemcuv2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -nodemcuv2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -nodemcuv2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -nodemcuv2.menu.wipe.none=Only Sketch -nodemcuv2.menu.wipe.none.upload.erase_cmd= -nodemcuv2.menu.wipe.sdk=Sketch + WiFi Settings -nodemcuv2.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -nodemcuv2.menu.wipe.all=All Flash Contents -nodemcuv2.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -nodemcuv2.menu.baud.115200=115200 -nodemcuv2.menu.baud.115200.upload.speed=115200 -nodemcuv2.menu.baud.9600=9600 -nodemcuv2.menu.baud.9600.upload.speed=9600 -nodemcuv2.menu.baud.57600=57600 -nodemcuv2.menu.baud.57600.upload.speed=57600 -nodemcuv2.menu.baud.230400.linux=230400 -nodemcuv2.menu.baud.230400.macosx=230400 -nodemcuv2.menu.baud.230400.upload.speed=230400 -nodemcuv2.menu.baud.256000.windows=256000 -nodemcuv2.menu.baud.256000.upload.speed=256000 -nodemcuv2.menu.baud.460800.linux=460800 -nodemcuv2.menu.baud.460800.macosx=460800 -nodemcuv2.menu.baud.460800.upload.speed=460800 -nodemcuv2.menu.baud.512000.windows=512000 -nodemcuv2.menu.baud.512000.upload.speed=512000 -nodemcuv2.menu.baud.921600=921600 -nodemcuv2.menu.baud.921600.upload.speed=921600 - -############################################################## -modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV) -modwifi.build.board=MOD_WIFI_ESP8266 -modwifi.build.variant=modwifi -modwifi.upload.tool=esptool -modwifi.upload.maximum_data_size=81920 -modwifi.upload.wait_for_upload_port=true -modwifi.upload.erase_cmd= -modwifi.serial.disableDTR=true -modwifi.serial.disableRTS=true -modwifi.build.mcu=esp8266 -modwifi.build.core=esp8266 -modwifi.build.spiffs_pagesize=256 -modwifi.build.debug_port= -modwifi.build.debug_level= -modwifi.menu.xtal.80=80 MHz -modwifi.menu.xtal.80.build.f_cpu=80000000L -modwifi.menu.xtal.160=160 MHz -modwifi.menu.xtal.160.build.f_cpu=160000000L -modwifi.menu.vt.flash=Flash -modwifi.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -modwifi.menu.vt.heap=Heap -modwifi.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -modwifi.menu.vt.iram=IRAM -modwifi.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -modwifi.menu.exception.enabled=Enabled -modwifi.menu.exception.enabled.build.exception_flags=-fexceptions -modwifi.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -modwifi.menu.exception.disabled=Disabled -modwifi.menu.exception.disabled.build.exception_flags=-fno-exceptions -modwifi.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -modwifi.upload.resetmethod=ck -modwifi.build.flash_mode=qio -modwifi.build.flash_freq=40 -modwifi.menu.eesz.2M=2M (no SPIFFS) -modwifi.menu.eesz.2M.build.flash_size=2M -modwifi.menu.eesz.2M.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld -modwifi.menu.eesz.2M.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M.upload.maximum_size=1044464 -modwifi.menu.eesz.2M.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M128=2M (128K SPIFFS) -modwifi.menu.eesz.2M128.build.flash_size=2M -modwifi.menu.eesz.2M128.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld -modwifi.menu.eesz.2M128.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M128.upload.maximum_size=1044464 -modwifi.menu.eesz.2M128.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M128.build.spiffs_start=0x1E0000 -modwifi.menu.eesz.2M128.build.spiffs_end=0x1FB000 -modwifi.menu.eesz.2M128.build.spiffs_blocksize=4096 -modwifi.menu.eesz.2M256=2M (256K SPIFFS) -modwifi.menu.eesz.2M256.build.flash_size=2M -modwifi.menu.eesz.2M256.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld -modwifi.menu.eesz.2M256.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M256.upload.maximum_size=1044464 -modwifi.menu.eesz.2M256.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M256.build.spiffs_start=0x1C0000 -modwifi.menu.eesz.2M256.build.spiffs_end=0x1FB000 -modwifi.menu.eesz.2M256.build.spiffs_blocksize=4096 -modwifi.menu.eesz.2M512=2M (512K SPIFFS) -modwifi.menu.eesz.2M512.build.flash_size=2M -modwifi.menu.eesz.2M512.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld -modwifi.menu.eesz.2M512.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M512.upload.maximum_size=1044464 -modwifi.menu.eesz.2M512.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M512.build.spiffs_start=0x180000 -modwifi.menu.eesz.2M512.build.spiffs_end=0x1FB000 -modwifi.menu.eesz.2M512.build.spiffs_blocksize=8192 -modwifi.menu.eesz.2M1M=2M (1M SPIFFS) -modwifi.menu.eesz.2M1M.build.flash_size=2M -modwifi.menu.eesz.2M1M.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld -modwifi.menu.eesz.2M1M.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M1M.upload.maximum_size=1044464 -modwifi.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M1M.build.spiffs_start=0x100000 -modwifi.menu.eesz.2M1M.build.spiffs_end=0x1FB000 -modwifi.menu.eesz.2M1M.build.spiffs_blocksize=8192 -modwifi.menu.ip.lm2f=v2 Lower Memory -modwifi.menu.ip.lm2f.build.lwip_include=lwip2/include -modwifi.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -modwifi.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -modwifi.menu.ip.hb2f=v2 Higher Bandwidth -modwifi.menu.ip.hb2f.build.lwip_include=lwip2/include -modwifi.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -modwifi.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -modwifi.menu.ip.lm2n=v2 Lower Memory (no features) -modwifi.menu.ip.lm2n.build.lwip_include=lwip2/include -modwifi.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -modwifi.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -modwifi.menu.ip.hb2n=v2 Higher Bandwidth (no features) -modwifi.menu.ip.hb2n.build.lwip_include=lwip2/include -modwifi.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -modwifi.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -modwifi.menu.ip.lm6f=v2 IPv6 Lower Memory -modwifi.menu.ip.lm6f.build.lwip_include=lwip2/include -modwifi.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -modwifi.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -modwifi.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -modwifi.menu.ip.hb6f.build.lwip_include=lwip2/include -modwifi.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -modwifi.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -modwifi.menu.ip.hb1=v1.4 Higher Bandwidth -modwifi.menu.ip.hb1.build.lwip_lib=-llwip_gcc -modwifi.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -modwifi.menu.ip.src=v1.4 Compile from source -modwifi.menu.ip.src.build.lwip_lib=-llwip_src -modwifi.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -modwifi.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -modwifi.menu.dbg.Disabled=Disabled -modwifi.menu.dbg.Disabled.build.debug_port= -modwifi.menu.dbg.Serial=Serial -modwifi.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -modwifi.menu.dbg.Serial1=Serial1 -modwifi.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -modwifi.menu.lvl.None____=None -modwifi.menu.lvl.None____.build.debug_level= -modwifi.menu.lvl.SSL=SSL -modwifi.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -modwifi.menu.lvl.TLS_MEM=TLS_MEM -modwifi.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -modwifi.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -modwifi.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.lvl.HTTP_SERVER=HTTP_SERVER -modwifi.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -modwifi.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -modwifi.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -modwifi.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -modwifi.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -modwifi.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -modwifi.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.CORE=CORE -modwifi.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -modwifi.menu.lvl.WIFI=WIFI -modwifi.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -modwifi.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -modwifi.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -modwifi.menu.lvl.UPDATER=UPDATER -modwifi.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -modwifi.menu.lvl.OTA=OTA -modwifi.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -modwifi.menu.lvl.OOM=OOM -modwifi.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -modwifi.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -modwifi.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -modwifi.menu.wipe.none=Only Sketch -modwifi.menu.wipe.none.upload.erase_cmd= -modwifi.menu.wipe.sdk=Sketch + WiFi Settings -modwifi.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -modwifi.menu.wipe.all=All Flash Contents -modwifi.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -modwifi.menu.baud.115200=115200 -modwifi.menu.baud.115200.upload.speed=115200 -modwifi.menu.baud.9600=9600 -modwifi.menu.baud.9600.upload.speed=9600 -modwifi.menu.baud.57600=57600 -modwifi.menu.baud.57600.upload.speed=57600 -modwifi.menu.baud.230400.linux=230400 -modwifi.menu.baud.230400.macosx=230400 -modwifi.menu.baud.230400.upload.speed=230400 -modwifi.menu.baud.256000.windows=256000 -modwifi.menu.baud.256000.upload.speed=256000 -modwifi.menu.baud.460800.linux=460800 -modwifi.menu.baud.460800.macosx=460800 -modwifi.menu.baud.460800.upload.speed=460800 -modwifi.menu.baud.512000.windows=512000 -modwifi.menu.baud.512000.upload.speed=512000 -modwifi.menu.baud.921600=921600 -modwifi.menu.baud.921600.upload.speed=921600 - -############################################################## -thing.name=SparkFun ESP8266 Thing -thing.build.board=ESP8266_THING -thing.build.variant=thing -thing.upload.tool=esptool -thing.upload.maximum_data_size=81920 -thing.upload.wait_for_upload_port=true -thing.upload.erase_cmd= -thing.serial.disableDTR=true -thing.serial.disableRTS=true -thing.build.mcu=esp8266 -thing.build.core=esp8266 -thing.build.spiffs_pagesize=256 -thing.build.debug_port= -thing.build.debug_level= -thing.menu.xtal.80=80 MHz -thing.menu.xtal.80.build.f_cpu=80000000L -thing.menu.xtal.160=160 MHz -thing.menu.xtal.160.build.f_cpu=160000000L -thing.menu.vt.flash=Flash -thing.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -thing.menu.vt.heap=Heap -thing.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -thing.menu.vt.iram=IRAM -thing.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -thing.menu.exception.enabled=Enabled -thing.menu.exception.enabled.build.exception_flags=-fexceptions -thing.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -thing.menu.exception.disabled=Disabled -thing.menu.exception.disabled.build.exception_flags=-fno-exceptions -thing.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -thing.upload.resetmethod=ck -thing.build.flash_mode=qio -thing.build.flash_freq=40 -thing.menu.eesz.512K=512K (no SPIFFS) -thing.menu.eesz.512K.build.flash_size=512K -thing.menu.eesz.512K.build.flash_size_bytes=0x80000 -thing.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld -thing.menu.eesz.512K.build.spiffs_pagesize=256 -thing.menu.eesz.512K.upload.maximum_size=499696 -thing.menu.eesz.512K.build.rfcal_addr=0x7C000 -thing.menu.eesz.512K32=512K (32K SPIFFS) -thing.menu.eesz.512K32.build.flash_size=512K -thing.menu.eesz.512K32.build.flash_size_bytes=0x80000 -thing.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld -thing.menu.eesz.512K32.build.spiffs_pagesize=256 -thing.menu.eesz.512K32.upload.maximum_size=466928 -thing.menu.eesz.512K32.build.rfcal_addr=0x7C000 -thing.menu.eesz.512K32.build.spiffs_start=0x73000 -thing.menu.eesz.512K32.build.spiffs_end=0x7B000 -thing.menu.eesz.512K32.build.spiffs_blocksize=4096 -thing.menu.eesz.512K64=512K (64K SPIFFS) -thing.menu.eesz.512K64.build.flash_size=512K -thing.menu.eesz.512K64.build.flash_size_bytes=0x80000 -thing.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld -thing.menu.eesz.512K64.build.spiffs_pagesize=256 -thing.menu.eesz.512K64.upload.maximum_size=434160 -thing.menu.eesz.512K64.build.rfcal_addr=0x7C000 -thing.menu.eesz.512K64.build.spiffs_start=0x6B000 -thing.menu.eesz.512K64.build.spiffs_end=0x7B000 -thing.menu.eesz.512K64.build.spiffs_blocksize=4096 -thing.menu.eesz.512K128=512K (128K SPIFFS) -thing.menu.eesz.512K128.build.flash_size=512K -thing.menu.eesz.512K128.build.flash_size_bytes=0x80000 -thing.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld -thing.menu.eesz.512K128.build.spiffs_pagesize=256 -thing.menu.eesz.512K128.upload.maximum_size=368624 -thing.menu.eesz.512K128.build.rfcal_addr=0x7C000 -thing.menu.eesz.512K128.build.spiffs_start=0x5B000 -thing.menu.eesz.512K128.build.spiffs_end=0x7B000 -thing.menu.eesz.512K128.build.spiffs_blocksize=4096 -thing.menu.ip.lm2f=v2 Lower Memory -thing.menu.ip.lm2f.build.lwip_include=lwip2/include -thing.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -thing.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -thing.menu.ip.hb2f=v2 Higher Bandwidth -thing.menu.ip.hb2f.build.lwip_include=lwip2/include -thing.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -thing.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -thing.menu.ip.lm2n=v2 Lower Memory (no features) -thing.menu.ip.lm2n.build.lwip_include=lwip2/include -thing.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -thing.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -thing.menu.ip.hb2n=v2 Higher Bandwidth (no features) -thing.menu.ip.hb2n.build.lwip_include=lwip2/include -thing.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -thing.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -thing.menu.ip.lm6f=v2 IPv6 Lower Memory -thing.menu.ip.lm6f.build.lwip_include=lwip2/include -thing.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -thing.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -thing.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -thing.menu.ip.hb6f.build.lwip_include=lwip2/include -thing.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -thing.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -thing.menu.ip.hb1=v1.4 Higher Bandwidth -thing.menu.ip.hb1.build.lwip_lib=-llwip_gcc -thing.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -thing.menu.ip.src=v1.4 Compile from source -thing.menu.ip.src.build.lwip_lib=-llwip_src -thing.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -thing.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -thing.menu.dbg.Disabled=Disabled -thing.menu.dbg.Disabled.build.debug_port= -thing.menu.dbg.Serial=Serial -thing.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -thing.menu.dbg.Serial1=Serial1 -thing.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -thing.menu.lvl.None____=None -thing.menu.lvl.None____.build.debug_level= -thing.menu.lvl.SSL=SSL -thing.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -thing.menu.lvl.TLS_MEM=TLS_MEM -thing.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -thing.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -thing.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -thing.menu.lvl.HTTP_SERVER=HTTP_SERVER -thing.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -thing.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -thing.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -thing.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -thing.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -thing.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -thing.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thing.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -thing.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -thing.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thing.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -thing.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.CORE=CORE -thing.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -thing.menu.lvl.WIFI=WIFI -thing.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -thing.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -thing.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -thing.menu.lvl.UPDATER=UPDATER -thing.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -thing.menu.lvl.OTA=OTA -thing.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -thing.menu.lvl.OOM=OOM -thing.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -thing.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -thing.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -thing.menu.wipe.none=Only Sketch -thing.menu.wipe.none.upload.erase_cmd= -thing.menu.wipe.sdk=Sketch + WiFi Settings -thing.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -thing.menu.wipe.all=All Flash Contents -thing.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -thing.menu.baud.115200=115200 -thing.menu.baud.115200.upload.speed=115200 -thing.menu.baud.9600=9600 -thing.menu.baud.9600.upload.speed=9600 -thing.menu.baud.57600=57600 -thing.menu.baud.57600.upload.speed=57600 -thing.menu.baud.230400.linux=230400 -thing.menu.baud.230400.macosx=230400 -thing.menu.baud.230400.upload.speed=230400 -thing.menu.baud.256000.windows=256000 -thing.menu.baud.256000.upload.speed=256000 -thing.menu.baud.460800.linux=460800 -thing.menu.baud.460800.macosx=460800 -thing.menu.baud.460800.upload.speed=460800 -thing.menu.baud.512000.windows=512000 -thing.menu.baud.512000.upload.speed=512000 -thing.menu.baud.921600=921600 -thing.menu.baud.921600.upload.speed=921600 - -############################################################## -thingdev.name=SparkFun ESP8266 Thing Dev -thingdev.build.board=ESP8266_THING_DEV -thingdev.build.variant=thing -thingdev.upload.tool=esptool -thingdev.upload.maximum_data_size=81920 -thingdev.upload.wait_for_upload_port=true -thingdev.upload.erase_cmd= -thingdev.serial.disableDTR=true -thingdev.serial.disableRTS=true -thingdev.build.mcu=esp8266 -thingdev.build.core=esp8266 -thingdev.build.spiffs_pagesize=256 -thingdev.build.debug_port= -thingdev.build.debug_level= -thingdev.menu.xtal.80=80 MHz -thingdev.menu.xtal.80.build.f_cpu=80000000L -thingdev.menu.xtal.160=160 MHz -thingdev.menu.xtal.160.build.f_cpu=160000000L -thingdev.menu.vt.flash=Flash -thingdev.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -thingdev.menu.vt.heap=Heap -thingdev.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -thingdev.menu.vt.iram=IRAM -thingdev.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -thingdev.menu.exception.enabled=Enabled -thingdev.menu.exception.enabled.build.exception_flags=-fexceptions -thingdev.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -thingdev.menu.exception.disabled=Disabled -thingdev.menu.exception.disabled.build.exception_flags=-fno-exceptions -thingdev.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -thingdev.upload.resetmethod=nodemcu -thingdev.build.flash_mode=dio -thingdev.build.flash_freq=40 -thingdev.menu.eesz.512K=512K (no SPIFFS) -thingdev.menu.eesz.512K.build.flash_size=512K -thingdev.menu.eesz.512K.build.flash_size_bytes=0x80000 -thingdev.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld -thingdev.menu.eesz.512K.build.spiffs_pagesize=256 -thingdev.menu.eesz.512K.upload.maximum_size=499696 -thingdev.menu.eesz.512K.build.rfcal_addr=0x7C000 -thingdev.menu.eesz.512K32=512K (32K SPIFFS) -thingdev.menu.eesz.512K32.build.flash_size=512K -thingdev.menu.eesz.512K32.build.flash_size_bytes=0x80000 -thingdev.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld -thingdev.menu.eesz.512K32.build.spiffs_pagesize=256 -thingdev.menu.eesz.512K32.upload.maximum_size=466928 -thingdev.menu.eesz.512K32.build.rfcal_addr=0x7C000 -thingdev.menu.eesz.512K32.build.spiffs_start=0x73000 -thingdev.menu.eesz.512K32.build.spiffs_end=0x7B000 -thingdev.menu.eesz.512K32.build.spiffs_blocksize=4096 -thingdev.menu.eesz.512K64=512K (64K SPIFFS) -thingdev.menu.eesz.512K64.build.flash_size=512K -thingdev.menu.eesz.512K64.build.flash_size_bytes=0x80000 -thingdev.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld -thingdev.menu.eesz.512K64.build.spiffs_pagesize=256 -thingdev.menu.eesz.512K64.upload.maximum_size=434160 -thingdev.menu.eesz.512K64.build.rfcal_addr=0x7C000 -thingdev.menu.eesz.512K64.build.spiffs_start=0x6B000 -thingdev.menu.eesz.512K64.build.spiffs_end=0x7B000 -thingdev.menu.eesz.512K64.build.spiffs_blocksize=4096 -thingdev.menu.eesz.512K128=512K (128K SPIFFS) -thingdev.menu.eesz.512K128.build.flash_size=512K -thingdev.menu.eesz.512K128.build.flash_size_bytes=0x80000 -thingdev.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld -thingdev.menu.eesz.512K128.build.spiffs_pagesize=256 -thingdev.menu.eesz.512K128.upload.maximum_size=368624 -thingdev.menu.eesz.512K128.build.rfcal_addr=0x7C000 -thingdev.menu.eesz.512K128.build.spiffs_start=0x5B000 -thingdev.menu.eesz.512K128.build.spiffs_end=0x7B000 -thingdev.menu.eesz.512K128.build.spiffs_blocksize=4096 -thingdev.menu.ip.lm2f=v2 Lower Memory -thingdev.menu.ip.lm2f.build.lwip_include=lwip2/include -thingdev.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -thingdev.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -thingdev.menu.ip.hb2f=v2 Higher Bandwidth -thingdev.menu.ip.hb2f.build.lwip_include=lwip2/include -thingdev.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -thingdev.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -thingdev.menu.ip.lm2n=v2 Lower Memory (no features) -thingdev.menu.ip.lm2n.build.lwip_include=lwip2/include -thingdev.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -thingdev.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -thingdev.menu.ip.hb2n=v2 Higher Bandwidth (no features) -thingdev.menu.ip.hb2n.build.lwip_include=lwip2/include -thingdev.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -thingdev.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -thingdev.menu.ip.lm6f=v2 IPv6 Lower Memory -thingdev.menu.ip.lm6f.build.lwip_include=lwip2/include -thingdev.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -thingdev.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -thingdev.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -thingdev.menu.ip.hb6f.build.lwip_include=lwip2/include -thingdev.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -thingdev.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -thingdev.menu.ip.hb1=v1.4 Higher Bandwidth -thingdev.menu.ip.hb1.build.lwip_lib=-llwip_gcc -thingdev.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -thingdev.menu.ip.src=v1.4 Compile from source -thingdev.menu.ip.src.build.lwip_lib=-llwip_src -thingdev.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -thingdev.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -thingdev.menu.dbg.Disabled=Disabled -thingdev.menu.dbg.Disabled.build.debug_port= -thingdev.menu.dbg.Serial=Serial -thingdev.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -thingdev.menu.dbg.Serial1=Serial1 -thingdev.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -thingdev.menu.lvl.None____=None -thingdev.menu.lvl.None____.build.debug_level= -thingdev.menu.lvl.SSL=SSL -thingdev.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -thingdev.menu.lvl.TLS_MEM=TLS_MEM -thingdev.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -thingdev.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -thingdev.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.lvl.HTTP_SERVER=HTTP_SERVER -thingdev.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -thingdev.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -thingdev.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -thingdev.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -thingdev.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -thingdev.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -thingdev.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.CORE=CORE -thingdev.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -thingdev.menu.lvl.WIFI=WIFI -thingdev.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -thingdev.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -thingdev.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -thingdev.menu.lvl.UPDATER=UPDATER -thingdev.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -thingdev.menu.lvl.OTA=OTA -thingdev.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -thingdev.menu.lvl.OOM=OOM -thingdev.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -thingdev.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -thingdev.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -thingdev.menu.wipe.none=Only Sketch -thingdev.menu.wipe.none.upload.erase_cmd= -thingdev.menu.wipe.sdk=Sketch + WiFi Settings -thingdev.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -thingdev.menu.wipe.all=All Flash Contents -thingdev.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -thingdev.menu.baud.115200=115200 -thingdev.menu.baud.115200.upload.speed=115200 -thingdev.menu.baud.9600=9600 -thingdev.menu.baud.9600.upload.speed=9600 -thingdev.menu.baud.57600=57600 -thingdev.menu.baud.57600.upload.speed=57600 -thingdev.menu.baud.230400.linux=230400 -thingdev.menu.baud.230400.macosx=230400 -thingdev.menu.baud.230400.upload.speed=230400 -thingdev.menu.baud.256000.windows=256000 -thingdev.menu.baud.256000.upload.speed=256000 -thingdev.menu.baud.460800.linux=460800 -thingdev.menu.baud.460800.macosx=460800 -thingdev.menu.baud.460800.upload.speed=460800 -thingdev.menu.baud.512000.windows=512000 -thingdev.menu.baud.512000.upload.speed=512000 -thingdev.menu.baud.921600=921600 -thingdev.menu.baud.921600.upload.speed=921600 - -############################################################## -esp210.name=SweetPea ESP-210 -esp210.build.board=ESP8266_ESP210 -esp210.upload.tool=esptool -esp210.upload.maximum_data_size=81920 -esp210.upload.wait_for_upload_port=true -esp210.upload.erase_cmd= -esp210.serial.disableDTR=true -esp210.serial.disableRTS=true -esp210.build.mcu=esp8266 -esp210.build.core=esp8266 -esp210.build.variant=generic -esp210.build.spiffs_pagesize=256 -esp210.build.debug_port= -esp210.build.debug_level= -esp210.menu.xtal.80=80 MHz -esp210.menu.xtal.80.build.f_cpu=80000000L -esp210.menu.xtal.160=160 MHz -esp210.menu.xtal.160.build.f_cpu=160000000L -esp210.menu.vt.flash=Flash -esp210.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -esp210.menu.vt.heap=Heap -esp210.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -esp210.menu.vt.iram=IRAM -esp210.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -esp210.menu.exception.enabled=Enabled -esp210.menu.exception.enabled.build.exception_flags=-fexceptions -esp210.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -esp210.menu.exception.disabled=Disabled -esp210.menu.exception.disabled.build.exception_flags=-fno-exceptions -esp210.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -esp210.upload.resetmethod=ck -esp210.build.flash_mode=qio -esp210.build.flash_freq=40 -esp210.menu.eesz.4M=4M (no SPIFFS) -esp210.menu.eesz.4M.build.flash_size=4M -esp210.menu.eesz.4M.build.flash_size_bytes=0x400000 -esp210.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -esp210.menu.eesz.4M.build.spiffs_pagesize=256 -esp210.menu.eesz.4M.upload.maximum_size=1044464 -esp210.menu.eesz.4M.build.rfcal_addr=0x3FC000 -esp210.menu.eesz.4M1M=4M (1M SPIFFS) -esp210.menu.eesz.4M1M.build.flash_size=4M -esp210.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -esp210.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -esp210.menu.eesz.4M1M.build.spiffs_pagesize=256 -esp210.menu.eesz.4M1M.upload.maximum_size=1044464 -esp210.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -esp210.menu.eesz.4M1M.build.spiffs_start=0x300000 -esp210.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -esp210.menu.eesz.4M1M.build.spiffs_blocksize=8192 -esp210.menu.eesz.4M2M=4M (2M SPIFFS) -esp210.menu.eesz.4M2M.build.flash_size=4M -esp210.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -esp210.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -esp210.menu.eesz.4M2M.build.spiffs_pagesize=256 -esp210.menu.eesz.4M2M.upload.maximum_size=1044464 -esp210.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -esp210.menu.eesz.4M2M.build.spiffs_start=0x200000 -esp210.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -esp210.menu.eesz.4M2M.build.spiffs_blocksize=8192 -esp210.menu.eesz.4M3M=4M (3M SPIFFS) -esp210.menu.eesz.4M3M.build.flash_size=4M -esp210.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -esp210.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -esp210.menu.eesz.4M3M.build.spiffs_pagesize=256 -esp210.menu.eesz.4M3M.upload.maximum_size=1044464 -esp210.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -esp210.menu.eesz.4M3M.build.spiffs_start=0x100000 -esp210.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -esp210.menu.eesz.4M3M.build.spiffs_blocksize=8192 -esp210.menu.ip.lm2f=v2 Lower Memory -esp210.menu.ip.lm2f.build.lwip_include=lwip2/include -esp210.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -esp210.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -esp210.menu.ip.hb2f=v2 Higher Bandwidth -esp210.menu.ip.hb2f.build.lwip_include=lwip2/include -esp210.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -esp210.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -esp210.menu.ip.lm2n=v2 Lower Memory (no features) -esp210.menu.ip.lm2n.build.lwip_include=lwip2/include -esp210.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -esp210.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -esp210.menu.ip.hb2n=v2 Higher Bandwidth (no features) -esp210.menu.ip.hb2n.build.lwip_include=lwip2/include -esp210.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -esp210.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -esp210.menu.ip.lm6f=v2 IPv6 Lower Memory -esp210.menu.ip.lm6f.build.lwip_include=lwip2/include -esp210.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -esp210.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -esp210.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -esp210.menu.ip.hb6f.build.lwip_include=lwip2/include -esp210.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -esp210.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -esp210.menu.ip.hb1=v1.4 Higher Bandwidth -esp210.menu.ip.hb1.build.lwip_lib=-llwip_gcc -esp210.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -esp210.menu.ip.src=v1.4 Compile from source -esp210.menu.ip.src.build.lwip_lib=-llwip_src -esp210.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -esp210.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -esp210.menu.dbg.Disabled=Disabled -esp210.menu.dbg.Disabled.build.debug_port= -esp210.menu.dbg.Serial=Serial -esp210.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -esp210.menu.dbg.Serial1=Serial1 -esp210.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -esp210.menu.lvl.None____=None -esp210.menu.lvl.None____.build.debug_level= -esp210.menu.lvl.SSL=SSL -esp210.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -esp210.menu.lvl.TLS_MEM=TLS_MEM -esp210.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -esp210.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -esp210.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.lvl.HTTP_SERVER=HTTP_SERVER -esp210.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -esp210.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -esp210.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -esp210.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -esp210.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -esp210.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -esp210.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.CORE=CORE -esp210.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -esp210.menu.lvl.WIFI=WIFI -esp210.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -esp210.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -esp210.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -esp210.menu.lvl.UPDATER=UPDATER -esp210.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -esp210.menu.lvl.OTA=OTA -esp210.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -esp210.menu.lvl.OOM=OOM -esp210.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -esp210.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -esp210.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -esp210.menu.wipe.none=Only Sketch -esp210.menu.wipe.none.upload.erase_cmd= -esp210.menu.wipe.sdk=Sketch + WiFi Settings -esp210.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -esp210.menu.wipe.all=All Flash Contents -esp210.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -esp210.menu.baud.57600=57600 -esp210.menu.baud.57600.upload.speed=57600 -esp210.menu.baud.9600=9600 -esp210.menu.baud.9600.upload.speed=9600 -esp210.menu.baud.115200=115200 -esp210.menu.baud.115200.upload.speed=115200 -esp210.menu.baud.230400.linux=230400 -esp210.menu.baud.230400.macosx=230400 -esp210.menu.baud.230400.upload.speed=230400 -esp210.menu.baud.256000.windows=256000 -esp210.menu.baud.256000.upload.speed=256000 -esp210.menu.baud.460800.linux=460800 -esp210.menu.baud.460800.macosx=460800 -esp210.menu.baud.460800.upload.speed=460800 -esp210.menu.baud.512000.windows=512000 -esp210.menu.baud.512000.upload.speed=512000 -esp210.menu.baud.921600=921600 -esp210.menu.baud.921600.upload.speed=921600 - -############################################################## -d1_mini.name=LOLIN(WEMOS) D1 R2 & mini -d1_mini.build.board=ESP8266_WEMOS_D1MINI -d1_mini.build.variant=d1_mini -d1_mini.upload.tool=esptool -d1_mini.upload.maximum_data_size=81920 -d1_mini.upload.wait_for_upload_port=true -d1_mini.upload.erase_cmd= -d1_mini.serial.disableDTR=true -d1_mini.serial.disableRTS=true -d1_mini.build.mcu=esp8266 -d1_mini.build.core=esp8266 -d1_mini.build.spiffs_pagesize=256 -d1_mini.build.debug_port= -d1_mini.build.debug_level= -d1_mini.menu.xtal.80=80 MHz -d1_mini.menu.xtal.80.build.f_cpu=80000000L -d1_mini.menu.xtal.160=160 MHz -d1_mini.menu.xtal.160.build.f_cpu=160000000L -d1_mini.menu.vt.flash=Flash -d1_mini.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1_mini.menu.vt.heap=Heap -d1_mini.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1_mini.menu.vt.iram=IRAM -d1_mini.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1_mini.menu.exception.enabled=Enabled -d1_mini.menu.exception.enabled.build.exception_flags=-fexceptions -d1_mini.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -d1_mini.menu.exception.disabled=Disabled -d1_mini.menu.exception.disabled.build.exception_flags=-fno-exceptions -d1_mini.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -d1_mini.upload.resetmethod=nodemcu -d1_mini.build.flash_mode=dio -d1_mini.build.flash_freq=40 -d1_mini.menu.eesz.4M=4M (no SPIFFS) -d1_mini.menu.eesz.4M.build.flash_size=4M -d1_mini.menu.eesz.4M.build.flash_size_bytes=0x400000 -d1_mini.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -d1_mini.menu.eesz.4M.build.spiffs_pagesize=256 -d1_mini.menu.eesz.4M.upload.maximum_size=1044464 -d1_mini.menu.eesz.4M.build.rfcal_addr=0x3FC000 -d1_mini.menu.eesz.4M1M=4M (1M SPIFFS) -d1_mini.menu.eesz.4M1M.build.flash_size=4M -d1_mini.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -d1_mini.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1_mini.menu.eesz.4M1M.build.spiffs_pagesize=256 -d1_mini.menu.eesz.4M1M.upload.maximum_size=1044464 -d1_mini.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -d1_mini.menu.eesz.4M1M.build.spiffs_start=0x300000 -d1_mini.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -d1_mini.menu.eesz.4M1M.build.spiffs_blocksize=8192 -d1_mini.menu.eesz.4M2M=4M (2M SPIFFS) -d1_mini.menu.eesz.4M2M.build.flash_size=4M -d1_mini.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -d1_mini.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -d1_mini.menu.eesz.4M2M.build.spiffs_pagesize=256 -d1_mini.menu.eesz.4M2M.upload.maximum_size=1044464 -d1_mini.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -d1_mini.menu.eesz.4M2M.build.spiffs_start=0x200000 -d1_mini.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -d1_mini.menu.eesz.4M2M.build.spiffs_blocksize=8192 -d1_mini.menu.eesz.4M3M=4M (3M SPIFFS) -d1_mini.menu.eesz.4M3M.build.flash_size=4M -d1_mini.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -d1_mini.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -d1_mini.menu.eesz.4M3M.build.spiffs_pagesize=256 -d1_mini.menu.eesz.4M3M.upload.maximum_size=1044464 -d1_mini.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -d1_mini.menu.eesz.4M3M.build.spiffs_start=0x100000 -d1_mini.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -d1_mini.menu.eesz.4M3M.build.spiffs_blocksize=8192 -d1_mini.menu.ip.lm2f=v2 Lower Memory -d1_mini.menu.ip.lm2f.build.lwip_include=lwip2/include -d1_mini.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -d1_mini.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini.menu.ip.hb2f=v2 Higher Bandwidth -d1_mini.menu.ip.hb2f.build.lwip_include=lwip2/include -d1_mini.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -d1_mini.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini.menu.ip.lm2n=v2 Lower Memory (no features) -d1_mini.menu.ip.lm2n.build.lwip_include=lwip2/include -d1_mini.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -d1_mini.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini.menu.ip.hb2n=v2 Higher Bandwidth (no features) -d1_mini.menu.ip.hb2n.build.lwip_include=lwip2/include -d1_mini.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -d1_mini.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini.menu.ip.lm6f=v2 IPv6 Lower Memory -d1_mini.menu.ip.lm6f.build.lwip_include=lwip2/include -d1_mini.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -d1_mini.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -d1_mini.menu.ip.hb6f.build.lwip_include=lwip2/include -d1_mini.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -d1_mini.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini.menu.ip.hb1=v1.4 Higher Bandwidth -d1_mini.menu.ip.hb1.build.lwip_lib=-llwip_gcc -d1_mini.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini.menu.ip.src=v1.4 Compile from source -d1_mini.menu.ip.src.build.lwip_lib=-llwip_src -d1_mini.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini.menu.dbg.Disabled=Disabled -d1_mini.menu.dbg.Disabled.build.debug_port= -d1_mini.menu.dbg.Serial=Serial -d1_mini.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini.menu.dbg.Serial1=Serial1 -d1_mini.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini.menu.lvl.None____=None -d1_mini.menu.lvl.None____.build.debug_level= -d1_mini.menu.lvl.SSL=SSL -d1_mini.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini.menu.lvl.TLS_MEM=TLS_MEM -d1_mini.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -d1_mini.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.lvl.HTTP_SERVER=HTTP_SERVER -d1_mini.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -d1_mini.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.CORE=CORE -d1_mini.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini.menu.lvl.WIFI=WIFI -d1_mini.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -d1_mini.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini.menu.lvl.UPDATER=UPDATER -d1_mini.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini.menu.lvl.OTA=OTA -d1_mini.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini.menu.lvl.OOM=OOM -d1_mini.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini.menu.wipe.none=Only Sketch -d1_mini.menu.wipe.none.upload.erase_cmd= -d1_mini.menu.wipe.sdk=Sketch + WiFi Settings -d1_mini.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1_mini.menu.wipe.all=All Flash Contents -d1_mini.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1_mini.menu.baud.921600=921600 -d1_mini.menu.baud.921600.upload.speed=921600 -d1_mini.menu.baud.9600=9600 -d1_mini.menu.baud.9600.upload.speed=9600 -d1_mini.menu.baud.57600=57600 -d1_mini.menu.baud.57600.upload.speed=57600 -d1_mini.menu.baud.115200=115200 -d1_mini.menu.baud.115200.upload.speed=115200 -d1_mini.menu.baud.230400.linux=230400 -d1_mini.menu.baud.230400.macosx=230400 -d1_mini.menu.baud.230400.upload.speed=230400 -d1_mini.menu.baud.256000.windows=256000 -d1_mini.menu.baud.256000.upload.speed=256000 -d1_mini.menu.baud.460800.linux=460800 -d1_mini.menu.baud.460800.macosx=460800 -d1_mini.menu.baud.460800.upload.speed=460800 -d1_mini.menu.baud.512000.windows=512000 -d1_mini.menu.baud.512000.upload.speed=512000 - -############################################################## -d1_mini_pro.name=LOLIN(WEMOS) D1 mini Pro -d1_mini_pro.build.board=ESP8266_WEMOS_D1MINIPRO -d1_mini_pro.build.variant=d1_mini -d1_mini_pro.upload.tool=esptool -d1_mini_pro.upload.maximum_data_size=81920 -d1_mini_pro.upload.wait_for_upload_port=true -d1_mini_pro.upload.erase_cmd= -d1_mini_pro.serial.disableDTR=true -d1_mini_pro.serial.disableRTS=true -d1_mini_pro.build.mcu=esp8266 -d1_mini_pro.build.core=esp8266 -d1_mini_pro.build.spiffs_pagesize=256 -d1_mini_pro.build.debug_port= -d1_mini_pro.build.debug_level= -d1_mini_pro.menu.xtal.80=80 MHz -d1_mini_pro.menu.xtal.80.build.f_cpu=80000000L -d1_mini_pro.menu.xtal.160=160 MHz -d1_mini_pro.menu.xtal.160.build.f_cpu=160000000L -d1_mini_pro.menu.vt.flash=Flash -d1_mini_pro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1_mini_pro.menu.vt.heap=Heap -d1_mini_pro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1_mini_pro.menu.vt.iram=IRAM -d1_mini_pro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1_mini_pro.menu.exception.enabled=Enabled -d1_mini_pro.menu.exception.enabled.build.exception_flags=-fexceptions -d1_mini_pro.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -d1_mini_pro.menu.exception.disabled=Disabled -d1_mini_pro.menu.exception.disabled.build.exception_flags=-fno-exceptions -d1_mini_pro.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -d1_mini_pro.upload.resetmethod=nodemcu -d1_mini_pro.build.flash_mode=dio -d1_mini_pro.build.flash_freq=40 -d1_mini_pro.menu.eesz.16M14M=16M (14M SPIFFS) -d1_mini_pro.menu.eesz.16M14M.build.flash_size=16M -d1_mini_pro.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 -d1_mini_pro.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld -d1_mini_pro.menu.eesz.16M14M.build.spiffs_pagesize=256 -d1_mini_pro.menu.eesz.16M14M.upload.maximum_size=1044464 -d1_mini_pro.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 -d1_mini_pro.menu.eesz.16M14M.build.spiffs_start=0x200000 -d1_mini_pro.menu.eesz.16M14M.build.spiffs_end=0xFFB000 -d1_mini_pro.menu.eesz.16M14M.build.spiffs_blocksize=8192 -d1_mini_pro.menu.eesz.16M15M=16M (15M SPIFFS) -d1_mini_pro.menu.eesz.16M15M.build.flash_size=16M -d1_mini_pro.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 -d1_mini_pro.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld -d1_mini_pro.menu.eesz.16M15M.build.spiffs_pagesize=256 -d1_mini_pro.menu.eesz.16M15M.upload.maximum_size=1044464 -d1_mini_pro.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 -d1_mini_pro.menu.eesz.16M15M.build.spiffs_start=0x100000 -d1_mini_pro.menu.eesz.16M15M.build.spiffs_end=0xFFB000 -d1_mini_pro.menu.eesz.16M15M.build.spiffs_blocksize=8192 -d1_mini_pro.menu.ip.lm2f=v2 Lower Memory -d1_mini_pro.menu.ip.lm2f.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -d1_mini_pro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini_pro.menu.ip.hb2f=v2 Higher Bandwidth -d1_mini_pro.menu.ip.hb2f.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -d1_mini_pro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini_pro.menu.ip.lm2n=v2 Lower Memory (no features) -d1_mini_pro.menu.ip.lm2n.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -d1_mini_pro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini_pro.menu.ip.hb2n=v2 Higher Bandwidth (no features) -d1_mini_pro.menu.ip.hb2n.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -d1_mini_pro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini_pro.menu.ip.lm6f=v2 IPv6 Lower Memory -d1_mini_pro.menu.ip.lm6f.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -d1_mini_pro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini_pro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -d1_mini_pro.menu.ip.hb6f.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -d1_mini_pro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini_pro.menu.ip.hb1=v1.4 Higher Bandwidth -d1_mini_pro.menu.ip.hb1.build.lwip_lib=-llwip_gcc -d1_mini_pro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_pro.menu.ip.src=v1.4 Compile from source -d1_mini_pro.menu.ip.src.build.lwip_lib=-llwip_src -d1_mini_pro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_pro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini_pro.menu.dbg.Disabled=Disabled -d1_mini_pro.menu.dbg.Disabled.build.debug_port= -d1_mini_pro.menu.dbg.Serial=Serial -d1_mini_pro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini_pro.menu.dbg.Serial1=Serial1 -d1_mini_pro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini_pro.menu.lvl.None____=None -d1_mini_pro.menu.lvl.None____.build.debug_level= -d1_mini_pro.menu.lvl.SSL=SSL -d1_mini_pro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini_pro.menu.lvl.TLS_MEM=TLS_MEM -d1_mini_pro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini_pro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -d1_mini_pro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.lvl.HTTP_SERVER=HTTP_SERVER -d1_mini_pro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -d1_mini_pro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini_pro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini_pro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini_pro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.CORE=CORE -d1_mini_pro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini_pro.menu.lvl.WIFI=WIFI -d1_mini_pro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini_pro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -d1_mini_pro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini_pro.menu.lvl.UPDATER=UPDATER -d1_mini_pro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini_pro.menu.lvl.OTA=OTA -d1_mini_pro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini_pro.menu.lvl.OOM=OOM -d1_mini_pro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini_pro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini_pro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini_pro.menu.wipe.none=Only Sketch -d1_mini_pro.menu.wipe.none.upload.erase_cmd= -d1_mini_pro.menu.wipe.sdk=Sketch + WiFi Settings -d1_mini_pro.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1_mini_pro.menu.wipe.all=All Flash Contents -d1_mini_pro.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1_mini_pro.menu.baud.921600=921600 -d1_mini_pro.menu.baud.921600.upload.speed=921600 -d1_mini_pro.menu.baud.9600=9600 -d1_mini_pro.menu.baud.9600.upload.speed=9600 -d1_mini_pro.menu.baud.57600=57600 -d1_mini_pro.menu.baud.57600.upload.speed=57600 -d1_mini_pro.menu.baud.115200=115200 -d1_mini_pro.menu.baud.115200.upload.speed=115200 -d1_mini_pro.menu.baud.230400.linux=230400 -d1_mini_pro.menu.baud.230400.macosx=230400 -d1_mini_pro.menu.baud.230400.upload.speed=230400 -d1_mini_pro.menu.baud.256000.windows=256000 -d1_mini_pro.menu.baud.256000.upload.speed=256000 -d1_mini_pro.menu.baud.460800.linux=460800 -d1_mini_pro.menu.baud.460800.macosx=460800 -d1_mini_pro.menu.baud.460800.upload.speed=460800 -d1_mini_pro.menu.baud.512000.windows=512000 -d1_mini_pro.menu.baud.512000.upload.speed=512000 - -############################################################## -d1_mini_lite.name=LOLIN(WEMOS) D1 mini Lite -d1_mini_lite.build.board=ESP8266_WEMOS_D1MINILITE -d1_mini_lite.build.variant=d1_mini -d1_mini_lite.upload.tool=esptool -d1_mini_lite.upload.maximum_data_size=81920 -d1_mini_lite.upload.wait_for_upload_port=true -d1_mini_lite.upload.erase_cmd= -d1_mini_lite.serial.disableDTR=true -d1_mini_lite.serial.disableRTS=true -d1_mini_lite.build.mcu=esp8266 -d1_mini_lite.build.core=esp8266 -d1_mini_lite.build.spiffs_pagesize=256 -d1_mini_lite.build.debug_port= -d1_mini_lite.build.debug_level= -d1_mini_lite.menu.xtal.80=80 MHz -d1_mini_lite.menu.xtal.80.build.f_cpu=80000000L -d1_mini_lite.menu.xtal.160=160 MHz -d1_mini_lite.menu.xtal.160.build.f_cpu=160000000L -d1_mini_lite.menu.vt.flash=Flash -d1_mini_lite.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1_mini_lite.menu.vt.heap=Heap -d1_mini_lite.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1_mini_lite.menu.vt.iram=IRAM -d1_mini_lite.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1_mini_lite.menu.exception.enabled=Enabled -d1_mini_lite.menu.exception.enabled.build.exception_flags=-fexceptions -d1_mini_lite.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -d1_mini_lite.menu.exception.disabled=Disabled -d1_mini_lite.menu.exception.disabled.build.exception_flags=-fno-exceptions -d1_mini_lite.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -d1_mini_lite.upload.resetmethod=nodemcu -d1_mini_lite.build.flash_mode=dout -d1_mini_lite.build.flash_freq=40 -d1_mini_lite.menu.eesz.1M=1M (no SPIFFS) -d1_mini_lite.menu.eesz.1M.build.flash_size=1M -d1_mini_lite.menu.eesz.1M.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -d1_mini_lite.menu.eesz.1M.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M.upload.maximum_size=1023984 -d1_mini_lite.menu.eesz.1M.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M64=1M (64K SPIFFS) -d1_mini_lite.menu.eesz.1M64.build.flash_size=1M -d1_mini_lite.menu.eesz.1M64.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -d1_mini_lite.menu.eesz.1M64.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M64.upload.maximum_size=958448 -d1_mini_lite.menu.eesz.1M64.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M64.build.spiffs_start=0xEB000 -d1_mini_lite.menu.eesz.1M64.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M64.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M128=1M (128K SPIFFS) -d1_mini_lite.menu.eesz.1M128.build.flash_size=1M -d1_mini_lite.menu.eesz.1M128.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -d1_mini_lite.menu.eesz.1M128.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M128.upload.maximum_size=892912 -d1_mini_lite.menu.eesz.1M128.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M128.build.spiffs_start=0xDB000 -d1_mini_lite.menu.eesz.1M128.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M128.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M144=1M (144K SPIFFS) -d1_mini_lite.menu.eesz.1M144.build.flash_size=1M -d1_mini_lite.menu.eesz.1M144.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -d1_mini_lite.menu.eesz.1M144.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M144.upload.maximum_size=876528 -d1_mini_lite.menu.eesz.1M144.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M144.build.spiffs_start=0xD7000 -d1_mini_lite.menu.eesz.1M144.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M144.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M160=1M (160K SPIFFS) -d1_mini_lite.menu.eesz.1M160.build.flash_size=1M -d1_mini_lite.menu.eesz.1M160.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -d1_mini_lite.menu.eesz.1M160.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M160.upload.maximum_size=860144 -d1_mini_lite.menu.eesz.1M160.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M160.build.spiffs_start=0xD3000 -d1_mini_lite.menu.eesz.1M160.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M160.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M192=1M (192K SPIFFS) -d1_mini_lite.menu.eesz.1M192.build.flash_size=1M -d1_mini_lite.menu.eesz.1M192.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -d1_mini_lite.menu.eesz.1M192.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M192.upload.maximum_size=827376 -d1_mini_lite.menu.eesz.1M192.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M192.build.spiffs_start=0xCB000 -d1_mini_lite.menu.eesz.1M192.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M192.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M256=1M (256K SPIFFS) -d1_mini_lite.menu.eesz.1M256.build.flash_size=1M -d1_mini_lite.menu.eesz.1M256.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -d1_mini_lite.menu.eesz.1M256.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M256.upload.maximum_size=761840 -d1_mini_lite.menu.eesz.1M256.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M256.build.spiffs_start=0xBB000 -d1_mini_lite.menu.eesz.1M256.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M256.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M512=1M (512K SPIFFS) -d1_mini_lite.menu.eesz.1M512.build.flash_size=1M -d1_mini_lite.menu.eesz.1M512.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -d1_mini_lite.menu.eesz.1M512.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M512.upload.maximum_size=499696 -d1_mini_lite.menu.eesz.1M512.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M512.build.spiffs_start=0x7B000 -d1_mini_lite.menu.eesz.1M512.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M512.build.spiffs_blocksize=4096 -d1_mini_lite.menu.ip.lm2f=v2 Lower Memory -d1_mini_lite.menu.ip.lm2f.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -d1_mini_lite.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini_lite.menu.ip.hb2f=v2 Higher Bandwidth -d1_mini_lite.menu.ip.hb2f.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -d1_mini_lite.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini_lite.menu.ip.lm2n=v2 Lower Memory (no features) -d1_mini_lite.menu.ip.lm2n.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -d1_mini_lite.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini_lite.menu.ip.hb2n=v2 Higher Bandwidth (no features) -d1_mini_lite.menu.ip.hb2n.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -d1_mini_lite.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini_lite.menu.ip.lm6f=v2 IPv6 Lower Memory -d1_mini_lite.menu.ip.lm6f.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -d1_mini_lite.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini_lite.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -d1_mini_lite.menu.ip.hb6f.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -d1_mini_lite.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini_lite.menu.ip.hb1=v1.4 Higher Bandwidth -d1_mini_lite.menu.ip.hb1.build.lwip_lib=-llwip_gcc -d1_mini_lite.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_lite.menu.ip.src=v1.4 Compile from source -d1_mini_lite.menu.ip.src.build.lwip_lib=-llwip_src -d1_mini_lite.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_lite.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini_lite.menu.dbg.Disabled=Disabled -d1_mini_lite.menu.dbg.Disabled.build.debug_port= -d1_mini_lite.menu.dbg.Serial=Serial -d1_mini_lite.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini_lite.menu.dbg.Serial1=Serial1 -d1_mini_lite.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini_lite.menu.lvl.None____=None -d1_mini_lite.menu.lvl.None____.build.debug_level= -d1_mini_lite.menu.lvl.SSL=SSL -d1_mini_lite.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini_lite.menu.lvl.TLS_MEM=TLS_MEM -d1_mini_lite.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini_lite.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -d1_mini_lite.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.lvl.HTTP_SERVER=HTTP_SERVER -d1_mini_lite.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -d1_mini_lite.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini_lite.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini_lite.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini_lite.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.CORE=CORE -d1_mini_lite.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini_lite.menu.lvl.WIFI=WIFI -d1_mini_lite.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini_lite.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -d1_mini_lite.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini_lite.menu.lvl.UPDATER=UPDATER -d1_mini_lite.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini_lite.menu.lvl.OTA=OTA -d1_mini_lite.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini_lite.menu.lvl.OOM=OOM -d1_mini_lite.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini_lite.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini_lite.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini_lite.menu.wipe.none=Only Sketch -d1_mini_lite.menu.wipe.none.upload.erase_cmd= -d1_mini_lite.menu.wipe.sdk=Sketch + WiFi Settings -d1_mini_lite.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1_mini_lite.menu.wipe.all=All Flash Contents -d1_mini_lite.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1_mini_lite.menu.baud.921600=921600 -d1_mini_lite.menu.baud.921600.upload.speed=921600 -d1_mini_lite.menu.baud.9600=9600 -d1_mini_lite.menu.baud.9600.upload.speed=9600 -d1_mini_lite.menu.baud.57600=57600 -d1_mini_lite.menu.baud.57600.upload.speed=57600 -d1_mini_lite.menu.baud.115200=115200 -d1_mini_lite.menu.baud.115200.upload.speed=115200 -d1_mini_lite.menu.baud.230400.linux=230400 -d1_mini_lite.menu.baud.230400.macosx=230400 -d1_mini_lite.menu.baud.230400.upload.speed=230400 -d1_mini_lite.menu.baud.256000.windows=256000 -d1_mini_lite.menu.baud.256000.upload.speed=256000 -d1_mini_lite.menu.baud.460800.linux=460800 -d1_mini_lite.menu.baud.460800.macosx=460800 -d1_mini_lite.menu.baud.460800.upload.speed=460800 -d1_mini_lite.menu.baud.512000.windows=512000 -d1_mini_lite.menu.baud.512000.upload.speed=512000 - -############################################################## -d1.name=WeMos D1 R1 -d1.build.board=ESP8266_WEMOS_D1R1 -d1.build.variant=d1 -d1.upload.tool=esptool -d1.upload.maximum_data_size=81920 -d1.upload.wait_for_upload_port=true -d1.upload.erase_cmd= -d1.serial.disableDTR=true -d1.serial.disableRTS=true -d1.build.mcu=esp8266 -d1.build.core=esp8266 -d1.build.spiffs_pagesize=256 -d1.build.debug_port= -d1.build.debug_level= -d1.menu.xtal.80=80 MHz -d1.menu.xtal.80.build.f_cpu=80000000L -d1.menu.xtal.160=160 MHz -d1.menu.xtal.160.build.f_cpu=160000000L -d1.menu.vt.flash=Flash -d1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1.menu.vt.heap=Heap -d1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1.menu.vt.iram=IRAM -d1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1.menu.exception.enabled=Enabled -d1.menu.exception.enabled.build.exception_flags=-fexceptions -d1.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -d1.menu.exception.disabled=Disabled -d1.menu.exception.disabled.build.exception_flags=-fno-exceptions -d1.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -d1.upload.resetmethod=nodemcu -d1.build.flash_mode=dio -d1.build.flash_freq=40 -d1.menu.eesz.4M=4M (no SPIFFS) -d1.menu.eesz.4M.build.flash_size=4M -d1.menu.eesz.4M.build.flash_size_bytes=0x400000 -d1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -d1.menu.eesz.4M.build.spiffs_pagesize=256 -d1.menu.eesz.4M.upload.maximum_size=1044464 -d1.menu.eesz.4M.build.rfcal_addr=0x3FC000 -d1.menu.eesz.4M1M=4M (1M SPIFFS) -d1.menu.eesz.4M1M.build.flash_size=4M -d1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -d1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1.menu.eesz.4M1M.build.spiffs_pagesize=256 -d1.menu.eesz.4M1M.upload.maximum_size=1044464 -d1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -d1.menu.eesz.4M1M.build.spiffs_start=0x300000 -d1.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -d1.menu.eesz.4M1M.build.spiffs_blocksize=8192 -d1.menu.eesz.4M2M=4M (2M SPIFFS) -d1.menu.eesz.4M2M.build.flash_size=4M -d1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -d1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -d1.menu.eesz.4M2M.build.spiffs_pagesize=256 -d1.menu.eesz.4M2M.upload.maximum_size=1044464 -d1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -d1.menu.eesz.4M2M.build.spiffs_start=0x200000 -d1.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -d1.menu.eesz.4M2M.build.spiffs_blocksize=8192 -d1.menu.eesz.4M3M=4M (3M SPIFFS) -d1.menu.eesz.4M3M.build.flash_size=4M -d1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -d1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -d1.menu.eesz.4M3M.build.spiffs_pagesize=256 -d1.menu.eesz.4M3M.upload.maximum_size=1044464 -d1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -d1.menu.eesz.4M3M.build.spiffs_start=0x100000 -d1.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -d1.menu.eesz.4M3M.build.spiffs_blocksize=8192 -d1.menu.ip.lm2f=v2 Lower Memory -d1.menu.ip.lm2f.build.lwip_include=lwip2/include -d1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -d1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1.menu.ip.hb2f=v2 Higher Bandwidth -d1.menu.ip.hb2f.build.lwip_include=lwip2/include -d1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -d1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1.menu.ip.lm2n=v2 Lower Memory (no features) -d1.menu.ip.lm2n.build.lwip_include=lwip2/include -d1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -d1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1.menu.ip.hb2n=v2 Higher Bandwidth (no features) -d1.menu.ip.hb2n.build.lwip_include=lwip2/include -d1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -d1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1.menu.ip.lm6f=v2 IPv6 Lower Memory -d1.menu.ip.lm6f.build.lwip_include=lwip2/include -d1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -d1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -d1.menu.ip.hb6f.build.lwip_include=lwip2/include -d1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -d1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1.menu.ip.hb1=v1.4 Higher Bandwidth -d1.menu.ip.hb1.build.lwip_lib=-llwip_gcc -d1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -d1.menu.ip.src=v1.4 Compile from source -d1.menu.ip.src.build.lwip_lib=-llwip_src -d1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -d1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1.menu.dbg.Disabled=Disabled -d1.menu.dbg.Disabled.build.debug_port= -d1.menu.dbg.Serial=Serial -d1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1.menu.dbg.Serial1=Serial1 -d1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1.menu.lvl.None____=None -d1.menu.lvl.None____.build.debug_level= -d1.menu.lvl.SSL=SSL -d1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1.menu.lvl.TLS_MEM=TLS_MEM -d1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -d1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1.menu.lvl.HTTP_SERVER=HTTP_SERVER -d1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -d1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.CORE=CORE -d1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1.menu.lvl.WIFI=WIFI -d1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -d1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1.menu.lvl.UPDATER=UPDATER -d1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1.menu.lvl.OTA=OTA -d1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1.menu.lvl.OOM=OOM -d1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -d1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1.menu.wipe.none=Only Sketch -d1.menu.wipe.none.upload.erase_cmd= -d1.menu.wipe.sdk=Sketch + WiFi Settings -d1.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1.menu.wipe.all=All Flash Contents -d1.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1.menu.baud.921600=921600 -d1.menu.baud.921600.upload.speed=921600 -d1.menu.baud.9600=9600 -d1.menu.baud.9600.upload.speed=9600 -d1.menu.baud.57600=57600 -d1.menu.baud.57600.upload.speed=57600 -d1.menu.baud.115200=115200 -d1.menu.baud.115200.upload.speed=115200 -d1.menu.baud.230400.linux=230400 -d1.menu.baud.230400.macosx=230400 -d1.menu.baud.230400.upload.speed=230400 -d1.menu.baud.256000.windows=256000 -d1.menu.baud.256000.upload.speed=256000 -d1.menu.baud.460800.linux=460800 -d1.menu.baud.460800.macosx=460800 -d1.menu.baud.460800.upload.speed=460800 -d1.menu.baud.512000.windows=512000 -d1.menu.baud.512000.upload.speed=512000 - -############################################################## -espino.name=ESPino (ESP-12 Module) -espino.build.board=ESP8266_ESP12 -espino.build.variant=espino -espino.upload.tool=esptool -espino.upload.maximum_data_size=81920 -espino.upload.wait_for_upload_port=true -espino.upload.erase_cmd= -espino.serial.disableDTR=true -espino.serial.disableRTS=true -espino.build.mcu=esp8266 -espino.build.core=esp8266 -espino.build.spiffs_pagesize=256 -espino.build.debug_port= -espino.build.debug_level= -espino.menu.xtal.80=80 MHz -espino.menu.xtal.80.build.f_cpu=80000000L -espino.menu.xtal.160=160 MHz -espino.menu.xtal.160.build.f_cpu=160000000L -espino.menu.vt.flash=Flash -espino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espino.menu.vt.heap=Heap -espino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espino.menu.vt.iram=IRAM -espino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espino.menu.exception.enabled=Enabled -espino.menu.exception.enabled.build.exception_flags=-fexceptions -espino.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -espino.menu.exception.disabled=Disabled -espino.menu.exception.disabled.build.exception_flags=-fno-exceptions -espino.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -espino.menu.ResetMethod.ck=ck -espino.menu.ResetMethod.ck.upload.resetmethod=ck -espino.menu.ResetMethod.nodemcu=nodemcu -espino.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espino.build.flash_mode=qio -espino.build.flash_freq=40 -espino.menu.eesz.4M=4M (no SPIFFS) -espino.menu.eesz.4M.build.flash_size=4M -espino.menu.eesz.4M.build.flash_size_bytes=0x400000 -espino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espino.menu.eesz.4M.build.spiffs_pagesize=256 -espino.menu.eesz.4M.upload.maximum_size=1044464 -espino.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espino.menu.eesz.4M1M=4M (1M SPIFFS) -espino.menu.eesz.4M1M.build.flash_size=4M -espino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espino.menu.eesz.4M1M.build.spiffs_pagesize=256 -espino.menu.eesz.4M1M.upload.maximum_size=1044464 -espino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espino.menu.eesz.4M1M.build.spiffs_start=0x300000 -espino.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -espino.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espino.menu.eesz.4M2M=4M (2M SPIFFS) -espino.menu.eesz.4M2M.build.flash_size=4M -espino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espino.menu.eesz.4M2M.build.spiffs_pagesize=256 -espino.menu.eesz.4M2M.upload.maximum_size=1044464 -espino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espino.menu.eesz.4M2M.build.spiffs_start=0x200000 -espino.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -espino.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espino.menu.eesz.4M3M=4M (3M SPIFFS) -espino.menu.eesz.4M3M.build.flash_size=4M -espino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espino.menu.eesz.4M3M.build.spiffs_pagesize=256 -espino.menu.eesz.4M3M.upload.maximum_size=1044464 -espino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espino.menu.eesz.4M3M.build.spiffs_start=0x100000 -espino.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -espino.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espino.menu.ip.lm2f=v2 Lower Memory -espino.menu.ip.lm2f.build.lwip_include=lwip2/include -espino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espino.menu.ip.hb2f=v2 Higher Bandwidth -espino.menu.ip.hb2f.build.lwip_include=lwip2/include -espino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espino.menu.ip.lm2n=v2 Lower Memory (no features) -espino.menu.ip.lm2n.build.lwip_include=lwip2/include -espino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espino.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espino.menu.ip.hb2n.build.lwip_include=lwip2/include -espino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espino.menu.ip.lm6f=v2 IPv6 Lower Memory -espino.menu.ip.lm6f.build.lwip_include=lwip2/include -espino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espino.menu.ip.hb6f.build.lwip_include=lwip2/include -espino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espino.menu.ip.hb1=v1.4 Higher Bandwidth -espino.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espino.menu.ip.src=v1.4 Compile from source -espino.menu.ip.src.build.lwip_lib=-llwip_src -espino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espino.menu.dbg.Disabled=Disabled -espino.menu.dbg.Disabled.build.debug_port= -espino.menu.dbg.Serial=Serial -espino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espino.menu.dbg.Serial1=Serial1 -espino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espino.menu.lvl.None____=None -espino.menu.lvl.None____.build.debug_level= -espino.menu.lvl.SSL=SSL -espino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espino.menu.lvl.TLS_MEM=TLS_MEM -espino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espino.menu.lvl.HTTP_SERVER=HTTP_SERVER -espino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.CORE=CORE -espino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espino.menu.lvl.WIFI=WIFI -espino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espino.menu.lvl.UPDATER=UPDATER -espino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espino.menu.lvl.OTA=OTA -espino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espino.menu.lvl.OOM=OOM -espino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espino.menu.wipe.none=Only Sketch -espino.menu.wipe.none.upload.erase_cmd= -espino.menu.wipe.sdk=Sketch + WiFi Settings -espino.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espino.menu.wipe.all=All Flash Contents -espino.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espino.menu.baud.115200=115200 -espino.menu.baud.115200.upload.speed=115200 -espino.menu.baud.9600=9600 -espino.menu.baud.9600.upload.speed=9600 -espino.menu.baud.57600=57600 -espino.menu.baud.57600.upload.speed=57600 -espino.menu.baud.230400.linux=230400 -espino.menu.baud.230400.macosx=230400 -espino.menu.baud.230400.upload.speed=230400 -espino.menu.baud.256000.windows=256000 -espino.menu.baud.256000.upload.speed=256000 -espino.menu.baud.460800.linux=460800 -espino.menu.baud.460800.macosx=460800 -espino.menu.baud.460800.upload.speed=460800 -espino.menu.baud.512000.windows=512000 -espino.menu.baud.512000.upload.speed=512000 -espino.menu.baud.921600=921600 -espino.menu.baud.921600.upload.speed=921600 - -############################################################## -espinotee.name=ThaiEasyElec's ESPino -espinotee.build.board=ESP8266_ESP13 -espinotee.build.variant=espinotee -espinotee.upload.tool=esptool -espinotee.upload.maximum_data_size=81920 -espinotee.upload.wait_for_upload_port=true -espinotee.upload.erase_cmd= -espinotee.serial.disableDTR=true -espinotee.serial.disableRTS=true -espinotee.build.mcu=esp8266 -espinotee.build.core=esp8266 -espinotee.build.spiffs_pagesize=256 -espinotee.build.debug_port= -espinotee.build.debug_level= -espinotee.menu.xtal.80=80 MHz -espinotee.menu.xtal.80.build.f_cpu=80000000L -espinotee.menu.xtal.160=160 MHz -espinotee.menu.xtal.160.build.f_cpu=160000000L -espinotee.menu.vt.flash=Flash -espinotee.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espinotee.menu.vt.heap=Heap -espinotee.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espinotee.menu.vt.iram=IRAM -espinotee.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espinotee.menu.exception.enabled=Enabled -espinotee.menu.exception.enabled.build.exception_flags=-fexceptions -espinotee.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -espinotee.menu.exception.disabled=Disabled -espinotee.menu.exception.disabled.build.exception_flags=-fno-exceptions -espinotee.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -espinotee.upload.resetmethod=nodemcu -espinotee.build.flash_mode=qio -espinotee.build.flash_freq=40 -espinotee.menu.eesz.4M=4M (no SPIFFS) -espinotee.menu.eesz.4M.build.flash_size=4M -espinotee.menu.eesz.4M.build.flash_size_bytes=0x400000 -espinotee.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espinotee.menu.eesz.4M.build.spiffs_pagesize=256 -espinotee.menu.eesz.4M.upload.maximum_size=1044464 -espinotee.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espinotee.menu.eesz.4M1M=4M (1M SPIFFS) -espinotee.menu.eesz.4M1M.build.flash_size=4M -espinotee.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espinotee.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espinotee.menu.eesz.4M1M.build.spiffs_pagesize=256 -espinotee.menu.eesz.4M1M.upload.maximum_size=1044464 -espinotee.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espinotee.menu.eesz.4M1M.build.spiffs_start=0x300000 -espinotee.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -espinotee.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espinotee.menu.eesz.4M2M=4M (2M SPIFFS) -espinotee.menu.eesz.4M2M.build.flash_size=4M -espinotee.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espinotee.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espinotee.menu.eesz.4M2M.build.spiffs_pagesize=256 -espinotee.menu.eesz.4M2M.upload.maximum_size=1044464 -espinotee.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espinotee.menu.eesz.4M2M.build.spiffs_start=0x200000 -espinotee.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -espinotee.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espinotee.menu.eesz.4M3M=4M (3M SPIFFS) -espinotee.menu.eesz.4M3M.build.flash_size=4M -espinotee.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espinotee.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espinotee.menu.eesz.4M3M.build.spiffs_pagesize=256 -espinotee.menu.eesz.4M3M.upload.maximum_size=1044464 -espinotee.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espinotee.menu.eesz.4M3M.build.spiffs_start=0x100000 -espinotee.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -espinotee.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espinotee.menu.ip.lm2f=v2 Lower Memory -espinotee.menu.ip.lm2f.build.lwip_include=lwip2/include -espinotee.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espinotee.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espinotee.menu.ip.hb2f=v2 Higher Bandwidth -espinotee.menu.ip.hb2f.build.lwip_include=lwip2/include -espinotee.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espinotee.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espinotee.menu.ip.lm2n=v2 Lower Memory (no features) -espinotee.menu.ip.lm2n.build.lwip_include=lwip2/include -espinotee.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espinotee.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espinotee.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espinotee.menu.ip.hb2n.build.lwip_include=lwip2/include -espinotee.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espinotee.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espinotee.menu.ip.lm6f=v2 IPv6 Lower Memory -espinotee.menu.ip.lm6f.build.lwip_include=lwip2/include -espinotee.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espinotee.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espinotee.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espinotee.menu.ip.hb6f.build.lwip_include=lwip2/include -espinotee.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espinotee.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espinotee.menu.ip.hb1=v1.4 Higher Bandwidth -espinotee.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espinotee.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espinotee.menu.ip.src=v1.4 Compile from source -espinotee.menu.ip.src.build.lwip_lib=-llwip_src -espinotee.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espinotee.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espinotee.menu.dbg.Disabled=Disabled -espinotee.menu.dbg.Disabled.build.debug_port= -espinotee.menu.dbg.Serial=Serial -espinotee.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espinotee.menu.dbg.Serial1=Serial1 -espinotee.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espinotee.menu.lvl.None____=None -espinotee.menu.lvl.None____.build.debug_level= -espinotee.menu.lvl.SSL=SSL -espinotee.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espinotee.menu.lvl.TLS_MEM=TLS_MEM -espinotee.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espinotee.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espinotee.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.lvl.HTTP_SERVER=HTTP_SERVER -espinotee.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espinotee.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espinotee.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espinotee.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espinotee.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espinotee.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espinotee.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.CORE=CORE -espinotee.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espinotee.menu.lvl.WIFI=WIFI -espinotee.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espinotee.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espinotee.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espinotee.menu.lvl.UPDATER=UPDATER -espinotee.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espinotee.menu.lvl.OTA=OTA -espinotee.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espinotee.menu.lvl.OOM=OOM -espinotee.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espinotee.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espinotee.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espinotee.menu.wipe.none=Only Sketch -espinotee.menu.wipe.none.upload.erase_cmd= -espinotee.menu.wipe.sdk=Sketch + WiFi Settings -espinotee.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espinotee.menu.wipe.all=All Flash Contents -espinotee.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espinotee.menu.baud.115200=115200 -espinotee.menu.baud.115200.upload.speed=115200 -espinotee.menu.baud.9600=9600 -espinotee.menu.baud.9600.upload.speed=9600 -espinotee.menu.baud.57600=57600 -espinotee.menu.baud.57600.upload.speed=57600 -espinotee.menu.baud.230400.linux=230400 -espinotee.menu.baud.230400.macosx=230400 -espinotee.menu.baud.230400.upload.speed=230400 -espinotee.menu.baud.256000.windows=256000 -espinotee.menu.baud.256000.upload.speed=256000 -espinotee.menu.baud.460800.linux=460800 -espinotee.menu.baud.460800.macosx=460800 -espinotee.menu.baud.460800.upload.speed=460800 -espinotee.menu.baud.512000.windows=512000 -espinotee.menu.baud.512000.upload.speed=512000 -espinotee.menu.baud.921600=921600 -espinotee.menu.baud.921600.upload.speed=921600 - -############################################################## -wifinfo.name=WifInfo -wifinfo.menu.ESPModule.ESP12.build.board=ESP8266_ESP12 -wifinfo.menu.ESPModule.ESP12.upload.maximum_size=1044464 -wifinfo.menu.ESPModule.ESP12.build.spiffs_pagesize=256 -wifinfo.menu.ESPModule.ESP12.build.flash_ld=eagle.flash.4m1m.ld -wifinfo.menu.ESPModule.ESP07192.build.spiffs_blocksize=4096 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_end=0xFB000 -wifinfo.menu.ESPModule.ESP12=ESP12 (4M/1M SPIFFS) -wifinfo.menu.ESPModule.ESP12.build.spiffs_start=0x300000 -wifinfo.menu.ESPModule.ESP12.build.spiffs_end=0x3FB000 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_start=0xCB000 -wifinfo.menu.ESPModule.ESP07192.build.board=ESP8266_ESP07 -wifinfo.menu.ESPModule.ESP12.build.spiffs_blocksize=8192 -wifinfo.menu.ESPModule.ESP12.build.flash_size=4M -wifinfo.build.board=WIFINFO -wifinfo.build.variant=wifinfo -wifinfo.menu.ESPModule.ESP07192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.ESPModule.ESP07192.build.flash_size=1M -wifinfo.menu.ESPModule.ESP07192=ESP07 (1M/192K SPIFFS) -wifinfo.menu.ESPModule.ESP07192.upload.maximum_size=827376 -wifinfo.upload.tool=esptool -wifinfo.upload.maximum_data_size=81920 -wifinfo.upload.wait_for_upload_port=true -wifinfo.upload.erase_cmd= -wifinfo.serial.disableDTR=true -wifinfo.serial.disableRTS=true -wifinfo.build.mcu=esp8266 -wifinfo.build.core=esp8266 -wifinfo.build.spiffs_pagesize=256 -wifinfo.build.debug_port= -wifinfo.build.debug_level= -wifinfo.menu.xtal.80=80 MHz -wifinfo.menu.xtal.80.build.f_cpu=80000000L -wifinfo.menu.xtal.160=160 MHz -wifinfo.menu.xtal.160.build.f_cpu=160000000L -wifinfo.menu.vt.flash=Flash -wifinfo.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wifinfo.menu.vt.heap=Heap -wifinfo.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wifinfo.menu.vt.iram=IRAM -wifinfo.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wifinfo.menu.exception.enabled=Enabled -wifinfo.menu.exception.enabled.build.exception_flags=-fexceptions -wifinfo.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -wifinfo.menu.exception.disabled=Disabled -wifinfo.menu.exception.disabled.build.exception_flags=-fno-exceptions -wifinfo.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -wifinfo.upload.resetmethod=nodemcu -wifinfo.build.flash_mode=qio -wifinfo.menu.FlashFreq.40=40MHz -wifinfo.menu.FlashFreq.40.build.flash_freq=40 -wifinfo.menu.FlashFreq.80=80MHz -wifinfo.menu.FlashFreq.80.build.flash_freq=80 -wifinfo.menu.eesz.1M=1M (no SPIFFS) -wifinfo.menu.eesz.1M.build.flash_size=1M -wifinfo.menu.eesz.1M.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -wifinfo.menu.eesz.1M.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M.upload.maximum_size=1023984 -wifinfo.menu.eesz.1M.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M64=1M (64K SPIFFS) -wifinfo.menu.eesz.1M64.build.flash_size=1M -wifinfo.menu.eesz.1M64.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -wifinfo.menu.eesz.1M64.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M64.upload.maximum_size=958448 -wifinfo.menu.eesz.1M64.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M64.build.spiffs_start=0xEB000 -wifinfo.menu.eesz.1M64.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M64.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M128=1M (128K SPIFFS) -wifinfo.menu.eesz.1M128.build.flash_size=1M -wifinfo.menu.eesz.1M128.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -wifinfo.menu.eesz.1M128.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M128.upload.maximum_size=892912 -wifinfo.menu.eesz.1M128.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M128.build.spiffs_start=0xDB000 -wifinfo.menu.eesz.1M128.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M128.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M144=1M (144K SPIFFS) -wifinfo.menu.eesz.1M144.build.flash_size=1M -wifinfo.menu.eesz.1M144.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -wifinfo.menu.eesz.1M144.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M144.upload.maximum_size=876528 -wifinfo.menu.eesz.1M144.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M144.build.spiffs_start=0xD7000 -wifinfo.menu.eesz.1M144.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M144.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M160=1M (160K SPIFFS) -wifinfo.menu.eesz.1M160.build.flash_size=1M -wifinfo.menu.eesz.1M160.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -wifinfo.menu.eesz.1M160.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M160.upload.maximum_size=860144 -wifinfo.menu.eesz.1M160.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M160.build.spiffs_start=0xD3000 -wifinfo.menu.eesz.1M160.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M160.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M192=1M (192K SPIFFS) -wifinfo.menu.eesz.1M192.build.flash_size=1M -wifinfo.menu.eesz.1M192.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.eesz.1M192.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M192.upload.maximum_size=827376 -wifinfo.menu.eesz.1M192.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M192.build.spiffs_start=0xCB000 -wifinfo.menu.eesz.1M192.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M192.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M256=1M (256K SPIFFS) -wifinfo.menu.eesz.1M256.build.flash_size=1M -wifinfo.menu.eesz.1M256.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -wifinfo.menu.eesz.1M256.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M256.upload.maximum_size=761840 -wifinfo.menu.eesz.1M256.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M256.build.spiffs_start=0xBB000 -wifinfo.menu.eesz.1M256.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M256.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M512=1M (512K SPIFFS) -wifinfo.menu.eesz.1M512.build.flash_size=1M -wifinfo.menu.eesz.1M512.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -wifinfo.menu.eesz.1M512.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M512.upload.maximum_size=499696 -wifinfo.menu.eesz.1M512.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M512.build.spiffs_start=0x7B000 -wifinfo.menu.eesz.1M512.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M512.build.spiffs_blocksize=4096 -wifinfo.menu.ip.lm2f=v2 Lower Memory -wifinfo.menu.ip.lm2f.build.lwip_include=lwip2/include -wifinfo.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -wifinfo.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifinfo.menu.ip.hb2f=v2 Higher Bandwidth -wifinfo.menu.ip.hb2f.build.lwip_include=lwip2/include -wifinfo.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -wifinfo.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifinfo.menu.ip.lm2n=v2 Lower Memory (no features) -wifinfo.menu.ip.lm2n.build.lwip_include=lwip2/include -wifinfo.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -wifinfo.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifinfo.menu.ip.hb2n=v2 Higher Bandwidth (no features) -wifinfo.menu.ip.hb2n.build.lwip_include=lwip2/include -wifinfo.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -wifinfo.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifinfo.menu.ip.lm6f=v2 IPv6 Lower Memory -wifinfo.menu.ip.lm6f.build.lwip_include=lwip2/include -wifinfo.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -wifinfo.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifinfo.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -wifinfo.menu.ip.hb6f.build.lwip_include=lwip2/include -wifinfo.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -wifinfo.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifinfo.menu.ip.hb1=v1.4 Higher Bandwidth -wifinfo.menu.ip.hb1.build.lwip_lib=-llwip_gcc -wifinfo.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -wifinfo.menu.ip.src=v1.4 Compile from source -wifinfo.menu.ip.src.build.lwip_lib=-llwip_src -wifinfo.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -wifinfo.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifinfo.menu.dbg.Disabled=Disabled -wifinfo.menu.dbg.Disabled.build.debug_port= -wifinfo.menu.dbg.Serial=Serial -wifinfo.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifinfo.menu.dbg.Serial1=Serial1 -wifinfo.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifinfo.menu.lvl.None____=None -wifinfo.menu.lvl.None____.build.debug_level= -wifinfo.menu.lvl.SSL=SSL -wifinfo.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifinfo.menu.lvl.TLS_MEM=TLS_MEM -wifinfo.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifinfo.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -wifinfo.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.lvl.HTTP_SERVER=HTTP_SERVER -wifinfo.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -wifinfo.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifinfo.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifinfo.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifinfo.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifinfo.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.CORE=CORE -wifinfo.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifinfo.menu.lvl.WIFI=WIFI -wifinfo.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifinfo.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -wifinfo.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifinfo.menu.lvl.UPDATER=UPDATER -wifinfo.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifinfo.menu.lvl.OTA=OTA -wifinfo.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifinfo.menu.lvl.OOM=OOM -wifinfo.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifinfo.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -wifinfo.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifinfo.menu.wipe.none=Only Sketch -wifinfo.menu.wipe.none.upload.erase_cmd= -wifinfo.menu.wipe.sdk=Sketch + WiFi Settings -wifinfo.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wifinfo.menu.wipe.all=All Flash Contents -wifinfo.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wifinfo.menu.baud.115200=115200 -wifinfo.menu.baud.115200.upload.speed=115200 -wifinfo.menu.baud.9600=9600 -wifinfo.menu.baud.9600.upload.speed=9600 -wifinfo.menu.baud.57600=57600 -wifinfo.menu.baud.57600.upload.speed=57600 -wifinfo.menu.baud.230400.linux=230400 -wifinfo.menu.baud.230400.macosx=230400 -wifinfo.menu.baud.230400.upload.speed=230400 -wifinfo.menu.baud.256000.windows=256000 -wifinfo.menu.baud.256000.upload.speed=256000 -wifinfo.menu.baud.460800.linux=460800 -wifinfo.menu.baud.460800.macosx=460800 -wifinfo.menu.baud.460800.upload.speed=460800 -wifinfo.menu.baud.512000.windows=512000 -wifinfo.menu.baud.512000.upload.speed=512000 -wifinfo.menu.baud.921600=921600 -wifinfo.menu.baud.921600.upload.speed=921600 - -############################################################## -arduino-esp8266.name=Arduino -arduino-esp8266.menu.BoardModel.starottodeved.build.board=ESP8266_ARDUINO_STAR_OTTO -arduino-esp8266.menu.BoardModel.primo.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.starottodeved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.starottodeved.build.variant=arduino_uart -arduino-esp8266.menu.BoardModel.unowifideved.build.board=ESP8266_ARDUINO_UNOWIFI -arduino-esp8266.menu.BoardModel.unowifideved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.primo=Primo -arduino-esp8266.menu.BoardModel.unowifideved.build.variant=arduino_uart -arduino-esp8266.menu.BoardModel.primo.build.variant=arduino_spi -arduino-esp8266.menu.BoardModel.starottodeved=Star OTTO -arduino-esp8266.build.board=ESP8266_ARDUINO -arduino-esp8266.menu.BoardModel.primo.build.board=ESP8266_ARDUINO_PRIMO -arduino-esp8266.menu.BoardModel.unowifideved=Uno WiFi -arduino-esp8266.upload.tool=esptool -arduino-esp8266.upload.maximum_data_size=81920 -arduino-esp8266.upload.wait_for_upload_port=true -arduino-esp8266.upload.erase_cmd= -arduino-esp8266.serial.disableDTR=true -arduino-esp8266.serial.disableRTS=true -arduino-esp8266.build.mcu=esp8266 -arduino-esp8266.build.core=esp8266 -arduino-esp8266.build.variant=generic -arduino-esp8266.build.spiffs_pagesize=256 -arduino-esp8266.build.debug_port= -arduino-esp8266.build.debug_level= -arduino-esp8266.menu.xtal.80=80 MHz -arduino-esp8266.menu.xtal.80.build.f_cpu=80000000L -arduino-esp8266.menu.xtal.160=160 MHz -arduino-esp8266.menu.xtal.160.build.f_cpu=160000000L -arduino-esp8266.menu.vt.flash=Flash -arduino-esp8266.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -arduino-esp8266.menu.vt.heap=Heap -arduino-esp8266.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -arduino-esp8266.menu.vt.iram=IRAM -arduino-esp8266.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -arduino-esp8266.menu.exception.enabled=Enabled -arduino-esp8266.menu.exception.enabled.build.exception_flags=-fexceptions -arduino-esp8266.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -arduino-esp8266.menu.exception.disabled=Disabled -arduino-esp8266.menu.exception.disabled.build.exception_flags=-fno-exceptions -arduino-esp8266.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -arduino-esp8266.upload.resetmethod=ck -arduino-esp8266.build.flash_mode=qio -arduino-esp8266.build.flash_freq=40 -arduino-esp8266.menu.eesz.4M=4M (no SPIFFS) -arduino-esp8266.menu.eesz.4M.build.flash_size=4M -arduino-esp8266.menu.eesz.4M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -arduino-esp8266.menu.eesz.4M.build.spiffs_pagesize=256 -arduino-esp8266.menu.eesz.4M.upload.maximum_size=1044464 -arduino-esp8266.menu.eesz.4M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.eesz.4M1M=4M (1M SPIFFS) -arduino-esp8266.menu.eesz.4M1M.build.flash_size=4M -arduino-esp8266.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -arduino-esp8266.menu.eesz.4M1M.build.spiffs_pagesize=256 -arduino-esp8266.menu.eesz.4M1M.upload.maximum_size=1044464 -arduino-esp8266.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.eesz.4M1M.build.spiffs_start=0x300000 -arduino-esp8266.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.eesz.4M1M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.eesz.4M2M=4M (2M SPIFFS) -arduino-esp8266.menu.eesz.4M2M.build.flash_size=4M -arduino-esp8266.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -arduino-esp8266.menu.eesz.4M2M.build.spiffs_pagesize=256 -arduino-esp8266.menu.eesz.4M2M.upload.maximum_size=1044464 -arduino-esp8266.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.eesz.4M2M.build.spiffs_start=0x200000 -arduino-esp8266.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.eesz.4M2M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.eesz.4M3M=4M (3M SPIFFS) -arduino-esp8266.menu.eesz.4M3M.build.flash_size=4M -arduino-esp8266.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -arduino-esp8266.menu.eesz.4M3M.build.spiffs_pagesize=256 -arduino-esp8266.menu.eesz.4M3M.upload.maximum_size=1044464 -arduino-esp8266.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.eesz.4M3M.build.spiffs_start=0x100000 -arduino-esp8266.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.eesz.4M3M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.ip.lm2f=v2 Lower Memory -arduino-esp8266.menu.ip.lm2f.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -arduino-esp8266.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -arduino-esp8266.menu.ip.hb2f=v2 Higher Bandwidth -arduino-esp8266.menu.ip.hb2f.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -arduino-esp8266.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -arduino-esp8266.menu.ip.lm2n=v2 Lower Memory (no features) -arduino-esp8266.menu.ip.lm2n.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -arduino-esp8266.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -arduino-esp8266.menu.ip.hb2n=v2 Higher Bandwidth (no features) -arduino-esp8266.menu.ip.hb2n.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -arduino-esp8266.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -arduino-esp8266.menu.ip.lm6f=v2 IPv6 Lower Memory -arduino-esp8266.menu.ip.lm6f.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -arduino-esp8266.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -arduino-esp8266.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -arduino-esp8266.menu.ip.hb6f.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -arduino-esp8266.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -arduino-esp8266.menu.ip.hb1=v1.4 Higher Bandwidth -arduino-esp8266.menu.ip.hb1.build.lwip_lib=-llwip_gcc -arduino-esp8266.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -arduino-esp8266.menu.ip.src=v1.4 Compile from source -arduino-esp8266.menu.ip.src.build.lwip_lib=-llwip_src -arduino-esp8266.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -arduino-esp8266.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -arduino-esp8266.menu.dbg.Disabled=Disabled -arduino-esp8266.menu.dbg.Disabled.build.debug_port= -arduino-esp8266.menu.dbg.Serial=Serial -arduino-esp8266.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -arduino-esp8266.menu.dbg.Serial1=Serial1 -arduino-esp8266.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -arduino-esp8266.menu.lvl.None____=None -arduino-esp8266.menu.lvl.None____.build.debug_level= -arduino-esp8266.menu.lvl.SSL=SSL -arduino-esp8266.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -arduino-esp8266.menu.lvl.TLS_MEM=TLS_MEM -arduino-esp8266.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -arduino-esp8266.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -arduino-esp8266.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.lvl.HTTP_SERVER=HTTP_SERVER -arduino-esp8266.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -arduino-esp8266.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -arduino-esp8266.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -arduino-esp8266.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -arduino-esp8266.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.CORE=CORE -arduino-esp8266.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -arduino-esp8266.menu.lvl.WIFI=WIFI -arduino-esp8266.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -arduino-esp8266.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -arduino-esp8266.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -arduino-esp8266.menu.lvl.UPDATER=UPDATER -arduino-esp8266.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -arduino-esp8266.menu.lvl.OTA=OTA -arduino-esp8266.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -arduino-esp8266.menu.lvl.OOM=OOM -arduino-esp8266.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -arduino-esp8266.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -arduino-esp8266.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -arduino-esp8266.menu.wipe.none=Only Sketch -arduino-esp8266.menu.wipe.none.upload.erase_cmd= -arduino-esp8266.menu.wipe.sdk=Sketch + WiFi Settings -arduino-esp8266.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -arduino-esp8266.menu.wipe.all=All Flash Contents -arduino-esp8266.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -arduino-esp8266.menu.baud.115200=115200 -arduino-esp8266.menu.baud.115200.upload.speed=115200 -arduino-esp8266.menu.baud.9600=9600 -arduino-esp8266.menu.baud.9600.upload.speed=9600 -arduino-esp8266.menu.baud.57600=57600 -arduino-esp8266.menu.baud.57600.upload.speed=57600 -arduino-esp8266.menu.baud.230400.linux=230400 -arduino-esp8266.menu.baud.230400.macosx=230400 -arduino-esp8266.menu.baud.230400.upload.speed=230400 -arduino-esp8266.menu.baud.256000.windows=256000 -arduino-esp8266.menu.baud.256000.upload.speed=256000 -arduino-esp8266.menu.baud.460800.linux=460800 -arduino-esp8266.menu.baud.460800.macosx=460800 -arduino-esp8266.menu.baud.460800.upload.speed=460800 -arduino-esp8266.menu.baud.512000.windows=512000 -arduino-esp8266.menu.baud.512000.upload.speed=512000 -arduino-esp8266.menu.baud.921600=921600 -arduino-esp8266.menu.baud.921600.upload.speed=921600 - -############################################################## -gen4iod.name=4D Systems gen4 IoD Range -gen4iod.build.board=GEN4_IOD -gen4iod.build.f_cpu=160000000L -gen4iod.build.variant=generic -gen4iod.upload.tool=esptool -gen4iod.upload.maximum_data_size=81920 -gen4iod.upload.wait_for_upload_port=true -gen4iod.upload.erase_cmd= -gen4iod.serial.disableDTR=true -gen4iod.serial.disableRTS=true -gen4iod.build.mcu=esp8266 -gen4iod.build.core=esp8266 -gen4iod.build.spiffs_pagesize=256 -gen4iod.build.debug_port= -gen4iod.build.debug_level= -gen4iod.menu.xtal.80=80 MHz -gen4iod.menu.xtal.80.build.f_cpu=80000000L -gen4iod.menu.xtal.160=160 MHz -gen4iod.menu.xtal.160.build.f_cpu=160000000L -gen4iod.menu.vt.flash=Flash -gen4iod.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -gen4iod.menu.vt.heap=Heap -gen4iod.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -gen4iod.menu.vt.iram=IRAM -gen4iod.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -gen4iod.menu.exception.enabled=Enabled -gen4iod.menu.exception.enabled.build.exception_flags=-fexceptions -gen4iod.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -gen4iod.menu.exception.disabled=Disabled -gen4iod.menu.exception.disabled.build.exception_flags=-fno-exceptions -gen4iod.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -gen4iod.upload.resetmethod=nodemcu -gen4iod.build.flash_mode=dio -gen4iod.build.flash_freq=80 -gen4iod.menu.eesz.512K=512K (no SPIFFS) -gen4iod.menu.eesz.512K.build.flash_size=512K -gen4iod.menu.eesz.512K.build.flash_size_bytes=0x80000 -gen4iod.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld -gen4iod.menu.eesz.512K.build.spiffs_pagesize=256 -gen4iod.menu.eesz.512K.upload.maximum_size=499696 -gen4iod.menu.eesz.512K.build.rfcal_addr=0x7C000 -gen4iod.menu.eesz.512K32=512K (32K SPIFFS) -gen4iod.menu.eesz.512K32.build.flash_size=512K -gen4iod.menu.eesz.512K32.build.flash_size_bytes=0x80000 -gen4iod.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld -gen4iod.menu.eesz.512K32.build.spiffs_pagesize=256 -gen4iod.menu.eesz.512K32.upload.maximum_size=466928 -gen4iod.menu.eesz.512K32.build.rfcal_addr=0x7C000 -gen4iod.menu.eesz.512K32.build.spiffs_start=0x73000 -gen4iod.menu.eesz.512K32.build.spiffs_end=0x7B000 -gen4iod.menu.eesz.512K32.build.spiffs_blocksize=4096 -gen4iod.menu.eesz.512K64=512K (64K SPIFFS) -gen4iod.menu.eesz.512K64.build.flash_size=512K -gen4iod.menu.eesz.512K64.build.flash_size_bytes=0x80000 -gen4iod.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld -gen4iod.menu.eesz.512K64.build.spiffs_pagesize=256 -gen4iod.menu.eesz.512K64.upload.maximum_size=434160 -gen4iod.menu.eesz.512K64.build.rfcal_addr=0x7C000 -gen4iod.menu.eesz.512K64.build.spiffs_start=0x6B000 -gen4iod.menu.eesz.512K64.build.spiffs_end=0x7B000 -gen4iod.menu.eesz.512K64.build.spiffs_blocksize=4096 -gen4iod.menu.eesz.512K128=512K (128K SPIFFS) -gen4iod.menu.eesz.512K128.build.flash_size=512K -gen4iod.menu.eesz.512K128.build.flash_size_bytes=0x80000 -gen4iod.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld -gen4iod.menu.eesz.512K128.build.spiffs_pagesize=256 -gen4iod.menu.eesz.512K128.upload.maximum_size=368624 -gen4iod.menu.eesz.512K128.build.rfcal_addr=0x7C000 -gen4iod.menu.eesz.512K128.build.spiffs_start=0x5B000 -gen4iod.menu.eesz.512K128.build.spiffs_end=0x7B000 -gen4iod.menu.eesz.512K128.build.spiffs_blocksize=4096 -gen4iod.menu.ip.lm2f=v2 Lower Memory -gen4iod.menu.ip.lm2f.build.lwip_include=lwip2/include -gen4iod.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -gen4iod.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -gen4iod.menu.ip.hb2f=v2 Higher Bandwidth -gen4iod.menu.ip.hb2f.build.lwip_include=lwip2/include -gen4iod.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -gen4iod.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -gen4iod.menu.ip.lm2n=v2 Lower Memory (no features) -gen4iod.menu.ip.lm2n.build.lwip_include=lwip2/include -gen4iod.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -gen4iod.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -gen4iod.menu.ip.hb2n=v2 Higher Bandwidth (no features) -gen4iod.menu.ip.hb2n.build.lwip_include=lwip2/include -gen4iod.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -gen4iod.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -gen4iod.menu.ip.lm6f=v2 IPv6 Lower Memory -gen4iod.menu.ip.lm6f.build.lwip_include=lwip2/include -gen4iod.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -gen4iod.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -gen4iod.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -gen4iod.menu.ip.hb6f.build.lwip_include=lwip2/include -gen4iod.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -gen4iod.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -gen4iod.menu.ip.hb1=v1.4 Higher Bandwidth -gen4iod.menu.ip.hb1.build.lwip_lib=-llwip_gcc -gen4iod.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -gen4iod.menu.ip.src=v1.4 Compile from source -gen4iod.menu.ip.src.build.lwip_lib=-llwip_src -gen4iod.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -gen4iod.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -gen4iod.menu.dbg.Disabled=Disabled -gen4iod.menu.dbg.Disabled.build.debug_port= -gen4iod.menu.dbg.Serial=Serial -gen4iod.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -gen4iod.menu.dbg.Serial1=Serial1 -gen4iod.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -gen4iod.menu.lvl.None____=None -gen4iod.menu.lvl.None____.build.debug_level= -gen4iod.menu.lvl.SSL=SSL -gen4iod.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -gen4iod.menu.lvl.TLS_MEM=TLS_MEM -gen4iod.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -gen4iod.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -gen4iod.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.lvl.HTTP_SERVER=HTTP_SERVER -gen4iod.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -gen4iod.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -gen4iod.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -gen4iod.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -gen4iod.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -gen4iod.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.CORE=CORE -gen4iod.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -gen4iod.menu.lvl.WIFI=WIFI -gen4iod.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -gen4iod.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -gen4iod.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -gen4iod.menu.lvl.UPDATER=UPDATER -gen4iod.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -gen4iod.menu.lvl.OTA=OTA -gen4iod.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -gen4iod.menu.lvl.OOM=OOM -gen4iod.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -gen4iod.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -gen4iod.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -gen4iod.menu.wipe.none=Only Sketch -gen4iod.menu.wipe.none.upload.erase_cmd= -gen4iod.menu.wipe.sdk=Sketch + WiFi Settings -gen4iod.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -gen4iod.menu.wipe.all=All Flash Contents -gen4iod.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -gen4iod.menu.baud.115200=115200 -gen4iod.menu.baud.115200.upload.speed=115200 -gen4iod.menu.baud.9600=9600 -gen4iod.menu.baud.9600.upload.speed=9600 -gen4iod.menu.baud.57600=57600 -gen4iod.menu.baud.57600.upload.speed=57600 -gen4iod.menu.baud.230400.linux=230400 -gen4iod.menu.baud.230400.macosx=230400 -gen4iod.menu.baud.230400.upload.speed=230400 -gen4iod.menu.baud.256000.windows=256000 -gen4iod.menu.baud.256000.upload.speed=256000 -gen4iod.menu.baud.460800.linux=460800 -gen4iod.menu.baud.460800.macosx=460800 -gen4iod.menu.baud.460800.upload.speed=460800 -gen4iod.menu.baud.512000.windows=512000 -gen4iod.menu.baud.512000.upload.speed=512000 -gen4iod.menu.baud.921600=921600 -gen4iod.menu.baud.921600.upload.speed=921600 - -############################################################## -oak.name=Digistump Oak -oak.build.board=ESP8266_OAK -oak.build.variant=oak -oak.upload.maximum_size=1040368 -oak.upload.tool=esptool -oak.upload.maximum_data_size=81920 -oak.upload.wait_for_upload_port=true -oak.upload.erase_cmd= -oak.serial.disableDTR=true -oak.serial.disableRTS=true -oak.build.mcu=esp8266 -oak.build.core=esp8266 -oak.build.spiffs_pagesize=256 -oak.build.debug_port= -oak.build.debug_level= -oak.menu.xtal.80=80 MHz -oak.menu.xtal.80.build.f_cpu=80000000L -oak.menu.xtal.160=160 MHz -oak.menu.xtal.160.build.f_cpu=160000000L -oak.menu.vt.flash=Flash -oak.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -oak.menu.vt.heap=Heap -oak.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -oak.menu.vt.iram=IRAM -oak.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -oak.menu.exception.enabled=Enabled -oak.menu.exception.enabled.build.exception_flags=-fexceptions -oak.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -oak.menu.exception.disabled=Disabled -oak.menu.exception.disabled.build.exception_flags=-fno-exceptions -oak.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -oak.upload.resetmethod=none -oak.build.flash_mode=dio -oak.build.flash_freq=40 -oak.menu.eesz.4M=4M (no SPIFFS) -oak.menu.eesz.4M.build.flash_size=4M -oak.menu.eesz.4M.build.flash_size_bytes=0x400000 -oak.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -oak.menu.eesz.4M.build.spiffs_pagesize=256 -oak.menu.eesz.4M.upload.maximum_size=1044464 -oak.menu.eesz.4M.build.rfcal_addr=0x3FC000 -oak.menu.eesz.4M1M=4M (1M SPIFFS) -oak.menu.eesz.4M1M.build.flash_size=4M -oak.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -oak.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -oak.menu.eesz.4M1M.build.spiffs_pagesize=256 -oak.menu.eesz.4M1M.upload.maximum_size=1044464 -oak.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -oak.menu.eesz.4M1M.build.spiffs_start=0x300000 -oak.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -oak.menu.eesz.4M1M.build.spiffs_blocksize=8192 -oak.menu.eesz.4M2M=4M (2M SPIFFS) -oak.menu.eesz.4M2M.build.flash_size=4M -oak.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -oak.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -oak.menu.eesz.4M2M.build.spiffs_pagesize=256 -oak.menu.eesz.4M2M.upload.maximum_size=1044464 -oak.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -oak.menu.eesz.4M2M.build.spiffs_start=0x200000 -oak.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -oak.menu.eesz.4M2M.build.spiffs_blocksize=8192 -oak.menu.eesz.4M3M=4M (3M SPIFFS) -oak.menu.eesz.4M3M.build.flash_size=4M -oak.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -oak.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -oak.menu.eesz.4M3M.build.spiffs_pagesize=256 -oak.menu.eesz.4M3M.upload.maximum_size=1044464 -oak.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -oak.menu.eesz.4M3M.build.spiffs_start=0x100000 -oak.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -oak.menu.eesz.4M3M.build.spiffs_blocksize=8192 -oak.menu.ip.lm2f=v2 Lower Memory -oak.menu.ip.lm2f.build.lwip_include=lwip2/include -oak.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -oak.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -oak.menu.ip.hb2f=v2 Higher Bandwidth -oak.menu.ip.hb2f.build.lwip_include=lwip2/include -oak.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -oak.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -oak.menu.ip.lm2n=v2 Lower Memory (no features) -oak.menu.ip.lm2n.build.lwip_include=lwip2/include -oak.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -oak.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -oak.menu.ip.hb2n=v2 Higher Bandwidth (no features) -oak.menu.ip.hb2n.build.lwip_include=lwip2/include -oak.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -oak.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -oak.menu.ip.lm6f=v2 IPv6 Lower Memory -oak.menu.ip.lm6f.build.lwip_include=lwip2/include -oak.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -oak.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -oak.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -oak.menu.ip.hb6f.build.lwip_include=lwip2/include -oak.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -oak.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -oak.menu.ip.hb1=v1.4 Higher Bandwidth -oak.menu.ip.hb1.build.lwip_lib=-llwip_gcc -oak.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -oak.menu.ip.src=v1.4 Compile from source -oak.menu.ip.src.build.lwip_lib=-llwip_src -oak.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -oak.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -oak.menu.dbg.Disabled=Disabled -oak.menu.dbg.Disabled.build.debug_port= -oak.menu.dbg.Serial=Serial -oak.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -oak.menu.dbg.Serial1=Serial1 -oak.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -oak.menu.lvl.None____=None -oak.menu.lvl.None____.build.debug_level= -oak.menu.lvl.SSL=SSL -oak.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -oak.menu.lvl.TLS_MEM=TLS_MEM -oak.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -oak.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -oak.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -oak.menu.lvl.HTTP_SERVER=HTTP_SERVER -oak.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -oak.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -oak.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -oak.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -oak.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -oak.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -oak.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -oak.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -oak.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -oak.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -oak.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -oak.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.CORE=CORE -oak.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -oak.menu.lvl.WIFI=WIFI -oak.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -oak.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -oak.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -oak.menu.lvl.UPDATER=UPDATER -oak.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -oak.menu.lvl.OTA=OTA -oak.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -oak.menu.lvl.OOM=OOM -oak.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -oak.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -oak.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -oak.menu.wipe.none=Only Sketch -oak.menu.wipe.none.upload.erase_cmd= -oak.menu.wipe.sdk=Sketch + WiFi Settings -oak.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -oak.menu.wipe.all=All Flash Contents -oak.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -oak.menu.baud.921600=921600 -oak.menu.baud.921600.upload.speed=921600 -oak.menu.baud.9600=9600 -oak.menu.baud.9600.upload.speed=9600 -oak.menu.baud.57600=57600 -oak.menu.baud.57600.upload.speed=57600 -oak.menu.baud.115200=115200 -oak.menu.baud.115200.upload.speed=115200 -oak.menu.baud.230400.linux=230400 -oak.menu.baud.230400.macosx=230400 -oak.menu.baud.230400.upload.speed=230400 -oak.menu.baud.256000.windows=256000 -oak.menu.baud.256000.upload.speed=256000 -oak.menu.baud.460800.linux=460800 -oak.menu.baud.460800.macosx=460800 -oak.menu.baud.460800.upload.speed=460800 -oak.menu.baud.512000.windows=512000 -oak.menu.baud.512000.upload.speed=512000 - -############################################################## -wifiduino.name=WiFiduino -wifiduino.build.board=WIFIDUINO_ESP8266 -wifiduino.build.variant=wifiduino -wifiduino.upload.tool=esptool -wifiduino.upload.maximum_data_size=81920 -wifiduino.upload.wait_for_upload_port=true -wifiduino.upload.erase_cmd= -wifiduino.serial.disableDTR=true -wifiduino.serial.disableRTS=true -wifiduino.build.mcu=esp8266 -wifiduino.build.core=esp8266 -wifiduino.build.spiffs_pagesize=256 -wifiduino.build.debug_port= -wifiduino.build.debug_level= -wifiduino.menu.xtal.80=80 MHz -wifiduino.menu.xtal.80.build.f_cpu=80000000L -wifiduino.menu.xtal.160=160 MHz -wifiduino.menu.xtal.160.build.f_cpu=160000000L -wifiduino.menu.vt.flash=Flash -wifiduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wifiduino.menu.vt.heap=Heap -wifiduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wifiduino.menu.vt.iram=IRAM -wifiduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wifiduino.menu.exception.enabled=Enabled -wifiduino.menu.exception.enabled.build.exception_flags=-fexceptions -wifiduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -wifiduino.menu.exception.disabled=Disabled -wifiduino.menu.exception.disabled.build.exception_flags=-fno-exceptions -wifiduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -wifiduino.upload.resetmethod=nodemcu -wifiduino.build.flash_mode=dio -wifiduino.build.flash_freq=40 -wifiduino.menu.eesz.4M=4M (no SPIFFS) -wifiduino.menu.eesz.4M.build.flash_size=4M -wifiduino.menu.eesz.4M.build.flash_size_bytes=0x400000 -wifiduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -wifiduino.menu.eesz.4M.build.spiffs_pagesize=256 -wifiduino.menu.eesz.4M.upload.maximum_size=1044464 -wifiduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 -wifiduino.menu.eesz.4M1M=4M (1M SPIFFS) -wifiduino.menu.eesz.4M1M.build.flash_size=4M -wifiduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -wifiduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -wifiduino.menu.eesz.4M1M.build.spiffs_pagesize=256 -wifiduino.menu.eesz.4M1M.upload.maximum_size=1044464 -wifiduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -wifiduino.menu.eesz.4M1M.build.spiffs_start=0x300000 -wifiduino.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -wifiduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 -wifiduino.menu.eesz.4M2M=4M (2M SPIFFS) -wifiduino.menu.eesz.4M2M.build.flash_size=4M -wifiduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -wifiduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -wifiduino.menu.eesz.4M2M.build.spiffs_pagesize=256 -wifiduino.menu.eesz.4M2M.upload.maximum_size=1044464 -wifiduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -wifiduino.menu.eesz.4M2M.build.spiffs_start=0x200000 -wifiduino.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -wifiduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 -wifiduino.menu.eesz.4M3M=4M (3M SPIFFS) -wifiduino.menu.eesz.4M3M.build.flash_size=4M -wifiduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -wifiduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -wifiduino.menu.eesz.4M3M.build.spiffs_pagesize=256 -wifiduino.menu.eesz.4M3M.upload.maximum_size=1044464 -wifiduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -wifiduino.menu.eesz.4M3M.build.spiffs_start=0x100000 -wifiduino.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -wifiduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 -wifiduino.menu.ip.lm2f=v2 Lower Memory -wifiduino.menu.ip.lm2f.build.lwip_include=lwip2/include -wifiduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -wifiduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifiduino.menu.ip.hb2f=v2 Higher Bandwidth -wifiduino.menu.ip.hb2f.build.lwip_include=lwip2/include -wifiduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -wifiduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifiduino.menu.ip.lm2n=v2 Lower Memory (no features) -wifiduino.menu.ip.lm2n.build.lwip_include=lwip2/include -wifiduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -wifiduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifiduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) -wifiduino.menu.ip.hb2n.build.lwip_include=lwip2/include -wifiduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -wifiduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifiduino.menu.ip.lm6f=v2 IPv6 Lower Memory -wifiduino.menu.ip.lm6f.build.lwip_include=lwip2/include -wifiduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -wifiduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifiduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -wifiduino.menu.ip.hb6f.build.lwip_include=lwip2/include -wifiduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -wifiduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifiduino.menu.ip.hb1=v1.4 Higher Bandwidth -wifiduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc -wifiduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -wifiduino.menu.ip.src=v1.4 Compile from source -wifiduino.menu.ip.src.build.lwip_lib=-llwip_src -wifiduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -wifiduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifiduino.menu.dbg.Disabled=Disabled -wifiduino.menu.dbg.Disabled.build.debug_port= -wifiduino.menu.dbg.Serial=Serial -wifiduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifiduino.menu.dbg.Serial1=Serial1 -wifiduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifiduino.menu.lvl.None____=None -wifiduino.menu.lvl.None____.build.debug_level= -wifiduino.menu.lvl.SSL=SSL -wifiduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifiduino.menu.lvl.TLS_MEM=TLS_MEM -wifiduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifiduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -wifiduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.lvl.HTTP_SERVER=HTTP_SERVER -wifiduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -wifiduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifiduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifiduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifiduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifiduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.CORE=CORE -wifiduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifiduino.menu.lvl.WIFI=WIFI -wifiduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifiduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -wifiduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifiduino.menu.lvl.UPDATER=UPDATER -wifiduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifiduino.menu.lvl.OTA=OTA -wifiduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifiduino.menu.lvl.OOM=OOM -wifiduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifiduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -wifiduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifiduino.menu.wipe.none=Only Sketch -wifiduino.menu.wipe.none.upload.erase_cmd= -wifiduino.menu.wipe.sdk=Sketch + WiFi Settings -wifiduino.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wifiduino.menu.wipe.all=All Flash Contents -wifiduino.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wifiduino.menu.baud.921600=921600 -wifiduino.menu.baud.921600.upload.speed=921600 -wifiduino.menu.baud.9600=9600 -wifiduino.menu.baud.9600.upload.speed=9600 -wifiduino.menu.baud.57600=57600 -wifiduino.menu.baud.57600.upload.speed=57600 -wifiduino.menu.baud.115200=115200 -wifiduino.menu.baud.115200.upload.speed=115200 -wifiduino.menu.baud.230400.linux=230400 -wifiduino.menu.baud.230400.macosx=230400 -wifiduino.menu.baud.230400.upload.speed=230400 -wifiduino.menu.baud.256000.windows=256000 -wifiduino.menu.baud.256000.upload.speed=256000 -wifiduino.menu.baud.460800.linux=460800 -wifiduino.menu.baud.460800.macosx=460800 -wifiduino.menu.baud.460800.upload.speed=460800 -wifiduino.menu.baud.512000.windows=512000 -wifiduino.menu.baud.512000.upload.speed=512000 - -############################################################## -wifi_slot.name=Amperka WiFi Slot -wifi_slot.build.board=AMPERKA_WIFI_SLOT -wifi_slot.build.variant=wifi_slot -wifi_slot.upload.tool=esptool -wifi_slot.upload.maximum_data_size=81920 -wifi_slot.upload.wait_for_upload_port=true -wifi_slot.upload.erase_cmd= -wifi_slot.serial.disableDTR=true -wifi_slot.serial.disableRTS=true -wifi_slot.build.mcu=esp8266 -wifi_slot.build.core=esp8266 -wifi_slot.build.spiffs_pagesize=256 -wifi_slot.build.debug_port= -wifi_slot.build.debug_level= -wifi_slot.menu.xtal.80=80 MHz -wifi_slot.menu.xtal.80.build.f_cpu=80000000L -wifi_slot.menu.xtal.160=160 MHz -wifi_slot.menu.xtal.160.build.f_cpu=160000000L -wifi_slot.menu.vt.flash=Flash -wifi_slot.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wifi_slot.menu.vt.heap=Heap -wifi_slot.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wifi_slot.menu.vt.iram=IRAM -wifi_slot.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wifi_slot.menu.exception.enabled=Enabled -wifi_slot.menu.exception.enabled.build.exception_flags=-fexceptions -wifi_slot.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -wifi_slot.menu.exception.disabled=Disabled -wifi_slot.menu.exception.disabled.build.exception_flags=-fno-exceptions -wifi_slot.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -wifi_slot.upload.resetmethod=nodemcu -wifi_slot.menu.FlashFreq.40=40MHz -wifi_slot.menu.FlashFreq.40.build.flash_freq=40 -wifi_slot.menu.FlashFreq.80=80MHz -wifi_slot.menu.FlashFreq.80.build.flash_freq=80 -wifi_slot.menu.FlashMode.qio=QIO -wifi_slot.menu.FlashMode.qio.build.flash_mode=qio -wifi_slot.menu.FlashMode.qout=QOUT -wifi_slot.menu.FlashMode.qout.build.flash_mode=qout -wifi_slot.menu.FlashMode.dio=DIO -wifi_slot.menu.FlashMode.dio.build.flash_mode=dio -wifi_slot.menu.FlashMode.dout=DOUT -wifi_slot.menu.FlashMode.dout.build.flash_mode=dout -wifi_slot.menu.eesz.1M=1M (no SPIFFS) -wifi_slot.menu.eesz.1M.build.flash_size=1M -wifi_slot.menu.eesz.1M.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -wifi_slot.menu.eesz.1M.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M.upload.maximum_size=1023984 -wifi_slot.menu.eesz.1M.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M64=1M (64K SPIFFS) -wifi_slot.menu.eesz.1M64.build.flash_size=1M -wifi_slot.menu.eesz.1M64.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -wifi_slot.menu.eesz.1M64.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M64.upload.maximum_size=958448 -wifi_slot.menu.eesz.1M64.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M64.build.spiffs_start=0xEB000 -wifi_slot.menu.eesz.1M64.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M64.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M128=1M (128K SPIFFS) -wifi_slot.menu.eesz.1M128.build.flash_size=1M -wifi_slot.menu.eesz.1M128.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -wifi_slot.menu.eesz.1M128.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M128.upload.maximum_size=892912 -wifi_slot.menu.eesz.1M128.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M128.build.spiffs_start=0xDB000 -wifi_slot.menu.eesz.1M128.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M128.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M144=1M (144K SPIFFS) -wifi_slot.menu.eesz.1M144.build.flash_size=1M -wifi_slot.menu.eesz.1M144.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -wifi_slot.menu.eesz.1M144.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M144.upload.maximum_size=876528 -wifi_slot.menu.eesz.1M144.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M144.build.spiffs_start=0xD7000 -wifi_slot.menu.eesz.1M144.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M144.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M160=1M (160K SPIFFS) -wifi_slot.menu.eesz.1M160.build.flash_size=1M -wifi_slot.menu.eesz.1M160.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -wifi_slot.menu.eesz.1M160.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M160.upload.maximum_size=860144 -wifi_slot.menu.eesz.1M160.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M160.build.spiffs_start=0xD3000 -wifi_slot.menu.eesz.1M160.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M160.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M192=1M (192K SPIFFS) -wifi_slot.menu.eesz.1M192.build.flash_size=1M -wifi_slot.menu.eesz.1M192.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -wifi_slot.menu.eesz.1M192.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M192.upload.maximum_size=827376 -wifi_slot.menu.eesz.1M192.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M192.build.spiffs_start=0xCB000 -wifi_slot.menu.eesz.1M192.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M192.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M256=1M (256K SPIFFS) -wifi_slot.menu.eesz.1M256.build.flash_size=1M -wifi_slot.menu.eesz.1M256.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -wifi_slot.menu.eesz.1M256.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M256.upload.maximum_size=761840 -wifi_slot.menu.eesz.1M256.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M256.build.spiffs_start=0xBB000 -wifi_slot.menu.eesz.1M256.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M256.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M512=1M (512K SPIFFS) -wifi_slot.menu.eesz.1M512.build.flash_size=1M -wifi_slot.menu.eesz.1M512.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -wifi_slot.menu.eesz.1M512.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M512.upload.maximum_size=499696 -wifi_slot.menu.eesz.1M512.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M512.build.spiffs_start=0x7B000 -wifi_slot.menu.eesz.1M512.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M512.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.2M=2M (no SPIFFS) -wifi_slot.menu.eesz.2M.build.flash_size=2M -wifi_slot.menu.eesz.2M.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld -wifi_slot.menu.eesz.2M.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M128=2M (128K SPIFFS) -wifi_slot.menu.eesz.2M128.build.flash_size=2M -wifi_slot.menu.eesz.2M128.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld -wifi_slot.menu.eesz.2M128.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M128.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M128.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M128.build.spiffs_start=0x1E0000 -wifi_slot.menu.eesz.2M128.build.spiffs_end=0x1FB000 -wifi_slot.menu.eesz.2M128.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.2M256=2M (256K SPIFFS) -wifi_slot.menu.eesz.2M256.build.flash_size=2M -wifi_slot.menu.eesz.2M256.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld -wifi_slot.menu.eesz.2M256.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M256.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M256.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M256.build.spiffs_start=0x1C0000 -wifi_slot.menu.eesz.2M256.build.spiffs_end=0x1FB000 -wifi_slot.menu.eesz.2M256.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.2M512=2M (512K SPIFFS) -wifi_slot.menu.eesz.2M512.build.flash_size=2M -wifi_slot.menu.eesz.2M512.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld -wifi_slot.menu.eesz.2M512.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M512.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M512.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M512.build.spiffs_start=0x180000 -wifi_slot.menu.eesz.2M512.build.spiffs_end=0x1FB000 -wifi_slot.menu.eesz.2M512.build.spiffs_blocksize=8192 -wifi_slot.menu.eesz.2M1M=2M (1M SPIFFS) -wifi_slot.menu.eesz.2M1M.build.flash_size=2M -wifi_slot.menu.eesz.2M1M.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld -wifi_slot.menu.eesz.2M1M.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M1M.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M1M.build.spiffs_start=0x100000 -wifi_slot.menu.eesz.2M1M.build.spiffs_end=0x1FB000 -wifi_slot.menu.eesz.2M1M.build.spiffs_blocksize=8192 -wifi_slot.menu.ip.lm2f=v2 Lower Memory -wifi_slot.menu.ip.lm2f.build.lwip_include=lwip2/include -wifi_slot.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -wifi_slot.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifi_slot.menu.ip.hb2f=v2 Higher Bandwidth -wifi_slot.menu.ip.hb2f.build.lwip_include=lwip2/include -wifi_slot.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -wifi_slot.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifi_slot.menu.ip.lm2n=v2 Lower Memory (no features) -wifi_slot.menu.ip.lm2n.build.lwip_include=lwip2/include -wifi_slot.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -wifi_slot.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifi_slot.menu.ip.hb2n=v2 Higher Bandwidth (no features) -wifi_slot.menu.ip.hb2n.build.lwip_include=lwip2/include -wifi_slot.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -wifi_slot.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifi_slot.menu.ip.lm6f=v2 IPv6 Lower Memory -wifi_slot.menu.ip.lm6f.build.lwip_include=lwip2/include -wifi_slot.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -wifi_slot.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifi_slot.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -wifi_slot.menu.ip.hb6f.build.lwip_include=lwip2/include -wifi_slot.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -wifi_slot.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifi_slot.menu.ip.hb1=v1.4 Higher Bandwidth -wifi_slot.menu.ip.hb1.build.lwip_lib=-llwip_gcc -wifi_slot.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -wifi_slot.menu.ip.src=v1.4 Compile from source -wifi_slot.menu.ip.src.build.lwip_lib=-llwip_src -wifi_slot.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -wifi_slot.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifi_slot.menu.dbg.Disabled=Disabled -wifi_slot.menu.dbg.Disabled.build.debug_port= -wifi_slot.menu.dbg.Serial=Serial -wifi_slot.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifi_slot.menu.dbg.Serial1=Serial1 -wifi_slot.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifi_slot.menu.lvl.None____=None -wifi_slot.menu.lvl.None____.build.debug_level= -wifi_slot.menu.lvl.SSL=SSL -wifi_slot.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifi_slot.menu.lvl.TLS_MEM=TLS_MEM -wifi_slot.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifi_slot.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -wifi_slot.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.lvl.HTTP_SERVER=HTTP_SERVER -wifi_slot.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -wifi_slot.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifi_slot.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifi_slot.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifi_slot.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.CORE=CORE -wifi_slot.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifi_slot.menu.lvl.WIFI=WIFI -wifi_slot.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifi_slot.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -wifi_slot.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifi_slot.menu.lvl.UPDATER=UPDATER -wifi_slot.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifi_slot.menu.lvl.OTA=OTA -wifi_slot.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifi_slot.menu.lvl.OOM=OOM -wifi_slot.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifi_slot.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -wifi_slot.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifi_slot.menu.wipe.none=Only Sketch -wifi_slot.menu.wipe.none.upload.erase_cmd= -wifi_slot.menu.wipe.sdk=Sketch + WiFi Settings -wifi_slot.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wifi_slot.menu.wipe.all=All Flash Contents -wifi_slot.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wifi_slot.menu.baud.115200=115200 -wifi_slot.menu.baud.115200.upload.speed=115200 -wifi_slot.menu.baud.9600=9600 -wifi_slot.menu.baud.9600.upload.speed=9600 -wifi_slot.menu.baud.57600=57600 -wifi_slot.menu.baud.57600.upload.speed=57600 -wifi_slot.menu.baud.230400.linux=230400 -wifi_slot.menu.baud.230400.macosx=230400 -wifi_slot.menu.baud.230400.upload.speed=230400 -wifi_slot.menu.baud.256000.windows=256000 -wifi_slot.menu.baud.256000.upload.speed=256000 -wifi_slot.menu.baud.460800.linux=460800 -wifi_slot.menu.baud.460800.macosx=460800 -wifi_slot.menu.baud.460800.upload.speed=460800 -wifi_slot.menu.baud.512000.windows=512000 -wifi_slot.menu.baud.512000.upload.speed=512000 -wifi_slot.menu.baud.921600=921600 -wifi_slot.menu.baud.921600.upload.speed=921600 - -############################################################## -wiolink.name=Seeed Wio Link -wiolink.build.board=ESP8266_WIO_LINK -wiolink.build.variant=wiolink -wiolink.upload.tool=esptool -wiolink.upload.maximum_data_size=81920 -wiolink.upload.wait_for_upload_port=true -wiolink.upload.erase_cmd= -wiolink.serial.disableDTR=true -wiolink.serial.disableRTS=true -wiolink.build.mcu=esp8266 -wiolink.build.core=esp8266 -wiolink.build.spiffs_pagesize=256 -wiolink.build.debug_port= -wiolink.build.debug_level= -wiolink.menu.xtal.80=80 MHz -wiolink.menu.xtal.80.build.f_cpu=80000000L -wiolink.menu.xtal.160=160 MHz -wiolink.menu.xtal.160.build.f_cpu=160000000L -wiolink.menu.vt.flash=Flash -wiolink.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wiolink.menu.vt.heap=Heap -wiolink.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wiolink.menu.vt.iram=IRAM -wiolink.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wiolink.menu.exception.enabled=Enabled -wiolink.menu.exception.enabled.build.exception_flags=-fexceptions -wiolink.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -wiolink.menu.exception.disabled=Disabled -wiolink.menu.exception.disabled.build.exception_flags=-fno-exceptions -wiolink.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -wiolink.upload.resetmethod=nodemcu -wiolink.build.flash_mode=qio -wiolink.build.flash_freq=40 -wiolink.menu.eesz.4M=4M (no SPIFFS) -wiolink.menu.eesz.4M.build.flash_size=4M -wiolink.menu.eesz.4M.build.flash_size_bytes=0x400000 -wiolink.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -wiolink.menu.eesz.4M.build.spiffs_pagesize=256 -wiolink.menu.eesz.4M.upload.maximum_size=1044464 -wiolink.menu.eesz.4M.build.rfcal_addr=0x3FC000 -wiolink.menu.eesz.4M1M=4M (1M SPIFFS) -wiolink.menu.eesz.4M1M.build.flash_size=4M -wiolink.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -wiolink.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -wiolink.menu.eesz.4M1M.build.spiffs_pagesize=256 -wiolink.menu.eesz.4M1M.upload.maximum_size=1044464 -wiolink.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -wiolink.menu.eesz.4M1M.build.spiffs_start=0x300000 -wiolink.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -wiolink.menu.eesz.4M1M.build.spiffs_blocksize=8192 -wiolink.menu.eesz.4M2M=4M (2M SPIFFS) -wiolink.menu.eesz.4M2M.build.flash_size=4M -wiolink.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -wiolink.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -wiolink.menu.eesz.4M2M.build.spiffs_pagesize=256 -wiolink.menu.eesz.4M2M.upload.maximum_size=1044464 -wiolink.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -wiolink.menu.eesz.4M2M.build.spiffs_start=0x200000 -wiolink.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -wiolink.menu.eesz.4M2M.build.spiffs_blocksize=8192 -wiolink.menu.eesz.4M3M=4M (3M SPIFFS) -wiolink.menu.eesz.4M3M.build.flash_size=4M -wiolink.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -wiolink.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -wiolink.menu.eesz.4M3M.build.spiffs_pagesize=256 -wiolink.menu.eesz.4M3M.upload.maximum_size=1044464 -wiolink.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -wiolink.menu.eesz.4M3M.build.spiffs_start=0x100000 -wiolink.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -wiolink.menu.eesz.4M3M.build.spiffs_blocksize=8192 -wiolink.menu.ip.lm2f=v2 Lower Memory -wiolink.menu.ip.lm2f.build.lwip_include=lwip2/include -wiolink.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -wiolink.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wiolink.menu.ip.hb2f=v2 Higher Bandwidth -wiolink.menu.ip.hb2f.build.lwip_include=lwip2/include -wiolink.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -wiolink.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wiolink.menu.ip.lm2n=v2 Lower Memory (no features) -wiolink.menu.ip.lm2n.build.lwip_include=lwip2/include -wiolink.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -wiolink.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wiolink.menu.ip.hb2n=v2 Higher Bandwidth (no features) -wiolink.menu.ip.hb2n.build.lwip_include=lwip2/include -wiolink.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -wiolink.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wiolink.menu.ip.lm6f=v2 IPv6 Lower Memory -wiolink.menu.ip.lm6f.build.lwip_include=lwip2/include -wiolink.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -wiolink.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wiolink.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -wiolink.menu.ip.hb6f.build.lwip_include=lwip2/include -wiolink.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -wiolink.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wiolink.menu.ip.hb1=v1.4 Higher Bandwidth -wiolink.menu.ip.hb1.build.lwip_lib=-llwip_gcc -wiolink.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -wiolink.menu.ip.src=v1.4 Compile from source -wiolink.menu.ip.src.build.lwip_lib=-llwip_src -wiolink.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -wiolink.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wiolink.menu.dbg.Disabled=Disabled -wiolink.menu.dbg.Disabled.build.debug_port= -wiolink.menu.dbg.Serial=Serial -wiolink.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wiolink.menu.dbg.Serial1=Serial1 -wiolink.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wiolink.menu.lvl.None____=None -wiolink.menu.lvl.None____.build.debug_level= -wiolink.menu.lvl.SSL=SSL -wiolink.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -wiolink.menu.lvl.TLS_MEM=TLS_MEM -wiolink.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wiolink.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -wiolink.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.lvl.HTTP_SERVER=HTTP_SERVER -wiolink.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -wiolink.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wiolink.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wiolink.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -wiolink.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wiolink.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wiolink.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.CORE=CORE -wiolink.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -wiolink.menu.lvl.WIFI=WIFI -wiolink.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wiolink.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -wiolink.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wiolink.menu.lvl.UPDATER=UPDATER -wiolink.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wiolink.menu.lvl.OTA=OTA -wiolink.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -wiolink.menu.lvl.OOM=OOM -wiolink.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wiolink.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -wiolink.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wiolink.menu.wipe.none=Only Sketch -wiolink.menu.wipe.none.upload.erase_cmd= -wiolink.menu.wipe.sdk=Sketch + WiFi Settings -wiolink.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wiolink.menu.wipe.all=All Flash Contents -wiolink.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wiolink.menu.baud.115200=115200 -wiolink.menu.baud.115200.upload.speed=115200 -wiolink.menu.baud.9600=9600 -wiolink.menu.baud.9600.upload.speed=9600 -wiolink.menu.baud.57600=57600 -wiolink.menu.baud.57600.upload.speed=57600 -wiolink.menu.baud.230400.linux=230400 -wiolink.menu.baud.230400.macosx=230400 -wiolink.menu.baud.230400.upload.speed=230400 -wiolink.menu.baud.256000.windows=256000 -wiolink.menu.baud.256000.upload.speed=256000 -wiolink.menu.baud.460800.linux=460800 -wiolink.menu.baud.460800.macosx=460800 -wiolink.menu.baud.460800.upload.speed=460800 -wiolink.menu.baud.512000.windows=512000 -wiolink.menu.baud.512000.upload.speed=512000 -wiolink.menu.baud.921600=921600 -wiolink.menu.baud.921600.upload.speed=921600 - -############################################################## -espectro.name=ESPectro Core -espectro.build.board=ESP8266_ESPECTRO_CORE -espectro.build.variant=espectro -espectro.upload.tool=esptool -espectro.upload.maximum_data_size=81920 -espectro.upload.wait_for_upload_port=true -espectro.upload.erase_cmd= -espectro.serial.disableDTR=true -espectro.serial.disableRTS=true -espectro.build.mcu=esp8266 -espectro.build.core=esp8266 -espectro.build.spiffs_pagesize=256 -espectro.build.debug_port= -espectro.build.debug_level= -espectro.menu.xtal.80=80 MHz -espectro.menu.xtal.80.build.f_cpu=80000000L -espectro.menu.xtal.160=160 MHz -espectro.menu.xtal.160.build.f_cpu=160000000L -espectro.menu.vt.flash=Flash -espectro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espectro.menu.vt.heap=Heap -espectro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espectro.menu.vt.iram=IRAM -espectro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espectro.menu.exception.enabled=Enabled -espectro.menu.exception.enabled.build.exception_flags=-fexceptions -espectro.menu.exception.enabled.build.stdcpp_lib=-lstdc++ -espectro.menu.exception.disabled=Disabled -espectro.menu.exception.disabled.build.exception_flags=-fno-exceptions -espectro.menu.exception.disabled.build.stdcpp_lib=-lstdc++-nox -espectro.upload.resetmethod=nodemcu -espectro.build.flash_mode=dio -espectro.build.flash_freq=40 -espectro.menu.eesz.4M=4M (no SPIFFS) -espectro.menu.eesz.4M.build.flash_size=4M -espectro.menu.eesz.4M.build.flash_size_bytes=0x400000 -espectro.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espectro.menu.eesz.4M.build.spiffs_pagesize=256 -espectro.menu.eesz.4M.upload.maximum_size=1044464 -espectro.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espectro.menu.eesz.4M1M=4M (1M SPIFFS) -espectro.menu.eesz.4M1M.build.flash_size=4M -espectro.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espectro.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espectro.menu.eesz.4M1M.build.spiffs_pagesize=256 -espectro.menu.eesz.4M1M.upload.maximum_size=1044464 -espectro.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espectro.menu.eesz.4M1M.build.spiffs_start=0x300000 -espectro.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -espectro.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espectro.menu.eesz.4M2M=4M (2M SPIFFS) -espectro.menu.eesz.4M2M.build.flash_size=4M -espectro.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espectro.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espectro.menu.eesz.4M2M.build.spiffs_pagesize=256 -espectro.menu.eesz.4M2M.upload.maximum_size=1044464 -espectro.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espectro.menu.eesz.4M2M.build.spiffs_start=0x200000 -espectro.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -espectro.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espectro.menu.eesz.4M3M=4M (3M SPIFFS) -espectro.menu.eesz.4M3M.build.flash_size=4M -espectro.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espectro.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espectro.menu.eesz.4M3M.build.spiffs_pagesize=256 -espectro.menu.eesz.4M3M.upload.maximum_size=1044464 -espectro.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espectro.menu.eesz.4M3M.build.spiffs_start=0x100000 -espectro.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -espectro.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espectro.menu.ip.lm2f=v2 Lower Memory -espectro.menu.ip.lm2f.build.lwip_include=lwip2/include -espectro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espectro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espectro.menu.ip.hb2f=v2 Higher Bandwidth -espectro.menu.ip.hb2f.build.lwip_include=lwip2/include -espectro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espectro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espectro.menu.ip.lm2n=v2 Lower Memory (no features) -espectro.menu.ip.lm2n.build.lwip_include=lwip2/include -espectro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espectro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espectro.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espectro.menu.ip.hb2n.build.lwip_include=lwip2/include -espectro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espectro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espectro.menu.ip.lm6f=v2 IPv6 Lower Memory -espectro.menu.ip.lm6f.build.lwip_include=lwip2/include -espectro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espectro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espectro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espectro.menu.ip.hb6f.build.lwip_include=lwip2/include -espectro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espectro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espectro.menu.ip.hb1=v1.4 Higher Bandwidth -espectro.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espectro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espectro.menu.ip.src=v1.4 Compile from source -espectro.menu.ip.src.build.lwip_lib=-llwip_src -espectro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espectro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espectro.menu.dbg.Disabled=Disabled -espectro.menu.dbg.Disabled.build.debug_port= -espectro.menu.dbg.Serial=Serial -espectro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espectro.menu.dbg.Serial1=Serial1 -espectro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espectro.menu.lvl.None____=None -espectro.menu.lvl.None____.build.debug_level= -espectro.menu.lvl.SSL=SSL -espectro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espectro.menu.lvl.TLS_MEM=TLS_MEM -espectro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espectro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espectro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espectro.menu.lvl.HTTP_SERVER=HTTP_SERVER -espectro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espectro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espectro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espectro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espectro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espectro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espectro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espectro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espectro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.CORE=CORE -espectro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espectro.menu.lvl.WIFI=WIFI -espectro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espectro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espectro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espectro.menu.lvl.UPDATER=UPDATER -espectro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espectro.menu.lvl.OTA=OTA -espectro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espectro.menu.lvl.OOM=OOM -espectro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espectro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espectro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espectro.menu.wipe.none=Only Sketch -espectro.menu.wipe.none.upload.erase_cmd= -espectro.menu.wipe.sdk=Sketch + WiFi Settings -espectro.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espectro.menu.wipe.all=All Flash Contents -espectro.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espectro.menu.baud.115200=115200 -espectro.menu.baud.115200.upload.speed=115200 -espectro.menu.baud.9600=9600 -espectro.menu.baud.9600.upload.speed=9600 -espectro.menu.baud.57600=57600 -espectro.menu.baud.57600.upload.speed=57600 -espectro.menu.baud.230400.linux=230400 -espectro.menu.baud.230400.macosx=230400 -espectro.menu.baud.230400.upload.speed=230400 -espectro.menu.baud.256000.windows=256000 -espectro.menu.baud.256000.upload.speed=256000 -espectro.menu.baud.460800.linux=460800 -espectro.menu.baud.460800.macosx=460800 -espectro.menu.baud.460800.upload.speed=460800 -espectro.menu.baud.512000.windows=512000 -espectro.menu.baud.512000.upload.speed=512000 -espectro.menu.baud.921600=921600 -espectro.menu.baud.921600.upload.speed=921600 - From 16c38e85b0074d71263c758f2f7a294a58556e04 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sun, 17 Feb 2019 12:49:22 +0100 Subject: [PATCH 1022/2222] Delete platform.txt --- arduino/version 2.5.0-beta2/platform.txt | 156 ----------------------- 1 file changed, 156 deletions(-) delete mode 100644 arduino/version 2.5.0-beta2/platform.txt diff --git a/arduino/version 2.5.0-beta2/platform.txt b/arduino/version 2.5.0-beta2/platform.txt deleted file mode 100644 index 39988668a..000000000 --- a/arduino/version 2.5.0-beta2/platform.txt +++ /dev/null @@ -1,156 +0,0 @@ - -# ESP8266 platform -# ------------------------------ - -# For more info: -# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification - -name=ESP8266 Boards (2.5.0-beta2) -version=2.5.0-beta2 - - - -runtime.tools.signing={runtime.platform.path}/tools/signing.py - -compiler.warning_flags=-w -compiler.warning_flags.none=-w -compiler.warning_flags.default= -compiler.warning_flags.more=-Wall -compiler.warning_flags.all=-Wall -Wextra - -build.lwip_lib=-llwip_gcc -build.lwip_include=lwip/include -build.lwip_flags=-DLWIP_OPEN_SRC - -build.vtable_flags=-DVTABLES_IN_FLASH - -#build.exception_flags=-fexceptions -build.exception_flags=-fno-exceptions -#build.stdcpp_lib=-lstdc++ -build.stdcpp_lib=-lstdc++-nox - -#build.float=-u _printf_float -u _scanf_float -build.float= -build.led= - -compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/ -compiler.sdk.path={runtime.platform.path}/tools/sdk -compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf -compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" - -compiler.c.cmd=xtensa-lx106-elf-gcc -compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 {build.exception_flags} -ffunction-sections -fdata-sections {build.exception_flags} - -compiler.S.cmd=xtensa-lx106-elf-gcc -compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls - -compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read - -compiler.c.elf.cmd=xtensa-lx106-elf-gcc -compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc - -compiler.cpp.cmd=xtensa-lx106-elf-g++ -compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections {build.exception_flags} - -compiler.as.cmd=xtensa-lx106-elf-as - -compiler.ar.cmd=xtensa-lx106-elf-ar -compiler.ar.flags=cru - -compiler.elf2hex.cmd=esptool -compiler.elf2hex.flags= - -compiler.size.cmd=xtensa-lx106-elf-size - -compiler.esptool.cmd=esptool -compiler.esptool.cmd.windows=esptool.exe - -# This can be overriden in boards.txt -build.extra_flags=-DESP8266 - -# These can be overridden in platform.local.txt -compiler.c.extra_flags= -compiler.c.elf.extra_flags= -compiler.S.extra_flags= -compiler.cpp.extra_flags= -compiler.ar.extra_flags= -compiler.objcopy.eep.extra_flags= -compiler.elf2hex.extra_flags= - -## generate file with git version number -## needs bash, git, and echo -recipe.hooks.core.prebuild.1.pattern=python "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h" - - - -## windows-compatible version without git -recipe.hooks.core.prebuild.1.pattern.windows=cmd.exe /c rem cannot sign on windows - - - -## Build the app.ld linker file -recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld" - -## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile S files -recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Create archives -recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" - -## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" - -## Create eeprom -recipe.objcopy.eep.pattern= - -## Create hex -#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" - -recipe.objcopy.hex.1.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec -recipe.objcopy.hex.2.pattern=python "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed" - -# No signing on Windows -recipe.objcopy.hex.1.pattern.windows="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec -recipe.objcopy.hex.2.pattern.windows= - -## Save hex -recipe.output.tmp_file={build.project_name}.bin -recipe.output.save_file={build.project_name}.{build.variant}.bin - -## Compute size -recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).* -recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* -#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* - -# ------------------------------ - -tools.esptool.cmd=esptool -tools.esptool.cmd.windows=esptool.exe -tools.esptool.path={runtime.tools.esptool.path} -tools.esptool.network_cmd=python -tools.esptool.network_cmd.windows=python.exe - -tools.esptool.upload.protocol=esp -tools.esptool.upload.params.verbose=-vv -tools.esptool.upload.params.quiet= -tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin" -tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" - -tools.mkspiffs.cmd=mkspiffs -tools.mkspiffs.cmd.windows=mkspiffs.exe -tools.mkspiffs.path={runtime.tools.mkspiffs.path} - -tools.espupload.cmd=python -tools.espupload.cmd.windows=python.exe -tools.espupload.path={runtime.platform.path}/tools -tools.espupload.upload.protocol=espupload -tools.espupload.upload.params.verbose= -tools.espupload.upload.params.quiet= -tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin" From 623d290c0a90bd0bf469fa2525f10126d99cfc47 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sun, 17 Feb 2019 12:49:41 +0100 Subject: [PATCH 1023/2222] Delete boards.txt --- arduino/version 2.5.0-beta3/boards.txt | 6122 ------------------------ 1 file changed, 6122 deletions(-) delete mode 100644 arduino/version 2.5.0-beta3/boards.txt diff --git a/arduino/version 2.5.0-beta3/boards.txt b/arduino/version 2.5.0-beta3/boards.txt deleted file mode 100644 index 542054e59..000000000 --- a/arduino/version 2.5.0-beta3/boards.txt +++ /dev/null @@ -1,6122 +0,0 @@ -# -# Do not create pull-requests for this file only, CI will not accept them. -# You *must* edit/modify/run boards.txt.py to regenerate boards.txt. -# All modified files after running with option "--allgen" must be included in the pull-request. -# - -menu.BoardModel=Model -menu.baud=Upload Speed -menu.UploadTool=Upload Using -menu.xtal=CPU Frequency -menu.CrystalFreq=Crystal Frequency -menu.eesz=Flash Size -menu.FlashMode=Flash Mode -menu.FlashFreq=Flash Frequency -menu.ResetMethod=Reset Method -menu.ESPModule=Module -menu.dbg=Debug port -menu.lvl=Debug Level -menu.ip=lwIP Variant -menu.vt=VTables -menu.exception=Exceptions -menu.led=Builtin Led -menu.wipe=Erase Flash - -############################################################## -generic.name=Generic ESP8266 Module -generic.build.board=ESP8266_GENERIC -generic.upload.tool=esptool -generic.upload.maximum_data_size=81920 -generic.upload.wait_for_upload_port=true -generic.upload.erase_cmd= -generic.serial.disableDTR=true -generic.serial.disableRTS=true -generic.build.mcu=esp8266 -generic.build.core=esp8266 -generic.build.variant=generic -generic.build.spiffs_pagesize=256 -generic.build.debug_port= -generic.build.debug_level= - -generic.menu.UploadTool.esptool=Serial -generic.menu.UploadTool.esptool.upload.tool=esptool -generic.menu.UploadTool.esptool.upload.verbose=-vv -generic.menu.UploadTool.espupload=OTA_upload -generic.menu.UploadTool.espupload.upload.tool=espupload - -generic.menu.xtal.80=80 MHz -generic.menu.xtal.80.build.f_cpu=80000000L -generic.menu.xtal.160=160 MHz -generic.menu.xtal.160.build.f_cpu=160000000L -generic.menu.vt.flash=Flash -generic.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -generic.menu.vt.heap=Heap -generic.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -generic.menu.vt.iram=IRAM -generic.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -generic.menu.exception.disabled=Disabled -generic.menu.exception.disabled.build.exception_flags=-fno-exceptions -generic.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -generic.menu.exception.enabled=Enabled -generic.menu.exception.enabled.build.exception_flags=-fexceptions -generic.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -generic.menu.ResetMethod.ck=ck -generic.menu.ResetMethod.ck.upload.resetmethod=ck -generic.menu.ResetMethod.nodemcu=nodemcu -generic.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -generic.menu.ResetMethod.none=none -generic.menu.ResetMethod.none.upload.resetmethod=none -generic.menu.ResetMethod.dtrset=dtrset -generic.menu.ResetMethod.dtrset.upload.resetmethod=dtrset -generic.menu.CrystalFreq.26=26 MHz -generic.menu.CrystalFreq.40=40 MHz -generic.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -generic.menu.FlashFreq.40=40MHz -generic.menu.FlashFreq.40.build.flash_freq=40 -generic.menu.FlashFreq.80=80MHz -generic.menu.FlashFreq.80.build.flash_freq=80 -generic.menu.FlashMode.dout=DOUT (compatible) -generic.menu.FlashMode.dout.build.flash_mode=dout -generic.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT -generic.menu.FlashMode.dio=DIO -generic.menu.FlashMode.dio.build.flash_mode=dio -generic.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO -generic.menu.FlashMode.qout=QOUT -generic.menu.FlashMode.qout.build.flash_mode=qout -generic.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT -generic.menu.FlashMode.qio=QIO (fast) -generic.menu.FlashMode.qio.build.flash_mode=qio -generic.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO -generic.menu.eesz.512K=512K (no SPIFFS) -generic.menu.eesz.512K.build.flash_size=512K -generic.menu.eesz.512K.build.flash_size_bytes=0x80000 -generic.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld -generic.menu.eesz.512K.build.spiffs_pagesize=256 -generic.menu.eesz.512K.upload.maximum_size=499696 -generic.menu.eesz.512K.build.rfcal_addr=0x7C000 -generic.menu.eesz.512K32=512K (32K SPIFFS) -generic.menu.eesz.512K32.build.flash_size=512K -generic.menu.eesz.512K32.build.flash_size_bytes=0x80000 -generic.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld -generic.menu.eesz.512K32.build.spiffs_pagesize=256 -generic.menu.eesz.512K32.upload.maximum_size=466928 -generic.menu.eesz.512K32.build.rfcal_addr=0x7C000 -generic.menu.eesz.512K32.build.spiffs_start=0x73000 -generic.menu.eesz.512K32.build.spiffs_end=0x7B000 -generic.menu.eesz.512K32.build.spiffs_blocksize=4096 -generic.menu.eesz.512K64=512K (64K SPIFFS) -generic.menu.eesz.512K64.build.flash_size=512K -generic.menu.eesz.512K64.build.flash_size_bytes=0x80000 -generic.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld -generic.menu.eesz.512K64.build.spiffs_pagesize=256 -generic.menu.eesz.512K64.upload.maximum_size=434160 -generic.menu.eesz.512K64.build.rfcal_addr=0x7C000 -generic.menu.eesz.512K64.build.spiffs_start=0x6B000 -generic.menu.eesz.512K64.build.spiffs_end=0x7B000 -generic.menu.eesz.512K64.build.spiffs_blocksize=4096 -generic.menu.eesz.512K128=512K (128K SPIFFS) -generic.menu.eesz.512K128.build.flash_size=512K -generic.menu.eesz.512K128.build.flash_size_bytes=0x80000 -generic.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld -generic.menu.eesz.512K128.build.spiffs_pagesize=256 -generic.menu.eesz.512K128.upload.maximum_size=368624 -generic.menu.eesz.512K128.build.rfcal_addr=0x7C000 -generic.menu.eesz.512K128.build.spiffs_start=0x5B000 -generic.menu.eesz.512K128.build.spiffs_end=0x7B000 -generic.menu.eesz.512K128.build.spiffs_blocksize=4096 -generic.menu.eesz.1M=1M (no SPIFFS) -generic.menu.eesz.1M.build.flash_size=1M -generic.menu.eesz.1M.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -generic.menu.eesz.1M.build.spiffs_pagesize=256 -generic.menu.eesz.1M.upload.maximum_size=1023984 -generic.menu.eesz.1M.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M64=1M (64K SPIFFS) -generic.menu.eesz.1M64.build.flash_size=1M -generic.menu.eesz.1M64.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -generic.menu.eesz.1M64.build.spiffs_pagesize=256 -generic.menu.eesz.1M64.upload.maximum_size=958448 -generic.menu.eesz.1M64.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M64.build.spiffs_start=0xEB000 -generic.menu.eesz.1M64.build.spiffs_end=0xFB000 -generic.menu.eesz.1M64.build.spiffs_blocksize=4096 -generic.menu.eesz.1M128=1M (128K SPIFFS) -generic.menu.eesz.1M128.build.flash_size=1M -generic.menu.eesz.1M128.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -generic.menu.eesz.1M128.build.spiffs_pagesize=256 -generic.menu.eesz.1M128.upload.maximum_size=892912 -generic.menu.eesz.1M128.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M128.build.spiffs_start=0xDB000 -generic.menu.eesz.1M128.build.spiffs_end=0xFB000 -generic.menu.eesz.1M128.build.spiffs_blocksize=4096 -generic.menu.eesz.1M144=1M (144K SPIFFS) -generic.menu.eesz.1M144.build.flash_size=1M -generic.menu.eesz.1M144.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -generic.menu.eesz.1M144.build.spiffs_pagesize=256 -generic.menu.eesz.1M144.upload.maximum_size=876528 -generic.menu.eesz.1M144.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M144.build.spiffs_start=0xD7000 -generic.menu.eesz.1M144.build.spiffs_end=0xFB000 -generic.menu.eesz.1M144.build.spiffs_blocksize=4096 -generic.menu.eesz.1M160=1M (160K SPIFFS) -generic.menu.eesz.1M160.build.flash_size=1M -generic.menu.eesz.1M160.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -generic.menu.eesz.1M160.build.spiffs_pagesize=256 -generic.menu.eesz.1M160.upload.maximum_size=860144 -generic.menu.eesz.1M160.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M160.build.spiffs_start=0xD3000 -generic.menu.eesz.1M160.build.spiffs_end=0xFB000 -generic.menu.eesz.1M160.build.spiffs_blocksize=4096 -generic.menu.eesz.1M192=1M (192K SPIFFS) -generic.menu.eesz.1M192.build.flash_size=1M -generic.menu.eesz.1M192.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -generic.menu.eesz.1M192.build.spiffs_pagesize=256 -generic.menu.eesz.1M192.upload.maximum_size=827376 -generic.menu.eesz.1M192.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M192.build.spiffs_start=0xCB000 -generic.menu.eesz.1M192.build.spiffs_end=0xFB000 -generic.menu.eesz.1M192.build.spiffs_blocksize=4096 -generic.menu.eesz.1M256=1M (256K SPIFFS) -generic.menu.eesz.1M256.build.flash_size=1M -generic.menu.eesz.1M256.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -generic.menu.eesz.1M256.build.spiffs_pagesize=256 -generic.menu.eesz.1M256.upload.maximum_size=761840 -generic.menu.eesz.1M256.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M256.build.spiffs_start=0xBB000 -generic.menu.eesz.1M256.build.spiffs_end=0xFB000 -generic.menu.eesz.1M256.build.spiffs_blocksize=4096 -generic.menu.eesz.1M512=1M (512K SPIFFS) -generic.menu.eesz.1M512.build.flash_size=1M -generic.menu.eesz.1M512.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -generic.menu.eesz.1M512.build.spiffs_pagesize=256 -generic.menu.eesz.1M512.upload.maximum_size=499696 -generic.menu.eesz.1M512.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M512.build.spiffs_start=0x7B000 -generic.menu.eesz.1M512.build.spiffs_end=0xFB000 -generic.menu.eesz.1M512.build.spiffs_blocksize=4096 -generic.menu.eesz.2M=2M (no SPIFFS) -generic.menu.eesz.2M.build.flash_size=2M -generic.menu.eesz.2M.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld -generic.menu.eesz.2M.build.spiffs_pagesize=256 -generic.menu.eesz.2M.upload.maximum_size=1044464 -generic.menu.eesz.2M.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M128=2M (128K SPIFFS) -generic.menu.eesz.2M128.build.flash_size=2M -generic.menu.eesz.2M128.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld -generic.menu.eesz.2M128.build.spiffs_pagesize=256 -generic.menu.eesz.2M128.upload.maximum_size=1044464 -generic.menu.eesz.2M128.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M128.build.spiffs_start=0x1E0000 -generic.menu.eesz.2M128.build.spiffs_end=0x1FB000 -generic.menu.eesz.2M128.build.spiffs_blocksize=4096 -generic.menu.eesz.2M256=2M (256K SPIFFS) -generic.menu.eesz.2M256.build.flash_size=2M -generic.menu.eesz.2M256.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld -generic.menu.eesz.2M256.build.spiffs_pagesize=256 -generic.menu.eesz.2M256.upload.maximum_size=1044464 -generic.menu.eesz.2M256.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M256.build.spiffs_start=0x1C0000 -generic.menu.eesz.2M256.build.spiffs_end=0x1FB000 -generic.menu.eesz.2M256.build.spiffs_blocksize=4096 -generic.menu.eesz.2M512=2M (512K SPIFFS) -generic.menu.eesz.2M512.build.flash_size=2M -generic.menu.eesz.2M512.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld -generic.menu.eesz.2M512.build.spiffs_pagesize=256 -generic.menu.eesz.2M512.upload.maximum_size=1044464 -generic.menu.eesz.2M512.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M512.build.spiffs_start=0x180000 -generic.menu.eesz.2M512.build.spiffs_end=0x1FB000 -generic.menu.eesz.2M512.build.spiffs_blocksize=8192 -generic.menu.eesz.2M1M=2M (1M SPIFFS) -generic.menu.eesz.2M1M.build.flash_size=2M -generic.menu.eesz.2M1M.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld -generic.menu.eesz.2M1M.build.spiffs_pagesize=256 -generic.menu.eesz.2M1M.upload.maximum_size=1044464 -generic.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M1M.build.spiffs_start=0x100000 -generic.menu.eesz.2M1M.build.spiffs_end=0x1FB000 -generic.menu.eesz.2M1M.build.spiffs_blocksize=8192 -generic.menu.eesz.4M=4M (no SPIFFS) -generic.menu.eesz.4M.build.flash_size=4M -generic.menu.eesz.4M.build.flash_size_bytes=0x400000 -generic.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -generic.menu.eesz.4M.build.spiffs_pagesize=256 -generic.menu.eesz.4M.upload.maximum_size=1044464 -generic.menu.eesz.4M.build.rfcal_addr=0x3FC000 -generic.menu.eesz.4M1M=4M (1M SPIFFS) -generic.menu.eesz.4M1M.build.flash_size=4M -generic.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -generic.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -generic.menu.eesz.4M1M.build.spiffs_pagesize=256 -generic.menu.eesz.4M1M.upload.maximum_size=1044464 -generic.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -generic.menu.eesz.4M1M.build.spiffs_start=0x300000 -generic.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -generic.menu.eesz.4M1M.build.spiffs_blocksize=8192 -generic.menu.eesz.4M2M=4M (2M SPIFFS) -generic.menu.eesz.4M2M.build.flash_size=4M -generic.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -generic.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -generic.menu.eesz.4M2M.build.spiffs_pagesize=256 -generic.menu.eesz.4M2M.upload.maximum_size=1044464 -generic.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -generic.menu.eesz.4M2M.build.spiffs_start=0x200000 -generic.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -generic.menu.eesz.4M2M.build.spiffs_blocksize=8192 -generic.menu.eesz.4M3M=4M (3M SPIFFS) -generic.menu.eesz.4M3M.build.flash_size=4M -generic.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -generic.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -generic.menu.eesz.4M3M.build.spiffs_pagesize=256 -generic.menu.eesz.4M3M.upload.maximum_size=1044464 -generic.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -generic.menu.eesz.4M3M.build.spiffs_start=0x100000 -generic.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -generic.menu.eesz.4M3M.build.spiffs_blocksize=8192 -generic.menu.eesz.8M6M=8M (6M SPIFFS) -generic.menu.eesz.8M6M.build.flash_size=8M -generic.menu.eesz.8M6M.build.flash_size_bytes=0x800000 -generic.menu.eesz.8M6M.build.flash_ld=eagle.flash.8m6m.ld -generic.menu.eesz.8M6M.build.spiffs_pagesize=256 -generic.menu.eesz.8M6M.upload.maximum_size=1044464 -generic.menu.eesz.8M6M.build.rfcal_addr=0x7FC000 -generic.menu.eesz.8M6M.build.spiffs_start=0x200000 -generic.menu.eesz.8M6M.build.spiffs_end=0x7FB000 -generic.menu.eesz.8M6M.build.spiffs_blocksize=8192 -generic.menu.eesz.8M7M=8M (7M SPIFFS) -generic.menu.eesz.8M7M.build.flash_size=8M -generic.menu.eesz.8M7M.build.flash_size_bytes=0x800000 -generic.menu.eesz.8M7M.build.flash_ld=eagle.flash.8m7m.ld -generic.menu.eesz.8M7M.build.spiffs_pagesize=256 -generic.menu.eesz.8M7M.upload.maximum_size=1044464 -generic.menu.eesz.8M7M.build.rfcal_addr=0x7FC000 -generic.menu.eesz.8M7M.build.spiffs_start=0x100000 -generic.menu.eesz.8M7M.build.spiffs_end=0x7FB000 -generic.menu.eesz.8M7M.build.spiffs_blocksize=8192 -generic.menu.eesz.16M14M=16M (14M SPIFFS) -generic.menu.eesz.16M14M.build.flash_size=16M -generic.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 -generic.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld -generic.menu.eesz.16M14M.build.spiffs_pagesize=256 -generic.menu.eesz.16M14M.upload.maximum_size=1044464 -generic.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 -generic.menu.eesz.16M14M.build.spiffs_start=0x200000 -generic.menu.eesz.16M14M.build.spiffs_end=0xFFB000 -generic.menu.eesz.16M14M.build.spiffs_blocksize=8192 -generic.menu.eesz.16M15M=16M (15M SPIFFS) -generic.menu.eesz.16M15M.build.flash_size=16M -generic.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 -generic.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld -generic.menu.eesz.16M15M.build.spiffs_pagesize=256 -generic.menu.eesz.16M15M.upload.maximum_size=1044464 -generic.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 -generic.menu.eesz.16M15M.build.spiffs_start=0x100000 -generic.menu.eesz.16M15M.build.spiffs_end=0xFFB000 -generic.menu.eesz.16M15M.build.spiffs_blocksize=8192 -generic.menu.led.2=2 -generic.menu.led.2.build.led=-DLED_BUILTIN=2 -generic.menu.led.0=0 -generic.menu.led.0.build.led=-DLED_BUILTIN=0 -generic.menu.led.1=1 -generic.menu.led.1.build.led=-DLED_BUILTIN=1 -generic.menu.led.3=3 -generic.menu.led.3.build.led=-DLED_BUILTIN=3 -generic.menu.led.4=4 -generic.menu.led.4.build.led=-DLED_BUILTIN=4 -generic.menu.led.5=5 -generic.menu.led.5.build.led=-DLED_BUILTIN=5 -generic.menu.led.6=6 -generic.menu.led.6.build.led=-DLED_BUILTIN=6 -generic.menu.led.7=7 -generic.menu.led.7.build.led=-DLED_BUILTIN=7 -generic.menu.led.8=8 -generic.menu.led.8.build.led=-DLED_BUILTIN=8 -generic.menu.led.9=9 -generic.menu.led.9.build.led=-DLED_BUILTIN=9 -generic.menu.led.10=10 -generic.menu.led.10.build.led=-DLED_BUILTIN=10 -generic.menu.led.11=11 -generic.menu.led.11.build.led=-DLED_BUILTIN=11 -generic.menu.led.12=12 -generic.menu.led.12.build.led=-DLED_BUILTIN=12 -generic.menu.led.13=13 -generic.menu.led.13.build.led=-DLED_BUILTIN=13 -generic.menu.led.14=14 -generic.menu.led.14.build.led=-DLED_BUILTIN=14 -generic.menu.led.15=15 -generic.menu.led.15.build.led=-DLED_BUILTIN=15 -generic.menu.ip.lm2f=v2 Lower Memory -generic.menu.ip.lm2f.build.lwip_include=lwip2/include -generic.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -generic.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -generic.menu.ip.hb2f=v2 Higher Bandwidth -generic.menu.ip.hb2f.build.lwip_include=lwip2/include -generic.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -generic.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -generic.menu.ip.lm2n=v2 Lower Memory (no features) -generic.menu.ip.lm2n.build.lwip_include=lwip2/include -generic.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -generic.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -generic.menu.ip.hb2n=v2 Higher Bandwidth (no features) -generic.menu.ip.hb2n.build.lwip_include=lwip2/include -generic.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -generic.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -generic.menu.ip.lm6f=v2 IPv6 Lower Memory -generic.menu.ip.lm6f.build.lwip_include=lwip2/include -generic.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -generic.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -generic.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -generic.menu.ip.hb6f.build.lwip_include=lwip2/include -generic.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -generic.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -generic.menu.ip.hb1=v1.4 Higher Bandwidth -generic.menu.ip.hb1.build.lwip_lib=-llwip_gcc -generic.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -generic.menu.ip.src=v1.4 Compile from source -generic.menu.ip.src.build.lwip_lib=-llwip_src -generic.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -generic.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -generic.menu.dbg.Disabled=Disabled -generic.menu.dbg.Disabled.build.debug_port= -generic.menu.dbg.Serial=Serial -generic.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -generic.menu.dbg.Serial1=Serial1 -generic.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -generic.menu.lvl.None____=None -generic.menu.lvl.None____.build.debug_level= -generic.menu.lvl.SSL=SSL -generic.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -generic.menu.lvl.TLS_MEM=TLS_MEM -generic.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -generic.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -generic.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -generic.menu.lvl.HTTP_SERVER=HTTP_SERVER -generic.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -generic.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -generic.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -generic.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -generic.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -generic.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -generic.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -generic.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -generic.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -generic.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -generic.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -generic.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.CORE=CORE -generic.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -generic.menu.lvl.WIFI=WIFI -generic.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -generic.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -generic.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -generic.menu.lvl.UPDATER=UPDATER -generic.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -generic.menu.lvl.OTA=OTA -generic.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -generic.menu.lvl.OOM=OOM -generic.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -generic.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -generic.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -generic.menu.wipe.none=Only Sketch -generic.menu.wipe.none.upload.erase_cmd= -generic.menu.wipe.sdk=Sketch + WiFi Settings -generic.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -generic.menu.wipe.all=All Flash Contents -generic.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -generic.menu.baud.115200=115200 -generic.menu.baud.115200.upload.speed=115200 -generic.menu.baud.9600=9600 -generic.menu.baud.9600.upload.speed=9600 -generic.menu.baud.57600=57600 -generic.menu.baud.57600.upload.speed=57600 -generic.menu.baud.230400.linux=230400 -generic.menu.baud.230400.macosx=230400 -generic.menu.baud.230400.upload.speed=230400 -generic.menu.baud.256000.windows=256000 -generic.menu.baud.256000.upload.speed=256000 -generic.menu.baud.460800.linux=460800 -generic.menu.baud.460800.macosx=460800 -generic.menu.baud.460800.upload.speed=460800 -generic.menu.baud.512000.windows=512000 -generic.menu.baud.512000.upload.speed=512000 -generic.menu.baud.921600=921600 -generic.menu.baud.921600.upload.speed=921600 - -############################################################## -esp8285.name=Generic ESP8285 Module -esp8285.build.board=ESP8266_ESP01 -esp8285.build.variant=esp8285 -esp8285.upload.tool=esptool -esp8285.upload.maximum_data_size=81920 -esp8285.upload.wait_for_upload_port=true -esp8285.upload.erase_cmd= -esp8285.serial.disableDTR=true -esp8285.serial.disableRTS=true -esp8285.build.mcu=esp8266 -esp8285.build.core=esp8266 -esp8285.build.spiffs_pagesize=256 -esp8285.build.debug_port= -esp8285.build.debug_level= -esp8285.menu.xtal.80=80 MHz -esp8285.menu.xtal.80.build.f_cpu=80000000L -esp8285.menu.xtal.160=160 MHz -esp8285.menu.xtal.160.build.f_cpu=160000000L -esp8285.menu.vt.flash=Flash -esp8285.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -esp8285.menu.vt.heap=Heap -esp8285.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -esp8285.menu.vt.iram=IRAM -esp8285.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -esp8285.menu.exception.disabled=Disabled -esp8285.menu.exception.disabled.build.exception_flags=-fno-exceptions -esp8285.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -esp8285.menu.exception.enabled=Enabled -esp8285.menu.exception.enabled.build.exception_flags=-fexceptions -esp8285.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -esp8285.menu.ResetMethod.ck=ck -esp8285.menu.ResetMethod.ck.upload.resetmethod=ck -esp8285.menu.ResetMethod.nodemcu=nodemcu -esp8285.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -esp8285.menu.ResetMethod.none=none -esp8285.menu.ResetMethod.none.upload.resetmethod=none -esp8285.menu.ResetMethod.dtrset=dtrset -esp8285.menu.ResetMethod.dtrset.upload.resetmethod=dtrset -esp8285.menu.CrystalFreq.26=26 MHz -esp8285.menu.CrystalFreq.40=40 MHz -esp8285.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -esp8285.build.flash_mode=dout -esp8285.build.flash_flags=-DFLASHMODE_DOUT -esp8285.build.flash_freq=40 -esp8285.menu.eesz.1M=1M (no SPIFFS) -esp8285.menu.eesz.1M.build.flash_size=1M -esp8285.menu.eesz.1M.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -esp8285.menu.eesz.1M.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M.upload.maximum_size=1023984 -esp8285.menu.eesz.1M.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M64=1M (64K SPIFFS) -esp8285.menu.eesz.1M64.build.flash_size=1M -esp8285.menu.eesz.1M64.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -esp8285.menu.eesz.1M64.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M64.upload.maximum_size=958448 -esp8285.menu.eesz.1M64.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M64.build.spiffs_start=0xEB000 -esp8285.menu.eesz.1M64.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M64.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M128=1M (128K SPIFFS) -esp8285.menu.eesz.1M128.build.flash_size=1M -esp8285.menu.eesz.1M128.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -esp8285.menu.eesz.1M128.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M128.upload.maximum_size=892912 -esp8285.menu.eesz.1M128.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M128.build.spiffs_start=0xDB000 -esp8285.menu.eesz.1M128.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M128.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M144=1M (144K SPIFFS) -esp8285.menu.eesz.1M144.build.flash_size=1M -esp8285.menu.eesz.1M144.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -esp8285.menu.eesz.1M144.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M144.upload.maximum_size=876528 -esp8285.menu.eesz.1M144.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M144.build.spiffs_start=0xD7000 -esp8285.menu.eesz.1M144.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M144.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M160=1M (160K SPIFFS) -esp8285.menu.eesz.1M160.build.flash_size=1M -esp8285.menu.eesz.1M160.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -esp8285.menu.eesz.1M160.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M160.upload.maximum_size=860144 -esp8285.menu.eesz.1M160.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M160.build.spiffs_start=0xD3000 -esp8285.menu.eesz.1M160.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M160.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M192=1M (192K SPIFFS) -esp8285.menu.eesz.1M192.build.flash_size=1M -esp8285.menu.eesz.1M192.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -esp8285.menu.eesz.1M192.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M192.upload.maximum_size=827376 -esp8285.menu.eesz.1M192.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M192.build.spiffs_start=0xCB000 -esp8285.menu.eesz.1M192.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M192.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M256=1M (256K SPIFFS) -esp8285.menu.eesz.1M256.build.flash_size=1M -esp8285.menu.eesz.1M256.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -esp8285.menu.eesz.1M256.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M256.upload.maximum_size=761840 -esp8285.menu.eesz.1M256.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M256.build.spiffs_start=0xBB000 -esp8285.menu.eesz.1M256.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M256.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M512=1M (512K SPIFFS) -esp8285.menu.eesz.1M512.build.flash_size=1M -esp8285.menu.eesz.1M512.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -esp8285.menu.eesz.1M512.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M512.upload.maximum_size=499696 -esp8285.menu.eesz.1M512.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M512.build.spiffs_start=0x7B000 -esp8285.menu.eesz.1M512.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M512.build.spiffs_blocksize=4096 -esp8285.menu.led.2=2 -esp8285.menu.led.2.build.led=-DLED_BUILTIN=2 -esp8285.menu.led.0=0 -esp8285.menu.led.0.build.led=-DLED_BUILTIN=0 -esp8285.menu.led.1=1 -esp8285.menu.led.1.build.led=-DLED_BUILTIN=1 -esp8285.menu.led.3=3 -esp8285.menu.led.3.build.led=-DLED_BUILTIN=3 -esp8285.menu.led.4=4 -esp8285.menu.led.4.build.led=-DLED_BUILTIN=4 -esp8285.menu.led.5=5 -esp8285.menu.led.5.build.led=-DLED_BUILTIN=5 -esp8285.menu.led.6=6 -esp8285.menu.led.6.build.led=-DLED_BUILTIN=6 -esp8285.menu.led.7=7 -esp8285.menu.led.7.build.led=-DLED_BUILTIN=7 -esp8285.menu.led.8=8 -esp8285.menu.led.8.build.led=-DLED_BUILTIN=8 -esp8285.menu.led.9=9 -esp8285.menu.led.9.build.led=-DLED_BUILTIN=9 -esp8285.menu.led.10=10 -esp8285.menu.led.10.build.led=-DLED_BUILTIN=10 -esp8285.menu.led.11=11 -esp8285.menu.led.11.build.led=-DLED_BUILTIN=11 -esp8285.menu.led.12=12 -esp8285.menu.led.12.build.led=-DLED_BUILTIN=12 -esp8285.menu.led.13=13 -esp8285.menu.led.13.build.led=-DLED_BUILTIN=13 -esp8285.menu.led.14=14 -esp8285.menu.led.14.build.led=-DLED_BUILTIN=14 -esp8285.menu.led.15=15 -esp8285.menu.led.15.build.led=-DLED_BUILTIN=15 -esp8285.menu.ip.lm2f=v2 Lower Memory -esp8285.menu.ip.lm2f.build.lwip_include=lwip2/include -esp8285.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -esp8285.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -esp8285.menu.ip.hb2f=v2 Higher Bandwidth -esp8285.menu.ip.hb2f.build.lwip_include=lwip2/include -esp8285.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -esp8285.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -esp8285.menu.ip.lm2n=v2 Lower Memory (no features) -esp8285.menu.ip.lm2n.build.lwip_include=lwip2/include -esp8285.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -esp8285.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -esp8285.menu.ip.hb2n=v2 Higher Bandwidth (no features) -esp8285.menu.ip.hb2n.build.lwip_include=lwip2/include -esp8285.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -esp8285.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -esp8285.menu.ip.lm6f=v2 IPv6 Lower Memory -esp8285.menu.ip.lm6f.build.lwip_include=lwip2/include -esp8285.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -esp8285.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -esp8285.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -esp8285.menu.ip.hb6f.build.lwip_include=lwip2/include -esp8285.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -esp8285.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -esp8285.menu.ip.hb1=v1.4 Higher Bandwidth -esp8285.menu.ip.hb1.build.lwip_lib=-llwip_gcc -esp8285.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -esp8285.menu.ip.src=v1.4 Compile from source -esp8285.menu.ip.src.build.lwip_lib=-llwip_src -esp8285.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -esp8285.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -esp8285.menu.dbg.Disabled=Disabled -esp8285.menu.dbg.Disabled.build.debug_port= -esp8285.menu.dbg.Serial=Serial -esp8285.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -esp8285.menu.dbg.Serial1=Serial1 -esp8285.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -esp8285.menu.lvl.None____=None -esp8285.menu.lvl.None____.build.debug_level= -esp8285.menu.lvl.SSL=SSL -esp8285.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -esp8285.menu.lvl.TLS_MEM=TLS_MEM -esp8285.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -esp8285.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -esp8285.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.lvl.HTTP_SERVER=HTTP_SERVER -esp8285.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -esp8285.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -esp8285.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -esp8285.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -esp8285.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -esp8285.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -esp8285.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.CORE=CORE -esp8285.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -esp8285.menu.lvl.WIFI=WIFI -esp8285.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -esp8285.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -esp8285.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -esp8285.menu.lvl.UPDATER=UPDATER -esp8285.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -esp8285.menu.lvl.OTA=OTA -esp8285.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -esp8285.menu.lvl.OOM=OOM -esp8285.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -esp8285.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -esp8285.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -esp8285.menu.wipe.none=Only Sketch -esp8285.menu.wipe.none.upload.erase_cmd= -esp8285.menu.wipe.sdk=Sketch + WiFi Settings -esp8285.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -esp8285.menu.wipe.all=All Flash Contents -esp8285.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -esp8285.menu.baud.115200=115200 -esp8285.menu.baud.115200.upload.speed=115200 -esp8285.menu.baud.9600=9600 -esp8285.menu.baud.9600.upload.speed=9600 -esp8285.menu.baud.57600=57600 -esp8285.menu.baud.57600.upload.speed=57600 -esp8285.menu.baud.230400.linux=230400 -esp8285.menu.baud.230400.macosx=230400 -esp8285.menu.baud.230400.upload.speed=230400 -esp8285.menu.baud.256000.windows=256000 -esp8285.menu.baud.256000.upload.speed=256000 -esp8285.menu.baud.460800.linux=460800 -esp8285.menu.baud.460800.macosx=460800 -esp8285.menu.baud.460800.upload.speed=460800 -esp8285.menu.baud.512000.windows=512000 -esp8285.menu.baud.512000.upload.speed=512000 -esp8285.menu.baud.921600=921600 -esp8285.menu.baud.921600.upload.speed=921600 - -############################################################## -espduino.name=ESPDuino (ESP-13 Module) -espduino.build.board=ESP8266_ESP13 -espduino.build.variant=ESPDuino -espduino.menu.ResetMethod.v2=ESPduino-V2 -espduino.menu.ResetMethod.v2.upload.resetmethod=nodemcu -espduino.menu.ResetMethod.v1=ESPduino-V1 -espduino.menu.ResetMethod.v1.upload.resetmethod=ck -espduino.menu.UploadTool.esptool=Serial -espduino.menu.UploadTool.esptool.upload.tool=esptool -espduino.menu.UploadTool.esptool.upload.verbose=-vv -espduino.menu.UploadTool.espota=OTA -espduino.menu.UploadTool.espota.upload.tool=espota -espduino.upload.tool=esptool -espduino.upload.maximum_data_size=81920 -espduino.upload.wait_for_upload_port=true -espduino.upload.erase_cmd= -espduino.serial.disableDTR=true -espduino.serial.disableRTS=true -espduino.build.mcu=esp8266 -espduino.build.core=esp8266 -espduino.build.spiffs_pagesize=256 -espduino.build.debug_port= -espduino.build.debug_level= -espduino.menu.xtal.80=80 MHz -espduino.menu.xtal.80.build.f_cpu=80000000L -espduino.menu.xtal.160=160 MHz -espduino.menu.xtal.160.build.f_cpu=160000000L -espduino.menu.vt.flash=Flash -espduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espduino.menu.vt.heap=Heap -espduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espduino.menu.vt.iram=IRAM -espduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espduino.menu.exception.disabled=Disabled -espduino.menu.exception.disabled.build.exception_flags=-fno-exceptions -espduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espduino.menu.exception.enabled=Enabled -espduino.menu.exception.enabled.build.exception_flags=-fexceptions -espduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espduino.build.flash_mode=dio -espduino.build.flash_flags=-DFLASHMODE_DIO -espduino.build.flash_freq=40 -espduino.menu.eesz.4M=4M (no SPIFFS) -espduino.menu.eesz.4M.build.flash_size=4M -espduino.menu.eesz.4M.build.flash_size_bytes=0x400000 -espduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espduino.menu.eesz.4M.build.spiffs_pagesize=256 -espduino.menu.eesz.4M.upload.maximum_size=1044464 -espduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espduino.menu.eesz.4M1M=4M (1M SPIFFS) -espduino.menu.eesz.4M1M.build.flash_size=4M -espduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espduino.menu.eesz.4M1M.build.spiffs_pagesize=256 -espduino.menu.eesz.4M1M.upload.maximum_size=1044464 -espduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espduino.menu.eesz.4M1M.build.spiffs_start=0x300000 -espduino.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -espduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espduino.menu.eesz.4M2M=4M (2M SPIFFS) -espduino.menu.eesz.4M2M.build.flash_size=4M -espduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espduino.menu.eesz.4M2M.build.spiffs_pagesize=256 -espduino.menu.eesz.4M2M.upload.maximum_size=1044464 -espduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espduino.menu.eesz.4M2M.build.spiffs_start=0x200000 -espduino.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -espduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espduino.menu.eesz.4M3M=4M (3M SPIFFS) -espduino.menu.eesz.4M3M.build.flash_size=4M -espduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espduino.menu.eesz.4M3M.build.spiffs_pagesize=256 -espduino.menu.eesz.4M3M.upload.maximum_size=1044464 -espduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espduino.menu.eesz.4M3M.build.spiffs_start=0x100000 -espduino.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -espduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espduino.menu.ip.lm2f=v2 Lower Memory -espduino.menu.ip.lm2f.build.lwip_include=lwip2/include -espduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espduino.menu.ip.hb2f=v2 Higher Bandwidth -espduino.menu.ip.hb2f.build.lwip_include=lwip2/include -espduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espduino.menu.ip.lm2n=v2 Lower Memory (no features) -espduino.menu.ip.lm2n.build.lwip_include=lwip2/include -espduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espduino.menu.ip.hb2n.build.lwip_include=lwip2/include -espduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espduino.menu.ip.lm6f=v2 IPv6 Lower Memory -espduino.menu.ip.lm6f.build.lwip_include=lwip2/include -espduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espduino.menu.ip.hb6f.build.lwip_include=lwip2/include -espduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espduino.menu.ip.hb1=v1.4 Higher Bandwidth -espduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espduino.menu.ip.src=v1.4 Compile from source -espduino.menu.ip.src.build.lwip_lib=-llwip_src -espduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espduino.menu.dbg.Disabled=Disabled -espduino.menu.dbg.Disabled.build.debug_port= -espduino.menu.dbg.Serial=Serial -espduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espduino.menu.dbg.Serial1=Serial1 -espduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espduino.menu.lvl.None____=None -espduino.menu.lvl.None____.build.debug_level= -espduino.menu.lvl.SSL=SSL -espduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espduino.menu.lvl.TLS_MEM=TLS_MEM -espduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.lvl.HTTP_SERVER=HTTP_SERVER -espduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.CORE=CORE -espduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espduino.menu.lvl.WIFI=WIFI -espduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espduino.menu.lvl.UPDATER=UPDATER -espduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espduino.menu.lvl.OTA=OTA -espduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espduino.menu.lvl.OOM=OOM -espduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espduino.menu.wipe.none=Only Sketch -espduino.menu.wipe.none.upload.erase_cmd= -espduino.menu.wipe.sdk=Sketch + WiFi Settings -espduino.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espduino.menu.wipe.all=All Flash Contents -espduino.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espduino.menu.baud.115200=115200 -espduino.menu.baud.115200.upload.speed=115200 -espduino.menu.baud.9600=9600 -espduino.menu.baud.9600.upload.speed=9600 -espduino.menu.baud.57600=57600 -espduino.menu.baud.57600.upload.speed=57600 -espduino.menu.baud.230400.linux=230400 -espduino.menu.baud.230400.macosx=230400 -espduino.menu.baud.230400.upload.speed=230400 -espduino.menu.baud.256000.windows=256000 -espduino.menu.baud.256000.upload.speed=256000 -espduino.menu.baud.460800.linux=460800 -espduino.menu.baud.460800.macosx=460800 -espduino.menu.baud.460800.upload.speed=460800 -espduino.menu.baud.512000.windows=512000 -espduino.menu.baud.512000.upload.speed=512000 -espduino.menu.baud.921600=921600 -espduino.menu.baud.921600.upload.speed=921600 - -############################################################## -huzzah.name=Adafruit Feather HUZZAH ESP8266 -huzzah.build.board=ESP8266_ESP12 -huzzah.build.variant=adafruit -huzzah.upload.tool=esptool -huzzah.upload.maximum_data_size=81920 -huzzah.upload.wait_for_upload_port=true -huzzah.upload.erase_cmd= -huzzah.serial.disableDTR=true -huzzah.serial.disableRTS=true -huzzah.build.mcu=esp8266 -huzzah.build.core=esp8266 -huzzah.build.spiffs_pagesize=256 -huzzah.build.debug_port= -huzzah.build.debug_level= -huzzah.menu.xtal.80=80 MHz -huzzah.menu.xtal.80.build.f_cpu=80000000L -huzzah.menu.xtal.160=160 MHz -huzzah.menu.xtal.160.build.f_cpu=160000000L -huzzah.menu.vt.flash=Flash -huzzah.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -huzzah.menu.vt.heap=Heap -huzzah.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -huzzah.menu.vt.iram=IRAM -huzzah.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -huzzah.menu.exception.disabled=Disabled -huzzah.menu.exception.disabled.build.exception_flags=-fno-exceptions -huzzah.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -huzzah.menu.exception.enabled=Enabled -huzzah.menu.exception.enabled.build.exception_flags=-fexceptions -huzzah.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -huzzah.upload.resetmethod=nodemcu -huzzah.build.flash_mode=qio -huzzah.build.flash_flags=-DFLASHMODE_QIO -huzzah.build.flash_freq=40 -huzzah.menu.eesz.4M=4M (no SPIFFS) -huzzah.menu.eesz.4M.build.flash_size=4M -huzzah.menu.eesz.4M.build.flash_size_bytes=0x400000 -huzzah.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -huzzah.menu.eesz.4M.build.spiffs_pagesize=256 -huzzah.menu.eesz.4M.upload.maximum_size=1044464 -huzzah.menu.eesz.4M.build.rfcal_addr=0x3FC000 -huzzah.menu.eesz.4M1M=4M (1M SPIFFS) -huzzah.menu.eesz.4M1M.build.flash_size=4M -huzzah.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -huzzah.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -huzzah.menu.eesz.4M1M.build.spiffs_pagesize=256 -huzzah.menu.eesz.4M1M.upload.maximum_size=1044464 -huzzah.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -huzzah.menu.eesz.4M1M.build.spiffs_start=0x300000 -huzzah.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -huzzah.menu.eesz.4M1M.build.spiffs_blocksize=8192 -huzzah.menu.eesz.4M2M=4M (2M SPIFFS) -huzzah.menu.eesz.4M2M.build.flash_size=4M -huzzah.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -huzzah.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -huzzah.menu.eesz.4M2M.build.spiffs_pagesize=256 -huzzah.menu.eesz.4M2M.upload.maximum_size=1044464 -huzzah.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -huzzah.menu.eesz.4M2M.build.spiffs_start=0x200000 -huzzah.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -huzzah.menu.eesz.4M2M.build.spiffs_blocksize=8192 -huzzah.menu.eesz.4M3M=4M (3M SPIFFS) -huzzah.menu.eesz.4M3M.build.flash_size=4M -huzzah.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -huzzah.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -huzzah.menu.eesz.4M3M.build.spiffs_pagesize=256 -huzzah.menu.eesz.4M3M.upload.maximum_size=1044464 -huzzah.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -huzzah.menu.eesz.4M3M.build.spiffs_start=0x100000 -huzzah.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -huzzah.menu.eesz.4M3M.build.spiffs_blocksize=8192 -huzzah.menu.ip.lm2f=v2 Lower Memory -huzzah.menu.ip.lm2f.build.lwip_include=lwip2/include -huzzah.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -huzzah.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -huzzah.menu.ip.hb2f=v2 Higher Bandwidth -huzzah.menu.ip.hb2f.build.lwip_include=lwip2/include -huzzah.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -huzzah.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -huzzah.menu.ip.lm2n=v2 Lower Memory (no features) -huzzah.menu.ip.lm2n.build.lwip_include=lwip2/include -huzzah.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -huzzah.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -huzzah.menu.ip.hb2n=v2 Higher Bandwidth (no features) -huzzah.menu.ip.hb2n.build.lwip_include=lwip2/include -huzzah.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -huzzah.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -huzzah.menu.ip.lm6f=v2 IPv6 Lower Memory -huzzah.menu.ip.lm6f.build.lwip_include=lwip2/include -huzzah.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -huzzah.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -huzzah.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -huzzah.menu.ip.hb6f.build.lwip_include=lwip2/include -huzzah.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -huzzah.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -huzzah.menu.ip.hb1=v1.4 Higher Bandwidth -huzzah.menu.ip.hb1.build.lwip_lib=-llwip_gcc -huzzah.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -huzzah.menu.ip.src=v1.4 Compile from source -huzzah.menu.ip.src.build.lwip_lib=-llwip_src -huzzah.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -huzzah.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -huzzah.menu.dbg.Disabled=Disabled -huzzah.menu.dbg.Disabled.build.debug_port= -huzzah.menu.dbg.Serial=Serial -huzzah.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -huzzah.menu.dbg.Serial1=Serial1 -huzzah.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -huzzah.menu.lvl.None____=None -huzzah.menu.lvl.None____.build.debug_level= -huzzah.menu.lvl.SSL=SSL -huzzah.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -huzzah.menu.lvl.TLS_MEM=TLS_MEM -huzzah.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -huzzah.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -huzzah.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.lvl.HTTP_SERVER=HTTP_SERVER -huzzah.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -huzzah.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -huzzah.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -huzzah.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -huzzah.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -huzzah.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -huzzah.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.CORE=CORE -huzzah.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -huzzah.menu.lvl.WIFI=WIFI -huzzah.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -huzzah.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -huzzah.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -huzzah.menu.lvl.UPDATER=UPDATER -huzzah.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -huzzah.menu.lvl.OTA=OTA -huzzah.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -huzzah.menu.lvl.OOM=OOM -huzzah.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -huzzah.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -huzzah.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -huzzah.menu.wipe.none=Only Sketch -huzzah.menu.wipe.none.upload.erase_cmd= -huzzah.menu.wipe.sdk=Sketch + WiFi Settings -huzzah.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -huzzah.menu.wipe.all=All Flash Contents -huzzah.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -huzzah.menu.baud.115200=115200 -huzzah.menu.baud.115200.upload.speed=115200 -huzzah.menu.baud.9600=9600 -huzzah.menu.baud.9600.upload.speed=9600 -huzzah.menu.baud.57600=57600 -huzzah.menu.baud.57600.upload.speed=57600 -huzzah.menu.baud.230400.linux=230400 -huzzah.menu.baud.230400.macosx=230400 -huzzah.menu.baud.230400.upload.speed=230400 -huzzah.menu.baud.256000.windows=256000 -huzzah.menu.baud.256000.upload.speed=256000 -huzzah.menu.baud.460800.linux=460800 -huzzah.menu.baud.460800.macosx=460800 -huzzah.menu.baud.460800.upload.speed=460800 -huzzah.menu.baud.512000.windows=512000 -huzzah.menu.baud.512000.upload.speed=512000 -huzzah.menu.baud.921600=921600 -huzzah.menu.baud.921600.upload.speed=921600 - -############################################################## -inventone.name=Invent One -inventone.build.board=ESP8266_GENERIC -inventone.build.variant=inventone -inventone.upload.tool=esptool -inventone.upload.maximum_data_size=81920 -inventone.upload.wait_for_upload_port=true -inventone.upload.erase_cmd= -inventone.serial.disableDTR=true -inventone.serial.disableRTS=true -inventone.build.mcu=esp8266 -inventone.build.core=esp8266 -inventone.build.spiffs_pagesize=256 -inventone.build.debug_port= -inventone.build.debug_level= -inventone.menu.xtal.80=80 MHz -inventone.menu.xtal.80.build.f_cpu=80000000L -inventone.menu.xtal.160=160 MHz -inventone.menu.xtal.160.build.f_cpu=160000000L -inventone.menu.vt.flash=Flash -inventone.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -inventone.menu.vt.heap=Heap -inventone.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -inventone.menu.vt.iram=IRAM -inventone.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -inventone.menu.exception.disabled=Disabled -inventone.menu.exception.disabled.build.exception_flags=-fno-exceptions -inventone.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -inventone.menu.exception.enabled=Enabled -inventone.menu.exception.enabled.build.exception_flags=-fexceptions -inventone.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -inventone.upload.resetmethod=nodemcu -inventone.build.flash_mode=dio -inventone.build.flash_flags=-DFLASHMODE_DIO -inventone.build.flash_freq=40 -inventone.menu.eesz.4M=4M (no SPIFFS) -inventone.menu.eesz.4M.build.flash_size=4M -inventone.menu.eesz.4M.build.flash_size_bytes=0x400000 -inventone.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -inventone.menu.eesz.4M.build.spiffs_pagesize=256 -inventone.menu.eesz.4M.upload.maximum_size=1044464 -inventone.menu.eesz.4M.build.rfcal_addr=0x3FC000 -inventone.menu.eesz.4M1M=4M (1M SPIFFS) -inventone.menu.eesz.4M1M.build.flash_size=4M -inventone.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -inventone.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -inventone.menu.eesz.4M1M.build.spiffs_pagesize=256 -inventone.menu.eesz.4M1M.upload.maximum_size=1044464 -inventone.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -inventone.menu.eesz.4M1M.build.spiffs_start=0x300000 -inventone.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -inventone.menu.eesz.4M1M.build.spiffs_blocksize=8192 -inventone.menu.eesz.4M2M=4M (2M SPIFFS) -inventone.menu.eesz.4M2M.build.flash_size=4M -inventone.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -inventone.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -inventone.menu.eesz.4M2M.build.spiffs_pagesize=256 -inventone.menu.eesz.4M2M.upload.maximum_size=1044464 -inventone.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -inventone.menu.eesz.4M2M.build.spiffs_start=0x200000 -inventone.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -inventone.menu.eesz.4M2M.build.spiffs_blocksize=8192 -inventone.menu.eesz.4M3M=4M (3M SPIFFS) -inventone.menu.eesz.4M3M.build.flash_size=4M -inventone.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -inventone.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -inventone.menu.eesz.4M3M.build.spiffs_pagesize=256 -inventone.menu.eesz.4M3M.upload.maximum_size=1044464 -inventone.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -inventone.menu.eesz.4M3M.build.spiffs_start=0x100000 -inventone.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -inventone.menu.eesz.4M3M.build.spiffs_blocksize=8192 -inventone.menu.ip.lm2f=v2 Lower Memory -inventone.menu.ip.lm2f.build.lwip_include=lwip2/include -inventone.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -inventone.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -inventone.menu.ip.hb2f=v2 Higher Bandwidth -inventone.menu.ip.hb2f.build.lwip_include=lwip2/include -inventone.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -inventone.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -inventone.menu.ip.lm2n=v2 Lower Memory (no features) -inventone.menu.ip.lm2n.build.lwip_include=lwip2/include -inventone.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -inventone.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -inventone.menu.ip.hb2n=v2 Higher Bandwidth (no features) -inventone.menu.ip.hb2n.build.lwip_include=lwip2/include -inventone.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -inventone.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -inventone.menu.ip.lm6f=v2 IPv6 Lower Memory -inventone.menu.ip.lm6f.build.lwip_include=lwip2/include -inventone.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -inventone.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -inventone.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -inventone.menu.ip.hb6f.build.lwip_include=lwip2/include -inventone.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -inventone.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -inventone.menu.ip.hb1=v1.4 Higher Bandwidth -inventone.menu.ip.hb1.build.lwip_lib=-llwip_gcc -inventone.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -inventone.menu.ip.src=v1.4 Compile from source -inventone.menu.ip.src.build.lwip_lib=-llwip_src -inventone.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -inventone.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -inventone.menu.dbg.Disabled=Disabled -inventone.menu.dbg.Disabled.build.debug_port= -inventone.menu.dbg.Serial=Serial -inventone.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -inventone.menu.dbg.Serial1=Serial1 -inventone.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -inventone.menu.lvl.None____=None -inventone.menu.lvl.None____.build.debug_level= -inventone.menu.lvl.SSL=SSL -inventone.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -inventone.menu.lvl.TLS_MEM=TLS_MEM -inventone.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -inventone.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -inventone.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -inventone.menu.lvl.HTTP_SERVER=HTTP_SERVER -inventone.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -inventone.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -inventone.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -inventone.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -inventone.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -inventone.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -inventone.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -inventone.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -inventone.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.CORE=CORE -inventone.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -inventone.menu.lvl.WIFI=WIFI -inventone.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -inventone.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -inventone.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -inventone.menu.lvl.UPDATER=UPDATER -inventone.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -inventone.menu.lvl.OTA=OTA -inventone.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -inventone.menu.lvl.OOM=OOM -inventone.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -inventone.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -inventone.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -inventone.menu.wipe.none=Only Sketch -inventone.menu.wipe.none.upload.erase_cmd= -inventone.menu.wipe.sdk=Sketch + WiFi Settings -inventone.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -inventone.menu.wipe.all=All Flash Contents -inventone.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -inventone.menu.baud.115200=115200 -inventone.menu.baud.115200.upload.speed=115200 -inventone.menu.baud.9600=9600 -inventone.menu.baud.9600.upload.speed=9600 -inventone.menu.baud.57600=57600 -inventone.menu.baud.57600.upload.speed=57600 -inventone.menu.baud.230400.linux=230400 -inventone.menu.baud.230400.macosx=230400 -inventone.menu.baud.230400.upload.speed=230400 -inventone.menu.baud.256000.windows=256000 -inventone.menu.baud.256000.upload.speed=256000 -inventone.menu.baud.460800.linux=460800 -inventone.menu.baud.460800.macosx=460800 -inventone.menu.baud.460800.upload.speed=460800 -inventone.menu.baud.512000.windows=512000 -inventone.menu.baud.512000.upload.speed=512000 -inventone.menu.baud.921600=921600 -inventone.menu.baud.921600.upload.speed=921600 - -############################################################## -cw01.name=XinaBox CW01 -cw01.build.board=ESP8266_GENERIC -cw01.build.variant=xinabox -cw01.upload.tool=esptool -cw01.upload.maximum_data_size=81920 -cw01.upload.wait_for_upload_port=true -cw01.upload.erase_cmd= -cw01.serial.disableDTR=true -cw01.serial.disableRTS=true -cw01.build.mcu=esp8266 -cw01.build.core=esp8266 -cw01.build.spiffs_pagesize=256 -cw01.build.debug_port= -cw01.build.debug_level= -cw01.menu.xtal.80=80 MHz -cw01.menu.xtal.80.build.f_cpu=80000000L -cw01.menu.xtal.160=160 MHz -cw01.menu.xtal.160.build.f_cpu=160000000L -cw01.menu.vt.flash=Flash -cw01.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -cw01.menu.vt.heap=Heap -cw01.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -cw01.menu.vt.iram=IRAM -cw01.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -cw01.menu.exception.disabled=Disabled -cw01.menu.exception.disabled.build.exception_flags=-fno-exceptions -cw01.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -cw01.menu.exception.enabled=Enabled -cw01.menu.exception.enabled.build.exception_flags=-fexceptions -cw01.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -cw01.upload.resetmethod=nodemcu -cw01.menu.CrystalFreq.26=26 MHz -cw01.menu.CrystalFreq.40=40 MHz -cw01.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -cw01.build.flash_mode=qio -cw01.build.flash_flags=-DFLASHMODE_QIO -cw01.build.flash_freq=40 -cw01.menu.eesz.4M=4M (no SPIFFS) -cw01.menu.eesz.4M.build.flash_size=4M -cw01.menu.eesz.4M.build.flash_size_bytes=0x400000 -cw01.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -cw01.menu.eesz.4M.build.spiffs_pagesize=256 -cw01.menu.eesz.4M.upload.maximum_size=1044464 -cw01.menu.eesz.4M.build.rfcal_addr=0x3FC000 -cw01.menu.eesz.4M1M=4M (1M SPIFFS) -cw01.menu.eesz.4M1M.build.flash_size=4M -cw01.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -cw01.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -cw01.menu.eesz.4M1M.build.spiffs_pagesize=256 -cw01.menu.eesz.4M1M.upload.maximum_size=1044464 -cw01.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -cw01.menu.eesz.4M1M.build.spiffs_start=0x300000 -cw01.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -cw01.menu.eesz.4M1M.build.spiffs_blocksize=8192 -cw01.menu.eesz.4M2M=4M (2M SPIFFS) -cw01.menu.eesz.4M2M.build.flash_size=4M -cw01.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -cw01.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -cw01.menu.eesz.4M2M.build.spiffs_pagesize=256 -cw01.menu.eesz.4M2M.upload.maximum_size=1044464 -cw01.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -cw01.menu.eesz.4M2M.build.spiffs_start=0x200000 -cw01.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -cw01.menu.eesz.4M2M.build.spiffs_blocksize=8192 -cw01.menu.eesz.4M3M=4M (3M SPIFFS) -cw01.menu.eesz.4M3M.build.flash_size=4M -cw01.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -cw01.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -cw01.menu.eesz.4M3M.build.spiffs_pagesize=256 -cw01.menu.eesz.4M3M.upload.maximum_size=1044464 -cw01.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -cw01.menu.eesz.4M3M.build.spiffs_start=0x100000 -cw01.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -cw01.menu.eesz.4M3M.build.spiffs_blocksize=8192 -cw01.menu.ip.lm2f=v2 Lower Memory -cw01.menu.ip.lm2f.build.lwip_include=lwip2/include -cw01.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -cw01.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -cw01.menu.ip.hb2f=v2 Higher Bandwidth -cw01.menu.ip.hb2f.build.lwip_include=lwip2/include -cw01.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -cw01.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -cw01.menu.ip.lm2n=v2 Lower Memory (no features) -cw01.menu.ip.lm2n.build.lwip_include=lwip2/include -cw01.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -cw01.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -cw01.menu.ip.hb2n=v2 Higher Bandwidth (no features) -cw01.menu.ip.hb2n.build.lwip_include=lwip2/include -cw01.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -cw01.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -cw01.menu.ip.lm6f=v2 IPv6 Lower Memory -cw01.menu.ip.lm6f.build.lwip_include=lwip2/include -cw01.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -cw01.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -cw01.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -cw01.menu.ip.hb6f.build.lwip_include=lwip2/include -cw01.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -cw01.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -cw01.menu.ip.hb1=v1.4 Higher Bandwidth -cw01.menu.ip.hb1.build.lwip_lib=-llwip_gcc -cw01.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -cw01.menu.ip.src=v1.4 Compile from source -cw01.menu.ip.src.build.lwip_lib=-llwip_src -cw01.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -cw01.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -cw01.menu.dbg.Disabled=Disabled -cw01.menu.dbg.Disabled.build.debug_port= -cw01.menu.dbg.Serial=Serial -cw01.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -cw01.menu.dbg.Serial1=Serial1 -cw01.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -cw01.menu.lvl.None____=None -cw01.menu.lvl.None____.build.debug_level= -cw01.menu.lvl.SSL=SSL -cw01.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -cw01.menu.lvl.TLS_MEM=TLS_MEM -cw01.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -cw01.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -cw01.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.lvl.HTTP_SERVER=HTTP_SERVER -cw01.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -cw01.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -cw01.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -cw01.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -cw01.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -cw01.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -cw01.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.CORE=CORE -cw01.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -cw01.menu.lvl.WIFI=WIFI -cw01.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -cw01.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -cw01.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -cw01.menu.lvl.UPDATER=UPDATER -cw01.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -cw01.menu.lvl.OTA=OTA -cw01.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -cw01.menu.lvl.OOM=OOM -cw01.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -cw01.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -cw01.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -cw01.menu.wipe.none=Only Sketch -cw01.menu.wipe.none.upload.erase_cmd= -cw01.menu.wipe.sdk=Sketch + WiFi Settings -cw01.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -cw01.menu.wipe.all=All Flash Contents -cw01.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -cw01.menu.baud.115200=115200 -cw01.menu.baud.115200.upload.speed=115200 -cw01.menu.baud.9600=9600 -cw01.menu.baud.9600.upload.speed=9600 -cw01.menu.baud.57600=57600 -cw01.menu.baud.57600.upload.speed=57600 -cw01.menu.baud.230400.linux=230400 -cw01.menu.baud.230400.macosx=230400 -cw01.menu.baud.230400.upload.speed=230400 -cw01.menu.baud.256000.windows=256000 -cw01.menu.baud.256000.upload.speed=256000 -cw01.menu.baud.460800.linux=460800 -cw01.menu.baud.460800.macosx=460800 -cw01.menu.baud.460800.upload.speed=460800 -cw01.menu.baud.512000.windows=512000 -cw01.menu.baud.512000.upload.speed=512000 -cw01.menu.baud.921600=921600 -cw01.menu.baud.921600.upload.speed=921600 - -############################################################## -espresso_lite_v1.name=ESPresso Lite 1.0 -espresso_lite_v1.build.board=ESP8266_ESPRESSO_LITE_V1 -espresso_lite_v1.build.variant=espresso_lite_v1 -espresso_lite_v1.upload.tool=esptool -espresso_lite_v1.upload.maximum_data_size=81920 -espresso_lite_v1.upload.wait_for_upload_port=true -espresso_lite_v1.upload.erase_cmd= -espresso_lite_v1.serial.disableDTR=true -espresso_lite_v1.serial.disableRTS=true -espresso_lite_v1.build.mcu=esp8266 -espresso_lite_v1.build.core=esp8266 -espresso_lite_v1.build.spiffs_pagesize=256 -espresso_lite_v1.build.debug_port= -espresso_lite_v1.build.debug_level= -espresso_lite_v1.menu.xtal.80=80 MHz -espresso_lite_v1.menu.xtal.80.build.f_cpu=80000000L -espresso_lite_v1.menu.xtal.160=160 MHz -espresso_lite_v1.menu.xtal.160.build.f_cpu=160000000L -espresso_lite_v1.menu.vt.flash=Flash -espresso_lite_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espresso_lite_v1.menu.vt.heap=Heap -espresso_lite_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espresso_lite_v1.menu.vt.iram=IRAM -espresso_lite_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espresso_lite_v1.menu.exception.disabled=Disabled -espresso_lite_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions -espresso_lite_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espresso_lite_v1.menu.exception.enabled=Enabled -espresso_lite_v1.menu.exception.enabled.build.exception_flags=-fexceptions -espresso_lite_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espresso_lite_v1.build.flash_mode=dio -espresso_lite_v1.build.flash_flags=-DFLASHMODE_DIO -espresso_lite_v1.build.flash_freq=40 -espresso_lite_v1.menu.eesz.4M=4M (no SPIFFS) -espresso_lite_v1.menu.eesz.4M.build.flash_size=4M -espresso_lite_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v1.menu.eesz.4M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.eesz.4M.upload.maximum_size=1044464 -espresso_lite_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.eesz.4M1M=4M (1M SPIFFS) -espresso_lite_v1.menu.eesz.4M1M.build.flash_size=4M -espresso_lite_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.eesz.4M1M.upload.maximum_size=1044464 -espresso_lite_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 -espresso_lite_v1.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.eesz.4M2M=4M (2M SPIFFS) -espresso_lite_v1.menu.eesz.4M2M.build.flash_size=4M -espresso_lite_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espresso_lite_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.eesz.4M2M.upload.maximum_size=1044464 -espresso_lite_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 -espresso_lite_v1.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.eesz.4M3M=4M (3M SPIFFS) -espresso_lite_v1.menu.eesz.4M3M.build.flash_size=4M -espresso_lite_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espresso_lite_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.eesz.4M3M.upload.maximum_size=1044464 -espresso_lite_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 -espresso_lite_v1.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.ResetMethod.ck=ck -espresso_lite_v1.menu.ResetMethod.ck.upload.resetmethod=ck -espresso_lite_v1.menu.ResetMethod.nodemcu=nodemcu -espresso_lite_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espresso_lite_v1.menu.ip.lm2f=v2 Lower Memory -espresso_lite_v1.menu.ip.lm2f.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espresso_lite_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espresso_lite_v1.menu.ip.hb2f=v2 Higher Bandwidth -espresso_lite_v1.menu.ip.hb2f.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espresso_lite_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espresso_lite_v1.menu.ip.lm2n=v2 Lower Memory (no features) -espresso_lite_v1.menu.ip.lm2n.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espresso_lite_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espresso_lite_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espresso_lite_v1.menu.ip.hb2n.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espresso_lite_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espresso_lite_v1.menu.ip.lm6f=v2 IPv6 Lower Memory -espresso_lite_v1.menu.ip.lm6f.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espresso_lite_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espresso_lite_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espresso_lite_v1.menu.ip.hb6f.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espresso_lite_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espresso_lite_v1.menu.ip.hb1=v1.4 Higher Bandwidth -espresso_lite_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espresso_lite_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v1.menu.ip.src=v1.4 Compile from source -espresso_lite_v1.menu.ip.src.build.lwip_lib=-llwip_src -espresso_lite_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espresso_lite_v1.menu.dbg.Disabled=Disabled -espresso_lite_v1.menu.dbg.Disabled.build.debug_port= -espresso_lite_v1.menu.dbg.Serial=Serial -espresso_lite_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v1.menu.dbg.Serial1=Serial1 -espresso_lite_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espresso_lite_v1.menu.lvl.None____=None -espresso_lite_v1.menu.lvl.None____.build.debug_level= -espresso_lite_v1.menu.lvl.SSL=SSL -espresso_lite_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espresso_lite_v1.menu.lvl.TLS_MEM=TLS_MEM -espresso_lite_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espresso_lite_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espresso_lite_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER -espresso_lite_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espresso_lite_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.CORE=CORE -espresso_lite_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espresso_lite_v1.menu.lvl.WIFI=WIFI -espresso_lite_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espresso_lite_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espresso_lite_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v1.menu.lvl.UPDATER=UPDATER -espresso_lite_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espresso_lite_v1.menu.lvl.OTA=OTA -espresso_lite_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espresso_lite_v1.menu.lvl.OOM=OOM -espresso_lite_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espresso_lite_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espresso_lite_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espresso_lite_v1.menu.wipe.none=Only Sketch -espresso_lite_v1.menu.wipe.none.upload.erase_cmd= -espresso_lite_v1.menu.wipe.sdk=Sketch + WiFi Settings -espresso_lite_v1.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espresso_lite_v1.menu.wipe.all=All Flash Contents -espresso_lite_v1.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espresso_lite_v1.menu.baud.115200=115200 -espresso_lite_v1.menu.baud.115200.upload.speed=115200 -espresso_lite_v1.menu.baud.9600=9600 -espresso_lite_v1.menu.baud.9600.upload.speed=9600 -espresso_lite_v1.menu.baud.57600=57600 -espresso_lite_v1.menu.baud.57600.upload.speed=57600 -espresso_lite_v1.menu.baud.230400.linux=230400 -espresso_lite_v1.menu.baud.230400.macosx=230400 -espresso_lite_v1.menu.baud.230400.upload.speed=230400 -espresso_lite_v1.menu.baud.256000.windows=256000 -espresso_lite_v1.menu.baud.256000.upload.speed=256000 -espresso_lite_v1.menu.baud.460800.linux=460800 -espresso_lite_v1.menu.baud.460800.macosx=460800 -espresso_lite_v1.menu.baud.460800.upload.speed=460800 -espresso_lite_v1.menu.baud.512000.windows=512000 -espresso_lite_v1.menu.baud.512000.upload.speed=512000 -espresso_lite_v1.menu.baud.921600=921600 -espresso_lite_v1.menu.baud.921600.upload.speed=921600 - -############################################################## -espresso_lite_v2.name=ESPresso Lite 2.0 -espresso_lite_v2.build.board=ESP8266_ESPRESSO_LITE_V2 -espresso_lite_v2.build.variant=espresso_lite_v2 -espresso_lite_v2.upload.tool=esptool -espresso_lite_v2.upload.maximum_data_size=81920 -espresso_lite_v2.upload.wait_for_upload_port=true -espresso_lite_v2.upload.erase_cmd= -espresso_lite_v2.serial.disableDTR=true -espresso_lite_v2.serial.disableRTS=true -espresso_lite_v2.build.mcu=esp8266 -espresso_lite_v2.build.core=esp8266 -espresso_lite_v2.build.spiffs_pagesize=256 -espresso_lite_v2.build.debug_port= -espresso_lite_v2.build.debug_level= -espresso_lite_v2.menu.xtal.80=80 MHz -espresso_lite_v2.menu.xtal.80.build.f_cpu=80000000L -espresso_lite_v2.menu.xtal.160=160 MHz -espresso_lite_v2.menu.xtal.160.build.f_cpu=160000000L -espresso_lite_v2.menu.vt.flash=Flash -espresso_lite_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espresso_lite_v2.menu.vt.heap=Heap -espresso_lite_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espresso_lite_v2.menu.vt.iram=IRAM -espresso_lite_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espresso_lite_v2.menu.exception.disabled=Disabled -espresso_lite_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions -espresso_lite_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espresso_lite_v2.menu.exception.enabled=Enabled -espresso_lite_v2.menu.exception.enabled.build.exception_flags=-fexceptions -espresso_lite_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espresso_lite_v2.build.flash_mode=dio -espresso_lite_v2.build.flash_flags=-DFLASHMODE_DIO -espresso_lite_v2.build.flash_freq=40 -espresso_lite_v2.menu.eesz.4M=4M (no SPIFFS) -espresso_lite_v2.menu.eesz.4M.build.flash_size=4M -espresso_lite_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v2.menu.eesz.4M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.eesz.4M.upload.maximum_size=1044464 -espresso_lite_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.eesz.4M1M=4M (1M SPIFFS) -espresso_lite_v2.menu.eesz.4M1M.build.flash_size=4M -espresso_lite_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.eesz.4M1M.upload.maximum_size=1044464 -espresso_lite_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 -espresso_lite_v2.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.eesz.4M2M=4M (2M SPIFFS) -espresso_lite_v2.menu.eesz.4M2M.build.flash_size=4M -espresso_lite_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espresso_lite_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.eesz.4M2M.upload.maximum_size=1044464 -espresso_lite_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 -espresso_lite_v2.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.eesz.4M3M=4M (3M SPIFFS) -espresso_lite_v2.menu.eesz.4M3M.build.flash_size=4M -espresso_lite_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espresso_lite_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.eesz.4M3M.upload.maximum_size=1044464 -espresso_lite_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 -espresso_lite_v2.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.ResetMethod.ck=ck -espresso_lite_v2.menu.ResetMethod.ck.upload.resetmethod=ck -espresso_lite_v2.menu.ResetMethod.nodemcu=nodemcu -espresso_lite_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espresso_lite_v2.menu.ip.lm2f=v2 Lower Memory -espresso_lite_v2.menu.ip.lm2f.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espresso_lite_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espresso_lite_v2.menu.ip.hb2f=v2 Higher Bandwidth -espresso_lite_v2.menu.ip.hb2f.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espresso_lite_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espresso_lite_v2.menu.ip.lm2n=v2 Lower Memory (no features) -espresso_lite_v2.menu.ip.lm2n.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espresso_lite_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espresso_lite_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espresso_lite_v2.menu.ip.hb2n.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espresso_lite_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espresso_lite_v2.menu.ip.lm6f=v2 IPv6 Lower Memory -espresso_lite_v2.menu.ip.lm6f.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espresso_lite_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espresso_lite_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espresso_lite_v2.menu.ip.hb6f.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espresso_lite_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espresso_lite_v2.menu.ip.hb1=v1.4 Higher Bandwidth -espresso_lite_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espresso_lite_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v2.menu.ip.src=v1.4 Compile from source -espresso_lite_v2.menu.ip.src.build.lwip_lib=-llwip_src -espresso_lite_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espresso_lite_v2.menu.dbg.Disabled=Disabled -espresso_lite_v2.menu.dbg.Disabled.build.debug_port= -espresso_lite_v2.menu.dbg.Serial=Serial -espresso_lite_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v2.menu.dbg.Serial1=Serial1 -espresso_lite_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espresso_lite_v2.menu.lvl.None____=None -espresso_lite_v2.menu.lvl.None____.build.debug_level= -espresso_lite_v2.menu.lvl.SSL=SSL -espresso_lite_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espresso_lite_v2.menu.lvl.TLS_MEM=TLS_MEM -espresso_lite_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espresso_lite_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espresso_lite_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER -espresso_lite_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espresso_lite_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.CORE=CORE -espresso_lite_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espresso_lite_v2.menu.lvl.WIFI=WIFI -espresso_lite_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espresso_lite_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espresso_lite_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v2.menu.lvl.UPDATER=UPDATER -espresso_lite_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espresso_lite_v2.menu.lvl.OTA=OTA -espresso_lite_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espresso_lite_v2.menu.lvl.OOM=OOM -espresso_lite_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espresso_lite_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espresso_lite_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espresso_lite_v2.menu.wipe.none=Only Sketch -espresso_lite_v2.menu.wipe.none.upload.erase_cmd= -espresso_lite_v2.menu.wipe.sdk=Sketch + WiFi Settings -espresso_lite_v2.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espresso_lite_v2.menu.wipe.all=All Flash Contents -espresso_lite_v2.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espresso_lite_v2.menu.baud.115200=115200 -espresso_lite_v2.menu.baud.115200.upload.speed=115200 -espresso_lite_v2.menu.baud.9600=9600 -espresso_lite_v2.menu.baud.9600.upload.speed=9600 -espresso_lite_v2.menu.baud.57600=57600 -espresso_lite_v2.menu.baud.57600.upload.speed=57600 -espresso_lite_v2.menu.baud.230400.linux=230400 -espresso_lite_v2.menu.baud.230400.macosx=230400 -espresso_lite_v2.menu.baud.230400.upload.speed=230400 -espresso_lite_v2.menu.baud.256000.windows=256000 -espresso_lite_v2.menu.baud.256000.upload.speed=256000 -espresso_lite_v2.menu.baud.460800.linux=460800 -espresso_lite_v2.menu.baud.460800.macosx=460800 -espresso_lite_v2.menu.baud.460800.upload.speed=460800 -espresso_lite_v2.menu.baud.512000.windows=512000 -espresso_lite_v2.menu.baud.512000.upload.speed=512000 -espresso_lite_v2.menu.baud.921600=921600 -espresso_lite_v2.menu.baud.921600.upload.speed=921600 - -############################################################## -phoenix_v1.name=Phoenix 1.0 -phoenix_v1.build.board=ESP8266_PHOENIX_V1 -phoenix_v1.build.variant=phoenix_v1 -phoenix_v1.upload.tool=esptool -phoenix_v1.upload.maximum_data_size=81920 -phoenix_v1.upload.wait_for_upload_port=true -phoenix_v1.upload.erase_cmd= -phoenix_v1.serial.disableDTR=true -phoenix_v1.serial.disableRTS=true -phoenix_v1.build.mcu=esp8266 -phoenix_v1.build.core=esp8266 -phoenix_v1.build.spiffs_pagesize=256 -phoenix_v1.build.debug_port= -phoenix_v1.build.debug_level= -phoenix_v1.menu.xtal.80=80 MHz -phoenix_v1.menu.xtal.80.build.f_cpu=80000000L -phoenix_v1.menu.xtal.160=160 MHz -phoenix_v1.menu.xtal.160.build.f_cpu=160000000L -phoenix_v1.menu.vt.flash=Flash -phoenix_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -phoenix_v1.menu.vt.heap=Heap -phoenix_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -phoenix_v1.menu.vt.iram=IRAM -phoenix_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -phoenix_v1.menu.exception.disabled=Disabled -phoenix_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions -phoenix_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -phoenix_v1.menu.exception.enabled=Enabled -phoenix_v1.menu.exception.enabled.build.exception_flags=-fexceptions -phoenix_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -phoenix_v1.build.flash_mode=dio -phoenix_v1.build.flash_flags=-DFLASHMODE_DIO -phoenix_v1.build.flash_freq=40 -phoenix_v1.menu.eesz.4M=4M (no SPIFFS) -phoenix_v1.menu.eesz.4M.build.flash_size=4M -phoenix_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -phoenix_v1.menu.eesz.4M.build.spiffs_pagesize=256 -phoenix_v1.menu.eesz.4M.upload.maximum_size=1044464 -phoenix_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.eesz.4M1M=4M (1M SPIFFS) -phoenix_v1.menu.eesz.4M1M.build.flash_size=4M -phoenix_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 -phoenix_v1.menu.eesz.4M1M.upload.maximum_size=1044464 -phoenix_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 -phoenix_v1.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 -phoenix_v1.menu.eesz.4M2M=4M (2M SPIFFS) -phoenix_v1.menu.eesz.4M2M.build.flash_size=4M -phoenix_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -phoenix_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 -phoenix_v1.menu.eesz.4M2M.upload.maximum_size=1044464 -phoenix_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 -phoenix_v1.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 -phoenix_v1.menu.eesz.4M3M=4M (3M SPIFFS) -phoenix_v1.menu.eesz.4M3M.build.flash_size=4M -phoenix_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -phoenix_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 -phoenix_v1.menu.eesz.4M3M.upload.maximum_size=1044464 -phoenix_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 -phoenix_v1.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 -phoenix_v1.menu.ResetMethod.ck=ck -phoenix_v1.menu.ResetMethod.ck.upload.resetmethod=ck -phoenix_v1.menu.ResetMethod.nodemcu=nodemcu -phoenix_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -phoenix_v1.menu.ip.lm2f=v2 Lower Memory -phoenix_v1.menu.ip.lm2f.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -phoenix_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -phoenix_v1.menu.ip.hb2f=v2 Higher Bandwidth -phoenix_v1.menu.ip.hb2f.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -phoenix_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -phoenix_v1.menu.ip.lm2n=v2 Lower Memory (no features) -phoenix_v1.menu.ip.lm2n.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -phoenix_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -phoenix_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) -phoenix_v1.menu.ip.hb2n.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -phoenix_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -phoenix_v1.menu.ip.lm6f=v2 IPv6 Lower Memory -phoenix_v1.menu.ip.lm6f.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -phoenix_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -phoenix_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -phoenix_v1.menu.ip.hb6f.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -phoenix_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -phoenix_v1.menu.ip.hb1=v1.4 Higher Bandwidth -phoenix_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc -phoenix_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v1.menu.ip.src=v1.4 Compile from source -phoenix_v1.menu.ip.src.build.lwip_lib=-llwip_src -phoenix_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -phoenix_v1.menu.dbg.Disabled=Disabled -phoenix_v1.menu.dbg.Disabled.build.debug_port= -phoenix_v1.menu.dbg.Serial=Serial -phoenix_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v1.menu.dbg.Serial1=Serial1 -phoenix_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -phoenix_v1.menu.lvl.None____=None -phoenix_v1.menu.lvl.None____.build.debug_level= -phoenix_v1.menu.lvl.SSL=SSL -phoenix_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -phoenix_v1.menu.lvl.TLS_MEM=TLS_MEM -phoenix_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -phoenix_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -phoenix_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER -phoenix_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -phoenix_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -phoenix_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -phoenix_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -phoenix_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.CORE=CORE -phoenix_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -phoenix_v1.menu.lvl.WIFI=WIFI -phoenix_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -phoenix_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -phoenix_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -phoenix_v1.menu.lvl.UPDATER=UPDATER -phoenix_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -phoenix_v1.menu.lvl.OTA=OTA -phoenix_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -phoenix_v1.menu.lvl.OOM=OOM -phoenix_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -phoenix_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -phoenix_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -phoenix_v1.menu.wipe.none=Only Sketch -phoenix_v1.menu.wipe.none.upload.erase_cmd= -phoenix_v1.menu.wipe.sdk=Sketch + WiFi Settings -phoenix_v1.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -phoenix_v1.menu.wipe.all=All Flash Contents -phoenix_v1.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -phoenix_v1.menu.baud.115200=115200 -phoenix_v1.menu.baud.115200.upload.speed=115200 -phoenix_v1.menu.baud.9600=9600 -phoenix_v1.menu.baud.9600.upload.speed=9600 -phoenix_v1.menu.baud.57600=57600 -phoenix_v1.menu.baud.57600.upload.speed=57600 -phoenix_v1.menu.baud.230400.linux=230400 -phoenix_v1.menu.baud.230400.macosx=230400 -phoenix_v1.menu.baud.230400.upload.speed=230400 -phoenix_v1.menu.baud.256000.windows=256000 -phoenix_v1.menu.baud.256000.upload.speed=256000 -phoenix_v1.menu.baud.460800.linux=460800 -phoenix_v1.menu.baud.460800.macosx=460800 -phoenix_v1.menu.baud.460800.upload.speed=460800 -phoenix_v1.menu.baud.512000.windows=512000 -phoenix_v1.menu.baud.512000.upload.speed=512000 -phoenix_v1.menu.baud.921600=921600 -phoenix_v1.menu.baud.921600.upload.speed=921600 - -############################################################## -phoenix_v2.name=Phoenix 2.0 -phoenix_v2.build.board=ESP8266_PHOENIX_V2 -phoenix_v2.build.variant=phoenix_v2 -phoenix_v2.upload.tool=esptool -phoenix_v2.upload.maximum_data_size=81920 -phoenix_v2.upload.wait_for_upload_port=true -phoenix_v2.upload.erase_cmd= -phoenix_v2.serial.disableDTR=true -phoenix_v2.serial.disableRTS=true -phoenix_v2.build.mcu=esp8266 -phoenix_v2.build.core=esp8266 -phoenix_v2.build.spiffs_pagesize=256 -phoenix_v2.build.debug_port= -phoenix_v2.build.debug_level= -phoenix_v2.menu.xtal.80=80 MHz -phoenix_v2.menu.xtal.80.build.f_cpu=80000000L -phoenix_v2.menu.xtal.160=160 MHz -phoenix_v2.menu.xtal.160.build.f_cpu=160000000L -phoenix_v2.menu.vt.flash=Flash -phoenix_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -phoenix_v2.menu.vt.heap=Heap -phoenix_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -phoenix_v2.menu.vt.iram=IRAM -phoenix_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -phoenix_v2.menu.exception.disabled=Disabled -phoenix_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions -phoenix_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -phoenix_v2.menu.exception.enabled=Enabled -phoenix_v2.menu.exception.enabled.build.exception_flags=-fexceptions -phoenix_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -phoenix_v2.build.flash_mode=dio -phoenix_v2.build.flash_flags=-DFLASHMODE_DIO -phoenix_v2.build.flash_freq=40 -phoenix_v2.menu.eesz.4M=4M (no SPIFFS) -phoenix_v2.menu.eesz.4M.build.flash_size=4M -phoenix_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -phoenix_v2.menu.eesz.4M.build.spiffs_pagesize=256 -phoenix_v2.menu.eesz.4M.upload.maximum_size=1044464 -phoenix_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.eesz.4M1M=4M (1M SPIFFS) -phoenix_v2.menu.eesz.4M1M.build.flash_size=4M -phoenix_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 -phoenix_v2.menu.eesz.4M1M.upload.maximum_size=1044464 -phoenix_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 -phoenix_v2.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 -phoenix_v2.menu.eesz.4M2M=4M (2M SPIFFS) -phoenix_v2.menu.eesz.4M2M.build.flash_size=4M -phoenix_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -phoenix_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 -phoenix_v2.menu.eesz.4M2M.upload.maximum_size=1044464 -phoenix_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 -phoenix_v2.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 -phoenix_v2.menu.eesz.4M3M=4M (3M SPIFFS) -phoenix_v2.menu.eesz.4M3M.build.flash_size=4M -phoenix_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -phoenix_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 -phoenix_v2.menu.eesz.4M3M.upload.maximum_size=1044464 -phoenix_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 -phoenix_v2.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 -phoenix_v2.menu.ResetMethod.ck=ck -phoenix_v2.menu.ResetMethod.ck.upload.resetmethod=ck -phoenix_v2.menu.ResetMethod.nodemcu=nodemcu -phoenix_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -phoenix_v2.menu.ip.lm2f=v2 Lower Memory -phoenix_v2.menu.ip.lm2f.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -phoenix_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -phoenix_v2.menu.ip.hb2f=v2 Higher Bandwidth -phoenix_v2.menu.ip.hb2f.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -phoenix_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -phoenix_v2.menu.ip.lm2n=v2 Lower Memory (no features) -phoenix_v2.menu.ip.lm2n.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -phoenix_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -phoenix_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) -phoenix_v2.menu.ip.hb2n.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -phoenix_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -phoenix_v2.menu.ip.lm6f=v2 IPv6 Lower Memory -phoenix_v2.menu.ip.lm6f.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -phoenix_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -phoenix_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -phoenix_v2.menu.ip.hb6f.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -phoenix_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -phoenix_v2.menu.ip.hb1=v1.4 Higher Bandwidth -phoenix_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc -phoenix_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v2.menu.ip.src=v1.4 Compile from source -phoenix_v2.menu.ip.src.build.lwip_lib=-llwip_src -phoenix_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -phoenix_v2.menu.dbg.Disabled=Disabled -phoenix_v2.menu.dbg.Disabled.build.debug_port= -phoenix_v2.menu.dbg.Serial=Serial -phoenix_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v2.menu.dbg.Serial1=Serial1 -phoenix_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -phoenix_v2.menu.lvl.None____=None -phoenix_v2.menu.lvl.None____.build.debug_level= -phoenix_v2.menu.lvl.SSL=SSL -phoenix_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -phoenix_v2.menu.lvl.TLS_MEM=TLS_MEM -phoenix_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -phoenix_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -phoenix_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER -phoenix_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -phoenix_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -phoenix_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -phoenix_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -phoenix_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.CORE=CORE -phoenix_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -phoenix_v2.menu.lvl.WIFI=WIFI -phoenix_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -phoenix_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -phoenix_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -phoenix_v2.menu.lvl.UPDATER=UPDATER -phoenix_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -phoenix_v2.menu.lvl.OTA=OTA -phoenix_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -phoenix_v2.menu.lvl.OOM=OOM -phoenix_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -phoenix_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -phoenix_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -phoenix_v2.menu.wipe.none=Only Sketch -phoenix_v2.menu.wipe.none.upload.erase_cmd= -phoenix_v2.menu.wipe.sdk=Sketch + WiFi Settings -phoenix_v2.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -phoenix_v2.menu.wipe.all=All Flash Contents -phoenix_v2.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -phoenix_v2.menu.baud.115200=115200 -phoenix_v2.menu.baud.115200.upload.speed=115200 -phoenix_v2.menu.baud.9600=9600 -phoenix_v2.menu.baud.9600.upload.speed=9600 -phoenix_v2.menu.baud.57600=57600 -phoenix_v2.menu.baud.57600.upload.speed=57600 -phoenix_v2.menu.baud.230400.linux=230400 -phoenix_v2.menu.baud.230400.macosx=230400 -phoenix_v2.menu.baud.230400.upload.speed=230400 -phoenix_v2.menu.baud.256000.windows=256000 -phoenix_v2.menu.baud.256000.upload.speed=256000 -phoenix_v2.menu.baud.460800.linux=460800 -phoenix_v2.menu.baud.460800.macosx=460800 -phoenix_v2.menu.baud.460800.upload.speed=460800 -phoenix_v2.menu.baud.512000.windows=512000 -phoenix_v2.menu.baud.512000.upload.speed=512000 -phoenix_v2.menu.baud.921600=921600 -phoenix_v2.menu.baud.921600.upload.speed=921600 - -############################################################## -nodemcu.name=NodeMCU 0.9 (ESP-12 Module) -nodemcu.build.board=ESP8266_NODEMCU -nodemcu.build.variant=nodemcu -nodemcu.upload.tool=esptool -nodemcu.upload.maximum_data_size=81920 -nodemcu.upload.wait_for_upload_port=true -nodemcu.upload.erase_cmd= -nodemcu.serial.disableDTR=true -nodemcu.serial.disableRTS=true -nodemcu.build.mcu=esp8266 -nodemcu.build.core=esp8266 -nodemcu.build.spiffs_pagesize=256 -nodemcu.build.debug_port= -nodemcu.build.debug_level= -nodemcu.menu.xtal.80=80 MHz -nodemcu.menu.xtal.80.build.f_cpu=80000000L -nodemcu.menu.xtal.160=160 MHz -nodemcu.menu.xtal.160.build.f_cpu=160000000L -nodemcu.menu.vt.flash=Flash -nodemcu.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -nodemcu.menu.vt.heap=Heap -nodemcu.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -nodemcu.menu.vt.iram=IRAM -nodemcu.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -nodemcu.menu.exception.disabled=Disabled -nodemcu.menu.exception.disabled.build.exception_flags=-fno-exceptions -nodemcu.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -nodemcu.menu.exception.enabled=Enabled -nodemcu.menu.exception.enabled.build.exception_flags=-fexceptions -nodemcu.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -nodemcu.upload.resetmethod=nodemcu -nodemcu.build.flash_mode=qio -nodemcu.build.flash_flags=-DFLASHMODE_QIO -nodemcu.build.flash_freq=40 -nodemcu.menu.eesz.4M=4M (no SPIFFS) -nodemcu.menu.eesz.4M.build.flash_size=4M -nodemcu.menu.eesz.4M.build.flash_size_bytes=0x400000 -nodemcu.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -nodemcu.menu.eesz.4M.build.spiffs_pagesize=256 -nodemcu.menu.eesz.4M.upload.maximum_size=1044464 -nodemcu.menu.eesz.4M.build.rfcal_addr=0x3FC000 -nodemcu.menu.eesz.4M1M=4M (1M SPIFFS) -nodemcu.menu.eesz.4M1M.build.flash_size=4M -nodemcu.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -nodemcu.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcu.menu.eesz.4M1M.build.spiffs_pagesize=256 -nodemcu.menu.eesz.4M1M.upload.maximum_size=1044464 -nodemcu.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -nodemcu.menu.eesz.4M1M.build.spiffs_start=0x300000 -nodemcu.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -nodemcu.menu.eesz.4M1M.build.spiffs_blocksize=8192 -nodemcu.menu.eesz.4M2M=4M (2M SPIFFS) -nodemcu.menu.eesz.4M2M.build.flash_size=4M -nodemcu.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -nodemcu.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -nodemcu.menu.eesz.4M2M.build.spiffs_pagesize=256 -nodemcu.menu.eesz.4M2M.upload.maximum_size=1044464 -nodemcu.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -nodemcu.menu.eesz.4M2M.build.spiffs_start=0x200000 -nodemcu.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -nodemcu.menu.eesz.4M2M.build.spiffs_blocksize=8192 -nodemcu.menu.eesz.4M3M=4M (3M SPIFFS) -nodemcu.menu.eesz.4M3M.build.flash_size=4M -nodemcu.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -nodemcu.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -nodemcu.menu.eesz.4M3M.build.spiffs_pagesize=256 -nodemcu.menu.eesz.4M3M.upload.maximum_size=1044464 -nodemcu.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -nodemcu.menu.eesz.4M3M.build.spiffs_start=0x100000 -nodemcu.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -nodemcu.menu.eesz.4M3M.build.spiffs_blocksize=8192 -nodemcu.menu.ip.lm2f=v2 Lower Memory -nodemcu.menu.ip.lm2f.build.lwip_include=lwip2/include -nodemcu.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -nodemcu.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -nodemcu.menu.ip.hb2f=v2 Higher Bandwidth -nodemcu.menu.ip.hb2f.build.lwip_include=lwip2/include -nodemcu.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -nodemcu.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -nodemcu.menu.ip.lm2n=v2 Lower Memory (no features) -nodemcu.menu.ip.lm2n.build.lwip_include=lwip2/include -nodemcu.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -nodemcu.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -nodemcu.menu.ip.hb2n=v2 Higher Bandwidth (no features) -nodemcu.menu.ip.hb2n.build.lwip_include=lwip2/include -nodemcu.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -nodemcu.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -nodemcu.menu.ip.lm6f=v2 IPv6 Lower Memory -nodemcu.menu.ip.lm6f.build.lwip_include=lwip2/include -nodemcu.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -nodemcu.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -nodemcu.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -nodemcu.menu.ip.hb6f.build.lwip_include=lwip2/include -nodemcu.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -nodemcu.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -nodemcu.menu.ip.hb1=v1.4 Higher Bandwidth -nodemcu.menu.ip.hb1.build.lwip_lib=-llwip_gcc -nodemcu.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcu.menu.ip.src=v1.4 Compile from source -nodemcu.menu.ip.src.build.lwip_lib=-llwip_src -nodemcu.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcu.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -nodemcu.menu.dbg.Disabled=Disabled -nodemcu.menu.dbg.Disabled.build.debug_port= -nodemcu.menu.dbg.Serial=Serial -nodemcu.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -nodemcu.menu.dbg.Serial1=Serial1 -nodemcu.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -nodemcu.menu.lvl.None____=None -nodemcu.menu.lvl.None____.build.debug_level= -nodemcu.menu.lvl.SSL=SSL -nodemcu.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -nodemcu.menu.lvl.TLS_MEM=TLS_MEM -nodemcu.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -nodemcu.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -nodemcu.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.lvl.HTTP_SERVER=HTTP_SERVER -nodemcu.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -nodemcu.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -nodemcu.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -nodemcu.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -nodemcu.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -nodemcu.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.CORE=CORE -nodemcu.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -nodemcu.menu.lvl.WIFI=WIFI -nodemcu.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -nodemcu.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -nodemcu.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -nodemcu.menu.lvl.UPDATER=UPDATER -nodemcu.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -nodemcu.menu.lvl.OTA=OTA -nodemcu.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -nodemcu.menu.lvl.OOM=OOM -nodemcu.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -nodemcu.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -nodemcu.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -nodemcu.menu.wipe.none=Only Sketch -nodemcu.menu.wipe.none.upload.erase_cmd= -nodemcu.menu.wipe.sdk=Sketch + WiFi Settings -nodemcu.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -nodemcu.menu.wipe.all=All Flash Contents -nodemcu.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -nodemcu.menu.baud.115200=115200 -nodemcu.menu.baud.115200.upload.speed=115200 -nodemcu.menu.baud.9600=9600 -nodemcu.menu.baud.9600.upload.speed=9600 -nodemcu.menu.baud.57600=57600 -nodemcu.menu.baud.57600.upload.speed=57600 -nodemcu.menu.baud.230400.linux=230400 -nodemcu.menu.baud.230400.macosx=230400 -nodemcu.menu.baud.230400.upload.speed=230400 -nodemcu.menu.baud.256000.windows=256000 -nodemcu.menu.baud.256000.upload.speed=256000 -nodemcu.menu.baud.460800.linux=460800 -nodemcu.menu.baud.460800.macosx=460800 -nodemcu.menu.baud.460800.upload.speed=460800 -nodemcu.menu.baud.512000.windows=512000 -nodemcu.menu.baud.512000.upload.speed=512000 -nodemcu.menu.baud.921600=921600 -nodemcu.menu.baud.921600.upload.speed=921600 - -############################################################## -nodemcuv2.name=NodeMCU 1.0 (ESP-12E Module) -nodemcuv2.build.board=ESP8266_NODEMCU -nodemcuv2.build.variant=nodemcu -nodemcuv2.upload.tool=esptool -nodemcuv2.upload.maximum_data_size=81920 -nodemcuv2.upload.wait_for_upload_port=true -nodemcuv2.upload.erase_cmd= -nodemcuv2.serial.disableDTR=true -nodemcuv2.serial.disableRTS=true -nodemcuv2.build.mcu=esp8266 -nodemcuv2.build.core=esp8266 -nodemcuv2.build.spiffs_pagesize=256 -nodemcuv2.build.debug_port= -nodemcuv2.build.debug_level= -nodemcuv2.menu.xtal.80=80 MHz -nodemcuv2.menu.xtal.80.build.f_cpu=80000000L -nodemcuv2.menu.xtal.160=160 MHz -nodemcuv2.menu.xtal.160.build.f_cpu=160000000L -nodemcuv2.menu.vt.flash=Flash -nodemcuv2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -nodemcuv2.menu.vt.heap=Heap -nodemcuv2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -nodemcuv2.menu.vt.iram=IRAM -nodemcuv2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -nodemcuv2.menu.exception.disabled=Disabled -nodemcuv2.menu.exception.disabled.build.exception_flags=-fno-exceptions -nodemcuv2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -nodemcuv2.menu.exception.enabled=Enabled -nodemcuv2.menu.exception.enabled.build.exception_flags=-fexceptions -nodemcuv2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -nodemcuv2.upload.resetmethod=nodemcu -nodemcuv2.build.flash_mode=dio -nodemcuv2.build.flash_flags=-DFLASHMODE_DIO -nodemcuv2.build.flash_freq=40 -nodemcuv2.menu.eesz.4M=4M (no SPIFFS) -nodemcuv2.menu.eesz.4M.build.flash_size=4M -nodemcuv2.menu.eesz.4M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -nodemcuv2.menu.eesz.4M.build.spiffs_pagesize=256 -nodemcuv2.menu.eesz.4M.upload.maximum_size=1044464 -nodemcuv2.menu.eesz.4M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.eesz.4M1M=4M (1M SPIFFS) -nodemcuv2.menu.eesz.4M1M.build.flash_size=4M -nodemcuv2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcuv2.menu.eesz.4M1M.build.spiffs_pagesize=256 -nodemcuv2.menu.eesz.4M1M.upload.maximum_size=1044464 -nodemcuv2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.eesz.4M1M.build.spiffs_start=0x300000 -nodemcuv2.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.eesz.4M1M.build.spiffs_blocksize=8192 -nodemcuv2.menu.eesz.4M2M=4M (2M SPIFFS) -nodemcuv2.menu.eesz.4M2M.build.flash_size=4M -nodemcuv2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -nodemcuv2.menu.eesz.4M2M.build.spiffs_pagesize=256 -nodemcuv2.menu.eesz.4M2M.upload.maximum_size=1044464 -nodemcuv2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.eesz.4M2M.build.spiffs_start=0x200000 -nodemcuv2.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.eesz.4M2M.build.spiffs_blocksize=8192 -nodemcuv2.menu.eesz.4M3M=4M (3M SPIFFS) -nodemcuv2.menu.eesz.4M3M.build.flash_size=4M -nodemcuv2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -nodemcuv2.menu.eesz.4M3M.build.spiffs_pagesize=256 -nodemcuv2.menu.eesz.4M3M.upload.maximum_size=1044464 -nodemcuv2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.eesz.4M3M.build.spiffs_start=0x100000 -nodemcuv2.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.eesz.4M3M.build.spiffs_blocksize=8192 -nodemcuv2.menu.ip.lm2f=v2 Lower Memory -nodemcuv2.menu.ip.lm2f.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -nodemcuv2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -nodemcuv2.menu.ip.hb2f=v2 Higher Bandwidth -nodemcuv2.menu.ip.hb2f.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -nodemcuv2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -nodemcuv2.menu.ip.lm2n=v2 Lower Memory (no features) -nodemcuv2.menu.ip.lm2n.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -nodemcuv2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -nodemcuv2.menu.ip.hb2n=v2 Higher Bandwidth (no features) -nodemcuv2.menu.ip.hb2n.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -nodemcuv2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -nodemcuv2.menu.ip.lm6f=v2 IPv6 Lower Memory -nodemcuv2.menu.ip.lm6f.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -nodemcuv2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -nodemcuv2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -nodemcuv2.menu.ip.hb6f.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -nodemcuv2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -nodemcuv2.menu.ip.hb1=v1.4 Higher Bandwidth -nodemcuv2.menu.ip.hb1.build.lwip_lib=-llwip_gcc -nodemcuv2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcuv2.menu.ip.src=v1.4 Compile from source -nodemcuv2.menu.ip.src.build.lwip_lib=-llwip_src -nodemcuv2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcuv2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -nodemcuv2.menu.dbg.Disabled=Disabled -nodemcuv2.menu.dbg.Disabled.build.debug_port= -nodemcuv2.menu.dbg.Serial=Serial -nodemcuv2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -nodemcuv2.menu.dbg.Serial1=Serial1 -nodemcuv2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -nodemcuv2.menu.lvl.None____=None -nodemcuv2.menu.lvl.None____.build.debug_level= -nodemcuv2.menu.lvl.SSL=SSL -nodemcuv2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -nodemcuv2.menu.lvl.TLS_MEM=TLS_MEM -nodemcuv2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -nodemcuv2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -nodemcuv2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.lvl.HTTP_SERVER=HTTP_SERVER -nodemcuv2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -nodemcuv2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -nodemcuv2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -nodemcuv2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -nodemcuv2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.CORE=CORE -nodemcuv2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -nodemcuv2.menu.lvl.WIFI=WIFI -nodemcuv2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -nodemcuv2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -nodemcuv2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -nodemcuv2.menu.lvl.UPDATER=UPDATER -nodemcuv2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -nodemcuv2.menu.lvl.OTA=OTA -nodemcuv2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -nodemcuv2.menu.lvl.OOM=OOM -nodemcuv2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -nodemcuv2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -nodemcuv2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -nodemcuv2.menu.wipe.none=Only Sketch -nodemcuv2.menu.wipe.none.upload.erase_cmd= -nodemcuv2.menu.wipe.sdk=Sketch + WiFi Settings -nodemcuv2.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -nodemcuv2.menu.wipe.all=All Flash Contents -nodemcuv2.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -nodemcuv2.menu.baud.115200=115200 -nodemcuv2.menu.baud.115200.upload.speed=115200 -nodemcuv2.menu.baud.9600=9600 -nodemcuv2.menu.baud.9600.upload.speed=9600 -nodemcuv2.menu.baud.57600=57600 -nodemcuv2.menu.baud.57600.upload.speed=57600 -nodemcuv2.menu.baud.230400.linux=230400 -nodemcuv2.menu.baud.230400.macosx=230400 -nodemcuv2.menu.baud.230400.upload.speed=230400 -nodemcuv2.menu.baud.256000.windows=256000 -nodemcuv2.menu.baud.256000.upload.speed=256000 -nodemcuv2.menu.baud.460800.linux=460800 -nodemcuv2.menu.baud.460800.macosx=460800 -nodemcuv2.menu.baud.460800.upload.speed=460800 -nodemcuv2.menu.baud.512000.windows=512000 -nodemcuv2.menu.baud.512000.upload.speed=512000 -nodemcuv2.menu.baud.921600=921600 -nodemcuv2.menu.baud.921600.upload.speed=921600 - -############################################################## -modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV) -modwifi.build.board=MOD_WIFI_ESP8266 -modwifi.build.variant=modwifi -modwifi.upload.tool=esptool -modwifi.upload.maximum_data_size=81920 -modwifi.upload.wait_for_upload_port=true -modwifi.upload.erase_cmd= -modwifi.serial.disableDTR=true -modwifi.serial.disableRTS=true -modwifi.build.mcu=esp8266 -modwifi.build.core=esp8266 -modwifi.build.spiffs_pagesize=256 -modwifi.build.debug_port= -modwifi.build.debug_level= -modwifi.menu.xtal.80=80 MHz -modwifi.menu.xtal.80.build.f_cpu=80000000L -modwifi.menu.xtal.160=160 MHz -modwifi.menu.xtal.160.build.f_cpu=160000000L -modwifi.menu.vt.flash=Flash -modwifi.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -modwifi.menu.vt.heap=Heap -modwifi.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -modwifi.menu.vt.iram=IRAM -modwifi.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -modwifi.menu.exception.disabled=Disabled -modwifi.menu.exception.disabled.build.exception_flags=-fno-exceptions -modwifi.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -modwifi.menu.exception.enabled=Enabled -modwifi.menu.exception.enabled.build.exception_flags=-fexceptions -modwifi.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -modwifi.upload.resetmethod=ck -modwifi.build.flash_mode=qio -modwifi.build.flash_flags=-DFLASHMODE_QIO -modwifi.build.flash_freq=40 -modwifi.menu.eesz.2M=2M (no SPIFFS) -modwifi.menu.eesz.2M.build.flash_size=2M -modwifi.menu.eesz.2M.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld -modwifi.menu.eesz.2M.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M.upload.maximum_size=1044464 -modwifi.menu.eesz.2M.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M128=2M (128K SPIFFS) -modwifi.menu.eesz.2M128.build.flash_size=2M -modwifi.menu.eesz.2M128.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld -modwifi.menu.eesz.2M128.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M128.upload.maximum_size=1044464 -modwifi.menu.eesz.2M128.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M128.build.spiffs_start=0x1E0000 -modwifi.menu.eesz.2M128.build.spiffs_end=0x1FB000 -modwifi.menu.eesz.2M128.build.spiffs_blocksize=4096 -modwifi.menu.eesz.2M256=2M (256K SPIFFS) -modwifi.menu.eesz.2M256.build.flash_size=2M -modwifi.menu.eesz.2M256.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld -modwifi.menu.eesz.2M256.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M256.upload.maximum_size=1044464 -modwifi.menu.eesz.2M256.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M256.build.spiffs_start=0x1C0000 -modwifi.menu.eesz.2M256.build.spiffs_end=0x1FB000 -modwifi.menu.eesz.2M256.build.spiffs_blocksize=4096 -modwifi.menu.eesz.2M512=2M (512K SPIFFS) -modwifi.menu.eesz.2M512.build.flash_size=2M -modwifi.menu.eesz.2M512.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld -modwifi.menu.eesz.2M512.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M512.upload.maximum_size=1044464 -modwifi.menu.eesz.2M512.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M512.build.spiffs_start=0x180000 -modwifi.menu.eesz.2M512.build.spiffs_end=0x1FB000 -modwifi.menu.eesz.2M512.build.spiffs_blocksize=8192 -modwifi.menu.eesz.2M1M=2M (1M SPIFFS) -modwifi.menu.eesz.2M1M.build.flash_size=2M -modwifi.menu.eesz.2M1M.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld -modwifi.menu.eesz.2M1M.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M1M.upload.maximum_size=1044464 -modwifi.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M1M.build.spiffs_start=0x100000 -modwifi.menu.eesz.2M1M.build.spiffs_end=0x1FB000 -modwifi.menu.eesz.2M1M.build.spiffs_blocksize=8192 -modwifi.menu.ip.lm2f=v2 Lower Memory -modwifi.menu.ip.lm2f.build.lwip_include=lwip2/include -modwifi.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -modwifi.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -modwifi.menu.ip.hb2f=v2 Higher Bandwidth -modwifi.menu.ip.hb2f.build.lwip_include=lwip2/include -modwifi.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -modwifi.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -modwifi.menu.ip.lm2n=v2 Lower Memory (no features) -modwifi.menu.ip.lm2n.build.lwip_include=lwip2/include -modwifi.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -modwifi.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -modwifi.menu.ip.hb2n=v2 Higher Bandwidth (no features) -modwifi.menu.ip.hb2n.build.lwip_include=lwip2/include -modwifi.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -modwifi.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -modwifi.menu.ip.lm6f=v2 IPv6 Lower Memory -modwifi.menu.ip.lm6f.build.lwip_include=lwip2/include -modwifi.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -modwifi.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -modwifi.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -modwifi.menu.ip.hb6f.build.lwip_include=lwip2/include -modwifi.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -modwifi.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -modwifi.menu.ip.hb1=v1.4 Higher Bandwidth -modwifi.menu.ip.hb1.build.lwip_lib=-llwip_gcc -modwifi.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -modwifi.menu.ip.src=v1.4 Compile from source -modwifi.menu.ip.src.build.lwip_lib=-llwip_src -modwifi.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -modwifi.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -modwifi.menu.dbg.Disabled=Disabled -modwifi.menu.dbg.Disabled.build.debug_port= -modwifi.menu.dbg.Serial=Serial -modwifi.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -modwifi.menu.dbg.Serial1=Serial1 -modwifi.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -modwifi.menu.lvl.None____=None -modwifi.menu.lvl.None____.build.debug_level= -modwifi.menu.lvl.SSL=SSL -modwifi.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -modwifi.menu.lvl.TLS_MEM=TLS_MEM -modwifi.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -modwifi.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -modwifi.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.lvl.HTTP_SERVER=HTTP_SERVER -modwifi.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -modwifi.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -modwifi.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -modwifi.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -modwifi.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -modwifi.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -modwifi.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.CORE=CORE -modwifi.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -modwifi.menu.lvl.WIFI=WIFI -modwifi.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -modwifi.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -modwifi.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -modwifi.menu.lvl.UPDATER=UPDATER -modwifi.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -modwifi.menu.lvl.OTA=OTA -modwifi.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -modwifi.menu.lvl.OOM=OOM -modwifi.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -modwifi.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -modwifi.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -modwifi.menu.wipe.none=Only Sketch -modwifi.menu.wipe.none.upload.erase_cmd= -modwifi.menu.wipe.sdk=Sketch + WiFi Settings -modwifi.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -modwifi.menu.wipe.all=All Flash Contents -modwifi.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -modwifi.menu.baud.115200=115200 -modwifi.menu.baud.115200.upload.speed=115200 -modwifi.menu.baud.9600=9600 -modwifi.menu.baud.9600.upload.speed=9600 -modwifi.menu.baud.57600=57600 -modwifi.menu.baud.57600.upload.speed=57600 -modwifi.menu.baud.230400.linux=230400 -modwifi.menu.baud.230400.macosx=230400 -modwifi.menu.baud.230400.upload.speed=230400 -modwifi.menu.baud.256000.windows=256000 -modwifi.menu.baud.256000.upload.speed=256000 -modwifi.menu.baud.460800.linux=460800 -modwifi.menu.baud.460800.macosx=460800 -modwifi.menu.baud.460800.upload.speed=460800 -modwifi.menu.baud.512000.windows=512000 -modwifi.menu.baud.512000.upload.speed=512000 -modwifi.menu.baud.921600=921600 -modwifi.menu.baud.921600.upload.speed=921600 - -############################################################## -thing.name=SparkFun ESP8266 Thing -thing.build.board=ESP8266_THING -thing.build.variant=thing -thing.upload.tool=esptool -thing.upload.maximum_data_size=81920 -thing.upload.wait_for_upload_port=true -thing.upload.erase_cmd= -thing.serial.disableDTR=true -thing.serial.disableRTS=true -thing.build.mcu=esp8266 -thing.build.core=esp8266 -thing.build.spiffs_pagesize=256 -thing.build.debug_port= -thing.build.debug_level= -thing.menu.xtal.80=80 MHz -thing.menu.xtal.80.build.f_cpu=80000000L -thing.menu.xtal.160=160 MHz -thing.menu.xtal.160.build.f_cpu=160000000L -thing.menu.vt.flash=Flash -thing.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -thing.menu.vt.heap=Heap -thing.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -thing.menu.vt.iram=IRAM -thing.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -thing.menu.exception.disabled=Disabled -thing.menu.exception.disabled.build.exception_flags=-fno-exceptions -thing.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -thing.menu.exception.enabled=Enabled -thing.menu.exception.enabled.build.exception_flags=-fexceptions -thing.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -thing.upload.resetmethod=ck -thing.build.flash_mode=qio -thing.build.flash_flags=-DFLASHMODE_QIO -thing.build.flash_freq=40 -thing.menu.eesz.512K=512K (no SPIFFS) -thing.menu.eesz.512K.build.flash_size=512K -thing.menu.eesz.512K.build.flash_size_bytes=0x80000 -thing.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld -thing.menu.eesz.512K.build.spiffs_pagesize=256 -thing.menu.eesz.512K.upload.maximum_size=499696 -thing.menu.eesz.512K.build.rfcal_addr=0x7C000 -thing.menu.eesz.512K32=512K (32K SPIFFS) -thing.menu.eesz.512K32.build.flash_size=512K -thing.menu.eesz.512K32.build.flash_size_bytes=0x80000 -thing.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld -thing.menu.eesz.512K32.build.spiffs_pagesize=256 -thing.menu.eesz.512K32.upload.maximum_size=466928 -thing.menu.eesz.512K32.build.rfcal_addr=0x7C000 -thing.menu.eesz.512K32.build.spiffs_start=0x73000 -thing.menu.eesz.512K32.build.spiffs_end=0x7B000 -thing.menu.eesz.512K32.build.spiffs_blocksize=4096 -thing.menu.eesz.512K64=512K (64K SPIFFS) -thing.menu.eesz.512K64.build.flash_size=512K -thing.menu.eesz.512K64.build.flash_size_bytes=0x80000 -thing.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld -thing.menu.eesz.512K64.build.spiffs_pagesize=256 -thing.menu.eesz.512K64.upload.maximum_size=434160 -thing.menu.eesz.512K64.build.rfcal_addr=0x7C000 -thing.menu.eesz.512K64.build.spiffs_start=0x6B000 -thing.menu.eesz.512K64.build.spiffs_end=0x7B000 -thing.menu.eesz.512K64.build.spiffs_blocksize=4096 -thing.menu.eesz.512K128=512K (128K SPIFFS) -thing.menu.eesz.512K128.build.flash_size=512K -thing.menu.eesz.512K128.build.flash_size_bytes=0x80000 -thing.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld -thing.menu.eesz.512K128.build.spiffs_pagesize=256 -thing.menu.eesz.512K128.upload.maximum_size=368624 -thing.menu.eesz.512K128.build.rfcal_addr=0x7C000 -thing.menu.eesz.512K128.build.spiffs_start=0x5B000 -thing.menu.eesz.512K128.build.spiffs_end=0x7B000 -thing.menu.eesz.512K128.build.spiffs_blocksize=4096 -thing.menu.ip.lm2f=v2 Lower Memory -thing.menu.ip.lm2f.build.lwip_include=lwip2/include -thing.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -thing.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -thing.menu.ip.hb2f=v2 Higher Bandwidth -thing.menu.ip.hb2f.build.lwip_include=lwip2/include -thing.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -thing.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -thing.menu.ip.lm2n=v2 Lower Memory (no features) -thing.menu.ip.lm2n.build.lwip_include=lwip2/include -thing.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -thing.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -thing.menu.ip.hb2n=v2 Higher Bandwidth (no features) -thing.menu.ip.hb2n.build.lwip_include=lwip2/include -thing.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -thing.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -thing.menu.ip.lm6f=v2 IPv6 Lower Memory -thing.menu.ip.lm6f.build.lwip_include=lwip2/include -thing.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -thing.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -thing.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -thing.menu.ip.hb6f.build.lwip_include=lwip2/include -thing.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -thing.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -thing.menu.ip.hb1=v1.4 Higher Bandwidth -thing.menu.ip.hb1.build.lwip_lib=-llwip_gcc -thing.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -thing.menu.ip.src=v1.4 Compile from source -thing.menu.ip.src.build.lwip_lib=-llwip_src -thing.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -thing.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -thing.menu.dbg.Disabled=Disabled -thing.menu.dbg.Disabled.build.debug_port= -thing.menu.dbg.Serial=Serial -thing.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -thing.menu.dbg.Serial1=Serial1 -thing.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -thing.menu.lvl.None____=None -thing.menu.lvl.None____.build.debug_level= -thing.menu.lvl.SSL=SSL -thing.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -thing.menu.lvl.TLS_MEM=TLS_MEM -thing.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -thing.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -thing.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -thing.menu.lvl.HTTP_SERVER=HTTP_SERVER -thing.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -thing.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -thing.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -thing.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -thing.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -thing.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -thing.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thing.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -thing.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -thing.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thing.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -thing.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.CORE=CORE -thing.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -thing.menu.lvl.WIFI=WIFI -thing.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -thing.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -thing.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -thing.menu.lvl.UPDATER=UPDATER -thing.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -thing.menu.lvl.OTA=OTA -thing.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -thing.menu.lvl.OOM=OOM -thing.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -thing.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -thing.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -thing.menu.wipe.none=Only Sketch -thing.menu.wipe.none.upload.erase_cmd= -thing.menu.wipe.sdk=Sketch + WiFi Settings -thing.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -thing.menu.wipe.all=All Flash Contents -thing.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -thing.menu.baud.115200=115200 -thing.menu.baud.115200.upload.speed=115200 -thing.menu.baud.9600=9600 -thing.menu.baud.9600.upload.speed=9600 -thing.menu.baud.57600=57600 -thing.menu.baud.57600.upload.speed=57600 -thing.menu.baud.230400.linux=230400 -thing.menu.baud.230400.macosx=230400 -thing.menu.baud.230400.upload.speed=230400 -thing.menu.baud.256000.windows=256000 -thing.menu.baud.256000.upload.speed=256000 -thing.menu.baud.460800.linux=460800 -thing.menu.baud.460800.macosx=460800 -thing.menu.baud.460800.upload.speed=460800 -thing.menu.baud.512000.windows=512000 -thing.menu.baud.512000.upload.speed=512000 -thing.menu.baud.921600=921600 -thing.menu.baud.921600.upload.speed=921600 - -############################################################## -thingdev.name=SparkFun ESP8266 Thing Dev -thingdev.build.board=ESP8266_THING_DEV -thingdev.build.variant=thing -thingdev.upload.tool=esptool -thingdev.upload.maximum_data_size=81920 -thingdev.upload.wait_for_upload_port=true -thingdev.upload.erase_cmd= -thingdev.serial.disableDTR=true -thingdev.serial.disableRTS=true -thingdev.build.mcu=esp8266 -thingdev.build.core=esp8266 -thingdev.build.spiffs_pagesize=256 -thingdev.build.debug_port= -thingdev.build.debug_level= -thingdev.menu.xtal.80=80 MHz -thingdev.menu.xtal.80.build.f_cpu=80000000L -thingdev.menu.xtal.160=160 MHz -thingdev.menu.xtal.160.build.f_cpu=160000000L -thingdev.menu.vt.flash=Flash -thingdev.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -thingdev.menu.vt.heap=Heap -thingdev.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -thingdev.menu.vt.iram=IRAM -thingdev.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -thingdev.menu.exception.disabled=Disabled -thingdev.menu.exception.disabled.build.exception_flags=-fno-exceptions -thingdev.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -thingdev.menu.exception.enabled=Enabled -thingdev.menu.exception.enabled.build.exception_flags=-fexceptions -thingdev.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -thingdev.upload.resetmethod=nodemcu -thingdev.build.flash_mode=dio -thingdev.build.flash_flags=-DFLASHMODE_DIO -thingdev.build.flash_freq=40 -thingdev.menu.eesz.512K=512K (no SPIFFS) -thingdev.menu.eesz.512K.build.flash_size=512K -thingdev.menu.eesz.512K.build.flash_size_bytes=0x80000 -thingdev.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld -thingdev.menu.eesz.512K.build.spiffs_pagesize=256 -thingdev.menu.eesz.512K.upload.maximum_size=499696 -thingdev.menu.eesz.512K.build.rfcal_addr=0x7C000 -thingdev.menu.eesz.512K32=512K (32K SPIFFS) -thingdev.menu.eesz.512K32.build.flash_size=512K -thingdev.menu.eesz.512K32.build.flash_size_bytes=0x80000 -thingdev.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld -thingdev.menu.eesz.512K32.build.spiffs_pagesize=256 -thingdev.menu.eesz.512K32.upload.maximum_size=466928 -thingdev.menu.eesz.512K32.build.rfcal_addr=0x7C000 -thingdev.menu.eesz.512K32.build.spiffs_start=0x73000 -thingdev.menu.eesz.512K32.build.spiffs_end=0x7B000 -thingdev.menu.eesz.512K32.build.spiffs_blocksize=4096 -thingdev.menu.eesz.512K64=512K (64K SPIFFS) -thingdev.menu.eesz.512K64.build.flash_size=512K -thingdev.menu.eesz.512K64.build.flash_size_bytes=0x80000 -thingdev.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld -thingdev.menu.eesz.512K64.build.spiffs_pagesize=256 -thingdev.menu.eesz.512K64.upload.maximum_size=434160 -thingdev.menu.eesz.512K64.build.rfcal_addr=0x7C000 -thingdev.menu.eesz.512K64.build.spiffs_start=0x6B000 -thingdev.menu.eesz.512K64.build.spiffs_end=0x7B000 -thingdev.menu.eesz.512K64.build.spiffs_blocksize=4096 -thingdev.menu.eesz.512K128=512K (128K SPIFFS) -thingdev.menu.eesz.512K128.build.flash_size=512K -thingdev.menu.eesz.512K128.build.flash_size_bytes=0x80000 -thingdev.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld -thingdev.menu.eesz.512K128.build.spiffs_pagesize=256 -thingdev.menu.eesz.512K128.upload.maximum_size=368624 -thingdev.menu.eesz.512K128.build.rfcal_addr=0x7C000 -thingdev.menu.eesz.512K128.build.spiffs_start=0x5B000 -thingdev.menu.eesz.512K128.build.spiffs_end=0x7B000 -thingdev.menu.eesz.512K128.build.spiffs_blocksize=4096 -thingdev.menu.ip.lm2f=v2 Lower Memory -thingdev.menu.ip.lm2f.build.lwip_include=lwip2/include -thingdev.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -thingdev.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -thingdev.menu.ip.hb2f=v2 Higher Bandwidth -thingdev.menu.ip.hb2f.build.lwip_include=lwip2/include -thingdev.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -thingdev.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -thingdev.menu.ip.lm2n=v2 Lower Memory (no features) -thingdev.menu.ip.lm2n.build.lwip_include=lwip2/include -thingdev.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -thingdev.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -thingdev.menu.ip.hb2n=v2 Higher Bandwidth (no features) -thingdev.menu.ip.hb2n.build.lwip_include=lwip2/include -thingdev.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -thingdev.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -thingdev.menu.ip.lm6f=v2 IPv6 Lower Memory -thingdev.menu.ip.lm6f.build.lwip_include=lwip2/include -thingdev.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -thingdev.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -thingdev.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -thingdev.menu.ip.hb6f.build.lwip_include=lwip2/include -thingdev.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -thingdev.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -thingdev.menu.ip.hb1=v1.4 Higher Bandwidth -thingdev.menu.ip.hb1.build.lwip_lib=-llwip_gcc -thingdev.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -thingdev.menu.ip.src=v1.4 Compile from source -thingdev.menu.ip.src.build.lwip_lib=-llwip_src -thingdev.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -thingdev.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -thingdev.menu.dbg.Disabled=Disabled -thingdev.menu.dbg.Disabled.build.debug_port= -thingdev.menu.dbg.Serial=Serial -thingdev.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -thingdev.menu.dbg.Serial1=Serial1 -thingdev.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -thingdev.menu.lvl.None____=None -thingdev.menu.lvl.None____.build.debug_level= -thingdev.menu.lvl.SSL=SSL -thingdev.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -thingdev.menu.lvl.TLS_MEM=TLS_MEM -thingdev.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -thingdev.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -thingdev.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.lvl.HTTP_SERVER=HTTP_SERVER -thingdev.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -thingdev.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -thingdev.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -thingdev.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -thingdev.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -thingdev.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -thingdev.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.CORE=CORE -thingdev.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -thingdev.menu.lvl.WIFI=WIFI -thingdev.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -thingdev.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -thingdev.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -thingdev.menu.lvl.UPDATER=UPDATER -thingdev.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -thingdev.menu.lvl.OTA=OTA -thingdev.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -thingdev.menu.lvl.OOM=OOM -thingdev.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -thingdev.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -thingdev.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -thingdev.menu.wipe.none=Only Sketch -thingdev.menu.wipe.none.upload.erase_cmd= -thingdev.menu.wipe.sdk=Sketch + WiFi Settings -thingdev.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -thingdev.menu.wipe.all=All Flash Contents -thingdev.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -thingdev.menu.baud.115200=115200 -thingdev.menu.baud.115200.upload.speed=115200 -thingdev.menu.baud.9600=9600 -thingdev.menu.baud.9600.upload.speed=9600 -thingdev.menu.baud.57600=57600 -thingdev.menu.baud.57600.upload.speed=57600 -thingdev.menu.baud.230400.linux=230400 -thingdev.menu.baud.230400.macosx=230400 -thingdev.menu.baud.230400.upload.speed=230400 -thingdev.menu.baud.256000.windows=256000 -thingdev.menu.baud.256000.upload.speed=256000 -thingdev.menu.baud.460800.linux=460800 -thingdev.menu.baud.460800.macosx=460800 -thingdev.menu.baud.460800.upload.speed=460800 -thingdev.menu.baud.512000.windows=512000 -thingdev.menu.baud.512000.upload.speed=512000 -thingdev.menu.baud.921600=921600 -thingdev.menu.baud.921600.upload.speed=921600 - -############################################################## -esp210.name=SweetPea ESP-210 -esp210.build.board=ESP8266_ESP210 -esp210.upload.tool=esptool -esp210.upload.maximum_data_size=81920 -esp210.upload.wait_for_upload_port=true -esp210.upload.erase_cmd= -esp210.serial.disableDTR=true -esp210.serial.disableRTS=true -esp210.build.mcu=esp8266 -esp210.build.core=esp8266 -esp210.build.variant=generic -esp210.build.spiffs_pagesize=256 -esp210.build.debug_port= -esp210.build.debug_level= -esp210.menu.xtal.80=80 MHz -esp210.menu.xtal.80.build.f_cpu=80000000L -esp210.menu.xtal.160=160 MHz -esp210.menu.xtal.160.build.f_cpu=160000000L -esp210.menu.vt.flash=Flash -esp210.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -esp210.menu.vt.heap=Heap -esp210.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -esp210.menu.vt.iram=IRAM -esp210.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -esp210.menu.exception.disabled=Disabled -esp210.menu.exception.disabled.build.exception_flags=-fno-exceptions -esp210.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -esp210.menu.exception.enabled=Enabled -esp210.menu.exception.enabled.build.exception_flags=-fexceptions -esp210.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -esp210.upload.resetmethod=ck -esp210.build.flash_mode=qio -esp210.build.flash_flags=-DFLASHMODE_QIO -esp210.build.flash_freq=40 -esp210.menu.eesz.4M=4M (no SPIFFS) -esp210.menu.eesz.4M.build.flash_size=4M -esp210.menu.eesz.4M.build.flash_size_bytes=0x400000 -esp210.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -esp210.menu.eesz.4M.build.spiffs_pagesize=256 -esp210.menu.eesz.4M.upload.maximum_size=1044464 -esp210.menu.eesz.4M.build.rfcal_addr=0x3FC000 -esp210.menu.eesz.4M1M=4M (1M SPIFFS) -esp210.menu.eesz.4M1M.build.flash_size=4M -esp210.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -esp210.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -esp210.menu.eesz.4M1M.build.spiffs_pagesize=256 -esp210.menu.eesz.4M1M.upload.maximum_size=1044464 -esp210.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -esp210.menu.eesz.4M1M.build.spiffs_start=0x300000 -esp210.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -esp210.menu.eesz.4M1M.build.spiffs_blocksize=8192 -esp210.menu.eesz.4M2M=4M (2M SPIFFS) -esp210.menu.eesz.4M2M.build.flash_size=4M -esp210.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -esp210.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -esp210.menu.eesz.4M2M.build.spiffs_pagesize=256 -esp210.menu.eesz.4M2M.upload.maximum_size=1044464 -esp210.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -esp210.menu.eesz.4M2M.build.spiffs_start=0x200000 -esp210.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -esp210.menu.eesz.4M2M.build.spiffs_blocksize=8192 -esp210.menu.eesz.4M3M=4M (3M SPIFFS) -esp210.menu.eesz.4M3M.build.flash_size=4M -esp210.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -esp210.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -esp210.menu.eesz.4M3M.build.spiffs_pagesize=256 -esp210.menu.eesz.4M3M.upload.maximum_size=1044464 -esp210.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -esp210.menu.eesz.4M3M.build.spiffs_start=0x100000 -esp210.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -esp210.menu.eesz.4M3M.build.spiffs_blocksize=8192 -esp210.menu.ip.lm2f=v2 Lower Memory -esp210.menu.ip.lm2f.build.lwip_include=lwip2/include -esp210.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -esp210.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -esp210.menu.ip.hb2f=v2 Higher Bandwidth -esp210.menu.ip.hb2f.build.lwip_include=lwip2/include -esp210.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -esp210.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -esp210.menu.ip.lm2n=v2 Lower Memory (no features) -esp210.menu.ip.lm2n.build.lwip_include=lwip2/include -esp210.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -esp210.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -esp210.menu.ip.hb2n=v2 Higher Bandwidth (no features) -esp210.menu.ip.hb2n.build.lwip_include=lwip2/include -esp210.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -esp210.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -esp210.menu.ip.lm6f=v2 IPv6 Lower Memory -esp210.menu.ip.lm6f.build.lwip_include=lwip2/include -esp210.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -esp210.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -esp210.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -esp210.menu.ip.hb6f.build.lwip_include=lwip2/include -esp210.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -esp210.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -esp210.menu.ip.hb1=v1.4 Higher Bandwidth -esp210.menu.ip.hb1.build.lwip_lib=-llwip_gcc -esp210.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -esp210.menu.ip.src=v1.4 Compile from source -esp210.menu.ip.src.build.lwip_lib=-llwip_src -esp210.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -esp210.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -esp210.menu.dbg.Disabled=Disabled -esp210.menu.dbg.Disabled.build.debug_port= -esp210.menu.dbg.Serial=Serial -esp210.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -esp210.menu.dbg.Serial1=Serial1 -esp210.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -esp210.menu.lvl.None____=None -esp210.menu.lvl.None____.build.debug_level= -esp210.menu.lvl.SSL=SSL -esp210.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -esp210.menu.lvl.TLS_MEM=TLS_MEM -esp210.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -esp210.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -esp210.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.lvl.HTTP_SERVER=HTTP_SERVER -esp210.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -esp210.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -esp210.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -esp210.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -esp210.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -esp210.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -esp210.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.CORE=CORE -esp210.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -esp210.menu.lvl.WIFI=WIFI -esp210.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -esp210.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -esp210.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -esp210.menu.lvl.UPDATER=UPDATER -esp210.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -esp210.menu.lvl.OTA=OTA -esp210.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -esp210.menu.lvl.OOM=OOM -esp210.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -esp210.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -esp210.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -esp210.menu.wipe.none=Only Sketch -esp210.menu.wipe.none.upload.erase_cmd= -esp210.menu.wipe.sdk=Sketch + WiFi Settings -esp210.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -esp210.menu.wipe.all=All Flash Contents -esp210.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -esp210.menu.baud.57600=57600 -esp210.menu.baud.57600.upload.speed=57600 -esp210.menu.baud.9600=9600 -esp210.menu.baud.9600.upload.speed=9600 -esp210.menu.baud.115200=115200 -esp210.menu.baud.115200.upload.speed=115200 -esp210.menu.baud.230400.linux=230400 -esp210.menu.baud.230400.macosx=230400 -esp210.menu.baud.230400.upload.speed=230400 -esp210.menu.baud.256000.windows=256000 -esp210.menu.baud.256000.upload.speed=256000 -esp210.menu.baud.460800.linux=460800 -esp210.menu.baud.460800.macosx=460800 -esp210.menu.baud.460800.upload.speed=460800 -esp210.menu.baud.512000.windows=512000 -esp210.menu.baud.512000.upload.speed=512000 -esp210.menu.baud.921600=921600 -esp210.menu.baud.921600.upload.speed=921600 - -############################################################## -d1_mini.name=LOLIN(WEMOS) D1 R2 & mini -d1_mini.build.board=ESP8266_WEMOS_D1MINI -d1_mini.build.variant=d1_mini -d1_mini.upload.tool=esptool -d1_mini.upload.maximum_data_size=81920 -d1_mini.upload.wait_for_upload_port=true -d1_mini.upload.erase_cmd= -d1_mini.serial.disableDTR=true -d1_mini.serial.disableRTS=true -d1_mini.build.mcu=esp8266 -d1_mini.build.core=esp8266 -d1_mini.build.spiffs_pagesize=256 -d1_mini.build.debug_port= -d1_mini.build.debug_level= -d1_mini.menu.xtal.80=80 MHz -d1_mini.menu.xtal.80.build.f_cpu=80000000L -d1_mini.menu.xtal.160=160 MHz -d1_mini.menu.xtal.160.build.f_cpu=160000000L -d1_mini.menu.vt.flash=Flash -d1_mini.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1_mini.menu.vt.heap=Heap -d1_mini.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1_mini.menu.vt.iram=IRAM -d1_mini.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1_mini.menu.exception.disabled=Disabled -d1_mini.menu.exception.disabled.build.exception_flags=-fno-exceptions -d1_mini.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -d1_mini.menu.exception.enabled=Enabled -d1_mini.menu.exception.enabled.build.exception_flags=-fexceptions -d1_mini.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -d1_mini.upload.resetmethod=nodemcu -d1_mini.build.flash_mode=dio -d1_mini.build.flash_flags=-DFLASHMODE_DIO -d1_mini.build.flash_freq=40 -d1_mini.menu.eesz.4M=4M (no SPIFFS) -d1_mini.menu.eesz.4M.build.flash_size=4M -d1_mini.menu.eesz.4M.build.flash_size_bytes=0x400000 -d1_mini.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -d1_mini.menu.eesz.4M.build.spiffs_pagesize=256 -d1_mini.menu.eesz.4M.upload.maximum_size=1044464 -d1_mini.menu.eesz.4M.build.rfcal_addr=0x3FC000 -d1_mini.menu.eesz.4M1M=4M (1M SPIFFS) -d1_mini.menu.eesz.4M1M.build.flash_size=4M -d1_mini.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -d1_mini.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1_mini.menu.eesz.4M1M.build.spiffs_pagesize=256 -d1_mini.menu.eesz.4M1M.upload.maximum_size=1044464 -d1_mini.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -d1_mini.menu.eesz.4M1M.build.spiffs_start=0x300000 -d1_mini.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -d1_mini.menu.eesz.4M1M.build.spiffs_blocksize=8192 -d1_mini.menu.eesz.4M2M=4M (2M SPIFFS) -d1_mini.menu.eesz.4M2M.build.flash_size=4M -d1_mini.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -d1_mini.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -d1_mini.menu.eesz.4M2M.build.spiffs_pagesize=256 -d1_mini.menu.eesz.4M2M.upload.maximum_size=1044464 -d1_mini.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -d1_mini.menu.eesz.4M2M.build.spiffs_start=0x200000 -d1_mini.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -d1_mini.menu.eesz.4M2M.build.spiffs_blocksize=8192 -d1_mini.menu.eesz.4M3M=4M (3M SPIFFS) -d1_mini.menu.eesz.4M3M.build.flash_size=4M -d1_mini.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -d1_mini.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -d1_mini.menu.eesz.4M3M.build.spiffs_pagesize=256 -d1_mini.menu.eesz.4M3M.upload.maximum_size=1044464 -d1_mini.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -d1_mini.menu.eesz.4M3M.build.spiffs_start=0x100000 -d1_mini.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -d1_mini.menu.eesz.4M3M.build.spiffs_blocksize=8192 -d1_mini.menu.ip.lm2f=v2 Lower Memory -d1_mini.menu.ip.lm2f.build.lwip_include=lwip2/include -d1_mini.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -d1_mini.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini.menu.ip.hb2f=v2 Higher Bandwidth -d1_mini.menu.ip.hb2f.build.lwip_include=lwip2/include -d1_mini.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -d1_mini.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini.menu.ip.lm2n=v2 Lower Memory (no features) -d1_mini.menu.ip.lm2n.build.lwip_include=lwip2/include -d1_mini.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -d1_mini.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini.menu.ip.hb2n=v2 Higher Bandwidth (no features) -d1_mini.menu.ip.hb2n.build.lwip_include=lwip2/include -d1_mini.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -d1_mini.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini.menu.ip.lm6f=v2 IPv6 Lower Memory -d1_mini.menu.ip.lm6f.build.lwip_include=lwip2/include -d1_mini.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -d1_mini.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -d1_mini.menu.ip.hb6f.build.lwip_include=lwip2/include -d1_mini.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -d1_mini.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini.menu.ip.hb1=v1.4 Higher Bandwidth -d1_mini.menu.ip.hb1.build.lwip_lib=-llwip_gcc -d1_mini.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini.menu.ip.src=v1.4 Compile from source -d1_mini.menu.ip.src.build.lwip_lib=-llwip_src -d1_mini.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini.menu.dbg.Disabled=Disabled -d1_mini.menu.dbg.Disabled.build.debug_port= -d1_mini.menu.dbg.Serial=Serial -d1_mini.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini.menu.dbg.Serial1=Serial1 -d1_mini.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini.menu.lvl.None____=None -d1_mini.menu.lvl.None____.build.debug_level= -d1_mini.menu.lvl.SSL=SSL -d1_mini.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini.menu.lvl.TLS_MEM=TLS_MEM -d1_mini.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -d1_mini.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.lvl.HTTP_SERVER=HTTP_SERVER -d1_mini.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -d1_mini.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.CORE=CORE -d1_mini.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini.menu.lvl.WIFI=WIFI -d1_mini.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -d1_mini.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini.menu.lvl.UPDATER=UPDATER -d1_mini.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini.menu.lvl.OTA=OTA -d1_mini.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini.menu.lvl.OOM=OOM -d1_mini.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini.menu.wipe.none=Only Sketch -d1_mini.menu.wipe.none.upload.erase_cmd= -d1_mini.menu.wipe.sdk=Sketch + WiFi Settings -d1_mini.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1_mini.menu.wipe.all=All Flash Contents -d1_mini.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1_mini.menu.baud.921600=921600 -d1_mini.menu.baud.921600.upload.speed=921600 -d1_mini.menu.baud.9600=9600 -d1_mini.menu.baud.9600.upload.speed=9600 -d1_mini.menu.baud.57600=57600 -d1_mini.menu.baud.57600.upload.speed=57600 -d1_mini.menu.baud.115200=115200 -d1_mini.menu.baud.115200.upload.speed=115200 -d1_mini.menu.baud.230400.linux=230400 -d1_mini.menu.baud.230400.macosx=230400 -d1_mini.menu.baud.230400.upload.speed=230400 -d1_mini.menu.baud.256000.windows=256000 -d1_mini.menu.baud.256000.upload.speed=256000 -d1_mini.menu.baud.460800.linux=460800 -d1_mini.menu.baud.460800.macosx=460800 -d1_mini.menu.baud.460800.upload.speed=460800 -d1_mini.menu.baud.512000.windows=512000 -d1_mini.menu.baud.512000.upload.speed=512000 - -############################################################## -d1_mini_pro.name=LOLIN(WEMOS) D1 mini Pro -d1_mini_pro.build.board=ESP8266_WEMOS_D1MINIPRO -d1_mini_pro.build.variant=d1_mini -d1_mini_pro.upload.tool=esptool -d1_mini_pro.upload.maximum_data_size=81920 -d1_mini_pro.upload.wait_for_upload_port=true -d1_mini_pro.upload.erase_cmd= -d1_mini_pro.serial.disableDTR=true -d1_mini_pro.serial.disableRTS=true -d1_mini_pro.build.mcu=esp8266 -d1_mini_pro.build.core=esp8266 -d1_mini_pro.build.spiffs_pagesize=256 -d1_mini_pro.build.debug_port= -d1_mini_pro.build.debug_level= -d1_mini_pro.menu.xtal.80=80 MHz -d1_mini_pro.menu.xtal.80.build.f_cpu=80000000L -d1_mini_pro.menu.xtal.160=160 MHz -d1_mini_pro.menu.xtal.160.build.f_cpu=160000000L -d1_mini_pro.menu.vt.flash=Flash -d1_mini_pro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1_mini_pro.menu.vt.heap=Heap -d1_mini_pro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1_mini_pro.menu.vt.iram=IRAM -d1_mini_pro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1_mini_pro.menu.exception.disabled=Disabled -d1_mini_pro.menu.exception.disabled.build.exception_flags=-fno-exceptions -d1_mini_pro.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -d1_mini_pro.menu.exception.enabled=Enabled -d1_mini_pro.menu.exception.enabled.build.exception_flags=-fexceptions -d1_mini_pro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -d1_mini_pro.upload.resetmethod=nodemcu -d1_mini_pro.build.flash_mode=dio -d1_mini_pro.build.flash_flags=-DFLASHMODE_DIO -d1_mini_pro.build.flash_freq=40 -d1_mini_pro.menu.eesz.16M14M=16M (14M SPIFFS) -d1_mini_pro.menu.eesz.16M14M.build.flash_size=16M -d1_mini_pro.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 -d1_mini_pro.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld -d1_mini_pro.menu.eesz.16M14M.build.spiffs_pagesize=256 -d1_mini_pro.menu.eesz.16M14M.upload.maximum_size=1044464 -d1_mini_pro.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 -d1_mini_pro.menu.eesz.16M14M.build.spiffs_start=0x200000 -d1_mini_pro.menu.eesz.16M14M.build.spiffs_end=0xFFB000 -d1_mini_pro.menu.eesz.16M14M.build.spiffs_blocksize=8192 -d1_mini_pro.menu.eesz.16M15M=16M (15M SPIFFS) -d1_mini_pro.menu.eesz.16M15M.build.flash_size=16M -d1_mini_pro.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 -d1_mini_pro.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld -d1_mini_pro.menu.eesz.16M15M.build.spiffs_pagesize=256 -d1_mini_pro.menu.eesz.16M15M.upload.maximum_size=1044464 -d1_mini_pro.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 -d1_mini_pro.menu.eesz.16M15M.build.spiffs_start=0x100000 -d1_mini_pro.menu.eesz.16M15M.build.spiffs_end=0xFFB000 -d1_mini_pro.menu.eesz.16M15M.build.spiffs_blocksize=8192 -d1_mini_pro.menu.ip.lm2f=v2 Lower Memory -d1_mini_pro.menu.ip.lm2f.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -d1_mini_pro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini_pro.menu.ip.hb2f=v2 Higher Bandwidth -d1_mini_pro.menu.ip.hb2f.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -d1_mini_pro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini_pro.menu.ip.lm2n=v2 Lower Memory (no features) -d1_mini_pro.menu.ip.lm2n.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -d1_mini_pro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini_pro.menu.ip.hb2n=v2 Higher Bandwidth (no features) -d1_mini_pro.menu.ip.hb2n.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -d1_mini_pro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini_pro.menu.ip.lm6f=v2 IPv6 Lower Memory -d1_mini_pro.menu.ip.lm6f.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -d1_mini_pro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini_pro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -d1_mini_pro.menu.ip.hb6f.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -d1_mini_pro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini_pro.menu.ip.hb1=v1.4 Higher Bandwidth -d1_mini_pro.menu.ip.hb1.build.lwip_lib=-llwip_gcc -d1_mini_pro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_pro.menu.ip.src=v1.4 Compile from source -d1_mini_pro.menu.ip.src.build.lwip_lib=-llwip_src -d1_mini_pro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_pro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini_pro.menu.dbg.Disabled=Disabled -d1_mini_pro.menu.dbg.Disabled.build.debug_port= -d1_mini_pro.menu.dbg.Serial=Serial -d1_mini_pro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini_pro.menu.dbg.Serial1=Serial1 -d1_mini_pro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini_pro.menu.lvl.None____=None -d1_mini_pro.menu.lvl.None____.build.debug_level= -d1_mini_pro.menu.lvl.SSL=SSL -d1_mini_pro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini_pro.menu.lvl.TLS_MEM=TLS_MEM -d1_mini_pro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini_pro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -d1_mini_pro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.lvl.HTTP_SERVER=HTTP_SERVER -d1_mini_pro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -d1_mini_pro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini_pro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini_pro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini_pro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.CORE=CORE -d1_mini_pro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini_pro.menu.lvl.WIFI=WIFI -d1_mini_pro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini_pro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -d1_mini_pro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini_pro.menu.lvl.UPDATER=UPDATER -d1_mini_pro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini_pro.menu.lvl.OTA=OTA -d1_mini_pro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini_pro.menu.lvl.OOM=OOM -d1_mini_pro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini_pro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini_pro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini_pro.menu.wipe.none=Only Sketch -d1_mini_pro.menu.wipe.none.upload.erase_cmd= -d1_mini_pro.menu.wipe.sdk=Sketch + WiFi Settings -d1_mini_pro.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1_mini_pro.menu.wipe.all=All Flash Contents -d1_mini_pro.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1_mini_pro.menu.baud.921600=921600 -d1_mini_pro.menu.baud.921600.upload.speed=921600 -d1_mini_pro.menu.baud.9600=9600 -d1_mini_pro.menu.baud.9600.upload.speed=9600 -d1_mini_pro.menu.baud.57600=57600 -d1_mini_pro.menu.baud.57600.upload.speed=57600 -d1_mini_pro.menu.baud.115200=115200 -d1_mini_pro.menu.baud.115200.upload.speed=115200 -d1_mini_pro.menu.baud.230400.linux=230400 -d1_mini_pro.menu.baud.230400.macosx=230400 -d1_mini_pro.menu.baud.230400.upload.speed=230400 -d1_mini_pro.menu.baud.256000.windows=256000 -d1_mini_pro.menu.baud.256000.upload.speed=256000 -d1_mini_pro.menu.baud.460800.linux=460800 -d1_mini_pro.menu.baud.460800.macosx=460800 -d1_mini_pro.menu.baud.460800.upload.speed=460800 -d1_mini_pro.menu.baud.512000.windows=512000 -d1_mini_pro.menu.baud.512000.upload.speed=512000 - -############################################################## -d1_mini_lite.name=LOLIN(WEMOS) D1 mini Lite -d1_mini_lite.build.board=ESP8266_WEMOS_D1MINILITE -d1_mini_lite.build.variant=d1_mini -d1_mini_lite.upload.tool=esptool -d1_mini_lite.upload.maximum_data_size=81920 -d1_mini_lite.upload.wait_for_upload_port=true -d1_mini_lite.upload.erase_cmd= -d1_mini_lite.serial.disableDTR=true -d1_mini_lite.serial.disableRTS=true -d1_mini_lite.build.mcu=esp8266 -d1_mini_lite.build.core=esp8266 -d1_mini_lite.build.spiffs_pagesize=256 -d1_mini_lite.build.debug_port= -d1_mini_lite.build.debug_level= -d1_mini_lite.menu.xtal.80=80 MHz -d1_mini_lite.menu.xtal.80.build.f_cpu=80000000L -d1_mini_lite.menu.xtal.160=160 MHz -d1_mini_lite.menu.xtal.160.build.f_cpu=160000000L -d1_mini_lite.menu.vt.flash=Flash -d1_mini_lite.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1_mini_lite.menu.vt.heap=Heap -d1_mini_lite.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1_mini_lite.menu.vt.iram=IRAM -d1_mini_lite.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1_mini_lite.menu.exception.disabled=Disabled -d1_mini_lite.menu.exception.disabled.build.exception_flags=-fno-exceptions -d1_mini_lite.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -d1_mini_lite.menu.exception.enabled=Enabled -d1_mini_lite.menu.exception.enabled.build.exception_flags=-fexceptions -d1_mini_lite.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -d1_mini_lite.upload.resetmethod=nodemcu -d1_mini_lite.build.flash_mode=dout -d1_mini_lite.build.flash_flags=-DFLASHMODE_DOUT -d1_mini_lite.build.flash_freq=40 -d1_mini_lite.menu.eesz.1M=1M (no SPIFFS) -d1_mini_lite.menu.eesz.1M.build.flash_size=1M -d1_mini_lite.menu.eesz.1M.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -d1_mini_lite.menu.eesz.1M.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M.upload.maximum_size=1023984 -d1_mini_lite.menu.eesz.1M.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M64=1M (64K SPIFFS) -d1_mini_lite.menu.eesz.1M64.build.flash_size=1M -d1_mini_lite.menu.eesz.1M64.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -d1_mini_lite.menu.eesz.1M64.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M64.upload.maximum_size=958448 -d1_mini_lite.menu.eesz.1M64.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M64.build.spiffs_start=0xEB000 -d1_mini_lite.menu.eesz.1M64.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M64.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M128=1M (128K SPIFFS) -d1_mini_lite.menu.eesz.1M128.build.flash_size=1M -d1_mini_lite.menu.eesz.1M128.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -d1_mini_lite.menu.eesz.1M128.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M128.upload.maximum_size=892912 -d1_mini_lite.menu.eesz.1M128.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M128.build.spiffs_start=0xDB000 -d1_mini_lite.menu.eesz.1M128.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M128.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M144=1M (144K SPIFFS) -d1_mini_lite.menu.eesz.1M144.build.flash_size=1M -d1_mini_lite.menu.eesz.1M144.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -d1_mini_lite.menu.eesz.1M144.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M144.upload.maximum_size=876528 -d1_mini_lite.menu.eesz.1M144.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M144.build.spiffs_start=0xD7000 -d1_mini_lite.menu.eesz.1M144.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M144.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M160=1M (160K SPIFFS) -d1_mini_lite.menu.eesz.1M160.build.flash_size=1M -d1_mini_lite.menu.eesz.1M160.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -d1_mini_lite.menu.eesz.1M160.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M160.upload.maximum_size=860144 -d1_mini_lite.menu.eesz.1M160.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M160.build.spiffs_start=0xD3000 -d1_mini_lite.menu.eesz.1M160.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M160.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M192=1M (192K SPIFFS) -d1_mini_lite.menu.eesz.1M192.build.flash_size=1M -d1_mini_lite.menu.eesz.1M192.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -d1_mini_lite.menu.eesz.1M192.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M192.upload.maximum_size=827376 -d1_mini_lite.menu.eesz.1M192.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M192.build.spiffs_start=0xCB000 -d1_mini_lite.menu.eesz.1M192.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M192.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M256=1M (256K SPIFFS) -d1_mini_lite.menu.eesz.1M256.build.flash_size=1M -d1_mini_lite.menu.eesz.1M256.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -d1_mini_lite.menu.eesz.1M256.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M256.upload.maximum_size=761840 -d1_mini_lite.menu.eesz.1M256.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M256.build.spiffs_start=0xBB000 -d1_mini_lite.menu.eesz.1M256.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M256.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M512=1M (512K SPIFFS) -d1_mini_lite.menu.eesz.1M512.build.flash_size=1M -d1_mini_lite.menu.eesz.1M512.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -d1_mini_lite.menu.eesz.1M512.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M512.upload.maximum_size=499696 -d1_mini_lite.menu.eesz.1M512.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M512.build.spiffs_start=0x7B000 -d1_mini_lite.menu.eesz.1M512.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M512.build.spiffs_blocksize=4096 -d1_mini_lite.menu.ip.lm2f=v2 Lower Memory -d1_mini_lite.menu.ip.lm2f.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -d1_mini_lite.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini_lite.menu.ip.hb2f=v2 Higher Bandwidth -d1_mini_lite.menu.ip.hb2f.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -d1_mini_lite.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini_lite.menu.ip.lm2n=v2 Lower Memory (no features) -d1_mini_lite.menu.ip.lm2n.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -d1_mini_lite.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini_lite.menu.ip.hb2n=v2 Higher Bandwidth (no features) -d1_mini_lite.menu.ip.hb2n.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -d1_mini_lite.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini_lite.menu.ip.lm6f=v2 IPv6 Lower Memory -d1_mini_lite.menu.ip.lm6f.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -d1_mini_lite.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini_lite.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -d1_mini_lite.menu.ip.hb6f.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -d1_mini_lite.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini_lite.menu.ip.hb1=v1.4 Higher Bandwidth -d1_mini_lite.menu.ip.hb1.build.lwip_lib=-llwip_gcc -d1_mini_lite.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_lite.menu.ip.src=v1.4 Compile from source -d1_mini_lite.menu.ip.src.build.lwip_lib=-llwip_src -d1_mini_lite.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_lite.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini_lite.menu.dbg.Disabled=Disabled -d1_mini_lite.menu.dbg.Disabled.build.debug_port= -d1_mini_lite.menu.dbg.Serial=Serial -d1_mini_lite.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini_lite.menu.dbg.Serial1=Serial1 -d1_mini_lite.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini_lite.menu.lvl.None____=None -d1_mini_lite.menu.lvl.None____.build.debug_level= -d1_mini_lite.menu.lvl.SSL=SSL -d1_mini_lite.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini_lite.menu.lvl.TLS_MEM=TLS_MEM -d1_mini_lite.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini_lite.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -d1_mini_lite.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.lvl.HTTP_SERVER=HTTP_SERVER -d1_mini_lite.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -d1_mini_lite.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini_lite.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini_lite.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini_lite.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.CORE=CORE -d1_mini_lite.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini_lite.menu.lvl.WIFI=WIFI -d1_mini_lite.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini_lite.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -d1_mini_lite.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini_lite.menu.lvl.UPDATER=UPDATER -d1_mini_lite.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini_lite.menu.lvl.OTA=OTA -d1_mini_lite.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini_lite.menu.lvl.OOM=OOM -d1_mini_lite.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini_lite.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini_lite.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini_lite.menu.wipe.none=Only Sketch -d1_mini_lite.menu.wipe.none.upload.erase_cmd= -d1_mini_lite.menu.wipe.sdk=Sketch + WiFi Settings -d1_mini_lite.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1_mini_lite.menu.wipe.all=All Flash Contents -d1_mini_lite.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1_mini_lite.menu.baud.921600=921600 -d1_mini_lite.menu.baud.921600.upload.speed=921600 -d1_mini_lite.menu.baud.9600=9600 -d1_mini_lite.menu.baud.9600.upload.speed=9600 -d1_mini_lite.menu.baud.57600=57600 -d1_mini_lite.menu.baud.57600.upload.speed=57600 -d1_mini_lite.menu.baud.115200=115200 -d1_mini_lite.menu.baud.115200.upload.speed=115200 -d1_mini_lite.menu.baud.230400.linux=230400 -d1_mini_lite.menu.baud.230400.macosx=230400 -d1_mini_lite.menu.baud.230400.upload.speed=230400 -d1_mini_lite.menu.baud.256000.windows=256000 -d1_mini_lite.menu.baud.256000.upload.speed=256000 -d1_mini_lite.menu.baud.460800.linux=460800 -d1_mini_lite.menu.baud.460800.macosx=460800 -d1_mini_lite.menu.baud.460800.upload.speed=460800 -d1_mini_lite.menu.baud.512000.windows=512000 -d1_mini_lite.menu.baud.512000.upload.speed=512000 - -############################################################## -d1.name=WeMos D1 R1 -d1.build.board=ESP8266_WEMOS_D1R1 -d1.build.variant=d1 -d1.upload.tool=esptool -d1.upload.maximum_data_size=81920 -d1.upload.wait_for_upload_port=true -d1.upload.erase_cmd= -d1.serial.disableDTR=true -d1.serial.disableRTS=true -d1.build.mcu=esp8266 -d1.build.core=esp8266 -d1.build.spiffs_pagesize=256 -d1.build.debug_port= -d1.build.debug_level= -d1.menu.xtal.80=80 MHz -d1.menu.xtal.80.build.f_cpu=80000000L -d1.menu.xtal.160=160 MHz -d1.menu.xtal.160.build.f_cpu=160000000L -d1.menu.vt.flash=Flash -d1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1.menu.vt.heap=Heap -d1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1.menu.vt.iram=IRAM -d1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1.menu.exception.disabled=Disabled -d1.menu.exception.disabled.build.exception_flags=-fno-exceptions -d1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -d1.menu.exception.enabled=Enabled -d1.menu.exception.enabled.build.exception_flags=-fexceptions -d1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -d1.upload.resetmethod=nodemcu -d1.build.flash_mode=dio -d1.build.flash_flags=-DFLASHMODE_DIO -d1.build.flash_freq=40 -d1.menu.eesz.4M=4M (no SPIFFS) -d1.menu.eesz.4M.build.flash_size=4M -d1.menu.eesz.4M.build.flash_size_bytes=0x400000 -d1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -d1.menu.eesz.4M.build.spiffs_pagesize=256 -d1.menu.eesz.4M.upload.maximum_size=1044464 -d1.menu.eesz.4M.build.rfcal_addr=0x3FC000 -d1.menu.eesz.4M1M=4M (1M SPIFFS) -d1.menu.eesz.4M1M.build.flash_size=4M -d1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -d1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1.menu.eesz.4M1M.build.spiffs_pagesize=256 -d1.menu.eesz.4M1M.upload.maximum_size=1044464 -d1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -d1.menu.eesz.4M1M.build.spiffs_start=0x300000 -d1.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -d1.menu.eesz.4M1M.build.spiffs_blocksize=8192 -d1.menu.eesz.4M2M=4M (2M SPIFFS) -d1.menu.eesz.4M2M.build.flash_size=4M -d1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -d1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -d1.menu.eesz.4M2M.build.spiffs_pagesize=256 -d1.menu.eesz.4M2M.upload.maximum_size=1044464 -d1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -d1.menu.eesz.4M2M.build.spiffs_start=0x200000 -d1.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -d1.menu.eesz.4M2M.build.spiffs_blocksize=8192 -d1.menu.eesz.4M3M=4M (3M SPIFFS) -d1.menu.eesz.4M3M.build.flash_size=4M -d1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -d1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -d1.menu.eesz.4M3M.build.spiffs_pagesize=256 -d1.menu.eesz.4M3M.upload.maximum_size=1044464 -d1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -d1.menu.eesz.4M3M.build.spiffs_start=0x100000 -d1.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -d1.menu.eesz.4M3M.build.spiffs_blocksize=8192 -d1.menu.ip.lm2f=v2 Lower Memory -d1.menu.ip.lm2f.build.lwip_include=lwip2/include -d1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -d1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1.menu.ip.hb2f=v2 Higher Bandwidth -d1.menu.ip.hb2f.build.lwip_include=lwip2/include -d1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -d1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1.menu.ip.lm2n=v2 Lower Memory (no features) -d1.menu.ip.lm2n.build.lwip_include=lwip2/include -d1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -d1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1.menu.ip.hb2n=v2 Higher Bandwidth (no features) -d1.menu.ip.hb2n.build.lwip_include=lwip2/include -d1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -d1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1.menu.ip.lm6f=v2 IPv6 Lower Memory -d1.menu.ip.lm6f.build.lwip_include=lwip2/include -d1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -d1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -d1.menu.ip.hb6f.build.lwip_include=lwip2/include -d1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -d1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1.menu.ip.hb1=v1.4 Higher Bandwidth -d1.menu.ip.hb1.build.lwip_lib=-llwip_gcc -d1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -d1.menu.ip.src=v1.4 Compile from source -d1.menu.ip.src.build.lwip_lib=-llwip_src -d1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -d1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1.menu.dbg.Disabled=Disabled -d1.menu.dbg.Disabled.build.debug_port= -d1.menu.dbg.Serial=Serial -d1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1.menu.dbg.Serial1=Serial1 -d1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1.menu.lvl.None____=None -d1.menu.lvl.None____.build.debug_level= -d1.menu.lvl.SSL=SSL -d1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1.menu.lvl.TLS_MEM=TLS_MEM -d1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -d1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1.menu.lvl.HTTP_SERVER=HTTP_SERVER -d1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -d1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.CORE=CORE -d1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1.menu.lvl.WIFI=WIFI -d1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -d1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1.menu.lvl.UPDATER=UPDATER -d1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1.menu.lvl.OTA=OTA -d1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1.menu.lvl.OOM=OOM -d1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -d1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1.menu.wipe.none=Only Sketch -d1.menu.wipe.none.upload.erase_cmd= -d1.menu.wipe.sdk=Sketch + WiFi Settings -d1.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1.menu.wipe.all=All Flash Contents -d1.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1.menu.baud.921600=921600 -d1.menu.baud.921600.upload.speed=921600 -d1.menu.baud.9600=9600 -d1.menu.baud.9600.upload.speed=9600 -d1.menu.baud.57600=57600 -d1.menu.baud.57600.upload.speed=57600 -d1.menu.baud.115200=115200 -d1.menu.baud.115200.upload.speed=115200 -d1.menu.baud.230400.linux=230400 -d1.menu.baud.230400.macosx=230400 -d1.menu.baud.230400.upload.speed=230400 -d1.menu.baud.256000.windows=256000 -d1.menu.baud.256000.upload.speed=256000 -d1.menu.baud.460800.linux=460800 -d1.menu.baud.460800.macosx=460800 -d1.menu.baud.460800.upload.speed=460800 -d1.menu.baud.512000.windows=512000 -d1.menu.baud.512000.upload.speed=512000 - -############################################################## -espino.name=ESPino (ESP-12 Module) -espino.build.board=ESP8266_ESP12 -espino.build.variant=espino -espino.upload.tool=esptool -espino.upload.maximum_data_size=81920 -espino.upload.wait_for_upload_port=true -espino.upload.erase_cmd= -espino.serial.disableDTR=true -espino.serial.disableRTS=true -espino.build.mcu=esp8266 -espino.build.core=esp8266 -espino.build.spiffs_pagesize=256 -espino.build.debug_port= -espino.build.debug_level= -espino.menu.xtal.80=80 MHz -espino.menu.xtal.80.build.f_cpu=80000000L -espino.menu.xtal.160=160 MHz -espino.menu.xtal.160.build.f_cpu=160000000L -espino.menu.vt.flash=Flash -espino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espino.menu.vt.heap=Heap -espino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espino.menu.vt.iram=IRAM -espino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espino.menu.exception.disabled=Disabled -espino.menu.exception.disabled.build.exception_flags=-fno-exceptions -espino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espino.menu.exception.enabled=Enabled -espino.menu.exception.enabled.build.exception_flags=-fexceptions -espino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espino.menu.ResetMethod.ck=ck -espino.menu.ResetMethod.ck.upload.resetmethod=ck -espino.menu.ResetMethod.nodemcu=nodemcu -espino.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espino.build.flash_mode=qio -espino.build.flash_flags=-DFLASHMODE_QIO -espino.build.flash_freq=40 -espino.menu.eesz.4M=4M (no SPIFFS) -espino.menu.eesz.4M.build.flash_size=4M -espino.menu.eesz.4M.build.flash_size_bytes=0x400000 -espino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espino.menu.eesz.4M.build.spiffs_pagesize=256 -espino.menu.eesz.4M.upload.maximum_size=1044464 -espino.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espino.menu.eesz.4M1M=4M (1M SPIFFS) -espino.menu.eesz.4M1M.build.flash_size=4M -espino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espino.menu.eesz.4M1M.build.spiffs_pagesize=256 -espino.menu.eesz.4M1M.upload.maximum_size=1044464 -espino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espino.menu.eesz.4M1M.build.spiffs_start=0x300000 -espino.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -espino.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espino.menu.eesz.4M2M=4M (2M SPIFFS) -espino.menu.eesz.4M2M.build.flash_size=4M -espino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espino.menu.eesz.4M2M.build.spiffs_pagesize=256 -espino.menu.eesz.4M2M.upload.maximum_size=1044464 -espino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espino.menu.eesz.4M2M.build.spiffs_start=0x200000 -espino.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -espino.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espino.menu.eesz.4M3M=4M (3M SPIFFS) -espino.menu.eesz.4M3M.build.flash_size=4M -espino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espino.menu.eesz.4M3M.build.spiffs_pagesize=256 -espino.menu.eesz.4M3M.upload.maximum_size=1044464 -espino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espino.menu.eesz.4M3M.build.spiffs_start=0x100000 -espino.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -espino.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espino.menu.ip.lm2f=v2 Lower Memory -espino.menu.ip.lm2f.build.lwip_include=lwip2/include -espino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espino.menu.ip.hb2f=v2 Higher Bandwidth -espino.menu.ip.hb2f.build.lwip_include=lwip2/include -espino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espino.menu.ip.lm2n=v2 Lower Memory (no features) -espino.menu.ip.lm2n.build.lwip_include=lwip2/include -espino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espino.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espino.menu.ip.hb2n.build.lwip_include=lwip2/include -espino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espino.menu.ip.lm6f=v2 IPv6 Lower Memory -espino.menu.ip.lm6f.build.lwip_include=lwip2/include -espino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espino.menu.ip.hb6f.build.lwip_include=lwip2/include -espino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espino.menu.ip.hb1=v1.4 Higher Bandwidth -espino.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espino.menu.ip.src=v1.4 Compile from source -espino.menu.ip.src.build.lwip_lib=-llwip_src -espino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espino.menu.dbg.Disabled=Disabled -espino.menu.dbg.Disabled.build.debug_port= -espino.menu.dbg.Serial=Serial -espino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espino.menu.dbg.Serial1=Serial1 -espino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espino.menu.lvl.None____=None -espino.menu.lvl.None____.build.debug_level= -espino.menu.lvl.SSL=SSL -espino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espino.menu.lvl.TLS_MEM=TLS_MEM -espino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espino.menu.lvl.HTTP_SERVER=HTTP_SERVER -espino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.CORE=CORE -espino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espino.menu.lvl.WIFI=WIFI -espino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espino.menu.lvl.UPDATER=UPDATER -espino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espino.menu.lvl.OTA=OTA -espino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espino.menu.lvl.OOM=OOM -espino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espino.menu.wipe.none=Only Sketch -espino.menu.wipe.none.upload.erase_cmd= -espino.menu.wipe.sdk=Sketch + WiFi Settings -espino.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espino.menu.wipe.all=All Flash Contents -espino.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espino.menu.baud.115200=115200 -espino.menu.baud.115200.upload.speed=115200 -espino.menu.baud.9600=9600 -espino.menu.baud.9600.upload.speed=9600 -espino.menu.baud.57600=57600 -espino.menu.baud.57600.upload.speed=57600 -espino.menu.baud.230400.linux=230400 -espino.menu.baud.230400.macosx=230400 -espino.menu.baud.230400.upload.speed=230400 -espino.menu.baud.256000.windows=256000 -espino.menu.baud.256000.upload.speed=256000 -espino.menu.baud.460800.linux=460800 -espino.menu.baud.460800.macosx=460800 -espino.menu.baud.460800.upload.speed=460800 -espino.menu.baud.512000.windows=512000 -espino.menu.baud.512000.upload.speed=512000 -espino.menu.baud.921600=921600 -espino.menu.baud.921600.upload.speed=921600 - -############################################################## -espinotee.name=ThaiEasyElec's ESPino -espinotee.build.board=ESP8266_ESP13 -espinotee.build.variant=espinotee -espinotee.upload.tool=esptool -espinotee.upload.maximum_data_size=81920 -espinotee.upload.wait_for_upload_port=true -espinotee.upload.erase_cmd= -espinotee.serial.disableDTR=true -espinotee.serial.disableRTS=true -espinotee.build.mcu=esp8266 -espinotee.build.core=esp8266 -espinotee.build.spiffs_pagesize=256 -espinotee.build.debug_port= -espinotee.build.debug_level= -espinotee.menu.xtal.80=80 MHz -espinotee.menu.xtal.80.build.f_cpu=80000000L -espinotee.menu.xtal.160=160 MHz -espinotee.menu.xtal.160.build.f_cpu=160000000L -espinotee.menu.vt.flash=Flash -espinotee.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espinotee.menu.vt.heap=Heap -espinotee.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espinotee.menu.vt.iram=IRAM -espinotee.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espinotee.menu.exception.disabled=Disabled -espinotee.menu.exception.disabled.build.exception_flags=-fno-exceptions -espinotee.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espinotee.menu.exception.enabled=Enabled -espinotee.menu.exception.enabled.build.exception_flags=-fexceptions -espinotee.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espinotee.upload.resetmethod=nodemcu -espinotee.build.flash_mode=qio -espinotee.build.flash_flags=-DFLASHMODE_QIO -espinotee.build.flash_freq=40 -espinotee.menu.eesz.4M=4M (no SPIFFS) -espinotee.menu.eesz.4M.build.flash_size=4M -espinotee.menu.eesz.4M.build.flash_size_bytes=0x400000 -espinotee.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espinotee.menu.eesz.4M.build.spiffs_pagesize=256 -espinotee.menu.eesz.4M.upload.maximum_size=1044464 -espinotee.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espinotee.menu.eesz.4M1M=4M (1M SPIFFS) -espinotee.menu.eesz.4M1M.build.flash_size=4M -espinotee.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espinotee.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espinotee.menu.eesz.4M1M.build.spiffs_pagesize=256 -espinotee.menu.eesz.4M1M.upload.maximum_size=1044464 -espinotee.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espinotee.menu.eesz.4M1M.build.spiffs_start=0x300000 -espinotee.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -espinotee.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espinotee.menu.eesz.4M2M=4M (2M SPIFFS) -espinotee.menu.eesz.4M2M.build.flash_size=4M -espinotee.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espinotee.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espinotee.menu.eesz.4M2M.build.spiffs_pagesize=256 -espinotee.menu.eesz.4M2M.upload.maximum_size=1044464 -espinotee.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espinotee.menu.eesz.4M2M.build.spiffs_start=0x200000 -espinotee.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -espinotee.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espinotee.menu.eesz.4M3M=4M (3M SPIFFS) -espinotee.menu.eesz.4M3M.build.flash_size=4M -espinotee.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espinotee.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espinotee.menu.eesz.4M3M.build.spiffs_pagesize=256 -espinotee.menu.eesz.4M3M.upload.maximum_size=1044464 -espinotee.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espinotee.menu.eesz.4M3M.build.spiffs_start=0x100000 -espinotee.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -espinotee.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espinotee.menu.ip.lm2f=v2 Lower Memory -espinotee.menu.ip.lm2f.build.lwip_include=lwip2/include -espinotee.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espinotee.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espinotee.menu.ip.hb2f=v2 Higher Bandwidth -espinotee.menu.ip.hb2f.build.lwip_include=lwip2/include -espinotee.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espinotee.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espinotee.menu.ip.lm2n=v2 Lower Memory (no features) -espinotee.menu.ip.lm2n.build.lwip_include=lwip2/include -espinotee.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espinotee.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espinotee.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espinotee.menu.ip.hb2n.build.lwip_include=lwip2/include -espinotee.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espinotee.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espinotee.menu.ip.lm6f=v2 IPv6 Lower Memory -espinotee.menu.ip.lm6f.build.lwip_include=lwip2/include -espinotee.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espinotee.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espinotee.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espinotee.menu.ip.hb6f.build.lwip_include=lwip2/include -espinotee.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espinotee.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espinotee.menu.ip.hb1=v1.4 Higher Bandwidth -espinotee.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espinotee.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espinotee.menu.ip.src=v1.4 Compile from source -espinotee.menu.ip.src.build.lwip_lib=-llwip_src -espinotee.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espinotee.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espinotee.menu.dbg.Disabled=Disabled -espinotee.menu.dbg.Disabled.build.debug_port= -espinotee.menu.dbg.Serial=Serial -espinotee.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espinotee.menu.dbg.Serial1=Serial1 -espinotee.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espinotee.menu.lvl.None____=None -espinotee.menu.lvl.None____.build.debug_level= -espinotee.menu.lvl.SSL=SSL -espinotee.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espinotee.menu.lvl.TLS_MEM=TLS_MEM -espinotee.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espinotee.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espinotee.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.lvl.HTTP_SERVER=HTTP_SERVER -espinotee.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espinotee.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espinotee.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espinotee.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espinotee.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espinotee.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espinotee.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.CORE=CORE -espinotee.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espinotee.menu.lvl.WIFI=WIFI -espinotee.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espinotee.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espinotee.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espinotee.menu.lvl.UPDATER=UPDATER -espinotee.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espinotee.menu.lvl.OTA=OTA -espinotee.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espinotee.menu.lvl.OOM=OOM -espinotee.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espinotee.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espinotee.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espinotee.menu.wipe.none=Only Sketch -espinotee.menu.wipe.none.upload.erase_cmd= -espinotee.menu.wipe.sdk=Sketch + WiFi Settings -espinotee.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espinotee.menu.wipe.all=All Flash Contents -espinotee.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espinotee.menu.baud.115200=115200 -espinotee.menu.baud.115200.upload.speed=115200 -espinotee.menu.baud.9600=9600 -espinotee.menu.baud.9600.upload.speed=9600 -espinotee.menu.baud.57600=57600 -espinotee.menu.baud.57600.upload.speed=57600 -espinotee.menu.baud.230400.linux=230400 -espinotee.menu.baud.230400.macosx=230400 -espinotee.menu.baud.230400.upload.speed=230400 -espinotee.menu.baud.256000.windows=256000 -espinotee.menu.baud.256000.upload.speed=256000 -espinotee.menu.baud.460800.linux=460800 -espinotee.menu.baud.460800.macosx=460800 -espinotee.menu.baud.460800.upload.speed=460800 -espinotee.menu.baud.512000.windows=512000 -espinotee.menu.baud.512000.upload.speed=512000 -espinotee.menu.baud.921600=921600 -espinotee.menu.baud.921600.upload.speed=921600 - -############################################################## -wifinfo.name=WifInfo -wifinfo.menu.ESPModule.ESP12.build.board=ESP8266_ESP12 -wifinfo.menu.ESPModule.ESP12.upload.maximum_size=1044464 -wifinfo.menu.ESPModule.ESP12.build.spiffs_pagesize=256 -wifinfo.menu.ESPModule.ESP12.build.flash_ld=eagle.flash.4m1m.ld -wifinfo.menu.ESPModule.ESP07192.build.spiffs_blocksize=4096 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_end=0xFB000 -wifinfo.menu.ESPModule.ESP12=ESP12 (4M/1M SPIFFS) -wifinfo.menu.ESPModule.ESP12.build.spiffs_start=0x300000 -wifinfo.menu.ESPModule.ESP12.build.spiffs_end=0x3FB000 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_start=0xCB000 -wifinfo.menu.ESPModule.ESP07192.build.board=ESP8266_ESP07 -wifinfo.menu.ESPModule.ESP12.build.spiffs_blocksize=8192 -wifinfo.menu.ESPModule.ESP12.build.flash_size=4M -wifinfo.build.board=WIFINFO -wifinfo.build.variant=wifinfo -wifinfo.menu.ESPModule.ESP07192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.ESPModule.ESP07192.build.flash_size=1M -wifinfo.menu.ESPModule.ESP07192=ESP07 (1M/192K SPIFFS) -wifinfo.menu.ESPModule.ESP07192.upload.maximum_size=827376 -wifinfo.upload.tool=esptool -wifinfo.upload.maximum_data_size=81920 -wifinfo.upload.wait_for_upload_port=true -wifinfo.upload.erase_cmd= -wifinfo.serial.disableDTR=true -wifinfo.serial.disableRTS=true -wifinfo.build.mcu=esp8266 -wifinfo.build.core=esp8266 -wifinfo.build.spiffs_pagesize=256 -wifinfo.build.debug_port= -wifinfo.build.debug_level= -wifinfo.menu.xtal.80=80 MHz -wifinfo.menu.xtal.80.build.f_cpu=80000000L -wifinfo.menu.xtal.160=160 MHz -wifinfo.menu.xtal.160.build.f_cpu=160000000L -wifinfo.menu.vt.flash=Flash -wifinfo.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wifinfo.menu.vt.heap=Heap -wifinfo.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wifinfo.menu.vt.iram=IRAM -wifinfo.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wifinfo.menu.exception.disabled=Disabled -wifinfo.menu.exception.disabled.build.exception_flags=-fno-exceptions -wifinfo.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -wifinfo.menu.exception.enabled=Enabled -wifinfo.menu.exception.enabled.build.exception_flags=-fexceptions -wifinfo.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -wifinfo.upload.resetmethod=nodemcu -wifinfo.build.flash_mode=qio -wifinfo.build.flash_flags=-DFLASHMODE_QIO -wifinfo.menu.FlashFreq.40=40MHz -wifinfo.menu.FlashFreq.40.build.flash_freq=40 -wifinfo.menu.FlashFreq.80=80MHz -wifinfo.menu.FlashFreq.80.build.flash_freq=80 -wifinfo.menu.eesz.1M=1M (no SPIFFS) -wifinfo.menu.eesz.1M.build.flash_size=1M -wifinfo.menu.eesz.1M.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -wifinfo.menu.eesz.1M.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M.upload.maximum_size=1023984 -wifinfo.menu.eesz.1M.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M64=1M (64K SPIFFS) -wifinfo.menu.eesz.1M64.build.flash_size=1M -wifinfo.menu.eesz.1M64.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -wifinfo.menu.eesz.1M64.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M64.upload.maximum_size=958448 -wifinfo.menu.eesz.1M64.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M64.build.spiffs_start=0xEB000 -wifinfo.menu.eesz.1M64.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M64.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M128=1M (128K SPIFFS) -wifinfo.menu.eesz.1M128.build.flash_size=1M -wifinfo.menu.eesz.1M128.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -wifinfo.menu.eesz.1M128.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M128.upload.maximum_size=892912 -wifinfo.menu.eesz.1M128.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M128.build.spiffs_start=0xDB000 -wifinfo.menu.eesz.1M128.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M128.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M144=1M (144K SPIFFS) -wifinfo.menu.eesz.1M144.build.flash_size=1M -wifinfo.menu.eesz.1M144.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -wifinfo.menu.eesz.1M144.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M144.upload.maximum_size=876528 -wifinfo.menu.eesz.1M144.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M144.build.spiffs_start=0xD7000 -wifinfo.menu.eesz.1M144.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M144.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M160=1M (160K SPIFFS) -wifinfo.menu.eesz.1M160.build.flash_size=1M -wifinfo.menu.eesz.1M160.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -wifinfo.menu.eesz.1M160.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M160.upload.maximum_size=860144 -wifinfo.menu.eesz.1M160.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M160.build.spiffs_start=0xD3000 -wifinfo.menu.eesz.1M160.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M160.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M192=1M (192K SPIFFS) -wifinfo.menu.eesz.1M192.build.flash_size=1M -wifinfo.menu.eesz.1M192.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.eesz.1M192.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M192.upload.maximum_size=827376 -wifinfo.menu.eesz.1M192.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M192.build.spiffs_start=0xCB000 -wifinfo.menu.eesz.1M192.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M192.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M256=1M (256K SPIFFS) -wifinfo.menu.eesz.1M256.build.flash_size=1M -wifinfo.menu.eesz.1M256.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -wifinfo.menu.eesz.1M256.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M256.upload.maximum_size=761840 -wifinfo.menu.eesz.1M256.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M256.build.spiffs_start=0xBB000 -wifinfo.menu.eesz.1M256.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M256.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M512=1M (512K SPIFFS) -wifinfo.menu.eesz.1M512.build.flash_size=1M -wifinfo.menu.eesz.1M512.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -wifinfo.menu.eesz.1M512.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M512.upload.maximum_size=499696 -wifinfo.menu.eesz.1M512.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M512.build.spiffs_start=0x7B000 -wifinfo.menu.eesz.1M512.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M512.build.spiffs_blocksize=4096 -wifinfo.menu.ip.lm2f=v2 Lower Memory -wifinfo.menu.ip.lm2f.build.lwip_include=lwip2/include -wifinfo.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -wifinfo.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifinfo.menu.ip.hb2f=v2 Higher Bandwidth -wifinfo.menu.ip.hb2f.build.lwip_include=lwip2/include -wifinfo.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -wifinfo.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifinfo.menu.ip.lm2n=v2 Lower Memory (no features) -wifinfo.menu.ip.lm2n.build.lwip_include=lwip2/include -wifinfo.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -wifinfo.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifinfo.menu.ip.hb2n=v2 Higher Bandwidth (no features) -wifinfo.menu.ip.hb2n.build.lwip_include=lwip2/include -wifinfo.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -wifinfo.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifinfo.menu.ip.lm6f=v2 IPv6 Lower Memory -wifinfo.menu.ip.lm6f.build.lwip_include=lwip2/include -wifinfo.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -wifinfo.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifinfo.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -wifinfo.menu.ip.hb6f.build.lwip_include=lwip2/include -wifinfo.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -wifinfo.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifinfo.menu.ip.hb1=v1.4 Higher Bandwidth -wifinfo.menu.ip.hb1.build.lwip_lib=-llwip_gcc -wifinfo.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -wifinfo.menu.ip.src=v1.4 Compile from source -wifinfo.menu.ip.src.build.lwip_lib=-llwip_src -wifinfo.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -wifinfo.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifinfo.menu.dbg.Disabled=Disabled -wifinfo.menu.dbg.Disabled.build.debug_port= -wifinfo.menu.dbg.Serial=Serial -wifinfo.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifinfo.menu.dbg.Serial1=Serial1 -wifinfo.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifinfo.menu.lvl.None____=None -wifinfo.menu.lvl.None____.build.debug_level= -wifinfo.menu.lvl.SSL=SSL -wifinfo.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifinfo.menu.lvl.TLS_MEM=TLS_MEM -wifinfo.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifinfo.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -wifinfo.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.lvl.HTTP_SERVER=HTTP_SERVER -wifinfo.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -wifinfo.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifinfo.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifinfo.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifinfo.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifinfo.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.CORE=CORE -wifinfo.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifinfo.menu.lvl.WIFI=WIFI -wifinfo.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifinfo.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -wifinfo.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifinfo.menu.lvl.UPDATER=UPDATER -wifinfo.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifinfo.menu.lvl.OTA=OTA -wifinfo.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifinfo.menu.lvl.OOM=OOM -wifinfo.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifinfo.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -wifinfo.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifinfo.menu.wipe.none=Only Sketch -wifinfo.menu.wipe.none.upload.erase_cmd= -wifinfo.menu.wipe.sdk=Sketch + WiFi Settings -wifinfo.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wifinfo.menu.wipe.all=All Flash Contents -wifinfo.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wifinfo.menu.baud.115200=115200 -wifinfo.menu.baud.115200.upload.speed=115200 -wifinfo.menu.baud.9600=9600 -wifinfo.menu.baud.9600.upload.speed=9600 -wifinfo.menu.baud.57600=57600 -wifinfo.menu.baud.57600.upload.speed=57600 -wifinfo.menu.baud.230400.linux=230400 -wifinfo.menu.baud.230400.macosx=230400 -wifinfo.menu.baud.230400.upload.speed=230400 -wifinfo.menu.baud.256000.windows=256000 -wifinfo.menu.baud.256000.upload.speed=256000 -wifinfo.menu.baud.460800.linux=460800 -wifinfo.menu.baud.460800.macosx=460800 -wifinfo.menu.baud.460800.upload.speed=460800 -wifinfo.menu.baud.512000.windows=512000 -wifinfo.menu.baud.512000.upload.speed=512000 -wifinfo.menu.baud.921600=921600 -wifinfo.menu.baud.921600.upload.speed=921600 - -############################################################## -arduino-esp8266.name=Arduino -arduino-esp8266.menu.BoardModel.starottodeved.build.board=ESP8266_ARDUINO_STAR_OTTO -arduino-esp8266.menu.BoardModel.primo.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.starottodeved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.starottodeved.build.variant=arduino_uart -arduino-esp8266.menu.BoardModel.unowifideved.build.board=ESP8266_ARDUINO_UNOWIFI -arduino-esp8266.menu.BoardModel.unowifideved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.primo=Primo -arduino-esp8266.menu.BoardModel.unowifideved.build.variant=arduino_uart -arduino-esp8266.menu.BoardModel.primo.build.variant=arduino_spi -arduino-esp8266.menu.BoardModel.starottodeved=Star OTTO -arduino-esp8266.build.board=ESP8266_ARDUINO -arduino-esp8266.menu.BoardModel.primo.build.board=ESP8266_ARDUINO_PRIMO -arduino-esp8266.menu.BoardModel.unowifideved=Uno WiFi -arduino-esp8266.upload.tool=esptool -arduino-esp8266.upload.maximum_data_size=81920 -arduino-esp8266.upload.wait_for_upload_port=true -arduino-esp8266.upload.erase_cmd= -arduino-esp8266.serial.disableDTR=true -arduino-esp8266.serial.disableRTS=true -arduino-esp8266.build.mcu=esp8266 -arduino-esp8266.build.core=esp8266 -arduino-esp8266.build.variant=generic -arduino-esp8266.build.spiffs_pagesize=256 -arduino-esp8266.build.debug_port= -arduino-esp8266.build.debug_level= -arduino-esp8266.menu.xtal.80=80 MHz -arduino-esp8266.menu.xtal.80.build.f_cpu=80000000L -arduino-esp8266.menu.xtal.160=160 MHz -arduino-esp8266.menu.xtal.160.build.f_cpu=160000000L -arduino-esp8266.menu.vt.flash=Flash -arduino-esp8266.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -arduino-esp8266.menu.vt.heap=Heap -arduino-esp8266.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -arduino-esp8266.menu.vt.iram=IRAM -arduino-esp8266.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -arduino-esp8266.menu.exception.disabled=Disabled -arduino-esp8266.menu.exception.disabled.build.exception_flags=-fno-exceptions -arduino-esp8266.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -arduino-esp8266.menu.exception.enabled=Enabled -arduino-esp8266.menu.exception.enabled.build.exception_flags=-fexceptions -arduino-esp8266.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -arduino-esp8266.upload.resetmethod=ck -arduino-esp8266.build.flash_mode=qio -arduino-esp8266.build.flash_flags=-DFLASHMODE_QIO -arduino-esp8266.build.flash_freq=40 -arduino-esp8266.menu.eesz.4M=4M (no SPIFFS) -arduino-esp8266.menu.eesz.4M.build.flash_size=4M -arduino-esp8266.menu.eesz.4M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -arduino-esp8266.menu.eesz.4M.build.spiffs_pagesize=256 -arduino-esp8266.menu.eesz.4M.upload.maximum_size=1044464 -arduino-esp8266.menu.eesz.4M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.eesz.4M1M=4M (1M SPIFFS) -arduino-esp8266.menu.eesz.4M1M.build.flash_size=4M -arduino-esp8266.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -arduino-esp8266.menu.eesz.4M1M.build.spiffs_pagesize=256 -arduino-esp8266.menu.eesz.4M1M.upload.maximum_size=1044464 -arduino-esp8266.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.eesz.4M1M.build.spiffs_start=0x300000 -arduino-esp8266.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.eesz.4M1M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.eesz.4M2M=4M (2M SPIFFS) -arduino-esp8266.menu.eesz.4M2M.build.flash_size=4M -arduino-esp8266.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -arduino-esp8266.menu.eesz.4M2M.build.spiffs_pagesize=256 -arduino-esp8266.menu.eesz.4M2M.upload.maximum_size=1044464 -arduino-esp8266.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.eesz.4M2M.build.spiffs_start=0x200000 -arduino-esp8266.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.eesz.4M2M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.eesz.4M3M=4M (3M SPIFFS) -arduino-esp8266.menu.eesz.4M3M.build.flash_size=4M -arduino-esp8266.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -arduino-esp8266.menu.eesz.4M3M.build.spiffs_pagesize=256 -arduino-esp8266.menu.eesz.4M3M.upload.maximum_size=1044464 -arduino-esp8266.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.eesz.4M3M.build.spiffs_start=0x100000 -arduino-esp8266.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.eesz.4M3M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.ip.lm2f=v2 Lower Memory -arduino-esp8266.menu.ip.lm2f.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -arduino-esp8266.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -arduino-esp8266.menu.ip.hb2f=v2 Higher Bandwidth -arduino-esp8266.menu.ip.hb2f.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -arduino-esp8266.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -arduino-esp8266.menu.ip.lm2n=v2 Lower Memory (no features) -arduino-esp8266.menu.ip.lm2n.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -arduino-esp8266.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -arduino-esp8266.menu.ip.hb2n=v2 Higher Bandwidth (no features) -arduino-esp8266.menu.ip.hb2n.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -arduino-esp8266.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -arduino-esp8266.menu.ip.lm6f=v2 IPv6 Lower Memory -arduino-esp8266.menu.ip.lm6f.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -arduino-esp8266.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -arduino-esp8266.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -arduino-esp8266.menu.ip.hb6f.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -arduino-esp8266.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -arduino-esp8266.menu.ip.hb1=v1.4 Higher Bandwidth -arduino-esp8266.menu.ip.hb1.build.lwip_lib=-llwip_gcc -arduino-esp8266.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -arduino-esp8266.menu.ip.src=v1.4 Compile from source -arduino-esp8266.menu.ip.src.build.lwip_lib=-llwip_src -arduino-esp8266.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -arduino-esp8266.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -arduino-esp8266.menu.dbg.Disabled=Disabled -arduino-esp8266.menu.dbg.Disabled.build.debug_port= -arduino-esp8266.menu.dbg.Serial=Serial -arduino-esp8266.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -arduino-esp8266.menu.dbg.Serial1=Serial1 -arduino-esp8266.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -arduino-esp8266.menu.lvl.None____=None -arduino-esp8266.menu.lvl.None____.build.debug_level= -arduino-esp8266.menu.lvl.SSL=SSL -arduino-esp8266.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -arduino-esp8266.menu.lvl.TLS_MEM=TLS_MEM -arduino-esp8266.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -arduino-esp8266.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -arduino-esp8266.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.lvl.HTTP_SERVER=HTTP_SERVER -arduino-esp8266.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -arduino-esp8266.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -arduino-esp8266.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -arduino-esp8266.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -arduino-esp8266.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.CORE=CORE -arduino-esp8266.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -arduino-esp8266.menu.lvl.WIFI=WIFI -arduino-esp8266.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -arduino-esp8266.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -arduino-esp8266.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -arduino-esp8266.menu.lvl.UPDATER=UPDATER -arduino-esp8266.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -arduino-esp8266.menu.lvl.OTA=OTA -arduino-esp8266.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -arduino-esp8266.menu.lvl.OOM=OOM -arduino-esp8266.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -arduino-esp8266.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -arduino-esp8266.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -arduino-esp8266.menu.wipe.none=Only Sketch -arduino-esp8266.menu.wipe.none.upload.erase_cmd= -arduino-esp8266.menu.wipe.sdk=Sketch + WiFi Settings -arduino-esp8266.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -arduino-esp8266.menu.wipe.all=All Flash Contents -arduino-esp8266.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -arduino-esp8266.menu.baud.115200=115200 -arduino-esp8266.menu.baud.115200.upload.speed=115200 -arduino-esp8266.menu.baud.9600=9600 -arduino-esp8266.menu.baud.9600.upload.speed=9600 -arduino-esp8266.menu.baud.57600=57600 -arduino-esp8266.menu.baud.57600.upload.speed=57600 -arduino-esp8266.menu.baud.230400.linux=230400 -arduino-esp8266.menu.baud.230400.macosx=230400 -arduino-esp8266.menu.baud.230400.upload.speed=230400 -arduino-esp8266.menu.baud.256000.windows=256000 -arduino-esp8266.menu.baud.256000.upload.speed=256000 -arduino-esp8266.menu.baud.460800.linux=460800 -arduino-esp8266.menu.baud.460800.macosx=460800 -arduino-esp8266.menu.baud.460800.upload.speed=460800 -arduino-esp8266.menu.baud.512000.windows=512000 -arduino-esp8266.menu.baud.512000.upload.speed=512000 -arduino-esp8266.menu.baud.921600=921600 -arduino-esp8266.menu.baud.921600.upload.speed=921600 - -############################################################## -gen4iod.name=4D Systems gen4 IoD Range -gen4iod.build.board=GEN4_IOD -gen4iod.build.f_cpu=160000000L -gen4iod.build.variant=generic -gen4iod.upload.tool=esptool -gen4iod.upload.maximum_data_size=81920 -gen4iod.upload.wait_for_upload_port=true -gen4iod.upload.erase_cmd= -gen4iod.serial.disableDTR=true -gen4iod.serial.disableRTS=true -gen4iod.build.mcu=esp8266 -gen4iod.build.core=esp8266 -gen4iod.build.spiffs_pagesize=256 -gen4iod.build.debug_port= -gen4iod.build.debug_level= -gen4iod.menu.xtal.80=80 MHz -gen4iod.menu.xtal.80.build.f_cpu=80000000L -gen4iod.menu.xtal.160=160 MHz -gen4iod.menu.xtal.160.build.f_cpu=160000000L -gen4iod.menu.vt.flash=Flash -gen4iod.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -gen4iod.menu.vt.heap=Heap -gen4iod.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -gen4iod.menu.vt.iram=IRAM -gen4iod.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -gen4iod.menu.exception.disabled=Disabled -gen4iod.menu.exception.disabled.build.exception_flags=-fno-exceptions -gen4iod.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -gen4iod.menu.exception.enabled=Enabled -gen4iod.menu.exception.enabled.build.exception_flags=-fexceptions -gen4iod.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -gen4iod.upload.resetmethod=nodemcu -gen4iod.build.flash_mode=dio -gen4iod.build.flash_flags=-DFLASHMODE_DIO -gen4iod.build.flash_freq=80 -gen4iod.menu.eesz.512K=512K (no SPIFFS) -gen4iod.menu.eesz.512K.build.flash_size=512K -gen4iod.menu.eesz.512K.build.flash_size_bytes=0x80000 -gen4iod.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld -gen4iod.menu.eesz.512K.build.spiffs_pagesize=256 -gen4iod.menu.eesz.512K.upload.maximum_size=499696 -gen4iod.menu.eesz.512K.build.rfcal_addr=0x7C000 -gen4iod.menu.eesz.512K32=512K (32K SPIFFS) -gen4iod.menu.eesz.512K32.build.flash_size=512K -gen4iod.menu.eesz.512K32.build.flash_size_bytes=0x80000 -gen4iod.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld -gen4iod.menu.eesz.512K32.build.spiffs_pagesize=256 -gen4iod.menu.eesz.512K32.upload.maximum_size=466928 -gen4iod.menu.eesz.512K32.build.rfcal_addr=0x7C000 -gen4iod.menu.eesz.512K32.build.spiffs_start=0x73000 -gen4iod.menu.eesz.512K32.build.spiffs_end=0x7B000 -gen4iod.menu.eesz.512K32.build.spiffs_blocksize=4096 -gen4iod.menu.eesz.512K64=512K (64K SPIFFS) -gen4iod.menu.eesz.512K64.build.flash_size=512K -gen4iod.menu.eesz.512K64.build.flash_size_bytes=0x80000 -gen4iod.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld -gen4iod.menu.eesz.512K64.build.spiffs_pagesize=256 -gen4iod.menu.eesz.512K64.upload.maximum_size=434160 -gen4iod.menu.eesz.512K64.build.rfcal_addr=0x7C000 -gen4iod.menu.eesz.512K64.build.spiffs_start=0x6B000 -gen4iod.menu.eesz.512K64.build.spiffs_end=0x7B000 -gen4iod.menu.eesz.512K64.build.spiffs_blocksize=4096 -gen4iod.menu.eesz.512K128=512K (128K SPIFFS) -gen4iod.menu.eesz.512K128.build.flash_size=512K -gen4iod.menu.eesz.512K128.build.flash_size_bytes=0x80000 -gen4iod.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld -gen4iod.menu.eesz.512K128.build.spiffs_pagesize=256 -gen4iod.menu.eesz.512K128.upload.maximum_size=368624 -gen4iod.menu.eesz.512K128.build.rfcal_addr=0x7C000 -gen4iod.menu.eesz.512K128.build.spiffs_start=0x5B000 -gen4iod.menu.eesz.512K128.build.spiffs_end=0x7B000 -gen4iod.menu.eesz.512K128.build.spiffs_blocksize=4096 -gen4iod.menu.ip.lm2f=v2 Lower Memory -gen4iod.menu.ip.lm2f.build.lwip_include=lwip2/include -gen4iod.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -gen4iod.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -gen4iod.menu.ip.hb2f=v2 Higher Bandwidth -gen4iod.menu.ip.hb2f.build.lwip_include=lwip2/include -gen4iod.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -gen4iod.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -gen4iod.menu.ip.lm2n=v2 Lower Memory (no features) -gen4iod.menu.ip.lm2n.build.lwip_include=lwip2/include -gen4iod.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -gen4iod.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -gen4iod.menu.ip.hb2n=v2 Higher Bandwidth (no features) -gen4iod.menu.ip.hb2n.build.lwip_include=lwip2/include -gen4iod.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -gen4iod.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -gen4iod.menu.ip.lm6f=v2 IPv6 Lower Memory -gen4iod.menu.ip.lm6f.build.lwip_include=lwip2/include -gen4iod.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -gen4iod.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -gen4iod.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -gen4iod.menu.ip.hb6f.build.lwip_include=lwip2/include -gen4iod.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -gen4iod.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -gen4iod.menu.ip.hb1=v1.4 Higher Bandwidth -gen4iod.menu.ip.hb1.build.lwip_lib=-llwip_gcc -gen4iod.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -gen4iod.menu.ip.src=v1.4 Compile from source -gen4iod.menu.ip.src.build.lwip_lib=-llwip_src -gen4iod.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -gen4iod.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -gen4iod.menu.dbg.Disabled=Disabled -gen4iod.menu.dbg.Disabled.build.debug_port= -gen4iod.menu.dbg.Serial=Serial -gen4iod.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -gen4iod.menu.dbg.Serial1=Serial1 -gen4iod.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -gen4iod.menu.lvl.None____=None -gen4iod.menu.lvl.None____.build.debug_level= -gen4iod.menu.lvl.SSL=SSL -gen4iod.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -gen4iod.menu.lvl.TLS_MEM=TLS_MEM -gen4iod.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -gen4iod.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -gen4iod.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.lvl.HTTP_SERVER=HTTP_SERVER -gen4iod.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -gen4iod.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -gen4iod.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -gen4iod.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -gen4iod.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -gen4iod.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.CORE=CORE -gen4iod.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -gen4iod.menu.lvl.WIFI=WIFI -gen4iod.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -gen4iod.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -gen4iod.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -gen4iod.menu.lvl.UPDATER=UPDATER -gen4iod.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -gen4iod.menu.lvl.OTA=OTA -gen4iod.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -gen4iod.menu.lvl.OOM=OOM -gen4iod.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -gen4iod.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -gen4iod.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -gen4iod.menu.wipe.none=Only Sketch -gen4iod.menu.wipe.none.upload.erase_cmd= -gen4iod.menu.wipe.sdk=Sketch + WiFi Settings -gen4iod.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -gen4iod.menu.wipe.all=All Flash Contents -gen4iod.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -gen4iod.menu.baud.115200=115200 -gen4iod.menu.baud.115200.upload.speed=115200 -gen4iod.menu.baud.9600=9600 -gen4iod.menu.baud.9600.upload.speed=9600 -gen4iod.menu.baud.57600=57600 -gen4iod.menu.baud.57600.upload.speed=57600 -gen4iod.menu.baud.230400.linux=230400 -gen4iod.menu.baud.230400.macosx=230400 -gen4iod.menu.baud.230400.upload.speed=230400 -gen4iod.menu.baud.256000.windows=256000 -gen4iod.menu.baud.256000.upload.speed=256000 -gen4iod.menu.baud.460800.linux=460800 -gen4iod.menu.baud.460800.macosx=460800 -gen4iod.menu.baud.460800.upload.speed=460800 -gen4iod.menu.baud.512000.windows=512000 -gen4iod.menu.baud.512000.upload.speed=512000 -gen4iod.menu.baud.921600=921600 -gen4iod.menu.baud.921600.upload.speed=921600 - -############################################################## -oak.name=Digistump Oak -oak.build.board=ESP8266_OAK -oak.build.variant=oak -oak.upload.maximum_size=1040368 -oak.upload.tool=esptool -oak.upload.maximum_data_size=81920 -oak.upload.wait_for_upload_port=true -oak.upload.erase_cmd= -oak.serial.disableDTR=true -oak.serial.disableRTS=true -oak.build.mcu=esp8266 -oak.build.core=esp8266 -oak.build.spiffs_pagesize=256 -oak.build.debug_port= -oak.build.debug_level= -oak.menu.xtal.80=80 MHz -oak.menu.xtal.80.build.f_cpu=80000000L -oak.menu.xtal.160=160 MHz -oak.menu.xtal.160.build.f_cpu=160000000L -oak.menu.vt.flash=Flash -oak.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -oak.menu.vt.heap=Heap -oak.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -oak.menu.vt.iram=IRAM -oak.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -oak.menu.exception.disabled=Disabled -oak.menu.exception.disabled.build.exception_flags=-fno-exceptions -oak.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -oak.menu.exception.enabled=Enabled -oak.menu.exception.enabled.build.exception_flags=-fexceptions -oak.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -oak.upload.resetmethod=none -oak.build.flash_mode=dio -oak.build.flash_flags=-DFLASHMODE_DIO -oak.build.flash_freq=40 -oak.menu.eesz.4M=4M (no SPIFFS) -oak.menu.eesz.4M.build.flash_size=4M -oak.menu.eesz.4M.build.flash_size_bytes=0x400000 -oak.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -oak.menu.eesz.4M.build.spiffs_pagesize=256 -oak.menu.eesz.4M.upload.maximum_size=1044464 -oak.menu.eesz.4M.build.rfcal_addr=0x3FC000 -oak.menu.eesz.4M1M=4M (1M SPIFFS) -oak.menu.eesz.4M1M.build.flash_size=4M -oak.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -oak.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -oak.menu.eesz.4M1M.build.spiffs_pagesize=256 -oak.menu.eesz.4M1M.upload.maximum_size=1044464 -oak.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -oak.menu.eesz.4M1M.build.spiffs_start=0x300000 -oak.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -oak.menu.eesz.4M1M.build.spiffs_blocksize=8192 -oak.menu.eesz.4M2M=4M (2M SPIFFS) -oak.menu.eesz.4M2M.build.flash_size=4M -oak.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -oak.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -oak.menu.eesz.4M2M.build.spiffs_pagesize=256 -oak.menu.eesz.4M2M.upload.maximum_size=1044464 -oak.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -oak.menu.eesz.4M2M.build.spiffs_start=0x200000 -oak.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -oak.menu.eesz.4M2M.build.spiffs_blocksize=8192 -oak.menu.eesz.4M3M=4M (3M SPIFFS) -oak.menu.eesz.4M3M.build.flash_size=4M -oak.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -oak.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -oak.menu.eesz.4M3M.build.spiffs_pagesize=256 -oak.menu.eesz.4M3M.upload.maximum_size=1044464 -oak.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -oak.menu.eesz.4M3M.build.spiffs_start=0x100000 -oak.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -oak.menu.eesz.4M3M.build.spiffs_blocksize=8192 -oak.menu.ip.lm2f=v2 Lower Memory -oak.menu.ip.lm2f.build.lwip_include=lwip2/include -oak.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -oak.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -oak.menu.ip.hb2f=v2 Higher Bandwidth -oak.menu.ip.hb2f.build.lwip_include=lwip2/include -oak.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -oak.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -oak.menu.ip.lm2n=v2 Lower Memory (no features) -oak.menu.ip.lm2n.build.lwip_include=lwip2/include -oak.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -oak.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -oak.menu.ip.hb2n=v2 Higher Bandwidth (no features) -oak.menu.ip.hb2n.build.lwip_include=lwip2/include -oak.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -oak.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -oak.menu.ip.lm6f=v2 IPv6 Lower Memory -oak.menu.ip.lm6f.build.lwip_include=lwip2/include -oak.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -oak.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -oak.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -oak.menu.ip.hb6f.build.lwip_include=lwip2/include -oak.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -oak.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -oak.menu.ip.hb1=v1.4 Higher Bandwidth -oak.menu.ip.hb1.build.lwip_lib=-llwip_gcc -oak.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -oak.menu.ip.src=v1.4 Compile from source -oak.menu.ip.src.build.lwip_lib=-llwip_src -oak.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -oak.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -oak.menu.dbg.Disabled=Disabled -oak.menu.dbg.Disabled.build.debug_port= -oak.menu.dbg.Serial=Serial -oak.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -oak.menu.dbg.Serial1=Serial1 -oak.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -oak.menu.lvl.None____=None -oak.menu.lvl.None____.build.debug_level= -oak.menu.lvl.SSL=SSL -oak.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -oak.menu.lvl.TLS_MEM=TLS_MEM -oak.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -oak.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -oak.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -oak.menu.lvl.HTTP_SERVER=HTTP_SERVER -oak.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -oak.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -oak.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -oak.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -oak.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -oak.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -oak.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -oak.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -oak.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -oak.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -oak.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -oak.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.CORE=CORE -oak.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -oak.menu.lvl.WIFI=WIFI -oak.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -oak.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -oak.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -oak.menu.lvl.UPDATER=UPDATER -oak.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -oak.menu.lvl.OTA=OTA -oak.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -oak.menu.lvl.OOM=OOM -oak.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -oak.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -oak.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -oak.menu.wipe.none=Only Sketch -oak.menu.wipe.none.upload.erase_cmd= -oak.menu.wipe.sdk=Sketch + WiFi Settings -oak.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -oak.menu.wipe.all=All Flash Contents -oak.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -oak.menu.baud.921600=921600 -oak.menu.baud.921600.upload.speed=921600 -oak.menu.baud.9600=9600 -oak.menu.baud.9600.upload.speed=9600 -oak.menu.baud.57600=57600 -oak.menu.baud.57600.upload.speed=57600 -oak.menu.baud.115200=115200 -oak.menu.baud.115200.upload.speed=115200 -oak.menu.baud.230400.linux=230400 -oak.menu.baud.230400.macosx=230400 -oak.menu.baud.230400.upload.speed=230400 -oak.menu.baud.256000.windows=256000 -oak.menu.baud.256000.upload.speed=256000 -oak.menu.baud.460800.linux=460800 -oak.menu.baud.460800.macosx=460800 -oak.menu.baud.460800.upload.speed=460800 -oak.menu.baud.512000.windows=512000 -oak.menu.baud.512000.upload.speed=512000 - -############################################################## -wifiduino.name=WiFiduino -wifiduino.build.board=WIFIDUINO_ESP8266 -wifiduino.build.variant=wifiduino -wifiduino.upload.tool=esptool -wifiduino.upload.maximum_data_size=81920 -wifiduino.upload.wait_for_upload_port=true -wifiduino.upload.erase_cmd= -wifiduino.serial.disableDTR=true -wifiduino.serial.disableRTS=true -wifiduino.build.mcu=esp8266 -wifiduino.build.core=esp8266 -wifiduino.build.spiffs_pagesize=256 -wifiduino.build.debug_port= -wifiduino.build.debug_level= -wifiduino.menu.xtal.80=80 MHz -wifiduino.menu.xtal.80.build.f_cpu=80000000L -wifiduino.menu.xtal.160=160 MHz -wifiduino.menu.xtal.160.build.f_cpu=160000000L -wifiduino.menu.vt.flash=Flash -wifiduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wifiduino.menu.vt.heap=Heap -wifiduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wifiduino.menu.vt.iram=IRAM -wifiduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wifiduino.menu.exception.disabled=Disabled -wifiduino.menu.exception.disabled.build.exception_flags=-fno-exceptions -wifiduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -wifiduino.menu.exception.enabled=Enabled -wifiduino.menu.exception.enabled.build.exception_flags=-fexceptions -wifiduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -wifiduino.upload.resetmethod=nodemcu -wifiduino.build.flash_mode=dio -wifiduino.build.flash_flags=-DFLASHMODE_DIO -wifiduino.build.flash_freq=40 -wifiduino.menu.eesz.4M=4M (no SPIFFS) -wifiduino.menu.eesz.4M.build.flash_size=4M -wifiduino.menu.eesz.4M.build.flash_size_bytes=0x400000 -wifiduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -wifiduino.menu.eesz.4M.build.spiffs_pagesize=256 -wifiduino.menu.eesz.4M.upload.maximum_size=1044464 -wifiduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 -wifiduino.menu.eesz.4M1M=4M (1M SPIFFS) -wifiduino.menu.eesz.4M1M.build.flash_size=4M -wifiduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -wifiduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -wifiduino.menu.eesz.4M1M.build.spiffs_pagesize=256 -wifiduino.menu.eesz.4M1M.upload.maximum_size=1044464 -wifiduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -wifiduino.menu.eesz.4M1M.build.spiffs_start=0x300000 -wifiduino.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -wifiduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 -wifiduino.menu.eesz.4M2M=4M (2M SPIFFS) -wifiduino.menu.eesz.4M2M.build.flash_size=4M -wifiduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -wifiduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -wifiduino.menu.eesz.4M2M.build.spiffs_pagesize=256 -wifiduino.menu.eesz.4M2M.upload.maximum_size=1044464 -wifiduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -wifiduino.menu.eesz.4M2M.build.spiffs_start=0x200000 -wifiduino.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -wifiduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 -wifiduino.menu.eesz.4M3M=4M (3M SPIFFS) -wifiduino.menu.eesz.4M3M.build.flash_size=4M -wifiduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -wifiduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -wifiduino.menu.eesz.4M3M.build.spiffs_pagesize=256 -wifiduino.menu.eesz.4M3M.upload.maximum_size=1044464 -wifiduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -wifiduino.menu.eesz.4M3M.build.spiffs_start=0x100000 -wifiduino.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -wifiduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 -wifiduino.menu.ip.lm2f=v2 Lower Memory -wifiduino.menu.ip.lm2f.build.lwip_include=lwip2/include -wifiduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -wifiduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifiduino.menu.ip.hb2f=v2 Higher Bandwidth -wifiduino.menu.ip.hb2f.build.lwip_include=lwip2/include -wifiduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -wifiduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifiduino.menu.ip.lm2n=v2 Lower Memory (no features) -wifiduino.menu.ip.lm2n.build.lwip_include=lwip2/include -wifiduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -wifiduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifiduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) -wifiduino.menu.ip.hb2n.build.lwip_include=lwip2/include -wifiduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -wifiduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifiduino.menu.ip.lm6f=v2 IPv6 Lower Memory -wifiduino.menu.ip.lm6f.build.lwip_include=lwip2/include -wifiduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -wifiduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifiduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -wifiduino.menu.ip.hb6f.build.lwip_include=lwip2/include -wifiduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -wifiduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifiduino.menu.ip.hb1=v1.4 Higher Bandwidth -wifiduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc -wifiduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -wifiduino.menu.ip.src=v1.4 Compile from source -wifiduino.menu.ip.src.build.lwip_lib=-llwip_src -wifiduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -wifiduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifiduino.menu.dbg.Disabled=Disabled -wifiduino.menu.dbg.Disabled.build.debug_port= -wifiduino.menu.dbg.Serial=Serial -wifiduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifiduino.menu.dbg.Serial1=Serial1 -wifiduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifiduino.menu.lvl.None____=None -wifiduino.menu.lvl.None____.build.debug_level= -wifiduino.menu.lvl.SSL=SSL -wifiduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifiduino.menu.lvl.TLS_MEM=TLS_MEM -wifiduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifiduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -wifiduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.lvl.HTTP_SERVER=HTTP_SERVER -wifiduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -wifiduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifiduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifiduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifiduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifiduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.CORE=CORE -wifiduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifiduino.menu.lvl.WIFI=WIFI -wifiduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifiduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -wifiduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifiduino.menu.lvl.UPDATER=UPDATER -wifiduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifiduino.menu.lvl.OTA=OTA -wifiduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifiduino.menu.lvl.OOM=OOM -wifiduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifiduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -wifiduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifiduino.menu.wipe.none=Only Sketch -wifiduino.menu.wipe.none.upload.erase_cmd= -wifiduino.menu.wipe.sdk=Sketch + WiFi Settings -wifiduino.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wifiduino.menu.wipe.all=All Flash Contents -wifiduino.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wifiduino.menu.baud.921600=921600 -wifiduino.menu.baud.921600.upload.speed=921600 -wifiduino.menu.baud.9600=9600 -wifiduino.menu.baud.9600.upload.speed=9600 -wifiduino.menu.baud.57600=57600 -wifiduino.menu.baud.57600.upload.speed=57600 -wifiduino.menu.baud.115200=115200 -wifiduino.menu.baud.115200.upload.speed=115200 -wifiduino.menu.baud.230400.linux=230400 -wifiduino.menu.baud.230400.macosx=230400 -wifiduino.menu.baud.230400.upload.speed=230400 -wifiduino.menu.baud.256000.windows=256000 -wifiduino.menu.baud.256000.upload.speed=256000 -wifiduino.menu.baud.460800.linux=460800 -wifiduino.menu.baud.460800.macosx=460800 -wifiduino.menu.baud.460800.upload.speed=460800 -wifiduino.menu.baud.512000.windows=512000 -wifiduino.menu.baud.512000.upload.speed=512000 - -############################################################## -wifi_slot.name=Amperka WiFi Slot -wifi_slot.build.board=AMPERKA_WIFI_SLOT -wifi_slot.build.variant=wifi_slot -wifi_slot.upload.tool=esptool -wifi_slot.upload.maximum_data_size=81920 -wifi_slot.upload.wait_for_upload_port=true -wifi_slot.upload.erase_cmd= -wifi_slot.serial.disableDTR=true -wifi_slot.serial.disableRTS=true -wifi_slot.build.mcu=esp8266 -wifi_slot.build.core=esp8266 -wifi_slot.build.spiffs_pagesize=256 -wifi_slot.build.debug_port= -wifi_slot.build.debug_level= -wifi_slot.menu.xtal.80=80 MHz -wifi_slot.menu.xtal.80.build.f_cpu=80000000L -wifi_slot.menu.xtal.160=160 MHz -wifi_slot.menu.xtal.160.build.f_cpu=160000000L -wifi_slot.menu.vt.flash=Flash -wifi_slot.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wifi_slot.menu.vt.heap=Heap -wifi_slot.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wifi_slot.menu.vt.iram=IRAM -wifi_slot.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wifi_slot.menu.exception.disabled=Disabled -wifi_slot.menu.exception.disabled.build.exception_flags=-fno-exceptions -wifi_slot.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -wifi_slot.menu.exception.enabled=Enabled -wifi_slot.menu.exception.enabled.build.exception_flags=-fexceptions -wifi_slot.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -wifi_slot.upload.resetmethod=nodemcu -wifi_slot.menu.FlashFreq.40=40MHz -wifi_slot.menu.FlashFreq.40.build.flash_freq=40 -wifi_slot.menu.FlashFreq.80=80MHz -wifi_slot.menu.FlashFreq.80.build.flash_freq=80 -wifi_slot.menu.FlashMode.dout=DOUT (compatible) -wifi_slot.menu.FlashMode.dout.build.flash_mode=dout -wifi_slot.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT -wifi_slot.menu.FlashMode.dio=DIO -wifi_slot.menu.FlashMode.dio.build.flash_mode=dio -wifi_slot.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO -wifi_slot.menu.FlashMode.qout=QOUT -wifi_slot.menu.FlashMode.qout.build.flash_mode=qout -wifi_slot.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT -wifi_slot.menu.FlashMode.qio=QIO (fast) -wifi_slot.menu.FlashMode.qio.build.flash_mode=qio -wifi_slot.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO -wifi_slot.menu.eesz.1M=1M (no SPIFFS) -wifi_slot.menu.eesz.1M.build.flash_size=1M -wifi_slot.menu.eesz.1M.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -wifi_slot.menu.eesz.1M.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M.upload.maximum_size=1023984 -wifi_slot.menu.eesz.1M.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M64=1M (64K SPIFFS) -wifi_slot.menu.eesz.1M64.build.flash_size=1M -wifi_slot.menu.eesz.1M64.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -wifi_slot.menu.eesz.1M64.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M64.upload.maximum_size=958448 -wifi_slot.menu.eesz.1M64.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M64.build.spiffs_start=0xEB000 -wifi_slot.menu.eesz.1M64.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M64.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M128=1M (128K SPIFFS) -wifi_slot.menu.eesz.1M128.build.flash_size=1M -wifi_slot.menu.eesz.1M128.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -wifi_slot.menu.eesz.1M128.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M128.upload.maximum_size=892912 -wifi_slot.menu.eesz.1M128.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M128.build.spiffs_start=0xDB000 -wifi_slot.menu.eesz.1M128.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M128.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M144=1M (144K SPIFFS) -wifi_slot.menu.eesz.1M144.build.flash_size=1M -wifi_slot.menu.eesz.1M144.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -wifi_slot.menu.eesz.1M144.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M144.upload.maximum_size=876528 -wifi_slot.menu.eesz.1M144.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M144.build.spiffs_start=0xD7000 -wifi_slot.menu.eesz.1M144.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M144.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M160=1M (160K SPIFFS) -wifi_slot.menu.eesz.1M160.build.flash_size=1M -wifi_slot.menu.eesz.1M160.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -wifi_slot.menu.eesz.1M160.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M160.upload.maximum_size=860144 -wifi_slot.menu.eesz.1M160.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M160.build.spiffs_start=0xD3000 -wifi_slot.menu.eesz.1M160.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M160.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M192=1M (192K SPIFFS) -wifi_slot.menu.eesz.1M192.build.flash_size=1M -wifi_slot.menu.eesz.1M192.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -wifi_slot.menu.eesz.1M192.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M192.upload.maximum_size=827376 -wifi_slot.menu.eesz.1M192.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M192.build.spiffs_start=0xCB000 -wifi_slot.menu.eesz.1M192.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M192.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M256=1M (256K SPIFFS) -wifi_slot.menu.eesz.1M256.build.flash_size=1M -wifi_slot.menu.eesz.1M256.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -wifi_slot.menu.eesz.1M256.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M256.upload.maximum_size=761840 -wifi_slot.menu.eesz.1M256.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M256.build.spiffs_start=0xBB000 -wifi_slot.menu.eesz.1M256.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M256.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M512=1M (512K SPIFFS) -wifi_slot.menu.eesz.1M512.build.flash_size=1M -wifi_slot.menu.eesz.1M512.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -wifi_slot.menu.eesz.1M512.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M512.upload.maximum_size=499696 -wifi_slot.menu.eesz.1M512.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M512.build.spiffs_start=0x7B000 -wifi_slot.menu.eesz.1M512.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M512.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.2M=2M (no SPIFFS) -wifi_slot.menu.eesz.2M.build.flash_size=2M -wifi_slot.menu.eesz.2M.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld -wifi_slot.menu.eesz.2M.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M128=2M (128K SPIFFS) -wifi_slot.menu.eesz.2M128.build.flash_size=2M -wifi_slot.menu.eesz.2M128.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld -wifi_slot.menu.eesz.2M128.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M128.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M128.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M128.build.spiffs_start=0x1E0000 -wifi_slot.menu.eesz.2M128.build.spiffs_end=0x1FB000 -wifi_slot.menu.eesz.2M128.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.2M256=2M (256K SPIFFS) -wifi_slot.menu.eesz.2M256.build.flash_size=2M -wifi_slot.menu.eesz.2M256.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld -wifi_slot.menu.eesz.2M256.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M256.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M256.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M256.build.spiffs_start=0x1C0000 -wifi_slot.menu.eesz.2M256.build.spiffs_end=0x1FB000 -wifi_slot.menu.eesz.2M256.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.2M512=2M (512K SPIFFS) -wifi_slot.menu.eesz.2M512.build.flash_size=2M -wifi_slot.menu.eesz.2M512.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld -wifi_slot.menu.eesz.2M512.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M512.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M512.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M512.build.spiffs_start=0x180000 -wifi_slot.menu.eesz.2M512.build.spiffs_end=0x1FB000 -wifi_slot.menu.eesz.2M512.build.spiffs_blocksize=8192 -wifi_slot.menu.eesz.2M1M=2M (1M SPIFFS) -wifi_slot.menu.eesz.2M1M.build.flash_size=2M -wifi_slot.menu.eesz.2M1M.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld -wifi_slot.menu.eesz.2M1M.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M1M.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M1M.build.spiffs_start=0x100000 -wifi_slot.menu.eesz.2M1M.build.spiffs_end=0x1FB000 -wifi_slot.menu.eesz.2M1M.build.spiffs_blocksize=8192 -wifi_slot.menu.ip.lm2f=v2 Lower Memory -wifi_slot.menu.ip.lm2f.build.lwip_include=lwip2/include -wifi_slot.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -wifi_slot.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifi_slot.menu.ip.hb2f=v2 Higher Bandwidth -wifi_slot.menu.ip.hb2f.build.lwip_include=lwip2/include -wifi_slot.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -wifi_slot.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifi_slot.menu.ip.lm2n=v2 Lower Memory (no features) -wifi_slot.menu.ip.lm2n.build.lwip_include=lwip2/include -wifi_slot.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -wifi_slot.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifi_slot.menu.ip.hb2n=v2 Higher Bandwidth (no features) -wifi_slot.menu.ip.hb2n.build.lwip_include=lwip2/include -wifi_slot.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -wifi_slot.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifi_slot.menu.ip.lm6f=v2 IPv6 Lower Memory -wifi_slot.menu.ip.lm6f.build.lwip_include=lwip2/include -wifi_slot.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -wifi_slot.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifi_slot.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -wifi_slot.menu.ip.hb6f.build.lwip_include=lwip2/include -wifi_slot.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -wifi_slot.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifi_slot.menu.ip.hb1=v1.4 Higher Bandwidth -wifi_slot.menu.ip.hb1.build.lwip_lib=-llwip_gcc -wifi_slot.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -wifi_slot.menu.ip.src=v1.4 Compile from source -wifi_slot.menu.ip.src.build.lwip_lib=-llwip_src -wifi_slot.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -wifi_slot.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifi_slot.menu.dbg.Disabled=Disabled -wifi_slot.menu.dbg.Disabled.build.debug_port= -wifi_slot.menu.dbg.Serial=Serial -wifi_slot.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifi_slot.menu.dbg.Serial1=Serial1 -wifi_slot.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifi_slot.menu.lvl.None____=None -wifi_slot.menu.lvl.None____.build.debug_level= -wifi_slot.menu.lvl.SSL=SSL -wifi_slot.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifi_slot.menu.lvl.TLS_MEM=TLS_MEM -wifi_slot.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifi_slot.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -wifi_slot.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.lvl.HTTP_SERVER=HTTP_SERVER -wifi_slot.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -wifi_slot.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifi_slot.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifi_slot.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifi_slot.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.CORE=CORE -wifi_slot.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifi_slot.menu.lvl.WIFI=WIFI -wifi_slot.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifi_slot.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -wifi_slot.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifi_slot.menu.lvl.UPDATER=UPDATER -wifi_slot.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifi_slot.menu.lvl.OTA=OTA -wifi_slot.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifi_slot.menu.lvl.OOM=OOM -wifi_slot.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifi_slot.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -wifi_slot.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifi_slot.menu.wipe.none=Only Sketch -wifi_slot.menu.wipe.none.upload.erase_cmd= -wifi_slot.menu.wipe.sdk=Sketch + WiFi Settings -wifi_slot.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wifi_slot.menu.wipe.all=All Flash Contents -wifi_slot.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wifi_slot.menu.baud.115200=115200 -wifi_slot.menu.baud.115200.upload.speed=115200 -wifi_slot.menu.baud.9600=9600 -wifi_slot.menu.baud.9600.upload.speed=9600 -wifi_slot.menu.baud.57600=57600 -wifi_slot.menu.baud.57600.upload.speed=57600 -wifi_slot.menu.baud.230400.linux=230400 -wifi_slot.menu.baud.230400.macosx=230400 -wifi_slot.menu.baud.230400.upload.speed=230400 -wifi_slot.menu.baud.256000.windows=256000 -wifi_slot.menu.baud.256000.upload.speed=256000 -wifi_slot.menu.baud.460800.linux=460800 -wifi_slot.menu.baud.460800.macosx=460800 -wifi_slot.menu.baud.460800.upload.speed=460800 -wifi_slot.menu.baud.512000.windows=512000 -wifi_slot.menu.baud.512000.upload.speed=512000 -wifi_slot.menu.baud.921600=921600 -wifi_slot.menu.baud.921600.upload.speed=921600 - -############################################################## -wiolink.name=Seeed Wio Link -wiolink.build.board=ESP8266_WIO_LINK -wiolink.build.variant=wiolink -wiolink.upload.tool=esptool -wiolink.upload.maximum_data_size=81920 -wiolink.upload.wait_for_upload_port=true -wiolink.upload.erase_cmd= -wiolink.serial.disableDTR=true -wiolink.serial.disableRTS=true -wiolink.build.mcu=esp8266 -wiolink.build.core=esp8266 -wiolink.build.spiffs_pagesize=256 -wiolink.build.debug_port= -wiolink.build.debug_level= -wiolink.menu.xtal.80=80 MHz -wiolink.menu.xtal.80.build.f_cpu=80000000L -wiolink.menu.xtal.160=160 MHz -wiolink.menu.xtal.160.build.f_cpu=160000000L -wiolink.menu.vt.flash=Flash -wiolink.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wiolink.menu.vt.heap=Heap -wiolink.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wiolink.menu.vt.iram=IRAM -wiolink.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wiolink.menu.exception.disabled=Disabled -wiolink.menu.exception.disabled.build.exception_flags=-fno-exceptions -wiolink.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -wiolink.menu.exception.enabled=Enabled -wiolink.menu.exception.enabled.build.exception_flags=-fexceptions -wiolink.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -wiolink.upload.resetmethod=nodemcu -wiolink.build.flash_mode=qio -wiolink.build.flash_flags=-DFLASHMODE_QIO -wiolink.build.flash_freq=40 -wiolink.menu.eesz.4M=4M (no SPIFFS) -wiolink.menu.eesz.4M.build.flash_size=4M -wiolink.menu.eesz.4M.build.flash_size_bytes=0x400000 -wiolink.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -wiolink.menu.eesz.4M.build.spiffs_pagesize=256 -wiolink.menu.eesz.4M.upload.maximum_size=1044464 -wiolink.menu.eesz.4M.build.rfcal_addr=0x3FC000 -wiolink.menu.eesz.4M1M=4M (1M SPIFFS) -wiolink.menu.eesz.4M1M.build.flash_size=4M -wiolink.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -wiolink.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -wiolink.menu.eesz.4M1M.build.spiffs_pagesize=256 -wiolink.menu.eesz.4M1M.upload.maximum_size=1044464 -wiolink.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -wiolink.menu.eesz.4M1M.build.spiffs_start=0x300000 -wiolink.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -wiolink.menu.eesz.4M1M.build.spiffs_blocksize=8192 -wiolink.menu.eesz.4M2M=4M (2M SPIFFS) -wiolink.menu.eesz.4M2M.build.flash_size=4M -wiolink.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -wiolink.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -wiolink.menu.eesz.4M2M.build.spiffs_pagesize=256 -wiolink.menu.eesz.4M2M.upload.maximum_size=1044464 -wiolink.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -wiolink.menu.eesz.4M2M.build.spiffs_start=0x200000 -wiolink.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -wiolink.menu.eesz.4M2M.build.spiffs_blocksize=8192 -wiolink.menu.eesz.4M3M=4M (3M SPIFFS) -wiolink.menu.eesz.4M3M.build.flash_size=4M -wiolink.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -wiolink.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -wiolink.menu.eesz.4M3M.build.spiffs_pagesize=256 -wiolink.menu.eesz.4M3M.upload.maximum_size=1044464 -wiolink.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -wiolink.menu.eesz.4M3M.build.spiffs_start=0x100000 -wiolink.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -wiolink.menu.eesz.4M3M.build.spiffs_blocksize=8192 -wiolink.menu.ip.lm2f=v2 Lower Memory -wiolink.menu.ip.lm2f.build.lwip_include=lwip2/include -wiolink.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -wiolink.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wiolink.menu.ip.hb2f=v2 Higher Bandwidth -wiolink.menu.ip.hb2f.build.lwip_include=lwip2/include -wiolink.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -wiolink.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wiolink.menu.ip.lm2n=v2 Lower Memory (no features) -wiolink.menu.ip.lm2n.build.lwip_include=lwip2/include -wiolink.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -wiolink.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wiolink.menu.ip.hb2n=v2 Higher Bandwidth (no features) -wiolink.menu.ip.hb2n.build.lwip_include=lwip2/include -wiolink.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -wiolink.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wiolink.menu.ip.lm6f=v2 IPv6 Lower Memory -wiolink.menu.ip.lm6f.build.lwip_include=lwip2/include -wiolink.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -wiolink.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wiolink.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -wiolink.menu.ip.hb6f.build.lwip_include=lwip2/include -wiolink.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -wiolink.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wiolink.menu.ip.hb1=v1.4 Higher Bandwidth -wiolink.menu.ip.hb1.build.lwip_lib=-llwip_gcc -wiolink.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -wiolink.menu.ip.src=v1.4 Compile from source -wiolink.menu.ip.src.build.lwip_lib=-llwip_src -wiolink.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -wiolink.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wiolink.menu.dbg.Disabled=Disabled -wiolink.menu.dbg.Disabled.build.debug_port= -wiolink.menu.dbg.Serial=Serial -wiolink.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wiolink.menu.dbg.Serial1=Serial1 -wiolink.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wiolink.menu.lvl.None____=None -wiolink.menu.lvl.None____.build.debug_level= -wiolink.menu.lvl.SSL=SSL -wiolink.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -wiolink.menu.lvl.TLS_MEM=TLS_MEM -wiolink.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wiolink.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -wiolink.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.lvl.HTTP_SERVER=HTTP_SERVER -wiolink.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -wiolink.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wiolink.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wiolink.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -wiolink.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wiolink.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wiolink.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.CORE=CORE -wiolink.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -wiolink.menu.lvl.WIFI=WIFI -wiolink.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wiolink.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -wiolink.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wiolink.menu.lvl.UPDATER=UPDATER -wiolink.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wiolink.menu.lvl.OTA=OTA -wiolink.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -wiolink.menu.lvl.OOM=OOM -wiolink.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wiolink.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -wiolink.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wiolink.menu.wipe.none=Only Sketch -wiolink.menu.wipe.none.upload.erase_cmd= -wiolink.menu.wipe.sdk=Sketch + WiFi Settings -wiolink.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wiolink.menu.wipe.all=All Flash Contents -wiolink.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wiolink.menu.baud.115200=115200 -wiolink.menu.baud.115200.upload.speed=115200 -wiolink.menu.baud.9600=9600 -wiolink.menu.baud.9600.upload.speed=9600 -wiolink.menu.baud.57600=57600 -wiolink.menu.baud.57600.upload.speed=57600 -wiolink.menu.baud.230400.linux=230400 -wiolink.menu.baud.230400.macosx=230400 -wiolink.menu.baud.230400.upload.speed=230400 -wiolink.menu.baud.256000.windows=256000 -wiolink.menu.baud.256000.upload.speed=256000 -wiolink.menu.baud.460800.linux=460800 -wiolink.menu.baud.460800.macosx=460800 -wiolink.menu.baud.460800.upload.speed=460800 -wiolink.menu.baud.512000.windows=512000 -wiolink.menu.baud.512000.upload.speed=512000 -wiolink.menu.baud.921600=921600 -wiolink.menu.baud.921600.upload.speed=921600 - -############################################################## -espectro.name=ESPectro Core -espectro.build.board=ESP8266_ESPECTRO_CORE -espectro.build.variant=espectro -espectro.upload.tool=esptool -espectro.upload.maximum_data_size=81920 -espectro.upload.wait_for_upload_port=true -espectro.upload.erase_cmd= -espectro.serial.disableDTR=true -espectro.serial.disableRTS=true -espectro.build.mcu=esp8266 -espectro.build.core=esp8266 -espectro.build.spiffs_pagesize=256 -espectro.build.debug_port= -espectro.build.debug_level= -espectro.menu.xtal.80=80 MHz -espectro.menu.xtal.80.build.f_cpu=80000000L -espectro.menu.xtal.160=160 MHz -espectro.menu.xtal.160.build.f_cpu=160000000L -espectro.menu.vt.flash=Flash -espectro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espectro.menu.vt.heap=Heap -espectro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espectro.menu.vt.iram=IRAM -espectro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espectro.menu.exception.disabled=Disabled -espectro.menu.exception.disabled.build.exception_flags=-fno-exceptions -espectro.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espectro.menu.exception.enabled=Enabled -espectro.menu.exception.enabled.build.exception_flags=-fexceptions -espectro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espectro.upload.resetmethod=nodemcu -espectro.build.flash_mode=dio -espectro.build.flash_flags=-DFLASHMODE_DIO -espectro.build.flash_freq=40 -espectro.menu.eesz.4M=4M (no SPIFFS) -espectro.menu.eesz.4M.build.flash_size=4M -espectro.menu.eesz.4M.build.flash_size_bytes=0x400000 -espectro.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espectro.menu.eesz.4M.build.spiffs_pagesize=256 -espectro.menu.eesz.4M.upload.maximum_size=1044464 -espectro.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espectro.menu.eesz.4M1M=4M (1M SPIFFS) -espectro.menu.eesz.4M1M.build.flash_size=4M -espectro.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espectro.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espectro.menu.eesz.4M1M.build.spiffs_pagesize=256 -espectro.menu.eesz.4M1M.upload.maximum_size=1044464 -espectro.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espectro.menu.eesz.4M1M.build.spiffs_start=0x300000 -espectro.menu.eesz.4M1M.build.spiffs_end=0x3FB000 -espectro.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espectro.menu.eesz.4M2M=4M (2M SPIFFS) -espectro.menu.eesz.4M2M.build.flash_size=4M -espectro.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espectro.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espectro.menu.eesz.4M2M.build.spiffs_pagesize=256 -espectro.menu.eesz.4M2M.upload.maximum_size=1044464 -espectro.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espectro.menu.eesz.4M2M.build.spiffs_start=0x200000 -espectro.menu.eesz.4M2M.build.spiffs_end=0x3FB000 -espectro.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espectro.menu.eesz.4M3M=4M (3M SPIFFS) -espectro.menu.eesz.4M3M.build.flash_size=4M -espectro.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espectro.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espectro.menu.eesz.4M3M.build.spiffs_pagesize=256 -espectro.menu.eesz.4M3M.upload.maximum_size=1044464 -espectro.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espectro.menu.eesz.4M3M.build.spiffs_start=0x100000 -espectro.menu.eesz.4M3M.build.spiffs_end=0x3FB000 -espectro.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espectro.menu.ip.lm2f=v2 Lower Memory -espectro.menu.ip.lm2f.build.lwip_include=lwip2/include -espectro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espectro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espectro.menu.ip.hb2f=v2 Higher Bandwidth -espectro.menu.ip.hb2f.build.lwip_include=lwip2/include -espectro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espectro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espectro.menu.ip.lm2n=v2 Lower Memory (no features) -espectro.menu.ip.lm2n.build.lwip_include=lwip2/include -espectro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espectro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espectro.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espectro.menu.ip.hb2n.build.lwip_include=lwip2/include -espectro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espectro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espectro.menu.ip.lm6f=v2 IPv6 Lower Memory -espectro.menu.ip.lm6f.build.lwip_include=lwip2/include -espectro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espectro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espectro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espectro.menu.ip.hb6f.build.lwip_include=lwip2/include -espectro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espectro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espectro.menu.ip.hb1=v1.4 Higher Bandwidth -espectro.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espectro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espectro.menu.ip.src=v1.4 Compile from source -espectro.menu.ip.src.build.lwip_lib=-llwip_src -espectro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espectro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espectro.menu.dbg.Disabled=Disabled -espectro.menu.dbg.Disabled.build.debug_port= -espectro.menu.dbg.Serial=Serial -espectro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espectro.menu.dbg.Serial1=Serial1 -espectro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espectro.menu.lvl.None____=None -espectro.menu.lvl.None____.build.debug_level= -espectro.menu.lvl.SSL=SSL -espectro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espectro.menu.lvl.TLS_MEM=TLS_MEM -espectro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espectro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espectro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espectro.menu.lvl.HTTP_SERVER=HTTP_SERVER -espectro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espectro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espectro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espectro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espectro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espectro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espectro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espectro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espectro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.CORE=CORE -espectro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espectro.menu.lvl.WIFI=WIFI -espectro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espectro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espectro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espectro.menu.lvl.UPDATER=UPDATER -espectro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espectro.menu.lvl.OTA=OTA -espectro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espectro.menu.lvl.OOM=OOM -espectro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espectro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espectro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espectro.menu.wipe.none=Only Sketch -espectro.menu.wipe.none.upload.erase_cmd= -espectro.menu.wipe.sdk=Sketch + WiFi Settings -espectro.menu.wipe.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espectro.menu.wipe.all=All Flash Contents -espectro.menu.wipe.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espectro.menu.baud.115200=115200 -espectro.menu.baud.115200.upload.speed=115200 -espectro.menu.baud.9600=9600 -espectro.menu.baud.9600.upload.speed=9600 -espectro.menu.baud.57600=57600 -espectro.menu.baud.57600.upload.speed=57600 -espectro.menu.baud.230400.linux=230400 -espectro.menu.baud.230400.macosx=230400 -espectro.menu.baud.230400.upload.speed=230400 -espectro.menu.baud.256000.windows=256000 -espectro.menu.baud.256000.upload.speed=256000 -espectro.menu.baud.460800.linux=460800 -espectro.menu.baud.460800.macosx=460800 -espectro.menu.baud.460800.upload.speed=460800 -espectro.menu.baud.512000.windows=512000 -espectro.menu.baud.512000.upload.speed=512000 -espectro.menu.baud.921600=921600 -espectro.menu.baud.921600.upload.speed=921600 - From 54f7a63d000a162cf29fa7f42e8db970d72ee0dc Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sun, 17 Feb 2019 12:49:50 +0100 Subject: [PATCH 1024/2222] Delete platform.txt --- arduino/version 2.5.0-beta3/platform.txt | 154 ----------------------- 1 file changed, 154 deletions(-) delete mode 100644 arduino/version 2.5.0-beta3/platform.txt diff --git a/arduino/version 2.5.0-beta3/platform.txt b/arduino/version 2.5.0-beta3/platform.txt deleted file mode 100644 index a790bc6c0..000000000 --- a/arduino/version 2.5.0-beta3/platform.txt +++ /dev/null @@ -1,154 +0,0 @@ - -# ESP8266 platform -# ------------------------------ - -# For more info: -# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification - -name=ESP8266 Boards (2.5.0-beta3) -version=2.5.0-beta3 - - - -runtime.tools.signing={runtime.platform.path}/tools/signing.py - -compiler.warning_flags=-w -compiler.warning_flags.none=-w -compiler.warning_flags.default= -compiler.warning_flags.more=-Wall -compiler.warning_flags.all=-Wall -Wextra - -build.lwip_lib=-llwip_gcc -build.lwip_include=lwip/include -build.lwip_flags=-DLWIP_OPEN_SRC - -build.vtable_flags=-DVTABLES_IN_FLASH - -build.exception_flags=-fno-exceptions -build.stdcpp_lib=-lstdc++ - -#build.float=-u _printf_float -u _scanf_float -build.float= -build.led= - -compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/ -compiler.sdk.path={runtime.platform.path}/tools/sdk -compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf -compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" - -compiler.c.cmd=xtensa-lx106-elf-gcc -compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} - -compiler.S.cmd=xtensa-lx106-elf-gcc -compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls - -compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read - -compiler.c.elf.cmd=xtensa-lx106-elf-gcc -compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc - -compiler.cpp.cmd=xtensa-lx106-elf-g++ -compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections {build.exception_flags} - -compiler.as.cmd=xtensa-lx106-elf-as - -compiler.ar.cmd=xtensa-lx106-elf-ar -compiler.ar.flags=cru - -compiler.elf2hex.cmd=esptool -compiler.elf2hex.flags= - -compiler.size.cmd=xtensa-lx106-elf-size - -compiler.esptool.cmd=esptool -compiler.esptool.cmd.windows=esptool.exe - -# This can be overriden in boards.txt -build.extra_flags=-DESP8266 - -# These can be overridden in platform.local.txt -compiler.c.extra_flags= -compiler.c.elf.extra_flags= -compiler.S.extra_flags= -compiler.cpp.extra_flags= -compiler.ar.extra_flags= -compiler.objcopy.eep.extra_flags= -compiler.elf2hex.extra_flags= - -## generate file with git version number -## needs bash, git, and echo -recipe.hooks.core.prebuild.1.pattern=python "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h" - - - -## windows-compatible version without git -recipe.hooks.core.prebuild.1.pattern.windows=cmd.exe /c rem cannot sign on windows - - - -## Build the app.ld linker file -recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld" - -## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile S files -recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Create archives -recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" - -## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" - -## Create eeprom -recipe.objcopy.eep.pattern= - -## Create hex -#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" - -recipe.objcopy.hex.1.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec -recipe.objcopy.hex.2.pattern=python "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed" - -# No signing on Windows -recipe.objcopy.hex.1.pattern.windows="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec -recipe.objcopy.hex.2.pattern.windows= - -## Save hex -recipe.output.tmp_file={build.project_name}.bin -recipe.output.save_file={build.project_name}.{build.variant}.bin - -## Compute size -recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).* -recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* -#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* - -# ------------------------------ - -tools.esptool.cmd=esptool -tools.esptool.cmd.windows=esptool.exe -tools.esptool.path={runtime.tools.esptool.path} -tools.esptool.network_cmd=python -tools.esptool.network_cmd.windows=python.exe - -tools.esptool.upload.protocol=esp -tools.esptool.upload.params.verbose=-vv -tools.esptool.upload.params.quiet= -tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin" -tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" - -tools.mkspiffs.cmd=mkspiffs -tools.mkspiffs.cmd.windows=mkspiffs.exe -tools.mkspiffs.path={runtime.tools.mkspiffs.path} - -tools.espupload.cmd=python -tools.espupload.cmd.windows=python.exe -tools.espupload.path={runtime.platform.path}/tools -tools.espupload.upload.protocol=espupload -tools.espupload.upload.params.verbose= -tools.espupload.upload.params.quiet= -tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin" From 3f6db361875fc66833390569cc9b5a986e64e71f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 17 Feb 2019 14:43:07 +0100 Subject: [PATCH 1025/2222] Update xdrv_01_webserver.ino Fix 404 error --- sonoff/xdrv_01_webserver.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index b796de246..60e49407b 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -94,7 +94,7 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "function lc(p){" "la('?t='+p);" // ?t related to WebGetArg("t", tmp, sizeof(tmp)); "}" - "window.onload=la;"; + "window.onload=la();"; const char HTTP_SCRIPT_WIFI[] PROGMEM = "function c(l){" @@ -152,8 +152,9 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = const char HTTP_SCRIPT_MODULE_TEMPLATE[] PROGMEM = "var os;" "function sk(s,g){" // s = value, g = id and name - "var o=os.replace(/}1/g,\"
 " D_MODULE_PARAMETERS " " "" "

" D_MODULE_TYPE " ({mt)

"; -const char HTTP_FORM_MODULE_PULLUP[] PROGMEM = - "
" D_PULLUP_ENABLE "
"; const char HTTP_LNK_ITEM[] PROGMEM = "
{v} ({w}) {i} {r}%
"; @@ -1073,12 +1070,6 @@ void HandleModuleConfiguration(void) page += FPSTR(HTTP_HEAD_STYLE); page += FPSTR(HTTP_FORM_MODULE); page.replace(F("{mt"), AnyModuleName(MODULE)); - - if (my_module_flag.pullup) { - page += FPSTR(HTTP_FORM_MODULE_PULLUP); - page.replace(F("{r1"), (Settings.flag3.no_pullup) ? F(" checked") : F("")); - } - page += F("
"); for (uint8_t i = 0; i < sizeof(cmodule); i++) { if (ValidGPIO(i, cmodule.io[i])) { @@ -1104,11 +1095,6 @@ void ModuleSaveSettings(void) Settings.last_module = Settings.module; Settings.module = new_module; SetModuleType(); - if (Settings.last_module == new_module) { - if (my_module_flag.pullup) { - Settings.flag3.no_pullup = WebServer->hasArg("b1"); - } - } myio cmodule; ModuleGpios(&cmodule); String gpios = ""; From 4d0ab9448d736bb14672f88cd556c75607f03509 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 17 Feb 2019 16:43:52 +0100 Subject: [PATCH 1028/2222] Fix unsupported sensor ids Fix unsupported sensor ids popping up after a config restore --- sonoff/sonoff.ino | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ad16735db..4a62d5c88 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2316,17 +2316,23 @@ void GpioInit(void) baudrate = APP_BAUDRATE; } + for (uint8_t i = 0; i < sizeof(Settings.user_template.gp); i++) { + if ((Settings.user_template.gp.io[i] >= GPIO_SENSOR_END) && (Settings.user_template.gp.io[i] < GPIO_USER)) { + Settings.user_template.gp.io[i] = GPIO_USER; // Fix not supported sensor ids in template + } + } + myio def_gp; ModuleGpios(&def_gp); for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (Settings.my_gp.io[i] > GPIO_NONE) { + if ((Settings.my_gp.io[i] >= GPIO_SENSOR_END) && (Settings.my_gp.io[i] < GPIO_USER)) { + Settings.my_gp.io[i] = GPIO_NONE; // Fix not supported sensor ids in module + } + else if (Settings.my_gp.io[i] > GPIO_NONE) { my_module.io[i] = Settings.my_gp.io[i]; } if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < GPIO_USER)) { my_module.io[i] = def_gp.io[i]; - if (USER_MODULE == Settings.module) { - Settings.my_gp.io[i] = def_gp.io[i]; // Copy user template settings - } } } my_module_flag = ModuleFlag(); From 10bdb7c9751c27d4ece0fced2aa61a2a3c7fab9d Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 17 Feb 2019 18:45:58 +0000 Subject: [PATCH 1029/2222] mqtt password GUI aligned to revised wifi version --- sonoff/xdrv_02_mqtt.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 726dd2dee..64afb0ebd 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -877,7 +877,7 @@ const char HTTP_FORM_MQTT[] PROGMEM = "

" D_PORT " (" STR(MQTT_PORT) ")

" "

" D_CLIENT " ({m0)

" "

" D_USER " (" MQTT_USER ")

" - "

" D_PASSWORD "

" + "

" D_PASSWORD "

" "

" D_TOPIC " = %topic% (" MQTT_TOPIC ")

" "

" D_FULL_TOPIC " (" MQTT_FULLTOPIC ")

"; @@ -939,7 +939,7 @@ void MqttSaveSettings(void) WebGetArg("mu", tmp, sizeof(tmp)); strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user)); WebGetArg("mp", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.mqtt_pwd : tmp, sizeof(Settings.mqtt_pwd)); + strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? Settings.mqtt_pwd : tmp, sizeof(Settings.mqtt_pwd)); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_topic, Settings.mqtt_fulltopic); AddLog(LOG_LEVEL_INFO); From ba7c4cd49b44c003f25f83dbffd26b0f5b1bc509 Mon Sep 17 00:00:00 2001 From: localhost61 Date: Sun, 17 Feb 2019 21:32:07 +0100 Subject: [PATCH 1030/2222] fr-FR.h update --- sonoff/language/fr-FR.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 5a809d7d6..562d85e60 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -98,8 +98,8 @@ #define D_GAS "Gaz" #define D_GATEWAY "Passerelle" #define D_GROUP "Groupe" -#define D_HOST "Host" -#define D_HOSTNAME "Hostname" +#define D_HOST "Hôte" +#define D_HOSTNAME "Nom d'Hôte" #define D_HUMIDITY "Humidité" #define D_ILLUMINANCE "Éclairement" #define D_IMMEDIATE "immédiat" // Button immediate @@ -184,7 +184,7 @@ #define D_LEVEL_10 "level 1-0" #define D_LEVEL_01 "level 0-1" #define D_SERIAL_LOGGING_DISABLED "Journalisation série désactivée" -#define D_SYSLOG_LOGGING_REENABLED "Jounalisation syslog réactivée" +#define D_SYSLOG_LOGGING_REENABLED "Jounalisation SysLog réactivée" #define D_SET_BAUDRATE_TO "Définir le débit à" #define D_RECEIVED_TOPIC "Topic reçu" // Terme MQTT @@ -209,7 +209,7 @@ #define D_QUERY_DONE "Requête terminée. Services MQTT trouvés" #define D_MQTT_SERVICE_FOUND "Service MQTT trouvé sur" #define D_FOUND_AT "trouvé à" -#define D_SYSLOG_HOST_NOT_FOUND "Host syslog introuvable" +#define D_SYSLOG_HOST_NOT_FOUND "Hôte SysLog introuvable" // settings.ino #define D_SAVED_TO_FLASH_AT "Enregistré en flash à" @@ -281,10 +281,10 @@ #define D_LOGGING_PARAMETERS "Paramètres du journal" #define D_SERIAL_LOG_LEVEL "Niveau de journalisation série" #define D_WEB_LOG_LEVEL "Niveau de journalisation web" -#define D_SYS_LOG_LEVEL "Niveau Syslog" +#define D_SYS_LOG_LEVEL "Niveau SysLog" #define D_MORE_DEBUG "Plus de debug" -#define D_SYSLOG_HOST "Hôte Syslog" -#define D_SYSLOG_PORT "Port Syslog" +#define D_SYSLOG_HOST "Hôte SysLog" +#define D_SYSLOG_PORT "Port SysLog" #define D_TELEMETRY_PERIOD "Période télémétrie" #define D_OTHER_PARAMETERS "Autres paramètres" @@ -298,13 +298,13 @@ #define D_SINGLE_DEVICE "module unique" #define D_MULTI_DEVICE "multi module" -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" +#define D_CONFIGURE_TEMPLATE "Configuration du modèle" +#define D_TEMPLATE_PARAMETERS "Paramètres du modèle" +#define D_TEMPLATE_NAME "Nom" +#define D_BASE_TYPE "Basé sur" #define D_TEMPLATE_FLAGS "Flags" -#define D_ALLOW_ADC0 "ADC0 input" -#define D_ALLOW_PULLUP "User pull-up selection" +#define D_ALLOW_ADC0 "Entrée ADC0" +#define D_ALLOW_PULLUP "Choix de pull-up utilisateur" #define D_SAVE_CONFIGURATION "Enregistrer la configuration" #define D_CONFIGURATION_SAVED "Configuration enregistrée" @@ -341,7 +341,7 @@ #define D_UPLOAD_ERR_3 "L'octet magique n'est pas 0xE9" #define D_UPLOAD_ERR_4 "La taille du programme à flasher est plus grande que la taille réelle de la mémoire flash" #define D_UPLOAD_ERR_5 "Erreur de comparaison du buffer de téléchargement" -#define D_UPLOAD_ERR_6 "Téléchargement échoué. Activer Weblog 3" +#define D_UPLOAD_ERR_6 "Téléchargement échoué. Activer WebLog 3" #define D_UPLOAD_ERR_7 "Téléchargement annulé" #define D_UPLOAD_ERR_8 "Fichier invalide" #define D_UPLOAD_ERR_9 "Fichier trop grand" @@ -352,7 +352,7 @@ #define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement" #define D_ENTER_COMMAND "Saisir une commande" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Activer Weblog 2 si une réponse est attendue" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Activer WebLog 2 si une réponse est attendue" #define D_NEED_USER_AND_PASSWORD "Nécessite utilisateur=&password=" // xdrv_01_mqtt.ino @@ -493,7 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Aucun" -#define D_SENSOR_USER "User" +#define D_SENSOR_USER "Utilisateur" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" From deeceaf2a0b045988976a8850673be06864edf1e Mon Sep 17 00:00:00 2001 From: gfrancesco Date: Sun, 17 Feb 2019 22:05:02 +0100 Subject: [PATCH 1031/2222] Add configuration parameter to send MQTT telemetry on status change (SetOption59) --- sonoff/my_user_config.h | 1 + sonoff/settings.ino | 1 + 2 files changed, 2 insertions(+) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 5a7f3a14a..f0cd75cf6 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -122,6 +122,7 @@ // -- MQTT - Telemetry ---------------------------- #define TELE_PERIOD 300 // [TelePeriod] Telemetry (0 = disable, 10 - 3600 seconds) +#define TELE_ON_POWER 0 // [SetOption59] send tele/STATE together with stat/RESULT (0 = Disable, 1 = Enable) // -- MQTT - Domoticz ----------------------------- #define DOMOTICZ_UPDATE_TIMER 0 // [DomoticzUpdateTimer] Send relay status (0 = disable, 1 - 3600 seconds) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index e15701e0b..2fb9a9afa 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -661,6 +661,7 @@ void SettingsDefaultSet2(void) Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN; Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; Settings.flag3.button_switch_force_local = MQTT_BUTTON_SWITCH_FORCE_LOCAL; + Settings.flag3.hass_tele_on_power = TELE_ON_POWER; // Settings.flag.mqtt_sensor_retain = 0; // Settings.flag.mqtt_offline = 0; // Settings.flag.mqtt_serial = 0; From cee9fee75619371dea6d26dbdaa995cb8f16f5d2 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Mon, 18 Feb 2019 08:19:17 +0200 Subject: [PATCH 1032/2222] Make pwm scheme 0 sleep optional Make pwm scheme 0 sleep optional (enabled by default) --- sonoff/sonoff.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index b54a32f3c..790059450 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -104,6 +104,7 @@ typedef unsigned long power_t; // Power (Relay) type #define PWM_MIN 100 // [PWM_MIN] Minimum frequency - Default: 100 // For Dimmers use double of your mains AC frequecy (100 for 50Hz and 120 for 60Hz) // For Controlling Servos use 50 and also set PWM_FREQ as 50 (DO NOT USE THESE VALUES FOR DIMMERS) +//#define PWM_LIGHTSCHEME0_IGNORE_SLEEP // Do not change sleep value for LightAnimate() scheme 0 #define DEFAULT_POWER_DELTA 80 // Power change percentage #define MAX_POWER_HOLD 10 // Time in SECONDS to allow max agreed power From 5b71095e02cedbd870a19e549b972da268b8677e Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Mon, 18 Feb 2019 08:21:57 +0200 Subject: [PATCH 1033/2222] Make sleep for light scheme0 optional Make sleep for light scheme0 optional with compile directive (enabled by default) --- sonoff/xdrv_04_light.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 0b027335b..8a5259f64 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -896,7 +896,11 @@ void LightAnimate(void) } } else { +#ifdef PWM_LIGHTSCHEME0_IGNORE_SLEEP sleep = (LS_POWER == Settings.light_scheme) ? Settings.sleep : 0; // If no animation then use sleep as is +#else + sleep = 0; +#endif // PWM_LIGHTSCHEME0_IGNORE_SLEEP switch (Settings.light_scheme) { case LS_POWER: LightSetDimmer(Settings.light_dimmer); From 8c73cddfedecb56acfafbed3293d243f47695d1c Mon Sep 17 00:00:00 2001 From: znanev <20048364+znanev@users.noreply.github.com> Date: Mon, 18 Feb 2019 09:29:23 +0000 Subject: [PATCH 1034/2222] Update Bulgarian translations --- sonoff/language/bg-BG.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index d8b54ddea..b56d7fd01 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.4.0.1 + * Updated until v6.4.1.17 (up to commit 590c883b) \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -253,7 +253,7 @@ #define D_MODULE_PARAMETERS "Параметри на модула" #define D_MODULE_TYPE "Тип на модула" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_PULLUP_ENABLE "Без pull-up за бутон/ключ" #define D_GPIO "GPIO" #define D_SERIAL_IN "Сериен вход" #define D_SERIAL_OUT "Сериен изход" @@ -288,8 +288,8 @@ #define D_TELEMETRY_PERIOD "Период на телеметрия" #define D_OTHER_PARAMETERS "Други параметри" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" +#define D_TEMPLATE "Модел" +#define D_ACTIVATE "Активирай" #define D_WEB_ADMIN_PASSWORD "Парола на уеб администратора" #define D_MQTT_ENABLE "Активиране на MQTT" #define D_FRIENDLY_NAME "Приятелско име" @@ -298,13 +298,13 @@ #define D_SINGLE_DEVICE "Единично" #define D_MULTI_DEVICE "Мулти" -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" -#define D_ALLOW_ADC0 "ADC0 input" -#define D_ALLOW_PULLUP "User pull-up selection" +#define D_CONFIGURE_TEMPLATE "Конфигуриране на модел" +#define D_TEMPLATE_PARAMETERS "Параметри на модел" +#define D_TEMPLATE_NAME "Име" +#define D_BASE_TYPE "Базиран на" +#define D_TEMPLATE_FLAGS "Флагове" +#define D_ALLOW_ADC0 "ADC0 вход" +#define D_ALLOW_PULLUP "Потребителски избор на pull-up" #define D_SAVE_CONFIGURATION "Запазване на конфигурацията" #define D_CONFIGURATION_SAVED "Конфигурацията е запазена" @@ -493,7 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Няма" -#define D_SENSOR_USER "User" +#define D_SENSOR_USER "Потребителски" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" From bd582980e9c6eaa7f7c853fa3f1757b614e365b1 Mon Sep 17 00:00:00 2001 From: znanev <20048364+znanev@users.noreply.github.com> Date: Mon, 18 Feb 2019 09:52:29 +0000 Subject: [PATCH 1035/2222] Abbreviate translation for D_SENSOR_USER --- sonoff/language/bg-BG.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index b56d7fd01..626c0b1b8 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -493,7 +493,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Няма" -#define D_SENSOR_USER "Потребителски" +#define D_SENSOR_USER "Потребит." #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" From c37a4a43984a6d4bef17ef9d00d9d08dac4cdfb1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 18 Feb 2019 11:06:16 +0100 Subject: [PATCH 1036/2222] Update xsns_01_counter.ino Fix non floating point use function (#5265) --- sonoff/xsns_01_counter.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index d62885cc5..6fe0cf333 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -103,7 +103,7 @@ void CounterShow(bool json) dtostrfd((double)RtcSettings.pulse_counter[i] / 1000000, 6, counter); } else { dsxflg++; - dtostrfd(RtcSettings.pulse_counter[i], 0, counter); + snprintf_P(counter, sizeof(counter), PSTR("%lu"), RtcSettings.pulse_counter[i]); } if (json) { From 8d2b9e4734250d75a845c3d4998457563ea6ed0c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 18 Feb 2019 11:35:49 +0100 Subject: [PATCH 1037/2222] Update xdrv_01_webserver.ino Tune webserver --- sonoff/xdrv_01_webserver.ino | 141 +++++++++++++++++------------------ 1 file changed, 68 insertions(+), 73 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index df9764748..4817dde85 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -52,13 +52,13 @@ const char HTTP_HEAD[] PROGMEM = "{h} - {v}" ""; const char HTTP_SCRIPT_CONSOL[] PROGMEM = - "var sn=0;" // Scroll position - "var id=0;" // Get most of weblog initially - "function l(p){" // Console log and command service + "var sn=0;" // Scroll position + "var id=0;" // Get most of weblog initially + "function l(p){" // Console log and command service "var c,o,t;" "clearTimeout(lt);" "o='';" @@ -125,8 +125,8 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "c.value='';" "t.scrollTop=sn;" "}" - "if(t.scrollTop>=sn){" // User scrolled back so no updates - "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1) + "if(t.scrollTop>=sn){" // User scrolled back so no updates + "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1) "x=new XMLHttpRequest();" "x.onreadystatechange=function(){" "if(x.readyState==4&&x.status==200){" @@ -151,88 +151,83 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = const char HTTP_SCRIPT_MODULE_TEMPLATE[] PROGMEM = "var os;" - "function sk(s,g){" // s = value, g = id and name + "function sk(s,g){" // s = value, g = id and name "var o=os.replace(/}1/g,\"
"); - uint8_t idx = 0; - for (uint8_t i = 0; i < 4; i++) { - if (idx > 0) { page += F(""); } - for (uint8_t j = 0; j < 4; j++) { - idx++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), idx, idx); // ?k is related to WebGetArg("k", tmp, sizeof(tmp)); - page += mqtt_data; - } + } else { + for (uint8_t idx = 1; idx <= devices_present; idx++) { + snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, + 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); + page += mqtt_data; } - page += F("
\").replace(/}2/g,\"\");" "eb('i').innerHTML=s;" "}" From 483eb4dd44b3a75ed15acc0432e4a742f666c0c7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 18 Feb 2019 13:10:10 +0100 Subject: [PATCH 1038/2222] Change Flags to Options Change Flags to Options and enforce Activate for already active template (#5256) --- sonoff/language/cs-CZ.h | 2 +- sonoff/language/de-DE.h | 2 +- sonoff/language/el-GR.h | 2 +- sonoff/language/en-GB.h | 2 +- sonoff/language/es-AR.h | 2 +- sonoff/language/fr-FR.h | 2 +- sonoff/language/he-HE.h | 2 +- sonoff/language/hu-HU.h | 2 +- sonoff/language/it-IT.h | 2 +- sonoff/language/nl-NL.h | 2 +- sonoff/language/pl-PL.h | 2 +- sonoff/language/pt-BR.h | 2 +- sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 2 +- sonoff/language/sk-SK.h | 2 +- sonoff/language/sv-SE.h | 2 +- sonoff/language/tr-TR.h | 2 +- sonoff/language/uk-UK.h | 2 +- sonoff/language/zh-CN.h | 2 +- sonoff/language/zh-TW.h | 2 +- sonoff/xdrv_01_webserver.ino | 3 ++- 21 files changed, 22 insertions(+), 21 deletions(-) diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 769acfd0d..e9d17bb8e 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 1bc7b2ea7..ed3202919 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Vorlage Parameter" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "basiert auf" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "Nutzer pull-up Auswahl" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 3d96d4744..8e4cf7077 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 7d8f32e6b..794af57fa 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 1bc0f064c..9dc72cf7c 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 562d85e60..06ada0874 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Paramètres du modèle" #define D_TEMPLATE_NAME "Nom" #define D_BASE_TYPE "Basé sur" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "Entrée ADC0" #define D_ALLOW_PULLUP "Choix de pull-up utilisateur" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index deca89d18..8437e1a05 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index e9eed8025..393d250e7 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 8269441ae..0f35e92b2 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 00d658d0c..b8b159eff 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 14161f0be..5d2db7afc 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 013768607..94d7bea00 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 11f10f750..47dec4ea2 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index b3641c647..038ba6615 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 76fa89e7a..ff05b471d 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index eca87b7c7..9045b2e24 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index bb9aa1a4c..f971c9ba2 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 289e9292c..1557a0d78 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index f37a127de..4e3a7d9fd 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 5188db09b..f8526aa5b 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -302,7 +302,7 @@ #define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_NAME "Name" #define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Flags" +#define D_TEMPLATE_FLAGS "Options" #define D_ALLOW_ADC0 "ADC0 input" #define D_ALLOW_PULLUP "User pull-up selection" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 4817dde85..3370fda1f 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -368,7 +368,7 @@ const char HTTP_FORM_OTHER[] PROGMEM = "

" "
 " D_TEMPLATE " " "

" - "

" D_ACTIVATE "

" + "

" D_ACTIVATE "

" "
" "
" "" D_WEB_ADMIN_PASSWORD "

" @@ -1352,6 +1352,7 @@ void HandleOtherConfiguration(void) page += FPSTR(HTTP_FORM_OTHER); TemplateJson(); page.replace(F("{t1"), mqtt_data); + page.replace(F("{t2"), (USER_MODULE == Settings.module) ? F(" checked disabled") : F("")); page.replace(F("{r1"), (Settings.flag.mqtt_enabled) ? F(" checked") : F("")); uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; From a6c7e3b5f421e942f283e9384e87f33e76366b69 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 18 Feb 2019 15:13:37 +0100 Subject: [PATCH 1039/2222] Update xdrv_01_webserver.ino Force restart on any template change to fix page refresh hang (#5222) --- sonoff/xdrv_01_webserver.ino | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 3370fda1f..c78a47c57 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -185,7 +185,7 @@ const char HTTP_SCRIPT_TEMPLATE[] PROGMEM = "sk(g[i],j);" // Set GPIO "j++;" "}" - "for(i=0;i<1;i++){" // Supports 1 FLAG + "for(i=0;i<" STR(GPIO_FLAG_USED) ";i++){" "p=(g[13]>>i)&1;" "eb('c'+i).checked=p;" // Set FLAG checkboxes "}" @@ -886,9 +886,7 @@ void HandleTemplateConfiguration(void) if (WebServer->hasArg("save")) { TemplateSaveSettings(); - if (USER_MODULE == Settings.module) { - WebRestart(1); - } + WebRestart(1); return; } @@ -917,7 +915,6 @@ void HandleTemplateConfiguration(void) String page = AnyModuleName(module); // NAME: Generic -// page += F("}1'255'>" D_SENSOR_USER " (255)}2"); // GPIO: }1'255'>User (255)}2 for (uint8_t i = 0; i < sizeof(kGpioNiceList); i++) { // GPIO: }1'0'>None (0)}2}1'17'>Button1 (17)}2... if (1 == i) { @@ -932,7 +929,7 @@ void HandleTemplateConfiguration(void) mqtt_data[0] = '\0'; for (uint8_t i = 0; i < sizeof(cmodule); i++) { // 17,148,29,149,7,255,255,255,138,255,139,255,255 - if ((i < 6) || ((i > 8) && (i < 11)) || (i > 11)) { // Ignore flash pins GPIO06, 7, 8 and 11 + if ((i < 6) || ((i > 8) && (i != 11))) { // Ignore flash pins GPIO06, 7, 8 and 11 snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", cmodule.io[i]); } } @@ -953,9 +950,9 @@ void HandleTemplateConfiguration(void) page += FPSTR(HTTP_FORM_TEMPLATE); page += F("
"); for (uint8_t i = 0; i < 17; i++) { - if ((i < 6) || ((i > 8) && (i < 11)) || (i > 11)) { // Ignore flash pins GPIO06, 7, 8 and 11 + if ((i < 6) || ((i > 8) && (i != 11))) { // Ignore flash pins GPIO06, 7, 8 and 11 snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("" D_GPIO "%d"), - (0==i)?" style='width:80px'":"", i, ((9==i)||(10==i))? "ESP8285" :"", (0==i)?" style='width:176px'":"", i, i); + (0==i)?" style='width:74px'":"", i, ((9==i)||(10==i))? "ESP8285" :"", (0==i)?" style='width:176px'":"", i, i); page += mqtt_data; } } @@ -987,7 +984,7 @@ void TemplateSaveSettings(void) } uint8_t flag = 0; - for (uint8_t i = 0; i < 2; i++) { + for (uint8_t i = 0; i < GPIO_FLAG_USED; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("c%d"), i); uint8_t state = WebServer->hasArg(stemp) << i; // FLAG flag += state; From e898dc03e7d2ea09454817f2353ae6948bbd0774 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 18 Feb 2019 15:41:41 +0100 Subject: [PATCH 1040/2222] Add Wifi Link Connection Count Add Wifi Link Connection (Retry) count to state message. Always starts with 1 being the initial connection. --- sonoff/i18n.h | 1 + sonoff/sonoff.ino | 4 ++-- sonoff/support_wifi.ino | 10 +++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index a35161433..b5a7f7697 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -89,6 +89,7 @@ #define D_JSON_INFRARED "Infrared" #define D_JSON_UNKNOWN "Unknown" #define D_JSON_LIGHT "Light" +#define D_JSON_LINK_DOWN "LinkCount" #define D_JSON_LOCAL_TIME "Local" #define D_JSON_LOW "Low" #define D_JSON_MAC "Mac" diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 4a62d5c88..9e0f4530e 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1775,8 +1775,8 @@ void MqttShowState(void) MqttShowPWMState(); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d}}"), - mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI())); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_DOWN "\":%d}}"), + mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkDown()); } bool MqttShowSensor(void) diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 90f0584b7..138768138 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -49,6 +49,7 @@ using namespace axTLS; */ #include // Wifi, MQTT, Ota, WifiManager +uint32_t wifi_link_down = 0; uint8_t wifi_counter; uint8_t wifi_retry_init; uint8_t wifi_retry; @@ -222,7 +223,8 @@ void WifiBegin(uint8_t flag, uint8_t channel) delay(200); WiFi.mode(WIFI_STA); // Disable AP mode WiFiSetSleepMode(); -// if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); } +// if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); } // B/G/N +// if (WiFi.getPhyMode() != WIFI_PHY_MODE_11G) { WiFi.setPhyMode(WIFI_PHY_MODE_11G); } // B/G if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } // WiFi.setAutoReconnect(true); switch (flag) { @@ -339,6 +341,11 @@ void WifiBeginAfterScan() } } +uint32_t WifiLinkDown() +{ + return wifi_link_down; +} + void WifiSetState(uint8_t state) { if (state == global_state.wifi_down) { @@ -346,6 +353,7 @@ void WifiSetState(uint8_t state) rules_flag.wifi_connected = 1; } else { rules_flag.wifi_disconnected = 1; + wifi_link_down++; } } global_state.wifi_down = state ^1; From 0658ae19599e88432bbb20348f1d49279276acd7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 18 Feb 2019 16:19:46 +0100 Subject: [PATCH 1041/2222] Update sonoff_template.h Fix compile error --- sonoff/sonoff_template.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index bf900ac6b..462ec3b3f 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -335,6 +335,8 @@ typedef struct MYCFGIO { uint8_t io[MAX_GPIO_PIN - MIN_FLASH_PINS]; } mycfgio; +#define GPIO_FLAG_USED 1 // Currently only one flag used + #define GPIO_FLAG_ADC0 1 // Allow ADC0 when define USE_ADC_VCC is disabled #define GPIO_FLAG_SPARE01 2 // Allow input pull-up control using SetOption62 - Superseded by user template editing #define GPIO_FLAG_SPARE02 4 From 4884a94b6d643a40ca60bdd4a6638b82bb185b18 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 18 Feb 2019 17:05:25 +0100 Subject: [PATCH 1042/2222] Add LinkCount and MqttCount * Add property LinkCount to state and status 11 message representing number of Wifi Link re-connections * Add property MqttCount to status 6 message representing number of Mqtt re-connections --- sonoff/_changelog.ino | 2 ++ sonoff/i18n.h | 3 ++- sonoff/sonoff.ino | 8 ++++---- sonoff/support_wifi.ino | 8 ++++---- sonoff/xdrv_02_mqtt.ino | 7 +++++++ 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 8872f0e4a..ad30eb7f7 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -5,6 +5,8 @@ * Add rule expression enabled by define USE_EXPRESSION in my_user_config.h (#5210) * Add Configure Template menu option to GUI (#5222) * Remove command SetOption62 as it's functionality is replaced by user changing the device template (#5255) + * Add property LinkCount to state and status 11 message representing number of Wifi Link re-connections + * Add property MqttCount to status 6 message representing number of Mqtt re-connections * * 6.4.1.16 20190211 * Initial support for online template change using command Template or GUI Configure Other (#5177) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index b5a7f7697..d2e15e475 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -89,13 +89,14 @@ #define D_JSON_INFRARED "Infrared" #define D_JSON_UNKNOWN "Unknown" #define D_JSON_LIGHT "Light" -#define D_JSON_LINK_DOWN "LinkCount" +#define D_JSON_LINK_COUNT "LinkCount" #define D_JSON_LOCAL_TIME "Local" #define D_JSON_LOW "Low" #define D_JSON_MAC "Mac" #define D_JSON_MASK "Mask" #define D_JSON_MINIMAL "minimal" #define D_JSON_MODEL "Model" +#define D_JSON_MQTT_COUNT "MqttCount" #define D_JSON_NO "No" #define D_JSON_NOISE "Noise" #define D_JSON_NONE "None" diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 9e0f4530e..26198507b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1682,8 +1682,8 @@ void PublishStatus(uint8_t payload) } 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_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"MqttType\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), - Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, mqtt_client, Settings.mqtt_user, MqttLibraryType(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); + 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_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"MqttType\":%d,\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), + Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, mqtt_client, Settings.mqtt_user, MqttLibraryType(), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6")); } @@ -1775,8 +1775,8 @@ void MqttShowState(void) MqttShowPWMState(); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_DOWN "\":%d}}"), - mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkDown()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_COUNT "\":%d}}"), + mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount()); } bool MqttShowSensor(void) diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 138768138..ba3f81ac8 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -49,7 +49,7 @@ using namespace axTLS; */ #include // Wifi, MQTT, Ota, WifiManager -uint32_t wifi_link_down = 0; +uint16_t wifi_link_count = 0; uint8_t wifi_counter; uint8_t wifi_retry_init; uint8_t wifi_retry; @@ -341,9 +341,9 @@ void WifiBeginAfterScan() } } -uint32_t WifiLinkDown() +uint16_t WifiLinkCount() { - return wifi_link_down; + return wifi_link_count; } void WifiSetState(uint8_t state) @@ -351,9 +351,9 @@ void WifiSetState(uint8_t state) if (state == global_state.wifi_down) { if (state) { rules_flag.wifi_connected = 1; + wifi_link_count++; } else { rules_flag.wifi_disconnected = 1; - wifi_link_down++; } } global_state.wifi_down = state ^1; diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 64afb0ebd..fa681e309 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -73,6 +73,7 @@ const char kMqttCommands[] PROGMEM = D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|" D_CMND_BUTTONTOPIC "|" D_CMND_SWITCHTOPIC "|" D_CMND_BUTTONRETAIN "|" D_CMND_SWITCHRETAIN "|" D_CMND_POWERRETAIN "|" D_CMND_SENSORRETAIN ; +uint16_t mqtt_connect_count = 0; // MQTT re-connect count uint16_t mqtt_retry_counter = 1; // MQTT connection retry counter uint8_t mqtt_initial_connection_state = 2; // MQTT connection messages state bool mqtt_connected = false; // MQTT virtual connection status @@ -379,6 +380,11 @@ void MqttPublishPowerBlinkState(uint8_t device) /*********************************************************************************************/ +uint16_t MqttConnectCount() +{ + return mqtt_connect_count; +} + void MqttDisconnected(int state) { mqtt_connected = false; @@ -398,6 +404,7 @@ void MqttConnected(void) AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_CONNECTED)); mqtt_connected = true; mqtt_retry_counter = 0; + mqtt_connect_count++; GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_ONLINE)); From 3c3b5bb8ca1eaaa1684b6c042326a8fa2fdd9eb0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 18 Feb 2019 18:02:22 +0100 Subject: [PATCH 1043/2222] Add property Downtime Add property Downtime to state and status 11 message representing the duration of wifi connection loss --- sonoff/_changelog.ino | 1 + sonoff/i18n.h | 1 + sonoff/sonoff.ino | 4 ++-- sonoff/support_rtc.ino | 52 ++++++++++++++++++++++------------------- sonoff/support_wifi.ino | 11 ++++++++- 5 files changed, 42 insertions(+), 27 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index ad30eb7f7..a08bea0fc 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -7,6 +7,7 @@ * Remove command SetOption62 as it's functionality is replaced by user changing the device template (#5255) * Add property LinkCount to state and status 11 message representing number of Wifi Link re-connections * Add property MqttCount to status 6 message representing number of Mqtt re-connections + * Add property Downtime to state and status 11 message representing the duration of wifi connection loss * * 6.4.1.16 20190211 * Initial support for online template change using command Template or GUI Configure Other (#5177) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index d2e15e475..7340a3484 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -54,6 +54,7 @@ #define D_JSON_DISTANCE "Distance" #define D_JSON_DNSSERVER "DNSServer" #define D_JSON_DONE "Done" +#define D_JSON_DOWNTIME "Downtime" #define D_JSON_ECO2 "eCO2" #define D_JSON_EMPTY "Empty" #define D_JSON_ENDDST "EndDST" // End Daylight Savings Time diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 26198507b..e54c23260 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1775,8 +1775,8 @@ void MqttShowState(void) MqttShowPWMState(); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_COUNT "\":%d}}"), - mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount()); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), + mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount(), WifiDowntime().c_str()); } bool MqttShowSensor(void) diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index 12a4d89ec..5c9f9e2b4 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -87,6 +87,23 @@ String GetTimeZone(void) return String(tz); // -03:45 } +String GetDuration(uint32_t time) +{ + char dt[16]; + + TIME_T ut; + BreakTime(time, ut); + + // "P128DT14H35M44S" - ISO8601:2004 - https://en.wikipedia.org/wiki/ISO_8601 Durations +// snprintf_P(dt, sizeof(dt), PSTR("P%dDT%02dH%02dM%02dS"), ut.days, ut.hour, ut.minute, ut.second); + + // "128 14:35:44" - OpenVMS + // "128T14:35:44" - Tasmota + snprintf_P(dt, sizeof(dt), PSTR("%dT%02d:%02d:%02d"), ut.days, ut.hour, ut.minute, ut.second); + + return String(dt); // 128T14:35:44 +} + String GetDT(uint32_t time) { // "2017-03-07T11:08:02" - ISO8601:2004 @@ -155,37 +172,24 @@ String GetTime(int type) return String(stime); // Thu Nov 01 11:41:02 2018 } +uint32_t UpTime(void) +{ + if (restart_time) { + return utc_time - restart_time; + } else { + return uptime; + } +} + String GetUptime(void) { - char dt[16]; - - TIME_T ut; - - if (restart_time) { - BreakTime(utc_time - restart_time, ut); - } else { - BreakTime(uptime, ut); - } - - // "P128DT14H35M44S" - ISO8601:2004 - https://en.wikipedia.org/wiki/ISO_8601 Durations -// snprintf_P(dt, sizeof(dt), PSTR("P%dDT%02dH%02dM%02dS"), ut.days, ut.hour, ut.minute, ut.second); - - // "128 14:35:44" - OpenVMS - // "128T14:35:44" - Tasmota - snprintf_P(dt, sizeof(dt), PSTR("%dT%02d:%02d:%02d"), ut.days, ut.hour, ut.minute, ut.second); - - return String(dt); // 128T14:35:44 + return GetDuration(UpTime()); } uint32_t GetMinutesUptime(void) { TIME_T ut; - - if (restart_time) { - BreakTime(utc_time - restart_time, ut); - } else { - BreakTime(uptime, ut); - } + BreakTime(UpTime(), ut); return (ut.days *1440) + (ut.hour *60) + ut.minute; } diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index ba3f81ac8..c394005a1 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -49,7 +49,9 @@ using namespace axTLS; */ #include // Wifi, MQTT, Ota, WifiManager -uint16_t wifi_link_count = 0; +uint32_t wifi_last_event = 0; // Last wifi connection event +uint32_t wifi_downtime = 0; // Wifi down duration +uint16_t wifi_link_count = 0; // Number of wifi re-connect uint8_t wifi_counter; uint8_t wifi_retry_init; uint8_t wifi_retry; @@ -346,14 +348,21 @@ uint16_t WifiLinkCount() return wifi_link_count; } +String WifiDowntime() +{ + return GetDuration(wifi_downtime); +} + void WifiSetState(uint8_t state) { if (state == global_state.wifi_down) { if (state) { rules_flag.wifi_connected = 1; wifi_link_count++; + wifi_downtime += UpTime() - wifi_last_event; } else { rules_flag.wifi_disconnected = 1; + wifi_last_event = UpTime(); } } global_state.wifi_down = state ^1; From 1da8f94a05262f6e0878b9f619d24eac08e349fe Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 18 Feb 2019 21:52:22 +0200 Subject: [PATCH 1044/2222] Introduce Reset 6 --- sonoff/sonoff.ino | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index e54c23260..058631a15 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1309,7 +1309,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) case 2: case 3: case 4: - case 5: + case 5 ... 6: restart_flag = 210 + payload; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); break; @@ -2084,14 +2084,33 @@ void Every250mSeconds(void) } } if (restart_flag && (backlog_pointer == backlog_index)) { - if ((214 == restart_flag) || (215 == restart_flag)) { + if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) { char storage[sizeof(Settings.sta_ssid) + sizeof(Settings.sta_pwd)]; + char storage_mqtt_host[sizeof(Settings.mqtt_host)]; + uint16_t storage_mqtt_port; + char storage_mqtt_user[sizeof(Settings.mqtt_user)]; + char storage_mqtt_pwd[sizeof(Settings.mqtt_pwd)]; + char storage_mqtt_topic[sizeof(Settings.mqtt_topic)]; memcpy(storage, Settings.sta_ssid, sizeof(storage)); // Backup current SSIDs and Passwords - if (215 == restart_flag) { + if (216 == restart_flag) { + memcpy(storage_mqtt_host, Settings.mqtt_host, sizeof(Settings.mqtt_host)); + storage_mqtt_port = Settings.mqtt_port; + memcpy(storage_mqtt_user, Settings.mqtt_user, sizeof(Settings.mqtt_user)); + memcpy(storage_mqtt_pwd, Settings.mqtt_pwd, sizeof(Settings.mqtt_pwd)); + memcpy(storage_mqtt_topic, Settings.mqtt_topic, sizeof(Settings.mqtt_topic)); + } + if ((215 == restart_flag) || (216 == restart_flag)) { SettingsErase(0); // Erase all flash from program end to end of physical flash } SettingsDefault(); memcpy(Settings.sta_ssid, storage, sizeof(storage)); // Restore current SSIDs and Passwords + if (216 == restart_flag) { // Restore the mqtt host, port, username and password + memcpy(Settings.mqtt_host, storage_mqtt_host, sizeof(Settings.mqtt_host)); + Settings.mqtt_port = storage_mqtt_port; + memcpy(Settings.mqtt_user, storage_mqtt_user, sizeof(Settings.mqtt_user)); + memcpy(Settings.mqtt_pwd, storage_mqtt_pwd, sizeof(Settings.mqtt_pwd)); + memcpy(Settings.mqtt_topic, storage_mqtt_topic, sizeof(Settings.mqtt_topic)); + } restart_flag = 2; } else if (213 == restart_flag) { From c527d4dc995a2e7d4f88abc3ab05b62c82ad1446 Mon Sep 17 00:00:00 2001 From: Laurent <44267323+laurentdong@users.noreply.github.com> Date: Mon, 18 Feb 2019 15:41:40 -0500 Subject: [PATCH 1045/2222] Support HttpGet command HttpGet command send a HTTP Get request to specified URL and return the response from website or error message if failed. Note: This command support URL encoding, so you do not have to do encode by yourself. For example replacing all " " with %20 is no necessary. Format: httpget With HttpGet command you can do a lot of things. For example: - Retrieve your physical location: httpget http://ipinfo.io/geo Result is a JSON object { "ip": "8.8.8.8", "city": "Mountain View", "region": "California", "country": "US", "loc": "37.3860,-122.0840", "postal": "94035", "phone": "650" } - Control another Sonoff switch directly: httpget http://192.168.1.130/cm?cmnd=power off --- sonoff/i18n.h | 1 + sonoff/sonoff.ino | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 7340a3484..f601b1095 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -272,6 +272,7 @@ #define D_JSON_GPIO "GPIO" #define D_JSON_FLAG "FLAG" #define D_JSON_BASE "BASE" +#define D_CMND_HTTP_GET "HttpGet" // Commands xdrv_01_mqtt.ino #define D_CMND_MQTTHOST "MqttHost" diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index e54c23260..3ce445a4b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -75,7 +75,7 @@ enum TasmotaCommands { CMND_MODULE, CMND_MODULES, CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE, CMND_COUNTERDEBOUNCE, CMND_BUTTONDEBOUNCE, CMND_SWITCHDEBOUNCE, 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_INTERLOCK, CMND_TEMPLATE, + CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_INTERLOCK, CMND_TEMPLATE, CMND_HTTP_GET, CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_TIMESTD, CMND_TIMEDST, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER, CMND_DRIVER }; const char kTasmotaCommands[] PROGMEM = @@ -85,7 +85,7 @@ const char kTasmotaCommands[] PROGMEM = 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_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" 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_INTERLOCK "|" D_CMND_TEMPLATE "|" + D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TEMPLATE "|" D_CMND_HTTP_GET "|" D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER "|" D_CMND_DRIVER; @@ -1018,6 +1018,35 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.pwm_frequency); } + else if (CMND_HTTP_GET == command_code) { + //Test http get + if (data_len > 10 && strncasecmp_P(dataBuf, PSTR("HTTP://"),7) == 0) { + String sUrl = dataBuf; + String sResult = ""; + WiFiClient client; + HTTPClient http; + if (http.begin(client, UrlEncode(dataBuf))) { // HTTP + // start connection and send HTTP header + int httpCode = http.GET(); + + // httpCode will be negative on error + if (httpCode > 0) { + // HTTP header has been send and Server response header has been handled + // file found at server + if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { + sResult = http.getString(); + } + } else { + //Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); + sResult = http.errorToString(httpCode); + } + http.end(); + } else { + sResult = "[HTTP} Unable to connect\n"; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, sResult.c_str()); + } + } else if (CMND_PWMRANGE == command_code) { if ((1 == payload) || ((payload > 254) && (payload < 1024))) { Settings.pwm_range = (1 == payload) ? PWM_RANGE : payload; From 2bc84a9aad04762318eddcd53bec83348e7c45e3 Mon Sep 17 00:00:00 2001 From: Laurent <44267323+laurentdong@users.noreply.github.com> Date: Mon, 18 Feb 2019 16:12:14 -0500 Subject: [PATCH 1046/2222] Optimize RAM usage for Expression --- sonoff/xdrv_10_rules.ino | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 9603e549b..1e0c57ae6 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -625,7 +625,7 @@ bool findNextNumber(char * &pNumber, double &value) */ bool findNextVariableValue(char * &pVarname, double &value) { - bool succeed = false; + bool succeed = true; value = 0; String sVarName = ""; while (*pVarname) { @@ -637,32 +637,28 @@ bool findNextVariableValue(char * &pVarname, double &value) } } sVarName.toUpperCase(); - if (sVarName.startsWith("VAR")) { + if (sVarName.startsWith(F("VAR"))) { int index = sVarName.substring(3).toInt(); if (index > 0 && index <= MAX_RULE_VARS) { value = CharToDouble(vars[index -1]); - succeed = true; } - } else if (sVarName.startsWith("MEM")) { + } else if (sVarName.startsWith(F("MEM"))) { int index = sVarName.substring(3).toInt(); if (index > 0 && index <= MAX_RULE_MEMS) { value = CharToDouble(Settings.mems[index -1]); - succeed = true; } - } else if (sVarName.equals("TIME")) { + } else if (sVarName.equals(F("TIME"))) { value = GetMinutesPastMidnight(); - succeed = true; - } else if (sVarName.equals("UPTIME")) { + } else if (sVarName.equals(F("UPTIME"))) { value = GetMinutesUptime(); - succeed = true; #if defined(USE_TIMERS) && defined(USE_SUNRISE) - } else if (sVarName.equals("SUNRISE")) { + } else if (sVarName.equals(F("SUNRISE"))) { value = GetSunMinutes(0); - succeed = true; - } else if (sVarName.equals("SUNSET")) { + } else if (sVarName.equals(F("SUNSET"))) { value = GetSunMinutes(1); - succeed = true; #endif + } else { + succeed = false; } return succeed; From 6f2f0b6feae018ef1414fbbae3bac4e2586d999f Mon Sep 17 00:00:00 2001 From: Laurent <44267323+laurentdong@users.noreply.github.com> Date: Mon, 18 Feb 2019 16:17:32 -0500 Subject: [PATCH 1047/2222] Add two constant varibles in rules expression Add two variables: - UtcTime The number of seconds that have elapsed since January 1, 1970 (midnight UTC/GMT) - LocalTime Seconds passed after Jan 1, 1970 midnight base on current timezone and daylight saving setting. --- sonoff/support_rtc.ino | 5 +++++ sonoff/xdrv_10_rules.ino | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index 5c9f9e2b4..71fe7220c 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -331,6 +331,11 @@ uint32_t LocalTime(void) return local_time; } +uint32_t UtcTime(void) +{ + return utc_time; +} + uint32_t Midnight(void) { return midnight; diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 1e0c57ae6..1dfbb2a58 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -651,6 +651,10 @@ bool findNextVariableValue(char * &pVarname, double &value) value = GetMinutesPastMidnight(); } else if (sVarName.equals(F("UPTIME"))) { value = GetMinutesUptime(); + } else if (sVarName.equals(F("UTCTIME"))) { + value = UtcTime(); + } else if (sVarName.equals(F("LOCALTIME"))) { + value = LocalTime(); #if defined(USE_TIMERS) && defined(USE_SUNRISE) } else if (sVarName.equals(F("SUNRISE"))) { value = GetSunMinutes(0); From 660d0106c23b8bfba0348ef4bd7e07d4636f14aa Mon Sep 17 00:00:00 2001 From: Laurent <44267323+laurentdong@users.noreply.github.com> Date: Mon, 18 Feb 2019 16:18:01 -0500 Subject: [PATCH 1048/2222] Revert "Support HttpGet command" This reverts commit c527d4dc995a2e7d4f88abc3ab05b62c82ad1446. --- sonoff/i18n.h | 1 - sonoff/sonoff.ino | 33 ++------------------------------- 2 files changed, 2 insertions(+), 32 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index f601b1095..7340a3484 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -272,7 +272,6 @@ #define D_JSON_GPIO "GPIO" #define D_JSON_FLAG "FLAG" #define D_JSON_BASE "BASE" -#define D_CMND_HTTP_GET "HttpGet" // Commands xdrv_01_mqtt.ino #define D_CMND_MQTTHOST "MqttHost" diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 3ce445a4b..e54c23260 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -75,7 +75,7 @@ enum TasmotaCommands { CMND_MODULE, CMND_MODULES, CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE, CMND_COUNTERDEBOUNCE, CMND_BUTTONDEBOUNCE, CMND_SWITCHDEBOUNCE, 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_INTERLOCK, CMND_TEMPLATE, CMND_HTTP_GET, + CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_INTERLOCK, CMND_TEMPLATE, CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_TIMESTD, CMND_TIMEDST, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER, CMND_DRIVER }; const char kTasmotaCommands[] PROGMEM = @@ -85,7 +85,7 @@ const char kTasmotaCommands[] PROGMEM = 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_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" 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_INTERLOCK "|" D_CMND_TEMPLATE "|" D_CMND_HTTP_GET "|" + D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TEMPLATE "|" D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER "|" D_CMND_DRIVER; @@ -1018,35 +1018,6 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.pwm_frequency); } - else if (CMND_HTTP_GET == command_code) { - //Test http get - if (data_len > 10 && strncasecmp_P(dataBuf, PSTR("HTTP://"),7) == 0) { - String sUrl = dataBuf; - String sResult = ""; - WiFiClient client; - HTTPClient http; - if (http.begin(client, UrlEncode(dataBuf))) { // HTTP - // start connection and send HTTP header - int httpCode = http.GET(); - - // httpCode will be negative on error - if (httpCode > 0) { - // HTTP header has been send and Server response header has been handled - // file found at server - if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { - sResult = http.getString(); - } - } else { - //Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); - sResult = http.errorToString(httpCode); - } - http.end(); - } else { - sResult = "[HTTP} Unable to connect\n"; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, sResult.c_str()); - } - } else if (CMND_PWMRANGE == command_code) { if ((1 == payload) || ((payload > 254) && (payload < 1024))) { Settings.pwm_range = (1 == payload) ? PWM_RANGE : payload; From 32c1e2d13c9b6fc28a7a5fd80e0a5d1fdb614b03 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Feb 2019 10:48:19 +0100 Subject: [PATCH 1049/2222] Tuning uptime and add utctime Tuning uptime and add utctime --- sonoff/sonoff.ino | 5 +---- sonoff/support_rtc.ino | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 058631a15..55d218456 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1306,10 +1306,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) restart_flag = 211; snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command , D_JSON_RESET_AND_RESTARTING); break; - case 2: - case 3: - case 4: - case 5 ... 6: + case 2 ... 6: restart_flag = 210 + payload; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); break; diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index 5c9f9e2b4..e13dd540e 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -181,19 +181,16 @@ uint32_t UpTime(void) } } +uint32_t GetMinutesUptime(void) +{ + return (UpTime() / 60); +} + String GetUptime(void) { return GetDuration(UpTime()); } -uint32_t GetMinutesUptime(void) -{ - TIME_T ut; - BreakTime(UpTime(), ut); - - return (ut.days *1440) + (ut.hour *60) + ut.minute; -} - uint32_t GetMinutesPastMidnight(void) { uint32_t minutes = 0; @@ -326,6 +323,11 @@ uint32_t RuleToTime(TimeRule r, int yr) return t; } +uint32_t UtcTime(void) +{ + return utc_time; +} + uint32_t LocalTime(void) { return local_time; From 06c97c4e1954c7243493768b84bb7952eea0b158 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Feb 2019 12:51:38 +0100 Subject: [PATCH 1050/2222] Fix command WebSend Fix command WebSend intermittent results (#5273) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_01_webserver.ino | 89 +++++++++++++++++------------------- 2 files changed, 43 insertions(+), 47 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index a08bea0fc..0549b2576 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -8,6 +8,7 @@ * Add property LinkCount to state and status 11 message representing number of Wifi Link re-connections * Add property MqttCount to status 6 message representing number of Mqtt re-connections * Add property Downtime to state and status 11 message representing the duration of wifi connection loss + * Fix command WebSend intermittent results (#5273) * * 6.4.1.16 20190211 * Initial support for online template change using command Template or GUI Configure Other (#5177) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index c78a47c57..46b6ca6eb 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2146,23 +2146,22 @@ String UrlEncode(const String& text) int WebSend(char *buffer) { - /* [sonoff] POWER1 ON --> Sends http://sonoff/cm?cmnd=POWER1 ON - * [192.168.178.86:80,admin:joker] POWER1 ON --> Sends http://hostname:80/cm?user=admin&password=joker&cmnd=POWER1 ON - * [sonoff] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 - * [sonoff,admin:joker] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 - */ + // [sonoff] POWER1 ON --> Sends http://sonoff/cm?cmnd=POWER1 ON + // [192.168.178.86:80,admin:joker] POWER1 ON --> Sends http://hostname:80/cm?user=admin&password=joker&cmnd=POWER1 ON + // [sonoff] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 + // [sonoff,admin:joker] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 char *host; char *port; char *user; char *password; char *command; - uint16_t nport = 80; int status = 1; // Wrong parameters // buffer = | [ 192.168.178.86 : 80 , admin : joker ] POWER1 ON | host = strtok_r(buffer, "]", &command); // host = | [ 192.168.178.86 : 80 , admin : joker |, command = | POWER1 ON | if (host && command) { + String url = F("http:"); // url = |http:| host = Trim(host); // host = |[ 192.168.178.86 : 80 , admin : joker| host++; // host = | 192.168.178.86 : 80 , admin : joker| - Skip [ host = strtok_r(host, ",", &user); // host = | 192.168.178.86 : 80 |, user = | admin : joker| @@ -2170,66 +2169,62 @@ int WebSend(char *buffer) host = Trim(host); // host = |192.168.178.86| if (port) { port = Trim(port); // port = |80| - nport = atoi(port); + url += port; // url = |http:80| } + url += F("//"); // url = |http://| or |http:80//| + url += host; // url = |http://192.168.178.86| + if (user) { user = strtok_r(user, ":", &password); // user = | admin |, password = | joker| user = Trim(user); // user = |admin| if (password) { password = Trim(password); } // password = |joker| } + command = Trim(command); // command = |POWER1 ON| or |/any/link/starting/with/a/slash.php?log=123| - - String nuri = ""; if (command[0] != '/') { - nuri = "/cm?"; + url += F("/cm?"); // url = |http://192.168.178.86/cm?| if (user && password) { - nuri += F("user="); - nuri += user; - nuri += F("&password="); - nuri += password; - nuri += F("&"); + url += F("user="); // url = |http://192.168.178.86/cm?user=| + url += user; // url = |http://192.168.178.86/cm?user=admin| + url += F("&password="); // url = |http://192.168.178.86/cm?user=admin&password=| + url += password; // url = |http://192.168.178.86/cm?user=admin&password=joker| + url += F("&"); // url = |http://192.168.178.86/cm?user=admin&password=joker&| } - nuri += F("cmnd="); + url += F("cmnd="); // url = |http://192.168.178.86/cm?cmnd=| or |http://192.168.178.86/cm?user=admin&password=joker&cmnd=| } - nuri += command; - String uri = UrlEncode(nuri); + url += command; // url = |http://192.168.178.86/cm?cmnd=POWER1 ON| - IPAddress host_ip; - if (WiFi.hostByName(host, host_ip)) { - WiFiClient client; - - bool connected = false; - uint8_t retry = 2; - while ((retry > 0) && !connected) { - --retry; - connected = client.connect(host_ip, nport); - if (connected) break; - } - - if (connected) { - String url = F("GET "); - url += uri; - url += F(" HTTP/1.1\r\nHost: "); -// url += IPAddress(host_ip).toString(); - url += host; // https://tools.ietf.org/html/rfc7230#section-5.4 (#4331) - if (port) { - url += F(":"); - url += port; - } - url += F("\r\nConnection: close\r\n\r\n"); - -//snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Url |%s|"), url.c_str()); +//snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Uri |%s|"), url.c_str()); //AddLog(LOG_LEVEL_DEBUG); - client.print(url.c_str()); - client.flush(); - client.stop(); + HTTPClient http; + if (http.begin(UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON| + int http_code = http.GET(); // Start connection and send HTTP header + if (http_code > 0) { // http_code will be negative on error + if (http_code == HTTP_CODE_OK || http_code == HTTP_CODE_MOVED_PERMANENTLY) { +/* + // Return received data to the user - Adds 900+ bytes to the code + String result = http.getString(); // File found at server - may need lot of ram or trigger out of memory! + uint16_t j = 0; + for (uint16_t i = 0; i < result.length(); i++) { + char text = result.charAt(i); + if (text > 31) { // Remove control characters like linefeed + mqtt_data[j] = result.charAt(i); + j++; + if (j == sizeof(mqtt_data) -2) { break; } + } + } + mqtt_data[j] = '\0'; + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WEBSEND)); +*/ + } status = 0; // No error - Done } else { status = 2; // Connection failed } + http.end(); } else { - status = 3; // Host not found + status = 3; // Host not found or connection error } } return status; From 280dd25a8b65aa0f58ec1719ba290ec3d3cd7bcf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Feb 2019 14:49:15 +0100 Subject: [PATCH 1051/2222] Optimize RAM for expression Optimize RAM for expression and add two more constant variables (#5275) --- sonoff/support_rtc.ino | 4 +-- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_10_rules.ino | 56 +++++++++++++++++++-------------------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index e13dd540e..35f9b61e9 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -181,7 +181,7 @@ uint32_t UpTime(void) } } -uint32_t GetMinutesUptime(void) +uint32_t MinutesUptime(void) { return (UpTime() / 60); } @@ -191,7 +191,7 @@ String GetUptime(void) return GetDuration(UpTime()); } -uint32_t GetMinutesPastMidnight(void) +uint32_t MinutesPastMidnight(void) { uint32_t minutes = 0; diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 1b0f480fb..3c3b1f376 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -232,7 +232,7 @@ String GetSun(uint8_t dawn) return String(stime); } -uint16_t GetSunMinutes(uint8_t dawn) +uint16_t SunMinutes(uint8_t dawn) { uint8_t hour[2]; uint8_t minute[2]; diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 9603e549b..08c6c362b 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -185,11 +185,11 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) } snprintf_P(stemp, sizeof(stemp), PSTR("%%TIME%%")); if (rule_param.startsWith(stemp)) { - rule_param = String(GetMinutesPastMidnight()); + rule_param = String(MinutesPastMidnight()); } snprintf_P(stemp, sizeof(stemp), PSTR("%%UPTIME%%")); if (rule_param.startsWith(stemp)) { - rule_param = String(GetMinutesUptime()); + rule_param = String(MinutesUptime()); } snprintf_P(stemp, sizeof(stemp), PSTR("%%TIMESTAMP%%")); if (rule_param.startsWith(stemp)) { @@ -198,11 +198,11 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) #if defined(USE_TIMERS) && defined(USE_SUNRISE) snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNRISE%%")); if (rule_param.startsWith(stemp)) { - rule_param = String(GetSunMinutes(0)); + rule_param = String(SunMinutes(0)); } snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNSET%%")); if (rule_param.startsWith(stemp)) { - rule_param = String(GetSunMinutes(1)); + rule_param = String(SunMinutes(1)); } #endif // USE_TIMERS and USE_SUNRISE rule_param.toUpperCase(); @@ -347,12 +347,12 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) snprintf_P(stemp, sizeof(stemp), PSTR("%%mem%d%%"), i +1); commands.replace(stemp, Settings.mems[i]); } - commands.replace(F("%time%"), String(GetMinutesPastMidnight())); - commands.replace(F("%uptime%"), String(GetMinutesUptime())); + commands.replace(F("%time%"), String(MinutesPastMidnight())); + commands.replace(F("%uptime%"), String(MinutesUptime())); commands.replace(F("%timestamp%"), GetDateAndTime(DT_LOCAL).c_str()); #if defined(USE_TIMERS) && defined(USE_SUNRISE) - commands.replace(F("%sunrise%"), String(GetSunMinutes(0))); - commands.replace(F("%sunset%"), String(GetSunMinutes(1))); + commands.replace(F("%sunrise%"), String(SunMinutes(0))); + commands.replace(F("%sunset%"), String(SunMinutes(1))); #endif // USE_TIMERS and USE_SUNRISE char command[commands.length() +1]; @@ -505,8 +505,8 @@ void RulesEvery50ms(void) json_event[0] = '\0'; switch (i) { case 0: strncpy_P(json_event, PSTR("{\"System\":{\"Boot\":1}}"), sizeof(json_event)); break; - case 1: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Initialized\":%d}}"), GetMinutesPastMidnight()); break; - case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), GetMinutesPastMidnight()); break; + case 1: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Initialized\":%d}}"), MinutesPastMidnight()); break; + case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), MinutesPastMidnight()); break; case 3: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Connected\":1}}"), sizeof(json_event)); break; case 4: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Disconnected\":1}}"), sizeof(json_event)); break; case 5: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Connected\":1}}"), sizeof(json_event)); break; @@ -549,7 +549,7 @@ void RulesEverySecond(void) if (RtcTime.valid) { if ((uptime > 60) && (RtcTime.minute != rules_last_minute)) { // Execute from one minute after restart every minute only once rules_last_minute = RtcTime.minute; - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Minute\":%d}}"), GetMinutesPastMidnight()); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Minute\":%d}}"), MinutesPastMidnight()); RulesProcessEvent(json_event); } } @@ -625,7 +625,7 @@ bool findNextNumber(char * &pNumber, double &value) */ bool findNextVariableValue(char * &pVarname, double &value) { - bool succeed = false; + bool succeed = true; value = 0; String sVarName = ""; while (*pVarname) { @@ -637,32 +637,32 @@ bool findNextVariableValue(char * &pVarname, double &value) } } sVarName.toUpperCase(); - if (sVarName.startsWith("VAR")) { + if (sVarName.startsWith(F("VAR"))) { int index = sVarName.substring(3).toInt(); if (index > 0 && index <= MAX_RULE_VARS) { value = CharToDouble(vars[index -1]); - succeed = true; } - } else if (sVarName.startsWith("MEM")) { + } else if (sVarName.startsWith(F("MEM"))) { int index = sVarName.substring(3).toInt(); if (index > 0 && index <= MAX_RULE_MEMS) { value = CharToDouble(Settings.mems[index -1]); - succeed = true; } - } else if (sVarName.equals("TIME")) { - value = GetMinutesPastMidnight(); - succeed = true; - } else if (sVarName.equals("UPTIME")) { - value = GetMinutesUptime(); - succeed = true; + } else if (sVarName.equals(F("TIME"))) { + value = MinutesPastMidnight(); + } else if (sVarName.equals(F("UPTIME"))) { + value = MinutesUptime(); + } else if (sVarName.equals(F("UTCTIME"))) { + value = UtcTime(); + } else if (sVarName.equals(F("LOCALTIME"))) { + value = LocalTime(); #if defined(USE_TIMERS) && defined(USE_SUNRISE) - } else if (sVarName.equals("SUNRISE")) { - value = GetSunMinutes(0); - succeed = true; - } else if (sVarName.equals("SUNSET")) { - value = GetSunMinutes(1); - succeed = true; + } else if (sVarName.equals(F("SUNRISE"))) { + value = SunMinutes(0); + } else if (sVarName.equals(F("SUNSET"))) { + value = SunMinutes(1); #endif + } else { + succeed = false; } return succeed; From 51227b1d951476effa4458e3566e31563f6f1312 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Wed, 20 Feb 2019 21:07:01 +0100 Subject: [PATCH 1052/2222] Update platformio.ini --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index f5d958ebf..21816c3ab 100644 --- a/platformio.ini +++ b/platformio.ini @@ -65,8 +65,8 @@ build_flags = ${esp82xx_defaults.build_flags} -DVTABLES_IN_FLASH [core_2_5_0] -; *** Esp8266 core for Arduino version 2.5.0 release (still not available via platformio) -platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota +; *** Esp8266 core for Arduino version 2.5.0 +platform = espressif8266@2.0.0 build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld ; lwIP 1.4 (Default) From cfd3f3f4f5dd095e9cc1c294c905b48be2a5e7cc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 21 Feb 2019 09:48:58 +0100 Subject: [PATCH 1053/2222] Fix WebSend compile warning Fix WebSend compile warning --- sonoff/xdrv_01_webserver.ino | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 46b6ca6eb..2bdf55248 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2179,7 +2179,7 @@ int WebSend(char *buffer) user = Trim(user); // user = |admin| if (password) { password = Trim(password); } // password = |joker| } - + command = Trim(command); // command = |POWER1 ON| or |/any/link/starting/with/a/slash.php?log=123| if (command[0] != '/') { url += F("/cm?"); // url = |http://192.168.178.86/cm?| @@ -2197,8 +2197,14 @@ int WebSend(char *buffer) //snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Uri |%s|"), url.c_str()); //AddLog(LOG_LEVEL_DEBUG); +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) HTTPClient http; if (http.begin(UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON| +#else + WiFiClient http_client; + HTTPClient http; + if (http.begin(client, UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON| +#endif int http_code = http.GET(); // Start connection and send HTTP header if (http_code > 0) { // http_code will be negative on error if (http_code == HTTP_CODE_OK || http_code == HTTP_CODE_MOVED_PERMANENTLY) { @@ -2209,8 +2215,7 @@ int WebSend(char *buffer) for (uint16_t i = 0; i < result.length(); i++) { char text = result.charAt(i); if (text > 31) { // Remove control characters like linefeed - mqtt_data[j] = result.charAt(i); - j++; + mqtt_data[j++] = text; if (j == sizeof(mqtt_data) -2) { break; } } } @@ -2222,7 +2227,7 @@ int WebSend(char *buffer) } else { status = 2; // Connection failed } - http.end(); + http.end(); // Clean up connection data } else { status = 3; // Host not found or connection error } From 05b02800198a1ef592c0bc6099a6c8cefc239e83 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 21 Feb 2019 14:31:31 +0100 Subject: [PATCH 1054/2222] 6.4.1.18 - Fix some exceptions and watchdogs 6.4.1.18 20191221 * Fix some exceptions and watchdogs due to lack of stack space - part 1 (#5215) --- sonoff/_changelog.ino | 5 ++++- sonoff/sonoff.ino | 40 ++++++------------------------------ sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 36 ++++++++++++++++++++++++++++++++ sonoff/xdrv_01_webserver.ino | 2 ++ 5 files changed, 49 insertions(+), 36 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0549b2576..0d4fef299 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.17 20190214 +/* 6.4.1.18 20191221 + * Fix some exceptions and watchdogs due to lack of stack space - part 1 (#5215) + * + * 6.4.1.17 20190214 * Change template update by removing possibility to add user module config keeping template as defined (#5222) * Fix regression from 6.4.1.16 where GPIO9 and GPIO10 connected devices did not work (#5197) * Fix GUI wifi password acception starting with asteriks (*) (#5231, #5242) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 55d218456..39f0d7e0b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -963,41 +963,12 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } } } - else if (data_len > 9) { // Workaround exception if empty JSON like {} - Needs checks - StaticJsonBuffer<350> jb; // 331 from https://arduinojson.org/v5/assistant/ - JsonObject& obj = jb.parseObject(dataBuf); - if (!obj.success()) { + else if (data_len > 9) { // Workaround exception if empty JSON like {} - Needs checks + if (JsonTemplate(dataBuf)) { // Free 336 bytes StaticJsonBuffer stack space by moving code to function + if (USER_MODULE == Settings.module) { restart_flag = 2; } + } else { snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); error = true; - } else { - // All parameters are optional allowing for partial changes - const char* name = obj[D_JSON_NAME]; - if (name != nullptr) { - strlcpy(Settings.user_template.name, name, sizeof(Settings.user_template.name)); - } - if (obj[D_JSON_GPIO].success()) { - for (uint8_t i = 0; i < sizeof(mycfgio); i++) { - Settings.user_template.gp.io[i] = obj[D_JSON_GPIO][i] | 0; - } - } - if (obj[D_JSON_FLAG].success()) { - uint8_t flag = obj[D_JSON_FLAG] | 0; - memcpy(&Settings.user_template.flag, &flag, sizeof(gpio_flag)); - } - if (obj[D_JSON_BASE].success()) { - uint8_t base = obj[D_JSON_BASE]; - if ((0 == base) || (base >= MAXMODULE)) { base = 17; } else { base--; } - Settings.user_template_base = base; // Default WEMOS - } - - // Validate GPIO -// for (uint8_t i = 0; i < sizeof(mycfgio); i++) { - // For now do not allow non-user configurable GPIO -// if ((Settings.user_template.gp.io[i] > GPIO_FIX_START) && (Settings.user_template.gp.io[i] < GPIO_USER)) { -// Settings.user_template.gp.io[i] = GPIO_NONE; -// }; -// } - if (USER_MODULE == Settings.module) { restart_flag = 2; } } } if (!error) { TemplateJson(); } @@ -2223,7 +2194,8 @@ void ArduinoOTAInit(void) void SerialInput(void) { while (Serial.available()) { - yield(); +// yield(); + delay(0); serial_in_byte = Serial.read(); /*-------------------------------------------------------------------------------------------*\ diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 3816029fd..bba08f9de 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040111 +#define VERSION 0x06040112 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index d37185e3f..113968974 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -845,6 +845,42 @@ bool GetUsedInModule(uint8_t val, uint8_t *arr) return false; } +bool JsonTemplate(const char* dataBuf) +{ + StaticJsonBuffer<350> jb; // 331 from https://arduinojson.org/v5/assistant/ + JsonObject& obj = jb.parseObject(dataBuf); + if (!obj.success()) { return false; } + + // All parameters are optional allowing for partial changes + const char* name = obj[D_JSON_NAME]; + if (name != nullptr) { + strlcpy(Settings.user_template.name, name, sizeof(Settings.user_template.name)); + } + if (obj[D_JSON_GPIO].success()) { + for (uint8_t i = 0; i < sizeof(mycfgio); i++) { + Settings.user_template.gp.io[i] = obj[D_JSON_GPIO][i] | 0; + } + } + if (obj[D_JSON_FLAG].success()) { + uint8_t flag = obj[D_JSON_FLAG] | 0; + memcpy(&Settings.user_template.flag, &flag, sizeof(gpio_flag)); + } + if (obj[D_JSON_BASE].success()) { + uint8_t base = obj[D_JSON_BASE]; + if ((0 == base) || (base >= MAXMODULE)) { base = 17; } else { base--; } + Settings.user_template_base = base; // Default WEMOS + } + + // Validate GPIO +// for (uint8_t i = 0; i < sizeof(mycfgio); i++) { + // For now do not allow non-user configurable GPIO +// if ((Settings.user_template.gp.io[i] > GPIO_FIX_START) && (Settings.user_template.gp.io[i] < GPIO_USER)) { +// Settings.user_template.gp.io[i] = GPIO_NONE; +// }; +// } + return true; +} + void TemplateJson() { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 2bdf55248..e8aab33db 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1968,6 +1968,7 @@ void HandleHttpCommand(void) if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O]) if (message.length() > 1) { message += F(","); } size_t JSONlen = len - (JSON - tmp); + if (JSONlen > sizeof(mqtt_data)) { JSONlen = sizeof(mqtt_data); } strlcpy(mqtt_data, JSON +1, JSONlen -2); message += mqtt_data; } @@ -2047,6 +2048,7 @@ void HandleAjaxConsoleRefresh(void) } else { cflg = true; } + if (len > sizeof(mqtt_data) -2) { len = sizeof(mqtt_data); } strlcpy(mqtt_data, tmp, len); message += mqtt_data; // mqtt_data used as scratch space } From 95da493325fbad0be9e88f950f6bc0c3a51c90e6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 21 Feb 2019 14:56:39 +0100 Subject: [PATCH 1055/2222] Update xdrv_01_webserver.ino Fix compile error --- sonoff/xdrv_01_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index e8aab33db..a056c48ef 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2205,7 +2205,7 @@ int WebSend(char *buffer) #else WiFiClient http_client; HTTPClient http; - if (http.begin(client, UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON| + if (http.begin(http_client, UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON| #endif int http_code = http.GET(); // Start connection and send HTTP header if (http_code > 0) { // http_code will be negative on error From eb08bb07ee2c37aaa1a73b70746655cc0ec9ecef Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Thu, 21 Feb 2019 15:37:46 +0100 Subject: [PATCH 1056/2222] decode-config.py: adapt settings - remove SetOption62 (no_pullup) - remove obsolete Tasmota command converter --- tools/decode-config.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 642c31954..0b76ece85 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -866,11 +866,15 @@ Setting_6_4_1_16.update({ 'pullup': ('B', (0x73C,1,1), (None, None, ('Management', None)) ), }, 0x73C, (None, None, ('Management', None)) ), - }, 0x720, (None, None, ('Management', '"Template GPIO:{}".format(@["user_template"]["gp"][0])')) + }, 0x720, (None, None, ('Management', None)) ), }) # ====================================================================== +Setting_6_4_1_17 = copy.deepcopy(Setting_6_4_1_16) +Setting_6_4_1_17['flag3'][0].pop('no_pullup',None) +# ====================================================================== Settings = [ + (0x6040111, 0xe00, Setting_6_4_1_17), (0x6040110, 0xe00, Setting_6_4_1_16), (0x604010D, 0xe00, Setting_6_4_1_13), (0x604010B, 0xe00, Setting_6_4_1_11), From 3c58f5b7b9a3fe937f6365f4a2d461b1a267693e Mon Sep 17 00:00:00 2001 From: netpok Date: Thu, 21 Feb 2019 15:53:29 +0100 Subject: [PATCH 1057/2222] Add password validation to password command --- sonoff/sonoff.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 39f0d7e0b..24a3d5723 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1144,7 +1144,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.sta_ssid[index -1]); } else if ((CMND_PASSWORD == command_code) && (index > 0) && (index <= 2)) { - if ((data_len > 0) && (data_len < sizeof(Settings.sta_pwd[0]))) { + if ((data_len > 4 || SC_CLEAR == Shortcut(dataBuf) || SC_DEFAULT == Shortcut(dataBuf)) && (data_len < sizeof(Settings.sta_pwd[0]))) { strlcpy(Settings.sta_pwd[index -1], (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? (1 == index) ? STA_PASS1 : STA_PASS2 : dataBuf, sizeof(Settings.sta_pwd[0])); Settings.sta_active = index -1; restart_flag = 2; From e035a3253a0b23fb69dd3466ce633c79da1517a9 Mon Sep 17 00:00:00 2001 From: netpok Date: Thu, 21 Feb 2019 15:58:37 +0100 Subject: [PATCH 1058/2222] Add password validation to WebUI --- sonoff/xdrv_01_webserver.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index a056c48ef..8c9f373a8 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1236,9 +1236,9 @@ void WifiSaveSettings(void) WebGetArg("s2", tmp, sizeof(tmp)); strlcpy(Settings.sta_ssid[1], (!strlen(tmp)) ? STA_SSID2 : tmp, sizeof(Settings.sta_ssid[1])); WebGetArg("p1", tmp, sizeof(tmp)); - strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (!strcmp(tmp,D_ASTERISK_PWD)) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); + strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); WebGetArg("p2", tmp, sizeof(tmp)); - strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (!strcmp(tmp,D_ASTERISK_PWD)) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); + strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s"), Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1]); AddLog(LOG_LEVEL_INFO); @@ -2181,7 +2181,7 @@ int WebSend(char *buffer) user = Trim(user); // user = |admin| if (password) { password = Trim(password); } // password = |joker| } - + command = Trim(command); // command = |POWER1 ON| or |/any/link/starting/with/a/slash.php?log=123| if (command[0] != '/') { url += F("/cm?"); // url = |http://192.168.178.86/cm?| From 4993d16ecb1c19a2c182b6405297c51efc2a5335 Mon Sep 17 00:00:00 2001 From: netpok Date: Thu, 21 Feb 2019 17:49:11 +0100 Subject: [PATCH 1059/2222] Implement WifiConfig 7 --- sonoff/sonoff.h | 2 +- sonoff/support_wifi.ino | 4 +- sonoff/xdrv_01_webserver.ino | 223 +++++++++++++++++++---------------- 3 files changed, 124 insertions(+), 105 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 790059450..c86733621 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -212,7 +212,7 @@ enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_RESTART, DT_ENERGY }; enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; -enum WifiConfigOptions {WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, MAX_WIFI_OPTION}; +enum WifiConfigOptions {WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, WIFI_MANAGER_RESET_ONLY, MAX_WIFI_OPTION}; enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION}; diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index c394005a1..23f4b20c1 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -174,9 +174,9 @@ void WifiConfig(uint8_t type) } #endif // USE_WPS #ifdef USE_WEBSERVER - else if (WIFI_MANAGER == wifi_config_type) { + else if (WIFI_MANAGER == wifi_config_type || WIFI_MANAGER_RESET_ONLY == wifi_config_type) { AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_2_WIFIMANAGER " " D_ACTIVE_FOR_3_MINUTES)); - WifiManagerBegin(); + WifiManagerBegin(WIFI_MANAGER_RESET_ONLY == wifi_config_type); } #endif // USE_WEBSERVER } diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index a056c48ef..5d975ac1b 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -294,12 +294,14 @@ const char HTTP_BTN_RSTRT[] PROGMEM = const char HTTP_BTN_MENU_MODULE[] PROGMEM = "

" "

"; +const char HTTP_BTN_RESET[] PROGMEM = + "
" + "
"; const char HTTP_BTN_MENU4[] PROGMEM = "

" "

" - "

" - "
" - "
" + "

"; +const char HTTP_BTN_MENU5[] PROGMEM = "

" "

"; const char HTTP_BTN_MAIN[] PROGMEM = @@ -437,7 +439,7 @@ const char HDR_CTYPE_JSON[] PROGMEM = "application/json"; const char HDR_CTYPE_STREAM[] PROGMEM = "application/octet-stream"; #define DNS_PORT 53 -enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER}; +enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER, HTTP_MANAGER_RESET_ONLY}; DNSServer *DnsServer; ESP8266WebServer *WebServer; @@ -460,6 +462,10 @@ static void WebGetArg(const char* arg, char* out, size_t max) // out[max-1] = '\0'; // Ensure terminating NUL } +static bool WifiIsInManagerMode(){ + return (HTTP_MANAGER == webserver_state || HTTP_MANAGER_RESET_ONLY == webserver_state); +} + void ShowWebSource(int source) { if ((source > 0) && (source < SRC_MAX)) { @@ -480,34 +486,39 @@ void StartWebserver(int type, IPAddress ipweb) if (!Settings.web_refresh) { Settings.web_refresh = HTTP_REFRESH_TIME; } if (!webserver_state) { if (!WebServer) { - WebServer = new ESP8266WebServer((HTTP_MANAGER==type) ? 80 : WEB_PORT); + WebServer = new ESP8266WebServer((HTTP_MANAGER==type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT); WebServer->on("/", HandleRoot); - WebServer->on("/up", HandleUpgradeFirmware); - WebServer->on("/u1", HandleUpgradeFirmwareStart); // OTA - WebServer->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); - WebServer->on("/u2", HTTP_OPTIONS, HandlePreflightRequest); - WebServer->on("/cs", HandleConsole); - WebServer->on("/ax", HandleAjaxConsoleRefresh); - WebServer->on("/ay", HandleAjaxStatusRefresh); - WebServer->on("/cm", HandleHttpCommand); WebServer->onNotFound(HandleNotFound); #ifndef FIRMWARE_MINIMAL - WebServer->on("/cn", HandleConfiguration); - WebServer->on("/md", HandleModuleConfiguration); - WebServer->on("/wi", HandleWifiConfiguration); - WebServer->on("/lg", HandleLoggingConfiguration); - WebServer->on("/tp", HandleTemplateConfiguration); - WebServer->on("/co", HandleOtherConfiguration); - WebServer->on("/dl", HandleBackupConfiguration); - WebServer->on("/rs", HandleRestoreConfiguration); WebServer->on("/rt", HandleResetConfiguration); - WebServer->on("/in", HandleInformation); +#endif // FIRMWARE_MINIMAL + if(HTTP_MANAGER_RESET_ONLY != type){ + WebServer->on("/up", HandleUpgradeFirmware); + WebServer->on("/u1", HandleUpgradeFirmwareStart); // OTA + WebServer->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); + WebServer->on("/u2", HTTP_OPTIONS, HandlePreflightRequest); + WebServer->on("/cs", HandleConsole); + WebServer->on("/ax", HandleAjaxConsoleRefresh); + WebServer->on("/ay", HandleAjaxStatusRefresh); + WebServer->on("/cm", HandleHttpCommand); +#ifndef FIRMWARE_MINIMAL + WebServer->on("/cn", HandleConfiguration); + WebServer->on("/md", HandleModuleConfiguration); + WebServer->on("/wi", HandleWifiConfiguration); + WebServer->on("/lg", HandleLoggingConfiguration); + WebServer->on("/tp", HandleTemplateConfiguration); + WebServer->on("/co", HandleOtherConfiguration); + WebServer->on("/dl", HandleBackupConfiguration); + WebServer->on("/rs", HandleRestoreConfiguration); + WebServer->on("/rt", HandleResetConfiguration); + WebServer->on("/in", HandleInformation); #ifdef USE_EMULATION - HueWemoAddHandlers(); + HueWemoAddHandlers(); #endif // USE_EMULATION - XdrvCall(FUNC_WEB_ADD_HANDLER); - XsnsCall(FUNC_WEB_ADD_HANDLER); + XdrvCall(FUNC_WEB_ADD_HANDLER); + XsnsCall(FUNC_WEB_ADD_HANDLER); #endif // Not FIRMWARE_MINIMAL + } } reset_web_log_flag = false; WebServer->begin(); // Web server start @@ -529,7 +540,7 @@ void StopWebserver(void) } } -void WifiManagerBegin(void) +void WifiManagerBegin(bool reset_only) { // setup AP if (!global_state.wifi_down) { @@ -553,7 +564,7 @@ void WifiManagerBegin(void) DnsServer->setErrorReplyCode(DNSReplyCode::NoError); DnsServer->start(DNS_PORT, "*", WiFi.softAPIP()); - StartWebserver(HTTP_MANAGER, WiFi.softAPIP()); + StartWebserver((reset_only ? HTTP_MANAGER_RESET_ONLY : HTTP_MANAGER), WiFi.softAPIP()); } void PollDnsWebserver(void) @@ -576,7 +587,7 @@ void SetHeader(void) bool WebAuthenticate(void) { - if (Settings.web_password[0] != 0) { + if (Settings.web_password[0] != 0 && HTTP_MANAGER_RESET_ONLY != webserver_state) { return WebServer->authenticate(WEB_USERNAME, Settings.web_password); } else { return true; @@ -611,7 +622,7 @@ void ShowPage(String &page, bool auth) } page.replace(F("{j}"), info); - if (HTTP_MANAGER == webserver_state) { + if (WifiIsInManagerMode()) { if (WifiConfigCounter()) { page.replace(F(""), FPSTR(HTTP_SCRIPT_COUNTER)); page += FPSTR(HTTP_COUNTER); @@ -690,12 +701,12 @@ void HandleRoot(void) return; } - if (HTTP_MANAGER == webserver_state) { + if (WifiIsInManagerMode()) { #ifndef FIRMWARE_MINIMAL - if ((Settings.web_password[0] != 0) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1"))) { + if ((Settings.web_password[0] != 0) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != webserver_state) { HandleWifiLogin(); } else { - if (!(Settings.web_password[0] != 0) || ((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == Settings.web_password ))) { + if (!(Settings.web_password[0] != 0) || ((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == Settings.web_password ) || HTTP_MANAGER_RESET_ONLY == webserver_state)) { HandleWifiConfiguration(); } else { // wrong user and pass @@ -874,6 +885,8 @@ void HandleConfiguration(void) page += String(mqtt_data); page += FPSTR(HTTP_BTN_MENU4); + page += FPSTR(HTTP_BTN_RESET); + page += FPSTR(HTTP_BTN_MENU5); page += FPSTR(HTTP_BTN_MAIN); ShowPage(page); } @@ -1125,7 +1138,7 @@ void HandleWifiConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); - if (WebServer->hasArg("save")) { + if (WebServer->hasArg("save") && HTTP_MANAGER_RESET_ONLY != webserver_state) { WifiSaveSettings(); WebRestart(2); return; @@ -1136,90 +1149,96 @@ void HandleWifiConfiguration(void) page += FPSTR(HTTP_SCRIPT_WIFI); page += FPSTR(HTTP_HEAD_STYLE); - if (WebServer->hasArg("scan")) { -#ifdef USE_EMULATION - UdpDisconnect(); -#endif // USE_EMULATION - int n = WiFi.scanNetworks(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SCAN_DONE)); - if (0 == n) { - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, S_NO_NETWORKS_FOUND); - page += FPSTR(S_NO_NETWORKS_FOUND); - page += F(". " D_REFRESH_TO_SCAN_AGAIN "."); - } else { - //sort networks - int indices[n]; - for (int i = 0; i < n; i++) { - indices[i] = i; - } + if(HTTP_MANAGER_RESET_ONLY != webserver_state){ + if (WebServer->hasArg("scan")) { + #ifdef USE_EMULATION + UdpDisconnect(); + #endif // USE_EMULATION + int n = WiFi.scanNetworks(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SCAN_DONE)); - // RSSI SORT - for (int i = 0; i < n; i++) { - for (int j = i + 1; j < n; j++) { - if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) { - std::swap(indices[i], indices[j]); - } - } - } - - // remove duplicates ( must be RSSI sorted ) - if (remove_duplicate_access_points) { - String cssid; + if (0 == n) { + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, S_NO_NETWORKS_FOUND); + page += FPSTR(S_NO_NETWORKS_FOUND); + page += F(". " D_REFRESH_TO_SCAN_AGAIN "."); + } else { + //sort networks + int indices[n]; + for (int i = 0; i < n; i++) { + indices[i] = i; + } + + // RSSI SORT for (int i = 0; i < n; i++) { - if (-1 == indices[i]) { continue; } - cssid = WiFi.SSID(indices[i]); for (int j = i + 1; j < n; j++) { - if (cssid == WiFi.SSID(indices[j])) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_DUPLICATE_ACCESSPOINT " %s"), WiFi.SSID(indices[j]).c_str()); - AddLog(LOG_LEVEL_DEBUG); - indices[j] = -1; // set dup aps to index -1 + if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) { + std::swap(indices[i], indices[j]); } } } - } - //display networks in page - for (int i = 0; i < n; i++) { - if (-1 == indices[i]) { continue; } // skip dups - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i])); - AddLog(LOG_LEVEL_DEBUG); - int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); - - if (minimum_signal_quality == -1 || minimum_signal_quality < quality) { - String item = FPSTR(HTTP_LNK_ITEM); - String rssiQ; - rssiQ += quality; - item.replace(F("{v}"), htmlEscape(WiFi.SSID(indices[i]))); - item.replace(F("{w}"), String(WiFi.channel(indices[i]))); - item.replace(F("{r}"), rssiQ); - uint8_t auth = WiFi.encryptionType(indices[i]); - item.replace(F("{i}"), (ENC_TYPE_WEP == auth) ? F(D_WEP) : (ENC_TYPE_TKIP == auth) ? F(D_WPA_PSK) : (ENC_TYPE_CCMP == auth) ? F(D_WPA2_PSK) : (ENC_TYPE_AUTO == auth) ? F(D_AUTO) : F("")); - page += item; - delay(0); - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SKIPPING_LOW_QUALITY)); + // remove duplicates ( must be RSSI sorted ) + if (remove_duplicate_access_points) { + String cssid; + for (int i = 0; i < n; i++) { + if (-1 == indices[i]) { continue; } + cssid = WiFi.SSID(indices[i]); + for (int j = i + 1; j < n; j++) { + if (cssid == WiFi.SSID(indices[j])) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_DUPLICATE_ACCESSPOINT " %s"), WiFi.SSID(indices[j]).c_str()); + AddLog(LOG_LEVEL_DEBUG); + indices[j] = -1; // set dup aps to index -1 + } + } + } } - } - page += "
"; - } - } else { - page += FPSTR(HTTP_LNK_SCAN); - } + //display networks in page + for (int i = 0; i < n; i++) { + if (-1 == indices[i]) { continue; } // skip dups + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i])); + AddLog(LOG_LEVEL_DEBUG); + int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); - page += FPSTR(HTTP_FORM_WIFI); - page.replace(F("{h1"), Settings.hostname); - page.replace(F("{s1"), Settings.sta_ssid[0]); - page.replace(F("{s2"), Settings.sta_ssid[1]); - page += FPSTR(HTTP_FORM_END); - if (HTTP_MANAGER == webserver_state) { + if (minimum_signal_quality == -1 || minimum_signal_quality < quality) { + String item = FPSTR(HTTP_LNK_ITEM); + String rssiQ; + rssiQ += quality; + item.replace(F("{v}"), htmlEscape(WiFi.SSID(indices[i]))); + item.replace(F("{w}"), String(WiFi.channel(indices[i]))); + item.replace(F("{r}"), rssiQ); + uint8_t auth = WiFi.encryptionType(indices[i]); + item.replace(F("{i}"), (ENC_TYPE_WEP == auth) ? F(D_WEP) : (ENC_TYPE_TKIP == auth) ? F(D_WPA_PSK) : (ENC_TYPE_CCMP == auth) ? F(D_WPA2_PSK) : (ENC_TYPE_AUTO == auth) ? F(D_AUTO) : F("")); + page += item; + delay(0); + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SKIPPING_LOW_QUALITY)); + } + + } + page += "
"; + } + } else { + page += FPSTR(HTTP_LNK_SCAN); + } + + page += FPSTR(HTTP_FORM_WIFI); + page.replace(F("{h1"), Settings.hostname); + page.replace(F("{s1"), Settings.sta_ssid[0]); + page.replace(F("{s2"), Settings.sta_ssid[1]); + page += FPSTR(HTTP_FORM_END); + } + if (WifiIsInManagerMode()) { page += FPSTR(HTTP_BTN_RSTRT); + #ifndef FIRMWARE_MINIMAL + page += FPSTR(HTTP_BTN_RESET); + #endif // FIRMWARE_MINIMAL } else { page += FPSTR(HTTP_BTN_CONF); } // ShowPage(page); - ShowPage(page, !(HTTP_MANAGER == webserver_state)); + ShowPage(page, !(WifiIsInManagerMode())); } void WifiSaveSettings(void) @@ -2089,7 +2108,7 @@ void HandleNotFound(void) /* 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. */ bool CaptivePortal(void) { - if ((HTTP_MANAGER == webserver_state) && !ValidIpAddress(WebServer->hostHeader())) { + if ((WifiIsInManagerMode()) && !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); From 731154cc9bc3c3f1434b329b21b074994e011a12 Mon Sep 17 00:00:00 2001 From: netpok Date: Thu, 21 Feb 2019 19:45:03 +0100 Subject: [PATCH 1060/2222] Handle authentication on reset/restart --- sonoff/xdrv_01_webserver.ino | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 5d975ac1b..05f095010 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -666,14 +666,16 @@ void WebRestart(uint8_t type) page.replace(F("{v}"), FPSTR(S_RESTART)); } + bool reset_only = (HTTP_MANAGER_RESET_ONLY == webserver_state); + page += FPSTR(HTTP_MSG_RSTRT); - if (HTTP_MANAGER == webserver_state) { + if (HTTP_MANAGER == webserver_state || reset_only) { webserver_state = HTTP_ADMIN; } else { page += FPSTR(HTTP_BTN_MAIN); } page.replace(F(""), FPSTR(HTTP_SCRIPT_RELOAD)); - ShowPage(page); + ShowPage(page, !reset_only); ShowWebSource(SRC_WEBGUI); restart_flag = 2; @@ -1494,7 +1496,7 @@ void HandleResetConfiguration(void) page += F("
" D_CONFIGURATION_RESET "
"); page += FPSTR(HTTP_MSG_RSTRT); page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + ShowPage(page, HTTP_MANAGER_RESET_ONLY != webserver_state); snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RESET " 1")); ExecuteWebCommand(svalue, SRC_WEBGUI); From e9396d0ed42864835fef78e61a142cb87809e953 Mon Sep 17 00:00:00 2001 From: netpok Date: Thu, 21 Feb 2019 19:45:21 +0100 Subject: [PATCH 1061/2222] Add missing localization strings --- sonoff/i18n.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 7340a3484..e0b3af57b 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -248,6 +248,7 @@ #define D_WCFG_4_RETRY "Retry" #define D_WCFG_5_WAIT "Wait" #define D_WCFG_6_SERIAL "Serial" + #define D_WCFG_7_WIFIMANAGER_RESET_ONLY "ManagerRst" #define D_CMND_FRIENDLYNAME "FriendlyName" #define D_CMND_SWITCHMODE "SwitchMode" #define D_CMND_INTERLOCK "Interlock" @@ -540,7 +541,8 @@ const char kWifiConfig[MAX_WIFI_OPTION][WCFG_MAX_STRING_LENGTH] PROGMEM = { D_WCFG_3_WPSCONFIG, D_WCFG_4_RETRY, D_WCFG_5_WAIT, - D_WCFG_6_SERIAL }; + D_WCFG_6_SERIAL, + D_WCFG_7_WIFIMANAGER_RESET_ONLY }; const char kPrefixes[3][PRFX_MAX_STRING_LENGTH] PROGMEM = { D_CMND, D_STAT, From b3adab40979b6882bab6f8a8277e84f23f112805 Mon Sep 17 00:00:00 2001 From: netpok Date: Thu, 21 Feb 2019 21:27:52 +0100 Subject: [PATCH 1062/2222] Add flag for no hold retain --- sonoff/settings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index bc39d7d8a..447db10c0 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -75,7 +75,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t hass_tele_on_power : 1; // bit 9 (v6.3.0.13) uint32_t sleep_normal : 1; // bit 10 (v6.3.0.15) - SetOption60 - Enable normal sleep instead of dynamic sleep uint32_t button_switch_force_local : 1;// bit 11 (v6.3.0.16) - SetOption61 - Force local operation when button/switch topic is set - uint32_t spare12 : 1; + uint32_t no_hold_retain : 1; // bit 12 (v6.4.1.19) - SetOption62 - Don't use retain flag on HOLD messages uint32_t spare13 : 1; uint32_t spare14 : 1; uint32_t spare15 : 1; From 6cbfb0308aede1b6d2161b51c36f377151e077ba Mon Sep 17 00:00:00 2001 From: netpok Date: Thu, 21 Feb 2019 21:28:35 +0100 Subject: [PATCH 1063/2222] Check no hold retain flag on hold action sending --- sonoff/sonoff.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 24a3d5723..5cb6379f9 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1434,10 +1434,10 @@ bool SendKey(uint8_t key, uint8_t device, uint8_t state) } #ifdef USE_DOMOTICZ if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) { - MqttPublishDirect(stopic, (key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain); + MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != 3 || !Settings.flag3.no_hold_retain)); } #else - MqttPublishDirect(stopic, (key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain); + MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != 3 || !Settings.flag3.no_hold_retain)); #endif // USE_DOMOTICZ result = !Settings.flag3.button_switch_force_local; } else { From 49f0b514ebae8f9f17a48eada91361258ee92585 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 22 Feb 2019 12:04:05 +0100 Subject: [PATCH 1064/2222] Fix some exceptions and watchdogs * Fix some exceptions and watchdogs due to lack of stack space - part 2 * Add command SetOption62 0/1 to disable retain on Button or Swith hold messages (#5299) * Add option WifiConfig 7 to allow reset of device in AP mode without admin password (#5297) --- sonoff/_changelog.ino | 3 +++ sonoff/sonoff.ino | 14 +++++++------- sonoff/xdrv_01_webserver.ino | 24 +++++++++++------------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0d4fef299..0ca38587b 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,8 @@ /* 6.4.1.18 20191221 * Fix some exceptions and watchdogs due to lack of stack space - part 1 (#5215) + * Fix some exceptions and watchdogs due to lack of stack space - part 2 + * Add command SetOption62 0/1 to disable retain on Button or Swith hold messages (#5299) + * Add option WifiConfig 7 to allow reset of device in AP mode without admin password (#5297) * * 6.4.1.17 20190214 * Change template update by removing possibility to add user module config keeping template as defined (#5222) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 5cb6379f9..161c26ed8 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -866,9 +866,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } restart_flag = 2; } - uint8_t module = Settings.module; - if (USER_MODULE == Settings.module) { module = 0; } else { module++; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, module, ModuleName().c_str()); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, ModuleNr(), ModuleName().c_str()); } else if (CMND_MODULES == command_code) { for (uint8_t i = 0; i <= MAXMODULE; i++) { @@ -1566,8 +1564,6 @@ void StopAllPowerBlink(void) void ExecuteCommand(char *cmnd, int source) { - char stopic[CMDSZ]; - char svalue[INPUT_BUFFER_SIZE]; char *start; char *token; @@ -1579,9 +1575,13 @@ void ExecuteCommand(char *cmnd, int source) start = strrchr(token, '/'); // Skip possible cmnd/sonoff/ preamble if (start) { token = start +1; } } + uint16_t size = (token != NULL) ? strlen(token) : 0; + char stopic[size +2]; // / + \0 snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == NULL) ? "" : token); + token = strtok(NULL, ""); -// snprintf_P(svalue, sizeof(svalue), (token == NULL) ? "" : token); // Fails with command FullTopic home/%prefix%/%topic% as it processes %p of %prefix% + size = (token != NULL) ? strlen(token) : 0; + char svalue[size +1]; strlcpy(svalue, (token == NULL) ? "" : token, sizeof(svalue)); // Fixed 5.8.0b MqttDataHandler(stopic, (uint8_t*)svalue, strlen(svalue)); } @@ -1610,7 +1610,7 @@ void PublishStatus(uint8_t payload) snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%d" ), stemp2, (i > 0 ? "," : ""), Settings.switchmode[i]); } 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_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), - (USER_MODULE == Settings.module)?0:Settings.module +1, stemp, mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, Settings.save_data, Settings.flag.save_state, Settings.switch_topic, stemp2, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_switch_retain, Settings.flag.mqtt_sensor_retain, Settings.flag.mqtt_power_retain); + ModuleNr(), stemp, mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, Settings.save_data, Settings.flag.save_state, Settings.switch_topic, stemp2, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_switch_retain, Settings.flag.mqtt_sensor_retain, Settings.flag.mqtt_power_retain); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS)); } diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 0258484b9..779872bb9 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1956,8 +1956,6 @@ void HandleHttpCommand(void) { if (!HttpCheckPriviledgedAccess(false)) { return; } - char svalue[INPUT_BUFFER_SIZE]; // Large to serve Backlog - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_COMMAND)); uint8_t valid = 1; @@ -1972,9 +1970,9 @@ void HandleHttpCommand(void) String message = F("{\"" D_RSLT_WARNING "\":\""); if (valid) { uint8_t curridx = web_log_index; - WebGetArg("cmnd", svalue, sizeof(svalue)); - if (strlen(svalue)) { - ExecuteWebCommand(svalue, SRC_WEBCOMMAND); + String svalue = WebServer->arg("cmnd"); + if (svalue.length() && (svalue.length() < INPUT_BUFFER_SIZE)) { + ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE); if (web_log_index != curridx) { uint8_t counter = curridx; @@ -2032,19 +2030,19 @@ void HandleAjaxConsoleRefresh(void) { if (!HttpCheckPriviledgedAccess()) { return; } - char svalue[INPUT_BUFFER_SIZE]; // Large to serve Backlog bool cflg = true; uint8_t counter = 0; // Initial start, should never be 0 again - WebGetArg("c1", svalue, sizeof(svalue)); - if (strlen(svalue)) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_COMMAND "%s"), svalue); + String svalue = WebServer->arg("c1"); + if (svalue.length() && (svalue.length() < INPUT_BUFFER_SIZE)) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_COMMAND "%s"), svalue.c_str()); AddLog(LOG_LEVEL_INFO); - ExecuteWebCommand(svalue, SRC_WEBCONSOLE); + ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE); } - WebGetArg("c2", svalue, sizeof(svalue)); - if (strlen(svalue)) { counter = atoi(svalue); } + char stmp[10]; + WebGetArg("c2", stmp, sizeof(stmp)); + if (strlen(stmp)) { counter = atoi(stmp); } bool last_reset_web_log_flag = reset_web_log_flag; // mqtt_data used as scratch space @@ -2202,7 +2200,7 @@ int WebSend(char *buffer) user = Trim(user); // user = |admin| if (password) { password = Trim(password); } // password = |joker| } - + command = Trim(command); // command = |POWER1 ON| or |/any/link/starting/with/a/slash.php?log=123| if (command[0] != '/') { url += F("/cm?"); // url = |http://192.168.178.86/cm?| From d219d1c9b5d482f5233e37caa63071a194c7240b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 22 Feb 2019 12:11:15 +0100 Subject: [PATCH 1065/2222] Update support.ino Houskeeping --- sonoff/support.ino | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 113968974..ff488d008 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -699,6 +699,13 @@ void ShowSource(int source) * GPIO Module and Template management \*********************************************************************************************/ +uint8_t ModuleNr() +{ + // 0 = User module (255) + // 1 up = Template module 0 up + return (USER_MODULE == Settings.module) ? 0 : Settings.module +1; +} + String AnyModuleName(uint8_t index) { if (USER_MODULE == index) { @@ -720,7 +727,6 @@ void ModuleGpios(myio *gp) uint8_t src[sizeof(mycfgio)]; if (USER_MODULE == Settings.module) { -// src = Settings.user_template.gp; memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio)); } else { memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio)); @@ -870,14 +876,6 @@ bool JsonTemplate(const char* dataBuf) if ((0 == base) || (base >= MAXMODULE)) { base = 17; } else { base--; } Settings.user_template_base = base; // Default WEMOS } - - // Validate GPIO -// for (uint8_t i = 0; i < sizeof(mycfgio); i++) { - // For now do not allow non-user configurable GPIO -// if ((Settings.user_template.gp.io[i] > GPIO_FIX_START) && (Settings.user_template.gp.io[i] < GPIO_USER)) { -// Settings.user_template.gp.io[i] = GPIO_NONE; -// }; -// } return true; } @@ -887,8 +885,6 @@ void TemplateJson() for (uint8_t i = 0; i < sizeof(Settings.user_template.gp); i++) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", Settings.user_template.gp.io[i]); } -// snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":\"%d (%s)\"}"), -// mqtt_data, Settings.user_template.flag, Settings.user_template_base +1, AnyModuleName(Settings.user_template_base).c_str()); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), mqtt_data, Settings.user_template.flag, Settings.user_template_base +1); } From e315be06198ae481b102967359c886ed1e9bd6da Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 22 Feb 2019 15:19:59 +0100 Subject: [PATCH 1066/2222] Fix command WebSend Fix command WebSend when using a port number as regression from 6.4.1.17 (#5304) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_01_webserver.ino | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0ca38587b..d9762ec24 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Fix some exceptions and watchdogs due to lack of stack space - part 2 * Add command SetOption62 0/1 to disable retain on Button or Swith hold messages (#5299) * Add option WifiConfig 7 to allow reset of device in AP mode without admin password (#5297) + * Fix command WebSend when using a port number as regression from 6.4.1.17 (#5304) * * 6.4.1.17 20190214 * Change template update by removing possibility to add user module config keeping template as defined (#5222) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 779872bb9..cb2717db3 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2182,18 +2182,19 @@ int WebSend(char *buffer) // buffer = | [ 192.168.178.86 : 80 , admin : joker ] POWER1 ON | host = strtok_r(buffer, "]", &command); // host = | [ 192.168.178.86 : 80 , admin : joker |, command = | POWER1 ON | if (host && command) { - String url = F("http:"); // url = |http:| + String url = F("http://"); // url = |http://| host = Trim(host); // host = |[ 192.168.178.86 : 80 , admin : joker| host++; // host = | 192.168.178.86 : 80 , admin : joker| - Skip [ host = strtok_r(host, ",", &user); // host = | 192.168.178.86 : 80 |, user = | admin : joker| host = strtok_r(host, ":", &port); // host = | 192.168.178.86 |, port = | 80 | host = Trim(host); // host = |192.168.178.86| + url += host; // url = |http://192.168.178.86| + if (port) { port = Trim(port); // port = |80| - url += port; // url = |http:80| + url += F(":"); // url = |http://192.168.178.86:| + url += port; // url = |http://192.168.178.86:80| } - url += F("//"); // url = |http://| or |http:80//| - url += host; // url = |http://192.168.178.86| if (user) { user = strtok_r(user, ":", &password); // user = | admin |, password = | joker| From 2a8e785a8bd1c1b5e2633fa40b46e5981612195b Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 22 Feb 2019 15:23:37 +0100 Subject: [PATCH 1067/2222] Revert to modular build 2.5.0 release --- platformio.ini | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 21816c3ab..af1adb697 100644 --- a/platformio.ini +++ b/platformio.ini @@ -65,8 +65,9 @@ build_flags = ${esp82xx_defaults.build_flags} -DVTABLES_IN_FLASH [core_2_5_0] -; *** Esp8266 core for Arduino version 2.5.0 -platform = espressif8266@2.0.0 +; *** Esp8266 core for Arduino version 2.5.0 (since version from platformio is faulty) +platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota +;platform = espressif8266@2.0.0 build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld ; lwIP 1.4 (Default) From 06bec0d95e109876ab00123681d044cf0598b021 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Feb 2019 11:18:57 +0100 Subject: [PATCH 1068/2222] Update _changelog.ino Back from the future --- sonoff/_changelog.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index d9762ec24..1e4e9f172 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,4 @@ -/* 6.4.1.18 20191221 +/* 6.4.1.18 20190221 * Fix some exceptions and watchdogs due to lack of stack space - part 1 (#5215) * Fix some exceptions and watchdogs due to lack of stack space - part 2 * Add command SetOption62 0/1 to disable retain on Button or Swith hold messages (#5299) From 5d8ae266d0969d02b18d166774c073a3b6f91c7b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Feb 2019 12:48:39 +0100 Subject: [PATCH 1069/2222] Fix RemoveSpace and tune Websend Fix RemoveSpace and tune Websend --- sonoff/support.ino | 2 +- sonoff/xdrv_01_webserver.ino | 39 +++++++++++------------------------- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index ff488d008..8bb9d1dea 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -275,7 +275,7 @@ char* RemoveSpace(char* p) *write++ = ch; } } - *write = '\0'; +// *write = '\0'; // Removed 20190223 as it buffer overflows on no isspace found - no need either return p; } diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index cb2717db3..473d1f11f 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1972,8 +1972,7 @@ void HandleHttpCommand(void) uint8_t curridx = web_log_index; String svalue = WebServer->arg("cmnd"); if (svalue.length() && (svalue.length() < INPUT_BUFFER_SIZE)) { - ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE); - + ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCOMMAND); if (web_log_index != curridx) { uint8_t counter = curridx; message = F("{"); @@ -2173,7 +2172,6 @@ int WebSend(char *buffer) // [sonoff,admin:joker] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 char *host; - char *port; char *user; char *password; char *command; @@ -2182,35 +2180,22 @@ int WebSend(char *buffer) // buffer = | [ 192.168.178.86 : 80 , admin : joker ] POWER1 ON | host = strtok_r(buffer, "]", &command); // host = | [ 192.168.178.86 : 80 , admin : joker |, command = | POWER1 ON | if (host && command) { + RemoveSpace(host); // host = |[192.168.178.86:80,admin:joker| + host++; // host = |192.168.178.86:80,admin:joker| - Skip [ + host = strtok_r(host, ",", &user); // host = |192.168.178.86:80|, user = |admin:joker| String url = F("http://"); // url = |http://| - host = Trim(host); // host = |[ 192.168.178.86 : 80 , admin : joker| - host++; // host = | 192.168.178.86 : 80 , admin : joker| - Skip [ - host = strtok_r(host, ",", &user); // host = | 192.168.178.86 : 80 |, user = | admin : joker| - host = strtok_r(host, ":", &port); // host = | 192.168.178.86 |, port = | 80 | - host = Trim(host); // host = |192.168.178.86| - url += host; // url = |http://192.168.178.86| - - if (port) { - port = Trim(port); // port = |80| - url += F(":"); // url = |http://192.168.178.86:| - url += port; // url = |http://192.168.178.86:80| - } - - if (user) { - user = strtok_r(user, ":", &password); // user = | admin |, password = | joker| - user = Trim(user); // user = |admin| - if (password) { password = Trim(password); } // password = |joker| - } + url += host; // url = |http://192.168.178.86:80| command = Trim(command); // command = |POWER1 ON| or |/any/link/starting/with/a/slash.php?log=123| if (command[0] != '/') { url += F("/cm?"); // url = |http://192.168.178.86/cm?| - if (user && password) { - url += F("user="); // url = |http://192.168.178.86/cm?user=| - url += user; // url = |http://192.168.178.86/cm?user=admin| - url += F("&password="); // url = |http://192.168.178.86/cm?user=admin&password=| - url += password; // url = |http://192.168.178.86/cm?user=admin&password=joker| - url += F("&"); // url = |http://192.168.178.86/cm?user=admin&password=joker&| + if (user) { + user = strtok_r(user, ":", &password); // user = |admin|, password = |joker| + if (user && password) { + char userpass[128]; + snprintf_P(userpass, sizeof(userpass), PSTR("user=%s&password=%s&"), user, password); + url += userpass; // url = |http://192.168.178.86/cm?user=admin&password=joker&| + } } url += F("cmnd="); // url = |http://192.168.178.86/cm?cmnd=| or |http://192.168.178.86/cm?user=admin&password=joker&cmnd=| } From 1cb956b541e6416ce161fc949ce15dca69e97576 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Feb 2019 13:17:02 +0100 Subject: [PATCH 1070/2222] Free flash space Free flash space --- sonoff/xdrv_01_webserver.ino | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 473d1f11f..212e16f92 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -438,6 +438,13 @@ const char HDR_CTYPE_XML[] PROGMEM = "text/xml"; const char HDR_CTYPE_JSON[] PROGMEM = "application/json"; const char HDR_CTYPE_STREAM[] PROGMEM = "application/octet-stream"; +const char kUploadErrors[] PROGMEM = + D_UPLOAD_ERR_1 "|" D_UPLOAD_ERR_2 "|" D_UPLOAD_ERR_3 "|" D_UPLOAD_ERR_4 "|" D_UPLOAD_ERR_5 "|" D_UPLOAD_ERR_6 "|" D_UPLOAD_ERR_7 "|" D_UPLOAD_ERR_8 "|" D_UPLOAD_ERR_9 +#ifdef USE_RF_FLASH + "|" D_UPLOAD_ERR_10 "|" D_UPLOAD_ERR_11 "|" D_UPLOAD_ERR_12 "|" D_UPLOAD_ERR_13 +#endif + ; + #define DNS_PORT 53 enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER, HTTP_MANAGER_RESET_ONLY}; @@ -1712,24 +1719,14 @@ void HandleUploadDone(void) page += F("
" D_UPLOAD " " D_FAILED "

"); - switch (upload_error) { - case 1: strncpy_P(error, PSTR(D_UPLOAD_ERR_1), sizeof(error)); break; - case 2: strncpy_P(error, PSTR(D_UPLOAD_ERR_2), sizeof(error)); break; - case 3: strncpy_P(error, PSTR(D_UPLOAD_ERR_3), sizeof(error)); break; - case 4: strncpy_P(error, PSTR(D_UPLOAD_ERR_4), sizeof(error)); break; - case 5: strncpy_P(error, PSTR(D_UPLOAD_ERR_5), sizeof(error)); break; - case 6: strncpy_P(error, PSTR(D_UPLOAD_ERR_6), sizeof(error)); break; - case 7: strncpy_P(error, PSTR(D_UPLOAD_ERR_7), sizeof(error)); break; - case 8: strncpy_P(error, PSTR(D_UPLOAD_ERR_8), sizeof(error)); break; - case 9: strncpy_P(error, PSTR(D_UPLOAD_ERR_9), sizeof(error)); break; #ifdef USE_RF_FLASH - case 10: strncpy_P(error, PSTR(D_UPLOAD_ERR_10), sizeof(error)); break; - case 11: strncpy_P(error, PSTR(D_UPLOAD_ERR_11), sizeof(error)); break; - case 12: strncpy_P(error, PSTR(D_UPLOAD_ERR_12), sizeof(error)); break; - case 13: strncpy_P(error, PSTR(D_UPLOAD_ERR_13), sizeof(error)); break; + if (upload_error < 14) { +#else + if (upload_error < 10) { #endif - default: - snprintf_P(error, sizeof(error), PSTR(D_UPLOAD_ERROR_CODE " %d"), upload_error); + GetTextIndexed(error, sizeof(error), upload_error -1, kUploadErrors); + } else { + snprintf_P(error, sizeof(error), PSTR(D_UPLOAD_ERROR_CODE " %d"), upload_error); } page += error; snprintf_P(log_data, sizeof(log_data), PSTR(D_UPLOAD ": %s"), error); From ef7150aa6e2a2ec0c957e8c84e5c69a8fb30c982 Mon Sep 17 00:00:00 2001 From: blakadder Date: Sat, 23 Feb 2019 13:53:38 +0100 Subject: [PATCH 1071/2222] Update README.md Wikified first paragraph and a contribute line for Wiki --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0184e7cc5..dda9b6227 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Sonoff-Tasmota -Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web**, **timers**, 'Over The Air' (**OTA**) firmware updates and **sensors support**, allowing control under **Serial**, **HTTP**, **MQTT** and **KNX**, so as to be used on **Smart Home Systems**. Written for Arduino IDE and PlatformIO. +Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custome device templates and sensors support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. [![GitHub version](https://img.shields.io/github/release/arendst/Sonoff-Tasmota.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) [![GitHub download](https://img.shields.io/github/downloads/arendst/Sonoff-Tasmota/total.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) @@ -64,7 +64,7 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for more information.
See [Community](https://groups.google.com/d/forum/sonoffusers) for forum.
-See [Chat](https://discord.gg/Ks2Kzd4) for more user experience. +Visit [Discord Chat](https://discord.gg/Ks2Kzd4) for discussions and troubleshooting. The following devices are supported: - [iTead Sonoff Basic (R2)](https://www.itead.cc/smart-home/sonoff-wifi-wireless-switch-1.html) @@ -113,6 +113,7 @@ You can contribute to Sonoff-Tasmota by - providing Pull Requests (Features, Proof of Concepts, Language files or Fixes) - testing new released features and report issues - donating to acquire hardware for testing and implementing or out of gratitude +- contributing missing documentation for features and devices on our [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) [![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/tasmota) From 19bdf7e803ab14f1ff6325a8c4266dc8f67946ae Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Feb 2019 15:29:42 +0100 Subject: [PATCH 1072/2222] Free flash space (WSSend) Free flash space (WSSend) --- sonoff/xdrv_01_webserver.ino | 37 +++++++++++++++++++----------------- sonoff/xdrv_11_knx.ino | 12 ++++++------ sonoff/xplg_wemohue.ino | 33 ++++++++++++++++---------------- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 212e16f92..9347a5c11 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -432,11 +432,8 @@ const char HTTP_END[] PROGMEM = const char HTTP_DEVICE_CONTROL[] PROGMEM = "
"; // ?o is related to WebGetArg("o", tmp, sizeof(tmp)); const char HTTP_DEVICE_STATE[] PROGMEM = "%s"; // {c} = %'>
send(200, FPSTR(HDR_CTYPE_XML), state_xml); + WSSend(200, CT_XML, state_xml); } void HandleUpnpService(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_EVENT_SERVICE)); - WebServer->send(200, FPSTR(HDR_CTYPE_PLAIN), FPSTR(WEMO_EVENTSERVICE_XML)); + WSSend(200, CT_PLAIN, FPSTR(WEMO_EVENTSERVICE_XML)); } void HandleUpnpMetaService(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_META_SERVICE)); - WebServer->send(200, FPSTR(HDR_CTYPE_PLAIN), FPSTR(WEMO_METASERVICE_XML)); + WSSend(200, CT_PLAIN, FPSTR(WEMO_METASERVICE_XML)); } void HandleUpnpSetupWemo(void) @@ -430,7 +430,7 @@ void HandleUpnpSetupWemo(void) 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); + WSSend(200, CT_XML, setup_xml); } /*********************************************************************************************\ @@ -532,7 +532,7 @@ void HandleUpnpSetupHue(void) 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); + WSSend(200, CT_XML, description_xml); } void HueNotImplemented(String *path) @@ -540,7 +540,7 @@ 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); - WebServer->send(200, FPSTR(HDR_CTYPE_JSON), "{}"); + WSSend(200, CT_JSON, "{}"); } void HueConfigResponse(String *response) @@ -559,7 +559,7 @@ void HueConfig(String *path) { String response = ""; HueConfigResponse(&response); - WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); + WSSend(200, CT_JSON, response); } bool g_gotct = false; @@ -610,7 +610,7 @@ void HueGlobalConfig(String *path) response += F("},\"groups\":{},\"schedules\":{},\"config\":"); HueConfigResponse(&response); response += "}"; - WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); + WSSend(200, CT_JSON, response); } void HueAuthentication(String *path) @@ -618,7 +618,7 @@ void HueAuthentication(String *path) char response[38]; snprintf_P(response, sizeof(response), PSTR("[{\"success\":{\"username\":\"%s\"}}]"), GetHueUserId().c_str()); - WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); + WSSend(200, CT_JSON, response); } void HueLights(String *path) @@ -627,15 +627,16 @@ void HueLights(String *path) * http://sonoff/api/username/lights/1/state?1={"on":true,"hue":56100,"sat":254,"bri":254,"alert":"none","transitiontime":40} */ String response; - uint8_t device = 1; - uint16_t tmp = 0; + int code = 200; float bri = 0; float hue = 0; float sat = 0; + uint16_t tmp = 0; uint16_t ct = 0; bool resp = false; bool on = false; bool change = false; + uint8_t device = 1; uint8_t maxhue = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present; path->remove(0,path->indexOf("/lights")); // Remove until /lights @@ -651,7 +652,6 @@ void HueLights(String *path) } } response += "}"; - WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } else if (path->endsWith("/state")) { // Got ID/state path->remove(0,8); // Remove /lights/ @@ -761,8 +761,6 @@ void HueLights(String *path) else { response = FPSTR(HUE_ERROR_JSON); } - - WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID path->remove(0,8); // Remove /lights/ @@ -773,11 +771,12 @@ void HueLights(String *path) response += F("{\"state\":"); HueLightStatus1(device, &response); HueLightStatus2(device, &response); - WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } else { - WebServer->send(406, FPSTR(HDR_CTYPE_JSON), "{}"); + response = "{}"; + code = 406; } + WSSend(code, CT_JSON, response); } void HueGroups(String *path) @@ -799,7 +798,7 @@ void HueGroups(String *path) response += F("}"); } - WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); + WSSend(200, CT_JSON, response); } void HandleHueApi(String *path) From 93d07c1accde753491baa4e2a3e4a4dc2740ab6a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Feb 2019 18:38:36 +0100 Subject: [PATCH 1073/2222] Webserver memory optimizations Webserver memory optimizations --- sonoff/xdrv_01_webserver.ino | 121 +++++++++++++++++------------------ 1 file changed, 60 insertions(+), 61 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 9347a5c11..ef6083d2b 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -448,8 +448,8 @@ enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER, HTTP_MANAGER_RE DNSServer *DnsServer; ESP8266WebServer *WebServer; -bool remove_duplicate_access_points = true; int minimum_signal_quality = -1; +bool remove_duplicate_access_points = true; uint8_t webserver_state = HTTP_OFF; uint8_t upload_error = 0; uint8_t upload_file_type; @@ -496,7 +496,7 @@ void StartWebserver(int type, IPAddress ipweb) #ifndef FIRMWARE_MINIMAL WebServer->on("/rt", HandleResetConfiguration); #endif // FIRMWARE_MINIMAL - if(HTTP_MANAGER_RESET_ONLY != type){ + if (HTTP_MANAGER_RESET_ONLY != type) { WebServer->on("/up", HandleUpgradeFirmware); WebServer->on("/u1", HandleUpgradeFirmwareStart); // OTA WebServer->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); @@ -727,7 +727,8 @@ void HandleRoot(void) } #endif // Not FIRMWARE_MINIMAL } else { - char stemp[10]; + char stemp[5]; + String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_MAIN_MENU)); page += FPSTR(HTTP_SCRIPT_ROOT); @@ -797,10 +798,10 @@ void HandleAjaxStatusRefresh(void) { if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } - char svalue[80]; - char tmp[100]; + char tmp[8]; // WebGetArg numbers only + char svalue[32]; // Command and number parameter - WebGetArg("o", tmp, sizeof(tmp)); + WebGetArg("o", tmp, sizeof(tmp)); // 1 - 16 Device number for button Toggle or Fanspeed if (strlen(tmp)) { ShowWebSource(SRC_WEBGUI); uint8_t device = atoi(tmp); @@ -815,17 +816,17 @@ void HandleAjaxStatusRefresh(void) ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); } } - WebGetArg("d", tmp, sizeof(tmp)); + WebGetArg("d", tmp, sizeof(tmp)); // 0 - 100 Dimmer value if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } - WebGetArg("t", tmp, sizeof(tmp)); + WebGetArg("t", tmp, sizeof(tmp)); // 153 - 500 Color temperature if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } - WebGetArg("k", tmp, sizeof(tmp)); + WebGetArg("k", tmp, sizeof(tmp)); // 1 - 16 Pre defined RF keys if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); @@ -915,7 +916,7 @@ void HandleTemplateConfiguration(void) return; } - char stemp[20]; + char stemp[20]; // Template number and Sensor name if (WebServer->hasArg("m")) { String page = ""; @@ -928,7 +929,7 @@ void HandleTemplateConfiguration(void) return; } - WebGetArg("t", stemp, sizeof(stemp)); + WebGetArg("t", stemp, sizeof(stemp)); // 0 - 69 Template number if (strlen(stemp)) { uint8_t module = atoi(stemp); uint8_t module_save = Settings.module; @@ -990,9 +991,9 @@ void HandleTemplateConfiguration(void) void TemplateSaveSettings(void) { - char svalue[128]; - char tmp[100]; - char stemp[20]; + char tmp[15]; // WebGetArg NAME and GPIO/BASE/FLAG byte value + char webindex[5]; // WebGetArg name + char svalue[128]; // Template command string WebGetArg("s1", tmp, sizeof(tmp)); // NAME snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp); @@ -1001,8 +1002,8 @@ void TemplateSaveSettings(void) for (uint8_t i = 0; i < sizeof(Settings.user_template.gp); i++) { if (6 == i) { j = 9; } if (8 == i) { j = 12; } - snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), j); - WebGetArg(stemp, tmp, sizeof(tmp)); // GPIO + snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), j); + WebGetArg(webindex, tmp, sizeof(tmp)); // GPIO uint8_t gpio = atoi(tmp); snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", gpio); j++; @@ -1010,8 +1011,8 @@ void TemplateSaveSettings(void) uint8_t flag = 0; for (uint8_t i = 0; i < GPIO_FLAG_USED; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("c%d"), i); - uint8_t state = WebServer->hasArg(stemp) << i; // FLAG + snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i); + uint8_t state = WebServer->hasArg(webindex) << i; // FLAG flag += state; } WebGetArg("g99", tmp, sizeof(tmp)); // BASE @@ -1034,7 +1035,7 @@ void HandleModuleConfiguration(void) return; } - char stemp[20]; + char stemp[20]; // Sensor name uint8_t midx; myio cmodule; ModuleGpios(&cmodule); @@ -1104,8 +1105,8 @@ void HandleModuleConfiguration(void) void ModuleSaveSettings(void) { - char tmp[100]; - char stemp[TOPSZ]; + char tmp[8]; // WebGetArg numbers only + char webindex[5]; // WebGetArg name WebGetArg("g99", tmp, sizeof(tmp)); uint8_t new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); @@ -1120,8 +1121,8 @@ void ModuleSaveSettings(void) Settings.my_gp.io[i] = GPIO_NONE; } else { if (ValidGPIO(i, cmodule.io[i])) { - snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), i); - WebGetArg(stemp, tmp, sizeof(tmp)); + snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i); + WebGetArg(webindex, tmp, sizeof(tmp)); Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); } @@ -1135,13 +1136,13 @@ void ModuleSaveSettings(void) String htmlEscape(String s) { - s.replace("&", "&"); - s.replace("<", "<"); - s.replace(">", ">"); - s.replace("\"", """); - s.replace("'", "'"); - s.replace("/", "/"); - return s; + s.replace("&", "&"); + s.replace("<", "<"); + s.replace(">", ">"); + s.replace("\"", """); + s.replace("'", "'"); + s.replace("/", "/"); + return s; } void HandleWifiConfiguration(void) @@ -1161,12 +1162,11 @@ void HandleWifiConfiguration(void) page += FPSTR(HTTP_SCRIPT_WIFI); page += FPSTR(HTTP_HEAD_STYLE); - - if(HTTP_MANAGER_RESET_ONLY != webserver_state){ + if (HTTP_MANAGER_RESET_ONLY != webserver_state) { if (WebServer->hasArg("scan")) { - #ifdef USE_EMULATION +#ifdef USE_EMULATION UdpDisconnect(); - #endif // USE_EMULATION +#endif // USE_EMULATION int n = WiFi.scanNetworks(); AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SCAN_DONE)); @@ -1243,9 +1243,9 @@ void HandleWifiConfiguration(void) } if (WifiIsInManagerMode()) { page += FPSTR(HTTP_BTN_RSTRT); - #ifndef FIRMWARE_MINIMAL +#ifndef FIRMWARE_MINIMAL page += FPSTR(HTTP_BTN_RESET); - #endif // FIRMWARE_MINIMAL +#endif // FIRMWARE_MINIMAL } else { page += FPSTR(HTTP_BTN_CONF); } @@ -1255,7 +1255,7 @@ void HandleWifiConfiguration(void) void WifiSaveSettings(void) { - char tmp[100]; + char tmp[sizeof(Settings.sta_pwd[0])]; // Max length is currently 65 WebGetArg("h", tmp, sizeof(tmp)); strlcpy(Settings.hostname, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp, sizeof(Settings.hostname)); @@ -1334,7 +1334,7 @@ void HandleLoggingConfiguration(void) void LoggingSaveSettings(void) { - char tmp[100]; + char tmp[sizeof(Settings.syslog_host)]; // Max length is currently 33 WebGetArg("ls", tmp, sizeof(tmp)); Settings.seriallog_level = (!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp); @@ -1372,7 +1372,7 @@ void HandleOtherConfiguration(void) return; } - char stemp[40]; + char stemp[sizeof(Settings.friendlyname[0])]; // Max length is currently 33 String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_CONFIGURE_OTHER)); @@ -1413,8 +1413,8 @@ void HandleOtherConfiguration(void) void OtherSaveSettings(void) { char tmp[128]; - char stemp[TOPSZ]; - char stemp2[TOPSZ]; + char webindex[5]; + char friendlyname[sizeof(Settings.friendlyname[0])]; WebGetArg("p1", tmp, sizeof(tmp)); strlcpy(Settings.web_password, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.web_password : tmp, sizeof(Settings.web_password)); @@ -1425,10 +1425,10 @@ void OtherSaveSettings(void) #endif // USE_EMULATION snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); for (uint8_t i = 0; i < MAX_FRIENDLYNAMES; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("a%d"), i +1); - WebGetArg(stemp, tmp, sizeof(tmp)); - snprintf_P(stemp2, sizeof(stemp2), PSTR(FRIENDLY_NAME"%d"), i +1); - strlcpy(Settings.friendlyname[i], (!strlen(tmp)) ? (i) ? stemp2 : FRIENDLY_NAME : tmp, sizeof(Settings.friendlyname[i])); + snprintf_P(webindex, sizeof(webindex), PSTR("a%d"), i +1); + WebGetArg(webindex, tmp, sizeof(tmp)); + snprintf_P(friendlyname, sizeof(friendlyname), PSTR(FRIENDLY_NAME"%d"), i +1); + strlcpy(Settings.friendlyname[i], (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp, sizeof(Settings.friendlyname[i])); snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", Settings.friendlyname[i]); } AddLog(LOG_LEVEL_INFO); @@ -1496,8 +1496,6 @@ void HandleResetConfiguration(void) { if (!HttpCheckPriviledgedAccess()) { return; } - char svalue[33]; - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESET_CONFIGURATION); String page = FPSTR(HTTP_HEAD); @@ -1508,8 +1506,9 @@ void HandleResetConfiguration(void) page += FPSTR(HTTP_BTN_MAIN); ShowPage(page, HTTP_MANAGER_RESET_ONLY != webserver_state); - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RESET " 1")); - ExecuteWebCommand(svalue, SRC_WEBGUI); + char command[CMDSZ]; + snprintf_P(command, sizeof(command), PSTR(D_CMND_RESET " 1")); + ExecuteWebCommand(command, SRC_WEBGUI); } void HandleRestoreConfiguration(void) @@ -1679,16 +1678,16 @@ void HandleUpgradeFirmwareStart(void) { if (!HttpCheckPriviledgedAccess()) { return; } - char svalue[100]; + char command[sizeof(Settings.ota_url) + 10]; // OtaUrl AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPGRADE_STARTED)); WifiConfigCounter(); - char tmp[100]; - WebGetArg("o", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_OTAURL " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); + char otaurl[sizeof(Settings.ota_url)]; + WebGetArg("o", otaurl, sizeof(otaurl)); + if (strlen(otaurl)) { + snprintf_P(command, sizeof(command), PSTR(D_CMND_OTAURL " %s"), otaurl); + ExecuteWebCommand(command, SRC_WEBGUI); } String page = FPSTR(HTTP_HEAD); @@ -1700,8 +1699,8 @@ void HandleUpgradeFirmwareStart(void) page.replace(F(""), FPSTR(HTTP_SCRIPT_RELOAD_OTA)); ShowPage(page); - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_UPGRADE " 1")); - ExecuteWebCommand(svalue, SRC_WEBGUI); + snprintf_P(command, sizeof(command), PSTR(D_CMND_UPGRADE " 1")); + ExecuteWebCommand(command, SRC_WEBGUI); } void HandleUploadDone(void) @@ -1960,9 +1959,9 @@ void HandleHttpCommand(void) uint8_t valid = 1; if (Settings.web_password[0] != 0) { - char tmp1[100]; + char tmp1[sizeof(Settings.web_password)]; WebGetArg("user", tmp1, sizeof(tmp1)); - char tmp2[100]; + char tmp2[sizeof(Settings.web_password)]; WebGetArg("password", tmp2, sizeof(tmp2)); if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, Settings.web_password))) { valid = 0; } } @@ -2039,7 +2038,7 @@ void HandleAjaxConsoleRefresh(void) ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE); } - char stmp[10]; + char stmp[8]; WebGetArg("c2", stmp, sizeof(stmp)); if (strlen(stmp)) { counter = atoi(stmp); } @@ -2075,7 +2074,7 @@ void HandleAjaxConsoleRefresh(void) } while (counter != web_log_index); } message += F("\1"); - WSSend(200, CT_XML, message); + WSSend(200, CT_PLAIN, message); } /********************************************************************************************/ From 68c60c321ea36a39fa217fa3d19215c0ac53767c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Feb 2019 19:19:31 +0100 Subject: [PATCH 1074/2222] Handle too many command data Handle too many command data --- sonoff/sonoff.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 161c26ed8..2a65f8f65 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -431,6 +431,8 @@ uint16_t GetPulseTimer(uint8_t index) void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) { + if (data_len > MQTT_MAX_PACKET_SIZE) { return; } // Do not allow more data than would be feasable within stack space + char *str; if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1])) { From 3298048c60676a4890f94b10379d914ca083c5bd Mon Sep 17 00:00:00 2001 From: Laurent <44267323+laurentdong@users.noreply.github.com> Date: Sat, 23 Feb 2019 17:41:06 -0500 Subject: [PATCH 1075/2222] Update support_rtc.ino --- sonoff/support_rtc.ino | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index 57f85d559..35f9b61e9 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -333,11 +333,6 @@ uint32_t LocalTime(void) return local_time; } -uint32_t UtcTime(void) -{ - return utc_time; -} - uint32_t Midnight(void) { return midnight; From dd27ade7efc9d978e9fdee21fbdfa90827b29e06 Mon Sep 17 00:00:00 2001 From: Laurent <44267323+laurentdong@users.noreply.github.com> Date: Sat, 23 Feb 2019 22:33:09 -0500 Subject: [PATCH 1076/2222] Rules: Trigger Event with MQTT Subscriptions Support subscribe/unsubscribe MQTT topics and trigger specified event with the subscribed MQTT topic. You can subscribe a MQTT topic and assign an event name. Once we received subscribed MQTT message, an event will be automatically triggered. So you can set up a rule with "ON EVENT# DO ..." to do whatever you want based on this MQTT message. The payload is passed as a parameter once the event been triggered. If the payload is in JSON format, you are able to get the value of specified key as parameter. For example, if you have a Tasmota based thermostat and multiple temperature sensors in different place, usually you have to set up a centre home automation system like Domoticz to control the thermostat. Right now, with this new feature, you can write a rule to do this. Two new commands in Rules: 1. Subscribe Subscribe a MQTT topic (with or without key) and assign an event name to it. Command format: Subscribe [, [, ]] This command will subscribe a and give it an event name . The optional parameter is for parse the specified key/value from MQTT message payload with JSON format. In order to parse value from two level JSON data, you can use one dot (".") to split the key into two section. Subscribe command without any parameter will list all topics currently subscribed. 2. Unsubscribe Unsubscribe specified MQTT event. Command format: Unsubscribe [] Unsubscribe a topic subscribed by specify the event name. If no event specified, Unsubscribe all topics subscribed. Examples: 1. Subscribe BkLight, Tasmota/BackyardLight/stat/POWER And define a rule like: Rule1 on event#BkLight=ON do ruletimer4 60 endon 2. Subscribe DnTemp, Tasmota/RoomSensor1/stat/SENSOR, DS18B20.Temperature Define a rule to deal with the MQTT message like {"Time":"2017-02-16T10:13:52", "DS18B20":{"Temperature":20.6}} Rule1 ON EVENT#DnTemp>=21 DO ... ENDON --- sonoff/language/en-GB.h | 1 + sonoff/my_user_config.h | 1 + sonoff/xdrv_02_mqtt.ino | 31 +++++- sonoff/xdrv_10_rules.ino | 215 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 242 insertions(+), 6 deletions(-) diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 794af57fa..e459cd02d 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -148,6 +148,7 @@ #define D_STOP "Stop" #define D_SUBNET_MASK "Subnet Mask" #define D_SUBSCRIBE_TO "Subscribe to" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" #define D_SUCCESSFUL "Successful" #define D_SUNRISE "Sunrise" #define D_SUNSET "Sunset" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index f0cd75cf6..c4ac51eff 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -280,6 +280,7 @@ // -- Rules --------------------------------------- #define USE_RULES // Add support for rules (+4k4 code) #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) + #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) // -- Internal Analog input ----------------------- #define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index fa681e309..8721b42b2 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -110,12 +110,18 @@ void MqttDisconnect(void) MqttClient.disconnect(); } -void MqttSubscribeLib(char *topic) +void MqttSubscribeLib(const char *topic) { MqttClient.subscribe(topic); MqttClient.loop(); // Solve LmacRxBlk:1 messages } +void MqttUnsubscribeLib(const char *topic) +{ + MqttClient.unsubscribe(topic); + MqttClient.loop(); // Solve LmacRxBlk:1 messages +} + bool MqttPublishLib(const char* topic, bool retained) { bool result = MqttClient.publish(topic, mqtt_data, retained); @@ -148,11 +154,16 @@ void MqttDisconnectedCb(void) MqttDisconnected(MqttClient.State()); // status codes are documented in file mqtt.h as tConnState } -void MqttSubscribeLib(char *topic) +void MqttSubscribeLib(const char *topic) { MqttClient.Subscribe(topic, 0); } +void MqttUnsubscribeLib(const char *topic) +{ + MqttClient.Unsubscribe(topic, 0); +} + bool MqttPublishLib(const char* topic, bool retained) { return MqttClient.Publish(topic, mqtt_data, strlen(mqtt_data), 0, retained); @@ -190,11 +201,16 @@ void MqttMyDataCb(String &topic, String &data) MqttDataHandler((char*)topic.c_str(), (uint8_t*)data.c_str(), data.length()); } -void MqttSubscribeLib(char *topic) +void MqttSubscribeLib(const char *topic) { MqttClient.subscribe(topic, 0); } +void MqttUnsubscribeLib(const char *topic) +{ + MqttClient.unsubscribe(topic, 0); +} + bool MqttPublishLib(const char* topic, bool retained) { return MqttClient.publish(topic, mqtt_data, strlen(mqtt_data), retained, 0); @@ -251,13 +267,20 @@ void MqttRetryCounter(uint8_t value) mqtt_retry_counter = value; } -void MqttSubscribe(char *topic) +void MqttSubscribe(const char *topic) { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_SUBSCRIBE_TO " %s"), topic); AddLog(LOG_LEVEL_DEBUG); MqttSubscribeLib(topic); } +void MqttUnsubscribe(const char *topic) +{ + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_UNSUBSCRIBE_FROM " %s"), topic); + AddLog(LOG_LEVEL_DEBUG); + MqttUnsubscribeLib(topic); +} + void MqttPublishDirect(const char* topic, bool retained) { char sretained[CMDSZ]; diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 08c6c362b..2a58ea880 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -75,6 +75,8 @@ #define D_CMND_MULT "Mult" #define D_CMND_SCALE "Scale" #define D_CMND_CALC_RESOLUTION "CalcRes" +#define D_CMND_SUBSCRIBE "Subscribe" +#define D_CMND_UNSUBSCRIBE "Unsubscribe" #define D_JSON_INITIATED "Initiated" @@ -105,8 +107,18 @@ const char kCompareOperators[] PROGMEM = "=\0>\0<\0|\0==!=>=<="; #define MAX_EXPRESSION_OPERATOR_PRIORITY 4 #endif // USE_EXPRESSION -enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM, CMND_ADD, CMND_SUB, CMND_MULT, CMND_SCALE, CMND_CALC_RESOLUTION }; -const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM "|" D_CMND_ADD "|" D_CMND_SUB "|" D_CMND_MULT "|" D_CMND_SCALE "|" D_CMND_CALC_RESOLUTION ; +enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM, CMND_ADD, CMND_SUB, CMND_MULT, CMND_SCALE, CMND_CALC_RESOLUTION, CMND_SUBSCRIBE, CMND_UNSUBSCRIBE }; +const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM "|" D_CMND_ADD "|" D_CMND_SUB "|" D_CMND_MULT "|" D_CMND_SCALE "|" D_CMND_CALC_RESOLUTION "|" D_CMND_SUBSCRIBE "|" D_CMND_UNSUBSCRIBE ; + +#ifdef SUPPORT_MQTT_EVENT + #include // Import LinkedList library + typedef struct { + String Event; + String Topic; + String Key; + } MQTT_Subscription; + LinkedList subscriptions; +#endif //SUPPORT_MQTT_EVENT String rules_event_value; unsigned long rules_timer[MAX_RULE_TIMERS] = { 0 }; @@ -577,6 +589,192 @@ void RulesTeleperiod(void) rules_teleperiod = 0; } +#ifdef SUPPORT_MQTT_EVENT +/********************************************************************************************/ +/* + * Rules: Process received MQTT message. + * If the message is in our subscription list, trigger an event with the value parsed from MQTT data + * Input: + * void - We are going to access XdrvMailbox data directly. + * Return: + * true - The message is consumed. + * false - The message is not in our list. + */ +bool RulesMqttData(void) +{ + bool serviced = false; + if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 128) { + return false; + } + String sTopic = XdrvMailbox.topic; + String sData = XdrvMailbox.data; + //snprintf_P(log_data, sizeof(log_data), PSTR("RUL: MQTT Topic %s, Event %s"), XdrvMailbox.topic, XdrvMailbox.data); + //AddLog(LOG_LEVEL_DEBUG); + MQTT_Subscription event_item; + //Looking for matched topic + for (int index = 0; index < subscriptions.size(); index++) { + event_item = subscriptions.get(index); + + //snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Match MQTT message Topic %s with subscription topic %s"), sTopic.c_str(), event_item.Topic.c_str()); + //AddLog(LOG_LEVEL_DEBUG); + if (sTopic.startsWith(event_item.Topic)) { + //This topic is subscribed by us, so serve it + serviced = true; + String value; + if (event_item.Key.length() == 0) { //If did not specify Key + value = sData; + } else { //If specified Key, need to parse Key/Value from JSON data + StaticJsonBuffer<400> jsonBuf; + JsonObject& jsonData = jsonBuf.parseObject(sData); + String key1 = event_item.Key; + String key2; + if (!jsonData.success()) break; //Failed to parse JSON data, ignore this message. + int dot; + if ((dot = key1.indexOf('.')) > 0) { + key2 = key1.substring(dot+1); + key1 = key1.substring(0, dot); + if (!jsonData[key1][key2].success()) break; //Failed to get the key/value, ignore this message. + value = (const char *)jsonData[key1][key2]; + } else { + if (!jsonData[key1].success()) break; + value = (const char *)jsonData[key1]; + } + } + value.trim(); + //Create an new event. Cannot directly call RulesProcessEvent(). + snprintf_P(event_data, sizeof(event_data), PSTR("%s=%s"), event_item.Event.c_str(), value.c_str()); + } + } + return serviced; +} + +/********************************************************************************************/ +/* + * Subscribe a MQTT topic (with or without key) and assign an event name to it + * Command Subscribe format: + * Subscribe , [, ] + * This command will subscribe a and give it an event name . + * The optional parameter is for parse the specified key/value from MQTT message + * payload with JSON format. + * Subscribe + * Subscribe command without any parameter will list all topics currently subscribed. + * Input: + * data - A char buffer with all the parameters + * data_len - Length of the parameters + * Return: + * A string include subscribed event, topic and key. + */ +String RulesSubscribe(const char *data, int data_len) +{ + MQTT_Subscription subscription_item; + String events; + if (data_len > 0) { + char parameters[data_len+1]; + memcpy(parameters, data, data_len); + parameters[data_len] = '\0'; + String event_name, topic, key; + + char * pos = strtok(parameters, ","); + if (pos) { + event_name = Trim(pos); + pos = strtok(NULL, ","); + if (pos) { + topic = Trim(pos); + pos = strtok(NULL, ","); + if (pos) { + key = Trim(pos); + } + } + } + //snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Subscribe command with parameters: %s, %s, %s."), event_name.c_str(), topic.c_str(), key.c_str()); + //AddLog(LOG_LEVEL_DEBUG); + event_name.toUpperCase(); + if (event_name.length() > 0 && topic.length() > 0) { + //Search all subscriptions + for (int index=0; index < subscriptions.size(); index++) { + if (subscriptions.get(index).Event.equals(event_name)) { + //If find exists one, remove it. + String stopic = subscriptions.get(index).Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + subscriptions.remove(index); + break; + } + } + //Add "/#" to the topic + if (!topic.endsWith("#")) { + if (topic.endsWith("/")) { + topic.concat("#"); + } else { + topic.concat("/#"); + } + } + //snprintf_P(log_data, sizeof(log_data), PSTR("RUL: New topic: %s."), topic.c_str()); + //AddLog(LOG_LEVEL_DEBUG); + //MQTT Subscribe + subscription_item.Event = event_name; + subscription_item.Topic = topic.substring(0, topic.length() - 2); //Remove "/#" so easy to match + subscription_item.Key = key; + subscriptions.add(subscription_item); + + MqttSubscribe(topic.c_str()); + events.concat(event_name + "," + topic + + (key.length()>0 ? "," : "") + + key); + } else { + events = D_JSON_WRONG_PARAMETERS; + } + } else { + //If did not specify the event name, list all subscribed event + for (int index=0; index < subscriptions.size(); index++) { + subscription_item = subscriptions.get(index); + events.concat(subscription_item.Event + "," + subscription_item.Topic + + (subscription_item.Key.length()>0 ? "," : "") + + subscription_item.Key + "; "); + } + } + return events; +} + +/********************************************************************************************/ +/* + * Unsubscribe specified MQTT event. If no event specified, Unsubscribe all. + * Command Unsubscribe format: + * Unsubscribe [] + * Input: + * data - Event name + * data_len - Length of the parameters + * Return: + * list all the events unsubscribed. + */ +String RulesUnsubscribe(const char * data, int data_len) +{ + MQTT_Subscription subscription_item; + String events; + if (data_len > 0) { + for (int index = 0; index < subscriptions.size(); index++) { + subscription_item = subscriptions.get(index); + if (subscription_item.Event.equalsIgnoreCase(data)) { + String stopic = subscription_item.Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + events = subscription_item.Event; + subscriptions.remove(index); + break; + } + } + } else { + //If did not specify the event name, unsubscribe all event + String stopic; + while (subscriptions.size() > 0) { + events.concat(subscriptions.get(0).Event + "; "); + stopic = subscriptions.get(0).Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + subscriptions.remove(0); + } + } + return events; +} +#endif // SUPPORT_MQTT_EVENT + #ifdef USE_EXPRESSION /********************************************************************************************/ /* @@ -1026,6 +1224,14 @@ bool RulesCommand(void) } } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); +#ifdef SUPPORT_MQTT_EVENT + } else if (CMND_SUBSCRIBE == command_code) { //MQTT Subscribe command. Subscribe , [, ] + String result = RulesSubscribe(XdrvMailbox.data, XdrvMailbox.data_len); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, result.c_str()); + } else if (CMND_UNSUBSCRIBE == command_code) { //MQTT Un-subscribe command. UnSubscribe + String result = RulesUnsubscribe(XdrvMailbox.data, XdrvMailbox.data_len); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, result.c_str()); +#endif //SUPPORT_MQTT_EVENT } else serviced = false; // Unknown command @@ -1067,6 +1273,11 @@ bool Xdrv10(uint8_t function) case FUNC_RULES_PROCESS: result = RulesProcess(); break; +#ifdef SUPPORT_MQTT_EVENT + case FUNC_MQTT_DATA: + result = RulesMqttData(); + break; +#endif //SUPPORT_MQTT_EVENT } return result; } From 38b81302e39f9dcfc3a1df9b02b696883a67c4e6 Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Sun, 24 Feb 2019 09:26:10 +0400 Subject: [PATCH 1077/2222] sm16716: added config option for custom rgb order --- sonoff/my_user_config.h | 1 + sonoff/sonoff.h | 7 +++++++ sonoff/xdrv_04_light.ino | 30 ++++++++++++++++++++++++------ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index f0cd75cf6..d447eed08 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -421,6 +421,7 @@ // #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver (+1k7 code) #define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) + #define USE_SM16716_RGB_ORDER SM16716_RGB // SM16716 RGB order (SM16716_RGB, SM16716_RBG, SM16716_GRB, SM16716_GBR, SM16716_BRG, SM16716_BGR) /*********************************************************************************************\ * Debug features are only supported in development branch diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index c86733621..a30cf4019 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -171,6 +171,13 @@ typedef unsigned long power_t; // Power (Relay) type #define LT_SM16716 16 // Lights that use SM16716 will have this bit set in light_type +#define SM16716_RGB 0 +#define SM16716_RBG 1 +#define SM16716_GRB 2 +#define SM16716_GBR 3 +#define SM16716_BRG 4 +#define SM16716_BGR 5 + #define MQTT_PUBSUBCLIENT 1 // Mqtt PubSubClient library #define MQTT_TASMOTAMQTT 2 // Mqtt TasmotaMqtt library based on esp-mqtt-arduino - soon obsolete #define MQTT_ESPMQTTARDUINO 3 // Mqtt esp-mqtt-arduino library by Ingo Randolf - obsolete but define is present for debugging purposes diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 8a5259f64..9083372dd 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -397,6 +397,12 @@ void SM16716_SendByte(uint8_t v) } } +void SM16716_SendRGB(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) { + SM16716_SendByte(duty_r); + SM16716_SendByte(duty_g); + SM16716_SendByte(duty_b); +} + void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) { if (sm16716_pin_sel < 99) { @@ -432,17 +438,29 @@ void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) // send start bit SM16716_SendBit(1); // send 24-bit rgb data - SM16716_SendByte(duty_r); - SM16716_SendByte(duty_g); - SM16716_SendByte(duty_b); +#if USE_SM16716_RGB_ORDER == SM16716_RGB + SM16716_SendRGB(duty_r, duty_g, duty_b); +#elif USE_SM16716_RGB_ORDER == SM16716_RBG + SM16716_SendRGB(duty_r, duty_b, duty_g); +#elif USE_SM16716_RGB_ORDER == SM16716_GRB + SM16716_SendRGB(duty_g, duty_r, duty_b); +#elif USE_SM16716_RGB_ORDER == SM16716_GBR + SM16716_SendRGB(duty_g, duty_b, duty_r); +#elif USE_SM16716_RGB_ORDER == SM16716_BRG + SM16716_SendRGB(duty_b, duty_r, duty_g); +#elif USE_SM16716_RGB_ORDER == SM16716_BGR + SM16716_SendRGB(duty_b, duty_g, duty_r); +#else + // fall back to RGB + SM16716_SendRGB(duty_r, duty_g, duty_b); +#endif + // send a 'do it' pulse // (if multiple chips are chained, each one processes the 1st '1rgb' 25-bit block and // passes on the rest, right until the one starting with 0) //SM16716_Init(); SM16716_SendBit(0); - SM16716_SendByte(0); - SM16716_SendByte(0); - SM16716_SendByte(0); + SM16716_SendRGB(0, 0, 0); } bool SM16716_ModuleSelected(void) From ca237a312367b7f9776288ba175a9ddf2d429537 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sun, 24 Feb 2019 11:15:40 +0100 Subject: [PATCH 1078/2222] Platformio 2.0.1 (Core 2.5.0) Platformio is back to working build toolchain from core 2.4.2. --- platformio.ini | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index af1adb697..f57883985 100644 --- a/platformio.ini +++ b/platformio.ini @@ -65,9 +65,8 @@ build_flags = ${esp82xx_defaults.build_flags} -DVTABLES_IN_FLASH [core_2_5_0] -; *** Esp8266 core for Arduino version 2.5.0 (since version from platformio is faulty) -platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota -;platform = espressif8266@2.0.0 +; *** Esp8266 core for Arduino version 2.5.0 +platform = espressif8266@2.0.1 build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld ; lwIP 1.4 (Default) From 4492a145743e2dee6ea1382f5a196baae51368e5 Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Sun, 24 Feb 2019 12:07:15 +0000 Subject: [PATCH 1079/2222] Added SetOption37 for RGB remapping --- sonoff/.gitignore | 3 ++ sonoff/.travis.yml | 67 ++++++++++++++++++++++++++++++++++++++++ sonoff/my_user_config.h | 1 - sonoff/settings.ino | 4 +++ sonoff/sonoff.h | 18 ++++++----- sonoff/xdrv_04_light.ino | 45 +++++++++++++-------------- 6 files changed, 106 insertions(+), 32 deletions(-) create mode 100644 sonoff/.gitignore create mode 100644 sonoff/.travis.yml diff --git a/sonoff/.gitignore b/sonoff/.gitignore new file mode 100644 index 000000000..58e33b977 --- /dev/null +++ b/sonoff/.gitignore @@ -0,0 +1,3 @@ +.pio +.pioenvs +.piolibdeps diff --git a/sonoff/.travis.yml b/sonoff/.travis.yml new file mode 100644 index 000000000..7c486f183 --- /dev/null +++ b/sonoff/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index d447eed08..f0cd75cf6 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -421,7 +421,6 @@ // #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver (+1k7 code) #define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) - #define USE_SM16716_RGB_ORDER SM16716_RGB // SM16716 RGB order (SM16716_RGB, SM16716_RBG, SM16716_GRB, SM16716_GBR, SM16716_BRG, SM16716_BGR) /*********************************************************************************************\ * Debug features are only supported in development branch diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 2fb9a9afa..c18d60d3f 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -587,6 +587,7 @@ void SettingsDefaultSet2(void) // Settings.flag.stop_flash_rotate = 0; Settings.save_data = SAVE_DATA; Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; + Settings.param[P_RGB_REMAP] = RGB_REMAP_RGB; Settings.sleep = APP_SLEEP; if (Settings.sleep < 50) { Settings.sleep = 50; // Default to 50 for sleep, for now @@ -1055,6 +1056,9 @@ void SettingsDelta(void) if (Settings.version < 0x06040110) { ModuleDefault(WEMOS); } + if (Settings.version < 0x06040112) { + Settings.param[P_RGB_REMAP] = RGB_REMAP_RGB; + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index a30cf4019..aafc98615 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -171,12 +171,16 @@ typedef unsigned long power_t; // Power (Relay) type #define LT_SM16716 16 // Lights that use SM16716 will have this bit set in light_type -#define SM16716_RGB 0 -#define SM16716_RBG 1 -#define SM16716_GRB 2 -#define SM16716_GBR 3 -#define SM16716_BRG 4 -#define SM16716_BGR 5 +// Remap constants are 3-digit ternary numbers, each digit tells where the corresponding color component is mapped *from* +// digit 0 = ( n % 3) tells where the red is mapped from (0=red, 1=green, 2=blue) +// digit 1 = ((n/3) % 3) tells where the green is mapped from +// digit 2 = ((n/9) % 3) tells where the blue is mapped from +#define RGB_REMAP_RGB (0*1 + 1*3 + 2*9) +#define RGB_REMAP_RBG (0*1 + 2*3 + 1*9) +#define RGB_REMAP_GRB (1*1 + 0*3 + 2*9) +#define RGB_REMAP_GBR (1*1 + 2*3 + 0*9) +#define RGB_REMAP_BRG (2*1 + 0*3 + 1*9) +#define RGB_REMAP_BGR (2*1 + 1*3 + 0*9) #define MQTT_PUBSUBCLIENT 1 // Mqtt PubSubClient library #define MQTT_TASMOTAMQTT 2 // Mqtt TasmotaMqtt library based on esp-mqtt-arduino - soon obsolete @@ -237,7 +241,7 @@ enum ButtonStates { PRESSED, NOT_PRESSED }; enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; -enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 +enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_MAX_SENSORS}; diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 9083372dd..54085a4ba 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -397,12 +397,6 @@ void SM16716_SendByte(uint8_t v) } } -void SM16716_SendRGB(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) { - SM16716_SendByte(duty_r); - SM16716_SendByte(duty_g); - SM16716_SendByte(duty_b); -} - void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) { if (sm16716_pin_sel < 99) { @@ -437,30 +431,18 @@ void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) // send start bit SM16716_SendBit(1); - // send 24-bit rgb data -#if USE_SM16716_RGB_ORDER == SM16716_RGB - SM16716_SendRGB(duty_r, duty_g, duty_b); -#elif USE_SM16716_RGB_ORDER == SM16716_RBG - SM16716_SendRGB(duty_r, duty_b, duty_g); -#elif USE_SM16716_RGB_ORDER == SM16716_GRB - SM16716_SendRGB(duty_g, duty_r, duty_b); -#elif USE_SM16716_RGB_ORDER == SM16716_GBR - SM16716_SendRGB(duty_g, duty_b, duty_r); -#elif USE_SM16716_RGB_ORDER == SM16716_BRG - SM16716_SendRGB(duty_b, duty_r, duty_g); -#elif USE_SM16716_RGB_ORDER == SM16716_BGR - SM16716_SendRGB(duty_b, duty_g, duty_r); -#else - // fall back to RGB - SM16716_SendRGB(duty_r, duty_g, duty_b); -#endif + SM16716_SendByte(duty_r); + SM16716_SendByte(duty_g); + SM16716_SendByte(duty_b); // send a 'do it' pulse // (if multiple chips are chained, each one processes the 1st '1rgb' 25-bit block and // passes on the rest, right until the one starting with 0) //SM16716_Init(); SM16716_SendBit(0); - SM16716_SendRGB(0, 0, 0); + SM16716_SendByte(0); + SM16716_SendByte(0); + SM16716_SendByte(0); } bool SM16716_ModuleSelected(void) @@ -980,6 +962,21 @@ void LightAnimate(void) light_last_color[i] = light_new_color[i]; cur_col[i] = light_last_color[i]*Settings.rgbwwTable[i]/255; cur_col[i] = (Settings.light_correction) ? ledTable[cur_col[i]] : cur_col[i]; + } + + // RGB remapping + uint8_t rgb_mapping = Settings.param[P_RGB_REMAP]; + + if (rgb_mapping != RGB_REMAP_RGB) { + uint8_t orig_col[3]; + memcpy(orig_col, cur_col, sizeof(orig_col)); + for (uint8_t i = 0; i < 3; i++) { + cur_col[i] = orig_col[rgb_mapping % 3]; + rgb_mapping /= 3; + } + } + + for (uint8_t i = 0; i < light_subtype; i++) { if (light_type < LT_PWM6) { if (pin[GPIO_PWM1 +i] < 99) { if (cur_col[i] > 0xFC) { From 0bb05bb604b66fc595d8af2a19e973780ac5035b Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Sun, 24 Feb 2019 16:41:54 +0400 Subject: [PATCH 1080/2222] Delete .travis.yml meanwhile removed at adc781b8fcfb173787c192763a3046412c0dd783 --- sonoff/.travis.yml | 67 ---------------------------------------------- 1 file changed, 67 deletions(-) delete mode 100644 sonoff/.travis.yml diff --git a/sonoff/.travis.yml b/sonoff/.travis.yml deleted file mode 100644 index 7c486f183..000000000 --- a/sonoff/.travis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Continuous Integration (CI) is the practice, in software -# engineering, of merging all developer working copies with a shared mainline -# several times a day < https://docs.platformio.org/page/ci/index.html > -# -# Documentation: -# -# * Travis CI Embedded Builds with PlatformIO -# < https://docs.travis-ci.com/user/integration/platformio/ > -# -# * PlatformIO integration with Travis CI -# < https://docs.platformio.org/page/ci/travis.html > -# -# * User Guide for `platformio ci` command -# < https://docs.platformio.org/page/userguide/cmd_ci.html > -# -# -# Please choose one of the following templates (proposed below) and uncomment -# it (remove "# " before each line) or use own configuration according to the -# Travis CI documentation (see above). -# - - -# -# Template #1: General project. Test it using existing `platformio.ini`. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio run - - -# -# Template #2: The project is intended to be used as a library with examples. -# - -# language: python -# python: -# - "2.7" -# -# sudo: false -# cache: -# directories: -# - "~/.platformio" -# -# env: -# - PLATFORMIO_CI_SRC=path/to/test/file.c -# - PLATFORMIO_CI_SRC=examples/file.ino -# - PLATFORMIO_CI_SRC=path/to/test/directory -# -# install: -# - pip install -U platformio -# - platformio update -# -# script: -# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N From 0a4a21a038261e8f9f1d97650c5eabb4f4ce292c Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Sun, 24 Feb 2019 16:43:42 +0400 Subject: [PATCH 1081/2222] Delete .gitignore created by mistake --- sonoff/.gitignore | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 sonoff/.gitignore diff --git a/sonoff/.gitignore b/sonoff/.gitignore deleted file mode 100644 index 58e33b977..000000000 --- a/sonoff/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.pio -.pioenvs -.piolibdeps From 9b6e5bd1222c7fa3a807466caf2b27d48cb806ba Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 24 Feb 2019 15:05:18 +0100 Subject: [PATCH 1082/2222] Webserver Ajax optimizations Webserver Ajax optimizations --- sonoff/xdrv_01_webserver.ino | 51 ++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index ef6083d2b..f954fae40 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -131,7 +131,7 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "x.onreadystatechange=function(){" "if(x.readyState==4&&x.status==200){" "var z,d;" - "d=x.responseText.split(/\1/);" + "d=x.responseText.split(/\1/);" // Field separator "id=d.shift();" "if(d.shift()==0){t.value='';}" "z=d.shift();" @@ -149,10 +149,13 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "window.onload=l;" ""; +const char HTTP_MODULE_TEMPLATE_REPLACE[] PROGMEM = + "\2%d'>%s (%d\3"; // \2 and \3 are used in below os.replace + const char HTTP_SCRIPT_MODULE_TEMPLATE[] PROGMEM = "var os;" "function sk(s,g){" // s = value, g = id and name - "var o=os.replace(/}1/g,\"
"); } for (uint8_t j = 0; j < 4; j++) { idx++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), idx, idx); // ?k is related to WebGetArg("k", tmp, sizeof(tmp)); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), idx, idx); // ?k is related to WebGetArg("k", tmp, sizeof(tmp)); page += mqtt_data; } } From d70ed77f1a60859b068ee97ce2ba4103ca20650c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 1 Mar 2019 18:25:46 +0100 Subject: [PATCH 1109/2222] Update xdrv_01_webserver.ino Prep for chunks --- sonoff/xdrv_01_webserver.ino | 155 +++++++++++++++++++---------------- 1 file changed, 84 insertions(+), 71 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index a0f01a763..6070d8ac8 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -76,7 +76,7 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "a=p;" "clearTimeout(lt);" "}" - "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1) + "if(x!=null){x.abort();}" // Abort if no response within Settings.web_refresh milliseconds (happens on restart 1) "x=new XMLHttpRequest();" "x.onreadystatechange=function(){" "if(x.readyState==4&&x.status==200){" @@ -84,15 +84,15 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "eb('l1').innerHTML=s;" "}" "};" - "x.open('GET','ay'+a,true);" + "x.open('GET','?m=1'+a,true);" // ?m related to WebServer->hasArg("m") "x.send();" "lt=setTimeout(la,{a});" // Settings.web_refresh "}" "function lb(p){" - "la('?d='+p);" // ?d related to WebGetArg("d", tmp, sizeof(tmp)); + "la('&d='+p);" // &d related to WebGetArg("d", tmp, sizeof(tmp)); "}" "function lc(p){" - "la('?t='+p);" // ?t related to WebGetArg("t", tmp, sizeof(tmp)); + "la('&t='+p);" // &t related to WebGetArg("t", tmp, sizeof(tmp)); "}" "window.onload=la();"; @@ -140,7 +140,7 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "sn=t.scrollTop;" "}" "};" - "x.open('GET','ax?c2='+id+o,true);" + "x.open('GET','cs?c2='+id+o,true);" // Related to WebServer->hasArg("c2") and WebGetArg("c2", stmp, sizeof(stmp)) "x.send();" "}" "lt=setTimeout(l,{a});" @@ -431,7 +431,7 @@ const char HTTP_END[] PROGMEM = "" ""; -const char HTTP_DEVICE_CONTROL[] PROGMEM = ""; // ?o is related to WebGetArg("o", tmp, sizeof(tmp)); +const char HTTP_DEVICE_CONTROL[] PROGMEM = ""; // ?o is related to WebGetArg("o", tmp, sizeof(tmp)); const char HTTP_DEVICE_STATE[] PROGMEM = "%s"; // {c} = %'>
"); - if (devices_present) { - if (light_type) { - if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MSG_SLIDER1, LightGetColorTemp()); - page += mqtt_data; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MSG_SLIDER2, Settings.light_dimmer); + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_MAIN_MENU); + + char stemp[5]; + + String page = FPSTR(HTTP_HEAD); + page.replace(F("{v}"), FPSTR(S_MAIN_MENU)); + page += FPSTR(HTTP_SCRIPT_ROOT); + page += FPSTR(HTTP_HEAD_STYLE); + + page += F("
"); + if (devices_present) { + if (light_type) { + if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MSG_SLIDER1, LightGetColorTemp()); page += mqtt_data; } - page += FPSTR(HTTP_TABLE100); - page += F(""); - if (SONOFF_IFAN02 == my_module_type) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MSG_SLIDER2, Settings.light_dimmer); + page += mqtt_data; + } + page += FPSTR(HTTP_TABLE100); + page += F(""); + if (SONOFF_IFAN02 == my_module_type) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); + page += mqtt_data; + for (uint8_t i = 0; i < MAX_FAN_SPEED; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 16, i +2, stemp, ""); page += mqtt_data; - for (uint8_t i = 0; i < MAX_FAN_SPEED; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 16, i +2, stemp, ""); - page += mqtt_data; - } - } else { - for (uint8_t idx = 1; idx <= devices_present; idx++) { - snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, - 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); - page += mqtt_data; - } } - page += F("
%s
%s
%s
"); - } - if (SONOFF_BRIDGE == my_module_type) { - page += FPSTR(HTTP_TABLE100); - page += F("
"); } + page += F(""); + } + if (SONOFF_BRIDGE == my_module_type) { + page += FPSTR(HTTP_TABLE100); + page += F(""); + uint8_t idx = 0; + for (uint8_t i = 0; i < 4; i++) { + if (idx > 0) { page += F(""); } + for (uint8_t j = 0; j < 4; j++) { + idx++; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), idx, idx); // ?k is related to WebGetArg("k", tmp, sizeof(tmp)); + page += mqtt_data; + } + } + page += F(""); + } #ifndef FIRMWARE_MINIMAL - mqtt_data[0] = '\0'; - XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); - XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); - page += String(mqtt_data); + mqtt_data[0] = '\0'; + XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); + XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); + page += String(mqtt_data); #endif // Not FIRMWARE_MINIMAL - if (HTTP_ADMIN == webserver_state) { - page += FPSTR(HTTP_BTN_MENU1); - page += FPSTR(HTTP_BTN_RSTRT); - } - ShowPage(page); + if (HTTP_ADMIN == webserver_state) { + page += FPSTR(HTTP_BTN_MENU1); + page += FPSTR(HTTP_BTN_RSTRT); } + ShowPage(page); } -void HandleAjaxStatusRefresh(void) +bool HandleRootStatusRefresh(void) { - if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } + if (!WebAuthenticate()) { + WebServer->requestAuthentication(); + return true; + } + + if (!WebServer->hasArg("m")) { // Status refresh requested + return false; + } char tmp[8]; // WebGetArg numbers only char svalue[32]; // Command and number parameter @@ -864,6 +873,7 @@ void HandleAjaxStatusRefresh(void) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s"), mqtt_data); } WSSend(200, CT_HTML, mqtt_data); + return true; } bool HttpCheckPriviledgedAccess(bool autorequestauth = true) @@ -2016,6 +2026,11 @@ void HandleConsole(void) { if (!HttpCheckPriviledgedAccess()) { return; } + if (WebServer->hasArg("c2")) { // Console refresh requested + HandleConsoleRefresh(); + return; + } + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONSOLE); String page = FPSTR(HTTP_HEAD); @@ -2027,10 +2042,8 @@ void HandleConsole(void) ShowPage(page); } -void HandleAjaxConsoleRefresh(void) +void HandleConsoleRefresh(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - bool cflg = true; uint8_t counter = 0; // Initial start, should never be 0 again From 9f42e6dced15136697a414dd173f1bfc495cf415 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 2 Mar 2019 12:33:52 +0100 Subject: [PATCH 1110/2222] Fix DS18S20 temperature calculation Fix DS18S20 temperature calculation (#5375) --- sonoff/_changelog.ino | 1 + sonoff/xsns_05_ds18x20.ino | 76 +++++++++++++++---------------- sonoff/xsns_05_ds18x20_legacy.ino | 6 +-- 3 files changed, 38 insertions(+), 45 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0214da3cd..3690ecf4a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Add command SetOption37 for RGBCW color mapping (#5326) * Add Korean language translations (#5344) * Fix Energy TotalStartTime when commands EnergyReset0 and/or EnergyReset3 used (#5373) + * Fix DS18S20 temperature calculation (#5375) * * 6.4.1.18 20190221 * Fix some exceptions and watchdogs due to lack of stack space - part 1 (#5215) diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index d8cbd7189..cdf1be836 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -310,9 +310,6 @@ bool Ds18x20Read(uint8_t sensor) { uint8_t data[9]; int8_t sign = 1; - uint16_t temp12 = 0; - int16_t temp14 = 0; - float temp9 = 0.0; uint8_t index = ds18x20_sensor[sensor].index; if (ds18x20_sensor[index].valid) { ds18x20_sensor[index].valid--; } @@ -325,48 +322,47 @@ bool Ds18x20Read(uint8_t sensor) } if (OneWireCrc8(data)) { switch(ds18x20_sensor[index].address[0]) { - case DS18S20_CHIPID: - if (data[1] > 0x80) { - data[0] = (~data[0]) +1; - sign = -1; // App-Note fix possible sign error + case DS18S20_CHIPID: { + if (data[1] > 0x80) { + data[0] = (~data[0]) +1; + sign = -1; // App-Note fix possible sign error + } + float temp9 = (float)(data[0] >> 1) * sign; + ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; } - if (data[0] & 1) { - temp9 = ((data[0] >> 1) + 0.5) * sign; - } else { - temp9 = (data[0] >> 1) * sign; - } - ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); - ds18x20_sensor[index].valid = SENSOR_MAX_MISS; - return true; - case DS1822_CHIPID: - case DS18B20_CHIPID: - if (data[4] != 0x7F) { - data[4] = 0x7F; // Set resolution to 12-bit - OneWireReset(); - OneWireSelect(ds18x20_sensor[index].address); - OneWireWrite(W1_WRITE_SCRATCHPAD); - OneWireWrite(data[2]); // Th Register - OneWireWrite(data[3]); // Tl Register - OneWireWrite(data[4]); // Configuration Register - OneWireSelect(ds18x20_sensor[index].address); - OneWireWrite(W1_WRITE_EEPROM); // Save scratchpad to EEPROM + case DS1822_CHIPID: + case DS18B20_CHIPID: { + if (data[4] != 0x7F) { + data[4] = 0x7F; // Set resolution to 12-bit + OneWireReset(); + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_WRITE_SCRATCHPAD); + OneWireWrite(data[2]); // Th Register + OneWireWrite(data[3]); // Tl Register + OneWireWrite(data[4]); // Configuration Register + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_WRITE_EEPROM); // Save scratchpad to EEPROM #ifdef W1_PARASITE_POWER - w1_power_until = millis() + 10; // 10ms specified duration for EEPROM write + w1_power_until = millis() + 10; // 10ms specified duration for EEPROM write #endif + } + uint16_t temp12 = (data[1] << 8) + data[0]; + if (temp12 > 2047) { + temp12 = (~temp12) +1; + sign = -1; + } + ds18x20_sensor[index].temperature = ConvertTemp(sign * temp12 * 0.0625); // Divide by 16 + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; } - temp12 = (data[1] << 8) + data[0]; - if (temp12 > 2047) { - temp12 = (~temp12) +1; - sign = -1; + case MAX31850_CHIPID: { + int16_t temp14 = (data[1] << 8) + (data[0] & 0xFC); + ds18x20_sensor[index].temperature = ConvertTemp(temp14 * 0.0625); // Divide by 16 + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; } - ds18x20_sensor[index].temperature = ConvertTemp(sign * temp12 * 0.0625); // Divide by 16 - ds18x20_sensor[index].valid = SENSOR_MAX_MISS; - return true; - case MAX31850_CHIPID: - temp14 = (data[1] << 8) + (data[0] & 0xFC); - ds18x20_sensor[index].temperature = ConvertTemp(temp14 * 0.0625); // Divide by 16 - ds18x20_sensor[index].valid = SENSOR_MAX_MISS; - return true; } } } diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index 3f6474044..cb07bf63c 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -126,11 +126,7 @@ bool Ds18x20Read(uint8_t sensor, float &t) data[0] = (~data[0]) +1; sign = -1; // App-Note fix possible sign error } - if (data[0] & 1) { - temp9 = ((data[0] >> 1) + 0.5) * sign; - } else { - temp9 = (data[0] >> 1) * sign; - } + temp9 = (float)(data[0] >> 1) * sign; t = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); break; case DS18B20_CHIPID: From de220cefd064d5c9bd78c1fc59d1269e677de37a Mon Sep 17 00:00:00 2001 From: killadm Date: Sun, 3 Mar 2019 00:35:44 +0800 Subject: [PATCH 1111/2222] zh-CN language updated --- sonoff/language/zh-CN.h | 118 ++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index dddf34a48..586591278 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -65,7 +65,7 @@ #define D_BY "汉化: killadm 作者:" // Written by me #define D_BYTES "大小:" #define D_CELSIUS "摄氏" -#define D_CHANNEL "Channel" +#define D_CHANNEL "频道" #define D_CO2 "二氧化碳" #define D_CODE "代码" // Button code #define D_COLDLIGHT "冷" @@ -132,7 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "固件 Flash 大小" #define D_PROGRAM_SIZE "固件大小" #define D_PROJECT "项目:" -#define D_RAIN "Rain" +#define D_RAIN "降水量" #define D_RECEIVED "已接收" #define D_RESTART "重启" #define D_RESTARTING "正在重启" @@ -165,18 +165,18 @@ #define D_USER "用户名" #define D_UTC_TIME "UTC" #define D_UV_INDEX "紫外线指数" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_1 "低" +#define D_UV_INDEX_2 "中" +#define D_UV_INDEX_3 "高" +#define D_UV_INDEX_4 "危险" #define D_UV_INDEX_5 "BurnL1/2" #define D_UV_INDEX_6 "BurnL3" #define D_UV_INDEX_7 "OoR" #define D_UV_LEVEL "紫外线水平" -#define D_UV_POWER "UV Power" +#define D_UV_POWER "紫外线功率 " #define D_VERSION "版本" #define D_VOLTAGE "电压" -#define D_WEIGHT "Weight" +#define D_WEIGHT "重量" #define D_WARMLIGHT "暖" #define D_WEB_SERVER "Web Server" @@ -219,7 +219,7 @@ #define D_ERASED_SECTOR "擦除扇区" // webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_NOSCRIPT "Tasmota要求浏览器支持 JavaScript" #define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件 - 请升级" #define D_WEBSERVER_ACTIVE_ON "Web 服务器地址:" #define D_WITH_IP_ADDRESS "IP 地址:" @@ -254,7 +254,7 @@ #define D_MODULE_PARAMETERS "模块设置" #define D_MODULE_TYPE "模块类型" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_PULLUP_ENABLE "没有按钮/开关上拉" #define D_GPIO "GPIO" #define D_SERIAL_IN "串口输入(RX)" #define D_SERIAL_OUT "串口输出(TX)" @@ -289,8 +289,8 @@ #define D_TELEMETRY_PERIOD "上报周期" #define D_OTHER_PARAMETERS "其他设置" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" +#define D_TEMPLATE "模板" +#define D_ACTIVATE "启用" #define D_WEB_ADMIN_PASSWORD "WEB 管理密码" #define D_MQTT_ENABLE "启用MQTT" #define D_FRIENDLY_NAME "昵称" @@ -299,13 +299,13 @@ #define D_SINGLE_DEVICE "单设备" #define D_MULTI_DEVICE "多设备" -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" -#define D_ALLOW_ADC0 "ADC0 input" -#define D_ALLOW_PULLUP "User pull-up selection" +#define D_CONFIGURE_TEMPLATE "模板配置" +#define D_TEMPLATE_PARAMETERS "模板参数" +#define D_TEMPLATE_NAME "名称" +#define D_BASE_TYPE "基于" +#define D_TEMPLATE_FLAGS "选项" +#define D_ALLOW_ADC0 "ADC0 输入" +#define D_ALLOW_PULLUP "用户上拉选择" #define D_SAVE_CONFIGURATION "保存设置" #define D_CONFIGURATION_SAVED "设置已保存" @@ -462,35 +462,35 @@ #define D_PARTICALS_BEYOND "颗粒物直径大于" // xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" +#define D_AX_AXIS "加速度计X轴分量" +#define D_AY_AXIS "加速度计Y轴分量" +#define D_AZ_AXIS "加速度计Z轴分量" +#define D_GX_AXIS "绕X轴旋转的角速度" +#define D_GY_AXIS "绕Y轴旋转的角速度" +#define D_GZ_AXIS "绕Z轴旋转的角速度" // xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" +#define D_HX_CAL_REMOVE "去除重量" +#define D_HX_CAL_REFERENCE "加载参考重量" +#define D_HX_CAL_DONE "已校准" +#define D_HX_CAL_FAIL "校准失败" +#define D_RESET_HX711 "秤重置" +#define D_CONFIGURE_HX711 "秤配置" +#define D_HX711_PARAMETERS "秤参数" +#define D_ITEM_WEIGHT "物品中粮" +#define D_REFERENCE_WEIGHT "参考重量" +#define D_CALIBRATE "校准" +#define D_CALIBRATION "校准" //xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" +#define D_TX20_WIND_DIRECTION "风向" +#define D_TX20_WIND_SPEED "风速" +#define D_TX20_WIND_SPEED_AVG "平均风速" +#define D_TX20_WIND_SPEED_MAX "最高风速" +#define D_TX20_NORTH "北" +#define D_TX20_EAST "东" +#define D_TX20_SOUTH "南" +#define D_TX20_WEST "西" // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "无" @@ -582,8 +582,8 @@ #define D_UNIT_CENTIMETER "厘米" #define D_UNIT_HOUR "时" #define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOGRAM "千克" +#define D_UNIT_KILOMETER_PER_HOUR "公里/时" // or "km/h" #define D_UNIT_KILOOHM "千欧" #define D_UNIT_KILOWATTHOUR "千瓦时" #define D_UNIT_LUX "勒克斯" @@ -591,8 +591,8 @@ #define D_UNIT_MICROMETER "微米" #define D_UNIT_MICROSECOND "微秒" #define D_UNIT_MILLIAMPERE "毫安" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLIMETER "毫米" +#define D_UNIT_MILLIMETER_MERCURY "毫米汞柱" #define D_UNIT_MILLISECOND "毫秒" #define D_UNIT_MINUTE "分" #define D_UNIT_PARTS_PER_BILLION "ppb" @@ -601,13 +601,13 @@ #define D_UNIT_PRESSURE "百帕" #define D_UNIT_SECOND "秒" #define D_UNIT_SECTORS "扇区" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" +#define D_UNIT_VA "伏安" +#define D_UNIT_VAR "无功伏安" #define D_UNIT_VOLT "伏" #define D_UNIT_WATT "瓦" #define D_UNIT_WATTHOUR "瓦时" #define D_UNIT_HERTZ "赫兹" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" +#define D_UNIT_WATT_METER_QUADRAT "瓦/平米" // Log message prefix #define D_LOG_APPLICATION "APP: " // Application @@ -635,13 +635,13 @@ #define D_LOG_WIFI "WIF: " // Wifi //SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" +#define D_PHASE_ANGLE "相位角" +#define D_IMPORT_ACTIVE "有功输入" +#define D_EXPORT_ACTIVE "有功输出" +#define D_IMPORT_REACTIVE "无功输入" +#define D_EXPORT_REACTIVE "无功输出" +#define D_TOTAL_REACTIVE "总无功功率" +#define D_UNIT_KWARH "千乏时" +#define D_UNIT_ANGLE "度" #endif // _LANGUAGE_ZH_CN_H_ From 3e1e565dffad1fe48e7e3f9fb35e44a358d7bad2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 4 Mar 2019 12:36:44 +0100 Subject: [PATCH 1112/2222] Update xdrv_01_webserver.ino Fix webpage redirect --- sonoff/xdrv_01_webserver.ino | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 6070d8ac8..cbd52ccee 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -84,7 +84,7 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "eb('l1').innerHTML=s;" "}" "};" - "x.open('GET','?m=1'+a,true);" // ?m related to WebServer->hasArg("m") + "x.open('GET','.?m=1'+a,true);" // ?m related to WebServer->hasArg("m") "x.send();" "lt=setTimeout(la,{a});" // Settings.web_refresh "}" @@ -103,13 +103,11 @@ const char HTTP_SCRIPT_WIFI[] PROGMEM = "}"; const char HTTP_SCRIPT_RELOAD[] PROGMEM = - "setTimeout(function(){location.href='.';}," STR(HTTP_RESTART_RECONNECT_TIME) ");" - ""; + "setTimeout(function(){location.href='.';}," STR(HTTP_RESTART_RECONNECT_TIME) ");"; // Local OTA upgrade requires more time to complete cp: before web ui should be reloaded const char HTTP_SCRIPT_RELOAD_OTA[] PROGMEM = - "setTimeout(function(){location.href='.';}," STR(HTTP_OTA_RESTART_RECONNECT_TIME) ");" - ""; + "setTimeout(function(){location.href='.';}," STR(HTTP_OTA_RESTART_RECONNECT_TIME) ");"; const char HTTP_SCRIPT_CONSOL[] PROGMEM = "var sn=0;" // Scroll position @@ -348,7 +346,7 @@ const char HTTP_FORM_WIFI[] PROGMEM = "

" D_AP1_PASSWORD "

" "

" D_AP2_SSID " (" STA_SSID2 ")

" "

" D_AP2_PASSWORD "

" - "

" D_HOSTNAME " (" WIFI_HOSTNAME ")

"; + "

" D_HOSTNAME " (" WIFI_HOSTNAME ")

"; const char HTTP_FORM_LOG1[] PROGMEM = "
 " D_LOGGING_PARAMETERS " " @@ -661,6 +659,7 @@ void WebRestart(uint8_t type) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTART); String page = FPSTR(HTTP_HEAD); + page += FPSTR(HTTP_SCRIPT_RELOAD); page += FPSTR(HTTP_HEAD_STYLE); if (type) { @@ -683,7 +682,6 @@ void WebRestart(uint8_t type) } else { page += FPSTR(HTTP_BTN_MAIN); } - page.replace(F(""), FPSTR(HTTP_SCRIPT_RELOAD)); ShowPage(page, !reset_only); ShowWebSource(SRC_WEBGUI); @@ -1705,11 +1703,11 @@ void HandleUpgradeFirmwareStart(void) String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_INFORMATION)); + page += FPSTR(HTTP_SCRIPT_RELOAD_OTA); page += FPSTR(HTTP_HEAD_STYLE); page += F("
" D_UPGRADE_STARTED " ...
"); page += FPSTR(HTTP_MSG_RSTRT); page += FPSTR(HTTP_BTN_MAIN); - page.replace(F(""), FPSTR(HTTP_SCRIPT_RELOAD_OTA)); ShowPage(page); snprintf_P(command, sizeof(command), PSTR(D_CMND_UPGRADE " 1")); @@ -1730,6 +1728,9 @@ void HandleUploadDone(void) String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), FPSTR(S_INFORMATION)); + if (!upload_error) { + page += FPSTR(HTTP_SCRIPT_RELOAD_OTA); // Refesh main web ui after OTA upgrade + } page += FPSTR(HTTP_HEAD_STYLE); page += F("
" D_UPLOAD " " D_SUCCESSFUL "
"); page += FPSTR(HTTP_MSG_RSTRT); - page.replace(F(""), FPSTR(HTTP_SCRIPT_RELOAD_OTA)); // Refesh main web ui after OTA upgrade ShowWebSource(SRC_WEBGUI); restart_flag = 2; // Always restart to re-enable disabled features during update } From d790b1cfcaf2abc4f880f615d7903a54481266be Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 4 Mar 2019 18:16:07 +0100 Subject: [PATCH 1113/2222] 6.4.1.20 Webserver uses chunks 6.4.1.20 20190304 * Changed webserver content handling from single String to small Chunks increasing RAM --- sonoff/_changelog.ino | 5 +- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_webserver.ino | 865 ++++++++++++++++++----------------- sonoff/xdrv_02_mqtt.ino | 46 +- sonoff/xdrv_07_domoticz.ino | 53 +-- sonoff/xdrv_09_timers.ino | 96 ++-- sonoff/xdrv_11_knx.ino | 200 +++----- sonoff/xsns_34_hx711.ino | 39 +- 8 files changed, 633 insertions(+), 673 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 3690ecf4a..f5606578a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.19 20190222 +/* 6.4.1.20 20190304 + * Changed webserver content handling from single String to small Chunks increasing RAM + * + * 6.4.1.19 20190222 * Add command SetOption37 for RGBCW color mapping (#5326) * Add Korean language translations (#5344) * Fix Energy TotalStartTime when commands EnergyReset0 and/or EnergyReset3 used (#5373) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index d4bfa230b..6dc3c6f38 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040113 +#define VERSION 0x06040114 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index cbd52ccee..40f8f7fbf 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -27,6 +27,8 @@ #define XDRV_01 1 +#define CHUNKED_BUFFER_SIZE 400 // Chunk buffer size + #ifndef WIFI_SOFT_AP_CHANNEL #define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by SmartConfig web GUI #endif @@ -49,7 +51,7 @@ const char HTTP_HEAD[] PROGMEM = "" "" "" - "{h} - {v}" + "%s - %s" ""; + "window.onload=u;"; const char HTTP_SCRIPT_ROOT[] PROGMEM = "function la(p){" @@ -76,17 +77,17 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "a=p;" "clearTimeout(lt);" "}" - "if(x!=null){x.abort();}" // Abort if no response within Settings.web_refresh milliseconds (happens on restart 1) + "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1) "x=new XMLHttpRequest();" "x.onreadystatechange=function(){" "if(x.readyState==4&&x.status==200){" - "var s=x.responseText.replace(/{t}/g,\"\").replace(/{s}/g,\"\").replace(/{c}/g,\"%'>
\").replace(/{s}/g,\"
\").replace(/{c}/g,\"%%'>
hasArg("m") "x.send();" - "lt=setTimeout(la,{a});" // Settings.web_refresh + "lt=setTimeout(la,%d);" // Settings.web_refresh "}" "function lb(p){" "la('&d='+p);" // &d related to WebGetArg("d", tmp, sizeof(tmp)); @@ -129,7 +130,7 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "x.onreadystatechange=function(){" "if(x.readyState==4&&x.status==200){" "var z,d;" - "d=x.responseText.split(/\1/);" // Field separator + "d=x.responseText.split(/}1/);" // Field separator "id=d.shift();" "if(d.shift()==0){t.value='';}" "z=d.shift();" @@ -141,18 +142,18 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "x.open('GET','cs?c2='+id+o,true);" // Related to WebServer->hasArg("c2") and WebGetArg("c2", stmp, sizeof(stmp)) "x.send();" "}" - "lt=setTimeout(l,{a});" + "lt=setTimeout(l,%d);" "return false;" "}" "window.onload=l;"; const char HTTP_MODULE_TEMPLATE_REPLACE[] PROGMEM = - "\2%d'>%s (%d\3"; // \2 and \3 are used in below os.replace + "}2%d'>%s (%d}3"; // }2 and }3 are used in below os.replace const char HTTP_SCRIPT_MODULE_TEMPLATE[] PROGMEM = "var os;" "function sk(s,g){" // s = value, g = id and name - "var o=os.replace(/\2/g,\"
\").replace(/{m}/g,\"\").replace(/{e}/g,\"
\").replace(/{m}/g,\"\").replace(/{e}/g,\"
\").replace(/}2/g,\"\");" "eb('i').innerHTML=s;" "}" - "window.onload=i;" - ""; + "window.onload=i;"; -const char HTTP_HEAD_STYLE[] PROGMEM = +const char HTTP_HEAD_STYLE1[] PROGMEM = "" "" "" @@ -266,11 +268,12 @@ const char HTTP_HEAD_STYLE[] PROGMEM = #endif "
" #ifdef LANGUAGE_MODULE_NAME - "

" D_MODULE " {ha

" + "

" D_MODULE " %s

" #else - "

{ha " D_MODULE "

" + "

%s " D_MODULE "

" #endif - "

{h}

{j}
"; + "

%s

%s"; + const char HTTP_MSG_SLIDER1[] PROGMEM = "
" D_COLDLIGHT "" D_WARMLIGHT "
" "
"; @@ -333,61 +336,39 @@ const char HTTP_FORM_TEMPLATE_FLAG[] PROGMEM = const char HTTP_FORM_MODULE[] PROGMEM = "
 " D_MODULE_PARAMETERS " " "
" - "

" D_MODULE_TYPE " ({mt)

"; + "

" D_MODULE_TYPE " (%s)

" + "
"; -const char HTTP_LNK_ITEM[] PROGMEM = - "
{v} ({w}) {i} {r}%
"; -const char HTTP_LNK_SCAN[] PROGMEM = - "
"; const char HTTP_FORM_WIFI[] PROGMEM = "
 " D_WIFI_PARAMETERS " " "" - "

" D_AP1_SSID " (" STA_SSID1 ")

" + "

" D_AP1_SSID " (" STA_SSID1 ")

" "

" D_AP1_PASSWORD "

" - "

" D_AP2_SSID " (" STA_SSID2 ")

" + "

" D_AP2_SSID " (" STA_SSID2 ")

" "

" D_AP2_PASSWORD "

" - "

" D_HOSTNAME " (" WIFI_HOSTNAME ")

"; + "

" D_HOSTNAME " (%s)

"; const char HTTP_FORM_LOG1[] PROGMEM = "
 " D_LOGGING_PARAMETERS " " ""; const char HTTP_FORM_LOG2[] PROGMEM = - "

{b0 ({b1)

"; -const char HTTP_FORM_LOG3[] PROGMEM = - "

" D_SYSLOG_HOST " (" SYS_LOG_HOST ")

" - "

" D_SYSLOG_PORT " (" STR(SYS_LOG_PORT) ")

" - "

" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

"; + "

" D_SYSLOG_HOST " (" SYS_LOG_HOST ")

" + "

" D_SYSLOG_PORT " (" STR(SYS_LOG_PORT) ")

" + "

" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

"; const char HTTP_FORM_OTHER[] PROGMEM = "
 " D_OTHER_PARAMETERS " " "" "

" "
 " D_TEMPLATE " " - "

" - "

" D_ACTIVATE "

" + "

" + "

" D_ACTIVATE "

" "
" "
" "" D_WEB_ADMIN_PASSWORD "

" "
" - "" D_MQTT_ENABLE "
" + "" D_MQTT_ENABLE "
" "
"; - const char HTTP_FORM_OTHER2[] PROGMEM = - "" D_FRIENDLY_NAME " {1 ({2)

"; -#ifdef USE_EMULATION -const char HTTP_FORM_OTHER3a[] PROGMEM = - "

" // Keep close to Friendlynames so do not use
- "
 " D_EMULATION " 

"; -const char HTTP_FORM_OTHER3b[] PROGMEM = - "{3{4
"; // Different id only used for labels -const char HTTP_FORM_OTHER3c[] PROGMEM = - "

"; -#endif // USE_EMULATION const char HTTP_FORM_END[] PROGMEM = "
" @@ -401,30 +382,34 @@ const char HTTP_FORM_UPG[] PROGMEM = "
" "
 " D_UPGRADE_BY_WEBSERVER " " "" - "
" D_OTA_URL "

" + "
" D_OTA_URL "

" "
" "


" "
 " D_UPGRADE_BY_FILE_UPLOAD " "; const char HTTP_FORM_RST_UPG[] PROGMEM = "
" "

" - "
" + "
" "
" "
" ""; + const char HTTP_FORM_CMND[] PROGMEM = "


" "
" "
" // "
" ""; + const char HTTP_TABLE100[] PROGMEM = "
"; + const char HTTP_COUNTER[] PROGMEM = "
"; + const char HTTP_END[] PROGMEM = "
" - "" + "" "" "" ""; @@ -435,6 +420,11 @@ const char HTTP_DEVICE_STATE[] PROGMEM = "%s"); + WSContentSend(FPSTR(HTTP_TABLE100)); + WSContentSend(F("")); if (SONOFF_IFAN02 == my_module_type) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); - page += mqtt_data; + WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); for (uint8_t i = 0; i < MAX_FAN_SPEED; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 16, i +2, stemp, ""); - page += mqtt_data; + WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i +2, stemp, ""); } } else { for (uint8_t idx = 1; idx <= devices_present; idx++) { snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, - 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); - page += mqtt_data; + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); } } - page += F("
" D_CONFIGURATION_SAVED "
"); - if (2 == type) { - page += F("
" D_TRYING_TO_CONNECT "
"); - } - page += F(""); - } - else { - page.replace(F("{v}"), FPSTR(S_RESTART)); - } - bool reset_only = (HTTP_MANAGER_RESET_ONLY == webserver_state); - page += FPSTR(HTTP_MSG_RSTRT); + WSContentStart((type) ? FPSTR(S_SAVE_CONFIGURATION) : FPSTR(S_RESTART), !reset_only); + WSContentSend(FPSTR(HTTP_SCRIPT_RELOAD)); + WSContentSendStyle(); + if (type) { + WSContentSend(F("
" D_CONFIGURATION_SAVED "
")); + if (2 == type) { + WSContentSend(F("
" D_TRYING_TO_CONNECT "
")); + } + WSContentSend(F("
")); + } + WSContentSend(FPSTR(HTTP_MSG_RSTRT)); if (HTTP_MANAGER == webserver_state || reset_only) { webserver_state = HTTP_ADMIN; } else { - page += FPSTR(HTTP_BTN_MAIN); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); } - ShowPage(page, !reset_only); + WSContentStop(); ShowWebSource(SRC_WEBGUI); restart_flag = 2; @@ -692,11 +777,10 @@ void WebRestart(uint8_t type) void HandleWifiLogin(void) { - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR( D_CONFIGURE_WIFI )); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_LOGIN); - ShowPage(page, false); // false means show page no matter if the client has or has not credentials + WSContentStart(FPSTR(D_CONFIGURE_WIFI), false); // false means show page no matter if the client has or has not credentials + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_FORM_LOGIN)); + WSContentStop(); } void HandleRoot(void) @@ -732,68 +816,60 @@ void HandleRoot(void) char stemp[5]; - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_MAIN_MENU)); - page += FPSTR(HTTP_SCRIPT_ROOT); - page += FPSTR(HTTP_HEAD_STYLE); + WSContentStart(FPSTR(S_MAIN_MENU)); + WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh); + WSContentSendStyle(); - page += F("
"); + WSContentSend(F("
")); if (devices_present) { if (light_type) { if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MSG_SLIDER1, LightGetColorTemp()); - page += mqtt_data; + WSContentSend_P(HTTP_MSG_SLIDER1, LightGetColorTemp()); } - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MSG_SLIDER2, Settings.light_dimmer); - page += mqtt_data; + WSContentSend_P(HTTP_MSG_SLIDER2, Settings.light_dimmer); } - page += FPSTR(HTTP_TABLE100); - page += F("
"); + WSContentSend(F("
")); } if (SONOFF_BRIDGE == my_module_type) { - page += FPSTR(HTTP_TABLE100); - page += F(""); + WSContentSend(FPSTR(HTTP_TABLE100)); + WSContentSend(F("")); uint8_t idx = 0; for (uint8_t i = 0; i < 4; i++) { - if (idx > 0) { page += F(""); } + if (idx > 0) { WSContentSend(F("")); } for (uint8_t j = 0; j < 4; j++) { idx++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), idx, idx); // ?k is related to WebGetArg("k", tmp, sizeof(tmp)); - page += mqtt_data; + WSContentSend_P(PSTR(""), idx, idx); // &k is related to WebGetArg("k", tmp, sizeof(tmp)); } } - page += F(""); + WSContentSend(F("")); } #ifndef FIRMWARE_MINIMAL mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); - page += String(mqtt_data); + WSContentSend(mqtt_data); #endif // Not FIRMWARE_MINIMAL if (HTTP_ADMIN == webserver_state) { - page += FPSTR(HTTP_BTN_MENU1); - page += FPSTR(HTTP_BTN_RSTRT); + WSContentSend(FPSTR(HTTP_BTN_MENU1)); + WSContentSend(FPSTR(HTTP_BTN_RSTRT)); } - ShowPage(page); + WSContentStop(); } bool HandleRootStatusRefresh(void) @@ -874,19 +950,6 @@ bool HandleRootStatusRefresh(void) return true; } -bool HttpCheckPriviledgedAccess(bool autorequestauth = true) -{ - if (HTTP_USER == webserver_state) { - HandleRoot(); - return false; - } - if (autorequestauth && !WebAuthenticate()) { - WebServer->requestAuthentication(); - return false; - } - return true; -} - /*-------------------------------------------------------------------------------------------*/ #ifndef FIRMWARE_MINIMAL @@ -897,21 +960,20 @@ void HandleConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURATION); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURATION)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_BTN_MENU_MODULE); + WSContentStart(FPSTR(S_CONFIGURATION)); + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_BTN_MENU_MODULE)); mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_BUTTON); XsnsCall(FUNC_WEB_ADD_BUTTON); - page += String(mqtt_data); + WSContentSend(mqtt_data); - page += FPSTR(HTTP_BTN_MENU4); - page += FPSTR(HTTP_BTN_RESET); - page += FPSTR(HTTP_BTN_MENU5); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + WSContentSend(FPSTR(HTTP_BTN_MENU4)); + WSContentSend(FPSTR(HTTP_BTN_RESET)); + WSContentSend(FPSTR(HTTP_BTN_MENU5)); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); } /*-------------------------------------------------------------------------------------------*/ @@ -930,7 +992,7 @@ void HandleTemplateConfiguration(void) if (WebServer->hasArg("m")) { String page = ""; - for (uint8_t i = 0; i < MAXMODULE; i++) { // "\2'%d'>%s (%d)\3" - "\2'0'>Sonoff Basic (1)\3" + for (uint8_t i = 0; i < MAXMODULE; i++) { // "}2'%d'>%s (%d)}3" - "}2'0'>Sonoff Basic (1)}3" uint8_t midx = pgm_read_byte(kModuleNiceList + i); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1); page += mqtt_data; @@ -950,12 +1012,12 @@ void HandleTemplateConfiguration(void) Settings.module = module_save; String page = AnyModuleName(module); // NAME: Generic - page += F("\1"); // Field separator + page += F("}1"); // Field separator - for (uint8_t i = 0; i < sizeof(kGpioNiceList); i++) { // GPIO: \2'0'>None (0)\3\2'17'>Button1 (17)\3... + for (uint8_t i = 0; i < sizeof(kGpioNiceList); i++) { // GPIO: }2'0'>None (0)}3}2'17'>Button1 (17)}3... if (1 == i) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MODULE_TEMPLATE_REPLACE, 255, D_SENSOR_USER, 255); // \2'255'>User (255)\3 + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MODULE_TEMPLATE_REPLACE, 255, D_SENSOR_USER, 255); // }2'255'>User (255)}3 page += mqtt_data; } @@ -964,14 +1026,14 @@ void HandleTemplateConfiguration(void) page += mqtt_data; } - mqtt_data[0] = '\1'; // Field separator - mqtt_data[1] = '\0'; // Char eot + page += F("}1"); // Field separator + mqtt_data[0] = '\0'; for (uint8_t i = 0; i < sizeof(cmodule); i++) { // 17,148,29,149,7,255,255,255,138,255,139,255,255 if ((i < 6) || ((i > 8) && (i != 11))) { // Ignore flash pins GPIO06, 7, 8 and 11 snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", cmodule.io[i]); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\1%d\1%d"), mqtt_data, flag, Settings.user_template_base); // FLAG: 1 BASE: 17 + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}1%d}1%d"), mqtt_data, flag, Settings.user_template_base); // FLAG: 1 BASE: 17 page += mqtt_data; WSSend(200, CT_PLAIN, page); @@ -980,25 +1042,25 @@ void HandleTemplateConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TEMPLATE); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_TEMPLATE)); - page += FPSTR(HTTP_SCRIPT_MODULE_TEMPLATE); - page += FPSTR(HTTP_SCRIPT_TEMPLATE); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_TEMPLATE); - page += F("
"); + WSContentStart(FPSTR(S_CONFIGURE_TEMPLATE)); + WSContentSend(FPSTR(HTTP_SCRIPT_MODULE_TEMPLATE)); + WSContentSend(FPSTR(HTTP_SCRIPT_TEMPLATE)); + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_FORM_TEMPLATE)); + + WSContentSend(F("
")); for (uint8_t i = 0; i < 17; i++) { - if ((i < 6) || ((i > 8) && (i != 11))) { // Ignore flash pins GPIO06, 7, 8 and 11 - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("" D_GPIO "%d"), + if ((i < 6) || ((i > 8) && (i != 11))) { // Ignore flash pins GPIO06, 7, 8 and 11 + WSContentSend_P(PSTR("" D_GPIO "%d"), (0==i)?" style='width:74px'":"", i, ((9==i)||(10==i))? "ESP8285" :"", (0==i)?" style='width:176px'":"", i, i); - page += mqtt_data; } } - page += F("
%s
%s
"); - page += FPSTR(HTTP_FORM_TEMPLATE_FLAG); - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentSend(F("")); + + WSContentSend(FPSTR(HTTP_FORM_TEMPLATE_FLAG)); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void TemplateSaveSettings(void) @@ -1054,7 +1116,7 @@ void HandleModuleConfiguration(void) if (WebServer->hasArg("m")) { String page = ""; uint8_t vidx = 0; - for (uint8_t i = 0; i <= MAXMODULE; i++) { // "\2'%d'>%s (%d)\3" - "\2'255'>UserTemplate (0)\3" - "\2'0'>Sonoff Basic (1)\3" + for (uint8_t i = 0; i <= MAXMODULE; i++) { // "}2'%d'>%s (%d)}3" - "}2'255'>UserTemplate (0)}3" - "}2'0'>Sonoff Basic (1)}3" if (0 == i) { midx = USER_MODULE; vidx = 0; @@ -1084,34 +1146,28 @@ void HandleModuleConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE)); - page += FPSTR(HTTP_SCRIPT_MODULE_TEMPLATE); - page += FPSTR(HTTP_SCRIPT_MODULE1); - page.replace(F("}4"), String(Settings.module)); + WSContentStart(FPSTR(S_CONFIGURE_MODULE)); + WSContentSend(FPSTR(HTTP_SCRIPT_MODULE_TEMPLATE)); + WSContentSend_P(HTTP_SCRIPT_MODULE1, Settings.module); for (uint8_t i = 0; i < sizeof(cmodule); i++) { if (ValidGPIO(i, cmodule.io[i])) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,%d);"), my_module.io[i], i); // g0 - g16 - page += mqtt_data; + WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); // g0 - g16 } } - page += FPSTR(HTTP_SCRIPT_MODULE2); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_MODULE); - page.replace(F("{mt"), AnyModuleName(MODULE)); - page += F("
"); + WSContentSend(FPSTR(HTTP_SCRIPT_MODULE2)); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); for (uint8_t i = 0; i < sizeof(cmodule); i++) { if (ValidGPIO(i, cmodule.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), + WSContentSend_P(PSTR(""), (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); - page += mqtt_data; } } - page += F("
%s " D_GPIO "%d %s
%s " D_GPIO "%d %s
"); - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentSend(F("")); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void ModuleSaveSettings(void) @@ -1168,10 +1224,9 @@ void HandleWifiConfiguration(void) return; } - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_WIFI)); - page += FPSTR(HTTP_SCRIPT_WIFI); - page += FPSTR(HTTP_HEAD_STYLE); + WSContentStart(FPSTR(S_CONFIGURE_WIFI)); + WSContentSend(FPSTR(HTTP_SCRIPT_WIFI)); + WSContentSendStyle(); if (HTTP_MANAGER_RESET_ONLY != webserver_state) { if (WebServer->hasArg("scan")) { @@ -1183,8 +1238,8 @@ void HandleWifiConfiguration(void) if (0 == n) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, S_NO_NETWORKS_FOUND); - page += FPSTR(S_NO_NETWORKS_FOUND); - page += F(". " D_REFRESH_TO_SCAN_AGAIN "."); + WSContentSend(FPSTR(S_NO_NETWORKS_FOUND)); + WSContentSend(F(". " D_REFRESH_TO_SCAN_AGAIN ".")); } else { //sort networks int indices[n]; @@ -1225,7 +1280,7 @@ void HandleWifiConfiguration(void) int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); if (minimum_signal_quality == -1 || minimum_signal_quality < quality) { - String item = FPSTR(HTTP_LNK_ITEM); + String item = F("
{v} ({w}) {i} {r}%
"); String rssiQ; rssiQ += quality; item.replace(F("{v}"), htmlEscape(WiFi.SSID(indices[i]))); @@ -1233,35 +1288,33 @@ void HandleWifiConfiguration(void) item.replace(F("{r}"), rssiQ); uint8_t auth = WiFi.encryptionType(indices[i]); item.replace(F("{i}"), (ENC_TYPE_WEP == auth) ? F(D_WEP) : (ENC_TYPE_TKIP == auth) ? F(D_WPA_PSK) : (ENC_TYPE_CCMP == auth) ? F(D_WPA2_PSK) : (ENC_TYPE_AUTO == auth) ? F(D_AUTO) : F("")); - page += item; + WSContentSend(item); delay(0); } else { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SKIPPING_LOW_QUALITY)); } } - page += "
"; + WSContentSend(F("
")); } } else { - page += FPSTR(HTTP_LNK_SCAN); + WSContentSend(F("
")); } - page += FPSTR(HTTP_FORM_WIFI); - page.replace(F("{h1"), Settings.hostname); - page.replace(F("{s1"), Settings.sta_ssid[0]); - page.replace(F("{s2"), Settings.sta_ssid[1]); - page += FPSTR(HTTP_FORM_END); + // As WIFI_HOSTNAME may contain %s-%04d it cannot be part of HTTP_FORM_WIFI where it will exception + WSContentSend_P(HTTP_FORM_WIFI, Settings.sta_ssid[0], Settings.sta_ssid[1], WIFI_HOSTNAME, WIFI_HOSTNAME, Settings.hostname); + WSContentSend(FPSTR(HTTP_FORM_END)); } + if (WifiIsInManagerMode()) { - page += FPSTR(HTTP_BTN_RSTRT); + WSContentSend(FPSTR(HTTP_BTN_RSTRT)); #ifndef FIRMWARE_MINIMAL - page += FPSTR(HTTP_BTN_RESET); -#endif // FIRMWARE_MINIMAL + WSContentSend(FPSTR(HTTP_BTN_RESET)); +#endif // FIRMWARE_MINIMAL } else { - page += FPSTR(HTTP_BTN_CONF); + WSContentSend(FPSTR(HTTP_BTN_CONF)); } -// ShowPage(page); - ShowPage(page, !(WifiIsInManagerMode())); + WSContentStop(); } void WifiSaveSettings(void) @@ -1300,58 +1353,40 @@ void HandleLoggingConfiguration(void) return; } - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_LOGGING)); - page += FPSTR(HTTP_HEAD_STYLE); - - page += FPSTR(HTTP_FORM_LOG1); + WSContentStart(FPSTR(S_CONFIGURE_LOGGING)); + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_FORM_LOG1)); + char stemp1[32]; + char stemp2[32]; + uint8_t dlevel[3] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE }; for (uint8_t idx = 0; idx < 3; idx++) { - page += FPSTR(HTTP_FORM_LOG2); - switch (idx) { - case 0: - page.replace(F("{b0"), F(D_SERIAL_LOG_LEVEL)); - page.replace(F("{b1"), STR(SERIAL_LOG_LEVEL)); - page.replace(F("{b2"), F("ls")); - for (uint8_t i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { - page.replace("{a" + String(i), (i == Settings.seriallog_level) ? F(" selected ") : F(" ")); - } - break; - case 1: - page.replace(F("{b0"), F(D_WEB_LOG_LEVEL)); - page.replace(F("{b1"), STR(WEB_LOG_LEVEL)); - page.replace(F("{b2"), F("lw")); - for (uint8_t i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { - page.replace("{a" + String(i), (i == Settings.weblog_level) ? F(" selected ") : F(" ")); - } - break; - case 2: - page.replace(F("{b0"), F(D_SYS_LOG_LEVEL)); - page.replace(F("{b1"), STR(SYS_LOG_LEVEL)); - page.replace(F("{b2"), F("ll")); - for (uint8_t i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { - page.replace("{a" + String(i), (i == Settings.syslog_level) ? F(" selected ") : F(" ")); - } - break; + uint8_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:Settings.syslog_level; + WSContentSend_P(PSTR("

%s (%s)

")); } - page += FPSTR(HTTP_FORM_LOG3); - page.replace(F("{l2"), Settings.syslog_host); - page.replace(F("{l3"), String(Settings.syslog_port)); - page.replace(F("{l4"), String(Settings.tele_period)); - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentSend_P(HTTP_FORM_LOG2, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void LoggingSaveSettings(void) { char tmp[sizeof(Settings.syslog_host)]; // Max length is currently 33 - WebGetArg("ls", tmp, sizeof(tmp)); + WebGetArg("l0", tmp, sizeof(tmp)); Settings.seriallog_level = (!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp); - WebGetArg("lw", tmp, sizeof(tmp)); + WebGetArg("l1", tmp, sizeof(tmp)); Settings.weblog_level = (!strlen(tmp)) ? WEB_LOG_LEVEL : atoi(tmp); - WebGetArg("ll", tmp, sizeof(tmp)); + WebGetArg("l2", tmp, sizeof(tmp)); Settings.syslog_level = (!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp); syslog_level = Settings.syslog_level; syslog_timer = 0; @@ -1383,42 +1418,41 @@ void HandleOtherConfiguration(void) return; } - char stemp[sizeof(Settings.friendlyname[0])]; // Max length is currently 33 + WSContentStart(FPSTR(S_CONFIGURE_OTHER)); + WSContentSendStyle(); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_OTHER)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_OTHER); TemplateJson(); - page.replace(F("{t1"), mqtt_data); - page.replace(F("{t2"), (USER_MODULE == Settings.module) ? F(" checked disabled") : F("")); - page.replace(F("{r1"), (Settings.flag.mqtt_enabled) ? F(" checked") : F("")); + char stemp[strlen(mqtt_data) +1]; + strlcpy(stemp, mqtt_data, sizeof(stemp)); // Get JSON template + WSContentSend_P(HTTP_FORM_OTHER, stemp, (USER_MODULE == Settings.module) ? " checked disabled" : "", (Settings.flag.mqtt_enabled) ? " checked" : ""); uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; if (SONOFF_IFAN02 == my_module_type) { maxfn = 1; } for (uint8_t i = 0; i < maxfn; i++) { - page += FPSTR(HTTP_FORM_OTHER2); - page.replace(F("{1"), String(i +1)); - snprintf_P(stemp, sizeof(stemp), PSTR(FRIENDLY_NAME"%d"), i +1); - page.replace(F("{2"), (i) ? stemp : FRIENDLY_NAME); - page.replace(F("{3"), Settings.friendlyname[i]); + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i +1); + WSContentSend_P(PSTR("" D_FRIENDLY_NAME " %d (" FRIENDLY_NAME "%s)

"), + i +1, + (i) ? stemp : "", + i, i, + (i) ? stemp : "", + Settings.friendlyname[i]); } #ifdef USE_EMULATION - page += FPSTR(HTTP_FORM_OTHER3a); + WSContentSend(PSTR("

 " D_EMULATION " 

")); // Keep close to Friendlynames so do not use
for (uint8_t i = 0; i < EMUL_MAX; i++) { - page += FPSTR(HTTP_FORM_OTHER3b); - page.replace(F("{1"), String(i)); - page.replace(F("{2"), (i == Settings.flag2.emulation) ? F(" checked") : F("")); - page.replace(F("{3"), (i == EMUL_NONE) ? F(D_NONE) : (i == EMUL_WEMO) ? F(D_BELKIN_WEMO) : F(D_HUE_BRIDGE)); - page.replace(F("{4"), (i == EMUL_NONE) ? F("") : (i == EMUL_WEMO) ? F(" " D_SINGLE_DEVICE) : F(" " D_MULTI_DEVICE)); + WSContentSend_P(PSTR("%s %s
"), // Different id only used for labels + i, i, + (i == Settings.flag2.emulation) ? " checked" : "", + GetTextIndexed(stemp, sizeof(stemp), i, kEmulationOptions), + (i == EMUL_NONE) ? "" : (i == EMUL_WEMO) ? D_SINGLE_DEVICE : D_MULTI_DEVICE); } - page += FPSTR(HTTP_FORM_OTHER3c); + WSContentSend(PSTR("

")); #endif // USE_EMULATION - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void OtherSaveSettings(void) @@ -1436,7 +1470,7 @@ void OtherSaveSettings(void) #endif // USE_EMULATION snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); for (uint8_t i = 0; i < MAX_FRIENDLYNAMES; i++) { - snprintf_P(webindex, sizeof(webindex), PSTR("a%d"), i +1); + snprintf_P(webindex, sizeof(webindex), PSTR("a%d"), i); WebGetArg(webindex, tmp, sizeof(tmp)); snprintf_P(friendlyname, sizeof(friendlyname), PSTR(FRIENDLY_NAME"%d"), i +1); strlcpy(Settings.friendlyname[i], (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp, sizeof(Settings.friendlyname[i])); @@ -1509,13 +1543,12 @@ void HandleResetConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESET_CONFIGURATION); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_RESET_CONFIGURATION)); - page += FPSTR(HTTP_HEAD_STYLE); - page += F("
" D_CONFIGURATION_RESET "
"); - page += FPSTR(HTTP_MSG_RSTRT); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page, HTTP_MANAGER_RESET_ONLY != webserver_state); + WSContentStart(FPSTR(S_RESET_CONFIGURATION), (HTTP_MANAGER_RESET_ONLY != webserver_state)); + WSContentSendStyle(); + WSContentSend(F("
" D_CONFIGURATION_RESET "
")); + WSContentSend(FPSTR(HTTP_MSG_RSTRT)); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); char command[CMDSZ]; snprintf_P(command, sizeof(command), PSTR(D_CMND_RESET " 1")); @@ -1528,14 +1561,12 @@ void HandleRestoreConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTORE_CONFIGURATION); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_RESTORE_CONFIGURATION)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_RST); - page += FPSTR(HTTP_FORM_RST_UPG); - page.replace(F("{r1"), F(D_RESTORE)); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentStart(FPSTR(S_RESTORE_CONFIGURATION)); + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_FORM_RST)); + WSContentSend_P(HTTP_FORM_RST_UPG, D_RESTORE); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); upload_error = 0; upload_file_type = UPL_SETTINGS; @@ -1553,113 +1584,91 @@ void HandleInformation(void) int freeMem = ESP.getFreeHeap(); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_INFORMATION)); - page += FPSTR(HTTP_HEAD_STYLE); - // page += F("
 Information "); - - page += F(""); - page += F("
"); - + WSContentStart(FPSTR(S_INFORMATION)); // Save 1k of code space replacing table html with javascript replace codes // }1 = // }2 = - String func = FPSTR(HTTP_SCRIPT_INFO_BEGIN); - func += F("
"); - func += F(D_PROGRAM_VERSION "}2"); func += my_version; func += my_image; - func += F("}1" D_BUILD_DATE_AND_TIME "}2"); func += GetBuildDateAndTime(); - func += F("}1" D_CORE_AND_SDK_VERSION "}2" ARDUINO_ESP8266_RELEASE "/"); func += String(ESP.getSdkVersion()); - func += F("}1" D_UPTIME "}2"); func += GetUptime(); - snprintf_P(stopic, sizeof(stopic), PSTR(" at 0x%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(); + WSContentSend(FPSTR(HTTP_SCRIPT_INFO_BEGIN)); + WSContentSend_P(PSTR("
")); + WSContentSend_P(PSTR(D_PROGRAM_VERSION "}2%s%s"), my_version, my_image); + WSContentSend_P(PSTR("}1" D_BUILD_DATE_AND_TIME "}2%s"), GetBuildDateAndTime().c_str()); + WSContentSend_P(PSTR("}1" D_CORE_AND_SDK_VERSION "}2" ARDUINO_ESP8266_RELEASE "/%s"), ESP.getSdkVersion()); + WSContentSend_P(PSTR("}1" D_UPTIME "}2%s"), GetUptime().c_str()); + WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d at 0x%X"), Settings.save_flag, GetSettingsAddress()); + WSContentSend_P(PSTR("}1" D_BOOT_COUNT "}2%d"), Settings.bootcount); + WSContentSend_P(PSTR("}1" D_RESTART_REASON "}2%s"), GetResetReason().c_str()); uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present; if (SONOFF_IFAN02 == my_module_type) { maxfn = 1; } for (uint8_t i = 0; i < maxfn; i++) { - func += F("}1" D_FRIENDLY_NAME " "); func += i +1; func += F("}2"); func += Settings.friendlyname[i]; + WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, Settings.friendlyname[i]); } - - 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 (mdns_begun) { func += F(".local"); } + WSContentSend_P(PSTR("}1}2 ")); // Empty line + WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%)"), Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI())); + WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (mdns_begun) ? ".local" : ""); if (static_cast(WiFi.localIP()) != 0) { - func += F("}1" D_IP_ADDRESS "}2"); func += WiFi.localIP().toString(); - func += F("}1" D_GATEWAY "}2"); func += IPAddress(Settings.ip_address[1]).toString(); - 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(); + WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.localIP().toString().c_str()); + WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), IPAddress(Settings.ip_address[1]).toString().c_str()); + WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%s"), IPAddress(Settings.ip_address[2]).toString().c_str()); + WSContentSend_P(PSTR("}1" D_DNS_SERVER "}2%s"), IPAddress(Settings.ip_address[3]).toString().c_str()); + WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.macAddress().c_str()); } if (static_cast(WiFi.softAPIP()) != 0) { - 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(); + WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.softAPIP().toString().c_str()); + WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), WiFi.softAPIP().toString().c_str()); + WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.softAPmacAddress().c_str()); } - - func += F("}1}2 "); // Empty line + WSContentSend_P(PSTR("}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_USER "}2"); func += Settings.mqtt_user; - func += F("}1" D_MQTT_CLIENT "}2"); func += mqtt_client; - func += F("}1" D_MQTT_TOPIC "}2"); func += Settings.mqtt_topic; - func += F("}1" D_MQTT_GROUP_TOPIC "}2"); func += Settings.mqtt_grptopic; - func += F("}1" D_MQTT_FULL_TOPIC "}2"); func += GetTopic_P(stopic, CMND, mqtt_topic, ""); - func += F("}1" D_MQTT " " D_FALLBACK_TOPIC "}2"); func += GetFallbackTopic_P(stopic, CMND, ""); + WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), Settings.mqtt_host); + WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port); + WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), Settings.mqtt_user); + WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client); + WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), Settings.mqtt_topic); + WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), Settings.mqtt_grptopic); + WSContentSend_P(PSTR("}1" D_MQTT_FULL_TOPIC "}2%s"), GetTopic_P(stopic, CMND, mqtt_topic, "")); + WSContentSend_P(PSTR("}1" D_MQTT " " D_FALLBACK_TOPIC "}2%s"), GetFallbackTopic_P(stopic, CMND, "")); } else { - func += F("}1" D_MQTT "}2" D_DISABLED); + WSContentSend_P(PSTR("}1" D_MQTT "}2" D_DISABLED)); } + WSContentSend_P(PSTR("}1}2 ")); // Empty line - func += F("}1}2 "); // Empty line - func += F("}1" D_EMULATION "}2"); #ifdef USE_EMULATION - if (EMUL_WEMO == Settings.flag2.emulation) { - func += F(D_BELKIN_WEMO); - } - else if (EMUL_HUE == Settings.flag2.emulation) { - func += F(D_HUE_BRIDGE); - } - else { - func += F(D_NONE); - } + WSContentSend_P(PSTR("}1" D_EMULATION "}2%s"), GetTextIndexed(stopic, sizeof(stopic), Settings.flag2.emulation, kEmulationOptions)); #else - func += F(D_DISABLED); + WSContentSend_P(PSTR("}1" D_EMULATION "}2" D_DISABLED)); #endif // USE_EMULATION - func += F("}1" D_MDNS_DISCOVERY "}2"); + #ifdef USE_DISCOVERY + WSContentSend_P(PSTR("}1" D_MDNS_DISCOVERY "}2%s"), (Settings.flag3.mdns_enabled) ? D_ENABLED : D_DISABLED); if (Settings.flag3.mdns_enabled) { - func += F(D_ENABLED); - func += F("}1" D_MDNS_ADVERTISE "}2"); #ifdef WEBSERVER_ADVERTISE - func += F(D_WEB_SERVER); + WSContentSend_P(PSTR("}1" D_MDNS_ADVERTISE "}2" D_WEB_SERVER)); #else - func += F(D_DISABLED); + WSContentSend_P(PSTR("}1" D_MDNS_ADVERTISE "}2" D_DISABLED)); #endif // WEBSERVER_ADVERTISE - } else { - func += F(D_DISABLED); } #else - func += F(D_DISABLED); + WSContentSend_P(PSTR("}1" D_MDNS_DISCOVERY "}2" D_DISABLED)); #endif // USE_DISCOVERY - func += F("}1}2 "); // Empty line - func += F("}1" D_ESP_CHIP_ID "}2"); func += String(ESP.getChipId()); - snprintf_P(stopic, sizeof(stopic), PSTR("0x%06X"), ESP.getFlashChipId()); - func += F("}1" D_FLASH_CHIP_ID "}2"); func += stopic; - 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); + WSContentSend_P(PSTR("}1}2 ")); // Empty line + WSContentSend_P(PSTR("}1" D_ESP_CHIP_ID "}2%d"), ESP.getChipId()); + WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X"), ESP.getFlashChipId()); + WSContentSend_P(PSTR("}1" D_FLASH_CHIP_SIZE "}2%dkB"), ESP.getFlashChipRealSize() / 1024); + WSContentSend_P(PSTR("}1" D_PROGRAM_FLASH_SIZE "}2%dkB"), ESP.getFlashChipSize() / 1024); + WSContentSend_P(PSTR("}1" D_PROGRAM_SIZE "}2%dkB"), ESP.getSketchSize() / 1024); + WSContentSend_P(PSTR("}1" D_FREE_PROGRAM_SPACE "}2%dkB"), ESP.getFreeSketchSpace() / 1024); + WSContentSend_P(PSTR("}1" D_FREE_MEMORY "}2%dkB"), freeMem / 1024); + WSContentSend_P(PSTR("
")); - // page += F("
"); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + WSContentSend(FPSTR(HTTP_SCRIPT_INFO_END)); + WSContentSendStyle(); + // WSContentSend(F("
 Information ")); + WSContentSend_P(PSTR("" + "
")); + // WSContentSend(F("
")); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); } #endif // Not FIRMWARE_MINIMAL @@ -1671,15 +1680,12 @@ void HandleUpgradeFirmware(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_FIRMWARE_UPGRADE); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_FIRMWARE_UPGRADE)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_UPG); - page.replace(F("{o1"), Settings.ota_url); - page += FPSTR(HTTP_FORM_RST_UPG); - page.replace(F("{r1"), F(D_UPGRADE)); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + WSContentStart(FPSTR(S_FIRMWARE_UPGRADE)); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_UPG, Settings.ota_url); + WSContentSend_P(HTTP_FORM_RST_UPG, D_UPGRADE); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); upload_error = 0; upload_file_type = UPL_TASMOTA; @@ -1701,14 +1707,13 @@ void HandleUpgradeFirmwareStart(void) ExecuteWebCommand(command, SRC_WEBGUI); } - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_INFORMATION)); - page += FPSTR(HTTP_SCRIPT_RELOAD_OTA); - page += FPSTR(HTTP_HEAD_STYLE); - page += F("
" D_UPGRADE_STARTED " ...
"); - page += FPSTR(HTTP_MSG_RSTRT); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + WSContentStart(FPSTR(S_INFORMATION)); + WSContentSend(FPSTR(HTTP_SCRIPT_RELOAD_OTA)); + WSContentSendStyle(); + WSContentSend(F("
" D_UPGRADE_STARTED " ...
")); + WSContentSend(FPSTR(HTTP_MSG_RSTRT)); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); snprintf_P(command, sizeof(command), PSTR(D_CMND_UPGRADE " 1")); ExecuteWebCommand(command, SRC_WEBGUI); @@ -1726,15 +1731,14 @@ void HandleUploadDone(void) restart_flag = 0; MqttRetryCounter(0); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_INFORMATION)); + WSContentStart(FPSTR(S_INFORMATION)); if (!upload_error) { - page += FPSTR(HTTP_SCRIPT_RELOAD_OTA); // Refesh main web ui after OTA upgrade + WSContentSend(FPSTR(HTTP_SCRIPT_RELOAD_OTA)); // Refesh main web ui after OTA upgrade } - page += FPSTR(HTTP_HEAD_STYLE); - page += F("
" D_UPLOAD " " D_UPLOAD " " D_FAILED "

"); + WSContentSend(F("red'>" D_FAILED "


")); #ifdef USE_RF_FLASH if (upload_error < 14) { #else @@ -1744,20 +1748,20 @@ void HandleUploadDone(void) } else { snprintf_P(error, sizeof(error), PSTR(D_UPLOAD_ERROR_CODE " %d"), upload_error); } - page += error; + WSContentSend(error); snprintf_P(log_data, sizeof(log_data), PSTR(D_UPLOAD ": %s"), error); AddLog(LOG_LEVEL_DEBUG); stop_flash_rotate = Settings.flag.stop_flash_rotate; } else { - page += F("green'>" D_SUCCESSFUL "

"); - page += FPSTR(HTTP_MSG_RSTRT); + WSContentSend(F("green'>" D_SUCCESSFUL "
")); + WSContentSend(FPSTR(HTTP_MSG_RSTRT)); ShowWebSource(SRC_WEBGUI); restart_flag = 2; // Always restart to re-enable disabled features during update } SettingsBufferFree(); - page += F("

"); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + WSContentSend(F("

")); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); } void HandleUploadLoop(void) @@ -2016,7 +2020,7 @@ void HandleHttpCommand(void) } else { message += F(D_NEED_USER_AND_PASSWORD "\"}"); } - SetHeader(); + WSHeaderSend(); WSSend(200, CT_JSON, message); } @@ -2033,13 +2037,12 @@ void HandleConsole(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONSOLE); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONSOLE)); - page += FPSTR(HTTP_SCRIPT_CONSOL); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_CMND); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + WSContentStart(FPSTR(S_CONSOLE)); + WSContentSend_P(HTTP_SCRIPT_CONSOL, Settings.web_refresh); + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_FORM_CMND)); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); } void HandleConsoleRefresh(void) @@ -2060,7 +2063,7 @@ void HandleConsoleRefresh(void) bool last_reset_web_log_flag = reset_web_log_flag; // mqtt_data used as scratch space - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%d\1%d\1"), web_log_index, last_reset_web_log_flag); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%d}1%d}1"), web_log_index, last_reset_web_log_flag); String message = mqtt_data; if (!reset_web_log_flag) { counter = 0; @@ -2089,7 +2092,7 @@ void HandleConsoleRefresh(void) if (!counter) { counter++; } // Skip log index 0 as it is not allowed } while (counter != web_log_index); } - message += F("\1"); + message += F("}1"); WSSend(200, CT_PLAIN, message); } @@ -2114,7 +2117,7 @@ void HandleNotFound(void) for (uint8_t i = 0; i < WebServer->args(); i++) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s %s: %s\n"), mqtt_data, WebServer->argName(i).c_str(), WebServer->arg(i).c_str()); } - SetHeader(); + WSHeaderSend(); WSSend(404, CT_PLAIN, mqtt_data); } } diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 8721b42b2..d5ad9f4b5 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -900,16 +900,17 @@ const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT; const char HTTP_BTN_MENU_MQTT[] PROGMEM = "

"; -const char HTTP_FORM_MQTT[] PROGMEM = +const char HTTP_FORM_MQTT1[] PROGMEM = "
 " D_MQTT_PARAMETERS " " "
" - "

" D_HOST " (" MQTT_HOST ")

" - "

" D_PORT " (" STR(MQTT_PORT) ")

" - "

" D_CLIENT " ({m0)

" - "

" D_USER " (" MQTT_USER ")

" + "

" D_HOST " (" MQTT_HOST ")

" + "

" D_PORT " (" STR(MQTT_PORT) ")

" + "

" D_CLIENT " (%s)

"; +const char HTTP_FORM_MQTT2[] PROGMEM = + "

" D_USER " (" MQTT_USER ")

" "

" D_PASSWORD "

" - "

" D_TOPIC " = %topic% (" MQTT_TOPIC ")

" - "

" D_FULL_TOPIC " (" MQTT_FULLTOPIC ")

"; + "

" D_TOPIC " = %%topic%% (" MQTT_TOPIC ")

" + "

" D_FULL_TOPIC " (%s)

"; void HandleMqttConfiguration(void) { @@ -923,23 +924,24 @@ void HandleMqttConfiguration(void) return; } - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_MQTT)); - page += FPSTR(HTTP_HEAD_STYLE); - - page += FPSTR(HTTP_FORM_MQTT); char str[sizeof(Settings.mqtt_client)]; - page.replace(F("{m0"), Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client))); - page.replace(F("{m1"), Settings.mqtt_host); - page.replace(F("{m2"), String(Settings.mqtt_port)); - page.replace(F("{m3"), Settings.mqtt_client); - page.replace(F("{m4"), (Settings.mqtt_user[0] == '\0')?"0":Settings.mqtt_user); - page.replace(F("{m6"), Settings.mqtt_topic); - page.replace(F("{m7"), Settings.mqtt_fulltopic); - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentStart(FPSTR(S_CONFIGURE_MQTT)); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_MQTT1, + Settings.mqtt_host, + Settings.mqtt_port, + Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)), + MQTT_CLIENT_ID, + Settings.mqtt_client); + WSContentSend_P(HTTP_FORM_MQTT2, + (Settings.mqtt_user[0] == '\0') ? "0" : Settings.mqtt_user, + Settings.mqtt_topic, + MQTT_FULLTOPIC, MQTT_FULLTOPIC, + Settings.mqtt_fulltopic); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void MqttSaveSettings(void) diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 65711cd68..c12203d2f 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -439,14 +439,14 @@ const char HTTP_FORM_DOMOTICZ[] PROGMEM = "
" ""; const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM = - "" - ""; + "" + ""; const char HTTP_FORM_DOMOTICZ_SWITCH[] PROGMEM = - ""; + ""; const char HTTP_FORM_DOMOTICZ_SENSOR[] PROGMEM = - ""; + ""; const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM = - ""; + ""; void HandleDomoticzConfiguration(void) { @@ -462,35 +462,30 @@ void HandleDomoticzConfiguration(void) char stemp[32]; - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_DOMOTICZ)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_DOMOTICZ); + WSContentStart(FPSTR(S_CONFIGURE_DOMOTICZ)); + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_FORM_DOMOTICZ)); for (int i = 0; i < MAX_DOMOTICZ_IDX; i++) { if (i < devices_present) { - page += FPSTR(HTTP_FORM_DOMOTICZ_RELAY); - page.replace("{2", String((int)Settings.domoticz_relay_idx[i])); - page.replace("{3", String((int)Settings.domoticz_key_idx[i])); + WSContentSend_P(HTTP_FORM_DOMOTICZ_RELAY, + i +1, i, i, Settings.domoticz_relay_idx[i], + i +1, i, i, Settings.domoticz_key_idx[i]); } if (pin[GPIO_SWT1 +i] < 99) { - page += FPSTR(HTTP_FORM_DOMOTICZ_SWITCH); - page.replace("{4", String((int)Settings.domoticz_switch_idx[i])); + WSContentSend_P(HTTP_FORM_DOMOTICZ_SWITCH, + i +1, i, i, Settings.domoticz_switch_idx[i]); } - page.replace("{1", String(i +1)); if ((SONOFF_IFAN02 == my_module_type) && (1 == i)) { break; } } for (int i = 0; i < DZ_MAX_SENSORS; i++) { - page += FPSTR(HTTP_FORM_DOMOTICZ_SENSOR); - page.replace("{1", String(i +1)); - page.replace("{2", GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors)); - page.replace("{5", String((int)Settings.domoticz_sensor_idx[i])); + WSContentSend_P(HTTP_FORM_DOMOTICZ_SENSOR, + i +1, GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors), i, i, Settings.domoticz_sensor_idx[i]); } - page += FPSTR(HTTP_FORM_DOMOTICZ_TIMER); - page.replace("{6", String((int)Settings.domoticz_update_timer)); - page += F("
" D_DOMOTICZ_IDX " {1
" D_DOMOTICZ_KEY_IDX " {1
" D_DOMOTICZ_IDX " %d
" D_DOMOTICZ_KEY_IDX " %d
" D_DOMOTICZ_SWITCH_IDX " {1
" D_DOMOTICZ_SWITCH_IDX " %d
" D_DOMOTICZ_SENSOR_IDX " {1 {2
" D_DOMOTICZ_SENSOR_IDX " %d %s
" 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); + WSContentSend_P(HTTP_FORM_DOMOTICZ_TIMER, Settings.domoticz_update_timer); + WSContentSend(F("")); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void DomoticzSaveSettings(void) @@ -500,19 +495,19 @@ void DomoticzSaveSettings(void) char tmp[100]; for (uint8_t i = 0; i < MAX_DOMOTICZ_IDX; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("r%d"), i +1); + snprintf_P(stemp, sizeof(stemp), PSTR("r%d"), i); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.domoticz_relay_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - snprintf_P(stemp, sizeof(stemp), PSTR("k%d"), i +1); + snprintf_P(stemp, sizeof(stemp), PSTR("k%d"), i); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.domoticz_key_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - snprintf_P(stemp, sizeof(stemp), PSTR("s%d"), i +1); + snprintf_P(stemp, sizeof(stemp), PSTR("s%d"), i); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.domoticz_switch_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); } ssensor_indices[0] = '\0'; for (uint8_t i = 0; i < DZ_MAX_SENSORS; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("l%d"), i +1); + snprintf_P(stemp, sizeof(stemp), PSTR("l%d"), i); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.domoticz_sensor_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); snprintf_P(ssensor_indices, sizeof(ssensor_indices), PSTR("%s%s%d"), ssensor_indices, (strlen(ssensor_indices)) ? "," : "", Settings.domoticz_sensor_idx[i]); diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 3c3b1f376..7bc55ff63 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -519,7 +519,7 @@ const char S_CONFIGURE_TIMER[] PROGMEM = D_CONFIGURE_TIMER; const char HTTP_BTN_MENU_TIMER[] PROGMEM = "

"; -const char HTTP_TIMER_SCRIPT[] PROGMEM = +const char HTTP_TIMER_SCRIPT1[] PROGMEM = "var pt=[],ct=99;" "function qs(s){" // Alias to save code space "return document.querySelector(s);" @@ -528,8 +528,9 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = "var o=document.createElement('option');" "o.textContent=i;" "q.appendChild(o);" - "}" + "}"; #ifdef USE_SUNRISE +const char HTTP_TIMER_SCRIPT2[] PROGMEM = "function gt(){" // Set hours and minutes according to mode "var m,p,q;" "m=qs('input[name=\"rd\"]:checked').value;" // Get mode @@ -558,8 +559,9 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = "qs('#dr').disabled='disabled';" "if(e<23){for(i=12;i<=23;i++){ce(i,o);}}" // Create hours select options "}" - "}" + "}"; #endif +const char HTTP_TIMER_SCRIPT3[] PROGMEM = "function st(){" // Save parameters to hidden area "var i,l,m,n,p,s;" "m=0;s=0;" @@ -570,7 +572,7 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = "m=qs('input[name=\"rd\"]:checked').value;" // Check mode "s|=(qs('input[name=\"rd\"]:checked').value<<29);" // Get mode #endif - "if(}1>0){" + "if(%d>0){" "i=qs('#d1').selectedIndex;if(i>=0){s|=(i<<23);}" // Get output "s|=(qs('#p1').selectedIndex<<27);" // Get action "}else{" @@ -587,7 +589,8 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = "s|=((qs('#mw').selectedIndex)&0x0F)<<11;" // Get window minutes "pt[ct]=s;" "eb('t0').value=pt.join();" // Save parameters from array to hidden area - "}" + "}"; +const char HTTP_TIMER_SCRIPT4[] PROGMEM = "function ot(t,e){" // Select tab and update elements "var i,n,o,p,q,s;" "if(ct<99){st();}" // Save changes @@ -602,23 +605,24 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = #else "p=s&0x7FF;" // Get time "q=Math.floor(p/60);if(q<10){q='0'+q;}qs('#ho').value=q;" // Set hours - "q=p%60;if(q<10){q='0'+q;}qs('#mi').value=q;" // Set minutes + "q=p%%60;if(q<10){q='0'+q;}qs('#mi').value=q;" // Set minutes #endif "q=(s>>11)&0xF;if(q<10){q='0'+q;}qs('#mw').value=q;" // Set window minutes "for(i=0;i<7;i++){p=(s>>(16+i))&1;eb('w'+i).checked=p;}" // Set weekdays - "if(}1>0){" + "if(%d>0){" "p=(s>>23)&0xF;qs('#d1').value=p+1;" // Set output "p=(s>>27)&3;qs('#p1').selectedIndex=p;" // Set action "}" "p=(s>>15)&1;eb('r0').checked=p;" // Set repeat "p=(s>>31)&1;eb('a0').checked=p;" // Set arm - "}" + "}"; +const char HTTP_TIMER_SCRIPT5[] PROGMEM = "function it(){" // Initialize elements and select first tab "var b,i,o,s;" "pt=eb('t0').value.split(',').map(Number);" // Get parameters from hidden area to array "s='';for(i=0;i<" STR(MAX_TIMERS) ";i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" "eb('bt').innerHTML=s;" // Create tabs - "if(}1>0){" // Create Output and Action drop down boxes + "if(%d>0){" // Create Output and Action drop down boxes "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" "o=qs('#p1');ce('" D_OFF "',o);ce('" D_ON "',o);ce('" D_TOGGLE "',o);" // Create offset direction select options #ifdef USE_RULES @@ -628,48 +632,52 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = #endif "}else{" "eb('oa').innerHTML=\"" D_TIMER_ACTION " " D_RULE "\";" // No outputs but rule is allowed - "}" + "}"; +const char HTTP_TIMER_SCRIPT6[] PROGMEM = #ifdef USE_SUNRISE "o=qs('#dr');ce('+',o);ce('-',o);" // Create offset direction select options #endif "o=qs('#ho');for(i=0;i<=23;i++){ce((i<10)?('0'+i):i,o);}" // Create hours select options "o=qs('#mi');for(i=0;i<=59;i++){ce((i<10)?('0'+i):i,o);}" // Create minutes select options "o=qs('#mw');for(i=0;i<=15;i++){ce((i<10)?('0'+i):i,o);}" // Create window minutes select options - "o=qs('#d1');for(i=0;i<}1;i++){ce(i+1,o);}" // Create outputs + "o=qs('#d1');for(i=0;i<%d;i++){ce(i+1,o);}" // Create outputs "var a='" D_DAY3LIST "';" "s='';for(i=0;i<7;i++){s+=\"\"+a.substring(i*3,(i*3)+3)+\" \"}" "eb('ds').innerHTML=s;" // Create weekdays "eb('dP').click();" // Get the element with id='dP' and click on it - "}"; + "}" + "window.onload=it;"; const char HTTP_TIMER_STYLE[] PROGMEM = - ".tl{float:left;border-radius:0;border:1px solid #f2f2f2;padding:1px;width:6.25%;}" // Border color needs to be the same as Fieldset background color from HTTP_HEAD_STYLE (transparent won't work) - ""; -const char HTTP_FORM_TIMER[] PROGMEM = + ".tl{float:left;border-radius:0;border:1px solid #f2f2f2;padding:1px;width:6.25%;}"; // Border color needs to be the same as Fieldset background color from HTTP_HEAD_STYLE1 (transparent won't work) +const char HTTP_FORM_TIMER1[] PROGMEM = "
" " " D_TIMER_PARAMETERS " " "
" - "
" D_TIMER_ENABLE "


" + "
" D_TIMER_ENABLE "


" "



" "

" "
" "" D_TIMER_ARM " " "" D_TIMER_REPEAT "" "

" - "
" + "
"; #ifdef USE_SUNRISE - "
" // 299 used in page.replace(F("299") +const char HTTP_FORM_TIMER3[] PROGMEM = + "
" "" D_TIMER_TIME "
" - "" D_SUNRISE " (}8)
" - "" D_SUNSET " (}9)
" + "" D_SUNRISE " (%s)
" + "" D_SUNSET " (%s)
" "
" "

" "" - " " + " "; #else - "" D_TIMER_TIME " " +const char HTTP_FORM_TIMER3[] PROGMEM = + "" D_TIMER_TIME " "; #endif // USE_SUNRISE +const char HTTP_FORM_TIMER4[] PROGMEM = "" " " D_HOUR_MINUTE_SEPARATOR " " "" @@ -690,28 +698,30 @@ void HandleTimerConfiguration(void) return; } - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_TIMER)); - page += FPSTR(HTTP_TIMER_SCRIPT); - page += FPSTR(HTTP_HEAD_STYLE); - page.replace(F(""), FPSTR(HTTP_TIMER_STYLE)); - page += FPSTR(HTTP_FORM_TIMER); - page.replace(F("{e0"), (Settings.flag3.timers_enable) ? F(" checked") : F("")); - for (uint8_t i = 0; i < MAX_TIMERS; i++) { - if (i > 0) { page += F(","); } - page += String(Settings.timer[i].data); - } - page += FPSTR(HTTP_FORM_TIMER1); - page.replace(F("}1"), String(devices_present)); + WSContentStart(FPSTR(S_CONFIGURE_TIMER)); + WSContentSend(FPSTR(HTTP_TIMER_SCRIPT1)); #ifdef USE_SUNRISE - page.replace(F("}8"), GetSun(0)); // Add Sunrise - page.replace(F("}9"), GetSun(1)); // Add Sunset - page.replace(F("299"), String(100 + (strlen(D_SUNSET) *12))); // Fix string length to keep radios centered + WSContentSend(FPSTR(HTTP_TIMER_SCRIPT2)); #endif // USE_SUNRISE - page += FPSTR(HTTP_FORM_END); - page += F(""); // Init elements and select first tab/button - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT4, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT5, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present); + WSContentSendStyle(FPSTR(HTTP_TIMER_STYLE)); + WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); + for (uint8_t i = 0; i < MAX_TIMERS; i++) { + WSContentSend_P(PSTR("%s%u"), (i > 0) ? "," : "", Settings.timer[i].data); + } + WSContentSend(FPSTR(HTTP_FORM_TIMER2)); +#ifdef USE_SUNRISE + WSContentSend_P(HTTP_FORM_TIMER3, 100 + (strlen(D_SUNSET) *12), GetSun(0).c_str(), GetSun(1).c_str()); +#else + WSContentSend(FPSTR(HTTP_FORM_TIMER3)); +#endif // USE_SUNRISE + WSContentSend(FPSTR(HTTP_FORM_TIMER4)); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void TimerSaveSettings(void) diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 461094162..9f3e6d344 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -755,13 +755,14 @@ const char HTTP_BTN_MENU_KNX[] PROGMEM = "

"; const char HTTP_FORM_KNX[] PROGMEM = - "
 " D_KNX_PARAMETERS " " - "
" + "
" + " " D_KNX_PARAMETERS " " + "" "
" "" D_KNX_PHYSICAL_ADDRESS " " - " . " - " . " - "" + " . " + " . " + "" "

" D_KNX_PHYSICAL_ADDRESS_NOTE "

" "{nop}"; + ""; const char HTTP_FORM_KNX_GA[] PROGMEM = - " / " - " / " - " "; + " / " + " / " + " "; const char HTTP_FORM_KNX_ADD_BTN[] PROGMEM = - "

" - ""; + "

" + "
"; const char HTTP_FORM_KNX_ADD_TABLE_ROW[] PROGMEM = - "" - ""; + "" + ""; const char HTTP_FORM_KNX3[] PROGMEM = "
{optex} -> GAfnum / GAarea / GAfdef
%s -> %d / %d / %d

" @@ -801,8 +802,8 @@ const char HTTP_FORM_KNX4[] PROGMEM = "-> -> "); - page += FPSTR(HTTP_FORM_KNX_GA); - page.replace(F("GAfnum"), F("GA_FNUM")); - page.replace(F("GAarea"), F("GA_AREA")); - page.replace(F("GAfdef"), F("GA_FDEF")); - page.replace(F("GAfnum"), F("GA_FNUM")); - page.replace(F("GAarea"), F("GA_AREA")); - page.replace(F("GAfdef"), F("GA_FDEF")); - page += FPSTR(HTTP_FORM_KNX_ADD_BTN); - page.replace(F("{btnval}"), String(1)); - if (Settings.knx_GA_registered < MAX_KNX_GA) { - page.replace(F("btndis"), F(" ")); - } - else - { - page.replace(F("btndis"), F("disabled")); - } - page.replace(F("fncbtnadd"), F("GAwarning")); - for (uint8_t i = 0; i < Settings.knx_GA_registered ; ++i) - { - if ( Settings.knx_GA_param[i] ) - { - page += FPSTR(HTTP_FORM_KNX_ADD_TABLE_ROW); - page.replace(F("{opval}"), String(i+1)); - page.replace(F("{optex}"), String(device_param_ga[Settings.knx_GA_param[i]-1])); - KNX_addr.value = Settings.knx_GA_addr[i]; - page.replace(F("GAfnum"), String(KNX_addr.ga.area)); - page.replace(F("GAarea"), String(KNX_addr.ga.line)); - page.replace(F("GAfdef"), String(KNX_addr.ga.member)); - } - } - - page += FPSTR(HTTP_FORM_KNX3); - page += FPSTR(HTTP_FORM_KNX_GA); - page.replace(F("GAfnum"), F("CB_FNUM")); - page.replace(F("GAarea"), F("CB_AREA")); - page.replace(F("GAfdef"), F("CB_FDEF")); - page.replace(F("GAfnum"), F("CB_FNUM")); - page.replace(F("GAarea"), F("CB_AREA")); - page.replace(F("GAfdef"), F("CB_FDEF")); - page += FPSTR(HTTP_FORM_KNX4); - uint8_t j; - for (uint8_t i = 0; i < KNX_MAX_device_param ; i++) - { - // Check How many Relays are available and add: RelayX and TogleRelayX - if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; } - if ( i == 8 ) { j = 0; } - if ( device_param[j].show ) - { - page += FPSTR(HTTP_FORM_KNX_OPT); - page.replace(F("{vop}"), String(device_param[i].type)); - page.replace(F("{nop}"), String(device_param_cb[i])); - } - } - page += F(" "); - page += FPSTR(HTTP_FORM_KNX_ADD_BTN); - page.replace(F("{btnval}"), String(2)); - if (Settings.knx_CB_registered < MAX_KNX_CB) { - page.replace(F("btndis"), F(" ")); - } - else - { - page.replace(F("btndis"), F("disabled")); - } - page.replace(F("fncbtnadd"), F("CBwarning")); - - for (uint8_t i = 0; i < Settings.knx_CB_registered ; ++i) - { - if ( Settings.knx_CB_param[i] ) - { - page += FPSTR(HTTP_FORM_KNX_ADD_TABLE_ROW2); - page.replace(F("{opval}"), String(i+1)); - page.replace(F("{optex}"), String(device_param_cb[Settings.knx_CB_param[i]-1])); - KNX_addr.value = Settings.knx_CB_addr[i]; - page.replace(F("GAfnum"), String(KNX_addr.ga.area)); - page.replace(F("GAarea"), String(KNX_addr.ga.line)); - page.replace(F("GAfdef"), String(KNX_addr.ga.member)); - } - } - page += F("
"); - page += F("
"); - page += FPSTR(HTTP_BTN_CONF); - - page.replace( F(""), + WSContentStart(FPSTR(S_CONFIGURE_KNX)); + WSContentSend( F("function GAwarning()" "{" "var GA_FNUM = eb('GA_FNUM');" @@ -995,9 +891,63 @@ void HandleKNXConfiguration(void) "if ( CB_FNUM != null && CB_FNUM.value == '0' && CB_AREA.value == '0' && CB_FDEF.value == '0' ) {" "alert('" D_KNX_WARNING "');" "}" - "}" - "") ); - ShowPage(page); + "}")); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_KNX, KNX_physs_addr.pa.area, KNX_physs_addr.pa.line, KNX_physs_addr.pa.member); + if ( Settings.flag.knx_enabled ) { WSContentSend(F(" checked")); } + WSContentSend(FPSTR(HTTP_FORM_KNX1)); + if ( Settings.flag.knx_enable_enhancement ) { WSContentSend(F(" checked")); } + + WSContentSend(FPSTR(HTTP_FORM_KNX2)); + for (uint8_t i = 0; i < KNX_MAX_device_param ; i++) + { + if ( device_param[i].show ) + { + WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_ga[i]); + } + } + WSContentSend(F(" -> ")); + WSContentSend_P(HTTP_FORM_KNX_GA, "GA_FNUM", "GA_FNUM", "GA_AREA", "GA_AREA", "GA_FDEF", "GA_FDEF"); + WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "GAwarning", (Settings.knx_GA_registered < MAX_KNX_GA) ? "" : "disabled", 1); + for (uint8_t i = 0; i < Settings.knx_GA_registered ; ++i) + { + if ( Settings.knx_GA_param[i] ) + { + KNX_addr.value = Settings.knx_GA_addr[i]; + WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW, device_param_ga[Settings.knx_GA_param[i]-1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, i +1); + } + } + + WSContentSend(FPSTR(HTTP_FORM_KNX3)); + WSContentSend_P(HTTP_FORM_KNX_GA, "CB_FNUM", "CB_FNUM", "CB_AREA", "CB_AREA", "CB_FDEF", "CB_FDEF"); + WSContentSend(FPSTR(HTTP_FORM_KNX4)); + + uint8_t j; + for (uint8_t i = 0; i < KNX_MAX_device_param ; i++) + { + // Check How many Relays are available and add: RelayX and TogleRelayX + if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; } + if ( i == 8 ) { j = 0; } + if ( device_param[j].show ) + { + WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_cb[i]); + } + } + WSContentSend(F(" ")); + WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "CBwarning", (Settings.knx_CB_registered < MAX_KNX_CB) ? "" : "disabled", 2); + + for (uint8_t i = 0; i < Settings.knx_CB_registered ; ++i) + { + if ( Settings.knx_CB_param[i] ) + { + KNX_addr.value = Settings.knx_CB_addr[i]; + WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW2, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings.knx_CB_param[i]-1], i +1); + } + } + WSContentSend(F("
")); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } } diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 148f7f860..f019625fc 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -382,14 +382,14 @@ const char HTTP_BTN_MENU_HX711[] PROGMEM = const char HTTP_FORM_HX711[] PROGMEM = "
 " D_CALIBRATION " " "
" - "

" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" + "

" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" "
" "
" "


" "
 " D_HX711_PARAMETERS " " "
" - "

" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; + "

" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; void HandleHxAction(void) { @@ -403,41 +403,38 @@ void HandleHxAction(void) return; } - char tmp[100]; + char stemp1[20]; if (WebServer->hasArg("reset")) { - snprintf_P(tmp, sizeof(tmp), PSTR("Sensor34 1")); // Reset - ExecuteWebCommand(tmp, SRC_WEBGUI); + snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 1")); // Reset + ExecuteWebCommand(stemp1, SRC_WEBGUI); HandleRoot(); // Return to main screen return; } if (WebServer->hasArg("calibrate")) { - WebGetArg("p1", tmp, sizeof(tmp)); - Settings.weight_reference = (!strlen(tmp)) ? 0 : (unsigned long)(CharToDouble(tmp) * 1000); + WebGetArg("p1", stemp1, sizeof(stemp1)); + Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToDouble(stemp1) * 1000); HxLogUpdates(); - snprintf_P(tmp, sizeof(tmp), PSTR("Sensor34 2")); // Start calibration - ExecuteWebCommand(tmp, SRC_WEBGUI); + snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 2")); // Start calibration + ExecuteWebCommand(stemp1, SRC_WEBGUI); HandleRoot(); // Return to main screen return; } - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(D_CONFIGURE_HX711)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_HX711); - dtostrfd((float)Settings.weight_reference / 1000, 3, tmp); - page.replace("{1", String(tmp)); - dtostrfd((float)Settings.weight_item / 10000, 4, tmp); - page.replace("{2", String(tmp)); - - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentStart(FPSTR(D_CONFIGURE_HX711)); + WSContentSendStyle(); + dtostrfd((float)Settings.weight_reference / 1000, 3, stemp1); + char stemp2[20]; + dtostrfd((float)Settings.weight_item / 10000, 4, stemp2); + WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void HxSaveSettings(void) From b393cdc9f1d5784d1855084c260b157ce9022216 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 4 Mar 2019 18:32:23 +0100 Subject: [PATCH 1114/2222] Replace menu button list Replace menu button list --- sonoff/xdrv_01_webserver.ino | 4 ---- sonoff/xdrv_02_mqtt.ino | 2 +- sonoff/xdrv_07_domoticz.ino | 2 +- sonoff/xdrv_09_timers.ino | 4 ++-- sonoff/xdrv_11_knx.ino | 2 +- sonoff/xsns_34_hx711.ino | 4 ++-- 6 files changed, 7 insertions(+), 11 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 40f8f7fbf..bb2af46e9 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -859,10 +859,8 @@ void HandleRoot(void) } #ifndef FIRMWARE_MINIMAL - mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); - WSContentSend(mqtt_data); #endif // Not FIRMWARE_MINIMAL if (HTTP_ADMIN == webserver_state) { @@ -964,10 +962,8 @@ void HandleConfiguration(void) WSContentSendStyle(); WSContentSend(FPSTR(HTTP_BTN_MENU_MODULE)); - mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_BUTTON); XsnsCall(FUNC_WEB_ADD_BUTTON); - WSContentSend(mqtt_data); WSContentSend(FPSTR(HTTP_BTN_MENU4)); WSContentSend(FPSTR(HTTP_BTN_RESET)); diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index d5ad9f4b5..d2874f490 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -990,7 +990,7 @@ bool Xdrv02(uint8_t function) switch (function) { #ifdef USE_WEBSERVER case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_MQTT, sizeof(mqtt_data) - strlen(mqtt_data) -1); + WSContentSend(FPSTR(HTTP_BTN_MENU_MQTT)); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index c12203d2f..a90245e08 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -536,7 +536,7 @@ bool Xdrv07(uint8_t function) switch (function) { #ifdef USE_WEBSERVER case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_DOMOTICZ, sizeof(mqtt_data) - strlen(mqtt_data) -1); + WSContentSend(FPSTR(HTTP_BTN_MENU_DOMOTICZ)); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration); diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 7bc55ff63..cfc18904a 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -764,9 +764,9 @@ bool Xdrv09(uint8_t function) #ifdef USE_TIMERS_WEB case FUNC_WEB_ADD_BUTTON: #ifdef USE_RULES - strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data) - strlen(mqtt_data) -1); + WSContentSend(FPSTR(HTTP_BTN_MENU_TIMER)); #else - if (devices_present) { strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data) - strlen(mqtt_data) -1); } + if (devices_present) { WSContentSend(FPSTR(HTTP_BTN_MENU_TIMER)); } #endif // USE_RULES break; case FUNC_WEB_ADD_HANDLER: diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 9f3e6d344..d39001250 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -1249,7 +1249,7 @@ bool Xdrv11(uint8_t function) #ifdef USE_WEBSERVER #ifdef USE_KNX_WEB_MENU case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_KNX, sizeof(mqtt_data) - strlen(mqtt_data) -1); + WSContentSend(FPSTR(HTTP_BTN_MENU_KNX)); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/kn", HandleKNXConfiguration); diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index f019625fc..5057b8c47 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -492,10 +492,10 @@ bool Xsns34(uint8_t function) break; #ifdef USE_HX711_GUI case FUNC_WEB_ADD_MAIN_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_MAIN_HX711, sizeof(mqtt_data) - strlen(mqtt_data) -1); + WSContentSend(FPSTR(HTTP_BTN_MENU_MAIN_HX711)); break; case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_HX711, sizeof(mqtt_data) - strlen(mqtt_data) -1); + WSContentSend(FPSTR(HTTP_BTN_MENU_HX711)); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); From 7a8916b892769ed6652fa60b6f760b7f72ba7b99 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 5 Mar 2019 23:57:28 -0300 Subject: [PATCH 1115/2222] Create CODE_OF_CONDUCT.md As Tasmota Project has grown, a code of conduct is needed. This is just the standard Contributor Covenant Code of Conduct provided by GitHub. Adding this makes GitHub to show a link to this file when opening a new issue. --- CODE_OF_CONDUCT.md | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..1408ce048 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at https://sidweb.nl/cms3/en/contact. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq From a86757561855c8571a0e54734cbacc72a1f52e59 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 5 Mar 2019 23:58:00 -0300 Subject: [PATCH 1116/2222] Create SUPPORT.md Adding this makes GitHub to show a link to this file when opening a new issue. --- SUPPORT.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 SUPPORT.md diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 000000000..46fa03ebc --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,22 @@ +# Sonoff-Tasmota Support + +If you're looking for support on **Sonoff-Tasmota** there are some options available: + +### Documentation: + +* [Wiki Pages](https://github.com/arendst/Sonoff-Tasmota/wiki): For information on how to Flash Tasmota, configure and use it. +* [Troubleshooting Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting): For information on common problems and solutions. +* [Commands Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands): For information on all the commands supported by Tasmota. + +### Support's Community: + +* [Tasmota Forum](https://groups.google.com/d/forum/sonoffusers): For usage and discussions. +* [Tasmota Support Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community. +* [Search in Issues](https://github.com/arendst/Sonoff-Tasmota/issues): You might find an answer to your question by searching current or closed issues. + +### Developers' Community: + +* [Bug Report](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software. +* [Feature Request](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software. +* [Troubleshooting](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Custom.md): As a last resort, you can open new *Troubleshooting* issue on GitHub if the solution could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. +* [Issue a question](https://github.com/arendst/Sonoff-Tasmota/issues/new/choose): As a last resort, you can open new *Question* issue on GitHub if the answer could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. From ea8237998665b44f585e45d12f1423d14db37f20 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 5 Mar 2019 23:58:25 -0300 Subject: [PATCH 1117/2222] Create PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..aea7cd816 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,10 @@ +## Description: + +**Related issue (if applicable):** fixes # + +## Checklist: + - [ ] The pull request is done against the dev branch + - [ ] Only relevant files were touched (Also beware if your editor has auto-formatting feature enabled) + - [ ] Only one feature/fix was added per PR. + - [ ] The code change is tested and works. + - [ ] The code change pass travis tests. **Your PR cannot be merged unless tests pass** From 5ec26d7727531af47d6b4955d4751e9eaf163bd4 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 6 Mar 2019 00:28:21 -0300 Subject: [PATCH 1118/2222] Create CONTRIBUTING.md Adding this makes GitHub to show a link to this file when opening a new issue. As Sonoff-Tasmota Project has grown, a contributing guideline and policy is needed in order to clarify the usage of the resources as issues and PR for new users in the community. --- CONTRIBUTING.md | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..2e2beec04 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,62 @@ +# Contributing to Sonoff-Tasmota + +**Any contribution helps our team and makes Tasmota better for the entire community!** + +Everybody is welcome and invited to contribute to Sonoff-Tasmota Project by: + +* Testing new released features and reporting issues. +* Providing Pull Requests (Features, Proof of Concepts, Language files or Fixes) +* Contributing missing documentation for features and devices on our [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Contributing) + +This document describes rules that are in effect for this repository, meant for handling issues by contributors in the issue tracker and PRs. + +## Opening New Issues + +1. The issue tracker is precisely that: a tool to track issues in the Tasmota code, and not a discussion forum. Opening an issue means that a problem has been found in the code, and that it should be addressed by a contributor. +2. When opening an issue, a template is presented with fields to fill out. The requested information is important. If the template is ignored, or not enough info about the issue is provided, the issue may be closed due to lack of info. +3. Questions of type "How do I..." or "Can you please help me with..." or "Can the Tasmota do..." won't be handled here. Such questions should be directed at a discussion forum or to the Tasmota Support Chat. All issues of this type will be closed with a simple reference to this contributing policy. +4. Issues about topics already handled in the documentation will be closed in a similar manner. +5. Issues for unmerged PRs will be closed. If there is an issue with a PR, the explanation should be added to the PR itself. +6. Issues with accompanied investigation that shows the root of the problem should be given priority. +7. Duplicate issues will be closed. + +## Triaging of Issues/PR's + +1. Any contributor of the project can participate in the triaging process, if he/she chooses to do so. +2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor. +3. Issues that are accepted should be marked with appropriate labels. +4. Issues that could impact functionality for many users should be considered severe. +5. Issues caused by the SDK or chip should not be marked severe, as there usually isn’t much to be done. Common sense should be applied when deciding. Such issues should be documented in the Wiki, for reference by users. +6. Issues with feature requests should be discussed for viability/desirability. +7. Feature requests or changes that are meant to address a very specific/limited use case, especially if at the expense of increased code complexity, may be denied, or may be required to be redesigned, generalized, or simplified. +8. Feature requests that are not accompanied by a PR: + * could be closed immediately (denied). + * could be closed after some predetermined period of time (left as candidate for somebody to pick up). +9. In some cases, feedback may be requested from the issue reporter, either as additional info for clarification, additional testing, or other. If no feedback is provided, the issue may be closed by a contributor or after 30 days by the STALE bot. + +## Pull requests + +A Pull Request (PR) is the process where code modifications are managed in GitHub. + +The process is straight-forward. + + - Read [How to get faster PR reviews](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) by Kubernetes (but skip step 0) + - Fork the Sonoff-Tasmota Repository [git repository](https://github.com/arendst/Sonoff-Tasmota). + - Write/Change the code in your Fork for a new feature, bug fix, new sensor, optimization, etc. + - Ensure tests work. + - Create a Pull Request against the [**dev**](https://github.com/arendst/Sonoff-Tasmota/tree/dev) branch of Sonoff-Tasmota. + +1. All pull requests must be done against the dev branch. +2. Only relevant files should be touched (Also beware if your editor has auto-formatting feature enabled). +3. Only one feature/fix should be added per PR. +4. If adding a new functionality (new hardware, new library support) not related to an existing component move it to it's own modules (.ino file). +5. PRs that don't compile (break Travis) or cause coding errors will not be merged. Please fix the issue. Same goes for PRs that are raised against older commit in dev - you might need to rebase and resolve conflicts. +6. All pull requests should undergo peer review by at least one contributor other than the creator, excepts for the owner. +7. All pull requests should consider updates to the documentation. +8. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority. +9. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged. +10. Pull requests that don't meet the above will be denied and closed. + + + + From 060e2e47303ae5c5b276da8027d2816c50113c3a Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 6 Mar 2019 00:51:31 -0300 Subject: [PATCH 1119/2222] Update STALE Bot As the amount of users in the community has grown, also the rate of issues that are opened every month have grown. This led to an increase of issues left behind (not closed by its author no matter if it is answered or solved) making collaborators to spend more time on searching for those between the opened issues. The actual rate of the Bot is 60 days to close an issue that has been left behind (45 days to raise attention to that issue and then other more 15 days to close it), and as the amount of opened issues are around 250-300 each month, in 60 days the amount of issues can raise to about 600 opened issues if no action is taken by collaborators. With this update to the BOT, the new rate will be 25 days to raise the attention to the issue, and if there is no one comment on that issue, the Bot will close it after 5 more days. This 30 days are more suited to the actual speed of the project. As always the Bot will not close any issue labeled as - pinned - security - enhancement - bug And also, if the issue is closed by the Bot, it can be reopened again. Also this update expands the Bot activity to PRs, so PRs should be labeled as well as issues. --- .github/stale.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/stale.yml b/.github/stale.yml index 88c5f7c21..484010321 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,9 +1,9 @@ # Number of days of inactivity before an Issue or Pull Request becomes stale -daysUntilStale: 45 +daysUntilStale: 25 # Number of days of inactivity before a stale Issue or Pull Request is closed. # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. -daysUntilClose: 15 +daysUntilClose: 5 # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable exemptLabels: @@ -37,4 +37,4 @@ closeComment: > limitPerRun: 30 # Limit to only `issues` or `pulls` -only: issues +#only: issues From 06c3a6111eb1a000582aa243708a987ead4cc07c Mon Sep 17 00:00:00 2001 From: blakadder Date: Wed, 6 Mar 2019 08:25:48 +0100 Subject: [PATCH 1120/2222] Update CONTRIBUTING.md Hope you don't mind. I did some language tuning in the beginning of the article --- CONTRIBUTING.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2e2beec04..7cfcdfadb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ Everybody is welcome and invited to contribute to Sonoff-Tasmota Project by: -* Testing new released features and reporting issues. +* Testing newly released features and reporting issues. * Providing Pull Requests (Features, Proof of Concepts, Language files or Fixes) * Contributing missing documentation for features and devices on our [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Contributing) @@ -12,9 +12,10 @@ This document describes rules that are in effect for this repository, meant for ## Opening New Issues -1. The issue tracker is precisely that: a tool to track issues in the Tasmota code, and not a discussion forum. Opening an issue means that a problem has been found in the code, and that it should be addressed by a contributor. -2. When opening an issue, a template is presented with fields to fill out. The requested information is important. If the template is ignored, or not enough info about the issue is provided, the issue may be closed due to lack of info. -3. Questions of type "How do I..." or "Can you please help me with..." or "Can the Tasmota do..." won't be handled here. Such questions should be directed at a discussion forum or to the Tasmota Support Chat. All issues of this type will be closed with a simple reference to this contributing policy. +**Issue tracker is NOT a general discussion forum!** +1. Opening an issue means that a problem exists in the code and should be addressed by the project contributors. +2. When opening an issue, it is required to fill out the presented template. The requested information is important! If the template is ignored or insufficient info about the issue is provided, the issue may be closed. +3. Questions of type "How do I..." or "Can you please help me with..." or "Can Tasmota do..." WILL NOT be handled here. Such questions should be directed at a discussion forum or to the Tasmota Support Chat. All issues of this type will be closed with a simple reference to this contributing policy. 4. Issues about topics already handled in the documentation will be closed in a similar manner. 5. Issues for unmerged PRs will be closed. If there is an issue with a PR, the explanation should be added to the PR itself. 6. Issues with accompanied investigation that shows the root of the problem should be given priority. @@ -22,7 +23,7 @@ This document describes rules that are in effect for this repository, meant for ## Triaging of Issues/PR's -1. Any contributor of the project can participate in the triaging process, if he/she chooses to do so. +1. Any contributor to the project can participate in the triaging process, if he/she chooses to do so. 2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor. 3. Issues that are accepted should be marked with appropriate labels. 4. Issues that could impact functionality for many users should be considered severe. From 2ec545d7394c46fd7321a1e58708f7b22ddef5a3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 6 Mar 2019 17:59:18 +0100 Subject: [PATCH 1121/2222] Fix float calculations Fix float calculations in range from 0 to -1 (#5386) --- sonoff/_changelog.ino | 1 + sonoff/support.ino | 43 ++++++++++++++++++++++++------------------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 3690ecf4a..245cc5edb 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Add Korean language translations (#5344) * Fix Energy TotalStartTime when commands EnergyReset0 and/or EnergyReset3 used (#5373) * Fix DS18S20 temperature calculation (#5375) + * Fix float calculations in range from 0 to -1 (#5386) * * 6.4.1.18 20190221 * Fix some exceptions and watchdogs due to lack of stack space - part 1 (#5215) diff --git a/sonoff/support.ino b/sonoff/support.ino index 8bb9d1dea..c5e5dcc42 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -154,34 +154,39 @@ char* subStr(char* dest, char* str, const char *delim, int index) return sub; } -double CharToDouble(const char *str) +double CharToDouble(char *str) { // simple ascii to double, because atof or strtod are too large char strbuf[24]; strlcpy(strbuf, str, sizeof(strbuf)); - char *pt; - double left = atoi(strbuf); + char *pt = strbuf; + while ((*pt != '\0') && isblank(*pt)) { pt++; } // Trim leading spaces + + signed char sign = 1; + if (*pt == '-') { sign = -1; } + if (*pt == '-' || *pt=='+') { pt++; } // Skip any sign + + double left = 0; + if (*pt != '.') { + left = atoi(pt); // Get left part + while (isdigit(*pt)) { pt++; } // Skip number + } + double right = 0; - short len = 0; - pt = strtok (strbuf, "."); - if (pt) { - pt = strtok (NULL, "."); - if (pt) { - right = atoi(pt); - len = strlen(pt); - double fac = 1; - while (len) { - fac /= 10.0; - len--; - } - // pow is also very large - //double fac=pow(10,-len); - right *= fac; + if (*pt == '.') { + pt++; + right = atoi(pt); // Decimal part + while (isdigit(*pt)) { + pt++; + right /= 10.0; } } + double result = left + right; - if (left < 0) { result = left - right; } + if (sign < 0) { + return -result; // Add negative sign + } return result; } From 108e1797d2a1c82e1f872168c26f61ca1501caf9 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 6 Mar 2019 14:23:30 -0300 Subject: [PATCH 1122/2222] Update to Troubleshooting Issue Template Added Links to Contributing Guide for new users Clarified the step asking for Tasmota Version and uploader tool used. Added Guide Notes for the issue opener that are not displayed when submitting the issue. --- .github/ISSUE_TEMPLATE/Custom.md | 43 ++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Custom.md b/.github/ISSUE_TEMPLATE/Custom.md index 4d1eba459..44bd847cb 100644 --- a/.github/ISSUE_TEMPLATE/Custom.md +++ b/.github/ISSUE_TEMPLATE/Custom.md @@ -4,24 +4,47 @@ about: Users Troubleshooting Help --- -**IMPORTANT NOTICE** -If you do not complete the template below it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses. + + + + + + + + + + + + + +### ISSUE DESCRIPTION - TROUBLESHOOTING +_A clear description of what the issue is and be as extensive as possible_ + + +### REQUESTED INFORMATION +_Make sure these boxes are checked before submitting your issue. Thank you_ **FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** -Make sure these boxes are checked [x] before submitting your issue - Thank you! - +- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md) - [ ] Searched the problem in issues (https://github.com/arendst/Sonoff-Tasmota/issues) - [ ] Searched the problem in the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting) - [ ] Searched the problem in the forum (https://groups.google.com/d/forum/sonoffusers) - [ ] Searched the problem in the chat (https://discord.gg/Ks2Kzd4) -- [ ] Development/Compiler/Upload tools used : -- [ ] Hardware used : -- [ ] If a pre-compiled release or development binary was used, which one? : -- [ ] You have tried latest release or development binaries? : +- [ ] Device used (i.e. Sonoff Basic) : _____ +- [ ] Tasmota binary firmware version number used : ____ / (pre-compiled or self-compiled ?) +- [ ] Development IDE - Compiler / Upload tools used : ____ / ____ - [ ] Provide the output of command ``status 0`` : ``` -STATUS 0 OUTPUT HERE -``` +STATUS 0 OUTPUT HERE: + +``` +- [ ] Provide the output of console when you experience your issue if apply : +_(Please use_ ``weblog 4`` _for more debug information)_ +``` +CONSOLE OUTPUT HERE: + + +``` **(Please, remember to close the issue when the problem has been addressed)** From d4c2f48fef3fdf781a435fec25e54ca520a0d021 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 6 Mar 2019 14:24:32 -0300 Subject: [PATCH 1123/2222] Update to Bug Issue Template Added Links to Contributing Guide for new users Clarified the step asking for Tasmota Version and uploader tool used. Added Guide Notes for the issue opener that are not displayed when submitting the issue. --- .github/ISSUE_TEMPLATE/Bug_report.md | 54 +++++++++++++++++++--------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index ad522ec4e..a0ab5e7e3 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -4,39 +4,61 @@ about: Create a report to help us improve --- -**IMPORTANT NOTICE** -If you do not complete the template below it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses. + -**FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** + + + + + + + + -**Describe the bug** +### BUG DESCRIPTION _A clear and concise description of what the bug is._ -_Also, make sure these boxes are checked [x] before submitting your issue - Thank you!_ -- [ ] _Searched the problem in issues and in the wiki_ -- [ ] _Hardware used_ : -- [ ] _Development/Compiler/Upload tools used_ : -- [ ] _If a pre-compiled release or development binary was used, which one?_ : -- [ ] _You have tried latest release or development binaries?_ : -- [ ] _Provide the output of command_``status 0`` : +### REQUESTED INFORMATION +_Make sure these boxes are checked before submitting your issue. Thank you_ + +**FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** + +- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md) +- [ ] Searched the problem in issues (https://github.com/arendst/Sonoff-Tasmota/issues) +- [ ] Searched the problem in the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting) +- [ ] Searched the problem in the forum (https://groups.google.com/d/forum/sonoffusers) +- [ ] Searched the problem in the chat (https://discord.gg/Ks2Kzd4) +- [ ] Device used (i.e. Sonoff Basic) : _____ +- [ ] Tasmota binary firmware version number used : ____ / (pre-compiled or self-compiled ?) +- [ ] Development IDE - Compiler / Upload tools used : ____ / ____ +- [ ] Provide the output of command ``status 0`` : ``` -STATUS 0 OUTPUT HERE - DO NOT DELETE THE MARKERS ABOVE AND BELOW THIS LINE +STATUS 0 OUTPUT HERE: + + +``` +- [ ] Provide the output of console when you experience your issue if apply : +_(Please use_ ``weblog 4`` _for more debug information)_ +``` +CONSOLE OUTPUT HERE: + + ``` -**To Reproduce** +### TO REPRODUCE _Steps to reproduce the behavior:_ -**Expected behavior** +### EXPECTED BEHAVIOUR _A clear and concise description of what you expected to happen._ -**Screenshots** +### SCREENSHOTS _If applicable, add screenshots to help explain your problem._ -**Additional context** +### ADDITIONAL CONTEXT _Add any other context about the problem here._ From 7ab884afc9d7414ae35822f49b4dd5e79f8169fa Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 6 Mar 2019 20:38:13 +0100 Subject: [PATCH 1124/2222] Fix compile error Fix compile error --- sonoff/support.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index c5e5dcc42..8b3cbe58a 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -154,7 +154,7 @@ char* subStr(char* dest, char* str, const char *delim, int index) return sub; } -double CharToDouble(char *str) +double CharToDouble(const char *str) { // simple ascii to double, because atof or strtod are too large char strbuf[24]; From cfcf125b7ec8acd5d9746b5f07a2a79ce8b4301c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 7 Mar 2019 17:47:14 +0100 Subject: [PATCH 1125/2222] Default disable new rule features Default disable rule USE_EXPRESSION and SUPPORT_MQTT_EVENT (#5369) --- sonoff/my_user_config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index e8d900ebe..b5c52ff81 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -280,8 +280,8 @@ // -- Rules --------------------------------------- #define USE_RULES // Add support for rules (+4k4 code) - #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) - #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) +// #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) +// #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) // -- Internal Analog input ----------------------- #define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices @@ -291,7 +291,7 @@ //#define USE_DS18x20_LEGACY // Optional for more than one DS18x20 sensors with dynamic scan using library OneWire (+1k5 code) #define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) // #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors -// #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistors for single DS18B20 +// #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistors for single DS18B20 // -- I2C sensors --------------------------------- #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) From 58fe50d81a49735ac2e8531c8f2eae5aa4112c96 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 7 Mar 2019 18:18:30 +0100 Subject: [PATCH 1126/2222] Update webserver layout Update webserver layout --- .github/ISSUE_TEMPLATE/Bug_report.md | 54 ++++++++---- .github/ISSUE_TEMPLATE/Custom.md | 43 ++++++--- .github/PULL_REQUEST_TEMPLATE.md | 10 +++ .github/stale.yml | 6 +- CODE_OF_CONDUCT.md | 76 ++++++++++++++++ CONTRIBUTING.md | 63 ++++++++++++++ SUPPORT.md | 22 +++++ sonoff/my_user_config.h | 6 +- sonoff/support.ino | 52 +++++++---- sonoff/xdrv_01_webserver.ino | 125 +++++++++++++++------------ sonoff/xdrv_02_mqtt.ino | 2 +- sonoff/xdrv_07_domoticz.ino | 2 +- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_11_knx.ino | 2 +- sonoff/xsns_34_hx711.ino | 2 +- 15 files changed, 355 insertions(+), 112 deletions(-) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 SUPPORT.md diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index ad522ec4e..a0ab5e7e3 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -4,39 +4,61 @@ about: Create a report to help us improve --- -**IMPORTANT NOTICE** -If you do not complete the template below it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses. + -**FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** + + + + + + + + -**Describe the bug** +### BUG DESCRIPTION _A clear and concise description of what the bug is._ -_Also, make sure these boxes are checked [x] before submitting your issue - Thank you!_ -- [ ] _Searched the problem in issues and in the wiki_ -- [ ] _Hardware used_ : -- [ ] _Development/Compiler/Upload tools used_ : -- [ ] _If a pre-compiled release or development binary was used, which one?_ : -- [ ] _You have tried latest release or development binaries?_ : -- [ ] _Provide the output of command_``status 0`` : +### REQUESTED INFORMATION +_Make sure these boxes are checked before submitting your issue. Thank you_ + +**FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** + +- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md) +- [ ] Searched the problem in issues (https://github.com/arendst/Sonoff-Tasmota/issues) +- [ ] Searched the problem in the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting) +- [ ] Searched the problem in the forum (https://groups.google.com/d/forum/sonoffusers) +- [ ] Searched the problem in the chat (https://discord.gg/Ks2Kzd4) +- [ ] Device used (i.e. Sonoff Basic) : _____ +- [ ] Tasmota binary firmware version number used : ____ / (pre-compiled or self-compiled ?) +- [ ] Development IDE - Compiler / Upload tools used : ____ / ____ +- [ ] Provide the output of command ``status 0`` : ``` -STATUS 0 OUTPUT HERE - DO NOT DELETE THE MARKERS ABOVE AND BELOW THIS LINE +STATUS 0 OUTPUT HERE: + + +``` +- [ ] Provide the output of console when you experience your issue if apply : +_(Please use_ ``weblog 4`` _for more debug information)_ +``` +CONSOLE OUTPUT HERE: + + ``` -**To Reproduce** +### TO REPRODUCE _Steps to reproduce the behavior:_ -**Expected behavior** +### EXPECTED BEHAVIOUR _A clear and concise description of what you expected to happen._ -**Screenshots** +### SCREENSHOTS _If applicable, add screenshots to help explain your problem._ -**Additional context** +### ADDITIONAL CONTEXT _Add any other context about the problem here._ diff --git a/.github/ISSUE_TEMPLATE/Custom.md b/.github/ISSUE_TEMPLATE/Custom.md index 4d1eba459..44bd847cb 100644 --- a/.github/ISSUE_TEMPLATE/Custom.md +++ b/.github/ISSUE_TEMPLATE/Custom.md @@ -4,24 +4,47 @@ about: Users Troubleshooting Help --- -**IMPORTANT NOTICE** -If you do not complete the template below it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses. + + + + + + + + + + + + + +### ISSUE DESCRIPTION - TROUBLESHOOTING +_A clear description of what the issue is and be as extensive as possible_ + + +### REQUESTED INFORMATION +_Make sure these boxes are checked before submitting your issue. Thank you_ **FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** -Make sure these boxes are checked [x] before submitting your issue - Thank you! - +- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md) - [ ] Searched the problem in issues (https://github.com/arendst/Sonoff-Tasmota/issues) - [ ] Searched the problem in the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting) - [ ] Searched the problem in the forum (https://groups.google.com/d/forum/sonoffusers) - [ ] Searched the problem in the chat (https://discord.gg/Ks2Kzd4) -- [ ] Development/Compiler/Upload tools used : -- [ ] Hardware used : -- [ ] If a pre-compiled release or development binary was used, which one? : -- [ ] You have tried latest release or development binaries? : +- [ ] Device used (i.e. Sonoff Basic) : _____ +- [ ] Tasmota binary firmware version number used : ____ / (pre-compiled or self-compiled ?) +- [ ] Development IDE - Compiler / Upload tools used : ____ / ____ - [ ] Provide the output of command ``status 0`` : ``` -STATUS 0 OUTPUT HERE -``` +STATUS 0 OUTPUT HERE: + +``` +- [ ] Provide the output of console when you experience your issue if apply : +_(Please use_ ``weblog 4`` _for more debug information)_ +``` +CONSOLE OUTPUT HERE: + + +``` **(Please, remember to close the issue when the problem has been addressed)** diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..aea7cd816 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,10 @@ +## Description: + +**Related issue (if applicable):** fixes # + +## Checklist: + - [ ] The pull request is done against the dev branch + - [ ] Only relevant files were touched (Also beware if your editor has auto-formatting feature enabled) + - [ ] Only one feature/fix was added per PR. + - [ ] The code change is tested and works. + - [ ] The code change pass travis tests. **Your PR cannot be merged unless tests pass** diff --git a/.github/stale.yml b/.github/stale.yml index 88c5f7c21..484010321 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,9 +1,9 @@ # Number of days of inactivity before an Issue or Pull Request becomes stale -daysUntilStale: 45 +daysUntilStale: 25 # Number of days of inactivity before a stale Issue or Pull Request is closed. # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. -daysUntilClose: 15 +daysUntilClose: 5 # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable exemptLabels: @@ -37,4 +37,4 @@ closeComment: > limitPerRun: 30 # Limit to only `issues` or `pulls` -only: issues +#only: issues diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..1408ce048 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at https://sidweb.nl/cms3/en/contact. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..7cfcdfadb --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,63 @@ +# Contributing to Sonoff-Tasmota + +**Any contribution helps our team and makes Tasmota better for the entire community!** + +Everybody is welcome and invited to contribute to Sonoff-Tasmota Project by: + +* Testing newly released features and reporting issues. +* Providing Pull Requests (Features, Proof of Concepts, Language files or Fixes) +* Contributing missing documentation for features and devices on our [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Contributing) + +This document describes rules that are in effect for this repository, meant for handling issues by contributors in the issue tracker and PRs. + +## Opening New Issues + +**Issue tracker is NOT a general discussion forum!** +1. Opening an issue means that a problem exists in the code and should be addressed by the project contributors. +2. When opening an issue, it is required to fill out the presented template. The requested information is important! If the template is ignored or insufficient info about the issue is provided, the issue may be closed. +3. Questions of type "How do I..." or "Can you please help me with..." or "Can Tasmota do..." WILL NOT be handled here. Such questions should be directed at a discussion forum or to the Tasmota Support Chat. All issues of this type will be closed with a simple reference to this contributing policy. +4. Issues about topics already handled in the documentation will be closed in a similar manner. +5. Issues for unmerged PRs will be closed. If there is an issue with a PR, the explanation should be added to the PR itself. +6. Issues with accompanied investigation that shows the root of the problem should be given priority. +7. Duplicate issues will be closed. + +## Triaging of Issues/PR's + +1. Any contributor to the project can participate in the triaging process, if he/she chooses to do so. +2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor. +3. Issues that are accepted should be marked with appropriate labels. +4. Issues that could impact functionality for many users should be considered severe. +5. Issues caused by the SDK or chip should not be marked severe, as there usually isn’t much to be done. Common sense should be applied when deciding. Such issues should be documented in the Wiki, for reference by users. +6. Issues with feature requests should be discussed for viability/desirability. +7. Feature requests or changes that are meant to address a very specific/limited use case, especially if at the expense of increased code complexity, may be denied, or may be required to be redesigned, generalized, or simplified. +8. Feature requests that are not accompanied by a PR: + * could be closed immediately (denied). + * could be closed after some predetermined period of time (left as candidate for somebody to pick up). +9. In some cases, feedback may be requested from the issue reporter, either as additional info for clarification, additional testing, or other. If no feedback is provided, the issue may be closed by a contributor or after 30 days by the STALE bot. + +## Pull requests + +A Pull Request (PR) is the process where code modifications are managed in GitHub. + +The process is straight-forward. + + - Read [How to get faster PR reviews](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) by Kubernetes (but skip step 0) + - Fork the Sonoff-Tasmota Repository [git repository](https://github.com/arendst/Sonoff-Tasmota). + - Write/Change the code in your Fork for a new feature, bug fix, new sensor, optimization, etc. + - Ensure tests work. + - Create a Pull Request against the [**dev**](https://github.com/arendst/Sonoff-Tasmota/tree/dev) branch of Sonoff-Tasmota. + +1. All pull requests must be done against the dev branch. +2. Only relevant files should be touched (Also beware if your editor has auto-formatting feature enabled). +3. Only one feature/fix should be added per PR. +4. If adding a new functionality (new hardware, new library support) not related to an existing component move it to it's own modules (.ino file). +5. PRs that don't compile (break Travis) or cause coding errors will not be merged. Please fix the issue. Same goes for PRs that are raised against older commit in dev - you might need to rebase and resolve conflicts. +6. All pull requests should undergo peer review by at least one contributor other than the creator, excepts for the owner. +7. All pull requests should consider updates to the documentation. +8. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority. +9. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged. +10. Pull requests that don't meet the above will be denied and closed. + + + + diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 000000000..46fa03ebc --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,22 @@ +# Sonoff-Tasmota Support + +If you're looking for support on **Sonoff-Tasmota** there are some options available: + +### Documentation: + +* [Wiki Pages](https://github.com/arendst/Sonoff-Tasmota/wiki): For information on how to Flash Tasmota, configure and use it. +* [Troubleshooting Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting): For information on common problems and solutions. +* [Commands Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands): For information on all the commands supported by Tasmota. + +### Support's Community: + +* [Tasmota Forum](https://groups.google.com/d/forum/sonoffusers): For usage and discussions. +* [Tasmota Support Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community. +* [Search in Issues](https://github.com/arendst/Sonoff-Tasmota/issues): You might find an answer to your question by searching current or closed issues. + +### Developers' Community: + +* [Bug Report](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software. +* [Feature Request](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software. +* [Troubleshooting](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Custom.md): As a last resort, you can open new *Troubleshooting* issue on GitHub if the solution could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. +* [Issue a question](https://github.com/arendst/Sonoff-Tasmota/issues/new/choose): As a last resort, you can open new *Question* issue on GitHub if the answer could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index e8d900ebe..b5c52ff81 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -280,8 +280,8 @@ // -- Rules --------------------------------------- #define USE_RULES // Add support for rules (+4k4 code) - #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) - #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) +// #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) +// #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) // -- Internal Analog input ----------------------- #define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices @@ -291,7 +291,7 @@ //#define USE_DS18x20_LEGACY // Optional for more than one DS18x20 sensors with dynamic scan using library OneWire (+1k5 code) #define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) // #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors -// #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistors for single DS18B20 +// #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistors for single DS18B20 // -- I2C sensors --------------------------------- #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) diff --git a/sonoff/support.ino b/sonoff/support.ino index 8bb9d1dea..67f53d451 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -160,28 +160,33 @@ double CharToDouble(const char *str) char strbuf[24]; strlcpy(strbuf, str, sizeof(strbuf)); - char *pt; - double left = atoi(strbuf); + char *pt = strbuf; + while ((*pt != '\0') && isblank(*pt)) { pt++; } // Trim leading spaces + + signed char sign = 1; + if (*pt == '-') { sign = -1; } + if (*pt == '-' || *pt=='+') { pt++; } // Skip any sign + + double left = 0; + if (*pt != '.') { + left = atoi(pt); // Get left part + while (isdigit(*pt)) { pt++; } // Skip number + } + double right = 0; - short len = 0; - pt = strtok (strbuf, "."); - if (pt) { - pt = strtok (NULL, "."); - if (pt) { - right = atoi(pt); - len = strlen(pt); - double fac = 1; - while (len) { - fac /= 10.0; - len--; - } - // pow is also very large - //double fac=pow(10,-len); - right *= fac; + if (*pt == '.') { + pt++; + right = atoi(pt); // Decimal part + while (isdigit(*pt)) { + pt++; + right /= 10.0; } } + double result = left + right; - if (left < 0) { result = left - right; } + if (sign < 0) { + return -result; // Add negative sign + } return result; } @@ -1274,6 +1279,17 @@ void AddLog_P(uint8_t loglevel, const char *formatP, const char *formatP2) AddLog(loglevel); } +void AddLog_P2(uint8_t loglevel, PGM_P formatP, ...) +{ + // This uses char strings. Be aware of sending %% if % is needed + va_list arg; + va_start(arg, formatP); + int len = vsnprintf_P(log_data, sizeof(log_data), formatP, arg); + va_end(arg); + + AddLog(loglevel); +} + void AddLogBuffer(uint8_t loglevel, uint8_t *buffer, int count) { snprintf_P(log_data, sizeof(log_data), PSTR("DMP:")); diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index bb2af46e9..8df9529b4 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -283,10 +283,11 @@ const char HTTP_MSG_SLIDER2[] PROGMEM = const char HTTP_MSG_RSTRT[] PROGMEM = "
" D_DEVICE_WILL_RESTART "

"; -const char HTTP_BTN_MENU1[] PROGMEM = +const char HTTP_BTN_CONF[] PROGMEM = "
" + ""; +const char HTTP_BTN_MENU1[] PROGMEM = #ifndef FIRMWARE_MINIMAL - "
" "

" #endif "
" @@ -297,30 +298,30 @@ const char HTTP_BTN_RSTRT[] PROGMEM = const char HTTP_BTN_MENU_MODULE[] PROGMEM = "

" "

"; -const char HTTP_BTN_RESET[] PROGMEM = - "
" - "
"; const char HTTP_BTN_MENU4[] PROGMEM = "

" "

" "

"; + +const char HTTP_BTN_RESET[] PROGMEM = + "
" + "
"; const char HTTP_BTN_MENU5[] PROGMEM = "

" "

"; + const char HTTP_BTN_MAIN[] PROGMEM = "
" "
"; const char HTTP_FORM_LOGIN[] PROGMEM = + "
" "
" - "
" D_USER "

" - "
" D_PASSWORD "

" + "

" D_USER "

" + "

" D_PASSWORD "

" "
" - "
"; - -const char HTTP_BTN_CONF[] PROGMEM = - "
" - "
"; + "" + "
"; const char HTTP_FORM_TEMPLATE[] PROGMEM = "
 " D_TEMPLATE_PARAMETERS " " @@ -481,37 +482,32 @@ void StartWebserver(int type, IPAddress ipweb) if (!Settings.web_refresh) { Settings.web_refresh = HTTP_REFRESH_TIME; } if (!webserver_state) { if (!WebServer) { - WebServer = new ESP8266WebServer((HTTP_MANAGER==type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT); + WebServer = new ESP8266WebServer((HTTP_MANAGER == type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT); WebServer->on("/", HandleRoot); WebServer->onNotFound(HandleNotFound); + WebServer->on("/up", HandleUpgradeFirmware); + WebServer->on("/u1", HandleUpgradeFirmwareStart); // OTA + WebServer->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); + WebServer->on("/u2", HTTP_OPTIONS, HandlePreflightRequest); + WebServer->on("/cs", HandleConsole); + WebServer->on("/cm", HandleHttpCommand); #ifndef FIRMWARE_MINIMAL + WebServer->on("/cn", HandleConfiguration); + WebServer->on("/md", HandleModuleConfiguration); + WebServer->on("/wi", HandleWifiConfiguration); + WebServer->on("/lg", HandleLoggingConfiguration); + WebServer->on("/tp", HandleTemplateConfiguration); + WebServer->on("/co", HandleOtherConfiguration); + WebServer->on("/dl", HandleBackupConfiguration); + WebServer->on("/rs", HandleRestoreConfiguration); WebServer->on("/rt", HandleResetConfiguration); -#endif // FIRMWARE_MINIMAL - if (HTTP_MANAGER_RESET_ONLY != type) { - WebServer->on("/up", HandleUpgradeFirmware); - WebServer->on("/u1", HandleUpgradeFirmwareStart); // OTA - WebServer->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); - WebServer->on("/u2", HTTP_OPTIONS, HandlePreflightRequest); - WebServer->on("/cs", HandleConsole); - WebServer->on("/cm", HandleHttpCommand); -#ifndef FIRMWARE_MINIMAL - WebServer->on("/cn", HandleConfiguration); - WebServer->on("/md", HandleModuleConfiguration); - WebServer->on("/wi", HandleWifiConfiguration); - WebServer->on("/lg", HandleLoggingConfiguration); - WebServer->on("/tp", HandleTemplateConfiguration); - WebServer->on("/co", HandleOtherConfiguration); - WebServer->on("/dl", HandleBackupConfiguration); - WebServer->on("/rs", HandleRestoreConfiguration); - WebServer->on("/rt", HandleResetConfiguration); - WebServer->on("/in", HandleInformation); + WebServer->on("/in", HandleInformation); #ifdef USE_EMULATION - HueWemoAddHandlers(); + HueWemoAddHandlers(); #endif // USE_EMULATION - XdrvCall(FUNC_WEB_ADD_HANDLER); - XsnsCall(FUNC_WEB_ADD_HANDLER); + XdrvCall(FUNC_WEB_ADD_HANDLER); + XsnsCall(FUNC_WEB_ADD_HANDLER); #endif // Not FIRMWARE_MINIMAL - } } reset_web_log_flag = false; WebServer->begin(); // Web server start @@ -727,7 +723,7 @@ void WSContentSendStyle() WSContentSendStyle(F("")); } -void WSContentStop(void) +void WSContentEnd(void) { if (WifiIsInManagerMode()) { if (WifiConfigCounter()) { @@ -767,7 +763,7 @@ void WebRestart(uint8_t type) } else { WSContentSend(FPSTR(HTTP_BTN_MAIN)); } - WSContentStop(); + WSContentEnd(); ShowWebSource(SRC_WEBGUI); restart_flag = 2; @@ -780,7 +776,16 @@ void HandleWifiLogin(void) WSContentStart(FPSTR(D_CONFIGURE_WIFI), false); // false means show page no matter if the client has or has not credentials WSContentSendStyle(); WSContentSend(FPSTR(HTTP_FORM_LOGIN)); - WSContentStop(); + + if (WifiIsInManagerMode()) { + WSContentSend(F("
")); + WSContentSend(FPSTR(HTTP_BTN_RSTRT)); +#ifndef FIRMWARE_MINIMAL + WSContentSend(FPSTR(HTTP_BTN_RESET)); +#endif // FIRMWARE_MINIMAL + } + + WSContentEnd(); } void HandleRoot(void) @@ -864,10 +869,15 @@ void HandleRoot(void) #endif // Not FIRMWARE_MINIMAL if (HTTP_ADMIN == webserver_state) { +#ifndef FIRMWARE_MINIMAL + WSContentSend(FPSTR(HTTP_BTN_CONF)); +#else + WSContentSend(F("
")); +#endif // Not FIRMWARE_MINIMAL WSContentSend(FPSTR(HTTP_BTN_MENU1)); WSContentSend(FPSTR(HTTP_BTN_RSTRT)); } - WSContentStop(); + WSContentEnd(); } bool HandleRootStatusRefresh(void) @@ -969,7 +979,7 @@ void HandleConfiguration(void) WSContentSend(FPSTR(HTTP_BTN_RESET)); WSContentSend(FPSTR(HTTP_BTN_MENU5)); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); } /*-------------------------------------------------------------------------------------------*/ @@ -1056,7 +1066,7 @@ void HandleTemplateConfiguration(void) WSContentSend(FPSTR(HTTP_FORM_TEMPLATE_FLAG)); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void TemplateSaveSettings(void) @@ -1163,7 +1173,7 @@ void HandleModuleConfiguration(void) WSContentSend(F("")); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void ModuleSaveSettings(void) @@ -1210,7 +1220,7 @@ String htmlEscape(String s) void HandleWifiConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } + if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); @@ -1220,7 +1230,7 @@ void HandleWifiConfiguration(void) return; } - WSContentStart(FPSTR(S_CONFIGURE_WIFI)); + WSContentStart(FPSTR(S_CONFIGURE_WIFI), !WifiIsInManagerMode()); WSContentSend(FPSTR(HTTP_SCRIPT_WIFI)); WSContentSendStyle(); @@ -1303,6 +1313,7 @@ void HandleWifiConfiguration(void) } if (WifiIsInManagerMode()) { + WSContentSend(F("
")); WSContentSend(FPSTR(HTTP_BTN_RSTRT)); #ifndef FIRMWARE_MINIMAL WSContentSend(FPSTR(HTTP_BTN_RESET)); @@ -1310,7 +1321,7 @@ void HandleWifiConfiguration(void) } else { WSContentSend(FPSTR(HTTP_BTN_CONF)); } - WSContentStop(); + WSContentEnd(); } void WifiSaveSettings(void) @@ -1371,7 +1382,7 @@ void HandleLoggingConfiguration(void) WSContentSend_P(HTTP_FORM_LOG2, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void LoggingSaveSettings(void) @@ -1448,7 +1459,7 @@ void HandleOtherConfiguration(void) WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void OtherSaveSettings(void) @@ -1535,16 +1546,16 @@ void HandleBackupConfiguration(void) void HandleResetConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } + if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESET_CONFIGURATION); - WSContentStart(FPSTR(S_RESET_CONFIGURATION), (HTTP_MANAGER_RESET_ONLY != webserver_state)); + WSContentStart(FPSTR(S_RESET_CONFIGURATION), !WifiIsInManagerMode()); WSContentSendStyle(); WSContentSend(F("
" D_CONFIGURATION_RESET "
")); WSContentSend(FPSTR(HTTP_MSG_RSTRT)); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); char command[CMDSZ]; snprintf_P(command, sizeof(command), PSTR(D_CMND_RESET " 1")); @@ -1562,7 +1573,7 @@ void HandleRestoreConfiguration(void) WSContentSend(FPSTR(HTTP_FORM_RST)); WSContentSend_P(HTTP_FORM_RST_UPG, D_RESTORE); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); upload_error = 0; upload_file_type = UPL_SETTINGS; @@ -1664,7 +1675,7 @@ void HandleInformation(void) "
")); // WSContentSend(F("
")); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); } #endif // Not FIRMWARE_MINIMAL @@ -1681,7 +1692,7 @@ void HandleUpgradeFirmware(void) WSContentSend_P(HTTP_FORM_UPG, Settings.ota_url); WSContentSend_P(HTTP_FORM_RST_UPG, D_UPGRADE); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); upload_error = 0; upload_file_type = UPL_TASMOTA; @@ -1709,7 +1720,7 @@ void HandleUpgradeFirmwareStart(void) WSContentSend(F("
" D_UPGRADE_STARTED " ...
")); WSContentSend(FPSTR(HTTP_MSG_RSTRT)); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); snprintf_P(command, sizeof(command), PSTR(D_CMND_UPGRADE " 1")); ExecuteWebCommand(command, SRC_WEBGUI); @@ -1757,7 +1768,7 @@ void HandleUploadDone(void) SettingsBufferFree(); WSContentSend(F("

")); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); } void HandleUploadLoop(void) @@ -2038,7 +2049,7 @@ void HandleConsole(void) WSContentSendStyle(); WSContentSend(FPSTR(HTTP_FORM_CMND)); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); } void HandleConsoleRefresh(void) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index d2874f490..ea0cc01e5 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -941,7 +941,7 @@ void HandleMqttConfiguration(void) Settings.mqtt_fulltopic); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void MqttSaveSettings(void) diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index a90245e08..ec4e4f142 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -485,7 +485,7 @@ void HandleDomoticzConfiguration(void) WSContentSend(F("")); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void DomoticzSaveSettings(void) diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index cfc18904a..094fbcd96 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -721,7 +721,7 @@ void HandleTimerConfiguration(void) WSContentSend(FPSTR(HTTP_FORM_TIMER4)); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void TimerSaveSettings(void) diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index d39001250..379f01157 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -947,7 +947,7 @@ void HandleKNXConfiguration(void) WSContentSend(F("
")); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } } diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 5057b8c47..2de8b985a 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -434,7 +434,7 @@ void HandleHxAction(void) WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void HxSaveSettings(void) From 32c69ff0c2c28562e827c3d838460a7aa195782b Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 7 Mar 2019 18:40:50 +0100 Subject: [PATCH 1127/2222] Fix broken hass button announcement --- sonoff/xdrv_12_home_assistant.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index d815eacb2..08c8679d4 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -319,7 +319,7 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint name, state_topic, Settings.state_text[toggle?2:1], availability_topic); try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, unique_id, ESP.getChipId()); - if (strlen(prefix) > 0 ) try_snprintf_P(mqtt_data-1, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + if (strlen(prefix) > 0 ) try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); if (toggle) try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, mqtt_data); else try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH_ONOFF, mqtt_data, Settings.state_text[0]); From 89f55563f742ffddb9bce92c7c52d1bf7310d1e1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 7 Mar 2019 18:59:24 +0100 Subject: [PATCH 1128/2222] Add secure test Add secure test --- sonoff/xdrv_01_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 8df9529b4..d4b9fdaa3 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -777,7 +777,7 @@ void HandleWifiLogin(void) WSContentSendStyle(); WSContentSend(FPSTR(HTTP_FORM_LOGIN)); - if (WifiIsInManagerMode()) { + if (HTTP_MANAGER_RESET_ONLY == webserver_state) { WSContentSend(F("
")); WSContentSend(FPSTR(HTTP_BTN_RSTRT)); #ifndef FIRMWARE_MINIMAL From 06a9fbd792372905059782c478e1ca09317309c5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 8 Mar 2019 15:15:42 +0100 Subject: [PATCH 1129/2222] Changed logging message handling Changed logging message handling --- sonoff/_changelog.ino | 3 +- sonoff/settings.ino | 12 ++--- sonoff/sonoff.ino | 48 ++++++------------- sonoff/support.ino | 19 +++----- sonoff/support_button.ino | 15 ++---- sonoff/support_rotary.ino | 6 +-- sonoff/support_rtc.ino | 4 +- sonoff/support_wifi.ino | 15 ++---- sonoff/xdrv_01_webserver.ino | 44 ++++++----------- sonoff/xdrv_02_mqtt.ino | 26 ++++------- sonoff/xdrv_03_energy.ino | 3 +- sonoff/xdrv_04_light.ino | 31 ++++-------- sonoff/xdrv_05_irremote.ino | 31 ++++-------- sonoff/xdrv_07_domoticz.ino | 9 ++-- sonoff/xdrv_10_rules.ino | 27 ++++------- sonoff/xdrv_11_knx.ino | 70 ++++++++++------------------ sonoff/xdrv_12_home_assistant.ino | 12 ++--- sonoff/xdrv_13_display.ino | 9 ++-- sonoff/xdrv_15_pca9685.ino | 5 +- sonoff/xdrv_16_tuyadimmer.ino | 33 +++++-------- sonoff/xdrv_17_rcswitch.ino | 3 +- sonoff/xdrv_18_armtronix_dimmers.ino | 15 ++---- sonoff/xdrv_19_ps16dz_dimmer.ino | 24 ++++------ sonoff/xdsp_01_lcd.ino | 3 +- sonoff/xdsp_02_ssd1306.ino | 3 +- sonoff/xdsp_03_matrix.ino | 6 +-- sonoff/xdsp_04_ili9341.ino | 3 +- sonoff/xdsp_05_epaper_29.ino | 9 ++-- sonoff/xnrg_01_hlw8012.ino | 3 +- sonoff/xnrg_05_pzem_ac.ino | 3 +- sonoff/xnrg_06_pzem_dc.ino | 3 +- sonoff/xplg_wemohue.ino | 15 ++---- sonoff/xsns_01_counter.ino | 3 +- sonoff/xsns_04_snfsc.ino | 6 +-- sonoff/xsns_05_ds18x20.ino | 3 +- sonoff/xsns_06_dht.ino | 3 +- sonoff/xsns_08_htu21.ino | 3 +- sonoff/xsns_09_bmp.ino | 3 +- sonoff/xsns_10_bh1750.ino | 3 +- sonoff/xsns_11_veml6070.ino | 17 +++---- sonoff/xsns_12_ads1115.ino | 11 ++--- sonoff/xsns_12_ads1115_i2cdev.ino | 3 +- sonoff/xsns_13_ina219.ino | 3 +- sonoff/xsns_14_sht3x.ino | 3 +- sonoff/xsns_15_mhz19.ino | 3 +- sonoff/xsns_16_tsl2561.ino | 3 +- sonoff/xsns_17_senseair.ino | 15 ++---- sonoff/xsns_19_mgs.ino | 3 +- sonoff/xsns_20_novasds.ino | 3 +- sonoff/xsns_21_sgp30.ino | 9 ++-- sonoff/xsns_23_sdm120.ino | 3 +- sonoff/xsns_24_si1145.ino | 3 +- sonoff/xsns_25_sdm630.ino | 3 +- sonoff/xsns_26_lm75ad.ino | 3 +- sonoff/xsns_27_apds9960.ino | 25 ++++------ sonoff/xsns_29_mcp230xx.ino | 24 ++++------ sonoff/xsns_30_mpr121.ino | 22 +++------ sonoff/xsns_31_ccs811.ino | 6 +-- sonoff/xsns_32_mpu6050.ino | 7 ++- sonoff/xsns_33_ds3231.ino | 11 ++--- sonoff/xsns_34_hx711.ino | 4 +- sonoff/xsns_36_mgc3130.ino | 6 +-- sonoff/xsns_37_rfsensor.ino | 9 ++-- sonoff/xsns_40_pn532.ino | 27 ++++------- sonoff/xsns_41_max44009.ino | 3 +- sonoff/xsns_interface.ino | 6 +-- 66 files changed, 259 insertions(+), 512 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 98378f368..29b4175ac 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.4.1.20 20190304 * Changed webserver content handling from single String to small Chunks increasing RAM - * + * Changed logging message handling + * * 6.4.1.19 20190222 * Add command SetOption37 for RGBCW color mapping (#5326) * Add Korean language translations (#5344) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 1b06dae05..dff0d849f 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -435,9 +435,8 @@ void SettingsSave(uint8_t rotate) 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"), - settings_location, Settings.save_flag, sizeof(SYSCFG)); - AddLog(LOG_LEVEL_DEBUG); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG)); settings_crc = Settings.cfg_crc; } @@ -482,9 +481,7 @@ void SettingsLoad(void) } if (settings_location > 0) { ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %d"), - settings_location, Settings.save_flag); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %d"), settings_location, Settings.save_flag); } #ifndef FIRMWARE_MINIMAL @@ -516,8 +513,7 @@ void SettingsErase(uint8_t type) bool _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_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " %d " D_UNIT_SECTORS), _sectorEnd - _sectorStart); for (uint32_t _sector = _sectorStart; _sector < _sectorEnd; _sector++) { result = ESP.flashEraseSector(_sector); diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 2c9392300..d235b125f 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -473,9 +473,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (topicBuf[0] != '/') { ShowSource(SRC_MQTT); } - 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_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_RESULT D_RECEIVED_TOPIC " %s, " D_DATA_SIZE " %d, " D_DATA " %s"), topicBuf, data_len, dataBuf); // if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) { Serial.println(dataBuf); } if (XdrvMqttData(topicBuf, sizeof(topicBuf), dataBuf, sizeof(dataBuf))) { return; } @@ -503,9 +501,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) type[i] = '\0'; } - 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_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_RESULT D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " %s, " D_DATA " %s"), grpflg, index, type, dataBuf); if (type != NULL) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); @@ -526,8 +522,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) int temp_payload = GetStateNumber(dataBuf); if (temp_payload > -1) { payload = temp_payload; } -// snprintf_P(log_data, sizeof(log_data), PSTR("RSLT: Payload %d, Payload16 %d"), payload, payload16); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RSLT: Payload %d, Payload16 %d"), payload, payload16); int command_code = GetCommandCode(command, sizeof(command), type, kTasmotaCommands); if (-1 == command_code) { @@ -1793,8 +1788,7 @@ void PerformEverySecond(void) RtcRebootSave(); Settings.bootcount++; // Moved to here to stop flash writes during start-up - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); } if ((4 == uptime) && (SONOFF_IFAN02 == my_module_type)) { // Microcontroller needs 3 seconds before accepting commands @@ -2001,8 +1995,7 @@ void Every250mSeconds(void) } } #endif // FIRMWARE_MINIMAL - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "%s"), mqtt_data); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), mqtt_data); #if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(mqtt_data)); #else @@ -2013,8 +2006,7 @@ void Every250mSeconds(void) if (!ota_result) { #ifndef FIRMWARE_MINIMAL int ota_error = ESPhttpUpdate.getLastError(); -// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Ota error %d"), ota_error); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "Ota error %d"), ota_error); if ((HTTP_UE_TOO_LESS_SPACE == ota_error) || (HTTP_UE_BIN_FOR_WRONG_FLASH == ota_error)) { RtcSettings.ota_loader = 1; // Try minimal image next } @@ -2145,8 +2137,7 @@ void ArduinoOTAInit(void) AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine #endif // USE_ARILUX_RF if (Settings.flag.mqtt_enabled) { MqttDisconnect(); } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Arduino OTA " D_UPLOAD_STARTED)); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_UPLOAD_STARTED)); arduino_ota_triggered = true; arduino_ota_progress_dot_count = 0; delay(100); // Allow time for message xfer @@ -2177,22 +2168,19 @@ void ArduinoOTAInit(void) default: snprintf_P(error_str, sizeof(error_str), PSTR(D_UPLOAD_ERROR_CODE " %d"), error); } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Arduino OTA %s. " D_RESTARTING), error_str); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA %s. " D_RESTARTING), error_str); EspRestart(); }); ArduinoOTA.onEnd([]() { if ((LOG_LEVEL_DEBUG <= seriallog_level)) { Serial.println(); } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Arduino OTA " D_SUCCESSFUL ". " D_RESTARTING)); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_SUCCESSFUL ". " D_RESTARTING)); EspRestart(); }); ArduinoOTA.begin(); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Arduino OTA " D_ENABLED " " D_PORT " 8266")); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_ENABLED " " D_PORT " 8266")); } #endif // USE_ARDUINO_OTA @@ -2268,8 +2256,7 @@ void SerialInput(void) else if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) { serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)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); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), serial_in_buffer); ExecuteCommand(serial_in_buffer, SRC_SERIAL); serial_in_byte_counter = 0; serial_polling_window = 0; @@ -2338,8 +2325,7 @@ void GpioInit(void) for (uint8_t i = 0; i < sizeof(my_module.io); i++) { mpin = ValidPin(i, my_module.io[i]); -// snprintf_P(log_data, sizeof(log_data), PSTR("DBG: gpio pin %d, mpin %d"), i, mpin); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: gpio pin %d, mpin %d"), i, mpin); if (mpin) { if ((mpin >= GPIO_SWT1_NP) && (mpin < (GPIO_SWT1_NP + MAX_SWITCHES))) { @@ -2584,8 +2570,7 @@ void setup(void) Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic // Settings.last_module = SONOFF_BASIC; } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); } } @@ -2651,12 +2636,9 @@ void setup(void) } blink_powersave = power; - snprintf_P(log_data, sizeof(log_data), PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), - PROJECT, Settings.friendlyname[0], my_version, my_image); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), PROJECT, Settings.friendlyname[0], my_version, my_image); #ifdef FIRMWARE_MINIMAL - snprintf_P(log_data, sizeof(log_data), PSTR(D_WARNING_MINIMAL_VERSION)); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_WARNING_MINIMAL_VERSION)); #endif // FIRMWARE_MINIMAL RtcInit(); diff --git a/sonoff/support.ino b/sonoff/support.ino index 67f53d451..8f1e4c104 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -47,8 +47,7 @@ void OsWatchTicker(void) 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(), WifiGetRssiAsQuality(WiFi.RSSI()), last_run); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d, last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(WiFi.RSSI()), last_run); #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)); // Save iram space @@ -645,8 +644,7 @@ void SetSerialBaudrate(int baudrate) Settings.baudrate = baudrate / 1200; 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); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SET_BAUDRATE_TO " %d"), baudrate); } delay(100); Serial.flush(); @@ -695,8 +693,7 @@ void ShowSource(int source) { if ((source > 0) && (source < SRC_MAX)) { char stemp1[20]; - snprintf_P(log_data, sizeof(log_data), PSTR("SRC: %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource)); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SRC: %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource)); } } @@ -1171,8 +1168,7 @@ bool I2cDevice(uint8_t addr) * Syslog * * Example: - * snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_LOG "Any value %d"), value); - * AddLog(LOG_LEVEL_DEBUG); + * AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_LOG "Any value %d"), value); * \*********************************************************************************************/ @@ -1228,8 +1224,7 @@ void Syslog(void) } 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_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_HOST_NOT_FOUND ". " D_RETRY_IN " %d " D_UNIT_SECOND), SYSLOG_TIMER); } } @@ -1281,7 +1276,6 @@ void AddLog_P(uint8_t loglevel, const char *formatP, const char *formatP2) void AddLog_P2(uint8_t loglevel, PGM_P formatP, ...) { - // This uses char strings. Be aware of sending %% if % is needed va_list arg; va_start(arg, formatP); int len = vsnprintf_P(log_data, sizeof(log_data), formatP, arg); @@ -1306,6 +1300,5 @@ void AddLogSerial(uint8_t loglevel) void AddLogMissed(char *sensor, uint8_t misses) { - snprintf_P(log_data, sizeof(log_data), PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses); } diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index 93b1c22c4..ad17edd77 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -103,8 +103,7 @@ void ButtonHandler(void) if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { 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); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), dual_button_code); button = PRESSED; if (0xF500 == dual_button_code) { // Button hold holdbutton[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; @@ -130,14 +129,12 @@ void ButtonHandler(void) bool button_pressed = false; if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); holdbutton[button_index] = loops_per_second; button_pressed = true; } if ((NOT_PRESSED == button) && (PRESSED == lastbutton[button_index])) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_01), button_index +1); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_01), button_index +1); if (!holdbutton[button_index]) { button_pressed = true; } // Do not allow within 1 second } if (button_pressed) { @@ -149,15 +146,13 @@ void ButtonHandler(void) else { if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { 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), button_index +1); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1); if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally } } else { multipress[button_index] = (multiwindow[button_index]) ? multipress[button_index] +1 : 1; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, multipress[button_index]); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, multipress[button_index]); multiwindow[button_index] = loops_per_second / 2; // 0.5 second multi press window } blinks = 201; diff --git a/sonoff/support_rotary.ino b/sonoff/support_rotary.ino index c8178586a..db88d8378 100644 --- a/sonoff/support_rotary.ino +++ b/sonoff/support_rotary.ino @@ -115,8 +115,7 @@ void RotaryHandler(void) if (t > 500) { t = 500; } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_CMND_COLORTEMPERATURE " %d"), rotary_position - rotary_last_position); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_CMND_COLORTEMPERATURE " %d"), rotary_position - rotary_last_position); LightSetColorTemp((uint16_t)t); } else { int8_t d = Settings.light_dimmer; @@ -127,8 +126,7 @@ void RotaryHandler(void) if (d > 100) { d = 100; } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_CMND_DIMMER " %d"), rotary_position - rotary_last_position); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_CMND_DIMMER " %d"), rotary_position - rotary_last_position); LightSetDimmer((uint8_t)d); Settings.light_dimmer = d; diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index e66eda691..9a36951f0 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -364,9 +364,7 @@ void RtcSecond(void) RtcTime.year = tmpTime.year + 1970; daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "(" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "(" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); if (local_time < 1451602800) { // 2016-01-01 rules_flag.time_init = 1; } else { diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 23f4b20c1..2c7299991 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -107,8 +107,7 @@ void WifiWpsStatusCallback(wps_cb_status 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"), wps_result); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_WPS_FAILED_WITH_STATUS " %d"), wps_result); wifi_config_counter = 2; } } @@ -247,9 +246,8 @@ void WifiBegin(uint8_t flag, uint8_t channel) } else { 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..."), + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s " D_IN_MODE " 11%c " D_AS " %s..."), Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); - AddLog(LOG_LEVEL_INFO); } void WifiBeginAfterScan() @@ -324,9 +322,8 @@ void WifiBeginAfterScan() break; } } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI "Network %d, AP%c, SSId %s, Channel %d, BSSId %02X:%02X:%02X:%02X:%02X:%02X, RSSI %d, Encryption %d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI "Network %d, AP%c, SSId %s, Channel %d, BSSId %02X:%02X:%02X:%02X:%02X:%02X, RSSI %d, Encryption %d"), i, (known) ? (j) ? '2' : '1' : '-', ssid_scan.c_str(), chan_scan, bssid_scan[0], bssid_scan[1], bssid_scan[2], bssid_scan[3], bssid_scan[4], bssid_scan[5], rssi_scan, (sec_scan == ENC_TYPE_NONE) ? 0 : 1); - AddLog(LOG_LEVEL_DEBUG); delay(0); } WiFi.scanDelete(); // Clean up Ram @@ -490,8 +487,7 @@ void WifiCheck(uint8_t param) strlcpy(Settings.sta_pwd[0], WiFi.psk().c_str(), sizeof(Settings.sta_pwd[0])); } Settings.sta_active = 0; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_WCFG_1_SMARTCONFIG D_CMND_SSID "1 %s"), Settings.sta_ssid[0]); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_1_SMARTCONFIG D_CMND_SSID "1 %s"), Settings.sta_ssid[0]); } } if (!wifi_config_counter) { @@ -534,8 +530,7 @@ void WifiCheck(uint8_t param) // } else { // mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; mdns_begun = (uint8_t)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); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (mdns_begun) ? D_INITIALIZED : D_FAILED); // } } } diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index d4b9fdaa3..cfb563e92 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -466,8 +466,7 @@ void ShowWebSource(int source) { if ((source > 0) && (source < SRC_MAX)) { char stemp1[20]; - snprintf_P(log_data, sizeof(log_data), PSTR("SRC: %s from %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource), WebServer->client().remoteIP().toString().c_str()); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SRC: %s from %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource), WebServer->client().remoteIP().toString().c_str()); } } @@ -513,9 +512,7 @@ void StartWebserver(int type, IPAddress ipweb) WebServer->begin(); // Web server start } if (webserver_state != type) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), - my_hostname, (mdns_begun) ? ".local" : "", ipweb.toString().c_str()); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), my_hostname, (mdns_begun) ? ".local" : "", ipweb.toString().c_str()); } if (type) { webserver_state = type; } } @@ -638,8 +635,7 @@ void WSContentSendLl(const String& content) // Low level sendContent for a ShowFreeMem(PSTR("WSContentSend")); -// snprintf_P(log_data, sizeof(log_data), PSTR("WEB: Chunk size %d"), len); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("WEB: Chunk size %d"), len); } void WSContentFlush() @@ -1201,8 +1197,7 @@ void ModuleSaveSettings(void) } } } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), ModuleName().c_str(), gpios.c_str()); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), ModuleName().c_str(), gpios.c_str()); } /*-------------------------------------------------------------------------------------------*/ @@ -1270,8 +1265,7 @@ void HandleWifiConfiguration(void) cssid = WiFi.SSID(indices[i]); for (int j = i + 1; j < n; j++) { if (cssid == WiFi.SSID(indices[j])) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_DUPLICATE_ACCESSPOINT " %s"), WiFi.SSID(indices[j]).c_str()); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_DUPLICATE_ACCESSPOINT " %s"), WiFi.SSID(indices[j]).c_str()); indices[j] = -1; // set dup aps to index -1 } } @@ -1281,8 +1275,7 @@ void HandleWifiConfiguration(void) //display networks in page for (int i = 0; i < n; i++) { if (-1 == indices[i]) { continue; } // skip dups - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i])); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i])); int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); if (minimum_signal_quality == -1 || minimum_signal_quality < quality) { @@ -1341,9 +1334,7 @@ void WifiSaveSettings(void) strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); WebGetArg("p2", tmp, sizeof(tmp)); strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s"), - Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1]); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s"), Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1]); } /*-------------------------------------------------------------------------------------------*/ @@ -1406,9 +1397,8 @@ void LoggingSaveSettings(void) if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) { Settings.tele_period = 10; // Do not allow periods < 10 seconds } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_LOG D_CMND_SERIALLOG " %d, " D_CMND_WEBLOG " %d, " D_CMND_SYSLOG " %d, " D_CMND_LOGHOST " %s, " D_CMND_LOGPORT " %d, " D_CMND_TELEPERIOD " %d"), + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_LOG D_CMND_SERIALLOG " %d, " D_CMND_WEBLOG " %d, " D_CMND_SYSLOG " %d, " D_CMND_LOGHOST " %s, " D_CMND_LOGPORT " %d, " D_CMND_TELEPERIOD " %d"), Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); - AddLog(LOG_LEVEL_INFO); } /*-------------------------------------------------------------------------------------------*/ @@ -1756,8 +1746,7 @@ void HandleUploadDone(void) snprintf_P(error, sizeof(error), PSTR(D_UPLOAD_ERROR_CODE " %d"), upload_error); } WSContentSend(error); - snprintf_P(log_data, sizeof(log_data), PSTR(D_UPLOAD ": %s"), error); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_UPLOAD ": %s"), error); stop_flash_rotate = Settings.flag.stop_flash_rotate; } else { WSContentSend(F("green'>" D_SUCCESSFUL "
")); @@ -1791,8 +1780,7 @@ void HandleUploadLoop(void) return; } SettingsSave(1); // Free flash for upload - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD D_FILE " %s ..."), upload.filename.c_str()); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_FILE " %s ..."), upload.filename.c_str()); if (UPL_SETTINGS == upload_file_type) { if (!SettingsBufferAlloc()) { upload_error = 2; // Not enough space @@ -1951,8 +1939,7 @@ void HandleUploadLoop(void) } } if (!upload_error) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD D_SUCCESSFUL " %u bytes. " D_RESTARTING), upload.totalSize); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_SUCCESSFUL " %u bytes. " D_RESTARTING), upload.totalSize); } } else if (UPLOAD_FILE_ABORTED == upload.status) { restart_flag = 0; @@ -2059,8 +2046,7 @@ void HandleConsoleRefresh(void) String svalue = WebServer->arg("c1"); if (svalue.length() && (svalue.length() < INPUT_BUFFER_SIZE)) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_COMMAND "%s"), svalue.c_str()); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), svalue.c_str()); ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE); } @@ -2107,8 +2093,7 @@ void HandleConsoleRefresh(void) void HandleNotFound(void) { -// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_HTTP "Not fount (%s)"), WebServer->uri().c_str()); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Not fount (%s)"), WebServer->uri().c_str()); if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the error page. @@ -2226,8 +2211,7 @@ int WebSend(char *buffer) } url += command; // url = |http://192.168.178.86/cm?cmnd=POWER1 ON| -//snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Uri |%s|"), url.c_str()); -//AddLog(LOG_LEVEL_DEBUG); +//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: Uri |%s|"), url.c_str()); #if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) HTTPClient http; diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index ea0cc01e5..4df9ca6cb 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -234,8 +234,7 @@ void MqttDiscoverServer(void) 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_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_QUERY_DONE " %d"), n); if (n > 0) { uint8_t i = 0; // If the hostname isn't set, use the first record found. @@ -249,9 +248,7 @@ void MqttDiscoverServer(void) snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(i).toString().c_str()); Settings.mqtt_port = MDNS.port(i); - 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(i).c_str(), Settings.mqtt_host, Settings.mqtt_port); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), MDNS.hostname(i).c_str(), Settings.mqtt_host, Settings.mqtt_port); } } #endif // MQTT_HOST_DISCOVERY @@ -269,15 +266,13 @@ void MqttRetryCounter(uint8_t value) void MqttSubscribe(const char *topic) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_SUBSCRIBE_TO " %s"), topic); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT D_SUBSCRIBE_TO " %s"), topic); MqttSubscribeLib(topic); } void MqttUnsubscribe(const char *topic) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_UNSUBSCRIBE_FROM " %s"), topic); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT D_UNSUBSCRIBE_FROM " %s"), topic); MqttUnsubscribeLib(topic); } @@ -308,8 +303,8 @@ void MqttPublishDirect(const char* topic, bool retained) snprintf_P(log_data, sizeof(log_data), PSTR("%s ..."), log_data); } snprintf_P(log_data, sizeof(log_data), PSTR("%s%s"), log_data, sretained); - AddLog(LOG_LEVEL_INFO); + if (Settings.ledstate &0x04) { blinks++; } @@ -413,9 +408,7 @@ void MqttDisconnected(int state) mqtt_connected = false; mqtt_retry_counter = Settings.mqtt_retry; - 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), - Settings.mqtt_host, Settings.mqtt_port, state, mqtt_retry_counter); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), Settings.mqtt_host, Settings.mqtt_port, state, mqtt_retry_counter); rules_flag.mqtt_disconnected = 1; } @@ -500,9 +493,7 @@ bool MqttCheckTls(void) //#endif 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), - Settings.mqtt_host, Settings.mqtt_port, mqtt_retry_counter); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT D_TLS_CONNECT_FAILED_TO " %s:%d. " D_RETRY_IN " %d " D_UNIT_SECOND), Settings.mqtt_host, Settings.mqtt_port, mqtt_retry_counter); } else { #ifdef USE_MQTT_TLS_CA_CERT unsigned char tls_ca_cert[] = MQTT_TLS_CA_CERT; @@ -972,9 +963,8 @@ void MqttSaveSettings(void) strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user)); WebGetArg("mp", tmp, sizeof(tmp)); strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? Settings.mqtt_pwd : tmp, sizeof(Settings.mqtt_pwd)); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_topic, Settings.mqtt_fulltopic); - AddLog(LOG_LEVEL_INFO); } #endif // USE_WEBSERVER diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 850a5f2d0..10814bd65 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -199,8 +199,7 @@ void EnergyMarginCheck(void) energy_voltage_u = (uint16_t)(energy_voltage); energy_current_u = (uint16_t)(energy_current * 1000); -// snprintf_P(log_data, sizeof(log_data), PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); jsonflg = false; diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index dcf82aa86..1dc6e8630 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -205,8 +205,7 @@ void AriluxRfHandler(void) } uint16_t stored_hostcode = Settings.rf_code[1][6] << 8 | Settings.rf_code[1][7]; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_RFR D_HOST D_CODE " 0x%04X, " D_RECEIVED " 0x%06X"), stored_hostcode, arilux_rf_received_value); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_RFR D_HOST D_CODE " 0x%04X, " D_RECEIVED " 0x%06X"), stored_hostcode, arilux_rf_received_value); if (hostcode == stored_hostcode) { char command[33]; @@ -406,8 +405,7 @@ void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) uint8_t sm16716_should_enable = (duty_r | duty_g | duty_b); if (!sm16716_enabled && sm16716_should_enable) { #ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "turning color on")); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SM16716 "turning color on")); #endif // D_LOG_SM16716 sm16716_enabled = 1; digitalWrite(sm16716_pin_sel, HIGH); @@ -418,18 +416,14 @@ void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) } else if (sm16716_enabled && !sm16716_should_enable) { #ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "turning color off")); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SM16716 "turning color off")); #endif // D_LOG_SM16716 sm16716_enabled = 0; digitalWrite(sm16716_pin_sel, LOW); } } #ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), - duty_r, duty_g, duty_b); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), duty_r, duty_g, duty_b); #endif // D_LOG_SM16716 // send start bit @@ -454,10 +448,7 @@ bool SM16716_ModuleSelected(void) sm16716_pin_dat = pin[GPIO_SM16716_DAT]; sm16716_pin_sel = pin[GPIO_SM16716_SEL]; #ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), - sm16716_pin_clk, sm16716_pin_dat); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), sm16716_pin_clk, sm16716_pin_dat); #endif // D_LOG_SM16716 return (sm16716_pin_clk < 99) && (sm16716_pin_dat < 99); } @@ -598,8 +589,7 @@ void LightUpdateColorMapping(void) light_ct_rgb_linked = !(Settings.param[P_RGB_REMAP] & 128); light_update = 1; - //snprintf_P(log_data, sizeof(log_data), "%d colors: %d %d %d %d %d",Settings.param[P_RGB_REMAP], light_color_remap[0],light_color_remap[1],light_color_remap[2],light_color_remap[3],light_color_remap[4]); - //AddLog(LOG_LEVEL_DEBUG); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%d colors: %d %d %d %d %d") ,Settings.param[P_RGB_REMAP], light_color_remap[0],light_color_remap[1],light_color_remap[2],light_color_remap[3],light_color_remap[4]); } void LightSetColorTemp(uint16_t ct) @@ -707,8 +697,7 @@ void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value) signal = 255; } } -// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "Light signal %d"), signal); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Light signal %d"), signal); light_signal_color[0] = signal; light_signal_color[1] = 255 - signal; light_signal_color[2] = 0; @@ -1015,8 +1004,7 @@ void LightAnimate(void) cur_col[i] = 0xFC; // Fix unwanted blinking and PWM watchdog errors for values close to pwm_range (H801, Arilux and BN-SZ01) } 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); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d %d, CurCol %d"), i, cur_col[i], curcol); analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - curcol : curcol); } } @@ -1044,8 +1032,7 @@ void LightAnimate(void) cur_col[i] = 0xFC; // Fix unwanted blinking and PWM watchdog errors for values close to pwm_range (H801, Arilux and BN-SZ01) } 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); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d %d, CurCol %d"), i, cur_col[i], curcol); analogWrite(pin[GPIO_PWM1 +i-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - curcol : curcol); } } diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 32a7d054b..f9f88bd56 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -114,9 +114,8 @@ void IrReceiveCheck(void) if (irrecv->decode(&results)) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value %08X, Decode %d"), - irsend_active, results.rawlen, results.overflow, results.bits, results.value, results.decode_type); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value %08X, Decode %d"), + irsend_active, results.rawlen, results.overflow, results.bits, results.value, results.decode_type); unsigned long now = millis(); // if ((now - ir_lasttime > IR_TIME_AVOID_DUPLICATE) && (UNKNOWN != results.decode_type) && (results.bits > 0)) { @@ -314,9 +313,8 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC 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"), +// AddLog_P2(LOG_LEVEL_DEBUG, 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; } @@ -381,8 +379,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, hvacOn = true; } -// snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: HvacMode %s, ModeVal %d, Code %d"), p, mode, data[3]); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: HvacMode %s, ModeVal %d, Code %d"), p, mode, data[3]); // Set code for HVAC temperature - data[4] if (HVAC_Temp > 30) { @@ -414,8 +411,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, data[5] = (mode * 2) - 2; // Low = 0x00, Mid = 0x02, High = 0x04 } -// snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: FanMode %s, ModeVal %d, Code %d"), p, mode, data[5]); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: FanMode %s, ModeVal %d, Code %d"), p, mode, data[5]); // Set CRC code - data[6] data[6] = (data[3] + data[4] + data[5]) & 0x0f; // CRC @@ -428,8 +424,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, } LG_Code = LG_Code + data[6]; -// snprintf_P(log_data, sizeof(log_data), PSTR("IRHVAC: LG_Code %d"), LG_Code); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: LG_Code %d"), LG_Code); // Send LG IR Code // noInterrupts(); @@ -449,8 +444,7 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po { const char kFujitsuHvacModeOptions[] = "HDCAF"; -// snprintf_P(log_data, sizeof(log_data), PSTR("FUJITSU: mode:%s, fan:%s, power:%u, temp:%u"), HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FUJITSU: mode:%s, fan:%s, power:%u, temp:%u"), HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); IRFujitsuAC ac(pin[GPIO_IRSEND]); @@ -541,9 +535,7 @@ bool IrSendCommand(void) raw_array[i++] = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input } -// snprintf_P(log_data, sizeof(log_data), PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), -// count, freq, raw_array[0], raw_array[count -1]); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), count, freq, raw_array[0], raw_array[count -1]); irsend_active = true; irsend->sendRaw(raw_array, count, freq); @@ -573,9 +565,8 @@ bool IrSendCommand(void) char protocol_text[20]; int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); - snprintf_P(log_data, sizeof(log_data), PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"), protocol_text, protocol, bits, data, data, protocol_code); - AddLog(LOG_LEVEL_DEBUG); irsend_active = true; switch (protocol_code) { @@ -637,9 +628,7 @@ bool IrSendCommand(void) HVAC_FanMode = root[D_JSON_IRHVAC_FANSPEED]; HVAC_Temp = root[D_JSON_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); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Received Vendor %s, Power %d, Mode %s, FanSpeed %s, Temp %d"), HVAC_Vendor, HVAC_Power, HVAC_Mode, HVAC_FanMode, HVAC_Temp); char vendor[20]; int vendor_code = GetCommandCode(vendor, sizeof(vendor), HVAC_Vendor, kIrHvacVendors); diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index ec4e4f142..4c660998e 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -206,8 +206,7 @@ bool DomoticzMqttData(void) 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_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) { uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; @@ -275,8 +274,7 @@ bool DomoticzMqttData(void) return 1; } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data); - AddLog(LOG_LEVEL_DEBUG_MORE); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data); domoticz_update_flag = 0; } @@ -515,12 +513,11 @@ void DomoticzSaveSettings(void) WebGetArg("ut", tmp, sizeof(tmp)); Settings.domoticz_update_timer = (!strlen(tmp)) ? DOMOTICZ_UPDATE_TIMER : atoi(tmp); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DOMOTICZ D_CMND_IDX " %d,%d,%d,%d, " D_CMND_KEYIDX " %d,%d,%d,%d, " D_CMND_SWITCHIDX " %d,%d,%d,%d, " D_CMND_SENSORIDX " %s, " D_CMND_UPDATETIMER " %d"), + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_DOMOTICZ D_CMND_IDX " %d,%d,%d,%d, " D_CMND_KEYIDX " %d,%d,%d,%d, " D_CMND_SWITCHIDX " %d,%d,%d,%d, " D_CMND_SENSORIDX " %s, " D_CMND_UPDATETIMER " %d"), Settings.domoticz_relay_idx[0], Settings.domoticz_relay_idx[1], Settings.domoticz_relay_idx[2], Settings.domoticz_relay_idx[3], 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], ssensor_indices, Settings.domoticz_update_timer); - AddLog(LOG_LEVEL_INFO); } #endif // USE_WEBSERVER diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 2a58ea880..7897a0c17 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -237,9 +237,8 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) double value = 0; const char* str_value = root[rule_task][rule_name]; -//snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Task %s, Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json %s"), +//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Task %s, Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json %s"), // rule_task.c_str(), rule_name.c_str(), rule_svalue, rules_trigger_count[rule_set], bitRead(rules_triggers[rule_set], rules_trigger_count[rule_set]), event.c_str(), (str_value) ? str_value : "none"); -//AddLog(LOG_LEVEL_DEBUG); if (!root[rule_task][rule_name].success()) { return false; } // No value but rule_name is ok @@ -305,8 +304,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) delay(0); // Prohibit possible loop software watchdog -//snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Event = %s, Rule = %s"), event_saved.c_str(), Settings.rules[rule_set]); -//AddLog(LOG_LEVEL_DEBUG); +//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Event = %s, Rule = %s"), event_saved.c_str(), Settings.rules[rule_set]); String rules = Settings.rules[rule_set]; @@ -341,8 +339,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) rules_event_value = ""; String event = event_saved; -//snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Event |%s|, Rule |%s|, Command(s) |%s|"), event.c_str(), event_trigger.c_str(), commands.c_str()); -//AddLog(LOG_LEVEL_DEBUG); +//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Event |%s|, Rule |%s|, Command(s) |%s|"), event.c_str(), event_trigger.c_str(), commands.c_str()); if (RulesRuleMatch(rule_set, event, event_trigger)) { commands.trim(); @@ -370,8 +367,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) char command[commands.length() +1]; snprintf(command, sizeof(command), commands.c_str()); - snprintf_P(log_data, sizeof(log_data), PSTR("RUL: %s performs \"%s\""), event_trigger.c_str(), command); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: %s performs \"%s\""), event_trigger.c_str(), command); // snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, D_CMND_RULE, D_JSON_INITIATED); // MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RULE)); @@ -396,8 +392,7 @@ bool RulesProcessEvent(char *json_event) String event_saved = json_event; event_saved.toUpperCase(); -//snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Event %s"), event_saved.c_str()); -//AddLog(LOG_LEVEL_DEBUG); +//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Event %s"), event_saved.c_str()); for (uint8_t i = 0; i < MAX_RULE_SETS; i++) { if (strlen(Settings.rules[i]) && bitRead(Settings.rule_enabled, i)) { @@ -608,15 +603,13 @@ bool RulesMqttData(void) } String sTopic = XdrvMailbox.topic; String sData = XdrvMailbox.data; - //snprintf_P(log_data, sizeof(log_data), PSTR("RUL: MQTT Topic %s, Event %s"), XdrvMailbox.topic, XdrvMailbox.data); - //AddLog(LOG_LEVEL_DEBUG); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: MQTT Topic %s, Event %s"), XdrvMailbox.topic, XdrvMailbox.data); MQTT_Subscription event_item; //Looking for matched topic for (int index = 0; index < subscriptions.size(); index++) { event_item = subscriptions.get(index); - //snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Match MQTT message Topic %s with subscription topic %s"), sTopic.c_str(), event_item.Topic.c_str()); - //AddLog(LOG_LEVEL_DEBUG); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Match MQTT message Topic %s with subscription topic %s"), sTopic.c_str(), event_item.Topic.c_str()); if (sTopic.startsWith(event_item.Topic)) { //This topic is subscribed by us, so serve it serviced = true; @@ -686,8 +679,7 @@ String RulesSubscribe(const char *data, int data_len) } } } - //snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Subscribe command with parameters: %s, %s, %s."), event_name.c_str(), topic.c_str(), key.c_str()); - //AddLog(LOG_LEVEL_DEBUG); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Subscribe command with parameters: %s, %s, %s."), event_name.c_str(), topic.c_str(), key.c_str()); event_name.toUpperCase(); if (event_name.length() > 0 && topic.length() > 0) { //Search all subscriptions @@ -708,8 +700,7 @@ String RulesSubscribe(const char *data, int data_len) topic.concat("/#"); } } - //snprintf_P(log_data, sizeof(log_data), PSTR("RUL: New topic: %s."), topic.c_str()); - //AddLog(LOG_LEVEL_DEBUG); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: New topic: %s."), topic.c_str()); //MQTT Subscribe subscription_item.Event = event_name; subscription_item.Topic = topic.substring(0, topic.length() - 2); //Remove "/#" so easy to match diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 379f01157..af23ab220 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -247,11 +247,10 @@ void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF Settings.knx_GA_registered++; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_ADD " GA #%d: %s " D_TO " %d/%d/%d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " GA #%d: %s " D_TO " %d/%d/%d"), Settings.knx_GA_registered, device_param_ga[GAop-1], GA_FNUM, GA_AREA, GA_FDEF ); - AddLog(LOG_LEVEL_DEBUG); } @@ -297,9 +296,8 @@ void KNX_DEL_GA( uint8_t GAnum ) Settings.knx_GA_registered--; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_DELETE " GA #%d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " GA #%d"), GAnum ); - AddLog(LOG_LEVEL_DEBUG); } @@ -330,11 +328,10 @@ void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF Settings.knx_CB_registered++; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_ADD " CB #%d: %d/%d/%d " D_TO " %s"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " CB #%d: %d/%d/%d " D_TO " %s"), Settings.knx_CB_registered, CB_FNUM, CB_AREA, CB_FDEF, device_param_cb[CBop-1] ); - AddLog(LOG_LEVEL_DEBUG); } @@ -387,8 +384,7 @@ void KNX_DEL_CB( uint8_t CBnum ) device_param[oldparam-1].CB_id = KNX_Empty; } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_DELETE " CB #%d"), CBnum ); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " CB #%d"), CBnum ); } @@ -445,8 +441,7 @@ bool KNX_CONFIG_NOT_MATCH(void) void KNXStart(void) { knx.start(nullptr); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_START)); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_START)); } @@ -522,8 +517,7 @@ void KNX_INIT(void) if (KNX_CONFIG_NOT_MATCH()) { Settings.knx_GA_registered = 0; Settings.knx_CB_registered = 0; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_DELETE " " D_KNX_PARAMETERS )); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " " D_KNX_PARAMETERS)); } // Register Group Addresses to listen to @@ -555,22 +549,18 @@ void KNX_CB_Action(message_t const &msg, void *arg) if (msg.data_len == 1) { // COMMAND - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %d " D_TO " %s"), - msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member, - (msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER, - msg.data[0], - device_param_cb[(chan->type)-1]); + tempchar[0] = msg.data[0]; + tempchar[1] = '\0'; } else { // VALUE float tempvar = knx.data_to_2byte_float(msg.data); dtostrfd(tempvar,2,tempchar); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %s " D_TO " %s"), - msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member, - (msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER, - tempchar, - device_param_cb[(chan->type)-1]); } - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %s " D_TO " %s"), + msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member, + (msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER, + tempchar, + device_param_cb[(chan->type)-1]); switch (msg.ct) { @@ -668,10 +658,9 @@ void KnxUpdatePowerState(uint8_t device, power_t state) knx.write_1bit(KNX_addr, device_param[device -1].last_state); } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), device_param_ga[device -1], device_param[device -1].last_state, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - AddLog(LOG_LEVEL_INFO); i = KNX_GA_Search(device, i + 1); } @@ -701,10 +690,9 @@ void KnxSendButtonPower(uint8_t key, uint8_t device, uint8_t state) knx.write_1bit(KNX_addr, !(state == 0)); } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), device_param_ga[device + 7], !(state == 0), KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - AddLog(LOG_LEVEL_INFO); i = KNX_GA_Search(device + 8, i + 1); } @@ -733,10 +721,9 @@ void KnxSensor(uint8_t sensor_type, float value) knx.write_2byte_float(KNX_addr, value); } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "%s " D_SENT_TO " %d.%d.%d "), + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s " D_SENT_TO " %d.%d.%d "), device_param_ga[sensor_type -1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - AddLog(LOG_LEVEL_INFO); i = KNX_GA_Search(sensor_type, i+1); } @@ -960,9 +947,8 @@ void KNX_Save_Settings(void) Settings.flag.knx_enabled = WebServer->hasArg("b1"); Settings.flag.knx_enable_enhancement = WebServer->hasArg("b2"); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_ENABLED ": %d, " D_KNX_ENHANCEMENT ": %d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ENABLED ": %d, " D_KNX_ENHANCEMENT ": %d"), Settings.flag.knx_enabled, Settings.flag.knx_enable_enhancement ); - AddLog(LOG_LEVEL_DEBUG); stmp = WebServer->arg("area"); KNX_addr.pa.area = stmp.toInt(); @@ -972,33 +958,29 @@ void KNX_Save_Settings(void) KNX_addr.pa.member = stmp.toInt(); Settings.knx_physsical_addr = KNX_addr.value; knx.physical_address_set( KNX_addr ); // Set Physical KNX Address of the device - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_KNX_PHYSICAL_ADDRESS ": %d.%d.%d "), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_KNX_PHYSICAL_ADDRESS ": %d.%d.%d "), KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); - AddLog(LOG_LEVEL_DEBUG); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "GA: %d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA: %d"), Settings.knx_GA_registered ); - AddLog(LOG_LEVEL_DEBUG); for (uint8_t i = 0; i < Settings.knx_GA_registered ; ++i) { KNX_addr.value = Settings.knx_GA_addr[i]; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "GA #%d: %s " D_TO " %d/%d/%d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA #%d: %s " D_TO " %d/%d/%d"), i+1, device_param_ga[Settings.knx_GA_param[i]-1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); - AddLog(LOG_LEVEL_DEBUG); + } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "CB: %d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB: %d"), Settings.knx_CB_registered ); - AddLog(LOG_LEVEL_DEBUG); for (uint8_t i = 0; i < Settings.knx_CB_registered ; ++i) { KNX_addr.value = Settings.knx_CB_addr[i]; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "CB #%d: %d/%d/%d " D_TO " %s"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB #%d: %d/%d/%d " D_TO " %s"), i+1, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings.knx_CB_param[i]-1] ); - AddLog(LOG_LEVEL_DEBUG); } } @@ -1028,10 +1010,9 @@ bool KnxCommand(void) knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), device_param_ga[index + KNX_SLOT1 -2], !(XdrvMailbox.payload == 0), KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - AddLog(LOG_LEVEL_INFO); i = KNX_GA_Search(index + KNX_SLOT1 -1, i + 1); } @@ -1057,10 +1038,9 @@ bool KnxCommand(void) knx.write_2byte_float(KNX_addr, tempvar); } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "%s = %s " D_SENT_TO " %d.%d.%d"), + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %s " D_SENT_TO " %d.%d.%d"), device_param_ga[index + KNX_SLOT1 -2], XdrvMailbox.data, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - AddLog(LOG_LEVEL_INFO); i = KNX_GA_Search(index + KNX_SLOT1 -1, i + 1); } diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 08c8679d4..39679b9d9 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -172,10 +172,8 @@ int try_snprintf_P(char *s, size_t n, const char *format, ... ) va_start(args, format); int len = vsnprintf_P(NULL, 0, format, args); if (len >= n) { - snprintf_P(log_data, sizeof(log_data), - PSTR("ERROR: MQTT discovery failed due to too long topic or friendly name. " - "Please shorten topic and friendly name. Failed to format(%u/%u):"), len, n); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("ERROR: MQTT discovery failed due to too long topic or friendly name. " + "Please shorten topic and friendly name. Failed to format(%u/%u):"), len, n); va_start(args, format); vsnprintf_P(log_data, sizeof(log_data), format, args); AddLog(LOG_LEVEL_ERROR); @@ -479,16 +477,14 @@ void HAssAnnounceSensors(void) StaticJsonBuffer<500> jsonBuffer; JsonObject& root = jsonBuffer.parseObject(sensordata); if (!root.success()) { - snprintf_P(log_data, sizeof(log_data), PSTR("HASS: failed to parse '%s'"), sensordata); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: failed to parse '%s'"), sensordata); continue; } for (auto sensor : root) { const char* sensorname = sensor.key; JsonObject& sensors = sensor.value.as(); if (!sensors.success()) { - snprintf_P(log_data, sizeof(log_data), PSTR("HASS: failed to parse '%s'"), sensordata); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: failed to parse '%s'"), sensordata); continue; } for (auto subsensor : sensors) { diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 9ffdf275a..3f779b821 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -746,8 +746,7 @@ void DisplayJsonValue(const char* topic, const char* device, const char* mkey, c } snprintf_P(buffer, sizeof(buffer), PSTR("%s %s"), source, svalue); -// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "mkey [%s], source [%s], value [%s], quantity_code %d, log_buffer [%s]"), mkey, source, value, quantity_code, buffer); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "mkey [%s], source [%s], value [%s], quantity_code %d, log_buffer [%s]"), mkey, source, value, quantity_code, buffer); DisplayLogBufferAdd(buffer); } @@ -777,8 +776,7 @@ void DisplayAnalyzeJson(char *topic, char *json) tempunit = root[D_JSON_TEMPERATURE_UNIT]; if (tempunit) { snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%s"), tempunit); -// snprintf_P(log_data, sizeof(log_data), disp_temp); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, disp_temp); } for (JsonObject::iterator it = root.begin(); it != root.end(); ++it) { @@ -883,8 +881,7 @@ void DisplayInitDriver(void) { XdspCall(FUNC_DISPLAY_INIT_DRIVER); -// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "Display model %d"), Settings.display_model); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Display model %d"), Settings.display_model); if (Settings.display_model) { devices_present++; diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index 14eaf8a07..de91a02b4 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -45,8 +45,7 @@ void PCA9685_Detect(void) if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { if (0x20 == buffer) { pca9685_detected = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "PCA9685", USE_PCA9685_ADDR); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "PCA9685", USE_PCA9685_ADDR); PCA9685_Reset(); // Reset the controller } } @@ -101,7 +100,7 @@ void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted) { pca9685_pin_pwm_value[pin] = pwm; } -bool PCA9685_Command(void) +bool PCA9685_Command(void) { bool serviced = true; bool validpin = false; diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index d2eca8383..53c4984cc 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -123,8 +123,7 @@ bool TuyaSetPower(void) if (source != SRC_SWITCH && TuyaSerial) { // ignore to prevent loop from pushing state from faceplate interaction - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: SetDevicePower.rpower=%d"), rpower); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: SetDevicePower.rpower=%d"), rpower); TuyaSendBool(TUYA_POWER_ID, rpower); @@ -146,16 +145,14 @@ void LightSerialDuty(uint8_t duty) duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself } - snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Serial Packet Dim Value=%d (id=%d)"), duty, Settings.param[P_TUYA_DIMMER_ID]); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR( "TYA: Send Serial Packet Dim Value=%d (id=%d)"), duty, Settings.param[P_TUYA_DIMMER_ID]); TuyaSendValue(Settings.param[P_TUYA_DIMMER_ID], duty); } else { tuya_ignore_dim = false; // reset flag - snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Dim Level skipped due to 0 or already set. Value=%d"), duty); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR( "TYA: Send Dim Level skipped due to 0 or already set. Value=%d"), duty); } } @@ -164,8 +161,7 @@ void TuyaRequestState(void){ if(TuyaSerial) { // Get current status of MCU - snprintf_P(log_data, sizeof(log_data), "TYA: Request MCU state"); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Request MCU state")); TuyaSendCmd(TUYA_CMD_QUERY_STATE); } @@ -197,8 +193,7 @@ void TuyaPacketProcess(void) case TUYA_CMD_STATE: if (tuya_buffer[5] == 5) { // on/off packet - snprintf_P(log_data, sizeof(log_data),PSTR("TYA: RX - %s State"),tuya_buffer[10]?"On":"Off"); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX - %s State"),tuya_buffer[10]?"On":"Off"); if((power || Settings.light_dimmer > 0) && (power != tuya_buffer[10])) { ExecuteCommandPower(1, tuya_buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction @@ -206,12 +201,10 @@ void TuyaPacketProcess(void) } else if (tuya_buffer[5] == 8) { // dim packet - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: RX Dim State=%d"), tuya_buffer[13]); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), tuya_buffer[13]); if (!Settings.param[P_TUYA_DIMMER_ID]) { - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Autoconfiguring Dimmer ID %d"), tuya_buffer[6]); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Autoconfiguring Dimmer ID %d"), tuya_buffer[6]); Settings.param[P_TUYA_DIMMER_ID] = tuya_buffer[6]; } @@ -220,8 +213,7 @@ void TuyaPacketProcess(void) snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), tuya_new_dim ); - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER_STR=%s"), scmnd ); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send CMND_DIMMER_STR=%s"), scmnd ); tuya_ignore_dim = true; ExecuteCommand(scmnd, SRC_SWITCH); @@ -297,8 +289,7 @@ void TuyaInit(void) if (TuyaSerial->begin(9600)) { if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } // Get MCU Configuration - snprintf_P(log_data, sizeof(log_data), "TYA: Request MCU configuration"); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Request MCU configuration")); TuyaSendCmd(TUYA_CMD_MCU_CONF); } @@ -364,8 +355,7 @@ void TuyaSerialInput(void) bool TuyaButtonPressed(void) { if (!XdrvMailbox.index && ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == lastbutton[XdrvMailbox.index]))) { - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Reset GPIO triggered")); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Reset GPIO triggered")); TuyaResetWifi(); return true; // Reset GPIO served here } @@ -387,8 +377,7 @@ void TuyaSetWifiLed(void){ break; } - snprintf_P(log_data, sizeof(log_data), "TYA: Set WiFi LED to state %d (%d)", wifi_state, WifiState()); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Set WiFi LED to state %d (%d)"), wifi_state, WifiState()); TuyaSendCmd(TUYA_CMD_WIFI_STATE, &wifi_state, 1); } diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index 7689f3d1c..4566c44d8 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -49,8 +49,7 @@ void RfReceiveCheck(void) int protocol = mySwitch.getReceivedProtocol(); int delay = mySwitch.getReceivedDelay(); - snprintf_P(log_data, sizeof(log_data), PSTR("RFR: Data %lX (%u), Bits %d, Protocol %d, Delay %d"), data, data, bits, protocol, delay); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFR: Data %lX (%u), Bits %d, Protocol %d, Delay %d"), data, data, bits, protocol, delay); uint32_t now = millis(); if ((now - rf_lasttime > RF_TIME_AVOID_DUPLICATE) && (data > 0)) { diff --git a/sonoff/xdrv_18_armtronix_dimmers.ino b/sonoff/xdrv_18_armtronix_dimmers.ino index a22a5a973..30af12ce7 100644 --- a/sonoff/xdrv_18_armtronix_dimmers.ino +++ b/sonoff/xdrv_18_armtronix_dimmers.ino @@ -58,13 +58,11 @@ void LightSerial2Duty(uint8_t duty1, uint8_t duty2) ArmtronixSerial->print("\nDimmer2:"); ArmtronixSerial->println(duty2); - snprintf_P(log_data, sizeof(log_data), PSTR( "ARM: Send Serial Packet Dim Values=%d,%d"), armtronix_dimState[0],armtronix_dimState[1]); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Serial Packet Dim Values=%d,%d"), armtronix_dimState[0],armtronix_dimState[1]); } else { armtronix_ignore_dim = false; - snprintf_P(log_data, sizeof(log_data), PSTR( "ARM: Send Dim Level skipped due to already set. Value=%d,%d"), armtronix_dimState[0],armtronix_dimState[1]); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Dim Level skipped due to already set. Value=%d,%d"), armtronix_dimState[0],armtronix_dimState[1]); } } @@ -73,8 +71,7 @@ void ArmtronixRequestState(void) { if (ArmtronixSerial) { // Get current status of MCU - snprintf_P(log_data, sizeof(log_data), "TYA: Request MCU state"); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("ARM: Request MCU state")); ArmtronixSerial->println("Status"); } @@ -123,8 +120,7 @@ void ArmtronixSerialInput(void) armtronix_ignore_dim = true; snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "%d %d"),i+1, temp); ExecuteCommand(scmnd,SRC_SWITCH); - snprintf_P(log_data, sizeof(log_data), PSTR("ARM: Send CMND_CHANNEL=%s"), scmnd ); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send CMND_CHANNEL=%s"), scmnd ); } commaIndex = answer.indexOf(',',commaIndex+1); } @@ -152,8 +148,7 @@ void ArmtronixSetWifiLed(void) break; } - snprintf_P(log_data, sizeof(log_data), "ARM: Set WiFi LED to state %d (%d)", wifi_state, WifiState()); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Set WiFi LED to state %d (%d)"), wifi_state, WifiState()); char state = '0' + ((wifi_state & 1) > 0); ArmtronixSerial->print("Setled:"); diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index baa4e5dfa..e4b71bb18 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -67,8 +67,7 @@ void PS16DZSendCommand(char type = 0, uint8_t value = 0) break; } - snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send serial command: %s"), ps16dz_tx_buffer ); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Send serial command: %s"), ps16dz_tx_buffer ); PS16DZSerial->print(ps16dz_tx_buffer); PS16DZSerial->write(0x1B); @@ -109,8 +108,7 @@ void PS16DZSerialDuty(uint8_t duty) } else { ps16dz_ignore_dim = false; // reset flag - snprintf_P(log_data, sizeof(log_data), PSTR( "PSZ: Send Dim Level skipped due to 0 or already set. Value=%d"), duty); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Send Dim Level skipped due to 0 or already set. Value=%d"), duty); } } @@ -165,8 +163,7 @@ void PS16DZSerialInput(void) } else { ps16dz_rx_buffer[ps16dz_byte_counter++] = 0x00; - snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: command received: %s"), ps16dz_rx_buffer); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: command received: %s"), ps16dz_rx_buffer); if(!strncmp(ps16dz_rx_buffer+3, "UPDATE", 6) || !strncmp(ps16dz_rx_buffer+3, "RESULT", 6)) { char *end_str; char *string = ps16dz_rx_buffer+10; @@ -177,22 +174,19 @@ void PS16DZSerialInput(void) char* token3 = strtok_r(NULL, ":", &end_token); if(!strncmp(token2, "\"switch\"", 8)){ bool ps16dz_power = !strncmp(token3, "\"on\"", 4)?true:false; - snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: power received: %s"), token3); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: power received: %s"), token3); if((power || Settings.light_dimmer > 0) && (power !=ps16dz_power)) { ExecuteCommandPower(1, ps16dz_power, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction } } else if(!strncmp(token2, "\"bright\"", 8)){ uint8_t ps16dz_bright = atoi(token3); - snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: brightness received: %d"), ps16dz_bright); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: brightness received: %d"), ps16dz_bright); if(power && ps16dz_bright > 0 && ps16dz_bright != Settings.light_dimmer) { snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), ps16dz_bright ); - snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: Send CMND_DIMMER_STR=%s"), scmnd ); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Send CMND_DIMMER_STR=%s"), scmnd ); ps16dz_ignore_dim = true; ExecuteCommand(scmnd, SRC_SWITCH); @@ -200,15 +194,13 @@ void PS16DZSerialInput(void) } else if(!strncmp(token2, "\"sequence\"", 10)){ //ps16dz_seq = strtoull(token3+1, NULL, 10); - snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: sequence received: %s"), token3); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: sequence received: %s"), token3); } token = strtok_r(NULL, ",", &end_str); } } else if(!strncmp(ps16dz_rx_buffer+3, "SETTING", 7)) { - snprintf_P(log_data, sizeof(log_data), PSTR("PSZ: Reset")); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("PSZ: Reset")); PS16DZResetWifi(); } memset(ps16dz_rx_buffer, 0, PS16DZ_BUFFER_SIZE); diff --git a/sonoff/xdsp_01_lcd.ino b/sonoff/xdsp_01_lcd.ino index 8a37342a3..28d045858 100644 --- a/sonoff/xdsp_01_lcd.ino +++ b/sonoff/xdsp_01_lcd.ino @@ -138,8 +138,7 @@ bool LcdPrintLog(void) strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); DisplayFillScreen(last_row); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); lcd->setCursor(0, last_row); lcd->print(disp_screen_buffer[last_row]); diff --git a/sonoff/xdsp_02_ssd1306.ino b/sonoff/xdsp_02_ssd1306.ino index e7952b65e..9697e4db0 100644 --- a/sonoff/xdsp_02_ssd1306.ino +++ b/sonoff/xdsp_02_ssd1306.ino @@ -154,8 +154,7 @@ void Ssd1306PrintLog(void) strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); DisplayFillScreen(last_row); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); oled->println(disp_screen_buffer[last_row]); oled->display(); diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index 8af7c50c2..b63a6675e 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -94,8 +94,7 @@ void MatrixScrollLeft(char* txt, int loop) // Horiz. position of text -- starts off right edge mtx_x = 8 * mtx_matrices; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), txt); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), txt); disp_refresh = Settings.display_refresh; case 2: @@ -261,8 +260,7 @@ void MatrixPrintLog(uint8_t direction) i++; } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "[%s]"), mtx_buffer); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), mtx_buffer); mtx_done = 1; } diff --git a/sonoff/xdsp_04_ili9341.ino b/sonoff/xdsp_04_ili9341.ino index 6b6511c62..f50164e59 100644 --- a/sonoff/xdsp_04_ili9341.ino +++ b/sonoff/xdsp_04_ili9341.ino @@ -178,8 +178,7 @@ void Ili9341PrintLog(void) DisplayFillScreen(last_row); tft->print(disp_screen_buffer[last_row]); } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "[%s]"), txt); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); } } } diff --git a/sonoff/xdsp_05_epaper_29.ino b/sonoff/xdsp_05_epaper_29.ino index 50495a1db..6f4034ece 100644 --- a/sonoff/xdsp_05_epaper_29.ino +++ b/sonoff/xdsp_05_epaper_29.ino @@ -123,16 +123,14 @@ void EpdInitDriver(void) epd.sclk_pin = pin[GPIO_SPI_CLK]; // 14 epd.mosi_pin = pin[GPIO_SPI_MOSI]; // 13 EpdInitMode(); - snprintf_P(log_data, sizeof(log_data), PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"), epd.cs_pin, epd.sclk_pin, epd.mosi_pin); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"), epd.cs_pin, epd.sclk_pin, epd.mosi_pin); } else if ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_MOSI] < 99)) { epd.cs_pin = pin[GPIO_SSPI_CS]; epd.sclk_pin = pin[GPIO_SSPI_SCLK]; epd.mosi_pin = pin[GPIO_SSPI_MOSI]; EpdInitMode(); - snprintf_P(log_data, sizeof(log_data), PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"), epd.cs_pin, epd.sclk_pin, epd.mosi_pin); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"), epd.cs_pin, epd.sclk_pin, epd.mosi_pin); } } } @@ -221,8 +219,7 @@ void EpdPrintLog(void) EpdDrawStringAt(0, epd_scroll, disp_screen_buffer[last_row], COLORED, 0); // EpdDisplayFrame(); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "[%s]"), txt); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); } } } diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index 778b49b36..14c00d911 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -152,9 +152,8 @@ void HlwEvery200ms(void) } } unsigned long median = hlw_debug[(hlw_cf1_pulse_counter +1) / 2]; - snprintf_P(log_data, sizeof(log_data), PSTR("NRG: power %d, ui %d, cnt %d, smpl%s, sum %d, mean %d, median %d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: power %d, ui %d, cnt %d, smpl%s, sum %d, mean %d, median %d"), hlw_cf_power_pulse_length, hlw_select_ui_flag, hlw_cf1_pulse_counter, stemp, hlw_cf1_summed_pulse_length, cf1_pulse_length, median); - AddLog(LOG_LEVEL_DEBUG); #endif if (hlw_select_ui_flag == hlw_ui_flag) { diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index 375b2e2cc..b4ecea288 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -49,8 +49,7 @@ void PzemAcEverySecond(void) AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); if (error) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PzemAc response error %d"), error); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "PzemAc response error %d"), error); } else { // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // 01 04 14 08 D1 00 6C 00 00 00 F4 00 00 00 26 00 00 01 F4 00 64 00 00 51 34 diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index 1c3713c8f..2bb2bc4a2 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -49,8 +49,7 @@ void PzemDcEverySecond(void) AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); if (error) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PzemDc response error %d"), error); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "PzemDc response error %d"), error); } else { // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // 01 04 10 05 40 00 0A 00 0D 00 00 00 02 00 00 00 00 00 00 D6 29 diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 163b5abf8..2a7b60b80 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -95,9 +95,8 @@ void WemoRespondToMSearch(int echo_type) } 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 " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"), echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port); - AddLog(LOG_LEVEL_DEBUG); udp_response_mutex = false; } @@ -186,9 +185,8 @@ void HueRespondToMSearch(void) } 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"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"), message, udp_remote_ip.toString().c_str(), udp_remote_port); - AddLog(LOG_LEVEL_DEBUG); udp_response_mutex = false; } @@ -537,8 +535,7 @@ void HandleUpnpSetupHue(void) 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_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API_NOT_IMPLEMENTED " (%s)"), path->c_str()); WSSend(200, CT_JSON, "{}"); } @@ -819,12 +816,10 @@ void HandleHueApi(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); // HTP: Hue API (//lights/1/state) + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API " (%s)"), path->c_str()); // 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); // HTP: Hue POST args ({"on":false}) + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_POST_ARGS " (%s)"), json.c_str()); // HTP: Hue POST args ({"on":false}) } if (path->endsWith("/invalid/")) {} // Just ignore diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index 6fe0cf333..cfa797030 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -36,8 +36,7 @@ void CounterUpdate(uint8_t index) RtcSettings.pulse_counter[index -1]++; } -// snprintf_P(log_data, sizeof(log_data), PSTR("CNTR: Interrupt %d"), index); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CNTR: Interrupt %d"), index); } } diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index 4d881bd01..f4880a308 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -61,8 +61,7 @@ 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_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_TRANSMIT " %s"), data); } void SonoffScInit(void) @@ -78,8 +77,7 @@ void SonoffScSerialInput(char *rcvstat) 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_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_RECEIVED " %s"), rcvstat); if (!strncasecmp_P(rcvstat, PSTR("AT+UPDATE="), 10)) { int8_t i = -1; diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index cdf1be836..521fdeaa8 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -287,8 +287,7 @@ void Ds18x20Init(void) } } } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DSB D_SENSORS_FOUND " %d"), ds18x20_sensors); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSORS_FOUND " %d"), ds18x20_sensors); } void Ds18x20Convert(void) diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index 47993bea9..e6d8d7328 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -125,9 +125,8 @@ bool DhtRead(uint8_t sensor) uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; if (dht_data[4] != checksum) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %02X, %02X, %02X, %02X, %02X =? %02X"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %02X, %02X, %02X, %02X, %02X =? %02X"), dht_data[0], dht_data[1], dht_data[2], dht_data[3], dht_data[4], checksum); - AddLog(LOG_LEVEL_DEBUG); return false; } diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index 2120129de..8ce9657ea 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -224,8 +224,7 @@ void HtuDetect(void) htu_delay_humidity = 23; } GetTextIndexed(htu_types, sizeof(htu_types), index, kHtuTypes); - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, htu_types, htu_address); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, htu_types, htu_address); } } diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index 60e43c09c..9696a9c07 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -482,8 +482,7 @@ void BmpDetect(void) } if (success) { GetTextIndexed(bmp_sensors[bmp_count].bmp_name, sizeof(bmp_sensors[bmp_count].bmp_name), bmp_sensors[bmp_count].bmp_model, kBmpTypes); - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, bmp_sensors[bmp_count].bmp_name, bmp_sensors[bmp_count].bmp_address); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, bmp_sensors[bmp_count].bmp_name, bmp_sensors[bmp_count].bmp_address); bmp_count++; } } diff --git a/sonoff/xsns_10_bh1750.ino b/sonoff/xsns_10_bh1750.ino index 5dd791397..95abc41c5 100644 --- a/sonoff/xsns_10_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -65,8 +65,7 @@ void Bh1750Detect(void) Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE); if (!Wire.endTransmission()) { bh1750_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, bh1750_types, bh1750_address); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, bh1750_types, bh1750_address); break; } } diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index 276b90d9f..c32fc090f 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -31,7 +31,7 @@ Version Date Action Description -------------------------------------------------------------------------------------------- - 1.0.0.3 20181006 fixed - missing "" around the UV Index text + 1.0.0.3 20181006 fixed - missing "" around the UV Index text - thanks to Lisa she had tested it on here mqtt system. -- 1.0.0.2 20180928 tests - same as in version 1.0.0.1 @@ -140,8 +140,7 @@ void Veml6070Detect(void) veml6070_type = 1; uint8_t veml_model = 0; GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes); - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VEML6070", VEML6070_ADDR_L); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "VEML6070", VEML6070_ADDR_L); } } @@ -156,13 +155,11 @@ void Veml6070UvTableInit(void) uv_risk_map[i] = ( (USE_VEML6070_RSET / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); } else { uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "VEML6070 resistor error %d"), USE_VEML6070_RSET); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor error %d"), USE_VEML6070_RSET); } #else uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "VEML6070 resistor default used %d"), VEML6070_RSET_DEFAULT); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor default used %d"), VEML6070_RSET_DEFAULT); #endif } } @@ -196,8 +193,7 @@ void Veml6070ModeCmd(bool mode_cmd) uint8_t status = Wire.endTransmission(); // action on status if (!status) { - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VEML6070 mode_cmd", VEML6070_ADDR_L); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "VEML6070 mode_cmd", VEML6070_ADDR_L); } } @@ -241,8 +237,7 @@ double Veml6070UvRiskLevel(uint16_t uv_level) // out of range and much to high - it must be outerspace or sensor damaged snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); return ( risk = 99 ); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "VEML6070 out of range %d"), risk); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 out of range %d"), risk); } } diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index 51cbb6c43..a8f0d8531 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -164,13 +164,12 @@ void Ads1115Detect(void) for (uint8_t i = 0; i < sizeof(ads1115_addresses); i++) { if (!ads1115_found[i]) { ads1115_address = ads1115_addresses[i]; - if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT) && + if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT) && I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONFIG)) { Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); ads1115_type = 1; ads1115_found[i] = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); } } } @@ -182,8 +181,7 @@ void Ads1115GetValues(uint8_t address) ads1115_address = address; for (uint8_t i = 0; i < 4; i++) { ads1115_values[i] = Ads1115GetConversion(i); - //snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x (%i) = %i", address, i, ads1115_values[i] ); - //AddLog(LOG_LEVEL_INFO); + //AddLog_P2(LOG_LEVEL_INFO, "Logging ADS1115 %02x (%i) = %i", address, i, ads1115_values[i] ); } ads1115_address = old_address; } @@ -220,8 +218,7 @@ void Ads1115Show(bool json) char *comma = (char*)""; for (uint8_t t = 0; t < sizeof(ads1115_addresses); t++) { - //snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x", ads1115_addresses[t]); - //AddLog(LOG_LEVEL_INFO); + //AddLog_P2(LOG_LEVEL_INFO, "Logging ADS1115 %02x", ads1115_addresses[t]); if (ads1115_found[t]) { Ads1115GetValues(ads1115_addresses[t]); if (json) { diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/sonoff/xsns_12_ads1115_i2cdev.ino index 2e0bd0ab7..f73581ec0 100644 --- a/sonoff/xsns_12_ads1115_i2cdev.ino +++ b/sonoff/xsns_12_ads1115_i2cdev.ino @@ -90,8 +90,7 @@ void Ads1115Detect(void) adc0.setRate(ADS1115_RATE_860); adc0.setMode(ADS1115_MODE_CONTINUOUS); ads1115_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); break; } } diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index 6b25e8bac..dcf93867b 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -198,8 +198,7 @@ void Ina219Detect(void) ina219_address = ina219_addresses[i]; if (Ina219SetCalibration(Settings.ina219_mode)) { ina219_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, ina219_types, ina219_address); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, ina219_types, ina219_address); break; } } diff --git a/sonoff/xsns_14_sht3x.ino b/sonoff/xsns_14_sht3x.ino index 531e93ceb..fcb7f4a22 100755 --- a/sonoff/xsns_14_sht3x.ino +++ b/sonoff/xsns_14_sht3x.ino @@ -86,8 +86,7 @@ void Sht3xDetect(void) if (Sht3xRead(t, h, sht3x_addresses[i])) { sht3x_sensors[sht3x_count].address = sht3x_addresses[i]; GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), i, kShtTypes); - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, sht3x_sensors[sht3x_count].types, sht3x_sensors[sht3x_count].address); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, sht3x_sensors[sht3x_count].types, sht3x_sensors[sht3x_count].address); sht3x_count++; } } diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 8558a9cd9..019a4dc6f 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -123,8 +123,7 @@ size_t MhzSendCmd(uint8_t command_id) memcpy_P(&mhz_send[6], kMhzCommands[command_id] + sizeof(uint16_t), sizeof(uint16_t)); mhz_send[8] = MhzCalculateChecksum(mhz_send); -// snprintf_P(log_data, sizeof(log_data), PSTR("Final MhzCommand: %x %x %x %x %x %x %x %x %x"),mhz_send[0],mhz_send[1],mhz_send[2],mhz_send[3],mhz_send[4],mhz_send[5],mhz_send[6],mhz_send[7],mhz_send[8]); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Final MhzCommand: %x %x %x %x %x %x %x %x %x"),mhz_send[0],mhz_send[1],mhz_send[2],mhz_send[3],mhz_send[4],mhz_send[5],mhz_send[6],mhz_send[7],mhz_send[8]); return MhzSerial->write(mhz_send, sizeof(mhz_send)); } diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index ab923f2e8..688cdf419 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -71,8 +71,7 @@ void Tsl2561Detect(void) if (!Tsl.id(id)) return; if (Tsl.on()) { tsl2561_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, tsl2561_types, Tsl.address(), id); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, tsl2561_types, Tsl.address(), id); } } } diff --git a/sonoff/xsns_17_senseair.ino b/sonoff/xsns_17_senseair.ino index 4758b454b..461b41145 100644 --- a/sonoff/xsns_17_senseair.ino +++ b/sonoff/xsns_17_senseair.ino @@ -70,19 +70,16 @@ void Senseair250ms(void) // Every 250 mSec if (data_ready) { uint8_t error = SenseairModbus->Receive16BitRegister(&value); if (error) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "SenseAir response error %d"), error); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir response error %d"), error); } else { switch(senseair_read_state) { case 0: // 0x1A (26) READ_TYPE_LOW - S8: fe 04 02 01 77 ec 92 senseair_type = 2; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "SenseAir type id low %04X"), value); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir type id low %04X"), value); break; case 1: // 0x00 (0) READ_ERRORLOG - fe 04 02 00 00 ad 24 if (value) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "SenseAir error %04X"), value); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir error %04X"), value); } break; case 2: // 0x03 (3) READ_CO2 - fe 04 02 06 2c af 59 @@ -98,13 +95,11 @@ void Senseair250ms(void) // Every 250 mSec case 5: // 0x1C (28) READ_RELAY_STATE - S8: fe 04 02 01 54 ad 4b - firmware version { bool relay_state = value >> 8 & 1; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "SenseAir relay state %d"), relay_state); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir relay state %d"), relay_state); break; } case 6: // 0x0A (10) READ_TEMP_ADJUSTMENT - S8: fe 84 02 f2 f1 - Illegal Data Address - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "SenseAir temp adjustment %d"), value); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir temp adjustment %d"), value); break; } } diff --git a/sonoff/xsns_19_mgs.ino b/sonoff/xsns_19_mgs.ino index 13ab99bd6..dacd1430e 100644 --- a/sonoff/xsns_19_mgs.ino +++ b/sonoff/xsns_19_mgs.ino @@ -42,8 +42,7 @@ bool MGSPrepare(void) { gas.begin(MGS_SENSOR_ADDR); if (!gas.isError()) { - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "MultiGasSensor", MGS_SENSOR_ADDR); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "MultiGasSensor", MGS_SENSOR_ADDR); return true; } else { return false; diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 72843f169..d40301508 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -82,10 +82,9 @@ bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensor for (uint8_t i = 2; i < 17; i++) { novasds_cmnd[17] += novasds_cmnd[i]; } - //~ snprintf_P(log_data, sizeof(log_data), PSTR("SDS: Send %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X"), + //~ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDS: Send %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X"), //~ novasds_cmnd[0],novasds_cmnd[1],novasds_cmnd[2],novasds_cmnd[3],novasds_cmnd[4],novasds_cmnd[5],novasds_cmnd[6],novasds_cmnd[7],novasds_cmnd[8],novasds_cmnd[9], //~ novasds_cmnd[10],novasds_cmnd[11],novasds_cmnd[12],novasds_cmnd[13],novasds_cmnd[14],novasds_cmnd[15],novasds_cmnd[16],novasds_cmnd[17],novasds_cmnd[18]); - //~ AddLog(LOG_LEVEL_DEBUG); // send cmnd NovaSdsSerial->write(novasds_cmnd, sizeof(novasds_cmnd)); NovaSdsSerial->flush(); diff --git a/sonoff/xsns_21_sgp30.ino b/sonoff/xsns_21_sgp30.ino index 2f7bf4673..48fde6793 100644 --- a/sonoff/xsns_21_sgp30.ino +++ b/sonoff/xsns_21_sgp30.ino @@ -44,10 +44,8 @@ void Sgp30Update(void) // Perform every second to ensure proper operation of th if (!sgp30_type) { if (sgp.begin()) { sgp30_type = 1; -// snprintf_P(log_data, sizeof(log_data), PSTR("SGP: Serialnumber 0x%04X-0x%04X-0x%04X"), sgp.serialnumber[0], sgp.serialnumber[1], sgp.serialnumber[2]); -// AddLog(LOG_LEVEL_DEBUG); - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "SGP30", 0x58); - AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SGP: Serialnumber 0x%04X-0x%04X-0x%04X"), sgp.serialnumber[0], sgp.serialnumber[1], sgp.serialnumber[2]); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "SGP30", 0x58); } } else { if (!sgp.IAQmeasure()) return; // Measurement failed @@ -59,8 +57,7 @@ void Sgp30Update(void) // Perform every second to ensure proper operation of th uint16_t eCO2_base; if (!sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) return; // Failed to get baseline readings -// snprintf_P(log_data, sizeof(log_data), PSTR("SGP: Baseline values eCO2 0x%04X, TVOC 0x%04X"), eCO2_base, TVOC_base); -// AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SGP: Baseline values eCO2 0x%04X, TVOC 0x%04X"), eCO2_base, TVOC_base); } sgp30_ready = 1; } diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino index ec4891183..67971845a 100644 --- a/sonoff/xsns_23_sdm120.ino +++ b/sonoff/xsns_23_sdm120.ino @@ -165,8 +165,7 @@ void SDM120250ms(void) // Every 250 mSec if (data_ready) { uint8_t error = SDM120_ModbusReceive(&value); if (error) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "SDM120 response error %d"), error); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM120 response error %d"), error); } else { switch(sdm120_read_state) { case 0: diff --git a/sonoff/xsns_24_si1145.ino b/sonoff/xsns_24_si1145.ino index 85f2297aa..19855bf42 100644 --- a/sonoff/xsns_24_si1145.ino +++ b/sonoff/xsns_24_si1145.ino @@ -310,8 +310,7 @@ void Si1145Update(void) if (!si1145_type) { if (Si1145Begin()) { si1145_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "SI1145", SI114X_ADDR); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "SI1145", SI114X_ADDR); } } } diff --git a/sonoff/xsns_25_sdm630.ino b/sonoff/xsns_25_sdm630.ino index 41f83ec93..2f8e0acd8 100644 --- a/sonoff/xsns_25_sdm630.ino +++ b/sonoff/xsns_25_sdm630.ino @@ -155,8 +155,7 @@ void SDM630250ms(void) // Every 250 mSec if (data_ready) { uint8_t error = SDM630_ModbusReceive(&value); if (error) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "SDM630 response error %d"), error); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM630 response error %d"), error); } else { switch(sdm630_read_state) { case 0: diff --git a/sonoff/xsns_26_lm75ad.ino b/sonoff/xsns_26_lm75ad.ino index 31aba77b8..8a48327bf 100644 --- a/sonoff/xsns_26_lm75ad.ino +++ b/sonoff/xsns_26_lm75ad.ino @@ -58,8 +58,7 @@ void LM75ADDetect(void) if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) { if (buffer == 0x4B00) { lm75ad_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "LM75AD", lm75ad_address); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "LM75AD", lm75ad_address); break; } } diff --git a/sonoff/xsns_27_apds9960.ino b/sonoff/xsns_27_apds9960.ino index 90978db7f..ac1b7a947 100644 --- a/sonoff/xsns_27_apds9960.ino +++ b/sonoff/xsns_27_apds9960.ino @@ -1518,8 +1518,7 @@ int16_t readGesture(void) if (gesture_loop_counter == APDS9960_MAX_GESTURE_CYCLES){ // We will escape after a few loops disableGestureSensor(); // stop the sensor to prevent problems with power consumption/blocking and return to the main loop APDS9960_overload = true; // we report this as "long"-gesture - snprintf_P(log_data, sizeof(log_data), PSTR("Sensor overload")); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("Sensor overload")); } gesture_loop_counter += 1; /* Wait some time to collect next batch of FIFO data */ @@ -1794,33 +1793,32 @@ void handleGesture(void) { if (isGestureAvailable() ) { switch (readGesture()) { case DIR_UP: - snprintf_P(log_data, sizeof(log_data), PSTR("UP")); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("UP")); snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Up")); break; case DIR_DOWN: - snprintf_P(log_data, sizeof(log_data), PSTR("DOWN")); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("DOWN")); snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Down")); break; case DIR_LEFT: - snprintf_P(log_data, sizeof(log_data), PSTR("LEFT")); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("LEFT")); snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Left")); break; case DIR_RIGHT: - snprintf_P(log_data, sizeof(log_data), PSTR("RIGHT")); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("RIGHT")); snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Right")); break; default: if(APDS9960_overload) { - snprintf_P(log_data, sizeof(log_data), PSTR("LONG")); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("LONG")); snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Long")); } else{ - snprintf_P(log_data, sizeof(log_data), PSTR("NONE")); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("NONE")); snprintf_P(currentGesture, sizeof(currentGesture), PSTR("None")); } } - AddLog(LOG_LEVEL_DEBUG); mqtt_data[0] = '\0'; if (MqttShowSensor()) { @@ -1908,8 +1906,7 @@ bool APDS9960_detect(void) if (APDS9960type == APDS9960_CHIPID_1 || APDS9960type == APDS9960_CHIPID_2) { strcpy_P(APDS9960stype, PSTR("APDS9960")); - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, APDS9960stype, APDS9960_I2C_ADDR); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, APDS9960stype, APDS9960_I2C_ADDR); if (APDS9960_init()) { success = true; AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "APDS9960 initialized")); @@ -1919,12 +1916,10 @@ bool APDS9960_detect(void) } else { if (APDS9960type == APDS9930_CHIPID_1 || APDS9960type == APDS9930_CHIPID_2) { - snprintf_P(log_data, sizeof(log_data), PSTR("APDS9930 found at address 0x%x, unsupported chip"), APDS9960_I2C_ADDR); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("APDS9930 found at address 0x%x, unsupported chip"), APDS9960_I2C_ADDR); } else{ - snprintf_P(log_data, sizeof(log_data), PSTR("APDS9960 not found at address 0x%x"), APDS9960_I2C_ADDR); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("APDS9960 not found at address 0x%x"), APDS9960_I2C_ADDR); } } currentGesture[0] = '\0'; diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 559b3e809..b72afb66a 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -81,7 +81,7 @@ void MCP230xx_CheckForIntCounter(void) { } } } - + void MCP230xx_CheckForIntRetainer(void) { uint8_t en = 0; for (uint8_t ca=0;ca<16;ca++) { @@ -210,15 +210,13 @@ void MCP230xx_Detect(void) if (I2cValidRead8(&buffer, USE_MCP230xx_ADDR, MCP230xx_IOCON)) { if (0x00 == buffer) { mcp230xx_type = 1; // We have a MCP23008 - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "MCP23008", USE_MCP230xx_ADDR); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "MCP23008", USE_MCP230xx_ADDR); mcp230xx_pincount = 8; MCP230xx_ApplySettings(); } else { if (0x80 == buffer) { mcp230xx_type = 2; // We have a MCP23017 - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "MCP23017", USE_MCP230xx_ADDR); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "MCP23017", USE_MCP230xx_ADDR); mcp230xx_pincount = 16; // Reset bank mode to 0 I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_IOCON, 0x00); @@ -498,8 +496,7 @@ bool MCP230xx_Command(void) { if (Settings.mcp230xx_config[pin].int_count_en) { Settings.mcp230xx_config[pin].int_count_en=0; MCP230xx_CheckForIntCounter(); - snprintf_P(log_data, sizeof(log_data), PSTR("*** WARNING *** - Disabled INTCNT for pin D%i"),pin); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTCNT for pin D%i"),pin); } snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; @@ -537,17 +534,14 @@ bool MCP230xx_Command(void) { Settings.mcp230xx_config[pin].int_count_en=intcnt; if (Settings.mcp230xx_config[pin].int_report_defer) { Settings.mcp230xx_config[pin].int_report_defer=0; - snprintf_P(log_data, sizeof(log_data), PSTR("*** WARNING *** - Disabled INTDEF for pin D%i"),pin); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTDEF for pin D%i"),pin); } if (Settings.mcp230xx_config[pin].int_report_mode < 3) { Settings.mcp230xx_config[pin].int_report_mode=3; - snprintf_P(log_data, sizeof(log_data), PSTR("*** WARNING *** - Disabled immediate interrupt/telemetry reporting for pin D%i"),pin); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled immediate interrupt/telemetry reporting for pin D%i"),pin); } if ((Settings.mcp230xx_config[pin].int_count_en) && (!Settings.mcp230xx_int_timer)) { - snprintf_P(log_data, sizeof(log_data), PSTR("*** WARNING *** - INTCNT enabled for pin D%i but global INTTIMER is disabled!"),pin); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - INTCNT enabled for pin D%i but global INTTIMER is disabled!"),pin); } MCP230xx_CheckForIntCounter(); // update register on whether or not we should be counting interrupts snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; @@ -605,7 +599,7 @@ bool MCP230xx_Command(void) { } uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); - + if (pin < mcp230xx_pincount) { if (0 == pin) { if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1), "0")) validpin=true; @@ -767,7 +761,7 @@ void MCP230xx_Interrupt_Retain_Report(void) { uint16_t retainresult = 0; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP_INTRETAIN\": {"), GetDateAndTime(DT_LOCAL).c_str()); for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].int_retain_flag) { + if (Settings.mcp230xx_config[pinx].int_retain_flag) { snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"D%i\":%i,"),mqtt_data,pinx,mcp230xx_int_retainer[pinx]); retainresult |= (((mcp230xx_int_retainer[pinx])&1) << pinx); mcp230xx_int_retainer[pinx]=0; diff --git a/sonoff/xsns_30_mpr121.ino b/sonoff/xsns_30_mpr121.ino index e9dbfad4f..01431faa6 100644 --- a/sonoff/xsns_30_mpr121.ino +++ b/sonoff/xsns_30_mpr121.ino @@ -220,8 +220,7 @@ void Mpr121Init(struct mpr121 *pS) if (pS->connected[i]) { // Log sensor found - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "MPR121(%c) " D_FOUND_AT " 0x%X"), pS->id[i], pS->i2c_addr[i]); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "MPR121(%c) " D_FOUND_AT " 0x%X"), pS->id[i], pS->i2c_addr[i]); // Set thresholds for registers 0x41 - 0x5A (ExTTH and ExRTH) for (uint8_t j = 0; j < 13; j++) { @@ -283,12 +282,9 @@ void Mpr121Init(struct mpr121 *pS) // Check if sensor is running pS->running[i] = (0x00 != I2cRead8(pS->i2c_addr[i], MPR121_ECR_REG)); - if (pS->running[i]) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "MPR121%c: Running"), pS->id[i]); - } else { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "MPR121%c: NOT Running"), pS->id[i]); - } - AddLog(LOG_LEVEL_INFO); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "MPR121%c: %sRunning"), pS->id[i], (pS->running[i]) ? "" : "NOT"); + } else { // Make sure running is false @@ -299,8 +295,7 @@ void Mpr121Init(struct mpr121 *pS) // Display no sensor found message if (!(pS->connected[0] || pS->connected[1] || pS->connected[2] || pS->connected[3])) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "MPR121: No sensors found")); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C "MPR121: No sensors found")); } } // void Mpr121Init(struct mpr121 *s) @@ -329,8 +324,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) // Read data if (!I2cValidRead16LE(&pS->current[i], pS->i2c_addr[i], MPR121_ELEX_REG)) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "MPR121%c: ERROR: Cannot read data!"), pS->id[i]); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Cannot read data!"), pS->id[i]); Mpr121Init(pS); return; } @@ -339,9 +333,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) // Clear OVCF bit I2cWrite8(pS->i2c_addr[i], MPR121_ELEX_REG, 0x00); - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_I2C "MPR121%c: ERROR: Excess current detected! Fix circuits if it happens repeatedly! Soft-resetting MPR121 ..."), pS->id[i]); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Excess current detected! Fix circuits if it happens repeatedly! Soft-resetting MPR121 ..."), pS->id[i]); Mpr121Init(pS); return; } diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index 75dca5451..173cbe388 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -52,11 +52,9 @@ void CCS811Update(void) // Perform every n second sint8_t res = ccs.begin(CCS811_ADDRESS); if (!res) { CCS811_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "CCS811", 0x5A); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "CCS811", 0x5A); } else { - //snprintf_P(log_data, sizeof(log_data), "CCS811 init failed: %d",res); - //AddLog(LOG_LEVEL_DEBUG); + //AddLog_P2(LOG_LEVEL_DEBUG, "CCS811 init failed: %d",res); } } else { if (ccs.available()) { diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index 9556c5fe4..61156f9c1 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -134,12 +134,12 @@ void MPU_6050Detect(void) mpu6050.setXGyroOffset(220); mpu6050.setYGyroOffset(76); mpu6050.setZGyroOffset(-85); - mpu6050.setZAccelOffset(1788); + mpu6050.setZAccelOffset(1788); if (MPU6050_dmp.devStatus == 0) { mpu6050.setDMPEnabled(true); MPU6050_dmp.packetSize = mpu6050.dmpGetFIFOPacketSize(); MPU_6050_found = true; - } + } #else mpu6050.initialize(); MPU_6050_found = mpu6050.testConnection(); @@ -150,8 +150,7 @@ void MPU_6050Detect(void) if (MPU_6050_found) { - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, D_SENSOR_MPU6050, MPU_6050_address); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, D_SENSOR_MPU6050, MPU_6050_address); } } diff --git a/sonoff/xsns_33_ds3231.ino b/sonoff/xsns_33_ds3231.ino index 2e4586489..98afa0ab0 100644 --- a/sonoff/xsns_33_ds3231.ino +++ b/sonoff/xsns_33_ds3231.ino @@ -73,12 +73,11 @@ void DS3231Detect(void) { DS3231chipDetected = false; if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) { - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "DS3231", USE_RTC_ADDR); + AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, "DS3231", USE_RTC_ADDR); DS3231chipDetected = true; } else { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s *NOT* " D_FOUND_AT " 0x%x"), "DS3231", USE_RTC_ADDR); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "DS3231 NOT " D_FOUND_AT " 0x%x"), USE_RTC_ADDR); } - AddLog(LOG_LEVEL_INFO); } /*----------------------------------------------------------------------* @@ -155,9 +154,8 @@ bool Xsns33(uint8_t function) RtcTime.year = tmpTime.year + 1970; daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); - snprintf_P(log_data, sizeof(log_data), PSTR("Set time from DS3231 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + AddLog_P2(LOG_LEVEL_INFO, PSTR("Set time from DS3231 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - AddLog(LOG_LEVEL_INFO); if (local_time < 1451602800) { // 2016-01-01 rules_flag.time_init = 1; } else { @@ -165,9 +163,8 @@ bool Xsns33(uint8_t function) } } else if (!ds3231WriteStatus && DS3231chipDetected && utc_time > 1451602800 && abs(utc_time - ReadFromDS3231()) > 60) {//if time is valid and is drift from RTC in more that 60 second - snprintf_P(log_data, sizeof(log_data), PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + AddLog_P2(LOG_LEVEL_INFO, PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - AddLog(LOG_LEVEL_INFO); SetDS3231Time (utc_time); //update the DS3231 time ds3231WriteStatus = true; } diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 2de8b985a..15f9f37db 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -454,9 +454,7 @@ void HxLogUpdates(void) char weigth_item_chr[33]; dtostrfd((float)Settings.weight_item / 10000, 4, weigth_item_chr); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_JSON_WEIGHT_REF " %s, " D_JSON_WEIGHT_ITEM " %s"), - weigth_ref_chr, weigth_item_chr); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_JSON_WEIGHT_REF " %s, " D_JSON_WEIGHT_ITEM " %s"), weigth_ref_chr, weigth_item_chr); } #endif // USE_HX711_GUI diff --git a/sonoff/xsns_36_mgc3130.ino b/sonoff/xsns_36_mgc3130.ino index 760330a8a..20df0a223 100644 --- a/sonoff/xsns_36_mgc3130.ino +++ b/sonoff/xsns_36_mgc3130.ino @@ -501,13 +501,11 @@ bool MGC3130_detect(void) success = MGC3130_receiveMessage(); // This should read the firmware info if (success) { strcpy_P(MGC3130stype, PSTR("MGC3130")); - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, MGC3130stype, MGC3130_I2C_ADDR); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, MGC3130stype, MGC3130_I2C_ADDR); MGC3130_currentGesture[0] = '\0'; MGC3130_type = true; } else { - snprintf_P(log_data, sizeof(log_data), PSTR("MGC3130 did not respond at address 0x%x"), MGC3130_I2C_ADDR); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MGC3130 did not respond at address 0x%x"), MGC3130_I2C_ADDR); } return success; } diff --git a/sonoff/xsns_37_rfsensor.ino b/sonoff/xsns_37_rfsensor.ino index 66a7688ce..efb6ded06 100644 --- a/sonoff/xsns_37_rfsensor.ino +++ b/sonoff/xsns_37_rfsensor.ino @@ -251,9 +251,8 @@ void RfSnsAnalyzeTheov2(void) break; } - snprintf_P(log_data, sizeof(log_data), PSTR("RFS: TheoV2, ChkCalc %d, Chksum %d, id %d, Type %d, Ch %d, Volt %d, BattLo %d, Pld1 %d, Pld2 %d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: TheoV2, ChkCalc %d, Chksum %d, id %d, Type %d, Ch %d, Volt %d, BattLo %d, Pld1 %d, Pld2 %d"), chksum, Checksum, id, Type, Channel +1, Payload3, (Voltage & 0x80) >> 7, Payload1, Payload2); - AddLog(LOG_LEVEL_DEBUG); } void RfSnsTheoV2Show(bool json) @@ -507,9 +506,8 @@ void RfSnsAnalyzeAlectov2() rfsns_alecto_v2->wdir = data[8] & 0xf; } - snprintf_P(log_data, sizeof(log_data), PSTR("RFS: " D_ALECTOV2 ", ChkCalc %d, Chksum %d, rc %d, Temp %d, Hum %d, Rain %d, Wind %d, Gust %d, Dir %d, Factor %s"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: " D_ALECTOV2 ", ChkCalc %d, Chksum %d, rc %d, Temp %d, Hum %d, Rain %d, Wind %d, Gust %d, Dir %d, Factor %s"), checksumcalc, checksum, rc, ((data[1] & 0x3) * 256 + data[2]) - 400, data[3], (data[6] * 256) + data[7], data[4], data[5], data[8] & 0xf, dtostrfd(factor, 3, buf1)); - AddLog(LOG_LEVEL_DEBUG); } void RfSnsAlectoResetRain(void) @@ -627,8 +625,7 @@ void RfSnsInit(void) void RfSnsAnalyzeRawSignal(void) { - snprintf_P(log_data, sizeof(log_data), PSTR("RFS: Pulses %d"), (int)rfsns_raw_signal->Number); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: Pulses %d"), (int)rfsns_raw_signal->Number); #ifdef USE_THEO_V2 RfSnsAnalyzeTheov2(); diff --git a/sonoff/xsns_40_pn532.ino b/sonoff/xsns_40_pn532.ino index c1daef96e..ea88143e3 100644 --- a/sonoff/xsns_40_pn532.ino +++ b/sonoff/xsns_40_pn532.ino @@ -76,8 +76,7 @@ void PN532_Init(void) PN532_setPassiveActivationRetries(0xFF); PN532_SAMConfig(); pn532_model = 1; - snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC Reader detected (V%u.%u)",(ver>>16) & 0xFF, (ver>>8) & 0xFF); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO,"NFC: PN532 NFC Reader detected (V%u.%u)",(ver>>16) & 0xFF, (ver>>8) & 0xFF); } } } @@ -446,8 +445,7 @@ void PN532_ScanForTag(void) } if (mifareclassic_WriteDataBlock(1, card_data)) { erase_success = true; - snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Erase success"); - AddLog(LOG_LEVEL_INFO); + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase success")); memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string } } @@ -456,8 +454,7 @@ void PN532_ScanForTag(void) memcpy(&card_data,&pn532_newdata,sizeof(card_data)); if (mifareclassic_WriteDataBlock(1, card_data)) { set_success = true; - snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Data write successful"); - AddLog(LOG_LEVEL_INFO); + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string } #else @@ -472,13 +469,11 @@ void PN532_ScanForTag(void) card_data[pn532_newdata_len] = '\0'; // Enforce null termination if (mifareclassic_WriteDataBlock(1, card_data)) { set_success = true; - snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Data write successful"); - AddLog(LOG_LEVEL_INFO); + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string } } else { - snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Data must be alphanumeric"); - AddLog(LOG_LEVEL_INFO); + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data must be alphanumeric")); } #endif // USE_PN532_DATA_RAW } @@ -489,14 +484,12 @@ void PN532_ScanForTag(void) switch (pn532_function) { case 0x01: if (!erase_success) { - snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Erase fail - exiting erase mode"); - AddLog(LOG_LEVEL_INFO); + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase fail - exiting erase mode")); } break; case 0x02: if (!set_success) { - snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Write failed - exiting set mode"); - AddLog(LOG_LEVEL_INFO); + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Write failed - exiting set mode")); } default: break; @@ -550,8 +543,7 @@ bool PN532_Command(void) UpperCase(XdrvMailbox.data,XdrvMailbox.data); if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"E")) { pn532_function = 1; // Block 1 of next card/tag will be reset to 0x00... - snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Next scanned tag data block 1 will be erased"); - AddLog(LOG_LEVEL_INFO); + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be erased")); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"E\"\"}}"), mqtt_data); return serviced; @@ -568,8 +560,7 @@ bool PN532_Command(void) memcpy(&pn532_newdata,&sub_string_tmp,pn532_newdata_len); pn532_newdata[pn532_newdata_len] = 0x00; // Null terminate the string pn532_function = 2; - snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'",pn532_newdata); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'"), pn532_newdata); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"S\"\"}}"), mqtt_data); return serviced; diff --git a/sonoff/xsns_41_max44009.ino b/sonoff/xsns_41_max44009.ino index 25d415222..1cb0e97a7 100644 --- a/sonoff/xsns_41_max44009.ino +++ b/sonoff/xsns_41_max44009.ino @@ -94,8 +94,7 @@ void Max4409Detect(void) Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); if (0 == Wire.endTransmission()) { max44009_found = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, max44009_types, max44009_address); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, max44009_types, max44009_address); break; } } diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index 589e95adb..5e77b0d46 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -305,8 +305,7 @@ bool XsnsCall(uint8_t Function) uint32_t profile_millis = millis() - profile_start_millis; if (profile_millis) { if (FUNC_EVERY_SECOND == Function) { - snprintf_P(log_data, sizeof(log_data), PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), uptime, Function, x, profile_millis); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), uptime, Function, x, profile_millis); } } #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND @@ -323,8 +322,7 @@ bool XsnsCall(uint8_t Function) uint32_t profile_millis = millis() - profile_start_millis; if (profile_millis) { if (FUNC_EVERY_SECOND == Function) { - snprintf_P(log_data, sizeof(log_data), PSTR("PRF: At %08u XsnsCall %d took %u mS"), uptime, Function, profile_millis); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d took %u mS"), uptime, Function, profile_millis); } } #endif // PROFILE_XSNS_EVERY_SECOND From 168b1332e00d35abc5432cf4cb580c9fd7774108 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 8 Mar 2019 16:28:46 +0100 Subject: [PATCH 1130/2222] Fix bad snprintf in format() --- sonoff/sonoff.ino | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 2c9392300..cea40aee3 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -200,12 +200,13 @@ char* Format(char* output, const char* input, int size) if (token != NULL) { digits = atoi(token); if (digits) { + char tmp[size]; if (strchr(token, 'd')) { - snprintf_P(output, size, PSTR("%s%c0%dd"), output, '%', digits); - snprintf_P(output, size, output, ESP.getChipId() & 0x1fff); // %04d - short chip ID in dec, like in hostname + snprintf_P(tmp, size, PSTR("%s%c0%dd"), output, '%', digits); + snprintf(output, size, tmp, ESP.getChipId() & 0x1fff); // %04d - short chip ID in dec, like in hostname } else { - snprintf_P(output, size, PSTR("%s%c0%dX"), output, '%', digits); - snprintf_P(output, size, output, ESP.getChipId()); // %06X - full chip ID in hex + snprintf_P(tmp, size, PSTR("%s%c0%dX"), output, '%', digits); + snprintf_P(output, size, tmp, ESP.getChipId()); // %06X - full chip ID in hex } } else { if (strchr(token, 'd')) { @@ -624,9 +625,9 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) // 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))) { ota_state_flag = 3; - snprintf_P(mqtt_data, sizeof(mqtt_data), "{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}", command, my_version, GetOtaUrl(stemp1, sizeof(stemp1))); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}"), command, my_version, GetOtaUrl(stemp1, sizeof(stemp1))); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), "{\"%s\":\"" D_JSON_ONE_OR_GT "\"}", command, my_version); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_JSON_ONE_OR_GT "\"}"), command, my_version); } } else if (CMND_OTAURL == command_code) { From b72df698a2765fba36828510249ab72bc2dc7377 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 8 Mar 2019 16:38:36 +0100 Subject: [PATCH 1131/2222] Add more information to status sensor --- sonoff/xdrv_12_home_assistant.ino | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index d815eacb2..ee1f7f499 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -202,7 +202,7 @@ void HAssAnnounceRelayLight(void) mqtt_data[0] = '\0'; // Clear retained message - // Clear "other" topic first in case the device has been reconfigured from ligth to switch or vice versa + // Clear "other" topic first in case the device has been reconfigured from light to switch or vice versa snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "RL" : "LI", i); snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), (is_topic_light) ? "switch" : "light", unique_id); @@ -543,11 +543,16 @@ void HAssAnnounceStatusSensor(void) void HAssPublishStatus(void) { snprintf_P(mqtt_data, sizeof(mqtt_data), - PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" - D_JSON_UPTIME "\":\"%s\",\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" - D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_RSSI "\":\"%d\",\"LoadAvg\":%lu}"), - my_version, my_image, ModuleName().c_str(), GetResetReason().c_str(), GetUptime().c_str(), Settings.bootcount, - Settings.save_flag, WiFi.localIP().toString().c_str(), WifiGetRssiAsQuality(WiFi.RSSI()), loop_load_avg); + PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"," + "\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," + "\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"," + "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\"," + "\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_CMND_IPADDRESS "\":\"%s\"," + "\"" D_JSON_RSSI "\":\"%d\",\"LoadAvg\":%lu}"), + my_version, my_image, GetBuildDateAndTime().c_str(), ESP.getSdkVersion(), ModuleName().c_str(), + GetResetReason().c_str(), GetUptime().c_str(), WifiLinkCount(), WifiDowntime().c_str(), + Settings.bootcount, Settings.save_flag, WiFi.localIP().toString().c_str(), + WifiGetRssiAsQuality(WiFi.RSSI()), loop_load_avg); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE)); } From a80aac91f1b9a03ca94db62b30668ebf840365bd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 8 Mar 2019 16:52:37 +0100 Subject: [PATCH 1132/2222] Fix additional characters in fallbacktopic Fix additional characters in fallbacktopic, hostname and mqttclient on core 2.5.0 (#5359, #5417) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_99_debug.ino | 92 +++++++++++++++------------------------- 2 files changed, 35 insertions(+), 58 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 29b4175ac..467ddfdc2 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.4.1.20 20190304 * Changed webserver content handling from single String to small Chunks increasing RAM * Changed logging message handling + * Fix additional characters in fallbacktopic, hostname and mqttclient on core 2.5.0 (#5359, #5417) * * 6.4.1.19 20190222 * Add command SetOption37 for RGBCW color mapping (#5326) diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_99_debug.ino index 113fc7ce4..e9da144b8 100644 --- a/sonoff/xdrv_99_debug.ino +++ b/sonoff/xdrv_99_debug.ino @@ -25,6 +25,8 @@ #endif // USE_DEBUG_DRIVER #endif // DEBUG_THEO +//#define USE_DEBUG_SETTING_NAMES + #ifdef USE_DEBUG_DRIVER /*********************************************************************************************\ * Virtual debugging support - Part1 @@ -148,13 +150,12 @@ void CpuLoadLoop(void) #if defined(F_CPU) && (F_CPU == 160000000L) int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *800) ); CPU_loops = CPU_loops / CPU_load_check; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(160MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(160MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); #else int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *400) ); CPU_loops = CPU_loops / CPU_load_check; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(80MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(80MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); #endif - AddLog(LOG_LEVEL_DEBUG); CPU_last_millis = CPU_last_loop_time; CPU_loops = 0; } @@ -176,12 +177,8 @@ void DebugFreeMem(void) { register uint32_t *sp asm("a1"); -// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d, UnmodifiedStack %d (%s)"), -// ESP.getFreeHeap(), 4 * (sp - g_cont.stack), cont_get_free_stack(&g_cont), XdrvMailbox.data); - - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), - ESP.getFreeHeap(), 4 * (sp - g_cont.stack), XdrvMailbox.data); - AddLog(LOG_LEVEL_DEBUG); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d, UnmodifiedStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_cont.stack), cont_get_free_stack(&g_cont), XdrvMailbox.data); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_cont.stack), XdrvMailbox.data); } #else @@ -198,9 +195,7 @@ void DebugFreeMem(void) { register uint32_t *sp asm("a1"); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), - ESP.getFreeHeap(), 4 * (sp - g_pcont->stack), XdrvMailbox.data); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_pcont->stack), XdrvMailbox.data); } #endif // ARDUINO_ESP8266_RELEASE_2_x_x @@ -233,8 +228,7 @@ void DebugRtcDump(char* parms) 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_P2(LOG_LEVEL_DEBUG, PSTR("Cnfg: Parms %s, Start row %d, rows %d"), parms, srow, mrow); if (0 == mrow) { // Default only 8 lines mrow = 8; @@ -285,8 +279,7 @@ void DebugCfgDump(char* parms) 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_P2(LOG_LEVEL_DEBUG, PSTR("Cnfg: Parms %s, Start row %d, rows %d"), parms, srow, mrow); if (0 == mrow) { // Default only 8 lines mrow = 8; @@ -363,56 +356,38 @@ void DebugCfgPoke(char* parms) uint32_t ndata32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: 0x%0LX (%lu) poked to 0x%0LX (%lu)"), address, data32, data32, ndata32, ndata32); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: 0x%0LX (%lu) poked to 0x%0LX (%lu)"), address, data32, data32, ndata32, ndata32); } +#ifdef USE_DEBUG_SETTING_NAMES void DebugCfgShow(uint8_t more) { uint8_t *SetAddr; SetAddr = (uint8_t *)&Settings; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: Hostname (%d) [%s]"), (uint8_t *)&Settings.hostname - SetAddr, sizeof(Settings.hostname)-1, Settings.hostname); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: SSids (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_ssid - SetAddr, sizeof(Settings.sta_ssid[0])-1, Settings.sta_ssid[0], Settings.sta_ssid[1]); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: Friendlynames (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.friendlyname - SetAddr, sizeof(Settings.friendlyname[0])-1, Settings.friendlyname[0], Settings.friendlyname[1], Settings.friendlyname[2], Settings.friendlyname[3]); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: OTA Url (%d) [%s]"), (uint8_t *)&Settings.ota_url - SetAddr, sizeof(Settings.ota_url)-1, Settings.ota_url); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: StateText (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.state_text - SetAddr, sizeof(Settings.state_text[0])-1, Settings.state_text[0], Settings.state_text[1], Settings.state_text[2], Settings.state_text[3]); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: Syslog Host (%d) [%s]"), (uint8_t *)&Settings.syslog_host - SetAddr, sizeof(Settings.syslog_host)-1, Settings.syslog_host); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: NTP Servers (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.ntp_server - SetAddr, sizeof(Settings.ntp_server[0])-1, Settings.ntp_server[0], Settings.ntp_server[1], Settings.ntp_server[2]); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Host (%d) [%s]"), (uint8_t *)&Settings.mqtt_host - SetAddr, sizeof(Settings.mqtt_host)-1, Settings.mqtt_host); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Client (%d) [%s]"), (uint8_t *)&Settings.mqtt_client - SetAddr, sizeof(Settings.mqtt_client)-1, Settings.mqtt_client); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT User (%d) [%s]"), (uint8_t *)&Settings.mqtt_user - SetAddr, sizeof(Settings.mqtt_user)-1, Settings.mqtt_user); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT FullTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_fulltopic - SetAddr, sizeof(Settings.mqtt_fulltopic)-1, Settings.mqtt_fulltopic); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Topic (%d) [%s]"), (uint8_t *)&Settings.mqtt_topic - SetAddr, sizeof(Settings.mqtt_topic)-1, Settings.mqtt_topic); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT GroupTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_grptopic - SetAddr, sizeof(Settings.mqtt_grptopic)-1, Settings.mqtt_grptopic); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT ButtonTopic (%d) [%s]"), (uint8_t *)&Settings.button_topic - SetAddr, sizeof(Settings.button_topic)-1, Settings.button_topic); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT SwitchTopic (%d) [%s]"), (uint8_t *)&Settings.switch_topic - SetAddr, sizeof(Settings.switch_topic)-1, Settings.switch_topic); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Prefixes (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.mqtt_prefix - SetAddr, sizeof(Settings.mqtt_prefix[0])-1, Settings.mqtt_prefix[0], Settings.mqtt_prefix[1], Settings.mqtt_prefix[2]); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Hostname (%d) [%s]"), (uint8_t *)&Settings.hostname - SetAddr, sizeof(Settings.hostname)-1, Settings.hostname); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: SSids (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_ssid - SetAddr, sizeof(Settings.sta_ssid[0])-1, Settings.sta_ssid[0], Settings.sta_ssid[1]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Friendlynames (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.friendlyname - SetAddr, sizeof(Settings.friendlyname[0])-1, Settings.friendlyname[0], Settings.friendlyname[1], Settings.friendlyname[2], Settings.friendlyname[3]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: OTA Url (%d) [%s]"), (uint8_t *)&Settings.ota_url - SetAddr, sizeof(Settings.ota_url)-1, Settings.ota_url); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: StateText (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.state_text - SetAddr, sizeof(Settings.state_text[0])-1, Settings.state_text[0], Settings.state_text[1], Settings.state_text[2], Settings.state_text[3]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Syslog Host (%d) [%s]"), (uint8_t *)&Settings.syslog_host - SetAddr, sizeof(Settings.syslog_host)-1, Settings.syslog_host); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: NTP Servers (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.ntp_server - SetAddr, sizeof(Settings.ntp_server[0])-1, Settings.ntp_server[0], Settings.ntp_server[1], Settings.ntp_server[2]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Host (%d) [%s]"), (uint8_t *)&Settings.mqtt_host - SetAddr, sizeof(Settings.mqtt_host)-1, Settings.mqtt_host); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Client (%d) [%s]"), (uint8_t *)&Settings.mqtt_client - SetAddr, sizeof(Settings.mqtt_client)-1, Settings.mqtt_client); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT User (%d) [%s]"), (uint8_t *)&Settings.mqtt_user - SetAddr, sizeof(Settings.mqtt_user)-1, Settings.mqtt_user); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT FullTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_fulltopic - SetAddr, sizeof(Settings.mqtt_fulltopic)-1, Settings.mqtt_fulltopic); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Topic (%d) [%s]"), (uint8_t *)&Settings.mqtt_topic - SetAddr, sizeof(Settings.mqtt_topic)-1, Settings.mqtt_topic); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT GroupTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_grptopic - SetAddr, sizeof(Settings.mqtt_grptopic)-1, Settings.mqtt_grptopic); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT ButtonTopic (%d) [%s]"), (uint8_t *)&Settings.button_topic - SetAddr, sizeof(Settings.button_topic)-1, Settings.button_topic); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT SwitchTopic (%d) [%s]"), (uint8_t *)&Settings.switch_topic - SetAddr, sizeof(Settings.switch_topic)-1, Settings.switch_topic); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Prefixes (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.mqtt_prefix - SetAddr, sizeof(Settings.mqtt_prefix[0])-1, Settings.mqtt_prefix[0], Settings.mqtt_prefix[1], Settings.mqtt_prefix[2]); if (17 == more) { - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: AP Passwords (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_pwd - SetAddr, sizeof(Settings.sta_pwd[0])-1, Settings.sta_pwd[0], Settings.sta_pwd[1]); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: MQTT Password (%d) [%s]"), (uint8_t *)&Settings.mqtt_pwd - SetAddr, sizeof(Settings.mqtt_pwd)-1, Settings.mqtt_pwd); - AddLog(LOG_LEVEL_INFO); - snprintf_P(log_data, sizeof(log_data), PSTR("%03X: Web Password (%d) [%s]"), (uint8_t *)&Settings.web_password - SetAddr, sizeof(Settings.web_password)-1, Settings.web_password); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: AP Passwords (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_pwd - SetAddr, sizeof(Settings.sta_pwd[0])-1, Settings.sta_pwd[0], Settings.sta_pwd[1]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Password (%d) [%s]"), (uint8_t *)&Settings.mqtt_pwd - SetAddr, sizeof(Settings.mqtt_pwd)-1, Settings.mqtt_pwd); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Web Password (%d) [%s]"), (uint8_t *)&Settings.web_password - SetAddr, sizeof(Settings.web_password)-1, Settings.web_password); } } +#endif // USE_DEBUG_SETTING_NAMES void SetFlashMode(uint8_t mode) { @@ -443,8 +418,7 @@ bool DebugCommand(void) serviced = false; // Unknown command } else if (CMND_HELP == command_code) { - snprintf_P(log_data, sizeof(log_data), kDebugCommands); - AddLog(LOG_LEVEL_INFO); + AddLog_P(LOG_LEVEL_INFO, kDebugCommands); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } else if (CMND_RTCDUMP == command_code) { @@ -463,10 +437,12 @@ bool DebugCommand(void) DebugCfgPoke(XdrvMailbox.data); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } +#ifdef USE_DEBUG_SETTING_NAMES else if (CMND_CFGSHOW == command_code) { DebugCfgShow(XdrvMailbox.payload); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } +#endif // USE_DEBUG_SETTING_NAMES #ifdef USE_WEBSERVER else if (CMND_CFGXOR == command_code) { if (XdrvMailbox.data_len > 0) { From 0d8545f658c5e258f62d5427a405895858ec21f8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 8 Mar 2019 17:42:21 +0100 Subject: [PATCH 1133/2222] Add command Template 255 Add command Template 255 to copy module configuration over to current active template and store as user template named Merged (#5371) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 467ddfdc2..0bc5eb73e 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Changed webserver content handling from single String to small Chunks increasing RAM * Changed logging message handling * Fix additional characters in fallbacktopic, hostname and mqttclient on core 2.5.0 (#5359, #5417) + * Add command Template 255 to copy module configuration over to current active template and store as user template named Merged (#5371) * * 6.4.1.19 20190222 * Add command SetOption37 for RGBCW color mapping (#5326) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c043dc634..b5110f696 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -203,7 +203,7 @@ char* Format(char* output, const char* input, int size) char tmp[size]; if (strchr(token, 'd')) { snprintf_P(tmp, size, PSTR("%s%c0%dd"), output, '%', digits); - snprintf(output, size, tmp, ESP.getChipId() & 0x1fff); // %04d - short chip ID in dec, like in hostname + snprintf_P(output, size, tmp, ESP.getChipId() & 0x1fff); // %04d - short chip ID in dec, like in hostname } else { snprintf_P(tmp, size, PSTR("%s%c0%dX"), output, '%', digits); snprintf_P(output, size, tmp, ESP.getChipId()); // %06X - full chip ID in hex @@ -958,11 +958,26 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) ModuleDefault(payload -1); // Copy template module if (USER_MODULE == Settings.module) { restart_flag = 2; } } - else if (0 == payload) { // Copy current module with user configured GPIO + else if (0 == payload) { // Copy current template to user template if (Settings.module != USER_MODULE) { ModuleDefault(Settings.module); } } + else if (255 == payload) { // Copy current module with user configured GPIO + if (Settings.module != USER_MODULE) { + ModuleDefault(Settings.module); + } + snprintf_P(Settings.user_template.name, sizeof(Settings.user_template.name), PSTR("Merged")); + uint8_t j = 0; + for (uint8_t i = 0; i < sizeof(mycfgio); i++) { + if (6 == i) { j = 9; } + if (8 == i) { j = 12; } + if (my_module.io[j] > GPIO_NONE) { + Settings.user_template.gp.io[i] = my_module.io[j]; + } + j++; + } + } } else if (data_len > 9) { // Workaround exception if empty JSON like {} - Needs checks if (JsonTemplate(dataBuf)) { // Free 336 bytes StaticJsonBuffer stack space by moving code to function From b87afc3bcb2190c0c2b1b19e79229197e09bc431 Mon Sep 17 00:00:00 2001 From: Laurent Dong Date: Fri, 8 Mar 2019 13:24:02 -0500 Subject: [PATCH 1134/2222] Code review: Copy string with strlcpy() instead of snprintf() Copying string with snprintf() is unsafy and slow because it check and replace plcaehold (%?) --- sonoff/sonoff.ino | 2 +- sonoff/support.ino | 2 +- sonoff/xdrv_02_mqtt.ino | 4 ++-- sonoff/xdrv_08_serial_bridge.ino | 2 +- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_10_rules.ino | 4 ++-- sonoff/xdsp_03_matrix.ino | 2 +- sonoff/xsns_09_bmp.ino | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c043dc634..52308641a 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -229,7 +229,7 @@ char* GetOtaUrl(char *otaurl, size_t otaurl_size) snprintf_P(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId()); } else { - snprintf(otaurl, otaurl_size, Settings.ota_url); + strlcpy(otaurl, Settings.ota_url, otaurl_size); } return otaurl; } diff --git a/sonoff/support.ino b/sonoff/support.ino index 8f1e4c104..fc2a3d853 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -672,7 +672,7 @@ void SerialSendRaw(char *codes) int size = strlen(codes); while (size > 0) { - snprintf(stemp, sizeof(stemp), codes); + strlcpy(stemp, codes, sizeof(stemp)); code = strtol(stemp, &p, 16); Serial.write(code); size -= 2; diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 4df9ca6cb..450ff252b 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -765,10 +765,10 @@ bool MqttCommand(void) if (data_len > 0) { char *mqtt_part = strtok(dataBuf, " "); if (mqtt_part) { - snprintf(stemp1, sizeof(stemp1), mqtt_part); + strlcpy(stemp1, mqtt_part, sizeof(stemp1)); mqtt_part = strtok(NULL, " "); if (mqtt_part) { - snprintf(mqtt_data, sizeof(mqtt_data), mqtt_part); + strlcpy(mqtt_data, mqtt_part, sizeof(mqtt_data)); } else { mqtt_data[0] = '\0'; } diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index ba83f11ec..0db7da58c 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -137,7 +137,7 @@ bool SerialBridgeCommand(void) int size = strlen(XdrvMailbox.data); while (size > 0) { - snprintf(stemp, sizeof(stemp), codes); + strlcpy(stemp, codes, sizeof(stemp)); code = strtol(stemp, &p, 16); SerialBridgeSerial->write(code); // "AA004566" as hex values size -= 2; diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 094fbcd96..e80f5bc01 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -385,7 +385,7 @@ bool TimerCommand(void) uint8_t sign = 0; char time_str[10]; - snprintf(time_str, sizeof(time_str), root[parm_uc]); + strlcpy(time_str, root[parm_uc], sizeof(time_str)); const char *substr = strtok(time_str, ":"); if (substr != NULL) { if (strchr(substr, '-')) { diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 7897a0c17..4422d92b3 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -218,7 +218,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) } #endif // USE_TIMERS and USE_SUNRISE rule_param.toUpperCase(); - snprintf(rule_svalue, sizeof(rule_svalue), rule_param.c_str()); + strlcpy(rule_svalue, rule_param.c_str(), sizeof(rule_svalue)); int temp_value = GetStateNumber(rule_svalue); if (temp_value > -1) { @@ -365,7 +365,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) #endif // USE_TIMERS and USE_SUNRISE char command[commands.length() +1]; - snprintf(command, sizeof(command), commands.c_str()); + strlcpy(command, commands.c_str(), sizeof(command)); AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: %s performs \"%s\""), event_trigger.c_str(), command); diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index b63a6675e..2535c92d9 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -226,7 +226,7 @@ void MatrixOnOff(void) void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) { - snprintf(mtx_buffer, MTX_MAX_SCREEN_BUFFER, str); + strlcpy(mtx_buffer, str, MTX_MAX_SCREEN_BUFFER); mtx_mode = x &1; // Use x for selecting scroll up (0) or scroll left (1) mtx_loop = y &1; // Use y for selecting no loop (0) or loop (1) if (!mtx_state) { mtx_state = 1; } diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index 9696a9c07..488efd7ee 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -539,7 +539,7 @@ void BmpShow(bool json) float bmp_pressure = ConvertPressure(bmp_sensors[bmp_idx].bmp_pressure); char name[10]; - snprintf(name, sizeof(name), bmp_sensors[bmp_idx].bmp_name); + strlcpy(name, bmp_sensors[bmp_idx].bmp_name, sizeof(name)); if (bmp_count > 1) { snprintf_P(name, sizeof(name), PSTR("%s-%02X"), name, bmp_sensors[bmp_idx].bmp_address); // BMXXXX-XX } From ecbe6ac618067f57b9a4b307559a574f027a71fe Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 9 Mar 2019 14:39:48 +0100 Subject: [PATCH 1135/2222] 6.4.1.21 Fix exception on GUI 6.4.1.21 20190309 * Fix exception on GUI Configure Logging and Configure Other (#5424) --- sonoff/_changelog.ino | 5 ++++- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_webserver.ino | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0bc5eb73e..7fcc80b8d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.20 20190304 +/* 6.4.1.21 20190309 + * Fix exception on GUI Configure Logging and Configure Other (#5424) + * + * 6.4.1.20 20190304 * Changed webserver content handling from single String to small Chunks increasing RAM * Changed logging message handling * Fix additional characters in fallbacktopic, hostname and mqttclient on core 2.5.0 (#5359, #5417) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 6dc3c6f38..89c999a90 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040114 +#define VERSION 0x06040115 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index cfb563e92..bf1f96f34 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1368,7 +1368,7 @@ void HandleLoggingConfiguration(void) (i == llevel) ? " selected" : "", i, i, GetTextIndexed(stemp1, sizeof(stemp1), i, kLoggingLevels)); } - WSContentSend(PSTR("

")); + WSContentSend(F("

")); } WSContentSend_P(HTTP_FORM_LOG2, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); WSContentSend(FPSTR(HTTP_FORM_END)); @@ -1436,7 +1436,7 @@ void HandleOtherConfiguration(void) } #ifdef USE_EMULATION - WSContentSend(PSTR("

 " D_EMULATION " 

")); // Keep close to Friendlynames so do not use
+ WSContentSend(F("

 " D_EMULATION " 

")); // Keep close to Friendlynames so do not use
for (uint8_t i = 0; i < EMUL_MAX; i++) { WSContentSend_P(PSTR("%s %s
"), // Different id only used for labels i, i, @@ -1444,7 +1444,7 @@ void HandleOtherConfiguration(void) GetTextIndexed(stemp, sizeof(stemp), i, kEmulationOptions), (i == EMUL_NONE) ? "" : (i == EMUL_WEMO) ? D_SINGLE_DEVICE : D_MULTI_DEVICE); } - WSContentSend(PSTR("

")); + WSContentSend(F("

")); #endif // USE_EMULATION WSContentSend(FPSTR(HTTP_FORM_END)); From 8a43cfb3e6f50d035c3b551231b92667a6ee7c90 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 9 Mar 2019 15:51:16 +0100 Subject: [PATCH 1136/2222] Add headers to status update data Add headers to status update data (#5410) --- sonoff/xdrv_01_webserver.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index bf1f96f34..2dbeeaa0d 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -950,6 +950,7 @@ bool HandleRootStatusRefresh(void) } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s"), mqtt_data); } + WSHeaderSend(); WSSend(200, CT_HTML, mqtt_data); return true; } From bbc63c207767e3e8e5c7fd0a1553fd632e555bac Mon Sep 17 00:00:00 2001 From: Neel Malik Date: Sat, 9 Mar 2019 17:44:42 -0800 Subject: [PATCH 1137/2222] preliminary SCD30 support --- lib/FrogmoreScd30/FrogmoreScd30.cpp | 653 ++++++++++++++++++++++++++++ lib/FrogmoreScd30/FrogmoreScd30.h | 105 +++++ sonoff/i18n.h | 8 +- sonoff/sonoff_post.h | 1 + sonoff/xdrv_92_scd30.ino | 505 +++++++++++++++++++++ 5 files changed, 1270 insertions(+), 2 deletions(-) create mode 100644 lib/FrogmoreScd30/FrogmoreScd30.cpp create mode 100644 lib/FrogmoreScd30/FrogmoreScd30.h create mode 100644 sonoff/xdrv_92_scd30.ino diff --git a/lib/FrogmoreScd30/FrogmoreScd30.cpp b/lib/FrogmoreScd30/FrogmoreScd30.cpp new file mode 100644 index 000000000..32bbee5ba --- /dev/null +++ b/lib/FrogmoreScd30/FrogmoreScd30.cpp @@ -0,0 +1,653 @@ +/* +# Copyright (c) 2019 Frogmore42 +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#include +#include +#include +#include +#include + +#define COMMAND_SCD30_CONTINUOUS_MEASUREMENT 0x0010 +#define COMMAND_SCD30_MEASUREMENT_INTERVAL 0x4600 +#define COMMAND_SCD30_GET_DATA_READY 0x0202 +#define COMMAND_SCD30_READ_MEASUREMENT 0x0300 +#define COMMAND_SCD30_CALIBRATION_TYPE 0x5306 +#define COMMAND_SCD30_FORCED_RECALIBRATION_FACTOR 0x5204 +#define COMMAND_SCD30_TEMPERATURE_OFFSET 0x5403 +#define COMMAND_SCD30_ALTITUDE_COMPENSATION 0x5102 +#define COMMAND_SCD30_SOFT_RESET 0xD304 +#define COMMAND_SCD30_GET_FW_VERSION 0xD100 +#define COMMAND_SCD30_STOP_MEASUREMENT 0x0104 + +#define SCD30_DATA_REGISTER_BYTES 2 +#define SCD30_DATA_REGISTER_WITH_CRC 3 +#define SCD30_MEAS_BYTES 18 + +#ifdef SCD30_DEBUG +enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; +char scd30log_data[180]; +#endif + +void FrogmoreScd30::begin(TwoWire *pWire, uint8_t i2cAddress) +{ + this->i2cAddress = i2cAddress; + if (pWire == NULL) + { + this->pWire = &Wire; + } + else + { + this->pWire = pWire; + } + + co2NewDataLocation = -1; // indicates there is no data, so the 1st data point needs to fill up the median filter + this->pWire->setClockStretchLimit(200000); + this->ambientPressure = 0; +} + +void FrogmoreScd30::begin(uint8_t i2cAddress) +{ + begin(NULL, i2cAddress); +} + +void FrogmoreScd30::begin(TwoWire *pWire) +{ + begin(pWire, SCD30_ADDRESS); +} + +void FrogmoreScd30::begin(void) +{ + begin(NULL, SCD30_ADDRESS); +} + +/*--------------------------------------------------------------------------- + Function : opt_med5() In : pointer to array of 5 values + Out : a uint16_t which is the middle value of the sorted array + Job : optimized search of the median of 5 values + Notice : found on sci.image.processing cannot go faster unless assumptions are made on the nature of the input signal. + ---------------------------------------------------------------------------*/ +#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); } +#define PIX_SWAP(a,b) { uint16_t temp=(a);(a)=(b);(b)=temp; } + +uint16_t opt_med5(uint16_t * p) +{ + PIX_SORT(p[0], p[1]); + PIX_SORT(p[3], p[4]); + PIX_SORT(p[0], p[3]); + PIX_SORT(p[1], p[4]); + PIX_SORT(p[1], p[2]); + PIX_SORT(p[2], p[3]); + PIX_SORT(p[1], p[2]); + return(p[2]); +} + +// twi_status() attempts to read out any data left that is holding SDA low, so a new transaction can take place +// something like (http://www.forward.com.au/pfod/ArduinoProgramming/I2C_ClearBus/index.html) +int FrogmoreScd30::clearI2CBus(void) +{ +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "clearI2CBus"); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + return (twi_status()); +} + +#ifdef SCD30_DEBUG +void FrogmoreScd30::AddLog(uint8_t loglevel) +{ + if (loglevel <= LOG_LEVEL_INFO) + { + Serial.printf("%s\r\n", scd30log_data); + } +} +#endif + +uint8_t FrogmoreScd30::computeCRC8(uint8_t data[], uint8_t len) +// Computes the CRC that the SCD30 uses +{ + uint8_t crc = 0xFF; //Init with 0xFF + + for (uint8_t x = 0 ; x < len ; x++) + { + crc ^= data[x]; // XOR-in the next input byte + for (uint8_t i = 0 ; i < 8 ; i++) + { + if ((crc & 0x80) != 0) + crc = (uint8_t)((crc << 1) ^ 0x31); + else + crc <<= 1; + } + } + + return crc; //No output reflection +} + +// Sends stream of bytes to device +int FrogmoreScd30::sendBytes(void *pInput, uint8_t len) +{ + uint8_t *pBytes = (uint8_t *) pInput; + int result; + uint8_t errorBytes = 0; // number of bytes that had an error in transmission +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30SendBytes: data: 0x %02X %02X %02X | 0x %02X %02X %02X | 0x %02X %02X %02X", pBytes[0], pBytes[1], pBytes[2], pBytes[3], pBytes[4], pBytes[5], pBytes[6], pBytes[7], pBytes[8]); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + pWire->beginTransmission(this->i2cAddress); + errorBytes = len - (pWire->write(pBytes, len)); + result = pWire->endTransmission(); + if (errorBytes || result) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30SendBytes: errorBytes: %d | Wire.end: %d", errorBytes, result); + AddLog(LOG_LEVEL_INFO); +#endif + } + + result <<= 8; // leave room for error bytes number + result |= errorBytes; // low byte has number of bytes that were not written correctly + return (result); +} + +// Gets a number of bytes from device +int FrogmoreScd30::getBytes(void *pOutput, uint8_t len) +{ + uint8_t *pBytes = (uint8_t *) pOutput; + uint8_t result; + + result = pWire->requestFrom(this->i2cAddress, len); + if (len != result) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30GetBytes: wire request expected %d got: %d", len, result); + AddLog(LOG_LEVEL_INFO); +#endif + return (ERROR_SCD30_NOT_ENOUGH_BYTES_ERROR); + } + + if (pWire->available()) + { + for (int x = 0; x < len; x++) + { + pBytes[x] = pWire->read(); + } +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30GetBytes: data: 0x %02X %02X %02X | 0x %02X %02X %02X | 0x %02X %02X %02X", pBytes[0], pBytes[1], pBytes[2], pBytes[3], pBytes[4], pBytes[5], pBytes[6], pBytes[7], pBytes[8]); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + return (ERROR_SCD30_NO_ERROR); + } + + return (ERROR_SCD30_UNKNOWN_ERROR); +} + +//Sends just a command, no arguments, no CRC +int FrogmoreScd30::sendCommand(uint16_t command) +{ + uint8_t data[2]; + data[0] = command >> 8; + data[1] = command & 0xFF; + int error = sendBytes(data, sizeof(data)); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30SendCommand: Scd30SendBytes failed: 0x%lX", error); + AddLog(LOG_LEVEL_INFO); +#endif + } + return (error); +} + +//Sends a command along with arguments and CRC +int FrogmoreScd30::sendCommandArguments(uint16_t command, uint16_t arguments) +{ + uint8_t data[5]; + data[0] = command >> 8; + data[1] = command & 0xFF; + data[2] = arguments >> 8; + data[3] = arguments & 0xFF; + data[4] = computeCRC8(&data[2], 2); //Calc CRC on the arguments only, not the command + int error = sendBytes(data, sizeof(data)); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30SendCommandArguments: Scd30SendBytes failed: 0x%lX", error); + AddLog(LOG_LEVEL_INFO); +#endif + } + return (error); +} + +int FrogmoreScd30::get16BitRegCheckCRC(void* pInput, uint16_t *pData) +{ + uint8_t *pBytes = (uint8_t *) pInput; + uint8_t expectedCRC = computeCRC8(pBytes, SCD30_DATA_REGISTER_BYTES); + if (expectedCRC != pBytes[SCD30_DATA_REGISTER_BYTES]) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30get16BitRegCheckCRC: expected: 0x%02X, but got: 0x%02X", expectedCRC, pBytes[SCD30_DATA_REGISTER_BYTES]); + AddLog(LOG_LEVEL_INFO); + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30get16BitRegCheckCRC: data: 0x%02X, 0x%02X, 0x%02X", pBytes[0], pBytes[1], pBytes[2]); + AddLog(LOG_LEVEL_INFO); +#endif + return (ERROR_SCD30_CRC_ERROR); + } + *pData = (uint16_t) pBytes[0] << 8 | pBytes[1]; // data from SCD30 is Big-Endian + return (ERROR_SCD30_NO_ERROR); +} + +// gets 32 bits, (2) 16-bit chunks, and validates the CRCs +// +int FrogmoreScd30::get32BitRegCheckCRC(void *pInput, float *pData) +{ + uint16_t tempU16High; + uint16_t tempU16Low; + uint8_t *pBytes = (uint8_t *) pInput; + uint32_t rawInt = 0; + + int error = get16BitRegCheckCRC(pBytes, &tempU16High); + if (error) { + return (error); + } + + error = get16BitRegCheckCRC(pBytes + SCD30_DATA_REGISTER_WITH_CRC, &tempU16Low); + if (error) { + return (error); + } + + // data from SCD is Big-Endian + rawInt |= tempU16High; + rawInt <<= 16; + rawInt |= tempU16Low; + + *pData = * (float *) &rawInt; +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "get32BitRegCheckCRC: got: tempUs 0x%lX, %lX", tempU16High, tempU16Low); + AddLog(LOG_LEVEL_DEBUG); +#endif + + if (isnan(*pData) || isinf(*pData)) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "get32BitRegCheckCRC: not a floating point number: rawInt 0x%lX", rawInt); + AddLog(LOG_LEVEL_INFO); +#endif + return (ERROR_SCD30_NOT_A_NUMBER_ERROR); + } + + return (ERROR_SCD30_NO_ERROR); +} + +//Gets two bytes (and check CRC) from SCD30 +int FrogmoreScd30::readRegister(uint16_t registerAddress, uint16_t* pData) +{ + int error = sendCommand(registerAddress); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadRegister: SendCommand error: 0x%lX", error); + AddLog(LOG_LEVEL_INFO); +#endif + return (error); + } + delay(1); // the SCD30 uses clock streching to give it time to prepare data, waiting here makes it work + uint8_t data[SCD30_DATA_REGISTER_WITH_CRC]; + error = getBytes(data, sizeof(data)); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadRegister: Scd30GetBytes error: 0x%lX", error); + AddLog(LOG_LEVEL_INFO); +#endif + return (error); + } + uint16 regValue; + error = get16BitRegCheckCRC(data, ®Value); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadRegister: Scd30get16BitRegCheckCRC error: 0x%lX", error); + AddLog(LOG_LEVEL_INFO); +#endif + return (error); + } + + *pData = regValue; + return (ERROR_SCD30_NO_ERROR); +} + +int FrogmoreScd30::softReset(void) +{ + return (sendCommand(COMMAND_SCD30_SOFT_RESET)); +} + +int FrogmoreScd30::getAltitudeCompensation(uint16_t *pHeight_meter) +{ + return (readRegister(COMMAND_SCD30_ALTITUDE_COMPENSATION, pHeight_meter)); +} + +int FrogmoreScd30::getAmbientPressure(uint16_t *pAirPressure_mbar) +{ + *pAirPressure_mbar = ambientPressure; + return (ERROR_SCD30_NO_ERROR); +} + +int FrogmoreScd30::getCalibrationType(uint16_t *pIsAuto) +{ + uint16_t value = 0; + int error = readRegister(COMMAND_SCD30_CALIBRATION_TYPE, &value); + if (!error) + { + *pIsAuto = value != 0; + } + return (error); +} + +int FrogmoreScd30::getFirmwareVersion(uint8_t *pMajor, uint8_t *pMinor) +{ + uint16_t value; + int error = readRegister(COMMAND_SCD30_GET_FW_VERSION, &value); + if (!error) + { + *pMajor = value >> 8; + *pMinor = value & 0xFF; + } + return (error); +} + +int FrogmoreScd30::getForcedRecalibrationFactor(uint16_t *pCo2_ppm) +{ + return (readRegister(COMMAND_SCD30_FORCED_RECALIBRATION_FACTOR, pCo2_ppm)); +} + +int FrogmoreScd30::getMeasurementInterval(uint16_t *pTime_sec) +{ + return (readRegister(COMMAND_SCD30_MEASUREMENT_INTERVAL, pTime_sec)); +} + +int FrogmoreScd30::getTemperatureOffset(float *pOffset_degC) +{ + uint16_t value; + int error = readRegister(COMMAND_SCD30_TEMPERATURE_OFFSET, &value); + if (!error) + { + // result is in centi-degrees, need to convert to degrees + *pOffset_degC = (float) value / 100.0; + } + return (error); +} + +int FrogmoreScd30::getTemperatureOffset(uint16_t *pOffset_centiDegC) +{ + uint16_t value; + int error = readRegister(COMMAND_SCD30_TEMPERATURE_OFFSET, &value); + if (!error) + { + // result is in centi-degrees, need to convert to degrees + *pOffset_centiDegC = value; + } + return (error); +} + +int FrogmoreScd30::setAltitudeCompensation(uint16_t height_meter) +{ + return (sendCommandArguments(COMMAND_SCD30_ALTITUDE_COMPENSATION, height_meter)); +} + +int FrogmoreScd30::setAmbientPressure(uint16_t airPressure_mbar) +{ + ambientPressure = airPressure_mbar; + return (beginMeasuring(ambientPressure)); +} + +int FrogmoreScd30::setAutoSelfCalibration(void) +{ + bool isAuto = true; + return (setCalibrationType(isAuto)); +} + +int FrogmoreScd30::setCalibrationType(bool isAuto) +{ + bool value = !!isAuto; // using NOT operator twice makes sure value is 0 or 1 + return (sendCommandArguments(COMMAND_SCD30_CALIBRATION_TYPE, value)); +} + +int FrogmoreScd30::setForcedRecalibrationFactor(uint16_t co2_ppm) +{ + return (sendCommandArguments(COMMAND_SCD30_FORCED_RECALIBRATION_FACTOR, co2_ppm)); +} + +int FrogmoreScd30::setManualCalibration(void) +{ + bool isAuto = false; + return (setCalibrationType(isAuto)); +} + +int FrogmoreScd30::setMeasurementInterval(uint16_t time_sec) +{ + if (time_sec < 2) time_sec = 2; + if (time_sec > 1800) time_sec = 1800; + return (sendCommandArguments(COMMAND_SCD30_MEASUREMENT_INTERVAL, time_sec)); +} + +int FrogmoreScd30::setTemperatureOffset(float offset_degC) +{ + uint16_t offset_centiDegC; + if (offset_degC >= 0) + { + offset_centiDegC = (uint16_t) offset_degC * 100; + return (sendCommandArguments(COMMAND_SCD30_TEMPERATURE_OFFSET, offset_centiDegC)); + } + else + { + return (ERROR_SCD30_INVALID_VALUE); + } + +} + +int FrogmoreScd30::setTemperatureOffset(uint16_t offset_centiDegC) +{ + return (sendCommandArguments(COMMAND_SCD30_TEMPERATURE_OFFSET, offset_centiDegC)); +} + +int FrogmoreScd30::beginMeasuring(void) +{ + return (beginMeasuring(ambientPressure)); +} + +int FrogmoreScd30::beginMeasuring(uint16_t airPressure_mbar) +{ + ambientPressure = airPressure_mbar; + return(sendCommandArguments(COMMAND_SCD30_CONTINUOUS_MEASUREMENT, ambientPressure)); +} + +int FrogmoreScd30::isDataAvailable(bool *pIsAvailable) +{ + uint16_t isDataAvailable = false; + int error = readRegister(COMMAND_SCD30_GET_DATA_READY, &isDataAvailable); + if (!error) + { + *pIsAvailable = isDataAvailable != 0; + } + return (error); +} + +int FrogmoreScd30::readMeasurement( + uint16 *pCO2_ppm, + uint16 *pCO2EAvg_ppm, + float *pTemperature, + float *pHumidity +) +{ + bool isAvailable = false; + int error = 0; + float tempCO2; + float tempHumidity; + float tempTemperature; + + error = isDataAvailable(&isAvailable); + if (error) + { + return (error); + } + + if (!isAvailable) + { + return (ERROR_SCD30_NO_DATA); + } + +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: have data"); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + + error = sendCommand(COMMAND_SCD30_READ_MEASUREMENT); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: send command failed: 0x%lX", error); + AddLog(LOG_LEVEL_INFO); +#endif + return (error); + } + delay(1); // the SCD30 uses clock streching to give it time to prepare data, waiting here makes it work + + uint8_t bytes[SCD30_MEAS_BYTES]; + // there are (6) 16-bit values, each with a CRC in the measurement data + // the chip does not seem to like sending this data, except all at once + error = getBytes(bytes, SCD30_MEAS_BYTES); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: Scd30GetBytes command failed: 0x%lX", error); + AddLog(LOG_LEVEL_INFO); +#endif + return (error); + } + +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: Scd30GetBytes data: 0x %02X %02X %02X | 0x %02X %02X %02X | 0x %02X %02X %02X", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8]); + AddLog(LOG_LEVEL_DEBUG_MORE); + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: Scd30GetBytes data: 0x %02X %02X %02X | 0x %02X %02X %02X | 0x %02X %02X %02X", bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15], bytes[16], bytes[17]); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + + error = get32BitRegCheckCRC(&bytes[0], &tempCO2); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: Scd30Get32BitsCheckCRC 1st command failed: 0x%lX", error); + AddLog(LOG_LEVEL_INFO); +#endif + return (error); + } + + error = get32BitRegCheckCRC(&bytes[6], &tempTemperature); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: Scd30Get32BitsCheckCRC 2nd command failed: 0x%lX", error); + AddLog(LOG_LEVEL_INFO); +#endif + return (error); + } + + error = get32BitRegCheckCRC(&bytes[12], &tempHumidity); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: Scd30Get32BitsCheckCRC 3rd command failed: 0x%lX", error); + AddLog(LOG_LEVEL_INFO); +#endif + return (error); + } + + if (tempCO2 == 0) + { + return (ERROR_SCD30_CO2_ZERO); + } + + if (co2NewDataLocation < 0) + { + co2EAverage = tempCO2; + for (int x = 0; x < SCD30_MEDIAN_FILTER_SIZE; x++) + { + co2History[x] = tempCO2; + co2NewDataLocation = 1; + } + } + else + { + co2History[co2NewDataLocation++] = tempCO2; + if (co2NewDataLocation >= SCD30_MEDIAN_FILTER_SIZE) + { + co2NewDataLocation = 0; + } + } + +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: co2History: %ld, %ld, %ld, %ld, %ld", co2History[0], co2History[1], co2History[2], co2History[3], co2History[4]); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + // copy array since the median filter function will re-arrange it + uint16_t temp[SCD30_MEDIAN_FILTER_SIZE]; + for (int x = 0; x < SCD30_MEDIAN_FILTER_SIZE; x++) + { + temp[x] = co2History[x]; + } +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: temp: %ld, %ld, %ld, %ld, %ld", temp[0], temp[1], temp[2], temp[3], temp[4]); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + + *pCO2_ppm = opt_med5(temp); +#ifdef SCD30_DEBUG + snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: CO2_ppm: %ld", *pCO2_ppm); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + if (pCO2EAvg_ppm) + { + int16_t delta = (int16_t) *pCO2_ppm - (int16_t) co2EAverage; + int16_t change = delta / 32; + co2EAverage += change; +#if 0 + uint16_t remain = co2EAverage % 5; + uint16_t dividend = co2EAverage / 5; + uint16_t co2EAReported = dividend * 5; + if (remain > 2) + { + co2EAReported += 5; + } + *pCO2EAvg_ppm = co2EAReported; +#else + *pCO2EAvg_ppm = co2EAverage; +#endif + + } + + *pTemperature = tempTemperature; + *pHumidity = tempHumidity; + return (ERROR_SCD30_NO_ERROR); +} + +int FrogmoreScd30::stopMeasuring(void) +{ + return (sendCommand(COMMAND_SCD30_STOP_MEASUREMENT)); +} + diff --git a/lib/FrogmoreScd30/FrogmoreScd30.h b/lib/FrogmoreScd30/FrogmoreScd30.h new file mode 100644 index 000000000..d1f2d1309 --- /dev/null +++ b/lib/FrogmoreScd30/FrogmoreScd30.h @@ -0,0 +1,105 @@ +/* +# Copyright (c) 2019 Frogmore42 +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#pragma once + +#include "Arduino.h" + +//#define SCD30_DEBUG + +#define SCD30_ADDRESS 0x61 +#define ERROR_SCD30_NO_ERROR 0 +#define ERROR_SCD30_NO_DATA 0x80000000 +#define ERROR_SCD30_CO2_ZERO 0x90000000 +#define ERROR_SCD30_UNKNOWN_ERROR 0x1000000 +#define ERROR_SCD30_CRC_ERROR 0x2000000 +#define ERROR_SCD30_NOT_ENOUGH_BYTES_ERROR 0x3000000 +#define ERROR_SCD30_NOT_FOUND_ERROR 0x4000000 +#define ERROR_SCD30_NOT_A_NUMBER_ERROR 0x5000000 +#define ERROR_SCD30_INVALID_VALUE 0x6000000 + +#define SCD30_MEDIAN_FILTER_SIZE 5 + +class FrogmoreScd30 +{ + public: + FrogmoreScd30() {}; + // Constructors + // the SCD30 only lists a single i2c address, so not necesary to specify + // + void begin(void); + void begin(uint8_t _i2cAddress); + void begin(TwoWire *pWire); + void begin(TwoWire *pWire, uint8_t _i2cAddress); + + int softReset(void); + int clearI2CBus(void); // this is a HARD reset of the IC2 bus to restore communication, it will disrupt the bus + + int getAltitudeCompensation(uint16_t *pHeight_meter); + int getAmbientPressure(uint16_t *pAirPressure_mbar); + int getCalibrationType(uint16_t *pIsAuto); + int getFirmwareVersion(uint8_t *pMajor, uint8_t *pMinor); + int getForcedRecalibrationFactor(uint16_t *pCo2_ppm); + int getMeasurementInterval(uint16_t *pTime_sec); + int getTemperatureOffset(float *pOffset_degC); + int getTemperatureOffset(uint16_t *pOffset_centiDegC); + + int setAltitudeCompensation(uint16_t height_meter); + int setAmbientPressure(uint16_t airPressure_mbar); + int setAutoSelfCalibration(void); + int setCalibrationType(bool isAuto); + int setForcedRecalibrationFactor(uint16_t co2_ppm); + int setManualCalibration(void); + int setMeasurementInterval(uint16_t time_sec); + int setTemperatureOffset(float offset_degC); + int setTemperatureOffset(uint16_t offset_centiDegC); + + int beginMeasuring(void); + int beginMeasuring(uint16_t airPressure_mbar); // also sets ambient pressure offset in mbar/hPascal + int isDataAvailable(bool *pIsAvailable); + int readMeasurement( + uint16 *pCO2_ppm, + uint16 *pCO2EAvg_ppm, + float *pTemperature, + float *pHumidity + ); + int stopMeasuring(void); + + private: + uint8_t i2cAddress; + TwoWire *pWire; + uint16_t ambientPressure; + uint16_t co2AvgExtra; + uint16_t co2History[SCD30_MEDIAN_FILTER_SIZE]; + uint16_t co2EAverage; + int8_t co2NewDataLocation; // location to put new CO2 data for median filter + + uint8_t computeCRC8(uint8_t data[], uint8_t len); + int sendBytes(void *pInput, uint8_t len); + int getBytes(void *pOutput, uint8_t len); + int sendCommand(uint16_t command); + int sendCommandArguments(uint16_t command, uint16_t arguments); + int get16BitRegCheckCRC(void* pInput, uint16_t* pData); + int get32BitRegCheckCRC(void* pInput, float* pData); + int readRegister(uint16_t registerAddress, uint16_t* pData); +#ifdef SCD30_DEBUG + void AddLog(uint8_t loglevel); +#endif +}; \ No newline at end of file diff --git a/sonoff/i18n.h b/sonoff/i18n.h index e0b3af57b..73e228124 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -568,9 +568,13 @@ const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m} const char HTTP_SNS_ANALOG[] PROGMEM = "%s{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = , {m} = , {e} = const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = -#if defined(USE_MHZ19) || defined(USE_SENSEAIR) || defined(USE_AZ7798) +#if defined(USE_MHZ19) || defined(USE_SENSEAIR) || defined(USE_AZ7798) || defined(USE_SCD30) const char HTTP_SNS_CO2[] PROGMEM = "%s{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = -#endif // USE_WEBSERVER +#endif // USE_MHZ19 + +#if defined(USE_SCD30) +const char HTTP_SNS_CO2EAVG[] PROGMEM = "%s{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = +#endif // USE_SCD30 const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU; const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION; diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 06bd3688b..b114c9c3d 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -95,6 +95,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); //#define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code) #define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) #define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) +#define USE_SCD30 // Add support for Sensiron SCd30 CO2 sensor (+3k6 code) #ifndef CO2_LOW #define CO2_LOW 800 // Below this CO2 value show green light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #endif diff --git a/sonoff/xdrv_92_scd30.ino b/sonoff/xdrv_92_scd30.ino new file mode 100644 index 000000000..80743ebb0 --- /dev/null +++ b/sonoff/xdrv_92_scd30.ino @@ -0,0 +1,505 @@ +/* + xdrv_92_scd30.ino - SC30 CO2 sensor support for Sonoff-Tasmota + + Copyright (C) 2019 Frogmore42 + + 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_SCD30 + +#define XDRV_92 92 +#define XSNS_92 92 +#define SCD30_MAX_MISSED_READS 3 +#define SONOFF_SCD30_STATE_NO_ERROR 0 +#define SONOFF_SCD30_STATE_ERROR_DATA_CRC 1 +#define SONOFF_SCD30_STATE_ERROR_READ_MEAS 2 +#define SONOFF_SCD30_STATE_ERROR_SOFT_RESET 3 +#define SONOFF_SCD30_STATE_ERROR_I2C_RESET 4 +#define SONOFF_SCD30_STATE_ERROR_UNKNOWN 5 + +#include "Arduino.h" +#include + +#define D_CMND_SCD30 "SCD30" + +const char S_JSON_SCD30_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d}"; +const char S_JSON_SCD30_COMMAND_NFW_VALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d.%d}"; +const char S_JSON_SCD30_COMMAND[] PROGMEM = "{\"" D_CMND_SCD30 "%s\"}"; +const char kSCD30_Commands[] PROGMEM = "Alt|Auto|Cal|FW|Int|Pres|TOff"; + +/*********************************************************************************************\ + * enumerationsines +\*********************************************************************************************/ + +enum SCD30_Commands { // commands useable in console or rules + CMND_SCD30_ALTITUDE, + CMND_SCD30_AUTOMODE, + CMND_SCD30_CALIBRATE, + CMND_SCD30_FW, + CMND_SCD30_INTERVAL, + CMND_SCD30_PRESSURE, + CMND_SCD30_TEMPOFFSET +}; + + + +FrogmoreScd30 scd30; + +bool scd30Found = false; +bool scd30IsDataValid = false; +int scd30ErrorState = SONOFF_SCD30_STATE_NO_ERROR; +uint16_t scd30Interval_sec; +int scd30Loop_count = 0; +int scd30DataNotAvailable_count = 0; +int scd30GoodMeas_count = 0; +int scd30Reset_count = 0; +int scd30CrcError_count = 0; +int scd30Co2Zero_count = 0; +int i2cReset_count = 0; +uint16_t scd30_CO2 = 0; +uint16_t scd30_CO2EAvg = 0; +float scd30_Humid = 0.0; +float scd30_Temp = 0.0; + +bool Scd30Init() +{ + int error; + bool i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); + if (i2c_flg) + { + uint8_t major = 0; + uint8_t minor = 0; + uint16_t interval_sec; + scd30.begin(); + error = scd30.getFirmwareVersion(&major, &minor); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: did not find an SCD30: 0x%lX", error); + AddLog(LOG_LEVEL_DEBUG); +#endif + return false; + } + else + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: found an SCD30: FW v%d.%d", major, minor); + AddLog(LOG_LEVEL_INFO); +#endif + } + + error = scd30.getMeasurementInterval(&scd30Interval_sec); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: error getMeasurementInterval: 0x%lX", error); + AddLog(LOG_LEVEL_ERROR); +#endif + return false; + } + + error = scd30.beginMeasuring(); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "Error: Scd30BeginMeasuring: 0x%lX", error); + AddLog(LOG_LEVEL_ERROR); +#endif + return false; + } + + return true; + } +} + +// gets data from the sensor every 3 seconds or so to give the sensor time to gather new data +int Scd30Update() +{ + int error = 0; + int16_t delta = 0; + scd30Loop_count++; + + if (!scd30Found) + { + scd30Found = Scd30Init(); +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "Scd30Update: found: %d ", scd30Found); + AddLog(LOG_LEVEL_INFO); +#endif + if (!scd30Found) + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "Scd30Update: found: %d ", scd30Found); + AddLog(LOG_LEVEL_INFO); +#endif + return (ERROR_SCD30_NOT_FOUND_ERROR); + } + } + else + { + if (scd30Loop_count > (scd30Interval_sec - 1)) + { + switch (scd30ErrorState) + { + case SONOFF_SCD30_STATE_NO_ERROR: + { + error = scd30.readMeasurement(&scd30_CO2, &scd30_CO2EAvg, &scd30_Temp, &scd30_Humid); + switch (error) + { + case ERROR_SCD30_NO_ERROR: + scd30Loop_count = 0; + scd30IsDataValid = true; + scd30GoodMeas_count++; + break; + + case ERROR_SCD30_NO_DATA: + scd30DataNotAvailable_count++; + break; + + case ERROR_SCD30_CRC_ERROR: + scd30ErrorState = SONOFF_SCD30_STATE_ERROR_DATA_CRC; + scd30CrcError_count++; +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: CRC error, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld", scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog(LOG_LEVEL_ERROR); +#endif + break; + + case ERROR_SCD30_CO2_ZERO: + scd30Co2Zero_count++; +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: CO2 zero, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld", scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog(LOG_LEVEL_ERROR); +#endif + break; + + default: + { + scd30ErrorState = SONOFF_SCD30_STATE_ERROR_READ_MEAS; +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld", error, scd30Loop_count); + AddLog(LOG_LEVEL_ERROR); +#endif + return (error); + } + break; + } + } + break; + + case SONOFF_SCD30_STATE_ERROR_DATA_CRC: + { + //scd30IsDataValid = false; +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld", scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog(LOG_LEVEL_ERROR); + snprintf_P(log_data, sizeof(log_data), "SCD30: got CRC error, try again, counter: %ld", scd30Loop_count); + AddLog(LOG_LEVEL_ERROR); +#endif + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + break; + + case SONOFF_SCD30_STATE_ERROR_READ_MEAS: + { + //scd30IsDataValid = false; +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld", scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog(LOG_LEVEL_ERROR); + snprintf_P(log_data, sizeof(log_data), "SCD30: not answering, sending soft reset, counter: %ld", scd30Loop_count); + AddLog(LOG_LEVEL_ERROR); +#endif + scd30Reset_count++; + error = scd30.softReset(); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: resetting got error: 0x%lX", error); + AddLog(LOG_LEVEL_ERROR); +#endif + error >>= 8; + if (error == 4) + { + scd30ErrorState = SONOFF_SCD30_STATE_ERROR_SOFT_RESET; + } + else + { + scd30ErrorState = SONOFF_SCD30_STATE_ERROR_UNKNOWN; + } + } + else + { + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + } + break; + + case SONOFF_SCD30_STATE_ERROR_SOFT_RESET: + { + //scd30IsDataValid = false; +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld", scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog(LOG_LEVEL_ERROR); + snprintf_P(log_data, sizeof(log_data), "SCD30: clearing i2c bus"); + AddLog(LOG_LEVEL_ERROR); +#endif + i2cReset_count++; + error = scd30.clearI2CBus(); + if (error) + { + scd30ErrorState = SONOFF_SCD30_STATE_ERROR_I2C_RESET; +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: error clearing i2c bus: 0x%lX", error); + AddLog(LOG_LEVEL_ERROR); +#endif + } + else + { + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + } + break; + + default: + { + //scd30IsDataValid = false; +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: unknown error state: 0x%lX", scd30ErrorState); + AddLog(LOG_LEVEL_ERROR); +#endif + scd30ErrorState = SONOFF_SCD30_STATE_ERROR_SOFT_RESET; // try again + } + } + + if (scd30Loop_count > (SCD30_MAX_MISSED_READS * scd30Interval_sec)) + { + scd30IsDataValid = false; + } + } + } + return (ERROR_SCD30_NO_ERROR); +} + + +int Scd30GetCommand(int command_code, uint16_t *pvalue) +{ + switch (command_code) + { + case CMND_SCD30_ALTITUDE: + return scd30.getAltitudeCompensation(pvalue); + break; + + case CMND_SCD30_AUTOMODE: + return scd30.getCalibrationType(pvalue); + break; + + case CMND_SCD30_CALIBRATE: + return scd30.getForcedRecalibrationFactor(pvalue); + break; + + case CMND_SCD30_INTERVAL: + return scd30.getMeasurementInterval(pvalue); + break; + + case CMND_SCD30_PRESSURE: + return scd30.getAmbientPressure(pvalue); + break; + + case CMND_SCD30_TEMPOFFSET: + return scd30.getTemperatureOffset(pvalue); + break; + + default: + // else for Unknown command + break; + } +} + +int Scd30SetCommand(int command_code, uint16_t value) +{ + switch (command_code) + { + case CMND_SCD30_ALTITUDE: + return scd30.setAltitudeCompensation(value); + break; + + case CMND_SCD30_AUTOMODE: + return scd30.setCalibrationType(value); + break; + + case CMND_SCD30_CALIBRATE: + return scd30.setForcedRecalibrationFactor(value); + break; + + case CMND_SCD30_INTERVAL: + { + int error = scd30.setMeasurementInterval(value); + if (!error) + { + scd30Interval_sec = value; + } + + return error; + } + break; + + case CMND_SCD30_PRESSURE: + return scd30.setAmbientPressure(value); + break; + + case CMND_SCD30_TEMPOFFSET: + return scd30.setTemperatureOffset(value); + break; + + default: + // else for Unknown command + break; + } +} +/*********************************************************************************************\ + * Command Sensor92 +\*********************************************************************************************/ + +bool Scd30CommandSensor() +{ + char command[CMDSZ]; + bool serviced = true; + uint8_t prefix_len = strlen(D_CMND_SCD30); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_SCD30), prefix_len)) { // prefix + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + prefix_len, kSCD30_Commands); + + switch (command_code) { + case CMND_SCD30_ALTITUDE: + case CMND_SCD30_AUTOMODE: + case CMND_SCD30_CALIBRATE: + case CMND_SCD30_INTERVAL: + case CMND_SCD30_PRESSURE: + case CMND_SCD30_TEMPOFFSET: + { + uint16_t value = 0; + if (XdrvMailbox.data_len > 0) + { + value = XdrvMailbox.payload16; + Scd30SetCommand(command_code, value); + } + else + { + Scd30GetCommand(command_code, &value); + } + + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SCD30_COMMAND_NVALUE, command, value); + } + break; + + case CMND_SCD30_FW: + { + uint8_t major = 0; + uint8_t minor = 0; + int error; + error = scd30.getFirmwareVersion(&major, &minor); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: error getting FW version: 0x%lX", error); + AddLog(LOG_LEVEL_ERROR); +#endif + serviced = false; + } + else + { + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SCD30_COMMAND_NFW_VALUE, command, major, minor); + } + } + break; + + default: + // else for Unknown command + serviced = false; + break; + } + } + return serviced; +} + +void Scd30Show(bool json) +{ + char humidity[10]; + char temperature[10]; + + if (scd30Found && scd30IsDataValid) + { + dtostrfd(scd30_Humid, Settings.flag2.humidity_resolution, humidity); + dtostrfd(ConvertTemp(scd30_Temp), Settings.flag2.temperature_resolution, temperature); + if (json) { + //snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), mqtt_data, scd30_CO2, temperature, humidity); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), mqtt_data, scd30_CO2, scd30_CO2EAvg, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, scd30_CO2); +#endif // USE_DOMOTICZ +#ifdef USE_WEBSERVER + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CO2EAVG, mqtt_data, "SCD30", scd30_CO2EAvg); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CO2, mqtt_data, "SCD30", scd30_CO2); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "SCD30", temperature, TempUnit()); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, "SCD30", humidity); +#endif // USE_WEBSERVER + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv92(byte function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_COMMAND: + result = Scd30CommandSensor(); + break; + } + } + return result; +} + +bool Xsns92(byte function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_EVERY_SECOND: + Scd30Update(); + break; + case FUNC_JSON_APPEND: + Scd30Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_APPEND: + Scd30Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_SCD30 +#endif // USE_I2C From 37e1b31937cc8dbb3971453e2bfb2a29a22a2b27 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 10 Mar 2019 13:33:32 +0100 Subject: [PATCH 1138/2222] Add support for sensor SCD30 * Add support for sensor SCD30 (#5434) * Add support for commands in sensor drivers --- API.md | 2 ++ sonoff/_changelog.ino | 2 ++ sonoff/my_user_config.h | 1 + sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 18 ++++++++++--- sonoff/sonoff_post.h | 4 +-- sonoff/xdrv_interface.ino | 15 +---------- sonoff/xsns_13_ina219.ino | 2 +- sonoff/xsns_15_mhz19.ino | 2 +- sonoff/xsns_27_apds9960.ino | 2 +- sonoff/xsns_29_mcp230xx.ino | 2 +- sonoff/xsns_34_hx711.ino | 2 +- sonoff/xsns_36_mgc3130.ino | 2 +- sonoff/xsns_40_pn532.ino | 2 +- .../{xdrv_92_scd30.ino => xsns_42_scd30.ino} | 27 ++++++------------- sonoff/xsns_interface.ino | 4 ++- 16 files changed, 41 insertions(+), 48 deletions(-) rename sonoff/{xdrv_92_scd30.ino => xsns_42_scd30.ino} (98%) diff --git a/API.md b/API.md index 23e45369d..caec908c6 100644 --- a/API.md +++ b/API.md @@ -23,6 +23,8 @@ FUNC_JSON_APPEND | | | | x | | Extend tele FUNC_WEB_APPEND | | | | x | | Extend webgui ajax info FUNC_SAVE_BEFORE_RESTART | | | | x | | Just before a planned restart FUNC_COMMAND | x | | x | x | | When a command is not recognized +FUNC_COMMAND_DRIVER | x | 6.4.1.21 | x | | | When command Driver\ is executed +FUNC_COMMAND_SENSOR | x | 6.4.1.21 | | x | | When command Sensor\ is executed FUNC_MQTT_SUBSCRIBE | | 5.12.0k | x | | | At end of MQTT subscriptions FUNC_MQTT_INIT | | 5.12.0k | x | | | Once at end of MQTT connection FUNC_MQTT_DATA | x | 5.12.0k | x | | | Before decoding command diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 7fcc80b8d..f0112b908 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,7 @@ /* 6.4.1.21 20190309 * Fix exception on GUI Configure Logging and Configure Other (#5424) + * Add support for sensor SCD30 (#5434) + * Add support for commands in sensor drivers * * 6.4.1.20 20190304 * Changed webserver content handling from single String to small Chunks increasing RAM diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index b5c52ff81..3030654ce 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -331,6 +331,7 @@ // #define USE_RTC_ADDR 0x68 // Default I2C address 0x68 // #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) // #define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code) +// #define USE_SCD30 // Enable Sensiron SCd30 CO2 sensor (I2C address 0x61) (+3k3 code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 951c7f6d2..6c44f54fd 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -252,7 +252,7 @@ enum LightSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MA enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, - FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, + FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_COMMAND_SENSOR, FUNC_COMMAND_DRIVER, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR, FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED, diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 0f403312e..57e4f62df 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -527,8 +527,18 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) int command_code = GetCommandCode(command, sizeof(command), type, kTasmotaCommands); if (-1 == command_code) { - if (!XdrvCommand(grpflg, type, index, dataBuf, data_len, payload, payload16)) { - type = NULL; // Unknown command +// XdrvMailbox.valid = 1; + XdrvMailbox.index = index; + XdrvMailbox.data_len = data_len; + XdrvMailbox.payload16 = payload16; + XdrvMailbox.payload = payload; + XdrvMailbox.grpflg = grpflg; + XdrvMailbox.topic = type; + XdrvMailbox.data = dataBuf; + if (!XdrvCall(FUNC_COMMAND)) { + if (!XsnsCall(FUNC_COMMAND)) { + type = NULL; // Unknown command + } } } else if (CMND_BACKLOG == command_code) { @@ -711,9 +721,9 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) XdrvMailbox.topic = command; XdrvMailbox.data = dataBuf; if (CMND_SENSOR == command_code) { - XsnsCall(FUNC_COMMAND); + XsnsCall(FUNC_COMMAND_SENSOR); } else { - XdrvCall(FUNC_COMMAND); + XdrvCall(FUNC_COMMAND_DRIVER); } } else if ((CMND_SETOPTION == command_code) && (index < 82)) { diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index b114c9c3d..fe5c5c08d 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -92,10 +92,10 @@ void KNX_CB_Action(message_t const &msg, void *arg); //#define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) //#define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) //#define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) -//#define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code) +//#define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code) +#define USE_SCD30 // Enable Sensiron SCd30 CO2 sensor (I2C address 0x61) (+3k3 code) #define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) #define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) -#define USE_SCD30 // Add support for Sensiron SCd30 CO2 sensor (+3k6 code) #ifndef CO2_LOW #define CO2_LOW 800 // Below this CO2 value show green light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #endif diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 7c3a31c25..7afea8531 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -192,20 +192,6 @@ bool (* const xdrv_func_ptr[])(uint8_t) = { // Driver Function Pointers const uint8_t xdrv_present = sizeof(xdrv_func_ptr) / sizeof(xdrv_func_ptr[0]); // Number of drivers found -bool XdrvCommand(bool grpflg, char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload, uint16_t payload16) -{ -// XdrvMailbox.valid = 1; - XdrvMailbox.index = index; - XdrvMailbox.data_len = data_len; - XdrvMailbox.payload16 = payload16; - XdrvMailbox.payload = payload; - XdrvMailbox.grpflg = grpflg; - XdrvMailbox.topic = type; - XdrvMailbox.data = dataBuf; - - return XdrvCall(FUNC_COMMAND); -} - bool XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t sdataBuf) { XdrvMailbox.index = stopicBuf; @@ -242,6 +228,7 @@ bool XdrvCall(uint8_t Function) result = xdrv_func_ptr[x](Function); if (result && ((FUNC_COMMAND == Function) || + (FUNC_COMMAND_DRIVER == Function) || (FUNC_MQTT_DATA == Function) || (FUNC_RULES_PROCESS == Function) || (FUNC_BUTTON_PRESSED == Function) || diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index dcf93867b..88f6ce240 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -266,7 +266,7 @@ bool Xsns13(uint8_t function) if (i2c_flg) { switch (function) { - case FUNC_COMMAND: + case FUNC_COMMAND_SENSOR: if ((XSNS_13 == XdrvMailbox.index) && (ina219_type)) { result = Ina219CommandSensor(); } diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 019a4dc6f..1e21aa6fb 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -373,7 +373,7 @@ bool Xsns15(uint8_t function) case FUNC_EVERY_SECOND: MhzEverySecond(); break; - case FUNC_COMMAND: + case FUNC_COMMAND_SENSOR: if (XSNS_15 == XdrvMailbox.index) { result = MhzCommandSensor(); } diff --git a/sonoff/xsns_27_apds9960.ino b/sonoff/xsns_27_apds9960.ino index ac1b7a947..765c89263 100644 --- a/sonoff/xsns_27_apds9960.ino +++ b/sonoff/xsns_27_apds9960.ino @@ -2046,7 +2046,7 @@ bool Xsns27(uint8_t function) case FUNC_EVERY_50_MSECOND: APDS9960_loop(); break; - case FUNC_COMMAND: + case FUNC_COMMAND_SENSOR: if (XSNS_27 == XdrvMailbox.index) { result = APDS9960CommandSensor(); } diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index b72afb66a..d7aaaf2ef 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -814,7 +814,7 @@ bool Xsns29(uint8_t function) case FUNC_JSON_APPEND: MCP230xx_Show(1); break; - case FUNC_COMMAND: + case FUNC_COMMAND_SENSOR: if (XSNS_29 == XdrvMailbox.index) { result = MCP230xx_Command(); } diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 15f9f37db..349dcee63 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -476,7 +476,7 @@ bool Xsns34(uint8_t function) case FUNC_EVERY_100_MSECOND: HxEvery100mSecond(); break; - case FUNC_COMMAND: + case FUNC_COMMAND_SENSOR: if (XSNS_34 == XdrvMailbox.index) { result = HxCommand(); } diff --git a/sonoff/xsns_36_mgc3130.ino b/sonoff/xsns_36_mgc3130.ino index 20df0a223..5c1d2df48 100644 --- a/sonoff/xsns_36_mgc3130.ino +++ b/sonoff/xsns_36_mgc3130.ino @@ -613,7 +613,7 @@ bool Xsns36(uint8_t function) case FUNC_EVERY_50_MSECOND: MGC3130_loop(); break; - case FUNC_COMMAND: + case FUNC_COMMAND_SENSOR: if (XSNS_36 == XdrvMailbox.index) { result = MGC3130CommandSensor(); } diff --git a/sonoff/xsns_40_pn532.ino b/sonoff/xsns_40_pn532.ino index ea88143e3..0bfa8bda1 100644 --- a/sonoff/xsns_40_pn532.ino +++ b/sonoff/xsns_40_pn532.ino @@ -593,7 +593,7 @@ bool Xsns40(uint8_t function) case FUNC_EVERY_SECOND: break; #ifdef USE_PN532_DATA_FUNCTION - case FUNC_COMMAND: + case FUNC_COMMAND_SENSOR: if (XSNS_40 == XdrvMailbox.index) { result = PN532_Command(); } diff --git a/sonoff/xdrv_92_scd30.ino b/sonoff/xsns_42_scd30.ino similarity index 98% rename from sonoff/xdrv_92_scd30.ino rename to sonoff/xsns_42_scd30.ino index 80743ebb0..c62df4d25 100644 --- a/sonoff/xdrv_92_scd30.ino +++ b/sonoff/xsns_42_scd30.ino @@ -1,5 +1,5 @@ /* - xdrv_92_scd30.ino - SC30 CO2 sensor support for Sonoff-Tasmota + xsns_42_scd30.ino - SC30 CO2 sensor support for Sonoff-Tasmota Copyright (C) 2019 Frogmore42 @@ -20,8 +20,8 @@ #ifdef USE_I2C #ifdef USE_SCD30 -#define XDRV_92 92 -#define XSNS_92 92 +#define XSNS_42 42 + #define SCD30_MAX_MISSED_READS 3 #define SONOFF_SCD30_STATE_NO_ERROR 0 #define SONOFF_SCD30_STATE_ERROR_DATA_CRC 1 @@ -224,7 +224,7 @@ int Scd30Update() #endif scd30Reset_count++; error = scd30.softReset(); - if (error) + if (error) { #ifdef SCD30_DEBUG snprintf_P(log_data, sizeof(log_data), "SCD30: resetting got error: 0x%lX", error); @@ -465,21 +465,7 @@ void Scd30Show(bool json) * Interface \*********************************************************************************************/ -bool Xdrv92(byte function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_COMMAND: - result = Scd30CommandSensor(); - break; - } - } - return result; -} - -bool Xsns92(byte function) +bool Xsns42(byte function) { bool result = false; @@ -488,6 +474,9 @@ bool Xsns92(byte function) case FUNC_EVERY_SECOND: Scd30Update(); break; + case FUNC_COMMAND: + result = Scd30CommandSensor(); + break; case FUNC_JSON_APPEND: Scd30Show(1); break; diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index 5e77b0d46..fdb947bfb 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -310,7 +310,9 @@ bool XsnsCall(uint8_t Function) } #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND - if (result && (FUNC_COMMAND == Function)) { + if (result && ((FUNC_COMMAND == Function) || + (FUNC_COMMAND_SENSOR == Function) + )) { break; } #ifdef USE_DEBUG_DRIVER From d0ac200a787444f53ad65ea2c14338ab4fdb8bbb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 10 Mar 2019 15:36:34 +0100 Subject: [PATCH 1139/2222] Replace webserver flash string to char Replace webserver flash string to char --- sonoff/xdrv_01_webserver.ino | 311 ++++++++++++++++++----------------- sonoff/xdrv_02_mqtt.ino | 8 +- sonoff/xdrv_07_domoticz.ino | 12 +- sonoff/xdrv_09_timers.ino | 28 ++-- sonoff/xdrv_11_knx.ino | 66 ++++---- sonoff/xsns_34_hx711.ino | 10 +- 6 files changed, 219 insertions(+), 216 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 2dbeeaa0d..7c69405ad 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -241,14 +241,14 @@ const char HTTP_HEAD_STYLE1[] PROGMEM = "div,fieldset,input,select{padding:5px;font-size:1em;}" "fieldset{background-color:#f2f2f2;}" // Also update HTTP_TIMER_STYLE "p{margin:0.5em 0;}" - "input{width:100%;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;}" + "input{width:100%%;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;}" "input[type=checkbox],input[type=radio]{width:1em;margin-right:6px;vertical-align:-1px;}" - "select{width:100%;}" - "textarea{resize:none;width:98%;height:318px;padding:5px;overflow:auto;}" + "select{width:100%%;}" + "textarea{resize:none;width:98%%;height:318px;padding:5px;overflow:auto;}" "body{text-align:center;font-family:verdana;}" "td{padding:0px;}"; const char HTTP_HEAD_STYLE2[] PROGMEM = - "button{border:0;border-radius:0.3rem;background-color:#1fa3ec;color:#fff;line-height:2.4rem;font-size:1.2rem;width:100%;-webkit-transition-duration:0.4s;transition-duration:0.4s;cursor:pointer;}" + "button{border:0;border-radius:0.3rem;background-color:#1fa3ec;color:#fff;line-height:2.4rem;font-size:1.2rem;width:100%%;-webkit-transition-duration:0.4s;transition-duration:0.4s;cursor:pointer;}" "button:hover{background-color:#0e70a4;}" ".bred{background-color:#d43535;}" ".bred:hover{background-color:#931f1f;}" @@ -403,7 +403,7 @@ const char HTTP_FORM_CMND[] PROGMEM = ""; const char HTTP_TABLE100[] PROGMEM = - ""; + "
"; const char HTTP_COUNTER[] PROGMEM = "
"; @@ -614,13 +614,21 @@ void WSHeaderSend(void) #endif } +/********************************************************************************************** +* HTTP Content Page handler +**********************************************************************************************/ + void WSSend(int code, int ctype, const String& content) { char ct[25]; // strlen("application/octet-stream") +1 = Longest Content type string WebServer->send(code, GetTextIndexed(ct, sizeof(ct), ctype, kContentTypes), content); } -void WSContentSendLl(const String& content) // Low level sendContent for all core versions +/********************************************************************************************** +* HTTP Content Chunk handler +**********************************************************************************************/ + +void _WSContentSend(const String& content) // Low level sendContent for all core versions { size_t len = content.length(); @@ -633,40 +641,19 @@ void WSContentSendLl(const String& content) // Low level sendContent for a WebServer->sendContent(content); #endif - ShowFreeMem(PSTR("WSContentSend")); - -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("WEB: Chunk size %d"), len); +// ShowFreeMem(PSTR("WSContentSend")); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("HTP: Chunk size %d"), len); } void WSContentFlush() { if (chunk_buffer.length() > 0) { - WSContentSendLl(chunk_buffer); // Flush chunk buffer + _WSContentSend(chunk_buffer); // Flush chunk buffer chunk_buffer = ""; } } -void WSContentSend(const String& content) // Content send string data -{ - size_t len = content.length(); - - if (0 == len) { // No content - return; - } - else if (len < CHUNKED_BUFFER_SIZE) { // Append chunk buffer with small content - chunk_buffer += content; - len = chunk_buffer.length(); - } - - if (len >= CHUNKED_BUFFER_SIZE) { // Either content or chunk buffer is oversize - WSContentFlush(); // Send chunk buffer before possible content oversize - } - if (content.length() >= CHUNKED_BUFFER_SIZE) { // Content is oversize - WSContentSendLl(content); // Send content - } -} - -void WSContentSend_P(PGM_P formatP, ...) // Content send snprintf_P char data +void WSContentSend_P(const char* formatP, ...) // Content send snprintf_P char data { // This uses char strings. Be aware of sending %% if % is needed va_list arg; @@ -674,10 +661,26 @@ void WSContentSend_P(PGM_P formatP, ...) // Content send snprintf_P cha int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); va_end(arg); - WSContentSend(mqtt_data); + if (0 == len) { // No content + return; + } + else if (len == sizeof(mqtt_data)) { + AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: Content too large")); + } + else if (len < CHUNKED_BUFFER_SIZE) { // Append chunk buffer with small content + chunk_buffer += mqtt_data; + len = chunk_buffer.length(); + } + + if (len >= CHUNKED_BUFFER_SIZE) { // Either content or chunk buffer is oversize + WSContentFlush(); // Send chunk buffer before possible content oversize + } + if (strlen(mqtt_data) >= CHUNKED_BUFFER_SIZE) { // Content is oversize + _WSContentSend(mqtt_data); // Send content + } } -void WSContentStart(const String& title, bool auth) +void WSContentStart_P(const char* title, bool auth) { if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) { return WebServer->requestAuthentication(); @@ -690,45 +693,47 @@ void WSContentStart(const String& title, bool auth) WebServer->sendHeader(F("Accept-Ranges"),F("none")); WebServer->sendHeader(F("Transfer-Encoding"),F("chunked")); #endif - WSSend(200, CT_HTML, ""); // Signal start of chunked content + WSSend(200, CT_HTML, ""); // Signal start of chunked content chunk_buffer = ""; - WSContentSend_P(HTTP_HEAD, Settings.friendlyname[0], title.c_str()); + char ctitle[strlen_P(title) +1]; + strcpy_P(ctitle, title); // Get title from flash to RAM + WSContentSend_P(HTTP_HEAD, Settings.friendlyname[0], ctitle); } -void WSContentStart(const String& title) +void WSContentStart_P(const char* title) { - WSContentStart(title, true); + WSContentStart_P(title, true); } -void WSContentSendStyle(const String& style) +void WSContentSendStyle_P(const char* style) { if (WifiIsInManagerMode()) { if (WifiConfigCounter()) { - WSContentSend(FPSTR(HTTP_SCRIPT_COUNTER)); + WSContentSend_P(HTTP_SCRIPT_COUNTER); } } - WSContentSend(FPSTR(HTTP_HEAD_STYLE1)); - WSContentSend(FPSTR(HTTP_HEAD_STYLE2)); - WSContentSend(style); + WSContentSend_P(HTTP_HEAD_STYLE1); + WSContentSend_P(HTTP_HEAD_STYLE2); + WSContentSend_P(style); WSContentSend_P(HTTP_HEAD_STYLE3, ModuleName().c_str(), Settings.friendlyname[0], WSNetworkInfo().c_str()); } -void WSContentSendStyle() +void WSContentSendStyle(void) { - WSContentSendStyle(F("")); + WSContentSendStyle_P(PSTR("")); } void WSContentEnd(void) { if (WifiIsInManagerMode()) { if (WifiConfigCounter()) { - WSContentSend(FPSTR(HTTP_COUNTER)); + WSContentSend_P(HTTP_COUNTER); } } WSContentSend_P(HTTP_END, my_version); - WSContentFlush(); // Flush chunk buffer - WSContentSendLl(""); // Signal end of chunked content + WSContentFlush(); // Flush chunk buffer + _WSContentSend(""); // Signal end of chunked content WebServer->client().stop(); } @@ -743,21 +748,21 @@ void WebRestart(uint8_t type) bool reset_only = (HTTP_MANAGER_RESET_ONLY == webserver_state); - WSContentStart((type) ? FPSTR(S_SAVE_CONFIGURATION) : FPSTR(S_RESTART), !reset_only); - WSContentSend(FPSTR(HTTP_SCRIPT_RELOAD)); + WSContentStart_P((type) ? S_SAVE_CONFIGURATION : S_RESTART, !reset_only); + WSContentSend_P(HTTP_SCRIPT_RELOAD); WSContentSendStyle(); if (type) { - WSContentSend(F("
" D_CONFIGURATION_SAVED "
")); + WSContentSend_P(PSTR("
" D_CONFIGURATION_SAVED "
")); if (2 == type) { - WSContentSend(F("
" D_TRYING_TO_CONNECT "
")); + WSContentSend_P(PSTR("
" D_TRYING_TO_CONNECT "
")); } - WSContentSend(F("
")); + WSContentSend_P(PSTR("
")); } - WSContentSend(FPSTR(HTTP_MSG_RSTRT)); + WSContentSend_P(HTTP_MSG_RSTRT); if (HTTP_MANAGER == webserver_state || reset_only) { webserver_state = HTTP_ADMIN; } else { - WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentSend_P(HTTP_BTN_MAIN); } WSContentEnd(); @@ -769,15 +774,15 @@ void WebRestart(uint8_t type) void HandleWifiLogin(void) { - WSContentStart(FPSTR(D_CONFIGURE_WIFI), false); // false means show page no matter if the client has or has not credentials + WSContentStart_P(S_CONFIGURE_WIFI, false); // false means show page no matter if the client has or has not credentials WSContentSendStyle(); - WSContentSend(FPSTR(HTTP_FORM_LOGIN)); + WSContentSend_P(HTTP_FORM_LOGIN); if (HTTP_MANAGER_RESET_ONLY == webserver_state) { - WSContentSend(F("
")); - WSContentSend(FPSTR(HTTP_BTN_RSTRT)); + WSContentSend_P(PSTR("
")); + WSContentSend_P(HTTP_BTN_RSTRT); #ifndef FIRMWARE_MINIMAL - WSContentSend(FPSTR(HTTP_BTN_RESET)); + WSContentSend_P(HTTP_BTN_RESET); #endif // FIRMWARE_MINIMAL } @@ -817,11 +822,11 @@ void HandleRoot(void) char stemp[5]; - WSContentStart(FPSTR(S_MAIN_MENU)); + WSContentStart_P(S_MAIN_MENU); WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh); WSContentSendStyle(); - WSContentSend(F("
")); + WSContentSend_P(PSTR("
")); if (devices_present) { if (light_type) { if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { @@ -829,8 +834,8 @@ void HandleRoot(void) } WSContentSend_P(HTTP_MSG_SLIDER2, Settings.light_dimmer); } - WSContentSend(FPSTR(HTTP_TABLE100)); - WSContentSend(F("")); + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("")); if (SONOFF_IFAN02 == my_module_type) { WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); for (uint8_t i = 0; i < MAX_FAN_SPEED; i++) { @@ -843,20 +848,20 @@ void HandleRoot(void) WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); } } - WSContentSend(F("
")); + WSContentSend_P(PSTR("")); } if (SONOFF_BRIDGE == my_module_type) { - WSContentSend(FPSTR(HTTP_TABLE100)); - WSContentSend(F("")); + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("")); uint8_t idx = 0; for (uint8_t i = 0; i < 4; i++) { - if (idx > 0) { WSContentSend(F("")); } + if (idx > 0) { WSContentSend_P(PSTR("")); } for (uint8_t j = 0; j < 4; j++) { idx++; WSContentSend_P(PSTR(""), idx, idx); // &k is related to WebGetArg("k", tmp, sizeof(tmp)); } } - WSContentSend(F("")); + WSContentSend_P(PSTR("")); } #ifndef FIRMWARE_MINIMAL @@ -866,12 +871,12 @@ void HandleRoot(void) if (HTTP_ADMIN == webserver_state) { #ifndef FIRMWARE_MINIMAL - WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentSend_P(HTTP_BTN_CONF); #else - WSContentSend(F("
")); + WSContentSend_P(PSTR("
")); #endif // Not FIRMWARE_MINIMAL - WSContentSend(FPSTR(HTTP_BTN_MENU1)); - WSContentSend(FPSTR(HTTP_BTN_RSTRT)); + WSContentSend_P(HTTP_BTN_MENU1); + WSContentSend_P(HTTP_BTN_RSTRT); } WSContentEnd(); } @@ -965,17 +970,17 @@ void HandleConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURATION); - WSContentStart(FPSTR(S_CONFIGURATION)); + WSContentStart_P(S_CONFIGURATION); WSContentSendStyle(); - WSContentSend(FPSTR(HTTP_BTN_MENU_MODULE)); + WSContentSend_P(HTTP_BTN_MENU_MODULE); XdrvCall(FUNC_WEB_ADD_BUTTON); XsnsCall(FUNC_WEB_ADD_BUTTON); - WSContentSend(FPSTR(HTTP_BTN_MENU4)); - WSContentSend(FPSTR(HTTP_BTN_RESET)); - WSContentSend(FPSTR(HTTP_BTN_MENU5)); - WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentSend_P(HTTP_BTN_MENU4); + WSContentSend_P(HTTP_BTN_RESET); + WSContentSend_P(HTTP_BTN_MENU5); + WSContentSend_P(HTTP_BTN_MAIN); WSContentEnd(); } @@ -1045,24 +1050,24 @@ void HandleTemplateConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TEMPLATE); - WSContentStart(FPSTR(S_CONFIGURE_TEMPLATE)); - WSContentSend(FPSTR(HTTP_SCRIPT_MODULE_TEMPLATE)); - WSContentSend(FPSTR(HTTP_SCRIPT_TEMPLATE)); + WSContentStart_P(S_CONFIGURE_TEMPLATE); + WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); + WSContentSend_P(HTTP_SCRIPT_TEMPLATE); WSContentSendStyle(); - WSContentSend(FPSTR(HTTP_FORM_TEMPLATE)); + WSContentSend_P(HTTP_FORM_TEMPLATE); - WSContentSend(F("
")); + WSContentSend_P(PSTR("
")); for (uint8_t i = 0; i < 17; i++) { if ((i < 6) || ((i > 8) && (i != 11))) { // Ignore flash pins GPIO06, 7, 8 and 11 WSContentSend_P(PSTR("" D_GPIO "%d"), (0==i)?" style='width:74px'":"", i, ((9==i)||(10==i))? "ESP8285" :"", (0==i)?" style='width:176px'":"", i, i); } } - WSContentSend(F("
%s
")); + WSContentSend_P(PSTR("")); - WSContentSend(FPSTR(HTTP_FORM_TEMPLATE_FLAG)); - WSContentSend(FPSTR(HTTP_FORM_END)); - WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); + WSContentSend_P(HTTP_FORM_END); + WSContentSend_P(HTTP_BTN_CONF); WSContentEnd(); } @@ -1149,15 +1154,15 @@ void HandleModuleConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); - WSContentStart(FPSTR(S_CONFIGURE_MODULE)); - WSContentSend(FPSTR(HTTP_SCRIPT_MODULE_TEMPLATE)); + WSContentStart_P(S_CONFIGURE_MODULE); + WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); WSContentSend_P(HTTP_SCRIPT_MODULE1, Settings.module); for (uint8_t i = 0; i < sizeof(cmodule); i++) { if (ValidGPIO(i, cmodule.io[i])) { WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); // g0 - g16 } } - WSContentSend(FPSTR(HTTP_SCRIPT_MODULE2)); + WSContentSend_P(HTTP_SCRIPT_MODULE2); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); for (uint8_t i = 0; i < sizeof(cmodule); i++) { @@ -1167,9 +1172,9 @@ void HandleModuleConfiguration(void) (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); } } - WSContentSend(F("")); - WSContentSend(FPSTR(HTTP_FORM_END)); - WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentSend_P(PSTR("")); + WSContentSend_P(HTTP_FORM_END); + WSContentSend_P(HTTP_BTN_CONF); WSContentEnd(); } @@ -1226,8 +1231,8 @@ void HandleWifiConfiguration(void) return; } - WSContentStart(FPSTR(S_CONFIGURE_WIFI), !WifiIsInManagerMode()); - WSContentSend(FPSTR(HTTP_SCRIPT_WIFI)); + WSContentStart_P(S_CONFIGURE_WIFI, !WifiIsInManagerMode()); + WSContentSend_P(HTTP_SCRIPT_WIFI); WSContentSendStyle(); if (HTTP_MANAGER_RESET_ONLY != webserver_state) { @@ -1240,8 +1245,8 @@ void HandleWifiConfiguration(void) if (0 == n) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, S_NO_NETWORKS_FOUND); - WSContentSend(FPSTR(S_NO_NETWORKS_FOUND)); - WSContentSend(F(". " D_REFRESH_TO_SCAN_AGAIN ".")); + WSContentSend_P(S_NO_NETWORKS_FOUND); + WSContentSend_P(PSTR(". " D_REFRESH_TO_SCAN_AGAIN ".")); } else { //sort networks int indices[n]; @@ -1280,40 +1285,38 @@ void HandleWifiConfiguration(void) int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); if (minimum_signal_quality == -1 || minimum_signal_quality < quality) { - String item = F("
{v} ({w}) {i} {r}%
"); - String rssiQ; - rssiQ += quality; - item.replace(F("{v}"), htmlEscape(WiFi.SSID(indices[i]))); - item.replace(F("{w}"), String(WiFi.channel(indices[i]))); - item.replace(F("{r}"), rssiQ); uint8_t auth = WiFi.encryptionType(indices[i]); - item.replace(F("{i}"), (ENC_TYPE_WEP == auth) ? F(D_WEP) : (ENC_TYPE_TKIP == auth) ? F(D_WPA_PSK) : (ENC_TYPE_CCMP == auth) ? F(D_WPA2_PSK) : (ENC_TYPE_AUTO == auth) ? F(D_AUTO) : F("")); - WSContentSend(item); + WSContentSend_P(PSTR("
%s (%d) %s %d%%
"), + htmlEscape(WiFi.SSID(indices[i])).c_str(), + WiFi.channel(indices[i]), + (ENC_TYPE_WEP == auth) ? D_WEP : (ENC_TYPE_TKIP == auth) ? D_WPA_PSK : (ENC_TYPE_CCMP == auth) ? D_WPA2_PSK : (ENC_TYPE_AUTO == auth) ? D_AUTO : "", + quality + ); delay(0); } else { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SKIPPING_LOW_QUALITY)); } } - WSContentSend(F("
")); + WSContentSend_P(PSTR("
")); } } else { - WSContentSend(F("
")); + WSContentSend_P(PSTR("
")); } // As WIFI_HOSTNAME may contain %s-%04d it cannot be part of HTTP_FORM_WIFI where it will exception WSContentSend_P(HTTP_FORM_WIFI, Settings.sta_ssid[0], Settings.sta_ssid[1], WIFI_HOSTNAME, WIFI_HOSTNAME, Settings.hostname); - WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend_P(HTTP_FORM_END); } if (WifiIsInManagerMode()) { - WSContentSend(F("
")); - WSContentSend(FPSTR(HTTP_BTN_RSTRT)); + WSContentSend_P(PSTR("
")); + WSContentSend_P(HTTP_BTN_RSTRT); #ifndef FIRMWARE_MINIMAL - WSContentSend(FPSTR(HTTP_BTN_RESET)); + WSContentSend_P(HTTP_BTN_RESET); #endif // FIRMWARE_MINIMAL } else { - WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentSend_P(HTTP_BTN_CONF); } WSContentEnd(); } @@ -1352,9 +1355,9 @@ void HandleLoggingConfiguration(void) return; } - WSContentStart(FPSTR(S_CONFIGURE_LOGGING)); + WSContentStart_P(S_CONFIGURE_LOGGING); WSContentSendStyle(); - WSContentSend(FPSTR(HTTP_FORM_LOG1)); + WSContentSend_P(HTTP_FORM_LOG1); char stemp1[32]; char stemp2[32]; uint8_t dlevel[3] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE }; @@ -1369,11 +1372,11 @@ void HandleLoggingConfiguration(void) (i == llevel) ? " selected" : "", i, i, GetTextIndexed(stemp1, sizeof(stemp1), i, kLoggingLevels)); } - WSContentSend(F("

")); + WSContentSend_P(PSTR("

")); } WSContentSend_P(HTTP_FORM_LOG2, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); - WSContentSend(FPSTR(HTTP_FORM_END)); - WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentSend_P(HTTP_FORM_END); + WSContentSend_P(HTTP_BTN_CONF); WSContentEnd(); } @@ -1416,7 +1419,7 @@ void HandleOtherConfiguration(void) return; } - WSContentStart(FPSTR(S_CONFIGURE_OTHER)); + WSContentStart_P(S_CONFIGURE_OTHER); WSContentSendStyle(); TemplateJson(); @@ -1437,7 +1440,7 @@ void HandleOtherConfiguration(void) } #ifdef USE_EMULATION - WSContentSend(F("

 " D_EMULATION " 

")); // Keep close to Friendlynames so do not use
+ WSContentSend_P(PSTR("

 " D_EMULATION " 

")); // Keep close to Friendlynames so do not use
for (uint8_t i = 0; i < EMUL_MAX; i++) { WSContentSend_P(PSTR("%s %s
"), // Different id only used for labels i, i, @@ -1445,11 +1448,11 @@ void HandleOtherConfiguration(void) GetTextIndexed(stemp, sizeof(stemp), i, kEmulationOptions), (i == EMUL_NONE) ? "" : (i == EMUL_WEMO) ? D_SINGLE_DEVICE : D_MULTI_DEVICE); } - WSContentSend(F("

")); + WSContentSend_P(PSTR("

")); #endif // USE_EMULATION - WSContentSend(FPSTR(HTTP_FORM_END)); - WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentSend_P(HTTP_FORM_END); + WSContentSend_P(HTTP_BTN_CONF); WSContentEnd(); } @@ -1541,11 +1544,11 @@ void HandleResetConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESET_CONFIGURATION); - WSContentStart(FPSTR(S_RESET_CONFIGURATION), !WifiIsInManagerMode()); + WSContentStart_P(S_RESET_CONFIGURATION, !WifiIsInManagerMode()); WSContentSendStyle(); - WSContentSend(F("
" D_CONFIGURATION_RESET "
")); - WSContentSend(FPSTR(HTTP_MSG_RSTRT)); - WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentSend_P(PSTR("
" D_CONFIGURATION_RESET "
")); + WSContentSend_P(HTTP_MSG_RSTRT); + WSContentSend_P(HTTP_BTN_MAIN); WSContentEnd(); char command[CMDSZ]; @@ -1559,11 +1562,11 @@ void HandleRestoreConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTORE_CONFIGURATION); - WSContentStart(FPSTR(S_RESTORE_CONFIGURATION)); + WSContentStart_P(S_RESTORE_CONFIGURATION); WSContentSendStyle(); - WSContentSend(FPSTR(HTTP_FORM_RST)); + WSContentSend_P(HTTP_FORM_RST); WSContentSend_P(HTTP_FORM_RST_UPG, D_RESTORE); - WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentSend_P(HTTP_BTN_CONF); WSContentEnd(); upload_error = 0; @@ -1582,11 +1585,11 @@ void HandleInformation(void) int freeMem = ESP.getFreeHeap(); - WSContentStart(FPSTR(S_INFORMATION)); + WSContentStart_P(S_INFORMATION); // Save 1k of code space replacing table html with javascript replace codes // }1 = // }2 = - WSContentSend(FPSTR(HTTP_SCRIPT_INFO_BEGIN)); + WSContentSend_P(HTTP_SCRIPT_INFO_BEGIN); WSContentSend_P(PSTR("
")); WSContentSend_P(PSTR(D_PROGRAM_VERSION "}2%s%s"), my_version, my_image); WSContentSend_P(PSTR("}1" D_BUILD_DATE_AND_TIME "}2%s"), GetBuildDateAndTime().c_str()); @@ -1659,13 +1662,13 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1" D_FREE_MEMORY "}2%dkB"), freeMem / 1024); WSContentSend_P(PSTR("
")); - WSContentSend(FPSTR(HTTP_SCRIPT_INFO_END)); + WSContentSend_P(HTTP_SCRIPT_INFO_END); WSContentSendStyle(); - // WSContentSend(F("
 Information ")); + // WSContentSend_P(PSTR("
 Information ")); WSContentSend_P(PSTR("" "
")); - // WSContentSend(F("
")); - WSContentSend(FPSTR(HTTP_BTN_MAIN)); + // WSContentSend_P(PSTR("
")); + WSContentSend_P(HTTP_BTN_MAIN); WSContentEnd(); } #endif // Not FIRMWARE_MINIMAL @@ -1678,11 +1681,11 @@ void HandleUpgradeFirmware(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_FIRMWARE_UPGRADE); - WSContentStart(FPSTR(S_FIRMWARE_UPGRADE)); + WSContentStart_P(S_FIRMWARE_UPGRADE); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_UPG, Settings.ota_url); WSContentSend_P(HTTP_FORM_RST_UPG, D_UPGRADE); - WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentSend_P(HTTP_BTN_MAIN); WSContentEnd(); upload_error = 0; @@ -1705,12 +1708,12 @@ void HandleUpgradeFirmwareStart(void) ExecuteWebCommand(command, SRC_WEBGUI); } - WSContentStart(FPSTR(S_INFORMATION)); - WSContentSend(FPSTR(HTTP_SCRIPT_RELOAD_OTA)); + WSContentStart_P(S_INFORMATION); + WSContentSend_P(HTTP_SCRIPT_RELOAD_OTA); WSContentSendStyle(); - WSContentSend(F("
" D_UPGRADE_STARTED " ...
")); - WSContentSend(FPSTR(HTTP_MSG_RSTRT)); - WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentSend_P(PSTR("
" D_UPGRADE_STARTED " ...
")); + WSContentSend_P(HTTP_MSG_RSTRT); + WSContentSend_P(HTTP_BTN_MAIN); WSContentEnd(); snprintf_P(command, sizeof(command), PSTR(D_CMND_UPGRADE " 1")); @@ -1729,14 +1732,14 @@ void HandleUploadDone(void) restart_flag = 0; MqttRetryCounter(0); - WSContentStart(FPSTR(S_INFORMATION)); + WSContentStart_P(S_INFORMATION); if (!upload_error) { - WSContentSend(FPSTR(HTTP_SCRIPT_RELOAD_OTA)); // Refesh main web ui after OTA upgrade + WSContentSend_P(HTTP_SCRIPT_RELOAD_OTA); // Refesh main web ui after OTA upgrade } WSContentSendStyle(); - WSContentSend(F("
" D_UPLOAD " " D_UPLOAD " " D_FAILED "

")); + WSContentSend_P(PSTR("red'>" D_FAILED "


")); #ifdef USE_RF_FLASH if (upload_error < 14) { #else @@ -1746,18 +1749,18 @@ void HandleUploadDone(void) } else { snprintf_P(error, sizeof(error), PSTR(D_UPLOAD_ERROR_CODE " %d"), upload_error); } - WSContentSend(error); + WSContentSend_P(error); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_UPLOAD ": %s"), error); stop_flash_rotate = Settings.flag.stop_flash_rotate; } else { - WSContentSend(F("green'>" D_SUCCESSFUL "
")); - WSContentSend(FPSTR(HTTP_MSG_RSTRT)); + WSContentSend_P(PSTR("green'>" D_SUCCESSFUL "
")); + WSContentSend_P(HTTP_MSG_RSTRT); ShowWebSource(SRC_WEBGUI); restart_flag = 2; // Always restart to re-enable disabled features during update } SettingsBufferFree(); - WSContentSend(F("

")); - WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentSend_P(PSTR("

")); + WSContentSend_P(HTTP_BTN_MAIN); WSContentEnd(); } @@ -2032,11 +2035,11 @@ void HandleConsole(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONSOLE); - WSContentStart(FPSTR(S_CONSOLE)); + WSContentStart_P(S_CONSOLE); WSContentSend_P(HTTP_SCRIPT_CONSOL, Settings.web_refresh); WSContentSendStyle(); - WSContentSend(FPSTR(HTTP_FORM_CMND)); - WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentSend_P(HTTP_FORM_CMND); + WSContentSend_P(HTTP_BTN_MAIN); WSContentEnd(); } diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 450ff252b..b79f6a866 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -917,7 +917,7 @@ void HandleMqttConfiguration(void) char str[sizeof(Settings.mqtt_client)]; - WSContentStart(FPSTR(S_CONFIGURE_MQTT)); + WSContentStart_P(S_CONFIGURE_MQTT); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_MQTT1, Settings.mqtt_host, @@ -930,8 +930,8 @@ void HandleMqttConfiguration(void) Settings.mqtt_topic, MQTT_FULLTOPIC, MQTT_FULLTOPIC, Settings.mqtt_fulltopic); - WSContentSend(FPSTR(HTTP_FORM_END)); - WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentSend_P(HTTP_FORM_END); + WSContentSend_P(HTTP_BTN_CONF); WSContentEnd(); } @@ -980,7 +980,7 @@ bool Xdrv02(uint8_t function) switch (function) { #ifdef USE_WEBSERVER case FUNC_WEB_ADD_BUTTON: - WSContentSend(FPSTR(HTTP_BTN_MENU_MQTT)); + WSContentSend_P(HTTP_BTN_MENU_MQTT); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 4c660998e..490c2e00d 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -460,9 +460,9 @@ void HandleDomoticzConfiguration(void) char stemp[32]; - WSContentStart(FPSTR(S_CONFIGURE_DOMOTICZ)); + WSContentStart_P(S_CONFIGURE_DOMOTICZ); WSContentSendStyle(); - WSContentSend(FPSTR(HTTP_FORM_DOMOTICZ)); + WSContentSend_P(HTTP_FORM_DOMOTICZ); for (int i = 0; i < MAX_DOMOTICZ_IDX; i++) { if (i < devices_present) { WSContentSend_P(HTTP_FORM_DOMOTICZ_RELAY, @@ -480,9 +480,9 @@ void HandleDomoticzConfiguration(void) i +1, GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors), i, i, Settings.domoticz_sensor_idx[i]); } WSContentSend_P(HTTP_FORM_DOMOTICZ_TIMER, Settings.domoticz_update_timer); - WSContentSend(F("")); - WSContentSend(FPSTR(HTTP_FORM_END)); - WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentSend_P(PSTR("")); + WSContentSend_P(HTTP_FORM_END); + WSContentSend_P(HTTP_BTN_CONF); WSContentEnd(); } @@ -533,7 +533,7 @@ bool Xdrv07(uint8_t function) switch (function) { #ifdef USE_WEBSERVER case FUNC_WEB_ADD_BUTTON: - WSContentSend(FPSTR(HTTP_BTN_MENU_DOMOTICZ)); + WSContentSend_P(HTTP_BTN_MENU_DOMOTICZ); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration); diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index e80f5bc01..e8de5effa 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -538,7 +538,7 @@ const char HTTP_TIMER_SCRIPT2[] PROGMEM = "if(m==0){" // Time is set "so(0);" // Hide offset span and allow Hour 00..23 "q=Math.floor(p/60);if(q<10){q='0'+q;}qs('#ho').value=q;" // Set hours - "q=p%60;if(q<10){q='0'+q;}qs('#mi').value=q;" // Set minutes + "q=p%%60;if(q<10){q='0'+q;}qs('#mi').value=q;" // Set minutes "}" "if((m==1)||(m==2)){" // Sunrise or sunset is set "so(1);" // Show offset span and allow Hour 00..11 @@ -546,7 +546,7 @@ const char HTTP_TIMER_SCRIPT2[] PROGMEM = "if(q>=12){q-=12;qs('#dr').selectedIndex=1;}" // Negative offset "else{qs('#dr').selectedIndex=0;}" "if(q<10){q='0'+q;}qs('#ho').value=q;" // Set offset hours - "q=p%60;if(q<10){q='0'+q;}qs('#mi').value=q;" // Set offset minutes + "q=p%%60;if(q<10){q='0'+q;}qs('#mi').value=q;" // Set offset minutes "}" "}" "function so(b){" // Hide or show offset items @@ -648,7 +648,7 @@ const char HTTP_TIMER_SCRIPT6[] PROGMEM = "}" "window.onload=it;"; const char HTTP_TIMER_STYLE[] PROGMEM = - ".tl{float:left;border-radius:0;border:1px solid #f2f2f2;padding:1px;width:6.25%;}"; // Border color needs to be the same as Fieldset background color from HTTP_HEAD_STYLE1 (transparent won't work) + ".tl{float:left;border-radius:0;border:1px solid #f2f2f2;padding:1px;width:6.25%%;}"; // Border color needs to be the same as Fieldset background color from HTTP_HEAD_STYLE1 (transparent won't work) const char HTTP_FORM_TIMER1[] PROGMEM = "
" " " D_TIMER_PARAMETERS " " @@ -698,29 +698,29 @@ void HandleTimerConfiguration(void) return; } - WSContentStart(FPSTR(S_CONFIGURE_TIMER)); - WSContentSend(FPSTR(HTTP_TIMER_SCRIPT1)); + WSContentStart_P(S_CONFIGURE_TIMER); + WSContentSend_P(HTTP_TIMER_SCRIPT1); #ifdef USE_SUNRISE - WSContentSend(FPSTR(HTTP_TIMER_SCRIPT2)); + WSContentSend_P(HTTP_TIMER_SCRIPT2); #endif // USE_SUNRISE WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT4, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT5, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present); - WSContentSendStyle(FPSTR(HTTP_TIMER_STYLE)); + WSContentSendStyle_P(HTTP_TIMER_STYLE); WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); for (uint8_t i = 0; i < MAX_TIMERS; i++) { WSContentSend_P(PSTR("%s%u"), (i > 0) ? "," : "", Settings.timer[i].data); } - WSContentSend(FPSTR(HTTP_FORM_TIMER2)); + WSContentSend_P(HTTP_FORM_TIMER2); #ifdef USE_SUNRISE WSContentSend_P(HTTP_FORM_TIMER3, 100 + (strlen(D_SUNSET) *12), GetSun(0).c_str(), GetSun(1).c_str()); #else - WSContentSend(FPSTR(HTTP_FORM_TIMER3)); + WSContentSend_P(HTTP_FORM_TIMER3); #endif // USE_SUNRISE - WSContentSend(FPSTR(HTTP_FORM_TIMER4)); - WSContentSend(FPSTR(HTTP_FORM_END)); - WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentSend_P(HTTP_FORM_TIMER4); + WSContentSend_P(HTTP_FORM_END); + WSContentSend_P(HTTP_BTN_CONF); WSContentEnd(); } @@ -764,9 +764,9 @@ bool Xdrv09(uint8_t function) #ifdef USE_TIMERS_WEB case FUNC_WEB_ADD_BUTTON: #ifdef USE_RULES - WSContentSend(FPSTR(HTTP_BTN_MENU_TIMER)); + WSContentSend_P(HTTP_BTN_MENU_TIMER); #else - if (devices_present) { WSContentSend(FPSTR(HTTP_BTN_MENU_TIMER)); } + if (devices_present) { WSContentSend_P(HTTP_BTN_MENU_TIMER); } #endif // USE_RULES break; case FUNC_WEB_ADD_HANDLER: diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index af23ab220..6f4a5b96d 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -762,7 +762,7 @@ const char HTTP_FORM_KNX2[] PROGMEM = "
" "" D_KNX_GROUP_ADDRESS_TO_WRITE "
" - ""; const char HTTP_FORM_KNX_OPT[] PROGMEM = ""; @@ -786,7 +786,7 @@ const char HTTP_FORM_KNX3[] PROGMEM = "" D_KNX_GROUP_ADDRESS_TO_READ "
"; const char HTTP_FORM_KNX4[] PROGMEM = - "-> "; const char HTTP_FORM_KNX_ADD_TABLE_ROW2[] PROGMEM = "%d / %d / %d -> %s" @@ -859,33 +859,33 @@ void HandleKNXConfiguration(void) } - WSContentStart(FPSTR(S_CONFIGURE_KNX)); - WSContentSend( - F("function GAwarning()" - "{" - "var GA_FNUM = eb('GA_FNUM');" - "var GA_AREA = eb('GA_AREA');" - "var GA_FDEF = eb('GA_FDEF');" - "if ( GA_FNUM != null && GA_FNUM.value == '0' && GA_AREA.value == '0' && GA_FDEF.value == '0' ) {" - "alert('" D_KNX_WARNING "');" + WSContentStart_P(S_CONFIGURE_KNX); + WSContentSend_P( + PSTR("function GAwarning()" + "{" + "var GA_FNUM=eb('GA_FNUM');" + "var GA_AREA=eb('GA_AREA');" + "var GA_FDEF=eb('GA_FDEF');" + "if(GA_FNUM!=null&&GA_FNUM.value=='0'&&GA_AREA.value=='0'&&GA_FDEF.value=='0'){" + "alert('" D_KNX_WARNING "');" + "}" "}" - "}" - "function CBwarning()" - "{" - "var CB_FNUM = eb('CB_FNUM');" - "var CB_AREA = eb('CB_AREA');" - "var CB_FDEF = eb('CB_FDEF');" - "if ( CB_FNUM != null && CB_FNUM.value == '0' && CB_AREA.value == '0' && CB_FDEF.value == '0' ) {" - "alert('" D_KNX_WARNING "');" - "}" - "}")); + "function CBwarning()" + "{" + "var CB_FNUM=eb('CB_FNUM');" + "var CB_AREA=eb('CB_AREA');" + "var CB_FDEF=eb('CB_FDEF');" + "if(CB_FNUM!=null&&CB_FNUM.value=='0'&&CB_AREA.value=='0'&&CB_FDEF.value=='0'){" + "alert('" D_KNX_WARNING "');" + "}" + "}")); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_KNX, KNX_physs_addr.pa.area, KNX_physs_addr.pa.line, KNX_physs_addr.pa.member); - if ( Settings.flag.knx_enabled ) { WSContentSend(F(" checked")); } - WSContentSend(FPSTR(HTTP_FORM_KNX1)); - if ( Settings.flag.knx_enable_enhancement ) { WSContentSend(F(" checked")); } + if ( Settings.flag.knx_enabled ) { WSContentSend_P(PSTR(" checked")); } + WSContentSend_P(HTTP_FORM_KNX1); + if ( Settings.flag.knx_enable_enhancement ) { WSContentSend_P(PSTR(" checked")); } - WSContentSend(FPSTR(HTTP_FORM_KNX2)); + WSContentSend_P(HTTP_FORM_KNX2); for (uint8_t i = 0; i < KNX_MAX_device_param ; i++) { if ( device_param[i].show ) @@ -893,7 +893,7 @@ void HandleKNXConfiguration(void) WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_ga[i]); } } - WSContentSend(F(" -> ")); + WSContentSend_P(PSTR(" -> ")); WSContentSend_P(HTTP_FORM_KNX_GA, "GA_FNUM", "GA_FNUM", "GA_AREA", "GA_AREA", "GA_FDEF", "GA_FDEF"); WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "GAwarning", (Settings.knx_GA_registered < MAX_KNX_GA) ? "" : "disabled", 1); for (uint8_t i = 0; i < Settings.knx_GA_registered ; ++i) @@ -905,9 +905,9 @@ void HandleKNXConfiguration(void) } } - WSContentSend(FPSTR(HTTP_FORM_KNX3)); + WSContentSend_P(HTTP_FORM_KNX3); WSContentSend_P(HTTP_FORM_KNX_GA, "CB_FNUM", "CB_FNUM", "CB_AREA", "CB_AREA", "CB_FDEF", "CB_FDEF"); - WSContentSend(FPSTR(HTTP_FORM_KNX4)); + WSContentSend_P(HTTP_FORM_KNX4); uint8_t j; for (uint8_t i = 0; i < KNX_MAX_device_param ; i++) @@ -920,7 +920,7 @@ void HandleKNXConfiguration(void) WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_cb[i]); } } - WSContentSend(F(" ")); + WSContentSend_P(PSTR(" ")); WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "CBwarning", (Settings.knx_CB_registered < MAX_KNX_CB) ? "" : "disabled", 2); for (uint8_t i = 0; i < Settings.knx_CB_registered ; ++i) @@ -931,9 +931,9 @@ void HandleKNXConfiguration(void) WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW2, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings.knx_CB_param[i]-1], i +1); } } - WSContentSend(F("
")); - WSContentSend(FPSTR(HTTP_FORM_END)); - WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentSend_P(PSTR("
")); + WSContentSend_P(HTTP_FORM_END); + WSContentSend_P(HTTP_BTN_CONF); WSContentEnd(); } @@ -1229,7 +1229,7 @@ bool Xdrv11(uint8_t function) #ifdef USE_WEBSERVER #ifdef USE_KNX_WEB_MENU case FUNC_WEB_ADD_BUTTON: - WSContentSend(FPSTR(HTTP_BTN_MENU_KNX)); + WSContentSend_P(HTTP_BTN_MENU_KNX); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/kn", HandleKNXConfiguration); diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 349dcee63..3405b377b 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -426,14 +426,14 @@ void HandleHxAction(void) return; } - WSContentStart(FPSTR(D_CONFIGURE_HX711)); + WSContentStart_P(S_CONFIGURE_HX711); WSContentSendStyle(); dtostrfd((float)Settings.weight_reference / 1000, 3, stemp1); char stemp2[20]; dtostrfd((float)Settings.weight_item / 10000, 4, stemp2); WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); - WSContentSend(FPSTR(HTTP_FORM_END)); - WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentSend_P(HTTP_FORM_END); + WSContentSend_P(HTTP_BTN_CONF); WSContentEnd(); } @@ -490,10 +490,10 @@ bool Xsns34(uint8_t function) break; #ifdef USE_HX711_GUI case FUNC_WEB_ADD_MAIN_BUTTON: - WSContentSend(FPSTR(HTTP_BTN_MENU_MAIN_HX711)); + WSContentSend_P(HTTP_BTN_MENU_MAIN_HX711); break; case FUNC_WEB_ADD_BUTTON: - WSContentSend(FPSTR(HTTP_BTN_MENU_HX711)); + WSContentSend_P(HTTP_BTN_MENU_HX711); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); From baa582556912b6606040f7b37d393ee9900ab177 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 11 Mar 2019 10:38:41 +0100 Subject: [PATCH 1140/2222] Free some flash Free some flash --- sonoff/sonoff.ino | 4 + sonoff/xdrv_01_webserver.ino | 141 ++++++++++++++++++++--------------- sonoff/xdrv_02_mqtt.ino | 4 +- sonoff/xdrv_07_domoticz.ino | 2 +- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_10_rules.ino | 2 + sonoff/xdrv_11_knx.ino | 2 +- sonoff/xdrv_13_display.ino | 2 + sonoff/xdrv_interface.ino | 2 + sonoff/xsns_34_hx711.ino | 2 +- 10 files changed, 96 insertions(+), 67 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 57e4f62df..f7a78c179 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -462,7 +462,9 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) uint16_t index; uint32_t address; +#ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("MqttDataHandler")); +#endif strlcpy(topicBuf, topic, sizeof(topicBuf)); for (i = 0; i < data_len; i++) { @@ -1595,7 +1597,9 @@ void ExecuteCommand(char *cmnd, int source) char *start; char *token; +#ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("ExecuteCommand")); +#endif ShowSource(source); token = strtok(cmnd, " "); diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 7c69405ad..9d96c480c 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -283,37 +283,6 @@ const char HTTP_MSG_SLIDER2[] PROGMEM = const char HTTP_MSG_RSTRT[] PROGMEM = "
" D_DEVICE_WILL_RESTART "

"; -const char HTTP_BTN_CONF[] PROGMEM = - "
" - "
"; -const char HTTP_BTN_MENU1[] PROGMEM = -#ifndef FIRMWARE_MINIMAL - "

" -#endif - "
" - "

"; -const char HTTP_BTN_RSTRT[] PROGMEM = - "
"; - -const char HTTP_BTN_MENU_MODULE[] PROGMEM = - "

" - "

"; -const char HTTP_BTN_MENU4[] PROGMEM = - "

" - "

" - "

"; - -const char HTTP_BTN_RESET[] PROGMEM = - "
" - "
"; -const char HTTP_BTN_MENU5[] PROGMEM = - "

" - "

"; - -const char HTTP_BTN_MAIN[] PROGMEM = - "
" - "
"; - const char HTTP_FORM_LOGIN[] PROGMEM = "
" "
" @@ -418,6 +387,20 @@ const char HTTP_END[] PROGMEM = const char HTTP_DEVICE_CONTROL[] PROGMEM = ""; // ?o is related to WebGetArg("o", tmp, sizeof(tmp)); const char HTTP_DEVICE_STATE[] PROGMEM = "%s%s"; // {c} = %'>

"), + GetTextIndexed(action, sizeof(action), title_index, kButtonAction), + GetTextIndexed(confirm, sizeof(confirm), title_index, kButtonConfirm), + (!title_index) ? "rst" : "non", + GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); + } else { + WSContentSend_P(PSTR("

"), + GetTextIndexed(action, sizeof(action), title_index, kButtonAction), + GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); + } +} + +void WSContentSpaceButton(uint8_t title_index) +{ + WSContentSend_P(PSTR("
")); // 5px padding + WSContentButton(title_index); +} + void WSContentEnd(void) { if (WifiIsInManagerMode()) { @@ -762,7 +772,7 @@ void WebRestart(uint8_t type) if (HTTP_MANAGER == webserver_state || reset_only) { webserver_state = HTTP_ADMIN; } else { - WSContentSend_P(HTTP_BTN_MAIN); + WSContentSpaceButton(BUTTON_MAIN); } WSContentEnd(); @@ -779,10 +789,9 @@ void HandleWifiLogin(void) WSContentSend_P(HTTP_FORM_LOGIN); if (HTTP_MANAGER_RESET_ONLY == webserver_state) { - WSContentSend_P(PSTR("
")); - WSContentSend_P(HTTP_BTN_RSTRT); + WSContentSpaceButton(BUTTON_RESTART); #ifndef FIRMWARE_MINIMAL - WSContentSend_P(HTTP_BTN_RESET); + WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); #endif // FIRMWARE_MINIMAL } @@ -793,7 +802,7 @@ void HandleRoot(void) { if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the page. - if (WebServer->hasArg("rstrt")) { + if (WebServer->hasArg("rst")) { WebRestart(0); return; } @@ -870,13 +879,15 @@ void HandleRoot(void) #endif // Not FIRMWARE_MINIMAL if (HTTP_ADMIN == webserver_state) { -#ifndef FIRMWARE_MINIMAL - WSContentSend_P(HTTP_BTN_CONF); +#ifdef FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_FIRMWARE_UPGRADE); #else - WSContentSend_P(PSTR("
")); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentButton(BUTTON_INFORMATION); + WSContentButton(BUTTON_FIRMWARE_UPGRADE); #endif // Not FIRMWARE_MINIMAL - WSContentSend_P(HTTP_BTN_MENU1); - WSContentSend_P(HTTP_BTN_RSTRT); + WSContentButton(BUTTON_CONSOLE); + WSContentButton(BUTTON_RESTART); } WSContentEnd(); } @@ -972,15 +983,22 @@ void HandleConfiguration(void) WSContentStart_P(S_CONFIGURATION); WSContentSendStyle(); - WSContentSend_P(HTTP_BTN_MENU_MODULE); + + WSContentButton(BUTTON_MODULE); + WSContentButton(BUTTON_WIFI); XdrvCall(FUNC_WEB_ADD_BUTTON); XsnsCall(FUNC_WEB_ADD_BUTTON); - WSContentSend_P(HTTP_BTN_MENU4); - WSContentSend_P(HTTP_BTN_RESET); - WSContentSend_P(HTTP_BTN_MENU5); - WSContentSend_P(HTTP_BTN_MAIN); + WSContentButton(BUTTON_LOGGING); + WSContentButton(BUTTON_OTHER); + WSContentButton(BUTTON_TEMPLATE); + + WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); + WSContentButton(BUTTON_BACKUP); + WSContentButton(BUTTON_RESTORE); + + WSContentSpaceButton(BUTTON_MAIN); WSContentEnd(); } @@ -1067,7 +1085,7 @@ void HandleTemplateConfiguration(void) WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); WSContentSend_P(HTTP_FORM_END); - WSContentSend_P(HTTP_BTN_CONF); + WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentEnd(); } @@ -1174,7 +1192,7 @@ void HandleModuleConfiguration(void) } WSContentSend_P(PSTR("")); WSContentSend_P(HTTP_FORM_END); - WSContentSend_P(HTTP_BTN_CONF); + WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentEnd(); } @@ -1310,13 +1328,12 @@ void HandleWifiConfiguration(void) } if (WifiIsInManagerMode()) { - WSContentSend_P(PSTR("
")); - WSContentSend_P(HTTP_BTN_RSTRT); + WSContentSpaceButton(BUTTON_RESTART); #ifndef FIRMWARE_MINIMAL - WSContentSend_P(HTTP_BTN_RESET); + WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); #endif // FIRMWARE_MINIMAL } else { - WSContentSend_P(HTTP_BTN_CONF); + WSContentSpaceButton(BUTTON_CONFIGURATION); } WSContentEnd(); } @@ -1376,7 +1393,7 @@ void HandleLoggingConfiguration(void) } WSContentSend_P(HTTP_FORM_LOG2, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); WSContentSend_P(HTTP_FORM_END); - WSContentSend_P(HTTP_BTN_CONF); + WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentEnd(); } @@ -1452,7 +1469,7 @@ void HandleOtherConfiguration(void) #endif // USE_EMULATION WSContentSend_P(HTTP_FORM_END); - WSContentSend_P(HTTP_BTN_CONF); + WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentEnd(); } @@ -1548,7 +1565,7 @@ void HandleResetConfiguration(void) WSContentSendStyle(); WSContentSend_P(PSTR("
" D_CONFIGURATION_RESET "
")); WSContentSend_P(HTTP_MSG_RSTRT); - WSContentSend_P(HTTP_BTN_MAIN); + WSContentSpaceButton(BUTTON_MAIN); WSContentEnd(); char command[CMDSZ]; @@ -1566,7 +1583,7 @@ void HandleRestoreConfiguration(void) WSContentSendStyle(); WSContentSend_P(HTTP_FORM_RST); WSContentSend_P(HTTP_FORM_RST_UPG, D_RESTORE); - WSContentSend_P(HTTP_BTN_CONF); + WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentEnd(); upload_error = 0; @@ -1668,7 +1685,7 @@ void HandleInformation(void) WSContentSend_P(PSTR("" "
")); // WSContentSend_P(PSTR("
")); - WSContentSend_P(HTTP_BTN_MAIN); + WSContentSpaceButton(BUTTON_MAIN); WSContentEnd(); } #endif // Not FIRMWARE_MINIMAL @@ -1685,7 +1702,7 @@ void HandleUpgradeFirmware(void) WSContentSendStyle(); WSContentSend_P(HTTP_FORM_UPG, Settings.ota_url); WSContentSend_P(HTTP_FORM_RST_UPG, D_UPGRADE); - WSContentSend_P(HTTP_BTN_MAIN); + WSContentSpaceButton(BUTTON_MAIN); WSContentEnd(); upload_error = 0; @@ -1713,7 +1730,7 @@ void HandleUpgradeFirmwareStart(void) WSContentSendStyle(); WSContentSend_P(PSTR("
" D_UPGRADE_STARTED " ...
")); WSContentSend_P(HTTP_MSG_RSTRT); - WSContentSend_P(HTTP_BTN_MAIN); + WSContentSpaceButton(BUTTON_MAIN); WSContentEnd(); snprintf_P(command, sizeof(command), PSTR(D_CMND_UPGRADE " 1")); @@ -1760,7 +1777,7 @@ void HandleUploadDone(void) } SettingsBufferFree(); WSContentSend_P(PSTR("
")); - WSContentSend_P(HTTP_BTN_MAIN); + WSContentSpaceButton(BUTTON_MAIN); WSContentEnd(); } @@ -2039,7 +2056,7 @@ void HandleConsole(void) WSContentSend_P(HTTP_SCRIPT_CONSOL, Settings.web_refresh); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_CMND); - WSContentSend_P(HTTP_BTN_MAIN); + WSContentSpaceButton(BUTTON_MAIN); WSContentEnd(); } diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index b79f6a866..ba3dabc09 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -281,7 +281,9 @@ void MqttPublishDirect(const char* topic, bool retained) char sretained[CMDSZ]; char slog_type[10]; +#ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("MqttPublishDirect")); +#endif sretained[0] = '\0'; snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_RESULT)); @@ -931,7 +933,7 @@ void HandleMqttConfiguration(void) MQTT_FULLTOPIC, MQTT_FULLTOPIC, Settings.mqtt_fulltopic); WSContentSend_P(HTTP_FORM_END); - WSContentSend_P(HTTP_BTN_CONF); + WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentEnd(); } diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 490c2e00d..0bd275d7c 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -482,7 +482,7 @@ void HandleDomoticzConfiguration(void) WSContentSend_P(HTTP_FORM_DOMOTICZ_TIMER, Settings.domoticz_update_timer); WSContentSend_P(PSTR("")); WSContentSend_P(HTTP_FORM_END); - WSContentSend_P(HTTP_BTN_CONF); + WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentEnd(); } diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index e8de5effa..9a85ad3c4 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -720,7 +720,7 @@ void HandleTimerConfiguration(void) #endif // USE_SUNRISE WSContentSend_P(HTTP_FORM_TIMER4); WSContentSend_P(HTTP_FORM_END); - WSContentSend_P(HTTP_BTN_CONF); + WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentEnd(); } diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 4422d92b3..4d13bf6b9 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -387,7 +387,9 @@ bool RulesProcessEvent(char *json_event) { bool serviced = false; +#ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("RulesProcessEvent")); +#endif String event_saved = json_event; event_saved.toUpperCase(); diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 6f4a5b96d..5ab0c7c88 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -933,7 +933,7 @@ void HandleKNXConfiguration(void) } WSContentSend_P(PSTR("")); WSContentSend_P(HTTP_FORM_END); - WSContentSend_P(HTTP_BTN_CONF); + WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentEnd(); } diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 3f779b821..f14680939 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -695,7 +695,9 @@ void DisplayJsonValue(const char* topic, const char* device, const char* mkey, c char source[Settings.display_cols[0] - Settings.display_cols[1]]; char svalue[Settings.display_cols[1] +1]; +#ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("DisplayJsonValue")); +#endif memset(spaces, 0x20, sizeof(spaces)); spaces[sizeof(spaces) -1] = '\0'; diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 7afea8531..7de5e1bb5 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -207,6 +207,7 @@ bool XdrvRulesProcess(void) return XdrvCall(FUNC_RULES_PROCESS); } +#ifdef USE_DEBUG_DRIVER void ShowFreeMem(const char *where) { char stemp[20]; @@ -214,6 +215,7 @@ void ShowFreeMem(const char *where) XdrvMailbox.data = stemp; XdrvCall(FUNC_FREE_MEM); } +#endif /*********************************************************************************************\ * Function call to all xdrv diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 3405b377b..2072dc496 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -433,7 +433,7 @@ void HandleHxAction(void) dtostrfd((float)Settings.weight_item / 10000, 4, stemp2); WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); WSContentSend_P(HTTP_FORM_END); - WSContentSend_P(HTTP_BTN_CONF); + WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentEnd(); } From d7715d1d2ad8f837bd7e588a77f27dcc63fd57a1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 11 Mar 2019 14:55:14 +0100 Subject: [PATCH 1141/2222] Add 0x to IRRemote and RCSwitch Add 0x to IRRemote (SetOption29) and RCSwitch (SetOption28) received hexadecimal data (#5431) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_05_irremote.ino | 4 ++-- sonoff/xdrv_17_rcswitch.ino | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index f0112b908..5cce34d71 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Fix exception on GUI Configure Logging and Configure Other (#5424) * Add support for sensor SCD30 (#5434) * Add support for commands in sensor drivers + * Add 0x to IRRemote (SetOption29) and RCSwitch (SetOption28) received hexadecimal data (#5431) * * 6.4.1.20 20190304 * Changed webserver content handling from single String to small Chunks increasing RAM diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index f9f88bd56..a72bc2764 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -114,7 +114,7 @@ void IrReceiveCheck(void) if (irrecv->decode(&results)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value %08X, Decode %d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value 0x%08X, Decode %d"), irsend_active, results.rawlen, results.overflow, results.bits, results.value, results.decode_type); unsigned long now = millis(); @@ -129,7 +129,7 @@ void IrReceiveCheck(void) if (Settings.flag.ir_receive_decimal) { snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)results.value); } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"%lX\""), (uint32_t)results.value); + snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)results.value); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s"), GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, stemp); diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index 4566c44d8..300a156f5 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -49,7 +49,7 @@ void RfReceiveCheck(void) int protocol = mySwitch.getReceivedProtocol(); int delay = mySwitch.getReceivedDelay(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFR: Data %lX (%u), Bits %d, Protocol %d, Delay %d"), data, data, bits, protocol, delay); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFR: Data 0x%lX (%u), Bits %d, Protocol %d, Delay %d"), data, data, bits, protocol, delay); uint32_t now = millis(); if ((now - rf_lasttime > RF_TIME_AVOID_DUPLICATE) && (data > 0)) { @@ -59,7 +59,7 @@ void RfReceiveCheck(void) if (Settings.flag.rf_receive_decimal) { // SetOption28 (0 = hexadecimal, 1 = decimal) snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)data); } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"%lX\""), (uint32_t)data); + snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), stemp, bits, protocol, delay); From 5927f7501c24527c7c73ecc6e60ebf31c9ca2862 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 11 Mar 2019 15:41:06 +0100 Subject: [PATCH 1142/2222] Update xdrv_12_home_assistant.ino Quick fix for #5356 --- sonoff/xdrv_12_home_assistant.ino | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index adc93ae09..0304d1411 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -170,7 +170,8 @@ int try_snprintf_P(char *s, size_t n, const char *format, ... ) { va_list args; va_start(args, format); - int len = vsnprintf_P(NULL, 0, format, args); + char dummy[2]; + int len = vsnprintf_P(dummy, 1, format, args); if (len >= n) { AddLog_P2(LOG_LEVEL_ERROR, PSTR("ERROR: MQTT discovery failed due to too long topic or friendly name. " "Please shorten topic and friendly name. Failed to format(%u/%u):"), len, n); @@ -232,6 +233,7 @@ void HAssAnnounceRelayLight(void) Shorten(&command_topic, prefix); Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); + try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, From 58d075deff0fee5b17b89d52c2e94d51fad075be Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 11 Mar 2019 16:49:59 +0100 Subject: [PATCH 1143/2222] Update xsns_22_sr04.ino Fix debug compile error --- sonoff/xsns_22_sr04.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index ee4939bba..a52898728 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -28,6 +28,8 @@ * - https://www.dfrobot.com/wiki/index.php/Weather-proof_Ultrasonic_Sensor_SKU_:_SEN0207 \*********************************************************************************************/ +#define XSNS_22 22 + uint8_t sr04_echo_pin = 0; uint8_t sr04_trig_pin = 0; real64_t distance; @@ -73,8 +75,6 @@ void Sr04Show(bool json) * Interface \*********************************************************************************************/ -#define XSNS_22 - bool Xsns22(uint8_t function) { bool result = false; From 6c69b8d12dda6f9821e7a79ed4f16032b8e93565 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 11 Mar 2019 18:18:47 +0100 Subject: [PATCH 1144/2222] Add button control when no relay configured Add button control when no relay configured (#4682) --- sonoff/_changelog.ino | 1 + sonoff/support_button.ino | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 5cce34d71..63e229fdc 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Add support for sensor SCD30 (#5434) * Add support for commands in sensor drivers * Add 0x to IRRemote (SetOption29) and RCSwitch (SetOption28) received hexadecimal data (#5431) + * Add button control when no relay configured (#4682) * * 6.4.1.20 20190304 * Changed webserver content handling from single String to small Chunks increasing RAM diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index ad17edd77..c0fe14bd2 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -95,8 +95,9 @@ void ButtonHandler(void) uint16_t loops_per_second = 1000 / Settings.button_debounce; char scmnd[20]; - uint8_t maxdev = (devices_present > MAX_KEYS) ? MAX_KEYS : devices_present; - for (uint8_t button_index = 0; button_index < maxdev; button_index++) { +// uint8_t maxdev = (devices_present > MAX_KEYS) ? MAX_KEYS : devices_present; +// for (uint8_t button_index = 0; button_index < maxdev; button_index++) { + for (uint8_t button_index = 0; button_index < MAX_KEYS; button_index++) { button = NOT_PRESSED; button_present = 0; From d4ca635db6e8449f5d44387d80155bf7b6335947 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 11 Mar 2019 18:29:39 +0100 Subject: [PATCH 1145/2222] Add MQTT connect count to HASS sensor --- sonoff/xdrv_12_home_assistant.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 0304d1411..5998b3585 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -544,11 +544,11 @@ void HAssPublishStatus(void) PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"," "\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," "\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"," - "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\"," + "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d," "\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_CMND_IPADDRESS "\":\"%s\"," "\"" D_JSON_RSSI "\":\"%d\",\"LoadAvg\":%lu}"), my_version, my_image, GetBuildDateAndTime().c_str(), ESP.getSdkVersion(), ModuleName().c_str(), - GetResetReason().c_str(), GetUptime().c_str(), WifiLinkCount(), WifiDowntime().c_str(), + GetResetReason().c_str(), GetUptime().c_str(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), Settings.bootcount, Settings.save_flag, WiFi.localIP().toString().c_str(), WifiGetRssiAsQuality(WiFi.RSSI()), loop_load_avg); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE)); From ffc1505872ed4d179647fa2f32d97816cc1ee3ba Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Mar 2019 10:21:33 +0100 Subject: [PATCH 1146/2222] Fix exception caused by wrong baudrate selection Fix exception caused by wrong baudrate selection --- sonoff/sonoff.ino | 2 +- sonoff/xdrv_08_serial_bridge.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index f7a78c179..82c306c90 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1068,7 +1068,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.switch_debounce); } else if (CMND_BAUDRATE == command_code) { - if (payload32 > 0) { + if (payload32 > 1200) { payload32 /= 1200; // Make it a valid baudrate baudrate = (1 == payload) ? APP_BAUDRATE : payload32 * 1200; SetSerialBaudrate(baudrate); diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 0db7da58c..d39e7a6eb 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -150,7 +150,7 @@ bool SerialBridgeCommand(void) else if (CMND_SBAUDRATE == command_code) { char *p; int baud = strtol(XdrvMailbox.data, &p, 10); - if (baud > 0) { + if (baud >= 1200) { baud /= 1200; // Make it a valid baudrate Settings.sbaudrate = (1 == XdrvMailbox.payload) ? SOFT_BAUDRATE / 1200 : baud; SerialBridgeSerial->begin(Settings.sbaudrate * 1200); // Reinitialize serial port with new baud rate From 2aaca4bc2b99c37bb4f1283f0db18b88e18878af Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Mar 2019 10:22:40 +0100 Subject: [PATCH 1147/2222] Revert "Fix exception caused by wrong baudrate selection" This reverts commit ffc1505872ed4d179647fa2f32d97816cc1ee3ba. --- sonoff/sonoff.ino | 2 +- sonoff/xdrv_08_serial_bridge.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 82c306c90..f7a78c179 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1068,7 +1068,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.switch_debounce); } else if (CMND_BAUDRATE == command_code) { - if (payload32 > 1200) { + if (payload32 > 0) { payload32 /= 1200; // Make it a valid baudrate baudrate = (1 == payload) ? APP_BAUDRATE : payload32 * 1200; SetSerialBaudrate(baudrate); diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index d39e7a6eb..0db7da58c 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -150,7 +150,7 @@ bool SerialBridgeCommand(void) else if (CMND_SBAUDRATE == command_code) { char *p; int baud = strtol(XdrvMailbox.data, &p, 10); - if (baud >= 1200) { + if (baud > 0) { baud /= 1200; // Make it a valid baudrate Settings.sbaudrate = (1 == XdrvMailbox.payload) ? SOFT_BAUDRATE / 1200 : baud; SerialBridgeSerial->begin(Settings.sbaudrate * 1200); // Reinitialize serial port with new baud rate From 73be43b60fe5348368cf7b373a1966bff2aedd1c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Mar 2019 10:23:20 +0100 Subject: [PATCH 1148/2222] Fix exception caused by wrong baudrate selection Fix exception caused by wrong baudrate selection (#5441) --- sonoff/sonoff.ino | 2 +- sonoff/xdrv_08_serial_bridge.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index f7a78c179..82c306c90 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1068,7 +1068,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.switch_debounce); } else if (CMND_BAUDRATE == command_code) { - if (payload32 > 0) { + if (payload32 > 1200) { payload32 /= 1200; // Make it a valid baudrate baudrate = (1 == payload) ? APP_BAUDRATE : payload32 * 1200; SetSerialBaudrate(baudrate); diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 0db7da58c..d39e7a6eb 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -150,7 +150,7 @@ bool SerialBridgeCommand(void) else if (CMND_SBAUDRATE == command_code) { char *p; int baud = strtol(XdrvMailbox.data, &p, 10); - if (baud > 0) { + if (baud >= 1200) { baud /= 1200; // Make it a valid baudrate Settings.sbaudrate = (1 == XdrvMailbox.payload) ? SOFT_BAUDRATE / 1200 : baud; SerialBridgeSerial->begin(Settings.sbaudrate * 1200); // Reinitialize serial port with new baud rate From 282744d5fd4f3877be1ba5274a4990d808fd32b3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 13 Mar 2019 18:06:20 +0100 Subject: [PATCH 1149/2222] Houskeeping Houskeeping --- sonoff/support_features.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 31c449531..c69b8e671 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -383,8 +383,10 @@ void GetFeatures(void) #endif #ifdef USE_MAX44009 feature_sns2 |= 0x00200000; -#endif -// feature_sns2 |= 0x00400000; +#endif +#ifdef USE_SCD30 + feature_sns2 |= 0x00400000; +#endif // feature_sns2 |= 0x00800000; // feature_sns2 |= 0x01000000; // feature_sns2 |= 0x02000000; From 3332a54942253b673e72fc4f45b7f744d50ecdf0 Mon Sep 17 00:00:00 2001 From: Yuval <38878996+rt400@users.noreply.github.com> Date: Thu, 14 Mar 2019 16:05:40 +0200 Subject: [PATCH 1150/2222] Update he-HE.h --- sonoff/language/he-HE.h | 124 ++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 9f3458889..2a876d2b0 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -55,20 +55,20 @@ #define D_AIR_QUALITY "איכות אוויר" #define D_AP "AP" // Access Point #define D_AS "as" -#define D_AUTO "AUTO" +#define D_AUTO "אוטומטי" #define D_BLINK "מהבהב" #define D_BLINKOFF "כיבוי היבהוב" #define D_BOOT_COUNT "מונה הפעלה מחדש" #define D_BRIGHTLIGHT "בהירות" #define D_BSSID "BSSId" #define D_BUTTON "לחצן" -#define D_BY "by" // Written by me +#define D_BY "ע"י" // Written by me #define D_BYTES "בייט" #define D_CELSIUS "צלזיוס" #define D_CHANNEL "ערוץ" #define D_CO2 "Carbon dioxide" #define D_CODE "קוד" // Button code -#define D_COLDLIGHT "קור" +#define D_COLDLIGHT "אור קר" #define D_COMMAND "פקודה" #define D_CONNECTED "מחובר" #define D_COUNT "סופר" @@ -148,7 +148,7 @@ #define D_STOP "עצירה" #define D_SUBNET_MASK "רשת מסכת משנה" #define D_SUBSCRIBE_TO "הרשם ל" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_UNSUBSCRIBE_FROM "בטל רישום" #define D_SUCCESSFUL "הצליח" #define D_SUNRISE "זריחה" #define D_SUNSET "שקיעה" @@ -176,33 +176,33 @@ #define D_UV_POWER "UV Power" #define D_VERSION "גרסה" #define D_VOLTAGE "מתח" -#define D_WEIGHT "Weight" +#define D_WEIGHT "משקל" #define D_WARMLIGHT "חום" #define D_WEB_SERVER "Web שרת" // sonoff.ino -#define D_WARNING_MINIMAL_VERSION "WARNING This version does not support persistent settings" +#define D_WARNING_MINIMAL_VERSION "אזהרה גרסה זו אינה תומכת בהגדרות קבועות" #define D_LEVEL_10 "level 1-0" #define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serial logging disabled" -#define D_SYSLOG_LOGGING_REENABLED "Syslog logging re-enabled" +#define D_SERIAL_LOGGING_DISABLED "רישום טורי מושבת" +#define D_SYSLOG_LOGGING_REENABLED "הופעל מחדש Syslog רישום" -#define D_SET_BAUDRATE_TO "Set Baudrate to" -#define D_RECEIVED_TOPIC "Received Topic" -#define D_DATA_SIZE "Data Size" +#define D_SET_BAUDRATE_TO "הגדר קצב שידור ל" +#define D_RECEIVED_TOPIC "Topic התקבל" +#define D_DATA_SIZE "גודל נתונים" #define D_ANALOG_INPUT "אנלוגי" // support.ino #define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" -#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes" -#define D_FAILED_TO_START "failed to start" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "Connecting to AP" -#define D_IN_MODE "in mode" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connect failed as no IP address received" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Connect failed as AP cannot be reached" +#define D_BLOCKED_LOOP "לולאות חסומות" +#define D_WPS_FAILED_WITH_STATUS "נכשל עם הסטטוס WPSconfig" +#define D_ACTIVE_FOR_3_MINUTES "פעיל במשך 3 דקות" +#define D_FAILED_TO_START "נכשל בנסיון להתחיל" +#define D_PATCH_ISSUE_2186 "בעית תיקון 2186" +#define D_CONNECTING_TO_AP "AP -מתחבר ל" +#define D_IN_MODE "במצב" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP החיבור נכשל מכיוון שלא התקבלה כתובת" +#define D_CONNECT_FAILED_AP_NOT_REACHED "זמין AP החיבור נכשל כיוון שאין" #define D_CONNECT_FAILED_WRONG_PASSWORD "Connect failed with AP incorrect password" #define D_CONNECT_FAILED_AP_TIMEOUT "Connect failed with AP timeout" #define D_ATTEMPTING_CONNECTION "Attempting connection..." @@ -213,19 +213,19 @@ #define D_SYSLOG_HOST_NOT_FOUND "Syslog Host not found" // settings.ino -#define D_SAVED_TO_FLASH_AT "Saved to flash at" -#define D_LOADED_FROM_FLASH_AT "Loaded from flash at" +#define D_SAVED_TO_FLASH_AT "נשמר לפלאש ב" +#define D_LOADED_FROM_FLASH_AT "נטען מהפלאש מ" #define D_USE_DEFAULTS "השתמש בהגדרות ברירת המחדל" #define D_ERASED_SECTOR "סקטור מחוק" // xdrv_02_webserver.ino #define D_NOSCRIPT "JavaScript - כדי להשתמש ב קושחה אסמוטה אנא הפעל" #define D_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" -#define D_FILE_NOT_FOUND "File Not Found" -#define D_REDIRECTED "Redirected to captive portal" +#define D_WEBSERVER_ACTIVE_ON "שרת ווב פעיל" +#define D_WITH_IP_ADDRESS "IP עם כתובת" +#define D_WEBSERVER_STOPPED "שרת ווב הופסק" +#define D_FILE_NOT_FOUND "קובץ לא נמצא" +#define D_REDIRECTED "הופנה מחדש לפורטל" #define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" #define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" #define D_TRYING_TO_CONNECT "מנסה לחבר את ההתקן לרשת" @@ -254,7 +254,7 @@ #define D_MODULE_PARAMETERS "מודול פרמטרים" #define D_MODULE_TYPE "סוג מודול" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_PULLUP_ENABLE "pull-up אין לחצן/מתג" #define D_GPIO " רגל " #define D_SERIAL_IN "כניסת סריאל" #define D_SERIAL_OUT "יציאת סריאל" @@ -299,13 +299,13 @@ #define D_SINGLE_DEVICE "התקן בודד" #define D_MULTI_DEVICE "התקנים" -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" -#define D_ALLOW_ADC0 "ADC0 input" -#define D_ALLOW_PULLUP "User pull-up selection" +#define D_CONFIGURE_TEMPLATE "הגדר תבנית" +#define D_TEMPLATE_PARAMETERS "פרמטרים של תבנית" +#define D_TEMPLATE_NAME "שם" +#define D_BASE_TYPE "מבוסס על" +#define D_TEMPLATE_FLAGS "אפשריות" +#define D_ALLOW_ADC0 "ADC0 כניסת" +#define D_ALLOW_PULLUP "pull-up בחירת משתמש עבור" #define D_SAVE_CONFIGURATION "שמירת הגדרות" #define D_CONFIGURATION_SAVED "הגדרות נשמרו" @@ -357,12 +357,12 @@ #define D_NEED_USER_AND_PASSWORD "Need user=&password=" // xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verify TLS fingerprint..." -#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to" -#define D_RETRY_IN "Retry in" -#define D_VERIFIED "Verified using Fingerprint" -#define D_INSECURE "Insecure connection due to invalid Fingerprint" -#define D_CONNECT_FAILED_TO "Connect failed to" +#define D_FINGERPRINT "...TLS אמת טביעת אצבע של" +#define D_TLS_CONNECT_FAILED_TO "נכשל TLS חיבור" +#define D_RETRY_IN "נסה שוב תוך" +#define D_VERIFIED "מאומת באמצעות טביעת אצבע" +#define D_INSECURE "חיבור לא מאובטח עקב טביעת אצבע לא חוקית" +#define D_CONNECT_FAILED_TO "חיבור נכשל ל" // xplg_wemohue.ino #define D_MULTICAST_DISABLED "Multicast disabled" @@ -441,16 +441,16 @@ #define D_ENERGY_TOTAL "צריכה כללית" // xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor busy" -#define D_SENSOR_CRC_ERROR "Sensor CRC error" -#define D_SENSORS_FOUND "Sensors found" +#define D_SENSOR_BUSY "שרת עסוק" +#define D_SENSOR_CRC_ERROR "בחיישן CRC שגיאת" +#define D_SENSORS_FOUND "חיישנים לא נמצאו" // xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Timeout waiting for" -#define D_START_SIGNAL_LOW "start signal low" -#define D_START_SIGNAL_HIGH "start signal high" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "Checksum failure" +#define D_TIMEOUT_WAITING_FOR "הזמן הקצוב להמתנה" +#define D_START_SIGNAL_LOW "להתחיל אות נמוך" +#define D_START_SIGNAL_HIGH "להתחיל אות גבוה" +#define D_PULSE "פעימה" +#define D_CHECKSUM_FAILURE "בדיקת כשל נכשלה" // xsns_07_sht1x.ino #define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" @@ -470,17 +470,17 @@ #define D_GZ_AXIS "Gyro Z-Axis" // xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" +#define D_HX_CAL_REMOVE "הסר משקל" +#define D_HX_CAL_REFERENCE "טען משקל התייחסות" +#define D_HX_CAL_DONE "מכויל" +#define D_HX_CAL_FAIL "כיול נכשל" +#define D_RESET_HX711 "אפס את קנה המידה" +#define D_CONFIGURE_HX711 "הגדר קנה מידה" +#define D_HX711_PARAMETERS "פרמטרים של קנה מידה" +#define D_ITEM_WEIGHT "משקל פריט" +#define D_REFERENCE_WEIGHT "משקל הפניה" +#define D_CALIBRATE "כייל" +#define D_CALIBRATION "כיול" //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Wind Direction" @@ -494,7 +494,7 @@ // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" -#define D_SENSOR_USER "User" +#define D_SENSOR_USER "משתמש" #define D_SENSOR_DHT11 "DHT11" #define D_SENSOR_AM2301 "AM2301" #define D_SENSOR_SI7021 "SI7021" @@ -502,7 +502,7 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_DFR562 "נגן מוזיקה" #define D_SENSOR_IRSEND "IRsend" #define D_SENSOR_SWITCH "מתג" // Suffix "1" #define D_SENSOR_BUTTON "לחצן" // Suffix "1" From 2959ec93412951b6b9cdf1c4673b5b170208938c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 14 Mar 2019 16:50:56 +0100 Subject: [PATCH 1151/2222] Prep for release with fix some warnings Prep for release with fix some warnings --- sonoff/settings.h | 16 ++++++------- sonoff/sonoff.ino | 33 ++++++++++++--------------- sonoff/support.ino | 2 +- sonoff/xdrv_01_webserver.ino | 38 ++++++++++++------------------- sonoff/xdrv_12_home_assistant.ino | 2 +- 5 files changed, 38 insertions(+), 53 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 342ff1612..5a7827365 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -200,8 +200,8 @@ struct SYSCFG { uint8_t seriallog_level; // 09E uint8_t sta_config; // 09F uint8_t sta_active; // 0A0 - char sta_ssid[2][33]; // 0A1 - Keep together with sta_pwd as being copied as one chunck with reset 4/5 - char sta_pwd[2][65]; // 0E3 - Keep together with sta_ssid as being copied as one chunck with reset 4/5 + char sta_ssid[2][33]; // 0A1 - Keep together with sta_pwd as being copied as one chunck with reset 5 + char sta_pwd[2][65]; // 0E3 - Keep together with sta_ssid as being copied as one chunck with reset 5 char hostname[33]; // 165 char syslog_host[33]; // 186 uint8_t rule_stop; // 1A7 @@ -213,12 +213,12 @@ struct SYSCFG { uint8_t free_1D5[20]; // 1D5 Free since 5.12.0e - 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 mqtt_host[33]; // 1E9 - Keep together with below as being copied as one chunck with reset 6 + uint16_t mqtt_port; // 20A - Keep together + char mqtt_client[33]; // 20C - Keep together + char mqtt_user[33]; // 22D - Keep together + char mqtt_pwd[33]; // 24E - Keep together + char mqtt_topic[33]; // 26F - Keep together with above items as being copied as one chunck with reset 6 char button_topic[33]; // 290 char mqtt_grptopic[33]; // 2B1 uint8_t display_model; // 2D2 diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 82c306c90..39f180c0b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2082,31 +2082,26 @@ void Every250mSeconds(void) } if (restart_flag && (backlog_pointer == backlog_index)) { if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) { - char storage[sizeof(Settings.sta_ssid) + sizeof(Settings.sta_pwd)]; - char storage_mqtt_host[sizeof(Settings.mqtt_host)]; - uint16_t storage_mqtt_port; - char storage_mqtt_user[sizeof(Settings.mqtt_user)]; - char storage_mqtt_pwd[sizeof(Settings.mqtt_pwd)]; - char storage_mqtt_topic[sizeof(Settings.mqtt_topic)]; - memcpy(storage, Settings.sta_ssid, sizeof(storage)); // Backup current SSIDs and Passwords + char storage_wifi[sizeof(Settings.sta_ssid) + + sizeof(Settings.sta_pwd)]; + char storage_mqtt[sizeof(Settings.mqtt_host) + + sizeof(Settings.mqtt_port) + + sizeof(Settings.mqtt_client) + + sizeof(Settings.mqtt_user) + + sizeof(Settings.mqtt_pwd) + + sizeof(Settings.mqtt_topic)]; + memcpy(storage_wifi, Settings.sta_ssid, sizeof(storage_wifi)); // Backup current SSIDs and Passwords if (216 == restart_flag) { - memcpy(storage_mqtt_host, Settings.mqtt_host, sizeof(Settings.mqtt_host)); - storage_mqtt_port = Settings.mqtt_port; - memcpy(storage_mqtt_user, Settings.mqtt_user, sizeof(Settings.mqtt_user)); - memcpy(storage_mqtt_pwd, Settings.mqtt_pwd, sizeof(Settings.mqtt_pwd)); - memcpy(storage_mqtt_topic, Settings.mqtt_topic, sizeof(Settings.mqtt_topic)); + memcpy(storage_mqtt, Settings.mqtt_host, sizeof(storage_mqtt)); // Backup mqtt host, port, client, username and password } if ((215 == restart_flag) || (216 == restart_flag)) { SettingsErase(0); // Erase all flash from program end to end of physical flash } SettingsDefault(); - memcpy(Settings.sta_ssid, storage, sizeof(storage)); // Restore current SSIDs and Passwords - if (216 == restart_flag) { // Restore the mqtt host, port, username and password - memcpy(Settings.mqtt_host, storage_mqtt_host, sizeof(Settings.mqtt_host)); - Settings.mqtt_port = storage_mqtt_port; - memcpy(Settings.mqtt_user, storage_mqtt_user, sizeof(Settings.mqtt_user)); - memcpy(Settings.mqtt_pwd, storage_mqtt_pwd, sizeof(Settings.mqtt_pwd)); - memcpy(Settings.mqtt_topic, storage_mqtt_topic, sizeof(Settings.mqtt_topic)); + memcpy(Settings.sta_ssid, storage_wifi, sizeof(storage_wifi)); // Restore current SSIDs and Passwords + if (216 == restart_flag) { + memcpy(Settings.mqtt_host, storage_mqtt, sizeof(storage_mqtt)); // Restore the mqtt host, port, client, username and password + strlcpy(Settings.mqtt_client, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)); // Set client to default } restart_flag = 2; } diff --git a/sonoff/support.ino b/sonoff/support.ino index fc2a3d853..e6068fb77 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1278,7 +1278,7 @@ void AddLog_P2(uint8_t loglevel, PGM_P formatP, ...) { va_list arg; va_start(arg, formatP); - int len = vsnprintf_P(log_data, sizeof(log_data), formatP, arg); + vsnprintf_P(log_data, sizeof(log_data), formatP, arg); va_end(arg); AddLog(loglevel); diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 9d96c480c..f243b1b11 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -272,7 +272,7 @@ const char HTTP_HEAD_STYLE3[] PROGMEM = #else "

%s " D_MODULE "

" #endif - "

%s

%s"; + "

%s

"; const char HTTP_MSG_SLIDER1[] PROGMEM = "
" D_COLDLIGHT "" D_WARMLIGHT "
" @@ -566,27 +566,6 @@ bool HttpCheckPriviledgedAccess(bool autorequestauth = true) return true; } -String WSNetworkInfo(void) -{ - String info = ""; - if (Settings.flag3.gui_hostname_ip) { - uint8_t more_ips = 0; - info += F("

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

"); - } - return info; -} - void WSHeaderSend(void) { WebServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate")); @@ -701,7 +680,18 @@ void WSContentSendStyle_P(const char* style) WSContentSend_P(HTTP_HEAD_STYLE1); WSContentSend_P(HTTP_HEAD_STYLE2); WSContentSend_P(style); - WSContentSend_P(HTTP_HEAD_STYLE3, ModuleName().c_str(), Settings.friendlyname[0], WSNetworkInfo().c_str()); + WSContentSend_P(HTTP_HEAD_STYLE3, ModuleName().c_str(), Settings.friendlyname[0]); + if (Settings.flag3.gui_hostname_ip) { + bool lip = (static_cast(WiFi.localIP()) != 0); + bool sip = (static_cast(WiFi.softAPIP()) != 0); + WSContentSend_P(PSTR("

%s%s (%s%s%s)

"), // sonoff.local (192.168.2.12,192.168.4.1) + my_hostname, + (mdns_begun) ? ".local" : "", + (lip) ? WiFi.localIP().toString().c_str() : "", + (lip && sip) ? "," : "", + (sip) ? WiFi.softAPIP().toString().c_str() : ""); + } + WSContentSend_P(PSTR("")); } void WSContentSendStyle(void) @@ -812,7 +802,7 @@ void HandleRoot(void) if ((Settings.web_password[0] != 0) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != webserver_state) { HandleWifiLogin(); } else { - if (!(Settings.web_password[0] != 0) || ((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == Settings.web_password ) || HTTP_MANAGER_RESET_ONLY == webserver_state)) { + if (!(Settings.web_password[0] != 0) || (((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == Settings.web_password )) || HTTP_MANAGER_RESET_ONLY == webserver_state)) { HandleWifiConfiguration(); } else { // wrong user and pass diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 5998b3585..639c74499 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -166,7 +166,7 @@ static void Shorten(char** s, char *prefix) } } -int try_snprintf_P(char *s, size_t n, const char *format, ... ) +void try_snprintf_P(char *s, int n, const char *format, ... ) { va_list args; va_start(args, format); From 398d21cc14592ae4c1c9b7b9cef01ffcf34ccc47 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Thu, 14 Mar 2019 18:29:09 +0100 Subject: [PATCH 1152/2222] decode-config.py: adapt settings - add SetOption62 (no_hold_retain) --- tools/decode-config.py | 8 +++++++- tools/decode-status.py | 0 2 files changed, 7 insertions(+), 1 deletion(-) mode change 100644 => 100755 tools/decode-status.py diff --git a/tools/decode-config.py b/tools/decode-config.py index 0b76ece85..feec178cf 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0021' +VER = '2.1.0022' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -873,7 +873,13 @@ Setting_6_4_1_16.update({ Setting_6_4_1_17 = copy.deepcopy(Setting_6_4_1_16) Setting_6_4_1_17['flag3'][0].pop('no_pullup',None) # ====================================================================== +Setting_6_4_1_18 = copy.deepcopy(Setting_6_4_1_17) +Setting_6_4_1_18['flag3'][0].update ({ + 'no_hold_retain': (' Date: Thu, 14 Mar 2019 22:05:07 -0300 Subject: [PATCH 1153/2222] Fix compiling issue Deleted and extra " that prevents compiling. --- sonoff/language/he-HE.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 2a876d2b0..8ce1a3a78 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -62,7 +62,7 @@ #define D_BRIGHTLIGHT "בהירות" #define D_BSSID "BSSId" #define D_BUTTON "לחצן" -#define D_BY "ע"י" // Written by me +#define D_BY "ע" // Written by me #define D_BYTES "בייט" #define D_CELSIUS "צלזיוס" #define D_CHANNEL "ערוץ" From 798b8b73e0361353c74b28024497dff702b3d43d Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 15 Mar 2019 09:30:59 +0100 Subject: [PATCH 1154/2222] nonos-sdk 22x as default for [core_stage] Using for core stage latest updated nonos sdk 22x --- platformio.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platformio.ini b/platformio.ini index b12b3ad00..5c52af18b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -89,6 +89,10 @@ build_flags = ${esp82xx_defaults.build_flags} platform = https://github.com/platformio/platform-espressif8266.git#feature/stage build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld +; nonos-sdk 22x + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x +; nonos-sdk-pre-v3 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 ; lwIP 1.4 (Default) ; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH ; lwIP 2 - Low Memory From ef5377e3274c1beea1773e34adbb4960d38229d3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 15 Mar 2019 11:25:02 +0100 Subject: [PATCH 1155/2222] Workaround NeoPixelBus STAGE compile error Workaround NeoPixelBus STAGE compile error --- .../src/internal/NeoEsp8266DmaMethod.h | 16 ++++++++++------ platformio.ini | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266DmaMethod.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266DmaMethod.h index af11e1a7a..dc4dd2723 100644 --- a/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266DmaMethod.h +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266DmaMethod.h @@ -48,7 +48,11 @@ extern "C" #include "ets_sys.h" #include "user_interface.h" +// Workaround STAGE compile error +#include +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) void rom_i2c_writeReg_Mask(uint32_t block, uint32_t host_id, uint32_t reg_add, uint32_t Msb, uint32_t Lsb, uint32_t indata); +#endif } struct slc_queue_item @@ -74,7 +78,7 @@ public: class NeoEsp8266DmaSpeed800Kbps { public: - const static uint32_t I2sClockDivisor = 3; + const static uint32_t I2sClockDivisor = 3; const static uint32_t I2sBaseClockDivisor = 16; const static uint32_t ResetTimeUs = 50; }; @@ -82,7 +86,7 @@ public: class NeoEsp8266DmaSpeed400Kbps { public: - const static uint32_t I2sClockDivisor = 6; + const static uint32_t I2sClockDivisor = 6; const static uint32_t I2sBaseClockDivisor = 16; const static uint32_t ResetTimeUs = 50; }; @@ -100,7 +104,7 @@ const uint8_t c_I2sPin = 3; // due to I2S hardware, the pin used is restricted t template class NeoEsp8266DmaMethodBase { public: - NeoEsp8266DmaMethodBase(uint16_t pixelCount, size_t elementSize) + NeoEsp8266DmaMethodBase(uint16_t pixelCount, size_t elementSize) { uint16_t dmaPixelSize = c_dmaBytesPerPixelBytes * elementSize; @@ -269,7 +273,7 @@ public: private: static NeoEsp8266DmaMethodBase* s_this; // for the ISR - size_t _pixelsSize; // Size of '_pixels' buffer + size_t _pixelsSize; // Size of '_pixels' buffer uint8_t* _pixels; // Holds LED color values uint32_t _i2sBufferSize; // total size of _i2sBuffer @@ -310,7 +314,7 @@ private: slc_queue_item* finished_item = (slc_queue_item*)SLCRXEDA; // data block has pending data waiting to send, prepare it - // point last state block to top + // point last state block to top (finished_item + 1)->next_link_ptr = (uint32_t)(s_this->_i2sBufDesc); s_this->_dmaState = NeoDmaState_Sending; @@ -367,7 +371,7 @@ private: } }; -template +template NeoEsp8266DmaMethodBase* NeoEsp8266DmaMethodBase::s_this; typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaWs2813Method; diff --git a/platformio.ini b/platformio.ini index 5c52af18b..671a6f284 100644 --- a/platformio.ini +++ b/platformio.ini @@ -90,7 +90,7 @@ platform = https://github.com/platformio/platform-espressif8266 build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld ; nonos-sdk 22x - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x ; nonos-sdk-pre-v3 ; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 ; lwIP 1.4 (Default) From 3dbd49f9b72f2b03673fb1f5299fdddcb4a7d8ce Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 15 Mar 2019 14:10:42 +0100 Subject: [PATCH 1156/2222] Update GUI template screen Update GUI template screen --- sonoff/xdrv_01_webserver.ino | 18 ++++++++++-------- sonoff/xdrv_07_domoticz.ino | 1 - 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index f243b1b11..d8ab7b56e 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -294,9 +294,7 @@ const char HTTP_FORM_LOGIN[] PROGMEM = const char HTTP_FORM_TEMPLATE[] PROGMEM = "
 " D_TEMPLATE_PARAMETERS " " - "
" - "

" D_TEMPLATE_NAME "

" - "

" D_BASE_TYPE "

"; + ""; const char HTTP_FORM_TEMPLATE_FLAG[] PROGMEM = "

" // Keep close so do not use
"
 " D_TEMPLATE_FLAGS " 

" @@ -1063,16 +1061,20 @@ void HandleTemplateConfiguration(void) WSContentSend_P(HTTP_SCRIPT_TEMPLATE); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_TEMPLATE); - - WSContentSend_P(PSTR("
")); + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("" + "" + "
" D_TEMPLATE_NAME "
" D_BASE_TYPE "
" + "


")); + WSContentSend_P(HTTP_TABLE100); for (uint8_t i = 0; i < 17; i++) { if ((i < 6) || ((i > 8) && (i != 11))) { // Ignore flash pins GPIO06, 7, 8 and 11 - WSContentSend_P(PSTR("" D_GPIO "%d%s"), - (0==i)?" style='width:74px'":"", i, ((9==i)||(10==i))? "ESP8285" :"", (0==i)?" style='width:176px'":"", i, i); + bool esp8285 = ((9==i)||(10==i)); + WSContentSend_P(PSTR("%s" D_GPIO "%d%s"), + (esp8285) ? "" : "", i, (esp8285) ? "" : "", (0==i) ? " style='width:200px'" : "", i, i); } } WSContentSend_P(PSTR("")); - WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 0bd275d7c..c2020176d 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -434,7 +434,6 @@ const char HTTP_BTN_MENU_DOMOTICZ[] PROGMEM = const char HTTP_FORM_DOMOTICZ[] PROGMEM = "
 " D_DOMOTICZ_PARAMETERS " " "" - "
" ""; const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM = "" From ca5c3d1eeb852a8631035b49e93499fc868585a7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 15 Mar 2019 14:29:47 +0100 Subject: [PATCH 1157/2222] 6.4.2.22 Remove support for MQTT_LIBRARY_TYPE 6.4.2.22 20190315 * Remove support for MQTT_LIBRARY_TYPE, MQTT_ARDUINOMQTT and MQTT_TASMOTAMQTT (#5474) --- lib/TasmotaMqtt-1.1.1/.gitignore | 28 - lib/TasmotaMqtt-1.1.1/README.md | 8 - .../examples/mqtt_pub/mqtt_pub.ino | 102 -- .../examples/mqtt_sub/mqtt_sub.ino | 97 -- lib/TasmotaMqtt-1.1.1/keywords.txt | 39 - lib/TasmotaMqtt-1.1.1/library.properties | 9 - lib/TasmotaMqtt-1.1.1/src/TasmotaMqtt.cpp | 194 ---- lib/TasmotaMqtt-1.1.1/src/TasmotaMqtt.h | 88 -- lib/TasmotaMqtt-1.1.1/src/mqtt/debug.h | 19 - lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt.c | 997 ------------------ lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt.h | 148 --- lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt_msg.c | 487 --------- lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt_msg.h | 141 --- lib/TasmotaMqtt-1.1.1/src/mqtt/proto.c | 129 --- lib/TasmotaMqtt-1.1.1/src/mqtt/proto.h | 32 - lib/TasmotaMqtt-1.1.1/src/mqtt/queue.c | 75 -- lib/TasmotaMqtt-1.1.1/src/mqtt/queue.h | 44 - lib/TasmotaMqtt-1.1.1/src/mqtt/ringbuf.c | 67 -- lib/TasmotaMqtt-1.1.1/src/mqtt/ringbuf.h | 19 - lib/TasmotaMqtt-1.1.1/src/mqtt/typedef.h | 17 - lib/TasmotaMqtt-1.1.1/src/mqtt/user_config.h | 15 - lib/TasmotaMqtt-1.1.1/src/mqtt/utils.c | 149 --- lib/TasmotaMqtt-1.1.1/src/mqtt/utils.h | 9 - lib/arduino-mqtt-2.4.0/.editorconfig | 7 - lib/arduino-mqtt-2.4.0/.gitignore | 2 - lib/arduino-mqtt-2.4.0/.travis.yml | 46 - lib/arduino-mqtt-2.4.0/CMakeLists.txt | 38 - lib/arduino-mqtt-2.4.0/LICENSE.md | 21 - lib/arduino-mqtt-2.4.0/Makefile | 14 - lib/arduino-mqtt-2.4.0/README.md | 226 ---- .../AdafruitHuzzahESP8266.ino | 69 -- .../AdafruitHuzzahESP8266Secure.ino | 71 -- .../ArduinoEthernetShield.ino | 62 -- .../ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino | 84 -- .../ArduinoMKRGSM1400Secure.ino | 86 -- .../ArduinoWiFi101/ArduinoWiFi101.ino | 70 -- .../ArduinoWiFi101Secure.ino | 75 -- .../ArduinoWiFiShield/ArduinoWiFiShield.ino | 68 -- .../examples/ArduinoYun/ArduinoYun.ino | 60 -- .../ArduinoYunSecure/ArduinoYunSecure.ino | 62 -- .../ESP32DevelopmentBoard.ino | 69 -- .../ESP32DevelopmentBoardSecure.ino | 71 -- lib/arduino-mqtt-2.4.0/library.properties | 9 - lib/arduino-mqtt-2.4.0/src/MQTT.h | 6 - lib/arduino-mqtt-2.4.0/src/MQTTClient.h | 491 --------- lib/arduino-mqtt-2.4.0/src/lwmqtt/client.c | 618 ----------- lib/arduino-mqtt-2.4.0/src/lwmqtt/helpers.c | 249 ----- lib/arduino-mqtt-2.4.0/src/lwmqtt/helpers.h | 137 --- lib/arduino-mqtt-2.4.0/src/lwmqtt/lwmqtt.h | 381 ------- lib/arduino-mqtt-2.4.0/src/lwmqtt/packet.c | 742 ------------- lib/arduino-mqtt-2.4.0/src/lwmqtt/packet.h | 185 ---- lib/arduino-mqtt-2.4.0/src/lwmqtt/string.c | 38 - sonoff/_changelog.ino | 5 +- sonoff/my_user_config.h | 12 +- sonoff/sonoff.ino | 4 +- sonoff/sonoff_post.h | 2 - sonoff/sonoff_version.h | 2 +- sonoff/support_features.ino | 6 +- sonoff/xdrv_02_mqtt.ino | 157 --- 59 files changed, 11 insertions(+), 7147 deletions(-) delete mode 100644 lib/TasmotaMqtt-1.1.1/.gitignore delete mode 100644 lib/TasmotaMqtt-1.1.1/README.md delete mode 100644 lib/TasmotaMqtt-1.1.1/examples/mqtt_pub/mqtt_pub.ino delete mode 100644 lib/TasmotaMqtt-1.1.1/examples/mqtt_sub/mqtt_sub.ino delete mode 100644 lib/TasmotaMqtt-1.1.1/keywords.txt delete mode 100644 lib/TasmotaMqtt-1.1.1/library.properties delete mode 100644 lib/TasmotaMqtt-1.1.1/src/TasmotaMqtt.cpp delete mode 100644 lib/TasmotaMqtt-1.1.1/src/TasmotaMqtt.h delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/debug.h delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt.c delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt.h delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt_msg.c delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt_msg.h delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/proto.c delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/proto.h delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/queue.c delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/queue.h delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/ringbuf.c delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/ringbuf.h delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/typedef.h delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/user_config.h delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/utils.c delete mode 100644 lib/TasmotaMqtt-1.1.1/src/mqtt/utils.h delete mode 100644 lib/arduino-mqtt-2.4.0/.editorconfig delete mode 100644 lib/arduino-mqtt-2.4.0/.gitignore delete mode 100644 lib/arduino-mqtt-2.4.0/.travis.yml delete mode 100644 lib/arduino-mqtt-2.4.0/CMakeLists.txt delete mode 100644 lib/arduino-mqtt-2.4.0/LICENSE.md delete mode 100644 lib/arduino-mqtt-2.4.0/Makefile delete mode 100644 lib/arduino-mqtt-2.4.0/README.md delete mode 100644 lib/arduino-mqtt-2.4.0/examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino delete mode 100644 lib/arduino-mqtt-2.4.0/examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino delete mode 100644 lib/arduino-mqtt-2.4.0/examples/ArduinoEthernetShield/ArduinoEthernetShield.ino delete mode 100644 lib/arduino-mqtt-2.4.0/examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino delete mode 100644 lib/arduino-mqtt-2.4.0/examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino delete mode 100644 lib/arduino-mqtt-2.4.0/examples/ArduinoWiFi101/ArduinoWiFi101.ino delete mode 100644 lib/arduino-mqtt-2.4.0/examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino delete mode 100644 lib/arduino-mqtt-2.4.0/examples/ArduinoWiFiShield/ArduinoWiFiShield.ino delete mode 100644 lib/arduino-mqtt-2.4.0/examples/ArduinoYun/ArduinoYun.ino delete mode 100644 lib/arduino-mqtt-2.4.0/examples/ArduinoYunSecure/ArduinoYunSecure.ino delete mode 100644 lib/arduino-mqtt-2.4.0/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino delete mode 100644 lib/arduino-mqtt-2.4.0/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino delete mode 100644 lib/arduino-mqtt-2.4.0/library.properties delete mode 100644 lib/arduino-mqtt-2.4.0/src/MQTT.h delete mode 100644 lib/arduino-mqtt-2.4.0/src/MQTTClient.h delete mode 100644 lib/arduino-mqtt-2.4.0/src/lwmqtt/client.c delete mode 100644 lib/arduino-mqtt-2.4.0/src/lwmqtt/helpers.c delete mode 100644 lib/arduino-mqtt-2.4.0/src/lwmqtt/helpers.h delete mode 100644 lib/arduino-mqtt-2.4.0/src/lwmqtt/lwmqtt.h delete mode 100644 lib/arduino-mqtt-2.4.0/src/lwmqtt/packet.c delete mode 100644 lib/arduino-mqtt-2.4.0/src/lwmqtt/packet.h delete mode 100644 lib/arduino-mqtt-2.4.0/src/lwmqtt/string.c diff --git a/lib/TasmotaMqtt-1.1.1/.gitignore b/lib/TasmotaMqtt-1.1.1/.gitignore deleted file mode 100644 index 2ee75414c..000000000 --- a/lib/TasmotaMqtt-1.1.1/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -# C++ objects and libs - -*.slo -*.lo -*.o -#*.a -*.la -*.lai -*.so -*.dll -*.dylib - -#Makefile -*-build-* -build-* -*.autosave - -# .log files (usually created by QtTest - thanks to VestniK) -*.log - - -# Editors temporary files -*~ - - -#OSX -.DS_Store -._* diff --git a/lib/TasmotaMqtt-1.1.1/README.md b/lib/TasmotaMqtt-1.1.1/README.md deleted file mode 100644 index db197299e..000000000 --- a/lib/TasmotaMqtt-1.1.1/README.md +++ /dev/null @@ -1,8 +0,0 @@ -MQTT -==== - -A Wrapper around mqtt for Arduino to be used with esp8266 modules. - -It wraps a slightly modified version of mqtt for esp8266 ported by Tuan PM. -Original code for esp: https://github.com/tuanpmt/esp_mqtt -Original code for contiki: https://github.com/esar/contiki-mqtt diff --git a/lib/TasmotaMqtt-1.1.1/examples/mqtt_pub/mqtt_pub.ino b/lib/TasmotaMqtt-1.1.1/examples/mqtt_pub/mqtt_pub.ino deleted file mode 100644 index 17b3be8db..000000000 --- a/lib/TasmotaMqtt-1.1.1/examples/mqtt_pub/mqtt_pub.ino +++ /dev/null @@ -1,102 +0,0 @@ -#include -#include - -void myDataCb(String& topic, String& data); -void myPublishedCb(); -void myDisconnectedCb(); -void myConnectedCb(); - -#define CLIENT_ID "client1" - -// create MQTT object -MQTT myMqtt(CLIENT_ID, "192.168.0.1", 1883); - -// -const char* ssid = "ssid"; -const char* password = "ssid_password"; - - -// -void setup() { - Serial.begin(115200); - delay(1000); - - Serial.println(); - Serial.println(); - Serial.print("Connecting to "); - Serial.println(ssid); - - WiFi.begin(ssid, password); - - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - } - - Serial.println(""); - Serial.println("WiFi connected"); - Serial.println("IP address: "); - Serial.println(WiFi.localIP()); - - Serial.println("Connecting to MQTT server"); - - // setup callbacks - myMqtt.onConnected(myConnectedCb); - myMqtt.onDisconnected(myDisconnectedCb); - myMqtt.onPublished(myPublishedCb); - myMqtt.onData(myDataCb); - - Serial.println("connect mqtt..."); - myMqtt.connect(); - - delay(10); -} - -// -void loop() { - - int value = analogRead(A0); - - String topic("/"); - topic += CLIENT_ID; - topic += "/value"; - - String valueStr(value); - - // publish value to topic - boolean result = myMqtt.publish(topic, valueStr); - - delay(1000); -} - - -/* - * - */ -void myConnectedCb() -{ - Serial.println("connected to MQTT server"); -} - -void myDisconnectedCb() -{ - Serial.println("disconnected. try to reconnect..."); - delay(500); - myMqtt.connect(); -} - -void myPublishedCb() -{ - //Serial.println("published."); -} - -void myDataCb(String& topic, String& data) -{ - - Serial.print(topic); - Serial.print(": "); - Serial.println(data); -} - - - diff --git a/lib/TasmotaMqtt-1.1.1/examples/mqtt_sub/mqtt_sub.ino b/lib/TasmotaMqtt-1.1.1/examples/mqtt_sub/mqtt_sub.ino deleted file mode 100644 index e88e0a7bb..000000000 --- a/lib/TasmotaMqtt-1.1.1/examples/mqtt_sub/mqtt_sub.ino +++ /dev/null @@ -1,97 +0,0 @@ -#include -#include - -// This needs testing - -void myDataCb(char* topic, uint8_t* data, unsigned int data_len); -void myPublishedCb(); -void myDisconnectedCb(); -void myConnectedCb(); - -#define CLIENT_ID "client3" -#define TOPIC "/client1/value" - -// create MQTT -TasmotaMqtt myMqtt(); - -const char* ssid = "ssid"; -const char* password = "ssid_password"; - -// -void setup() { - Serial.begin(115200); - delay(1000); - - Serial.println(); - Serial.println(); - Serial.print("Connecting to "); - Serial.println(ssid); - - WiFi.begin(ssid, password); - - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - } - - Serial.println(""); - Serial.println("WiFi connected"); - Serial.println("IP address: "); - Serial.println(WiFi.localIP()); - - - Serial.println("Connecting to MQTT server"); - - myMqtt.InitConnection("192.168.0.1", 1883); - myMqtt.InitClient(CLIENT_ID, "", ""); - myMqtt.InitLWT("/lwt", "offline"); - - // setup callbacks - myMqtt.OnConnected(myConnectedCb); - myMqtt.OnDisconnected(myDisconnectedCb); - myMqtt.OnPublished(myPublishedCb); - myMqtt.OnData(myDataCb); - - Serial.println("connect mqtt..."); - myMqtt.Connect(); - - Serial.println("subscribe to topic..."); - myMqtt.Subscribe(TOPIC); - - delay(10); -} - -// -void loop() { -} - - -/* - * - */ -void myConnectedCb() -{ - Serial.println("connected to MQTT server"); -} - -void myDisconnectedCb() -{ - Serial.println("disconnected. try to reconnect..."); - delay(500); - myMqtt.Connect(); -} - -void myPublishedCb() -{ - //Serial.println("published."); -} - -void myDataCb(char* topic, uint8_t* data, unsigned int data_len) -{ - Serial.print(topic); - Serial.print(": "); - Serial.println(data); -} - - - diff --git a/lib/TasmotaMqtt-1.1.1/keywords.txt b/lib/TasmotaMqtt-1.1.1/keywords.txt deleted file mode 100644 index 198919125..000000000 --- a/lib/TasmotaMqtt-1.1.1/keywords.txt +++ /dev/null @@ -1,39 +0,0 @@ -####################################### -# Syntax Coloring Map For Test -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -TasmotaMqtt.h KEYWORD1 -TasmotaMqtt KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -InitConnection KEYWORD2 -InitClient KEYWORD2 -InitLWT KEYWORD2 - -Connect KEYWORD2 -Disconnect KEYWORD2 -Connected KEYWORD2 - -Publish KEYWORD2 -Subscribe KEYWORD2 - -#general -OnConnected KEYWORD2 -OnDisconnected KEYWORD2 -OnData KEYWORD2 - -####################################### -# Instances (KEYWORD2) -####################################### - -####################################### -# Constants (LITERAL1) -####################################### - diff --git a/lib/TasmotaMqtt-1.1.1/library.properties b/lib/TasmotaMqtt-1.1.1/library.properties deleted file mode 100644 index 5a3802f35..000000000 --- a/lib/TasmotaMqtt-1.1.1/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=TasmotaMqtt -version=1.0.0 -author=Theo Arends -maintainer=Theo Arends -sentence=A Wrapper around mqtt for Arduino to be used with esp8266 modules. -paragraph=It wraps a slightly modified version of mqtt for esp8266 ported by Tuan PM. Original code for esp: https://github.com/tuanpmt/esp_mqtt Original code for contiki: https://github.com/esar/contiki-mqtt -category=Communication -url= -architectures=esp8266 \ No newline at end of file diff --git a/lib/TasmotaMqtt-1.1.1/src/TasmotaMqtt.cpp b/lib/TasmotaMqtt-1.1.1/src/TasmotaMqtt.cpp deleted file mode 100644 index 9beddd452..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/TasmotaMqtt.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - TasmotaMqtt.cpp - Wrapper for mqtt for esp8266 by Tuan PM for Tasmota - - Copyright (C) 2018 Theo Arends and Ingo Randolf - - This library 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 . -*/ - -#include "TasmotaMqtt.h" - -#include "user_interface.h" -#include "osapi.h" -#include "os_type.h" - -/*********************************************************************************************\ - * Prerequisite - * - * Copy .c and .h files from https://github.com/tuanpmt/esp_mqtt folder mqtt to folder mqtt - * - Replace BOOL with bool - * - Remove variables certificate and private_key from file mqtt.c - * - Add file user_config.h with default defines for - * MQTT_BUF_SIZE 256, MQTT_RECONNECT_TIMEOUT 5, QUEUE_BUFFER_SIZE 2048 and PROTOCOL_NAMEv311 -\*********************************************************************************************/ - -/*********************************************************************************************\ - * Mqtt internal callbacks -\*********************************************************************************************/ - -static void mqttConnectedCb(uint32_t *args) -{ - MQTT_Client* client = (MQTT_Client*)args; - TasmotaMqtt* _this = (TasmotaMqtt*)client->user_data; - if (_this && _this->onMqttConnectedCb) _this->onMqttConnectedCb(); -} - -static void mqttDisconnectedCb(uint32_t *args) -{ - MQTT_Client* client = (MQTT_Client*)args; - TasmotaMqtt* _this = (TasmotaMqtt*)client->user_data; - if (_this && _this->onMqttDisconnectedCb) _this->onMqttDisconnectedCb(); -} - -static void mqttPublishedCb(uint32_t *args) -{ - MQTT_Client* client = (MQTT_Client*)args; - TasmotaMqtt* _this = (TasmotaMqtt*)client->user_data; - if (_this && _this->onMqttPublishedCb) _this->onMqttPublishedCb(); -} - -static void mqttTimeoutCb(uint32_t *args) -{ - MQTT_Client* client = (MQTT_Client*)args; - TasmotaMqtt* _this = (TasmotaMqtt*)client->user_data; - if (_this && _this->onMqttTimeoutCb) _this->onMqttTimeoutCb(); -} - -static void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len) -{ - MQTT_Client* client = (MQTT_Client*)args; - TasmotaMqtt* _this = (TasmotaMqtt*)client->user_data; - if (_this) _this->_onMqttDataCb(topic, topic_len, data, data_len); -} - -/*********************************************************************************************\ - * TasmotaMqtt class implementation -\*********************************************************************************************/ - -TasmotaMqtt::TasmotaMqtt() : - onMqttConnectedCb(0), - onMqttDisconnectedCb(0), - onMqttPublishedCb(0), - onMqttTimeoutCb(0), - onMqttDataCb(0) -{ -} - -TasmotaMqtt::~TasmotaMqtt() -{ - MQTT_DeleteClient(&mqttClient); -} - -void TasmotaMqtt::InitConnection(const char* host, uint32_t port, uint8_t security) -{ - MQTT_InitConnection(&mqttClient, (uint8_t*)host, port, security); - - // set user data - mqttClient.user_data = (void*)this; - - MQTT_OnConnected(&mqttClient, mqttConnectedCb); - MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb); - MQTT_OnPublished(&mqttClient, mqttPublishedCb); - MQTT_OnTimeout(&mqttClient, mqttTimeoutCb); - MQTT_OnData(&mqttClient, mqttDataCb); -} - -void TasmotaMqtt::InitClient(const char* client_id, const char* client_user, const char* client_pass, uint32_t keep_alive_time, uint8_t clean_session) -{ - MQTT_InitClient(&mqttClient, (uint8_t*)client_id, (uint8_t*)client_user, (uint8_t*)client_pass, keep_alive_time, clean_session); -} - -void TasmotaMqtt::DeleteClient() -{ - MQTT_DeleteClient(&mqttClient); -} - -void TasmotaMqtt::InitLWT(const char* will_topic, const char* will_msg, uint8_t will_qos, bool will_retain) -{ - MQTT_InitLWT(&mqttClient, (uint8_t*)will_topic, (uint8_t*)will_msg, will_qos, (uint8_t)will_retain); -} - -void TasmotaMqtt::OnConnected( void (*function)(void) ) -{ - onMqttConnectedCb = function; -} - -void TasmotaMqtt::OnDisconnected( void (*function)(void) ) -{ - onMqttDisconnectedCb = function; -} - -void TasmotaMqtt::OnPublished( void (*function)(void) ) -{ - onMqttPublishedCb = function; -} - -void TasmotaMqtt::OnTimeout( void (*function)(void) ) -{ - onMqttTimeoutCb = function; -} - -void TasmotaMqtt::OnData( void (*function)(char*, uint8_t*, unsigned int) ) -{ - onMqttDataCb = function; -} - -bool TasmotaMqtt::Subscribe(const char* topic, uint8_t qos) -{ - return MQTT_Subscribe(&mqttClient, (char*)topic, qos); -} - -bool TasmotaMqtt::Unsubscribe(const char* topic) -{ - return MQTT_UnSubscribe(&mqttClient, (char*)topic); -} - -void TasmotaMqtt::Connect() -{ - MQTT_Connect(&mqttClient); -} - -void TasmotaMqtt::Connect(const char* client_id, const char* client_user, const char* client_pass, const char* will_topic, const char* will_msg, uint8_t will_qos, bool will_retain) -{ - MQTT_InitClient(&mqttClient, (uint8_t*)client_id, (uint8_t*)client_user, (uint8_t*)client_pass, MQTT_KEEPALIVE, 1); - MQTT_InitLWT(&mqttClient, (uint8_t*)will_topic, (uint8_t*)will_msg, will_qos, (uint8_t)will_retain); - MQTT_Connect(&mqttClient); -} - -void TasmotaMqtt::Disconnect() -{ - MQTT_Disconnect(&mqttClient); -} - -bool TasmotaMqtt::Publish(const char* topic, const char* data, int data_length, int qos, bool retain) -{ - return MQTT_Publish(&mqttClient, topic, data, data_length, qos, (int)retain); -} - -bool TasmotaMqtt::Connected() -{ - return (mqttClient.connState > TCP_CONNECTED); -} - -/*********************************************************************************************/ - -void TasmotaMqtt::_onMqttDataCb(const char* topic, uint32_t topic_len, const char* data, uint32_t data_len) -{ - char topic_copy[topic_len +1]; - - memcpy(topic_copy, topic, topic_len); - topic_copy[topic_len] = 0; - if (0 == data_len) data = (const char*)&topic_copy + topic_len; - onMqttDataCb((char*)topic_copy, (byte*)data, data_len); -} diff --git a/lib/TasmotaMqtt-1.1.1/src/TasmotaMqtt.h b/lib/TasmotaMqtt-1.1.1/src/TasmotaMqtt.h deleted file mode 100644 index e512d8d5a..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/TasmotaMqtt.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - TasmotaMqtt.h - Wrapper for mqtt for esp8266 by Tuan PM for Tasmota - - Copyright (C) 2018 Theo Arends and Ingo Randolf - - This library 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 TasmotaMqtt_h -#define TasmotaMqtt_h -/*********************************************************************************************\ - * TasmotaMqtt supports currently only non-TLS MQTT - * - * Adapted from esp-mqtt-arduino by Ingo Randolf (https://github.com/i-n-g-o/esp-mqtt-arduino) -\*********************************************************************************************/ - -#include - -#include -#include -#include -#include -#include - -extern "C" { - #include - #include "mqtt/mqtt.h" -} - -// MQTT_KEEPALIVE : keepAlive interval in Seconds -#ifndef MQTT_KEEPALIVE -#define MQTT_KEEPALIVE 15 -#endif - -class TasmotaMqtt { -public: - TasmotaMqtt(); - ~TasmotaMqtt(); - - void InitConnection(const char* host, uint32_t port, uint8_t security = 0); - void InitClient(const char* client_id, const char* client_user, const char* client_pass, uint32_t keep_alive_time = MQTT_KEEPALIVE, uint8_t clean_session = 1); - void DeleteClient(); - void InitLWT(const char* will_topic, const char* will_msg, uint8_t will_qos = 0, bool will_retain = false); - - void OnConnected( void (*)(void) ); - void OnDisconnected( void (*)(void) ); - void OnPublished( void (*)(void) ); - void OnTimeout( void (*)(void) ); - void OnData( void (*)(char*, uint8_t*, unsigned int) ); - - bool Subscribe(const char* topic, uint8_t qos = 0); - bool Unsubscribe(const char* topic); - - void Connect(); - void Connect(const char* client_id, const char* client_user, const char* client_pass, const char* will_topic, const char* will_msg, uint8_t will_qos = 0, bool will_retain = false); - void Disconnect(); - - bool Publish(const char* topic, const char* data, int data_length, int qos = 0, bool retain = false); - - bool Connected(); - - int State() { return mqttClient.connState; }; - - void (*onMqttConnectedCb)(void); - void (*onMqttDisconnectedCb)(void); - void (*onMqttPublishedCb)(void); - void (*onMqttTimeoutCb)(void); - void (*onMqttDataCb) (char*, uint8_t*, unsigned int); - - // internal callback - void _onMqttDataCb(const char*, uint32_t, const char*, uint32_t); - -private: - MQTT_Client mqttClient; -}; - -#endif // TasmotaMqtt_h \ No newline at end of file diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/debug.h b/lib/TasmotaMqtt-1.1.1/src/mqtt/debug.h deleted file mode 100644 index f45dd6d8d..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/debug.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * debug.h - * - * Created on: Dec 4, 2014 - * Author: Minh - */ - -#ifndef USER_DEBUG_H_ -#define USER_DEBUG_H_ - - -#if defined(MQTT_DEBUG_ON) -#define MQTT_INFO( format, ... ) os_printf( format, ## __VA_ARGS__ ) -#else -#define MQTT_INFO( format, ... ) -#endif - - -#endif /* USER_DEBUG_H_ */ diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt.c b/lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt.c deleted file mode 100644 index 06609fe4a..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt.c +++ /dev/null @@ -1,997 +0,0 @@ -/* mqtt.c -* Protocol: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html -* -* Copyright (c) 2014-2015, Tuan PM -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* * Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of Redis nor the names of its contributors may be used -* to endorse or promote products derived from this software without -* specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "user_interface.h" -#include "osapi.h" -#include "espconn.h" -#include "os_type.h" -#include "mem.h" -#include "mqtt_msg.h" -#include "debug.h" -#include "user_config.h" -#include "mqtt.h" -#include "queue.h" - -#define MQTT_TASK_PRIO 2 -#define MQTT_TASK_QUEUE_SIZE 1 -#define MQTT_SEND_TIMOUT 5 - -#ifndef MQTT_SSL_SIZE -#define MQTT_SSL_SIZE 5120 -#endif - -#ifndef QUEUE_BUFFER_SIZE -#define QUEUE_BUFFER_SIZE 2048 -#endif - -/* -unsigned char *default_certificate; -unsigned int default_certificate_len = 0; -unsigned char *default_private_key; -unsigned int default_private_key_len = 0; -*/ - -os_event_t mqtt_procTaskQueue[MQTT_TASK_QUEUE_SIZE]; - -#ifdef PROTOCOL_NAMEv311 -LOCAL uint8_t zero_len_id[2] = { 0, 0 }; -#endif - -LOCAL void ICACHE_FLASH_ATTR -mqtt_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) -{ - struct espconn *pConn = (struct espconn *)arg; - MQTT_Client* client = (MQTT_Client *)pConn->reverse; - - - if (ipaddr == NULL) - { - MQTT_INFO("DNS: Found, but got no ip, try to reconnect\r\n"); - client->connState = TCP_RECONNECT_REQ; - return; - } - - MQTT_INFO("DNS: found ip %d.%d.%d.%d\n", - *((uint8 *) &ipaddr->addr), - *((uint8 *) &ipaddr->addr + 1), - *((uint8 *) &ipaddr->addr + 2), - *((uint8 *) &ipaddr->addr + 3)); - - if (client->ip.addr == 0 && ipaddr->addr != 0) - { - os_memcpy(client->pCon->proto.tcp->remote_ip, &ipaddr->addr, 4); - if (client->security) { -#ifdef MQTT_SSL_ENABLE - espconn_secure_set_size(ESPCONN_CLIENT, MQTT_SSL_SIZE); - espconn_secure_connect(client->pCon); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - espconn_connect(client->pCon); - } - - client->connState = TCP_CONNECTING; - MQTT_INFO("TCP: connecting...\r\n"); - } - - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); -} - - - -LOCAL void ICACHE_FLASH_ATTR -deliver_publish(MQTT_Client* client, uint8_t* message, int length) -{ - mqtt_event_data_t event_data; - - event_data.topic_length = length; - event_data.topic = mqtt_get_publish_topic(message, &event_data.topic_length); - event_data.data_length = length; - event_data.data = mqtt_get_publish_data(message, &event_data.data_length); - - if (client->dataCb) - client->dataCb((uint32_t*)client, event_data.topic, event_data.topic_length, event_data.data, event_data.data_length); - -} - -void ICACHE_FLASH_ATTR -mqtt_send_keepalive(MQTT_Client *client) -{ - MQTT_INFO("\r\nMQTT: Send keepalive packet to %s:%d!\r\n", client->host, client->port); - client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection); - client->mqtt_state.pending_msg_type = MQTT_MSG_TYPE_PINGREQ; - client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); - client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); - - - client->sendTimeout = MQTT_SEND_TIMOUT; - MQTT_INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); - err_t result = ESPCONN_OK; - if (client->security) { -#ifdef MQTT_SSL_ENABLE - result = espconn_secure_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - result = espconn_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); - } - - client->mqtt_state.outbound_message = NULL; - if (ESPCONN_OK == result) { - client->keepAliveTick = 0; - client->connState = MQTT_DATA; - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - } - else { - client->connState = TCP_RECONNECT_DISCONNECTING; - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - } -} - -/** - * @brief Delete tcp client and free all memory - * @param mqttClient: The mqtt client which contain TCP client - * @retval None - */ -void ICACHE_FLASH_ATTR -mqtt_tcpclient_delete(MQTT_Client *mqttClient) -{ - if (mqttClient->pCon != NULL) { - MQTT_INFO("TCP: Free memory\r\n"); - // Force abort connections - espconn_abort(mqttClient->pCon); - // Delete connections - espconn_delete(mqttClient->pCon); - - if (mqttClient->pCon->proto.tcp) { - os_free(mqttClient->pCon->proto.tcp); - mqttClient->pCon->proto.tcp = NULL; - } - os_free(mqttClient->pCon); - mqttClient->pCon = NULL; - } -} - -/** - * @brief Delete MQTT client and free all memory - * @param mqttClient: The mqtt client - * @retval None - */ -void ICACHE_FLASH_ATTR -mqtt_client_delete(MQTT_Client *mqttClient) -{ - if (mqttClient == NULL) - return; - - if (mqttClient->pCon != NULL) { - mqtt_tcpclient_delete(mqttClient); - } - - if (mqttClient->host != NULL) { - os_free(mqttClient->host); - mqttClient->host = NULL; - } - - if (mqttClient->user_data != NULL) { - os_free(mqttClient->user_data); - mqttClient->user_data = NULL; - } - - if (mqttClient->mqtt_state.in_buffer != NULL) { - os_free(mqttClient->mqtt_state.in_buffer); - mqttClient->mqtt_state.in_buffer = NULL; - } - - if (mqttClient->mqtt_state.out_buffer != NULL) { - os_free(mqttClient->mqtt_state.out_buffer); - mqttClient->mqtt_state.out_buffer = NULL; - } - - if (mqttClient->mqtt_state.outbound_message != NULL) { - if (mqttClient->mqtt_state.outbound_message->data != NULL) - { - os_free(mqttClient->mqtt_state.outbound_message->data); - mqttClient->mqtt_state.outbound_message->data = NULL; - } - } - - if (mqttClient->mqtt_state.mqtt_connection.buffer != NULL) { - // Already freed but not NULL - mqttClient->mqtt_state.mqtt_connection.buffer = NULL; - } - - if (mqttClient->connect_info.client_id != NULL) { -#ifdef PROTOCOL_NAMEv311 - /* Don't attempt to free if it's the zero_len array */ - if ( ((uint8_t*)mqttClient->connect_info.client_id) != zero_len_id ) - os_free(mqttClient->connect_info.client_id); -#else - os_free(mqttClient->connect_info.client_id); -#endif - mqttClient->connect_info.client_id = NULL; - } - - if (mqttClient->connect_info.username != NULL) { - os_free(mqttClient->connect_info.username); - mqttClient->connect_info.username = NULL; - } - - if (mqttClient->connect_info.password != NULL) { - os_free(mqttClient->connect_info.password); - mqttClient->connect_info.password = NULL; - } - - if (mqttClient->connect_info.will_topic != NULL) { - os_free(mqttClient->connect_info.will_topic); - mqttClient->connect_info.will_topic = NULL; - } - - if (mqttClient->connect_info.will_message != NULL) { - os_free(mqttClient->connect_info.will_message); - mqttClient->connect_info.will_message = NULL; - } - - if (mqttClient->msgQueue.buf != NULL) { - os_free(mqttClient->msgQueue.buf); - mqttClient->msgQueue.buf = NULL; - } - - // Initialize state - mqttClient->connState = WIFI_INIT; - // Clear callback functions to avoid abnormal callback - mqttClient->connectedCb = NULL; - mqttClient->disconnectedCb = NULL; - mqttClient->publishedCb = NULL; - mqttClient->timeoutCb = NULL; - mqttClient->dataCb = NULL; - - MQTT_INFO("MQTT: client already deleted\r\n"); -} - - -/** - * @brief Client received callback function. - * @param arg: contain the ip link information - * @param pdata: received data - * @param len: the lenght of received data - * @retval None - */ -void ICACHE_FLASH_ATTR -mqtt_tcpclient_recv(void *arg, char *pdata, unsigned short len) -{ - uint8_t msg_type; - uint8_t msg_qos; - uint16_t msg_id; - uint8_t msg_conn_ret; - - struct espconn *pCon = (struct espconn*)arg; - MQTT_Client *client = (MQTT_Client *)pCon->reverse; - -READPACKET: - MQTT_INFO("TCP: data received %d bytes\r\n", len); - // MQTT_INFO("STATE: %d\r\n", client->connState); - if (len < MQTT_BUF_SIZE && len > 0) { - os_memcpy(client->mqtt_state.in_buffer, pdata, len); - - msg_type = mqtt_get_type(client->mqtt_state.in_buffer); - msg_qos = mqtt_get_qos(client->mqtt_state.in_buffer); - msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length); - switch (client->connState) { - case MQTT_CONNECT_SENDING: - if (msg_type == MQTT_MSG_TYPE_CONNACK) { - if (client->mqtt_state.pending_msg_type != MQTT_MSG_TYPE_CONNECT) { - MQTT_INFO("MQTT: Invalid packet\r\n"); - if (client->security) { -#ifdef MQTT_SSL_ENABLE - espconn_secure_disconnect(client->pCon); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - espconn_disconnect(client->pCon); - } - } else { - msg_conn_ret = mqtt_get_connect_return_code(client->mqtt_state.in_buffer); - switch (msg_conn_ret) { - case CONNECTION_ACCEPTED: - MQTT_INFO("MQTT: Connected to %s:%d\r\n", client->host, client->port); - client->connState = MQTT_DATA; - if (client->connectedCb) - client->connectedCb((uint32_t*)client); - break; - case CONNECTION_REFUSE_PROTOCOL: - case CONNECTION_REFUSE_SERVER_UNAVAILABLE: - case CONNECTION_REFUSE_BAD_USERNAME: - case CONNECTION_REFUSE_NOT_AUTHORIZED: - MQTT_INFO("MQTT: Connection refuse, reason code: %d\r\n", msg_conn_ret); - default: - if (client->security) { -#ifdef MQTT_SSL_ENABLE - espconn_secure_disconnect(client->pCon); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - espconn_disconnect(client->pCon); - } - - } - - } - - } - break; - case MQTT_DATA: - case MQTT_KEEPALIVE_SEND: - client->mqtt_state.message_length_read = len; - client->mqtt_state.message_length = mqtt_get_total_length(client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); - - - switch (msg_type) - { - - case MQTT_MSG_TYPE_SUBACK: - if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) - MQTT_INFO("MQTT: Subscribe successful\r\n"); - break; - case MQTT_MSG_TYPE_UNSUBACK: - if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) - MQTT_INFO("MQTT: UnSubscribe successful\r\n"); - break; - case MQTT_MSG_TYPE_PUBLISH: - if (msg_qos == 1) - client->mqtt_state.outbound_message = mqtt_msg_puback(&client->mqtt_state.mqtt_connection, msg_id); - else if (msg_qos == 2) - client->mqtt_state.outbound_message = mqtt_msg_pubrec(&client->mqtt_state.mqtt_connection, msg_id); - if (msg_qos == 1 || msg_qos == 2) { - MQTT_INFO("MQTT: Queue response QoS: %d\r\n", msg_qos); - if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - } - } - - deliver_publish(client, client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); - break; - case MQTT_MSG_TYPE_PUBACK: - if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id) { - MQTT_INFO("MQTT: received MQTT_MSG_TYPE_PUBACK, finish QoS1 publish\r\n"); - } - - break; - case MQTT_MSG_TYPE_PUBREC: - client->mqtt_state.outbound_message = mqtt_msg_pubrel(&client->mqtt_state.mqtt_connection, msg_id); - if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - } - break; - case MQTT_MSG_TYPE_PUBREL: - client->mqtt_state.outbound_message = mqtt_msg_pubcomp(&client->mqtt_state.mqtt_connection, msg_id); - if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - } - break; - case MQTT_MSG_TYPE_PUBCOMP: - if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id) { - MQTT_INFO("MQTT: receive MQTT_MSG_TYPE_PUBCOMP, finish QoS2 publish\r\n"); - } - break; - case MQTT_MSG_TYPE_PINGREQ: - client->mqtt_state.outbound_message = mqtt_msg_pingresp(&client->mqtt_state.mqtt_connection); - if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - } - break; - case MQTT_MSG_TYPE_PINGRESP: - // Ignore - break; - } - // NOTE: this is done down here and not in the switch case above - // because the PSOCK_READBUF_LEN() won't work inside a switch - // statement due to the way protothreads resume. - if (msg_type == MQTT_MSG_TYPE_PUBLISH) - { - len = client->mqtt_state.message_length_read; - - if (client->mqtt_state.message_length < client->mqtt_state.message_length_read) - { - //client->connState = MQTT_PUBLISH_RECV; - //Not Implement yet - len -= client->mqtt_state.message_length; - pdata += client->mqtt_state.message_length; - - MQTT_INFO("Get another published message\r\n"); - goto READPACKET; - } - - } - break; - } - } else { - MQTT_INFO("ERROR: Message too long\r\n"); - } - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); -} - -/** - * @brief Client send over callback function. - * @param arg: contain the ip link information - * @retval None - */ -void ICACHE_FLASH_ATTR -mqtt_tcpclient_sent_cb(void *arg) -{ - struct espconn *pCon = (struct espconn *)arg; - MQTT_Client* client = (MQTT_Client *)pCon->reverse; - MQTT_INFO("TCP: Sent\r\n"); - client->sendTimeout = 0; - client->keepAliveTick = 0; - - if ((client->connState == MQTT_DATA || client->connState == MQTT_KEEPALIVE_SEND) - && client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH) { - if (client->publishedCb) - client->publishedCb((uint32_t*)client); - } - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); -} - -void ICACHE_FLASH_ATTR mqtt_timer(void *arg) -{ - MQTT_Client* client = (MQTT_Client*)arg; - - if (client->connState == MQTT_DATA) { - client->keepAliveTick ++; - if (client->keepAliveTick > (client->mqtt_state.connect_info->keepalive / 2)) { - client->connState = MQTT_KEEPALIVE_SEND; - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - } - - } else if (client->connState == TCP_RECONNECT_REQ) { - client->reconnectTick ++; - if (client->reconnectTick > MQTT_RECONNECT_TIMEOUT) { - client->reconnectTick = 0; - client->connState = TCP_RECONNECT; - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - if (client->timeoutCb) - client->timeoutCb((uint32_t*)client); - } - } - if (client->sendTimeout > 0) - client->sendTimeout --; -} - -void ICACHE_FLASH_ATTR -mqtt_tcpclient_discon_cb(void *arg) -{ - - struct espconn *pespconn = (struct espconn *)arg; - MQTT_Client* client = (MQTT_Client *)pespconn->reverse; - MQTT_INFO("TCP: Disconnected callback\r\n"); - if (TCP_DISCONNECTING == client->connState) { - client->connState = TCP_DISCONNECTED; - } - else if (MQTT_DELETING == client->connState) { - client->connState = MQTT_DELETED; - } - else { - client->connState = TCP_RECONNECT_REQ; - } - if (client->disconnectedCb) - client->disconnectedCb((uint32_t*)client); - - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); -} - - - -/** - * @brief Tcp client connect success callback function. - * @param arg: contain the ip link information - * @retval None - */ -void ICACHE_FLASH_ATTR -mqtt_tcpclient_connect_cb(void *arg) -{ - struct espconn *pCon = (struct espconn *)arg; - MQTT_Client* client = (MQTT_Client *)pCon->reverse; - - espconn_regist_disconcb(client->pCon, mqtt_tcpclient_discon_cb); - espconn_regist_recvcb(client->pCon, mqtt_tcpclient_recv);//////// - espconn_regist_sentcb(client->pCon, mqtt_tcpclient_sent_cb);/////// - MQTT_INFO("MQTT: Connected to broker %s:%d\r\n", client->host, client->port); - - mqtt_msg_init(&client->mqtt_state.mqtt_connection, client->mqtt_state.out_buffer, client->mqtt_state.out_buffer_length); - client->mqtt_state.outbound_message = mqtt_msg_connect(&client->mqtt_state.mqtt_connection, client->mqtt_state.connect_info); - client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); - client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); - - - client->sendTimeout = MQTT_SEND_TIMOUT; - MQTT_INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); - if (client->security) { -#ifdef MQTT_SSL_ENABLE - espconn_secure_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - espconn_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); - } - - client->mqtt_state.outbound_message = NULL; - client->connState = MQTT_CONNECT_SENDING; - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); -} - -/** - * @brief Tcp client connect repeat callback function. - * @param arg: contain the ip link information - * @retval None - */ -void ICACHE_FLASH_ATTR -mqtt_tcpclient_recon_cb(void *arg, sint8 errType) -{ - struct espconn *pCon = (struct espconn *)arg; - MQTT_Client* client = (MQTT_Client *)pCon->reverse; - - MQTT_INFO("TCP: Reconnect to %s:%d\r\n", client->host, client->port); - - client->connState = TCP_RECONNECT_REQ; - - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - -} - -/** - * @brief MQTT publish function. - * @param client: MQTT_Client reference - * @param topic: string topic will publish to - * @param data: buffer data send point to - * @param data_length: length of data - * @param qos: qos - * @param retain: retain - * @retval TRUE if success queue - */ -bool ICACHE_FLASH_ATTR -MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain) -{ - uint8_t dataBuffer[MQTT_BUF_SIZE]; - uint16_t dataLen; - client->mqtt_state.outbound_message = mqtt_msg_publish(&client->mqtt_state.mqtt_connection, - topic, data, data_length, - qos, retain, - &client->mqtt_state.pending_msg_id); - if (client->mqtt_state.outbound_message->length == 0) { - MQTT_INFO("MQTT: Queuing publish failed\r\n"); - return FALSE; - } - MQTT_INFO("MQTT: queuing publish, length: %d, queue size(%d/%d)\r\n", client->mqtt_state.outbound_message->length, client->msgQueue.rb.fill_cnt, client->msgQueue.rb.size); - while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) { - MQTT_INFO("MQTT: Serious buffer error\r\n"); - return FALSE; - } - } - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - return TRUE; -} - -/** - * @brief MQTT subscibe function. - * @param client: MQTT_Client reference - * @param topic: string topic will subscribe - * @param qos: qos - * @retval TRUE if success queue - */ -bool ICACHE_FLASH_ATTR -MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos) -{ - uint8_t dataBuffer[MQTT_BUF_SIZE]; - uint16_t dataLen; - - client->mqtt_state.outbound_message = mqtt_msg_subscribe(&client->mqtt_state.mqtt_connection, - topic, qos, - &client->mqtt_state.pending_msg_id); - MQTT_INFO("MQTT: queue subscribe, topic\"%s\", id: %d\r\n", topic, client->mqtt_state.pending_msg_id); - while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) { - MQTT_INFO("MQTT: Serious buffer error\r\n"); - return FALSE; - } - } - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - - return TRUE; -} - -/** - * @brief MQTT un-subscibe function. - * @param client: MQTT_Client reference - * @param topic: String topic will un-subscribe - * @retval TRUE if success queue - */ -bool ICACHE_FLASH_ATTR -MQTT_UnSubscribe(MQTT_Client *client, char* topic) -{ - uint8_t dataBuffer[MQTT_BUF_SIZE]; - uint16_t dataLen; - client->mqtt_state.outbound_message = mqtt_msg_unsubscribe(&client->mqtt_state.mqtt_connection, - topic, - &client->mqtt_state.pending_msg_id); - MQTT_INFO("MQTT: queue un-subscribe, topic\"%s\", id: %d\r\n", topic, client->mqtt_state.pending_msg_id); - while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) { - MQTT_INFO("MQTT: Serious buffer error\r\n"); - return FALSE; - } - } - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - return TRUE; -} - -/** - * @brief MQTT ping function. - * @param client: MQTT_Client reference - * @retval TRUE if success queue - */ -bool ICACHE_FLASH_ATTR -MQTT_Ping(MQTT_Client *client) -{ - uint8_t dataBuffer[MQTT_BUF_SIZE]; - uint16_t dataLen; - client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection); - if (client->mqtt_state.outbound_message->length == 0) { - MQTT_INFO("MQTT: Queuing publish failed\r\n"); - return FALSE; - } - MQTT_INFO("MQTT: queuing publish, length: %d, queue size(%d/%d)\r\n", client->mqtt_state.outbound_message->length, client->msgQueue.rb.fill_cnt, client->msgQueue.rb.size); - while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - MQTT_INFO("MQTT: Queue full\r\n"); - if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) { - MQTT_INFO("MQTT: Serious buffer error\r\n"); - return FALSE; - } - } - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); - return TRUE; -} - -void ICACHE_FLASH_ATTR -MQTT_Task(os_event_t *e) -{ - MQTT_Client* client = (MQTT_Client*)e->par; - uint8_t dataBuffer[MQTT_BUF_SIZE]; - uint16_t dataLen; - if (e->par == 0) - return; - switch (client->connState) { - - case TCP_RECONNECT_REQ: - break; - case TCP_RECONNECT: - mqtt_tcpclient_delete(client); - MQTT_Connect(client); - MQTT_INFO("TCP: Reconnect to: %s:%d\r\n", client->host, client->port); - client->connState = TCP_CONNECTING; - break; - case MQTT_DELETING: - case TCP_DISCONNECTING: - case TCP_RECONNECT_DISCONNECTING: - if (client->security) { -#ifdef MQTT_SSL_ENABLE - espconn_secure_disconnect(client->pCon); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - espconn_disconnect(client->pCon); - } - break; - case TCP_DISCONNECTED: - MQTT_INFO("MQTT: Disconnected\r\n"); - mqtt_tcpclient_delete(client); - break; - case MQTT_DELETED: - MQTT_INFO("MQTT: Deleted client\r\n"); - mqtt_client_delete(client); - break; - case MQTT_KEEPALIVE_SEND: - mqtt_send_keepalive(client); - break; - case MQTT_DATA: - if (QUEUE_IsEmpty(&client->msgQueue) || client->sendTimeout != 0) { - break; - } - if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == 0) { - client->mqtt_state.pending_msg_type = mqtt_get_type(dataBuffer); - client->mqtt_state.pending_msg_id = mqtt_get_id(dataBuffer, dataLen); - - - client->sendTimeout = MQTT_SEND_TIMOUT; - MQTT_INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); - client->keepAliveTick = 0; - if (client->security) { -#ifdef MQTT_SSL_ENABLE - espconn_secure_send(client->pCon, dataBuffer, dataLen); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else { - espconn_send(client->pCon, dataBuffer, dataLen); - } - - client->mqtt_state.outbound_message = NULL; - break; - } - break; - } -} - -/** - * @brief MQTT initialization connection function - * @param client: MQTT_Client reference - * @param host: Domain or IP string - * @param port: Port to connect - * @param security: 1 for ssl, 0 for none - * @retval None - */ -void ICACHE_FLASH_ATTR -MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security) -{ - uint32_t temp; - MQTT_INFO("MQTT:InitConnection\r\n"); - os_memset(mqttClient, 0, sizeof(MQTT_Client)); - temp = os_strlen(host); - mqttClient->host = (uint8_t*)os_zalloc(temp + 1); - os_strcpy(mqttClient->host, host); - mqttClient->host[temp] = 0; - mqttClient->port = port; - mqttClient->security = security; - -} - -/** - * @brief MQTT initialization mqtt client function - * @param client: MQTT_Client reference - * @param clientid: MQTT client id - * @param client_user:MQTT client user - * @param client_pass:MQTT client password - * @param client_pass:MQTT keep alive timer, in second - * @retval None - */ -bool ICACHE_FLASH_ATTR -MQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession) -{ - uint32_t temp; - MQTT_INFO("MQTT:InitClient\r\n"); - - os_memset(&mqttClient->connect_info, 0, sizeof(mqtt_connect_info_t)); - - if ( !client_id ) - { - /* Should be allowed by broker, but clean session flag must be set. */ - #ifdef PROTOCOL_NAMEv311 - if (cleanSession) - { - mqttClient->connect_info.client_id = zero_len_id; - } else { - MQTT_INFO("cleanSession must be set to use 0 length client_id\r\n"); - return false; - } - /* Not supported. Return. */ - #else - MQTT_INFO("Client ID required for MQTT < 3.1.1!\r\n"); - return false; - #endif - } - - /* If connect_info's client_id is still NULL and we get here, we can * - * assume the passed client_id is non-NULL. */ - if ( !(mqttClient->connect_info.client_id) ) - { - temp = os_strlen(client_id); - mqttClient->connect_info.client_id = (uint8_t*)os_zalloc(temp + 1); - os_strcpy(mqttClient->connect_info.client_id, client_id); - mqttClient->connect_info.client_id[temp] = 0; - } - - if (client_user) - { - temp = os_strlen(client_user); - mqttClient->connect_info.username = (uint8_t*)os_zalloc(temp + 1); - os_strcpy(mqttClient->connect_info.username, client_user); - mqttClient->connect_info.username[temp] = 0; - } - - if (client_pass) - { - temp = os_strlen(client_pass); - mqttClient->connect_info.password = (uint8_t*)os_zalloc(temp + 1); - os_strcpy(mqttClient->connect_info.password, client_pass); - mqttClient->connect_info.password[temp] = 0; - } - - - mqttClient->connect_info.keepalive = keepAliveTime; - mqttClient->connect_info.clean_session = cleanSession; - - mqttClient->mqtt_state.in_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE); - mqttClient->mqtt_state.in_buffer_length = MQTT_BUF_SIZE; - mqttClient->mqtt_state.out_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE); - mqttClient->mqtt_state.out_buffer_length = MQTT_BUF_SIZE; - mqttClient->mqtt_state.connect_info = &mqttClient->connect_info; - - mqtt_msg_init(&mqttClient->mqtt_state.mqtt_connection, mqttClient->mqtt_state.out_buffer, mqttClient->mqtt_state.out_buffer_length); - - QUEUE_Init(&mqttClient->msgQueue, QUEUE_BUFFER_SIZE); - - system_os_task(MQTT_Task, MQTT_TASK_PRIO, mqtt_procTaskQueue, MQTT_TASK_QUEUE_SIZE); - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient); - return true; -} -void ICACHE_FLASH_ATTR -MQTT_InitLWT(MQTT_Client *mqttClient, uint8_t* will_topic, uint8_t* will_msg, uint8_t will_qos, uint8_t will_retain) -{ - uint32_t temp; - temp = os_strlen(will_topic); - mqttClient->connect_info.will_topic = (uint8_t*)os_zalloc(temp + 1); - os_strcpy(mqttClient->connect_info.will_topic, will_topic); - mqttClient->connect_info.will_topic[temp] = 0; - - temp = os_strlen(will_msg); - mqttClient->connect_info.will_message = (uint8_t*)os_zalloc(temp + 1); - os_strcpy(mqttClient->connect_info.will_message, will_msg); - mqttClient->connect_info.will_message[temp] = 0; - - - mqttClient->connect_info.will_qos = will_qos; - mqttClient->connect_info.will_retain = will_retain; -} -/** - * @brief Begin connect to MQTT broker - * @param client: MQTT_Client reference - * @retval None - */ -void ICACHE_FLASH_ATTR -MQTT_Connect(MQTT_Client *mqttClient) -{ - if (mqttClient->pCon) { - // Clean up the old connection forcefully - using MQTT_Disconnect - // does not actually release the old connection until the - // disconnection callback is invoked. - mqtt_tcpclient_delete(mqttClient); - } - mqttClient->pCon = (struct espconn *)os_zalloc(sizeof(struct espconn)); - mqttClient->pCon->type = ESPCONN_TCP; - mqttClient->pCon->state = ESPCONN_NONE; - mqttClient->pCon->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp)); - mqttClient->pCon->proto.tcp->local_port = espconn_port(); - mqttClient->pCon->proto.tcp->remote_port = mqttClient->port; - mqttClient->pCon->reverse = mqttClient; - espconn_regist_connectcb(mqttClient->pCon, mqtt_tcpclient_connect_cb); - espconn_regist_reconcb(mqttClient->pCon, mqtt_tcpclient_recon_cb); - - mqttClient->keepAliveTick = 0; - mqttClient->reconnectTick = 0; - - - os_timer_disarm(&mqttClient->mqttTimer); - os_timer_setfn(&mqttClient->mqttTimer, (os_timer_func_t *)mqtt_timer, mqttClient); - os_timer_arm(&mqttClient->mqttTimer, 1000, 1); - - if (UTILS_StrToIP(mqttClient->host, &mqttClient->pCon->proto.tcp->remote_ip)) { - MQTT_INFO("TCP: Connect to ip %s:%d\r\n", mqttClient->host, mqttClient->port); - if (mqttClient->security) - { -#ifdef MQTT_SSL_ENABLE - espconn_secure_set_size(ESPCONN_CLIENT, MQTT_SSL_SIZE); - espconn_secure_connect(mqttClient->pCon); -#else - MQTT_INFO("TCP: Do not support SSL\r\n"); -#endif - } - else - { - espconn_connect(mqttClient->pCon); - } - } - else { - MQTT_INFO("TCP: Connect to domain %s:%d\r\n", mqttClient->host, mqttClient->port); - espconn_gethostbyname(mqttClient->pCon, mqttClient->host, &mqttClient->ip, mqtt_dns_found); - } - mqttClient->connState = TCP_CONNECTING; -} - -void ICACHE_FLASH_ATTR -MQTT_Disconnect(MQTT_Client *mqttClient) -{ - mqttClient->connState = TCP_DISCONNECTING; - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient); - os_timer_disarm(&mqttClient->mqttTimer); -} - -void ICACHE_FLASH_ATTR -MQTT_DeleteClient(MQTT_Client *mqttClient) -{ - if (NULL == mqttClient) - return; - - mqttClient->connState = MQTT_DELETED; - // if(TCP_DISCONNECTED == mqttClient->connState) { - // mqttClient->connState = MQTT_DELETED; - // } else if(MQTT_DELETED != mqttClient->connState) { - // mqttClient->connState = MQTT_DELETING; - // } - - system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient); - os_timer_disarm(&mqttClient->mqttTimer); -} - -void ICACHE_FLASH_ATTR -MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb) -{ - mqttClient->connectedCb = connectedCb; -} - -void ICACHE_FLASH_ATTR -MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb) -{ - mqttClient->disconnectedCb = disconnectedCb; -} - -void ICACHE_FLASH_ATTR -MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb) -{ - mqttClient->dataCb = dataCb; -} - -void ICACHE_FLASH_ATTR -MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb) -{ - mqttClient->publishedCb = publishedCb; -} - -void ICACHE_FLASH_ATTR -MQTT_OnTimeout(MQTT_Client *mqttClient, MqttCallback timeoutCb) -{ - mqttClient->timeoutCb = timeoutCb; -} diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt.h b/lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt.h deleted file mode 100644 index 96489107e..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt.h +++ /dev/null @@ -1,148 +0,0 @@ -/* mqtt.h -* -* Copyright (c) 2014-2015, Tuan PM -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* * Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of Redis nor the names of its contributors may be used -* to endorse or promote products derived from this software without -* specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef USER_AT_MQTT_H_ -#define USER_AT_MQTT_H_ -#include "user_config.h" -#include "mqtt_msg.h" -#include "user_interface.h" - -#include "queue.h" -typedef struct mqtt_event_data_t -{ - uint8_t type; - const char* topic; - const char* data; - uint16_t topic_length; - uint16_t data_length; - uint16_t data_offset; -} mqtt_event_data_t; - -typedef struct mqtt_state_t -{ - uint16_t port; - int auto_reconnect; - mqtt_connect_info_t* connect_info; - uint8_t* in_buffer; - uint8_t* out_buffer; - int in_buffer_length; - int out_buffer_length; - uint16_t message_length; - uint16_t message_length_read; - mqtt_message_t* outbound_message; - mqtt_connection_t mqtt_connection; - uint16_t pending_msg_id; - int pending_msg_type; - int pending_publish_qos; -} mqtt_state_t; - -typedef enum { - WIFI_INIT, - WIFI_CONNECTING, - WIFI_CONNECTING_ERROR, - WIFI_CONNECTED, - DNS_RESOLVE, - TCP_DISCONNECTING, - TCP_DISCONNECTED, - TCP_RECONNECT_DISCONNECTING, - TCP_RECONNECT_REQ, - TCP_RECONNECT, - TCP_CONNECTING, - TCP_CONNECTING_ERROR, - TCP_CONNECTED, - MQTT_CONNECT_SEND, - MQTT_CONNECT_SENDING, - MQTT_SUBSCIBE_SEND, - MQTT_SUBSCIBE_SENDING, - MQTT_DATA, - MQTT_KEEPALIVE_SEND, - MQTT_PUBLISH_RECV, - MQTT_PUBLISHING, - MQTT_DELETING, - MQTT_DELETED, -} tConnState; - -typedef void (*MqttCallback)(uint32_t *args); -typedef void (*MqttDataCallback)(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t lengh); - -typedef struct { - struct espconn *pCon; - uint8_t security; - uint8_t* host; - uint32_t port; - ip_addr_t ip; - mqtt_state_t mqtt_state; - mqtt_connect_info_t connect_info; - MqttCallback connectedCb; - MqttCallback disconnectedCb; - MqttCallback publishedCb; - MqttCallback timeoutCb; - MqttDataCallback dataCb; - ETSTimer mqttTimer; - uint32_t keepAliveTick; - uint32_t reconnectTick; - uint32_t sendTimeout; - tConnState connState; - QUEUE msgQueue; - void* user_data; -} MQTT_Client; - -#define SEC_NONSSL 0 -#define SEC_SSL 1 - -#define MQTT_FLAG_CONNECTED 1 -#define MQTT_FLAG_READY 2 -#define MQTT_FLAG_EXIT 4 - -#define MQTT_EVENT_TYPE_NONE 0 -#define MQTT_EVENT_TYPE_CONNECTED 1 -#define MQTT_EVENT_TYPE_DISCONNECTED 2 -#define MQTT_EVENT_TYPE_SUBSCRIBED 3 -#define MQTT_EVENT_TYPE_UNSUBSCRIBED 4 -#define MQTT_EVENT_TYPE_PUBLISH 5 -#define MQTT_EVENT_TYPE_PUBLISHED 6 -#define MQTT_EVENT_TYPE_EXITED 7 -#define MQTT_EVENT_TYPE_PUBLISH_CONTINUATION 8 - -void ICACHE_FLASH_ATTR MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security); -bool ICACHE_FLASH_ATTR MQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession); -void ICACHE_FLASH_ATTR MQTT_DeleteClient(MQTT_Client *mqttClient); -void ICACHE_FLASH_ATTR MQTT_InitLWT(MQTT_Client *mqttClient, uint8_t* will_topic, uint8_t* will_msg, uint8_t will_qos, uint8_t will_retain); -void ICACHE_FLASH_ATTR MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb); -void ICACHE_FLASH_ATTR MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb); -void ICACHE_FLASH_ATTR MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb); -void ICACHE_FLASH_ATTR MQTT_OnTimeout(MQTT_Client *mqttClient, MqttCallback timeoutCb); -void ICACHE_FLASH_ATTR MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb); -bool ICACHE_FLASH_ATTR MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos); -bool ICACHE_FLASH_ATTR MQTT_UnSubscribe(MQTT_Client *client, char* topic); -void ICACHE_FLASH_ATTR MQTT_Connect(MQTT_Client *mqttClient); -void ICACHE_FLASH_ATTR MQTT_Disconnect(MQTT_Client *mqttClient); -bool ICACHE_FLASH_ATTR MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain); - -#endif /* USER_AT_MQTT_H_ */ diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt_msg.c b/lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt_msg.c deleted file mode 100644 index 57dcbac27..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt_msg.c +++ /dev/null @@ -1,487 +0,0 @@ -/* -* Copyright (c) 2014, Stephen Robinson -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holder nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -*/ - -#include -#include "mqtt_msg.h" -#include "user_config.h" -#define MQTT_MAX_FIXED_HEADER_SIZE 3 - -enum mqtt_connect_flag -{ - MQTT_CONNECT_FLAG_USERNAME = 1 << 7, - MQTT_CONNECT_FLAG_PASSWORD = 1 << 6, - MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5, - MQTT_CONNECT_FLAG_WILL = 1 << 2, - MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1 -}; - -struct __attribute((__packed__)) mqtt_connect_variable_header -{ - uint8_t lengthMsb; - uint8_t lengthLsb; -#if defined(PROTOCOL_NAMEv31) - uint8_t magic[6]; -#elif defined(PROTOCOL_NAMEv311) - uint8_t magic[4]; -#else -#error "Please define protocol name" -#endif - uint8_t version; - uint8_t flags; - uint8_t keepaliveMsb; - uint8_t keepaliveLsb; -}; - -static int ICACHE_FLASH_ATTR append_string(mqtt_connection_t* connection, const char* string, int len) -{ - if (connection->message.length + len + 2 > connection->buffer_length) - return -1; - - connection->buffer[connection->message.length++] = len >> 8; - connection->buffer[connection->message.length++] = len & 0xff; - memcpy(connection->buffer + connection->message.length, string, len); - connection->message.length += len; - - return len + 2; -} - -static uint16_t ICACHE_FLASH_ATTR append_message_id(mqtt_connection_t* connection, uint16_t message_id) -{ - // If message_id is zero then we should assign one, otherwise - // we'll use the one supplied by the caller - while (message_id == 0) - message_id = ++connection->message_id; - - if (connection->message.length + 2 > connection->buffer_length) - return 0; - - connection->buffer[connection->message.length++] = message_id >> 8; - connection->buffer[connection->message.length++] = message_id & 0xff; - - return message_id; -} - -static int ICACHE_FLASH_ATTR init_message(mqtt_connection_t* connection) -{ - connection->message.length = MQTT_MAX_FIXED_HEADER_SIZE; - return MQTT_MAX_FIXED_HEADER_SIZE; -} - -static mqtt_message_t* ICACHE_FLASH_ATTR fail_message(mqtt_connection_t* connection) -{ - connection->message.data = connection->buffer; - connection->message.length = 0; - return &connection->message; -} - -static mqtt_message_t* ICACHE_FLASH_ATTR fini_message(mqtt_connection_t* connection, int type, int dup, int qos, int retain) -{ - int remaining_length = connection->message.length - MQTT_MAX_FIXED_HEADER_SIZE; - - if (remaining_length > 127) - { - connection->buffer[0] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1); - connection->buffer[1] = 0x80 | (remaining_length % 128); - connection->buffer[2] = remaining_length / 128; - connection->message.length = remaining_length + 3; - connection->message.data = connection->buffer; - } - else - { - connection->buffer[1] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1); - connection->buffer[2] = remaining_length; - connection->message.length = remaining_length + 2; - connection->message.data = connection->buffer + 1; - } - - return &connection->message; -} - -void ICACHE_FLASH_ATTR mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length) -{ - memset(connection, 0, sizeof(mqtt_connection_t)); - connection->buffer = buffer; - connection->buffer_length = buffer_length; -} - -int ICACHE_FLASH_ATTR mqtt_get_total_length(uint8_t* buffer, uint16_t length) -{ - int i; - int totlen = 0; - - for (i = 1; i < length; ++i) - { - totlen += (buffer[i] & 0x7f) << (7 * (i - 1)); - if ((buffer[i] & 0x80) == 0) - { - ++i; - break; - } - } - totlen += i; - - return totlen; -} - -const char* ICACHE_FLASH_ATTR mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length) -{ - int i; - int totlen = 0; - int topiclen; - - for (i = 1; i < *length; ++i) - { - totlen += (buffer[i] & 0x7f) << (7 * (i - 1)); - if ((buffer[i] & 0x80) == 0) - { - ++i; - break; - } - } - totlen += i; - - if (i + 2 >= *length) - return NULL; - topiclen = buffer[i++] << 8; - topiclen |= buffer[i++]; - - if (i + topiclen > *length) - return NULL; - - *length = topiclen; - return (const char*)(buffer + i); -} - -const char* ICACHE_FLASH_ATTR mqtt_get_publish_data(uint8_t* buffer, uint16_t* length) -{ - int i; - int totlen = 0; - int topiclen; - int blength = *length; - *length = 0; - - for (i = 1; i < blength; ++i) - { - totlen += (buffer[i] & 0x7f) << (7 * (i - 1)); - if ((buffer[i] & 0x80) == 0) - { - ++i; - break; - } - } - totlen += i; - - if (i + 2 >= blength) - return NULL; - topiclen = buffer[i++] << 8; - topiclen |= buffer[i++]; - - if (i + topiclen >= blength) - return NULL; - - i += topiclen; - - if (mqtt_get_qos(buffer) > 0) - { - if (i + 2 >= blength) - return NULL; - i += 2; - } - - if (totlen < i) - return NULL; - - if (totlen <= blength) - *length = totlen - i; - else - *length = blength - i; - return (const char*)(buffer + i); -} - -uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length) -{ - if (length < 1) - return 0; - - switch (mqtt_get_type(buffer)) - { - case MQTT_MSG_TYPE_PUBLISH: - { - int i; - int topiclen; - - for (i = 1; i < length; ++i) - { - if ((buffer[i] & 0x80) == 0) - { - ++i; - break; - } - } - - if (i + 2 >= length) - return 0; - topiclen = buffer[i++] << 8; - topiclen |= buffer[i++]; - - if (i + topiclen >= length) - return 0; - i += topiclen; - - if (mqtt_get_qos(buffer) > 0) - { - if (i + 2 >= length) - return 0; - //i += 2; - } else { - return 0; - } - - return (buffer[i] << 8) | buffer[i + 1]; - } - case MQTT_MSG_TYPE_PUBACK: - case MQTT_MSG_TYPE_PUBREC: - case MQTT_MSG_TYPE_PUBREL: - case MQTT_MSG_TYPE_PUBCOMP: - case MQTT_MSG_TYPE_SUBACK: - case MQTT_MSG_TYPE_UNSUBACK: - case MQTT_MSG_TYPE_SUBSCRIBE: - { - // This requires the remaining length to be encoded in 1 byte, - // which it should be. - if (length >= 4 && (buffer[1] & 0x80) == 0) - return (buffer[2] << 8) | buffer[3]; - else - return 0; - } - - default: - return 0; - } -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info) -{ - struct mqtt_connect_variable_header* variable_header; - - init_message(connection); - - if (connection->message.length + sizeof(*variable_header) > connection->buffer_length) - return fail_message(connection); - variable_header = (void*)(connection->buffer + connection->message.length); - connection->message.length += sizeof(*variable_header); - - variable_header->lengthMsb = 0; -#if defined(PROTOCOL_NAMEv31) - variable_header->lengthLsb = 6; - memcpy(variable_header->magic, "MQIsdp", 6); - variable_header->version = 3; -#elif defined(PROTOCOL_NAMEv311) - variable_header->lengthLsb = 4; - memcpy(variable_header->magic, "MQTT", 4); - variable_header->version = 4; -#else -#error "Please define protocol name" -#endif - - variable_header->flags = 0; - variable_header->keepaliveMsb = info->keepalive >> 8; - variable_header->keepaliveLsb = info->keepalive & 0xff; - - if (info->clean_session) - variable_header->flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; - - if (info->client_id == NULL) - { - /* Never allowed */ - return fail_message(connection); - } - else if (info->client_id[0] == '\0') - { -#ifdef PROTOCOL_NAMEv311 - /* Allowed. Format 0 Length ID */ - append_string(connection, info->client_id, 2) ; -#else - /* 0 Length not allowed */ - return fail_message(connection); -#endif - } - else - { - /* No 0 data and at least 1 long. Good to go. */ - if(append_string(connection, info->client_id, strlen(info->client_id)) < 0) - return fail_message(connection); - } - - if (info->will_topic != NULL && info->will_topic[0] != '\0') - { - if (append_string(connection, info->will_topic, strlen(info->will_topic)) < 0) - return fail_message(connection); - - if (append_string(connection, info->will_message, strlen(info->will_message)) < 0) - return fail_message(connection); - - variable_header->flags |= MQTT_CONNECT_FLAG_WILL; - if (info->will_retain) - variable_header->flags |= MQTT_CONNECT_FLAG_WILL_RETAIN; - variable_header->flags |= (info->will_qos & 3) << 3; - } - - if (info->username != NULL && info->username[0] != '\0') - { - if (append_string(connection, info->username, strlen(info->username)) < 0) - return fail_message(connection); - - variable_header->flags |= MQTT_CONNECT_FLAG_USERNAME; - } - - if (info->password != NULL && info->password[0] != '\0') - { - if (append_string(connection, info->password, strlen(info->password)) < 0) - return fail_message(connection); - - variable_header->flags |= MQTT_CONNECT_FLAG_PASSWORD; - } - - return fini_message(connection, MQTT_MSG_TYPE_CONNECT, 0, 0, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id) -{ - init_message(connection); - - if (topic == NULL || topic[0] == '\0') - return fail_message(connection); - - if (append_string(connection, topic, strlen(topic)) < 0) - return fail_message(connection); - - if (qos > 0) - { - if ((*message_id = append_message_id(connection, 0)) == 0) - return fail_message(connection); - } - else - *message_id = 0; - - if (connection->message.length + data_length > connection->buffer_length) - return fail_message(connection); - memcpy(connection->buffer + connection->message.length, data, data_length); - connection->message.length += data_length; - - return fini_message(connection, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id) -{ - init_message(connection); - if (append_message_id(connection, message_id) == 0) - return fail_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_PUBACK, 0, 0, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id) -{ - init_message(connection); - if (append_message_id(connection, message_id) == 0) - return fail_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_PUBREC, 0, 0, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id) -{ - init_message(connection); - if (append_message_id(connection, message_id) == 0) - return fail_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_PUBREL, 0, 1, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id) -{ - init_message(connection); - if (append_message_id(connection, message_id) == 0) - return fail_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_PUBCOMP, 0, 0, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id) -{ - init_message(connection); - - if (topic == NULL || topic[0] == '\0') - return fail_message(connection); - - if ((*message_id = append_message_id(connection, 0)) == 0) - return fail_message(connection); - - if (append_string(connection, topic, strlen(topic)) < 0) - return fail_message(connection); - - if (connection->message.length + 1 > connection->buffer_length) - return fail_message(connection); - connection->buffer[connection->message.length++] = qos; - - return fini_message(connection, MQTT_MSG_TYPE_SUBSCRIBE, 0, 1, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id) -{ - init_message(connection); - - if (topic == NULL || topic[0] == '\0') - return fail_message(connection); - - if ((*message_id = append_message_id(connection, 0)) == 0) - return fail_message(connection); - - if (append_string(connection, topic, strlen(topic)) < 0) - return fail_message(connection); - - return fini_message(connection, MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection) -{ - init_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection) -{ - init_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_PINGRESP, 0, 0, 0); -} - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection) -{ - init_message(connection); - return fini_message(connection, MQTT_MSG_TYPE_DISCONNECT, 0, 0, 0); -} diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt_msg.h b/lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt_msg.h deleted file mode 100644 index be3cc55cb..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/mqtt_msg.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * File: mqtt_msg.h - * Author: Minh Tuan - * - * Created on July 12, 2014, 1:05 PM - */ - -#ifndef MQTT_MSG_H -#define MQTT_MSG_H -#include "user_config.h" -#include "c_types.h" -#ifdef __cplusplus -extern "C" { -#endif - -/* -* Copyright (c) 2014, Stephen Robinson -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holder nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -*/ -/* 7 6 5 4 3 2 1 0*/ -/*| --- Message Type---- | DUP Flag | QoS Level | Retain | -/* Remaining Length */ - - -enum mqtt_message_type -{ - MQTT_MSG_TYPE_CONNECT = 1, - MQTT_MSG_TYPE_CONNACK = 2, - MQTT_MSG_TYPE_PUBLISH = 3, - MQTT_MSG_TYPE_PUBACK = 4, - MQTT_MSG_TYPE_PUBREC = 5, - MQTT_MSG_TYPE_PUBREL = 6, - MQTT_MSG_TYPE_PUBCOMP = 7, - MQTT_MSG_TYPE_SUBSCRIBE = 8, - MQTT_MSG_TYPE_SUBACK = 9, - MQTT_MSG_TYPE_UNSUBSCRIBE = 10, - MQTT_MSG_TYPE_UNSUBACK = 11, - MQTT_MSG_TYPE_PINGREQ = 12, - MQTT_MSG_TYPE_PINGRESP = 13, - MQTT_MSG_TYPE_DISCONNECT = 14 -}; - -enum mqtt_connect_return_code -{ - CONNECTION_ACCEPTED = 0, - CONNECTION_REFUSE_PROTOCOL, - CONNECTION_REFUSE_ID_REJECTED, - CONNECTION_REFUSE_SERVER_UNAVAILABLE, - CONNECTION_REFUSE_BAD_USERNAME, - CONNECTION_REFUSE_NOT_AUTHORIZED -}; - -typedef struct mqtt_message -{ - uint8_t* data; - uint16_t length; - -} mqtt_message_t; - -typedef struct mqtt_connection -{ - mqtt_message_t message; - - uint16_t message_id; - uint8_t* buffer; - uint16_t buffer_length; - -} mqtt_connection_t; - -typedef struct mqtt_connect_info -{ - char* client_id; - char* username; - char* password; - char* will_topic; - char* will_message; - uint32_t keepalive; - int will_qos; - int will_retain; - int clean_session; - -} mqtt_connect_info_t; - - -static inline int ICACHE_FLASH_ATTR mqtt_get_type(uint8_t* buffer) { return (buffer[0] & 0xf0) >> 4; } -static inline int ICACHE_FLASH_ATTR mqtt_get_connect_return_code(uint8_t* buffer) { return buffer[3]; } -static inline int ICACHE_FLASH_ATTR mqtt_get_dup(uint8_t* buffer) { return (buffer[0] & 0x08) >> 3; } -static inline int ICACHE_FLASH_ATTR mqtt_get_qos(uint8_t* buffer) { return (buffer[0] & 0x06) >> 1; } -static inline int ICACHE_FLASH_ATTR mqtt_get_retain(uint8_t* buffer) { return (buffer[0] & 0x01); } - -void ICACHE_FLASH_ATTR mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length); -int ICACHE_FLASH_ATTR mqtt_get_total_length(uint8_t* buffer, uint16_t length); -const char* ICACHE_FLASH_ATTR mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length); -const char* ICACHE_FLASH_ATTR mqtt_get_publish_data(uint8_t* buffer, uint16_t* length); -uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length); - -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection); -mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection); - - -#ifdef __cplusplus -} -#endif - -#endif /* MQTT_MSG_H */ - diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/proto.c b/lib/TasmotaMqtt-1.1.1/src/mqtt/proto.c deleted file mode 100644 index 84078b233..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/proto.c +++ /dev/null @@ -1,129 +0,0 @@ -#include "proto.h" -#include "ringbuf.h" -I8 ICACHE_FLASH_ATTR PROTO_Init(PROTO_PARSER *parser, PROTO_PARSE_CALLBACK *completeCallback, U8 *buf, U16 bufSize) -{ - parser->buf = buf; - parser->bufSize = bufSize; - parser->dataLen = 0; - parser->callback = completeCallback; - parser->isEsc = 0; - return 0; -} - -I8 ICACHE_FLASH_ATTR PROTO_ParseByte(PROTO_PARSER *parser, U8 value) -{ - switch (value) { - case 0x7D: - parser->isEsc = 1; - break; - - case 0x7E: - parser->dataLen = 0; - parser->isEsc = 0; - parser->isBegin = 1; - break; - - case 0x7F: - if (parser->callback != NULL) - parser->callback(); - parser->isBegin = 0; - return 0; - break; - - default: - if (parser->isBegin == 0) break; - - if (parser->isEsc) { - value ^= 0x20; - parser->isEsc = 0; - } - - if (parser->dataLen < parser->bufSize) - parser->buf[parser->dataLen++] = value; - - break; - } - return -1; -} - -I8 ICACHE_FLASH_ATTR PROTO_Parse(PROTO_PARSER *parser, U8 *buf, U16 len) -{ - while (len--) - PROTO_ParseByte(parser, *buf++); - - return 0; -} -I16 ICACHE_FLASH_ATTR PROTO_ParseRb(RINGBUF* rb, U8 *bufOut, U16* len, U16 maxBufLen) -{ - U8 c; - - PROTO_PARSER proto; - PROTO_Init(&proto, NULL, bufOut, maxBufLen); - while (RINGBUF_Get(rb, &c) == 0) { - if (PROTO_ParseByte(&proto, c) == 0) { - *len = proto.dataLen; - return 0; - } - } - return -1; -} -I16 ICACHE_FLASH_ATTR PROTO_Add(U8 *buf, const U8 *packet, I16 bufSize) -{ - U16 i = 2; - U16 len = *(U16*) packet; - - if (bufSize < 1) return -1; - - *buf++ = 0x7E; - bufSize--; - - while (len--) { - switch (*packet) { - case 0x7D: - case 0x7E: - case 0x7F: - if (bufSize < 2) return -1; - *buf++ = 0x7D; - *buf++ = *packet++ ^ 0x20; - i += 2; - bufSize -= 2; - break; - default: - if (bufSize < 1) return -1; - *buf++ = *packet++; - i++; - bufSize--; - break; - } - } - - if (bufSize < 1) return -1; - *buf++ = 0x7F; - - return i; -} - -I16 ICACHE_FLASH_ATTR PROTO_AddRb(RINGBUF *rb, const U8 *packet, I16 len) -{ - U16 i = 2; - if (RINGBUF_Put(rb, 0x7E) == -1) return -1; - while (len--) { - switch (*packet) { - case 0x7D: - case 0x7E: - case 0x7F: - if (RINGBUF_Put(rb, 0x7D) == -1) return -1; - if (RINGBUF_Put(rb, *packet++ ^ 0x20) == -1) return -1; - i += 2; - break; - default: - if (RINGBUF_Put(rb, *packet++) == -1) return -1; - i++; - break; - } - } - if (RINGBUF_Put(rb, 0x7F) == -1) return -1; - - return i; -} - diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/proto.h b/lib/TasmotaMqtt-1.1.1/src/mqtt/proto.h deleted file mode 100644 index a405bcb95..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/proto.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * File: proto.h - * Author: ThuHien - * - * Created on November 23, 2012, 8:57 AM - */ - -#ifndef _PROTO_H_ -#define _PROTO_H_ -#include -#include "typedef.h" -#include "ringbuf.h" - -typedef void(PROTO_PARSE_CALLBACK)(); - -typedef struct { - U8 *buf; - U16 bufSize; - U16 dataLen; - U8 isEsc; - U8 isBegin; - PROTO_PARSE_CALLBACK* callback; -} PROTO_PARSER; - -I8 ICACHE_FLASH_ATTR PROTO_Init(PROTO_PARSER *parser, PROTO_PARSE_CALLBACK *completeCallback, U8 *buf, U16 bufSize); -I8 ICACHE_FLASH_ATTR PROTO_Parse(PROTO_PARSER *parser, U8 *buf, U16 len); -I16 ICACHE_FLASH_ATTR PROTO_Add(U8 *buf, const U8 *packet, I16 bufSize); -I16 ICACHE_FLASH_ATTR PROTO_AddRb(RINGBUF *rb, const U8 *packet, I16 len); -I8 ICACHE_FLASH_ATTR PROTO_ParseByte(PROTO_PARSER *parser, U8 value); -I16 ICACHE_FLASH_ATTR PROTO_ParseRb(RINGBUF *rb, U8 *bufOut, U16* len, U16 maxBufLen); -#endif - diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/queue.c b/lib/TasmotaMqtt-1.1.1/src/mqtt/queue.c deleted file mode 100644 index 5e4216d0f..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/queue.c +++ /dev/null @@ -1,75 +0,0 @@ -/* str_queue.c -* -* Copyright (c) 2014-2015, Tuan PM -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* * Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of Redis nor the names of its contributors may be used -* to endorse or promote products derived from this software without -* specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*/ -#include "queue.h" - -#include "user_interface.h" -#include "osapi.h" -#include "os_type.h" -#include "mem.h" -#include "proto.h" - -uint8_t *last_rb_p_r; -uint8_t *last_rb_p_w; -uint32_t last_fill_cnt; - -void ICACHE_FLASH_ATTR QUEUE_Init(QUEUE *queue, int bufferSize) -{ - queue->buf = (uint8_t*)os_zalloc(bufferSize); - RINGBUF_Init(&queue->rb, queue->buf, bufferSize); -} -int32_t ICACHE_FLASH_ATTR QUEUE_Puts(QUEUE *queue, uint8_t* buffer, uint16_t len) -{ - uint32_t ret; - - last_rb_p_r = queue->rb.p_r; - last_rb_p_w = queue->rb.p_w; - last_fill_cnt = queue->rb.fill_cnt; - - ret = PROTO_AddRb(&queue->rb, buffer, len); - if (ret == -1) { - // rolling ring buffer back - queue->rb.p_r = last_rb_p_r; - queue->rb.p_w = last_rb_p_w; - queue->rb.fill_cnt = last_fill_cnt; - } - return ret; -} -int32_t ICACHE_FLASH_ATTR QUEUE_Gets(QUEUE *queue, uint8_t* buffer, uint16_t* len, uint16_t maxLen) -{ - - return PROTO_ParseRb(&queue->rb, buffer, len, maxLen); -} - -bool ICACHE_FLASH_ATTR QUEUE_IsEmpty(QUEUE *queue) -{ - if (queue->rb.fill_cnt <= 0) - return TRUE; - return FALSE; -} diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/queue.h b/lib/TasmotaMqtt-1.1.1/src/mqtt/queue.h deleted file mode 100644 index 79107f2d5..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/queue.h +++ /dev/null @@ -1,44 +0,0 @@ -/* str_queue.h -- -* -* Copyright (c) 2014-2015, Tuan PM -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* * Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of Redis nor the names of its contributors may be used -* to endorse or promote products derived from this software without -* specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef USER_QUEUE_H_ -#define USER_QUEUE_H_ -#include "os_type.h" -#include "ringbuf.h" -typedef struct { - uint8_t *buf; - RINGBUF rb; -} QUEUE; - -void ICACHE_FLASH_ATTR QUEUE_Init(QUEUE *queue, int bufferSize); -int32_t ICACHE_FLASH_ATTR QUEUE_Puts(QUEUE *queue, uint8_t* buffer, uint16_t len); -int32_t ICACHE_FLASH_ATTR QUEUE_Gets(QUEUE *queue, uint8_t* buffer, uint16_t* len, uint16_t maxLen); -bool ICACHE_FLASH_ATTR QUEUE_IsEmpty(QUEUE *queue); -#endif /* USER_QUEUE_H_ */ diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/ringbuf.c b/lib/TasmotaMqtt-1.1.1/src/mqtt/ringbuf.c deleted file mode 100644 index fc882fd5c..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/ringbuf.c +++ /dev/null @@ -1,67 +0,0 @@ -/** -* \file -* Ring Buffer library -*/ - -#include "ringbuf.h" - - -/** -* \brief init a RINGBUF object -* \param r pointer to a RINGBUF object -* \param buf pointer to a byte array -* \param size size of buf -* \return 0 if successfull, otherwise failed -*/ -I16 ICACHE_FLASH_ATTR RINGBUF_Init(RINGBUF *r, U8* buf, I32 size) -{ - if (r == NULL || buf == NULL || size < 2) return -1; - - r->p_o = r->p_r = r->p_w = buf; - r->fill_cnt = 0; - r->size = size; - - return 0; -} -/** -* \brief put a character into ring buffer -* \param r pointer to a ringbuf object -* \param c character to be put -* \return 0 if successfull, otherwise failed -*/ -I16 ICACHE_FLASH_ATTR RINGBUF_Put(RINGBUF *r, U8 c) -{ - if (r->fill_cnt >= r->size)return -1; // ring buffer is full, this should be atomic operation - - - r->fill_cnt++; // increase filled slots count, this should be atomic operation - - - *r->p_w++ = c; // put character into buffer - - if (r->p_w >= r->p_o + r->size) // rollback if write pointer go pass - r->p_w = r->p_o; // the physical boundary - - return 0; -} -/** -* \brief get a character from ring buffer -* \param r pointer to a ringbuf object -* \param c read character -* \return 0 if successfull, otherwise failed -*/ -I16 ICACHE_FLASH_ATTR RINGBUF_Get(RINGBUF *r, U8* c) -{ - if (r->fill_cnt <= 0)return -1; // ring buffer is empty, this should be atomic operation - - - r->fill_cnt--; // decrease filled slots count - - - *c = *r->p_r++; // get the character out - - if (r->p_r >= r->p_o + r->size) // rollback if write pointer go pass - r->p_r = r->p_o; // the physical boundary - - return 0; -} diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/ringbuf.h b/lib/TasmotaMqtt-1.1.1/src/mqtt/ringbuf.h deleted file mode 100644 index f1a4f7e8b..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/ringbuf.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _RING_BUF_H_ -#define _RING_BUF_H_ - -#include -#include -#include "typedef.h" - -typedef struct { - U8* p_o; /**< Original pointer */ - U8* volatile p_r; /**< Read pointer */ - U8* volatile p_w; /**< Write pointer */ - volatile I32 fill_cnt; /**< Number of filled slots */ - I32 size; /**< Buffer size */ -} RINGBUF; - -I16 ICACHE_FLASH_ATTR RINGBUF_Init(RINGBUF *r, U8* buf, I32 size); -I16 ICACHE_FLASH_ATTR RINGBUF_Put(RINGBUF *r, U8 c); -I16 ICACHE_FLASH_ATTR RINGBUF_Get(RINGBUF *r, U8* c); -#endif diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/typedef.h b/lib/TasmotaMqtt-1.1.1/src/mqtt/typedef.h deleted file mode 100644 index 887001ace..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/typedef.h +++ /dev/null @@ -1,17 +0,0 @@ -/** -* \file -* Standard Types definition -*/ - -#ifndef _TYPE_DEF_H_ -#define _TYPE_DEF_H_ - -typedef char I8; -typedef unsigned char U8; -typedef short I16; -typedef unsigned short U16; -typedef long I32; -typedef unsigned long U32; -typedef unsigned long long U64; - -#endif diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/user_config.h b/lib/TasmotaMqtt-1.1.1/src/mqtt/user_config.h deleted file mode 100644 index 125353ed0..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/user_config.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __MQTT_CONFIG_H__ -#define __MQTT_CONFIG_H__ - -//#define MQTT_SSL_ENABLE - -#define MQTT_RECONNECT_TIMEOUT 5 /*second*/ - -//#define MQTT_BUF_SIZE 1024 -#define MQTT_BUF_SIZE 512 -#define QUEUE_BUFFER_SIZE 2048 - -//#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/ -#define PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/ - -#endif // __MQTT_CONFIG_H__ \ No newline at end of file diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/utils.c b/lib/TasmotaMqtt-1.1.1/src/mqtt/utils.c deleted file mode 100644 index ac4c9272b..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/utils.c +++ /dev/null @@ -1,149 +0,0 @@ -/* -* Copyright (c) 2014, Tuan PM -* Email: tuanpm@live.com -* -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holder nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -* -*/ -#include -#include -#include -#include -#include -#include "utils.h" - - -uint8_t ICACHE_FLASH_ATTR UTILS_IsIPV4 (int8_t *str) -{ - uint8_t segs = 0; /* Segment count. */ - uint8_t chcnt = 0; /* Character count within segment. */ - uint8_t accum = 0; /* Accumulator for segment. */ - /* Catch NULL pointer. */ - if (str == 0) - return 0; - /* Process every character in string. */ - - while (*str != '\0') { - /* Segment changeover. */ - - if (*str == '.') { - /* Must have some digits in segment. */ - if (chcnt == 0) - return 0; - /* Limit number of segments. */ - if (++segs == 4) - return 0; - /* Reset segment values and restart loop. */ - chcnt = accum = 0; - str++; - continue; - } - - /* Check numeric. */ - if ((*str < '0') || (*str > '9')) - return 0; - - /* Accumulate and check segment. */ - - if ((accum = accum * 10 + *str - '0') > 255) - return 0; - /* Advance other segment specific stuff and continue loop. */ - - chcnt++; - str++; - } - - /* Check enough segments and enough characters in last segment. */ - - if (segs != 3) - return 0; - if (chcnt == 0) - return 0; - /* Address okay. */ - - return 1; -} -uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const int8_t* str, void *ip) -{ - - /* The count of the number of bytes processed. */ - int i; - /* A pointer to the next digit to process. */ - const char * start; - - start = str; - for (i = 0; i < 4; i++) { - /* The digit being processed. */ - char c; - /* The value of this byte. */ - int n = 0; - while (1) { - c = * start; - start++; - if (c >= '0' && c <= '9') { - n *= 10; - n += c - '0'; - } - /* We insist on stopping at "." if we are still parsing - the first, second, or third numbers. If we have reached - the end of the numbers, we will allow any character. */ - else if ((i < 3 && c == '.') || i == 3) { - break; - } - else { - return 0; - } - } - if (n >= 256) { - return 0; - } - ((uint8_t*)ip)[i] = n; - } - return 1; - -} -uint32_t ICACHE_FLASH_ATTR UTILS_Atoh(const int8_t *s) -{ - uint32_t value = 0, digit; - int8_t c; - - while ((c = *s++)) { - if ('0' <= c && c <= '9') - digit = c - '0'; - else if ('A' <= c && c <= 'F') - digit = c - 'A' + 10; - else if ('a' <= c && c <= 'f') - digit = c - 'a' + 10; - else break; - - value = (value << 4) | digit; - } - - return value; -} - diff --git a/lib/TasmotaMqtt-1.1.1/src/mqtt/utils.h b/lib/TasmotaMqtt-1.1.1/src/mqtt/utils.h deleted file mode 100644 index fe2874803..000000000 --- a/lib/TasmotaMqtt-1.1.1/src/mqtt/utils.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _UTILS_H_ -#define _UTILS_H_ - -#include "c_types.h" - -uint32_t ICACHE_FLASH_ATTR UTILS_Atoh(const int8_t *s); -uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const int8_t* str, void *ip); -uint8_t ICACHE_FLASH_ATTR UTILS_IsIPV4 (int8_t *str); -#endif diff --git a/lib/arduino-mqtt-2.4.0/.editorconfig b/lib/arduino-mqtt-2.4.0/.editorconfig deleted file mode 100644 index 3edae7b53..000000000 --- a/lib/arduino-mqtt-2.4.0/.editorconfig +++ /dev/null @@ -1,7 +0,0 @@ -[Makefile] -indent_style = tab -indent_size = 4 - -[src/*.h,src/*.cpp,examples/**.ino] -indent_style = space -indent_size = 2 diff --git a/lib/arduino-mqtt-2.4.0/.gitignore b/lib/arduino-mqtt-2.4.0/.gitignore deleted file mode 100644 index 0c4fe4711..000000000 --- a/lib/arduino-mqtt-2.4.0/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.DS_Store -cmake-build-debug/ diff --git a/lib/arduino-mqtt-2.4.0/.travis.yml b/lib/arduino-mqtt-2.4.0/.travis.yml deleted file mode 100644 index 6971b9fba..000000000 --- a/lib/arduino-mqtt-2.4.0/.travis.yml +++ /dev/null @@ -1,46 +0,0 @@ -language: generic -env: - global: - - IDE_VERSION=1.8.7 - matrix: - - EXAMPLE="AdafruitHuzzahESP8266" BOARD="esp8266:esp8266:huzzah:FlashSize=4M3M,CpuFrequency=80" - - EXAMPLE="AdafruitHuzzahESP8266Secure" BOARD="esp8266:esp8266:huzzah:FlashSize=4M3M,CpuFrequency=80" - - EXAMPLE="ArduinoEthernetShield" BOARD="arduino:avr:uno" - - EXAMPLE="ArduinoMKRGSM1400" BOARD="arduino:samd:mkrgsm1400" - - EXAMPLE="ArduinoMKRGSM1400Secure" BOARD="arduino:samd:mkrgsm1400" - - EXAMPLE="ArduinoWiFi101Secure" BOARD="arduino:avr:uno" - - EXAMPLE="ArduinoWiFiShield" BOARD="arduino:avr:uno" - - EXAMPLE="ArduinoYun" BOARD="arduino:avr:yun" - - EXAMPLE="ArduinoYunSecure" BOARD="arduino:avr:yun" - - EXAMPLE="ESP32DevelopmentBoard" BOARD="espressif:esp32:esp32:FlashFreq=80" - - EXAMPLE="ESP32DevelopmentBoardSecure" BOARD="espressif:esp32:esp32:FlashFreq=80" -before_install: - - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 - - sleep 3 - - export DISPLAY=:1.0 - - wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz - - tar xf arduino-$IDE_VERSION-linux64.tar.xz - - mv arduino-$IDE_VERSION ~/arduino-ide - - export PATH=$PATH:~/arduino-ide - - if [[ "$BOARD" =~ "esp8266:esp8266:" ]]; then - arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --install-boards esp8266:esp8266; - arduino --pref "boardsmanager.additional.urls=" --save-prefs; - fi - - if [[ "$BOARD" =~ "espressif:esp32:" ]]; then - mkdir -p ~/Arduino/hardware/espressif && - cd ~/Arduino/hardware/espressif && - git clone https://github.com/espressif/arduino-esp32.git esp32 && - cd esp32/tools/ && - python get.py && - cd $TRAVIS_BUILD_DIR; - fi - - if [[ "$BOARD" =~ "arduino:samd:mkrgsm1400" ]]; then - arduino --install-boards arduino:samd; - arduino --install-library MKRGSM; - fi - - arduino --install-library WiFi101 -install: - - mkdir -p ~/Arduino/libraries - - ln -s $PWD ~/Arduino/libraries/. -script: - - arduino --verbose-build --verify --board $BOARD $PWD/examples/$EXAMPLE/$EXAMPLE.ino; diff --git a/lib/arduino-mqtt-2.4.0/CMakeLists.txt b/lib/arduino-mqtt-2.4.0/CMakeLists.txt deleted file mode 100644 index 328ce0c87..000000000 --- a/lib/arduino-mqtt-2.4.0/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# Uncompilable CMake File to enable project editing with CLion IDE - -cmake_minimum_required(VERSION 2.8.4) -project(arduino-mqtt) - -include_directories( - /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/ - /Users/256dpi/Development/Arduino/libraries/Ethernet/src - /Users/256dpi/Development/Arduino/libraries/WiFi101/src - /Users/256dpi/Development/Arduino/libraries/MKRGSM/src - /Applications/Arduino.app/Contents/Java/libraries/Bridge/src - /Users/256dpi/Library/Arduino15/packages/esp8266/hardware/esp8266/2.3.0/libraries/ESP8266WiFi/src - /Users/256dpi/Library/Arduino15/packages/esp32/libraries/WiFi/src - /Users/256dpi/Library/Arduino15/packages/esp32/libraries/WiFiClientSecure/src - src/) - -include_directories(src/) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - -set(SOURCE_FILES - examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino - examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino - examples/ArduinoEthernetShield/ArduinoEthernetShield.ino - examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino - examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino - examples/ArduinoWiFi101/ArduinoWiFi101.ino - examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino - examples/ArduinoWiFiShield/ArduinoWiFiShield.ino - examples/ArduinoYun/ArduinoYun.ino - examples/ArduinoYunSecure/ArduinoYunSecure.ino - examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino - examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino - src/lwmqtt - src/MQTT.h - src/MQTTClient.h) - -add_executable(arduino-mqtt ${SOURCE_FILES}) diff --git a/lib/arduino-mqtt-2.4.0/LICENSE.md b/lib/arduino-mqtt-2.4.0/LICENSE.md deleted file mode 100644 index 325e07cff..000000000 --- a/lib/arduino-mqtt-2.4.0/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Joël Gähwiler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/arduino-mqtt-2.4.0/Makefile b/lib/arduino-mqtt-2.4.0/Makefile deleted file mode 100644 index 9e734fcc3..000000000 --- a/lib/arduino-mqtt-2.4.0/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -all: fmt - -fmt: - clang-format -i src/*.h -style="{BasedOnStyle: Google, ColumnLimit: 120}" - -update: - rm -rf ./lwmqtt - git clone --branch v0.6.2 https://github.com/256dpi/lwmqtt.git ./lwmqtt - mkdir -p ./src/lwmqtt - cp -r ./lwmqtt/src/*.c ./src/lwmqtt/ - cp -r ./lwmqtt/src/*.h ./src/lwmqtt/ - cp -r ./lwmqtt/include/*.h ./src/lwmqtt/ - rm -rf ./lwmqtt - sed -i '' "s//\"lwmqtt.h\"/g" ./src/lwmqtt/* diff --git a/lib/arduino-mqtt-2.4.0/README.md b/lib/arduino-mqtt-2.4.0/README.md deleted file mode 100644 index 92e61ed6e..000000000 --- a/lib/arduino-mqtt-2.4.0/README.md +++ /dev/null @@ -1,226 +0,0 @@ -# arduino-mqtt - -[![Build Status](https://travis-ci.org/256dpi/arduino-mqtt.svg?branch=master)](https://travis-ci.org/256dpi/arduino-mqtt) -[![GitHub release](https://img.shields.io/github/release/256dpi/arduino-mqtt.svg)](https://github.com/256dpi/arduino-mqtt/releases) - -This library bundles the [lwmqtt](https://github.com/256dpi/lwmqtt) MQTT 3.1.1 client and adds a thin wrapper to get an Arduino like API. - -Download the latest version from the [release](https://github.com/256dpi/arduino-mqtt/releases) section. Or even better use the builtin Library Manager in the Arduino IDE and search for "MQTT". - -The library is also available on [PlatformIO](https://platformio.org/lib/show/617/MQTT). You can install it by running: `pio lib install "MQTT"`. - -## Compatibility - -The following examples show how you can use the library with various Arduino compatible hardware: - -- [Arduino Yun & Yun-Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoYun/ArduinoYun.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoYunSecure/ArduinoYunSecure.ino)) -- [Arduino Ethernet Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoEthernetShield/ArduinoEthernetShield.ino) -- [Arduino WiFi Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoWiFiShield/ArduinoWiFiShield.ino) -- [Adafruit HUZZAH ESP8266](https://github.com/256dpi/arduino-mqtt/blob/master/examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino)) -- [Arduino/Genuino WiFi101 Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoWiFi101/ArduinoWiFi101.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino)) -- [Arduino MKR GSM 1400](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino)) -- [ESP32 Development Board](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino)) - -Other shields and boards should also work if they provide a [Client](https://www.arduino.cc/en/Reference/ClientConstructor) based network implementation. - -## Notes - -- The maximum size for packets being published and received is set by default to 128 bytes. To change the buffer sizes, you need to use `MQTTClient client(256)` instead of just `MQTTClient client` on the top of your sketch. The passed value denotes the read and write buffer size. - -- On the ESP8266 it has been reported that an additional `delay(10);` after `client.loop();` fixes many stability issues with WiFi connections. - -- To use the library with shiftr.io, you need to provide the token key (username) and token secret (password) as the second and third argument to `client.connect(name, key, secret)`. - -## Example - -The following example uses an Arduino MKR1000 to connect to shiftr.io. You can check on your device after a successful connection here: https://shiftr.io/try. - -```c++ -#include -#include -#include - -const char ssid[] = "ssid"; -const char pass[] = "pass"; - -WiFiClient net; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - Serial.print("checking wifi..."); - while (WiFi.status() != WL_CONNECTED) { - Serial.print("."); - delay(1000); - } - - Serial.print("\nconnecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Serial.begin(115200); - WiFi.begin(ssid, pass); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - client.begin("broker.shiftr.io", net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} -``` - -## API - -Initialize the object using the hostname of the broker, the brokers port (default: `1883`) and the underlying Client class for network transport: - -```c++ -void begin(const char hostname[], Client &client); -void begin(const char hostname[], int port, Client &client); -``` - -- Specify port `8883` when using secure clients for encrypted connections. -- Local domain names (e.g. `Computer.local` on OSX) are not supported by Arduino. You need to set the IP address directly. - -The hostname and port can also be changed after calling `begin()`: - -```c++ -void setHost(const char hostname[]); -void setHost(const char hostname[], int port); -``` - -Set a will message (last testament) that gets registered on the broker after connecting. `setWill()` has to be called before calling `connect()`: - -```c++ -void setWill(const char topic[]); -void setWill(const char topic[], const char payload[]); -void setWill(const char topic[], const char payload[], bool retained, int qos); -void clearWill(); -``` - -Register a callback to receive messages: - -```c++ -void onMessage(MQTTClientCallbackSimple); -// Callback signature: void messageReceived(String &topic, String &payload) {} - -void onMessageAdvanced(MQTTClientCallbackAdvanced); -// Callback signature: void messageReceived(MQTTClient *client, char topic[], char payload[], int payload_length) {} -``` - -- The set callback is mostly called during a call to `loop()` but may also be called during a call to `subscribe()`, `unsubscribe()` or `publish() // QoS > 0` if messages have been received before receiving the required acknowledgement. Therefore, it is strongly recommended to not call `subscribe()`, `unsubscribe()` or `publish() // QoS > 0` directly in the callback. - -Set more advanced options: - -```c++ -void setOptions(int keepAlive, bool cleanSession, int timeout); -``` - -- The `keepAlive` option controls the keep alive interval in seconds (default: 10). -- The `cleanSession` option controls the session retention on the broker side (default: true). -- The `timeout` option controls the default timeout for all commands in milliseconds (default: 1000). - -Connect to broker using the supplied client id and an optional username and password: - -```c++ -bool connect(const char clientId[], bool skip = false); -bool connect(const char clientId[], const char username[], bool skip = false); -bool connect(const char clientId[], const char username[], const char password[], bool skip = false); -``` - -- If the `skip` option is set to true, the client will skip the network level connection and jump to the MQTT level connection. This option can be used in order to establish and verify TLS connections manually before giving control to the MQTT client. -- This functions returns a boolean that indicates if the connection has been established successfully. - -Publishes a message to the broker with an optional payload: - -```c++ -bool publish(const String &topic); -bool publish(const char topic[]); -bool publish(const String &topic, const String &payload); -bool publish(const String &topic, const String &payload, bool retained, int qos); -bool publish(const char topic[], const String &payload); -bool publish(const char topic[], const String &payload, bool retained, int qos); -bool publish(const char topic[], const char payload[]); -bool publish(const char topic[], const char payload[], bool retained, int qos); -bool publish(const char topic[], const char payload[], int length); -bool publish(const char topic[], const char payload[], int length, bool retained, int qos); -``` - -Subscribe to a topic: - -```c++ -bool subscribe(const String &topic); -bool subscribe(const String &topic, int qos); -bool subscribe(const char topic[]); -bool subscribe(const char topic[], int qos); -``` - -Unsubscribe from a topic: - -```c++ -bool unsubscribe(const String &topic); -bool unsubscribe(const char topic[]); -``` - -Sends and receives packets: - -```c++ -bool loop(); -``` - -- This function should be called in every `loop`. - -Check if the client is currently connected: - -```c++ -bool connected(); -``` - -Access low-level information for debugging: - -```c++ -lwmqtt_err_t lastError(); -lwmqtt_return_code_t returnCode(); -``` - -- The error codes can be found [here](https://github.com/256dpi/lwmqtt/blob/master/include/lwmqtt.h#L11). -- The return codes can be found [here](https://github.com/256dpi/lwmqtt/blob/master/include/lwmqtt.h#L243). - -Disconnect from the broker: - -```c++ -bool disconnect(); -``` - -## Release Management - -- Update version in `library.properties`. -- Create release on GitHub. diff --git a/lib/arduino-mqtt-2.4.0/examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino b/lib/arduino-mqtt-2.4.0/examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino deleted file mode 100644 index ca5a22607..000000000 --- a/lib/arduino-mqtt-2.4.0/examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino +++ /dev/null @@ -1,69 +0,0 @@ -// This example uses an Adafruit Huzzah ESP8266 -// to connect to shiftr.io. -// -// You can check on your device after a successful -// connection here: https://shiftr.io/try. -// -// by Joël Gähwiler -// https://github.com/256dpi/arduino-mqtt - -#include -#include - -const char ssid[] = "ssid"; -const char pass[] = "pass"; - -WiFiClient net; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - Serial.print("checking wifi..."); - while (WiFi.status() != WL_CONNECTED) { - Serial.print("."); - delay(1000); - } - - Serial.print("\nconnecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Serial.begin(115200); - WiFi.begin(ssid, pass); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - client.begin("broker.shiftr.io", net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - delay(10); // <- fixes some issues with WiFi stability - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} diff --git a/lib/arduino-mqtt-2.4.0/examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino b/lib/arduino-mqtt-2.4.0/examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino deleted file mode 100644 index 1def5678d..000000000 --- a/lib/arduino-mqtt-2.4.0/examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino +++ /dev/null @@ -1,71 +0,0 @@ -// This example uses an Adafruit Huzzah ESP8266 -// to connect to shiftr.io. -// -// You can check on your device after a successful -// connection here: https://shiftr.io/try. -// -// by Joël Gähwiler -// https://github.com/256dpi/arduino-mqtt - -#include -#include - -const char ssid[] = "ssid"; -const char pass[] = "pass"; - -WiFiClientSecure net; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - Serial.print("checking wifi..."); - while (WiFi.status() != WL_CONNECTED) { - Serial.print("."); - delay(1000); - } - - Serial.print("\nconnecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Serial.begin(115200); - WiFi.begin(ssid, pass); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - // - // MQTT brokers usually use port 8883 for secure connections. - client.begin("broker.shiftr.io", 8883, net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - delay(10); // <- fixes some issues with WiFi stability - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} diff --git a/lib/arduino-mqtt-2.4.0/examples/ArduinoEthernetShield/ArduinoEthernetShield.ino b/lib/arduino-mqtt-2.4.0/examples/ArduinoEthernetShield/ArduinoEthernetShield.ino deleted file mode 100644 index 8386c7788..000000000 --- a/lib/arduino-mqtt-2.4.0/examples/ArduinoEthernetShield/ArduinoEthernetShield.ino +++ /dev/null @@ -1,62 +0,0 @@ -// This example uses an Arduino Uno together with -// an Ethernet Shield to connect to shiftr.io. -// -// You can check on your device after a successful -// connection here: https://shiftr.io/try. -// -// by Joël Gähwiler -// https://github.com/256dpi/arduino-mqtt - -#include -#include - -byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; -byte ip[] = {192, 168, 1, 177}; // <- change to match your network - -EthernetClient net; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - Serial.print("connecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Serial.begin(115200); - Ethernet.begin(mac, ip); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - client.begin("broker.shiftr.io", net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} diff --git a/lib/arduino-mqtt-2.4.0/examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino b/lib/arduino-mqtt-2.4.0/examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino deleted file mode 100644 index dd56d5e21..000000000 --- a/lib/arduino-mqtt-2.4.0/examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino +++ /dev/null @@ -1,84 +0,0 @@ -// This example uses an Arduino MKR GSM 1400 board -// to connect to shiftr.io. -// -// IMPORTANT: This example uses the new MKRGSM library. -// -// You can check on your device after a successful -// connection here: https://shiftr.io/try. -// -// by Sandeep Mistry -// https://github.com/256dpi/arduino-mqtt - -#include -#include - -const char pin[] = ""; -const char apn[] = "apn"; -const char login[] = "login"; -const char password[] = "password"; - -GSMClient net; -GPRS gprs; -GSM gsmAccess; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - // connection state - bool connected = false; - - Serial.print("connecting to cellular network ..."); - - // After starting the modem with gsmAccess.begin() - // attach to the GPRS network with the APN, login and password - while (!connected) { - if ((gsmAccess.begin(pin) == GSM_READY) && - (gprs.attachGPRS(apn, login, password) == GPRS_READY)) { - connected = true; - } else { - Serial.print("."); - delay(1000); - } - } - - Serial.print("\nconnecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Serial.begin(115200); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - client.begin("broker.shiftr.io", net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} diff --git a/lib/arduino-mqtt-2.4.0/examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino b/lib/arduino-mqtt-2.4.0/examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino deleted file mode 100644 index 1b172ab6e..000000000 --- a/lib/arduino-mqtt-2.4.0/examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino +++ /dev/null @@ -1,86 +0,0 @@ -// This example uses an Arduino MKR GSM 1400 board -// to securely connect to shiftr.io. -// -// IMPORTANT: This example uses the new MKRGSM library. -// -// You can check on your device after a successful -// connection here: https://shiftr.io/try. -// -// by Sandeep Mistry -// https://github.com/256dpi/arduino-mqtt - -#include -#include - -const char pin[] = ""; -const char apn[] = "apn"; -const char login[] = "login"; -const char password[] = "password"; - -GSMSSLClient net; -GPRS gprs; -GSM gsmAccess; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - // connection state - bool connected = false; - - Serial.print("connecting to cellular network ..."); - - // After starting the modem with gsmAccess.begin() - // attach to the GPRS network with the APN, login and password - while (!connected) { - if ((gsmAccess.begin(pin) == GSM_READY) && - (gprs.attachGPRS(apn, login, password) == GPRS_READY)) { - connected = true; - } else { - Serial.print("."); - delay(1000); - } - } - - Serial.print("\nconnecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Serial.begin(115200); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - // - // MQTT brokers usually use port 8883 for secure connections. - client.begin("broker.shiftr.io", 8883, net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} diff --git a/lib/arduino-mqtt-2.4.0/examples/ArduinoWiFi101/ArduinoWiFi101.ino b/lib/arduino-mqtt-2.4.0/examples/ArduinoWiFi101/ArduinoWiFi101.ino deleted file mode 100644 index a36bd65aa..000000000 --- a/lib/arduino-mqtt-2.4.0/examples/ArduinoWiFi101/ArduinoWiFi101.ino +++ /dev/null @@ -1,70 +0,0 @@ -// This example uses an Arduino/Genuino Zero together with -// a WiFi101 Shield or a MKR1000 to connect to shiftr.io. -// -// IMPORTANT: This example uses the new WiFi101 library. -// -// You can check on your device after a successful -// connection here: https://shiftr.io/try. -// -// by Gilberto Conti -// https://github.com/256dpi/arduino-mqtt - -#include -#include - -const char ssid[] = "ssid"; -const char pass[] = "pass"; - -WiFiClient net; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - Serial.print("checking wifi..."); - while (WiFi.status() != WL_CONNECTED) { - Serial.print("."); - delay(1000); - } - - Serial.print("\nconnecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Serial.begin(115200); - WiFi.begin(ssid, pass); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - client.begin("broker.shiftr.io", net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} diff --git a/lib/arduino-mqtt-2.4.0/examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino b/lib/arduino-mqtt-2.4.0/examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino deleted file mode 100644 index c21e7ae99..000000000 --- a/lib/arduino-mqtt-2.4.0/examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino +++ /dev/null @@ -1,75 +0,0 @@ -// This example uses an Arduino/Genuino Zero together with -// a WiFi101 Shield or a MKR1000 to connect to shiftr.io. -// -// IMPORTANT: This example uses the new WiFi101 library. -// -// IMPORTANT: You need to install/update the SSL certificates first: -// https://github.com/arduino-libraries/WiFi101-FirmwareUpdater#to-update-ssl-certificates -// -// You can check on your device after a successful -// connection here: https://shiftr.io/try. -// -// by Gilberto Conti -// https://github.com/256dpi/arduino-mqtt - -#include -#include - -const char ssid[] = "ssid"; -const char pass[] = "pass"; - -WiFiSSLClient net; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - Serial.print("checking wifi..."); - while (WiFi.status() != WL_CONNECTED) { - Serial.print("."); - delay(1000); - } - - Serial.print("\nconnecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Serial.begin(115200); - WiFi.begin(ssid, pass); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - // - // MQTT brokers usually use port 8883 for secure connections. - client.begin("broker.shiftr.io", 8883, net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} diff --git a/lib/arduino-mqtt-2.4.0/examples/ArduinoWiFiShield/ArduinoWiFiShield.ino b/lib/arduino-mqtt-2.4.0/examples/ArduinoWiFiShield/ArduinoWiFiShield.ino deleted file mode 100644 index 4aff769f4..000000000 --- a/lib/arduino-mqtt-2.4.0/examples/ArduinoWiFiShield/ArduinoWiFiShield.ino +++ /dev/null @@ -1,68 +0,0 @@ -// This example uses an Arduino Uno together with -// a WiFi Shield to connect to shiftr.io. -// -// You can check on your device after a successful -// connection here: https://shiftr.io/try. -// -// by Joël Gähwiler -// https://github.com/256dpi/arduino-mqtt - -#include -#include - -const char ssid[] = "ssid"; -const char pass[] = "pass"; - -WiFiClient net; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - Serial.print("checking wifi..."); - while (WiFi.status() != WL_CONNECTED) { - Serial.print("."); - delay(1000); - } - - Serial.print("\nconnecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Serial.begin(115200); - WiFi.begin(ssid, pass); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - client.begin("broker.shiftr.io", net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} diff --git a/lib/arduino-mqtt-2.4.0/examples/ArduinoYun/ArduinoYun.ino b/lib/arduino-mqtt-2.4.0/examples/ArduinoYun/ArduinoYun.ino deleted file mode 100644 index 823bdff36..000000000 --- a/lib/arduino-mqtt-2.4.0/examples/ArduinoYun/ArduinoYun.ino +++ /dev/null @@ -1,60 +0,0 @@ -// This example uses an Arduino Yun or a Yun-Shield -// and the MQTTClient to connect to shiftr.io. -// -// You can check on your device after a successful -// connection here: https://shiftr.io/try. -// -// by Joël Gähwiler -// https://github.com/256dpi/arduino-mqtt - -#include -#include -#include - -BridgeClient net; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - Serial.print("connecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Bridge.begin(); - Serial.begin(115200); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - client.begin("broker.shiftr.io", net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} diff --git a/lib/arduino-mqtt-2.4.0/examples/ArduinoYunSecure/ArduinoYunSecure.ino b/lib/arduino-mqtt-2.4.0/examples/ArduinoYunSecure/ArduinoYunSecure.ino deleted file mode 100644 index 46c068ab2..000000000 --- a/lib/arduino-mqtt-2.4.0/examples/ArduinoYunSecure/ArduinoYunSecure.ino +++ /dev/null @@ -1,62 +0,0 @@ -// This example uses an Arduino Yun or a Yun-Shield -// and the MQTTClient to connect to shiftr.io. -// -// You can check on your device after a successful -// connection here: https://shiftr.io/try. -// -// by Joël Gähwiler -// https://github.com/256dpi/arduino-mqtt - -#include -#include -#include - -BridgeSSLClient net; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - Serial.print("connecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Bridge.begin(); - Serial.begin(115200); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - // - // MQTT brokers usually use port 8883 for secure connections. - client.begin("broker.shiftr.io", 8883, net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} diff --git a/lib/arduino-mqtt-2.4.0/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino b/lib/arduino-mqtt-2.4.0/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino deleted file mode 100644 index c6919280d..000000000 --- a/lib/arduino-mqtt-2.4.0/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino +++ /dev/null @@ -1,69 +0,0 @@ -// This example uses an ESP32 Development Board -// to connect to shiftr.io. -// -// You can check on your device after a successful -// connection here: https://shiftr.io/try. -// -// by Joël Gähwiler -// https://github.com/256dpi/arduino-mqtt - -#include -#include - -const char ssid[] = "ssid"; -const char pass[] = "pass"; - -WiFiClient net; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - Serial.print("checking wifi..."); - while (WiFi.status() != WL_CONNECTED) { - Serial.print("."); - delay(1000); - } - - Serial.print("\nconnecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Serial.begin(115200); - WiFi.begin(ssid, pass); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - client.begin("broker.shiftr.io", net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - delay(10); // <- fixes some issues with WiFi stability - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} diff --git a/lib/arduino-mqtt-2.4.0/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino b/lib/arduino-mqtt-2.4.0/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino deleted file mode 100644 index cff75379e..000000000 --- a/lib/arduino-mqtt-2.4.0/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino +++ /dev/null @@ -1,71 +0,0 @@ -// This example uses an ESP32 Development Board -// to connect to shiftr.io. -// -// You can check on your device after a successful -// connection here: https://shiftr.io/try. -// -// by Joël Gähwiler -// https://github.com/256dpi/arduino-mqtt - -#include -#include - -const char ssid[] = "ssid"; -const char pass[] = "pass"; - -WiFiClientSecure net; -MQTTClient client; - -unsigned long lastMillis = 0; - -void connect() { - Serial.print("checking wifi..."); - while (WiFi.status() != WL_CONNECTED) { - Serial.print("."); - delay(1000); - } - - Serial.print("\nconnecting..."); - while (!client.connect("arduino", "try", "try")) { - Serial.print("."); - delay(1000); - } - - Serial.println("\nconnected!"); - - client.subscribe("/hello"); - // client.unsubscribe("/hello"); -} - -void messageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); -} - -void setup() { - Serial.begin(115200); - WiFi.begin(ssid, pass); - - // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino. - // You need to set the IP address directly. - // - // MQTT brokers usually use port 8883 for secure connections. - client.begin("broker.shiftr.io", 8883, net); - client.onMessage(messageReceived); - - connect(); -} - -void loop() { - client.loop(); - delay(10); // <- fixes some issues with WiFi stability - - if (!client.connected()) { - connect(); - } - - // publish a message roughly every second. - if (millis() - lastMillis > 1000) { - lastMillis = millis(); - client.publish("/hello", "world"); - } -} diff --git a/lib/arduino-mqtt-2.4.0/library.properties b/lib/arduino-mqtt-2.4.0/library.properties deleted file mode 100644 index 0cf498e9b..000000000 --- a/lib/arduino-mqtt-2.4.0/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=MQTT -version=2.4.0 -author=Joel Gaehwiler -maintainer=Joel Gaehwiler -sentence=MQTT library for Arduino -paragraph=This library bundles the lwmqtt client and adds a thin wrapper to get an Arduino like API. -category=Communication -url=https://github.com/256dpi/arduino-mqtt -architectures=* diff --git a/lib/arduino-mqtt-2.4.0/src/MQTT.h b/lib/arduino-mqtt-2.4.0/src/MQTT.h deleted file mode 100644 index 35652c45f..000000000 --- a/lib/arduino-mqtt-2.4.0/src/MQTT.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef MQTT_H -#define MQTT_H - -#include "MQTTClient.h" - -#endif diff --git a/lib/arduino-mqtt-2.4.0/src/MQTTClient.h b/lib/arduino-mqtt-2.4.0/src/MQTTClient.h deleted file mode 100644 index d87f62cd5..000000000 --- a/lib/arduino-mqtt-2.4.0/src/MQTTClient.h +++ /dev/null @@ -1,491 +0,0 @@ -#ifndef MQTT_CLIENT_H -#define MQTT_CLIENT_H - -#include -#include -#include - -extern "C" { -#include "lwmqtt/lwmqtt.h" -}; - -typedef struct { - uint32_t end; -} lwmqtt_arduino_timer_t; - -void lwmqtt_arduino_timer_set(void *ref, uint32_t timeout); - -int32_t lwmqtt_arduino_timer_get(void *ref); - -typedef struct { - Client *client; -} lwmqtt_arduino_network_t; - -void lwmqtt_arduino_timer_set(void *ref, uint32_t timeout) { - // cast timer reference - auto t = (lwmqtt_arduino_timer_t *)ref; - - // set future end time - t->end = (uint32_t)(millis() + timeout); -} - -int32_t lwmqtt_arduino_timer_get(void *ref) { - // cast timer reference - auto t = (lwmqtt_arduino_timer_t *)ref; - - // get difference to end time - return (int32_t)t->end - (int32_t)millis(); -} - -lwmqtt_err_t lwmqtt_arduino_network_read(void *ref, uint8_t *buffer, size_t len, size_t *read, uint32_t timeout) { - // cast network reference - auto n = (lwmqtt_arduino_network_t *)ref; - - // set timeout - n->client->setTimeout(timeout); - - // read bytes - *read = n->client->readBytes(buffer, len); - if (*read <= 0) { - return LWMQTT_NETWORK_FAILED_READ; - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_arduino_network_write(void *ref, uint8_t *buffer, size_t len, size_t *sent, uint32_t /*timeout*/) { - // cast network reference - auto n = (lwmqtt_arduino_network_t *)ref; - - // write bytes - *sent = n->client->write(buffer, len); - if (*sent <= 0) { - return LWMQTT_NETWORK_FAILED_WRITE; - }; - - return LWMQTT_SUCCESS; -} - -class MQTTClient; - -typedef void (*MQTTClientCallbackSimple)(String &topic, String &payload); -typedef void (*MQTTClientCallbackAdvanced)(MQTTClient *client, char topic[], char bytes[], int length); - -typedef struct { - MQTTClient *client = nullptr; - MQTTClientCallbackSimple simple = nullptr; - MQTTClientCallbackAdvanced advanced = nullptr; -} MQTTClientCallback; - -static void MQTTClientHandler(lwmqtt_client_t * /*client*/, void *ref, lwmqtt_string_t topic, - lwmqtt_message_t message) { - // get callback - auto cb = (MQTTClientCallback *)ref; - - // null terminate topic - char terminated_topic[topic.len + 1]; - memcpy(terminated_topic, topic.data, topic.len); - terminated_topic[topic.len] = '\0'; - - // null terminate payload if available - if (message.payload != nullptr) { - message.payload[message.payload_len] = '\0'; - } - - // call the advanced callback and return if available - if (cb->advanced != nullptr) { - cb->advanced(cb->client, terminated_topic, (char *)message.payload, (int)message.payload_len); - return; - } - - // return if simple callback is not set - if (cb->simple == nullptr) { - return; - } - - // create topic string - String str_topic = String(terminated_topic); - - // create payload string - String str_payload; - if (message.payload != nullptr) { - str_payload = String((const char *)message.payload); - } - - // call simple callback - cb->simple(str_topic, str_payload); -} - -class MQTTClient { - private: - size_t bufSize = 0; - uint8_t *readBuf = nullptr; - uint8_t *writeBuf = nullptr; - - uint16_t keepAlive = 10; - bool cleanSession = true; - uint32_t timeout = 1000; - - Client *netClient = nullptr; - const char *hostname = nullptr; - int port = 0; - lwmqtt_will_t *will = nullptr; - MQTTClientCallback callback; - - lwmqtt_arduino_network_t network = {nullptr}; - lwmqtt_arduino_timer_t timer1 = {0}; - lwmqtt_arduino_timer_t timer2 = {0}; - lwmqtt_client_t client = {0}; - - bool _connected = false; - lwmqtt_return_code_t _returnCode = (lwmqtt_return_code_t)0; - lwmqtt_err_t _lastError = (lwmqtt_err_t)0; - - public: - explicit MQTTClient(int bufSize = 128) { - // reset client - memset(&this->client, 0, sizeof(lwmqtt_client_t)); - - // allocate buffers - this->bufSize = (size_t)bufSize; - this->readBuf = (uint8_t *)malloc((size_t)bufSize + 1); - this->writeBuf = (uint8_t *)malloc((size_t)bufSize); - } - - ~MQTTClient() { - // free will - this->clearWill(); - - // free hostname - if (this->hostname != nullptr) { - free((void *)this->hostname); - } - - // free buffers - free(this->readBuf); - free(this->writeBuf); - } - - void begin(const char hostname[], Client &client) { this->begin(hostname, 1883, client); } - - void begin(const char hostname[], int port, Client &client) { - // set hostname and port - this->setHost(hostname, port); - - // set client - this->netClient = &client; - - // initialize client - lwmqtt_init(&this->client, this->writeBuf, this->bufSize, this->readBuf, this->bufSize); - - // set timers - lwmqtt_set_timers(&this->client, &this->timer1, &this->timer2, lwmqtt_arduino_timer_set, lwmqtt_arduino_timer_get); - - // set network - lwmqtt_set_network(&this->client, &this->network, lwmqtt_arduino_network_read, lwmqtt_arduino_network_write); - - // set callback - lwmqtt_set_callback(&this->client, (void *)&this->callback, MQTTClientHandler); - } - - void onMessage(MQTTClientCallbackSimple cb) { - // set callback - this->callback.client = this; - this->callback.simple = cb; - this->callback.advanced = nullptr; - } - - void onMessageAdvanced(MQTTClientCallbackAdvanced cb) { - // set callback - this->callback.client = this; - this->callback.simple = nullptr; - this->callback.advanced = cb; - } - - void setHost(const char hostname[]) { this->setHost(hostname, 1883); } - - void setHost(const char hostname[], int port) { - // free hostname if set - if (this->hostname != nullptr) { - free((void *)this->hostname); - } - - // set hostname and port - this->hostname = strdup(hostname); - this->port = port; - } - - void setWill(const char topic[]) { this->setWill(topic, ""); } - - void setWill(const char topic[], const char payload[]) { this->setWill(topic, payload, false, 0); } - - void setWill(const char topic[], const char payload[], bool retained, int qos) { - // return if topic is missing - if (topic == nullptr || strlen(topic) == 0) { - return; - } - - // clear existing will - this->clearWill(); - - // allocate will - this->will = (lwmqtt_will_t *)malloc(sizeof(lwmqtt_will_t)); - memset(this->will, 0, sizeof(lwmqtt_will_t)); - - // set topic - this->will->topic = lwmqtt_string(strdup(topic)); - - // set payload if available - if (payload != nullptr && strlen(payload) > 0) { - this->will->payload = lwmqtt_string(strdup(payload)); - } - - // set flags - this->will->retained = retained; - this->will->qos = (lwmqtt_qos_t)qos; - } - - void clearWill() { - // return if not set - if (this->will == nullptr) { - return; - } - - // free payload if set - if (this->will->payload.len > 0) { - free(this->will->payload.data); - } - - // free topic if set - if (this->will->topic.len > 0) { - free(this->will->topic.data); - } - - // free will - free(this->will); - this->will = nullptr; - } - - void setOptions(int keepAlive, bool cleanSession, int timeout) { - // set new options - this->keepAlive = (uint16_t)keepAlive; - this->cleanSession = cleanSession; - this->timeout = (uint32_t)timeout; - } - - bool connect(const char clientId[], bool skip = false) { return this->connect(clientId, nullptr, nullptr); } - - bool connect(const char clientId[], const char username[], bool skip = false) { return this->connect(clientId, username, nullptr); } - - bool connect(const char clientId[], const char username[], const char password[], bool skip = false) { - // close left open connection if still connected - if (!skip && this->connected()) { - this->close(); - } - - // save client - this->network.client = this->netClient; - - // connect to hostg - if(!skip) { - int ret = this->netClient->connect(this->hostname, (uint16_t)this->port); - if (ret <= 0) { - return false; - } - } - - // prepare options - lwmqtt_options_t options = lwmqtt_default_options; - options.keep_alive = this->keepAlive; - options.clean_session = this->cleanSession; - options.client_id = lwmqtt_string(clientId); - - // set username and password if available - if (username != nullptr) { - options.username = lwmqtt_string(username); - - if (password != nullptr) { - options.password = lwmqtt_string(password); - } - } - - // connect to broker - this->_lastError = lwmqtt_connect(&this->client, options, this->will, &this->_returnCode, this->timeout); - if (this->_lastError != LWMQTT_SUCCESS) { - // close connection - this->close(); - - return false; - } - - // set flag - this->_connected = true; - - return true; - } - - bool publish(const String &topic) { return this->publish(topic.c_str(), ""); } - - bool publish(const char topic[]) { return this->publish(topic, ""); } - - bool publish(const String &topic, const String &payload) { return this->publish(topic.c_str(), payload.c_str()); } - - bool publish(const String &topic, const String &payload, bool retained, int qos) { - return this->publish(topic.c_str(), payload.c_str(), retained, qos); - } - - bool publish(const char topic[], const String &payload) { return this->publish(topic, payload.c_str()); } - - bool publish(const char topic[], const String &payload, bool retained, int qos) { - return this->publish(topic, payload.c_str(), retained, qos); - } - - bool publish(const char topic[], const char payload[]) { - return this->publish(topic, (char *)payload, (int)strlen(payload)); - } - - bool publish(const char topic[], const char payload[], bool retained, int qos) { - return this->publish(topic, (char *)payload, (int)strlen(payload), retained, qos); - } - - bool publish(const char topic[], const char payload[], int length) { - return this->publish(topic, payload, length, false, 0); - } - - bool publish(const char topic[], const char payload[], int length, bool retained, int qos) { - // return immediately if not connected - if (!this->connected()) { - return false; - } - - // prepare message - lwmqtt_message_t message = lwmqtt_default_message; - message.payload = (uint8_t *)payload; - message.payload_len = (size_t)length; - message.retained = retained; - message.qos = lwmqtt_qos_t(qos); - - // publish message - this->_lastError = lwmqtt_publish(&this->client, lwmqtt_string(topic), message, this->timeout); - if (this->_lastError != LWMQTT_SUCCESS) { - // close connection - this->close(); - - return false; - } - - return true; - } - - bool subscribe(const String &topic) { return this->subscribe(topic.c_str()); } - - bool subscribe(const String &topic, int qos) { return this->subscribe(topic.c_str(), qos); } - - bool subscribe(const char topic[]) { return this->subscribe(topic, 0); } - - bool subscribe(const char topic[], int qos) { - // return immediately if not connected - if (!this->connected()) { - return false; - } - - // subscribe to topic - this->_lastError = lwmqtt_subscribe_one(&this->client, lwmqtt_string(topic), (lwmqtt_qos_t)qos, this->timeout); - if (this->_lastError != LWMQTT_SUCCESS) { - // close connection - this->close(); - - return false; - } - - return true; - } - - bool unsubscribe(const String &topic) { return this->unsubscribe(topic.c_str()); } - - bool unsubscribe(const char topic[]) { - // return immediately if not connected - if (!this->connected()) { - return false; - } - - // unsubscribe from topic - this->_lastError = lwmqtt_unsubscribe_one(&this->client, lwmqtt_string(topic), this->timeout); - if (this->_lastError != LWMQTT_SUCCESS) { - // close connection - this->close(); - - return false; - } - - return true; - } - - bool loop() { - // return immediately if not connected - if (!this->connected()) { - return false; - } - - // get available bytes on the network - auto available = (size_t)this->netClient->available(); - - // yield if data is available - if (available > 0) { - this->_lastError = lwmqtt_yield(&this->client, available, this->timeout); - if (this->_lastError != LWMQTT_SUCCESS) { - // close connection - this->close(); - - return false; - } - } - - // keep the connection alive - this->_lastError = lwmqtt_keep_alive(&this->client, this->timeout); - if (this->_lastError != LWMQTT_SUCCESS) { - // close connection - this->close(); - - return false; - } - - return true; - } - - bool connected() { - // a client is connected if the network is connected, a client is available and - // the connection has been properly initiated - return this->netClient != nullptr && this->netClient->connected() == 1 && this->_connected; - } - - lwmqtt_err_t lastError() { return this->_lastError; } - - lwmqtt_return_code_t returnCode() { return this->_returnCode; } - - bool disconnect() { - // return immediately if not connected anymore - if (!this->connected()) { - return false; - } - - // cleanly disconnect - this->_lastError = lwmqtt_disconnect(&this->client, this->timeout); - - // close - this->close(); - - return this->_lastError == LWMQTT_SUCCESS; - } - - private: - void close() { - // set flag - this->_connected = false; - - // close network - this->netClient->stop(); - } -}; - -#endif diff --git a/lib/arduino-mqtt-2.4.0/src/lwmqtt/client.c b/lib/arduino-mqtt-2.4.0/src/lwmqtt/client.c deleted file mode 100644 index b1772b9f7..000000000 --- a/lib/arduino-mqtt-2.4.0/src/lwmqtt/client.c +++ /dev/null @@ -1,618 +0,0 @@ -#include "packet.h" - -void lwmqtt_init(lwmqtt_client_t *client, uint8_t *write_buf, size_t write_buf_size, uint8_t *read_buf, - size_t read_buf_size) { - client->last_packet_id = 1; - client->keep_alive_interval = 0; - client->pong_pending = false; - - client->write_buf = write_buf; - client->write_buf_size = write_buf_size; - client->read_buf = read_buf; - client->read_buf_size = read_buf_size; - - client->callback = NULL; - client->callback_ref = NULL; - - client->network = NULL; - client->network_read = NULL; - client->network_write = NULL; - - client->keep_alive_timer = NULL; - client->command_timer = NULL; - client->timer_set = NULL; - client->timer_get = NULL; -} - -void lwmqtt_set_network(lwmqtt_client_t *client, void *ref, lwmqtt_network_read_t read, lwmqtt_network_write_t write) { - client->network = ref; - client->network_read = read; - client->network_write = write; -} - -void lwmqtt_set_timers(lwmqtt_client_t *client, void *keep_alive_timer, void *command_timer, lwmqtt_timer_set_t set, - lwmqtt_timer_get_t get) { - client->keep_alive_timer = keep_alive_timer; - client->command_timer = command_timer; - client->timer_set = set; - client->timer_get = get; - - client->timer_set(client->keep_alive_timer, 0); - client->timer_set(client->command_timer, 0); -} - -void lwmqtt_set_callback(lwmqtt_client_t *client, void *ref, lwmqtt_callback_t cb) { - client->callback_ref = ref; - client->callback = cb; -} - -static uint16_t lwmqtt_get_next_packet_id(lwmqtt_client_t *client) { - // check overflow - if (client->last_packet_id == 65535) { - client->last_packet_id = 1; - return 1; - } - - // increment packet id - client->last_packet_id++; - - return client->last_packet_id; -} - -static lwmqtt_err_t lwmqtt_read_from_network(lwmqtt_client_t *client, size_t offset, size_t len) { - // check read buffer capacity - if (client->read_buf_size < offset + len) { - return LWMQTT_BUFFER_TOO_SHORT; - } - - // prepare counter - size_t read = 0; - - // read while data is missing - while (read < len) { - // check remaining time - int32_t remaining_time = client->timer_get(client->command_timer); - if (remaining_time <= 0) { - return LWMQTT_NETWORK_TIMEOUT; - } - - // read - size_t partial_read = 0; - lwmqtt_err_t err = client->network_read(client->network, client->read_buf + offset + read, len - read, - &partial_read, (uint32_t)remaining_time); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // increment counter - read += partial_read; - } - - return LWMQTT_SUCCESS; -} - -static lwmqtt_err_t lwmqtt_write_to_network(lwmqtt_client_t *client, size_t offset, size_t len) { - // prepare counter - size_t written = 0; - - // write while data is left - while (written < len) { - // check remaining time - int32_t remaining_time = client->timer_get(client->command_timer); - if (remaining_time <= 0) { - return LWMQTT_NETWORK_TIMEOUT; - } - - // write - size_t partial_write = 0; - lwmqtt_err_t err = client->network_write(client->network, client->write_buf + offset + written, len - written, - &partial_write, (uint32_t)remaining_time); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // increment counter - written += partial_write; - } - - return LWMQTT_SUCCESS; -} - -static lwmqtt_err_t lwmqtt_read_packet_in_buffer(lwmqtt_client_t *client, size_t *read, - lwmqtt_packet_type_t *packet_type) { - // preset packet type - *packet_type = LWMQTT_NO_PACKET; - - // read or wait for header byte - lwmqtt_err_t err = lwmqtt_read_from_network(client, 0, 1); - if (err == LWMQTT_NETWORK_TIMEOUT) { - // this is ok as no data has been read at all - return LWMQTT_SUCCESS; - } else if (err != LWMQTT_SUCCESS) { - return err; - } - - // detect packet type - err = lwmqtt_detect_packet_type(client->read_buf, 1, packet_type); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // prepare variables - size_t len = 0; - uint32_t rem_len = 0; - - do { - // adjust len - len++; - - // read next byte - err = lwmqtt_read_from_network(client, len, 1); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // attempt to detect remaining length - err = lwmqtt_detect_remaining_length(client->read_buf + 1, len, &rem_len); - } while (err == LWMQTT_BUFFER_TOO_SHORT); - - // check final error - if (err != LWMQTT_SUCCESS) { - return err; - } - - // read the rest of the buffer if needed - if (rem_len > 0) { - err = lwmqtt_read_from_network(client, 1 + len, rem_len); - if (err != LWMQTT_SUCCESS) { - return err; - } - } - - // adjust counter - *read += 1 + len + rem_len; - - return LWMQTT_SUCCESS; -} - -static lwmqtt_err_t lwmqtt_send_packet_in_buffer(lwmqtt_client_t *client, size_t length) { - // write to network - lwmqtt_err_t err = lwmqtt_write_to_network(client, 0, length); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // reset keep alive timer - client->timer_set(client->keep_alive_timer, client->keep_alive_interval); - - return LWMQTT_SUCCESS; -} - -static lwmqtt_err_t lwmqtt_cycle(lwmqtt_client_t *client, size_t *read, lwmqtt_packet_type_t *packet_type) { - // read next packet from the network - lwmqtt_err_t err = lwmqtt_read_packet_in_buffer(client, read, packet_type); - if (err != LWMQTT_SUCCESS) { - return err; - } else if (*packet_type == LWMQTT_NO_PACKET) { - return LWMQTT_SUCCESS; - } - - switch (*packet_type) { - // handle publish packets - case LWMQTT_PUBLISH_PACKET: { - // decode publish packet - bool dup; - uint16_t packet_id; - lwmqtt_string_t topic; - lwmqtt_message_t msg; - err = lwmqtt_decode_publish(client->read_buf, client->read_buf_size, &dup, &packet_id, &topic, &msg); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // call callback if set - if (client->callback != NULL) { - client->callback(client, client->callback_ref, topic, msg); - } - - // break early on qos zero - if (msg.qos == LWMQTT_QOS0) { - break; - } - - // define ack packet - lwmqtt_packet_type_t ack_type = LWMQTT_NO_PACKET; - if (msg.qos == LWMQTT_QOS1) { - ack_type = LWMQTT_PUBACK_PACKET; - } else if (msg.qos == LWMQTT_QOS2) { - ack_type = LWMQTT_PUBREC_PACKET; - } - - // encode ack packet - size_t len; - err = lwmqtt_encode_ack(client->write_buf, client->write_buf_size, &len, ack_type, false, packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // send ack packet - err = lwmqtt_send_packet_in_buffer(client, len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - break; - } - - // handle pubrec packets - case LWMQTT_PUBREC_PACKET: { - // decode pubrec packet - bool dup; - uint16_t packet_id; - err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, LWMQTT_PUBREC_PACKET, &dup, &packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // encode pubrel packet - size_t len; - err = lwmqtt_encode_ack(client->write_buf, client->write_buf_size, &len, LWMQTT_PUBREL_PACKET, 0, packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // send pubrel packet - err = lwmqtt_send_packet_in_buffer(client, len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - break; - } - - // handle pubrel packets - case LWMQTT_PUBREL_PACKET: { - // decode pubrec packet - bool dup; - uint16_t packet_id; - err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, LWMQTT_PUBREL_PACKET, &dup, &packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // encode pubcomp packet - size_t len; - err = lwmqtt_encode_ack(client->write_buf, client->write_buf_size, &len, LWMQTT_PUBCOMP_PACKET, 0, packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // send pubcomp packet - err = lwmqtt_send_packet_in_buffer(client, len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - break; - } - - // handle pingresp packets - case LWMQTT_PINGRESP_PACKET: { - // set flag - client->pong_pending = false; - - break; - } - - // handle all other packets - default: { break; } - } - - return LWMQTT_SUCCESS; -} - -static lwmqtt_err_t lwmqtt_cycle_until(lwmqtt_client_t *client, lwmqtt_packet_type_t *packet_type, size_t available, - lwmqtt_packet_type_t needle) { - // prepare counter - size_t read = 0; - - // loop until timeout has been reached - do { - // do one cycle - lwmqtt_err_t err = lwmqtt_cycle(client, &read, packet_type); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // return when one packet has been successfully read when no availability has been given - if (needle == LWMQTT_NO_PACKET && available == 0) { - return LWMQTT_SUCCESS; - } - - // otherwise check if needle has been found - if (*packet_type == needle) { - return LWMQTT_SUCCESS; - } - } while (client->timer_get(client->command_timer) > 0 && (available == 0 || read < available)); - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_yield(lwmqtt_client_t *client, size_t available, uint32_t timeout) { - // set command timer - client->timer_set(client->command_timer, timeout); - - // cycle until timeout has been reached - lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET; - lwmqtt_err_t err = lwmqtt_cycle_until(client, &packet_type, available, LWMQTT_NO_PACKET); - if (err != LWMQTT_SUCCESS) { - return err; - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_connect(lwmqtt_client_t *client, lwmqtt_options_t options, lwmqtt_will_t *will, - lwmqtt_return_code_t *return_code, uint32_t timeout) { - // set command timer - client->timer_set(client->command_timer, timeout); - - // save keep alive interval (take 75% to be a little earlier than actually needed) - client->keep_alive_interval = (uint32_t)(options.keep_alive * 750); - - // set keep alive timer - client->timer_set(client->keep_alive_timer, client->keep_alive_interval); - - // reset pong pending flag - client->pong_pending = false; - - // initialize return code - *return_code = LWMQTT_UNKNOWN_RETURN_CODE; - - // encode connect packet - size_t len; - lwmqtt_err_t err = lwmqtt_encode_connect(client->write_buf, client->write_buf_size, &len, options, will); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // send packet - err = lwmqtt_send_packet_in_buffer(client, len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // wait for connack packet - lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET; - err = lwmqtt_cycle_until(client, &packet_type, 0, LWMQTT_CONNACK_PACKET); - if (err != LWMQTT_SUCCESS) { - return err; - } else if (packet_type != LWMQTT_CONNACK_PACKET) { - return LWMQTT_MISSING_OR_WRONG_PACKET; - } - - // decode connack packet - bool session_present; - err = lwmqtt_decode_connack(client->read_buf, client->read_buf_size, &session_present, return_code); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // return error if connection was not accepted - if (*return_code != LWMQTT_CONNECTION_ACCEPTED) { - return LWMQTT_CONNECTION_DENIED; - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_subscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, lwmqtt_qos_t *qos, - uint32_t timeout) { - // set command timer - client->timer_set(client->command_timer, timeout); - - // encode subscribe packet - size_t len; - lwmqtt_err_t err = lwmqtt_encode_subscribe(client->write_buf, client->write_buf_size, &len, - lwmqtt_get_next_packet_id(client), count, topic_filter, qos); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // send packet - err = lwmqtt_send_packet_in_buffer(client, len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // wait for suback packet - lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET; - err = lwmqtt_cycle_until(client, &packet_type, 0, LWMQTT_SUBACK_PACKET); - if (err != LWMQTT_SUCCESS) { - return err; - } else if (packet_type != LWMQTT_SUBACK_PACKET) { - return LWMQTT_MISSING_OR_WRONG_PACKET; - } - - // decode packet - int suback_count = 0; - lwmqtt_qos_t granted_qos[count]; - uint16_t packet_id; - err = lwmqtt_decode_suback(client->read_buf, client->read_buf_size, &packet_id, count, &suback_count, granted_qos); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // check suback codes - for (int i = 0; i < suback_count; i++) { - if (granted_qos[i] == LWMQTT_QOS_FAILURE) { - return LWMQTT_FAILED_SUBSCRIPTION; - } - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_subscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, lwmqtt_qos_t qos, - uint32_t timeout) { - return lwmqtt_subscribe(client, 1, &topic_filter, &qos, timeout); -} - -lwmqtt_err_t lwmqtt_unsubscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, uint32_t timeout) { - // set command timer - client->timer_set(client->command_timer, timeout); - - // encode unsubscribe packet - size_t len; - lwmqtt_err_t err = lwmqtt_encode_unsubscribe(client->write_buf, client->write_buf_size, &len, - lwmqtt_get_next_packet_id(client), count, topic_filter); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // send unsubscribe packet - err = lwmqtt_send_packet_in_buffer(client, len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // wait for unsuback packet - lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET; - err = lwmqtt_cycle_until(client, &packet_type, 0, LWMQTT_UNSUBACK_PACKET); - if (err != LWMQTT_SUCCESS) { - return err; - } else if (packet_type != LWMQTT_UNSUBACK_PACKET) { - return LWMQTT_MISSING_OR_WRONG_PACKET; - } - - // decode unsuback packet - bool dup; - uint16_t packet_id; - err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, LWMQTT_UNSUBACK_PACKET, &dup, &packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_unsubscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, uint32_t timeout) { - return lwmqtt_unsubscribe(client, 1, &topic_filter, timeout); -} - -lwmqtt_err_t lwmqtt_publish(lwmqtt_client_t *client, lwmqtt_string_t topic, lwmqtt_message_t message, - uint32_t timeout) { - // set command timer - client->timer_set(client->command_timer, timeout); - - // add packet id if at least qos 1 - uint16_t packet_id = 0; - if (message.qos == LWMQTT_QOS1 || message.qos == LWMQTT_QOS2) { - packet_id = lwmqtt_get_next_packet_id(client); - } - - // encode publish packet - size_t len = 0; - lwmqtt_err_t err = - lwmqtt_encode_publish(client->write_buf, client->write_buf_size, &len, 0, packet_id, topic, message); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // send packet - err = lwmqtt_send_packet_in_buffer(client, len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // immediately return on qos zero - if (message.qos == LWMQTT_QOS0) { - return LWMQTT_SUCCESS; - } - - // define ack packet - lwmqtt_packet_type_t ack_type = LWMQTT_NO_PACKET; - if (message.qos == LWMQTT_QOS1) { - ack_type = LWMQTT_PUBACK_PACKET; - } else if (message.qos == LWMQTT_QOS2) { - ack_type = LWMQTT_PUBCOMP_PACKET; - } - - // wait for ack packet - lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET; - err = lwmqtt_cycle_until(client, &packet_type, 0, ack_type); - if (err != LWMQTT_SUCCESS) { - return err; - } else if (packet_type != ack_type) { - return LWMQTT_MISSING_OR_WRONG_PACKET; - } - - // decode ack packet - bool dup; - err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, ack_type, &dup, &packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_disconnect(lwmqtt_client_t *client, uint32_t timeout) { - // set command timer - client->timer_set(client->command_timer, timeout); - - // encode disconnect packet - size_t len; - lwmqtt_err_t err = lwmqtt_encode_zero(client->write_buf, client->write_buf_size, &len, LWMQTT_DISCONNECT_PACKET); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // send disconnected packet - err = lwmqtt_send_packet_in_buffer(client, len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_keep_alive(lwmqtt_client_t *client, uint32_t timeout) { - // set command timer - client->timer_set(client->command_timer, timeout); - - // return immediately if keep alive interval is zero - if (client->keep_alive_interval == 0) { - return LWMQTT_SUCCESS; - } - - // return immediately if no ping is due - if (client->timer_get(client->keep_alive_timer) > 0) { - return LWMQTT_SUCCESS; - } - - // a ping is due - - // fail immediately if a pong is already pending - if (client->pong_pending) { - return LWMQTT_PONG_TIMEOUT; - } - - // encode pingreq packet - size_t len; - lwmqtt_err_t err = lwmqtt_encode_zero(client->write_buf, client->write_buf_size, &len, LWMQTT_PINGREQ_PACKET); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // send packet - err = lwmqtt_send_packet_in_buffer(client, len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // set flag - client->pong_pending = true; - - return LWMQTT_SUCCESS; -} diff --git a/lib/arduino-mqtt-2.4.0/src/lwmqtt/helpers.c b/lib/arduino-mqtt-2.4.0/src/lwmqtt/helpers.c deleted file mode 100644 index 9c78f4eaf..000000000 --- a/lib/arduino-mqtt-2.4.0/src/lwmqtt/helpers.c +++ /dev/null @@ -1,249 +0,0 @@ -#include - -#include "helpers.h" - -uint8_t lwmqtt_read_bits(uint8_t byte, int pos, int num) { return (byte & (uint8_t)((~(0xFF << num)) << pos)) >> pos; } - -void lwmqtt_write_bits(uint8_t *byte, uint8_t value, int pos, int num) { - *byte = (*byte & ~(uint8_t)((~(0xFF << num)) << pos)) | (value << pos); -} - -lwmqtt_err_t lwmqtt_read_data(uint8_t **buf, const uint8_t *buf_end, uint8_t **data, size_t len) { - // check zero length - if (len == 0) { - *data = NULL; - return LWMQTT_SUCCESS; - } - - // check buffer size - if ((size_t)(buf_end - (*buf)) < len) { - return LWMQTT_BUFFER_TOO_SHORT; - } - - // read data - *data = *buf; - - // advance pointer - *buf += len; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_write_data(uint8_t **buf, const uint8_t *buf_end, uint8_t *data, size_t len) { - // check zero length - if (len == 0) { - return LWMQTT_SUCCESS; - } - - // check buffer size - if ((size_t)(buf_end - (*buf)) < len) { - return LWMQTT_BUFFER_TOO_SHORT; - } - - // write data - memcpy(*buf, data, len); - - // advance pointer - *buf += len; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_read_num(uint8_t **buf, const uint8_t *buf_end, uint16_t *num) { - // check buffer size - if ((size_t)(buf_end - (*buf)) < 2) { - *num = 0; - return LWMQTT_BUFFER_TOO_SHORT; - } - - // read two byte integer - *num = (uint16_t)256 * (*buf)[0] + (*buf)[1]; - - // adjust pointer - *buf += 2; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_write_num(uint8_t **buf, const uint8_t *buf_end, uint16_t num) { - // check buffer size - if ((size_t)(buf_end - (*buf)) < 2) { - return LWMQTT_BUFFER_TOO_SHORT; - } - - // write bytes - (*buf)[0] = (uint8_t)(num / 256); - (*buf)[1] = (uint8_t)(num % 256); - - // adjust pointer - *buf += 2; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_read_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t *str) { - // read length - uint16_t len; - lwmqtt_err_t err = lwmqtt_read_num(buf, buf_end, &len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // read data - err = lwmqtt_read_data(buf, buf_end, (uint8_t **)&str->data, len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // set length - str->len = len; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_write_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t str) { - // write string length - lwmqtt_err_t err = lwmqtt_write_num(buf, buf_end, str.len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write data - err = lwmqtt_write_data(buf, buf_end, (uint8_t *)str.data, str.len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_read_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t *byte) { - // check buffer size - if ((size_t)(buf_end - (*buf)) < 1) { - *byte = 0; - return LWMQTT_BUFFER_TOO_SHORT; - } - - // read byte - *byte = (*buf)[0]; - - // adjust pointer - *buf += 1; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_write_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t byte) { - // check buffer size - if ((size_t)(buf_end - (*buf)) < 1) { - return LWMQTT_BUFFER_TOO_SHORT; - } - - // write byte - (*buf)[0] = byte; - - // adjust pointer - *buf += 1; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_varnum_length(uint32_t varnum, int *len) { - if (varnum < 128) { - *len = 1; - return LWMQTT_SUCCESS; - } else if (varnum < 16384) { - *len = 2; - return LWMQTT_SUCCESS; - } else if (varnum < 2097151) { - *len = 3; - return LWMQTT_SUCCESS; - } else if (varnum < 268435455) { - *len = 4; - return LWMQTT_SUCCESS; - } else { - *len = 0; - return LWMQTT_VARNUM_OVERFLOW; - } -} - -lwmqtt_err_t lwmqtt_read_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t *varnum) { - // prepare last byte - uint8_t byte; - - // prepare multiplier - uint32_t multiplier = 1; - - // prepare length - size_t len = 0; - - // initialize number - *varnum = 0; - - // decode variadic number - do { - // increment length - len++; - - // return error if buffer is to small - if ((size_t)(buf_end - (*buf)) < len) { - return LWMQTT_BUFFER_TOO_SHORT; - } - - // return error if the length has overflowed - if (len > 4) { - return LWMQTT_VARNUM_OVERFLOW; - } - - // read byte - byte = (*buf)[len - 1]; - - // add byte to number - *varnum += (byte & 127) * multiplier; - - // increase multiplier - multiplier *= 128; - } while ((byte & 128) != 0); - - // adjust pointer - *buf += len; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_write_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t varnum) { - // init len counter - size_t len = 0; - - // encode variadic number - do { - // check overflow - if (len == 4) { - return LWMQTT_VARNUM_OVERFLOW; - } - - // return error if buffer is to small - if ((size_t)(buf_end - (*buf)) < len + 1) { - return LWMQTT_BUFFER_TOO_SHORT; - } - - // calculate current byte - uint8_t byte = (uint8_t)(varnum % 128); - - // change remaining length - varnum /= 128; - - // set the top bit of this byte if there are more to encode - if (varnum > 0) { - byte |= 0x80; - } - - // write byte - (*buf)[len++] = byte; - } while (varnum > 0); - - // adjust pointer - *buf += len; - - return LWMQTT_SUCCESS; -} diff --git a/lib/arduino-mqtt-2.4.0/src/lwmqtt/helpers.h b/lib/arduino-mqtt-2.4.0/src/lwmqtt/helpers.h deleted file mode 100644 index 978eaf4a5..000000000 --- a/lib/arduino-mqtt-2.4.0/src/lwmqtt/helpers.h +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef LWMQTT_HELPERS_H -#define LWMQTT_HELPERS_H - -#include "lwmqtt.h" - -/** - * Reads bits from a byte. - * - * @param byte - The byte to read from. - * @param pos - The position of the first bit. - * @param num - The number of bits to read. - * @return The read bits as a byte. - */ -uint8_t lwmqtt_read_bits(uint8_t byte, int pos, int num); - -/** - * Write bits to a byte. - * - * @param byte - The byte to write bits to. - * @param value - The bits to write as a byte. - * @param pos - The position of the first bit. - * @param num - The number of bits to write. - */ -void lwmqtt_write_bits(uint8_t *byte, uint8_t value, int pos, int num); - -/** - * Reads arbitrary data from the specified buffer. The pointer is incremented by bytes read. - * - * @param buf - Pointer to the buffer. - * @param buf_end - Pointer to the end of the buffer. - * @param data - Pointer to beginning of data. - * @param len - The amount of data to read. - * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. - */ -lwmqtt_err_t lwmqtt_read_data(uint8_t **buf, const uint8_t *buf_end, uint8_t **data, size_t len); - -/** - * Writes arbitrary data to the specified buffer. The pointer is incremented by the bytes written. - * - * @param buf - Pointer to the buffer. - * @param buf_end - Pointer to the end of the buffer. - * @param data - Pointer to the to be written data. - * @param len - The amount of data to write. - * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. - */ -lwmqtt_err_t lwmqtt_write_data(uint8_t **buf, const uint8_t *buf_end, uint8_t *data, size_t len); - -/** - * Reads two byte number from the specified buffer. The pointer is incremented by two. - * - * @param buf - Pointer to the buffer. - * @param buf_end - Pointer to the end of the buffer. - * @param num - The read number. - * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. - */ -lwmqtt_err_t lwmqtt_read_num(uint8_t **buf, const uint8_t *buf_end, uint16_t *num); - -/** - * Writes a two byte number to the specified buffer. The pointer is incremented by two. - * - * @param buf - Pointer to the buffer. - * @param buf_end - Pointer to the end of the buffer. - * @param num - The number to write. - * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. - */ -lwmqtt_err_t lwmqtt_write_num(uint8_t **buf, const uint8_t *buf_end, uint16_t num); - -/** - * Reads a string from the specified buffer into the passed object. The pointer is incremented by the bytes read. - * - * @param buf - Pointer to the buffer. - * @param buf_end - Pointer to the end of the buffer. - * @param str - The object into which the data is to be read. - * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. - */ -lwmqtt_err_t lwmqtt_read_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t *str); - -/** - * Writes a string to the specified buffer. The pointer is incremented by the bytes written. - * - * @param buf - Pointer to the buffer. - * @param buf_end - Pointer to the end of the buffer. - * @param str - The string to write. - * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. - */ -lwmqtt_err_t lwmqtt_write_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t str); - -/** - * Reads one byte from the buffer. The pointer is incremented by one. - * - * @param buf - Pointer to the buffer. - * @param buf_end - Pointer to the end of the buffer. - * @param byte - The read byte. - * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. - */ -lwmqtt_err_t lwmqtt_read_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t *byte); - -/** - * Writes one byte to the specified buffer. The pointer is incremented by one. - * - * @param buf - Pointer to the buffer. - * @param buf_end - Pointer to the end of the buffer. - * @param byte - The byte to write. - * @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT. - */ -lwmqtt_err_t lwmqtt_write_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t byte); - -/** - * Returns the amount of bytes required by the variable number. - * - * @param varnum - The number to check. - * @param len - The required length; - * @return LWMQTT_SUCCESS or LWMQTT_VARNUM_OVERFLOW. - */ -lwmqtt_err_t lwmqtt_varnum_length(uint32_t varnum, int *len); - -/** - * Reads a variable number from the specified buffer. The pointer is incremented by the bytes read. - * - * @param buf - Pointer to the buffer. - * @param buf_end - Pointer to the end of the buffer. - * @param varnum - The read varnum. - * @return LWMQTT_SUCCESS, LWMQTT_BUFFER_TOO_SHORT or LWMQTT_VARNUM_OVERFLOW. - */ -lwmqtt_err_t lwmqtt_read_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t *varnum); - -/** - * Writes a variable number to the specified buffer. The pointer is incremented by the bytes written. - * - * @param buf - Pointer to the buffer. - * @param buf_end - Pointer to the end of the buffer. - * @param varnum - The number to write. - * @return LWMQTT_SUCCESS, LWMQTT_BUFFER_TOO_SHORT or LWMQTT_VARNUM_OVERFLOW. - */ -lwmqtt_err_t lwmqtt_write_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t varnum); - -#endif diff --git a/lib/arduino-mqtt-2.4.0/src/lwmqtt/lwmqtt.h b/lib/arduino-mqtt-2.4.0/src/lwmqtt/lwmqtt.h deleted file mode 100644 index 7a7f142cc..000000000 --- a/lib/arduino-mqtt-2.4.0/src/lwmqtt/lwmqtt.h +++ /dev/null @@ -1,381 +0,0 @@ -#ifndef LWMQTT_H -#define LWMQTT_H - -#include -#include -#include - -/** - * The error type used by all exposed APIs. - * - * If a function returns an error that operates on a connected client (e.g publish, keep_alive, etc.) the caller should - * switch into a disconnected state, close and cleanup the current connection and start over by creating a new - * connection. - */ -typedef enum { - LWMQTT_SUCCESS = 0, - LWMQTT_BUFFER_TOO_SHORT = -1, - LWMQTT_VARNUM_OVERFLOW = -2, - LWMQTT_NETWORK_FAILED_CONNECT = -3, - LWMQTT_NETWORK_TIMEOUT = -4, - LWMQTT_NETWORK_FAILED_READ = -5, - LWMQTT_NETWORK_FAILED_WRITE = -6, - LWMQTT_REMAINING_LENGTH_OVERFLOW = -7, - LWMQTT_REMAINING_LENGTH_MISMATCH = -8, - LWMQTT_MISSING_OR_WRONG_PACKET = -9, - LWMQTT_CONNECTION_DENIED = -10, - LWMQTT_FAILED_SUBSCRIPTION = -11, - LWMQTT_SUBACK_ARRAY_OVERFLOW = -12, - LWMQTT_PONG_TIMEOUT = -13, -} lwmqtt_err_t; - -/** - * A common string object. - */ -typedef struct { - uint16_t len; - char *data; -} lwmqtt_string_t; - -/** - * The initializer for string objects. - */ -#define lwmqtt_default_string \ - { 0, NULL } - -/** - * Returns a string object for the passed C string. - * - * @param str - The C string. - * @return A string object. - */ -lwmqtt_string_t lwmqtt_string(const char *str); - -/** - * Compares a string object to a C string. - * - * @param a - The string object to compare. - * @param b - The C string to compare. - * @return Similarity e.g. strcmp(). - */ -int lwmqtt_strcmp(lwmqtt_string_t a, const char *b); - -/** - * The available QOS levels. - */ -typedef enum { LWMQTT_QOS0 = 0, LWMQTT_QOS1 = 1, LWMQTT_QOS2 = 2, LWMQTT_QOS_FAILURE = 128 } lwmqtt_qos_t; - -/** - * The message object used to publish and receive messages. - */ -typedef struct { - lwmqtt_qos_t qos; - bool retained; - uint8_t *payload; - size_t payload_len; -} lwmqtt_message_t; - -/** - * The initializer for message objects. - */ -#define lwmqtt_default_message \ - { LWMQTT_QOS0, false, NULL, 0 } - -/** - * Forward declaration of the client object. - */ -typedef struct lwmqtt_client_t lwmqtt_client_t; - -/** - * The callback used to read from a network object. - * - * The callbacks is expected to read up to the amount of bytes in to the passed buffer. It should block the specified - * timeout and wait for more incoming data. - * - * @param ref - A custom reference. - * @param buf - The buffer. - * @param len - The length of the buffer. - * @param read - Variable that must be set with the amount of read bytes. - * @param timeout - The timeout in milliseconds for the operation. - */ -typedef lwmqtt_err_t (*lwmqtt_network_read_t)(void *ref, uint8_t *buf, size_t len, size_t *read, uint32_t timeout); - -/** - * The callback used to write to a network object. - * - * The callback is expected to write up to the amount of bytes from the passed buffer. It should wait up to the - * specified timeout to write the specified data to the network. - * - * @param ref - A custom reference. - * @param buf - The buffer. - * @param len - The length of the buffer. - * @param sent - Variable that must be set with the amount of written bytes. - * @param timeout - The timeout in milliseconds for the operation. - */ -typedef lwmqtt_err_t (*lwmqtt_network_write_t)(void *ref, uint8_t *buf, size_t len, size_t *sent, uint32_t timeout); - -/** - * The callback used to set a timer. - * - * @param ref - A custom reference. - * @param timeout - The amount of milliseconds until the deadline. - */ -typedef void (*lwmqtt_timer_set_t)(void *ref, uint32_t timeout); - -/** - * The callback used to get a timers value. - * - * @param - A custom reference. - * @return The amount of milliseconds until the deadline. May return negative numbers if the deadline has been reached. - */ -typedef int32_t (*lwmqtt_timer_get_t)(void *ref); - -/** - * The callback used to forward incoming messages. - * - * Note: The callback is mostly executed because of a call to lwmqtt_yield() that processes incoming messages. However, - * it is possible that the callback is also executed during a call to lwmqtt_subscribe(), lwmqtt_publish() or - * lwmqtt_unsubscribe() if incoming messages are received between the required acknowledgements. It is therefore not - * recommended to call any further lwmqtt methods in the callback as this might result in weird call stacks. The - * callback should place the received messages in a queue and dispatch them after the caller has returned. - */ -typedef void (*lwmqtt_callback_t)(lwmqtt_client_t *client, void *ref, lwmqtt_string_t str, lwmqtt_message_t msg); - -/** - * The client object. - */ -struct lwmqtt_client_t { - uint16_t last_packet_id; - uint32_t keep_alive_interval; - bool pong_pending; - - size_t write_buf_size, read_buf_size; - uint8_t *write_buf, *read_buf; - - lwmqtt_callback_t callback; - void *callback_ref; - - void *network; - lwmqtt_network_read_t network_read; - lwmqtt_network_write_t network_write; - - void *keep_alive_timer; - void *command_timer; - lwmqtt_timer_set_t timer_set; - lwmqtt_timer_get_t timer_get; -}; - -/** - * Will initialize the specified client object. - * - * @param client - The client object. - * @param write_buf - The write buffer. - * @param write_buf_size - The write buffer size. - * @param read_buf - The read buffer. - * @param read_buf_size - The read buffer size. - */ -void lwmqtt_init(lwmqtt_client_t *client, uint8_t *write_buf, size_t write_buf_size, uint8_t *read_buf, - size_t read_buf_size); - -/** - * Will set the network reference and callbacks for this client object. - * - * @param client - The client object. - * @param ref - The reference to the network object. - * @param read - The read callback. - * @param write - The write callback. - */ -void lwmqtt_set_network(lwmqtt_client_t *client, void *ref, lwmqtt_network_read_t read, lwmqtt_network_write_t write); - -/** - * Will set the timer references and callbacks for this client object. - * - * @param client - The client object. - * @param keep_alive_timer - The reference to the keep alive timer. - * @param command_timer - The reference to the command timer. - * @param set - The set callback. - * @param get - The get callback. - */ -void lwmqtt_set_timers(lwmqtt_client_t *client, void *keep_alive_timer, void *command_timer, lwmqtt_timer_set_t set, - lwmqtt_timer_get_t get); - -/** - * Will set the callback used to receive incoming messages. - * - * @param client - The client object. - * @param ref - A custom reference that will passed to the callback. - * @param cb - The callback to be called. - */ -void lwmqtt_set_callback(lwmqtt_client_t *client, void *ref, lwmqtt_callback_t cb); - -/** - * The object defining the last will of a client. - */ -typedef struct { - lwmqtt_string_t topic; - lwmqtt_qos_t qos; - bool retained; - lwmqtt_string_t payload; -} lwmqtt_will_t; - -/** - * The default initializer for the will object. - */ -#define lwmqtt_default_will \ - { lwmqtt_default_string, LWMQTT_QOS0, false, lwmqtt_default_string } - -/** - * The object containing the connection options for a client. - */ -typedef struct { - lwmqtt_string_t client_id; - uint16_t keep_alive; - bool clean_session; - lwmqtt_string_t username; - lwmqtt_string_t password; -} lwmqtt_options_t; - -/** - * The default initializer for the options object. - */ -#define lwmqtt_default_options \ - { lwmqtt_default_string, 60, true, lwmqtt_default_string, lwmqtt_default_string } - -/** - * The available return codes transported by the connack packet. - */ -typedef enum { - LWMQTT_CONNECTION_ACCEPTED = 0, - LWMQTT_UNACCEPTABLE_PROTOCOL = 1, - LWMQTT_IDENTIFIER_REJECTED = 2, - LWMQTT_SERVER_UNAVAILABLE = 3, - LWMQTT_BAD_USERNAME_OR_PASSWORD = 4, - LWMQTT_NOT_AUTHORIZED = 5, - LWMQTT_UNKNOWN_RETURN_CODE = 6 -} lwmqtt_return_code_t; - -/** - * Will send a connect packet and wait for a connack response and set the return code. - * - * The network object must already be connected to the server. An error is returned if the broker rejects the - * connection. - * - * @param client - The client object. - * @param options - The options object. - * @param will - The will object. - * @param return_code - The variable that will receive the return code. - * @param timeout - The command timeout. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_connect(lwmqtt_client_t *client, lwmqtt_options_t options, lwmqtt_will_t *will, - lwmqtt_return_code_t *return_code, uint32_t timeout); - -/** - * Will send a publish packet and wait for all acks to complete. - * - * Note: The message callback might be called with incoming messages as part of this call. - * - * @param client - The client object. - * @param topic - The topic. - * @param message - The message. - * @param timeout - The command timeout. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_publish(lwmqtt_client_t *client, lwmqtt_string_t topic, lwmqtt_message_t msg, uint32_t timeout); - -/** - * Will send a subscribe packet with multiple topic filters plus QOS levels and wait for the suback to complete. - * - * Note: The message callback might be called with incoming messages as part of this call. - * - * @param client - The client object. - * @param count - The number of topic filters and QOS levels. - * @param topic_filter - The list of topic filters. - * @param qos - The list of QOS levels. - * @param timeout - The command timeout. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_subscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, lwmqtt_qos_t *qos, - uint32_t timeout); - -/** - * Will send a subscribe packet with a single topic filter plus QOS level and wait for the suback to complete. - * - * Note: The message callback might be called with incoming messages as part of this call. - * - * @param client - The client object. - * @param topic_filter - The topic filter. - * @param qos - The QOS level. - * @param timeout - The command timeout. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_subscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, lwmqtt_qos_t qos, - uint32_t timeout); - -/** - * Will send an unsubscribe packet with multiple topic filters and wait for the unsuback to complete. - * - * Note: The message callback might be called with incoming messages as part of this call. - * - * @param client - The client object. - * @param count - The number of topic filters. - * @param topic_filter - The topic filter. - * @param timeout - The command timeout. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_unsubscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, uint32_t timeout); - -/** - * Will send an unsubscribe packet with a single topic filter and wait for the unsuback to complete. - * - * Note: The message callback might be called with incoming messages as part of this call. - * - * @param client - The client object. - * @param topic_filter - The topic filter. - * @param timeout - The command timeout. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_unsubscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, uint32_t timeout); - -/** - * Will send a disconnect packet and finish the client. - * - * @param client - The client object. - * @param timeout - The command timeout. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_disconnect(lwmqtt_client_t *client, uint32_t timeout); - -/** - * Will yield control to the client and receive incoming packets from the network. - * - * Single-threaded applications may peek on the network and assess if data is available to read before calling yield and - * potentially block until the timeout is reached. Multi-threaded applications may select on the socket and block until - * data is available and then yield to the client if data is available. All applications may specify the amount of bytes - * available to read in order to constrain the yield to only receive packets that are already in-flight. - * - * If no availability info is given the yield will return after one packet has been successfully read or the deadline - * has been reached but no single bytes has been received. - * - * Note: The message callback might be called with incoming messages as part of this call. - * - * @param client - The client object. - * @param available - The available bytes to read. - * @param timeout - The command timeout. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_yield(lwmqtt_client_t *client, size_t available, uint32_t timeout); - -/** - * Will yield control to the client to keep the connection alive. - * - * This functions must be called at a rate slightly lower than 25% of the configured keep alive. If keep alive is zero, - * the function must not be called at all. - * - * @param client - The client object. - * @param timeout - The command timeout. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_keep_alive(lwmqtt_client_t *client, uint32_t timeout); - -#endif // LWMQTT_H diff --git a/lib/arduino-mqtt-2.4.0/src/lwmqtt/packet.c b/lib/arduino-mqtt-2.4.0/src/lwmqtt/packet.c deleted file mode 100644 index 512b44d94..000000000 --- a/lib/arduino-mqtt-2.4.0/src/lwmqtt/packet.c +++ /dev/null @@ -1,742 +0,0 @@ -#include "packet.h" - -lwmqtt_err_t lwmqtt_detect_packet_type(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t *packet_type) { - // set default packet type - *packet_type = LWMQTT_NO_PACKET; - - // prepare pointer - uint8_t *buf_ptr = buf; - uint8_t *buf_end = buf + buf_len; - - // prepare header - uint8_t header; - - // read header - lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // get packet type - *packet_type = (lwmqtt_packet_type_t)lwmqtt_read_bits(header, 4, 4); - - // check if packet type is correct and can be received - switch (*packet_type) { - case LWMQTT_CONNACK_PACKET: - case LWMQTT_PUBLISH_PACKET: - case LWMQTT_PUBACK_PACKET: - case LWMQTT_PUBREC_PACKET: - case LWMQTT_PUBREL_PACKET: - case LWMQTT_PUBCOMP_PACKET: - case LWMQTT_SUBACK_PACKET: - case LWMQTT_UNSUBACK_PACKET: - case LWMQTT_PINGRESP_PACKET: - return LWMQTT_SUCCESS; - default: - *packet_type = LWMQTT_NO_PACKET; - return LWMQTT_MISSING_OR_WRONG_PACKET; - } -} - -lwmqtt_err_t lwmqtt_detect_remaining_length(uint8_t *buf, size_t buf_len, uint32_t *rem_len) { - // prepare pointer - uint8_t *ptr = buf; - - // attempt to decode remaining length - lwmqtt_err_t err = lwmqtt_read_varnum(&ptr, buf + buf_len, rem_len); - if (err == LWMQTT_VARNUM_OVERFLOW) { - *rem_len = 0; - return LWMQTT_REMAINING_LENGTH_OVERFLOW; - } else if (err != LWMQTT_SUCCESS) { - *rem_len = 0; - return err; - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_encode_connect(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_options_t options, - lwmqtt_will_t *will) { - // prepare pointers - uint8_t *buf_ptr = buf; - uint8_t *buf_end = buf + buf_len; - - // fixed header is 10 - uint32_t rem_len = 10; - - // add client id to remaining length - rem_len += options.client_id.len + 2; - - // add will if present to remaining length - if (will != NULL) { - rem_len += will->topic.len + 2 + will->payload.len + 2; - } - - // add username if present to remaining length - if (options.username.len > 0) { - rem_len += options.username.len + 2; - - // add password if present to remaining length - if (options.password.len > 0) { - rem_len += options.password.len + 2; - } - } - - // check remaining length length - int rem_len_len; - lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len); - if (err == LWMQTT_VARNUM_OVERFLOW) { - return LWMQTT_REMAINING_LENGTH_OVERFLOW; - } - - // prepare header - uint8_t header = 0; - lwmqtt_write_bits(&header, LWMQTT_CONNECT_PACKET, 4, 4); - - // write header - err = lwmqtt_write_byte(&buf_ptr, buf_end, header); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write remaining length - err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write version string - err = lwmqtt_write_string(&buf_ptr, buf_end, lwmqtt_string("MQTT")); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write version number - err = lwmqtt_write_byte(&buf_ptr, buf_end, 4); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // prepare flags - uint8_t flags = 0; - - // set clean session - lwmqtt_write_bits(&flags, (uint8_t)(options.clean_session), 1, 1); - - // set will flags if present - if (will != NULL) { - lwmqtt_write_bits(&flags, 1, 2, 1); - lwmqtt_write_bits(&flags, will->qos, 3, 2); - lwmqtt_write_bits(&flags, (uint8_t)(will->retained), 5, 1); - } - - // set username flag if present - if (options.username.len > 0) { - lwmqtt_write_bits(&flags, 1, 7, 1); - - // set password flag if present - if (options.password.len > 0) { - lwmqtt_write_bits(&flags, 1, 6, 1); - } - } - - // write flags - err = lwmqtt_write_byte(&buf_ptr, buf_end, flags); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write keep alive - err = lwmqtt_write_num(&buf_ptr, buf_end, options.keep_alive); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write client id - err = lwmqtt_write_string(&buf_ptr, buf_end, options.client_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write will if present - if (will != NULL) { - // write topic - err = lwmqtt_write_string(&buf_ptr, buf_end, will->topic); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write payload length - err = lwmqtt_write_num(&buf_ptr, buf_end, (uint16_t)will->payload.len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write payload - err = lwmqtt_write_data(&buf_ptr, buf_end, (uint8_t *)will->payload.data, will->payload.len); - if (err != LWMQTT_SUCCESS) { - return err; - } - } - - // write username if present - if (options.username.len > 0) { - err = lwmqtt_write_string(&buf_ptr, buf_end, options.username); - if (err != LWMQTT_SUCCESS) { - return err; - } - } - - // write password if present - if (options.username.len > 0 && options.password.len > 0) { - err = lwmqtt_write_string(&buf_ptr, buf_end, options.password); - if (err != LWMQTT_SUCCESS) { - return err; - } - } - - // set written length - *len = buf_ptr - buf; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_decode_connack(uint8_t *buf, size_t buf_len, bool *session_present, - lwmqtt_return_code_t *return_code) { - // prepare pointers - uint8_t *buf_ptr = buf; - uint8_t *buf_end = buf + buf_len; - - // read header - uint8_t header; - lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // check packet type - if (lwmqtt_read_bits(header, 4, 4) != LWMQTT_CONNACK_PACKET) { - return LWMQTT_MISSING_OR_WRONG_PACKET; - } - - // read remaining length - uint32_t rem_len; - err = lwmqtt_read_varnum(&buf_ptr, buf_end, &rem_len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // check remaining length - if (rem_len != 2) { - return LWMQTT_REMAINING_LENGTH_MISMATCH; - } - - // read flags - uint8_t flags; - err = lwmqtt_read_byte(&buf_ptr, buf_end, &flags); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // read return code - uint8_t raw_return_code; - err = lwmqtt_read_byte(&buf_ptr, buf_end, &raw_return_code); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // get session present - *session_present = lwmqtt_read_bits(flags, 7, 1) == 1; - - // get return code - switch (raw_return_code) { - case 0: - *return_code = LWMQTT_CONNECTION_ACCEPTED; - break; - case 1: - *return_code = LWMQTT_UNACCEPTABLE_PROTOCOL; - break; - case 2: - *return_code = LWMQTT_IDENTIFIER_REJECTED; - break; - case 3: - *return_code = LWMQTT_SERVER_UNAVAILABLE; - break; - case 4: - *return_code = LWMQTT_BAD_USERNAME_OR_PASSWORD; - break; - case 5: - *return_code = LWMQTT_NOT_AUTHORIZED; - break; - default: - *return_code = LWMQTT_UNKNOWN_RETURN_CODE; - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_encode_zero(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type) { - // prepare pointer - uint8_t *buf_ptr = buf; - uint8_t *buf_end = buf + buf_len; - - // write header - uint8_t header = 0; - lwmqtt_write_bits(&header, packet_type, 4, 4); - lwmqtt_err_t err = lwmqtt_write_byte(&buf_ptr, buf_end, header); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write remaining length - err = lwmqtt_write_varnum(&buf_ptr, buf_end, 0); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // set length - *len = buf_ptr - buf; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_decode_ack(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t packet_type, bool *dup, - uint16_t *packet_id) { - // prepare pointer - uint8_t *buf_ptr = buf; - uint8_t *buf_end = buf + buf_len; - - // read header - uint8_t header = 0; - lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // check packet type - if (lwmqtt_read_bits(header, 4, 4) != packet_type) { - return LWMQTT_MISSING_OR_WRONG_PACKET; - } - - // get dup - *dup = lwmqtt_read_bits(header, 3, 1) == 1; - - // read remaining length - uint32_t rem_len; - err = lwmqtt_read_varnum(&buf_ptr, buf + buf_len, &rem_len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // check remaining length - if (rem_len != 2) { - return LWMQTT_REMAINING_LENGTH_MISMATCH; - } - - // read packet id - err = lwmqtt_read_num(&buf_ptr, buf_end, packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_encode_ack(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type, bool dup, - uint16_t packet_id) { - // prepare pointer - uint8_t *buf_ptr = buf; - uint8_t *buf_end = buf + buf_len; - - // prepare header - uint8_t header = 0; - - // set packet type - lwmqtt_write_bits(&header, packet_type, 4, 4); - - // set dup - lwmqtt_write_bits(&header, (uint8_t)(dup), 3, 1); - - // set qos - lwmqtt_write_bits(&header, (uint8_t)(packet_type == LWMQTT_PUBREL_PACKET ? LWMQTT_QOS1 : LWMQTT_QOS0), 1, 2); - - // write header - lwmqtt_err_t err = lwmqtt_write_byte(&buf_ptr, buf_end, header); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write remaining length - err = lwmqtt_write_varnum(&buf_ptr, buf_end, 2); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write packet id - err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // set written length - *len = buf_ptr - buf; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_decode_publish(uint8_t *buf, size_t buf_len, bool *dup, uint16_t *packet_id, lwmqtt_string_t *topic, - lwmqtt_message_t *msg) { - // prepare pointer - uint8_t *buf_ptr = buf; - uint8_t *buf_end = buf + buf_len; - - // read header - uint8_t header; - lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // check packet type - if (lwmqtt_read_bits(header, 4, 4) != LWMQTT_PUBLISH_PACKET) { - return LWMQTT_MISSING_OR_WRONG_PACKET; - } - - // get dup - *dup = lwmqtt_read_bits(header, 3, 1) == 1; - - // get retained - msg->retained = lwmqtt_read_bits(header, 0, 1) == 1; - - // get qos - switch (lwmqtt_read_bits(header, 1, 2)) { - case 0: - msg->qos = LWMQTT_QOS0; - break; - case 1: - msg->qos = LWMQTT_QOS1; - break; - case 2: - msg->qos = LWMQTT_QOS2; - break; - default: - msg->qos = LWMQTT_QOS0; - break; - } - - // read remaining length - uint32_t rem_len; - err = lwmqtt_read_varnum(&buf_ptr, buf_end, &rem_len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // check remaining length (topic length) - if (rem_len < 2) { - return LWMQTT_REMAINING_LENGTH_MISMATCH; - } - - // check buffer capacity - if ((uint32_t)(buf_end - buf_ptr) < rem_len) { - return LWMQTT_BUFFER_TOO_SHORT; - } - - // reset buf end - buf_end = buf_ptr + rem_len; - - // read topic - err = lwmqtt_read_string(&buf_ptr, buf_end, topic); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // read packet id if qos is at least 1 - if (msg->qos > 0) { - err = lwmqtt_read_num(&buf_ptr, buf_end, packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - } else { - *packet_id = 0; - } - - // set payload length - msg->payload_len = buf_end - buf_ptr; - - // read payload - err = lwmqtt_read_data(&buf_ptr, buf_end, &msg->payload, buf_end - buf_ptr); - if (err != LWMQTT_SUCCESS) { - return err; - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_encode_publish(uint8_t *buf, size_t buf_len, size_t *len, bool dup, uint16_t packet_id, - lwmqtt_string_t topic, lwmqtt_message_t msg) { - // prepare pointer - uint8_t *buf_ptr = buf; - uint8_t *buf_end = buf + buf_len; - - // calculate remaining length - uint32_t rem_len = 2 + topic.len + (uint32_t)msg.payload_len; - if (msg.qos > 0) { - rem_len += 2; - } - - // check remaining length length - int rem_len_len; - lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len); - if (err == LWMQTT_VARNUM_OVERFLOW) { - return LWMQTT_REMAINING_LENGTH_OVERFLOW; - } - - // prepare header - uint8_t header = 0; - - // set packet type - lwmqtt_write_bits(&header, LWMQTT_PUBLISH_PACKET, 4, 4); - - // set dup - lwmqtt_write_bits(&header, (uint8_t)(dup), 3, 1); - - // set qos - lwmqtt_write_bits(&header, msg.qos, 1, 2); - - // set retained - lwmqtt_write_bits(&header, (uint8_t)(msg.retained), 0, 1); - - // write header - err = lwmqtt_write_byte(&buf_ptr, buf_end, header); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write remaining length - err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write topic - err = lwmqtt_write_string(&buf_ptr, buf_end, topic); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write packet id if qos is at least 1 - if (msg.qos > 0) { - err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - } - - // write payload - err = lwmqtt_write_data(&buf_ptr, buf_end, msg.payload, msg.payload_len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // set length - *len = buf_ptr - buf; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_encode_subscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count, - lwmqtt_string_t *topic_filters, lwmqtt_qos_t *qos_levels) { - // prepare pointer - uint8_t *buf_ptr = buf; - uint8_t *buf_end = buf + buf_len; - - // calculate remaining length - uint32_t rem_len = 2; - for (int i = 0; i < count; i++) { - rem_len += 2 + topic_filters[i].len + 1; - } - - // check remaining length length - int rem_len_len; - lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len); - if (err == LWMQTT_VARNUM_OVERFLOW) { - return LWMQTT_REMAINING_LENGTH_OVERFLOW; - } - - // prepare header - uint8_t header = 0; - - // set packet type - lwmqtt_write_bits(&header, LWMQTT_SUBSCRIBE_PACKET, 4, 4); - - // set qos - lwmqtt_write_bits(&header, LWMQTT_QOS1, 1, 2); - - // write header - err = lwmqtt_write_byte(&buf_ptr, buf_end, header); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write remaining length - err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write packet id - err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write all subscriptions - for (int i = 0; i < count; i++) { - // write topic - err = lwmqtt_write_string(&buf_ptr, buf_end, topic_filters[i]); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write qos level - err = lwmqtt_write_byte(&buf_ptr, buf_end, (uint8_t)qos_levels[i]); - if (err != LWMQTT_SUCCESS) { - return err; - } - } - - // set length - *len = buf_ptr - buf; - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_decode_suback(uint8_t *buf, size_t buf_len, uint16_t *packet_id, int max_count, int *count, - lwmqtt_qos_t *granted_qos_levels) { - // prepare pointer - uint8_t *buf_ptr = buf; - uint8_t *buf_end = buf + buf_len; - - // read header - uint8_t header; - lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // check packet type - if (lwmqtt_read_bits(header, 4, 4) != LWMQTT_SUBACK_PACKET) { - return LWMQTT_MISSING_OR_WRONG_PACKET; - } - - // read remaining length - uint32_t rem_len; - err = lwmqtt_read_varnum(&buf_ptr, buf_end, &rem_len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // check remaining length (packet id + min. one suback code) - if (rem_len < 3) { - return LWMQTT_REMAINING_LENGTH_MISMATCH; - } - - // read packet id - err = lwmqtt_read_num(&buf_ptr, buf_end, packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // read all suback codes - for (*count = 0; *count < (int)rem_len - 2; (*count)++) { - // check max count - if (*count > max_count) { - return LWMQTT_SUBACK_ARRAY_OVERFLOW; - } - - // read qos level - uint8_t raw_qos_level; - err = lwmqtt_read_byte(&buf_ptr, buf_end, &raw_qos_level); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // set qos level - switch (raw_qos_level) { - case 0: - granted_qos_levels[*count] = LWMQTT_QOS0; - break; - case 1: - granted_qos_levels[*count] = LWMQTT_QOS1; - break; - case 2: - granted_qos_levels[*count] = LWMQTT_QOS2; - break; - default: - granted_qos_levels[*count] = LWMQTT_QOS_FAILURE; - break; - } - } - - return LWMQTT_SUCCESS; -} - -lwmqtt_err_t lwmqtt_encode_unsubscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count, - lwmqtt_string_t *topic_filters) { - // prepare pointer - uint8_t *buf_ptr = buf; - uint8_t *buf_end = buf + buf_len; - - // calculate remaining length - uint32_t rem_len = 2; - for (int i = 0; i < count; i++) { - rem_len += 2 + topic_filters[i].len; - } - - // check remaining length length - int rem_len_len; - lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len); - if (err == LWMQTT_VARNUM_OVERFLOW) { - return LWMQTT_REMAINING_LENGTH_OVERFLOW; - } - - // prepare header - uint8_t header = 0; - - // set packet type - lwmqtt_write_bits(&header, LWMQTT_UNSUBSCRIBE_PACKET, 4, 4); - - // set qos - lwmqtt_write_bits(&header, LWMQTT_QOS1, 1, 2); - - // write header - err = lwmqtt_write_byte(&buf_ptr, buf_end, header); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write remaining length - err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write packet id - err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id); - if (err != LWMQTT_SUCCESS) { - return err; - } - - // write topics - for (int i = 0; i < count; i++) { - err = lwmqtt_write_string(&buf_ptr, buf_end, topic_filters[i]); - if (err != LWMQTT_SUCCESS) { - return err; - } - } - - // set length - *len = buf_ptr - buf; - - return LWMQTT_SUCCESS; -} diff --git a/lib/arduino-mqtt-2.4.0/src/lwmqtt/packet.h b/lib/arduino-mqtt-2.4.0/src/lwmqtt/packet.h deleted file mode 100644 index 5fe9e50f1..000000000 --- a/lib/arduino-mqtt-2.4.0/src/lwmqtt/packet.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef LWMQTT_PACKET_H -#define LWMQTT_PACKET_H - -#include "helpers.h" - -/** - * The available packet types. - */ -typedef enum { - LWMQTT_NO_PACKET = 0, - LWMQTT_CONNECT_PACKET = 1, - LWMQTT_CONNACK_PACKET, - LWMQTT_PUBLISH_PACKET, - LWMQTT_PUBACK_PACKET, - LWMQTT_PUBREC_PACKET, - LWMQTT_PUBREL_PACKET, - LWMQTT_PUBCOMP_PACKET, - LWMQTT_SUBSCRIBE_PACKET, - LWMQTT_SUBACK_PACKET, - LWMQTT_UNSUBSCRIBE_PACKET, - LWMQTT_UNSUBACK_PACKET, - LWMQTT_PINGREQ_PACKET, - LWMQTT_PINGRESP_PACKET, - LWMQTT_DISCONNECT_PACKET -} lwmqtt_packet_type_t; - -/** - * Will detect the packet type from the at least one byte long buffer. - * - * @param buf - The buffer from which the packet type will be detected. - * @param buf_len - The length of the specified buffer. - * @param packet_type - The packet type. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_detect_packet_type(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t *packet_type); - -/** - * Will detect the remaining length form the at least on byte long buffer. - * - * It will return LWMQTT_BUFFER_TOO_SHORT if the buffer is to short and an additional byte should be read from the - * network. In case the remaining length is overflowed it will return LWMQTT_REMAINING_LENGTH_OVERFLOW. - * - * @param buf - The buffer from which the remaining length will be detected. - * @param buf_len - The length of the specified buffer. - * @param rem_len - The detected remaining length. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_detect_remaining_length(uint8_t *buf, size_t buf_len, uint32_t *rem_len); - -/** - * Encodes a connect packet into the supplied buffer. - * - * @param buf - The buffer into which the packet will be encoded. - * @param buf_len - The length of the specified buffer. - * @param len - The encoded length of the packet. - * @param options - The options to be used to build the connect packet. - * @param will - The last will and testament. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_encode_connect(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_options_t options, - lwmqtt_will_t *will); - -/** - * Decodes a connack packet from the supplied buffer. - * - * @param buf - The raw buffer data. - * @param buf_len - The length of the specified buffer. - * @param session_present - The session present flag. - * @param return_code - The return code. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_decode_connack(uint8_t *buf, size_t buf_len, bool *session_present, - lwmqtt_return_code_t *return_code); - -/** - * Encodes a zero (disconnect, pingreq) packet into the supplied buffer. - * - * @param buf - The buffer into which the packet will be encoded. - * @param buf_len - The length of the specified buffer. - * @param len - The encoded length of the packet. - * @param packet_type - The packets type. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_encode_zero(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type); - -/** - * Decodes an ack (puback, pubrec, pubrel, pubcomp, unsuback) packet from the supplied buffer. - * - * @param buf - The raw buffer data. - * @param buf_len - The length of the specified buffer. - * @param packet_type - The packet type. - * @param dup - The dup flag. - * @param packet_id - The packet id. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_decode_ack(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t packet_type, bool *dup, - uint16_t *packet_id); - -/** - * Encodes an ack (puback, pubrec, pubrel, pubcomp) packet into the supplied buffer. - * - * @param buf - The buffer into which the packet will be encoded. - * @param buf_len - The length of the specified buffer. - * @param len - The encoded length of the packet. - * @param packet_type - The packets type. - * @param dup - The dup flag. - * @param packet_id - The packet id. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_encode_ack(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type, bool dup, - uint16_t packet_id); - -/** - * Decodes a publish packet from the supplied buffer. - * - * @param buf - The raw buffer data. - * @param buf_len - The length of the specified buffer. - * @param dup - The dup flag. - * @param packet_id - The packet id. - * @param topic - The topic. - * @parma msg - The message. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_decode_publish(uint8_t *buf, size_t buf_len, bool *dup, uint16_t *packet_id, lwmqtt_string_t *topic, - lwmqtt_message_t *msg); - -/** - * Encodes a publish packet into the supplied buffer. - * - * @param buf - The buffer into which the packet will be encoded. - * @param buf_len - The length of the specified buffer. - * @param len - The encoded length of the packet. - * @param dup - The dup flag. - * @param packet_id - The packet id. - * @param topic - The topic. - * @param msg - The message. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_encode_publish(uint8_t *buf, size_t buf_len, size_t *len, bool dup, uint16_t packet_id, - lwmqtt_string_t topic, lwmqtt_message_t msg); - -/** - * Encodes a subscribe packet into the supplied buffer. - * - * @param buf - The buffer into which the packet will be encoded. - * @param buf_len - The length of the specified buffer. - * @param len - The encoded length of the packet. - * @param packet_id - The packet id. - * @param count - The number of members in the topic_filters and qos_levels array. - * @param topic_filters - The array of topic filter. - * @param qos_levels - The array of requested QoS levels. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_encode_subscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count, - lwmqtt_string_t *topic_filters, lwmqtt_qos_t *qos_levels); - -/** - * Decodes a suback packet from the supplied buffer. - * - * @param buf - The raw buffer data. - * @param buf_len - The length of the specified buffer. - * @param packet_id - The packet id. - * @param max_count - The maximum number of members allowed in the granted_qos_levels array. - * @param count - The number of members in the granted_qos_levels array. - * @param granted_qos_levels - The granted QoS levels. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_decode_suback(uint8_t *buf, size_t buf_len, uint16_t *packet_id, int max_count, int *count, - lwmqtt_qos_t *granted_qos_levels); - -/** - * Encodes the supplied unsubscribe data into the supplied buffer, ready for sending - * - * @param buf - The buffer into which the packet will be encoded. - * @param buf_len - The length of the specified buffer. - * @param len - The encoded length of the packet. - * @param packet_id - The packet id. - * @param count - The number of members in the topic_filters array. - * @param topic_filters - The array of topic filters. - * @return An error value. - */ -lwmqtt_err_t lwmqtt_encode_unsubscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count, - lwmqtt_string_t *topic_filters); - -#endif // LWMQTT_PACKET_H diff --git a/lib/arduino-mqtt-2.4.0/src/lwmqtt/string.c b/lib/arduino-mqtt-2.4.0/src/lwmqtt/string.c deleted file mode 100644 index c27dc94e3..000000000 --- a/lib/arduino-mqtt-2.4.0/src/lwmqtt/string.c +++ /dev/null @@ -1,38 +0,0 @@ -#include - -#include "lwmqtt.h" - -lwmqtt_string_t lwmqtt_string(const char *str) { - // check for null - if (str == NULL) { - return (lwmqtt_string_t){0, NULL}; - } - - // get length - uint16_t len = (uint16_t)strlen(str); - - // check zero length - if (len == 0) { - return (lwmqtt_string_t){0, NULL}; - } - - return (lwmqtt_string_t){len, (char *)str}; -} - -int lwmqtt_strcmp(lwmqtt_string_t a, const char *b) { - // get string of b - lwmqtt_string_t b_str = lwmqtt_string(b); - - // return if both are zero length - if (a.len == 0 && b_str.len == 0) { - return 0; - } - - // return if lengths are different - if (a.len != b_str.len) { - return -1; - } - - // compare memory of same length - return strncmp(a.data, b_str.data, a.len); -} diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 63e229fdc..0e7ab1e8c 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.21 20190309 +/* 6.4.2.22 20190315 + * Remove support for MQTT_LIBRARY_TYPE, MQTT_ARDUINOMQTT and MQTT_TASMOTAMQTT (#5474) + * + * 6.4.1.21 20190309 * Fix exception on GUI Configure Logging and Configure Other (#5424) * Add support for sensor SCD30 (#5434) * Add support for commands in sensor drivers diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 3030654ce..b7e0846e4 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -230,16 +230,6 @@ // -- OTA ----------------------------------------- //#define USE_ARDUINO_OTA // Add optional support for Arduino OTA (+13k code) -/*-------------------------------------------------------------------------------------------*\ - * Select ONE of possible MQTT library types below -\*-------------------------------------------------------------------------------------------*/ - // Default MQTT driver for both non-TLS and TLS connections. Latest library version (20181016) does not block network if MQTT server is unavailable. -#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library - // Alternative MQTT driver does not block network when MQTT server is unavailable. No TLS support -//#define MQTT_LIBRARY_TYPE MQTT_TASMOTAMQTT // Use TasmotaMqtt library (+4k4 (core 2.3.0), +14k4 (core 2.4.2 lwip2) code, +4k mem) - non-TLS only - // Alternative MQTT driver does not block network when MQTT server is unavailable. TLS should work but needs to be tested. -//#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem) - // -- MQTT ---------------------------------------- #define MQTT_TELE_RETAIN 0 // Tele messages may send retain flag (0 = off, 1 = on) @@ -249,7 +239,7 @@ #define DOMOTICZ_OUT_TOPIC "domoticz/out" // Domoticz Output Topic // -- MQTT - Home Assistant Discovery ------------- -#define USE_HOME_ASSISTANT // Enable Home Assistant Discovery Support (+2k code) +#define USE_HOME_ASSISTANT // Enable Home Assistant Discovery Support (+7k code) #define HOME_ASSISTANT_DISCOVERY_PREFIX "homeassistant" // Home Assistant discovery prefix // -- MQTT - TLS ---------------------------------- diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 39f180c0b..bccd057cf 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1682,8 +1682,8 @@ void PublishStatus(uint8_t payload) } 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_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"MqttType\":%d,\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), - Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, mqtt_client, Settings.mqtt_user, MqttLibraryType(), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); + 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_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), + Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, mqtt_client, Settings.mqtt_user, MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6")); } diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index fe5c5c08d..bcbc8f2ad 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -158,8 +158,6 @@ void KNX_CB_Action(message_t const &msg, void *arg); #ifndef USE_SMARTCONFIG #define USE_SMARTCONFIG // Add support for Wifi SmartConfig as initial wifi configuration tool (+23k code, +0.6k mem) #endif -#undef MQTT_LIBRARY_TYPE -#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library #undef USE_ARDUINO_OTA // Disable support for Arduino OTA //#undef USE_DOMOTICZ // Disable Domoticz #undef USE_HOME_ASSISTANT // Disable Home Assistant diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 89c999a90..b9516367a 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040115 +#define VERSION 0x06040116 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index c69b8e671..f5229e81f 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -56,10 +56,10 @@ void GetFeatures(void) feature_drv1 |= 0x00000400; // xdrv_01_mqtt.ino #endif #if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) - feature_drv1 |= 0x00000800; // xdrv_01_mqtt.ino +// feature_drv1 |= 0x00000800; // xdrv_01_mqtt.ino #endif #if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) // Obsolete since 6.2.1.11 - feature_drv1 |= 0x00001000; // xdrv_01_mqtt.ino +// feature_drv1 |= 0x00001000; // xdrv_01_mqtt.ino #endif #ifdef MQTT_HOST_DISCOVERY feature_drv1 |= 0x00002000; // xdrv_01_mqtt.ino @@ -116,7 +116,7 @@ void GetFeatures(void) feature_drv1 |= 0x40000000; // support.ino #endif #if (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT) - feature_drv1 |= 0x80000000; // xdrv_01_mqtt.ino +// feature_drv1 |= 0x80000000; // xdrv_01_mqtt.ino #endif /*********************************************************************************************/ diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index ba3dabc09..97ee79894 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -18,41 +18,6 @@ */ #define XDRV_02 2 - -/*********************************************************************************************\ - * Select ONE of possible MQTT library types below -\*********************************************************************************************/ -// Default MQTT driver for both non-TLS and TLS connections. Blocks network if MQTT server is unavailable. -//#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library -// Alternative MQTT driver does not block network when MQTT server is unavailable. No TLS support -//#define MQTT_LIBRARY_TYPE MQTT_TASMOTAMQTT // Use TasmotaMqtt library (+4k4 (core 2.3.0), +14k4 (core 2.4.2 lwip2) code, +4k mem) - non-TLS only -// Alternative MQTT driver does not block network when MQTT server is unavailable. TLS should work but needs to be tested. -//#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem) - -#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) // Obsolete as of v6.2.1.11 -#undef MQTT_LIBRARY_TYPE -#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT -#endif - -/* -#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) -#undef MQTT_LIBRARY_TYPE -#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Obsolete in near future -#endif -*/ - -#ifdef USE_MQTT_TLS - -#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) -#undef MQTT_LIBRARY_TYPE -#endif - -#ifndef MQTT_LIBRARY_TYPE -#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library as it only supports TLS -#endif - -#endif // USE_MQTT_TLS - /*********************************************************************************************/ #ifdef USE_MQTT_TLS @@ -89,8 +54,6 @@ bool mqtt_allowed = false; // MQTT enabled and parameters valid * void MqttLoop() \*********************************************************************************************/ -#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT) /***********************************************/ - #include // Max message size calculated by PubSubClient is (MQTT_MAX_PACKET_SIZE < 5 + 2 + strlen(topic) + plength) @@ -134,96 +97,6 @@ void MqttLoop(void) MqttClient.loop(); } -#elif (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) /**********************************************/ - -#include -TasmotaMqtt MqttClient; - -bool MqttIsConnected(void) -{ - return MqttClient.Connected(); -} - -void MqttDisconnect(void) -{ - MqttClient.Disconnect(); -} - -void MqttDisconnectedCb(void) -{ - MqttDisconnected(MqttClient.State()); // status codes are documented in file mqtt.h as tConnState -} - -void MqttSubscribeLib(const char *topic) -{ - MqttClient.Subscribe(topic, 0); -} - -void MqttUnsubscribeLib(const char *topic) -{ - MqttClient.Unsubscribe(topic, 0); -} - -bool MqttPublishLib(const char* topic, bool retained) -{ - return MqttClient.Publish(topic, mqtt_data, strlen(mqtt_data), 0, retained); -} - -void MqttLoop(void) -{ -} - -#elif (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT) /**********************************************/ - -#include -MQTTClient MqttClient(MQTT_MAX_PACKET_SIZE); - -bool MqttIsConnected(void) -{ - return MqttClient.connected(); -} - -void MqttDisconnect(void) -{ - MqttClient.disconnect(); -} - -/* -void MqttMyDataCb(MQTTClient* client, char* topic, char* data, int data_len) -//void MqttMyDataCb(MQTTClient *client, char topic[], char data[], int data_len) -{ -// MqttDataHandler((char*)topic, (uint8_t*)data, data_len); -} -*/ - -void MqttMyDataCb(String &topic, String &data) -{ - MqttDataHandler((char*)topic.c_str(), (uint8_t*)data.c_str(), data.length()); -} - -void MqttSubscribeLib(const char *topic) -{ - MqttClient.subscribe(topic, 0); -} - -void MqttUnsubscribeLib(const char *topic) -{ - MqttClient.unsubscribe(topic, 0); -} - -bool MqttPublishLib(const char* topic, bool retained) -{ - return MqttClient.publish(topic, mqtt_data, strlen(mqtt_data), retained, 0); -} - -void MqttLoop(void) -{ - MqttClient.loop(); -// delay(10); -} - -#endif // MQTT_LIBRARY_TYPE - /*********************************************************************************************/ #ifdef USE_DISCOVERY @@ -254,11 +127,6 @@ void MqttDiscoverServer(void) #endif // MQTT_HOST_DISCOVERY #endif // USE_DISCOVERY -int MqttLibraryType(void) -{ - return (int)MQTT_LIBRARY_TYPE; -} - void MqttRetryCounter(uint8_t value) { mqtt_retry_counter = value; @@ -586,25 +454,9 @@ void MqttReconnect(void) if (!MqttCheckTls()) return; #endif // USE_MQTT_TLS -#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) - MqttClient.InitConnection(Settings.mqtt_host, Settings.mqtt_port); - MqttClient.InitClient(mqtt_client, mqtt_user, mqtt_pwd, MQTT_KEEPALIVE); - MqttClient.InitLWT(stopic, mqtt_data, 1, true); - MqttClient.OnConnected(MqttConnected); - MqttClient.OnDisconnected(MqttDisconnectedCb); - MqttClient.OnData(MqttDataHandler); -#elif (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT) - MqttClient.begin(Settings.mqtt_host, Settings.mqtt_port, EspClient); - MqttClient.setWill(stopic, mqtt_data, true, 1); - MqttClient.setOptions(MQTT_KEEPALIVE, true, MQTT_TIMEOUT); -// MqttClient.onMessageAdvanced(MqttMyDataCb); - MqttClient.onMessage(MqttMyDataCb); -#endif - mqtt_initial_connection_state = 1; } -#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT) MqttClient.setCallback(MqttDataHandler); MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data)) { @@ -612,15 +464,6 @@ void MqttReconnect(void) } else { MqttDisconnected(MqttClient.state()); // status codes are documented here http://pubsubclient.knolleary.net/api.html#state } -#elif (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) - MqttClient.Connect(); -#elif (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT) - if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd)) { - MqttConnected(); - } else { - MqttDisconnected(MqttClient.lastError()); // status codes are documented here https://github.com/256dpi/lwmqtt/blob/master/include/lwmqtt.h#L11 - } -#endif // MQTT_LIBRARY_TYPE } void MqttCheck(void) From 70b1a24450ceb32b4a72ef0a7e56fb6d4ed99428 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 15 Mar 2019 14:54:49 +0100 Subject: [PATCH 1158/2222] delete arduino mqtt link --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 579263ec5..021643824 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,6 @@ Libraries used with Sonoff-Tasmota are: - [Adafruit SSD1306](https://github.com/adafruit/Adafruit_SSD1306) - [Adafruit GFX](https://github.com/adafruit/Adafruit-GFX-Library) - [ArduinoJson](https://arduinojson.org/) -- [arduino mqtt](https://github.com/256dpi/arduino-mqtt) - [Bosch BME680](https://github.com/BoschSensortec/BME680_driver) - [C2 Programmer](http://app.cear.ufpb.br/~lucas.hartmann/tag/efm8bb1/) - [esp-epaper-29-ws-20171230-gemu](https://github.com/gemu2015/Sonoff-Tasmota/tree/displays/lib) From 99d20f803b383994b434c10a6f168e18df959ca2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 16 Mar 2019 16:23:41 +0100 Subject: [PATCH 1159/2222] More web chunks More web chunks --- sonoff/sonoff.ino | 1 - sonoff/xdrv_01_webserver.ino | 201 ++++++++++++++++++----------------- sonoff/xdrv_02_mqtt.ino | 5 +- sonoff/xdrv_07_domoticz.ino | 2 +- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_11_knx.ino | 2 +- sonoff/xsns_34_hx711.ino | 2 +- 7 files changed, 107 insertions(+), 108 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index bccd057cf..51b89031c 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -167,7 +167,6 @@ bool i2c_flg = false; // I2C configured bool spi_flg = false; // SPI configured bool soft_spi_flg = false; // Software SPI configured bool ntp_force_sync = false; // Force NTP sync -bool reset_web_log_flag = false; // Reset web console log myio my_module; // Active copy of Module GPIOs (17 x 8 bits) gpio_flag my_module_flag; // Active copy of Module GPIO flags StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index d8ab7b56e..415d14e53 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -383,7 +383,7 @@ const char HTTP_END[] PROGMEM = ""; const char HTTP_DEVICE_CONTROL[] PROGMEM = ""; // ?o is related to WebGetArg("o", tmp, sizeof(tmp)); -const char HTTP_DEVICE_STATE[] PROGMEM = "%s"; // {c} = %'>
%s
"; // {c} = %'>
"), mqtt_data); + char stemp[strlen(mqtt_data) +1]; + memcpy(stemp, mqtt_data, sizeof(stemp)); + + WSContentBegin(200, CT_HTML); + WSContentSend_P(PSTR("{t}%s
" D_DOMOTICZ_IDX " %d
%s
"), stemp); if (devices_present) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{t}"), mqtt_data); + WSContentSend_P(PSTR("{t}")); uint8_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32; if (SONOFF_IFAN02 == my_module_type) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_STATE, - mqtt_data, 36, (bitRead(power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(power, 0))); + WSContentSend_P(HTTP_DEVICE_STATE, 36, (bitRead(power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(power, 0))); uint8_t fanspeed = GetFanspeed(); snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fanspeed); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_STATE, - mqtt_data, 64, (fanspeed) ? "bold" : "normal", 54, (fanspeed) ? svalue : GetStateText(0)); + WSContentSend_P(HTTP_DEVICE_STATE, 64, (fanspeed) ? "bold" : "normal", 54, (fanspeed) ? svalue : GetStateText(0)); } else { for (uint8_t idx = 1; idx <= devices_present; idx++) { snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1)); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_STATE, - mqtt_data, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue); + WSContentSend_P(HTTP_DEVICE_STATE, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s"), mqtt_data); + WSContentSend_P(PSTR("")); } - WSHeaderSend(); - WSSend(200, CT_HTML, mqtt_data); + WSContentEnd(); + return true; } @@ -987,7 +1003,7 @@ void HandleConfiguration(void) WSContentButton(BUTTON_RESTORE); WSContentSpaceButton(BUTTON_MAIN); - WSContentEnd(); + WSContentStop(); } /*-------------------------------------------------------------------------------------------*/ @@ -1005,13 +1021,12 @@ void HandleTemplateConfiguration(void) char stemp[20]; // Template number and Sensor name if (WebServer->hasArg("m")) { - String page = ""; + WSContentBegin(200, CT_PLAIN); for (uint8_t i = 0; i < MAXMODULE; i++) { // "}2'%d'>%s (%d)}3" - "}2'0'>Sonoff Basic (1)}3" uint8_t midx = pgm_read_byte(kModuleNiceList + i); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1); - page += mqtt_data; + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1); } - WSSend(200, CT_PLAIN, page); + WSContentEnd(); return; } @@ -1025,32 +1040,26 @@ void HandleTemplateConfiguration(void) gpio_flag flag = ModuleFlag(); Settings.module = module_save; - String page = AnyModuleName(module); // NAME: Generic - page += F("}1"); // Field separator - + WSContentBegin(200, CT_PLAIN); + WSContentSend_P(PSTR("%s}1"), AnyModuleName(module).c_str()); // NAME: Generic for (uint8_t i = 0; i < sizeof(kGpioNiceList); i++) { // GPIO: }2'0'>None (0)}3}2'17'>Button1 (17)}3... if (1 == i) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MODULE_TEMPLATE_REPLACE, 255, D_SENSOR_USER, 255); // }2'255'>User (255)}3 - page += mqtt_data; + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, 255, D_SENSOR_USER, 255); // }2'255'>User (255)}3 } uint8_t midx = pgm_read_byte(kGpioNiceList + i); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); - page += mqtt_data; + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); } - page += F("}1"); // Field separator - mqtt_data[0] = '\0'; + WSContentSend_P(PSTR("}1")); // Field separator for (uint8_t i = 0; i < sizeof(cmodule); i++) { // 17,148,29,149,7,255,255,255,138,255,139,255,255 if ((i < 6) || ((i > 8) && (i != 11))) { // Ignore flash pins GPIO06, 7, 8 and 11 - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", cmodule.io[i]); + WSContentSend_P(PSTR("%s%d"), (i>0)?",":"", cmodule.io[i]); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}1%d}1%d"), mqtt_data, flag, Settings.user_template_base); // FLAG: 1 BASE: 17 - page += mqtt_data; - - WSSend(200, CT_PLAIN, page); + WSContentSend_P(PSTR("}1%d}1%d"), flag, Settings.user_template_base); // FLAG: 1 BASE: 17 + WSContentEnd(); return; } @@ -1078,7 +1087,7 @@ void HandleTemplateConfiguration(void) WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentEnd(); + WSContentStop(); } void TemplateSaveSettings(void) @@ -1132,7 +1141,7 @@ void HandleModuleConfiguration(void) ModuleGpios(&cmodule); if (WebServer->hasArg("m")) { - String page = ""; + WSContentBegin(200, CT_PLAIN); uint8_t vidx = 0; for (uint8_t i = 0; i <= MAXMODULE; i++) { // "}2'%d'>%s (%d)}3" - "}2'255'>UserTemplate (0)}3" - "}2'0'>Sonoff Basic (1)}3" if (0 == i) { @@ -1142,23 +1151,21 @@ void HandleModuleConfiguration(void) midx = pgm_read_byte(kModuleNiceList + i -1); vidx = midx +1; } - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), vidx); - page += mqtt_data; + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), vidx); } - WSSend(200, CT_PLAIN, page); + WSContentEnd(); return; } if (WebServer->hasArg("g")) { - String page = ""; + WSContentBegin(200, CT_PLAIN); for (uint8_t j = 0; j < sizeof(kGpioNiceList); j++) { midx = pgm_read_byte(kGpioNiceList + j); if (!GetUsedInModule(midx, cmodule.io)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); - page += mqtt_data; + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); } } - WSSend(200, CT_PLAIN, page); + WSContentEnd(); return; } @@ -1185,7 +1192,7 @@ void HandleModuleConfiguration(void) WSContentSend_P(PSTR("")); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentEnd(); + WSContentStop(); } void ModuleSaveSettings(void) @@ -1327,7 +1334,7 @@ void HandleWifiConfiguration(void) } else { WSContentSpaceButton(BUTTON_CONFIGURATION); } - WSContentEnd(); + WSContentStop(); } void WifiSaveSettings(void) @@ -1386,7 +1393,7 @@ void HandleLoggingConfiguration(void) WSContentSend_P(HTTP_FORM_LOG2, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentEnd(); + WSContentStop(); } void LoggingSaveSettings(void) @@ -1462,7 +1469,7 @@ void HandleOtherConfiguration(void) WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentEnd(); + WSContentStop(); } void OtherSaveSettings(void) @@ -1558,7 +1565,7 @@ void HandleResetConfiguration(void) WSContentSend_P(PSTR("
" D_CONFIGURATION_RESET "
")); WSContentSend_P(HTTP_MSG_RSTRT); WSContentSpaceButton(BUTTON_MAIN); - WSContentEnd(); + WSContentStop(); char command[CMDSZ]; snprintf_P(command, sizeof(command), PSTR(D_CMND_RESET " 1")); @@ -1576,7 +1583,7 @@ void HandleRestoreConfiguration(void) WSContentSend_P(HTTP_FORM_RST); WSContentSend_P(HTTP_FORM_RST_UPG, D_RESTORE); WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentEnd(); + WSContentStop(); upload_error = 0; upload_file_type = UPL_SETTINGS; @@ -1678,7 +1685,7 @@ void HandleInformation(void) "
")); // WSContentSend_P(PSTR("
")); WSContentSpaceButton(BUTTON_MAIN); - WSContentEnd(); + WSContentStop(); } #endif // Not FIRMWARE_MINIMAL @@ -1695,7 +1702,7 @@ void HandleUpgradeFirmware(void) WSContentSend_P(HTTP_FORM_UPG, Settings.ota_url); WSContentSend_P(HTTP_FORM_RST_UPG, D_UPGRADE); WSContentSpaceButton(BUTTON_MAIN); - WSContentEnd(); + WSContentStop(); upload_error = 0; upload_file_type = UPL_TASMOTA; @@ -1723,7 +1730,7 @@ void HandleUpgradeFirmwareStart(void) WSContentSend_P(PSTR("
" D_UPGRADE_STARTED " ...
")); WSContentSend_P(HTTP_MSG_RSTRT); WSContentSpaceButton(BUTTON_MAIN); - WSContentEnd(); + WSContentStop(); snprintf_P(command, sizeof(command), PSTR(D_CMND_UPGRADE " 1")); ExecuteWebCommand(command, SRC_WEBGUI); @@ -1770,7 +1777,7 @@ void HandleUploadDone(void) SettingsBufferFree(); WSContentSend_P(PSTR("
")); WSContentSpaceButton(BUTTON_MAIN); - WSContentEnd(); + WSContentStop(); } void HandleUploadLoop(void) @@ -1990,7 +1997,7 @@ void HandleHttpCommand(void) if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, Settings.web_password))) { valid = 0; } } - String message = F("{\"" D_RSLT_WARNING "\":\""); + WSContentBegin(200, CT_JSON); if (valid) { uint8_t curridx = web_log_index; String svalue = WebServer->arg("cmnd"); @@ -1998,7 +2005,8 @@ void HandleHttpCommand(void) ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCOMMAND); if (web_log_index != curridx) { uint8_t counter = curridx; - message = F("{"); + WSContentSend_P(PSTR("{")); + bool cflg = false; do { char* tmp; size_t len; @@ -2007,28 +2015,28 @@ void HandleHttpCommand(void) // [14:49:36 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}] char* JSON = (char*)memchr(tmp, '{', len); if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O]) - if (message.length() > 1) { message += F(","); } size_t JSONlen = len - (JSON - tmp); if (JSONlen > sizeof(mqtt_data)) { JSONlen = sizeof(mqtt_data); } - strlcpy(mqtt_data, JSON +1, JSONlen -2); - message += mqtt_data; + char stemp[JSONlen]; + strlcpy(stemp, JSON +1, JSONlen -2); + WSContentSend_P(PSTR("%s%s"), (cflg) ? "," : "", stemp); + cflg = true; } } counter++; if (!counter) counter++; // Skip 0 as it is not allowed } while (counter != web_log_index); - message += F("}"); + WSContentSend_P(PSTR("}")); } else { - message += F(D_ENABLE_WEBLOG_FOR_RESPONSE "\"}"); + WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}")); } } else { - message += F(D_ENTER_COMMAND " cmnd=\"}"); + WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENTER_COMMAND " cmnd=\"}")); } } else { - message += F(D_NEED_USER_AND_PASSWORD "\"}"); + WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_NEED_USER_AND_PASSWORD "\"}")); } - WSHeaderSend(); - WSSend(200, CT_JSON, message); + WSContentEnd(); } /*-------------------------------------------------------------------------------------------*/ @@ -2049,7 +2057,7 @@ void HandleConsole(void) WSContentSendStyle(); WSContentSend_P(HTTP_FORM_CMND); WSContentSpaceButton(BUTTON_MAIN); - WSContentEnd(); + WSContentStop(); } void HandleConsoleRefresh(void) @@ -2067,10 +2075,8 @@ void HandleConsoleRefresh(void) WebGetArg("c2", stmp, sizeof(stmp)); if (strlen(stmp)) { counter = atoi(stmp); } - bool last_reset_web_log_flag = reset_web_log_flag; - // mqtt_data used as scratch space - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%d}1%d}1"), web_log_index, last_reset_web_log_flag); - String message = mqtt_data; + WSContentBegin(200, CT_PLAIN); + WSContentSend_P(PSTR("%d}1%d}1"), web_log_index, reset_web_log_flag); if (!reset_web_log_flag) { counter = 0; reset_web_log_flag = true; @@ -2085,21 +2091,18 @@ void HandleConsoleRefresh(void) size_t len; GetLog(counter, &tmp, &len); if (len) { - if (cflg) { - message += F("\n"); - } else { - cflg = true; - } if (len > sizeof(mqtt_data) -2) { len = sizeof(mqtt_data); } - strlcpy(mqtt_data, tmp, len); - message += mqtt_data; // mqtt_data used as scratch space + char stemp[len +1]; + strlcpy(stemp, tmp, len); + WSContentSend_P(PSTR("%s%s"), (cflg) ? "\n" : "", stemp); + cflg = true; } counter++; - if (!counter) { counter++; } // Skip log index 0 as it is not allowed + if (!counter) { counter++; } // Skip log index 0 as it is not allowed } while (counter != web_log_index); } - message += F("}1"); - WSSend(200, CT_PLAIN, message); + WSContentSend_P(PSTR("}1")); + WSContentEnd(); } /********************************************************************************************/ diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 97ee79894..57086d46e 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -18,7 +18,6 @@ */ #define XDRV_02 2 -/*********************************************************************************************/ #ifdef USE_MQTT_TLS #ifdef USE_MQTT_TLS_CA_CERT @@ -441,13 +440,11 @@ void MqttReconnect(void) GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); snprintf_P(mqtt_data, sizeof(mqtt_data), S_OFFLINE); -//#ifdef ARDUINO_ESP8266_RELEASE_2_4_1 #ifdef USE_MQTT_TLS EspClient = WiFiClientSecure(); // Wifi Secure Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497) #else EspClient = WiFiClient(); // Wifi Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497) #endif -//#endif if (2 == mqtt_initial_connection_state) { // Executed once just after power on and wifi is connected #ifdef USE_MQTT_TLS @@ -777,7 +774,7 @@ void HandleMqttConfiguration(void) Settings.mqtt_fulltopic); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentEnd(); + WSContentStop(); } void MqttSaveSettings(void) diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index c2020176d..799b2d4b8 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -482,7 +482,7 @@ void HandleDomoticzConfiguration(void) WSContentSend_P(PSTR("")); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentEnd(); + WSContentStop(); } void DomoticzSaveSettings(void) diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 9a85ad3c4..a3ab51a1b 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -721,7 +721,7 @@ void HandleTimerConfiguration(void) WSContentSend_P(HTTP_FORM_TIMER4); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentEnd(); + WSContentStop(); } void TimerSaveSettings(void) diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 5ab0c7c88..45c9fe15f 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -934,7 +934,7 @@ void HandleKNXConfiguration(void) WSContentSend_P(PSTR("
")); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentEnd(); + WSContentStop(); } } diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 2072dc496..c287ef3f4 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -434,7 +434,7 @@ void HandleHxAction(void) WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentEnd(); + WSContentStop(); } void HxSaveSettings(void) From 7f43eff739c0ea8c0922ff527396408e655cf187 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sun, 17 Mar 2019 22:10:10 -0300 Subject: [PATCH 1160/2222] Hiding User Configurable Pins for SHELLY 1 As explained in https://github.com/arendst/Sonoff-Tasmota/issues/5487 some users had tried to connect sensors to shelly 1, being it powered using mains AC. So, as it is very dangerous and a safety concern, those extra GPIO are being taken from the template. Comments on this is, were left on the code for people who really know what they are doing. --- sonoff/sonoff_template.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index c839d2a7e..cf5a1af78 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1472,10 +1472,10 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0 }, { "Shelly 1", // Shelly1 Open Source (ESP8266 - 2MB) - https://shelly.cloud/shelly1-open-source/ - GPIO_USER, // GPIO00 - Only to be used when Shelly is connected to 12V DC - GPIO_USER, // GPIO01 Serial RXD - Only to be used when Shelly is connected to 12V DC + 0, // GPIO00 - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC + 0, // GPIO01 Serial RXD - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC 0, - GPIO_USER, // GPIO03 Serial TXD - Only to be used when Shelly is connected to 12V DC + 0, // GPIO03 Serial TXD - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) GPIO_SWT1_NP, // GPIO05 SW pin // GPIO06 (SD_CLK Flash) From c114530e34eb156a1cdbc2be53752df0649f02ee Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Mar 2019 12:23:09 +0100 Subject: [PATCH 1161/2222] Update minimal text Update minimal text --- sonoff/language/bg-BG.h | 2 +- sonoff/language/cs-CZ.h | 2 +- sonoff/language/de-DE.h | 2 +- sonoff/language/el-GR.h | 2 +- sonoff/language/en-GB.h | 2 +- sonoff/language/es-AR.h | 2 +- sonoff/language/fr-FR.h | 2 +- sonoff/language/he-HE.h | 2 +- sonoff/language/hu-HU.h | 2 +- sonoff/language/it-IT.h | 2 +- sonoff/language/ko-KO.h | 2 +- sonoff/language/nl-NL.h | 2 +- sonoff/language/pl-PL.h | 2 +- sonoff/language/pt-BR.h | 2 +- sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 2 +- sonoff/language/sk-SK.h | 2 +- sonoff/language/sv-SE.h | 2 +- sonoff/language/tr-TR.h | 2 +- sonoff/language/uk-UK.h | 2 +- sonoff/language/zh-CN.h | 2 +- sonoff/language/zh-TW.h | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 6d44af3ff..2214634f9 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Разрешете JavaScript, за да използвате Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуеър - моля надградете го" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуеър
моля надградете го" #define D_WEBSERVER_ACTIVE_ON "Уеб сървърът е активен на" #define D_WITH_IP_ADDRESS "с IP адрес" #define D_WEBSERVER_STOPPED "Уеб сървърът е спрян" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index e4053ea75..41d4fc9de 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Pro používání prostředí Tasmota povolte JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ - prosím zaktualizujte" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ
prosím zaktualizujte" #define D_WEBSERVER_ACTIVE_ON "Aktivní Web server" #define D_WITH_IP_ADDRESS "na IP adrese" #define D_WEBSERVER_STOPPED "Web server zastaven" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index d93f77b89..0808c91c4 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "JavaScript aktivieren um Tasmota benutzen zu können" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMUM-Firmware - bitte upgraden" +#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" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 8a3fe75a5..0e483759d 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -220,7 +220,7 @@ // webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - παρακαλώ αναβαθμίστε" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
παρακαλώ αναβαθμίστε" #define D_WEBSERVER_ACTIVE_ON "Ενεργός διακομιστής Web στο" #define D_WITH_IP_ADDRESS "με διεύθυνση IP" #define D_WEBSERVER_STOPPED "Ο διακομιστής Web σταμάτησε" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index e459cd02d..d5e792462 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - please upgrade" +#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" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 9f2187bbf..baf9838bf 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Habilitar JavaScript para usar Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO - actualice por favor" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
actualice por favor" #define D_WEBSERVER_ACTIVE_ON "Servidor web activo en" #define D_WITH_IP_ADDRESS "con dirección IP" #define D_WEBSERVER_STOPPED "Servidor web detenido" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 6b26a6212..0b7d29eb7 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Pour utiliser Tasmota, veuillez activer JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL - merci de mettre à jour" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL
merci de mettre à jour" #define D_WEBSERVER_ACTIVE_ON "Serveur web actif sur" #define D_WITH_IP_ADDRESS "avec l'adresse IP" #define D_WEBSERVER_STOPPED "Serveur web éteint" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 8ce1a3a78..2a876d2b0 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -62,7 +62,7 @@ #define D_BRIGHTLIGHT "בהירות" #define D_BSSID "BSSId" #define D_BUTTON "לחצן" -#define D_BY "ע" // Written by me +#define D_BY "ע"י" // Written by me #define D_BYTES "בייט" #define D_CELSIUS "צלזיוס" #define D_CHANNEL "ערוץ" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 649796121..e8b818029 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "A Tasmota használatához engedélyezd a Javascriptet!" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware - frissítsd!" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware
frissítsd!" #define D_WEBSERVER_ACTIVE_ON "Webszerver aktív:" #define D_WITH_IP_ADDRESS "IP cím:" #define D_WEBSERVER_STOPPED "Webszerver leállítva" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 4d735426f..db8e58475 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Abilitare JavaScript per utilizzare Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - effettuare aggiornamento" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
effettuare aggiornamento" #define D_WEBSERVER_ACTIVE_ON "Web server attivo su" #define D_WITH_IP_ADDRESS "con indirizzo IP" #define D_WEBSERVER_STOPPED "Web server arrestato" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index 1ea02b01f..ddfaba8d3 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Tasmota를 사용하려면 JavaScript를 활성화 하십시오." -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - 업그레이드가 필요합니다" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
업그레이드가 필요합니다" #define D_WEBSERVER_ACTIVE_ON "Web 서버 작동 중" #define D_WITH_IP_ADDRESS "IP 주소" #define D_WEBSERVER_STOPPED "Web 서버 멈춤" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index dd3fb1806..9e428165d 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Zet JavaScript aan voor Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - opwaarderen" +#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" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 24e2f60ae..0f13d248a 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Aby korzystać z Tasmota, włącz obsługę JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL - proszę uaktualnić" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL
proszę uaktualnić" #define D_WEBSERVER_ACTIVE_ON "Aktywny serwer Web" #define D_WITH_IP_ADDRESS "z adresem IP" #define D_WEBSERVER_STOPPED "Serwer Web zatrzymany" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 3d24e2dbc..63efc3f1e 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo - Atualizar por favor" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo
Atualizar por favor" #define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" #define D_WITH_IP_ADDRESS "com o endereço IP" #define D_WEBSERVER_STOPPED "Servidor WEB parou" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index d675efe54..171f33d9b 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMO firmware - Atualizar Por favor" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMO firmware
Atualizar Por favor" #define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" #define D_WITH_IP_ADDRESS "com o endereço IP" #define D_WEBSERVER_STOPPED "Servitor WEB parou" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 50eabbc35..e4112953c 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL - пожалуйста обновите" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
пожалуйста обновите" #define D_WEBSERVER_ACTIVE_ON "Веб-сервер активен" #define D_WITH_IP_ADDRESS "с IP-адресом" #define D_WEBSERVER_STOPPED "Веб-сервер остановлен" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 4f741ac51..cf99703c8 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Pre používanie prostredia Tasmota povoľte JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY - prosím aktualizujte" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY
prosím aktualizujte" #define D_WEBSERVER_ACTIVE_ON "Aktívny Web server" #define D_WITH_IP_ADDRESS "na IP adrese" #define D_WEBSERVER_STOPPED "Web server zastavený" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index dd6b31469..6a92c1bc1 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "För att använda Tasmota, aktivera JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - var god uppgradera" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
var god uppgradera" #define D_WEBSERVER_ACTIVE_ON "Webbserver aktiv på" #define D_WITH_IP_ADDRESS "med IP-adress" #define D_WEBSERVER_STOPPED "Webbserver stoppad" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index f6f61ec56..b887c89c2 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük, lütfen yükseltin" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük
lütfen yükseltin" #define D_WEBSERVER_ACTIVE_ON "Web sunucusu aktif" #define D_WITH_IP_ADDRESS "IP adres ile" #define D_WEBSERVER_STOPPED "Web sunucusu durdu" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 71b7665c1..0efdd1c94 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL - будь-ласка оновіть" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
будь-ласка оновіть" #define D_WEBSERVER_ACTIVE_ON "Веб-сервер активний" #define D_WITH_IP_ADDRESS "з IP-адресом" #define D_WEBSERVER_STOPPED "Веб-сервер зупинений" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 586591278..88767053b 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -220,7 +220,7 @@ // webserver.ino #define D_NOSCRIPT "Tasmota要求浏览器支持 JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件 - 请升级" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件
请升级" #define D_WEBSERVER_ACTIVE_ON "Web 服务器地址:" #define D_WITH_IP_ADDRESS "IP 地址:" #define D_WEBSERVER_STOPPED "Web 服务已停止" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index ae6d4df07..11f85eef2 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低 - 請升級" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低
請升級" #define D_WEBSERVER_ACTIVE_ON "Web服務器:" #define D_WITH_IP_ADDRESS "IP地址:" #define D_WEBSERVER_STOPPED "Web 服務器已停止" From 47e9361d55809800071fadde3ddf303eb069664a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Mar 2019 13:02:12 +0100 Subject: [PATCH 1162/2222] Revert "Update minimal text" This reverts commit c114530e34eb156a1cdbc2be53752df0649f02ee. --- sonoff/language/bg-BG.h | 2 +- sonoff/language/cs-CZ.h | 2 +- sonoff/language/de-DE.h | 2 +- sonoff/language/el-GR.h | 2 +- sonoff/language/en-GB.h | 2 +- sonoff/language/es-AR.h | 2 +- sonoff/language/fr-FR.h | 2 +- sonoff/language/he-HE.h | 2 +- sonoff/language/hu-HU.h | 2 +- sonoff/language/it-IT.h | 2 +- sonoff/language/ko-KO.h | 2 +- sonoff/language/nl-NL.h | 2 +- sonoff/language/pl-PL.h | 2 +- sonoff/language/pt-BR.h | 2 +- sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 2 +- sonoff/language/sk-SK.h | 2 +- sonoff/language/sv-SE.h | 2 +- sonoff/language/tr-TR.h | 2 +- sonoff/language/uk-UK.h | 2 +- sonoff/language/zh-CN.h | 2 +- sonoff/language/zh-TW.h | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 2214634f9..6d44af3ff 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Разрешете JavaScript, за да използвате Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуеър
моля надградете го" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуеър - моля надградете го" #define D_WEBSERVER_ACTIVE_ON "Уеб сървърът е активен на" #define D_WITH_IP_ADDRESS "с IP адрес" #define D_WEBSERVER_STOPPED "Уеб сървърът е спрян" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 41d4fc9de..e4053ea75 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Pro používání prostředí Tasmota povolte JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ
prosím zaktualizujte" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ - prosím zaktualizujte" #define D_WEBSERVER_ACTIVE_ON "Aktivní Web server" #define D_WITH_IP_ADDRESS "na IP adrese" #define D_WEBSERVER_STOPPED "Web server zastaven" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 0808c91c4..d93f77b89 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "JavaScript aktivieren um Tasmota benutzen zu können" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMUM-Firmware
bitte upgraden" +#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" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 0e483759d..8a3fe75a5 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -220,7 +220,7 @@ // webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
παρακαλώ αναβαθμίστε" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - παρακαλώ αναβαθμίστε" #define D_WEBSERVER_ACTIVE_ON "Ενεργός διακομιστής Web στο" #define D_WITH_IP_ADDRESS "με διεύθυνση IP" #define D_WEBSERVER_STOPPED "Ο διακομιστής Web σταμάτησε" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index d5e792462..e459cd02d 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
please upgrade" +#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" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index baf9838bf..9f2187bbf 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Habilitar JavaScript para usar Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
actualice por favor" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO - actualice por favor" #define D_WEBSERVER_ACTIVE_ON "Servidor web activo en" #define D_WITH_IP_ADDRESS "con dirección IP" #define D_WEBSERVER_STOPPED "Servidor web detenido" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 0b7d29eb7..6b26a6212 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Pour utiliser Tasmota, veuillez activer JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL
merci de mettre à jour" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL - merci de mettre à jour" #define D_WEBSERVER_ACTIVE_ON "Serveur web actif sur" #define D_WITH_IP_ADDRESS "avec l'adresse IP" #define D_WEBSERVER_STOPPED "Serveur web éteint" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 2a876d2b0..8ce1a3a78 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -62,7 +62,7 @@ #define D_BRIGHTLIGHT "בהירות" #define D_BSSID "BSSId" #define D_BUTTON "לחצן" -#define D_BY "ע"י" // Written by me +#define D_BY "ע" // Written by me #define D_BYTES "בייט" #define D_CELSIUS "צלזיוס" #define D_CHANNEL "ערוץ" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index e8b818029..649796121 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "A Tasmota használatához engedélyezd a Javascriptet!" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware
frissítsd!" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware - frissítsd!" #define D_WEBSERVER_ACTIVE_ON "Webszerver aktív:" #define D_WITH_IP_ADDRESS "IP cím:" #define D_WEBSERVER_STOPPED "Webszerver leállítva" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index db8e58475..4d735426f 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Abilitare JavaScript per utilizzare Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
effettuare aggiornamento" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - effettuare aggiornamento" #define D_WEBSERVER_ACTIVE_ON "Web server attivo su" #define D_WITH_IP_ADDRESS "con indirizzo IP" #define D_WEBSERVER_STOPPED "Web server arrestato" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index ddfaba8d3..1ea02b01f 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Tasmota를 사용하려면 JavaScript를 활성화 하십시오." -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
업그레이드가 필요합니다" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - 업그레이드가 필요합니다" #define D_WEBSERVER_ACTIVE_ON "Web 서버 작동 중" #define D_WITH_IP_ADDRESS "IP 주소" #define D_WEBSERVER_STOPPED "Web 서버 멈춤" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 9e428165d..dd3fb1806 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Zet JavaScript aan voor Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
opwaarderen" +#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" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 0f13d248a..24e2f60ae 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Aby korzystać z Tasmota, włącz obsługę JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL
proszę uaktualnić" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL - proszę uaktualnić" #define D_WEBSERVER_ACTIVE_ON "Aktywny serwer Web" #define D_WITH_IP_ADDRESS "z adresem IP" #define D_WEBSERVER_STOPPED "Serwer Web zatrzymany" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 63efc3f1e..3d24e2dbc 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo
Atualizar por favor" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo - Atualizar por favor" #define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" #define D_WITH_IP_ADDRESS "com o endereço IP" #define D_WEBSERVER_STOPPED "Servidor WEB parou" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 171f33d9b..d675efe54 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMO firmware
Atualizar Por favor" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMO firmware - Atualizar Por favor" #define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" #define D_WITH_IP_ADDRESS "com o endereço IP" #define D_WEBSERVER_STOPPED "Servitor WEB parou" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index e4112953c..50eabbc35 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
пожалуйста обновите" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL - пожалуйста обновите" #define D_WEBSERVER_ACTIVE_ON "Веб-сервер активен" #define D_WITH_IP_ADDRESS "с IP-адресом" #define D_WEBSERVER_STOPPED "Веб-сервер остановлен" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index cf99703c8..4f741ac51 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Pre používanie prostredia Tasmota povoľte JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY
prosím aktualizujte" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY - prosím aktualizujte" #define D_WEBSERVER_ACTIVE_ON "Aktívny Web server" #define D_WITH_IP_ADDRESS "na IP adrese" #define D_WEBSERVER_STOPPED "Web server zastavený" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 6a92c1bc1..dd6b31469 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "För att använda Tasmota, aktivera JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
var god uppgradera" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - var god uppgradera" #define D_WEBSERVER_ACTIVE_ON "Webbserver aktiv på" #define D_WITH_IP_ADDRESS "med IP-adress" #define D_WEBSERVER_STOPPED "Webbserver stoppad" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index b887c89c2..f6f61ec56 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük
lütfen yükseltin" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük, lütfen yükseltin" #define D_WEBSERVER_ACTIVE_ON "Web sunucusu aktif" #define D_WITH_IP_ADDRESS "IP adres ile" #define D_WEBSERVER_STOPPED "Web sunucusu durdu" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 0efdd1c94..71b7665c1 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
будь-ласка оновіть" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL - будь-ласка оновіть" #define D_WEBSERVER_ACTIVE_ON "Веб-сервер активний" #define D_WITH_IP_ADDRESS "з IP-адресом" #define D_WEBSERVER_STOPPED "Веб-сервер зупинений" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 88767053b..586591278 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -220,7 +220,7 @@ // webserver.ino #define D_NOSCRIPT "Tasmota要求浏览器支持 JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件
请升级" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件 - 请升级" #define D_WEBSERVER_ACTIVE_ON "Web 服务器地址:" #define D_WITH_IP_ADDRESS "IP 地址:" #define D_WEBSERVER_STOPPED "Web 服务已停止" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 11f85eef2..ae6d4df07 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低
請升級" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低 - 請升級" #define D_WEBSERVER_ACTIVE_ON "Web服務器:" #define D_WITH_IP_ADDRESS "IP地址:" #define D_WEBSERVER_STOPPED "Web 服務器已停止" From 46b2fcac0894731b7cc19e1a92dc1706c4b6cc0f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Mar 2019 13:03:46 +0100 Subject: [PATCH 1163/2222] Second try Second try --- sonoff/language/bg-BG.h | 2 +- sonoff/language/cs-CZ.h | 2 +- sonoff/language/de-DE.h | 2 +- sonoff/language/el-GR.h | 2 +- sonoff/language/en-GB.h | 2 +- sonoff/language/es-AR.h | 2 +- sonoff/language/fr-FR.h | 2 +- sonoff/language/hu-HU.h | 2 +- sonoff/language/it-IT.h | 2 +- sonoff/language/ko-KO.h | 2 +- sonoff/language/nl-NL.h | 2 +- sonoff/language/pl-PL.h | 2 +- sonoff/language/pt-BR.h | 2 +- sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 2 +- sonoff/language/sk-SK.h | 2 +- sonoff/language/sv-SE.h | 2 +- sonoff/language/tr-TR.h | 2 +- sonoff/language/uk-UK.h | 2 +- sonoff/language/zh-CN.h | 2 +- sonoff/language/zh-TW.h | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 6d44af3ff..2214634f9 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Разрешете JavaScript, за да използвате Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуеър - моля надградете го" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуеър
моля надградете го" #define D_WEBSERVER_ACTIVE_ON "Уеб сървърът е активен на" #define D_WITH_IP_ADDRESS "с IP адрес" #define D_WEBSERVER_STOPPED "Уеб сървърът е спрян" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index e4053ea75..41d4fc9de 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Pro používání prostředí Tasmota povolte JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ - prosím zaktualizujte" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ
prosím zaktualizujte" #define D_WEBSERVER_ACTIVE_ON "Aktivní Web server" #define D_WITH_IP_ADDRESS "na IP adrese" #define D_WEBSERVER_STOPPED "Web server zastaven" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index d93f77b89..0808c91c4 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "JavaScript aktivieren um Tasmota benutzen zu können" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMUM-Firmware - bitte upgraden" +#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" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 8a3fe75a5..0e483759d 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -220,7 +220,7 @@ // webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - παρακαλώ αναβαθμίστε" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
παρακαλώ αναβαθμίστε" #define D_WEBSERVER_ACTIVE_ON "Ενεργός διακομιστής Web στο" #define D_WITH_IP_ADDRESS "με διεύθυνση IP" #define D_WEBSERVER_STOPPED "Ο διακομιστής Web σταμάτησε" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index e459cd02d..d5e792462 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - please upgrade" +#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" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 9f2187bbf..baf9838bf 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Habilitar JavaScript para usar Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO - actualice por favor" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
actualice por favor" #define D_WEBSERVER_ACTIVE_ON "Servidor web activo en" #define D_WITH_IP_ADDRESS "con dirección IP" #define D_WEBSERVER_STOPPED "Servidor web detenido" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 6b26a6212..0b7d29eb7 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Pour utiliser Tasmota, veuillez activer JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL - merci de mettre à jour" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL
merci de mettre à jour" #define D_WEBSERVER_ACTIVE_ON "Serveur web actif sur" #define D_WITH_IP_ADDRESS "avec l'adresse IP" #define D_WEBSERVER_STOPPED "Serveur web éteint" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 649796121..e8b818029 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "A Tasmota használatához engedélyezd a Javascriptet!" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware - frissítsd!" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware
frissítsd!" #define D_WEBSERVER_ACTIVE_ON "Webszerver aktív:" #define D_WITH_IP_ADDRESS "IP cím:" #define D_WEBSERVER_STOPPED "Webszerver leállítva" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 4d735426f..db8e58475 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Abilitare JavaScript per utilizzare Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - effettuare aggiornamento" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
effettuare aggiornamento" #define D_WEBSERVER_ACTIVE_ON "Web server attivo su" #define D_WITH_IP_ADDRESS "con indirizzo IP" #define D_WEBSERVER_STOPPED "Web server arrestato" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index 1ea02b01f..ddfaba8d3 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Tasmota를 사용하려면 JavaScript를 활성화 하십시오." -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - 업그레이드가 필요합니다" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
업그레이드가 필요합니다" #define D_WEBSERVER_ACTIVE_ON "Web 서버 작동 중" #define D_WITH_IP_ADDRESS "IP 주소" #define D_WEBSERVER_STOPPED "Web 서버 멈춤" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index dd3fb1806..9e428165d 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Zet JavaScript aan voor Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - opwaarderen" +#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" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 24e2f60ae..0f13d248a 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Aby korzystać z Tasmota, włącz obsługę JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL - proszę uaktualnić" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL
proszę uaktualnić" #define D_WEBSERVER_ACTIVE_ON "Aktywny serwer Web" #define D_WITH_IP_ADDRESS "z adresem IP" #define D_WEBSERVER_STOPPED "Serwer Web zatrzymany" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 3d24e2dbc..63efc3f1e 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo - Atualizar por favor" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo
Atualizar por favor" #define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" #define D_WITH_IP_ADDRESS "com o endereço IP" #define D_WEBSERVER_STOPPED "Servidor WEB parou" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index d675efe54..171f33d9b 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMO firmware - Atualizar Por favor" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMO firmware
Atualizar Por favor" #define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" #define D_WITH_IP_ADDRESS "com o endereço IP" #define D_WEBSERVER_STOPPED "Servitor WEB parou" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 50eabbc35..e4112953c 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL - пожалуйста обновите" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
пожалуйста обновите" #define D_WEBSERVER_ACTIVE_ON "Веб-сервер активен" #define D_WITH_IP_ADDRESS "с IP-адресом" #define D_WEBSERVER_STOPPED "Веб-сервер остановлен" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 4f741ac51..cf99703c8 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Pre používanie prostredia Tasmota povoľte JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY - prosím aktualizujte" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY
prosím aktualizujte" #define D_WEBSERVER_ACTIVE_ON "Aktívny Web server" #define D_WITH_IP_ADDRESS "na IP adrese" #define D_WEBSERVER_STOPPED "Web server zastavený" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index dd6b31469..6a92c1bc1 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "För att använda Tasmota, aktivera JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - var god uppgradera" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
var god uppgradera" #define D_WEBSERVER_ACTIVE_ON "Webbserver aktiv på" #define D_WITH_IP_ADDRESS "med IP-adress" #define D_WEBSERVER_STOPPED "Webbserver stoppad" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index f6f61ec56..b887c89c2 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük, lütfen yükseltin" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük
lütfen yükseltin" #define D_WEBSERVER_ACTIVE_ON "Web sunucusu aktif" #define D_WITH_IP_ADDRESS "IP adres ile" #define D_WEBSERVER_STOPPED "Web sunucusu durdu" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 71b7665c1..0efdd1c94 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL - будь-ласка оновіть" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
будь-ласка оновіть" #define D_WEBSERVER_ACTIVE_ON "Веб-сервер активний" #define D_WITH_IP_ADDRESS "з IP-адресом" #define D_WEBSERVER_STOPPED "Веб-сервер зупинений" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 586591278..88767053b 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -220,7 +220,7 @@ // webserver.ino #define D_NOSCRIPT "Tasmota要求浏览器支持 JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件 - 请升级" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件
请升级" #define D_WEBSERVER_ACTIVE_ON "Web 服务器地址:" #define D_WITH_IP_ADDRESS "IP 地址:" #define D_WEBSERVER_STOPPED "Web 服务已停止" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index ae6d4df07..11f85eef2 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -220,7 +220,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低 - 請升級" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低
請升級" #define D_WEBSERVER_ACTIVE_ON "Web服務器:" #define D_WITH_IP_ADDRESS "IP地址:" #define D_WEBSERVER_STOPPED "Web 服務器已停止" From 28694bff7ab846b8d6deb08e27a3edaa8482a0e7 Mon Sep 17 00:00:00 2001 From: Yuval <38878996+rt400@users.noreply.github.com> Date: Tue, 19 Mar 2019 15:09:32 +0200 Subject: [PATCH 1164/2222] Add new translate and fix some --- sonoff/language/he-HE.h | 104 ++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 8ce1a3a78..b26529cf2 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -54,7 +54,7 @@ #define D_ADMIN "מנהל" #define D_AIR_QUALITY "איכות אוויר" #define D_AP "AP" // Access Point -#define D_AS "as" +#define D_AS "-כ" #define D_AUTO "אוטומטי" #define D_BLINK "מהבהב" #define D_BLINKOFF "כיבוי היבהוב" @@ -62,11 +62,11 @@ #define D_BRIGHTLIGHT "בהירות" #define D_BSSID "BSSId" #define D_BUTTON "לחצן" -#define D_BY "ע" // Written by me +#define D_BY "על ידי" // Written by me #define D_BYTES "בייט" #define D_CELSIUS "צלזיוס" #define D_CHANNEL "ערוץ" -#define D_CO2 "Carbon dioxide" +#define D_CO2 "פחמן דו חמצני" #define D_CODE "קוד" // Button code #define D_COLDLIGHT "אור קר" #define D_COMMAND "פקודה" @@ -112,7 +112,7 @@ #define D_LWT "LWT" #define D_MODULE "מודול" #define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-press" +#define D_MULTI_PRESS "לחיצה מרובה" #define D_NOISE "רעש" #define D_NONE "כלום" #define D_OFF "כבוי" @@ -132,7 +132,7 @@ #define D_PROGRAM_FLASH_SIZE "גודל תוכנית פלאש" #define D_PROGRAM_SIZE "גודל תוכנית" #define D_PROJECT "פרויקט" -#define D_RAIN "Rain" +#define D_RAIN "גשם" #define D_RECEIVED "התקבל" #define D_RESTART "איתחול" #define D_RESTARTING "הפעלה מחדש" @@ -203,14 +203,14 @@ #define D_IN_MODE "במצב" #define D_CONNECT_FAILED_NO_IP_ADDRESS "IP החיבור נכשל מכיוון שלא התקבלה כתובת" #define D_CONNECT_FAILED_AP_NOT_REACHED "זמין AP החיבור נכשל כיוון שאין" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Connect failed with AP incorrect password" -#define D_CONNECT_FAILED_AP_TIMEOUT "Connect failed with AP timeout" -#define D_ATTEMPTING_CONNECTION "Attempting connection..." -#define D_CHECKING_CONNECTION "Checking connection..." -#define D_QUERY_DONE "Query done. MQTT services found" -#define D_MQTT_SERVICE_FOUND "MQTT service found on" -#define D_FOUND_AT "found at" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host not found" +#define D_CONNECT_FAILED_WRONG_PASSWORD "סיסמא שגויה , AP חיבור נכשל ל" +#define D_CONNECT_FAILED_AP_TIMEOUT "פג זמן המתנה , AP חיבור נכשל ל" +#define D_ATTEMPTING_CONNECTION "...מנסה להתחבר" +#define D_CHECKING_CONNECTION "...בודק חיבור" +#define D_QUERY_DONE "MQTT השאילתה נעשתה. נמצאו שירותי" +#define D_MQTT_SERVICE_FOUND "MQTT נמצאו שירותי" +#define D_FOUND_AT "נמצא ב" +#define D_SYSLOG_HOST_NOT_FOUND "לא נמצא Syslog מארח" // settings.ino #define D_SAVED_TO_FLASH_AT "נשמר לפלאש ב" @@ -219,7 +219,7 @@ #define D_ERASED_SECTOR "סקטור מחוק" // xdrv_02_webserver.ino -#define D_NOSCRIPT "JavaScript - כדי להשתמש ב קושחה אסמוטה אנא הפעל" +#define D_NOSCRIPT "JavaScript - כדי להשתמש בקושחת אסמוטה אנא הפעל" #define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "קושחה מינימלית - בבקשה אנא שדרג" #define D_WEBSERVER_ACTIVE_ON "שרת ווב פעיל" #define D_WITH_IP_ADDRESS "IP עם כתובת" @@ -230,7 +230,7 @@ #define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" #define D_TRYING_TO_CONNECT "מנסה לחבר את ההתקן לרשת" -#define D_RESTART_IN "הפעלה מחדש תןך" +#define D_RESTART_IN "הפעלה מחדש תוך" #define D_SECONDS "שניות" #define D_DEVICE_WILL_RESTART "ההתקן יופעל מחדש בעוד מס' שניות" #define D_BUTTON_TOGGLE "מצב" @@ -286,12 +286,12 @@ #define D_MORE_DEBUG "מיפוי נוסף" #define D_SYSLOG_HOST "Syslog מארח" #define D_SYSLOG_PORT "Syslog פורט" -#define D_TELEMETRY_PERIOD "Telemetry period" +#define D_TELEMETRY_PERIOD "זמן שידור" #define D_OTHER_PARAMETERS "פרמטרים שונים" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "סיסמת מנהל - אתר" +#define D_TEMPLATE "תבנית" +#define D_ACTIVATE "הפעל" +#define D_WEB_ADMIN_PASSWORD "סיסמת מנהל" #define D_MQTT_ENABLE "MQTT אפשר" #define D_FRIENDLY_NAME "שם ידידותי" #define D_BELKIN_WEMO "Belkin WeMo" @@ -374,38 +374,38 @@ #define D_WEMO_BASIC_EVENT "WeMo basic event" #define D_WEMO_EVENT_SERVICE "WeMo event service" #define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo setup" -#define D_RESPONSE_SENT "Response sent" +#define D_WEMO_SETUP "WeMo הגדרת" +#define D_RESPONSE_SENT "תגובה נשלחה" #define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue setup" +#define D_HUE_BRIDGE_SETUP "Hue הגדרת" #define D_HUE_API_NOT_IMPLEMENTED "Hue API not implemented" #define D_HUE_API "Hue API" #define D_HUE_POST_ARGS "Hue POST args" #define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" // xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" +#define D_DOMOTICZ_PARAMETERS "Domoticz פרמטרי" #define D_DOMOTICZ_IDX "Idx" #define D_DOMOTICZ_KEY_IDX "Key idx" #define D_DOMOTICZ_SWITCH_IDX "Switch idx" #define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_TEMP "טמפרטורה" + #define D_DOMOTICZ_TEMP_HUM "טמפרטורה,לחות" + #define D_DOMOTICZ_TEMP_HUM_BARO "טמפרטורה,לחות,ברומטר" + #define D_DOMOTICZ_POWER_ENERGY "הספק,צריכה" + #define D_DOMOTICZ_ILLUMINANCE "עוצמת אור" #define D_DOMOTICZ_COUNT "Count/PM1" #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" -#define D_DOMOTICZ_UPDATE_TIMER "Update timer" + #define D_DOMOTICZ_AIRQUALITY "איכות אוויר" +#define D_DOMOTICZ_UPDATE_TIMER "עדכן טיימר" // xdrv_09_timers.ino #define D_CONFIGURE_TIMER "הגדרות תזמון" #define D_TIMER_PARAMETERS "פרמטרים עבור תזמון" #define D_TIMER_ENABLE "אפשר תזמון" -#define D_TIMER_ARM "חמש" +#define D_TIMER_ARM "טען" #define D_TIMER_TIME "זמן" #define D_TIMER_DAYS "ימים" #define D_TIMER_REPEAT "חזרות" @@ -413,25 +413,25 @@ #define D_TIMER_ACTION "פעולה" // xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configure KNX" -#define D_KNX_PARAMETERS "KNX Parameters" -#define D_KNX_GENERAL_CONFIG "General" -#define D_KNX_PHYSICAL_ADDRESS "Physical Address" +#define D_CONFIGURE_KNX "KNX הגדר" +#define D_KNX_PARAMETERS "KNX פרמטרי" +#define D_KNX_GENERAL_CONFIG "כללי" +#define D_KNX_PHYSICAL_ADDRESS "כתובת פיזית" #define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "Enable KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" -#define D_ADD "Add" -#define D_DELETE "Delete" -#define D_REPLY "Reply" -#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" +#define D_KNX_ENABLE "KNX אפשר" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "נתונים לשליחה אל כתובות קבוצתיות" +#define D_ADD "הוסף" +#define D_DELETE "מחק" +#define D_REPLY "השב" +#define D_KNX_GROUP_ADDRESS_TO_READ "כתובות קבוצתיות לקבלת נתונים מ" #define D_LOG_KNX "KNX: " -#define D_RECEIVED_FROM "Received from" -#define D_KNX_COMMAND_WRITE "Write" -#define D_KNX_COMMAND_READ "Read" -#define D_KNX_COMMAND_OTHER "Other" -#define D_SENT_TO "sent to" +#define D_RECEIVED_FROM "התקבל מאת" +#define D_KNX_COMMAND_WRITE "כתיבה" +#define D_KNX_COMMAND_READ "קריאה" +#define D_KNX_COMMAND_OTHER "אחר" +#define D_SENT_TO "נשלח ל" #define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_ENHANCEMENT "שיפור התקשורת" #define D_KNX_TX_SLOT "KNX TX" #define D_KNX_RX_SLOT "KNX RX" @@ -459,7 +459,7 @@ // xsns_18_pms5003.ino #define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter #define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particals" +#define D_PARTICALS_BEYOND "חלקיקים" // xsns_32_mpu6050.ino #define D_AX_AXIS "Accel. X-Axis" @@ -483,10 +483,10 @@ #define D_CALIBRATION "כיול" //xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_WIND_DIRECTION "כיוון הרוח" +#define D_TX20_WIND_SPEED "מהירות הרוח" +#define D_TX20_WIND_SPEED_AVG "מהירות הרוח ממוצעת" +#define D_TX20_WIND_SPEED_MAX "מהירות הרוח מקסימלית" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" #define D_TX20_SOUTH "S" From bcd6cf0e34d0e6e66560fe9f4304c12941e3f3d9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Mar 2019 15:37:21 +0100 Subject: [PATCH 1165/2222] Release 6.5.0 Release 6.5.0 --- README.md | 2 + RELEASENOTES.md | 365 +++++++++++++++++++++------------------- sonoff/_changelog.ino | 192 ++++++++------------- sonoff/sonoff_post.h | 2 + sonoff/sonoff_version.h | 2 +- 5 files changed, 264 insertions(+), 299 deletions(-) diff --git a/README.md b/README.md index 021643824..424e9e802 100644 --- a/README.md +++ b/README.md @@ -133,9 +133,11 @@ Libraries used with Sonoff-Tasmota are: - [C2 Programmer](http://app.cear.ufpb.br/~lucas.hartmann/tag/efm8bb1/) - [esp-epaper-29-ws-20171230-gemu](https://github.com/gemu2015/Sonoff-Tasmota/tree/displays/lib) - [esp-knx-ip](https://github.com/envy/esp-knx-ip) +- FrogmoreScd30 - [I2Cdevlib](https://github.com/jrowberg/i2cdevlib) - [IRremoteEsp8266](https://github.com/markszabo/IRremoteESP8266) - [JobaTsl2561](https://github.com/joba-1/Joba_Tsl2561) +- [LinkedList](https://github.com/ivanseidel/LinkedList) - [Liquid Cristal](https://github.com/marcoschwartz/LiquidCrystal_I2C) - [MultiChannelGasSensor](http://wiki.seeedstudio.com/Grove-Multichannel_Gas_Sensor/) - [NeoPixelBus](https://github.com/Makuna/NeoPixelBus) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1198a6165..4485d3083 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -7,16 +7,14 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade 4. Migrate to **Sonoff-Tasmota 6.x** ## Release notes +### Core version 2.3.0 vs 2.4.2 +This release is based on ESP8266/Arduino library core 2.3.0 (again) as some people encountered wifi related issues on core 2.4.2. For others core 2.4.2 is working just fine. Both version are available from http://thehackbox.org/tasmota/release/ + ### Change in default initial configuration tool Firmware binary **sonoff-classic.bin** supports **WifiManager, Wps and SmartConfig** for initial configuration. The default tool is **Wps**. To save memory space all other binaries support **WifiManager only**. -See _changelog.ino how to enable them again. -- Define WIFI_CONFIG_TOOL now contains the default behaviour once a SSID has been configured. -- If no SSID is configured making a wifi connection impossible the new define WIFI_CONFIG_NO_SSID will be used. -- While define WIFI_CONFIG_NO_SSID is set to WIFI_WPSCONFIG in my_user_config.h the compiler will check for define USE_WPS and if not enabled WIFI_CONFIG_NO_SSID will default to WIFI_MANAGER using the webserver. If define USE_WEBSERVER is also not enabled WIFI_CONFIG_NO_SSID will default to WIFI_SMARTCONFIG. If define USE_SMARTCONFIG is also not enabled WIFI_CONFIG_NO_SSID will default to a new option WIFI_SERIAL allowing to enter wifi parameters to serial which is always possible. - ## Supported Modules The following hardware modules are supported. @@ -82,180 +80,203 @@ Module | Description 58 PS-16-DZ | PS-16-DZ Wifi dimmer for Incandescent Lights and Led 59 Teckin US | Teckin US and ZooZee SA102 Wifi Smart Switch with Energy Monitoring 60 Manzoku strip | Manzoku Wifi Smart Power Strip with four Relays +61 OBI Socket 2 | OBI 2 Wifi Smart Socket +62 YTF IR Bridge | YTF Infra Red Wifi Bridge +63 Digoo DG-SP202 | Digoo DG-SP202 Dual Wifi Smart Switch with Energy Monitoring +64 KA10 | Smanergy KA10 Wifi Smart Wall Switch with Energy Monitoring +65 Luminea ZX2820 | Luminea ZX2820 Wifi Smart Switch with Energy Monitoring +66 Mi Desk Lamp | Mi Desk Lamp with rotary switch and Wifi +67 SP10 | Tuya SP10 Wifi Smart Switch with Energy Monitoring +68 WAGA CHCZ02MB | WAGA life CHCZ02MB Wifi Smart Switch with Energy Monitoring +69 SYF05 | Sunyesmart SYF05 RGBWW Wifi Led Bulb ## Provided Binary Downloads -The following binary downloads have been compiled with ESP8266/Arduino library core version **2.4.2** patched with the Alexa fix. +The following binary downloads have been compiled with ESP8266/Arduino library core version **2.3.0**. -- **sonoff-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**. -- **sonoff-classic.bin** = The Classic version allows **initial installation** using either WifiManager, Wps or SmartConfig. -- **sonoff.bin** = The Sonoff version without Wps and SmartConfig configuration but adds more sensors. +- **sonoff.bin** = The Sonoff version without Wps and SmartConfig configuration but adds more sensors. **RECOMMENDED RELEASE BINARY** +- **sonoff-basic.bin** = The Basic version without Wps and SmartConfig configuration and most sensors. +- **sonoff-classic.bin** = The Classic version allows initial installation using either WifiManager, Wps or SmartConfig. - **sonoff-BG.bin** to **sonoff-TW.bin** = The Sonoff version without Wps and SmartConfig configuration in different languages. -- **sonoff-sensors.bin** = The Sensors version without Wps and SmartConfig configuration but adds even more useful sensors. -- **sonoff-display.bin** = The Display version without Wps and SmartConfig configuration but adds display support. - **sonoff-knx.bin** = The Knx version without Wps and SmartConfig configuration and some other features but adds KNX support. +- **sonoff-sensors.bin** = The Sensors version without Wps and SmartConfig configuration but adds even more useful sensors. +- **sonoff-display.bin** = The Display version without Wps and SmartConfig configuration and Energy Monitoring but adds display support. +- **sonoff-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**. + +Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/release/020402/ ### Available Features and Sensors -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | Remarks -|--------------------------------|---------|-------|---------|--------|------|---------|-------- -| ESP/Arduino lib v2.3.0 | 346k | 429k | 482k | 504k | 522k | 535k | -| ESP/Arduino lib v2.4.2 | 366k | 446k | 496k | 522k | 538k | 551k | No wifi sleep -| | | | | | | | -| MY_LANGUAGE en-GB | x | x | x | x | x | x | -| MQTT_LIBRARY_TYPE PUBSUBCLIENT | x | x | x | x | x | x | -| USE_WPS | - | - | x | - | - | - | WPS -| USE_SMARTCONFIG | - | - | x | - | - | - | SmartConfig -| USE_ARDUINO_OTA | - | - | - | - | - | - | -| USE_DOMOTICZ | - | - | x | x | x | x | -| USE_HOME_ASSISTANT | - | - | - | x | x | x | -| USE_MQTT_TLS | - | - | - | - | - | - | -| USE_KNX | - | - | - | - | x | - | -| USE_WEBSERVER | x | x | x | x | x | x | WifiManager -| USE_EMULATION | - | x | x | x | - | x | -| USE_DISCOVERY | - | - | x | x | x | x | -| WEBSERVER_ADVERTISE | - | - | x | x | x | x | -| MQTT_HOST_DISCOVERY | - | - | x | x | x | x | -| USE_TIMERS | - | x | - | x | x | x | -| USE_TIMERS_WEB | - | x | - | x | x | x | -| USE_SUNRISE | - | x | - | x | x | x | -| USE_RULES | - | x | - | x | x | x | -| | | | | | | -| USE_ADC_VCC | x | x | x | x | x | - | -| USE_DS18B20 | - | - | - | - | - | - | Single sensor -| USE_DS18x20 | - | - | x | x | x | x | Multiple sensors -| USE_DS18x20_LEGACY | - | - | - | - | - | - | Multiple sensors -| | | | | | | | -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | -| USE_I2C | - | - | - | x | x | x | -| USE_SHT | - | - | - | x | x | x | -| USE_HTU | - | - | - | x | x | x | -| USE_BMP | - | - | - | x | x | x | -| USE_BME680 | - | - | - | - | - | x | -| USE_BH1750 | - | - | - | x | x | x | -| USE_VEML6070 | - | - | - | - | - | x | -| USE_ADS1115 | - | - | - | - | - | x | -| USE_ADS1115_I2CDEV | - | - | - | - | - | - | -| USE_INA219 | - | - | - | - | - | x | -| USE_SHT3X | - | - | - | x | x | x | -| USE_TSL2561 | - | - | - | - | - | x | -| USE_MGS | - | - | - | - | - | x | -| USE_SGP30 | - | - | - | x | x | x | -| USE_SI1145 | - | - | - | - | - | x | -| USE_LM75AD | - | - | - | x | x | x | -| USE_APDS9960 | - | - | - | - | - | - | -| USE_MCP230xx | - | - | - | - | - | - | -| USE_PCA9685 | - | - | - | - | - | - | -| USE_MPR121 | - | - | - | - | - | - | -| USE_CCS811 | - | - | - | - | - | - | -| USE_MPU6050 | - | - | - | - | - | - | -| USE_DS3231 | - | - | - | - | - | - | -| USE_MGC3130 | - | - | - | - | - | - | -| | | | | | | | -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | -| USE_SPI | - | - | - | - | - | - | -| USE_MHZ19 | - | - | - | x | x | x | -| USE_SENSEAIR | - | - | - | x | x | x | -| USE_PMS5003 | - | - | - | x | x | x | -| USE_NOVA_SDS | - | - | - | x | x | x | -| USE_PZEM004T | - | - | - | x | x | x | -| USE_PZEM_AC | - | - | - | x | x | x | -| USE_PZEM_DC | - | - | - | x | x | x | -| USE_MCP39F501 | - | x | - | x | x | x | -| USE_SERIAL_BRIDGE | - | - | - | x | x | x | -| USE_SDM120 | - | - | - | - | - | x | -| USE_SDM630 | - | - | - | - | - | x | -| USE_MP3_PLAYER | - | - | - | - | - | x | -| USE_TUYA_DIMMER | - | x | - | x | x | x | -| USE_ARMTRONIX_DIMMERS | - | x | - | x | x | x | -| USE_PS_16_DZ | - | x | - | x | x | x | -| USE_AZ7798 | - | - | - | - | - | - | -| USE_IR_REMOTE | - | - | - | x | x | x | -| USE_IR_HVAC | - | - | - | - | - | x | -| USE_IR_RECEIVE | - | - | - | x | x | x | -| USE_WS2812 | - | - | x | x | x | x | -| USE_WS2812_DMA | - | - | - | - | - | - | -| USE_ARILUX_RF | - | - | - | x | x | x | -| USE_SR04 | - | - | - | x | x | x | -| USE_TM1638 | - | - | - | - | - | x | -| USE_HX711 | - | - | - | x | x | x | -| USE_RF_FLASH | - | - | - | x | x | x | -| USE_TX20_WIND_SENSOR | - | - | - | x | x | x | -| USE_RC_SWITCH | - | - | - | x | x | x | -| USE_RF_SENSOR | - | - | - | - | - | x | AlectoV2 only -| USE_DISPLAY | - | - | - | - | - | - | +| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks +|-----------------------|---------|-------|---------|--------|------|---------|---------|-------- +| MY_LANGUAGE en-GB | x | x | x | x | x | x | x | +| USE_WPS | - | - | x | - | - | - | - | WPS +| USE_SMARTCONFIG | - | - | x | - | - | - | - | SmartConfig +| USE_ARDUINO_OTA | - | - | - | - | - | - | - | +| USE_DOMOTICZ | - | - | x | x | x | x | - | +| USE_HOME_ASSISTANT | - | - | - | x | x | x | - | +| USE_MQTT_TLS | - | - | - | - | - | - | - | +| USE_KNX | - | - | - | - | x | - | - | +| USE_WEBSERVER | x | x | x | x | x | x | x | WifiManager +| USE_EMULATION | - | x | x | x | - | x | - | +| USE_DISCOVERY | - | - | x | x | x | x | x | +| WEBSERVER_ADVERTISE | - | - | x | x | x | x | x | +| MQTT_HOST_DISCOVERY | - | - | x | x | x | x | x | +| USE_TIMERS | - | x | - | x | x | x | x | +| USE_TIMERS_WEB | - | x | - | x | x | x | x | +| USE_SUNRISE | - | x | - | x | x | x | x | +| USE_RULES | - | x | - | x | x | x | x | +| USE_EXPRESSION | - | - | - | - | - | - | - | +| | | | | | | | | +| USE_ADC_VCC | x | x | x | x | x | - | x | +| USE_DS18B20 | - | - | - | - | - | - | - | Single sensor +| USE_DS18x20 | - | - | x | x | x | x | x | Multiple sensors +| USE_DS18x20_LEGACY | - | - | - | - | - | - | - | Multiple sensors +| | | | | | | | | +| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks +| USE_I2C | - | - | - | x | x | x | x | +| USE_SHT | - | - | - | x | x | x | x | +| USE_HTU | - | - | - | x | x | x | x | +| USE_BMP | - | - | - | x | x | x | x | +| USE_BME680 | - | - | - | - | - | x | - | +| USE_BH1750 | - | - | - | x | x | x | x | +| USE_VEML6070 | - | - | - | - | - | x | - | +| USE_ADS1115 | - | - | - | - | - | x | - | +| USE_ADS1115_I2CDEV | - | - | - | - | - | - | - | +| USE_INA219 | - | - | - | - | - | x | - | +| USE_SHT3X | - | - | - | x | x | x | x | +| USE_TSL2561 | - | - | - | - | - | x | - | +| USE_MGS | - | - | - | - | - | x | - | +| USE_SGP30 | - | - | - | x | x | x | x | +| USE_SI1145 | - | - | - | - | - | - | - | +| USE_LM75AD | - | - | - | x | x | x | x | +| USE_APDS9960 | - | - | - | - | - | - | - | +| USE_MCP230xx | - | - | - | - | - | - | - | +| USE_PCA9685 | - | - | - | - | - | - | - | +| USE_MPR121 | - | - | - | - | - | - | - | +| USE_CCS811 | - | - | - | - | - | - | - | +| USE_MPU6050 | - | - | - | - | - | - | - | +| USE_DS3231 | - | - | - | - | - | - | - | +| USE_MGC3130 | - | - | - | - | - | - | - | +| USE_MAX44009 | - | - | - | - | - | - | - | +| USE_SCD30 | - | - | - | - | - | x | - | +| | | | | | | | | +| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks +| USE_SPI | - | - | - | - | - | - | x | +| USE_MHZ19 | - | - | - | x | x | x | x | +| USE_SENSEAIR | - | - | - | x | x | x | x | +| USE_PMS5003 | - | - | - | x | x | x | x | +| USE_NOVA_SDS | - | - | - | x | x | x | x | +| USE_ENERGY_SENSOR | - | x | x | x | x | x | - | +| USE_PZEM004T | - | - | - | x | x | x | - | +| USE_PZEM_AC | - | - | - | x | x | x | - | +| USE_PZEM_DC | - | - | - | x | x | x | - | +| USE_MCP39F501 | - | x | - | x | x | x | - | +| USE_SERIAL_BRIDGE | - | - | - | x | x | x | x | +| USE_SDM120 | - | - | - | - | - | x | - | +| USE_SDM630 | - | - | - | - | - | x | - | +| USE_MP3_PLAYER | - | - | - | - | - | x | - | +| USE_TUYA_DIMMER | - | x | - | x | x | x | x | +| USE_ARMTRONIX_DIMMERS | - | x | - | x | x | x | x | +| USE_PS_16_DZ | - | x | - | x | x | x | x | +| USE_AZ7798 | - | - | - | - | - | - | - | +| USE_PN532_HSU | - | - | - | - | - | x | - | +| USE_IR_REMOTE | - | - | - | x | x | x | x | +| USE_IR_HVAC | - | - | - | - | - | x | - | +| USE_IR_RECEIVE | - | - | - | x | x | x | x | +| USE_WS2812 | - | - | x | x | x | x | x | +| USE_WS2812_DMA | - | - | - | - | - | - | - | +| USE_ARILUX_RF | - | - | - | x | x | x | - | +| USE_SR04 | - | - | - | x | x | x | x | +| USE_TM1638 | - | - | - | - | - | x | - | +| USE_HX711 | - | - | - | x | x | x | x | +| USE_RF_FLASH | - | - | - | x | x | x | - | +| USE_TX20_WIND_SENSOR | - | - | - | x | x | x | x | +| USE_RC_SWITCH | - | - | - | x | x | x | x | +| USE_RF_SENSOR | - | - | - | - | - | x | - | AlectoV2 only +| USE_SM16716 | - | x | x | x | x | x | x | +| USE_DISPLAY | - | - | - | - | - | - | x | +| USE_DISPLAY_LCD | - | - | - | - | - | - | x | +| USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x | +| USE_DISPLAY_MATRIX | - | - | - | - | - | - | x | +| USE_DISPLAY_ILI9341 | - | - | - | - | - | - | x | +| USE_DISPLAY_EPAPER_29 | - | - | - | - | - | - | x | Disabled for core 2.3.0 ## Changelog -Version 6.4.1 20181225 - * Change RAM usage BMP/BME I2C sensors - * Change FallbackTopic from cmnd/\/ to cmnd/\_fb/ to discriminate from Topic (#1528) - * Change FallbackTopic detection (#4706) - * Change Hass discovery to short MQTT messages as used by Hass 0.81 and up (#4711) - * Change MQTT GUI password handling (#4723) - * Fix possible dtostrf buffer overflows by increasing buffers - * Fix wifi strongest signal detection (#4704) - * Fix Alexa "this value is outside the range of the device". Needs power cycle and Alexa deletion/discovery cycle. (#3159, #4712) - * Add Slovak language file (#4663) - * Add support for AZ-Instrument 7798 CO2 meter/datalogger (#4672) - * Add define WIFI_SOFT_AP_CHANNEL in my_user_config.h to set Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI (#4673) - * Add define USE_MQTT_TLS_CA_CERT for checking MQTT TLS against root ca using Let's Encrypt cert from sonoff_letsencrypt.h - not supported with core 2.3.0 (#4703) - -Version 6.4.0 20181217 - * Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40%. - In case of web page errors clear your browser cache or do Page Reload (F5 or Ctrl+R) - * Change enforcing flashmode dout but it is still mandatory - * Change bootcount update (being first) flash write to 10 seconds after restart - * Change display and epaper drivers - * Change command WebSend Host header field from IP address to hostname (#4331) - * Change log buffer size from 512 to 520 to accommodate http sensor data (#4354) - * Change default WIFI_CONFIG_TOOL from WIFI_WAIT to WIFI_RETRY in my_user_config.h (#4400) - * Change webgui refresh time delay for Save Settings and local OTA Upload (#4423) - * Change SR-04 driver to use NewPing library (#4488) - * Change MCP230xx driver to support interrupt retention over teleperiod (#4547) - * Change support for MPU6050 using DMP (#4581) - * Fix unintended function overload of WifiState - * Fix wifi connection errors using wifi disconnect and ESP.reset instead of ESP.restart - * Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by Sonoff Basic R2 driver delay implementation (and possibly core bug) - * Fix MQTT connection error after restart - * Fix wifi re-scan connection baseline - * Fix possible strncat buffer overflows - * Fix intermittent Pzem sensor energy overflow calculation error - * Fix shelly2 ghost switching caused by lack of pull-up inputs (#4255) - * Fix hardware serial pin configuration. To keep using hardware serial swap current Rx/Tx pin configuration only (#4280) - * Fix MqttRetry values above 255 seconds (#4424) - * Fix WifiManager functionality on initial installation (#4433) - * Fix ArduinoOTA for Core 2.5.0 (#4620) - * Add minutes to commands Timezone to allow all possible world timezones - * Add more strict checks for GPIO selections - * Add code image and optional commit number to version - * Add dynamic delay to main loop providing time for wifi background tasks - * Add additional start-up delay during initial wifi connection - * Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver - * Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver - * Add user definition of defines WIFI_RSSI_THRESHOLD (default 10) and WIFI_RESCAN_MINUTES (default 44) - * Add command SetOption58 0/1 to enable IR raw data info in JSON message (#2116) - * Add command IRSend \|0,\,\,.. to allow raw data transmission (#2116) - * Add command SetOption56 0/1 to enable wifi network scan and select highest RSSI (#3173) - * Add command SetOption57 0/1 to enable wifi network re-scan every 44 minutes with a rssi threshold of 10 to select highest RSSI (#3173) - * Add support for SDM220 (#3610) - * Add default sleep 1 to sonoff-basic to lower energy consumption (#4217) - * Add wifi status to Tuya (#4221) - * Add delays to reduce CPU usage at boot time (#4233) - * Add command SetOption24 0/1 to select pressure unit as hPa or mmHg (#4241) - * Add optional hardware serial when GPIO13(Rx) and GPIO15(Tx) are selected removing hardware serial from GPIO01(Tx) and GPIO03(Rx) (#4288) - * Add support for Gosund SP1 v2.3 Power Socket with Energy Monitoring (#4297) - * Add support for Armtronix dimmers. See wiki for info (#4321) - * Add to command WebSend option to send a direct path when command starts with a slash (#4329) - * Add support for LG HVac and IrRemote (#4377) - * Add initial support for Hass sensor discovery (#4380) - * Add support for Fujitsu HVac and IrRemote (#4387) - * Add support for I2C MGC3130 Electric Field Effect sensor by Christian Baars (#3774, #4404) - * Add command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420) - * Add CPU average load to state message (#4431) - * Add command SetOption59 0/1 to change state topic from tele/STATE to stat/RESULT (#4450) - * Add support for SM Smart Wifi Dimmer PS-16-DZ (#4465) - * Add support for Teckin US Power Socket with Energy Monitoring (#4481) - * Add command SetOption60 0/1 to select dynamic sleep (0) or sleep (1) (#4497) - * Add support for iFan02 Fanspeed in Domoticz using a selector (#4517) - * Add support for GPIO02 for newer Sonoff Basic (#4518) - * Add Announce Switches to MQTT Discovery (#4531) - * Add support for Manzoku Power Strip (#4590) +Version 6.5.0 20190319 + * Remove commands SetOption14 and SetOption63 as it has been superseded by command Interlock + * Remove command SetOption35 0-255 for mDNS start-up delay (#4793) + * Remove support for MQTT_LIBRARY_TYPE, MQTT_ARDUINOMQTT and MQTT_TASMOTAMQTT (#5474) + * Change webserver content handling from single String to small Chunks increasing RAM + * Change code use of boolean to bool and byte to uint8_t + * Change code uint8_t flags to bool flags + * Change sonoff_template.h layout regarding optional module flags like ADC0 + * Change sonoff_template.h module lay-out by removing non-configurable GPIOs + * Change button driver making it modular + * Change switch driver making it modular and introduce input filter (#4665, #4724) + * Change switch input detection by optimizing switch debounce (#4724) + * Change web authentication (#4865) + * Change image name BE_MINIMAL to FIRMWARE_MINIMAL and USE_xyz to FIRMWARE_xyz (#5106) + * Change GUI weblog from XML to plain text solving possible empty screens (#5154) + * Fix most compiler warnings + * Fix Display exception 28 when JSON value is NULL received + * Fix epaper driver (#4785) + * Fix HAss Sensor Discovery Software Watchdog restart (#4831, #4988) + * Fix allowable MAX_RULE_VARS to 16 (#4933) + * Fix mDNS addService (#4938, #4951) + * Fix HAss discovery of MHZ19(B) sensors (#4992) + * Fix some exceptions and watchdogs due to lack of stack space (#5215) + * Fix GUI wifi password acception starting with asteriks (*) (#5231, #5242) + * Fix command WebSend intermittent results (#5273, #5304) + * Fix additional characters in fallbacktopic, hostname and mqttclient on core 2.5.0 (#5359, #5417) + * Fix Energy TotalStartTime when commands EnergyReset0 and/or EnergyReset3 used (#5373) + * Fix DS18S20 temperature calculation (#5375) + * Fix float calculations in range from 0 to -1 (#5386) + * Fix exception on GUI Configure Logging and Configure Other (#5424) + * Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors + * Add command SerialDelimiter 128 to filter reception of only characters between ASCII 32 and 127 (#5131) + * Add command SSerialSend5 \ to SerialBridge + * Add command Interlock 0 / 1 / 1,2 3,4 .. to control interlock ON/OFF and add up to 8 relays in 1 to 4 interlock groups (#4910, #5014) + * Add command Template 255 to copy module configuration over to current active template and store as user template named Merged (#5371) + * Add command WifiConfig 7 to allow reset of device in AP mode without admin password (#5297) + * Add command SetOption36 to control boot loop default restoration (#4645, #5063) + * Add command SetOption37 for RGBCW color mapping (#5326) + * Add command SetOption55 0/1 and define MDNS_ENABLE to disable/enable mDNS (#4793, #4923) + * Add command SetOption62 0/1 to disable retain on Button or Switch hold messages (#5299) + * Add support for Smanergy KA10 Smart Wall Socket with Energy monitoring + * Add support for commands in sensor drivers + * Add support for MAX31855 K-Type thermocouple sensor using softSPI (#4764) + * Add support for Near Field Communication (NFC) controller PN532 using Serial (#4791, #5162) + * Add support for OBI Power Socket 2 (#4829) + * Add support for YTF IR Bridge (#4855) + * Add support for Mi LED Desk Lamp with rotary switch (#4887) + * Add support for Digoo DG-SP202 Smart Socket with Energy monitoring (#4891) + * Add support for MAX44009 Ambient Light sensor (#4907) + * Add support for inverted buttons and inverted buttons without pullup (#4914) + * Add support for Luminea ZX2820 Smart Socket with Energy monitoring (#4921) + * Add support for multiple ADS1115 I2C devices (#5083) + * Add support for online template change using command Template or GUI Configure Other (#5177) + * Add support for Korean language translations (#5344) + * Add support for sensor SCD30 (#5434) + * Add parameter CFG_HOLDER to status 1 message (#5206) + * Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name + * Add Resolution property to Status 3 report providing previous SetOption second value property + * Add property MqttCount to status 6 message representing number of Mqtt re-connections + * Add property LinkCount to state and status 11 message representing number of Wifi Link re-connections + * Add property Downtime to state and status 11 message representing the duration of wifi connection loss + * Add variable %timestamp% to rules (#4749) + * Add rule support for "==", "!=" ">=" and "<=" (#5122) + * Add rule expression enabled by define USE_EXPRESSION in my_user_config.h (#5210) + * Add Power status functionality to LED2 when configured leaving LED1 for Link status indication + * Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring as used in Sonoff Pow and many Tuya based devices + * Add user configuration of MCP39F501 Energy Monitoring as used in Shelly2 + * Add online template configuration using both commands and Configure Template menu option in GUI + * Add (S)SerialSend3 escape sequence \x to allow hexadecimal byte value (#3560, #4947) + * Add define DS18B20_INTERNAL_PULLUP to select internal input pullup when only one DS18B20 sensor is connected eliminating external resistor (#4738) + * Add button control when no relay configured (#4682) + * Add startup delay of 4 seconds to button control (#4829) + * Add core version conditional compile options to provided PWM files (#4917) + * Add resiliency to saved Settings (#5065) + * Add MHZ19 Temperature as Domoticz Temperature selection (#5128) + * Add HAss status sensor (#5139) + * Add status message to former declined group commands (#5145) + * Add 0x to IRRemote (SetOption29) and RCSwitch (SetOption28) received hexadecimal data (#5431) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0e7ab1e8c..68d677454 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,141 +1,81 @@ -/* 6.4.2.22 20190315 +/* 6.5.0 20190319 + * Remove commands SetOption14 and SetOption63 as it has been superseded by command Interlock + * Remove command SetOption35 0-255 for mDNS start-up delay (#4793) * Remove support for MQTT_LIBRARY_TYPE, MQTT_ARDUINOMQTT and MQTT_TASMOTAMQTT (#5474) - * - * 6.4.1.21 20190309 - * Fix exception on GUI Configure Logging and Configure Other (#5424) - * Add support for sensor SCD30 (#5434) - * Add support for commands in sensor drivers - * Add 0x to IRRemote (SetOption29) and RCSwitch (SetOption28) received hexadecimal data (#5431) - * Add button control when no relay configured (#4682) - * - * 6.4.1.20 20190304 - * Changed webserver content handling from single String to small Chunks increasing RAM - * Changed logging message handling + * Change webserver content handling from single String to small Chunks increasing RAM + * Change code use of boolean to bool and byte to uint8_t + * Change code uint8_t flags to bool flags + * Change sonoff_template.h layout regarding optional module flags like ADC0 + * Change sonoff_template.h module lay-out by removing non-configurable GPIOs + * Change button driver making it modular + * Change switch driver making it modular and introduce input filter (#4665, #4724) + * Change switch input detection by optimizing switch debounce (#4724) + * Change web authentication (#4865) + * Change image name BE_MINIMAL to FIRMWARE_MINIMAL and USE_xyz to FIRMWARE_xyz (#5106) + * Change GUI weblog from XML to plain text solving possible empty screens (#5154) + * Fix most compiler warnings + * Fix Display exception 28 when JSON value is NULL received + * Fix epaper driver (#4785) + * Fix HAss Sensor Discovery Software Watchdog restart (#4831, #4988) + * Fix allowable MAX_RULE_VARS to 16 (#4933) + * Fix mDNS addService (#4938, #4951) + * Fix HAss discovery of MHZ19(B) sensors (#4992) + * Fix some exceptions and watchdogs due to lack of stack space (#5215) + * Fix GUI wifi password acception starting with asteriks (*) (#5231, #5242) + * Fix command WebSend intermittent results (#5273, #5304) * Fix additional characters in fallbacktopic, hostname and mqttclient on core 2.5.0 (#5359, #5417) - * Add command Template 255 to copy module configuration over to current active template and store as user template named Merged (#5371) - * - * 6.4.1.19 20190222 - * Add command SetOption37 for RGBCW color mapping (#5326) - * Add Korean language translations (#5344) * Fix Energy TotalStartTime when commands EnergyReset0 and/or EnergyReset3 used (#5373) * Fix DS18S20 temperature calculation (#5375) * Fix float calculations in range from 0 to -1 (#5386) - * - * 6.4.1.18 20190221 - * Fix some exceptions and watchdogs due to lack of stack space - part 1 (#5215) - * Fix some exceptions and watchdogs due to lack of stack space - part 2 - * Add command SetOption62 0/1 to disable retain on Button or Swith hold messages (#5299) - * Add option WifiConfig 7 to allow reset of device in AP mode without admin password (#5297) - * Fix command WebSend when using a port number as regression from 6.4.1.17 (#5304) - * - * 6.4.1.17 20190214 - * Change template update by removing possibility to add user module config keeping template as defined (#5222) - * Fix regression from 6.4.1.16 where GPIO9 and GPIO10 connected devices did not work (#5197) - * Fix GUI wifi password acception starting with asteriks (*) (#5231, #5242) - * Add rule expression enabled by define USE_EXPRESSION in my_user_config.h (#5210) - * Add Configure Template menu option to GUI (#5222) - * Remove command SetOption62 as it's functionality is replaced by user changing the device template (#5255) - * Add property LinkCount to state and status 11 message representing number of Wifi Link re-connections - * Add property MqttCount to status 6 message representing number of Mqtt re-connections - * Add property Downtime to state and status 11 message representing the duration of wifi connection loss - * Fix command WebSend intermittent results (#5273) - * - * 6.4.1.16 20190211 - * Initial support for online template change using command Template or GUI Configure Other (#5177) - * Add parameter CFG_HOLDER to status 1 message (#5206) - * Update GUI - * - * 6.4.1.15 20190208 - * Change image name BE_MINIMAL to FIRMWARE_MINIMAL (#5106) - * Change image names USE_xyz to FIRMWARE_xyz (#5106) + * Fix exception on GUI Configure Logging and Configure Other (#5424) + * Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors * Add command SerialDelimiter 128 to filter reception of only characters between ASCII 32 and 127 (#5131) - * Add status message to former declined group commands (#5145) - * - * 6.4.1.14 20190203 - * Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name - * Add Resolution property to Status 3 report providing previous SetOption second value property - * Fix IR local echo - * Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring as used in Sonoff S31, Pow Ra and many Tuya based devices - * Add user configuration of MCP39F501 Energy Monitoring as used in Shelly2 - * Add support for multiple ADS1115 I2C devices (#5083) - * Add rule support for "==", "!=" ">=" and "<=" (#5122) - * Add Hass status sensor (#5139) - * Change GUI weblog solving possible empty screens (#5154) - * Change PN532 support from I2C to Serial for more stability (#5162) - * Add MHZ19 Temperature as Domoticz Temperature selection (#5128) - * - * 6.4.1.13 20190130 + * Add command SSerialSend5 \ to SerialBridge + * Add command Interlock 0 / 1 / 1,2 3,4 .. to control interlock ON/OFF and add up to 8 relays in 1 to 4 interlock groups (#4910, #5014) + * Add command Template 255 to copy module configuration over to current active template and store as user template named Merged (#5371) + * Add command WifiConfig 7 to allow reset of device in AP mode without admin password (#5297) * Add command SetOption36 to control boot loop default restoration (#4645, #5063) - * Add resiliency to saved Settings (#5065) - * - * 6.4.1.12 20190128 - * Change code use of boolean to bool and byte to uint8_t - * Change code uint8_t flags to bool flags - * - * 6.4.1.11 20190124 - * Remove command SetOption14 as it has been superseded by command Interlock - * Remove command SetOption63 as it has been superseded by command Interlock - * Add command Interlock 0 / 1 / 1,2 3,4 .. to control interlock ON/OFF and add up to 8 relays in 1 to 4 interlock groups (#5014) - * Add core version conditional compile options to provided PWM files (#4917) - * Add support for inverted buttons and inverted buttons without pullup (#4914) - * - * 6.4.1.10 20190121 - * Fix Hass discovery of MHZ19(B) sensors (#4992) - * Fix Hass Software Watchdog exception during discovery (#4988) - * Add support for MAX44009 Ambient Light sensor (#4907) - * - * 6.4.1.9 20190115 - * Add support for Mi LED Desk Lamp with rotary switch (#4887) - * Fix mDNS addService (#4938, #4951) - * Fix allowable MAX_RULE_VARS to 16 (#4933) - * Add (S)SerialSend3 escape sequence \x to allow hexadecimal byte value (#3560, #4947) - * Add SerialBridge command SSerialSend5 - * - * 6.4.1.8 20190107 - * Change sonoff_template.h layout regarding optional module flags like ADC0 - * Add command SetOption62 1 to force no Button/Switch pullup on dedicated modules. Currently only supported on Shelly2 (#4841) - * Fix Display exception 28 when JSON value is NULL received - * Fix Home Assistant Sensor Discovery Software Watchdog restart (#4831) + * Add command SetOption37 for RGBCW color mapping (#5326) + * Add command SetOption55 0/1 and define MDNS_ENABLE to disable/enable mDNS (#4793, #4923) + * Add command SetOption62 0/1 to disable retain on Button or Switch hold messages (#5299) + * Add support for Smanergy KA10 Smart Wall Socket with Energy monitoring + * Add support for commands in sensor drivers + * Add support for MAX31855 K-Type thermocouple sensor using softSPI (#4764) + * Add support for Near Field Communication (NFC) controller PN532 using Serial (#4791, #5162) * Add support for OBI Power Socket 2 (#4829) * Add support for YTF IR Bridge (#4855) - * Change web authentication (#4865) + * Add support for Mi LED Desk Lamp with rotary switch (#4887) * Add support for Digoo DG-SP202 Smart Socket with Energy monitoring (#4891) - * Add support for Smanergy KA10 Smart Wall Socket with Energy monitoring + * Add support for MAX44009 Ambient Light sensor (#4907) + * Add support for inverted buttons and inverted buttons without pullup (#4914) * Add support for Luminea ZX2820 Smart Socket with Energy monitoring (#4921) - * Add define MDNS_ENABLE to control initial mDNS state (#4923) - * Add split interlock part 1 (#4910) - * - * 6.4.1.7 20190106 - * Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6 - * Add Power status functionality to LED2 when configured leaving LED1 for Link status indication - * Add no pull-up control to Shelly 2 module (default is pull-up, change GPIO2 to Switch3n for no pull-up) (#4841) - * Add 4 seconds startup delay to button control (#4829) - * Change button driver making it modular - * - * 6.4.1.6 20190105 - * Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors - * - * 6.4.1.5 20190103 - * Remove command SetOption35 0-255 for mDNS start-up delay (#4793) - * Add command SetOption55 0/1 to disable/enable mDNS (#4793) - * - * 6.4.1.4 20190101 - * Update Copyright (C) 2019 - * Fix epaper driver (#4785) - * Add support for Near Field Communication (NFC) controller PN532 using I2C (#4791) - * - * 6.4.1.3 20181229 - * Change sonoff_template.h module lay-out by removing non-configurable GPIOs - * Add support for MAX31855 K-Type thermocouple sensor using softSPI (#4764) - * - * 6.4.1.2 20181228 - * Change switch driver making it modular and introduce input filter (#4665, #4724) - * Add define DS18B20_INTERNAL_PULLUP to select internal input pullup when only one DS18B20 sensor is connected eliminating external resistor (#4738) + * Add support for multiple ADS1115 I2C devices (#5083) + * Add support for online template change using command Template or GUI Configure Other (#5177) + * Add support for Korean language translations (#5344) + * Add support for sensor SCD30 (#5434) + * Add parameter CFG_HOLDER to status 1 message (#5206) + * Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name + * Add Resolution property to Status 3 report providing previous SetOption second value property + * Add property MqttCount to status 6 message representing number of Mqtt re-connections + * Add property LinkCount to state and status 11 message representing number of Wifi Link re-connections + * Add property Downtime to state and status 11 message representing the duration of wifi connection loss * Add variable %timestamp% to rules (#4749) - * - * 6.4.1.1 20181224 - * Fix most compiler warnings - * Change switch input detection by optimizing switch debounce (#4724) + * Add rule support for "==", "!=" ">=" and "<=" (#5122) + * Add rule expression enabled by define USE_EXPRESSION in my_user_config.h (#5210) + * Add Power status functionality to LED2 when configured leaving LED1 for Link status indication + * Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring as used in Sonoff Pow and many Tuya based devices + * Add user configuration of MCP39F501 Energy Monitoring as used in Shelly2 + * Add online template configuration using both commands and Configure Template menu option in GUI + * Add (S)SerialSend3 escape sequence \x to allow hexadecimal byte value (#3560, #4947) + * Add define DS18B20_INTERNAL_PULLUP to select internal input pullup when only one DS18B20 sensor is connected eliminating external resistor (#4738) + * Add button control when no relay configured (#4682) + * Add startup delay of 4 seconds to button control (#4829) + * Add core version conditional compile options to provided PWM files (#4917) + * Add resiliency to saved Settings (#5065) + * Add MHZ19 Temperature as Domoticz Temperature selection (#5128) + * Add HAss status sensor (#5139) + * Add status message to former declined group commands (#5145) + * Add 0x to IRRemote (SetOption29) and RCSwitch (SetOption28) received hexadecimal data (#5431) * * 6.4.1 20181224 * Change RAM usage BMP/BME I2C sensors diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index bcbc8f2ad..095c7e2ac 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -245,7 +245,9 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_SPI // Hardware SPI using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK) in addition to two user selectable GPIOs(CS and DC) #define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display (+19k code) +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // There is not enough spare RAM with core 2.3.0 to support the following #define USE_DISPLAY_EPAPER_29 // [DisplayModel 5] Enable e-paper 2.9 inch display (+19k code) +#endif #undef USE_ARILUX_RF // Remove support for Arilux RF remote controller (-0k8 code, 252 iram (non 2.3.0)) #undef USE_RF_FLASH // Remove support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (-3k code) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index b9516367a..0e9c322ac 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040116 +#define VERSION 0x06050000 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" From dfc67332cd5b41591713f309bd9c6ed569899f9c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Mar 2019 15:42:28 +0100 Subject: [PATCH 1166/2222] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 424e9e802..8a8402339 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest) the binaries can also be OTA downloaded from http://thehackbox.org/tasmota/release/ ### Development -[![Dev Version](https://img.shields.io/badge/development%20version-6.4.1.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-6.5.0.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota) From b7f89c0a8c63f6c8bcef681449dc384e4a24d9bc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Mar 2019 17:31:43 +0100 Subject: [PATCH 1167/2222] 6.5.0.1 Change GUI data collection 6.5.0.1 20190319 * Change Web GUI sensor data collection --- sonoff/_changelog.ino | 5 ++- sonoff/i18n.h | 16 ++++----- sonoff/sonoff.h | 2 +- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_webserver.ino | 55 ++++++++++++++++++++----------- sonoff/xdrv_03_energy.ino | 18 +++++----- sonoff/xsns_01_counter.ino | 6 ++-- sonoff/xsns_02_analog.ino | 4 +-- sonoff/xsns_04_snfsc.ino | 10 +++--- sonoff/xsns_05_ds18b20.ino | 4 +-- sonoff/xsns_05_ds18x20.ino | 4 +-- sonoff/xsns_05_ds18x20_legacy.ino | 4 +-- sonoff/xsns_06_dht.ino | 6 ++-- sonoff/xsns_07_sht1x.ino | 6 ++-- sonoff/xsns_08_htu21.ino | 6 ++-- sonoff/xsns_09_bmp.ino | 13 ++++---- sonoff/xsns_10_bh1750.ino | 4 +-- sonoff/xsns_11_veml6070.ino | 16 ++++----- sonoff/xsns_12_ads1115.ino | 4 +-- sonoff/xsns_12_ads1115_i2cdev.ino | 4 +-- sonoff/xsns_13_ina219.ino | 6 ++-- sonoff/xsns_14_sht3x.ino | 6 ++-- sonoff/xsns_15_mhz19.ino | 6 ++-- sonoff/xsns_16_tsl2561.ino | 6 ++-- sonoff/xsns_17_senseair.ino | 8 ++--- sonoff/xsns_18_pms5003.ino | 6 ++-- sonoff/xsns_19_mgs.ino | 20 +++++------ sonoff/xsns_20_novasds.ino | 6 ++-- sonoff/xsns_21_sgp30.ino | 6 ++-- sonoff/xsns_22_sr04.ino | 6 ++-- sonoff/xsns_23_sdm120.ino | 8 ++--- sonoff/xsns_24_si1145.ino | 6 ++-- sonoff/xsns_25_sdm630.ino | 6 ++-- sonoff/xsns_26_lm75ad.ino | 4 +-- sonoff/xsns_27_apds9960.ino | 6 ++-- sonoff/xsns_28_tm1638.ino | 2 +- sonoff/xsns_29_mcp230xx.ino | 6 ++-- sonoff/xsns_30_mpr121.ino | 10 +++--- sonoff/xsns_31_ccs811.ino | 6 ++-- sonoff/xsns_32_mpu6050.ino | 24 ++++++-------- sonoff/xsns_34_hx711.ino | 14 ++++---- sonoff/xsns_35_tx20.ino | 6 ++-- sonoff/xsns_36_mgc3130.ino | 6 ++-- sonoff/xsns_37_rfsensor.ino | 22 ++++++------- sonoff/xsns_38_az7798.ino | 8 ++--- sonoff/xsns_39_max31855.ino | 8 ++--- sonoff/xsns_41_max44009.ino | 5 ++- sonoff/xsns_42_scd30.ino | 10 +++--- 48 files changed, 219 insertions(+), 203 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 68d677454..978aa861f 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.5.0 20190319 +/* 6.5.0.1 20190319 + * Change Web GUI sensor data collection + * + * 6.5.0 20190319 * Remove commands SetOption14 and SetOption63 as it has been superseded by command Interlock * Remove command SetOption35 0-255 for mDNS start-up delay (#4793) * Remove support for MQTT_LIBRARY_TYPE, MQTT_ARDUINOMQTT and MQTT_TASMOTAMQTT (#5474) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 73e228124..ded4ccd43 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -561,19 +561,19 @@ const char kOptionBlinkOff[] PROGMEM = "BLINKOFF|" D_BLINKOFF ; // xdrv_02_webserver.ino #ifdef USE_WEBSERVER -const char HTTP_SNS_TEMP[] PROGMEM = "%s{s}%s " D_TEMPERATURE "{m}%s°%c{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_HUM[] PROGMEM = "%s{s}%s " D_HUMIDITY "{m}%s%%{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_PRESSURE[] PROGMEM = "%s{s}%s " D_PRESSURE "{m}%s %s{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_ANALOG[] PROGMEM = "%s{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_TEMP[] PROGMEM = "{s}%s " D_TEMPERATURE "{m}%s°%c{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_HUM[] PROGMEM = "{s}%s " D_HUMIDITY "{m}%s%%{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_PRESSURE[] PROGMEM = "{s}%s " D_PRESSURE "{m}%s %s{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_ANALOG[] PROGMEM = "{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = #if defined(USE_MHZ19) || defined(USE_SENSEAIR) || defined(USE_AZ7798) || defined(USE_SCD30) -const char HTTP_SNS_CO2[] PROGMEM = "%s{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_CO2[] PROGMEM = "{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = #endif // USE_MHZ19 #if defined(USE_SCD30) -const char HTTP_SNS_CO2EAVG[] PROGMEM = "%s{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_CO2EAVG[] PROGMEM = "{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = #endif // USE_SCD30 const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 6c44f54fd..635a1017a 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -252,7 +252,7 @@ enum LightSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MA enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, - FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_COMMAND_SENSOR, FUNC_COMMAND_DRIVER, + FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_SENSOR, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_COMMAND_SENSOR, FUNC_COMMAND_DRIVER, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR, FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED, diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 0e9c322ac..7a5dac4cc 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06050000 +#define VERSION 0x06050001 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 415d14e53..ec017810f 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -629,13 +629,9 @@ void WSContentFlush() } } -void WSContentSend_P(const char* formatP, ...) // Content send snprintf_P char data +void _WSContentSendBuffer(void) { - // This uses char strings. Be aware of sending %% if % is needed - va_list arg; - va_start(arg, formatP); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); - va_end(arg); + int len = strlen(mqtt_data); if (0 == len) { // No content return; @@ -656,6 +652,36 @@ void WSContentSend_P(const char* formatP, ...) // Content send snprintf_P ch } } +void WSContentSend_P(const char* formatP, ...) // Content send snprintf_P char data +{ + // This uses char strings. Be aware of sending %% if % is needed + va_list arg; + va_start(arg, formatP); + vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); + va_end(arg); + + _WSContentSendBuffer(); +} + +void WSContentSend_PD(const char* formatP, ...) // Content send snprintf_P char data checked for decimal separator +{ + // This uses char strings. Be aware of sending %% if % is needed + va_list arg; + va_start(arg, formatP); + int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); + va_end(arg); + + if (D_DECIMAL_SEPARATOR[0] != '.') { + for (uint16_t i = 0; i < strlen(mqtt_data); i++) { + if ('.' == mqtt_data[i]) { + mqtt_data[i] = D_DECIMAL_SEPARATOR[0]; + } + } + } + + _WSContentSendBuffer(); +} + void WSContentStart_P(const char* title, bool auth) { if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) { @@ -940,20 +966,11 @@ bool HandleRootStatusRefresh(void) ExecuteWebCommand(svalue, SRC_WEBGUI); } - mqtt_data[0] = '\0'; - XsnsCall(FUNC_WEB_APPEND); - if (D_DECIMAL_SEPARATOR[0] != '.') { - for (uint16_t i = 0; i < strlen(mqtt_data); i++) { - if ('.' == mqtt_data[i]) { - mqtt_data[i] = D_DECIMAL_SEPARATOR[0]; - } - } - } - char stemp[strlen(mqtt_data) +1]; - memcpy(stemp, mqtt_data, sizeof(stemp)); - WSContentBegin(200, CT_HTML); - WSContentSend_P(PSTR("{t}%s"), stemp); + WSContentSend_P(PSTR("{t}")); + XsnsCall(FUNC_WEB_SENSOR); + WSContentSend_P(PSTR("")); + if (devices_present) { WSContentSend_P(PSTR("{t}")); uint8_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32; diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 10814bd65..b2393a311 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -548,20 +548,20 @@ void EnergySnsInit(void) } #ifdef USE_WEBSERVER -const char HTTP_ENERGY_SNS1[] PROGMEM = "%s" +const char HTTP_ENERGY_SNS1[] PROGMEM = "{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" "{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" "{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; -const char HTTP_ENERGY_SNS2[] PROGMEM = "%s" +const char HTTP_ENERGY_SNS2[] PROGMEM = "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" "{s}" D_POWER_FACTOR "{m}%s{e}"; -const char HTTP_ENERGY_SNS3[] PROGMEM = "%s" +const char HTTP_ENERGY_SNS3[] PROGMEM = "{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"; -const char HTTP_ENERGY_SNS4[] PROGMEM = "%s" +const char HTTP_ENERGY_SNS4[] PROGMEM = "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; // {s} = , {m} = , {e} = @@ -666,12 +666,12 @@ void EnergyShow(bool json) #endif // USE_KNX #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS1, mqtt_data, voltage_chr, current_chr, active_power_chr); + WSContentSend_PD(HTTP_ENERGY_SNS1, voltage_chr, current_chr, active_power_chr); if (!energy_type_dc) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS2, mqtt_data, apparent_power_chr, reactive_power_chr, power_factor_chr); - if (!isnan(energy_frequency)) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS3, mqtt_data, frequency_chr); } + WSContentSend_PD(HTTP_ENERGY_SNS2, apparent_power_chr, reactive_power_chr, power_factor_chr); + if (!isnan(energy_frequency)) { WSContentSend_PD(HTTP_ENERGY_SNS3, frequency_chr); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS4, mqtt_data, energy_daily_chr, energy_yesterday_chr, energy_total_chr); + WSContentSend_PD(HTTP_ENERGY_SNS4, energy_daily_chr, energy_yesterday_chr, energy_total_chr); #endif // USE_WEBSERVER } } @@ -722,7 +722,7 @@ bool Xsns03(uint8_t function) EnergyShow(true); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: EnergyShow(false); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index cfa797030..901793fec 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -86,7 +86,7 @@ void CounterInit(void) #ifdef USE_WEBSERVER const char HTTP_SNS_COUNTER[] PROGMEM = - "%s{s}" D_COUNTER "%d{m}%s%s{e}"; // {s} = , {m} = , {e} = + "{s}" D_COUNTER "%d{m}%s%s{e}"; // {s} = , {m} = , {e} = #endif // USE_WEBSERVER void CounterShow(bool json) @@ -121,7 +121,7 @@ void CounterShow(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_COUNTER, mqtt_data, i +1, counter, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : ""); + WSContentSend_PD(HTTP_SNS_COUNTER, i +1, counter, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : ""); #endif // USE_WEBSERVER } } @@ -152,7 +152,7 @@ bool Xsns01(uint8_t function) CounterShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: CounterShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_02_analog.ino b/sonoff/xsns_02_analog.ino index e75160697..79a622f0f 100644 --- a/sonoff/xsns_02_analog.ino +++ b/sonoff/xsns_02_analog.ino @@ -58,7 +58,7 @@ void AdcShow(bool json) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ANALOG\":{\"A0\":%d}"), mqtt_data, analog); #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "", 0, analog); + WSContentSend_PD(HTTP_SNS_ANALOG, "", 0, analog); #endif // USE_WEBSERVER } } @@ -82,7 +82,7 @@ bool Xsns02(uint8_t function) AdcShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: AdcShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index f4880a308..98d1f6276 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -105,7 +105,7 @@ void SonoffScSerialInput(char *rcvstat) #ifdef USE_WEBSERVER const char HTTP_SNS_SCPLUS[] PROGMEM = - "%s{s}" D_LIGHT "{m}%d%%{e}{s}" D_NOISE "{m}%d%%{e}{s}" D_AIR_QUALITY "{m}%d%%{e}"; // {s} = , {m} = , {e} = + "{s}" D_LIGHT "{m}%d%%{e}{s}" D_NOISE "{m}%d%%{e}{s}" D_AIR_QUALITY "{m}%d%%{e}"; // {s} = , {m} = , {e} = #endif // USE_WEBSERVER void SonoffScShow(bool json) @@ -140,9 +140,9 @@ void SonoffScShow(bool json) #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "", temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, "", humidity); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SCPLUS, mqtt_data, sc_value[2], sc_value[3], sc_value[4]); + WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, "", humidity); + WSContentSend_PD(HTTP_SNS_SCPLUS, sc_value[2], sc_value[3], sc_value[4]); #endif // USE_WEBSERVER } } @@ -165,7 +165,7 @@ bool Xsns04(uint8_t function) SonoffScShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: SonoffScShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index f5d4bd03d..9e82a8e9b 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -218,7 +218,7 @@ void Ds18b20Show(bool json) #endif // USE_KNX #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, ds18b20_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_TEMP, ds18b20_types, temperature, TempUnit()); #endif // USE_WEBSERVER } } @@ -241,7 +241,7 @@ bool Xsns05(uint8_t function) Ds18b20Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Ds18b20Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index 521fdeaa8..e2ff0767c 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -452,7 +452,7 @@ void Ds18x20Show(bool json) #endif // USE_KNX #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, ds18x20_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_TEMP, ds18x20_types, temperature, TempUnit()); #endif // USE_WEBSERVER } } @@ -479,7 +479,7 @@ bool Xsns05(uint8_t function) Ds18x20Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Ds18x20Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index cb07bf63c..2b157cfb7 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -198,7 +198,7 @@ void Ds18x20Show(bool json) #ifdef USE_WEBSERVER } else { snprintf_P(stemp, sizeof(stemp), PSTR("%s-%d"), ds18x20_types, i +1); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, stemp, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_TEMP, stemp, temperature, TempUnit()); #endif // USE_WEBSERVER } } @@ -233,7 +233,7 @@ bool Xsns05(uint8_t function) Ds18x20Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Ds18x20Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index e6d8d7328..016f012f0 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -227,8 +227,8 @@ void DhtShow(bool json) #endif // USE_KNX #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, Dht[i].stype, temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, Dht[i].stype, humidity); + WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); #endif // USE_WEBSERVER } } @@ -254,7 +254,7 @@ bool Xsns06(uint8_t function) DhtShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: DhtShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index 51351bdf5..0967560b1 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -208,8 +208,8 @@ void ShtShow(bool json) #endif // USE_KNX #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sht_types, temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, sht_types, humidity); + WSContentSend_PD(HTTP_SNS_TEMP, sht_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, sht_types, humidity); #endif // USE_WEBSERVER } } @@ -236,7 +236,7 @@ bool Xsns07(uint8_t function) ShtShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: ShtShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index 8ce9657ea..1ef208d61 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -268,8 +268,8 @@ void HtuShow(bool json) #endif // USE_KNX #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, htu_types, temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, htu_types, humidity); + WSContentSend_PD(HTTP_SNS_TEMP, htu_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, htu_types, humidity); #endif // USE_WEBSERVER } } @@ -295,7 +295,7 @@ bool Xsns08(uint8_t function) HtuShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: HtuShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index 488efd7ee..22b0cd365 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -597,19 +597,20 @@ void BmpShow(bool json) #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, name, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_TEMP, name, temperature, TempUnit()); if (bmp_sensors[bmp_idx].bmp_model >= 2) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, name, humidity); + WSContentSend_PD(HTTP_SNS_HUM, name, humidity); } - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_PRESSURE, mqtt_data, name, pressure, PressureUnit().c_str()); + WSContentSend_PD(HTTP_SNS_PRESSURE, name, pressure, PressureUnit().c_str()); if (Settings.altitude != 0) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SEAPRESSURE, mqtt_data, name, sea_pressure, PressureUnit().c_str()); + WSContentSend_PD(HTTP_SNS_SEAPRESSURE, name, sea_pressure, PressureUnit().c_str()); } #ifdef USE_BME680 if (bmp_sensors[bmp_idx].bmp_model >= 3) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{s}%s " D_GAS "{m}%s " D_UNIT_KILOOHM "{e}"), mqtt_data, name, gas_resistance); + WSContentSend_PD(PSTR("{s}%s " D_GAS "{m}%s " D_UNIT_KILOOHM "{e}"), name, gas_resistance); } #endif // USE_BME680 + #endif // USE_WEBSERVER } } @@ -636,7 +637,7 @@ bool Xsns09(uint8_t function) BmpShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: BmpShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_10_bh1750.ino b/sonoff/xsns_10_bh1750.ino index 95abc41c5..d4ffa3a10 100644 --- a/sonoff/xsns_10_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -100,7 +100,7 @@ void Bh1750Show(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE, mqtt_data, bh1750_types, bh1750_illuminance); + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); #endif // USE_WEBSERVER } } @@ -126,7 +126,7 @@ bool Xsns10(uint8_t function) Bh1750Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Bh1750Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index c32fc090f..2222cc335 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -256,11 +256,11 @@ double Veml6070UvPower(double uvrisk) #ifdef USE_WEBSERVER // {s} = , {m} = , {e} = #ifdef USE_VEML6070_SHOW_RAW - const char HTTP_SNS_UV_LEVEL[] PROGMEM = "%s{s}VEML6070 " D_UV_LEVEL "{m}%s " D_UNIT_INCREMENTS "{e}"; + const char HTTP_SNS_UV_LEVEL[] PROGMEM = "{s}VEML6070 " D_UV_LEVEL "{m}%s " D_UNIT_INCREMENTS "{e}"; #endif // USE_VEML6070_SHOW_RAW // different uv index level texts - const char HTTP_SNS_UV_INDEX[] PROGMEM = "%s{s}VEML6070 " D_UV_INDEX " {m}%s %s{e}"; - const char HTTP_SNS_UV_POWER[] PROGMEM = "%s{s}VEML6070 " D_UV_POWER "{m}%s " D_UNIT_WATT_METER_QUADRAT "{e}"; + const char HTTP_SNS_UV_INDEX[] PROGMEM = "{s}VEML6070 " D_UV_INDEX "{m}%s %s{e}"; + const char HTTP_SNS_UV_POWER[] PROGMEM = "{s}VEML6070 " D_UV_POWER "{m}%s " D_UNIT_WATT_METER_QUADRAT "{e}"; #endif // USE_WEBSERVER /********************************************************************************************/ @@ -289,10 +289,10 @@ void Veml6070Show(bool json) #ifdef USE_WEBSERVER } else { #ifdef USE_VEML6070_SHOW_RAW - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_LEVEL, mqtt_data, str_uvlevel); + WSContentSend_PD(HTTP_SNS_UV_LEVEL, str_uvlevel); #endif // USE_VEML6070_SHOW_RAW - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_INDEX, mqtt_data, str_uvrisk, str_uvrisk_text); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_UV_POWER, mqtt_data, str_uvpower); + WSContentSend_PD(HTTP_SNS_UV_INDEX, str_uvrisk, str_uvrisk_text); + WSContentSend_PD(HTTP_SNS_UV_POWER, str_uvpower); #endif // USE_WEBSERVER } } @@ -310,7 +310,7 @@ bool Xsns11(uint8_t function) switch (function) { case FUNC_INIT: Veml6070Detect(); // 1[ms], detect and init the sensor - Veml6070UvTableInit(); // 1[ms], initalize the UV compare table only once + Veml6070UvTableInit(); // 1[ms], initalize the UV compare table only once break; case FUNC_EVERY_SECOND: Veml6070EverySecond(); // 10..15[ms], tested with OLED display, do all the actions needed to get all sensor values @@ -319,7 +319,7 @@ bool Xsns11(uint8_t function) Veml6070Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Veml6070Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index a8f0d8531..7c674debe 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -203,7 +203,7 @@ void Ads1115toString(uint8_t address) snprintf_P(label, sizeof(label), "ADS1115(%02x)", address); for (uint8_t i = 0; i < 4; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, label, i, ads1115_values[i]); + WSContentSend_PD(HTTP_SNS_ANALOG, label, i, ads1115_values[i]); } } @@ -255,7 +255,7 @@ bool Xsns12(uint8_t function) Ads1115Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Ads1115Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/sonoff/xsns_12_ads1115_i2cdev.ino index f73581ec0..855658647 100644 --- a/sonoff/xsns_12_ads1115_i2cdev.ino +++ b/sonoff/xsns_12_ads1115_i2cdev.ino @@ -115,7 +115,7 @@ void Ads1115Show(bool json) strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value); + WSContentSend_PD(HTTP_SNS_ANALOG, "ADS1115", i, adc_value); #endif // USE_WEBSERVER } } @@ -144,7 +144,7 @@ bool Xsns12(uint8_t function) Ads1115Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Ads1115Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index 88f6ce240..fa6327f70 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -222,7 +222,7 @@ void Ina219EverySecond(void) } #ifdef USE_WEBSERVER -const char HTTP_SNS_INA219_DATA[] PROGMEM = "%s" +const char HTTP_SNS_INA219_DATA[] PROGMEM = "{s}INA219 " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" "{s}INA219 " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" "{s}INA219 " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; @@ -250,7 +250,7 @@ void Ina219Show(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_INA219_DATA, mqtt_data, voltage, current, power); + WSContentSend_PD(HTTP_SNS_INA219_DATA, voltage, current, power); #endif // USE_WEBSERVER } } @@ -281,7 +281,7 @@ bool Xsns13(uint8_t function) Ina219Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Ina219Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_14_sht3x.ino b/sonoff/xsns_14_sht3x.ino index fcb7f4a22..e7aa63007 100755 --- a/sonoff/xsns_14_sht3x.ino +++ b/sonoff/xsns_14_sht3x.ino @@ -126,8 +126,8 @@ void Sht3xShow(bool json) #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, types, temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, types, humidity); + WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, types, humidity); #endif // USE_WEBSERVER } } @@ -152,7 +152,7 @@ bool Xsns14(uint8_t function) Sht3xShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Sht3xShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 1e21aa6fb..058336f39 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -351,8 +351,8 @@ void MhzShow(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CO2, mqtt_data, types, mhz_last_ppm); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_CO2, types, mhz_last_ppm); + WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); #endif // USE_WEBSERVER } } @@ -382,7 +382,7 @@ bool Xsns15(uint8_t function) MhzShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: MhzShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index 688cdf419..74f9fb0fb 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -95,7 +95,7 @@ void Tsl2561EverySecond(void) #ifdef USE_WEBSERVER const char HTTP_SNS_TSL2561[] PROGMEM = - "%s{s}TSL2561 " D_ILLUMINANCE "{m}%u.%03u " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = + "{s}TSL2561 " D_ILLUMINANCE "{m}%u.%03u " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = #endif // USE_WEBSERVER void Tsl2561Show(bool json) @@ -109,7 +109,7 @@ void Tsl2561Show(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TSL2561, mqtt_data, tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); + WSContentSend_PD(HTTP_SNS_TSL2561, tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); #endif // USE_WEBSERVER } } @@ -135,7 +135,7 @@ bool Xsns16(uint8_t function) Tsl2561Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Tsl2561Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_17_senseair.ino b/sonoff/xsns_17_senseair.ino index 461b41145..b5772a4d1 100644 --- a/sonoff/xsns_17_senseair.ino +++ b/sonoff/xsns_17_senseair.ino @@ -159,10 +159,10 @@ void SenseairShow(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CO2, mqtt_data, senseair_types, senseair_co2); + WSContentSend_PD(HTTP_SNS_CO2, senseair_types, senseair_co2); if (senseair_type != 2) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, senseair_types, temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, senseair_types, humidity); + WSContentSend_PD(HTTP_SNS_TEMP, senseair_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, senseair_types, humidity); } #endif // USE_WEBSERVER } @@ -188,7 +188,7 @@ bool Xsns17(uint8_t function) SenseairShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: SenseairShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_18_pms5003.ino b/sonoff/xsns_18_pms5003.ino index 82959ff88..6f9c97711 100644 --- a/sonoff/xsns_18_pms5003.ino +++ b/sonoff/xsns_18_pms5003.ino @@ -113,7 +113,7 @@ void PmsInit(void) } #ifdef USE_WEBSERVER -const char HTTP_PMS5003_SNS[] PROGMEM = "%s" +const char HTTP_PMS5003_SNS[] PROGMEM = // "{s}PMS5003 " D_STANDARD_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" // "{s}PMS5003 " D_STANDARD_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" // "{s}PMS5003 " D_STANDARD_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" @@ -145,7 +145,7 @@ void PmsShow(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_PMS5003_SNS, mqtt_data, + WSContentSend_PD(HTTP_PMS5003_SNS, // pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); @@ -174,7 +174,7 @@ bool Xsns18(uint8_t function) PmsShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: PmsShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_19_mgs.ino b/sonoff/xsns_19_mgs.ino index dacd1430e..942664b96 100644 --- a/sonoff/xsns_19_mgs.ino +++ b/sonoff/xsns_19_mgs.ino @@ -57,7 +57,7 @@ char* measure_gas(int gas_type, char* buffer) } #ifdef USE_WEBSERVER -const char HTTP_MGS_GAS[] PROGMEM = "%s{s}MGS %s{m}%s " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = +const char HTTP_MGS_GAS[] PROGMEM = "{s}MGS %s{m}%s " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = #endif // USE_WEBSERVER void MGSShow(bool json) @@ -74,14 +74,14 @@ void MGSShow(bool json) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"C2H5OH\":%s}"), mqtt_data, measure_gas(C2H5OH, buffer)); #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGS_GAS, mqtt_data, "NH3", measure_gas(NH3, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGS_GAS, mqtt_data, "CO", measure_gas(CO, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGS_GAS, mqtt_data, "NO2", measure_gas(NO2, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGS_GAS, mqtt_data, "C3H8", measure_gas(C3H8, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGS_GAS, mqtt_data, "C4H10", measure_gas(C4H10, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGS_GAS, mqtt_data, "CH4", measure_gas(GAS_CH4, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGS_GAS, mqtt_data, "H2", measure_gas(H2, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGS_GAS, mqtt_data, "C2H5OH", measure_gas(C2H5OH, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "NH3", measure_gas(NH3, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "CO", measure_gas(CO, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "NO2", measure_gas(NO2, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "C3H8", measure_gas(C3H8, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "C4H10", measure_gas(C4H10, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "CH4", measure_gas(GAS_CH4, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "H2", measure_gas(H2, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "C2H5OH", measure_gas(C2H5OH, buffer)); #endif // USE_WEBSERVER } } @@ -107,7 +107,7 @@ bool Xsns19(uint8_t function) if (detected) MGSShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: if (detected) MGSShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index d40301508..702d3d8fe 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -180,7 +180,7 @@ void NovaSdsInit(void) } #ifdef USE_WEBSERVER -const char HTTP_SDS0X1_SNS[] PROGMEM = "%s" +const char HTTP_SDS0X1_SNS[] PROGMEM = "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; // {s} = , {m} = , {e} = #endif // USE_WEBSERVER @@ -204,7 +204,7 @@ void NovaSdsShow(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SDS0X1_SNS, mqtt_data, pm2_5, pm10); + WSContentSend_PD(HTTP_SDS0X1_SNS, pm2_5, pm10); #endif // USE_WEBSERVER } } @@ -230,7 +230,7 @@ bool Xsns20(uint8_t function) NovaSdsShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: NovaSdsShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_21_sgp30.ino b/sonoff/xsns_21_sgp30.ino index 48fde6793..a544e4472 100644 --- a/sonoff/xsns_21_sgp30.ino +++ b/sonoff/xsns_21_sgp30.ino @@ -63,7 +63,7 @@ void Sgp30Update(void) // Perform every second to ensure proper operation of th } } -const char HTTP_SNS_SGP30[] PROGMEM = "%s" +const char HTTP_SNS_SGP30[] PROGMEM = "{s}SGP30 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" // {s} = , {m} = , {e} = "{s}SGP30 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; @@ -77,7 +77,7 @@ void Sgp30Show(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SGP30, mqtt_data, sgp.eCO2, sgp.TVOC); + WSContentSend_PD(HTTP_SNS_SGP30, sgp.eCO2, sgp.TVOC); #endif } } @@ -100,7 +100,7 @@ bool Xsns21(uint8_t function) Sgp30Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Sgp30Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index a52898728..3c8a933bf 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -45,7 +45,7 @@ void Sr04Init(void) #ifdef USE_WEBSERVER const char HTTP_SNS_DISTANCE[] PROGMEM = - "%s{s}SR04 " D_DISTANCE "{m}%s" D_UNIT_CENTIMETER "{e}"; // {s} = , {m} = , {e} = + "{s}SR04 " D_DISTANCE "{m}%s" D_UNIT_CENTIMETER "{e}"; // {s} = , {m} = , {e} = #endif // USE_WEBSERVER void Sr04Show(bool json) @@ -65,7 +65,7 @@ void Sr04Show(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_DISTANCE, mqtt_data, distance_chr); + WSContentSend_PD(HTTP_SNS_DISTANCE, distance_chr); #endif // USE_WEBSERVER } } @@ -88,7 +88,7 @@ bool Xsns22(uint8_t function) Sr04Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Sr04Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino index 67971845a..c77ca1875 100644 --- a/sonoff/xsns_23_sdm120.ino +++ b/sonoff/xsns_23_sdm120.ino @@ -260,7 +260,7 @@ void SDM120Init(void) } #ifdef USE_WEBSERVER -const char HTTP_SNS_SDM120_DATA[] PROGMEM = "%s" +const char HTTP_SNS_SDM120_DATA[] PROGMEM = "{s}SDM120 " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" "{s}SDM120 " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" "{s}SDM120 " D_POWERUSAGE_ACTIVE "{m}%s " D_UNIT_WATT "{e}" @@ -330,9 +330,9 @@ void SDM120Show(bool json) #ifdef USE_WEBSERVER } else { #ifdef USE_SDM220 - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SDM120_DATA, mqtt_data, voltage, current, active_power, apparent_power, reactive_power, power_factor, frequency, energy_total, phase_angle,import_active,export_active,import_reactive,export_reactive,total_reactive); + WSContentSend_PD(HTTP_SNS_SDM120_DATA, voltage, current, active_power, apparent_power, reactive_power, power_factor, frequency, energy_total, phase_angle,import_active,export_active,import_reactive,export_reactive,total_reactive); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SDM120_DATA, mqtt_data, voltage, current, active_power, apparent_power, reactive_power, power_factor, frequency, energy_total); + WSContentSend_PD(HTTP_SNS_SDM120_DATA, voltage, current, active_power, apparent_power, reactive_power, power_factor, frequency, energy_total); #endif // USE_SDM220 #endif // USE_WEBSERVER } @@ -358,7 +358,7 @@ bool Xsns23(uint8_t function) SDM120Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: SDM120Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_24_si1145.ino b/sonoff/xsns_24_si1145.ino index 19855bf42..56bce1018 100644 --- a/sonoff/xsns_24_si1145.ino +++ b/sonoff/xsns_24_si1145.ino @@ -316,7 +316,7 @@ void Si1145Update(void) } #ifdef USE_WEBSERVER -const char HTTP_SNS_SI1145[] PROGMEM = "%s" +const char HTTP_SNS_SI1145[] PROGMEM = "{s}SI1145 " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}" // {s} = , {m} = , {e} = "{s}SI1145 " D_INFRARED "{m}%d " D_UNIT_LUX "{e}" "{s}SI1145 " D_UV_INDEX "{m}%d.%d{e}"; @@ -336,7 +336,7 @@ void Si1145Show(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SI1145, mqtt_data, visible, infrared, uvindex /100, uvindex %100); + WSContentSend_PD(HTTP_SNS_SI1145, visible, infrared, uvindex /100, uvindex %100); #endif } } else { @@ -361,7 +361,7 @@ bool Xsns24(uint8_t function) Si1145Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Si1145Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_25_sdm630.ino b/sonoff/xsns_25_sdm630.ino index 2f8e0acd8..013964915 100644 --- a/sonoff/xsns_25_sdm630.ino +++ b/sonoff/xsns_25_sdm630.ino @@ -257,7 +257,7 @@ void SDM630Init(void) } #ifdef USE_WEBSERVER -const char HTTP_SNS_SDM630_DATA[] PROGMEM = "%s" +const char HTTP_SNS_SDM630_DATA[] PROGMEM = "{s}SDM630 " D_VOLTAGE "{m}%s/%s/%s " D_UNIT_VOLT "{e}" "{s}SDM630 " D_CURRENT "{m}%s/%s/%s " D_UNIT_AMPERE "{e}" "{s}SDM630 " D_POWERUSAGE_ACTIVE "{m}%s/%s/%s " D_UNIT_WATT "{e}" @@ -312,7 +312,7 @@ void SDM630Show(bool json) current_l1, current_l2, current_l3); #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SDM630_DATA, mqtt_data, + WSContentSend_PD(HTTP_SNS_SDM630_DATA, voltage_l1, voltage_l2, voltage_l3, current_l1, current_l2, current_l3, active_power_l1, active_power_l2, active_power_l3, reactive_power_l1, reactive_power_l2, reactive_power_l3, @@ -341,7 +341,7 @@ bool Xsns25(uint8_t function) SDM630Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: SDM630Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_26_lm75ad.ino b/sonoff/xsns_26_lm75ad.ino index 8a48327bf..b7b92fca7 100644 --- a/sonoff/xsns_26_lm75ad.ino +++ b/sonoff/xsns_26_lm75ad.ino @@ -91,7 +91,7 @@ void LM75ADShow(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "LM75AD", temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_TEMP, "LM75AD", temperature, TempUnit()); #endif // USE_WEBSERVER } } @@ -114,7 +114,7 @@ bool Xsns26(uint8_t function) LM75ADShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: LM75ADShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_27_apds9960.ino b/sonoff/xsns_27_apds9960.ino index 765c89263..5be8b0e5b 100644 --- a/sonoff/xsns_27_apds9960.ino +++ b/sonoff/xsns_27_apds9960.ino @@ -77,7 +77,7 @@ volatile uint8_t recovery_loop_counter = 0; //count number of stateloops to swi bool APDS9960_overload = false; #ifdef USE_WEBSERVER -const char HTTP_APDS_9960_SNS[] PROGMEM = "%s" +const char HTTP_APDS_9960_SNS[] PROGMEM = "{s}" "Red" "{m}%s{e}" "{s}" "Green" "{m}%s{e}" "{s}" "Blue" "{m}%s{e}" @@ -1963,7 +1963,7 @@ void APDS9960_show(bool json) mqtt_data, APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_APDS_9960_SNS, mqtt_data, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr ); + WSContentSend_PD(HTTP_APDS_9960_SNS, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr ); #endif // USE_WEBSERVER } } @@ -2055,7 +2055,7 @@ bool Xsns27(uint8_t function) APDS9960_show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: APDS9960_show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_28_tm1638.ino b/sonoff/xsns_28_tm1638.ino index 590432dfd..05e756966 100644 --- a/sonoff/xsns_28_tm1638.ino +++ b/sonoff/xsns_28_tm1638.ino @@ -215,7 +215,7 @@ bool Xsns28(uint8_t function) TmShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: TmShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index d7aaaf2ef..5aa4992dd 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -694,7 +694,7 @@ bool MCP230xx_Command(void) { #ifdef USE_MCP230xx_DISPLAYOUTPUT -const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "%s{s}MCP230XX D%d{m}%s{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "{s}MCP230XX D%d{m}%s{e}"; // {s} = , {m} = , {e} = void MCP230xx_UpdateWebData(void) { uint8_t gpio1 = MCP230xx_readGPIO(0); @@ -707,7 +707,7 @@ void MCP230xx_UpdateWebData(void) { if (Settings.mcp230xx_config[pin].pinmode >= 5) { char stt[7]; sprintf(stt,ConvertNumTxt((gpio>>pin)&1,Settings.mcp230xx_config[pin].pinmode)); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_MCP230xx_OUTPUT, mqtt_data, pin, stt); + WSContentSend_PD(HTTP_SNS_MCP230xx_OUTPUT, pin, stt); } } } @@ -822,7 +822,7 @@ bool Xsns29(uint8_t function) #ifdef USE_WEBSERVER #ifdef USE_MCP230xx_OUTPUT #ifdef USE_MCP230xx_DISPLAYOUTPUT - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: MCP230xx_UpdateWebData(); break; #endif // USE_MCP230xx_DISPLAYOUTPUT diff --git a/sonoff/xsns_30_mpr121.ino b/sonoff/xsns_30_mpr121.ino index 01431faa6..10ea46078 100644 --- a/sonoff/xsns_30_mpr121.ino +++ b/sonoff/xsns_30_mpr121.ino @@ -356,8 +356,8 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) } // Add buttons to web string #ifdef USE_WEBSERVER - if (FUNC_WEB_APPEND == function) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{s}MPR121%c Button%d{m}%d{e}"), mqtt_data, pS->id[i], j, BITC(i, j)); + if (FUNC_WEB_SENSOR == function) { + WSContentSend_PD(PSTR("{s}MPR121%c Button%d{m}%d{e}"), pS->id[i], j, BITC(i, j)); } #endif // USE_WEBSERVER @@ -389,7 +389,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) * FUNC_INIT to initialize a driver, * FUNC_EVERY_50_MSECOND for near real-time operation, * FUNC_JSON_APPEND for telemetry data and - * FUNC_WEB_APPEND for displaying data in the Tasmota web-interface + * FUNC_WEB_SENSOR for displaying data in the Tasmota web-interface * * @param byte function Tasmota function ID. * @return bool ??? @@ -426,8 +426,8 @@ bool Xsns30(uint8_t function) #ifdef USE_WEBSERVER // Show sensor data on main web page - case FUNC_WEB_APPEND: - Mpr121Show(&mpr121, FUNC_WEB_APPEND); + case FUNC_WEB_SENSOR: + Mpr121Show(&mpr121, FUNC_WEB_SENSOR); break; #endif // USE_WEBSERVER } diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index 173cbe388..9ce63b228 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -77,7 +77,7 @@ void CCS811Update(void) // Perform every n second } } -const char HTTP_SNS_CCS811[] PROGMEM = "%s" +const char HTTP_SNS_CCS811[] PROGMEM = "{s}CCS811 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" // {s} = , {m} = , {e} = "{s}CCS811 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; @@ -91,7 +91,7 @@ void CCS811Show(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CCS811, mqtt_data, eCO2, TVOC); + WSContentSend_PD(HTTP_SNS_CCS811, eCO2, TVOC); #endif } } @@ -114,7 +114,7 @@ bool Xsns31(uint8_t function) CCS811Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: CCS811Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index 61156f9c1..e7dddd953 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -155,12 +155,13 @@ void MPU_6050Detect(void) } #ifdef USE_WEBSERVER -const char HTTP_SNS_AX_AXIS[] PROGMEM = "%s{s}%s " D_AX_AXIS "{m}%s{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_AY_AXIS[] PROGMEM = "%s{s}%s " D_AY_AXIS "{m}%s{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_AZ_AXIS[] PROGMEM = "%s{s}%s " D_AZ_AXIS "{m}%s{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_GX_AXIS[] PROGMEM = "%s{s}%s " D_GX_AXIS "{m}%s{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_GY_AXIS[] PROGMEM = "%s{s}%s " D_GY_AXIS "{m}%s{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_GZ_AXIS[] PROGMEM = "%s{s}%s " D_GZ_AXIS "{m}%s{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_AXIS[] PROGMEM = + "{s}" D_SENSOR_MPU6050 " " D_AX_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = + "{s}" D_SENSOR_MPU6050 " " D_AY_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = + "{s}" D_SENSOR_MPU6050 " " D_AZ_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = + "{s}" D_SENSOR_MPU6050 " " D_GX_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = + "{s}" D_SENSOR_MPU6050 " " D_GY_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = + "{s}" D_SENSOR_MPU6050 " " D_GZ_AXIS "{m}%s{e}"; // {s} = , {m} = , {e} = #endif // USE_WEBSERVER #define D_JSON_AXIS_AX "AccelXAxis" @@ -211,13 +212,8 @@ void MPU_6050Show(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, D_SENSOR_MPU6050, temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_AX_AXIS, mqtt_data, D_SENSOR_MPU6050, axis_ax); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_AY_AXIS, mqtt_data, D_SENSOR_MPU6050, axis_ay); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_AZ_AXIS, mqtt_data, D_SENSOR_MPU6050, axis_az); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GX_AXIS, mqtt_data, D_SENSOR_MPU6050, axis_gx); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GY_AXIS, mqtt_data, D_SENSOR_MPU6050, axis_gy); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GZ_AXIS, mqtt_data, D_SENSOR_MPU6050, axis_gz); + WSContentSend_PD(HTTP_SNS_TEMP, D_SENSOR_MPU6050, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_AXIS, axis_ax, axis_ay, axis_az, axis_gx, axis_gy, axis_gz); #endif // USE_WEBSERVER } } @@ -245,7 +241,7 @@ bool Xsns32(uint8_t function) MPU_6050Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: MPU_6050Show(0); MPU_6050PerformReading(); break; diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index c287ef3f4..568936db1 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -321,11 +321,11 @@ void HxEvery100mSecond(void) } #ifdef USE_WEBSERVER -const char HTTP_HX711_WEIGHT[] PROGMEM = "%s" +const char HTTP_HX711_WEIGHT[] PROGMEM = "{s}HX711 " D_WEIGHT "{m}%s " D_UNIT_KILOGRAM "{e}"; // {s} = , {m} = , {e} = -const char HTTP_HX711_COUNT[] PROGMEM = "%s" +const char HTTP_HX711_COUNT[] PROGMEM = "{s}HX711 " D_COUNT "{m}%d{e}"; -const char HTTP_HX711_CAL[] PROGMEM = "%s" +const char HTTP_HX711_CAL[] PROGMEM = "{s}HX711 %s{m}{e}"; #endif // USE_WEBSERVER @@ -351,13 +351,13 @@ void HxShow(bool json) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s}"), mqtt_data, weight_chr, scount); #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_HX711_WEIGHT, mqtt_data, weight_chr); + WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr); if (count > 1) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_HX711_COUNT, mqtt_data, count); + WSContentSend_PD(HTTP_HX711_COUNT, count); } if (hx_calibrate_step) { char cal_text[30]; - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_HX711_CAL, mqtt_data, GetTextIndexed(cal_text, sizeof(cal_text), hx_calibrate_msg, kHxCalibrationStates)); + WSContentSend_PD(HTTP_HX711_CAL, GetTextIndexed(cal_text, sizeof(cal_text), hx_calibrate_msg, kHxCalibrationStates)); } #endif // USE_WEBSERVER } @@ -485,7 +485,7 @@ bool Xsns34(uint8_t function) HxShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: HxShow(0); break; #ifdef USE_HX711_GUI diff --git a/sonoff/xsns_35_tx20.ino b/sonoff/xsns_35_tx20.ino index bae2e9532..444c5231d 100644 --- a/sonoff/xsns_35_tx20.ino +++ b/sonoff/xsns_35_tx20.ino @@ -39,7 +39,7 @@ extern "C" { #ifdef USE_WEBSERVER -const char HTTP_SNS_TX20[] PROGMEM = "%s" +const char HTTP_SNS_TX20[] PROGMEM = "{s}TX20 " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" "{s}TX20 " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" "{s}TX20 " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" @@ -186,7 +186,7 @@ void Tx20Show(bool json) mqtt_data, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TX20, mqtt_data, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); + WSContentSend_PD(HTTP_SNS_TX20, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); #endif // USE_WEBSERVER } } @@ -211,7 +211,7 @@ bool Xsns35(uint8_t function) Tx20Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Tx20Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_36_mgc3130.ino b/sonoff/xsns_36_mgc3130.ino index 5c1d2df48..c767c192c 100644 --- a/sonoff/xsns_36_mgc3130.ino +++ b/sonoff/xsns_36_mgc3130.ino @@ -67,7 +67,7 @@ char MGC3130stype[8]; #ifdef USE_WEBSERVER -const char HTTP_MGC_3130_SNS[] PROGMEM = "%s" +const char HTTP_MGC_3130_SNS[] PROGMEM = "{s}" "%s" "{m}%s{e}" "{s}" "HwRev" "{m}%u.%u{e}" "{s}" "loaderVer" "{m}%u.%u{e}" @@ -555,7 +555,7 @@ void MGC3130_show(bool json) } #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGC_3130_SNS, mqtt_data, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform ); + WSContentSend_PD(HTTP_MGC_3130_SNS, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform ); #endif // USE_WEBSERVER } } @@ -622,7 +622,7 @@ bool Xsns36(uint8_t function) MGC3130_show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: MGC3130_show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_37_rfsensor.ino b/sonoff/xsns_37_rfsensor.ino index efb6ded06..7230ae692 100644 --- a/sonoff/xsns_37_rfsensor.ino +++ b/sonoff/xsns_37_rfsensor.ino @@ -287,8 +287,8 @@ void RfSnsTheoV2Show(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sensor, temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE, mqtt_data, sensor, rfsns_theo_v2_t1[i].lux); + WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, sensor, rfsns_theo_v2_t1[i].lux); #endif // USE_WEBSERVER } } @@ -331,8 +331,8 @@ void RfSnsTheoV2Show(bool json) } #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sensor, temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, sensor, humidity); + WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, sensor, humidity); #endif // USE_WEBSERVER } } @@ -539,11 +539,11 @@ uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len) } #ifdef USE_WEBSERVER -const char HTTP_SNS_ALECTOV2[] PROGMEM = "%s" +const char HTTP_SNS_ALECTOV2[] PROGMEM = "{s}" D_ALECTOV2 " " D_RAIN "{m}%s " D_UNIT_MILLIMETER "{e}" "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"; -const char HTTP_SNS_ALECTOV2_WDIR[] PROGMEM = "%s" +const char HTTP_SNS_ALECTOV2_WDIR[] PROGMEM = "{s}" D_ALECTOV2 " " D_TX20_WIND_DIRECTION "{m}%s{e}"; #endif @@ -588,11 +588,11 @@ void RfSnsAlectoV2Show(bool json) } #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, D_ALECTOV2, temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, D_ALECTOV2, humidity); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ALECTOV2, mqtt_data, rain, wind, gust); + WSContentSend_PD(HTTP_SNS_TEMP, D_ALECTOV2, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, D_ALECTOV2, humidity); + WSContentSend_PD(HTTP_SNS_ALECTOV2, rain, wind, gust); if (rfsns_alecto_v2->type) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ALECTOV2_WDIR, mqtt_data, wdir); + WSContentSend_PD(HTTP_SNS_ALECTOV2_WDIR, wdir); } #endif // USE_WEBSERVER } @@ -680,7 +680,7 @@ bool Xsns37(uint8_t function) RfSnsShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: RfSnsShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino index 3ec73085e..953832d6f 100644 --- a/sonoff/xsns_38_az7798.ino +++ b/sonoff/xsns_38_az7798.ino @@ -264,9 +264,9 @@ void AzShow(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CO2, mqtt_data, ktype, az_co2); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, ktype, temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, ktype, humidity); + WSContentSend_PD(HTTP_SNS_CO2, ktype, az_co2); + WSContentSend_PD(HTTP_SNS_TEMP, ktype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, ktype, humidity); #endif // USE_WEBSERVER } } @@ -291,7 +291,7 @@ bool Xsns38(uint8_t function) AzShow(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: AzShow(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_39_max31855.ino b/sonoff/xsns_39_max31855.ino index 10630e171..a6275caa7 100644 --- a/sonoff/xsns_39_max31855.ino +++ b/sonoff/xsns_39_max31855.ino @@ -101,7 +101,7 @@ int32_t MAX31855_ShiftIn(uint8_t Length){ digitalWrite(pin[GPIO_MAX31855CS], LOW); // CS = LOW -> Start SPI communication delayMicroseconds(1); // CS fall to output enable = max. 100ns - + for(uint8_t i = 0; i < Length; i++) { digitalWrite(pin[GPIO_MAX31855CLK], LOW); @@ -115,7 +115,7 @@ int32_t MAX31855_ShiftIn(uint8_t Length){ digitalWrite(pin[GPIO_MAX31855CS], HIGH); // CS = HIGH -> End SPI communication digitalWrite(pin[GPIO_MAX31855CLK], LOW); - return dataIn; + return dataIn; } void MAX31855_Show(bool Json){ @@ -139,7 +139,7 @@ void MAX31855_Show(bool Json){ #endif // USE_KNX } else { #ifdef USE_WEBSERVER - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "MAX31855", probetemp, TempUnit()); + WSContentSend_PD(HTTP_SNS_TEMP, "MAX31855", probetemp, TempUnit()); #endif // USE_WEBSERVER } } @@ -164,7 +164,7 @@ bool Xsns39(uint8_t function) MAX31855_Show(true); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: MAX31855_Show(false); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_41_max44009.ino b/sonoff/xsns_41_max44009.ino index 1cb0e97a7..58a809ed9 100644 --- a/sonoff/xsns_41_max44009.ino +++ b/sonoff/xsns_41_max44009.ino @@ -139,8 +139,7 @@ void Max4409Show(bool json) #ifdef USE_WEBSERVER } else { // show integer value for lx on web-server - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE, - mqtt_data, max44009_types, (int)max44009_illuminance); + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, max44009_types, (int)max44009_illuminance); #endif // USE_WEBSERVER } } @@ -166,7 +165,7 @@ bool Xsns41(uint8_t function) Max4409Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Max4409Show(0); break; #endif // USE_WEBSERVER diff --git a/sonoff/xsns_42_scd30.ino b/sonoff/xsns_42_scd30.ino index c62df4d25..defa01892 100644 --- a/sonoff/xsns_42_scd30.ino +++ b/sonoff/xsns_42_scd30.ino @@ -452,10 +452,10 @@ void Scd30Show(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CO2EAVG, mqtt_data, "SCD30", scd30_CO2EAvg); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CO2, mqtt_data, "SCD30", scd30_CO2); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "SCD30", temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, "SCD30", humidity); + WSContentSend_PD(HTTP_SNS_CO2EAVG, "SCD30", scd30_CO2EAvg); + WSContentSend_PD(HTTP_SNS_CO2, "SCD30", scd30_CO2); + WSContentSend_PD(HTTP_SNS_TEMP, "SCD30", temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, "SCD30", humidity); #endif // USE_WEBSERVER } } @@ -481,7 +481,7 @@ bool Xsns42(byte function) Scd30Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_APPEND: + case FUNC_WEB_SENSOR: Scd30Show(0); break; #endif // USE_WEBSERVER From 83188c926c6a88097fff13dcd7c431315f7b9b1a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Mar 2019 18:02:38 +0100 Subject: [PATCH 1168/2222] Update GUI Update GUI --- sonoff/xdrv_01_webserver.ino | 3 +-- sonoff/xsns_34_hx711.ino | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index ec017810f..48a13fe11 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -376,7 +376,6 @@ const char HTTP_COUNTER[] PROGMEM = "
"; const char HTTP_END[] PROGMEM = - "
" "" "" "" @@ -672,7 +671,7 @@ void WSContentSend_PD(const char* formatP, ...) // Content send snprintf_P ch va_end(arg); if (D_DECIMAL_SEPARATOR[0] != '.') { - for (uint16_t i = 0; i < strlen(mqtt_data); i++) { + for (int i = 0; i < len; i++) { if ('.' == mqtt_data[i]) { mqtt_data[i] = D_DECIMAL_SEPARATOR[0]; } diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 568936db1..272e35a9e 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -374,7 +374,7 @@ void HxShow(bool json) const char S_CONFIGURE_HX711[] PROGMEM = D_CONFIGURE_HX711; const char HTTP_BTN_MENU_MAIN_HX711[] PROGMEM = - "
"; + "

"; const char HTTP_BTN_MENU_HX711[] PROGMEM = "

"; From f4da1d1d869710c83054309c43790e00405b2a36 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 20 Mar 2019 00:57:26 -0300 Subject: [PATCH 1169/2222] Added HASS_STATE to command STATE The command STATE has a secondary mqtt message in the case that SETOPTION59 is 1 This adds a HASS_STATE mqtt message if HomeAssistant discovery is enabled. This is useful for syncing HomeAssistant with all the states of a Tasmota device when HA is restarted. The actual automation for HA explained in the wiki will also make use of this new message. --- sonoff/sonoff.ino | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 51b89031c..d1cf3adb1 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -615,6 +615,11 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (Settings.flag3.hass_tele_on_power) { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); } +#ifdef USE_HOME_ASSISTANT + if (Settings.flag.hass_discovery) { + HAssPublishStatus(); + } +#endif // USE_HOME_ASSISTANT } else if (CMND_SLEEP == command_code) { if ((payload >= 0) && (payload < 251)) { From 878205335ff6af018990f849b8d884941fab5b61 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 20 Mar 2019 14:05:43 +0100 Subject: [PATCH 1170/2222] Consolidate MqttPublishTeleState Consolidate MqttPublishTeleState --- sonoff/sonoff.ino | 19 ++++++++++--------- sonoff/xdrv_04_light.ino | 12 ++---------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index d1cf3adb1..74fbafee5 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -619,7 +619,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (Settings.flag.hass_discovery) { HAssPublishStatus(); } -#endif // USE_HOME_ASSISTANT +#endif // USE_HOME_ASSISTANT } else if (CMND_SLEEP == command_code) { if ((payload >= 0) && (payload < 251)) { @@ -1552,11 +1552,7 @@ void ExecuteCommandPower(uint8_t device, uint8_t state, int source) #ifdef USE_KNX KnxUpdatePowerState(device, power); #endif // USE_KNX - if (publish_power && Settings.flag3.hass_tele_on_power) { - mqtt_data[0] = '\0'; - MqttShowState(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); - } + if (publish_power && Settings.flag3.hass_tele_on_power) { MqttPublishTeleState(); } if (device <= MAX_PULSETIMERS) { // Restart PulseTime if powered On SetPulseTimer(device -1, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[device -1] : 0); } @@ -1783,6 +1779,13 @@ void MqttShowState(void) mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount(), WifiDowntime().c_str()); } +void MqttPublishTeleState(void) +{ + mqtt_data[0] = '\0'; + MqttShowState(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); +} + bool MqttShowSensor(void) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\""), mqtt_data, GetDateAndTime(DT_LOCAL).c_str()); @@ -1860,9 +1863,7 @@ void PerformEverySecond(void) if (tele_period >= Settings.tele_period) { tele_period = 0; - mqtt_data[0] = '\0'; - MqttShowState(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); + MqttPublishTeleState(); mqtt_data[0] = '\0'; if (MqttShowSensor()) { diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 1dc6e8630..532ecc42d 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -793,11 +793,7 @@ void LightPreparePower(void) #ifdef USE_DOMOTICZ DomoticzUpdatePowerState(light_device); #endif // USE_DOMOTICZ - if (Settings.flag3.hass_tele_on_power) { - mqtt_data[0] = '\0'; - MqttShowState(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); - } + if (Settings.flag3.hass_tele_on_power) { MqttPublishTeleState(); } LightState(0); } @@ -1456,11 +1452,7 @@ bool LightCommand(void) LightPowerOn(); strip_timer_counter = 0; // Publish state message for Hass - if (Settings.flag3.hass_tele_on_power) { - mqtt_data[0] = '\0'; - MqttShowState(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); - } + if (Settings.flag3.hass_tele_on_power) { MqttPublishTeleState(); } } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_scheme); } From 76b7d778ec7692711eebc653fd1bce1e27bec6ea Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Mar 2019 12:41:35 +0100 Subject: [PATCH 1171/2222] Fix incomplete syslog Fix incomplete syslog when MQTT is disabled (#5512) --- sonoff/support.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/support.ino b/sonoff/support.ino index e6068fb77..dc0396be2 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1221,6 +1221,7 @@ void Syslog(void) memcpy(log_data, syslog_preamble, strlen(syslog_preamble)); PortUdp.write(log_data); PortUdp.endPacket(); + delay(1); // Add time for UDP handling (#5512) } else { syslog_level = 0; syslog_timer = SYSLOG_TIMER; From 6922e657d9f6b13d0140aefe6a8c52303c8324bf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Mar 2019 17:00:59 +0100 Subject: [PATCH 1172/2222] Shrink code/flash space Shrink code/flash space --- sonoff/sonoff.ino | 261 +++++++++++++++--------------- sonoff/support.ino | 32 +++- sonoff/xdrv_01_webserver.ino | 25 ++- sonoff/xdrv_02_mqtt.ino | 65 ++++---- sonoff/xdrv_03_energy.ino | 46 +++--- sonoff/xdrv_04_light.ino | 68 ++++---- sonoff/xdrv_05_irremote.ino | 32 ++-- sonoff/xdrv_06_snfbridge.ino | 32 ++-- sonoff/xdrv_07_domoticz.ino | 24 ++- sonoff/xdrv_08_serial_bridge.ino | 12 +- sonoff/xdrv_09_timers.ino | 28 ++-- sonoff/xdrv_10_rules.ino | 28 ++-- sonoff/xdrv_12_home_assistant.ino | 3 +- sonoff/xdrv_13_display.ino | 28 ++-- sonoff/xdrv_14_mp3.ino | 4 +- sonoff/xdrv_15_pca9685.ino | 20 +-- sonoff/xdrv_17_rcswitch.ino | 6 +- sonoff/xdrv_99_debug.ino | 24 +-- 18 files changed, 380 insertions(+), 358 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 74fbafee5..cf11abcff 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -506,7 +506,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_RESULT D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " %s, " D_DATA " %s"), grpflg, index, type, dataBuf); if (type != NULL) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); + Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); if (Settings.ledstate &0x02) { blinks++; } if (!strcmp(dataBuf,"?")) { data_len = 0; } @@ -563,12 +563,12 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } blcommand = strtok(NULL, ";"); } -// snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_APPENDED); +// Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_APPENDED); mqtt_data[0] = '\0'; } else { 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_JSON_EMPTY : D_JSON_ABORTED); + Response_P(S_JSON_COMMAND_SVALUE, command, blflag ? D_JSON_EMPTY : D_JSON_ABORTED); } } else if (CMND_DELAY == command_code) { @@ -578,7 +578,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) uint16_t bl_delay = 0; long bl_delta = TimePassedSince(backlog_delay); if (bl_delta < 0) { bl_delay = (bl_delta *-1) / 100; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, bl_delay); + Response_P(S_JSON_COMMAND_NVALUE, command, bl_delay); } else if ((CMND_POWER == command_code) && (index > 0) && (index <= devices_present)) { if ((payload < 0) || (payload > 4)) { payload = 9; } @@ -601,7 +601,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if ((payload >= 0) && (payload < MAX_FAN_SPEED) && (payload != GetFanspeed())) { SetFanspeed(payload); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, GetFanspeed()); + Response_P(S_JSON_COMMAND_NVALUE, command, GetFanspeed()); } else if (CMND_STATUS == command_code) { if ((payload < 0) || (payload > MAX_STATUS)) payload = 99; @@ -627,7 +627,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) sleep = payload; WiFiSetSleepMode(); } - 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 : ""); + Response_P(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 ((CMND_UPGRADE == command_code) || (CMND_UPLOAD == command_code)) { // Check if the payload is numerically 1, and had no trailing chars. @@ -636,36 +636,36 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) // 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))) { ota_state_flag = 3; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}"), command, my_version, GetOtaUrl(stemp1, sizeof(stemp1))); + Response_P(PSTR("{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}"), command, my_version, GetOtaUrl(stemp1, sizeof(stemp1))); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_JSON_ONE_OR_GT "\"}"), command, my_version); + Response_P(PSTR("{\"%s\":\"" D_JSON_ONE_OR_GT "\"}"), command, my_version); } } else if (CMND_OTAURL == command_code) { if ((data_len > 0) && (data_len < sizeof(Settings.ota_url))) { strlcpy(Settings.ota_url, (SC_DEFAULT == Shortcut(dataBuf)) ? OTA_URL : dataBuf, sizeof(Settings.ota_url)); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.ota_url); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.ota_url); } else if (CMND_SERIALLOG == command_code) { if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) { Settings.flag.mqtt_serial = 0; SetSeriallog(payload); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.seriallog_level, seriallog_level); + Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.seriallog_level, seriallog_level); } else if (CMND_RESTART == command_code) { switch (payload) { case 1: restart_flag = 2; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_RESTARTING); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_RESTARTING); break; case 99: AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); EspRestart(); break; default: - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_ONE_TO_RESTART); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_ONE_TO_RESTART); } } else if ((CMND_POWERONSTATE == command_code) && (my_module_type != MOTOR)) { @@ -684,28 +684,28 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.poweronstate); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.poweronstate); } else if ((CMND_PULSETIME == command_code) && (index > 0) && (index <= MAX_PULSETIMERS)) { if (data_len > 0) { Settings.pulse_timer[index -1] = payload16; // 0 - 65535 SetPulseTimer(index -1, payload16); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE, command, index, Settings.pulse_timer[index -1], GetPulseTimer(index -1)); + Response_P(S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE, command, index, Settings.pulse_timer[index -1], GetPulseTimer(index -1)); } else if (CMND_BLINKTIME == command_code) { if ((payload > 1) && (payload <= 3600)) { Settings.blinktime = payload; if (blink_timer > 0) { blink_timer = millis() + (100 * payload); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.blinktime); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.blinktime); } else if (CMND_BLINKCOUNT == command_code) { if (data_len > 0) { Settings.blinkcount = payload16; // 0 - 65535 if (blink_counter) blink_counter = Settings.blinkcount *2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.blinkcount); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.blinkcount); } else if (CMND_SAVEDATA == command_code) { if ((payload >= 0) && (payload <= 3600)) { @@ -716,7 +716,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (Settings.save_data > 1) { snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_EVERY " %d " D_UNIT_SECOND), Settings.save_data); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, (Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data)); + Response_P(S_JSON_COMMAND_SVALUE, command, (Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data)); } else if ((CMND_SENSOR == command_code) || (CMND_DRIVER == command_code)) { XdrvMailbox.index = index; @@ -814,62 +814,62 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } if (ptype < 99) { if (2 == ptype) snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), Settings.param[pindex]); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, (2 == ptype) ? stemp1 : (1 == ptype) ? GetStateText(bitRead(Settings.flag3.data, pindex)) : GetStateText(bitRead(Settings.flag.data, pindex))); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, (2 == ptype) ? stemp1 : (1 == ptype) ? GetStateText(bitRead(Settings.flag3.data, pindex)) : GetStateText(bitRead(Settings.flag.data, pindex))); } } else if (CMND_TEMPERATURE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.temperature_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.temperature_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.temperature_resolution); } else if (CMND_HUMIDITY_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.humidity_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.humidity_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.humidity_resolution); } else if (CMND_PRESSURE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.pressure_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.pressure_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.pressure_resolution); } else if (CMND_POWER_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.wattage_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.wattage_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.wattage_resolution); } else if (CMND_VOLTAGE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.voltage_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.voltage_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.voltage_resolution); } else if (CMND_FREQUENCY_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.frequency_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.frequency_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.frequency_resolution); } else if (CMND_CURRENT_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.current_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.current_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.current_resolution); } else if (CMND_ENERGY_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 5)) { Settings.flag2.energy_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.energy_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.energy_resolution); } else if (CMND_WEIGHT_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.weight_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.weight_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.weight_resolution); } else if (CMND_MODULE == command_code) { if ((payload >= 0) && (payload <= MAXMODULE)) { @@ -885,21 +885,24 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, ModuleNr(), ModuleName().c_str()); + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, command, ModuleNr(), ModuleName().c_str()); } else if (CMND_MODULES == command_code) { for (uint8_t i = 0; i <= MAXMODULE; i++) { if (!jsflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULES "%d\":["), lines); + Response_P(PSTR("{\"" D_CMND_MODULES "%d\":["), lines); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + ResponseAppend_P(PSTR(",")); } jsflg = true; uint8_t j = i; if (0 == i) { j = USER_MODULE; } else { j--; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, i, AnyModuleName(j).c_str()); - if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == MAXMODULE)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]}"), mqtt_data); + +// ResponseAppend_P(PSTR("\"%d (%s)\""), i, AnyModuleName(j).c_str()); +// if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == MAXMODULE)) { + + if ((ResponseAppend_P(PSTR("\"%d (%s)\""), i, AnyModuleName(j).c_str()) > (LOGSZ - TOPSZ)) || (i == MAXMODULE)) { + ResponseAppend_P(PSTR("]}")); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); jsflg = false; lines++; @@ -926,19 +929,18 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) restart_flag = 2; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); + Response_P(PSTR("{")); for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { if (ValidGPIO(i, cmodule.io[i])) { - if (jsflg) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + if (jsflg) { ResponseAppend_P(PSTR(",")); } jsflg = true; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_GPIO "%d\":\"%d (%s)\""), - mqtt_data, i, Settings.my_gp.io[i], GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_gp.io[i], kSensorNames)); + ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":\"%d (%s)\""), i, Settings.my_gp.io[i], GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_gp.io[i], kSensorNames)); } } if (jsflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_NOT_SUPPORTED); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_NOT_SUPPORTED); } } else if (CMND_GPIOS == command_code) { @@ -949,14 +951,17 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) midx = pgm_read_byte(kGpioNiceList + i); if (!GetUsedInModule(midx, cmodule.io)) { if (!jsflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_GPIOS "%d\":["), lines); + Response_P(PSTR("{\"" D_CMND_GPIOS "%d\":["), lines); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + ResponseAppend_P(PSTR(",")); } jsflg = true; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)); - if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]}"), mqtt_data); + +// ResponseAppend_P(PSTR("\"%d (%s)\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)); +// if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { + + if ((ResponseAppend_P(PSTR("\"%d (%s)\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { + ResponseAppend_P(PSTR("]}")); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); jsflg = false; lines++; @@ -999,7 +1004,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (JsonTemplate(dataBuf)) { // Free 336 bytes StaticJsonBuffer stack space by moving code to function if (USER_MODULE == Settings.module) { restart_flag = 2; } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); error = true; } } @@ -1010,16 +1015,16 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) 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("{")); + Response_P(PSTR("{")); MqttShowPWMState(); // Render the PWM status to MQTT - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } else if (CMND_PWMFREQUENCY == command_code) { if ((1 == payload) || ((payload >= PWM_MIN) && (payload <= PWM_MAX))) { 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), S_JSON_COMMAND_NVALUE, command, Settings.pwm_frequency); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.pwm_frequency); } else if (CMND_PWMRANGE == command_code) { if ((1 == payload) || ((payload > 254) && (payload < 1024))) { @@ -1031,7 +1036,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.pwm_range); + Response_P(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)) { @@ -1043,7 +1048,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) Settings.pulse_counter[index -1] = payload32; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_LVALUE, command, index, RtcSettings.pulse_counter[index -1]); + Response_P(S_JSON_COMMAND_INDEX_LVALUE, 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)) { @@ -1051,25 +1056,25 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) 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)); + Response_P(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); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.pulse_counter_debounce); } else if (CMND_BUTTONDEBOUNCE == command_code) { if ((payload > 39) && (payload < 1001)) { Settings.button_debounce = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.button_debounce); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.button_debounce); } else if (CMND_SWITCHDEBOUNCE == command_code) { if ((payload > 39) && (payload < 1001)) { Settings.switch_debounce = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.switch_debounce); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.switch_debounce); } else if (CMND_BAUDRATE == command_code) { if (payload32 > 1200) { @@ -1077,7 +1082,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) baudrate = (1 == payload) ? APP_BAUDRATE : payload32 * 1200; SetSerialBaudrate(baudrate); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.baudrate * 1200); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.baudrate * 1200); } else if ((CMND_SERIALSEND == command_code) && (index > 0) && (index <= 5)) { SetSeriallog(LOG_LEVEL_NONE); @@ -1099,7 +1104,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) else if (5 == index) { SerialSendRaw(RemoveSpace(dataBuf)); // "AA004566" as hex values } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } } else if (CMND_SERIALDELIMITER == command_code) { @@ -1112,7 +1117,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) Settings.serial_delimiter = dataBuf[0]; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.serial_delimiter); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.serial_delimiter); } else if (CMND_SYSLOG == command_code) { if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) { @@ -1120,19 +1125,19 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) syslog_level = payload; syslog_timer = 0; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.syslog_level, syslog_level); + Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.syslog_level, syslog_level); } else if (CMND_LOGHOST == command_code) { if ((data_len > 0) && (data_len < sizeof(Settings.syslog_host))) { strlcpy(Settings.syslog_host, (SC_DEFAULT == Shortcut(dataBuf)) ? SYS_LOG_HOST : dataBuf, sizeof(Settings.syslog_host)); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.syslog_host); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.syslog_host); } else if (CMND_LOGPORT == command_code) { if (payload16 > 0) { Settings.syslog_port = (1 == payload16) ? SYS_LOG_PORT : payload16; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.syslog_port); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.syslog_port); } else if ((CMND_IPADDRESS == command_code) && (index > 0) && (index <= 4)) { if (ParseIp(&address, dataBuf)) { @@ -1140,7 +1145,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) // restart_flag = 2; } snprintf_P(stemp1, sizeof(stemp1), PSTR(" (%s)"), WiFi.localIP().toString().c_str()); - 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:""); + Response_P(S_JSON_COMMAND_INDEX_SVALUE_SVALUE, command, index, IPAddress(Settings.ip_address[index -1]).toString().c_str(), (1 == index) ? stemp1:""); } else if ((CMND_NTPSERVER == command_code) && (index > 0) && (index <= 3)) { if ((data_len > 0) && (data_len < sizeof(Settings.ntp_server[0]))) { @@ -1151,7 +1156,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) // restart_flag = 2; // Issue #3890 ntp_force_sync = true; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.ntp_server[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.ntp_server[index -1]); } else if (CMND_AP == command_code) { if ((payload >= 0) && (payload <= 2)) { @@ -1165,7 +1170,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active]); + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active]); } else if ((CMND_SSID == command_code) && (index > 0) && (index <= 2)) { if ((data_len > 0) && (data_len < sizeof(Settings.sta_ssid[0]))) { @@ -1173,16 +1178,16 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) Settings.sta_active = index -1; restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.sta_ssid[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.sta_ssid[index -1]); } else if ((CMND_PASSWORD == command_code) && (index > 0) && (index <= 2)) { if ((data_len > 4 || SC_CLEAR == Shortcut(dataBuf) || SC_DEFAULT == Shortcut(dataBuf)) && (data_len < sizeof(Settings.sta_pwd[0]))) { strlcpy(Settings.sta_pwd[index -1], (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? (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), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.sta_pwd[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.sta_pwd[index -1]); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_ASTERIX, command, index); + Response_P(S_JSON_COMMAND_INDEX_ASTERIX, command, index); } } else if (CMND_HOSTNAME == command_code) { @@ -1193,21 +1198,21 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.hostname); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.hostname); } else if (CMND_WIFICONFIG == command_code) { if ((payload >= WIFI_RESTART) && (payload < MAX_WIFI_OPTION)) { 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_JSON_SELECTED "\"}"), stemp1); + Response_P(PSTR("{\"" D_CMND_WIFICONFIG "\":\"%s " D_JSON_SELECTED "\"}"), stemp1); if (WifiState() > WIFI_RESTART) { // snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s after restart"), mqtt_data); restart_flag = 2; } } else { 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); + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.sta_config, stemp1); } } else if ((CMND_FRIENDLYNAME == command_code) && (index > 0) && (index <= MAX_FRIENDLYNAMES)) { @@ -1219,13 +1224,13 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } strlcpy(Settings.friendlyname[index -1], (SC_DEFAULT == Shortcut(dataBuf)) ? stemp1 : dataBuf, sizeof(Settings.friendlyname[index -1])); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.friendlyname[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.friendlyname[index -1]); } else if ((CMND_SWITCHMODE == command_code) && (index > 0) && (index <= MAX_SWITCHES)) { if ((payload >= 0) && (payload < MAX_SWITCH_OPTION)) { Settings.switchmode[index -1] = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, index, Settings.switchmode[index-1]); + Response_P(S_JSON_COMMAND_INDEX_NVALUE, command, index, Settings.switchmode[index-1]); } else if (CMND_INTERLOCK == command_code) { // Interlock 0 - Off, Interlock 1 - On, Interlock 1,2 3,4 5,6,7 uint8_t max_relays = devices_present; @@ -1267,18 +1272,18 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_INTERLOCK "\":\"%s\",\"" D_JSON_GROUPS "\":\""), GetStateText(Settings.flag.interlock)); + Response_P(PSTR("{\"" D_CMND_INTERLOCK "\":\"%s\",\"" D_JSON_GROUPS "\":\""), GetStateText(Settings.flag.interlock)); uint8_t anygroup = 0; for (uint8_t i = 0; i < MAX_INTERLOCKS; i++) { if (Settings.interlock[i]) { anygroup++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s"), mqtt_data, (anygroup > 1) ? " " : ""); + ResponseAppend_P(PSTR("%s"), (anygroup > 1) ? " " : ""); uint8_t anybit = 0; power_t mask = 1; for (uint8_t j = 0; j < max_relays; j++) { if (Settings.interlock[i] & mask) { anybit++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (anybit > 1) ? "," : "", j +1); + ResponseAppend_P(PSTR("%s%d"), (anybit > 1) ? "," : "", j +1); } mask <<= 1; } @@ -1286,13 +1291,13 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } if (!anygroup) { for (uint8_t j = 1; j <= max_relays; j++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (j > 1) ? "," : "", j); + ResponseAppend_P(PSTR("%s%d"), (j > 1) ? "," : "", j); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); + ResponseAppend_P(PSTR("\"}")); } else { Settings.flag.interlock = 0; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.interlock)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.interlock)); } } else if (CMND_TELEPERIOD == command_code) { @@ -1301,20 +1306,20 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) Settings.tele_period = 10; // Do not allow periods < 10 seconds tele_period = Settings.tele_period; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_UNIT, command, Settings.tele_period, (Settings.flag.value_units) ? " " D_UNIT_SECOND : ""); + Response_P(S_JSON_COMMAND_NVALUE_UNIT, command, Settings.tele_period, (Settings.flag.value_units) ? " " D_UNIT_SECOND : ""); } else if (CMND_RESET == command_code) { switch (payload) { case 1: restart_flag = 211; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command , D_JSON_RESET_AND_RESTARTING); + Response_P(S_JSON_COMMAND_SVALUE, command , D_JSON_RESET_AND_RESTARTING); break; case 2 ... 6: restart_flag = 210 + payload; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); + Response_P(PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); break; default: - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_ONE_TO_RESET); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_ONE_TO_RESET); } } else if (CMND_TIMEZONE == command_code) { @@ -1336,10 +1341,10 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) ntp_force_sync = true; } if (99 == Settings.timezone) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.timezone); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.timezone); } else { snprintf_P(stemp1, sizeof(stemp1), PSTR("%+03d:%02d"), Settings.timezone, Settings.timezone_minutes); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, stemp1); + Response_P(S_JSON_COMMAND_SVALUE, command, stemp1); } } else if ((CMND_TIMESTD == command_code) || (CMND_TIMEDST == command_code)) { @@ -1380,14 +1385,14 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) ntp_force_sync = true; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d}}"), + Response_P(PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d}}"), command, Settings.tflag[ts].hemis, Settings.tflag[ts].week, Settings.tflag[ts].month, Settings.tflag[ts].dow, Settings.tflag[ts].hour, Settings.toffset[ts]); } 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); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.altitude); } else if (CMND_LEDPOWER == command_code) { if ((payload >= 0) && (payload <= 2)) { @@ -1404,7 +1409,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) blinks = 0; SetLedPower(Settings.ledstate &8); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(bitRead(Settings.ledstate, 3))); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(bitRead(Settings.ledstate, 3))); } else if (CMND_LEDSTATE == command_code) { if ((payload >= 0) && (payload < MAX_LED_OPTION)) { @@ -1414,7 +1419,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) SetLedLink(0); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.ledstate); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.ledstate); } #ifdef USE_I2C else if ((CMND_I2CSCAN == command_code) && i2c_flg) { @@ -1426,10 +1431,10 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (type == NULL) { blinks = 201; snprintf_P(topicBuf, sizeof(topicBuf), PSTR(D_JSON_COMMAND)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); + Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); type = (char*)topicBuf; } - if (mqtt_data[0] != '\0') MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); + if (mqtt_data[0] != '\0') { MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); } fallback_topic_flag = false; } @@ -1641,19 +1646,19 @@ void PublishStatus(uint8_t payload) for (uint8_t i = 0; i < MAX_SWITCHES; i++) { snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%d" ), stemp2, (i > 0 ? "," : ""), Settings.switchmode[i]); } - 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_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), + Response_P(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_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), ModuleNr(), stemp, mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, Settings.save_data, Settings.flag.save_state, Settings.switch_topic, stemp2, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_switch_retain, Settings.flag.mqtt_sensor_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_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), baudrate, Settings.mqtt_grptopic, Settings.ota_url, GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.cfg_holder, 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_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"}}"), my_version, my_image, GetBuildDateAndTime().c_str(), ESP.getBootVersion(), ESP.getSdkVersion()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); } @@ -1663,26 +1668,26 @@ void PublishStatus(uint8_t payload) for (int8_t i = 0; i < PARAM8_SIZE; i++) { snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%02X"), stemp2, Settings.param[i]); } - 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 "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\"]}}"), + Response_P(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 "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\"]}}"), 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.flag2.data, Settings.flag.data, stemp2, Settings.flag3.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_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\"" D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\"" D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]}}"), ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipId(), ESP.getFlashChipMode(), LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2); 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_JSON_GATEWAY "\":\"%s\",\"" D_JSON_SUBNETMASK "\":\"%s\",\"" D_JSON_DNSSERVER "\":\"%s\",\"" D_JSON_MAC "\":\"%s\",\"" D_CMND_WEBSERVER "\":%d,\"" D_CMND_WIFICONFIG "\":%d}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_GATEWAY "\":\"%s\",\"" D_JSON_SUBNETMASK "\":\"%s\",\"" D_JSON_DNSSERVER "\":\"%s\",\"" D_JSON_MAC "\":\"%s\",\"" D_CMND_WEBSERVER "\":%d,\"" D_CMND_WIFICONFIG "\":%d}}"), 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)) && 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_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, mqtt_client, Settings.mqtt_user, MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6")); } @@ -1694,10 +1699,10 @@ void PublishStatus(uint8_t payload) snprintf_P(stemp, sizeof(stemp), PSTR("\"%s\"" ), GetTimeZone().c_str()); } #if defined(USE_TIMERS) && defined(USE_SUNRISE) - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s,\"" D_JSON_SUNRISE "\":\"%s\",\"" D_JSON_SUNSET "\":\"%s\"}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s,\"" D_JSON_SUNRISE "\":\"%s\",\"" D_JSON_SUNSET "\":\"%s\"}}"), GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), GetTime(3).c_str(), stemp, GetSun(0).c_str(), GetSun(1).c_str()); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s}}"), GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), GetTime(3).c_str(), stemp); #endif // USE_TIMERS and USE_SUNRISE MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "7")); @@ -1705,16 +1710,16 @@ void PublishStatus(uint8_t payload) if (energy_flg) { if ((0 == payload) || (9 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS9_MARGIN "\":{\"" D_CMND_POWERDELTA "\":%d,\"" D_CMND_POWERLOW "\":%d,\"" D_CMND_POWERHIGH "\":%d,\"" D_CMND_VOLTAGELOW "\":%d,\"" D_CMND_VOLTAGEHIGH "\":%d,\"" D_CMND_CURRENTLOW "\":%d,\"" D_CMND_CURRENTHIGH "\":%d}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS9_MARGIN "\":{\"" D_CMND_POWERDELTA "\":%d,\"" D_CMND_POWERLOW "\":%d,\"" D_CMND_POWERHIGH "\":%d,\"" D_CMND_VOLTAGELOW "\":%d,\"" D_CMND_VOLTAGEHIGH "\":%d,\"" D_CMND_CURRENTLOW "\":%d,\"" D_CMND_CURRENTHIGH "\":%d}}"), Settings.energy_power_delta, Settings.energy_min_power, Settings.energy_max_power, Settings.energy_min_voltage, Settings.energy_max_voltage, Settings.energy_min_current, Settings.energy_max_current); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "9")); } } if ((0 == payload) || (8 == payload) || (10 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":")); + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":")); MqttShowSensor(); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); if (8 == payload) { MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "8")); } else { @@ -1723,9 +1728,9 @@ void PublishStatus(uint8_t payload) } if ((0 == payload) || (11 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS11_STATUS "\":")); + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS11_STATUS "\":")); MqttShowState(); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); } @@ -1733,50 +1738,50 @@ void PublishStatus(uint8_t payload) void MqttShowPWMState(void) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_PWM "\":{"), mqtt_data); + ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{")); bool first = true; for (uint8_t 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, Settings.pwm_value[i]); + ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings.pwm_value[i]); first = false; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } void MqttShowState(void) { char stemp1[33]; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\""), mqtt_data, GetDateAndTime(DT_LOCAL).c_str(), GetUptime().c_str()); + ResponseAppend_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str(), GetUptime().c_str()); #ifdef USE_ADC_VCC dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VCC "\":%s"), mqtt_data, stemp1); + ResponseAppend_P(PSTR(",\"" D_JSON_VCC "\":%s"), stemp1); #endif - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u"), - mqtt_data, GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), sleep, loop_load_avg); + ResponseAppend_P(PSTR(",\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u"), + GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), sleep, loop_load_avg); for (uint8_t i = 0; i < devices_present; i++) { if (i == light_device -1) { LightState(1); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":\"%s\""), mqtt_data, GetPowerDevice(stemp1, i +1, sizeof(stemp1), Settings.flag.device_index_enable), GetStateText(bitRead(power, i))); + ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i +1, sizeof(stemp1), Settings.flag.device_index_enable), GetStateText(bitRead(power, i))); if (SONOFF_IFAN02 == my_module_type) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_FANSPEED "\":%d"), mqtt_data, GetFanspeed()); + ResponseAppend_P(PSTR(",\"" D_CMND_FANSPEED "\":%d"), GetFanspeed()); break; } } } if (pwm_present) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + ResponseAppend_P(PSTR(",")); MqttShowPWMState(); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), - mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount(), WifiDowntime().c_str()); + ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), + Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount(), WifiDowntime().c_str()); } void MqttPublishTeleState(void) @@ -1788,7 +1793,7 @@ void MqttPublishTeleState(void) bool MqttShowSensor(void) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\""), mqtt_data, GetDateAndTime(DT_LOCAL).c_str()); + ResponseAppend_P(PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); int json_data_start = strlen(mqtt_data); for (uint8_t i = 0; i < MAX_SWITCHES; i++) { #ifdef USE_TM1638 @@ -1797,20 +1802,20 @@ bool MqttShowSensor(void) if (pin[GPIO_SWT1 +i] < 99) { #endif // USE_TM1638 bool 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_JSON_SWITCH "%d\":\"%s\""), mqtt_data, i +1, GetStateText(swm ^ SwitchLastState(i))); + ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(swm ^ SwitchLastState(i))); } } XsnsCall(FUNC_JSON_APPEND); bool json_data_available = (strlen(mqtt_data) - json_data_start); if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), mqtt_data, PressureUnit().c_str()); + ResponseAppend_P(PSTR(",\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), PressureUnit().c_str()); } if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), mqtt_data, TempUnit()); + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); - if (json_data_available) XdrvCall(FUNC_SHOW_SENSOR); + if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } return json_data_available; } @@ -1880,7 +1885,7 @@ void PerformEverySecond(void) if ((2 == RtcTime.minute) && latest_uptime_flag) { latest_uptime_flag = false; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"}"), GetDateAndTime(DT_LOCAL).c_str(), GetUptime().c_str()); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"}"), GetDateAndTime(DT_LOCAL).c_str(), GetUptime().c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_UPTIME)); } if ((3 == RtcTime.minute) && !latest_uptime_flag) latest_uptime_flag = true; @@ -2054,9 +2059,9 @@ void Every250mSeconds(void) ota_state_flag = 0; if (ota_result) { // SetFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285 - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); + Response_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); + Response_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); } restart_flag = 2; // Restart anyway to keep memory clean webserver MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE)); @@ -2298,13 +2303,13 @@ void SerialInput(void) if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed if (!Settings.flag.mqtt_serial_raw) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer); + Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"")); + Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"")); for (int i = 0; i < serial_in_byte_counter; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_in_buffer[i]); + ResponseAppend_P(PSTR("%02x"), serial_in_buffer[i]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); + ResponseAppend_P(PSTR("\"}")); } MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); // XdrvRulesProcess(); diff --git a/sonoff/support.ino b/sonoff/support.ino index dc0396be2..24f0c6f8c 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -697,6 +697,31 @@ void ShowSource(int source) } } +/*********************************************************************************************\ + * Response data handling +\*********************************************************************************************/ + +int Response_P(const char* formatP, ...) // Content send snprintf_P char data +{ + // This uses char strings. Be aware of sending %% if % is needed + va_list arg; + va_start(arg, formatP); + int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); + va_end(arg); + return len; +} + +int ResponseAppend_P(const char* formatP, ...) // Content send snprintf_P char data +{ + // This uses char strings. Be aware of sending %% if % is needed + va_list arg; + va_start(arg, formatP); + int mlen = strlen(mqtt_data); + int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, formatP, arg); + va_end(arg); + return len + mlen; +} + /*********************************************************************************************\ * GPIO Module and Template management \*********************************************************************************************/ @@ -883,12 +908,11 @@ bool JsonTemplate(const char* dataBuf) void TemplateJson() { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); + Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); for (uint8_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", Settings.user_template.gp.io[i]); + ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", Settings.user_template.gp.io[i]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), - mqtt_data, Settings.user_template.flag, Settings.user_template_base +1); + ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1); } /*********************************************************************************************\ diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 48a13fe11..f34bfda09 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2136,13 +2136,12 @@ void HandleNotFound(void) } else #endif // USE_EMULATION { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), - WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args()); + WSContentBegin(404, CT_PLAIN); + WSContentSend_P(PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args()); for (uint8_t i = 0; i < WebServer->args(); i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s %s: %s\n"), mqtt_data, WebServer->argName(i).c_str(), WebServer->arg(i).c_str()); + WSContentSend_P(PSTR(" %s: %s\n"), WebServer->argName(i).c_str(), WebServer->arg(i).c_str()); } - WSHeaderSend(); - WSSend(404, CT_PLAIN, mqtt_data); + WSContentEnd(); } } @@ -2301,33 +2300,33 @@ bool WebCommand(void) if (CMND_WEBSERVER == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { Settings.webserver = XdrvMailbox.payload; } if (Settings.webserver) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WEBSERVER "\":\"" D_JSON_ACTIVE_FOR " %s " D_JSON_ON_DEVICE " %s " D_JSON_WITH_IP_ADDRESS " %s\"}"), + Response_P(PSTR("{\"" D_CMND_WEBSERVER "\":\"" D_JSON_ACTIVE_FOR " %s " D_JSON_ON_DEVICE " %s " D_JSON_WITH_IP_ADDRESS " %s\"}"), (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(0)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(0)); } } else if (CMND_WEBPASSWORD == command_code) { if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.web_password))) { strlcpy(Settings.web_password, (SC_CLEAR == Shortcut(XdrvMailbox.data)) ? "" : (SC_DEFAULT == Shortcut(XdrvMailbox.data)) ? WEB_PASSWORD : XdrvMailbox.data, sizeof(Settings.web_password)); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.web_password); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.web_password); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_ASTERIX, command); + Response_P(S_JSON_COMMAND_ASTERIX, command); } } else if (CMND_WEBLOG == command_code) { if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { Settings.weblog_level = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.weblog_level); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.weblog_level); } else if (CMND_WEBREFRESH == command_code) { if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload <= 10000)) { Settings.web_refresh = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.web_refresh); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.web_refresh); } else if (CMND_WEBSEND == command_code) { if (XdrvMailbox.data_len > 0) { uint8_t result = WebSend(XdrvMailbox.data); char stemp1[20]; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus)); } } #ifdef USE_EMULATION @@ -2336,7 +2335,7 @@ bool WebCommand(void) Settings.flag2.emulation = XdrvMailbox.payload; restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.emulation); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.emulation); } #endif // USE_EMULATION else serviced = false; // Unknown command diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 57086d46e..21b97edd0 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -237,17 +237,17 @@ void MqttPublishPowerState(uint8_t device) #endif // USE_DOMOTICZ snprintf_P(scommand, sizeof(scommand), PSTR(D_CMND_FANSPEED)); GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, scommand, GetFanspeed()); + Response_P(S_JSON_COMMAND_NVALUE, scommand, GetFanspeed()); MqttPublish(stopic); } } else { GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable); GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(power, device -1))); + Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(power, device -1))); MqttPublish(stopic); GetTopic_P(stopic, STAT, mqtt_topic, scommand); - snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(bitRead(power, device -1))); + Response_P(GetStateText(bitRead(power, device -1))); MqttPublish(stopic, Settings.flag.mqtt_power_retain); } } @@ -259,7 +259,7 @@ void MqttPublishPowerBlinkState(uint8_t device) if ((device < 1) || (device > devices_present)) { device = 1; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_JSON_BLINK " %s\"}"), + Response_P(PSTR("{\"%s\":\"" D_JSON_BLINK " %s\"}"), GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable), GetStateText(bitRead(blink_mask, device -1))); MqttPublishPrefixTopic_P(RESULT_OR_STAT, S_RSLT_POWER); @@ -292,7 +292,7 @@ void MqttConnected(void) mqtt_connect_count++; GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_ONLINE)); + Response_P(PSTR(D_ONLINE)); MqttPublish(stopic, true); // Satisfy iobroker (#299) @@ -312,18 +312,17 @@ void MqttConnected(void) } if (mqtt_initial_connection_state) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), + Response_P(PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), ModuleName().c_str(), my_version, my_image, GetFallbackTopic_P(stopic, CMND, ""), Settings.mqtt_grptopic); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); #ifdef USE_WEBSERVER if (Settings.webserver) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"), + Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"), (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); } #endif // USE_WEBSERVER - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), - (GetResetReason() == "Exception") ? ESP.getResetInfo().c_str() : GetResetReason().c_str()); + Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), (GetResetReason() == "Exception") ? ESP.getResetInfo().c_str() : GetResetReason().c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); for (uint8_t i = 1; i <= devices_present; i++) { MqttPublishPowerState(i); @@ -438,7 +437,7 @@ void MqttReconnect(void) if (strlen(Settings.mqtt_pwd) > 0) mqtt_pwd = Settings.mqtt_pwd; GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_OFFLINE); + Response_P(S_OFFLINE); #ifdef USE_MQTT_TLS EspClient = WiFiClientSecure(); // Wifi Secure Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497) @@ -514,21 +513,21 @@ bool MqttCommand(void) strlcpy(Settings.mqtt_host, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_HOST : dataBuf, sizeof(Settings.mqtt_host)); restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_host); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_host); } else if (CMND_MQTTPORT == command_code) { if (payload16 > 0) { Settings.mqtt_port = (1 == payload16) ? MQTT_PORT : payload16; restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.mqtt_port); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.mqtt_port); } else if (CMND_MQTTRETRY == command_code) { if ((payload >= MQTT_RETRY_SECS) && (payload < 32001)) { Settings.mqtt_retry = payload; mqtt_retry_counter = Settings.mqtt_retry; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.mqtt_retry); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.mqtt_retry); } else if ((CMND_STATETEXT == command_code) && (index > 0) && (index <= 4)) { if ((data_len > 0) && (data_len < sizeof(Settings.state_text[0]))) { @@ -537,7 +536,7 @@ bool MqttCommand(void) } strlcpy(Settings.state_text[index -1], dataBuf, sizeof(Settings.state_text[0])); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(index -1)); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(index -1)); } #ifdef USE_MQTT_TLS else if ((CMND_MQTTFINGERPRINT == command_code) && (index > 0) && (index <= 2)) { @@ -554,7 +553,7 @@ bool MqttCommand(void) for (uint8_t i = 0; i < sizeof(Settings.mqtt_fingerprint[index -1]); i++) { snprintf_P(fingerprint, sizeof(fingerprint), PSTR("%s%s%02X"), fingerprint, (i) ? " " : "", Settings.mqtt_fingerprint[index -1][i]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, fingerprint); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, fingerprint); } #endif else if (CMND_MQTTCLIENT == command_code) { @@ -562,22 +561,22 @@ bool MqttCommand(void) strlcpy(Settings.mqtt_client, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_CLIENT_ID : dataBuf, sizeof(Settings.mqtt_client)); restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_client); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_client); } else if (CMND_MQTTUSER == command_code) { if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_user))) { strlcpy(Settings.mqtt_user, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_USER : dataBuf, sizeof(Settings.mqtt_user)); restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_user); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_user); } else if (CMND_MQTTPASSWORD == command_code) { if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_pwd))) { strlcpy(Settings.mqtt_pwd, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_PASS : dataBuf, sizeof(Settings.mqtt_pwd)); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_pwd); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_pwd); restart_flag = 2; } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_ASTERIX, command); + Response_P(S_JSON_COMMAND_ASTERIX, command); } } else if (CMND_FULLTOPIC == command_code) { @@ -586,13 +585,13 @@ bool MqttCommand(void) if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT); strlcpy(stemp1, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_FULLTOPIC : dataBuf, sizeof(stemp1)); if (strcmp(stemp1, Settings.mqtt_fulltopic)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); MqttPublishPrefixTopic_P(TELE, 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), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_fulltopic); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_fulltopic); } else if ((CMND_PREFIX == command_code) && (index > 0) && (index <= 3)) { if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_prefix[0]))) { @@ -601,7 +600,7 @@ bool MqttCommand(void) // 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), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mqtt_prefix[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mqtt_prefix[index -1]); } else if (CMND_PUBLISH == command_code) { if (data_len > 0) { @@ -615,7 +614,7 @@ bool MqttCommand(void) mqtt_data[0] = '\0'; } MqttPublishDirect(stemp1, (index == 2)); -// snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); +// Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); mqtt_data[0] = '\0'; } } @@ -627,7 +626,7 @@ bool MqttCommand(void) strlcpy(Settings.mqtt_grptopic, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_GRPTOPIC : dataBuf, sizeof(Settings.mqtt_grptopic)); restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_grptopic); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_grptopic); } else if (CMND_TOPIC == command_code) { if (!grpflg && (data_len > 0) && (data_len < sizeof(Settings.mqtt_topic))) { @@ -635,13 +634,13 @@ bool MqttCommand(void) if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT); strlcpy(stemp1, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_TOPIC : dataBuf, sizeof(stemp1)); if (strcmp(stemp1, Settings.mqtt_topic)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); MqttPublishPrefixTopic_P(TELE, 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), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_topic); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_topic); } else if (CMND_BUTTONTOPIC == command_code) { if (!grpflg && (data_len > 0) && (data_len < sizeof(Settings.button_topic))) { @@ -654,7 +653,7 @@ bool MqttCommand(void) default: strlcpy(Settings.button_topic, dataBuf, sizeof(Settings.button_topic)); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.button_topic); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.button_topic); } else if (CMND_SWITCHTOPIC == command_code) { if ((data_len > 0) && (data_len < sizeof(Settings.switch_topic))) { @@ -667,7 +666,7 @@ bool MqttCommand(void) default: strlcpy(Settings.switch_topic, dataBuf, sizeof(Settings.switch_topic)); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.switch_topic); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.switch_topic); } else if (CMND_BUTTONRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { @@ -678,7 +677,7 @@ bool MqttCommand(void) } Settings.flag.mqtt_button_retain = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_button_retain)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_button_retain)); } else if (CMND_SWITCHRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { @@ -689,7 +688,7 @@ bool MqttCommand(void) } Settings.flag.mqtt_switch_retain = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_switch_retain)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_switch_retain)); } else if (CMND_POWERRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { @@ -702,7 +701,7 @@ bool MqttCommand(void) } Settings.flag.mqtt_power_retain = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_power_retain)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_power_retain)); } else if (CMND_SENSORRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { @@ -713,7 +712,7 @@ bool MqttCommand(void) } Settings.flag.mqtt_sensor_retain = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_sensor_retain)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_sensor_retain)); } else serviced = false; // Unknown command @@ -790,7 +789,7 @@ void MqttSaveSettings(void) strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); MakeValidMqtt(1,stemp2); if ((strcmp(stemp, Settings.mqtt_topic)) || (strcmp(stemp2, Settings.mqtt_fulltopic))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic } strlcpy(Settings.mqtt_topic, stemp, sizeof(Settings.mqtt_topic)); diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index b2393a311..69d93b244 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -201,34 +201,34 @@ void EnergyMarginCheck(void) // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); + Response_P(PSTR("{")); jsonflg = false; if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, energy_min_power_flag)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_POWERLOW "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); + ResponseAppend_P(PSTR("%s\"" D_CMND_POWERLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; } if (EnergyMargin(true, Settings.energy_max_power, energy_power_u, flag, energy_max_power_flag)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_POWERHIGH "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); + ResponseAppend_P(PSTR("%s\"" D_CMND_POWERHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; } if (EnergyMargin(false, Settings.energy_min_voltage, energy_voltage_u, flag, energy_min_voltage_flag)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); + ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; } if (EnergyMargin(true, Settings.energy_max_voltage, energy_voltage_u, flag, energy_max_voltage_flag)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); + ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; } if (EnergyMargin(false, Settings.energy_min_current, energy_current_u, flag, energy_min_current_flag)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_CURRENTLOW "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); + ResponseAppend_P(PSTR("%s%s\"" D_CMND_CURRENTLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; } if (EnergyMargin(true, Settings.energy_max_current, energy_current_u, flag, energy_max_current_flag)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); + ResponseAppend_P(PSTR("%s%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; } if (jsonflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_MARGINS), MQTT_TELE_RETAIN); EnergyMqttShow(); } @@ -243,7 +243,7 @@ void EnergyMarginCheck(void) } else { energy_mplh_counter--; if (!energy_mplh_counter) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); + Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); ExecuteCommandPower(1, POWER_OFF, SRC_MAXPOWER); @@ -266,11 +266,11 @@ void EnergyMarginCheck(void) if (energy_mplr_counter) { energy_mplr_counter--; if (energy_mplr_counter) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); + Response_P(PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); ExecuteCommandPower(1, POWER_ON, SRC_MAXPOWER); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); + Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); } @@ -284,14 +284,14 @@ void EnergyMarginCheck(void) energy_daily_u = (uint16_t)(energy_daily * 1000); if (!energy_max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) { energy_max_energy_state = 1; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); + Response_P(PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); ExecuteCommandPower(1, POWER_ON, SRC_MAXENERGY); } else if ((1 == energy_max_energy_state) && (energy_daily_u >= Settings.energy_max_energy)) { energy_max_energy_state = 2; dtostrfd(energy_daily, 3, mqtt_data); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); + Response_P(PSTR("{\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); ExecuteCommandPower(1, POWER_OFF, SRC_MAXENERGY); @@ -305,12 +305,12 @@ void EnergyMarginCheck(void) void EnergyMqttShow(void) { // {"Time":"2017-12-16T11:48:55","ENERGY":{"Total":0.212,"Yesterday":0.000,"Today":0.014,"Period":2.0,"Power":22.0,"Factor":1.00,"Voltage":213.6,"Current":0.100}} - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); int tele_period_save = tele_period; tele_period = 2; EnergyShow(true); tele_period = tele_period_save; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); energy_power_delta = 0; } @@ -414,7 +414,7 @@ bool EnergyCommand(void) char energy_yesterday_chr[33]; dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s}}"), + Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s}}"), command, energy_total_chr, energy_yesterday_chr, energy_daily_chr); status_flag = true; } @@ -519,9 +519,9 @@ bool EnergyCommand(void) } if (Settings.flag.value_units) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_LVALUE_SPACE_UNIT, command, nvalue, GetTextIndexed(sunit, sizeof(sunit), unit, kUnitNames)); + Response_P(S_JSON_COMMAND_LVALUE_SPACE_UNIT, command, nvalue, GetTextIndexed(sunit, sizeof(sunit), unit, kUnitNames)); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_LVALUE, command, nvalue); + Response_P(S_JSON_COMMAND_LVALUE, command, nvalue); } } @@ -637,13 +637,13 @@ void EnergyShow(bool json) } if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" D_JSON_POWERUSAGE "\":%s"), - mqtt_data, GetDateAndTime(DT_ENERGY).c_str(), energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", active_power_chr); + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" D_JSON_POWERUSAGE "\":%s"), + GetDateAndTime(DT_ENERGY).c_str(), energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", active_power_chr); if (!energy_type_dc) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s%s"), - mqtt_data, apparent_power_chr, reactive_power_chr, power_factor_chr, (!isnan(energy_frequency)) ? sfrequency : ""); + ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s%s"), + apparent_power_chr, reactive_power_chr, power_factor_chr, (!isnan(energy_frequency)) ? sfrequency : ""); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), mqtt_data, voltage_chr, current_chr); + ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), voltage_chr, current_chr); #ifdef USE_DOMOTICZ if (show_energy_period) { // Only send if telemetry diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 532ecc42d..6a4c11db7 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -740,43 +740,42 @@ void LightState(uint8_t append) int16_t h,s,b; if (append) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + ResponseAppend_P(PSTR(",")); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); + Response_P(PSTR("{")); } GetPowerDevice(scommand, light_device, sizeof(scommand), Settings.flag.device_index_enable); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), - mqtt_data, scommand, GetStateText(light_power), Settings.light_dimmer); + ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(light_power), Settings.light_dimmer); if (light_subtype > LST_SINGLE) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor)); + ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(0, scolor)); // Add status for HSB LightGetHsb(&hsb[0],&hsb[1],&hsb[2], false); // Scale these percentages up to the numbers expected by the client h = round(hsb[0] * 360); s = round(hsb[1] * 100); b = round(hsb[2] * 100); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), mqtt_data, h,s,b); + ResponseAppend_P(PSTR(",\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), h,s,b); // Add status for each channel - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_CHANNEL "\":[" ), mqtt_data); + ResponseAppend_P(PSTR(",\"" D_CMND_CHANNEL "\":[" )); for (uint8_t i = 0; i < light_subtype; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d" ), mqtt_data, (i > 0 ? "," : ""), light_current_color[i] * 100 / 255); + ResponseAppend_P(PSTR("%s%d" ), (i > 0 ? "," : ""), light_current_color[i] * 100 / 255); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]" ), mqtt_data); + ResponseAppend_P(PSTR("%s]")); } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLORTEMPERATURE "\":%d"), mqtt_data, LightGetColorTemp()); + ResponseAppend_P(PSTR(",\"" D_CMND_COLORTEMPERATURE "\":%d"), LightGetColorTemp()); } if (append) { if (light_subtype >= LST_RGB) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_SCHEME "\":%d"), mqtt_data, Settings.light_scheme); + ResponseAppend_P(PSTR(",\"" D_CMND_SCHEME "\":%d"), Settings.light_scheme); } if (LT_WS2812 == light_type) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_WIDTH "\":%d"), mqtt_data, Settings.light_width); + ResponseAppend_P(PSTR(",\"" D_CMND_WIDTH "\":%d"), Settings.light_width); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""), - mqtt_data, GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction)); + ResponseAppend_P(PSTR(",\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""), + GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction)); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } } @@ -949,7 +948,7 @@ void LightAnimate(void) light_new_color[i] = light_current_color[i]; } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"}")); + Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"}")); MqttPublishPrefixTopic_P(TELE, PSTR(D_CMND_WAKEUP)); light_wakeup_active = 0; Settings.light_scheme = LS_POWER; @@ -1319,7 +1318,7 @@ bool LightCommand(void) } } if (!valid_entry && (XdrvMailbox.index <= 2)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, LightGetColor(0, scolor)); + Response_P(S_JSON_COMMAND_SVALUE, command, LightGetColor(0, scolor)); } if (XdrvMailbox.index >= 3) { scolor[0] = '\0'; @@ -1330,7 +1329,7 @@ bool LightCommand(void) snprintf_P(scolor, 25, PSTR("%s%02X"), scolor, Settings.ws_color[XdrvMailbox.index -3][i]); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor); } } else if ((CMND_CHANNEL == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= light_subtype ) ) { @@ -1340,7 +1339,7 @@ bool LightCommand(void) LightSetColor(); coldim = true; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, light_current_color[XdrvMailbox.index -1] * 100 / 255); + Response_P(S_JSON_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, light_current_color[XdrvMailbox.index -1] * 100 / 255); } else if ((CMND_HSBCOLOR == command_code) && ( light_subtype >= LST_RGB)) { bool validHSB = (XdrvMailbox.data_len > 0); @@ -1405,7 +1404,7 @@ bool LightCommand(void) Ws2812ForceUpdate(); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, Ws2812GetColor(XdrvMailbox.index, scolor)); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, Ws2812GetColor(XdrvMailbox.index, scolor)); } else if ((CMND_PIXELS == command_code) && (LT_WS2812 == light_type)) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) { @@ -1414,25 +1413,25 @@ bool LightCommand(void) Ws2812Clear(); light_update = 1; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_pixels); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_pixels); } else if ((CMND_ROTATION == command_code) && (LT_WS2812 == light_type)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings.light_pixels)) { Settings.light_rotation = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_rotation); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_rotation); } else if ((CMND_WIDTH == command_code) && (LT_WS2812 == light_type) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { if (1 == XdrvMailbox.index) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 4)) { Settings.light_width = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_width); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_width); } else { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 32)) { Settings.ws_width[XdrvMailbox.index -2] = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.ws_width[XdrvMailbox.index -2]); + Response_P(S_JSON_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.ws_width[XdrvMailbox.index -2]); } } #endif // USE_WS2812 ************************************************************************ @@ -1454,7 +1453,7 @@ bool LightCommand(void) // Publish state message for Hass if (Settings.flag3.hass_tele_on_power) { MqttPublishTeleState(); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_scheme); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_scheme); } else if (CMND_WAKEUP == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { @@ -1463,7 +1462,7 @@ bool LightCommand(void) light_wakeup_active = 3; Settings.light_scheme = LS_WAKEUP; LightPowerOn(); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_STARTED); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_STARTED); } else if ((CMND_COLORTEMPERATURE == command_code) && ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype))) { // ColorTemp if (option != '\0') { @@ -1479,7 +1478,7 @@ bool LightCommand(void) LightSetColorTemp(XdrvMailbox.payload); coldim = true; } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, LightGetColorTemp()); + Response_P(S_JSON_COMMAND_NVALUE, command, LightGetColorTemp()); } } else if (CMND_DIMMER == command_code) { @@ -1494,7 +1493,7 @@ bool LightCommand(void) light_update = 1; coldim = true; } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_dimmer); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_dimmer); } } else if (CMND_LEDTABLE == command_code) { @@ -1510,7 +1509,7 @@ bool LightCommand(void) } light_update = 1; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.light_correction)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.light_correction)); } else if (CMND_RGBWWTABLE == command_code) { bool validtable = (XdrvMailbox.data_len > 0); @@ -1536,7 +1535,7 @@ bool LightCommand(void) for (uint8_t i = 0; i < LST_RGBWC; i++) { snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor); } else if (CMND_FADE == command_code) { switch (XdrvMailbox.payload) { @@ -1548,7 +1547,7 @@ bool LightCommand(void) Settings.light_fade ^= 1; break; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.light_fade)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.light_fade)); } else if (CMND_SPEED == command_code) { // 1 - fast, 20 - very slow if (('+' == option) && (Settings.light_speed > 1)) { @@ -1560,20 +1559,19 @@ bool LightCommand(void) if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= STATES)) { Settings.light_speed = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_speed); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_speed); } else if (CMND_WAKEUPDURATION == command_code) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3001)) { Settings.light_wakeup = XdrvMailbox.payload; light_wakeup_active = 0; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_wakeup); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_wakeup); } 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, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width); + Response_P(PSTR("%s,%d,%d,%d,%d,%d"), scolor, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width); MqttPublishPrefixTopic_P(STAT, XdrvMailbox.topic); mqtt_data[0] = '\0'; } diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index a72bc2764..9592555b8 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -131,19 +131,19 @@ void IrReceiveCheck(void) } else { snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)results.value); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s"), + Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s"), GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, stemp); if (Settings.flag3.receive_raw) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_IR_RAWDATA "\":["), mqtt_data); + ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); uint16_t i; for (i = 1; i < results.rawlen; i++) { - if (i > 1) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); } + if (i > 1) { ResponseAppend_P(PSTR(",")); } uint32_t usecs; for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%d,0,"), mqtt_data, UINT16_MAX); + ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%d"), mqtt_data, usecs); + ResponseAppend_P(PSTR("%d"), usecs); if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } // Quit if char string becomes too long } uint16_t extended_length = results.rawlen - 1; @@ -152,10 +152,10 @@ void IrReceiveCheck(void) // Add two extra entries for multiple larger than UINT16_MAX it is. extended_length += (usecs / (UINT16_MAX + 1)) * 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), mqtt_data, extended_length, i -1, results.overflow); + ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}}"), mqtt_data); + ResponseAppend_P(PSTR("}}")); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); if (iridx) { @@ -516,7 +516,7 @@ bool IrSendCommand(void) } else if (CMND_IRSEND == command_code) { if (XdrvMailbox.data_len) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); if (!strstr(XdrvMailbox.data, "{")) { // If no JSON it must be rawdata // IRSend frequency, rawdata, rawdata ... @@ -540,11 +540,11 @@ bool IrSendCommand(void) irsend_active = true; irsend->sendRaw(raw_array, count, freq); if (!count) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_FAILED); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_FAILED); } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_RAWDATA); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_RAWDATA); } } else { @@ -553,7 +553,7 @@ bool IrSendCommand(void) StaticJsonBuffer<128> jsonBuf; JsonObject &root = jsonBuf.parseObject(dataBufUc); if (!root.success()) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); } else { // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } @@ -588,7 +588,7 @@ bool IrSendCommand(void) irsend->sendPanasonic(bits, data); break; default: irsend_active = false; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED); } } else { @@ -601,7 +601,7 @@ bool IrSendCommand(void) error = true; } if (error) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); } } #ifdef USE_IR_HVAC @@ -618,10 +618,10 @@ bool IrSendCommand(void) StaticJsonBuffer<164> jsonBufer; JsonObject &root = jsonBufer.parseObject(dataBufUc); if (!root.success()) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); HVAC_Vendor = root[D_JSON_IRHVAC_VENDOR]; HVAC_Power = root[D_JSON_IRHVAC_POWER]; HVAC_Mode = root[D_JSON_IRHVAC_MODE]; @@ -650,7 +650,7 @@ bool IrSendCommand(void) error = true; } if (error) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); } } #endif // USE_IR_HVAC diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index c4b4d209b..14947fd77 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -208,17 +208,17 @@ void SonoffBridgeReceivedRaw(void) if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } // Bucket sniffing - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); + Response_P(PSTR("{\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); for (int i = 0; i < serial_in_byte_counter; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02X"), mqtt_data, serial_in_buffer[i]); + ResponseAppend_P(PSTR("%02X"), serial_in_buffer[i]); if (0xB1 == serial_in_buffer[1]) { if ((i > 3) && buckets) { buckets--; } if ((i < 3) || (buckets % 2) || (i == serial_in_byte_counter -2)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s "), mqtt_data); + ResponseAppend_P(PSTR(" ")); } } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}}"), mqtt_data); + ResponseAppend_P(PSTR("\"}}")); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW)); XdrvRulesProcess(); } @@ -228,7 +228,7 @@ void SonoffBridgeReceivedRaw(void) void SonoffBridgeLearnFailed(void) { 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_JSON_LEARN_FAILED); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_JSON_LEARN_FAILED); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); } @@ -254,7 +254,7 @@ void SonoffBridgeReceived(void) for (uint8_t 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), S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_JSON_LEARNED); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_JSON_LEARNED); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); } else { SonoffBridgeLearnFailed(); @@ -288,7 +288,7 @@ void SonoffBridgeReceived(void) } else { snprintf_P(stemp, sizeof(stemp), PSTR("\"%06X\""), received_id); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"), + Response_P(PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"), sync_time, low_time, high_time, stemp, rfkey); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); XdrvRulesProcess(); @@ -470,7 +470,7 @@ bool SonoffBridgeCommand(void) } else { snprintf_P(stemp, sizeof(stemp), PSTR("\"#%X\""), code); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, stemp); + Response_P(S_JSON_COMMAND_XVALUE, command, stemp); } else if ((CMND_RFKEY == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 16)) { unsigned long now = millis(); @@ -478,11 +478,11 @@ bool SonoffBridgeCommand(void) sonoff_bridge_learn_active = 0; if (2 == XdrvMailbox.payload) { // Learn RF data SonoffBridgeLearn(XdrvMailbox.index); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_START_LEARNING); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_START_LEARNING); } else if (3 == XdrvMailbox.payload) { // Unlearn RF data Settings.rf_code[XdrvMailbox.index][0] = 0; // Reset sync_time MSB - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_SET_TO_DEFAULT); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_SET_TO_DEFAULT); } else if (4 == XdrvMailbox.payload) { // Save RF data provided by RFSync, RfLow, RfHigh and last RfCode for (uint8_t i = 0; i < 6; i++) { @@ -491,7 +491,7 @@ bool SonoffBridgeCommand(void) Settings.rf_code[XdrvMailbox.index][6] = (sonoff_bridge_last_send_code >> 16) & 0xff; Settings.rf_code[XdrvMailbox.index][7] = (sonoff_bridge_last_send_code >> 8) & 0xff; Settings.rf_code[XdrvMailbox.index][8] = sonoff_bridge_last_send_code & 0xff; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_SAVED); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_SAVED); } else if (5 == XdrvMailbox.payload) { // Show default or learned RF data uint8_t key = XdrvMailbox.index; uint8_t index = (0 == Settings.rf_code[key][0]) ? 0 : key; // Use default if sync_time MSB = 0 @@ -505,19 +505,19 @@ bool SonoffBridgeCommand(void) } else { code |= Settings.rf_code[index][8]; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\"}}"), + Response_P(PSTR("{\"%s%d\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\"}}"), command, XdrvMailbox.index, sync_time, low_time, high_time, code); } else { if ((1 == XdrvMailbox.payload) || (0 == Settings.rf_code[XdrvMailbox.index][0])) { // Test sync_time MSB SonoffBridgeSend(0, XdrvMailbox.index); // Send default RF data - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_DEFAULT_SENT); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_DEFAULT_SENT); } else { SonoffBridgeSend(XdrvMailbox.index, 0); // Send learned RF data - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_LEARNED_SENT); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_LEARNED_SENT); } } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, sonoff_bridge_learn_key, D_JSON_LEARNING_ACTIVE); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, sonoff_bridge_learn_key, D_JSON_LEARNING_ACTIVE); } } else if (CMND_RFRAW == command_code) { @@ -548,7 +548,7 @@ bool SonoffBridgeCommand(void) sonoff_bridge_receive_raw_flag = 1; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(sonoff_bridge_receive_raw_flag)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(sonoff_bridge_receive_raw_flag)); } else serviced = false; // Unknown command return serviced; diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 799b2d4b8..21c191699 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -79,8 +79,7 @@ void MqttPublishDomoticzFanState() int fan_speed = GetFanspeed(); snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fan_speed * 10); - snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE, - (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); + Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); MqttPublish(domoticz_in_topic); fan_debounce = millis(); @@ -106,8 +105,7 @@ void MqttPublishDomoticzPowerState(uint8_t device) char svalue[8]; // Dimmer value snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); - snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE, - (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); + Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); MqttPublish(domoticz_in_topic); } } @@ -301,31 +299,31 @@ bool DomoticzCommand(void) Settings.domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DOMOTICZ_COMMAND_INDEX_LVALUE, command, XdrvMailbox.index, Settings.domoticz_relay_idx[XdrvMailbox.index -1]); + Response_P(S_JSON_DOMOTICZ_COMMAND_INDEX_LVALUE, command, XdrvMailbox.index, Settings.domoticz_relay_idx[XdrvMailbox.index -1]); } else if ((CMND_KEYIDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { if (XdrvMailbox.payload >= 0) { Settings.domoticz_key_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DOMOTICZ_COMMAND_INDEX_LVALUE, command, XdrvMailbox.index, Settings.domoticz_key_idx[XdrvMailbox.index -1]); + Response_P(S_JSON_DOMOTICZ_COMMAND_INDEX_LVALUE, command, XdrvMailbox.index, Settings.domoticz_key_idx[XdrvMailbox.index -1]); } else if ((CMND_SWITCHIDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { if (XdrvMailbox.payload >= 0) { Settings.domoticz_switch_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.domoticz_switch_idx[XdrvMailbox.index -1]); + Response_P(S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.domoticz_switch_idx[XdrvMailbox.index -1]); } else if ((CMND_SENSORIDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= DZ_MAX_SENSORS)) { if (XdrvMailbox.payload >= 0) { Settings.domoticz_sensor_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.domoticz_sensor_idx[XdrvMailbox.index -1]); + Response_P(S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.domoticz_sensor_idx[XdrvMailbox.index -1]); } else if (CMND_UPDATETIMER == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { Settings.domoticz_update_timer = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ "%s\":%d}"), command, Settings.domoticz_update_timer); + Response_P(PSTR("{\"" D_CMND_DOMOTICZ "%s\":%d}"), command, Settings.domoticz_update_timer); } else serviced = false; // Unknown command } @@ -340,7 +338,7 @@ bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg if (device <= MAX_DOMOTICZ_IDX) { 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\"}"), + Response_P(PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (2 == state) ? "Toggle" : "On" : "Off"); MqttPublish(domoticz_in_topic); result = 1; @@ -375,14 +373,14 @@ uint8_t DomoticzHumidityState(char *hum) void DomoticzSensor(uint8_t idx, char *data) { if (Settings.domoticz_sensor_idx[idx]) { - char dmess[90]; + char dmess[100]; memcpy(dmess, mqtt_data, sizeof(dmess)); if (DZ_AIRQUALITY == idx) { - snprintf_P(mqtt_data, sizeof(dmess), PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), + Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), Settings.domoticz_sensor_idx[idx], data, DomoticzBatteryQuality(), DomoticzRssiQuality()); } else { - snprintf_P(mqtt_data, sizeof(dmess), DOMOTICZ_MESSAGE, + Response_P(DOMOTICZ_MESSAGE, Settings.domoticz_sensor_idx[idx], 0, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); } MqttPublish(domoticz_in_topic); diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index d39e7a6eb..bf3221025 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -68,13 +68,13 @@ void SerialBridgeInput(void) if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) { serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // Serial data completed if (!serial_bridge_raw) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), serial_bridge_buffer); + Response_P(PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), serial_bridge_buffer); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"")); + Response_P(PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"")); for (int i = 0; i < serial_bridge_in_byte_counter; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_bridge_buffer[i]); + ResponseAppend_P(PSTR("%02x"), serial_bridge_buffer[i]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); + ResponseAppend_P(PSTR("\"}")); } MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); // XdrvRulesProcess(); @@ -144,7 +144,7 @@ bool SerialBridgeCommand(void) codes += 2; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } } else if (CMND_SBAUDRATE == command_code) { @@ -155,7 +155,7 @@ bool SerialBridgeCommand(void) Settings.sbaudrate = (1 == XdrvMailbox.payload) ? SOFT_BAUDRATE / 1200 : baud; SerialBridgeSerial->begin(Settings.sbaudrate * 1200); // Reinitialize serial port with new baud rate } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.sbaudrate * 1200); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.sbaudrate * 1200); } else serviced = false; // Unknown command diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index a3ab51a1b..adaaf0603 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -325,11 +325,11 @@ void PrepShowTimer(uint8_t index) sign[0] = '-'; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_MODE "\":%d,\"" D_JSON_TIMER_TIME "\":\"%s%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), - mqtt_data, index, xtimer.arm, xtimer.mode, sign, hour, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); + ResponseAppend_P(PSTR("\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_MODE "\":%d,\"" D_JSON_TIMER_TIME "\":\"%s%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), + index, xtimer.arm, xtimer.mode, sign, hour, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_TIME "\":\"%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), - mqtt_data, index, xtimer.arm, xtimer.time / 60, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); + ResponseAppend_P(PSTR("\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_TIME "\":\"%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), + index, xtimer.arm, xtimer.time / 60, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); #endif // USE_SUNRISE } @@ -365,7 +365,7 @@ bool TimerCommand(void) StaticJsonBuffer<256> jsonBuffer; JsonObject& root = jsonBuffer.parseObject(dataBufUc); if (!root.success()) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_INVALID_JSON "\"}"), index); // JSON decode failed + Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_INVALID_JSON "\"}"), index); // JSON decode failed error = 1; } else { @@ -439,16 +439,16 @@ bool TimerCommand(void) } #ifndef USE_RULES } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_TIMER_NO_DEVICE "\"}"), index); // No outputs defined so nothing to control + Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_TIMER_NO_DEVICE "\"}"), index); // No outputs defined so nothing to control error = 1; } #endif } } if (!error) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); + Response_P(PSTR("{")); PrepShowTimer(index); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } } else if (CMND_TIMERS == command_code) { @@ -461,21 +461,21 @@ bool TimerCommand(void) } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag3.timers_enable)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag3.timers_enable)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, command); uint8_t jsflg = 0; uint8_t lines = 1; for (uint8_t i = 0; i < MAX_TIMERS; i++) { if (!jsflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_TIMERS "%d\":{"), lines++); + Response_P(PSTR("{\"" D_CMND_TIMERS "%d\":{"), lines++); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + ResponseAppend_P(PSTR(",")); } jsflg++; PrepShowTimer(i +1); if (jsflg > 3) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}}"), mqtt_data); + ResponseAppend_P(PSTR("}}")); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_TIMERS)); jsflg = 0; } @@ -489,7 +489,7 @@ bool TimerCommand(void) } char lbuff[33]; dtostrfd(((double)Settings.longitude) /1000000, 6, lbuff); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, lbuff); + Response_P(S_JSON_COMMAND_SVALUE, command, lbuff); } else if (CMND_LATITUDE == command_code) { if (XdrvMailbox.data_len) { @@ -497,7 +497,7 @@ bool TimerCommand(void) } char lbuff[33]; dtostrfd(((double)Settings.latitude) /1000000, 6, lbuff); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, lbuff); + Response_P(S_JSON_COMMAND_SVALUE, command, lbuff); } #endif else serviced = false; // Unknown command diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 4d13bf6b9..b2761a2d4 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -369,7 +369,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: %s performs \"%s\""), event_trigger.c_str(), command); -// snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, D_CMND_RULE, D_JSON_INITIATED); +// Response_P(S_JSON_COMMAND_SVALUE, D_CMND_RULE, D_JSON_INITIATED); // MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RULE)); ExecuteCommand(command, SRC_RULE); @@ -544,7 +544,7 @@ void RulesEvery100ms(void) tele_period = tele_period_save; if (strlen(mqtt_data)) { mqtt_data[0] = '{'; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); RulesProcess(); } } @@ -1139,15 +1139,15 @@ bool RulesCommand(void) } mqtt_data[0] = '\0'; for (uint8_t i = 0; i < MAX_RULE_TIMERS; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%c\"T%d\":%d"), mqtt_data, (i) ? ',' : '{', i +1, (rules_timer[i]) ? (rules_timer[i] - millis()) / 1000 : 0); + ResponseAppend_P(PSTR("%c\"T%d\":%d"), (i) ? ',' : '{', i +1, (rules_timer[i]) ? (rules_timer[i] - millis()) / 1000 : 0); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } else if (CMND_EVENT == command_code) { if (XdrvMailbox.data_len > 0) { strlcpy(event_data, XdrvMailbox.data, sizeof(event_data)); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } else if ((CMND_VAR == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { @@ -1158,7 +1158,7 @@ bool RulesCommand(void) #endif //USE_EXPRESSION bitSet(vars_event, index -1); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } else if ((CMND_MEM == command_code) && (index > 0) && (index <= MAX_RULE_MEMS)) { if (XdrvMailbox.data_len > 0) { @@ -1169,13 +1169,13 @@ bool RulesCommand(void) #endif //USE_EXPRESSION bitSet(mems_event, index -1); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]); } else if (CMND_CALC_RESOLUTION == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 7)) { Settings.flag2.calc_resolution = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.calc_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.calc_resolution); } else if ((CMND_ADD == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { @@ -1183,7 +1183,7 @@ bool RulesCommand(void) dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]); bitSet(vars_event, index -1); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } else if ((CMND_SUB == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { @@ -1191,7 +1191,7 @@ bool RulesCommand(void) dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]); bitSet(vars_event, index -1); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } else if ((CMND_MULT == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { @@ -1199,7 +1199,7 @@ bool RulesCommand(void) dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]); bitSet(vars_event, index -1); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } else if ((CMND_SCALE == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { @@ -1216,14 +1216,14 @@ bool RulesCommand(void) bitSet(vars_event, index -1); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); #ifdef SUPPORT_MQTT_EVENT } else if (CMND_SUBSCRIBE == command_code) { //MQTT Subscribe command. Subscribe , [, ] String result = RulesSubscribe(XdrvMailbox.data, XdrvMailbox.data_len); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, result.c_str()); + Response_P(S_JSON_COMMAND_SVALUE, command, result.c_str()); } else if (CMND_UNSUBSCRIBE == command_code) { //MQTT Un-subscribe command. UnSubscribe String result = RulesUnsubscribe(XdrvMailbox.data, XdrvMailbox.data_len); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, result.c_str()); + Response_P(S_JSON_COMMAND_SVALUE, command, result.c_str()); #endif //SUPPORT_MQTT_EVENT } else serviced = false; // Unknown command diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 639c74499..4437a91eb 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -540,8 +540,7 @@ void HAssAnnounceStatusSensor(void) void HAssPublishStatus(void) { - snprintf_P(mqtt_data, sizeof(mqtt_data), - PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"," + Response_P(PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"," "\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," "\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"," "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d," diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index f14680939..89dde70d1 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -465,7 +465,7 @@ void DisplayText(void) break; default: // unknown escape - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("Unknown Escape")); + Response_P(PSTR("Unknown Escape")); goto exit; break; } @@ -921,7 +921,7 @@ bool DisplayCommand(void) serviced = false; // Unknown command } else if (CMND_DISPLAY == command_code) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" + Response_P(PSTR("{\"" D_CMND_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" D_CMND_DISP_SIZE "\":%d,\"" D_CMND_DISP_FONT "\":%d,\"" D_CMND_DISP_ROTATE "\":%d,\"" D_CMND_DISP_REFRESH "\":%d,\"" D_CMND_DISP_COLS "\":[%d,%d],\"" D_CMND_DISP_ROWS "\":%d}}"), Settings.display_model, Settings.display_mode, Settings.display_dimmer, Settings.display_size, Settings.display_font, Settings.display_rotate, Settings.display_refresh, Settings.display_cols[0], Settings.display_cols[1], Settings.display_rows); @@ -936,7 +936,7 @@ bool DisplayCommand(void) Settings.display_model = last_display_model; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_model); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_model); } else if (CMND_DISP_MODE == command_code) { #ifdef USE_DISPLAY_MODES1TO5 @@ -964,7 +964,7 @@ bool DisplayCommand(void) } } #endif // USE_DISPLAY_MODES1TO5 - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_mode); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_mode); } else if (CMND_DISP_DIMMER == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { @@ -976,19 +976,19 @@ bool DisplayCommand(void) ExecuteCommandPower(disp_device, POWER_OFF, SRC_DISPLAY); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_dimmer); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_dimmer); } else if (CMND_DISP_SIZE == command_code) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { Settings.display_size = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_size); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_size); } else if (CMND_DISP_FONT == command_code) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { Settings.display_font = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_font); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_font); } else if (CMND_DISP_ROTATE == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { @@ -1011,7 +1011,7 @@ bool DisplayCommand(void) #endif // USE_DISPLAY_MODES1TO5 } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rotate); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rotate); } else if (CMND_DISP_TEXT == command_code) { mqtt_data[0] = '\0'; @@ -1026,23 +1026,23 @@ bool DisplayCommand(void) } #endif // USE_DISPLAY_MODES1TO5 } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("No Text")); + Response_P(PSTR("No Text")); } if (mqtt_data[0] == '\0') { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_VALUE, command, XdrvMailbox.data); + Response_P(S_JSON_DISPLAY_COMMAND_VALUE, command, XdrvMailbox.data); } } else if ((CMND_DISP_ADDRESS == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { Settings.display_address[XdrvMailbox.index -1] = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_address[XdrvMailbox.index -1]); + Response_P(S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_address[XdrvMailbox.index -1]); } else if (CMND_DISP_REFRESH == command_code) { if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) { Settings.display_refresh = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_refresh); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_refresh); } else if ((CMND_DISP_COLS == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) { @@ -1054,7 +1054,7 @@ bool DisplayCommand(void) } #endif // USE_DISPLAY_MODES1TO5 } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_cols[XdrvMailbox.index -1]); + Response_P(S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_cols[XdrvMailbox.index -1]); } else if (CMND_DISP_ROWS == command_code) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) { @@ -1064,7 +1064,7 @@ bool DisplayCommand(void) DisplayReAllocScreenBuffer(); #endif // USE_DISPLAY_MODES1TO5 } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rows); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rows); } else serviced = false; // Unknown command } diff --git a/sonoff/xdrv_14_mp3.ino b/sonoff/xdrv_14_mp3.ino index 4e55cddc5..5e74b7122 100644 --- a/sonoff/xdrv_14_mp3.ino +++ b/sonoff/xdrv_14_mp3.ino @@ -200,7 +200,7 @@ bool MP3PlayerCmd(void) { if (command_code == CMND_MP3_DEVICE) { MP3_CMD(MP3_CMD_DEVICE, XdrvMailbox.payload); } if (command_code == CMND_MP3_DAC) { MP3_CMD(MP3_CMD_DAC, XdrvMailbox.payload); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); + Response_P(S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); break; case CMND_MP3_PLAY: case CMND_MP3_PAUSE: @@ -211,7 +211,7 @@ bool MP3PlayerCmd(void) { if (command_code == CMND_MP3_PAUSE) { MP3_CMD(MP3_CMD_PAUSE, 0); } if (command_code == CMND_MP3_STOP) { MP3_CMD(MP3_CMD_STOP, 0); } if (command_code == CMND_MP3_RESET) { MP3_CMD(MP3_CMD_RESET, 0); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); + Response_P(S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); break; default: // else for Unknown command diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index de91a02b4..1a27219c8 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -60,7 +60,7 @@ void PCA9685_Reset(void) PCA9685_SetPWM(pin,0,false); pca9685_pin_pwm_value[pin] = 0; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); + Response_P(PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); } void PCA9685_SetPWMfreq(double freq) { @@ -127,11 +127,11 @@ bool PCA9685_Command(void) uint16_t new_freq = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); if ((new_freq >= 24) && (new_freq <= 1526)) { PCA9685_SetPWMfreq(new_freq); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}"),new_freq); + Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}"),new_freq); return serviced; } } else { // No parameter was given for setfreq, so we return current setting - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PWMF\":%i}}"),pca9685_freq); + Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i}}"),pca9685_freq); return serviced; } } @@ -141,20 +141,20 @@ bool PCA9685_Command(void) if (paramcount > 2) { if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "ON")) { PCA9685_SetPWM(pin, 4096, false); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,4096); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,4096); serviced = true; return serviced; } if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "OFF")) { PCA9685_SetPWM(pin, 0, false); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,0); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,0); serviced = true; return serviced; } uint16_t pwm = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); if ((pin >= 0 && pin <= 15) && (pwm >= 0 && pwm <= 4096)) { PCA9685_SetPWM(pin, pwm, false); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,pwm); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,pwm); serviced = true; return serviced; } @@ -166,12 +166,12 @@ bool PCA9685_Command(void) void PCA9685_OutputTelemetry(bool telemetry) { if (0 == pca9685_detected) { return; } // We do not do this if the PCA9685 has not been detected - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"PCA9685\": {"), GetDateAndTime(DT_LOCAL).c_str()); - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"PWM_FREQ\":%i,"),mqtt_data,pca9685_freq); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"PCA9685\": {"), GetDateAndTime(DT_LOCAL).c_str()); + ResponseAppend_P(PSTR("\"PWM_FREQ\":%i,"),pca9685_freq); for (uint8_t pin=0;pin<16;pin++) { - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"PWM%i\":%i,"),mqtt_data,pin,pca9685_pin_pwm_value[pin]); + ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pca9685_pin_pwm_value[pin]); } - snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"END\":1}}"),mqtt_data); + ResponseAppend_P(PSTR("\"END\":1}}")); if (telemetry) { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index 300a156f5..aaa594b2a 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -61,7 +61,7 @@ void RfReceiveCheck(void) } else { snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), + Response_P(PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), stemp, bits, protocol, delay); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); XdrvRulesProcess(); @@ -145,7 +145,7 @@ bool RfSendCommand(void) if (!bits) { bits = 24; } // Default 24 bits if (data) { mySwitch.send(data, bits); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_DONE "\"}")); + Response_P(PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_DONE "\"}")); } else { error = true; } @@ -153,7 +153,7 @@ bool RfSendCommand(void) error = true; } if (error) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_DATA ", " D_JSON_RF_BITS ", " D_JSON_RF_PROTOCOL ", " D_JSON_RF_REPEAT " " D_JSON_OR " " D_JSON_RF_PULSE "\"}")); + Response_P(PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_DATA ", " D_JSON_RF_BITS ", " D_JSON_RF_PROTOCOL ", " D_JSON_RF_REPEAT " " D_JSON_OR " " D_JSON_RF_PULSE "\"}")); } } else serviced = false; // Unknown command diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_99_debug.ino index e9da144b8..08a73d4da 100644 --- a/sonoff/xdrv_99_debug.ino +++ b/sonoff/xdrv_99_debug.ino @@ -419,28 +419,28 @@ bool DebugCommand(void) } else if (CMND_HELP == command_code) { AddLog_P(LOG_LEVEL_INFO, kDebugCommands); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } else if (CMND_RTCDUMP == command_code) { DebugRtcDump(XdrvMailbox.data); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } else if (CMND_CFGDUMP == command_code) { DebugCfgDump(XdrvMailbox.data); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } else if (CMND_CFGPEEK == command_code) { DebugCfgPeek(XdrvMailbox.data); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } else if (CMND_CFGPOKE == command_code) { DebugCfgPoke(XdrvMailbox.data); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } #ifdef USE_DEBUG_SETTING_NAMES else if (CMND_CFGSHOW == command_code) { DebugCfgShow(XdrvMailbox.payload); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } #endif // USE_DEBUG_SETTING_NAMES #ifdef USE_WEBSERVER @@ -448,13 +448,13 @@ bool DebugCommand(void) if (XdrvMailbox.data_len > 0) { config_xor_on_set = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, config_xor_on_set); + Response_P(S_JSON_COMMAND_NVALUE, command, config_xor_on_set); } #endif // USE_WEBSERVER #ifdef DEBUG_THEO else if (CMND_EXCEPTION == command_code) { if (XdrvMailbox.data_len > 0) ExceptionTest(XdrvMailbox.payload); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } #endif // DEBUG_THEO else if (CMND_CPUCHECK == command_code) { @@ -462,26 +462,26 @@ bool DebugCommand(void) CPU_load_check = XdrvMailbox.payload; CPU_last_millis = CPU_last_loop_time; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, CPU_load_check); + Response_P(S_JSON_COMMAND_NVALUE, command, CPU_load_check); } else if (CMND_FREEMEM == command_code) { if (XdrvMailbox.data_len > 0) { CPU_show_freemem = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, CPU_show_freemem); + Response_P(S_JSON_COMMAND_NVALUE, command, CPU_show_freemem); } else if ((CMND_SETSENSOR == command_code) && (XdrvMailbox.index < MAX_XSNS_DRIVERS)) { if ((XdrvMailbox.payload >= 0) && XsnsPresent(XdrvMailbox.index)) { bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); if (1 == XdrvMailbox.payload) { restart_flag = 2; } // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, XsnsGetSensors().c_str()); + Response_P(S_JSON_COMMAND_XVALUE, command, XsnsGetSensors().c_str()); } else if (CMND_FLASHMODE == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { SetFlashMode(XdrvMailbox.payload); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, ESP.getFlashChipMode()); + Response_P(S_JSON_COMMAND_NVALUE, command, ESP.getFlashChipMode()); } else serviced = false; // Unknown command From dcc69bdff09717e5b78aa970f955b9682870fbdb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Mar 2019 17:57:31 +0100 Subject: [PATCH 1173/2222] Shrink code/flash space pt.2/2 Shrink code/flash space pt.2/2 --- sonoff/i18n.h | 12 +++--- sonoff/sonoff.ino | 4 +- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xsns_01_counter.ino | 6 +-- sonoff/xsns_02_analog.ino | 4 +- sonoff/xsns_04_snfsc.ino | 4 +- sonoff/xsns_05_ds18b20.ino | 2 +- sonoff/xsns_05_ds18x20.ino | 4 +- sonoff/xsns_05_ds18x20_legacy.ino | 8 ++-- sonoff/xsns_06_dht.ino | 2 +- sonoff/xsns_07_sht1x.ino | 2 +- sonoff/xsns_08_htu21.ino | 2 +- sonoff/xsns_09_bmp.ino | 7 ++-- sonoff/xsns_10_bh1750.ino | 2 +- sonoff/xsns_11_veml6070.ino | 8 ++-- sonoff/xsns_12_ads1115.ino | 10 ++--- sonoff/xsns_12_ads1115_i2cdev.ino | 9 ++--- sonoff/xsns_13_ina219.ino | 6 +-- sonoff/xsns_14_sht3x.ino | 2 +- sonoff/xsns_15_mhz19.ino | 22 +++++------ sonoff/xsns_16_tsl2561.ino | 4 +- sonoff/xsns_17_senseair.ino | 6 +-- sonoff/xsns_18_pms5003.ino | 2 +- sonoff/xsns_19_mgs.ino | 16 ++++---- sonoff/xsns_20_novasds.ino | 2 +- sonoff/xsns_21_sgp30.ino | 2 +- sonoff/xsns_22_sr04.ino | 2 +- sonoff/xsns_23_sdm120.ino | 8 ++-- sonoff/xsns_24_si1145.ino | 4 +- sonoff/xsns_25_sdm630.ino | 4 +- sonoff/xsns_26_lm75ad.ino | 2 +- sonoff/xsns_27_apds9960.ino | 12 +++--- sonoff/xsns_29_mcp230xx.ino | 65 +++++++++++++++---------------- sonoff/xsns_30_mpr121.ino | 8 ++-- sonoff/xsns_31_ccs811.ino | 2 +- sonoff/xsns_32_mpu6050.ino | 4 +- sonoff/xsns_34_hx711.ino | 8 ++-- sonoff/xsns_35_tx20.ino | 4 +- sonoff/xsns_36_mgc3130.ino | 8 ++-- sonoff/xsns_37_rfsensor.ino | 23 ++++++----- sonoff/xsns_38_az7798.ino | 2 +- sonoff/xsns_39_max31855.ino | 4 +- sonoff/xsns_40_pn532.ino | 12 +++--- sonoff/xsns_41_max44009.ino | 4 +- sonoff/xsns_42_scd30.ino | 9 +++-- 45 files changed, 163 insertions(+), 172 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index ded4ccd43..ca5e2b79a 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -506,14 +506,14 @@ const char S_JSON_COMMAND_INDEX_ASTERIX[] PROGMEM = "{\"%s%d\":\"" D_A const char S_JSON_COMMAND_INDEX_SVALUE_SVALUE[] PROGMEM = "{\"%s%d\":\"%s%s\"}"; const char S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE[] PROGMEM = "{\"%s%d\":\"%d (" D_JSON_ACTIVE " %d)\"}"; -const char S_JSON_SENSOR_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":%d}"; -const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":\"%s\"}"; +const char S_JSON_SENSOR_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":%d}"; +const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":\"%s\"}"; -const char S_JSON_DRIVER_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":%d}"; -const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":\"%s\"}"; +const char S_JSON_DRIVER_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":%d}"; +const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":\"%s\"}"; -const char JSON_SNS_TEMP[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"; -const char JSON_SNS_TEMPHUM[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"; +const char JSON_SNS_TEMP[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"; +const char JSON_SNS_TEMPHUM[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"; const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x"; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index cf11abcff..458b12ed6 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1207,7 +1207,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) snprintf_P(stemp1, sizeof(stemp1), kWifiConfig[Settings.sta_config]); Response_P(PSTR("{\"" D_CMND_WIFICONFIG "\":\"%s " D_JSON_SELECTED "\"}"), stemp1); if (WifiState() > WIFI_RESTART) { -// snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s after restart"), mqtt_data); +// ResponseAppend_P(PSTR(" after restart")); restart_flag = 2; } } else { @@ -1478,7 +1478,7 @@ bool SendKey(uint8_t key, uint8_t device, uint8_t state) #endif // USE_DOMOTICZ result = !Settings.flag3.button_switch_force_local; } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); + Response_P(PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); result = XdrvRulesProcess(); } #ifdef USE_KNX diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index adaaf0603..59d9300f4 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -287,7 +287,7 @@ void TimerEverySecond(void) Settings.timer[i].arm = xtimer.repeat; #ifdef USE_RULES if (3 == xtimer.power) { // Blink becomes Rule disregarding device and allowing use of Backlog commands - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1); + Response_P(PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1); XdrvRulesProcess(); } else #endif // USE_RULES diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index 901793fec..eadd9a4b9 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -107,11 +107,11 @@ void CounterShow(bool json) if (json) { if (!header) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"COUNTER\":{"), mqtt_data); + ResponseAppend_P(PSTR(",\"COUNTER\":{")); stemp[0] = '\0'; } header++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"C%d\":%s"), mqtt_data, stemp, i +1, counter); + ResponseAppend_P(PSTR("%s\"C%d\":%s"), stemp, i +1, counter); strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_DOMOTICZ if ((0 == tele_period) && (1 == dsxflg)) { @@ -131,7 +131,7 @@ void CounterShow(bool json) } if (json) { if (header) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } } } diff --git a/sonoff/xsns_02_analog.ino b/sonoff/xsns_02_analog.ino index 79a622f0f..9c6c5074e 100644 --- a/sonoff/xsns_02_analog.ino +++ b/sonoff/xsns_02_analog.ino @@ -44,7 +44,7 @@ void AdcEvery250ms(void) if ((new_value < adc_last_value -10) || (new_value > adc_last_value +10)) { adc_last_value = new_value; uint16_t value = adc_last_value / 10; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); + Response_P(PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); XdrvRulesProcess(); } } @@ -55,7 +55,7 @@ void AdcShow(bool json) uint16_t analog = AdcRead(); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ANALOG\":{\"A0\":%d}"), mqtt_data, analog); + ResponseAppend_P(PSTR(",\"ANALOG\":{\"A0\":%d}"), analog); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_SNS_ANALOG, "", 0, analog); diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index 98d1f6276..051640f63 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -120,8 +120,8 @@ void SonoffScShow(bool json) dtostrfd(h, Settings.flag2.humidity_resolution, humidity); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SonoffSC\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), - mqtt_data, temperature, humidity, sc_value[2], sc_value[3], sc_value[4]); + ResponseAppend_P(PSTR(",\"SonoffSC\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), + temperature, humidity, sc_value[2], sc_value[3], sc_value[4]); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzTempHumSensor(temperature, humidity); diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index 9e82a8e9b..d68664570 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -205,7 +205,7 @@ void Ds18b20Show(bool json) char temperature[33]; dtostrfd(ds18b20_temperature, Settings.flag2.temperature_resolution, temperature); if(json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMP, mqtt_data, ds18b20_types, temperature); + ResponseAppend_P(JSON_SNS_TEMP, ds18b20_types, temperature); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_TEMP, temperature); diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index e2ff0767c..7a67f80a9 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -432,13 +432,13 @@ void Ds18x20Show(bool json) if (json) { if (1 == ds18x20_sensors) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, ds18x20_types, temperature); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, temperature); } else { char address[17]; for (uint8_t j = 0; j < 6; j++) { sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); // Skip sensor type and crc } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, ds18x20_types, address, temperature); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); } #ifdef USE_DOMOTICZ if ((0 == tele_period) && (0 == i)) { diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index 2b157cfb7..9ecdcbff5 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -178,12 +178,12 @@ void Ds18x20Show(bool json) if (json) { if (!dsxflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"DS18x20\":{"), mqtt_data); + ResponseAppend_P(PSTR(",\"DS18x20\":{")); stemp[0] = '\0'; } dsxflg++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"DS%d\":{\"" D_JSON_TYPE "\":\"%s\",\"" D_JSON_ADDRESS "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), - mqtt_data, stemp, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), temperature); + ResponseAppend_P(PSTR("%s\"DS%d\":{\"" D_JSON_TYPE "\":\"%s\",\"" D_JSON_ADDRESS "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), + stemp, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), temperature); strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_DOMOTICZ if ((0 == tele_period) && (1 == dsxflg)) { @@ -205,7 +205,7 @@ void Ds18x20Show(bool json) } if (json) { if (dsxflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } } Ds18x20Search(); // Check for changes in sensors number diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index 016f012f0..00bbf7f15 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -213,7 +213,7 @@ void DhtShow(bool json) dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, Dht[i].stype, temperature, humidity); + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); #ifdef USE_DOMOTICZ if ((0 == tele_period) && (0 == i)) { DomoticzTempHumSensor(temperature, humidity); diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index 0967560b1..12d7f4e79 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -194,7 +194,7 @@ void ShtShow(bool json) dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, sht_types, temperature, humidity); + ResponseAppend_P(JSON_SNS_TEMPHUM, sht_types, temperature, humidity); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzTempHumSensor(temperature, humidity); diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index 1ef208d61..c12a068c9 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -254,7 +254,7 @@ void HtuShow(bool json) dtostrfd(htu_humidity, Settings.flag2.humidity_resolution, humidity); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, htu_types, temperature, humidity); + ResponseAppend_P(JSON_SNS_TEMPHUM, htu_types, temperature, humidity); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzTempHumSensor(temperature, humidity); diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index 22b0cd365..cc738f977 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -566,8 +566,7 @@ void BmpShow(bool json) char json_gas[40]; snprintf_P(json_gas, sizeof(json_gas), PSTR(",\"" D_JSON_GAS "\":%s"), gas_resistance); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), - mqtt_data, + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", @@ -575,8 +574,8 @@ void BmpShow(bool json) (Settings.altitude != 0) ? json_sealevel : "", (bmp_sensors[bmp_idx].bmp_model >= 3) ? json_gas : ""); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), - mqtt_data, name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), + name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); #endif // USE_BME680 #ifdef USE_DOMOTICZ diff --git a/sonoff/xsns_10_bh1750.ino b/sonoff/xsns_10_bh1750.ino index d4ffa3a10..5398422b7 100644 --- a/sonoff/xsns_10_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -92,7 +92,7 @@ void Bh1750Show(bool json) { if (bh1750_valid) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ILLUMINANCE "\":%d}"), mqtt_data, bh1750_types, bh1750_illuminance); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%d}"), bh1750_types, bh1750_illuminance); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, bh1750_illuminance); diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index 2222cc335..b6f50d05d 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -277,11 +277,11 @@ void Veml6070Show(bool json) dtostrfd(uvpower, 3, str_uvpower); if (json) { #ifdef USE_VEML6070_SHOW_RAW - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), - mqtt_data, veml6070_name, str_uvlevel, str_uvrisk, str_uvrisk_text, str_uvpower); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), + veml6070_name, str_uvlevel, str_uvrisk, str_uvrisk_text, str_uvpower); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), - mqtt_data, veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), + veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); #endif // USE_VEML6070_SHOW_RAW #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); } diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index 7c674debe..d40b72849 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -188,13 +188,13 @@ void Ads1115GetValues(uint8_t address) void Ads1115toJSON(char *comma_j) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s{"), mqtt_data,comma_j); + ResponseAppend_P(PSTR("%s{"), comma_j); char *comma = (char*)""; for (uint8_t i = 0; i < 4; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, comma, i, ads1115_values[i]); + ResponseAppend_P(PSTR("%s\"A%d\":%d"), comma, i, ads1115_values[i]); comma = (char*)","; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } void Ads1115toString(uint8_t address) @@ -212,7 +212,7 @@ void Ads1115Show(bool json) if (!ads1115_type) { return; } if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":["), mqtt_data); + ResponseAppend_P(PSTR(",\"ADS1115\":[")); } char *comma = (char*)""; @@ -234,7 +234,7 @@ void Ads1115Show(bool json) } if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]"), mqtt_data); + ResponseAppend_P(PSTR("]")); } } diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/sonoff/xsns_12_ads1115_i2cdev.ino index 855658647..eb5643c3e 100644 --- a/sonoff/xsns_12_ads1115_i2cdev.ino +++ b/sonoff/xsns_12_ads1115_i2cdev.ino @@ -99,7 +99,6 @@ void Ads1115Detect(void) void Ads1115Show(bool json) { if (ads1115_type) { - char stemp[10]; uint8_t dsxflg = 0; for (uint8_t i = 0; i < 4; i++) { @@ -107,12 +106,10 @@ void Ads1115Show(bool json) if (json) { if (!dsxflg ) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":{"), mqtt_data); - stemp[0] = '\0'; + ResponseAppend_P(PSTR(",\"ADS1115\":{")); } + ResponseAppend_P(PSTR("%s\"A%d\":%d"), (dsxflg) ? "," : "", i, adc_value); dsxflg++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, stemp, i, adc_value); - strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_SNS_ANALOG, "ADS1115", i, adc_value); @@ -121,7 +118,7 @@ void Ads1115Show(bool json) } if (json) { if (dsxflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } } } diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index fa6327f70..0dd7e5398 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -183,7 +183,7 @@ bool Ina219CommandSensor(void) Settings.ina219_mode = XdrvMailbox.payload; restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); return serviced; } @@ -240,8 +240,8 @@ void Ina219Show(bool json) dtostrfd(ina219_current, Settings.flag2.current_resolution, current); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), - mqtt_data, ina219_types, voltage, current, power); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), + ina219_types, voltage, current, power); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_VOLTAGE, voltage); diff --git a/sonoff/xsns_14_sht3x.ino b/sonoff/xsns_14_sht3x.ino index e7aa63007..bdaa43e1a 100755 --- a/sonoff/xsns_14_sht3x.ino +++ b/sonoff/xsns_14_sht3x.ino @@ -110,7 +110,7 @@ void Sht3xShow(bool json) snprintf_P(types, sizeof(types), PSTR("%s-0x%02X"), sht3x_sensors[i].types, sht3x_sensors[i].address); // "SHT3X-0xXX" if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, types, temperature, humidity); + ResponseAppend_P(JSON_SNS_TEMPHUM, types, temperature, humidity); #ifdef USE_DOMOTICZ if ((0 == tele_period) && (0 == i)) { // We want the same first sensor to report to Domoticz in case a read is missed DomoticzTempHumSensor(temperature, humidity); diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 058336f39..00f272a55 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -276,42 +276,42 @@ bool MhzCommandSensor(void) case 0: Settings.SensorBits1.mhz19b_abc_disable = true; MhzSendCmd(MHZ_CMND_ABCDISABLE); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); break; case 1: Settings.SensorBits1.mhz19b_abc_disable = false; MhzSendCmd(MHZ_CMND_ABCENABLE); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); break; case 2: MhzSendCmd(MHZ_CMND_ZEROPOINT); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); break; case 9: MhzSendCmd(MHZ_CMND_RESET); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); break; case 1000: MhzSendCmd(MHZ_CMND_RANGE_1000); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_1000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_1000); break; case 2000: MhzSendCmd(MHZ_CMND_RANGE_2000); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_2000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_2000); break; case 3000: MhzSendCmd(MHZ_CMND_RANGE_3000); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_3000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_3000); break; case 5000: MhzSendCmd(MHZ_CMND_RANGE_5000); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); break; default: if (!Settings.SensorBits1.mhz19b_abc_disable) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); } } @@ -342,7 +342,7 @@ void MhzShow(bool json) GetTextIndexed(model, sizeof(model), mhz_type -1, kMhzModels); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, types, model, mhz_last_ppm, temperature); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), types, model, mhz_last_ppm, temperature); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm); diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index 74f9fb0fb..af1d60d54 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -102,8 +102,8 @@ void Tsl2561Show(bool json) { if (tsl2561_valid) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), - mqtt_data, tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); + ResponseAppend_P(PSTR(",\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), + tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, (tsl2561_milliLux + 500) / 1000); } #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_17_senseair.ino b/sonoff/xsns_17_senseair.ino index b5772a4d1..d11195b50 100644 --- a/sonoff/xsns_17_senseair.ino +++ b/sonoff/xsns_17_senseair.ino @@ -149,11 +149,11 @@ void SenseairShow(bool json) GetTextIndexed(senseair_types, sizeof(senseair_types), senseair_type -1, kSenseairTypes); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_CO2 "\":%d"), mqtt_data, senseair_types, senseair_co2); + ResponseAppend_P(PSTR("%s,\"%s\":{\"" D_JSON_CO2 "\":%d"), senseair_types, senseair_co2); if (senseair_type != 2) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), mqtt_data, temperature, humidity); + ResponseAppend_P(PSTR("%s,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), temperature, humidity); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, senseair_co2); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_18_pms5003.ino b/sonoff/xsns_18_pms5003.ino index 6f9c97711..e77eb0271 100644 --- a/sonoff/xsns_18_pms5003.ino +++ b/sonoff/xsns_18_pms5003.ino @@ -132,7 +132,7 @@ void PmsShow(bool json) { if (pms_valid) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PMS5003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d,\"PB0.3\":%d,\"PB0.5\":%d,\"PB1\":%d,\"PB2.5\":%d,\"PB5\":%d,\"PB10\":%d}"), mqtt_data, + ResponseAppend_P(PSTR(",\"PMS5003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d,\"PB0.3\":%d,\"PB0.5\":%d,\"PB1\":%d,\"PB2.5\":%d,\"PB5\":%d,\"PB10\":%d}"), pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); diff --git a/sonoff/xsns_19_mgs.ino b/sonoff/xsns_19_mgs.ino index 942664b96..30b979eaa 100644 --- a/sonoff/xsns_19_mgs.ino +++ b/sonoff/xsns_19_mgs.ino @@ -64,14 +64,14 @@ void MGSShow(bool json) { char buffer[33]; if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MGS\":{\"NH3\":%s"), mqtt_data, measure_gas(NH3, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"CO\":%s"), mqtt_data, measure_gas(CO, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"NO2\":%s"), mqtt_data, measure_gas(NO2, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"C3H8\":%s"), mqtt_data, measure_gas(C3H8, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"C4H10\":%s"), mqtt_data, measure_gas(C4H10, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"CH4\":%s"), mqtt_data, measure_gas(GAS_CH4, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"H2\":%s"), mqtt_data, measure_gas(H2, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"C2H5OH\":%s}"), mqtt_data, measure_gas(C2H5OH, buffer)); + ResponseAppend_P(PSTR(",\"MGS\":{\"NH3\":%s"), measure_gas(NH3, buffer)); + ResponseAppend_P(PSTR(",\"CO\":%s"), measure_gas(CO, buffer)); + ResponseAppend_P(PSTR(",\"NO2\":%s"), measure_gas(NO2, buffer)); + ResponseAppend_P(PSTR(",\"C3H8\":%s"), measure_gas(C3H8, buffer)); + ResponseAppend_P(PSTR(",\"C4H10\":%s"), measure_gas(C4H10, buffer)); + ResponseAppend_P(PSTR(",\"CH4\":%s"), measure_gas(GAS_CH4, buffer)); + ResponseAppend_P(PSTR(",\"H2\":%s"), measure_gas(H2, buffer)); + ResponseAppend_P(PSTR(",\"C2H5OH\":%s}"), measure_gas(C2H5OH, buffer)); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_MGS_GAS, "NH3", measure_gas(NH3, buffer)); diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 702d3d8fe..25f73c2df 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -195,7 +195,7 @@ void NovaSdsShow(bool json) char pm2_5[33]; dtostrfd(pm2_5f, 1, pm2_5); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), mqtt_data, pm2_5, pm10); + ResponseAppend_P(PSTR(",\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), pm2_5, pm10); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_VOLTAGE, pm2_5); // PM2.5 diff --git a/sonoff/xsns_21_sgp30.ino b/sonoff/xsns_21_sgp30.ino index a544e4472..d8241f1d6 100644 --- a/sonoff/xsns_21_sgp30.ino +++ b/sonoff/xsns_21_sgp30.ino @@ -71,7 +71,7 @@ void Sgp30Show(bool json) { if (sgp30_ready) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), mqtt_data, sgp.eCO2, sgp.TVOC); + ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), sgp.eCO2, sgp.TVOC); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, sgp.eCO2); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index 3c8a933bf..f30ff11f7 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -57,7 +57,7 @@ void Sr04Show(bool json) dtostrfd(distance, 3, distance_chr); if(json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), mqtt_data, distance_chr); + ResponseAppend_P(PSTR(",\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), distance_chr); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_COUNT, distance_chr); // Send distance as Domoticz Counter value diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino index c77ca1875..8f0b6b74f 100644 --- a/sonoff/xsns_23_sdm120.ino +++ b/sonoff/xsns_23_sdm120.ino @@ -314,11 +314,11 @@ void SDM120Show(bool json) #endif // USE_SDM220 if (json) { #ifdef USE_SDM220 - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s,\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_EXPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s}"), - mqtt_data, energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current, phase_angle, import_active, export_active, import_reactive, export_reactive, total_reactive); + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s,\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_EXPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s}"), + energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current, phase_angle, import_active, export_active, import_reactive, export_reactive, total_reactive); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), - mqtt_data, energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current); + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), + energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current); #endif // USE_SDM220 #ifdef USE_DOMOTICZ if (0 == tele_period) { diff --git a/sonoff/xsns_24_si1145.ino b/sonoff/xsns_24_si1145.ino index 56bce1018..2a1c26cd5 100644 --- a/sonoff/xsns_24_si1145.ino +++ b/sonoff/xsns_24_si1145.ino @@ -329,8 +329,8 @@ void Si1145Show(bool json) uint16_t infrared = Si1145ReadIR(); uint16_t uvindex = Si1145ReadUV(); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), - mqtt_data, visible, infrared, uvindex /100, uvindex %100); + ResponseAppend_P(PSTR(",\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), + visible, infrared, uvindex /100, uvindex %100); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, visible); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_25_sdm630.ino b/sonoff/xsns_25_sdm630.ino index 013964915..c71009ce4 100644 --- a/sonoff/xsns_25_sdm630.ino +++ b/sonoff/xsns_25_sdm630.ino @@ -302,10 +302,10 @@ void SDM630Show(bool json) dtostrfd(sdm630_energy_total, Settings.flag2.energy_resolution, energy_total); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":[%s,%s,%s],\"" D_JSON_REACTIVE_POWERUSAGE "\":[%s,%s,%s],\"" D_JSON_POWERFACTOR "\":[%s,%s,%s],\"" D_JSON_VOLTAGE "\":[%s,%s,%s],\"" D_JSON_CURRENT "\":[%s,%s,%s]}"), - mqtt_data, energy_total, active_power_l1, active_power_l2, active_power_l3, + energy_total, active_power_l1, active_power_l2, active_power_l3, reactive_power_l1, reactive_power_l2, reactive_power_l3, power_factor_l1, power_factor_l2, power_factor_l3, voltage_l1, voltage_l2, voltage_l3, diff --git a/sonoff/xsns_26_lm75ad.ino b/sonoff/xsns_26_lm75ad.ino index b7b92fca7..88769b3aa 100644 --- a/sonoff/xsns_26_lm75ad.ino +++ b/sonoff/xsns_26_lm75ad.ino @@ -85,7 +85,7 @@ void LM75ADShow(bool json) dtostrfd(t, Settings.flag2.temperature_resolution, temperature); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LM75AD\":{\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, temperature); + ResponseAppend_P(PSTR(",\"LM75AD\":{\"" D_JSON_TEMPERATURE "\":%s}"), temperature); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_27_apds9960.ino b/sonoff/xsns_27_apds9960.ino index 5be8b0e5b..7594a5322 100644 --- a/sonoff/xsns_27_apds9960.ino +++ b/sonoff/xsns_27_apds9960.ino @@ -1874,7 +1874,7 @@ void APDS9960_loop(void) if (recovery_loop_counter == 1 && APDS9960_overload){ //restart sensor just before the end of recovery from long press enableGestureSensor(); APDS9960_overload = false; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Gesture\":\"On\"}")); + Response_P(PSTR("{\"Gesture\":\"On\"}")); MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); // only after the long break we report, that we are online again gesture_mode = 1; } @@ -1887,7 +1887,7 @@ void APDS9960_loop(void) { disableGestureSensor(); recovery_loop_counter = APDS9960_LONG_RECOVERY; // long pause after overload/long press - number of stateloops - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Gesture\":\"Off\"}")); + Response_P(PSTR("{\"Gesture\":\"Off\"}")); MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); gesture_mode = 0; } @@ -1959,8 +1959,8 @@ void APDS9960_show(bool json) sprintf (cct_chr, "%u", color_data.cct); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"CCT\":%s,\"Proximity\":%s}"), - mqtt_data, APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); + ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"CCT\":%s,\"Proximity\":%s}"), + APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_APDS_9960_SNS, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr ); @@ -1969,7 +1969,7 @@ void APDS9960_show(bool json) } else { if (json && (currentGesture[0] != '\0' )) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"%s\":1}"), mqtt_data, APDS9960stype, currentGesture); + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":1}"), APDS9960stype, currentGesture); currentGesture[0] = '\0'; } } @@ -2025,7 +2025,7 @@ bool APDS9960CommandSensor(void) } break; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_27, GetStateText(gesture_mode)); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_27, GetStateText(gesture_mode)); return serviced; } diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 5aa4992dd..bef4e1738 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -303,9 +303,8 @@ void MCP230xx_CheckForInterrupt(void) { break; } if (int_tele) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}"), mqtt_data, intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"), + GetDateAndTime(DT_LOCAL).c_str(), intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("MCP230XX_INT")); } if (int_event) { @@ -329,14 +328,14 @@ void MCP230xx_Show(bool json) if (json) { if (mcp230xx_type > 0) { // we have at least 8 pins uint8_t gpio = MCP230xx_readGPIO(0); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i"), - mqtt_data,(gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); + ResponseAppend_P(PSTR(",\"MCP230XX\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i"), + (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); if (2 == mcp230xx_type) { gpio = MCP230xx_readGPIO(1); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), - mqtt_data,(gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); + ResponseAppend_P(PSTR(",\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), + (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s"),mqtt_data,"}"); + ResponseAppend_P(PSTR("}")); } } } @@ -384,9 +383,9 @@ void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { char stt1[4]; sprintf(stt1,ConvertNumTxt((portpins >> (pin+pinadd-(port*8))&1), pinmo)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"},\"S29cmnd_D%i\":{\"STATE\":\"%s\"}}"),pin, cmnd, stt, pin+pinadd, stt1); + Response_P(PSTR("{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"},\"S29cmnd_D%i\":{\"STATE\":\"%s\"}}"),pin, cmnd, stt, pin+pinadd, stt1); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_CMND_RESPONSE, pin, cmnd, stt); + Response_P(MCP230XX_CMND_RESPONSE, pin, cmnd, stt); } } @@ -420,7 +419,7 @@ void MCP230xx_Reset(uint8_t pinmode) { uint8_t intmode = 3; if ((pinmode > 1) && (pinmode < 5)) { intmode = 0; } sprintf(intmodetxt,IntModeTxt(intmode)); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,""); + Response_P(MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,""); } bool MCP230xx_Command(void) { @@ -454,11 +453,11 @@ bool MCP230xx_Command(void) { uint8_t intpri = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); if ((intpri >= 0) && (intpri <= 20)) { Settings.mcp230xx_int_prio = intpri; - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } } else { // No parameter was given for INTPRI so we return the current configured value - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } } @@ -469,11 +468,11 @@ bool MCP230xx_Command(void) { if ((inttim >= 0) && (inttim <= 3600)) { Settings.mcp230xx_int_timer = inttim; MCP230xx_CheckForIntCounter(); // update register on whether or not we should be counting interrupts - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } } else { // No parameter was given for INTTIM so we return the current configured value - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } } @@ -498,14 +497,14 @@ bool MCP230xx_Command(void) { MCP230xx_CheckForIntCounter(); AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTCNT for pin D%i"),pin); } - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } else { serviced=false; return serviced; } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } } @@ -544,14 +543,14 @@ bool MCP230xx_Command(void) { AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - INTCNT enabled for pin D%i but global INTTIMER is disabled!"),pin); } MCP230xx_CheckForIntCounter(); // update register on whether or not we should be counting interrupts - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } else { serviced=false; return serviced; } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } } @@ -578,7 +577,7 @@ bool MCP230xx_Command(void) { uint8_t int_retain = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); if ((int_retain >= 0) && (int_retain <= 1)) { Settings.mcp230xx_config[pin].int_retain_flag=int_retain; - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); + Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); MCP230xx_CheckForIntRetainer(); return serviced; } else { @@ -586,7 +585,7 @@ bool MCP230xx_Command(void) { return serviced; } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); + Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); return serviced; } } @@ -619,10 +618,10 @@ bool MCP230xx_Command(void) { #ifdef USE_MCP230xx_OUTPUT uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode; sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr); + Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr); #else // not USE_MCP230xx_OUTPUT sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,intmodetxt,pinstatustxtr); + Response_P(MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,intmodetxt,pinstatustxtr); #endif //USE_MCP230xx_OUTPUT return serviced; } @@ -682,7 +681,7 @@ bool MCP230xx_Command(void) { #else // not USE_MCP230xx_OUTPUT sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1)); #endif // USE_MCP230xx_OUTPUT - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); + Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); return serviced; } } else { @@ -730,14 +729,14 @@ void MCP230xx_OutputTelemetry(void) { } if (outputcount) { char stt[7]; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230_OUT\": {"), GetDateAndTime(DT_LOCAL).c_str()); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230_OUT\": {"), GetDateAndTime(DT_LOCAL).c_str()); for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].pinmode >= 5) { sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"OUT_D%i\":\"%s\","),mqtt_data,pinx,stt); + ResponseAppend_P(PSTR("\"OUT_D%i\":\"%s\","),pinx,stt); } } - snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"END\":1}}"),mqtt_data); + ResponseAppend_P(PSTR("\"END\":1}}")); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } } @@ -745,29 +744,29 @@ void MCP230xx_OutputTelemetry(void) { #endif // USE_MCP230xx_OUTPUT void MCP230xx_Interrupt_Counter_Report(void) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230_INTTIMER\": {"), GetDateAndTime(DT_LOCAL).c_str()); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230_INTTIMER\": {"), GetDateAndTime(DT_LOCAL).c_str()); for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].int_count_en) { // Counting is enabled for this pin so we add to report - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"INTCNT_D%i\":%i,"),mqtt_data,pinx,mcp230xx_int_counter[pinx]); + ResponseAppend_P(PSTR("\"INTCNT_D%i\":%i,"),pinx,mcp230xx_int_counter[pinx]); mcp230xx_int_counter[pinx]=0; } } - snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"END\":1}}"),mqtt_data); + ResponseAppend_P(PSTR("\"END\":1}}")); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); mcp230xx_int_sec_counter = 0; } void MCP230xx_Interrupt_Retain_Report(void) { uint16_t retainresult = 0; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP_INTRETAIN\": {"), GetDateAndTime(DT_LOCAL).c_str()); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP_INTRETAIN\": {"), GetDateAndTime(DT_LOCAL).c_str()); for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].int_retain_flag) { - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"D%i\":%i,"),mqtt_data,pinx,mcp230xx_int_retainer[pinx]); + ResponseAppend_P(PSTR("\"D%i\":%i,"),pinx,mcp230xx_int_retainer[pinx]); retainresult |= (((mcp230xx_int_retainer[pinx])&1) << pinx); mcp230xx_int_retainer[pinx]=0; } } - snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"Value\":%u}}"),mqtt_data,retainresult); + ResponseAppend_P(PSTR("\"Value\":%u}}"),retainresult); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } diff --git a/sonoff/xsns_30_mpr121.ino b/sonoff/xsns_30_mpr121.ino index 10ea46078..6f23117c6 100644 --- a/sonoff/xsns_30_mpr121.ino +++ b/sonoff/xsns_30_mpr121.ino @@ -343,7 +343,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) // Append sensor to JSON message string if (FUNC_JSON_APPEND == function) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MPR121%c\":{"), mqtt_data, pS->id[i]); + ResponseAppend_P(PSTR(",\"MPR121%c\":{"), pS->id[i]); } // Loop through buttons for (uint8_t j = 0; j < 13; j++) { @@ -351,7 +351,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) // Add sensor, button and state to MQTT JSON message string if ((FUNC_EVERY_50_MSECOND == function) && (BITC(i, j) != BITP(i, j))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"MPR121%c\":{\"Button%i\":%i}}"), pS->id[i], j, BITC(i, j)); + Response_P(PSTR("{\"MPR121%c\":{\"Button%i\":%i}}"), pS->id[i], j, BITC(i, j)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); } // Add buttons to web string @@ -363,7 +363,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) // Append JSON message string if (FUNC_JSON_APPEND == function) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"Button%i\":%i"), mqtt_data, (j > 0 ? "," : ""), j, BITC(i, j)); + ResponseAppend_P(PSTR("%s\"Button%i\":%i"), (j > 0 ? "," : ""), j, BITC(i, j)); } } // for-loop j @@ -372,7 +372,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) // Append JSON message string if (FUNC_JSON_APPEND == function) { - snprintf_P(mqtt_data, sizeof(mqtt_data), "%s}", mqtt_data); + ResponseAppend_P(PSTR("}")); } } // if->running } // for-loop i diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index 9ce63b228..2624d0b8c 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -85,7 +85,7 @@ void CCS811Show(bool json) { if (CCS811_ready) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), mqtt_data,eCO2,TVOC); + ResponseAppend_P(PSTR(",\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), eCO2,TVOC); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, eCO2); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index e7dddd953..6ac8763bd 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -205,8 +205,8 @@ void MPU_6050Show(bool json) snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy); char json_axis_gz[25]; snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), - mqtt_data, D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), + D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); #ifdef USE_DOMOTICZ DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 272e35a9e..b72ef0a9f 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -128,7 +128,7 @@ void HxCalibrationStateTextJson(uint8_t msg_id) char cal_text[30]; hx_calibrate_msg = msg_id; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, GetTextIndexed(cal_text, sizeof(cal_text), hx_calibrate_msg, kHxCalibrationStates)); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, GetTextIndexed(cal_text, sizeof(cal_text), hx_calibrate_msg, kHxCalibrationStates)); if (msg_id < 3) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("Sensor34")); } } @@ -162,7 +162,7 @@ bool HxCommand(void) switch (XdrvMailbox.payload) { case 1: // Reset scale HxReset(); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); break; case 2: // Calibrate if (strstr(XdrvMailbox.data, ",")) { @@ -206,7 +206,7 @@ bool HxCommand(void) if (show_parms) { char item[33]; dtostrfd((float)Settings.weight_item / 10, 1, item); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" D_JSON_WEIGHT_ITEM "\":%s}}"), + Response_P(PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" D_JSON_WEIGHT_ITEM "\":%s}}"), Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, item); } @@ -348,7 +348,7 @@ void HxShow(bool json) dtostrfd(weight, Settings.flag2.weight_resolution, weight_chr); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s}"), mqtt_data, weight_chr, scount); + ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s}"), weight_chr, scount); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr); diff --git a/sonoff/xsns_35_tx20.ino b/sonoff/xsns_35_tx20.ino index 444c5231d..b5e8a2091 100644 --- a/sonoff/xsns_35_tx20.ino +++ b/sonoff/xsns_35_tx20.ino @@ -182,8 +182,8 @@ void Tx20Show(bool json) GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx20_wind_direction, kTx20Directions); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"), - mqtt_data, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); + ResponseAppend_P(PSTR(",\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"), + wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_SNS_TX20, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); diff --git a/sonoff/xsns_36_mgc3130.ino b/sonoff/xsns_36_mgc3130.ino index c767c192c..055126c6d 100644 --- a/sonoff/xsns_36_mgc3130.ino +++ b/sonoff/xsns_36_mgc3130.ino @@ -529,8 +529,8 @@ void MGC3130_show(bool json) if (json) { if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch) { if (MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), - mqtt_data, MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); + ResponseAppend_P(PSTR(",\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), + MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); MGC3130_lastSentX = MGC_data.out.x; MGC3130_lastSentY = MGC_data.out.y; MGC3130_lastSentZ = MGC_data.out.z; @@ -540,7 +540,7 @@ void MGC3130_show(bool json) if (MGC3130_mode == 2) { if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"AW\":%i}"), mqtt_data, MGC3130stype, MGC3130_rotValue); + ResponseAppend_P(PSTR(",\"%s\":{\"AW\":%i}"), MGC3130stype, MGC3130_rotValue); MGC3130_lastSentRotValue = MGC3130_rotValue; } } @@ -549,7 +549,7 @@ void MGC3130_show(bool json) if (millis() - MGC3130_touchTimeStamp > 220 ) { MGC3130_touchCounter = 1; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"%s\":%u}"), mqtt_data, MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); MGC3130_currentGesture[0] = '\0'; MGC3130_touchTimeStamp = millis(); } diff --git a/sonoff/xsns_37_rfsensor.ino b/sonoff/xsns_37_rfsensor.ino index 7230ae692..4a94e2d77 100644 --- a/sonoff/xsns_37_rfsensor.ino +++ b/sonoff/xsns_37_rfsensor.ino @@ -268,16 +268,16 @@ void RfSnsTheoV2Show(bool json) if (rfsns_theo_v2_t1[i].time < LocalTime() - RFSNS_VALID_WINDOW) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), - mqtt_data, sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), + sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage); } } else { char temperature[33]; dtostrfd(ConvertTemp((float)rfsns_theo_v2_t1[i].temp / 100), Settings.flag2.temperature_resolution, temperature); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"), - mqtt_data, sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"), + sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage); #ifdef USE_DOMOTICZ if ((0 == tele_period) && !sensor_once) { DomoticzSensor(DZ_TEMP, temperature); @@ -305,8 +305,8 @@ void RfSnsTheoV2Show(bool json) if (rfsns_theo_v2_t2[i].time < LocalTime() - RFSNS_VALID_WINDOW) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_RFRECEIVED" \":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), - mqtt_data, sensor, GetDT(rfsns_theo_v2_t2[i].time).c_str(), voltage); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED" \":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), + sensor, GetDT(rfsns_theo_v2_t2[i].time).c_str(), voltage); } } else { float temp = ConvertTemp((float)rfsns_theo_v2_t2[i].temp / 100); @@ -317,8 +317,8 @@ void RfSnsTheoV2Show(bool json) dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_VOLTAGE "\":%s}"), - mqtt_data, sensor, temperature, humidity, voltage); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_VOLTAGE "\":%s}"), + sensor, temperature, humidity, voltage); if ((0 == tele_period) && !sensor_once) { #ifdef USE_DOMOTICZ DomoticzTempHumSensor(temperature, humidity); // @@ -552,8 +552,7 @@ void RfSnsAlectoV2Show(bool json) if (rfsns_alecto_v2->time) { if (rfsns_alecto_v2->time < LocalTime() - RFSNS_VALID_WINDOW) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_ALECTOV2 "\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), - mqtt_data, GetDT(rfsns_alecto_v2->time).c_str()); + ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), GetDT(rfsns_alecto_v2->time).c_str()); } } else { float temp = ConvertTemp(rfsns_alecto_v2->temp); @@ -576,8 +575,8 @@ void RfSnsAlectoV2Show(bool json) } if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_ALECTOV2 "\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), - mqtt_data, temperature, humidity, rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); + ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), + temperature, humidity, rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); if (0 == tele_period) { #ifdef USE_DOMOTICZ // Use a rules to send data to Domoticz where also a local BMP280 is connected: diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino index 953832d6f..2aecab9a1 100644 --- a/sonoff/xsns_38_az7798.ino +++ b/sonoff/xsns_38_az7798.ino @@ -258,7 +258,7 @@ void AzShow(bool json) dtostrfd(az_humidity, Settings.flag2.humidity_resolution, humidity); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), mqtt_data, ktype, az_co2, temperature, humidity); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), ktype, az_co2, temperature, humidity); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, az_co2); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_39_max31855.ino b/sonoff/xsns_39_max31855.ino index a6275caa7..fc43ecac1 100644 --- a/sonoff/xsns_39_max31855.ino +++ b/sonoff/xsns_39_max31855.ino @@ -125,8 +125,8 @@ void MAX31855_Show(bool Json){ dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); if(Json){ - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ - mqtt_data, "MAX31855", probetemp, referencetemp, MAX31855_Result.ErrorCode); + ResponseAppend_P(PSTR(",\"MAX31855\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ + probetemp, referencetemp, MAX31855_Result.ErrorCode); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_TEMP, probetemp); diff --git a/sonoff/xsns_40_pn532.ino b/sonoff/xsns_40_pn532.ino index 0bfa8bda1..491996327 100644 --- a/sonoff/xsns_40_pn532.ino +++ b/sonoff/xsns_40_pn532.ino @@ -497,12 +497,12 @@ void PN532_ScanForTag(void) pn532_function = 0; #endif // USE_PN532_DATA_FUNCTION - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); #ifdef USE_PN532_DATA_FUNCTION - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), mqtt_data, uids, card_datas); + ResponseAppend_P(PSTR(",\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), uids, card_datas); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids); + ResponseAppend_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids); #endif // USE_PN532_DATA_FUNCTION MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); @@ -544,8 +544,7 @@ bool PN532_Command(void) if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"E")) { pn532_function = 1; // Block 1 of next card/tag will be reset to 0x00... AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be erased")); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"E\"\"}}"), mqtt_data); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"PN532\":{\"COMMAND\":\"E\"}}"), GetDateAndTime(DT_LOCAL).c_str()); return serviced; } if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"S")) { @@ -561,8 +560,7 @@ bool PN532_Command(void) pn532_newdata[pn532_newdata_len] = 0x00; // Null terminate the string pn532_function = 2; AddLog_P2(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'"), pn532_newdata); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"S\"\"}}"), mqtt_data); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"PN532\":{\"COMMAND\":\"S\"}}"), GetDateAndTime(DT_LOCAL).c_str()); return serviced; } } diff --git a/sonoff/xsns_41_max44009.ino b/sonoff/xsns_41_max44009.ino index 58a809ed9..891b36815 100644 --- a/sonoff/xsns_41_max44009.ino +++ b/sonoff/xsns_41_max44009.ino @@ -128,9 +128,7 @@ void Max4409Show(bool json) dtostrf(max44009_illuminance, sizeof(illum_str) -1, prec, illum_str); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), - PSTR("%s,\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), - mqtt_data, max44009_types, illum_str); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), max44009_types, illum_str); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, illum_str); diff --git a/sonoff/xsns_42_scd30.ino b/sonoff/xsns_42_scd30.ino index defa01892..44e23ea49 100644 --- a/sonoff/xsns_42_scd30.ino +++ b/sonoff/xsns_42_scd30.ino @@ -401,7 +401,7 @@ bool Scd30CommandSensor() Scd30GetCommand(command_code, &value); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SCD30_COMMAND_NVALUE, command, value); + Response_P(S_JSON_SCD30_COMMAND_NVALUE, command, value); } break; @@ -421,7 +421,7 @@ bool Scd30CommandSensor() } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SCD30_COMMAND_NFW_VALUE, command, major, minor); + Response_P(S_JSON_SCD30_COMMAND_NFW_VALUE, command, major, minor); } } break; @@ -445,8 +445,9 @@ void Scd30Show(bool json) dtostrfd(scd30_Humid, Settings.flag2.humidity_resolution, humidity); dtostrfd(ConvertTemp(scd30_Temp), Settings.flag2.temperature_resolution, temperature); if (json) { - //snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), mqtt_data, scd30_CO2, temperature, humidity); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), mqtt_data, scd30_CO2, scd30_CO2EAvg, temperature, humidity); + //ResponseAppend_P(PSTR(",\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), scd30_CO2, temperature, humidity); + ResponseAppend_P(PSTR(",\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), + scd30_CO2, scd30_CO2EAvg, temperature, humidity); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, scd30_CO2); #endif // USE_DOMOTICZ From 10d32accccc4c44eb4e6edd608111e3d7ecd09ac Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 24 Mar 2019 14:23:20 +0100 Subject: [PATCH 1174/2222] Free some flash used by hass Free some flash used by hass --- sonoff/i18n.h | 22 ++--- sonoff/support.ino | 20 ++--- sonoff/xdrv_12_home_assistant.ino | 139 +++++++++++++----------------- 3 files changed, 80 insertions(+), 101 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index ca5e2b79a..60b5880e0 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -561,20 +561,14 @@ const char kOptionBlinkOff[] PROGMEM = "BLINKOFF|" D_BLINKOFF ; // xdrv_02_webserver.ino #ifdef USE_WEBSERVER -const char HTTP_SNS_TEMP[] PROGMEM = "{s}%s " D_TEMPERATURE "{m}%s°%c{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_HUM[] PROGMEM = "{s}%s " D_HUMIDITY "{m}%s%%{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_PRESSURE[] PROGMEM = "{s}%s " D_PRESSURE "{m}%s %s{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_ANALOG[] PROGMEM = "{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = - -#if defined(USE_MHZ19) || defined(USE_SENSEAIR) || defined(USE_AZ7798) || defined(USE_SCD30) -const char HTTP_SNS_CO2[] PROGMEM = "{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = -#endif // USE_MHZ19 - -#if defined(USE_SCD30) -const char HTTP_SNS_CO2EAVG[] PROGMEM = "{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = -#endif // USE_SCD30 +const char HTTP_SNS_TEMP[] PROGMEM = "{s}%s " D_TEMPERATURE "{m}%s°%c{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_HUM[] PROGMEM = "{s}%s " D_HUMIDITY "{m}%s%%{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_PRESSURE[] PROGMEM = "{s}%s " D_PRESSURE "{m}%s %s{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_ANALOG[] PROGMEM = "{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_CO2[] PROGMEM = "{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_CO2EAVG[] PROGMEM = "{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU; const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION; diff --git a/sonoff/support.ino b/sonoff/support.ino index 24f0c6f8c..cfe3e6a6a 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -701,24 +701,24 @@ void ShowSource(int source) * Response data handling \*********************************************************************************************/ -int Response_P(const char* formatP, ...) // Content send snprintf_P char data +int Response_P(const char* format, ...) // Content send snprintf_P char data { // This uses char strings. Be aware of sending %% if % is needed - va_list arg; - va_start(arg, formatP); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); - va_end(arg); + va_list args; + va_start(args, format); + int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), format, args); + va_end(args); return len; } -int ResponseAppend_P(const char* formatP, ...) // Content send snprintf_P char data +int ResponseAppend_P(const char* format, ...) // Content send snprintf_P char data { // This uses char strings. Be aware of sending %% if % is needed - va_list arg; - va_start(arg, formatP); + va_list args; + va_start(args, format); int mlen = strlen(mqtt_data); - int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, formatP, arg); - va_end(arg); + int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); + va_end(args); return len + mlen; } diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 4437a91eb..406e6d451 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -44,38 +44,37 @@ const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE[] PROGMEM = - "%s,\"off_delay\":1"; // Hass has no support for TOGGLE, fake it by resetting to OFF after 1s + ",\"off_delay\":1"; // Hass has no support for TOGGLE, fake it by resetting to OFF after 1s const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = - "%s,\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work + ",\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work "\"pl_off\":\"%s\""; // OFF - const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = - "%s,\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer + ",\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer "\"bri_stat_t\":\"%s\"," // stat/led2/RESULT "\"bri_scl\":100," // 100% "\"on_cmd_type\":\"brightness\"," // power on (first), power on (last), no power on (brightness) "\"bri_val_tpl\":\"{{value_json." D_CMND_DIMMER "}}\""; const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = - "%s,\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2 + ",\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2 "\"rgb_stat_t\":\"%s\"," // stat/led2/RESULT "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = - "%s,\"whit_val_cmd_t\":\"%s\"," // cmnd/led2/White + ",\"whit_val_cmd_t\":\"%s\"," // cmnd/led2/White "\"whit_val_stat_t\":\"%s\"," // stat/led2/RESULT "\"white_value_scale\":100," // (No abbreviation defined) "\"whit_val_tpl\":\"{{value_json.Channel[3]}}\""; const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = - "%s,\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT + ",\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT "\"clr_temp_stat_t\":\"%s\"," // stat/led2/RESULT "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = - "%s,\"fx_cmd_t\":\"%s\"," // cmnd/led2/Scheme + ",\"fx_cmd_t\":\"%s\"," // cmnd/led2/Scheme "\"fx_stat_t\":\"%s\"," // stat/led2/RESULT "\"fx_val_tpl\":\"{{value_json." D_CMND_SCHEME "}}\"," "\"fx_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; // string list with reference to scheme parameter. @@ -88,47 +87,47 @@ const char HASS_DISCOVER_SENSOR[] PROGMEM = "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline const char HASS_DISCOVER_SENSOR_TEMP[] PROGMEM = - "%s,\"unit_of_meas\":\"°%c\"," // °C / °F + ",\"unit_of_meas\":\"°%c\"," // °C / °F "\"val_tpl\":\"{{value_json['%s'].Temperature}}\""; // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Temperature }} const char HASS_DISCOVER_SENSOR_HUM[] PROGMEM = - "%s,\"unit_of_meas\":\"%%\"," // % + ",\"unit_of_meas\":\"%%\"," // % "\"val_tpl\":\"{{value_json['%s'].Humidity}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }} "\"dev_cla\":\"humidity\""; // humidity const char HASS_DISCOVER_SENSOR_PRESS[] PROGMEM = - "%s,\"unit_of_meas\":\"%s\"," // PressureUnit() setting + ",\"unit_of_meas\":\"%s\"," // PressureUnit() setting "\"val_tpl\":\"{{value_json['%s'].Pressure}}\"," // "BME280":{"Temperature":19.7,"Humidity":27.8,"Pressure":990.1} -> {{ value_json['BME280'].Pressure }} "\"dev_cla\":\"pressure\""; // pressure //ENERGY const char HASS_DISCOVER_SENSOR_KWH[] PROGMEM = - "%s,\"unit_of_meas\":\"kWh\"," // kWh + ",\"unit_of_meas\":\"kWh\"," // kWh "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Total/Yesterday/Today }} const char HASS_DISCOVER_SENSOR_WATT[] PROGMEM = - "%s,\"unit_of_meas\":\"W\"," // W + ",\"unit_of_meas\":\"W\"," // W "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].POWER }} const char HASS_DISCOVER_SENSOR_VOLTAGE[] PROGMEM = - "%s,\"unit_of_meas\":\"V\"," // V + ",\"unit_of_meas\":\"V\"," // V "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Voltage }} const char HASS_DISCOVER_SENSOR_AMPERE[] PROGMEM = - "%s,\"unit_of_meas\":\"A\"," // A + ",\"unit_of_meas\":\"A\"," // A "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Current }} const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = - "%s,\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass + ",\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = - "%s,\"json_attributes_topic\":\"%s\"," + ",\"json_attributes_topic\":\"%s\"," "\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\"";// "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = - "%s,\"uniq_id\":\"%s\"," + ",\"uniq_id\":\"%s\"," "\"device\":{\"identifiers\":[\"%06X\"]," "\"name\":\"%s\"," "\"model\":\"%s\"," @@ -136,11 +135,11 @@ const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = "\"manufacturer\":\"Tasmota\"}"; const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = - "%s,\"uniq_id\":\"%s\"," + ",\"uniq_id\":\"%s\"," "\"device\":{\"identifiers\":[\"%06X\"]}"; const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM = - "%s, \"~\":\"%s\""; + ",\"~\":\"%s\""; uint8_t hass_init_step = 0; uint8_t hass_mode = 0; @@ -166,21 +165,24 @@ static void Shorten(char** s, char *prefix) } } -void try_snprintf_P(char *s, int n, const char *format, ... ) +void TryResponseAppend_P(const char *format, ... ) { va_list args; va_start(args, format); char dummy[2]; - int len = vsnprintf_P(dummy, 1, format, args); - if (len >= n) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("ERROR: MQTT discovery failed due to too long topic or friendly name. " - "Please shorten topic and friendly name. Failed to format(%u/%u):"), len, n); + int dlen = vsnprintf_P(dummy, 1, format, args); + + int mlen = strlen(mqtt_data); + int slen = sizeof(mqtt_data) -1 -mlen; + if (dlen >= slen) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: MQTT discovery failed due to too long topic or friendly name. " + "Please shorten topic and friendly name. Failed to format(%u/%u):"), dlen, slen); va_start(args, format); vsnprintf_P(log_data, sizeof(log_data), format, args); AddLog(LOG_LEVEL_ERROR); } else { va_start(args, format); - vsnprintf_P(s, n, format, args); + vsnprintf_P(mqtt_data + mlen, slen, format, args); } va_end(args); } @@ -234,30 +236,28 @@ void HAssAnnounceRelayLight(void) Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_RELAY, - name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, - unique_id, ESP.getChipId()); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + Response_P(HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId()); + TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); if (is_light) { char *brightness_command_topic = stemp1; GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); Shorten(&brightness_command_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_DIMMER, mqtt_data, brightness_command_topic, state_topic); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_DIMMER, brightness_command_topic, state_topic); if (light_subtype >= LST_RGB) { char *rgb_command_topic = stemp1; GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); Shorten(&rgb_command_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_COLOR, mqtt_data, rgb_command_topic, state_topic); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_COLOR, rgb_command_topic, state_topic); char *effect_command_topic = stemp1; GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); Shorten(&effect_command_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_SCHEME, mqtt_data, effect_command_topic, state_topic); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_SCHEME, effect_command_topic, state_topic); } if (LST_RGBW == light_subtype) { @@ -265,17 +265,17 @@ void HAssAnnounceRelayLight(void) GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); Shorten(&white_temp_command_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_WHITE, mqtt_data, white_temp_command_topic, state_topic); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_WHITE, white_temp_command_topic, state_topic); } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { char *color_temp_command_topic = stemp1; GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); Shorten(&color_temp_command_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_CT, mqtt_data, color_temp_command_topic, state_topic); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_CT, color_temp_command_topic, state_topic); } } - try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + TryResponseAppend_P(PSTR("}")); } MqttPublish(stopic, true); } @@ -315,15 +315,13 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint FindPrefix(state_topic, availability_topic, prefix); Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH, - name, state_topic, Settings.state_text[toggle?2:1], availability_topic); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, - unique_id, ESP.getChipId()); - if (strlen(prefix) > 0 ) try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); - if (toggle) try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, mqtt_data); - else try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH_ONOFF, mqtt_data, Settings.state_text[0]); + Response_P(HASS_DISCOVER_BUTTON_SWITCH, name, state_topic, Settings.state_text[toggle?2:1], availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId()); + if (strlen(prefix) > 0 ) TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); + if (toggle) TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_TOGGLE); + else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, Settings.state_text[0]); - try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + TryResponseAppend_P(PSTR("}")); } MqttPublish(stopic, true); } @@ -416,40 +414,30 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR, - name, state_topic, availability_topic); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, - unique_id, ESP.getChipId()); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + Response_P(HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId()); + TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); if (!strcmp_P(subsensortype, PSTR(D_JSON_TEMPERATURE))) { - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_TEMP, - mqtt_data, TempUnit(), sensorname); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_TEMP, TempUnit(), sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_HUM, - mqtt_data, sensorname); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_HUM, sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE))) { - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_PRESS, - mqtt_data, PressureUnit().c_str(), sensorname); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_PRESS, PressureUnit().c_str(), sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL)) || !strcmp_P(subsensortype, PSTR(D_JSON_TODAY)) || !strcmp_P(subsensortype, PSTR(D_JSON_YESTERDAY))){ - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_KWH, - mqtt_data, sensorname, subsensortype); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_KWH, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_POWERUSAGE))){ - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_WATT, - mqtt_data, sensorname, subsensortype); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_WATT, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_VOLTAGE))){ - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_VOLTAGE, - mqtt_data, sensorname, subsensortype); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_VOLTAGE, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_CURRENT))){ - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_AMPERE, - mqtt_data, sensorname, subsensortype); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_AMPERE, sensorname, subsensortype); } else { - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_ANY, - mqtt_data, sensorname, subsensortype); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_ANY, sensorname, subsensortype); } - try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + TryResponseAppend_P(PSTR("}")); } MqttPublish(stopic, true); } @@ -509,7 +497,7 @@ void HAssAnnounceStatusSensor(void) mqtt_data[0] = '\0'; // Clear retained message // Clear or Set topic - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s"), ESP.getChipId(), "status"); + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_status"), ESP.getChipId()); snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); if (Settings.flag.hass_discovery) { @@ -518,22 +506,19 @@ void HAssAnnounceStatusSensor(void) char *state_topic = stemp1; char *availability_topic = stemp2; - snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[0], "status"); + snprintf_P(name, sizeof(name), PSTR("%s status"), Settings.friendlyname[0]); GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); FindPrefix(state_topic, availability_topic, prefix); Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR, - name, state_topic, availability_topic); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_HASS_STATUS, - mqtt_data, state_topic); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO, mqtt_data, - unique_id, ESP.getChipId(), + Response_P(HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(), Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); + TryResponseAppend_P(PSTR("}")); } MqttPublish(stopic, true); } From a7a07c5b96ab793ed692fdd7fad1dd5c261972d2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 25 Mar 2019 10:02:12 +0100 Subject: [PATCH 1175/2222] Fix JSON message error (#5521) Fix JSON message error regression (#5521) --- sonoff/xdrv_04_light.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 6a4c11db7..fc9d1a635 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -760,7 +760,7 @@ void LightState(uint8_t append) for (uint8_t i = 0; i < light_subtype; i++) { ResponseAppend_P(PSTR("%s%d" ), (i > 0 ? "," : ""), light_current_color[i] * 100 / 255); } - ResponseAppend_P(PSTR("%s]")); + ResponseAppend_P(PSTR("]")); } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { ResponseAppend_P(PSTR(",\"" D_CMND_COLORTEMPERATURE "\":%d"), LightGetColorTemp()); From 57cb570b8fa145207e6e1f4879c26a3a2979a41b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 25 Mar 2019 11:20:03 +0100 Subject: [PATCH 1176/2222] Fix GUI corruption Fix GUI corruption due to format string usage (#5519) --- sonoff/xdrv_02_mqtt.ino | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 21b97edd0..37bdd97c2 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -741,7 +741,7 @@ const char HTTP_FORM_MQTT1[] PROGMEM = const char HTTP_FORM_MQTT2[] PROGMEM = "

" D_USER " (" MQTT_USER ")

" "

" D_PASSWORD "

" - "

" D_TOPIC " = %%topic%% (" MQTT_TOPIC ")

" + "

" D_TOPIC " = %%topic%% (%s)

" "

" D_FULL_TOPIC " (%s)

"; void HandleMqttConfiguration(void) @@ -763,14 +763,11 @@ void HandleMqttConfiguration(void) WSContentSend_P(HTTP_FORM_MQTT1, Settings.mqtt_host, Settings.mqtt_port, - Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)), - MQTT_CLIENT_ID, - Settings.mqtt_client); + Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, Settings.mqtt_client); WSContentSend_P(HTTP_FORM_MQTT2, (Settings.mqtt_user[0] == '\0') ? "0" : Settings.mqtt_user, - Settings.mqtt_topic, - MQTT_FULLTOPIC, MQTT_FULLTOPIC, - Settings.mqtt_fulltopic); + Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, Settings.mqtt_topic, + MQTT_FULLTOPIC, MQTT_FULLTOPIC, Settings.mqtt_fulltopic); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentStop(); From 1c7fb82af83f391624a20210da6bd67e218d8682 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 25 Mar 2019 16:03:28 +0100 Subject: [PATCH 1177/2222] 6.5.0.2 Change UDP initial message handling 6.5.0.2 20190325 * Change UDP initial message handling from string to char using static memory and add debug info (#5505) --- sonoff/_changelog.ino | 5 ++++- sonoff/sonoff_version.h | 2 +- sonoff/xplg_wemohue.ino | 43 +++++++++++++++++++++++------------------ 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 978aa861f..54ed9c21f 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.5.0.1 20190319 +/* 6.5.0.2 20190325 + * Change UDP initial message handling from string to char using static memory and add debug info (#5505) + * + * 6.5.0.1 20190319 * Change Web GUI sensor data collection * * 6.5.0 20190319 diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 7a5dac4cc..66b50129c 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06050001 +#define VERSION 0x06050002 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 2a7b60b80..9a99b3633 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -222,26 +222,26 @@ bool UdpConnect(void) void PollUdp(void) { - if (udp_connected && !udp_response_mutex) { + if (udp_connected && !udp_response_mutex && devices_present) { if (PortUdp.parsePacket()) { int len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1); if (len > 0) { packet_buffer[len] = 0; } - String request = packet_buffer; -// 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_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); +// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); + if (strstr_P(packet_buffer, PSTR("M-SEARCH"))) { udp_remote_ip = PortUdp.remoteIP(); udp_remote_port = PortUdp.remotePort(); + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"), + udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer); + + String request = packet_buffer; + request.toLowerCase(); + request.replace(" ", ""); if (EMUL_WEMO == Settings.flag2.emulation) { if (request.indexOf(F("urn:belkin:device:**")) > 0) { // type1 echo dot 2g, echo 1g's udp_response_mutex = true; @@ -384,6 +384,9 @@ void HandleUpnpEvent(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); String request = WebServer->arg(0); + +// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), request.c_str()); + String state_xml = FPSTR(WEMO_RESPONSE_STATE_SOAP); //differentiate get and set state if (request.indexOf(F("SetBinaryState")) > 0) { @@ -837,14 +840,16 @@ void HandleHueApi(String *path) void HueWemoAddHandlers(void) { - if (EMUL_WEMO == Settings.flag2.emulation) { - WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); - WebServer->on("/eventservice.xml", HandleUpnpService); - WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); - WebServer->on("/setup.xml", HandleUpnpSetupWemo); - } - if (EMUL_HUE == Settings.flag2.emulation) { - WebServer->on("/description.xml", HandleUpnpSetupHue); + if (devices_present) { + if (EMUL_WEMO == Settings.flag2.emulation) { + WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); + WebServer->on("/eventservice.xml", HandleUpnpService); + WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); + WebServer->on("/setup.xml", HandleUpnpSetupWemo); + } + if (EMUL_HUE == Settings.flag2.emulation) { + WebServer->on("/description.xml", HandleUpnpSetupHue); + } } } From 0b1945cd5dafa9de8cd5d32e046f7071bab026a1 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Mon, 25 Mar 2019 17:29:20 +0100 Subject: [PATCH 1178/2222] resolve VSC warning To get ride of VSC warning --- include/dummy.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 include/dummy.txt diff --git a/include/dummy.txt b/include/dummy.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/include/dummy.txt @@ -0,0 +1 @@ + From bf8845c3bdab7da3dd4069be03f0fadc21509cd7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 26 Mar 2019 10:28:30 +0100 Subject: [PATCH 1179/2222] Increase emulation stability (#5505) Increase emulation stability (#5505) --- sonoff/xplg_wemohue.ino | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 9a99b3633..4944b41b1 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -233,37 +233,40 @@ void PollUdp(void) // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); if (strstr_P(packet_buffer, PSTR("M-SEARCH"))) { + udp_response_mutex = true; + udp_remote_ip = PortUdp.remoteIP(); udp_remote_port = PortUdp.remotePort(); AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"), udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer); - String request = packet_buffer; - request.toLowerCase(); - request.replace(" ", ""); + UpperCase(packet_buffer, packet_buffer); + RemoveSpace(packet_buffer); if (EMUL_WEMO == Settings.flag2.emulation) { - if (request.indexOf(F("urn:belkin:device:**")) > 0) { // type1 echo dot 2g, echo 1g's - udp_response_mutex = true; + if (strstr_P(packet_buffer, PSTR("URN:BELKIN:DEVICE:**"))) { // type1 echo dot 2g, echo 1g's TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, WemoRespondToMSearch, 1); + return; } - else if ((request.indexOf(F("upnp:rootdevice")) > 0) || // type2 Echo 2g (echo & echo plus) - (request.indexOf(F("ssdpsearch:all")) > 0) || - (request.indexOf(F("ssdp:all")) > 0)) { - udp_response_mutex = true; + else if (strstr_P(packet_buffer, PSTR("UPNP:ROOTDEVICE")) || // type2 Echo 2g (echo & echo plus) + strstr_P(packet_buffer, PSTR("SSDPSEARCH:ALL")) || + strstr_P(packet_buffer, PSTR("SSDP:ALL"))) { TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, WemoRespondToMSearch, 2); + return; + } + } else { + if (strstr_P(packet_buffer, PSTR("URN:SCHEMAS-UPNP-ORG:DEVICE:BASIC:1")) || + strstr_P(packet_buffer, PSTR("UPNP:ROOTDEVICE")) || + strstr_P(packet_buffer, PSTR("SSDPSEARCH:ALL")) || + strstr_P(packet_buffer, PSTR("SSDP:ALL"))) { + TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, HueRespondToMSearch); + return; } } - else if ((EMUL_HUE == Settings.flag2.emulation) && - ((request.indexOf(F("urn:schemas-upnp-org:device:basic:1")) > 0) || - (request.indexOf(F("upnp:rootdevice")) > 0) || - (request.indexOf(F("ssdpsearch:all")) > 0) || - (request.indexOf(F("ssdp:all")) > 0))) { - udp_response_mutex = true; - TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, HueRespondToMSearch); - } + udp_response_mutex = false; } } + delay(1); } } From f709ecf78668f7a1389fec3e05802a34a0d69faa Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Tue, 26 Mar 2019 11:46:03 +0100 Subject: [PATCH 1180/2222] Update Core 2.5.0 to build chain 2.0.4 Update Core 2.5.0 to build chain 2.0.4 Set Compiler Option -O2 for Core 2.5.0 and Core Stage (Faster code) See https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473 --- platformio.ini | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 671a6f284..8fffc69d3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -67,9 +67,11 @@ build_flags = ${esp82xx_defaults.build_flags} [core_2_5_0] ; *** Esp8266 core for Arduino version 2.5.0 -platform = espressif8266@2.0.1 +platform = espressif8266@~2.0.4 build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld +; Code optimization see https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473 + -O2 ; lwIP 1.4 (Default) ; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH ; lwIP 2 - Low Memory @@ -89,6 +91,8 @@ build_flags = ${esp82xx_defaults.build_flags} platform = https://github.com/platformio/platform-espressif8266.git#feature/stage build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld +; Code optimization see https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473 + -O2 ; nonos-sdk 22x -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x ; nonos-sdk-pre-v3 From f83a5bb9898f99982e17d53197392fd1891bc164 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 26 Mar 2019 17:10:07 +0100 Subject: [PATCH 1181/2222] More Wemo tuning More Wemo tuning --- sonoff/support.ino | 13 ++++++ sonoff/xplg_wemohue.ino | 97 ++++++++++++++++++++++------------------- 2 files changed, 66 insertions(+), 44 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index cfe3e6a6a..823655ce4 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -283,6 +283,19 @@ char* RemoveSpace(char* p) return p; } +char* LowerCase(char* dest, const char* source) +{ + char* write = dest; + const char* read = source; + char ch = '.'; + + while (ch != '\0') { + ch = *read++; + *write++ = tolower(ch); + } + return dest; +} + char* UpperCase(char* dest, const char* source) { char* write = dest; diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 4944b41b1..60edf4a64 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -31,16 +31,22 @@ #include Ticker TickerMSearch; -bool udp_connected = false; - 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 port_multicast = 1900; // Multicast address and port - -bool udp_response_mutex = false; // M-Search response mutex to control re-entry IPAddress udp_remote_ip; // M-Search remote IP address uint16_t udp_remote_port; // M-Search remote port +bool udp_connected = false; +bool udp_response_mutex = false; // M-Search response mutex to control re-entry + +/*********************************************************************************************\ + * UPNP search targets +\*********************************************************************************************/ + +const char URN_BELKIN_DEVICE[] PROGMEM = "urn:belkin:device:**"; +const char UPNP_ROOTDEVICE[] PROGMEM = "upnp:rootdevice"; +const char SSDPSEARCH_ALL[] PROGMEM = "ssdpsearch:all"; +const char SSDP_ALL[] PROGMEM = "ssdp:all"; + /*********************************************************************************************\ * WeMo UPNP support routines \*********************************************************************************************/ @@ -50,12 +56,12 @@ 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://%s: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: {r3\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice - "USN: uuid:{r2::{r3\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice + "ST: %s\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice + "USN: uuid:%s::%s\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice "X-User-Agent: redsonic\r\n" "\r\n"; @@ -81,15 +87,15 @@ void WemoRespondToMSearch(int echo_type) TickerMSearch.detach(); if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { - String response = FPSTR(WEMO_MSEARCH); - response.replace("{r1", WiFi.localIP().toString()); - response.replace("{r2", WemoUuid()); + char type[24]; if (1 == echo_type) { // type1 echo 1g & dot 2g - response.replace("{r3", F("urn:Belkin:device:**")); + strcpy_P(type, URN_BELKIN_DEVICE); } else { // type2 echo 2g (echo, plus, show) - response.replace("{r3", F("upnp:rootdevice")); + strcpy_P(type, UPNP_ROOTDEVICE); } - PortUdp.write(response.c_str()); + char response[400]; + snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), type, WemoUuid().c_str(), type); + PortUdp.write(response); PortUdp.endPacket(); snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT)); } else { @@ -208,7 +214,8 @@ bool UdpDisconnect(void) bool UdpConnect(void) { if (!udp_connected) { - if (PortUdp.beginMulticast(WiFi.localIP(), ipMulticast, port_multicast)) { + // Simple Service Discovery Protocol (SSDP) + if (PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), 1900)) { AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED)); udp_response_mutex = false; udp_connected = true; @@ -238,28 +245,30 @@ void PollUdp(void) udp_remote_ip = PortUdp.remoteIP(); udp_remote_port = PortUdp.remotePort(); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"), - udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer); +// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"), +// udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer); - UpperCase(packet_buffer, packet_buffer); + uint32_t response_delay = UDP_MSEARCH_SEND_DELAY + ((millis() &0x7) * 100); // 1500 - 2200 msec + + LowerCase(packet_buffer, packet_buffer); RemoveSpace(packet_buffer); if (EMUL_WEMO == Settings.flag2.emulation) { - if (strstr_P(packet_buffer, PSTR("URN:BELKIN:DEVICE:**"))) { // type1 echo dot 2g, echo 1g's - TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, WemoRespondToMSearch, 1); + if (strstr_P(packet_buffer, URN_BELKIN_DEVICE)) { // type1 echo dot 2g, echo 1g's + TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1); return; } - else if (strstr_P(packet_buffer, PSTR("UPNP:ROOTDEVICE")) || // type2 Echo 2g (echo & echo plus) - strstr_P(packet_buffer, PSTR("SSDPSEARCH:ALL")) || - strstr_P(packet_buffer, PSTR("SSDP:ALL"))) { - TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, WemoRespondToMSearch, 2); + else if (strstr_P(packet_buffer, UPNP_ROOTDEVICE) || // type2 Echo 2g (echo & echo plus) + strstr_P(packet_buffer, SSDPSEARCH_ALL) || + strstr_P(packet_buffer, SSDP_ALL)) { + TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2); return; } } else { - if (strstr_P(packet_buffer, PSTR("URN:SCHEMAS-UPNP-ORG:DEVICE:BASIC:1")) || - strstr_P(packet_buffer, PSTR("UPNP:ROOTDEVICE")) || - strstr_P(packet_buffer, PSTR("SSDPSEARCH:ALL")) || - strstr_P(packet_buffer, PSTR("SSDP:ALL"))) { - TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, HueRespondToMSearch); + if (strstr_P(packet_buffer, PSTR("urn:schemas-upnp-org:device:basic:1")) || + strstr_P(packet_buffer, UPNP_ROOTDEVICE) || + strstr_P(packet_buffer, SSDPSEARCH_ALL) || + strstr_P(packet_buffer, SSDP_ALL)) { + TickerMSearch.attach_ms(response_delay, HueRespondToMSearch); return; } } @@ -343,9 +352,9 @@ const char WEMO_METASERVICE_XML[] PROGMEM = const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = "" "" - "" - "{x1" - "" + "" + "%d" + "" "" "\r\n"; @@ -386,18 +395,20 @@ void HandleUpnpEvent(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); - String request = WebServer->arg(0); + char event[500]; + strlcpy(event, WebServer->arg(0).c_str(), sizeof(event)); -// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), request.c_str()); +// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), event); - String state_xml = FPSTR(WEMO_RESPONSE_STATE_SOAP); //differentiate get and set state - if (request.indexOf(F("SetBinaryState")) > 0) { + char state = 'G'; + if (strstr_P(event, PSTR("SetBinaryState"))) { + state = 'S'; uint8_t power = POWER_TOGGLE; - if (request.indexOf(F("State>1 0) { + if (strstr_P(event, PSTR("State>10 0) { + else if (strstr_P(event, PSTR("State>0 0){ - state_xml.replace(F("Set"), F("Get")); - } - state_xml.replace("{x1", String(bitRead(power, devices_present -1))); - WSSend(200, CT_XML, state_xml); + + snprintf_P(event, sizeof(event), WEMO_RESPONSE_STATE_SOAP, state, bitRead(power, devices_present -1), state); + WSSend(200, CT_XML, event); } void HandleUpnpService(void) From e1c92b701b0c5528ca5384b2e1c9c0d8f46620d5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 26 Mar 2019 18:26:50 +0100 Subject: [PATCH 1182/2222] Change NULL to nullptr Change NULL to nullptr --- sonoff/Parsing.cpp | 6 +-- sonoff/_changelog.ino | 2 +- sonoff/settings.ino | 6 +-- sonoff/sonoff.ino | 68 +++++++++++++++---------------- sonoff/support.ino | 14 +++---- sonoff/support_rtc.ino | 2 +- sonoff/xdrv_01_webserver.ino | 18 ++++---- sonoff/xdrv_02_mqtt.ino | 8 ++-- sonoff/xdrv_04_light.ino | 18 ++++---- sonoff/xdrv_05_irremote.ino | 30 +++++++------- sonoff/xdrv_06_snfbridge.ino | 2 +- sonoff/xdrv_08_serial_bridge.ino | 4 +- sonoff/xdrv_09_timers.ino | 6 +-- sonoff/xdrv_10_rules.ino | 6 +-- sonoff/xdrv_11_knx.ino | 6 +-- sonoff/xdrv_13_display.ino | 28 ++++++------- sonoff/xdrv_16_tuyadimmer.ino | 4 +- sonoff/xdrv_17_rcswitch.ino | 6 +-- sonoff/xdrv_19_ps16dz_dimmer.ino | 16 ++++---- sonoff/xdsp_01_lcd.ino | 2 +- sonoff/xdsp_02_ssd1306.ino | 2 +- sonoff/xdsp_03_matrix.ino | 10 ++--- sonoff/xdsp_04_ili9341.ino | 2 +- sonoff/xdsp_05_epaper_29.ino | 2 +- sonoff/xnrg_03_pzem004t.ino | 2 +- sonoff/xnrg_04_mcp39f501.ino | 4 +- sonoff/xplg_wemohue.ino | 24 +++++------ sonoff/xplg_ws2812.ino | 2 +- sonoff/xsns_04_snfsc.ino | 2 +- sonoff/xsns_05_ds18x20_legacy.ino | 2 +- sonoff/xsns_09_bmp.ino | 8 ++-- sonoff/xsns_20_novasds.ino | 6 +-- sonoff/xsns_22_sr04.ino | 2 +- sonoff/xsns_34_hx711.ino | 18 ++++---- sonoff/xsns_37_rfsensor.ino | 10 ++--- 35 files changed, 174 insertions(+), 174 deletions(-) diff --git a/sonoff/Parsing.cpp b/sonoff/Parsing.cpp index 525277c74..6c68a3af4 100644 --- a/sonoff/Parsing.cpp +++ b/sonoff/Parsing.cpp @@ -415,7 +415,7 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t DEBUG_OUTPUT.println(argFilename); #endif //use GET to set the filename if uploading using blob - if (argFilename == F("blob") && hasArg(FPSTR(filename))) + if (argFilename == F("blob") && hasArg(FPSTR(filename))) argFilename = arg(FPSTR(filename)); } #ifdef DEBUG_ESP_HTTP_SERVER @@ -510,7 +510,7 @@ readfile: uint8_t endBuf[boundary.length()]; client.readBytes(endBuf, boundary.length()); - if (strstr((const char*)endBuf, boundary.c_str()) != NULL){ + if (strstr((const char*)endBuf, boundary.c_str()) != nullptr){ if(_currentHandler && _currentHandler->canUpload(_currentUri)) _currentHandler->upload(*this, _currentUri, *_currentUpload); _currentUpload->totalSize += _currentUpload->currentSize; @@ -571,7 +571,7 @@ readfile: arg.value = postArgs[iarg].value; } _currentArgCount = iarg; - if (postArgs) + if (postArgs) delete[] postArgs; return true; } diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 54ed9c21f..3d9c77a9d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -20,7 +20,7 @@ * Change image name BE_MINIMAL to FIRMWARE_MINIMAL and USE_xyz to FIRMWARE_xyz (#5106) * Change GUI weblog from XML to plain text solving possible empty screens (#5154) * Fix most compiler warnings - * Fix Display exception 28 when JSON value is NULL received + * Fix Display exception 28 when JSON value is nullptr received * Fix epaper driver (#4785) * Fix HAss Sensor Discovery Software Watchdog restart (#4831, #4988) * Fix allowable MAX_RULE_VARS to 16 (#4933) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index dff0d849f..ca8cd1b3a 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -306,7 +306,7 @@ void EepromEnd(void) uint16_t settings_crc = 0; uint32_t settings_location = SETTINGS_LOCATION; -uint8_t *settings_buffer = NULL; +uint8_t *settings_buffer = nullptr; /********************************************************************************************/ /* @@ -333,9 +333,9 @@ void SetFlashModeDout(void) void SettingsBufferFree(void) { - if (settings_buffer != NULL) { + if (settings_buffer != nullptr) { free(settings_buffer); - settings_buffer = NULL; + settings_buffer = nullptr; } } diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 458b12ed6..bcefc9a08 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -188,15 +188,15 @@ char* Format(char* output, const char* input, int size) char *token; uint8_t digits = 0; - if (strstr(input, "%")) { + if (strstr(input, "%") != nullptr) { strlcpy(output, input, size); token = strtok(output, "%"); if (strstr(input, "%") == input) { output[0] = '\0'; } else { - token = strtok(NULL, ""); + token = strtok(nullptr, ""); } - if (token != NULL) { + if (token != nullptr) { digits = atoi(token); if (digits) { char tmp[size]; @@ -221,10 +221,10 @@ char* Format(char* output, const char* input, int size) char* GetOtaUrl(char *otaurl, size_t otaurl_size) { - if (strstr(Settings.ota_url, "%04d") != NULL) { // OTA url contains placeholder for chip ID + if (strstr(Settings.ota_url, "%04d") != nullptr) { // OTA url contains placeholder for chip ID snprintf(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId() & 0x1fff); } - else if (strstr(Settings.ota_url, "%d") != NULL) { // OTA url contains placeholder for chip ID + else if (strstr(Settings.ota_url, "%d") != nullptr) { // OTA url contains placeholder for chip ID snprintf_P(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId()); } else { @@ -278,7 +278,7 @@ char* GetTopic_P(char *stopic, uint8_t prefix, char *topic, const char* subtopic char* GetFallbackTopic_P(char *stopic, uint8_t prefix, const char* subtopic) { - return GetTopic_P(stopic, prefix +4, NULL, subtopic); + return GetTopic_P(stopic, prefix +4, nullptr, subtopic); } char* GetStateText(uint8_t state) @@ -452,7 +452,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) char command [CMDSZ]; char stemp1[TOPSZ]; char *p; - char *type = NULL; + char *type = nullptr; uint8_t lines = 1; bool jsflg = false; bool grpflg = false; @@ -480,7 +480,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (XdrvMqttData(topicBuf, sizeof(topicBuf), dataBuf, sizeof(dataBuf))) { return; } - grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != NULL); + grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != nullptr); GetFallbackTopic_P(stemp1, CMND, ""); // Full Fallback topic = cmnd/DVES_xxxxxxxx_fb/ fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); @@ -488,7 +488,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type) index = 1; - if (type != NULL) { + if (type != nullptr) { type++; for (i = 0; i < strlen(type); i++) { type[i] = toupper(type[i]); @@ -505,7 +505,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_RESULT D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " %s, " D_DATA " %s"), grpflg, index, type, dataBuf); - if (type != NULL) { + if (type != nullptr) { Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); if (Settings.ledstate &0x02) { blinks++; } @@ -538,7 +538,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) XdrvMailbox.data = dataBuf; if (!XdrvCall(FUNC_COMMAND)) { if (!XsnsCall(FUNC_COMMAND)) { - type = NULL; // Unknown command + type = nullptr; // Unknown command } } } @@ -547,7 +547,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) uint8_t bl_pointer = (!backlog_pointer) ? MAX_BACKLOG -1 : backlog_pointer; bl_pointer--; char *blcommand = strtok(dataBuf, ";"); - while ((blcommand != NULL) && (backlog_index != bl_pointer)) { + while ((blcommand != nullptr) && (backlog_index != bl_pointer)) { while(true) { blcommand = Trim(blcommand); if (!strncasecmp_P(blcommand, PSTR(D_CMND_BACKLOG), strlen(D_CMND_BACKLOG))) { @@ -561,7 +561,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) backlog_index++; if (backlog_index >= MAX_BACKLOG) backlog_index = 0; } - blcommand = strtok(NULL, ";"); + blcommand = strtok(nullptr, ";"); } // Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_APPENDED); mqtt_data[0] = '\0'; @@ -974,7 +974,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) // {"NAME":"Generic","GPIO":[17,254,29,254,7,254,254,254,138,254,139,254,254],"FLAG":1,"BASE":255} bool error = false; - if (!strstr(dataBuf, "{")) { // If no JSON it must be parameter + if (strstr(dataBuf, "{") == nullptr) { // If no JSON it must be parameter if ((payload > 0) && (payload <= MAXMODULE)) { ModuleDefault(payload -1); // Copy template module if (USER_MODULE == Settings.module) { restart_flag = 2; } @@ -1193,7 +1193,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) else if (CMND_HOSTNAME == command_code) { if (!grpflg && (data_len > 0) && (data_len < sizeof(Settings.hostname))) { strlcpy(Settings.hostname, (SC_DEFAULT == Shortcut(dataBuf)) ? WIFI_HOSTNAME : dataBuf, sizeof(Settings.hostname)); - if (strstr(Settings.hostname,"%")) { + if (strstr(Settings.hostname, "%") != nullptr) { strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); } restart_flag = 2; @@ -1238,15 +1238,15 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (max_relays > sizeof(Settings.interlock[0]) * 8) { max_relays = sizeof(Settings.interlock[0]) * 8; } if (max_relays > 1) { // Only interlock with more than 1 relay if (data_len > 0) { - if (strstr(dataBuf, ",")) { // Interlock entry + if (strstr(dataBuf, ",") != nullptr) { // Interlock entry for (uint8_t i = 0; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } // Reset current interlocks char *group; char *q; uint8_t group_index = 0; power_t relay_mask = 0; - for (group = strtok_r(dataBuf, " ", &q); group && group_index < MAX_INTERLOCKS; group = strtok_r(NULL, " ", &q)) { + for (group = strtok_r(dataBuf, " ", &q); group && group_index < MAX_INTERLOCKS; group = strtok_r(nullptr, " ", &q)) { char *str; - for (str = strtok_r(group, ",", &p); str; str = strtok_r(NULL, ",", &p)) { + for (str = strtok_r(group, ",", &p); str; str = strtok_r(nullptr, ",", &p)) { int pbit = atoi(str); if ((pbit > 0) && (pbit <= max_relays)) { // Only valid relays pbit--; @@ -1329,9 +1329,9 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (payload < 15) { p = strtok (dataBuf, ":"); if (p) { - p = strtok (NULL, ":"); + p = strtok (nullptr, ":"); if (p) { - Settings.timezone_minutes = strtol(p, NULL, 10); + Settings.timezone_minutes = strtol(p, nullptr, 10); if (Settings.timezone_minutes > 59) { Settings.timezone_minutes = 59; } } } @@ -1352,7 +1352,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) uint8_t ts = 0; if (CMND_TIMEDST == command_code) { ts = 1; } if (data_len > 0) { - if (strstr(dataBuf, ",")) { // Process parameter entry + if (strstr(dataBuf, ",") != nullptr) { // Process parameter entry uint8_t tpos = 0; // Parameter index int value = 0; p = dataBuf; // Parameters like "1, 2,3 , 4 ,5, -120" or ",,,,,+240" @@ -1426,9 +1426,9 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) I2cScan(mqtt_data, sizeof(mqtt_data)); } #endif // USE_I2C - else type = NULL; // Unknown command + else type = nullptr; // Unknown command } - if (type == NULL) { + if (type == nullptr) { blinks = 201; snprintf_P(topicBuf, sizeof(topicBuf), PSTR(D_JSON_COMMAND)); Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); @@ -1608,18 +1608,18 @@ void ExecuteCommand(char *cmnd, int source) ShowSource(source); token = strtok(cmnd, " "); - if (token != NULL) { + if (token != nullptr) { start = strrchr(token, '/'); // Skip possible cmnd/sonoff/ preamble if (start) { token = start +1; } } - uint16_t size = (token != NULL) ? strlen(token) : 0; + uint16_t size = (token != nullptr) ? strlen(token) : 0; char stopic[size +2]; // / + \0 - snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == NULL) ? "" : token); + snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == nullptr) ? "" : token); - token = strtok(NULL, ""); - size = (token != NULL) ? strlen(token) : 0; + token = strtok(nullptr, ""); + size = (token != nullptr) ? strlen(token) : 0; char svalue[size +1]; - strlcpy(svalue, (token == NULL) ? "" : token, sizeof(svalue)); // Fixed 5.8.0b + strlcpy(svalue, (token == nullptr) ? "" : token, sizeof(svalue)); // Fixed 5.8.0b MqttDataHandler(stopic, (uint8_t*)svalue, strlen(svalue)); } @@ -1807,10 +1807,10 @@ bool MqttShowSensor(void) } XsnsCall(FUNC_JSON_APPEND); bool json_data_available = (strlen(mqtt_data) - json_data_start); - if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE))) { + if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE)) != nullptr) { ResponseAppend_P(PSTR(",\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), PressureUnit().c_str()); } - if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE))) { + if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE)) != nullptr) { ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); } ResponseAppend_P(PSTR("}")); @@ -2025,8 +2025,8 @@ void Every250mSeconds(void) #ifndef FIRMWARE_MINIMAL if (RtcSettings.ota_loader) { char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it - char *pch = strrchr((bch != NULL) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin - char *ech = strrchr((bch != NULL) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin + char *pch = strrchr((bch != nullptr) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin + char *ech = strrchr((bch != nullptr) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin if (!pch) { pch = ech; } if (pch) { mqtt_data[pch - mqtt_data] = '\0'; @@ -2611,7 +2611,7 @@ void setup(void) Format(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); Format(mqtt_topic, Settings.mqtt_topic, sizeof(mqtt_topic)); - if (strstr(Settings.hostname, "%")) { + if (strstr(Settings.hostname, "%") != nullptr) { strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname, mqtt_topic, ESP.getChipId() & 0x1FFF); } else { diff --git a/sonoff/support.ino b/sonoff/support.ino index 823655ce4..07edd039a 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -139,15 +139,15 @@ size_t strchrspn(const char *str1, int character) char* subStr(char* dest, char* str, const char *delim, int index) { char *act; - char *sub = NULL; + char *sub = nullptr; char *ptr; int i; // Since strtok consumes the first arg, make a copy strncpy(dest, str, strlen(str)+1); - for (i = 1, act = dest; i <= index; i++, act = NULL) { + for (i = 1, act = dest; i <= index; i++, act = nullptr) { sub = strtok_r(act, delim, &ptr); - if (sub == NULL) break; + if (sub == nullptr) break; } sub = Trim(sub); return sub; @@ -377,9 +377,9 @@ bool ParseIp(uint32_t* addr, const char* str) *addr = 0; for (i = 0; i < 4; i++) { - part[i] = strtoul(str, NULL, 10); // Convert byte + part[i] = strtoul(str, nullptr, 10); // Convert byte str = strchr(str, '.'); - if (str == NULL || *str == '\0') { + if (str == nullptr || *str == '\0') { break; // No more separators, exit } str++; // Point to next character after separator @@ -422,7 +422,7 @@ bool NewerVersion(char* version_str) return false; // Bail if we can't duplicate. Assume bad. } // Loop through the version string, splitting on '.' seperators. - for (char *str = strtok_r(version_dup, ".", &str_ptr); str && i < sizeof(VERSION); str = strtok_r(NULL, ".", &str_ptr), i++) { + for (char *str = strtok_r(version_dup, ".", &str_ptr); str && i < sizeof(VERSION); str = strtok_r(nullptr, ".", &str_ptr), i++) { int field = atoi(str); // The fields in a version string can only range from 0-255. if ((field < 0) || (field > 255)) { @@ -1219,7 +1219,7 @@ void SetSeriallog(uint8_t loglevel) #ifdef USE_WEBSERVER void GetLog(uint8_t idx, char** entry_pp, size_t* len_p) { - char* entry_p = NULL; + char* entry_p = nullptr; size_t len = 0; if (idx) { diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index 9a36951f0..5af8b49a0 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -61,7 +61,7 @@ String GetBuildDateAndTime(void) // sscanf(mdate, "%s %d %d", bdt, &day, &year); // Not implemented in 2.3.0 and probably too much code uint8_t i = 0; - for (char *str = strtok_r(mdate, " ", &p); str && i < 3; str = strtok_r(NULL, " ", &p)) { + for (char *str = strtok_r(mdate, " ", &p); str && i < 3; str = strtok_r(nullptr, " ", &p)) { switch (i++) { case 0: // Month smonth = str; diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index f34bfda09..48932fb0d 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -41,7 +41,7 @@ #include #ifdef USE_RF_FLASH -uint8_t *efm8bb1_update = NULL; +uint8_t *efm8bb1_update = nullptr; #endif // USE_RF_FLASH enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1 }; @@ -524,7 +524,7 @@ void WifiManagerBegin(bool reset_only) int channel = WIFI_SOFT_AP_CHANNEL; if ((channel < 1) || (channel > 13)) { channel = 1; } - WiFi.softAP(my_hostname, NULL, channel); + WiFi.softAP(my_hostname, nullptr, channel); delay(500); // Without delay I've seen the IP address blank /* Setup the DNS server redirecting all the domains to the apIP */ @@ -689,7 +689,7 @@ void WSContentStart_P(const char* title, bool auth) WSContentBegin(200, CT_HTML); - if (title != NULL) { + if (title != nullptr) { char ctitle[strlen_P(title) +1]; strcpy_P(ctitle, title); // Get title from flash to RAM WSContentSend_P(HTTP_HEAD, Settings.friendlyname[0], ctitle); @@ -710,7 +710,7 @@ void WSContentSendStyle_P(const char* style) } WSContentSend_P(HTTP_HEAD_STYLE1); WSContentSend_P(HTTP_HEAD_STYLE2); - if (style != NULL) { + if (style != nullptr) { WSContentSend_P(style); } WSContentSend_P(HTTP_HEAD_STYLE3, ModuleName().c_str(), Settings.friendlyname[0]); @@ -729,7 +729,7 @@ void WSContentSendStyle_P(const char* style) void WSContentSendStyle(void) { - WSContentSendStyle_P(NULL); + WSContentSendStyle_P(nullptr); } void WSContentButton(uint8_t title_index) @@ -1359,7 +1359,7 @@ void WifiSaveSettings(void) WebGetArg("h", tmp, sizeof(tmp)); strlcpy(Settings.hostname, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp, sizeof(Settings.hostname)); - if (strstr(Settings.hostname,"%")) { + if (strstr(Settings.hostname, "%") != nullptr) { strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); } WebGetArg("s1", tmp, sizeof(tmp)); @@ -1885,10 +1885,10 @@ void HandleUploadLoop(void) } #ifdef USE_RF_FLASH else if (UPL_EFM8BB1 == upload_file_type) { - if (efm8bb1_update != NULL) { // We have carry over data since last write, i. e. a start but not an end + if (efm8bb1_update != nullptr) { // We have carry over data since last write, i. e. a start but not an end ssize_t result = rf_glue_remnant_with_new_data_and_write(efm8bb1_update, upload.buf, upload.currentSize); free(efm8bb1_update); - efm8bb1_update = NULL; + efm8bb1_update = nullptr; if (result != 0) { upload_error = abs(result); // 2 = Not enough space, 8 = File invalid return; @@ -1907,7 +1907,7 @@ void HandleUploadLoop(void) // A remnant has been detected, allocate data for it plus a null termination byte size_t remnant_sz = upload.currentSize - result; efm8bb1_update = (uint8_t *) malloc(remnant_sz + 1); - if (efm8bb1_update == NULL) { + if (efm8bb1_update == nullptr) { upload_error = 2; // Not enough space - Unable to allocate memory to store new RF firmware return; } diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 37bdd97c2..b4228b11e 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -301,7 +301,7 @@ void MqttConnected(void) GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); MqttSubscribe(stopic); - if (strstr(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != NULL) { + if (strstr(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != nullptr) { GetTopic_P(stopic, CMND, Settings.mqtt_grptopic, PSTR("#")); MqttSubscribe(stopic); GetFallbackTopic_P(stopic, CMND, PSTR("#")); @@ -431,8 +431,8 @@ void MqttReconnect(void) mqtt_retry_counter = Settings.mqtt_retry; global_state.mqtt_down = 1; - char *mqtt_user = NULL; - char *mqtt_pwd = NULL; + char *mqtt_user = nullptr; + char *mqtt_pwd = nullptr; if (strlen(Settings.mqtt_user) > 0) mqtt_user = Settings.mqtt_user; if (strlen(Settings.mqtt_pwd) > 0) mqtt_pwd = Settings.mqtt_pwd; @@ -607,7 +607,7 @@ bool MqttCommand(void) char *mqtt_part = strtok(dataBuf, " "); if (mqtt_part) { strlcpy(stemp1, mqtt_part, sizeof(stemp1)); - mqtt_part = strtok(NULL, " "); + mqtt_part = strtok(nullptr, " "); if (mqtt_part) { strlcpy(mqtt_data, mqtt_part, sizeof(mqtt_data)); } else { diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index fc9d1a635..5dae14ce7 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -1231,9 +1231,9 @@ bool LightColorEntry(char *buffer, uint8_t buffer_length) } memset(&light_entry_color, 0x00, sizeof(light_entry_color)); - if (strstr(buffer, ",")) { // Decimal entry + if (strstr(buffer, ",") != nullptr) { // Decimal entry int8_t i = 0; - for (str = strtok_r(buffer, ",", &p); str && i < 6; str = strtok_r(NULL, ",", &p)) { + for (str = strtok_r(buffer, ",", &p); str && i < 6; str = strtok_r(nullptr, ",", &p)) { if (i < 5) { light_entry_color[i++] = atoi(str); } @@ -1345,16 +1345,16 @@ bool LightCommand(void) bool validHSB = (XdrvMailbox.data_len > 0); if (validHSB) { uint16_t HSB[3]; - if (strstr(XdrvMailbox.data, ",")) { // Command with 3 comma separated parameters, Hue (0 0); char scolor[25]; if (validtable) { - if (strstr(XdrvMailbox.data, ",")) { // Command with up to 5 comma separated parameters + if (strstr(XdrvMailbox.data, ",") != nullptr) { // Command with up to 5 comma separated parameters for (int i = 0; i < LST_RGBWC; i++) { char *substr; if (0 == i) { substr = strtok(XdrvMailbox.data, ","); } else { - substr = strtok(NULL, ","); + substr = strtok(nullptr, ","); } - if (substr != NULL) { + if (substr != nullptr) { Settings.rgbwwTable[i] = atoi(substr); } } diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 9592555b8..7e6501142 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -54,7 +54,7 @@ const char kIrHvacVendors[] PROGMEM = "Toshiba|Mitsubishi|LG|Fujitsu" ; // HVAC LG #define HVAC_LG_DATALEN 7 -IRMitsubishiAC *mitsubir = NULL; +IRMitsubishiAC *mitsubir = nullptr; const char kFanSpeedOptions[] = "A12345S"; const char kHvacModeOptions[] = "HDCA"; @@ -66,7 +66,7 @@ const char kHvacModeOptions[] = "HDCA"; #include -IRsend *irsend = NULL; +IRsend *irsend = nullptr; bool irsend_active = false; void IrSendInit(void) @@ -90,7 +90,7 @@ void IrSendInit(void) #include -IRrecv *irrecv = NULL; +IRrecv *irrecv = nullptr; unsigned long ir_lasttime = 0; @@ -189,7 +189,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po char *p; uint8_t mode; - if (HVAC_Mode == NULL) { + if (HVAC_Mode == nullptr) { p = (char *)kHvacModeOptions; // default HVAC_HOT } else { @@ -204,7 +204,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po data[6] = (uint8_t)0x07; // Turn OFF HVAC } - if (HVAC_FanMode == NULL) { + if (HVAC_FanMode == nullptr) { p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO } else { @@ -283,7 +283,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC mitsubir->stateReset(); - if (HVAC_Mode == NULL) { + if (HVAC_Mode == nullptr) { p = (char *)kHvacModeOptions; // default HVAC_HOT } else { @@ -297,7 +297,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC mitsubir->setPower(HVAC_Power); - if (HVAC_FanMode == NULL) { + if (HVAC_FanMode == nullptr) { p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO } else { @@ -350,7 +350,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, else { // Set code for HVAC Mode - data[3] - if (HVAC_Mode == NULL) { + if (HVAC_Mode == nullptr) { p = (char *)kHvacModeOptions; // default HVAC_HOT } else { @@ -394,7 +394,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, data[4] = (uint8_t)(Temp - 15); // Set code for HVAC fan mode - data[5] - if (HVAC_FanMode == NULL) { + if (HVAC_FanMode == nullptr) { p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO } else { @@ -462,7 +462,7 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po ac.setSwing(FUJITSU_AC_SWING_VERT); char *p; - if (NULL == HVAC_Mode) { + if (nullptr == HVAC_Mode) { p = (char *)kFujitsuHvacModeOptions; } else { @@ -473,7 +473,7 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po } ac.setMode(modes[p - kFujitsuHvacModeOptions]); - if (HVAC_FanMode == NULL) { + if (HVAC_FanMode == nullptr) { p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO } else { @@ -518,7 +518,7 @@ bool IrSendCommand(void) if (XdrvMailbox.data_len) { Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - if (!strstr(XdrvMailbox.data, "{")) { // If no JSON it must be rawdata + if (strstr(XdrvMailbox.data, "{") == nullptr) { // If no JSON it must be rawdata // IRSend frequency, rawdata, rawdata ... char *p; char *str = strtok_r(XdrvMailbox.data, ", ", &p); @@ -531,8 +531,8 @@ bool IrSendCommand(void) count++; uint16_t raw_array[count]; // It's safe to use stack for up to 240 packets (limited by mqtt_data length) uint8_t i = 0; - for (str = strtok_r(NULL, ", ", &p); str && i < count; str = strtok_r(NULL, ", ", &p)) { - raw_array[i++] = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input + for (str = strtok_r(nullptr, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p)) { + raw_array[i++] = strtoul(str, nullptr, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input } // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), count, freq, raw_array[0], raw_array[count -1]); @@ -560,7 +560,7 @@ bool IrSendCommand(void) char parm_uc[10]; const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; uint32_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; - uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], NULL, 0); + uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); if (protocol && bits) { char protocol_text[20]; int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 14947fd77..f2550bf8d 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -98,7 +98,7 @@ ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uin glue_record_sz = strlen((const char *) remnant_data) + record_end; glue_buf = (uint8_t *) malloc(glue_record_sz); - if (glue_buf == NULL) { return -2; } // Not enough space + if (glue_buf == nullptr) { return -2; } // Not enough space // Assemble new glue buffer memcpy(glue_buf, remnant_data, strlen((const char *) remnant_data)); diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index bf3221025..e9f8294ca 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -31,10 +31,10 @@ enum SerialBridgeCommands { CMND_SSERIALSEND, CMND_SBAUDRATE }; const char kSerialBridgeCommands[] PROGMEM = D_CMND_SSERIALSEND "|" D_CMND_SBAUDRATE; -TasmotaSerial *SerialBridgeSerial = NULL; +TasmotaSerial *SerialBridgeSerial = nullptr; unsigned long serial_bridge_polling_window = 0; -char *serial_bridge_buffer = NULL; +char *serial_bridge_buffer = nullptr; int serial_bridge_in_byte_counter = 0; bool serial_bridge_active = true; bool serial_bridge_raw = false; diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 59d9300f4..05e931254 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -387,7 +387,7 @@ bool TimerCommand(void) strlcpy(time_str, root[parm_uc], sizeof(time_str)); const char *substr = strtok(time_str, ":"); - if (substr != NULL) { + if (substr != nullptr) { if (strchr(substr, '-')) { sign = 1; substr++; @@ -396,8 +396,8 @@ bool TimerCommand(void) if (sign) { value += 12; } // Allow entering timer offset from -11:59 to -00:01 converted to 12:01 to 23:59 if (value > 23) { value = 23; } itime = value * 60; - substr = strtok(NULL, ":"); - if (substr != NULL) { + substr = strtok(nullptr, ":"); + if (substr != nullptr) { value = atoi(substr); if (value < 0) { value = 0; } if (value > 59) { value = 59; } diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index b2761a2d4..2a93ee86f 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -672,10 +672,10 @@ String RulesSubscribe(const char *data, int data_len) char * pos = strtok(parameters, ","); if (pos) { event_name = Trim(pos); - pos = strtok(NULL, ","); + pos = strtok(nullptr, ","); if (pos) { topic = Trim(pos); - pos = strtok(NULL, ","); + pos = strtok(nullptr, ","); if (pos) { key = Trim(pos); } @@ -1203,7 +1203,7 @@ bool RulesCommand(void) } else if ((CMND_SCALE == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { - if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry + if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry char sub_string[XdrvMailbox.data_len +1]; double valueIN = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 1)); diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 45c9fe15f..b92ed1c7b 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -1086,7 +1086,7 @@ bool KnxCommand(void) else if (CMND_KNX_PA == command_code) { if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ".")) { // Process parameter entry + if (strstr(XdrvMailbox.data, ".") != nullptr) { // Process parameter entry char sub_string[XdrvMailbox.data_len]; int pa_area = atoi(subStr(sub_string, XdrvMailbox.data, ".", 1)); @@ -1113,7 +1113,7 @@ bool KnxCommand(void) else if ((CMND_KNX_GA == command_code) && (index > 0) && (index <= MAX_KNX_GA)) { if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry + if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry char sub_string[XdrvMailbox.data_len]; int ga_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); @@ -1162,7 +1162,7 @@ bool KnxCommand(void) else if ((CMND_KNX_CB == command_code) && (index > 0) && (index <= MAX_KNX_CB)) { if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry + if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry char sub_string[XdrvMailbox.data_len]; int cb_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 89dde70d1..8a05d68f3 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -503,9 +503,9 @@ void DisplayClearScreenBuffer(void) void DisplayFreeScreenBuffer(void) { - if (disp_screen_buffer != NULL) { + if (disp_screen_buffer != nullptr) { for (uint8_t i = 0; i < disp_screen_buffer_rows; i++) { - if (disp_screen_buffer[i] != NULL) { free(disp_screen_buffer[i]); } + if (disp_screen_buffer[i] != nullptr) { free(disp_screen_buffer[i]); } } free(disp_screen_buffer); disp_screen_buffer_cols = 0; @@ -518,16 +518,16 @@ void DisplayAllocScreenBuffer(void) if (!disp_screen_buffer_cols) { disp_screen_buffer_rows = Settings.display_rows; disp_screen_buffer = (char**)malloc(sizeof(*disp_screen_buffer) * disp_screen_buffer_rows); - if (disp_screen_buffer != NULL) { + if (disp_screen_buffer != nullptr) { for (uint8_t i = 0; i < disp_screen_buffer_rows; i++) { disp_screen_buffer[i] = (char*)malloc(sizeof(*disp_screen_buffer[i]) * (Settings.display_cols[0] +1)); - if (disp_screen_buffer[i] == NULL) { + if (disp_screen_buffer[i] == nullptr) { DisplayFreeScreenBuffer(); break; } } } - if (disp_screen_buffer != NULL) { + if (disp_screen_buffer != nullptr) { disp_screen_buffer_cols = Settings.display_cols[0] +1; DisplayClearScreenBuffer(); } @@ -562,9 +562,9 @@ void DisplayClearLogBuffer(void) void DisplayFreeLogBuffer(void) { - if (disp_log_buffer != NULL) { + if (disp_log_buffer != nullptr) { for (uint8_t i = 0; i < DISPLAY_LOG_ROWS; i++) { - if (disp_log_buffer[i] != NULL) { free(disp_log_buffer[i]); } + if (disp_log_buffer[i] != nullptr) { free(disp_log_buffer[i]); } } free(disp_log_buffer); disp_log_buffer_cols = 0; @@ -575,16 +575,16 @@ void DisplayAllocLogBuffer(void) { if (!disp_log_buffer_cols) { disp_log_buffer = (char**)malloc(sizeof(*disp_log_buffer) * DISPLAY_LOG_ROWS); - if (disp_log_buffer != NULL) { + if (disp_log_buffer != nullptr) { for (uint8_t i = 0; i < DISPLAY_LOG_ROWS; i++) { disp_log_buffer[i] = (char*)malloc(sizeof(*disp_log_buffer[i]) * (Settings.display_cols[0] +1)); - if (disp_log_buffer[i] == NULL) { + if (disp_log_buffer[i] == nullptr) { DisplayFreeLogBuffer(); break; } } } - if (disp_log_buffer != NULL) { + if (disp_log_buffer != nullptr) { disp_log_buffer_cols = Settings.display_cols[0] +1; DisplayClearLogBuffer(); } @@ -608,7 +608,7 @@ void DisplayLogBufferAdd(char* txt) char* DisplayLogBuffer(char temp_code) { - char* result = NULL; + char* result = nullptr; if (disp_log_buffer_cols) { if (disp_log_buffer_idx != disp_log_buffer_ptr) { result = disp_log_buffer[disp_log_buffer_ptr]; @@ -616,7 +616,7 @@ char* DisplayLogBuffer(char temp_code) if (DISPLAY_LOG_ROWS == disp_log_buffer_ptr) { disp_log_buffer_ptr = 0; } char *pch = strchr(result, '~'); // = 0x7E (~) Replace degrees character (276 octal) - if (pch != NULL) { result[pch - result] = temp_code; } + if (pch != nullptr) { result[pch - result] = temp_code; } } } return result; @@ -829,12 +829,12 @@ void DisplayMqttSubscribe(void) ntopic[0] = '\0'; strlcpy(stopic, Settings.mqtt_fulltopic, sizeof(stopic)); char *tp = strtok(stopic, "/"); - while (tp != NULL) { + while (tp != nullptr) { if (!strcmp_P(tp, PSTR(MQTT_TOKEN_PREFIX))) { break; } strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); // Add single-level wildcards - tp = strtok(NULL, "/"); + tp = strtok(nullptr, "/"); } strncat(ntopic, Settings.mqtt_prefix[2], sizeof(ntopic) - strlen(ntopic) -1); // Subscribe to tele messages strncat_P(ntopic, PSTR("/#"), sizeof(ntopic) - strlen(ntopic) -1); // Add multi-level wildcard diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index 53c4984cc..f9b3665e4 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -53,7 +53,7 @@ uint8_t tuya_cmd_checksum = 0; // Checksum of tuya command uint8_t tuya_data_len = 0; // Data lenght of command int8_t tuya_wifi_state = -2; // Keep MCU wifi-status in sync with WifiState() -char *tuya_buffer = NULL; // Serial receive buffer +char *tuya_buffer = nullptr; // Serial receive buffer int tuya_byte_counter = 0; // Index in serial receive buffer /*********************************************************************************************\ @@ -284,7 +284,7 @@ void TuyaInit(void) Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID; } tuya_buffer = (char*)(malloc(TUYA_BUFFER_SIZE)); - if (tuya_buffer != NULL) { + if (tuya_buffer != nullptr) { TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); if (TuyaSerial->begin(9600)) { if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index aaa594b2a..8018eaa2d 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -107,7 +107,7 @@ bool RfSendCommand(void) if (root.success()) { // RFsend {"data":0x501014,"bits":24,"protocol":1,"repeat":10,"pulse":350} char parm_uc[10]; - data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input + data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], nullptr, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_BITS))]; protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PROTOCOL))]; repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_REPEAT))]; @@ -116,10 +116,10 @@ bool RfSendCommand(void) // RFsend data, bits, protocol, repeat, pulse char *p; uint8_t i = 0; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 5; str = strtok_r(NULL, ", ", &p)) { + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 5; str = strtok_r(nullptr, ", ", &p)) { switch (i++) { case 0: - data = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input + data = strtoul(str, nullptr, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input break; case 1: bits = atoi(str); diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index e4b71bb18..ab58b6d9d 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -35,8 +35,8 @@ bool ps16dz_ignore_dim = false; // Flag to skip serial send to preven //uint64_t ps16dz_seq = 0; -char *ps16dz_tx_buffer = NULL; // Serial transmit buffer -char *ps16dz_rx_buffer = NULL; // Serial receive buffer +char *ps16dz_tx_buffer = nullptr; // Serial transmit buffer +char *ps16dz_rx_buffer = nullptr; // Serial receive buffer int ps16dz_byte_counter = 0; /*********************************************************************************************\ @@ -135,9 +135,9 @@ bool PS16DZModuleSelected(void) void PS16DZInit(void) { ps16dz_tx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); - if (ps16dz_tx_buffer != NULL) { + if (ps16dz_tx_buffer != nullptr) { ps16dz_rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); - if (ps16dz_rx_buffer != NULL) { + if (ps16dz_rx_buffer != nullptr) { PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); if (PS16DZSerial->begin(19200)) { if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } @@ -168,10 +168,10 @@ void PS16DZSerialInput(void) char *end_str; char *string = ps16dz_rx_buffer+10; char* token = strtok_r(string, ",", &end_str); - while (token != NULL) { + while (token != nullptr) { char* end_token; char* token2 = strtok_r(token, ":", &end_token); - char* token3 = strtok_r(NULL, ":", &end_token); + char* token3 = strtok_r(nullptr, ":", &end_token); if(!strncmp(token2, "\"switch\"", 8)){ bool ps16dz_power = !strncmp(token3, "\"on\"", 4)?true:false; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: power received: %s"), token3); @@ -193,10 +193,10 @@ void PS16DZSerialInput(void) } } else if(!strncmp(token2, "\"sequence\"", 10)){ - //ps16dz_seq = strtoull(token3+1, NULL, 10); + //ps16dz_seq = strtoull(token3+1, nullptr, 10); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: sequence received: %s"), token3); } - token = strtok_r(NULL, ",", &end_str); + token = strtok_r(nullptr, ",", &end_str); } } else if(!strncmp(ps16dz_rx_buffer+3, "SETTING", 7)) { diff --git a/sonoff/xdsp_01_lcd.ino b/sonoff/xdsp_01_lcd.ino index 28d045858..c0877a859 100644 --- a/sonoff/xdsp_01_lcd.ino +++ b/sonoff/xdsp_01_lcd.ino @@ -127,7 +127,7 @@ bool LcdPrintLog(void) if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } char* txt = DisplayLogBuffer('\337'); - if (txt != NULL) { + if (txt != nullptr) { uint8_t last_row = Settings.display_rows -1; for (uint8_t i = 0; i < last_row; i++) { diff --git a/sonoff/xdsp_02_ssd1306.ino b/sonoff/xdsp_02_ssd1306.ino index 9697e4db0..8d8b696d7 100644 --- a/sonoff/xdsp_02_ssd1306.ino +++ b/sonoff/xdsp_02_ssd1306.ino @@ -141,7 +141,7 @@ void Ssd1306PrintLog(void) if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { + if (txt != nullptr) { uint8_t last_row = Settings.display_rows -1; oled->clearDisplay(); diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index 2535c92d9..a77b5df1e 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -37,7 +37,7 @@ int16_t mtx_x = 0; int16_t mtx_y = 0; //char mtx_buffer[MTX_MAX_SCREEN_BUFFER]; -char *mtx_buffer = NULL; +char *mtx_buffer = nullptr; uint8_t mtx_mode = 0; uint8_t mtx_loop = 0; @@ -140,9 +140,9 @@ void MatrixScrollUp(char* txt, int loop) disp_refresh = Settings.display_refresh; strlcpy(tmpbuf, txt, sizeof(tmpbuf)); char *p = strtok(tmpbuf, separators); - while (p != NULL && wordcounter < 40) { + while (p != nullptr && wordcounter < 40) { words[wordcounter++] = p; - p = strtok(NULL, separators); + p = strtok(nullptr, separators); } for (uint8_t i = 0; i < mtx_matrices; i++) { matrix[i]->clear(); @@ -196,7 +196,7 @@ void MatrixInit(uint8_t mode) void MatrixInitDriver(void) { mtx_buffer = (char*)(malloc(MTX_MAX_SCREEN_BUFFER)); - if (mtx_buffer != NULL) { + if (mtx_buffer != nullptr) { if (!Settings.display_model) { if (I2cDevice(Settings.display_address[1])) { Settings.display_model = XDSP_03; @@ -239,7 +239,7 @@ void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8 void MatrixPrintLog(uint8_t direction) { char* txt = (!mtx_done) ? DisplayLogBuffer('\370') : mtx_buffer; - if (txt != NULL) { + if (txt != nullptr) { if (!mtx_state) { mtx_state = 1; } if (!mtx_done) { diff --git a/sonoff/xdsp_04_ili9341.ino b/sonoff/xdsp_04_ili9341.ino index f50164e59..bf3c2729c 100644 --- a/sonoff/xdsp_04_ili9341.ino +++ b/sonoff/xdsp_04_ili9341.ino @@ -147,7 +147,7 @@ void Ili9341PrintLog(void) } char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { + if (txt != nullptr) { uint8_t size = Settings.display_size; uint16_t theight = size * TFT_FONT_HEIGTH; diff --git a/sonoff/xdsp_05_epaper_29.ino b/sonoff/xdsp_05_epaper_29.ino index 6f4034ece..c1daf8259 100644 --- a/sonoff/xdsp_05_epaper_29.ino +++ b/sonoff/xdsp_05_epaper_29.ino @@ -200,7 +200,7 @@ void EpdPrintLog(void) } char* txt = DisplayLogBuffer('\040'); - if (txt != NULL) { + if (txt != nullptr) { uint8_t size = Settings.display_size; uint16_t theight = size * EPD_FONT_HEIGTH; diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index a15d61ba1..b2c72bfa8 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -32,7 +32,7 @@ #include -TasmotaSerial *PzemSerial = NULL; +TasmotaSerial *PzemSerial = nullptr; #define PZEM_VOLTAGE (uint8_t)0xB0 #define RESP_VOLTAGE (uint8_t)0xA0 diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index d878d9e8b..5d6adec33 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -67,7 +67,7 @@ #define MCP_BUFFER_SIZE 60 #include -TasmotaSerial *McpSerial = NULL; +TasmotaSerial *McpSerial = nullptr; typedef struct mcp_cal_registers_type { uint16_t gain_current_rms; @@ -92,7 +92,7 @@ typedef struct mcp_cal_registers_type { uint16_t accumulation_interval; } mcp_cal_registers_type; -char *mcp_buffer = NULL; +char *mcp_buffer = nullptr; unsigned long mcp_window = 0; unsigned long mcp_kWhcounter = 0; uint32_t mcp_system_configuration = 0x03000000; diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 60edf4a64..1c0a4f782 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -239,7 +239,7 @@ void PollUdp(void) AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); - if (strstr_P(packet_buffer, PSTR("M-SEARCH"))) { + if (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr) { udp_response_mutex = true; udp_remote_ip = PortUdp.remoteIP(); @@ -253,21 +253,21 @@ void PollUdp(void) LowerCase(packet_buffer, packet_buffer); RemoveSpace(packet_buffer); if (EMUL_WEMO == Settings.flag2.emulation) { - if (strstr_P(packet_buffer, URN_BELKIN_DEVICE)) { // type1 echo dot 2g, echo 1g's + if (strstr_P(packet_buffer, URN_BELKIN_DEVICE) != nullptr) { // type1 echo dot 2g, echo 1g's TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1); return; } - else if (strstr_P(packet_buffer, UPNP_ROOTDEVICE) || // type2 Echo 2g (echo & echo plus) - strstr_P(packet_buffer, SSDPSEARCH_ALL) || - strstr_P(packet_buffer, SSDP_ALL)) { + else if ((strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || // type2 Echo 2g (echo & echo plus) + (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || + (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2); return; } } else { - if (strstr_P(packet_buffer, PSTR("urn:schemas-upnp-org:device:basic:1")) || - strstr_P(packet_buffer, UPNP_ROOTDEVICE) || - strstr_P(packet_buffer, SSDPSEARCH_ALL) || - strstr_P(packet_buffer, SSDP_ALL)) { + if ((strstr_P(packet_buffer, PSTR("urn:schemas-upnp-org:device:basic:1")) != nullptr) || + (strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || + (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || + (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { TickerMSearch.attach_ms(response_delay, HueRespondToMSearch); return; } @@ -402,13 +402,13 @@ void HandleUpnpEvent(void) //differentiate get and set state char state = 'G'; - if (strstr_P(event, PSTR("SetBinaryState"))) { + if (strstr_P(event, PSTR("SetBinaryState")) != nullptr) { state = 'S'; uint8_t power = POWER_TOGGLE; - if (strstr_P(event, PSTR("State>1100 *strip = NULL; + NeoPixelBus *strip = nullptr; struct WsColor { uint8_t red, green, blue; diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index 051640f63..54611fd0d 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -81,7 +81,7 @@ void SonoffScSerialInput(char *rcvstat) if (!strncasecmp_P(rcvstat, PSTR("AT+UPDATE="), 10)) { int8_t i = -1; - for (str = strtok_r(rcvstat, ":", &p); str && i < 5; str = strtok_r(NULL, ":", &p)) { + for (str = strtok_r(rcvstat, ":", &p); str && i < 5; str = strtok_r(nullptr, ":", &p)) { value[i++] = atoi(str); } if (value[0] > 0) { diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index 9ecdcbff5..f02ee9e12 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -36,7 +36,7 @@ #include -OneWire *ds = NULL; +OneWire *ds = nullptr; uint8_t ds18x20_address[DS18X20_MAX_SENSORS][8]; uint8_t ds18x20_index[DS18X20_MAX_SENSORS]; diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index cc738f977..881738745 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -61,7 +61,7 @@ uint8_t bmp_addresses[] = { BMP_ADDR1, BMP_ADDR2 }; uint8_t bmp_count = 0; uint8_t bmp_once = 1; -bmp_sensors_t *bmp_sensors = NULL; +bmp_sensors_t *bmp_sensors = nullptr; /*********************************************************************************************\ * BMP085 and BME180 @@ -99,7 +99,7 @@ typedef struct { uint16_t cal_ac6; } bmp180_cal_data_t; -bmp180_cal_data_t *bmp180_cal_data = NULL; +bmp180_cal_data_t *bmp180_cal_data = nullptr; bool Bmp180Calibration(uint8_t bmp_idx) { @@ -244,7 +244,7 @@ typedef struct { int8_t dig_H6; } Bme280CalibrationData_t; -Bme280CalibrationData_t *Bme280CalibrationData = NULL; +Bme280CalibrationData_t *Bme280CalibrationData = nullptr; bool Bmx280Calibrate(uint8_t bmp_idx) { @@ -344,7 +344,7 @@ void Bme280Read(uint8_t bmp_idx) #include -struct bme680_dev *gas_sensor = NULL; +struct bme680_dev *gas_sensor = nullptr; static void BmeDelayMs(uint32_t ms) { diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 25f73c2df..8b8d6ef52 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -109,7 +109,7 @@ bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensor NovaSdsSerial->readBytes(&recbuf[1], 9); AddLogBuffer(LOG_LEVEL_DEBUG_MORE, recbuf, sizeof(recbuf)); - if ( NULL != buffer ) { + if ( nullptr != buffer ) { // return data to buffer memcpy(buffer, recbuf, sizeof(recbuf)); } @@ -126,9 +126,9 @@ bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensor void NovaSdsSetWorkPeriod(void) { // set sensor working period - NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, WORKING_PERIOD, NOVA_SDS_DEVICE_ID, NULL); + NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, WORKING_PERIOD, NOVA_SDS_DEVICE_ID, nullptr); // set sensor report only on query - NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, NULL); + NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); } bool NovaSdsReadData(void) diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index f30ff11f7..f475790ae 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -34,7 +34,7 @@ uint8_t sr04_echo_pin = 0; uint8_t sr04_trig_pin = 0; real64_t distance; -NewPing* sonar = NULL; +NewPing* sonar = nullptr; void Sr04Init(void) { diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index b72ef0a9f..c1fd9c20e 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -165,8 +165,8 @@ bool HxCommand(void) Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); break; case 2: // Calibrate - if (strstr(XdrvMailbox.data, ",")) { - Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), NULL, 10); + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); } hx_scale = 1; HxReset(); @@ -175,26 +175,26 @@ bool HxCommand(void) HxCalibrationStateTextJson(3); break; case 3: // WeightRef to user reference - if (strstr(XdrvMailbox.data, ",")) { - Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), NULL, 10); + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); } show_parms = true; break; case 4: // WeightCal to user calculated value - if (strstr(XdrvMailbox.data, ",")) { - Settings.weight_calibration = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), NULL, 10); + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_calibration = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); hx_scale = Settings.weight_calibration; } show_parms = true; break; case 5: // WeightMax - if (strstr(XdrvMailbox.data, ",")) { - Settings.weight_max = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), NULL, 10) / 1000; + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_max = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) / 1000; } show_parms = true; break; case 6: // WeightItem - if (strstr(XdrvMailbox.data, ",")) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { Settings.weight_item = (unsigned long)(CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10); } show_parms = true; diff --git a/sonoff/xsns_37_rfsensor.ino b/sonoff/xsns_37_rfsensor.ino index 4a94e2d77..aadcf01d9 100644 --- a/sonoff/xsns_37_rfsensor.ino +++ b/sonoff/xsns_37_rfsensor.ino @@ -56,7 +56,7 @@ typedef struct RawSignalStruct // Variabelen geplaatst in stru // Om legacy redenen zit de eerste puls in element 1. Element 0 wordt dus niet gebruikt. } raw_signal_t; -raw_signal_t *rfsns_raw_signal = NULL; +raw_signal_t *rfsns_raw_signal = nullptr; uint8_t rfsns_rf_bit; uint8_t rfsns_rf_port; uint8_t rfsns_any_sensor = 0; @@ -165,8 +165,8 @@ typedef struct { uint8_t volt; } theo_v2_t2_t; -theo_v2_t1_t *rfsns_theo_v2_t1 = NULL; -theo_v2_t2_t *rfsns_theo_v2_t2 = NULL; +theo_v2_t1_t *rfsns_theo_v2_t1 = nullptr; +theo_v2_t2_t *rfsns_theo_v2_t2 = nullptr; void RfSnsInitTheoV2(void) { @@ -423,7 +423,7 @@ typedef struct { uint8_t wdir; } alecto_v2_t; -alecto_v2_t *rfsns_alecto_v2 = NULL; +alecto_v2_t *rfsns_alecto_v2 = nullptr; uint16_t rfsns_alecto_rain_base = 0; void RfSnsInitAlectoV2(void) @@ -617,7 +617,7 @@ void RfSnsInit(void) pinMode(pin[GPIO_RF_SENSOR], INPUT); } else { free(rfsns_raw_signal); - rfsns_raw_signal = NULL; + rfsns_raw_signal = nullptr; } } } From 43e79e83521c165d011e2c0b77b841c672e1d2d2 Mon Sep 17 00:00:00 2001 From: Christoph Hofmann Date: Wed, 27 Mar 2019 03:39:22 +0100 Subject: [PATCH 1183/2222] Fix pca9685 driver command --- sonoff/xdrv_15_pca9685.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index 1a27219c8..e3ffbaa8e 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -189,9 +189,9 @@ bool Xdrv15(uint8_t function) PCA9685_OutputTelemetry(true); } break; - case FUNC_COMMAND: + case FUNC_COMMAND_DRIVER: if (XDRV_15 == XdrvMailbox.index) { - PCA9685_Command(); + result = PCA9685_Command(); } break; default: From feb11dd49e0003d7e5b6233330b8d8e68b5f17ad Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 27 Mar 2019 18:09:27 +0100 Subject: [PATCH 1184/2222] wemohue tuning wemohue tuning --- sonoff/xdrv_interface.ino | 2 +- sonoff/xplg_wemohue.ino | 45 +++++++++++++++++---------------------- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 7de5e1bb5..84f80062b 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -210,7 +210,7 @@ bool XdrvRulesProcess(void) #ifdef USE_DEBUG_DRIVER void ShowFreeMem(const char *where) { - char stemp[20]; + char stemp[30]; snprintf_P(stemp, sizeof(stemp), where); XdrvMailbox.data = stemp; XdrvCall(FUNC_FREE_MEM); diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 1c0a4f782..e3351fbe4 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -31,7 +31,6 @@ #include Ticker TickerMSearch; -char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP packet IPAddress udp_remote_ip; // M-Search remote IP address uint16_t udp_remote_port; // M-Search remote port @@ -120,20 +119,20 @@ 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://%s: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: %s\r\n"; const char HUE_ST1[] PROGMEM = "ST: upnp:rootdevice\r\n" - "USN: uuid:{r3::upnp:rootdevice\r\n" + "USN: uuid:%s::upnp:rootdevice\r\n" "\r\n"; const char HUE_ST2[] PROGMEM = - "ST: uuid:{r3\r\n" - "USN: uuid:{r3\r\n" + "ST: uuid:%s\r\n" + "USN: uuid:%s\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:%s\r\n" "\r\n"; String HueBridgeId(void) @@ -165,26 +164,20 @@ void HueRespondToMSearch(void) TickerMSearch.detach(); if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { - String response1 = FPSTR(HUE_RESPONSE); - response1.replace("{r1", WiFi.localIP().toString()); - response1.replace("{r2", HueBridgeId()); + char response[320]; + snprintf_P(response, sizeof(response), HUE_RESPONSE, WiFi.localIP().toString().c_str(), HueBridgeId().c_str()); + int len = strlen(response); - String response = response1; - response += FPSTR(HUE_ST1); - response.replace("{r3", HueUuid()); - PortUdp.write(response.c_str()); + snprintf_P(response + len, sizeof(response) - len, HUE_ST1, HueUuid().c_str()); + PortUdp.write(response); PortUdp.endPacket(); - response = response1; - response += FPSTR(HUE_ST2); - response.replace("{r3", HueUuid()); - PortUdp.write(response.c_str()); + snprintf_P(response + len, sizeof(response) - len, HUE_ST2, HueUuid().c_str(), HueUuid().c_str()); + PortUdp.write(response); PortUdp.endPacket(); - response = response1; - response += FPSTR(HUE_ST3); - response.replace("{r3", HueUuid()); - PortUdp.write(response.c_str()); + snprintf_P(response + len, sizeof(response) - len, HUE_ST3, HueUuid().c_str()); + PortUdp.write(response); PortUdp.endPacket(); snprintf_P(message, sizeof(message), PSTR(D_3_RESPONSE_PACKETS_SENT)); @@ -231,10 +224,10 @@ void PollUdp(void) { if (udp_connected && !udp_response_mutex && devices_present) { if (PortUdp.parsePacket()) { + char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP/SSDP packet + int len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1); - if (len > 0) { - packet_buffer[len] = 0; - } + packet_buffer[len] = 0; AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); @@ -264,7 +257,7 @@ void PollUdp(void) return; } } else { - if ((strstr_P(packet_buffer, PSTR("urn:schemas-upnp-org:device:basic:1")) != nullptr) || + if ((strstr_P(packet_buffer, PSTR(":device:basic:1")) != nullptr) || (strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { From 8ee8fa262c23ce44270acee83c914d614a89f6d0 Mon Sep 17 00:00:00 2001 From: Tom Paine Date: Thu, 28 Mar 2019 00:22:53 +0000 Subject: [PATCH 1185/2222] Minor spelling --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8a8402339..586520fc6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Sonoff-Tasmota -Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custome device templates and sensors support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. +Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custom device templates and sensor support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. [![GitHub version](https://img.shields.io/github/release/arendst/Sonoff-Tasmota.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) [![GitHub download](https://img.shields.io/github/downloads/arendst/Sonoff-Tasmota/total.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) @@ -15,7 +15,7 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute! See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development/RELEASENOTES.md) for release information. -In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest) the binaries can also be OTA downloaded from http://thehackbox.org/tasmota/release/ +In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest), the binaries can also be OTA downloaded from http://thehackbox.org/tasmota/release/ ### Development [![Dev Version](https://img.shields.io/badge/development%20version-6.5.0.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) @@ -29,12 +29,12 @@ The development codebase is checked hourly for changes and if new commits have b ### Disclaimer :warning: **DANGER OF ELECTROCUTION** :warning: -A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocution if not installed properly. If you don't know how to install it, please call an electrician. Remember: _**SAFETY FIRST**_. It is not worth to risk yourself, your family and your home if you don't know exactly what you are doing. Never try to flash a Sonoff device while it is connected to MAINS AC. +A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocution if not installed properly. If you don't know how to install it, please call an electrician. Remember: _**SAFETY FIRST**_. It is not worth risk to yourself, your family, and your home if you don't know exactly what you are doing. Never try to flash a Sonoff device while it is connected to MAINS AC. We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site. ### Note -Please do not ask to add devices where you can't provide a basic working configuration (other than sonoff). Since there are thousands of them.. +Please do not ask to add devices where you can't provide a basic working configuration (other than sonoff). Since there are thousands of them. ### Quick Install Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki. From 3ad804616662fa275bec38aa3a62a915a45d0983 Mon Sep 17 00:00:00 2001 From: Jon Little Date: Sat, 23 Mar 2019 18:26:03 -0500 Subject: [PATCH 1186/2222] Adding HRE interface for en-GB --- sonoff/i18n.h | 6 + sonoff/language/en-GB.h | 7 +- sonoff/sonoff_template.h | 9 +- sonoff/xsns_91_hre.ino | 299 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 319 insertions(+), 2 deletions(-) create mode 100644 sonoff/xsns_91_hre.ino diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 60b5880e0..766a2cd7e 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -69,6 +69,7 @@ #define D_JSON_FLASHCHIPID "FlashChipId" #define D_JSON_FLASHMODE "FlashMode" #define D_JSON_FLASHSIZE "FlashSize" +#define D_JSON_FLOWRATE "FlowRate" #define D_JSON_FREEMEMORY "Free" #define D_JSON_FREQUENCY "Frequency" #define D_JSON_FROM "from" @@ -143,6 +144,7 @@ #define D_JSON_TIME "Time" #define D_JSON_TODAY "Today" #define D_JSON_TOTAL "Total" +#define D_JSON_TOTAL_USAGE "TotalUsage" #define D_JSON_TOTAL_REACTIVE "TotalReactivePower" #define D_JSON_TOTAL_START_TIME "TotalStartTime" #define D_JSON_TVOC "TVOC" @@ -515,6 +517,8 @@ const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVE const char JSON_SNS_TEMP[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"; const char JSON_SNS_TEMPHUM[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"; +const char JSON_SNS_GNGPM[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TOTAL_USAGE "\":%s,\"" D_JSON_FLOWRATE "\":%s}"; + const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x"; const char S_LOG_HTTP[] PROGMEM = D_LOG_HTTP; @@ -569,6 +573,8 @@ const char HTTP_SNS_ANALOG[] PROGMEM = "{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = const char HTTP_SNS_CO2[] PROGMEM = "{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = const char HTTP_SNS_CO2EAVG[] PROGMEM = "{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_GALLONS[] PROGMEM = "{s}%s " D_TOTAL_USAGE "{m}%s " D_UNIT_GALLONS " {e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_GPM[] PROGMEM = "{s}%s " D_FLOW_RATE "{m}%s " D_UNIT_GALLONS_PER_MIN" {e}"; // {s} = , {m} = , {e} = const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU; const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION; diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index d5e792462..e8ba8f3fb 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback Topic" #define D_FALSE "False" #define D_FILE "File" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Free Memory" #define D_FREQUENCY "Frequency" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "to" #define D_TOGGLE "Toggle" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Transmit" #define D_TRUE "True" #define D_TVOC "TVOC" @@ -576,12 +578,15 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" - +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index cf5a1af78..b50c2184b 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -178,6 +178,8 @@ enum UserSelectablePins { GPIO_ROT1B, // Rotary switch1 B Pin GPIO_ROT2A, // Rotary switch2 A Pin GPIO_ROT2B, // Rotary switch2 B Pin + GPIO_HRE_CLOCK, // Clock/Power line for HR-E Water Meter + GPIO_HRE_DATA, // Data line for HR-E Water Meter GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -241,6 +243,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_CSE7766_TX "|" D_SENSOR_CSE7766_RX "|" D_SENSOR_ARIRFRCV "|" D_SENSOR_TXD "|" D_SENSOR_RXD "|" D_SENSOR_ROTARY "1a|" D_SENSOR_ROTARY "1b|" D_SENSOR_ROTARY "2a|" D_SENSOR_ROTARY "2b|" + D_SENSOR_HRE_CLOCK "|" D_SENSOR_HRE_DATA "|" ; /********************************************************************************************/ @@ -584,7 +587,11 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_ROT1B, // Rotary switch1 B Pin GPIO_ROT2A, // Rotary switch2 A Pin GPIO_ROT2B, // Rotary switch2 B Pin - GPIO_ARIRFRCV // AliLux RF Receive input + GPIO_ARIRFRCV, // AliLux RF Receive input +#ifdef USE_HRE + GPIO_HRE_CLOCK, + GPIO_HRE_DATA +#endif }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { diff --git a/sonoff/xsns_91_hre.ino b/sonoff/xsns_91_hre.ino new file mode 100644 index 000000000..ac15a937a --- /dev/null +++ b/sonoff/xsns_91_hre.ino @@ -0,0 +1,299 @@ +/* + xsns_07_sht1x.ino - SHT1x temperature and sensor support for Sonoff-Tasmota + + Copyright (C) 2019 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 . +*/ + +/*********************************************************************************************\ + * HR-E LCD Water meter register interface + * + * https://www.badgermeter.com/business-lines/utility/high-resolution-lcd-encoders-hr-e-lcd/ + * Source: Jon Little, https://github.com/burundiocibu/particle/blob/master/water_meter/src/HRE_Reader.cpp + * + * This code marches the bits out the data line as ASCII characters with the form + * KG44?Q45484=0444444V;RB000000022;IB018435683 + * where the RB...; is the miligalons used + * + * Note that this sensor takes a _long_ time to read. 62 bits * 4 ms/bit for the + * sync sequence plus 46 bytes * 40 ms/byte = 2088 ms minimum. If we aren't alligned + * to the sync sequence, it could be almost twice that. + * To keep from bogging the kernel down, we read 8 bits at a time on the 50 ms callback. + * It will take seconds to discover if the device is there. + * + * In lieu of an actual schematic to describe the electrical interface, here is a description: + * + * hre_clock_pin: drives the power/clock for the water meter through a 1k resister to + * the base of a pnp transistor + * hre_data_pin: is the data and has a 1 k pulldown + * + * The pnp transitor has the collector connected to the power/clock and is pulled up + * to +5 via a 1 k resistor. + * The emitter is connected to ground + * +\*********************************************************************************************/ + +#ifdef USE_HRE + +#define XSNS_91 91 + +enum hre_states { + hre_idle, // Initial state, + hre_sync, // Start search for sync sequence + hre_syncing, // Searching for sync sequence + hre_read, // Start reading data block + hre_reading, // Reading data + hre_sleep, // Start sleeping + hre_sleeping // pausing before reading again +}; + +hre_states hre_state = hre_idle; + +float hre_usage = 0; // total water usage, in gal +float hre_rate = 0; // flow rate, in gal/min +uint32_t hre_usage_time = 0; // uptime associated with hre_usage and hre_rate + +int hre_read_errors = 0; // total number of read errors since boot +bool hre_good = false; + + +// The settling times here were determined using a single unit hooked to a scope +int hreReadBit() +{ + digitalWrite(pin[GPIO_HRE_CLOCK], HIGH); + delay(1); + int bit = digitalRead(pin[GPIO_HRE_DATA]); + digitalWrite(pin[GPIO_HRE_CLOCK], LOW); + delay(1); + return bit; +} + +// With the times in the HreReadBit routine, a characer will take +// 20 ms plus io time. +char hreReadChar(int &parity_errors) +{ + // start bit + hreReadBit(); + + unsigned ch=0; + int sum=0; + for (int i=0; i<7; i++) + { + int b = hreReadBit(); + ch |= b << i; + sum += b; + } + + // parity + if ( (sum & 0x1) != hreReadBit()) + parity_errors++; + + // stop bit + hreReadBit(); + + return ch; +} + +void hreInit(void) +{ + hre_read_errors = 0; + hre_good = false; + + pinMode(pin[GPIO_HRE_CLOCK], OUTPUT); + pinMode(pin[GPIO_HRE_DATA], INPUT); + + // Note that the level shifter inverts this line and we want to leave it + // high when not being read. + digitalWrite(pin[GPIO_HRE_CLOCK], LOW); + + hre_state = hre_sync; +} + + +void hreEvery50ms(void) +{ + static int sync_counter = 0; // Number of sync bit reads + static int sync_run = 0; // Number of consecutive '1's read + + static uint32_t curr_start = 0; // uptime when entered hre_reading for current read + static int read_counter = 0; // number of bytes in the current read + static int parity_errors = 0; // Number of parity errors in current read + static char buff[46]; // 8 char and a term + static char aux[46]; // 8 char and a term + + static char ch; + static size_t i; + + switch (hre_state) + { + case hre_sync: + if (uptime < 15) + break; + sync_run = 0; + sync_counter = 0; + hre_state = hre_syncing; + snprintf_P(log_data, sizeof(log_data), PSTR("HRE: state:syncing")); + AddLog(LOG_LEVEL_DEBUG); + break; + + case hre_syncing: + // Find the header, a string of 62 '1's + // Note that on startup, this could take a a whole block (46 bytes) + // before we start seeing the header + for (int i=0; i<8; i++) + { + if (hreReadBit()) + sync_run++; + else + sync_run = 0; + if (sync_run == 62) + { + hre_state = hre_read; + break; + } + sync_counter++; + } + // If the meter doesn't get in sync within 1000 bits, give up for now + if (sync_counter > 1000) + { + hre_state = hre_sleep; + snprintf_P(log_data, sizeof(log_data), PSTR("HRE: sync error")); + AddLog(LOG_LEVEL_DEBUG); + } + break; + + // Start reading the data block + case hre_read: + snprintf_P(log_data, sizeof(log_data), PSTR("HRE: sync_run:%d, sync_counter:%d"), sync_run, sync_counter); + AddLog(LOG_LEVEL_DEBUG); + read_counter = 0; + parity_errors = 0; + curr_start = uptime; + memset(buff, 0, sizeof(buff)); + hre_state = hre_reading; + snprintf_P(log_data, sizeof(log_data), PSTR("HRE: state:reading")); + AddLog(LOG_LEVEL_DEBUG); + // So this is intended to fall through to the hre_reading section. + // it seems that if there is much of a delay between getting the sync + // bits and starting the read, the HRE won't output the message we + // are looking for... + + case hre_reading: + //ch = hreReadChar(parity_errors); + //i = read_counter - 24; // The water usage reading starts 24 bytes into the block + //if (i>=0 && i 27) + hre_state = hre_sync; + } +} + +void hreShow(boolean json) +{ + if (!hre_good) + return; + + const char hre_types[] = "HRE"; + + char usage[33]; + char rate[33]; + dtostrfd(hre_usage, 2, usage); + dtostrfd(hre_rate, 3, rate); + + if (json) + { + snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_GNGPM, mqtt_data, hre_types, usage, rate); +#ifdef USE_WEBSERVER + } + else + { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GALLONS, mqtt_data, hre_types, usage); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GPM, mqtt_data, hre_types, rate); +#endif // USE_WEBSERVER + } +} + + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ +bool Xsns91(byte function) +{ + // If we don't have pins assigned give up quickly. + if (pin[GPIO_HRE_CLOCK] >= 99 || pin[GPIO_HRE_DATA] >= 99) + return false; + + switch (function) + { + case FUNC_INIT: + hreInit(); + break; + case FUNC_EVERY_50_MSECOND: + hreEvery50ms(); + break; + case FUNC_EVERY_SECOND: + break; + case FUNC_JSON_APPEND: + hreShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + hreShow(0); + break; +#endif // USE_WEBSERVER + } + return false; +} + +#endif // USE_HRE From 17a5e90e865a4c75d0e5e73bbab196d7415306bf Mon Sep 17 00:00:00 2001 From: Jon Little Date: Sun, 24 Mar 2019 14:58:26 -0500 Subject: [PATCH 1187/2222] Fixing copyright and name --- sonoff/xsns_91_hre.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_91_hre.ino b/sonoff/xsns_91_hre.ino index ac15a937a..d3410556b 100644 --- a/sonoff/xsns_91_hre.ino +++ b/sonoff/xsns_91_hre.ino @@ -1,7 +1,7 @@ /* - xsns_07_sht1x.ino - SHT1x temperature and sensor support for Sonoff-Tasmota + xsns_09_hre.ino - Badger HR-E Water Meter Encoder interface - Copyright (C) 2019 Theo Arends + Copyright (C) 2019 Jon Little 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 From d375d95529500eddaf28a306de8476d4cfc1b9cd Mon Sep 17 00:00:00 2001 From: Jon Little Date: Mon, 25 Mar 2019 14:10:17 -0500 Subject: [PATCH 1188/2222] Updating to work with new web/mqtt api --- sonoff/i18n.h | 2 +- sonoff/language/en-GB.h | 3 +++ sonoff/xsns_91_hre.ino | 40 +++++++++++++++------------------------- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 766a2cd7e..58e1ba63d 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -517,7 +517,7 @@ const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVE const char JSON_SNS_TEMP[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"; const char JSON_SNS_TEMPHUM[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"; -const char JSON_SNS_GNGPM[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TOTAL_USAGE "\":%s,\"" D_JSON_FLOWRATE "\":%s}"; +const char JSON_SNS_GNGPM[] PROGMEM = ",\"%s\":{\"" D_JSON_TOTAL_USAGE "\":%s,\"" D_JSON_FLOWRATE "\":%s}"; const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x"; diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index e8ba8f3fb..c1ee1ed5c 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -494,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" #define D_SENSOR_USER "User" diff --git a/sonoff/xsns_91_hre.ino b/sonoff/xsns_91_hre.ino index d3410556b..c73d94338 100644 --- a/sonoff/xsns_91_hre.ino +++ b/sonoff/xsns_91_hre.ino @@ -131,7 +131,6 @@ void hreEvery50ms(void) static int read_counter = 0; // number of bytes in the current read static int parity_errors = 0; // Number of parity errors in current read static char buff[46]; // 8 char and a term - static char aux[46]; // 8 char and a term static char ch; static size_t i; @@ -144,8 +143,7 @@ void hreEvery50ms(void) sync_run = 0; sync_counter = 0; hre_state = hre_syncing; - snprintf_P(log_data, sizeof(log_data), PSTR("HRE: state:syncing")); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_syncing")); break; case hre_syncing: @@ -169,40 +167,34 @@ void hreEvery50ms(void) if (sync_counter > 1000) { hre_state = hre_sleep; - snprintf_P(log_data, sizeof(log_data), PSTR("HRE: sync error")); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE D_ERROR)); } break; // Start reading the data block case hre_read: - snprintf_P(log_data, sizeof(log_data), PSTR("HRE: sync_run:%d, sync_counter:%d"), sync_run, sync_counter); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE " sync_run:%d, sync_counter:%d"), sync_run, sync_counter); read_counter = 0; parity_errors = 0; curr_start = uptime; memset(buff, 0, sizeof(buff)); hre_state = hre_reading; - snprintf_P(log_data, sizeof(log_data), PSTR("HRE: state:reading")); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_reading")); // So this is intended to fall through to the hre_reading section. // it seems that if there is much of a delay between getting the sync // bits and starting the read, the HRE won't output the message we // are looking for... case hre_reading: - //ch = hreReadChar(parity_errors); - //i = read_counter - 24; // The water usage reading starts 24 bytes into the block - //if (i>=0 && i 27) @@ -243,8 +233,8 @@ void hreShow(boolean json) { if (!hre_good) return; - - const char hre_types[] = "HRE"; + + const char *id = "HRE"; char usage[33]; char rate[33]; @@ -253,13 +243,13 @@ void hreShow(boolean json) if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_GNGPM, mqtt_data, hre_types, usage, rate); + ResponseAppend_P(JSON_SNS_GNGPM, id, usage, rate); #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GALLONS, mqtt_data, hre_types, usage); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GPM, mqtt_data, hre_types, rate); + WSContentSend_PD(HTTP_SNS_GALLONS, id, usage); + WSContentSend_PD(HTTP_SNS_GPM, id, rate); #endif // USE_WEBSERVER } } From fb81b65bbcf94f5302004a515ace2b1d4d8d3c1b Mon Sep 17 00:00:00 2001 From: Jon Little Date: Mon, 25 Mar 2019 18:33:29 -0500 Subject: [PATCH 1189/2222] Cleaned up debugging output --- sonoff/xsns_91_hre.ino | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/sonoff/xsns_91_hre.ino b/sonoff/xsns_91_hre.ino index c73d94338..177c40e0c 100644 --- a/sonoff/xsns_91_hre.ino +++ b/sonoff/xsns_91_hre.ino @@ -138,7 +138,7 @@ void hreEvery50ms(void) switch (hre_state) { case hre_sync: - if (uptime < 15) + if (uptime < 10) break; sync_run = 0; sync_counter = 0; @@ -148,9 +148,8 @@ void hreEvery50ms(void) case hre_syncing: // Find the header, a string of 62 '1's - // Note that on startup, this could take a a whole block (46 bytes) - // before we start seeing the header - for (int i=0; i<8; i++) + // Since each bit taks 2 ms, we just read 20 bits at a time + for (int i=0; i<20; i++) { if (hreReadBit()) sync_run++; @@ -173,7 +172,7 @@ void hreEvery50ms(void) // Start reading the data block case hre_read: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE " sync_run:%d, sync_counter:%d"), sync_run, sync_counter); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "sync_run:%d, sync_counter:%d"), sync_run, sync_counter); read_counter = 0; parity_errors = 0; curr_start = uptime; @@ -186,15 +185,14 @@ void hreEvery50ms(void) // are looking for... case hre_reading: - //KG44?Q45484=0444444V;RB000000022;IB018435683 - // RB003119173;IB018435683 - buff[read_counter] = hreReadChar(parity_errors); + // Read two characters at a time... + buff[read_counter++] = hreReadChar(parity_errors); + buff[read_counter++] = hreReadChar(parity_errors); - read_counter++; if (read_counter == 46) { - //buff[33]='\0'; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE " pe:%d, buff:%s"), parity_errors, buff); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "pe:%d, re:%d, buff:%s"), + parity_errors, hre_read_errors, buff); if (parity_errors == 0) { float curr_usage; @@ -207,7 +205,7 @@ void hreEvery50ms(void) hre_usage = curr_usage; hre_usage_time = curr_start; hre_good = true; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE " usage:%d, rate:%d"), int(100*hre_usage), int(100*hre_rate)); + hre_state = hre_sleep; } else @@ -224,7 +222,9 @@ void hreEvery50ms(void) AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_sleeping")); case hre_sleeping: - if (uptime - hre_usage_time > 27) + // If there isn't some delay between readings, rate calculations + // aren't as accurate. 27 seconds will give about a 30 second refresh rate + if (uptime - hre_usage_time >= 27) hre_state = hre_sync; } } @@ -236,8 +236,8 @@ void hreShow(boolean json) const char *id = "HRE"; - char usage[33]; - char rate[33]; + char usage[16]; + char rate[16]; dtostrfd(hre_usage, 2, usage); dtostrfd(hre_rate, 3, rate); From deaf1f3d5b3064b2d0c2bff27295b8f73a0f9299 Mon Sep 17 00:00:00 2001 From: Jon Little Date: Wed, 27 Mar 2019 21:30:03 -0500 Subject: [PATCH 1190/2222] Adding additional languages --- sonoff/language/bg-BG.h | 10 ++++++++++ sonoff/language/cs-CZ.h | 9 +++++++++ sonoff/language/de-DE.h | 9 +++++++++ sonoff/language/el-GR.h | 9 +++++++++ sonoff/language/es-AR.h | 9 +++++++++ sonoff/language/fr-FR.h | 9 +++++++++ sonoff/language/he-HE.h | 9 +++++++++ sonoff/language/hu-HU.h | 9 +++++++++ sonoff/language/it-IT.h | 9 +++++++++ sonoff/language/ko-KO.h | 9 +++++++++ sonoff/language/nl-NL.h | 9 +++++++++ sonoff/language/pl-PL.h | 9 +++++++++ sonoff/language/pt-BR.h | 9 +++++++++ sonoff/language/pt-PT.h | 9 +++++++++ sonoff/language/ru-RU.h | 9 +++++++++ sonoff/language/sk-SK.h | 9 +++++++++ sonoff/language/sv-SE.h | 9 +++++++++ sonoff/language/tr-TR.h | 9 +++++++++ sonoff/language/uk-UK.h | 9 +++++++++ sonoff/language/zh-CN.h | 9 +++++++++ sonoff/language/zh-TW.h | 9 +++++++++ 21 files changed, 190 insertions(+) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 2214634f9..7b1a41675 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Помощен топик" #define D_FALSE "Невярно" #define D_FILE "Файл" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Свободна памет" #define D_FREQUENCY "Честота" #define D_GAS "Газ" @@ -156,6 +157,7 @@ #define D_TO "към" #define D_TOGGLE "Превключване" #define D_TOPIC "Топик" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Предаване" #define D_TRUE "Вярно" #define D_TVOC "TVOC" @@ -492,6 +494,10 @@ #define D_TX20_SOUTH "Ю" #define D_TX20_WEST "З" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Няма" #define D_SENSOR_USER "Потребит." @@ -576,12 +582,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOMETER_PER_HOUR "km/h" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 41d4fc9de..ccbb84ed0 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Záložní topic" #define D_FALSE "Nepravda" #define D_FILE "Soubor" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Volná paměť" #define D_FREQUENCY "Kmitočet" #define D_GAS "Plyn" @@ -156,6 +157,7 @@ #define D_TO "do" #define D_TOGGLE "Přepni" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Odešli" #define D_TRUE "Pravda" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "J" #define D_TX20_WEST "Z" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Není" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "hod" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 0808c91c4..f670a3416 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback-Topic" #define D_FALSE "falsch" #define D_FILE "Datei" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Freier Arbeitsspeicher" #define D_FREQUENCY "Frequenz" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "zu" #define D_TOGGLE "An/Aus" #define D_TOPIC "topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Übertragen" #define D_TRUE "wahr" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 0e483759d..f3680d639 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback Topic" #define D_FALSE "Ψευδές" #define D_FILE "Αρχείο" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Ελεύθερη μνήμη" #define D_FREQUENCY "Συχνότητα" #define D_GAS "Αέριο" @@ -156,6 +157,7 @@ #define D_TO "έως" #define D_TOGGLE "Εναλλαγή" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Μετάδοση" #define D_TRUE "Αληθές" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "Ν" #define D_TX20_WEST "Δ" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Κανένα" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index baf9838bf..17511fd71 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "FallbackTopic" #define D_FALSE "Falso" #define D_FILE "Archivo" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Memoria Libre" #define D_FREQUENCY "Frecuencia" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "a" #define D_TOGGLE "Conmutar" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Transmitir" #define D_TRUE "Verdadero" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "O" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Ninguno" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 0b7d29eb7..1436cc33b 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Topic de secours" #define D_FALSE "Faux" #define D_FILE "Fichier" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Mémoire libre" #define D_FREQUENCY "Fréquence" #define D_GAS "Gaz" @@ -156,6 +157,7 @@ #define D_TO "à" #define D_TOGGLE "Inverser" #define D_TOPIC "Topic" // Keep MQTT keyword +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Transmettre" #define D_TRUE "Vrai" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "O" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Aucun" #define D_SENSOR_USER "Utilisateur" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index b26529cf2..a7041304a 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "נושא לחזרה" #define D_FALSE "שגוי" #define D_FILE "קובץ" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "זכרון פנוי" #define D_FREQUENCY "תדר" #define D_GAS "גז" @@ -156,6 +157,7 @@ #define D_TO "ל" #define D_TOGGLE "מתג" #define D_TOPIC "נושא" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "עבר" #define D_TRUE "נכון" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" #define D_SENSOR_USER "משתמש" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index e8b818029..e9b51849d 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "fallback topik" #define D_FALSE "Hamis" #define D_FILE "Fájl" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Szabad memória" #define D_FREQUENCY "Frekvencia" #define D_GAS "Gáz" @@ -156,6 +157,7 @@ #define D_TO "-nak" #define D_TOGGLE "Megfordítás" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Továbbít" #define D_TRUE "Igaz" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "D" #define D_TX20_WEST "NY" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nincs" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index db8e58475..200d5cd3f 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Topic Riserva" #define D_FALSE "Falso" #define D_FILE "File" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Memoria Libera" #define D_FREQUENCY "Frequenza" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "a" #define D_TOGGLE "Toggle" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Trasmesso" #define D_TRUE "Vero" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nessuno" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index ddfaba8d3..3bcb69ff4 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback Topic" #define D_FALSE "거짓" #define D_FILE "파일" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "남은 메모리" #define D_FREQUENCY "빈도" #define D_GAS "가스" @@ -156,6 +157,7 @@ #define D_TO "to" #define D_TOGGLE "전환" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "전송" #define D_TRUE "참" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "없음" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "시" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 9e428165d..0c157ae13 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback Topic" #define D_FALSE "Onwaar" #define D_FILE "Bestand" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Vrij geheugen" #define D_FREQUENCY "Frequentie" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "naar" #define D_TOGGLE "Toggle" // Wissel, Tuimel #define D_TOPIC "Topic" // Onderwerp +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Verzend" #define D_TRUE "Waar" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Geen" #define D_SENSOR_USER "Gebruiker" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 0f13d248a..5e74d9cbb 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Zastępczy temat" #define D_FALSE "Fałsz" #define D_FILE "Plik" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Wolna pamięć" #define D_FREQUENCY "Frequency" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "do" #define D_TOGGLE "Przełącz" #define D_TOPIC "Temat" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Wyślij" #define D_TRUE "Prawda" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Brak" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Godz" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 63efc3f1e..3ac016f27 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Tópico para retornar" #define D_FALSE "Falso" #define D_FILE "Arquivo" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Memória livre" #define D_FREQUENCY "Frequência" #define D_GAS "Gás" @@ -156,6 +157,7 @@ #define D_TO "Para" #define D_TOGGLE "Inverter" #define D_TOPIC "Tópico" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Transmitir" #define D_TRUE "Verdadeiro" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nenhum" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "H" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 171f33d9b..0a573f166 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Tópico para retornar" #define D_FALSE "Falso" #define D_FILE "Ficheiro" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Memoria Livre" #define D_FREQUENCY "Frequency" #define D_GAS "Gás" @@ -156,6 +157,7 @@ #define D_TO "para" #define D_TOGGLE "Pressionar" #define D_TOPIC "Tópico" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Transmitir" #define D_TRUE "Verdadeiro" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nenhum" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index e4112953c..ee1d30540 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Топик обратной связи" #define D_FALSE "Ложно" #define D_FILE "Файл" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Свободная память" #define D_FREQUENCY "Frequency" #define D_GAS "Газ" @@ -156,6 +157,7 @@ #define D_TO "до" #define D_TOGGLE "Переключить" #define D_TOPIC "Топик" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Передать" #define D_TRUE "Истина" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "-нет-" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "А" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Ч" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index cf99703c8..05787f7f2 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -75,6 +75,7 @@ #define D_COUNTER "Počítadlo" #define D_CURRENT "Prúd" // As in Voltage and Current #define D_DATA "Dáta" +#define D_FLOW_RATE "Flow rate" #define D_DARKLIGHT "Tmavý" #define D_DEBUG "Debug" #define D_DISABLED "Zablokované" @@ -156,6 +157,7 @@ #define D_TO "do" #define D_TOGGLE "Prepni" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Odošli" #define D_TRUE "Pravda" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "J" #define D_TX20_WEST "Z" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Žiaden" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "hod" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 6a92c1bc1..59f940e7a 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Reservämne" #define D_FALSE "Falskt" #define D_FILE "Fil" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Ledigt minne" #define D_FREQUENCY "Frekvens" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "till" #define D_TOGGLE "Växla" #define D_TOPIC "Ämne" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Sänd" #define D_TRUE "Sant" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "V" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Ingen" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Tim" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "ink" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index b887c89c2..99c7be5b6 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Geri İletim Topiği" #define D_FALSE "False" #define D_FILE "Dosya" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Boş Hafıza" #define D_FREQUENCY "Frekans" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "den" #define D_TOGGLE "Geçiş Tuşu" #define D_TOPIC "Başlık" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "İletim" #define D_TRUE "True" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" #define D_SENSOR_USER "User" @@ -576,11 +581,15 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 0efdd1c94..3d9efa25a 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Топік зворотнього зв'язку" #define D_FALSE "Помилково" #define D_FILE "Файл" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Вільна память" #define D_FREQUENCY "Частота" #define D_GAS "Газ" @@ -156,6 +157,7 @@ #define D_TO "до" #define D_TOGGLE "Перекл." #define D_TOPIC "Топік" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Передати" #define D_TRUE "Істина" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "-відсутньо-" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "А" #define D_UNIT_CENTIMETER "cм" #define D_UNIT_HERTZ "Гц" #define D_UNIT_HOUR "Г" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 88767053b..bda9e0053 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "回退主题" #define D_FALSE "False" #define D_FILE "文件:" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "空闲内存" #define D_FREQUENCY "频率" #define D_GAS "气体" @@ -156,6 +157,7 @@ #define D_TO "to" #define D_TOGGLE "切换" #define D_TOPIC "主题" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "发送" #define D_TRUE "True" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "南" #define D_TX20_WEST "西" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "无" #define D_SENSOR_USER "User" @@ -576,11 +581,15 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "安" #define D_UNIT_CENTIMETER "厘米" #define D_UNIT_HOUR "时" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "千克" #define D_UNIT_KILOMETER_PER_HOUR "公里/时" // or "km/h" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 11f85eef2..8273de199 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback Topic" #define D_FALSE "False" #define D_FILE "文件:" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "可用記憶體" #define D_FREQUENCY "Frequency" #define D_GAS "氣體" @@ -156,6 +157,7 @@ #define D_TO "to" #define D_TOGGLE "切換" #define D_TOPIC "主題" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "發送" #define D_TRUE "True" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "安" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "時" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" From a596fc7948caaa97c2cfd38ed2bf5065fb127e8c Mon Sep 17 00:00:00 2001 From: Jon Little Date: Wed, 27 Mar 2019 21:36:32 -0500 Subject: [PATCH 1191/2222] renamed driver from 91 to 43 --- sonoff/language/bg-BG.h | 2 +- sonoff/language/cs-CZ.h | 2 +- sonoff/language/de-DE.h | 2 +- sonoff/language/el-GR.h | 2 +- sonoff/language/en-GB.h | 2 +- sonoff/language/es-AR.h | 2 +- sonoff/language/fr-FR.h | 2 +- sonoff/language/he-HE.h | 2 +- sonoff/language/hu-HU.h | 2 +- sonoff/language/it-IT.h | 2 +- sonoff/language/ko-KO.h | 2 +- sonoff/language/nl-NL.h | 2 +- sonoff/language/pl-PL.h | 2 +- sonoff/language/pt-BR.h | 2 +- sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 2 +- sonoff/language/sk-SK.h | 2 +- sonoff/language/sv-SE.h | 2 +- sonoff/language/tr-TR.h | 2 +- sonoff/language/uk-UK.h | 2 +- sonoff/language/zh-CN.h | 2 +- sonoff/language/zh-TW.h | 2 +- sonoff/{xsns_91_hre.ino => xsns_43_hre.ino} | 6 +++--- 23 files changed, 25 insertions(+), 25 deletions(-) rename sonoff/{xsns_91_hre.ino => xsns_43_hre.ino} (98%) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 7b1a41675..bd71bf38c 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "Ю" #define D_TX20_WEST "З" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index ccbb84ed0..a0b48f627 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "J" #define D_TX20_WEST "Z" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index f670a3416..dbcc39b9a 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index f3680d639..20e4ed47a 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "Ν" #define D_TX20_WEST "Δ" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index c1ee1ed5c..911e88d29 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 17511fd71..9aca4f417 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "O" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 1436cc33b..36e8566f3 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "O" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index a7041304a..c6061d05a 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index e9b51849d..76628df43 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "D" #define D_TX20_WEST "NY" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 200d5cd3f..b77fc7282 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index 3bcb69ff4..c1c5d2b43 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 0c157ae13..dc78b1445 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 5e74d9cbb..20507fc87 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 3ac016f27..433390fb6 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 0a573f166..4240008b4 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index ee1d30540..2c39bb456 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 05787f7f2..a8134677b 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "J" #define D_TX20_WEST "Z" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 59f940e7a..786d5c766 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "V" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 99c7be5b6..59cd95023 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 3d9efa25a..4cceb18a6 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index bda9e0053..9612b370a 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "南" #define D_TX20_WEST "西" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 8273de199..0a1f8ed03 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/xsns_91_hre.ino b/sonoff/xsns_43_hre.ino similarity index 98% rename from sonoff/xsns_91_hre.ino rename to sonoff/xsns_43_hre.ino index 177c40e0c..5a25b6784 100644 --- a/sonoff/xsns_91_hre.ino +++ b/sonoff/xsns_43_hre.ino @@ -1,5 +1,5 @@ /* - xsns_09_hre.ino - Badger HR-E Water Meter Encoder interface + xsns_43_hre.ino - Badger HR-E Water Meter Encoder interface Copyright (C) 2019 Jon Little @@ -47,7 +47,7 @@ #ifdef USE_HRE -#define XSNS_91 91 +#define XSNS_43 43 enum hre_states { hre_idle, // Initial state, @@ -258,7 +258,7 @@ void hreShow(boolean json) /*********************************************************************************************\ * Interface \*********************************************************************************************/ -bool Xsns91(byte function) +bool Xsns43(byte function) { // If we don't have pins assigned give up quickly. if (pin[GPIO_HRE_CLOCK] >= 99 || pin[GPIO_HRE_DATA] >= 99) From 64ab5d95e5b22d65c586742f449f80fa81cad001 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 28 Mar 2019 11:14:09 +0100 Subject: [PATCH 1192/2222] Add optional support for Badger HR-E Water Meter Add optional support for Badger HR-E Water Meter (#5539) --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 2 ++ sonoff/sonoff_post.h | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 3d9c77a9d..be64368e0 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.5.0.2 20190325 * Change UDP initial message handling from string to char using static memory and add debug info (#5505) + * Add optional support for Badger HR-E Water Meter (#5539) * * 6.5.0.1 20190319 * Change Web GUI sensor data collection diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index b7e0846e4..29eb632a6 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -415,6 +415,8 @@ #define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) +//#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) + /*********************************************************************************************\ * Debug features are only supported in development branch \*********************************************************************************************/ diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 095c7e2ac..10a466981 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -140,6 +140,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code) +#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) #endif // FIRMWARE_SENSORS /*********************************************************************************************\ @@ -197,6 +198,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_CLASSIC @@ -326,6 +328,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_BASIC @@ -391,6 +394,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_MINIMAL From e631d49d0fdd244f3fe21cebce08bca8ea0ede47 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 28 Mar 2019 11:25:38 +0100 Subject: [PATCH 1193/2222] Housekeeping Housekeeping --- RELEASENOTES.md | 1 + sonoff/support_features.ino | 8 +++++--- tools/decode-status.py | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 4485d3083..c3e3afd4b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -194,6 +194,7 @@ Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/re | USE_RC_SWITCH | - | - | - | x | x | x | x | | USE_RF_SENSOR | - | - | - | - | - | x | - | AlectoV2 only | USE_SM16716 | - | x | x | x | x | x | x | +| USE_HRE | - | - | - | - | - | x | - | | USE_DISPLAY | - | - | - | - | - | - | x | | USE_DISPLAY_LCD | - | - | - | - | - | - | x | | USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x | diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index f5229e81f..bde88738e 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -382,12 +382,14 @@ void GetFeatures(void) feature_sns2 |= 0x00100000; // xsns_40_pn532.ino #endif #ifdef USE_MAX44009 - feature_sns2 |= 0x00200000; + feature_sns2 |= 0x00200000; // xsns_41_max44009.ino #endif #ifdef USE_SCD30 - feature_sns2 |= 0x00400000; + feature_sns2 |= 0x00400000; // xsns_42_scd30.ino +#endif +#ifdef USE_HRE + feature_sns2 |= 0x00800000; // xsns_43_hre.ino #endif -// feature_sns2 |= 0x00800000; // feature_sns2 |= 0x01000000; // feature_sns2 |= 0x02000000; // feature_sns2 |= 0x04000000; diff --git a/tools/decode-status.py b/tools/decode-status.py index dd90d1669..ca8a35ed4 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -89,7 +89,7 @@ a_setoption = [[ "Tuya dimmer device id", "(not used) mDNS delayed start (Sec)", "Boot loop retry offset (0 = disable)", - "", + "RGBWW remap", "","","","","","", "","","","","","", ],[ @@ -105,7 +105,7 @@ a_setoption = [[ "Change state topic from tele/STATE to stat/RESULT", "Enable normal sleep instead of dynamic sleep", "Force local operation when button/switch topic is set", - "Force no pull-up", + "Do not use retain flag on HOLD messages", "","","", "","","","", "","","","", @@ -146,7 +146,7 @@ a_features = [[ "USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711", "USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","USE_RF_SENSOR", "USE_THEO_V2","USE_ALECTO_V2","USE_AZ7798","USE_MAX31855", - "USE_PN532_I2C","USE_MAX44009","","", + "USE_PN532_I2C","USE_MAX44009","USE_SCD30","USE_HRE", "","","","", "","","",""]] From e8e5d1c03c2f51432199064e2325da41233d8ab1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 28 Mar 2019 12:06:48 +0100 Subject: [PATCH 1194/2222] 6.5.0.3 Add command Sensor20 6.5.0.3 20190328 * Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452) --- sonoff/_changelog.ino | 5 ++++- sonoff/settings.h | 3 ++- sonoff/settings.ino | 5 +++++ sonoff/sonoff_version.h | 2 +- sonoff/xsns_20_novasds.ino | 28 +++++++++++++++++++++++----- sonoff/xsns_43_hre.ino | 33 ++++++++++++++++----------------- 6 files changed, 51 insertions(+), 25 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index be64368e0..c15f33aff 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.5.0.2 20190325 +/* 6.5.0.3 20190328 + * Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452) + * + * 6.5.0.2 20190325 * Change UDP initial message handling from string to char using static memory and add debug info (#5505) * Add optional support for Badger HR-E Water Meter (#5539) * diff --git a/sonoff/settings.h b/sonoff/settings.h index 5a7827365..f7eed3f11 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -330,8 +330,9 @@ struct SYSCFG { uint8_t rgbwwTable[5]; // 71A uint8_t user_template_base; // 71F mytmplt user_template; // 720 29 bytes + uint8_t novasds_period; // 73D - uint8_t free_73D[87]; // 73D + uint8_t free_73D[86]; // 73E uint32_t drivers[3]; // 794 uint32_t monitors; // 7A0 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index ca8cd1b3a..1e570a96b 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -815,6 +815,8 @@ void SettingsDefaultSet2(void) Settings.rgbwwTable[j] = 255; } + Settings.novasds_period = WORKING_PERIOD; + memset(&Settings.drivers, 0xFF, 32); // Enable all possible monitors, displays, drivers and sensors } @@ -1055,6 +1057,9 @@ void SettingsDelta(void) if (Settings.version < 0x06040113) { Settings.param[P_RGB_REMAP] = RGB_REMAP_RGBW; } + if (Settings.version < 0x06050003) { + Settings.novasds_period = WORKING_PERIOD; + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 66b50129c..ac84738ec 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06050002 +#define VERSION 0x06050003 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 8b8d6ef52..e9d955af3 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -47,13 +47,11 @@ #define NOVA_SDS_DEVICE_ID 0xFFFF // NodaSDS all sensor response #endif - TasmotaSerial *NovaSdsSerial; uint8_t novasds_type = 1; uint8_t novasds_valid = 0; - struct sds011data { uint16_t pm100; uint16_t pm25; @@ -126,9 +124,9 @@ bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensor void NovaSdsSetWorkPeriod(void) { // set sensor working period - NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, WORKING_PERIOD, NOVA_SDS_DEVICE_ID, nullptr); + NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, Settings.novasds_period, NOVA_SDS_DEVICE_ID, nullptr); // set sensor report only on query - NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); + NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); } bool NovaSdsReadData(void) @@ -162,7 +160,22 @@ void NovaSdsSecond(void) // Every second } } -/*********************************************************************************************/ +/*********************************************************************************************\ + * Command Sensor20 + * + * 1 .. 255 - Set working period in minutes +\*********************************************************************************************/ + +bool NovaSdsCommandSensor(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 256)) { + Settings.novasds_period = XdrvMailbox.payload; + NovaSdsSetWorkPeriod(); + } + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_20, Settings.novasds_period); + + return true; +} void NovaSdsInit(void) { @@ -226,6 +239,11 @@ bool Xsns20(uint8_t function) case FUNC_EVERY_SECOND: NovaSdsSecond(); break; + case FUNC_COMMAND_SENSOR: + if (XSNS_20 == XdrvMailbox.index) { + result = NovaSdsCommandSensor(); + } + break; case FUNC_JSON_APPEND: NovaSdsShow(1); break; diff --git a/sonoff/xsns_43_hre.ino b/sonoff/xsns_43_hre.ino index 5a25b6784..08181559f 100644 --- a/sonoff/xsns_43_hre.ino +++ b/sonoff/xsns_43_hre.ino @@ -17,6 +17,7 @@ along with this program. If not, see . */ +#ifdef USE_HRE /*********************************************************************************************\ * HR-E LCD Water meter register interface * @@ -27,26 +28,24 @@ * KG44?Q45484=0444444V;RB000000022;IB018435683 * where the RB...; is the miligalons used * - * Note that this sensor takes a _long_ time to read. 62 bits * 4 ms/bit for the + * Note that this sensor takes a _long_ time to read. 62 bits * 4 ms/bit for the * sync sequence plus 46 bytes * 40 ms/byte = 2088 ms minimum. If we aren't alligned * to the sync sequence, it could be almost twice that. * To keep from bogging the kernel down, we read 8 bits at a time on the 50 ms callback. * It will take seconds to discover if the device is there. * * In lieu of an actual schematic to describe the electrical interface, here is a description: - * + * * hre_clock_pin: drives the power/clock for the water meter through a 1k resister to * the base of a pnp transistor * hre_data_pin: is the data and has a 1 k pulldown - * + * * The pnp transitor has the collector connected to the power/clock and is pulled up * to +5 via a 1 k resistor. * The emitter is connected to ground - * + * \*********************************************************************************************/ -#ifdef USE_HRE - #define XSNS_43 43 enum hre_states { @@ -110,14 +109,14 @@ void hreInit(void) { hre_read_errors = 0; hre_good = false; - + pinMode(pin[GPIO_HRE_CLOCK], OUTPUT); pinMode(pin[GPIO_HRE_DATA], INPUT); // Note that the level shifter inverts this line and we want to leave it // high when not being read. digitalWrite(pin[GPIO_HRE_CLOCK], LOW); - + hre_state = hre_sync; } @@ -134,7 +133,7 @@ void hreEvery50ms(void) static char ch; static size_t i; - + switch (hre_state) { case hre_sync: @@ -145,7 +144,7 @@ void hreEvery50ms(void) hre_state = hre_syncing; AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_syncing")); break; - + case hre_syncing: // Find the header, a string of 62 '1's // Since each bit taks 2 ms, we just read 20 bits at a time @@ -183,12 +182,12 @@ void hreEvery50ms(void) // it seems that if there is much of a delay between getting the sync // bits and starting the read, the HRE won't output the message we // are looking for... - + case hre_reading: // Read two characters at a time... buff[read_counter++] = hreReadChar(parity_errors); buff[read_counter++] = hreReadChar(parity_errors); - + if (read_counter == 46) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "pe:%d, re:%d, buff:%s"), @@ -205,7 +204,7 @@ void hreEvery50ms(void) hre_usage = curr_usage; hre_usage_time = curr_start; hre_good = true; - + hre_state = hre_sleep; } else @@ -215,7 +214,7 @@ void hreEvery50ms(void) } } break; - + case hre_sleep: hre_usage_time = curr_start; hre_state = hre_sleeping; @@ -233,14 +232,14 @@ void hreShow(boolean json) { if (!hre_good) return; - + const char *id = "HRE"; char usage[16]; char rate[16]; dtostrfd(hre_usage, 2, usage); dtostrfd(hre_rate, 3, rate); - + if (json) { ResponseAppend_P(JSON_SNS_GNGPM, id, usage, rate); @@ -263,7 +262,7 @@ bool Xsns43(byte function) // If we don't have pins assigned give up quickly. if (pin[GPIO_HRE_CLOCK] >= 99 || pin[GPIO_HRE_DATA] >= 99) return false; - + switch (function) { case FUNC_INIT: From e19ba70c7ff42565a02165c7f1fef1f9aa3d8f88 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 28 Mar 2019 14:39:12 +0100 Subject: [PATCH 1195/2222] Fix exception due to UDP packet memory flooding (#5540) Fix exception due to UDP packet memory flooding (#5540) --- sonoff/xplg_wemohue.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index e3351fbe4..51e51f84b 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -222,7 +222,7 @@ bool UdpConnect(void) void PollUdp(void) { - if (udp_connected && !udp_response_mutex && devices_present) { + if (udp_connected) { if (PortUdp.parsePacket()) { char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP/SSDP packet @@ -232,7 +232,7 @@ void PollUdp(void) AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); - if (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr) { + if ((strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr) && !udp_response_mutex && devices_present) { udp_response_mutex = true; udp_remote_ip = PortUdp.remoteIP(); From b8dfc6b1b5db4a021a9480101e0961ed71e283e5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 28 Mar 2019 15:29:08 +0100 Subject: [PATCH 1196/2222] Change order of evaluation Change order of evaluation --- sonoff/xplg_wemohue.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 51e51f84b..0dfcc2f5d 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -197,6 +197,7 @@ void HueRespondToMSearch(void) bool UdpDisconnect(void) { if (udp_connected) { + PortUdp.flush(); WiFiUDP::stopAll(); AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_MULTICAST_DISABLED)); udp_connected = false; @@ -232,7 +233,7 @@ void PollUdp(void) AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); - if ((strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr) && !udp_response_mutex && devices_present) { + if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { udp_response_mutex = true; udp_remote_ip = PortUdp.remoteIP(); From 1400a15076a6fd54274fe6d8db51b7fc66798708 Mon Sep 17 00:00:00 2001 From: Staars Date: Fri, 29 Mar 2019 09:42:50 +0100 Subject: [PATCH 1197/2222] always check for vars_events and mems_events --- sonoff/xdrv_10_rules.ino | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 2a93ee86f..d8c0cd5c0 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -486,23 +486,25 @@ void RulesEvery50ms(void) event_data[0] ='\0'; } } - else if (vars_event) { - for (uint8_t i = 0; i < MAX_RULE_VARS-1; i++) { - if (bitRead(vars_event, i)) { - bitClear(vars_event, i); - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Var%d\":{\"State\":%s}}"), i+1, vars[i]); - RulesProcessEvent(json_event); - break; + else if (vars_event || mems_event){ + if (vars_event) { + for (uint8_t i = 0; i < MAX_RULE_VARS-1; i++) { + if (bitRead(vars_event, i)) { + bitClear(vars_event, i); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Var%d\":{\"State\":%s}}"), i+1, vars[i]); + RulesProcessEvent(json_event); + break; + } } } - } - else if (mems_event) { - for (uint8_t i = 0; i < MAX_RULE_MEMS-1; i++) { - if (bitRead(mems_event, i)) { - bitClear(mems_event, i); - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Mem%d\":{\"State\":%s}}"), i+1, Settings.mems[i]); - RulesProcessEvent(json_event); - break; + if (mems_event) { + for (uint8_t i = 0; i < MAX_RULE_MEMS-1; i++) { + if (bitRead(mems_event, i)) { + bitClear(mems_event, i); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Mem%d\":{\"State\":%s}}"), i+1, Settings.mems[i]); + RulesProcessEvent(json_event); + break; + } } } } @@ -1275,4 +1277,4 @@ bool Xdrv10(uint8_t function) return result; } -#endif // USE_RULES +#endif // USE_RULES \ No newline at end of file From d9bd95911963188c97dfd9c1b1aae11887170fd1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 30 Mar 2019 10:02:22 +0100 Subject: [PATCH 1198/2222] Fix compile error (#5544) Fix compile error (#5544) --- sonoff/settings.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 1e570a96b..c3e7203d7 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -61,6 +61,10 @@ #define LONGITUDE 2.294442 // [Longitude] Your location to be used with sunrise and sunset #endif +#ifndef WORKING_PERIOD +#define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes +#endif + /*********************************************************************************************\ * RTC memory \*********************************************************************************************/ From eb9617e3f91ad1f0075b7ebd42b094825765d924 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 30 Mar 2019 13:03:45 +0100 Subject: [PATCH 1199/2222] Tune some functionality Tune some functionality --- sonoff/xdrv_01_webserver.ino | 2 +- sonoff/xdrv_02_mqtt.ino | 15 +++++---------- sonoff/xdrv_03_energy.ino | 6 +++--- sonoff/xdrv_08_serial_bridge.ino | 6 +++--- sonoff/xdrv_11_knx.ino | 6 +++--- sonoff/xdrv_16_tuyadimmer.ino | 6 +++--- sonoff/xdrv_18_armtronix_dimmers.ino | 6 +++--- sonoff/xdrv_19_ps16dz_dimmer.ino | 6 +++--- sonoff/xdrv_99_debug.ino | 6 +++--- sonoff/xnrg_04_mcp39f501.ino | 6 +++--- 10 files changed, 30 insertions(+), 35 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 48932fb0d..eb58081ee 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2355,7 +2355,7 @@ bool Xdrv01(uint8_t function) case FUNC_LOOP: PollDnsWebserver(); #ifdef USE_EMULATION - if (Settings.flag2.emulation) PollUdp(); + if (Settings.flag2.emulation) { PollUdp(); } #endif // USE_EMULATION break; case FUNC_COMMAND: diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index b4228b11e..dda79790c 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -50,7 +50,6 @@ bool mqtt_allowed = false; // MQTT enabled and parameters valid * void MqttDisconnect() * void MqttSubscribeLib(char *topic) * bool MqttPublishLib(const char* topic, bool retained) - * void MqttLoop() \*********************************************************************************************/ #include @@ -91,11 +90,6 @@ bool MqttPublishLib(const char* topic, bool retained) return result; } -void MqttLoop(void) -{ - MqttClient.loop(); -} - /*********************************************************************************************/ #ifdef USE_DISCOVERY @@ -425,7 +419,8 @@ void MqttReconnect(void) UdpDisconnect(); #endif // USE_EMULATION - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); +// AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "(%d) " D_ATTEMPTING_CONNECTION), ESP.getFreeHeap()/1024); mqtt_connected = false; mqtt_retry_counter = Settings.mqtt_retry; @@ -816,6 +811,9 @@ bool Xdrv02(uint8_t function) if (Settings.flag.mqtt_enabled) { switch (function) { + case FUNC_LOOP: + if (MqttIsConnected()) { MqttClient.loop(); } + break; #ifdef USE_WEBSERVER case FUNC_WEB_ADD_BUTTON: WSContentSend_P(HTTP_BTN_MENU_MQTT); @@ -824,9 +822,6 @@ bool Xdrv02(uint8_t function) WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); break; #endif // USE_WEBSERVER - case FUNC_LOOP: - if (!global_state.mqtt_down) { MqttLoop(); } - break; case FUNC_COMMAND: result = MqttCommand(); break; diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 69d93b244..c1c65eafe 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -689,15 +689,15 @@ bool Xdrv03(uint8_t function) } else if (energy_flg) { switch (function) { + case FUNC_LOOP: + XnrgCall(FUNC_LOOP); + break; case FUNC_COMMAND: result = EnergyCommand(); break; case FUNC_SET_POWER: EnergySetPowerSteadyCounter(); break; - case FUNC_LOOP: - XnrgCall(FUNC_LOOP); - break; case FUNC_SERIAL: result = XnrgCall(FUNC_SERIAL); break; diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index e9f8294ca..fbad30683 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -172,12 +172,12 @@ bool Xdrv08(uint8_t function) if (serial_bridge_active) { switch (function) { - case FUNC_PRE_INIT: - SerialBridgeInit(); - break; case FUNC_LOOP: if (SerialBridgeSerial) { SerialBridgeInput(); } break; + case FUNC_PRE_INIT: + SerialBridgeInit(); + break; case FUNC_COMMAND: result = SerialBridgeCommand(); break; diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index b92ed1c7b..c4111bae3 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -1223,6 +1223,9 @@ bool Xdrv11(uint8_t function) { bool result = false; switch (function) { + case FUNC_LOOP: + if (!global_state.wifi_down) { knx.loop(); } // Process knx events + break; case FUNC_PRE_INIT: KNX_INIT(); break; @@ -1236,9 +1239,6 @@ bool Xdrv11(uint8_t function) break; #endif // USE_KNX_WEB_MENU #endif // USE_WEBSERVER - case FUNC_LOOP: - if (!global_state.wifi_down) { knx.loop(); } // Process knx events - break; case FUNC_EVERY_50_MSECOND: if (toggle_inhibit) { toggle_inhibit--; diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index f9b3665e4..d43e6397e 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -393,15 +393,15 @@ bool Xdrv16(uint8_t function) if (TUYA_DIMMER == my_module_type) { switch (function) { + case FUNC_LOOP: + if (TuyaSerial) { TuyaSerialInput(); } + break; case FUNC_MODULE_INIT: result = TuyaModuleSelected(); break; case FUNC_INIT: TuyaInit(); break; - case FUNC_LOOP: - if (TuyaSerial) { TuyaSerialInput(); } - break; case FUNC_SET_DEVICE_POWER: result = TuyaSetPower(); break; diff --git a/sonoff/xdrv_18_armtronix_dimmers.ino b/sonoff/xdrv_18_armtronix_dimmers.ino index 30af12ce7..79645bdf9 100644 --- a/sonoff/xdrv_18_armtronix_dimmers.ino +++ b/sonoff/xdrv_18_armtronix_dimmers.ino @@ -170,15 +170,15 @@ bool Xdrv18(uint8_t function) if (ARMTRONIX_DIMMERS == my_module_type) { switch (function) { + case FUNC_LOOP: + if (ArmtronixSerial) { ArmtronixSerialInput(); } + break; case FUNC_MODULE_INIT: result = ArmtronixModuleSelected(); break; case FUNC_INIT: ArmtronixInit(); break; - case FUNC_LOOP: - if (ArmtronixSerial) { ArmtronixSerialInput(); } - break; case FUNC_EVERY_SECOND: if (ArmtronixSerial) { if (armtronix_wifi_state!=WifiState()) { ArmtronixSetWifiLed(); } diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index ab58b6d9d..bcca6b0be 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -223,15 +223,15 @@ bool Xdrv19(uint8_t function) if (PS_16_DZ == my_module_type) { switch (function) { + case FUNC_LOOP: + if (PS16DZSerial) { PS16DZSerialInput(); } + break; case FUNC_MODULE_INIT: result = PS16DZModuleSelected(); break; case FUNC_INIT: PS16DZInit(); break; - case FUNC_LOOP: - if (PS16DZSerial) { PS16DZSerialInput(); } - break; case FUNC_SET_DEVICE_POWER: result = PS16DZSetPower(); break; diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_99_debug.ino index 08a73d4da..e3e90a398 100644 --- a/sonoff/xdrv_99_debug.ino +++ b/sonoff/xdrv_99_debug.ino @@ -497,12 +497,12 @@ bool Xdrv99(uint8_t function) bool result = false; switch (function) { - case FUNC_PRE_INIT: - CPU_last_millis = millis(); - break; case FUNC_LOOP: CpuLoadLoop(); break; + case FUNC_PRE_INIT: + CPU_last_millis = millis(); + break; case FUNC_COMMAND: result = DebugCommand(); break; diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index 5d6adec33..5441a45ca 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -652,12 +652,12 @@ int Xnrg04(uint8_t function) } else if (XNRG_04 == energy_flg) { switch (function) { - case FUNC_INIT: - McpSnsInit(); - break; case FUNC_LOOP: if (McpSerial) { McpSerialInput(); } break; + case FUNC_INIT: + McpSnsInit(); + break; case FUNC_EVERY_SECOND: if (McpSerial) { McpEverySecond(); } break; From 2aad0567bfc0352ef355129c960c522eb40be099 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 30 Mar 2019 16:29:27 +0100 Subject: [PATCH 1200/2222] Change some defines to const Change some defines to const --- sonoff/_changelog.ino | 1 + sonoff/sonoff.h | 190 ++++++++++++++++++------------------- sonoff/sonoff.ino | 13 +-- sonoff/support_rtc.ino | 9 +- sonoff/xdrv_02_mqtt.ino | 2 +- sonoff/xdrv_13_display.ino | 2 +- 6 files changed, 110 insertions(+), 107 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index c15f33aff..6f40ca4ae 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.5.0.3 20190328 * Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452) + * Change some defines to const * * 6.5.0.2 20190325 * Change UDP initial message handling from string to char using static memory and add debug info (#5505) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 635a1017a..cd1659388 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -42,109 +42,109 @@ \*********************************************************************************************/ typedef unsigned long power_t; // Power (Relay) type -#define POWER_MASK 0xffffffffUL // Power (Relay) full mask +const uint32_t POWER_MASK = 0xffffffffUL; // Power (Relay) full mask + +/*********************************************************************************************\ + * Constants +\*********************************************************************************************/ + +// Changes to the following MAX_ defines will impact settings layout +const uint8_t MAX_SWITCHES = 8; // Max number of switches +const uint8_t MAX_RELAYS = 8; // Max number of relays +const uint8_t MAX_INTERLOCKS = 4; // Max number of interlock groups (MAX_RELAYS / 2) +const uint8_t MAX_LEDS = 4; // Max number of leds +const uint8_t MAX_KEYS = 4; // Max number of keys or buttons +const uint8_t MAX_PWMS = 5; // Max number of PWM channels +const uint8_t MAX_COUNTERS = 4; // Max number of counter sensors +const uint8_t MAX_TIMERS = 16; // Max number of Timers +const uint8_t MAX_PULSETIMERS = 8; // Max number of supported pulse timers +const uint8_t MAX_FRIENDLYNAMES = 4; // Max number of Friendly names +const uint8_t MAX_DOMOTICZ_IDX = 4; // Max number of Domoticz device, key and switch indices +const uint8_t MAX_DOMOTICZ_SNS_IDX = 12; // Max number of Domoticz sensors indices +const uint8_t MAX_KNX_GA = 10; // Max number of KNX Group Addresses to read that can be set +const uint8_t MAX_KNX_CB = 10; // Max number of KNX Group Addresses to write that can be set +const uint8_t MAX_XNRG_DRIVERS = 32; // Max number of allowed energy drivers +const uint8_t MAX_XDSP_DRIVERS = 32; // Max number of allowed display drivers +const uint8_t MAX_XDRV_DRIVERS = 96; // Max number of allowed driver drivers +const uint8_t MAX_XSNS_DRIVERS = 96; // Max number of allowed sensor drivers +const uint8_t MAX_RULE_MEMS = 5; // Max number of saved vars +const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 512 characters +const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules + +const uint8_t MAX_FAN_SPEED = 4; // Max number of iFan02 fan speeds (0 .. 3) + +const char MQTT_TOKEN_PREFIX[] PROGMEM = "%prefix%"; // To be substituted by mqtt_prefix[x] +const char MQTT_TOKEN_TOPIC[] PROGMEM = "%topic%"; // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic +const char WIFI_HOSTNAME[] = "%s-%04d"; // Expands to - + +const uint8_t CONFIG_FILE_SIGN = 0xA5; // Configuration file signature +const uint8_t CONFIG_FILE_XOR = 0x5A; // Configuration file xor (0 = No Xor) + +const uint32_t HLW_PREF_PULSE = 12530; // was 4975us = 201Hz = 1000W +const uint32_t HLW_UREF_PULSE = 1950; // was 1666us = 600Hz = 220V +const uint32_t HLW_IREF_PULSE = 3500; // was 1666us = 600Hz = 4.545A + +const uint8_t MQTT_RETRY_SECS = 10; // Minimum seconds to retry MQTT connection +const uint32_t GLOBAL_VALUES_VALID = 300; // Max number of seconds to keep last received values +const power_t APP_POWER = 0; // Default saved power state Off +const uint16_t WS2812_MAX_LEDS = 512; // Max number of LEDs + +const uint32_t PWM_RANGE = 1023; // 255..1023 needs to be devisible by 256 +//const uint16_t PWM_FREQ = 1000; // 100..1000 Hz led refresh +//const uint16_t PWM_FREQ = 910; // 100..1000 Hz led refresh (iTead value) +const uint16_t PWM_FREQ = 880; // 100..1000 Hz led refresh (BN-SZ01 value) +const uint16_t PWM_MAX = 4000; // [PWM_MAX] Maximum frequency - Default: 4000 +const uint16_t PWM_MIN = 100; // [PWM_MIN] Minimum frequency - Default: 100 + // For Dimmers use double of your mains AC frequecy (100 for 50Hz and 120 for 60Hz) + // For Controlling Servos use 50 and also set PWM_FREQ as 50 (DO NOT USE THESE VALUES FOR DIMMERS) +//#define PWM_LIGHTSCHEME0_IGNORE_SLEEP // Do not change sleep value for LightAnimate() scheme 0 + +const uint8_t DEFAULT_POWER_DELTA = 80; // Power change percentage +const uint16_t MAX_POWER_HOLD = 10; // Time in SECONDS to allow max agreed power +const uint16_t MAX_POWER_WINDOW = 30; // Time in SECONDS to disable allow max agreed power +const uint16_t SAFE_POWER_HOLD = 10; // Time in SECONDS to allow max unit safe power +const uint16_t SAFE_POWER_WINDOW = 30; // Time in MINUTES to disable allow max unit safe power +const uint8_t MAX_POWER_RETRY = 5; // Retry count allowing agreed power limit overflow + +const uint8_t STATES = 20; // Number of states per second using 50 mSec interval +const uint8_t IMMINENT_RESET_FACTOR = 10; // Factor to extent button hold time for imminent Reset to default 40 seconds using KEY_HOLD_TIME of 40 +const uint32_t BOOT_LOOP_TIME = 10; // Number of seconds to stop detecting boot loops +const uint16_t SYSLOG_TIMER = 600; // Seconds to restore syslog_level +const uint16_t SERIALLOG_TIMER = 600; // Seconds to disable SerialLog +const uint8_t OTA_ATTEMPTS = 5; // Number of times to try fetching the new firmware + +const uint16_t INPUT_BUFFER_SIZE = 520; // Max number of characters in (serial and http) command buffer +const uint16_t CMDSZ = 24; // Max number of characters in command +const uint16_t TOPSZ = 100; // Max number of characters in topic string +const uint16_t LOGSZ = 520; // Max number of characters in log +const uint16_t MIN_MESSZ = 893; // Min number of characters in MQTT message + +const uint8_t SENSOR_MAX_MISS = 5; // Max number of missed sensor reads before deciding it's offline + +#ifdef USE_MQTT_TLS + const uint16_t WEB_LOG_SIZE = 2000; // Max number of characters in weblog +#else + const uint16_t WEB_LOG_SIZE = 4000; // Max number of characters in weblog +#endif + +const uint8_t MAX_BACKLOG = 30; // Max number of commands in backlog +const uint32_t MIN_BACKLOG_DELAY = 2; // Minimal backlog delay in 0.1 seconds + +const uint32_t SOFT_BAUDRATE = 9600; // Default software serial baudrate +const uint32_t APP_BAUDRATE = 115200; // Default serial baudrate +const uint32_t SERIAL_POLLING = 100; // Serial receive polling in ms +const uint8_t MAX_STATUS = 11; // Max number of status lines + +const uint32_t DRIVER_BOOT_DELAY = 1; // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting +const uint32_t LOOP_SLEEP_DELAY = 50; // Lowest number of milliseconds to go through the main loop using delay when needed /*********************************************************************************************\ * Defines \*********************************************************************************************/ -// Changes to the following MAX_ defines will impact settings layout -#define MAX_SWITCHES 8 // Max number of switches -#define MAX_RELAYS 8 // Max number of relays -#define MAX_INTERLOCKS 4 // Max number of interlock groups (MAX_RELAYS / 2) -#define MAX_LEDS 4 // Max number of leds -#define MAX_KEYS 4 // Max number of keys or buttons -#define MAX_PWMS 5 // Max number of PWM channels -#define MAX_COUNTERS 4 // Max number of counter sensors -#define MAX_TIMERS 16 // Max number of Timers -#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 MAX_DOMOTICZ_SNS_IDX 12 // Max number of Domoticz sensors indices -#define MAX_KNX_GA 10 // Max number of KNX Group Addresses to read that can be set -#define MAX_KNX_CB 10 // Max number of KNX Group Addresses to write that can be set -#define MAX_XNRG_DRIVERS 32 // Max number of allowed energy drivers -#define MAX_XDSP_DRIVERS 32 // Max number of allowed display drivers -#define MAX_XDRV_DRIVERS 96 // Max number of allowed driver drivers -#define MAX_XSNS_DRIVERS 96 // Max number of allowed sensor drivers -#define MAX_RULE_MEMS 5 // Max number of saved vars -#define MAX_RULE_SETS 3 // Max number of rule sets of size 512 characters -#define MAX_RULE_SIZE 512 // Max number of characters in rules - -// Changes to the following defines have no impact on settings layout #define MAX_RULE_TIMERS 8 // Max number of rule timers (4 bytes / timer) #define MAX_RULE_VARS 5 // Max number of rule variables (10 bytes / variable) -#define MAX_FAN_SPEED 4 // Max number of iFan02 fan speeds (0 .. 3) - -#define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x] -#define MQTT_TOKEN_TOPIC "%topic%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic -#define MQTT_TOKEN_HOSTNAME "%hostname%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic -#define MQTT_TOKEN_ID "%id%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic - -#define WIFI_HOSTNAME "%s-%04d" // Expands to - - -#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 GLOBAL_VALUES_VALID 300 // Max number of seconds to keep last received values -#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 PWM_MAX 4000 // [PWM_MAX] Maximum frequency - Default: 4000 -#define PWM_MIN 100 // [PWM_MIN] Minimum frequency - Default: 100 - // For Dimmers use double of your mains AC frequecy (100 for 50Hz and 120 for 60Hz) - // For Controlling Servos use 50 and also set PWM_FREQ as 50 (DO NOT USE THESE VALUES FOR DIMMERS) -//#define PWM_LIGHTSCHEME0_IGNORE_SLEEP // Do not change sleep value for LightAnimate() scheme 0 - -#define DEFAULT_POWER_DELTA 80 // Power change percentage -#define MAX_POWER_HOLD 10 // Time in SECONDS to allow max agreed power -#define MAX_POWER_WINDOW 30 // Time in SECONDS to disable allow max agreed power -#define SAFE_POWER_HOLD 10 // Time in SECONDS to allow max unit safe power -#define SAFE_POWER_WINDOW 30 // Time in MINUTES to disable allow max unit safe power -#define MAX_POWER_RETRY 5 // Retry count allowing agreed power limit overflow - -#define STATES 20 // Number of states per second using 50 mSec interval -#define IMMINENT_RESET_FACTOR 10 // Factor to extent button hold time for imminent Reset to default 40 seconds using KEY_HOLD_TIME of 40 -#define BOOT_LOOP_TIME 10 // Number of seconds to stop detecting boot loops -#define SYSLOG_TIMER 600 // Seconds to restore syslog_level -#define SERIALLOG_TIMER 600 // Seconds to disable SerialLog -#define OTA_ATTEMPTS 5 // Number of times to try fetching the new firmware - -#define INPUT_BUFFER_SIZE 520 // Max number of characters in (serial and http) command buffer -#define CMDSZ 24 // Max number of characters in command -#define TOPSZ 100 // Max number of characters in topic string -#define LOGSZ 520 // Max number of characters in log -#define MIN_MESSZ 893 // Min number of characters in MQTT message - -#define SENSOR_MAX_MISS 5 // Max number of missed sensor reads before deciding it's offline - -#ifdef USE_MQTT_TLS - #define WEB_LOG_SIZE 2000 // Max number of characters in weblog -#else - #define WEB_LOG_SIZE 4000 // Max number of characters in weblog -#endif - -#define MAX_BACKLOG 30 // Max number of commands in backlog -#define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds - -#define SOFT_BAUDRATE 9600 // Default software serial baudrate -#define APP_BAUDRATE 115200 // Default serial baudrate -#define SERIAL_POLLING 100 // Serial receive polling in ms -#define MAX_STATUS 11 // Max number of status lines - -#define DRIVER_BOOT_DELAY 1 // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting -#define LOOP_SLEEP_DELAY 50 // Lowest number of milliseconds to go through the main loop using delay when needed - #define NO_EXTRA_4K_HEAP // Allocate 4k heap for WPS in ESP8166/Arduino core v2.4.2 (was always allocated in previous versions) /* diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index bcefc9a08..e85a26af2 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -254,20 +254,21 @@ char* GetTopic_P(char *stopic, uint8_t prefix, char *topic, const char* subtopic fulltopic += F("_fb"); // cmnd/_fb } else { 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 + if ((0 == prefix) && (-1 == fulltopic.indexOf(FPSTR(MQTT_TOKEN_PREFIX)))) { + fulltopic += F("/"); + fulltopic += FPSTR(MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops } for (uint8_t i = 0; i < 3; 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), Settings.mqtt_prefix[prefix]); - fulltopic.replace(F(MQTT_TOKEN_TOPIC), topic); - fulltopic.replace(F(MQTT_TOKEN_HOSTNAME), my_hostname); + fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), Settings.mqtt_prefix[prefix]); + fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), topic); + fulltopic.replace(F("%hostname%"), my_hostname); String token_id = WiFi.macAddress(); token_id.replace(":", ""); - fulltopic.replace(F(MQTT_TOKEN_ID), token_id); + fulltopic.replace(F("%id%"), token_id); } fulltopic.replace(F("#"), ""); fulltopic.replace(F("//"), "/"); diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index 5af8b49a0..fd9575b32 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -22,10 +22,11 @@ * Timezone by Jack Christensen (https://github.com/JChristensen/Timezone) \*********************************************************************************************/ -#define SECS_PER_MIN ((uint32_t)(60UL)) -#define SECS_PER_HOUR ((uint32_t)(3600UL)) -#define SECS_PER_DAY ((uint32_t)(SECS_PER_HOUR * 24UL)) -#define MINS_PER_HOUR ((uint32_t)(60UL)) +const uint32_t SECS_PER_MIN = 60UL; +const uint32_t SECS_PER_HOUR = 3600UL; +const uint32_t SECS_PER_DAY = SECS_PER_HOUR * 24UL; +const uint32_t MINS_PER_HOUR = 60UL; + #define LEAP_YEAR(Y) (((1970+Y)>0) && !((1970+Y)%4) && (((1970+Y)%100) || !((1970+Y)%400))) extern "C" { diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index dda79790c..fd58ff8bb 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -295,7 +295,7 @@ void MqttConnected(void) GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); MqttSubscribe(stopic); - if (strstr(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != nullptr) { + if (strstr_P(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != nullptr) { GetTopic_P(stopic, CMND, Settings.mqtt_grptopic, PSTR("#")); MqttSubscribe(stopic); GetFallbackTopic_P(stopic, CMND, PSTR("#")); diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 8a05d68f3..498cce9fc 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -830,7 +830,7 @@ void DisplayMqttSubscribe(void) strlcpy(stopic, Settings.mqtt_fulltopic, sizeof(stopic)); char *tp = strtok(stopic, "/"); while (tp != nullptr) { - if (!strcmp_P(tp, PSTR(MQTT_TOKEN_PREFIX))) { + if (!strcmp_P(tp, MQTT_TOKEN_PREFIX)) { break; } strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); // Add single-level wildcards From 929292f7a8967abfee35fdcf0a1a9cac07c7c8ff Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 30 Mar 2019 16:32:22 +0100 Subject: [PATCH 1201/2222] Update xdrv_02_mqtt.ino Restore MQTT attempting connection message --- sonoff/xdrv_02_mqtt.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index fd58ff8bb..d3c3c5446 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -419,8 +419,8 @@ void MqttReconnect(void) UdpDisconnect(); #endif // USE_EMULATION -// AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "(%d) " D_ATTEMPTING_CONNECTION), ESP.getFreeHeap()/1024); + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); +// AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "(%d) " D_ATTEMPTING_CONNECTION), ESP.getFreeHeap()/1024); mqtt_connected = false; mqtt_retry_counter = Settings.mqtt_retry; From 5c1fa161ba8f7b1acddc2d4b6fd612f6d88b73de Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sat, 30 Mar 2019 18:28:40 -0300 Subject: [PATCH 1202/2222] Update CONTRIBUTING.md --- CONTRIBUTING.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7cfcdfadb..3ecb5a9bc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -56,7 +56,57 @@ The process is straight-forward. 7. All pull requests should consider updates to the documentation. 8. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority. 9. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged. -10. Pull requests that don't meet the above will be denied and closed. +10. By submitting a PR, it is needed to use the provided PR template and check all boxes, performing the required tasks and accepting the CLA. +11. Pull requests that don't meet the above will be denied and closed. + +-------------------------------------- + +## Contributor License Agreement (CLA) + +``` +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the GPL-3.0 license; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the GPL-3.0 license; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it) is maintained indefinitely + and may be redistributed consistent with this project or the open + source license(s) involved. +``` + +This Contributor License Agreement (CLA) was adopted on April 1st, 2019. + +The text of this license is available under the [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/). It is based on the Linux [Developer Certificate Of Origin](http://elinux.org/Developer_Certificate_Of_Origin), but is modified to explicitly use the GPL-3.0 license and not mention sign-off (due to GitHub.com keeps an historial, with your user name, of PRs' commits and all editions on PR's comments). + +To accept the CLA it is required to put a x between [ ] on `[ ] I accept the CLA` in the PR template when submitting it. The [ ] is an opt-in box, so you have to manually accept it. + +**Why a CLA ?** + +_"A Contributor Licence Agreement (CLA) is strongly recommended when accepting third party contributions to an open development project, such as an open source software project. In order to redistribute contributions, it is necessary to ensure that the project has the necessary rights to do so. A Contributor Licence Agreement is a lightweight agreement, signed by the copyright holder, that grants the necessary rights for the contribution to be redistributed as part of the project."_ [OSS Watch](http://oss-watch.ac.uk/resources/cla) + +A CLA is a legal document in which you state _you are entitled to contribute the code/documentation/translation to the project_ you’re contributing to and that _you are willing to have it used in distributions and derivative works_. This means that should there be any kind of legal issue in the future as to the origins and ownership of any particular piece of code, then that project has the necessary forms on file from the contributor(s) saying they were permitted to make this contribution. + +CLA is a safety because it also ensures that once you have provided a contribution, you cannot try to withdraw permission for its use at a later date. People can therefore use that software, confident that they will not be asked to stop using pieces of the code at a later date. + +A __license__ grants "outbound" rights to the user of project. + +A __CLA__ enables a contributor to grant "inbound" rights to a project. + + + + From 34d5cbf20f4cd2f8a826f59bc24d34b7d844e24b Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sat, 30 Mar 2019 18:42:56 -0300 Subject: [PATCH 1203/2222] Update PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index aea7cd816..a4a459a18 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,8 +3,9 @@ **Related issue (if applicable):** fixes # ## Checklist: - - [ ] The pull request is done against the dev branch - - [ ] Only relevant files were touched (Also beware if your editor has auto-formatting feature enabled) + - [ ] The pull request is done against the latest dev branch + - [ ] Only relevant files were touched (Also remember to update _changelog.ino_ file) - [ ] Only one feature/fix was added per PR. - [ ] The code change is tested and works. - [ ] The code change pass travis tests. **Your PR cannot be merged unless tests pass** + - [ ] I accept the [CLA](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla). From f7c30250c10a49bcf6b20e501a7df6afb3e24703 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 31 Mar 2019 11:59:04 +0200 Subject: [PATCH 1204/2222] Change some more defines to const Change some more defines to const --- sonoff/settings.h | 4 ++-- sonoff/settings.ino | 8 ++++---- sonoff/sonoff_version.h | 7 +------ sonoff/support.ino | 4 ++-- sonoff/support_switch.ino | 2 +- sonoff/support_wifi.ino | 10 +++++----- sonoff/xdrv_01_webserver.ino | 16 ++++++++-------- sonoff/xdrv_02_mqtt.ino | 1 - sonoff/xdrv_04_light.ino | 18 +++++++++--------- sonoff/xdrv_05_irremote.ino | 23 +++++++++++------------ sonoff/xdrv_06_snfbridge.ino | 6 +++--- sonoff/xdrv_08_serial_bridge.ino | 2 +- sonoff/xdrv_13_display.ino | 8 ++++---- 13 files changed, 51 insertions(+), 58 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index f7eed3f11..07cb646d8 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -20,7 +20,7 @@ #ifndef _SETTINGS_H_ #define _SETTINGS_H_ -#define PARAM8_SIZE 18 // Number of param bytes (SetOption) +const uint8_t PARAM8_SIZE = 18; // Number of param bytes (SetOption) typedef union { // Restricted by MISRA-C Rule 18.4 but so useful... uint32_t data; // Allow bit manipulation using SetOption @@ -397,7 +397,7 @@ struct XDRVMAILBOX { char *data; } XdrvMailbox; -#define MAX_RULES_FLAG 7 // Number of bits used in RulesBitfield (tricky I know...) +const uint8_t MAX_RULES_FLAG = 7; // Number of bits used in RulesBitfield (tricky I know...) typedef union { // Restricted by MISRA-C Rule 18.4 but so useful... uint16_t data; // Allow bit manipulation struct { diff --git a/sonoff/settings.ino b/sonoff/settings.ino index c3e7203d7..dcebe4512 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -69,7 +69,7 @@ * RTC memory \*********************************************************************************************/ -#define RTC_MEM_VALID 0xA55A +const uint16_t RTC_MEM_VALID = 0xA55A; uint32_t rtc_settings_crc = 0; @@ -168,12 +168,12 @@ extern "C" { extern "C" uint32_t _SPIFFS_end; // From libraries/EEPROM/EEPROM.cpp EEPROMClass -#define SPIFFS_END ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE +const uint32_t SPIFFS_END = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; // Version 4.2 config = eeprom area -#define SETTINGS_LOCATION SPIFFS_END // No need for SPIFFS as it uses EEPROM area +const uint32_t 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) +const uint8_t CFG_ROTATES = 8; // Number of flash sectors used (handles uploads) /*********************************************************************************************\ * EEPROM support based on EEPROM library and tuned for Tasmota diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index ac84738ec..68c28a9d0 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,11 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06050003 - -#define D_PROGRAMNAME "Sonoff-Tasmota" -#define D_AUTHOR "Theo Arends" -//#define D_WEBLINK "https://github.com/arendst/Sonoff-Tasmota" -#define D_WEBLINK "https://bit.ly/tasmota" +const uint32_t VERSION = 0x06050003; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/support.ino b/sonoff/support.ino index 07edd039a..e571e6ec1 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -28,7 +28,7 @@ uint32_t syslog_host_hash = 0; // Syslog host name hash Ticker tickerOSWatch; -#define OSWATCH_RESET_TIME 120 +const uint32_t OSWATCH_RESET_TIME = 120; static unsigned long oswatch_last_loop_time; uint8_t oswatch_blocked_loop = 0; @@ -996,7 +996,7 @@ void SetNextTimeInterval(unsigned long& timer, const unsigned long step) \*********************************************************************************************/ #ifdef USE_I2C -#define I2C_RETRY_COUNTER 3 +const uint8_t I2C_RETRY_COUNTER = 3; uint32_t i2c_buffer = 0; diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino index 7e84149ba..3eb927388 100644 --- a/sonoff/support_switch.ino +++ b/sonoff/support_switch.ino @@ -25,7 +25,7 @@ * Inspired by (https://github.com/OLIMEX/olimex-iot-firmware-esp8266/blob/master/olimex/user/user_switch2.c) \*********************************************************************************************/ -#define SWITCH_PROBE_INTERVAL 10 // Time in milliseconds between switch input probe +const uint8_t SWITCH_PROBE_INTERVAL = 10; // Time in milliseconds between switch input probe #include diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 2c7299991..445c14c0b 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -22,15 +22,15 @@ \*********************************************************************************************/ #ifndef WIFI_RSSI_THRESHOLD -#define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network +#define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network #endif #ifndef WIFI_RESCAN_MINUTES -#define WIFI_RESCAN_MINUTES 44 // Number of minutes between wifi network rescan +#define WIFI_RESCAN_MINUTES 44 // Number of minutes between wifi network rescan #endif -#define WIFI_CONFIG_SEC 180 // seconds before restart -#define WIFI_CHECK_SEC 20 // seconds -#define WIFI_RETRY_OFFSET_SEC 20 // seconds +const uint8_t WIFI_CONFIG_SEC = 180; // seconds before restart +const uint8_t WIFI_CHECK_SEC = 20; // seconds +const uint8_t WIFI_RETRY_OFFSET_SEC = 20; // seconds /* // This worked for 2_5_0_BETA2 but fails since then. Waiting for a solution from core team (#4952) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index eb58081ee..44be997a6 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -27,15 +27,15 @@ #define XDRV_01 1 -#define CHUNKED_BUFFER_SIZE 400 // Chunk buffer size - #ifndef WIFI_SOFT_AP_CHANNEL -#define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by SmartConfig web GUI +#define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by SmartConfig web GUI #endif -#define HTTP_REFRESH_TIME 2345 // milliseconds -#define HTTP_RESTART_RECONNECT_TIME 9000 // milliseconds -#define HTTP_OTA_RESTART_RECONNECT_TIME 20000 // milliseconds +const uint16_t CHUNKED_BUFFER_SIZE = 400; // Chunk buffer size (should be smaller than half mqtt_date size) + +const uint16_t HTTP_REFRESH_TIME = 2345; // milliseconds +#define HTTP_RESTART_RECONNECT_TIME 9000 // milliseconds +#define HTTP_OTA_RESTART_RECONNECT_TIME 20000 // milliseconds #include #include @@ -376,7 +376,7 @@ const char HTTP_COUNTER[] PROGMEM = "
"; const char HTTP_END[] PROGMEM = - "
" + "" "" "" ""; @@ -413,7 +413,7 @@ const char kUploadErrors[] PROGMEM = #endif ; -#define DNS_PORT 53 +const uint16_t DNS_PORT = 53; enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER, HTTP_MANAGER_RESET_ONLY}; DNSServer *DnsServer; diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index d3c3c5446..5720b9a7d 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -420,7 +420,6 @@ void MqttReconnect(void) #endif // USE_EMULATION AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); -// AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "(%d) " D_ATTEMPTING_CONNECTION), ESP.getFreeHeap()/1024); mqtt_connected = false; mqtt_retry_counter = Settings.mqtt_retry; diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 5dae14ce7..7597415d6 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -56,7 +56,7 @@ #define XDRV_04 4 -#define WS2812_SCHEMES 7 // Number of additional WS2812 schemes supported by xdrv_ws2812.ino +const uint8_t WS2812_SCHEMES = 7; // Number of additional WS2812 schemes supported by xdrv_ws2812.ino enum LightCommands { CMND_COLOR, CMND_COLORTEMPERATURE, CMND_DIMMER, CMND_LED, CMND_LEDTABLE, CMND_FADE, @@ -70,23 +70,23 @@ const char kLightCommands[] PROGMEM = struct LRgbColor { uint8_t R, G, B; }; -#define MAX_FIXED_COLOR 12 +const uint8_t MAX_FIXED_COLOR = 12; const LRgbColor kFixedColor[MAX_FIXED_COLOR] PROGMEM = { 255,0,0, 0,255,0, 0,0,255, 228,32,0, 0,228,32, 0,32,228, 188,64,0, 0,160,96, 160,32,240, 255,255,0, 255,0,170, 255,255,255 }; struct LWColor { uint8_t W; }; -#define MAX_FIXED_WHITE 4 +const uint8_t MAX_FIXED_WHITE = 4; const LWColor kFixedWhite[MAX_FIXED_WHITE] PROGMEM = { 0, 255, 128, 32 }; struct LCwColor { uint8_t C, W; }; -#define MAX_FIXED_COLD_WARM 4 +const uint8_t MAX_FIXED_COLD_WARM = 4; const LCwColor kFixedColdWarm[MAX_FIXED_COLD_WARM] PROGMEM = { 0,0, 255,0, 0,255, 128,128 }; -uint8_t ledTable[] = { +const 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, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, @@ -132,11 +132,11 @@ unsigned long strip_timer_counter = 0; // Bars and Gradient * Arilux LC11 Rf support stripped from RCSwitch library \*********************************************************************************************/ -#define ARILUX_RF_TIME_AVOID_DUPLICATE 1000 // Milliseconds +const uint32_t ARILUX_RF_TIME_AVOID_DUPLICATE = 1000; // Milliseconds -#define ARILUX_RF_MAX_CHANGES 51 // Pulses (sync + 2 x 24 bits) -#define ARILUX_RF_SEPARATION_LIMIT 4300 // Microseconds -#define ARILUX_RF_RECEIVE_TOLERANCE 60 // Percentage +const uint8_t ARILUX_RF_MAX_CHANGES = 51; // Pulses (sync + 2 x 24 bits) +const uint32_t ARILUX_RF_SEPARATION_LIMIT = 4300; // Microseconds +const uint32_t ARILUX_RF_RECEIVE_TOLERANCE = 60; // Percentage unsigned int arilux_rf_timings[ARILUX_RF_MAX_CHANGES]; diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 7e6501142..864d77e8c 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -42,17 +42,17 @@ enum IrHvacVendors { VNDR_TOSHIBA, VNDR_MITSUBISHI, VNDR_LG, VNDR_FUJITSU }; const char kIrHvacVendors[] PROGMEM = "Toshiba|Mitsubishi|LG|Fujitsu" ; // 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 +const uint16_t HVAC_TOSHIBA_HDR_MARK = 4400; +const uint16_t HVAC_TOSHIBA_HDR_SPACE = 4300; +const uint16_t HVAC_TOSHIBA_BIT_MARK = 543; +const uint16_t HVAC_TOSHIBA_ONE_SPACE = 1623; +const uint16_t HVAC_MISTUBISHI_ZERO_SPACE = 472; +const uint16_t HVAC_TOSHIBA_RPT_MARK = 440; +const uint16_t HVAC_TOSHIBA_RPT_SPACE = 7048; // Above original iremote limit +const uint8_t HVAC_TOSHIBA_DATALEN = 9; // HVAC LG -#define HVAC_LG_DATALEN 7 +const uint8_t HVAC_LG_DATALEN = 7; IRMitsubishiAC *mitsubir = nullptr; @@ -84,9 +84,8 @@ void IrSendInit(void) * IR Receive \*********************************************************************************************/ -#define IR_RCV_SAVE_BUFFER 0 // 0 = do not use buffer, 1 = use buffer for decoding - -#define IR_TIME_AVOID_DUPLICATE 500 // Milliseconds +const bool IR_RCV_SAVE_BUFFER = false; // false = do not use buffer, true = use buffer for decoding +const uint32_t IR_TIME_AVOID_DUPLICATE = 500; // Milliseconds #include diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index f2550bf8d..eaf934043 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -23,7 +23,7 @@ #define XDRV_06 6 -#define SFB_TIME_AVOID_DUPLICATE 2000 // Milliseconds +const uint32_t SFB_TIME_AVOID_DUPLICATE = 2000; // Milliseconds enum SonoffBridgeCommands { CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE, CMND_RFKEY, CMND_RFRAW }; @@ -51,8 +51,8 @@ unsigned long sonoff_bridge_last_learn_time = 0; #include "ihx.h" #include "c2.h" -#define RF_RECORD_NO_START_FOUND -1 -#define RF_RECORD_NO_END_FOUND -2 +const ssize_t RF_RECORD_NO_START_FOUND = -1; +const ssize_t RF_RECORD_NO_END_FOUND = -2; ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size) { diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index fbad30683..0125591c1 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -24,7 +24,7 @@ #define XDRV_08 8 -#define SERIAL_BRIDGE_BUFFER_SIZE 130 +const uint8_t SERIAL_BRIDGE_BUFFER_SIZE = 130; #include diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 498cce9fc..3f40bdb84 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -22,11 +22,11 @@ #define XDRV_13 13 -#define DISPLAY_MAX_DRIVERS 16 // Max number of display drivers/models supported by xdsp_interface.ino -#define DISPLAY_MAX_COLS 44 // Max number of columns allowed with command DisplayCols -#define DISPLAY_MAX_ROWS 32 // Max number of lines allowed with command DisplayRows +const uint8_t DISPLAY_MAX_DRIVERS = 16; // Max number of display drivers/models supported by xdsp_interface.ino +const uint8_t DISPLAY_MAX_COLS = 44; // Max number of columns allowed with command DisplayCols +const uint8_t DISPLAY_MAX_ROWS = 32; // Max number of lines allowed with command DisplayRows -#define DISPLAY_LOG_ROWS 32 // Number of lines in display log buffer +const uint8_t DISPLAY_LOG_ROWS = 32; // Number of lines in display log buffer #define D_CMND_DISPLAY "Display" #define D_CMND_DISP_ADDRESS "Address" From d310373c288189f32fd1055b9f96d6f9a2829308 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Sun, 31 Mar 2019 12:23:09 +0200 Subject: [PATCH 1205/2222] decode-config.py: adapt settings - add Sensor20 (novasds_period) --- tools/decode-config.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index feec178cf..161cc850d 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0022' +VER = '2.1.0023' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -878,7 +878,13 @@ Setting_6_4_1_18['flag3'][0].update ({ 'no_hold_retain': (' Date: Sun, 31 Mar 2019 13:06:42 +0200 Subject: [PATCH 1206/2222] Fix parameter exceptions (#5555) Fix parameter exceptions (#5555) --- sonoff/xdrv_05_irremote.ino | 261 +++++++++++++++++++----------------- 1 file changed, 141 insertions(+), 120 deletions(-) diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 864d77e8c..d62be8ee3 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -26,6 +26,8 @@ #include +enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC }; + enum IrRemoteCommands { CMND_IRSEND, CMND_IRHVAC }; const char kIrRemoteCommands[] PROGMEM = D_CMND_IRSEND "|" D_CMND_IRHVAC ; @@ -180,7 +182,7 @@ void IrReceiveCheck(void) TOSHIBA ********************/ -bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +uint8_t IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) { uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; uint8_t data[HVAC_TOSHIBA_DATALEN] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}; @@ -195,7 +197,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } data[6] = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 @@ -210,7 +212,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } mode = p - kFanSpeedOptions + 1; if ((1 == mode) || (7 == mode)) { @@ -267,7 +269,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po irsend->sendRaw(rawdata, i, 38); // interrupts(); - return false; + return IE_NO_ERROR; } @@ -275,7 +277,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po MITSUBISHI ********************/ -bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +uint8_t IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) { char *p; uint8_t mode; @@ -289,7 +291,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } mode = (p - kHvacModeOptions + 1) << 3; // HOT = 0x08, DRY = 0x10, COOL = 0x18, AUTO = 0x20 mitsubir->setMode(mode); @@ -303,7 +305,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } mode = p - kFanSpeedOptions; // AUTO = 0, SPEED = 1 .. 5, SILENT = 6 mitsubir->setFan(mode); @@ -315,7 +317,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Mitsubishi Power %d, Mode %d, FanSpeed %d, Temp %d, VaneMode %d"), // mitsubir->getPower(), mitsubir->getMode(), mitsubir->getFan(), mitsubir->getTemp(), mitsubir->getVane()); - return false; + return IE_NO_ERROR; } @@ -323,7 +325,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC LG ********************/ -bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +uint8_t IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) { uint32_t LG_Code; uint8_t data[HVAC_LG_DATALEN]; @@ -356,7 +358,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } mode = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 switch (mode) { @@ -400,7 +402,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } mode = p - kFanSpeedOptions; if ((mode == 0) || (mode > 3)) { @@ -431,7 +433,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, irsend->sendLG(LG_Code, 28); // interrupts(); - return false; + return IE_NO_ERROR; } @@ -439,7 +441,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, Fujitsu ********************/ -bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +uint8_t IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) { const char kFujitsuHvacModeOptions[] = "HDCAF"; @@ -452,7 +454,7 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po if (0 == HVAC_Power) { ac.off(); ac.send(); - return false; + return IE_NO_ERROR; } uint8_t modes[5] = {FUJITSU_AC_MODE_HEAT, FUJITSU_AC_MODE_DRY, FUJITSU_AC_MODE_COOL, FUJITSU_AC_MODE_AUTO, FUJITSU_AC_MODE_FAN}; @@ -468,7 +470,7 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po p = strchr(kFujitsuHvacModeOptions, toupper(HVAC_Mode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } ac.setMode(modes[p - kFujitsuHvacModeOptions]); @@ -479,14 +481,14 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } ac.setFanSpeed(fanModes[p - kFanSpeedOptions]); ac.setTemp(HVAC_Temp); ac.send(); - return false; + return IE_NO_ERROR; } #endif // USE_IR_HVAC @@ -507,7 +509,7 @@ bool IrSendCommand(void) { char command [CMDSZ]; bool serviced = true; - bool error = false; + uint8_t error = IE_NO_ERROR; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kIrRemoteCommands); if (-1 == command_code) { @@ -521,86 +523,87 @@ bool IrSendCommand(void) // IRSend frequency, rawdata, rawdata ... char *p; char *str = strtok_r(XdrvMailbox.data, ", ", &p); - uint16_t freq = atoi(str); - if (!freq) { freq = 38000; } // Default to 38kHz - uint16_t count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - if (count) { // At least two raw data values - count++; - uint16_t raw_array[count]; // It's safe to use stack for up to 240 packets (limited by mqtt_data length) - uint8_t i = 0; - for (str = strtok_r(nullptr, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p)) { - raw_array[i++] = strtoul(str, nullptr, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input - } + if (p == nullptr) { + error = IE_INVALID_RAWDATA; + } else { + uint16_t freq = atoi(str); + if (!freq) { freq = 38000; } // Default to 38kHz + uint16_t count = 0; + char *q = p; + for (; *q; count += (*q++ == ',')); + if (0 == count) { + error = IE_INVALID_RAWDATA; + } else { // At least two raw data values + count++; + uint16_t raw_array[count]; // It's safe to use stack for up to 240 packets (limited by mqtt_data length) + uint8_t i = 0; + for (str = strtok_r(nullptr, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p)) { + raw_array[i++] = strtoul(str, nullptr, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input + } -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), count, freq, raw_array[0], raw_array[count -1]); - - irsend_active = true; - irsend->sendRaw(raw_array, count, freq); - if (!count) { - Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_FAILED); - } - } - else { - Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_RAWDATA); - } - } - else { - char dataBufUc[XdrvMailbox.data_len]; - UpperCase(dataBufUc, XdrvMailbox.data); - StaticJsonBuffer<128> jsonBuf; - JsonObject &root = jsonBuf.parseObject(dataBufUc); - if (!root.success()) { - Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); - } - else { - // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } - char parm_uc[10]; - const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; - uint32_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; - uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); - if (protocol && bits) { - char protocol_text[20]; - int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"), - protocol_text, protocol, bits, data, data, protocol_code); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), count, freq, raw_array[0], raw_array[count -1]); irsend_active = true; - switch (protocol_code) { - case NEC: - irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits); break; - case SONY: - irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, 2); break; - case RC5: - irsend->sendRC5(data, bits); break; - case RC6: - irsend->sendRC6(data, bits); break; - case DISH: - irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits); break; - case JVC: - irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, 1); break; - case SAMSUNG: - irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits); break; - case PANASONIC: - irsend->sendPanasonic(bits, data); break; - default: - irsend_active = false; - Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED); + irsend->sendRaw(raw_array, count, freq); + if (!count) { + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_FAILED); } } - else { - error = true; + } + } else { + char dataBufUc[XdrvMailbox.data_len]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { + error = IE_INVALID_JSON; + } else { + StaticJsonBuffer<128> jsonBuf; + JsonObject &root = jsonBuf.parseObject(dataBufUc); + if (!root.success()) { + error = IE_INVALID_JSON; + } else { + // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } + char parm_uc[10]; + const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; + uint32_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; + uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); + if (protocol && bits) { + char protocol_text[20]; + int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"), + protocol_text, protocol, bits, data, data, protocol_code); + + irsend_active = true; + switch (protocol_code) { + case NEC: + irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits); break; + case SONY: + irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, 2); break; + case RC5: + irsend->sendRC5(data, bits); break; + case RC6: + irsend->sendRC6(data, bits); break; + case DISH: + irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits); break; + case JVC: + irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, 1); break; + case SAMSUNG: + irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits); break; + case PANASONIC: + irsend->sendPanasonic(bits, data); break; + default: + irsend_active = false; + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED); + } + } else { + error = IE_SYNTAX_IRSEND; + } } } } - } - else { - error = true; - } - if (error) { - Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); + } else { + error = IE_SYNTAX_IRSEND; } } #ifdef USE_IR_HVAC @@ -614,47 +617,65 @@ bool IrSendCommand(void) if (XdrvMailbox.data_len) { char dataBufUc[XdrvMailbox.data_len]; UpperCase(dataBufUc, XdrvMailbox.data); - StaticJsonBuffer<164> jsonBufer; - JsonObject &root = jsonBufer.parseObject(dataBufUc); - if (!root.success()) { - Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); - } - else { - Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - HVAC_Vendor = root[D_JSON_IRHVAC_VENDOR]; - HVAC_Power = root[D_JSON_IRHVAC_POWER]; - HVAC_Mode = root[D_JSON_IRHVAC_MODE]; - HVAC_FanMode = root[D_JSON_IRHVAC_FANSPEED]; - HVAC_Temp = root[D_JSON_IRHVAC_TEMP]; + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { + error = IE_INVALID_JSON; + } else { + StaticJsonBuffer<164> jsonBufer; + JsonObject &root = jsonBufer.parseObject(dataBufUc); + if (!root.success()) { + error = IE_INVALID_JSON; + } else { + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + HVAC_Vendor = root[D_JSON_IRHVAC_VENDOR]; + HVAC_Power = root[D_JSON_IRHVAC_POWER]; + HVAC_Mode = root[D_JSON_IRHVAC_MODE]; + HVAC_FanMode = root[D_JSON_IRHVAC_FANSPEED]; + HVAC_Temp = root[D_JSON_IRHVAC_TEMP]; -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Received Vendor %s, Power %d, Mode %s, FanSpeed %s, Temp %d"), HVAC_Vendor, HVAC_Power, HVAC_Mode, HVAC_FanMode, HVAC_Temp); + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Received Vendor %s, Power %d, Mode %s, FanSpeed %s, Temp %d"), HVAC_Vendor, HVAC_Power, HVAC_Mode, HVAC_FanMode, HVAC_Temp); - char vendor[20]; - int vendor_code = GetCommandCode(vendor, sizeof(vendor), HVAC_Vendor, kIrHvacVendors); - switch (vendor_code) { - case VNDR_TOSHIBA: - error = IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; - case VNDR_MITSUBISHI: - error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; - case VNDR_LG: - error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; - case VNDR_FUJITSU: - error = IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; - default: - error = true; + char vendor[20]; + int vendor_code = GetCommandCode(vendor, sizeof(vendor), HVAC_Vendor, kIrHvacVendors); + switch (vendor_code) { + case VNDR_TOSHIBA: + error = IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; + case VNDR_MITSUBISHI: + error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; + case VNDR_LG: + error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; + case VNDR_FUJITSU: + error = IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; + default: + error = IE_SYNTAX_IRHVAC; + } } } } else { - error = true; - } - if (error) { - Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); + error = IE_SYNTAX_IRHVAC; } } #endif // USE_IR_HVAC else serviced = false; // Unknown command + switch (error) { + case IE_INVALID_RAWDATA: + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_RAWDATA); + break; + case IE_INVALID_JSON: + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); + break; + case IE_SYNTAX_IRSEND: + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); + break; +#ifdef USE_IR_HVAC + case IE_SYNTAX_IRHVAC: + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); + break; +#endif // USE_IR_HVAC + } + return serviced; } From b7adb109238939f9ab11770fb71bcec54830f692 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 31 Mar 2019 17:51:05 +0200 Subject: [PATCH 1207/2222] Test for easier MQTT reconnects Test for easier MQTT reconnects --- sonoff/support.ino | 13 +++++++++++-- sonoff/xdrv_01_webserver.ino | 12 +----------- sonoff/xdrv_02_mqtt.ino | 14 +++++++++++++- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index e571e6ec1..d101185a6 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -370,6 +370,14 @@ uint8_t Shortcut(const char* str) return result; } +bool ValidIpAddress(const char* str) +{ + const char* p = str; + + while (*p && ( (*p == '.') || (*p >= '0') || (*p <= '9') )) { p++; } + return (*p == '\0'); +} + bool ParseIp(uint32_t* addr, const char* str) { uint8_t *part = (uint8_t*)addr; @@ -1247,8 +1255,9 @@ void Syslog(void) // Destroys log_data char syslog_preamble[64]; // Hostname + Id - if (syslog_host_hash != GetHash(Settings.syslog_host, strlen(Settings.syslog_host))) { - syslog_host_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); + uint32_t current_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); + if (syslog_host_hash != current_hash) { + syslog_host_hash = current_hash; WiFi.hostByName(Settings.syslog_host, syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash } if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 44be997a6..76cdae534 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2148,7 +2148,7 @@ void HandleNotFound(void) /* 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. */ bool CaptivePortal(void) { - if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader())) { + if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader().c_str())) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); WebServer->sendHeader(F("Location"), String("http://") + WebServer->client().localIP().toString(), true); @@ -2159,16 +2159,6 @@ bool CaptivePortal(void) return false; } -/** Is this an IP? */ -bool ValidIpAddress(String str) -{ - for (uint16_t i = 0; i < str.length(); i++) { - int c = str.charAt(i); - if (c != '.' && (c < '0' || c > '9')) { return false; } - } - return true; -} - /*********************************************************************************************/ String UrlEncode(const String& text) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 5720b9a7d..f001b39d5 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -37,6 +37,9 @@ const char kMqttCommands[] PROGMEM = D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|" D_CMND_BUTTONTOPIC "|" D_CMND_SWITCHTOPIC "|" D_CMND_BUTTONRETAIN "|" D_CMND_SWITCHRETAIN "|" D_CMND_POWERRETAIN "|" D_CMND_SENSORRETAIN ; +IPAddress mqtt_host_addr; // MQTT host IP address +uint32_t mqtt_host_hash = 0; // MQTT host name hash + uint16_t mqtt_connect_count = 0; // MQTT re-connect count uint16_t mqtt_retry_counter = 1; // MQTT connection retry counter uint8_t mqtt_initial_connection_state = 2; // MQTT connection messages state @@ -448,7 +451,16 @@ void MqttReconnect(void) } MqttClient.setCallback(MqttDataHandler); - MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); +// MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); + + // Skip MQTT host DNS lookup if not needed + uint32_t current_hash = GetHash(Settings.mqtt_host, strlen(Settings.mqtt_host)); + if (mqtt_host_hash != current_hash) { + mqtt_host_hash = current_hash; + WiFi.hostByName(Settings.mqtt_host, mqtt_host_addr); // Skips DNS lookup if mqtt_host is IP address string as from mDns + } + MqttClient.setServer(mqtt_host_addr, Settings.mqtt_port); + if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data)) { MqttConnected(); } else { From 8d8e06055086f632365bcdd64f4e255768cbd699 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 31 Mar 2019 17:55:58 +0200 Subject: [PATCH 1208/2222] Revert "Test for easier MQTT reconnects" This reverts commit b7adb109238939f9ab11770fb71bcec54830f692. --- sonoff/support.ino | 13 ++----------- sonoff/xdrv_01_webserver.ino | 12 +++++++++++- sonoff/xdrv_02_mqtt.ino | 14 +------------- 3 files changed, 14 insertions(+), 25 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index d101185a6..e571e6ec1 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -370,14 +370,6 @@ uint8_t Shortcut(const char* str) return result; } -bool ValidIpAddress(const char* str) -{ - const char* p = str; - - while (*p && ( (*p == '.') || (*p >= '0') || (*p <= '9') )) { p++; } - return (*p == '\0'); -} - bool ParseIp(uint32_t* addr, const char* str) { uint8_t *part = (uint8_t*)addr; @@ -1255,9 +1247,8 @@ void Syslog(void) // Destroys log_data char syslog_preamble[64]; // Hostname + Id - uint32_t current_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); - if (syslog_host_hash != current_hash) { - syslog_host_hash = current_hash; + if (syslog_host_hash != GetHash(Settings.syslog_host, strlen(Settings.syslog_host))) { + syslog_host_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); WiFi.hostByName(Settings.syslog_host, syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash } if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 76cdae534..44be997a6 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2148,7 +2148,7 @@ void HandleNotFound(void) /* 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. */ bool CaptivePortal(void) { - if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader().c_str())) { + if ((WifiIsInManagerMode()) && !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); @@ -2159,6 +2159,16 @@ bool CaptivePortal(void) return false; } +/** Is this an IP? */ +bool ValidIpAddress(String str) +{ + for (uint16_t i = 0; i < str.length(); i++) { + int c = str.charAt(i); + if (c != '.' && (c < '0' || c > '9')) { return false; } + } + return true; +} + /*********************************************************************************************/ String UrlEncode(const String& text) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index f001b39d5..5720b9a7d 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -37,9 +37,6 @@ const char kMqttCommands[] PROGMEM = D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|" D_CMND_BUTTONTOPIC "|" D_CMND_SWITCHTOPIC "|" D_CMND_BUTTONRETAIN "|" D_CMND_SWITCHRETAIN "|" D_CMND_POWERRETAIN "|" D_CMND_SENSORRETAIN ; -IPAddress mqtt_host_addr; // MQTT host IP address -uint32_t mqtt_host_hash = 0; // MQTT host name hash - uint16_t mqtt_connect_count = 0; // MQTT re-connect count uint16_t mqtt_retry_counter = 1; // MQTT connection retry counter uint8_t mqtt_initial_connection_state = 2; // MQTT connection messages state @@ -451,16 +448,7 @@ void MqttReconnect(void) } MqttClient.setCallback(MqttDataHandler); -// MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); - - // Skip MQTT host DNS lookup if not needed - uint32_t current_hash = GetHash(Settings.mqtt_host, strlen(Settings.mqtt_host)); - if (mqtt_host_hash != current_hash) { - mqtt_host_hash = current_hash; - WiFi.hostByName(Settings.mqtt_host, mqtt_host_addr); // Skips DNS lookup if mqtt_host is IP address string as from mDns - } - MqttClient.setServer(mqtt_host_addr, Settings.mqtt_port); - + MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data)) { MqttConnected(); } else { From 880bbe357d5c232de81a5cd7db288c26151fc9ef Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 31 Mar 2019 17:57:28 +0200 Subject: [PATCH 1209/2222] Change String to char Change String to char --- sonoff/support.ino | 13 +++++++++++-- sonoff/xdrv_01_webserver.ino | 12 +----------- sonoff/xdrv_02_mqtt.ino | 12 ++++++++++++ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index e571e6ec1..d101185a6 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -370,6 +370,14 @@ uint8_t Shortcut(const char* str) return result; } +bool ValidIpAddress(const char* str) +{ + const char* p = str; + + while (*p && ( (*p == '.') || (*p >= '0') || (*p <= '9') )) { p++; } + return (*p == '\0'); +} + bool ParseIp(uint32_t* addr, const char* str) { uint8_t *part = (uint8_t*)addr; @@ -1247,8 +1255,9 @@ void Syslog(void) // Destroys log_data char syslog_preamble[64]; // Hostname + Id - if (syslog_host_hash != GetHash(Settings.syslog_host, strlen(Settings.syslog_host))) { - syslog_host_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); + uint32_t current_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); + if (syslog_host_hash != current_hash) { + syslog_host_hash = current_hash; WiFi.hostByName(Settings.syslog_host, syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash } if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 44be997a6..76cdae534 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2148,7 +2148,7 @@ void HandleNotFound(void) /* 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. */ bool CaptivePortal(void) { - if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader())) { + if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader().c_str())) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); WebServer->sendHeader(F("Location"), String("http://") + WebServer->client().localIP().toString(), true); @@ -2159,16 +2159,6 @@ bool CaptivePortal(void) return false; } -/** Is this an IP? */ -bool ValidIpAddress(String str) -{ - for (uint16_t i = 0; i < str.length(); i++) { - int c = str.charAt(i); - if (c != '.' && (c < '0' || c > '9')) { return false; } - } - return true; -} - /*********************************************************************************************/ String UrlEncode(const String& text) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 5720b9a7d..b7daa1f34 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -37,6 +37,9 @@ const char kMqttCommands[] PROGMEM = D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|" D_CMND_BUTTONTOPIC "|" D_CMND_SWITCHTOPIC "|" D_CMND_BUTTONRETAIN "|" D_CMND_SWITCHRETAIN "|" D_CMND_POWERRETAIN "|" D_CMND_SENSORRETAIN ; +IPAddress mqtt_host_addr; // MQTT host IP address +uint32_t mqtt_host_hash = 0; // MQTT host name hash + uint16_t mqtt_connect_count = 0; // MQTT re-connect count uint16_t mqtt_retry_counter = 1; // MQTT connection retry counter uint8_t mqtt_initial_connection_state = 2; // MQTT connection messages state @@ -449,6 +452,15 @@ void MqttReconnect(void) MqttClient.setCallback(MqttDataHandler); MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); +/* + // Skip MQTT host DNS lookup if not needed + uint32_t current_hash = GetHash(Settings.mqtt_host, strlen(Settings.mqtt_host)); + if (mqtt_host_hash != current_hash) { + mqtt_host_hash = current_hash; + WiFi.hostByName(Settings.mqtt_host, mqtt_host_addr); // Skips DNS lookup if mqtt_host is IP address string as from mDns + } + MqttClient.setServer(mqtt_host_addr, Settings.mqtt_port); +*/ if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data)) { MqttConnected(); } else { From 127892e0c186bef0678b1683fff913918116ced5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 1 Apr 2019 15:15:16 +0200 Subject: [PATCH 1210/2222] Change IRsend and receive for 64-bit support * Change IRsend and receive for 64-bit support (#5523) * Change IRSend Panasonic protocol to 64-bit (#5523) --- sonoff/_changelog.ino | 2 ++ sonoff/support.ino | 22 +++++++++++++++++ sonoff/xdrv_05_irremote.ino | 49 ++++++++++++++++++++++++++----------- 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 6f40ca4ae..7ffe22789 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,8 @@ /* 6.5.0.3 20190328 * Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452) * Change some defines to const + * Change IRsend and receive for 64-bit support (#5523) + * Change IRSend Panasonic protocol to 64-bit (#5523) * * 6.5.0.2 20190325 * Change UDP initial message handling from string to char using static memory and add debug info (#5505) diff --git a/sonoff/support.ino b/sonoff/support.ino index d101185a6..cffcb4690 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -200,6 +200,28 @@ int TextToInt(char *str) return strtol(str, &p, radix); } +char* ulltoa(unsigned long long value, char *str, int radix) +{ + char digits[64]; + char *dst = str; + int i = 0; + int n = 0; + +/* + if (radix < 2 || radix > 36) { radix = 10; } +*/ + do { + n = value % radix; + digits[i++] = (n < 10) ? (char)n+'0' : (char)n-10+'A'; + value /= radix; + } while (value != 0); + + while (i > 0) { *dst++ = digits[--i]; } + + *dst = 0; + return str; +} + char* dtostrfd(double number, unsigned char prec, char *s) { if ((isnan(number)) || (isinf(number))) { // Fix for JSON output (https://stackoverflow.com/questions/1423081/json-left-out-infinity-and-nan-json-status-in-ecmascript) diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index d62be8ee3..9bddc3617 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -105,18 +105,37 @@ void IrReceiveInit(void) // AddLog_P(LOG_LEVEL_DEBUG, PSTR("IrReceive initialized")); } +char* IrUint64toHex(uint64_t value, char *str, uint16_t bits) +{ + ulltoa(value, str, 16); // Get 64bit value + + int fill = 8; + if ((bits > 3) && (bits < 65)) { fill = bits / 4 ; } // Max 16 + int len = strlen(str); + fill -= len; + if (fill > 0) { + memmove(str + fill, str, len +1); + memset(str, '0', fill); + } + memmove(str + 2, str, strlen(str) +1); + str[0] = '0'; + str[1] = 'x'; + return str; +} + void IrReceiveCheck(void) { char sirtype[14]; // Max is AIWA_RC_T501 - char stemp[16]; int8_t iridx = 0; decode_results results; if (irrecv->decode(&results)) { + char hvalue[64]; + IrUint64toHex(results.value, hvalue, results.bits); // Get 64bit value as hex 0x00123456 - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value 0x%08X, Decode %d"), - irsend_active, results.rawlen, results.overflow, results.bits, results.value, results.decode_type); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value %s, Decode %d"), + irsend_active, results.rawlen, results.overflow, results.bits, hvalue, results.decode_type); unsigned long now = millis(); // if ((now - ir_lasttime > IR_TIME_AVOID_DUPLICATE) && (UNKNOWN != results.decode_type) && (results.bits > 0)) { @@ -124,16 +143,15 @@ void IrReceiveCheck(void) ir_lasttime = now; iridx = results.decode_type; - if ((iridx < 0) || (iridx > 14)) { - iridx = 0; // UNKNOWN - } + if ((iridx < 0) || (iridx > 14)) { iridx = 0; } // UNKNOWN + char svalue[64]; if (Settings.flag.ir_receive_decimal) { - snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)results.value); + ulltoa(results.value, svalue, 10); } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)results.value); + snprintf_P(svalue, sizeof(svalue), PSTR("\"%s\""), hvalue); } Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s"), - GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, stemp); + GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, svalue); if (Settings.flag3.receive_raw) { ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); @@ -565,14 +583,16 @@ bool IrSendCommand(void) // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } char parm_uc[10]; const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; - uint32_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; - uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); + uint16_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; + uint64_t data = strtoull(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); if (protocol && bits) { char protocol_text[20]; int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"), - protocol_text, protocol, bits, data, data, protocol_code); + char dvalue[64]; + char hvalue[64]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %s (%s), protocol_code %d"), + protocol_text, protocol, bits, ulltoa(data, dvalue, 10), IrUint64toHex(data, hvalue, bits), protocol_code); irsend_active = true; switch (protocol_code) { @@ -591,7 +611,8 @@ bool IrSendCommand(void) case SAMSUNG: irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits); break; case PANASONIC: - irsend->sendPanasonic(bits, data); break; +// irsend->sendPanasonic(bits, data); break; + irsend->sendPanasonic64(data, bits); break; default: irsend_active = false; Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED); From a380eb956643c3202a34a7e1923589c6033b3969 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 1 Apr 2019 16:39:13 +0200 Subject: [PATCH 1211/2222] Fix possible compile error Fix possible compile error --- sonoff/xdrv_05_irremote.ino | 39 ++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 9bddc3617..8b6a0de1c 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -81,6 +81,27 @@ void IrSendInit(void) #endif //USE_IR_HVAC } +char* IrUint64toHex(uint64_t value, char *str, uint16_t bits) +{ + ulltoa(value, str, 16); // Get 64bit value + + int fill = 8; + if ((bits > 3) && (bits < 65)) { + fill = bits / 4; // Max 16 + if (bits % 4) { fill++; } + } + int len = strlen(str); + fill -= len; + if (fill > 0) { + memmove(str + fill, str, len +1); + memset(str, '0', fill); + } + memmove(str + 2, str, strlen(str) +1); + str[0] = '0'; + str[1] = 'x'; + return str; +} + #ifdef USE_IR_RECEIVE /*********************************************************************************************\ * IR Receive @@ -105,24 +126,6 @@ void IrReceiveInit(void) // AddLog_P(LOG_LEVEL_DEBUG, PSTR("IrReceive initialized")); } -char* IrUint64toHex(uint64_t value, char *str, uint16_t bits) -{ - ulltoa(value, str, 16); // Get 64bit value - - int fill = 8; - if ((bits > 3) && (bits < 65)) { fill = bits / 4 ; } // Max 16 - int len = strlen(str); - fill -= len; - if (fill > 0) { - memmove(str + fill, str, len +1); - memset(str, '0', fill); - } - memmove(str + 2, str, strlen(str) +1); - str[0] = '0'; - str[1] = 'x'; - return str; -} - void IrReceiveCheck(void) { char sirtype[14]; // Max is AIWA_RC_T501 From 7f590e62f3e5fbec230091239040e74113e70fa1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 1 Apr 2019 17:41:47 +0200 Subject: [PATCH 1212/2222] Change Spanish Argentina to Spanish Spain (#5565) Change Spanish Argentina to Spanish Spain (#5565) --- platformio.ini | 2 +- sonoff/language/{es-AR.h => es-ES.h} | 10 +++++----- sonoff/my_user_config.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) rename sonoff/language/{es-AR.h => es-ES.h} (99%) diff --git a/platformio.ini b/platformio.ini index 8fffc69d3..9ca59d3e8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -347,7 +347,7 @@ board = ${common.board} board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_cpu = ${common.board_build.f_cpu} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=es-AR +build_flags = ${common.build_flags} -DMY_LANGUAGE=es-ES monitor_speed = ${common.monitor_speed} upload_port = ${common.upload_port} upload_resetmethod = ${common.upload_resetmethod} diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-ES.h similarity index 99% rename from sonoff/language/es-AR.h rename to sonoff/language/es-ES.h index 9aca4f417..426d829bd 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-ES.h @@ -1,5 +1,5 @@ /* - es-AR.h - localization for Spanish - Argentina for Sonoff-Tasmota + es-ES.h - localization for Spanish - Spain for Sonoff-Tasmota Copyright (C) 2019 Adrian Scillato @@ -17,8 +17,8 @@ along with this program. If not, see . */ -#ifndef _LANGUAGE_ES_AR_H_ -#define _LANGUAGE_ES_AR_H_ +#ifndef _LANGUAGE_ES_ES_H_ +#define _LANGUAGE_ES_ES_H_ /*************************** ATTENTION *******************************\ * @@ -33,7 +33,7 @@ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) -#define LANGUAGE_LCID 11274 +#define LANGUAGE_LCID 1034 // HTML (ISO 639-1) Language Code #define D_HTML_LANGUAGE "es" @@ -653,4 +653,4 @@ #define D_UNIT_KWARH "kVArH" #define D_UNIT_ANGLE "Grados" -#endif // _LANGUAGE_ES_AR_H_ +#endif // _LANGUAGE_ES_ES_H_ diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 29eb632a6..5ba994a4b 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -204,7 +204,7 @@ //#define MY_LANGUAGE de-DE // German in Germany //#define MY_LANGUAGE el-GR // Greek in Greece //#define MY_LANGUAGE en-GB // English in Great Britain. Enabled by Default -//#define MY_LANGUAGE es-AR // Spanish in Argentina +//#define MY_LANGUAGE es-ES // Spanish in Spain //#define MY_LANGUAGE fr-FR // French in France //#define MY_LANGUAGE he-HE // Hebrew in Israel //#define MY_LANGUAGE hu-HU // Hungarian in Hungary From 7c31bedc9b2ea039119e0ee5bba10fe995d46d0a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Apr 2019 10:35:19 +0200 Subject: [PATCH 1213/2222] Fix Configure Timer Gui webinterface (#5568) Fix Configure Timer Gui webinterface (#5568) --- sonoff/xdrv_09_timers.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 05e931254..2f11421dc 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -620,7 +620,7 @@ const char HTTP_TIMER_SCRIPT5[] PROGMEM = "function it(){" // Initialize elements and select first tab "var b,i,o,s;" "pt=eb('t0').value.split(',').map(Number);" // Get parameters from hidden area to array - "s='';for(i=0;i<" STR(MAX_TIMERS) ";i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" + "s='';for(i=0;i<%d;i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" "eb('bt').innerHTML=s;" // Create tabs "if(%d>0){" // Create Output and Action drop down boxes "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" @@ -705,7 +705,7 @@ void HandleTimerConfiguration(void) #endif // USE_SUNRISE WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT4, devices_present); - WSContentSend_P(HTTP_TIMER_SCRIPT5, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT5, MAX_TIMERS, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present); WSContentSendStyle_P(HTTP_TIMER_STYLE); WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); From c58b40e838ed5d52488f7c3e23180c87f7d95c1e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Apr 2019 11:07:30 +0200 Subject: [PATCH 1214/2222] Revert "Fix Configure Timer Gui webinterface (#5568)" This reverts commit 7c31bedc9b2ea039119e0ee5bba10fe995d46d0a. --- sonoff/xdrv_09_timers.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 2f11421dc..05e931254 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -620,7 +620,7 @@ const char HTTP_TIMER_SCRIPT5[] PROGMEM = "function it(){" // Initialize elements and select first tab "var b,i,o,s;" "pt=eb('t0').value.split(',').map(Number);" // Get parameters from hidden area to array - "s='';for(i=0;i<%d;i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" + "s='';for(i=0;i<" STR(MAX_TIMERS) ";i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" "eb('bt').innerHTML=s;" // Create tabs "if(%d>0){" // Create Output and Action drop down boxes "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" @@ -705,7 +705,7 @@ void HandleTimerConfiguration(void) #endif // USE_SUNRISE WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT4, devices_present); - WSContentSend_P(HTTP_TIMER_SCRIPT5, MAX_TIMERS, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT5, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present); WSContentSendStyle_P(HTTP_TIMER_STYLE); WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); From 76eec9b8ab7e06b7809ec853db31d064c99f6947 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Apr 2019 11:26:55 +0200 Subject: [PATCH 1215/2222] Fix Configure Timer Gui webinterface (#5568) Fix Configure Timer Gui webinterface (#5568) --- sonoff/xdrv_09_timers.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 05e931254..e9f7e6c53 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -620,7 +620,7 @@ const char HTTP_TIMER_SCRIPT5[] PROGMEM = "function it(){" // Initialize elements and select first tab "var b,i,o,s;" "pt=eb('t0').value.split(',').map(Number);" // Get parameters from hidden area to array - "s='';for(i=0;i<" STR(MAX_TIMERS) ";i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" + "s='';for(i=0;i<16;i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" "eb('bt').innerHTML=s;" // Create tabs "if(%d>0){" // Create Output and Action drop down boxes "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" From 8ff2759cccabc0215e0b20abc63ac83798123f0c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Apr 2019 15:47:39 +0200 Subject: [PATCH 1216/2222] 6.5.0.4 Fix Configure Timer Web GUI 6.5.0.4 20190402 * Fix Configure Timer Web GUI (#5568) * Add validation check when loading settings from flash --- sonoff/_changelog.ino | 6 +++++- sonoff/settings.h | 8 ++++---- sonoff/settings.ino | 8 ++++++-- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_09_timers.ino | 9 +++++++-- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 7ffe22789..abbbc40ae 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ -/* 6.5.0.3 20190328 +/* 6.5.0.4 20190402 + * Fix Configure Timer Web GUI (#5568) + * Add validation check when loading settings from flash + * + * 6.5.0.3 20190328 * Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452) * Change some defines to const * Change IRsend and receive for 64-bit support (#5523) diff --git a/sonoff/settings.h b/sonoff/settings.h index 07cb646d8..329b152f4 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -185,12 +185,12 @@ struct SYSCFG { unsigned long bootcount; // 00C */ struct SYSCFG { - uint16_t cfg_holder; // 000 v6 header - uint16_t cfg_size; // 002 + uint16_t cfg_holder; // 000 v6 header + uint16_t cfg_size; // 002 unsigned long save_flag; // 004 unsigned long version; // 008 - uint16_t bootcount; // 00C - uint16_t cfg_crc; // 00E + uint16_t bootcount; // 00C + uint16_t cfg_crc; // 00E SysBitfield flag; // 010 int16_t save_data; // 014 int8_t timezone; // 016 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index dcebe4512..70ab8afc9 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -460,13 +460,17 @@ void SettingsLoad(void) settings_location = 0; uint32_t flash_location = SETTINGS_LOCATION +1; + uint16_t cfg_holder = 0; for (uint8_t i = 0; i < CFG_ROTATES; i++) { flash_location--; ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); bool valid = false; if (Settings.version > 0x06000000) { - valid = (Settings.cfg_crc == GetSettingsCrc()); + bool almost_valid = (Settings.cfg_crc == GetSettingsCrc()); + // Sometimes CRC on pages below FB, overwritten by OTA, is fine but Settings are still invalid. So check cfg_holder too + if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } // At FB always active cfg_holder + valid = (cfg_holder == Settings.cfg_holder); } else { ESP.flashRead((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); valid = (Settings.cfg_holder == _SettingsH.cfg_holder); @@ -485,7 +489,7 @@ void SettingsLoad(void) } if (settings_location > 0) { ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %d"), settings_location, Settings.save_flag); + AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); } #ifndef FIRMWARE_MINIMAL diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 68c28a9d0..3a8dc0eb8 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06050003; +const uint32_t VERSION = 0x06050004; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index e9f7e6c53..36941b9f1 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -620,7 +620,12 @@ const char HTTP_TIMER_SCRIPT5[] PROGMEM = "function it(){" // Initialize elements and select first tab "var b,i,o,s;" "pt=eb('t0').value.split(',').map(Number);" // Get parameters from hidden area to array - "s='';for(i=0;i<16;i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" + "s='';" + "for(i=0;i<%d;i++){" + "b='';" + "if(0==i){b=\" id='dP'\";}" + "s+=\"\"" + "}" "eb('bt').innerHTML=s;" // Create tabs "if(%d>0){" // Create Output and Action drop down boxes "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" @@ -705,7 +710,7 @@ void HandleTimerConfiguration(void) #endif // USE_SUNRISE WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT4, devices_present); - WSContentSend_P(HTTP_TIMER_SCRIPT5, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT5, MAX_TIMERS, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present); WSContentSendStyle_P(HTTP_TIMER_STYLE); WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); From 2fd15c463370a68612aaf8c9b2e56689365bb209 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Apr 2019 20:26:30 +0200 Subject: [PATCH 1217/2222] Fix WifiManager Pop Up when no SSID is configured (#5575) Fix WifiManager Pop Up when no SSID is configured (#5575) --- sonoff/support.ino | 7 +++---- sonoff/xdrv_01_webserver.ino | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index cffcb4690..f060a551b 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -207,9 +207,8 @@ char* ulltoa(unsigned long long value, char *str, int radix) int i = 0; int n = 0; -/* - if (radix < 2 || radix > 36) { radix = 10; } -*/ +// if (radix < 2 || radix > 36) { radix = 10; } + do { n = value % radix; digits[i++] = (n < 10) ? (char)n+'0' : (char)n-10+'A'; @@ -396,7 +395,7 @@ bool ValidIpAddress(const char* str) { const char* p = str; - while (*p && ( (*p == '.') || (*p >= '0') || (*p <= '9') )) { p++; } + while (*p && ((*p == '.') || ((*p >= '0') && (*p <= '9')))) { p++; } return (*p == '\0'); } diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 76cdae534..771a010b1 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2148,6 +2148,7 @@ void HandleNotFound(void) /* 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. */ bool CaptivePortal(void) { + // Possible hostHeader: connectivitycheck.gstatic.com or 192.168.4.1 if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader().c_str())) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); From 531c4fe44e5d3f0ea6b1acb9012cfabefc461e08 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Apr 2019 20:53:17 +0200 Subject: [PATCH 1218/2222] Disable unused code Disable unused code --- sonoff/settings.ino | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 70ab8afc9..1dd8f02b0 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -176,8 +176,10 @@ const uint32_t SETTINGS_LOCATION = SPIFFS_END; // No need for SPIFFS as it uses const uint8_t CFG_ROTATES = 8; // Number of flash sectors used (handles uploads) /*********************************************************************************************\ - * EEPROM support based on EEPROM library and tuned for Tasmota + * Optional EEPROM support based on EEPROM library and tuned for Tasmota \*********************************************************************************************/ +//#define USE_EEPROM +#ifdef USE_EEPROM uint32_t eeprom_sector = SPIFFS_END; uint8_t* eeprom_data = 0; @@ -305,7 +307,7 @@ void EepromEnd(void) eeprom_size = 0; eeprom_dirty = false; } - +#endif // USE_EEPROM /********************************************************************************************/ uint16_t settings_crc = 0; @@ -372,7 +374,9 @@ void SettingsSaveAll(void) Settings.power = 0; } XsnsCall(FUNC_SAVE_BEFORE_RESTART); +#ifdef USE_EEPROM EepromCommit(); +#endif SettingsSave(0); } @@ -415,6 +419,7 @@ void SettingsSave(uint8_t rotate) Settings.cfg_size = sizeof(SYSCFG); Settings.cfg_crc = GetSettingsCrc(); +#ifdef USE_EEPROM if (SPIFFS_END == settings_location) { uint8_t* flash_buffer; flash_buffer = new uint8_t[SPI_FLASH_SEC_SIZE]; @@ -432,6 +437,10 @@ void SettingsSave(uint8_t rotate) ESP.flashEraseSector(settings_location); ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); } +#else + ESP.flashEraseSector(settings_location); + ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); +#endif // USE_EEPROM if (!stop_flash_rotate && rotate) { for (uint8_t i = 1; i < CFG_ROTATES; i++) { From 43bc2a31a37c8d649f42c3bc5509eb909c116be2 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 2 Apr 2019 21:41:52 -0300 Subject: [PATCH 1219/2222] Fixed Display Bug in KNX webmenu for Phys Address --- sonoff/xdrv_11_knx.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index c4111bae3..ee7e8b291 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -880,6 +880,7 @@ void HandleKNXConfiguration(void) "}" "}")); WSContentSendStyle(); + KNX_physs_addr.value = Settings.knx_physsical_addr; WSContentSend_P(HTTP_FORM_KNX, KNX_physs_addr.pa.area, KNX_physs_addr.pa.line, KNX_physs_addr.pa.member); if ( Settings.flag.knx_enabled ) { WSContentSend_P(PSTR(" checked")); } WSContentSend_P(HTTP_FORM_KNX1); From bf33e8fcd7f4ac3325f5c5c0796d8fe65dc3a835 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 2 Apr 2019 21:44:01 -0300 Subject: [PATCH 1220/2222] Update _changelog.ino --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index abbbc40ae..e21c7409a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.5.0.4 20190402 * Fix Configure Timer Web GUI (#5568) * Add validation check when loading settings from flash + * Fixed Display Bug in KNX webmenu for Physical Address * * 6.5.0.3 20190328 * Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452) From 2c286c43f13ce1a531f6cfed75c1566257fb952c Mon Sep 17 00:00:00 2001 From: Yury Sannikov Date: Tue, 2 Apr 2019 21:16:50 -0400 Subject: [PATCH 1221/2222] Fix Sensor15 command crash due to the wrong memory specifier --- sonoff/xsns_15_mhz19.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 00f272a55..5978ba058 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -71,8 +71,8 @@ TasmotaSerial *MhzSerial; const char kMhzModels[] PROGMEM = "|B"; -const char ABC_ENABLED[] PROGMEM = "ABC is Enabled"; -const char ABC_DISABLED[] PROGMEM = "ABC is Enabled"; +const char ABC_ENABLED[] = "ABC is Enabled"; +const char ABC_DISABLED[] = "ABC is Disabled"; enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; const uint8_t kMhzCommands[][4] PROGMEM = { From f455b738a5124b17883d74d11a8aefb29616a831 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 3 Apr 2019 10:28:13 +0200 Subject: [PATCH 1222/2222] QFix for core 2.3.0 compile error on strtoull QFix for core 2.3.0 compile error on strtoull --- sonoff/support.ino | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/sonoff/support.ino b/sonoff/support.ino index f060a551b..388ebacfc 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -123,6 +123,89 @@ size_t strcspn(const char *str1, const char *str2) } return ret; } + +/* + * Convert a string to an unsigned long long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + * https://opensource.apple.com/source/Libc/Libc-583/stdlib/FreeBSD/strtoull.c + */ + +#ifndef __LONG_LONG_MAX__ +#define __LONG_LONG_MAX__ 9223372036854775807LL +#endif +#undef ULLONG_MAX +#define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1) + +unsigned long long strtoull(const char *__restrict nptr, char **__restrict endptr, int base) +{ + const char *s; + unsigned long long acc; + char c; + unsigned long long cutoff; + int neg, any, cutlim; + + /* + * See strtoq for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + if (base < 2 || base > 36) + goto noconv; + + cutoff = ULLONG_MAX / base; + cutlim = ULLONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULLONG_MAX; + } else if (!any) { +noconv: + uint8_t dummy = 0; + } else if (neg) + acc = -acc; + if (endptr != nullptr) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} + #endif // ARDUINO_ESP8266_RELEASE_2_3_0 // Get span until single character in string From ce4e9b0e30101b5d571772e1b7ef97d0c7023eaf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 4 Apr 2019 17:52:14 +0200 Subject: [PATCH 1223/2222] Add stable strtoull to core 2.3.0 Add stable strtoull to core 2.3.0 --- sonoff/support.ino | 134 +++++++++++++++++++++------------------------ 1 file changed, 61 insertions(+), 73 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 388ebacfc..1a222686c 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -108,7 +108,7 @@ void* memchr(const void* ptr, int value, size_t num) return 0; } -// http://clc-wiki.net/wiki/C_standard_library:string.h:strspn +// http://clc-wiki.net/wiki/C_standard_library:string.h:strcspn // Get span until any character in string size_t strcspn(const char *str1, const char *str2) { @@ -124,88 +124,76 @@ size_t strcspn(const char *str1, const char *str2) return ret; } -/* - * Convert a string to an unsigned long long integer. - * - * Assumes that the upper and lower case - * alphabets and digits are each contiguous. - * https://opensource.apple.com/source/Libc/Libc-583/stdlib/FreeBSD/strtoull.c - */ - +// https://opensource.apple.com/source/Libc/Libc-583/stdlib/FreeBSD/strtoull.c +// Convert a string to an unsigned long long integer #ifndef __LONG_LONG_MAX__ #define __LONG_LONG_MAX__ 9223372036854775807LL #endif -#undef ULLONG_MAX +#ifndef ULLONG_MAX #define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1) +#endif unsigned long long strtoull(const char *__restrict nptr, char **__restrict endptr, int base) { - const char *s; - unsigned long long acc; - char c; - unsigned long long cutoff; - int neg, any, cutlim; + const char *s = nptr; + char c; + do { c = *s++; } while (isspace((unsigned char)c)); // Trim leading spaces - /* - * See strtoq for comments as to the logic used. - */ - s = nptr; - do { - c = *s++; - } while (isspace((unsigned char)c)); - if (c == '-') { - neg = 1; - c = *s++; - } else { - neg = 0; - if (c == '+') - c = *s++; - } - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - acc = any = 0; - if (base < 2 || base > 36) - goto noconv; + int neg = 0; + if (c == '-') { // Set minus flag and/or skip sign + neg = 1; + c = *s++; + } else { + if (c == '+') { + c = *s++; + } + } - cutoff = ULLONG_MAX / base; - cutlim = ULLONG_MAX % base; - for ( ; ; c = *s++) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'A' && c <= 'Z') - c -= 'A' - 10; - else if (c >= 'a' && c <= 'z') - c -= 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = ULLONG_MAX; - } else if (!any) { -noconv: - uint8_t dummy = 0; - } else if (neg) - acc = -acc; - if (endptr != nullptr) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); + if ((base == 0 || base == 16) && (c == '0') && (*s == 'x' || *s == 'X')) { // Set Hexadecimal + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) { base = (c == '0') ? 8 : 10; } // Set Octal or Decimal + + unsigned long long acc = 0; + int any = 0; + if (base > 1 && base < 37) { + unsigned long long cutoff = ULLONG_MAX / base; + int cutlim = ULLONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + + if (c >= base) + break; + + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULLONG_MAX; // Range error + } + else if (any && neg) { + acc = -acc; + } + } + + if (endptr != nullptr) { *endptr = (char *)(any ? s - 1 : nptr); } + + return acc; } - #endif // ARDUINO_ESP8266_RELEASE_2_3_0 // Get span until single character in string From 82ef09b684fd62935f8fba7e82280724e909e56e Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 5 Apr 2019 08:41:26 +0200 Subject: [PATCH 1224/2222] Make MI Desk Lamp default off Mi Desk Lamp can be activated in my_user_config.h by setting uncommenting //#define ROTARY_V1 --- sonoff/my_user_config.h | 1 + sonoff/sonoff.ino | 4 ++++ sonoff/sonoff_template.h | 4 ++++ sonoff/support_rotary.ino | 6 ++++-- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 5ba994a4b..6e62e3031 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -369,6 +369,7 @@ #define TUYA_DIMMER_ID 0 // Default dimmer Id #define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer +//#define ROTARY_V1 // Add support for MI Desk Lamp //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code) //#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) // #define USE_PN532_CAUSE_EVENTS // Cause event execution for PN532_UID= and PN532_DATA=[if defined] (+ 30 bytes code) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index e85a26af2..c53510ada 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2507,7 +2507,9 @@ void GpioInit(void) ButtonInit(); SwitchInit(); +#ifdef ROTARY_V1 RotaryInit(); +#endif #ifdef USE_WS2812 if (!light_type && (pin[GPIO_WS2812] < 99)) { // RGB led @@ -2700,7 +2702,9 @@ void loop(void) ButtonLoop(); SwitchLoop(); +#ifdef ROTARY_V1 RotaryLoop(); +#endif if (TimeReached(state_50msecond)) { SetNextTimeInterval(state_50msecond, 50); diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index b50c2184b..fbe5cd931 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -583,10 +583,12 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_SM16716_DAT, // SM16716 DATA GPIO_SM16716_SEL, // SM16716 SELECT #endif // USE_SM16716 +#ifdef ROTARY_V1 GPIO_ROT1A, // Rotary switch1 A Pin GPIO_ROT1B, // Rotary switch1 B Pin GPIO_ROT2A, // Rotary switch2 A Pin GPIO_ROT2B, // Rotary switch2 B Pin +#endif GPIO_ARIRFRCV, // AliLux RF Receive input #ifdef USE_HRE GPIO_HRE_CLOCK, @@ -656,7 +658,9 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { ARILUX_LC11, ZENGGE_ZF_WF017, HUAFAN_SS, +#ifdef ROTARY_V1 MI_DESK_LAMP, +#endif KMC_70011, AILIGHT, // Light Bulbs PHILIPS, diff --git a/sonoff/support_rotary.ino b/sonoff/support_rotary.ino index db88d8378..c04889a3f 100644 --- a/sonoff/support_rotary.ino +++ b/sonoff/support_rotary.ino @@ -17,8 +17,7 @@ along with this program. If not, see . */ -#define ROTARY_V1 -#ifdef ROTARY_V1 + /*********************************************************************************************\ * Rotary support \*********************************************************************************************/ @@ -31,6 +30,9 @@ uint8_t rotary_last_position = 128; uint8_t interrupts_in_use = 0; uint8_t rotary_changed = 0; +//#define ROTARY_V1 +#ifdef ROTARY_V1 + /********************************************************************************************/ void update_position(void) From 5e1cbcf94fc10f338b1d95258a0b7019df8d5e79 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 5 Apr 2019 15:27:06 +0200 Subject: [PATCH 1225/2222] Make MI Desk Lamp optional Make MI Desk Lamp optional --- sonoff/my_user_config.h | 2 +- sonoff/sonoff.ino | 59 +++++++++++++++++++----------------- sonoff/sonoff_template.h | 8 ++--- sonoff/support.ino | 10 ++++++ sonoff/xdrv_01_webserver.ino | 4 +-- 5 files changed, 48 insertions(+), 35 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 6e62e3031..407a25c13 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -369,7 +369,7 @@ #define TUYA_DIMMER_ID 0 // Default dimmer Id #define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer -//#define ROTARY_V1 // Add support for MI Desk Lamp +//#define ROTARY_V1 // Add support for MI Desk Lamp //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code) //#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) // #define USE_PN532_CAUSE_EVENTS // Cause event execution for PN532_UID= and PN532_DATA=[if defined] (+ 30 bytes code) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c53510ada..d87aba99b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -874,35 +874,40 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } else if (CMND_MODULE == command_code) { if ((payload >= 0) && (payload <= MAXMODULE)) { - if (0 == payload) { payload = 256; } - payload--; - Settings.last_module = Settings.module; - Settings.module = payload; - SetModuleType(); - if (Settings.last_module != payload) { - for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { - Settings.my_gp.io[i] = GPIO_NONE; - } + bool present = false; + if (0 == payload) { + payload = 255; + present = true; + } else { + payload--; + present = ValidModule(payload); + } + if (present) { + Settings.last_module = Settings.module; + Settings.module = payload; + SetModuleType(); + if (Settings.last_module != payload) { + for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { + Settings.my_gp.io[i] = GPIO_NONE; + } + } + restart_flag = 2; } - restart_flag = 2; } Response_P(S_JSON_COMMAND_NVALUE_SVALUE, command, ModuleNr(), ModuleName().c_str()); } else if (CMND_MODULES == command_code) { - for (uint8_t i = 0; i <= MAXMODULE; i++) { + uint8_t midx = USER_MODULE; + for (uint8_t i = 0; i <= sizeof(kModuleNiceList); i++) { + if (i > 0) { midx = pgm_read_byte(kModuleNiceList + i -1); } if (!jsflg) { Response_P(PSTR("{\"" D_CMND_MODULES "%d\":["), lines); } else { ResponseAppend_P(PSTR(",")); } jsflg = true; - uint8_t j = i; - if (0 == i) { j = USER_MODULE; } else { j--; } - -// ResponseAppend_P(PSTR("\"%d (%s)\""), i, AnyModuleName(j).c_str()); -// if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == MAXMODULE)) { - - if ((ResponseAppend_P(PSTR("\"%d (%s)\""), i, AnyModuleName(j).c_str()) > (LOGSZ - TOPSZ)) || (i == MAXMODULE)) { + uint8_t j = i ? midx +1 : 0; + if ((ResponseAppend_P(PSTR("\"%d (%s)\""), j, AnyModuleName(midx).c_str()) > (LOGSZ - TOPSZ)) || (i == sizeof(kModuleNiceList))) { ResponseAppend_P(PSTR("]}")); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); jsflg = false; @@ -957,10 +962,6 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) ResponseAppend_P(PSTR(",")); } jsflg = true; - -// ResponseAppend_P(PSTR("\"%d (%s)\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)); -// if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { - if ((ResponseAppend_P(PSTR("\"%d (%s)\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { ResponseAppend_P(PSTR("]}")); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); @@ -2324,9 +2325,11 @@ void GpioInit(void) { uint8_t mpin; - if ((Settings.module >= MAXMODULE) && (Settings.module < USER_MODULE)) { - Settings.module = MODULE; - Settings.last_module = MODULE; + if (!ValidModule(Settings.module)) { + uint8_t module = MODULE; + if (!ValidModule(MODULE)) { module = SONOFF_BASIC; } + Settings.module = module; + Settings.last_module = module; } SetModuleType(); @@ -2509,7 +2512,7 @@ void GpioInit(void) SwitchInit(); #ifdef ROTARY_V1 RotaryInit(); -#endif +#endif #ifdef USE_WS2812 if (!light_type && (pin[GPIO_WS2812] < 99)) { // RGB led @@ -2702,9 +2705,9 @@ void loop(void) ButtonLoop(); SwitchLoop(); -#ifdef ROTARY_V1 +#ifdef ROTARY_V1 RotaryLoop(); -#endif +#endif if (TimeReached(state_50msecond)) { SetNextTimeInterval(state_50msecond, 50); diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index fbe5cd931..1461e0370 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -588,15 +588,15 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_ROT1B, // Rotary switch1 B Pin GPIO_ROT2A, // Rotary switch2 A Pin GPIO_ROT2B, // Rotary switch2 B Pin -#endif +#endif GPIO_ARIRFRCV, // AliLux RF Receive input #ifdef USE_HRE GPIO_HRE_CLOCK, GPIO_HRE_DATA -#endif +#endif }; -const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { +const uint8_t kModuleNiceList[] PROGMEM = { SONOFF_BASIC, // Sonoff Relay Devices SONOFF_RF, SONOFF_TH, @@ -660,7 +660,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { HUAFAN_SS, #ifdef ROTARY_V1 MI_DESK_LAMP, -#endif +#endif KMC_70011, AILIGHT, // Light Bulbs PHILIPS, diff --git a/sonoff/support.ino b/sonoff/support.ino index 1a222686c..d9fe3ed7a 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -846,6 +846,16 @@ uint8_t ModuleNr() return (USER_MODULE == Settings.module) ? 0 : Settings.module +1; } +bool ValidModule(uint8_t index) +{ + for (uint8_t i = 0; i < sizeof(kModuleNiceList); i++) { + if (index == pgm_read_byte(kModuleNiceList + i)) { + return true; + } + } + return false; +} + String AnyModuleName(uint8_t index) { if (USER_MODULE == index) { diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 771a010b1..33391287f 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1038,7 +1038,7 @@ void HandleTemplateConfiguration(void) if (WebServer->hasArg("m")) { WSContentBegin(200, CT_PLAIN); - for (uint8_t i = 0; i < MAXMODULE; i++) { // "}2'%d'>%s (%d)}3" - "}2'0'>Sonoff Basic (1)}3" + for (uint8_t i = 0; i < sizeof(kModuleNiceList); i++) { // "}2'%d'>%s (%d)}3" - "}2'0'>Sonoff Basic (1)}3" uint8_t midx = pgm_read_byte(kModuleNiceList + i); WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1); } @@ -1159,7 +1159,7 @@ void HandleModuleConfiguration(void) if (WebServer->hasArg("m")) { WSContentBegin(200, CT_PLAIN); uint8_t vidx = 0; - for (uint8_t i = 0; i <= MAXMODULE; i++) { // "}2'%d'>%s (%d)}3" - "}2'255'>UserTemplate (0)}3" - "}2'0'>Sonoff Basic (1)}3" + for (uint8_t i = 0; i <= sizeof(kModuleNiceList); i++) { // "}2'%d'>%s (%d)}3" - "}2'255'>UserTemplate (0)}3" - "}2'0'>Sonoff Basic (1)}3" if (0 == i) { midx = USER_MODULE; vidx = 0; From c673ea17287104e3dc49e0510b8561f53aff18c9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 5 Apr 2019 15:41:01 +0200 Subject: [PATCH 1226/2222] Make MI Desk Lamp optional Make MI Desk Lamp optional --- sonoff/sonoff.ino | 7 +++++-- sonoff/support.ino | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index d87aba99b..741743618 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -978,8 +978,11 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (strstr(dataBuf, "{") == nullptr) { // If no JSON it must be parameter if ((payload > 0) && (payload <= MAXMODULE)) { - ModuleDefault(payload -1); // Copy template module - if (USER_MODULE == Settings.module) { restart_flag = 2; } + payload--; + if (ValidModule(payload)) { + ModuleDefault(payload); // Copy template module + if (USER_MODULE == Settings.module) { restart_flag = 2; } + } } else if (0 == payload) { // Copy current template to user template if (Settings.module != USER_MODULE) { diff --git a/sonoff/support.ino b/sonoff/support.ino index d9fe3ed7a..51c895905 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1023,8 +1023,8 @@ bool JsonTemplate(const char* dataBuf) } if (obj[D_JSON_BASE].success()) { uint8_t base = obj[D_JSON_BASE]; - if ((0 == base) || (base >= MAXMODULE)) { base = 17; } else { base--; } - Settings.user_template_base = base; // Default WEMOS + if ((0 == base) || !ValidModule(base -1)) { base = 18; } + Settings.user_template_base = base -1; // Default WEMOS } return true; } From 03f76a4a9779156543a7727549a6c2e795f1e16e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 5 Apr 2019 17:46:26 +0200 Subject: [PATCH 1227/2222] Tune templates Tune templates --- sonoff/sonoff_template.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 1461e0370..947ee2667 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -466,7 +466,9 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_DHT11, // DHT11 GPIO_DHT22, // DHT21, DHT22, AM2301, AM2302, AM2321 GPIO_SI7021, // iTead SI7021 +#if defined(USE_DS18B20) || defined(USE_DS18x20) || defined(USE_DS18x20_LEGACY) GPIO_DSB, // Single wire DS18B20 or DS18S20 +#endif #ifdef USE_WS2812 GPIO_WS2812, // WS2812 Led string #endif @@ -589,7 +591,9 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_ROT2A, // Rotary switch2 A Pin GPIO_ROT2B, // Rotary switch2 B Pin #endif +#ifdef USE_ARILUX_RF GPIO_ARIRFRCV, // AliLux RF Receive input +#endif #ifdef USE_HRE GPIO_HRE_CLOCK, GPIO_HRE_DATA @@ -648,9 +652,15 @@ const uint8_t kModuleNiceList[] PROGMEM = { OBI2, MANZOKU_EU_4, ESP_SWITCH, // Switch Devices +#ifdef USE_TUYA_DIMMER TUYA_DIMMER, // Dimmer Devices +#endif +#ifdef USE_ARMTRONIX_DIMMERS ARMTRONIX_DIMMERS, +#endif +#ifdef USE_PS_16_DZ PS_16_DZ, +#endif H801, // Light Devices MAGICHOME, ARILUX_LC01, From 148192b80dad2dbad2aee7a60d3678a3bf633a59 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Apr 2019 13:39:59 +0200 Subject: [PATCH 1228/2222] Attempt to fix MQTT reconnects Attempt to fix MQTT reconnects --- sonoff/xdrv_02_mqtt.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index b7daa1f34..28f32c183 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -822,7 +822,7 @@ bool Xdrv02(uint8_t function) if (Settings.flag.mqtt_enabled) { switch (function) { - case FUNC_LOOP: + case FUNC_EVERY_100_MSECOND: // https://github.com/knolleary/pubsubclient/issues/556 if (MqttIsConnected()) { MqttClient.loop(); } break; #ifdef USE_WEBSERVER From 756400de195a5d5d979583b44c9bdc2db2525432 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Apr 2019 15:22:25 +0200 Subject: [PATCH 1229/2222] Attempt to fix MQTT reconnects while keeping good response Attempt to fix MQTT reconnects while keeping good response --- sonoff/xdrv_02_mqtt.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 28f32c183..8ef49a54a 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -822,8 +822,8 @@ bool Xdrv02(uint8_t function) if (Settings.flag.mqtt_enabled) { switch (function) { - case FUNC_EVERY_100_MSECOND: // https://github.com/knolleary/pubsubclient/issues/556 - if (MqttIsConnected()) { MqttClient.loop(); } + case FUNC_EVERY_50_MSECOND: // https://github.com/knolleary/pubsubclient/issues/556 + MqttClient.loop(); break; #ifdef USE_WEBSERVER case FUNC_WEB_ADD_BUTTON: From 43a61b3e249dbea13eebe10c94fb2651921040e0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Apr 2019 18:25:26 +0200 Subject: [PATCH 1230/2222] 6.5.0.5 Add compile time GUI color options 6.5.0.5 20190406 * Add compile time GUI color options (#5586) --- sonoff/_changelog.ino | 5 ++- sonoff/my_user_config.h | 26 +++++++++++++++ sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_webserver.ino | 65 ++++++++++++++++++++++++++++-------- sonoff/xdrv_09_timers.ino | 19 +++++++++-- 5 files changed, 98 insertions(+), 19 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e21c7409a..95d065ccb 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.5.0.4 20190402 +/* 6.5.0.5 20190406 + * Add compile time GUI color options (#5586) + * + * 6.5.0.4 20190402 * Fix Configure Timer Web GUI (#5568) * Add validation check when loading settings from flash * Fixed Display Bug in KNX webmenu for Physical Address diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 407a25c13..97a43836f 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -257,6 +257,32 @@ #define WEB_USERNAME "admin" // Web server Admin mode user name #define USE_EMULATION // Enable Belkin WeMo and Hue Bridge emulation for Alexa (+16k code, +2k mem) +// Black text on white/greyish background (default) + #define COLOR_TEXT "#000" // Global text color - Black + #define COLOR_BACKGROUND "#fff" // Global background color - White + #define COLOR_FORM "#f2f2f2" // Form background color - Greyish + +// White text on black/greyish background (alternative) +// #define COLOR_TEXT "#fff" // Global text color - White +// #define COLOR_BACKGROUND "#000" // Global background color - Black +// #define COLOR_FORM "#4f4f4f" // Form background color - Greyish + + #define COLOR_TEXT_WARNING "red" // Warning text color - Red + #define COLOR_TEXT_SUCCESS "green" // Success text color - Green + + #define COLOR_BUTTON_TEXT "#fff" // Button text color - White + #define COLOR_BUTTON "#1fa3ec" // Button color - Blueish + #define COLOR_BUTTON_HOVER "#0e70a4" // Button color when hovered over - Darker blueish + #define COLOR_BUTTON_RESET "#d43535" // Restart/Reset/Delete button color - Redish + #define COLOR_BUTTON_RESET_HOVER "#931f1f" // Restart/Reset/Delete button color when hovered over - Darker redish + #define COLOR_BUTTON_SAVE "#47c266" // Save button color - Greenish + #define COLOR_BUTTON_SAVE_HOVER "#5aaf6f" // Save button color when hovered over - Darker greenish + + #define COLOR_TIMER_TAB_TEXT "#fff" // Config timer tab text color - White + #define COLOR_TIMER_TAB_BACKGROUND "#999" // Config timer tab background color - Light grey + #define COLOR_TIMER_ACTIVE_TAB_TEXT "#000" // Config timer active tab text color - Black + #define COLOR_TIMER_ACTIVE_TAB_BG "transparent" // Config timer active tab text color - Transparent (= COLOR_FORM) + // -- mDNS ---------------------------------------- #define USE_DISCOVERY // Enable mDNS for the following services (+8k code, +0.3k mem) #define WEBSERVER_ADVERTISE // Provide access to webserver by name .local/ diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 3a8dc0eb8..c43d2d6d3 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06050004; +const uint32_t VERSION = 0x06050005; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 33391287f..ff5672093 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -31,6 +31,43 @@ #define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by SmartConfig web GUI #endif +#ifndef COLOR_TEXT_WARNING +#define COLOR_TEXT_WARNING "red" // Warning text color - Red +#endif +#ifndef COLOR_TEXT_SUCCESS +#define COLOR_TEXT_SUCCESS "green" // Success text color - Green +#endif +#ifndef COLOR_TEXT +#define COLOR_TEXT "#000" // Global text color - Black +#endif +#ifndef COLOR_BACKGROUND +#define COLOR_BACKGROUND "#fff" // Global background color - White +#endif +#ifndef COLOR_FORM +#define COLOR_FORM "#f2f2f2" // Form background color - Greyish +#endif +#ifndef COLOR_BUTTON_TEXT +#define COLOR_BUTTON_TEXT "#fff" // Button text color - White +#endif +#ifndef COLOR_BUTTON +#define COLOR_BUTTON "#1fa3ec" // Button color - Blueish +#endif +#ifndef COLOR_BUTTON_HOVER +#define COLOR_BUTTON_HOVER "#0e70a4" // Button color when hovered over - Darker blueish +#endif +#ifndef COLOR_BUTTON_RESET +#define COLOR_BUTTON_RESET "#d43535" // Restart/Reset/Delete button color - Redish +#endif +#ifndef COLOR_BUTTON_RESET_HOVER +#define COLOR_BUTTON_RESET_HOVER "#931f1f" // Restart/Reset/Delete button color when hovered over - Darker redish +#endif +#ifndef COLOR_BUTTON_SAVE +#define COLOR_BUTTON_SAVE "#47c266" // Save button color - Greenish +#endif +#ifndef COLOR_BUTTON_SAVE_HOVER +#define COLOR_BUTTON_SAVE_HOVER "#5aaf6f" // Save button color when hovered over - Darker greenish +#endif + const uint16_t CHUNKED_BUFFER_SIZE = 400; // Chunk buffer size (should be smaller than half mqtt_date size) const uint16_t HTTP_REFRESH_TIME = 2345; // milliseconds @@ -239,21 +276,21 @@ const char HTTP_HEAD_STYLE1[] PROGMEM = "Zeichenfläche 1 \ No newline at end of file diff --git a/tools/logo/TASMOTA_Symbol_Vector.svg b/tools/logo/TASMOTA_Symbol_Vector.svg new file mode 100644 index 000000000..43f86da17 --- /dev/null +++ b/tools/logo/TASMOTA_Symbol_Vector.svg @@ -0,0 +1 @@ +Element 1 \ No newline at end of file From 5beaea32fdc181935caec652c926b11e04edd8e6 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 22 May 2019 12:22:58 +0200 Subject: [PATCH 1387/2222] global update fix --- sonoff/sonoff.ino | 2 +- sonoff/support.ino | 2 +- sonoff/xsns_21_sgp30.ino | 4 ++-- sonoff/xsns_31_ccs811.ino | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ef9845c81..48145fb2f 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -125,7 +125,7 @@ int blinks = 201; // Number of LED blinks uint32_t uptime = 0; // Counting every second until 4294967295 = 130 year uint32_t loop_load_avg = 0; // Indicative loop load average uint32_t global_update = 0; // Timestamp of last global temperature and humidity update -float global_temperature = 0; // Provide a global temperature to be used by some sensors +float global_temperature = 9999; // Provide a global temperature to be used by some sensors float global_humidity = 0; // Provide a global humidity to be used by some sensors float global_pressure = 0; // Provide a global pressure to be used by some sensors char *ota_url; // OTA url string pointer diff --git a/sonoff/support.ino b/sonoff/support.ino index da79be0e0..f3faa1798 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -644,7 +644,7 @@ void ResetGlobalValues(void) { if ((uptime - global_update) > GLOBAL_VALUES_VALID) { // Reset after 5 minutes global_update = 0; - global_temperature = 0; + global_temperature = 9999; global_humidity = 0; global_pressure = 0; } diff --git a/sonoff/xsns_21_sgp30.ino b/sonoff/xsns_21_sgp30.ino index 27d1a43f9..e9c097dc4 100644 --- a/sonoff/xsns_21_sgp30.ino +++ b/sonoff/xsns_21_sgp30.ino @@ -89,7 +89,7 @@ void Sgp30Update(void) // Perform every second to ensure proper operation of th } return; // Measurement failed } - if (global_update) { + if (global_update && global_humidity>0 && global_temperature!=9999) { // abs hum in mg/m3 sgp30_abshum=sgp30_AbsoluteHumidity(global_temperature,global_humidity,TempUnit()); sgp.setHumidity(sgp30_abshum*1000); @@ -124,7 +124,7 @@ void Sgp30Show(bool json) if (sgp30_ready) { char abs_hum[33]; - if (global_update) { + if (global_update && global_humidity>0 && global_temperature!=9999) { // has humidity + temperature dtostrfd(sgp30_abshum,4,abs_hum); } diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index 2624d0b8c..550313b51 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -62,7 +62,7 @@ void CCS811Update(void) // Perform every n second TVOC = ccs.getTVOC(); eCO2 = ccs.geteCO2(); CCS811_ready = 1; - if (global_update) { ccs.setEnvironmentalData((uint8_t)global_humidity, global_temperature); } + if (global_update && global_humidity>0 && global_temperature!=9999) { ccs.setEnvironmentalData((uint8_t)global_humidity, global_temperature); } ecnt = 0; } } else { From a623d1e90b9a40efc4133ac7f14078ecd5304c1a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 22 May 2019 12:31:23 +0200 Subject: [PATCH 1388/2222] Add temp test Add temp test --- sonoff/xdrv_03_energy.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 2793c3663..74867263e 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -323,7 +323,7 @@ void EnergyMqttShow(void) void EnergyOverTempCheck() { if (global_update) { - if (power && (global_temperature > ENERGY_OVERTEMP)) { // Device overtemp, turn off relays + if (power && (global_temperature != 9999) && (global_temperature > ENERGY_OVERTEMP)) { // Device overtemp, turn off relays SetAllPower(POWER_ALL_OFF, SRC_OVERTEMP); } } From 48eb9c437eaf986046cb3a3be121aea62d8aea04 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 22 May 2019 12:33:51 +0200 Subject: [PATCH 1389/2222] Update xdrv_10_scripter.ino optimized median filter, support for opt filter lenght, support for arrays string token support, at least needed to decode json comma seperated values (now all json result may be decoded) --- sonoff/xdrv_10_scripter.ino | 192 +++++++++++++++++++++++++++--------- 1 file changed, 146 insertions(+), 46 deletions(-) diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index 9edd27a9f..288a052ee 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -20,17 +20,15 @@ #ifdef USE_SCRIPT #ifndef USE_RULES /*********************************************************************************************\ - for documentation see up to date docs in file SCRIPTER.md - uses about 14,2 k of flash more stack could be needed for sendmail => -D CONT_STACKSIZE=4800 = +0.8k stack -0.8k heap - to do optimize code for space remarks + goal is fast execution time, minimal use of ram and intuitive syntax therefore => case sensitive cmds and vars (lowercase uses time and code) @@ -38,6 +36,10 @@ no math hierarchy (costs ram and execution time, better group with brackets, an (will probably make math hierarchy an ifdefed option) keywords if then else endif, or, and are better readable for beginners (others may use {}) +changelog after merging to Tasmota +1.01 optimized median filter, support for opt filter lenght, support for arrays +1.02 string token support + \*********************************************************************************************/ #define XDRV_10 10 @@ -104,11 +106,14 @@ struct SCRIPT_MEM { uint8_t script_loglevel; } glob_script_mem; + +int16_t last_findex; uint8_t tasm_cmd_activ=0; uint32_t script_lastmillis; char *GetNumericResult(char *lp,uint8_t lastop,float *fp,JsonObject *jo); +char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo); void ScriptEverySecond(void) { @@ -243,6 +248,19 @@ int16_t Init_Scripter(char *script) { if (nvars>MAXNVARS) { return -1; } + if (vtypes[vars].bits.is_filter) { + while (isdigit(*op) || *op=='.' || *op=='-') { + op++; + } + while (*op==' ') op++; + if (isdigit(*op)) { + // lenght define follows + uint8_t flen=atoi(op); + mfilt[numflt-1].numvals&=0x7f; + mfilt[numflt-1].numvals|=flen&0x7f; + } + } + } else { // string vars op++; @@ -445,9 +463,65 @@ int16_t Init_Scripter(char *script) { #define NTYPE 0 #define STYPE 0x80 +#define FLT_MAX 99999999 + +float median_array(float *array,uint8_t len) { + uint8_t ind[len]; + uint8_t mind=0,index=0,flg; + float min=FLT_MAX; + + for (uint8_t hcnt=0; hcntnumvals&0x7f; + if (!bind) { + return mflp->index; + } + if (bind<1 || bind>maxind) bind=maxind; + return mflp->rbuff[bind-1]; + } + mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); + } + return 0; +} + +void Set_MFVal(uint8_t index,uint8_t bind,float val) { + uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; + for (uint8_t count=0; countnumvals&0x7f; + if (bind<1 || bind>maxind) bind=maxind; + mflp->rbuff[bind-1]=val; + } + mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); + } +} -//Settings.seriallog_level -//Settings.weblog_level float Get_MFilter(uint8_t index) { uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; @@ -458,23 +532,8 @@ float Get_MFilter(uint8_t index) { // moving average return mflp->maccu/(mflp->numvals&0x7f); } else { - // median, sort array - float tbuff[mflp->numvals],tmp; - uint8_t flag; - memmove(tbuff,mflp->rbuff,sizeof(tbuff)); - for (uint8_t ocnt=0; ocntnumvals; ocnt++) { - flag=0; - for (uint8_t count=0; countnumvals-1; count++) { - if (tbuff[count]>tbuff[count+1]) { - tmp=tbuff[count]; - tbuff[count]=tbuff[count+1]; - tbuff[count+1]=tmp; - flag=1; - } - } - if (!flag) break; - } - return mflp->rbuff[mflp->numvals/2]; + // median, sort array indices + return median_array(mflp->rbuff,mflp->numvals); } } mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); @@ -519,27 +578,10 @@ float DoMedian5(uint8_t index, float in) { if (index>=MEDIAN_FILTER_NUM) index=0; struct MEDIAN_FILTER* mf=&script_mf[index]; - - float tbuff[MEDIAN_SIZE],tmp; - uint8_t flag; mf->buffer[mf->index]=in; mf->index++; if (mf->index>=MEDIAN_SIZE) mf->index=0; - // sort list and take median - memmove(tbuff,mf->buffer,sizeof(tbuff)); - for (uint8_t ocnt=0; ocnttbuff[count+1]) { - tmp=tbuff[count]; - tbuff[count]=tbuff[count+1]; - tbuff[count+1]=tmp; - flag=1; - } - } - if (!flag) break; - } - return tbuff[MEDIAN_SIZE/2]; + return median_array(mf->buffer,MEDIAN_SIZE); } @@ -606,19 +648,35 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso } struct T_INDEX *vtp=glob_script_mem.type; + char dvnam[32]; + strcpy (dvnam,vname); + uint8_t olen=len; + last_findex=-1; + char *ja=strchr(dvnam,'['); + if (ja) { + *ja=0; + ja++; + olen=strlen(dvnam); + } for (count=0; countindex=count; // overwrite with global var index if (vtp[count].bits.is_string==0) { *vtype=NTYPE|index; if (vtp[count].bits.is_filter) { - fvar=Get_MFilter(index); + if (ja) { + GetNumericResult(ja,OPER_EQU,&fvar,0); + last_findex=fvar; + fvar=Get_MFVal(index,fvar); + len++; + } else { + fvar=Get_MFilter(index); + } } else { fvar=glob_script_mem.fvars[index]; } @@ -943,6 +1001,40 @@ chknext: fvar=strlen(Settings.rules[0]); goto exit; } + if (!strncmp(vname,"st(",3)) { + lp+=3; + char str[SCRIPT_MAXSSIZE]; + lp=GetStringResult(lp,OPER_EQU,str,0); + while (*lp==' ') lp++; + char token[2]; + token[0]=*lp++; + token[1]=0; + while (*lp==' ') lp++; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + // skip ) bracket + lp++; + len=0; + if (sp) { + // get stringtoken + char *st=strtok(str,token); + if (!st) { + *sp=0; + } else { + for (uint8_t cnt=1; cnt<=fvar; cnt++) { + if (cnt==fvar) { + strcpy(sp,st); + break; + } + st=strtok(NULL,token); + if (!st) { + *sp=0; + break; + } + } + } + } + goto strexit; + } #if defined(USE_TIMERS) && defined(USE_SUNRISE) if (!strncmp(vname,"sunrise",7)) { fvar=SunMinutes(0); @@ -1416,10 +1508,13 @@ void toSLog(const char *str) { #endif } + + + #define IF_NEST 8 // execute section of scripter int16_t Run_Scripter(const char *type, uint8_t tlen, char *js) { - uint8_t vtype=0,sindex,xflg,floop=0,globvindex; + uint8_t vtype=0,sindex,xflg,floop=0,globvindex,globaindex; struct T_INDEX ind; uint8_t operand,lastop,numeric=1,if_state[IF_NEST],if_result[IF_NEST],and_or,ifstck=0,s_ifstck=0; if_state[ifstck]=0; @@ -1726,6 +1821,7 @@ int16_t Run_Scripter(const char *type, uint8_t tlen, char *js) { if (vtype!=VAR_NV) { // found variable as result globvindex=ind.index; // save destination var index here + globaindex=last_findex; uint8_t index=glob_script_mem.type[ind.index].index; if ((vtype&STYPE)==0) { // numeric result @@ -1860,7 +1956,11 @@ int16_t Run_Scripter(const char *type, uint8_t tlen, char *js) { // var was changed glob_script_mem.type[globvindex].bits.changed=1; if (glob_script_mem.type[globvindex].bits.is_filter) { - Set_MFilter(glob_script_mem.type[globvindex].index,*dfvar); + if (globaindex>=0) { + Set_MFVal(glob_script_mem.type[globvindex].index,globaindex,*dfvar); + } else { + Set_MFilter(glob_script_mem.type[globvindex].index,*dfvar); + } } if (sysv_type) { From c71b06614ebcb7bba27c418f2bfa380ff04ab039 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 22 May 2019 12:34:16 +0200 Subject: [PATCH 1390/2222] Update xdrv_10_scripter.ino --- sonoff/xdrv_10_scripter.ino | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index 288a052ee..83c29a42c 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -36,9 +36,7 @@ no math hierarchy (costs ram and execution time, better group with brackets, an (will probably make math hierarchy an ifdefed option) keywords if then else endif, or, and are better readable for beginners (others may use {}) -changelog after merging to Tasmota -1.01 optimized median filter, support for opt filter lenght, support for arrays -1.02 string token support + \*********************************************************************************************/ From 1c7e013837ed03197f30cd9bd7446138f60c2ed5 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 22 May 2019 12:38:34 +0200 Subject: [PATCH 1391/2222] Update scripter.md --- scripter.md | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/scripter.md b/scripter.md index 5b9ac7840..dc4123192 100644 --- a/scripter.md +++ b/scripter.md @@ -39,7 +39,9 @@ numeric var=4 bytes, string var=lenght of string+1) **i:**vname specifies auto increment counters if >=0 (in seconds) **m:**vname specifies a median filter variable with 5 entries (for elimination of outliers) **M:**vname specifies a moving average filter variable with 8 entries (for smoothing data) -(max 5 filters in total m+M) +(max 5 filters in total m+M) optional another filter lenght (1..127) can be given after the definition. +filter vars can be accessed also in indexed mode vname[x] (index = 1...N, index 0 returns current array index pointer) +by this filter vars can be used as arrays >all variable names length taken together may not exceed 256 characters, so keep variable names as short as possible. memory is dynamically allocated as a result of the D section. @@ -84,7 +86,8 @@ special variables (read only): **pow(x y)** = calculates the power of x^y **med(n x)** = calculates a 5 value median filter of x (2 filters possible n=0,1) **int(x)** = gets the integer part of x (like floor) -**hn(x)** = converts x (0..255) zu a hex nibble string +**hn(x)** = converts x (0..255) to a hex nibble string +**st(svar c n)** = stringtoken gets the n th substring of svar separated by c **mqtts** = state of mqtt disconnected=0, connected>0 **wifis** = state of wifi disconnected=0, connected>0 @@ -225,7 +228,9 @@ tcnt=0 hour=0 state=1 m:med5=0 -M:movav=0 +M:movav=0 +; define array with 10 entries +m:array=0 10 **\>B** @@ -258,15 +263,14 @@ delay(100) =>power 0 **\>T** - hum=BME280#Humidity temp=BME280#Temperature rssi=Wifi#RSSI string=SleepMode -; add to median filter +; add to median filter median=temp -; add to moving average filter +; add to moving average filter movav=hum ; show filtered results @@ -274,7 +278,7 @@ movav=hum if chg[rssi]>0 then =>print rssi changed to %rssi% -endif +endif if temp\>30 and hum\>70 @@ -286,6 +290,11 @@ endif ; every second but not completely reliable time here ; use upsecs and uptime or best t: for reliable timers +; arrays +array[1]=4 +array[2]=5 +tmp=array[1]+array[2] + ; call subrountines with parameters =#sub1("hallo") =#sub2(999) @@ -427,6 +436,8 @@ ends **\>E** =\>print event executed! +; get HSBColor 1. component +tmp=st(HSBColor , 1) ; check if switch changed state sw=sw[1] From 1f17a407c9fc575dcc384a48a67035654165002f Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 22 May 2019 13:21:41 +0200 Subject: [PATCH 1392/2222] add vl53l0x --- lib/vl53l0x-arduino-1.02/.travis.yml | 24 + lib/vl53l0x-arduino-1.02/LICENSE.txt | 71 ++ lib/vl53l0x-arduino-1.02/README.md | 164 +++ lib/vl53l0x-arduino-1.02/VL53L0X.cpp | 1036 +++++++++++++++++ lib/vl53l0x-arduino-1.02/VL53L0X.h | 176 +++ .../examples/Continuous/Continuous.ino | 33 + .../examples/Single/Single.ino | 65 ++ lib/vl53l0x-arduino-1.02/keywords.txt | 90 ++ lib/vl53l0x-arduino-1.02/library.properties | 9 + sonoff/xsns_45_vl53l0x.ino | 162 +++ 10 files changed, 1830 insertions(+) create mode 100755 lib/vl53l0x-arduino-1.02/.travis.yml create mode 100755 lib/vl53l0x-arduino-1.02/LICENSE.txt create mode 100755 lib/vl53l0x-arduino-1.02/README.md create mode 100755 lib/vl53l0x-arduino-1.02/VL53L0X.cpp create mode 100755 lib/vl53l0x-arduino-1.02/VL53L0X.h create mode 100755 lib/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino create mode 100755 lib/vl53l0x-arduino-1.02/examples/Single/Single.ino create mode 100755 lib/vl53l0x-arduino-1.02/keywords.txt create mode 100755 lib/vl53l0x-arduino-1.02/library.properties create mode 100755 sonoff/xsns_45_vl53l0x.ino diff --git a/lib/vl53l0x-arduino-1.02/.travis.yml b/lib/vl53l0x-arduino-1.02/.travis.yml new file mode 100755 index 000000000..f3ed70c21 --- /dev/null +++ b/lib/vl53l0x-arduino-1.02/.travis.yml @@ -0,0 +1,24 @@ +language: python + +cache: + directories: + - "~/.platformio" + +install: +- pip install -U platformio + +env: +- BOARD=uno +- BOARD=leonardo +- BOARD=micro +- BOARD=megaatmega2560 +- BOARD=due +- BOARD=yun +- BOARD=genuino101 +- BOARD=zero + +script: +- set -eo pipefail; + for e in examples/*; do + platformio ci --board=$BOARD --lib=. $e/*; + done diff --git a/lib/vl53l0x-arduino-1.02/LICENSE.txt b/lib/vl53l0x-arduino-1.02/LICENSE.txt new file mode 100755 index 000000000..bea985af6 --- /dev/null +++ b/lib/vl53l0x-arduino-1.02/LICENSE.txt @@ -0,0 +1,71 @@ +Copyright (c) 2017 Pololu Corporation. For more information, see + +https://www.pololu.com/ +https://forum.pololu.com/ + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +================================================================= + +Most of the functionality of this library is based on the VL53L0X +API provided by ST (STSW-IMG005), and some of the explanatory +comments are quoted or paraphrased from the API source code, API +user manual (UM2039), and the VL53L0X datasheet. + +The following applies to source code reproduced or derived from +the API: + +----------------------------------------------------------------- + +Copyright © 2016, STMicroelectronics International N.V. All +rights reserved. + +Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following +conditions are met: +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following +disclaimer in the documentation and/or other materials provided +with the distribution. +* Neither the name of STMicroelectronics nor the +names of its contributors may be used to endorse or promote +products derived from this software without specific prior +written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. +IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +----------------------------------------------------------------- diff --git a/lib/vl53l0x-arduino-1.02/README.md b/lib/vl53l0x-arduino-1.02/README.md new file mode 100755 index 000000000..917514d70 --- /dev/null +++ b/lib/vl53l0x-arduino-1.02/README.md @@ -0,0 +1,164 @@ +# VL53L0X library for Arduino + +Version: 1.0.2
+Release date: 2017 Jun 27
+[![Build Status](https://travis-ci.org/pololu/vl53l0x-arduino.svg?branch=master)](https://travis-ci.org/pololu/vl53l0x-arduino)
+[www.pololu.com](https://www.pololu.com/) + +## Summary + +This is a library for the Arduino IDE that helps interface with ST's [VL53L0X time-of-flight distance sensor](https://www.pololu.com/product/2490). The library makes it simple to configure the sensor and read range data from it via I²C. + +## Supported platforms + +This library is designed to work with the Arduino IDE versions 1.6.x or later; we have not tested it with earlier versions. This library should support any Arduino-compatible board, including the [Pololu A-Star 32U4 controllers](https://www.pololu.com/category/149/a-star-programmable-controllers). + +## Getting started + +### Hardware + +A [VL53L0X carrier](https://www.pololu.com/product/2490) can be purchased from Pololu's website. Before continuing, careful reading of the [product page](https://www.pololu.com/product/2490) as well as the VL53L0X datasheet is recommended. + +Make the following connections between the Arduino and the VL53L0X board: + +#### 5V Arduino boards + +(including Arduino Uno, Leonardo, Mega; Pololu A-Star 32U4) + + Arduino VL53L0X board + ------- ------------- + 5V - VIN + GND - GND + SDA - SDA + SCL - SCL + +#### 3.3V Arduino boards + +(including Arduino Due) + + Arduino VL53L0X board + ------- ------------- + 3V3 - VIN + GND - GND + SDA - SDA + SCL - SCL + +### Software + +If you are using version 1.6.2 or later of the [Arduino software (IDE)](http://www.arduino.cc/en/Main/Software), you can use the Library Manager to install this library: + +1. In the Arduino IDE, open the "Sketch" menu, select "Include Library", then "Manage Libraries...". +2. Search for "VL53L0X". +3. Click the VL53L0X entry in the list. +4. Click "Install". + +If this does not work, you can manually install the library: + +1. Download the [latest release archive from GitHub](https://github.com/pololu/vl53l0x-arduino/releases) and decompress it. +2. Rename the folder "vl53l0x-arduino-master" to "VL53L0X". +3. Move the "VL53L0X" folder into the "libraries" directory inside your Arduino sketchbook directory. You can view your sketchbook location by opening the "File" menu and selecting "Preferences" in the Arduino IDE. If there is not already a "libraries" folder in that location, you should make the folder yourself. +4. After installing the library, restart the Arduino IDE. + +## Examples + +Several example sketches are available that show how to use the library. You can access them from the Arduino IDE by opening the "File" menu, selecting "Examples", and then selecting "VL53L0X". If you cannot find these examples, the library was probably installed incorrectly and you should retry the installation instructions above. + +## ST's VL53L0X API and this library + +Most of the functionality of this library is based on the [VL53L0X API](http://www.st.com/content/st_com/en/products/embedded-software/proximity-sensors-software/stsw-img005.html) provided by ST (STSW-IMG005), and some of the explanatory comments in the code are quoted or paraphrased from the API source code, API user manual (UM2039), and the VL53L0X datasheet. For more explanation about the library code and how it was derived from the API, see the comments in VL53L0X.cpp. + +This library is intended to provide a quicker and easier way to get started using the VL53L0X with an Arduino-compatible controller, in contrast to customizing and compiling ST's API for the Arduino. The library has a more streamlined interface, as well as smaller storage and memory footprints. However, it does not implement some of the more advanced functionality available in the API (for example, calibrating the sensor to work well under a cover glass), and it has less robust error checking. For advanced applications, especially when storage and memory are less of an issue, consider using the VL53L0X API directly. + +## Library reference + +* `uint8_t last_status`
+ The status of the last I²C write transmission. See the [`Wire.endTransmission()` documentation](http://arduino.cc/en/Reference/WireEndTransmission) for return values. + +* `VL53L0X(void)`
+ Constructor. + +* `void setAddress(uint8_t new_addr)`
+ Changes the I²C slave device address of the VL53L0X to the given value (7-bit). + +* `uint8_t getAddress(void)`
+ Returns the current I²C address. + +* `bool init(bool io_2v8 = true)`
+ Iniitializes and configures the sensor. If the optional argument `io_2v8` is true (the default if not specified), the sensor is configured for 2V8 mode (2.8 V I/O); if false, the sensor is left in 1V8 mode. The return value is a boolean indicating whether the initialization completed successfully. + +* `void writeReg(uint8_t reg, uint8_t value)`
+ Writes an 8-bit sensor register with the given value. + + Register address constants are defined by the regAddr enumeration type in VL53L0X.h.
+ Example use: `sensor.writeReg(VL53L0X::SYSRANGE_START, 0x01);` + +* `void writeReg16Bit(uint8_t reg, uint16_t value)`
+ Writes a 16-bit sensor register with the given value. + +* `void writeReg32Bit(uint8_t reg, uint32_t value)`
+ Writes a 32-bit sensor register with the given value. + +* `uint8_t readReg(uint8_t reg)`
+ Reads an 8-bit sensor register and returns the value read. + +* `uint16_t readReg16Bit(uint8_t reg)`
+ Reads a 16-bit sensor register and returns the value read. + +* `uint32_t readReg32Bit(uint8_t reg)`
+ Reads a 32-bit sensor register and returns the value read. + +* `void writeMulti(uint8_t reg, uint8_t const * src, uint8_t count)`
+ Writes an arbitrary number of bytes from the given array to the sensor, starting at the given register. + +* `void readMulti(uint8_t reg, uint8_t * dst, uint8_t count)`
+ Reads an arbitrary number of bytes from the sensor, starting at the given register, into the given array. + +* `bool setSignalRateLimit(float limit_Mcps)`
+ Sets the return signal rate limit to the given value in units of MCPS (mega counts per second). This is the minimum amplitude of the signal reflected from the target and received by the sensor necessary for it to report a valid reading. Setting a lower limit increases the potential range of the sensor but also increases the likelihood of getting an inaccurate reading because of reflections from objects other than the intended target. This limit is initialized to 0.25 MCPS by default. The return value is a boolean indicating whether the requested limit was valid. + +* `float getSignalRateLimit(void)`
+ Returns the current return signal rate limit in MCPS. + +* `bool setMeasurementTimingBudget(uint32_t budget_us)`
+ Sets the measurement timing budget to the given value in microseconds. This is the time allowed for one range measurement; a longer timing budget allows for more accurate measurements. The default budget is about 33000 microseconds, or 33 ms; the minimum is 20 ms. The return value is a boolean indicating whether the requested budget was valid. + +* `uint32_t getMeasurementTimingBudget(void)`
+ Returns the current measurement timing budget in microseconds. + +* `bool setVcselPulsePeriod(vcselPeriodType type, uint8_t period_pclks)` + Sets the VCSEL (vertical cavity surface emitting laser) pulse period for the given period type (`VL53L0X::VcselPeriodPreRange` or `VL53L0X::VcselPeriodFinalRange`) to the given value (in PCLKs). Longer periods increase the potential range of the sensor. Valid values are (even numbers only): + + Pre: 12 to 18 (initialized to 14 by default)
+ Final: 8 to 14 (initialized to 10 by default) + + The return value is a boolean indicating whether the requested period was valid. + +* `uint8_t getVcselPulsePeriod(vcselPeriodType type)`
+ Returns the current VCSEL pulse period for the given period type. + +* `void startContinuous(uint32_t period_ms = 0)`
+ Starts continuous ranging measurements. If the optional argument `period_ms` is 0 (the default if not specified), continuous back-to-back mode is used (the sensor takes measurements as often as possible); if it is nonzero, continuous timed mode is used, with the specified inter-measurement period in milliseconds determining how often the sensor takes a measurement. + +* `void stopContinuous(void)`
+ Stops continuous mode. + +* `uint16_t readRangeContinuousMillimeters(void)`
+ Returns a range reading in millimeters when continuous mode is active. + +* `uint16_t readRangeSingleMillimeters(void)`
+ Performs a single-shot ranging measurement and returns the reading in millimeters. + +* `void setTimeout(uint16_t timeout)`
+ Sets a timeout period in milliseconds after which read operations will abort if the sensor is not ready. A value of 0 disables the timeout. + +* `uint16_t getTimeout(void)`
+ Returns the current timeout period setting. + +* `bool timeoutOccurred(void)`
+ Indicates whether a read timeout has occurred since the last call to `timeoutOccurred()`. + +## Version history + +* 1.0.2 (2017 Jun 27): Fixed a typo in a register modification in `getSpadInfo()` (thanks @tridge). +* 1.0.1 (2016 Dec 08): Fixed type error in `readReg32Bit()`. +* 1.0.0 (2016 Aug 12): Original release. diff --git a/lib/vl53l0x-arduino-1.02/VL53L0X.cpp b/lib/vl53l0x-arduino-1.02/VL53L0X.cpp new file mode 100755 index 000000000..fb2ed3028 --- /dev/null +++ b/lib/vl53l0x-arduino-1.02/VL53L0X.cpp @@ -0,0 +1,1036 @@ +// Most of the functionality of this library is based on the VL53L0X API +// provided by ST (STSW-IMG005), and some of the explanatory comments are quoted +// or paraphrased from the API source code, API user manual (UM2039), and the +// VL53L0X datasheet. + +#include +#include + +// Defines ///////////////////////////////////////////////////////////////////// + +// The Arduino two-wire interface uses a 7-bit number for the address, +// and sets the last bit correctly based on reads and writes +#define ADDRESS_DEFAULT 0b0101001 + +// Record the current time to check an upcoming timeout against +#define startTimeout() (timeout_start_ms = millis()) + +// Check if timeout is enabled (set to nonzero value) and has expired +#define checkTimeoutExpired() (io_timeout > 0 && ((uint16_t)millis() - timeout_start_ms) > io_timeout) + +// Decode VCSEL (vertical cavity surface emitting laser) pulse period in PCLKs +// from register value +// based on VL53L0X_decode_vcsel_period() +#define decodeVcselPeriod(reg_val) (((reg_val) + 1) << 1) + +// Encode VCSEL pulse period register value from period in PCLKs +// based on VL53L0X_encode_vcsel_period() +#define encodeVcselPeriod(period_pclks) (((period_pclks) >> 1) - 1) + +// Calculate macro period in *nanoseconds* from VCSEL period in PCLKs +// based on VL53L0X_calc_macro_period_ps() +// PLL_period_ps = 1655; macro_period_vclks = 2304 +#define calcMacroPeriod(vcsel_period_pclks) ((((uint32_t)2304 * (vcsel_period_pclks) * 1655) + 500) / 1000) + +// Constructors //////////////////////////////////////////////////////////////// + +VL53L0X::VL53L0X(void) + : address(ADDRESS_DEFAULT) + , io_timeout(0) // no timeout + , did_timeout(false) +{ +} + +// Public Methods ////////////////////////////////////////////////////////////// + +void VL53L0X::setAddress(uint8_t new_addr) +{ + writeReg(I2C_SLAVE_DEVICE_ADDRESS, new_addr & 0x7F); + address = new_addr; +} + +// Initialize sensor using sequence based on VL53L0X_DataInit(), +// VL53L0X_StaticInit(), and VL53L0X_PerformRefCalibration(). +// This function does not perform reference SPAD calibration +// (VL53L0X_PerformRefSpadManagement()), since the API user manual says that it +// is performed by ST on the bare modules; it seems like that should work well +// enough unless a cover glass is added. +// If io_2v8 (optional) is true or not given, the sensor is configured for 2V8 +// mode. +bool VL53L0X::init(bool io_2v8) +{ + // VL53L0X_DataInit() begin + + // sensor uses 1V8 mode for I/O by default; switch to 2V8 mode if necessary + if (io_2v8) + { + writeReg(VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV, + readReg(VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV) | 0x01); // set bit 0 + } + + // "Set I2C standard mode" + writeReg(0x88, 0x00); + + writeReg(0x80, 0x01); + writeReg(0xFF, 0x01); + writeReg(0x00, 0x00); + stop_variable = readReg(0x91); + writeReg(0x00, 0x01); + writeReg(0xFF, 0x00); + writeReg(0x80, 0x00); + + // disable SIGNAL_RATE_MSRC (bit 1) and SIGNAL_RATE_PRE_RANGE (bit 4) limit checks + writeReg(MSRC_CONFIG_CONTROL, readReg(MSRC_CONFIG_CONTROL) | 0x12); + + // set final range signal rate limit to 0.25 MCPS (million counts per second) + setSignalRateLimit(0.25); + + writeReg(SYSTEM_SEQUENCE_CONFIG, 0xFF); + + // VL53L0X_DataInit() end + + // VL53L0X_StaticInit() begin + + uint8_t spad_count; + bool spad_type_is_aperture; + if (!getSpadInfo(&spad_count, &spad_type_is_aperture)) { return false; } + + // The SPAD map (RefGoodSpadMap) is read by VL53L0X_get_info_from_device() in + // the API, but the same data seems to be more easily readable from + // GLOBAL_CONFIG_SPAD_ENABLES_REF_0 through _6, so read it from there + uint8_t ref_spad_map[6]; + readMulti(GLOBAL_CONFIG_SPAD_ENABLES_REF_0, ref_spad_map, 6); + + // -- VL53L0X_set_reference_spads() begin (assume NVM values are valid) + + writeReg(0xFF, 0x01); + writeReg(DYNAMIC_SPAD_REF_EN_START_OFFSET, 0x00); + writeReg(DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD, 0x2C); + writeReg(0xFF, 0x00); + writeReg(GLOBAL_CONFIG_REF_EN_START_SELECT, 0xB4); + + uint8_t first_spad_to_enable = spad_type_is_aperture ? 12 : 0; // 12 is the first aperture spad + uint8_t spads_enabled = 0; + + for (uint8_t i = 0; i < 48; i++) + { + if (i < first_spad_to_enable || spads_enabled == spad_count) + { + // This bit is lower than the first one that should be enabled, or + // (reference_spad_count) bits have already been enabled, so zero this bit + ref_spad_map[i / 8] &= ~(1 << (i % 8)); + } + else if ((ref_spad_map[i / 8] >> (i % 8)) & 0x1) + { + spads_enabled++; + } + } + + writeMulti(GLOBAL_CONFIG_SPAD_ENABLES_REF_0, ref_spad_map, 6); + + // -- VL53L0X_set_reference_spads() end + + // -- VL53L0X_load_tuning_settings() begin + // DefaultTuningSettings from vl53l0x_tuning.h + + writeReg(0xFF, 0x01); + writeReg(0x00, 0x00); + + writeReg(0xFF, 0x00); + writeReg(0x09, 0x00); + writeReg(0x10, 0x00); + writeReg(0x11, 0x00); + + writeReg(0x24, 0x01); + writeReg(0x25, 0xFF); + writeReg(0x75, 0x00); + + writeReg(0xFF, 0x01); + writeReg(0x4E, 0x2C); + writeReg(0x48, 0x00); + writeReg(0x30, 0x20); + + writeReg(0xFF, 0x00); + writeReg(0x30, 0x09); + writeReg(0x54, 0x00); + writeReg(0x31, 0x04); + writeReg(0x32, 0x03); + writeReg(0x40, 0x83); + writeReg(0x46, 0x25); + writeReg(0x60, 0x00); + writeReg(0x27, 0x00); + writeReg(0x50, 0x06); + writeReg(0x51, 0x00); + writeReg(0x52, 0x96); + writeReg(0x56, 0x08); + writeReg(0x57, 0x30); + writeReg(0x61, 0x00); + writeReg(0x62, 0x00); + writeReg(0x64, 0x00); + writeReg(0x65, 0x00); + writeReg(0x66, 0xA0); + + writeReg(0xFF, 0x01); + writeReg(0x22, 0x32); + writeReg(0x47, 0x14); + writeReg(0x49, 0xFF); + writeReg(0x4A, 0x00); + + writeReg(0xFF, 0x00); + writeReg(0x7A, 0x0A); + writeReg(0x7B, 0x00); + writeReg(0x78, 0x21); + + writeReg(0xFF, 0x01); + writeReg(0x23, 0x34); + writeReg(0x42, 0x00); + writeReg(0x44, 0xFF); + writeReg(0x45, 0x26); + writeReg(0x46, 0x05); + writeReg(0x40, 0x40); + writeReg(0x0E, 0x06); + writeReg(0x20, 0x1A); + writeReg(0x43, 0x40); + + writeReg(0xFF, 0x00); + writeReg(0x34, 0x03); + writeReg(0x35, 0x44); + + writeReg(0xFF, 0x01); + writeReg(0x31, 0x04); + writeReg(0x4B, 0x09); + writeReg(0x4C, 0x05); + writeReg(0x4D, 0x04); + + writeReg(0xFF, 0x00); + writeReg(0x44, 0x00); + writeReg(0x45, 0x20); + writeReg(0x47, 0x08); + writeReg(0x48, 0x28); + writeReg(0x67, 0x00); + writeReg(0x70, 0x04); + writeReg(0x71, 0x01); + writeReg(0x72, 0xFE); + writeReg(0x76, 0x00); + writeReg(0x77, 0x00); + + writeReg(0xFF, 0x01); + writeReg(0x0D, 0x01); + + writeReg(0xFF, 0x00); + writeReg(0x80, 0x01); + writeReg(0x01, 0xF8); + + writeReg(0xFF, 0x01); + writeReg(0x8E, 0x01); + writeReg(0x00, 0x01); + writeReg(0xFF, 0x00); + writeReg(0x80, 0x00); + + // -- VL53L0X_load_tuning_settings() end + + // "Set interrupt config to new sample ready" + // -- VL53L0X_SetGpioConfig() begin + + writeReg(SYSTEM_INTERRUPT_CONFIG_GPIO, 0x04); + writeReg(GPIO_HV_MUX_ACTIVE_HIGH, readReg(GPIO_HV_MUX_ACTIVE_HIGH) & ~0x10); // active low + writeReg(SYSTEM_INTERRUPT_CLEAR, 0x01); + + // -- VL53L0X_SetGpioConfig() end + + measurement_timing_budget_us = getMeasurementTimingBudget(); + + // "Disable MSRC and TCC by default" + // MSRC = Minimum Signal Rate Check + // TCC = Target CentreCheck + // -- VL53L0X_SetSequenceStepEnable() begin + + writeReg(SYSTEM_SEQUENCE_CONFIG, 0xE8); + + // -- VL53L0X_SetSequenceStepEnable() end + + // "Recalculate timing budget" + setMeasurementTimingBudget(measurement_timing_budget_us); + + // VL53L0X_StaticInit() end + + // VL53L0X_PerformRefCalibration() begin (VL53L0X_perform_ref_calibration()) + + // -- VL53L0X_perform_vhv_calibration() begin + + writeReg(SYSTEM_SEQUENCE_CONFIG, 0x01); + if (!performSingleRefCalibration(0x40)) { return false; } + + // -- VL53L0X_perform_vhv_calibration() end + + // -- VL53L0X_perform_phase_calibration() begin + + writeReg(SYSTEM_SEQUENCE_CONFIG, 0x02); + if (!performSingleRefCalibration(0x00)) { return false; } + + // -- VL53L0X_perform_phase_calibration() end + + // "restore the previous Sequence Config" + writeReg(SYSTEM_SEQUENCE_CONFIG, 0xE8); + + // VL53L0X_PerformRefCalibration() end + + return true; +} + +// Write an 8-bit register +void VL53L0X::writeReg(uint8_t reg, uint8_t value) +{ + Wire.beginTransmission(address); + Wire.write(reg); + Wire.write(value); + last_status = Wire.endTransmission(); +} + +// Write a 16-bit register +void VL53L0X::writeReg16Bit(uint8_t reg, uint16_t value) +{ + Wire.beginTransmission(address); + Wire.write(reg); + Wire.write((value >> 8) & 0xFF); // value high byte + Wire.write( value & 0xFF); // value low byte + last_status = Wire.endTransmission(); +} + +// Write a 32-bit register +void VL53L0X::writeReg32Bit(uint8_t reg, uint32_t value) +{ + Wire.beginTransmission(address); + Wire.write(reg); + Wire.write((value >> 24) & 0xFF); // value highest byte + Wire.write((value >> 16) & 0xFF); + Wire.write((value >> 8) & 0xFF); + Wire.write( value & 0xFF); // value lowest byte + last_status = Wire.endTransmission(); +} + +// Read an 8-bit register +uint8_t VL53L0X::readReg(uint8_t reg) +{ + uint8_t value; + + Wire.beginTransmission(address); + Wire.write(reg); + last_status = Wire.endTransmission(); + + Wire.requestFrom(address, (uint8_t)1); + value = Wire.read(); + + return value; +} + +// Read a 16-bit register +uint16_t VL53L0X::readReg16Bit(uint8_t reg) +{ + uint16_t value; + + Wire.beginTransmission(address); + Wire.write(reg); + last_status = Wire.endTransmission(); + + Wire.requestFrom(address, (uint8_t)2); + value = (uint16_t)Wire.read() << 8; // value high byte + value |= Wire.read(); // value low byte + + return value; +} + +// Read a 32-bit register +uint32_t VL53L0X::readReg32Bit(uint8_t reg) +{ + uint32_t value; + + Wire.beginTransmission(address); + Wire.write(reg); + last_status = Wire.endTransmission(); + + Wire.requestFrom(address, (uint8_t)4); + value = (uint32_t)Wire.read() << 24; // value highest byte + value |= (uint32_t)Wire.read() << 16; + value |= (uint16_t)Wire.read() << 8; + value |= Wire.read(); // value lowest byte + + return value; +} + +// Write an arbitrary number of bytes from the given array to the sensor, +// starting at the given register +void VL53L0X::writeMulti(uint8_t reg, uint8_t const * src, uint8_t count) +{ + Wire.beginTransmission(address); + Wire.write(reg); + + while (count-- > 0) + { + Wire.write(*(src++)); + } + + last_status = Wire.endTransmission(); +} + +// Read an arbitrary number of bytes from the sensor, starting at the given +// register, into the given array +void VL53L0X::readMulti(uint8_t reg, uint8_t * dst, uint8_t count) +{ + Wire.beginTransmission(address); + Wire.write(reg); + last_status = Wire.endTransmission(); + + Wire.requestFrom(address, count); + + while (count-- > 0) + { + *(dst++) = Wire.read(); + } +} + +// Set the return signal rate limit check value in units of MCPS (mega counts +// per second). "This represents the amplitude of the signal reflected from the +// target and detected by the device"; setting this limit presumably determines +// the minimum measurement necessary for the sensor to report a valid reading. +// Setting a lower limit increases the potential range of the sensor but also +// seems to increase the likelihood of getting an inaccurate reading because of +// unwanted reflections from objects other than the intended target. +// Defaults to 0.25 MCPS as initialized by the ST API and this library. +bool VL53L0X::setSignalRateLimit(float limit_Mcps) +{ + if (limit_Mcps < 0 || limit_Mcps > 511.99) { return false; } + + // Q9.7 fixed point format (9 integer bits, 7 fractional bits) + writeReg16Bit(FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT, limit_Mcps * (1 << 7)); + return true; +} + +// Get the return signal rate limit check value in MCPS +float VL53L0X::getSignalRateLimit(void) +{ + return (float)readReg16Bit(FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT) / (1 << 7); +} + +// Set the measurement timing budget in microseconds, which is the time allowed +// for one measurement; the ST API and this library take care of splitting the +// timing budget among the sub-steps in the ranging sequence. A longer timing +// budget allows for more accurate measurements. Increasing the budget by a +// factor of N decreases the range measurement standard deviation by a factor of +// sqrt(N). Defaults to about 33 milliseconds; the minimum is 20 ms. +// based on VL53L0X_set_measurement_timing_budget_micro_seconds() +bool VL53L0X::setMeasurementTimingBudget(uint32_t budget_us) +{ + SequenceStepEnables enables; + SequenceStepTimeouts timeouts; + + uint16_t const StartOverhead = 1320; // note that this is different than the value in get_ + uint16_t const EndOverhead = 960; + uint16_t const MsrcOverhead = 660; + uint16_t const TccOverhead = 590; + uint16_t const DssOverhead = 690; + uint16_t const PreRangeOverhead = 660; + uint16_t const FinalRangeOverhead = 550; + + uint32_t const MinTimingBudget = 20000; + + if (budget_us < MinTimingBudget) { return false; } + + uint32_t used_budget_us = StartOverhead + EndOverhead; + + getSequenceStepEnables(&enables); + getSequenceStepTimeouts(&enables, &timeouts); + + if (enables.tcc) + { + used_budget_us += (timeouts.msrc_dss_tcc_us + TccOverhead); + } + + if (enables.dss) + { + used_budget_us += 2 * (timeouts.msrc_dss_tcc_us + DssOverhead); + } + else if (enables.msrc) + { + used_budget_us += (timeouts.msrc_dss_tcc_us + MsrcOverhead); + } + + if (enables.pre_range) + { + used_budget_us += (timeouts.pre_range_us + PreRangeOverhead); + } + + if (enables.final_range) + { + used_budget_us += FinalRangeOverhead; + + // "Note that the final range timeout is determined by the timing + // budget and the sum of all other timeouts within the sequence. + // If there is no room for the final range timeout, then an error + // will be set. Otherwise the remaining time will be applied to + // the final range." + + if (used_budget_us > budget_us) + { + // "Requested timeout too big." + return false; + } + + uint32_t final_range_timeout_us = budget_us - used_budget_us; + + // set_sequence_step_timeout() begin + // (SequenceStepId == VL53L0X_SEQUENCESTEP_FINAL_RANGE) + + // "For the final range timeout, the pre-range timeout + // must be added. To do this both final and pre-range + // timeouts must be expressed in macro periods MClks + // because they have different vcsel periods." + + uint16_t final_range_timeout_mclks = + timeoutMicrosecondsToMclks(final_range_timeout_us, + timeouts.final_range_vcsel_period_pclks); + + if (enables.pre_range) + { + final_range_timeout_mclks += timeouts.pre_range_mclks; + } + + writeReg16Bit(FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI, + encodeTimeout(final_range_timeout_mclks)); + + // set_sequence_step_timeout() end + + measurement_timing_budget_us = budget_us; // store for internal reuse + } + return true; +} + +// Get the measurement timing budget in microseconds +// based on VL53L0X_get_measurement_timing_budget_micro_seconds() +// in us +uint32_t VL53L0X::getMeasurementTimingBudget(void) +{ + SequenceStepEnables enables; + SequenceStepTimeouts timeouts; + + uint16_t const StartOverhead = 1910; // note that this is different than the value in set_ + uint16_t const EndOverhead = 960; + uint16_t const MsrcOverhead = 660; + uint16_t const TccOverhead = 590; + uint16_t const DssOverhead = 690; + uint16_t const PreRangeOverhead = 660; + uint16_t const FinalRangeOverhead = 550; + + // "Start and end overhead times always present" + uint32_t budget_us = StartOverhead + EndOverhead; + + getSequenceStepEnables(&enables); + getSequenceStepTimeouts(&enables, &timeouts); + + if (enables.tcc) + { + budget_us += (timeouts.msrc_dss_tcc_us + TccOverhead); + } + + if (enables.dss) + { + budget_us += 2 * (timeouts.msrc_dss_tcc_us + DssOverhead); + } + else if (enables.msrc) + { + budget_us += (timeouts.msrc_dss_tcc_us + MsrcOverhead); + } + + if (enables.pre_range) + { + budget_us += (timeouts.pre_range_us + PreRangeOverhead); + } + + if (enables.final_range) + { + budget_us += (timeouts.final_range_us + FinalRangeOverhead); + } + + measurement_timing_budget_us = budget_us; // store for internal reuse + return budget_us; +} + +// Set the VCSEL (vertical cavity surface emitting laser) pulse period for the +// given period type (pre-range or final range) to the given value in PCLKs. +// Longer periods seem to increase the potential range of the sensor. +// Valid values are (even numbers only): +// pre: 12 to 18 (initialized default: 14) +// final: 8 to 14 (initialized default: 10) +// based on VL53L0X_set_vcsel_pulse_period() +bool VL53L0X::setVcselPulsePeriod(vcselPeriodType type, uint8_t period_pclks) +{ + uint8_t vcsel_period_reg = encodeVcselPeriod(period_pclks); + + SequenceStepEnables enables; + SequenceStepTimeouts timeouts; + + getSequenceStepEnables(&enables); + getSequenceStepTimeouts(&enables, &timeouts); + + // "Apply specific settings for the requested clock period" + // "Re-calculate and apply timeouts, in macro periods" + + // "When the VCSEL period for the pre or final range is changed, + // the corresponding timeout must be read from the device using + // the current VCSEL period, then the new VCSEL period can be + // applied. The timeout then must be written back to the device + // using the new VCSEL period. + // + // For the MSRC timeout, the same applies - this timeout being + // dependant on the pre-range vcsel period." + + + if (type == VcselPeriodPreRange) + { + // "Set phase check limits" + switch (period_pclks) + { + case 12: + writeReg(PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 0x18); + break; + + case 14: + writeReg(PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 0x30); + break; + + case 16: + writeReg(PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 0x40); + break; + + case 18: + writeReg(PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 0x50); + break; + + default: + // invalid period + return false; + } + writeReg(PRE_RANGE_CONFIG_VALID_PHASE_LOW, 0x08); + + // apply new VCSEL period + writeReg(PRE_RANGE_CONFIG_VCSEL_PERIOD, vcsel_period_reg); + + // update timeouts + + // set_sequence_step_timeout() begin + // (SequenceStepId == VL53L0X_SEQUENCESTEP_PRE_RANGE) + + uint16_t new_pre_range_timeout_mclks = + timeoutMicrosecondsToMclks(timeouts.pre_range_us, period_pclks); + + writeReg16Bit(PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI, + encodeTimeout(new_pre_range_timeout_mclks)); + + // set_sequence_step_timeout() end + + // set_sequence_step_timeout() begin + // (SequenceStepId == VL53L0X_SEQUENCESTEP_MSRC) + + uint16_t new_msrc_timeout_mclks = + timeoutMicrosecondsToMclks(timeouts.msrc_dss_tcc_us, period_pclks); + + writeReg(MSRC_CONFIG_TIMEOUT_MACROP, + (new_msrc_timeout_mclks > 256) ? 255 : (new_msrc_timeout_mclks - 1)); + + // set_sequence_step_timeout() end + } + else if (type == VcselPeriodFinalRange) + { + switch (period_pclks) + { + case 8: + writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 0x10); + writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 0x08); + writeReg(GLOBAL_CONFIG_VCSEL_WIDTH, 0x02); + writeReg(ALGO_PHASECAL_CONFIG_TIMEOUT, 0x0C); + writeReg(0xFF, 0x01); + writeReg(ALGO_PHASECAL_LIM, 0x30); + writeReg(0xFF, 0x00); + break; + + case 10: + writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 0x28); + writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 0x08); + writeReg(GLOBAL_CONFIG_VCSEL_WIDTH, 0x03); + writeReg(ALGO_PHASECAL_CONFIG_TIMEOUT, 0x09); + writeReg(0xFF, 0x01); + writeReg(ALGO_PHASECAL_LIM, 0x20); + writeReg(0xFF, 0x00); + break; + + case 12: + writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 0x38); + writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 0x08); + writeReg(GLOBAL_CONFIG_VCSEL_WIDTH, 0x03); + writeReg(ALGO_PHASECAL_CONFIG_TIMEOUT, 0x08); + writeReg(0xFF, 0x01); + writeReg(ALGO_PHASECAL_LIM, 0x20); + writeReg(0xFF, 0x00); + break; + + case 14: + writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 0x48); + writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 0x08); + writeReg(GLOBAL_CONFIG_VCSEL_WIDTH, 0x03); + writeReg(ALGO_PHASECAL_CONFIG_TIMEOUT, 0x07); + writeReg(0xFF, 0x01); + writeReg(ALGO_PHASECAL_LIM, 0x20); + writeReg(0xFF, 0x00); + break; + + default: + // invalid period + return false; + } + + // apply new VCSEL period + writeReg(FINAL_RANGE_CONFIG_VCSEL_PERIOD, vcsel_period_reg); + + // update timeouts + + // set_sequence_step_timeout() begin + // (SequenceStepId == VL53L0X_SEQUENCESTEP_FINAL_RANGE) + + // "For the final range timeout, the pre-range timeout + // must be added. To do this both final and pre-range + // timeouts must be expressed in macro periods MClks + // because they have different vcsel periods." + + uint16_t new_final_range_timeout_mclks = + timeoutMicrosecondsToMclks(timeouts.final_range_us, period_pclks); + + if (enables.pre_range) + { + new_final_range_timeout_mclks += timeouts.pre_range_mclks; + } + + writeReg16Bit(FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI, + encodeTimeout(new_final_range_timeout_mclks)); + + // set_sequence_step_timeout end + } + else + { + // invalid type + return false; + } + + // "Finally, the timing budget must be re-applied" + + setMeasurementTimingBudget(measurement_timing_budget_us); + + // "Perform the phase calibration. This is needed after changing on vcsel period." + // VL53L0X_perform_phase_calibration() begin + + uint8_t sequence_config = readReg(SYSTEM_SEQUENCE_CONFIG); + writeReg(SYSTEM_SEQUENCE_CONFIG, 0x02); + performSingleRefCalibration(0x0); + writeReg(SYSTEM_SEQUENCE_CONFIG, sequence_config); + + // VL53L0X_perform_phase_calibration() end + + return true; +} + +// Get the VCSEL pulse period in PCLKs for the given period type. +// based on VL53L0X_get_vcsel_pulse_period() +uint8_t VL53L0X::getVcselPulsePeriod(vcselPeriodType type) +{ + if (type == VcselPeriodPreRange) + { + return decodeVcselPeriod(readReg(PRE_RANGE_CONFIG_VCSEL_PERIOD)); + } + else if (type == VcselPeriodFinalRange) + { + return decodeVcselPeriod(readReg(FINAL_RANGE_CONFIG_VCSEL_PERIOD)); + } + else { return 255; } +} + +// Start continuous ranging measurements. If period_ms (optional) is 0 or not +// given, continuous back-to-back mode is used (the sensor takes measurements as +// often as possible); otherwise, continuous timed mode is used, with the given +// inter-measurement period in milliseconds determining how often the sensor +// takes a measurement. +// based on VL53L0X_StartMeasurement() +void VL53L0X::startContinuous(uint32_t period_ms) +{ + writeReg(0x80, 0x01); + writeReg(0xFF, 0x01); + writeReg(0x00, 0x00); + writeReg(0x91, stop_variable); + writeReg(0x00, 0x01); + writeReg(0xFF, 0x00); + writeReg(0x80, 0x00); + + if (period_ms != 0) + { + // continuous timed mode + + // VL53L0X_SetInterMeasurementPeriodMilliSeconds() begin + + uint16_t osc_calibrate_val = readReg16Bit(OSC_CALIBRATE_VAL); + + if (osc_calibrate_val != 0) + { + period_ms *= osc_calibrate_val; + } + + writeReg32Bit(SYSTEM_INTERMEASUREMENT_PERIOD, period_ms); + + // VL53L0X_SetInterMeasurementPeriodMilliSeconds() end + + writeReg(SYSRANGE_START, 0x04); // VL53L0X_REG_SYSRANGE_MODE_TIMED + } + else + { + // continuous back-to-back mode + writeReg(SYSRANGE_START, 0x02); // VL53L0X_REG_SYSRANGE_MODE_BACKTOBACK + } +} + +// Stop continuous measurements +// based on VL53L0X_StopMeasurement() +void VL53L0X::stopContinuous(void) +{ + writeReg(SYSRANGE_START, 0x01); // VL53L0X_REG_SYSRANGE_MODE_SINGLESHOT + + writeReg(0xFF, 0x01); + writeReg(0x00, 0x00); + writeReg(0x91, 0x00); + writeReg(0x00, 0x01); + writeReg(0xFF, 0x00); +} + +// Returns a range reading in millimeters when continuous mode is active +// (readRangeSingleMillimeters() also calls this function after starting a +// single-shot range measurement) +uint16_t VL53L0X::readRangeContinuousMillimeters(void) +{ + startTimeout(); + while ((readReg(RESULT_INTERRUPT_STATUS) & 0x07) == 0) + { + if (checkTimeoutExpired()) + { + did_timeout = true; + return 65535; + } + } + + // assumptions: Linearity Corrective Gain is 1000 (default); + // fractional ranging is not enabled + uint16_t range = readReg16Bit(RESULT_RANGE_STATUS + 10); + + writeReg(SYSTEM_INTERRUPT_CLEAR, 0x01); + + return range; +} + +// Performs a single-shot range measurement and returns the reading in +// millimeters +// based on VL53L0X_PerformSingleRangingMeasurement() +uint16_t VL53L0X::readRangeSingleMillimeters(void) +{ + writeReg(0x80, 0x01); + writeReg(0xFF, 0x01); + writeReg(0x00, 0x00); + writeReg(0x91, stop_variable); + writeReg(0x00, 0x01); + writeReg(0xFF, 0x00); + writeReg(0x80, 0x00); + + writeReg(SYSRANGE_START, 0x01); + + // "Wait until start bit has been cleared" + startTimeout(); + while (readReg(SYSRANGE_START) & 0x01) + { + if (checkTimeoutExpired()) + { + did_timeout = true; + return 65535; + } + } + + return readRangeContinuousMillimeters(); +} + +// Did a timeout occur in one of the read functions since the last call to +// timeoutOccurred()? +bool VL53L0X::timeoutOccurred() +{ + bool tmp = did_timeout; + did_timeout = false; + return tmp; +} + +// Private Methods ///////////////////////////////////////////////////////////// + +// Get reference SPAD (single photon avalanche diode) count and type +// based on VL53L0X_get_info_from_device(), +// but only gets reference SPAD count and type +bool VL53L0X::getSpadInfo(uint8_t * count, bool * type_is_aperture) +{ + uint8_t tmp; + + writeReg(0x80, 0x01); + writeReg(0xFF, 0x01); + writeReg(0x00, 0x00); + + writeReg(0xFF, 0x06); + writeReg(0x83, readReg(0x83) | 0x04); + writeReg(0xFF, 0x07); + writeReg(0x81, 0x01); + + writeReg(0x80, 0x01); + + writeReg(0x94, 0x6b); + writeReg(0x83, 0x00); + startTimeout(); + while (readReg(0x83) == 0x00) + { + if (checkTimeoutExpired()) { return false; } + } + writeReg(0x83, 0x01); + tmp = readReg(0x92); + + *count = tmp & 0x7f; + *type_is_aperture = (tmp >> 7) & 0x01; + + writeReg(0x81, 0x00); + writeReg(0xFF, 0x06); + writeReg(0x83, readReg(0x83) & ~0x04); + writeReg(0xFF, 0x01); + writeReg(0x00, 0x01); + + writeReg(0xFF, 0x00); + writeReg(0x80, 0x00); + + return true; +} + +// Get sequence step enables +// based on VL53L0X_GetSequenceStepEnables() +void VL53L0X::getSequenceStepEnables(SequenceStepEnables * enables) +{ + uint8_t sequence_config = readReg(SYSTEM_SEQUENCE_CONFIG); + + enables->tcc = (sequence_config >> 4) & 0x1; + enables->dss = (sequence_config >> 3) & 0x1; + enables->msrc = (sequence_config >> 2) & 0x1; + enables->pre_range = (sequence_config >> 6) & 0x1; + enables->final_range = (sequence_config >> 7) & 0x1; +} + +// Get sequence step timeouts +// based on get_sequence_step_timeout(), +// but gets all timeouts instead of just the requested one, and also stores +// intermediate values +void VL53L0X::getSequenceStepTimeouts(SequenceStepEnables const * enables, SequenceStepTimeouts * timeouts) +{ + timeouts->pre_range_vcsel_period_pclks = getVcselPulsePeriod(VcselPeriodPreRange); + + timeouts->msrc_dss_tcc_mclks = readReg(MSRC_CONFIG_TIMEOUT_MACROP) + 1; + timeouts->msrc_dss_tcc_us = + timeoutMclksToMicroseconds(timeouts->msrc_dss_tcc_mclks, + timeouts->pre_range_vcsel_period_pclks); + + timeouts->pre_range_mclks = + decodeTimeout(readReg16Bit(PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI)); + timeouts->pre_range_us = + timeoutMclksToMicroseconds(timeouts->pre_range_mclks, + timeouts->pre_range_vcsel_period_pclks); + + timeouts->final_range_vcsel_period_pclks = getVcselPulsePeriod(VcselPeriodFinalRange); + + timeouts->final_range_mclks = + decodeTimeout(readReg16Bit(FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI)); + + if (enables->pre_range) + { + timeouts->final_range_mclks -= timeouts->pre_range_mclks; + } + + timeouts->final_range_us = + timeoutMclksToMicroseconds(timeouts->final_range_mclks, + timeouts->final_range_vcsel_period_pclks); +} + +// Decode sequence step timeout in MCLKs from register value +// based on VL53L0X_decode_timeout() +// Note: the original function returned a uint32_t, but the return value is +// always stored in a uint16_t. +uint16_t VL53L0X::decodeTimeout(uint16_t reg_val) +{ + // format: "(LSByte * 2^MSByte) + 1" + return (uint16_t)((reg_val & 0x00FF) << + (uint16_t)((reg_val & 0xFF00) >> 8)) + 1; +} + +// Encode sequence step timeout register value from timeout in MCLKs +// based on VL53L0X_encode_timeout() +// Note: the original function took a uint16_t, but the argument passed to it +// is always a uint16_t. +uint16_t VL53L0X::encodeTimeout(uint16_t timeout_mclks) +{ + // format: "(LSByte * 2^MSByte) + 1" + + uint32_t ls_byte = 0; + uint16_t ms_byte = 0; + + if (timeout_mclks > 0) + { + ls_byte = timeout_mclks - 1; + + while ((ls_byte & 0xFFFFFF00) > 0) + { + ls_byte >>= 1; + ms_byte++; + } + + return (ms_byte << 8) | (ls_byte & 0xFF); + } + else { return 0; } +} + +// Convert sequence step timeout from MCLKs to microseconds with given VCSEL period in PCLKs +// based on VL53L0X_calc_timeout_us() +uint32_t VL53L0X::timeoutMclksToMicroseconds(uint16_t timeout_period_mclks, uint8_t vcsel_period_pclks) +{ + uint32_t macro_period_ns = calcMacroPeriod(vcsel_period_pclks); + + return ((timeout_period_mclks * macro_period_ns) + (macro_period_ns / 2)) / 1000; +} + +// Convert sequence step timeout from microseconds to MCLKs with given VCSEL period in PCLKs +// based on VL53L0X_calc_timeout_mclks() +uint32_t VL53L0X::timeoutMicrosecondsToMclks(uint32_t timeout_period_us, uint8_t vcsel_period_pclks) +{ + uint32_t macro_period_ns = calcMacroPeriod(vcsel_period_pclks); + + return (((timeout_period_us * 1000) + (macro_period_ns / 2)) / macro_period_ns); +} + + +// based on VL53L0X_perform_single_ref_calibration() +bool VL53L0X::performSingleRefCalibration(uint8_t vhv_init_byte) +{ + writeReg(SYSRANGE_START, 0x01 | vhv_init_byte); // VL53L0X_REG_SYSRANGE_MODE_START_STOP + + startTimeout(); + while ((readReg(RESULT_INTERRUPT_STATUS) & 0x07) == 0) + { + if (checkTimeoutExpired()) { return false; } + } + + writeReg(SYSTEM_INTERRUPT_CLEAR, 0x01); + + writeReg(SYSRANGE_START, 0x00); + + return true; +} diff --git a/lib/vl53l0x-arduino-1.02/VL53L0X.h b/lib/vl53l0x-arduino-1.02/VL53L0X.h new file mode 100755 index 000000000..b531ff96a --- /dev/null +++ b/lib/vl53l0x-arduino-1.02/VL53L0X.h @@ -0,0 +1,176 @@ +#ifndef VL53L0X_h +#define VL53L0X_h + +#include + +class VL53L0X +{ + public: + // register addresses from API vl53l0x_device.h (ordered as listed there) + enum regAddr + { + SYSRANGE_START = 0x00, + + SYSTEM_THRESH_HIGH = 0x0C, + SYSTEM_THRESH_LOW = 0x0E, + + SYSTEM_SEQUENCE_CONFIG = 0x01, + SYSTEM_RANGE_CONFIG = 0x09, + SYSTEM_INTERMEASUREMENT_PERIOD = 0x04, + + SYSTEM_INTERRUPT_CONFIG_GPIO = 0x0A, + + GPIO_HV_MUX_ACTIVE_HIGH = 0x84, + + SYSTEM_INTERRUPT_CLEAR = 0x0B, + + RESULT_INTERRUPT_STATUS = 0x13, + RESULT_RANGE_STATUS = 0x14, + + RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN = 0xBC, + RESULT_CORE_RANGING_TOTAL_EVENTS_RTN = 0xC0, + RESULT_CORE_AMBIENT_WINDOW_EVENTS_REF = 0xD0, + RESULT_CORE_RANGING_TOTAL_EVENTS_REF = 0xD4, + RESULT_PEAK_SIGNAL_RATE_REF = 0xB6, + + ALGO_PART_TO_PART_RANGE_OFFSET_MM = 0x28, + + I2C_SLAVE_DEVICE_ADDRESS = 0x8A, + + MSRC_CONFIG_CONTROL = 0x60, + + PRE_RANGE_CONFIG_MIN_SNR = 0x27, + PRE_RANGE_CONFIG_VALID_PHASE_LOW = 0x56, + PRE_RANGE_CONFIG_VALID_PHASE_HIGH = 0x57, + PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT = 0x64, + + FINAL_RANGE_CONFIG_MIN_SNR = 0x67, + FINAL_RANGE_CONFIG_VALID_PHASE_LOW = 0x47, + FINAL_RANGE_CONFIG_VALID_PHASE_HIGH = 0x48, + FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT = 0x44, + + PRE_RANGE_CONFIG_SIGMA_THRESH_HI = 0x61, + PRE_RANGE_CONFIG_SIGMA_THRESH_LO = 0x62, + + PRE_RANGE_CONFIG_VCSEL_PERIOD = 0x50, + PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI = 0x51, + PRE_RANGE_CONFIG_TIMEOUT_MACROP_LO = 0x52, + + SYSTEM_HISTOGRAM_BIN = 0x81, + HISTOGRAM_CONFIG_INITIAL_PHASE_SELECT = 0x33, + HISTOGRAM_CONFIG_READOUT_CTRL = 0x55, + + FINAL_RANGE_CONFIG_VCSEL_PERIOD = 0x70, + FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI = 0x71, + FINAL_RANGE_CONFIG_TIMEOUT_MACROP_LO = 0x72, + CROSSTALK_COMPENSATION_PEAK_RATE_MCPS = 0x20, + + MSRC_CONFIG_TIMEOUT_MACROP = 0x46, + + SOFT_RESET_GO2_SOFT_RESET_N = 0xBF, + IDENTIFICATION_MODEL_ID = 0xC0, + IDENTIFICATION_REVISION_ID = 0xC2, + + OSC_CALIBRATE_VAL = 0xF8, + + GLOBAL_CONFIG_VCSEL_WIDTH = 0x32, + GLOBAL_CONFIG_SPAD_ENABLES_REF_0 = 0xB0, + GLOBAL_CONFIG_SPAD_ENABLES_REF_1 = 0xB1, + GLOBAL_CONFIG_SPAD_ENABLES_REF_2 = 0xB2, + GLOBAL_CONFIG_SPAD_ENABLES_REF_3 = 0xB3, + GLOBAL_CONFIG_SPAD_ENABLES_REF_4 = 0xB4, + GLOBAL_CONFIG_SPAD_ENABLES_REF_5 = 0xB5, + + GLOBAL_CONFIG_REF_EN_START_SELECT = 0xB6, + DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD = 0x4E, + DYNAMIC_SPAD_REF_EN_START_OFFSET = 0x4F, + POWER_MANAGEMENT_GO1_POWER_FORCE = 0x80, + + VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV = 0x89, + + ALGO_PHASECAL_LIM = 0x30, + ALGO_PHASECAL_CONFIG_TIMEOUT = 0x30, + }; + + enum vcselPeriodType { VcselPeriodPreRange, VcselPeriodFinalRange }; + + uint8_t last_status; // status of last I2C transmission + + VL53L0X(void); + + void setAddress(uint8_t new_addr); + inline uint8_t getAddress(void) { return address; } + + bool init(bool io_2v8 = true); + + void writeReg(uint8_t reg, uint8_t value); + void writeReg16Bit(uint8_t reg, uint16_t value); + void writeReg32Bit(uint8_t reg, uint32_t value); + uint8_t readReg(uint8_t reg); + uint16_t readReg16Bit(uint8_t reg); + uint32_t readReg32Bit(uint8_t reg); + + void writeMulti(uint8_t reg, uint8_t const * src, uint8_t count); + void readMulti(uint8_t reg, uint8_t * dst, uint8_t count); + + bool setSignalRateLimit(float limit_Mcps); + float getSignalRateLimit(void); + + bool setMeasurementTimingBudget(uint32_t budget_us); + uint32_t getMeasurementTimingBudget(void); + + bool setVcselPulsePeriod(vcselPeriodType type, uint8_t period_pclks); + uint8_t getVcselPulsePeriod(vcselPeriodType type); + + void startContinuous(uint32_t period_ms = 0); + void stopContinuous(void); + uint16_t readRangeContinuousMillimeters(void); + uint16_t readRangeSingleMillimeters(void); + + inline void setTimeout(uint16_t timeout) { io_timeout = timeout; } + inline uint16_t getTimeout(void) { return io_timeout; } + bool timeoutOccurred(void); + + private: + // TCC: Target CentreCheck + // MSRC: Minimum Signal Rate Check + // DSS: Dynamic Spad Selection + + struct SequenceStepEnables + { + boolean tcc, msrc, dss, pre_range, final_range; + }; + + struct SequenceStepTimeouts + { + uint16_t pre_range_vcsel_period_pclks, final_range_vcsel_period_pclks; + + uint16_t msrc_dss_tcc_mclks, pre_range_mclks, final_range_mclks; + uint32_t msrc_dss_tcc_us, pre_range_us, final_range_us; + }; + + uint8_t address; + uint16_t io_timeout; + bool did_timeout; + uint16_t timeout_start_ms; + + uint8_t stop_variable; // read by init and used when starting measurement; is StopVariable field of VL53L0X_DevData_t structure in API + uint32_t measurement_timing_budget_us; + + bool getSpadInfo(uint8_t * count, bool * type_is_aperture); + + void getSequenceStepEnables(SequenceStepEnables * enables); + void getSequenceStepTimeouts(SequenceStepEnables const * enables, SequenceStepTimeouts * timeouts); + + bool performSingleRefCalibration(uint8_t vhv_init_byte); + + static uint16_t decodeTimeout(uint16_t value); + static uint16_t encodeTimeout(uint16_t timeout_mclks); + static uint32_t timeoutMclksToMicroseconds(uint16_t timeout_period_mclks, uint8_t vcsel_period_pclks); + static uint32_t timeoutMicrosecondsToMclks(uint32_t timeout_period_us, uint8_t vcsel_period_pclks); +}; + +#endif + + + diff --git a/lib/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino b/lib/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino new file mode 100755 index 000000000..33fcd05c4 --- /dev/null +++ b/lib/vl53l0x-arduino-1.02/examples/Continuous/Continuous.ino @@ -0,0 +1,33 @@ +/* This example shows how to use continuous mode to take +range measurements with the VL53L0X. It is based on +vl53l0x_ContinuousRanging_Example.c from the VL53L0X API. + +The range readings are in units of mm. */ + +#include +#include + +VL53L0X sensor; + +void setup() +{ + Serial.begin(9600); + Wire.begin(); + + sensor.init(); + sensor.setTimeout(500); + + // Start continuous back-to-back mode (take readings as + // fast as possible). To use continuous timed mode + // instead, provide a desired inter-measurement period in + // ms (e.g. sensor.startContinuous(100)). + sensor.startContinuous(); +} + +void loop() +{ + Serial.print(sensor.readRangeContinuousMillimeters()); + if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); } + + Serial.println(); +} diff --git a/lib/vl53l0x-arduino-1.02/examples/Single/Single.ino b/lib/vl53l0x-arduino-1.02/examples/Single/Single.ino new file mode 100755 index 000000000..9f24463fc --- /dev/null +++ b/lib/vl53l0x-arduino-1.02/examples/Single/Single.ino @@ -0,0 +1,65 @@ +/* This example shows how to get single-shot range + measurements from the VL53L0X. The sensor can optionally be + configured with different ranging profiles, as described in + the VL53L0X API user manual, to get better performance for + a certain application. This code is based on the four + "SingleRanging" examples in the VL53L0X API. + + The range readings are in units of mm. */ + +#include +#include + +VL53L0X sensor; + + +// Uncomment this line to use long range mode. This +// increases the sensitivity of the sensor and extends its +// potential range, but increases the likelihood of getting +// an inaccurate reading because of reflections from objects +// other than the intended target. It works best in dark +// conditions. + +//#define LONG_RANGE + + +// Uncomment ONE of these two lines to get +// - higher speed at the cost of lower accuracy OR +// - higher accuracy at the cost of lower speed + +//#define HIGH_SPEED +//#define HIGH_ACCURACY + + +void setup() +{ + Serial.begin(9600); + Wire.begin(); + + sensor.init(); + sensor.setTimeout(500); + +#if defined LONG_RANGE + // lower the return signal rate limit (default is 0.25 MCPS) + sensor.setSignalRateLimit(0.1); + // increase laser pulse periods (defaults are 14 and 10 PCLKs) + sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18); + sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14); +#endif + +#if defined HIGH_SPEED + // reduce timing budget to 20 ms (default is about 33 ms) + sensor.setMeasurementTimingBudget(20000); +#elif defined HIGH_ACCURACY + // increase timing budget to 200 ms + sensor.setMeasurementTimingBudget(200000); +#endif +} + +void loop() +{ + Serial.print(sensor.readRangeSingleMillimeters()); + if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); } + + Serial.println(); +} diff --git a/lib/vl53l0x-arduino-1.02/keywords.txt b/lib/vl53l0x-arduino-1.02/keywords.txt new file mode 100755 index 000000000..437add908 --- /dev/null +++ b/lib/vl53l0x-arduino-1.02/keywords.txt @@ -0,0 +1,90 @@ +VL53L0X KEYWORD1 + +setAddress KEYWORD2 +getAddress KEYWORD2 +init KEYWORD2 +writeReg KEYWORD2 +writeReg16Bit KEYWORD2 +writeReg32Bit KEYWORD2 +readReg KEYWORD2 +readReg16Bit KEYWORD2 +readReg32Bit KEYWORD2 +writeMulti KEYWORD2 +readMulti KEYWORD2 +setSignalRateLimit KEYWORD2 +getSignalRateLimit KEYWORD2 +setMeasurementTimingBudget KEYWORD2 +getMeasurementTimingBudget KEYWORD2 +setVcselPulsePeriod KEYWORD2 +getVcselPulsePeriod KEYWORD2 +startContinuous KEYWORD2 +stopContinuous KEYWORD2 +readRangeContinuousMillimeters KEYWORD2 +readRangeSingleMillimeters KEYWORD2 +setTimeout KEYWORD2 +getTimeout KEYWORD2 +timeoutOccurred KEYWORD2 + +SYSRANGE_START LITERAL1 +SYSTEM_THRESH_HIGH LITERAL1 +SYSTEM_THRESH_LOW LITERAL1 +SYSTEM_SEQUENCE_CONFIG LITERAL1 +SYSTEM_RANGE_CONFIG LITERAL1 +SYSTEM_INTERMEASUREMENT_PERIOD LITERAL1 +SYSTEM_INTERRUPT_CONFIG_GPIO LITERAL1 +GPIO_HV_MUX_ACTIVE_HIGH LITERAL1 +SYSTEM_INTERRUPT_CLEAR LITERAL1 +RESULT_INTERRUPT_STATUS LITERAL1 +RESULT_RANGE_STATUS LITERAL1 +RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN LITERAL1 +RESULT_CORE_RANGING_TOTAL_EVENTS_RTN LITERAL1 +RESULT_CORE_AMBIENT_WINDOW_EVENTS_REF LITERAL1 +RESULT_CORE_RANGING_TOTAL_EVENTS_REF LITERAL1 +RESULT_PEAK_SIGNAL_RATE_REF LITERAL1 +ALGO_PART_TO_PART_RANGE_OFFSET_MM LITERAL1 +I2C_SLAVE_DEVICE_ADDRESS LITERAL1 +MSRC_CONFIG_CONTROL LITERAL1 +PRE_RANGE_CONFIG_MIN_SNR LITERAL1 +PRE_RANGE_CONFIG_VALID_PHASE_LOW LITERAL1 +PRE_RANGE_CONFIG_VALID_PHASE_HIGH LITERAL1 +PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT LITERAL1 +FINAL_RANGE_CONFIG_MIN_SNR LITERAL1 +FINAL_RANGE_CONFIG_VALID_PHASE_LOW LITERAL1 +FINAL_RANGE_CONFIG_VALID_PHASE_HIGH LITERAL1 +FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT LITERAL1 +PRE_RANGE_CONFIG_SIGMA_THRESH_HI LITERAL1 +PRE_RANGE_CONFIG_SIGMA_THRESH_LO LITERAL1 +PRE_RANGE_CONFIG_VCSEL_PERIOD LITERAL1 +PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI LITERAL1 +PRE_RANGE_CONFIG_TIMEOUT_MACROP_LO LITERAL1 +SYSTEM_HISTOGRAM_BIN LITERAL1 +HISTOGRAM_CONFIG_INITIAL_PHASE_SELECT LITERAL1 +HISTOGRAM_CONFIG_READOUT_CTRL LITERAL1 +FINAL_RANGE_CONFIG_VCSEL_PERIOD LITERAL1 +FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI LITERAL1 +FINAL_RANGE_CONFIG_TIMEOUT_MACROP_LO LITERAL1 +CROSSTALK_COMPENSATION_PEAK_RATE_MCPS LITERAL1 +MSRC_CONFIG_TIMEOUT_MACROP LITERAL1 +SOFT_RESET_GO2_SOFT_RESET_N LITERAL1 +IDENTIFICATION_MODEL_ID LITERAL1 +IDENTIFICATION_REVISION_ID LITERAL1 +OSC_CALIBRATE_VAL LITERAL1 +GLOBAL_CONFIG_VCSEL_WIDTH LITERAL1 +GLOBAL_CONFIG_SPAD_ENABLES_REF_0 LITERAL1 +GLOBAL_CONFIG_SPAD_ENABLES_REF_1 LITERAL1 +GLOBAL_CONFIG_SPAD_ENABLES_REF_2 LITERAL1 +GLOBAL_CONFIG_SPAD_ENABLES_REF_3 LITERAL1 +GLOBAL_CONFIG_SPAD_ENABLES_REF_4 LITERAL1 +GLOBAL_CONFIG_SPAD_ENABLES_REF_5 LITERAL1 +GLOBAL_CONFIG_REF_EN_START_SELECT LITERAL1 +DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD LITERAL1 +DYNAMIC_SPAD_REF_EN_START_OFFSET LITERAL1 +POWER_MANAGEMENT_GO1_POWER_FORCE LITERAL1 +VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV LITERAL1 +ALGO_PHASECAL_LIM LITERAL1 +ALGO_PHASECAL_CONFIG_TIMEOUT LITERAL1 + +VcselPeriodPreRange LITERAL1 +VcselPeriodFinalRange LITERAL1 + + diff --git a/lib/vl53l0x-arduino-1.02/library.properties b/lib/vl53l0x-arduino-1.02/library.properties new file mode 100755 index 000000000..43dd4d3a2 --- /dev/null +++ b/lib/vl53l0x-arduino-1.02/library.properties @@ -0,0 +1,9 @@ +name=VL53L0X +version=1.0.2 +author=Pololu +maintainer=Pololu +sentence=VL53L0X distance sensor library +paragraph=This is a library for the Arduino IDE that helps interface with ST's VL53L0X distance sensor. +category=Sensors +url=https://github.com/pololu/vl53l0x-arduino +architectures=* diff --git a/sonoff/xsns_45_vl53l0x.ino b/sonoff/xsns_45_vl53l0x.ino new file mode 100755 index 000000000..1f9248709 --- /dev/null +++ b/sonoff/xsns_45_vl53l0x.ino @@ -0,0 +1,162 @@ +/* + xsns_99_vl53l0x.ino - VL53L0X + + Copyright (C) 2018 Theo Arends and Gerhard Mutz + + 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_VL53L0X + +#include +#include "VL53L0X.h" +VL53L0X sensor; + +uint8_t vl53l0x_ready = 0; +uint16_t vl53l0x_distance; +uint16_t Vl53l0_buffer[5]; +uint8_t Vl53l0_index; + + +/********************************************************************************************/ + +void Vl53l0Detect() +{ + + if (!I2cDevice(0x29)) { + return; + } + + if (vl53l0x_ready) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("VL53L1X is ready")); + return; + } + + if (sensor.init()==true) { + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VL53L0X", sensor.getAddress()); + AddLog(LOG_LEVEL_DEBUG); + } else { + return; + } + + sensor.setTimeout(500); + + // Start continuous back-to-back mode (take readings as + // fast as possible). To use continuous timed mode + // instead, provide a desired inter-measurement period in + // ms (e.g. sensor.startContinuous(100)). + sensor.startContinuous(); + vl53l0x_ready = 1; + + Vl53l0_index=0; + +} + +#define D_UNIT_MILLIMETER "mm" + +#ifdef USE_WEBSERVER +const char HTTP_SNS_VL53L0X[] PROGMEM = + "{s}VL53L0X " D_DISTANCE "{m}%d" D_UNIT_MILLIMETER "{e}"; // {s} = , {m} = , {e} = +#endif // USE_WEBSERVER + +#define USE_VL_MEDIAN + +void Vl53l0Every_250MSecond() { + uint16_t tbuff[5],tmp; + uint8_t flag; + + if (!vl53l0x_ready) return; + + // every 200 ms + uint16_t dist = sensor.readRangeContinuousMillimeters(); + if (dist==0 || dist>2000) { + dist=9999; + } + +#ifdef USE_VL_MEDIAN + // store in ring buffer + Vl53l0_buffer[Vl53l0_index]=dist; + Vl53l0_index++; + if (Vl53l0_index>=5) Vl53l0_index=0; + + // sort list and take median + memmove(tbuff,Vl53l0_buffer,sizeof(tbuff)); + for (byte ocnt=0; ocnt<5; ocnt++) { + flag=0; + for (byte count=0; count<4; count++) { + if (tbuff[count]>tbuff[count+1]) { + tmp=tbuff[count]; + tbuff[count]=tbuff[count+1]; + tbuff[count+1]=tmp; + flag=1; + } + } + if (!flag) break; + } + vl53l0x_distance=tbuff[2]; +#else + vl53l0x_distance=dist; +#endif +} + +void Vl53l0Show(boolean json) +{ + if (!vl53l0x_ready) { + return; + } + + if (json) { + ResponseAppend_P(PSTR(",\"VL53L0X\":{\"" D_JSON_DISTANCE "\":%d}"), vl53l0x_distance); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_VL53L0X, vl53l0x_distance); +#endif + } + +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_45 + +bool Xsns45(byte function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + Vl53l0Detect(); + break; + case FUNC_EVERY_250_MSECOND: + Vl53l0Every_250MSecond(); + break; + case FUNC_JSON_APPEND: + Vl53l0Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Vl53l0Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_VL53L0X +#endif // USE_I2C From 85d8fc76936ef59bd609dc84a278f40d6240bfa0 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 22 May 2019 13:23:21 +0200 Subject: [PATCH 1393/2222] Update my_user_config.h --- sonoff/my_user_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 6786f755b..4bbf7b201 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -442,6 +442,7 @@ #define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) +#define USE_VL53L0X // add support for VL53L0x time of flight sensor //#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) /*********************************************************************************************\ From dc1bf2ff0328f932bc326542dfc8fdedf0e4f08a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 22 May 2019 13:39:26 +0200 Subject: [PATCH 1394/2222] Add support for VL53L0x time of flight sensor. Might interfere with TSL2561 using same I2C address (#5845) Add support for VL53L0x time of flight sensor. Might interfere with TSL2561 using same I2C address (#5845) --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 450ef7859..58e0edbb2 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,6 +4,7 @@ * Add support for up to four LEDs related to four power outputs. Enabled when "LedLink(i)" is configured too (#5709) * Add extended LED power control using command LedPowerX where X is 1 to 4. Enabled when "LedLink(i)" is configured too (#5709) * Fix core 2.5.x ISR not in IRAM exception (#5837) + * Add support for VL53L0x time of flight sensor. Might interfere with TSL2561 using same I2C address (#5845) * * 6.5.0.11 20190517 * Add command SetOption64 0/1 to switch between "-" or "_" as sensor index separator impacting DS18X20, DHT, BMP and SHT3X sensor names (#5689) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 4bbf7b201..32b656065 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -348,6 +348,7 @@ // #define USE_SCD30 // Enable Sensiron SCd30 CO2 sensor (I2C address 0x61) (+3k3 code) #define USE_SPS30 // Enable Sensiron SPS30 particle sensor (I2C address 0x69) (+1.7 code) #define USE_ADE7953 // Enable ADE7953 Energy monitor as used on Shelly 2.5 (I2C address 0x38) (+1k5) + #define USE_VL53L0X // Enable VL53L0x time of flight sensor (I2C address 0x29) (+4k code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 @@ -442,7 +443,6 @@ #define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) -#define USE_VL53L0X // add support for VL53L0x time of flight sensor //#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) /*********************************************************************************************\ From e5f8167ebe70d658d220e78168f6069ac740e84f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 22 May 2019 13:51:33 +0200 Subject: [PATCH 1395/2222] Trying to fix exception 0 (#5837) Trying to fix exception 0 on counter usage (#5837) --- sonoff/support_rotary.ino | 2 +- sonoff/xsns_01_counter.ino | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/sonoff/support_rotary.ino b/sonoff/support_rotary.ino index 35974251b..64a7bc738 100644 --- a/sonoff/support_rotary.ino +++ b/sonoff/support_rotary.ino @@ -62,7 +62,7 @@ void update_position(void) } #ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception -void update_rotary(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too +void update_rotary(void) ICACHE_RAM_ATTR; #endif // ARDUINO_ESP8266_RELEASE_2_3_0 void update_rotary(void) diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index 069016a87..84b1c29ea 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -25,6 +25,14 @@ unsigned long last_counter_timer[MAX_COUNTERS]; // Last counter time in micro seconds +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception +void CounterUpdate(uint8_t index) ICACHE_RAM_ATTR; +void CounterUpdate1(void) ICACHE_RAM_ATTR; +void CounterUpdate2(void) ICACHE_RAM_ATTR; +void CounterUpdate3(void) ICACHE_RAM_ATTR; +void CounterUpdate4(void) ICACHE_RAM_ATTR; +#endif // ARDUINO_ESP8266_RELEASE_2_3_0 + void CounterUpdate(uint8_t index) { unsigned long counter_debounce_time = micros() - last_counter_timer[index -1]; @@ -40,13 +48,6 @@ void CounterUpdate(uint8_t index) } } -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception -void CounterUpdate1(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too -void CounterUpdate2(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too -void CounterUpdate3(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too -void CounterUpdate4(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too -#endif // ARDUINO_ESP8266_RELEASE_2_3_0 - void CounterUpdate1(void) { CounterUpdate(1); From 55c44f84029689bbdf58e9084f717a97b12c7684 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 22 May 2019 14:37:28 +0200 Subject: [PATCH 1396/2222] Update README.md Add logo --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index aaf844a2b..ebd6fa9fe 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +![Logo](/tools/logo/TASMOTA_FullLogo_Vector.svg) + ## Sonoff-Tasmota Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custom device templates and sensor support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. From c707b1fafd86830e2725ed766ee785bd0adf2480 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 22 May 2019 14:48:46 +0200 Subject: [PATCH 1397/2222] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ebd6fa9fe..a41401205 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -![Logo](/tools/logo/TASMOTA_FullLogo_Vector.svg) +Logo -## Sonoff-Tasmota +# Sonoff-Tasmota Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custom device templates and sensor support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. From d697e747e43e60061337444b2464a3043d10c439 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 22 May 2019 14:56:47 +0200 Subject: [PATCH 1398/2222] Add Logo Add Logo --- API.md | 5 ++++- CONTRIBUTING.md | 6 ++++-- REFERENCE.md | 5 ++++- RELEASENOTES.md | 11 +++++++---- SUPPORT.md | 8 +++++--- TEMPLATE.md | 5 ++++- 6 files changed, 28 insertions(+), 12 deletions(-) diff --git a/API.md b/API.md index caec908c6..08225689e 100644 --- a/API.md +++ b/API.md @@ -1,4 +1,7 @@ -## Sonoff-Tasmota basic API information +Logo + +# Sonoff-Tasmota basic API information + Sonoff-Tasmota can easily be extended by developers using provided function pointers as callback Ids. This document lists the available callback function Ids. See the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Sensor-API) for more information. Callback availability can be checked by searching for either XdrvCall, XsnsCall, XdspCall and XnrgCall. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ecb5a9bc..f748e36de 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,5 @@ +Logo + # Contributing to Sonoff-Tasmota **Any contribution helps our team and makes Tasmota better for the entire community!** @@ -26,7 +28,7 @@ This document describes rules that are in effect for this repository, meant for 1. Any contributor to the project can participate in the triaging process, if he/she chooses to do so. 2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor. 3. Issues that are accepted should be marked with appropriate labels. -4. Issues that could impact functionality for many users should be considered severe. +4. Issues that could impact functionality for many users should be considered severe. 5. Issues caused by the SDK or chip should not be marked severe, as there usually isn’t much to be done. Common sense should be applied when deciding. Such issues should be documented in the Wiki, for reference by users. 6. Issues with feature requests should be discussed for viability/desirability. 7. Feature requests or changes that are meant to address a very specific/limited use case, especially if at the expense of increased code complexity, may be denied, or may be required to be redesigned, generalized, or simplified. @@ -100,7 +102,7 @@ A CLA is a legal document in which you state _you are entitled to contribute the CLA is a safety because it also ensures that once you have provided a contribution, you cannot try to withdraw permission for its use at a later date. People can therefore use that software, confident that they will not be asked to stop using pieces of the code at a later date. -A __license__ grants "outbound" rights to the user of project. +A __license__ grants "outbound" rights to the user of project. A __CLA__ enables a contributor to grant "inbound" rights to a project. diff --git a/REFERENCE.md b/REFERENCE.md index 22bd77899..04dbf8807 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -1,4 +1,7 @@ -## Tasmota Reference +Logo + +# Tasmota Reference + Tasmota backgound information. ## Supported Smart Switch with Energy Monitoring GPIO usage diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0df822456..1209b76bf 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,3 +1,7 @@ +Logo + +# RELEASE NOTES + ## Migration Information See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade#migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates: @@ -6,11 +10,10 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade 3. Migrate to **Sonoff-Tasmota 5.14** 4. Migrate to **Sonoff-Tasmota 6.x** -## Release notes -### Core version 2.3.0 vs 2.4.2 +## Core version 2.3.0 vs 2.4.2 This release is based on ESP8266/Arduino library core 2.3.0 (again) as some people encountered wifi related issues on core 2.4.2. For others core 2.4.2 is working just fine. Both version are available from http://thehackbox.org/tasmota/release/ -### Change in default initial configuration tool +## Change in default initial configuration tool Firmware binary **sonoff-classic.bin** supports **WifiManager, Wps and SmartConfig** for initial configuration. The default tool is **Wps**. To save memory space all other binaries support **WifiManager only**. @@ -104,7 +107,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/release/020402/ -### Available Features and Sensors +## Available Features and Sensors | Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks |-----------------------|---------|-------|---------|--------|------|---------|---------|-------- diff --git a/SUPPORT.md b/SUPPORT.md index a0780c77c..6f41533d4 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -1,21 +1,23 @@ +Logo + # Sonoff-Tasmota Support If you're looking for support on **Sonoff-Tasmota** there are some options available: -### Documentation: +## Documentation: * [Wiki Pages](https://github.com/arendst/Sonoff-Tasmota/wiki): For information on how to Flash Tasmota, configure and use it. * [FAQ](https://github.com/arendst/Sonoff-Tasmota/wiki/FAQ): For information on common problems and solutions. * [Troubleshooting Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting): For ways to debug and troubleshoot. * [Commands Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands): For information on all the commands supported by Tasmota. -### Support's Community: +## Support's Community: * [Tasmota Forum](https://groups.google.com/d/forum/sonoffusers): For usage and discussions. * [Tasmota Support Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community. * [Search in Issues](https://github.com/arendst/Sonoff-Tasmota/issues): You might find an answer to your question by searching current or closed issues. -### Developers' Community: +## Developers' Community: * [Bug Report](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software. * [Feature Request](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software. diff --git a/TEMPLATE.md b/TEMPLATE.md index 67431f651..c189400b3 100644 --- a/TEMPLATE.md +++ b/TEMPLATE.md @@ -1,4 +1,7 @@ -## Sonoff-Tasmota template information +Logo + +# Sonoff-Tasmota template information + Sonoff-Tasmota uses Device or Module information to control peripherals connected to GPIOs. This information is stored in the ``sonoff_template.h`` file as a device specific template. The template contains information about what GPIO should be connected to what peripheral and what GPIO may be configured online using the ``GPIO`` command or GUI Configure Module menu. In addition a device may need specific coding to process the data from these peripherals. The module number as provided by the ``Modules`` command is used to select this coding. Starting with version 6.4.1.16 Sonoff-Tasmota Modules can be extended by users online using a template. To provide easy processing by Sonoff-Tasmota a user template is written as JSON text and could look like this: From 463a8064e31d0854425240adbee93fa3b77722e9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 22 May 2019 14:57:45 +0200 Subject: [PATCH 1399/2222] Update API.md --- API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API.md b/API.md index 08225689e..dc3a7f6e3 100644 --- a/API.md +++ b/API.md @@ -1,6 +1,6 @@ Logo -# Sonoff-Tasmota basic API information +# Basic API information Sonoff-Tasmota can easily be extended by developers using provided function pointers as callback Ids. This document lists the available callback function Ids. See the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Sensor-API) for more information. From c23d34bc5925475ff756e4fd8bdef43a2d4189ff Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 22 May 2019 14:58:25 +0200 Subject: [PATCH 1400/2222] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f748e36de..96e1c3173 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ Logo -# Contributing to Sonoff-Tasmota +# Contributing **Any contribution helps our team and makes Tasmota better for the entire community!** From 193b986a01aa18bed730fb6a4e013066d2727cd4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 22 May 2019 14:58:59 +0200 Subject: [PATCH 1401/2222] Update REFERENCE.md --- REFERENCE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REFERENCE.md b/REFERENCE.md index 04dbf8807..6d2c08747 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -1,6 +1,6 @@ Logo -# Tasmota Reference +# Reference Tasmota backgound information. From cfee103caf27aa5b8eddced1b50b230be538be74 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 22 May 2019 14:59:36 +0200 Subject: [PATCH 1402/2222] Update SUPPORT.md --- SUPPORT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SUPPORT.md b/SUPPORT.md index 6f41533d4..26c770b80 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -1,6 +1,6 @@ Logo -# Sonoff-Tasmota Support +# Support If you're looking for support on **Sonoff-Tasmota** there are some options available: From 4f778006e0792b3285067d095a70b68f602e942d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 22 May 2019 15:00:05 +0200 Subject: [PATCH 1403/2222] Update TEMPLATE.md --- TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TEMPLATE.md b/TEMPLATE.md index c189400b3..33465a0e9 100644 --- a/TEMPLATE.md +++ b/TEMPLATE.md @@ -1,6 +1,6 @@ Logo -# Sonoff-Tasmota template information +# Template information Sonoff-Tasmota uses Device or Module information to control peripherals connected to GPIOs. This information is stored in the ``sonoff_template.h`` file as a device specific template. The template contains information about what GPIO should be connected to what peripheral and what GPIO may be configured online using the ``GPIO`` command or GUI Configure Module menu. In addition a device may need specific coding to process the data from these peripherals. The module number as provided by the ``Modules`` command is used to select this coding. @@ -86,4 +86,4 @@ The following command will update the flag of a stored template ``Template {"FLAG":1}`` The following command will update the base of a stored template to Generic -``Template {"BASE":0}`` \ No newline at end of file +``Template {"BASE":0}`` From 4fe260dfc5bdd6acef68d59fa55b95b5db1a4de5 Mon Sep 17 00:00:00 2001 From: blakadder Date: Wed, 22 May 2019 18:27:42 +0200 Subject: [PATCH 1404/2222] Update README.md --- README.md | 54 ++++++------------------------------------------------ 1 file changed, 6 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index a41401205..f0cfb3f0a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ -Logo - # Sonoff-Tasmota -Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custom device templates and sensor support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. +LogoAlternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custom device templates and sensor support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. [![GitHub version](https://img.shields.io/github/release/arendst/Sonoff-Tasmota.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) [![GitHub download](https://img.shields.io/github/downloads/arendst/Sonoff-Tasmota/total.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) @@ -36,7 +34,7 @@ A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocu We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site. ### Note -Please do not ask to add devices where you can't provide a basic working configuration (other than sonoff). Since there are thousands of them. +Please do not ask to add new devices unless it requires additional code for new features. If the device is not listed as a module, try using Templates first. See if it is listed in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) or create your own [template](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates#creating-your-template-). ### Quick Install Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki. @@ -50,7 +48,7 @@ If you want to compile Sonoff-Tasmota yourself keep in mind the following: ### Version Information - Sonoff-Tasmota provides all (Sonoff) modules in one file and starts with module Sonoff Basic. -- Once uploaded select module using the configuration webpage or the commands ```Modules``` and ```Module```. +- Once uploaded, select module using the configuration webpage, the commands ```Modules``` and ```Module``` or configure the [Template](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates) for your device - After reboot select config menu again or use commands ```GPIOs``` and ```GPIO``` to change GPIO with desired sensor. ### Migration Information @@ -63,53 +61,12 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade ### Support Information +For a database of supported devices see [Tasmota Device Templates Repository](http://blakadder.github.io/templates). -See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for more information.
+See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for use instructions and how-to's.
See [Community](https://groups.google.com/d/forum/sonoffusers) for forum.
Visit [Discord Chat](https://discord.gg/Ks2Kzd4) for discussions and troubleshooting. -The following devices are supported: -- [iTead Sonoff Basic (R2)](https://www.itead.cc/smart-home/sonoff-wifi-wireless-switch-1.html) -- [iTead Sonoff RF](https://www.itead.cc/smart-home/sonoff-rf.html) -- [iTead Sonoff SV](https://www.itead.cc/smart-home/sonoff-sv.html) -- [iTead Sonoff TH10/TH16 with temperature sensor](https://www.itead.cc/smart-home/sonoff-th.html) -- [iTead Sonoff Dual (R2)](https://www.itead.cc/smart-home/sonoff-dual.html) -- [iTead Sonoff Pow with Energy Monitoring](https://www.itead.cc/smart-home/sonoff-pow.html) -- [iTead Sonoff Pow R2 with Energy Monitoring](https://www.itead.cc/sonoff-pow-r2.html) -- [iTead Sonoff 4CH (R2)](https://www.itead.cc/smart-home/sonoff-4ch.html) -- [iTead Sonoff 4CH Pro (R2)](https://www.itead.cc/smart-home/sonoff-4ch-pro.html) -- [iTead Sonoff S20 Smart Socket](https://www.itead.cc/smart-socket.html) -- [Sonoff S22 Smart Socket](https://github.com/arendst/Sonoff-Tasmota/issues/627) -- [iTead Sonoff S26 Smart Socket](https://www.itead.cc/sonoff-s26-wifi-smart-plug.html) -- [iTead Sonoff S31 Smart Socket with Energy Monitoring](https://www.itead.cc/sonoff-s31.html) -- [iTead Slampher](https://www.itead.cc/slampher.html) -- [iTead Sonoff Touch](https://www.itead.cc/sonoff-touch.html) -- [iTead Sonoff T1](https://www.itead.cc/sonoff-t1.html) -- [iTead Sonoff SC](https://www.itead.cc/sonoff-sc.html) -- [iTead Sonoff Led](https://www.itead.cc/sonoff-led.html) -- [iTead Sonoff BN-SZ01 Ceiling Led](https://www.itead.cc/bn-sz01.html) -- [iTead Sonoff B1](https://www.itead.cc/sonoff-b1.html) -- [iTead Sonoff iFan02](https://www.itead.cc/sonoff-ifan02-wifi-smart-ceiling-fan-with-light.html) -- [iTead Sonoff RF Bridge 433](https://www.itead.cc/sonoff-rf-bridge-433.html) -- [iTead Sonoff Dev](https://www.itead.cc/sonoff-dev.html) -- [iTead 1 Channel Switch 5V / 12V](https://www.itead.cc/smart-home/inching-self-locking-wifi-wireless-switch.html) -- [iTead Motor Clockwise/Anticlockwise](https://www.itead.cc/smart-home/motor-reversing-wifi-wireless-switch.html) -- [Electrodragon IoT Relay Board](http://www.electrodragon.com/product/wifi-iot-relay-board-based-esp8266/) -- AI Light or any my9291 compatible RGBW LED bulb -- H801 PWM LED controller -- [MagicHome PWM LED controller](https://github.com/arendst/Sonoff-Tasmota/wiki/MagicHome-LED-strip-controller) -- AriLux AL-LC01, AL-LC06 and AL-LC11 PWM LED controller -- [Supla device - Espablo-inCan mod. for electrical Installation box](https://forum.supla.org/viewtopic.php?f=33&t=2188) -- [BlitzWolf BW-SHP2 Smart Socket with Energy Monitoring](https://www.banggood.com/BlitzWolf-BW-SHP2-Smart-WIFI-Socket-EU-Plug-220V-16A-Work-with-Amazon-Alexa-Google-Assistant-p-1292899.html) -- [Luani HVIO board](https://luani.de/projekte/esp8266-hvio/) -- [Wemos D1 mini](https://wiki.wemos.cc/products:d1:d1_mini) -- [HuaFan Smart Socket](https://github.com/arendst/Sonoff-Tasmota/wiki/HuaFan-Smart-Socket) -- [Hyleton-313 Smart Plug](https://github.com/arendst/Sonoff-Tasmota/wiki/Hyleton-313-Smart-Plug) -- [Allterco Shelly 1](https://shelly.cloud/shelly1-open-source/) -- [Allterco Shelly 2 with Energy Monitoring](https://shelly.cloud/shelly2/) -- NodeMcu and Ledunia -- [KS-602 based switches like GresaTek, Jesiya, NewRice, Lyasi etc](https://ucexperiment.wordpress.com/2017/11/14/reprogramming-a-lyasi-wifi-wall-switch-with-esp8285/) - ### Contribute You can contribute to Sonoff-Tasmota by - providing Pull Requests (Features, Proof of Concepts, Language files or Fixes) @@ -175,6 +132,7 @@ People helping to keep the show on the road: - Frogmore42 and Jason2866 for providing many issue answers - Blakadder for editing the wiki and providing template management - Stephan Hadinger for refactoring light driver and enhancing HueEmulation +- tmo for designing the official logo - Many more providing Tips, Wips, Pocs or PRs ### License From dd4f527123eb6d8a9cc972c3bcea7d5ee72ee5d0 Mon Sep 17 00:00:00 2001 From: blakadder Date: Wed, 22 May 2019 18:28:12 +0200 Subject: [PATCH 1405/2222] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f0cfb3f0a..464af371b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Sonoff-Tasmota -LogoAlternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custom device templates and sensor support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. +LogoAlternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custom device templates and sensor support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. [![GitHub version](https://img.shields.io/github/release/arendst/Sonoff-Tasmota.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) [![GitHub download](https://img.shields.io/github/downloads/arendst/Sonoff-Tasmota/total.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) From e93dadbfa764f8fa4d4a561148c659553c65c64f Mon Sep 17 00:00:00 2001 From: blakadder Date: Wed, 22 May 2019 18:28:46 +0200 Subject: [PATCH 1406/2222] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 464af371b..b091083e2 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute! See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development/RELEASENOTES.md) for release information. -In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest), the binaries can also be OTA downloaded from http://thehackbox.org/tasmota/release/ +In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest), the binaries can be downloaded from http://thehackbox.org/tasmota/release/ ### Development [![Dev Version](https://img.shields.io/badge/development%20version-6.5.0.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) From f8268864c187b647f46c84e25ab71086c4b1c689 Mon Sep 17 00:00:00 2001 From: blakadder Date: Wed, 22 May 2019 18:33:35 +0200 Subject: [PATCH 1407/2222] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b091083e2..a1a7f228a 100644 --- a/README.md +++ b/README.md @@ -34,10 +34,10 @@ A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocu We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site. ### Note -Please do not ask to add new devices unless it requires additional code for new features. If the device is not listed as a module, try using Templates first. See if it is listed in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) or create your own [template](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates#creating-your-template-). +Please do not ask to add new devices unless it requires additional code for new features. If the device is not listed as a module, try using [Templates](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates) first. If it is not listed in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) create your own [Template](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates#creating-your-template-). ### Quick Install -Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki. +Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as [documented in the wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Flashing). ### Important User Compilation Information If you want to compile Sonoff-Tasmota yourself keep in mind the following: @@ -48,7 +48,7 @@ If you want to compile Sonoff-Tasmota yourself keep in mind the following: ### Version Information - Sonoff-Tasmota provides all (Sonoff) modules in one file and starts with module Sonoff Basic. -- Once uploaded, select module using the configuration webpage, the commands ```Modules``` and ```Module``` or configure the [Template](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates) for your device +- Once uploaded, select [Module](https://github.com/arendst/Sonoff-Tasmota/wiki/Modules) using the configuration webpage, the commands ```Modules``` and ```Module``` or configure the [Template](https://github.com/arendst/Sonoff-Tasmota/wiki/Templates) for your device - After reboot select config menu again or use commands ```GPIOs``` and ```GPIO``` to change GPIO with desired sensor. ### Migration Information @@ -61,7 +61,7 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade ### Support Information -For a database of supported devices see [Tasmota Device Templates Repository](http://blakadder.github.io/templates). +For a database of supported devices see [Tasmota Device Templates Repository](http://blakadder.github.io/templates) See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for use instructions and how-to's.
See [Community](https://groups.google.com/d/forum/sonoffusers) for forum.
From fc660dcd07203ed5a506ce6f98336e6d2074514e Mon Sep 17 00:00:00 2001 From: blakadder Date: Wed, 22 May 2019 18:39:31 +0200 Subject: [PATCH 1408/2222] streamlined README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a1a7f228a..77473b2a5 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,8 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade ### Support Information -For a database of supported devices see [Tasmota Device Templates Repository](http://blakadder.github.io/templates) + +For a database of supported devices see [Tasmota Device Templates Repository](https://blakadder.github.io/templates) See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for use instructions and how-to's.
See [Community](https://groups.google.com/d/forum/sonoffusers) for forum.
From e65790e55eb0b1ac5f2efffcba2243d846937141 Mon Sep 17 00:00:00 2001 From: Tiberiu Ana Date: Thu, 23 May 2019 12:21:08 +0200 Subject: [PATCH 1409/2222] Add CORS preflight support to console URL Please see #5847 for reference. --- sonoff/xdrv_01_webserver.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index fc5ffa467..163453109 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -480,7 +480,8 @@ void StartWebserver(int type, IPAddress ipweb) WebServer->on("/u1", HandleUpgradeFirmwareStart); // OTA WebServer->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); WebServer->on("/u2", HTTP_OPTIONS, HandlePreflightRequest); - WebServer->on("/cs", HandleConsole); + WebServer->on("/cs", HTTP_GET, HandleConsole); + WebServer->on("/cs", HTTP_OPTIONS, HandlePreflightRequest); WebServer->on("/cm", HandleHttpCommand); #ifndef FIRMWARE_MINIMAL WebServer->on("/cn", HandleConfiguration); From 41226593023843918cbd82042b8a4064e8803c2b Mon Sep 17 00:00:00 2001 From: Michael Ingraham <34340210+meingraham@users.noreply.github.com> Date: Thu, 23 May 2019 11:09:20 -0400 Subject: [PATCH 1410/2222] Gerhard Mutz credits --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 77473b2a5..dc30dfccb 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ People helping to keep the show on the road: - Emontnemery for his HomeAssistant Discovery concept and many code tuning tips - Aidan Mountford for his HSB support - Daniel Ztolnai for his Serial Bridge implementation -- Gerhard Mutz for his SGP30, Sunrise/Sunset and display support drivers +- Gerhard Mutz for multiple sensor & display drivers, Sunrise/Sunset, and scripting - Nuno Ferreira for his HC-SR04 driver - Adrian Scillato for his (security)fixes and implementing and maintaining KNX - Gennaro Tortone for implementing and maintaining Eastron drivers From 56615dce4e4031e9befd5cb7bf9037a8896c4b5d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 24 May 2019 12:28:09 +0200 Subject: [PATCH 1411/2222] Add command AdcParam Add command AdcParam to control ADC0 Temperature and Light formula parameters --- sonoff/_changelog.ino | 1 + sonoff/settings.h | 8 +++- sonoff/settings.ino | 4 +- sonoff/xsns_02_analog.ino | 97 +++++++++++++++++++++++++++++++++++---- 4 files changed, 97 insertions(+), 13 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 58e0edbb2..0a96b4630 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -5,6 +5,7 @@ * Add extended LED power control using command LedPowerX where X is 1 to 4. Enabled when "LedLink(i)" is configured too (#5709) * Fix core 2.5.x ISR not in IRAM exception (#5837) * Add support for VL53L0x time of flight sensor. Might interfere with TSL2561 using same I2C address (#5845) + * Add command AdcParam to control ADC0 Temperature and Light formula parameters * * 6.5.0.11 20190517 * Add command SetOption64 0/1 to switch between "-" or "_" as sensor index separator impacting DS18X20, DHT, BMP and SHT3X sensor names (#5689) diff --git a/sonoff/settings.h b/sonoff/settings.h index 03529e8fa..5f6350116 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -210,8 +210,9 @@ struct SYSCFG { uint8_t webserver; // 1AB uint8_t weblog_level; // 1AC uint8_t mqtt_fingerprint[2][20]; // 1AD + uint8_t adc_param_type; // 1D5 - uint8_t free_1D5[19]; // 1D5 Free since 5.12.0e + uint8_t free_1D6[18]; // 1D6 Free since 5.12.0e uint8_t sps30_inuse_hours; // 1E8 char mqtt_host[33]; // 1E9 - Keep together with below as being copied as one chunck with reset 6 @@ -336,7 +337,10 @@ struct SYSCFG { uint8_t free_774[32]; // 774 - uint32_t drivers[3]; // 794 +// uint32_t drivers[3]; // 794 - 6.5.0.12 replaced by below three entries + uint32_t adc_param1; // 794 + uint32_t adc_param2; // 798 + int adc_param3; // 79C uint32_t monitors; // 7A0 uint32_t sensors[3]; // 7A4 uint32_t displays; // 7B0 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index a8445b232..0adc1ab9e 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -908,7 +908,7 @@ void SettingsDefaultSet2(void) SettingsDefaultWebColor(); - memset(&Settings.drivers, 0xFF, 32); // Enable all possible monitors, displays, drivers and sensors + memset(&Settings.monitors, 0xFF, 20); // Enable all possible monitors, displays and sensors } /********************************************************************************************/ @@ -1129,7 +1129,7 @@ void SettingsDelta(void) Settings.timezone_minutes = 0; } if (Settings.version < 0x06030004) { - memset(&Settings.drivers, 0xFF, 32); // Enable all possible monitors, displays, drivers and sensors + memset(&Settings.monitors, 0xFF, 20); // Enable all possible monitors, displays and sensors } if (Settings.version < 0x0603000E) { Settings.flag2.calc_resolution = CALC_RESOLUTION; diff --git a/sonoff/xsns_02_analog.ino b/sonoff/xsns_02_analog.ino index 85560e3d3..0fe674c3a 100644 --- a/sonoff/xsns_02_analog.ino +++ b/sonoff/xsns_02_analog.ino @@ -35,21 +35,40 @@ // 3V3 --- ANALOG_NTC_BRIDGE_RESISTANCE ---v--- NTC --- Gnd // | // ADC0 -#define ANALOG_NTC_BRIDGE_RESISTANCE 32000.0 // NTC Voltage bridge resistor -#define ANALOG_NTC_RESISTANCE 10000.0 // NTC Resistance -#define ANALOG_NTC_B_COEFFICIENT 3350.0 // NTC Beta Coefficient +#define ANALOG_NTC_BRIDGE_RESISTANCE 32000 // NTC Voltage bridge resistor +#define ANALOG_NTC_RESISTANCE 10000 // NTC Resistance +#define ANALOG_NTC_B_COEFFICIENT 3350 // NTC Beta Coefficient // LDR parameters // 3V3 --- LDR ---v--- ANALOG_LDR_BRIDGE_RESISTANCE --- Gnd // | // ADC0 -#define ANALOG_LDR_BRIDGE_RESISTANCE 10000.0 // LDR Voltage bridge resistor +#define ANALOG_LDR_BRIDGE_RESISTANCE 10000 // LDR Voltage bridge resistor #define ANALOG_LDR_LUX_CALC_SCALAR 12518931 // Experimental -#define ANALOG_LDR_LUX_CALC_EXPONENT -1.405 // Experimental +#define ANALOG_LDR_LUX_CALC_EXPONENT -1.4050 // Experimental uint16_t adc_last_value = 0; float adc_temp = 0; +void AdcInit(void) +{ + if ((Settings.adc_param_type != my_adc0) || (Settings.adc_param1 > 1000000) || (Settings.adc_param1 < 100)) { + if (ADC0_TEMP == my_adc0) { + // Default Shelly 2.5 and 1PM parameters + Settings.adc_param_type = ADC0_TEMP; + Settings.adc_param1 = ANALOG_NTC_BRIDGE_RESISTANCE; + Settings.adc_param2 = ANALOG_NTC_RESISTANCE; + Settings.adc_param3 = ANALOG_NTC_B_COEFFICIENT * 10000; + } + else if (ADC0_LIGHT == my_adc0) { + Settings.adc_param_type = ADC0_LIGHT; + Settings.adc_param1 = ANALOG_LDR_BRIDGE_RESISTANCE; + Settings.adc_param2 = ANALOG_LDR_LUX_CALC_SCALAR; + Settings.adc_param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000; + } + } +} + uint16_t AdcRead(uint8_t factor) { // factor 1 = 2 samples @@ -88,8 +107,8 @@ uint16_t AdcGetLux() // Source: https://www.allaboutcircuits.com/projects/design-a-luxmeter-using-a-light-dependent-resistor/ double resistorVoltage = ((double)adc / 1023) * ANALOG_V33; double ldrVoltage = ANALOG_V33 - resistorVoltage; - double ldrResistance = ldrVoltage / resistorVoltage * ANALOG_LDR_BRIDGE_RESISTANCE; - double ldrLux = ANALOG_LDR_LUX_CALC_SCALAR * FastPrecisePow(ldrResistance, ANALOG_LDR_LUX_CALC_EXPONENT); + double ldrResistance = ldrVoltage / resistorVoltage * (double)Settings.adc_param1; + double ldrLux = (double)Settings.adc_param2 * FastPrecisePow(ldrResistance, (double)Settings.adc_param3 / 10000); return (uint16_t)ldrLux; } @@ -99,12 +118,66 @@ void AdcEverySecond(void) if (ADC0_TEMP == my_adc0) { int adc = AdcRead(2); // Steinhart-Hart equation for thermistor as temperature sensor - double Rt = (adc * ANALOG_NTC_BRIDGE_RESISTANCE) / (1024.0 * ANALOG_V33 - (double)adc); - double T = ANALOG_NTC_B_COEFFICIENT / (ANALOG_NTC_B_COEFFICIENT / ANALOG_T0 + TaylorLog(Rt / ANALOG_NTC_RESISTANCE)); + double Rt = (adc * Settings.adc_param1) / (1024.0 * ANALOG_V33 - (double)adc); + double BC = (double)Settings.adc_param3 / 10000; + double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Settings.adc_param2)); adc_temp = ConvertTemp(TO_CELSIUS(T)); } } +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + +#define D_CMND_ADCPARAM "AdcParam" +enum AdcCommands { CMND_ADCPARAM }; +const char kAdcCommands[] PROGMEM = D_CMND_ADCPARAM; + +bool AdcCommand(void) +{ + char command[CMDSZ]; + bool serviced = true; + + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kAdcCommands); + if (CMND_ADCPARAM == command_code) { + if (XdrvMailbox.data_len) { + if ((ADC0_TEMP == XdrvMailbox.payload) || (ADC0_LIGHT == XdrvMailbox.payload)) { +// if ((XdrvMailbox.payload == my_adc0) && ((ADC0_TEMP == my_adc0) || (ADC0_LIGHT == my_adc0))) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry + char sub_string[XdrvMailbox.data_len +1]; + // AdcParam 2, 32000, 10000, 3350 + // AdcParam 3, 10000, 12518931, -1.405 + Settings.adc_param_type = XdrvMailbox.payload; +// Settings.adc_param_type = my_adc0; + Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); + Settings.adc_param3 = (int)(CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); + } else { // Set default values based on current adc type + // AdcParam 2 + // AdcParam 3 + Settings.adc_param_type = 0; + AdcInit(); + } + } + } + + // AdcParam + int value = Settings.adc_param3; + uint8_t precision; + for (precision = 4; precision > 0; precision--) { + if (value % 10) { break; } + value /= 10; + } + char param3[33]; + dtostrfd(((double)Settings.adc_param3)/10000, precision, param3); + Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d,%s]}"), + Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2, param3); + } + else serviced = false; // Unknown command + + return serviced; +} + void AdcShow(bool json) { if (ADC0_INPUT == my_adc0) { @@ -176,6 +249,12 @@ bool Xsns02(uint8_t function) case FUNC_EVERY_SECOND: AdcEverySecond(); break; + case FUNC_INIT: + AdcInit(); + break; + case FUNC_COMMAND: + result = AdcCommand(); + break; case FUNC_JSON_APPEND: AdcShow(1); break; From 4d070bfb157f0db7b0c0ad8e6e79050bb55fba42 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 24 May 2019 15:04:48 +0200 Subject: [PATCH 1412/2222] Change default PowerDelta from 80% to 0% on new installations Change default PowerDelta from 80% to 0% on new installations (#5858, #5028, #4813, #4130, #4145, #3795, #3778, #3660, #3648) --- sonoff/_changelog.ino | 1 + sonoff/settings.ino | 4 ++-- sonoff/sonoff.h | 1 - sonoff/xdrv_03_energy.ino | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0a96b4630..276084707 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -6,6 +6,7 @@ * Fix core 2.5.x ISR not in IRAM exception (#5837) * Add support for VL53L0x time of flight sensor. Might interfere with TSL2561 using same I2C address (#5845) * Add command AdcParam to control ADC0 Temperature and Light formula parameters + * Change default PowerDelta from 80% to 0% on new installations (#5858, #5028, #4813, #4130, #4145, #3795, #3778, #3660, #3648) * * 6.5.0.11 20190517 * Add command SetOption64 0/1 to switch between "-" or "_" as sensor index separator impacting DS18X20, DHT, BMP and SHT3X sensor names (#5689) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 0adc1ab9e..7d957ba14 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -789,7 +789,7 @@ void SettingsDefaultSet2(void) // Settings.flag2.wattage_resolution = 0; Settings.flag2.energy_resolution = ENERGY_RESOLUTION; Settings.param[P_MAX_POWER_RETRY] = MAX_POWER_RETRY; - Settings.energy_power_delta = DEFAULT_POWER_DELTA; +// Settings.energy_power_delta = 0; Settings.energy_power_calibration = HLW_PREF_PULSE; Settings.energy_voltage_calibration = HLW_UREF_PULSE; Settings.energy_current_calibration = HLW_IREF_PULSE; @@ -1047,7 +1047,7 @@ void SettingsDelta(void) } if (Settings.version < 0x050C0005) { Settings.light_rotation = 0; - Settings.energy_power_delta = DEFAULT_POWER_DELTA; + Settings.energy_power_delta = 0; char fingerprint[60]; memcpy(fingerprint, Settings.mqtt_fingerprint, sizeof(fingerprint)); char *p = fingerprint; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 9b3ed0020..8be609155 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -99,7 +99,6 @@ const uint16_t PWM_MIN = 100; // [PWM_MIN] Minimum frequency - Def // For Controlling Servos use 50 and also set PWM_FREQ as 50 (DO NOT USE THESE VALUES FOR DIMMERS) //#define PWM_LIGHTSCHEME0_IGNORE_SLEEP // Do not change sleep value for LightAnimate() scheme 0 -const uint8_t DEFAULT_POWER_DELTA = 80; // Power change percentage const uint16_t MAX_POWER_HOLD = 10; // Time in SECONDS to allow max agreed power const uint16_t MAX_POWER_WINDOW = 30; // Time in SECONDS to disable allow max agreed power const uint16_t SAFE_POWER_HOLD = 10; // Time in SECONDS to allow max unit safe power diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 74867263e..1d47bc034 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -349,7 +349,7 @@ bool EnergyCommand(void) } else if (CMND_POWERDELTA == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 101)) { - Settings.energy_power_delta = (1 == XdrvMailbox.payload) ? DEFAULT_POWER_DELTA : XdrvMailbox.payload; + Settings.energy_power_delta = XdrvMailbox.payload; } nvalue = Settings.energy_power_delta; unit = UNIT_PERCENTAGE; From abb7e0f412573d774971b5f58427324d95806580 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Sun, 26 May 2019 14:19:26 +0200 Subject: [PATCH 1413/2222] Small fixes in platformio Fixes in platformio update to 2.2.1 Fixed broken example "esp8266-nonos-sdk-blink" Use 115200 upload speed by default (issue #153) --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 351d1ba02..a5c0946d1 100755 --- a/platformio.ini +++ b/platformio.ini @@ -67,7 +67,7 @@ build_flags = ${esp82xx_defaults.build_flags} [core_2_5_2] ; *** Esp8266 core for Arduino version 2.5.2 -platform = espressif8266@~2.2.0 +platform = espressif8266@~2.2.1 build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld ; Code optimization see https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473 From 22663fc10c9f10fa015fcdda80f13b669f8aee68 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 27 May 2019 11:56:14 +0200 Subject: [PATCH 1414/2222] 6.5.0.13 Add command SetOption38 6..255 6.5.0.13 20190527 * Add command SetOption38 6..255 to set IRReceive protocol detection sensitivity mimizing UNKNOWN protocols (#5853) --- sonoff/_changelog.ino | 5 ++++- sonoff/my_user_config.h | 2 +- sonoff/settings.ino | 6 ++++++ sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 5 +++++ sonoff/sonoff_version.h | 2 +- sonoff/xdrv_05_irremote.ino | 8 +++++++- 7 files changed, 25 insertions(+), 5 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 276084707..874fa5e34 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.5.0.12 20190521 +/* 6.5.0.13 20190527 + * Add command SetOption38 6..255 to set IRReceive protocol detection sensitivity mimizing UNKNOWN protocols (#5853) + * + * 6.5.0.12 20190521 * Add AriLux RF control GPIO option "ALux IrSel" (159) replacing "Led4i" (59) for full LED control (#5709) * Add LED GPIO option "LedLink" (157) and "LedLinki" (158) to select dedicated link status LED (#5709) * Add support for up to four LEDs related to four power outputs. Enabled when "LedLink(i)" is configured too (#5709) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 32b656065..690340c86 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -417,7 +417,7 @@ #define USE_IR_RECEIVE // Support for IR receiver (+7k2 code, 264 iram) #define IR_RCV_BUFFER_SIZE 100 // Max number of packets allowed in capture buffer (default 100 (*2 bytes ram)) #define IR_RCV_TIMEOUT 15 // Number of milli-Seconds of no-more-data before we consider a message ended (default 15) - #define IR_RCV_MIN_UNKNOWN_SIZE 6 // Set the smallest sized "UNKNOWN" message packets we actually care about (default 6) + #define IR_RCV_MIN_UNKNOWN_SIZE 6 // Set the smallest sized "UNKNOWN" message packets we actually care about (default 6, max 255) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // #define USE_WS2812_CTYPE NEO_GRB // WS2812 Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 7d957ba14..246b503b5 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -813,6 +813,9 @@ void SettingsDefaultSet2(void) // Settings.energy_kWhtotal = 0; RtcSettings.energy_kWhtotal = 0; + // IRRemote + Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; + // RF Bridge // for (uint8_t i = 0; i < 17; i++) { Settings.rf_code[i][0] = 0; } memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); @@ -1168,6 +1171,9 @@ void SettingsDelta(void) if (Settings.version < 0x0605000A) { Settings.my_adc0 = ADC0_NONE; } + if (Settings.version < 0x0605000D) { + Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 8be609155..d7d4ef905 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -236,7 +236,7 @@ enum ButtonStates { PRESSED, NOT_PRESSED }; enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; -enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 +enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_IR_UNKNOW_THRESHOLD, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_MAX_SENSORS}; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 48145fb2f..905e8b3ea 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -851,6 +851,11 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) case P_RGB_REMAP: LightUpdateColorMapping(); break; +#ifdef USE_IR_RECEIVE + case P_IR_UNKNOW_THRESHOLD: + IrReceiveUpdateThreshold(); + break; +#endif } } } diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index e06fab8d0..8b7c27bfc 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x0605000C; +const uint32_t VERSION = 0x0605000D; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 9f1c33a10..9bd0694e3 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -116,11 +116,17 @@ IRrecv *irrecv = nullptr; unsigned long ir_lasttime = 0; +void IrReceiveUpdateThreshold() +{ + if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); +} + void IrReceiveInit(void) { // an IR led is at GPIO_IRRECV irrecv = new IRrecv(pin[GPIO_IRRECV], IR_RCV_BUFFER_SIZE, IR_RCV_TIMEOUT, IR_RCV_SAVE_BUFFER); - irrecv->setUnknownThreshold(IR_RCV_MIN_UNKNOWN_SIZE); + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); irrecv->enableIRIn(); // Start the receiver // AddLog_P(LOG_LEVEL_DEBUG, PSTR("IrReceive initialized")); From 0c2d1323e7da8d23593d9f70a2c7fbb03fe9ea9c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 27 May 2019 14:09:33 +0200 Subject: [PATCH 1415/2222] Shrink HtmlEscape code size Shrink HtmlEscape code size by 200 bytes --- sonoff/xdrv_01_webserver.ino | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 163453109..af4156f57 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1294,15 +1294,23 @@ void ModuleSaveSettings(void) /*-------------------------------------------------------------------------------------------*/ -String htmlEscape(String s) -{ - s.replace("&", "&"); - s.replace("<", "<"); - s.replace(">", ">"); - s.replace("\"", """); - s.replace("'", "'"); - s.replace("/", "/"); - return s; +const char kUnescapeCode[] = "&><\"\'"; +const char kEscapeCode[] PROGMEM = "&|>|<|"|'"; + +String HtmlEscape(const String unescaped) { + char escaped[10]; + uint16_t ulen = unescaped.length(); + String result = ""; + for (size_t i = 0; i < ulen; i++) { + char c = unescaped[i]; + char *p = strchr(kUnescapeCode, c); + if (p != nullptr) { + result += GetTextIndexed(escaped, sizeof(escaped), p - kUnescapeCode, kEscapeCode); + } else { + result += c; + } + } + return result; } void HandleWifiConfiguration(void) @@ -1373,7 +1381,7 @@ void HandleWifiConfiguration(void) if (minimum_signal_quality == -1 || minimum_signal_quality < quality) { uint8_t auth = WiFi.encryptionType(indices[i]); WSContentSend_P(PSTR("
%s (%d) %s %d%%
"), - htmlEscape(WiFi.SSID(indices[i])).c_str(), + HtmlEscape(WiFi.SSID(indices[i])).c_str(), WiFi.channel(indices[i]), (ENC_TYPE_WEP == auth) ? D_WEP : (ENC_TYPE_TKIP == auth) ? D_WPA_PSK : (ENC_TYPE_CCMP == auth) ? D_WPA2_PSK : (ENC_TYPE_AUTO == auth) ? D_AUTO : "", quality From 5df4931add610dd4a60e9470f2590863ecd030d7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 27 May 2019 14:11:01 +0200 Subject: [PATCH 1416/2222] Update IRRemote library to 2.6.0 Update IRRemote library from 2.5.2 to 2.6.0 --- .../examples/IRMQTTServer/IRMQTTServer.ino | 1608 --------- .../examples/IRrecvDump/platformio.ini | 17 - .../examples/IRrecvDumpV2/platformio.ini | 17 - .../examples/IRsendDemo/platformio.ini | 17 - .../examples/IRsendProntoDemo/platformio.ini | 17 - .../JVCPanasonicSendDemo/platformio.ini | 17 - .../examples/LGACSend/platformio.ini | 17 - .../examples/TurnOnArgoAC/platformio.ini | 17 - .../examples/TurnOnDaikinAC/platformio.ini | 17 - .../examples/TurnOnFujitsuAC/platformio.ini | 17 - .../TurnOnKelvinatorAC/platformio.ini | 17 - .../TurnOnMitsubishiAC/platformio.ini | 17 - .../examples/TurnOnToshibaAC/platformio.ini | 17 - .../examples/TurnOnTrotecAC/platformio.ini | 17 - lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp | 470 --- .../src/ir_Daikin.cpp | 750 ---- lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h | 208 -- .../src/ir_Trotec.cpp | 127 - .../src/ir_Whirlpool.cpp | 149 - .../test/IRsend_test.cpp | 290 -- .../test/ir_Daikin_test.cpp | 838 ----- .../test/ir_Whirlpool_test.cpp | 118 - .../.github/CONTRIBUTING.md | 0 .../.github/Contributors.md | 4 +- .../.github/issue_template.md | 0 .../.gitignore | 0 .../.gitmodules | 0 .../.style.yapf | 0 .../.travis.yml | 15 +- .../CPPLINT.cfg | 0 .../LICENSE.txt | 0 .../README.md | 5 +- .../ReleaseNotes.md | 102 + .../ControlSamsungAC/ControlSamsungAC.ino | 99 + .../examples/ControlSamsungAC}/platformio.ini | 2 + .../examples/IRGCSendDemo/IRGCSendDemo.ino | 0 .../examples/IRGCSendDemo/platformio.ini | 2 + .../examples/IRGCTCPServer/IRGCTCPServer.ino | 0 .../examples/IRGCTCPServer/platformio.ini | 2 + .../examples/IRMQTTServer/IRMQTTServer.h | 258 ++ .../examples/IRMQTTServer/IRMQTTServer.ino | 3034 +++++++++++++++++ .../examples/IRMQTTServer/platformio.ini | 16 +- .../examples/IRServer/IRServer.ino | 0 .../examples/IRServer/platformio.ini | 2 + .../examples/IRrecvDemo/IRrecvDemo.ino | 0 .../examples/IRrecvDemo/platformio.ini | 19 + .../examples/IRrecvDump/IRrecvDump.ino | 0 .../examples/IRrecvDump/platformio.ini | 19 + .../examples/IRrecvDumpV2/IRrecvDumpV2.ino | 62 +- .../examples/IRrecvDumpV2/platformio.ini | 19 + .../examples/IRsendDemo/IRsendDemo.ino | 19 +- .../examples/IRsendDemo/platformio.ini | 19 + .../IRsendProntoDemo/IRsendProntoDemo.ino | 0 .../examples/IRsendProntoDemo/platformio.ini | 19 + .../JVCPanasonicSendDemo.ino | 0 .../JVCPanasonicSendDemo/platformio.ini | 19 + .../examples/LGACSend/LGACSend.ino | 0 .../examples/LGACSend/platformio.ini | 19 + .../examples/TurnOnArgoAC/TurnOnArgoAC.ino | 0 .../examples/TurnOnArgoAC/platformio.ini | 19 + .../TurnOnDaikinAC/TurnOnDaikinAC.ino | 0 .../examples/TurnOnDaikinAC/platformio.ini | 19 + .../TurnOnFujitsuAC/TurnOnFujitsuAC.ino | 0 .../examples/TurnOnFujitsuAC/platformio.ini | 19 + .../TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino | 0 .../TurnOnKelvinatorAC/platformio.ini | 19 + .../TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino | 0 .../TurnOnMitsubishiAC/platformio.ini | 19 + .../TurnOnMitsubishiHeavyAc.ino | 72 + .../TurnOnMitsubishiHeavyAc/platformio.ini | 19 + .../TurnOnPanasonicAC/TurnOnPanasonicAC.ino | 74 + .../examples/TurnOnPanasonicAC/platformio.ini | 19 + .../TurnOnToshibaAC/TurnOnToshibaAC.ino | 0 .../examples/TurnOnToshibaAC/platformio.ini | 19 + .../TurnOnTrotecAC/TurnOnTrotecAC.ino | 0 .../examples/TurnOnTrotecAC/platformio.ini | 19 + .../keywords.txt | 542 ++- .../library.json | 2 +- .../library.properties | 2 +- .../platformio.ini | 3 + .../pylintrc | 0 .../src/CPPLINT.cfg | 0 lib/IRremoteESP8266-2.6.0/src/IRac.cpp | 1125 ++++++ lib/IRremoteESP8266-2.6.0/src/IRac.h | 248 ++ .../src/IRrecv.cpp | 34 + .../src/IRrecv.h | 38 +- .../src/IRremoteESP8266.h | 137 +- .../src/IRsend.cpp | 213 +- .../src/IRsend.h | 124 +- .../src/IRtimer.cpp | 33 +- .../src/IRtimer.h | 12 + lib/IRremoteESP8266-2.6.0/src/IRutils.cpp | 768 +++++ .../src/IRutils.h | 13 +- .../src/ir_Aiwa.cpp | 0 .../src/ir_Argo.cpp | 38 +- .../src/ir_Argo.h | 16 +- .../src/ir_Carrier.cpp | 0 .../src/ir_Coolix.cpp | 216 +- .../src/ir_Coolix.h | 31 +- lib/IRremoteESP8266-2.6.0/src/ir_Daikin.cpp | 1712 ++++++++++ lib/IRremoteESP8266-2.6.0/src/ir_Daikin.h | 444 +++ .../src/ir_Denon.cpp | 0 .../src/ir_Dish.cpp | 0 .../src/ir_Electra.cpp | 21 +- .../src/ir_Fujitsu.cpp | 95 +- .../src/ir_Fujitsu.h | 13 +- .../src/ir_GICable.cpp | 0 .../src/ir_GlobalCache.cpp | 0 .../src/ir_Gree.cpp | 128 +- .../src/ir_Gree.h | 17 +- .../src/ir_Haier.cpp | 324 +- .../src/ir_Haier.h | 26 +- .../src/ir_Hitachi.cpp | 89 +- .../src/ir_Hitachi.h | 13 +- .../src/ir_JVC.cpp | 0 .../src/ir_Kelvinator.cpp | 94 +- .../src/ir_Kelvinator.h | 12 +- .../src/ir_LG.cpp | 6 +- .../src/ir_LG.h | 0 .../src/ir_Lasertag.cpp | 2 +- lib/IRremoteESP8266-2.6.0/src/ir_Lego.cpp | 128 + .../src/ir_Lutron.cpp | 0 .../src/ir_MWM.cpp | 4 +- .../src/ir_Magiquest.cpp | 0 .../src/ir_Magiquest.h | 4 +- .../src/ir_Midea.cpp | 81 +- .../src/ir_Midea.h | 11 +- .../src/ir_Mitsubishi.cpp | 111 +- .../src/ir_Mitsubishi.h | 14 +- .../src/ir_MitsubishiHeavy.cpp | 1014 ++++++ .../src/ir_MitsubishiHeavy.h | 264 ++ .../src/ir_NEC.cpp | 0 .../src/ir_NEC.h | 0 .../src/ir_Nikai.cpp | 0 .../src/ir_Panasonic.cpp | 240 +- .../src/ir_Panasonic.h | 16 +- .../src/ir_Pioneer.cpp | 0 .../src/ir_Pronto.cpp | 0 .../src/ir_RC5_RC6.cpp | 0 .../src/ir_RCMM.cpp | 0 .../src/ir_Samsung.cpp | 293 +- .../src/ir_Samsung.h | 19 +- .../src/ir_Sanyo.cpp | 0 .../src/ir_Sharp.cpp | 0 .../src/ir_Sherwood.cpp | 0 .../src/ir_Sony.cpp | 0 lib/IRremoteESP8266-2.6.0/src/ir_Tcl.cpp | 420 +++ lib/IRremoteESP8266-2.6.0/src/ir_Tcl.h | 105 + lib/IRremoteESP8266-2.6.0/src/ir_Teco.cpp | 278 ++ lib/IRremoteESP8266-2.6.0/src/ir_Teco.h | 144 + .../src/ir_Toshiba.cpp | 66 +- .../src/ir_Toshiba.h | 11 +- lib/IRremoteESP8266-2.6.0/src/ir_Trotec.cpp | 162 + .../src/ir_Trotec.h | 37 +- lib/IRremoteESP8266-2.6.0/src/ir_Vestel.cpp | 583 ++++ lib/IRremoteESP8266-2.6.0/src/ir_Vestel.h | 177 + .../src/ir_Whirlpool.cpp | 671 ++++ lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.h | 167 + .../src/ir_Whynter.cpp | 0 lib/IRremoteESP8266-2.6.0/test/IRac_test.cpp | 865 +++++ .../test/IRrecv_test.cpp | 0 .../test/IRrecv_test.h | 0 .../test/IRsend_test.cpp | 686 ++++ .../test/IRsend_test.h | 22 +- .../test/IRutils_test.cpp | 65 + .../test/Makefile | 186 +- .../test/ir_Aiwa_test.cpp | 6 + .../test/ir_Carrier_test.cpp | 4 + .../test/ir_Coolix_test.cpp | 164 +- .../test/ir_Daikin_test.cpp | 1880 ++++++++++ .../test/ir_Denon_test.cpp | 8 + .../test/ir_Dish_test.cpp | 8 + .../test/ir_Electra_test.cpp | 19 +- .../test/ir_Fujitsu_test.cpp | 5 + .../test/ir_GICable_test.cpp | 6 + .../test/ir_GlobalCache_test.cpp | 2 + .../test/ir_Gree_test.cpp | 21 +- .../test/ir_Haier_test.cpp | 93 +- .../test/ir_Hitachi_test.cpp | 5 + .../test/ir_JVC_test.cpp | 5 + .../test/ir_Kelvinator_test.cpp | 4 + .../test/ir_LG_test.cpp | 58 + .../test/ir_Lasertag_test.cpp | 9 +- .../test/ir_Lego_test.cpp | 196 ++ .../test/ir_Lutron_test.cpp | 9 +- .../test/ir_MWM_test.cpp | 2 + .../test/ir_Magiquest_test.cpp | 3 + .../test/ir_Midea_test.cpp | 7 + .../test/ir_MitsubishiHeavy_test.cpp | 851 +++++ .../test/ir_Mitsubishi_test.cpp | 17 + .../test/ir_NEC_test.cpp | 9 +- .../test/ir_Nikai_test.cpp | 3 + .../test/ir_Panasonic_test.cpp | 9 + .../test/ir_Pioneer_test.cpp | 3 + .../test/ir_Pronto_test.cpp | 20 +- .../test/ir_RC5_RC6_test.cpp | 26 + .../test/ir_RCMM_test.cpp | 5 + .../test/ir_Samsung_test.cpp | 289 +- .../test/ir_Sanyo_test.cpp | 2 + .../test/ir_Sharp_test.cpp | 8 + .../test/ir_Sherwood_test.cpp | 3 + .../test/ir_Sony_test.cpp | 7 + .../test/ir_Tcl_test.cpp | 384 +++ .../test/ir_Teco_test.cpp | 358 ++ .../test/ir_Toshiba_test.cpp | 7 + .../test/ir_Vestel_test.cpp | 513 +++ .../test/ir_Whirlpool_test.cpp | 585 ++++ .../test/ir_Whynter_test.cpp | 8 + .../tools/Makefile | 55 +- .../tools/RawToGlobalCache.sh | 0 .../tools/auto_analyse_raw_data.py | 6 +- .../tools/auto_analyse_raw_data_test.py | 0 .../tools/gc_decode.cpp | 0 .../tools/mkkeywords | 0 .../tools/mode2_decode.cpp | 0 215 files changed, 22345 insertions(+), 5623 deletions(-) delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/IRMQTTServer.ino delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/platformio.ini delete mode 100644 lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp delete mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.cpp delete mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h delete mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.cpp delete mode 100644 lib/IRremoteESP8266-2.5.2.03/src/ir_Whirlpool.cpp delete mode 100644 lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.cpp delete mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Daikin_test.cpp delete mode 100644 lib/IRremoteESP8266-2.5.2.03/test/ir_Whirlpool_test.cpp rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/.github/CONTRIBUTING.md (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/.github/Contributors.md (87%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/.github/issue_template.md (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/.gitignore (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/.gitmodules (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/.style.yapf (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/.travis.yml (81%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/CPPLINT.cfg (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/LICENSE.txt (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/README.md (95%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/ReleaseNotes.md (72%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/ControlSamsungAC.ino rename lib/{IRremoteESP8266-2.5.2.03/examples/IRrecvDemo => IRremoteESP8266-2.6.0/examples/ControlSamsungAC}/platformio.ini (83%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/IRGCSendDemo/IRGCSendDemo.ino (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/IRGCSendDemo/platformio.ini (83%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/IRGCTCPServer/IRGCTCPServer.ino (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/IRGCTCPServer/platformio.ini (83%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.h create mode 100644 lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.ino rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/IRMQTTServer/platformio.ini (55%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/IRServer/IRServer.ino (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/IRServer/platformio.ini (83%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/IRrecvDemo/IRrecvDemo.ino (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/IRrecvDemo/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/IRrecvDump/IRrecvDump.ino (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/IRrecvDump/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/IRrecvDumpV2/IRrecvDumpV2.ino (84%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/IRsendDemo/IRsendDemo.ino (85%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/IRsendProntoDemo/IRsendProntoDemo.ino (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/IRsendProntoDemo/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/JVCPanasonicSendDemo/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/LGACSend/LGACSend.ino (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/LGACSend/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/TurnOnArgoAC/TurnOnArgoAC.ino (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/TurnOnArgoAC/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/TurnOnDaikinAC/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/TurnOnFujitsuAC/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/TurnOnKelvinatorAC/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiAC/platformio.ini create mode 100644 lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino create mode 100644 lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/platformio.ini create mode 100644 lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino create mode 100644 lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/TurnOnToshibaAC/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/examples/TurnOnTrotecAC/platformio.ini rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/keywords.txt (74%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/library.json (97%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/library.properties (96%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/platformio.ini (83%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/pylintrc (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/CPPLINT.cfg (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/src/IRac.cpp create mode 100644 lib/IRremoteESP8266-2.6.0/src/IRac.h rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/IRrecv.cpp (95%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/IRrecv.h (90%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/IRremoteESP8266.h (82%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/IRsend.cpp (92%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/IRsend.h (77%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/IRtimer.cpp (53%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/IRtimer.h (64%) create mode 100644 lib/IRremoteESP8266-2.6.0/src/IRutils.cpp rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/IRutils.h (74%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Aiwa.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Argo.cpp (84%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Argo.h (91%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Carrier.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Coolix.cpp (72%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Coolix.h (82%) create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_Daikin.cpp create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_Daikin.h rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Denon.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Dish.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Electra.cpp (87%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Fujitsu.cpp (88%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Fujitsu.h (93%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_GICable.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_GlobalCache.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Gree.cpp (82%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Gree.h (89%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Haier.cpp (75%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Haier.h (93%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Hitachi.cpp (86%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Hitachi.h (87%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_JVC.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Kelvinator.cpp (91%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Kelvinator.h (96%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_LG.cpp (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_LG.h (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Lasertag.cpp (98%) create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_Lego.cpp rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Lutron.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_MWM.cpp (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Magiquest.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Magiquest.h (86%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Midea.cpp (87%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Midea.h (93%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Mitsubishi.cpp (90%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Mitsubishi.h (91%) create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.cpp create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.h rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_NEC.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_NEC.h (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Nikai.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Panasonic.cpp (83%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Panasonic.h (91%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Pioneer.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Pronto.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_RC5_RC6.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_RCMM.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Samsung.cpp (66%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Samsung.h (84%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Sanyo.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Sharp.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Sherwood.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Sony.cpp (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_Tcl.cpp create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_Tcl.h create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_Teco.cpp create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_Teco.h rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Toshiba.cpp (86%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Toshiba.h (90%) create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_Trotec.cpp rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Trotec.h (68%) create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_Vestel.cpp create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_Vestel.h create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.cpp create mode 100644 lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.h rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/src/ir_Whynter.cpp (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/test/IRac_test.cpp rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/IRrecv_test.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/IRrecv_test.h (100%) create mode 100644 lib/IRremoteESP8266-2.6.0/test/IRsend_test.cpp rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/IRsend_test.h (82%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/IRutils_test.cpp (85%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/Makefile (71%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Aiwa_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Carrier_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Coolix_test.cpp (70%) create mode 100644 lib/IRremoteESP8266-2.6.0/test/ir_Daikin_test.cpp rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Denon_test.cpp (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Dish_test.cpp (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Electra_test.cpp (84%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Fujitsu_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_GICable_test.cpp (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_GlobalCache_test.cpp (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Gree_test.cpp (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Haier_test.cpp (90%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Hitachi_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_JVC_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Kelvinator_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_LG_test.cpp (88%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Lasertag_test.cpp (98%) create mode 100644 lib/IRremoteESP8266-2.6.0/test/ir_Lego_test.cpp rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Lutron_test.cpp (95%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_MWM_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Magiquest_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Midea_test.cpp (99%) create mode 100644 lib/IRremoteESP8266-2.6.0/test/ir_MitsubishiHeavy_test.cpp rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Mitsubishi_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_NEC_test.cpp (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Nikai_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Panasonic_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Pioneer_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Pronto_test.cpp (96%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_RC5_RC6_test.cpp (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_RCMM_test.cpp (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Samsung_test.cpp (77%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Sanyo_test.cpp (99%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Sharp_test.cpp (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Sherwood_test.cpp (97%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Sony_test.cpp (99%) create mode 100644 lib/IRremoteESP8266-2.6.0/test/ir_Tcl_test.cpp create mode 100644 lib/IRremoteESP8266-2.6.0/test/ir_Teco_test.cpp rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Toshiba_test.cpp (99%) create mode 100644 lib/IRremoteESP8266-2.6.0/test/ir_Vestel_test.cpp create mode 100644 lib/IRremoteESP8266-2.6.0/test/ir_Whirlpool_test.cpp rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/test/ir_Whynter_test.cpp (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/tools/Makefile (76%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/tools/RawToGlobalCache.sh (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/tools/auto_analyse_raw_data.py (98%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/tools/auto_analyse_raw_data_test.py (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/tools/gc_decode.cpp (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/tools/mkkeywords (100%) rename lib/{IRremoteESP8266-2.5.2.03 => IRremoteESP8266-2.6.0}/tools/mode2_decode.cpp (100%) diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/IRMQTTServer.ino b/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/IRMQTTServer.ino deleted file mode 100644 index 7851cf5dc..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/IRMQTTServer.ino +++ /dev/null @@ -1,1608 +0,0 @@ -/* - * Send & receive arbitrary IR codes via a web server or MQTT. - * Copyright David Conran 2016, 2017, 2018 - * - * NOTE: An IR LED circuit *MUST* be connected to ESP8266 GPIO4 (D2) if - * you want to send IR messages. See IR_LED below. - * A compatible IR RX modules *MUST* be connected to ESP8266 GPIO14 (D5) - * if you want to capture & decode IR nessages. See IR_RX below. - * - * WARN: This is very advanced & complicated example code. Not for beginners. - * You are strongly suggested to try & look at other example code first. - * - * # Instructions - * - * ## Before First Boot (i.e. Compile time) - * - Either: - * o Set the MQTT_SERVER define below to the address of your MQTT server. - * or - * o Disable MQTT by commenting out the line "#define MQTT_ENABLE" down below. - * - * - Arduino IDE: - * o Install the following libraries via Library Manager - * - WiFiManager (https://github.com/tzapu/WiFiManager) (Version >= 0.14) - * - PubSubClient (https://pubsubclient.knolleary.net/) - * o You MUST change to have the following (or larger) value: - * #define MQTT_MAX_PACKET_SIZE 512 - * - PlatformIO IDE: - * If you are using PlatformIO, this should already been done for you in - * the accompanying platformio.ini file. - * - * ## First Boot (Initial setup) - * The ESP8266 board will boot into the WiFiManager's AP mode. - * i.e. It will create a WiFi Access Point with a SSID like: "ESP123456" etc. - * Connect to that SSID. Then point your browser to http://192.168.4.1/ and - * configure the ESP8266 to connect to your desired WiFi network. - * It will remember the new WiFi connection details on next boot. - * More information can be found here: - * https://github.com/tzapu/WiFiManager#how-it-works - * - * If you need to reset the WiFi settings, visit: - * http:///reset - * - * ## Normal Use (After setup) - * Enter 'http:///ir?type=7&code=E0E09966 - * http:///ir?type=4&code=0xf50&bits=12 - * http:///ir?code=C1A2E21D&repeats=8&type=19 - * http:///ir?type=31&code=40000,1,1,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,1058 - * http:///ir?type=18&code=190B8050000000E0190B8070000010f0 - * http:///ir?repeats=1&type=25&code=0000,006E,0022,0002,0155,00AA,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0040,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0040,0015,0040,0015,0040,0015,0640,0155,0055,0015,0E40 - * - * or - * - * Send a MQTT message to the topic 'ir_server/send' using the following - * format (Order is important): - * protocol_num,hexcode e.g. 7,E0E09966 which is Samsung(7), Power On code, - * default bit size, default nr. of repeats. - * protocol_num,hexcode,bits e.g. 4,f50,12 which is Sony(4), Power Off code, - * 12 bits & default nr. of repeats. - * protocol_num,hexcode,bits,repeats e.g. 19,C1A2E21D,0,8 which is - * Sherwood(19), Vol Up, default bit size & - * repeated 8 times. - * 30,frequency,raw_string e.g. 30,38000,9000,4500,500,1500,500,750,500,750 - * Raw (30) @ 38kHz with a raw code of "9000,4500,500,1500,500,750,500,750" - * 31,code_string e.g. 31,40000,1,1,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,1058 - * GlobalCache (31) & "40000,1,1,96,..." (Sony Vol Up) - * 25,Rrepeats,hex_code_string e.g. 25,R1,0000,006E,0022,0002,0155,00AA,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0040,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0040,0015,0040,0015,0040,0015,0640,0155,0055,0015,0E40 - * Pronto (25), 1 repeat, & "0000 006E 0022 0002 ..." (Sherwood Amp Tape Input) - * ac_protocol_num,really_long_hexcode e.g. 18,190B8050000000E0190B8070000010F0 - * Kelvinator (18) Air Con on, Low Fan, 25 deg etc. - * NOTE: Ensure you zero-pad to the correct number of - * digits for the bit/byte size you want to send - * as some A/C units have units have different - * sized messages. e.g. Fujitsu A/C units. - * In short: - * No spaces after/before commas. - * Values are comma separated. - * The first value is always in Decimal. - * For simple protocols, the next value (hexcode) is always hexadecimal. - * The optional bit size is in decimal. - * - * Unix command line usage example: - * # Install a MQTT client - * $ sudo apt install mosquitto-clients - * # Send a 32-bit NEC code of 0x1234abcd via MQTT. - * $ mosquitto_pub -h 10.20.0.253 -t ir_server/send -m '3,1234abcd,32' - * - * This server will send (back) what ever IR message it just transmitted to - * the MQTT topic 'ir_server/sent' to confirm it has been performed. This works - * for messages requested via MQTT or via HTTP. - * Note: Other status messages are also sent to 'ir_server/sent' from time to - * time. - * Unix command line usage example: - * # Listen to MQTT acknowledgements. - * $ mosquitto_sub -h 10.20.0.253 -t ir_server/sent - * - * Incoming IR messages (from an IR remote control) will be transmitted to - * the MQTT topic 'ir_server/received'. The MQTT message will be formatted - * similar to what is required to for the 'sent' topic. - * e.g. "3,C1A2F00F,32" (Protocol,Value,Bits) for simple codes - * or "18,110B805000000060110B807000001070" (Protocol,Value) for complex codes - * Note: If the protocol is listed as -1, then that is an UNKNOWN IR protocol. - * You can't use that to recreate/resend an IR message. It's only for - * matching purposes and shouldn't be trusted. - * - * Unix command line usage example: - * # Listen via MQTT for IR messages captured by this server. - * $ mosquitto_sub -h 10.20.0.253 -t ir_server/received - * - * If DEBUG is turned on, there is additional information printed on the Serial - * Port. - * - * ## Updates - * You can upload new firmware over the air (OTA) via the form on the device's - * main page. No need to connect to the device again via USB. \o/ - * Your WiFi settings should be remembered between updates. \o/ \o/ - * - * Copyright Notice: - * Code for this has been borrowed from lots of other OpenSource projects & - * resources. I'm *NOT* claiming complete Copyright ownership of all the code. - * Likewise, feel free to borrow from this as much as you want. - */ - -#define MQTT_ENABLE // Comment this out if you don't want to use MQTT at all. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef MQTT_ENABLE -// -------------------------------------------------------------------- -// * * * IMPORTANT * * * -// You must change to have the following value. -// #define MQTT_MAX_PACKET_SIZE 512 -// -------------------------------------------------------------------- -#include -#endif // MQTT_ENABLE -#include -#include - -// Configuration parameters -// GPIO the IR LED is connected to/controlled by. GPIO 4 = D2. -#define IR_LED 4 -// define IR_LED 3 // For an ESP-01 we suggest you use RX/GPIO3/Pin 7. -// -// GPIO the IR RX module is connected to/controlled by. GPIO 14 = D5. -// Comment this out to disable receiving/decoding IR messages entirely. -#define IR_RX 14 -const uint16_t kHttpPort = 80; // The TCP port the HTTP server is listening on. -// Name of the device you want in mDNS. -// NOTE: Changing this will change the MQTT path too unless you override it -// via MQTTprefix below. -#define HOSTNAME "ir_server" - -// We obtain our network config via DHCP by default but allow an easy way to -// use a static IP config. -#define USE_STATIC_IP false // Change to 'true' if you don't want to use DHCP. -#if USE_STATIC_IP -const IPAddress kIPAddress = IPAddress(10, 0, 1, 78); -const IPAddress kGateway = IPAddress(10, 0, 1, 1); -const IPAddress kSubnetMask = IPAddress(255, 255, 255, 0); -#endif // USE_STATIC_IP - -#ifdef MQTT_ENABLE -// Address of your MQTT server. -#define MQTT_SERVER "10.20.0.253" // <=- CHANGE ME -const uint16_t kMqttPort = 1883; // Default port used by MQTT servers. -// Set if your MQTT server requires a Username & Password to connect. -const char* mqtt_user = ""; -const char* mqtt_password = ""; -const uint32_t kMqttReconnectTime = 5000; // Delay(ms) between reconnect tries. - -#define MQTTprefix HOSTNAME // Change this if you want the MQTT topic to be - // independent of the hostname. -#define MQTTack MQTTprefix "/sent" // Topic we send back acknowledgements on -#define MQTTcommand MQTTprefix "/send" // Topic we get new commands from. -#define MQTTrecv MQTTprefix "/received" // Topic we send received IRs to. -#endif // MQTT_ENABLE - -// HTML arguments we will parse for IR code information. -#define argType "type" -#define argData "code" -#define argBits "bits" -#define argRepeat "repeats" -// Let's use a larger than normal buffer so we can handle AirCon remote codes. -const uint16_t kCaptureBufferSize = 1024; -#if DECODE_AC -// Some A/C units have gaps in their protocols of ~40ms. e.g. Kelvinator -// A value this large may swallow repeats of some protocols -const uint8_t kCaptureTimeout = 50; -#else // DECODE_AC -// Suits most messages, while not swallowing many repeats. -const uint8_t kCaptureTimeout = 15; -#endif // DECODE_AC -// Ignore unknown messages with <10 pulses -const uint16_t kMinUnknownSize = 20; - -#define _MY_VERSION_ "v0.7.0" - -// Disable debug output if any of the IR pins are on the TX (D1) pin. -#if (IR_LED != 1 && IR_RX != 1) -#undef DEBUG -#define DEBUG true // Change to 'false' to disable all serial output. -#else -#undef DEBUG -#define DEBUG false -#endif -// NOTE: Make sure you set your Serial Monitor to the same speed. -#define BAUD_RATE 115200 // Serial port Baud rate. - -// Globals -ESP8266WebServer server(kHttpPort); -IRsend irsend = IRsend(IR_LED); -#ifdef IR_RX -IRrecv irrecv(IR_RX, kCaptureBufferSize, kCaptureTimeout, true); -decode_results capture; // Somewhere to store inbound IR messages. -#endif // IR_RX -MDNSResponder mdns; -WiFiClient espClient; -WiFiManager wifiManager; - -uint16_t *codeArray; -uint32_t lastReconnectAttempt = 0; // MQTT last attempt reconnection number -bool boot = true; -bool ir_lock = false; // Primitive locking for gating the IR LED. -uint32_t sendReqCounter = 0; -bool lastSendSucceeded = false; // Store the success status of the last send. -uint32_t lastSendTime = 0; -int8_t offset; // The calculated period offset for this chip and library. - -#ifdef MQTT_ENABLE -String lastMqttCmd = "None"; -uint32_t lastMqttCmdTime = 0; -uint32_t lastConnectedTime = 0; -uint32_t lastDisconnectedTime = 0; -uint32_t mqttDisconnectCounter = 0; -bool wasConnected = true; -#ifdef IR_RX -String lastIrReceived = "None"; -uint32_t lastIrReceivedTime = 0; -uint32_t irRecvCounter = 0; -#endif // IR_RX - - -// MQTT client parameters -void callback(char* topic, byte* payload, unsigned int length); -PubSubClient mqtt_client(MQTT_SERVER, kMqttPort, callback, espClient); -// Create a unique MQTT client id. -String mqtt_clientid = MQTTprefix + String(ESP.getChipId(), HEX); -#endif // MQTT_ENABLE - -// Debug messages get sent to the serial port. -void debug(String str) { -#ifdef DEBUG - uint32_t now = millis(); - Serial.printf("%07u.%03u: %s\n", now / 1000, now % 1000, str.c_str()); -#endif // DEBUG -} - -String timeSince(uint32_t const start) { - if (start == 0) - return "Never"; - uint32_t diff = 0; - uint32_t now = millis(); - if (start < now) - diff = now - start; - else - diff = UINT32_MAX - start + now; - diff /= 1000; // Convert to seconds. - if (diff == 0) return "Now"; - - // Note: millis() can only count up to 45 days, so uint8_t is safe. - uint8_t days = diff / (60 * 60 * 24); - uint8_t hours = (diff / (60 * 60)) % 24; - uint8_t minutes = (diff / 60) % 60; - uint8_t seconds = diff % 60; - - String result = ""; - if (days) - result += String(days) + " day"; - if (days > 1) result += "s"; - if (hours) - result += " " + String(hours) + " hour"; - if (hours > 1) result += "s"; - if (minutes) - result += " " + String(minutes) + " minute"; - if (minutes > 1) result += "s"; - if (seconds) - result += " " + String(seconds) + " second"; - if (seconds > 1) result += "s"; - result.trim(); - return result + " ago"; -} - -// Quick and dirty check for any unsafe chars in a string -// that may cause HTML shenanigans. e.g. An XSS. -bool hasUnsafeHTMLChars(String input) { - static char unsafe[] = "';!-\"<>=&{}()"; - for (uint8_t i = 0; unsafe[i]; i++) - if (input.indexOf(unsafe[i]) != -1) return true; - return false; -} - -// Root web page with example usage etc. -void handleRoot() { - server.send(200, "text/html", - "IR MQTT server" - "" - "

ESP8266 IR MQTT Server

" - "

" - "

Information

" - "

IP address: " + WiFi.localIP().toString() + "
" - "Booted: " + timeSince(1) + "
" + - "Version: " _MY_VERSION_ "
" - "Period Offset: " + String(offset) + "us
" - "IR Lib Version: " _IRREMOTEESP8266_VERSION_ "
" - "ESP8266 Core Version: " + ESP.getCoreVersion() + "
" - "IR Send GPIO: " + String(IR_LED) + "
" - "Total send requests: " + String(sendReqCounter) + "
" - "Last message sent: " + String(lastSendSucceeded ? "Ok" : "FAILED") + - " (" + timeSince(lastSendTime) + ")
" -#ifdef IR_RX - "IR Recv GPIO: " + String(IR_RX) + "
" - "Total IR Received: " + String(irRecvCounter) + "
" - "Last IR Received: " + lastIrReceived + - " (" + timeSince(lastIrReceivedTime) + ")
" -#endif // IR_RX - "

" -#ifdef MQTT_ENABLE - "

MQTT Information

" - "

Server: " MQTT_SERVER ":" + String(kMqttPort) + " (" + - (mqtt_client.connected() ? "Connected " + timeSince(lastDisconnectedTime) - : "Disconnected " + timeSince(lastConnectedTime)) + - ")
" - "Disconnections: " + String(mqttDisconnectCounter - 1) + "
" - "Client id: " + mqtt_clientid + "
" - "Command topic: " MQTTcommand "
" - "Acknowledgements topic: " MQTTack "
" -#ifdef IR_RX - "IR Received topic: " MQTTrecv "
" -#endif // IR_RX - "Last MQTT command seen: " + - // lastMqttCmd is unescaped untrusted input. - // Avoid any possible HTML/XSS when displaying it. - (hasUnsafeHTMLChars(lastMqttCmd) ? - "Contains unsafe HTML characters" : lastMqttCmd) + - " (" + timeSince(lastMqttCmdTime) + ")

" -#endif // MQTT_ENABLE - "

" - "

Hardcoded examples

" - "

" - "Sherwood Amp On (GlobalCache)

" - "

" - "Sherwood Amp Off (Raw)

" - "

" - "Sherwood Amp Input TAPE (Pronto)

" - "

TV on (Samsung)

" - "

Power Off (Sony 12bit)

" - "

" - "

Send a simple IR message

" - "

" - "Type: " - "" - " Code: 0x" - " Bit size: " - "" - " Repeats: " - " " - "
" - "

" - "

Send an IRremote Raw IR message

" - "

" - "" - "String: (freq,array data) " - " " - "
" - "

" - "

Send a GlobalCache" - " IR message

" - "

" - "" - "String: 1:1,1," - " " - "
" - "

" - "

Send a Pronto code IR message

" - "

" - "" - "String (comma separated): " - " Repeats: " - " " - "
" - "

" - "

Send an Air Conditioner IR message

" - "

" - "Type: " - "" - " State code: 0x" - "" - " " - "
" - "

" - "

Update IR Server firmware

" - "Warning:
" - "Updating your firmware may screw up your access to the device. " - "If you are going to use this, know what you are doing first " - "(and you probably do).
" - "

" - "Firmware to upload: " - "" - "
" - ""); -} - -// Reset web page -void handleReset() { - server.send(200, "text/html", - "Reset Config" - "" - "

Resetting the WiFiManager config back to defaults.

" - "

Device restarting. Try connecting in a few seconds.

" - ""); - // Do the reset. - wifiManager.resetSettings(); - delay(10); - ESP.restart(); - delay(1000); -} - -// Parse an Air Conditioner A/C Hex String/code and send it. -// Args: -// irType: Nr. of the protocol we need to send. -// str: A hexadecimal string containing the state to be sent. -// Returns: -// bool: Successfully sent or not. -bool parseStringAndSendAirCon(const uint16_t irType, const String str) { - uint8_t strOffset = 0; - uint8_t state[kStateSizeMax] = {0}; // All array elements are set to 0. - uint16_t stateSize = 0; - - if (str.startsWith("0x") || str.startsWith("0X")) - strOffset = 2; - // Calculate how many hexadecimal characters there are. - uint16_t inputLength = str.length() - strOffset; - if (inputLength == 0) { - debug("Zero length AirCon code encountered. Ignored."); - return false; // No input. Abort. - } - - switch (irType) { // Get the correct state size for the protocol. - case KELVINATOR: - stateSize = kKelvinatorStateLength; - break; - case TOSHIBA_AC: - stateSize = kToshibaACStateLength; - break; - case DAIKIN: - stateSize = kDaikinStateLength; - break; - case ELECTRA_AC: - stateSize = kElectraAcStateLength; - break; - case MITSUBISHI_AC: - stateSize = kMitsubishiACStateLength; - break; - case PANASONIC_AC: - stateSize = kPanasonicAcStateLength; - break; - case TROTEC: - stateSize = kTrotecStateLength; - break; - case ARGO: - stateSize = kArgoStateLength; - break; - case GREE: - stateSize = kGreeStateLength; - break; - case FUJITSU_AC: - // Fujitsu has four distinct & different size states, so make a best guess - // which one we are being presented with based on the number of - // hexadecimal digits provided. i.e. Zero-pad if you need to to get - // the correct length/byte size. - stateSize = inputLength / 2; // Every two hex chars is a byte. - // Use at least the minimum size. - stateSize = std::max(stateSize, - (uint16_t) (kFujitsuAcStateLengthShort - 1)); - // If we think it isn't a "short" message. - if (stateSize > kFujitsuAcStateLengthShort) - // Then it has to be at least the smaller version of the "normal" size. - stateSize = std::max(stateSize, (uint16_t) (kFujitsuAcStateLength - 1)); - // Lastly, it should never exceed the maximum "normal" size. - stateSize = std::min(stateSize, kFujitsuAcStateLength); - break; - case HAIER_AC: - stateSize = kHaierACStateLength; - break; - case HAIER_AC_YRW02: - stateSize = kHaierACYRW02StateLength; - break; - case HITACHI_AC: - stateSize = kHitachiAcStateLength; - break; - case HITACHI_AC1: - stateSize = kHitachiAc1StateLength; - break; - case HITACHI_AC2: - stateSize = kHitachiAc2StateLength; - break; - case WHIRLPOOL_AC: - stateSize = kWhirlpoolAcStateLength; - break; - case SAMSUNG_AC: - // Samsung has two distinct & different size states, so make a best guess - // which one we are being presented with based on the number of - // hexadecimal digits provided. i.e. Zero-pad if you need to to get - // the correct length/byte size. - stateSize = inputLength / 2; // Every two hex chars is a byte. - // Use at least the minimum size. - stateSize = std::max(stateSize, (uint16_t) (kSamsungAcStateLength)); - // If we think it isn't a "normal" message. - if (stateSize > kSamsungAcStateLength) - // Then it probably the extended size. - stateSize = std::max(stateSize, - (uint16_t) (kSamsungAcExtendedStateLength)); - // Lastly, it should never exceed the maximum "extended" size. - stateSize = std::min(stateSize, kSamsungAcExtendedStateLength); - break; - case MWM: - // MWM has variable size states, so make a best guess - // which one we are being presented with based on the number of - // hexadecimal digits provided. i.e. Zero-pad if you need to to get - // the correct length/byte size. - stateSize = inputLength / 2; // Every two hex chars is a byte. - // Use at least the minimum size. - stateSize = std::max(stateSize, (uint16_t) 3); - // Cap the maximum size. - stateSize = std::min(stateSize, kStateSizeMax); - break; - default: // Not a protocol we expected. Abort. - debug("Unexpected AirCon protocol detected. Ignoring."); - return false; - } - if (inputLength > stateSize * 2) { - debug("AirCon code to large for the given protocol."); - return false; - } - - // Ptr to the least significant byte of the resulting state for this protocol. - uint8_t *statePtr = &state[stateSize - 1]; - - // Convert the string into a state array of the correct length. - for (uint16_t i = 0; i < inputLength; i++) { - // Grab the next least sigificant hexadecimal digit from the string. - uint8_t c = tolower(str[inputLength + strOffset - i - 1]); - if (isxdigit(c)) { - if (isdigit(c)) - c -= '0'; - else - c = c - 'a' + 10; - } else { - debug("Aborting! Non-hexadecimal char found in AirCon state: " + str); - return false; - } - if (i % 2 == 1) { // Odd: Upper half of the byte. - *statePtr += (c << 4); - statePtr--; // Advance up to the next least significant byte of state. - } else { // Even: Lower half of the byte. - *statePtr = c; - } - } - - // Make the appropriate call for the protocol type. - switch (irType) { -#if SEND_KELVINATOR - case KELVINATOR: - irsend.sendKelvinator(reinterpret_cast(state)); - break; -#endif -#if SEND_TOSHIBA_AC - case TOSHIBA_AC: - irsend.sendToshibaAC(reinterpret_cast(state)); - break; -#endif -#if SEND_DAIKIN - case DAIKIN: - irsend.sendDaikin(reinterpret_cast(state)); - break; -#endif -#if MITSUBISHI_AC - case MITSUBISHI_AC: - irsend.sendMitsubishiAC(reinterpret_cast(state)); - break; -#endif -#if SEND_TROTEC - case TROTEC: - irsend.sendTrotec(reinterpret_cast(state)); - break; -#endif -#if SEND_ARGO - case ARGO: - irsend.sendArgo(reinterpret_cast(state)); - break; -#endif -#if SEND_GREE - case GREE: - irsend.sendGree(reinterpret_cast(state)); - break; -#endif -#if SEND_FUJITSU_AC - case FUJITSU_AC: - irsend.sendFujitsuAC(reinterpret_cast(state), stateSize); - break; -#endif -#if SEND_HAIER_AC - case HAIER_AC: - irsend.sendHaierAC(reinterpret_cast(state)); - break; -#endif -#if SEND_HAIER_AC_YRW02 - case HAIER_AC_YRW02: - irsend.sendHaierACYRW02(reinterpret_cast(state)); - break; -#endif -#if SEND_HITACHI_AC - case HITACHI_AC: - irsend.sendHitachiAC(reinterpret_cast(state)); - break; -#endif -#if SEND_HITACHI_AC1 - case HITACHI_AC1: - irsend.sendHitachiAC1(reinterpret_cast(state)); - break; -#endif -#if SEND_HITACHI_AC2 - case HITACHI_AC2: - irsend.sendHitachiAC2(reinterpret_cast(state)); - break; -#endif -#if SEND_WHIRLPOOL_AC - case WHIRLPOOL_AC: - irsend.sendWhirlpoolAC(reinterpret_cast(state)); - break; -#endif -#if SEND_SAMSUNG_AC - case SAMSUNG_AC: - irsend.sendSamsungAC(reinterpret_cast(state), stateSize); - break; -#endif -#if SEND_ELECTRA_AC - case ELECTRA_AC: - irsend.sendElectraAC(reinterpret_cast(state)); - break; -#endif -#if SEND_PANASONIC_AC - case PANASONIC_AC: - irsend.sendPanasonicAC(reinterpret_cast(state)); - break; -#endif -#if SEND_MWM_ - case MWM: - irsend.sendMWM(reinterpret_cast(state), stateSize); - break; -#endif - default: - debug("Unexpected AirCon type in send request. Not sent."); - return false; - } - return true; // We were successful as far as we can tell. -} - -// Count how many values are in the String. -// Args: -// str: String containing the values. -// sep: Character that separates the values. -// Returns: -// The number of values found in the String. -uint16_t countValuesInStr(const String str, char sep) { - int16_t index = -1; - uint16_t count = 1; - do { - index = str.indexOf(sep, index + 1); - count++; - } while (index != -1); - return count; -} - -// Dynamically allocate an array of uint16_t's. -// Args: -// size: Nr. of uint16_t's need to be in the new array. -// Returns: -// A Ptr to the new array. Restarts the ESP8266 if it fails. -uint16_t * newCodeArray(const uint16_t size) { - uint16_t *result; - - result = reinterpret_cast(malloc(size * sizeof(uint16_t))); - // Check we malloc'ed successfully. - if (result == NULL) { // malloc failed, so give up. - Serial.printf("\nCan't allocate %d bytes. (%d bytes free)\n", - size * sizeof(uint16_t), ESP.getFreeHeap()); - Serial.println("Giving up & forcing a reboot."); - ESP.restart(); // Reboot. - delay(500); // Wait for the restart to happen. - return result; // Should never get here, but just in case. - } - return result; -} - -#if SEND_GLOBALCACHE -// Parse a GlobalCache String/code and send it. -// Args: -// str: A GlobalCache formatted String of comma separated numbers. -// e.g. "38000,1,1,170,170,20,63,20,63,20,63,20,20,20,20,20,20,20,20,20, -// 20,20,63,20,63,20,63,20,20,20,20,20,20,20,20,20,20,20,20,20,63, -// 20,20,20,20,20,20,20,20,20,20,20,20,20,63,20,20,20,63,20,63,20, -// 63,20,63,20,63,20,63,20,1798" -// Note: The leading "1:1,1," of normal GC codes should be removed. -// Returns: -// bool: Successfully sent or not. -bool parseStringAndSendGC(const String str) { - uint16_t count; - uint16_t *code_array; - String tmp_str; - - // Remove the leading "1:1,1," if present. - if (str.startsWith("1:1,1,")) - tmp_str = str.substring(6); - else - tmp_str = str; - - // Find out how many items there are in the string. - count = countValuesInStr(tmp_str, ','); - - // Now we know how many there are, allocate the memory to store them all. - code_array = newCodeArray(count); - - // Now convert the strings to integers and place them in code_array. - count = 0; - uint16_t start_from = 0; - int16_t index = -1; - do { - index = tmp_str.indexOf(',', start_from); - code_array[count] = tmp_str.substring(start_from, index).toInt(); - start_from = index + 1; - count++; - } while (index != -1); - - irsend.sendGC(code_array, count); // All done. Send it. - free(code_array); // Free up the memory allocated. - if (count > 0) - return true; // We sent something. - return false; // We probably didn't. -} -#endif // SEND_GLOBALCACHE - -#if SEND_PRONTO -// Parse a Pronto Hex String/code and send it. -// Args: -// str: A comma-separated String of nr. of repeats, then hexadecimal numbers. -// e.g. "R1,0000,0067,0000,0015,0060,0018,0018,0018,0030,0018,0030,0018, -// 0030,0018,0018,0018,0030,0018,0018,0018,0018,0018,0030,0018, -// 0018,0018,0030,0018,0030,0018,0030,0018,0018,0018,0018,0018, -// 0030,0018,0018,0018,0018,0018,0030,0018,0018,03f6" -// or -// "0000,0067,0000,0015,0060,0018". i.e. without the Repeat value -// Requires at least kProntoMinLength comma-separated values. -// sendPronto() only supports raw pronto code types, thus so does this. -// repeats: Nr. of times the message is to be repeated. -// This value is ignored if an embeddd repeat is found in str. -// Returns: -// bool: Successfully sent or not. -bool parseStringAndSendPronto(const String str, uint16_t repeats) { - uint16_t count; - uint16_t *code_array; - int16_t index = -1; - uint16_t start_from = 0; - - // Find out how many items there are in the string. - count = countValuesInStr(str, ','); - - // Check if we have the optional embedded repeats value in the code string. - if (str.startsWith("R") || str.startsWith("r")) { - // Grab the first value from the string, as it is the nr. of repeats. - index = str.indexOf(',', start_from); - repeats = str.substring(start_from + 1, index).toInt(); // Skip the 'R'. - start_from = index + 1; - count--; // We don't count the repeats value as part of the code array. - } - - // We need at least kProntoMinLength values for the code part. - if (count < kProntoMinLength) return false; - - // Now we know how many there are, allocate the memory to store them all. - code_array = newCodeArray(count); - - // Rest of the string are values for the code array. - // Now convert the hex strings to integers and place them in code_array. - count = 0; - do { - index = str.indexOf(',', start_from); - // Convert the hexadecimal value string to an unsigned integer. - code_array[count] = strtoul(str.substring(start_from, index).c_str(), - NULL, 16); - start_from = index + 1; - count++; - } while (index != -1); - - irsend.sendPronto(code_array, count, repeats); // All done. Send it. - free(code_array); // Free up the memory allocated. - if (count > 0) - return true; // We sent something. - return false; // We probably didn't. -} -#endif // SEND_PRONTO - -#if SEND_RAW -// Parse an IRremote Raw Hex String/code and send it. -// Args: -// str: A comma-separated String containing the freq and raw IR data. -// e.g. "38000,9000,4500,600,1450,600,900,650,1500,..." -// Requires at least two comma-separated values. -// First value is the transmission frequency in Hz or kHz. -// Returns: -// bool: Successfully sent or not. -bool parseStringAndSendRaw(const String str) { - uint16_t count; - uint16_t freq = 38000; // Default to 38kHz. - uint16_t *raw_array; - - // Find out how many items there are in the string. - count = countValuesInStr(str, ','); - - // We expect the frequency as the first comma separated value, so we need at - // least two values. If not, bail out. - if (count < 2) return false; - count--; // We don't count the frequency value as part of the raw array. - - // Now we know how many there are, allocate the memory to store them all. - raw_array = newCodeArray(count); - - // Grab the first value from the string, as it is the frequency. - int16_t index = str.indexOf(',', 0); - freq = str.substring(0, index).toInt(); - uint16_t start_from = index + 1; - // Rest of the string are values for the raw array. - // Now convert the strings to integers and place them in raw_array. - count = 0; - do { - index = str.indexOf(',', start_from); - raw_array[count] = str.substring(start_from, index).toInt(); - start_from = index + 1; - count++; - } while (index != -1); - - irsend.sendRaw(raw_array, count, freq); // All done. Send it. - free(raw_array); // Free up the memory allocated. - if (count > 0) - return true; // We sent something. - return false; // We probably didn't. -} -#endif // SEND_RAW - -// Parse the URL args to find the IR code. -void handleIr() { - uint64_t data = 0; - String data_str = ""; - int ir_type = 3; // Default to NEC codes. - uint16_t nbits = 0; - uint16_t repeat = 0; - - for (uint16_t i = 0; i < server.args(); i++) { - if (server.argName(i) == argType) - ir_type = atoi(server.arg(i).c_str()); - if (server.argName(i) == argData) { - data = getUInt64fromHex(server.arg(i).c_str()); - data_str = server.arg(i); - } - if (server.argName(i) == argBits) - nbits = atoi(server.arg(i).c_str()); - if (server.argName(i) == argRepeat) - repeat = atoi(server.arg(i).c_str()); - } - debug("New code received via HTTP"); - lastSendSucceeded = sendIRCode(ir_type, data, data_str.c_str(), nbits, - repeat); - handleRoot(); -} - -void handleNotFound() { - String message = "File Not Found\n\n"; - message += "URI: "; - message += server.uri(); - message += "\nMethod: "; - message += (server.method() == HTTP_GET)?"GET":"POST"; - message += "\nArguments: "; - message += server.args(); - message += "\n"; - for (uint8_t i=0; i < server.args(); i++) - message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; - server.send(404, "text/plain", message); -} - -void setup_wifi() { - delay(10); - // We start by connecting to a WiFi network - - wifiManager.setTimeout(300); // Time out after 5 mins. -#if USE_STATIC_IP - // Use a static IP config rather than the one supplied via DHCP. - wifiManager.setSTAStaticIPConfig(kIPAddress, kGateway, kSubnetMask); -#endif // USE_STATIC_IP - if (!wifiManager.autoConnect()) { - debug("Wifi failed to connect and hit timeout."); - delay(3000); - // Reboot. A.k.a. "Have you tried turning it Off and On again?" - ESP.reset(); - delay(5000); - } - - debug("WiFi connected. IP address: " + WiFi.localIP().toString()); -} - -void setup(void) { - irsend.begin(); - offset = irsend.calibrate(); -#if IR_RX -#if DECODE_HASH - // Ignore messages with less than minimum on or off pulses. - irrecv.setUnknownThreshold(kMinUnknownSize); -#endif // DECODE_HASH - irrecv.enableIRIn(); // Start the receiver -#endif // IR_RX - - #ifdef DEBUG - // Use SERIAL_TX_ONLY so that the RX pin can be freed up for GPIO/IR use. - Serial.begin(BAUD_RATE, SERIAL_8N1, SERIAL_TX_ONLY); - while (!Serial) // Wait for the serial connection to be establised. - delay(50); - Serial.println(); - debug("IRMQTTServer " _MY_VERSION_" has booted."); - #endif // DEBUG - - setup_wifi(); - - // Wait a bit for things to settle. - delay(1500); - - lastReconnectAttempt = 0; - - if (mdns.begin(HOSTNAME, WiFi.localIP())) { - debug("MDNS responder started"); - } - - // Setup the root web page. - server.on("/", handleRoot); - // Setup the page to handle web-based IR codes. - server.on("/ir", handleIr); - // Setup a reset page to cause WiFiManager information to be reset. - server.on("/reset", handleReset); - - // Setup the URL to allow Over-The-Air (OTA) firmware updates. - server.on("/update", HTTP_POST, [](){ - server.sendHeader("Connection", "close"); - server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK"); - ESP.restart(); - }, [](){ - HTTPUpload& upload = server.upload(); - if (upload.status == UPLOAD_FILE_START) { - WiFiUDP::stopAll(); - debug("Update: " + upload.filename); - uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & - 0xFFFFF000; - if (!Update.begin(maxSketchSpace)) { // start with max available size -#ifdef DEBUG - Update.printError(Serial); -#endif // DEBUG - } - } else if (upload.status == UPLOAD_FILE_WRITE) { - if (Update.write(upload.buf, upload.currentSize) != - upload.currentSize) { -#ifdef DEBUG - Update.printError(Serial); -#endif // DEBUG - } - } else if (upload.status == UPLOAD_FILE_END) { - if (Update.end(true)) { // true to set the size to the current progress - debug("Update Success: " + (String) upload.totalSize + - "\nRebooting..."); - } - } - yield(); - }); - - // Set up an error page. - server.onNotFound(handleNotFound); - - server.begin(); - debug("HTTP server started"); -} - -#ifdef MQTT_ENABLE -// MQTT subscribing to topic -void subscribing(const String topic_name) { - // subscription to topic for receiving data - if (mqtt_client.subscribe(topic_name.c_str())) { - debug("Subscription OK to " + topic_name); - } -} - -bool reconnect() { - // Loop a few times or until we're reconnected - uint16_t tries = 1; - while (!mqtt_client.connected() && tries <= 3) { - int connected = false; - // Attempt to connect - debug("Attempting MQTT connection to " MQTT_SERVER ":" + String(kMqttPort) + - "... "); - if (mqtt_user && mqtt_password) - connected = mqtt_client.connect(mqtt_clientid.c_str(), mqtt_user, - mqtt_password); - else - connected = mqtt_client.connect(mqtt_clientid.c_str()); - if (connected) { - // Once connected, publish an announcement... - mqtt_client.publish(MQTTack, "Connected"); - debug("connected."); - // Subscribing to topic(s) - subscribing(MQTTcommand); - } else { - debug("failed, rc=" + String(mqtt_client.state()) + - " Try again in a bit."); - // Wait for a bit before retrying - delay(tries << 7); // Linear increasing back-off (x128) - } - tries++; - } - return mqtt_client.connected(); -} -#endif // MQTT_ENABLE - -void loop(void) { - server.handleClient(); // Handle any web activity - -#ifdef MQTT_ENABLE - uint32_t now = millis(); - // MQTT client connection management - if (!mqtt_client.connected()) { - if (wasConnected) { - lastDisconnectedTime = now; - wasConnected = false; - mqttDisconnectCounter++; - } - // Reconnect if it's longer than kMqttReconnectTime since we last tried. - if (now - lastReconnectAttempt > kMqttReconnectTime) { - lastReconnectAttempt = now; - debug("client mqtt not connected, trying to connect"); - // Attempt to reconnect - if (reconnect()) { - lastReconnectAttempt = 0; - wasConnected = true; - if (boot) { - mqtt_client.publish(MQTTack, "IR Server just booted"); - boot = false; - } else { - String text = "IR Server just (re)connected to MQTT. " - "Lost connection about " + timeSince(lastConnectedTime); - mqtt_client.publish(MQTTack, text.c_str()); - } - lastConnectedTime = now; - debug("successful client mqtt connection"); - } - } - } else { - lastConnectedTime = now; - // MQTT loop - mqtt_client.loop(); - } -#endif // MQTT_ENABLE -#ifdef IR_RX - // Check if an IR code has been received via the IR RX module. - if (irrecv.decode(&capture)) { - lastIrReceivedTime = millis(); - lastIrReceived = String(capture.decode_type) + "," + - resultToHexidecimal(&capture); - // If it isn't an AC code, add the bits. - if (!hasACState(capture.decode_type)) - lastIrReceived += "," + String(capture.bits); - mqtt_client.publish(MQTTrecv, lastIrReceived.c_str()); - irRecvCounter++; - debug("Incoming IR message sent to MQTT: " + lastIrReceived); - } -#endif // IR_RX - delay(100); -} - -// Arduino framework doesn't support strtoull(), so make our own one. -uint64_t getUInt64fromHex(char const *str) { - uint64_t result = 0; - uint16_t offset = 0; - // Skip any leading '0x' or '0X' prefix. - if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) - offset = 2; - for (; isxdigit((unsigned char)str[offset]); offset++) { - char c = str[offset]; - result *= 16; - if (isdigit(c)) /* '0' .. '9' */ - result += c - '0'; - else if (isupper(c)) /* 'A' .. 'F' */ - result += c - 'A' + 10; - else /* 'a' .. 'f'*/ - result += c - 'a' + 10; - } - return result; -} - -// Transmit the given IR message. -// -// Args: -// ir_type: enum of the protocol to be sent. -// code: Numeric payload of the IR message. Most protocols use this. -// code_str: The unparsed code to be sent. Used by complex protocol encodings. -// bits: Nr. of bits in the protocol. 0 means use the protocol's default. -// repeat: Nr. of times the message is to be repeated. (Not all protcols.) -// Returns: -// bool: Successfully sent or not. -bool sendIRCode(int const ir_type, uint64_t const code, char const * code_str, - uint16_t bits, uint16_t repeat) { - // Create a pseudo-lock so we don't try to send two codes at the same time. - while (ir_lock) - delay(20); - ir_lock = true; - - bool success = true; // Assume success. - - // send the IR message. - switch (ir_type) { -#if SEND_RC5 - case RC5: // 1 - if (bits == 0) - bits = kRC5Bits; - irsend.sendRC5(code, bits, repeat); - break; -#endif -#if SEND_RC6 - case RC6: // 2 - if (bits == 0) - bits = kRC6Mode0Bits; - irsend.sendRC6(code, bits, repeat); - break; -#endif -#if SEND_NEC - case NEC: // 3 - if (bits == 0) - bits = kNECBits; - irsend.sendNEC(code, bits, repeat); - break; -#endif -#if SEND_SONY - case SONY: // 4 - if (bits == 0) - bits = kSony12Bits; - repeat = std::max(repeat, kSonyMinRepeat); - irsend.sendSony(code, bits, repeat); - break; -#endif -#if SEND_PANASONIC - case PANASONIC: // 5 - if (bits == 0) - bits = kPanasonicBits; - irsend.sendPanasonic64(code, bits, repeat); - break; -#endif -#if SEND_JVC - case JVC: // 6 - if (bits == 0) - bits = kJvcBits; - irsend.sendJVC(code, bits, repeat); - break; -#endif -#if SEND_SAMSUNG - case SAMSUNG: // 7 - if (bits == 0) - bits = kSamsungBits; - irsend.sendSAMSUNG(code, bits, repeat); - break; -#endif -#if SEND_WHYNTER - case WHYNTER: // 8 - if (bits == 0) - bits = kWhynterBits; - irsend.sendWhynter(code, bits, repeat); - break; -#endif -#if SEND_AIWA_RC_T501 - case AIWA_RC_T501: // 9 - if (bits == 0) - bits = kAiwaRcT501Bits; - repeat = std::max(repeat, kAiwaRcT501MinRepeats); - irsend.sendAiwaRCT501(code, bits, repeat); - break; -#endif -#if SEND_LG - case LG: // 10 - if (bits == 0) - bits = kLgBits; - irsend.sendLG(code, bits, repeat); - break; -#endif -#if SEND_MITSUBISHI - case MITSUBISHI: // 12 - if (bits == 0) - bits = kMitsubishiBits; - repeat = std::max(repeat, kMitsubishiMinRepeat); - irsend.sendMitsubishi(code, bits, repeat); - break; -#endif -#if SEND_DISH - case DISH: // 13 - if (bits == 0) - bits = kDishBits; - repeat = std::max(repeat, kDishMinRepeat); - irsend.sendDISH(code, bits, repeat); - break; -#endif -#if SEND_SHARP - case SHARP: // 14 - if (bits == 0) - bits = kSharpBits; - irsend.sendSharpRaw(code, bits, repeat); - break; -#endif -#if SEND_COOLIX - case COOLIX: // 15 - if (bits == 0) - bits = kCoolixBits; - irsend.sendCOOLIX(code, bits, repeat); - break; -#endif - case DAIKIN: // 16 - case KELVINATOR: // 18 - case MITSUBISHI_AC: // 20 - case GREE: // 24 - case ARGO: // 27 - case TROTEC: // 28 - case TOSHIBA_AC: // 32 - case FUJITSU_AC: // 33 - case HAIER_AC: // 38 - case HAIER_AC_YRW02: // 44 - case HITACHI_AC: // 40 - case HITACHI_AC1: // 41 - case HITACHI_AC2: // 42 - case WHIRLPOOL_AC: // 45 - case SAMSUNG_AC: // 46 - case ELECTRA_AC: // 48 - case PANASONIC_AC: // 49 - case MWM: // 52 - success = parseStringAndSendAirCon(ir_type, code_str); - break; -#if SEND_DENON - case DENON: // 17 - if (bits == 0) - bits = DENON_BITS; - irsend.sendDenon(code, bits, repeat); - break; -#endif -#if SEND_SHERWOOD - case SHERWOOD: // 19 - if (bits == 0) - bits = kSherwoodBits; - repeat = std::max(repeat, kSherwoodMinRepeat); - irsend.sendSherwood(code, bits, repeat); - break; -#endif -#if SEND_RCMM - case RCMM: // 21 - if (bits == 0) - bits = kRCMMBits; - irsend.sendRCMM(code, bits, repeat); - break; -#endif -#if SEND_SANYO - case SANYO_LC7461: // 22 - if (bits == 0) - bits = kSanyoLC7461Bits; - irsend.sendSanyoLC7461(code, bits, repeat); - break; -#endif -#if SEND_RC5 - case RC5X: // 23 - if (bits == 0) - bits = kRC5XBits; - irsend.sendRC5(code, bits, repeat); - break; -#endif -#if SEND_PRONTO - case PRONTO: // 25 - success = parseStringAndSendPronto(code_str, repeat); - break; -#endif -#if SEND_NIKAI - case NIKAI: // 29 - if (bits == 0) - bits = kNikaiBits; - irsend.sendNikai(code, bits, repeat); - break; -#endif -#if SEND_RAW - case RAW: // 30 - success = parseStringAndSendRaw(code_str); - break; -#endif -#if SEND_GLOBALCACHE - case GLOBALCACHE: // 31 - success = parseStringAndSendGC(code_str); - break; -#endif -#if SEND_MIDEA - case MIDEA: // 34 - if (bits == 0) - bits = kMideaBits; - irsend.sendMidea(code, bits, repeat); - break; -#endif -#if SEND_MAGIQUEST - case MAGIQUEST: // 35 - if (bits == 0) - bits = kMagiquestBits; - irsend.sendMagiQuest(code, bits, repeat); - break; -#endif -#if SEND_LASERTAG - case LASERTAG: // 36 - if (bits == 0) - bits = kLasertagBits; - irsend.sendLasertag(code, bits, repeat); - break; -#endif -#if SEND_CARRIER_AC - case CARRIER_AC: // 37 - if (bits == 0) - bits = kCarrierAcBits; - irsend.sendCarrierAC(code, bits, repeat); - break; -#endif -#if SEND_MITSUBISHI2 - case MITSUBISHI2: // 39 - if (bits == 0) - bits = kMitsubishiBits; - repeat = std::max(repeat, kMitsubishiMinRepeat); - irsend.sendMitsubishi2(code, bits, repeat); - break; -#endif -#if SEND_GICABLE - case GICABLE: // 43 - if (bits == 0) - bits = kGicableBits; - repeat = std::max(repeat, kGicableMinRepeat); - irsend.sendGICable(code, bits, repeat); - break; -#endif -#if SEND_LUTRON - case LUTRON: // 47 - if (bits == 0) - bits = kLutronBits; - irsend.sendLutron(code, bits, repeat); - break; -#endif -#if SEND_PIONEER - case PIONEER: // 50 - if (bits == 0) - bits = kPioneerBits; - irsend.sendPioneer(code, bits, repeat); - break; -#endif - -#if SEND_LG - case LG2: // 51 - if (bits == 0) - bits = kLgBits; - irsend.sendLG2(code, bits, repeat); - break; -#endif - default: - // If we got here, we didn't know how to send it. - success = false; - } - lastSendTime = millis(); - // Release the lock. - ir_lock = false; - - // Indicate that we sent the message or not. - if (success) { - sendReqCounter++; - debug("Sent the IR message:"); - } else { - debug("Failed to send IR Message:"); - } - debug("Type: " + String(ir_type)); - // For "long" codes we basically repeat what we got. - if (hasACState((decode_type_t) ir_type) || - ir_type == PRONTO || - ir_type == RAW || - ir_type == GLOBALCACHE) { - debug("Code: "); - debug(code_str); - // Confirm what we were asked to send was sent. -#ifdef MQTT_ENABLE - if (success) { - if (ir_type == PRONTO && repeat > 0) - mqtt_client.publish(MQTTack, (String(ir_type) + ",R" + - String(repeat) + "," + - String(code_str)).c_str()); - else - mqtt_client.publish(MQTTack, (String(ir_type) + "," + - String(code_str)).c_str()); - } -#endif // MQTT_ENABLE - } else { // For "short" codes, we break it down a bit more before we report. - debug("Code: 0x" + uint64ToString(code, 16)); - debug("Bits: " + String(bits)); - debug("Repeats: " + String(repeat)); -#ifdef MQTT_ENABLE - if (success) - mqtt_client.publish(MQTTack, (String(ir_type) + "," + - uint64ToString(code, 16) - + "," + String(bits) + "," + - String(repeat)).c_str()); -#endif // MQTT_ENABLE - } - return success; -} - -#ifdef MQTT_ENABLE -void receivingMQTT(String const topic_name, String const callback_str) { - char* tok_ptr; - uint64_t code = 0; - uint16_t nbits = 0; - uint16_t repeat = 0; - - debug("Receiving data by MQTT topic " + topic_name); - - // Make a copy of the callback string as strtok destroys it. - char* callback_c_str = strdup(callback_str.c_str()); - debug("MQTT Payload (raw): " + callback_str); - // Save the message as the last command seen (global). - lastMqttCmd = callback_str; - lastMqttCmdTime = millis(); - - // Get the numeric protocol type. - int ir_type = strtoul(strtok_r(callback_c_str, ",", &tok_ptr), NULL, 10); - char* next = strtok_r(NULL, ",", &tok_ptr); - // If there is unparsed string left, try to convert it assuming it's hex. - if (next != NULL) { - code = getUInt64fromHex(next); - next = strtok_r(NULL, ",", &tok_ptr); - } else { - // We require at least two value in the string. Give up. - return; - } - // If there is still string left, assume it is the bit size. - if (next != NULL) { - nbits = atoi(next); - next = strtok_r(NULL, ",", &tok_ptr); - } - // If there is still string left, assume it is the repeat count. - if (next != NULL) - repeat = atoi(next); - - free(callback_c_str); - - - // send received MQTT value by IR signal - lastSendSucceeded = sendIRCode( - ir_type, code, - callback_str.substring(callback_str.indexOf(",") + 1).c_str(), - nbits, repeat); -} - -// Callback function, when the gateway receive an MQTT value on the topics -// subscribed this function is called -void callback(char* topic, byte* payload, unsigned int length) { - // In order to republish this payload, a copy must be made - // as the orignal payload buffer will be overwritten whilst - // constructing the PUBLISH packet. - // Allocate the correct amount of memory for the payload copy - byte* payload_copy = reinterpret_cast(malloc(length + 1)); - // Copy the payload to the new buffer - memcpy(payload_copy, payload, length); - - // Conversion to a printable string - payload_copy[length] = '\0'; - String callback_string = String(reinterpret_cast(payload_copy)); - String topic_name = String(reinterpret_cast(topic)); - - // launch the function to treat received data - receivingMQTT(topic_name, callback_string); - - // Free the memory - free(payload_copy); -} -#endif // MQTT_ENABLE diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/platformio.ini deleted file mode 100644 index eeb8d1f2e..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/platformio.ini +++ /dev/null @@ -1,17 +0,0 @@ -[platformio] -lib_extra_dirs = ../../ -src_dir=. - -[common] -build_flags = -lib_deps_builtin = -lib_deps_external = - -[env:nodemcuv2] -platform = espressif8266 -framework = arduino -board = nodemcuv2 -build_flags = ${common.build_flags} -lib_deps = - ${common.lib_deps_builtin} - ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp b/lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp deleted file mode 100644 index 7864625a5..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/src/IRutils.cpp +++ /dev/null @@ -1,470 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRutils.h" -#ifndef UNIT_TEST -#include -#endif - -#define __STDC_LIMIT_MACROS -#include -#include -#ifndef ARDUINO -#include -#endif -#include "IRrecv.h" -#include "IRremoteESP8266.h" - -// Reverse the order of the requested least significant nr. of bits. -// Args: -// input: Bit pattern/integer to reverse. -// nbits: Nr. of bits to reverse. -// Returns: -// The reversed bit pattern. -uint64_t reverseBits(uint64_t input, uint16_t nbits) { - if (nbits <= 1) return input; // Reversing <= 1 bits makes no change at all. - // Cap the nr. of bits to rotate to the max nr. of bits in the input. - nbits = std::min(nbits, (uint16_t)(sizeof(input) * 8)); - uint64_t output = 0; - for (uint16_t i = 0; i < nbits; i++) { - output <<= 1; - output |= (input & 1); - input >>= 1; - } - // Merge any remaining unreversed bits back to the top of the reversed bits. - return (input << nbits) | output; -} - -// Convert a uint64_t (unsigned long long) to a string. -// Arduino String/toInt/Serial.print() can't handle printing 64 bit values. -// -// Args: -// input: The value to print -// base: The output base. -// Returns: -// A string representation of the integer. -// Note: Based on Arduino's Print::printNumber() -#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. -String uint64ToString(uint64_t input, uint8_t base) { - String result = ""; -#else -std::string uint64ToString(uint64_t input, uint8_t base) { - std::string result = ""; -#endif - // prevent issues if called with base <= 1 - if (base < 2) base = 10; - // Check we have a base that we can actually print. - // i.e. [0-9A-Z] == 36 - if (base > 36) base = 10; - - do { - char c = input % base; - input /= base; - - if (c < 10) - c += '0'; - else - c += 'A' - 10; - result = c + result; - } while (input); - return result; -} - -#ifdef ARDUINO -// Print a uint64_t/unsigned long long to the Serial port -// Serial.print() can't handle printing long longs. (uint64_t) -// -// Args: -// input: The value to print -// base: The output base. -void serialPrintUint64(uint64_t input, uint8_t base) { - Serial.print(uint64ToString(input, base)); -} -#endif - -// Convert a protocol type (enum etc) to a human readable string. -// Args: -// protocol: Nr. (enum) of the protocol. -// isRepeat: A flag indicating if it is a repeat message of the protocol. -// Returns: -// A string containing the protocol name. -#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. -String typeToString(const decode_type_t protocol, const bool isRepeat) { - String result = ""; -#else -std::string typeToString(const decode_type_t protocol, const bool isRepeat) { - std::string result = ""; -#endif - switch (protocol) { - default: - case UNKNOWN: - result = "UNKNOWN"; - break; - case UNUSED: - result = "UNUSED"; - break; - case AIWA_RC_T501: - result = "AIWA_RC_T501"; - break; - case ARGO: - result = "ARGO"; - break; - case CARRIER_AC: - result = "CARRIER_AC"; - break; - case COOLIX: - result = "COOLIX"; - break; - case DAIKIN: - result = "DAIKIN"; - break; - case DENON: - result = "DENON"; - break; - case DISH: - result = "DISH"; - break; - case ELECTRA_AC: - result = "ELECTRA_AC"; - break; - case FUJITSU_AC: - result = "FUJITSU_AC"; - break; - case GICABLE: - result = "GICABLE"; - break; - case GLOBALCACHE: - result = "GLOBALCACHE"; - break; - case GREE: - result = "GREE"; - break; - case HAIER_AC: - result = "HAIER_AC"; - break; - case HAIER_AC_YRW02: - result = "HAIER_AC_YRW02"; - break; - case HITACHI_AC: - result = "HITACHI_AC"; - break; - case HITACHI_AC1: - result = "HITACHI_AC1"; - break; - case HITACHI_AC2: - result = "HITACHI_AC2"; - break; - case JVC: - result = "JVC"; - break; - case KELVINATOR: - result = "KELVINATOR"; - break; - case LG: - result = "LG"; - break; - case LG2: - result = "LG2"; - break; - case LASERTAG: - result = "LASERTAG"; - break; - case LUTRON: - result = "LUTRON"; - break; - case MAGIQUEST: - result = "MAGIQUEST"; - break; - case MIDEA: - result = "MIDEA"; - break; - case MITSUBISHI: - result = "MITSUBISHI"; - break; - case MITSUBISHI2: - result = "MITSUBISHI2"; - break; - case MITSUBISHI_AC: - result = "MITSUBISHI_AC"; - break; - case MWM: - result = "MWM"; - break; - case NEC: - result = "NEC"; - break; - case NEC_LIKE: - result = "NEC (non-strict)"; - break; - case NIKAI: - result = "NIKAI"; - break; - case PANASONIC: - result = "PANASONIC"; - break; - case PANASONIC_AC: - result = "PANASONIC_AC"; - break; - case PIONEER: - result = "PIONEER"; - break; - case PRONTO: - result = "PRONTO"; - break; - case RAW: - result = "RAW"; - break; - case RC5: - result = "RC5"; - break; - case RC5X: - result = "RC5X"; - break; - case RC6: - result = "RC6"; - break; - case RCMM: - result = "RCMM"; - break; - case SAMSUNG: - result = "SAMSUNG"; - break; - case SAMSUNG_AC: - result = "SAMSUNG_AC"; - break; - case SANYO: - result = "SANYO"; - break; - case SANYO_LC7461: - result = "SANYO_LC7461"; - break; - case SHARP: - result = "SHARP"; - break; - case SHERWOOD: - result = "SHERWOOD"; - break; - case SONY: - result = "SONY"; - break; - case TOSHIBA_AC: - result = "TOSHIBA_AC"; - break; - case TROTEC: - result = "TROTEC"; - break; - case WHIRLPOOL_AC: - result = "WHIRLPOOL_AC"; - break; - case WHYNTER: - result = "WHYNTER"; - break; - } - if (isRepeat) result += " (Repeat)"; - return result; -} - -// Does the given protocol use a complex state as part of the decode? -bool hasACState(const decode_type_t protocol) { - switch (protocol) { - case DAIKIN: - case ELECTRA_AC: - case FUJITSU_AC: - case GREE: - case HAIER_AC: - case HAIER_AC_YRW02: - case HITACHI_AC: - case HITACHI_AC1: - case HITACHI_AC2: - case KELVINATOR: - case MITSUBISHI_AC: - case MWM: - case PANASONIC_AC: - case SAMSUNG_AC: - case TOSHIBA_AC: - case WHIRLPOOL_AC: - return true; - default: - return false; - } -} - -// Return the corrected length of a 'raw' format array structure -// after over-large values are converted into multiple entries. -// Args: -// results: A ptr to a decode result. -// Returns: -// A uint16_t containing the length. -uint16_t getCorrectedRawLength(const decode_results *results) { - uint16_t extended_length = results->rawlen - 1; - for (uint16_t i = 0; i < results->rawlen - 1; i++) { - uint32_t usecs = results->rawbuf[i] * kRawTick; - // Add two extra entries for multiple larger than UINT16_MAX it is. - extended_length += (usecs / (UINT16_MAX + 1)) * 2; - } - return extended_length; -} - -// Return a string containing the key values of a decode_results structure -// in a C/C++ code style format. -#ifdef ARDUINO -String resultToSourceCode(const decode_results *results) { - String output = ""; -#else -std::string resultToSourceCode(const decode_results *results) { - std::string output = ""; -#endif - // Start declaration - output += "uint16_t "; // variable type - output += "rawData["; // array name - output += uint64ToString(getCorrectedRawLength(results), 10); - // array size - output += "] = {"; // Start declaration - - // Dump data - for (uint16_t i = 1; i < results->rawlen; i++) { - uint32_t usecs; - for (usecs = results->rawbuf[i] * kRawTick; usecs > UINT16_MAX; - usecs -= UINT16_MAX) { - output += uint64ToString(UINT16_MAX); - if (i % 2) - output += ", 0, "; - else - output += ", 0, "; - } - output += uint64ToString(usecs, 10); - if (i < results->rawlen - 1) - output += ", "; // ',' not needed on the last one - if (i % 2 == 0) output += " "; // Extra if it was even. - } - - // End declaration - output += "};"; - - // Comment - output += " // " + typeToString(results->decode_type, results->repeat); - // Only display the value if the decode type doesn't have an A/C state. - if (!hasACState(results->decode_type)) - output += " " + uint64ToString(results->value, 16); - output += "\n"; - - // Now dump "known" codes - if (results->decode_type != UNKNOWN) { - if (hasACState(results->decode_type)) { -#if DECODE_AC - uint16_t nbytes = results->bits / 8; - output += "uint8_t state[" + uint64ToString(nbytes) + "] = {"; - for (uint16_t i = 0; i < nbytes; i++) { - output += "0x"; - if (results->state[i] < 0x10) output += "0"; - output += uint64ToString(results->state[i], 16); - if (i < nbytes - 1) output += ", "; - } - output += "};\n"; -#endif // DECODE_AC - } else { - // Simple protocols - // Some protocols have an address &/or command. - // NOTE: It will ignore the atypical case when a message has been - // decoded but the address & the command are both 0. - if (results->address > 0 || results->command > 0) { - output += "uint32_t address = 0x" + - uint64ToString(results->address, 16) + ";\n"; - output += "uint32_t command = 0x" + - uint64ToString(results->command, 16) + ";\n"; - } - // Most protocols have data - output += - "uint64_t data = 0x" + uint64ToString(results->value, 16) + ";\n"; - } - } - return output; -} - -// Dump out the decode_results structure. -// -#ifdef ARDUINO -String resultToTimingInfo(const decode_results *results) { - String output = ""; - String value = ""; -#else -std::string resultToTimingInfo(const decode_results *results) { - std::string output = ""; - std::string value = ""; -#endif - output += "Raw Timing[" + uint64ToString(results->rawlen - 1, 10) + "]:\n"; - - for (uint16_t i = 1; i < results->rawlen; i++) { - if (i % 2 == 0) - output += "-"; // even - else - output += " +"; // odd - value = uint64ToString(results->rawbuf[i] * kRawTick); - // Space pad the value till it is at least 6 chars long. - while (value.length() < 6) value = " " + value; - output += value; - if (i < results->rawlen - 1) output += ", "; // ',' not needed for last one - if (!(i % 8)) output += "\n"; // Newline every 8 entries. - } - output += "\n"; - return output; -} - -// Convert the decode_results structure's value/state to simple hexadecimal. -// -#ifdef ARDUINO -String resultToHexidecimal(const decode_results *result) { - String output = ""; -#else -std::string resultToHexidecimal(const decode_results *result) { - std::string output = ""; -#endif - if (hasACState(result->decode_type)) { -#if DECODE_AC - for (uint16_t i = 0; result->bits > i * 8; i++) { - if (result->state[i] < 0x10) output += "0"; // Zero pad - output += uint64ToString(result->state[i], 16); - } -#endif // DECODE_AC - } else { - output += uint64ToString(result->value, 16); - } - return output; -} - -// Dump out the decode_results structure. -// -#ifdef ARDUINO -String resultToHumanReadableBasic(const decode_results *results) { - String output = ""; -#else -std::string resultToHumanReadableBasic(const decode_results *results) { - std::string output = ""; -#endif - // Show Encoding standard - output += - "Encoding : " + typeToString(results->decode_type, results->repeat) + - "\n"; - - // Show Code & length - output += "Code : "; - output += resultToHexidecimal(results); - output += " (" + uint64ToString(results->bits) + " bits)\n"; - return output; -} - -uint8_t sumBytes(uint8_t *start, const uint16_t length, const uint8_t init) { - uint8_t checksum = init; - uint8_t *ptr; - for (ptr = start; ptr - start < length; ptr++) checksum += *ptr; - return checksum; -} - -uint64_t invertBits(const uint64_t data, const uint16_t nbits) { - // No change if we are asked to invert no bits. - if (nbits == 0) return data; - uint64_t result = ~data; - // If we are asked to invert all the bits or more than we have, it's simple. - if (nbits >= sizeof(data) * 8) return result; - // Mask off any unwanted bits and return the result. - return (result & ((1ULL << nbits) - 1)); -} diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.cpp deleted file mode 100644 index b94b4a63a..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.cpp +++ /dev/null @@ -1,750 +0,0 @@ -/* -An Arduino sketch to emulate IR Daikin ARC433** remote control unit -Read more at: -http://harizanov.com/2012/02/control-daikin-air-conditioner-over-the-internet/ - -Copyright 2016 sillyfrog -Copyright 2017 sillyfrog, crankyoldgit -*/ - -#include "ir_Daikin.h" -#include -#ifndef ARDUINO -#include -#endif -#include "IRrecv.h" -#include "IRremoteESP8266.h" -#include "IRsend.h" -#include "IRutils.h" - -// DDDDD AAA IIIII KK KK IIIII NN NN -// DD DD AAAAA III KK KK III NNN NN -// DD DD AA AA III KKKK III NN N NN -// DD DD AAAAAAA III KK KK III NN NNN -// DDDDDD AA AA IIIII KK KK IIIII NN NN - -// Constants -// Ref: -// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote -// http://rdlab.cdmt.vn/project-2013/daikin-ir-protocol - -#if SEND_DAIKIN -// Original header -// static uint8_t header1[DAIKIN_HEADER1_LENGTH]; -// header1[0] = 0b00010001; -// header1[1] = 0b11011010; -// header1[2] = 0b00100111; -// header1[3] = 0b00000000; -// header1[4] = 0b11000101; -// header1[5] = 0b00000000; -// header1[6] = 0b00000000; -// header1[7] = 0b11010111; - -// Send a Daikin A/C message. -// -// Args: -// data: An array of kDaikinStateLength bytes containing the IR command. -// -// Status: STABLE -// -// Ref: -// IRDaikinESP.cpp -// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote -void IRsend::sendDaikin(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - if (nbytes < kDaikinStateLength) - return; // Not enough bytes to send a proper message. - - for (uint16_t r = 0; r <= repeat; r++) { - // Send the header, 0b00000 - sendGeneric(0, 0, // No header for the header - kDaikinBitMark, kDaikinOneSpace, kDaikinBitMark, - kDaikinZeroSpace, kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, - (uint64_t)0b00000, 5, 38, false, 0, 50); - // Leading header - // Do this as a constant to save RAM and keep in flash memory - sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, - kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, - kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, - kDaikinFirstHeader64, 64, 38, false, 0, 50); - // Data #1 - sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, - kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, - kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, data, 8, 38, - false, 0, 50); - // Data #2 - sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, - kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, - kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, data + 8, - nbytes - 8, 38, false, 0, 50); - } -} -#endif // SEND_DAIKIN - -IRDaikinESP::IRDaikinESP(uint16_t pin) : _irsend(pin) { stateReset(); } - -void IRDaikinESP::begin() { _irsend.begin(); } - -#if SEND_DAIKIN -void IRDaikinESP::send() { - checksum(); - _irsend.sendDaikin(daikin); -} -#endif // SEND_DAIKIN - -// Calculate the checksum for a given data block. -// Args: -// block: Ptr to the start of the data block. -// length: Nr. of bytes to checksum. -// Returns: -// A byte containing the calculated checksum. -uint8_t IRDaikinESP::calcBlockChecksum(const uint8_t *block, - const uint16_t length) { - uint8_t sum = 0; - // Daikin checksum is just the addition of all the data bytes - // in the block but capped to 8 bits. - for (uint16_t i = 0; i < length; i++, block++) sum += *block; - return sum & 0xFFU; -} - -// Verify the checksum is valid for a given state. -// Args: -// state: The array to verify the checksum of. -// length: The size of the state. -// Returns: -// A boolean. -bool IRDaikinESP::validChecksum(const uint8_t state[], const uint16_t length) { - if (length < 8 || state[7] != calcBlockChecksum(state, 7)) return false; - if (length < 10 || - state[length - 1] != calcBlockChecksum(state + 8, length - 9)) - return false; - return true; -} - -// Calculate and set the checksum values for the internal state. -void IRDaikinESP::checksum() { - daikin[7] = calcBlockChecksum(daikin, 7); - daikin[26] = calcBlockChecksum(daikin + 8, 17); -} - -void IRDaikinESP::stateReset() { - for (uint8_t i = 0; i < kDaikinStateLength; i++) daikin[i] = 0x0; - - daikin[0] = 0x11; - daikin[1] = 0xDA; - daikin[2] = 0x27; - daikin[4] = 0x42; - // daikin[7] is a checksum byte, it will be set by checksum(). - daikin[8] = 0x11; - daikin[9] = 0xDA; - daikin[10] = 0x27; - daikin[13] = 0x49; - daikin[14] = 0x1E; - daikin[16] = 0xB0; - daikin[19] = 0x06; - daikin[20] = 0x60; - daikin[23] = 0xC0; - // daikin[26] is a checksum byte, it will be set by checksum(). - checksum(); -} - -uint8_t *IRDaikinESP::getRaw() { - checksum(); // Ensure correct settings before sending. - return daikin; -} - -void IRDaikinESP::setRaw(uint8_t new_code[]) { - for (uint8_t i = 0; i < kDaikinStateLength; i++) daikin[i] = new_code[i]; -} - -void IRDaikinESP::on() { - // state = ON; - setBit(kDaikinBytePower, kDaikinBitPower); -} - -void IRDaikinESP::off() { - // state = OFF; - clearBit(kDaikinBytePower, kDaikinBitPower); -} - -void IRDaikinESP::setPower(bool state) { - if (state) - on(); - else - off(); -} - -bool IRDaikinESP::getPower() { - return (getBit(kDaikinBytePower, kDaikinBitPower) > 0); -} - -// Set the temp in deg C -void IRDaikinESP::setTemp(uint8_t temp) { - if (temp < kDaikinMinTemp) - temp = kDaikinMinTemp; - else if (temp > kDaikinMaxTemp) - temp = kDaikinMaxTemp; - daikin[14] = temp * 2; -} - -uint8_t IRDaikinESP::getTemp() { return daikin[14] / 2; } - -// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet -void IRDaikinESP::setFan(uint8_t fan) { - // Set the fan speed bits, leave low 4 bits alone - uint8_t fanset; - if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto) - fanset = fan; - else if (fan < kDaikinFanMin || fan > kDaikinFanMax) - fanset = kDaikinFanAuto; - else - fanset = 2 + fan; - daikin[16] &= 0x0F; - daikin[16] |= (fanset << 4); -} - -uint8_t IRDaikinESP::getFan() { - uint8_t fan = daikin[16] >> 4; - if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2; - return fan; -} - -uint8_t IRDaikinESP::getMode() { - /* - kDaikinCool - kDaikinHeat - kDaikinFan - kDaikinAuto - kDaikinDry - */ - return daikin[13] >> 4; -} - -void IRDaikinESP::setMode(uint8_t mode) { - switch (mode) { - case kDaikinCool: - case kDaikinHeat: - case kDaikinFan: - case kDaikinDry: - break; - default: - mode = kDaikinAuto; - } - mode <<= 4; - daikin[13] &= 0b10001111; - daikin[13] |= mode; -} - -void IRDaikinESP::setSwingVertical(bool state) { - if (state) - daikin[16] |= 0x0F; - else - daikin[16] &= 0xF0; -} - -bool IRDaikinESP::getSwingVertical() { return daikin[16] & 0x01; } - -void IRDaikinESP::setSwingHorizontal(bool state) { - if (state) - daikin[17] |= 0x0F; - else - daikin[17] &= 0xF0; -} - -bool IRDaikinESP::getSwingHorizontal() { return daikin[17] & 0x01; } - -void IRDaikinESP::setQuiet(bool state) { - if (state) { - setBit(kDaikinByteSilent, kDaikinBitSilent); - // Powerful & Quiet mode being on are mutually exclusive. - setPowerful(false); - } else { - clearBit(kDaikinByteSilent, kDaikinBitSilent); - } -} - -bool IRDaikinESP::getQuiet() { - return (getBit(kDaikinByteSilent, kDaikinBitSilent) > 0); -} - -void IRDaikinESP::setPowerful(bool state) { - if (state) { - setBit(kDaikinBytePowerful, kDaikinBitPowerful); - // Powerful, Quiet, & Econo mode being on are mutually exclusive. - setQuiet(false); - setEcono(false); - } else { - clearBit(kDaikinBytePowerful, kDaikinBitPowerful); - } -} - -bool IRDaikinESP::getPowerful() { - return (getBit(kDaikinBytePowerful, kDaikinBitPowerful) > 0); -} - -void IRDaikinESP::setSensor(bool state) { - if (state) - setBit(kDaikinByteSensor, kDaikinBitSensor); - else - clearBit(kDaikinByteSensor, kDaikinBitSensor); -} - -bool IRDaikinESP::getSensor() { - return (getBit(kDaikinByteSensor, kDaikinBitSensor) > 0); -} - -void IRDaikinESP::setEcono(bool state) { - if (state) { - setBit(kDaikinByteEcono, kDaikinBitEcono); - // Powerful & Econo mode being on are mutually exclusive. - setPowerful(false); - } else { - clearBit(kDaikinByteEcono, kDaikinBitEcono); - } -} - -bool IRDaikinESP::getEcono() { - return (getBit(kDaikinByteEcono, kDaikinBitEcono) > 0); -} - -void IRDaikinESP::setEye(bool state) { - if (state) - setBit(kDaikinByteEye, kDaikinBitEye); - else - clearBit(kDaikinByteEye, kDaikinBitEye); -} - -bool IRDaikinESP::getEye() { - return (getBit(kDaikinByteEye, kDaikinBitEye) > 0); -} - -void IRDaikinESP::setMold(bool state) { - if (state) - setBit(kDaikinByteMold, kDaikinBitMold); - else - clearBit(kDaikinByteMold, kDaikinBitMold); -} - -bool IRDaikinESP::getMold() { - return (getBit(kDaikinByteMold, kDaikinBitMold) > 0); -} - -void IRDaikinESP::setBit(uint8_t byte, uint8_t bitmask) { - daikin[byte] |= bitmask; -} - -void IRDaikinESP::clearBit(uint8_t byte, uint8_t bitmask) { - bitmask = ~bitmask; - daikin[byte] &= bitmask; -} - -uint8_t IRDaikinESP::getBit(uint8_t byte, uint8_t bitmask) { - return daikin[byte] & bitmask; -} - -// starttime: Number of minutes after midnight, in 10 minutes increments -void IRDaikinESP::enableOnTimer(uint16_t starttime) { - setBit(kDaikinByteOnTimer, kDaikinBitOnTimer); - daikin[18] = (uint8_t)(starttime & 0x00FF); - // only keep 4 bits - daikin[19] &= 0xF0; - daikin[19] |= (uint8_t)((starttime >> 8) & 0x0F); -} - -void IRDaikinESP::disableOnTimer() { - enableOnTimer(0x600); - clearBit(kDaikinByteOnTimer, kDaikinBitOnTimer); -} - -uint16_t IRDaikinESP::getOnTime() { - uint16_t ret; - ret = daikin[19] & 0x0F; - ret = ret << 8; - ret += daikin[18]; - return ret; -} - -bool IRDaikinESP::getOnTimerEnabled() { - return getBit(kDaikinByteOnTimer, kDaikinBitOnTimer); -} - -// endtime: Number of minutes after midnight, in 10 minutes increments -void IRDaikinESP::enableOffTimer(uint16_t endtime) { - setBit(kDaikinByteOffTimer, kDaikinBitOffTimer); - daikin[20] = (uint8_t)((endtime >> 4) & 0xFF); - daikin[19] &= 0x0F; - daikin[19] |= (uint8_t)((endtime & 0x000F) << 4); -} - -void IRDaikinESP::disableOffTimer() { - enableOffTimer(0x600); - clearBit(kDaikinByteOffTimer, kDaikinBitOffTimer); -} - -uint16_t IRDaikinESP::getOffTime() { - uint16_t ret, tmp; - ret = daikin[20]; - ret <<= 4; - tmp = daikin[19] & 0xF0; - tmp >>= 4; - ret += tmp; - return ret; -} - -bool IRDaikinESP::getOffTimerEnabled() { - return getBit(kDaikinByteOffTimer, kDaikinBitOffTimer); -} - -void IRDaikinESP::setCurrentTime(uint16_t numMins) { - if (numMins > 24 * 60) numMins = 0; // If > 23:59, set to 00:00 - daikin[5] = (uint8_t)(numMins & 0x00FF); - // only keep 4 bits - daikin[6] &= 0xF0; - daikin[6] |= (uint8_t)((numMins >> 8) & 0x0F); -} - -uint16_t IRDaikinESP::getCurrentTime() { - uint16_t ret; - ret = daikin[6] & 0x0F; - ret <<= 8; - ret += daikin[5]; - return ret; -} - -#ifdef ARDUINO -String IRDaikinESP::renderTime(uint16_t timemins) { - String ret; -#else // ARDUINO -std::string IRDaikinESP::renderTime(uint16_t timemins) { - std::string ret; -#endif // ARDUINO - uint16_t hours, mins; - hours = timemins / 60; - ret = uint64ToString(hours) + ":"; - mins = timemins - (hours * 60); - if (mins < 10) ret += "0"; - ret += uint64ToString(mins); - return ret; -} - -// Convert the internal state into a human readable string. -#ifdef ARDUINO -String IRDaikinESP::toString() { - String result = ""; -#else // ARDUINO -std::string IRDaikinESP::toString() { - std::string result = ""; -#endif // ARDUINO - result += "Power: "; - if (getPower()) - result += "On"; - else - result += "Off"; - result += ", Mode: " + uint64ToString(getMode()); - switch (getMode()) { - case kDaikinAuto: - result += " (AUTO)"; - break; - case kDaikinCool: - result += " (COOL)"; - break; - case kDaikinHeat: - result += " (HEAT)"; - break; - case kDaikinDry: - result += " (DRY)"; - break; - case kDaikinFan: - result += " (FAN)"; - break; - default: - result += " (UNKNOWN)"; - } - result += ", Temp: " + uint64ToString(getTemp()) + "C"; - result += ", Fan: " + uint64ToString(getFan()); - switch (getFan()) { - case kDaikinFanAuto: - result += " (AUTO)"; - break; - case kDaikinFanQuiet: - result += " (QUIET)"; - break; - case kDaikinFanMin: - result += " (MIN)"; - break; - case kDaikinFanMax: - result += " (MAX)"; - break; - } - result += ", Powerful: "; - if (getPowerful()) - result += "On"; - else - result += "Off"; - result += ", Quiet: "; - if (getQuiet()) - result += "On"; - else - result += "Off"; - result += ", Sensor: "; - if (getSensor()) - result += "On"; - else - result += "Off"; - result += ", Eye: "; - if (getEye()) - result += "On"; - else - result += "Off"; - result += ", Mold: "; - if (getMold()) - result += "On"; - else - result += "Off"; - result += ", Swing (Horizontal): "; - if (getSwingHorizontal()) - result += "On"; - else - result += "Off"; - result += ", Swing (Vertical): "; - if (getSwingVertical()) - result += "On"; - else - result += "Off"; - result += ", Current Time: " + renderTime(getCurrentTime()); - result += ", On Time: "; - if (getOnTimerEnabled()) - result += renderTime(getOnTime()); - else - result += "Off"; - result += ", Off Time: "; - if (getOffTimerEnabled()) - result += renderTime(getOffTime()); - else - result += "Off"; - - return result; -} - -#if DAIKIN_DEBUG -// Print what we have -void IRDaikinESP::printState() { -#ifdef ARDUINO - String strbits; -#else // ARDUINO - std::string strbits; -#endif // ARDUINO - DPRINTLN("Raw Bits:"); - for (uint8_t i = 0; i < kDaikinStateLength; i++) { - strbits = uint64ToString(daikin[i], BIN); - while (strbits.length() < 8) strbits = "0" + strbits; - DPRINT(strbits); - DPRINT(" "); - } - DPRINTLN(""); - DPRINTLN(toString()); -} -#endif // DAIKIN_DEBUG - -/* - * Return most important bits to allow replay - * layout is: - * 0: Power - * 1-3: Mode - * 4-7: Fan speed/mode - * 8-14: Target Temperature - * 15: Econo - * 16: Powerful - * 17: Quiet - * 18: Sensor - * 19: Swing Vertical - * 20-31: Current time (mins since midnight) - * */ -uint32_t IRDaikinESP::getCommand() { - uint32_t ret = 0; - uint32_t tmp = 0; - if (getPower()) ret |= 0b00000000000000000000000000000001; - tmp = getMode(); - tmp = tmp << 1; - ret |= tmp; - - tmp = getFan(); - tmp <<= 4; - ret |= tmp; - - tmp = getTemp(); - tmp <<= 8; - ret |= tmp; - - if (getEcono()) ret |= 0b00000000000000001000000000000000; - if (getPowerful()) ret |= 0b00000000000000010000000000000000; - if (getQuiet()) ret |= 0b00000000000000100000000000000000; - if (getSensor()) ret |= 0b00000000000001000000000000000000; - if (getSwingVertical()) ret |= 0b00000000000010000000000000000000; - ret |= (getCurrentTime() << 20); - return ret; -} - -void IRDaikinESP::setCommand(uint32_t value) { - uint32_t tmp = 0; - if (value & 0b00000000000000000000000000000001) setPower(true); - tmp = value & 0b00000000000000000000000000001110; - tmp >>= 1; - setMode(tmp); - - tmp = value & 0b00000000000000000000000011110000; - tmp >>= 4; - setFan(tmp); - - tmp = value & 0b00000000000000000111111100000000; - tmp >>= 8; - setTemp(tmp); - - if (value & 0b00000000000000001000000000000000) setEcono(true); - if (value & 0b00000000000000010000000000000000) setPowerful(true); - if (value & 0b00000000000000100000000000000000) setQuiet(true); - if (value & 0b00000000000001000000000000000000) setSensor(true); - if (value & 0b00000000000010000000000000000000) setSwingVertical(true); - - value >>= 20; - setCurrentTime(value); -} - -#if DECODE_DAIKIN - -void addbit(bool val, unsigned char data[]) { - uint8_t curbit = data[kDaikinCurBit]; - uint8_t curindex = data[kDaikinCurIndex]; - if (val) { - unsigned char bit = 1; - bit = bit << curbit; - data[curindex] |= bit; - } - curbit++; - if (curbit == 8) { - curbit = 0; - curindex++; - } - data[kDaikinCurBit] = curbit; - data[kDaikinCurIndex] = curindex; -} - -bool checkheader(decode_results *results, uint16_t *offset) { - if (!IRrecv::matchMark(results->rawbuf[(*offset)++], kDaikinBitMark, - kDaikinTolerance, kDaikinMarkExcess)) - return false; - if (!IRrecv::matchSpace(results->rawbuf[(*offset)++], - kDaikinZeroSpace + kDaikinGap, kDaikinTolerance, - kDaikinMarkExcess)) - return false; - if (!IRrecv::matchMark(results->rawbuf[(*offset)++], kDaikinHdrMark, - kDaikinTolerance, kDaikinMarkExcess)) - return false; - if (!IRrecv::matchSpace(results->rawbuf[(*offset)++], kDaikinHdrSpace, - kDaikinTolerance, kDaikinMarkExcess)) - return false; - - return true; -} - -bool readbits(decode_results *results, uint16_t *offset, - unsigned char daikin_code[], uint16_t countbits) { - for (uint16_t i = 0; i < countbits && *offset < results->rawlen - 1; - i++, (*offset)++) { - if (!IRrecv::matchMark(results->rawbuf[(*offset)++], kDaikinBitMark, - kDaikinTolerance, kDaikinMarkExcess)) - return false; - if (IRrecv::matchSpace(results->rawbuf[*offset], kDaikinOneSpace, - kDaikinTolerance, kDaikinMarkExcess)) - addbit(1, daikin_code); - else if (IRrecv::matchSpace(results->rawbuf[*offset], kDaikinZeroSpace, - kDaikinTolerance, kDaikinMarkExcess)) - addbit(0, daikin_code); - else - return false; - } - return true; -} - -// Decode the supplied Daikin A/C message. -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: Nr. of bits to expect in the data portion. (kDaikinRawBits) -// strict: Flag to indicate if we strictly adhere to the specification. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: BETA / Should be working. -// -// Notes: -// If DAIKIN_DEBUG enabled, will print all the set options and values. -// -// Ref: -// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote -bool IRrecv::decodeDaikin(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < kDaikinRawBits) return false; - - // Compliance - if (strict && nbits != kDaikinRawBits) return false; - - uint16_t offset = kStartOffset; - unsigned char daikin_code[kDaikinStateLength + 2]; - for (uint8_t i = 0; i < kDaikinStateLength + 2; i++) daikin_code[i] = 0; - - // Header (#1) - for (uint8_t i = 0; i < 10; i++) { - if (!matchMark(results->rawbuf[offset++], kDaikinBitMark)) return false; - } - if (!checkheader(results, &offset)) return false; - - // Data (#1) - if (!readbits(results, &offset, daikin_code, 8 * 8)) return false; - - // Ignore everything that has just been captured as it is not needed. - // Some remotes may not send this portion, my remote did, but it's not - // required. - for (uint8_t i = 0; i < kDaikinStateLength + 2; i++) daikin_code[i] = 0; - - // Header (#2) - if (!checkheader(results, &offset)) return false; - - // Data (#2) - if (!readbits(results, &offset, daikin_code, 8 * 8)) return false; - - // Header (#3) - if (!checkheader(results, &offset)) return false; - - // Data (#3), read up everything else - if (!readbits(results, &offset, daikin_code, kDaikinBits - (8 * 8))) - return false; - - // Footer - if (!matchMark(results->rawbuf[offset++], kDaikinBitMark)) return false; - if (offset < results->rawlen && - !matchAtLeast(results->rawbuf[offset], kDaikinGap)) - return false; - - // Compliance - if (strict) { - if (!IRDaikinESP::validChecksum(daikin_code)) return false; - } - - // Success -#if DAIKIN_DEBUG - IRDaikinESP dako = IRDaikinESP(0); - dako.setRaw(daikin_code); -#ifdef ARDUINO - yield(); -#endif // ARDUINO - dako.printState(); -#endif // DAIKIN_DEBUG - - // Copy across the bits to state - for (uint8_t i = 0; i < kDaikinStateLength; i++) - results->state[i] = daikin_code[i]; - results->bits = kDaikinStateLength * 8; - results->decode_type = DAIKIN; - return true; -} -#endif // DECODE_DAIKIN diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h b/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h deleted file mode 100644 index 7094990d8..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Daikin.h +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2016 sillyfrog -// Copyright 2017 sillyfrog, crankyoldgit -#ifndef IR_DAIKIN_H_ -#define IR_DAIKIN_H_ - -#ifndef UNIT_TEST -#include -#else -#include -#endif -#include "IRrecv.h" -#include "IRremoteESP8266.h" -#include "IRsend.h" - -// Option to disable the additional Daikin debug info to conserve memory -#define DAIKIN_DEBUG false - -// DDDDD AAA IIIII KK KK IIIII NN NN -// DD DD AAAAA III KK KK III NNN NN -// DD DD AA AA III KKKK III NN N NN -// DD DD AAAAAAA III KK KK III NN NNN -// DDDDDD AA AA IIIII KK KK IIIII NN NN - -/* - Daikin AC map - byte 5=Current time, mins past midnight, low bits - byte 6 - b0-b3=Current time, mins past midnight, high bits - byte 7= checksum of the first part (and last byte before a 29ms pause) - byte 13=mode - b7 = 0 - b6+b5+b4 = Mode - Modes: b6+b5+b4 - 011 = Cool - 100 = Heat (temp 23) - 110 = FAN (temp not shown, but 25) - 000 = Fully Automatic (temp 25) - 010 = DRY (temp 0xc0 = 96 degrees c) - b3 = 1 - b2 = OFF timer set - b1 = ON timer set - b0 = Air Conditioner ON - byte 14=temp*2 (Temp should be between 10 - 32) - byte 16=Fan - FAN control - b7+b6+b5+b4 = Fan speed - Fan: b7+b6+b5+b4 - 0×3 = 1 bar - 0×4 = 2 bar - 0×5 = 3 bar - 0×6 = 4 bar - 0×7 = 5 bar - 0xa = Auto - 0xb = Quite - b3+b2+b1+b0 = Swing control up/down - Swing control up/down: - 0000 = Swing up/down off - 1111 = Swing up/down on - byte 17 - Swing control left/right: - 0000 = Swing left/right off - 1111 = Swing left/right on - byte 18=On timer mins past midnight, low bits - byte 19 - b0-b3=On timer mins past midnight, high bits - b4-b7=Off timer mins past midnight, low bits - byte 20=Off timer mins past midnight, high bits - byte 21=Aux -> Powerful (bit 1), Silent (bit 5) - byte 24=Aux2 - b1: Sensor - b2: Econo mode - b7: Intelligent eye on - byte 25=Aux3 - b1: Mold Proof - byte 26= checksum of the second part -*/ - -// Constants -const uint8_t kDaikinAuto = 0b000; -const uint8_t kDaikinDry = 0b010; -const uint8_t kDaikinCool = 0b011; -const uint8_t kDaikinHeat = 0b100; -const uint8_t kDaikinFan = 0b110; -const uint8_t kDaikinMinTemp = 10; // Celsius -const uint8_t kDaikinMaxTemp = 32; // Celsius -const uint8_t kDaikinFanMin = 1; -const uint8_t kDaikinFanMax = 5; -const uint8_t kDaikinFanAuto = 0b1010; -const uint8_t kDaikinFanQuiet = 0b1011; -const uint8_t kDaikinBytePower = 13; -const uint8_t kDaikinBitPower = 0b00000001; -const uint8_t kDaikinBytePowerful = 21; -const uint8_t kDaikinBitPowerful = 0b00000001; -const uint8_t kDaikinByteSilent = 21; -const uint8_t kDaikinBitSilent = 0b00100000; -const uint8_t kDaikinByteSensor = 24; -const uint8_t kDaikinBitSensor = 0b00000010; -const uint8_t kDaikinByteEcono = 24; -const uint8_t kDaikinBitEcono = 0b00000100; -const uint8_t kDaikinByteEye = 24; -const uint8_t kDaikinBitEye = 0b10000000; -const uint8_t kDaikinByteMold = 25; -const uint8_t kDaikinBitMold = 0b00000010; -const uint8_t kDaikinByteOffTimer = 13; -const uint8_t kDaikinBitOffTimer = 0b00000100; -const uint8_t kDaikinByteOnTimer = 13; -const uint8_t kDaikinBitOnTimer = 0b00000010; -const uint8_t kDaikinCurBit = kDaikinStateLength; -const uint8_t kDaikinCurIndex = kDaikinStateLength + 1; -const uint8_t kDaikinTolerance = 35; -const uint16_t kDaikinMarkExcess = kMarkExcess; -const uint16_t kDaikinHdrMark = 3650; // kDaikinBitMark * 8 -const uint16_t kDaikinHdrSpace = 1623; // kDaikinBitMark * 4 -const uint16_t kDaikinBitMark = 428; -const uint16_t kDaikinZeroSpace = 428; -const uint16_t kDaikinOneSpace = 1280; -const uint16_t kDaikinGap = 29000; -// Note bits in each octet swapped so can be sent as a single value -const uint64_t kDaikinFirstHeader64 = - 0b1101011100000000000000001100010100000000001001111101101000010001; - -// Legacy defines. -#define DAIKIN_COOL kDaikinCool -#define DAIKIN_HEAT kDaikinHeat -#define DAIKIN_FAN kDaikinFan -#define DAIKIN_AUTO kDaikinAuto -#define DAIKIN_DRY kDaikinDry -#define DAIKIN_MIN_TEMP kDaikinMinTemp -#define DAIKIN_MAX_TEMP kDaikinMaxTemp -#define DAIKIN_FAN_MIN kDaikinFanMin -#define DAIKIN_FAN_MAX kDaikinFanMax -#define DAIKIN_FAN_AUTO kDaikinFanAuto -#define DAIKIN_FAN_QUIET kDaikinFanQuiet - -class IRDaikinESP { - public: - explicit IRDaikinESP(uint16_t pin); - -#if SEND_DAIKIN - void send(); -#endif - void begin(); - void on(); - void off(); - void setPower(bool state); - bool getPower(); - void setTemp(uint8_t temp); - uint8_t getTemp(); - void setFan(uint8_t fan); - uint8_t getFan(); - uint8_t getMode(); - void setMode(uint8_t mode); - void setSwingVertical(bool state); - bool getSwingVertical(); - void setSwingHorizontal(bool state); - bool getSwingHorizontal(); - bool getQuiet(); - void setQuiet(bool state); - bool getPowerful(); - void setPowerful(bool state); - void setSensor(bool state); - bool getSensor(); - void setEcono(bool state); - bool getEcono(); - void setEye(bool state); - bool getEye(); - void setMold(bool state); - bool getMold(); - void enableOnTimer(uint16_t starttime); - void disableOnTimer(); - uint16_t getOnTime(); - bool getOnTimerEnabled(); - void enableOffTimer(uint16_t endtime); - void disableOffTimer(); - uint16_t getOffTime(); - bool getOffTimerEnabled(); - void setCurrentTime(uint16_t time); - uint16_t getCurrentTime(); - uint8_t* getRaw(); - void setRaw(uint8_t new_code[]); -#if DAIKIN_DEBUG - void printState(); -#endif // DAIKIN_DEBUG - uint32_t getCommand(); - void setCommand(uint32_t value); - static bool validChecksum(const uint8_t state[], - const uint16_t length = kDaikinStateLength); -#ifdef ARDUINO - String toString(); - static String renderTime(uint16_t timemins); -#else - std::string toString(); - static std::string renderTime(uint16_t timemins); -#endif - - private: - // # of bytes per command - uint8_t daikin[kDaikinStateLength]; - void stateReset(); - static uint8_t calcBlockChecksum(const uint8_t* block, const uint16_t length); - void checksum(); - void setBit(uint8_t byte, uint8_t bitmask); - void clearBit(uint8_t byte, uint8_t bitmask); - uint8_t getBit(uint8_t byte, uint8_t bitmask); - IRsend _irsend; -}; - -#endif // IR_DAIKIN_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.cpp deleted file mode 100644 index 0bece2664..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2017 stufisher - -#include "ir_Trotec.h" -#include "IRremoteESP8266.h" -#include "IRutils.h" - -// Constants -const uint16_t kTrotecHdrMark = 5952; -const uint16_t kTrotecHdrSpace = 7364; -const uint16_t kTrotecOneMark = 592; -const uint16_t kTrotecOneSpace = 1560; -const uint16_t kTrotecZeroMark = 592; -const uint16_t kTrotecZeroSpace = 592; -const uint16_t kTrotecGap = 6184; -const uint16_t kTrotecGapEnd = 1500; // made up value - -#if SEND_TROTEC - -void IRsend::sendTrotec(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - if (nbytes < kTrotecStateLength) return; - - for (uint16_t r = 0; r <= repeat; r++) { - sendGeneric(kTrotecHdrMark, kTrotecHdrSpace, kTrotecOneMark, - kTrotecOneSpace, kTrotecZeroMark, kTrotecZeroSpace, - kTrotecOneMark, kTrotecGap, data, nbytes, 36, false, - 0, // Repeats handled elsewhere - 50); - // More footer - enableIROut(36); - mark(kTrotecOneMark); - space(kTrotecGapEnd); - } -} -#endif // SEND_TROTEC - -IRTrotecESP::IRTrotecESP(uint16_t pin) : _irsend(pin) { stateReset(); } - -void IRTrotecESP::begin() { _irsend.begin(); } - -#if SEND_TROTEC -void IRTrotecESP::send() { - checksum(); - _irsend.sendTrotec(trotec); -} -#endif // SEND_TROTEC - -void IRTrotecESP::checksum() { - uint8_t sum = 0; - uint8_t i; - - for (i = 2; i < 8; i++) sum += trotec[i]; - - trotec[8] = sum & 0xFF; -} - -void IRTrotecESP::stateReset() { - for (uint8_t i = 2; i < kTrotecStateLength; i++) trotec[i] = 0x0; - - trotec[0] = kTrotecIntro1; - trotec[1] = kTrotecIntro2; - - setPower(false); - setTemp(kTrotecDefTemp); - setSpeed(kTrotecFanMed); - setMode(kTrotecAuto); -} - -uint8_t* IRTrotecESP::getRaw() { - checksum(); - return trotec; -} - -void IRTrotecESP::setPower(bool state) { - if (state) - trotec[2] |= (kTrotecOn << 3); - else - trotec[2] &= ~(kTrotecOn << 3); -} - -uint8_t IRTrotecESP::getPower() { return trotec[2] & (kTrotecOn << 3); } - -void IRTrotecESP::setSpeed(uint8_t speed) { - trotec[2] = (trotec[2] & 0xcf) | (speed << 4); -} - -uint8_t IRTrotecESP::getSpeed() { return trotec[2] & 0x30; } - -void IRTrotecESP::setMode(uint8_t mode) { - trotec[2] = (trotec[2] & 0xfc) | mode; -} - -uint8_t IRTrotecESP::getMode() { return trotec[2] & 0x03; } - -void IRTrotecESP::setTemp(uint8_t temp) { - if (temp < kTrotecMinTemp) - temp = kTrotecMinTemp; - else if (temp > kTrotecMaxTemp) - temp = kTrotecMaxTemp; - - trotec[3] = (trotec[3] & 0x80) | (temp - kTrotecMinTemp); -} - -uint8_t IRTrotecESP::getTemp() { return trotec[3] & 0x7f; } - -void IRTrotecESP::setSleep(bool sleep) { - if (sleep) - trotec[3] |= (kTrotecSleepOn << 7); - else - trotec[3] &= ~(kTrotecSleepOn << 7); -} - -bool IRTrotecESP::getSleep(void) { return trotec[3] & (kTrotecSleepOn << 7); } - -void IRTrotecESP::setTimer(uint8_t timer) { - if (timer > kTrotecMaxTimer) timer = kTrotecMaxTimer; - - if (timer) { - trotec[5] |= (kTrotecTimerOn << 6); - trotec[6] = timer; - } else { - trotec[5] &= ~(kTrotecTimerOn << 6); - trotec[6] = 0; - } -} - -uint8_t IRTrotecESP::getTimer() { return trotec[6]; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Whirlpool.cpp b/lib/IRremoteESP8266-2.5.2.03/src/ir_Whirlpool.cpp deleted file mode 100644 index 671513991..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Whirlpool.cpp +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2018 David Conran -// -// Code to emulate Whirlpool protocol compatible devices. -// Should be compatible with: -// * SPIS409L, SPIS412L, SPIW409L, SPIW412L, SPIW418L -// - -#include -#ifndef ARDUINO -#include -#endif -#include "IRrecv.h" -#include "IRremoteESP8266.h" -#include "IRsend.h" -#include "IRutils.h" - -// WW WW HH HH IIIII RRRRRR LL PPPPPP OOOOO OOOOO LL -// WW WW HH HH III RR RR LL PP PP OO OO OO OO LL -// WW W WW HHHHHHH III RRRRRR LL PPPPPP OO OO OO OO LL -// WW WWW WW HH HH III RR RR LL PP OO OO OO OO LL -// WW WW HH HH IIIII RR RR LLLLLLL PP OOOO0 OOOO0 LLLLLLL - -// Constants -// Ref: https://github.com/markszabo/IRremoteESP8266/issues/509 -const uint16_t kWhirlpoolAcHdrMark = 8950; -const uint16_t kWhirlpoolAcHdrSpace = 4484; -const uint16_t kWhirlpoolAcBitMark = 597; -const uint16_t kWhirlpoolAcOneSpace = 1649; -const uint16_t kWhirlpoolAcZeroSpace = 533; -const uint16_t kWhirlpoolAcGap = 7920; -const uint32_t kWhirlpoolAcMinGap = 100000; // Completely made up value. -const uint8_t kWhirlpoolAcSections = 3; - -#if SEND_WHIRLPOOL_AC -// Send a Whirlpool A/C message. -// -// Args: -// data: An array of bytes containing the IR command. -// nbytes: Nr. of bytes of data in the array. (>=kWhirlpoolAcStateLength) -// repeat: Nr. of times the message is to be repeated. (Default = 0). -// -// Status: ALPHA / Untested. -// -// Ref: -// https://github.com/markszabo/IRremoteESP8266/issues/509 -void IRsend::sendWhirlpoolAC(unsigned char data[], uint16_t nbytes, - uint16_t repeat) { - if (nbytes < kWhirlpoolAcStateLength) - return; // Not enough bytes to send a proper message. - for (uint16_t r = 0; r <= repeat; r++) { - // Section 1 - sendGeneric(kWhirlpoolAcHdrMark, kWhirlpoolAcHdrSpace, kWhirlpoolAcBitMark, - kWhirlpoolAcOneSpace, kWhirlpoolAcBitMark, - kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, kWhirlpoolAcGap, - data, 6, // 6 bytes == 48 bits - 38000, // Complete guess of the modulation frequency. - false, 0, 50); - // Section 2 - sendGeneric(0, 0, kWhirlpoolAcBitMark, kWhirlpoolAcOneSpace, - kWhirlpoolAcBitMark, kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, - kWhirlpoolAcGap, data + 6, 8, // 8 bytes == 64 bits - 38000, // Complete guess of the modulation frequency. - false, 0, 50); - // Section 3 - sendGeneric(0, 0, kWhirlpoolAcBitMark, kWhirlpoolAcOneSpace, - kWhirlpoolAcBitMark, kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, - kWhirlpoolAcMinGap, data + 14, 7, // 7 bytes == 56 bits - 38000, // Complete guess of the modulation frequency. - false, 0, 50); - } -} -#endif // SEND_WHIRLPOOL_AC - -#if DECODE_WHIRLPOOL_AC -// Decode the supplied Whirlpool A/C message. -// -// Args: -// results: Ptr to the data to decode and where to store the decode result. -// nbits: The number of data bits to expect. Typically kWhirlpoolAcBits -// strict: Flag indicating if we should perform strict matching. -// Returns: -// boolean: True if it can decode it, false if it can't. -// -// Status: ALPHA / Untested. -// -// -// Ref: -// https://github.com/markszabo/IRremoteESP8266/issues/509 -bool IRrecv::decodeWhirlpoolAC(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + 4 + kHeader + kFooter - 1) - return false; // Can't possibly be a valid Whirlpool A/C message. - if (strict) { - if (nbits != kWhirlpoolAcBits) return false; - } - - uint16_t offset = kStartOffset; - uint16_t dataBitsSoFar = 0; - uint16_t i = 0; - match_result_t data_result; - uint8_t sectionSize[kWhirlpoolAcSections] = {6, 8, 7}; - - // Header - if (!matchMark(results->rawbuf[offset++], kWhirlpoolAcHdrMark)) return false; - if (!matchSpace(results->rawbuf[offset++], kWhirlpoolAcHdrSpace)) - return false; - - // Data Section - // Keep reading bytes until we either run out of section or state to fill. - for (uint8_t section = 0, pos = 0; section < kWhirlpoolAcSections; - section++) { - pos += sectionSize[section]; - for (; offset <= results->rawlen - 16 && i < pos; - i++, dataBitsSoFar += 8, offset += data_result.used) { - data_result = - matchData(&(results->rawbuf[offset]), 8, kWhirlpoolAcBitMark, - kWhirlpoolAcOneSpace, kWhirlpoolAcBitMark, - kWhirlpoolAcZeroSpace, kTolerance, kMarkExcess, false); - if (data_result.success == false) break; // Fail - // Data is in LSB order. We need to reverse it. - results->state[i] = (uint8_t)data_result.data; - } - // Section Footer - if (!matchMark(results->rawbuf[offset++], kWhirlpoolAcBitMark)) - return false; - if (section < kWhirlpoolAcSections - 1) { // Inter-section gaps. - if (!matchSpace(results->rawbuf[offset++], kWhirlpoolAcGap)) return false; - } else { // Last section / End of message gap. - if (offset <= results->rawlen && - !matchAtLeast(results->rawbuf[offset++], kWhirlpoolAcGap)) - return false; - } - } - - // Compliance - if (strict) { - // Re-check we got the correct size/length due to the way we read the data. - if (dataBitsSoFar != kWhirlpoolAcBits) return false; - } - - // Success - results->decode_type = WHIRLPOOL_AC; - results->bits = dataBitsSoFar; - // No need to record the state as we stored it as we decoded it. - // As we use result->state, we don't record value, address, or command as it - // is a union data type. - return true; -} -#endif // WHIRLPOOL_AC diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.cpp deleted file mode 100644 index 353639918..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.cpp +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2017 David Conran - -#include "IRsend_test.h" -#include "IRsend.h" -#include "gtest/gtest.h" - -// Tests sendData(). - -// Test sending zero bits. -TEST(TestSendData, SendZeroBits) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b1, 0, true); - EXPECT_EQ("", irsend.outputStr()); -} - -// Test sending zero and one. -TEST(TestSendData, SendSingleBit) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b1, 1, true); - EXPECT_EQ("m1s2", irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0b0, 1, true); - EXPECT_EQ("m3s4", irsend.outputStr()); -} - -// Test sending bit order. -TEST(TestSendData, TestingBitSendOrder) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b10, 2, true); - EXPECT_EQ("m1s2m3s4", irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0b10, 2, false); - EXPECT_EQ("m3s4m1s2", irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0b0001, 4, false); - EXPECT_EQ("m1s2m3s4m3s4m3s4", irsend.outputStr()); -} - -// Test sending typical data. -TEST(TestSendData, SendTypicalData) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b1010110011110000, 16, true); - EXPECT_EQ("m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4m3s4", - irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0x1234567890ABCDEF, 64, true); - EXPECT_EQ( - "m3s4m3s4m3s4m1s2m3s4m3s4m1s2m3s4m3s4m3s4m1s2m1s2m3s4m1s2m3s4m3s4" - "m3s4m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4" - "m1s2m3s4m3s4m1s2m3s4m3s4m3s4m3s4m1s2m3s4m1s2m3s4m1s2m3s4m1s2m1s2" - "m1s2m1s2m3s4m3s4m1s2m1s2m3s4m1s2m1s2m1s2m1s2m3s4m1s2m1s2m1s2m1s2", - irsend.outputStr()); -} - -// Test sending more than expected bits. -TEST(TestSendData, SendOverLargeData) { - IRsendTest irsend(4); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0xFFFFFFFFFFFFFFFF, 70, true); - EXPECT_EQ( - "m3s4m3s4m3s4m3s4m3s4m3s4" - "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" - "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" - "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" - "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2", - irsend.outputStr()); -} - -// Test inverting the output. -TEST(TestIRSend, InvertedOutput) { - IRsendTest irsend(4, true); - irsend.begin(); - irsend.sendData(1, 2, 3, 4, 0b1, 1, true); - EXPECT_EQ("s1m2", irsend.outputStr()); - irsend.sendData(1, 2, 3, 4, 0b0, 1, true); - EXPECT_EQ("s3m4", irsend.outputStr()); -} - -// Test typical use of sendRaw(). -TEST(TestSendRaw, GeneralUse) { - IRsendTest irsend(4); - IRrecv irrecv(0); - - irsend.begin(); - // NEC C3E0E0E8 as measured in #204 - uint16_t rawData[67] = { - 8950, 4500, 550, 1650, 600, 1650, 550, 550, 600, 500, 600, 550, - 550, 550, 600, 1650, 550, 1650, 600, 1650, 600, 1650, 550, 1700, - 550, 550, 600, 550, 550, 550, 600, 500, 600, 550, 550, 1650, - 600, 1650, 600, 1650, 550, 550, 600, 500, 600, 500, 600, 550, - 550, 550, 600, 1650, 550, 1650, 600, 1650, 600, 500, 650, 1600, - 600, 500, 600, 550, 550, 550, 600}; - - irsend.sendRaw(rawData, 67, 38); - EXPECT_EQ( - "m8950s4500" - "m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650" - "m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550" - "m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550" - "m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550" - "m600", - irsend.outputStr()); - - irsend.reset(); - irsend.sendRaw(rawData, 67, 38); - irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, kNECBits, false)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(32, irsend.capture.bits); - EXPECT_EQ(0xC3E0E0E8, irsend.capture.value); - EXPECT_EQ( - "m8950s4500" - "m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650" - "m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550" - "m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550" - "m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550" - "m600", - irsend.outputStr()); -} - -// Incorrect handling of decodes from Raw. i.e. There is no gap recorded at -// the end of a command when using the interrupt code. sendRaw() best emulates -// this for unit testing purposes. sendGC() and sendXXX() will add the trailing -// gap. Users won't see this in normal use. -TEST(TestSendRaw, NoTrailingGap) { - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - irsend.reset(); - uint16_t rawData[67] = { - 9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, 600, 1650, - 650, 550, 600, 1650, 650, 1650, 650, 1650, 600, 550, 650, 1650, - 650, 1650, 650, 550, 600, 1650, 650, 1650, 650, 550, 650, 550, - 650, 1650, 650, 550, 650, 550, 650, 550, 600, 550, 650, 550, - 650, 550, 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650, - 650, 1650, 650, 1650, 650, 1650, 600}; - irsend.sendRaw(rawData, 67, 38); - irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); - EXPECT_EQ(NEC, irsend.capture.decode_type); - EXPECT_EQ(kNECBits, irsend.capture.bits); -} - -TEST(TestLowLevelSend, MarkFrequencyModulationAt38kHz) { - IRsendLowLevelTest irsend(0); - - irsend.begin(); - - irsend.reset(); - irsend.enableIROut(38000, 50); - EXPECT_EQ(5, irsend.mark(100)); - EXPECT_EQ( - "[On]10usecs[Off]11usecs[On]10usecs[Off]11usecs[On]10usecs[Off]11usecs" - "[On]10usecs[Off]11usecs[On]10usecs[Off]6usecs", - irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(38000, 33); - EXPECT_EQ(5, irsend.mark(100)); - EXPECT_EQ( - "[On]6usecs[Off]15usecs[On]6usecs[Off]15usecs[On]6usecs[Off]15usecs" - "[On]6usecs[Off]15usecs[On]6usecs[Off]10usecs", - irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(38000, 100); - EXPECT_EQ(1, irsend.mark(1000)); - EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); -} - -TEST(TestLowLevelSend, MarkFrequencyModulationAt36_7kHz) { - IRsendLowLevelTest irsend(0); - - irsend.begin(); - - irsend.reset(); - irsend.enableIROut(36700, 50); - EXPECT_EQ(5, irsend.mark(100)); - EXPECT_EQ( - "[On]11usecs[Off]11usecs[On]11usecs[Off]11usecs[On]11usecs[Off]11usecs" - "[On]11usecs[Off]11usecs[On]11usecs[Off]1usecs", - irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(36700, 33); - EXPECT_EQ(5, irsend.mark(100)); - EXPECT_EQ( - "[On]7usecs[Off]15usecs[On]7usecs[Off]15usecs[On]7usecs[Off]15usecs" - "[On]7usecs[Off]15usecs[On]7usecs[Off]5usecs", - irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(36700, 100); - EXPECT_EQ(1, irsend.mark(1000)); - EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); -} - -TEST(TestLowLevelSend, MarkFrequencyModulationAt40kHz) { - IRsendLowLevelTest irsend(0); - - irsend.begin(); - - irsend.reset(); - irsend.enableIROut(40000, 50); - EXPECT_EQ(5, irsend.mark(100)); - EXPECT_EQ( - "[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs" - "[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs", - irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(40000, 33); - EXPECT_EQ(5, irsend.mark(100)); - EXPECT_EQ( - "[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs" - "[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs", - irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(40000, 100); - EXPECT_EQ(1, irsend.mark(1000)); - EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); -} - -TEST(TestLowLevelSend, MarkNoModulation) { - IRsendLowLevelTest irsend(0, false, false); - - irsend.begin(); - - irsend.reset(); - irsend.enableIROut(38000, 50); - EXPECT_EQ(1, irsend.mark(1000)); - EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(36700, 25); - EXPECT_EQ(1, irsend.mark(1000)); - EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(40000, 75); - EXPECT_EQ(1, irsend.mark(1000)); - EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); -} - -TEST(TestLowLevelSend, SpaceFrequencyModulation) { - IRsendLowLevelTest irsend(0); - - irsend.reset(); - irsend.enableIROut(38000); - irsend.space(1000); - EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(40000, 75); - irsend.space(1000); - EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(38000, 100); - irsend.space(1000); - EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(38000, 33); - irsend.space(1000); - EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); -} - -TEST(TestLowLevelSend, SpaceNoModulation) { - IRsendLowLevelTest irsend(0, false, false); - - irsend.begin(); - - irsend.reset(); - irsend.enableIROut(38000, 50); - irsend.space(1000); - EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(36700, 25); - irsend.space(1000); - EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); - - irsend.reset(); - irsend.enableIROut(40000, 75); - irsend.space(1000); - EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); -} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Daikin_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Daikin_test.cpp deleted file mode 100644 index c8192fc82..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Daikin_test.cpp +++ /dev/null @@ -1,838 +0,0 @@ -// Copyright 2017 David Conran -#include "ir_Daikin.h" -#include "IRrecv.h" -#include "IRrecv_test.h" -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendDaikin(). - -// Test sending typical data only. -TEST(TestSendDaikin, SendDataOnly) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t daikin_code[kDaikinStateLength] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, - 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3}; - - irsend.reset(); - irsend.sendDaikin(daikin_code); - EXPECT_EQ( - "m428s428m428s428m428s428m428s428m428s428" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" - "m428s29428", - irsend.outputStr()); -} - -// Test sending with repeats. -TEST(TestSendDaikin, SendWithRepeats) { - IRsendTest irsend(4); - irsend.begin(); - - irsend.reset(); - uint8_t daikin_code[kDaikinStateLength] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, - 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3}; - irsend.reset(); - - irsend.sendDaikin(daikin_code, kDaikinStateLength, 1); - EXPECT_EQ( - "m428s428m428s428m428s428m428s428m428s428" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" - "m428s29428" - "m428s428m428s428m428s428m428s428m428s428" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" - "m428s29428", - irsend.outputStr()); -} - -// Test sending atypical sizes. -TEST(TestSendDaikin, SendUnexpectedSizes) { - IRsendTest irsend(4); - irsend.begin(); - - uint8_t daikin_short_code[kDaikinStateLength - 1] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, - 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00}; - - irsend.reset(); - irsend.sendDaikin(daikin_short_code, kDaikinStateLength - 1); - ASSERT_EQ("", irsend.outputStr()); - - uint8_t daikin_long_code[kDaikinStateLength + 1] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, 0xDA, - 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3, 0x11}; - irsend.reset(); - irsend.sendDaikin(daikin_long_code, kDaikinStateLength + 1); - ASSERT_EQ( - "m428s428m428s428m428s428m428s428m428s428" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s29428", - irsend.outputStr()); -} - -// Tests for IRDaikinESP class. - -TEST(TestDaikinClass, Power) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.on(); - EXPECT_TRUE(irdaikin.getPower()); - - irdaikin.off(); - EXPECT_FALSE(irdaikin.getPower()); - - irdaikin.setPower(true); - EXPECT_TRUE(irdaikin.getPower()); - - irdaikin.setPower(false); - EXPECT_FALSE(irdaikin.getPower()); -} - -TEST(TestDaikinClass, Temperature) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setTemp(0); - EXPECT_EQ(kDaikinMinTemp, irdaikin.getTemp()); - - irdaikin.setTemp(255); - EXPECT_EQ(kDaikinMaxTemp, irdaikin.getTemp()); - - irdaikin.setTemp(kDaikinMinTemp); - EXPECT_EQ(kDaikinMinTemp, irdaikin.getTemp()); - - irdaikin.setTemp(kDaikinMaxTemp); - EXPECT_EQ(kDaikinMaxTemp, irdaikin.getTemp()); - - irdaikin.setTemp(kDaikinMinTemp - 1); - EXPECT_EQ(kDaikinMinTemp, irdaikin.getTemp()); - - irdaikin.setTemp(kDaikinMaxTemp + 1); - EXPECT_EQ(kDaikinMaxTemp, irdaikin.getTemp()); - - irdaikin.setTemp(kDaikinMinTemp + 1); - EXPECT_EQ(kDaikinMinTemp + 1, irdaikin.getTemp()); - - irdaikin.setTemp(21); - EXPECT_EQ(21, irdaikin.getTemp()); - - irdaikin.setTemp(25); - EXPECT_EQ(25, irdaikin.getTemp()); - - irdaikin.setTemp(29); - EXPECT_EQ(29, irdaikin.getTemp()); -} - -TEST(TestDaikinClass, OperatingMode) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setMode(kDaikinAuto); - EXPECT_EQ(kDaikinAuto, irdaikin.getMode()); - - irdaikin.setMode(kDaikinCool); - EXPECT_EQ(kDaikinCool, irdaikin.getMode()); - - irdaikin.setMode(kDaikinHeat); - EXPECT_EQ(kDaikinHeat, irdaikin.getMode()); - - irdaikin.setMode(kDaikinDry); - EXPECT_EQ(kDaikinDry, irdaikin.getMode()); - - irdaikin.setMode(kDaikinFan); - EXPECT_EQ(kDaikinFan, irdaikin.getMode()); - - irdaikin.setMode(kDaikinFan + 1); - EXPECT_EQ(kDaikinAuto, irdaikin.getMode()); - - irdaikin.setMode(kDaikinAuto + 1); - EXPECT_EQ(kDaikinAuto, irdaikin.getMode()); - - irdaikin.setMode(255); - EXPECT_EQ(kDaikinAuto, irdaikin.getMode()); -} - -TEST(TestDaikinClass, VaneSwing) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setSwingHorizontal(true); - irdaikin.setSwingVertical(false); - - irdaikin.setSwingHorizontal(true); - EXPECT_TRUE(irdaikin.getSwingHorizontal()); - EXPECT_FALSE(irdaikin.getSwingVertical()); - - irdaikin.setSwingVertical(true); - EXPECT_TRUE(irdaikin.getSwingHorizontal()); - EXPECT_TRUE(irdaikin.getSwingVertical()); - - irdaikin.setSwingHorizontal(false); - EXPECT_FALSE(irdaikin.getSwingHorizontal()); - EXPECT_TRUE(irdaikin.getSwingVertical()); - - irdaikin.setSwingVertical(false); - EXPECT_FALSE(irdaikin.getSwingHorizontal()); - EXPECT_FALSE(irdaikin.getSwingVertical()); -} - -TEST(TestDaikinClass, QuietMode) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setQuiet(true); - EXPECT_TRUE(irdaikin.getQuiet()); - - irdaikin.setQuiet(false); - EXPECT_FALSE(irdaikin.getQuiet()); - - irdaikin.setQuiet(true); - EXPECT_TRUE(irdaikin.getQuiet()); - - // Setting Econo mode should NOT change out of quiet mode. - irdaikin.setEcono(true); - EXPECT_TRUE(irdaikin.getQuiet()); - irdaikin.setEcono(false); - EXPECT_TRUE(irdaikin.getQuiet()); - - // But setting Powerful mode should exit out of quiet mode. - irdaikin.setPowerful(true); - EXPECT_FALSE(irdaikin.getQuiet()); -} - -TEST(TestDaikinClass, PowerfulMode) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setPowerful(true); - EXPECT_TRUE(irdaikin.getPowerful()); - - irdaikin.setPowerful(false); - EXPECT_FALSE(irdaikin.getPowerful()); - - irdaikin.setPowerful(true); - EXPECT_TRUE(irdaikin.getPowerful()); - - irdaikin.setQuiet(true); - EXPECT_FALSE(irdaikin.getPowerful()); - - irdaikin.setPowerful(true); - irdaikin.setEcono(true); - EXPECT_FALSE(irdaikin.getPowerful()); -} - -TEST(TestDaikinClass, EconoMode) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setEcono(true); - EXPECT_TRUE(irdaikin.getEcono()); - - irdaikin.setEcono(false); - EXPECT_FALSE(irdaikin.getEcono()); - - irdaikin.setEcono(true); - EXPECT_TRUE(irdaikin.getEcono()); - - // Setting Quiet mode should NOT change out of Econo mode. - irdaikin.setQuiet(true); - EXPECT_TRUE(irdaikin.getEcono()); - irdaikin.setQuiet(false); - EXPECT_TRUE(irdaikin.getEcono()); - - // But setting Powerful mode should exit out of Econo mode. - irdaikin.setPowerful(true); - EXPECT_FALSE(irdaikin.getEcono()); -} - -TEST(TestDaikinClass, FanSpeed) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - // Unexpected value should default to Auto. - irdaikin.setFan(0); - EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); - - // Unexpected value should default to Auto. - irdaikin.setFan(255); - EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); - - irdaikin.setFan(kDaikinFanMax); - EXPECT_EQ(kDaikinFanMax, irdaikin.getFan()); - - // Beyond Max should default to Auto. - irdaikin.setFan(kDaikinFanMax + 1); - EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); - - irdaikin.setFan(kDaikinFanMax - 1); - EXPECT_EQ(kDaikinFanMax - 1, irdaikin.getFan()); - - irdaikin.setFan(kDaikinFanMin); - EXPECT_EQ(kDaikinFanMin, irdaikin.getFan()); - - irdaikin.setFan(kDaikinFanMin + 1); - EXPECT_EQ(kDaikinFanMin + 1, irdaikin.getFan()); - - // Beyond Min should default to Auto. - irdaikin.setFan(kDaikinFanMin - 1); - EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); - - irdaikin.setFan(3); - EXPECT_EQ(3, irdaikin.getFan()); - - irdaikin.setFan(kDaikinFanAuto); - EXPECT_EQ(kDaikinFanAuto, irdaikin.getFan()); - - irdaikin.setFan(kDaikinFanQuiet); - EXPECT_EQ(kDaikinFanQuiet, irdaikin.getFan()); -} - -TEST(TestDaikinClass, CurrentTime) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setCurrentTime(0); // 00:00 - EXPECT_EQ(0, irdaikin.getCurrentTime()); - - irdaikin.setCurrentTime(754); // 12:34 - EXPECT_EQ(754, irdaikin.getCurrentTime()); - - irdaikin.setCurrentTime(1439); // 23:59 - EXPECT_EQ(1439, irdaikin.getCurrentTime()); -} - -TEST(TestDaikinClass, OnOffTimers) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - // Both timers turned off. - irdaikin.disableOnTimer(); - irdaikin.disableOffTimer(); - EXPECT_FALSE(irdaikin.getOnTimerEnabled()); - EXPECT_EQ(0x600, irdaikin.getOnTime()); - EXPECT_FALSE(irdaikin.getOffTimerEnabled()); - EXPECT_EQ(0x600, irdaikin.getOffTime()); - - // Turn on just the On Timer. - irdaikin.enableOnTimer(123); - EXPECT_TRUE(irdaikin.getOnTimerEnabled()); - EXPECT_EQ(123, irdaikin.getOnTime()); - EXPECT_FALSE(irdaikin.getOffTimerEnabled()); - EXPECT_EQ(0x600, irdaikin.getOffTime()); - - // Now turn on the Off Timer. - irdaikin.enableOffTimer(754); - EXPECT_TRUE(irdaikin.getOffTimerEnabled()); - EXPECT_EQ(754, irdaikin.getOffTime()); - EXPECT_TRUE(irdaikin.getOnTimerEnabled()); - EXPECT_EQ(123, irdaikin.getOnTime()); - - // Turn off the just the On Timer. - irdaikin.disableOnTimer(); - EXPECT_FALSE(irdaikin.getOnTimerEnabled()); - EXPECT_EQ(0x600, irdaikin.getOnTime()); - EXPECT_TRUE(irdaikin.getOffTimerEnabled()); - EXPECT_EQ(754, irdaikin.getOffTime()); - - // Now turn off the Off Timer. - irdaikin.disableOffTimer(); - EXPECT_FALSE(irdaikin.getOffTimerEnabled()); - EXPECT_EQ(0x600, irdaikin.getOffTime()); - EXPECT_FALSE(irdaikin.getOnTimerEnabled()); - EXPECT_EQ(0x600, irdaikin.getOnTime()); - - // Use some canary values around the timers to ensure no accidental - // bit flips happen. i.e. Neighbouring bytes in the state. - // (Found some during testing on systems with different endian-ness) - // Tests here to make sure it never happens again. - irdaikin.setSwingHorizontal(true); - irdaikin.setPowerful(true); - irdaikin.disableOffTimer(); - irdaikin.disableOnTimer(); - ASSERT_TRUE(irdaikin.getSwingHorizontal()); - ASSERT_TRUE(irdaikin.getPowerful()); - irdaikin.enableOnTimer(123); - irdaikin.enableOffTimer(456); - ASSERT_TRUE(irdaikin.getSwingHorizontal()); - ASSERT_TRUE(irdaikin.getPowerful()); - irdaikin.disableOffTimer(); - irdaikin.disableOnTimer(); - ASSERT_TRUE(irdaikin.getSwingHorizontal()); - ASSERT_TRUE(irdaikin.getPowerful()); - - irdaikin.setSwingHorizontal(false); - irdaikin.setPowerful(false); - irdaikin.disableOffTimer(); - irdaikin.disableOnTimer(); - ASSERT_FALSE(irdaikin.getSwingHorizontal()); - ASSERT_FALSE(irdaikin.getPowerful()); - irdaikin.enableOnTimer(123); - irdaikin.enableOffTimer(456); - ASSERT_FALSE(irdaikin.getSwingHorizontal()); - ASSERT_FALSE(irdaikin.getPowerful()); - irdaikin.disableOffTimer(); - irdaikin.disableOnTimer(); - ASSERT_FALSE(irdaikin.getSwingHorizontal()); - ASSERT_FALSE(irdaikin.getPowerful()); -} - -// Test Eye mode. -TEST(TestDaikinClass, EyeSetting) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - // The Eye setting is stored in the same byte as Econo mode. - // Econo mode tests are there to make sure it isn't harmed and vice-versa. - irdaikin.setEcono(false); - irdaikin.setEye(false); - ASSERT_FALSE(irdaikin.getEye()); - EXPECT_FALSE(irdaikin.getEcono()); - - irdaikin.setEye(true); - ASSERT_TRUE(irdaikin.getEye()); - EXPECT_FALSE(irdaikin.getEcono()); - - irdaikin.setEcono(false); - ASSERT_TRUE(irdaikin.getEye()); - EXPECT_FALSE(irdaikin.getEcono()); - - irdaikin.setEcono(true); - ASSERT_TRUE(irdaikin.getEye()); - EXPECT_TRUE(irdaikin.getEcono()); - - irdaikin.setEye(false); - ASSERT_FALSE(irdaikin.getEye()); - EXPECT_TRUE(irdaikin.getEcono()); -} - -// Test Mold mode. -TEST(TestDaikinClass, MoldSetting) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setMold(false); - ASSERT_FALSE(irdaikin.getMold()); - - irdaikin.setMold(true); - ASSERT_TRUE(irdaikin.getMold()); - - irdaikin.setMold(false); - ASSERT_FALSE(irdaikin.getMold()); -} - -// Test Sensor mode. -TEST(TestDaikinClass, SensorSetting) { - IRDaikinESP irdaikin(0); - irdaikin.begin(); - - irdaikin.setSensor(false); - ASSERT_FALSE(irdaikin.getSensor()); - - irdaikin.setSensor(true); - ASSERT_TRUE(irdaikin.getSensor()); - - irdaikin.setSensor(false); - ASSERT_FALSE(irdaikin.getSensor()); -} - -TEST(TestDaikinClass, RenderTime) { - EXPECT_EQ("0:00", IRDaikinESP::renderTime(0)); - EXPECT_EQ("0:10", IRDaikinESP::renderTime(10)); - EXPECT_EQ("1:00", IRDaikinESP::renderTime(1 * 60 + 0)); - EXPECT_EQ("23:59", IRDaikinESP::renderTime(23 * 60 + 59)); -} - -TEST(TestDaikinClass, SetAndGetRaw) { - IRDaikinESP irdaikin(0); - uint8_t initialState[kDaikinStateLength] = { - 0x11, 0xDA, 0x27, 0x00, 0x42, 0x00, 0x00, 0x54, 0x11, - 0xDA, 0x27, 0x00, 0x00, 0x49, 0x1E, 0x00, 0xB0, 0x00, - 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x4F}; - uint8_t expectedState[kDaikinStateLength] = { - 0x11, 0xDA, 0x27, 0x00, 0x42, 0x00, 0x00, 0x54, 0x11, - 0xDA, 0x27, 0x00, 0x00, 0x48, 0x2A, 0x00, 0xB0, 0x00, - 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x02, 0x5A}; - - EXPECT_STATE_EQ(initialState, irdaikin.getRaw(), kDaikinBits); - // toggle the power state. - irdaikin.setPower(!irdaikin.getPower()); - irdaikin.setTemp(21); - irdaikin.setMold(true); - EXPECT_STATE_EQ(expectedState, irdaikin.getRaw(), kDaikinBits); - irdaikin.setRaw(initialState); - EXPECT_STATE_EQ(initialState, irdaikin.getRaw(), kDaikinBits); -} - -TEST(TestDaikinClass, ChecksumValidation) { - uint8_t daikin_code[kDaikinStateLength] = { - 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x02, 0x11, - 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE1}; - - EXPECT_TRUE(IRDaikinESP::validChecksum(daikin_code)); - // Change the array so the checksum is invalid. - daikin_code[0] ^= 0xFF; - EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); - // Restore the previous change, and change another byte. - daikin_code[0] ^= 0xFF; - daikin_code[4] ^= 0xFF; - EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); - daikin_code[4] ^= 0xFF; - // Change something in the 2nd block. - daikin_code[10] ^= 0xFF; - EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); - daikin_code[10] ^= 0xFF; - EXPECT_TRUE(IRDaikinESP::validChecksum(daikin_code)); -} - -// Test human readable output. -TEST(TestDaikinClass, HumanReadable) { - IRDaikinESP irdaikin(0); - - EXPECT_EQ( - "Power: On, Mode: 4 (HEAT), Temp: 15C, Fan: 11 (QUIET), " - "Powerful: Off, Quiet: Off, Sensor: Off, Eye: Off, Mold: Off, " - "Swing (Horizontal): Off, Swing (Vertical): Off, " - "Current Time: 0:00, On Time: Off, Off Time: Off", - irdaikin.toString()); - irdaikin.setMode(kDaikinAuto); - irdaikin.setTemp(25); - irdaikin.setFan(kDaikinFanAuto); - irdaikin.setQuiet(true); - irdaikin.setSensor(true); - irdaikin.setEye(true); - irdaikin.setMold(true); - irdaikin.setSwingVertical(true); - irdaikin.setSwingHorizontal(true); - irdaikin.setCurrentTime(9 * 60 + 15); - irdaikin.enableOnTimer(8 * 60 + 0); - irdaikin.enableOffTimer(17 * 60 + 30); - irdaikin.off(); - EXPECT_EQ( - "Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 10 (AUTO), " - "Powerful: Off, Quiet: On, Sensor: On, Eye: On, Mold: On, " - "Swing (Horizontal): On, Swing (Vertical): On, " - "Current Time: 9:15, On Time: 8:00, Off Time: 17:30", - irdaikin.toString()); -} - -// Test general message construction after tweaking some settings. -TEST(TestDaikinClass, MessageConstuction) { - IRDaikinESP irdaikin(0); - IRsendTest irsend(4); - irdaikin.begin(); - irsend.begin(); - - irdaikin.setFan(kDaikinFanMin); - irdaikin.setMode(kDaikinCool); - irdaikin.setTemp(27); - irdaikin.setSwingVertical(false); - irdaikin.setSwingHorizontal(true); - irdaikin.setQuiet(false); - irdaikin.setPower(true); - - // Check everything for kicks. - EXPECT_EQ(kDaikinFanMin, irdaikin.getFan()); - EXPECT_EQ(kDaikinCool, irdaikin.getMode()); - EXPECT_EQ(27, irdaikin.getTemp()); - EXPECT_FALSE(irdaikin.getSwingVertical()); - EXPECT_TRUE(irdaikin.getSwingHorizontal()); - EXPECT_FALSE(irdaikin.getQuiet()); - EXPECT_TRUE(irdaikin.getPower()); - - irsend.reset(); - irsend.sendDaikin(irdaikin.getRaw()); - EXPECT_EQ( - "m428s428m428s428m428s428m428s428m428s428" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s428m428s428m428s428m428s1280m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s1280m428s428m428s1280m428s428m428s1280m428s428" - "m428s29428m3650s1623" - "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" - "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" - "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s1280m428s428m428s428m428s1280m428s1280m428s1280m428s428m428s428" - "m428s428m428s1280m428s1280m428s428m428s1280m428s1280m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s428" - "m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s1280m428s1280m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" - "m428s428m428s1280m428s1280m428s428m428s428m428s1280m428s1280m428s1280" - "m428s29428", - irsend.outputStr()); -} - -// Tests for decodeDaikin(). - -// Test decoding a message captured from a real IR remote. -TEST(TestDecodeDaikin, RealExample) { - IRDaikinESP irdaikin(0); - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - uint8_t expectedState[kDaikinStateLength] = { - 0x11, 0xDA, 0x27, 0x00, 0x42, 0x3A, 0x05, 0x93, 0x11, - 0xDA, 0x27, 0x00, 0x00, 0x3F, 0x3A, 0x00, 0xA0, 0x00, - 0x0A, 0x25, 0x17, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x32}; - uint16_t rawData[kDaikinRawBits] = { - 416, 446, 416, 446, 416, 446, 418, 446, 416, 446, 416, 25434, - 3436, 1768, 390, 1336, 390, 446, 416, 446, 416, 446, 416, 1336, - 390, 446, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 448, - 416, 1336, 390, 1336, 390, 448, 416, 1336, 390, 1336, 390, 1338, - 388, 1338, 390, 1336, 390, 446, 416, 446, 416, 1336, 390, 446, - 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 448, - 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, 416, 1336, - 390, 448, 416, 446, 416, 446, 416, 1336, 390, 1336, 390, 446, - 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, - 416, 446, 416, 446, 416, 448, 416, 446, 416, 446, 416, 446, - 416, 448, 414, 448, 416, 448, 416, 1336, 390, 1336, 390, 1336, - 390, 446, 414, 1336, 390, 448, 414, 1336, 390, 1336, 390, 34878, - 3436, 1768, 390, 1336, 390, 446, 416, 448, 416, 446, 416, 1336, - 390, 446, 416, 448, 416, 446, 416, 446, 416, 1336, 390, 446, - 416, 1336, 390, 1336, 390, 446, 416, 1336, 390, 1336, 390, 1336, - 390, 1336, 390, 1336, 392, 446, 414, 448, 416, 1336, 390, 446, - 416, 446, 416, 446, 416, 446, 414, 448, 416, 446, 416, 448, - 414, 448, 416, 446, 416, 446, 416, 446, 414, 1336, 390, 448, - 416, 446, 416, 446, 416, 448, 416, 1336, 390, 446, 416, 446, - 416, 1336, 390, 446, 416, 1336, 390, 1336, 390, 1336, 390, 446, - 416, 446, 414, 1338, 390, 446, 416, 1336, 390, 446, 416, 446, - 416, 446, 416, 446, 416, 446, 416, 1336, 390, 1336, 390, 446, - 416, 446, 416, 1336, 390, 446, 416, 446, 416, 1336, 390, 34876, - 3436, 1768, 388, 1336, 390, 446, 416, 446, 416, 448, 416, 1336, - 390, 446, 416, 446, 416, 446, 416, 448, 416, 1336, 390, 448, - 414, 1336, 390, 1336, 390, 446, 416, 1336, 388, 1338, 388, 1336, - 390, 1336, 390, 1336, 390, 446, 416, 446, 416, 1336, 390, 446, - 420, 442, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, - 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 448, - 416, 446, 416, 448, 416, 446, 416, 448, 416, 446, 416, 1336, - 390, 1336, 390, 1336, 388, 1338, 390, 1336, 390, 1336, 392, 446, - 416, 446, 416, 448, 416, 1334, 390, 446, 416, 1338, 388, 1336, - 390, 1336, 390, 446, 416, 446, 416, 448, 414, 446, 416, 446, - 416, 446, 416, 448, 416, 446, 416, 446, 416, 446, 416, 446, - 416, 446, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, - 416, 1336, 390, 446, 414, 448, 416, 446, 416, 446, 416, 446, - 416, 448, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, - 416, 1336, 390, 446, 416, 446, 416, 446, 416, 448, 416, 1338, - 390, 444, 418, 1336, 390, 448, 416, 446, 416, 1336, 390, 446, - 416, 446, 416, 1336, 390, 1336, 388, 1336, 390, 446, 416, 1336, - 390, 448, 414, 448, 414, 448, 416, 1334, 390, 446, 416, 446, - 416, 446, 416, 448, 416, 446, 416, 446, 416, 448, 416, 446, - 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, - 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, - 416, 448, 416, 1336, 390, 1336, 390, 446, 416, 446, 416, 446, - 416, 446, 414, 446, 416, 448, 416, 446, 416, 448, 414, 446, - 418, 446, 416, 446, 416, 448, 416, 446, 416, 448, 416, 446, - 416, 448, 416, 446, 416, 1336, 390, 446, 416, 446, 416, 1338, - 390, 1336, 390, 446, 416, 446, 416}; // Captured by @sillyfrog - - irsend.reset(); - irsend.sendRaw(rawData, kDaikinRawBits, 38000); - irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - ASSERT_EQ(DAIKIN, irsend.capture.decode_type); - ASSERT_EQ(kDaikinBits, irsend.capture.bits); - EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); -} - -// Decoding a message we entirely constructed based solely on a given state. -TEST(TestDecodeDaikin, SyntheticExample) { - IRDaikinESP irdaikin(0); - IRsendTest irsend(4); - IRrecv irrecv(4); - irsend.begin(); - - uint8_t expectedState[kDaikinStateLength] = { - 0x11, 0xDA, 0x27, 0x00, 0x42, 0x3A, 0x05, 0x93, 0x11, - 0xDA, 0x27, 0x00, 0x00, 0x3F, 0x3A, 0x00, 0xA0, 0x00, - 0x0A, 0x25, 0x17, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x32}; - - irsend.reset(); - irsend.sendDaikin(expectedState); - irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - ASSERT_EQ(DAIKIN, irsend.capture.decode_type); - ASSERT_EQ(kDaikinBits, irsend.capture.bits); - EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); -} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Whirlpool_test.cpp b/lib/IRremoteESP8266-2.5.2.03/test/ir_Whirlpool_test.cpp deleted file mode 100644 index c30cb21d3..000000000 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Whirlpool_test.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2018 David Conran - -#include "IRrecv.h" -#include "IRrecv_test.h" -#include "IRsend.h" -#include "IRsend_test.h" -#include "gtest/gtest.h" - -// Tests for sendWhirlpoolAC(). - -// Test sending typical data only. -TEST(TestSendWhirlpoolAC, SendDataOnly) { - IRsendTest irsend(0); - irsend.begin(); - uint8_t data[kWhirlpoolAcStateLength] = { - 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; - - irsend.sendWhirlpoolAC(data); - EXPECT_EQ( - "m8950s4484" - "m597s1649m597s1649m597s533m597s533m597s533m597s533m597s533m597s1649" - "m597s533m597s1649m597s1649m597s533m597s533m597s533m597s533m597s533" - "m597s533m597s533m597s533m597s533m597s1649m597s533m597s533m597s533" - "m597s1649m597s533m597s533m597s533m597s1649m597s1649m597s1649m597s533" - "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s7920" - "m597s1649m597s533m597s533m597s533m597s1649m597s533m597s533m597s1649" - "m597s1649m597s1649m597s1649m597s1649m597s1649m597s533m597s533m597s533" - "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s1649m597s1649m597s1649m597s1649m597s533m597s1649m597s1649m597s1649" - "m597s7920" - "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s533m597s1649m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s533m597s1649m597s533m597s533m597s533m597s533m597s533m597s533" - "m597s100000", - irsend.outputStr()); -} - -// Tests for decodeWhirlpoolAC(). -// Decode normal WhirlpoolAC messages. -TEST(TestDecodeWhirlpoolAC, SyntheticDecode) { - IRsendTest irsend(0); - IRrecv irrecv(0); - irsend.begin(); - - // Synthesised Normal WhirlpoolAC message. - irsend.reset(); - uint8_t expectedState[kWhirlpoolAcStateLength] = { - 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; - irsend.sendWhirlpoolAC(expectedState); - irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(WHIRLPOOL_AC, irsend.capture.decode_type); - EXPECT_EQ(kWhirlpoolAcBits, irsend.capture.bits); - EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); -} - -// Decode a recorded example -TEST(TestDecodeWhirlpoolAC, RealExampleDecode) { - IRsendTest irsend(0); - IRrecv irrecv(0); - irsend.begin(); - - // Real WhirlpoolAC message. - // Ref: https://github.com/markszabo/IRremoteESP8266/issues/509 - uint16_t rawData[343] = { - 8950, 4484, 598, 1642, 598, 1646, 594, 534, 594, 538, 602, 532, - 598, 540, 600, 542, 598, 1650, 600, 522, 598, 1644, 596, 1650, - 600, 532, 598, 538, 602, 536, 594, 548, 592, 538, 602, 518, - 600, 524, 596, 532, 598, 532, 598, 1654, 596, 544, 596, 544, - 596, 536, 594, 1644, 596, 528, 600, 528, 592, 538, 602, 1648, - 602, 1654, 596, 1664, 598, 534, 594, 526, 594, 530, 598, 528, - 602, 530, 600, 534, 596, 542, 598, 542, 598, 534, 596, 526, - 594, 530, 600, 528, 602, 530, 600, 534, 596, 542, 598, 544, - 596, 518, 602, 7916, 598, 1642, 598, 528, 600, 528, 602, 530, - 600, 1652, 598, 542, 598, 544, 596, 1654, 596, 1644, 596, 1648, - 602, 1644, 596, 1654, 596, 1656, 604, 536, 594, 548, 602, 528, - 600, 520, 600, 524, 596, 532, 598, 532, 596, 538, 602, 536, - 594, 546, 594, 538, 602, 518, 600, 524, 596, 532, 598, 532, - 598, 536, 594, 544, 596, 544, 596, 536, 594, 526, 592, 530, - 600, 528, 600, 530, 602, 532, 596, 542, 598, 542, 598, 534, - 596, 524, 596, 528, 600, 526, 592, 538, 592, 542, 598, 540, - 600, 540, 600, 530, 598, 522, 598, 526, 594, 534, 596, 534, - 594, 540, 602, 536, 592, 548, 592, 538, 600, 1636, 594, 1648, - 602, 1642, 598, 1652, 598, 538, 602, 1680, 570, 1662, 598, 1634, - 596, 7924, 600, 520, 598, 526, 592, 534, 596, 534, 596, 540, - 600, 536, 604, 538, 602, 530, 600, 520, 598, 1640, 600, 528, - 600, 530, 600, 534, 594, 544, 596, 544, 596, 534, 596, 526, - 594, 528, 600, 526, 594, 536, 592, 542, 598, 538, 602, 538, - 602, 528, 600, 520, 600, 524, 596, 530, 600, 532, 598, 534, - 596, 542, 598, 542, 598, 532, 598, 524, 596, 528, 602, 526, - 594, 536, 594, 540, 600, 536, 594, 548, 592, 538, 602, 518, - 602, 522, 596, 530, 600, 530, 600, 534, 596, 542, 598, 544, - 596, 534, 596, 524, 594, 1644, 596, 532, 596, 534, 596, 538, - 602, 536, 594, 546, 594, 520, 600}; - uint8_t expectedState[kWhirlpoolAcStateLength] = { - 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; - - irsend.reset(); - irsend.sendRaw(rawData, 343, 38000); - irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decode(&irsend.capture)); - EXPECT_EQ(WHIRLPOOL_AC, irsend.capture.decode_type); - EXPECT_EQ(kWhirlpoolAcBits, irsend.capture.bits); - EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); -} diff --git a/lib/IRremoteESP8266-2.5.2.03/.github/CONTRIBUTING.md b/lib/IRremoteESP8266-2.6.0/.github/CONTRIBUTING.md similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/.github/CONTRIBUTING.md rename to lib/IRremoteESP8266-2.6.0/.github/CONTRIBUTING.md diff --git a/lib/IRremoteESP8266-2.5.2.03/.github/Contributors.md b/lib/IRremoteESP8266-2.6.0/.github/Contributors.md similarity index 87% rename from lib/IRremoteESP8266-2.5.2.03/.github/Contributors.md rename to lib/IRremoteESP8266-2.6.0/.github/Contributors.md index 5f75ea3b4..af9734d69 100644 --- a/lib/IRremoteESP8266-2.5.2.03/.github/Contributors.md +++ b/lib/IRremoteESP8266-2.6.0/.github/Contributors.md @@ -12,7 +12,9 @@ - [Jorge Cisneros](https://github.com/jorgecis/) - [Denes Varga](https://github.com/denxhun/) - [Brett T. Warden](https://github.com/bwarden/) +- [Fabien Valthier](https://github.com/hcoohb) +- [Ajay Pala](https://github.com/ajaypala/) -All contributors can be found on the [contributors site](https://github.com/markszabo/IRremoteESP8266/graphs/contributors). +All contributors can be found on the [contributors site](https://github.com/markszabo/IRremoteESP8266/graphs/contributors). ### Contributors of the [original project](https://github.com/z3t0/Arduino-IRremote) can be found on the [original project's contributors page](https://github.com/z3t0/Arduino-IRremote/blob/master/Contributors.md) diff --git a/lib/IRremoteESP8266-2.5.2.03/.github/issue_template.md b/lib/IRremoteESP8266-2.6.0/.github/issue_template.md similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/.github/issue_template.md rename to lib/IRremoteESP8266-2.6.0/.github/issue_template.md diff --git a/lib/IRremoteESP8266-2.5.2.03/.gitignore b/lib/IRremoteESP8266-2.6.0/.gitignore similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/.gitignore rename to lib/IRremoteESP8266-2.6.0/.gitignore diff --git a/lib/IRremoteESP8266-2.5.2.03/.gitmodules b/lib/IRremoteESP8266-2.6.0/.gitmodules similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/.gitmodules rename to lib/IRremoteESP8266-2.6.0/.gitmodules diff --git a/lib/IRremoteESP8266-2.5.2.03/.style.yapf b/lib/IRremoteESP8266-2.6.0/.style.yapf similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/.style.yapf rename to lib/IRremoteESP8266-2.6.0/.style.yapf diff --git a/lib/IRremoteESP8266-2.5.2.03/.travis.yml b/lib/IRremoteESP8266-2.6.0/.travis.yml similarity index 81% rename from lib/IRremoteESP8266-2.5.2.03/.travis.yml rename to lib/IRremoteESP8266-2.6.0/.travis.yml index 4331425e9..ae2d9fe3c 100644 --- a/lib/IRremoteESP8266-2.5.2.03/.travis.yml +++ b/lib/IRremoteESP8266-2.6.0/.travis.yml @@ -1,20 +1,21 @@ language: c env: - - BD=esp8266:esp8266:nodemcuv2:CpuFrequency=80,FlashSize=4M3M - - BD=esp8266:esp8266:d1_mini:CpuFrequency=80,FlashSize=4M3M + - BD=esp8266:esp8266:nodemcuv2:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled + - BD=esp8266:esp8266:d1_mini:xtal=80,eesz=4M3M,ip=lm2f,exception=disabled before_install: - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" - sleep 3 - export DISPLAY=:1.0 - - wget http://downloads.arduino.cc/arduino-1.8.2-linux64.tar.xz - - tar xf arduino-1.8.2-linux64.tar.xz - - sudo mv arduino-1.8.2 /usr/local/share/arduino + - wget http://downloads.arduino.cc/arduino-1.8.8-linux64.tar.xz + - tar xf arduino-1.8.8-linux64.tar.xz + - sudo mv arduino-1.8.8 /usr/local/share/arduino - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino - wget https://raw.githubusercontent.com/google/styleguide/gh-pages/cpplint/cpplint.py install: - ln -s $PWD /usr/local/share/arduino/libraries/ - git clone https://github.com/tzapu/WiFiManager.git /usr/local/share/arduino/libraries/WiFiManager - git clone https://github.com/knolleary/pubsubclient.git /usr/local/share/arduino/libraries/PubSubClient + - git clone https://github.com/bblanchon/ArduinoJson.git --branch 5.x /usr/local/share/arduino/libraries/ArduinoJson - arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs - arduino --install-boards esp8266:esp8266 - arduino --board $BD --save-prefs @@ -40,6 +41,10 @@ script: - arduino --verify --board $BD $PWD/examples/TurnOnArgoAC/TurnOnArgoAC.ino - arduino --verify --board $BD $PWD/examples/IRMQTTServer/IRMQTTServer.ino - arduino --verify --board $BD $PWD/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino + - arduino --verify --board $BD $PWD/examples/ControlSamsungAC/ControlSamsungAC.ino + - arduino --verify --board $BD $PWD/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino + - arduino --verify --board $BD $PWD/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino + # Also check the tools programs compile. - (cd tools; make all) # Check for lint issues. diff --git a/lib/IRremoteESP8266-2.5.2.03/CPPLINT.cfg b/lib/IRremoteESP8266-2.6.0/CPPLINT.cfg similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/CPPLINT.cfg rename to lib/IRremoteESP8266-2.6.0/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.5.2.03/LICENSE.txt b/lib/IRremoteESP8266-2.6.0/LICENSE.txt similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/LICENSE.txt rename to lib/IRremoteESP8266-2.6.0/LICENSE.txt diff --git a/lib/IRremoteESP8266-2.5.2.03/README.md b/lib/IRremoteESP8266-2.6.0/README.md similarity index 95% rename from lib/IRremoteESP8266-2.5.2.03/README.md rename to lib/IRremoteESP8266-2.6.0/README.md index bb9d5a9d8..1eaaa21b4 100644 --- a/lib/IRremoteESP8266-2.5.2.03/README.md +++ b/lib/IRremoteESP8266-2.6.0/README.md @@ -1,14 +1,15 @@ # IRremote ESP8266 Library [![Build Status](https://travis-ci.org/markszabo/IRremoteESP8266.svg?branch=master)](https://travis-ci.org/markszabo/IRremoteESP8266) +[![arduino-library-badge](https://www.ardu-badge.com/badge/IRremoteESP8266.svg?)](https://www.ardu-badge.com/IRremoteESP8266) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Average time to resolve an issue") [![Percentage of issues still open](http://isitmaintained.com/badge/open/markszabo/IRremoteESP8266.svg)](http://isitmaintained.com/project/markszabo/IRremoteESP8266 "Percentage of issues still open") [![GitLicense](https://gitlicense.com/badge/markszabo/IRremoteESP8266)](https://gitlicense.com/license/markszabo/IRremoteESP8266) This library enables you to **send _and_ receive** infra-red signals on an [ESP8266 using the Arduino framework](https://github.com/esp8266/Arduino) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* etc. -## v2.5.2 Now Available -Version 2.5.2 of the library is now [available](https://github.com/markszabo/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. +## v2.6.0 Now Available +Version 2.6.0 of the library is now [available](https://github.com/markszabo/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. #### Upgrading from pre-v2.0 Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/markszabo/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. diff --git a/lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md b/lib/IRremoteESP8266-2.6.0/ReleaseNotes.md similarity index 72% rename from lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md rename to lib/IRremoteESP8266-2.6.0/ReleaseNotes.md index 56e84dd89..98416a12a 100644 --- a/lib/IRremoteESP8266-2.5.2.03/ReleaseNotes.md +++ b/lib/IRremoteESP8266-2.6.0/ReleaseNotes.md @@ -1,5 +1,107 @@ # Release Notes +## _v2.6.0 (20190430)_ + +**[Bug Fixes]** +- Fixed problem where LG protocol used wrong duty cycle for repeat. (#687) +- Fix checksum calculation for Daikin protocols. (#678) +- Fix the byte array version of sendGree() (#684, #685) +- Fix artificial vs. real state creation on HaierAC. (#668, #671) +- Fix issues caused by having `MQTT_ENABLE` set to false. (#677) +- Fix compile problem when DEBUG is defined. (#673, #674) +- Fix Minor bug with MQTT_ENABLE False condition (#654) + +**[Features]** +- Experimental support for DAIKIN216 (ARC433B69) (#690) +- Experimental support for Mitsubishi Heavy Industries A/Cs. (#660, #665, #667) +- Support more features of TCL A/C (#656) +- Add LEGO(TM) Power Functions IR protocol. (#655) +- Add Panasonic AC RKR model & Example (#649) +- DAIKIN/IRDaikinESP overhaul and add Comfort mode support. (#678) + **WARNING**: Previous `sendDaikin()` calls may not work. + Please recapture codes or use `kDaikinStateLengthShort` for + `nbytes` in those calls. +- IRMQTTServer: Move MQTT server and other parameters to WifiManager. (#680) + **WARNING**: Previous users may need to fully wipe/reset the + SPIFFS/WifiManager settings by visiting + `http:///reset` prior to or + after update. +- Add Wifi filtering options to IRMQTTServer. (#679) +- Add advanced aircon/climate functionality to IRMQTTServer (#677) +- Initial prototype of a common interface for all A/Cs. (#664) +- Improve MQTT topic usage for feedback messages. (#663) +- Add multiple independent GPIO sending support via MQTT. (#661) + +**[Misc]** +- Adjust kGreeHdrSpace to 4500 (#684, #686) +- Add Home Assistant mqtt climate instructions. (#682) +- Implement htmlEscape() to prevent XSS etc. (#681) +- Add F() Macros (#670) +- Update Daikin2's Cool mode min temp to 18C (#658) +- Change per byte bit-order in Electra protocol. (#648) +- Improve Daikin2 power on/off. (#647) + + +## _v2.5.6 (20190316)_ + +**[Bug Fixes]** +- Fix Coolix A/C Class to handle special states better. (#633, #624) + +**[Features]** +- Fix case style for recent A/C protocols. (#631) +- Update `IRsend::send()` to include all simple protocols. (#629, #628) +- Experimental basic support for 112 bit TCL AC messages (#627, #619) +- Add support for TECO AC (#622) +- Experimental support for Samsung 36 bit protocol (#625, #621) + +**[Misc]** +- Set Coolix to default to 1 repeat. (#637, #636, #624, #439) +- Set Daikin2 modulation to 36.7kHz. (#635) +- Refactor IRVestelAC class to use portable code. (#617) +- Adjust Daikin2 timings and tolerance. (#616, #582) + + +## _v2.5.5 (20190207)_ + +**[Bug Fixes]** +- Fix decoding of Samsung A/C Extended messages. (#610) +- Fix IRMQTTServer example to work with GPIO0 as IR_RX (#608) +- Fix incorrect #define usage. (#597, #596) + +**[Features]** +- Add deep decoding/construction of Daikin2 messages (#600) +- Added Old Vestel A/C support (56 Bits) with full functions. (#607) + +**[Misc]** +- Add ControlSamsungAC example code. (#599) +- Add how to send a state/air-con to IRsendDemo.ino (#594) + + +## _v2.5.4 (20190102)_ + +**[Features]** +- Experimental basic support for 39 Byte Daikin A/C (#583) +- Handle send() repeats in A/C classes. Improve Coolix support. (#580) +- Add optional RX pin pullup and dump raw messages in IRMQTTServer.ino (#589) + +**[Misc]** +- Make auto_analyse_raw_data.py work with Python3 (#581) +- Update CI/travis config due to esp8266 core 2.5.0 changes (#591) + + +## _v2.5.3 (20181123)_ + +**[Features]** +- Add deep support for the Hitachi 28-Byte A/C Protocol (#563) +- Deep decoding for Whirlpool A/C (#572) +- Improve security options for IRMQTTServer example. (#575) +- Require a changed firmware password before upload. (#576) + +**[Misc]** +- Add missing '}' in output of Auto analyse. (#562) +- Make A/C example code a bit more simple. (#571) + + ## _v2.5.2 (20181021)_ **[Bug Fixes]** diff --git a/lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/ControlSamsungAC.ino b/lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/ControlSamsungAC.ino new file mode 100644 index 000000000..df910fe87 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/ControlSamsungAC.ino @@ -0,0 +1,99 @@ +/* Copyright 2019 David Conran +* +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. +* +* TL;DR: The IR LED needs to be driven by a transistor for a good result. +* +* Suggested circuit: +* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending +* +* Common mistakes & tips: +* * Don't just connect the IR LED directly to the pin, it won't +* have enough current to drive the IR LED effectively. +* * Make sure you have the IR LED polarity correct. +* See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity +* * Typical digital camera/phones can be used to see if the IR LED is flashed. +* Replace the IR LED with a normal LED if you don't have a digital camera +* when debugging. +* * Avoid using the following pins unless you really know what you are doing: +* * Pin 0/D3: Can interfere with the boot/program mode & support circuits. +* * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will interfere. +* * Pin 3/RX/RXD0: Any serial transmissions to the ESP8266 will interfere. +* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs +* for your first time. e.g. ESP-12 etc. +*/ +#ifndef UNIT_TEST +#include +#endif +#include +#include +#include + +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRSamsungAc ac(kIrLed); // Set the GPIO used for sending messages. + +void printState() { + // Display the settings. + Serial.println("Samsung A/C remote is in the following state:"); + Serial.printf(" %s\n", ac.toString().c_str()); +} + +void setup() { + ac.begin(); + Serial.begin(115200); + delay(200); + + // Set up what we want to send. See ir_Samsung.cpp for all the options. + Serial.println("Default state of the remote."); + printState(); + Serial.println("Setting initial state for A/C."); + ac.off(); + ac.setFan(kSamsungAcFanLow); + ac.setMode(kSamsungAcCool); + ac.setTemp(25); + ac.setSwing(false); + printState(); +} + +void loop() { + // Turn the A/C unit on and set to cooling mode. + // Power changes require we send an extended message. + Serial.println("Sending an extended IR command to A/C ..."); + ac.on(); + ac.setMode(kSamsungAcCool); + ac.sendExtended(); + printState(); + delay(15000); // wait 15 seconds + + // Increase the fan speed. + Serial.println("Sending a normal IR command to A/C ..."); + ac.setFan(kSamsungAcFanHigh); + ac.send(); + printState(); + delay(15000); + + // Change to swing the fan. + Serial.println("Sending a normal IR command to A/C ..."); + ac.setSwing(true); + ac.send(); + printState(); + delay(15000); + + // Change to Fan mode, lower the speed, and stop the swing. + Serial.println("Sending a normal IR command to A/C ..."); + ac.setSwing(false); + ac.setMode(kSamsungAcFan); + ac.setFan(kSamsungAcFanLow); + ac.send(); + printState(); + delay(15000); + + // Turn the A/C unit off. + // Power changes require we send an extended message. + Serial.println("Sending an extended IR command to A/C ..."); + ac.off(); + ac.sendExtended(); + printState(); + delay(15000); // wait 15 seconds +} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/platformio.ini similarity index 83% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/platformio.ini rename to lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/platformio.ini index eeb8d1f2e..ec84f22f3 100644 --- a/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/platformio.ini +++ b/lib/IRremoteESP8266-2.6.0/examples/ControlSamsungAC/platformio.ini @@ -6,11 +6,13 @@ src_dir=. build_flags = lib_deps_builtin = lib_deps_external = +lib_ldf_mode = chain+ [env:nodemcuv2] platform = espressif8266 framework = arduino board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} build_flags = ${common.build_flags} lib_deps = ${common.lib_deps_builtin} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/IRGCSendDemo.ino b/lib/IRremoteESP8266-2.6.0/examples/IRGCSendDemo/IRGCSendDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/IRGCSendDemo.ino rename to lib/IRremoteESP8266-2.6.0/examples/IRGCSendDemo/IRGCSendDemo.ino diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRGCSendDemo/platformio.ini similarity index 83% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/platformio.ini rename to lib/IRremoteESP8266-2.6.0/examples/IRGCSendDemo/platformio.ini index eeb8d1f2e..ec84f22f3 100644 --- a/lib/IRremoteESP8266-2.5.2.03/examples/IRGCSendDemo/platformio.ini +++ b/lib/IRremoteESP8266-2.6.0/examples/IRGCSendDemo/platformio.ini @@ -6,11 +6,13 @@ src_dir=. build_flags = lib_deps_builtin = lib_deps_external = +lib_ldf_mode = chain+ [env:nodemcuv2] platform = espressif8266 framework = arduino board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} build_flags = ${common.build_flags} lib_deps = ${common.lib_deps_builtin} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/IRGCTCPServer.ino b/lib/IRremoteESP8266-2.6.0/examples/IRGCTCPServer/IRGCTCPServer.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/IRGCTCPServer.ino rename to lib/IRremoteESP8266-2.6.0/examples/IRGCTCPServer/IRGCTCPServer.ino diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRGCTCPServer/platformio.ini similarity index 83% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/platformio.ini rename to lib/IRremoteESP8266-2.6.0/examples/IRGCTCPServer/platformio.ini index eeb8d1f2e..ec84f22f3 100644 --- a/lib/IRremoteESP8266-2.5.2.03/examples/IRGCTCPServer/platformio.ini +++ b/lib/IRremoteESP8266-2.6.0/examples/IRGCTCPServer/platformio.ini @@ -6,11 +6,13 @@ src_dir=. build_flags = lib_deps_builtin = lib_deps_external = +lib_ldf_mode = chain+ [env:nodemcuv2] platform = espressif8266 framework = arduino board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} build_flags = ${common.build_flags} lib_deps = ${common.lib_deps_builtin} diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.h b/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.h new file mode 100644 index 000000000..9494dbe2b --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.h @@ -0,0 +1,258 @@ +/* + * Send & receive arbitrary IR codes via a web server or MQTT. + * Copyright David Conran 2016, 2017, 2018, 2019 + */ +#ifndef EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_ +#define EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_ + +#include +#include +#include +#include +#include +#include + +// ---------------- Start of User Configuration Section ------------------------ + +#ifndef MQTT_ENABLE +#define MQTT_ENABLE true // Whether or not MQTT is used at all. +#endif // MQTT_ENABLE + +// ---------------------- Board Related Settings ------------------------------- +// NOTE: Make sure you set your Serial Monitor to the same speed. +#define BAUD_RATE 115200 // Serial port Baud rate. + +// GPIO the IR LED is connected to/controlled by. GPIO 4 = D2. +#define IR_LED 4 // <=- CHANGE_ME (optional) +// define IR_LED 3 // For an ESP-01 we suggest you use RX/GPIO3/Pin 7. + +// GPIO the IR RX module is connected to/controlled by. e.g. GPIO 14 = D5. +// Comment this out to disable receiving/decoding IR messages entirely. +#define IR_RX 14 // <=- CHANGE_ME (optional) +#define IR_RX_PULLUP false + +// --------------------- Network Related Settings ------------------------------ +const uint16_t kHttpPort = 80; // The TCP port the HTTP server is listening on. +// Change to 'true'/'false' if you do/don't want these features or functions. +#define USE_STATIC_IP false // Change to 'true' if you don't want to use DHCP. +// We obtain our network config via DHCP by default but allow an easy way to +// use a static IP config. +#if USE_STATIC_IP +const IPAddress kIPAddress = IPAddress(10, 0, 1, 78); +const IPAddress kGateway = IPAddress(10, 0, 1, 1); +const IPAddress kSubnetMask = IPAddress(255, 255, 255, 0); +#endif // USE_STATIC_IP + +// See: https://github.com/tzapu/WiFiManager#filter-networks for these settings. +#define HIDE_DUPLIATE_NETWORKS false // Should WifiManager hide duplicate SSIDs +// #define MIN_SIGNAL_STRENGTH 20 // Minimum WiFi signal stength (percentage) + // before we will connect. + // The unset default is 8%. + // (Uncomment to enable) + +// ----------------------- HTTP Related Settings ------------------------------- +#define FIRMWARE_OTA true // Allow remote update of the firmware via http. + // Less secure if enabled. + // Note: Firmware OTA is also disabled until + // a password is set. +#define HTML_PASSWORD_ENABLE false // Protect access to the HTML interface. + // Note: OTA update is always passworded. +// If you do not set a password, Firmware OTA updates will be blocked. + +// ----------------------- MQTT Related Settings ------------------------------- +#if MQTT_ENABLE +const uint32_t kMqttReconnectTime = 5000; // Delay(ms) between reconnect tries. + +#define MQTT_ACK "sent" // Sub-topic we send back acknowledgements on. +#define MQTT_SEND "send" // Sub-topic we get new commands from. +#define MQTT_RECV "received" // Topic we send received IRs to. +#define MQTT_LOG "log" // Topic we send log messages to. +#define MQTT_LWT "status" // Topic for the Last Will & Testament. +#define MQTT_CLIMATE "ac" // Sub-topic for the climate topics. +#define MQTT_CLIMATE_CMND "cmnd" // Sub-topic for the climate command topics. +#define MQTT_CLIMATE_STAT "stat" // Sub-topic for the climate stat topics. +#define MQTTbroadcastInterval 10 * 60 // Seconds between rebroadcasts + +#define QOS 1 // MQTT broker should queue up any unreceived messages for us +// #define QOS 0 // MQTT broker WON'T queue up messages for us. Fire & Forget. +#endif // MQTT_ENABLE + +// ------------------------ IR Capture Settings -------------------------------- +// Let's use a larger than normal buffer so we can handle AirCon remote codes. +const uint16_t kCaptureBufferSize = 1024; +#if DECODE_AC +// Some A/C units have gaps in their protocols of ~40ms. e.g. Kelvinator +// A value this large may swallow repeats of some protocols +const uint8_t kCaptureTimeout = 50; // Milliseconds +#else // DECODE_AC +// Suits most messages, while not swallowing many repeats. +const uint8_t kCaptureTimeout = 15; // Milliseconds +#endif // DECODE_AC +// Ignore unknown messages with <10 pulses (see also REPORT_UNKNOWNS) +const uint16_t kMinUnknownSize = 2 * 10; +#define REPORT_UNKNOWNS false // Report inbound IR messages that we don't know. +#define REPORT_RAW_UNKNOWNS false // Report the whole buffer, recommended: + // MQTT_MAX_PACKET_SIZE of 1024 or more + +// ------------------------ Advanced Usage Only -------------------------------- +// Change if you need multiple independent send gpio/topics. +const uint8_t gpioTable[] = { + IR_LED, // Default GPIO. e.g. ir_server/send or ir_server/send_0 + // Uncomment the following as needed. + // NOTE: Remember to disable DEBUG if you are using one of the serial pins. + // 5, // GPIO 5 / D1 e.g. ir_server/send_1 + // 14, // GPIO 14 / D5 e.g. ir_server/send_2 + // 16, // GPIO 16 / D0 e.g. ir_server/send_3 +}; + +#define KEY_PROTOCOL "protocol" +#define KEY_MODEL "model" +#define KEY_POWER "power" +#define KEY_MODE "mode" +#define KEY_TEMP "temp" +#define KEY_FANSPEED "fanspeed" +#define KEY_SWINGV "swingv" +#define KEY_SWINGH "swingh" +#define KEY_QUIET "quiet" +#define KEY_TURBO "turbo" +#define KEY_LIGHT "light" +#define KEY_BEEP "beep" +#define KEY_ECONO "econo" +#define KEY_SLEEP "sleep" +#define KEY_CLOCK "clock" +#define KEY_FILTER "filter" +#define KEY_CLEAN "clean" +#define KEY_CELSIUS "use_celsius" + +// HTML arguments we will parse for IR code information. +#define KEY_TYPE "type" // KEY_PROTOCOL is also checked too. +#define KEY_CODE "code" +#define KEY_BITS "bits" +#define KEY_REPEAT "repeats" + +// Text for Last Will & Testament status messages. +const char* kLwtOnline = "Online"; +const char* kLwtOffline = "Offline"; + +const uint8_t kHostnameLength = 30; +const uint8_t kPortLength = 5; // Largest value of uint16_t is "65535". +const uint8_t kUsernameLength = 15; +const uint8_t kPasswordLength = 20; + +// -------------------------- Debug Settings ----------------------------------- +// Disable debug output if any of the IR pins are on the TX (D1) pin. +// Note: This is a crude method to catch the common use cases. +// See `isSerialGpioUsedByIr()` for the better method. +#if (IR_LED != 1 && IR_RX != 1) +#ifndef DEBUG +#define DEBUG true // Change to 'false' to disable all serial output. +#endif // DEBUG +#else // (IR_LED != 1 && IR_RX != 1) +#undef DEBUG +#define DEBUG false +#endif + +// ----------------- End of User Configuration Section ------------------------- + +// Constants +#define _MY_VERSION_ "v1.0.0" + +const uint8_t kSendTableSize = sizeof(gpioTable); +// JSON stuff +// Name of the json config file in SPIFFS. +const char* kConfigFile = "/config.json"; +const char* kMqttServerKey = "mqtt_server"; +const char* kMqttPortKey = "mqtt_port"; +const char* kMqttUserKey = "mqtt_user"; +const char* kMqttPassKey = "mqtt_pass"; +const char* kMqttPrefixKey = "mqtt_prefix"; +const char* kHostnameKey = "hostname"; +const char* kHttpUserKey = "http_user"; +const char* kHttpPassKey = "http_pass"; + +#if MQTT_ENABLE +const uint32_t kBroadcastPeriodMs = MQTTbroadcastInterval * 1000; // mSeconds. +const uint32_t kStatListenPeriodMs = 5 * 1000; // mSeconds + +void mqttCallback(char* topic, byte* payload, unsigned int length); +String listOfCommandTopics(void); +void handleSendMqttDiscovery(void); +void subscribing(const String topic_name); +void unsubscribing(const String topic_name); +void mqttLog(const String mesg); +bool reconnect(void); +void receivingMQTT(String const topic_name, String const callback_str); +void callback(char* topic, byte* payload, unsigned int length); +void sendMQTTDiscovery(const char *topic); +void doBroadcast(TimerMs *timer, const uint32_t interval, + const commonAcState_t state, const bool retain, + const bool force); +#endif // MQTT_ENABLE +bool isSerialGpioUsedByIr(void); +void debug(const char *str); +void saveWifiConfigCallback(void); +void saveWifiConfig(void); +void loadWifiConfigFile(void); +String msToHumanString(uint32_t const msecs); +String timeElapsed(uint32_t const msec); +String timeSince(uint32_t const start); +String listOfSendGpios(void); +bool hasUnsafeHTMLChars(String input); +String htmlMenu(void); +void handleRoot(void); +String addJsReloadUrl(const String url, const uint16_t timeout_s, + const bool notify); +void handleExamples(void); +String boolToString(const bool value); +String opmodeToString(const stdAc::opmode_t mode); +String fanspeedToString(const stdAc::fanspeed_t speed); +String swingvToString(const stdAc::swingv_t swingv); +String swinghToString(const stdAc::swingh_t swingh); +String htmlSelectBool(const String name, const bool def); +String htmlSelectProtocol(const String name, const decode_type_t def); +String htmlSelectModel(const String name, const int16_t def); +String htmlSelectMode(const String name, const stdAc::opmode_t def); +String htmlSelectFanspeed(const String name, const stdAc::fanspeed_t def); +String htmlSelectSwingv(const String name, const stdAc::swingv_t def); +String htmlSelectSwingh(const String name, const stdAc::swingh_t def); +void handleAirCon(void); +void handleAirConSet(void); +void handleAdmin(void); +void handleInfo(void); +void handleReset(void); +void handleReboot(void); +bool parseStringAndSendAirCon(IRsend *irsend, const uint16_t irType, + const String str); +uint16_t countValuesInStr(const String str, char sep); +uint16_t * newCodeArray(const uint16_t size); +#if SEND_GLOBALCACHE +bool parseStringAndSendGC(IRsend *irsend, const String str); +#endif // SEND_GLOBALCACHE +#if SEND_PRONTO +bool parseStringAndSendPronto(IRsend *irsend, const String str, + uint16_t repeats); +#endif // SEND_PRONTO +#if SEND_RAW +bool parseStringAndSendRaw(IRsend *irsend, const String str); +#endif // SEND_RAW +void handleIr(void); +void handleNotFound(void); +void setup_wifi(void); +void init_vars(void); +void setup(void); +void loop(void); +uint64_t getUInt64fromHex(char const *str); +bool sendIRCode(IRsend *irsend, int const ir_type, + uint64_t const code, char const * code_str, uint16_t bits, + uint16_t repeat); +bool sendInt(const String topic, const int32_t num, const bool retain); +bool sendBool(const String topic, const bool on, const bool retain); +bool sendString(const String topic, const String str, const bool retain); +bool sendFloat(const String topic, const float_t temp, const bool retain); +commonAcState_t updateClimate(commonAcState_t current, const String str, + const String prefix, const String payload); +bool cmpClimate(const commonAcState_t a, const commonAcState_t b); +bool sendClimate(const commonAcState_t prev, const commonAcState_t next, + const String topic_prefix, const bool retain, + const bool forceMQTT, const bool forceIR); +#endif // EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_ diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.ino b/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.ino new file mode 100644 index 000000000..31e40432d --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.ino @@ -0,0 +1,3034 @@ +/* + * Send & receive arbitrary IR codes via a web server or MQTT. + * Copyright David Conran 2016, 2017, 2018, 2019 + * + * Copyright: + * Code for this has been borrowed from lots of other OpenSource projects & + * resources. I'm *NOT* claiming complete Copyright ownership of all the code. + * Likewise, feel free to borrow from this as much as you want. + * + * NOTE: An IR LED circuit SHOULD be connected to ESP8266 GPIO4 (D2) if + * you want to send IR messages. + * A compatible IR RX modules SHOULD be connected to ESP8266 GPIO14 (D5) + * if you want to capture & decode IR nessages. + * See 'IR_LED' & 'IR_RX' in IRMQTTServer.h. + * + * WARN: This is *very* advanced & complicated example code. Not for beginners. + * You are strongly suggested to try & look at other example code first + * to understand how this library works. + * + * # Instructions + * + * ## Before First Boot (i.e. Compile time) + * - Disable MQTT if desired. (see '#define MQTT_ENABLE' in IRMQTTServer.h). + * + * - Site specific settings: + * o Search for 'CHANGE_ME' in IRMQTTServer.h for the things you probably + * need to change for your particular situation. + * o All user changable settings are in the file IRMQTTServer.h. + * + * - Arduino IDE: + * o Install the following libraries via Library Manager + * - ArduinoJson (https://arduinojson.org/) (Version >= 5.x and < 6) + * - PubSubClient (https://pubsubclient.knolleary.net/) + * - WiFiManager (https://github.com/tzapu/WiFiManager) (Version >= 0.14) + * o You MUST change to have the following (or larger) value: + * (with REPORT_RAW_UNKNOWNS 1024 or more is recommended) + * #define MQTT_MAX_PACKET_SIZE 768 + * - PlatformIO IDE: + * If you are using PlatformIO, this should already been done for you in + * the accompanying platformio.ini file. + * + * ## First Boot (Initial setup) + * The ESP8266 board will boot into the WiFiManager's AP mode. + * i.e. It will create a WiFi Access Point with a SSID like: "ESP123456" etc. + * Connect to that SSID. Then point your browser to http://192.168.4.1/ and + * configure the ESP8266 to connect to your desired WiFi network and associated + * required settings. It will remember these details on next boot if the device + * connects successfully. + * More information can be found here: + * https://github.com/tzapu/WiFiManager#how-it-works + * + * If you need to reset the WiFi and saved settings to go back to "First Boot", + * visit: http:///reset + * + * ## Normal Use (After initial setup) + * Enter 'http:///ir?type=7&code=E0E09966 + * http:///ir?type=4&code=0xf50&bits=12 + * http:///ir?code=C1A2E21D&repeats=8&type=19 + * http:///ir?type=31&code=40000,1,1,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,1058 + * http:///ir?type=18&code=190B8050000000E0190B8070000010f0 + * http:///ir?repeats=1&type=25&code=0000,006E,0022,0002,0155,00AA,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0040,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0040,0015,0040,0015,0040,0015,0640,0155,0055,0015,0E40 + * + * or + * + * Send a MQTT message to the topic 'ir_server/send' (or 'ir_server/send_0' etc) + * using the following format (Order is important): + * protocol_num,hexcode + * e.g. 7,E0E09966 + * which is: Samsung(7), Power On code, default bit size, + * default nr. of repeats. + * + * protocol_num,hexcode,bits + * e.g. 4,f50,12 + * which is: Sony(4), Power Off code, 12 bits & default nr. of repeats. + * + * protocol_num,hexcode,bits,repeats + * e.g. 19,C1A2E21D,0,8 + * which is: Sherwood(19), Vol Up, default bit size & repeated 8 times. + * + * 30,frequency,raw_string + * e.g. 30,38000,9000,4500,500,1500,500,750,500,750 + * which is: Raw (30) @ 38kHz with a raw code of + * "9000,4500,500,1500,500,750,500,750" + * + * 31,code_string + * e.g. 31,40000,1,1,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,1058 + * which is: GlobalCache (31) & "40000,1,1,96,..." (Sony Vol Up) + * + * 25,Rrepeats,hex_code_string + * e.g. 25,R1,0000,006E,0022,0002,0155,00AA,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0040,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0015,0040,0015,0015,0015,0015,0015,0040,0015,0040,0015,0040,0015,0040,0015,0040,0015,0640,0155,0055,0015,0E40 + * which is: Pronto (25), 1 repeat, & "0000 006E 0022 0002 ..." + * aka a "Sherwood Amp Tape Input" message. + * + * ac_protocol_num,really_long_hexcode + * e.g. 18,190B8050000000E0190B8070000010F0 + * which is: Kelvinator (18) Air Con on, Low Fan, 25 deg etc. + * NOTE: Ensure you zero-pad to the correct number of digits for the + * bit/byte size you want to send as some A/C units have units + * have different sized messages. e.g. Fujitsu A/C units. + * + * In short: + * No spaces after/before commas. + * Values are comma separated. + * The first value is always in Decimal. + * For simple protocols, the next value (hexcode) is always hexadecimal. + * The optional bit size is in decimal. + * CAUTION: Some AC protocols DO NOT use the really_long_hexcode method. + * e.g. < 64bit AC protocols. + * + * Unix command line usage example: + * # Install a MQTT client + * $ sudo apt install mosquitto-clients + * # Send a 32-bit NEC code of 0x1234abcd via MQTT. + * $ mosquitto_pub -h 10.0.0.4 -t ir_server/send -m '3,1234abcd,32' + * + * This server will send (back) what ever IR message it just transmitted to + * the MQTT topic 'ir_server/sent' to confirm it has been performed. This works + * for messages requested via MQTT or via HTTP. + * + * Unix command line usage example: + * # Listen to MQTT acknowledgements. + * $ mosquitto_sub -h 10.0.0.4 -t ir_server/sent + * + * Incoming IR messages (from an IR remote control) will be transmitted to + * the MQTT topic 'ir_server/received'. The MQTT message will be formatted + * similar to what is required to for the 'sent' topic. + * e.g. "3,C1A2F00F,32" (Protocol,Value,Bits) for simple codes + * or "18,110B805000000060110B807000001070" (Protocol,Value) for complex codes + * Note: If the protocol is listed as -1, then that is an UNKNOWN IR protocol. + * You can't use that to recreate/resend an IR message. It's only for + * matching purposes and shouldn't be trusted. + * + * Unix command line usage example: + * # Listen via MQTT for IR messages captured by this server. + * $ mosquitto_sub -h 10.0.0.4 -t ir_server/received + * + * Note: General logging messages are also sent to 'ir_server/log' from + * time to time. + * + * ## Climate (AirCon) interface. (Advanced use) + * You can now control Air Conditioner devices that have full/detailed support + * from the IRremoteESP8266 library. See the "Aircon" page for list of supported + * devices. You can do this via HTTP/HTML or via MQTT. + * + * NOTE: It will only change the attributes you change/set. It's up to you to + * maintain a consistent set of attributes for your particular aircon. + * + * TIP: Use "-1" for 'model' if your A/C doesn't have a specific `setModel()` + * or IR class attribute. Most don't. Some do. + * e.g. PANASONIC_AC, FUJITSU_AC, WHIRLPOOL_AC + * + * ### via MQTT: + * The code listen for commands (via wildcard) on the MQTT topics at the + * `ir_server/ac/cmnd/+` level, such as: + * i.e. protocol, model, power, mode, temp, fanspeed, swingv, swingh, quiet, + * turbo, light, beep, econo, sleep, filter, clean, use_celsius + * e.g. ir_server/ac/cmnd/power, ir_server/ac/cmnd/temp, etc. + * It will process them, and if successful and it caused a change, it will + * acknowledge this via the relevant state topic for that command. + * e.g. If the aircon/climate changes from power off to power on, it will + * send an "on" payload to "ir_server/ac/stat/power" + * NOTE: These "stat" messages have the MQTT retain flag set to on. Thus the + * MQTT broker will remember them until reset/restarted etc. + * + * The code will also periodically broadcast all possible aircon/climate state + * attributes to their corresponding "ir_server/ac/stat" topics. This ensures + * any updates to the ESP's knowledge that may have been lost in transmission + * are re-communicated. e.g. The MQTT broker being offline. + * This also helps with Home Assistant MQTT discovery. + * + * The program on boot & first successful connection to the MQTT broker, will + * try to re-acquire any previous aircon/climate state information and act + * accordingly. This will typically result in A/C IR message being sent as and + * saved state will probably be different from the defaults. + * + * NOTE: Command attributes are processed sequentially. + * e.g. Going from "25C, cool, fan low" to "27C, heat, fan high" may go + * via "27C, cool, fan low" & "27C, heat, fan low" depending on the order + * of arrival & processing of the MQTT commands. + * + * ### Home Assistant (HA) MQTT climate integration + * After you have set the Protocol (required) & Model (if needed) and any of + * the other misc aircon settings you desire, you can then add the following to + * your Home Assistant configuration, and it should allow you to + * control most of the important settings. Google Home/Assistant (via HA) + * can also control the device, but you will need to configure Home Assistant + * via it's documentation for that. It has even more limited control. + * It's far beyond the scope of these instructions to guide you through setting + * up HA and Google Home integration. See https://www.home-assistant.io/ + * + * In HA's configuration.yaml, add: + * + * climate: + * platform: mqtt + * name: Living Room Aircon + * modes: + * - "off" + * - "auto" + * - "cool" + * - "heat" + * - "dry" + * - "fan_only" + * fan_modes: + * - "auto" + * - "min" + * - "low" + * - "medium" + * - "high" + * - "max" + * swing_modes: + * - "off" + * - "auto" + * - "highest" + * - "high" + * - "middle" + * - "low" + * - "lowest" + * power_command_topic: "ir_server/ac/cmnd/power" + * mode_command_topic: "ir_server/ac/cmnd/mode" + * mode_state_topic: "ir_server/ac/stat/mode" + * temperature_command_topic: "ir_server/ac/cmnd/temp" + * temperature_state_topic: "ir_server/ac/stat/temp" + * fan_mode_command_topic: "ir_server/ac/cmnd/fanspeed" + * fan_mode_state_topic: "ir_server/ac/stat/fanspeed" + * swing_mode_command_topic: "ir_server/ac/cmnd/swingv" + * swing_mode_state_topic: "ir_server/ac/stat/swingv" + * min_temp: 16 + * max_temp: 32 + * temp_step: 1 + * retain: false + * + * ### via HTTP: + * Use the "http:///aircon/set" URL and pass on + * the arguments as needed to control your device. See the `KEY_*` #defines + * in the code for all the parameters. + * i.e. protocol, model, power, mode, temp, fanspeed, swingv, swingh, quiet, + * turbo, light, beep, econo, sleep, filter, clean, use_celsius + * Example: + * http:///aircon/set?protocol=PANASONIC_AC&model=LKE&power=on&mode=auto&fanspeed=min&temp=23 + * + * ## Debugging & Logging + * If DEBUG is turned on, there is additional information printed on the Serial + * Port. Serial Port output may be disabled if the GPIO is used for IR. + * + * If MQTT is enabled, some information/logging is sent to the MQTT topic: + * `ir_server/log` + * + * ## Updates + * You can upload new firmware over the air (OTA) via the form on the device's + * main page. No need to connect to the device again via USB. \o/ + * Your WiFi settings should be remembered between updates. \o/ \o/ + * + * ## Security + * + * There is NO authentication set on the HTTP/HTML interface by default (see + * `HTML_PASSWORD_ENABLE` to change that), and there is NO SSL/TLS (encryption) + * used by this example code. + * i.e. All usernames & passwords are sent in clear text. + * All communication to the MQTT server is in clear text. + * e.g. This on/using the public Internet is a 'Really Bad Idea'! + * You should NOT have or use this code or device exposed on an untrusted and/or + * unprotected network. + * If you allow access to OTA firmware updates, then a 'Bad Guy' could + * potentially compromise your network. OTA updates are password protected by + * default. If you are sufficiently paranoid, you SHOULD disable uploading + * firmware via OTA. (see 'FIRMWARE_OTA') + * You SHOULD also set/change all usernames & passwords. + * For extra bonus points: Use a separate untrusted SSID/vlan/network/ segment + * for your IoT stuff, including this device. + * Caveat Emptor. You have now been suitably warned. + * + */ + +#include "IRMQTTServer.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if MQTT_ENABLE +// -------------------------------------------------------------------- +// * * * IMPORTANT * * * +// You must change to have the following value. +// #define MQTT_MAX_PACKET_SIZE 768 +// -------------------------------------------------------------------- +#include +#endif // MQTT_ENABLE +#include // NOLINT(build/include) +#include +#include + +// Globals +ESP8266WebServer server(kHttpPort); +#ifdef IR_RX +IRrecv irrecv(IR_RX, kCaptureBufferSize, kCaptureTimeout, true); +decode_results capture; // Somewhere to store inbound IR messages. +#endif // IR_RX +MDNSResponder mdns; +WiFiClient espClient; +WiFiManager wifiManager; +bool flagSaveWifiConfig = false; +char HttpUsername[kUsernameLength + 1] = "admin"; // Default HTT username. +char HttpPassword[kPasswordLength + 1] = ""; // No HTTP password by default. +char Hostname[kHostnameLength + 1] = "ir_server"; // Default hostname. +uint16_t *codeArray; +uint32_t lastReconnectAttempt = 0; // MQTT last attempt reconnection number +bool boot = true; +bool lockIr = false; // Primitive locking for gating the IR LED. +uint32_t sendReqCounter = 0; +bool lastSendSucceeded = false; // Store the success status of the last send. +uint32_t lastSendTime = 0; +int8_t offset; // The calculated period offset for this chip and library. +IRsend *IrSendTable[kSendTableSize]; + +#ifdef IR_RX +String lastIrReceived = "None"; +uint32_t lastIrReceivedTime = 0; +uint32_t irRecvCounter = 0; +#endif // IR_RX + +// Climate stuff +commonAcState_t climate; +commonAcState_t climate_prev; +IRac commonAc(gpioTable[0]); +TimerMs lastClimateIr = TimerMs(); // When we last sent the IR Climate mesg. +uint32_t irClimateCounter = 0; // How many have we sent? +// Store the success status of the last climate send. +bool lastClimateSucceeded = false; +bool hasClimateBeenSent = false; // Has the Climate ever been sent? + +#if MQTT_ENABLE +PubSubClient mqtt_client(espClient); +String lastMqttCmd = "None"; +String lastMqttCmdTopic = "None"; +uint32_t lastMqttCmdTime = 0; +uint32_t lastConnectedTime = 0; +uint32_t lastDisconnectedTime = 0; +uint32_t mqttDisconnectCounter = 0; +uint32_t mqttSentCounter = 0; +uint32_t mqttRecvCounter = 0; +bool wasConnected = true; + +char MqttServer[kHostnameLength + 1] = "10.0.0.4"; +char MqttPort[kPortLength + 1] = "1883"; +char MqttUsername[kUsernameLength + 1] = ""; +char MqttPassword[kPasswordLength + 1] = ""; +char MqttPrefix[kHostnameLength + 1] = ""; + +String MqttAck; // Sub-topic we send back acknowledgements on. +String MqttSend; // Sub-topic we get new commands from. +String MqttRecv; // Topic we send received IRs to. +String MqttLog; // Topic we send log messages to. +String MqttLwt; // Topic for the Last Will & Testament. +String MqttClimate; // Sub-topic for the climate topics. +String MqttClimateCmnd; // Sub-topic for the climate command topics. +String MqttClimateStat; // Sub-topic for the climate stat topics. +String MqttDiscovery; +String MqttHAName; +String MqttClientId; + +// Primative lock file for gating MQTT state broadcasts. +bool lockMqttBroadcast = true; +TimerMs lastBroadcast = TimerMs(); // When we last sent a broadcast. +bool hasBroadcastBeenSent = false; +TimerMs lastDiscovery = TimerMs(); // When we last sent a Discovery. +bool hasDiscoveryBeenSent = false; +TimerMs statListenTime = TimerMs(); // How long we've been listening for. +#endif // MQTT_ENABLE + +bool isSerialGpioUsedByIr(void) { + const uint8_t kSerialTxGpio = 1; // The GPIO serial output is sent too. + // Note: *DOES NOT* control Serial output. + // Ensure we are not trodding on anything IR related. +#ifdef IR_RX + if (IR_RX == kSerialTxGpio) + return true; // Serial port is in use by IR capture. Abort. +#endif // IR_RX + for (uint8_t i = 0; i < kSendTableSize; i++) + if (gpioTable[i] == kSerialTxGpio) + return true; // Serial port is in use for IR sending. Abort. + return false; // Not in use as far as we can tell. +} + +// Debug messages get sent to the serial port. +void debug(const char *str) { +#if DEBUG + if (isSerialGpioUsedByIr()) return; // Abort. + uint32_t now = millis(); + Serial.printf("%07u.%03u: %s\n", now / 1000, now % 1000, str); +#endif // DEBUG +} + +// callback notifying us of the need to save the wifi config +void saveWifiConfigCallback(void) { + debug("saveWifiConfigCallback called."); + flagSaveWifiConfig = true; +} + +void saveWifiConfig(void) { + debug("Saving the wifi config."); + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); +#if MQTT_ENABLE + json[kMqttServerKey] = MqttServer; + json[kMqttPortKey] = MqttPort; + json[kMqttUserKey] = MqttUsername; + json[kMqttPassKey] = MqttPassword; + json[kMqttPrefixKey] = MqttPrefix; +#endif // MQTT_ENABLE + json[kHostnameKey] = Hostname; + json[kHttpUserKey] = HttpUsername; + json[kHttpPassKey] = HttpPassword; + + if (SPIFFS.begin()) { + File configFile = SPIFFS.open(kConfigFile, "w"); + if (!configFile) { + debug("Failed to open config file for writing."); + } else { + debug("Writing out the config file."); + json.printTo(configFile); + configFile.close(); + debug("Finished writing config file."); + } + SPIFFS.end(); + } +} + +void loadWifiConfigFile(void) { + debug("Trying to mount SPIFFS"); + if (SPIFFS.begin()) { + debug("mounted file system"); + if (SPIFFS.exists(kConfigFile)) { + debug("config file exists"); + + File configFile = SPIFFS.open(kConfigFile, "r"); + if (configFile) { + debug("Opened config file"); + size_t size = configFile.size(); + // Allocate a buffer to store contents of the file. + std::unique_ptr buf(new char[size]); + + configFile.readBytes(buf.get(), size); + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.parseObject(buf.get()); + if (json.success()) { + debug("Json config file parsed ok."); +#if MQTT_ENABLE + strncpy(MqttServer, json[kMqttServerKey] | "", kHostnameLength); + strncpy(MqttPort, json[kMqttPortKey] | "1883", kPortLength); + strncpy(MqttUsername, json[kMqttUserKey] | "", kUsernameLength); + strncpy(MqttPassword, json[kMqttPassKey] | "", kPasswordLength); + strncpy(MqttPrefix, json[kMqttPrefixKey] | "", kHostnameLength); +#endif // MQTT_ENABLE + strncpy(Hostname, json[kHostnameKey] | "", kHostnameLength); + strncpy(HttpUsername, json[kHttpUserKey] | "", kUsernameLength); + strncpy(HttpPassword, json[kHttpPassKey] | "", kPasswordLength); + debug("Recovered Json fields."); + } else { + debug("Failed to load json config"); + } + debug("Closing the config file."); + configFile.close(); + } + } else { + debug("Config file doesn't exist!"); + } + debug("Unmounting SPIFFS."); + SPIFFS.end(); + } else { + debug("Failed to mount SPIFFS"); + } +} + +String msToHumanString(uint32_t const msecs) { + uint32_t totalseconds = msecs / 1000; + if (totalseconds == 0) return "Now"; + + // Note: millis() can only count up to 45 days, so uint8_t is safe. + uint8_t days = totalseconds / (60 * 60 * 24); + uint8_t hours = (totalseconds / (60 * 60)) % 24; + uint8_t minutes = (totalseconds / 60) % 60; + uint8_t seconds = totalseconds % 60; + + String result = ""; + if (days) result += String(days) + " day"; + if (days > 1) result += 's'; + if (hours) result += ' ' + String(hours) + " hour"; + if (hours > 1) result += 's'; + if (minutes) result += ' ' + String(minutes) + " minute"; + if (minutes > 1) result += 's'; + if (seconds) result += ' ' + String(seconds) + " second"; + if (seconds > 1) result += 's'; + result.trim(); + return result; +} + +String timeElapsed(uint32_t const msec) { + String result = msToHumanString(msec); + if (result.equalsIgnoreCase("Now")) + return result; + else + return result + " ago"; +} + +String timeSince(uint32_t const start) { + if (start == 0) + return "Never"; + uint32_t diff = 0; + uint32_t now = millis(); + if (start < now) + diff = now - start; + else + diff = UINT32_MAX - start + now; + return msToHumanString(diff) + " ago"; +} + +// Return a string containing the comma separated list of sending gpios. +String listOfSendGpios(void) { + String result = String(gpioTable[0]); + if (kSendTableSize > 1) result += " (default)"; + for (uint8_t i = 1; i < kSendTableSize; i++) { + result += ", " + String(gpioTable[i]); + } + return result; +} + +String htmlMenu(void) { + return F( + "
" + "" + "" + "" + "" + "" + "
" + "
"); +} + +// Root web page with example usage etc. +void handleRoot(void) { +#if HTML_PASSWORD_ENABLE + if (!server.authenticate(HttpUsername, HttpPassword)) { + debug("Basic HTTP authentication failure for /."); + return server.requestAuthentication(); + } +#endif + String html = F( + "IR MQTT server" + "" + "

ESP8266 IR MQTT Server

" + "
" _MY_VERSION_ "
"); + html += htmlMenu(); + html += F( + "

Send a simple IR message

" + "

" + "Type: " + "" + " Code: 0x" + " Bit size: " + "" + " Repeats: " + " " + "
" + "

" + "

Send a complex (Air Conditioner) IR message

" + "

" + "Type: " + "" + " State code: 0x" + "" + " " + "
" + "

" + "

Send an IRremote Raw IR message

" + "

" + "" + "String: (freq,array data) " + " " + "
" + "

" + "

Send a GlobalCache" + " IR message

" + "

" + "" + "String: 1:1,1," + " " + "
" + "

" + "

Send a Pronto code IR message

" + "

" + "" + "String (comma separated): " + " Repeats: " + " " + "
" + "
"); + server.send(200, "text/html", html); +} + +String addJsReloadUrl(const String url, const uint16_t timeout_s, + const bool notify) { + String html = F( + "\n"); + return html; +} + +// Web page with hardcoded example usage etc. +void handleExamples(void) { +#if HTML_PASSWORD_ENABLE + if (!server.authenticate(HttpUsername, HttpPassword)) { + debug("Basic HTTP authentication failure for /examples."); + return server.requestAuthentication(); + } +#endif + String html = F( + "IR MQTT examples" + "" + "

ESP8266 IR MQTT Server

" + "
" _MY_VERSION_ "
"); + html += htmlMenu(); + html += F( + "

Hardcoded examples

" + "

" + "Sherwood Amp On (GlobalCache)

" + "

" + "Sherwood Amp Off (Raw)

" + "

" + "Sherwood Amp Input TAPE (Pronto)

" + "

TV on (Samsung)

" + "

Power Off (Sony 12bit)

" + "

" + "Panasonic A/C LKE model, On, Auto mode, Min fan, 23C" + " (via HTTP aircon interface)

" + "

" + "Change just the temp to 27C (via HTTP aircon interface)

" + "

" + "Turn OFF the current A/C (via HTTP aircon interface)

" + "

"); + server.send(200, "text/html", html); +} + +String boolToString(const bool value) { + return value ? F("on") : F("off"); +} + + +String opmodeToString(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kOff: + return F("off"); + case stdAc::opmode_t::kAuto: + return F("auto"); + case stdAc::opmode_t::kCool: + return F("cool"); + case stdAc::opmode_t::kHeat: + return F("heat"); + case stdAc::opmode_t::kDry: + return F("dry"); + case stdAc::opmode_t::kFan: + return F("fan_only"); + default: + return F("unknown"); + } +} + +String fanspeedToString(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kAuto: + return F("auto"); + case stdAc::fanspeed_t::kMax: + return F("max"); + case stdAc::fanspeed_t::kHigh: + return F("high"); + case stdAc::fanspeed_t::kMedium: + return F("medium"); + case stdAc::fanspeed_t::kLow: + return F("low"); + case stdAc::fanspeed_t::kMin: + return F("min"); + default: + return F("unknown"); + } +} + +String swingvToString(const stdAc::swingv_t swingv) { + switch (swingv) { + case stdAc::swingv_t::kOff: + return F("off"); + case stdAc::swingv_t::kAuto: + return F("auto"); + case stdAc::swingv_t::kHighest: + return F("highest"); + case stdAc::swingv_t::kHigh: + return F("high"); + case stdAc::swingv_t::kMiddle: + return F("middle"); + case stdAc::swingv_t::kLow: + return F("low"); + case stdAc::swingv_t::kLowest: + return F("lowest"); + default: + return F("unknown"); + } +} + +String swinghToString(const stdAc::swingh_t swingh) { + switch (swingh) { + case stdAc::swingh_t::kOff: + return F("off"); + case stdAc::swingh_t::kAuto: + return F("auto"); + case stdAc::swingh_t::kLeftMax: + return F("leftmax"); + case stdAc::swingh_t::kLeft: + return F("left"); + case stdAc::swingh_t::kMiddle: + return F("middle"); + case stdAc::swingh_t::kRight: + return F("right"); + case stdAc::swingh_t::kRightMax: + return F("rightmax"); + default: + return F("unknown"); + } +} + +String htmlSelectBool(const String name, const bool def) { + String html = ""); + return html; +} + +String htmlSelectProtocol(const String name, const decode_type_t def) { + String html = ""); + return html; +} + +String htmlSelectModel(const String name, const int16_t def) { + String html = ""); + return html; +} + +String htmlSelectMode(const String name, const stdAc::opmode_t def) { + String html = ""); + return html; +} + +String htmlSelectFanspeed(const String name, const stdAc::fanspeed_t def) { + String html = ""); + return html; +} + +String htmlSelectSwingv(const String name, const stdAc::swingv_t def) { + String html = ""); + return html; +} + +String htmlSelectSwingh(const String name, const stdAc::swingh_t def) { + String html = ""); + return html; +} + +// Admin web page +void handleAirCon(void) { + String html = F( + "AirCon control" + "" + "

Air Conditioner Control

"); + html += htmlMenu(); + html += "

Current Settings

" + "
" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
Protocol" + + htmlSelectProtocol(KEY_PROTOCOL, climate.protocol) + "
Model" + htmlSelectModel(KEY_MODEL, climate.model) + + "
Power" + htmlSelectBool(KEY_POWER, climate.power) + + "
Mode" + htmlSelectMode(KEY_MODE, climate.mode) + + "
Temp" + "" + "
Fan Speed" + + htmlSelectFanspeed(KEY_FANSPEED, climate.fanspeed) + "
Swing (V)" + + htmlSelectSwingv(KEY_SWINGV, climate.swingv) + "
Swing (H)" + + htmlSelectSwingh(KEY_SWINGH, climate.swingh) + "
Quiet" + htmlSelectBool(KEY_QUIET, climate.quiet) + + "
Turbo" + htmlSelectBool(KEY_TURBO, climate.turbo) + + "
Econo" + htmlSelectBool(KEY_ECONO, climate.econo) + + "
Light" + htmlSelectBool(KEY_LIGHT, climate.light) + + "
Filter" + htmlSelectBool(KEY_FILTER, climate.filter) + + "
Clean" + htmlSelectBool(KEY_CLEAN, climate.clean) + + "
Beep" + htmlSelectBool(KEY_BEEP, climate.beep) + + "
" + "" + "
"; + // Display the current settings. + html += F(""); + server.send(200, "text/html", html); +} + +// Parse the URL args to find the Common A/C arguments. +void handleAirConSet(void) { +#if HTML_PASSWORD_ENABLE + if (!server.authenticate(HttpUsername, HttpPassword)) { + debug("Basic HTTP authentication failure for /aircon/set."); + return server.requestAuthentication(); + } +#endif + commonAcState_t result = climate; + debug("New common a/c received via HTTP"); + for (uint16_t i = 0; i < server.args(); i++) + result = updateClimate(result, server.argName(i), "", server.arg(i)); + +#if MQTT_ENABLE + sendClimate(climate, result, MqttClimateStat, + true, false, false); +#else // MQTT_ENABLE + sendClimate(climate, result, "", false, false, false); +#endif // MQTT_ENABLE + // Update the old climate state with the new one. + climate = result; + // Redirect back to the aircon page. + String html = F( + "Update Aircon" + "" + "

Aircon updated!

"); + html += addJsReloadUrl("/aircon", 2, false); + html += F(""); + server.send(200, "text/html", html); +} + +// Admin web page +void handleAdmin(void) { + String html = F( + "IR MQTT server admin" + "" + "

Administration

"); + html += htmlMenu(); + html += F( + "

Special commands

" +#if MQTT_ENABLE + " " + "Send a Climate MQTT discovery message to Home Assistant.

" +#endif // MQTT_ENABLE + " A simple reboot of the ESP8266. " + "ie. No changes

" + " Warning: " + "Resets the device back to original settings. " + "ie. Goes back to AP/Setup mode.
"); +#if FIRMWARE_OTA + html += F("

Update firmware

" + "Warning:
"); + if (!strlen(HttpPassword)) // Deny if password not set + html += F("OTA firmware is disabled until you set a password. " + "You will need to wipe & reset to set one." + "

"); + else // default password has been changed, so allow it. + html += F( + "Updating your firmware may screw up your access to the device. " + "If you are going to use this, know what you are doing first " + "(and you probably do).
" + "

" + "Firmware to upload: " + "" + "
"); +#endif // FIRMWARE_OTA + html += F(""); + server.send(200, "text/html", html); +} + +// Info web page +void handleInfo(void) { + String html = + "IR MQTT server info" + "" + "

Information

"; + html += htmlMenu(); + html += + "

General

" + "

Hostname: " + String(Hostname) + "
" + "IP address: " + WiFi.localIP().toString() + "
" + "Booted: " + timeSince(1) + "
" + + "Version: " _MY_VERSION_ "
" + "Built: " __DATE__ + " " __TIME__ "
" + "Period Offset: " + String(offset) + "us
" + "IR Lib Version: " _IRREMOTEESP8266_VERSION_ "
" + "ESP8266 Core Version: " + ESP.getCoreVersion() + "
" + "IR Send GPIO(s): " + listOfSendGpios() + "
" + "Total send requests: " + String(sendReqCounter) + "
" + "Last message sent: " + String(lastSendSucceeded ? "Ok" : "FAILED") + + " (" + timeSince(lastSendTime) + ")
" +#ifdef IR_RX + "IR Recv GPIO: " + String(IR_RX) + +#if IR_RX_PULLUP + " (pullup)" +#endif // IR_RX_PULLUP + "
" + "Total IR Received: " + String(irRecvCounter) + "
" + "Last IR Received: " + lastIrReceived + + " (" + timeSince(lastIrReceivedTime) + ")
" +#endif // IR_RX + "Duplicate Wifi networks: " + + String(HIDE_DUPLIATE_NETWORKS ? "Hide" : "Show") + "
" + "Min Wifi signal required: " +#ifdef MIN_SIGNAL_STRENGTH + + String(static_cast(MIN_SIGNAL_STRENGTH)) + +#else // MIN_SIGNAL_STRENGTH + "8" +#endif // MIN_SIGNAL_STRENGTH + "%
" + "Serial debugging: " +#if DEBUG + + String(isSerialGpioUsedByIr() ? "Off" : "On") + +#else // DEBUG + "Off" +#endif // DEBUG + "
" + "

" +#if MQTT_ENABLE + "

MQTT Information

" + "

Server: " + String(MqttServer) + ":" + String(MqttPort) + " (" + + (mqtt_client.connected() ? "Connected " + timeSince(lastDisconnectedTime) + : "Disconnected " + timeSince(lastConnectedTime)) + + ")
" + "Disconnections: " + String(mqttDisconnectCounter - 1) + "
" + "Client id: " + MqttClientId + "
" + "Command topic(s): " + listOfCommandTopics() + "
" + "Acknowledgements topic: " + MqttAck + "
" +#ifdef IR_RX + "IR Received topic: " + MqttRecv + "
" +#endif // IR_RX + "Log topic: " + MqttLog + "
" + "LWT topic: " + MqttLwt + "
" + "QoS: " + String(QOS) + "
" + // lastMqttCmd* is unescaped untrusted input. + // Avoid any possible HTML/XSS when displaying it. + "Last MQTT command seen: (topic) '" + htmlEscape(lastMqttCmdTopic) + + "' (payload) '" + htmlEscape(lastMqttCmd) + "' (" + + timeSince(lastMqttCmdTime) + ")
" + "Total published: " + String(mqttSentCounter) + "
" + "Total received: " + String(mqttRecvCounter) + "
" + "

" +#endif // MQTT_ENABLE + "

Climate Information

" + "

" + "IR Send GPIO: " + String(gpioTable[0]) + "
" + "Total sent: " + String(irClimateCounter) + "
" + "Last send: " + String(hasClimateBeenSent ? + (String(lastClimateSucceeded ? "Ok" : "FAILED") + + " (" + timeElapsed(lastClimateIr.elapsed()) + ")") : + "Never") + "
" +#if MQTT_ENABLE + "State listen period: " + msToHumanString(kStatListenPeriodMs) + "
" + "State broadcast period: " + msToHumanString(kBroadcastPeriodMs) + "
" + "Last state broadcast: " + (hasBroadcastBeenSent ? + timeElapsed(lastBroadcast.elapsed()) : + String("Never")) + "
" + "Last discovery sent: " + (lockMqttBroadcast ? + String("Locked") : + (hasDiscoveryBeenSent ? + timeElapsed(lastDiscovery.elapsed()) : + String("Never"))) + + "
" + "Command topics: " + MqttClimateCmnd + + "(" KEY_PROTOCOL "|" KEY_MODEL "|" KEY_POWER "|" KEY_MODE "|" KEY_TEMP "|" + KEY_FANSPEED "|" KEY_SWINGV "|" KEY_SWINGH "|" KEY_QUIET "|" + KEY_TURBO "|" KEY_LIGHT "|" KEY_BEEP "|" KEY_ECONO "|" KEY_SLEEP "|" + KEY_CLOCK "|" KEY_FILTER "|" KEY_CLEAN "|" KEY_CELSIUS ")
" + "State topics: " + MqttClimateStat + + "(" KEY_PROTOCOL "|" KEY_MODEL "|" KEY_POWER "|" KEY_MODE "|" KEY_TEMP "|" + KEY_FANSPEED "|" KEY_SWINGV "|" KEY_SWINGH "|" KEY_QUIET "|" + KEY_TURBO "|" KEY_LIGHT "|" KEY_BEEP "|" KEY_ECONO "|" KEY_SLEEP "|" + KEY_CLOCK "|" KEY_FILTER "|" KEY_CLEAN "|" KEY_CELSIUS ")
" +#endif // MQTT_ENABLE + "

" + // Page footer + "

" + "(Note: Page will refresh every 60 seconds.)" + "

"; + html += addJsReloadUrl("/info", 60, false); + html += ""; + server.send(200, "text/html", html); +} +// Reset web page +void handleReset(void) { +#if HTML_PASSWORD_ENABLE + if (!server.authenticate(HttpUsername, HttpPassword)) { + debug("Basic HTTP authentication failure for /reset."); + return server.requestAuthentication(); + } +#endif + server.send(200, "text/html", + "Reset WiFi Config" + "" + "

Resetting the WiFiManager config back to defaults.

" + "

Device restarting. Try connecting in a few seconds.

" + + addJsReloadUrl("/", 10, true) + + ""); + // Do the reset. +#if MQTT_ENABLE + mqttLog("Wiping all saved config settings."); +#endif // MQTT_ENABLE + debug("Trying to mount SPIFFS"); + if (SPIFFS.begin()) { + debug("Removing JSON config file"); + SPIFFS.remove(kConfigFile); + SPIFFS.end(); + } + delay(1000); + debug("Reseting wifiManager's settings."); + wifiManager.resetSettings(); + delay(1000); + debug("rebooting..."); + ESP.restart(); + delay(1000); +} + +// Reboot web page +void handleReboot() { +#if HTML_PASSWORD_ENABLE + if (!server.authenticate(HttpUsername, HttpPassword)) { + debug("Basic HTTP authentication failure for /quitquitquit."); + return server.requestAuthentication(); + } +#endif + server.send(200, "text/html", + "Rebooting" + "" + "

Device restarting.

" + "

Try connecting in a few seconds.

" + + addJsReloadUrl("/", 15, true) + + ""); +#if MQTT_ENABLE + mqttLog("Reboot requested"); +#endif // MQTT_ENABLE + // Do the reset. + delay(1000); + ESP.restart(); + delay(1000); +} + +// Parse an Air Conditioner A/C Hex String/code and send it. +// Args: +// irsend: A Ptr to the IRsend object to transmit via. +// irType: Nr. of the protocol we need to send. +// str: A hexadecimal string containing the state to be sent. +// Returns: +// bool: Successfully sent or not. +bool parseStringAndSendAirCon(IRsend *irsend, const uint16_t irType, + const String str) { + uint8_t strOffset = 0; + uint8_t state[kStateSizeMax] = {0}; // All array elements are set to 0. + uint16_t stateSize = 0; + + if (str.startsWith("0x") || str.startsWith("0X")) + strOffset = 2; + // Calculate how many hexadecimal characters there are. + uint16_t inputLength = str.length() - strOffset; + if (inputLength == 0) { + debug("Zero length AirCon code encountered. Ignored."); + return false; // No input. Abort. + } + + switch (irType) { // Get the correct state size for the protocol. + case KELVINATOR: + stateSize = kKelvinatorStateLength; + break; + case TOSHIBA_AC: + stateSize = kToshibaACStateLength; + break; + case DAIKIN: + // Daikin has 2 different possible size states. + // (The correct size, and a legacy shorter size.) + // Guess which one we are being presented with based on the number of + // hexadecimal digits provided. i.e. Zero-pad if you need to to get + // the correct length/byte size. + // This should provide backward compatiblity with legacy messages. + stateSize = inputLength / 2; // Every two hex chars is a byte. + // Use at least the minimum size. + stateSize = std::max(stateSize, kDaikinStateLengthShort); + // If we think it isn't a "short" message. + if (stateSize > kDaikinStateLengthShort) + // Then it has to be at least the version of the "normal" size. + stateSize = std::max(stateSize, kDaikinStateLength); + // Lastly, it should never exceed the "normal" size. + stateSize = std::min(stateSize, kDaikinStateLength); + break; + case DAIKIN2: + stateSize = kDaikin2StateLength; + break; + case DAIKIN216: + stateSize = kDaikin216StateLength; + break; + case ELECTRA_AC: + stateSize = kElectraAcStateLength; + break; + case MITSUBISHI_AC: + stateSize = kMitsubishiACStateLength; + break; + case MITSUBISHI_HEAVY_88: + stateSize = kMitsubishiHeavy88StateLength; + break; + case MITSUBISHI_HEAVY_152: + stateSize = kMitsubishiHeavy152StateLength; + break; + case PANASONIC_AC: + stateSize = kPanasonicAcStateLength; + break; + case TROTEC: + stateSize = kTrotecStateLength; + break; + case ARGO: + stateSize = kArgoStateLength; + break; + case GREE: + stateSize = kGreeStateLength; + break; + case FUJITSU_AC: + // Fujitsu has four distinct & different size states, so make a best guess + // which one we are being presented with based on the number of + // hexadecimal digits provided. i.e. Zero-pad if you need to to get + // the correct length/byte size. + stateSize = inputLength / 2; // Every two hex chars is a byte. + // Use at least the minimum size. + stateSize = std::max(stateSize, + (uint16_t) (kFujitsuAcStateLengthShort - 1)); + // If we think it isn't a "short" message. + if (stateSize > kFujitsuAcStateLengthShort) + // Then it has to be at least the smaller version of the "normal" size. + stateSize = std::max(stateSize, (uint16_t) (kFujitsuAcStateLength - 1)); + // Lastly, it should never exceed the maximum "normal" size. + stateSize = std::min(stateSize, kFujitsuAcStateLength); + break; + case HAIER_AC: + stateSize = kHaierACStateLength; + break; + case HAIER_AC_YRW02: + stateSize = kHaierACYRW02StateLength; + break; + case HITACHI_AC: + stateSize = kHitachiAcStateLength; + break; + case HITACHI_AC1: + stateSize = kHitachiAc1StateLength; + break; + case HITACHI_AC2: + stateSize = kHitachiAc2StateLength; + break; + case WHIRLPOOL_AC: + stateSize = kWhirlpoolAcStateLength; + break; + case SAMSUNG_AC: + // Samsung has two distinct & different size states, so make a best guess + // which one we are being presented with based on the number of + // hexadecimal digits provided. i.e. Zero-pad if you need to to get + // the correct length/byte size. + stateSize = inputLength / 2; // Every two hex chars is a byte. + // Use at least the minimum size. + stateSize = std::max(stateSize, (uint16_t) (kSamsungAcStateLength)); + // If we think it isn't a "normal" message. + if (stateSize > kSamsungAcStateLength) + // Then it probably the extended size. + stateSize = std::max(stateSize, + (uint16_t) (kSamsungAcExtendedStateLength)); + // Lastly, it should never exceed the maximum "extended" size. + stateSize = std::min(stateSize, kSamsungAcExtendedStateLength); + break; + case MWM: + // MWM has variable size states, so make a best guess + // which one we are being presented with based on the number of + // hexadecimal digits provided. i.e. Zero-pad if you need to to get + // the correct length/byte size. + stateSize = inputLength / 2; // Every two hex chars is a byte. + // Use at least the minimum size. + stateSize = std::max(stateSize, (uint16_t) 3); + // Cap the maximum size. + stateSize = std::min(stateSize, kStateSizeMax); + break; + case TCL112AC: + stateSize = kTcl112AcStateLength; + break; + default: // Not a protocol we expected. Abort. + debug("Unexpected AirCon protocol detected. Ignoring."); + return false; + } + if (inputLength > stateSize * 2) { + debug("AirCon code to large for the given protocol."); + return false; + } + + // Ptr to the least significant byte of the resulting state for this protocol. + uint8_t *statePtr = &state[stateSize - 1]; + + // Convert the string into a state array of the correct length. + for (uint16_t i = 0; i < inputLength; i++) { + // Grab the next least sigificant hexadecimal digit from the string. + uint8_t c = tolower(str[inputLength + strOffset - i - 1]); + if (isxdigit(c)) { + if (isdigit(c)) + c -= '0'; + else + c = c - 'a' + 10; + } else { + debug("Aborting! Non-hexadecimal char found in AirCon state:"); + debug(str.c_str()); + return false; + } + if (i % 2 == 1) { // Odd: Upper half of the byte. + *statePtr += (c << 4); + statePtr--; // Advance up to the next least significant byte of state. + } else { // Even: Lower half of the byte. + *statePtr = c; + } + } + + // Make the appropriate call for the protocol type. + switch (irType) { +#if SEND_KELVINATOR + case KELVINATOR: + irsend->sendKelvinator(reinterpret_cast(state)); + break; +#endif +#if SEND_TOSHIBA_AC + case TOSHIBA_AC: + irsend->sendToshibaAC(reinterpret_cast(state)); + break; +#endif +#if SEND_DAIKIN + case DAIKIN: + irsend->sendDaikin(reinterpret_cast(state)); + break; +#endif +#if SEND_DAIKIN2 + case DAIKIN2: + irsend->sendDaikin2(reinterpret_cast(state)); + break; +#endif +#if SEND_DAIKIN216 + case DAIKIN216: + irsend->sendDaikin216(reinterpret_cast(state)); + break; +#endif // SEND_DAIKIN216 +#if SEND_MITSUBISHI_AC + case MITSUBISHI_AC: + irsend->sendMitsubishiAC(reinterpret_cast(state)); + break; +#endif +#if SEND_MITSUBISHIHEAVY + case MITSUBISHI_HEAVY_88: // 59 + irsend->sendMitsubishiHeavy88(reinterpret_cast(state)); + break; + case MITSUBISHI_HEAVY_152: // 60 + irsend->sendMitsubishiHeavy152(reinterpret_cast(state)); + break; +#endif // SEND_MITSUBISHIHEAVY +#if SEND_TROTEC + case TROTEC: + irsend->sendTrotec(reinterpret_cast(state)); + break; +#endif +#if SEND_ARGO + case ARGO: + irsend->sendArgo(reinterpret_cast(state)); + break; +#endif +#if SEND_GREE + case GREE: + irsend->sendGree(reinterpret_cast(state)); + break; +#endif +#if SEND_FUJITSU_AC + case FUJITSU_AC: + irsend->sendFujitsuAC(reinterpret_cast(state), stateSize); + break; +#endif +#if SEND_HAIER_AC + case HAIER_AC: + irsend->sendHaierAC(reinterpret_cast(state)); + break; +#endif +#if SEND_HAIER_AC_YRW02 + case HAIER_AC_YRW02: + irsend->sendHaierACYRW02(reinterpret_cast(state)); + break; +#endif +#if SEND_HITACHI_AC + case HITACHI_AC: + irsend->sendHitachiAC(reinterpret_cast(state)); + break; +#endif +#if SEND_HITACHI_AC1 + case HITACHI_AC1: + irsend->sendHitachiAC1(reinterpret_cast(state)); + break; +#endif +#if SEND_HITACHI_AC2 + case HITACHI_AC2: + irsend->sendHitachiAC2(reinterpret_cast(state)); + break; +#endif +#if SEND_WHIRLPOOL_AC + case WHIRLPOOL_AC: + irsend->sendWhirlpoolAC(reinterpret_cast(state)); + break; +#endif +#if SEND_SAMSUNG_AC + case SAMSUNG_AC: + irsend->sendSamsungAC(reinterpret_cast(state), stateSize); + break; +#endif +#if SEND_ELECTRA_AC + case ELECTRA_AC: + irsend->sendElectraAC(reinterpret_cast(state)); + break; +#endif +#if SEND_PANASONIC_AC + case PANASONIC_AC: + irsend->sendPanasonicAC(reinterpret_cast(state)); + break; +#endif +#if SEND_MWM + case MWM: + irsend->sendMWM(reinterpret_cast(state), stateSize); + break; +#endif +#if SEND_TCL112AC + case TCL112AC: + irsend->sendTcl112Ac(reinterpret_cast(state)); + break; +#endif + default: + debug("Unexpected AirCon type in send request. Not sent."); + return false; + } + return true; // We were successful as far as we can tell. +} + +// Count how many values are in the String. +// Args: +// str: String containing the values. +// sep: Character that separates the values. +// Returns: +// The number of values found in the String. +uint16_t countValuesInStr(const String str, char sep) { + int16_t index = -1; + uint16_t count = 1; + do { + index = str.indexOf(sep, index + 1); + count++; + } while (index != -1); + return count; +} + +// Dynamically allocate an array of uint16_t's. +// Args: +// size: Nr. of uint16_t's need to be in the new array. +// Returns: +// A Ptr to the new array. Restarts the ESP8266 if it fails. +uint16_t * newCodeArray(const uint16_t size) { + uint16_t *result; + + result = reinterpret_cast(malloc(size * sizeof(uint16_t))); + // Check we malloc'ed successfully. + if (result == NULL) { // malloc failed, so give up. + Serial.printf("\nCan't allocate %d bytes. (%d bytes free)\n", + size * sizeof(uint16_t), ESP.getFreeHeap()); + Serial.println("Giving up & forcing a reboot."); + ESP.restart(); // Reboot. + delay(500); // Wait for the restart to happen. + return result; // Should never get here, but just in case. + } + return result; +} + +#if SEND_GLOBALCACHE +// Parse a GlobalCache String/code and send it. +// Args: +// irsend: A ptr to the IRsend object to transmit via. +// str: A GlobalCache formatted String of comma separated numbers. +// e.g. "38000,1,1,170,170,20,63,20,63,20,63,20,20,20,20,20,20,20,20,20, +// 20,20,63,20,63,20,63,20,20,20,20,20,20,20,20,20,20,20,20,20,63, +// 20,20,20,20,20,20,20,20,20,20,20,20,20,63,20,20,20,63,20,63,20, +// 63,20,63,20,63,20,63,20,1798" +// Note: The leading "1:1,1," of normal GC codes should be removed. +// Returns: +// bool: Successfully sent or not. +bool parseStringAndSendGC(IRsend *irsend, const String str) { + uint16_t count; + uint16_t *code_array; + String tmp_str; + + // Remove the leading "1:1,1," if present. + if (str.startsWith("1:1,1,")) + tmp_str = str.substring(6); + else + tmp_str = str; + + // Find out how many items there are in the string. + count = countValuesInStr(tmp_str, ','); + + // Now we know how many there are, allocate the memory to store them all. + code_array = newCodeArray(count); + + // Now convert the strings to integers and place them in code_array. + count = 0; + uint16_t start_from = 0; + int16_t index = -1; + do { + index = tmp_str.indexOf(',', start_from); + code_array[count] = tmp_str.substring(start_from, index).toInt(); + start_from = index + 1; + count++; + } while (index != -1); + + irsend->sendGC(code_array, count); // All done. Send it. + free(code_array); // Free up the memory allocated. + if (count > 0) + return true; // We sent something. + return false; // We probably didn't. +} +#endif // SEND_GLOBALCACHE + +#if SEND_PRONTO +// Parse a Pronto Hex String/code and send it. +// Args: +// irsend: A ptr to the IRsend object to transmit via. +// str: A comma-separated String of nr. of repeats, then hexadecimal numbers. +// e.g. "R1,0000,0067,0000,0015,0060,0018,0018,0018,0030,0018,0030,0018, +// 0030,0018,0018,0018,0030,0018,0018,0018,0018,0018,0030,0018, +// 0018,0018,0030,0018,0030,0018,0030,0018,0018,0018,0018,0018, +// 0030,0018,0018,0018,0018,0018,0030,0018,0018,03f6" +// or +// "0000,0067,0000,0015,0060,0018". i.e. without the Repeat value +// Requires at least kProntoMinLength comma-separated values. +// sendPronto() only supports raw pronto code types, thus so does this. +// repeats: Nr. of times the message is to be repeated. +// This value is ignored if an embeddd repeat is found in str. +// Returns: +// bool: Successfully sent or not. +bool parseStringAndSendPronto(IRsend *irsend, const String str, + uint16_t repeats) { + uint16_t count; + uint16_t *code_array; + int16_t index = -1; + uint16_t start_from = 0; + + // Find out how many items there are in the string. + count = countValuesInStr(str, ','); + + // Check if we have the optional embedded repeats value in the code string. + if (str.startsWith("R") || str.startsWith("r")) { + // Grab the first value from the string, as it is the nr. of repeats. + index = str.indexOf(',', start_from); + repeats = str.substring(start_from + 1, index).toInt(); // Skip the 'R'. + start_from = index + 1; + count--; // We don't count the repeats value as part of the code array. + } + + // We need at least kProntoMinLength values for the code part. + if (count < kProntoMinLength) return false; + + // Now we know how many there are, allocate the memory to store them all. + code_array = newCodeArray(count); + + // Rest of the string are values for the code array. + // Now convert the hex strings to integers and place them in code_array. + count = 0; + do { + index = str.indexOf(',', start_from); + // Convert the hexadecimal value string to an unsigned integer. + code_array[count] = strtoul(str.substring(start_from, index).c_str(), + NULL, 16); + start_from = index + 1; + count++; + } while (index != -1); + + irsend->sendPronto(code_array, count, repeats); // All done. Send it. + free(code_array); // Free up the memory allocated. + if (count > 0) + return true; // We sent something. + return false; // We probably didn't. +} +#endif // SEND_PRONTO + +#if SEND_RAW +// Parse an IRremote Raw Hex String/code and send it. +// Args: +// irsend: A ptr to the IRsend object to transmit via. +// str: A comma-separated String containing the freq and raw IR data. +// e.g. "38000,9000,4500,600,1450,600,900,650,1500,..." +// Requires at least two comma-separated values. +// First value is the transmission frequency in Hz or kHz. +// Returns: +// bool: Successfully sent or not. +bool parseStringAndSendRaw(IRsend *irsend, const String str) { + uint16_t count; + uint16_t freq = 38000; // Default to 38kHz. + uint16_t *raw_array; + + // Find out how many items there are in the string. + count = countValuesInStr(str, ','); + + // We expect the frequency as the first comma separated value, so we need at + // least two values. If not, bail out. + if (count < 2) return false; + count--; // We don't count the frequency value as part of the raw array. + + // Now we know how many there are, allocate the memory to store them all. + raw_array = newCodeArray(count); + + // Grab the first value from the string, as it is the frequency. + int16_t index = str.indexOf(',', 0); + freq = str.substring(0, index).toInt(); + uint16_t start_from = index + 1; + // Rest of the string are values for the raw array. + // Now convert the strings to integers and place them in raw_array. + count = 0; + do { + index = str.indexOf(',', start_from); + raw_array[count] = str.substring(start_from, index).toInt(); + start_from = index + 1; + count++; + } while (index != -1); + + irsend->sendRaw(raw_array, count, freq); // All done. Send it. + free(raw_array); // Free up the memory allocated. + if (count > 0) + return true; // We sent something. + return false; // We probably didn't. +} +#endif // SEND_RAW + +// Parse the URL args to find the IR code. +void handleIr(void) { +#if HTML_PASSWORD_ENABLE + if (!server.authenticate(HttpUsername, HttpPassword)) { + debug("Basic HTTP authentication failure for /ir."); + return server.requestAuthentication(); + } +#endif + uint64_t data = 0; + String data_str = ""; + int16_t ir_type = decode_type_t::NEC; // Default to NEC codes. + uint16_t nbits = 0; + uint16_t repeat = 0; + + for (uint16_t i = 0; i < server.args(); i++) { + if (server.argName(i).equals(KEY_TYPE) || + server.argName(i).equals(KEY_PROTOCOL)) { + ir_type = strToDecodeType(server.arg(i).c_str()); + } else if (server.argName(i).equals(KEY_CODE)) { + data = getUInt64fromHex(server.arg(i).c_str()); + data_str = server.arg(i); + } else if (server.argName(i).equals(KEY_BITS)) { + nbits = server.arg(i).toInt(); + } else if (server.argName(i).equals(KEY_REPEAT)) { + repeat = server.arg(i).toInt(); + } + } + debug("New code received via HTTP"); + lastSendSucceeded = sendIRCode(IrSendTable[0], ir_type, data, + data_str.c_str(), nbits, repeat); + String html = F( + "Send IR command" + "" + "

IR command sent!

"); + html += addJsReloadUrl("/", 2, true); + html += F(""); + server.send(200, "text/html", html); +} + +void handleNotFound(void) { + String message = "File Not Found\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET)?"GET":"POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + for (uint8_t i=0; i < server.args(); i++) + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + server.send(404, "text/plain", message); +} + +void setup_wifi(void) { + delay(10); + loadWifiConfigFile(); + // We start by connecting to a WiFi network + wifiManager.setTimeout(300); // Time out after 5 mins. + // Set up additional parameters for WiFiManager config menu page. + wifiManager.setSaveConfigCallback(saveWifiConfigCallback); + WiFiManagerParameter custom_hostname_text( + "
Hostname
"); + wifiManager.addParameter(&custom_hostname_text); + WiFiManagerParameter custom_hostname( + kHostnameKey, kHostnameKey, Hostname, kHostnameLength); + wifiManager.addParameter(&custom_hostname); + WiFiManagerParameter custom_authentication_text( + "

Web/OTA authentication
"); + wifiManager.addParameter(&custom_authentication_text); + WiFiManagerParameter custom_http_username( + kHttpUserKey, "username", HttpUsername, kUsernameLength); + wifiManager.addParameter(&custom_http_username); + WiFiManagerParameter custom_http_password( + kHttpPassKey, "password (No OTA if blank)", HttpPassword, kPasswordLength, + " type='password'"); + wifiManager.addParameter(&custom_http_password); +#if MQTT_ENABLE + WiFiManagerParameter custom_mqtt_text( + "

MQTT Broker details
"); + wifiManager.addParameter(&custom_mqtt_text); + WiFiManagerParameter custom_mqtt_server( + kMqttServerKey, "mqtt server", MqttServer, kHostnameLength); + wifiManager.addParameter(&custom_mqtt_server); + WiFiManagerParameter custom_mqtt_port( + kMqttPortKey, "mqtt port", MqttPort, kPortLength, + " input type='number' min='1' max='65535'"); + wifiManager.addParameter(&custom_mqtt_port); + WiFiManagerParameter custom_mqtt_user( + kMqttUserKey, "mqtt username", MqttUsername, kUsernameLength); + wifiManager.addParameter(&custom_mqtt_user); + WiFiManagerParameter custom_mqtt_pass( + kMqttPassKey, "mqtt password", MqttPassword, kPasswordLength, + " type='password'"); + wifiManager.addParameter(&custom_mqtt_pass); + WiFiManagerParameter custom_prefix_text( + "

MQTT Prefix
"); + wifiManager.addParameter(&custom_prefix_text); + WiFiManagerParameter custom_mqtt_prefix( + kMqttPrefixKey, "Leave empty to use Hostname", MqttPrefix, + kHostnameLength); + wifiManager.addParameter(&custom_mqtt_prefix); + #endif // MQTT_ENABLE +#if USE_STATIC_IP + // Use a static IP config rather than the one supplied via DHCP. + wifiManager.setSTAStaticIPConfig(kIPAddress, kGateway, kSubnetMask); +#endif // USE_STATIC_IP +#if MIN_SIGNAL_STRENGTH + wifiManager.setMinimumSignalQuality(MIN_SIGNAL_STRENGTH); +#endif // MIN_SIGNAL_STRENGTH + wifiManager.setRemoveDuplicateAPs(HIDE_DUPLIATE_NETWORKS); + + if (!wifiManager.autoConnect()) { + debug("Wifi failed to connect and hit timeout. Rebooting..."); + delay(3000); + // Reboot. A.k.a. "Have you tried turning it Off and On again?" + ESP.reset(); + delay(5000); + } + +#if MQTT_ENABLE + strncpy(MqttServer, custom_mqtt_server.getValue(), kHostnameLength); + strncpy(MqttPort, custom_mqtt_port.getValue(), kPortLength); + strncpy(MqttUsername, custom_mqtt_user.getValue(), kUsernameLength); + strncpy(MqttPassword, custom_mqtt_pass.getValue(), kPasswordLength); + strncpy(MqttPrefix, custom_mqtt_prefix.getValue(), kHostnameLength); +#endif // MQTT_ENABLE + strncpy(Hostname, custom_hostname.getValue(), kHostnameLength); + strncpy(HttpUsername, custom_http_username.getValue(), kUsernameLength); + strncpy(HttpPassword, custom_http_password.getValue(), kPasswordLength); + if (flagSaveWifiConfig) { + saveWifiConfig(); + } + debug("WiFi connected. IP address:"); + debug(WiFi.localIP().toString().c_str()); +} + +void init_vars(void) { +#if MQTT_ENABLE + // If we have a prefix already, use it. Otherwise use the hostname. + if (!strlen(MqttPrefix)) strncpy(MqttPrefix, Hostname, kHostnameLength); + // Topic we send back acknowledgements on. + MqttAck = String(MqttPrefix) + '/' + MQTT_ACK; + // Sub-topic we get new commands from. + MqttSend = String(MqttPrefix) + '/' + MQTT_SEND; + // Topic we send received IRs to. + MqttRecv = String(MqttPrefix) + '/' + MQTT_RECV; + // Topic we send log messages to. + MqttLog = String(MqttPrefix) + '/' + MQTT_LOG; + // Topic for the Last Will & Testament. + MqttLwt = String(MqttPrefix) + '/' + MQTT_LWT; + // Sub-topic for the climate topics. + MqttClimate = String(MqttPrefix) + '/' + MQTT_CLIMATE; + // Sub-topic for the climate command topics. + MqttClimateCmnd = MqttClimate + '/' + MQTT_CLIMATE_CMND + '/'; + // Sub-topic for the climate stat topics. + MqttClimateStat = MqttClimate + '/' + MQTT_CLIMATE_STAT + '/'; + MqttDiscovery = "homeassistant/climate/" + String(Hostname) + "/config"; + MqttHAName = String(Hostname) + "_aircon"; + // Create a unique MQTT client id. + MqttClientId = String(Hostname) + String(ESP.getChipId(), HEX); +#endif // MQTT_ENABLE +} + +void setup(void) { + // Set the default climate settings. + climate.protocol = decode_type_t::UNKNOWN; + climate.model = -1; // Unknown. + climate.power = false; + climate.mode = stdAc::opmode_t::kAuto; + climate.celsius = true; + climate.degrees = 25; // 25C + climate.fanspeed = stdAc::fanspeed_t::kAuto; + climate.swingv = stdAc::swingv_t::kAuto; + climate.swingh = stdAc::swingh_t::kAuto; + climate.quiet = false; + climate.turbo = false; + climate.econo = false; + climate.light = false; + climate.filter = false; + climate.clean = false; + climate.beep = false; + climate.sleep = -1; // Off + climate.clock = -1; // Don't set. + climate_prev = climate; + + // Initialise all the IR transmitters. + for (uint8_t i = 0; i < kSendTableSize; i++) { + IrSendTable[i] = new IRsend(gpioTable[i]); + IrSendTable[i]->begin(); + offset = IrSendTable[i]->calibrate(); + } +#ifdef IR_RX +#if IR_RX_PULLUP + pinMode(IR_RX, INPUT_PULLUP); +#endif // IR_RX_PULLUP +#if DECODE_HASH + // Ignore messages with less than minimum on or off pulses. + irrecv.setUnknownThreshold(kMinUnknownSize); +#endif // DECODE_HASH + irrecv.enableIRIn(); // Start the receiver +#endif // IR_RX + +#if DEBUG + if (!isSerialGpioUsedByIr()) { + // Use SERIAL_TX_ONLY so that the RX pin can be freed up for GPIO/IR use. + Serial.begin(BAUD_RATE, SERIAL_8N1, SERIAL_TX_ONLY); + while (!Serial) // Wait for the serial connection to be establised. + delay(50); + Serial.println(); + debug("IRMQTTServer " _MY_VERSION_" has booted."); + } +#endif // DEBUG + + setup_wifi(); + + // Wait a bit for things to settle. + delay(500); + + lastReconnectAttempt = 0; + + if (mdns.begin(Hostname, WiFi.localIP())) { + debug("MDNS responder started"); + } + + // Setup the root web page. + server.on("/", handleRoot); + // Setup the examples web page. + server.on("/examples", handleExamples); + // Setup the page to handle web-based IR codes. + server.on("/ir", handleIr); + // Setup the aircon page. + server.on("/aircon", handleAirCon); + // Setup the aircon update page. + server.on("/aircon/set", handleAirConSet); + // Setup the info page. + server.on("/info", handleInfo); + // Setup the admin page. + server.on("/admin", handleAdmin); + // Setup a reset page to cause WiFiManager information to be reset. + server.on("/reset", handleReset); + // Reboot url + server.on("/quitquitquit", handleReboot); +#if MQTT_ENABLE + // MQTT Discovery url + server.on("/send_discovery", handleSendMqttDiscovery); + // Finish setup of the mqtt clent object. + mqtt_client.setServer(MqttServer, atoi(MqttPort)); + mqtt_client.setCallback(mqttCallback); + // Set various variables + init_vars(); +#endif // MQTT_ENABLE + +#if FIRMWARE_OTA + // Setup the URL to allow Over-The-Air (OTA) firmware updates. + if (strlen(HttpPassword)) { // Allow if password is set. + server.on("/update", HTTP_POST, [](){ +#if MQTT_ENABLE + mqttLog("Attempting firmware update & reboot"); + delay(1000); +#endif // MQTT_ENABLE + server.send(200, "text/html", + "Updating firmware." + "" + "

Updating firmware

" + "
" + "

Warning! Don't power off the device for 60 seconds!

" + "

The firmware is uploading and will try to flash itself. " + "It is important to not interrupt the process.

" + "

The firmware upload seems to have " + + String(Update.hasError() ? "FAILED!" : "SUCCEEDED!") + + " Rebooting!

" + + addJsReloadUrl("/", 20, true) + + ""); + delay(1000); + ESP.restart(); + delay(1000); + }, [](){ + if (!server.authenticate(HttpUsername, HttpPassword)) { + debug("Basic HTTP authentication failure for /update."); + return server.requestAuthentication(); + } + HTTPUpload& upload = server.upload(); + if (upload.status == UPLOAD_FILE_START) { + WiFiUDP::stopAll(); + debug("Update:"); + debug(upload.filename.c_str()); + uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & + 0xFFFFF000; + if (!Update.begin(maxSketchSpace)) { // start with max available size +#if DEBUG + if (!isSerialGpioUsedByIr()) + Update.printError(Serial); +#endif // DEBUG + } + } else if (upload.status == UPLOAD_FILE_WRITE) { + if (Update.write(upload.buf, upload.currentSize) != + upload.currentSize) { +#if DEBUG + if (!isSerialGpioUsedByIr()) + Update.printError(Serial); +#endif // DEBUG + } + } else if (upload.status == UPLOAD_FILE_END) { + // true to set the size to the current progress + if (Update.end(true)) { + debug("Update Success:"); + debug(String(upload.totalSize).c_str()); + debug("Rebooting..."); + } + } + yield(); + }); + } +#endif // FIRMWARE_OTA + + // Set up an error page. + server.onNotFound(handleNotFound); + + server.begin(); + debug("HTTP server started"); +} + +#if MQTT_ENABLE +// MQTT subscribing to topic +void subscribing(const String topic_name) { + // subscription to topic for receiving data with QoS. + if (mqtt_client.subscribe(topic_name.c_str(), QOS)) + debug("Subscription OK to:"); + else + debug("Subscription FAILED to:"); + debug(topic_name.c_str()); +} + +// Un-subscribe from a MQTT topic +void unsubscribing(const String topic_name) { + // subscription to topic for receiving data with QoS. + if (mqtt_client.unsubscribe(topic_name.c_str())) + debug("Unsubscribed OK from:"); + else + debug("FAILED to unsubscribe from:"); + debug(topic_name.c_str()); +} + +void mqttLog(const String mesg) { + debug(mesg.c_str()); + mqtt_client.publish(MqttLog.c_str(), mesg.c_str()); + mqttSentCounter++; +} + +bool reconnect(void) { + // Loop a few times or until we're reconnected + uint16_t tries = 1; + while (!mqtt_client.connected() && tries <= 3) { + int connected = false; + // Attempt to connect + debug(("Attempting MQTT connection to " + String(MqttServer) + ":" + + String(MqttPort) + "... ").c_str()); + if (strcmp(MqttUsername, "") && strcmp(MqttPassword, "")) { + debug("Using mqtt username/password to connect."); + connected = mqtt_client.connect(MqttClientId.c_str(), + MqttUsername, MqttPassword, + MqttLwt.c_str(), + QOS, true, kLwtOffline); + + } else { + debug("Using password-less mqtt connection."); + connected = mqtt_client.connect(MqttClientId.c_str(), MqttLwt.c_str(), + QOS, true, kLwtOffline); + } + if (connected) { + // Once connected, publish an announcement... + mqttLog("(Re)Connected."); + + // Update Last Will & Testament to say we are back online. + mqtt_client.publish(MqttLwt.c_str(), kLwtOnline, true); + mqttSentCounter++; + + // Subscribing to topic(s) + subscribing(MqttSend); + for (uint8_t i = 0; i < kSendTableSize; i++) { + subscribing(MqttSend + '_' + String(static_cast(i))); + } + // Climate command topics. + subscribing(MqttClimateCmnd + '+'); + } else { + debug(("failed, rc=" + String(mqtt_client.state()) + + " Try again in a bit.").c_str()); + // Wait for a bit before retrying + delay(tries << 7); // Linear increasing back-off (x128) + } + tries++; + } + return mqtt_client.connected(); +} + +// Return a string containing the comma separated list of MQTT command topics. +String listOfCommandTopics(void) { + String result = MqttSend; + for (uint16_t i = 0; i < kSendTableSize; i++) { + result += ", " + MqttSend + '_' + String(i); + } + return result; +} + +// MQTT Discovery web page +void handleSendMqttDiscovery(void) { +#if HTML_PASSWORD_ENABLE + if (!server.authenticate(HttpUsername, HttpPassword)) { + debug("Basic HTTP authentication failure for /send_discovery."); + return server.requestAuthentication(); + } +#endif // HTML_PASSWORD_ENABLE + server.send(200, "text/html", + "Sending MQTT Discovery message" + "" + "

Sending MQTT Discovery message.

" + + htmlMenu() + + "

The Home Assistant MQTT Discovery message is being sent to topic: " + + MqttDiscovery + ". It will show up in Home Assistant in a few seconds." + "

" + "

Warning!

" + "

Home Assistant's config for this device is reset each time this is " + " is sent.

" + + addJsReloadUrl("/", 15, true) + + ""); + sendMQTTDiscovery(MqttDiscovery.c_str()); +} + +void doBroadcast(TimerMs *timer, const uint32_t interval, + const commonAcState_t state, const bool retain, + const bool force) { + if (force || (!lockMqttBroadcast && timer->elapsed() > interval)) { + debug("Sending MQTT stat update broadcast."); + sendClimate(state, state, MqttClimateStat, + retain, true, false); + timer->reset(); // It's been sent, so reset the timer. + hasBroadcastBeenSent = true; + } +} + +void receivingMQTT(String const topic_name, String const callback_str) { + char* tok_ptr; + uint64_t code = 0; + uint16_t nbits = 0; + uint16_t repeat = 0; + uint8_t channel = 0; // Default to the first channel. e.g. "*_0" + + debug("Receiving data by MQTT topic:"); + debug(topic_name.c_str()); + debug("with payload:"); + debug(callback_str.c_str()); + // Save the message as the last command seen (global). + lastMqttCmdTopic = topic_name; + lastMqttCmd = callback_str; + lastMqttCmdTime = millis(); + mqttRecvCounter++; + + if (topic_name.startsWith(MqttClimate)) { + if (topic_name.startsWith(MqttClimateCmnd)) { + debug("It's a climate command topic"); + commonAcState_t updated = updateClimate( + climate, topic_name, MqttClimateCmnd, callback_str); + sendClimate(climate, updated, MqttClimateStat, + true, false, false); + climate = updated; + } else if (topic_name.startsWith(MqttClimateStat)) { + debug("It's a climate state topic. Update internal state and DON'T send"); + climate = updateClimate( + climate, topic_name, MqttClimateStat, callback_str); + } + return; // We are done for now. + } + // Check if a specific channel was requested by looking for a "*_[0-9]" suffix + for (uint8_t i = 0; i < kSendTableSize; i++) { + debug(("Checking if " + topic_name + " ends with _" + String(i)).c_str()); + if (topic_name.endsWith("_" + String(i))) { + channel = i; + debug("It does!"); + break; + } + } + + debug(("Using transmit channel " + String(static_cast(channel)) + + " / GPIO " + String(static_cast(gpioTable[channel]))).c_str()); + // Make a copy of the callback string as strtok destroys it. + char* callback_c_str = strdup(callback_str.c_str()); + debug("MQTT Payload (raw):"); + debug(callback_c_str); + + // Get the numeric protocol type. + int ir_type = strtoul(strtok_r(callback_c_str, ",", &tok_ptr), NULL, 10); + char* next = strtok_r(NULL, ",", &tok_ptr); + // If there is unparsed string left, try to convert it assuming it's hex. + if (next != NULL) { + code = getUInt64fromHex(next); + next = strtok_r(NULL, ",", &tok_ptr); + } else { + // We require at least two value in the string. Give up. + return; + } + // If there is still string left, assume it is the bit size. + if (next != NULL) { + nbits = atoi(next); + next = strtok_r(NULL, ",", &tok_ptr); + } + // If there is still string left, assume it is the repeat count. + if (next != NULL) + repeat = atoi(next); + + free(callback_c_str); + + // send received MQTT value by IR signal + lastSendSucceeded = sendIRCode( + IrSendTable[channel], ir_type, code, + callback_str.substring(callback_str.indexOf(",") + 1).c_str(), + nbits, repeat); +} + +// Callback function, when we receive an MQTT value on the topics +// subscribed this function is called +void mqttCallback(char* topic, byte* payload, unsigned int length) { + // In order to republish this payload, a copy must be made + // as the orignal payload buffer will be overwritten whilst + // constructing the PUBLISH packet. + // Allocate the correct amount of memory for the payload copy + byte* payload_copy = reinterpret_cast(malloc(length + 1)); + // Copy the payload to the new buffer + memcpy(payload_copy, payload, length); + + // Conversion to a printable string + payload_copy[length] = '\0'; + String callback_string = String(reinterpret_cast(payload_copy)); + String topic_name = String(reinterpret_cast(topic)); + + // launch the function to treat received data + receivingMQTT(topic_name, callback_string); + + // Free the memory + free(payload_copy); +} + +void sendMQTTDiscovery(const char *topic) { + if (mqtt_client.publish( + topic, String( + "{" + "\"~\":\"" + MqttClimate + "\"," + "\"name\":\"" + MqttHAName + "\"," + "\"pow_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/" KEY_POWER "\"," + "\"mode_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/" KEY_MODE "\"," + "\"mode_stat_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_STAT "/" KEY_MODE + "\"," + "\"modes\":[\"off\",\"auto\",\"cool\",\"heat\",\"dry\",\"fan_only\"]," + "\"temp_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/" KEY_TEMP "\"," + "\"temp_stat_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_STAT "/" KEY_TEMP + "\"," + "\"min_temp\":\"16\"," + "\"max_temp\":\"30\"," + "\"temp_step\":\"1\"," + "\"fan_mode_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/" + KEY_FANSPEED "\"," + "\"fan_mode_stat_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_STAT "/" + KEY_FANSPEED "\"," + "\"fan_modes\":[\"auto\",\"min\",\"low\",\"medium\",\"high\",\"max\"]," + "\"swing_mode_cmd_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_CMND "/" + KEY_SWINGV "\"," + "\"swing_mode_stat_t\":\"~" MQTT_CLIMATE "/" MQTT_CLIMATE_STAT "/" + KEY_SWINGV "\"," + "\"swing_modes\":[" + "\"off\",\"auto\",\"highest\",\"high\",\"middle\",\"low\",\"lowest\"" + "]" + "}").c_str())) { + mqttLog("MQTT climate discovery successful sent."); + hasDiscoveryBeenSent = true; + lastDiscovery.reset(); + mqttSentCounter++; + } else { + mqttLog("MQTT climate discovery FAILED to send."); + } +} +#endif // MQTT_ENABLE + +void loop(void) { + server.handleClient(); // Handle any web activity + +#if MQTT_ENABLE + uint32_t now = millis(); + // MQTT client connection management + if (!mqtt_client.connected()) { + if (wasConnected) { + lastDisconnectedTime = now; + wasConnected = false; + mqttDisconnectCounter++; + } + // Reconnect if it's longer than kMqttReconnectTime since we last tried. + if (now - lastReconnectAttempt > kMqttReconnectTime) { + lastReconnectAttempt = now; + debug("client mqtt not connected, trying to connect"); + // Attempt to reconnect + if (reconnect()) { + lastReconnectAttempt = 0; + wasConnected = true; + if (boot) { + mqttLog("IR Server just booted"); + boot = false; + } else { + mqttLog("IR Server just (re)connected to MQTT. " + "Lost connection about " + timeSince(lastConnectedTime)); + } + lastConnectedTime = now; + debug("successful client mqtt connection"); + if (lockMqttBroadcast) { + // Attempt to fetch back any Climate state stored in MQTT retained + // messages on the MQTT broker. + mqttLog("Started listening for previous state."); + climate_prev = climate; // Make a copy so we can compare afterwards. + subscribing(MqttClimateStat + '+'); + statListenTime.reset(); + } + } + } + } else { + // MQTT loop + lastConnectedTime = now; + mqtt_client.loop(); + if (lockMqttBroadcast && statListenTime.elapsed() > kStatListenPeriodMs) { + unsubscribing(MqttClimateStat + '+'); + mqttLog("Finished listening for previous state."); + if (cmpClimate(climate, climate_prev)) { // Something changed. + mqttLog("The state was recovered from MQTT broker. Updating."); + sendClimate(climate_prev, climate, MqttClimateStat, + true, false, false); + } + lockMqttBroadcast = false; // Release the lock so we can broadcast again. + } + // Periodically send all of the climate state via MQTT. + doBroadcast(&lastBroadcast, kBroadcastPeriodMs, climate, false, false); + } +#endif // MQTT_ENABLE +#ifdef IR_RX + // Check if an IR code has been received via the IR RX module. +#if REPORT_UNKNOWNS + if (irrecv.decode(&capture)) { +#else // REPORT_UNKNOWNS + if (irrecv.decode(&capture) && capture.decode_type != UNKNOWN) { +#endif // REPORT_UNKNOWNS + lastIrReceivedTime = millis(); + lastIrReceived = String(capture.decode_type) + "," + + resultToHexidecimal(&capture); +#if REPORT_RAW_UNKNOWNS + if (capture.decode_type == UNKNOWN) { + lastIrReceived += ";"; + for (uint16_t i = 1; i < capture.rawlen; i++) { + uint32_t usecs; + for (usecs = capture.rawbuf[i] * kRawTick; usecs > UINT16_MAX; + usecs -= UINT16_MAX) { + lastIrReceived += uint64ToString(UINT16_MAX); + lastIrReceived += ",0,"; + } + lastIrReceived += uint64ToString(usecs, 10); + if (i < capture.rawlen - 1) + lastIrReceived += ","; + } + } +#endif // REPORT_RAW_UNKNOWNS + // If it isn't an AC code, add the bits. + if (!hasACState(capture.decode_type)) + lastIrReceived += "," + String(capture.bits); +#if MQTT_ENABLE + mqtt_client.publish(MqttRecv.c_str(), lastIrReceived.c_str()); + mqttSentCounter++; +#endif // MQTT_ENABLE + irRecvCounter++; + debug("Incoming IR message sent to MQTT:"); + debug(lastIrReceived.c_str()); + } +#endif // IR_RX + delay(100); +} + +// Arduino framework doesn't support strtoull(), so make our own one. +uint64_t getUInt64fromHex(char const *str) { + uint64_t result = 0; + uint16_t offset = 0; + // Skip any leading '0x' or '0X' prefix. + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + offset = 2; + for (; isxdigit((unsigned char)str[offset]); offset++) { + char c = str[offset]; + result *= 16; + if (isdigit(c)) /* '0' .. '9' */ + result += c - '0'; + else if (isupper(c)) /* 'A' .. 'F' */ + result += c - 'A' + 10; + else /* 'a' .. 'f'*/ + result += c - 'a' + 10; + } + return result; +} + +// Transmit the given IR message. +// +// Args: +// irsend: A pointer to a IRsend object to transmit via. +// ir_type: enum of the protocol to be sent. +// code: Numeric payload of the IR message. Most protocols use this. +// code_str: The unparsed code to be sent. Used by complex protocol encodings. +// bits: Nr. of bits in the protocol. 0 means use the protocol's default. +// repeat: Nr. of times the message is to be repeated. (Not all protcols.) +// Returns: +// bool: Successfully sent or not. +bool sendIRCode(IRsend *irsend, int const ir_type, + uint64_t const code, char const * code_str, uint16_t bits, + uint16_t repeat) { + // Create a pseudo-lock so we don't try to send two codes at the same time. + while (lockIr) + delay(20); + lockIr = true; + + bool success = true; // Assume success. + + // send the IR message. + switch (ir_type) { +#if SEND_RC5 + case RC5: // 1 + if (bits == 0) + bits = kRC5Bits; + irsend->sendRC5(code, bits, repeat); + break; +#endif +#if SEND_RC6 + case RC6: // 2 + if (bits == 0) + bits = kRC6Mode0Bits; + irsend->sendRC6(code, bits, repeat); + break; +#endif +#if SEND_NEC + case NEC: // 3 + if (bits == 0) + bits = kNECBits; + irsend->sendNEC(code, bits, repeat); + break; +#endif +#if SEND_SONY + case SONY: // 4 + if (bits == 0) + bits = kSony12Bits; + repeat = std::max(repeat, kSonyMinRepeat); + irsend->sendSony(code, bits, repeat); + break; +#endif +#if SEND_PANASONIC + case PANASONIC: // 5 + if (bits == 0) + bits = kPanasonicBits; + irsend->sendPanasonic64(code, bits, repeat); + break; +#endif +#if SEND_JVC + case JVC: // 6 + if (bits == 0) + bits = kJvcBits; + irsend->sendJVC(code, bits, repeat); + break; +#endif +#if SEND_SAMSUNG + case SAMSUNG: // 7 + if (bits == 0) + bits = kSamsungBits; + irsend->sendSAMSUNG(code, bits, repeat); + break; +#endif +#if SEND_SAMSUNG36 + case SAMSUNG36: // 56 + if (bits == 0) + bits = kSamsung36Bits; + irsend->sendSamsung36(code, bits, repeat); + break; +#endif +#if SEND_WHYNTER + case WHYNTER: // 8 + if (bits == 0) + bits = kWhynterBits; + irsend->sendWhynter(code, bits, repeat); + break; +#endif +#if SEND_AIWA_RC_T501 + case AIWA_RC_T501: // 9 + if (bits == 0) + bits = kAiwaRcT501Bits; + repeat = std::max(repeat, kAiwaRcT501MinRepeats); + irsend->sendAiwaRCT501(code, bits, repeat); + break; +#endif +#if SEND_LG + case LG: // 10 + if (bits == 0) + bits = kLgBits; + irsend->sendLG(code, bits, repeat); + break; +#endif +#if SEND_MITSUBISHI + case MITSUBISHI: // 12 + if (bits == 0) + bits = kMitsubishiBits; + repeat = std::max(repeat, kMitsubishiMinRepeat); + irsend->sendMitsubishi(code, bits, repeat); + break; +#endif +#if SEND_DISH + case DISH: // 13 + if (bits == 0) + bits = kDishBits; + repeat = std::max(repeat, kDishMinRepeat); + irsend->sendDISH(code, bits, repeat); + break; +#endif +#if SEND_SHARP + case SHARP: // 14 + if (bits == 0) + bits = kSharpBits; + irsend->sendSharpRaw(code, bits, repeat); + break; +#endif +#if SEND_COOLIX + case COOLIX: // 15 + if (bits == 0) + bits = kCoolixBits; + irsend->sendCOOLIX(code, bits, repeat); + break; +#endif + case DAIKIN: // 16 + case DAIKIN2: // 53 + case DAIKIN216: // 61 + case KELVINATOR: // 18 + case MITSUBISHI_AC: // 20 + case GREE: // 24 + case ARGO: // 27 + case TROTEC: // 28 + case TOSHIBA_AC: // 32 + case FUJITSU_AC: // 33 + case HAIER_AC: // 38 + case HAIER_AC_YRW02: // 44 + case HITACHI_AC: // 40 + case HITACHI_AC1: // 41 + case HITACHI_AC2: // 42 + case WHIRLPOOL_AC: // 45 + case SAMSUNG_AC: // 46 + case ELECTRA_AC: // 48 + case PANASONIC_AC: // 49 + case MWM: // 52 + success = parseStringAndSendAirCon(irsend, ir_type, code_str); + break; +#if SEND_DENON + case DENON: // 17 + if (bits == 0) + bits = DENON_BITS; + irsend->sendDenon(code, bits, repeat); + break; +#endif +#if SEND_SHERWOOD + case SHERWOOD: // 19 + if (bits == 0) + bits = kSherwoodBits; + repeat = std::max(repeat, kSherwoodMinRepeat); + irsend->sendSherwood(code, bits, repeat); + break; +#endif +#if SEND_RCMM + case RCMM: // 21 + if (bits == 0) + bits = kRCMMBits; + irsend->sendRCMM(code, bits, repeat); + break; +#endif +#if SEND_SANYO + case SANYO_LC7461: // 22 + if (bits == 0) + bits = kSanyoLC7461Bits; + irsend->sendSanyoLC7461(code, bits, repeat); + break; +#endif +#if SEND_RC5 + case RC5X: // 23 + if (bits == 0) + bits = kRC5XBits; + irsend->sendRC5(code, bits, repeat); + break; +#endif +#if SEND_PRONTO + case PRONTO: // 25 + success = parseStringAndSendPronto(irsend, code_str, repeat); + break; +#endif +#if SEND_NIKAI + case NIKAI: // 29 + if (bits == 0) + bits = kNikaiBits; + irsend->sendNikai(code, bits, repeat); + break; +#endif +#if SEND_RAW + case RAW: // 30 + success = parseStringAndSendRaw(irsend, code_str); + break; +#endif +#if SEND_GLOBALCACHE + case GLOBALCACHE: // 31 + success = parseStringAndSendGC(irsend, code_str); + break; +#endif +#if SEND_MIDEA + case MIDEA: // 34 + if (bits == 0) + bits = kMideaBits; + irsend->sendMidea(code, bits, repeat); + break; +#endif +#if SEND_MAGIQUEST + case MAGIQUEST: // 35 + if (bits == 0) + bits = kMagiquestBits; + irsend->sendMagiQuest(code, bits, repeat); + break; +#endif +#if SEND_LASERTAG + case LASERTAG: // 36 + if (bits == 0) + bits = kLasertagBits; + irsend->sendLasertag(code, bits, repeat); + break; +#endif +#if SEND_CARRIER_AC + case CARRIER_AC: // 37 + if (bits == 0) + bits = kCarrierAcBits; + irsend->sendCarrierAC(code, bits, repeat); + break; +#endif +#if SEND_MITSUBISHI2 + case MITSUBISHI2: // 39 + if (bits == 0) + bits = kMitsubishiBits; + repeat = std::max(repeat, kMitsubishiMinRepeat); + irsend->sendMitsubishi2(code, bits, repeat); + break; +#endif +#if SEND_GICABLE + case GICABLE: // 43 + if (bits == 0) + bits = kGicableBits; + repeat = std::max(repeat, kGicableMinRepeat); + irsend->sendGICable(code, bits, repeat); + break; +#endif +#if SEND_LUTRON + case LUTRON: // 47 + if (bits == 0) + bits = kLutronBits; + irsend->sendLutron(code, bits, repeat); + break; +#endif +#if SEND_PIONEER + case PIONEER: // 50 + if (bits == 0) + bits = kPioneerBits; + irsend->sendPioneer(code, bits, repeat); + break; +#endif +#if SEND_LG + case LG2: // 51 + if (bits == 0) + bits = kLgBits; + irsend->sendLG2(code, bits, repeat); + break; +#endif +#if SEND_VESTEL_AC + case VESTEL_AC: // 54 + if (bits == 0) + bits = kVestelAcBits; + irsend->sendVestelAc(code, bits, repeat); + break; +#endif +#if SEND_TECO + case TECO: // 55 + if (bits == 0) + bits = kTecoBits; + irsend->sendTeco(code, bits, repeat); + break; +#endif +#if SEND_LEGOPF + case LEGOPF: // 58 + if (bits == 0) + bits = kLegoPfBits; + irsend->sendLegoPf(code, bits, repeat); + break; +#endif + default: + // If we got here, we didn't know how to send it. + success = false; + } + lastSendTime = millis(); + // Release the lock. + lockIr = false; + + // Indicate that we sent the message or not. + if (success) { + sendReqCounter++; + debug("Sent the IR message:"); + } else { + debug("Failed to send IR Message:"); + } + debug("Type:"); + debug(String(ir_type).c_str()); + // For "long" codes we basically repeat what we got. + if (hasACState((decode_type_t) ir_type) || + ir_type == PRONTO || + ir_type == RAW || + ir_type == GLOBALCACHE) { + debug("Code: "); + debug(code_str); + // Confirm what we were asked to send was sent. +#if MQTT_ENABLE + if (success) { + if (ir_type == PRONTO && repeat > 0) + mqtt_client.publish(MqttAck.c_str(), (String(ir_type) + ",R" + + String(repeat) + "," + + String(code_str)).c_str()); + else + mqtt_client.publish(MqttAck.c_str(), (String(ir_type) + "," + + String(code_str)).c_str()); + mqttSentCounter++; + } +#endif // MQTT_ENABLE + } else { // For "short" codes, we break it down a bit more before we report. + debug(("Code: 0x" + uint64ToString(code, 16)).c_str()); + debug(("Bits: " + String(bits)).c_str()); + debug(("Repeats: " + String(repeat)).c_str()); +#if MQTT_ENABLE + if (success) { + mqtt_client.publish(MqttAck.c_str(), (String(ir_type) + "," + + uint64ToString(code, 16) + + "," + String(bits) + "," + + String(repeat)).c_str()); + mqttSentCounter++; + } +#endif // MQTT_ENABLE + } + return success; +} + +bool sendInt(const String topic, const int32_t num, const bool retain) { +#if MQTT_ENABLE + mqttSentCounter++; + return mqtt_client.publish(topic.c_str(), String(num).c_str(), retain); +#else // MQTT_ENABLE + return true; +#endif // MQTT_ENABLE +} + +bool sendBool(const String topic, const bool on, const bool retain) { +#if MQTT_ENABLE + mqttSentCounter++; + return mqtt_client.publish(topic.c_str(), (on ? "on" : "off"), retain); +#else // MQTT_ENABLE + return true; +#endif // MQTT_ENABLE +} + +bool sendString(const String topic, const String str, const bool retain) { +#if MQTT_ENABLE + mqttSentCounter++; + return mqtt_client.publish(topic.c_str(), str.c_str(), retain); +#else // MQTT_ENABLE + return true; +#endif // MQTT_ENABLE +} + +bool sendFloat(const String topic, const float_t temp, const bool retain) { +#if MQTT_ENABLE + mqttSentCounter++; + return mqtt_client.publish(topic.c_str(), String(temp, 1).c_str(), retain); +#else // MQTT_ENABLE + return true; +#endif // MQTT_ENABLE +} + +commonAcState_t updateClimate(commonAcState_t current, const String str, + const String prefix, const String payload) { + commonAcState_t result = current; + String value = payload; + value.toUpperCase(); + if (str.equals(prefix + KEY_PROTOCOL)) + result.protocol = strToDecodeType(value.c_str()); + else if (str.equals(prefix + KEY_MODEL)) + result.model = IRac::strToModel(value.c_str()); + else if (str.equals(prefix + KEY_POWER)) + result.power = IRac::strToBool(value.c_str()); + else if (str.equals(prefix + KEY_MODE)) + result.mode = IRac::strToOpmode(value.c_str()); + else if (str.equals(prefix + KEY_TEMP)) + result.degrees = value.toFloat(); + else if (str.equals(prefix + KEY_FANSPEED)) + result.fanspeed = IRac::strToFanspeed(value.c_str()); + else if (str.equals(prefix + KEY_SWINGV)) + result.swingv = IRac::strToSwingV(value.c_str()); + else if (str.equals(prefix + KEY_SWINGH)) + result.swingh = IRac::strToSwingH(value.c_str()); + else if (str.equals(prefix + KEY_QUIET)) + result.quiet = IRac::strToBool(value.c_str()); + else if (str.equals(prefix + KEY_TURBO)) + result.turbo = IRac::strToBool(value.c_str()); + else if (str.equals(prefix + KEY_ECONO)) + result.econo = IRac::strToBool(value.c_str()); + else if (str.equals(prefix + KEY_LIGHT)) + result.light = IRac::strToBool(value.c_str()); + else if (str.equals(prefix + KEY_BEEP)) + result.beep = IRac::strToBool(value.c_str()); + else if (str.equals(prefix + KEY_FILTER)) + result.filter = IRac::strToBool(value.c_str()); + else if (str.equals(prefix + KEY_CLEAN)) + result.clean = IRac::strToBool(value.c_str()); + else if (str.equals(prefix + KEY_SLEEP)) + result.sleep = value.toInt(); + else if (str.equals(prefix + KEY_CLOCK)) + result.clock = value.toInt(); + return result; +} + +// Compare two AirCon states (climates). +// Returns: True if they differ, False if they don't. +bool cmpClimate(const commonAcState_t a, const commonAcState_t b) { + return a.protocol != b.protocol || a.model != b.model || a.power != b.power || + a.mode != b.mode || a.degrees != b.degrees || a.celsius != b.celsius || + a.fanspeed != b.fanspeed || a.swingv != b.swingv || + a.swingh != b.swingh || a.quiet != b.quiet || a.turbo != b.turbo || + a.econo != b.econo || a.light != b.light || a.filter != b.filter || + a.clean != b.clean || a.beep != b.beep || a.sleep != b.sleep; +} + +bool sendClimate(const commonAcState_t prev, const commonAcState_t next, + const String topic_prefix, const bool retain, + const bool forceMQTT, const bool forceIR) { + bool diff = false; + bool success = true; + + if (prev.protocol != next.protocol || forceMQTT) { + diff = true; + success &= sendString(topic_prefix + KEY_PROTOCOL, + typeToString(next.protocol), retain); + } + if (prev.model != next.model || forceMQTT) { + diff = true; + success &= sendInt(topic_prefix + KEY_MODEL, next.model, retain); + } + if (prev.power != next.power || prev.mode != next.mode || forceMQTT) { + diff = true; + success &= sendBool(topic_prefix + KEY_POWER, next.power, retain); + success &= sendString(topic_prefix + KEY_MODE, + (next.power ? opmodeToString(next.mode) : F("off")), + retain); + } + if (prev.degrees != next.degrees || forceMQTT) { + diff = true; + success &= sendFloat(topic_prefix + KEY_TEMP, next.degrees, retain); + } + if (prev.celsius != next.celsius || forceMQTT) { + diff = true; + success &= sendBool(topic_prefix + KEY_CELSIUS, next.celsius, retain); + } + if (prev.fanspeed != next.fanspeed || forceMQTT) { + diff = true; + success &= sendString(topic_prefix + KEY_FANSPEED, + fanspeedToString(next.fanspeed), retain); + } + if (prev.swingv != next.swingv || forceMQTT) { + diff = true; + success &= sendString(topic_prefix + KEY_SWINGV, + swingvToString(next.swingv), retain); + } + if (prev.swingh != next.swingh || forceMQTT) { + diff = true; + success &= sendString(topic_prefix + KEY_SWINGH, + swinghToString(next.swingh), retain); + } + if (prev.quiet != next.quiet || forceMQTT) { + diff = true; + success &= sendBool(topic_prefix + KEY_QUIET, next.quiet, retain); + } + if (prev.turbo != next.turbo || forceMQTT) { + diff = true; + success &= sendBool(topic_prefix + KEY_TURBO, next.turbo, retain); + } + if (prev.econo != next.econo || forceMQTT) { + diff = true; + success &= sendBool(topic_prefix + KEY_ECONO, next.econo, retain); + } + if (prev.light != next.light || forceMQTT) { + diff = true; + success &= sendBool(topic_prefix + KEY_LIGHT, next.light, retain); + } + if (prev.filter != next.filter || forceMQTT) { + diff = true; + success &= sendBool(topic_prefix + KEY_FILTER, next.filter, retain); + } + if (prev.clean != next.clean || forceMQTT) { + diff = true; + success &= sendBool(topic_prefix + KEY_CLEAN, next.clean, retain); + } + if (prev.beep != next.beep || forceMQTT) { + diff = true; + success &= sendBool(topic_prefix + KEY_BEEP, next.beep, retain); + } + if (prev.sleep != next.sleep || forceMQTT) { + diff = true; + success &= sendInt(topic_prefix + KEY_SLEEP, next.sleep, retain); + } + if (diff && !forceMQTT) + debug("Difference in common A/C state detected."); + else + debug("NO difference in common A/C state detected."); + // Only send an IR message if we need to. + if ((diff && !forceMQTT) || forceIR) { + debug("Sending common A/C state via IR."); + lastClimateSucceeded = commonAc.sendAc( + next.protocol, next.model, next.power, next.mode, + next.degrees, next.celsius, next.fanspeed, next.swingv, next.swingh, + next.quiet, next.turbo, next.econo, next.light, next.filter, next.clean, + next.beep, next.sleep, -1); + if (lastClimateSucceeded) hasClimateBeenSent = true; + success &= lastClimateSucceeded; + lastClimateIr.reset(); + irClimateCounter++; + sendReqCounter++; + } + return success; +} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/platformio.ini similarity index 55% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/platformio.ini rename to lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/platformio.ini index 27b44ddca..243b36a99 100644 --- a/lib/IRremoteESP8266-2.5.2.03/examples/IRMQTTServer/platformio.ini +++ b/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/platformio.ini @@ -3,16 +3,19 @@ lib_extra_dirs = ../../ src_dir=. [common] -build_flags = -DMQTT_MAX_PACKET_SIZE=512 +build_flags = -DMQTT_MAX_PACKET_SIZE=768 +lib_ldf_mode = chain+ lib_deps_builtin = lib_deps_external = PubSubClient WifiManager@0.14 + ArduinoJson [env:nodemcuv2] platform = espressif8266 framework = arduino board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} build_flags = ${common.build_flags} lib_deps = ${common.lib_deps_builtin} @@ -22,7 +25,18 @@ lib_deps = platform=espressif8266 framework=arduino board=d1_mini +lib_ldf_mode = ${common.lib_ldf_mode} build_flags = ${common.build_flags} lib_deps = ${common.lib_deps_builtin} ${common.lib_deps_external} + +[env:d1_mini_no_mqtt] +platform=espressif8266 +framework=arduino +board=d1_mini +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} -DMQTT_ENABLE=false +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRServer/IRServer.ino b/lib/IRremoteESP8266-2.6.0/examples/IRServer/IRServer.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRServer/IRServer.ino rename to lib/IRremoteESP8266-2.6.0/examples/IRServer/IRServer.ino diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRServer/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRServer/platformio.ini similarity index 83% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRServer/platformio.ini rename to lib/IRremoteESP8266-2.6.0/examples/IRServer/platformio.ini index eeb8d1f2e..ec84f22f3 100644 --- a/lib/IRremoteESP8266-2.5.2.03/examples/IRServer/platformio.ini +++ b/lib/IRremoteESP8266-2.6.0/examples/IRServer/platformio.ini @@ -6,11 +6,13 @@ src_dir=. build_flags = lib_deps_builtin = lib_deps_external = +lib_ldf_mode = chain+ [env:nodemcuv2] platform = espressif8266 framework = arduino board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} build_flags = ${common.build_flags} lib_deps = ${common.lib_deps_builtin} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/IRrecvDemo.ino b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDemo/IRrecvDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDemo/IRrecvDemo.ino rename to lib/IRremoteESP8266-2.6.0/examples/IRrecvDemo/IRrecvDemo.ino diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDemo/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDemo/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDemo/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/IRrecvDump.ino b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDump/IRrecvDump.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDump/IRrecvDump.ino rename to lib/IRremoteESP8266-2.6.0/examples/IRrecvDump/IRrecvDump.ino diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDump/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDump/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDump/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/IRrecvDumpV2.ino similarity index 84% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/IRrecvDumpV2.ino rename to lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/IRrecvDumpV2.ino index d72e0814c..2dee0597c 100644 --- a/lib/IRremoteESP8266-2.5.2.03/examples/IRrecvDumpV2/IRrecvDumpV2.ino +++ b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/IRrecvDumpV2.ino @@ -35,9 +35,15 @@ #include #include #include +#include #include #include +#include +#include #include +#include +#include + // ==================== start of TUNEABLE PARAMETERS ==================== // An IR detector/demodulator is connected to GPIO pin 14 @@ -121,6 +127,20 @@ void dumpACInfo(decode_results *results) { description = ac.toString(); } #endif // DECODE_DAIKIN +#if DECODE_DAIKIN2 + if (results->decode_type == DAIKIN2) { + IRDaikin2 ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_DAIKIN2 +#if DECODE_DAIKIN216 + if (results->decode_type == DAIKIN216) { + IRDaikin216 ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_DAIKIN216 #if DECODE_FUJITSU_AC if (results->decode_type == FUJITSU_AC) { IRFujitsuAC ac(0); @@ -142,6 +162,18 @@ void dumpACInfo(decode_results *results) { description = ac.toString(); } #endif // DECODE_MITSUBISHI_AC +#if DECODE_MITSUBISHIHEAVY + if (results->decode_type == MITSUBISHI_HEAVY_88) { + IRMitsubishiHeavy88Ac ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } + if (results->decode_type == MITSUBISHI_HEAVY_152) { + IRMitsubishiHeavy152Ac ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_MITSUBISHIHEAVY #if DECODE_TOSHIBA_AC if (results->decode_type == TOSHIBA_AC) { IRToshibaAC ac(0); @@ -180,7 +212,7 @@ void dumpACInfo(decode_results *results) { #if DECODE_SAMSUNG_AC if (results->decode_type == SAMSUNG_AC) { IRSamsungAc ac(0); - ac.setRaw(results->state); + ac.setRaw(results->state, results->bits / 8); description = ac.toString(); } #endif // DECODE_SAMSUNG_AC @@ -206,6 +238,34 @@ void dumpACInfo(decode_results *results) { description = ac.toString(); } #endif // DECODE_HITACHI_AC +#if DECODE_WHIRLPOOL_AC + if (results->decode_type == WHIRLPOOL_AC) { + IRWhirlpoolAc ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_WHIRLPOOL_AC +#if DECODE_VESTEL_AC + if (results->decode_type == VESTEL_AC) { + IRVestelAc ac(0); + ac.setRaw(results->value); // Like Coolix, use value instead of state. + description = ac.toString(); + } +#endif // DECODE_VESTEL_AC +#if DECODE_TECO + if (results->decode_type == TECO) { + IRTecoAc ac(0); + ac.setRaw(results->value); // Like Coolix, use value instead of state. + description = ac.toString(); + } +#endif // DECODE_TECO +#if DECODE_TCL112AC + if (results->decode_type == TCL112AC) { + IRTcl112Ac ac(0); + ac.setRaw(results->state); + description = ac.toString(); + } +#endif // DECODE_TCL112AC // If we got a human-readable description of the message, display it. if (description != "") Serial.println("Mesg Desc.: " + description); } diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/IRrecvDumpV2/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/IRsendDemo.ino b/lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/IRsendDemo.ino similarity index 85% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/IRsendDemo.ino rename to lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/IRsendDemo.ino index 892016b3e..19f118671 100644 --- a/lib/IRremoteESP8266-2.5.2.03/examples/IRsendDemo/IRsendDemo.ino +++ b/lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/IRsendDemo.ino @@ -1,6 +1,6 @@ /* IRremoteESP8266: IRsendDemo - demonstrates sending IR codes with IRsend. * - * Version 1.0 April, 2017 + * Version 1.1 January, 2019 * Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, * Copyright 2009 Ken Shirriff, http://arcfn.com * @@ -46,6 +46,10 @@ uint16_t rawData[67] = {9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, 650, 550, 650, 550, 600, 550, 650, 550, 650, 550, 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650, 650, 1650, 650, 1650, 650, 1650, 600}; +// Example Samsung A/C state captured from IRrecvDumpV2.ino +uint8_t samsungState[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xE2, 0xFE, 0x71, 0x40, 0x11, 0xF0}; void setup() { irsend.begin(); @@ -53,19 +57,16 @@ void setup() { } void loop() { -#if SEND_NEC Serial.println("NEC"); - irsend.sendNEC(0x00FFE01FUL, 32); -#endif // SEND_NEC + irsend.sendNEC(0x00FFE01FUL); delay(2000); -#if SEND_SONY Serial.println("Sony"); - irsend.sendSony(0xa90, 12, 2); -#endif // SEND_SONY + irsend.sendSony(0xa90, 12, 2); // 12 bits & 2 repeats delay(2000); -#if SEND_RAW Serial.println("a rawData capture from IRrecvDumpV2"); irsend.sendRaw(rawData, 67, 38); // Send a raw data capture at 38kHz. -#endif // SEND_RAW + delay(2000); + Serial.println("a Samsung A/C state from IRrecvDumpV2"); + irsend.sendSamsungAC(samsungState); delay(2000); } diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/IRsendDemo/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/IRsendProntoDemo.ino b/lib/IRremoteESP8266-2.6.0/examples/IRsendProntoDemo/IRsendProntoDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/IRsendProntoDemo/IRsendProntoDemo.ino rename to lib/IRremoteESP8266-2.6.0/examples/IRsendProntoDemo/IRsendProntoDemo.ino diff --git a/lib/IRremoteESP8266-2.6.0/examples/IRsendProntoDemo/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/IRsendProntoDemo/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/IRsendProntoDemo/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino b/lib/IRremoteESP8266-2.6.0/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino rename to lib/IRremoteESP8266-2.6.0/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino diff --git a/lib/IRremoteESP8266-2.6.0/examples/JVCPanasonicSendDemo/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/JVCPanasonicSendDemo/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/JVCPanasonicSendDemo/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/LGACSend.ino b/lib/IRremoteESP8266-2.6.0/examples/LGACSend/LGACSend.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/LGACSend/LGACSend.ino rename to lib/IRremoteESP8266-2.6.0/examples/LGACSend/LGACSend.ino diff --git a/lib/IRremoteESP8266-2.6.0/examples/LGACSend/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/LGACSend/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/LGACSend/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/TurnOnArgoAC.ino b/lib/IRremoteESP8266-2.6.0/examples/TurnOnArgoAC/TurnOnArgoAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/TurnOnArgoAC/TurnOnArgoAC.ino rename to lib/IRremoteESP8266-2.6.0/examples/TurnOnArgoAC/TurnOnArgoAC.ino diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnArgoAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnArgoAC/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/TurnOnArgoAC/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino b/lib/IRremoteESP8266-2.6.0/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino rename to lib/IRremoteESP8266-2.6.0/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnDaikinAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnDaikinAC/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/TurnOnDaikinAC/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino b/lib/IRremoteESP8266-2.6.0/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino rename to lib/IRremoteESP8266-2.6.0/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnFujitsuAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnFujitsuAC/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/TurnOnFujitsuAC/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino b/lib/IRremoteESP8266-2.6.0/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino rename to lib/IRremoteESP8266-2.6.0/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnKelvinatorAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnKelvinatorAC/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/TurnOnKelvinatorAC/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino b/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino rename to lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiAC/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiAC/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino b/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino new file mode 100644 index 000000000..2ad2d7bc3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino @@ -0,0 +1,72 @@ +/* Copyright 2019 David Conran +* +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. +* +* TL;DR: The IR LED needs to be driven by a transistor for a good result. +* +* Suggested circuit: +* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending +* +* Common mistakes & tips: +* * Don't just connect the IR LED directly to the pin, it won't +* have enough current to drive the IR LED effectively. +* * Make sure you have the IR LED polarity correct. +* See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity +* * Typical digital camera/phones can be used to see if the IR LED is flashed. +* Replace the IR LED with a normal LED if you don't have a digital camera +* when debugging. +* * Avoid using the following pins unless you really know what you are doing: +* * Pin 0/D3: Can interfere with the boot/program mode & support circuits. +* * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will interfere. +* * Pin 3/RX/RXD0: Any serial transmissions to the ESP8266 will interfere. +* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs +* for your first time. e.g. ESP-12 etc. +*/ +#ifndef UNIT_TEST +#include +#endif +#include +#include +#include + +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRMitsubishiHeavy152Ac ac(kIrLed); // Set the GPIO used for sending messages. + +void printState() { + // Display the settings. + Serial.println("Mitsubishi Heavy A/C remote is in the following state:"); + Serial.printf(" %s\n", ac.toString().c_str()); + // Display the encoded IR sequence. + unsigned char* ir_code = ac.getRaw(); + Serial.print("IR Code: 0x"); + for (uint8_t i = 0; i < kMitsubishiHeavy152StateLength; i++) + Serial.printf("%02X", ir_code[i]); + Serial.println(); +} + +void setup() { + ac.begin(); + Serial.begin(115200); + delay(200); + + // Set up what we want to send. See ir_MitsubishiHeavy.(cpp|h) for all the + // options. + Serial.println("Default state of the remote."); + printState(); + Serial.println("Setting desired state for A/C."); + ac.setPower(true); // Turn it on. + ac.setFan(kMitsubishiHeavy152FanMed); // Medium Fan + ac.setMode(kMitsubishiHeavyCool); // Cool mode + ac.setTemp(26); // Celsius + ac.setSwingVertical(kMitsubishiHeavy152SwingVAuto); // Swing vertically + ac.setSwingHorizontal(kMitsubishiHeavy152SwingHMiddle); // Swing Horizontally +} + +void loop() { + // Now send the IR signal. + Serial.println("Sending IR command to A/C ..."); + ac.send(); + printState(); + delay(5000); +} diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/TurnOnMitsubishiHeavyAc/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino b/lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino new file mode 100644 index 000000000..ea39ac5e2 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino @@ -0,0 +1,74 @@ +/* Copyright 2017, 2018 David Conran +* +* An IR LED circuit *MUST* be connected to the ESP8266 on a pin +* as specified by kIrLed below. +* +* TL;DR: The IR LED needs to be driven by a transistor for a good result. +* +* Suggested circuit: +* https://github.com/markszabo/IRremoteESP8266/wiki#ir-sending +* +* Common mistakes & tips: +* * Don't just connect the IR LED directly to the pin, it won't +* have enough current to drive the IR LED effectively. +* * Make sure you have the IR LED polarity correct. +* See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity +* * Typical digital camera/phones can be used to see if the IR LED is flashed. +* Replace the IR LED with a normal LED if you don't have a digital camera +* when debugging. +* * Avoid using the following pins unless you really know what you are doing: +* * Pin 0/D3: Can interfere with the boot/program mode & support circuits. +* * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will interfere. +* * Pin 3/RX/RXD0: Any serial transmissions to the ESP8266 will interfere. +* * ESP-01 modules are tricky. We suggest you use a module with more GPIOs +* for your first time. e.g. ESP-12 etc. +*/ +#ifndef UNIT_TEST +#include +#endif +#include +#include +#include + +const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2). +IRPanasonicAc ac(kIrLed); // Set the GPIO used for sending messages. + +void printState() { + // Display the settings. + Serial.println("Panasonic A/C remote is in the following state:"); + Serial.printf(" %s\n", ac.toString().c_str()); + // Display the encoded IR sequence. + unsigned char* ir_code = ac.getRaw(); + Serial.print("IR Code: 0x"); + for (uint8_t i = 0; i < kPanasonicAcStateLength; i++) + Serial.printf("%02X", ir_code[i]); + Serial.println(); +} + +void setup() { + ac.begin(); + Serial.begin(115200); + delay(200); + + // Set up what we want to send. See ir_Panasonic.cpp for all the options. + Serial.println("Default state of the remote."); + printState(); + Serial.println("Setting desired state for A/C."); + ac.setModel(kPanasonicRkr); + ac.on(); + ac.setFan(kPanasonicAcFanAuto); + ac.setMode(kPanasonicAcCool); + ac.setTemp(26); + ac.setSwingVertical(kPanasonicAcSwingVAuto); + ac.setSwingHorizontal(kPanasonicAcSwingHAuto); +} + +void loop() { + // Now send the IR signal. +#if SEND_PANASONIC_AC + Serial.println("Sending IR command to A/C ..."); + ac.send(); +#endif // SEND_PANASONIC_AC + printState(); + delay(5000); +} diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/TurnOnPanasonicAC/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino b/lib/IRremoteESP8266-2.6.0/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino rename to lib/IRremoteESP8266-2.6.0/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnToshibaAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnToshibaAC/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/TurnOnToshibaAC/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino b/lib/IRremoteESP8266-2.6.0/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino rename to lib/IRremoteESP8266-2.6.0/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino diff --git a/lib/IRremoteESP8266-2.6.0/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.6.0/examples/TurnOnTrotecAC/platformio.ini new file mode 100644 index 000000000..ec84f22f3 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/examples/TurnOnTrotecAC/platformio.ini @@ -0,0 +1,19 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = +lib_deps_builtin = +lib_deps_external = +lib_ldf_mode = chain+ + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.5.2.03/keywords.txt b/lib/IRremoteESP8266-2.6.0/keywords.txt similarity index 74% rename from lib/IRremoteESP8266-2.5.2.03/keywords.txt rename to lib/IRremoteESP8266-2.6.0/keywords.txt index ac3f43fe1..a498c5d61 100644 --- a/lib/IRremoteESP8266-2.5.2.03/keywords.txt +++ b/lib/IRremoteESP8266-2.6.0/keywords.txt @@ -22,21 +22,32 @@ IRArgoAC KEYWORD1 IRCoolixAC KEYWORD1 +IRDaikin2 KEYWORD1 +IRDaikin216 KEYWORD1 IRDaikinESP KEYWORD1 IRFujitsuAC KEYWORD1 IRGreeAC KEYWORD1 IRHaierAC KEYWORD1 IRHaierACYRW02 KEYWORD1 +IRHitachiAc KEYWORD1 IRKelvinatorAC KEYWORD1 IRMideaAC KEYWORD1 IRMitsubishiAC KEYWORD1 +IRMitsubishiHeavy152Ac KEYWORD1 +IRMitsubishiHeavy88Ac KEYWORD1 IRPanasonicAc KEYWORD1 IRSamsungAc KEYWORD1 +IRTcl112Ac KEYWORD1 +IRTecoAc KEYWORD1 IRToshibaAC KEYWORD1 IRTrotecESP KEYWORD1 +IRVestelAc KEYWORD1 +IRWhirlpoolAc KEYWORD1 +IRac KEYWORD1 IRrecv KEYWORD1 IRsend KEYWORD1 IRtimer KEYWORD1 +TimerMs KEYWORD1 decode_results KEYWORD1 ir_params_t KEYWORD1 match_result_t KEYWORD1 @@ -46,8 +57,10 @@ match_result_t KEYWORD1 ####################################### _delayMicroseconds KEYWORD2 +_setMode KEYWORD2 +_setTemp KEYWORD2 add KEYWORD2 -addbit KEYWORD2 +argo KEYWORD2 begin KEYWORD2 buildFromState KEYWORD2 buildState KEYWORD2 @@ -60,18 +73,27 @@ calibrate KEYWORD2 cancelOffTimer KEYWORD2 cancelOnTimer KEYWORD2 cancelTimers KEYWORD2 -checkheader KEYWORD2 +checkZjsSig KEYWORD2 +checkZmsSig KEYWORD2 checksum KEYWORD2 -clearBit KEYWORD2 +clearOnTimerFlag KEYWORD2 clearSensorTemp KEYWORD2 +clearSleepTimerFlag KEYWORD2 compare KEYWORD2 +coolix KEYWORD2 copyIrParams KEYWORD2 +countBits KEYWORD2 +daikin KEYWORD2 +daikin2 KEYWORD2 +daikin216 KEYWORD2 decode KEYWORD2 decodeAiwaRCT501 KEYWORD2 decodeCOOLIX KEYWORD2 decodeCarrierAC KEYWORD2 decodeDISH KEYWORD2 decodeDaikin KEYWORD2 +decodeDaikin2 KEYWORD2 +decodeDaikin216 KEYWORD2 decodeDenon KEYWORD2 decodeElectraAC KEYWORD2 decodeFujitsuAC KEYWORD2 @@ -85,6 +107,7 @@ decodeJVC KEYWORD2 decodeKelvinator KEYWORD2 decodeLG KEYWORD2 decodeLasertag KEYWORD2 +decodeLegoPf KEYWORD2 decodeLutron KEYWORD2 decodeMWM KEYWORD2 decodeMagiQuest KEYWORD2 @@ -92,6 +115,7 @@ decodeMidea KEYWORD2 decodeMitsubishi KEYWORD2 decodeMitsubishi2 KEYWORD2 decodeMitsubishiAC KEYWORD2 +decodeMitsubishiHeavy KEYWORD2 decodeNEC KEYWORD2 decodeNikai KEYWORD2 decodePanasonic KEYWORD2 @@ -101,22 +125,29 @@ decodeRC5 KEYWORD2 decodeRC6 KEYWORD2 decodeRCMM KEYWORD2 decodeSAMSUNG KEYWORD2 +decodeSamsung36 KEYWORD2 decodeSamsungAC KEYWORD2 decodeSanyo KEYWORD2 decodeSanyoLC7461 KEYWORD2 decodeSharp KEYWORD2 decodeSony KEYWORD2 +decodeTcl112Ac KEYWORD2 +decodeTeco KEYWORD2 decodeToshibaAC KEYWORD2 +decodeVestelAc KEYWORD2 decodeWhirlpoolAC KEYWORD2 decodeWhynter KEYWORD2 disableIRIn KEYWORD2 disableOffTimer KEYWORD2 disableOnTimer KEYWORD2 +disableSleepTimer KEYWORD2 elapsed KEYWORD2 enableIRIn KEYWORD2 enableIROut KEYWORD2 enableOffTimer KEYWORD2 enableOnTimer KEYWORD2 +enableSleepTimer KEYWORD2 +enableTimer KEYWORD2 encodeJVC KEYWORD2 encodeLG KEYWORD2 encodeMagiQuest KEYWORD2 @@ -131,15 +162,18 @@ encodeSanyoLC7461 KEYWORD2 encodeSharp KEYWORD2 encodeSony KEYWORD2 encodeTime KEYWORD2 +fanspeed_t KEYWORD2 fixChecksum KEYWORD2 fixup KEYWORD2 +fujitsu KEYWORD2 +get3D KEYWORD2 getBeep KEYWORD2 -getBit KEYWORD2 getBufSize KEYWORD2 getButton KEYWORD2 getClean KEYWORD2 getClock KEYWORD2 getCmd KEYWORD2 +getComfort KEYWORD2 getCommand KEYWORD2 getCoolMode KEYWORD2 getCorrectedRawLength KEYWORD2 @@ -147,11 +181,16 @@ getCurrTime KEYWORD2 getCurrentTime KEYWORD2 getEcono KEYWORD2 getEye KEYWORD2 +getEyeAuto KEYWORD2 getFan KEYWORD2 getFanSpeed KEYWORD2 +getFilter KEYWORD2 getFlap KEYWORD2 +getFreshAir KEYWORD2 +getFreshAirHigh KEYWORD2 getHealth KEYWORD2 getHeatMode KEYWORD2 +getIon KEYWORD2 getIonFilter KEYWORD2 getLed KEYWORD2 getLight KEYWORD2 @@ -159,6 +198,7 @@ getMax KEYWORD2 getMode KEYWORD2 getMold KEYWORD2 getNight KEYWORD2 +getNormalState KEYWORD2 getOffTime KEYWORD2 getOffTimer KEYWORD2 getOffTimerEnabled KEYWORD2 @@ -166,23 +206,30 @@ getOnTime KEYWORD2 getOnTimer KEYWORD2 getOnTimerEnabled KEYWORD2 getPower KEYWORD2 +getPowerToggle KEYWORD2 getPowerful KEYWORD2 +getPurify KEYWORD2 getQuiet KEYWORD2 getRClevel KEYWORD2 getRaw KEYWORD2 getSensor KEYWORD2 getSensorTemp KEYWORD2 +getSilent KEYWORD2 getSleep KEYWORD2 +getSleepTime KEYWORD2 +getSleepTimerEnabled KEYWORD2 getSpeed KEYWORD2 getStartClock KEYWORD2 getStateLength KEYWORD2 getStopClock KEYWORD2 +getSuper KEYWORD2 getSwing KEYWORD2 getSwingHorizontal KEYWORD2 getSwingVertical KEYWORD2 getSwingVerticalAuto KEYWORD2 getSwingVerticalPosition KEYWORD2 getTemp KEYWORD2 +getTempOffset KEYWORD2 getTempRaw KEYWORD2 getTime KEYWORD2 getTimer KEYWORD2 @@ -191,10 +238,23 @@ getVane KEYWORD2 getXFan KEYWORD2 getZoneFollow KEYWORD2 getiFeel KEYWORD2 +gree KEYWORD2 +haier KEYWORD2 +haierYrwo2 KEYWORD2 hasACState KEYWORD2 +hitachi KEYWORD2 +htmlEscape KEYWORD2 invertBits KEYWORD2 +isOffTimerActive KEYWORD2 isOffTimerEnabled KEYWORD2 +isOnTimerActive KEYWORD2 isOnTimerEnabled KEYWORD2 +isProtocolSupported KEYWORD2 +isSpecialState KEYWORD2 +isTimeCommand KEYWORD2 +isTimerActive KEYWORD2 +isTimerEnabled KEYWORD2 +kelvinator KEYWORD2 ledOff KEYWORD2 ledOn KEYWORD2 mark KEYWORD2 @@ -203,10 +263,17 @@ matchAtLeast KEYWORD2 matchData KEYWORD2 matchMark KEYWORD2 matchSpace KEYWORD2 +midea KEYWORD2 +mitsubishi KEYWORD2 +mitsubishiHeavy152 KEYWORD2 +mitsubishiHeavy88 KEYWORD2 +mode) KEYWORD2 off KEYWORD2 on KEYWORD2 -printState KEYWORD2 -readbits KEYWORD2 +opmode_t KEYWORD2 +panasonic KEYWORD2 +position) KEYWORD2 +recoverSavedState KEYWORD2 renderTime KEYWORD2 reset KEYWORD2 resultToHexidecimal KEYWORD2 @@ -215,13 +282,17 @@ resultToSourceCode KEYWORD2 resultToTimingInfo KEYWORD2 resume KEYWORD2 reverseBits KEYWORD2 +samsung KEYWORD2 send KEYWORD2 +sendAc KEYWORD2 sendAiwaRCT501 KEYWORD2 sendArgo KEYWORD2 sendCOOLIX KEYWORD2 sendCarrierAC KEYWORD2 sendDISH KEYWORD2 sendDaikin KEYWORD2 +sendDaikin2 KEYWORD2 +sendDaikin216 KEYWORD2 sendData KEYWORD2 sendDenon KEYWORD2 sendElectraAC KEYWORD2 @@ -241,6 +312,7 @@ sendKelvinator KEYWORD2 sendLG KEYWORD2 sendLG2 KEYWORD2 sendLasertag KEYWORD2 +sendLegoPf KEYWORD2 sendLutron KEYWORD2 sendMWM KEYWORD2 sendMagiQuest KEYWORD2 @@ -248,8 +320,12 @@ sendMidea KEYWORD2 sendMitsubishi KEYWORD2 sendMitsubishi2 KEYWORD2 sendMitsubishiAC KEYWORD2 +sendMitsubishiHeavy152 KEYWORD2 +sendMitsubishiHeavy88 KEYWORD2 sendNEC KEYWORD2 sendNikai KEYWORD2 +sendOff KEYWORD2 +sendOn KEYWORD2 sendPanasonic KEYWORD2 sendPanasonic64 KEYWORD2 sendPanasonicAC KEYWORD2 @@ -260,34 +336,45 @@ sendRC6 KEYWORD2 sendRCMM KEYWORD2 sendRaw KEYWORD2 sendSAMSUNG KEYWORD2 +sendSamsung36 KEYWORD2 sendSamsungAC KEYWORD2 sendSanyoLC7461 KEYWORD2 sendSharp KEYWORD2 sendSharpRaw KEYWORD2 sendSherwood KEYWORD2 sendSony KEYWORD2 +sendTcl112Ac KEYWORD2 +sendTeco KEYWORD2 sendToshibaAC KEYWORD2 sendTrotec KEYWORD2 +sendVestelAc KEYWORD2 sendWhirlpoolAC KEYWORD2 sendWhynter KEYWORD2 serialPrintUint64 KEYWORD2 +set3D KEYWORD2 +setAuto KEYWORD2 setBeep KEYWORD2 -setBit KEYWORD2 setButton KEYWORD2 setClean KEYWORD2 setClock KEYWORD2 setCmd KEYWORD2 +setComfort KEYWORD2 setCommand KEYWORD2 setCoolMode KEYWORD2 setCurrTime KEYWORD2 setCurrentTime KEYWORD2 setEcono KEYWORD2 setEye KEYWORD2 +setEyeAuto KEYWORD2 setFan KEYWORD2 setFanSpeed KEYWORD2 +setFilter KEYWORD2 setFlap KEYWORD2 +setFreshAir KEYWORD2 +setFreshAirHigh KEYWORD2 setHealth KEYWORD2 setHeatMode KEYWORD2 +setIon KEYWORD2 setIonFilter KEYWORD2 setLed KEYWORD2 setLight KEYWORD2 @@ -297,19 +384,25 @@ setModel KEYWORD2 setMold KEYWORD2 setNight KEYWORD2 setOffTimer KEYWORD2 +setOffTimerActive KEYWORD2 setOnTimer KEYWORD2 +setOnTimerActive KEYWORD2 setPower KEYWORD2 +setPowerToggle KEYWORD2 setPowerful KEYWORD2 +setPurify KEYWORD2 setQuiet KEYWORD2 setRaw KEYWORD2 setRoomTemp KEYWORD2 setSensor KEYWORD2 setSensorTemp KEYWORD2 setSensorTempRaw KEYWORD2 +setSilent KEYWORD2 setSleep KEYWORD2 setSpeed KEYWORD2 setStartClock KEYWORD2 setStopClock KEYWORD2 +setSuper KEYWORD2 setSwing KEYWORD2 setSwingHorizontal KEYWORD2 setSwingVertical KEYWORD2 @@ -317,6 +410,7 @@ setTemp KEYWORD2 setTempRaw KEYWORD2 setTime KEYWORD2 setTimer KEYWORD2 +setTimerActive KEYWORD2 setTurbo KEYWORD2 setUnknownThreshold KEYWORD2 setVane KEYWORD2 @@ -324,19 +418,33 @@ setXFan KEYWORD2 setZoneFollow KEYWORD2 setiFeel KEYWORD2 space KEYWORD2 +speed) KEYWORD2 stateReset KEYWORD2 stepHoriz KEYWORD2 stepVert KEYWORD2 +strToBool KEYWORD2 +strToModel KEYWORD2 sumBytes KEYWORD2 +swingh_t KEYWORD2 +swingv) KEYWORD2 +swingv_t KEYWORD2 +tcl112 KEYWORD2 +teco KEYWORD2 ticksHigh KEYWORD2 ticksLow KEYWORD2 timeToString KEYWORD2 toString KEYWORD2 toggleRC5 KEYWORD2 toggleRC6 KEYWORD2 +toshiba KEYWORD2 +trotec KEYWORD2 typeToString KEYWORD2 uint64ToString KEYWORD2 +updateSavedState KEYWORD2 validChecksum KEYWORD2 +vestel KEYWORD2 +whirlpool KEYWORD2 +xorBytes KEYWORD2 ####################################### # Constants (LITERAL1) @@ -349,9 +457,9 @@ ARDB1 LITERAL1 ARGO LITERAL1 ARGO_COMMAND_LENGTH LITERAL1 ARGO_COOL_AUTO LITERAL1 +ARGO_COOL_HUM LITERAL1 ARGO_COOL_OFF LITERAL1 ARGO_COOL_ON LITERAL1 -ARGO_COOl_HUM LITERAL1 ARGO_FAN_1 LITERAL1 ARGO_FAN_2 LITERAL1 ARGO_FAN_3 LITERAL1 @@ -375,10 +483,11 @@ CARRIER_AC_BITS LITERAL1 COOLIX LITERAL1 COOLIX_BITS LITERAL1 DAIKIN LITERAL1 +DAIKIN2 LITERAL1 +DAIKIN216 LITERAL1 DAIKIN_AUTO LITERAL1 DAIKIN_COMMAND_LENGTH LITERAL1 DAIKIN_COOL LITERAL1 -DAIKIN_DEBUG LITERAL1 DAIKIN_DRY LITERAL1 DAIKIN_FAN LITERAL1 DAIKIN_FAN_AUTO LITERAL1 @@ -394,6 +503,8 @@ DECODE_ARGO LITERAL1 DECODE_CARRIER_AC LITERAL1 DECODE_COOLIX LITERAL1 DECODE_DAIKIN LITERAL1 +DECODE_DAIKIN2 LITERAL1 +DECODE_DAIKIN216 LITERAL1 DECODE_DENON LITERAL1 DECODE_DISH LITERAL1 DECODE_ELECTRA_AC LITERAL1 @@ -410,12 +521,14 @@ DECODE_HITACHI_AC2 LITERAL1 DECODE_JVC LITERAL1 DECODE_KELVINATOR LITERAL1 DECODE_LASERTAG LITERAL1 +DECODE_LEGOPF LITERAL1 DECODE_LG LITERAL1 DECODE_LUTRON LITERAL1 DECODE_MAGIQUEST LITERAL1 DECODE_MIDEA LITERAL1 DECODE_MITSUBISHI LITERAL1 DECODE_MITSUBISHI2 LITERAL1 +DECODE_MITSUBISHIHEAVY LITERAL1 DECODE_MITSUBISHI_AC LITERAL1 DECODE_MWM LITERAL1 DECODE_NEC LITERAL1 @@ -428,19 +541,25 @@ DECODE_RC5 LITERAL1 DECODE_RC6 LITERAL1 DECODE_RCMM LITERAL1 DECODE_SAMSUNG LITERAL1 +DECODE_SAMSUNG36 LITERAL1 DECODE_SAMSUNG_AC LITERAL1 DECODE_SANYO LITERAL1 DECODE_SHARP LITERAL1 DECODE_SHERWOOD LITERAL1 DECODE_SONY LITERAL1 +DECODE_TCL112AC LITERAL1 +DECODE_TECO LITERAL1 DECODE_TOSHIBA_AC LITERAL1 DECODE_TROTEC LITERAL1 +DECODE_VESTEL_AC LITERAL1 DECODE_WHIRLPOOL_AC LITERAL1 DECODE_WHYNTER LITERAL1 DENON LITERAL1 DENON_48_BITS LITERAL1 DENON_BITS LITERAL1 DENON_LEGACY_BITS LITERAL1 +DG11J13A LITERAL1 +DG11J191 LITERAL1 DISH LITERAL1 DISH_BITS LITERAL1 ELECTRA_AC LITERAL1 @@ -580,6 +699,7 @@ KELVINATOR_MIN_TEMP LITERAL1 KELVINATOR_STATE_LENGTH LITERAL1 LASERTAG LITERAL1 LASERTAG_BITS LITERAL1 +LEGOPF LITERAL1 LG LITERAL1 LG2 LITERAL1 LG32_BITS LITERAL1 @@ -623,6 +743,8 @@ MITSUBISHI_AC_STATE_LENGTH LITERAL1 MITSUBISHI_AC_VANE_AUTO LITERAL1 MITSUBISHI_AC_VANE_AUTO_MOVE LITERAL1 MITSUBISHI_BITS LITERAL1 +MITSUBISHI_HEAVY_152 LITERAL1 +MITSUBISHI_HEAVY_88 LITERAL1 MWM LITERAL1 NEC LITERAL1 NEC_BITS LITERAL1 @@ -647,6 +769,7 @@ RC6_MODE0_BITS LITERAL1 RCMM LITERAL1 RCMM_BITS LITERAL1 SAMSUNG LITERAL1 +SAMSUNG36 LITERAL1 SAMSUNG_AC LITERAL1 SAMSUNG_BITS LITERAL1 SANYO LITERAL1 @@ -658,6 +781,8 @@ SEND_ARGO LITERAL1 SEND_CARRIER_AC LITERAL1 SEND_COOLIX LITERAL1 SEND_DAIKIN LITERAL1 +SEND_DAIKIN2 LITERAL1 +SEND_DAIKIN216 LITERAL1 SEND_DENON LITERAL1 SEND_DISH LITERAL1 SEND_ELECTRA_AC LITERAL1 @@ -673,12 +798,14 @@ SEND_HITACHI_AC2 LITERAL1 SEND_JVC LITERAL1 SEND_KELVINATOR LITERAL1 SEND_LASERTAG LITERAL1 +SEND_LEGOPF LITERAL1 SEND_LG LITERAL1 SEND_LUTRON LITERAL1 SEND_MAGIQUEST LITERAL1 SEND_MIDEA LITERAL1 SEND_MITSUBISHI LITERAL1 SEND_MITSUBISHI2 LITERAL1 +SEND_MITSUBISHIHEAVY LITERAL1 SEND_MITSUBISHI_AC LITERAL1 SEND_MWM LITERAL1 SEND_NEC LITERAL1 @@ -692,13 +819,17 @@ SEND_RC5 LITERAL1 SEND_RC6 LITERAL1 SEND_RCMM LITERAL1 SEND_SAMSUNG LITERAL1 +SEND_SAMSUNG36 LITERAL1 SEND_SAMSUNG_AC LITERAL1 SEND_SANYO LITERAL1 SEND_SHARP LITERAL1 SEND_SHERWOOD LITERAL1 SEND_SONY LITERAL1 +SEND_TCL112AC LITERAL1 +SEND_TECO LITERAL1 SEND_TOSHIBA_AC LITERAL1 SEND_TROTEC LITERAL1 +SEND_VESTEL_AC LITERAL1 SEND_WHIRLPOOL_AC LITERAL1 SEND_WHYNTER LITERAL1 SHARP LITERAL1 @@ -709,6 +840,8 @@ SONY LITERAL1 SONY_12_BITS LITERAL1 SONY_15_BITS LITERAL1 SONY_20_BITS LITERAL1 +TCL112AC LITERAL1 +TECO LITERAL1 TIMEOUT_MS LITERAL1 TOSHIBA_AC LITERAL1 TOSHIBA_AC_AUTO LITERAL1 @@ -733,9 +866,9 @@ TROTEC_FAN_MED LITERAL1 TROTEC_MAX_TEMP LITERAL1 TROTEC_MAX_TIMER LITERAL1 TROTEC_MIN_TEMP LITERAL1 -TROTEC_MIN_TIMER LITERAL1 UNKNOWN LITERAL1 UNUSED LITERAL1 +VESTEL_AC LITERAL1 WHIRLPOOL_AC LITERAL1 WHYNTER LITERAL1 WHYNTER_BITS LITERAL1 @@ -750,6 +883,7 @@ kArgoCoolAuto LITERAL1 kArgoCoolHum LITERAL1 kArgoCoolOff LITERAL1 kArgoCoolOn LITERAL1 +kArgoDefaultRepeat LITERAL1 kArgoFan1 LITERAL1 kArgoFan2 LITERAL1 kArgoFan3 LITERAL1 @@ -772,6 +906,7 @@ kArgoMinTemp LITERAL1 kArgoOneSpace LITERAL1 kArgoStateLength LITERAL1 kArgoZeroSpace LITERAL1 +kAuto LITERAL1 kCarrierAcBitMark LITERAL1 kCarrierAcBits LITERAL1 kCarrierAcGap LITERAL1 @@ -780,16 +915,19 @@ kCarrierAcHdrSpace LITERAL1 kCarrierAcMinRepeat LITERAL1 kCarrierAcOneSpace LITERAL1 kCarrierAcZeroSpace LITERAL1 +kCool LITERAL1 kCoolixAuto LITERAL1 kCoolixBitMark LITERAL1 kCoolixBitMarkTicks LITERAL1 kCoolixBits LITERAL1 kCoolixClean LITERAL1 kCoolixCool LITERAL1 +kCoolixDefaultRepeat LITERAL1 kCoolixDefaultState LITERAL1 kCoolixDry LITERAL1 kCoolixFan LITERAL1 kCoolixFanAuto LITERAL1 +kCoolixFanAuto0 LITERAL1 kCoolixFanFixed LITERAL1 kCoolixFanMask LITERAL1 kCoolixFanMax LITERAL1 @@ -827,7 +965,70 @@ kCoolixUnknown LITERAL1 kCoolixZeroSpace LITERAL1 kCoolixZeroSpaceTicks LITERAL1 kCoolixZoneFollowMask LITERAL1 +kDaikin216BitMark LITERAL1 +kDaikin216Bits LITERAL1 +kDaikin216ByteFan LITERAL1 +kDaikin216ByteMode LITERAL1 +kDaikin216BytePower LITERAL1 +kDaikin216ByteSwingH LITERAL1 +kDaikin216ByteSwingV LITERAL1 +kDaikin216ByteTemp LITERAL1 +kDaikin216DefaultRepeat LITERAL1 +kDaikin216Freq LITERAL1 +kDaikin216Gap LITERAL1 +kDaikin216HdrMark LITERAL1 +kDaikin216HdrSpace LITERAL1 +kDaikin216MaskFan LITERAL1 +kDaikin216MaskMode LITERAL1 +kDaikin216MaskSwingH LITERAL1 +kDaikin216MaskSwingV LITERAL1 +kDaikin216MaskTemp LITERAL1 +kDaikin216OneSpace LITERAL1 +kDaikin216Section1Length LITERAL1 +kDaikin216Section2Length LITERAL1 +kDaikin216Sections LITERAL1 +kDaikin216StateLength LITERAL1 +kDaikin216ZeroSpace LITERAL1 +kDaikin2BeepMask LITERAL1 +kDaikin2BitClean LITERAL1 +kDaikin2BitEye LITERAL1 +kDaikin2BitEyeAuto LITERAL1 +kDaikin2BitFreshAir LITERAL1 +kDaikin2BitFreshAirHigh LITERAL1 +kDaikin2BitMark LITERAL1 +kDaikin2BitMold LITERAL1 +kDaikin2BitPower LITERAL1 +kDaikin2BitPurify LITERAL1 +kDaikin2BitSleepTimer LITERAL1 +kDaikin2Bits LITERAL1 +kDaikin2DefaultRepeat LITERAL1 +kDaikin2Freq LITERAL1 +kDaikin2Gap LITERAL1 +kDaikin2HdrMark LITERAL1 +kDaikin2HdrSpace LITERAL1 +kDaikin2LeaderMark LITERAL1 +kDaikin2LeaderSpace LITERAL1 +kDaikin2LightMask LITERAL1 +kDaikin2MinCoolTemp LITERAL1 +kDaikin2OneSpace LITERAL1 +kDaikin2Section1Length LITERAL1 +kDaikin2Section2Length LITERAL1 +kDaikin2Sections LITERAL1 +kDaikin2StateLength LITERAL1 +kDaikin2SwingHAuto LITERAL1 +kDaikin2SwingHSwing LITERAL1 +kDaikin2SwingVAuto LITERAL1 +kDaikin2SwingVBreeze LITERAL1 +kDaikin2SwingVCirculate LITERAL1 +kDaikin2SwingVHigh LITERAL1 +kDaikin2SwingVLow LITERAL1 +kDaikin2Tolerance LITERAL1 +kDaikin2ZeroSpace LITERAL1 kDaikinAuto LITERAL1 +kDaikinBeepLoud LITERAL1 +kDaikinBeepOff LITERAL1 +kDaikinBeepQuiet LITERAL1 +kDaikinBitComfort LITERAL1 kDaikinBitEcono LITERAL1 kDaikinBitEye LITERAL1 kDaikinBitMark LITERAL1 @@ -839,18 +1040,33 @@ kDaikinBitPowerful LITERAL1 kDaikinBitSensor LITERAL1 kDaikinBitSilent LITERAL1 kDaikinBits LITERAL1 +kDaikinBitsShort LITERAL1 +kDaikinByteChecksum1 LITERAL1 +kDaikinByteChecksum2 LITERAL1 +kDaikinByteChecksum3 LITERAL1 +kDaikinByteClockMinsHigh LITERAL1 +kDaikinByteClockMinsLow LITERAL1 +kDaikinByteComfort LITERAL1 kDaikinByteEcono LITERAL1 kDaikinByteEye LITERAL1 +kDaikinByteFan LITERAL1 kDaikinByteMold LITERAL1 kDaikinByteOffTimer LITERAL1 +kDaikinByteOffTimerMinsHigh LITERAL1 +kDaikinByteOffTimerMinsLow LITERAL1 kDaikinByteOnTimer LITERAL1 +kDaikinByteOnTimerMinsHigh LITERAL1 +kDaikinByteOnTimerMinsLow LITERAL1 kDaikinBytePower LITERAL1 kDaikinBytePowerful LITERAL1 kDaikinByteSensor LITERAL1 kDaikinByteSilent LITERAL1 +kDaikinByteSwingH LITERAL1 +kDaikinByteTemp LITERAL1 kDaikinCool LITERAL1 kDaikinCurBit LITERAL1 kDaikinCurIndex LITERAL1 +kDaikinDefaultRepeat LITERAL1 kDaikinDry LITERAL1 kDaikinFan LITERAL1 kDaikinFanAuto LITERAL1 @@ -861,15 +1077,25 @@ kDaikinFirstHeader64 LITERAL1 kDaikinGap LITERAL1 kDaikinHdrMark LITERAL1 kDaikinHdrSpace LITERAL1 +kDaikinHeaderLength LITERAL1 kDaikinHeat LITERAL1 +kDaikinLightBright LITERAL1 +kDaikinLightDim LITERAL1 +kDaikinLightOff LITERAL1 kDaikinMarkExcess LITERAL1 kDaikinMaxTemp LITERAL1 kDaikinMinTemp LITERAL1 kDaikinOneSpace LITERAL1 -kDaikinRawBits LITERAL1 +kDaikinSection1Length LITERAL1 +kDaikinSection2Length LITERAL1 +kDaikinSection3Length LITERAL1 +kDaikinSections LITERAL1 kDaikinStateLength LITERAL1 +kDaikinStateLengthShort LITERAL1 kDaikinTolerance LITERAL1 +kDaikinUnusedTime LITERAL1 kDaikinZeroSpace LITERAL1 +kDefaultMessageGap LITERAL1 kDenonBitMark LITERAL1 kDenonBitMarkTicks LITERAL1 kDenonBits LITERAL1 @@ -902,6 +1128,7 @@ kDishRptSpaceTicks LITERAL1 kDishTick LITERAL1 kDishZeroSpace LITERAL1 kDishZeroSpaceTicks LITERAL1 +kDry LITERAL1 kDutyDefault LITERAL1 kDutyMax LITERAL1 kElectraAcBitMark LITERAL1 @@ -912,6 +1139,7 @@ kElectraAcMessageGap LITERAL1 kElectraAcOneSpace LITERAL1 kElectraAcStateLength LITERAL1 kElectraAcZeroSpace LITERAL1 +kFan LITERAL1 kFnvBasis32 LITERAL1 kFnvPrime32 LITERAL1 kFooter LITERAL1 @@ -969,10 +1197,13 @@ kGreeBits LITERAL1 kGreeBlockFooter LITERAL1 kGreeBlockFooterBits LITERAL1 kGreeCool LITERAL1 +kGreeDefaultRepeat LITERAL1 kGreeDry LITERAL1 kGreeFan LITERAL1 +kGreeFanAuto LITERAL1 kGreeFanMask LITERAL1 kGreeFanMax LITERAL1 +kGreeFanMin LITERAL1 kGreeHdrMark LITERAL1 kGreeHdrSpace LITERAL1 kGreeHeat LITERAL1 @@ -1020,6 +1251,7 @@ kHaierAcCmdTimerCancel LITERAL1 kHaierAcCmdTimerSet LITERAL1 kHaierAcCool LITERAL1 kHaierAcDefTemp LITERAL1 +kHaierAcDefaultRepeat LITERAL1 kHaierAcDry LITERAL1 kHaierAcFan LITERAL1 kHaierAcFanAuto LITERAL1 @@ -1050,6 +1282,7 @@ kHaierAcYrw02ButtonTempDown LITERAL1 kHaierAcYrw02ButtonTempUp LITERAL1 kHaierAcYrw02ButtonTurbo LITERAL1 kHaierAcYrw02Cool LITERAL1 +kHaierAcYrw02DefaultRepeat LITERAL1 kHaierAcYrw02Dry LITERAL1 kHaierAcYrw02Fan LITERAL1 kHaierAcYrw02FanAuto LITERAL1 @@ -1071,17 +1304,32 @@ kHaierAcYrw02TurboLow LITERAL1 kHaierAcYrw02TurboOff LITERAL1 kHaierAcZeroSpace LITERAL1 kHeader LITERAL1 +kHeat LITERAL1 +kHigh LITERAL1 +kHighest LITERAL1 kHitachiAc1Bits LITERAL1 kHitachiAc1HdrMark LITERAL1 kHitachiAc1HdrSpace LITERAL1 kHitachiAc1StateLength LITERAL1 kHitachiAc2Bits LITERAL1 kHitachiAc2StateLength LITERAL1 +kHitachiAcAuto LITERAL1 +kHitachiAcAutoTemp LITERAL1 kHitachiAcBitMark LITERAL1 kHitachiAcBits LITERAL1 +kHitachiAcCool LITERAL1 +kHitachiAcDefaultRepeat LITERAL1 +kHitachiAcDry LITERAL1 +kHitachiAcFan LITERAL1 +kHitachiAcFanAuto LITERAL1 +kHitachiAcFanHigh LITERAL1 +kHitachiAcFanLow LITERAL1 kHitachiAcHdrMark LITERAL1 kHitachiAcHdrSpace LITERAL1 +kHitachiAcHeat LITERAL1 +kHitachiAcMaxTemp LITERAL1 kHitachiAcMinGap LITERAL1 +kHitachiAcMinTemp LITERAL1 kHitachiAcOneSpace LITERAL1 kHitachiAcStateLength LITERAL1 kHitachiAcZeroSpace LITERAL1 @@ -1113,6 +1361,7 @@ kKelvinatorChecksumStart LITERAL1 kKelvinatorCmdFooter LITERAL1 kKelvinatorCmdFooterBits LITERAL1 kKelvinatorCool LITERAL1 +kKelvinatorDefaultRepeat LITERAL1 kKelvinatorDry LITERAL1 kKelvinatorFan LITERAL1 kKelvinatorFanAuto LITERAL1 @@ -1159,6 +1408,16 @@ kLasertagMinRepeat LITERAL1 kLasertagMinSamples LITERAL1 kLasertagTick LITERAL1 kLasertagTolerance LITERAL1 +kLastDecodeType LITERAL1 +kLeft LITERAL1 +kLeftMax LITERAL1 +kLegoPfBitMark LITERAL1 +kLegoPfBits LITERAL1 +kLegoPfHdrSpace LITERAL1 +kLegoPfMinCommandLength LITERAL1 +kLegoPfMinRepeat LITERAL1 +kLegoPfOneSpace LITERAL1 +kLegoPfZeroSpace LITERAL1 kLg2BitMark LITERAL1 kLg2BitMarkTicks LITERAL1 kLg2HdrMark LITERAL1 @@ -1190,6 +1449,8 @@ kLgRptSpaceTicks LITERAL1 kLgTick LITERAL1 kLgZeroSpace LITERAL1 kLgZeroSpaceTicks LITERAL1 +kLow LITERAL1 +kLowest LITERAL1 kLutronBits LITERAL1 kLutronDelta LITERAL1 kLutronGap LITERAL1 @@ -1213,8 +1474,11 @@ kMagiquestBits LITERAL1 kMark LITERAL1 kMarkExcess LITERAL1 kMarkState LITERAL1 +kMax LITERAL1 kMaxAccurateUsecDelay LITERAL1 kMaxTimeoutMs LITERAL1 +kMedium LITERAL1 +kMiddle LITERAL1 kMideaACAuto LITERAL1 kMideaACChecksumMask LITERAL1 kMideaACCool LITERAL1 @@ -1251,6 +1515,7 @@ kMideaTick LITERAL1 kMideaTolerance LITERAL1 kMideaZeroSpace LITERAL1 kMideaZeroSpaceTicks LITERAL1 +kMin LITERAL1 kMitsubishi2BitMark LITERAL1 kMitsubishi2HdrMark LITERAL1 kMitsubishi2HdrSpace LITERAL1 @@ -1287,6 +1552,91 @@ kMitsubishiAcZeroSpace LITERAL1 kMitsubishiBitMark LITERAL1 kMitsubishiBitMarkTicks LITERAL1 kMitsubishiBits LITERAL1 +kMitsubishiHeavy152Bits LITERAL1 +kMitsubishiHeavy152FanAuto LITERAL1 +kMitsubishiHeavy152FanEcono LITERAL1 +kMitsubishiHeavy152FanHigh LITERAL1 +kMitsubishiHeavy152FanLow LITERAL1 +kMitsubishiHeavy152FanMax LITERAL1 +kMitsubishiHeavy152FanMed LITERAL1 +kMitsubishiHeavy152FanTurbo LITERAL1 +kMitsubishiHeavy152MinRepeat LITERAL1 +kMitsubishiHeavy152StateLength LITERAL1 +kMitsubishiHeavy152SwingHAuto LITERAL1 +kMitsubishiHeavy152SwingHLeft LITERAL1 +kMitsubishiHeavy152SwingHLeftMax LITERAL1 +kMitsubishiHeavy152SwingHLeftRight LITERAL1 +kMitsubishiHeavy152SwingHMask LITERAL1 +kMitsubishiHeavy152SwingHMiddle LITERAL1 +kMitsubishiHeavy152SwingHOff LITERAL1 +kMitsubishiHeavy152SwingHRight LITERAL1 +kMitsubishiHeavy152SwingHRightLeft LITERAL1 +kMitsubishiHeavy152SwingHRightMax LITERAL1 +kMitsubishiHeavy152SwingVAuto LITERAL1 +kMitsubishiHeavy152SwingVHigh LITERAL1 +kMitsubishiHeavy152SwingVHighest LITERAL1 +kMitsubishiHeavy152SwingVLow LITERAL1 +kMitsubishiHeavy152SwingVLowest LITERAL1 +kMitsubishiHeavy152SwingVMask LITERAL1 +kMitsubishiHeavy152SwingVMiddle LITERAL1 +kMitsubishiHeavy152SwingVOff LITERAL1 +kMitsubishiHeavy3DMask LITERAL1 +kMitsubishiHeavy88Bits LITERAL1 +kMitsubishiHeavy88CleanBit LITERAL1 +kMitsubishiHeavy88FanAuto LITERAL1 +kMitsubishiHeavy88FanEcono LITERAL1 +kMitsubishiHeavy88FanHigh LITERAL1 +kMitsubishiHeavy88FanLow LITERAL1 +kMitsubishiHeavy88FanMask LITERAL1 +kMitsubishiHeavy88FanMed LITERAL1 +kMitsubishiHeavy88FanTurbo LITERAL1 +kMitsubishiHeavy88MinRepeat LITERAL1 +kMitsubishiHeavy88StateLength LITERAL1 +kMitsubishiHeavy88SwingH3D LITERAL1 +kMitsubishiHeavy88SwingHAuto LITERAL1 +kMitsubishiHeavy88SwingHLeft LITERAL1 +kMitsubishiHeavy88SwingHLeftMax LITERAL1 +kMitsubishiHeavy88SwingHLeftRight LITERAL1 +kMitsubishiHeavy88SwingHMask LITERAL1 +kMitsubishiHeavy88SwingHMiddle LITERAL1 +kMitsubishiHeavy88SwingHOff LITERAL1 +kMitsubishiHeavy88SwingHRight LITERAL1 +kMitsubishiHeavy88SwingHRightLeft LITERAL1 +kMitsubishiHeavy88SwingHRightMax LITERAL1 +kMitsubishiHeavy88SwingVAuto LITERAL1 +kMitsubishiHeavy88SwingVHigh LITERAL1 +kMitsubishiHeavy88SwingVHighest LITERAL1 +kMitsubishiHeavy88SwingVLow LITERAL1 +kMitsubishiHeavy88SwingVLowest LITERAL1 +kMitsubishiHeavy88SwingVMask LITERAL1 +kMitsubishiHeavy88SwingVMaskByte5 LITERAL1 +kMitsubishiHeavy88SwingVMaskByte7 LITERAL1 +kMitsubishiHeavy88SwingVMiddle LITERAL1 +kMitsubishiHeavy88SwingVOff LITERAL1 +kMitsubishiHeavyAuto LITERAL1 +kMitsubishiHeavyBitMark LITERAL1 +kMitsubishiHeavyCleanBit LITERAL1 +kMitsubishiHeavyCool LITERAL1 +kMitsubishiHeavyDry LITERAL1 +kMitsubishiHeavyFan LITERAL1 +kMitsubishiHeavyFanMask LITERAL1 +kMitsubishiHeavyFilterBit LITERAL1 +kMitsubishiHeavyGap LITERAL1 +kMitsubishiHeavyHdrMark LITERAL1 +kMitsubishiHeavyHdrSpace LITERAL1 +kMitsubishiHeavyHeat LITERAL1 +kMitsubishiHeavyMaxTemp LITERAL1 +kMitsubishiHeavyMinTemp LITERAL1 +kMitsubishiHeavyModeMask LITERAL1 +kMitsubishiHeavyNightBit LITERAL1 +kMitsubishiHeavyOneSpace LITERAL1 +kMitsubishiHeavyPowerBit LITERAL1 +kMitsubishiHeavySigLength LITERAL1 +kMitsubishiHeavySilentBit LITERAL1 +kMitsubishiHeavyTempMask LITERAL1 +kMitsubishiHeavyZeroSpace LITERAL1 +kMitsubishiHeavyZjsSig LITERAL1 +kMitsubishiHeavyZmsSig LITERAL1 kMitsubishiMinCommandLength LITERAL1 kMitsubishiMinCommandLengthTicks LITERAL1 kMitsubishiMinGap LITERAL1 @@ -1331,10 +1681,12 @@ kNikaiTick LITERAL1 kNikaiZeroSpace LITERAL1 kNikaiZeroSpaceTicks LITERAL1 kNoRepeat LITERAL1 +kOff LITERAL1 kPanasonicAcAuto LITERAL1 kPanasonicAcBits LITERAL1 kPanasonicAcChecksumInit LITERAL1 kPanasonicAcCool LITERAL1 +kPanasonicAcDefaultRepeat LITERAL1 kPanasonicAcDry LITERAL1 kPanasonicAcExcess LITERAL1 kPanasonicAcFan LITERAL1 @@ -1393,6 +1745,7 @@ kPanasonicMinGapTicks LITERAL1 kPanasonicNke LITERAL1 kPanasonicOneSpace LITERAL1 kPanasonicOneSpaceTicks LITERAL1 +kPanasonicRkr LITERAL1 kPanasonicTick LITERAL1 kPanasonicUnknown LITERAL1 kPanasonicZeroSpace LITERAL1 @@ -1450,6 +1803,9 @@ kRcmmRptLengthTicks LITERAL1 kRcmmTick LITERAL1 kRcmmTolerance LITERAL1 kRepeat LITERAL1 +kRight LITERAL1 +kRightMax LITERAL1 +kSamsung36Bits LITERAL1 kSamsungACSectionLength LITERAL1 kSamsungAcAuto LITERAL1 kSamsungAcAutoTemp LITERAL1 @@ -1459,6 +1815,7 @@ kSamsungAcBits LITERAL1 kSamsungAcCleanMask10 LITERAL1 kSamsungAcCleanMask11 LITERAL1 kSamsungAcCool LITERAL1 +kSamsungAcDefaultRepeat LITERAL1 kSamsungAcDry LITERAL1 kSamsungAcExtendedBits LITERAL1 kSamsungAcExtendedStateLength LITERAL1 @@ -1569,6 +1926,65 @@ kSpaceState LITERAL1 kStartOffset LITERAL1 kStateSizeMax LITERAL1 kStopState LITERAL1 +kTcl112AcAuto LITERAL1 +kTcl112AcBitEcono LITERAL1 +kTcl112AcBitHealth LITERAL1 +kTcl112AcBitLight LITERAL1 +kTcl112AcBitMark LITERAL1 +kTcl112AcBitSwingH LITERAL1 +kTcl112AcBitSwingV LITERAL1 +kTcl112AcBitTurbo LITERAL1 +kTcl112AcBits LITERAL1 +kTcl112AcCool LITERAL1 +kTcl112AcDefaultRepeat LITERAL1 +kTcl112AcDry LITERAL1 +kTcl112AcFan LITERAL1 +kTcl112AcFanAuto LITERAL1 +kTcl112AcFanHigh LITERAL1 +kTcl112AcFanLow LITERAL1 +kTcl112AcFanMask LITERAL1 +kTcl112AcFanMed LITERAL1 +kTcl112AcGap LITERAL1 +kTcl112AcHalfDegree LITERAL1 +kTcl112AcHdrMark LITERAL1 +kTcl112AcHdrSpace LITERAL1 +kTcl112AcHeat LITERAL1 +kTcl112AcOneSpace LITERAL1 +kTcl112AcPowerMask LITERAL1 +kTcl112AcStateLength LITERAL1 +kTcl112AcTempMax LITERAL1 +kTcl112AcTempMin LITERAL1 +kTcl112AcZeroSpace LITERAL1 +kTecoAuto LITERAL1 +kTecoBitMark LITERAL1 +kTecoBits LITERAL1 +kTecoCool LITERAL1 +kTecoDefaultRepeat LITERAL1 +kTecoDry LITERAL1 +kTecoFan LITERAL1 +kTecoFanAuto LITERAL1 +kTecoFanHigh LITERAL1 +kTecoFanLow LITERAL1 +kTecoFanMask LITERAL1 +kTecoFanMed LITERAL1 +kTecoGap LITERAL1 +kTecoHdrMark LITERAL1 +kTecoHdrSpace LITERAL1 +kTecoHeat LITERAL1 +kTecoMaxTemp LITERAL1 +kTecoMinTemp LITERAL1 +kTecoModeMask LITERAL1 +kTecoOneSpace LITERAL1 +kTecoPower LITERAL1 +kTecoReset LITERAL1 +kTecoSleep LITERAL1 +kTecoSwing LITERAL1 +kTecoTempMask LITERAL1 +kTecoTimerHalfH LITERAL1 +kTecoTimerOn LITERAL1 +kTecoTimerTenHr LITERAL1 +kTecoTimerUniHr LITERAL1 +kTecoZeroSpace LITERAL1 kTimeoutMs LITERAL1 kTolerance LITERAL1 kToshibaACBits LITERAL1 @@ -1592,6 +2008,7 @@ kToshibaAcZeroSpace LITERAL1 kTrotecAuto LITERAL1 kTrotecCool LITERAL1 kTrotecDefTemp LITERAL1 +kTrotecDefaultRepeat LITERAL1 kTrotecDry LITERAL1 kTrotecFan LITERAL1 kTrotecFanHigh LITERAL1 @@ -1606,26 +2023,119 @@ kTrotecIntro2 LITERAL1 kTrotecMaxTemp LITERAL1 kTrotecMaxTimer LITERAL1 kTrotecMinTemp LITERAL1 -kTrotecMinTimer LITERAL1 -kTrotecOff LITERAL1 -kTrotecOn LITERAL1 kTrotecOneMark LITERAL1 kTrotecOneSpace LITERAL1 -kTrotecSleepOn LITERAL1 +kTrotecPowerBit LITERAL1 +kTrotecSleepBit LITERAL1 kTrotecStateLength LITERAL1 -kTrotecTimerOn LITERAL1 +kTrotecTimerBit LITERAL1 kTrotecZeroMark LITERAL1 kTrotecZeroSpace LITERAL1 kUnknownThreshold LITERAL1 +kVestelAcAuto LITERAL1 +kVestelAcBitMark LITERAL1 +kVestelAcBits LITERAL1 +kVestelAcCRCMask LITERAL1 +kVestelAcChecksumOffset LITERAL1 +kVestelAcCool LITERAL1 +kVestelAcDry LITERAL1 +kVestelAcFan LITERAL1 +kVestelAcFanAuto LITERAL1 +kVestelAcFanAutoCool LITERAL1 +kVestelAcFanAutoHot LITERAL1 +kVestelAcFanHigh LITERAL1 +kVestelAcFanLow LITERAL1 +kVestelAcFanMed LITERAL1 +kVestelAcFanOffset LITERAL1 +kVestelAcHdrMark LITERAL1 +kVestelAcHdrSpace LITERAL1 +kVestelAcHeat LITERAL1 +kVestelAcHourOffset LITERAL1 +kVestelAcIon LITERAL1 +kVestelAcIonOffset LITERAL1 +kVestelAcMaxTemp LITERAL1 +kVestelAcMinTempC LITERAL1 +kVestelAcMinTempH LITERAL1 +kVestelAcMinuteOffset LITERAL1 +kVestelAcModeOffset LITERAL1 +kVestelAcNormal LITERAL1 +kVestelAcOffTimeOffset LITERAL1 +kVestelAcOffTimerFlagOffset LITERAL1 +kVestelAcOnTimeOffset LITERAL1 +kVestelAcOnTimerFlagOffset LITERAL1 +kVestelAcOneSpace LITERAL1 +kVestelAcPowerOffset LITERAL1 +kVestelAcSleep LITERAL1 +kVestelAcStateDefault LITERAL1 +kVestelAcSwing LITERAL1 +kVestelAcSwingOffset LITERAL1 +kVestelAcTempOffset LITERAL1 +kVestelAcTimeStateDefault LITERAL1 +kVestelAcTimerFlagOffset LITERAL1 +kVestelAcTolerance LITERAL1 +kVestelAcTurbo LITERAL1 +kVestelAcTurboSleepOffset LITERAL1 +kVestelAcZeroSpace LITERAL1 +kWhirlpoolAcAltTempMask LITERAL1 +kWhirlpoolAcAltTempPos LITERAL1 +kWhirlpoolAcAuto LITERAL1 +kWhirlpoolAcAutoTemp LITERAL1 kWhirlpoolAcBitMark LITERAL1 kWhirlpoolAcBits LITERAL1 +kWhirlpoolAcChecksumByte1 LITERAL1 +kWhirlpoolAcChecksumByte2 LITERAL1 +kWhirlpoolAcClockPos LITERAL1 +kWhirlpoolAcCommand6thSense LITERAL1 +kWhirlpoolAcCommandFanSpeed LITERAL1 +kWhirlpoolAcCommandIFeel LITERAL1 +kWhirlpoolAcCommandLight LITERAL1 +kWhirlpoolAcCommandMode LITERAL1 +kWhirlpoolAcCommandOffTimer LITERAL1 +kWhirlpoolAcCommandOnTimer LITERAL1 +kWhirlpoolAcCommandPos LITERAL1 +kWhirlpoolAcCommandPower LITERAL1 +kWhirlpoolAcCommandSleep LITERAL1 +kWhirlpoolAcCommandSuper LITERAL1 +kWhirlpoolAcCommandSwing LITERAL1 +kWhirlpoolAcCommandTemp LITERAL1 +kWhirlpoolAcCool LITERAL1 +kWhirlpoolAcDefaultRepeat LITERAL1 +kWhirlpoolAcDry LITERAL1 +kWhirlpoolAcFan LITERAL1 +kWhirlpoolAcFanAuto LITERAL1 +kWhirlpoolAcFanHigh LITERAL1 +kWhirlpoolAcFanLow LITERAL1 +kWhirlpoolAcFanMask LITERAL1 +kWhirlpoolAcFanMedium LITERAL1 +kWhirlpoolAcFanPos LITERAL1 kWhirlpoolAcGap LITERAL1 kWhirlpoolAcHdrMark LITERAL1 kWhirlpoolAcHdrSpace LITERAL1 +kWhirlpoolAcHeat LITERAL1 +kWhirlpoolAcHourMask LITERAL1 +kWhirlpoolAcLightMask LITERAL1 +kWhirlpoolAcMaxTemp LITERAL1 kWhirlpoolAcMinGap LITERAL1 +kWhirlpoolAcMinTemp LITERAL1 +kWhirlpoolAcMinuteMask LITERAL1 +kWhirlpoolAcModeMask LITERAL1 +kWhirlpoolAcModePos LITERAL1 +kWhirlpoolAcOffTimerPos LITERAL1 +kWhirlpoolAcOnTimerPos LITERAL1 kWhirlpoolAcOneSpace LITERAL1 +kWhirlpoolAcPowerToggleMask LITERAL1 +kWhirlpoolAcPowerTogglePos LITERAL1 kWhirlpoolAcSections LITERAL1 +kWhirlpoolAcSleepMask LITERAL1 +kWhirlpoolAcSleepPos LITERAL1 kWhirlpoolAcStateLength LITERAL1 +kWhirlpoolAcSuperMask LITERAL1 +kWhirlpoolAcSuperPos LITERAL1 +kWhirlpoolAcSwing1Mask LITERAL1 +kWhirlpoolAcSwing2Mask LITERAL1 +kWhirlpoolAcTempMask LITERAL1 +kWhirlpoolAcTempPos LITERAL1 +kWhirlpoolAcTimerEnableMask LITERAL1 kWhirlpoolAcZeroSpace LITERAL1 kWhynterBitMark LITERAL1 kWhynterBitMarkTicks LITERAL1 diff --git a/lib/IRremoteESP8266-2.5.2.03/library.json b/lib/IRremoteESP8266-2.6.0/library.json similarity index 97% rename from lib/IRremoteESP8266-2.5.2.03/library.json rename to lib/IRremoteESP8266-2.6.0/library.json index 3fc14f027..95867de1d 100644 --- a/lib/IRremoteESP8266-2.5.2.03/library.json +++ b/lib/IRremoteESP8266-2.6.0/library.json @@ -1,6 +1,6 @@ { "name": "IRremoteESP8266", - "version": "2.5.2", + "version": "2.6.0", "keywords": "infrared, ir, remote, esp8266", "description": "Send and receive infrared signals with multiple protocols (ESP8266)", "repository": diff --git a/lib/IRremoteESP8266-2.5.2.03/library.properties b/lib/IRremoteESP8266-2.6.0/library.properties similarity index 96% rename from lib/IRremoteESP8266-2.5.2.03/library.properties rename to lib/IRremoteESP8266-2.6.0/library.properties index e71dc4154..f122067c5 100644 --- a/lib/IRremoteESP8266-2.5.2.03/library.properties +++ b/lib/IRremoteESP8266-2.6.0/library.properties @@ -1,5 +1,5 @@ name=IRremoteESP8266 -version=2.5.2 +version=2.6.0 author=Sebastien Warin, Mark Szabo, Ken Shirriff, David Conran maintainer=Mark Szabo, David Conran, Sebastien Warin, Roi Dayan, Massimiliano Pinto sentence=Send and receive infrared signals with multiple protocols (ESP8266) diff --git a/lib/IRremoteESP8266-2.5.2.03/platformio.ini b/lib/IRremoteESP8266-2.6.0/platformio.ini similarity index 83% rename from lib/IRremoteESP8266-2.5.2.03/platformio.ini rename to lib/IRremoteESP8266-2.6.0/platformio.ini index 63c3781e1..b6020c165 100644 --- a/lib/IRremoteESP8266-2.5.2.03/platformio.ini +++ b/lib/IRremoteESP8266-2.6.0/platformio.ini @@ -6,11 +6,13 @@ src_dir = examples/IRrecvDumpV2 build_flags = lib_deps_builtin = lib_deps_external = +lib_ldf_mode = chain+ [env:nodemcuv2] platform = espressif8266 framework = arduino board = nodemcuv2 +lib_ldf_mode = ${common.lib_ldf_mode} build_flags = ${common.build_flags} lib_deps = ${common.lib_deps_builtin} @@ -20,6 +22,7 @@ lib_deps = platform = espressif8266 framework = arduino board = d1_mini +lib_ldf_mode = ${common.lib_ldf_mode} build_flags = ${common.build_flags} lib_deps = ${common.lib_deps_builtin} diff --git a/lib/IRremoteESP8266-2.5.2.03/pylintrc b/lib/IRremoteESP8266-2.6.0/pylintrc similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/pylintrc rename to lib/IRremoteESP8266-2.6.0/pylintrc diff --git a/lib/IRremoteESP8266-2.5.2.03/src/CPPLINT.cfg b/lib/IRremoteESP8266-2.6.0/src/CPPLINT.cfg similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/CPPLINT.cfg rename to lib/IRremoteESP8266-2.6.0/src/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.6.0/src/IRac.cpp b/lib/IRremoteESP8266-2.6.0/src/IRac.cpp new file mode 100644 index 000000000..782c147c2 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/IRac.cpp @@ -0,0 +1,1125 @@ +// Copyright 2019 David Conran + +// Provide a universal/standard interface for sending A/C nessages. +// It does not provide complete and maximum granular control but tries +// to off most common functionallity across all supported devices. + +#include "IRac.h" +#ifndef UNIT_TEST +#include +#endif + +#include +#ifndef ARDUINO +#include +#endif +#include "IRsend.h" +#include "IRremoteESP8266.h" +#include "ir_Argo.h" +#include "ir_Coolix.h" +#include "ir_Daikin.h" +#include "ir_Fujitsu.h" +#include "ir_Haier.h" +#include "ir_Hitachi.h" +#include "ir_Kelvinator.h" +#include "ir_Midea.h" +#include "ir_Mitsubishi.h" +#include "ir_MitsubishiHeavy.h" +#include "ir_Panasonic.h" +#include "ir_Samsung.h" +#include "ir_Tcl.h" +#include "ir_Teco.h" +#include "ir_Toshiba.h" +#include "ir_Trotec.h" +#include "ir_Vestel.h" +#include "ir_Whirlpool.h" + +IRac::IRac(uint8_t pin) { _pin = pin; } + +// Is the given protocol supported by the IRac class? +bool IRac::isProtocolSupported(const decode_type_t protocol) { + switch (protocol) { +#if SEND_ARGO + case decode_type_t::ARGO: +#endif +#if SEND_COOLIX + case decode_type_t::COOLIX: +#endif +#if SEND_DAIKIN + case decode_type_t::DAIKIN: +#endif +#if SEND_DAIKIN2 + case decode_type_t::DAIKIN2: +#endif +#if SEND_DAIKIN216 + case decode_type_t::DAIKIN216: +#endif +#if SEND_FUJITSU_AC + case decode_type_t::FUJITSU_AC: +#endif +#if SEND_GREE + case decode_type_t::GREE: +#endif +#if SEND_HAIER_AC + case decode_type_t::HAIER_AC: +#endif +#if SEND_HAIER_AC_YRW02 + case decode_type_t::HAIER_AC_YRW02: +#endif +#if SEND_HITACHI_AC + case decode_type_t::HITACHI_AC: +#endif +#if SEND_KELVINATOR + case decode_type_t::KELVINATOR: +#endif +#if SEND_MIDEA + case decode_type_t::MIDEA: +#endif +#if SEND_MITSUBISHI_AC + case decode_type_t::MITSUBISHI_AC: +#endif +#if SEND_MITSUBISHIHEAVY + case decode_type_t::MITSUBISHI_HEAVY_88: + case decode_type_t::MITSUBISHI_HEAVY_152: +#endif +#if SEND_PANASONIC_AC + case decode_type_t::PANASONIC_AC: +#endif +#if SEND_SAMSUNG_AC + case decode_type_t::SAMSUNG_AC: +#endif +#if SEND_TCL112AC + case decode_type_t::TCL112AC: +#endif +#if SEND_TECO + case decode_type_t::TECO: +#endif +#if SEND_TOSHIBA_AC + case decode_type_t::TOSHIBA_AC: +#endif +#if SEND_TROTEC + case decode_type_t::TROTEC: +#endif +#if SEND_VESTEL_AC + case decode_type_t::VESTEL_AC: +#endif +#if SEND_WHIRLPOOL_AC + case decode_type_t::WHIRLPOOL_AC: +#endif + return true; + default: + return false; + } +} + +#if SEND_ARGO +void IRac::argo(IRArgoAC *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool turbo, const int16_t sleep) { + ac->setPower(on); + switch (mode) { + case stdAc::opmode_t::kCool: + ac->setCoolMode(kArgoCoolOn); + break; + case stdAc::opmode_t::kHeat: + ac->setHeatMode(kArgoHeatOn); + break; + case stdAc::opmode_t::kDry: + ac->setCoolMode(kArgoCoolHum); + break; + default: // No idea how to set Fan mode. + ac->setCoolMode(kArgoCoolAuto); + } + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setFlap(ac->convertSwingV(swingv)); + // No Quiet setting available. + // No Light setting available. + // No Filter setting available. + ac->setMax(turbo); + // No Economy setting available. + // No Clean setting available. + // No Beep setting available. + ac->setNight(sleep >= 0); // Convert to a boolean. + ac->send(); +} +#endif // SEND_ARGO + +#if SEND_COOLIX +void IRac::coolix(IRCoolixAC *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool turbo, const bool light, const bool clean, + const int16_t sleep) { + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + // No Filter setting available. + // No Beep setting available. + // No Clock setting available. + // No Econo setting available. + // No Quiet setting available. + if (swingv != stdAc::swingv_t::kOff || swingh != stdAc::swingh_t::kOff) { + // Swing has a special command that needs to be sent independently. + ac->setSwing(); + ac->send(); + } + if (turbo) { + // Turbo has a special command that needs to be sent independently. + ac->setTurbo(); + ac->send(); + } + if (sleep > 0) { + // Sleep has a special command that needs to be sent independently. + ac->setSleep(); + ac->send(); + } + if (light) { + // Light has a special command that needs to be sent independently. + ac->setLed(); + ac->send(); + } + if (clean) { + // Clean has a special command that needs to be sent independently. + ac->setClean(); + ac->send(); + } + // Power gets done last, as off has a special command. + ac->setPower(on); + ac->send(); +} +#endif // SEND_COOLIX + +#if SEND_DAIKIN +void IRac::daikin(IRDaikinESP *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool econo, + const bool clean) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingVertical((int8_t)swingv >= 0); + ac->setSwingHorizontal((int8_t)swingh >= 0); + ac->setQuiet(quiet); + // No Light setting available. + // No Filter setting available. + ac->setPowerful(turbo); + ac->setEcono(econo); + ac->setMold(clean); + // No Beep setting available. + // No Sleep setting available. + // No Clock setting available. + ac->send(); +} +#endif // SEND_DAIKIN + +#if SEND_DAIKIN2 +void IRac::daikin2(IRDaikin2 *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool light, + const bool econo, const bool filter, const bool clean, + const bool beep, const int16_t sleep, const int16_t clock) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingVertical(ac->convertSwingV(swingv)); + ac->setSwingHorizontal((int8_t)swingh >= 0); + ac->setQuiet(quiet); + ac->setLight(light); + ac->setPowerful(turbo); + ac->setEcono(econo); + ac->setPurify(filter); + ac->setMold(clean); + ac->setBeep(beep); + if (sleep > 0) ac->enableSleepTimer(sleep); + if (clock >= 0) ac->setCurrentTime(clock); + ac->send(); +} +#endif // SEND_DAIKIN2 + +#if SEND_DAIKIN216 +void IRac::daikin216(IRDaikin216 *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingVertical((int8_t)swingv >= 0); + ac->setSwingHorizontal((int8_t)swingh >= 0); + ac->setQuiet(quiet); + ac->send(); +} +#endif // SEND_DAIKIN216 + +#if SEND_FUJITSU_AC +void IRac::fujitsu(IRFujitsuAC *ac, const fujitsu_ac_remote_model_t model, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet) { + ac->setModel(model); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFanSpeed(ac->convertFan(fan)); + uint8_t swing = kFujitsuAcSwingOff; + if (swingv > stdAc::swingv_t::kOff) swing |= kFujitsuAcSwingVert; + if (swingh > stdAc::swingh_t::kOff) swing |= kFujitsuAcSwingHoriz; + ac->setSwing(swing); + if (quiet) ac->setFanSpeed(kFujitsuAcFanQuiet); + // No Turbo setting available. + // No Light setting available. + // No Econo setting available. + // No Filter setting available. + // No Clean setting available. + // No Beep setting available. + // No Sleep setting available. + // No Clock setting available. + if (!on) ac->off(); + ac->send(); +} +#endif // SEND_FUJITSU_AC + +#if SEND_GREE +void IRac::gree(IRGreeAC *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool turbo, const bool light, const bool clean, + const int16_t sleep) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingVertical(swingv == stdAc::swingv_t::kAuto, // Set auto flag. + ac->convertSwingV(swingv)); + ac->setLight(light); + ac->setTurbo(turbo); + ac->setXFan(clean); + ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off. + // No Horizontal Swing setting available. + // No Filter setting available. + // No Beep setting available. + // No Quiet setting available. + // No Clock setting available. + ac->send(); +} +#endif // SEND_GREE + +#if SEND_HAIER_AC +void IRac::haier(IRHaierAC *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool filter, const int16_t sleep, const int16_t clock) { + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwing(ac->convertSwingV(swingv)); + // No Horizontal Swing setting available. + // No Quiet setting available. + // No Turbo setting available. + // No Light setting available. + ac->setHealth(filter); + // No Clean setting available. + // No Beep setting available. + ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off. + if (clock >=0) ac->setCurrTime(clock); + if (on) + ac->setCommand(kHaierAcCmdOn); + else + ac->setCommand(kHaierAcCmdOff); + ac->send(); +} +#endif // SEND_HAIER_AC + +#if SEND_HAIER_AC_YRW02 +void IRac::haierYrwo2(IRHaierACYRW02 *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const bool turbo, + const bool filter, const int16_t sleep) { + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwing(ac->convertSwingV(swingv)); + // No Horizontal Swing setting available. + // No Quiet setting available. + ac->setTurbo(turbo); + // No Light setting available. + ac->setHealth(filter); + // No Clean setting available. + // No Beep setting available. + ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off. + ac->setPower(on); + ac->send(); +} +#endif // SEND_HAIER_AC_YRW02 + +#if SEND_HITACHI_AC +void IRac::hitachi(IRHitachiAc *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingVertical(swingv != stdAc::swingv_t::kOff); + ac->setSwingHorizontal(swingh != stdAc::swingh_t::kOff); + // No Quiet setting available. + // No Turbo setting available. + // No Light setting available. + // No Filter setting available. + // No Clean setting available. + // No Beep setting available. + // No Sleep setting available. + // No Clock setting available. + ac->send(); +} +#endif // SEND_HITACHI_AC + +#if SEND_KELVINATOR +void IRac::kelvinator(IRKelvinatorAC *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, + const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool light, + const bool filter, const bool clean) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan((uint8_t)fan); // No conversion needed. + ac->setSwingVertical((int8_t)swingv >= 0); + ac->setSwingHorizontal((int8_t)swingh >= 0); + ac->setQuiet(quiet); + ac->setTurbo(turbo); + ac->setLight(light); + ac->setIonFilter(filter); + ac->setXFan(clean); + // No Beep setting available. + // No Sleep setting available. + // No Clock setting available. + ac->send(); +} +#endif // SEND_KELVINATOR + +#if SEND_MIDEA +void IRac::midea(IRMideaAC *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const int16_t sleep) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees, true); // true means use Celsius. + ac->setFan(ac->convertFan(fan)); + // No Vertical swing setting available. + // No Horizontal swing setting available. + // No Quiet setting available. + // No Turbo setting available. + // No Light setting available. + // No Filter setting available. + // No Clean setting available. + // No Beep setting available. + ac->setSleep(sleep >= 0); // Sleep on this A/C is either on or off. + // No Clock setting available. + ac->send(); +} +#endif // SEND_MIDEA + +#if SEND_MITSUBISHI_AC +void IRac::mitsubishi(IRMitsubishiAC *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool quiet, const int16_t clock) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setVane(ac->convertSwingV(swingv)); + // No Horizontal swing setting available. + if (quiet) ac->setFan(kMitsubishiAcFanSilent); + // No Turbo setting available. + // No Light setting available. + // No Filter setting available. + // No Clean setting available. + // No Beep setting available. + // No Sleep setting available. + if (clock >= 0) ac->setClock(clock / 10); // Clock is in 10 min increments. + ac->send(); +} +#endif // SEND_MITSUBISHI_AC + +#if SEND_MITSUBISHIHEAVY +void IRac::mitsubishiHeavy88(IRMitsubishiHeavy88Ac *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, + const stdAc::swingh_t swingh, + const bool turbo, const bool econo, + const bool clean) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingVertical(ac->convertSwingV(swingv)); + ac->setSwingHorizontal(ac->convertSwingH(swingh)); + // No Quiet setting available. + ac->setTurbo(turbo); + // No Light setting available. + ac->setEcono(econo); + // No Filter setting available. + ac->setClean(clean); + // No Beep setting available. + // No Sleep setting available. + // No Clock setting available. + ac->send(); +} + +void IRac::mitsubishiHeavy152(IRMitsubishiHeavy152Ac *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, + const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, + const bool econo, const bool filter, + const bool clean, const int16_t sleep) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingVertical(ac->convertSwingV(swingv)); + ac->setSwingHorizontal(ac->convertSwingH(swingh)); + ac->setSilent(quiet); + ac->setTurbo(turbo); + // No Light setting available. + ac->setEcono(econo); + ac->setClean(clean); + ac->setFilter(filter); + // No Beep setting available. + ac->setNight(sleep >= 0); // Sleep is either on/off, so convert to boolean. + // No Clock setting available. + ac->send(); +} +#endif // SEND_MITSUBISHIHEAVY + +#if SEND_PANASONIC_AC +void IRac::panasonic(IRPanasonicAc *ac, const panasonic_ac_remote_model_t model, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const int16_t clock) { + ac->setModel(model); + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingVertical(ac->convertSwingV(swingv)); + ac->setSwingHorizontal(ac->convertSwingH(swingh)); + ac->setQuiet(quiet); + ac->setPowerful(turbo); + // No Light setting available. + // No Econo setting available. + // No Filter setting available. + // No Clean setting available. + // No Beep setting available. + // No Sleep setting available. + if (clock >= 0) ac->setClock(clock); + ac->send(); +} +#endif // SEND_PANASONIC_AC + +#if SEND_SAMSUNG_AC +void IRac::samsung(IRSamsungAc *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool quiet, const bool turbo, const bool clean, + const bool beep, const bool sendOnOffHack) { + if (sendOnOffHack) { + // Use a hack to for the unit on or off. + // See: https://github.com/markszabo/IRremoteESP8266/issues/604#issuecomment-475020036 + if (on) + ac->sendOn(); + else + ac->sendOff(); + } + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwing(swingv != stdAc::swingv_t::kOff); + // No Horizontal swing setting available. + ac->setQuiet(quiet); + if (turbo) ac->setFan(kSamsungAcFanTurbo); + // No Light setting available. + // No Econo setting available. + // No Filter setting available. + ac->setClean(clean); + ac->setBeep(beep); + // No Sleep setting available. + // No Clock setting available. + // Do setMode() again as it can affect fan speed. + ac->setMode(ac->convertMode(mode)); + ac->send(); +} +#endif // SEND_SAMSUNG_AC + +#if SEND_TCL112AC +void IRac::tcl112(IRTcl112Ac *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool turbo, const bool light, const bool econo, + const bool filter) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwingVertical(swingv != stdAc::swingv_t::kOff); + ac->setSwingHorizontal(swingh != stdAc::swingh_t::kOff); + // No Quiet setting available. + ac->setTurbo(turbo); + ac->setLight(light); + ac->setEcono(econo); + ac->setHealth(filter); + // No Clean setting available. + // No Beep setting available. + // No Sleep setting available. + // No Clock setting available. + ac->send(); +} +#endif // SEND_TCL112AC + +#if SEND_TECO +void IRac::teco(IRTecoAc *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const int16_t sleep) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwing(swingv != stdAc::swingv_t::kOff); + // No Horizontal swing setting available. + // No Quiet setting available. + // No Turbo setting available. + // No Light setting available. + // No Filter setting available. + // No Clean setting available. + // No Beep setting available. + ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean. + // No Clock setting available. + ac->send(); +} +#endif // SEND_TECO + +#if SEND_TOSHIBA_AC +void IRac::toshiba(IRToshibaAC *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + // No Vertical swing setting available. + // No Horizontal swing setting available. + // No Quiet setting available. + // No Turbo setting available. + // No Light setting available. + // No Filter setting available. + // No Clean setting available. + // No Beep setting available. + // No Sleep setting available. + // No Clock setting available. + ac->send(); +} +#endif // SEND_TOSHIBA_AC + +#if SEND_TROTEC +void IRac::trotec(IRTrotecESP *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const int16_t sleep) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setSpeed(ac->convertFan(fan)); + // No Vertical swing setting available. + // No Horizontal swing setting available. + // No Quiet setting available. + // No Turbo setting available. + // No Light setting available. + // No Filter setting available. + // No Clean setting available. + // No Beep setting available. + ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean. + // No Clock setting available. + ac->send(); +} +#endif // SEND_TROTEC + +#if SEND_VESTEL_AC +void IRac::vestel(IRVestelAc *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool turbo, const bool filter, const int16_t sleep, + const int16_t clock, const bool sendNormal) { + ac->setPower(on); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwing(swingv != stdAc::swingv_t::kOff); + // No Horizontal swing setting available. + // No Quiet setting available. + ac->setTurbo(turbo); + // No Light setting available. + ac->setIon(filter); + // No Clean setting available. + // No Beep setting available. + ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean. + if (sendNormal) ac->send(); // Send the normal message. + if (clock >= 0) { + ac->setTime(clock); + ac->send(); // Setting the clock requires a different "timer" message. + } +} +#endif // SEND_VESTEL_AC + +#if SEND_WHIRLPOOL_AC +void IRac::whirlpool(IRWhirlpoolAc *ac, const whirlpool_ac_remote_model_t model, + const bool on, const stdAc::opmode_t mode, + const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool turbo, const bool light, + const int16_t sleep, const int16_t clock) { + ac->setModel(model); + ac->setMode(ac->convertMode(mode)); + ac->setTemp(degrees); + ac->setFan(ac->convertFan(fan)); + ac->setSwing(swingv != stdAc::swingv_t::kOff); + // No Horizontal swing setting available. + // No Quiet setting available. + ac->setSuper(turbo); + ac->setLight(light); + // No Filter setting available + // No Clean setting available. + // No Beep setting available. + ac->setSleep(sleep >= 0); // Sleep is either on/off, so convert to boolean. + if (clock >= 0) ac->setClock(clock); + ac->setPowerToggle(on); + ac->send(); +} +#endif // SEND_WHIRLPOOL_AC + +// Send A/C message for a given device using common A/C settings. +// Args: +// vendor: The type of A/C protocol to use. +// model: The specific model of A/C if supported/applicable. +// on: Should the unit be powered on? (or in some cases, toggled) +// mode: What operating mode should the unit perform? e.g. Cool, Heat etc. +// degrees: What temperature should the unit be set to? +// celsius: Use degreees Celsius, otherwise Fahrenheit. +// fan: Fan speed. +// The following args are all "if supported" by the underlying A/C classes. +// swingv: Control the vertical swing of the vanes. +// swingh: Control the horizontal swing of the vanes. +// quiet: Set the unit to quiet (fan) operation mode. +// turbo: Set the unit to turbo operating mode. e.g. Max fan & cooling etc. +// econo: Set the unit to economical operating mode. +// light: Turn on the display/LEDs etc. +// filter: Turn on any particle/ion/allergy filter etc. +// clean: Turn on any settings to reduce mold etc. (Not self-clean mode.) +// beep: Control if the unit beeps upon receiving commands. +// sleep: Nr. of mins of sleep mode, or use sleep mode. (< 0 means off.) +// clock: Nr. of mins past midnight to set the clock to. (< 0 means off.) +// Returns: +// boolean: True, if accepted/converted/attempted. False, if unsupported. +bool IRac::sendAc(const decode_type_t vendor, const int16_t model, + const bool power, const stdAc::opmode_t mode, + const float degrees, const bool celsius, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool econo, + const bool light, const bool filter, const bool clean, + const bool beep, const int16_t sleep, const int16_t clock) { + // Convert the temperature to Celsius. + float degC; + bool on = power; + if (celsius) + degC = degrees; + else + degC = (degrees - 32.0) * (5.0 / 9.0); + // A hack for Home Assistant, it appears to need/want an Off opmode. + if (mode == stdAc::opmode_t::kOff) on = false; + // Per vendor settings & setup. + switch (vendor) { +#if SEND_ARGO + case ARGO: + { + IRArgoAC ac(_pin); + argo(&ac, on, mode, degC, fan, swingv, turbo, sleep); + break; + } +#endif // SEND_DAIKIN +#if SEND_COOLIX + case COOLIX: + { + IRCoolixAC ac(_pin); + coolix(&ac, on, mode, degC, fan, swingv, swingh, + quiet, turbo, econo, clean); + break; + } +#endif // SEND_DAIKIN +#if SEND_DAIKIN + case DAIKIN: + { + IRDaikinESP ac(_pin); + daikin(&ac, on, mode, degC, fan, swingv, swingh, + quiet, turbo, econo, clean); + break; + } +#endif // SEND_DAIKIN +#if SEND_DAIKIN2 + case DAIKIN2: + { + IRDaikin2 ac(_pin); + daikin2(&ac, on, mode, degC, fan, swingv, swingh, quiet, turbo, + light, econo, filter, clean, beep, sleep, clock); + break; + } +#endif // SEND_DAIKIN216 +#if SEND_DAIKIN216 + case DAIKIN216: + { + IRDaikin216 ac(_pin); + daikin216(&ac, on, mode, degC, fan, swingv, swingh, quiet); + break; + } +#endif // SEND_DAIKIN216 +#if SEND_FUJITSU_AC + case FUJITSU_AC: + { + IRFujitsuAC ac(_pin); + ac.begin(); + fujitsu(&ac, (fujitsu_ac_remote_model_t)model, on, mode, degC, fan, + swingv, swingh, quiet); + break; + } +#endif // SEND_FUJITSU_AC +#if SEND_GREE + case GREE: + { + IRGreeAC ac(_pin); + ac.begin(); + gree(&ac, on, mode, degC, fan, swingv, light, turbo, clean, sleep); + break; + } +#endif // SEND_GREE +#if SEND_HAIER_AC + case HAIER_AC: + { + IRHaierAC ac(_pin); + ac.begin(); + haier(&ac, on, mode, degC, fan, swingv, filter, sleep, clock); + break; + } +#endif // SEND_HAIER_AC +#if SEND_HAIER_AC_YRW02 + case HAIER_AC_YRW02: + { + IRHaierACYRW02 ac(_pin); + ac.begin(); + haierYrwo2(&ac, on, mode, degC, fan, swingv, turbo, filter, sleep); + break; + } +#endif // SEND_HAIER_AC_YRW02 +#if SEND_HITACHI_AC + case HITACHI_AC: + { + IRHitachiAc ac(_pin); + ac.begin(); + hitachi(&ac, on, mode, degC, fan, swingv, swingh); + break; + } +#endif // SEND_HITACHI_AC +#if SEND_KELVINATOR + case KELVINATOR: + { + IRKelvinatorAC ac(_pin); + ac.begin(); + kelvinator(&ac, on, mode, degC, fan, swingv, swingh, quiet, turbo, + light, filter, clean); + break; + } +#endif // SEND_KELVINATOR +#if SEND_MIDEA + case MIDEA: + { + IRMideaAC ac(_pin); + ac.begin(); + midea(&ac, on, mode, degC, fan, sleep); + break; + } +#endif // SEND_MIDEA +#if SEND_MITSUBISHI_AC + case MITSUBISHI_AC: + { + IRMitsubishiAC ac(_pin); + ac.begin(); + mitsubishi(&ac, on, mode, degC, fan, swingv, quiet, clock); + break; + } +#endif // SEND_MITSUBISHI_AC +#if SEND_MITSUBISHIHEAVY + case MITSUBISHI_HEAVY_88: + { + IRMitsubishiHeavy88Ac ac(_pin); + ac.begin(); + mitsubishiHeavy88(&ac, on, mode, degC, fan, swingv, swingh, + turbo, econo, clean); + break; + } + case MITSUBISHI_HEAVY_152: + { + IRMitsubishiHeavy152Ac ac(_pin); + ac.begin(); + mitsubishiHeavy152(&ac, on, mode, degC, fan, swingv, swingh, + quiet, turbo, econo, filter, clean, sleep); + break; + } +#endif // SEND_MITSUBISHIHEAVY +#if SEND_PANASONIC_AC + case PANASONIC_AC: + { + IRPanasonicAc ac(_pin); + ac.begin(); + panasonic(&ac, (panasonic_ac_remote_model_t)model, on, mode, degC, fan, + swingv, swingh, quiet, turbo, clock); + break; + } +#endif // SEND_PANASONIC_AC +#if SEND_SAMSUNG_AC + case SAMSUNG_AC: + { + IRSamsungAc ac(_pin); + ac.begin(); + samsung(&ac, on, mode, degC, fan, swingv, quiet, turbo, clean, beep); + break; + } +#endif // SEND_SAMSUNG_AC +#if SEND_TCL112AC + case TCL112AC: + { + IRTcl112Ac ac(_pin); + ac.begin(); + tcl112(&ac, on, mode, degC, fan, swingv, swingh, turbo, light, econo, + filter); + break; + } +#endif // SEND_TCL112AC +#if SEND_TECO + case TECO: + { + IRTecoAc ac(_pin); + ac.begin(); + teco(&ac, on, mode, degC, fan, swingv, sleep); + break; + } +#endif // SEND_TECO +#if SEND_TOSHIBA_AC + case TOSHIBA_AC: + { + IRToshibaAC ac(_pin); + ac.begin(); + toshiba(&ac, on, mode, degC, fan); + break; + } +#endif // SEND_TOSHIBA_AC +#if SEND_TROTEC + case TROTEC: + { + IRTrotecESP ac(_pin); + ac.begin(); + trotec(&ac, on, mode, degC, fan, sleep); + break; + } +#endif // SEND_TROTEC +#if SEND_VESTEL_AC + case VESTEL_AC: + { + IRVestelAc ac(_pin); + ac.begin(); + vestel(&ac, on, mode, degC, fan, swingv, turbo, filter, sleep, clock); + break; + } +#endif // SEND_VESTEL_AC +#if SEND_WHIRLPOOL_AC + case WHIRLPOOL_AC: + { + IRWhirlpoolAc ac(_pin); + ac.begin(); + whirlpool(&ac, (whirlpool_ac_remote_model_t)model, on, mode, degC, fan, + swingv, turbo, light, sleep, clock); + break; + } +#endif // SEND_WHIRLPOOL_AC + default: + return false; // Fail, didn't match anything. + } + return true; // Success. +} + +stdAc::opmode_t IRac::strToOpmode(const char *str, + const stdAc::opmode_t def) { + if (!strcmp(str, "AUTO") || !strcmp(str, "AUTOMATIC")) + return stdAc::opmode_t::kAuto; + else if (!strcmp(str, "OFF") || !strcmp(str, "STOP")) + return stdAc::opmode_t::kOff; + else if (!strcmp(str, "COOL") || !strcmp(str, "COOLING")) + return stdAc::opmode_t::kCool; + else if (!strcmp(str, "HEAT") || !strcmp(str, "HEATING")) + return stdAc::opmode_t::kHeat; + else if (!strcmp(str, "DRY") || !strcmp(str, "DRYING") || + !strcmp(str, "DEHUMIDIFY")) + return stdAc::opmode_t::kDry; + else if (!strcmp(str, "FAN") || !strcmp(str, "FANONLY") || + !strcmp(str, "FAN_ONLY")) + return stdAc::opmode_t::kFan; + else + return def; +} + +stdAc::fanspeed_t IRac::strToFanspeed(const char *str, + const stdAc::fanspeed_t def) { + if (!strcmp(str, "AUTO") || !strcmp(str, "AUTOMATIC")) + return stdAc::fanspeed_t::kAuto; + else if (!strcmp(str, "MIN") || !strcmp(str, "MINIMUM") || + !strcmp(str, "LOWEST")) + return stdAc::fanspeed_t::kMin; + else if (!strcmp(str, "LOW")) + return stdAc::fanspeed_t::kLow; + else if (!strcmp(str, "MED") || !strcmp(str, "MEDIUM") || + !strcmp(str, "MID")) + return stdAc::fanspeed_t::kMedium; + else if (!strcmp(str, "HIGH") || !strcmp(str, "HI")) + return stdAc::fanspeed_t::kHigh; + else if (!strcmp(str, "MAX") || !strcmp(str, "MAXIMUM") || + !strcmp(str, "HIGHEST")) + return stdAc::fanspeed_t::kMax; + else + return def; +} + +stdAc::swingv_t IRac::strToSwingV(const char *str, + const stdAc::swingv_t def) { + if (!strcmp(str, "AUTO") || !strcmp(str, "AUTOMATIC") || + !strcmp(str, "ON") || !strcmp(str, "SWING")) + return stdAc::swingv_t::kAuto; + else if (!strcmp(str, "OFF") || !strcmp(str, "STOP")) + return stdAc::swingv_t::kOff; + else if (!strcmp(str, "MIN") || !strcmp(str, "MINIMUM") || + !strcmp(str, "LOWEST") || !strcmp(str, "BOTTOM") || + !strcmp(str, "DOWN")) + return stdAc::swingv_t::kLowest; + else if (!strcmp(str, "LOW")) + return stdAc::swingv_t::kLow; + else if (!strcmp(str, "MID") || !strcmp(str, "MIDDLE") || + !strcmp(str, "MED") || !strcmp(str, "MEDIUM") || + !strcmp(str, "CENTRE") || !strcmp(str, "CENTER")) + return stdAc::swingv_t::kMiddle; + else if (!strcmp(str, "HIGH") || !strcmp(str, "HI")) + return stdAc::swingv_t::kHigh; + else if (!strcmp(str, "HIGHEST") || !strcmp(str, "MAX") || + !strcmp(str, "MAXIMUM") || !strcmp(str, "TOP") || + !strcmp(str, "UP")) + return stdAc::swingv_t::kHighest; + else + return def; +} + +stdAc::swingh_t IRac::strToSwingH(const char *str, + const stdAc::swingh_t def) { + if (!strcmp(str, "AUTO") || !strcmp(str, "AUTOMATIC") || + !strcmp(str, "ON") || !strcmp(str, "SWING")) + return stdAc::swingh_t::kAuto; + else if (!strcmp(str, "OFF") || !strcmp(str, "STOP")) + return stdAc::swingh_t::kOff; + else if (!strcmp(str, "LEFTMAX") || !strcmp(str, "LEFT MAX") || + !strcmp(str, "MAXLEFT") || !strcmp(str, "MAX LEFT") || + !strcmp(str, "FARLEFT") || !strcmp(str, "FAR LEFT")) + return stdAc::swingh_t::kLeftMax; + else if (!strcmp(str, "LEFT")) + return stdAc::swingh_t::kLeft; + else if (!strcmp(str, "MID") || !strcmp(str, "MIDDLE") || + !strcmp(str, "MED") || !strcmp(str, "MEDIUM") || + !strcmp(str, "CENTRE") || !strcmp(str, "CENTER")) + return stdAc::swingh_t::kMiddle; + else if (!strcmp(str, "RIGHT")) + return stdAc::swingh_t::kRight; + else if (!strcmp(str, "RIGHTMAX") || !strcmp(str, "RIGHT MAX") || + !strcmp(str, "MAXRIGHT") || !strcmp(str, "MAX RIGHT") || + !strcmp(str, "FARRIGHT") || !strcmp(str, "FAR RIGHT")) + return stdAc::swingh_t::kRightMax; + else + return def; +} + +// Assumes str is upper case or an integer >= 1. +int16_t IRac::strToModel(const char *str, const int16_t def) { + // Fujitsu A/C models + if (!strcmp(str, "ARRAH2E")) { + return fujitsu_ac_remote_model_t::ARRAH2E; + } else if (!strcmp(str, "ARDB1")) { + return fujitsu_ac_remote_model_t::ARDB1; + // Panasonic A/C families + } else if (!strcmp(str, "LKE") || !strcmp(str, "PANASONICLKE")) { + return panasonic_ac_remote_model_t::kPanasonicLke; + } else if (!strcmp(str, "NKE") || !strcmp(str, "PANASONICNKE")) { + return panasonic_ac_remote_model_t::kPanasonicNke; + } else if (!strcmp(str, "DKE") || !strcmp(str, "PANASONICDKE")) { + return panasonic_ac_remote_model_t::kPanasonicDke; + } else if (!strcmp(str, "JKE") || !strcmp(str, "PANASONICJKE")) { + return panasonic_ac_remote_model_t::kPanasonicJke; + } else if (!strcmp(str, "CKP") || !strcmp(str, "PANASONICCKP")) { + return panasonic_ac_remote_model_t::kPanasonicCkp; + } else if (!strcmp(str, "RKR") || !strcmp(str, "PANASONICRKR")) { + return panasonic_ac_remote_model_t::kPanasonicRkr; + // Whirlpool A/C models + } else if (!strcmp(str, "DG11J13A") || !strcmp(str, "DG11J104") || + !strcmp(str, "DG11J1-04")) { + return whirlpool_ac_remote_model_t::DG11J13A; + } else if (!strcmp(str, "DG11J191")) { + return whirlpool_ac_remote_model_t::DG11J191; + } else { + int16_t number = atoi(str); + if (number > 0) + return number; + else + return def; + } +} + +// Assumes str is upper case. +bool IRac::strToBool(const char *str, const bool def) { + if (!strcmp(str, "ON") || !strcmp(str, "1") || !strcmp(str, "YES") || + !strcmp(str, "TRUE")) + return true; + else if (!strcmp(str, "OFF") || !strcmp(str, "0") || + !strcmp(str, "NO") || !strcmp(str, "FALSE")) + return false; + else + return def; +} diff --git a/lib/IRremoteESP8266-2.6.0/src/IRac.h b/lib/IRremoteESP8266-2.6.0/src/IRac.h new file mode 100644 index 000000000..ce8d50507 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/IRac.h @@ -0,0 +1,248 @@ +#ifndef IRAC_H_ +#define IRAC_H_ + +// Copyright 2019 David Conran + +#ifndef UNIT_TEST +#include +#endif +#ifndef ARDUINO +#include +#endif +#include "IRremoteESP8266.h" +#include "ir_Argo.h" +#include "ir_Coolix.h" +#include "ir_Daikin.h" +#include "ir_Fujitsu.h" +#include "ir_Gree.h" +#include "ir_Haier.h" +#include "ir_Hitachi.h" +#include "ir_Kelvinator.h" +#include "ir_Midea.h" +#include "ir_Mitsubishi.h" +#include "ir_MitsubishiHeavy.h" +#include "ir_Panasonic.h" +#include "ir_Samsung.h" +#include "ir_Tcl.h" +#include "ir_Teco.h" +#include "ir_Toshiba.h" +#include "ir_Trotec.h" +#include "ir_Vestel.h" +#include "ir_Whirlpool.h" + +class IRac { + public: + explicit IRac(uint8_t pin); + static bool isProtocolSupported(const decode_type_t protocol); + bool sendAc(const decode_type_t vendor, const int16_t model, + const bool power, const stdAc::opmode_t mode, const float degrees, + const bool celsius, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool econo, + const bool light, const bool filter, const bool clean, + const bool beep, const int16_t sleep = -1, + const int16_t clock = -1); + + static bool strToBool(const char *str, const bool def = false); + static int16_t strToModel(const char *str, const int16_t def = -1); + static stdAc::opmode_t strToOpmode( + const char *str, const stdAc::opmode_t def = stdAc::opmode_t::kAuto); + static stdAc::fanspeed_t strToFanspeed( + const char *str, + const stdAc::fanspeed_t def = stdAc::fanspeed_t::kAuto); + static stdAc::swingv_t strToSwingV( + const char *str, const stdAc::swingv_t def = stdAc::swingv_t::kOff); + static stdAc::swingh_t strToSwingH( + const char *str, const stdAc::swingh_t def = stdAc::swingh_t::kOff); +#ifndef UNIT_TEST + + private: +#endif + uint8_t _pin; +#if SEND_ARGO + void argo(IRArgoAC *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool turbo, const int16_t sleep = -1); +#endif // SEND_ARGO +#if SEND_COOLIX + void coolix(IRCoolixAC *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool turbo, const bool light, const bool clean, + const int16_t sleep = -1); +#endif // SEND_COOLIX +#if SEND_DAIKIN + void daikin(IRDaikinESP *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool econo, + const bool clean); +#endif // SEND_DAIKIN +#if SEND_DAIKIN2 + void daikin2(IRDaikin2 *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool light, + const bool econo, const bool filter, const bool clean, + const bool beep, const int16_t sleep = -1, + const int16_t clock = -1); +#endif // SEND_DAIKIN2 +#if SEND_DAIKIN216 +void daikin216(IRDaikin216 *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet); +#endif // SEND_DAIKIN216 +#if SEND_FUJITSU_AC + void fujitsu(IRFujitsuAC *ac, const fujitsu_ac_remote_model_t model, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet); +#endif // SEND_FUJITSU_AC +#if SEND_GREE + void gree(IRGreeAC *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool turbo, const bool light, const bool clean, + const int16_t sleep = -1); +#endif // SEND_GREE +#if SEND_HAIER_AC + void haier(IRHaierAC *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool filter, const int16_t sleep = -1, + const int16_t clock = -1); +#endif // SEND_HAIER_AC +#if SEND_HAIER_AC_YRW02 + void haierYrwo2(IRHaierACYRW02 *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, + const bool turbo, const bool filter, + const int16_t sleep = -1); +#endif // SEND_HAIER_AC_YRW02 +#if SEND_HITACHI_AC + void hitachi(IRHitachiAc *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh); +#endif // SEND_HITACHI_AC +#if SEND_KELVINATOR + void kelvinator(IRKelvinatorAC *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool light, + const bool filter, const bool clean); +#endif // SEND_KELVINATOR +#if SEND_MIDEA + void midea(IRMideaAC *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const int16_t sleep = -1); +#endif // SEND_MIDEA +#if SEND_MITSUBISHI_AC + void mitsubishi(IRMitsubishiAC *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool quiet, const int16_t clock = -1); +#endif // SEND_MITSUBISHI_AC +#if SEND_MITSUBISHIHEAVY + void mitsubishiHeavy88(IRMitsubishiHeavy88Ac *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, + const stdAc::swingh_t swingh, + const bool turbo, const bool econo, const bool clean); + void mitsubishiHeavy152(IRMitsubishiHeavy152Ac *ac, + const bool on, const stdAc::opmode_t mode, + const float degrees, const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, + const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const bool econo, + const bool filter, const bool clean, + const int16_t sleep = -1); +#endif // SEND_MITSUBISHIHEAVY +#if SEND_PANASONIC_AC + void panasonic(IRPanasonicAc *ac, const panasonic_ac_remote_model_t model, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool quiet, const bool turbo, const int16_t clock = -1); +#endif // SEND_PANASONIC_AC +#if SEND_SAMSUNG_AC + void samsung(IRSamsungAc *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool quiet, const bool turbo, const bool clean, + const bool beep, const bool sendOnOffHack = true); +#endif // SEND_SAMSUNG_AC +#if SEND_TCL112AC + void tcl112(IRTcl112Ac *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, + const stdAc::swingv_t swingv, const stdAc::swingh_t swingh, + const bool turbo, const bool light, const bool econo, + const bool filter); +#endif // SEND_TCL112AC +#if SEND_TECO + void teco(IRTecoAc *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const int16_t sleep = -1); +#endif // SEND_TECO +#if SEND_TOSHIBA_AC + void toshiba(IRToshibaAC *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan); +#endif // SEND_TOSHIBA_AC +#if SEND_TROTEC + void trotec(IRTrotecESP *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const int16_t sleep = -1); +#endif // SEND_TROTEC +#if SEND_VESTEL_AC + void vestel(IRVestelAc *ac, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool turbo, const bool filter, + const int16_t sleep = -1, const int16_t clock = -1, + const bool sendNormal = true); +#endif // SEND_VESTEL_AC +#if SEND_WHIRLPOOL_AC + void whirlpool(IRWhirlpoolAc *ac, const whirlpool_ac_remote_model_t model, + const bool on, const stdAc::opmode_t mode, const float degrees, + const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, + const bool turbo, const bool light, + const int16_t sleep = -1, const int16_t clock = -1); +#endif // SEND_WHIRLPOOL_AC +}; // IRac class + +// Structure to hold a common A/C state. +typedef struct { + decode_type_t protocol; + int16_t model; + bool power; + stdAc::opmode_t mode; + float degrees; + bool celsius; + stdAc::fanspeed_t fanspeed; + stdAc::swingv_t swingv; + stdAc::swingh_t swingh; + bool quiet; + bool turbo; + bool econo; + bool light; + bool filter; + bool clean; + bool beep; + int16_t sleep; + int16_t clock; +} commonAcState_t; +#endif // IRAC_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.cpp b/lib/IRremoteESP8266-2.6.0/src/IRrecv.cpp similarity index 95% rename from lib/IRremoteESP8266-2.5.2.03/src/IRrecv.cpp rename to lib/IRremoteESP8266-2.6.0/src/IRrecv.cpp index b2c984396..eac868084 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/IRrecv.cpp @@ -364,6 +364,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { DPRINTLN("Attempting SAMSUNG decode"); if (decodeSAMSUNG(results)) return true; #endif +#if DECODE_SAMSUNG36 + DPRINTLN("Attempting Samsung36 decode"); + if (decodeSamsung36(results)) return true; +#endif #if DECODE_WHYNTER DPRINTLN("Attempting Whynter decode"); if (decodeWhynter(results)) return true; @@ -394,6 +398,14 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { DPRINTLN("Attempting Daikin decode"); if (decodeDaikin(results)) return true; #endif +#if DECODE_DAIKIN2 + DPRINTLN("Attempting Daikin2 decode"); + if (decodeDaikin2(results)) return true; +#endif +#if DECODE_DAIKIN216 + DPRINTLN("Attempting Daikin216 decode"); + if (decodeDaikin216(results)) return true; +#endif #if DECODE_TOSHIBA_AC DPRINTLN("Attempting Toshiba AC decode"); if (decodeToshibaAC(results)) return true; @@ -489,6 +501,28 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { DPRINTLN("Attempting MWM decode"); if (decodeMWM(results)) return true; #endif +#if DECODE_VESTEL_AC + DPRINTLN("Attempting Vestel AC decode"); + if (decodeVestelAc(results)) return true; +#endif +#if DECODE_TCL112AC + DPRINTLN("Attempting TCL112AC decode"); + if (decodeTcl112Ac(results)) return true; +#endif +#if DECODE_TECO + DPRINTLN("Attempting Teco decode"); + if (decodeTeco(results)) return true; +#endif +#if DECODE_LEGOPF + DPRINTLN("Attempting LEGOPF decode"); + if (decodeLegoPf(results)) return true; +#endif +#if DECODE_MITSUBISHIHEAVY + DPRINTLN("Attempting MITSUBISHIHEAVY (152 bit) decode"); + if (decodeMitsubishiHeavy(results, kMitsubishiHeavy152Bits)) return true; + DPRINTLN("Attempting MITSUBISHIHEAVY (88 bit) decode"); + if (decodeMitsubishiHeavy(results, kMitsubishiHeavy88Bits)) return true; +#endif #if DECODE_HASH // decodeHash returns a hash on any input. // Thus, it needs to be last in the list. diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h b/lib/IRremoteESP8266-2.6.0/src/IRrecv.h similarity index 90% rename from lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h rename to lib/IRremoteESP8266-2.6.0/src/IRrecv.h index c0f5e781a..0659f093e 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/IRrecv.h +++ b/lib/IRremoteESP8266-2.6.0/src/IRrecv.h @@ -181,6 +181,10 @@ class IRrecv { uint16_t nbits = kMitsubishiACBits, bool strict = false); #endif +#if DECODE_MITSUBISHIHEAVY + bool decodeMitsubishiHeavy(decode_results *results, const uint16_t nbits, + const bool strict = true); +#endif #if (DECODE_RC5 || DECODE_R6 || DECODE_LASERTAG || DECODE_MWM) int16_t getRClevel(decode_results *results, uint16_t *offset, uint16_t *used, uint16_t bitTime, uint8_t tolerance = kTolerance, @@ -216,6 +220,11 @@ class IRrecv { bool decodeSAMSUNG(decode_results *results, uint16_t nbits = kSamsungBits, bool strict = true); #endif +#if DECODE_SAMSUNG + bool decodeSamsung36(decode_results *results, + const uint16_t nbits = kSamsung36Bits, + const bool strict = true); +#endif #if DECODE_SAMSUNG_AC bool decodeSamsungAC(decode_results *results, uint16_t nbits = kSamsungAcBits, bool strict = true); @@ -257,8 +266,17 @@ class IRrecv { uint16_t nbits = kKelvinatorBits, bool strict = true); #endif #if DECODE_DAIKIN - bool decodeDaikin(decode_results *results, uint16_t nbits = kDaikinRawBits, - bool strict = true); + bool decodeDaikin(decode_results *results, const uint16_t nbits = kDaikinBits, + const bool strict = true); +#endif +#if DECODE_DAIKIN2 + bool decodeDaikin2(decode_results *results, uint16_t nbits = kDaikin2Bits, + bool strict = true); +#endif +#if DECODE_DAIKIN216 + bool decodeDaikin216(decode_results *results, + const uint16_t nbits = kDaikin216Bits, + const bool strict = true); #endif #if DECODE_TOSHIBA_AC bool decodeToshibaAC(decode_results *results, @@ -330,6 +348,22 @@ class IRrecv { bool decodeMWM(decode_results *results, uint16_t nbits = 24, bool strict = true); #endif +#if DECODE_VESTEL_AC + bool decodeVestelAc(decode_results *results, uint16_t nbits = kVestelAcBits, + bool strict = true); +#endif +#if DECODE_TCL112AC + bool decodeTcl112Ac(decode_results *results, uint16_t nbits = kTcl112AcBits, + bool strict = true); +#endif +#if DECODE_TECO + bool decodeTeco(decode_results *results, uint16_t nbits = kTecoBits, + bool strict = false); +#endif +#if DECODE_LEGOPF + bool decodeLegoPf(decode_results *results, const uint16_t nbits = kLegoPfBits, + const bool strict = true); +#endif }; #endif // IRRECV_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRremoteESP8266.h b/lib/IRremoteESP8266-2.6.0/src/IRremoteESP8266.h similarity index 82% rename from lib/IRremoteESP8266-2.5.2.03/src/IRremoteESP8266.h rename to lib/IRremoteESP8266-2.6.0/src/IRremoteESP8266.h index e228cbcb0..b532cb1c0 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/IRremoteESP8266.h +++ b/lib/IRremoteESP8266-2.6.0/src/IRremoteESP8266.h @@ -34,6 +34,8 @@ * Fujitsu A/C code added by jonnygraham * Trotec AC code by stufisher * Carrier & Haier AC code by crankyoldgit + * Vestel AC code by Erdem U. Altınyurt + * Teco AC code by Fabien Valthier (hcoohb) * * GPL license, all text above must be included in any redistribution ****************************************************/ @@ -48,7 +50,7 @@ #endif // Library Version -#define _IRREMOTEESP8266_VERSION_ "2.5.2" +#define _IRREMOTEESP8266_VERSION_ "2.6.0" // Supported IR protocols // Each protocol you include costs memory and, during decode, costs time // Disable (set to false) all the protocols you do not need/want! @@ -86,6 +88,9 @@ #define DECODE_SAMSUNG true #define SEND_SAMSUNG true +#define DECODE_SAMSUNG36 true +#define SEND_SAMSUNG36 true + #define DECODE_SAMSUNG_AC true #define SEND_SAMSUNG_AC true @@ -199,6 +204,27 @@ #define DECODE_PIONEER true #define SEND_PIONEER true + +#define DECODE_DAIKIN2 true +#define SEND_DAIKIN2 true + +#define DECODE_VESTEL_AC true +#define SEND_VESTEL_AC true + +#define DECODE_TECO true +#define SEND_TECO true + +#define DECODE_TCL112AC true +#define SEND_TCL112AC true + +#define DECODE_LEGOPF true +#define SEND_LEGOPF true + +#define DECODE_MITSUBISHIHEAVY true +#define SEND_MITSUBISHIHEAVY true + +#define DECODE_DAIKIN216 true +#define SEND_DAIKIN216 true */ // Tasmota supported protocols (less protocols is less code size) @@ -233,6 +259,9 @@ #define DECODE_SAMSUNG true #define SEND_SAMSUNG true +#define DECODE_SAMSUNG36 false +#define SEND_SAMSUNG36 false + #define DECODE_SAMSUNG_AC false #define SEND_SAMSUNG_AC false @@ -347,12 +376,35 @@ #define DECODE_PIONEER false #define SEND_PIONEER false +#define DECODE_DAIKIN2 false +#define SEND_DAIKIN2 false + +#define DECODE_VESTEL_AC false +#define SEND_VESTEL_AC false + +#define DECODE_TECO false +#define SEND_TECO false + +#define DECODE_TCL112AC false +#define SEND_TCL112AC false + +#define DECODE_LEGOPF false +#define SEND_LEGOPF false + +#define DECODE_MITSUBISHIHEAVY false +#define SEND_MITSUBISHIHEAVY false + +#define DECODE_DAIKIN216 false +#define SEND_DAIKIN216 false + #if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \ DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \ DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \ DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2 || DECODE_HAIER_AC_YRW02 || \ DECODE_WHIRLPOOL_AC || DECODE_SAMSUNG_AC || DECODE_ELECTRA_AC || \ - DECODE_PANASONIC_AC || DECODE_MWM) + DECODE_PANASONIC_AC || DECODE_MWM || DECODE_DAIKIN2 || \ + DECODE_VESTEL_AC || DECODE_TCL112AC || DECODE_MITSUBISHIHEAVY || \ + DECODE_DAIKIN216) #define DECODE_AC true // We need some common infrastructure for decoding A/Cs. #else #define DECODE_AC false // We don't need that infrastructure. @@ -376,54 +428,65 @@ enum decode_type_t { RC6, NEC, SONY, - PANASONIC, + PANASONIC, // (5) JVC, SAMSUNG, WHYNTER, AIWA_RC_T501, - LG, + LG, // (10) SANYO, MITSUBISHI, DISH, SHARP, - COOLIX, + COOLIX, // (15) DAIKIN, DENON, KELVINATOR, SHERWOOD, - MITSUBISHI_AC, + MITSUBISHI_AC, // (20) RCMM, SANYO_LC7461, RC5X, GREE, - PRONTO, // Technically not a protocol, but an encoding. + PRONTO, // Technically not a protocol, but an encoding. (25) NEC_LIKE, ARGO, TROTEC, NIKAI, - RAW, // Technically not a protocol, but an encoding. + RAW, // Technically not a protocol, but an encoding. (30) GLOBALCACHE, // Technically not a protocol, but an encoding. TOSHIBA_AC, FUJITSU_AC, MIDEA, - MAGIQUEST, + MAGIQUEST, // (35) LASERTAG, CARRIER_AC, HAIER_AC, MITSUBISHI2, - HITACHI_AC, + HITACHI_AC, // (40) HITACHI_AC1, HITACHI_AC2, GICABLE, HAIER_AC_YRW02, - WHIRLPOOL_AC, + WHIRLPOOL_AC, // (45) SAMSUNG_AC, LUTRON, ELECTRA_AC, PANASONIC_AC, - PIONEER, + PIONEER, // (50) LG2, MWM, + DAIKIN2, + VESTEL_AC, + TECO, // (55) + SAMSUNG36, + TCL112AC, + LEGOPF, + MITSUBISHI_HEAVY_88, + MITSUBISHI_HEAVY_152, // 60 + DAIKIN216, + // Add new entries before this one, and update it to point to the last entry. + kLastDecodeType = DAIKIN216, }; // Message lengths & required repeat values @@ -433,13 +496,22 @@ const uint16_t kSingleRepeat = 1; const uint16_t kAiwaRcT501Bits = 15; const uint16_t kAiwaRcT501MinRepeats = kSingleRepeat; const uint16_t kArgoStateLength = 12; +const uint16_t kArgoDefaultRepeat = kNoRepeat; const uint16_t kCoolixBits = 24; +const uint16_t kCoolixDefaultRepeat = 1; const uint16_t kCarrierAcBits = 32; const uint16_t kCarrierAcMinRepeat = kNoRepeat; -// Daikin has a lot of static stuff that is discarded -const uint16_t kDaikinRawBits = 583; -const uint16_t kDaikinStateLength = 27; +const uint16_t kDaikinStateLength = 35; const uint16_t kDaikinBits = kDaikinStateLength * 8; +const uint16_t kDaikinStateLengthShort = kDaikinStateLength - 8; +const uint16_t kDaikinBitsShort = kDaikinStateLengthShort * 8; +const uint16_t kDaikinDefaultRepeat = kNoRepeat; +const uint16_t kDaikin2StateLength = 39; +const uint16_t kDaikin2Bits = kDaikin2StateLength * 8; +const uint16_t kDaikin2DefaultRepeat = kNoRepeat; +const uint16_t kDaikin216StateLength = 27; +const uint16_t kDaikin216Bits = kDaikin216StateLength * 8; +const uint16_t kDaikin216DefaultRepeat = kNoRepeat; const uint16_t kDenonBits = 15; const uint16_t kDenonLegacyBits = 14; const uint16_t kDishBits = 16; @@ -455,12 +527,16 @@ const uint16_t kGicableBits = 16; const uint16_t kGicableMinRepeat = kSingleRepeat; const uint16_t kGreeStateLength = 8; const uint16_t kGreeBits = kGreeStateLength * 8; +const uint16_t kGreeDefaultRepeat = kNoRepeat; const uint16_t kHaierACStateLength = 9; const uint16_t kHaierACBits = kHaierACStateLength * 8; +const uint16_t kHaierAcDefaultRepeat = kNoRepeat; const uint16_t kHaierACYRW02StateLength = 14; const uint16_t kHaierACYRW02Bits = kHaierACYRW02StateLength * 8; +const uint16_t kHaierAcYrw02DefaultRepeat = kNoRepeat; const uint16_t kHitachiAcStateLength = 28; const uint16_t kHitachiAcBits = kHitachiAcStateLength * 8; +const uint16_t kHitachiAcDefaultRepeat = kNoRepeat; const uint16_t kHitachiAc1StateLength = 13; const uint16_t kHitachiAc1Bits = kHitachiAc1StateLength * 8; const uint16_t kHitachiAc2StateLength = 53; @@ -468,8 +544,11 @@ const uint16_t kHitachiAc2Bits = kHitachiAc2StateLength * 8; const uint16_t kJvcBits = 16; const uint16_t kKelvinatorStateLength = 16; const uint16_t kKelvinatorBits = kKelvinatorStateLength * 8; +const uint16_t kKelvinatorDefaultRepeat = kNoRepeat; const uint16_t kLasertagBits = 13; const uint16_t kLasertagMinRepeat = kNoRepeat; +const uint16_t kLegoPfBits = 16; +const uint16_t kLegoPfMinRepeat = kNoRepeat; const uint16_t kLgBits = 28; const uint16_t kLg32Bits = 32; const uint16_t kLutronBits = 35; @@ -483,6 +562,12 @@ const uint16_t kMitsubishiMinRepeat = kSingleRepeat; const uint16_t kMitsubishiACStateLength = 18; const uint16_t kMitsubishiACBits = kMitsubishiACStateLength * 8; const uint16_t kMitsubishiACMinRepeat = kSingleRepeat; +const uint16_t kMitsubishiHeavy88StateLength = 11; +const uint16_t kMitsubishiHeavy88Bits = kMitsubishiHeavy88StateLength * 8; +const uint16_t kMitsubishiHeavy88MinRepeat = kNoRepeat; +const uint16_t kMitsubishiHeavy152StateLength = 19; +const uint16_t kMitsubishiHeavy152Bits = kMitsubishiHeavy152StateLength * 8; +const uint16_t kMitsubishiHeavy152MinRepeat = kNoRepeat; const uint16_t kNikaiBits = 24; const uint16_t kNECBits = 32; const uint16_t kPanasonicBits = 48; @@ -491,6 +576,7 @@ const uint16_t kPanasonicAcStateLength = 27; const uint16_t kPanasonicAcStateShortLength = 16; const uint16_t kPanasonicAcBits = kPanasonicAcStateLength * 8; const uint16_t kPanasonicAcShortBits = kPanasonicAcStateShortLength * 8; +const uint16_t kPanasonicAcDefaultRepeat = kNoRepeat; const uint16_t kPioneerBits = 64; const uint16_t kProntoMinLength = 6; const uint16_t kRC5RawBits = 14; @@ -500,10 +586,12 @@ const uint16_t kRC6Mode0Bits = 20; // Excludes the 'start' bit. const uint16_t kRC6_36Bits = 36; // Excludes the 'start' bit. const uint16_t kRCMMBits = 24; const uint16_t kSamsungBits = 32; +const uint16_t kSamsung36Bits = 36; const uint16_t kSamsungAcStateLength = 14; const uint16_t kSamsungAcBits = kSamsungAcStateLength * 8; const uint16_t kSamsungAcExtendedStateLength = 21; const uint16_t kSamsungAcExtendedBits = kSamsungAcExtendedStateLength * 8; +const uint16_t kSamsungAcDefaultRepeat = kNoRepeat; const uint16_t kSanyoSA8650BBits = 12; const uint16_t kSanyoLC7461AddressBits = 13; const uint16_t kSanyoLC7461CommandBits = 8; @@ -519,13 +607,22 @@ const uint16_t kSony15Bits = 15; const uint16_t kSony20Bits = 20; const uint16_t kSonyMinBits = 12; const uint16_t kSonyMinRepeat = 2; +const uint16_t kTcl112AcStateLength = 14; +const uint16_t kTcl112AcBits = kTcl112AcStateLength * 8; +const uint16_t kTcl112AcDefaultRepeat = kNoRepeat; +const uint16_t kTecoBits = 35; +const uint16_t kTecoDefaultRepeat = kNoRepeat; const uint16_t kToshibaACStateLength = 9; const uint16_t kToshibaACBits = kToshibaACStateLength * 8; const uint16_t kToshibaACMinRepeat = kSingleRepeat; const uint16_t kTrotecStateLength = 9; +const uint16_t kTrotecDefaultRepeat = kNoRepeat; const uint16_t kWhirlpoolAcStateLength = 21; const uint16_t kWhirlpoolAcBits = kWhirlpoolAcStateLength * 8; +const uint16_t kWhirlpoolAcDefaultRepeat = kNoRepeat; const uint16_t kWhynterBits = 32; +const uint8_t kVestelAcBits = 56; + // Legacy defines. (Deprecated) #define AIWA_RC_T501_BITS kAiwaRcT501Bits @@ -598,4 +695,14 @@ const uint16_t kWhynterBits = 32; #define DPRINTLN(x) #endif // DEBUG +#ifdef UNIT_TEST +#ifndef F +// Create a no-op F() macro so the code base still compiles outside of the +// Arduino framework. Thus we can safely use the Arduino 'F()' macro through-out +// the code base. That macro stores constants in Flash (PROGMEM) memory. +// See: https://github.com/markszabo/IRremoteESP8266/issues/667 +#define F(x) x +#endif // F +#endif // UNIT_TEST + #endif // IRREMOTEESP8266_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp b/lib/IRremoteESP8266-2.6.0/src/IRsend.cpp similarity index 92% rename from lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp rename to lib/IRremoteESP8266-2.6.0/src/IRsend.cpp index 96f95172d..22c0c874b 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/IRsend.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/IRsend.cpp @@ -1,6 +1,6 @@ // Copyright 2009 Ken Shirriff // Copyright 2015 Mark Szabo -// Copyright 2017 David Conran +// Copyright 2017,2019 David Conran #include "IRsend.h" #ifndef UNIT_TEST @@ -110,6 +110,9 @@ void IRsend::enableIROut(uint32_t freq, uint8_t duty) { } if (freq < 1000) // Were we given kHz? Supports the old call usage. freq *= 1000; +#ifdef UNIT_TEST + _freq_unittest = freq; +#endif // UNIT_TEST uint32_t period = calcUSecPeriod(freq); // Nr. of uSeconds the LED will be on per pulse. onTimePeriod = (period * _dutycycle) / kDutyMax; @@ -488,57 +491,24 @@ void IRsend::sendRaw(uint16_t buf[], uint16_t len, uint16_t hz) { } #endif // SEND_RAW -#ifndef UNIT_TEST -void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) { +// Send a simple (up to 64 bits) IR message of a given type. +// An unknown/unsupported type will do nothing. +// Args: +// type: Protocol number/type of the message you want to send. +// data: The data you want to send (up to 64 bits). +// nbits: How many bits long the message is to be. +// Returns: +// bool: True if it is a type we can attempt to send, false if not. +bool IRsend::send(decode_type_t type, uint64_t data, uint16_t nbits) { switch (type) { -#if SEND_NEC - case NEC: - sendNEC(data, nbits); +#if SEND_AIWA_RC_T501 + case AIWA_RC_T501: + sendAiwaRCT501(data, nbits); break; #endif -#if SEND_SONY - case SONY: - sendSony(data, nbits); - break; -#endif -#if SEND_RC5 - case RC5: - sendRC5(data, nbits); - break; -#endif -#if SEND_RC6 - case RC6: - sendRC6(data, nbits); - break; -#endif -#if SEND_DISH - case DISH: - sendDISH(data, nbits); - break; -#endif -#if SEND_JVC - case JVC: - sendJVC(data, nbits); - break; -#endif -#if SEND_SAMSUNG - case SAMSUNG: - sendSAMSUNG(data, nbits); - break; -#endif -#if SEND_LG - case LG: - sendLG(data, nbits); - break; -#endif -#if SEND_LG - case LG2: - sendLG2(data, nbits); - break; -#endif -#if SEND_WHYNTER - case WHYNTER: - sendWhynter(data, nbits); +#if SEND_CARRIER_AC + case CARRIER_AC: + sendCarrierAC(data, nbits); break; #endif #if SEND_COOLIX @@ -551,14 +521,57 @@ void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) { sendDenon(data, nbits); break; #endif -#if SEND_SHERWOOD - case SHERWOOD: - sendSherwood(data, nbits); +#if SEND_DISH + case DISH: + sendDISH(data, nbits); break; #endif -#if SEND_RCMM - case RCMM: - sendRCMM(data, nbits); +#if SEND_GICABLE + case GICABLE: + sendGICable(data, nbits); + break; +#endif +#if SEND_GREE + case GREE: + sendGree(data, nbits); + break; +#endif +#if SEND_JVC + case JVC: + sendJVC(data, nbits); + break; +#endif +#if SEND_LASERTAG + case LASERTAG: + sendLasertag(data, nbits); + break; +#endif +#if SEND_LEGOPF + case LEGOPF: + sendLegoPf(data, nbits); + break; +#endif +#if SEND_LG + case LG: + sendLG(data, nbits); + break; + case LG2: + sendLG2(data, nbits); + break; +#endif +#if SEND_LUTRON + case LUTRON: + sendLutron(data, nbits); + break; +#endif +#if SEND_MAGIQUEST + case MAGIQUEST: + sendMagiQuest(data, nbits); + break; +#endif +#if SEND_MIDEA + case MIDEA: + sendMidea(data, nbits); break; #endif #if SEND_MITSUBISHI @@ -571,24 +584,20 @@ void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) { sendMitsubishi2(data, nbits); break; #endif -#if SEND_SHARP - case SHARP: - sendSharpRaw(data, nbits); +#if SEND_NIKAI + case NIKAI: + sendNikai(data, nbits); break; #endif -#if SEND_AIWA_RC_T501 - case AIWA_RC_T501: - sendAiwaRCT501(data, nbits); +#if SEND_NEC + case NEC: + case NEC_LIKE: + sendNEC(data, nbits); break; #endif -#if SEND_MIDEA - case MIDEA: - sendMidea(data, nbits); - break; -#endif -#if SEND_GICABLE - case GICABLE: - sendGICable(data, nbits); +#if SEND_PANASONIC + case PANASONIC: + sendPanasonic64(data, nbits); break; #endif #if SEND_PIONEER @@ -596,6 +605,68 @@ void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) { sendPioneer(data, nbits); break; #endif - } -} +#if SEND_RC5 + case RC5: + sendRC5(data, nbits); + break; #endif +#if SEND_RC6 + case RC6: + sendRC6(data, nbits); + break; +#endif +#if SEND_RCMM + case RCMM: + sendRCMM(data, nbits); + break; +#endif +#if SEND_SAMSUNG + case SAMSUNG: + sendSAMSUNG(data, nbits); + break; +#endif +#if SEND_SAMSUNG36 + case SAMSUNG36: + sendSamsung36(data, nbits); + break; +#endif +#if SEND_SANYO + case SANYO_LC7461: + sendSanyoLC7461(data, nbits); + break; +#endif +#if SEND_SHARP + case SHARP: + sendSharpRaw(data, nbits); + break; +#endif +#if SEND_SHERWOOD + case SHERWOOD: + sendSherwood(data, nbits); + break; +#endif +#if SEND_SONY + case SONY: + sendSony(data, nbits); + break; +#endif +#if SEND_TECO + case TECO: + sendTeco(data, nbits); + break; +#endif +#if SEND_VESTEL_AC + case VESTEL_AC: + sendVestelAc(data, nbits); + break; +#endif +#if SEND_WHYNTER + case WHYNTER: + sendWhynter(data, nbits); + break; +#endif + default: + return false; + } + return true; +} diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRsend.h b/lib/IRremoteESP8266-2.6.0/src/IRsend.h similarity index 77% rename from lib/IRremoteESP8266-2.5.2.03/src/IRsend.h rename to lib/IRremoteESP8266-2.6.0/src/IRsend.h index 8e2dc248e..b065f6582 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/IRsend.h +++ b/lib/IRremoteESP8266-2.6.0/src/IRsend.h @@ -28,6 +28,49 @@ const uint8_t kDutyMax = 100; // Percentage // delayMicroseconds() is only accurate to 16383us. // Ref: https://www.arduino.cc/en/Reference/delayMicroseconds const uint16_t kMaxAccurateUsecDelay = 16383; +// Usecs to wait between messages we don't know the proper gap time. +const uint32_t kDefaultMessageGap = 100000; + + +namespace stdAc { + enum class opmode_t { + kOff = -1, + kAuto = 0, + kCool = 1, + kHeat = 2, + kDry = 3, + kFan = 4, + }; + + enum class fanspeed_t { + kAuto = 0, + kMin = 1, + kLow = 2, + kMedium = 3, + kHigh = 4, + kMax = 5, + }; + + enum class swingv_t { + kOff = -1, + kAuto = 0, + kHighest = 1, + kHigh = 2, + kMiddle = 3, + kLow = 4, + kLowest = 5, + }; + + enum class swingh_t { + kOff = -1, + kAuto = 0, // a.k.a. On. + kLeftMax = 1, + kLeft = 2, + kMiddle = 3, + kRight = 4, + kRightMax = 5, + }; +}; // namespace stdAc // Classes class IRsend { @@ -66,7 +109,7 @@ class IRsend { const uint8_t *dataptr, const uint16_t nbytes, const uint16_t frequency, const bool MSBfirst, const uint16_t repeat, const uint8_t dutycycle); - void send(uint16_t type, uint64_t data, uint16_t nbits); + bool send(decode_type_t type, uint64_t data, uint16_t nbits); #if (SEND_NEC || SEND_SHERWOOD || SEND_AIWA_RC_T501 || SEND_SANYO) void sendNEC(uint64_t data, uint16_t nbits = kNECBits, uint16_t repeat = kNoRepeat); @@ -92,10 +135,14 @@ class IRsend { uint16_t repeat = kNoRepeat); uint32_t encodeSAMSUNG(uint8_t customer, uint8_t command); #endif +#if SEND_SAMSUNG36 + void sendSamsung36(const uint64_t data, const uint16_t nbits = kSamsung36Bits, + const uint16_t repeat = kNoRepeat); +#endif #if SEND_SAMSUNG_AC - void sendSamsungAC(unsigned char data[], - uint16_t nbytes = kSamsungAcStateLength, - uint16_t repeat = kNoRepeat); + void sendSamsungAC(const unsigned char data[], + const uint16_t nbytes = kSamsungAcStateLength, + const uint16_t repeat = kSamsungAcDefaultRepeat); #endif #if SEND_LG void sendLG(uint64_t data, uint16_t nbits = kLgBits, @@ -166,7 +213,7 @@ class IRsend { #endif #if SEND_COOLIX void sendCOOLIX(uint64_t data, uint16_t nbits = kCoolixBits, - uint16_t repeat = kNoRepeat); + uint16_t repeat = kCoolixDefaultRepeat); #endif #if SEND_WHYNTER void sendWhynter(uint64_t data, uint16_t nbits = kWhynterBits, @@ -185,6 +232,16 @@ class IRsend { uint16_t nbytes = kMitsubishiACStateLength, uint16_t repeat = kMitsubishiACMinRepeat); #endif +#if SEND_MITSUBISHIHEAVY + void sendMitsubishiHeavy88( + const unsigned char data[], + const uint16_t nbytes = kMitsubishiHeavy88StateLength, + const uint16_t repeat = kMitsubishiHeavy88MinRepeat); + void sendMitsubishiHeavy152( + const unsigned char data[], + const uint16_t nbytes = kMitsubishiHeavy152StateLength, + const uint16_t repeat = kMitsubishiHeavy152MinRepeat); +#endif #if SEND_FUJITSU_AC void sendFujitsuAC(unsigned char data[], uint16_t nbytes, uint16_t repeat = kFujitsuAcMinRepeat); @@ -195,12 +252,21 @@ class IRsend { #if SEND_KELVINATOR void sendKelvinator(unsigned char data[], uint16_t nbytes = kKelvinatorStateLength, - uint16_t repeat = kNoRepeat); + uint16_t repeat = kKelvinatorDefaultRepeat); #endif #if SEND_DAIKIN - void sendDaikin(unsigned char data[], uint16_t nbytes = kDaikinStateLength, - uint16_t repeat = kNoRepeat); - void sendDaikinGapHeader(); + void sendDaikin(const unsigned char data[], + const uint16_t nbytes = kDaikinStateLength, + const uint16_t repeat = kDaikinDefaultRepeat); +#endif +#if SEND_DAIKIN2 + void sendDaikin2(unsigned char data[], uint16_t nbytes = kDaikin2StateLength, + uint16_t repeat = kDaikin2DefaultRepeat); +#endif +#if SEND_DAIKIN216 + void sendDaikin216(const unsigned char data[], + const uint16_t nbytes = kDaikin216StateLength, + const uint16_t repeat = kDaikin216DefaultRepeat); #endif #if SEND_AIWA_RC_T501 void sendAiwaRCT501(uint64_t data, uint16_t nbits = kAiwaRcT501Bits, @@ -208,20 +274,20 @@ class IRsend { #endif #if SEND_GREE void sendGree(uint64_t data, uint16_t nbits = kGreeBits, - uint16_t repeat = kNoRepeat); + uint16_t repeat = kGreeDefaultRepeat); void sendGree(uint8_t data[], uint16_t nbytes = kGreeStateLength, - uint16_t repeat = kNoRepeat); + uint16_t repeat = kGreeDefaultRepeat); #endif #if SEND_PRONTO void sendPronto(uint16_t data[], uint16_t len, uint16_t repeat = kNoRepeat); #endif #if SEND_ARGO void sendArgo(unsigned char data[], uint16_t nbytes = kArgoStateLength, - uint16_t repeat = kNoRepeat); + uint16_t repeat = kArgoDefaultRepeat); #endif #if SEND_TROTEC void sendTrotec(unsigned char data[], uint16_t nbytes = kTrotecStateLength, - uint16_t repeat = kNoRepeat); + uint16_t repeat = kTrotecDefaultRepeat); #endif #if SEND_NIKAI void sendNikai(uint64_t data, uint16_t nbits = kNikaiBits, @@ -251,17 +317,17 @@ class IRsend { #endif #if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02) void sendHaierAC(unsigned char data[], uint16_t nbytes = kHaierACStateLength, - uint16_t repeat = kNoRepeat); + uint16_t repeat = kHaierAcDefaultRepeat); #endif #if SEND_HAIER_AC_YRW02 void sendHaierACYRW02(unsigned char data[], uint16_t nbytes = kHaierACYRW02StateLength, - uint16_t repeat = kNoRepeat); + uint16_t repeat = kHaierAcYrw02DefaultRepeat); #endif #if SEND_HITACHI_AC void sendHitachiAC(unsigned char data[], uint16_t nbytes = kHitachiAcStateLength, - uint16_t repeat = kNoRepeat); + uint16_t repeat = kHitachiAcDefaultRepeat); #endif #if SEND_HITACHI_AC1 void sendHitachiAC1(unsigned char data[], @@ -280,7 +346,7 @@ class IRsend { #if SEND_WHIRLPOOL_AC void sendWhirlpoolAC(unsigned char data[], uint16_t nbytes = kWhirlpoolAcStateLength, - uint16_t repeat = kNoRepeat); + uint16_t repeat = kWhirlpoolAcDefaultRepeat); #endif #if SEND_LUTRON void sendLutron(uint64_t data, uint16_t nbits = kLutronBits, @@ -294,7 +360,7 @@ class IRsend { #if SEND_PANASONIC_AC void sendPanasonicAC(unsigned char data[], uint16_t nbytes = kPanasonicAcStateLength, - uint16_t repeat = kNoRepeat); + uint16_t repeat = kPanasonicAcDefaultRepeat); #endif #if SEND_PIONEER void sendPioneer(const uint64_t data, const uint16_t nbits = kPioneerBits, @@ -305,6 +371,24 @@ class IRsend { void sendMWM(unsigned char data[], uint16_t nbytes, uint16_t repeat = kNoRepeat); #endif +#if SEND_VESTEL_AC + void sendVestelAc(const uint64_t data, const uint16_t nbits = kVestelAcBits, + const uint16_t repeat = kNoRepeat); +#endif +#if SEND_TCL112AC + void sendTcl112Ac(const unsigned char data[], + const uint16_t nbytes = kTcl112AcStateLength, + const uint16_t repeat = kTcl112AcDefaultRepeat); +#endif +#if SEND_TECO + void sendTeco(uint64_t data, uint16_t nbits = kTecoBits, + uint16_t repeat = kNoRepeat); +#endif +#if SEND_LEGOPF + void sendLegoPf(const uint64_t data, const uint16_t nbits = kLegoPfBits, + const uint16_t repeat = kLegoPfMinRepeat); +#endif + protected: #ifdef UNIT_TEST @@ -319,8 +403,12 @@ class IRsend { uint8_t outputOff; VIRTUAL void ledOff(); VIRTUAL void ledOn(); +#ifndef UNIT_TEST private: +#else + uint32_t _freq_unittest; +#endif // UNIT_TEST uint16_t onTimePeriod; uint16_t offTimePeriod; uint16_t IRpin; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRtimer.cpp b/lib/IRremoteESP8266-2.6.0/src/IRtimer.cpp similarity index 53% rename from lib/IRremoteESP8266-2.5.2.03/src/IRtimer.cpp rename to lib/IRremoteESP8266-2.6.0/src/IRtimer.cpp index 029637cbb..4173d763b 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/IRtimer.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/IRtimer.cpp @@ -7,12 +7,12 @@ #ifdef UNIT_TEST // Used to help simulate elapsed time in unit tests. -extern uint32_t _IRtimer_unittest_now; +uint32_t _IRtimer_unittest_now = 0; +uint32_t _TimerMs_unittest_now = 0; #endif // UNIT_TEST // This class performs a simple time in useconds since instantiated. // Handles when the system timer wraps around (once). - IRtimer::IRtimer() { reset(); } void IRtimer::reset() { @@ -39,3 +39,32 @@ uint32_t IRtimer::elapsed() { #ifdef UNIT_TEST void IRtimer::add(uint32_t usecs) { _IRtimer_unittest_now += usecs; } #endif // UNIT_TEST + +// This class performs a simple time in milli-seoncds since instantiated. +// Handles when the system timer wraps around (once). +TimerMs::TimerMs() { reset(); } + +void TimerMs::reset() { +#ifndef UNIT_TEST + start = millis(); +#else + start = _TimerMs_unittest_now; +#endif +} + +uint32_t TimerMs::elapsed() { +#ifndef UNIT_TEST + uint32_t now = millis(); +#else + uint32_t now = _TimerMs_unittest_now; +#endif + if (start <= now) // Check if the system timer has wrapped. + return now - start; // No wrap. + else + return UINT32_MAX - start + now; // Has wrapped. +} + +// Only used in unit testing. +#ifdef UNIT_TEST +void TimerMs::add(uint32_t msecs) { _IRtimer_unittest_now += msecs; } +#endif // UNIT_TEST diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRtimer.h b/lib/IRremoteESP8266-2.6.0/src/IRtimer.h similarity index 64% rename from lib/IRremoteESP8266-2.5.2.03/src/IRtimer.h rename to lib/IRremoteESP8266-2.6.0/src/IRtimer.h index baca1cf74..d00e1d0fa 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/IRtimer.h +++ b/lib/IRremoteESP8266-2.6.0/src/IRtimer.h @@ -20,4 +20,16 @@ class IRtimer { uint32_t start; }; +class TimerMs { + public: + TimerMs(); + void reset(); + uint32_t elapsed(); +#ifdef UNIT_TEST + static void add(uint32_t msecs); +#endif // UNIT_TEST + + private: + uint32_t start; +}; #endif // IRTIMER_H_ diff --git a/lib/IRremoteESP8266-2.6.0/src/IRutils.cpp b/lib/IRremoteESP8266-2.6.0/src/IRutils.cpp new file mode 100644 index 000000000..d90925241 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/IRutils.cpp @@ -0,0 +1,768 @@ +// Copyright 2017 David Conran + +#include "IRutils.h" +#ifndef UNIT_TEST +#include +#endif + +#define __STDC_LIMIT_MACROS +#include +#include +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" + +// Reverse the order of the requested least significant nr. of bits. +// Args: +// input: Bit pattern/integer to reverse. +// nbits: Nr. of bits to reverse. +// Returns: +// The reversed bit pattern. +uint64_t reverseBits(uint64_t input, uint16_t nbits) { + if (nbits <= 1) return input; // Reversing <= 1 bits makes no change at all. + // Cap the nr. of bits to rotate to the max nr. of bits in the input. + nbits = std::min(nbits, (uint16_t)(sizeof(input) * 8)); + uint64_t output = 0; + for (uint16_t i = 0; i < nbits; i++) { + output <<= 1; + output |= (input & 1); + input >>= 1; + } + // Merge any remaining unreversed bits back to the top of the reversed bits. + return (input << nbits) | output; +} + +// Convert a uint64_t (unsigned long long) to a string. +// Arduino String/toInt/Serial.print() can't handle printing 64 bit values. +// +// Args: +// input: The value to print +// base: The output base. +// Returns: +// A string representation of the integer. +// Note: Based on Arduino's Print::printNumber() +#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. +String uint64ToString(uint64_t input, uint8_t base) { + String result = ""; +#else +std::string uint64ToString(uint64_t input, uint8_t base) { + std::string result = ""; +#endif + // prevent issues if called with base <= 1 + if (base < 2) base = 10; + // Check we have a base that we can actually print. + // i.e. [0-9A-Z] == 36 + if (base > 36) base = 10; + + do { + char c = input % base; + input /= base; + + if (c < 10) + c += '0'; + else + c += 'A' - 10; + result = c + result; + } while (input); + return result; +} + +#ifdef ARDUINO +// Print a uint64_t/unsigned long long to the Serial port +// Serial.print() can't handle printing long longs. (uint64_t) +// +// Args: +// input: The value to print +// base: The output base. +void serialPrintUint64(uint64_t input, uint8_t base) { + Serial.print(uint64ToString(input, base)); +} +#endif + +// Convert a c-style str to a decode_type_t +// Note: Assumes str is upper case. +// +// Args: +// str: An upper-case C-style string. +// Returns: +// A decode_type_t enum. +decode_type_t strToDecodeType(const char *str) { + if (!strcmp(str, "UNKNOWN")) + return decode_type_t::UNKNOWN; + else if (!strcmp(str, "UNUSED")) + return decode_type_t::UNUSED; + else if (!strcmp(str, "AIWA_RC_T501")) + return decode_type_t::AIWA_RC_T501; + else if (!strcmp(str, "ARGO")) + return decode_type_t::ARGO; + else if (!strcmp(str, "CARRIER_AC")) + return decode_type_t::CARRIER_AC; + else if (!strcmp(str, "COOLIX")) + return decode_type_t::COOLIX; + else if (!strcmp(str, "DAIKIN")) + return decode_type_t::DAIKIN; + else if (!strcmp(str, "DAIKIN2")) + return decode_type_t::DAIKIN2; + else if (!strcmp(str, "DAIKIN216")) + return decode_type_t::DAIKIN216; + else if (!strcmp(str, "DENON")) + return decode_type_t::DENON; + else if (!strcmp(str, "DISH")) + return decode_type_t::DISH; + else if (!strcmp(str, "ELECTRA_AC")) + return decode_type_t::ELECTRA_AC; + else if (!strcmp(str, "FUJITSU_AC")) + return decode_type_t::FUJITSU_AC; + else if (!strcmp(str, "GICABLE")) + return decode_type_t::GICABLE; + else if (!strcmp(str, "GLOBALCACHE")) + return decode_type_t::GLOBALCACHE; + else if (!strcmp(str, "GREE")) + return decode_type_t::GREE; + else if (!strcmp(str, "HAIER_AC")) + return decode_type_t::HAIER_AC; + else if (!strcmp(str, "HAIER_AC_YRW02")) + return decode_type_t::HAIER_AC_YRW02; + else if (!strcmp(str, "HITACHI_AC")) + return decode_type_t::HITACHI_AC; + else if (!strcmp(str, "HITACHI_AC1")) + return decode_type_t::HITACHI_AC1; + else if (!strcmp(str, "HITACHI_AC2")) + return decode_type_t::HITACHI_AC2; + else if (!strcmp(str, "JVC")) + return decode_type_t::JVC; + else if (!strcmp(str, "KELVINATOR")) + return decode_type_t::KELVINATOR; + else if (!strcmp(str, "LEGOPF")) + return decode_type_t::LEGOPF; + else if (!strcmp(str, "LG")) + return decode_type_t::LG; + else if (!strcmp(str, "LG2")) + return decode_type_t::LG2; + else if (!strcmp(str, "LASERTAG")) + return decode_type_t::LASERTAG; + else if (!strcmp(str, "LUTRON")) + return decode_type_t::LUTRON; + else if (!strcmp(str, "MAGIQUEST")) + return decode_type_t::MAGIQUEST; + else if (!strcmp(str, "MIDEA")) + return decode_type_t::MIDEA; + else if (!strcmp(str, "MITSUBISHI")) + return decode_type_t::MITSUBISHI; + else if (!strcmp(str, "MITSUBISHI2")) + return decode_type_t::MITSUBISHI2; + else if (!strcmp(str, "MITSUBISHI_AC")) + return decode_type_t::MITSUBISHI_AC; + else if (!strcmp(str, "MWM")) + return decode_type_t::MWM; + else if (!strcmp(str, "NEC") || !strcmp(str, "NEC (NON-STRICT")) + return decode_type_t::NEC; + else if (!strcmp(str, "NIKAI")) + return decode_type_t::NIKAI; + else if (!strcmp(str, "PANASONIC")) + return decode_type_t::PANASONIC; + else if (!strcmp(str, "PANASONIC_AC")) + return decode_type_t::PANASONIC_AC; + else if (!strcmp(str, "PIONEER")) + return decode_type_t::PIONEER; + else if (!strcmp(str, "PRONTO")) + return decode_type_t::PRONTO; + else if (!strcmp(str, "RAW")) + return decode_type_t::RAW; + else if (!strcmp(str, "RC5")) + return decode_type_t::RC5; + else if (!strcmp(str, "RC5X")) + return decode_type_t::RC5X; + else if (!strcmp(str, "RC6")) + return decode_type_t::RC6; + else if (!strcmp(str, "RCMM")) + return decode_type_t::RCMM; + else if (!strcmp(str, "SAMSUNG")) + return decode_type_t::SAMSUNG; + else if (!strcmp(str, "SAMSUNG36")) + return decode_type_t::SAMSUNG36; + else if (!strcmp(str, "SAMSUNG_AC")) + return decode_type_t::SAMSUNG_AC; + else if (!strcmp(str, "SANYO")) + return decode_type_t::SANYO; + else if (!strcmp(str, "SANYO_LC7461")) + return decode_type_t::SANYO_LC7461; + else if (!strcmp(str, "SHARP")) + return decode_type_t::SHARP; + else if (!strcmp(str, "SHERWOOD")) + return decode_type_t::SHERWOOD; + else if (!strcmp(str, "SONY")) + return decode_type_t::SONY; + else if (!strcmp(str, "TCL112AC")) + return decode_type_t::TCL112AC; + else if (!strcmp(str, "TECO")) + return decode_type_t::TECO; + else if (!strcmp(str, "TOSHIBA_AC")) + return decode_type_t::TOSHIBA_AC; + else if (!strcmp(str, "TROTEC")) + return decode_type_t::TROTEC; + else if (!strcmp(str, "VESTEL_AC")) + return decode_type_t::VESTEL_AC; + else if (!strcmp(str, "WHIRLPOOL_AC")) + return decode_type_t::WHIRLPOOL_AC; + else if (!strcmp(str, "WHYNTER")) + return decode_type_t::WHYNTER; + // Handle integer values of the type by converting to a string and back again. + decode_type_t result = strToDecodeType( + typeToString((decode_type_t)atoi(str)).c_str()); + if (result > 0) + return result; + else + return decode_type_t::UNKNOWN; +} + +// Escape any special HTML (unsafe) characters in a string. e.g. anti-XSS. +// Args: +// unescaped: A string containing text to make HTML safe. +// Returns: +// A string that is HTML safe. +#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. +String htmlEscape(const String unescaped) { + String result = ""; +#else +std::string htmlEscape(const std::string unescaped) { + std::string result = ""; +#endif + uint16_t ulen = unescaped.length(); + result.reserve(ulen); // The result will be at least the size of input. + for (size_t i = 0; i < ulen; i++) { + char c = unescaped[i]; + switch (c) { + // ';!-"<>=&#{}() are all unsafe. + case '\'': + result += F("'"); + break; + case ';': + result += F(";"); + break; + case '!': + result += F("!"); + break; + case '-': + result += F("‐"); + break; + case '\"': + result += F("""); + break; + case '<': + result += F("<"); + break; + case '>': + result += F(">"); + break; + case '=': + result += F("&#equals;"); + break; + case '&': + result += F("&"); + break; + case '#': + result += F("#"); + break; + case '{': + result += F("{"); + break; + case '}': + result += F("}"); + break; + case '(': + result += F("("); + break; + case ')': + result += F(")"); + break; + default: + result += c; + } + } + return result; +} + +// Convert a protocol type (enum etc) to a human readable string. +// Args: +// protocol: Nr. (enum) of the protocol. +// isRepeat: A flag indicating if it is a repeat message of the protocol. +// Returns: +// A string containing the protocol name. +#ifdef ARDUINO // Arduino's & C++'s string implementations can't co-exist. +String typeToString(const decode_type_t protocol, const bool isRepeat) { + String result = ""; +#else +std::string typeToString(const decode_type_t protocol, const bool isRepeat) { + std::string result = ""; +#endif + switch (protocol) { + case UNUSED: + result = F("UNUSED"); + break; + case AIWA_RC_T501: + result = F("AIWA_RC_T501"); + break; + case ARGO: + result = F("ARGO"); + break; + case CARRIER_AC: + result = F("CARRIER_AC"); + break; + case COOLIX: + result = F("COOLIX"); + break; + case DAIKIN: + result = F("DAIKIN"); + break; + case DAIKIN2: + result = F("DAIKIN2"); + break; + case DAIKIN216: + result = F("DAIKIN216"); + break; + case DENON: + result = F("DENON"); + break; + case DISH: + result = F("DISH"); + break; + case ELECTRA_AC: + result = F("ELECTRA_AC"); + break; + case FUJITSU_AC: + result = F("FUJITSU_AC"); + break; + case GICABLE: + result = F("GICABLE"); + break; + case GLOBALCACHE: + result = F("GLOBALCACHE"); + break; + case GREE: + result = F("GREE"); + break; + case HAIER_AC: + result = F("HAIER_AC"); + break; + case HAIER_AC_YRW02: + result = F("HAIER_AC_YRW02"); + break; + case HITACHI_AC: + result = F("HITACHI_AC"); + break; + case HITACHI_AC1: + result = F("HITACHI_AC1"); + break; + case HITACHI_AC2: + result = F("HITACHI_AC2"); + break; + case JVC: + result = F("JVC"); + break; + case KELVINATOR: + result = F("KELVINATOR"); + break; + case LEGOPF: + result = F("LEGOPF"); + break; + case LG: + result = F("LG"); + break; + case LG2: + result = F("LG2"); + break; + case LASERTAG: + result = F("LASERTAG"); + break; + case LUTRON: + result = F("LUTRON"); + break; + case MAGIQUEST: + result = F("MAGIQUEST"); + break; + case MIDEA: + result = F("MIDEA"); + break; + case MITSUBISHI: + result = F("MITSUBISHI"); + break; + case MITSUBISHI2: + result = F("MITSUBISHI2"); + break; + case MITSUBISHI_AC: + result = F("MITSUBISHI_AC"); + break; + case MITSUBISHI_HEAVY_88: + result = F("MITSUBISHI_HEAVY_88"); + break; + case MITSUBISHI_HEAVY_152: + result = F("MITSUBISHI_HEAVY_152"); + break; + case MWM: + result = F("MWM"); + break; + case NEC: + result = F("NEC"); + break; + case NEC_LIKE: + result = F("NEC (non-strict)"); + break; + case NIKAI: + result = F("NIKAI"); + break; + case PANASONIC: + result = F("PANASONIC"); + break; + case PANASONIC_AC: + result = F("PANASONIC_AC"); + break; + case PIONEER: + result = F("PIONEER"); + break; + case PRONTO: + result = F("PRONTO"); + break; + case RAW: + result = F("RAW"); + break; + case RC5: + result = F("RC5"); + break; + case RC5X: + result = F("RC5X"); + break; + case RC6: + result = F("RC6"); + break; + case RCMM: + result = F("RCMM"); + break; + case SAMSUNG: + result = F("SAMSUNG"); + break; + case SAMSUNG36: + result = F("SAMSUNG36"); + break; + case SAMSUNG_AC: + result = F("SAMSUNG_AC"); + break; + case SANYO: + result = F("SANYO"); + break; + case SANYO_LC7461: + result = F("SANYO_LC7461"); + break; + case SHARP: + result = F("SHARP"); + break; + case SHERWOOD: + result = F("SHERWOOD"); + break; + case SONY: + result = F("SONY"); + break; + case TCL112AC: + result = F("TCL112AC"); + break; + case TECO: + result = F("TECO"); + break; + case TOSHIBA_AC: + result = F("TOSHIBA_AC"); + break; + case TROTEC: + result = F("TROTEC"); + break; + case VESTEL_AC: + result = F("VESTEL_AC"); + break; + case WHIRLPOOL_AC: + result = F("WHIRLPOOL_AC"); + break; + case WHYNTER: + result = F("WHYNTER"); + break; + case UNKNOWN: + default: + result = F("UNKNOWN"); + break; + } + if (isRepeat) result += F(" (Repeat)"); + return result; +} + +// Does the given protocol use a complex state as part of the decode? +bool hasACState(const decode_type_t protocol) { + switch (protocol) { + case DAIKIN: + case DAIKIN2: + case DAIKIN216: + case ELECTRA_AC: + case FUJITSU_AC: + case GREE: + case HAIER_AC: + case HAIER_AC_YRW02: + case HITACHI_AC: + case HITACHI_AC1: + case HITACHI_AC2: + case KELVINATOR: + case MITSUBISHI_AC: + case MITSUBISHI_HEAVY_88: + case MITSUBISHI_HEAVY_152: + case MWM: + case PANASONIC_AC: + case SAMSUNG_AC: + case TCL112AC: + case TOSHIBA_AC: + case WHIRLPOOL_AC: + return true; + default: + return false; + } +} + +// Return the corrected length of a 'raw' format array structure +// after over-large values are converted into multiple entries. +// Args: +// results: A ptr to a decode result. +// Returns: +// A uint16_t containing the length. +uint16_t getCorrectedRawLength(const decode_results *results) { + uint16_t extended_length = results->rawlen - 1; + for (uint16_t i = 0; i < results->rawlen - 1; i++) { + uint32_t usecs = results->rawbuf[i] * kRawTick; + // Add two extra entries for multiple larger than UINT16_MAX it is. + extended_length += (usecs / (UINT16_MAX + 1)) * 2; + } + return extended_length; +} + +// Return a string containing the key values of a decode_results structure +// in a C/C++ code style format. +#ifdef ARDUINO +String resultToSourceCode(const decode_results *results) { + String output = ""; +#else +std::string resultToSourceCode(const decode_results *results) { + std::string output = ""; +#endif + // Start declaration + output += F("uint16_t "); // variable type + output += F("rawData["); // array name + output += uint64ToString(getCorrectedRawLength(results), 10); + // array size + output += F("] = {"); // Start declaration + + // Dump data + for (uint16_t i = 1; i < results->rawlen; i++) { + uint32_t usecs; + for (usecs = results->rawbuf[i] * kRawTick; usecs > UINT16_MAX; + usecs -= UINT16_MAX) { + output += uint64ToString(UINT16_MAX); + if (i % 2) + output += F(", 0, "); + else + output += F(", 0, "); + } + output += uint64ToString(usecs, 10); + if (i < results->rawlen - 1) + output += F(", "); // ',' not needed on the last one + if (i % 2 == 0) output += ' '; // Extra if it was even. + } + + // End declaration + output += F("};"); + + // Comment + output += F(" // "); + output += typeToString(results->decode_type, results->repeat); + // Only display the value if the decode type doesn't have an A/C state. + if (!hasACState(results->decode_type)) + output += ' ' + uint64ToString(results->value, 16); + output += F("\n"); + + // Now dump "known" codes + if (results->decode_type != UNKNOWN) { + if (hasACState(results->decode_type)) { +#if DECODE_AC + uint16_t nbytes = results->bits / 8; + output += F("uint8_t state["); + output += uint64ToString(nbytes); + output += F("] = {"); + for (uint16_t i = 0; i < nbytes; i++) { + output += F("0x"); + if (results->state[i] < 0x10) output += '0'; + output += uint64ToString(results->state[i], 16); + if (i < nbytes - 1) output += F(", "); + } + output += F("};\n"); +#endif // DECODE_AC + } else { + // Simple protocols + // Some protocols have an address &/or command. + // NOTE: It will ignore the atypical case when a message has been + // decoded but the address & the command are both 0. + if (results->address > 0 || results->command > 0) { + output += F("uint32_t address = 0x"); + output += uint64ToString(results->address, 16); + output += F(";\n"); + output += F("uint32_t command = 0x"); + output += uint64ToString(results->command, 16); + output += F(";\n"); + } + // Most protocols have data + output += F("uint64_t data = 0x"); + output += uint64ToString(results->value, 16); + output += F(";\n"); + } + } + return output; +} + +// Dump out the decode_results structure. +// +#ifdef ARDUINO +String resultToTimingInfo(const decode_results *results) { + String output = ""; + String value = ""; +#else +std::string resultToTimingInfo(const decode_results *results) { + std::string output = ""; + std::string value = ""; +#endif + output += F("Raw Timing["); + output += uint64ToString(results->rawlen - 1, 10); + output += F("]:\n"); + + for (uint16_t i = 1; i < results->rawlen; i++) { + if (i % 2 == 0) + output += '-'; // even + else + output += F(" +"); // odd + value = uint64ToString(results->rawbuf[i] * kRawTick); + // Space pad the value till it is at least 6 chars long. + while (value.length() < 6) value = ' ' + value; + output += value; + if (i < results->rawlen - 1) + output += F(", "); // ',' not needed for last one + if (!(i % 8)) output += '\n'; // Newline every 8 entries. + } + output += '\n'; + return output; +} + +// Convert the decode_results structure's value/state to simple hexadecimal. +// +#ifdef ARDUINO +String resultToHexidecimal(const decode_results *result) { + String output = ""; +#else +std::string resultToHexidecimal(const decode_results *result) { + std::string output = ""; +#endif + if (hasACState(result->decode_type)) { +#if DECODE_AC + for (uint16_t i = 0; result->bits > i * 8; i++) { + if (result->state[i] < 0x10) output += '0'; // Zero pad + output += uint64ToString(result->state[i], 16); + } +#endif // DECODE_AC + } else { + output += uint64ToString(result->value, 16); + } + return output; +} + +// Dump out the decode_results structure. +// +#ifdef ARDUINO +String resultToHumanReadableBasic(const decode_results *results) { + String output = ""; +#else +std::string resultToHumanReadableBasic(const decode_results *results) { + std::string output = ""; +#endif + // Show Encoding standard + output += F("Encoding : "); + output += typeToString(results->decode_type, results->repeat); + output += '\n'; + + // Show Code & length + output += F("Code : "); + output += resultToHexidecimal(results); + output += F(" ("); + output += uint64ToString(results->bits); + output += F(" bits)\n"); + return output; +} + +uint8_t sumBytes(uint8_t *start, const uint16_t length, const uint8_t init) { + uint8_t checksum = init; + uint8_t *ptr; + for (ptr = start; ptr - start < length; ptr++) checksum += *ptr; + return checksum; +} + +uint8_t xorBytes(uint8_t *start, const uint16_t length, const uint8_t init) { + uint8_t checksum = init; + uint8_t *ptr; + for (ptr = start; ptr - start < length; ptr++) checksum ^= *ptr; + return checksum; +} + +// Count the number of bits of a certain type. +// Args: +// start: Ptr to the start of data to count bits in. +// length: How many bytes to count. +// ones: Count the binary 1 bits. False for counting the 0 bits. +// init: Start the counting from this value. +// Returns: +// Nr. of bits found. +uint16_t countBits(const uint8_t *start, const uint16_t length, const bool ones, + const uint16_t init) { + uint16_t count = init; + for (uint16_t offset = 0; offset < length; offset++) + for (uint8_t currentbyte = *(start + offset); + currentbyte; + currentbyte >>= 1) + if (currentbyte & 1) count++; + if (ones || length == 0) + return count; + else + return (length * 8) - count; +} + +// Count the number of bits of a certain type. +// Args: +// data: The value you want bits counted for, starting from the LSB. +// length: How many bits to count. +// ones: Count the binary 1 bits. False for counting the 0 bits. +// init: Start the counting from this value. +// Returns: +// Nr. of bits found. +uint16_t countBits(const uint64_t data, const uint8_t length, const bool ones, + const uint16_t init) { + uint16_t count = init; + uint8_t bitsSoFar = length; + for (uint64_t remainder = data; remainder && bitsSoFar; + remainder >>= 1, bitsSoFar--) + if (remainder & 1) count++; + if (ones || length == 0) + return count; + else + return length - count; +} + +uint64_t invertBits(const uint64_t data, const uint16_t nbits) { + // No change if we are asked to invert no bits. + if (nbits == 0) return data; + uint64_t result = ~data; + // If we are asked to invert all the bits or more than we have, it's simple. + if (nbits >= sizeof(data) * 8) return result; + // Mask off any unwanted bits and return the result. + return (result & ((1ULL << nbits) - 1)); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/src/IRutils.h b/lib/IRremoteESP8266-2.6.0/src/IRutils.h similarity index 74% rename from lib/IRremoteESP8266-2.5.2.03/src/IRutils.h rename to lib/IRremoteESP8266-2.6.0/src/IRutils.h index c17375d98..0d0b677b5 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/IRutils.h +++ b/lib/IRremoteESP8266-2.6.0/src/IRutils.h @@ -24,7 +24,8 @@ String resultToSourceCode(const decode_results *results); String resultToTimingInfo(const decode_results *results); String resultToHumanReadableBasic(const decode_results *results); String resultToHexidecimal(const decode_results *result); -#else +String htmlEscape(const String unescaped); +#else // ARDUINO std::string uint64ToString(uint64_t input, uint8_t base = 10); std::string typeToString(const decode_type_t protocol, const bool isRepeat = false); @@ -32,10 +33,16 @@ std::string resultToSourceCode(const decode_results *results); std::string resultToTimingInfo(const decode_results *results); std::string resultToHumanReadableBasic(const decode_results *results); std::string resultToHexidecimal(const decode_results *result); -#endif +std::string htmlEscape(const std::string unescaped); +#endif // ARDUINO bool hasACState(const decode_type_t protocol); uint16_t getCorrectedRawLength(const decode_results *results); uint8_t sumBytes(uint8_t *start, const uint16_t length, const uint8_t init = 0); +uint8_t xorBytes(uint8_t *start, const uint16_t length, const uint8_t init = 0); +uint16_t countBits(const uint8_t *start, const uint16_t length, + const bool ones = true, const uint16_t init = 0); +uint16_t countBits(const uint64_t data, const uint8_t length, + const bool ones = true, const uint16_t init = 0); uint64_t invertBits(const uint64_t data, const uint16_t nbits); - +decode_type_t strToDecodeType(const char *str); #endif // IRUTILS_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Aiwa.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Aiwa.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Aiwa.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Aiwa.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Argo.cpp similarity index 84% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Argo.cpp index 8a3e69f72..d6711acd3 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Argo.cpp @@ -40,9 +40,9 @@ IRArgoAC::IRArgoAC(uint16_t pin) : _irsend(pin) { stateReset(); } void IRArgoAC::begin() { _irsend.begin(); } #if SEND_ARGO -void IRArgoAC::send() { +void IRArgoAC::send(const uint16_t repeat) { checksum(); // Create valid checksum before sending - _irsend.sendArgo(argo); + _irsend.sendArgo(argo, kArgoStateLength, repeat); } #endif // SEND_ARGO @@ -228,3 +228,37 @@ void IRArgoAC::setRoomTemp(uint8_t temp) { argo[3] += temp << 5; // Append to bit 5,6,7 argo[4] += temp >> 3; // Remove lowest 3 bits and append in 0,1 } + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRArgoAC::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kArgoFan1; + case stdAc::fanspeed_t::kMedium: + return kArgoFan2; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kArgoFan3; + default: + return kArgoFanAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRArgoAC::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kHighest: + return kArgoFlapFull; + case stdAc::swingv_t::kHigh: + return kArgoFlap5; + case stdAc::swingv_t::kMiddle: + return kArgoFlap4; + case stdAc::swingv_t::kLow: + return kArgoFlap3; + case stdAc::swingv_t::kLowest: + return kArgoFlap1; + default: + return kArgoFlapAuto; + } +} diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.h b/lib/IRremoteESP8266-2.6.0/src/ir_Argo.h similarity index 91% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Argo.h index b49fc3517..883c2ddfd 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Argo.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Argo.h @@ -6,6 +6,10 @@ #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + // ARGO Ulisse DCI @@ -55,7 +59,7 @@ const uint8_t kArgoFlapFull = 7; // 0b111 #define ARGO_COOL_ON kArgoCoolOn #define ARGO_COOL_OFF kArgoCoolOff #define ARGO_COOL_AUTO kArgoCoolAuto -#define ARGO_COOl_HUM kArgoCoolHum +#define ARGO_COOL_HUM kArgoCoolHum #define ARGO_HEAT_ON kArgoHeatOn #define ARGO_HEAT_AUTO kArgoHeatAuto #define ARGO_HEAT_BLINK kArgoHeatBlink @@ -80,7 +84,7 @@ class IRArgoAC { explicit IRArgoAC(uint16_t pin); #if SEND_ARGO - void send(); + void send(const uint16_t repeat = kArgoDefaultRepeat); #endif // SEND_ARGO void begin(); void on(); @@ -118,13 +122,19 @@ class IRArgoAC { void setRoomTemp(uint8_t temp); uint8_t* getRaw(); + uint8_t convertFan(const stdAc::fanspeed_t speed); + uint8_t convertSwingV(const stdAc::swingv_t position); +#ifndef UNIT_TEST private: + IRsend _irsend; // instance of the IR send class +#else + IRsendTest _irsend; // instance of the testing IR send class +#endif // # of bytes per command uint8_t argo[kArgoStateLength]; // Defined in IRremoteESP8266.h void stateReset(); void checksum(); - IRsend _irsend; // instance of the IR send class // Attributes uint8_t set_temp; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Carrier.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Carrier.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Carrier.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Carrier.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Coolix.cpp similarity index 72% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Coolix.cpp index ee539af25..2659a1d88 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Coolix.cpp @@ -93,25 +93,62 @@ void IRsend::sendCOOLIX(uint64_t data, uint16_t nbits, uint16_t repeat) { // https://github.com/markszabo/IRremoteESP8266/issues/484 IRCoolixAC::IRCoolixAC(uint16_t pin) : _irsend(pin) { stateReset(); } -void IRCoolixAC::stateReset() { remote_state = kCoolixDefaultState; } +void IRCoolixAC::stateReset() { setRaw(kCoolixDefaultState); } void IRCoolixAC::begin() { _irsend.begin(); } #if SEND_COOLIX -void IRCoolixAC::send() { _irsend.sendCOOLIX(remote_state); } +void IRCoolixAC::send(const uint16_t repeat) { + _irsend.sendCOOLIX(remote_state, kCoolixBits, repeat); +} #endif // SEND_COOLIX uint32_t IRCoolixAC::getRaw() { return remote_state; } -void IRCoolixAC::setRaw(const uint32_t new_code) { remote_state = new_code; } +void IRCoolixAC::setRaw(const uint32_t new_code) { + remote_state = new_code; + saved_state = new_code; +} + +// Return true if the current state is a special state. +bool IRCoolixAC::isSpecialState(void) { + switch (remote_state) { + case kCoolixClean: + case kCoolixLed: + case kCoolixOff: + case kCoolixSwing: + case kCoolixSleep: + case kCoolixTurbo: + return true; + default: + return false; + } +} + +void IRCoolixAC::updateSavedState(void) { + if (!isSpecialState()) saved_state = remote_state; +} + +void IRCoolixAC::recoverSavedState(void) { + // If the current state is a special one, last known normal one. + if (isSpecialState()) remote_state = saved_state; + // If the saved_state was also a special state, reset as we expect a normal + // state out of all this. + if (isSpecialState()) stateReset(); +} + +uint32_t IRCoolixAC::getNormalState(void) { + return isSpecialState() ? saved_state : remote_state; +} void IRCoolixAC::setTempRaw(const uint8_t code) { + recoverSavedState(); remote_state &= ~kCoolixTempMask; // Clear the old temp. remote_state |= (code << 4); } uint8_t IRCoolixAC::getTempRaw() { - return (remote_state & kCoolixTempMask) >> 4; + return (getNormalState() & kCoolixTempMask) >> 4; } void IRCoolixAC::setTemp(const uint8_t desired) { @@ -130,6 +167,7 @@ uint8_t IRCoolixAC::getTemp() { } void IRCoolixAC::setSensorTempRaw(const uint8_t code) { + recoverSavedState(); remote_state &= ~kCoolixSensorTempMask; // Clear previous sensor temp. remote_state |= ((code & 0xF) << 8); } @@ -143,7 +181,8 @@ void IRCoolixAC::setSensorTemp(const uint8_t desired) { } uint8_t IRCoolixAC::getSensorTemp() { - return ((remote_state & kCoolixSensorTempMask) >> 8) + kCoolixSensorTempMin; + return ((getNormalState() & kCoolixSensorTempMask) >> 8) + + kCoolixSensorTempMin; } bool IRCoolixAC::getPower() { @@ -152,25 +191,35 @@ bool IRCoolixAC::getPower() { } void IRCoolixAC::setPower(const bool power) { - if (!power) remote_state = kCoolixOff; - // There really is no distinct "on" setting, so do nothing. + if (power) { + // There really is no distinct "on" setting, just ensure it a normal state. + recoverSavedState(); + } else { + updateSavedState(); + remote_state = kCoolixOff; + } } bool IRCoolixAC::getSwing() { return remote_state == kCoolixSwing; } void IRCoolixAC::setSwing() { // Assumes that repeated sending "swing" toggles the action on the device. + updateSavedState(); remote_state = kCoolixSwing; } bool IRCoolixAC::getSleep() { return remote_state == kCoolixSleep; } -void IRCoolixAC::setSleep() { remote_state = kCoolixSleep; } +void IRCoolixAC::setSleep() { + updateSavedState(); + remote_state = kCoolixSleep; +} bool IRCoolixAC::getTurbo() { return remote_state == kCoolixTurbo; } void IRCoolixAC::setTurbo() { // Assumes that repeated sending "turbo" toggles the action on the device. + updateSavedState(); remote_state = kCoolixTurbo; } @@ -178,19 +227,24 @@ bool IRCoolixAC::getLed() { return remote_state == kCoolixLed; } void IRCoolixAC::setLed() { // Assumes that repeated sending "Led" toggles the action on the device. + updateSavedState(); remote_state = kCoolixLed; } bool IRCoolixAC::getClean() { return remote_state == kCoolixClean; } -void IRCoolixAC::setClean() { remote_state = kCoolixClean; } +void IRCoolixAC::setClean() { + updateSavedState(); + remote_state = kCoolixClean; +} bool IRCoolixAC::getZoneFollow() { - return remote_state & kCoolixZoneFollowMask; + return getNormalState() & kCoolixZoneFollowMask; } // Internal use only. void IRCoolixAC::setZoneFollow(bool state) { + recoverSavedState(); if (state) { remote_state |= kCoolixZoneFollowMask; } else { @@ -199,6 +253,7 @@ void IRCoolixAC::setZoneFollow(bool state) { } void IRCoolixAC::clearSensorTemp() { + recoverSavedState(); setZoneFollow(false); setSensorTempRaw(kCoolixSensorTempIgnoreCode); } @@ -212,6 +267,7 @@ void IRCoolixAC::setMode(const uint8_t mode) { case kCoolixAuto: case kCoolixHeat: case kCoolixDry: + recoverSavedState(); remote_state = (remote_state & ~kCoolixModeMask) | (actualmode << 2); // Force the temp into a known-good state. setTemp(getTemp()); @@ -220,21 +276,25 @@ void IRCoolixAC::setMode(const uint8_t mode) { } uint8_t IRCoolixAC::getMode() { - uint8_t mode = (remote_state & kCoolixModeMask) >> 2; + uint8_t mode = (getNormalState() & kCoolixModeMask) >> 2; if (mode == kCoolixDry) if (getTempRaw() == kCoolixFanTempCode) return kCoolixFan; return mode; } -uint8_t IRCoolixAC::getFan() { return (remote_state & kCoolixFanMask) >> 13; } +uint8_t IRCoolixAC::getFan() { + return (getNormalState() & kCoolixFanMask) >> 13; +} void IRCoolixAC::setFan(const uint8_t speed) { + recoverSavedState(); uint8_t newspeed = speed; switch (speed) { case kCoolixFanMin: case kCoolixFanMed: case kCoolixFanMax: case kCoolixFanAuto: + case kCoolixFanAuto0: case kCoolixFanZoneFollow: case kCoolixFanFixed: break; @@ -245,6 +305,38 @@ void IRCoolixAC::setFan(const uint8_t speed) { remote_state |= ((newspeed << 13) & kCoolixFanMask); } +// Convert a standard A/C mode into its native mode. +uint8_t IRCoolixAC::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kCoolixCool; + case stdAc::opmode_t::kHeat: + return kCoolixHeat; + case stdAc::opmode_t::kDry: + return kCoolixDry; + case stdAc::opmode_t::kFan: + return kCoolixFan; + default: + return kCoolixAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRCoolixAC::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kCoolixFanMin; + case stdAc::fanspeed_t::kMedium: + return kCoolixFanMed; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kCoolixFanMax; + default: + return kCoolixFanAuto; + } +} + // Convert the internal state into a human readable string. #ifdef ARDUINO String IRCoolixAC::toString() { @@ -253,89 +345,97 @@ String IRCoolixAC::toString() { std::string IRCoolixAC::toString() { std::string result = ""; #endif // ARDUINO - result += "Power: "; + result += F("Power: "); if (getPower()) { - result += "On"; + result += F("On"); } else { - result += "Off"; + result += F("Off"); return result; // If it's off, there is no other info. } - result += ", Fan: " + uint64ToString(getFan()); - switch (getFan()) { - case kCoolixFanAuto: - result += " (AUTO)"; - break; - case kCoolixFanMax: - result += " (MAX)"; - break; - case kCoolixFanMin: - result += " (MIN)"; - break; - case kCoolixFanMed: - result += " (MED)"; - break; - case kCoolixFanZoneFollow: - result += " (ZONEFOLLOW)"; - break; - case kCoolixFanFixed: - result += " (FIXED)"; - break; - default: - result += " (UNKNOWN)"; - } // Special modes. if (getSwing()) { - result += ", Swing: Toggle"; + result += F(", Swing: Toggle"); return result; } if (getSleep()) { - result += ", Sleep: Toggle"; + result += F(", Sleep: Toggle"); return result; } if (getTurbo()) { - result += ", Turbo: Toggle"; + result += F(", Turbo: Toggle"); return result; } if (getLed()) { - result += ", Led: Toggle"; + result += F(", Led: Toggle"); return result; } if (getClean()) { - result += ", Mode: Self clean"; + result += F(", Clean: Toggle"); return result; } - result += ", Mode: " + uint64ToString(getMode()); + result += F(", Mode: "); + result += uint64ToString(getMode()); switch (getMode()) { case kCoolixAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kCoolixCool: - result += " (COOL)"; + result += F(" (COOL)"); break; case kCoolixHeat: - result += " (HEAT)"; + result += F(" (HEAT)"); break; case kCoolixDry: - result += " (DRY)"; + result += F(" (DRY)"); break; case kCoolixFan: - result += " (FAN)"; + result += F(" (FAN)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - if (getMode() != kCoolixFan) // Fan mode doesn't have a temperature. - result += ", Temp: " + uint64ToString(getTemp()) + "C"; - result += ", Zone Follow: "; + result += F(", Fan: "); + result += uint64ToString(getFan()); + switch (getFan()) { + case kCoolixFanAuto: + result += F(" (AUTO)"); + break; + case kCoolixFanAuto0: + result += F(" (AUTO0)"); + break; + case kCoolixFanMax: + result += F(" (MAX)"); + break; + case kCoolixFanMin: + result += F(" (MIN)"); + break; + case kCoolixFanMed: + result += F(" (MED)"); + break; + case kCoolixFanZoneFollow: + result += F(" (ZONEFOLLOW)"); + break; + case kCoolixFanFixed: + result += F(" (FIXED)"); + break; + default: + result += F(" (UNKNOWN)"); + } + if (getMode() != kCoolixFan) { // Fan mode doesn't have a temperature. + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += 'C'; + } + result += F(", Zone Follow: "); if (getZoneFollow()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Sensor Temp: "; + result += F("Off"); + result += F(", Sensor Temp: "); if (getSensorTemp() > kCoolixSensorTempMax) - result += "Ignored"; + result += F("Ignored"); else - result += uint64ToString(getSensorTemp()) + "C"; + result += uint64ToString(getSensorTemp()) + F("C"); return result; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h b/lib/IRremoteESP8266-2.6.0/src/ir_Coolix.h similarity index 82% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Coolix.h index ee4552074..d85db98d7 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Coolix.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Coolix.h @@ -14,6 +14,9 @@ #endif #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif // CCCCC OOOOO OOOOO LL IIIII XX XX // CC C OO OO OO OO LL III XX XX @@ -30,11 +33,11 @@ // Constants // Modes -const uint8_t kCoolixCool = 0b00; -const uint8_t kCoolixDry = 0b01; -const uint8_t kCoolixAuto = 0b10; -const uint8_t kCoolixHeat = 0b11; -const uint8_t kCoolixFan = 4; // Synthetic. +const uint8_t kCoolixCool = 0b000; +const uint8_t kCoolixDry = 0b001; +const uint8_t kCoolixAuto = 0b010; +const uint8_t kCoolixHeat = 0b011; +const uint8_t kCoolixFan = 0b100; // Synthetic. const uint32_t kCoolixModeMask = 0b000000000000000000001100; // 0xC const uint32_t kCoolixZoneFollowMask = 0b000010000000000000000000; // 0x80000 // Fan Control @@ -42,6 +45,7 @@ const uint8_t kCoolixFanMin = 0b100; const uint8_t kCoolixFanMed = 0b010; const uint8_t kCoolixFanMax = 0b001; const uint8_t kCoolixFanAuto = 0b101; +const uint8_t kCoolixFanAuto0 = 0b000; const uint8_t kCoolixFanZoneFollow = 0b110; const uint8_t kCoolixFanFixed = 0b111; const uint32_t kCoolixFanMask = 0b000000001110000000000000; // 0x00E000 @@ -90,7 +94,7 @@ class IRCoolixAC { void stateReset(); #if SEND_COOLIX - void send(); + void send(const uint16_t repeat = kCoolixDefaultRepeat); #endif // SEND_COOLIX void begin(); void on(); @@ -119,21 +123,30 @@ class IRCoolixAC { bool getZoneFollow(); uint32_t getRaw(); void setRaw(const uint32_t new_code); - + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); #ifdef ARDUINO String toString(); #else std::string toString(); #endif +#ifndef UNIT_TEST private: - // The state of the IR remote in IR code form. - uint32_t remote_state; IRsend _irsend; +#else + IRsendTest _irsend; +#endif + uint32_t remote_state; // The state of the IR remote in IR code form. + uint32_t saved_state; // Copy of the state if we required a special mode. void setTempRaw(const uint8_t code); uint8_t getTempRaw(); void setSensorTempRaw(const uint8_t code); void setZoneFollow(const bool state); + bool isSpecialState(void); + void updateSavedState(void); + void recoverSavedState(void); + uint32_t getNormalState(void); }; #endif // IR_COOLIX_H_ diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Daikin.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Daikin.cpp new file mode 100644 index 000000000..358dbd603 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Daikin.cpp @@ -0,0 +1,1712 @@ +/* +An Arduino sketch to emulate IR Daikin ARC433** & ARC477A1 remote control unit +Read more at: +http://harizanov.com/2012/02/control-daikin-air-conditioner-over-the-internet/ + +Copyright 2016 sillyfrog +Copyright 2017 sillyfrog, crankyoldgit +Copyright 2018-2019 crankyoldgit +*/ + +#include "ir_Daikin.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif +#include "IRutils.h" + +// DDDDD AAA IIIII KK KK IIIII NN NN +// DD DD AAAAA III KK KK III NNN NN +// DD DD AA AA III KKKK III NN N NN +// DD DD AAAAAAA III KK KK III NN NNN +// DDDDDD AA AA IIIII KK KK IIIII NN NN + +// Constants +// Ref: +// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote +// http://rdlab.cdmt.vn/project-2013/daikin-ir-protocol +// https://github.com/markszabo/IRremoteESP8266/issues/582 + +#if SEND_DAIKIN +// Send a Daikin A/C message. +// +// Args: +// data: An array of kDaikinStateLength bytes containing the IR command. +// +// Status: STABLE +// +// Ref: +// IRDaikinESP.cpp +// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote +// https://github.com/blafois/Daikin-IR-Reverse +void IRsend::sendDaikin(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes < kDaikinStateLengthShort) + return; // Not enough bytes to send a proper message. + + for (uint16_t r = 0; r <= repeat; r++) { + uint16_t offset = 0; + // Send the header, 0b00000 + sendGeneric(0, 0, // No header for the header + kDaikinBitMark, kDaikinOneSpace, kDaikinBitMark, + kDaikinZeroSpace, kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, + (uint64_t)0b00000, kDaikinHeaderLength, 38, false, 0, 50); + // Data #1 + if (nbytes < kDaikinStateLength) { // Are we using the legacy size? + // Do this as a constant to save RAM and keep in flash memory + sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, + kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, + kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, + kDaikinFirstHeader64, 64, 38, false, 0, 50); + } else { // We are using the newer/more correct size. + sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, + kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, + kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, + data, kDaikinSection1Length, 38, false, 0, 50); + offset += kDaikinSection1Length; + } + // Data #2 + sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, + kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, + kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, + data + offset, kDaikinSection2Length, 38, false, 0, 50); + offset += kDaikinSection2Length; + // Data #3 + sendGeneric(kDaikinHdrMark, kDaikinHdrSpace, kDaikinBitMark, + kDaikinOneSpace, kDaikinBitMark, kDaikinZeroSpace, + kDaikinBitMark, kDaikinZeroSpace + kDaikinGap, + data + offset, nbytes - offset, 38, false, 0, 50); + } +} +#endif // SEND_DAIKIN + +IRDaikinESP::IRDaikinESP(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRDaikinESP::begin(void) { _irsend.begin(); } + +#if SEND_DAIKIN +void IRDaikinESP::send(const uint16_t repeat) { + this->checksum(); + _irsend.sendDaikin(remote, kDaikinStateLength, repeat); +} +#endif // SEND_DAIKIN + +// Verify the checksums are valid for a given state. +// Args: +// state: The array to verify the checksums of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRDaikinESP::validChecksum(uint8_t state[], const uint16_t length) { + // Data #1 + if (length < kDaikinSection1Length || + state[kDaikinByteChecksum1] != sumBytes(state, kDaikinSection1Length - 1)) + return false; + // Data #2 + if (length < kDaikinSection1Length + kDaikinSection2Length || + state[kDaikinByteChecksum2] != sumBytes(state + kDaikinSection1Length, + kDaikinSection2Length - 1)) + return false; + // Data #3 + if (length < kDaikinSection1Length + kDaikinSection2Length + 2 || + state[length - 1] != sumBytes(state + kDaikinSection1Length + + kDaikinSection2Length, + length - (kDaikinSection1Length + + kDaikinSection2Length) - 1)) + return false; + return true; +} + +// Calculate and set the checksum values for the internal state. +void IRDaikinESP::checksum(void) { + remote[kDaikinByteChecksum1] = sumBytes(remote, kDaikinSection1Length - 1); + remote[kDaikinByteChecksum2] = sumBytes(remote + kDaikinSection1Length, + kDaikinSection2Length - 1); + remote[kDaikinByteChecksum3] = sumBytes(remote + kDaikinSection1Length + + kDaikinSection2Length, + kDaikinSection3Length - 1); +} + +void IRDaikinESP::stateReset(void) { + for (uint8_t i = 0; i < kDaikinStateLength; i++) remote[i] = 0x0; + + remote[0] = 0x11; + remote[1] = 0xDA; + remote[2] = 0x27; + remote[4] = 0xC5; + // remote[7] is a checksum byte, it will be set by checksum(). + + remote[8] = 0x11; + remote[9] = 0xDA; + remote[10] = 0x27; + remote[12] = 0x42; + // remote[15] is a checksum byte, it will be set by checksum(). + remote[16] = 0x11; + remote[17] = 0xDA; + remote[18] = 0x27; + remote[21] = 0x49; + remote[22] = 0x1E; + remote[24] = 0xB0; + remote[27] = 0x06; + remote[28] = 0x60; + remote[31] = 0xC0; + // remote[34] is a checksum byte, it will be set by checksum(). + this->checksum(); +} + +uint8_t *IRDaikinESP::getRaw(void) { + this->checksum(); // Ensure correct settings before sending. + return remote; +} + +void IRDaikinESP::setRaw(const uint8_t new_code[], const uint16_t length) { + uint8_t offset = 0; + if (length == kDaikinStateLengthShort) { // Handle the "short" length case. + offset = kDaikinStateLength - kDaikinStateLengthShort; + this->stateReset(); + } + for (uint8_t i = 0; i < length && i < kDaikinStateLength; i++) + remote[i + offset] = new_code[i]; +} + +void IRDaikinESP::on(void) { remote[kDaikinBytePower] |= kDaikinBitPower; } + +void IRDaikinESP::off(void) { remote[kDaikinBytePower] &= ~kDaikinBitPower; } + +void IRDaikinESP::setPower(const bool on) { + if (on) + this->on(); + else + this->off(); +} + +bool IRDaikinESP::getPower(void) { + return remote[kDaikinBytePower] & kDaikinBitPower; +} + +// Set the temp in deg C +void IRDaikinESP::setTemp(const uint8_t temp) { + uint8_t degrees = std::max(temp, kDaikinMinTemp); + degrees = std::min(degrees, kDaikinMaxTemp); + remote[kDaikinByteTemp] = degrees << 1; +} + +uint8_t IRDaikinESP::getTemp(void) { return remote[kDaikinByteTemp] >> 1; } + +// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet +void IRDaikinESP::setFan(const uint8_t fan) { + // Set the fan speed bits, leave low 4 bits alone + uint8_t fanset; + if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto) + fanset = fan; + else if (fan < kDaikinFanMin || fan > kDaikinFanMax) + fanset = kDaikinFanAuto; + else + fanset = 2 + fan; + remote[kDaikinByteFan] &= 0x0F; + remote[kDaikinByteFan] |= (fanset << 4); +} + +uint8_t IRDaikinESP::getFan(void) { + uint8_t fan = remote[kDaikinByteFan] >> 4; + if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2; + return fan; +} + +uint8_t IRDaikinESP::getMode(void) { return remote[kDaikinBytePower] >> 4; } + +void IRDaikinESP::setMode(const uint8_t mode) { + switch (mode) { + case kDaikinAuto: + case kDaikinCool: + case kDaikinHeat: + case kDaikinFan: + case kDaikinDry: + remote[kDaikinBytePower] &= 0b10001111; + remote[kDaikinBytePower] |= (mode << 4); + break; + default: + this->setMode(kDaikinAuto); + } +} + +void IRDaikinESP::setSwingVertical(const bool on) { + if (on) + remote[kDaikinByteFan] |= 0x0F; + else + remote[kDaikinByteFan] &= 0xF0; +} + +bool IRDaikinESP::getSwingVertical(void) { + return remote[kDaikinByteFan] & 0x0F; +} + +void IRDaikinESP::setSwingHorizontal(const bool on) { + if (on) + remote[kDaikinByteSwingH] |= 0x0F; + else + remote[kDaikinByteSwingH] &= 0xF0; +} + +bool IRDaikinESP::getSwingHorizontal(void) { + return remote[kDaikinByteSwingH] & 0x0F; +} + +void IRDaikinESP::setQuiet(const bool on) { + if (on) { + remote[kDaikinByteSilent] |= kDaikinBitSilent; + // Powerful & Quiet mode being on are mutually exclusive. + this->setPowerful(false); + } else { + remote[kDaikinByteSilent] &= ~kDaikinBitSilent; + } +} + +bool IRDaikinESP::getQuiet(void) { + return remote[kDaikinByteSilent] & kDaikinBitSilent; +} + +void IRDaikinESP::setPowerful(const bool on) { + if (on) { + remote[kDaikinBytePowerful] |= kDaikinBitPowerful; + // Powerful, Quiet, & Econo mode being on are mutually exclusive. + this->setQuiet(false); + this->setEcono(false); + } else { + remote[kDaikinBytePowerful] &= ~kDaikinBitPowerful; + } +} + +bool IRDaikinESP::getPowerful(void) { + return remote[kDaikinBytePowerful] & kDaikinBitPowerful; +} + +void IRDaikinESP::setSensor(const bool on) { + if (on) + remote[kDaikinByteSensor] |= kDaikinBitSensor; + else + remote[kDaikinByteSensor] &= ~kDaikinBitSensor; +} + +bool IRDaikinESP::getSensor(void) { + return remote[kDaikinByteSensor] & kDaikinBitSensor; +} + +void IRDaikinESP::setEcono(const bool on) { + if (on) { + remote[kDaikinByteEcono] |= kDaikinBitEcono; + // Powerful & Econo mode being on are mutually exclusive. + this->setPowerful(false); + } else { + remote[kDaikinByteEcono] &= ~kDaikinBitEcono; + } +} + +bool IRDaikinESP::getEcono(void) { + return remote[kDaikinByteEcono] & kDaikinBitEcono; +} + +void IRDaikinESP::setEye(const bool on) { + if (on) + remote[kDaikinByteEye] |= kDaikinBitEye; + else + remote[kDaikinByteEye] &= ~kDaikinBitEye; +} + +bool IRDaikinESP::getEye(void) { + return remote[kDaikinByteEye] & kDaikinBitEye; +} + +void IRDaikinESP::setMold(const bool on) { + if (on) + remote[kDaikinByteMold] |= kDaikinBitMold; + else + remote[kDaikinByteMold] &= ~kDaikinBitMold; +} + +bool IRDaikinESP::getMold(void) { + return remote[kDaikinByteMold] & kDaikinBitMold; +} + +void IRDaikinESP::setComfort(const bool on) { + if (on) + remote[kDaikinByteComfort] |= kDaikinBitComfort; + else + remote[kDaikinByteComfort] &= ~kDaikinBitComfort; +} + +bool IRDaikinESP::getComfort(void) { + return remote[kDaikinByteComfort] & kDaikinBitComfort; +} + +// starttime: Number of minutes after midnight. +void IRDaikinESP::enableOnTimer(const uint16_t starttime) { + remote[kDaikinByteOnTimer] |= kDaikinBitOnTimer; + remote[kDaikinByteOnTimerMinsLow] = starttime; + // only keep 4 bits + remote[kDaikinByteOnTimerMinsHigh] &= 0xF0; + remote[kDaikinByteOnTimerMinsHigh] |= ((starttime >> 8) & 0x0F); +} + +void IRDaikinESP::disableOnTimer(void) { + this->enableOnTimer(kDaikinUnusedTime); + remote[kDaikinByteOnTimer] &= ~kDaikinBitOnTimer; +} + +uint16_t IRDaikinESP::getOnTime(void) { + return ((remote[kDaikinByteOnTimerMinsHigh] & 0x0F) << 8) + + remote[kDaikinByteOnTimerMinsLow]; +} + +bool IRDaikinESP::getOnTimerEnabled(void) { + return remote[kDaikinByteOnTimer] & kDaikinBitOnTimer; +} + +// endtime: Number of minutes after midnight. +void IRDaikinESP::enableOffTimer(const uint16_t endtime) { + remote[kDaikinByteOffTimer] |= kDaikinBitOffTimer; + remote[kDaikinByteOffTimerMinsHigh] = endtime >> 4; + remote[kDaikinByteOffTimerMinsLow] &= 0x0F; + remote[kDaikinByteOffTimerMinsLow] |= ((endtime & 0x0F) << 4); +} + +void IRDaikinESP::disableOffTimer(void) { + this->enableOffTimer(kDaikinUnusedTime); + remote[kDaikinByteOffTimer] &= ~kDaikinBitOffTimer; +} + +uint16_t IRDaikinESP::getOffTime(void) { + return (remote[kDaikinByteOffTimerMinsHigh] << 4) + + ((remote[kDaikinByteOffTimerMinsLow] & 0xF0) >> 4); +} + +bool IRDaikinESP::getOffTimerEnabled(void) { + return remote[kDaikinByteOffTimer] & kDaikinBitOffTimer; +} + +void IRDaikinESP::setCurrentTime(const uint16_t mins_since_midnight) { + uint16_t mins = mins_since_midnight; + if (mins > 24 * 60) mins = 0; // If > 23:59, set to 00:00 + remote[kDaikinByteClockMinsLow] = mins; + // only keep 4 bits + remote[kDaikinByteClockMinsHigh] &= 0xF0; + remote[kDaikinByteClockMinsHigh] |= ((mins >> 8) & 0x0F); +} + +uint16_t IRDaikinESP::getCurrentTime(void) { + return ((remote[kDaikinByteClockMinsHigh] & 0x0F) << 8) + + remote[kDaikinByteClockMinsLow]; +} + +#ifdef ARDUINO +String IRDaikinESP::renderTime(const uint16_t timemins) { + String ret; +#else // ARDUINO +std::string IRDaikinESP::renderTime(const uint16_t timemins) { + std::string ret; +#endif // ARDUINO + ret = uint64ToString(timemins / 60) + ':'; + uint8_t mins = timemins % 60; + if (mins < 10) ret += '0'; + ret += uint64ToString(mins); + return ret; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRDaikinESP::toString(void) { + String result = ""; +#else // ARDUINO +std::string IRDaikinESP::toString(void) { + std::string result = ""; +#endif // ARDUINO + result += F("Power: "); + result += this->getPower() ? F("On") : F("Off"); + result += F(", Mode: "); + result += uint64ToString(this->getMode()); + switch (this->getMode()) { + case kDaikinAuto: + result += F(" (AUTO)"); + break; + case kDaikinCool: + result += F(" (COOL)"); + break; + case kDaikinHeat: + result += F(" (HEAT)"); + break; + case kDaikinDry: + result += F(" (DRY)"); + break; + case kDaikinFan: + result += F(" (FAN)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Temp: "); + result += uint64ToString(this->getTemp()); + result += F("C, Fan: "); + result += uint64ToString(this->getFan()); + switch (this->getFan()) { + case kDaikinFanAuto: + result += F(" (AUTO)"); + break; + case kDaikinFanQuiet: + result += F(" (QUIET)"); + break; + case kDaikinFanMin: + result += F(" (MIN)"); + break; + case kDaikinFanMax: + result += F(" (MAX)"); + break; + } + result += F(", Powerful: "); + result += this->getPowerful() ? F("On") : F("Off"); + result += F(", Quiet: "); + result += this->getQuiet() ? F("On") : F("Off"); + result += F(", Sensor: "); + result += this->getSensor() ? F("On") : F("Off"); + result += F(", Eye: "); + result += this->getEye() ? F("On") : F("Off"); + result += F(", Mold: "); + result += this->getMold() ? F("On") : F("Off"); + result += F(", Comfort: "); + result += this->getComfort() ? F("On") : F("Off"); + result += F(", Swing (Horizontal): "); + result += this->getSwingHorizontal() ? F("On") : F("Off"); + result += F(", Swing (Vertical): "); + result += this->getSwingVertical() ? F("On") : F("Off"); + result += F(", Current Time: "); + result += this->renderTime(this->getCurrentTime()); + result += F(", On Time: "); + if (this->getOnTimerEnabled()) + result += this->renderTime(this->getOnTime()); + else + result += F("Off"); + result += F(", Off Time: "); + if (this->getOffTimerEnabled()) + result += this->renderTime(this->getOffTime()); + else + result += F("Off"); + return result; +} + +// Convert a standard A/C mode into its native mode. +uint8_t IRDaikinESP::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kDaikinCool; + case stdAc::opmode_t::kHeat: + return kDaikinHeat; + case stdAc::opmode_t::kDry: + return kDaikinDry; + case stdAc::opmode_t::kFan: + return kDaikinFan; + default: + return kDaikinAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRDaikinESP::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + return kDaikinFanQuiet; + case stdAc::fanspeed_t::kLow: + return kDaikinFanMin; + case stdAc::fanspeed_t::kMedium: + return kDaikinFanMin + 1; + case stdAc::fanspeed_t::kHigh: + return kDaikinFanMax - 1; + case stdAc::fanspeed_t::kMax: + return kDaikinFanMax; + default: + return kDaikinFanAuto; + } +} + +#if DECODE_DAIKIN +// Decode the supplied Daikin A/C message. +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. (kDaikinBits) +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Should be working. +// +// Ref: +// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote +bool IRrecv::decodeDaikin(decode_results *results, const uint16_t nbits, + const bool strict) { + // Is there enough data to match successfully? + if (results->rawlen < (2 * (nbits + kDaikinHeaderLength) + + kDaikinSections * (kHeader + kFooter) + kFooter - 1)) + return false; + + // Compliance + if (strict && nbits != kDaikinBits) return false; + + uint16_t offset = kStartOffset; + match_result_t data_result; + uint16_t dataBitsSoFar = 0; + uint16_t i = 0; + + // Header #1 - Doesn't count as data. + data_result = matchData(&(results->rawbuf[offset]), kDaikinHeaderLength, + kDaikinBitMark, kDaikinOneSpace, + kDaikinBitMark, kDaikinZeroSpace, + kDaikinTolerance, kDaikinMarkExcess, false); + offset += data_result.used; + if (data_result.success == false) return false; // Fail + if (data_result.data) return false; // The header bits should be zero. + + // Read the Data sections. + // Keep reading bytes until we either run out of section or state to fill. + const uint8_t kSectionSize[kDaikinSections] = { + kDaikinSection1Length, kDaikinSection2Length, kDaikinSection3Length}; + for (uint8_t section = 0, pos = 0; section < kDaikinSections; + section++) { + pos += kSectionSize[section]; + // Section Footer + if (!matchMark(results->rawbuf[offset++], kDaikinBitMark, + kDaikinTolerance, kDaikinMarkExcess)) return false; + if (!matchSpace(results->rawbuf[offset++], kDaikinZeroSpace + kDaikinGap, + kDaikinTolerance, kDaikinMarkExcess)) return false; + // Section Header + if (!matchMark(results->rawbuf[offset++], kDaikinHdrMark, + kDaikinTolerance, kDaikinMarkExcess)) return false; + if (!matchSpace(results->rawbuf[offset++], kDaikinHdrSpace, + kDaikinTolerance, kDaikinMarkExcess)) return false; + + // Section Data + for (; offset <= results->rawlen - 16 && i < pos; + i++, dataBitsSoFar += 8, offset += data_result.used) { + // Read in a byte at a time. + data_result = + matchData(&(results->rawbuf[offset]), 8, + kDaikinBitMark, kDaikinOneSpace, + kDaikinBitMark, kDaikinZeroSpace, + kDaikinTolerance, kDaikinMarkExcess, false); + if (data_result.success == false) break; // Fail + results->state[i] = (uint8_t)data_result.data; + } + } + + // Footer + if (!matchMark(results->rawbuf[offset++], kDaikinBitMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kDaikinGap)) + return false; + + // Compliance + if (strict) { + // Re-check we got the correct size/length due to the way we read the data. + if (dataBitsSoFar != kDaikinBits) return false; + // Validate the checksum. + if (!IRDaikinESP::validChecksum(results->state)) return false; + } + + // Success + results->decode_type = DAIKIN; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_DAIKIN + +#if SEND_DAIKIN2 +// Send a Daikin2 A/C message. +// +// Args: +// data: An array of kDaikin2StateLength bytes containing the IR command. +// +// Status: BETA/Appears to work. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/582 +void IRsend::sendDaikin2(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kDaikin2Section1Length) + return; // Not enough bytes to send a partial message. + + for (uint16_t r = 0; r <= repeat; r++) { + // Leader + sendGeneric(kDaikin2LeaderMark, kDaikin2LeaderSpace, + 0, 0, 0, 0, 0, 0, (uint64_t) 0, // No data payload. + 0, kDaikin2Freq, false, 0, 50); + // Section #1 + sendGeneric(kDaikin2HdrMark, kDaikin2HdrSpace, kDaikin2BitMark, + kDaikin2OneSpace, kDaikin2BitMark, kDaikin2ZeroSpace, + kDaikin2BitMark, kDaikin2Gap, data, kDaikin2Section1Length, + kDaikin2Freq, false, 0, 50); + // Section #2 + sendGeneric(kDaikin2HdrMark, kDaikin2HdrSpace, kDaikin2BitMark, + kDaikin2OneSpace, kDaikin2BitMark, kDaikin2ZeroSpace, + kDaikin2BitMark, kDaikin2Gap, data + kDaikin2Section1Length, + nbytes - kDaikin2Section1Length, + kDaikin2Freq, false, 0, 50); + } +} +#endif // SEND_DAIKIN2 + +// Class for handling Daikin2 A/C messages. +// +// Code by crankyoldgit, Reverse engineering analysis by sheppy99 +// +// Supported Remotes: Daikin ARC477A1 remote +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/582 +// https://docs.google.com/spreadsheets/d/1f8EGfIbBUo2B-CzUFdrgKQprWakoYNKM80IKZN4KXQE/edit?usp=sharing +// https://www.daikin.co.nz/sites/default/files/daikin-split-system-US7-FTXZ25-50NV1B.pdf +IRDaikin2::IRDaikin2(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRDaikin2::begin() { _irsend.begin(); } + +#if SEND_DAIKIN2 +void IRDaikin2::send(const uint16_t repeat) { + checksum(); + _irsend.sendDaikin2(remote_state, kDaikin2StateLength, repeat); +} +#endif // SEND_DAIKIN2 + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRDaikin2::validChecksum(uint8_t state[], const uint16_t length) { + // Validate the checksum of section #1. + if (length <= kDaikin2Section1Length - 1 || + state[kDaikin2Section1Length - 1] != sumBytes(state, + kDaikin2Section1Length - 1)) + return false; + // Validate the checksum of section #2 (a.k.a. the rest) + if (length <= kDaikin2Section1Length + 1 || + state[length - 1] != sumBytes(state + kDaikin2Section1Length, + length - kDaikin2Section1Length - 1)) + return false; + return true; +} + +// Calculate and set the checksum values for the internal state. +void IRDaikin2::checksum() { + remote_state[kDaikin2Section1Length - 1] = sumBytes( + remote_state, kDaikin2Section1Length - 1); + remote_state[kDaikin2StateLength -1 ] = sumBytes( + remote_state + kDaikin2Section1Length, kDaikin2Section2Length - 1); +} + +void IRDaikin2::stateReset() { + for (uint8_t i = 0; i < kDaikin2StateLength; i++) remote_state[i] = 0x0; + + remote_state[0] = 0x11; + remote_state[1] = 0xDA; + remote_state[2] = 0x27; + remote_state[4] = 0x01; + remote_state[6] = 0xC0; + remote_state[7] = 0x70; + remote_state[8] = 0x08; + remote_state[9] = 0x0C; + remote_state[10] = 0x80; + remote_state[11] = 0x04; + remote_state[12] = 0xB0; + remote_state[13] = 0x16; + remote_state[14] = 0x24; + remote_state[17] = 0xBE; + remote_state[18] = 0xD0; + // remote_state[19] is a checksum byte, it will be set by checksum(). + remote_state[20] = 0x11; + remote_state[21] = 0xDA; + remote_state[22] = 0x27; + remote_state[25] = 0x08; + remote_state[28] = 0xA0; + remote_state[35] = 0xC1; + remote_state[36] = 0x80; + remote_state[37] = 0x60; + // remote_state[38] is a checksum byte, it will be set by checksum(). + disableOnTimer(); + disableOffTimer(); + disableSleepTimer(); + checksum(); +} + +uint8_t *IRDaikin2::getRaw() { + checksum(); // Ensure correct settings before sending. + return remote_state; +} + +void IRDaikin2::setRaw(const uint8_t new_code[]) { + for (uint8_t i = 0; i < kDaikin2StateLength; i++) + remote_state[i] = new_code[i]; +} + +void IRDaikin2::on() { + remote_state[25] |= kDaikinBitPower; + remote_state[6] &= ~kDaikin2BitPower; +} + +void IRDaikin2::off() { + remote_state[25] &= ~kDaikinBitPower; + remote_state[6] |= kDaikin2BitPower; +} + +void IRDaikin2::setPower(const bool state) { + if (state) + on(); + else + off(); +} + +bool IRDaikin2::getPower() { + return (remote_state[25] & kDaikinBitPower) && + !(remote_state[6] & kDaikin2BitPower); +} + +uint8_t IRDaikin2::getMode() { return remote_state[25] >> 4; } + +void IRDaikin2::setMode(const uint8_t desired_mode) { + uint8_t mode = desired_mode; + switch (mode) { + case kDaikinCool: + case kDaikinHeat: + case kDaikinFan: + case kDaikinDry: + break; + default: + mode = kDaikinAuto; + } + remote_state[25] &= 0b10001111; + remote_state[25] |= (mode << 4); + // Redo the temp setting as Cool mode has a different min temp. + if (mode == kDaikinCool) this->setTemp(this->getTemp()); +} + +// Set the temp in deg C +void IRDaikin2::setTemp(const uint8_t desired) { + // The A/C has a different min temp if in cool mode. + uint8_t temp = std::max( + (this->getMode() == kDaikinCool) ? kDaikin2MinCoolTemp : kDaikinMinTemp, + desired); + temp = std::min(kDaikinMaxTemp, temp); + remote_state[26] = temp * 2; +} + +// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet +void IRDaikin2::setFan(const uint8_t fan) { + // Set the fan speed bits, leave low 4 bits alone + uint8_t fanset; + if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto) + fanset = fan; + else if (fan < kDaikinFanMin || fan > kDaikinFanMax) + fanset = kDaikinFanAuto; + else + fanset = 2 + fan; + remote_state[28] &= 0x0F; + remote_state[28] |= (fanset << 4); +} + +uint8_t IRDaikin2::getFan() { + uint8_t fan = remote_state[28] >> 4; + if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2; + return fan; +} + +uint8_t IRDaikin2::getTemp() { return remote_state[26] / 2; } + +void IRDaikin2::setSwingVertical(const uint8_t position) { + switch (position) { + case kDaikin2SwingVHigh: + case 2: + case 3: + case 4: + case 5: + case kDaikin2SwingVLow: + case kDaikin2SwingVBreeze: + case kDaikin2SwingVCirculate: + case kDaikin2SwingVAuto: + remote_state[18] &= 0xF0; + remote_state[18] |= (position & 0x0F); + } +} + +uint8_t IRDaikin2::getSwingVertical() { return remote_state[18] & 0x0F; } + +void IRDaikin2::setSwingHorizontal(const uint8_t position) { + remote_state[17] = position; +} + +uint8_t IRDaikin2::getSwingHorizontal() { return remote_state[17]; } + +void IRDaikin2::setCurrentTime(const uint16_t numMins) { + uint16_t mins = numMins; + if (numMins > 24 * 60) mins = 0; // If > 23:59, set to 00:00 + remote_state[5] = (uint8_t)(mins & 0xFF); + // only keep 4 bits + remote_state[6] &= 0xF0; + remote_state[6] |= (uint8_t)((mins >> 8) & 0x0F); +} + +uint16_t IRDaikin2::getCurrentTime() { + return ((remote_state[6] & 0x0F) << 8) + remote_state[5]; +} + +// starttime: Number of minutes after midnight. +// Note: Timer location is shared with sleep timer. +void IRDaikin2::enableOnTimer(const uint16_t starttime) { + clearSleepTimerFlag(); + remote_state[25] |= kDaikinBitOnTimer; // Set the On Timer flag. + remote_state[30] = (uint8_t)(starttime & 0xFF); + // only keep 4 bits + remote_state[31] &= 0xF0; + remote_state[31] |= (uint8_t)((starttime >> 8) & 0x0F); +} + +void IRDaikin2::clearOnTimerFlag() { + remote_state[25] &= ~kDaikinBitOnTimer; +} + +void IRDaikin2::disableOnTimer() { + enableOnTimer(kDaikinUnusedTime); + clearOnTimerFlag(); + clearSleepTimerFlag(); +} + +uint16_t IRDaikin2::getOnTime() { + return ((remote_state[31] & 0x0F) << 8) + remote_state[30]; +} + +bool IRDaikin2::getOnTimerEnabled() { + return remote_state[25] & kDaikinBitOnTimer; +} + +// endtime: Number of minutes after midnight. +void IRDaikin2::enableOffTimer(const uint16_t endtime) { + remote_state[25] |= kDaikinBitOffTimer; // Set the Off Timer flag. + remote_state[32] = (uint8_t)((endtime >> 4) & 0xFF); + remote_state[31] &= 0x0F; + remote_state[31] |= (uint8_t)((endtime & 0xF) << 4); +} + +void IRDaikin2::disableOffTimer() { + enableOffTimer(kDaikinUnusedTime); + remote_state[25] &= ~kDaikinBitOffTimer; // Clear the Off Timer flag. +} + +uint16_t IRDaikin2::getOffTime() { + return (remote_state[32] << 4) + (remote_state[31] >> 4); +} + +bool IRDaikin2::getOffTimerEnabled() { + return remote_state[25] & kDaikinBitOffTimer; +} + +uint8_t IRDaikin2::getBeep() { + return remote_state[7] >> 6; +} + +void IRDaikin2::setBeep(const uint8_t beep) { + remote_state[7] &= ~kDaikin2BeepMask; + remote_state[7] |= ((beep << 6) & kDaikin2BeepMask); +} + +uint8_t IRDaikin2::getLight() { + return (remote_state[7] & kDaikin2LightMask) >> 4; +} + +void IRDaikin2::setLight(const uint8_t light) { + remote_state[7] &= ~kDaikin2LightMask; + remote_state[7] |= ((light << 4) & kDaikin2LightMask); +} + +void IRDaikin2::setMold(const bool on) { + if (on) + remote_state[8] |= kDaikin2BitMold; + else + remote_state[8] &= ~kDaikin2BitMold; +} + +bool IRDaikin2::getMold() { + return remote_state[8] & kDaikin2BitMold; +} + +// Auto clean setting. +void IRDaikin2::setClean(const bool on) { + if (on) + remote_state[8] |= kDaikin2BitClean; + else + remote_state[8] &= ~kDaikin2BitClean; +} + +bool IRDaikin2::getClean() { + return remote_state[8] & kDaikin2BitClean; +} + +// Fresh Air settings. +void IRDaikin2::setFreshAir(const bool on) { + if (on) + remote_state[8] |= kDaikin2BitFreshAir; + else + remote_state[8] &= ~kDaikin2BitFreshAir; +} + +bool IRDaikin2::getFreshAir() { + return remote_state[8] & kDaikin2BitFreshAir; +} + +void IRDaikin2::setFreshAirHigh(const bool on) { + if (on) + remote_state[8] |= kDaikin2BitFreshAirHigh; + else + remote_state[8] &= ~kDaikin2BitFreshAirHigh; +} + +bool IRDaikin2::getFreshAirHigh() { + return remote_state[8] & kDaikin2BitFreshAirHigh; +} + +void IRDaikin2::setEyeAuto(bool on) { + if (on) + remote_state[13] |= kDaikin2BitEyeAuto; + else + remote_state[13] &= ~kDaikin2BitEyeAuto; +} + +bool IRDaikin2::getEyeAuto() { + return remote_state[13] & kDaikin2BitEyeAuto; +} + +void IRDaikin2::setEye(bool on) { + if (on) + remote_state[36] |= kDaikin2BitEye; + else + remote_state[36] &= ~kDaikin2BitEye; +} + +bool IRDaikin2::getEye() { + return remote_state[36] & kDaikin2BitEye; +} + +void IRDaikin2::setEcono(bool on) { + if (on) + remote_state[36] |= kDaikinBitEcono; + else + remote_state[36] &= ~kDaikinBitEcono; +} + +bool IRDaikin2::getEcono() { + return remote_state[36] & kDaikinBitEcono; +} + +// sleeptime: Number of minutes. +// Note: Timer location is shared with On Timer. +void IRDaikin2::enableSleepTimer(const uint16_t sleeptime) { + enableOnTimer(sleeptime); + clearOnTimerFlag(); + remote_state[36] |= kDaikin2BitSleepTimer; // Set the Sleep Timer flag. +} + +void IRDaikin2::clearSleepTimerFlag() { + remote_state[36] &= ~kDaikin2BitSleepTimer; +} + +void IRDaikin2::disableSleepTimer() { + disableOnTimer(); +} + +uint16_t IRDaikin2::getSleepTime() { + return getOnTime(); +} + +bool IRDaikin2::getSleepTimerEnabled() { + return remote_state[36] & kDaikin2BitSleepTimer; +} + +void IRDaikin2::setQuiet(const bool on) { + if (on) { + remote_state[33] |= kDaikinBitSilent; + // Powerful & Quiet mode being on are mutually exclusive. + setPowerful(false); + } else { + remote_state[33] &= ~kDaikinBitSilent; + } +} + +bool IRDaikin2::getQuiet() { return remote_state[33] & kDaikinBitSilent; } + +void IRDaikin2::setPowerful(const bool on) { + if (on) { + remote_state[33] |= kDaikinBitPowerful; + // Powerful & Quiet mode being on are mutually exclusive. + setQuiet(false); + } else { + remote_state[33] &= ~kDaikinBitPowerful; + } +} + +bool IRDaikin2::getPowerful() { return remote_state[33] & kDaikinBitPowerful; } + +void IRDaikin2::setPurify(const bool on) { + if (on) + remote_state[36] |= kDaikin2BitPurify; + else + remote_state[36] &= ~kDaikin2BitPurify; +} + +bool IRDaikin2::getPurify() { return remote_state[36] & kDaikin2BitPurify; } + +// Convert a standard A/C mode into its native mode. +uint8_t IRDaikin2::convertMode(const stdAc::opmode_t mode) { + return IRDaikinESP::convertMode(mode); +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRDaikin2::convertFan(const stdAc::fanspeed_t speed) { + return IRDaikinESP::convertFan(speed); +} + +// Convert a standard A/C vertical swing into its native version. +uint8_t IRDaikin2::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kHighest: + case stdAc::swingv_t::kHigh: + case stdAc::swingv_t::kMiddle: + case stdAc::swingv_t::kLow: + case stdAc::swingv_t::kLowest: + return (uint8_t)position + kDaikin2SwingVHigh; + default: + return kDaikin2SwingVAuto; + } +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRDaikin2::toString() { + String result = ""; +#else // ARDUINO +std::string IRDaikin2::toString() { + std::string result = ""; +#endif // ARDUINO + result += F("Power: "); + if (getPower()) + result += F("On"); + else + result += F("Off"); + result += F(", Mode: "); + result += uint64ToString(getMode()); + switch (getMode()) { + case kDaikinAuto: + result += F(" (AUTO)"); + break; + case kDaikinCool: + result += F(" (COOL)"); + break; + case kDaikinHeat: + result += F(" (HEAT)"); + break; + case kDaikinDry: + result += F(" (DRY)"); + break; + case kDaikinFan: + result += F(" (FAN)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFan()); + switch (getFan()) { + case kDaikinFanAuto: + result += F(" (Auto)"); + break; + case kDaikinFanQuiet: + result += F(" (Quiet)"); + break; + case kDaikinFanMin: + result += F(" (Min)"); + break; + case kDaikinFanMax: + result += F(" (Max)"); + break; + } + result += F(", Swing (V): "); + result += uint64ToString(getSwingVertical()); + switch (getSwingVertical()) { + case kDaikin2SwingVHigh: + result += F(" (Highest)"); + break; + case 2: + case 3: + case 4: + case 5: + break; + case kDaikin2SwingVLow: + result += F(" (Lowest)"); + break; + case kDaikin2SwingVBreeze: + result += F(" (Breeze)"); + break; + case kDaikin2SwingVCirculate: + result += F(" (Circulate)"); + break; + case kDaikin2SwingVAuto: + result += F(" (Auto)"); + break; + default: + result += F(" (Unknown)"); + } + result += F(", Swing (H): "); + result += uint64ToString(getSwingHorizontal()); + switch (getSwingHorizontal()) { + case kDaikin2SwingHAuto: + result += F(" (Auto)"); + break; + case kDaikin2SwingHSwing: + result += F(" (Swing)"); + break; + } + result += F(", Clock: "); + result += IRDaikinESP::renderTime(getCurrentTime()); + result += F(", On Time: "); + if (getOnTimerEnabled()) + result += IRDaikinESP::renderTime(getOnTime()); + else + result += F("Off"); + result += F(", Off Time: "); + if (getOffTimerEnabled()) + result += IRDaikinESP::renderTime(getOffTime()); + else + result += F("Off"); + result += F(", Sleep Time: "); + if (getSleepTimerEnabled()) + result += IRDaikinESP::renderTime(getSleepTime()); + else + result += F("Off"); + result += F(", Beep: "); + result += uint64ToString(getBeep()); + switch (getBeep()) { + case kDaikinBeepLoud: + result += F(" (Loud)"); + break; + case kDaikinBeepQuiet: + result += F(" (Quiet)"); + break; + case kDaikinBeepOff: + result += F(" (Off)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Light: "); + result += uint64ToString(getLight()); + switch (getLight()) { + case kDaikinLightBright: + result += F(" (Bright)"); + break; + case kDaikinLightDim: + result += F(" (Dim)"); + break; + case kDaikinLightOff: + result += F(" (Off)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Mold: "); + result += (getMold() ? F("On") : F("Off")); + result += F(", Clean: "); + result += (getClean() ? F("On") : F("Off")); + result += F(", Fresh Air: "); + if (getFreshAir()) + result += (getFreshAirHigh() ? "High" : "On"); + else + result += F("Off"); + result += F(", Eye: "); + result += (getEye() ? F("On") : F("Off")); + result += F(", Eye Auto: "); + result += (getEyeAuto() ? F("On") : F("Off")); + result += F(", Quiet: "); + result += (getQuiet() ? F("On") : F("Off")); + result += F(", Powerful: "); + result += (getPowerful() ? F("On") : F("Off")); + result += ", Purify: "; + result += (getPurify() ? F("On") : F("Off")); + result += F(", Econo: "); + result += (getEcono() ? F("On") : F("Off")); + return result; +} + +#if DECODE_DAIKIN2 +// Decode the supplied Daikin2 A/C message. +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. (kDaikin2Bits) +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Supported devices: +// - Daikin FTXZ25NV1B, FTXZ35NV1B, FTXZ50NV1B Aircon +// - Daikin ARC477A1 remote +// +// Status: BETA / Work as expected. +// +// Ref: +// https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote +bool IRrecv::decodeDaikin2(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * (nbits + kHeader + kFooter) + kHeader - 1) + return false; + + // Compliance + if (strict && nbits != kDaikin2Bits) return false; + + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + uint16_t i = 0; + match_result_t data_result; + uint8_t sectionSize[kDaikin2Sections] = {kDaikin2Section1Length, + kDaikin2Section2Length}; + + // Leader + if (!matchMark(results->rawbuf[offset++], kDaikin2LeaderMark, + kDaikin2Tolerance)) return false; + if (!matchSpace(results->rawbuf[offset++], kDaikin2LeaderSpace, + kDaikin2Tolerance)) return false; + + // Sections + // Keep reading bytes until we either run out of section or state to fill. + for (uint8_t section = 0, pos = 0; section < kDaikin2Sections; + section++) { + pos += sectionSize[section]; + + // Section Header + if (!matchMark(results->rawbuf[offset++], kDaikin2HdrMark, + kDaikin2Tolerance)) return false; + if (!matchSpace(results->rawbuf[offset++], kDaikin2HdrSpace, + kDaikin2Tolerance)) return false; + + // Section Data + for (; offset <= results->rawlen - 16 && i < pos; + i++, dataBitsSoFar += 8, offset += data_result.used) { + // Read in a byte at a time. + data_result = + matchData(&(results->rawbuf[offset]), 8, kDaikin2BitMark, + kDaikin2OneSpace, kDaikin2BitMark, + kDaikin2ZeroSpace, kDaikin2Tolerance, kMarkExcess, false); + if (data_result.success == false) break; // Fail + results->state[i] = (uint8_t)data_result.data; + } + + // Section Footer + if (!matchMark(results->rawbuf[offset++], kDaikin2BitMark, + kDaikin2Tolerance)) return false; + if (section < kDaikin2Sections - 1) { // Inter-section gaps. + if (!matchSpace(results->rawbuf[offset++], kDaikin2Gap, + kDaikin2Tolerance)) return false; + } else { // Last section / End of message gap. + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kDaikin2Gap, + kDaikin2Tolerance)) return false; + } + } + + // Compliance + if (strict) { + // Re-check we got the correct size/length due to the way we read the data. + if (dataBitsSoFar != kDaikin2Bits) return false; + // Validate the checksum. + if (!IRDaikin2::validChecksum(results->state)) return false; + } + + // Success + results->decode_type = DAIKIN2; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_DAIKIN2 + +#if SEND_DAIKIN216 +// Send a Daikin 216 bit A/C message. +// +// Args: +// data: An array of kDaikin216StateLength bytes containing the IR command. +// +// Status: Alpha/Untested on a real device. +// +// Supported devices: +// - Daikin ARC433B69 remote. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/689 +// https://github.com/danny-source/Arduino_DY_IRDaikin +void IRsend::sendDaikin216(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes < kDaikin216Section1Length) + return; // Not enough bytes to send a partial message. + + for (uint16_t r = 0; r <= repeat; r++) { + // Section #1 + sendGeneric(kDaikin216HdrMark, kDaikin216HdrSpace, kDaikin216BitMark, + kDaikin216OneSpace, kDaikin216BitMark, kDaikin216ZeroSpace, + kDaikin216BitMark, kDaikin216Gap, data, + kDaikin216Section1Length, + kDaikin216Freq, false, 0, kDutyDefault); + // Section #2 + sendGeneric(kDaikin216HdrMark, kDaikin216HdrSpace, kDaikin216BitMark, + kDaikin216OneSpace, kDaikin216BitMark, kDaikin216ZeroSpace, + kDaikin216BitMark, kDaikin216Gap, + data + kDaikin216Section1Length, + nbytes - kDaikin216Section1Length, + kDaikin216Freq, false, 0, kDutyDefault); + } +} +#endif // SEND_DAIKIN216 + +// Class for handling Daikin 216 bit / 27 byte A/C messages. +// +// Code by crankyoldgit. +// +// Supported Remotes: Daikin ARC433B69 remote +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/689 +// https://github.com/danny-source/Arduino_DY_IRDaikin +IRDaikin216::IRDaikin216(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRDaikin216::begin() { _irsend.begin(); } + +#if SEND_DAIKIN216 +void IRDaikin216::send(const uint16_t repeat) { + checksum(); + _irsend.sendDaikin216(remote_state, kDaikin216StateLength, repeat); +} +#endif // SEND_DAIKIN216 + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRDaikin216::validChecksum(uint8_t state[], const uint16_t length) { + // Validate the checksum of section #1. + if (length <= kDaikin216Section1Length - 1 || + state[kDaikin216Section1Length - 1] != sumBytes( + state, kDaikin216Section1Length - 1)) + return false; + // Validate the checksum of section #2 (a.k.a. the rest) + if (length <= kDaikin216Section1Length + 1 || + state[length - 1] != sumBytes(state + kDaikin216Section1Length, + length - kDaikin216Section1Length - 1)) + return false; + return true; +} + +// Calculate and set the checksum values for the internal state. +void IRDaikin216::checksum() { + remote_state[kDaikin216Section1Length - 1] = sumBytes( + remote_state, kDaikin216Section1Length - 1); + remote_state[kDaikin216StateLength - 1] = sumBytes( + remote_state + kDaikin216Section1Length, kDaikin216Section2Length - 1); +} + +void IRDaikin216::stateReset() { + for (uint8_t i = 0; i < kDaikin216StateLength; i++) remote_state[i] = 0x00; + remote_state[0] = 0x11; + remote_state[1] = 0xDA; + remote_state[2] = 0x27; + remote_state[3] = 0xF0; + // remote_state[7] is a checksum byte, it will be set by checksum(). + remote_state[8] = 0x11; + remote_state[9] = 0xDA; + remote_state[10] = 0x27; + remote_state[23] = 0xC0; + // remote_state[26] is a checksum byte, it will be set by checksum(). +} + +uint8_t *IRDaikin216::getRaw() { + checksum(); // Ensure correct settings before sending. + return remote_state; +} + +void IRDaikin216::setRaw(const uint8_t new_code[]) { + for (uint8_t i = 0; i < kDaikin216StateLength; i++) + remote_state[i] = new_code[i]; +} + + +void IRDaikin216::on() { + remote_state[kDaikin216BytePower] |= kDaikinBitPower; +} + +void IRDaikin216::off() { + remote_state[kDaikin216BytePower] &= ~kDaikinBitPower; +} + +void IRDaikin216::setPower(const bool state) { + if (state) + on(); + else + off(); +} + +bool IRDaikin216::getPower() { + return remote_state[kDaikin216BytePower] & kDaikinBitPower; +} + +uint8_t IRDaikin216::getMode() { + return (remote_state[kDaikin216ByteMode] & kDaikin216MaskMode) >> 4; +} + +void IRDaikin216::setMode(const uint8_t mode) { + switch (mode) { + case kDaikinAuto: + case kDaikinCool: + case kDaikinHeat: + case kDaikinFan: + case kDaikinDry: + remote_state[kDaikin216ByteMode] &= ~kDaikin216MaskMode; + remote_state[kDaikin216ByteMode] |= (mode << 4); + break; + default: + this->setMode(kDaikinAuto); + } +} + +// Convert a standard A/C mode into its native mode. +uint8_t IRDaikin216::convertMode(const stdAc::opmode_t mode) { + return IRDaikinESP::convertMode(mode); +} + +// Set the temp in deg C +void IRDaikin216::setTemp(const uint8_t temp) { + uint8_t degrees = std::max(temp, kDaikinMinTemp); + degrees = std::min(degrees, kDaikinMaxTemp); + remote_state[kDaikin216ByteTemp] &= ~kDaikin216MaskTemp; + remote_state[kDaikin216ByteTemp] |= (degrees << 1); +} + +uint8_t IRDaikin216::getTemp(void) { + return (remote_state[kDaikin216ByteTemp] & kDaikin216MaskTemp) >> 1; +} + +// Set the speed of the fan, 1-5 or kDaikinFanAuto or kDaikinFanQuiet +void IRDaikin216::setFan(const uint8_t fan) { + // Set the fan speed bits, leave low 4 bits alone + uint8_t fanset; + if (fan == kDaikinFanQuiet || fan == kDaikinFanAuto) + fanset = fan; + else if (fan < kDaikinFanMin || fan > kDaikinFanMax) + fanset = kDaikinFanAuto; + else + fanset = 2 + fan; + remote_state[kDaikin216ByteFan] &= ~kDaikin216MaskFan; + remote_state[kDaikin216ByteFan] |= (fanset << 4); +} + +uint8_t IRDaikin216::getFan() { + uint8_t fan = remote_state[kDaikin216ByteFan] >> 4; + if (fan != kDaikinFanQuiet && fan != kDaikinFanAuto) fan -= 2; + return fan; +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRDaikin216::convertFan(const stdAc::fanspeed_t speed) { + return IRDaikinESP::convertFan(speed); +} + +void IRDaikin216::setSwingVertical(const bool on) { + if (on) + remote_state[kDaikin216ByteSwingV] |= kDaikin216MaskSwingV; + else + remote_state[kDaikin216ByteSwingV] &= ~kDaikin216MaskSwingV; +} + +bool IRDaikin216::getSwingVertical(void) { + return remote_state[kDaikin216ByteSwingV] & kDaikin216MaskSwingV; +} + +void IRDaikin216::setSwingHorizontal(const bool on) { + if (on) + remote_state[kDaikin216ByteSwingH] |= kDaikin216MaskSwingH; + else + remote_state[kDaikin216ByteSwingH] &= ~kDaikin216MaskSwingH; +} + +bool IRDaikin216::getSwingHorizontal(void) { + return remote_state[kDaikin216ByteSwingH] & kDaikin216MaskSwingH; +} + +// This is a horrible hack till someone works out the quiet mode bit. +void IRDaikin216::setQuiet(const bool on) { + if (on) + this->setFan(kDaikinFanQuiet); + else if (this->getFan() == kDaikinFanQuiet) + this->setFan(kDaikinFanAuto); +} + +// This is a horrible hack till someone works out the quiet mode bit. +bool IRDaikin216::getQuiet(void) { + return this->getFan() == kDaikinFanQuiet; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRDaikin216::toString() { + String result = ""; +#else // ARDUINO +std::string IRDaikin216::toString() { + std::string result = ""; +#endif // ARDUINO + result += F("Power: "); + if (this->getPower()) + result += F("On"); + else + result += F("Off"); + result += F(", Mode: "); + result += uint64ToString(this->getMode()); + switch (getMode()) { + case kDaikinAuto: + result += F(" (AUTO)"); + break; + case kDaikinCool: + result += F(" (COOL)"); + break; + case kDaikinHeat: + result += F(" (HEAT)"); + break; + case kDaikinDry: + result += F(" (DRY)"); + break; + case kDaikinFan: + result += F(" (FAN)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Temp: "); + result += uint64ToString(this->getTemp()); + result += F("C, Fan: "); + result += uint64ToString(this->getFan()); + switch (this->getFan()) { + case kDaikinFanAuto: + result += F(" (AUTO)"); + break; + case kDaikinFanQuiet: + result += F(" (QUIET)"); + break; + case kDaikinFanMin: + result += F(" (MIN)"); + break; + case kDaikinFanMax: + result += F(" (MAX)"); + break; + } + result += F(", Swing (Horizontal): "); + result += this->getSwingHorizontal() ? F("On") : F("Off"); + result += F(", Swing (Vertical): "); + result += this->getSwingVertical() ? F("On") : F("Off"); + result += F(", Quiet: "); + result += (getQuiet() ? F("On") : F("Off")); + return result; +} + +#if DECODE_DAIKIN216 +// Decode the supplied Daikin 216 bit A/C message. +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. (kDaikin216Bits) +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Supported devices: +// - Daikin ARC433B69 remote. +// +// Status: BETA / Should be working. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/689 +// https://github.com/danny-source/Arduino_DY_IRDaikin +bool IRrecv::decodeDaikin216(decode_results *results, const uint16_t nbits, + const bool strict) { + if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1) + return false; + + // Compliance + if (strict && nbits != kDaikin216Bits) return false; + + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + uint16_t i = 0; + match_result_t data_result; + uint8_t sectionSize[kDaikin216Sections] = {kDaikin216Section1Length, + kDaikin216Section2Length}; + + // Sections + // Keep reading bytes until we either run out of section or state to fill. + for (uint8_t section = 0, pos = 0; section < kDaikin216Sections; + section++) { + pos += sectionSize[section]; + + // Section Header + if (!matchMark(results->rawbuf[offset++], kDaikin216HdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kDaikin2HdrSpace)) return false; + + // Section Data + for (; offset <= results->rawlen - 16 && i < pos; + i++, dataBitsSoFar += 8, offset += data_result.used) { + // Read in a byte at a time. + data_result = + matchData(&(results->rawbuf[offset]), 8, kDaikin216BitMark, + kDaikin216OneSpace, kDaikin216BitMark, + kDaikin216ZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) break; // Fail + results->state[i] = (uint8_t)data_result.data; + } + + // Section Footer + if (!matchMark(results->rawbuf[offset++], kDaikin216BitMark)) return false; + if (section < kDaikin216Sections - 1) { // Inter-section gaps. + if (!matchSpace(results->rawbuf[offset++], kDaikin216Gap)) return false; + } else { // Last section / End of message gap. + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kDaikin216Gap)) return false; + } + } + + // Compliance + if (strict) { + // Re-check we got the correct size/length due to the way we read the data. + if (dataBitsSoFar != kDaikin216Bits) return false; + // Validate the checksum. + if (!IRDaikin216::validChecksum(results->state)) return false; + } + + // Success + results->decode_type = decode_type_t::DAIKIN216; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_DAIKIN216 diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Daikin.h b/lib/IRremoteESP8266-2.6.0/src/ir_Daikin.h new file mode 100644 index 000000000..038e8edd9 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Daikin.h @@ -0,0 +1,444 @@ +// Copyright 2016 sillyfrog +// Copyright 2017 sillyfrog, crankyoldgit +// Copyright 2018-2019 crankyoldgit +#ifndef IR_DAIKIN_H_ +#define IR_DAIKIN_H_ + +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + +// DDDDD AAA IIIII KK KK IIIII NN NN +// DD DD AAAAA III KK KK III NNN NN +// DD DD AA AA III KKKK III NN N NN +// DD DD AAAAAAA III KK KK III NN NNN +// DDDDDD AA AA IIIII KK KK IIIII NN NN + +/* + Daikin AC map + byte 6= + b4:Comfort + byte 7= checksum of the first part (and last byte before a 29ms pause) + byte 13=Current time, mins past midnight, low bits + byte 14 + b0-b3=Current time, mins past midnight, high bits + byte 15= checksum of the second part (and last byte before a 29ms pause) + byte 21=mode + b7 = 0 + b6+b5+b4 = Mode + Modes: b6+b5+b4 + 011 = Cool + 100 = Heat (temp 23) + 110 = FAN (temp not shown, but 25) + 000 = Fully Automatic (temp 25) + 010 = DRY (temp 0xc0 = 96 degrees c) + b3 = 1 + b2 = OFF timer set + b1 = ON timer set + b0 = Air Conditioner ON + byte 22=temp*2 (Temp should be between 10 - 32) + byte 24=Fan + FAN control + b7+b6+b5+b4 = Fan speed + Fan: b7+b6+b5+b4 + 0×3 = 1 bar + 0×4 = 2 bar + 0×5 = 3 bar + 0×6 = 4 bar + 0×7 = 5 bar + 0xa = Auto + 0xb = Quite + b3+b2+b1+b0 = Swing control up/down + Swing control up/down: + 0000 = Swing up/down off + 1111 = Swing up/down on + byte 25 + Swing control left/right: + 0000 = Swing left/right off + 1111 = Swing left/right on + byte 26=On timer mins past midnight, low bits + byte 27 + b0-b3=On timer mins past midnight, high bits + b4-b7=Off timer mins past midnight, low bits + byte 28=Off timer mins past midnight, high bits + byte 29=Aux -> Powerful (bit 1), Silent (bit 5) + byte 32=Aux2 + b1: Sensor + b2: Econo mode + b7: Intelligent eye on + byte 33=Aux3 + b1: Mold Proof + byte 34= checksum of the third part +*/ + +// Constants +const uint8_t kDaikinAuto = 0b000; +const uint8_t kDaikinDry = 0b010; +const uint8_t kDaikinCool = 0b011; +const uint8_t kDaikinHeat = 0b100; +const uint8_t kDaikinFan = 0b110; +const uint8_t kDaikinMinTemp = 10; // Celsius +const uint8_t kDaikinMaxTemp = 32; // Celsius +const uint8_t kDaikinFanMin = 1; +const uint8_t kDaikinFanMax = 5; +const uint8_t kDaikinFanAuto = 0b1010; +const uint8_t kDaikinFanQuiet = 0b1011; +const uint16_t kDaikinHeaderLength = 5; +const uint8_t kDaikinSections = 3; +const uint8_t kDaikinSection1Length = 8; +const uint8_t kDaikinSection2Length = 8; +const uint8_t kDaikinSection3Length = + kDaikinStateLength - kDaikinSection1Length - kDaikinSection2Length; +const uint8_t kDaikinByteComfort = 6; +const uint8_t kDaikinByteChecksum1 = 7; +const uint8_t kDaikinBitComfort = 0b00010000; +const uint8_t kDaikinByteClockMinsLow = 13; +const uint8_t kDaikinByteClockMinsHigh = 14; +const uint8_t kDaikinByteChecksum2 = 15; +const uint8_t kDaikinBytePower = 21; +const uint8_t kDaikinBitPower = 0b00000001; +const uint8_t kDaikinByteTemp = 22; +const uint8_t kDaikinByteFan = 24; +const uint8_t kDaikinByteSwingH = 25; +const uint8_t kDaikinByteOnTimerMinsLow = 26; +const uint8_t kDaikinByteOnTimerMinsHigh = 27; +const uint8_t kDaikinByteOffTimerMinsLow = kDaikinByteOnTimerMinsHigh; +const uint8_t kDaikinByteOffTimerMinsHigh = 28; +const uint8_t kDaikinBytePowerful = 29; +const uint8_t kDaikinBitPowerful = 0b00000001; +const uint8_t kDaikinByteSilent = kDaikinBytePowerful; +const uint8_t kDaikinBitSilent = 0b00100000; +const uint8_t kDaikinByteSensor = 32; +const uint8_t kDaikinBitSensor = 0b00000010; +const uint8_t kDaikinByteEcono = kDaikinByteSensor; +const uint8_t kDaikinBitEcono = 0b00000100; +const uint8_t kDaikinByteEye = kDaikinByteSensor; +const uint8_t kDaikinBitEye = 0b10000000; +const uint8_t kDaikinByteMold = 33; +const uint8_t kDaikinBitMold = 0b00000010; +const uint8_t kDaikinByteOffTimer = kDaikinBytePower; +const uint8_t kDaikinBitOffTimer = 0b00000100; +const uint8_t kDaikinByteOnTimer = kDaikinByteOffTimer; +const uint8_t kDaikinBitOnTimer = 0b00000010; +const uint8_t kDaikinByteChecksum3 = kDaikinStateLength - 1; +const uint16_t kDaikinUnusedTime = 0x600; +const uint8_t kDaikinBeepQuiet = 1; +const uint8_t kDaikinBeepLoud = 2; +const uint8_t kDaikinBeepOff = 3; +const uint8_t kDaikinLightBright = 1; +const uint8_t kDaikinLightDim = 2; +const uint8_t kDaikinLightOff = 3; +const uint8_t kDaikinCurBit = kDaikinStateLength; +const uint8_t kDaikinCurIndex = kDaikinStateLength + 1; +const uint8_t kDaikinTolerance = 35; +const uint16_t kDaikinMarkExcess = kMarkExcess; +const uint16_t kDaikinHdrMark = 3650; // kDaikinBitMark * 8 +const uint16_t kDaikinHdrSpace = 1623; // kDaikinBitMark * 4 +const uint16_t kDaikinBitMark = 428; +const uint16_t kDaikinZeroSpace = 428; +const uint16_t kDaikinOneSpace = 1280; +const uint16_t kDaikinGap = 29000; +// Note bits in each octet swapped so can be sent as a single value +const uint64_t kDaikinFirstHeader64 = + 0b1101011100000000000000001100010100000000001001111101101000010001; + +// Another variant of the protocol for the Daikin ARC477A1 remote. +const uint16_t kDaikin2Freq = 36700; // Modulation Frequency in Hz. +const uint16_t kDaikin2LeaderMark = 10024; +const uint16_t kDaikin2LeaderSpace = 25180; +const uint16_t kDaikin2Gap = kDaikin2LeaderMark + kDaikin2LeaderSpace; +const uint16_t kDaikin2HdrMark = 3500; +const uint16_t kDaikin2HdrSpace = 1728; +const uint16_t kDaikin2BitMark = 460; +const uint16_t kDaikin2OneSpace = 1270; +const uint16_t kDaikin2ZeroSpace = 420; +const uint16_t kDaikin2Sections = 2; +const uint16_t kDaikin2Section1Length = 20; +const uint16_t kDaikin2Section2Length = 19; +const uint8_t kDaikin2Tolerance = kTolerance + 5; + +const uint8_t kDaikin2BitSleepTimer = 0b00100000; +const uint8_t kDaikin2BitPurify = 0b00010000; +const uint8_t kDaikin2BitEye = 0b00000010; +const uint8_t kDaikin2BitEyeAuto = 0b10000000; +const uint8_t kDaikin2BitMold = 0b00001000; +const uint8_t kDaikin2BitClean = 0b00100000; +const uint8_t kDaikin2BitFreshAir = 0b00000001; +const uint8_t kDaikin2BitFreshAirHigh = 0b10000000; +const uint8_t kDaikin2BitPower = 0b10000000; +const uint8_t kDaikin2LightMask = 0b00110000; +const uint8_t kDaikin2BeepMask = 0b11000000; +const uint8_t kDaikin2SwingVHigh = 0x1; +const uint8_t kDaikin2SwingVLow = 0x6; +const uint8_t kDaikin2SwingVBreeze = 0xC; +const uint8_t kDaikin2SwingVCirculate = 0xD; +const uint8_t kDaikin2SwingVAuto = 0xE; +const uint8_t kDaikin2SwingHAuto = 0xBE; +const uint8_t kDaikin2SwingHSwing = 0xBF; +const uint8_t kDaikin2MinCoolTemp = 18; // Min temp (in C) when in Cool mode. + +// Another variant of the protocol for the Daikin ARC433B69 remote. +const uint16_t kDaikin216Freq = 38000; // Modulation Frequency in Hz. +const uint16_t kDaikin216HdrMark = 3400; +const uint16_t kDaikin216HdrSpace = 1800; +const uint16_t kDaikin216BitMark = 380; +const uint16_t kDaikin216OneSpace = 1350; +const uint16_t kDaikin216ZeroSpace = 480; +const uint16_t kDaikin216Gap = 29650; +const uint16_t kDaikin216Sections = 2; +const uint16_t kDaikin216Section1Length = 8; +const uint16_t kDaikin216Section2Length = kDaikin216StateLength - + kDaikin216Section1Length; +const uint8_t kDaikin216BytePower = 13; +const uint8_t kDaikin216ByteMode = kDaikin216BytePower; +const uint8_t kDaikin216MaskMode = 0b01110000; +const uint8_t kDaikin216ByteTemp = 14; +const uint8_t kDaikin216MaskTemp = 0b01111110; +const uint8_t kDaikin216ByteFan = 16; +const uint8_t kDaikin216MaskFan = 0b11110000; +const uint8_t kDaikin216ByteSwingV = 16; +const uint8_t kDaikin216MaskSwingV = 0b00001111; +const uint8_t kDaikin216ByteSwingH = 17; +const uint8_t kDaikin216MaskSwingH = kDaikin216MaskSwingV; + + +// Legacy defines. +#define DAIKIN_COOL kDaikinCool +#define DAIKIN_HEAT kDaikinHeat +#define DAIKIN_FAN kDaikinFan +#define DAIKIN_AUTO kDaikinAuto +#define DAIKIN_DRY kDaikinDry +#define DAIKIN_MIN_TEMP kDaikinMinTemp +#define DAIKIN_MAX_TEMP kDaikinMaxTemp +#define DAIKIN_FAN_MIN kDaikinFanMin +#define DAIKIN_FAN_MAX kDaikinFanMax +#define DAIKIN_FAN_AUTO kDaikinFanAuto +#define DAIKIN_FAN_QUIET kDaikinFanQuiet + +class IRDaikinESP { + public: + explicit IRDaikinESP(uint16_t pin); + +#if SEND_DAIKIN + void send(const uint16_t repeat = kDaikinDefaultRepeat); +#endif + void begin(void); + void on(void); + void off(void); + void setPower(const bool on); + bool getPower(void); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setFan(const uint8_t fan); + uint8_t getFan(void); + void setMode(const uint8_t mode); + uint8_t getMode(void); + void setSwingVertical(const bool on); + bool getSwingVertical(void); + void setSwingHorizontal(const bool on); + bool getSwingHorizontal(void); + bool getQuiet(void); + void setQuiet(const bool on); + bool getPowerful(void); + void setPowerful(const bool on); + void setSensor(const bool on); + bool getSensor(void); + void setEcono(const bool on); + bool getEcono(void); + void setEye(const bool on); + bool getEye(void); + void setMold(const bool on); + bool getMold(void); + void setComfort(const bool on); + bool getComfort(void); + void enableOnTimer(const uint16_t starttime); + void disableOnTimer(void); + uint16_t getOnTime(void); + bool getOnTimerEnabled(); + void enableOffTimer(const uint16_t endtime); + void disableOffTimer(void); + uint16_t getOffTime(void); + bool getOffTimerEnabled(void); + void setCurrentTime(const uint16_t mins_since_midnight); + uint16_t getCurrentTime(void); + uint8_t* getRaw(void); + void setRaw(const uint8_t new_code[], + const uint16_t length = kDaikinStateLength); + static bool validChecksum(uint8_t state[], + const uint16_t length = kDaikinStateLength); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertFan(const stdAc::fanspeed_t speed); +#ifdef ARDUINO + String toString(void); + static String renderTime(const uint16_t timemins); +#else + std::string toString(void); + static std::string renderTime(const uint16_t timemins); +#endif +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif + // # of bytes per command + uint8_t remote[kDaikinStateLength]; + void stateReset(void); + void checksum(void); +}; + +// Class to emulate a Daikin ARC477A1 remote. +class IRDaikin2 { + public: + explicit IRDaikin2(uint16_t pin); + +#if SEND_DAIKIN2 + void send(const uint16_t repeat = kDaikin2DefaultRepeat); +#endif + void begin(); + void on(); + void off(); + void setPower(const bool state); + bool getPower(); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setFan(const uint8_t fan); + uint8_t getFan(); + uint8_t getMode(); + void setMode(const uint8_t mode); + void setSwingVertical(const uint8_t position); + uint8_t getSwingVertical(); + void setSwingHorizontal(const uint8_t position); + uint8_t getSwingHorizontal(); + bool getQuiet(); + void setQuiet(const bool on); + bool getPowerful(); + void setPowerful(const bool on); + void setSensor(const bool on); + bool getSensor(); + void setEcono(const bool on); + bool getEcono(); + void setEye(const bool on); + bool getEye(); + void setEyeAuto(const bool on); + bool getEyeAuto(); + void setPurify(const bool on); + bool getPurify(); + void setMold(const bool on); + bool getMold(); + void enableOnTimer(const uint16_t starttime); + void disableOnTimer(); + uint16_t getOnTime(); + bool getOnTimerEnabled(); + void enableSleepTimer(const uint16_t sleeptime); + void disableSleepTimer(); + uint16_t getSleepTime(); + bool getSleepTimerEnabled(); + void enableOffTimer(const uint16_t endtime); + void disableOffTimer(); + uint16_t getOffTime(); + bool getOffTimerEnabled(); + void setCurrentTime(const uint16_t time); + uint16_t getCurrentTime(); + void setBeep(const uint8_t beep); + uint8_t getBeep(); + void setLight(const uint8_t light); + uint8_t getLight(); + void setClean(const bool on); + bool getClean(); + void setFreshAir(const bool on); + bool getFreshAir(); + void setFreshAirHigh(const bool on); + bool getFreshAirHigh(); + uint8_t* getRaw(); + void setRaw(const uint8_t new_code[]); + uint32_t getCommand(); + void setCommand(uint32_t value); + static bool validChecksum(uint8_t state[], + const uint16_t length = kDaikin2StateLength); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertFan(const stdAc::fanspeed_t speed); + uint8_t convertSwingV(const stdAc::swingv_t position); +#ifdef ARDUINO + String toString(); + static String renderTime(uint16_t timemins); +#else + std::string toString(); + static std::string renderTime(uint16_t timemins); +#endif +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif + // # of bytes per command + uint8_t remote_state[kDaikin2StateLength]; + void stateReset(); + void checksum(); + void clearOnTimerFlag(); + void clearSleepTimerFlag(); +}; + +// Class to emulate a Daikin ARC433B69 remote. +class IRDaikin216 { + public: + explicit IRDaikin216(uint16_t pin); + +#if SEND_DAIKIN216 + void send(const uint16_t repeat = kDaikin216DefaultRepeat); +#endif + void begin(); + uint8_t* getRaw(); + void setRaw(const uint8_t new_code[]); + static bool validChecksum(uint8_t state[], + const uint16_t length = kDaikin216StateLength); + void on(void); + void off(void); + void setPower(const bool on); + bool getPower(void); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setMode(const uint8_t mode); + uint8_t getMode(void); + static uint8_t convertMode(const stdAc::opmode_t mode); + void setFan(const uint8_t fan); + uint8_t getFan(void); + static uint8_t convertFan(const stdAc::fanspeed_t speed); + void setSwingVertical(const bool on); + bool getSwingVertical(void); + void setSwingHorizontal(const bool on); + bool getSwingHorizontal(void); + void setQuiet(const bool on); + bool getQuiet(void); +#ifdef ARDUINO + String toString(void); + static String renderTime(const uint16_t timemins); +#else + std::string toString(void); + static std::string renderTime(const uint16_t timemins); +#endif +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif + // # of bytes per command + uint8_t remote_state[kDaikin216StateLength]; + void stateReset(); + void checksum(); +}; + +#endif // IR_DAIKIN_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Denon.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Denon.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Denon.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Denon.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Dish.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Dish.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Dish.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Dish.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Electra.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Electra.cpp similarity index 87% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Electra.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Electra.cpp index df69be748..0700ab698 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Electra.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Electra.cpp @@ -1,4 +1,4 @@ -// Copyright 2018 David Conran +// Copyright 2018, 2019 David Conran #include "IRrecv.h" #include "IRsend.h" @@ -17,6 +17,7 @@ // Ref: // https://github.com/markszabo/IRremoteESP8266/issues/527 +// https://github.com/markszabo/IRremoteESP8266/issues/642 // Constants const uint16_t kElectraAcHdrMark = 9166; @@ -24,7 +25,7 @@ const uint16_t kElectraAcBitMark = 646; const uint16_t kElectraAcHdrSpace = 4470; const uint16_t kElectraAcOneSpace = 1647; const uint16_t kElectraAcZeroSpace = 547; -const uint32_t kElectraAcMessageGap = 100000; // Completely made-up guess. +const uint32_t kElectraAcMessageGap = kDefaultMessageGap; // Just a guess. #if SEND_ELECTRA_AC // Send a Electra message @@ -42,7 +43,8 @@ void IRsend::sendElectraAC(uint8_t data[], uint16_t nbytes, uint16_t repeat) { kElectraAcOneSpace, kElectraAcBitMark, kElectraAcZeroSpace, kElectraAcBitMark, kElectraAcMessageGap, data, nbytes, 38000, // Complete guess of the modulation frequency. - true, 0, 50); + false, // Send data in LSB order per byte + 0, 50); } #endif @@ -56,7 +58,7 @@ void IRsend::sendElectraAC(uint8_t data[], uint16_t nbytes, uint16_t repeat) { // Returns: // boolean: True if it can decode it, false if it can't. // -// Status: Alpha / Needs testing against a real device. +// Status: Beta / Probably works. // bool IRrecv::decodeElectraAC(decode_results *results, uint16_t nbits, bool strict) { @@ -68,8 +70,6 @@ bool IRrecv::decodeElectraAC(decode_results *results, uint16_t nbits, return false; // Not strictly a ELECTRA_AC message. } - // The protocol sends the data normal + inverted, alternating on - // each byte. Hence twice the number of expected data bits. if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false; // Can't possibly be a valid ELECTRA_AC message. @@ -87,7 +87,7 @@ bool IRrecv::decodeElectraAC(decode_results *results, uint16_t nbits, i++, dataBitsSoFar += 8, offset += data_result.used) { data_result = matchData(&(results->rawbuf[offset]), 8, kElectraAcBitMark, kElectraAcOneSpace, kElectraAcBitMark, - kElectraAcZeroSpace, kTolerance, 0, true); + kElectraAcZeroSpace, kTolerance, 0, false); if (data_result.success == false) return false; // Fail results->state[i] = data_result.data; } @@ -99,7 +99,12 @@ bool IRrecv::decodeElectraAC(decode_results *results, uint16_t nbits, return false; // Compliance - if (strict && dataBitsSoFar != nbits) return false; + if (strict) { + if (dataBitsSoFar != nbits) return false; + // Verify the checksum. + if (sumBytes(results->state, (dataBitsSoFar / 8) - 1) != + results->state[(dataBitsSoFar / 8) - 1]) return false; + } // Success results->decode_type = ELECTRA_AC; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Fujitsu.cpp similarity index 88% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Fujitsu.cpp index 7c1b99834..de1b97e87 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Fujitsu.cpp @@ -84,9 +84,9 @@ void IRFujitsuAC::begin() { _irsend.begin(); } #if SEND_FUJITSU_AC // Send the current desired state to the IR LED. -void IRFujitsuAC::send() { +void IRFujitsuAC::send(const uint16_t repeat) { getRaw(); - _irsend.sendFujitsuAC(remote_state, getStateLength()); + _irsend.sendFujitsuAC(remote_state, getStateLength(), repeat); } #endif // SEND_FUJITSU_AC @@ -281,6 +281,7 @@ void IRFujitsuAC::setMode(uint8_t mode) { } uint8_t IRFujitsuAC::getMode() { return _mode; } + // Set the requested swing operation mode of the a/c unit. void IRFujitsuAC::setSwing(uint8_t swingMode) { switch (_model) { @@ -319,6 +320,39 @@ bool IRFujitsuAC::validChecksum(uint8_t state[], uint16_t length) { return checksum == (uint8_t)(sum_complement - sum); // Does it match? } +// Convert a standard A/C mode into its native mode. +uint8_t IRFujitsuAC::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kFujitsuAcModeCool; + case stdAc::opmode_t::kHeat: + return kFujitsuAcModeHeat; + case stdAc::opmode_t::kDry: + return kFujitsuAcModeDry; + case stdAc::opmode_t::kFan: + return kFujitsuAcModeFan; + default: + return kFujitsuAcModeAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRFujitsuAC::convertFan(stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + return kFujitsuAcFanQuiet; + case stdAc::fanspeed_t::kLow: + return kFujitsuAcFanLow; + case stdAc::fanspeed_t::kMedium: + return kFujitsuAcFanMed; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kFujitsuAcFanHigh; + default: + return kFujitsuAcFanAuto; + } +} + // Convert the internal state into a human readable string. #ifdef ARDUINO String IRFujitsuAC::toString() { @@ -327,77 +361,80 @@ String IRFujitsuAC::toString() { std::string IRFujitsuAC::toString() { std::string result = ""; #endif // ARDUINO - result += "Power: "; + result += F("Power: "); if (getPower()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Mode: " + uint64ToString(getMode()); + result += F("Off"); + result += F(", Mode: "); + result += uint64ToString(getMode()); switch (getMode()) { case kFujitsuAcModeAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kFujitsuAcModeCool: - result += " (COOL)"; + result += F(" (COOL)"); break; case kFujitsuAcModeHeat: - result += " (HEAT)"; + result += F(" (HEAT)"); break; case kFujitsuAcModeDry: - result += " (DRY)"; + result += F(" (DRY)"); break; case kFujitsuAcModeFan: - result += " (FAN)"; + result += F(" (FAN)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - result += ", Temp: " + uint64ToString(getTemp()) + "C"; - result += ", Fan: " + uint64ToString(getFanSpeed()); + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFanSpeed()); switch (getFanSpeed()) { case kFujitsuAcFanAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kFujitsuAcFanHigh: - result += " (HIGH)"; + result += F(" (HIGH)"); break; case kFujitsuAcFanMed: - result += " (MED)"; + result += F(" (MED)"); break; case kFujitsuAcFanLow: - result += " (LOW)"; + result += F(" (LOW)"); break; case kFujitsuAcFanQuiet: - result += " (QUIET)"; + result += F(" (QUIET)"); break; } - result += ", Swing: "; + result += F(", Swing: "); switch (getSwing()) { case kFujitsuAcSwingOff: - result += "Off"; + result += F("Off"); break; case kFujitsuAcSwingVert: - result += "Vert"; + result += F("Vert"); break; case kFujitsuAcSwingHoriz: - result += "Horiz"; + result += F("Horiz"); break; case kFujitsuAcSwingBoth: - result += "Vert + Horiz"; + result += F("Vert + Horiz"); break; default: - result += "UNKNOWN"; + result += F("UNKNOWN"); } - result += ", Command: "; + result += F(", Command: "); switch (getCmd()) { case kFujitsuAcCmdStepHoriz: - result += "Step vane horizontally"; + result += F("Step vane horizontally"); break; case kFujitsuAcCmdStepVert: - result += "Step vane vertically"; + result += F("Step vane vertically"); break; default: - result += "N/A"; + result += F("N/A"); } return result; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h b/lib/IRremoteESP8266-2.6.0/src/ir_Fujitsu.h similarity index 93% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Fujitsu.h index bba634be6..78a4f8951 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Fujitsu.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Fujitsu.h @@ -13,6 +13,9 @@ #include "IRrecv.h" #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif // FUJITSU A/C support added by Jonny Graham @@ -78,7 +81,7 @@ class IRFujitsuAC { void setModel(fujitsu_ac_remote_model_t model); void stateReset(); #if SEND_FUJITSU_AC - void send(); + void send(const uint16_t repeat = kFujitsuAcMinRepeat); #endif // SEND_FUJITSU_AC void begin(); void off(); @@ -99,15 +102,21 @@ class IRFujitsuAC { uint8_t getStateLength(); static bool validChecksum(uint8_t* state, uint16_t length); bool getPower(); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(stdAc::fanspeed_t speed); #ifdef ARDUINO String toString(); #else std::string toString(); #endif +#ifndef UNIT_TEST private: - uint8_t remote_state[kFujitsuAcStateLength]; IRsend _irsend; +#else + IRsendTest _irsend; +#endif + uint8_t remote_state[kFujitsuAcStateLength]; uint8_t _temp; uint8_t _fanSpeed; uint8_t _mode; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_GICable.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_GICable.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_GICable.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_GICable.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_GlobalCache.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_GlobalCache.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_GlobalCache.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_GlobalCache.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Gree.cpp similarity index 82% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Gree.cpp index df8afada6..756f008d4 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Gree.cpp @@ -27,7 +27,7 @@ // Constants // Ref: https://github.com/ToniA/arduino-heatpumpir/blob/master/GreeHeatpumpIR.h const uint16_t kGreeHdrMark = 9000; -const uint16_t kGreeHdrSpace = 4000; +const uint16_t kGreeHdrSpace = 4500; // See #684 and real example in unit tests const uint16_t kGreeBitMark = 620; const uint16_t kGreeOneSpace = 1600; const uint16_t kGreeZeroSpace = 540; @@ -59,7 +59,7 @@ void IRsend::sendGree(unsigned char data[], uint16_t nbytes, uint16_t repeat) { // Footer #1 sendGeneric(0, 0, // No Header kGreeBitMark, kGreeOneSpace, kGreeBitMark, kGreeZeroSpace, - kGreeBitMark, kGreeMsgSpace, 0b010, 3, 38, true, 0, false); + kGreeBitMark, kGreeMsgSpace, 0b010, 3, 38, false, 0, 50); // Block #2 sendGeneric(0, 0, // No Header for Block #2 @@ -129,9 +129,9 @@ void IRGreeAC::fixup() { void IRGreeAC::begin() { _irsend.begin(); } #if SEND_GREE -void IRGreeAC::send() { +void IRGreeAC::send(const uint16_t repeat) { fixup(); // Ensure correct settings before sending. - _irsend.sendGree(remote_state); + _irsend.sendGree(remote_state, kGreeStateLength, repeat); } #endif // SEND_GREE @@ -305,6 +305,57 @@ uint8_t IRGreeAC::getSwingVerticalPosition() { return remote_state[4] & kGreeSwingPosMask; } + +// Convert a standard A/C mode into its native mode. +uint8_t IRGreeAC::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kGreeCool; + case stdAc::opmode_t::kHeat: + return kGreeHeat; + case stdAc::opmode_t::kDry: + return kGreeDry; + case stdAc::opmode_t::kFan: + return kGreeFan; + default: + return kGreeAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRGreeAC::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + return kGreeFanMin; + case stdAc::fanspeed_t::kLow: + case stdAc::fanspeed_t::kMedium: + return kGreeFanMax - 1; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kGreeFanMax; + default: + return kGreeFanAuto; + } +} + +// Convert a standard A/C Vertical Swing into its native version. +uint8_t IRGreeAC::convertSwingV(const stdAc::swingv_t swingv) { + switch (swingv) { + case stdAc::swingv_t::kHighest: + return kGreeSwingUp; + case stdAc::swingv_t::kHigh: + return kGreeSwingMiddleUp; + case stdAc::swingv_t::kMiddle: + return kGreeSwingMiddle; + case stdAc::swingv_t::kLow: + return kGreeSwingMiddleDown; + case stdAc::swingv_t::kLowest: + return kGreeSwingDown; + default: + return kGreeSwingAuto; + } +} + // Convert the internal state into a human readable string. #ifdef ARDUINO String IRGreeAC::toString() { @@ -313,74 +364,77 @@ String IRGreeAC::toString() { std::string IRGreeAC::toString() { std::string result = ""; #endif // ARDUINO - result += "Power: "; + result += F("Power: "); if (getPower()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Mode: " + uint64ToString(getMode()); + result += F("Off"); + result += F(", Mode: "); + result += uint64ToString(getMode()); switch (getMode()) { case kGreeAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kGreeCool: - result += " (COOL)"; + result += F(" (COOL)"); break; case kGreeHeat: - result += " (HEAT)"; + result += F(" (HEAT)"); break; case kGreeDry: - result += " (DRY)"; + result += F(" (DRY)"); break; case kGreeFan: - result += " (FAN)"; + result += F(" (FAN)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - result += ", Temp: " + uint64ToString(getTemp()) + "C"; - result += ", Fan: " + uint64ToString(getFan()); + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFan()); switch (getFan()) { case 0: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kGreeFanMax: - result += " (MAX)"; + result += F(" (MAX)"); break; } - result += ", Turbo: "; + result += F(", Turbo: "); if (getTurbo()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", XFan: "; + result += F("Off"); + result += F(", XFan: "); if (getXFan()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Light: "; + result += F("Off"); + result += F(", Light: "); if (getLight()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Sleep: "; + result += F("Off"); + result += F(", Sleep: "); if (getSleep()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Swing Vertical Mode: "; + result += F("Off"); + result += F(", Swing Vertical Mode: "); if (getSwingVerticalAuto()) - result += "Auto"; + result += F("Auto"); else - result += "Manual"; - result += - ", Swing Vertical Pos: " + uint64ToString(getSwingVerticalPosition()); + result += F("Manual"); + result += F(", Swing Vertical Pos: "); + result += uint64ToString(getSwingVerticalPosition()); switch (getSwingVerticalPosition()) { case kGreeSwingLastPos: - result += " (Last Pos)"; + result += F(" (Last Pos)"); break; case kGreeSwingAuto: - result += " (Auto)"; + result += F(" (Auto)"); break; } return result; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h b/lib/IRremoteESP8266-2.6.0/src/ir_Gree.h similarity index 89% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Gree.h index 73f69eb31..c3c5916dc 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Gree.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Gree.h @@ -14,6 +14,9 @@ #endif #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif // GGGG RRRRRR EEEEEEE EEEEEEE // GG GG RR RR EE EE @@ -44,6 +47,8 @@ const uint8_t kGreeSwingPosMask = 0b00001111; const uint8_t kGreeMinTemp = 16; // Celsius const uint8_t kGreeMaxTemp = 30; // Celsius +const uint8_t kGreeFanAuto = 0; +const uint8_t kGreeFanMin = 1; const uint8_t kGreeFanMax = 3; const uint8_t kGreeSwingLastPos = 0b00000000; @@ -84,7 +89,7 @@ class IRGreeAC { void stateReset(); #if SEND_GREE - void send(); + void send(const uint16_t repeat = kGreeDefaultRepeat); #endif // SEND_GREE void begin(); void on(); @@ -108,7 +113,9 @@ class IRGreeAC { void setSwingVertical(const bool automatic, const uint8_t position); bool getSwingVerticalAuto(); uint8_t getSwingVerticalPosition(); - + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); + uint8_t convertSwingV(const stdAc::swingv_t swingv); uint8_t* getRaw(); void setRaw(uint8_t new_code[]); static bool validChecksum(const uint8_t state[], @@ -118,13 +125,17 @@ class IRGreeAC { #else std::string toString(); #endif +#ifndef UNIT_TEST private: + IRsend _irsend; +#else // UNIT_TEST + IRsendTest _irsend; +#endif // UNIT_TEST // The state of the IR remote in IR code form. uint8_t remote_state[kGreeStateLength]; void checksum(const uint16_t length = kGreeStateLength); void fixup(); - IRsend _irsend; }; #endif // IR_GREE_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Haier.cpp similarity index 75% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Haier.cpp index 2c47e4eac..f76bb3447 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Haier.cpp @@ -45,7 +45,7 @@ const uint32_t kHaierAcMinGap = 150000; // Completely made up value. // nbytes: Nr. of bytes of data in the array. (>=kHaierACStateLength) // repeat: Nr. of times the message is to be repeated. (Default = 0). // -// Status: Beta / Probably working. +// Status: STABLE / Known to be working. // void IRsend::sendHaierAC(unsigned char data[], uint16_t nbytes, uint16_t repeat) { @@ -86,9 +86,9 @@ IRHaierAC::IRHaierAC(uint16_t pin) : _irsend(pin) { stateReset(); } void IRHaierAC::begin() { _irsend.begin(); } #if SEND_HAIER_AC -void IRHaierAC::send() { +void IRHaierAC::send(const uint16_t repeat) { checksum(); - _irsend.sendHaierAC(remote_state); + _irsend.sendHaierAC(remote_state, kHaierACStateLength, repeat); } #endif // SEND_HAIER_AC @@ -104,7 +104,10 @@ bool IRHaierAC::validChecksum(uint8_t state[], const uint16_t length) { void IRHaierAC::stateReset() { for (uint8_t i = 1; i < kHaierACStateLength; i++) remote_state[i] = 0x0; remote_state[0] = kHaierAcPrefix; - remote_state[2] = 0b00100000; + remote_state[2] = 0x20; + remote_state[4] = 0x0C; + remote_state[5] = 0xC0; + remote_state[6] = 0x20; setTemp(kHaierAcDefTemp); setFan(kHaierAcFanAuto); @@ -304,14 +307,63 @@ std::string IRHaierAC::timeToString(const uint16_t nr_mins) { std::string result = ""; #endif // ARDUINO - if (nr_mins / 24 < 10) result += "0"; // Zero pad. + if (nr_mins / 24 < 10) result += '0'; // Zero pad. result += uint64ToString(nr_mins / 60); - result += ":"; - if (nr_mins % 60 < 10) result += "0"; // Zero pad. + result += ':'; + if (nr_mins % 60 < 10) result += '0'; // Zero pad. result += uint64ToString(nr_mins % 60); return result; } +// Convert a standard A/C mode into its native mode. +uint8_t IRHaierAC::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kHaierAcCool; + case stdAc::opmode_t::kHeat: + return kHaierAcHeat; + case stdAc::opmode_t::kDry: + return kHaierAcDry; + case stdAc::opmode_t::kFan: + return kHaierAcFan; + default: + return kHaierAcAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRHaierAC::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kHaierAcFanLow; + case stdAc::fanspeed_t::kMedium: + return kHaierAcFanMed; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kHaierAcFanHigh; + default: + return kHaierAcFanAuto; + } +} + +// Convert a standard A/C vertical swing into its native setting. +uint8_t IRHaierAC::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kHighest: + case stdAc::swingv_t::kHigh: + case stdAc::swingv_t::kMiddle: + return kHaierAcSwingUp; + case stdAc::swingv_t::kLow: + case stdAc::swingv_t::kLowest: + return kHaierAcSwingDown; + case stdAc::swingv_t::kOff: + return kHaierAcSwingOff; + default: + return kHaierAcSwingChg; + } +} + // Convert the internal state into a human readable string. #ifdef ARDUINO String IRHaierAC::toString() { @@ -321,114 +373,122 @@ std::string IRHaierAC::toString() { std::string result = ""; #endif // ARDUINO uint8_t cmd = getCommand(); - result += "Command: " + uint64ToString(cmd) + " ("; + result += F("Command: "); + result += uint64ToString(cmd); + result += F(" ("); switch (cmd) { case kHaierAcCmdOff: - result += "Off"; + result += F("Off"); break; case kHaierAcCmdOn: - result += "On"; + result += F("On"); break; case kHaierAcCmdMode: - result += "Mode"; + result += F("Mode"); break; case kHaierAcCmdFan: - result += "Fan"; + result += F("Fan"); break; case kHaierAcCmdTempUp: - result += "Temp Up"; + result += F("Temp Up"); break; case kHaierAcCmdTempDown: - result += "Temp Down"; + result += F("Temp Down"); break; case kHaierAcCmdSleep: - result += "Sleep"; + result += F("Sleep"); break; case kHaierAcCmdTimerSet: - result += "Timer Set"; + result += F("Timer Set"); break; case kHaierAcCmdTimerCancel: - result += "Timer Cancel"; + result += F("Timer Cancel"); break; case kHaierAcCmdHealth: - result += "Health"; + result += F("Health"); break; case kHaierAcCmdSwing: - result += "Swing"; + result += F("Swing"); break; default: - result += "Unknown"; + result += F("Unknown"); } - result += ")"; - result += ", Mode: " + uint64ToString(getMode()); + result += ')'; + result += F(", Mode: "); + result += uint64ToString(getMode()); switch (getMode()) { case kHaierAcAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kHaierAcCool: - result += " (COOL)"; + result += F(" (COOL)"); break; case kHaierAcHeat: - result += " (HEAT)"; + result += F(" (HEAT)"); break; case kHaierAcDry: - result += " (DRY)"; + result += F(" (DRY)"); break; case kHaierAcFan: - result += " (FAN)"; + result += F(" (FAN)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - result += ", Temp: " + uint64ToString(getTemp()) + "C"; - result += ", Fan: " + uint64ToString(getFan()); + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFan()); switch (getFan()) { case kHaierAcFanAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kHaierAcFanHigh: - result += " (MAX)"; + result += F(" (MAX)"); break; } - result += ", Swing: " + uint64ToString(getSwing()) + " ("; + result += F(", Swing: "); + result += uint64ToString(getSwing()); + result += F(" ("); switch (getSwing()) { case kHaierAcSwingOff: - result += "Off"; + result += F("Off"); break; case kHaierAcSwingUp: - result += "Up"; + result += F("Up"); break; case kHaierAcSwingDown: - result += "Down"; + result += F("Down"); break; case kHaierAcSwingChg: - result += "Chg"; + result += F("Chg"); break; default: - result += "Unknown"; + result += F("Unknown"); } - result += ")"; - result += ", Sleep: "; + result += ')'; + result += F(", Sleep: "); if (getSleep()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Health: "; + result += F("Off"); + result += F(", Health: "); if (getHealth()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Current Time: " + timeToString(getCurrTime()); - result += ", On Timer: "; + result += F("Off"); + result += F(", Current Time: "); + result += timeToString(getCurrTime()); + result += F(", On Timer: "); if (getOnTimer() >= 0) result += timeToString(getOnTimer()); else - result += "Off"; - result += ", Off Timer: "; + result += F("Off"); + result += F(", Off Timer: "); if (getOffTimer() >= 0) result += timeToString(getOffTimer()); else - result += "Off"; + result += F("Off"); return result; } @@ -440,9 +500,9 @@ IRHaierACYRW02::IRHaierACYRW02(uint16_t pin) : _irsend(pin) { stateReset(); } void IRHaierACYRW02::begin() { _irsend.begin(); } #if SEND_HAIER_AC_YRW02 -void IRHaierACYRW02::send() { +void IRHaierACYRW02::send(const uint16_t repeat) { checksum(); - _irsend.sendHaierACYRW02(remote_state); + _irsend.sendHaierACYRW02(remote_state, kHaierACYRW02StateLength, repeat); } #endif // SEND_HAIER_AC_YRW02 @@ -628,6 +688,57 @@ void IRHaierACYRW02::setSwing(uint8_t state) { remote_state[1] |= newstate; } +// Convert a standard A/C mode into its native mode. +uint8_t IRHaierACYRW02::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kHaierAcYrw02Cool; + case stdAc::opmode_t::kHeat: + return kHaierAcYrw02Heat; + case stdAc::opmode_t::kDry: + return kHaierAcYrw02Dry; + case stdAc::opmode_t::kFan: + return kHaierAcYrw02Fan; + default: + return kHaierAcYrw02Auto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRHaierACYRW02::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kHaierAcYrw02FanLow; + case stdAc::fanspeed_t::kMedium: + return kHaierAcYrw02FanMed; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kHaierAcYrw02FanHigh; + default: + return kHaierAcYrw02FanAuto; + } +} + +// Convert a standard A/C vertical swing into its native setting. +uint8_t IRHaierACYRW02::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kHighest: + case stdAc::swingv_t::kHigh: + return kHaierAcYrw02SwingTop; + case stdAc::swingv_t::kMiddle: + return kHaierAcYrw02SwingMiddle; + case stdAc::swingv_t::kLow: + return kHaierAcYrw02SwingDown; + case stdAc::swingv_t::kLowest: + return kHaierAcYrw02SwingBottom; + case stdAc::swingv_t::kOff: + return kHaierAcYrw02SwingOff; + default: + return kHaierAcYrw02SwingAuto; + } +} + // Convert the internal state into a human readable string. #ifdef ARDUINO String IRHaierACYRW02::toString() { @@ -636,132 +747,141 @@ String IRHaierACYRW02::toString() { std::string IRHaierACYRW02::toString() { std::string result = ""; #endif // ARDUINO - result += "Power: "; + result += F("Power: "); if (getPower()) - result += "On"; + result += F("On"); else - result += "Off"; + result += F("Off"); uint8_t cmd = getButton(); - result += ", Button: " + uint64ToString(cmd) + " ("; + result += F(", Button: "); + result += uint64ToString(cmd); + result += F(" ("); switch (cmd) { case kHaierAcYrw02ButtonPower: - result += "Power"; + result += F("Power"); break; case kHaierAcYrw02ButtonMode: - result += "Mode"; + result += F("Mode"); break; case kHaierAcYrw02ButtonFan: - result += "Fan"; + result += F("Fan"); break; case kHaierAcYrw02ButtonTempUp: - result += "Temp Up"; + result += F("Temp Up"); break; case kHaierAcYrw02ButtonTempDown: - result += "Temp Down"; + result += F("Temp Down"); break; case kHaierAcYrw02ButtonSleep: - result += "Sleep"; + result += F("Sleep"); break; case kHaierAcYrw02ButtonHealth: result += "Health"; break; case kHaierAcYrw02ButtonSwing: - result += "Swing"; + result += F("Swing"); break; case kHaierAcYrw02ButtonTurbo: - result += "Turbo"; + result += F("Turbo"); break; default: - result += "Unknown"; + result += F("Unknown"); } - result += ")"; - result += ", Mode: " + uint64ToString(getMode()); + result += ')'; + result += F(", Mode: "); + result += uint64ToString(getMode()); switch (getMode()) { case kHaierAcYrw02Auto: - result += " (Auto)"; + result += F(" (Auto)"); break; case kHaierAcYrw02Cool: - result += " (Cool)"; + result += F(" (Cool)"); break; case kHaierAcYrw02Heat: - result += " (Heat)"; + result += F(" (Heat)"); break; case kHaierAcYrw02Dry: - result += " (Dry)"; + result += F(" (Dry)"); break; case kHaierAcYrw02Fan: - result += " (Fan)"; + result += F(" (Fan)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - result += ", Temp: " + uint64ToString(getTemp()) + "C"; - result += ", Fan: " + uint64ToString(getFan()); + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFan()); switch (getFan()) { case kHaierAcYrw02FanAuto: - result += " (Auto)"; + result += F(" (Auto)"); break; case kHaierAcYrw02FanHigh: - result += " (High)"; + result += F(" (High)"); break; case kHaierAcYrw02FanLow: - result += " (Low)"; + result += F(" (Low)"); break; case kHaierAcYrw02FanMed: - result += " (Med)"; + result += F(" (Med)"); break; default: - result += " (Unknown)"; + result += F(" (Unknown)"); } - result += ", Turbo: " + uint64ToString(getTurbo()) + " ("; + result += F(", Turbo: "); + result += uint64ToString(getTurbo()); + result += F(" ("); switch (getTurbo()) { case kHaierAcYrw02TurboOff: - result += "Off"; + result += F("Off"); break; case kHaierAcYrw02TurboLow: - result += "Low"; + result += F("Low"); break; case kHaierAcYrw02TurboHigh: - result += "High"; + result += F("High"); break; default: - result += "Unknown"; + result += F("Unknown"); } - result += ")"; - result += ", Swing: " + uint64ToString(getSwing()) + " ("; + result += ')'; + result += F(", Swing: "); + result += uint64ToString(getSwing()); + result += F(" ("); switch (getSwing()) { case kHaierAcYrw02SwingOff: - result += "Off"; + result += F("Off"); break; case kHaierAcYrw02SwingAuto: - result += "Auto"; + result += F("Auto"); break; case kHaierAcYrw02SwingBottom: - result += "Bottom"; + result += F("Bottom"); break; case kHaierAcYrw02SwingDown: - result += "Down"; + result += F("Down"); break; case kHaierAcYrw02SwingTop: - result += "Top"; + result += F("Top"); break; case kHaierAcYrw02SwingMiddle: - result += "Middle"; + result += F("Middle"); break; default: - result += "Unknown"; + result += F("Unknown"); } - result += ")"; - result += ", Sleep: "; + result += ')'; + result += F(", Sleep: "); if (getSleep()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Health: "; + result += F("Off"); + result += F(", Health: "); if (getHealth()) - result += "On"; + result += F("On"); else - result += "Off"; + result += F("Off"); return result; } @@ -777,7 +897,7 @@ std::string IRHaierACYRW02::toString() { // Returns: // boolean: True if it can decode it, false if it can't. // -// Status: BETA / Appears to be working. +// Status: STABLE / Known to be working. // bool IRrecv::decodeHaierAC(decode_results* results, uint16_t nbits, bool strict) { diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h b/lib/IRremoteESP8266-2.6.0/src/ir_Haier.h similarity index 93% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Haier.h index fdc15a3a8..8f7b35196 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Haier.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Haier.h @@ -11,6 +11,9 @@ #endif #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif // HH HH AAA IIIII EEEEEEE RRRRRR // HH HH AAAAA III EE RR RR @@ -186,7 +189,7 @@ class IRHaierAC { explicit IRHaierAC(uint16_t pin); #if SEND_HAIER_AC - void send(); + void send(const uint16_t repeat = kHaierAcDefaultRepeat); #endif // SEND_HAIER_AC void begin(); @@ -223,6 +226,10 @@ class IRHaierAC { void setRaw(uint8_t new_code[]); static bool validChecksum(uint8_t state[], const uint16_t length = kHaierACStateLength); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); + uint8_t convertSwingV(const stdAc::swingv_t position); + #ifdef ARDUINO String toString(); static String timeToString(const uint16_t nr_mins); @@ -230,14 +237,18 @@ class IRHaierAC { std::string toString(); static std::string timeToString(const uint16_t nr_mins); #endif +#ifndef UNIT_TEST private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif uint8_t remote_state[kHaierACStateLength]; void stateReset(); void checksum(); static uint16_t getTime(const uint8_t ptr[]); static void setTime(uint8_t ptr[], const uint16_t nr_mins); - IRsend _irsend; }; class IRHaierACYRW02 { @@ -245,7 +256,7 @@ class IRHaierACYRW02 { explicit IRHaierACYRW02(uint16_t pin); #if SEND_HAIER_AC_YRW02 - void send(); + void send(const uint16_t repeat = kHaierAcYrw02DefaultRepeat); #endif // SEND_HAIER_AC_YRW02 void begin(); @@ -281,17 +292,24 @@ class IRHaierACYRW02 { void setRaw(uint8_t new_code[]); static bool validChecksum(uint8_t state[], const uint16_t length = kHaierACYRW02StateLength); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); + uint8_t convertSwingV(const stdAc::swingv_t position); #ifdef ARDUINO String toString(); #else std::string toString(); #endif +#ifndef UNIT_TEST private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif uint8_t remote_state[kHaierACYRW02StateLength]; void stateReset(); void checksum(); - IRsend _irsend; }; #endif // IR_HAIER_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Hitachi.cpp similarity index 86% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Hitachi.cpp index 111051974..b88189f4a 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Hitachi.cpp @@ -30,7 +30,7 @@ const uint16_t kHitachiAc1HdrSpace = 3400; const uint16_t kHitachiAcBitMark = 400; const uint16_t kHitachiAcOneSpace = 1250; const uint16_t kHitachiAcZeroSpace = 500; -const uint32_t kHitachiAcMinGap = 100000; // Completely made up value. +const uint32_t kHitachiAcMinGap = kDefaultMessageGap; // Just a guess. #if (SEND_HITACHI_AC || SEND_HITACHI_AC2) // Send a Hitachi A/C message. @@ -106,7 +106,7 @@ void IRsend::sendHitachiAC2(unsigned char data[], uint16_t nbytes, } #endif // SEND_HITACHI_AC2 -// Class for handling the remote control oh a Hitachi 28 byte A/C message. +// Class for handling the remote control on a Hitachi 28 byte A/C message. // Inspired by: // https://github.com/ToniA/arduino-heatpumpir/blob/master/HitachiHeatpumpIR.cpp @@ -159,9 +159,9 @@ void IRHitachiAc::setRaw(const uint8_t new_code[], const uint16_t length) { } #if SEND_HITACHI_AC -void IRHitachiAc::send() { +void IRHitachiAc::send(const uint16_t repeat) { checksum(); - _irsend.sendHitachiAC(remote_state); + _irsend.sendHitachiAC(remote_state, kHitachiAcStateLength, repeat); } #endif // SEND_HITACHI_AC @@ -257,6 +257,40 @@ void IRHitachiAc::setSwingHorizontal(const bool on) { remote_state[15] &= 0x7F; } + +// Convert a standard A/C mode into its native mode. +uint8_t IRHitachiAc::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kHitachiAcCool; + case stdAc::opmode_t::kHeat: + return kHitachiAcHeat; + case stdAc::opmode_t::kDry: + return kHitachiAcDry; + case stdAc::opmode_t::kFan: + return kHitachiAcFan; + default: + return kHitachiAcAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRHitachiAc::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kHitachiAcFanLow; + case stdAc::fanspeed_t::kMedium: + return kHitachiAcFanLow + 1; + case stdAc::fanspeed_t::kHigh: + return kHitachiAcFanHigh - 1; + case stdAc::fanspeed_t::kMax: + return kHitachiAcFanHigh; + default: + return kHitachiAcFanAuto; + } +} + // Convert the internal state into a human readable string. #ifdef ARDUINO String IRHitachiAc::toString() { @@ -265,57 +299,60 @@ String IRHitachiAc::toString() { std::string IRHitachiAc::toString() { std::string result = ""; #endif // ARDUINO - result += "Power: "; + result += F("Power: "); if (getPower()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Mode: " + uint64ToString(getMode()); + result += F("Off"); + result += F(", Mode: "); + result += uint64ToString(getMode()); switch (getMode()) { case kHitachiAcAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kHitachiAcCool: - result += " (COOL)"; + result += F(" (COOL)"); break; case kHitachiAcHeat: - result += " (HEAT)"; + result += F(" (HEAT)"); break; case kHitachiAcDry: - result += " (DRY)"; + result += F(" (DRY)"); break; case kHitachiAcFan: - result += " (FAN)"; + result += F(" (FAN)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - result += ", Temp: " + uint64ToString(getTemp()) + "C"; - result += ", Fan: " + uint64ToString(getFan()); + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFan()); switch (getFan()) { case kHitachiAcFanAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kHitachiAcFanLow: - result += " (LOW)"; + result += F(" (LOW)"); break; case kHitachiAcFanHigh: - result += " (HIGH)"; + result += F(" (HIGH)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); break; } - result += ", Swing (Vertical): "; + result += F(", Swing (Vertical): "); if (getSwingVertical()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Swing (Horizontal): "; + result += F("Off"); + result += F(", Swing (Horizontal): "); if (getSwingHorizontal()) - result += "On"; + result += F("On"); else - result += "Off"; + result += F("Off"); return result; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h b/lib/IRremoteESP8266-2.6.0/src/ir_Hitachi.h similarity index 87% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Hitachi.h index eddab59e4..532717447 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Hitachi.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Hitachi.h @@ -14,6 +14,9 @@ #endif #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif // Constants const uint8_t kHitachiAcAuto = 2; @@ -35,7 +38,7 @@ class IRHitachiAc { void stateReset(); #if SEND_HITACHI_AC - void send(); + void send(const uint16_t repeat = kHitachiAcDefaultRepeat); #endif // SEND_HITACHI_AC void begin(); void on(); @@ -59,17 +62,23 @@ class IRHitachiAc { const uint16_t length = kHitachiAcStateLength); static uint8_t calcChecksum(const uint8_t state[], const uint16_t length = kHitachiAcStateLength); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); #ifdef ARDUINO String toString(); #else std::string toString(); #endif +#ifndef UNIT_TEST private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif // The state of the IR remote in IR code form. uint8_t remote_state[kHitachiAcStateLength]; void checksum(const uint16_t length = kHitachiAcStateLength); - IRsend _irsend; uint8_t _previoustemp; }; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_JVC.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_JVC.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_JVC.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_JVC.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Kelvinator.cpp similarity index 91% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Kelvinator.cpp index ddf61b097..c69f4cb8a 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Kelvinator.cpp @@ -19,6 +19,7 @@ #ifndef ARDUINO #include #endif +#include "IRac.h" #include "IRrecv.h" #include "IRsend.h" #include "IRutils.h" @@ -141,9 +142,9 @@ void IRKelvinatorAC::fixup() { } #if SEND_KELVINATOR -void IRKelvinatorAC::send() { +void IRKelvinatorAC::send(const uint16_t repeat) { fixup(); // Ensure correct settings before sending. - _irsend.sendKelvinator(remote_state); + _irsend.sendKelvinator(remote_state, kKelvinatorStateLength, repeat); } #endif // SEND_KELVINATOR @@ -347,6 +348,22 @@ bool IRKelvinatorAC::getTurbo() { return ((remote_state[2] & kKelvinatorTurbo) != 0); } +// Convert a standard A/C mode into its native mode. +uint8_t IRKelvinatorAC::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kKelvinatorCool; + case stdAc::opmode_t::kHeat: + return kKelvinatorHeat; + case stdAc::opmode_t::kDry: + return kKelvinatorDry; + case stdAc::opmode_t::kFan: + return kKelvinatorFan; + default: + return kKelvinatorAuto; + } +} + // Convert the internal state into a human readable string. #ifdef ARDUINO String IRKelvinatorAC::toString() { @@ -355,76 +372,79 @@ String IRKelvinatorAC::toString() { std::string IRKelvinatorAC::toString() { std::string result = ""; #endif // ARDUINO - result += "Power: "; + result += F("Power: "); if (getPower()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Mode: " + uint64ToString(getMode()); + result += F("Off"); + result += F(", Mode: "); + result += uint64ToString(getMode()); switch (getMode()) { case kKelvinatorAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kKelvinatorCool: - result += " (COOL)"; + result += F(" (COOL)"); break; case kKelvinatorHeat: - result += " (HEAT)"; + result += F(" (HEAT)"); break; case kKelvinatorDry: - result += " (DRY)"; + result += F(" (DRY)"); break; case kKelvinatorFan: - result += " (FAN)"; + result += F(" (FAN)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - result += ", Temp: " + uint64ToString(getTemp()) + "C"; - result += ", Fan: " + uint64ToString(getFan()); + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFan()); switch (getFan()) { case kKelvinatorFanAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kKelvinatorFanMax: - result += " (MAX)"; + result += F(" (MAX)"); break; } - result += ", Turbo: "; + result += F(", Turbo: "); if (getTurbo()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Quiet: "; + result += F("Off"); + result += F(", Quiet: "); if (getQuiet()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", XFan: "; + result += F("Off"); + result += F(", XFan: "); if (getXFan()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", IonFilter: "; + result += F("Off"); + result += F(", IonFilter: "); if (getIonFilter()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Light: "; + result += F("Off"); + result += F(", Light: "); if (getLight()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Swing (Horizontal): "; + result += F("Off"); + result += F(", Swing (Horizontal): "); if (getSwingHorizontal()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Swing (Vertical): "; + result += F("Off"); + result += F(", Swing (Vertical): "); if (getSwingVertical()) - result += "On"; + result += F("On"); else - result += "Off"; + result += F("Off"); return result; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.h b/lib/IRremoteESP8266-2.6.0/src/ir_Kelvinator.h similarity index 96% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Kelvinator.h index 1508d6cdc..ce830c70a 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Kelvinator.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Kelvinator.h @@ -14,6 +14,9 @@ #endif #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif // KK KK EEEEEEE LL VV VV IIIII NN NN AAA TTTTTTT OOOOO RRRRRR // KK KK EE LL VV VV III NNN NN AAAAA TTT OO OO RR RR @@ -130,7 +133,7 @@ class IRKelvinatorAC { void stateReset(); #if SEND_KELVINATOR - void send(); + void send(const uint16_t repeat = kKelvinatorDefaultRepeat); #endif // SEND_KELVINATOR void begin(); void on(); @@ -163,18 +166,23 @@ class IRKelvinatorAC { const uint8_t* block, const uint16_t length = kKelvinatorStateLength / 2); static bool validChecksum(const uint8_t state[], const uint16_t length = kKelvinatorStateLength); + uint8_t convertMode(const stdAc::opmode_t mode); #ifdef ARDUINO String toString(); #else std::string toString(); #endif +#ifndef UNIT_TEST private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif // The state of the IR remote in IR code form. uint8_t remote_state[kKelvinatorStateLength]; void checksum(const uint16_t length = kKelvinatorStateLength); void fixup(); - IRsend _irsend; }; #endif // IR_KELVINATOR_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_LG.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_LG.cpp index f9d922fc7..36c85ff15 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_LG.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_LG.cpp @@ -85,11 +85,13 @@ uint8_t calcLGChecksum(uint16_t data) { // IR Remote models: 6711A20083V void IRsend::sendLG(uint64_t data, uint16_t nbits, uint16_t repeat) { uint16_t repeatHeaderMark = 0; + uint8_t duty = kDutyDefault; if (nbits >= kLg32Bits) { // LG 32bit protocol is near identical to Samsung except for repeats. sendSAMSUNG(data, nbits, 0); // Send it as a single Samsung message. repeatHeaderMark = kLg32RptHdrMark; + duty = 33; repeat++; } else { // LG (28-bit) protocol. @@ -97,7 +99,7 @@ void IRsend::sendLG(uint64_t data, uint16_t nbits, uint16_t repeat) { sendGeneric(kLgHdrMark, kLgHdrSpace, kLgBitMark, kLgOneSpace, kLgBitMark, kLgZeroSpace, kLgBitMark, kLgMinGap, kLgMinMessageLength, data, nbits, 38, true, 0, // Repeats are handled later. - 50); + duty); } // Repeat @@ -105,7 +107,7 @@ void IRsend::sendLG(uint64_t data, uint16_t nbits, uint16_t repeat) { if (repeat) sendGeneric(repeatHeaderMark, kLgRptSpace, 0, 0, 0, 0, // No data is sent. kLgBitMark, kLgMinGap, kLgMinMessageLength, 0, 0, // No data. - 38, true, repeat - 1, 50); + 38, true, repeat - 1, duty); } // Send an LG Variant-2 formatted message. diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_LG.h b/lib/IRremoteESP8266-2.6.0/src/ir_LG.h similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_LG.h rename to lib/IRremoteESP8266-2.6.0/src/ir_LG.h diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Lasertag.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Lasertag.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Lasertag.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Lasertag.cpp index 7f0b89ae9..b1cbdc9b1 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Lasertag.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Lasertag.cpp @@ -14,7 +14,7 @@ // Constants const uint16_t kLasertagMinSamples = 13; const uint16_t kLasertagTick = 333; -const uint32_t kLasertagMinGap = 100000; // Completely made up amount. +const uint32_t kLasertagMinGap = kDefaultMessageGap; // Just a guess. const uint8_t kLasertagTolerance = 0; // Percentage error margin. const uint16_t kLasertagExcess = 0; // See kMarkExcess. const uint16_t kLasertagDelta = 150; // Use instead of Excess and Tolerance. diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Lego.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Lego.cpp new file mode 100644 index 000000000..b051aba51 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Lego.cpp @@ -0,0 +1,128 @@ +// Copyright 2019 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" + +// LEGO +// (LEGO is a Registrated Trademark of the Lego Group.) +// +// Supported Devices: +// - LEGO Power Functions IR Receiver +// +// Ref: +// - https://github.com/markszabo/IRremoteESP8266/issues/641 +// - https://github.com/markszabo/IRremoteESP8266/files/2974525/LEGO_Power_Functions_RC_v120.pdf + +// Constants +const uint16_t kLegoPfBitMark = 158; +const uint16_t kLegoPfHdrSpace = 1026; +const uint16_t kLegoPfZeroSpace = 263; +const uint16_t kLegoPfOneSpace = 553; +const uint32_t kLegoPfMinCommandLength = 16000; // 16ms + + +#if SEND_LEGOPF +// Send a LEGO Power Functions message. +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kLegoPfBits. +// repeat: Nr. of additional times the message is to be sent. +// Note: Non-zero repeats results in at least 5 messages per spec. +// +// Status: Beta / Should work. +void IRsend::sendLegoPf(const uint64_t data, const uint16_t nbits, + const uint16_t repeat) { + uint8_t channelid = ((data >> (nbits - 4)) & 0b11) + 1; + if (repeat) { + // We are in repeat mode. + // Spec says a pause before transmittion. + if (channelid < 4) space((4 - channelid) * kLegoPfMinCommandLength); + // Spec says there are a minimum of 5 message repeats. + for (uint16_t r = 0; r < std::max(repeat, (uint16_t)5); r++) { + // Lego has a special repeat mode which repeats a message with varying + // start to start times. + sendGeneric(kLegoPfBitMark, kLegoPfHdrSpace, + kLegoPfBitMark, kLegoPfOneSpace, + kLegoPfBitMark, kLegoPfZeroSpace, + kLegoPfBitMark, kLegoPfHdrSpace, + ((r < 2) ? 5 : (6 + 2 * channelid)) * kLegoPfMinCommandLength, + data, nbits, 38000, true, 0, kDutyDefault); + } + } else { // No repeat, just a simple message. + sendGeneric(kLegoPfBitMark, kLegoPfHdrSpace, + kLegoPfBitMark, kLegoPfOneSpace, + kLegoPfBitMark, kLegoPfZeroSpace, + kLegoPfBitMark, kLegoPfHdrSpace, + kLegoPfMinCommandLength * 5, + data, nbits, 38000, true, 0, kDutyDefault); + } +} +#endif // SEND_LEGO + +#if DECODE_LEGOPF +// Decode the supplied LEGO Power Functions message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kLegoPfBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Alpha / Untested. +bool IRrecv::decodeLegoPf(decode_results* results, + const uint16_t nbits, const bool strict) { + // Check if can possibly be a valid LEGO message. + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false; + if (strict && nbits != kLegoPfBits) return false; // Not what is expected + + uint64_t data = 0; + uint16_t offset = kStartOffset; + match_result_t data_result; + + // Header + if (!matchMark(results->rawbuf[offset++], kLegoPfBitMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kLegoPfHdrSpace)) return false; + // Data (Typically 16 bits) + data_result = + matchData(&(results->rawbuf[offset]), nbits, + kLegoPfBitMark, kLegoPfOneSpace, + kLegoPfBitMark, kLegoPfZeroSpace, + kTolerance, kMarkExcess, true); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + uint16_t actualBits = data_result.used / 2; + + // Footer. + if (!matchMark(results->rawbuf[offset++], kLegoPfBitMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kLegoPfMinCommandLength)) + return false; + + // Compliance + if (actualBits < nbits) return false; + if (strict) { + if (actualBits != nbits) return false; // Not as we expected. + // Verify the Longitudinal Redundancy Check (LRC) + uint16_t lrc_data = data; + uint8_t lrc = 0xF; + for (uint8_t i = 0; i < 4; i++) { + lrc ^= (lrc_data & 0xF); + lrc_data >>= 4; + } + if (lrc) return false; + } + + // Success + results->decode_type = LEGOPF; + results->bits = actualBits; + results->value = data; + results->address = ((data >> (nbits - 4)) & 0b11) + 1; // Channel Id + results->command = (data >> 4) & 0xFF; // Stuff between Channel Id and LRC. + return true; +} +#endif // DECODE_LEGOPF diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Lutron.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Lutron.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Lutron.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Lutron.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_MWM.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_MWM.cpp index a75e99e3a..61eac49e2 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_MWM.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_MWM.cpp @@ -105,7 +105,7 @@ bool IRrecv::decodeMWM(decode_results *results, uint16_t nbits, bool strict) { for (; offset < results->rawlen && results->bits < 8 * kStateSizeMax; frame_bits++) { DPRINT("DEBUG: decodeMWM: offset = "); - DPRINTLN(uint64ToString(offset)); + DPRINTLN(offset); int16_t level = getRClevel(results, &offset, &used, kMWMTick, kMWMTolerance, kMWMExcess, kMWMDelta, kMWMMaxWidth); if (level < 0) { @@ -129,7 +129,7 @@ bool IRrecv::decodeMWM(decode_results *results, uint16_t nbits, bool strict) { DPRINT("DEBUG: decodeMWM: data_bits = "); DPRINTLN(data_bits); DPRINT("DEBUG: decodeMWM: Finished byte: "); - DPRINTLN(data); + DPRINTLN(uint64ToString(data)); results->state[data_bits / 8 - 1] = data & 0xFF; results->bits = data_bits; data = 0; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Magiquest.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Magiquest.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.h b/lib/IRremoteESP8266-2.6.0/src/ir_Magiquest.h similarity index 86% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Magiquest.h index d2d82d152..81fff53ad 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Magiquest.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Magiquest.h @@ -31,5 +31,5 @@ const uint16_t kMagiQuestMarkZero = 280; const uint16_t kMagiQuestSpaceZero = 850; const uint16_t kMagiQuestMarkOne = 580; const uint16_t kMagiQuestSpaceOne = 600; -const uint32_t kMagiQuestGap = 100000; // A guess of the gap between messages -#endif // IR_MAGIQUEST_H_ +const uint32_t kMagiQuestGap = kDefaultMessageGap; // Just a guess. +#endif // IR_MAGIQUEST_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Midea.cpp similarity index 87% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Midea.cpp index 8e55c7d22..8d5d9494f 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Midea.cpp @@ -104,9 +104,9 @@ void IRMideaAC::begin() { _irsend.begin(); } #if SEND_MIDEA // Send the current desired state to the IR LED. -void IRMideaAC::send() { +void IRMideaAC::send(const uint16_t repeat) { checksum(); // Ensure correct checksum before sending. - _irsend.sendMidea(remote_state); + _irsend.sendMidea(remote_state, kMideaBits, repeat); } #endif // SEND_MIDEA @@ -257,6 +257,39 @@ void IRMideaAC::checksum() { remote_state |= calcChecksum(remote_state); } + +// Convert a standard A/C mode into its native mode. +uint8_t IRMideaAC::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kMideaACCool; + case stdAc::opmode_t::kHeat: + return kMideaACHeat; + case stdAc::opmode_t::kDry: + return kMideaACDry; + case stdAc::opmode_t::kFan: + return kMideaACFan; + default: + return kMideaACAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRMideaAC::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kMideaACFanLow; + case stdAc::fanspeed_t::kMedium: + return kMideaACFanMed; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kMideaACFanHigh; + default: + return kMideaACFanAuto; + } +} + // Convert the internal state into a human readable string. #ifdef ARDUINO String IRMideaAC::toString() { @@ -265,53 +298,57 @@ String IRMideaAC::toString() { std::string IRMideaAC::toString() { std::string result = ""; #endif // ARDUINO - result += "Power: "; + result += F("Power: "); if (getPower()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Mode: " + uint64ToString(getMode()); + result += F("Off"); + result += F(", Mode: "); + result += uint64ToString(getMode()); switch (getMode()) { case kMideaACAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kMideaACCool: - result += " (COOL)"; + result += F(" (COOL)"); break; case kMideaACHeat: - result += " (HEAT)"; + result += F(" (HEAT)"); break; case kMideaACDry: - result += " (DRY)"; + result += F(" (DRY)"); break; case kMideaACFan: - result += " (FAN)"; + result += F(" (FAN)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - result += ", Temp: " + uint64ToString(getTemp(true)) + "C/" + - uint64ToString(getTemp(false)) + "F"; - result += ", Fan: " + uint64ToString(getFan()); + result += F(", Temp: "); + result += uint64ToString(getTemp(true)); + result += F("C/"); + result += uint64ToString(getTemp(false)); + result += F("F, Fan: "); + result += uint64ToString(getFan()); switch (getFan()) { case kMideaACFanAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kMideaACFanLow: - result += " (LOW)"; + result += F(" (LOW)"); break; case kMideaACFanMed: - result += " (MED)"; + result += F(" (MED)"); break; case kMideaACFanHigh: - result += " (HI)"; + result += F(" (HI)"); break; } - result += ", Sleep: "; + result += F(", Sleep: "); if (getSleep()) - result += "On"; + result += F("On"); else - result += "Off"; + result += F("Off"); return result; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h b/lib/IRremoteESP8266-2.6.0/src/ir_Midea.h similarity index 93% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Midea.h index aa9f94a92..ab14eb252 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Midea.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Midea.h @@ -11,6 +11,9 @@ #endif #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif // MM MM IIIII DDDDD EEEEEEE AAA // MMM MMM III DD DD EE AAAAA @@ -67,7 +70,7 @@ class IRMideaAC { void stateReset(); #if SEND_MIDEA - void send(); + void send(const uint16_t repeat = kMideaMinRepeat); #endif // SEND_MIDEA void begin(); void on(); @@ -85,6 +88,8 @@ class IRMideaAC { static bool validChecksum(const uint64_t state); void setSleep(const bool state); bool getSleep(); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); #ifdef ARDUINO String toString(); #else @@ -93,11 +98,13 @@ class IRMideaAC { #ifndef UNIT_TEST private: + IRsend _irsend; +#else + IRsendTest _irsend; #endif uint64_t remote_state; void checksum(); static uint8_t calcChecksum(const uint64_t state); - IRsend _irsend; }; #endif // IR_MIDEA_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Mitsubishi.cpp similarity index 90% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Mitsubishi.cpp index b092c27b9..ca9bef5d9 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Mitsubishi.cpp @@ -165,7 +165,7 @@ bool IRrecv::decodeMitsubishi(decode_results *results, uint16_t nbits, // This protocol appears to have a manditory in-protocol repeat. // That is in *addition* to the entire message needing to be sent twice // for the device to accept the command. That is separate from the repeat. -// i.e. Allegedly, the real remote requires the "OFF" button pressed twice. +// i.e. Allegedly, the real remote requires the "Off" button pressed twice. // You will need to add a suitable gap yourself. // Ref: // https://github.com/markszabo/IRremoteESP8266/issues/441 @@ -453,9 +453,9 @@ void IRMitsubishiAC::begin() { _irsend.begin(); } #if SEND_MITSUBISHI_AC // Send the current desired state to the IR LED. -void IRMitsubishiAC::send() { +void IRMitsubishiAC::send(const uint16_t repeat) { checksum(); // Ensure correct checksum before sending. - _irsend.sendMitsubishiAC(remote_state); + _irsend.sendMitsubishiAC(remote_state, kMitsubishiACStateLength, repeat); } #endif // SEND_MITSUBISHI_AC @@ -615,6 +615,52 @@ void IRMitsubishiAC::setTimer(uint8_t timer) { remote_state[13] = timer & 0b111; } +// Convert a standard A/C mode into its native mode. +uint8_t IRMitsubishiAC::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kMitsubishiAcCool; + case stdAc::opmode_t::kHeat: + return kMitsubishiAcHeat; + case stdAc::opmode_t::kDry: + return kMitsubishiAcDry; + default: + return kMitsubishiAcAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRMitsubishiAC::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + return kMitsubishiAcFanSilent; + case stdAc::fanspeed_t::kLow: + return kMitsubishiAcFanRealMax - 3; + case stdAc::fanspeed_t::kMedium: + return kMitsubishiAcFanRealMax - 2; + case stdAc::fanspeed_t::kHigh: + return kMitsubishiAcFanRealMax - 1; + case stdAc::fanspeed_t::kMax: + return kMitsubishiAcFanRealMax; + default: + return kMitsubishiAcFanAuto; + } +} + +// Convert a standard A/C vertical swing into its native setting. +uint8_t IRMitsubishiAC::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kHighest: + case stdAc::swingv_t::kHigh: + case stdAc::swingv_t::kMiddle: + case stdAc::swingv_t::kLow: + case stdAc::swingv_t::kLowest: + return kMitsubishiAcVaneAutoMove; + default: + return kMitsubishiAcVaneAuto; + } +} + #ifdef ARDUINO String IRMitsubishiAC::timeToString(uint64_t time) { String result = ""; @@ -622,10 +668,10 @@ String IRMitsubishiAC::timeToString(uint64_t time) { std::string IRMitsubishiAC::timeToString(uint64_t time) { std::string result = ""; #endif // ARDUINO - if (time / 6 < 10) result += "0"; + if (time / 6 < 10) result += '0'; result += uint64ToString(time / 6); - result += ":"; - if (time * 10 % 60 < 10) result += "0"; + result += ':'; + if (time * 10 % 60 < 10) result += '0'; result += uint64ToString(time * 10 % 60); return result; } @@ -638,77 +684,78 @@ String IRMitsubishiAC::toString() { std::string IRMitsubishiAC::toString() { std::string result = ""; #endif // ARDUINO - result += "Power: "; + result += F("Power: "); if (getPower()) - result += "On"; + result += F("On"); else - result += "Off"; + result += F("Off"); switch (getMode()) { case MITSUBISHI_AC_AUTO: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case MITSUBISHI_AC_COOL: - result += " (COOL)"; + result += F(" (COOL)"); break; case MITSUBISHI_AC_DRY: - result += " (DRY)"; + result += F(" (DRY)"); break; case MITSUBISHI_AC_HEAT: - result += " (HEAT)"; + result += F(" (HEAT)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - result += ", Temp: " + uint64ToString(getTemp()) + "C"; - result += ", FAN: "; + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, FAN: "); switch (getFan()) { case MITSUBISHI_AC_FAN_AUTO: - result += "AUTO"; + result += F("AUTO"); break; case MITSUBISHI_AC_FAN_MAX: - result += "MAX"; + result += F("MAX"); break; case MITSUBISHI_AC_FAN_SILENT: - result += "SILENT"; + result += F("SILENT"); break; default: result += uint64ToString(getFan()); } - result += ", VANE: "; + result += F(", VANE: "); switch (getVane()) { case MITSUBISHI_AC_VANE_AUTO: - result += "AUTO"; + result += F("AUTO"); break; case MITSUBISHI_AC_VANE_AUTO_MOVE: - result += "AUTO MOVE"; + result += F("AUTO MOVE"); break; default: result += uint64ToString(getVane()); } - result += ", Time: "; + result += F(", Time: "); result += timeToString(getClock()); - result += ", On timer: "; + result += F(", On timer: "); result += timeToString(getStartClock()); - result += ", Off timer: "; + result += F(", Off timer: "); result += timeToString(getStopClock()); - result += ", Timer: "; + result += F(", Timer: "); switch (getTimer()) { case kMitsubishiAcNoTimer: - result += "-"; + result += '-'; break; case kMitsubishiAcStartTimer: - result += "Start"; + result += F("Start"); break; case kMitsubishiAcStopTimer: - result += "Stop"; + result += F("Stop"); break; case kMitsubishiAcStartStopTimer: - result += "Start+Stop"; + result += F("Start+Stop"); break; default: - result += "? ("; + result += F("? ("); result += getTimer(); - result += ")\n"; + result += F(")\n"); } return result; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.h b/lib/IRremoteESP8266-2.6.0/src/ir_Mitsubishi.h similarity index 91% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Mitsubishi.h index 7b03efce6..c8dca5dbc 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Mitsubishi.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Mitsubishi.h @@ -12,6 +12,9 @@ #endif #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif // MMMMM IIIII TTTTT SSSS U U BBBB IIIII SSSS H H IIIII // M M M I T S U U B B I S H H I @@ -64,7 +67,7 @@ class IRMitsubishiAC { void stateReset(); #if SEND_MITSUBISHI_AC - void send(); + void send(const uint16_t repeat = kMitsubishiACMinRepeat); #endif // SEND_MITSUBISHI_AC void begin(); void on(); @@ -89,13 +92,21 @@ class IRMitsubishiAC { void setStopClock(uint8_t clock); uint8_t getTimer(); void setTimer(uint8_t timer); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); + uint8_t convertSwingV(const stdAc::swingv_t position); #ifdef ARDUINO String toString(); #else std::string toString(); #endif +#ifndef UNIT_TEST private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif #ifdef ARDUINO String timeToString(uint64_t time); #else @@ -103,7 +114,6 @@ class IRMitsubishiAC { #endif uint8_t remote_state[kMitsubishiACStateLength]; void checksum(); - IRsend _irsend; }; #endif // IR_MITSUBISHI_H_ diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.cpp new file mode 100644 index 000000000..9048124d4 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.cpp @@ -0,0 +1,1014 @@ +// Copyright 2019 David Conran +// Mitsubishi Heavy Industries A/C remote emulation. + +// Code to emulate Mitsubishi Heavy Industries A/C IR remote control units, +// which should control at least the following A/C units: +// Remote Control RLA502A700B: +// Model SRKxxZM-S +// Model SRKxxZMXA-S +// Remote Control RKX502A001C: +// Model SRKxxZJ-S + +// Note: This code was *heavily* influenced by @ToniA's great work & code, +// but it has been written from scratch. +// Nothing was copied other than constants and message analysis. + +#include "ir_MitsubishiHeavy.h" +#include +#include "IRremoteESP8266.h" +#include "IRutils.h" +#ifndef ARDUINO +#include +#endif + +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/660 +// https://github.com/ToniA/Raw-IR-decoder-for-Arduino/blob/master/MitsubishiHeavy.cpp +// https://github.com/ToniA/arduino-heatpumpir/blob/master/MitsubishiHeavyHeatpumpIR.cpp + +// Constants +const uint16_t kMitsubishiHeavyHdrMark = 3140; +const uint16_t kMitsubishiHeavyHdrSpace = 1630; +const uint16_t kMitsubishiHeavyBitMark = 370; +const uint16_t kMitsubishiHeavyOneSpace = 420; +const uint16_t kMitsubishiHeavyZeroSpace = 1220; +const uint32_t kMitsubishiHeavyGap = kDefaultMessageGap; // Just a guess. + +#if SEND_MITSUBISHIHEAVY +// Send a MitsubishiHeavy 88 bit A/C message. +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kMitsubishiHeavy88Bits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: BETA / Appears to be working. Needs testing against a real device. +void IRsend::sendMitsubishiHeavy88(const unsigned char data[], + const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes < kMitsubishiHeavy88StateLength) + return; // Not enough bytes to send a proper message. + sendGeneric(kMitsubishiHeavyHdrMark, kMitsubishiHeavyHdrSpace, + kMitsubishiHeavyBitMark, kMitsubishiHeavyOneSpace, + kMitsubishiHeavyBitMark, kMitsubishiHeavyZeroSpace, + kMitsubishiHeavyBitMark, kMitsubishiHeavyGap, + data, nbytes, 38000, false, repeat, kDutyDefault); +} + +// Send a MitsubishiHeavy 152 bit A/C message. +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kMitsubishiHeavy152Bits. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: BETA / Appears to be working. Needs testing against a real device. +void IRsend::sendMitsubishiHeavy152(const unsigned char data[], + const uint16_t nbytes, + const uint16_t repeat) { + if (nbytes < kMitsubishiHeavy152StateLength) + return; // Not enough bytes to send a proper message. + sendMitsubishiHeavy88(data, nbytes, repeat); +} +#endif // SEND_MITSUBISHIHEAVY + +// Class for decoding and constructing MitsubishiHeavy152 AC messages. +IRMitsubishiHeavy152Ac::IRMitsubishiHeavy152Ac( + const uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRMitsubishiHeavy152Ac::begin() { _irsend.begin(); } + +#if SEND_MITSUBISHIHEAVY +void IRMitsubishiHeavy152Ac::send(const uint16_t repeat) { + _irsend.sendMitsubishiHeavy152(this->getRaw(), kMitsubishiHeavy152StateLength, + repeat); +} +#endif // SEND_MITSUBISHIHEAVY + +void IRMitsubishiHeavy152Ac::stateReset(void) { + uint8_t i = 0; + for (; i < kMitsubishiHeavySigLength; i++) + remote_state[i] = kMitsubishiHeavyZmsSig[i]; + for (; i < kMitsubishiHeavy152StateLength - 3; i += 2) remote_state[i] = 0; + remote_state[17] = 0x80; +} + +uint8_t *IRMitsubishiHeavy152Ac::getRaw(void) { + checksum(); + return remote_state; +} + +void IRMitsubishiHeavy152Ac::setRaw(const uint8_t *data) { + for (uint8_t i = 0; i < kMitsubishiHeavy152StateLength; i++) + remote_state[i] = data[i]; +} + +void IRMitsubishiHeavy152Ac::on(void) { + remote_state[5] |= kMitsubishiHeavyPowerBit; +} + +void IRMitsubishiHeavy152Ac::off(void) { + remote_state[5] &= ~kMitsubishiHeavyPowerBit; +} + +void IRMitsubishiHeavy152Ac::setPower(const bool on) { + if (on) + this->on(); + else + this->off(); +} + +bool IRMitsubishiHeavy152Ac::getPower(void) { + return remote_state[5] & kMitsubishiHeavyPowerBit; +} + +void IRMitsubishiHeavy152Ac::setTemp(const uint8_t temp) { + uint8_t newtemp = temp; + newtemp = std::min(newtemp, kMitsubishiHeavyMaxTemp); + newtemp = std::max(newtemp, kMitsubishiHeavyMinTemp); + + remote_state[7] &= ~kMitsubishiHeavyTempMask; + remote_state[7] |= newtemp - kMitsubishiHeavyMinTemp; +} + +uint8_t IRMitsubishiHeavy152Ac::getTemp(void) { + return (remote_state[7] & kMitsubishiHeavyTempMask) + kMitsubishiHeavyMinTemp; +} + +// Set the speed of the fan +void IRMitsubishiHeavy152Ac::setFan(const uint8_t speed) { + uint8_t newspeed = speed; + switch (speed) { + case kMitsubishiHeavy152FanLow: + case kMitsubishiHeavy152FanMed: + case kMitsubishiHeavy152FanHigh: + case kMitsubishiHeavy152FanMax: + case kMitsubishiHeavy152FanEcono: + case kMitsubishiHeavy152FanTurbo: + break; + default: + newspeed = kMitsubishiHeavy152FanAuto; + } + remote_state[9] &= ~kMitsubishiHeavyFanMask; + remote_state[9] |= newspeed; +} + +uint8_t IRMitsubishiHeavy152Ac::getFan(void) { + return remote_state[9] & kMitsubishiHeavyFanMask; +} + +void IRMitsubishiHeavy152Ac::setMode(const uint8_t mode) { + uint8_t newmode = mode; + switch (mode) { + case kMitsubishiHeavyCool: + case kMitsubishiHeavyDry: + case kMitsubishiHeavyFan: + case kMitsubishiHeavyHeat: + break; + default: + newmode = kMitsubishiHeavyAuto; + } + remote_state[5] &= ~kMitsubishiHeavyModeMask; + remote_state[5] |= newmode; +} + +uint8_t IRMitsubishiHeavy152Ac::getMode(void) { + return remote_state[5] & kMitsubishiHeavyModeMask; +} + +void IRMitsubishiHeavy152Ac::setSwingVertical(const uint8_t pos) { + uint8_t newpos = std::min(pos, kMitsubishiHeavy152SwingVOff); + remote_state[11] &= ~kMitsubishiHeavy152SwingVMask; + remote_state[11] |= (newpos << 5); +} + +uint8_t IRMitsubishiHeavy152Ac::getSwingVertical(void) { + return remote_state[11] >> 5; +} + +void IRMitsubishiHeavy152Ac::setSwingHorizontal(const uint8_t pos) { + uint8_t newpos = std::min(pos, kMitsubishiHeavy152SwingHOff); + remote_state[13] &= ~kMitsubishiHeavy152SwingHMask; + remote_state[13] |= (newpos & kMitsubishiHeavy152SwingHMask); +} + +uint8_t IRMitsubishiHeavy152Ac::getSwingHorizontal(void) { + return remote_state[13] & kMitsubishiHeavy152SwingHMask; +} + +void IRMitsubishiHeavy152Ac::setNight(const bool on) { + if (on) + remote_state[15] |= kMitsubishiHeavyNightBit; + else + remote_state[15] &= ~kMitsubishiHeavyNightBit; +} + +bool IRMitsubishiHeavy152Ac::getNight(void) { + return remote_state[15] & kMitsubishiHeavyNightBit; +} + +void IRMitsubishiHeavy152Ac::set3D(const bool on) { + if (on) + remote_state[11] |= kMitsubishiHeavy3DMask; + else + remote_state[11] &= ~kMitsubishiHeavy3DMask; +} + +bool IRMitsubishiHeavy152Ac::get3D(void) { + return (remote_state[11] & kMitsubishiHeavy3DMask) == kMitsubishiHeavy3DMask; +} + +void IRMitsubishiHeavy152Ac::setSilent(const bool on) { + if (on) + remote_state[15] |= kMitsubishiHeavySilentBit; + else + remote_state[15] &= ~kMitsubishiHeavySilentBit; +} + +bool IRMitsubishiHeavy152Ac::getSilent(void) { + return remote_state[15] & kMitsubishiHeavySilentBit; +} + +void IRMitsubishiHeavy152Ac::setFilter(const bool on) { + if (on) + remote_state[5] |= kMitsubishiHeavyFilterBit; + else + remote_state[5] &= ~kMitsubishiHeavyFilterBit; +} + +bool IRMitsubishiHeavy152Ac::getFilter(void) { + return remote_state[5] & kMitsubishiHeavyFilterBit; +} + +void IRMitsubishiHeavy152Ac::setClean(const bool on) { + this->setFilter(on); + if (on) + remote_state[5] |= kMitsubishiHeavyCleanBit; + else + remote_state[5] &= ~kMitsubishiHeavyCleanBit; +} + +bool IRMitsubishiHeavy152Ac::getClean(void) { + return remote_state[5] & kMitsubishiHeavyCleanBit && this->getFilter(); +} + +void IRMitsubishiHeavy152Ac::setTurbo(const bool on) { + if (on) + this->setFan(kMitsubishiHeavy152FanTurbo); + else if (this->getTurbo()) this->setFan(kMitsubishiHeavy152FanAuto); +} + +bool IRMitsubishiHeavy152Ac::getTurbo(void) { + return this->getFan() == kMitsubishiHeavy152FanTurbo; +} + +void IRMitsubishiHeavy152Ac::setEcono(const bool on) { + if (on) + this->setFan(kMitsubishiHeavy152FanEcono); + else if (this->getEcono()) this->setFan(kMitsubishiHeavy152FanAuto); +} + +bool IRMitsubishiHeavy152Ac::getEcono(void) { + return this->getFan() == kMitsubishiHeavy152FanEcono; +} + +// Verify the given state has a ZM-S signature. +bool IRMitsubishiHeavy152Ac::checkZmsSig(const uint8_t *state) { + for (uint8_t i = 0; i < kMitsubishiHeavySigLength; i++) + if (state[i] != kMitsubishiHeavyZmsSig[i]) return false; + return true; +} + +// Protocol technically has no checksum, but does has inverted byte pairs. +void IRMitsubishiHeavy152Ac::checksum(void) { + for (uint8_t i = kMitsubishiHeavySigLength - 2; + i < kMitsubishiHeavy152StateLength; + i += 2) { + remote_state[i + 1] = ~remote_state[i]; + } +} + +// Protocol technically has no checksum, but does has inverted byte pairs. +bool IRMitsubishiHeavy152Ac::validChecksum(const uint8_t *state, + const uint16_t length) { + // Assume anything too short is fine. + if (length < kMitsubishiHeavySigLength) return true; + // Check all the byte pairs. + for (uint16_t i = kMitsubishiHeavySigLength - 2; + i < length; + i += 2) { + // XOR of a byte and it's self inverted should be 0xFF; + if ((state[i] ^ state[i + 1]) != 0xFF) return false; + } + return true; +} + + +// Convert a standard A/C mode into its native mode. +uint8_t IRMitsubishiHeavy152Ac::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kMitsubishiHeavyCool; + case stdAc::opmode_t::kHeat: + return kMitsubishiHeavyHeat; + case stdAc::opmode_t::kDry: + return kMitsubishiHeavyDry; + case stdAc::opmode_t::kFan: + return kMitsubishiHeavyFan; + default: + return kMitsubishiHeavyAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRMitsubishiHeavy152Ac::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + return kMitsubishiHeavy152FanEcono; // Assumes Econo is slower than Low. + case stdAc::fanspeed_t::kLow: + return kMitsubishiHeavy152FanLow; + case stdAc::fanspeed_t::kMedium: + return kMitsubishiHeavy152FanMed; + case stdAc::fanspeed_t::kHigh: + return kMitsubishiHeavy152FanHigh; + case stdAc::fanspeed_t::kMax: + return kMitsubishiHeavy152FanMax; + default: + return kMitsubishiHeavy152FanAuto; + } +} + +// Convert a standard A/C vertical swing into its native setting. +uint8_t IRMitsubishiHeavy152Ac::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kAuto: + return kMitsubishiHeavy152SwingVAuto; + case stdAc::swingv_t::kHighest: + return kMitsubishiHeavy152SwingVHighest; + case stdAc::swingv_t::kHigh: + return kMitsubishiHeavy152SwingVHigh; + case stdAc::swingv_t::kMiddle: + return kMitsubishiHeavy152SwingVMiddle; + case stdAc::swingv_t::kLow: + return kMitsubishiHeavy152SwingVLow; + case stdAc::swingv_t::kLowest: + return kMitsubishiHeavy152SwingVLowest; + default: + return kMitsubishiHeavy152SwingVOff; + } +} + +// Convert a standard A/C horizontal swing into its native setting. +uint8_t IRMitsubishiHeavy152Ac::convertSwingH(const stdAc::swingh_t position) { + switch (position) { + case stdAc::swingh_t::kAuto: + return kMitsubishiHeavy152SwingHAuto; + case stdAc::swingh_t::kLeftMax: + return kMitsubishiHeavy152SwingHLeftMax; + case stdAc::swingh_t::kLeft: + return kMitsubishiHeavy152SwingHLeft; + case stdAc::swingh_t::kMiddle: + return kMitsubishiHeavy152SwingHMiddle; + case stdAc::swingh_t::kRight: + return kMitsubishiHeavy152SwingHRight; + case stdAc::swingh_t::kRightMax: + return kMitsubishiHeavy152SwingHRightMax; + default: + return kMitsubishiHeavy152SwingHOff; + } +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRMitsubishiHeavy152Ac::toString(void) { + String result = ""; +#else +std::string IRMitsubishiHeavy152Ac::toString(void) { + std::string result = ""; +#endif // ARDUINO + result += F("Power: "); + result += (this->getPower() ? F("On") : F("Off")); + result += F(", Mode: "); + result += uint64ToString(this->getMode()); + switch (this->getMode()) { + case kMitsubishiHeavyAuto: + result += F(" (Auto)"); + break; + case kMitsubishiHeavyCool: + result += F(" (Cool)"); + break; + case kMitsubishiHeavyHeat: + result += F(" (Heat)"); + break; + case kMitsubishiHeavyDry: + result += F(" (Dry)"); + break; + case kMitsubishiHeavyFan: + result += F(" (Fan)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Temp: "); + result += uint64ToString(this->getTemp()) + 'C'; + result += F(", Fan: "); + result += uint64ToString(this->getFan()); + switch (this->getFan()) { + case kMitsubishiHeavy152FanAuto: + result += F(" (Auto)"); + break; + case kMitsubishiHeavy152FanHigh: + result += F(" (High)"); + break; + case kMitsubishiHeavy152FanLow: + result += F(" (Low)"); + break; + case kMitsubishiHeavy152FanMed: + result += F(" (Med)"); + break; + case kMitsubishiHeavy152FanMax: + result += F(" (Max)"); + break; + case kMitsubishiHeavy152FanEcono: + result += F(" (Econo)"); + break; + case kMitsubishiHeavy152FanTurbo: + result += F(" (Turbo)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Swing (V): "); + result += uint64ToString(this->getSwingVertical()); + switch (this->getSwingVertical()) { + case kMitsubishiHeavy152SwingVAuto: + result += F(" (Auto)"); + break; + case kMitsubishiHeavy152SwingVHighest: + result += F(" (Highest)"); + break; + case kMitsubishiHeavy152SwingVHigh: + result += F(" (High)"); + break; + case kMitsubishiHeavy152SwingVMiddle: + result += F(" (Middle)"); + break; + case kMitsubishiHeavy152SwingVLow: + result += F(" (Low)"); + break; + case kMitsubishiHeavy152SwingVLowest: + result += F(" (Lowest)"); + break; + case kMitsubishiHeavy152SwingVOff: + result += F(" (Off)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Swing (H): "); + result += uint64ToString(this->getSwingHorizontal()); + switch (this->getSwingHorizontal()) { + case kMitsubishiHeavy152SwingHAuto: + result += F(" (Auto)"); + break; + case kMitsubishiHeavy152SwingHLeftMax: + result += F(" (Max Left)"); + break; + case kMitsubishiHeavy152SwingHLeft: + result += F(" (Left)"); + break; + case kMitsubishiHeavy152SwingHMiddle: + result += F(" (Middle)"); + break; + case kMitsubishiHeavy152SwingHRight: + result += F(" (Right)"); + break; + case kMitsubishiHeavy152SwingHRightMax: + result += F(" (Max Right)"); + break; + case kMitsubishiHeavy152SwingHLeftRight: + result += F(" (Left Right)"); + break; + case kMitsubishiHeavy152SwingHRightLeft: + result += F(" (Right Left)"); + break; + case kMitsubishiHeavy152SwingHOff: + result += F(" (Off)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Silent: "); + result += (this->getSilent() ? F("On") : F("Off")); + result += F(", Turbo: "); + result += (this->getTurbo() ? F("On") : F("Off")); + result += F(", Econo: "); + result += (this->getEcono() ? F("On") : F("Off")); + result += F(", Night: "); + result += (this->getNight() ? F("On") : F("Off")); + result += F(", Filter: "); + result += (this->getFilter() ? F("On") : F("Off")); + result += F(", 3D: "); + result += (this->get3D() ? F("On") : F("Off")); + result += F(", Clean: "); + result += (this->getClean() ? F("On") : F("Off")); + return result; +} + + +// Class for decoding and constructing MitsubishiHeavy88 AC messages. +IRMitsubishiHeavy88Ac::IRMitsubishiHeavy88Ac( + const uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRMitsubishiHeavy88Ac::begin() { _irsend.begin(); } + +#if SEND_MITSUBISHIHEAVY +void IRMitsubishiHeavy88Ac::send(const uint16_t repeat) { + _irsend.sendMitsubishiHeavy88(this->getRaw(), kMitsubishiHeavy88StateLength, + repeat); +} +#endif // SEND_MITSUBISHIHEAVY + +void IRMitsubishiHeavy88Ac::stateReset(void) { + uint8_t i = 0; + for (; i < kMitsubishiHeavySigLength; i++) + remote_state[i] = kMitsubishiHeavyZjsSig[i]; + for (; i < kMitsubishiHeavy88StateLength; i++) remote_state[i] = 0; +} + +uint8_t *IRMitsubishiHeavy88Ac::getRaw(void) { + checksum(); + return remote_state; +} + +void IRMitsubishiHeavy88Ac::setRaw(const uint8_t *data) { + for (uint8_t i = 0; i < kMitsubishiHeavy88StateLength; i++) + remote_state[i] = data[i]; +} + +void IRMitsubishiHeavy88Ac::on(void) { + remote_state[9] |= kMitsubishiHeavyPowerBit; +} + +void IRMitsubishiHeavy88Ac::off(void) { + remote_state[9] &= ~kMitsubishiHeavyPowerBit; +} + +void IRMitsubishiHeavy88Ac::setPower(const bool on) { + if (on) + this->on(); + else + this->off(); +} + +bool IRMitsubishiHeavy88Ac::getPower(void) { + return remote_state[9] & kMitsubishiHeavyPowerBit; +} + +void IRMitsubishiHeavy88Ac::setTemp(const uint8_t temp) { + uint8_t newtemp = temp; + newtemp = std::min(newtemp, kMitsubishiHeavyMaxTemp); + newtemp = std::max(newtemp, kMitsubishiHeavyMinTemp); + + remote_state[9] &= kMitsubishiHeavyTempMask; + remote_state[9] |= ((newtemp - kMitsubishiHeavyMinTemp) << 4); +} + +uint8_t IRMitsubishiHeavy88Ac::getTemp(void) { + return (remote_state[9] >> 4) + kMitsubishiHeavyMinTemp; +} + +// Set the speed of the fan +void IRMitsubishiHeavy88Ac::setFan(const uint8_t speed) { + uint8_t newspeed = speed; + switch (speed) { + case kMitsubishiHeavy88FanLow: + case kMitsubishiHeavy88FanMed: + case kMitsubishiHeavy88FanHigh: + case kMitsubishiHeavy88FanTurbo: + case kMitsubishiHeavy88FanEcono: + break; + default: + newspeed = kMitsubishiHeavy88FanAuto; + } + remote_state[7] &= ~kMitsubishiHeavy88FanMask; + remote_state[7] |= (newspeed << 5); +} + +uint8_t IRMitsubishiHeavy88Ac::getFan(void) { + return remote_state[7] >> 5; +} + +void IRMitsubishiHeavy88Ac::setMode(const uint8_t mode) { + uint8_t newmode = mode; + switch (mode) { + case kMitsubishiHeavyCool: + case kMitsubishiHeavyDry: + case kMitsubishiHeavyFan: + case kMitsubishiHeavyHeat: + break; + default: + newmode = kMitsubishiHeavyAuto; + } + remote_state[9] &= ~kMitsubishiHeavyModeMask; + remote_state[9] |= newmode; +} + +uint8_t IRMitsubishiHeavy88Ac::getMode(void) { + return remote_state[9] & kMitsubishiHeavyModeMask; +} + +void IRMitsubishiHeavy88Ac::setSwingVertical(const uint8_t pos) { + uint8_t newpos; + switch (pos) { + case kMitsubishiHeavy88SwingVAuto: + case kMitsubishiHeavy88SwingVHighest: + case kMitsubishiHeavy88SwingVHigh: + case kMitsubishiHeavy88SwingVMiddle: + case kMitsubishiHeavy88SwingVLow: + case kMitsubishiHeavy88SwingVLowest: + newpos = pos; + break; + default: + newpos = kMitsubishiHeavy88SwingVOff; + } + remote_state[5] &= ~kMitsubishiHeavy88SwingVMaskByte5; + remote_state[5] |= (newpos & kMitsubishiHeavy88SwingVMaskByte5); + remote_state[7] &= ~kMitsubishiHeavy88SwingVMaskByte7; + remote_state[7] |= (newpos & kMitsubishiHeavy88SwingVMaskByte7); +} + +uint8_t IRMitsubishiHeavy88Ac::getSwingVertical(void) { + return (remote_state[5] & kMitsubishiHeavy88SwingVMaskByte5) | + (remote_state[7] & kMitsubishiHeavy88SwingVMaskByte7); +} + +void IRMitsubishiHeavy88Ac::setSwingHorizontal(const uint8_t pos) { + uint8_t newpos; + switch (pos) { + case kMitsubishiHeavy88SwingHAuto: + case kMitsubishiHeavy88SwingHLeftMax: + case kMitsubishiHeavy88SwingHLeft: + case kMitsubishiHeavy88SwingHMiddle: + case kMitsubishiHeavy88SwingHRight: + case kMitsubishiHeavy88SwingHRightMax: + case kMitsubishiHeavy88SwingHLeftRight: + case kMitsubishiHeavy88SwingHRightLeft: + case kMitsubishiHeavy88SwingH3D: + newpos = pos; + break; + default: + newpos = kMitsubishiHeavy88SwingHOff; + } + remote_state[5] &= ~kMitsubishiHeavy88SwingHMask; + remote_state[5] |= newpos; +} + +uint8_t IRMitsubishiHeavy88Ac::getSwingHorizontal(void) { + return remote_state[5] & kMitsubishiHeavy88SwingHMask; +} + +void IRMitsubishiHeavy88Ac::setTurbo(const bool on) { + if (on) + this->setFan(kMitsubishiHeavy88FanTurbo); + else if (this->getTurbo()) this->setFan(kMitsubishiHeavy88FanAuto); +} + +bool IRMitsubishiHeavy88Ac::getTurbo(void) { + return this->getFan() == kMitsubishiHeavy88FanTurbo; +} + +void IRMitsubishiHeavy88Ac::setEcono(const bool on) { + if (on) + this->setFan(kMitsubishiHeavy88FanEcono); + else if (this->getEcono()) this->setFan(kMitsubishiHeavy88FanAuto); +} + +bool IRMitsubishiHeavy88Ac::getEcono(void) { + return this->getFan() == kMitsubishiHeavy88FanEcono; +} + +void IRMitsubishiHeavy88Ac::set3D(const bool on) { + if (on) + this->setSwingHorizontal(kMitsubishiHeavy88SwingH3D); + else if (this->get3D()) + this->setSwingHorizontal(kMitsubishiHeavy88SwingHOff); +} + +bool IRMitsubishiHeavy88Ac::get3D(void) { + return this->getSwingHorizontal() == kMitsubishiHeavy88SwingH3D; +} + +void IRMitsubishiHeavy88Ac::setClean(const bool on) { + if (on) + remote_state[5] |= kMitsubishiHeavy88CleanBit; + else + remote_state[5] &= ~kMitsubishiHeavy88CleanBit; +} + +bool IRMitsubishiHeavy88Ac::getClean(void) { + return remote_state[5] & kMitsubishiHeavy88CleanBit; +} + +// Verify the given state has a ZJ-S signature. +bool IRMitsubishiHeavy88Ac::checkZjsSig(const uint8_t *state) { + for (uint8_t i = 0; i < kMitsubishiHeavySigLength; i++) + if (state[i] != kMitsubishiHeavyZjsSig[i]) return false; + return true; +} + +// Protocol technically has no checksum, but does has inverted byte pairs. +void IRMitsubishiHeavy88Ac::checksum(void) { + for (uint8_t i = kMitsubishiHeavySigLength - 2; + i < kMitsubishiHeavy88StateLength; + i += 2) { + remote_state[i + 1] = ~remote_state[i]; + } +} + +// Protocol technically has no checksum, but does has inverted byte pairs. +bool IRMitsubishiHeavy88Ac::validChecksum(const uint8_t *state, + const uint16_t length) { + return IRMitsubishiHeavy152Ac::validChecksum(state, length); +} + +// Convert a standard A/C mode into its native mode. +uint8_t IRMitsubishiHeavy88Ac::convertMode(const stdAc::opmode_t mode) { + return IRMitsubishiHeavy152Ac::convertMode(mode); +} + + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRMitsubishiHeavy88Ac::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + return kMitsubishiHeavy88FanEcono; // Assumes Econo is slower than Low. + case stdAc::fanspeed_t::kLow: + return kMitsubishiHeavy88FanLow; + case stdAc::fanspeed_t::kMedium: + return kMitsubishiHeavy88FanMed; + case stdAc::fanspeed_t::kHigh: + return kMitsubishiHeavy88FanHigh; + case stdAc::fanspeed_t::kMax: + return kMitsubishiHeavy88FanTurbo; + default: + return kMitsubishiHeavy88FanAuto; + } +} + +// Convert a standard A/C vertical swing into its native setting. +uint8_t IRMitsubishiHeavy88Ac::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kAuto: + return kMitsubishiHeavy88SwingVAuto; + case stdAc::swingv_t::kHighest: + return kMitsubishiHeavy88SwingVHighest; + case stdAc::swingv_t::kHigh: + return kMitsubishiHeavy88SwingVHigh; + case stdAc::swingv_t::kMiddle: + return kMitsubishiHeavy88SwingVMiddle; + case stdAc::swingv_t::kLow: + return kMitsubishiHeavy88SwingVLow; + case stdAc::swingv_t::kLowest: + return kMitsubishiHeavy88SwingVLowest; + default: + return kMitsubishiHeavy88SwingVOff; + } +} + +// Convert a standard A/C horizontal swing into its native setting. +uint8_t IRMitsubishiHeavy88Ac::convertSwingH(const stdAc::swingh_t position) { + switch (position) { + case stdAc::swingh_t::kAuto: + return kMitsubishiHeavy88SwingHAuto; + case stdAc::swingh_t::kLeftMax: + return kMitsubishiHeavy88SwingHLeftMax; + case stdAc::swingh_t::kLeft: + return kMitsubishiHeavy88SwingHLeft; + case stdAc::swingh_t::kMiddle: + return kMitsubishiHeavy88SwingHMiddle; + case stdAc::swingh_t::kRight: + return kMitsubishiHeavy88SwingHRight; + case stdAc::swingh_t::kRightMax: + return kMitsubishiHeavy88SwingHRightMax; + default: + return kMitsubishiHeavy88SwingHOff; + } +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRMitsubishiHeavy88Ac::toString(void) { + String result = ""; +#else +std::string IRMitsubishiHeavy88Ac::toString(void) { + std::string result = ""; +#endif // ARDUINO + result += F("Power: "); + result += (this->getPower() ? F("On") : F("Off")); + result += F(", Mode: "); + result += uint64ToString(this->getMode()); + switch (this->getMode()) { + case kMitsubishiHeavyAuto: + result += F(" (Auto)"); + break; + case kMitsubishiHeavyCool: + result += F(" (Cool)"); + break; + case kMitsubishiHeavyHeat: + result += F(" (Heat)"); + break; + case kMitsubishiHeavyDry: + result += F(" (Dry)"); + break; + case kMitsubishiHeavyFan: + result += F(" (Fan)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Temp: "); + result += uint64ToString(this->getTemp()) + 'C'; + result += F(", Fan: "); + result += uint64ToString(this->getFan()); + switch (this->getFan()) { + case kMitsubishiHeavy88FanAuto: + result += F(" (Auto)"); + break; + case kMitsubishiHeavy88FanHigh: + result += F(" (High)"); + break; + case kMitsubishiHeavy88FanLow: + result += F(" (Low)"); + break; + case kMitsubishiHeavy88FanMed: + result += F(" (Med)"); + break; + case kMitsubishiHeavy88FanEcono: + result += F(" (Econo)"); + break; + case kMitsubishiHeavy88FanTurbo: + result += F(" (Turbo)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Swing (V): "); + result += uint64ToString(this->getSwingVertical()); + switch (this->getSwingVertical()) { + case kMitsubishiHeavy88SwingVAuto: + result += F(" (Auto)"); + break; + case kMitsubishiHeavy88SwingVHighest: + result += F(" (Highest)"); + break; + case kMitsubishiHeavy88SwingVHigh: + result += F(" (High)"); + break; + case kMitsubishiHeavy88SwingVMiddle: + result += F(" (Middle)"); + break; + case kMitsubishiHeavy88SwingVLow: + result += F(" (Low)"); + break; + case kMitsubishiHeavy88SwingVLowest: + result += F(" (Lowest)"); + break; + case kMitsubishiHeavy88SwingVOff: + result += F(" (Off)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Swing (H): "); + result += uint64ToString(this->getSwingHorizontal()); + switch (this->getSwingHorizontal()) { + case kMitsubishiHeavy88SwingHAuto: + result += F(" (Auto)"); + break; + case kMitsubishiHeavy88SwingHLeftMax: + result += F(" (Max Left)"); + break; + case kMitsubishiHeavy88SwingHLeft: + result += F(" (Left)"); + break; + case kMitsubishiHeavy88SwingHMiddle: + result += F(" (Middle)"); + break; + case kMitsubishiHeavy88SwingHRight: + result += F(" (Right)"); + break; + case kMitsubishiHeavy88SwingHRightMax: + result += F(" (Max Right)"); + break; + case kMitsubishiHeavy88SwingHLeftRight: + result += F(" (Left Right)"); + break; + case kMitsubishiHeavy88SwingHRightLeft: + result += F(" (Right Left)"); + break; + case kMitsubishiHeavy88SwingH3D: + result += F(" (3D)"); + break; + case kMitsubishiHeavy88SwingHOff: + result += F(" (Off)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Turbo: "); + result += (this->getTurbo() ? F("On") : F("Off")); + result += F(", Econo: "); + result += (this->getEcono() ? F("On") : F("Off")); + result += F(", 3D: "); + result += (this->get3D() ? F("On") : F("Off")); + result += F(", Clean: "); + result += (this->getClean() ? F("On") : F("Off")); + return result; +} + +#if DECODE_MITSUBISHIHEAVY +// Decode the supplied MitsubishiHeavy message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. +// Typically kMitsubishiHeavy88Bits or kMitsubishiHeavy152Bits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Appears to be working. Needs testing against a real device. +bool IRrecv::decodeMitsubishiHeavy(decode_results* results, + const uint16_t nbits, const bool strict) { + // Check if can possibly be a valid MitsubishiHeavy message. + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false; + if (strict) { + switch (nbits) { + case kMitsubishiHeavy88Bits: + case kMitsubishiHeavy152Bits: + break; + default: + return false; // Not what is expected + } + } + + uint16_t actualBits = 0; + uint16_t offset = kStartOffset; + match_result_t data_result; + + // Header + if (!matchMark(results->rawbuf[offset++], kMitsubishiHeavyHdrMark)) + return false; + if (!matchSpace(results->rawbuf[offset++], kMitsubishiHeavyHdrSpace)) + return false; + // Data + // Keep reading bytes until we either run out of section or state to fill. + for (uint16_t i = 0; + offset <= results->rawlen - 16 && actualBits < nbits; + i++, actualBits += 8, offset += data_result.used) { + data_result = matchData(&(results->rawbuf[offset]), 8, + kMitsubishiHeavyBitMark, kMitsubishiHeavyOneSpace, + kMitsubishiHeavyBitMark, kMitsubishiHeavyZeroSpace, + kTolerance, 0, false); + if (data_result.success == false) { + DPRINT("DEBUG: offset = "); + DPRINTLN(offset + data_result.used); + return false; // Fail + } + results->state[i] = data_result.data; + } + // Footer. + if (!matchMark(results->rawbuf[offset++], kMitsubishiHeavyBitMark)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kMitsubishiHeavyGap)) return false; + + // Compliance + if (actualBits < nbits) return false; + if (strict && actualBits != nbits) return false; // Not as we expected. + switch (actualBits) { + case kMitsubishiHeavy88Bits: + if (strict && !(IRMitsubishiHeavy88Ac::checkZjsSig(results->state) && + IRMitsubishiHeavy88Ac::validChecksum(results->state))) + return false; + results->decode_type = MITSUBISHI_HEAVY_88; + break; + case kMitsubishiHeavy152Bits: + if (strict && !(IRMitsubishiHeavy152Ac::checkZmsSig(results->state) && + IRMitsubishiHeavy152Ac::validChecksum(results->state))) + return false; + results->decode_type = MITSUBISHI_HEAVY_152; + break; + default: + return false; + } + + // Success + results->bits = actualBits; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_MITSUBISHIHEAVY diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.h b/lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.h new file mode 100644 index 000000000..bcd85c6e0 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_MitsubishiHeavy.h @@ -0,0 +1,264 @@ +// Copyright 2019 David Conran + +#ifndef IR_MITSUBISHIHEAVY_H_ +#define IR_MITSUBISHIHEAVY_H_ + +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/660 +// https://github.com/ToniA/Raw-IR-decoder-for-Arduino/blob/master/MitsubishiHeavy.cpp +// https://github.com/ToniA/arduino-heatpumpir/blob/master/MitsubishiHeavyHeatpumpIR.cpp + +// Constants. +const uint8_t kMitsubishiHeavySigLength = 5; + + +// ZMS (152 bit) +const uint8_t kMitsubishiHeavyZmsSig[kMitsubishiHeavySigLength] = { + 0xAD, 0x51, 0x3C, 0xE5, 0x1A}; +// Byte[5] +const uint8_t kMitsubishiHeavyFilterBit = 0b01000000; +const uint8_t kMitsubishiHeavyCleanBit = 0b00100000; +const uint8_t kMitsubishiHeavyPowerBit = 0b00001000; // Byte 9 on ZJS +const uint8_t kMitsubishiHeavyModeMask = 0b00000111; // Byte 9 on ZJS +const uint8_t kMitsubishiHeavyAuto = 0; // 0b000 +const uint8_t kMitsubishiHeavyCool = 1; // 0b001 +const uint8_t kMitsubishiHeavyDry = 2; // 0b010 +const uint8_t kMitsubishiHeavyFan = 3; // 0b011 +const uint8_t kMitsubishiHeavyHeat = 4; // 0b100 +// Byte[7] +const uint8_t kMitsubishiHeavyTempMask = 0b00001111; +const uint8_t kMitsubishiHeavyMinTemp = 17; // 17C +const uint8_t kMitsubishiHeavyMaxTemp = 31; // 31C +// Byte[9] +const uint8_t kMitsubishiHeavyFanMask = 0b00001111; // ~Byte 7 on ZJS. +const uint8_t kMitsubishiHeavy152FanAuto = 0x0; // 0b0000 +const uint8_t kMitsubishiHeavy152FanLow = 0x1; // 0b0001 +const uint8_t kMitsubishiHeavy152FanMed = 0x2; // 0b0010 +const uint8_t kMitsubishiHeavy152FanHigh = 0x3; // 0b0011 +const uint8_t kMitsubishiHeavy152FanMax = 0x4; // 0b0100 +const uint8_t kMitsubishiHeavy152FanEcono = 0x6; // 0b0110 +const uint8_t kMitsubishiHeavy152FanTurbo = 0x8; // 0b1000 +// Byte[11] +const uint8_t kMitsubishiHeavy3DMask = 0b00010010; +const uint8_t kMitsubishiHeavy152SwingVMask = 0b11100000; +const uint8_t kMitsubishiHeavy152SwingVAuto = 0; // 0b000 +const uint8_t kMitsubishiHeavy152SwingVHighest = 1; // 0b001 +const uint8_t kMitsubishiHeavy152SwingVHigh = 2; // 0b010 +const uint8_t kMitsubishiHeavy152SwingVMiddle = 3; // 0b011 +const uint8_t kMitsubishiHeavy152SwingVLow = 4; // 0b100 +const uint8_t kMitsubishiHeavy152SwingVLowest = 5; // 0b101 +const uint8_t kMitsubishiHeavy152SwingVOff = 6; // 0b110 +// Byte[13] +const uint8_t kMitsubishiHeavy152SwingHMask = 0b00001111; +const uint8_t kMitsubishiHeavy152SwingHAuto = 0; // 0b0000 +const uint8_t kMitsubishiHeavy152SwingHLeftMax = 1; // 0b0001 +const uint8_t kMitsubishiHeavy152SwingHLeft = 2; // 0b0010 +const uint8_t kMitsubishiHeavy152SwingHMiddle = 3; // 0b0011 +const uint8_t kMitsubishiHeavy152SwingHRight = 4; // 0b0100 +const uint8_t kMitsubishiHeavy152SwingHRightMax = 5; // 0b0101 +const uint8_t kMitsubishiHeavy152SwingHRightLeft = 6; // 0b0110 +const uint8_t kMitsubishiHeavy152SwingHLeftRight = 7; // 0b0111 +const uint8_t kMitsubishiHeavy152SwingHOff = 8; // 0b1000 +// Byte[15] +const uint8_t kMitsubishiHeavyNightBit = 0b01000000; +const uint8_t kMitsubishiHeavySilentBit = 0b10000000; + + +// ZJS (88 bit) +const uint8_t kMitsubishiHeavyZjsSig[kMitsubishiHeavySigLength] = { + 0xAD, 0x51, 0x3C, 0xD9, 0x26}; +// Byte [5] +const uint8_t kMitsubishiHeavy88CleanBit = 0b00100000; +const uint8_t kMitsubishiHeavy88SwingHMask = 0b11001100; +const uint8_t kMitsubishiHeavy88SwingHAuto = 0x80; // 0b10000000 +const uint8_t kMitsubishiHeavy88SwingHLeftMax = 0x04; // 0b00000100 +const uint8_t kMitsubishiHeavy88SwingHLeft = 0x44; // 0b01000100 +const uint8_t kMitsubishiHeavy88SwingHMiddle = 0x84; // 0b10000100 +const uint8_t kMitsubishiHeavy88SwingHRight = 0xC4; // 0b11000100 +const uint8_t kMitsubishiHeavy88SwingHRightMax = 0x08; // 0b00001000 +const uint8_t kMitsubishiHeavy88SwingHRightLeft = 0x88; // 0b10001000 +const uint8_t kMitsubishiHeavy88SwingHLeftRight = 0x48; // 0b01001000 +const uint8_t kMitsubishiHeavy88SwingHOff = 0x00; // 0b00000000 +const uint8_t kMitsubishiHeavy88SwingH3D = 0xC8; // 0b11001000 +// Byte[7] +const uint8_t kMitsubishiHeavy88FanMask = 0b11100000; +const uint8_t kMitsubishiHeavy88FanAuto = 0; // 0b000 +const uint8_t kMitsubishiHeavy88FanLow = 2; // 0b010 +const uint8_t kMitsubishiHeavy88FanMed = 3; // 0b011 +const uint8_t kMitsubishiHeavy88FanHigh = 4; // 0b100 +const uint8_t kMitsubishiHeavy88FanTurbo = 6; // 0b110 +const uint8_t kMitsubishiHeavy88FanEcono = 7; // 0b111 +const uint8_t kMitsubishiHeavy88SwingVMaskByte5 = 0b00000010; +const uint8_t kMitsubishiHeavy88SwingVMaskByte7 = 0b00011000; +const uint8_t kMitsubishiHeavy88SwingVMask = + kMitsubishiHeavy88SwingVMaskByte5 | kMitsubishiHeavy88SwingVMaskByte7; + // i.e. 0b00011010 +const uint8_t kMitsubishiHeavy88SwingVAuto = 0b00010000; // 0x10 +const uint8_t kMitsubishiHeavy88SwingVHighest = 0b00011000; // 0x18 +const uint8_t kMitsubishiHeavy88SwingVHigh = 0b00000010; // 0x02 +const uint8_t kMitsubishiHeavy88SwingVMiddle = 0b00001010; // 0x0A +const uint8_t kMitsubishiHeavy88SwingVLow = 0b00010010; // 0x12 +const uint8_t kMitsubishiHeavy88SwingVLowest = 0b00011010; // 0x1A +const uint8_t kMitsubishiHeavy88SwingVOff = 0b00000000; // 0x00 +// Byte[9] is Power & Mode & Temp. + + +// Classes +class IRMitsubishiHeavy152Ac { + public: + explicit IRMitsubishiHeavy152Ac(const uint16_t pin); + + void stateReset(void); +#if SEND_MITSUBISHIHEAVY + void send(const uint16_t repeat = kMitsubishiHeavy152MinRepeat); +#endif // SEND_MITSUBISHIHEAVY + void begin(void); + void on(void); + void off(void); + + void setPower(const bool on); + bool getPower(void); + + void setTemp(const uint8_t temp); + uint8_t getTemp(void); + + void setFan(const uint8_t fan); + uint8_t getFan(void); + + void setMode(const uint8_t mode); + uint8_t getMode(void); + + void setSwingVertical(const uint8_t pos); + uint8_t getSwingVertical(void); + void setSwingHorizontal(const uint8_t pos); + uint8_t getSwingHorizontal(void); + + void setNight(const bool on); + bool getNight(void); + + void set3D(const bool on); + bool get3D(void); + + void setSilent(const bool on); + bool getSilent(void); + + void setFilter(const bool on); + bool getFilter(void); + + void setClean(const bool on); + bool getClean(void); + + void setTurbo(const bool on); + bool getTurbo(void); + + void setEcono(const bool on); + bool getEcono(void); + + uint8_t* getRaw(void); + void setRaw(const uint8_t* data); + + static bool checkZmsSig(const uint8_t *state); + static bool validChecksum( + const uint8_t *state, + const uint16_t length = kMitsubishiHeavy152StateLength); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertFan(const stdAc::fanspeed_t speed); + static uint8_t convertSwingV(const stdAc::swingv_t position); + static uint8_t convertSwingH(const stdAc::swingh_t position); +#ifdef ARDUINO + String toString(void); +#else // ARDUINO + std::string toString(void); +#endif // ARDUINO +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else // UNIT_TEST + IRsendTest _irsend; +#endif // UNIT_TEST + // The state of the IR remote in IR code form. + uint8_t remote_state[kMitsubishiHeavy152StateLength]; + void checksum(); +}; + +class IRMitsubishiHeavy88Ac { + public: + explicit IRMitsubishiHeavy88Ac(const uint16_t pin); + + void stateReset(void); +#if SEND_MITSUBISHIHEAVY + void send(const uint16_t repeat = kMitsubishiHeavy88MinRepeat); +#endif // SEND_MITSUBISHIHEAVY + void begin(void); + void on(void); + void off(void); + + void setPower(const bool on); + bool getPower(void); + + void setTemp(const uint8_t temp); + uint8_t getTemp(void); + + void setFan(const uint8_t fan); + uint8_t getFan(void); + + void setMode(const uint8_t mode); + uint8_t getMode(void); + + void setSwingVertical(const uint8_t pos); + uint8_t getSwingVertical(void); + void setSwingHorizontal(const uint8_t pos); + uint8_t getSwingHorizontal(void); + + void setTurbo(const bool on); + bool getTurbo(void); + + void setEcono(const bool on); + bool getEcono(void); + + void set3D(const bool on); + bool get3D(void); + + void setClean(const bool on); + bool getClean(void); + + uint8_t* getRaw(void); + void setRaw(const uint8_t* data); + + static bool checkZjsSig(const uint8_t *state); + static bool validChecksum( + const uint8_t *state, + const uint16_t length = kMitsubishiHeavy88StateLength); + static uint8_t convertMode(const stdAc::opmode_t mode); + static uint8_t convertFan(const stdAc::fanspeed_t speed); + static uint8_t convertSwingV(const stdAc::swingv_t position); + static uint8_t convertSwingH(const stdAc::swingh_t position); +#ifdef ARDUINO + String toString(void); +#else // ARDUINO + std::string toString(void); +#endif // ARDUINO +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else // UNIT_TEST + IRsendTest _irsend; +#endif // UNIT_TEST + // The state of the IR remote in IR code form. + uint8_t remote_state[kMitsubishiHeavy152StateLength]; + void checksum(); +}; +#endif // IR_MITSUBISHIHEAVY_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_NEC.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_NEC.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.h b/lib/IRremoteESP8266-2.6.0/src/ir_NEC.h similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_NEC.h rename to lib/IRremoteESP8266-2.6.0/src/ir_NEC.h diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Nikai.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Nikai.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Nikai.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Nikai.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Panasonic.cpp similarity index 83% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Panasonic.cpp index e79b136a5..47aa51c96 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Panasonic.cpp @@ -27,8 +27,8 @@ // Code by crankyoldgit // Panasonic A/C models supported: // A/C Series/models: -// JKE, LKE, DKE, CKP, & NKE series. (In theory) -// CS-YW9MKD (confirmed) +// JKE, LKE, DKE, CKP, RKR, & NKE series. (In theory) +// CS-YW9MKD, CS-Z9RKR (confirmed) // CS-ME14CKPG / CS-ME12CKPG / CS-ME10CKPG // A/C Remotes: // A75C3747 (confirmed) @@ -63,7 +63,7 @@ const uint32_t kPanasonicMinGap = kPanasonicMinGapTicks * kPanasonicTick; const uint16_t kPanasonicAcSectionGap = 10000; const uint16_t kPanasonicAcSection1Length = 8; -const uint32_t kPanasonicAcMessageGap = 100000; // A complete guess. +const uint32_t kPanasonicAcMessageGap = kDefaultMessageGap; // Just a guess. #if (SEND_PANASONIC || SEND_DENON) // Send a Panasonic formatted message. @@ -211,7 +211,7 @@ bool IRrecv::decodePanasonic(decode_results *results, uint16_t nbits, //: // Panasonic A/C models supported: // A/C Series/models: -// JKE, LKE, DKE, & NKE series. +// JKE, LKE, DKE, CKP, RKR, & NKE series. // CS-YW9MKD // A/C Remotes: // A75C3747 @@ -268,9 +268,9 @@ void IRPanasonicAc::fixChecksum(const uint16_t length) { } #if SEND_PANASONIC_AC -void IRPanasonicAc::send() { +void IRPanasonicAc::send(const uint16_t repeat) { fixChecksum(); - _irsend.sendPanasonicAC(remote_state); + _irsend.sendPanasonicAC(remote_state, kPanasonicAcStateLength, repeat); } #endif // SEND_PANASONIC_AC @@ -281,6 +281,7 @@ void IRPanasonicAc::setModel(const panasonic_ac_remote_model_t model) { case kPanasonicLke: case kPanasonicNke: case kPanasonicCkp: + case kPanasonicRkr: break; default: // Only proceed if we know what to do. return; @@ -311,12 +312,17 @@ void IRPanasonicAc::setModel(const panasonic_ac_remote_model_t model) { case kPanasonicCkp: remote_state[21] |= 0x10; remote_state[23] = 0x01; + break; + case kPanasonicRkr: + remote_state[13] |= 0x08; + remote_state[23] = 0x89; default: break; } } panasonic_ac_remote_model_t IRPanasonicAc::getModel() { + if (remote_state[23] == 0x89) return kPanasonicRkr; if (remote_state[17] == 0x00) { if ((remote_state[21] & 0x10) && (remote_state[23] & 0x01)) return kPanasonicCkp; @@ -438,6 +444,7 @@ void IRPanasonicAc::setSwingHorizontal(const uint8_t desired_direction) { uint8_t direction = desired_direction; switch (getModel()) { case kPanasonicDke: + case kPanasonicRkr: break; case kPanasonicNke: case kPanasonicLke: @@ -460,18 +467,25 @@ uint8_t IRPanasonicAc::getFan() { } bool IRPanasonicAc::getQuiet() { - if (getModel() == kPanasonicCkp) - return remote_state[21] & kPanasonicAcQuietCkp; - else - return remote_state[21] & kPanasonicAcQuiet; + switch (getModel()) { + case kPanasonicRkr: + case kPanasonicCkp: + return remote_state[21] & kPanasonicAcQuietCkp; + default: + return remote_state[21] & kPanasonicAcQuiet; + } } void IRPanasonicAc::setQuiet(const bool state) { uint8_t quiet; - if (getModel() == kPanasonicCkp) - quiet = kPanasonicAcQuietCkp; - else - quiet = kPanasonicAcQuiet; + switch (getModel()) { + case kPanasonicRkr: + case kPanasonicCkp: + quiet = kPanasonicAcQuietCkp; + break; + default: + quiet = kPanasonicAcQuiet; + } if (state) { setPowerful(false); // Powerful is mutually exclusive. @@ -482,18 +496,25 @@ void IRPanasonicAc::setQuiet(const bool state) { } bool IRPanasonicAc::getPowerful() { - if (getModel() == kPanasonicCkp) - return remote_state[21] & kPanasonicAcPowerfulCkp; - else - return remote_state[21] & kPanasonicAcPowerful; + switch (getModel()) { + case kPanasonicRkr: + case kPanasonicCkp: + return remote_state[21] & kPanasonicAcPowerfulCkp; + default: + return remote_state[21] & kPanasonicAcPowerful; + } } void IRPanasonicAc::setPowerful(const bool state) { uint8_t powerful; - if (getModel() == kPanasonicCkp) - powerful = kPanasonicAcPowerfulCkp; - else - powerful = kPanasonicAcPowerful; + switch (getModel()) { + case kPanasonicRkr: + case kPanasonicCkp: + powerful = kPanasonicAcPowerfulCkp; + break; + default: + powerful = kPanasonicAcPowerful; + } if (state) { setQuiet(false); // Quiet is mutually exclusive. @@ -591,12 +612,79 @@ String IRPanasonicAc::timeToString(const uint16_t mins_since_midnight) { std::string IRPanasonicAc::timeToString(const uint16_t mins_since_midnight) { std::string result = ""; #endif // ARDUINO - result += uint64ToString(mins_since_midnight / 60) + ":"; + result += uint64ToString(mins_since_midnight / 60) + ':'; uint8_t mins = mins_since_midnight % 60; - if (mins < 10) result += "0"; // Zero pad the minutes. + if (mins < 10) result += '0'; // Zero pad the minutes. return result + uint64ToString(mins); } +// Convert a standard A/C mode into its native mode. +uint8_t IRPanasonicAc::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kPanasonicAcCool; + case stdAc::opmode_t::kHeat: + return kPanasonicAcHeat; + case stdAc::opmode_t::kDry: + return kPanasonicAcDry; + case stdAc::opmode_t::kFan: + return kPanasonicAcFan; + default: + return kPanasonicAcAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRPanasonicAc::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + return kPanasonicAcFanMin; + case stdAc::fanspeed_t::kLow: + return kPanasonicAcFanMin + 1; + case stdAc::fanspeed_t::kMedium: + return kPanasonicAcFanMin + 2; + case stdAc::fanspeed_t::kHigh: + return kPanasonicAcFanMin + 3; + case stdAc::fanspeed_t::kMax: + return kPanasonicAcFanMax; + default: + return kPanasonicAcFanAuto; + } +} + +// Convert a standard A/C vertical swing into its native setting. +uint8_t IRPanasonicAc::convertSwingV(const stdAc::swingv_t position) { + switch (position) { + case stdAc::swingv_t::kHighest: + case stdAc::swingv_t::kHigh: + case stdAc::swingv_t::kMiddle: + return kPanasonicAcSwingVUp; + case stdAc::swingv_t::kLow: + case stdAc::swingv_t::kLowest: + return kPanasonicAcSwingVDown; + default: + return kPanasonicAcSwingVAuto; + } +} + +// Convert a standard A/C horizontal swing into its native setting. +uint8_t IRPanasonicAc::convertSwingH(const stdAc::swingh_t position) { + switch (position) { + case stdAc::swingh_t::kLeftMax: + return kPanasonicAcSwingHFullLeft; + case stdAc::swingh_t::kLeft: + return kPanasonicAcSwingHLeft; + case stdAc::swingh_t::kMiddle: + return kPanasonicAcSwingHMiddle; + case stdAc::swingh_t::kRight: + return kPanasonicAcSwingHRight; + case stdAc::swingh_t::kRightMax: + return kPanasonicAcSwingHFullRight; + default: + return kPanasonicAcSwingHAuto; + } +} + // Convert the internal state into a human readable string. #ifdef ARDUINO String IRPanasonicAc::toString() { @@ -605,84 +693,92 @@ String IRPanasonicAc::toString() { std::string IRPanasonicAc::toString() { std::string result = ""; #endif // ARDUINO - result += "Model: " + uint64ToString(getModel()); + result += F("Model: "); + result += uint64ToString(getModel()); switch (getModel()) { case kPanasonicDke: - result += " (DKE)"; + result += F(" (DKE)"); break; case kPanasonicJke: - result += " (JKE)"; + result += F(" (JKE)"); break; case kPanasonicNke: - result += " (NKE)"; + result += F(" (NKE)"); break; case kPanasonicLke: - result += " (LKE)"; + result += F(" (LKE)"); break; case kPanasonicCkp: - result += " (CKP)"; + result += F(" (CKP)"); + break; + case kPanasonicRkr: + result += F(" (RKR)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - result += ", Power: "; + result += F(", Power: "); if (getPower()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Mode: " + uint64ToString(getMode()); + result += F("Off"); + result += F(", Mode: "); + result += uint64ToString(getMode()); switch (getMode()) { case kPanasonicAcAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kPanasonicAcCool: - result += " (COOL)"; + result += F(" (COOL)"); break; case kPanasonicAcHeat: - result += " (HEAT)"; + result += F(" (HEAT)"); break; case kPanasonicAcDry: - result += " (DRY)"; + result += F(" (DRY)"); break; case kPanasonicAcFan: - result += " (FAN)"; + result += F(" (FAN)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - result += ", Temp: " + uint64ToString(getTemp()) + "C"; - result += ", Fan: " + uint64ToString(getFan()); + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFan()); switch (getFan()) { case kPanasonicAcFanAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kPanasonicAcFanMax: - result += " (MAX)"; + result += F(" (MAX)"); break; case kPanasonicAcFanMin: - result += " (MIN)"; + result += F(" (MIN)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); break; } - result += ", Swing (Vertical): " + uint64ToString(getSwingVertical()); + result += F(", Swing (Vertical): "); + result += uint64ToString(getSwingVertical()); switch (getSwingVertical()) { case kPanasonicAcSwingVAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kPanasonicAcSwingVUp: - result += " (Full Up)"; + result += F(" (Full Up)"); break; case kPanasonicAcSwingVDown: - result += " (Full Down)"; + result += F(" (Full Down)"); break; case 2: case 3: case 4: break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); break; } switch (getModel()) { @@ -690,52 +786,54 @@ std::string IRPanasonicAc::toString() { case kPanasonicCkp: break; // No Horizontal Swing support. default: - result += ", Swing (Horizontal): " + uint64ToString(getSwingHorizontal()); + result += F(", Swing (Horizontal): "); + result += uint64ToString(getSwingHorizontal()); switch (getSwingHorizontal()) { case kPanasonicAcSwingHAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kPanasonicAcSwingHFullLeft: - result += " (Full Left)"; + result += F(" (Full Left)"); break; case kPanasonicAcSwingHLeft: - result += " (Left)"; + result += F(" (Left)"); break; case kPanasonicAcSwingHMiddle: - result += " (Middle)"; + result += F(" (Middle)"); break; case kPanasonicAcSwingHFullRight: - result += " (Full Right)"; + result += F(" (Full Right)"); break; case kPanasonicAcSwingHRight: - result += " (Right)"; + result += F(" (Right)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); break; } } - result += ", Quiet: "; + result += F(", Quiet: "); if (getQuiet()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Powerful: "; + result += F("Off"); + result += F(", Powerful: "); if (getPowerful()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Clock: " + timeToString(getClock()); - result += ", On Timer: "; + result += F("Off"); + result += F(", Clock: "); + result += timeToString(getClock()); + result += F(", On Timer: "); if (isOnTimerEnabled()) result += timeToString(getOnTimer()); else - result += "Off"; - result += ", Off Timer: "; + result += F("Off"); + result += F(", Off Timer: "); if (isOffTimerEnabled()) result += timeToString(getOffTimer()); else - result += "Off"; + result += F("Off"); return result; } diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.h b/lib/IRremoteESP8266-2.6.0/src/ir_Panasonic.h similarity index 91% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Panasonic.h index 762631fe7..1a7b4e114 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Panasonic.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Panasonic.h @@ -12,6 +12,9 @@ #endif #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif // PPPP AAA N N AAA SSSS OOO N N IIIII CCCC // P P A A NN N A A S O O NN N I C @@ -43,7 +46,7 @@ const uint8_t kPanasonicAcMaxTemp = 30; // Celsius const uint8_t kPanasonicAcFanModeTemp = 27; // Celsius const uint8_t kPanasonicAcQuiet = 1; // 0b1 const uint8_t kPanasonicAcPowerful = 0x20; // 0b100000 -// CKP models have Powerful and Quiet bits swapped. +// CKP & RKR models have Powerful and Quiet bits swapped. const uint8_t kPanasonicAcQuietCkp = 0x20; // 0b100000 const uint8_t kPanasonicAcPowerfulCkp = 1; // 0b1 const uint8_t kPanasonicAcSwingVAuto = 0xF; @@ -73,6 +76,7 @@ enum panasonic_ac_remote_model_t { kPanasonicDke = 3, kPanasonicJke = 4, kPanasonicCkp = 5, + kPanasonicRkr = 6, }; class IRPanasonicAc { @@ -81,7 +85,7 @@ class IRPanasonicAc { void stateReset(); #if SEND_PANASONIC - void send(); + void send(const uint16_t repeat = kPanasonicAcDefaultRepeat); #endif // SEND_PANASONIC void begin(); void on(); @@ -122,6 +126,10 @@ class IRPanasonicAc { const bool enable = true); void cancelOffTimer(); bool isOffTimerEnabled(); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); + uint8_t convertSwingV(const stdAc::swingv_t position); + uint8_t convertSwingH(const stdAc::swingh_t position); #ifdef ARDUINO String toString(); static String timeToString(const uint16_t mins_since_midnight); @@ -132,6 +140,9 @@ class IRPanasonicAc { #ifndef UNIT_TEST private: + IRsend _irsend; +#else + IRsendTest _irsend; #endif uint8_t remote_state[kPanasonicAcStateLength]; uint8_t _swingh; @@ -139,7 +150,6 @@ class IRPanasonicAc { void fixChecksum(const uint16_t length = kPanasonicAcStateLength); static uint8_t calcChecksum(const uint8_t *state, const uint16_t length = kPanasonicAcStateLength); - IRsend _irsend; }; #endif // IR_PANASONIC_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Pioneer.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Pioneer.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Pioneer.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Pioneer.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Pronto.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Pronto.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Pronto.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Pronto.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_RC5_RC6.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_RC5_RC6.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_RC5_RC6.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_RC5_RC6.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_RCMM.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_RCMM.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_RCMM.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_RCMM.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Samsung.cpp similarity index 66% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Samsung.cpp index d943f8cf9..7e54d17df 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Samsung.cpp @@ -1,5 +1,5 @@ // Copyright 2009 Ken Shirriff -// Copyright 2017 David Conran +// Copyright 2017, 2018, 2019 David Conran #include "ir_Samsung.h" #include @@ -168,6 +168,127 @@ bool IRrecv::decodeSAMSUNG(decode_results *results, uint16_t nbits, } #endif +#if SEND_SAMSUNG36 +// Send a Samsung 36-bit formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The bit size of the message being sent. typically kSamsung36Bits. +// repeat: The number of times the message is to be repeated. +// +// Status: Alpha / Experimental. +// +// Note: +// Protocol is used by Samsung Bluray Remote: ak59-00167a +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/621 +void IRsend::sendSamsung36(const uint64_t data, const uint16_t nbits, + const uint16_t repeat) { + if (nbits < 16) return; // To small to send. + for (uint16_t r = 0; r <= repeat; r++) { + // Block #1 (16 bits) + sendGeneric(kSamsungHdrMark, kSamsungHdrSpace, + kSamsungBitMark, kSamsungOneSpace, + kSamsungBitMark, kSamsungZeroSpace, + kSamsungBitMark, kSamsungHdrSpace, + data >> (nbits - 16), 16, 38, true, 0, kDutyDefault); + // Block #2 (The rest, typically 20 bits) + sendGeneric(0, 0, // No header + kSamsungBitMark, kSamsungOneSpace, + kSamsungBitMark, kSamsungZeroSpace, + kSamsungBitMark, kSamsungMinGap, // Gap is just a guess. + // Mask off the rest of the bits. + data & ((1ULL << (nbits - 16)) - 1), + nbits - 16, 38, true, 0, kDutyDefault); + } +} +#endif // SEND_SAMSUNG36 + +#if DECODE_SAMSUNG36 +// Decode the supplied Samsung36 message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of bits to expect in the data portion. +// Typically kSamsung36Bits. +// strict: Flag to indicate if we strictly adhere to the specification. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Alpha / Experimental +// +// Note: +// Protocol is used by Samsung Bluray Remote: ak59-00167a +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/621 +bool IRrecv::decodeSamsung36(decode_results *results, const uint16_t nbits, + const bool strict) { + if (results->rawlen < 2 * nbits + kHeader + kFooter * 2 - 1) + return false; // Can't possibly be a valid Samsung message. + // We need to be looking for > 16 bits to make sense. + if (nbits <= 16) return false; + if (strict && nbits != kSamsung36Bits) + return false; // We expect nbits to be 36 bits of message. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + + // Header + if (!matchMark(results->rawbuf[offset], kSamsungHdrMark)) return false; + // Calculate how long the common tick time is based on the header mark. + uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kSamsungHdrMarkTicks; + if (!matchSpace(results->rawbuf[offset], kSamsungHdrSpace)) return false; + // Calculate how long the common tick time is based on the header space. + uint32_t s_tick = + results->rawbuf[offset++] * kRawTick / kSamsungHdrSpaceTicks; + // Data (Block #1) + match_result_t data_result = + matchData(&(results->rawbuf[offset]), 16, + kSamsungBitMarkTicks * m_tick, kSamsungOneSpaceTicks * s_tick, + kSamsungBitMarkTicks * m_tick, kSamsungZeroSpaceTicks * s_tick); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + uint16_t bitsSoFar = data_result.used / 2; + // Footer (Block #1) + if (!matchMark(results->rawbuf[offset++], kSamsungBitMarkTicks * m_tick)) + return false; + if (!matchSpace(results->rawbuf[offset++], kSamsungHdrSpaceTicks * s_tick)) + return false; + // Data (Block #2) + data_result = matchData(&(results->rawbuf[offset]), + nbits - 16, + kSamsungBitMarkTicks * m_tick, + kSamsungOneSpaceTicks * s_tick, + kSamsungBitMarkTicks * m_tick, + kSamsungZeroSpaceTicks * s_tick); + if (data_result.success == false) return false; + data <<= (nbits - 16); + data += data_result.data; + offset += data_result.used; + bitsSoFar += data_result.used / 2; + // Footer (Block #2) + if (!matchMark(results->rawbuf[offset++], kSamsungBitMarkTicks * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kSamsungMinGapTicks * s_tick)) + return false; + + // Compliance + if (nbits != bitsSoFar) return false; + + // Success + results->bits = bitsSoFar; + results->value = data; + results->decode_type = SAMSUNG36; + results->command = data & ((1ULL << (nbits - 16)) - 1); + results->address = data >> (nbits - 16); + return true; +} +#endif // DECODE_SAMSUNG36 + #if SEND_SAMSUNG_AC // Send a Samsung A/C message. // @@ -180,7 +301,8 @@ bool IRrecv::decodeSAMSUNG(decode_results *results, uint16_t nbits, // // Ref: // https://github.com/markszabo/IRremoteESP8266/issues/505 -void IRsend::sendSamsungAC(uint8_t data[], uint16_t nbytes, uint16_t repeat) { +void IRsend::sendSamsungAC(const uint8_t data[], const uint16_t nbytes, + const uint16_t repeat) { if (nbytes < kSamsungAcStateLength && nbytes % kSamsungACSectionLength) return; // Not an appropriate number of bytes to send a proper message. @@ -226,53 +348,85 @@ void IRSamsungAc::begin() { _irsend.begin(); } uint8_t IRSamsungAc::calcChecksum(const uint8_t state[], const uint16_t length) { uint8_t sum = 0; - uint8_t currentbyte; // Safety check so we don't go outside the array. - if (length <= 5) return 255; + if (length < 7) return 255; // Shamelessly inspired by: // https://github.com/adafruit/Raw-IR-decoder-for-Arduino/pull/3/files // Count most of the '1' bits after the checksum location. - for (uint8_t i = length - 5; i < length - 1; i++) { - currentbyte = state[i]; - if (i == length - 5) currentbyte = state[length - 5] & 0b11111110; - for (; currentbyte; currentbyte >>= 1) - if (currentbyte & 1) sum++; - } + sum += countBits(state[length - 7], 8); + sum -= countBits(state[length - 6] & 0xF, 8); + sum += countBits(state[length - 5] & 0b11111110, 8); + sum += countBits(state + length - 4, 3); return (28 - sum) & 0xF; } bool IRSamsungAc::validChecksum(const uint8_t state[], const uint16_t length) { - if (length <= 5) return true; // No checksum to compare with. Assume okay. - return (state[length - 6] >> 4) == calcChecksum(state, length); + if (length < kSamsungAcStateLength) + return true; // No checksum to compare with. Assume okay. + uint8_t offset = 0; + if (length >= kSamsungAcExtendedStateLength) offset = 7; + return ((state[length - 6] >> 4) == calcChecksum(state, length) && + (state[length - (13 + offset)] >> 4) == calcChecksum(state, length - + (7 + offset))); } // Update the checksum for the internal state. void IRSamsungAc::checksum(uint16_t length) { - if (length < 9) return; + if (length < 13) return; remote_state[length - 6] &= 0x0F; remote_state[length - 6] |= (calcChecksum(remote_state, length) << 4); + remote_state[length - 13] &= 0x0F; + remote_state[length - 13] |= (calcChecksum(remote_state, length - 7) << 4); } #if SEND_SAMSUNG_AC -void IRSamsungAc::send(const bool calcchecksum) { +// Use for most function/mode/settings changes to the unit. +// i.e. When the device is already running. +void IRSamsungAc::send(const uint16_t repeat, const bool calcchecksum) { if (calcchecksum) checksum(); - _irsend.sendSamsungAC(remote_state); + _irsend.sendSamsungAC(remote_state, kSamsungAcStateLength, repeat); } -#endif // SEND_SAMSUNG_AC -#if SEND_SAMSUNG_AC -void IRSamsungAc::sendExtended(const bool calcchecksum) { +// Use this for when you need to power on/off the device. +// Samsung A/C requires an extended length message when you want to +// change the power operating mode of the A/C unit. +void IRSamsungAc::sendExtended(const uint16_t repeat, const bool calcchecksum) { if (calcchecksum) checksum(); uint8_t extended_state[kSamsungAcExtendedStateLength] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xD2, 0x0F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Copy/convert the internal state to an extended state. for (uint16_t i = 0; i < kSamsungACSectionLength; i++) extended_state[i] = remote_state[i]; for (uint16_t i = kSamsungACSectionLength; i < kSamsungAcStateLength; i++) extended_state[i + kSamsungACSectionLength] = remote_state[i]; + // extended_state[8] seems special. This is a guess on how to calculate it. + extended_state[8] = (extended_state[1] & 0x9F) | 0x40; // Send it. - _irsend.sendSamsungAC(extended_state, kSamsungAcExtendedStateLength); + _irsend.sendSamsungAC(extended_state, kSamsungAcExtendedStateLength, repeat); +} + +// Send the special extended "On" message as the library can't seem to reproduce +// this message automatically. +// See: https://github.com/markszabo/IRremoteESP8266/issues/604#issuecomment-475020036 +void IRSamsungAc::sendOn(const uint16_t repeat) { + const uint8_t extended_state[21] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0}; + _irsend.sendSamsungAC(extended_state, kSamsungAcExtendedStateLength, repeat); +} + +// Send the special extended "Off" message as the library can't seem to +// reproduce this message automatically. +// See: https://github.com/markszabo/IRremoteESP8266/issues/604#issuecomment-475020036 +void IRSamsungAc::sendOff(const uint16_t repeat) { + const uint8_t extended_state[21] = { + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, + 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0}; + _irsend.sendSamsungAC(extended_state, kSamsungAcExtendedStateLength, repeat); } #endif // SEND_SAMSUNG_AC @@ -423,6 +577,39 @@ void IRSamsungAc::setQuiet(const bool state) { } } +// Convert a standard A/C mode into its native mode. +uint8_t IRSamsungAc::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kSamsungAcCool; + case stdAc::opmode_t::kHeat: + return kSamsungAcHeat; + case stdAc::opmode_t::kDry: + return kSamsungAcDry; + case stdAc::opmode_t::kFan: + return kSamsungAcFan; + default: + return kSamsungAcAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRSamsungAc::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kSamsungAcFanLow; + case stdAc::fanspeed_t::kMedium: + return kSamsungAcFanMed; + case stdAc::fanspeed_t::kHigh: + return kSamsungAcFanHigh; + case stdAc::fanspeed_t::kMax: + return kSamsungAcFanTurbo; + default: + return kSamsungAcFanAuto; + } +} + // Convert the internal state into a human readable string. #ifdef ARDUINO String IRSamsungAc::toString() { @@ -431,74 +618,77 @@ String IRSamsungAc::toString() { std::string IRSamsungAc::toString() { std::string result = ""; #endif // ARDUINO - result += "Power: "; + result += F("Power: "); if (getPower()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Mode: " + uint64ToString(getMode()); + result += F("Off"); + result += F(", Mode: "); + result += uint64ToString(getMode()); switch (getMode()) { case kSamsungAcAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kSamsungAcCool: - result += " (COOL)"; + result += F(" (COOL)"); break; case kSamsungAcHeat: - result += " (HEAT)"; + result += F(" (HEAT)"); break; case kSamsungAcDry: - result += " (DRY)"; + result += F(" (DRY)"); break; case kSamsungAcFan: - result += " (FAN)"; + result += F(" (FAN)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - result += ", Temp: " + uint64ToString(getTemp()) + "C"; - result += ", Fan: " + uint64ToString(getFan()); + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFan()); switch (getFan()) { case kSamsungAcFanAuto: case kSamsungAcFanAuto2: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kSamsungAcFanLow: - result += " (LOW)"; + result += F(" (LOW)"); break; case kSamsungAcFanMed: - result += " (MED)"; + result += F(" (MED)"); break; case kSamsungAcFanHigh: - result += " (HIGH)"; + result += F(" (HIGH)"); break; case kSamsungAcFanTurbo: - result += " (TURBO)"; + result += F(" (TURBO)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); break; } - result += ", Swing: "; + result += F(", Swing: "); if (getSwing()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Beep: "; + result += F("Off"); + result += F(", Beep: "); if (getBeep()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Clean: "; + result += F("Off"); + result += F(", Clean: "); if (getBeep()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Quiet: "; + result += F("Off"); + result += F(", Quiet: "); if (getQuiet()) - result += "On"; + result += F("On"); else - result += "Off"; + result += F("Off"); return result; } @@ -571,7 +761,6 @@ bool IRrecv::decodeSamsungAC(decode_results *results, uint16_t nbits, // Is the signature correct? DPRINTLN("DEBUG: Checking signature."); if (results->state[0] != 0x02 || results->state[2] != 0x0F) return false; - if (results->state[1] != 0x92 && results->state[1] != 0xB2) return false; if (strict) { // Is the checksum valid? if (!IRSamsungAc::validChecksum(results->state, nbits / 8)) { diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h b/lib/IRremoteESP8266-2.6.0/src/ir_Samsung.h similarity index 84% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Samsung.h index f80b47d20..9df427c6f 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Samsung.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Samsung.h @@ -14,6 +14,9 @@ #endif #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif // SSSS AAA MMM SSSS U U N N GGGG // S A A M M M S U U NN N G @@ -62,8 +65,12 @@ class IRSamsungAc { void stateReset(); #if SEND_SAMSUNG_AC - void send(const bool calcchecksum = true); - void sendExtended(const bool calcchecksum = true); + void send(const uint16_t repeat = kSamsungAcDefaultRepeat, + const bool calcchecksum = true); + void sendExtended(const uint16_t repeat = kSamsungAcDefaultRepeat, + const bool calcchecksum = true); + void sendOn(const uint16_t repeat = kSamsungAcDefaultRepeat); + void sendOff(const uint16_t repeat = kSamsungAcDefaultRepeat); #endif // SEND_SAMSUNG_AC void begin(); void on(); @@ -91,17 +98,23 @@ class IRSamsungAc { const uint16_t length = kSamsungAcStateLength); static uint8_t calcChecksum(const uint8_t state[], const uint16_t length = kSamsungAcStateLength); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); #ifdef ARDUINO String toString(); #else std::string toString(); #endif +#ifndef UNIT_TEST private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif // The state of the IR remote in IR code form. uint8_t remote_state[kSamsungAcExtendedStateLength]; void checksum(const uint16_t length = kSamsungAcStateLength); - IRsend _irsend; }; #endif // IR_SAMSUNG_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Sanyo.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Sanyo.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Sanyo.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Sanyo.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Sharp.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Sharp.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Sharp.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Sharp.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Sherwood.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Sherwood.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Sherwood.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Sherwood.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Sony.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Sony.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Sony.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Sony.cpp diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Tcl.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Tcl.cpp new file mode 100644 index 000000000..79fb23cf1 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Tcl.cpp @@ -0,0 +1,420 @@ +// Copyright 2019 David Conran + +#include "ir_Tcl.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRremoteESP8266.h" +#include "IRutils.h" + +// Constants + + +#if SEND_TCL112AC +void IRsend::sendTcl112Ac(const unsigned char data[], const uint16_t nbytes, + const uint16_t repeat) { + sendGeneric(kTcl112AcHdrMark, kTcl112AcHdrSpace, + kTcl112AcBitMark, kTcl112AcOneSpace, + kTcl112AcBitMark, kTcl112AcZeroSpace, + kTcl112AcBitMark, kTcl112AcGap, + data, nbytes, 38000, false, repeat, 50); +} +#endif // SEND_TCL112AC + +IRTcl112Ac::IRTcl112Ac(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRTcl112Ac::begin() { this->_irsend.begin(); } + +#if SEND_TCL112AC +void IRTcl112Ac::send(const uint16_t repeat) { + this->checksum(); + this->_irsend.sendTcl112Ac(remote_state, kTcl112AcStateLength, repeat); +} +#endif // SEND_TCL112AC + +// Calculate the checksum for a given array. +// Args: +// state: The array to calculate the checksum over. +// length: The size of the array. +// Returns: +// The 8 bit checksum value. +uint8_t IRTcl112Ac::calcChecksum(uint8_t state[], + const uint16_t length) { + if (length) + return sumBytes(state, length - 1); + else + return 0; +} + +// Calculate & set the checksum for the current internal state of the remote. +void IRTcl112Ac::checksum(const uint16_t length) { + // Stored the checksum value in the last byte. + if (length > 1) + remote_state[length - 1] = calcChecksum(remote_state, length); +} + +// Verify the checksum is valid for a given state. +// Args: +// state: The array to verify the checksum of. +// length: The size of the state. +// Returns: +// A boolean. +bool IRTcl112Ac::validChecksum(uint8_t state[], const uint16_t length) { + return (length > 1 && state[length - 1] == calcChecksum(state, length)); +} + +void IRTcl112Ac::stateReset() { + for (uint8_t i = 0; i < kTcl112AcStateLength; i++) + remote_state[i] = 0x0; + // A known good state. (On, Cool, 24C) + remote_state[0] = 0x23; + remote_state[1] = 0xCB; + remote_state[2] = 0x26; + remote_state[3] = 0x01; + remote_state[5] = 0x24; + remote_state[6] = 0x03; + remote_state[7] = 0x07; + remote_state[8] = 0x40; + remote_state[13] = 0x03; +} + +uint8_t* IRTcl112Ac::getRaw() { + this->checksum(); + return remote_state; +} + +void IRTcl112Ac::setRaw(const uint8_t new_code[], const uint16_t length) { + for (uint8_t i = 0; i < length && i < kTcl112AcStateLength; i++) { + remote_state[i] = new_code[i]; + } +} + +// Set the requested power state of the A/C to on. +void IRTcl112Ac::on(void) { this->setPower(true); } + +// Set the requested power state of the A/C to off. +void IRTcl112Ac::off(void) { this->setPower(false); } + +// Set the requested power state of the A/C. +void IRTcl112Ac::setPower(const bool on) { + if (on) + remote_state[5] |= kTcl112AcPowerMask; + else + remote_state[5] &= ~kTcl112AcPowerMask; +} + +// Return the requested power state of the A/C. +bool IRTcl112Ac::getPower(void) { + return remote_state[5] & kTcl112AcPowerMask; +} + +// Get the requested climate operation mode of the a/c unit. +// Returns: +// A uint8_t containing the A/C mode. +uint8_t IRTcl112Ac::getMode() { + return remote_state[6] & 0xF; +} + +// Set the requested climate operation mode of the a/c unit. +// Note: Fan/Ventilation mode sets the fan speed to high. +// Unknown values default to Auto. +void IRTcl112Ac::setMode(const uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + switch (mode) { + case kTcl112AcFan: + this->setFan(kTcl112AcFanHigh); + // FALLTHRU + case kTcl112AcAuto: + case kTcl112AcCool: + case kTcl112AcHeat: + case kTcl112AcDry: + remote_state[6] &= 0xF0; + remote_state[6] |= mode; + break; + default: + setMode(kTcl112AcAuto); + } +} + +void IRTcl112Ac::setTemp(const float celsius) { + // Make sure we have desired temp in the correct range. + float safecelsius = std::max(celsius, kTcl112AcTempMin); + safecelsius = std::min(safecelsius, kTcl112AcTempMax); + // Convert to integer nr. of half degrees. + uint8_t nrHalfDegrees = safecelsius * 2; + if (nrHalfDegrees & 1) // Do we have a half degree celsius? + remote_state[12] |= kTcl112AcHalfDegree; // Add 0.5 degrees + else + remote_state[12] &= ~kTcl112AcHalfDegree; // Clear the half degree. + remote_state[7] &= 0xF0; // Clear temp bits. + remote_state[7] |= ((uint8_t)kTcl112AcTempMax - nrHalfDegrees / 2); +} + +float IRTcl112Ac::getTemp() { + float result = kTcl112AcTempMax - (remote_state[7] & 0xF); + if (remote_state[12] & kTcl112AcHalfDegree) result += 0.5; + return result; +} + +// Set the speed of the fan. +// Unknown speeds will default to Auto. +void IRTcl112Ac::setFan(const uint8_t speed) { + switch (speed) { + case kTcl112AcFanAuto: + case kTcl112AcFanLow: + case kTcl112AcFanMed: + case kTcl112AcFanHigh: + remote_state[8] &= ~kTcl112AcFanMask; + remote_state[8] |= speed; + break; + default: + this->setFan(kTcl112AcFanAuto); + } +} + +// Return the currect fan speed. +uint8_t IRTcl112Ac::getFan() { + return remote_state[8] & kTcl112AcFanMask; +} + +// Control economy mode. +void IRTcl112Ac::setEcono(const bool on) { + if (on) + remote_state[5] |= kTcl112AcBitEcono; + else + remote_state[5] &= ~kTcl112AcBitEcono; +} + +// Return the economy state of the A/C. +bool IRTcl112Ac::getEcono(void) { + return remote_state[5] & kTcl112AcBitEcono; +} + +// Control Health mode. +void IRTcl112Ac::setHealth(const bool on) { + if (on) + remote_state[6] |= kTcl112AcBitHealth; + else + remote_state[6] &= ~kTcl112AcBitHealth; +} + +// Return the Health mode state of the A/C. +bool IRTcl112Ac::getHealth(void) { + return remote_state[6] & kTcl112AcBitHealth; +} + +// Control Light/Display mode. +void IRTcl112Ac::setLight(const bool on) { + if (on) + remote_state[5] &= ~kTcl112AcBitLight; + else + remote_state[5] |= kTcl112AcBitLight; +} + +// Return the Light/Display mode state of the A/C. +bool IRTcl112Ac::getLight(void) { + return !(remote_state[5] & kTcl112AcBitLight); +} + +// Control Horizontal Swing. +void IRTcl112Ac::setSwingHorizontal(const bool on) { + if (on) + remote_state[12] |= kTcl112AcBitSwingH; + else + remote_state[12] &= ~kTcl112AcBitSwingH; +} + +// Return the Horizontal Swing state of the A/C. +bool IRTcl112Ac::getSwingHorizontal(void) { + return remote_state[12] & kTcl112AcBitSwingH; +} + +// Control Vertical Swing. +void IRTcl112Ac::setSwingVertical(const bool on) { + if (on) + remote_state[8] |= kTcl112AcBitSwingV; + else + remote_state[8] &= ~kTcl112AcBitSwingV; +} + +// Return the Vertical Swing state of the A/C. +bool IRTcl112Ac::getSwingVertical(void) { + return remote_state[8] & kTcl112AcBitSwingV; +} + +// Control the Turbo setting. +void IRTcl112Ac::setTurbo(const bool on) { + if (on) { + remote_state[6] |= kTcl112AcBitTurbo; + this->setFan(kTcl112AcFanHigh); + this->setSwingVertical(true); + } else { + remote_state[6] &= ~kTcl112AcBitTurbo; + } +} + +// Return the Turbo setting state of the A/C. +bool IRTcl112Ac::getTurbo(void) { + return remote_state[6] & kTcl112AcBitTurbo; +} + +// Convert a standard A/C mode into its native mode. +uint8_t IRTcl112Ac::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kTcl112AcCool; + case stdAc::opmode_t::kHeat: + return kTcl112AcHeat; + case stdAc::opmode_t::kDry: + return kTcl112AcDry; + case stdAc::opmode_t::kFan: + return kTcl112AcFan; + default: + return kTcl112AcAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRTcl112Ac::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kTcl112AcFanLow; + case stdAc::fanspeed_t::kMedium: + return kTcl112AcFanMed; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kTcl112AcFanHigh; + default: + return kTcl112AcFanAuto; + } +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRTcl112Ac::toString() { + String result = ""; +#else +std::string IRTcl112Ac::toString() { + std::string result = ""; +#endif // ARDUINO + result += F("Power: "); + result += (this->getPower() ? F("On") : F("Off")); + result += F(", Mode: "); + result += uint64ToString(getMode()); + switch (this->getMode()) { + case kTcl112AcAuto: + result += F(" (AUTO)"); + break; + case kTcl112AcCool: + result += F(" (COOL)"); + break; + case kTcl112AcHeat: + result += F(" (HEAT)"); + break; + case kTcl112AcDry: + result += F(" (DRY)"); + break; + case kTcl112AcFan: + result += F(" (FAN)"); + break; + default: + result += F(" (UNKNOWN)"); + } + uint16_t nrHalfDegrees = this->getTemp() * 2; + result += F(", Temp: "); + result += uint64ToString(nrHalfDegrees / 2); + if (nrHalfDegrees & 1) result += F(".5"); + result += F("C, Fan: "); + result += uint64ToString(getFan()); + switch (getFan()) { + case kTcl112AcFanAuto: + result += F(" (Auto)"); + break; + case kTcl112AcFanLow: + result += F(" (Low)"); + break; + case kTcl112AcFanMed: + result += F(" (Med)"); + break; + case kTcl112AcFanHigh: + result += F(" (High)"); + break; + } + result += F(", Econo: "); + result += (this->getEcono() ? F("On") : F("Off")); + result += ", Health: "; + result += (this->getHealth() ? F("On") : F("Off")); + result += F(", Light: "); + result += (this->getLight() ? F("On") : F("Off")); + result += F(", Turbo: "); + result += (this->getTurbo() ? F("On") : F("Off")); + result += ", Swing (H): "; + result += (this->getSwingHorizontal() ? F("On") : F("Off")); + result += F(", Swing (V): "); + result += (this->getSwingVertical() ? F("On") : F("Off")); + return result; +} + +#if DECODE_TCL112AC +// Decode the supplied TCL112AC message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kTcl112AcBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Appears to mostly work. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/619 +bool IRrecv::decodeTcl112Ac(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + return false; // Can't possibly be a valid Samsung A/C message. + if (strict && nbits != kTcl112AcBits) return false; + + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + match_result_t data_result; + + // Message Header + if (!matchMark(results->rawbuf[offset++], kTcl112AcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kTcl112AcHdrSpace)) return false; + + // Data + // Keep reading bytes until we either run out of section or state to fill. + for (uint16_t i = 0; offset <= results->rawlen - 16 && i < nbits / 8; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = matchData(&(results->rawbuf[offset]), 8, kTcl112AcBitMark, + kTcl112AcOneSpace, kTcl112AcBitMark, + kTcl112AcZeroSpace, kTolerance, 0, false); + if (data_result.success == false) { + DPRINT("DEBUG: offset = "); + DPRINTLN(offset + data_result.used); + return false; // Fail + } + results->state[i] = data_result.data; + } + + // Footer + if (!matchMark(results->rawbuf[offset++], kTcl112AcBitMark)) return false; + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kTcl112AcGap)) return false; + // Compliance + // Re-check we got the correct size/length due to the way we read the data. + if (dataBitsSoFar != nbits) return false; + // Verify we got a valid checksum. + if (strict && !IRTcl112Ac::validChecksum(results->state)) return false; + // Success + results->decode_type = TCL112AC; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // DECODE_TCL112AC diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Tcl.h b/lib/IRremoteESP8266-2.6.0/src/ir_Tcl.h new file mode 100644 index 000000000..a1595451d --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Tcl.h @@ -0,0 +1,105 @@ +// Copyright 2019 David Conran + +#ifndef IR_TCL_H_ +#define IR_TCL_H_ + +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + +// Constants +const uint16_t kTcl112AcHdrMark = 3000; +const uint16_t kTcl112AcHdrSpace = 1650; +const uint16_t kTcl112AcBitMark = 500; +const uint16_t kTcl112AcOneSpace = 1050; +const uint16_t kTcl112AcZeroSpace = 325; +const uint32_t kTcl112AcGap = kDefaultMessageGap; // Just a guess. + +const uint8_t kTcl112AcHeat = 1; +const uint8_t kTcl112AcDry = 2; +const uint8_t kTcl112AcCool = 3; +const uint8_t kTcl112AcFan = 7; +const uint8_t kTcl112AcAuto = 8; +const uint8_t kTcl112AcFanMask = 0b00000111; +const uint8_t kTcl112AcFanAuto = 0b00000000; +const uint8_t kTcl112AcFanLow = 0b00000010; +const uint8_t kTcl112AcFanMed = 0b00000011; +const uint8_t kTcl112AcFanHigh = 0b00000101; + +const uint8_t kTcl112AcHalfDegree = 0b00100000; +const float kTcl112AcTempMax = 31.0; +const float kTcl112AcTempMin = 16.0; + +const uint8_t kTcl112AcPowerMask = 0b00000100; +const uint8_t kTcl112AcBitEcono = 0b10000000; +const uint8_t kTcl112AcBitLight = 0b01000000; +const uint8_t kTcl112AcBitHealth = 0b00010000; +const uint8_t kTcl112AcBitSwingH = 0b00001000; +const uint8_t kTcl112AcBitSwingV = 0b00111000; +const uint8_t kTcl112AcBitTurbo = 0b01000000; + + +class IRTcl112Ac { + public: + explicit IRTcl112Ac(uint16_t pin); + +#if SEND_TCL112AC + void send(const uint16_t repeat = kTcl112AcDefaultRepeat); +#endif // SEND_TCL + void begin(void); + uint8_t* getRaw(void); + void setRaw(const uint8_t new_code[], + const uint16_t length = kTcl112AcStateLength); + void on(void); + void off(void); + void setPower(const bool on); + bool getPower(void); + void setTemp(const float celsius); // Celsius in 0.5 increments + float getTemp(void); + void setMode(const uint8_t mode); + uint8_t getMode(void); + static uint8_t calcChecksum(uint8_t state[], + const uint16_t length = kTcl112AcStateLength); + static bool validChecksum(uint8_t state[], + const uint16_t length = kTcl112AcStateLength); + void setFan(const uint8_t speed); + uint8_t getFan(void); + void setEcono(const bool on); + bool getEcono(void); + void setHealth(const bool on); + bool getHealth(void); + void setLight(const bool on); + bool getLight(void); + void setSwingHorizontal(const bool on); + bool getSwingHorizontal(void); + void setSwingVertical(const bool on); + bool getSwingVertical(void); + void setTurbo(const bool on); + bool getTurbo(void); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif + uint8_t remote_state[kTcl112AcStateLength]; + void stateReset(); + void checksum(const uint16_t length = kTcl112AcStateLength); +}; + +#endif // IR_TCL_H_ diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Teco.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Teco.cpp new file mode 100644 index 000000000..779bf8f8f --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Teco.cpp @@ -0,0 +1,278 @@ +// Copyright 2019 Fabien Valthier +/* +Node MCU/ESP8266 Sketch to emulate Teco +*/ + +#include "ir_Teco.h" +#include +#include "IRremoteESP8266.h" +#include "IRutils.h" +#ifndef ARDUINO +#include +#endif + +// Constants +// using SPACE modulation. +const uint16_t kTecoHdrMark = 9000; +const uint16_t kTecoHdrSpace = 4440; +const uint16_t kTecoBitMark = 620; +const uint16_t kTecoOneSpace = 1650; +const uint16_t kTecoZeroSpace = 580; +const uint32_t kTecoGap = kDefaultMessageGap; // Made-up value. Just a guess. + +#if SEND_TECO +// Send a Teco A/C message. +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kTecoBits. +// repeat: Nr. of additional times the message is to be sent. +void IRsend::sendTeco(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(kTecoHdrMark, kTecoHdrSpace, kTecoBitMark, kTecoOneSpace, + kTecoBitMark, kTecoZeroSpace, kTecoBitMark, kTecoGap, + data, nbits, 38000, false, repeat, kDutyDefault); +} +#endif // SEND_TECO + +// Class for decoding and constructing Teco AC messages. +IRTecoAc::IRTecoAc(const uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRTecoAc::begin() { _irsend.begin(); } + +#if SEND_TECO +void IRTecoAc::send(const uint16_t repeat) { + _irsend.sendTeco(remote_state, kTecoBits, repeat); +} +#endif // SEND_TECO + +void IRTecoAc::stateReset(void) { + // Mode:auto, Power:Off, fan:auto, temp:16, swing:off, sleep:off + remote_state = kTecoReset; +} + +uint64_t IRTecoAc::getRaw(void) { return remote_state; } + +void IRTecoAc::setRaw(const uint64_t new_code) { remote_state = new_code; } + +void IRTecoAc::on(void) { remote_state |= kTecoPower; } + +void IRTecoAc::off(void) { remote_state &= ~kTecoPower; } + +void IRTecoAc::setPower(const bool on) { + if (on) + this->on(); + else + this->off(); +} + +bool IRTecoAc::getPower(void) { + return (remote_state & kTecoPower) == kTecoPower; } + +void IRTecoAc::setTemp(const uint8_t temp) { + uint8_t newtemp = temp; + newtemp = std::min(newtemp, kTecoMaxTemp); + newtemp = std::max(newtemp, kTecoMinTemp); + newtemp -= kTecoMinTemp; // 16=0b000 + + remote_state &= ~kTecoTempMask; // reinit temp + remote_state |= (newtemp << 8); +} + +uint8_t IRTecoAc::getTemp(void) { + return ((remote_state & kTecoTempMask) >> 8) + kTecoMinTemp; +} + +// Set the speed of the fan +void IRTecoAc::setFan(const uint8_t speed) { + uint8_t newspeed = speed; + switch (speed) { + case kTecoFanAuto: + case kTecoFanHigh: + case kTecoFanMed: + case kTecoFanLow: + break; + default: + newspeed = kTecoFanAuto; + } + remote_state &= ~kTecoFanMask; // reinit fan + remote_state |= (newspeed << 4); +} + +uint8_t IRTecoAc::getFan(void) { return (remote_state & kTecoFanMask) >> 4; } + +void IRTecoAc::setMode(const uint8_t mode) { + uint8_t newmode = mode; + switch (mode) { + case kTecoAuto: + case kTecoCool: + case kTecoDry: + case kTecoFan: + case kTecoHeat: + break; + default: + newmode = kTecoAuto; + } + remote_state &= ~kTecoModeMask; // reinit mode + remote_state |= newmode; +} + +uint8_t IRTecoAc::getMode(void) { return remote_state & kTecoModeMask; } + +void IRTecoAc::setSwing(const bool on) { + if (on) + remote_state |= kTecoSwing; + else + remote_state &= ~kTecoSwing; +} + +bool IRTecoAc::getSwing(void) { return remote_state & kTecoSwing; } + +void IRTecoAc::setSleep(const bool on) { + if (on) + remote_state |= kTecoSleep; + else + remote_state &= ~kTecoSleep; +} + +bool IRTecoAc::getSleep(void) { return remote_state & kTecoSleep; } + +// Convert a standard A/C mode into its native mode. +uint8_t IRTecoAc::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kTecoCool; + case stdAc::opmode_t::kHeat: + return kTecoHeat; + case stdAc::opmode_t::kDry: + return kTecoDry; + case stdAc::opmode_t::kFan: + return kTecoFan; + default: + return kTecoAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRTecoAc::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kTecoFanLow; + case stdAc::fanspeed_t::kMedium: + return kTecoFanMed; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kTecoFanHigh; + default: + return kTecoFanAuto; + } +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRTecoAc::toString(void) { + String result = ""; +#else +std::string IRTecoAc::toString(void) { + std::string result = ""; +#endif // ARDUINO + result += F("Power: "); + result += (this->getPower() ? F("On") : F("Off")); + result += F(", Mode: "); + result += uint64ToString(this->getMode()); + switch (this->getMode()) { + case kTecoAuto: + result += F(" (AUTO)"); + break; + case kTecoCool: + result += F(" (COOL)"); + break; + case kTecoHeat: + result += F(" (HEAT)"); + break; + case kTecoDry: + result += F(" (DRY)"); + break; + case kTecoFan: + result += F(" (FAN)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFan()); + switch (this->getFan()) { + case kTecoFanAuto: + result += F(" (Auto)"); + break; + case kTecoFanHigh: + result += F(" (High)"); + break; + case kTecoFanLow: + result += F(" (Low)"); + break; + case kTecoFanMed: + result += F(" (Med)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Sleep: "); + result += (this->getSleep() ? F("On") : F("Off")); + result += F(", Swing: "); + result += (this->getSwing() ? F("On") : F("Off")); + return result; +} + +#if DECODE_TECO +// Decode the supplied Teco message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kTecoBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE / Tested. +bool IRrecv::decodeTeco(decode_results* results, uint16_t nbits, bool strict) { + // Check if can possibly be a valid Teco message. + if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false; + if (strict && nbits != kTecoBits) return false; // Not what is expected + + uint64_t data = 0; + uint16_t offset = kStartOffset; + match_result_t data_result; + + // Header + if (!matchMark(results->rawbuf[offset++], kTecoHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kTecoHdrSpace)) return false; + // Data (35 bits) + data_result = + matchData(&(results->rawbuf[offset]), 35, kTecoBitMark, kTecoOneSpace, + kTecoBitMark, kTecoZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) return false; + data = data_result.data; + offset += data_result.used; + uint16_t actualBits = data_result.used / 2; + + // Footer. + if (!matchMark(results->rawbuf[offset++], kTecoBitMark)) return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], kTecoGap)) return false; + + // Compliance + if (actualBits < nbits) return false; + if (strict && actualBits != nbits) return false; // Not as we expected. + + // Success + results->decode_type = TECO; + results->bits = actualBits; + results->value = data; + results->address = 0; + results->command = 0; + return true; +} +#endif // DECODE_TECO diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Teco.h b/lib/IRremoteESP8266-2.6.0/src/ir_Teco.h new file mode 100644 index 000000000..65a0050ae --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Teco.h @@ -0,0 +1,144 @@ +// Copyright 2019 Fabien Valthier + +#ifndef IR_TECO_H_ +#define IR_TECO_H_ + +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + +// Constants. Using LSB to be able to send only 35bits. +const uint8_t kTecoAuto = 0; // 0b000 +const uint8_t kTecoCool = 1; // 0b001 +const uint8_t kTecoDry = 2; // 0b010 +const uint8_t kTecoFan = 3; // 0b110 +const uint8_t kTecoHeat = 4; // 0b001 +const uint8_t kTecoFanAuto = 0; // 0b00 +const uint8_t kTecoFanHigh = 3; // 0b11 +const uint8_t kTecoFanMed = 2; // 0b10 +const uint8_t kTecoFanLow = 1; // 0b01 +const uint8_t kTecoMinTemp = 16; // 16C +const uint8_t kTecoMaxTemp = 30; // 30C + +const uint64_t kTecoModeMask = 0b00000000000000000000000000000000111; +const uint64_t kTecoPower = 0b00000000000000000000000000000001000; +const uint64_t kTecoFanMask = 0b00000000000000000000000000000110000; +const uint64_t kTecoSwing = 0b00000000000000000000000000001000000; +const uint64_t kTecoSleep = 0b00000000000000000000000000010000000; +const uint64_t kTecoTempMask = 0b00000000000000000000000111100000000; +const uint64_t kTecoTimerHalfH = 0b00000000000000000000001000000000000; +const uint64_t kTecoTimerTenHr = 0b00000000000000000000110000000000000; +const uint64_t kTecoTimerOn = 0b00000000000000000001000000000000000; +const uint64_t kTecoTimerUniHr = 0b00000000000000011110000000000000000; +const uint64_t kTecoReset = 0b01001010000000000000010000000000000; +/* + (header mark and space) + Teco AC map read and to be sent in LSB with number of bits + + byte 0 = Cst 0x02 + byte 1 = Cst 0x50 + byte 2: + b0-3 = 0b0000 + b4-7 = Timer hours (unit, not thenth) + hours: + 0000 (0) = +0 hour + 0001 (1) = +1 hour + ... + 1001 (9) = +9 hours + byte 3: = timer and Temperature + b0 = Timer (1 = On, 0 = Off) + b1-2 = Timer - number of 10hours + 10Hours: + 00 = 0 * 10hours of timer + 01 = 1 * 10 hours of timer + 10 = 2 * 10hours of timer + b3 = Timer - half hour (1=half hour on, 0 = round hour) + b4-7: Degrees C. + 0000 (0) = 16C + 0001 (1) = 17C + 0010 (2) = 18C + ... + 1101 (13) = 29C + 1110 (14) = 30C + byte 4: Basics + b0 = Sleep Mode (1 = On, 0 = Off) + b1 = Vent swing (1 = On, 0 = Off) + b2-3 = Fan + Fan: + 00 = Auto + 01 = Fan 1 + 10 = Fan 2 + 11 = Fan 3 or higher + b4 = Power Status (1 = On, 0 = Off) + b5-7 = Modes LSB first + Modes: + 000 = Auto (temp = 25C) + 001 = Cool + 010 = Dry (temp = 25C, but not shown) + 011 = Fan + 100 = Heat +*/ + +// Classes +class IRTecoAc { + public: + explicit IRTecoAc(const uint16_t pin); + + void stateReset(void); +#if SEND_TECO + void send(const uint16_t repeat = kTecoDefaultRepeat); +#endif // SEND_TECO + void begin(void); + void on(void); + void off(void); + + void setPower(const bool on); + bool getPower(void); + + void setTemp(const uint8_t temp); + uint8_t getTemp(void); + + void setFan(const uint8_t fan); + uint8_t getFan(void); + + void setMode(const uint8_t mode); + uint8_t getMode(void); + + void setSwing(const bool state); + bool getSwing(void); + + void setSleep(const bool state); + bool getSleep(void); + + // void setTimer(uint8_t time); // To check unit + // uint8_t getTimer(uint8_t); + + uint64_t getRaw(void); + void setRaw(const uint64_t new_code); + + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); +#ifdef ARDUINO + String toString(void); +#else + std::string toString(void); +#endif +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif + // The state of the IR remote in IR code form. + uint64_t remote_state; +}; + +#endif // IR_TECO_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Toshiba.cpp similarity index 86% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Toshiba.cpp index 817b5fbaa..a82a2fb24 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.cpp +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Toshiba.cpp @@ -89,9 +89,9 @@ void IRToshibaAC::begin() { _irsend.begin(); } #if SEND_TOSHIBA_AC // Send the current desired state to the IR LED. -void IRToshibaAC::send() { +void IRToshibaAC::send(const uint16_t repeat) { checksum(); // Ensure correct checksum before sending. - _irsend.sendToshibaAC(remote_state); + _irsend.sendToshibaAC(remote_state, kToshibaACStateLength, repeat); } #endif // SEND_TOSHIBA_AC @@ -233,6 +233,39 @@ void IRToshibaAC::setMode(uint8_t mode) { } } +// Convert a standard A/C mode into its native mode. +uint8_t IRToshibaAC::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kToshibaAcCool; + case stdAc::opmode_t::kHeat: + return kToshibaAcHeat; + case stdAc::opmode_t::kDry: + return kToshibaAcDry; + // No Fan mode. + default: + return kToshibaAcAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRToshibaAC::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + return kToshibaAcFanMax - 4; + case stdAc::fanspeed_t::kLow: + return kToshibaAcFanMax - 3; + case stdAc::fanspeed_t::kMedium: + return kToshibaAcFanMax - 2; + case stdAc::fanspeed_t::kHigh: + return kToshibaAcFanMax - 1; + case stdAc::fanspeed_t::kMax: + return kToshibaAcFanMax; + default: + return kToshibaAcFanAuto; + } +} + // Convert the internal state into a human readable string. #ifdef ARDUINO String IRToshibaAC::toString() { @@ -241,36 +274,39 @@ String IRToshibaAC::toString() { std::string IRToshibaAC::toString() { std::string result = ""; #endif // ARDUINO - result += "Power: "; + result += F("Power: "); if (getPower()) - result += "On"; + result += F("On"); else - result += "Off"; - result += ", Mode: " + uint64ToString(getMode()); + result += F("Off"); + result += F(", Mode: "); + result += uint64ToString(getMode()); switch (getMode()) { case kToshibaAcAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kToshibaAcCool: - result += " (COOL)"; + result += F(" (COOL)"); break; case kToshibaAcHeat: - result += " (HEAT)"; + result += F(" (HEAT)"); break; case kToshibaAcDry: - result += " (DRY)"; + result += F(" (DRY)"); break; default: - result += " (UNKNOWN)"; + result += F(" (UNKNOWN)"); } - result += ", Temp: " + uint64ToString(getTemp()) + "C"; - result += ", Fan: " + uint64ToString(getFan()); + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFan()); switch (getFan()) { case kToshibaAcFanAuto: - result += " (AUTO)"; + result += F(" (AUTO)"); break; case kToshibaAcFanMax: - result += " (MAX)"; + result += F(" (MAX)"); break; } return result; diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h b/lib/IRremoteESP8266-2.6.0/src/ir_Toshiba.h similarity index 90% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Toshiba.h index 1a1e6cdc8..03b461add 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Toshiba.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Toshiba.h @@ -11,6 +11,9 @@ #endif #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif // TTTTTTT OOOOO SSSSS HH HH IIIII BBBBB AAA // TTT OO OO SS HH HH III BB B AAAAA @@ -48,7 +51,7 @@ class IRToshibaAC { void stateReset(); #if SEND_TOSHIBA_AC - void send(); + void send(const uint16_t repeat = kToshibaACMinRepeat); #endif // SEND_TOSHIBA_AC void begin(); void on(); @@ -65,6 +68,8 @@ class IRToshibaAC { uint8_t* getRaw(); static bool validChecksum(const uint8_t state[], const uint16_t length = kToshibaACStateLength); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); #ifdef ARDUINO String toString(); #else @@ -73,13 +78,15 @@ class IRToshibaAC { #ifndef UNIT_TEST private: + IRsend _irsend; +#else + IRsendTest _irsend; #endif uint8_t remote_state[kToshibaACStateLength]; void checksum(const uint16_t length = kToshibaACStateLength); static uint8_t calcChecksum(const uint8_t state[], const uint16_t length = kToshibaACStateLength); uint8_t mode_state; - IRsend _irsend; }; #endif // IR_TOSHIBA_H_ diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Trotec.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Trotec.cpp new file mode 100644 index 000000000..b5c15e7fd --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Trotec.cpp @@ -0,0 +1,162 @@ +// Copyright 2017 stufisher + +#include "ir_Trotec.h" +#include +#include "IRremoteESP8266.h" +#include "IRutils.h" + +// Constants +const uint16_t kTrotecHdrMark = 5952; +const uint16_t kTrotecHdrSpace = 7364; +const uint16_t kTrotecOneMark = 592; +const uint16_t kTrotecOneSpace = 1560; +const uint16_t kTrotecZeroMark = 592; +const uint16_t kTrotecZeroSpace = 592; +const uint16_t kTrotecGap = 6184; +const uint16_t kTrotecGapEnd = 1500; // made up value + +#if SEND_TROTEC + +void IRsend::sendTrotec(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kTrotecStateLength) return; + + for (uint16_t r = 0; r <= repeat; r++) { + sendGeneric(kTrotecHdrMark, kTrotecHdrSpace, kTrotecOneMark, + kTrotecOneSpace, kTrotecZeroMark, kTrotecZeroSpace, + kTrotecOneMark, kTrotecGap, data, nbytes, 36, false, + 0, // Repeats handled elsewhere + 50); + // More footer + enableIROut(36); + mark(kTrotecOneMark); + space(kTrotecGapEnd); + } +} +#endif // SEND_TROTEC + +IRTrotecESP::IRTrotecESP(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRTrotecESP::begin() { _irsend.begin(); } + +#if SEND_TROTEC +void IRTrotecESP::send(const uint16_t repeat) { + checksum(); + _irsend.sendTrotec(remote_state, kTrotecStateLength, repeat); +} +#endif // SEND_TROTEC + +void IRTrotecESP::checksum() { + uint8_t sum = 0; + + for (uint8_t i = 2; i < 8; i++) sum += remote_state[i]; + remote_state[8] = sum & 0xFF; +} + +void IRTrotecESP::stateReset() { + for (uint8_t i = 2; i < kTrotecStateLength; i++) remote_state[i] = 0x0; + + remote_state[0] = kTrotecIntro1; + remote_state[1] = kTrotecIntro2; + + setPower(false); + setTemp(kTrotecDefTemp); + setSpeed(kTrotecFanMed); + setMode(kTrotecAuto); +} + +uint8_t* IRTrotecESP::getRaw() { + checksum(); + return remote_state; +} + +void IRTrotecESP::setPower(const bool on) { + if (on) + remote_state[2] |= kTrotecPowerBit; + else + remote_state[2] &= ~kTrotecPowerBit; +} + +bool IRTrotecESP::getPower() { return remote_state[2] & kTrotecPowerBit; } + +void IRTrotecESP::setSpeed(const uint8_t fan) { + uint8_t speed = std::min(fan, kTrotecFanHigh); + remote_state[2] = (remote_state[2] & 0b11001111) | (speed << 4); +} + +uint8_t IRTrotecESP::getSpeed() { return (remote_state[2] & 0b00110000) >> 4; } + +void IRTrotecESP::setMode(const uint8_t mode) { + switch (mode) { + case kTrotecAuto: + case kTrotecCool: + case kTrotecDry: + case kTrotecFan: + remote_state[2] = (remote_state[2] & 0b11111100) | mode; + return; + default: + this->setMode(kTrotecAuto); + } +} + +uint8_t IRTrotecESP::getMode() { return remote_state[2] & 0b00000011; } + +void IRTrotecESP::setTemp(const uint8_t celsius) { + uint8_t temp = std::max(celsius, kTrotecMinTemp); + temp = std::min(temp, kTrotecMaxTemp); + remote_state[3] = (remote_state[3] & 0x80) | (temp - kTrotecMinTemp); +} + +uint8_t IRTrotecESP::getTemp() { + return (remote_state[3] & 0b01111111) + kTrotecMinTemp; +} + +void IRTrotecESP::setSleep(bool sleep) { + if (sleep) + remote_state[3] |= kTrotecSleepBit; + else + remote_state[3] &= ~kTrotecSleepBit; +} + +bool IRTrotecESP::getSleep(void) { return remote_state[3] & kTrotecSleepBit; } + +void IRTrotecESP::setTimer(const uint8_t timer) { + if (timer) + remote_state[5] |= kTrotecTimerBit; + else + remote_state[5] &= ~kTrotecTimerBit; + remote_state[6] = (timer > kTrotecMaxTimer) ? kTrotecMaxTimer : timer; +} + +uint8_t IRTrotecESP::getTimer() { return remote_state[6]; } + +// Convert a standard A/C mode into its native mode. +uint8_t IRTrotecESP::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kTrotecCool; + case stdAc::opmode_t::kDry: + return kTrotecDry; + case stdAc::opmode_t::kFan: + return kTrotecFan; + // Note: No Heat mode. + default: + return kTrotecAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRTrotecESP::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kTrotecFanLow; + case stdAc::fanspeed_t::kMedium: + return kTrotecFanMed; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kTrotecFanHigh; + default: + return kTrotecFanMed; + } +} diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h b/lib/IRremoteESP8266-2.6.0/src/ir_Trotec.h similarity index 68% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h rename to lib/IRremoteESP8266-2.6.0/src/ir_Trotec.h index 040d9a722..dfbc26c07 100644 --- a/lib/IRremoteESP8266-2.5.2.03/src/ir_Trotec.h +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Trotec.h @@ -5,6 +5,9 @@ #include "IRremoteESP8266.h" #include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif // Constants // Byte 0 @@ -19,8 +22,7 @@ const uint8_t kTrotecCool = 1; const uint8_t kTrotecDry = 2; const uint8_t kTrotecFan = 3; -const uint8_t kTrotecOn = 1; -const uint8_t kTrotecOff = 0; +const uint8_t kTrotecPowerBit = 0b00001000; const uint8_t kTrotecFanLow = 1; const uint8_t kTrotecFanMed = 2; @@ -31,13 +33,12 @@ const uint8_t kTrotecMinTemp = 18; const uint8_t kTrotecDefTemp = 25; const uint8_t kTrotecMaxTemp = 32; -const uint8_t kTrotecSleepOn = 1; +const uint8_t kTrotecSleepBit = 0b10000000; // Byte 5 -const uint8_t kTrotecTimerOn = 1; +const uint8_t kTrotecTimerBit = 0b01000000; // Byte 6 -const uint8_t kTrotecMinTimer = 0; const uint8_t kTrotecMaxTimer = 23; // Legacy defines. (Deperecated) @@ -50,7 +51,6 @@ const uint8_t kTrotecMaxTimer = 23; #define TROTEC_FAN_HIGH kTrotecFanHigh #define TROTEC_MIN_TEMP kTrotecMinTemp #define TROTEC_MAX_TEMP kTrotecMaxTemp -#define TROTEC_MIN_TIMER kTrotecMinTimer #define TROTEC_MAX_TIMER kTrotecMaxTimer class IRTrotecESP { @@ -58,35 +58,42 @@ class IRTrotecESP { explicit IRTrotecESP(uint16_t pin); #if SEND_TROTEC - void send(); + void send(const uint16_t repeat = kTrotecDefaultRepeat); #endif // SEND_TROTEC void begin(); - void setPower(bool state); - uint8_t getPower(); + void setPower(const bool state); + bool getPower(); - void setTemp(uint8_t temp); + void setTemp(const uint8_t celsius); uint8_t getTemp(); - void setSpeed(uint8_t fan); + void setSpeed(const uint8_t fan); uint8_t getSpeed(); uint8_t getMode(); - void setMode(uint8_t mode); + void setMode(const uint8_t mode); bool getSleep(); void setSleep(bool sleep); uint8_t getTimer(); - void setTimer(uint8_t timer); + void setTimer(const uint8_t timer); uint8_t* getRaw(); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); +#ifndef UNIT_TEST + private: - uint8_t trotec[kTrotecStateLength]; + IRsend _irsend; +#else + IRsendTest _irsend; +#endif + uint8_t remote_state[kTrotecStateLength]; void stateReset(); void checksum(); - IRsend _irsend; }; #endif // IR_TROTEC_H_ diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Vestel.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Vestel.cpp new file mode 100644 index 000000000..1fbb822cf --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Vestel.cpp @@ -0,0 +1,583 @@ +// Copyright 2018 Erdem U. Altinyurt +// Copyright 2019 David Conran + +#include "ir_Vestel.h" +#include +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRutils.h" +#include "ir_Haier.h" + +// VV VV EEEEEEE SSSSS TTTTTTTT EEEEEEE LL +// VV VV EE S TT EE LL +// VV VV EEEEE SSSS TT EEEEE LL +// VV VV EE S TT EE LL +// VVV EEEEEEE SSSSS TT EEEEEEE LLLLLLL + +// Vestel added by Erdem U. Altinyurt + +// Equipment it seems compatible with: +// * Vestel AC Model BIOX CXP-9 (9K BTU) +// * + +// Ref: +// None. Totally reverse engineered. + +#if SEND_VESTEL_AC +// Send a Vestel message +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically kVestelBits. +// +// Status: STABLE / Working. +// +void IRsend::sendVestelAc(const uint64_t data, const uint16_t nbits, + const uint16_t repeat) { + if (nbits % 8 != 0) return; // nbits is required to be a multiple of 8. + + sendGeneric(kVestelAcHdrMark, kVestelAcHdrSpace, // Header + kVestelAcBitMark, kVestelAcOneSpace, // Data + kVestelAcBitMark, kVestelAcZeroSpace, // Data + kVestelAcBitMark, 100000, // Footer + repeat gap + data, nbits, 38, false, repeat, 50); +} +#endif + +// Code to emulate Vestel A/C IR remote control unit. + +// Initialise the object. +IRVestelAc::IRVestelAc(uint16_t pin) : _irsend(pin) { stateReset(); } + +// Reset the state of the remote to a known good state/sequence. +void IRVestelAc::stateReset() { + // Power On, Mode Auto, Fan Auto, Temp = 25C/77F + remote_state = kVestelAcStateDefault; + remote_time_state = kVestelAcTimeStateDefault; + use_time_state = false; +} + +// Configure the pin for output. +void IRVestelAc::begin() { + _irsend.begin(); +} + +#if SEND_VESTEL_AC +// Send the current desired state to the IR LED. +void IRVestelAc::send() { + checksum(); // Ensure correct checksum before sending. + uint64_t code_to_send; + if (use_time_state) + code_to_send = remote_time_state; + else + code_to_send = remote_state; + _irsend.sendVestelAc(code_to_send); +} +#endif // SEND_VESTEL_AC + +// Return the internal state date of the remote. +uint64_t IRVestelAc::getRaw() { + checksum(); + if (use_time_state) return remote_time_state; + return remote_state; +} + +// Override the internal state with the new state. +void IRVestelAc::setRaw(uint8_t* newState) { + uint64_t upState = 0; + for (int i = 0; i < 7; i++) + upState |= static_cast(newState[i]) << (i * 8); + this->setRaw(upState); +} + +void IRVestelAc::setRaw(const uint64_t newState) { + use_time_state = false; + remote_state = newState; + remote_time_state = newState; + if (this->isTimeCommand()) { + use_time_state = true; + remote_state = kVestelAcStateDefault; + } else { + remote_time_state = kVestelAcTimeStateDefault; + } +} + +// Set the requested power state of the A/C to on. +void IRVestelAc::on() { setPower(true); } + +// Set the requested power state of the A/C to off. +void IRVestelAc::off() { setPower(false); } + +// Set the requested power state of the A/C. +void IRVestelAc::setPower(const bool state) { + remote_state &= ~((uint64_t)0xF << kVestelAcPowerOffset); + if (state) + remote_state |= ((uint64_t)0xF << kVestelAcPowerOffset); + else + remote_state |= ((uint64_t)0xC << kVestelAcPowerOffset); + use_time_state = false; +} + +// Return the requested power state of the A/C. +bool IRVestelAc::getPower() { + return (remote_state >> kVestelAcPowerOffset == 0xF); +} + +// Set the temperature in Celsius degrees. +void IRVestelAc::setTemp(const uint8_t temp) { + uint8_t new_temp = temp; + new_temp = std::max(kVestelAcMinTempC, new_temp); + // new_temp = std::max(kVestelAcMinTempH, new_temp); Check MODE + new_temp = std::min(kVestelAcMaxTemp, new_temp); + remote_state &= ~((uint64_t)0xF << kVestelAcTempOffset); + remote_state |= (uint64_t)(new_temp - 16) << kVestelAcTempOffset; + use_time_state = false; +} + +// Return the set temperature. +uint8_t IRVestelAc::getTemp(void) { + return ((remote_state >> kVestelAcTempOffset) & 0xF) + 16; +} + +// Set the speed of the fan, +// 1-3 set the fan speed, 0 or anything else set it to auto. +void IRVestelAc::setFan(const uint8_t fan) { + switch (fan) { + case kVestelAcFanLow: + case kVestelAcFanMed: + case kVestelAcFanHigh: + case kVestelAcFanAutoCool: + case kVestelAcFanAutoHot: + case kVestelAcFanAuto: + remote_state &= ~((uint64_t)0xF << kVestelAcFanOffset); + remote_state |= (uint64_t)fan << kVestelAcFanOffset; + break; + default: + setFan(kVestelAcFanAuto); + } + use_time_state = false; +} + +// Return the requested state of the unit's fan. +uint8_t IRVestelAc::getFan() { + return (remote_state >> kVestelAcFanOffset) & 0xF; +} + +// Get the requested climate operation mode of the a/c unit. +// Returns: +// A uint8_t containing the A/C mode. +uint8_t IRVestelAc::getMode() { + return (remote_state >> kVestelAcModeOffset) & 0xF; +} + +// Set the requested climate operation mode of the a/c unit. +void IRVestelAc::setMode(const uint8_t mode) { + // If we get an unexpected mode, default to AUTO. + switch (mode) { + case kVestelAcAuto: + case kVestelAcCool: + case kVestelAcHeat: + case kVestelAcDry: + case kVestelAcFan: + remote_state &= ~((uint64_t)0xF << kVestelAcModeOffset); + remote_state |= (uint64_t)mode << kVestelAcModeOffset; + break; + default: + setMode(kVestelAcAuto); + } + use_time_state = false; +} + +// Set Auto mode of AC. +void IRVestelAc::setAuto(const int8_t autoLevel) { + if (autoLevel < -2 || autoLevel > 2) return; + setMode(kVestelAcAuto); + setFan((autoLevel < 0 ? kVestelAcFanAutoCool : kVestelAcFanAutoHot)); + if (autoLevel == 2) + setTemp(30); + else if (autoLevel == 1) + setTemp(31); + else if (autoLevel == 0) + setTemp(25); + else if (autoLevel == -1) + setTemp(16); + else if (autoLevel == -2) + setTemp(17); +} + +void IRVestelAc::setTimerActive(const bool on) { + if (on) // activation + remote_time_state |= ((uint64_t)1 << kVestelAcTimerFlagOffset); + else // deactivate + remote_time_state &= ~((uint64_t)1 << kVestelAcTimerFlagOffset); + use_time_state = true; +} + +bool IRVestelAc::isTimerActive(void) { + return (remote_time_state >> kVestelAcTimerFlagOffset) & 1; +} + +// Set Timer option of AC. +// Valid time arguments are 0, 0.5, 1, 2, 3 and 5 hours (in min). 0 disables the +// timer. +void IRVestelAc::setTimer(const uint16_t minutes) { + // Clear both On & Off timers. + remote_time_state &= ~((uint64_t)0xFFFF << kVestelAcOffTimeOffset); + // Set the "Off" time with the nr of minutes before we turn off. + remote_time_state |= (uint64_t)(((minutes / 60) << 3) + (minutes % 60) / 10) + << kVestelAcOffTimeOffset; + setOffTimerActive(false); + // Yes. On Timer instead of Off timer active. + setOnTimerActive(minutes != 0); + setTimerActive(minutes != 0); + use_time_state = true; +} + +uint16_t IRVestelAc::getTimer(void) { return getOffTimer(); } + +// Set the AC's internal clock +void IRVestelAc::setTime(const uint16_t minutes) { + remote_time_state &= ~((uint64_t)0x1F << kVestelAcHourOffset); + remote_time_state |= (uint64_t)((minutes / 60) & 0x1F) + << kVestelAcHourOffset; + remote_time_state &= ~((uint64_t)0xFF << kVestelAcMinuteOffset); + remote_time_state |= (uint64_t)((minutes % 60) & 0xFF) + << kVestelAcMinuteOffset; + use_time_state = true; +} + +uint16_t IRVestelAc::getTime(void) { + return ((remote_time_state >> kVestelAcHourOffset) & 0x1F) * 60 + + ((remote_time_state >> kVestelAcMinuteOffset) & 0xFF); +} + +void IRVestelAc::setOnTimerActive(const bool on) { + if (on) // activation + remote_time_state |= ((uint64_t)1 << kVestelAcOnTimerFlagOffset); + else // deactivate + remote_time_state &= ~((uint64_t)1 << kVestelAcOnTimerFlagOffset); + use_time_state = true; +} + +bool IRVestelAc::isOnTimerActive(void) { + return (remote_time_state >> kVestelAcOnTimerFlagOffset) & 1; +} + +// Set AC's wake up time. Takes time in minute. +void IRVestelAc::setOnTimer(const uint16_t minutes) { + remote_time_state &= ~((uint64_t)0xFF << kVestelAcOnTimeOffset); + remote_time_state |= (uint64_t)(((minutes / 60) << 3) + (minutes % 60) / 10) + << kVestelAcOnTimeOffset; + setOnTimerActive(minutes != 0); + setTimerActive(false); + use_time_state = true; +} + +uint16_t IRVestelAc::getOnTimer(void) { + uint8_t ontime = (remote_time_state >> kVestelAcOnTimeOffset) & 0xFF; + return (ontime >> 3) * 60 + (ontime & 0x7) * 10; +} + +void IRVestelAc::setOffTimerActive(const bool on) { + if (on) // activation + remote_time_state |= ((uint64_t)1 << kVestelAcOffTimerFlagOffset); + else // deactivate + remote_time_state &= ~((uint64_t)1 << kVestelAcOffTimerFlagOffset); + use_time_state = true; +} + +bool IRVestelAc::isOffTimerActive(void) { + return (remote_time_state >> kVestelAcOffTimerFlagOffset) & 1; +} + +// Set AC's turn off time. Takes time in minute. +void IRVestelAc::setOffTimer(const uint16_t minutes) { + remote_time_state &= ~((uint64_t)0xFF << kVestelAcOffTimeOffset); + remote_time_state |= + (uint64_t)((((minutes / 60) << 3) + (minutes % 60) / 10) & 0xFF) + << kVestelAcOffTimeOffset; + setOffTimerActive(minutes != 0); + setTimerActive(false); + use_time_state = true; +} + +uint16_t IRVestelAc::getOffTimer(void) { + uint8_t offtime = (remote_time_state >> kVestelAcOffTimeOffset) & 0xFF; + return (offtime >> 3) * 60 + (offtime & 0x7) * 10; +} + +// Set the Sleep state of the A/C. +void IRVestelAc::setSleep(const bool state) { + remote_state &= ~((uint64_t)0xF << kVestelAcTurboSleepOffset); + remote_state |= (uint64_t)(state ? kVestelAcSleep : kVestelAcNormal) + << kVestelAcTurboSleepOffset; + use_time_state = false; +} + +// Return the Sleep state of the A/C. +bool IRVestelAc::getSleep() { + return ((remote_state >> kVestelAcTurboSleepOffset) & 0xF) == kVestelAcSleep; +} + +// Set the Turbo state of the A/C. +void IRVestelAc::setTurbo(const bool state) { + remote_state &= ~((uint64_t)0xF << kVestelAcTurboSleepOffset); + remote_state |= (uint64_t)(state ? kVestelAcTurbo : kVestelAcNormal) + << kVestelAcTurboSleepOffset; + use_time_state = false; +} + +// Return the Turbo state of the A/C. +bool IRVestelAc::getTurbo() { + return ((remote_state >> kVestelAcTurboSleepOffset) & 0xF) == kVestelAcTurbo; +} + +// Set the Ion state of the A/C. +void IRVestelAc::setIon(const bool state) { + remote_state &= ~((uint64_t)0x1 << kVestelAcIonOffset); + + remote_state |= (uint64_t)(state ? 1 : 0) << kVestelAcIonOffset; + use_time_state = false; +} + +// Return the Ion state of the A/C. +bool IRVestelAc::getIon() { return (remote_state >> kVestelAcIonOffset) & 1; } + +// Set the Swing Roaming state of the A/C. +void IRVestelAc::setSwing(const bool state) { + remote_state &= ~((uint64_t)0xF << kVestelAcSwingOffset); + + remote_state |= (uint64_t)(state ? kVestelAcSwing : 0xF) + << kVestelAcSwingOffset; + use_time_state = false; +} + +// Return the Swing Roaming state of the A/C. +bool IRVestelAc::getSwing() { + return ((remote_state >> kVestelAcSwingOffset) & 0xF) == kVestelAcSwing; +} + +// Calculate the checksum for a given array. +// Args: +// state: The state to calculate the checksum over. +// Returns: +// The 8 bit checksum value. +uint8_t IRVestelAc::calcChecksum(const uint64_t state) { + // Just counts the set bits +1 on stream and take inverse after mask + uint8_t sum = 0; + uint64_t temp_state = state & kVestelAcCRCMask; + for (; temp_state; temp_state >>= 1) + if (temp_state & 1) sum++; + sum += 2; + sum = 0xff - sum; + return sum; +} + +// Verify the checksum is valid for a given state. +// Args: +// state: The state to verify the checksum of. +// Returns: +// A boolean. +bool IRVestelAc::validChecksum(const uint64_t state) { + return (((state >> kVestelAcChecksumOffset) & 0xFF) == calcChecksum(state)); +} + +// Calculate & set the checksum for the current internal state of the remote. +void IRVestelAc::checksum() { + // Stored the checksum value in the last byte. + remote_state &= ~((uint64_t)0xFF << kVestelAcChecksumOffset); + remote_state |= (uint64_t)calcChecksum(remote_state) + << kVestelAcChecksumOffset; + + remote_time_state &= ~((uint64_t)0xFF << kVestelAcChecksumOffset); + remote_time_state |= (uint64_t)calcChecksum(remote_time_state) + << kVestelAcChecksumOffset; +} + +bool IRVestelAc::isTimeCommand() { + return (remote_state >> kVestelAcPowerOffset == 0x00 || use_time_state); +} + + +// Convert a standard A/C mode into its native mode. +uint8_t IRVestelAc::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kVestelAcCool; + case stdAc::opmode_t::kHeat: + return kVestelAcHeat; + case stdAc::opmode_t::kDry: + return kVestelAcDry; + case stdAc::opmode_t::kFan: + return kVestelAcFan; + default: + return kVestelAcAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRVestelAc::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kVestelAcFanLow; + case stdAc::fanspeed_t::kMedium: + return kVestelAcFanMed; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kVestelAcFanHigh; + default: + return kVestelAcFanAuto; + } +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRVestelAc::toString() { + String result = ""; +#else +std::string IRVestelAc::toString() { + std::string result = ""; +#endif // ARDUINO + if (isTimeCommand()) { + result += F("Time: "); + result += IRHaierAC::timeToString(getTime()); + + result += F(", Timer: "); + result += isTimerActive() ? IRHaierAC::timeToString(getTimer()) : F("Off"); + + result += F(", On Timer: "); + result += (isOnTimerActive() && !isTimerActive()) + ? IRHaierAC::timeToString(getOnTimer()) + : F("Off"); + + result += F(", Off Timer: "); + result += + isOffTimerActive() ? IRHaierAC::timeToString(getOffTimer()) : F("Off"); + return result; + } + // Not a time command, it's a normal command. + result += F("Power: "); + result += (getPower() ? F("On") : F("Off")); + result += F(", Mode: "); + result += uint64ToString(getMode()); + switch (getMode()) { + case kVestelAcAuto: + result += F(" (AUTO)"); + break; + case kVestelAcCool: + result += F(" (COOL)"); + break; + case kVestelAcHeat: + result += F(" (HEAT)"); + break; + case kVestelAcDry: + result += F(" (DRY)"); + break; + case kVestelAcFan: + result += F(" (FAN)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFan()); + switch (getFan()) { + case kVestelAcFanAuto: + result += F(" (AUTO)"); + break; + case kVestelAcFanLow: + result += F(" (LOW)"); + break; + case kVestelAcFanMed: + result += F(" (MEDIUM)"); + break; + case kVestelAcFanHigh: + result += F(" (HIGH)"); + break; + case kVestelAcFanAutoCool: + result += F(" (AUTO COOL)"); + break; + case kVestelAcFanAutoHot: + result += F(" (AUTO HOT)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Sleep: "); + result += (getSleep() ? F("On") : F("Off")); + result += F(", Turbo: "); + result += (getTurbo() ? F("On") : F("Off")); + result += F(", Ion: "); + result += (getIon() ? F("On") : F("Off")); + result += F(", Swing: "); + result += (getSwing() ? F("On") : F("Off")); + return result; +} + +#if DECODE_VESTEL_AC +// Decode the supplied Vestel message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kVestelBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Alpha / Needs testing against a real device. +// +bool IRrecv::decodeVestelAc(decode_results* results, uint16_t nbits, + bool strict) { + if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. + return false; + + if (strict) + if (nbits != kVestelAcBits) + return false; // Not strictly a Vestel AC message. + + uint64_t data = 0; + uint16_t offset = kStartOffset; + + if (nbits > sizeof(data) * 8) + return false; // We can't possibly capture a Vestel packet that big. + + // Header + if (!matchMark(results->rawbuf[offset++], kVestelAcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kVestelAcHdrSpace)) return false; + + // Data (Normal) + match_result_t data_result = + matchData(&(results->rawbuf[offset]), nbits, kVestelAcBitMark, + kVestelAcOneSpace, kVestelAcBitMark, kVestelAcZeroSpace, + kVestelAcTolerance, kMarkExcess, false); + + if (data_result.success == false) return false; + offset += data_result.used; + data = data_result.data; + + // Footer + if (!matchMark(results->rawbuf[offset++], kVestelAcBitMark)) return false; + + // Compliance + if (strict) + if (!IRVestelAc::validChecksum(data_result.data)) return false; + + // Success + results->decode_type = VESTEL_AC; + results->bits = nbits; + results->value = data; + results->address = 0; + results->command = 0; + + return true; +} +#endif // DECODE_VESTEL_AC diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Vestel.h b/lib/IRremoteESP8266-2.6.0/src/ir_Vestel.h new file mode 100644 index 000000000..ab04e8b35 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Vestel.h @@ -0,0 +1,177 @@ +// Copyright 2018 Erdem U. Altinyurt +// Copyright 2019 David Conran + +#ifndef IR_VESTEL_H_ +#define IR_VESTEL_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifdef ARDUINO +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + +// VV VV EEEEEEE SSSSS TTTTTTTT EEEEEEE LL +// VV VV EE S TT EE LL +// VV VV EEEEE SSSS TT EEEEE LL +// VV VV EE S TT EE LL +// VVV EEEEEEE SSSSS TT EEEEEEE LLLLLLL + +// Vestel added by Erdem U. Altinyurt + +// Structure of a Command message (56 bits) +// Signature: 12 bits. e.g. 0x201 +// Checksum: 8 bits +// Swing: 4 bits. (auto 0xA, stop 0xF) +// turbo_sleep_normal: 4bits. (normal 0x1, sleep 0x3, turbo 0x7) +// Unused: 8 bits. (0x00) +// Temperature: 4 bits. (Celcius, but offset by -16 degrees. e.g. 0x0 = 16C) +// Fan Speed: 4 bits (auto 0x1, low 0x5, mid 0x9, high 0xB, 0xD auto hot, +// 0xC auto cool) +// Mode: 3 bits. (auto 0x0, cold 0x1, dry 0x2, fan 0x3, hot 0x4) +// unknown/unused: 6 bits. +// Ion flag: 1 bit. +// unknown/unused: 1 bit. +// Power/message type: 4 bits. (on 0xF, off 0xC, 0x0 == Timer mesage) +// +// Structure of a Time(r) message (56 bits) +// Signature: 12 bits. e.g. 0x201 +// Checksum: 8 bits +// Off Minutes: 3 bits. (Stored in 10 min increments. eg. xx:20 is 0x2) +// Off Hours: 5 bits. (0x17 == 11PM / 23:00) +// On Minutes: 3 bits. (Stored in 10 min increments. eg. xx:20 is 0x2) +// On Hours: 5 bits. (0x9 == 9AM / 09:00) +// Clock Hours: 5 bits. +// On Timer flag: 1 bit. +// Off Timer flag: 1 bit. +// Timer mode flag: 1 bit. (Off after X many hours/mins, not at clock time.) +// Clock Minutes: 8 bits. (0-59) +// Power/message type: 4 bits. (0x0 == Timer mesage, else see Comman message) + +// Constants +const uint16_t kVestelAcHdrMark = 3110; +const uint16_t kVestelAcHdrSpace = 9066; +const uint16_t kVestelAcBitMark = 520; +const uint16_t kVestelAcOneSpace = 1535; +const uint16_t kVestelAcZeroSpace = 480; +const uint16_t kVestelAcTolerance = 30; + +const uint8_t kVestelAcMinTempH = 16; +const uint8_t kVestelAcMinTempC = 18; +const uint8_t kVestelAcMaxTemp = 30; + +const uint64_t kVestelAcCRCMask = 0xFFFFFFFFFFF00000; + +const uint8_t kVestelAcAuto = 0; +const uint8_t kVestelAcCool = 1; +const uint8_t kVestelAcDry = 2; +const uint8_t kVestelAcFan = 3; +const uint8_t kVestelAcHeat = 4; + +const uint8_t kVestelAcFanAuto = 1; +const uint8_t kVestelAcFanLow = 5; +const uint8_t kVestelAcFanMed = 9; +const uint8_t kVestelAcFanHigh = 0xB; +const uint8_t kVestelAcFanAutoCool = 0xC; +const uint8_t kVestelAcFanAutoHot = 0xD; + +const uint8_t kVestelAcNormal = 1; +const uint8_t kVestelAcSleep = 3; +const uint8_t kVestelAcTurbo = 7; +const uint8_t kVestelAcIon = 4; +const uint8_t kVestelAcSwing = 0xA; + +const uint8_t kVestelAcChecksumOffset = 12; +const uint8_t kVestelAcSwingOffset = 20; +const uint8_t kVestelAcTurboSleepOffset = 24; +const uint8_t kVestelAcTempOffset = 36; +const uint8_t kVestelAcFanOffset = 40; +const uint8_t kVestelAcModeOffset = 44; +const uint8_t kVestelAcIonOffset = 50; +const uint8_t kVestelAcPowerOffset = 52; +const uint8_t kVestelAcOffTimeOffset = 20; +const uint8_t kVestelAcOnTimeOffset = 28; +const uint8_t kVestelAcHourOffset = 36; // 5 bits +const uint8_t kVestelAcOnTimerFlagOffset = kVestelAcHourOffset + 5; +const uint8_t kVestelAcOffTimerFlagOffset = kVestelAcHourOffset + 6; +const uint8_t kVestelAcTimerFlagOffset = kVestelAcHourOffset + 7; +const uint8_t kVestelAcMinuteOffset = 44; + +const uint64_t kVestelAcStateDefault = 0x0F00D9001FEF201ULL; +const uint64_t kVestelAcTimeStateDefault = 0x201ULL; + +class IRVestelAc { + public: + explicit IRVestelAc(uint16_t pin); + + void stateReset(); +#if SEND_VESTEL_AC + void send(); +#endif // SEND_VESTEL_AC + void begin(void); + void on(void); + void off(void); + void setPower(const bool state); + bool getPower(); + void setAuto(const int8_t autoLevel); + void setTimer(const uint16_t minutes); + uint16_t getTimer(void); + void setTime(const uint16_t minutes); + uint16_t getTime(void); + void setOnTimer(const uint16_t minutes); + uint16_t getOnTimer(void); + void setOffTimer(const uint16_t minutes); + uint16_t getOffTimer(void); + void setTemp(const uint8_t temp); + uint8_t getTemp(void); + void setFan(const uint8_t fan); + uint8_t getFan(void); + void setMode(const uint8_t mode); + uint8_t getMode(void); + void setRaw(uint8_t* newState); + void setRaw(const uint64_t newState); + uint64_t getRaw(void); + static bool validChecksum(const uint64_t state); + void setSwing(const bool state); + bool getSwing(void); + void setSleep(const bool state); + bool getSleep(void); + void setTurbo(const bool state); + bool getTurbo(void); + void setIon(const bool state); + bool getIon(void); + bool isTimeCommand(void); + bool isOnTimerActive(void); + void setOnTimerActive(const bool on); + bool isOffTimerActive(void); + void setOffTimerActive(const bool on); + bool isTimerActive(void); + void setTimerActive(const bool on); + static uint8_t calcChecksum(const uint64_t state); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif + uint64_t remote_state; + uint64_t remote_time_state; + bool use_time_state; + void checksum(); +}; + +#endif // IR_VESTEL_H_ diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.cpp new file mode 100644 index 000000000..048c1a1eb --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.cpp @@ -0,0 +1,671 @@ +// Copyright 2018 David Conran +// +// Code to emulate Whirlpool protocol compatible devices. +// Should be compatible with: +// * SPIS409L, SPIS412L, SPIW409L, SPIW412L, SPIW418L +// Remotes: +// * DG11J1-3A / DG11J1-04 +// * DG11J1-91 +// +// Note: Smart, iFeel, AroundU, PowerSave, & Silent modes are unsupported. +// Advanced 6thSense, Dehumidify, & Sleep modes are not supported. +// FYI: +// Dim == !Light +// Jet == Super == Turbo +// + +#include "ir_Whirlpool.h" +#include +#ifndef ARDUINO +#include +#endif +#include "IRrecv.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRutils.h" + +// WW WW HH HH IIIII RRRRRR LL PPPPPP OOOOO OOOOO LL +// WW WW HH HH III RR RR LL PP PP OO OO OO OO LL +// WW W WW HHHHHHH III RRRRRR LL PPPPPP OO OO OO OO LL +// WW WWW WW HH HH III RR RR LL PP OO OO OO OO LL +// WW WW HH HH IIIII RR RR LLLLLLL PP OOOO0 OOOO0 LLLLLLL + +// Constants +// Ref: https://github.com/markszabo/IRremoteESP8266/issues/509 +const uint16_t kWhirlpoolAcHdrMark = 8950; +const uint16_t kWhirlpoolAcHdrSpace = 4484; +const uint16_t kWhirlpoolAcBitMark = 597; +const uint16_t kWhirlpoolAcOneSpace = 1649; +const uint16_t kWhirlpoolAcZeroSpace = 533; +const uint16_t kWhirlpoolAcGap = 7920; +const uint32_t kWhirlpoolAcMinGap = kDefaultMessageGap; // Just a guess. +const uint8_t kWhirlpoolAcSections = 3; + +#if SEND_WHIRLPOOL_AC +// Send a Whirlpool A/C message. +// +// Args: +// data: An array of bytes containing the IR command. +// nbytes: Nr. of bytes of data in the array. (>=kWhirlpoolAcStateLength) +// repeat: Nr. of times the message is to be repeated. (Default = 0). +// +// Status: ALPHA / Untested. +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/509 +void IRsend::sendWhirlpoolAC(unsigned char data[], uint16_t nbytes, + uint16_t repeat) { + if (nbytes < kWhirlpoolAcStateLength) + return; // Not enough bytes to send a proper message. + for (uint16_t r = 0; r <= repeat; r++) { + // Section 1 + sendGeneric(kWhirlpoolAcHdrMark, kWhirlpoolAcHdrSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcOneSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, kWhirlpoolAcGap, + data, 6, // 6 bytes == 48 bits + 38000, // Complete guess of the modulation frequency. + false, 0, 50); + // Section 2 + sendGeneric(0, 0, kWhirlpoolAcBitMark, kWhirlpoolAcOneSpace, + kWhirlpoolAcBitMark, kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcGap, data + 6, 8, // 8 bytes == 64 bits + 38000, // Complete guess of the modulation frequency. + false, 0, 50); + // Section 3 + sendGeneric(0, 0, kWhirlpoolAcBitMark, kWhirlpoolAcOneSpace, + kWhirlpoolAcBitMark, kWhirlpoolAcZeroSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcMinGap, data + 14, 7, // 7 bytes == 56 bits + 38000, // Complete guess of the modulation frequency. + false, 0, 50); + } +} +#endif // SEND_WHIRLPOOL_AC + +// Class for emulating a Whirlpool A/C remote. +// Decoding help from: +// @redmusicxd, @josh929800, @raducostea + +IRWhirlpoolAc::IRWhirlpoolAc(uint16_t pin) : _irsend(pin) { stateReset(); } + +void IRWhirlpoolAc::stateReset() { + for (uint8_t i = 2; i < kWhirlpoolAcStateLength; i++) remote_state[i] = 0x0; + remote_state[0] = 0x83; + remote_state[1] = 0x06; + remote_state[6] = 0x80; + _setTemp(kWhirlpoolAcAutoTemp); // Default to a sane value. +} + +void IRWhirlpoolAc::begin() { _irsend.begin(); } + +bool IRWhirlpoolAc::validChecksum(uint8_t state[], const uint16_t length) { + if (length > kWhirlpoolAcChecksumByte1 && + state[kWhirlpoolAcChecksumByte1] != + xorBytes(state + 2, kWhirlpoolAcChecksumByte1 - 1 - 2)) { + DPRINTLN("DEBUG: First Whirlpool AC checksum failed."); + return false; + } + if (length > kWhirlpoolAcChecksumByte2 && + state[kWhirlpoolAcChecksumByte2] != + xorBytes(state + kWhirlpoolAcChecksumByte1 + 1, + kWhirlpoolAcChecksumByte2 - kWhirlpoolAcChecksumByte1 - 1)) { + DPRINTLN("DEBUG: Second Whirlpool AC checksum failed."); + return false; + } + // State is too short to have a checksum or everything checked out. + return true; +} + +// Update the checksum for the internal state. +void IRWhirlpoolAc::checksum(uint16_t length) { + if (length >= kWhirlpoolAcChecksumByte1) + remote_state[kWhirlpoolAcChecksumByte1] = + xorBytes(remote_state + 2, kWhirlpoolAcChecksumByte1 - 1 - 2); + if (length >= kWhirlpoolAcChecksumByte2) + remote_state[kWhirlpoolAcChecksumByte2] = + xorBytes(remote_state + kWhirlpoolAcChecksumByte1 + 1, + kWhirlpoolAcChecksumByte2 - kWhirlpoolAcChecksumByte1 - 1); +} + +#if SEND_WHIRLPOOL_AC +void IRWhirlpoolAc::send(const uint16_t repeat, const bool calcchecksum) { + if (calcchecksum) checksum(); + _irsend.sendWhirlpoolAC(remote_state, kWhirlpoolAcStateLength, repeat); +} +#endif // SEND_WHIRLPOOL_AC + +uint8_t *IRWhirlpoolAc::getRaw(const bool calcchecksum) { + if (calcchecksum) checksum(); + return remote_state; +} + +void IRWhirlpoolAc::setRaw(const uint8_t new_code[], const uint16_t length) { + for (uint8_t i = 0; i < length && i < kWhirlpoolAcStateLength; i++) + remote_state[i] = new_code[i]; +} + +whirlpool_ac_remote_model_t IRWhirlpoolAc::getModel() { + if (remote_state[kWhirlpoolAcAltTempPos] & kWhirlpoolAcAltTempMask) + return DG11J191; + else + return DG11J13A; +} + +void IRWhirlpoolAc::setModel(const whirlpool_ac_remote_model_t model) { + switch (model) { + case DG11J191: + remote_state[kWhirlpoolAcAltTempPos] |= kWhirlpoolAcAltTempMask; + break; + case DG11J13A: + // FALL THRU + default: + remote_state[kWhirlpoolAcAltTempPos] &= ~kWhirlpoolAcAltTempMask; + } + _setTemp(_desiredtemp); // Different models have different temp values. +} + +// Return the temp. offset in deg C for the current model. +int8_t IRWhirlpoolAc::getTempOffset() { + switch (getModel()) { + case DG11J191: + return -2; + break; + default: + return 0; + } +} + +// Set the temp. in deg C +void IRWhirlpoolAc::_setTemp(const uint8_t temp, const bool remember) { + if (remember) _desiredtemp = temp; + int8_t offset = getTempOffset(); // Cache the min temp for the model. + uint8_t newtemp = std::max((uint8_t)(kWhirlpoolAcMinTemp + offset), temp); + newtemp = std::min((uint8_t)(kWhirlpoolAcMaxTemp + offset), newtemp); + remote_state[kWhirlpoolAcTempPos] = + (remote_state[kWhirlpoolAcTempPos] & ~kWhirlpoolAcTempMask) | + ((newtemp - (kWhirlpoolAcMinTemp + offset)) << 4); +} + +// Set the temp. in deg C +void IRWhirlpoolAc::setTemp(const uint8_t temp) { + _setTemp(temp); + setSuper(false); // Changing temp cancels Super/Jet mode. + setCommand(kWhirlpoolAcCommandTemp); +} + +// Return the set temp. in deg C +uint8_t IRWhirlpoolAc::getTemp() { + return ((remote_state[kWhirlpoolAcTempPos] & kWhirlpoolAcTempMask) >> 4) + + + kWhirlpoolAcMinTemp + getTempOffset(); +} + +void IRWhirlpoolAc::_setMode(const uint8_t mode) { + switch (mode) { + case kWhirlpoolAcAuto: + setFan(kWhirlpoolAcFanAuto); + _setTemp(kWhirlpoolAcAutoTemp, false); + setSleep(false); // Cancel sleep mode when in auto/6thsense mode. + // FALL THRU + case kWhirlpoolAcHeat: + case kWhirlpoolAcCool: + case kWhirlpoolAcDry: + case kWhirlpoolAcFan: + remote_state[kWhirlpoolAcModePos] &= ~kWhirlpoolAcModeMask; + remote_state[kWhirlpoolAcModePos] |= mode; + setCommand(kWhirlpoolAcCommandMode); + break; + default: + return; + } + if (mode == kWhirlpoolAcAuto) setCommand(kWhirlpoolAcCommand6thSense); +} + +void IRWhirlpoolAc::setMode(const uint8_t mode) { + setSuper(false); // Changing mode cancels Super/Jet mode. + _setMode(mode); +} + +uint8_t IRWhirlpoolAc::getMode() { + return remote_state[kWhirlpoolAcModePos] & kWhirlpoolAcModeMask; +} + +void IRWhirlpoolAc::setFan(const uint8_t speed) { + switch (speed) { + case kWhirlpoolAcFanAuto: + case kWhirlpoolAcFanLow: + case kWhirlpoolAcFanMedium: + case kWhirlpoolAcFanHigh: + remote_state[kWhirlpoolAcFanPos] = + (remote_state[kWhirlpoolAcFanPos] & ~kWhirlpoolAcFanMask) | speed; + setSuper(false); // Changing fan speed cancels Super/Jet mode. + setCommand(kWhirlpoolAcCommandFanSpeed); + break; + } +} + +uint8_t IRWhirlpoolAc::getFan() { + return remote_state[kWhirlpoolAcFanPos] & kWhirlpoolAcFanMask; +} + +void IRWhirlpoolAc::setSwing(const bool on) { + if (on) { + remote_state[kWhirlpoolAcFanPos] |= kWhirlpoolAcSwing1Mask; + remote_state[kWhirlpoolAcOffTimerPos] |= kWhirlpoolAcSwing2Mask; + } else { + remote_state[kWhirlpoolAcFanPos] &= ~kWhirlpoolAcSwing1Mask; + remote_state[kWhirlpoolAcOffTimerPos] &= ~kWhirlpoolAcSwing2Mask; + } + setCommand(kWhirlpoolAcCommandSwing); +} + +bool IRWhirlpoolAc::getSwing() { + return (remote_state[kWhirlpoolAcFanPos] & kWhirlpoolAcSwing1Mask) && + (remote_state[kWhirlpoolAcOffTimerPos] & kWhirlpoolAcSwing2Mask); +} + +void IRWhirlpoolAc::setLight(const bool on) { + if (on) + remote_state[kWhirlpoolAcClockPos] &= ~kWhirlpoolAcLightMask; + else + remote_state[kWhirlpoolAcClockPos] |= kWhirlpoolAcLightMask; +} + +bool IRWhirlpoolAc::getLight() { + return !(remote_state[kWhirlpoolAcClockPos] & kWhirlpoolAcLightMask); +} + +void IRWhirlpoolAc::setTime(const uint16_t pos, + const uint16_t minspastmidnight) { + // Hours + remote_state[pos] &= ~kWhirlpoolAcHourMask; + remote_state[pos] |= (minspastmidnight / 60) % 24; + // Minutes + remote_state[pos + 1] &= ~kWhirlpoolAcMinuteMask; + remote_state[pos + 1] |= minspastmidnight % 60; +} + +uint16_t IRWhirlpoolAc::getTime(const uint16_t pos) { + return (remote_state[pos] & kWhirlpoolAcHourMask) * 60 + + (remote_state[pos + 1] & kWhirlpoolAcMinuteMask); +} + +bool IRWhirlpoolAc::isTimerEnabled(const uint16_t pos) { + return remote_state[pos - 1] & kWhirlpoolAcTimerEnableMask; +} + +void IRWhirlpoolAc::enableTimer(const uint16_t pos, const bool state) { + if (state) + remote_state[pos - 1] |= kWhirlpoolAcTimerEnableMask; + else + remote_state[pos - 1] &= ~kWhirlpoolAcTimerEnableMask; +} + +void IRWhirlpoolAc::setClock(const uint16_t minspastmidnight) { + setTime(kWhirlpoolAcClockPos, minspastmidnight); +} + +uint16_t IRWhirlpoolAc::getClock() { return getTime(kWhirlpoolAcClockPos); } + +void IRWhirlpoolAc::setOffTimer(const uint16_t minspastmidnight) { + setTime(kWhirlpoolAcOffTimerPos, minspastmidnight); +} + +uint16_t IRWhirlpoolAc::getOffTimer() { + return getTime(kWhirlpoolAcOffTimerPos); +} + +bool IRWhirlpoolAc::isOffTimerEnabled() { + return isTimerEnabled(kWhirlpoolAcOffTimerPos); +} + +void IRWhirlpoolAc::enableOffTimer(const bool state) { + enableTimer(kWhirlpoolAcOffTimerPos, state); + setCommand(kWhirlpoolAcCommandOffTimer); +} + +void IRWhirlpoolAc::setOnTimer(const uint16_t minspastmidnight) { + setTime(kWhirlpoolAcOnTimerPos, minspastmidnight); +} + +uint16_t IRWhirlpoolAc::getOnTimer() { return getTime(kWhirlpoolAcOnTimerPos); } + +bool IRWhirlpoolAc::isOnTimerEnabled() { + return isTimerEnabled(kWhirlpoolAcOnTimerPos); +} + +void IRWhirlpoolAc::enableOnTimer(const bool state) { + enableTimer(kWhirlpoolAcOnTimerPos, state); + setCommand(kWhirlpoolAcCommandOnTimer); +} + +void IRWhirlpoolAc::setPowerToggle(const bool on) { + if (on) + remote_state[kWhirlpoolAcPowerTogglePos] |= kWhirlpoolAcPowerToggleMask; + else + remote_state[kWhirlpoolAcPowerTogglePos] &= ~kWhirlpoolAcPowerToggleMask; + setSuper(false); // Changing power cancels Super/Jet mode. + setCommand(kWhirlpoolAcCommandPower); +} + +bool IRWhirlpoolAc::getPowerToggle() { + return remote_state[kWhirlpoolAcPowerTogglePos] & kWhirlpoolAcPowerToggleMask; +} + +uint8_t IRWhirlpoolAc::getCommand() { + return remote_state[kWhirlpoolAcCommandPos]; +} + +void IRWhirlpoolAc::setSleep(const bool on) { + if (on) { + remote_state[kWhirlpoolAcSleepPos] |= kWhirlpoolAcSleepMask; + setFan(kWhirlpoolAcFanLow); + } else { + remote_state[kWhirlpoolAcSleepPos] &= ~kWhirlpoolAcSleepMask; + } + setCommand(kWhirlpoolAcCommandSleep); +} + +bool IRWhirlpoolAc::getSleep() { + return remote_state[kWhirlpoolAcSleepPos] & kWhirlpoolAcSleepMask; +} + +// AKA Jet/Turbo mode. +void IRWhirlpoolAc::setSuper(const bool on) { + if (on) { + setFan(kWhirlpoolAcFanHigh); + switch (getMode()) { + case kWhirlpoolAcHeat: + setTemp(kWhirlpoolAcMaxTemp + getTempOffset()); + break; + case kWhirlpoolAcCool: + default: + setTemp(kWhirlpoolAcMinTemp + getTempOffset()); + setMode(kWhirlpoolAcCool); + break; + } + remote_state[kWhirlpoolAcSuperPos] |= kWhirlpoolAcSuperMask; + } else { + remote_state[kWhirlpoolAcSuperPos] &= ~kWhirlpoolAcSuperMask; + } + setCommand(kWhirlpoolAcCommandSuper); +} + +bool IRWhirlpoolAc::getSuper() { + return remote_state[kWhirlpoolAcSuperPos] & kWhirlpoolAcSuperMask; +} + +void IRWhirlpoolAc::setCommand(const uint8_t code) { + remote_state[kWhirlpoolAcCommandPos] = code; +} + +// Convert a standard A/C mode into its native mode. +uint8_t IRWhirlpoolAc::convertMode(const stdAc::opmode_t mode) { + switch (mode) { + case stdAc::opmode_t::kCool: + return kWhirlpoolAcCool; + case stdAc::opmode_t::kHeat: + return kWhirlpoolAcHeat; + case stdAc::opmode_t::kDry: + return kWhirlpoolAcDry; + case stdAc::opmode_t::kFan: + return kWhirlpoolAcFan; + default: + return kWhirlpoolAcAuto; + } +} + +// Convert a standard A/C Fan speed into its native fan speed. +uint8_t IRWhirlpoolAc::convertFan(const stdAc::fanspeed_t speed) { + switch (speed) { + case stdAc::fanspeed_t::kMin: + case stdAc::fanspeed_t::kLow: + return kWhirlpoolAcFanLow; + case stdAc::fanspeed_t::kMedium: + return kWhirlpoolAcFanMedium; + case stdAc::fanspeed_t::kHigh: + case stdAc::fanspeed_t::kMax: + return kWhirlpoolAcFanHigh; + default: + return kWhirlpoolAcFanAuto; + } +} + +#ifdef ARDUINO +String IRWhirlpoolAc::timeToString(const uint16_t minspastmidnight) { + String result = ""; +#else +std::string IRWhirlpoolAc::timeToString(const uint16_t minspastmidnight) { + std::string result = ""; +#endif // ARDUINO + uint8_t hours = minspastmidnight / 60; + if (hours < 10) result += '0'; + result += uint64ToString(hours); + result += ':'; + uint8_t mins = minspastmidnight % 60; + if (mins < 10) result += '0'; + result += uint64ToString(mins); + return result; +} + +// Convert the internal state into a human readable string. +#ifdef ARDUINO +String IRWhirlpoolAc::toString() { + String result = ""; +#else +std::string IRWhirlpoolAc::toString() { + std::string result = ""; +#endif // ARDUINO + result += F("Model: "); + result += uint64ToString(getModel()); + switch (getModel()) { + case DG11J191: + result += F(" (DG11J191)"); + break; + case DG11J13A: + result += F(" (DG11J13A)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Power toggle: "); + if (getPowerToggle()) + result += F("On"); + else + result += F("Off"); + result += F(", Mode: "); + result += uint64ToString(getMode()); + switch (getMode()) { + case kWhirlpoolAcHeat: + result += F(" (HEAT)"); + break; + case kWhirlpoolAcAuto: + result += F(" (AUTO)"); + break; + case kWhirlpoolAcCool: + result += F(" (COOL)"); + break; + case kWhirlpoolAcDry: + result += F(" (DRY)"); + break; + case kWhirlpoolAcFan: + result += F(" (FAN)"); + break; + default: + result += F(" (UNKNOWN)"); + } + result += F(", Temp: "); + result += uint64ToString(getTemp()); + result += F("C, Fan: "); + result += uint64ToString(getFan()); + switch (getFan()) { + case kWhirlpoolAcFanAuto: + result += F(" (AUTO)"); + break; + case kWhirlpoolAcFanHigh: + result += F(" (HIGH)"); + break; + case kWhirlpoolAcFanMedium: + result += F(" (MEDIUM)"); + break; + case kWhirlpoolAcFanLow: + result += F(" (LOW)"); + break; + default: + result += F(" (UNKNOWN)"); + break; + } + result += F(", Swing: "); + if (getSwing()) + result += F("On"); + else + result += F("Off"); + result += F(", Light: "); + if (getLight()) + result += F("On"); + else + result += F("Off"); + result += F(", Clock: "); + result += timeToString(getClock()); + result += F(", On Timer: "); + if (isOnTimerEnabled()) + result += timeToString(getOnTimer()); + else + result += F("Off"); + result += F(", Off Timer: "); + if (isOffTimerEnabled()) + result += timeToString(getOffTimer()); + else + result += F("Off"); + result += F(", Sleep: "); + if (getSleep()) + result += F("On"); + else + result += F("Off"); + result += F(", Super: "); + if (getSuper()) + result += F("On"); + else + result += F("Off"); + result += F(", Command: "); + result += uint64ToString(getCommand()); + switch (getCommand()) { + case kWhirlpoolAcCommandLight: + result += F(" (LIGHT)"); + break; + case kWhirlpoolAcCommandPower: + result += F(" (POWER)"); + break; + case kWhirlpoolAcCommandTemp: + result += F(" (TEMP)"); + break; + case kWhirlpoolAcCommandSleep: + result += F(" (SLEEP)"); + break; + case kWhirlpoolAcCommandSuper: + result += F(" (SUPER)"); + break; + case kWhirlpoolAcCommandOnTimer: + result += F(" (ONTIMER)"); + break; + case kWhirlpoolAcCommandMode: + result += F(" (MODE)"); + break; + case kWhirlpoolAcCommandSwing: + result += F(" (SWING)"); + break; + case kWhirlpoolAcCommandIFeel: + result += F(" (IFEEL)"); + break; + case kWhirlpoolAcCommandFanSpeed: + result += F(" (FANSPEED)"); + break; + case kWhirlpoolAcCommand6thSense: + result += F(" (6THSENSE)"); + break; + case kWhirlpoolAcCommandOffTimer: + result += F(" (OFFTIMER)"); + break; + default: + result += F(" (UNKNOWN)"); + break; + } + return result; +} + +#if DECODE_WHIRLPOOL_AC +// Decode the supplied Whirlpool A/C message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: The number of data bits to expect. Typically kWhirlpoolAcBits +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE / Working as intended. +// +// +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/509 +bool IRrecv::decodeWhirlpoolAC(decode_results *results, uint16_t nbits, + bool strict) { + if (results->rawlen < 2 * nbits + 4 + kHeader + kFooter - 1) + return false; // Can't possibly be a valid Whirlpool A/C message. + if (strict) { + if (nbits != kWhirlpoolAcBits) return false; + } + + uint16_t offset = kStartOffset; + uint16_t dataBitsSoFar = 0; + uint16_t i = 0; + match_result_t data_result; + uint8_t sectionSize[kWhirlpoolAcSections] = {6, 8, 7}; + + // Header + if (!matchMark(results->rawbuf[offset++], kWhirlpoolAcHdrMark)) return false; + if (!matchSpace(results->rawbuf[offset++], kWhirlpoolAcHdrSpace)) + return false; + + // Data Section + // Keep reading bytes until we either run out of section or state to fill. + for (uint8_t section = 0, pos = 0; section < kWhirlpoolAcSections; + section++) { + pos += sectionSize[section]; + for (; offset <= results->rawlen - 16 && i < pos; + i++, dataBitsSoFar += 8, offset += data_result.used) { + data_result = + matchData(&(results->rawbuf[offset]), 8, kWhirlpoolAcBitMark, + kWhirlpoolAcOneSpace, kWhirlpoolAcBitMark, + kWhirlpoolAcZeroSpace, kTolerance, kMarkExcess, false); + if (data_result.success == false) break; // Fail + // Data is in LSB order. We need to reverse it. + results->state[i] = (uint8_t)data_result.data; + } + // Section Footer + if (!matchMark(results->rawbuf[offset++], kWhirlpoolAcBitMark)) + return false; + if (section < kWhirlpoolAcSections - 1) { // Inter-section gaps. + if (!matchSpace(results->rawbuf[offset++], kWhirlpoolAcGap)) return false; + } else { // Last section / End of message gap. + if (offset <= results->rawlen && + !matchAtLeast(results->rawbuf[offset++], kWhirlpoolAcGap)) + return false; + } + } + + // Compliance + if (strict) { + // Re-check we got the correct size/length due to the way we read the data. + if (dataBitsSoFar != kWhirlpoolAcBits) return false; + if (!IRWhirlpoolAc::validChecksum(results->state, dataBitsSoFar / 8)) + return false; + } + + // Success + results->decode_type = WHIRLPOOL_AC; + results->bits = dataBitsSoFar; + // No need to record the state as we stored it as we decoded it. + // As we use result->state, we don't record value, address, or command as it + // is a union data type. + return true; +} +#endif // WHIRLPOOL_AC diff --git a/lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.h b/lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.h new file mode 100644 index 000000000..9604d025c --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/src/ir_Whirlpool.h @@ -0,0 +1,167 @@ +// Whirlpool A/C +// +// Copyright 2018 David Conran + +#ifndef IR_WHIRLPOOL_H_ +#define IR_WHIRLPOOL_H_ + +#define __STDC_LIMIT_MACROS +#include +#ifndef UNIT_TEST +#include +#else +#include +#endif +#include "IRremoteESP8266.h" +#include "IRsend.h" +#ifdef UNIT_TEST +#include "IRsend_test.h" +#endif + +// WW WW HH HH IIIII RRRRRR LL PPPPPP OOOOO OOOOO LL +// WW WW HH HH III RR RR LL PP PP OO OO OO OO LL +// WW W WW HHHHHHH III RRRRRR LL PPPPPP OO OO OO OO LL +// WW WWW WW HH HH III RR RR LL PP OO OO OO OO LL +// WW WW HH HH IIIII RR RR LLLLLLL PP OOOO0 OOOO0 LLLLLLL + +// Ref: +// https://github.com/markszabo/IRremoteESP8266/issues/509 + +// Constants +const uint8_t kWhirlpoolAcChecksumByte1 = 13; +const uint8_t kWhirlpoolAcChecksumByte2 = kWhirlpoolAcStateLength - 1; +const uint8_t kWhirlpoolAcHeat = 0; +const uint8_t kWhirlpoolAcAuto = 1; +const uint8_t kWhirlpoolAcCool = 2; +const uint8_t kWhirlpoolAcDry = 3; +const uint8_t kWhirlpoolAcFan = 4; +const uint8_t kWhirlpoolAcModeMask = 0b00000111; +const uint8_t kWhirlpoolAcModePos = 3; +const uint8_t kWhirlpoolAcFanAuto = 0; +const uint8_t kWhirlpoolAcFanHigh = 1; +const uint8_t kWhirlpoolAcFanMedium = 2; +const uint8_t kWhirlpoolAcFanLow = 3; +const uint8_t kWhirlpoolAcFanMask = 0b00000011; +const uint8_t kWhirlpoolAcFanPos = 2; +const uint8_t kWhirlpoolAcMinTemp = 18; // 18C (DG11J1-3A), 16C (DG11J1-91) +const uint8_t kWhirlpoolAcMaxTemp = 32; // 32C (DG11J1-3A), 30C (DG11J1-91) +const uint8_t kWhirlpoolAcAutoTemp = 23; // 23C +const uint8_t kWhirlpoolAcTempMask = 0b11110000; +const uint8_t kWhirlpoolAcTempPos = 3; +const uint8_t kWhirlpoolAcSwing1Mask = 0b10000000; +const uint8_t kWhirlpoolAcSwing2Mask = 0b01000000; +const uint8_t kWhirlpoolAcLightMask = 0b00100000; +const uint8_t kWhirlpoolAcPowerToggleMask = 0b00000100; +const uint8_t kWhirlpoolAcPowerTogglePos = 2; +const uint8_t kWhirlpoolAcSleepMask = 0b00001000; +const uint8_t kWhirlpoolAcSleepPos = 2; +const uint8_t kWhirlpoolAcSuperMask = 0b10010000; +const uint8_t kWhirlpoolAcSuperPos = 5; +const uint8_t kWhirlpoolAcHourMask = 0b00011111; +const uint8_t kWhirlpoolAcMinuteMask = 0b00111111; +const uint8_t kWhirlpoolAcTimerEnableMask = 0b10000000; +const uint8_t kWhirlpoolAcClockPos = 6; +const uint8_t kWhirlpoolAcOffTimerPos = 8; +const uint8_t kWhirlpoolAcOnTimerPos = 10; +const uint8_t kWhirlpoolAcCommandPos = 15; +const uint8_t kWhirlpoolAcCommandLight = 0x00; +const uint8_t kWhirlpoolAcCommandPower = 0x01; +const uint8_t kWhirlpoolAcCommandTemp = 0x02; +const uint8_t kWhirlpoolAcCommandSleep = 0x03; +const uint8_t kWhirlpoolAcCommandSuper = 0x04; +const uint8_t kWhirlpoolAcCommandOnTimer = 0x05; +const uint8_t kWhirlpoolAcCommandMode = 0x06; +const uint8_t kWhirlpoolAcCommandSwing = 0x07; +const uint8_t kWhirlpoolAcCommandIFeel = 0x0D; +const uint8_t kWhirlpoolAcCommandFanSpeed = 0x11; +const uint8_t kWhirlpoolAcCommand6thSense = 0x17; +const uint8_t kWhirlpoolAcCommandOffTimer = 0x1D; +const uint8_t kWhirlpoolAcAltTempMask = 0b00001000; +const uint8_t kWhirlpoolAcAltTempPos = 18; + +enum whirlpool_ac_remote_model_t { + DG11J13A = 1, // DG11J1-04 too + DG11J191, +}; + +// Classes +class IRWhirlpoolAc { + public: + explicit IRWhirlpoolAc(uint16_t pin); + + void stateReset(); +#if SEND_WHIRLPOOL_AC + void send(const uint16_t repeat = kWhirlpoolAcDefaultRepeat, + const bool calcchecksum = true); +#endif // SEND_WHIRLPOOL_AC + void begin(); + void on(); + void off(); + void setPowerToggle(const bool on); + bool getPowerToggle(); + void setSleep(const bool on); + bool getSleep(); + void setSuper(const bool on); + bool getSuper(); + void setTemp(const uint8_t temp); + uint8_t getTemp(); + void setFan(const uint8_t speed); + uint8_t getFan(); + void setMode(const uint8_t mode); + uint8_t getMode(); + void setSwing(const bool on); + bool getSwing(); + void setLight(const bool on); + bool getLight(); + uint16_t getClock(); + void setClock(const uint16_t minspastmidnight); + uint16_t getOnTimer(); + void setOnTimer(const uint16_t minspastmidnight); + void enableOnTimer(const bool state); + bool isOnTimerEnabled(); + uint16_t getOffTimer(); + void setOffTimer(const uint16_t minspastmidnight); + void enableOffTimer(const bool state); + bool isOffTimerEnabled(); + void setCommand(const uint8_t code); + uint8_t getCommand(); + whirlpool_ac_remote_model_t getModel(); + void setModel(const whirlpool_ac_remote_model_t model); + uint8_t* getRaw(const bool calcchecksum = true); + void setRaw(const uint8_t new_code[], + const uint16_t length = kWhirlpoolAcStateLength); + static bool validChecksum(uint8_t state[], + const uint16_t length = kWhirlpoolAcStateLength); + uint8_t convertMode(const stdAc::opmode_t mode); + uint8_t convertFan(const stdAc::fanspeed_t speed); +#ifdef ARDUINO + String toString(); +#else + std::string toString(); +#endif +#ifndef UNIT_TEST + + private: + IRsend _irsend; +#else + IRsendTest _irsend; +#endif + // The state of the IR remote in IR code form. + uint8_t remote_state[kWhirlpoolAcStateLength]; + uint8_t _desiredtemp; + void checksum(const uint16_t length = kWhirlpoolAcStateLength); + uint16_t getTime(const uint16_t pos); + void setTime(const uint16_t pos, const uint16_t minspastmidnight); + bool isTimerEnabled(const uint16_t pos); + void enableTimer(const uint16_t pos, const bool state); + void _setTemp(const uint8_t temp, const bool remember = true); + void _setMode(const uint8_t mode); + int8_t getTempOffset(); +#ifdef ARDUINO + String timeToString(uint16_t minspastmidnight); +#else + std::string timeToString(uint16_t minspastmidnight); +#endif +}; + +#endif // IR_WHIRLPOOL_H_ diff --git a/lib/IRremoteESP8266-2.5.2.03/src/ir_Whynter.cpp b/lib/IRremoteESP8266-2.6.0/src/ir_Whynter.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/src/ir_Whynter.cpp rename to lib/IRremoteESP8266-2.6.0/src/ir_Whynter.cpp diff --git a/lib/IRremoteESP8266-2.6.0/test/IRac_test.cpp b/lib/IRremoteESP8266-2.6.0/test/IRac_test.cpp new file mode 100644 index 000000000..39c17a84b --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/test/IRac_test.cpp @@ -0,0 +1,865 @@ +// Copyright 2019 David Conran + +#include "ir_Argo.h" +#include "ir_Daikin.h" +#include "ir_Fujitsu.h" +#include "ir_Gree.h" +#include "ir_Haier.h" +#include "ir_Hitachi.h" +#include "ir_Kelvinator.h" +#include "ir_Midea.h" +#include "ir_Mitsubishi.h" +#include "ir_MitsubishiHeavy.h" +#include "ir_Panasonic.h" +#include "ir_Samsung.h" +#include "ir_Tcl.h" +#include "ir_Teco.h" +#include "ir_Toshiba.h" +#include "ir_Trotec.h" +#include "ir_Vestel.h" +#include "ir_Whirlpool.h" +#include "IRac.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for IRac class. + +TEST(TestIRac, Argo) { + IRArgoAC ac(0); + IRac irac(0); + + ac.begin(); + irac.argo(&ac, + true, // Power + stdAc::opmode_t::kHeat, // Mode + 21, // Celsius + stdAc::fanspeed_t::kHigh, // Fan speed + stdAc::swingv_t::kOff, // Veritcal swing + false, // Turbo + -1); // Sleep + EXPECT_TRUE(ac.getPower()); + EXPECT_EQ(1, ac.getMode()); + EXPECT_EQ(21, ac.getTemp()); + EXPECT_EQ(kArgoFlapAuto, ac.getFlap()); + EXPECT_FALSE(ac.getMax()); // Turbo + EXPECT_FALSE(ac.getNight()); // Sleep +} + +TEST(TestIRac, Coolix) { + IRCoolixAC ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 3 (HEAT), Fan: 1 (MAX), Temp: 21C, Zone Follow: Off, " + "Sensor Temp: Ignored"; + + ac.begin(); + irac.coolix(&ac, + true, // Power + stdAc::opmode_t::kHeat, // Mode + 21, // Celsius + stdAc::fanspeed_t::kHigh, // Fan speed + stdAc::swingv_t::kOff, // Veritcal swing + stdAc::swingh_t::kOff, // Horizontal swing + false, // Turbo + false, // Light + false, // Clean + -1); // Sleep + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(COOLIX, ac._irsend.capture.decode_type); + ASSERT_EQ(kCoolixBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.value); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Daikin) { + IRDaikinESP ac(0); + IRac irac(0); + char expected[] = + "Power: On, Mode: 3 (COOL), Temp: 19C, Fan: 2, Powerful: Off, " + "Quiet: Off, Sensor: Off, Eye: Off, Mold: On, Comfort: Off, " + "Swing (Horizontal): Off, Swing (Vertical): Off, " + "Current Time: 0:00, On Time: Off, Off Time: Off"; + + ac.begin(); + irac.daikin(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 19, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kOff, // Veritcal swing + stdAc::swingh_t::kOff, // Horizontal swing + false, // Quiet + false, // Turbo + true, // Filter + true); // Clean + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Daikin2) { + IRDaikin2 ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 3 (COOL), Temp: 19C, Fan: 2, Swing (V): 14 (Auto), " + "Swing (H): 0, Clock: 0:00, On Time: Off, Off Time: Off, " + "Sleep Time: Off, Beep: 1 (Quiet), Light: 1 (Bright), Mold: On, " + "Clean: Off, Fresh Air: Off, Eye: Off, Eye Auto: Off, Quiet: Off, " + "Powerful: Off, Purify: On, Econo: Off"; + + ac.begin(); + irac.daikin2(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 19, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kOff, // Veritcal swing + stdAc::swingh_t::kOff, // Horizontal swing + false, // Quiet + false, // Turbo + true, // Light + false, // Econo + true, // Filter + true, // Clean (aka Mold) + -1, // Sleep time + -1); // Current time + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(DAIKIN2, ac._irsend.capture.decode_type); + ASSERT_EQ(kDaikin2Bits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Daikin216) { + IRDaikin216 ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 4 (HEAT), Temp: 31C, Fan: 11 (QUIET), " + "Swing (Horizontal): On, Swing (Vertical): On, Quiet: On"; + + ac.begin(); + irac.daikin216(&ac, + true, // Power + stdAc::opmode_t::kHeat, // Mode + 31, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kAuto, // Veritcal swing + stdAc::swingh_t::kLeft, // Horizontal swing + true); // Quiet + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(DAIKIN216, ac._irsend.capture.decode_type); + ASSERT_EQ(kDaikin216Bits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Fujitsu) { + IRFujitsuAC ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 2 (MED), " + "Swing: Off, Command: N/A"; + + ac.begin(); + irac.fujitsu(&ac, + ARDB1, // Model + true, // Power + stdAc::opmode_t::kCool, // Mode + 19, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kOff, // Veritcal swing + stdAc::swingh_t::kOff, // Horizontal swing + false); // Quiet + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(FUJITSU_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits - 8, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state, ac._irsend.capture.bits / 8); + ASSERT_EQ(expected, ac.toString()); + + ac._irsend.reset(); + irac.fujitsu(&ac, + ARRAH2E, // Model + true, // Power + stdAc::opmode_t::kCool, // Mode + 19, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kOff, // Veritcal swing + stdAc::swingh_t::kOff, // Horizontal swing + false); // Quiet + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(FUJITSU_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kFujitsuAcBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state, ac._irsend.capture.bits / 8); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Gree) { + IRGreeAC ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 1 (COOL), Temp: 22C, Fan: 2, Turbo: Off, XFan: On, " + "Light: On, Sleep: On, Swing Vertical Mode: Manual, " + "Swing Vertical Pos: 3"; + + ac.begin(); + irac.gree(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 22, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kHigh, // Veritcal swing + false, // Turbo + true, // Light + true, // Clean (aka Mold/XFan) + 8 * 60 + 0); // Sleep time + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(GREE, ac._irsend.capture.decode_type); + ASSERT_EQ(kGreeBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Haier) { + IRHaierAC ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Command: 1 (On), Mode: 3 (HEAT), Temp: 24C, Fan: 2, Swing: 1 (Up), " + "Sleep: On, Health: On, Current Time: 13:45, On Timer: Off, " + "Off Timer: Off"; + + ac.begin(); + irac.haier(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 24, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kHigh, // Veritcal swing + true, // Filter + 8 * 60 + 0, // Sleep time + 13 * 60 + 45); // Clock + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(HAIER_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kHaierACBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + + +TEST(TestIRac, HaierYrwo2) { + IRHaierACYRW02 ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Button: 5 (Power), Mode: 2 (Cool), Temp: 23C, Fan: 4 (Med), " + "Turbo: 1 (High), Swing: 1 (Top), Sleep: On, Health: On"; + + ac.begin(); + irac.haierYrwo2(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 23, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kHigh, // Veritcal swing + true, // Turbo + true, // Filter + 8 * 60 + 0); // Sleep time + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(HAIER_AC_YRW02, ac._irsend.capture.decode_type); + ASSERT_EQ(kHaierACYRW02Bits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Hitachi) { + IRHitachiAc ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 2 (AUTO), Temp: 22C, Fan: 3 (UNKNOWN), " + "Swing (Vertical): Off, Swing (Horizontal): On"; + + ac.begin(); + irac.hitachi(&ac, + true, // Power + stdAc::opmode_t::kAuto, // Mode + 22, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kOff, // Veritcal swing + stdAc::swingh_t::kAuto); // Horizontal swing + + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(HITACHI_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kHitachiAcBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Kelvinator) { + IRKelvinatorAC ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 1 (COOL), Temp: 19C, Fan: 3, Turbo: Off, Quiet: Off, " + "XFan: On, IonFilter: On, Light: On, Swing (Horizontal): Off, " + "Swing (Vertical): Off"; + + ac.begin(); + irac.kelvinator(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 19, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kOff, // Veritcal swing + stdAc::swingh_t::kOff, // Horizontal swing + false, // Quiet + false, // Turbo + true, // Light + true, // Filter + true); // Clean + + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(KELVINATOR, ac._irsend.capture.decode_type); + ASSERT_EQ(kKelvinatorBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Midea) { + IRMideaAC ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 1 (DRY), Temp: 27C/81F, Fan: 2 (MED), Sleep: On"; + + ac.begin(); + irac.midea(&ac, + true, // Power + stdAc::opmode_t::kDry, // Mode + 27, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + 8 * 60 + 0); // Sleep time + + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(MIDEA, ac._irsend.capture.decode_type); + ASSERT_EQ(kMideaBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.value); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Mitsubishi) { + IRMitsubishiAC ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On (COOL), Temp: 20C, FAN: 2, VANE: AUTO, Time: 14:30, " + "On timer: 00:00, Off timer: 00:00, Timer: -"; + + ac.begin(); + irac.mitsubishi(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 20, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kOff, // Veritcal swing + false, // Silent + 14 * 60 + 35); // Clock + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(MITSUBISHI_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kMitsubishiACBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, MitsubishiHeavy88) { + IRMitsubishiHeavy88Ac ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 1 (Cool), Temp: 21C, Fan: 3 (Med), " + "Swing (V): 16 (Auto), Swing (H): 0 (Off), Turbo: Off, Econo: Off, " + "3D: Off, Clean: On"; + + ac.begin(); + irac.mitsubishiHeavy88(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 21, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kAuto, // Veritcal swing + stdAc::swingh_t::kOff, // Horizontal swing + false, // Turbo + false, // Econo + true); // Clean + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(MITSUBISHI_HEAVY_88, ac._irsend.capture.decode_type); + ASSERT_EQ(kMitsubishiHeavy88Bits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, MitsubishiHeavy152) { + IRMitsubishiHeavy152Ac ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 6 (Econo), " + "Swing (V): 6 (Off), Swing (H): 0 (Auto), Silent: On, Turbo: Off, " + "Econo: On, Night: On, Filter: On, 3D: Off, Clean: Off"; + + ac.begin(); + irac.mitsubishiHeavy152(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 20, // Celsius + stdAc::fanspeed_t::kLow, // Fan speed + stdAc::swingv_t::kOff, // Veritcal swing + stdAc::swingh_t::kAuto, // Horizontal swing + true, // Silent + false, // Turbo + true, // Econo + true, // Filter + false, // Clean + 8 * 60); // Sleep + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(MITSUBISHI_HEAVY_152, ac._irsend.capture.decode_type); + ASSERT_EQ(kMitsubishiHeavy152Bits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Panasonic) { + IRPanasonicAc ac(0); + IRac irac(0); + IRrecv capture(0); + char expected_nke[] = + "Model: 2 (NKE), Power: On, Mode: 4 (HEAT), Temp: 28C, Fan: 2 (UNKNOWN), " + "Swing (Vertical): 15 (AUTO), Swing (Horizontal): 6 (Middle), Quiet: On, " + "Powerful: Off, Clock: 19:17, On Timer: Off, Off Timer: Off"; + + ac.begin(); + irac.panasonic(&ac, + kPanasonicNke, // Model + true, // Power + stdAc::opmode_t::kHeat, // Mode + 28, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kAuto, // Veritcal swing + stdAc::swingh_t::kLeft, // Horizontal swing + true, // Quiet + false, // Turbo + 19 * 60 + 17); // Clock + ASSERT_EQ(expected_nke, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(PANASONIC_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kPanasonicAcBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected_nke, ac.toString()); + + char expected_dke[] = + "Model: 3 (DKE), Power: On, Mode: 3 (COOL), Temp: 18C, Fan: 4 (MAX), " + "Swing (Vertical): 1 (Full Up), Swing (Horizontal): 6 (Middle), " + "Quiet: Off, Powerful: On, Clock: 19:17, On Timer: Off, Off Timer: Off"; + ac._irsend.reset(); + irac.panasonic(&ac, + kPanasonicDke, // Model + true, // Power + stdAc::opmode_t::kCool, // Mode + 18, // Celsius + stdAc::fanspeed_t::kMax, // Fan speed + stdAc::swingv_t::kHigh, // Veritcal swing + stdAc::swingh_t::kMiddle, // Horizontal swing + false, // Quiet + true, // Turbo + 19 * 60 + 17); // Clock + ASSERT_EQ(expected_dke, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(PANASONIC_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kPanasonicAcBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected_dke, ac.toString()); +} + +TEST(TestIRac, Samsung) { + IRSamsungAc ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 0 (AUTO), Temp: 28C, Fan: 6 (AUTO), Swing: On, " + "Beep: On, Clean: On, Quiet: On"; + + ac.begin(); + irac.samsung(&ac, + true, // Power + stdAc::opmode_t::kAuto, // Mode + 28, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kAuto, // Veritcal swing + true, // Quiet + false, // Turbo + true, // Clean + true, // Beep + false); // with the Hack Off + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kSamsungAcBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); + + ac._irsend.reset(); + irac.samsung(&ac, + true, // Power + stdAc::opmode_t::kAuto, // Mode + 28, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kAuto, // Veritcal swing + true, // Quiet + false, // Turbo + true, // Clean + true, // Beep + true); // with the Hack On + ASSERT_EQ(expected, ac.toString()); // Class should be in the desired mode. + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kSamsungAcExtendedBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + // However, we expect a plain "on" state as it should be sent before the + // desired state. + char expected_on[] = + "Power: On, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (AUTO), Swing: Off, " + "Beep: Off, Clean: Off, Quiet: Off"; + ASSERT_EQ(expected_on, ac.toString()); +} + +TEST(TestIRac, Tcl112) { + IRTcl112Ac ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 3 (COOL), Temp: 20C, Fan: 3 (Med), Econo: On, " + "Health: On, Light: On, Turbo: Off, Swing (H): On, Swing (V): Off"; + + ac.begin(); + irac.tcl112(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 20, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kOff, // Veritcal swing + stdAc::swingh_t::kAuto, // Horizontal swing + false, // Turbo + true, // Light + true, // Econo + true); // Filter (aka. Health) + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(TCL112AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kTcl112AcBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Teco) { + IRTecoAc ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 0 (AUTO), Temp: 21C, Fan: 2 (Med), Sleep: On, " + "Swing: On"; + + ac.begin(); + irac.teco(&ac, + true, // Power + stdAc::opmode_t::kAuto, // Mode + 21, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kAuto, // Veritcal swing + 8 * 60 + 30); // Sleep + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(TECO, ac._irsend.capture.decode_type); + ASSERT_EQ(kTecoBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.value); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Toshiba) { + IRToshibaAC ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = "Power: On, Mode: 2 (DRY), Temp: 29C, Fan: 2"; + + ac.begin(); + irac.toshiba(&ac, + true, // Power + stdAc::opmode_t::kDry, // Mode + 29, // Celsius + stdAc::fanspeed_t::kLow); // Fan speed + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(TOSHIBA_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kToshibaACBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, Trotec) { + IRTrotecESP ac(0); + IRac irac(0); + + ac.begin(); + irac.trotec(&ac, + true, // Power + stdAc::opmode_t::kCool, // Mode + 18, // Celsius + stdAc::fanspeed_t::kHigh, // Fan speed + 8 * 60 + 17); // Sleep + EXPECT_TRUE(ac.getPower()); + EXPECT_EQ(kTrotecCool, ac.getMode()); + EXPECT_EQ(18, ac.getTemp()); + EXPECT_EQ(kTrotecFanHigh, ac.getSpeed()); + EXPECT_TRUE(ac.getSleep()); +} + +TEST(TestIRac, Vestel) { + IRVestelAc ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Power: On, Mode: 0 (AUTO), Temp: 22C, Fan: 5 (LOW), Sleep: On, " + "Turbo: Off, Ion: On, Swing: On"; + + ac.begin(); + irac.vestel(&ac, + true, // Power + stdAc::opmode_t::kAuto, // Mode + 22, // Celsius + stdAc::fanspeed_t::kLow, // Fan speed + stdAc::swingv_t::kHigh, // Veritcal swing + false, // Turbo + true, // Filter + 8 * 60 + 0); // Sleep time + // 13 * 60 + 45); // Clock + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(VESTEL_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kVestelAcBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); + + ac._irsend.reset(); + char expected_clocks[] = + "Time: 13:45, Timer: Off, On Timer: Off, Off Timer: Off"; + + ac.begin(); + irac.vestel(&ac, + true, // Power + stdAc::opmode_t::kAuto, // Mode + 22, // Celsius + stdAc::fanspeed_t::kLow, // Fan speed + stdAc::swingv_t::kHigh, // Veritcal swing + false, // Turbo + true, // Filter + 8 * 60 + 0, // Sleep time + 13 * 60 + 45, // Clock + false); // Don't send the normal message. + // Just for testing purposes. + ASSERT_EQ(expected_clocks, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(VESTEL_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kVestelAcBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected_clocks, ac.toString()); + + // Now check it sends both messages during normal operation when the + // clock is set. + ac._irsend.reset(); + ac.begin(); + irac.vestel(&ac, + true, // Power + stdAc::opmode_t::kAuto, // Mode + 22, // Celsius + stdAc::fanspeed_t::kLow, // Fan speed + stdAc::swingv_t::kHigh, // Veritcal swing + false, // Turbo + true, // Filter + 8 * 60 + 0, // Sleep time + 13 * 60 + 45); // Clock + + EXPECT_EQ( + "f38000d50" + "m3110s9066" + "m520s1535m520s480m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s1535m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s1535m520s1535m520s1535m520s1535m520s480m520s1535m520s480m520s1535" + "m520s1535m520s1535m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s480m520s480m520s480m520s480m520s1535m520s1535m520s480" + "m520s1535m520s480m520s1535m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s480m520s1535m520s480m520s1535m520s1535m520s1535m520s1535" + "m520s100000" + "m3110s9066" + "m520s1535m520s480m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s1535m520s480m520s480m520s480m520s1535m520s1535m520s480" + "m520s1535m520s1535m520s1535m520s1535m520s480m520s480m520s480m520s480" + "m520s480m520s480m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s480m520s480m520s480m520s1535m520s480m520s1535m520s1535" + "m520s480m520s480m520s480m520s480m520s1535m520s480m520s1535m520s1535" + "m520s480m520s1535m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s100000", ac._irsend.outputStr()); +} + + +TEST(TestIRac, Whirlpool) { + IRWhirlpoolAc ac(0); + IRac irac(0); + IRrecv capture(0); + char expected[] = + "Model: 1 (DG11J13A), Power toggle: On, Mode: 1 (AUTO), Temp: 21C, " + "Fan: 3 (LOW), Swing: On, Light: On, Clock: 23:58, On Timer: Off, " + "Off Timer: Off, Sleep: On, Super: Off, Command: 1 (POWER)"; + + ac.begin(); + irac.whirlpool(&ac, + DG11J13A, + true, // Power + stdAc::opmode_t::kAuto, // Mode + 21, // Celsius + stdAc::fanspeed_t::kMedium, // Fan speed + stdAc::swingv_t::kAuto, // Veritcal swing + false, // Turbo + true, // Light + 8 * 60 + 30, // Sleep + 23 * 60 + 58); // Clock + ASSERT_EQ(expected, ac.toString()); + ac._irsend.makeDecodeResult(); + EXPECT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(WHIRLPOOL_AC, ac._irsend.capture.decode_type); + ASSERT_EQ(kWhirlpoolAcBits, ac._irsend.capture.bits); + ac.setRaw(ac._irsend.capture.state); + ASSERT_EQ(expected, ac.toString()); +} + +TEST(TestIRac, strToBool) { + EXPECT_TRUE(IRac::strToBool("ON")); + EXPECT_TRUE(IRac::strToBool("1")); + EXPECT_TRUE(IRac::strToBool("TRUE")); + EXPECT_TRUE(IRac::strToBool("YES")); + EXPECT_FALSE(IRac::strToBool("OFF")); + EXPECT_FALSE(IRac::strToBool("0")); + EXPECT_FALSE(IRac::strToBool("FALSE")); + EXPECT_FALSE(IRac::strToBool("NO")); + EXPECT_FALSE(IRac::strToBool("FOOBAR")); + EXPECT_TRUE(IRac::strToBool("FOOBAR", true)); +} + +TEST(TestIRac, strToOpmode) { + EXPECT_EQ(stdAc::opmode_t::kAuto, IRac::strToOpmode("AUTO")); + EXPECT_EQ(stdAc::opmode_t::kCool, IRac::strToOpmode("COOL")); + EXPECT_EQ(stdAc::opmode_t::kHeat, IRac::strToOpmode("HEAT")); + EXPECT_EQ(stdAc::opmode_t::kDry, IRac::strToOpmode("DRY")); + EXPECT_EQ(stdAc::opmode_t::kFan, IRac::strToOpmode("FAN")); + EXPECT_EQ(stdAc::opmode_t::kFan, IRac::strToOpmode("FAN_ONLY")); + EXPECT_EQ(stdAc::opmode_t::kAuto, IRac::strToOpmode("FOOBAR")); + EXPECT_EQ(stdAc::opmode_t::kOff, IRac::strToOpmode("OFF")); + EXPECT_EQ(stdAc::opmode_t::kOff, IRac::strToOpmode("FOOBAR", + stdAc::opmode_t::kOff)); +} + +TEST(TestIRac, strToFanspeed) { + EXPECT_EQ(stdAc::fanspeed_t::kAuto, IRac::strToFanspeed("AUTO")); + EXPECT_EQ(stdAc::fanspeed_t::kMin, IRac::strToFanspeed("MIN")); + EXPECT_EQ(stdAc::fanspeed_t::kLow, IRac::strToFanspeed("LOW")); + EXPECT_EQ(stdAc::fanspeed_t::kMedium, IRac::strToFanspeed("MEDIUM")); + EXPECT_EQ(stdAc::fanspeed_t::kHigh, IRac::strToFanspeed("HIGH")); + EXPECT_EQ(stdAc::fanspeed_t::kMax, IRac::strToFanspeed("MAX")); + EXPECT_EQ(stdAc::fanspeed_t::kAuto, IRac::strToFanspeed("FOOBAR")); + EXPECT_EQ(stdAc::fanspeed_t::kMin, + IRac::strToFanspeed("FOOBAR", stdAc::fanspeed_t::kMin)); +} + +TEST(TestIRac, strToSwingV) { + EXPECT_EQ(stdAc::swingv_t::kAuto, IRac::strToSwingV("AUTO")); + EXPECT_EQ(stdAc::swingv_t::kLowest, IRac::strToSwingV("LOWEST")); + EXPECT_EQ(stdAc::swingv_t::kLow, IRac::strToSwingV("LOW")); + EXPECT_EQ(stdAc::swingv_t::kMiddle, IRac::strToSwingV("MIDDLE")); + EXPECT_EQ(stdAc::swingv_t::kHigh, IRac::strToSwingV("HIGH")); + EXPECT_EQ(stdAc::swingv_t::kHighest, IRac::strToSwingV("HIGHEST")); + EXPECT_EQ(stdAc::swingv_t::kOff, IRac::strToSwingV("OFF")); + EXPECT_EQ(stdAc::swingv_t::kOff, IRac::strToSwingV("FOOBAR")); + EXPECT_EQ(stdAc::swingv_t::kAuto, + IRac::strToSwingV("FOOBAR", stdAc::swingv_t::kAuto)); +} + +TEST(TestIRac, strToSwingH) { + EXPECT_EQ(stdAc::swingh_t::kAuto, IRac::strToSwingH("AUTO")); + EXPECT_EQ(stdAc::swingh_t::kLeftMax, IRac::strToSwingH("MAX LEFT")); + EXPECT_EQ(stdAc::swingh_t::kLeft, IRac::strToSwingH("LEFT")); + EXPECT_EQ(stdAc::swingh_t::kMiddle, IRac::strToSwingH("CENTRE")); + EXPECT_EQ(stdAc::swingh_t::kRight, IRac::strToSwingH("RIGHT")); + EXPECT_EQ(stdAc::swingh_t::kRightMax, IRac::strToSwingH("RIGHTMAX")); + EXPECT_EQ(stdAc::swingh_t::kOff, IRac::strToSwingH("OFF")); + EXPECT_EQ(stdAc::swingh_t::kOff, IRac::strToSwingH("FOOBAR")); + EXPECT_EQ(stdAc::swingh_t::kAuto, + IRac::strToSwingH("FOOBAR", stdAc::swingh_t::kAuto)); +} + +TEST(TestIRac, strToModel) { + EXPECT_EQ(panasonic_ac_remote_model_t::kPanasonicLke, + IRac::strToModel("LKE")); + EXPECT_EQ(panasonic_ac_remote_model_t::kPanasonicLke, + IRac::strToModel("PANASONICLKE")); + EXPECT_EQ(fujitsu_ac_remote_model_t::ARRAH2E, + IRac::strToModel("ARRAH2E")); + EXPECT_EQ(whirlpool_ac_remote_model_t::DG11J13A, + IRac::strToModel("DG11J13A")); + EXPECT_EQ(1, IRac::strToModel("1")); + EXPECT_EQ(10, IRac::strToModel("10")); + EXPECT_EQ(-1, IRac::strToModel("0")); + EXPECT_EQ(-1, IRac::strToModel("FOOBAR")); + EXPECT_EQ(0, IRac::strToModel("FOOBAR", 0)); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.cpp b/lib/IRremoteESP8266-2.6.0/test/IRrecv_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/IRrecv_test.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.h b/lib/IRremoteESP8266-2.6.0/test/IRrecv_test.h similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/test/IRrecv_test.h rename to lib/IRremoteESP8266-2.6.0/test/IRrecv_test.h diff --git a/lib/IRremoteESP8266-2.6.0/test/IRsend_test.cpp b/lib/IRremoteESP8266-2.6.0/test/IRsend_test.cpp new file mode 100644 index 000000000..ffd69cf71 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/test/IRsend_test.cpp @@ -0,0 +1,686 @@ +// Copyright 2017,2019 David Conran + +#include "IRsend_test.h" +#include "IRsend.h" +#include "IRutils.h" +#include "gtest/gtest.h" + +// Tests sendData(). + +// Test sending zero bits. +TEST(TestSendData, SendZeroBits) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b1, 0, true); + EXPECT_EQ("", irsend.outputStr()); +} + +// Test sending zero and one. +TEST(TestSendData, SendSingleBit) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + EXPECT_EQ("d50m1s2", irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0b0, 1, true); + EXPECT_EQ("d50m3s4", irsend.outputStr()); +} + +// Test sending bit order. +TEST(TestSendData, TestingBitSendOrder) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b10, 2, true); + EXPECT_EQ("d50m1s2m3s4", irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0b10, 2, false); + EXPECT_EQ("d50m3s4m1s2", irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0b0001, 4, false); + EXPECT_EQ("d50m1s2m3s4m3s4m3s4", irsend.outputStr()); +} + +// Test sending typical data. +TEST(TestSendData, SendTypicalData) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b1010110011110000, 16, true); + EXPECT_EQ( + "d50m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4m3s4", + irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0x1234567890ABCDEF, 64, true); + EXPECT_EQ( + "d50" + "m3s4m3s4m3s4m1s2m3s4m3s4m1s2m3s4m3s4m3s4m1s2m1s2m3s4m1s2m3s4m3s4" + "m3s4m1s2m3s4m1s2m3s4m1s2m1s2m3s4m3s4m1s2m1s2m1s2m1s2m3s4m3s4m3s4" + "m1s2m3s4m3s4m1s2m3s4m3s4m3s4m3s4m1s2m3s4m1s2m3s4m1s2m3s4m1s2m1s2" + "m1s2m1s2m3s4m3s4m1s2m1s2m3s4m1s2m1s2m1s2m1s2m3s4m1s2m1s2m1s2m1s2", + irsend.outputStr()); +} + +// Test sending more than expected bits. +TEST(TestSendData, SendOverLargeData) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0xFFFFFFFFFFFFFFFF, 70, true); + EXPECT_EQ( + "d50" + "m3s4m3s4m3s4m3s4m3s4m3s4" + "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" + "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" + "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2" + "m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2m1s2", + irsend.outputStr()); +} + +// Test inverting the output. +TEST(TestIRSend, InvertedOutput) { + IRsendTest irsend(4, true); + irsend.begin(); + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + EXPECT_EQ("d50s1m2", irsend.outputStr()); + irsend.sendData(1, 2, 3, 4, 0b0, 1, true); + EXPECT_EQ("d50s3m4", irsend.outputStr()); +} + +// Test we correctly pick up frequency changes. +TEST(TestIRSend, DetectFreqChanges) { + IRsendTest irsend(0); + + irsend.begin(); + irsend.enableIROut(40); // 40kHz + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + irsend.enableIROut(38); // 40kHz + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + irsend.enableIROut(40); // 40kHz + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + irsend.enableIROut(38); // 40kHz + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + EXPECT_EQ( + "f40000d50" + "m1s2" + "f38000" + "m1s2" + "f40000" + "m1s2" + "f38000" + "m1s2", + irsend.outputStr()); + irsend.reset(); + irsend.enableIROut(40); // 40kHz + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + irsend.enableIROut(40); // 40kHz + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + irsend.enableIROut(38); // 40kHz + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + irsend.enableIROut(38); // 40kHz + irsend.sendData(1, 2, 3, 4, 0b1, 1, true); + EXPECT_EQ( + "f40000d50" + "m1s2m1s2" + "f38000m1s2m1s2", + irsend.outputStr()); +} + +// Test we correctly pick up duty cycle changes. +TEST(TestIRSend, DetectDutyChanges) { + IRsendTest irsend(0); + + irsend.begin(); + irsend.sendGeneric(1, 2, 3, 4, 5, 6, 7, 8, 0b1, 1, 38000, true, 0, 33); + EXPECT_EQ( + "f38000d33" + "m1s2m3s4m7s8", + irsend.outputStr()); + + irsend.reset(); + irsend.sendGeneric(1, 2, 3, 4, 5, 6, 7, 8, 0b1, 1, 38000, true, 0, 50); + irsend.sendGeneric(1, 2, 3, 4, 5, 6, 7, 8, 0b1, 1, 38000, true, 0, 33); + irsend.sendGeneric(1, 2, 3, 4, 5, 6, 7, 8, 0b1, 1, 38000, true, 0, 25); + EXPECT_EQ( + "f38000d50" + "m1s2m3s4m7s8" + "d33" + "m1s2m3s4m7s8" + "d25" + "m1s2m3s4m7s8", + irsend.outputStr()); +} + + +// Test we correctly pick up frequency AND duty changes. +TEST(TestIRSend, DetectFreqAndDutyChanges) { + IRsendTest irsend(0); + + irsend.begin(); + irsend.sendGeneric(1, 2, 3, 4, 5, 6, 7, 8, 0b1, 1, 38000, true, 0, 50); + irsend.sendGeneric(1, 2, 3, 4, 5, 6, 7, 8, 0b1, 1, 38000, true, 0, 33); + irsend.sendGeneric(1, 2, 3, 4, 5, 6, 7, 8, 0b1, 1, 40000, true, 0, 25); + EXPECT_EQ( + "f38000d50" + "m1s2m3s4m7s8" + "d33" + "m1s2m3s4m7s8" + "f40000d25" + "m1s2m3s4m7s8", + irsend.outputStr()); +} + +// Test typical use of sendRaw(). +TEST(TestSendRaw, GeneralUse) { + IRsendTest irsend(4); + IRrecv irrecv(0); + + irsend.begin(); + // NEC C3E0E0E8 as measured in #204 + uint16_t rawData[67] = { + 8950, 4500, 550, 1650, 600, 1650, 550, 550, 600, 500, 600, 550, + 550, 550, 600, 1650, 550, 1650, 600, 1650, 600, 1650, 550, 1700, + 550, 550, 600, 550, 550, 550, 600, 500, 600, 550, 550, 1650, + 600, 1650, 600, 1650, 550, 550, 600, 500, 600, 500, 600, 550, + 550, 550, 600, 1650, 550, 1650, 600, 1650, 600, 500, 650, 1600, + 600, 500, 600, 550, 550, 550, 600}; + + irsend.sendRaw(rawData, 67, 38); + EXPECT_EQ( + "f38000d50" + "m8950s4500" + "m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650" + "m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550" + "m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550" + "m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550" + "m600", + irsend.outputStr()); + + irsend.reset(); + irsend.sendRaw(rawData, 67, 38); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, kNECBits, false)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0xC3E0E0E8, irsend.capture.value); + EXPECT_EQ( + "f38000d50" + "m8950s4500" + "m550s1650m600s1650m550s550m600s500m600s550m550s550m600s1650m550s1650" + "m600s1650m600s1650m550s1700m550s550m600s550m550s550m600s500m600s550" + "m550s1650m600s1650m600s1650m550s550m600s500m600s500m600s550m550s550" + "m600s1650m550s1650m600s1650m600s500m650s1600m600s500m600s550m550s550" + "m600", + irsend.outputStr()); +} + +// Incorrect handling of decodes from Raw. i.e. There is no gap recorded at +// the end of a command when using the interrupt code. sendRaw() best emulates +// this for unit testing purposes. sendGC() and sendXXX() will add the trailing +// gap. Users won't see this in normal use. +TEST(TestSendRaw, NoTrailingGap) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[67] = { + 9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550, 600, 1650, + 650, 550, 600, 1650, 650, 1650, 650, 1650, 600, 550, 650, 1650, + 650, 1650, 650, 550, 600, 1650, 650, 1650, 650, 550, 650, 550, + 650, 1650, 650, 550, 650, 550, 650, 550, 600, 550, 650, 550, + 650, 550, 650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650, + 650, 1650, 650, 1650, 650, 1650, 600}; + irsend.sendRaw(rawData, 67, 38); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); +} + +TEST(TestLowLevelSend, MarkFrequencyModulationAt38kHz) { + IRsendLowLevelTest irsend(0); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(38000, 50); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]10usecs[Off]11usecs[On]10usecs[Off]11usecs[On]10usecs[Off]11usecs" + "[On]10usecs[Off]11usecs[On]10usecs[Off]6usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(38000, 33); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]6usecs[Off]15usecs[On]6usecs[Off]15usecs[On]6usecs[Off]15usecs" + "[On]6usecs[Off]15usecs[On]6usecs[Off]10usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(38000, 100); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, MarkFrequencyModulationAt36_7kHz) { + IRsendLowLevelTest irsend(0); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(36700, 50); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]11usecs[Off]11usecs[On]11usecs[Off]11usecs[On]11usecs[Off]11usecs" + "[On]11usecs[Off]11usecs[On]11usecs[Off]1usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(36700, 33); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]7usecs[Off]15usecs[On]7usecs[Off]15usecs[On]7usecs[Off]15usecs" + "[On]7usecs[Off]15usecs[On]7usecs[Off]5usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(36700, 100); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, MarkFrequencyModulationAt40kHz) { + IRsendLowLevelTest irsend(0); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(40000, 50); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs" + "[On]10usecs[Off]10usecs[On]10usecs[Off]10usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 33); + EXPECT_EQ(5, irsend.mark(100)); + EXPECT_EQ( + "[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs" + "[On]6usecs[Off]14usecs[On]6usecs[Off]14usecs", + irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 100); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, MarkNoModulation) { + IRsendLowLevelTest irsend(0, false, false); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(38000, 50); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(36700, 25); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 75); + EXPECT_EQ(1, irsend.mark(1000)); + EXPECT_EQ("[On]1000usecs[Off]", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, SpaceFrequencyModulation) { + IRsendLowLevelTest irsend(0); + + irsend.reset(); + irsend.enableIROut(38000); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 75); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(38000, 100); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(38000, 33); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); +} + +TEST(TestLowLevelSend, SpaceNoModulation) { + IRsendLowLevelTest irsend(0, false, false); + + irsend.begin(); + + irsend.reset(); + irsend.enableIROut(38000, 50); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(36700, 25); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); + + irsend.reset(); + irsend.enableIROut(40000, 75); + irsend.space(1000); + EXPECT_EQ("[Off]1000usecs", irsend.low_level_sequence); +} + +// Test expected to work/produce a message for irsend:send() +TEST(TestSend, GenericSimpleSendMethod) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + ASSERT_TRUE(irsend.send(AIWA_RC_T501, 0x1234, kAiwaRcT501Bits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); + EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(CARRIER_AC, 0x1234, kCarrierAcBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(CARRIER_AC, irsend.capture.decode_type); + EXPECT_EQ(kCarrierAcBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(COOLIX, 0x1234, kCoolixBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(COOLIX, irsend.capture.decode_type); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(DENON, 0x1234, kDenonBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(DENON, irsend.capture.decode_type); + EXPECT_EQ(kDenonBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(DISH, 0x1234, kDishBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(DISH, irsend.capture.decode_type); + EXPECT_EQ(kDishBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(GICABLE, 0x1234, kGicableBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GICABLE, irsend.capture.decode_type); + EXPECT_EQ(kGicableBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(GREE, 0x0009205000200050, kGreeBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(GREE, irsend.capture.decode_type); + EXPECT_EQ(kGreeBits, irsend.capture.bits); + // No simple value test for gree as it decodes to an Array. + + irsend.reset(); + ASSERT_TRUE(irsend.send(JVC, 0x1234, kJvcBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(JVC, irsend.capture.decode_type); + EXPECT_EQ(kJvcBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(LASERTAG, 0x123, kLasertagBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LASERTAG, irsend.capture.decode_type); + EXPECT_EQ(kLasertagBits, irsend.capture.bits); + EXPECT_EQ(0x123, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(LG, 0x700992, kLgBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(kLgBits, irsend.capture.bits); + EXPECT_EQ(0x700992, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(LG, 0x700992, kLg32Bits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(kLg32Bits, irsend.capture.bits); + EXPECT_EQ(0x700992, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(LG2, 0x880094D, kLgBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LG2, irsend.capture.decode_type); + EXPECT_EQ(kLgBits, irsend.capture.bits); + EXPECT_EQ(0x880094D, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(LUTRON, 0x1234, kLutronBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LUTRON, irsend.capture.decode_type); + EXPECT_EQ(kLutronBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(MAGIQUEST, 0x560F40020455, kMagiquestBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); + EXPECT_EQ(kMagiquestBits, irsend.capture.bits); + EXPECT_EQ(0x560F40020455, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(MIDEA, 0xA18263FFFF6E, kMideaBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MIDEA, irsend.capture.decode_type); + EXPECT_EQ(kMideaBits, irsend.capture.bits); + EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(MITSUBISHI, 0x1234, kMitsubishiBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(MITSUBISHI2, 0x1234, kMitsubishiBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI2, irsend.capture.decode_type); + EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(NIKAI, 0x1234, kNikaiBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NIKAI, irsend.capture.decode_type); + EXPECT_EQ(kNikaiBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(NEC, 0x4BB640BF, kNECBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(NEC_LIKE, 0x12345678, kNECBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC_LIKE, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x12345678, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(PANASONIC, 0x40040190ED7C, kPanasonicBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(kPanasonicBits, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(PIONEER, 0x659A05FAF50AC53A, kPioneerBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(PIONEER, irsend.capture.decode_type); + EXPECT_EQ(kPioneerBits, irsend.capture.bits); + EXPECT_EQ(0x659A05FAF50AC53A, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(RC5, 0x175, kRC5Bits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(RC5, irsend.capture.decode_type); + EXPECT_EQ(kRC5Bits, irsend.capture.bits); + EXPECT_EQ(0x175, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(RC6, 0xC800F740C, kRC6_36Bits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(RC6, irsend.capture.decode_type); + EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); + EXPECT_EQ(0xC800F740C, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(RCMM, 0x1234, kRCMMBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(kRCMMBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(SAMSUNG, 0xE0E09966, kSamsungBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(kSamsungBits, irsend.capture.bits); + EXPECT_EQ(0xE0E09966, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(SAMSUNG36, 0x1234, kSamsung36Bits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SAMSUNG36, irsend.capture.decode_type); + EXPECT_EQ(kSamsung36Bits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(SANYO_LC7461, 0x2468DCB56A9, kSanyoLC7461Bits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); + EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); + EXPECT_EQ(0x2468DCB56A9, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(SHARP, 0x7266, kSharpBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SHARP, irsend.capture.decode_type); + EXPECT_EQ(kSharpBits, irsend.capture.bits); + EXPECT_EQ(0x7266, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(SHERWOOD, 0x4BB640BF, kSherwoodBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kSherwoodBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(SONY, 0x1234, kSony20Bits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(kSony20Bits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(TECO, 0x1234, kTecoBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(TECO, irsend.capture.decode_type); + EXPECT_EQ(kTecoBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(VESTEL_AC, 0xF4410001FF1201, kVestelAcBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(VESTEL_AC, irsend.capture.decode_type); + EXPECT_EQ(kVestelAcBits, irsend.capture.bits); + EXPECT_EQ(0xF4410001FF1201, irsend.capture.value); + + irsend.reset(); + ASSERT_TRUE(irsend.send(WHYNTER, 0x1234, kWhynterBits)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(WHYNTER, irsend.capture.decode_type); + EXPECT_EQ(kWhynterBits, irsend.capture.bits); + EXPECT_EQ(0x1234, irsend.capture.value); +} + +// Test some expected types to NOT work/produce a message via irsend:send() +TEST(TestSend, GenericSimpleSendMethodFailure) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Check nothing is sent for unexpected protocols + irsend.reset(); + ASSERT_FALSE(irsend.send(KELVINATOR, 0x1234, kKelvinatorBits)); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decode(&irsend.capture)); + + // For every A/C protocol which decodes to having a state[]. + for (int i = 0; i < 200; i++) { + if (hasACState((decode_type_t)i) && i != GREE) { // Gree is an exception. + // Check it fails. + ASSERT_FALSE(irsend.send((decode_type_t)i, 0, 0)); + } + } + + // Test some other special cases. + ASSERT_FALSE(irsend.send(UNKNOWN, 0, 0)); + ASSERT_FALSE(irsend.send(UNUSED, 0, 0)); + ASSERT_FALSE(irsend.send(RAW, 0, 0)); + ASSERT_FALSE(irsend.send(PRONTO, 0, 0)); + ASSERT_FALSE(irsend.send(GLOBALCACHE, 0, 0)); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.h b/lib/IRremoteESP8266-2.6.0/test/IRsend_test.h similarity index 82% rename from lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.h rename to lib/IRremoteESP8266-2.6.0/test/IRsend_test.h index 6d9fe51b8..f43409433 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/IRsend_test.h +++ b/lib/IRremoteESP8266-2.6.0/test/IRsend_test.h @@ -17,12 +17,14 @@ #ifdef UNIT_TEST // Used to help simulate elapsed time in unit tests. -uint32_t _IRtimer_unittest_now = 0; +extern uint32_t _IRtimer_unittest_now; #endif // UNIT_TEST class IRsendTest : public IRsend { public: uint32_t output[OUTPUT_BUF]; + uint32_t freq[OUTPUT_BUF]; + uint8_t duty[OUTPUT_BUF]; uint16_t last; uint16_t rawbuf[RAW_BUF]; decode_results capture; @@ -40,8 +42,22 @@ class IRsendTest : public IRsend { std::string outputStr() { std::stringstream result; + uint8_t lastduty = UINT8_MAX; // An impossible duty cycle value. + uint32_t lastfreq = 0; // An impossible frequency value. if (last == 0 && output[0] == 0) return ""; for (uint16_t i = 0; i <= last; i++) { + // Display the frequency only if it changes. + if (freq[i] != lastfreq) { + result << "f"; + result << freq[i]; + lastfreq = freq[i]; + } + // Display the duty cycle only if it changes. + if (duty[i] != lastduty) { + result << "d"; + result << static_cast(duty[i]); + lastduty = duty[i]; + } if ((i & 1) != outputOff) // Odd XOR outputOff result << "s"; else @@ -92,6 +108,8 @@ class IRsendTest : public IRsend { output[++last] = usec; else output[last] += usec; + duty[last] = _dutycycle; + freq[last] = _freq_unittest; return 0; } @@ -103,6 +121,8 @@ class IRsendTest : public IRsend { } else { output[++last] = time; } + duty[last] = _dutycycle; + freq[last] = _freq_unittest; } }; diff --git a/lib/IRremoteESP8266-2.5.2.03/test/IRutils_test.cpp b/lib/IRremoteESP8266-2.6.0/test/IRutils_test.cpp similarity index 85% rename from lib/IRremoteESP8266-2.5.2.03/test/IRutils_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/IRutils_test.cpp index 91cf4725c..4a4907649 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/IRutils_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/IRutils_test.cpp @@ -350,3 +350,68 @@ TEST(TestInvertBits, MoreThan64Bits) { ASSERT_EQ(0xAAAA5555AAAA5555, invertBits(0x5555AAAA5555AAAA, 70)); ASSERT_EQ(0xFFFFFFFFFFFFFFFF, invertBits(0x0, 128)); } + +TEST(TestCountBits, Pointer) { + uint8_t data[14] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; + + ASSERT_EQ(0, countBits(data, 0)); + ASSERT_EQ(0, countBits(data, 1)); + ASSERT_EQ(0, countBits(data, 1, true)); + ASSERT_EQ(8, countBits(data, 1, false)); + ASSERT_EQ(1, countBits(data, 2)); + ASSERT_EQ(15, countBits(data, 2, false)); + ASSERT_EQ(1, countBits(data + 1, 1)); + ASSERT_EQ(2, countBits(data, 3)); + ASSERT_EQ(4, countBits(data, 4)); + ASSERT_EQ(25, countBits(data, 14)); + ASSERT_EQ(25, countBits(data, 14)); + ASSERT_EQ(14 * 8, countBits(data, 14, true) + countBits(data, 14, false)); + ASSERT_EQ(125, countBits(data, 14, true, 100)); +} + +TEST(TestCountBits, Integer) { + uint64_t data = 0xAAAAAAAAAAAAAAAA; + + ASSERT_EQ(0, countBits(data, 0)); + ASSERT_EQ(0, countBits(data, 1)); + ASSERT_EQ(0, countBits(data, 1, true)); + ASSERT_EQ(1, countBits(data, 1, false)); + ASSERT_EQ(1, countBits(data, 3)); + ASSERT_EQ(2, countBits(data, 3, false)); + ASSERT_EQ(4, countBits(data, 8)); + ASSERT_EQ(4, countBits(data, 8, false)); + ASSERT_EQ(32, countBits(data, 64)); + ASSERT_EQ(32, countBits(data, 64, false)); + + data = 0; + ASSERT_EQ(0, countBits(data, 1, true)); + ASSERT_EQ(1, countBits(data, 1, false)); + ASSERT_EQ(0, countBits(data, 64)); + ASSERT_EQ(64, countBits(data, 64, false)); + + data = 0xFFFFFFFFFFFFFFFF; + ASSERT_EQ(1, countBits(data, 1, true)); + ASSERT_EQ(0, countBits(data, 1, false)); + ASSERT_EQ(64, countBits(data, 64)); + ASSERT_EQ(0, countBits(data, 64, false)); +} + +TEST(TestStrToDecodeType, strToDecodeType) { + EXPECT_EQ(decode_type_t::NEC, strToDecodeType("NEC")); + EXPECT_EQ(decode_type_t::KELVINATOR, strToDecodeType("KELVINATOR")); + EXPECT_EQ(decode_type_t::UNKNOWN, strToDecodeType("foo")); +} + +TEST(TestUtils, htmlEscape) { + EXPECT_EQ("", htmlEscape("")); + EXPECT_EQ("No Changes", htmlEscape("No Changes")); + EXPECT_EQ("No\tChanges+_%^$@~`\n:\\", htmlEscape("No\tChanges+_%^$@~`\n:\\")); + EXPECT_EQ(""With Changes"", htmlEscape("\"With Changes\"")); + EXPECT_EQ( + "';!‐"<>&#equals;&#{}" + "()", htmlEscape("';!-\"<>=&#{}()")); + EXPECT_EQ("""", htmlEscape("\"\"")); + EXPECT_EQ( + "&quot;&lt;&apos;&gt;&amp;", + htmlEscape(""<'>&")); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/Makefile b/lib/IRremoteESP8266-2.6.0/test/Makefile similarity index 71% rename from lib/IRremoteESP8266-2.5.2.03/test/Makefile rename to lib/IRremoteESP8266-2.6.0/test/Makefile index d53014183..9a64aaaaa 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/Makefile +++ b/lib/IRremoteESP8266-2.6.0/test/Makefile @@ -16,6 +16,7 @@ GTEST_DIR = ../lib/googletest/googletest # Where to find user code. USER_DIR = ../src +INCLUDES = -I$(USER_DIR) -I. # Flags passed to the preprocessor. # Set Google Test's header directory as a system directory, such that @@ -23,7 +24,7 @@ USER_DIR = ../src CPPFLAGS += -isystem $(GTEST_DIR)/include -DUNIT_TEST # Flags passed to the C++ compiler. -CXXFLAGS += -g -Wall -Wextra -pthread +CXXFLAGS += -g -Wall -Wextra -pthread -std=gnu++11 # All tests produced by this Makefile. Remember to add new tests you # created to the list. @@ -36,7 +37,8 @@ TESTS = IRutils_test IRsend_test ir_NEC_test ir_GlobalCache_test \ ir_Toshiba_test ir_Midea_test ir_Magiquest_test ir_Lasertag_test \ ir_Carrier_test ir_Haier_test ir_Hitachi_test ir_GICable_test \ ir_Whirlpool_test ir_Lutron_test ir_Electra_test ir_Pioneer_test \ - ir_MWM_test + ir_MWM_test ir_Vestel_test ir_Teco_test ir_Tcl_test ir_Lego_test IRac_test \ + ir_MitsubishiHeavy_test # All Google Test headers. Usually you shouldn't change this # definition. @@ -80,7 +82,8 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \ ir_Kelvinator.o ir_Daikin.o ir_Gree.o ir_Pronto.o ir_Nikai.o ir_Toshiba.o \ ir_Midea.o ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o \ ir_Hitachi.o ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o \ - ir_Pioneer.o ir_MWM.o + ir_Pioneer.o ir_MWM.o ir_Vestel.o ir_Teco.o ir_Tcl.o ir_Lego.o ir_Argo.o \ + ir_Trotec.o ir_MitsubishiHeavy.o # All the IR Protocol header files. PROTOCOLS_H = $(USER_DIR)/ir_Argo.h \ @@ -93,19 +96,24 @@ PROTOCOLS_H = $(USER_DIR)/ir_Argo.h \ $(USER_DIR)/ir_Daikin.h \ $(USER_DIR)/ir_Kelvinator.h \ $(USER_DIR)/ir_Mitsubishi.h \ + $(USER_DIR)/ir_MitsubishiHeavy.h \ $(USER_DIR)/ir_NEC.h \ $(USER_DIR)/ir_Samsung.h \ $(USER_DIR)/ir_Trotec.h \ $(USER_DIR)/ir_Fujitsu.h \ $(USER_DIR)/ir_LG.h \ - $(USER_DIR)/ir_Panasonic.h + $(USER_DIR)/ir_Panasonic.h \ + $(USER_DIR)/ir_Whirlpool.h \ + $(USER_DIR)/ir_Vestel.h \ + $(USER_DIR)/ir_Tcl.h \ + $(USER_DIR)/ir_Teco.h # Common object files -COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o ir_GlobalCache.o \ +COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o IRac.o ir_GlobalCache.o \ $(PROTOCOLS) gtest_main.a # Common dependencies COMMON_DEPS = $(USER_DIR)/IRrecv.h $(USER_DIR)/IRsend.h $(USER_DIR)/IRtimer.h \ $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h \ - $(PROTOCOLS_H) + $(USER_DIR)/IRac.h $(PROTOCOLS_H) # Common test dependencies COMMON_TEST_DEPS = $(COMMON_DEPS) IRrecv_test.h IRsend_test.h @@ -136,7 +144,7 @@ IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteES $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRutils.cpp IRutils_test.o : IRutils_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c IRutils_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c IRutils_test.cpp IRutils_test : IRutils_test.o ir_NEC.o ir_Nikai.o ir_Toshiba.o $(COMMON_OBJ) gtest_main.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -148,7 +156,7 @@ IRsend.o : $(USER_DIR)/IRsend.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRremoteESP82 $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRsend.cpp IRsend_test.o : IRsend_test.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRrecv.h IRsend_test.h $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c IRsend_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c IRsend_test.cpp IRsend_test : IRsend_test.o $(COMMON_OBJ) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -157,16 +165,25 @@ IRrecv.o : $(USER_DIR)/IRrecv.cpp $(USER_DIR)/IRrecv.h $(USER_DIR)/IRremoteESP82 $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRrecv.cpp IRrecv_test.o : IRrecv_test.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRrecv.h IRsend_test.h $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c IRrecv_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c IRrecv_test.cpp IRrecv_test : IRrecv_test.o $(COMMON_OBJ) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ +IRac.o : $(USER_DIR)/IRac.cpp $(USER_DIR)/IRac.h $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/IRac.cpp + +IRac_test.o : IRac_test.cpp $(USER_DIR)/IRac.h $(COMMON_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c IRac_test.cpp + +IRac_test : IRac_test.o $(COMMON_OBJ) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + ir_NEC.o : $(USER_DIR)/ir_NEC.cpp $(USER_DIR)/ir_NEC.h $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_NEC.cpp ir_NEC_test.o : ir_NEC_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_NEC_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_NEC_test.cpp ir_NEC_test : $(COMMON_OBJ) ir_NEC_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -175,7 +192,7 @@ ir_GlobalCache.o : $(USER_DIR)/ir_GlobalCache.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_GlobalCache.cpp ir_GlobalCache_test.o : ir_GlobalCache_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_GlobalCache_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_GlobalCache_test.cpp ir_GlobalCache_test : $(COMMON_OBJ) ir_GlobalCache_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -184,7 +201,7 @@ ir_Sherwood.o : $(USER_DIR)/ir_Sherwood.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sherwood.cpp ir_Sherwood_test.o : ir_Sherwood_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Sherwood_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Sherwood_test.cpp ir_Sherwood_test : $(COMMON_OBJ) ir_Sherwood_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -193,25 +210,25 @@ ir_Sony.o : $(USER_DIR)/ir_Sony.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sony.cpp ir_Sony_test.o : ir_Sony_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Sony_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Sony_test.cpp ir_Sony_test : $(COMMON_OBJ) ir_Sony_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(USER_DIR)/ir_Samsung.h $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Samsung.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Samsung.cpp ir_Samsung_test.o : ir_Samsung_test.cpp $(USER_DIR)/ir_Samsung.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Samsung_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Samsung_test.cpp ir_Samsung_test : $(COMMON_OBJ) ir_Samsung_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Kelvinator.o : $(USER_DIR)/ir_Kelvinator.cpp $(USER_DIR)/ir_Kelvinator.h $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Kelvinator.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Kelvinator.cpp ir_Kelvinator_test.o : ir_Kelvinator_test.cpp $(USER_DIR)/ir_Kelvinator.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Kelvinator_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Kelvinator_test.cpp ir_Kelvinator_test : $(COMMON_OBJ) ir_Kelvinator_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -220,7 +237,7 @@ ir_JVC.o : $(USER_DIR)/ir_JVC.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_JVC.cpp ir_JVC_test.o : ir_JVC_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_JVC_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_JVC_test.cpp ir_JVC_test : $(COMMON_OBJ) ir_JVC_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -229,7 +246,7 @@ ir_RCMM.o : $(USER_DIR)/ir_RCMM.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_RCMM.cpp ir_RCMM_test.o : ir_RCMM_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_RCMM_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_RCMM_test.cpp ir_RCMM_test : $(COMMON_OBJ) ir_RCMM_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -238,25 +255,34 @@ ir_LG.o : $(USER_DIR)/ir_LG.h $(USER_DIR)/ir_LG.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_LG.cpp ir_LG_test.o : ir_LG_test.cpp $(USER_DIR)/ir_LG.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_LG_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_LG_test.cpp ir_LG_test : $(COMMON_OBJ) ir_LG_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Mitsubishi.o : $(USER_DIR)/ir_Mitsubishi.h $(USER_DIR)/ir_Mitsubishi.cpp $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Mitsubishi.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Mitsubishi.cpp ir_Mitsubishi_test.o : ir_Mitsubishi_test.cpp $(USER_DIR)/ir_Mitsubishi.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Mitsubishi_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Mitsubishi_test.cpp ir_Mitsubishi_test : $(COMMON_OBJ) ir_Mitsubishi_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ +ir_MitsubishiHeavy.o : $(USER_DIR)/ir_MitsubishiHeavy.h $(USER_DIR)/ir_MitsubishiHeavy.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_MitsubishiHeavy.cpp + +ir_MitsubishiHeavy_test.o : ir_MitsubishiHeavy_test.cpp $(USER_DIR)/ir_MitsubishiHeavy.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_MitsubishiHeavy_test.cpp + +ir_MitsubishiHeavy_test : $(COMMON_OBJ) ir_MitsubishiHeavy_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + ir_Fujitsu.o : $(USER_DIR)/ir_Fujitsu.h $(USER_DIR)/ir_Fujitsu.cpp $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Fujitsu.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Fujitsu.cpp ir_Fujitsu_test.o : ir_Fujitsu_test.cpp $(USER_DIR)/ir_Fujitsu.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Fujitsu_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Fujitsu_test.cpp ir_Fujitsu_test : $(COMMON_OBJ) ir_Fujitsu_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -265,7 +291,7 @@ ir_Sharp.o : $(USER_DIR)/ir_Sharp.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sharp.cpp ir_Sharp_test.o : ir_Sharp_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Sharp_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Sharp_test.cpp ir_Sharp_test : $(COMMON_OBJ) ir_Sharp_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -274,16 +300,16 @@ ir_RC5_RC6.o : $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_RC5_RC6.cpp ir_RC5_RC6_test.o : ir_RC5_RC6_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_RC5_RC6_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_RC5_RC6_test.cpp ir_RC5_RC6_test : $(COMMON_OBJ) ir_RC5_RC6_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Panasonic.o : $(USER_DIR)/ir_Panasonic.cpp $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Panasonic.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Panasonic.cpp ir_Panasonic_test.o : ir_Panasonic_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Panasonic_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Panasonic_test.cpp ir_Panasonic_test : $(COMMON_OBJ) ir_Panasonic_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -292,7 +318,7 @@ ir_Dish.o : $(USER_DIR)/ir_Dish.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Dish.cpp ir_Dish_test.o : ir_Dish_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Dish_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Dish_test.cpp ir_Dish_test : $(COMMON_OBJ) ir_Dish_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -301,16 +327,16 @@ ir_Whynter.o : $(USER_DIR)/ir_Whynter.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whynter.cpp ir_Whynter_test.o : ir_Whynter_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Whynter_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Whynter_test.cpp ir_Whynter_test : $(COMMON_OBJ) ir_Whynter_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Coolix.o : $(USER_DIR)/ir_Coolix.cpp $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Coolix.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Coolix.cpp ir_Coolix_test.o : ir_Coolix_test.cpp $(USER_DIR)/ir_Coolix.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Coolix_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Coolix_test.cpp ir_Coolix_test : $(COMMON_OBJ) ir_Coolix_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -319,7 +345,7 @@ ir_Aiwa.o : $(USER_DIR)/ir_Aiwa.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Aiwa.cpp ir_Aiwa_test.o : ir_Aiwa_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Aiwa_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Aiwa_test.cpp ir_Aiwa_test : $(COMMON_OBJ) ir_Aiwa_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -328,7 +354,7 @@ ir_Denon.o : $(USER_DIR)/ir_Denon.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Denon.cpp ir_Denon_test.o : ir_Denon_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Denon_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Denon_test.cpp ir_Denon_test : $(COMMON_OBJ) ir_Denon_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -337,25 +363,25 @@ ir_Sanyo.o : $(USER_DIR)/ir_Sanyo.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sanyo.cpp ir_Sanyo_test.o : ir_Sanyo_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Sanyo_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Sanyo_test.cpp ir_Sanyo_test : $(COMMON_OBJ) ir_Sanyo_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Daikin.o : $(USER_DIR)/ir_Daikin.cpp $(USER_DIR)/ir_Daikin.h $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Daikin.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Daikin.cpp ir_Daikin_test.o : ir_Daikin_test.cpp $(USER_DIR)/ir_Daikin.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Daikin_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Daikin_test.cpp ir_Daikin_test : $(COMMON_OBJ) ir_Daikin_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Gree.o : $(USER_DIR)/ir_Gree.cpp $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Gree.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Gree.cpp ir_Gree_test.o : ir_Gree_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Gree_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Gree_test.cpp ir_Gree_test : $(COMMON_OBJ) ir_Gree_test.o ir_Kelvinator.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -364,7 +390,7 @@ ir_Pronto.o : $(USER_DIR)/ir_Pronto.cpp $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Pronto.cpp ir_Pronto_test.o : ir_Pronto_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Pronto_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Pronto_test.cpp ir_Pronto_test : $(COMMON_OBJ) ir_Pronto_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -373,25 +399,25 @@ ir_Nikai.o : $(USER_DIR)/ir_Nikai.cpp $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Nikai.cpp ir_Nikai_test.o : ir_Nikai_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Nikai_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Nikai_test.cpp ir_Nikai_test : $(COMMON_OBJ) ir_Nikai_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Toshiba.o : $(USER_DIR)/ir_Toshiba.cpp $(USER_DIR)/ir_Toshiba.h $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Toshiba.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Toshiba.cpp ir_Toshiba_test.o : ir_Toshiba_test.cpp $(USER_DIR)/ir_Toshiba.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Toshiba_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Toshiba_test.cpp ir_Toshiba_test : $(COMMON_OBJ) ir_Toshiba_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Midea.o : $(USER_DIR)/ir_Midea.cpp $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Midea.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Midea.cpp ir_Midea_test.o : ir_Midea_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Midea_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Midea_test.cpp ir_Midea_test : $(COMMON_OBJ) ir_Midea_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -400,7 +426,7 @@ ir_Magiquest.o : $(USER_DIR)/ir_Magiquest.cpp $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Magiquest.cpp ir_Magiquest_test.o : ir_Magiquest_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Magiquest_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Magiquest_test.cpp ir_Magiquest_test : $(COMMON_OBJ) ir_Magiquest_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -409,7 +435,7 @@ ir_Lasertag.o : $(USER_DIR)/ir_Lasertag.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(GTEST_H $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lasertag.cpp ir_Lasertag_test.o : ir_Lasertag_test.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Lasertag_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Lasertag_test.cpp ir_Lasertag_test : $(COMMON_OBJ) ir_Lasertag_test.o ir_RC5_RC6.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -418,25 +444,25 @@ ir_Carrier.o : $(USER_DIR)/ir_Carrier.cpp $(COMMON_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Carrier.cpp ir_Carrier_test.o : ir_Carrier_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Carrier_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Carrier_test.cpp ir_Carrier_test : $(COMMON_OBJ) ir_Carrier_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Haier.o : $(USER_DIR)/ir_Haier.cpp $(USER_DIR)/ir_Haier.h $(COMMON_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Haier.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Haier.cpp ir_Haier_test.o : ir_Haier_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Haier_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Haier_test.cpp ir_Haier_test : $(COMMON_OBJ) ir_Haier_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Hitachi.o : $(USER_DIR)/ir_Hitachi.cpp $(COMMON_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Hitachi.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Hitachi.cpp ir_Hitachi_test.o : ir_Hitachi_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Hitachi_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Hitachi_test.cpp ir_Hitachi_test : $(COMMON_OBJ) ir_Hitachi_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -445,16 +471,16 @@ ir_GICable.o : $(USER_DIR)/ir_GICable.cpp $(COMMON_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_GICable.cpp ir_GICable_test.o : ir_GICable_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_GICable_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_GICable_test.cpp ir_GICable_test : $(COMMON_OBJ) ir_GICable_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ ir_Whirlpool.o : $(USER_DIR)/ir_Whirlpool.cpp $(COMMON_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whirlpool.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Whirlpool.cpp ir_Whirlpool_test.o : ir_Whirlpool_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Whirlpool_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Whirlpool_test.cpp ir_Whirlpool_test : $(COMMON_OBJ) ir_Whirlpool_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -463,7 +489,7 @@ ir_Lutron.o : $(USER_DIR)/ir_Lutron.cpp $(COMMON_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lutron.cpp ir_Lutron_test.o : ir_Lutron_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Lutron_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Lutron_test.cpp ir_Lutron_test : $(COMMON_OBJ) ir_Lutron_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -472,7 +498,7 @@ ir_Electra.o : $(USER_DIR)/ir_Electra.cpp $(COMMON_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Electra.cpp ir_Electra_test.o : ir_Electra_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Electra_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Electra_test.cpp ir_Electra_test : $(COMMON_OBJ) ir_Electra_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -481,7 +507,7 @@ ir_Pioneer.o : $(USER_DIR)/ir_Pioneer.cpp $(COMMON_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Pioneer.cpp ir_Pioneer_test.o : ir_Pioneer_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Pioneer_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Pioneer_test.cpp ir_Pioneer_test : $(COMMON_OBJ) ir_Pioneer_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -490,7 +516,49 @@ ir_MWM.o : $(USER_DIR)/ir_MWM.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_MWM.cpp ir_MWM_test.o : ir_MWM_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_MWM_test.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_MWM_test.cpp ir_MWM_test : $(COMMON_OBJ) ir_MWM_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Vestel.o : $(USER_DIR)/ir_Vestel.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Vestel.cpp + +ir_Vestel_test.o : ir_Vestel_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Vestel_test.cpp + +ir_Vestel_test : $(COMMON_OBJ) ir_Vestel_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Teco.o : $(USER_DIR)/ir_Teco.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Teco.cpp + +ir_Teco_test.o : ir_Teco_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Teco_test.cpp + +ir_Teco_test : $(COMMON_OBJ) ir_Teco_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Tcl.o : $(USER_DIR)/ir_Tcl.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Tcl.cpp + +ir_Tcl_test.o : ir_Tcl_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Tcl_test.cpp + +ir_Tcl_test : $(COMMON_OBJ) ir_Tcl_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Lego.o : $(USER_DIR)/ir_Lego.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lego.cpp + +ir_Lego_test.o : ir_Lego_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Lego_test.cpp + +ir_Lego_test : $(COMMON_OBJ) ir_Lego_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Argo.o : $(USER_DIR)/ir_Argo.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Argo.cpp + +ir_Trotec.o : $(USER_DIR)/ir_Trotec.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Trotec.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Aiwa_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Aiwa_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Aiwa_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Aiwa_test.cpp index c5469d4a5..2fa63afe6 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Aiwa_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Aiwa_test.cpp @@ -14,6 +14,7 @@ TEST(TestSendAiwa, SendDataOnly) { irsend.reset(); irsend.sendAiwaRCT501(0x7F); // Aiwa Power Toggle. EXPECT_EQ( + "f38000d33" "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" @@ -43,6 +44,7 @@ TEST(TestSendAiwa, SendWithRepeats) { irsend.reset(); irsend.sendAiwaRCT501(0x7F, kAiwaRcT501Bits, 0); // No repeats. EXPECT_EQ( + "f38000d33" "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" @@ -54,6 +56,7 @@ TEST(TestSendAiwa, SendWithRepeats) { irsend.reset(); irsend.sendAiwaRCT501(0x7F, kAiwaRcT501Bits, 1); // 1 repeat. EXPECT_EQ( + "f38000d33" "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" @@ -66,6 +69,7 @@ TEST(TestSendAiwa, SendWithRepeats) { irsend.reset(); irsend.sendAiwaRCT501(0x7F, kAiwaRcT501Bits, 2); // 2 repeats. EXPECT_EQ( + "f38000d33" "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" @@ -86,6 +90,7 @@ TEST(TestSendAiwa, SendUnusualSize) { irsend.reset(); irsend.sendAiwaRCT501(0x12, 8); EXPECT_EQ( + "f38000d33" "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" @@ -98,6 +103,7 @@ TEST(TestSendAiwa, SendUnusualSize) { irsend.reset(); irsend.sendAiwaRCT501(0x1234567890, 37); EXPECT_EQ( + "f38000d33" "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Carrier_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Carrier_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Carrier_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Carrier_test.cpp index 24bdc232a..053b31dd4 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Carrier_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Carrier_test.cpp @@ -15,6 +15,7 @@ TEST(TestSendCarrierAC, SendDataOnly) { irsend.reset(); irsend.sendCarrierAC(0x0); EXPECT_EQ( + "f38000d50" "m8532s4228" "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" "m628s532m628s532m628s532m628s532m628s532m628s532m628s532m628s532" @@ -37,6 +38,7 @@ TEST(TestSendCarrierAC, SendDataOnly) { irsend.reset(); irsend.sendCarrierAC(0x12345678); EXPECT_EQ( + "f38000d50" "m8532s4228" "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" @@ -60,6 +62,7 @@ TEST(TestSendCarrierAC, SendDataOnly) { irsend.reset(); irsend.sendCarrierAC(0x4CCA541D); EXPECT_EQ( + "f38000d50" "m8532s4228" "m628s532m628s1320m628s532m628s532m628s1320m628s1320m628s532m628s532" "m628s1320m628s1320m628s532m628s532m628s1320m628s532m628s1320m628s532" @@ -89,6 +92,7 @@ TEST(TestSendCarrierAC, SendWithRepeats) { irsend.reset(); irsend.sendCarrierAC(0x12345678, kCarrierAcBits, 2); // two repeats. EXPECT_EQ( + "f38000d50" "m8532s4228" "m628s532m628s532m628s532m628s1320m628s532m628s532m628s1320m628s532" "m628s532m628s532m628s1320m628s1320m628s532m628s1320m628s532m628s532" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Coolix_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Coolix_test.cpp similarity index 70% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Coolix_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Coolix_test.cpp index 8b096ffca..0f97c5ead 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Coolix_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Coolix_test.cpp @@ -15,6 +15,15 @@ TEST(TestSendCoolix, SendDataOnly) { irsend.reset(); irsend.sendCOOLIX(0x0); EXPECT_EQ( + "f38000d50" + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s5040" "m4480s4480" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" @@ -28,6 +37,15 @@ TEST(TestSendCoolix, SendDataOnly) { irsend.reset(); irsend.sendCOOLIX(0xAA55AA); EXPECT_EQ( + "f38000d50" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5040" "m4480s4480" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" @@ -41,6 +59,15 @@ TEST(TestSendCoolix, SendDataOnly) { irsend.reset(); irsend.sendCOOLIX(0xFFFFFF); EXPECT_EQ( + "f38000d50" + "m4480s4480" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s5040" "m4480s4480" "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" @@ -60,6 +87,7 @@ TEST(TestSendCoolix, SendWithRepeats) { irsend.reset(); irsend.sendCOOLIX(0xAA55AA, kCoolixBits, 1); // 1 repeat. EXPECT_EQ( + "f38000d50" "m4480s4480" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" @@ -79,6 +107,7 @@ TEST(TestSendCoolix, SendWithRepeats) { irsend.outputStr()); irsend.sendCOOLIX(0xAA55AA, kCoolixBits, 2); // 2 repeats. EXPECT_EQ( + "f38000d50" "m4480s4480" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" @@ -114,6 +143,11 @@ TEST(TestSendCoolix, SendUnusualSize) { irsend.reset(); irsend.sendCOOLIX(0x0, 8); EXPECT_EQ( + "f38000d50" + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s5040" "m4480s4480" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" @@ -123,6 +157,25 @@ TEST(TestSendCoolix, SendUnusualSize) { irsend.reset(); irsend.sendCOOLIX(0x1234567890ABCDEF, 64); EXPECT_EQ( + "f38000d50" + "m4480s4480" + "m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680m560s560" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s1680" + "m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s1680m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560m560s1680" + "m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680" + "m560s1680m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560" + "m560s1680m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" + "m560s560m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" + "m560s5040" "m4480s4480" "m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680m560s560" "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s1680" @@ -411,7 +464,7 @@ TEST(TestCoolixACClass, HumanReadable) { // Initial starting point. EXPECT_EQ( - "Power: On, Fan: 5 (AUTO), Mode: 2 (AUTO), Temp: 25C, " + "Power: On, Mode: 2 (AUTO), Fan: 5 (AUTO), Temp: 25C, " "Zone Follow: Off, Sensor Temp: Ignored", ircoolix.toString()); @@ -420,11 +473,11 @@ TEST(TestCoolixACClass, HumanReadable) { ircoolix.setMode(kCoolixCool); ircoolix.setFan(kCoolixFanMin); EXPECT_EQ( - "Power: On, Fan: 4 (MIN), Mode: 0 (COOL), Temp: 22C, " + "Power: On, Mode: 0 (COOL), Fan: 4 (MIN), Temp: 22C, " "Zone Follow: On, Sensor Temp: 24C", ircoolix.toString()); ircoolix.setSwing(); - EXPECT_EQ("Power: On, Fan: 3 (UNKNOWN), Swing: Toggle", ircoolix.toString()); + EXPECT_EQ("Power: On, Swing: Toggle", ircoolix.toString()); ircoolix.setPower(false); EXPECT_EQ("Power: Off", ircoolix.toString()); } @@ -434,12 +487,113 @@ TEST(TestCoolixACClass, KnownExamples) { ircoolix.setRaw(0b101100101011111111100100); EXPECT_EQ( - "Power: On, Fan: 5 (AUTO), Mode: 4 (FAN), Zone Follow: Off, " + "Power: On, Mode: 4 (FAN), Fan: 5 (AUTO), Zone Follow: Off, " "Sensor Temp: Ignored", ircoolix.toString()); ircoolix.setRaw(0b101100101001111100000000); EXPECT_EQ( - "Power: On, Fan: 4 (MIN), Mode: 0 (COOL), Temp: 17C, " + "Power: On, Mode: 0 (COOL), Fan: 4 (MIN), Temp: 17C, " "Zone Follow: Off, Sensor Temp: Ignored", ircoolix.toString()); } + +TEST(TestCoolixACClass, Issue579FanAuto0) { + IRCoolixAC ircoolix(0); + + ircoolix.setRaw(0xB21F28); + EXPECT_EQ( + "Power: On, Mode: 2 (AUTO), Fan: 0 (AUTO0), Temp: 20C, " + "Zone Follow: Off, Sensor Temp: Ignored", + ircoolix.toString()); +} + +TEST(TestCoolixACClass, RealCaptureExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + + // From Issue #579 + uint16_t powerOffRawData[199] = { + 4444, 4434, 590, 1578, 698, 446, 590, 1578, 622, 1596, 622, 500, + 644, 476, 644, 1548, 588, 532, 594, 530, 612, 1578, 590, 532, + 588, 534, 672, 1518, 594, 1598, 590, 510, 612, 1580, 644, 480, + 612, 1578, 644, 1548, 644, 1548, 594, 1598, 642, 506, 644, 1550, + 644, 1548, 594, 1600, 644, 478, 644, 478, 642, 480, 644, 478, + 642, 1548, 594, 530, 590, 532, 614, 1578, 644, 1548, 594, 1600, + 588, 534, 566, 556, 588, 530, 590, 532, 586, 514, 612, 532, + 588, 532, 590, 534, 588, 1578, 642, 1576, 642, 1550, 588, 1602, + 588, 1580, 642, 4712, 4546, 4406, 588, 1606, 642, 478, 644, 1550, + 590, 1604, 588, 534, 586, 532, 586, 1582, 642, 480, 642, 480, + 668, 1550, 642, 480, 642, 478, 642, 1552, 612, 1578, 586, 538, + 588, 1580, 674, 472, 590, 1602, 586, 1580, 618, 1576, 642, 1548, + 594, 530, 590, 1584, 608, 1578, 644, 1550, 642, 480, 642, 478, + 642, 480, 642, 480, 642, 1550, 590, 530, 592, 528, 592, 1602, + 642, 1548, 592, 1604, 586, 584, 642, 480, 640, 480, 640, 480, + 642, 480, 642, 480, 642, 480, 642, 480, 642, 1552, 590, 1604, + 588, 1578, 642, 1552, 640, 1550, 592}; // COOLIX B27BE0 + + irsend.begin(); + + irsend.reset(); + + irsend.sendRaw(powerOffRawData, 199, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(COOLIX, irsend.capture.decode_type); + EXPECT_EQ(kCoolixBits, irsend.capture.bits); + EXPECT_EQ(kCoolixOff, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + + +// Tests to debug/fix: +// https://github.com/markszabo/IRremoteESP8266/issues/624 +TEST(TestCoolixACClass, Issue624HandleSpecialStatesBetter) { + IRCoolixAC ac(0); + ac.begin(); + // Default + EXPECT_EQ( + "Power: On, Mode: 2 (AUTO), Fan: 5 (AUTO), Temp: 25C, Zone Follow: Off, " + "Sensor Temp: Ignored", + ac.toString()); + EXPECT_EQ(0xB2BFC8, ac.getRaw()); + // Change of settings. + ac.setPower(true); + ac.setTemp(24); + ac.setMode(kCoolixCool); + ac.setFan(kCoolixFanAuto); + EXPECT_EQ( + "Power: On, Mode: 0 (COOL), Fan: 5 (AUTO), Temp: 24C, Zone Follow: Off, " + "Sensor Temp: Ignored", + ac.toString()); + EXPECT_EQ(0xB2BF40, ac.getRaw()); + // Turn the unit off. + ac.setPower(false); + EXPECT_EQ( + "Power: Off", + ac.toString()); + EXPECT_EQ(kCoolixOff, ac.getRaw()); + // Repeat change of settings. + ac.setPower(true); + ac.setTemp(24); + ac.setMode(kCoolixCool); + ac.setFan(kCoolixFanAuto); + EXPECT_EQ( + "Power: On, Mode: 0 (COOL), Fan: 5 (AUTO), Temp: 24C, Zone Follow: Off, " + "Sensor Temp: Ignored", + ac.toString()); + EXPECT_EQ(0xB2BF40, ac.getRaw()); + + // Now test if we setRaw() a special state first. + ac.setRaw(kCoolixSwing); + // Repeat change of settings. + ac.setPower(true); + ac.setTemp(24); + ac.setMode(kCoolixCool); + ac.setFan(kCoolixFanAuto); + EXPECT_EQ( + "Power: On, Mode: 0 (COOL), Fan: 5 (AUTO), Temp: 24C, Zone Follow: Off, " + "Sensor Temp: Ignored", + ac.toString()); + EXPECT_EQ(0xB2BF40, ac.getRaw()); +} diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Daikin_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Daikin_test.cpp new file mode 100644 index 000000000..67d144d54 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Daikin_test.cpp @@ -0,0 +1,1880 @@ +// Copyright 2017 David Conran +#include "ir_Daikin.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendDaikin(). + +// Test sending typical data only. +TEST(TestSendDaikin, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + uint8_t daikin_code[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3}; + + irsend.reset(); + irsend.sendDaikin(daikin_code); + EXPECT_EQ( + "f38000d50" + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428" + "m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428" + "m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" + "m428s29428" + "m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" + "m428s29428", + irsend.outputStr()); +} + +// Test sending with repeats. +TEST(TestSendDaikin, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + uint8_t daikin_code[kDaikinStateLengthShort] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3}; + irsend.reset(); + + irsend.sendDaikin(daikin_code, kDaikinStateLengthShort, 1); + EXPECT_EQ( + "f38000d50" + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" + "m428s29428" + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" + "m428s29428", + irsend.outputStr()); +} + +// Test sending atypical sizes. +TEST(TestSendDaikin, SendUnexpectedSizes) { + IRsendTest irsend(4); + irsend.begin(); + + uint8_t daikin_short_code[kDaikinStateLengthShort - 1] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00}; + + irsend.reset(); + irsend.sendDaikin(daikin_short_code, kDaikinStateLengthShort - 1); + ASSERT_EQ("", irsend.outputStr()); + + uint8_t daikin_long_code[kDaikinStateLengthShort + 1] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x20, 0x11, 0xDA, + 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE3, 0x11}; + irsend.reset(); + irsend.sendDaikin(daikin_long_code, kDaikinStateLengthShort + 1); + ASSERT_EQ( + "f38000d50" + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s428m428s428m428s428m428s1280m428s1280m428s1280" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s29428", + irsend.outputStr()); +} + +// Tests for IRDaikinESP class. + +TEST(TestDaikinClass, Power) { + IRDaikinESP ac(0); + ac.begin(); + + ac.on(); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_FALSE(ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestDaikinClass, Temperature) { + IRDaikinESP ac(0); + ac.begin(); + + ac.setTemp(0); + EXPECT_EQ(kDaikinMinTemp, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kDaikinMaxTemp, ac.getTemp()); + + ac.setTemp(kDaikinMinTemp); + EXPECT_EQ(kDaikinMinTemp, ac.getTemp()); + + ac.setTemp(kDaikinMaxTemp); + EXPECT_EQ(kDaikinMaxTemp, ac.getTemp()); + + ac.setTemp(kDaikinMinTemp - 1); + EXPECT_EQ(kDaikinMinTemp, ac.getTemp()); + + ac.setTemp(kDaikinMaxTemp + 1); + EXPECT_EQ(kDaikinMaxTemp, ac.getTemp()); + + ac.setTemp(kDaikinMinTemp + 1); + EXPECT_EQ(kDaikinMinTemp + 1, ac.getTemp()); + + ac.setTemp(21); + EXPECT_EQ(21, ac.getTemp()); + + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + + ac.setTemp(29); + EXPECT_EQ(29, ac.getTemp()); +} + +TEST(TestDaikinClass, OperatingMode) { + IRDaikinESP ac(0); + ac.begin(); + + ac.setMode(kDaikinAuto); + EXPECT_EQ(kDaikinAuto, ac.getMode()); + + ac.setMode(kDaikinCool); + EXPECT_EQ(kDaikinCool, ac.getMode()); + + ac.setMode(kDaikinHeat); + EXPECT_EQ(kDaikinHeat, ac.getMode()); + + ac.setMode(kDaikinDry); + EXPECT_EQ(kDaikinDry, ac.getMode()); + + ac.setMode(kDaikinFan); + EXPECT_EQ(kDaikinFan, ac.getMode()); + + ac.setMode(kDaikinFan + 1); + EXPECT_EQ(kDaikinAuto, ac.getMode()); + + ac.setMode(kDaikinAuto + 1); + EXPECT_EQ(kDaikinAuto, ac.getMode()); + + ac.setMode(255); + EXPECT_EQ(kDaikinAuto, ac.getMode()); +} + +TEST(TestDaikinClass, VaneSwing) { + IRDaikinESP ac(0); + ac.begin(); + + ac.setSwingHorizontal(true); + ac.setSwingVertical(false); + + ac.setSwingHorizontal(true); + EXPECT_TRUE(ac.getSwingHorizontal()); + EXPECT_FALSE(ac.getSwingVertical()); + + ac.setSwingVertical(true); + EXPECT_TRUE(ac.getSwingHorizontal()); + EXPECT_TRUE(ac.getSwingVertical()); + + ac.setSwingHorizontal(false); + EXPECT_FALSE(ac.getSwingHorizontal()); + EXPECT_TRUE(ac.getSwingVertical()); + + ac.setSwingVertical(false); + EXPECT_FALSE(ac.getSwingHorizontal()); + EXPECT_FALSE(ac.getSwingVertical()); +} + +TEST(TestDaikinClass, QuietMode) { + IRDaikinESP ac(0); + ac.begin(); + + ac.setQuiet(true); + EXPECT_TRUE(ac.getQuiet()); + + ac.setQuiet(false); + EXPECT_FALSE(ac.getQuiet()); + + ac.setQuiet(true); + EXPECT_TRUE(ac.getQuiet()); + + // Setting Econo mode should NOT change out of quiet mode. + ac.setEcono(true); + EXPECT_TRUE(ac.getQuiet()); + ac.setEcono(false); + EXPECT_TRUE(ac.getQuiet()); + + // But setting Powerful mode should exit out of quiet mode. + ac.setPowerful(true); + EXPECT_FALSE(ac.getQuiet()); +} + +TEST(TestDaikinClass, PowerfulMode) { + IRDaikinESP ac(0); + ac.begin(); + + ac.setPowerful(true); + EXPECT_TRUE(ac.getPowerful()); + + ac.setPowerful(false); + EXPECT_FALSE(ac.getPowerful()); + + ac.setPowerful(true); + EXPECT_TRUE(ac.getPowerful()); + + ac.setQuiet(true); + EXPECT_FALSE(ac.getPowerful()); + + ac.setPowerful(true); + ac.setEcono(true); + EXPECT_FALSE(ac.getPowerful()); +} + +TEST(TestDaikinClass, EconoMode) { + IRDaikinESP ac(0); + ac.begin(); + + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); + + ac.setEcono(false); + EXPECT_FALSE(ac.getEcono()); + + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); + + // Setting Quiet mode should NOT change out of Econo mode. + ac.setQuiet(true); + EXPECT_TRUE(ac.getEcono()); + ac.setQuiet(false); + EXPECT_TRUE(ac.getEcono()); + + // But setting Powerful mode should exit out of Econo mode. + ac.setPowerful(true); + EXPECT_FALSE(ac.getEcono()); +} + +TEST(TestDaikinClass, FanSpeed) { + IRDaikinESP ac(0); + ac.begin(); + + // Unexpected value should default to Auto. + ac.setFan(0); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + // Unexpected value should default to Auto. + ac.setFan(255); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(kDaikinFanMax); + EXPECT_EQ(kDaikinFanMax, ac.getFan()); + + // Beyond Max should default to Auto. + ac.setFan(kDaikinFanMax + 1); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(kDaikinFanMax - 1); + EXPECT_EQ(kDaikinFanMax - 1, ac.getFan()); + + ac.setFan(kDaikinFanMin); + EXPECT_EQ(kDaikinFanMin, ac.getFan()); + + ac.setFan(kDaikinFanMin + 1); + EXPECT_EQ(kDaikinFanMin + 1, ac.getFan()); + + // Beyond Min should default to Auto. + ac.setFan(kDaikinFanMin - 1); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(3); + EXPECT_EQ(3, ac.getFan()); + + ac.setFan(kDaikinFanAuto); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(kDaikinFanQuiet); + EXPECT_EQ(kDaikinFanQuiet, ac.getFan()); +} + +TEST(TestDaikinClass, CurrentTime) { + IRDaikinESP ac(0); + ac.begin(); + + ac.setCurrentTime(0); // 00:00 + EXPECT_EQ(0, ac.getCurrentTime()); + + ac.setCurrentTime(754); // 12:34 + EXPECT_EQ(754, ac.getCurrentTime()); + + ac.setCurrentTime(1439); // 23:59 + EXPECT_EQ(1439, ac.getCurrentTime()); +} + +TEST(TestDaikinClass, OnOffTimers) { + IRDaikinESP ac(0); + ac.begin(); + + // Both timers turned off. + ac.disableOnTimer(); + ac.disableOffTimer(); + EXPECT_FALSE(ac.getOnTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOnTime()); + EXPECT_FALSE(ac.getOffTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOffTime()); + + // Turn on just the On Timer. + ac.enableOnTimer(123); + EXPECT_TRUE(ac.getOnTimerEnabled()); + EXPECT_EQ(123, ac.getOnTime()); + EXPECT_FALSE(ac.getOffTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOffTime()); + + // Now turn on the Off Timer. + ac.enableOffTimer(754); + EXPECT_TRUE(ac.getOffTimerEnabled()); + EXPECT_EQ(754, ac.getOffTime()); + EXPECT_TRUE(ac.getOnTimerEnabled()); + EXPECT_EQ(123, ac.getOnTime()); + + // Turn off the just the On Timer. + ac.disableOnTimer(); + EXPECT_FALSE(ac.getOnTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOnTime()); + EXPECT_TRUE(ac.getOffTimerEnabled()); + EXPECT_EQ(754, ac.getOffTime()); + + // Now turn off the Off Timer. + ac.disableOffTimer(); + EXPECT_FALSE(ac.getOffTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOffTime()); + EXPECT_FALSE(ac.getOnTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOnTime()); + + // Use some canary values around the timers to ensure no accidental + // bit flips happen. i.e. Neighbouring bytes in the state. + // (Found some during testing on systems with different endian-ness) + // Tests here to make sure it never happens again. + ac.setSwingHorizontal(true); + ac.setPowerful(true); + ac.disableOffTimer(); + ac.disableOnTimer(); + ASSERT_TRUE(ac.getSwingHorizontal()); + ASSERT_TRUE(ac.getPowerful()); + ac.enableOnTimer(123); + ac.enableOffTimer(456); + ASSERT_TRUE(ac.getSwingHorizontal()); + ASSERT_TRUE(ac.getPowerful()); + ac.disableOffTimer(); + ac.disableOnTimer(); + ASSERT_TRUE(ac.getSwingHorizontal()); + ASSERT_TRUE(ac.getPowerful()); + + ac.setSwingHorizontal(false); + ac.setPowerful(false); + ac.disableOffTimer(); + ac.disableOnTimer(); + ASSERT_FALSE(ac.getSwingHorizontal()); + ASSERT_FALSE(ac.getPowerful()); + ac.enableOnTimer(123); + ac.enableOffTimer(456); + ASSERT_FALSE(ac.getSwingHorizontal()); + ASSERT_FALSE(ac.getPowerful()); + ac.disableOffTimer(); + ac.disableOnTimer(); + ASSERT_FALSE(ac.getSwingHorizontal()); + ASSERT_FALSE(ac.getPowerful()); +} + +// Test Eye mode. +TEST(TestDaikinClass, EyeSetting) { + IRDaikinESP ac(0); + ac.begin(); + + // The Eye setting is stored in the same byte as Econo mode. + // Econo mode tests are there to make sure it isn't harmed and vice-versa. + ac.setEcono(false); + ac.setEye(false); + ASSERT_FALSE(ac.getEye()); + EXPECT_FALSE(ac.getEcono()); + + ac.setEye(true); + ASSERT_TRUE(ac.getEye()); + EXPECT_FALSE(ac.getEcono()); + + ac.setEcono(false); + ASSERT_TRUE(ac.getEye()); + EXPECT_FALSE(ac.getEcono()); + + ac.setEcono(true); + ASSERT_TRUE(ac.getEye()); + EXPECT_TRUE(ac.getEcono()); + + ac.setEye(false); + ASSERT_FALSE(ac.getEye()); + EXPECT_TRUE(ac.getEcono()); +} + +// Test Mold mode. +TEST(TestDaikinClass, MoldSetting) { + IRDaikinESP ac(0); + ac.begin(); + + ac.setMold(false); + ASSERT_FALSE(ac.getMold()); + + ac.setMold(true); + ASSERT_TRUE(ac.getMold()); + + ac.setMold(false); + ASSERT_FALSE(ac.getMold()); +} + +// Test Comfort mode. +TEST(TestDaikinClass, ComfortSetting) { + IRDaikinESP ac(0); + ac.begin(); + + ac.setComfort(false); + ASSERT_FALSE(ac.getComfort()); + + ac.setComfort(true); + ASSERT_TRUE(ac.getComfort()); + + ac.setComfort(false); + ASSERT_FALSE(ac.getComfort()); +} + +// Test Sensor mode. +TEST(TestDaikinClass, SensorSetting) { + IRDaikinESP ac(0); + ac.begin(); + + ac.setSensor(false); + ASSERT_FALSE(ac.getSensor()); + + ac.setSensor(true); + ASSERT_TRUE(ac.getSensor()); + + ac.setSensor(false); + ASSERT_FALSE(ac.getSensor()); +} + +TEST(TestDaikinClass, RenderTime) { + EXPECT_EQ("0:00", IRDaikinESP::renderTime(0)); + EXPECT_EQ("0:10", IRDaikinESP::renderTime(10)); + EXPECT_EQ("1:00", IRDaikinESP::renderTime(1 * 60 + 0)); + EXPECT_EQ("23:59", IRDaikinESP::renderTime(23 * 60 + 59)); +} + +TEST(TestDaikinClass, SetAndGetRaw) { + IRDaikinESP ac(0); + uint8_t shortState[kDaikinStateLengthShort] = { + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x00, 0x00, 0x54, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x49, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x4F}; + uint8_t longState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x00, 0x00, 0x54, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x49, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x4F}; + uint8_t expectedState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x00, 0x00, 0x54, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x48, 0x2A, 0x00, 0xB0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x02, 0x5C}; + + EXPECT_STATE_EQ(longState, ac.getRaw(), kDaikinBits); + // toggle the power state. + ac.setPower(!ac.getPower()); + ac.setTemp(21); + ac.setMold(true); + EXPECT_STATE_EQ(expectedState, ac.getRaw(), kDaikinBits); + ac.setRaw(longState); + EXPECT_STATE_EQ(longState, ac.getRaw(), kDaikinBits); + ac.setRaw(shortState, kDaikinStateLengthShort); + EXPECT_STATE_EQ(longState, ac.getRaw(), kDaikinBits); +} + +TEST(TestDaikinClass, ChecksumValidation) { + uint8_t daikin_code[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x02, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x41, 0x1E, 0x00, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE1}; + + EXPECT_TRUE(IRDaikinESP::validChecksum(daikin_code)); + // Change the array so the checksum is invalid. + daikin_code[0] ^= 0xFF; + EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); + // Restore the previous change, and change another byte. + daikin_code[0] ^= 0xFF; + daikin_code[4] ^= 0xFF; + EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); + daikin_code[4] ^= 0xFF; + // Change something in the 2nd block. + daikin_code[10] ^= 0xFF; + EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); + daikin_code[10] ^= 0xFF; + EXPECT_TRUE(IRDaikinESP::validChecksum(daikin_code)); + // Change something in the 3rd block. + daikin_code[20] ^= 0xFF; + EXPECT_FALSE(IRDaikinESP::validChecksum(daikin_code)); + daikin_code[20] ^= 0xFF; + EXPECT_TRUE(IRDaikinESP::validChecksum(daikin_code)); +} + +// Test human readable output. +TEST(TestDaikinClass, HumanReadable) { + IRDaikinESP ac(0); + + EXPECT_EQ( + "Power: On, Mode: 4 (HEAT), Temp: 15C, Fan: 11 (QUIET), " + "Powerful: Off, Quiet: Off, Sensor: Off, Eye: Off, Mold: Off, " + "Comfort: Off, Swing (Horizontal): Off, Swing (Vertical): Off, " + "Current Time: 0:00, On Time: Off, Off Time: Off", + ac.toString()); + ac.setMode(kDaikinAuto); + ac.setTemp(25); + ac.setFan(kDaikinFanAuto); + ac.setQuiet(true); + ac.setSensor(true); + ac.setEye(true); + ac.setMold(true); + ac.setSwingVertical(true); + ac.setSwingHorizontal(true); + ac.setCurrentTime(9 * 60 + 15); + ac.enableOnTimer(8 * 60 + 0); + ac.enableOffTimer(17 * 60 + 30); + ac.setComfort(true); + ac.off(); + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 25C, Fan: 10 (AUTO), " + "Powerful: Off, Quiet: On, Sensor: On, Eye: On, Mold: On, Comfort: On, " + "Swing (Horizontal): On, Swing (Vertical): On, " + "Current Time: 9:15, On Time: 8:00, Off Time: 17:30", + ac.toString()); +} + +// Test general message construction after tweaking some settings. +TEST(TestDaikinClass, MessageConstuction) { + IRDaikinESP ac(0); + IRsendTest irsend(4); + ac.begin(); + irsend.begin(); + + ac.setFan(kDaikinFanMin); + ac.setMode(kDaikinCool); + ac.setTemp(27); + ac.setSwingVertical(false); + ac.setSwingHorizontal(true); + ac.setQuiet(false); + ac.setPower(true); + + // Check everything for kicks. + EXPECT_EQ(kDaikinFanMin, ac.getFan()); + EXPECT_EQ(kDaikinCool, ac.getMode()); + EXPECT_EQ(27, ac.getTemp()); + EXPECT_FALSE(ac.getSwingVertical()); + EXPECT_TRUE(ac.getSwingHorizontal()); + EXPECT_FALSE(ac.getQuiet()); + EXPECT_TRUE(ac.getPower()); + + irsend.reset(); + irsend.sendDaikin(ac.getRaw()); + EXPECT_EQ( + "f38000d50" + "m428s428m428s428m428s428m428s428m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s1280m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s1280m428s1280m428s428m428s1280m428s428m428s1280m428s1280" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s428m428s428m428s428m428s1280m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s1280m428s428m428s1280m428s428m428s1280m428s428" + "m428s29428m3650s1623" + "m428s1280m428s428m428s428m428s428m428s1280m428s428m428s428m428s428" + "m428s428m428s1280m428s428m428s1280m428s1280m428s428m428s1280m428s1280" + "m428s1280m428s1280m428s1280m428s428m428s428m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s1280m428s428m428s428m428s1280m428s1280m428s1280m428s428m428s428" + "m428s428m428s1280m428s1280m428s428m428s1280m428s1280m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428m428s428" + "m428s1280m428s1280m428s1280m428s1280m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s1280m428s1280m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s1280m428s1280" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s428m428s428m428s428m428s428m428s428m428s428m428s428" + "m428s428m428s1280m428s1280m428s428m428s428m428s1280m428s1280m428s1280" + "m428s29428", + irsend.outputStr()); +} + +// Tests for decodeDaikin(). + +// Test decoding a message captured from a real IR remote. +TEST(TestDecodeDaikin, RealExample) { + IRDaikinESP ac(0); + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t expectedState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x3A, 0x05, 0x93, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x3F, 0x3A, 0x00, 0xA0, 0x00, + 0x0A, 0x25, 0x17, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x32}; + uint16_t rawData[583] = { + 416, 446, 416, 446, 416, 446, 418, 446, 416, 446, 416, 25434, + 3436, 1768, 390, 1336, 390, 446, 416, 446, 416, 446, 416, 1336, + 390, 446, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 448, + 416, 1336, 390, 1336, 390, 448, 416, 1336, 390, 1336, 390, 1338, + 388, 1338, 390, 1336, 390, 446, 416, 446, 416, 1336, 390, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 448, + 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, 416, 1336, + 390, 448, 416, 446, 416, 446, 416, 1336, 390, 1336, 390, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 446, 416, 446, 416, 448, 416, 446, 416, 446, 416, 446, + 416, 448, 414, 448, 416, 448, 416, 1336, 390, 1336, 390, 1336, + 390, 446, 414, 1336, 390, 448, 414, 1336, 390, 1336, 390, 34878, + 3436, 1768, 390, 1336, 390, 446, 416, 448, 416, 446, 416, 1336, + 390, 446, 416, 448, 416, 446, 416, 446, 416, 1336, 390, 446, + 416, 1336, 390, 1336, 390, 446, 416, 1336, 390, 1336, 390, 1336, + 390, 1336, 390, 1336, 392, 446, 414, 448, 416, 1336, 390, 446, + 416, 446, 416, 446, 416, 446, 414, 448, 416, 446, 416, 448, + 414, 448, 416, 446, 416, 446, 416, 446, 414, 1336, 390, 448, + 416, 446, 416, 446, 416, 448, 416, 1336, 390, 446, 416, 446, + 416, 1336, 390, 446, 416, 1336, 390, 1336, 390, 1336, 390, 446, + 416, 446, 414, 1338, 390, 446, 416, 1336, 390, 446, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 1336, 390, 1336, 390, 446, + 416, 446, 416, 1336, 390, 446, 416, 446, 416, 1336, 390, 34876, + 3436, 1768, 388, 1336, 390, 446, 416, 446, 416, 448, 416, 1336, + 390, 446, 416, 446, 416, 446, 416, 448, 416, 1336, 390, 448, + 414, 1336, 390, 1336, 390, 446, 416, 1336, 388, 1338, 388, 1336, + 390, 1336, 390, 1336, 390, 446, 416, 446, 416, 1336, 390, 446, + 420, 442, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 448, + 416, 446, 416, 448, 416, 446, 416, 448, 416, 446, 416, 1336, + 390, 1336, 390, 1336, 388, 1338, 390, 1336, 390, 1336, 392, 446, + 416, 446, 416, 448, 416, 1334, 390, 446, 416, 1338, 388, 1336, + 390, 1336, 390, 446, 416, 446, 416, 448, 414, 446, 416, 446, + 416, 446, 416, 448, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, + 416, 1336, 390, 446, 414, 448, 416, 446, 416, 446, 416, 446, + 416, 448, 416, 446, 416, 446, 416, 446, 416, 1336, 390, 446, + 416, 1336, 390, 446, 416, 446, 416, 446, 416, 448, 416, 1338, + 390, 444, 418, 1336, 390, 448, 416, 446, 416, 1336, 390, 446, + 416, 446, 416, 1336, 390, 1336, 388, 1336, 390, 446, 416, 1336, + 390, 448, 414, 448, 414, 448, 416, 1334, 390, 446, 416, 446, + 416, 446, 416, 448, 416, 446, 416, 446, 416, 448, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, 416, 446, + 416, 448, 416, 1336, 390, 1336, 390, 446, 416, 446, 416, 446, + 416, 446, 414, 446, 416, 448, 416, 446, 416, 448, 414, 446, + 418, 446, 416, 446, 416, 448, 416, 446, 416, 448, 416, 446, + 416, 448, 416, 446, 416, 1336, 390, 446, 416, 446, 416, 1338, + 390, 1336, 390, 446, 416, 446, 416}; // Captured by @sillyfrog + + irsend.reset(); + irsend.sendRaw(rawData, 583, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN, irsend.capture.decode_type); + ASSERT_EQ(kDaikinBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 29C, Fan: 10 (AUTO), Powerful: On, " + "Quiet: Off, Sensor: Off, Eye: Off, Mold: Off, Comfort: Off, " + "Swing (Horizontal): Off, Swing (Vertical): Off, " + "Current Time: 22:18, On Time: 21:30, Off Time: 6:10", ac.toString()); +} + +// Decoding a message we entirely constructed based solely on a given state. +TEST(TestDecodeDaikin, ShortSyntheticExample) { + IRDaikinESP ac(0); + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t shortState[kDaikinStateLengthShort] = { + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x3A, 0x05, 0x93, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x3F, 0x3A, 0x00, 0xA0, 0x00, + 0x0A, 0x25, 0x17, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x32}; + + uint8_t longState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x3A, 0x05, 0x93, 0x11, + 0xDA, 0x27, 0x00, 0x00, 0x3F, 0x3A, 0x00, 0xA0, 0x00, + 0x0A, 0x25, 0x17, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x32}; + irsend.reset(); + irsend.sendDaikin(shortState, kDaikinStateLengthShort); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN, irsend.capture.decode_type); + ASSERT_EQ(kDaikinBits, irsend.capture.bits); + EXPECT_STATE_EQ(longState, irsend.capture.state, irsend.capture.bits); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 29C, Fan: 10 (AUTO), Powerful: On, " + "Quiet: Off, Sensor: Off, Eye: Off, Mold: Off, Comfort: Off, " + "Swing (Horizontal): Off, Swing (Vertical): Off, " + "Current Time: 22:18, On Time: 21:30, Off Time: 6:10", ac.toString()); +} + +// Decoding a message we entirely constructed based solely on a given state. +TEST(TestDecodeDaikin, LongSyntheticExample) { + IRDaikinESP ac(0); + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t expectedState[kDaikinStateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x00, 0xD7, + 0x11, 0xDA, 0x27, 0x00, 0x42, 0x3A, 0x05, 0x93, + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x3F, 0x3A, 0x00, 0xA0, 0x00, + 0x0A, 0x25, 0x17, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x32}; + + irsend.reset(); + irsend.sendDaikin(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeDaikin(&irsend.capture)); + ASSERT_EQ(DAIKIN, irsend.capture.decode_type); + ASSERT_EQ(kDaikinBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 29C, Fan: 10 (AUTO), Powerful: On, " + "Quiet: Off, Sensor: Off, Eye: Off, Mold: Off, Comfort: Off, " + "Swing (Horizontal): Off, Swing (Vertical): Off, " + "Current Time: 22:18, On Time: 21:30, Off Time: 6:10", ac.toString()); +} + +// Test decoding a message captured from a real IR remote. +TEST(TestDecodeDaikin2, RealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t expectedState[kDaikin2StateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x7A, 0xC3, 0x70, 0x28, 0x0C, + 0x80, 0x04, 0xB0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xD5, 0xF5, + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x08, 0x26, 0x00, 0xA0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, 0x80, 0x60, 0xE7}; + // "Off" Data from https://github.com/markszabo/IRremoteESP8266/issues/582 + uint16_t rawData[633] = { // Data supplied by @sheppy99 + 10024, 25180, 3494, 1732, 436, 1300, 436, 436, 432, 438, 430, 438, + 426, 1306, 430, 442, 430, 438, 428, 440, 430, 440, 430, 1304, + 432, 442, 428, 1308, 424, 1312, 428, 442, 428, 1306, 424, 1314, + 426, 1308, 434, 1306, 426, 1308, 428, 444, 426, 442, 428, 1310, + 428, 442, 424, 444, 426, 442, 426, 444, 424, 444, 426, 444, + 424, 446, 422, 446, 422, 446, 422, 446, 418, 1318, 418, 450, + 420, 448, 420, 448, 422, 448, 420, 450, 420, 448, 420, 450, + 420, 452, 418, 1318, 420, 450, 420, 1318, 420, 1314, 418, 1318, + 424, 1314, 424, 448, 422, 1316, 424, 1312, 426, 446, 422, 448, + 420, 448, 422, 448, 422, 1314, 418, 1320, 416, 452, 420, 448, + 420, 448, 422, 448, 422, 1314, 416, 1320, 422, 1316, 422, 450, + 418, 450, 420, 448, 420, 448, 416, 1320, 418, 452, 418, 1316, + 422, 448, 420, 450, 420, 450, 420, 448, 422, 1314, 418, 1320, + 418, 450, 420, 448, 420, 448, 420, 450, 420, 450, 418, 450, + 418, 450, 420, 450, 418, 452, 416, 452, 420, 450, 418, 1318, + 420, 452, 418, 452, 418, 1322, 416, 452, 416, 452, 418, 452, + 418, 452, 416, 454, 418, 452, 416, 456, 414, 452, 418, 454, + 416, 1320, 410, 1324, 418, 452, 418, 1320, 416, 452, 418, 1320, + 418, 1318, 420, 448, 420, 1316, 420, 450, 420, 450, 418, 450, + 420, 450, 418, 452, 418, 1320, 418, 450, 418, 450, 416, 1322, + 412, 458, 420, 450, 416, 452, 418, 452, 416, 452, 418, 452, + 416, 454, 416, 452, 418, 452, 416, 454, 414, 454, 416, 454, + 416, 454, 414, 456, 414, 454, 414, 456, 412, 454, 416, 456, + 414, 456, 412, 1326, 412, 1320, 412, 1322, 414, 1322, 418, 1320, + 420, 452, 418, 1318, 420, 1316, 422, 450, 420, 1314, 424, 448, + 422, 1314, 422, 448, 422, 1314, 418, 1318, 424, 1316, 422, 448, + 422, 1312, 424, 446, 422, 1314, 420, 1318, 422, 1316, 426, 1310, + 426, 35166, 3500, 1724, 446, 1296, 444, 432, 436, 432, 438, 432, + 436, 1296, 440, 434, 434, 436, 432, 436, 434, 436, 434, 1298, + 438, 438, 432, 1304, 428, 1304, 432, 442, 430, 1302, 430, 1308, + 430, 1306, 434, 1302, 432, 1306, 430, 440, 430, 438, 430, 1308, + 434, 438, 430, 440, 428, 440, 430, 440, 428, 442, 426, 444, + 428, 442, 426, 444, 426, 442, 426, 444, 424, 446, 422, 446, + 424, 446, 424, 446, 422, 446, 424, 448, 420, 448, 422, 446, + 422, 448, 422, 450, 420, 450, 414, 1320, 420, 450, 418, 450, + 418, 448, 420, 450, 418, 452, 418, 1320, 418, 1316, 422, 450, + 418, 452, 418, 1320, 420, 448, 418, 450, 420, 450, 418, 452, + 416, 452, 418, 450, 418, 452, 416, 452, 418, 452, 416, 454, + 416, 452, 416, 454, 416, 454, 414, 456, 416, 454, 414, 1322, + 416, 454, 416, 1320, 418, 452, 416, 454, 414, 454, 416, 454, + 414, 454, 414, 454, 414, 456, 414, 456, 412, 456, 414, 456, + 414, 456, 412, 456, 414, 458, 406, 464, 410, 458, 412, 458, + 410, 460, 410, 1326, 412, 1324, 414, 456, 412, 458, 412, 456, + 414, 456, 412, 458, 410, 458, 414, 458, 410, 458, 408, 460, + 410, 470, 400, 1324, 408, 1328, 410, 458, 410, 460, 414, 456, + 410, 456, 414, 458, 412, 460, 410, 458, 412, 458, 412, 460, + 408, 460, 410, 460, 408, 472, 396, 462, 408, 470, 402, 470, + 396, 472, 400, 470, 398, 1326, 412, 460, 408, 472, 396, 472, + 400, 470, 400, 472, 396, 1328, 410, 1324, 414, 458, 410, 458, + 410, 458, 412, 458, 412, 460, 408, 460, 410, 460, 410, 1324, + 414, 458, 410, 460, 408, 460, 410, 458, 410, 460, 410, 1326, + 412, 1322, 416, 456, 412, 1322, 412, 1326, 416, 1322, 418, 452, + 416, 454, 412, 1324, 418, 1320, 420, 1316, 420}; + irsend.reset(); + irsend.sendRaw(rawData, 633, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN2, irsend.capture.decode_type); + ASSERT_EQ(kDaikin2Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +// Decoding a message we entirely constructed based solely on a given state. +TEST(TestDecodeDaikin2, SyntheticExample) { + IRDaikin2 ac(0); + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + uint8_t expectedState[kDaikin2StateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x7A, 0xC3, 0x70, 0x28, 0x0C, + 0x80, 0x04, 0xB0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xD5, 0xF5, + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x08, 0x26, 0x00, 0xA0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, 0x80, 0x60, 0xE7}; + + irsend.reset(); + irsend.sendDaikin2(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN2, irsend.capture.decode_type); + ASSERT_EQ(kDaikin2Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (Auto), " + "Swing (V): 5, Swing (H): 190 (Auto), " + "Clock: 14:50, On Time: Off, Off Time: Off, Sleep Time: Off, " + "Beep: 1 (Quiet), Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, " + "Eye: Off, Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: Off, " + "Econo: Off", + ac.toString()); +} + +TEST(TestDaikin2Class, CurrentTime) { + IRDaikin2 ac(0); + ac.begin(); + + ac.setCurrentTime(0); // 00:00 + EXPECT_EQ(0, ac.getCurrentTime()); + + ac.setCurrentTime(754); // 12:34 + EXPECT_EQ(754, ac.getCurrentTime()); + + ac.setCurrentTime(1439); // 23:59 + EXPECT_EQ(1439, ac.getCurrentTime()); +} + +TEST(TestDaikin2Class, OnOffTimers) { + IRDaikin2 ac(0); + ac.begin(); + + // Both timers turned off. + ac.disableOnTimer(); + ac.disableOffTimer(); + EXPECT_FALSE(ac.getOnTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOnTime()); + EXPECT_FALSE(ac.getOffTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOffTime()); + + // Turn on just the On Timer. + ac.enableOnTimer(123); + EXPECT_TRUE(ac.getOnTimerEnabled()); + EXPECT_EQ(123, ac.getOnTime()); + EXPECT_FALSE(ac.getOffTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOffTime()); + + // Now turn on the Off Timer. + ac.enableOffTimer(754); + EXPECT_TRUE(ac.getOffTimerEnabled()); + EXPECT_EQ(754, ac.getOffTime()); + EXPECT_TRUE(ac.getOnTimerEnabled()); + EXPECT_EQ(123, ac.getOnTime()); + + // Turn off the just the On Timer. + ac.disableOnTimer(); + EXPECT_FALSE(ac.getOnTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOnTime()); + EXPECT_TRUE(ac.getOffTimerEnabled()); + EXPECT_EQ(754, ac.getOffTime()); + + // Now turn off the Off Timer. + ac.disableOffTimer(); + EXPECT_FALSE(ac.getOffTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOffTime()); + EXPECT_FALSE(ac.getOnTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOnTime()); +} + +TEST(TestDaikin2Class, LightAndBeep) { + IRDaikin2 ac(0); + ac.begin(); + + ac.setLight(kDaikinLightOff); + EXPECT_EQ(kDaikinLightOff, ac.getLight()); + ac.setBeep(kDaikinBeepOff); + EXPECT_EQ(kDaikinBeepOff, ac.getBeep()); + ac.setLight(kDaikinLightBright); + EXPECT_EQ(kDaikinLightBright, ac.getLight()); + EXPECT_EQ(kDaikinBeepOff, ac.getBeep()); + ac.setBeep(kDaikinBeepLoud); + EXPECT_EQ(kDaikinBeepLoud, ac.getBeep()); + EXPECT_EQ(kDaikinLightBright, ac.getLight()); +} + +TEST(TestDaikin2Class, FanSpeed) { + IRDaikin2 ac(0); + ac.begin(); + + // Unexpected value should default to Auto. + ac.setFan(0); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + // Unexpected value should default to Auto. + ac.setFan(255); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(kDaikinFanMax); + EXPECT_EQ(kDaikinFanMax, ac.getFan()); + + // Beyond Max should default to Auto. + ac.setFan(kDaikinFanMax + 1); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(kDaikinFanMax - 1); + EXPECT_EQ(kDaikinFanMax - 1, ac.getFan()); + + ac.setFan(kDaikinFanMin); + EXPECT_EQ(kDaikinFanMin, ac.getFan()); + + ac.setFan(kDaikinFanMin + 1); + EXPECT_EQ(kDaikinFanMin + 1, ac.getFan()); + + // Beyond Min should default to Auto. + ac.setFan(kDaikinFanMin - 1); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(3); + EXPECT_EQ(3, ac.getFan()); + + ac.setFan(kDaikinFanAuto); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(kDaikinFanQuiet); + EXPECT_EQ(kDaikinFanQuiet, ac.getFan()); +} + +// Test Mold mode. +TEST(TestDaikin2Class, MoldSetting) { + IRDaikin2 ac(0); + ac.begin(); + + ac.setMold(false); + ASSERT_FALSE(ac.getMold()); + + ac.setMold(true); + ASSERT_TRUE(ac.getMold()); + + ac.setMold(false); + ASSERT_FALSE(ac.getMold()); +} + +// Test Auto Clean setting. +TEST(TestDaikin2Class, CleanSetting) { + IRDaikin2 ac(0); + ac.begin(); + + ac.setClean(false); + ASSERT_FALSE(ac.getClean()); + + ac.setClean(true); + ASSERT_TRUE(ac.getClean()); + + ac.setClean(false); + ASSERT_FALSE(ac.getClean()); +} + + +TEST(TestDaikin2Class, Temperature) { + IRDaikin2 ac(0); + ac.begin(); + + ac.setMode(kDaikinAuto); + ac.setTemp(0); + EXPECT_EQ(kDaikinMinTemp, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kDaikinMaxTemp, ac.getTemp()); + + ac.setTemp(kDaikinMinTemp); + EXPECT_EQ(kDaikinMinTemp, ac.getTemp()); + + ac.setTemp(kDaikinMaxTemp); + EXPECT_EQ(kDaikinMaxTemp, ac.getTemp()); + + ac.setTemp(kDaikinMinTemp - 1); + EXPECT_EQ(kDaikinMinTemp, ac.getTemp()); + + ac.setTemp(kDaikinMaxTemp + 1); + EXPECT_EQ(kDaikinMaxTemp, ac.getTemp()); + + ac.setTemp(kDaikinMinTemp + 1); + EXPECT_EQ(kDaikinMinTemp + 1, ac.getTemp()); + + // Now try it with Cool mode, which should set the temp to kDaikin2MinCoolTemp + ASSERT_TRUE(kDaikinMinTemp + 1 < kDaikin2MinCoolTemp); + ac.setMode(kDaikinCool); + EXPECT_EQ(kDaikin2MinCoolTemp, ac.getTemp()); + ac.setTemp(kDaikin2MinCoolTemp - 1); + EXPECT_EQ(kDaikin2MinCoolTemp, ac.getTemp()); + ac.setTemp(kDaikin2MinCoolTemp + 1); + EXPECT_EQ(kDaikin2MinCoolTemp + 1, ac.getTemp()); + // Should be released from that requirement in other modes. + ac.setMode(kDaikinAuto); + ac.setTemp(kDaikin2MinCoolTemp - 1); + EXPECT_EQ(kDaikin2MinCoolTemp - 1, ac.getTemp()); + + ac.setTemp(21); + EXPECT_EQ(21, ac.getTemp()); + + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + + ac.setTemp(29); + EXPECT_EQ(29, ac.getTemp()); +} + +// Test Fresh Air settings. +TEST(TestDaikin2Class, FreshAirSettings) { + IRDaikin2 ac(0); + ac.begin(); + + ac.setFreshAir(false); + ac.setFreshAirHigh(false); + ASSERT_FALSE(ac.getFreshAir()); + ASSERT_FALSE(ac.getFreshAirHigh()); + + ac.setFreshAir(true); + ASSERT_TRUE(ac.getFreshAir()); + ASSERT_FALSE(ac.getFreshAirHigh()); + + ac.setFreshAirHigh(true); + ASSERT_TRUE(ac.getFreshAir()); + ASSERT_TRUE(ac.getFreshAirHigh()); + + ac.setFreshAir(false); + ASSERT_FALSE(ac.getFreshAir()); + ASSERT_TRUE(ac.getFreshAirHigh()); + + ac.setFreshAirHigh(false); + ASSERT_FALSE(ac.getFreshAir()); + ASSERT_FALSE(ac.getFreshAirHigh()); +} + +// Test Eye mode. +TEST(TestDaikin2Class, EyeSetting) { + IRDaikin2 ac(0); + ac.begin(); + + ac.setEye(false); + ASSERT_FALSE(ac.getEye()); + ac.setEye(true); + ASSERT_TRUE(ac.getEye()); + ac.setEye(false); + ASSERT_FALSE(ac.getEye()); +} + +// Test Econo setting. +TEST(TestDaikin2Class, EconoSetting) { + IRDaikin2 ac(0); + ac.begin(); + + ac.setEcono(false); + ASSERT_FALSE(ac.getEcono()); + ac.setEcono(true); + ASSERT_TRUE(ac.getEcono()); + ac.setEcono(false); + ASSERT_FALSE(ac.getEcono()); +} + +TEST(TestDaikin2Class, SleepTimer) { + IRDaikin2 ac(0); + ac.begin(); + + // NOTE: On & Sleep timer share the same time location. + + // Both timers turned off. + ac.disableOnTimer(); + ac.disableSleepTimer(); + EXPECT_FALSE(ac.getOnTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOnTime()); + EXPECT_FALSE(ac.getSleepTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getSleepTime()); + + // Turn on just the On Timer. + ac.enableOnTimer(123); + EXPECT_TRUE(ac.getOnTimerEnabled()); + EXPECT_EQ(123, ac.getOnTime()); + EXPECT_FALSE(ac.getSleepTimerEnabled()); + EXPECT_EQ(123, ac.getSleepTime()); + + // Now turn on the Sleep Timer. This shoud disable the On Timer. + ac.enableSleepTimer(754); + EXPECT_TRUE(ac.getSleepTimerEnabled()); + EXPECT_EQ(754, ac.getSleepTime()); + EXPECT_FALSE(ac.getOnTimerEnabled()); + EXPECT_EQ(754, ac.getOnTime()); + + // Turn off the just the On Timer. + ac.disableOnTimer(); + EXPECT_FALSE(ac.getOnTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOnTime()); + EXPECT_FALSE(ac.getSleepTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getSleepTime()); + + // Now turn on the On Timer and turn off the Sleep Timer. + // Both should be off afterwards. + ac.enableOnTimer(123); + ac.disableSleepTimer(); + EXPECT_FALSE(ac.getSleepTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getSleepTime()); + EXPECT_FALSE(ac.getOnTimerEnabled()); + EXPECT_EQ(kDaikinUnusedTime, ac.getOnTime()); +} + +// Test Vertical Swing. +TEST(TestDaikin2Class, Swing) { + IRDaikin2 ac(0); + ac.begin(); + + // Vertical + ac.setSwingVertical(1); + ASSERT_EQ(1, ac.getSwingVertical()); + ac.setSwingVertical(3); + ASSERT_EQ(3, ac.getSwingVertical()); + ac.setSwingVertical(6); + ASSERT_EQ(6, ac.getSwingVertical()); + ac.setSwingVertical(kDaikin2SwingVBreeze); + ASSERT_EQ(kDaikin2SwingVBreeze, ac.getSwingVertical()); + ac.setSwingVertical(kDaikin2SwingVCirculate); + ASSERT_EQ(kDaikin2SwingVCirculate, ac.getSwingVertical()); + ac.setSwingVertical(kDaikin2SwingVAuto); + ASSERT_EQ(kDaikin2SwingVAuto, ac.getSwingVertical()); + ac.setSwingVertical(0); + ASSERT_EQ(kDaikin2SwingVAuto, ac.getSwingVertical()); + ac.setSwingVertical(7); + ASSERT_EQ(kDaikin2SwingVAuto, ac.getSwingVertical()); + ac.setSwingVertical(255); + ASSERT_EQ(kDaikin2SwingVAuto, ac.getSwingVertical()); + + // Horizontal + ac.setSwingHorizontal(kDaikin2SwingHAuto); + ASSERT_EQ(kDaikin2SwingHAuto, ac.getSwingHorizontal()); + ac.setSwingHorizontal(kDaikin2SwingHSwing); + ASSERT_EQ(kDaikin2SwingHSwing, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(0); + ASSERT_EQ(0, ac.getSwingHorizontal()); + ac.setSwingHorizontal(255); + ASSERT_EQ(255, ac.getSwingHorizontal()); +} + +TEST(TestDaikin2Class, QuietMode) { + IRDaikin2 ac(0); + ac.begin(); + + ac.setQuiet(true); + EXPECT_TRUE(ac.getQuiet()); + + ac.setQuiet(false); + EXPECT_FALSE(ac.getQuiet()); + + ac.setQuiet(true); + EXPECT_TRUE(ac.getQuiet()); + + // But setting Powerful mode should exit out of quiet mode. + ac.setPowerful(true); + EXPECT_FALSE(ac.getQuiet()); +} + +TEST(TestDaikin2Class, PowerfulMode) { + IRDaikin2 ac(0); + ac.begin(); + + ac.setPowerful(true); + EXPECT_TRUE(ac.getPowerful()); + + ac.setPowerful(false); + EXPECT_FALSE(ac.getPowerful()); + + ac.setPowerful(true); + EXPECT_TRUE(ac.getPowerful()); + + ac.setQuiet(true); + EXPECT_FALSE(ac.getPowerful()); +} + +// Test Purify mode. +TEST(TestDaikin2Class, PurifySetting) { + IRDaikin2 ac(0); + ac.begin(); + + ac.setPurify(false); + ASSERT_FALSE(ac.getPurify()); + ac.setPurify(true); + ASSERT_TRUE(ac.getPurify()); + ac.setPurify(false); + ASSERT_FALSE(ac.getPurify()); +} + +TEST(TestDaikin2Class, HumanReadable) { + IRDaikin2 ac(0); + ac.begin(); + ac.setPower(true); + ac.setMode(kDaikinCool); + ac.setTemp(21); + ac.setFan(kDaikinFanMax); + ac.setSwingVertical(kDaikin2SwingVAuto); + ac.setSwingHorizontal(kDaikin2SwingHSwing); + ac.setCurrentTime(12 * 60 + 34); // 12:34 + ac.disableOnTimer(); + ac.enableOffTimer(20 * 60); // 20:00 + ac.enableSleepTimer(4 * 60); // 4:00 + ac.setBeep(kDaikinBeepLoud); + ac.setLight(kDaikinLightDim); + ac.setMold(true); + ac.setClean(false); + ac.setFreshAir(true); + ac.setEye(true); + ac.setEyeAuto(true); + ac.setQuiet(false); + ac.setPowerful(true); + ac.setPurify(true); + ac.setEcono(false); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 21C, Fan: 5 (Max), " + "Swing (V): 14 (Auto), Swing (H): 191 (Swing), Clock: 12:34, " + "On Time: Off, Off Time: 20:00, Sleep Time: 4:00, Beep: 2 (Loud), " + "Light: 2 (Dim), Mold: On, Clean: Off, Fresh Air: On, Eye: On, " + "Eye Auto: On, Quiet: Off, Powerful: On, Purify: On, Econo: Off", + ac.toString()); + ac.setQuiet(true); + ac.setMode(kDaikinHeat); + ac.setBeep(kDaikinBeepQuiet); + ac.setLight(kDaikinLightBright); + ac.setTemp(32); + ac.setFan(kDaikinFanMin); + ac.setCurrentTime(23 * 60 + 45); // 23:45 + ac.enableOnTimer(9 * 60 + 11); // 9:11 + EXPECT_EQ( + "Power: On, Mode: 4 (HEAT), Temp: 32C, Fan: 1 (Min), " + "Swing (V): 14 (Auto), Swing (H): 191 (Swing), Clock: 23:45, " + "On Time: 9:11, Off Time: 20:00, Sleep Time: Off, Beep: 1 (Quiet), " + "Light: 1 (Bright), Mold: On, Clean: Off, Fresh Air: On, Eye: On, " + "Eye Auto: On, Quiet: On, Powerful: Off, Purify: On, Econo: Off", + ac.toString()); +} + +// See if we can construct a known state. +TEST(TestDaikin2Class, KnownConstruction) { + IRDaikin2 ac(0); + + uint8_t expectedState[kDaikin2StateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x7A, 0xC3, 0x70, 0x28, 0x0C, + 0x80, 0x04, 0xB0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xD5, 0xF5, + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x08, 0x26, 0x00, 0xA0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, 0x80, 0x60, 0xE7}; + + ac.begin(); + ac.setPower(false); + ac.setMode(kDaikinAuto); + ac.setTemp(19); + ac.setFan(kDaikinFanAuto); + ac.setSwingVertical(5); + ac.setSwingHorizontal(kDaikin2SwingHAuto); + ac.setCurrentTime(14 * 60 + 50); // 14:50 + ac.disableOnTimer(); + ac.disableOffTimer(); + ac.disableSleepTimer(); + ac.setBeep(kDaikinBeepQuiet); + ac.setLight(kDaikinLightOff); + ac.setMold(true); + ac.setClean(true); + ac.setFreshAir(false); + ac.setEye(false); + ac.setEyeAuto(false); + ac.setQuiet(false); + ac.setPowerful(false); + ac.setPurify(false); + ac.setEcono(false); + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (Auto), " + "Swing (V): 5, Swing (H): 190 (Auto), " + "Clock: 14:50, On Time: Off, Off Time: Off, Sleep Time: Off, " + "Beep: 1 (Quiet), Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, " + "Eye: Off, Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: Off, " + "Econo: Off", + ac.toString()); + EXPECT_STATE_EQ(expectedState, ac.getRaw(), kDaikin2Bits); +} + +TEST(TestUtils, Housekeeping) { + ASSERT_EQ("DAIKIN", typeToString(decode_type_t::DAIKIN)); + ASSERT_EQ(decode_type_t::DAIKIN, strToDecodeType("DAIKIN")); + ASSERT_TRUE(hasACState(decode_type_t::DAIKIN)); + + ASSERT_EQ("DAIKIN2", typeToString(decode_type_t::DAIKIN2)); + ASSERT_EQ(decode_type_t::DAIKIN2, strToDecodeType("DAIKIN2")); + ASSERT_TRUE(hasACState(decode_type_t::DAIKIN2)); + + ASSERT_EQ("DAIKIN216", typeToString(decode_type_t::DAIKIN216)); + ASSERT_EQ(decode_type_t::DAIKIN216, strToDecodeType("DAIKIN216")); + ASSERT_TRUE(hasACState(decode_type_t::DAIKIN216)); +} + +// https://github.com/markszabo/IRremoteESP8266/issues/582#issuecomment-453863879 +TEST(TestDecodeDaikin2, Issue582DeepDecodeExample) { + IRDaikin2 ac(0); + + const uint8_t state[kDaikin2StateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x30, 0x42, 0xF0, 0x28, 0x0C, + 0x80, 0x04, 0xB0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xCE, 0xA3, + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x09, 0x26, 0x00, 0xA0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, 0x92, 0x60, 0xFA}; + + ac.setRaw(state); + ASSERT_TRUE(ac.getMold()); + ASSERT_TRUE(ac.getEye()); + ASSERT_TRUE(ac.getPurify()); + EXPECT_EQ( + "Power: On, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (Auto), " + "Swing (V): 14 (Auto), Swing (H): 190 (Auto), Clock: 9:20, On Time: Off, " + "Off Time: Off, Sleep Time: Off, Beep: 3 (Off), Light: 3 (Off), " + "Mold: On, Clean: On, Fresh Air: Off, Eye: On, Eye Auto: Off, " + "Quiet: Off, Powerful: Off, Purify: On, Econo: Off", + ac.toString()); +} + +// https://docs.google.com/spreadsheets/d/1f8EGfIbBUo2B-CzUFdrgKQprWakoYNKM80IKZN4KXQE/edit?ts=5c317775#gid=1023395743 +TEST(TestDecodeDaikin2, Issue582PowerfulEconoFix) { + IRDaikin2 ac(0); + + const uint8_t PowerfulOn[39] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x3A, 0x43, 0xF0, 0x28, 0x0C, + 0x80, 0x04, 0xB0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xCE, 0xAE, + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x39, 0x28, 0x00, 0xA0, 0x00, + 0x00, 0x06, 0x60, 0x01, 0x00, 0xC1, 0x90, 0x60, 0x2B}; + const uint8_t PowerfulOff[39] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x3A, 0x43, 0xF0, 0x28, 0x0C, + 0x80, 0x04, 0xB0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xCE, 0xAE, + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x39, 0x28, 0x00, 0xA0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, 0x90, 0x60, 0x2A}; + ac.setRaw(PowerfulOn); + ASSERT_TRUE(ac.getPowerful()); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 20C, Fan: 10 (Auto), " + "Swing (V): 14 (Auto), Swing (H): 190 (Auto), Clock: 13:46, " + "On Time: Off, Off Time: Off, Sleep Time: Off, Beep: 3 (Off), " + "Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, Eye: Off, " + "Eye Auto: Off, Quiet: Off, Powerful: On, Purify: On, Econo: Off", + ac.toString()); + ac.setRaw(PowerfulOff); + ASSERT_FALSE(ac.getPowerful()); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 20C, Fan: 10 (Auto), " + "Swing (V): 14 (Auto), Swing (H): 190 (Auto), Clock: 13:46, " + "On Time: Off, Off Time: Off, Sleep Time: Off, Beep: 3 (Off), " + "Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, Eye: Off, " + "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: Off", + ac.toString()); + + const uint8_t EconoOn[39] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x3B, 0x43, 0xF0, 0x28, 0x0C, + 0x80, 0x04, 0xB0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xCE, 0xAF, + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x39, 0x28, 0x00, 0xA0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, 0x94, 0x60, 0x2E}; + const uint8_t EconoOff[39] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x3B, 0x43, 0xF0, 0x28, 0x0C, + 0x80, 0x04, 0xB0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xCE, 0xAF, + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x39, 0x28, 0x00, 0xA0, 0x00, + 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, 0x90, 0x60, 0x2A}; + ac.setRaw(EconoOn); + ASSERT_TRUE(ac.getEcono()); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 20C, Fan: 10 (Auto), " + "Swing (V): 14 (Auto), Swing (H): 190 (Auto), Clock: 13:47, " + "On Time: Off, Off Time: Off, Sleep Time: Off, Beep: 3 (Off), " + "Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, Eye: Off, " + "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: On", + ac.toString()); + ac.setRaw(EconoOff); + ASSERT_FALSE(ac.getEcono()); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 20C, Fan: 10 (Auto), " + "Swing (V): 14 (Auto), Swing (H): 190 (Auto), Clock: 13:47, " + "On Time: Off, Off Time: Off, Sleep Time: Off, Beep: 3 (Off), " + "Light: 3 (Off), Mold: On, Clean: On, Fresh Air: Off, Eye: Off, " + "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: Off", + ac.toString()); +} + +// Tests for IRDaikin216 class. + +TEST(TestDaikin216Class, Power) { + IRDaikin216 ac(0); + ac.begin(); + + ac.on(); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_FALSE(ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestDaikin216Class, Temperature) { + IRDaikin216 ac(0); + ac.begin(); + + ac.setTemp(0); + EXPECT_EQ(kDaikinMinTemp, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kDaikinMaxTemp, ac.getTemp()); + + ac.setTemp(kDaikinMinTemp); + EXPECT_EQ(kDaikinMinTemp, ac.getTemp()); + + ac.setTemp(kDaikinMaxTemp); + EXPECT_EQ(kDaikinMaxTemp, ac.getTemp()); + + ac.setTemp(kDaikinMinTemp - 1); + EXPECT_EQ(kDaikinMinTemp, ac.getTemp()); + + ac.setTemp(kDaikinMaxTemp + 1); + EXPECT_EQ(kDaikinMaxTemp, ac.getTemp()); + + ac.setTemp(kDaikinMinTemp + 1); + EXPECT_EQ(kDaikinMinTemp + 1, ac.getTemp()); + + ac.setTemp(21); + EXPECT_EQ(21, ac.getTemp()); + + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + + ac.setTemp(29); + EXPECT_EQ(29, ac.getTemp()); +} + +TEST(TestDaikin216Class, OperatingMode) { + IRDaikin216 ac(0); + ac.begin(); + + ac.setMode(kDaikinAuto); + EXPECT_EQ(kDaikinAuto, ac.getMode()); + + ac.setMode(kDaikinCool); + EXPECT_EQ(kDaikinCool, ac.getMode()); + + ac.setMode(kDaikinHeat); + EXPECT_EQ(kDaikinHeat, ac.getMode()); + + ac.setMode(kDaikinDry); + EXPECT_EQ(kDaikinDry, ac.getMode()); + + ac.setMode(kDaikinFan); + EXPECT_EQ(kDaikinFan, ac.getMode()); + + ac.setMode(kDaikinFan + 1); + EXPECT_EQ(kDaikinAuto, ac.getMode()); + + ac.setMode(kDaikinAuto + 1); + EXPECT_EQ(kDaikinAuto, ac.getMode()); + + ac.setMode(255); + EXPECT_EQ(kDaikinAuto, ac.getMode()); +} + + +TEST(TestDaikin216Class, VaneSwing) { + IRDaikin216 ac(0); + ac.begin(); + + ac.setSwingHorizontal(true); + ac.setSwingVertical(false); + + ac.setSwingHorizontal(true); + EXPECT_TRUE(ac.getSwingHorizontal()); + EXPECT_FALSE(ac.getSwingVertical()); + + ac.setSwingVertical(true); + EXPECT_TRUE(ac.getSwingHorizontal()); + EXPECT_TRUE(ac.getSwingVertical()); + + ac.setSwingHorizontal(false); + EXPECT_FALSE(ac.getSwingHorizontal()); + EXPECT_TRUE(ac.getSwingVertical()); + + ac.setSwingVertical(false); + EXPECT_FALSE(ac.getSwingHorizontal()); + EXPECT_FALSE(ac.getSwingVertical()); +} + +TEST(TestDaikin216Class, FanSpeed) { + IRDaikin216 ac(0); + ac.begin(); + + // Unexpected value should default to Auto. + ac.setFan(0); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + // Unexpected value should default to Auto. + ac.setFan(255); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(kDaikinFanMax); + EXPECT_EQ(kDaikinFanMax, ac.getFan()); + + // Beyond Max should default to Auto. + ac.setFan(kDaikinFanMax + 1); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(kDaikinFanMax - 1); + EXPECT_EQ(kDaikinFanMax - 1, ac.getFan()); + + ac.setFan(kDaikinFanMin); + EXPECT_EQ(kDaikinFanMin, ac.getFan()); + + ac.setFan(kDaikinFanMin + 1); + EXPECT_EQ(kDaikinFanMin + 1, ac.getFan()); + + // Beyond Min should default to Auto. + ac.setFan(kDaikinFanMin - 1); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(3); + EXPECT_EQ(3, ac.getFan()); + + ac.setFan(kDaikinFanAuto); + EXPECT_EQ(kDaikinFanAuto, ac.getFan()); + + ac.setFan(kDaikinFanQuiet); + EXPECT_EQ(kDaikinFanQuiet, ac.getFan()); +} + +TEST(TestDaikin216Class, Quiet) { + IRDaikin216 ac(0); + ac.begin(); + + ac.setQuiet(true); + EXPECT_TRUE(ac.getQuiet()); + + ac.setQuiet(false); + EXPECT_FALSE(ac.getQuiet()); + + ac.setQuiet(true); + EXPECT_TRUE(ac.getQuiet()); +} + +TEST(TestDaikin216Class, ExampleStates) { + IRDaikin216 ac(0); + ac.begin(); + // https://github.com/markszabo/IRremoteESP8266/pull/690#issuecomment-487770194 + uint8_t state[kDaikin216StateLength] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x02, + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x21, 0xC0, 0x00, 0xA0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x53}; + ac.setRaw(state); + EXPECT_EQ( + "Power: On, Mode: 2 (DRY), Temp: 32C, Fan: 10 (AUTO), " + "Swing (Horizontal): Off, Swing (Vertical): Off, Quiet: Off", + ac.toString()); +} + +TEST(TestDaikin216Class, ReconstructKnownState) { + IRDaikin216 ac(0); + ac.begin(); + // https://github.com/markszabo/IRremoteESP8266/issues/689#issue-438086949 + uint8_t expectedState[kDaikin216StateLength] = { + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x02, + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x00, 0x26, 0x00, 0xA0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x98}; + ac.setPower(false); + ac.setMode(kDaikinAuto); + ac.setTemp(19); + ac.setFan(kDaikinFanAuto); + ac.setSwingHorizontal(false); + ac.setSwingVertical(false); + ac.setQuiet(false); + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (AUTO), " + "Swing (Horizontal): Off, Swing (Vertical): Off, Quiet: Off", + ac.toString()); + + EXPECT_STATE_EQ(expectedState, ac.getRaw(), kDaikin216Bits); +} + +// https://github.com/markszabo/IRremoteESP8266/issues/689 +TEST(TestDecodeDaikin216, RealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + // https://github.com/markszabo/IRremoteESP8266/issues/689#issue-438086949 + uint16_t rawData[439] = { + 3402, 1770, 382, 1340, 382, 480, 382, 478, 382, 480, 380, 1342, 382, 478, + 356, 504, 382, 480, 380, 478, 384, 1342, 380, 480, 380, 1342, 382, 1342, + 382, 478, 382, 1340, 382, 1340, 384, 1340, 382, 1342, 382, 1340, 380, 480, + 382, 480, 382, 1296, 426, 480, 380, 480, 382, 480, 380, 480, 382, 480, + 382, 478, 382, 1342, 382, 1342, 382, 1340, 356, 1368, 382, 478, 382, 480, + 382, 478, 380, 480, 382, 480, 382, 480, 382, 478, 382, 480, 382, 478, 358, + 504, 382, 480, 380, 480, 382, 480, 382, 480, 380, 480, 382, 478, 382, 480, + 382, 478, 382, 480, 354, 506, 354, 506, 380, 480, 382, 480, 382, 480, 382, + 480, 380, 1342, 382, 480, 382, 480, 382, 478, 382, 478, 382, 478, 384, + 478, 382, 29652, 3426, 1772, 382, 1340, 382, 480, 380, 478, 382, 480, 382, + 1342, 382, 480, 382, 480, 382, 478, 356, 506, 382, 1342, 380, 480, 382, + 1340, 382, 1340, 382, 478, 356, 1366, 382, 1340, 384, 1340, 382, 1340, + 382, 1342, 382, 478, 382, 478, 382, 1340, 382, 478, 382, 478, 382, 478, + 382, 480, 382, 480, 384, 478, 358, 504, 382, 478, 382, 480, 382, 478, 382, + 480, 382, 480, 382, 478, 382, 480, 382, 478, 382, 478, 382, 478, 382, 478, + 384, 478, 382, 478, 360, 500, 358, 504, 382, 478, 382, 480, 382, 480, 382, + 478, 382, 478, 382, 1340, 382, 1342, 382, 480, 380, 480, 382, 1342, 382, + 478, 382, 480, 356, 506, 382, 478, 382, 480, 382, 480, 356, 506, 382, 478, + 382, 480, 382, 478, 382, 480, 382, 478, 382, 480, 380, 480, 380, 480, 382, + 1342, 382, 478, 382, 1342, 382, 480, 382, 480, 382, 478, 382, 478, 382, + 480, 382, 478, 382, 480, 356, 504, 384, 478, 382, 480, 382, 480, 380, 480, + 382, 478, 382, 480, 382, 480, 382, 478, 356, 504, 384, 478, 380, 480, 382, + 480, 382, 480, 382, 478, 356, 506, 382, 478, 382, 480, 380, 480, 382, 478, + 382, 480, 382, 478, 382, 480, 358, 504, 382, 478, 382, 478, 356, 504, 382, + 478, 382, 480, 382, 478, 382, 478, 382, 478, 382, 480, 380, 480, 382, 480, + 380, 480, 356, 506, 356, 504, 382, 480, 382, 478, 382, 478, 382, 478, 382, + 478, 382, 480, 382, 478, 382, 480, 382, 480, 382, 1340, 382, 1342, 382, + 478, 384, 478, 382, 478, 382, 480, 380, 480, 382, 478, 382, 480, 356, 506, + 382, 478, 382, 480, 382, 478, 356, 506, 380, 480, 382, 478, 382, 478, 382, + 478, 382, 480, 382, 480, 380, 480, 382, 1342, 382, 1340, 382, 480, 356, + 504, 382, 1342, 382}; // UNKNOWN E0E32232 + uint8_t expectedState[kDaikin216StateLength] = { + // 8 bytes + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x02, + // 19 bytes + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x00, 0x26, 0x00, 0xA0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x98}; + + irsend.begin(); + irsend.reset(); + irsend.sendRaw(rawData, 439, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN216, irsend.capture.decode_type); + ASSERT_EQ(kDaikin216Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRDaikin216 ac(0); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 19C, Fan: 10 (AUTO), " + "Swing (Horizontal): Off, Swing (Vertical): Off, Quiet: Off", + ac.toString()); +} + +// https://github.com/markszabo/IRremoteESP8266/issues/689 +TEST(TestDecodeDaikin216, SyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + // https://github.com/markszabo/IRremoteESP8266/issues/689#issue-438086949 + uint8_t expectedState[kDaikin216StateLength] = { + // 8 bytes + 0x11, 0xDA, 0x27, 0xF0, 0x00, 0x00, 0x00, 0x02, + // 19 bytes + 0x11, 0xDA, 0x27, 0x00, 0x00, 0x00, 0x26, 0x00, 0xA0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x98}; + + irsend.begin(); + irsend.reset(); + irsend.sendDaikin216(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(DAIKIN216, irsend.capture.decode_type); + ASSERT_EQ(kDaikin216Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Denon_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Denon_test.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Denon_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Denon_test.cpp index 911fd7528..6b80eae02 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Denon_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Denon_test.cpp @@ -14,6 +14,7 @@ TEST(TestSendDenon, SendDataOnly) { irsend.reset(); irsend.sendDenon(0x2278); // Denon AVR Power On. (Sharp) EXPECT_EQ( + "f38000d33" "m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780" "m260s1820m260s1820m260s1820m260s1820m260s780m260s780m260s780" "m260s43602" @@ -26,6 +27,7 @@ TEST(TestSendDenon, SendDataOnly) { // Denon Eco Mode On. (Panasonic/Kaseikyo) irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS); EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" @@ -45,6 +47,7 @@ TEST(TestSendDenon, SendNormalWithRepeats) { irsend.reset(); irsend.sendDenon(0x2278, DENON_BITS, 1); // 1 repeat. EXPECT_EQ( + "f38000d33" "m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780" "m260s1820m260s1820m260s1820m260s1820m260s780m260s780m260s780" "m260s43602" @@ -60,6 +63,7 @@ TEST(TestSendDenon, SendNormalWithRepeats) { irsend.outputStr()); irsend.sendDenon(0x2278, DENON_BITS, 2); // 2 repeats. EXPECT_EQ( + "f38000d33" "m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780" "m260s1820m260s1820m260s1820m260s1820m260s780m260s780m260s780" "m260s43602" @@ -88,6 +92,7 @@ TEST(TestSendDenon, Send48BitWithRepeats) { irsend.reset(); irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS, 1); // 1 repeat. EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" @@ -107,6 +112,7 @@ TEST(TestSendDenon, Send48BitWithRepeats) { irsend.outputStr()); irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS, 2); // 2 repeats. EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" @@ -142,6 +148,7 @@ TEST(TestSendDenon, SendUnusualSize) { irsend.reset(); irsend.sendDenon(0x12, 8); EXPECT_EQ( + "f38000d33" "m260s780m260s780m260s780m260s1820m260s780m260s780m260s1820m260s780" "m260s43602" "m260s1820m260s1820m260s1820m260s780m260s1820m260s1820m260s780m260s1820" @@ -151,6 +158,7 @@ TEST(TestSendDenon, SendUnusualSize) { irsend.reset(); irsend.sendDenon(0x1234567890ABCDEF, 64); EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s432m432s432m432s432m432s1296m432s432m432s432m432s1296m432s432" "m432s432m432s432m432s1296m432s1296m432s432m432s1296m432s432m432s432" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Dish_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Dish_test.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Dish_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Dish_test.cpp index 0c58496ce..21286b7ac 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Dish_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Dish_test.cpp @@ -14,6 +14,7 @@ TEST(TestSendDish, SendDataOnly) { irsend.reset(); irsend.sendDISH(0x0); EXPECT_EQ( + "f57600d50" "m400s6100" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" @@ -32,6 +33,7 @@ TEST(TestSendDish, SendDataOnly) { irsend.reset(); irsend.sendDISH(0x9C00); // Power on. EXPECT_EQ( + "f57600d50" "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" @@ -50,6 +52,7 @@ TEST(TestSendDish, SendDataOnly) { irsend.reset(); irsend.sendDISH(0xFFFF); EXPECT_EQ( + "f57600d50" "m400s6100" "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" @@ -74,6 +77,7 @@ TEST(TestSendDish, SendWithRepeats) { irsend.reset(); irsend.sendDISH(0x9C00, kDishBits, 0); // 0 repeats. EXPECT_EQ( + "f57600d50" "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" @@ -83,6 +87,7 @@ TEST(TestSendDish, SendWithRepeats) { irsend.reset(); irsend.sendDISH(0x9C00, kDishBits, 1); // 1 repeat. EXPECT_EQ( + "f57600d50" "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" @@ -94,6 +99,7 @@ TEST(TestSendDish, SendWithRepeats) { irsend.sendDISH(0x9C00, kDishBits, 2); // 2 repeats. EXPECT_EQ( + "f57600d50" "m400s6100" "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" @@ -115,6 +121,7 @@ TEST(TestSendDish, SendUnusualSize) { irsend.reset(); irsend.sendDISH(0x0, 8); EXPECT_EQ( + "f57600d50" "m400s6100" "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" "m400s6100" @@ -129,6 +136,7 @@ TEST(TestSendDish, SendUnusualSize) { irsend.reset(); irsend.sendDISH(0x1234567890ABCDEF, 64); EXPECT_EQ( + "f57600d50" "m400s6100" "m400s2800m400s2800m400s2800m400s1700m400s2800m400s2800m400s1700m400s2800" "m400s2800m400s2800m400s1700m400s1700m400s2800m400s1700m400s2800m400s2800" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Electra_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Electra_test.cpp similarity index 84% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Electra_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Electra_test.cpp index df5dd7a5c..7d6d0c915 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Electra_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Electra_test.cpp @@ -12,12 +12,13 @@ TEST(TestSendElectraAC, SendDataOnly) { IRsendTest irsend(0); irsend.begin(); - uint8_t data[kElectraAcStateLength] = {0xC3, 0xE1, 0x6F, 0x14, 0x06, - 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0xA0, 0xB0}; + uint8_t data[kElectraAcStateLength] = {0xC3, 0x87, 0xF6, 0x28, 0x60, + 0x00, 0x20, 0x00, 0x00, 0x20, + 0x00, 0x05, 0x0D}; irsend.sendElectraAC(data); EXPECT_EQ( + "f38000d50" "m9166s4470" "m646s1647m646s1647m646s547m646s547m646s547m646s547m646s1647m646s1647" "m646s1647m646s1647m646s1647m646s547m646s547m646s547m646s547m646s1647" @@ -46,9 +47,9 @@ TEST(TestDecodeElectraAC, SyntheticDecode) { // Synthesised Normal ElectraAC message. irsend.reset(); - uint8_t expectedState[kElectraAcStateLength] = {0xC3, 0xE1, 0x6F, 0x14, 0x06, - 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0xA0, 0xB0}; + uint8_t expectedState[kElectraAcStateLength] = {0xC3, 0x87, 0xF6, 0x28, 0x60, + 0x00, 0x20, 0x00, 0x00, 0x20, + 0x00, 0x05, 0x0D}; irsend.sendElectraAC(expectedState); irsend.makeDecodeResult(); EXPECT_TRUE(irrecv.decode(&irsend.capture)); @@ -84,9 +85,9 @@ TEST(TestDecodeElectraAC, RealExampleDecode) { 662, 562, 642, 1686, 582, 570, 634, 566, 604, 576, 636, 566, 610, 578, 634, 1664, 584, 590, 660, 1636, 610, 1642, 664, 590, 610, 590, 636, 566, 634, 568, 686}; // UNKNOWN 9AD8CDB5 - uint8_t expectedState[kElectraAcStateLength] = {0xC3, 0xE1, 0x6F, 0x14, 0x06, - 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0xA0, 0xB0}; + uint8_t expectedState[kElectraAcStateLength] = {0xC3, 0x87, 0xF6, 0x28, 0x60, + 0x00, 0x20, 0x00, 0x00, 0x20, + 0x00, 0x05, 0x0D}; irsend.reset(); irsend.sendRaw(rawData, 211, 38000); diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Fujitsu_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Fujitsu_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Fujitsu_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Fujitsu_test.cpp index 23fa3e7a7..b895e4d9b 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Fujitsu_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Fujitsu_test.cpp @@ -183,6 +183,7 @@ TEST(TestSendFujitsuAC, GenerateMessage) { irsend.reset(); irsend.sendFujitsuAC(fujitsu.getRaw(), kFujitsuAcStateLength); EXPECT_EQ( + "f38000d50" "m3324s1574" "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390" "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390" @@ -217,6 +218,7 @@ TEST(TestSendFujitsuAC, GenerateShortMessage) { irsend.reset(); irsend.sendFujitsuAC(fujitsu.getRaw(), kFujitsuAcStateLengthShort); EXPECT_EQ( + "f38000d50" "m3324s1574m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448" "s390m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390" "m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390m448s390" @@ -238,6 +240,7 @@ TEST(TestSendFujitsuAC, Issue275) { fujitsu.setCmd(kFujitsuAcCmdTurnOff); irsend.sendFujitsuAC(fujitsu.getRaw(), kFujitsuAcStateLengthShort); EXPECT_EQ( + "f38000d50" // Header "m3324s1574" // 0 0 1 0 1 0 0 0 (0x28) @@ -272,6 +275,7 @@ TEST(TestSendFujitsuAC, Issue275) { 450, 1250, 450}; irsend.sendRaw(off, 115, 38); EXPECT_EQ( + "f38000d50" // Header "m3350s1650" // 0 0 1 0 1 0 0 0 (0x28) @@ -534,6 +538,7 @@ TEST(TestDecodeFujitsuAC, Issue414) { ASSERT_EQ(kFujitsuAcBits, irsend.capture.bits); EXPECT_TRUE(ArraysMatch(state, irsend.capture.state)); EXPECT_EQ( + "f38000d50" "m3324s1574" "m448s390m448s390m448s1182m448s390m448s1182m448s390m448s390m448s390" "m448s1182m448s1182m448s390m448s390m448s390m448s1182m448s1182m448s390" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_GICable_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_GICable_test.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_GICable_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_GICable_test.cpp index b9bfce997..bad9bbded 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_GICable_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_GICable_test.cpp @@ -12,6 +12,7 @@ TEST(TestSendGICable, SendDataOnly) { irsend.begin(); irsend.sendGICable(0); EXPECT_EQ( + "f39000d50" "m9000s4400" "m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200" "m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200m550s2200" @@ -20,6 +21,7 @@ TEST(TestSendGICable, SendDataOnly) { irsend.outputStr()); irsend.sendGICable(0x8807); EXPECT_EQ( + "f39000d50" "m9000s4400" "m550s4400m550s2200m550s2200m550s2200m550s4400m550s2200m550s2200m550s2200" "m550s2200m550s2200m550s2200m550s2200m550s2200m550s4400m550s4400m550s4400" @@ -28,6 +30,7 @@ TEST(TestSendGICable, SendDataOnly) { irsend.outputStr()); irsend.sendGICable(0xFFFF); EXPECT_EQ( + "f39000d50" "m9000s4400" "m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400" "m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400m550s4400" @@ -43,6 +46,7 @@ TEST(TestSendGICable, SendWithRepeats) { // Send a command with 0 repeats. irsend.sendGICable(0x8807, kGicableBits, 0); EXPECT_EQ( + "f39000d50" "m9000s4400" "m550s4400m550s2200m550s2200m550s2200m550s4400m550s2200m550s2200m550s2200" "m550s2200m550s2200m550s2200m550s2200m550s2200m550s4400m550s4400m550s4400" @@ -51,6 +55,7 @@ TEST(TestSendGICable, SendWithRepeats) { // Send a command with 1 repeat. irsend.sendGICable(0x8807, kGicableBits, 1); EXPECT_EQ( + "f39000d50" "m9000s4400" "m550s4400m550s2200m550s2200m550s2200m550s4400m550s2200m550s2200m550s2200" "m550s2200m550s2200m550s2200m550s2200m550s2200m550s4400m550s4400m550s4400" @@ -60,6 +65,7 @@ TEST(TestSendGICable, SendWithRepeats) { // Send a command with 3 repeats. irsend.sendGICable(0x8807, kGicableBits, 3); EXPECT_EQ( + "f39000d50" "m9000s4400" "m550s4400m550s2200m550s2200m550s2200m550s4400m550s2200m550s2200m550s2200" "m550s2200m550s2200m550s2200m550s2200m550s2200m550s4400m550s4400m550s4400" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_GlobalCache_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_GlobalCache_test.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_GlobalCache_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_GlobalCache_test.cpp index 16a556b57..00742aeda 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_GlobalCache_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_GlobalCache_test.cpp @@ -29,6 +29,7 @@ TEST(TestSendGlobalCache, NonRepeatingCode) { EXPECT_EQ(0x4, irsend.capture.address); EXPECT_EQ(0x41, irsend.capture.command); EXPECT_EQ( + "f38000d50" "m8892s4472m546s572m546s546m546s1690m546s546m546s572m546s572" "m546s546m546s572m546s1690m546s1690m546s572m546s1690m546s1690" "m546s1690m546s1690m546s1690m546s1690m546s572m546s572m546s546" @@ -60,6 +61,7 @@ TEST(TestSendGlobalCache, RepeatCode) { EXPECT_EQ(0x4583, irsend.capture.address); EXPECT_EQ(0x11, irsend.capture.command); EXPECT_EQ( + "f38000d50" "m8866s4446m546s1664m546s1664m546s546m546s546m546s546m546s546" "m546s546m546s1664m546s1664m546s546m546s1664m546s546m546s546" "m546s546m546s1664m546s546m546s1664m546s546m546s546m546s546" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Gree_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Gree_test.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Gree_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Gree_test.cpp index 6c7a1f637..a05b06391 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Gree_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Gree_test.cpp @@ -20,7 +20,8 @@ TEST(TestSendGreeChars, SendData) { irsend.reset(); irsend.sendGree(gree_code); EXPECT_EQ( - "m9000s4000" + "f38000d50" + "m9000s4500" "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" @@ -42,7 +43,8 @@ TEST(TestSendGreeUint64, SendData) { irsend.reset(); irsend.sendGree(0x1234567890ABCDEF); EXPECT_EQ( - "m9000s4000" + "f38000d50" + "m9000s4500" "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" @@ -69,7 +71,8 @@ TEST(TestSendGreeChars, SendWithRepeats) { irsend.sendGree(gree_code, kGreeStateLength, 1); EXPECT_EQ( - "m9000s4000" + "f38000d50" + "m9000s4500" "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" @@ -81,7 +84,7 @@ TEST(TestSendGreeChars, SendWithRepeats) { "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" "m620s19000" - "m9000s4000" + "m9000s4500" "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" @@ -103,7 +106,8 @@ TEST(TestSendGreeUint64, SendWithRepeats) { irsend.reset(); irsend.sendGree(0x1234567890ABCDEF, kGreeBits, 1); EXPECT_EQ( - "m9000s4000" + "f38000d50" + "m9000s4500" "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" @@ -115,7 +119,7 @@ TEST(TestSendGreeUint64, SendWithRepeats) { "m620s1600m620s540m620s1600m620s1600m620s540m620s540m620s1600m620s1600" "m620s1600m620s1600m620s1600m620s1600m620s540m620s1600m620s1600m620s1600" "m620s19000" - "m9000s4000" + "m9000s4500" "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" @@ -146,7 +150,8 @@ TEST(TestSendGreeChars, SendUnexpectedSizes) { irsend.reset(); irsend.sendGree(gree_long_code, kGreeStateLength + 1); ASSERT_EQ( - "m9000s4000" + "f38000d50" + "m9000s4500" "m620s540m620s1600m620s540m620s540m620s1600m620s540m620s540m620s540" "m620s540m620s540m620s1600m620s540m620s1600m620s1600m620s540m620s540" "m620s540m620s1600m620s1600m620s540m620s1600m620s540m620s1600m620s540" @@ -486,7 +491,7 @@ TEST(TestDecodeGree, NormalSynthetic) { EXPECT_STATE_EQ(gree_code, irsend.capture.state, kGreeBits); } -// Decode a synthetic Gree message. +// Decode a real Gree message. TEST(TestDecodeGree, NormalRealExample) { IRsendTest irsend(4); IRrecv irrecv(4); diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Haier_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Haier_test.cpp similarity index 90% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Haier_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Haier_test.cpp index 11848e00a..8d306cb0b 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Haier_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Haier_test.cpp @@ -19,6 +19,7 @@ TEST(TestSendHaierAC, SendDataOnly) { irsend.reset(); irsend.sendHaierAC(haier_zero); EXPECT_EQ( + "f38000d50" "m3000s3000m3000s4300" "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s650" @@ -37,6 +38,7 @@ TEST(TestSendHaierAC, SendDataOnly) { irsend.reset(); irsend.sendHaierAC(haier_test); EXPECT_EQ( + "f38000d50" "m3000s3000m3000s4300" "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s650m520s1650" "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" @@ -62,6 +64,7 @@ TEST(TestSendHaierAC, SendWithRepeats) { irsend.reset(); irsend.sendHaierAC(haier_test, kHaierACStateLength, 2); // two repeats. EXPECT_EQ( + "f38000d50" "m3000s3000m3000s4300" "m520s1650m520s650m520s1650m520s650m520s650m520s1650m520s650m520s1650" "m520s650m520s650m520s650m520s650m520s650m520s650m520s650m520s1650" @@ -404,7 +407,7 @@ TEST(TestHaierACClass, MessageConstuction) { haier.toString()); uint8_t expectedState[kHaierACStateLength] = {0xA5, 0x96, 0xEA, 0xCF, 0x32, - 0x2D, 0x0D, 0x74, 0xD4}; + 0xED, 0x2D, 0x74, 0xB4}; EXPECT_STATE_EQ(expectedState, haier.getRaw(), kHaierACBits); // Check that the checksum is valid. @@ -987,3 +990,91 @@ TEST(TestDecodeHaierAC_YRW02, RealExample) { " Health: On", haier.toString()); } + +// Default state of the remote needed to include hidden data. +// Ref: https://github.com/markszabo/IRremoteESP8266/issues/668 +TEST(TestHaierAcIssues, Issue668) { + IRHaierAC ac(0); + IRHaierAC acText(1); + IRrecv irrecv(0); + ac.begin(); + + // Turn on the AC. + ac._irsend.reset(); + char expected_on[] = + "Command: 1 (On), Mode: 0 (AUTO), Temp: 25C, Fan: 0 (AUTO), " + "Swing: 0 (Off), Sleep: Off, Health: Off, Current Time: 00:00, " + "On Timer: Off, Off Timer: Off"; + // State taken from real capture: + // https://github.com/markszabo/IRremoteESP8266/issues/668#issuecomment-483531895 + uint8_t expected_on_state[9] = { + 0xA5, 0x91, 0x20, 0x00, 0x0C, 0xC0, 0x20, 0x00, 0x42}; + ac.setCommand(kHaierAcCmdOn); + EXPECT_EQ(expected_on, ac.toString()); + ac.send(); + ac._irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&ac._irsend.capture)); + ASSERT_EQ(HAIER_AC, ac._irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, ac._irsend.capture.bits); + EXPECT_STATE_EQ(expected_on_state, + ac._irsend.capture.state, ac._irsend.capture.bits); + acText.setRaw(ac._irsend.capture.state); + EXPECT_EQ(expected_on, acText.toString()); + + // Set the temp to 25C + ac._irsend.reset(); + ac.setTemp(25); + EXPECT_EQ(expected_on, ac.toString()); + ASSERT_EQ(25, ac.getTemp()); + ac.send(); + ac._irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&ac._irsend.capture)); + ASSERT_EQ(HAIER_AC, ac._irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, ac._irsend.capture.bits); + EXPECT_STATE_EQ(expected_on_state, + ac._irsend.capture.state, ac._irsend.capture.bits); + acText.setRaw(ac._irsend.capture.state); + EXPECT_EQ(expected_on, acText.toString()); + + // Increase the temp by 1. + ac._irsend.reset(); + char expected_temp_plus_one[] = + "Command: 6 (Temp Up), Mode: 0 (AUTO), Temp: 26C, Fan: 0 (AUTO), " + "Swing: 0 (Off), Sleep: Off, Health: Off, Current Time: 00:00, " + "On Timer: Off, Off Timer: Off"; + // State taken from real capture: + // https://github.com/markszabo/IRremoteESP8266/issues/668#issuecomment-483531895 + uint8_t expected_temp_plus_one_state[9] = { + 0xA5, 0xA6, 0x20, 0x00, 0x0C, 0xC0, 0x20, 0x00, 0x57}; + ASSERT_EQ(25, ac.getTemp()); + ac.setTemp(ac.getTemp() + 1); + ASSERT_EQ(26, ac.getTemp()); + EXPECT_EQ(expected_temp_plus_one, ac.toString()); + ac.send(); + ac._irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&ac._irsend.capture)); + ASSERT_EQ(HAIER_AC, ac._irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, ac._irsend.capture.bits); + EXPECT_STATE_EQ(expected_temp_plus_one_state, + ac._irsend.capture.state, ac._irsend.capture.bits); + acText.setRaw(ac._irsend.capture.state); + EXPECT_EQ(expected_temp_plus_one, acText.toString()); + + // Decrease the temp by 1. + ac._irsend.reset(); + char expected_temp_minus_one[] = + "Command: 7 (Temp Down), Mode: 0 (AUTO), Temp: 25C, Fan: 0 (AUTO), " + "Swing: 0 (Off), Sleep: Off, Health: Off, Current Time: 00:00, " + "On Timer: Off, Off Timer: Off"; + ASSERT_EQ(26, ac.getTemp()); + ac.setTemp(ac.getTemp() - 1); + ASSERT_EQ(25, ac.getTemp()); + EXPECT_EQ(expected_temp_minus_one, ac.toString()); + ac.send(); + ac._irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&ac._irsend.capture)); + ASSERT_EQ(HAIER_AC, ac._irsend.capture.decode_type); + EXPECT_EQ(kHaierACBits, ac._irsend.capture.bits); + acText.setRaw(ac._irsend.capture.state); + EXPECT_EQ(expected_temp_minus_one, acText.toString()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Hitachi_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Hitachi_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Hitachi_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Hitachi_test.cpp index de0a4a2a1..a2471c4aa 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Hitachi_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Hitachi_test.cpp @@ -22,6 +22,7 @@ TEST(TestSendHitachiAC, SendData) { irsend.reset(); irsend.sendHitachiAC(hitachi_code); EXPECT_EQ( + "f38000d50" "m3300s1700" "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" @@ -68,6 +69,7 @@ TEST(TestSendHitachiAC, SendWithRepeats) { irsend.sendHitachiAC(hitachi_code, kHitachiAcStateLength, 1); EXPECT_EQ( + "f38000d50" "m3300s1700" "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" @@ -151,6 +153,7 @@ TEST(TestSendHitachiAC, SendUnexpectedSizes) { irsend.reset(); irsend.sendHitachiAC(hitachi_long_code, kHitachiAcStateLength + 1); ASSERT_EQ( + "f38000d50" "m3300s1700" "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" @@ -511,6 +514,7 @@ TEST(TestSendHitachiAC1, SendData) { irsend.reset(); irsend.sendHitachiAC1(hitachi_code); EXPECT_EQ( + "f38000d50" "m3400s3400" "m400s1250m400s500m400s1250m400s1250m400s500m400s500m400s1250m400s500" "m400s1250m400s500m400s1250m400s500m400s1250m400s1250m400s1250m400s500" @@ -585,6 +589,7 @@ TEST(TestSendHitachiAC2, SendData) { irsend.reset(); irsend.sendHitachiAC2(hitachi_code); EXPECT_EQ( + "f38000d50" "m3300s1700" "m400s1250m400s500m400s500m400s500m400s500m400s500m400s500m400s500" "m400s500m400s500m400s500m400s500m400s1250m400s500m400s500m400s500" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_JVC_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_JVC_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_JVC_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_JVC_test.cpp index c899fa8c6..3cd99c3aa 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_JVC_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_JVC_test.cpp @@ -14,6 +14,7 @@ TEST(TestSendJVC, SendDataOnly) { irsend.reset(); irsend.sendJVC(0xC2B8); // JVC VCR Power On. EXPECT_EQ( + "f38000d33" "m8400s4200" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" @@ -29,6 +30,7 @@ TEST(TestSendJVC, SendWithRepeats) { irsend.reset(); irsend.sendJVC(0xC2B8, kJvcBits, 1); // 1 repeat. EXPECT_EQ( + "f38000d33" "m8400s4200" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" @@ -39,6 +41,7 @@ TEST(TestSendJVC, SendWithRepeats) { irsend.outputStr()); irsend.sendJVC(0xC2B8, kJvcBits, 2); // 2 repeats. EXPECT_EQ( + "f38000d33" "m8400s4200" "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" @@ -60,6 +63,7 @@ TEST(TestSendJVC, SendUnusualSize) { irsend.reset(); irsend.sendJVC(0x0, 8); EXPECT_EQ( + "f38000d33" "m8400s4200" "m525s525m525s525m525s525m525s525m525s525m525s525m525s525m525s525" "m525s38475", @@ -68,6 +72,7 @@ TEST(TestSendJVC, SendUnusualSize) { irsend.reset(); irsend.sendJVC(0x1234567890ABCDEF, 64); EXPECT_EQ( + "f38000d33" "m8400s4200" "m525s525m525s525m525s525m525s1725m525s525m525s525m525s1725m525s525" "m525s525m525s525m525s1725m525s1725m525s525m525s1725m525s525m525s525" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Kelvinator_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Kelvinator_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Kelvinator_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Kelvinator_test.cpp index 001f8bcf2..38a298e58 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Kelvinator_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Kelvinator_test.cpp @@ -21,6 +21,7 @@ TEST(TestSendKelvinator, SendDataOnly) { irsend.reset(); irsend.sendKelvinator(kelv_code); EXPECT_EQ( + "f38000d50" "m9010s4505" "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" @@ -61,6 +62,7 @@ TEST(TestSendKelvinator, SendWithRepeats) { irsend.sendKelvinator(kelv_code, kKelvinatorStateLength, 1); EXPECT_EQ( + "f38000d50" "m9010s4505" "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" @@ -131,6 +133,7 @@ TEST(TestSendKelvinator, SendUnexpectedSizes) { // extra data. irsend.sendKelvinator(kelv_long_code, 17); ASSERT_EQ( + "f38000d50" "m9010s4505" "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s510m680s510" "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" @@ -472,6 +475,7 @@ TEST(TestKelvinatorClass, MessageConstuction) { irsend.reset(); irsend.sendKelvinator(irkelv.getRaw()); EXPECT_EQ( + "f38000d50" "m9010s4505" "m680s1530m680s510m680s510m680s1530m680s1530m680s510m680s1530m680s510" "m680s1530m680s1530m680s510m680s1530m680s510m680s510m680s510m680s510" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_LG_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_LG_test.cpp similarity index 88% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_LG_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_LG_test.cpp index 8ab24a731..2925494b9 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_LG_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_LG_test.cpp @@ -30,6 +30,7 @@ TEST(TestSendLG, SendDataOnly) { irsend.reset(); irsend.sendLG(0x4B4AE51); EXPECT_EQ( + "f38000d50" "m8500s4250" "m550s550m550s1600m550s550m550s550" "m550s1600m550s550m550s1600m550s1600m550s550m550s1600m550s550m550s550" @@ -41,6 +42,7 @@ TEST(TestSendLG, SendDataOnly) { irsend.reset(); irsend.sendLG(0xB4B4AE51, kLg32Bits); EXPECT_EQ( + "f38000d33" "m4480s4480" "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" @@ -59,6 +61,7 @@ TEST(TestSendLG, SendWithRepeats) { irsend.reset(); irsend.sendLG(0x4B4AE51, kLgBits, 1); EXPECT_EQ( + "f38000d50" "m8500s4250" "m550s550m550s1600m550s550m550s550" "m550s1600m550s550m550s1600m550s1600m550s550m550s1600m550s550m550s550" @@ -71,6 +74,7 @@ TEST(TestSendLG, SendWithRepeats) { irsend.reset(); irsend.sendLG(0xB4B4AE51, kLg32Bits, 1); EXPECT_EQ( + "f38000d33" "m4480s4480" "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" @@ -90,6 +94,7 @@ TEST(TestSendLG, SendUnusualSize) { irsend.reset(); irsend.sendLG(0x0, 31); EXPECT_EQ( + "f38000d50" "m8500s4250" "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" @@ -101,6 +106,7 @@ TEST(TestSendLG, SendUnusualSize) { irsend.reset(); irsend.sendLG(0x0, 64); EXPECT_EQ( + "f38000d33" "m4480s4480" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" @@ -373,6 +379,7 @@ TEST(TestSendLG2, SendDataOnly) { irsend.reset(); irsend.sendLG2(0x880094D); EXPECT_EQ( + "f38000d50" "m3200s9850" "m550s1600m550s550m550s550m550s550m550s1600m550s550m550s550m550s550" "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" @@ -420,3 +427,54 @@ TEST(TestDecodeLG2, RealLG2Example) { EXPECT_EQ(kLgBits, irsend.capture.bits); EXPECT_EQ(0x880094D, irsend.capture.value); } + +// Tests for issue reported in +// https://github.com/markszabo/IRremoteESP8266/issues/620 +TEST(TestDecodeLG, Issue620) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Raw data as reported in initial comment of Issue #620 + uint16_t rawData[59] = { + 8886, 4152, + 560, 1538, 532, 502, 532, 504, 530, 484, 558, 1536, + 508, 516, 558, 502, 532, 484, 558, 502, 532, 500, + 534, 508, 532, 502, 532, 1518, 558, 510, 532, 484, + 556, 486, 556, 510, 532, 1518, 558, 1560, 532, 1528, + 556, 504, 530, 506, 530, 1520, 558, 508, 534, 500, + 532, 512, 530, 484, 556, 1536, 532}; // LG 8808721 + irsend.sendRaw(rawData, 59, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(28, irsend.capture.bits); + EXPECT_EQ(0x8808721, irsend.capture.value); + EXPECT_EQ(0x88, irsend.capture.address); + EXPECT_EQ(0x872, irsend.capture.command); + + irsend.reset(); + + // Resend the same code as the report is a sent code doesn't decode + // to the same message code. + irsend.sendLG(0x8808721); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(28, irsend.capture.bits); + EXPECT_EQ(0x8808721, irsend.capture.value); + EXPECT_EQ(0x88, irsend.capture.address); + EXPECT_EQ(0x872, irsend.capture.command); + // The following seems to match the rawData above. + EXPECT_EQ( + "f38000d50" + "m8500s4250" + "m550s1600m550s550m550s550m550s550m550s1600" + "m550s550m550s550m550s550m550s550m550s550" + "m550s550m550s550m550s1600m550s550m550s550" + "m550s550m550s550m550s1600m550s1600m550s1600" + "m550s550m550s550m550s1600m550s550m550s550" + "m550s550m550s550m550s1600m550" + "s55550", + irsend.outputStr()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Lasertag_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Lasertag_test.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Lasertag_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Lasertag_test.cpp index 041109fb8..bad724f76 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Lasertag_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Lasertag_test.cpp @@ -20,6 +20,7 @@ TEST(TestSendLasertag, SendDataOnly) { irsend.reset(); irsend.sendLasertag(0x1); // Red 1 EXPECT_EQ( + "f36000d25" "m333s333m333s333m333s333m333s333m333s333m333s333m333s333m333s333m333" "s333m333s333m333s333m333s666m333s100000", irsend.outputStr()); @@ -27,6 +28,7 @@ TEST(TestSendLasertag, SendDataOnly) { irsend.reset(); irsend.sendLasertag(0x2); // Red 2 EXPECT_EQ( + "f36000d25" "m333s333m333s333m333s333m333s333m333s333m333s333m333s333" "m333s333m333s333m333s333m333s666m666s100333", irsend.outputStr()); @@ -38,6 +40,7 @@ TEST(TestSendLasertag, SendDataOnly) { EXPECT_EQ( // m364s364m332s336m384s276m332s364m332s304m416s584 // m692s724m640s360m304s332m392s612m380 + "f36000d25" "m333s333m333s333m333s333m333s333m333s333m333s666" "m666s666m666s333m333s333m333s666m333s100000", irsend.outputStr()); @@ -49,6 +52,7 @@ TEST(TestSendLasertag, SendDataOnly) { EXPECT_EQ( // m332s308m412s280m360s336m332s304m444s248m332s644 // m744s612m696s692m668s636m360 + "f36000d25" "m333s333m333s333m333s333m333s333m333s333m333s666" "m666s666m666s666m666s666m333s100000", irsend.outputStr()); @@ -61,6 +65,7 @@ TEST(TestSendLasertag, SendDataWithRepeat) { irsend.reset(); irsend.sendLasertag(0x1, kLasertagBits, 1); // Red 1, one repeat. EXPECT_EQ( + "f36000d25" "m333s333m333s333m333s333m333s333m333s333m333s333m333s333m333s333" "m333s333m333s333m333s333m333s666m333s100000" "m333s333m333s333m333s333m333s333m333s333m333s333m333s333m333s333" @@ -70,6 +75,7 @@ TEST(TestSendLasertag, SendDataWithRepeat) { irsend.reset(); irsend.sendLasertag(0x52, kLasertagBits, 2); // Green 2, two repeats. EXPECT_EQ( + "f36000d25" "m333s333m333s333m333s333m333s333m333s333m333s666m666s666m666s333" "m333s666m666s100333" "m333s333m333s333m333s333m333s333m333s333m333s666m666s666m666s333" @@ -86,7 +92,8 @@ TEST(TestSendLasertag, SmallestMessageSize) { irsend.reset(); irsend.sendLasertag(0x1555); // Alternating bit pattern will be the smallest. // i.e. 7 actual 'mark' pulses, which is a rawlen of 13. - EXPECT_EQ("m0s333m666s666m666s666m666s666m666s666m666s666m666s666m333s100000", + EXPECT_EQ("f36000d25" + "m0s333m666s666m666s666m666s666m666s666m666s666m666s666m333s100000", irsend.outputStr()); } diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Lego_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Lego_test.cpp new file mode 100644 index 000000000..4e859b170 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Lego_test.cpp @@ -0,0 +1,196 @@ +// Copyright 2019 David Conran + +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// General housekeeping +TEST(TestLego, Housekeeping) { + ASSERT_EQ("LEGOPF", typeToString(LEGOPF)); + ASSERT_FALSE(hasACState(LEGOPF)); // Uses uint64_t, not uint8_t*. +} + +// Tests for sendLego(). + +// Test sending typical data only. +TEST(TestSendLegoPf, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendLegoPf(0x1234); + EXPECT_EQ( + "f38000d50" + "m158s1026" + "m158s263m158s263m158s263m158s553m158s263m158s263m158s553m158s263" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s70472", irsend.outputStr()); + + irsend.reset(); + irsend.send(LEGOPF, 0x1234, kLegoPfBits); + EXPECT_EQ( + "f38000d50" + "m158s1026" + "m158s263m158s263m158s263m158s553m158s263m158s263m158s553m158s263" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s70472", irsend.outputStr()); +} + +// Test sending typical repeat data. +TEST(TestSendLegoPf, SendDataWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendLegoPf(0x1234, kLegoPfBits, 1); + EXPECT_EQ( + "f38000d50" + "m0s32000" + "m158s1026" + "m158s263m158s263m158s263m158s553m158s263m158s263m158s553m158s263" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s70472" + "m158s1026" + "m158s263m158s263m158s263m158s553m158s263m158s263m158s553m158s263" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s70472" + "m158s1026" + "m158s263m158s263m158s263m158s553m158s263m158s263m158s553m158s263" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s150472" + "m158s1026" + "m158s263m158s263m158s263m158s553m158s263m158s263m158s553m158s263" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s150472" + "m158s1026" + "m158s263m158s263m158s263m158s553m158s263m158s263m158s553m158s263" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s150472", irsend.outputStr()); + + irsend.reset(); + irsend.sendLegoPf(0x2345, kLegoPfBits, 2); + EXPECT_EQ( + "f38000d50" + "m0s16000" + "m158s1026" + "m158s263m158s263m158s553m158s263m158s263m158s263m158s553m158s553" + "m158s263m158s553m158s263m158s263m158s263m158s553m158s263m158s553" + "m158s70182" + "m158s1026" + "m158s263m158s263m158s553m158s263m158s263m158s263m158s553m158s553" + "m158s263m158s553m158s263m158s263m158s263m158s553m158s263m158s553" + "m158s70182" + "m158s1026" + "m158s263m158s263m158s553m158s263m158s263m158s263m158s553m158s553" + "m158s263m158s553m158s263m158s263m158s263m158s553m158s263m158s553" + "m158s182182" + "m158s1026" + "m158s263m158s263m158s553m158s263m158s263m158s263m158s553m158s553" + "m158s263m158s553m158s263m158s263m158s263m158s553m158s263m158s553" + "m158s182182" + "m158s1026" + "m158s263m158s263m158s553m158s263m158s263m158s263m158s553m158s553" + "m158s263m158s553m158s263m158s263m158s263m158s553m158s263m158s553" + "m158s182182", irsend.outputStr()); + + irsend.reset(); + irsend.sendLegoPf(0x3456, kLegoPfBits, 7); + EXPECT_EQ( + "f38000d50" + "m158s1026" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s263m158s553m158s263m158s553m158s263m158s553m158s553m158s263" + "m158s69892" + "m158s1026" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s263m158s553m158s263m158s553m158s263m158s553m158s553m158s263" + "m158s69892" + "m158s1026" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s263m158s553m158s263m158s553m158s263m158s553m158s553m158s263" + "m158s213892" + "m158s1026" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s263m158s553m158s263m158s553m158s263m158s553m158s553m158s263" + "m158s213892" + "m158s1026" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s263m158s553m158s263m158s553m158s263m158s553m158s553m158s263" + "m158s213892" + "m158s1026" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s263m158s553m158s263m158s553m158s263m158s553m158s553m158s263" + "m158s213892" + "m158s1026" + "m158s263m158s263m158s553m158s553m158s263m158s553m158s263m158s263" + "m158s263m158s553m158s263m158s553m158s263m158s553m158s553m158s263" + "m158s213892", irsend.outputStr()); +} + +// Tests for decodeLego(). + +// Decode normal "synthetic" messages. +TEST(TestDecodeLegoPf, SyntheticDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendLegoPf(0x000F); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LEGOPF, irsend.capture.decode_type); + EXPECT_EQ(kLegoPfBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ(0x000F, irsend.capture.value); + EXPECT_EQ(1, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + + irsend.reset(); + irsend.sendLegoPf(0x100E); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LEGOPF, irsend.capture.decode_type); + EXPECT_EQ(kLegoPfBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ(0x100E, irsend.capture.value); + EXPECT_EQ(2, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + + irsend.reset(); + irsend.sendLegoPf(0x221E); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LEGOPF, irsend.capture.decode_type); + EXPECT_EQ(kLegoPfBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ(0x221E, irsend.capture.value); + EXPECT_EQ(3, irsend.capture.address); + EXPECT_EQ(0x21, irsend.capture.command); + + // Test a bad LRC is not matched. + irsend.reset(); + irsend.sendLegoPf(0x001F); // LRC should be 0xE, not 0xF. + irsend.makeDecodeResult(); + irrecv.decode(&irsend.capture); + EXPECT_NE(LEGOPF, irsend.capture.decode_type); +} + +// Decode normal "synthetic" message with releats. +TEST(TestDecodeLegoPf, SyntheticDecodeWithRepeat) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + irsend.sendLegoPf(0x330F, kLegoPfBits, 1); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LEGOPF, irsend.capture.decode_type); + EXPECT_EQ(kLegoPfBits, irsend.capture.bits); + EXPECT_EQ(0x330F, irsend.capture.value); + EXPECT_EQ(4, irsend.capture.address); + EXPECT_EQ(0x30, irsend.capture.command); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Lutron_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Lutron_test.cpp similarity index 95% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Lutron_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Lutron_test.cpp index 6c99b9904..d682967ca 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Lutron_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Lutron_test.cpp @@ -11,17 +11,19 @@ TEST(TestSendLutron, SendDataOnly) { IRsendTest irsend(0); irsend.begin(); irsend.sendLutron(0); - EXPECT_EQ("m2288s230080", irsend.outputStr()); + EXPECT_EQ("f40000d40m2288s230080", irsend.outputStr()); irsend.sendLutron(0xAAAAAAAAA); // Longest possible sequence. (I think) EXPECT_EQ( + "f40000d40" "m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288" "m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288m2288s2288" "m2288s2288m2288s2288m2288s2288m2288s152288", irsend.outputStr()); irsend.sendLutron(0x7FFFFFFFF); - EXPECT_EQ("m82368s150000", irsend.outputStr()); + EXPECT_EQ("f40000d40m82368s150000", irsend.outputStr()); irsend.sendLutron(0x7F88BD120); EXPECT_EQ( + "f40000d40" "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" "s161440", irsend.outputStr()); @@ -34,12 +36,14 @@ TEST(TestSendLutron, SendWithRepeats) { // Send a command with 0 repeats. irsend.sendLutron(0x7F88BD120, kLutronBits, 0); EXPECT_EQ( + "f40000d40" "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" "s161440", irsend.outputStr()); // Send a command with 1 repeat. irsend.sendLutron(0x7F88BD120, kLutronBits, 1); EXPECT_EQ( + "f40000d40" "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" "s161440" "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" @@ -48,6 +52,7 @@ TEST(TestSendLutron, SendWithRepeats) { // Send a command with 3 repeats. irsend.sendLutron(0x7F88BD120, kLutronBits, 3); EXPECT_EQ( + "f40000d40" "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" "s161440" "m20592s6864m2288s6864m2288s2288m9152s2288m2288s6864m2288s4576m2288" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_MWM_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_MWM_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_MWM_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_MWM_test.cpp index 9ecd0eac1..2ca69ac83 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_MWM_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_MWM_test.cpp @@ -36,6 +36,7 @@ TEST(TestSendMWM, SendDataOnly) { */ irsend.sendMWM(test1, sizeof(test1), 0); EXPECT_EQ( + "f38000d25" "m834s834m417s417m834s834" "m417s417m834s834m1251s417" "m2085s417m1251s417" @@ -65,6 +66,7 @@ TEST(TestSendMWM, SendDataOnly) { }; irsend.sendMWM(test2, sizeof(test2), 0); EXPECT_EQ( + "f38000d25" "m417s417m834s834m834s834" "m834s834m834s417m834s417" "m834s834m834s834m417s417" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Magiquest_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Magiquest_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Magiquest_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Magiquest_test.cpp index e1c3da83d..bbc5f3366 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Magiquest_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Magiquest_test.cpp @@ -26,6 +26,7 @@ TEST(TestSendMagiQuest, SendDataOnly) { irsend.reset(); irsend.sendMagiQuest(0x0); EXPECT_EQ( + "f36000d50" "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" @@ -37,6 +38,7 @@ TEST(TestSendMagiQuest, SendDataOnly) { irsend.reset(); irsend.sendMagiQuest(0x123456789ABC); EXPECT_EQ( + "f36000d50" "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" "m280s850m280s850m280s850m580s600m280s850m280s850m580s600m280s850" "m280s850m280s850m580s600m580s600m280s850m580s600m280s850m280s850" @@ -55,6 +57,7 @@ TEST(TestSendMagiQuest, SendWithRepeats) { irsend.reset(); irsend.sendMagiQuest(0x12345678ABCD, kMagiquestBits, 2); // two repeats. EXPECT_EQ( + "f36000d50" "m280s850m280s850m280s850m280s850m280s850m280s850m280s850m280s850" "m280s850m280s850m280s850m580s600m280s850m280s850m580s600m280s850" "m280s850m280s850m580s600m580s600m280s850m580s600m280s850m280s850" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Midea_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Midea_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Midea_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Midea_test.cpp index 5d5f5e932..ced3ea10c 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Midea_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Midea_test.cpp @@ -15,6 +15,7 @@ TEST(TestSendMidea, SendDataOnly) { irsend.reset(); irsend.sendMidea(0x0); EXPECT_EQ( + "f38000d50" "m4480s4480" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" @@ -36,6 +37,7 @@ TEST(TestSendMidea, SendDataOnly) { irsend.reset(); irsend.sendMidea(0x55AA55AA55AA); EXPECT_EQ( + "f38000d50" "m4480s4480" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" @@ -57,6 +59,7 @@ TEST(TestSendMidea, SendDataOnly) { irsend.reset(); irsend.sendMidea(0xFFFFFFFFFFFF); EXPECT_EQ( + "f38000d50" "m4480s4480" "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" @@ -84,6 +87,7 @@ TEST(TestSendMidea, SendWithRepeats) { irsend.reset(); irsend.sendMidea(0x55AA55AA55AA, kMideaBits, 1); // 1 repeat. EXPECT_EQ( + "f38000d50" "m4480s4480" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" @@ -119,6 +123,7 @@ TEST(TestSendMidea, SendWithRepeats) { irsend.outputStr()); irsend.sendMidea(0x55AA55AA55AA, kMideaBits, 2); // 2 repeats. EXPECT_EQ( + "f38000d50" "m4480s4480" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" @@ -178,6 +183,7 @@ TEST(TestSendMidea, SendUnusualSize) { irsend.reset(); irsend.sendMidea(0x0, 8); EXPECT_EQ( + "f38000d50" "m4480s4480" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s5600" @@ -189,6 +195,7 @@ TEST(TestSendMidea, SendUnusualSize) { irsend.reset(); irsend.sendMidea(0x1234567890ABCDEF, 64); EXPECT_EQ( + "f38000d50" "m4480s4480" "m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680m560s560" "m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_MitsubishiHeavy_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_MitsubishiHeavy_test.cpp new file mode 100644 index 000000000..340a04078 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/test/ir_MitsubishiHeavy_test.cpp @@ -0,0 +1,851 @@ +// Copyright 2019 David Conran + +#include "ir_MitsubishiHeavy.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRremoteESP8266.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// General housekeeping +TEST(TestMitsubishiHeavy, Housekeeping) { + ASSERT_EQ("MITSUBISHI_HEAVY_88", typeToString(MITSUBISHI_HEAVY_88)); + ASSERT_TRUE(hasACState(MITSUBISHI_HEAVY_88)); + ASSERT_EQ("MITSUBISHI_HEAVY_152", typeToString(MITSUBISHI_HEAVY_152)); + ASSERT_TRUE(hasACState(MITSUBISHI_HEAVY_152)); +} + +// Tests for IRMitsubishiHeavy152Ac class. + +TEST(TestMitsubishiHeavy152AcClass, Power) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + + ac.on(); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_FALSE(ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestMitsubishiHeavy152AcClass, Temperature) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + + ac.setMode(kMitsubishiHeavyCool); + + ac.setTemp(0); + EXPECT_EQ(kMitsubishiHeavyMinTemp, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kMitsubishiHeavyMaxTemp, ac.getTemp()); + + ac.setTemp(kMitsubishiHeavyMinTemp); + EXPECT_EQ(kMitsubishiHeavyMinTemp, ac.getTemp()); + + ac.setTemp(kMitsubishiHeavyMaxTemp); + EXPECT_EQ(kMitsubishiHeavyMaxTemp, ac.getTemp()); + + ac.setTemp(kMitsubishiHeavyMinTemp - 1); + EXPECT_EQ(kMitsubishiHeavyMinTemp, ac.getTemp()); + + ac.setTemp(kMitsubishiHeavyMaxTemp + 1); + EXPECT_EQ(kMitsubishiHeavyMaxTemp, ac.getTemp()); + + ac.setTemp(19); + EXPECT_EQ(19, ac.getTemp()); + + ac.setTemp(21); + EXPECT_EQ(21, ac.getTemp()); + + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + + ac.setTemp(29); + EXPECT_EQ(29, ac.getTemp()); +} + +TEST(TestMitsubishiHeavy152AcClass, OperatingMode) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + + ac.setMode(kMitsubishiHeavyAuto); + EXPECT_EQ(kMitsubishiHeavyAuto, ac.getMode()); + + ac.setMode(kMitsubishiHeavyCool); + EXPECT_EQ(kMitsubishiHeavyCool, ac.getMode()); + + ac.setMode(kMitsubishiHeavyHeat); + EXPECT_EQ(kMitsubishiHeavyHeat, ac.getMode()); + + ac.setMode(kMitsubishiHeavyDry); + EXPECT_EQ(kMitsubishiHeavyDry, ac.getMode()); + + ac.setMode(kMitsubishiHeavyFan); + EXPECT_EQ(kMitsubishiHeavyFan, ac.getMode()); + + ac.setMode(kMitsubishiHeavyHeat + 1); + EXPECT_EQ(kMitsubishiHeavyAuto, ac.getMode()); + + ac.setMode(255); + EXPECT_EQ(kMitsubishiHeavyAuto, ac.getMode()); +} + + +TEST(TestMitsubishiHeavy152AcClass, Filter) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + + ac.setFilter(true); + EXPECT_TRUE(ac.getFilter()); + + ac.setFilter(false); + EXPECT_FALSE(ac.getFilter()); + + ac.setFilter(true); + EXPECT_TRUE(ac.getFilter()); +} + +TEST(TestMitsubishiHeavy152AcClass, Turbo) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + + ac.setTurbo(false); + EXPECT_FALSE(ac.getTurbo()); + + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); +} + +TEST(TestMitsubishiHeavy152AcClass, Econo) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); + + ac.setEcono(false); + EXPECT_FALSE(ac.getEcono()); + + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); +} + +TEST(TestMitsubishiHeavy152AcClass, 3D) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + + ac.set3D(true); + EXPECT_TRUE(ac.get3D()); + + ac.set3D(false); + EXPECT_FALSE(ac.get3D()); + + ac.set3D(true); + EXPECT_TRUE(ac.get3D()); +} + +TEST(TestMitsubishiHeavy152AcClass, Night) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + + ac.setNight(true); + EXPECT_TRUE(ac.getNight()); + + ac.setNight(false); + EXPECT_FALSE(ac.getNight()); + + ac.setNight(true); + EXPECT_TRUE(ac.getNight()); +} + +TEST(TestMitsubishiHeavy152AcClass, Clean) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + + ac.setClean(true); + EXPECT_TRUE(ac.getClean()); + + ac.setClean(false); + EXPECT_FALSE(ac.getClean()); + + ac.setClean(true); + EXPECT_TRUE(ac.getClean()); +} + +TEST(TestMitsubishiHeavy152AcClass, FanSpeed) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + + ac.setFan(kMitsubishiHeavy152FanLow); + EXPECT_EQ(kMitsubishiHeavy152FanLow, ac.getFan()); + + ac.setFan(kMitsubishiHeavy152FanAuto); + EXPECT_EQ(kMitsubishiHeavy152FanAuto, ac.getFan()); + + + ac.setFan(255); + EXPECT_EQ(kMitsubishiHeavy152FanAuto, ac.getFan()); + + ac.setFan(kMitsubishiHeavy152FanMax); + EXPECT_EQ(kMitsubishiHeavy152FanMax, ac.getFan()); + + ac.setFan(kMitsubishiHeavy152FanMax + 1); + EXPECT_EQ(kMitsubishiHeavy152FanAuto, ac.getFan()); + + ac.setFan(kMitsubishiHeavy152FanMax - 1); + EXPECT_EQ(kMitsubishiHeavy152FanMax - 1, ac.getFan()); + + ac.setFan(kMitsubishiHeavy152FanLow + 1); + EXPECT_EQ(kMitsubishiHeavy152FanLow + 1, ac.getFan()); + + ac.setFan(kMitsubishiHeavy152FanEcono); + EXPECT_EQ(kMitsubishiHeavy152FanEcono, ac.getFan()); + + ac.setFan(kMitsubishiHeavy152FanTurbo); + EXPECT_EQ(kMitsubishiHeavy152FanTurbo, ac.getFan()); +} + +TEST(TestMitsubishiHeavy152AcClass, VerticalSwing) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + ac.setSwingVertical(kMitsubishiHeavy152SwingVAuto); + EXPECT_EQ(kMitsubishiHeavy152SwingVAuto, ac.getSwingVertical()); + + ac.setSwingVertical(kMitsubishiHeavy152SwingVHighest); + EXPECT_EQ(kMitsubishiHeavy152SwingVHighest, ac.getSwingVertical()); + + ac.setSwingVertical(kMitsubishiHeavy152SwingVHighest + 1); + EXPECT_EQ(kMitsubishiHeavy152SwingVHighest + 1, ac.getSwingVertical()); + + ac.setSwingVertical(kMitsubishiHeavy152SwingVOff); + EXPECT_EQ(kMitsubishiHeavy152SwingVOff, ac.getSwingVertical()); + + ac.setSwingVertical(kMitsubishiHeavy152SwingVOff + 1); + EXPECT_EQ(kMitsubishiHeavy152SwingVOff, ac.getSwingVertical()); + + // Out of bounds. + ac.setSwingVertical(255); + EXPECT_EQ(kMitsubishiHeavy152SwingVOff, ac.getSwingVertical()); +} + +TEST(TestMitsubishiHeavy152AcClass, HorizontalSwing) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + ac.setSwingHorizontal(kMitsubishiHeavy152SwingHAuto); + EXPECT_EQ(kMitsubishiHeavy152SwingHAuto, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kMitsubishiHeavy152SwingHLeftMax); + EXPECT_EQ(kMitsubishiHeavy152SwingHLeftMax, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kMitsubishiHeavy152SwingHLeftMax + 1); + EXPECT_EQ(kMitsubishiHeavy152SwingHLeftMax + 1, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kMitsubishiHeavy152SwingHRightMax); + EXPECT_EQ(kMitsubishiHeavy152SwingHRightMax, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kMitsubishiHeavy152SwingHRightMax - 1); + EXPECT_EQ(kMitsubishiHeavy152SwingHRightMax - 1, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kMitsubishiHeavy152SwingHOff); + EXPECT_EQ(kMitsubishiHeavy152SwingHOff, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kMitsubishiHeavy152SwingHOff + 1); + EXPECT_EQ(kMitsubishiHeavy152SwingHOff, ac.getSwingHorizontal()); + + // Out of bounds. + ac.setSwingHorizontal(255); + EXPECT_EQ(kMitsubishiHeavy152SwingHOff, ac.getSwingHorizontal()); +} + +TEST(TestMitsubishiHeavy152AcClass, Checksums) { + IRMitsubishiHeavy152Ac ac(0); + ac.begin(); + + EXPECT_TRUE(ac.validChecksum(ac.getRaw())); + + uint8_t expected[kMitsubishiHeavy152StateLength] = { + 0xAD, 0x51, 0x3C, 0xE5, 0x1A, 0x0C, 0xF3, 0x07, + 0xF8, 0x04, 0xFB, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x80, 0x7F}; + EXPECT_TRUE(IRMitsubishiHeavy152Ac::validChecksum(expected)); + + // Screw up the "checksum" to test it fails. + expected[kMitsubishiHeavy152StateLength - 1] = 0x55; + EXPECT_FALSE(IRMitsubishiHeavy152Ac::validChecksum(expected)); + // getting the after getRaw() should repair it. + ac.setRaw(expected); + EXPECT_TRUE(ac.validChecksum(ac.getRaw())); + EXPECT_TRUE(IRMitsubishiHeavy152Ac::validChecksum(ac.getRaw())); +} + +TEST(TestMitsubishiHeavy152AcClass, HumanReadable) { + IRMitsubishiHeavy152Ac ac(0); + + EXPECT_EQ( + "Power: Off, Mode: 0 (Auto), Temp: 17C, Fan: 0 (Auto), " + "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, " + "Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", + ac.toString()); + ac.on(); + ac.setMode(kMitsubishiHeavyCool); + ac.setTemp(kMitsubishiHeavyMinTemp); + ac.setFan(kMitsubishiHeavy152FanMax); + ac.setFilter(true); + ac.setNight(true); + ac.setTurbo(false); + ac.setSilent(true); + ac.setEcono(false); + ac.set3D(true); + ac.setSwingVertical(kMitsubishiHeavy152SwingVAuto); + ac.setSwingHorizontal(kMitsubishiHeavy152SwingHAuto); + EXPECT_EQ( + "Power: On, Mode: 1 (Cool), Temp: 17C, Fan: 4 (Max), " + "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: On, Turbo: Off, " + "Econo: Off, Night: On, Filter: On, 3D: On, Clean: Off", + ac.toString()); + + ac.setMode(kMitsubishiHeavyHeat); + ac.setTemp(kMitsubishiHeavyMaxTemp); + ac.setFilter(true); + ac.setNight(false); + ac.setTurbo(true); + ac.setEcono(false); + ac.setSilent(false); + ac.set3D(false); + ac.setSwingVertical(kMitsubishiHeavy152SwingVLowest); + ac.setSwingHorizontal(kMitsubishiHeavy152SwingHLeftMax); + + EXPECT_EQ( + "Power: On, Mode: 4 (Heat), Temp: 31C, Fan: 8 (Turbo), " + "Swing (V): 5 (Lowest), Swing (H): 1 (Max Left), Silent: Off, Turbo: On, " + "Econo: Off, Night: Off, Filter: On, 3D: Off, Clean: Off", + ac.toString()); + + ac.setClean(true); + ac.setEcono(true); + ac.setMode(kMitsubishiHeavyAuto); + ac.setSwingVertical(kMitsubishiHeavy152SwingVOff); + + EXPECT_EQ( + "Power: On, Mode: 0 (Auto), Temp: 31C, Fan: 6 (Econo), " + "Swing (V): 6 (Off), Swing (H): 1 (Max Left), Silent: Off, " + "Turbo: Off, Econo: On, Night: Off, Filter: On, 3D: Off, Clean: On", + ac.toString()); + + ac.setClean(false); + ac.setTemp(25); + ac.setEcono(false); + ac.setMode(kMitsubishiHeavyDry); + ac.setSwingHorizontal(kMitsubishiHeavy152SwingHLeftRight); + EXPECT_EQ( + "Power: On, Mode: 2 (Dry), Temp: 25C, Fan: 0 (Auto), " + "Swing (V): 6 (Off), Swing (H): 7 (Left Right), Silent: Off, " + "Turbo: Off, Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", + ac.toString()); +} + +TEST(TestMitsubishiHeavy152AcClass, ReconstructKnownExample) { + IRMitsubishiHeavy152Ac ac(0); + + EXPECT_EQ( + "Power: Off, Mode: 0 (Auto), Temp: 17C, Fan: 0 (Auto), " + "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, " + "Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", + ac.toString()); + ac.on(); + ac.setMode(kMitsubishiHeavyHeat); + ac.setTemp(24); + ac.setFan(kMitsubishiHeavy152FanMax); + ac.setFilter(true); + ac.setNight(false); + ac.setTurbo(false); + ac.setSilent(false); + ac.setEcono(false); + ac.set3D(false); + ac.setClean(false); + ac.setSwingVertical(kMitsubishiHeavy152SwingVAuto); + ac.setSwingHorizontal(kMitsubishiHeavy152SwingHAuto); + EXPECT_EQ( + "Power: On, Mode: 4 (Heat), Temp: 24C, Fan: 4 (Max), " + "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, " + "Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", + ac.toString()); + + uint8_t expected[kMitsubishiHeavy152StateLength] = { + 0xAD, 0x51, 0x3C, 0xE5, 0x1A, 0x0C, 0xF3, 0x07, + 0xF8, 0x04, 0xFB, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x80, 0x7F}; + EXPECT_STATE_EQ(expected, ac.getRaw(), kMitsubishiHeavy152Bits); +} + +// Tests for IRMitsubishiHeavy88Ac class. + +TEST(TestMitsubishiHeavy88AcClass, Power) { + IRMitsubishiHeavy88Ac ac(0); + ac.begin(); + + ac.on(); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_FALSE(ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_FALSE(ac.getPower()); +} + +TEST(TestMitsubishiHeavy88AcClass, Temperature) { + IRMitsubishiHeavy88Ac ac(0); + ac.begin(); + + ac.setMode(kMitsubishiHeavyCool); + + ac.setTemp(0); + EXPECT_EQ(kMitsubishiHeavyMinTemp, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kMitsubishiHeavyMaxTemp, ac.getTemp()); + + ac.setTemp(kMitsubishiHeavyMinTemp); + EXPECT_EQ(kMitsubishiHeavyMinTemp, ac.getTemp()); + + ac.setTemp(kMitsubishiHeavyMaxTemp); + EXPECT_EQ(kMitsubishiHeavyMaxTemp, ac.getTemp()); + + ac.setTemp(kMitsubishiHeavyMinTemp - 1); + EXPECT_EQ(kMitsubishiHeavyMinTemp, ac.getTemp()); + + ac.setTemp(kMitsubishiHeavyMaxTemp + 1); + EXPECT_EQ(kMitsubishiHeavyMaxTemp, ac.getTemp()); + + ac.setTemp(19); + EXPECT_EQ(19, ac.getTemp()); + + ac.setTemp(21); + EXPECT_EQ(21, ac.getTemp()); + + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + + ac.setTemp(29); + EXPECT_EQ(29, ac.getTemp()); +} + +TEST(TestMitsubishiHeavy88AcClass, OperatingMode) { + IRMitsubishiHeavy88Ac ac(0); + ac.begin(); + + ac.setMode(kMitsubishiHeavyAuto); + EXPECT_EQ(kMitsubishiHeavyAuto, ac.getMode()); + + ac.setMode(kMitsubishiHeavyCool); + EXPECT_EQ(kMitsubishiHeavyCool, ac.getMode()); + + ac.setMode(kMitsubishiHeavyHeat); + EXPECT_EQ(kMitsubishiHeavyHeat, ac.getMode()); + + ac.setMode(kMitsubishiHeavyDry); + EXPECT_EQ(kMitsubishiHeavyDry, ac.getMode()); + + ac.setMode(kMitsubishiHeavyFan); + EXPECT_EQ(kMitsubishiHeavyFan, ac.getMode()); + + ac.setMode(kMitsubishiHeavyHeat + 1); + EXPECT_EQ(kMitsubishiHeavyAuto, ac.getMode()); + + ac.setMode(255); + EXPECT_EQ(kMitsubishiHeavyAuto, ac.getMode()); +} + +TEST(TestMitsubishiHeavy88AcClass, Turbo) { + IRMitsubishiHeavy88Ac ac(0); + ac.begin(); + + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + + ac.setTurbo(false); + EXPECT_FALSE(ac.getTurbo()); + + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); +} + +TEST(TestMitsubishiHeavy88AcClass, Econo) { + IRMitsubishiHeavy88Ac ac(0); + ac.begin(); + + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); + + ac.setEcono(false); + EXPECT_FALSE(ac.getEcono()); + + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); +} + +TEST(TestMitsubishiHeavy88AcClass, 3D) { + IRMitsubishiHeavy88Ac ac(0); + ac.begin(); + + ac.set3D(true); + EXPECT_TRUE(ac.get3D()); + + ac.set3D(false); + EXPECT_FALSE(ac.get3D()); + + ac.set3D(true); + EXPECT_TRUE(ac.get3D()); +} + +TEST(TestMitsubishiHeavy88AcClass, Clean) { + IRMitsubishiHeavy88Ac ac(0); + ac.begin(); + + ac.setClean(true); + EXPECT_TRUE(ac.getClean()); + + ac.setClean(false); + EXPECT_FALSE(ac.getClean()); + + ac.setClean(true); + EXPECT_TRUE(ac.getClean()); +} + +TEST(TestMitsubishiHeavy88AcClass, FanSpeed) { + IRMitsubishiHeavy88Ac ac(0); + ac.begin(); + + ac.setFan(kMitsubishiHeavy88FanLow); + EXPECT_EQ(kMitsubishiHeavy88FanLow, ac.getFan()); + + ac.setFan(kMitsubishiHeavy88FanAuto); + EXPECT_EQ(kMitsubishiHeavy88FanAuto, ac.getFan()); + + + ac.setFan(255); + EXPECT_EQ(kMitsubishiHeavy88FanAuto, ac.getFan()); + + ac.setFan(kMitsubishiHeavy88FanHigh); + EXPECT_EQ(kMitsubishiHeavy88FanHigh, ac.getFan()); + + ac.setFan(kMitsubishiHeavy88FanHigh + 1); + EXPECT_EQ(kMitsubishiHeavy88FanAuto, ac.getFan()); + + ac.setFan(kMitsubishiHeavy88FanHigh - 1); + EXPECT_EQ(kMitsubishiHeavy88FanHigh - 1, ac.getFan()); + + ac.setFan(kMitsubishiHeavy88FanLow + 1); + EXPECT_EQ(kMitsubishiHeavy88FanLow + 1, ac.getFan()); + + ac.setFan(kMitsubishiHeavy88FanEcono); + EXPECT_EQ(kMitsubishiHeavy88FanEcono, ac.getFan()); + + ac.setFan(kMitsubishiHeavy88FanTurbo); + EXPECT_EQ(kMitsubishiHeavy88FanTurbo, ac.getFan()); +} + +TEST(TestMitsubishiHeavy88AcClass, VerticalSwing) { + IRMitsubishiHeavy88Ac ac(0); + ac.begin(); + ac.setSwingVertical(kMitsubishiHeavy88SwingVAuto); + EXPECT_EQ(kMitsubishiHeavy88SwingVAuto, ac.getSwingVertical()); + + ac.setSwingVertical(kMitsubishiHeavy88SwingVHighest); + EXPECT_EQ(kMitsubishiHeavy88SwingVHighest, ac.getSwingVertical()); + + ac.setSwingVertical(kMitsubishiHeavy88SwingVOff); + EXPECT_EQ(kMitsubishiHeavy88SwingVOff, ac.getSwingVertical()); + + ac.setSwingVertical(kMitsubishiHeavy88SwingVHighest + 1); + EXPECT_EQ(kMitsubishiHeavy88SwingVOff, ac.getSwingVertical()); + + ac.setSwingVertical(kMitsubishiHeavy88SwingVOff + 1); + EXPECT_EQ(kMitsubishiHeavy88SwingVOff, ac.getSwingVertical()); + + // Out of bounds. + ac.setSwingVertical(255); + EXPECT_EQ(kMitsubishiHeavy88SwingVOff, ac.getSwingVertical()); +} + +TEST(TestMitsubishiHeavy88AcClass, HorizontalSwing) { + IRMitsubishiHeavy88Ac ac(0); + ac.begin(); + ac.setSwingHorizontal(kMitsubishiHeavy88SwingHAuto); + EXPECT_EQ(kMitsubishiHeavy88SwingHAuto, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kMitsubishiHeavy88SwingHLeftMax); + EXPECT_EQ(kMitsubishiHeavy88SwingHLeftMax, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kMitsubishiHeavy88SwingHLeftMax + 1); + EXPECT_EQ(kMitsubishiHeavy88SwingHOff, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kMitsubishiHeavy88SwingHRightMax); + EXPECT_EQ(kMitsubishiHeavy88SwingHRightMax, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kMitsubishiHeavy88SwingHRightMax - 1); + EXPECT_EQ(kMitsubishiHeavy88SwingHOff, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kMitsubishiHeavy88SwingHOff); + EXPECT_EQ(kMitsubishiHeavy88SwingHOff, ac.getSwingHorizontal()); + + ac.setSwingHorizontal(kMitsubishiHeavy88SwingHOff + 1); + EXPECT_EQ(kMitsubishiHeavy88SwingHOff, ac.getSwingHorizontal()); + + // Out of bounds. + ac.setSwingHorizontal(255); + EXPECT_EQ(kMitsubishiHeavy88SwingHOff, ac.getSwingHorizontal()); +} + +TEST(TestMitsubishiHeavy88AcClass, Checksums) { + IRMitsubishiHeavy88Ac ac(0); + ac.begin(); + + EXPECT_TRUE(ac.validChecksum(ac.getRaw())); + + uint8_t expected[kMitsubishiHeavy88StateLength] = { + 0xAD, 0x51, 0x3C, 0xD9, 0x26, 0x48, 0xB7, 0x00, 0xFF, 0x8A, 0x75}; + EXPECT_TRUE(IRMitsubishiHeavy88Ac::validChecksum(expected)); + + // Screw up the "checksum" to test it fails. + expected[kMitsubishiHeavy88StateLength - 1] = 0x55; + EXPECT_FALSE(IRMitsubishiHeavy88Ac::validChecksum(expected)); + // getting the after getRaw() should repair it. + ac.setRaw(expected); + EXPECT_TRUE(ac.validChecksum(ac.getRaw())); + EXPECT_TRUE(IRMitsubishiHeavy88Ac::validChecksum(ac.getRaw())); +} + +TEST(TestMitsubishiHeavy88AcClass, HumanReadable) { + IRMitsubishiHeavy88Ac ac(0); + + EXPECT_EQ( + "Power: Off, Mode: 0 (Auto), Temp: 17C, Fan: 0 (Auto), " + "Swing (V): 0 (Off), Swing (H): 0 (Off), " + "Turbo: Off, Econo: Off, 3D: Off, Clean: Off", + ac.toString()); + ac.on(); + ac.setMode(kMitsubishiHeavyCool); + ac.setTemp(kMitsubishiHeavyMinTemp); + ac.setFan(kMitsubishiHeavy88FanHigh); + ac.setTurbo(false); + ac.setEcono(false); + ac.set3D(true); + ac.setSwingVertical(kMitsubishiHeavy88SwingVAuto); + EXPECT_EQ( + "Power: On, Mode: 1 (Cool), Temp: 17C, Fan: 4 (High), " + "Swing (V): 16 (Auto), Swing (H): 200 (3D), " + "Turbo: Off, Econo: Off, 3D: On, Clean: Off", + ac.toString()); + + ac.setMode(kMitsubishiHeavyHeat); + ac.setTemp(kMitsubishiHeavyMaxTemp); + ac.setTurbo(true); + ac.setEcono(false); + ac.set3D(false); + ac.setSwingVertical(kMitsubishiHeavy88SwingVLowest); + ac.setSwingHorizontal(kMitsubishiHeavy88SwingHLeftMax); + + EXPECT_EQ( + "Power: On, Mode: 4 (Heat), Temp: 31C, Fan: 6 (Turbo), " + "Swing (V): 26 (Lowest), Swing (H): 4 (Max Left), Turbo: On, Econo: Off, " + "3D: Off, Clean: Off", + ac.toString()); + + ac.setClean(true); + ac.setEcono(true); + ac.setMode(kMitsubishiHeavyAuto); + ac.setSwingVertical(kMitsubishiHeavy88SwingVOff); + + EXPECT_EQ( + "Power: On, Mode: 0 (Auto), Temp: 31C, Fan: 7 (Econo), " + "Swing (V): 0 (Off), Swing (H): 4 (Max Left), Turbo: Off, Econo: On, " + "3D: Off, Clean: On", + ac.toString()); + + ac.setClean(false); + ac.setTemp(25); + ac.setEcono(false); + ac.setMode(kMitsubishiHeavyDry); + ac.setSwingHorizontal(kMitsubishiHeavy88SwingHLeftRight); + EXPECT_EQ( + "Power: On, Mode: 2 (Dry), Temp: 25C, Fan: 0 (Auto), " + "Swing (V): 0 (Off), Swing (H): 72 (Left Right), Turbo: Off, Econo: Off, " + "3D: Off, Clean: Off", + ac.toString()); +} + +// Tests for decodeMitsubishiHeavy(). + +// Decode a real MitsubishiHeavy 152Bit message. +TEST(TestDecodeMitsubishiHeavy, ZmsRealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRMitsubishiHeavy152Ac ac(0); + irsend.begin(); + + uint8_t expected[kMitsubishiHeavy152StateLength] = { + 0xAD, 0x51, 0x3C, 0xE5, 0x1A, 0x0C, 0xF3, 0x07, + 0xF8, 0x04, 0xFB, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x80, 0x7F}; + + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/660#issuecomment-480571466 + uint16_t rawData[307] = { + 3136, 1638, 364, 428, 366, 1224, 362, 432, 364, 430, 364, 1226, 362, 432, + 364, 1224, 366, 428, 366, 430, 366, 1224, 362, 1228, 362, 1228, 362, 432, + 364, 1224, 364, 432, 364, 1226, 364, 1224, 366, 1226, 364, 428, 364, 430, + 364, 430, 364, 432, 366, 1226, 364, 1224, 364, 430, 364, 1226, 364, 428, + 364, 1224, 368, 1224, 364, 428, 364, 430, 366, 430, 364, 1158, 430, 432, + 366, 1222, 366, 430, 366, 430, 364, 1226, 364, 1224, 364, 1224, 364, 1224, + 366, 1224, 364, 430, 364, 430, 364, 1228, 362, 1226, 364, 1226, 366, 1222, + 366, 430, 364, 430, 364, 1224, 366, 1224, 364, 430, 364, 430, 364, 432, + 364, 430, 364, 428, 364, 430, 364, 430, 366, 1226, 362, 1154, 434, 1228, + 364, 1226, 362, 1226, 364, 1226, 364, 1228, 362, 1226, 362, 432, 364, 430, + 364, 428, 364, 430, 364, 430, 364, 1228, 362, 1228, 362, 432, 364, 1224, + 368, 1224, 364, 1226, 362, 1226, 364, 1226, 366, 428, 366, 430, 364, 1224, + 364, 430, 366, 430, 366, 430, 364, 430, 364, 430, 364, 1226, 364, 1226, + 366, 1224, 366, 1224, 366, 1226, 364, 1224, 366, 1224, 366, 1224, 366, + 428, 364, 430, 366, 428, 364, 430, 364, 430, 366, 428, 364, 430, 364, 432, + 364, 1226, 364, 1226, 364, 1226, 364, 1228, 364, 1222, 370, 1222, 362, + 1228, 362, 1226, 362, 430, 364, 430, 364, 430, 364, 432, 364, 428, 364, + 432, 364, 428, 364, 430, 366, 1226, 362, 1224, 364, 1226, 364, 1226, 364, + 1226, 362, 1226, 366, 1224, 366, 1224, 364, 430, 364, 432, 364, 428, 364, + 432, 364, 428, 364, 430, 366, 430, 364, 430, 364, 1226, 362, 1226, 364, + 1224, 366, 1226, 362, 1228, 364, 1224, 366, 1224, 364, 430, 364, 432, 364, + 428, 364, 430, 364, 430, 364, 430, 366, 430, 364, 430, 338, 1252, 362 + }; // UNKNOWN 5138D49D + + irsend.reset(); + irsend.sendRaw(rawData, 307, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(MITSUBISHI_HEAVY_152, irsend.capture.decode_type); + ASSERT_EQ(kMitsubishiHeavy152Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 4 (Heat), Temp: 24C, Fan: 4 (Max), " + "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, " + "Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", + ac.toString()); +} + +// Decode a Synthetic MitsubishiHeavy 152Bit message. +TEST(TestDecodeMitsubishiHeavy, ZmsSyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRMitsubishiHeavy152Ac ac(0); + irsend.begin(); + + uint8_t expected[kMitsubishiHeavy152StateLength] = { + 0xAD, 0x51, 0x3C, 0xE5, 0x1A, 0x0C, 0xF3, 0x07, + 0xF8, 0x04, 0xFB, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x80, 0x7F}; + + irsend.reset(); + irsend.sendMitsubishiHeavy152(expected); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(MITSUBISHI_HEAVY_152, irsend.capture.decode_type); + ASSERT_EQ(kMitsubishiHeavy152Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 4 (Heat), Temp: 24C, Fan: 4 (Max), " + "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, " + "Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", + ac.toString()); +} + +// Decode a real MitsubishiHeavy 152Bit message. +TEST(TestDecodeMitsubishiHeavy, ZmsRealExample2) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRMitsubishiHeavy152Ac ac(0); + irsend.begin(); + + uint8_t expected[kMitsubishiHeavy152StateLength] = { + 0xAD, 0x51, 0x3C, 0xE5, 0x1A, 0x04, 0xFB, 0x07, + 0xF8, 0x04, 0xFB, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x80, 0x7F}; + + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/660#issuecomment-480571466 + uint16_t rawData[307] = { + 3196, 1580, 398, 390, 404, 1190, 400, 390, 402, 390, 402, 1192, 402, 388, + 402, 1192, 400, 390, 402, 392, 402, 1192, 400, 1188, 400, 1188, 400, 390, + 404, 1192, 398, 392, 400, 1192, 402, 1188, 400, 1190, 402, 388, 402, 392, + 404, 392, 402, 392, 404, 1188, 400, 1190, 398, 392, 404, 1188, 398, 392, + 402, 1192, 398, 1190, 400, 390, 404, 390, 402, 392, 404, 1188, 398, 392, + 404, 1190, 400, 392, 400, 394, 402, 1192, 398, 1190, 398, 1192, 398, 1190, + 400, 1190, 398, 392, 402, 1192, 398, 1190, 398, 1190, 398, 1192, 396, + 1192, 398, 396, 400, 394, 398, 1194, 396, 394, 400, 394, 398, 396, 398, + 396, 400, 402, 390, 394, 402, 392, 398, 396, 398, 1194, 396, 1194, 398, + 1192, 398, 1192, 396, 1194, 396, 1192, 396, 1196, 398, 1190, 398, 392, + 402, 392, 402, 394, 398, 394, 400, 394, 400, 1192, 398, 1192, 400, 390, + 402, 1190, 398, 1190, 398, 1192, 402, 1188, 398, 1190, 400, 390, 402, 392, + 402, 1190, 400, 390, 404, 390, 402, 394, 402, 392, 402, 390, 404, 1190, + 400, 1188, 400, 1190, 400, 1190, 402, 1188, 402, 1188, 400, 1188, 402, + 1190, 400, 388, 402, 394, 404, 392, 404, 388, 404, 390, 404, 392, 402, + 394, 402, 390, 402, 1190, 402, 1186, 402, 1190, 400, 1190, 398, 1190, 402, + 1186, 402, 1190, 400, 1188, 400, 390, 404, 392, 404, 390, 402, 392, 402, + 392, 400, 394, 402, 392, 402, 394, 400, 1192, 400, 1190, 400, 1188, 400, + 1192, 400, 1186, 402, 1190, 400, 1190, 400, 1188, 402, 388, 402, 390, 404, + 392, 402, 392, 402, 392, 402, 392, 404, 392, 402, 392, 404, 1190, 400, + 1190, 398, 1190, 400, 1190, 400, 1190, 400, 1188, 400, 1188, 400, 392, + 402, 392, 404, 390, 402, 392, 402, 392, 402, 392, 402, 390, 402, 392, 402, + 1192, 398}; // UNKNOWN A650F2C1 + + irsend.reset(); + irsend.sendRaw(rawData, 307, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(MITSUBISHI_HEAVY_152, irsend.capture.decode_type); + ASSERT_EQ(kMitsubishiHeavy152Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: Off, Mode: 4 (Heat), Temp: 24C, Fan: 4 (Max), " + "Swing (V): 0 (Auto), Swing (H): 0 (Auto), Silent: Off, Turbo: Off, " + "Econo: Off, Night: Off, Filter: Off, 3D: Off, Clean: Off", + ac.toString()); +} + +// Decode a Synthetic MitsubishiHeavy 88 Bit message. +TEST(TestDecodeMitsubishiHeavy, ZjsSyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRMitsubishiHeavy88Ac ac(0); + irsend.begin(); + + uint8_t expected[kMitsubishiHeavy88StateLength] = { + 0xAD, 0x51, 0x3C, 0xD9, 0x26, 0x48, 0xB7, 0x00, 0xFF, 0x8A, 0x75}; + + irsend.reset(); + irsend.sendMitsubishiHeavy88(expected); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(MITSUBISHI_HEAVY_88, irsend.capture.decode_type); + ASSERT_EQ(kMitsubishiHeavy88Bits, irsend.capture.bits); + EXPECT_STATE_EQ(expected, irsend.capture.state, irsend.capture.bits); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 2 (Dry), Temp: 25C, Fan: 0 (Auto), " + "Swing (V): 0 (Off), Swing (H): 72 (Left Right), Turbo: Off, Econo: Off, " + "3D: Off, Clean: Off", + ac.toString()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Mitsubishi_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Mitsubishi_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Mitsubishi_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Mitsubishi_test.cpp index 7b8eb2192..6c9480b31 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Mitsubishi_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Mitsubishi_test.cpp @@ -17,6 +17,7 @@ TEST(TestSendMitsubishi, SendDataOnly) { irsend.reset(); irsend.sendMitsubishi(0xE242); EXPECT_EQ( + "f33000d50" "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" "m300s28080" @@ -28,6 +29,7 @@ TEST(TestSendMitsubishi, SendDataOnly) { irsend.reset(); irsend.sendMitsubishi(0x0); EXPECT_EQ( + "f33000d50" "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" "m300s34080" @@ -39,6 +41,7 @@ TEST(TestSendMitsubishi, SendDataOnly) { irsend.reset(); irsend.sendMitsubishi(0x4321); EXPECT_EQ( + "f33000d50" "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s2100" "m300s900m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100" "m300s28080" @@ -56,6 +59,7 @@ TEST(TestSendMitsubishi, SendWithRepeats) { irsend.reset(); irsend.sendMitsubishi(0xE242, kMitsubishiBits, 0); // 0 repeat. EXPECT_EQ( + "f33000d50" "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" "m300s28080", @@ -64,6 +68,7 @@ TEST(TestSendMitsubishi, SendWithRepeats) { irsend.reset(); irsend.sendMitsubishi(0xE242, kMitsubishiBits, 1); // 1 repeat. EXPECT_EQ( + "f33000d50" "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" "m300s28080" @@ -73,6 +78,7 @@ TEST(TestSendMitsubishi, SendWithRepeats) { irsend.outputStr()); irsend.sendMitsubishi(0xE242, kMitsubishiBits, 2); // 2 repeats. EXPECT_EQ( + "f33000d50" "m300s2100m300s2100m300s2100m300s900m300s900m300s900m300s2100m300s900" "m300s900m300s2100m300s900m300s900m300s900m300s900m300s2100m300s900" "m300s28080" @@ -93,6 +99,7 @@ TEST(TestSendMitsubishi, SendUnusualSize) { irsend.reset(); irsend.sendMitsubishi(0x0, 8); EXPECT_EQ( + "f33000d50" "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" "m300s43680" "m300s900m300s900m300s900m300s900m300s900m300s900m300s900m300s900" @@ -102,6 +109,7 @@ TEST(TestSendMitsubishi, SendUnusualSize) { irsend.reset(); irsend.sendMitsubishi(0x1234567890ABCDEF, 64); EXPECT_EQ( + "f33000d50" "m300s900m300s900m300s900m300s2100m300s900m300s900m300s2100m300s900" "m300s900m300s900m300s2100m300s2100m300s900m300s2100m300s900m300s900" "m300s900m300s2100m300s900m300s2100m300s900m300s2100m300s2100m300s900" @@ -305,6 +313,7 @@ TEST(TestSendMitsubishiAC, SendDataOnly) { irsend.reset(); irsend.sendMitsubishiAC(mitsub_code); EXPECT_EQ( + "f38000d50" "m3400s1750" "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" @@ -360,6 +369,7 @@ TEST(TestSendMitsubishiAC, SendWithRepeats) { irsend.sendMitsubishiAC(mitsub_code, kMitsubishiACStateLength, 0); EXPECT_EQ( + "f38000d50" "m3400s1750" "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" @@ -385,6 +395,7 @@ TEST(TestSendMitsubishiAC, SendWithRepeats) { irsend.reset(); irsend.sendMitsubishiAC(mitsub_code, kMitsubishiACStateLength, 2); EXPECT_EQ( + "f38000d50" "m3400s1750" "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" @@ -466,6 +477,7 @@ TEST(TestSendMitsubishiAC, SendUnexpectedSizes) { irsend.reset(); irsend.sendMitsubishiAC(mitsub_long_code, 19); ASSERT_EQ( + "f38000d50" "m3400s1750" "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" @@ -665,6 +677,7 @@ TEST(TestMitsubishiACClass, MessageConstuction) { irsend.reset(); irsend.sendMitsubishiAC(mitsub.getRaw()); EXPECT_EQ( + "f38000d50" "m3400s1750" "m450s1300m450s1300m450s420m450s420m450s420m450s1300m450s420m450s420" "m450s1300m450s1300m450s420m450s1300m450s420m450s420m450s1300m450s1300" @@ -984,6 +997,7 @@ TEST(TestSendMitsubishi2, SendDataOnly) { irsend.reset(); irsend.sendMitsubishi2(0xF82); EXPECT_EQ( + "f33000d50" "m8400s4200" "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" "m560s4200" @@ -999,6 +1013,7 @@ TEST(TestSendMitsubishi2, SendDataOnly) { irsend.reset(); irsend.sendMitsubishi2(0x0); EXPECT_EQ( + "f33000d50" "m8400s4200" "m560s520m560s520m560s520m560s520m560s520m560s520m560s520m560s520" "m560s4200" @@ -1020,6 +1035,7 @@ TEST(TestSendMitsubishi2, Repeats) { irsend.reset(); irsend.sendMitsubishi2(0xF82, kMitsubishiBits, 0); EXPECT_EQ( + "f33000d50" "m8400s4200" "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" "m560s4200" @@ -1030,6 +1046,7 @@ TEST(TestSendMitsubishi2, Repeats) { irsend.reset(); irsend.sendMitsubishi2(0xF82, kMitsubishiBits, 2); EXPECT_EQ( + "f33000d50" "m8400s4200" "m560s520m560s520m560s520m560s520m560s1560m560s1560m560s1560m560s1560" "m560s4200" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_NEC_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_NEC_test.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_NEC_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_NEC_test.cpp index 6b84b0ec9..c881b7b44 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_NEC_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_NEC_test.cpp @@ -12,6 +12,7 @@ TEST(TestSendNEC, SendDataOnly) { irsend.begin(); irsend.sendNEC(0); EXPECT_EQ( + "f38000d33" "m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" @@ -20,6 +21,7 @@ TEST(TestSendNEC, SendDataOnly) { irsend.outputStr()); irsend.sendNEC(0xAA00FF55); EXPECT_EQ( + "f38000d33" "m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s1680m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680" @@ -33,15 +35,17 @@ TEST(TestSendNEC, SendSmallData) { IRsendTest irsend(4); irsend.begin(); irsend.sendNEC(0xA, 4); // Send only 4 data bits. - EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s87360", + EXPECT_EQ("f38000d33m8960s4480m560s1680m560s560m560s1680m560s560m560s87360", irsend.outputStr()); irsend.sendNEC(0, 8); // Send only 8 data bits. EXPECT_EQ( + "f38000d33" "m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s85120", irsend.outputStr()); irsend.sendNEC(0x1234567890ABCDEF, 64); // Send 64 data bits. EXPECT_EQ( + "f38000d33" "m8960s4480m560s560m560s560m560s560m560s1680m560s560m560s560" "m560s1680m560s560m560s560m560s560m560s1680m560s1680m560s560" "m560s1680m560s560m560s560m560s560m560s1680m560s560m560s1680" @@ -61,17 +65,20 @@ TEST(TestSendNEC, SendWithRepeats) { irsend.begin(); irsend.sendNEC(0, 8, 0); // Send a command with 0 repeats. EXPECT_EQ( + "f38000d33" "m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s85120", irsend.outputStr()); irsend.sendNEC(0xAA, 8, 1); // Send a command with 1 repeat. EXPECT_EQ( + "f38000d33" "m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s1680m560s560m560s80640" "m8960s2240m560s96320", irsend.outputStr()); irsend.sendNEC(0xAA, 8, 3); // Send a command with 3 repeats. EXPECT_EQ( + "f38000d33" "m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" "m560s1680m560s560m560s80640" "m8960s2240m560s96320" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Nikai_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Nikai_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Nikai_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Nikai_test.cpp index 4a4ea05bb..fff242326 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Nikai_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Nikai_test.cpp @@ -13,6 +13,7 @@ TEST(TestSendNikai, SendDataOnly) { irsend.reset(); irsend.sendNikai(0xD5F2A); // Nikai TV Power Off. EXPECT_EQ( + "f38000d33" "m4000s4000" "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" @@ -31,6 +32,7 @@ TEST(TestSendNikai, SendWithRepeats) { irsend.reset(); irsend.sendNikai(0xD5F2A, kNikaiBits, 1); // 1 repeat. EXPECT_EQ( + "f38000d33" "m4000s4000" "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" @@ -44,6 +46,7 @@ TEST(TestSendNikai, SendWithRepeats) { irsend.outputStr()); irsend.sendNikai(0xD5F2A, kNikaiBits, 2); // 2 repeat. EXPECT_EQ( + "f38000d33" "m4000s4000" "m500s2000m500s2000m500s2000m500s2000m500s1000m500s1000m500s2000" "m500s1000m500s2000m500s1000m500s2000m500s1000m500s1000m500s1000" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Panasonic_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Panasonic_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Panasonic_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Panasonic_test.cpp index a1d8a7979..4d10f8fb1 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Panasonic_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Panasonic_test.cpp @@ -32,6 +32,7 @@ TEST(TestSendPanasonic64, SendDataOnly) { irsend.reset(); irsend.sendPanasonic64(0x0); EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" @@ -45,6 +46,7 @@ TEST(TestSendPanasonic64, SendDataOnly) { irsend.reset(); irsend.sendPanasonic64(0x40040190ED7C); EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" @@ -58,6 +60,7 @@ TEST(TestSendPanasonic64, SendDataOnly) { irsend.reset(); irsend.sendPanasonic64(0xFFFFFFFFFFFF); EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" "m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296m432s1296" @@ -77,6 +80,7 @@ TEST(TestSendPanasonic64, SendWithRepeats) { irsend.reset(); irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 0); // 0 repeats. EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" @@ -90,6 +94,7 @@ TEST(TestSendPanasonic64, SendWithRepeats) { irsend.reset(); irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 1); // 1 repeat. EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" @@ -110,6 +115,7 @@ TEST(TestSendPanasonic64, SendWithRepeats) { irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 2); // 2 repeats. EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" @@ -145,6 +151,7 @@ TEST(TestSendPanasonic64, SendUnusualSize) { irsend.reset(); irsend.sendPanasonic64(0x0, 8); EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s432" "m432s150768", @@ -153,6 +160,7 @@ TEST(TestSendPanasonic64, SendUnusualSize) { irsend.reset(); irsend.sendPanasonic64(0x1234567890ABCDEF, 64); EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s432m432s432m432s432m432s1296m432s432m432s432m432s1296m432s432" "m432s432m432s432m432s1296m432s1296m432s432m432s1296m432s432m432s432" @@ -483,6 +491,7 @@ TEST(TestSendPanasonicAC, SendDataOnly) { 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x06, 0x83}; irsend.sendPanasonicAC(state); EXPECT_EQ( + "f36700d50" "m3456s1728" "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Pioneer_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Pioneer_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Pioneer_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Pioneer_test.cpp index b78469add..36d61c706 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Pioneer_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Pioneer_test.cpp @@ -13,6 +13,7 @@ TEST(TestSendPioneer, SendDataOnly) { irsend.begin(); irsend.sendPioneer(0); EXPECT_EQ( + "f38000d33" "m8960s4480" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" @@ -28,6 +29,7 @@ TEST(TestSendPioneer, SendDataOnly) { irsend.outputStr()); irsend.sendPioneer(0x55FF00AAAA00FF55); EXPECT_EQ( + "f38000d33" "m8960s4480" "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" @@ -136,6 +138,7 @@ TEST(TestDecodePioneer, SyntheticPioneerMessage) { irsend.reset(); irsend.sendPioneer(0x659A857AF50A3DC2, 64, 0); EXPECT_EQ( + "f38000d33" "m8960s4480" "m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s1680" "m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s560" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Pronto_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Pronto_test.cpp similarity index 96% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Pronto_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Pronto_test.cpp index e52c6dd90..513f985da 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Pronto_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Pronto_test.cpp @@ -58,7 +58,8 @@ TEST(TestSendPronto, MoreDataThanNeededInNormal) { uint16_t pronto_test[8] = {0x0000, 0x0067, 0x0001, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004}; irsend.sendPronto(pronto_test, 8); - EXPECT_EQ("m25s50", irsend.outputStr()); // Only send the data required. + EXPECT_EQ("f40244d50m25s50", + irsend.outputStr()); // Only send the data required. } TEST(TestSendPronto, MoreDataThanNeededInRepeat) { @@ -70,7 +71,8 @@ TEST(TestSendPronto, MoreDataThanNeededInRepeat) { uint16_t pronto_test[8] = {0x0000, 0x0067, 0x0000, 0x0001, 0x0001, 0x0002, 0x0003, 0x0004}; irsend.sendPronto(pronto_test, 8); - EXPECT_EQ("m25s50", irsend.outputStr()); // Only send the data required. + EXPECT_EQ("f40244d50m25s50", + irsend.outputStr()); // Only send the data required. } TEST(TestSendPronto, MoreDataThanNeededInBoth) { @@ -82,9 +84,11 @@ TEST(TestSendPronto, MoreDataThanNeededInBoth) { uint16_t pronto_test[10] = {0x0000, 0x0067, 0x0001, 0x0001, 0x0001, 0x0002, 0x0003, 0x0004, 0x5, 0x6}; irsend.sendPronto(pronto_test, 10); - EXPECT_EQ("m25s50", irsend.outputStr()); // Only send the data required. + EXPECT_EQ("f40244d50m25s50", + irsend.outputStr()); // Only send the data required. irsend.sendPronto(pronto_test, 10, 1); - EXPECT_EQ("m25s50m75s100", irsend.outputStr()); // Only the data required. + EXPECT_EQ("f40244d50m25s50m75s100", + irsend.outputStr()); // Only the data required. } TEST(TestSendPronto, ShortestValidCodeThatSendsNothing) { @@ -134,6 +138,7 @@ TEST(TestSendPronto, NonRepeatingCode) { EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); EXPECT_EQ( + "f40244d50" "m2400s600" "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" "m600s600m600s600m600s600m600s27650" @@ -160,6 +165,7 @@ TEST(TestSendPronto, NonRepeatingCode) { EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); EXPECT_EQ( + "f40244d50" "m2400s600" "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" "m600s600m600s600m600s600m600s27650" @@ -201,6 +207,7 @@ TEST(TestSendPronto, RepeatSequenceOnlyForSony) { EXPECT_EQ(0x1A, irsend.capture.address); EXPECT_EQ(0x24AE, irsend.capture.command); EXPECT_EQ( + "f40244d50" "m2400s600" "m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600" "m1200s600m600s600m1200s600m1200s600m1200s600m600s600m600s600m1200s600" @@ -218,6 +225,7 @@ TEST(TestSendPronto, RepeatSequenceOnlyForSony) { EXPECT_EQ(0x1A, irsend.capture.address); EXPECT_EQ(0x24AE, irsend.capture.command); EXPECT_EQ( + "f40244d50" "m2400s600" "m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600" "m1200s600m600s600m1200s600m1200s600m1200s600m600s600m600s600m1200s600" @@ -265,6 +273,7 @@ TEST(TestSendPronto, RepeatSequenceOnlyForPanasonic) { EXPECT_EQ(0x4004, irsend.capture.address); EXPECT_EQ(0x1007C7D, irsend.capture.command); EXPECT_EQ( + "f36682d50" "m3456s1701" "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" @@ -305,6 +314,7 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) { EXPECT_EQ(0x18, irsend.capture.address); EXPECT_EQ(0x8, irsend.capture.command); EXPECT_EQ( + "f38028d50" "m8892s4446" "m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546" "m546s1664m546s1664m546s1664m546s546m546s546m546s1664m546s1664m546s1664" @@ -324,6 +334,7 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) { EXPECT_EQ(0x18, irsend.capture.address); EXPECT_EQ(0x8, irsend.capture.command); EXPECT_EQ( + "f38028d50" "m8892s4446" "m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546" "m546s1664m546s1664m546s1664m546s546m546s546m546s1664m546s1664m546s1664" @@ -344,6 +355,7 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) { EXPECT_EQ(0x18, irsend.capture.address); EXPECT_EQ(0x8, irsend.capture.command); EXPECT_EQ( + "f38028d50" "m8892s4446" "m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546" "m546s1664m546s1664m546s1664m546s546m546s546m546s1664m546s1664m546s1664" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_RC5_RC6_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_RC5_RC6_test.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_RC5_RC6_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_RC5_RC6_test.cpp index e8aa9bfc1..da9fa027c 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_RC5_RC6_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_RC5_RC6_test.cpp @@ -79,6 +79,7 @@ TEST(TestSendRC5, SendDataOnly) { irsend.reset(); irsend.sendRC5(0x0, kRC5Bits); EXPECT_EQ( + "f36000d25" "m889s889m1778s889m889s889m889s889m889s889m889s889m889" "s889m889s889m889s889m889s889m889s889m889s889m889s90664", irsend.outputStr()); @@ -86,6 +87,7 @@ TEST(TestSendRC5, SendDataOnly) { irsend.reset(); irsend.sendRC5(0x1AAA, kRC5Bits); EXPECT_EQ( + "f36000d25" "m889s889m889s889m1778s1778m1778s1778m1778s1778" "m1778s1778m1778s1778m1778s90664", irsend.outputStr()); @@ -93,6 +95,7 @@ TEST(TestSendRC5, SendDataOnly) { irsend.reset(); irsend.sendRC5(0x175, kRC5Bits); EXPECT_EQ( + "f36000d25" "m889s889m1778s889m889s889m889s1778m1778s1778" "m889s889m889s889m1778s1778m1778s1778m889s89775", irsend.outputStr()); @@ -100,6 +103,7 @@ TEST(TestSendRC5, SendDataOnly) { irsend.reset(); irsend.sendRC5(0x3FFF, kRC5Bits); EXPECT_EQ( + "f36000d25" "m889s889m889s889m889s889m889s889m889s889m889s889m889s889" "m889s889m889s889m889s889m889s889m889s889m889s889m889s89775", irsend.outputStr()); @@ -107,6 +111,7 @@ TEST(TestSendRC5, SendDataOnly) { irsend.reset(); irsend.sendRC5(0x0, kRC5XBits); EXPECT_EQ( + "f36000d25" "m889s889m1778s889m889s889m889s889m889s889m889s889m889" "s889m889s889m889s889m889s889m889s889m889s889m889s90664", irsend.outputStr()); @@ -114,6 +119,7 @@ TEST(TestSendRC5, SendDataOnly) { irsend.reset(); irsend.sendRC5(0x1AAA, kRC5XBits); EXPECT_EQ( + "f36000d25" "m1778s1778m1778s1778m1778s1778m1778" "s1778m1778s1778m1778s1778m1778s90664", irsend.outputStr()); @@ -121,6 +127,7 @@ TEST(TestSendRC5, SendDataOnly) { irsend.reset(); irsend.sendRC5(0x175, kRC5XBits); EXPECT_EQ( + "f36000d25" "m889s889m1778s889m889s889m889s1778m1778s1778" "m889s889m889s889m1778s1778m1778s1778m889s89775", irsend.outputStr()); @@ -128,6 +135,7 @@ TEST(TestSendRC5, SendDataOnly) { irsend.reset(); irsend.sendRC5(0x3FFF, kRC5XBits); EXPECT_EQ( + "f36000d25" "m1778s1778m889s889m889s889m889s889m889s889m889s889m889" "s889m889s889m889s889m889s889m889s889m889s889m889s89775", irsend.outputStr()); @@ -141,6 +149,7 @@ TEST(TestSendRC5, SendWithRepeats) { irsend.reset(); irsend.sendRC5(0x175, kRC5Bits, 1); EXPECT_EQ( + "f36000d25" "m889s889m1778s889m889s889m889s1778m1778s1778" "m889s889m889s889m1778s1778m1778s1778m889s90664" "m889s889m1778s889m889s889m889s1778m1778s1778" @@ -150,6 +159,7 @@ TEST(TestSendRC5, SendWithRepeats) { irsend.reset(); irsend.sendRC5(0x175, kRC5Bits, 2); EXPECT_EQ( + "f36000d25" "m889s889m1778s889m889s889m889s1778m1778s1778" "m889s889m889s889m1778s1778m1778s1778m889s90664" "m889s889m1778s889m889s889m889s1778m1778s1778" @@ -161,6 +171,7 @@ TEST(TestSendRC5, SendWithRepeats) { irsend.reset(); irsend.sendRC5(0x175, kRC5XBits, 1); EXPECT_EQ( + "f36000d25" "m889s889m1778s889m889s889m889s1778m1778s1778" "m889s889m889s889m1778s1778m1778s1778m889s90664" "m889s889m1778s889m889s889m889s1778m1778s1778" @@ -170,6 +181,7 @@ TEST(TestSendRC5, SendWithRepeats) { irsend.reset(); irsend.sendRC5(0x1175, kRC5XBits, 2); EXPECT_EQ( + "f36000d25" "m1778s889m889s889m889s889m889s1778m1778s1778" "m889s889m889s889m1778s1778m1778s1778m889s90664" "m1778s889m889s889m889s889m889s1778m1778s1778" @@ -444,6 +456,7 @@ TEST(TestSendRC6, SendMode0DataOnly) { irsend.reset(); irsend.sendRC6(0x0); EXPECT_EQ( + "f36000d33" "m2664s888" "m444s888m444s444m444s444m444s888m888s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444s444m444s444" @@ -454,6 +467,7 @@ TEST(TestSendRC6, SendMode0DataOnly) { irsend.reset(); irsend.sendRC6(0x1FFFF); EXPECT_EQ( + "f36000d33" "m2664s888" "m444s888m444s444m444s444m1332s888m444s444m444s444m444s444" "m444s444m444s444m444s444m444s444m444s444m444s444m444s444" @@ -464,6 +478,7 @@ TEST(TestSendRC6, SendMode0DataOnly) { irsend.reset(); irsend.sendRC6(0x15555); EXPECT_EQ( + "f36000d33" "m2664s888" "m444s888m444s444m444s444m1332s1332m888s888m888s888" "m888s888m888s888m888s888m888s888m888s888m888" @@ -479,6 +494,7 @@ TEST(TestSendRC6, Send36BitDataOnly) { irsend.reset(); irsend.sendRC6(0x0, kRC6_36Bits); EXPECT_EQ( + "f36000d33" "m2664s888" "m444s888m444s444m444s444m444" "s888m888" @@ -492,6 +508,7 @@ TEST(TestSendRC6, Send36BitDataOnly) { irsend.reset(); irsend.sendRC6(0xFFFFFFFFF, kRC6_36Bits); EXPECT_EQ( + "f36000d33" "m2664s888" "m444s444m444s444m444s444m444s444" "m888s888" @@ -505,6 +522,7 @@ TEST(TestSendRC6, Send36BitDataOnly) { irsend.reset(); irsend.sendRC6(0xAAAAAAAAAA, kRC6_36Bits); EXPECT_EQ( + "f36000d33" "m2664s888m444s444m444s888m888" "s1332m1332" "s888m888s888m888s888m888s888m888s888m888s888m888s888m888s888m888s888m888" @@ -514,6 +532,7 @@ TEST(TestSendRC6, Send36BitDataOnly) { irsend.reset(); irsend.sendRC6(0xC800F740C, kRC6_36Bits); // Xbox 360 OnOff code EXPECT_EQ( + "f36000d33" "m2664s888" "m444s444m444s444m444s888m444" "s888m1332" @@ -526,6 +545,7 @@ TEST(TestSendRC6, Send36BitDataOnly) { irsend.sendRC6(irsend.toggleRC6(0xC800F740C, kRC6_36Bits), kRC6_36Bits); // Xbox 360 OnOff code (toggled) EXPECT_EQ( + "f36000d33" "m2664s888" "m444s444m444s444m444s888m444" "s888m1332" @@ -544,6 +564,7 @@ TEST(TestSendRC6, SendMode0WithRepeats) { irsend.reset(); irsend.sendRC6(0x175, kRC6Mode0Bits, 0); EXPECT_EQ( + "f36000d33" "m2664s888" "m444s888m444s444m444s444m444" "s888m888" @@ -554,6 +575,7 @@ TEST(TestSendRC6, SendMode0WithRepeats) { irsend.reset(); irsend.sendRC6(0x175, kRC6Mode0Bits, 1); EXPECT_EQ( + "f36000d33" "m2664s888" "m444s888m444s444m444s444m444" "s888m888" @@ -569,6 +591,7 @@ TEST(TestSendRC6, SendMode0WithRepeats) { irsend.reset(); irsend.sendRC6(0x175, kRC6Mode0Bits, 2); EXPECT_EQ( + "f36000d33" "m2664s888" "m444s888m444s444m444s444m444" "s888m888" @@ -595,6 +618,7 @@ TEST(TestSendRC6, Send36BitWithRepeats) { irsend.reset(); irsend.sendRC6(0x175, kRC6_36Bits, 0); EXPECT_EQ( + "f36000d33" "m2664s888" "m444s888m444s444m444s444m444" "s888m888" @@ -607,6 +631,7 @@ TEST(TestSendRC6, Send36BitWithRepeats) { irsend.reset(); irsend.sendRC6(0x175, kRC6_36Bits, 1); EXPECT_EQ( + "f36000d33" "m2664s888" "m444s888m444s444m444s444m444" "s888m888" @@ -626,6 +651,7 @@ TEST(TestSendRC6, Send36BitWithRepeats) { irsend.reset(); irsend.sendRC6(0x175, kRC6_36Bits, 2); EXPECT_EQ( + "f36000d33" "m2664s888" "m444s888m444s444m444s444m444" "s888m888" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_RCMM_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_RCMM_test.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_RCMM_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_RCMM_test.cpp index 028dbd8b3..22306a59b 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_RCMM_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_RCMM_test.cpp @@ -14,6 +14,7 @@ TEST(TestSendRCMM, SendDataOnly) { irsend.reset(); irsend.sendRCMM(0xe0a600); EXPECT_EQ( + "f36000d33" "m416s277" "m166s777m166s611m166s277m166s277" "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" @@ -22,6 +23,7 @@ TEST(TestSendRCMM, SendDataOnly) { irsend.reset(); irsend.sendRCMM(0x28e0a600UL, 32); EXPECT_EQ( + "f36000d33" "m416s277" "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" @@ -37,6 +39,7 @@ TEST(TestSendRCMM, SendWithRepeats) { irsend.reset(); irsend.sendRCMM(0x28e0a600, 32, 2); // 2 repeats. EXPECT_EQ( + "f36000d33" "m416s277" "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" @@ -60,6 +63,7 @@ TEST(TestSendRCMM, SendUnusualSize) { irsend.reset(); irsend.sendRCMM(0xE0, 8); EXPECT_EQ( + "f36000d33" "m416s277" "m166s777m166s611m166s277m166s277" "m166s24313", @@ -67,6 +71,7 @@ TEST(TestSendRCMM, SendUnusualSize) { irsend.reset(); irsend.sendRCMM(0x28e0a60000UL, 40); EXPECT_EQ( + "f36000d33" "m416s277" "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Samsung_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Samsung_test.cpp similarity index 77% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Samsung_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Samsung_test.cpp index 9ee1fcabb..8670ac4ab 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Samsung_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Samsung_test.cpp @@ -1,4 +1,4 @@ -// Copyright 2017 David Conran +// Copyright 2017, 2018, 2019 David Conran #include "ir_Samsung.h" #include "IRrecv.h" @@ -7,6 +7,13 @@ #include "IRsend_test.h" #include "gtest/gtest.h" + +// General housekeeping +TEST(TestSamsung, Housekeeping) { + ASSERT_EQ("SAMSUNG", typeToString(SAMSUNG)); + ASSERT_FALSE(hasACState(SAMSUNG)); +} + // Tests for sendSAMSUNG(). // Test sending typical data only. @@ -17,6 +24,7 @@ TEST(TestSendSamsung, SendDataOnly) { irsend.reset(); irsend.sendSAMSUNG(0xE0E09966); // Samsung TV Power On. EXPECT_EQ( + "f38000d33" "m4480s4480" "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" @@ -36,6 +44,7 @@ TEST(TestSendSamsung, SendWithRepeats) { irsend.reset(); irsend.sendSAMSUNG(0xE0E09966, kSamsungBits, 1); // 1 repeat. EXPECT_EQ( + "f38000d33" "m4480s4480" "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" @@ -51,6 +60,7 @@ TEST(TestSendSamsung, SendWithRepeats) { irsend.outputStr()); irsend.sendSAMSUNG(0xE0E09966, kSamsungBits, 2); // 2 repeats. EXPECT_EQ( + "f38000d33" "m4480s4480" "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560" "m560s560m560s1680m560s1680m560s1680m560s560m560s560m560s560" @@ -281,17 +291,24 @@ TEST(TestDecodeSamsung, FailToDecodeNonSamsungExample) { ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); } +// General housekeeping +TEST(TestSamsungAC, Housekeeping) { + ASSERT_EQ("SAMSUNG_AC", typeToString(SAMSUNG_AC)); + ASSERT_TRUE(hasACState(SAMSUNG_AC)); +} + // Tests for sendSamsungAC(). // Test sending typical data only. TEST(TestSendSamsungAC, SendDataOnly) { IRsendTest irsend(0); irsend.begin(); - uint8_t data[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, - 0x00, 0xF0, 0x01, 0x02, 0xAF, - 0x71, 0x00, 0x15, 0xF0}; + uint8_t data[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0x02, 0xAF, 0x71, 0x00, 0x15, 0xF0}; irsend.sendSamsungAC(data); EXPECT_EQ( + "f38000d50" "m690s17844" "m3086s8864" "m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436" @@ -320,10 +337,12 @@ TEST(TestSendSamsungAC, SendExtendedData) { irsend.begin(); // "Off" message. uint8_t data[kSamsungAcExtendedStateLength] = { - 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xD2, 0x0F, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0}; + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, + 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0}; irsend.sendSamsungAC(data, kSamsungAcExtendedStateLength); EXPECT_EQ( + "f38000d50" "m690s17844" "m3086s8864" "m586s436m586s1432m586s436m586s436m586s436m586s436m586s436m586s436" @@ -358,15 +377,16 @@ TEST(TestSendSamsungAC, SendExtendedData) { // Tests for IRSamsungAc class. TEST(TestIRSamsungAcClass, SetAndGetRaw) { - uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, - 0x00, 0xF0, 0x01, 0xE2, 0xFE, - 0x71, 0x40, 0x11, 0xF0}; + uint8_t expectedState[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xE2, 0xFE, 0x71, 0x40, 0x11, 0xF0}; IRSamsungAc samsung(0); samsung.setRaw(expectedState); EXPECT_STATE_EQ(expectedState, samsung.getRaw(), kSamsungAcBits); uint8_t extendedState[kSamsungAcExtendedStateLength] = { - 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0xD2, 0x0F, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xE2, 0xFE, 0x71, 0x40, 0x11, 0xF0}; + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xE2, 0xFE, 0x71, 0x40, 0x11, 0xF0}; samsung.setRaw(extendedState, kSamsungAcExtendedStateLength); // We should NOT get the extended state back. EXPECT_STATE_EQ(expectedState, samsung.getRaw(), kSamsungAcBits); @@ -496,9 +516,15 @@ TEST(TestIRSamsungAcClass, ChecksumCalculation) { const uint8_t originalstate[kSamsungAcStateLength] = { 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0x02, 0xAF, 0x71, 0x00, 0x15, 0xF0}; - uint8_t examplestate[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, - 0x00, 0xF0, 0x01, 0x02, 0xAF, - 0x71, 0x00, 0x15, 0xF0}; + uint8_t examplestate[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0x02, 0xAF, 0x71, 0x00, 0x15, 0xF0}; + + const uint8_t extendedstate[kSamsungAcExtendedStateLength] = { + 0x02, 0xA9, 0x0F, 0x00, 0x00, 0x00, 0xC0, + 0x01, 0xC9, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xF9, 0xCE, 0x71, 0xE0, 0x41, 0xC0}; + EXPECT_TRUE(IRSamsungAc::validChecksum(examplestate)); EXPECT_EQ(0, IRSamsungAc::calcChecksum(examplestate)); @@ -516,6 +542,9 @@ TEST(TestIRSamsungAcClass, ChecksumCalculation) { examplestate[11] = 0x01; EXPECT_FALSE(IRSamsungAc::validChecksum(examplestate)); EXPECT_EQ(0xF, IRSamsungAc::calcChecksum(examplestate)); + + // Check an extended state is valid. + EXPECT_TRUE(IRSamsungAc::validChecksum(extendedstate, 21)); } TEST(TestIRSamsungAcClass, HumanReadable) { @@ -585,9 +614,9 @@ TEST(TestDecodeSamsungAC, SyntheticDecode) { IRrecv irrecv(0); irsend.begin(); irsend.reset(); - uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, - 0x00, 0xF0, 0x01, 0x02, 0xAF, - 0x71, 0x00, 0x15, 0xF0}; + uint8_t expectedState[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0x02, 0xAF, 0x71, 0x00, 0x15, 0xF0}; // Synthesised Normal Samsung A/C message. irsend.sendSamsungAC(expectedState); irsend.makeDecodeResult(); @@ -626,9 +655,9 @@ TEST(TestDecodeSamsungAC, DecodeRealExample) { 584, 1406, 586, 410, 584, 1384, 606, 410, 586, 410, 584, 408, 586, 408, 586, 408, 586, 408, 588, 410, 584, 1408, 590, 1400, 592, 1398, 602, 1388, 612}; - uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, - 0x00, 0xF0, 0x01, 0x02, 0xAF, - 0x71, 0x00, 0x15, 0xF0}; + uint8_t expectedState[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0x02, 0xAF, 0x71, 0x00, 0x15, 0xF0}; irsend.sendRaw(rawData, 233, 38000); irsend.makeDecodeResult(); @@ -675,9 +704,9 @@ TEST(TestDecodeSamsungAC, DecodeRealExample2) { 560, 436, 486, 510, 566, 1400, 598, 420, 576, 418, 582, 414, 586, 410, 584, 410, 584, 410, 586, 410, 584, 1382, 608, 1384, 606, 1384, 606, 1408, 600}; - uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, - 0x00, 0xF0, 0x01, 0xE2, 0xFE, - 0x71, 0x80, 0x11, 0xF0}; + uint8_t expectedState[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0}; irsend.sendRaw(rawData, 233, 38000); irsend.makeDecodeResult(); @@ -735,8 +764,9 @@ TEST(TestDecodeSamsungAC, DecodePowerOnSample) { 518, 480, 520, 480, 520, 1454, 568, 1430, 566, 1432, 566, 1454, 594}; uint8_t expectedState[kSamsungAcExtendedStateLength] = { - 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01, 0xD2, 0x0F, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0}; + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xE2, 0xFE, 0x71, 0x80, 0x11, 0xF0}; irsend.sendRaw(rawData, 349, 38000); irsend.makeDecodeResult(); @@ -794,8 +824,9 @@ TEST(TestDecodeSamsungAC, DecodePowerOffSample) { 608}; uint8_t expectedState[kSamsungAcExtendedStateLength] = { - 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xD2, 0x0F, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0}; + 0x02, 0xB2, 0x0F, 0x00, 0x00, 0x00, 0xC0, + 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x02, 0xFF, 0x71, 0x80, 0x11, 0xC0}; irsend.sendRaw(rawData, 349, 38000); irsend.makeDecodeResult(); @@ -840,9 +871,9 @@ TEST(TestDecodeSamsungAC, DecodeHeatSample) { 512, 482, 512, 482, 510, 484, 510, 484, 510, 1478, 512, 1504, 488, 1480, 560, 1454, 514}; - uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, - 0x00, 0xF0, 0x01, 0x02, 0xAF, - 0x71, 0x10, 0x41, 0xF0}; + uint8_t expectedState[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0x02, 0xAF, 0x71, 0x10, 0x41, 0xF0}; irsend.sendRaw(rawData, 233, 38000); irsend.makeDecodeResult(); @@ -887,9 +918,9 @@ TEST(TestDecodeSamsungAC, DecodeCoolSample) { 584, 412, 584, 408, 586, 410, 586, 408, 586, 1404, 586, 1408, 582, 1410, 562, 1426, 610}; - uint8_t expectedState[kSamsungAcStateLength] = {0x02, 0x92, 0x0F, 0x00, 0x00, - 0x00, 0xF0, 0x01, 0xE2, 0xFE, - 0x71, 0x40, 0x11, 0xF0}; + uint8_t expectedState[kSamsungAcStateLength] = { + 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, + 0x01, 0xE2, 0xFE, 0x71, 0x40, 0x11, 0xF0}; irsend.sendRaw(rawData, 233, 38000); irsend.makeDecodeResult(); @@ -905,3 +936,195 @@ TEST(TestDecodeSamsungAC, DecodeCoolSample) { "Beep: Off, Clean: Off, Quiet: Off", samsung.toString()); } + +TEST(TestDecodeSamsungAC, Issue604DecodeExtended) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t sendOff[349] = { + 642, 17730, 3056, 8916, 542, 448, 552, 1440, 552, 444, 552, 444, + 552, 444, 552, 440, 556, 440, 556, 440, 556, 1436, 552, 444, + 552, 444, 552, 1440, 548, 470, 526, 1464, 470, 526, 516, 1470, + 552, 1440, 552, 1440, 550, 1436, 556, 1434, 552, 444, 552, 444, + 552, 444, 552, 442, 552, 444, 546, 470, 526, 470, 526, 470, + 470, 524, 518, 474, 548, 448, 552, 444, 552, 442, 552, 444, + 550, 444, 552, 440, 556, 440, 556, 438, 556, 440, 552, 442, + 552, 444, 552, 442, 552, 444, 550, 470, 526, 466, 524, 470, + 470, 524, 470, 524, 518, 476, 548, 444, 552, 444, 556, 440, + 552, 442, 552, 444, 550, 1436, 556, 1436, 552, 2946, 3026, 8918, + 550, 1440, 552, 444, 548, 468, 526, 468, 470, 526, 470, 526, + 542, 452, 548, 444, 552, 1440, 550, 444, 552, 444, 552, 1436, + 556, 438, 552, 442, 552, 1440, 552, 1440, 552, 1460, 526, 1464, + 470, 1516, 548, 1444, 552, 444, 552, 442, 552, 444, 552, 438, + 556, 440, 556, 440, 552, 444, 552, 444, 552, 444, 552, 444, + 552, 444, 548, 448, 546, 470, 526, 468, 526, 470, 470, 524, + 520, 470, 548, 448, 552, 444, 552, 444, 552, 444, 552, 444, + 552, 438, 556, 440, 556, 438, 552, 444, 552, 442, 552, 444, + 552, 444, 552, 444, 552, 470, 526, 466, 526, 470, 470, 524, + 518, 478, 546, 448, 552, 2920, 3052, 8916, 552, 1434, 556, 440, + 556, 438, 552, 444, 552, 442, 552, 442, 552, 442, 552, 444, + 548, 1444, 548, 470, 526, 470, 522, 1466, 470, 1520, 548, 1438, + 556, 1436, 552, 1440, 552, 442, 552, 1436, 552, 1440, 552, 1440, + 552, 442, 552, 470, 522, 1466, 526, 1466, 470, 1516, 552, 444, + 552, 442, 552, 444, 552, 1436, 556, 1436, 552, 1440, 550, 444, + 552, 444, 552, 444, 548, 448, 546, 448, 548, 470, 526, 1462, + 474, 1518, 548, 1440, 552, 1438, 556, 440, 550, 444, 552, 444, + 552, 444, 552, 440, 556, 1436, 552, 444, 552, 444, 552, 444, + 550, 470, 522, 470, 524, 470, 470, 524, 518, 1474, 548, 1440, + 556}; + + uint8_t expectedState[kSamsungAcExtendedStateLength] = { + 0x02, 0xA9, 0x0F, 0x00, 0x00, 0x00, 0xC0, + 0x01, 0xC9, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xF9, 0xCE, 0x71, 0xE0, 0x41, 0xC0}; + + irsend.sendRaw(sendOff, 349, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG_AC, irsend.capture.decode_type); + EXPECT_EQ(kSamsungAcExtendedBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRSamsungAc samsung(0); + samsung.setRaw(irsend.capture.state, irsend.capture.bits / 8); + EXPECT_EQ( + "Power: Off, Mode: 4 (HEAT), Temp: 30C, Fan: 0 (AUTO), Swing: Off, " + "Beep: Off, Clean: Off, Quiet: Off", + samsung.toString()); +} + +TEST(TestSendSamsung36, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendSamsung36(0); + EXPECT_EQ( + "f38000d50" + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560" + "m560s26880", + irsend.outputStr()); + irsend.sendSamsung36(0x400E00FF); + EXPECT_EQ( + "f38000d50" + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680" + "m560s26880", + irsend.outputStr()); + irsend.reset(); +} + +// General housekeeping +TEST(TestSamsung36, Housekeeping) { + ASSERT_EQ("SAMSUNG36", typeToString(SAMSUNG36)); + ASSERT_FALSE(hasACState(SAMSUNG36)); +} + +// Test sending with different repeats. +TEST(TestSendSamsung36, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendSamsung36(0x400E00FF, kSamsung36Bits, 1); // 1 repeat. + EXPECT_EQ( + "f38000d50" + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680" + "m560s26880" + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680" + "m560s26880", + irsend.outputStr()); + irsend.sendSamsung36(0x400E00FF, kSamsung36Bits, 2); // 2 repeats. + EXPECT_EQ( + "f38000d50" + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680" + "m560s26880" + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680" + "m560s26880" + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s4480" + "m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s1680" + "m560s26880", + irsend.outputStr()); +} + +TEST(TestDecodeSamsung36, RealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint16_t rawData[77] = { + 4542, 4438, 568, 432, 562, 436, 536, 462, 538, 460, 538, 460, 564, 1434, + 564, 434, 534, 464, 536, 462, 562, 436, 536, 464, 564, 432, 538, 462, 536, + 464, 534, 464, 564, 420, 566, 4414, 538, 1462, 566, 1432, 562, 1436, 536, + 462, 564, 436, 562, 436, 560, 436, 562, 436, 562, 436, 560, 438, 536, 462, + 562, 436, 562, 1436, 562, 1434, 536, 1462, 564, 1434, 562, 1436, 564, + 1436, 534, 1462, 534, 1464, 536}; // UNKNOWN E4CD1208 + + irsend.sendRaw(rawData, 77, 38000); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(SAMSUNG36, irsend.capture.decode_type); + EXPECT_EQ(kSamsung36Bits, irsend.capture.bits); + EXPECT_EQ(0x400E00FF, irsend.capture.value); + EXPECT_EQ(0xE00FF, irsend.capture.command); + EXPECT_EQ(0x400, irsend.capture.address); +} + +TEST(TestDecodeSamsung36, SyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + irsend.reset(); + + irsend.sendSamsung36(0x400E00FF); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSamsung36(&irsend.capture)); + ASSERT_EQ(SAMSUNG36, irsend.capture.decode_type); + EXPECT_EQ(kSamsung36Bits, irsend.capture.bits); + EXPECT_EQ(0x400E00FF, irsend.capture.value); + EXPECT_EQ(0xE00FF, irsend.capture.command); + EXPECT_EQ(0x400, irsend.capture.address); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Sanyo_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Sanyo_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Sanyo_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Sanyo_test.cpp index 14c1c7da0..165e29f17 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Sanyo_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Sanyo_test.cpp @@ -27,6 +27,7 @@ TEST(TestEncodeSanyoLC7461, SendDataOnly) { irsend.reset(); irsend.sendSanyoLC7461(0x1D8113F00FF); EXPECT_EQ( + "f38000d33" "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" @@ -45,6 +46,7 @@ TEST(TestEncodeSanyoLC7461, SendWithRepeats) { irsend.reset(); irsend.sendSanyoLC7461(0x1D8113F00FF, kSanyoLC7461Bits, 1); // 1 repeat. EXPECT_EQ( + "f38000d33" "m8960s4480" "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Sharp_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Sharp_test.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Sharp_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Sharp_test.cpp index 8481a4649..c9d3e851b 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Sharp_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Sharp_test.cpp @@ -47,6 +47,7 @@ TEST(TestSendSharp, SendDataOnly) { irsend.reset(); irsend.sendSharp(0x11, 0x52); EXPECT_EQ( + "f38000d33" "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" "m260s43602" @@ -64,6 +65,7 @@ TEST(TestSendSharp, SendWithRepeats) { irsend.reset(); irsend.sendSharp(0x11, 0x52, kSharpBits, 1); // 1 repeat. EXPECT_EQ( + "f38000d33" "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" "m260s43602" @@ -87,6 +89,7 @@ TEST(TestSendSharp, SendUnusualSize) { irsend.reset(); irsend.sendSharp(0x0, 0x0, 8); EXPECT_EQ( + "f38000d33" "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s780" "m260s43602" "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" @@ -96,6 +99,7 @@ TEST(TestSendSharp, SendUnusualSize) { irsend.reset(); irsend.sendSharp(0x0, 0x0, 16); EXPECT_EQ( + "f38000d33" "m260s780m260s780m260s780m260s780m260s780m260s780m260s780m260s780" "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s780" "m260s43602" @@ -115,6 +119,7 @@ TEST(TestSendSharpRaw, SendDataOnly) { irsend.reset(); irsend.sendSharpRaw(0x454A); EXPECT_EQ( + "f38000d33" "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" "m260s43602" @@ -132,6 +137,7 @@ TEST(TestSendSharpRaw, SendWithRepeats) { irsend.reset(); irsend.sendSharpRaw(0x454A, kSharpBits, 1); // 1 repeat. EXPECT_EQ( + "f38000d33" "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" "m260s43602" @@ -155,6 +161,7 @@ TEST(TestSendSharpRaw, SendUnusualSize) { irsend.reset(); irsend.sendSharpRaw(0x2, 8); EXPECT_EQ( + "f38000d33" "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s780" "m260s43602" "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" @@ -164,6 +171,7 @@ TEST(TestSendSharpRaw, SendUnusualSize) { irsend.reset(); irsend.sendSharpRaw(0x2, 16); EXPECT_EQ( + "f38000d33" "m260s780m260s780m260s780m260s780m260s780m260s780m260s780m260s780" "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s780" "m260s43602" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Sherwood_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Sherwood_test.cpp similarity index 97% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Sherwood_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Sherwood_test.cpp index 22d9ead38..f1f41d9c8 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Sherwood_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Sherwood_test.cpp @@ -14,6 +14,7 @@ TEST(TestSendSherwood, SendDataOnly) { irsend.reset(); irsend.sendSherwood(0xC1A28877); EXPECT_EQ( + "f38000d33" "m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" @@ -31,6 +32,7 @@ TEST(TestSendSherwood, SendDataWithRepeats) { irsend.reset(); irsend.sendSherwood(0xC1A28877, 32, 2); EXPECT_EQ( + "f38000d33" "m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" @@ -50,6 +52,7 @@ TEST(TestSendSherwood, SendDataWithZeroRepeats) { irsend.sendSherwood(0xC1A28877, 32, 0); // Should have a single NEC repeat, as we always send one. EXPECT_EQ( + "f38000d33" "m8960s4480m560s1680m560s1680m560s560m560s560m560s560m560s560" "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560" diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Sony_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Sony_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Sony_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Sony_test.cpp index c79ff6175..35c3287b0 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Sony_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Sony_test.cpp @@ -15,6 +15,7 @@ TEST(TestSendSony, SendDataOnly) { irsend.sendSony(0); // We expect three 20-bit commands to be sent. EXPECT_EQ( + "f40000d33" "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m600s600" "m600s600m600s600m600s600m600s600m600s18600" @@ -30,6 +31,7 @@ TEST(TestSendSony, SendDataOnly) { irsend.sendSony(0x240C, kSony20Bits); // We expect three 20-bit commands to be sent. EXPECT_EQ( + "f40000d33" "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" "m600s600m1200s600m1200s600m600s600m600s16200" @@ -45,6 +47,7 @@ TEST(TestSendSony, SendDataOnly) { irsend.sendSony(0x240C, kSony15Bits); // We expect three 15-bit commands to be sent. EXPECT_EQ( + "f40000d33" "m2400s600m600s600m1200s600m600s600m600s600m1200s600m600s600" "m600s600m600s600m600s600m600s600m600s600m1200s600m1200s600m600s600" "m600s22200" @@ -60,6 +63,7 @@ TEST(TestSendSony, SendDataOnly) { irsend.sendSony(0xA90, kSony12Bits); // We expect three 15-bit commands to be sent. EXPECT_EQ( + "f40000d33" "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" "m600s600m1200s600m600s600m600s600m600s600m600s25800" "m2400s600m1200s600m600s600m1200s600m600s600m1200s600m600s600" @@ -77,12 +81,14 @@ TEST(TestSendSony, SendWithDiffRepeats) { irsend.reset(); irsend.sendSony(0x240C, kSony20Bits, 0); // Send a command with 0 repeats. EXPECT_EQ( + "f40000d33" "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" "m600s600m1200s600m1200s600m600s600m600s16200", irsend.outputStr()); irsend.sendSony(0x240C, kSony20Bits, 1); // Send a command with 1 repeat. EXPECT_EQ( + "f40000d33" "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" "m600s600m1200s600m1200s600m600s600m600s16200" @@ -92,6 +98,7 @@ TEST(TestSendSony, SendWithDiffRepeats) { irsend.outputStr()); irsend.sendSony(0x240C, kSony20Bits, 3); // Send a command with 3 repeats. EXPECT_EQ( + "f40000d33" "m2400s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" "m600s600m600s600m1200s600m600s600m600s600m600s600m600s600m600s600" "m600s600m1200s600m1200s600m600s600m600s16200" diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Tcl_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Tcl_test.cpp new file mode 100644 index 000000000..249dcc637 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Tcl_test.cpp @@ -0,0 +1,384 @@ +// Copyright 2019 David Conran + +#include "ir_Tcl.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// General housekeeping +TEST(TestTcl112Ac, Housekeeping) { + ASSERT_EQ("TCL112AC", typeToString(TCL112AC)); + ASSERT_TRUE(hasACState(TCL112AC)); +} + +// Tests for decodeTcl112Ac(). + +// Decode a real Tcl112Ac A/C example from Issue #619 +TEST(TestDecodeTcl112Ac, DecodeRealExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Tcl112Ac A/C example from Issue #619 On.txt + uint16_t rawData[227] = { + 3030, 1658, 494, 1066, 494, 1068, 498, 320, 494, + 326, 498, 320, 494, 1068, 500, 320, 494, 332, + 494, 1068, 500, 1062, 496, 324, 492, 1044, 524, + 322, 492, 326, 498, 1062, 494, 1074, 494, 326, + 500, 1062, 496, 1066, 490, 328, 496, 322, 492, + 1070, 498, 322, 494, 332, 492, 1068, 498, 320, + 494, 326, 498, 320, 496, 324, 500, 320, 494, + 324, 490, 336, 500, 320, 496, 324, 490, 328, + 496, 322, 492, 328, 498, 322, 492, 326, 498, + 328, 496, 322, 492, 328, 498, 1064, 494, 326, + 498, 320, 494, 1066, 490, 330, 496, 330, 494, + 1066, 490, 1070, 498, 322, 492, 328, 498, 322, + 492, 326, 498, 322, 492, 332, 492, 1068, 498, + 1062, 494, 1066, 500, 318, 496, 324, 490, 328, + 496, 324, 492, 334, 490, 328, 496, 324, 492, + 328, 496, 322, 492, 328, 498, 320, 494, 1068, + 500, 326, 500, 320, 492, 326, 500, 320, 496, + 324, 500, 318, 496, 324, 490, 328, 496, 330, + 496, 324, 490, 328, 496, 324, 490, 328, 498, + 322, 492, 328, 498, 320, 492, 334, 492, 328, + 498, 322, 494, 326, 498, 320, 494, 324, 500, + 322, 492, 324, 490, 336, 498, 320, 494, 324, + 500, 320, 496, 324, 490, 328, 498, 322, 492, + 328, 496, 1070, 496, 1064, 492, 1070, 498, 322, + 494, 326, 500, 320, 494, 324, 500, 320, 494, + 324, 470}; // UNKNOWN CE60D6B9 + uint8_t expectedState[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, + 0x07, 0x40, 0x00, 0x00, 0x00, 0x80, 0x03}; + + irsend.sendRaw(rawData, 227, 38000); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TCL112AC, irsend.capture.decode_type); + EXPECT_EQ(kTcl112AcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + + IRTcl112Ac ac(0); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 24C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + ac.toString()); +} + +// Decode a synthetic Tcl112Ac A/C example from Issue #619 +TEST(TestDecodeTcl112Ac, DecodeSyntheticExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + + uint8_t expectedState[kTcl112AcStateLength] = {0x23, 0xCB, 0x26, 0x01, 0x00, + 0x24, 0x03, 0x07, 0x40, 0x00, + 0x00, 0x00, 0x80, 0x03}; + + irsend.sendTcl112Ac(expectedState); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_EQ(TCL112AC, irsend.capture.decode_type); + EXPECT_EQ(kTcl112AcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); +} + +TEST(TestTcl112AcClass, Temperature) { + const uint8_t temp16C[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x80, 0xCB}; + const uint8_t temp16point5C[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xEB}; + const uint8_t temp19point5C[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, + 0x0C, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xE8}; + const uint8_t temp31C[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xBC}; + IRTcl112Ac ac(0); + ac.setRaw(temp16C); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 16C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + ac.toString()); + ac.setRaw(temp16point5C); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 16.5C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + ac.toString()); + ac.setRaw(temp19point5C); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 19.5C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + ac.toString()); + ac.setRaw(temp31C); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 31C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + ac.toString()); + + ac.setTemp(kTcl112AcTempMin); + EXPECT_EQ(kTcl112AcTempMin, ac.getTemp()); + + ac.setTemp(kTcl112AcTempMin + 1); + EXPECT_EQ(kTcl112AcTempMin + 1, ac.getTemp()); + + ac.setTemp(kTcl112AcTempMax); + EXPECT_EQ(kTcl112AcTempMax, ac.getTemp()); + + ac.setTemp(kTcl112AcTempMin - 1); + EXPECT_EQ(kTcl112AcTempMin, ac.getTemp()); + + ac.setTemp(kTcl112AcTempMax + 0.5); + EXPECT_EQ(kTcl112AcTempMax, ac.getTemp()); + + ac.setTemp(23); + EXPECT_EQ(23, ac.getTemp()); + + ac.setTemp(27.4); + EXPECT_EQ(27, ac.getTemp()); + + ac.setTemp(22.5); + EXPECT_EQ(22.5, ac.getTemp()); + + ac.setTemp(25.6); + EXPECT_EQ(25.5, ac.getTemp()); + + ac.setTemp(0); + EXPECT_EQ(kTcl112AcTempMin, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kTcl112AcTempMax, ac.getTemp()); +} + +TEST(TestTcl112AcClass, OperatingMode) { + IRTcl112Ac ac(0); + ac.begin(); + + ac.setMode(kTcl112AcAuto); + EXPECT_EQ(kTcl112AcAuto, ac.getMode()); + + ac.setMode(kTcl112AcCool); + EXPECT_EQ(kTcl112AcCool, ac.getMode()); + + ac.setMode(kTcl112AcHeat); + EXPECT_EQ(kTcl112AcHeat, ac.getMode()); + + ac.setFan(kTcl112AcFanAuto); + ac.setMode(kTcl112AcFan); // Should set fan speed to High. + EXPECT_EQ(kTcl112AcFan, ac.getMode()); + EXPECT_EQ(kTcl112AcFanHigh, ac.getFan()); + + ac.setMode(kTcl112AcDry); + EXPECT_EQ(kTcl112AcDry, ac.getMode()); + + ac.setMode(kTcl112AcHeat - 1); + EXPECT_EQ(kTcl112AcAuto, ac.getMode()); + + ac.setMode(kTcl112AcCool); + EXPECT_EQ(kTcl112AcCool, ac.getMode()); + + ac.setMode(kTcl112AcAuto + 1); + EXPECT_EQ(kTcl112AcAuto, ac.getMode()); + + ac.setMode(kTcl112AcCool); + ac.setMode(255); + EXPECT_EQ(kTcl112AcAuto, ac.getMode()); + + ac.setMode(kTcl112AcCool); + ac.setMode(0); + EXPECT_EQ(kTcl112AcAuto, ac.getMode()); + + const uint8_t automode[] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x08, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x80, 0x48}; + ac.setRaw(automode); + EXPECT_EQ( + "Power: On, Mode: 8 (AUTO), Temp: 24C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + ac.toString()); +} + +TEST(TestTcl112AcClass, Power) { + IRTcl112Ac ac(0); + ac.begin(); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_EQ(false, ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_EQ(false, ac.getPower()); + + ac.on(); + EXPECT_TRUE(ac.getPower()); + + const uint8_t on[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x80, 0xCB}; + ac.setRaw(on); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 16C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + ac.toString()); + + const uint8_t off[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x03, + 0x07, 0x40, 0x00, 0x00, 0x00, 0x80, 0xCB}; + ac.setRaw(off); + EXPECT_EQ( + "Power: Off, Mode: 3 (COOL), Temp: 24C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + ac.toString()); +} + + +TEST(TestTcl112AcClass, Checksum) { + uint8_t temp16C[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x80, 0xCB}; + uint8_t temp31C[kTcl112AcStateLength] = { + 0x23, 0xCB, 0x26, 0x01, 0x00, 0x24, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xBC}; + IRTcl112Ac ac(0); + EXPECT_EQ(0xCB, ac.calcChecksum(temp16C)); + ac.setRaw(temp16C); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 16C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + ac.toString()); + ac.setRaw(temp31C); + EXPECT_EQ( + "Power: On, Mode: 3 (COOL), Temp: 31C, Fan: 0 (Auto), Econo: Off, " + "Health: Off, Light: On, Turbo: Off, Swing (H): Off, Swing (V): Off", + ac.toString()); + EXPECT_EQ(0xBC, ac.calcChecksum(temp31C)); + + EXPECT_TRUE(IRTcl112Ac::validChecksum(temp16C)); + EXPECT_TRUE(IRTcl112Ac::validChecksum(temp31C)); + EXPECT_TRUE(ac.validChecksum(temp31C)); + ac.setRaw(temp16C); + EXPECT_TRUE(ac.validChecksum(ac.getRaw())); + ac.setTemp(31); + EXPECT_TRUE(ac.validChecksum(ac.getRaw())); + EXPECT_EQ(0xBC, ac.calcChecksum(ac.getRaw())); +} + +TEST(TestTcl112AcClass, Econo) { + IRTcl112Ac ac(0); + ac.begin(); + + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); + ac.setEcono(false); + EXPECT_EQ(false, ac.getEcono()); + ac.setEcono(true); + EXPECT_TRUE(ac.getEcono()); +} + +TEST(TestTcl112AcClass, Health) { + IRTcl112Ac ac(0); + ac.begin(); + + ac.setHealth(true); + EXPECT_TRUE(ac.getHealth()); + ac.setHealth(false); + EXPECT_EQ(false, ac.getHealth()); + ac.setHealth(true); + EXPECT_TRUE(ac.getHealth()); +} + +TEST(TestTcl112AcClass, Light) { + IRTcl112Ac ac(0); + ac.begin(); + + ac.setLight(true); + EXPECT_TRUE(ac.getLight()); + ac.setLight(false); + EXPECT_EQ(false, ac.getLight()); + ac.setLight(true); + EXPECT_TRUE(ac.getLight()); +} + +TEST(TestTcl112AcClass, SwingHorizontal) { + IRTcl112Ac ac(0); + ac.begin(); + + ac.setSwingHorizontal(true); + EXPECT_TRUE(ac.getSwingHorizontal()); + ac.setSwingHorizontal(false); + EXPECT_EQ(false, ac.getSwingHorizontal()); + ac.setSwingHorizontal(true); + EXPECT_TRUE(ac.getSwingHorizontal()); +} + +TEST(TestTcl112AcClass, SwingVertical) { + IRTcl112Ac ac(0); + ac.begin(); + + ac.setSwingVertical(true); + EXPECT_TRUE(ac.getSwingVertical()); + ac.setSwingVertical(false); + EXPECT_EQ(false, ac.getSwingVertical()); + ac.setSwingVertical(true); + EXPECT_TRUE(ac.getSwingVertical()); +} + +TEST(TestTcl112AcClass, Turbo) { + IRTcl112Ac ac(0); + ac.begin(); + + ac.setFan(kTcl112AcFanLow); + ac.setSwingHorizontal(false); + + ac.setTurbo(false); + EXPECT_FALSE(ac.getTurbo()); + EXPECT_FALSE(ac.getSwingVertical()); + EXPECT_EQ(kTcl112AcFanLow, ac.getFan()); + + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + EXPECT_TRUE(ac.getSwingVertical()); + EXPECT_EQ(kTcl112AcFanHigh, ac.getFan()); + + ac.setTurbo(false); + EXPECT_FALSE(ac.getTurbo()); + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); +} + +TEST(TestTcl112AcClass, FanSpeed) { + IRTcl112Ac ac(0); + ac.begin(); + + // Unexpected value should default to Auto. + ac.setFan(255); + EXPECT_EQ(kTcl112AcFanAuto, ac.getFan()); + + ac.setFan(kTcl112AcFanLow); + EXPECT_EQ(kTcl112AcFanLow, ac.getFan()); + ac.setFan(kTcl112AcFanMed); + EXPECT_EQ(kTcl112AcFanMed, ac.getFan()); + ac.setFan(kTcl112AcFanHigh); + EXPECT_EQ(kTcl112AcFanHigh, ac.getFan()); + ac.setFan(kTcl112AcFanAuto); + EXPECT_EQ(kTcl112AcFanAuto, ac.getFan()); + + // Beyond High should default to Auto. + ac.setFan(kTcl112AcFanHigh + 1); + EXPECT_EQ(kTcl112AcFanAuto, ac.getFan()); +} diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Teco_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Teco_test.cpp new file mode 100644 index 000000000..6b03a671d --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Teco_test.cpp @@ -0,0 +1,358 @@ +// Copyright 2019 David Conran + +#include "ir_Teco.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// General housekeeping +TEST(TestTeco, Housekeeping) { + ASSERT_EQ("TECO", typeToString(TECO)); + ASSERT_FALSE(hasACState(TECO)); // Uses uint64_t, not uint8_t*. +} + +// Tests for sendTeco() + +// Test sending typical data only. +TEST(TestSendTeco, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendTeco(0x250002BC9); + EXPECT_EQ( + "f38000d50" + "m9000s4440" + "m620s1650m620s580m620s580m620s1650m620s580m620s580m620s1650m620s1650" + "m620s1650m620s1650m620s580m620s1650m620s580m620s1650m620s580m620s580" + "m620s580m620s580m620s580m620s580m620s580m620s580m620s580m620s580" + "m620s580m620s580m620s580m620s580m620s1650m620s580m620s1650m620s580" + "m620s580m620s1650m620s580" + "m620s100000", + irsend.outputStr()); +} + +// Test sending typical data with repeats. +TEST(TestSendTeco, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendTeco(0x250002BC9, kTecoBits, 2); // two repeats. + EXPECT_EQ( + "f38000d50" + "m9000s4440" + "m620s1650m620s580m620s580m620s1650m620s580m620s580m620s1650m620s1650" + "m620s1650m620s1650m620s580m620s1650m620s580m620s1650m620s580m620s580" + "m620s580m620s580m620s580m620s580m620s580m620s580m620s580m620s580" + "m620s580m620s580m620s580m620s580m620s1650m620s580m620s1650m620s580" + "m620s580m620s1650m620s580" + "m620s100000" + "m9000s4440" + "m620s1650m620s580m620s580m620s1650m620s580m620s580m620s1650m620s1650" + "m620s1650m620s1650m620s580m620s1650m620s580m620s1650m620s580m620s580" + "m620s580m620s580m620s580m620s580m620s580m620s580m620s580m620s580" + "m620s580m620s580m620s580m620s580m620s1650m620s580m620s1650m620s580" + "m620s580m620s1650m620s580" + "m620s100000" + "m9000s4440" + "m620s1650m620s580m620s580m620s1650m620s580m620s580m620s1650m620s1650" + "m620s1650m620s1650m620s580m620s1650m620s580m620s1650m620s580m620s580" + "m620s580m620s580m620s580m620s580m620s580m620s580m620s580m620s580" + "m620s580m620s580m620s580m620s580m620s1650m620s580m620s1650m620s580" + "m620s580m620s1650m620s580" + "m620s100000", + irsend.outputStr()); +} + + +// Tests for IRTeco class. + +TEST(TestTecoACClass, Power) { + IRTecoAc ac(0); + ac.begin(); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_EQ(false, ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_EQ(false, ac.getPower()); + + ac.on(); + EXPECT_TRUE(ac.getPower()); +} + +TEST(TestTecoACClass, OperatingMode) { + IRTecoAc ac(0); + ac.begin(); + + ac.setMode(kTecoAuto); + EXPECT_EQ(kTecoAuto, ac.getMode()); + + ac.setMode(kTecoCool); + EXPECT_EQ(kTecoCool, ac.getMode()); + + ac.setMode(kTecoHeat); + EXPECT_EQ(kTecoHeat, ac.getMode()); + + ac.setMode(kTecoFan); + EXPECT_EQ(kTecoFan, ac.getMode()); + + ac.setMode(kTecoDry); + EXPECT_EQ(kTecoDry, ac.getMode()); + + ac.setMode(kTecoAuto - 1); + EXPECT_EQ(kTecoAuto, ac.getMode()); + + ac.setMode(kTecoCool); + EXPECT_EQ(kTecoCool, ac.getMode()); + + ac.setMode(kTecoHeat + 1); + EXPECT_EQ(kTecoAuto, ac.getMode()); + + ac.setMode(255); + EXPECT_EQ(kTecoAuto, ac.getMode()); +} + +TEST(TestTecoACClass, Temperature) { + IRTecoAc ac(0); + ac.begin(); + + ac.setTemp(kTecoMinTemp); + EXPECT_EQ(kTecoMinTemp, ac.getTemp()); + + ac.setTemp(kTecoMinTemp + 1); + EXPECT_EQ(kTecoMinTemp + 1, ac.getTemp()); + + ac.setTemp(kTecoMaxTemp); + EXPECT_EQ(kTecoMaxTemp, ac.getTemp()); + + ac.setTemp(kTecoMinTemp - 1); + EXPECT_EQ(kTecoMinTemp, ac.getTemp()); + + ac.setTemp(kTecoMaxTemp + 1); + EXPECT_EQ(kTecoMaxTemp, ac.getTemp()); + + ac.setTemp(23); + EXPECT_EQ(23, ac.getTemp()); + + ac.setTemp(0); + EXPECT_EQ(kTecoMinTemp, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kTecoMaxTemp, ac.getTemp()); +} + +TEST(TestTecoACClass, FanSpeed) { + IRTecoAc ac(0); + ac.begin(); + ac.setFan(kTecoFanLow); + + ac.setFan(kTecoFanAuto); + EXPECT_EQ(kTecoFanAuto, ac.getFan()); + + ac.setFan(kTecoFanLow); + EXPECT_EQ(kTecoFanLow, ac.getFan()); + ac.setFan(kTecoFanMed); + EXPECT_EQ(kTecoFanMed, ac.getFan()); + ac.setFan(kTecoFanHigh); + EXPECT_EQ(kTecoFanHigh, ac.getFan()); + + ac.setFan(kTecoFanHigh); + EXPECT_EQ(kTecoFanHigh, ac.getFan()); +} + +TEST(TestTecoACClass, Swing) { + IRTecoAc ac(0); + ac.begin(); + + ac.setSwing(true); + EXPECT_TRUE(ac.getSwing()); + + ac.setSwing(false); + EXPECT_EQ(false, ac.getSwing()); + + ac.setSwing(true); + EXPECT_TRUE(ac.getSwing()); +} + +TEST(TestTecoACClass, Sleep) { + IRTecoAc ac(0); + ac.begin(); + + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + + ac.setSleep(false); + EXPECT_EQ(false, ac.getSleep()); + + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); +} + +TEST(TestTecoACClass, MessageConstuction) { + IRTecoAc ac(0); + + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (Auto), Sleep: Off, " + "Swing: Off", + ac.toString()); + ac.setPower(true); + ac.setMode(kTecoCool); + ac.setTemp(21); + ac.setFan(kTecoFanHigh); + ac.setSwing(false); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), Sleep: Off, " + "Swing: Off", + ac.toString()); + ac.setSwing(true); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 3 (High), Sleep: Off, " + "Swing: On", + ac.toString()); + ac.setSwing(false); + ac.setFan(kTecoFanLow); + ac.setSleep(true); + ac.setMode(kTecoHeat); + EXPECT_EQ( + "Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 1 (Low), Sleep: On, " + "Swing: Off", + ac.toString()); + ac.setSleep(false); + EXPECT_EQ( + "Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 1 (Low), Sleep: Off, " + "Swing: Off", + ac.toString()); + ac.setTemp(25); + EXPECT_EQ( + "Power: On, Mode: 4 (HEAT), Temp: 25C, Fan: 1 (Low), Sleep: Off, " + "Swing: Off", + ac.toString()); +} + +TEST(TestTecoACClass, ReconstructKnownMessage) { + IRTecoAc ac(0); + + const uint64_t expected = 0x250002BC9; + ASSERT_FALSE(ac.getRaw() == expected); + ac.setPower(true); + ac.setMode(kTecoCool); + ac.setTemp(27); + ac.setFan(kTecoFanAuto); + ac.setSleep(true); + ac.setSwing(true); + EXPECT_EQ(expected, ac.getRaw()); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 27C, Fan: 0 (Auto), Sleep: On, " + "Swing: On", + ac.toString()); +} + +// Tests for decodeTeco(). + +// Decode normal "synthetic" messages. +TEST(TestDecodeTeco, NormalDecodeWithStrict) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // With the specific decoder. + uint64_t expectedState = kTecoReset; + irsend.reset(); + irsend.sendTeco(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeTeco(&irsend.capture, kTecoBits, true)); + EXPECT_EQ(TECO, irsend.capture.decode_type); + EXPECT_EQ(kTecoBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ(expectedState, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + + // With the all the decoders. + irsend.reset(); + irsend.sendTeco(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(TECO, irsend.capture.decode_type); + EXPECT_EQ(kTecoBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ(expectedState, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + + IRTecoAc ac(0); + ac.begin(); + ac.setRaw(irsend.capture.value); + EXPECT_EQ( + "Power: Off, Mode: 0 (AUTO), Temp: 16C, Fan: 0 (Auto), Sleep: Off, " + "Swing: Off", + ac.toString()); +} + +// Decode a real message from Raw Data. +TEST(TestDecodeTeco, RealNormalExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRTecoAc ac(0); + irsend.begin(); + + uint16_t rawData1[73] = { + 9076, 4442, 670, 1620, 670, 516, 670, 516, 666, 1626, 670, 516, + 664, 520, 666, 1626, 666, 1626, 664, 1626, 666, 1626, 666, 520, + 666, 1626, 666, 520, 666, 1626, 666, 520, 666, 516, 670, 514, + 670, 516, 666, 520, 670, 516, 666, 520, 666, 516, 672, 514, 670, + 516, 666, 520, 666, 516, 672, 514, 670, 516, 666, 1624, 666, 520, + 666, 1626, 666, 520, 666, 516, 672, 1620, 670, 516, 670}; + uint64_t expected1 = 0b01001010000000000000010101111001001; // 0x250002BC9 + irsend.reset(); + irsend.sendRaw(rawData1, 73, 38); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(TECO, irsend.capture.decode_type); + EXPECT_EQ(kTecoBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ(expected1, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + ac.begin(); + ac.setRaw(irsend.capture.value); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 27C, Fan: 0 (Auto), Sleep: On, " + "Swing: On", + ac.toString()); + + uint16_t rawData2[73] = { + 9048, 4472, 636, 548, 636, 1654, 638, 546, 642, 1650, 642, 546, 638, + 1654, 638, 1654, 638, 546, 638, 1654, 636, 546, 642, 1650, 640, 548, + 636, 548, 638, 546, 636, 546, 642, 542, 642, 546, 638, 546, 638, 546, + 636, 548, 642, 542, 642, 546, 636, 548, 636, 546, 642, 542, 642, 546, + 638, 546, 638, 546, 636, 1654, 642, 542, 642, 1650, 642, 546, 638, 546, + 638, 1654, 638, 546, 642}; // TECO 25000056A + uint64_t expected2 = 0b01001010000000000000000010101101010; // 0x25000056A + irsend.reset(); + irsend.sendRaw(rawData2, 73, 38); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(TECO, irsend.capture.decode_type); + EXPECT_EQ(kTecoBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ(expected2, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + ac.begin(); + ac.setRaw(irsend.capture.value); + EXPECT_EQ( + "Power: On, Mode: 2 (DRY), Temp: 21C, Fan: 2 (Med), Sleep: Off, " + "Swing: On", + ac.toString()); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Toshiba_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Toshiba_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Toshiba_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Toshiba_test.cpp index b5e1e07a9..d74866f92 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Toshiba_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Toshiba_test.cpp @@ -18,6 +18,7 @@ TEST(TestSendToshibaAC, SendDataOnly) { irsend.reset(); irsend.sendToshibaAC(toshiba_code); EXPECT_EQ( + "f38000d50" "m4400s4300" "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" @@ -54,6 +55,7 @@ TEST(TestSendToshibaAC, SendWithRepeats) { irsend.sendToshibaAC(toshiba_code, kToshibaACStateLength, 0); EXPECT_EQ( + "f38000d50" "m4400s4300" "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" @@ -70,6 +72,7 @@ TEST(TestSendToshibaAC, SendWithRepeats) { irsend.reset(); irsend.sendToshibaAC(toshiba_code, kToshibaACStateLength, 2); EXPECT_EQ( + "f38000d50" "m4400s4300" "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" @@ -122,6 +125,7 @@ TEST(TestSendToshibaAC, SendUnexpectedSizes) { irsend.reset(); irsend.sendToshibaAC(toshiba_long_code, kToshibaACStateLength + 1); ASSERT_EQ( + "f38000d50" "m4400s4300" "m543s472m543s472m543s472m543s472m543s472m543s472m543s472m543s1623" "m543s472m543s472m543s472m543s472m543s472m543s472m543s1623m543s472" @@ -380,6 +384,7 @@ TEST(TestToshibaACClass, MessageConstuction) { irsend.reset(); irsend.sendToshibaAC(toshiba.getRaw()); EXPECT_EQ( + "f38000d50" "m4400s4300" "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" @@ -415,6 +420,7 @@ TEST(TestToshibaACClass, MessageConstuction) { irsend.reset(); irsend.sendToshibaAC(toshiba.getRaw()); EXPECT_EQ( + "f38000d50" "m4400s4300" "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" @@ -450,6 +456,7 @@ TEST(TestToshibaACClass, MessageConstuction) { irsend.reset(); irsend.sendToshibaAC(toshiba.getRaw()); EXPECT_EQ( + "f38000d50" "m4400s4300" "m543s1623m543s1623m543s1623m543s1623m543s472m543s472m543s1623m543s472" "m543s472m543s472m543s472m543s472m543s1623m543s1623m543s472m543s1623" diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Vestel_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Vestel_test.cpp new file mode 100644 index 000000000..077a0a25e --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Vestel_test.cpp @@ -0,0 +1,513 @@ +// Copyright 2019 David Conran + +#include "ir_Vestel.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendVestelAc() + +// Test sending typical data only. +TEST(TestSendVestelAc, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendVestelAc(0x0F00D9001FEF201ULL); + EXPECT_EQ( + "f38000d50" + "m3110s9066" + "m520s1535m520s480m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s1535m520s480m520s480m520s1535m520s1535m520s1535m520s1535" + "m520s480m520s1535m520s1535m520s1535m520s1535m520s1535m520s1535m520s1535" + "m520s1535m520s480m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s480m520s480m520s480m520s1535m520s480m520s480m520s1535" + "m520s1535m520s480m520s1535m520s1535m520s480m520s480m520s480m520s480" + "m520s480m520s480m520s480m520s480m520s1535m520s1535m520s1535m520s1535" + "m520s100000", + irsend.outputStr()); +} + +// Test sending typical data with repeats. +TEST(TestSendVestelAc, SendWithRepeats) { + IRsendTest irsend(0); + irsend.begin(); + + irsend.reset(); + irsend.sendVestelAc(0x0F00D9001FEF201ULL, kVestelAcBits, 2); // two repeats. + EXPECT_EQ( + "f38000d50" + "m3110s9066" + "m520s1535m520s480m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s1535m520s480m520s480m520s1535m520s1535m520s1535m520s1535" + "m520s480m520s1535m520s1535m520s1535m520s1535m520s1535m520s1535m520s1535" + "m520s1535m520s480m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s480m520s480m520s480m520s1535m520s480m520s480m520s1535" + "m520s1535m520s480m520s1535m520s1535m520s480m520s480m520s480m520s480" + "m520s480m520s480m520s480m520s480m520s1535m520s1535m520s1535m520s1535" + "m520s100000" + "m3110s9066" + "m520s1535m520s480m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s1535m520s480m520s480m520s1535m520s1535m520s1535m520s1535" + "m520s480m520s1535m520s1535m520s1535m520s1535m520s1535m520s1535m520s1535" + "m520s1535m520s480m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s480m520s480m520s480m520s1535m520s480m520s480m520s1535" + "m520s1535m520s480m520s1535m520s1535m520s480m520s480m520s480m520s480" + "m520s480m520s480m520s480m520s480m520s1535m520s1535m520s1535m520s1535" + "m520s100000" + "m3110s9066" + "m520s1535m520s480m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s1535m520s480m520s480m520s1535m520s1535m520s1535m520s1535" + "m520s480m520s1535m520s1535m520s1535m520s1535m520s1535m520s1535m520s1535" + "m520s1535m520s480m520s480m520s480m520s480m520s480m520s480m520s480" + "m520s480m520s480m520s480m520s480m520s1535m520s480m520s480m520s1535" + "m520s1535m520s480m520s1535m520s1535m520s480m520s480m520s480m520s480" + "m520s480m520s480m520s480m520s480m520s1535m520s1535m520s1535m520s1535" + "m520s100000", + irsend.outputStr()); +} + +// Tests for IRVestelAc class. + +TEST(TestVestelAcClass, Power) { + IRVestelAc ac(0); + ac.begin(); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.setPower(false); + EXPECT_EQ(false, ac.getPower()); + + ac.setPower(true); + EXPECT_TRUE(ac.getPower()); + + ac.off(); + EXPECT_EQ(false, ac.getPower()); + + ac.on(); + EXPECT_TRUE(ac.getPower()); + EXPECT_FALSE(ac.isTimeCommand()); +} + +TEST(TestVestelAcClass, OperatingMode) { + IRVestelAc ac(0); + ac.begin(); + + ac.setMode(kVestelAcAuto); + EXPECT_EQ(kVestelAcAuto, ac.getMode()); + + ac.setMode(kVestelAcCool); + EXPECT_EQ(kVestelAcCool, ac.getMode()); + + ac.setMode(kVestelAcHeat); + EXPECT_EQ(kVestelAcHeat, ac.getMode()); + + ac.setMode(kVestelAcFan); + EXPECT_EQ(kVestelAcFan, ac.getMode()); + + ac.setMode(kVestelAcDry); + EXPECT_EQ(kVestelAcDry, ac.getMode()); + + ac.setMode(kVestelAcAuto - 1); + EXPECT_EQ(kVestelAcAuto, ac.getMode()); + + ac.setMode(kVestelAcCool); + EXPECT_EQ(kVestelAcCool, ac.getMode()); + + ac.setMode(kVestelAcHeat + 1); + EXPECT_EQ(kVestelAcAuto, ac.getMode()); + + ac.setMode(255); + EXPECT_EQ(kVestelAcAuto, ac.getMode()); + EXPECT_FALSE(ac.isTimeCommand()); +} + +TEST(TestVestelAcClass, Temperature) { + IRVestelAc ac(0); + ac.begin(); + + ac.setTemp(kVestelAcMinTempC); + EXPECT_EQ(kVestelAcMinTempC, ac.getTemp()); + + ac.setTemp(kVestelAcMinTempC + 1); + EXPECT_EQ(kVestelAcMinTempC + 1, ac.getTemp()); + + ac.setTemp(kVestelAcMaxTemp); + EXPECT_EQ(kVestelAcMaxTemp, ac.getTemp()); + + ac.setTemp(kVestelAcMinTempC - 1); + EXPECT_EQ(kVestelAcMinTempC, ac.getTemp()); + + ac.setTemp(kVestelAcMaxTemp + 1); + EXPECT_EQ(kVestelAcMaxTemp, ac.getTemp()); + + ac.setTemp(23); + EXPECT_EQ(23, ac.getTemp()); + + ac.setTemp(0); + EXPECT_EQ(kVestelAcMinTempC, ac.getTemp()); + + ac.setTemp(255); + EXPECT_EQ(kVestelAcMaxTemp, ac.getTemp()); + EXPECT_FALSE(ac.isTimeCommand()); +} + +TEST(TestVestelAcClass, FanSpeed) { + IRVestelAc ac(0); + ac.begin(); + ac.setFan(kVestelAcFanLow); + + ac.setFan(kVestelAcFanAuto); + EXPECT_EQ(kVestelAcFanAuto, ac.getFan()); + + ac.setFan(kVestelAcFanLow); + EXPECT_EQ(kVestelAcFanLow, ac.getFan()); + ac.setFan(kVestelAcFanMed); + EXPECT_EQ(kVestelAcFanMed, ac.getFan()); + ac.setFan(kVestelAcFanHigh); + EXPECT_EQ(kVestelAcFanHigh, ac.getFan()); + + ac.setFan(kVestelAcFanHigh); + EXPECT_EQ(kVestelAcFanHigh, ac.getFan()); + EXPECT_FALSE(ac.isTimeCommand()); +} + +TEST(TestVestelAcClass, Swing) { + IRVestelAc ac(0); + ac.begin(); + + ac.setSwing(true); + EXPECT_TRUE(ac.getSwing()); + + ac.setSwing(false); + EXPECT_EQ(false, ac.getSwing()); + + ac.setSwing(true); + EXPECT_TRUE(ac.getSwing()); + EXPECT_FALSE(ac.isTimeCommand()); +} + +TEST(TestVestelAcClass, Ion) { + IRVestelAc ac(0); + ac.begin(); + + ac.setIon(true); + EXPECT_TRUE(ac.getIon()); + + ac.setIon(false); + EXPECT_EQ(false, ac.getIon()); + + ac.setIon(true); + EXPECT_TRUE(ac.getIon()); + EXPECT_FALSE(ac.isTimeCommand()); +} + +TEST(TestVestelAcClass, Turbo) { + IRVestelAc ac(0); + ac.begin(); + + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + + ac.setTurbo(false); + EXPECT_EQ(false, ac.getTurbo()); + + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + EXPECT_FALSE(ac.isTimeCommand()); +} + +TEST(TestVestelAcClass, Sleep) { + IRVestelAc ac(0); + ac.begin(); + + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + + ac.setSleep(false); + EXPECT_EQ(false, ac.getSleep()); + + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + EXPECT_FALSE(ac.isTimeCommand()); +} + +TEST(TestVestelAcClass, Time) { + IRVestelAc ac(0); + ac.begin(); + + ac.setTime(0); + EXPECT_EQ(0, ac.getTime()); + EXPECT_TRUE(ac.isTimeCommand()); + + ac.setTime(1); + EXPECT_EQ(1, ac.getTime()); + + ac.setTime(1234); + EXPECT_EQ(1234, ac.getTime()); + + ac.setTime(23 * 60 + 59); + EXPECT_EQ(23 * 60 + 59, ac.getTime()); +} + +TEST(TestVestelAcClass, OnTimer) { + IRVestelAc ac(0); + ac.begin(); + + ac.setOnTimer(0); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_TRUE(ac.isTimeCommand()); + + ac.setOnTimer(1); + EXPECT_EQ(0, ac.getOnTimer()); + + ac.setOnTimer(10); + EXPECT_EQ(10, ac.getOnTimer()); + + ac.setOnTimer(12 * 60 + 15); // we will round down to 10 min increments. + EXPECT_EQ(12 * 60 + 10, ac.getOnTimer()); + + ac.setOnTimer(23 * 60 + 50); + EXPECT_EQ(23 * 60 + 50, ac.getOnTimer()); +} + +TEST(TestVestelAcClass, OffTimer) { + IRVestelAc ac(0); + ac.begin(); + + ac.setOffTimer(0); + EXPECT_EQ(0, ac.getOffTimer()); + EXPECT_TRUE(ac.isTimeCommand()); + + ac.setOffTimer(1); + EXPECT_EQ(0, ac.getOffTimer()); + + ac.setOffTimer(10); + EXPECT_EQ(10, ac.getOffTimer()); + + ac.setOffTimer(12 * 60 + 15); // we will round down to 10 min increments. + EXPECT_EQ(12 * 60 + 10, ac.getOffTimer()); + + ac.setOffTimer(23 * 60 + 50); + EXPECT_EQ(23 * 60 + 50, ac.getOffTimer()); +} + +TEST(TestVestelAcClass, Timer) { + IRVestelAc ac(0); + ac.begin(); + + ac.setTimer(0); + EXPECT_EQ(0, ac.getTimer()); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_TRUE(ac.isTimeCommand()); + + ac.setTimer(10); + EXPECT_EQ(10, ac.getTimer()); + EXPECT_EQ(0, ac.getOnTimer()); + + ac.setTimer(12 * 60 + 15); // we will round down to 10 min increments. + EXPECT_EQ(12 * 60 + 10, ac.getTimer()); + EXPECT_EQ(0, ac.getOnTimer()); + + ac.setTimer(23 * 60 + 50); + EXPECT_EQ(23 * 60 + 50, ac.getTimer()); + EXPECT_EQ(0, ac.getOnTimer()); +} + +TEST(TestVestelAcClass, MessageConstuction) { + IRVestelAc ac(0); + + EXPECT_EQ( + "Power: On, Mode: 0 (AUTO), Temp: 25C, Fan: 13 (AUTO HOT), Sleep: Off, " + "Turbo: Off, Ion: Off, Swing: Off", + ac.toString()); + ac.setMode(kVestelAcCool); + ac.setTemp(21); + ac.setFan(kVestelAcFanHigh); + EXPECT_FALSE(ac.isTimeCommand()); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 11 (HIGH), Sleep: Off, " + "Turbo: Off, Ion: Off, Swing: Off", + ac.toString()); + ac.setSwing(true); + ac.setIon(true); + ac.setTurbo(true); + EXPECT_FALSE(ac.isTimeCommand()); + EXPECT_EQ( + "Power: On, Mode: 1 (COOL), Temp: 21C, Fan: 11 (HIGH), Sleep: Off, " + "Turbo: On, Ion: On, Swing: On", + ac.toString()); + + // Now change a few already set things. + ac.setSleep(true); + ac.setMode(kVestelAcHeat); + EXPECT_EQ( + "Power: On, Mode: 4 (HEAT), Temp: 21C, Fan: 11 (HIGH), Sleep: On, " + "Turbo: Off, Ion: On, Swing: On", + ac.toString()); + EXPECT_FALSE(ac.isTimeCommand()); + + ac.setTemp(25); + ac.setPower(false); + EXPECT_EQ( + "Power: Off, Mode: 4 (HEAT), Temp: 25C, Fan: 11 (HIGH), Sleep: On, " + "Turbo: Off, Ion: On, Swing: On", + ac.toString()); + EXPECT_FALSE(ac.isTimeCommand()); + + // Check that the checksum is valid. + EXPECT_TRUE(IRVestelAc::validChecksum(ac.getRaw())); + ac.setTime(23 * 60 + 59); + EXPECT_TRUE(ac.isTimeCommand()); + EXPECT_EQ( + "Time: 23:59, Timer: Off, On Timer: Off, Off Timer: Off", + ac.toString()); + ac.setTimer(8 * 60 + 0); + EXPECT_TRUE(ac.isTimeCommand()); + EXPECT_EQ( + "Time: 23:59, Timer: 8:00, On Timer: Off, Off Timer: Off", + ac.toString()); + ac.setOnTimer(7 * 60 + 40); + EXPECT_EQ( + "Time: 23:59, Timer: Off, On Timer: 7:40, Off Timer: Off", + ac.toString()); + ac.setOffTimer(17 * 60 + 10); + EXPECT_EQ( + "Time: 23:59, Timer: Off, On Timer: 7:40, Off Timer: 17:10", + ac.toString()); + ac.setTimer(8 * 60 + 0); + EXPECT_EQ( + "Time: 23:59, Timer: 8:00, On Timer: Off, Off Timer: Off", + ac.toString()); + ac.setTimer(0); + EXPECT_EQ( + "Time: 23:59, Timer: Off, On Timer: Off, Off Timer: Off", + ac.toString()); + ac.on(); + EXPECT_FALSE(ac.isTimeCommand()); + EXPECT_EQ( + "Power: On, Mode: 4 (HEAT), Temp: 25C, Fan: 11 (HIGH), Sleep: On, " + "Turbo: Off, Ion: On, Swing: On", + ac.toString()); +} + +// Tests for decodeVestelAc(). + +// Decode normal "synthetic" messages. +TEST(TestDecodeVestelAc, NormalDecodeWithStrict) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // With the specific decoder. + uint64_t expectedState = 0x0F00D9001FEF201ULL; + irsend.reset(); + irsend.sendVestelAc(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeVestelAc(&irsend.capture, kVestelAcBits, true)); + EXPECT_EQ(VESTEL_AC, irsend.capture.decode_type); + EXPECT_EQ(kVestelAcBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ(expectedState, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + + // With the all the decoders. + irsend.reset(); + irsend.sendVestelAc(expectedState); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(VESTEL_AC, irsend.capture.decode_type); + EXPECT_EQ(kVestelAcBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ(expectedState, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + + IRVestelAc ac(0); + ac.begin(); + ac.setRaw(irsend.capture.value); + EXPECT_EQ( + "Power: On, Mode: 0 (AUTO), Temp: 25C, Fan: 13 (AUTO HOT), Sleep: Off, " + "Turbo: Off, Ion: Off, Swing: Off", + ac.toString()); +} + +// Decode a real message from Raw Data. +TEST(TestDecodeVestelAc, RealNormalExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRVestelAc ac(0); + irsend.begin(); + + uint16_t rawData[115] = { + 3098, 9080, 548, 1538, 526, 492, 526, 468, 524, 468, 526, 468, + 550, 466, 526, 466, 526, 504, 540, 466, 526, 1538, 526, 466, + 526, 466, 552, 1540, 522, 466, 526, 492, 526, 544, 526, 1536, + 526, 1536, 552, 1536, 526, 1536, 552, 1536, 552, 1536, 526, 1536, + 526, 1574, 542, 1536, 526, 492, 526, 466, 526, 494, 524, 468, + 524, 468, 526, 492, 526, 502, 540, 468, 524, 494, 524, 468, + 526, 468, 524, 468, 526, 492, 526, 468, 524, 520, 524, 1538, + 524, 468, 524, 468, 524, 468, 524, 468, 524, 468, 524, 1538, + 524, 506, 538, 468, 524, 468, 524, 1538, 524, 468, 550, 1538, + 550, 1538, 524, 1538, 534, 1528, 544}; // VESTEL_AC + irsend.reset(); + irsend.sendRaw(rawData, 115, 38); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(VESTEL_AC, irsend.capture.decode_type); + EXPECT_EQ(kVestelAcBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ(0xF4410001FF1201ULL, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + ac.begin(); + ac.setRaw(irsend.capture.value); + EXPECT_EQ( + "Power: On, Mode: 4 (HEAT), Temp: 16C, Fan: 1 (AUTO), Sleep: Off, " + "Turbo: Off, Ion: On, Swing: Off", + ac.toString()); +} + +TEST(TestDecodeVestelAc, RealTimerExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + IRVestelAc ac(0); + irsend.begin(); + + uint16_t rawData[115] = { + 3022, 9080, 546, 1536, 526, 466, 526, 492, 526, 468, 526, 492, + 524, 468, 524, 494, 524, 504, 540, 492, 524, 1538, 526, 468, + 524, 492, 526, 466, 552, 1536, 526, 1536, 526, 1570, 542, 492, + 524, 1538, 550, 1538, 524, 1536, 526, 494, 524, 466, 526, 468, + 524, 1574, 540, 1536, 550, 1536, 526, 468, 550, 1536, 526, 492, + 526, 468, 524, 492, 526, 518, 526, 1536, 552, 1536, 550, 1536, + 526, 494, 550, 1538, 526, 492, 524, 1538, 526, 504, 540, 466, + 526, 1536, 526, 1536, 526, 468, 550, 1538, 524, 468, 524, 1538, + 550, 1574, 540, 468, 550, 1538, 526, 492, 524, 468, 526, 466, + 526, 468, 524, 494, 524, 468, 546}; // VESTEL_AC 2D6570B8EE201 + irsend.reset(); + irsend.sendRaw(rawData, 115, 38); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(VESTEL_AC, irsend.capture.decode_type); + EXPECT_EQ(kVestelAcBits, irsend.capture.bits); + EXPECT_FALSE(irsend.capture.repeat); + EXPECT_EQ(0x2D6570B8EE201ULL, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + ac.begin(); + ac.setRaw(irsend.capture.value); + EXPECT_EQ( + "Time: 5:45, Timer: Off, On Timer: 14:00, Off Timer: 23:00", + ac.toString()); +} + +// General housekeeping +TEST(TestDecodeVestelAc, Housekeeping) { + ASSERT_EQ("VESTEL_AC", typeToString(VESTEL_AC)); + ASSERT_FALSE(hasACState(VESTEL_AC)); // Uses uint64_t, not uint8_t*. +} diff --git a/lib/IRremoteESP8266-2.6.0/test/ir_Whirlpool_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Whirlpool_test.cpp new file mode 100644 index 000000000..e282989f0 --- /dev/null +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Whirlpool_test.cpp @@ -0,0 +1,585 @@ +// Copyright 2018 David Conran + +#include "ir_Whirlpool.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendWhirlpoolAC(). + +// Test sending typical data only. +TEST(TestSendWhirlpoolAC, SendDataOnly) { + IRsendTest irsend(0); + irsend.begin(); + uint8_t data[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + + irsend.sendWhirlpoolAC(data); + EXPECT_EQ( + "f38000d50" + "m8950s4484" + "m597s1649m597s1649m597s533m597s533m597s533m597s533m597s533m597s1649" + "m597s533m597s1649m597s1649m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s1649m597s533m597s533m597s533" + "m597s1649m597s533m597s533m597s533m597s1649m597s1649m597s1649m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s7920" + "m597s1649m597s533m597s533m597s533m597s1649m597s533m597s533m597s1649" + "m597s1649m597s1649m597s1649m597s1649m597s1649m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s1649m597s1649m597s1649m597s1649m597s533m597s1649m597s1649m597s1649" + "m597s7920" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s1649m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s533m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s533m597s1649m597s533m597s533m597s533m597s533m597s533m597s533" + "m597s100000", + irsend.outputStr()); +} + +// Tests for decodeWhirlpoolAC(). +// Decode normal WhirlpoolAC messages. +TEST(TestDecodeWhirlpoolAC, SyntheticDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Synthesised Normal WhirlpoolAC message. + irsend.reset(); + uint8_t expectedState[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + irsend.sendWhirlpoolAC(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(WHIRLPOOL_AC, irsend.capture.decode_type); + EXPECT_EQ(kWhirlpoolAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + IRWhirlpoolAc ac(0); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Model: 1 (DG11J13A), Power toggle: Off, Mode: 1 (AUTO), Temp: 25C, " + "Fan: 0 (AUTO), Swing: Off, Light: On, Clock: 17:31, On Timer: Off, " + "Off Timer: Off, Sleep: Off, Super: Off, Command: 2 (TEMP)", + ac.toString()); +} + +TEST(TestDecodeWhirlpoolAC, Real26CFanAutoCoolingSwingOnClock1918) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + uint8_t expectedState[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x80, 0x82, 0x00, 0x00, 0x93, 0x12, 0x40, 0x00, 0x00, + 0x00, 0x00, 0xC3, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x07}; + irsend.sendWhirlpoolAC(expectedState); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(WHIRLPOOL_AC, irsend.capture.decode_type); + EXPECT_EQ(kWhirlpoolAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + IRWhirlpoolAc ac(0); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Model: 1 (DG11J13A), Power toggle: Off, Mode: 2 (COOL), Temp: 26C, " + "Fan: 0 (AUTO), Swing: On, Light: On, Clock: 19:18, On Timer: Off, " + "Off Timer: Off, Sleep: Off, Super: Off, Command: 7 (SWING)", + ac.toString()); +} + +TEST(TestDecodeWhirlpoolAC, RealTimerExample) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + irsend.reset(); + // Dehumidify timer on 7:40 off 8:05 + uint16_t rawData[343] = { + 9092, 4556, 604, 1664, 604, 1674, 630, 514, 630, 518, 628, 522, + 604, 550, 628, 530, 602, 1680, 630, 508, 630, 1644, 604, 1674, + 604, 544, 604, 548, 630, 524, 604, 554, 620, 530, 630, 506, + 602, 538, 602, 542, 604, 542, 604, 546, 630, 524, 602, 556, + 628, 518, 604, 1666, 632, 1644, 604, 540, 602, 546, 604, 1680, + 604, 1684, 604, 1686, 630, 520, 602, 534, 606, 538, 602, 540, + 604, 544, 604, 548, 602, 552, 630, 528, 602, 546, 602, 536, + 628, 510, 606, 540, 604, 544, 630, 522, 604, 554, 600, 554, + 602, 528, 602, 8032, 604, 1666, 604, 1668, 602, 1676, 630, 518, + 630, 520, 602, 550, 604, 554, 604, 1678, 630, 1640, 602, 1672, + 602, 542, 602, 544, 628, 522, 630, 1658, 604, 554, 628, 1652, + 630, 508, 602, 538, 630, 514, 630, 1652, 602, 546, 604, 550, + 602, 554, 602, 546, 630, 1638, 604, 536, 630, 1646, 602, 544, + 628, 522, 632, 524, 628, 528, 602, 1686, 594, 1666, 604, 1670, + 602, 1674, 632, 516, 604, 546, 638, 518, 622, 534, 628, 518, + 604, 532, 604, 536, 600, 550, 622, 1652, 630, 520, 602, 1684, + 602, 554, 602, 544, 630, 506, 628, 512, 602, 540, 628, 518, + 602, 550, 602, 552, 604, 554, 602, 544, 628, 1642, 602, 536, + 632, 1646, 630, 516, 602, 1680, 630, 1656, 604, 1688, 602, 1660, + 602, 8030, 604, 532, 604, 536, 604, 540, 602, 544, 628, 522, + 602, 552, 602, 556, 602, 544, 602, 1666, 630, 510, 602, 1674, + 604, 544, 628, 522, 602, 552, 630, 526, 628, 520, 602, 534, + 630, 510, 604, 540, 602, 544, 606, 544, 604, 550, 604, 554, + 602, 544, 604, 534, 602, 538, 602, 542, 604, 542, 604, 546, + 604, 550, 632, 526, 604, 544, 630, 506, 604, 536, 604, 540, + 628, 518, 602, 548, 604, 550, 604, 552, 630, 516, 602, 534, + 604, 536, 630, 512, 604, 544, 602, 548, 630, 524, 602, 554, + 602, 542, 604, 1666, 606, 532, 630, 1644, 602, 544, 630, 520, + 604, 550, 604, 554, 602, 526, 598}; + uint8_t expectedState[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x00, 0x73, 0x00, 0x00, 0x87, 0xA3, 0x08, 0x85, 0x07, + 0x28, 0x00, 0xF5, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x05}; + irsend.sendRaw(rawData, 343, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(WHIRLPOOL_AC, irsend.capture.decode_type); + EXPECT_EQ(kWhirlpoolAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + IRWhirlpoolAc ac(0); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Model: 1 (DG11J13A), Power toggle: Off, Mode: 3 (DRY), Temp: 25C, " + "Fan: 0 (AUTO), Swing: Off, Light: On, Clock: 07:35, On Timer: 07:40, " + "Off Timer: 08:05, Sleep: Off, Super: Off, Command: 5 (ONTIMER)", + ac.toString()); +} + +// Decode a recorded example +TEST(TestDecodeWhirlpoolAC, RealExampleDecode) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // Real WhirlpoolAC message. + // Ref: https://github.com/markszabo/IRremoteESP8266/issues/509 + uint16_t rawData[343] = { + 8950, 4484, 598, 1642, 598, 1646, 594, 534, 594, 538, 602, 532, + 598, 540, 600, 542, 598, 1650, 600, 522, 598, 1644, 596, 1650, + 600, 532, 598, 538, 602, 536, 594, 548, 592, 538, 602, 518, + 600, 524, 596, 532, 598, 532, 598, 1654, 596, 544, 596, 544, + 596, 536, 594, 1644, 596, 528, 600, 528, 592, 538, 602, 1648, + 602, 1654, 596, 1664, 598, 534, 594, 526, 594, 530, 598, 528, + 602, 530, 600, 534, 596, 542, 598, 542, 598, 534, 596, 526, + 594, 530, 600, 528, 602, 530, 600, 534, 596, 542, 598, 544, + 596, 518, 602, 7916, 598, 1642, 598, 528, 600, 528, 602, 530, + 600, 1652, 598, 542, 598, 544, 596, 1654, 596, 1644, 596, 1648, + 602, 1644, 596, 1654, 596, 1656, 604, 536, 594, 548, 602, 528, + 600, 520, 600, 524, 596, 532, 598, 532, 596, 538, 602, 536, + 594, 546, 594, 538, 602, 518, 600, 524, 596, 532, 598, 532, + 598, 536, 594, 544, 596, 544, 596, 536, 594, 526, 592, 530, + 600, 528, 600, 530, 602, 532, 596, 542, 598, 542, 598, 534, + 596, 524, 596, 528, 600, 526, 592, 538, 592, 542, 598, 540, + 600, 540, 600, 530, 598, 522, 598, 526, 594, 534, 596, 534, + 594, 540, 602, 536, 592, 548, 592, 538, 600, 1636, 594, 1648, + 602, 1642, 598, 1652, 598, 538, 602, 1680, 570, 1662, 598, 1634, + 596, 7924, 600, 520, 598, 526, 592, 534, 596, 534, 596, 540, + 600, 536, 604, 538, 602, 530, 600, 520, 598, 1640, 600, 528, + 600, 530, 600, 534, 594, 544, 596, 544, 596, 534, 596, 526, + 594, 528, 600, 526, 594, 536, 592, 542, 598, 538, 602, 538, + 602, 528, 600, 520, 600, 524, 596, 530, 600, 532, 598, 534, + 596, 542, 598, 542, 598, 532, 598, 524, 596, 528, 602, 526, + 594, 536, 594, 540, 600, 536, 594, 548, 592, 538, 602, 518, + 602, 522, 596, 530, 600, 530, 600, 534, 596, 542, 598, 544, + 596, 534, 596, 524, 594, 1644, 596, 532, 596, 534, 596, 538, + 602, 536, 594, 546, 594, 520, 600}; + uint8_t expectedState[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + + irsend.reset(); + irsend.sendRaw(rawData, 343, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(WHIRLPOOL_AC, irsend.capture.decode_type); + EXPECT_EQ(kWhirlpoolAcBits, irsend.capture.bits); + EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); + IRWhirlpoolAc ac(0); + ac.setRaw(irsend.capture.state); + EXPECT_EQ( + "Model: 1 (DG11J13A), Power toggle: Off, Mode: 1 (AUTO), Temp: 25C, " + "Fan: 0 (AUTO), Swing: Off, Light: On, Clock: 17:31, On Timer: Off, " + "Off Timer: Off, Sleep: Off, Super: Off, Command: 2 (TEMP)", + ac.toString()); +} + +// Tests for IRWhirlpoolAc class. + +TEST(TestIRWhirlpoolAcClass, SetAndGetRaw) { + uint8_t expectedState[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x10, 0x71, 0x00, 0x00, 0x91, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + IRWhirlpoolAc ac(0); + ac.setRaw(expectedState); + EXPECT_STATE_EQ(expectedState, ac.getRaw(), kWhirlpoolAcBits); +} + +TEST(TestIRWhirlpoolAcClass, SetAndGetTemp) { + IRWhirlpoolAc ac(0); + ac.setCommand(0); // Clear the previous command. + + ac.setModel(DG11J13A); + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + EXPECT_EQ(kWhirlpoolAcCommandTemp, ac.getCommand()); + ac.setTemp(kWhirlpoolAcMinTemp); + EXPECT_EQ(kWhirlpoolAcMinTemp, ac.getTemp()); + ac.setTemp(kWhirlpoolAcMinTemp - 1); + EXPECT_EQ(kWhirlpoolAcMinTemp, ac.getTemp()); + ac.setTemp(kWhirlpoolAcMaxTemp); + EXPECT_EQ(kWhirlpoolAcMaxTemp, ac.getTemp()); + ac.setTemp(kWhirlpoolAcMaxTemp + 1); + EXPECT_EQ(kWhirlpoolAcMaxTemp, ac.getTemp()); + + ac.setModel(DG11J191); // Has a -2 offset on min/max temps. + ac.setTemp(25); + EXPECT_EQ(25, ac.getTemp()); + EXPECT_EQ(kWhirlpoolAcCommandTemp, ac.getCommand()); + ac.setTemp(kWhirlpoolAcMinTemp - 2); + EXPECT_EQ(kWhirlpoolAcMinTemp - 2, ac.getTemp()); + ac.setTemp(kWhirlpoolAcMinTemp - 2 - 1); + EXPECT_EQ(kWhirlpoolAcMinTemp - 2 , ac.getTemp()); + ac.setTemp(kWhirlpoolAcMaxTemp - 2); + EXPECT_EQ(kWhirlpoolAcMaxTemp - 2, ac.getTemp()); + ac.setTemp(kWhirlpoolAcMaxTemp - 2 + 1); + EXPECT_EQ(kWhirlpoolAcMaxTemp - 2, ac.getTemp()); +} + +TEST(TestIRWhirlpoolAcClass, SetAndGetMode) { + IRWhirlpoolAc ac(0); + ac.setCommand(0); // Clear the previous command. + + ac.setMode(kWhirlpoolAcCool); + EXPECT_EQ(kWhirlpoolAcCool, ac.getMode()); + EXPECT_EQ(kWhirlpoolAcCommandMode, ac.getCommand()); + ac.setMode(kWhirlpoolAcHeat); + EXPECT_EQ(kWhirlpoolAcHeat, ac.getMode()); + ac.setMode(kWhirlpoolAcAuto); + EXPECT_EQ(kWhirlpoolAcAuto, ac.getMode()); + EXPECT_EQ(kWhirlpoolAcCommand6thSense, ac.getCommand()); + ac.setMode(kWhirlpoolAcDry); + EXPECT_EQ(kWhirlpoolAcDry, ac.getMode()); + EXPECT_EQ(kWhirlpoolAcCommandMode, ac.getCommand()); +} + +TEST(TestIRWhirlpoolAcClass, SetAndGetFan) { + IRWhirlpoolAc ac(0); + ac.setCommand(0); // Clear the previous command. + + ac.setFan(kWhirlpoolAcFanAuto); + EXPECT_EQ(kWhirlpoolAcFanAuto, ac.getFan()); + EXPECT_EQ(kWhirlpoolAcCommandFanSpeed, ac.getCommand()); + ac.setFan(kWhirlpoolAcFanLow); + EXPECT_EQ(kWhirlpoolAcFanLow, ac.getFan()); + ac.setFan(kWhirlpoolAcFanMedium); + EXPECT_EQ(kWhirlpoolAcFanMedium, ac.getFan()); + ac.setFan(kWhirlpoolAcFanHigh); + EXPECT_EQ(kWhirlpoolAcFanHigh, ac.getFan()); + ac.setFan(kWhirlpoolAcFanAuto); + EXPECT_EQ(kWhirlpoolAcFanAuto, ac.getFan()); + + // Known state with a non-auto fan mode. + const uint8_t state[21] = {0x83, 0x06, 0x0B, 0x82, 0x00, 0x00, 0x93, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, + 0x00, 0x03, 0x00, 0x00, 0x08, 0x00, 0x0B}; + ac.setRaw(state); + EXPECT_EQ(kWhirlpoolAcFanLow, ac.getFan()); +} + +TEST(TestIRWhirlpoolAcClass, SetAndGetSwing) { + IRWhirlpoolAc ac(0); + ac.setCommand(0); // Clear the previous command. + + ac.setSwing(true); + EXPECT_TRUE(ac.getSwing()); + EXPECT_EQ(kWhirlpoolAcCommandSwing, ac.getCommand()); + ac.setSwing(false); + EXPECT_FALSE(ac.getSwing()); + ac.setSwing(true); + EXPECT_TRUE(ac.getSwing()); +} + +TEST(TestIRWhirlpoolAcClass, SetAndGetLight) { + IRWhirlpoolAc ac(0); + ac.setCommand(0); // Clear the previous command. + + ac.setLight(true); + EXPECT_TRUE(ac.getLight()); + ac.setLight(false); + EXPECT_FALSE(ac.getLight()); + ac.setLight(true); + EXPECT_TRUE(ac.getLight()); +} + +TEST(TestIRWhirlpoolAcClass, SetAndGetClock) { + IRWhirlpoolAc ac(0); + ac.setClock(0); + EXPECT_EQ(0, ac.getClock()); + EXPECT_EQ("00:00", ac.timeToString(ac.getClock())); + ac.setClock(1); + EXPECT_EQ(1, ac.getClock()); + EXPECT_EQ("00:01", ac.timeToString(ac.getClock())); + ac.setClock(12 * 60 + 34); + EXPECT_EQ(12 * 60 + 34, ac.getClock()); + EXPECT_EQ("12:34", ac.timeToString(ac.getClock())); + ac.setClock(7 * 60 + 5); + EXPECT_EQ(7 * 60 + 5, ac.getClock()); + EXPECT_EQ("07:05", ac.timeToString(ac.getClock())); + ac.setClock(23 * 60 + 59); + EXPECT_EQ(23 * 60 + 59, ac.getClock()); + EXPECT_EQ("23:59", ac.timeToString(ac.getClock())); + ac.setClock(24 * 60 + 0); + EXPECT_EQ(0, ac.getClock()); + EXPECT_EQ("00:00", ac.timeToString(ac.getClock())); + ac.setClock(25 * 60 + 23); + EXPECT_EQ(1 * 60 + 23, ac.getClock()); + EXPECT_EQ("01:23", ac.timeToString(ac.getClock())); +} + +TEST(TestIRWhirlpoolAcClass, OnOffTimers) { + IRWhirlpoolAc ac(0); + ac.setCommand(0); // Clear the previous command. + + // On Timer + ac.enableOnTimer(false); + ac.setOnTimer(0); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ("00:00", ac.timeToString(ac.getOnTimer())); + EXPECT_FALSE(ac.isOnTimerEnabled()); + EXPECT_EQ(kWhirlpoolAcCommandOnTimer, ac.getCommand()); + ac.setOnTimer(1); + EXPECT_EQ(1, ac.getOnTimer()); + EXPECT_EQ("00:01", ac.timeToString(ac.getOnTimer())); + ac.enableOnTimer(true); + ac.setOnTimer(12 * 60 + 34); + EXPECT_EQ(12 * 60 + 34, ac.getOnTimer()); + EXPECT_EQ("12:34", ac.timeToString(ac.getOnTimer())); + EXPECT_TRUE(ac.isOnTimerEnabled()); + ac.setOnTimer(7 * 60 + 5); + EXPECT_EQ(7 * 60 + 5, ac.getOnTimer()); + EXPECT_EQ("07:05", ac.timeToString(ac.getOnTimer())); + ac.setOnTimer(23 * 60 + 59); + EXPECT_EQ(23 * 60 + 59, ac.getOnTimer()); + EXPECT_EQ("23:59", ac.timeToString(ac.getOnTimer())); + ac.setOnTimer(24 * 60 + 0); + EXPECT_EQ(0, ac.getOnTimer()); + EXPECT_EQ("00:00", ac.timeToString(ac.getOnTimer())); + ac.setOnTimer(25 * 60 + 23); + EXPECT_EQ(1 * 60 + 23, ac.getOnTimer()); + EXPECT_EQ("01:23", ac.timeToString(ac.getOnTimer())); + // Off Timer + ac.enableOffTimer(false); + ac.setOffTimer(0); + EXPECT_EQ(0, ac.getOffTimer()); + EXPECT_EQ("00:00", ac.timeToString(ac.getOffTimer())); + EXPECT_FALSE(ac.isOffTimerEnabled()); + EXPECT_EQ(kWhirlpoolAcCommandOffTimer, ac.getCommand()); + ac.setOffTimer(1); + EXPECT_EQ(1, ac.getOffTimer()); + EXPECT_EQ("00:01", ac.timeToString(ac.getOffTimer())); + ac.enableOffTimer(true); + ac.setOffTimer(12 * 60 + 34); + EXPECT_EQ(12 * 60 + 34, ac.getOffTimer()); + EXPECT_EQ("12:34", ac.timeToString(ac.getOffTimer())); + EXPECT_TRUE(ac.isOffTimerEnabled()); + ac.setOffTimer(7 * 60 + 5); + EXPECT_EQ(7 * 60 + 5, ac.getOffTimer()); + EXPECT_EQ("07:05", ac.timeToString(ac.getOffTimer())); + ac.setOffTimer(23 * 60 + 59); + EXPECT_EQ(23 * 60 + 59, ac.getOffTimer()); + EXPECT_EQ("23:59", ac.timeToString(ac.getOffTimer())); + ac.setOffTimer(24 * 60 + 0); + EXPECT_EQ(0, ac.getOffTimer()); + EXPECT_EQ("00:00", ac.timeToString(ac.getOffTimer())); + ac.setOffTimer(25 * 60 + 23); + EXPECT_EQ(1 * 60 + 23, ac.getOffTimer()); + EXPECT_EQ("01:23", ac.timeToString(ac.getOffTimer())); +} + +TEST(TestIRWhirlpoolAcClass, SetAndGetCommand) { + IRWhirlpoolAc ac(0); + ac.setCommand(0); + EXPECT_EQ(0, ac.getCommand()); + ac.setCommand(kWhirlpoolAcCommandFanSpeed); + EXPECT_EQ(kWhirlpoolAcCommandFanSpeed, ac.getCommand()); + ac.setCommand(255); + EXPECT_EQ(255, ac.getCommand()); +} + +TEST(TestIRWhirlpoolAcClass, SetAndGetPowerToggle) { + IRWhirlpoolAc ac(0); + ac.setCommand(0); + + ac.setPowerToggle(false); + EXPECT_FALSE(ac.getPowerToggle()); + ac.setPowerToggle(true); + EXPECT_TRUE(ac.getPowerToggle()); + ac.setPowerToggle(false); + EXPECT_FALSE(ac.getPowerToggle()); + + // Known state with a power toggle in it. + uint8_t state[21] = {0x83, 0x06, 0x07, 0x82, 0x00, 0x00, 0x93, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, + 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x09}; + ac.setRaw(state); + EXPECT_TRUE(ac.getPowerToggle()); +} + +TEST(TestIRWhirlpoolAcClass, SetAndGetModel) { + IRWhirlpoolAc ac(0); + ac.setTemp(19); + ac.setCommand(0); // Set model shouldn't change the command setting. + + ac.setModel(DG11J191); + EXPECT_EQ(DG11J191, ac.getModel()); + EXPECT_EQ(19, ac.getTemp()); + EXPECT_EQ(0, ac.getCommand()); + ac.setModel(DG11J13A); + EXPECT_EQ(DG11J13A, ac.getModel()); + EXPECT_EQ(19, ac.getTemp()); + ac.setModel(DG11J191); + EXPECT_EQ(DG11J191, ac.getModel()); + EXPECT_EQ(19, ac.getTemp()); + EXPECT_EQ(0, ac.getCommand()); + + // One of the models has a lower min temp. Check that desired temp is kept. + ac.setTemp(16); + ac.setCommand(0); // Set model shouldn't change the command setting. + EXPECT_EQ(16, ac.getTemp()); + EXPECT_EQ(0, ac.getCommand()); + ac.setModel(DG11J13A); + EXPECT_EQ(DG11J13A, ac.getModel()); + EXPECT_EQ(18, ac.getTemp()); + ac.setModel(DG11J191); + EXPECT_EQ(DG11J191, ac.getModel()); + EXPECT_EQ(16, ac.getTemp()); + EXPECT_EQ(0, ac.getCommand()); + + // Known states with different models. + uint8_t state_1[21] = {0x83, 0x06, 0x01, 0x30, 0x00, 0x00, 0x92, + 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, + 0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x0A}; + uint8_t state_2[21] = {0x83, 0x06, 0x00, 0x30, 0x00, 0x00, 0x8B, + 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02}; + + ac.setRaw(state_1); + EXPECT_EQ(DG11J191, ac.getModel()); + ac.setRaw(state_2); + EXPECT_EQ(DG11J13A, ac.getModel()); +} + +TEST(TestIRWhirlpoolAcClass, SetAndGetSleep) { + IRWhirlpoolAc ac(0); + ac.setFan(kWhirlpoolAcFanAuto); + ac.setCommand(0); + + ac.setSleep(false); + EXPECT_FALSE(ac.getSleep()); + EXPECT_EQ(kWhirlpoolAcCommandSleep, ac.getCommand()); + ac.setSleep(true); + EXPECT_TRUE(ac.getSleep()); + EXPECT_EQ(kWhirlpoolAcCommandSleep, ac.getCommand()); + EXPECT_EQ(kWhirlpoolAcFanLow, ac.getFan()); + ac.setSleep(false); + EXPECT_FALSE(ac.getSleep()); + + // Known state with sleep mode in it. + uint8_t state[21] = {0x83, 0x06, 0x0B, 0x73, 0x00, 0x00, 0x90, + 0x9E, 0x00, 0xA0, 0x17, 0x3A, 0x00, 0xFB, + 0x00, 0x03, 0x00, 0x00, 0x08, 0x00, 0x0B}; + ac.setRaw(state); + EXPECT_TRUE(ac.getSleep()); +} + +TEST(TestIRWhirlpoolAcClass, SetAndGetSuper) { + IRWhirlpoolAc ac(0); + ac.setFan(kWhirlpoolAcFanAuto); + ac.setMode(kWhirlpoolAcDry); + ac.setCommand(0); + + ac.setSuper(false); + EXPECT_FALSE(ac.getSuper()); + EXPECT_EQ(kWhirlpoolAcCommandSuper, ac.getCommand()); + ac.setSuper(true); + EXPECT_TRUE(ac.getSuper()); + EXPECT_EQ(kWhirlpoolAcCommandSuper, ac.getCommand()); + EXPECT_EQ(kWhirlpoolAcFanHigh, ac.getFan()); + EXPECT_EQ(kWhirlpoolAcCool, ac.getMode()); + EXPECT_EQ(kWhirlpoolAcMinTemp, ac.getTemp()); + + ac.setSuper(false); + EXPECT_FALSE(ac.getSuper()); + EXPECT_EQ(kWhirlpoolAcFanHigh, ac.getFan()); + EXPECT_EQ(kWhirlpoolAcCool, ac.getMode()); + EXPECT_EQ(kWhirlpoolAcMinTemp, ac.getTemp()); + + // When in heat mode, it should stay in heat mode. + ac.setFan(kWhirlpoolAcFanAuto); + ac.setMode(kWhirlpoolAcHeat); + ac.setSuper(true); + EXPECT_TRUE(ac.getSuper()); + EXPECT_EQ(kWhirlpoolAcCommandSuper, ac.getCommand()); + EXPECT_EQ(kWhirlpoolAcFanHigh, ac.getFan()); + EXPECT_EQ(kWhirlpoolAcHeat, ac.getMode()); + EXPECT_EQ(kWhirlpoolAcMaxTemp, ac.getTemp()); + + // Changing mode/temp/fan/power should cancel super, + ac.setMode(kWhirlpoolAcCool); + EXPECT_FALSE(ac.getSuper()); + ac.setSuper(true); + ac.setTemp(25); + EXPECT_FALSE(ac.getSuper()); + ac.setSuper(true); + ac.setFan(kWhirlpoolAcFanMedium); + EXPECT_FALSE(ac.getSuper()); + ac.setSuper(true); + ac.setPowerToggle(true); + EXPECT_FALSE(ac.getSuper()); + + // Known state with Super mode in it. + uint8_t state[21] = {0x83, 0x06, 0x01, 0x02, 0x00, 0x90, 0x90, + 0x9F, 0x00, 0xA0, 0x17, 0x3A, 0x00, 0x11, + 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x0C}; + ac.setRaw(state); + EXPECT_TRUE(ac.getSuper()); +} + +// Build a known good message from scratch. +TEST(TestIRWhirlpoolAcClass, MessageConstruction) { + // Real example captured from a remote. (ref: RealTimerExample) + uint8_t expectedState[kWhirlpoolAcStateLength] = { + 0x83, 0x06, 0x00, 0x73, 0x00, 0x00, 0x87, 0xA3, 0x08, 0x85, 0x07, + 0x28, 0x00, 0xF5, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x05}; + IRWhirlpoolAc ac(0); + ac.setModel(DG11J13A); + ac.setTemp(25); + ac.setPowerToggle(false); + ac.setMode(kWhirlpoolAcDry); + ac.setFan(kWhirlpoolAcFanAuto); + ac.setSwing(false); + ac.setLight(true); + ac.setClock(7 * 60 + 35); + ac.setOnTimer(7 * 60 + 40); + ac.setOffTimer(8 * 60 + 5); + ac.enableOffTimer(true); + ac.setSleep(false); + ac.setSuper(false); + ac.enableOnTimer(true); + + EXPECT_EQ( + "Model: 1 (DG11J13A), Power toggle: Off, Mode: 3 (DRY), Temp: 25C, " + "Fan: 0 (AUTO), Swing: Off, Light: On, Clock: 07:35, On Timer: 07:40, " + "Off Timer: 08:05, Sleep: Off, Super: Off, Command: 5 (ONTIMER)", + ac.toString()); + EXPECT_STATE_EQ(expectedState, ac.getRaw(), kWhirlpoolAcBits); +} diff --git a/lib/IRremoteESP8266-2.5.2.03/test/ir_Whynter_test.cpp b/lib/IRremoteESP8266-2.6.0/test/ir_Whynter_test.cpp similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/test/ir_Whynter_test.cpp rename to lib/IRremoteESP8266-2.6.0/test/ir_Whynter_test.cpp index 748a4c9bf..92ced5cf6 100644 --- a/lib/IRremoteESP8266-2.5.2.03/test/ir_Whynter_test.cpp +++ b/lib/IRremoteESP8266-2.6.0/test/ir_Whynter_test.cpp @@ -14,6 +14,7 @@ TEST(TestSendWhynter, SendDataOnly) { irsend.reset(); irsend.sendWhynter(0x0); EXPECT_EQ( + "f38000d50" "m750s750m2850s2850" "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" @@ -25,6 +26,7 @@ TEST(TestSendWhynter, SendDataOnly) { irsend.reset(); irsend.sendWhynter(0xFFFFFFFF); EXPECT_EQ( + "f38000d50" "m750s750m2850s2850" "m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150" "m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150" @@ -36,6 +38,7 @@ TEST(TestSendWhynter, SendDataOnly) { irsend.reset(); irsend.sendWhynter(0x87654321); EXPECT_EQ( + "f38000d50" "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" @@ -53,6 +56,7 @@ TEST(TestSendWhynter, SendWithRepeats) { irsend.reset(); irsend.sendWhynter(0x87654321, kWhynterBits, 0); // 0 repeats. EXPECT_EQ( + "f38000d50" "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" @@ -64,6 +68,7 @@ TEST(TestSendWhynter, SendWithRepeats) { irsend.reset(); irsend.sendWhynter(0x87654321, kWhynterBits, 1); // 1 repeat. EXPECT_EQ( + "f38000d50" "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" @@ -81,6 +86,7 @@ TEST(TestSendWhynter, SendWithRepeats) { irsend.reset(); irsend.sendWhynter(0x87654321, kWhynterBits, 2); // 2 repeats. EXPECT_EQ( + "f38000d50" "m750s750m2850s2850" "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" @@ -110,6 +116,7 @@ TEST(TestSendWhynter, SendUnusualSize) { irsend.reset(); irsend.sendWhynter(0x0, 8); EXPECT_EQ( + "f38000d50" "m750s750m2850s2850" "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" "m750s88050", @@ -118,6 +125,7 @@ TEST(TestSendWhynter, SendUnusualSize) { irsend.reset(); irsend.sendWhynter(0x1234567890ABCDEF, 64); EXPECT_EQ( + "f38000d50" "m750s750m2850s2850" "m750s750m750s750m750s750m750s2150m750s750m750s750m750s2150m750s750" "m750s750m750s750m750s2150m750s2150m750s750m750s2150m750s750m750s750" diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/Makefile b/lib/IRremoteESP8266-2.6.0/tools/Makefile similarity index 76% rename from lib/IRremoteESP8266-2.5.2.03/tools/Makefile rename to lib/IRremoteESP8266-2.6.0/tools/Makefile index c303e051d..08488949c 100644 --- a/lib/IRremoteESP8266-2.5.2.03/tools/Makefile +++ b/lib/IRremoteESP8266-2.6.0/tools/Makefile @@ -14,13 +14,14 @@ USER_DIR = ../src # Where to find test code. TEST_DIR = ../test +INCLUDES = -I$(USER_DIR) -I$(TEST_DIR) # Flags passed to the preprocessor. # Set Google Test's header directory as a system directory, such that # the compiler doesn't generate warnings in Google Test headers. CPPFLAGS += -DUNIT_TEST # Flags passed to the C++ compiler. -CXXFLAGS += -g -Wall -Wextra -pthread +CXXFLAGS += -g -Wall -Wextra -pthread -std=gnu++11 all : gc_decode mode2_decode @@ -48,25 +49,27 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \ ir_Pronto.o ir_GlobalCache.o ir_Nikai.o ir_Toshiba.o ir_Midea.o \ ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o ir_Hitachi.o \ ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o ir_Pioneer.o \ - ir_MWM.o + ir_MWM.o ir_Vestel.o ir_Teco.o ir_Tcl.o ir_Lego.o \ + ir_MitsubishiHeavy.o # Common object files COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o $(PROTOCOLS) # Common dependencies COMMON_DEPS = $(USER_DIR)/IRrecv.h $(USER_DIR)/IRsend.h $(USER_DIR)/IRtimer.h \ - $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h + $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h \ + $(TEST_DIR)/IRsend_test.h # Common test dependencies COMMON_TEST_DEPS = $(COMMON_DEPS) $(TEST_DIR)/IRsend_test.h gc_decode.o : gc_decode.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -I$(TEST_DIR) -c gc_decode.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c gc_decode.cpp gc_decode : $(COMMON_OBJ) gc_decode.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ mode2_decode.o : mode2_decode.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -I$(TEST_DIR) -c mode2_decode.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c mode2_decode.cpp mode2_decode : $(COMMON_OBJ) mode2_decode.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ @@ -83,7 +86,6 @@ IRsend.o : $(USER_DIR)/IRsend.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRremoteESP82 IRrecv.o : $(USER_DIR)/IRrecv.cpp $(USER_DIR)/IRrecv.h $(USER_DIR)/IRremoteESP8266.h $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRrecv.cpp - ir_NEC.o : $(USER_DIR)/ir_NEC.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_NEC.cpp @@ -97,10 +99,10 @@ ir_Sony.o : $(USER_DIR)/ir_Sony.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sony.cpp ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(USER_DIR)/ir_Samsung.h $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Samsung.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Samsung.cpp ir_Kelvinator.o : $(USER_DIR)/ir_Kelvinator.cpp $(USER_DIR)/ir_Kelvinator.h $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Kelvinator.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Kelvinator.cpp ir_JVC.o : $(USER_DIR)/ir_JVC.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_JVC.cpp @@ -112,10 +114,13 @@ ir_LG.o : $(USER_DIR)/ir_LG.h $(USER_DIR)/ir_LG.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_LG.cpp ir_Mitsubishi.o : $(USER_DIR)/ir_Mitsubishi.h $(USER_DIR)/ir_Mitsubishi.cpp $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Mitsubishi.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Mitsubishi.cpp + +ir_MitsubishiHeavy.o : $(USER_DIR)/ir_MitsubishiHeavy.h $(USER_DIR)/ir_MitsubishiHeavy.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_MitsubishiHeavy.cpp ir_Fujitsu.o : $(USER_DIR)/ir_Fujitsu.h $(USER_DIR)/ir_Fujitsu.cpp $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Fujitsu.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Fujitsu.cpp ir_Sharp.o : $(USER_DIR)/ir_Sharp.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sharp.cpp @@ -124,7 +129,7 @@ ir_RC5_RC6.o : $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_RC5_RC6.cpp ir_Panasonic.o : $(USER_DIR)/ir_Panasonic.cpp $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Panasonic.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Panasonic.cpp ir_Dish.o : $(USER_DIR)/ir_Dish.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Dish.cpp @@ -133,7 +138,7 @@ ir_Whynter.o : $(USER_DIR)/ir_Whynter.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whynter.cpp ir_Coolix.o : $(USER_DIR)/ir_Coolix.cpp $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Coolix.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Coolix.cpp ir_Aiwa.o : $(USER_DIR)/ir_Aiwa.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Aiwa.cpp @@ -145,10 +150,10 @@ ir_Sanyo.o : $(USER_DIR)/ir_Sanyo.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sanyo.cpp ir_Daikin.o : $(USER_DIR)/ir_Daikin.cpp $(USER_DIR)/ir_Daikin.h $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Daikin.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Daikin.cpp ir_Gree.o : $(USER_DIR)/ir_Gree.cpp $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Gree.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Gree.cpp ir_Pronto.o : $(USER_DIR)/ir_Pronto.cpp $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Pronto.cpp @@ -157,10 +162,10 @@ ir_Nikai.o : $(USER_DIR)/ir_Nikai.cpp $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Nikai.cpp ir_Toshiba.o : $(USER_DIR)/ir_Toshiba.h $(USER_DIR)/ir_Toshiba.cpp $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Toshiba.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Toshiba.cpp ir_Midea.o : $(USER_DIR)/ir_Midea.cpp $(COMMON_DEPS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Midea.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Midea.cpp ir_Magiquest.o : $(USER_DIR)/ir_Magiquest.cpp $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Magiquest.cpp @@ -172,16 +177,16 @@ ir_Carrier.o : $(USER_DIR)/ir_Carrier.cpp $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Carrier.cpp ir_Haier.o : $(USER_DIR)/ir_Haier.cpp $(USER_DIR)/ir_Haier.h $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Haier.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Haier.cpp ir_Hitachi.o : $(USER_DIR)/ir_Hitachi.cpp $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Hitachi.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Hitachi.cpp ir_GICable.o : $(USER_DIR)/ir_GICable.cpp $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_GICable.cpp ir_Whirlpool.o : $(USER_DIR)/ir_Whirlpool.cpp $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whirlpool.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Whirlpool.cpp ir_Lutron.o : $(USER_DIR)/ir_Lutron.cpp $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lutron.cpp @@ -194,3 +199,15 @@ ir_Pioneer.o : $(USER_DIR)/ir_Pioneer.cpp $(GTEST_HEADERS) ir_MWM.o : $(USER_DIR)/ir_MWM.cpp $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_MWM.cpp + +ir_Vestel.o : $(USER_DIR)/ir_Vestel.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Vestel.cpp + +ir_Teco.o : $(USER_DIR)/ir_Teco.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Teco.cpp + +ir_Tcl.o : $(USER_DIR)/ir_Tcl.cpp $(USER_DIR)/ir_Tcl.h $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Tcl.cpp + +ir_Lego.o : $(USER_DIR)/ir_Lego.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Lego.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/RawToGlobalCache.sh b/lib/IRremoteESP8266-2.6.0/tools/RawToGlobalCache.sh similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/tools/RawToGlobalCache.sh rename to lib/IRremoteESP8266-2.6.0/tools/RawToGlobalCache.sh diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data.py b/lib/IRremoteESP8266-2.6.0/tools/auto_analyse_raw_data.py similarity index 98% rename from lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data.py rename to lib/IRremoteESP8266-2.6.0/tools/auto_analyse_raw_data.py index 5fd399807..b23cdb46f 100644 --- a/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data.py +++ b/lib/IRremoteESP8266-2.6.0/tools/auto_analyse_raw_data.py @@ -85,9 +85,9 @@ class RawIRMessage(object): " %s (LSB first)\n" " Bin: 0b%s (MSB first)\n" " 0b%s (LSB first)\n" % - (bits, "0x{0:0{1}X}".format(num, bits / 4), - "0x{0:0{1}X}".format(rev_num, bits / 4), num, rev_num, - binary_str, rev_binary_str)) + (bits, ("0x{0:0%dX}" % (bits / 4)).format(num), + ("0x{0:0%dX}" % (bits / 4)).format(rev_num), num, + rev_num, binary_str, rev_binary_str)) def add_data_code(self, bin_str, footer=True): """Add the common "data" sequence of code to send the bulk of a message.""" diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data_test.py b/lib/IRremoteESP8266-2.6.0/tools/auto_analyse_raw_data_test.py similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/tools/auto_analyse_raw_data_test.py rename to lib/IRremoteESP8266-2.6.0/tools/auto_analyse_raw_data_test.py diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/gc_decode.cpp b/lib/IRremoteESP8266-2.6.0/tools/gc_decode.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/tools/gc_decode.cpp rename to lib/IRremoteESP8266-2.6.0/tools/gc_decode.cpp diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/mkkeywords b/lib/IRremoteESP8266-2.6.0/tools/mkkeywords similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/tools/mkkeywords rename to lib/IRremoteESP8266-2.6.0/tools/mkkeywords diff --git a/lib/IRremoteESP8266-2.5.2.03/tools/mode2_decode.cpp b/lib/IRremoteESP8266-2.6.0/tools/mode2_decode.cpp similarity index 100% rename from lib/IRremoteESP8266-2.5.2.03/tools/mode2_decode.cpp rename to lib/IRremoteESP8266-2.6.0/tools/mode2_decode.cpp From b078d10bf4744fbcdf671b61b82cdbc2da30507a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 27 May 2019 14:17:31 +0200 Subject: [PATCH 1417/2222] Fix compilation error Fix compilation error --- sonoff/sonoff.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 905e8b3ea..38f28df0e 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -851,7 +851,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) case P_RGB_REMAP: LightUpdateColorMapping(); break; -#ifdef USE_IR_RECEIVE +#if defined(USE_IR_REMOTE) && defined(USE_IR_RECEIVE) case P_IR_UNKNOW_THRESHOLD: IrReceiveUpdateThreshold(); break; From f5fc4ae9ddbf42f8d6ac3df8c56644ceef12d9d3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 27 May 2019 15:08:11 +0200 Subject: [PATCH 1418/2222] Update HandleWifiConfiguration Update HandleWifiConfiguration --- sonoff/xdrv_01_webserver.ino | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index af4156f57..28250adf1 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1313,6 +1313,9 @@ String HtmlEscape(const String unescaped) { return result; } +// Indexed by enum wl_enc_type in file wl_definitions.h starting from -1 +const char kEncryptionType[] PROGMEM = "|||" D_WPA_PSK "||" D_WPA2_PSK "|" D_WEP "||" D_NONE "|" D_AUTO; + void HandleWifiConfiguration(void) { if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } @@ -1379,11 +1382,12 @@ void HandleWifiConfiguration(void) int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); if (minimum_signal_quality == -1 || minimum_signal_quality < quality) { - uint8_t auth = WiFi.encryptionType(indices[i]); + int auth = WiFi.encryptionType(indices[i]); + char encryption[20]; WSContentSend_P(PSTR("
%s (%d) %s %d%%
"), HtmlEscape(WiFi.SSID(indices[i])).c_str(), WiFi.channel(indices[i]), - (ENC_TYPE_WEP == auth) ? D_WEP : (ENC_TYPE_TKIP == auth) ? D_WPA_PSK : (ENC_TYPE_CCMP == auth) ? D_WPA2_PSK : (ENC_TYPE_AUTO == auth) ? D_AUTO : "", + GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), quality ); delay(0); From 9d780519f7af7f2afacaaeaf3cbb5df288ce4ec5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 27 May 2019 16:36:37 +0200 Subject: [PATCH 1419/2222] Update PubSubClient library to 2.7+fixes Update PubSubClient library to 2.7+fixes --- .../tests/testcases/mqtt_basic.py | 43 ----- .../testcases/mqtt_publish_in_callback.py | 64 ------- .../tests/testsuite.py | 179 ----------------- .../.gitignore | 0 .../.travis.yml | 0 .../CHANGES.txt | 10 +- .../LICENSE.txt | 0 .../README.md | 3 +- .../examples/mqtt_auth/mqtt_auth.ino | 0 .../examples/mqtt_basic/mqtt_basic.ino | 0 .../examples/mqtt_esp8266/mqtt_esp8266.ino | 28 +-- .../mqtt_large_message/mqtt_large_message.ino | 179 +++++++++++++++++ .../mqtt_publish_in_callback.ino | 0 .../mqtt_reconnect_nonblocking.ino | 0 .../examples/mqtt_stream/mqtt_stream.ino | 0 .../keywords.txt | 3 + .../library.json | 2 +- .../library.properties | 2 +- .../src/PubSubClient.cpp | 138 ++++++++++--- .../src/PubSubClient.h | 31 ++- .../tests/.gitignore | 0 .../tests/Makefile | 0 .../tests/README.md | 0 .../tests/src/connect_spec.cpp | 46 +++++ .../tests/src/keepalive_spec.cpp | 0 .../tests/src/lib/Arduino.h | 3 + .../tests/src/lib/BDDTest.cpp | 0 .../tests/src/lib/BDDTest.h | 0 .../tests/src/lib/Buffer.cpp | 4 + .../tests/src/lib/Buffer.h | 0 .../tests/src/lib/Client.h | 0 .../tests/src/lib/IPAddress.cpp | 0 .../tests/src/lib/IPAddress.h | 0 .../tests/src/lib/Print.h | 28 +++ .../tests/src/lib/ShimClient.cpp | 0 .../tests/src/lib/ShimClient.h | 0 .../tests/src/lib/Stream.cpp | 0 .../tests/src/lib/Stream.h | 0 .../tests/src/lib/trace.h | 0 .../tests/src/publish_spec.cpp | 0 .../tests/src/receive_spec.cpp | 30 +++ .../tests/src/subscribe_spec.cpp | 0 .../tests/testcases/__init__.py | 0 .../tests/testcases/mqtt_basic.py | 39 ++++ .../testcases/mqtt_publish_in_callback.py | 59 ++++++ .../tests/testcases/settings.py | 0 .../tests/testsuite.py | 181 ++++++++++++++++++ 47 files changed, 740 insertions(+), 332 deletions(-) delete mode 100644 lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_basic.py delete mode 100644 lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_publish_in_callback.py delete mode 100644 lib/PubSubClient-EspEasy-2.6.09/tests/testsuite.py rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/.gitignore (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/.travis.yml (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/CHANGES.txt (86%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/LICENSE.txt (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/README.md (95%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/examples/mqtt_auth/mqtt_auth.ino (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/examples/mqtt_basic/mqtt_basic.ino (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/examples/mqtt_esp8266/mqtt_esp8266.ino (92%) create mode 100644 lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_large_message/mqtt_large_message.ino rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/examples/mqtt_stream/mqtt_stream.ino (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/keywords.txt (91%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/library.json (97%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/library.properties (98%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/src/PubSubClient.cpp (79%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/src/PubSubClient.h (76%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/.gitignore (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/Makefile (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/README.md (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/connect_spec.cpp (83%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/keepalive_spec.cpp (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/Arduino.h (90%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/BDDTest.cpp (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/BDDTest.h (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/Buffer.cpp (86%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/Buffer.h (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/Client.h (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/IPAddress.cpp (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/IPAddress.h (100%) create mode 100644 lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Print.h rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/ShimClient.cpp (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/ShimClient.h (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/Stream.cpp (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/Stream.h (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/lib/trace.h (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/publish_spec.cpp (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/receive_spec.cpp (89%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/src/subscribe_spec.cpp (100%) rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/testcases/__init__.py (100%) create mode 100644 lib/PubSubClient-EspEasy-2.7.11/tests/testcases/mqtt_basic.py create mode 100644 lib/PubSubClient-EspEasy-2.7.11/tests/testcases/mqtt_publish_in_callback.py rename lib/{PubSubClient-EspEasy-2.6.09 => PubSubClient-EspEasy-2.7.11}/tests/testcases/settings.py (100%) create mode 100644 lib/PubSubClient-EspEasy-2.7.11/tests/testsuite.py diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_basic.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_basic.py deleted file mode 100644 index 1b0cc65bb..000000000 --- a/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_basic.py +++ /dev/null @@ -1,43 +0,0 @@ -import unittest -import settings - -import time -import mosquitto - -import serial - -def on_message(mosq, obj, msg): - obj.message_queue.append(msg) - -class mqtt_basic(unittest.TestCase): - - message_queue = [] - - @classmethod - def setUpClass(self): - self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True,obj=self) - self.client.connect(settings.server_ip) - self.client.on_message = on_message - self.client.subscribe("outTopic",0) - - @classmethod - def tearDownClass(self): - self.client.disconnect() - - def test_one(self): - i=30 - while len(self.message_queue) == 0 and i > 0: - self.client.loop() - time.sleep(0.5) - i -= 1 - self.assertTrue(i>0, "message receive timed-out") - self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") - msg = self.message_queue[0] - self.assertEqual(msg.mid,0,"message id not 0") - self.assertEqual(msg.topic,"outTopic","message topic incorrect") - self.assertEqual(msg.payload,"hello world") - self.assertEqual(msg.qos,0,"message qos not 0") - self.assertEqual(msg.retain,False,"message retain flag incorrect") - - - diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_publish_in_callback.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_publish_in_callback.py deleted file mode 100644 index 7989f7f17..000000000 --- a/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_publish_in_callback.py +++ /dev/null @@ -1,64 +0,0 @@ -import unittest -import settings - -import time -import mosquitto - -import serial - -def on_message(mosq, obj, msg): - obj.message_queue.append(msg) - -class mqtt_publish_in_callback(unittest.TestCase): - - message_queue = [] - - @classmethod - def setUpClass(self): - self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True,obj=self) - self.client.connect(settings.server_ip) - self.client.on_message = on_message - self.client.subscribe("outTopic",0) - - @classmethod - def tearDownClass(self): - self.client.disconnect() - - def test_connect(self): - i=30 - while len(self.message_queue) == 0 and i > 0: - self.client.loop() - time.sleep(0.5) - i -= 1 - self.assertTrue(i>0, "message receive timed-out") - self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") - msg = self.message_queue.pop(0) - self.assertEqual(msg.mid,0,"message id not 0") - self.assertEqual(msg.topic,"outTopic","message topic incorrect") - self.assertEqual(msg.payload,"hello world") - self.assertEqual(msg.qos,0,"message qos not 0") - self.assertEqual(msg.retain,False,"message retain flag incorrect") - - - def test_publish(self): - self.assertEqual(len(self.message_queue), 0, "message queue not empty") - payload = "abcdefghij" - self.client.publish("inTopic",payload) - - i=30 - while len(self.message_queue) == 0 and i > 0: - self.client.loop() - time.sleep(0.5) - i -= 1 - - self.assertTrue(i>0, "message receive timed-out") - self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") - msg = self.message_queue.pop(0) - self.assertEqual(msg.mid,0,"message id not 0") - self.assertEqual(msg.topic,"outTopic","message topic incorrect") - self.assertEqual(msg.payload,payload) - self.assertEqual(msg.qos,0,"message qos not 0") - self.assertEqual(msg.retain,False,"message retain flag incorrect") - - - diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/testsuite.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testsuite.py deleted file mode 100644 index 0a8e70dfd..000000000 --- a/lib/PubSubClient-EspEasy-2.6.09/tests/testsuite.py +++ /dev/null @@ -1,179 +0,0 @@ -#!/usr/bin/env python -import os -import os.path -import sys -import shutil -from subprocess import call -import importlib -import unittest -import re - -from testcases import settings - -class Workspace(object): - - def __init__(self): - self.root_dir = os.getcwd() - self.build_dir = os.path.join(self.root_dir,"tmpbin"); - self.log_dir = os.path.join(self.root_dir,"logs"); - self.tests_dir = os.path.join(self.root_dir,"testcases"); - self.examples_dir = os.path.join(self.root_dir,"../PubSubClient/examples") - self.examples = [] - self.tests = [] - if not os.path.isdir("../PubSubClient"): - raise Exception("Cannot find PubSubClient library") - try: - import ino - except: - raise Exception("ino tool not installed") - - def init(self): - if os.path.isdir(self.build_dir): - shutil.rmtree(self.build_dir) - os.mkdir(self.build_dir) - if os.path.isdir(self.log_dir): - shutil.rmtree(self.log_dir) - os.mkdir(self.log_dir) - - os.chdir(self.build_dir) - call(["ino","init"]) - - shutil.copytree("../../PubSubClient","lib/PubSubClient") - - filenames = [] - for root, dirs, files in os.walk(self.examples_dir): - filenames += [os.path.join(root,f) for f in files if f.endswith(".ino")] - filenames.sort() - for e in filenames: - self.examples.append(Sketch(self,e)) - - filenames = [] - for root, dirs, files in os.walk(self.tests_dir): - filenames += [os.path.join(root,f) for f in files if f.endswith(".ino")] - filenames.sort() - for e in filenames: - self.tests.append(Sketch(self,e)) - - def clean(self): - shutil.rmtree(self.build_dir) - -class Sketch(object): - def __init__(self,wksp,fn): - self.w = wksp - self.filename = fn - self.basename = os.path.basename(self.filename) - self.build_log = os.path.join(self.w.log_dir,"%s.log"%(os.path.basename(self.filename),)) - self.build_err_log = os.path.join(self.w.log_dir,"%s.err.log"%(os.path.basename(self.filename),)) - self.build_upload_log = os.path.join(self.w.log_dir,"%s.upload.log"%(os.path.basename(self.filename),)) - - def build(self): - sys.stdout.write(" Build: ") - sys.stdout.flush() - - # Copy sketch over, replacing IP addresses as necessary - fin = open(self.filename,"r") - lines = fin.readlines() - fin.close() - fout = open(os.path.join(self.w.build_dir,"src","sketch.ino"),"w") - for l in lines: - if re.match(r"^byte server\[\] = {",l): - fout.write("byte server[] = { %s };\n"%(settings.server_ip.replace(".",", "),)) - elif re.match(r"^byte ip\[\] = {",l): - fout.write("byte ip[] = { %s };\n"%(settings.arduino_ip.replace(".",", "),)) - else: - fout.write(l) - fout.flush() - fout.close() - - # Run build - fout = open(self.build_log, "w") - ferr = open(self.build_err_log, "w") - rc = call(["ino","build"],stdout=fout,stderr=ferr) - fout.close() - ferr.close() - if rc == 0: - sys.stdout.write("pass") - sys.stdout.write("\n") - return True - else: - sys.stdout.write("fail") - sys.stdout.write("\n") - with open(self.build_err_log) as f: - for line in f: - print " ",line, - return False - - def upload(self): - sys.stdout.write(" Upload: ") - sys.stdout.flush() - fout = open(self.build_upload_log, "w") - rc = call(["ino","upload"],stdout=fout,stderr=fout) - fout.close() - if rc == 0: - sys.stdout.write("pass") - sys.stdout.write("\n") - return True - else: - sys.stdout.write("fail") - sys.stdout.write("\n") - with open(self.build_upload_log) as f: - for line in f: - print " ",line, - return False - - - def test(self): - # import the matching test case, if it exists - try: - basename = os.path.basename(self.filename)[:-4] - i = importlib.import_module("testcases."+basename) - except: - sys.stdout.write(" Test: no tests found") - sys.stdout.write("\n") - return - c = getattr(i,basename) - - testmethods = [m for m in dir(c) if m.startswith("test_")] - testmethods.sort() - tests = [] - for m in testmethods: - tests.append(c(m)) - - result = unittest.TestResult() - c.setUpClass() - if self.upload(): - sys.stdout.write(" Test: ") - sys.stdout.flush() - for t in tests: - t.run(result) - print "%d/%d"%(result.testsRun-len(result.failures)-len(result.errors),result.testsRun) - if not result.wasSuccessful(): - if len(result.failures) > 0: - for f in result.failures: - print "-- %s"%(str(f[0]),) - print f[1] - if len(result.errors) > 0: - print " Errors:" - for f in result.errors: - print "-- %s"%(str(f[0]),) - print f[1] - c.tearDownClass() - -if __name__ == '__main__': - run_tests = True - - w = Workspace() - w.init() - - for e in w.examples: - print "--------------------------------------" - print "[%s]"%(e.basename,) - if e.build() and run_tests: - e.test() - for e in w.tests: - print "--------------------------------------" - print "[%s]"%(e.basename,) - if e.build() and run_tests: - e.test() - - w.clean() diff --git a/lib/PubSubClient-EspEasy-2.6.09/.gitignore b/lib/PubSubClient-EspEasy-2.7.11/.gitignore similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/.gitignore rename to lib/PubSubClient-EspEasy-2.7.11/.gitignore diff --git a/lib/PubSubClient-EspEasy-2.6.09/.travis.yml b/lib/PubSubClient-EspEasy-2.7.11/.travis.yml similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/.travis.yml rename to lib/PubSubClient-EspEasy-2.7.11/.travis.yml diff --git a/lib/PubSubClient-EspEasy-2.6.09/CHANGES.txt b/lib/PubSubClient-EspEasy-2.7.11/CHANGES.txt similarity index 86% rename from lib/PubSubClient-EspEasy-2.6.09/CHANGES.txt rename to lib/PubSubClient-EspEasy-2.7.11/CHANGES.txt index 8c8bef64e..ff4da62ab 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/CHANGES.txt +++ b/lib/PubSubClient-EspEasy-2.7.11/CHANGES.txt @@ -1,8 +1,16 @@ +2.7 + * Fix remaining-length handling to prevent buffer overrun + * Add large-payload API - beginPublish/write/publish/endPublish + * Add yield call to improve reliability on ESP + * Add Clean Session flag to connect options + * Add ESP32 support for functional callback signature + * Various other fixes + 2.4 * Add MQTT_SOCKET_TIMEOUT to prevent it blocking indefinitely whilst waiting for inbound data * Fixed return code when publishing >256 bytes - + 2.3 * Add publish(topic,payload,retained) function diff --git a/lib/PubSubClient-EspEasy-2.6.09/LICENSE.txt b/lib/PubSubClient-EspEasy-2.7.11/LICENSE.txt similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/LICENSE.txt rename to lib/PubSubClient-EspEasy-2.7.11/LICENSE.txt diff --git a/lib/PubSubClient-EspEasy-2.6.09/README.md b/lib/PubSubClient-EspEasy-2.7.11/README.md similarity index 95% rename from lib/PubSubClient-EspEasy-2.6.09/README.md rename to lib/PubSubClient-EspEasy-2.7.11/README.md index 83176919c..69cbb8f0c 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/README.md +++ b/lib/PubSubClient-EspEasy-2.7.11/README.md @@ -8,7 +8,7 @@ a server that supports MQTT. The library comes with a number of example sketches. See File > Examples > PubSubClient within the Arduino application. -Full API documentation is available here: http://pubsubclient.knolleary.net +Full API documentation is available here: https://pubsubclient.knolleary.net ## Limitations @@ -37,6 +37,7 @@ boards and shields, including: - TI CC3000 WiFi - [library](https://github.com/sparkfun/SFE_CC3000_Library) - Intel Galileo/Edison - ESP8266 + - ESP32 The library cannot currently be used with hardware based on the ENC28J60 chip – such as the Nanode or the Nuelectronics Ethernet Shield. For those, there is an diff --git a/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_auth/mqtt_auth.ino b/lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_auth/mqtt_auth.ino similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_auth/mqtt_auth.ino rename to lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_auth/mqtt_auth.ino diff --git a/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_basic/mqtt_basic.ino b/lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_basic/mqtt_basic.ino similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_basic/mqtt_basic.ino rename to lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_basic/mqtt_basic.ino diff --git a/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino b/lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_esp8266/mqtt_esp8266.ino similarity index 92% rename from lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino rename to lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_esp8266/mqtt_esp8266.ino index e46f85f3e..e7357b507 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino +++ b/lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_esp8266/mqtt_esp8266.ino @@ -38,14 +38,6 @@ long lastMsg = 0; char msg[50]; int value = 0; -void setup() { - pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output - Serial.begin(115200); - setup_wifi(); - client.setServer(mqtt_server, 1883); - client.setCallback(callback); -} - void setup_wifi() { delay(10); @@ -61,6 +53,8 @@ void setup_wifi() { Serial.print("."); } + randomSeed(micros()); + Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); @@ -80,7 +74,7 @@ void callback(char* topic, byte* payload, unsigned int length) { if ((char)payload[0] == '1') { digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level // but actually the LED is on; this is because - // it is acive low on the ESP-01) + // it is active low on the ESP-01) } else { digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH } @@ -91,8 +85,11 @@ void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); + // Create a random client ID + String clientId = "ESP8266Client-"; + clientId += String(random(0xffff), HEX); // Attempt to connect - if (client.connect("ESP8266Client")) { + if (client.connect(clientId.c_str())) { Serial.println("connected"); // Once connected, publish an announcement... client.publish("outTopic", "hello world"); @@ -107,6 +104,15 @@ void reconnect() { } } } + +void setup() { + pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output + Serial.begin(115200); + setup_wifi(); + client.setServer(mqtt_server, 1883); + client.setCallback(callback); +} + void loop() { if (!client.connected()) { @@ -118,7 +124,7 @@ void loop() { if (now - lastMsg > 2000) { lastMsg = now; ++value; - snprintf (msg, 75, "hello world #%ld", value); + snprintf (msg, 50, "hello world #%ld", value); Serial.print("Publish message: "); Serial.println(msg); client.publish("outTopic", msg); diff --git a/lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_large_message/mqtt_large_message.ino b/lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_large_message/mqtt_large_message.ino new file mode 100644 index 000000000..e048c3ed3 --- /dev/null +++ b/lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_large_message/mqtt_large_message.ino @@ -0,0 +1,179 @@ +/* + Long message ESP8266 MQTT example + + This sketch demonstrates sending arbitrarily large messages in combination + with the ESP8266 board/library. + + It connects to an MQTT server then: + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "greenBottles/#", printing out any messages + it receives. NB - it assumes the received payloads are strings not binary + - If the sub-topic is a number, it publishes a "greenBottles/lyrics" message + with a payload consisting of the lyrics to "10 green bottles", replacing + 10 with the number given in the sub-topic. + + It will reconnect to the server if the connection is lost using a blocking + reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to + achieve the same result without blocking the main loop. + + To install the ESP8266 board, (using Arduino 1.6.4+): + - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs": + http://arduino.esp8266.com/stable/package_esp8266com_index.json + - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266" + - Select your ESP8266 in "Tools -> Board" + +*/ + +#include +#include + +// Update these with values suitable for your network. + +const char* ssid = "........"; +const char* password = "........"; +const char* mqtt_server = "broker.mqtt-dashboard.com"; + +WiFiClient espClient; +PubSubClient client(espClient); +long lastMsg = 0; +char msg[50]; +int value = 0; + +void setup_wifi() { + + delay(10); + // We start by connecting to a WiFi network + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + + WiFi.begin(ssid, password); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + randomSeed(micros()); + + Serial.println(""); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} + +void callback(char* topic, byte* payload, unsigned int length) { + Serial.print("Message arrived ["); + Serial.print(topic); + Serial.print("] "); + for (int i = 0; i < length; i++) { + Serial.print((char)payload[i]); + } + Serial.println(); + + // Find out how many bottles we should generate lyrics for + String topicStr(topic); + int bottleCount = 0; // assume no bottles unless we correctly parse a value from the topic + if (topicStr.indexOf('/') >= 0) { + // The topic includes a '/', we'll try to read the number of bottles from just after that + topicStr.remove(0, topicStr.indexOf('/')+1); + // Now see if there's a number of bottles after the '/' + bottleCount = topicStr.toInt(); + } + + if (bottleCount > 0) { + // Work out how big our resulting message will be + int msgLen = 0; + for (int i = bottleCount; i > 0; i--) { + String numBottles(i); + msgLen += 2*numBottles.length(); + if (i == 1) { + msgLen += 2*String(" green bottle, standing on the wall\n").length(); + } else { + msgLen += 2*String(" green bottles, standing on the wall\n").length(); + } + msgLen += String("And if one green bottle should accidentally fall\nThere'll be ").length(); + switch (i) { + case 1: + msgLen += String("no green bottles, standing on the wall\n\n").length(); + break; + case 2: + msgLen += String("1 green bottle, standing on the wall\n\n").length(); + break; + default: + numBottles = i-1; + msgLen += numBottles.length(); + msgLen += String(" green bottles, standing on the wall\n\n").length(); + break; + }; + } + + // Now we can start to publish the message + client.beginPublish("greenBottles/lyrics", msgLen, false); + for (int i = bottleCount; i > 0; i--) { + for (int j = 0; j < 2; j++) { + client.print(i); + if (i == 1) { + client.print(" green bottle, standing on the wall\n"); + } else { + client.print(" green bottles, standing on the wall\n"); + } + } + client.print("And if one green bottle should accidentally fall\nThere'll be "); + switch (i) { + case 1: + client.print("no green bottles, standing on the wall\n\n"); + break; + case 2: + client.print("1 green bottle, standing on the wall\n\n"); + break; + default: + client.print(i-1); + client.print(" green bottles, standing on the wall\n\n"); + break; + }; + } + // Now we're done! + client.endPublish(); + } +} + +void reconnect() { + // Loop until we're reconnected + while (!client.connected()) { + Serial.print("Attempting MQTT connection..."); + // Create a random client ID + String clientId = "ESP8266Client-"; + clientId += String(random(0xffff), HEX); + // Attempt to connect + if (client.connect(clientId.c_str())) { + Serial.println("connected"); + // Once connected, publish an announcement... + client.publish("outTopic", "hello world"); + // ... and resubscribe + client.subscribe("greenBottles/#"); + } else { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + // Wait 5 seconds before retrying + delay(5000); + } + } +} + +void setup() { + pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output + Serial.begin(115200); + setup_wifi(); + client.setServer(mqtt_server, 1883); + client.setCallback(callback); +} + +void loop() { + + if (!client.connected()) { + reconnect(); + } + client.loop(); +} diff --git a/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino b/lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino rename to lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino diff --git a/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino b/lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino rename to lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino diff --git a/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_stream/mqtt_stream.ino b/lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_stream/mqtt_stream.ino similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_stream/mqtt_stream.ino rename to lib/PubSubClient-EspEasy-2.7.11/examples/mqtt_stream/mqtt_stream.ino diff --git a/lib/PubSubClient-EspEasy-2.6.09/keywords.txt b/lib/PubSubClient-EspEasy-2.7.11/keywords.txt similarity index 91% rename from lib/PubSubClient-EspEasy-2.6.09/keywords.txt rename to lib/PubSubClient-EspEasy-2.7.11/keywords.txt index b979588fe..1ee23d0fa 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/keywords.txt +++ b/lib/PubSubClient-EspEasy-2.7.11/keywords.txt @@ -16,6 +16,9 @@ connect KEYWORD2 disconnect KEYWORD2 publish KEYWORD2 publish_P KEYWORD2 +beginPublish KEYWORD2 +endPublish KEYWORD2 +write KEYWORD2 subscribe KEYWORD2 unsubscribe KEYWORD2 loop KEYWORD2 diff --git a/lib/PubSubClient-EspEasy-2.6.09/library.json b/lib/PubSubClient-EspEasy-2.7.11/library.json similarity index 97% rename from lib/PubSubClient-EspEasy-2.6.09/library.json rename to lib/PubSubClient-EspEasy-2.7.11/library.json index b96739078..8a36a1c5e 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/library.json +++ b/lib/PubSubClient-EspEasy-2.7.11/library.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://github.com/knolleary/pubsubclient.git" }, - "version": "2.6", + "version": "2.7", "exclude": "tests", "examples": "examples/*/*.ino", "frameworks": "arduino", diff --git a/lib/PubSubClient-EspEasy-2.6.09/library.properties b/lib/PubSubClient-EspEasy-2.7.11/library.properties similarity index 98% rename from lib/PubSubClient-EspEasy-2.6.09/library.properties rename to lib/PubSubClient-EspEasy-2.7.11/library.properties index 3ceeda81c..1ae97882e 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/library.properties +++ b/lib/PubSubClient-EspEasy-2.7.11/library.properties @@ -1,5 +1,5 @@ name=PubSubClient -version=2.6 +version=2.7 author=Nick O'Leary maintainer=Nick O'Leary sentence=A client library for MQTT messaging. diff --git a/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp b/lib/PubSubClient-EspEasy-2.7.11/src/PubSubClient.cpp similarity index 79% rename from lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp rename to lib/PubSubClient-EspEasy-2.7.11/src/PubSubClient.cpp index 79eb2d52e..9fe15006a 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp +++ b/lib/PubSubClient-EspEasy-2.7.11/src/PubSubClient.cpp @@ -102,30 +102,41 @@ PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGN } boolean PubSubClient::connect(const char *id) { - return connect(id,NULL,NULL,0,0,0,0); + return connect(id,NULL,NULL,0,0,0,0,1); } boolean PubSubClient::connect(const char *id, const char *user, const char *pass) { - return connect(id,user,pass,0,0,0,0); + return connect(id,user,pass,0,0,0,0,1); } boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) { - return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage); + return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage,1); } boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) { + return connect(id,user,pass,willTopic,willQos,willRetain,willMessage,1); +} + +boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession) { if (!connected()) { int result = 0; - if (domain.length() != 0) { - result = _client->connect(this->domain.c_str(), this->port); + if (_client == nullptr) { + return false; + } + if (_client->connected()) { + result = 1; } else { - result = _client->connect(this->ip, this->port); + if (domain != NULL) { + result = _client->connect(this->domain.c_str(), this->port); + } else { + result = _client->connect(this->ip, this->port); + } } if (result == 1) { nextMsgId = 1; // Leave room in the buffer for header and variable length field - uint16_t length = 5; + uint16_t length = MQTT_MAX_HEADER_SIZE; unsigned int j; #if MQTT_VERSION == MQTT_VERSION_3_1 @@ -141,9 +152,12 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass uint8_t v; if (willTopic) { - v = 0x06|(willQos<<3)|(willRetain<<5); + v = 0x04|(willQos<<3)|(willRetain<<5); } else { - v = 0x02; + v = 0x00; + } + if (cleanSession) { + v = v|0x02; } if(user != NULL) { @@ -158,24 +172,31 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass buffer[length++] = ((MQTT_KEEPALIVE) >> 8); buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF); + + CHECK_STRING_LENGTH(length,id) length = writeString(id,buffer,length); if (willTopic) { + CHECK_STRING_LENGTH(length,willTopic) length = writeString(willTopic,buffer,length); + CHECK_STRING_LENGTH(length,willMessage) length = writeString(willMessage,buffer,length); } if(user != NULL) { + CHECK_STRING_LENGTH(length,user) length = writeString(user,buffer,length); if(pass != NULL) { + CHECK_STRING_LENGTH(length,pass) length = writeString(pass,buffer,length); } } - write(MQTTCONNECT,buffer,length-5); + write(MQTTCONNECT,buffer,length-MQTT_MAX_HEADER_SIZE); lastInActivity = lastOutActivity = millis(); while (!_client->available()) { + delay(0); // Prevent watchdog crashes unsigned long t = millis(); if (t-lastInActivity >= ((int32_t) MQTT_SOCKET_TIMEOUT*1000UL)) { _state = MQTT_CONNECTION_TIMEOUT; @@ -207,9 +228,12 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass // reads a byte into result boolean PubSubClient::readByte(uint8_t * result) { + if (_client == nullptr) { + return false; + } uint32_t previousMillis = millis(); while(!_client->available()) { - delay(1); // Add esp8266 de-blocking (Tasmota #790, EspEasy #1943) + delay(1); // Prevent watchdog crashes uint32_t currentMillis = millis(); if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){ return false; @@ -241,7 +265,7 @@ uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { uint8_t start = 0; do { - if (len == 6) { + if (len == 5) { // Invalid remaining length encoding - kill the connection _state = MQTT_DISCONNECTED; _client->stop(); @@ -353,11 +377,13 @@ boolean PubSubClient::loop() { } boolean PubSubClient::publish(const char* topic, const char* payload) { - return publish(topic,(const uint8_t*)payload,strlen(payload),false); + size_t plength = (payload != nullptr) ? strlen(payload) : 0; + return publish(topic,(const uint8_t*)payload,plength,false); } boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) { - return publish(topic,(const uint8_t*)payload,strlen(payload),retained); + size_t plength = (payload != nullptr) ? strlen(payload) : 0; + return publish(topic,(const uint8_t*)payload,plength,retained); } boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) { @@ -366,12 +392,12 @@ boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigne boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) { if (connected()) { - if (MQTT_MAX_PACKET_SIZE < 5 + 2+strlen(topic) + plength) { + if (MQTT_MAX_PACKET_SIZE < MQTT_MAX_HEADER_SIZE + 2+strlen(topic) + plength) { // Too long return false; } // Leave room in the buffer for header and variable length field - uint16_t length = 5; + uint16_t length = MQTT_MAX_HEADER_SIZE; length = writeString(topic,buffer,length); uint16_t i; for (i=0;iwrite(buffer+(MQTT_MAX_HEADER_SIZE-hlen),length-(MQTT_MAX_HEADER_SIZE-hlen)); + lastOutActivity = millis(); + return (rc == (length-(MQTT_MAX_HEADER_SIZE-hlen))); + } + return false; +} + +int PubSubClient::endPublish() { + return 1; +} + +size_t PubSubClient::write(uint8_t data) { + lastOutActivity = millis(); + if (_client == nullptr) { + return 0; + } + return _client->write(data); +} + +size_t PubSubClient::write(const uint8_t *buffer, size_t size) { + lastOutActivity = millis(); + if (_client == nullptr) { + return 0; + } + return _client->write(buffer,size); +} + +size_t PubSubClient::buildHeader(uint8_t header, uint8_t* buf, uint16_t length) { uint8_t lenBuf[4]; uint8_t llen = 0; uint8_t digit; uint8_t pos = 0; - uint16_t rc; uint16_t len = length; do { digit = len % 128; @@ -450,15 +519,22 @@ boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { buf[4-llen] = header; for (int i=0;i 0) && result) { + delay(0); // Prevent watchdog crashes bytesToWrite = (bytesRemaining > MQTT_MAX_TRANSFER_SIZE)?MQTT_MAX_TRANSFER_SIZE:bytesRemaining; rc = _client->write(writeBuf,bytesToWrite); result = (rc == bytesToWrite); @@ -467,9 +543,9 @@ boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { } return result; #else - rc = _client->write(buf+(4-llen),length+1+llen); + rc = _client->write(buf+(MQTT_MAX_HEADER_SIZE-hlen),length+hlen); lastOutActivity = millis(); - return (rc == 1+llen+length); + return (rc == hlen+length); #endif } @@ -487,7 +563,7 @@ boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { } if (connected()) { // Leave room in the buffer for header and variable length field - uint16_t length = 5; + uint16_t length = MQTT_MAX_HEADER_SIZE; nextMsgId++; if (nextMsgId == 0) { nextMsgId = 1; @@ -496,7 +572,7 @@ boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { buffer[length++] = (nextMsgId & 0xFF); length = writeString((char*)topic, buffer,length); buffer[length++] = qos; - return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-5); + return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE); } return false; } @@ -507,7 +583,7 @@ boolean PubSubClient::unsubscribe(const char* topic) { return false; } if (connected()) { - uint16_t length = 5; + uint16_t length = MQTT_MAX_HEADER_SIZE; nextMsgId++; if (nextMsgId == 0) { nextMsgId = 1; @@ -515,7 +591,7 @@ boolean PubSubClient::unsubscribe(const char* topic) { buffer[length++] = (nextMsgId >> 8); buffer[length++] = (nextMsgId & 0xFF); length = writeString(topic, buffer,length); - return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-5); + return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE); } return false; } @@ -523,7 +599,7 @@ boolean PubSubClient::unsubscribe(const char* topic) { void PubSubClient::disconnect() { buffer[0] = MQTTDISCONNECT; buffer[1] = 0; - if (_client != NULL) { + if (_client != nullptr) { _client->write(buffer,2); _client->flush(); _client->stop(); @@ -558,6 +634,8 @@ boolean PubSubClient::connected() { _client->flush(); _client->stop(); } + } else { + return this->_state == MQTT_CONNECTED; } } return rc; diff --git a/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.h b/lib/PubSubClient-EspEasy-2.7.11/src/PubSubClient.h similarity index 76% rename from lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.h rename to lib/PubSubClient-EspEasy-2.7.11/src/PubSubClient.h index 003df770e..a519f75d7 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.h +++ b/lib/PubSubClient-EspEasy-2.7.11/src/PubSubClient.h @@ -75,6 +75,9 @@ #define MQTTQOS1 (1 << 1) #define MQTTQOS2 (2 << 1) +// Maximum size of fixed header and variable length size header +#define MQTT_MAX_HEADER_SIZE 5 + #if defined(ESP8266) || defined(ESP32) #include #define MQTT_CALLBACK_SIGNATURE std::function callback @@ -82,7 +85,9 @@ #define MQTT_CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int) #endif -class PubSubClient { +#define CHECK_STRING_LENGTH(l,s) if (l+2+strlen(s) > MQTT_MAX_PACKET_SIZE) {_client->stop();return false;} + +class PubSubClient : public Print { private: Client* _client; uint8_t buffer[MQTT_MAX_PACKET_SIZE]; @@ -96,6 +101,11 @@ private: boolean readByte(uint8_t * result, uint16_t * index); boolean write(uint8_t header, uint8_t* buf, uint16_t length); uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos); + // Build up the header ready to send + // Returns the size of the header + // Note: the header is built at the end of the first MQTT_MAX_HEADER_SIZE bytes, so will start + // (MQTT_MAX_HEADER_SIZE - ) bytes into the buffer + size_t buildHeader(uint8_t header, uint8_t* buf, uint16_t length); IPAddress ip; String domain; uint16_t port; @@ -129,12 +139,31 @@ public: boolean connect(const char* id, const char* user, const char* pass); boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); + boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession); void disconnect(); boolean publish(const char* topic, const char* payload); boolean publish(const char* topic, const char* payload, boolean retained); boolean publish(const char* topic, const uint8_t * payload, unsigned int plength); boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); + boolean publish_P(const char* topic, const char* payload, boolean retained); boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); + // Start to publish a message. + // This API: + // beginPublish(...) + // one or more calls to write(...) + // endPublish() + // Allows for arbitrarily large payloads to be sent without them having to be copied into + // a new buffer and held in memory at one time + // Returns 1 if the message was started successfully, 0 if there was an error + boolean beginPublish(const char* topic, unsigned int plength, boolean retained); + // Finish off this publish message (started with beginPublish) + // Returns 1 if the packet was sent successfully, 0 if there was an error + int endPublish(); + // Write a single byte of payload (only to be used with beginPublish/endPublish) + virtual size_t write(uint8_t); + // Write size bytes from buffer into the payload (only to be used with beginPublish/endPublish) + // Returns the number of bytes written + virtual size_t write(const uint8_t *buffer, size_t size); boolean subscribe(const char* topic); boolean subscribe(const char* topic, uint8_t qos); boolean unsubscribe(const char* topic); diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/.gitignore b/lib/PubSubClient-EspEasy-2.7.11/tests/.gitignore similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/.gitignore rename to lib/PubSubClient-EspEasy-2.7.11/tests/.gitignore diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/Makefile b/lib/PubSubClient-EspEasy-2.7.11/tests/Makefile similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/Makefile rename to lib/PubSubClient-EspEasy-2.7.11/tests/Makefile diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/README.md b/lib/PubSubClient-EspEasy-2.7.11/tests/README.md similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/README.md rename to lib/PubSubClient-EspEasy-2.7.11/tests/README.md diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/connect_spec.cpp b/lib/PubSubClient-EspEasy-2.7.11/tests/src/connect_spec.cpp similarity index 83% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/connect_spec.cpp rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/connect_spec.cpp index 69f18646f..e27a1f59f 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/tests/src/connect_spec.cpp +++ b/lib/PubSubClient-EspEasy-2.7.11/tests/src/connect_spec.cpp @@ -98,6 +98,33 @@ int test_connect_fails_on_bad_rc() { END_IT } +int test_connect_non_clean_session() { + IT("sends a properly formatted non-clean session connect packet and succeeds"); + ShimClient shimClient; + + shimClient.setAllowConnect(true); + byte expectServer[] = { 172, 16, 0, 2 }; + shimClient.expectConnect(expectServer,1883); + byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x0,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + + shimClient.expect(connect,26); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int state = client.state(); + IS_TRUE(state == MQTT_DISCONNECTED); + + int rc = client.connect((char*)"client_test1",0,0,0,0,0,0,0); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + state = client.state(); + IS_TRUE(state == MQTT_CONNECTED); + + END_IT +} + int test_connect_accepts_username_password() { IT("accepts a username and password"); ShimClient shimClient; @@ -133,6 +160,23 @@ int test_connect_accepts_username_no_password() { END_IT } +int test_connect_accepts_username_blank_password() { + IT("accepts a username and blank password"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connect[] = { 0x10,0x20,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0xc2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72,0x0,0x0}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.expect(connect,0x26); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"pass"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} int test_connect_ignores_password_no_username() { IT("ignores a password but no username"); @@ -239,10 +283,12 @@ int test_connect_disconnect_connect() { int main() { SUITE("Connect"); + test_connect_fails_no_network(); test_connect_fails_on_no_response(); test_connect_properly_formatted(); + test_connect_non_clean_session(); test_connect_accepts_username_password(); test_connect_fails_on_bad_rc(); test_connect_properly_formatted_hostname(); diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/keepalive_spec.cpp b/lib/PubSubClient-EspEasy-2.7.11/tests/src/keepalive_spec.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/keepalive_spec.cpp rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/keepalive_spec.cpp diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Arduino.h b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Arduino.h similarity index 90% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Arduino.h rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Arduino.h index c6752801a..2a00f24bc 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Arduino.h +++ b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Arduino.h @@ -5,6 +5,7 @@ #include #include #include +#include "Print.h" extern "C"{ @@ -20,4 +21,6 @@ extern "C"{ #define PROGMEM #define pgm_read_byte_near(x) *(x) +#define yield(x) {} + #endif // Arduino_h diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/BDDTest.cpp b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/BDDTest.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/BDDTest.cpp rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/BDDTest.cpp diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/BDDTest.h b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/BDDTest.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/BDDTest.h rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/BDDTest.h diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.cpp b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Buffer.cpp similarity index 86% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.cpp rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Buffer.cpp index 59a2fbbbd..f07759a3a 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.cpp +++ b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Buffer.cpp @@ -2,9 +2,13 @@ #include "Arduino.h" Buffer::Buffer() { + this->pos = 0; + this->length = 0; } Buffer::Buffer(uint8_t* buf, size_t size) { + this->pos = 0; + this->length = 0; this->add(buf,size); } bool Buffer::available() { diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.h b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Buffer.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.h rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Buffer.h diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Client.h b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Client.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Client.h rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Client.h diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/IPAddress.cpp b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/IPAddress.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/IPAddress.cpp rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/IPAddress.cpp diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/IPAddress.h b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/IPAddress.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/IPAddress.h rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/IPAddress.h diff --git a/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Print.h b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Print.h new file mode 100644 index 000000000..02ef77c2c --- /dev/null +++ b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Print.h @@ -0,0 +1,28 @@ +/* + Print.h - Base class that provides print() and println() + Copyright (c) 2008 David A. Mellis. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef Print_h +#define Print_h + +class Print { + public: + virtual size_t write(uint8_t) = 0; +}; + +#endif diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/ShimClient.cpp b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/ShimClient.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/ShimClient.cpp rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/ShimClient.cpp diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/ShimClient.h b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/ShimClient.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/ShimClient.h rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/ShimClient.h diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Stream.cpp b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Stream.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Stream.cpp rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Stream.cpp diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Stream.h b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Stream.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Stream.h rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/Stream.h diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/trace.h b/lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/trace.h similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/trace.h rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/lib/trace.h diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/publish_spec.cpp b/lib/PubSubClient-EspEasy-2.7.11/tests/src/publish_spec.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/publish_spec.cpp rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/publish_spec.cpp diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/receive_spec.cpp b/lib/PubSubClient-EspEasy-2.7.11/tests/src/receive_spec.cpp similarity index 89% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/receive_spec.cpp rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/receive_spec.cpp index 54a62ee5c..9a18af042 100644 --- a/lib/PubSubClient-EspEasy-2.6.09/tests/src/receive_spec.cpp +++ b/lib/PubSubClient-EspEasy-2.7.11/tests/src/receive_spec.cpp @@ -160,6 +160,35 @@ int test_receive_oversized_message() { END_IT } +int test_drop_invalid_remaining_length_message() { + IT("drops invalid remaining length message"); + reset_callback(); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0x92,0x92,0x92,0x92,0x01,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + shimClient.respond(publish,20); + + rc = client.loop(); + + IS_FALSE(rc); + + IS_FALSE(callback_called); + + IS_FALSE(shimClient.error()); + + END_IT +} + + int test_receive_oversized_stream_message() { IT("drops an oversized message"); reset_callback(); @@ -241,6 +270,7 @@ int main() test_receive_callback(); test_receive_stream(); test_receive_max_sized_message(); + test_drop_invalid_remaining_length_message(); test_receive_oversized_message(); test_receive_oversized_stream_message(); test_receive_qos1(); diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/src/subscribe_spec.cpp b/lib/PubSubClient-EspEasy-2.7.11/tests/src/subscribe_spec.cpp similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/src/subscribe_spec.cpp rename to lib/PubSubClient-EspEasy-2.7.11/tests/src/subscribe_spec.cpp diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/__init__.py b/lib/PubSubClient-EspEasy-2.7.11/tests/testcases/__init__.py similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/testcases/__init__.py rename to lib/PubSubClient-EspEasy-2.7.11/tests/testcases/__init__.py diff --git a/lib/PubSubClient-EspEasy-2.7.11/tests/testcases/mqtt_basic.py b/lib/PubSubClient-EspEasy-2.7.11/tests/testcases/mqtt_basic.py new file mode 100644 index 000000000..f23ef71c1 --- /dev/null +++ b/lib/PubSubClient-EspEasy-2.7.11/tests/testcases/mqtt_basic.py @@ -0,0 +1,39 @@ +import unittest +import settings +import time +import mosquitto + + +def on_message(mosq, obj, msg): + obj.message_queue.append(msg) + + +class mqtt_basic(unittest.TestCase): + + message_queue = [] + + @classmethod + def setUpClass(self): + self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self) + self.client.connect(settings.server_ip) + self.client.on_message = on_message + self.client.subscribe("outTopic", 0) + + @classmethod + def tearDownClass(self): + self.client.disconnect() + + def test_one(self): + i = 30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + self.assertTrue(i > 0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue[0] + self.assertEqual(msg.mid, 0, "message id not 0") + self.assertEqual(msg.topic, "outTopic", "message topic incorrect") + self.assertEqual(msg.payload, "hello world") + self.assertEqual(msg.qos, 0, "message qos not 0") + self.assertEqual(msg.retain, False, "message retain flag incorrect") diff --git a/lib/PubSubClient-EspEasy-2.7.11/tests/testcases/mqtt_publish_in_callback.py b/lib/PubSubClient-EspEasy-2.7.11/tests/testcases/mqtt_publish_in_callback.py new file mode 100644 index 000000000..45b0a8515 --- /dev/null +++ b/lib/PubSubClient-EspEasy-2.7.11/tests/testcases/mqtt_publish_in_callback.py @@ -0,0 +1,59 @@ +import unittest +import settings +import time +import mosquitto + + +def on_message(mosq, obj, msg): + obj.message_queue.append(msg) + + +class mqtt_publish_in_callback(unittest.TestCase): + + message_queue = [] + + @classmethod + def setUpClass(self): + self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self) + self.client.connect(settings.server_ip) + self.client.on_message = on_message + self.client.subscribe("outTopic", 0) + + @classmethod + def tearDownClass(self): + self.client.disconnect() + + def test_connect(self): + i = 30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + self.assertTrue(i > 0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue.pop(0) + self.assertEqual(msg.mid, 0, "message id not 0") + self.assertEqual(msg.topic, "outTopic", "message topic incorrect") + self.assertEqual(msg.payload, "hello world") + self.assertEqual(msg.qos, 0, "message qos not 0") + self.assertEqual(msg.retain, False, "message retain flag incorrect") + + def test_publish(self): + self.assertEqual(len(self.message_queue), 0, "message queue not empty") + payload = "abcdefghij" + self.client.publish("inTopic", payload) + + i = 30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + + self.assertTrue(i > 0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue.pop(0) + self.assertEqual(msg.mid, 0, "message id not 0") + self.assertEqual(msg.topic, "outTopic", "message topic incorrect") + self.assertEqual(msg.payload, payload) + self.assertEqual(msg.qos, 0, "message qos not 0") + self.assertEqual(msg.retain, False, "message retain flag incorrect") diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/settings.py b/lib/PubSubClient-EspEasy-2.7.11/tests/testcases/settings.py similarity index 100% rename from lib/PubSubClient-EspEasy-2.6.09/tests/testcases/settings.py rename to lib/PubSubClient-EspEasy-2.7.11/tests/testcases/settings.py diff --git a/lib/PubSubClient-EspEasy-2.7.11/tests/testsuite.py b/lib/PubSubClient-EspEasy-2.7.11/tests/testsuite.py new file mode 100644 index 000000000..788fc5d97 --- /dev/null +++ b/lib/PubSubClient-EspEasy-2.7.11/tests/testsuite.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python +import os +import os.path +import sys +import shutil +from subprocess import call +import importlib +import unittest +import re + +from testcases import settings + + +class Workspace(object): + + def __init__(self): + self.root_dir = os.getcwd() + self.build_dir = os.path.join(self.root_dir, "tmpbin") + self.log_dir = os.path.join(self.root_dir, "logs") + self.tests_dir = os.path.join(self.root_dir, "testcases") + self.examples_dir = os.path.join(self.root_dir, "../PubSubClient/examples") + self.examples = [] + self.tests = [] + if not os.path.isdir("../PubSubClient"): + raise Exception("Cannot find PubSubClient library") + try: + return __import__('ino') + except ImportError: + raise Exception("ino tool not installed") + + def init(self): + if os.path.isdir(self.build_dir): + shutil.rmtree(self.build_dir) + os.mkdir(self.build_dir) + if os.path.isdir(self.log_dir): + shutil.rmtree(self.log_dir) + os.mkdir(self.log_dir) + + os.chdir(self.build_dir) + call(["ino", "init"]) + + shutil.copytree("../../PubSubClient", "lib/PubSubClient") + + filenames = [] + for root, dirs, files in os.walk(self.examples_dir): + filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")] + filenames.sort() + for e in filenames: + self.examples.append(Sketch(self, e)) + + filenames = [] + for root, dirs, files in os.walk(self.tests_dir): + filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")] + filenames.sort() + for e in filenames: + self.tests.append(Sketch(self, e)) + + def clean(self): + shutil.rmtree(self.build_dir) + + +class Sketch(object): + def __init__(self, wksp, fn): + self.w = wksp + self.filename = fn + self.basename = os.path.basename(self.filename) + self.build_log = os.path.join(self.w.log_dir, "%s.log" % (os.path.basename(self.filename),)) + self.build_err_log = os.path.join(self.w.log_dir, "%s.err.log" % (os.path.basename(self.filename),)) + self.build_upload_log = os.path.join(self.w.log_dir, "%s.upload.log" % (os.path.basename(self.filename),)) + + def build(self): + sys.stdout.write(" Build: ") + sys.stdout.flush() + + # Copy sketch over, replacing IP addresses as necessary + fin = open(self.filename, "r") + lines = fin.readlines() + fin.close() + fout = open(os.path.join(self.w.build_dir, "src", "sketch.ino"), "w") + for l in lines: + if re.match(r"^byte server\[\] = {", l): + fout.write("byte server[] = { %s };\n" % (settings.server_ip.replace(".", ", "),)) + elif re.match(r"^byte ip\[\] = {", l): + fout.write("byte ip[] = { %s };\n" % (settings.arduino_ip.replace(".", ", "),)) + else: + fout.write(l) + fout.flush() + fout.close() + + # Run build + fout = open(self.build_log, "w") + ferr = open(self.build_err_log, "w") + rc = call(["ino", "build"], stdout=fout, stderr=ferr) + fout.close() + ferr.close() + if rc == 0: + sys.stdout.write("pass") + sys.stdout.write("\n") + return True + else: + sys.stdout.write("fail") + sys.stdout.write("\n") + with open(self.build_err_log) as f: + for line in f: + print(" " + line) + return False + + def upload(self): + sys.stdout.write(" Upload: ") + sys.stdout.flush() + fout = open(self.build_upload_log, "w") + rc = call(["ino", "upload"], stdout=fout, stderr=fout) + fout.close() + if rc == 0: + sys.stdout.write("pass") + sys.stdout.write("\n") + return True + else: + sys.stdout.write("fail") + sys.stdout.write("\n") + with open(self.build_upload_log) as f: + for line in f: + print(" " + line) + return False + + def test(self): + # import the matching test case, if it exists + try: + basename = os.path.basename(self.filename)[:-4] + i = importlib.import_module("testcases." + basename) + except: + sys.stdout.write(" Test: no tests found") + sys.stdout.write("\n") + return + c = getattr(i, basename) + + testmethods = [m for m in dir(c) if m.startswith("test_")] + testmethods.sort() + tests = [] + for m in testmethods: + tests.append(c(m)) + + result = unittest.TestResult() + c.setUpClass() + if self.upload(): + sys.stdout.write(" Test: ") + sys.stdout.flush() + for t in tests: + t.run(result) + print(str(result.testsRun - len(result.failures) - len(result.errors)) + "/" + str(result.testsRun)) + if not result.wasSuccessful(): + if len(result.failures) > 0: + for f in result.failures: + print("-- " + str(f[0])) + print(f[1]) + if len(result.errors) > 0: + print(" Errors:") + for f in result.errors: + print("-- " + str(f[0])) + print(f[1]) + c.tearDownClass() + + +if __name__ == '__main__': + run_tests = True + + w = Workspace() + w.init() + + for e in w.examples: + print("--------------------------------------") + print("[" + e.basename + "]") + if e.build() and run_tests: + e.test() + for e in w.tests: + print("--------------------------------------") + print("[" + e.basename + "]") + if e.build() and run_tests: + e.test() + + w.clean() From 1fb881a77e9061c4639fb87e71b41742373eb925 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Wed, 29 May 2019 12:16:04 +0200 Subject: [PATCH 1420/2222] SDM230 reset readings when offline --- sonoff/xsns_23_sdm120.ino | 53 ++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino index 8f0b6b74f..7c8e064de 100644 --- a/sonoff/xsns_23_sdm120.ino +++ b/sonoff/xsns_23_sdm120.ino @@ -27,8 +27,20 @@ #define XSNS_23 23 +// can be user defined in my_user_config.h +#ifndef SDM120_SPEED + #define SDM120_SPEED 2400 // default SDM120 Modbus address +#endif +// can be user defined in my_user_config.h +#ifndef SDM120_ADDR + #define SDM120_ADDR 1 // default SDM120 Modbus address +#endif + + #include +enum SDM120_Error {SDM120_ERR_NO_ERROR=0, SDM120_ERR_CRC_ERROR, SDM120_ERR_WRONG_BYTES, SDM120_ERR_NOT_ENOUGHT_BYTES}; + TasmotaSerial *SDM120Serial; uint8_t sdm120_type = 1; @@ -58,7 +70,7 @@ void SDM120_ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t r { uint8_t frame[8]; - frame[0] = 0x01; // default SDM120 Modbus address + frame[0] = SDM120_ADDR; frame[1] = function_code; frame[2] = (uint8_t)(start_address >> 8); frame[3] = (uint8_t)(start_address); @@ -87,13 +99,12 @@ uint8_t SDM120_ModbusReceive(float *value) buffer[len++] = (uint8_t)SDM120Serial->read(); } - if (len < 9) - return 3; // SDM_ERR_NOT_ENOUGHT_BYTES - - if (len == 9) { - - if (buffer[0] == 0x01 && buffer[1] == 0x04 && buffer[2] == 4) { // check node number, op code and reply bytes count + if (len < 9) { + return SDM120_ERR_NOT_ENOUGHT_BYTES; + } + if (9 == len) { + if (0x01 == buffer[0] && 0x04 == buffer[1] && 4 == buffer[2]) { // check node number, op code and reply bytes count if((SDM120_calculateCRC(buffer, 7)) == ((buffer[8] << 8) | buffer[7])) { //calculate crc from first 7 bytes and compare with received crc (bytes 7 & 8) ((uint8_t*)value)[3] = buffer[3]; @@ -101,12 +112,16 @@ uint8_t SDM120_ModbusReceive(float *value) ((uint8_t*)value)[1] = buffer[5]; ((uint8_t*)value)[0] = buffer[6]; - } else return 1; // SDM_ERR_CRC_ERROR + } else { + return SDM120_ERR_CRC_ERROR; + } - } else return 2; // SDM_ERR_WRONG_BYTES + } else { + return SDM120_ERR_WRONG_BYTES; + } } - return 0; // SDM_ERR_NO_ERROR + return SDM120_ERR_NO_ERROR; } uint16_t SDM120_calculateCRC(uint8_t *frame, uint8_t num) @@ -152,6 +167,7 @@ const uint16_t sdm120_start_addresses[] { uint8_t sdm120_read_state = 0; uint8_t sdm120_send_retry = 0; +uint8_t sdm120_nodata_count = 0; void SDM120250ms(void) // Every 250 mSec { @@ -163,6 +179,7 @@ void SDM120250ms(void) // Every 250 mSec bool data_ready = SDM120_ModbusReceiveReady(); if (data_ready) { + sdm120_nodata_count = 0; uint8_t error = SDM120_ModbusReceive(&value); if (error) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM120 response error %d"), error); @@ -233,6 +250,18 @@ void SDM120250ms(void) // Every 250 mSec } } } // end data ready + else { + if (sdm120_nodata_count <= (1000/250) * 4) { // max. 4 sec without data + sdm120_nodata_count++; + } else if (sdm120_nodata_count != 255) { + // no data from modbus, reset values to 0 + sdm120_nodata_count = 255; + sdm120_voltage = sdm120_current = sdm120_active_power = sdm120_apparent_power = sdm120_reactive_power = sdm120_power_factor = sdm120_frequency = sdm120_energy_total = 0; +#ifdef USE_SDM220 + sdm120_phase_angle = sdm120_import_active = sdm120_export_active = sdm120_import_reactive = sdm120_export_reactive = sdm120_total_reactive = 0; +#endif + } + } if (0 == sdm120_send_retry || data_ready) { sdm120_send_retry = 5; @@ -248,11 +277,7 @@ void SDM120Init(void) sdm120_type = 0; if ((pin[GPIO_SDM120_RX] < 99) && (pin[GPIO_SDM120_TX] < 99)) { SDM120Serial = new TasmotaSerial(pin[GPIO_SDM120_RX], pin[GPIO_SDM120_TX], 1); -#ifdef SDM120_SPEED if (SDM120Serial->begin(SDM120_SPEED)) { -#else - if (SDM120Serial->begin(2400)) { -#endif if (SDM120Serial->hardwareSerial()) { ClaimSerial(); } sdm120_type = 1; } From adf0eb03ef73d1afae1a80819e0a926b987acd27 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Wed, 29 May 2019 14:08:37 +0200 Subject: [PATCH 1421/2222] decode-config.py: adapt settings - add AdcParam (adc_param*) - cleanup vars may having conflict with keywords (PEP 8) --- tools/decode-config.py | 118 ++++++++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 44 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index f3e2b526b..94d0cc4fa 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.2.0026' +VER = '2.2.0027' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -908,7 +908,19 @@ Setting_6_5_0_11['flag3'][0].update ({ 'use_underscore': ('> sys.stderr, '{styp}{sdelimiter}{sstatus}{slineno}{scolon}{smgs}'.format(\ - styp=typ if typ is not None else '', - sdelimiter=' ' if status is not None and status > 0 and typ is not None else '', + styp=type_ if type_ is not None else '', + sdelimiter=' ' if status is not None and status > 0 and type_ is not None else '', sstatus=status if status is not None and status > 0 else '', - scolon=': ' if typ is not None or line is not None else '', + scolon=': ' if type_ is not None or line is not None else '', smgs=msg, slineno=' (@{:04d})'.format(line) if line is not None else '') -def exit(status=0, msg="end", typ=LogType.ERROR, src=None, doexit=True, line=None): +def exit(status=0, msg="end", type_=LogType.ERROR, src=None, doexit=True, line=None): """ Called when the program should be exit @@ -987,7 +999,7 @@ def exit(status=0, msg="end", typ=LogType.ERROR, src=None, doexit=True, line=Non the exit status program returns to callert @param msg: the msg logged before exit - @param typ: + @param type_: msg type: 'INFO', 'WARNING' or 'ERROR' @param doexit: True to exit program, otherwise return @@ -995,7 +1007,7 @@ def exit(status=0, msg="end", typ=LogType.ERROR, src=None, doexit=True, line=Non if src is not None: msg = '{} ({})'.format(src, msg) - message(msg, typ=typ if status!=ExitCode.OK else LogType.INFO, status=status, line=line) + message(msg, type_=type_ if status!=ExitCode.OK else LogType.INFO, status=status, line=line) exitcode = status if doexit: sys.exit(exitcode) @@ -1451,7 +1463,7 @@ def GetTasmotaHostname(host, port, username=DEFAULTS['source']['username'], pass if "StatusNET" in jsonbody and "Hostname" in jsonbody["StatusNET"]: hostname = jsonbody["StatusNET"]["Hostname"] if args.verbose: - message("Hostname for '{}' retrieved: '{}'".format(host, hostname), typ=LogType.INFO) + message("Hostname for '{}' retrieved: '{}'".format(host, hostname), type_=LogType.INFO) return hostname @@ -1759,7 +1771,7 @@ def ReadWriteConverter(value, fielddef, read=True, raw=False): elif callable(conv): # use as format function return conv(value) except Exception, e: - exit(e[0], e[1], typ=LogType.WARNING, line=inspect.getlineno(inspect.currentframe())) + exit(e[0], e[1], type_=LogType.WARNING, line=inspect.getlineno(inspect.currentframe())) return value @@ -2082,15 +2094,33 @@ def SetFieldValue(fielddef, dobj, addr, value): addr += (bitsize / 8) * formatcnt for _ in range(0, formatcnt): addr -= (bitsize / 8) - val = value & ((2**bitsize) - 1) + maxunsigned = ((2**bitsize) - 1) + maxsigned = ((2**bitsize)>>1)-1 + val = value & maxunsigned + if isinstance(value,int) and value < 0 and val > maxsigned: + val = ((maxunsigned+1)-val) * (-1) if args.debug >= 3: print >> sys.stderr, "SetFieldValue(): Single type - fielddef {}, addr 0x{:04x} value {} singletype {} bitsize {}".format(fielddef,addr,val,singletype,bitsize) - struct.pack_into(singletype, dobj, addr, val) + try: + struct.pack_into(singletype, dobj, addr, val) + except struct.error as e: + exit(ExitCode.RESTORE_DATA_ERROR, + "Single type {} [fielddef={}, addr=0x{:04x}, value={}] - skipped!".format(e,fielddef,addr,val), + type_=LogType.WARNING, + doexit=not args.ignorewarning, + line=inspect.getlineno(inspect.currentframe())) value >>= bitsize else: if args.debug >= 3: print >> sys.stderr, "SetFieldValue(): String type - fielddef {}, addr 0x{:04x} value {} format_ {}".format(fielddef,addr,value,format_) - struct.pack_into(format_, dobj, addr, value) + try: + struct.pack_into(format_, dobj, addr, value) + except struct.error as e: + exit(ExitCode.RESTORE_DATA_ERROR, + "String type {} [fielddef={}, addr=0x{:04x}, value={}} - skipped!".format(e,fielddef,addr,value), + type_=LogType.WARNING, + doexit=not args.ignorewarning, + line=inspect.getlineno(inspect.currentframe())) return dobj @@ -2156,7 +2186,7 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): valuemapping = ReadWriteConverter(GetFieldValue(fielddef, dobj, baseaddr+addroffset), fielddef, read=True, raw=raw) else: - exit(ExitCode.INTERNAL_ERROR, "Wrong mapping format definition: '{}'".format(format_), typ=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) + exit(ExitCode.INTERNAL_ERROR, "Wrong mapping format definition: '{}'".format(format_), type_=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) return valuemapping @@ -2199,7 +2229,7 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""): if isinstance(arraydef, list) and len(arraydef) > 0: offset = 0 if len(restore) > arraydef[0]: - exit(ExitCode.RESTORE_DATA_ERROR, "file '{sfile}', array '{sname}[{selem}]' exceeds max number of elements [{smax}]".format(sfile=filename, sname=fieldname, selem=len(restore), smax=arraydef[0]), typ=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) + exit(ExitCode.RESTORE_DATA_ERROR, "file '{sfile}', array '{sname}[{selem}]' exceeds max number of elements [{smax}]".format(sfile=filename, sname=fieldname, selem=len(restore), smax=arraydef[0]), type_=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) for i in range(0, arraydef[0]): subfielddef = GetSubfieldDef(fielddef) length = GetFieldLength(subfielddef) @@ -2231,7 +2261,7 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""): try: value = ReadWriteConverter(restore.encode(STR_ENCODING)[0], fielddef, read=False) except Exception, e: - exit(e[0], e[1], typ=LogType.WARNING, line=inspect.getlineno(inspect.currentframe())) + exit(e[0], e[1], type_=LogType.WARNING, line=inspect.getlineno(inspect.currentframe())) valid = False # bool @@ -2239,7 +2269,7 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""): try: value = ReadWriteConverter(bool(restore), fielddef, read=False) except Exception, e: - exit(e[0], e[1], typ=LogType.WARNING, line=inspect.getlineno(inspect.currentframe())) + exit(e[0], e[1], type_=LogType.WARNING, line=inspect.getlineno(inspect.currentframe())) valid = False # integer @@ -2331,13 +2361,13 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""): dobj = SetFieldValue(fielddef, dobj, baseaddr+addroffset, value) curvalue = GetFieldValue(fielddef, dobj, baseaddr+addroffset) if prevvalue != curvalue and args.verbose: - message("Value for '{}' changed from {} to {}".format(fieldname, prevvalue, curvalue), typ=LogType.INFO) + message("Value for '{}' changed from {} to {}".format(fieldname, prevvalue, curvalue), type_=LogType.INFO) else: if args.debug >= 2: print >> sys.stderr, "SetField(): Special field '{}' using '{}'/{}{} @{} skipped".format(fieldname, format_, arraydef, bits, hex(baseaddr+addroffset)) else: sformat = "file '{sfile}' - {{'{sname}': {svalue}}} ({serror})"+errformat - exit(ExitCode.RESTORE_DATA_ERROR, sformat.format(sfile=filename, sname=fieldname, serror=err, svalue=_value, smin=min_, smax=max_), typ=LogType.WARNING, doexit=not args.ignorewarning) + exit(ExitCode.RESTORE_DATA_ERROR, sformat.format(sfile=filename, sname=fieldname, serror=err, svalue=_value, smin=min_, smax=max_), type_=LogType.WARNING, doexit=not args.ignorewarning) return dobj @@ -2377,7 +2407,7 @@ def SetCmnd(cmnds, fieldname, fielddef, valuemapping, mappedvalue, addroffset=0, if isinstance(arraydef, list) and len(arraydef) > 0: offset = 0 if len(mappedvalue) > arraydef[0]: - exit(ExitCode.RESTORE_DATA_ERROR, "array '{sname}[{selem}]' exceeds max number of elements [{smax}]".format(sname=fieldname, selem=len(mappedvalue), smax=arraydef[0]), typ=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) + exit(ExitCode.RESTORE_DATA_ERROR, "array '{sname}[{selem}]' exceeds max number of elements [{smax}]".format(sname=fieldname, selem=len(mappedvalue), smax=arraydef[0]), type_=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) for i in range(0, arraydef[0]): subfielddef = GetSubfieldDef(fielddef) length = GetFieldLength(subfielddef) @@ -2443,10 +2473,10 @@ def Bin2Mapping(decode_cfg): # read size should be same as definied in setting if cfg_size > size: # may be processed - exit(ExitCode.DATA_SIZE_MISMATCH, "Number of bytes read does ot match - read {}, expected {} byte".format(cfg_size, size), typ=LogType.ERROR,line=inspect.getlineno(inspect.currentframe())) + exit(ExitCode.DATA_SIZE_MISMATCH, "Number of bytes read does ot match - read {}, expected {} byte".format(cfg_size, size), type_=LogType.ERROR,line=inspect.getlineno(inspect.currentframe())) elif cfg_size < size: # less number of bytes can not be processed - exit(ExitCode.DATA_SIZE_MISMATCH, "Number of bytes read to small to process - read {}, expected {} byte".format(cfg_size, size), typ=LogType.ERROR,line=inspect.getlineno(inspect.currentframe())) + exit(ExitCode.DATA_SIZE_MISMATCH, "Number of bytes read to small to process - read {}, expected {} byte".format(cfg_size, size), type_=LogType.ERROR,line=inspect.getlineno(inspect.currentframe())) # check crc if exists if 'cfg_crc' in setting: @@ -2454,7 +2484,7 @@ def Bin2Mapping(decode_cfg): else: cfg_crc = GetSettingsCrc(decode_cfg) if cfg_crc != GetSettingsCrc(decode_cfg): - exit(ExitCode.DATA_CRC_ERROR, 'Data CRC error, read 0x{:x} should be 0x{:x}'.format(cfg_crc, GetSettingsCrc(decode_cfg)), typ=LogType.WARNING, doexit=not args.ignorewarning,line=inspect.getlineno(inspect.currentframe())) + exit(ExitCode.DATA_CRC_ERROR, 'Data CRC error, read 0x{:x} should be 0x{:x}'.format(cfg_crc, GetSettingsCrc(decode_cfg)), type_=LogType.WARNING, doexit=not args.ignorewarning,line=inspect.getlineno(inspect.currentframe())) # get valuemapping valuemapping = GetField(decode_cfg, None, (setting,0,(None, None, (INTERNAL, None)))) @@ -2525,7 +2555,7 @@ def Mapping2Bin(decode_cfg, jsonconfig, filename=""): SetField(_buffer, name, setting[name], jsonconfig[name], addroffset=0, filename=filename) else: if name != 'header': - exit(ExitCode.RESTORE_DATA_ERROR, "Restore file '{}' contains obsolete name '{}', skipped".format(filename, name), typ=LogType.WARNING, doexit=not args.ignorewarning) + exit(ExitCode.RESTORE_DATA_ERROR, "Restore file '{}' contains obsolete name '{}', skipped".format(filename, name), type_=LogType.WARNING, doexit=not args.ignorewarning) if 'cfg_crc' in setting: crc = GetSettingsCrc(_buffer) @@ -2533,7 +2563,7 @@ def Mapping2Bin(decode_cfg, jsonconfig, filename=""): return _buffer else: - exit(ExitCode.UNSUPPORTED_VERSION,"File '{}', Tasmota configuration version 0x{:x} not supported".format(filename, version), typ=LogType.WARNING, doexit=not args.ignorewarning) + exit(ExitCode.UNSUPPORTED_VERSION,"File '{}', Tasmota configuration version 0x{:x} not supported".format(filename, version), type_=LogType.WARNING, doexit=not args.ignorewarning) return None @@ -2568,12 +2598,12 @@ def Mapping2Cmnd(decode_cfg, valuemapping, filename=""): cmnds = SetCmnd(cmnds, name, setting[name], valuemapping, valuemapping[name], addroffset=0) else: if name != 'header': - exit(ExitCode.RESTORE_DATA_ERROR, "Restore file '{}' contains obsolete name '{}', skipped".format(filename, name), typ=LogType.WARNING, doexit=not args.ignorewarning) + exit(ExitCode.RESTORE_DATA_ERROR, "Restore file '{}' contains obsolete name '{}', skipped".format(filename, name), type_=LogType.WARNING, doexit=not args.ignorewarning) return cmnds else: - exit(ExitCode.UNSUPPORTED_VERSION,"File '{}', Tasmota configuration version 0x{:x} not supported".format(filename, version), typ=LogType.WARNING, doexit=not args.ignorewarning) + exit(ExitCode.UNSUPPORTED_VERSION,"File '{}', Tasmota configuration version 0x{:x} not supported".format(filename, version), type_=LogType.WARNING, doexit=not args.ignorewarning) return None @@ -2608,7 +2638,7 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configmapping): fileformat = "Tasmota" backup_filename = MakeFilename(backupfile, FileType.DMP, configmapping) if args.verbose: - message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), typ=LogType.INFO) + message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), type_=LogType.INFO) try: with open(backup_filename, "wb") as backupfp: backupfp.write(encode_cfg) @@ -2620,7 +2650,7 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configmapping): fileformat = "binary" backup_filename = MakeFilename(backupfile, FileType.BIN, configmapping) if args.verbose: - message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), typ=LogType.INFO) + message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), type_=LogType.INFO) try: with open(backup_filename, "wb") as backupfp: backupfp.write(struct.pack(' Date: Wed, 29 May 2019 19:24:47 +0200 Subject: [PATCH 1422/2222] Fix #5869 --- sonoff/_changelog.ino | 1 + sonoff/xdrv_04_light.ino | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 874fa5e34..5a5195a48 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.5.0.13 20190527 * Add command SetOption38 6..255 to set IRReceive protocol detection sensitivity mimizing UNKNOWN protocols (#5853) + * Fix missing white channel for SW2812 (#5869) * * 6.5.0.12 20190521 * Add AriLux RF control GPIO option "ALux IrSel" (159) replacing "Led4i" (59) for full LED control (#5709) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 17a0806bb..b737fcc1d 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -1326,6 +1326,12 @@ void LightInit(void) light_device = devices_present; light_subtype = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); // Always 0 - LST_MAX (5) +#if defined(USE_WS2812) && (USE_WS2812_CTYPE > NEO_3LED) + if (LT_WS2812 == light_type) { + light_subtype++; // from RGB to RGBW + } +#endif + light_controller.setSubType(light_subtype); light_controller.loadSettings(); @@ -1362,9 +1368,6 @@ void LightInit(void) } #ifdef USE_WS2812 // ************************************************************************ else if (LT_WS2812 == light_type) { -#if (USE_WS2812_CTYPE > NEO_3LED) - light_subtype++; // from RGB to RGBW -#endif Ws2812Init(); max_scheme = LS_MAX + WS2812_SCHEMES; } From 74685f12024b31510dfc71bed9284e6afef20e33 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 29 May 2019 19:26:42 +0200 Subject: [PATCH 1423/2222] Fix #5869 typo --- sonoff/_changelog.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 5a5195a48..7327cb8b6 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,6 @@ /* 6.5.0.13 20190527 * Add command SetOption38 6..255 to set IRReceive protocol detection sensitivity mimizing UNKNOWN protocols (#5853) - * Fix missing white channel for SW2812 (#5869) + * Fix missing white channel for WS2812 (#5869) * * 6.5.0.12 20190521 * Add AriLux RF control GPIO option "ALux IrSel" (159) replacing "Led4i" (59) for full LED control (#5709) From f2731d6128b3547bf3cd8247caf06e174f0b334a Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 29 May 2019 19:34:52 +0200 Subject: [PATCH 1424/2222] Updated code size impact for #define USE_DISCOVERY on core 2_5_x --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 690340c86..4c3b3ae30 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -279,7 +279,7 @@ #define USE_EMULATION_WEMO // Enable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) // -- mDNS ---------------------------------------- -#define USE_DISCOVERY // Enable mDNS for the following services (+8k code, +0.3k mem) +#define USE_DISCOVERY // Enable mDNS for the following services (+8k code or +23.5k code with core 2_5_x, +0.3k mem) #define WEBSERVER_ADVERTISE // Provide access to webserver by name .local/ #define MQTT_HOST_DISCOVERY // Find MQTT host server (overrides MQTT_HOST if found) From 4e95417db4c5f8e9875ab33898f2aa97b1590392 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 30 May 2019 12:45:02 +0200 Subject: [PATCH 1425/2222] Add reset of Energy values when connection to sensor is lost for over 4 seconds Add reset of Energy values when connection to sensor is lost for over 4 seconds (#5874, #5881) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_03_energy.ino | 14 ++++++++++++ sonoff/xnrg_01_hlw8012.ino | 22 ++++++++++++------ sonoff/xnrg_02_cse7766.ino | 43 +++++++++++++++++++++--------------- sonoff/xnrg_03_pzem004t.ino | 1 + sonoff/xnrg_04_mcp39f501.ino | 8 +++++++ sonoff/xnrg_05_pzem_ac.ino | 2 ++ sonoff/xnrg_06_pzem_dc.ino | 2 ++ 8 files changed, 68 insertions(+), 25 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 7327cb8b6..444375040 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.5.0.13 20190527 * Add command SetOption38 6..255 to set IRReceive protocol detection sensitivity mimizing UNKNOWN protocols (#5853) * Fix missing white channel for WS2812 (#5869) + * Add reset of Energy values when connection to sensor is lost for over 4 seconds (#5874, #5881) * * 6.5.0.12 20190521 * Add AriLux RF control GPIO option "ALux IrSel" (159) replacing "Led4i" (59) for full LED control (#5709) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 1d47bc034..52585a632 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -28,6 +28,7 @@ #define ENERGY_NONE 0 #define ENERGY_OVERTEMP 73.0 // Industry standard lowest overtemp in Celsius +#define ENERGY_WATCHDOG 4 // Allow up to 4 seconds before deciding no valid data present #define FEATURE_POWER_LIMIT true @@ -71,6 +72,7 @@ unsigned long energy_period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hour float energy_power_last[3] = { 0 }; uint8_t energy_power_delta = 0; +uint8_t energy_data_valid = 0; bool energy_voltage_available = true; // Enable if voltage is measured bool energy_current_available = true; // Enable if current is measured @@ -327,6 +329,18 @@ void EnergyOverTempCheck() SetAllPower(POWER_ALL_OFF, SRC_OVERTEMP); } } + if (energy_data_valid <= ENERGY_WATCHDOG) { + energy_data_valid++; + if (energy_data_valid > ENERGY_WATCHDOG) { + // Reset energy registers + energy_voltage = 0; + energy_current = 0; + energy_active_power = 0; + if (!isnan(energy_frequency)) { energy_frequency = 0; } + if (!isnan(energy_power_factor)) { energy_power_factor = 0; } + energy_start = 0; + } + } } /*********************************************************************************************\ diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index c098870e4..e26f195fb 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -86,6 +86,7 @@ void HlwCfInterrupt(void) // Service Power hlw_cf_pulse_last_time = us; hlw_energy_period_counter++; } + energy_data_valid = 0; } void HlwCf1Interrupt(void) // Service Voltage and Current @@ -104,6 +105,7 @@ void HlwCf1Interrupt(void) // Service Voltage and Current hlw_cf1_timer = 8; // We need up to HLW_SAMPLE_COUNT samples within 1 second (low current could take up to 0.3 second) } } + energy_data_valid = 0; } /********************************************************************************************/ @@ -189,14 +191,20 @@ void HlwEvery200ms(void) void HlwEverySecond(void) { - unsigned long hlw_len; + if (energy_data_valid > ENERGY_WATCHDOG) { + hlw_cf1_voltage_pulse_length = 0; + hlw_cf1_current_pulse_length = 0; + hlw_cf_power_pulse_length = 0; + } else { + unsigned long hlw_len; - if (hlw_energy_period_counter) { - hlw_len = 10000 / hlw_energy_period_counter; - hlw_energy_period_counter = 0; - if (hlw_len) { - energy_kWhtoday_delta += ((hlw_power_ratio * Settings.energy_power_calibration) / hlw_len) / 36; - EnergyUpdateToday(); + if (hlw_energy_period_counter) { + hlw_len = 10000 / hlw_energy_period_counter; + hlw_energy_period_counter = 0; + if (hlw_len) { + energy_kWhtoday_delta += ((hlw_power_ratio * Settings.energy_power_calibration) / hlw_len) / 36; + EnergyUpdateToday(); + } } } } diff --git a/sonoff/xnrg_02_cse7766.ino b/sonoff/xnrg_02_cse7766.ino index 55d87a163..b2b2cecca 100644 --- a/sonoff/xnrg_02_cse7766.ino +++ b/sonoff/xnrg_02_cse7766.ino @@ -139,6 +139,7 @@ bool CseSerialInput(void) uint8_t checksum = 0; for (uint8_t i = 2; i < 23; i++) { checksum += serial_in_buffer[i]; } if (checksum == serial_in_buffer[23]) { + energy_data_valid = 0; CseReceived(); cse_receive_flag = 0; return 1; @@ -170,28 +171,34 @@ bool CseSerialInput(void) void CseEverySecond(void) { - long cf_frequency = 0; - - if (CSE_PULSES_NOT_INITIALIZED == cf_pulses_last_time) { - cf_pulses_last_time = cf_pulses; // Init after restart + if (energy_data_valid > ENERGY_WATCHDOG) { + voltage_cycle = 0; + current_cycle = 0; + power_cycle = 0; } else { - if (cf_pulses < cf_pulses_last_time) { // Rolled over after 65535 pulses - cf_frequency = (65536 - cf_pulses_last_time) + cf_pulses; + long cf_frequency = 0; + + if (CSE_PULSES_NOT_INITIALIZED == cf_pulses_last_time) { + cf_pulses_last_time = cf_pulses; // Init after restart } else { - cf_frequency = cf_pulses - cf_pulses_last_time; - } - if (cf_frequency && energy_active_power) { - unsigned long delta = (cf_frequency * Settings.energy_power_calibration) / 36; - // prevent invalid load delta steps even checksum is valid (issue #5789): - if (delta <= (3680*100/36) * 10 ) { // max load for S31/Pow R2: 3.68kW - cf_pulses_last_time = cf_pulses; - energy_kWhtoday_delta += delta; + if (cf_pulses < cf_pulses_last_time) { // Rolled over after 65535 pulses + cf_frequency = (65536 - cf_pulses_last_time) + cf_pulses; + } else { + cf_frequency = cf_pulses - cf_pulses_last_time; } - else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Load overflow")); - cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; + if (cf_frequency && energy_active_power) { + unsigned long delta = (cf_frequency * Settings.energy_power_calibration) / 36; + // prevent invalid load delta steps even checksum is valid (issue #5789): + if (delta <= (3680*100/36) * 10 ) { // max load for S31/Pow R2: 3.68kW + cf_pulses_last_time = cf_pulses; + energy_kWhtoday_delta += delta; + } + else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Load overflow")); + cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; + } + EnergyUpdateToday(); } - EnergyUpdateToday(); } } } diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index b2c72bfa8..8340b09dc 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -169,6 +169,7 @@ void PzemEvery200ms(void) if (data_ready) { float value = 0; if (PzemRecieve(pzem_responses[pzem_read_state], &value)) { + energy_data_valid = 0; switch (pzem_read_state) { case 1: // Voltage as 230.2V energy_voltage = value; diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index af6e8657c..cbffbf10b 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -469,6 +469,7 @@ void McpParseData(void) energy_active_power = 0; energy_current = 0; } + energy_data_valid = 0; } /********************************************************************************************/ @@ -526,6 +527,13 @@ void McpSerialInput(void) void McpEverySecond(void) { + if (energy_data_valid > ENERGY_WATCHDOG) { + mcp_voltage_rms = 0; + mcp_current_rms = 0; + mcp_active_power = 0; + mcp_line_frequency = 0; + } + if (mcp_active_power) { energy_kWhtoday_delta += ((mcp_active_power * 10) / 36); EnergyUpdateToday(); diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index bb8c129d5..653b4ef63 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -51,6 +51,8 @@ void PzemAcEverySecond(void) if (error) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "PzemAc response error %d"), error); } else { + energy_data_valid = 0; + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // 01 04 14 08 D1 00 6C 00 00 00 F4 00 00 00 26 00 00 01 F4 00 64 00 00 51 34 // Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc-- diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index 00e75a5ca..f9817577a 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -51,6 +51,8 @@ void PzemDcEverySecond(void) if (error) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "PzemDc response error %d"), error); } else { + energy_data_valid = 0; + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // 01 04 10 05 40 00 0A 00 0D 00 00 00 02 00 00 00 00 00 00 D6 29 // Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc-- From ce72a8347a9e3e1db0d28719d192080101ca1582 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 30 May 2019 13:22:50 +0200 Subject: [PATCH 1426/2222] empty --- scripter.md | 0 sonoff/xdrv_10_scripter.ino | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripter.md mode change 100644 => 100755 sonoff/xdrv_10_scripter.ino diff --git a/scripter.md b/scripter.md old mode 100644 new mode 100755 diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino old mode 100644 new mode 100755 From fb4ada320a02e5eb0e1e98404c8eed1ab1783296 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 30 May 2019 13:23:54 +0200 Subject: [PATCH 1427/2222] scripter update --- scripter.md | 88 ++++++- sonoff/xdrv_10_scripter.ino | 472 +++++++++++++++++++++++++++++++++--- 2 files changed, 511 insertions(+), 49 deletions(-) mode change 100755 => 100644 scripter.md mode change 100755 => 100644 sonoff/xdrv_10_scripter.ino diff --git a/scripter.md b/scripter.md old mode 100755 new mode 100644 index dc4123192..40ad3451e --- a/scripter.md +++ b/scripter.md @@ -1,6 +1,6 @@ **Script Language for Tasmota** -As an alternative to rules. (about 14,2k flash size, variable ram size) +As an alternative to rules. (about 17k flash size, variable ram size) In submenu Configuration =\> edit script 1535 bytes max script size (uses rules buffer) @@ -88,6 +88,7 @@ special variables (read only): **int(x)** = gets the integer part of x (like floor) **hn(x)** = converts x (0..255) to a hex nibble string **st(svar c n)** = stringtoken gets the n th substring of svar separated by c +**s(x)** = explicit conversion from number x to string **mqtts** = state of mqtt disconnected=0, connected>0 **wifis** = state of wifi disconnected=0, connected>0 @@ -187,6 +188,24 @@ specifies a for next loop, (loop count must not be less then 1) **ends** specifies a switch case selector +**sd card support** +enable by CARD_CS = gpio pin of card chip select +\#define USE_SCRIPT_FATFS CARD_CS +sd card uses standard hardware spi gpios: mosi,miso,sclk +max 4 files open at a time +allows for e.g. logging sensors to a tab delimited file and then download (see example below) +script itself is also stored on sdcard with a default size of 4096 chars +requires additional 10k flash + +>**fr=fo("fname" m)** open file fname, mode 0=read, 1=write (returns file reference (0-3) or -1 for error) +**res=fw("text" fr)** writes text to (the end of) file fr, returns number of bytes written +**res=fr(svar fr)** reads a string into svar, returns bytes read (string is read until delimiter \t \n \r or eof) +**fc(fr)** close file +**fd("fname")** delete file fname +**flx(fname)** create download link for file (x=1 or 2) fname = file name of file to download +**fsm** return 1 if filesystem is mounted, (valid sd card found) + + **konsole script cmds** >**script 1 or 0** switch script on or off **script >cmdline** executes the script cmdline @@ -228,8 +247,8 @@ tcnt=0 hour=0 state=1 m:med5=0 -M:movav=0 -; define array with 10 entries +M:movav=0 +; define array with 10 entries m:array=0 10 **\>B** @@ -290,10 +309,10 @@ endif ; every second but not completely reliable time here ; use upsecs and uptime or best t: for reliable timers -; arrays -array[1]=4 -array[2]=5 -tmp=array[1]+array[2] +; arrays +array[1]=4 +array[2]=5 +tmp=array[1]+array[2] ; call subrountines with parameters =#sub1("hallo") @@ -473,11 +492,54 @@ col=hn(255)+hn(0)+hn(0) **\>R** =\>print restarting now +**a log sensor example** +; define all vars here +; reserve large strings +**\>D** 48 +hum=0 +temp=0 +fr=0 +res=0 +; moving average for 60 seconds +M:mhum=0 60 +M:mtemp=0 60 +str="" + +**\>B** +; open file for write +fr=fo("slog.txt" 1) +; set sensor file download link +fl1("slog.txt") + +**\>T** +; get sensor values +temp=BME280#Temperature +hum=BME280#Humidity + +**\>S** +; average sensor values every second +mhum=hum +mtemp=temp + +; write average to sensor log every minute +if upsecs%60==0 +then +; compose string for tab delimited file entry +str=s(upsecs)+"\t"+s(mhum)+"\t"+s(mtemp)+"\n" +; write string to log file +res=fw(str fr) +endif + +**\>R** +; close file +fc(fr) + + **a real example** epaper 29 with sgp30 and bme280 some vars are set from iobroker DisplayText substituted to save script space -\>D +**\>D** hum=0 temp=0 press=0 @@ -496,13 +558,13 @@ DT="DisplayText" punit="hPa" tunit="C" -\>B +**\>B** ;reset auto draw =>%DT% [zD0] ;clr display and draw a frame =>%DT% [x0y20h296x0y40h296] -\>T +**\>T** ; get tele vars temp=BME280#Temperature hum=BME280#Humidity @@ -513,7 +575,7 @@ ahum=SGP30#aHumidity tunit=TempUnit punit=PressureUnit -\>S +**\>S** // update display every teleperiod time if upsecs%tper==0 then @@ -536,9 +598,9 @@ dprec0 endif -\>E +**\>E** -\>R +**\>R** **another real example** ILI 9488 color LCD Display shows various energy graphs diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino old mode 100755 new mode 100644 index 83c29a42c..d5a3176da --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -21,8 +21,7 @@ #ifndef USE_RULES /*********************************************************************************************\ for documentation see up to date docs in file SCRIPTER.md -uses about 14,2 k of flash -more stack could be needed for sendmail => -D CONT_STACKSIZE=4800 = +0.8k stack -0.8k heap +uses about 17 k of flash to do optimize code for space @@ -36,7 +35,13 @@ no math hierarchy (costs ram and execution time, better group with brackets, an (will probably make math hierarchy an ifdefed option) keywords if then else endif, or, and are better readable for beginners (others may use {}) - +changelog after merging to Tasmota +1 show remaining chars in webui, +2 now can expand script space to 2048 chars by setting MAX_RULE_SETS to 4 +3 at24256 eeprom support #ifdef defaults to 4095 bytes script size (reduces heap by this amount) +4 some housekeeping +5 sd card support #ifdef allows eg for sensor logging +6 download link for sdcard files \*********************************************************************************************/ @@ -53,11 +58,18 @@ keywords if then else endif, or, and are better readable for beginners (others m #define SCRIPT_EOL '\n' #define SCRIPT_FLOAT_PRECISION 2 #define SCRIPT_MAXPERM (MAX_RULE_MEMS*10)-4/sizeof(float) - +#define MAX_SCRIPT_SIZE MAX_RULE_SIZE*MAX_RULE_SETS enum {OPER_EQU=1,OPER_PLS,OPER_MIN,OPER_MUL,OPER_DIV,OPER_PLSEQU,OPER_MINEQU,OPER_MULEQU,OPER_DIVEQU,OPER_EQUEQU,OPER_NOTEQU,OPER_GRTEQU,OPER_LOWEQU,OPER_GRT,OPER_LOW,OPER_PERC,OPER_XOR,OPER_AND,OPER_OR,OPER_ANDEQU,OPER_OREQU,OPER_XOREQU,OPER_PERCEQU}; enum {SCRIPT_LOGLEVEL=1,SCRIPT_TELEPERIOD}; +#ifdef USE_SCRIPT_FATFS +#include +#include +#define FAT_SCRIPT_SIZE 4096 +#define FAT_SCRIPT_NAME "script.txt" +#endif + typedef union { uint8_t data; struct { @@ -84,6 +96,7 @@ struct M_FILT { float rbuff[1]; }; +#define SFS_MAX 4 // global memory struct SCRIPT_MEM { float *fvars; // number var pointer @@ -94,6 +107,10 @@ struct SCRIPT_MEM { uint8_t *vnp_offset; char *glob_snp; // string vars pointer char *scriptptr; + char *script_ram; + uint16_t script_size; + uint8_t *script_pram; + uint16_t script_pram_size; uint8_t numvars; void *script_mem; uint16_t script_mem_size; @@ -102,6 +119,13 @@ struct SCRIPT_MEM { uint8_t glob_error; uint8_t max_ssize; uint8_t script_loglevel; + uint8_t flags; +#ifdef USE_SCRIPT_FATFS + File files[SFS_MAX]; + uint8_t file_flags[SFS_MAX]; + uint8_t script_sd_found; + char flink[2][14]; +#endif } glob_script_mem; @@ -110,8 +134,11 @@ uint8_t tasm_cmd_activ=0; uint32_t script_lastmillis; + char *GetNumericResult(char *lp,uint8_t lastop,float *fp,JsonObject *jo); char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo); +char *ForceStringVar(char *lp,char *dstr); +void send_download(void); void ScriptEverySecond(void) { @@ -145,11 +172,31 @@ void RulesTeleperiod(void) { if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">T",2, mqtt_data); } +//#define USE_24C256 + +// EEPROM MACROS +#ifdef USE_24C256 +// i2c eeprom +#include +#define EEPROM_ADDRESS 0x50 +// strange bug, crashes with powers of 2 ??? 4096 crashes +#define EEP_SCRIPT_SIZE 4095 +static Eeprom24C128_256 eeprom(EEPROM_ADDRESS); +// eeprom.writeBytes(address, length, buffer); +#define EEP_WRITE(A,B,C) eeprom.writeBytes(A,B,(uint8_t*)C); +// eeprom.readBytes(address, length, buffer); +#define EEP_READ(A,B,C) eeprom.readBytes(A,B,(uint8_t*)C); +#endif + #define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++; #define SCRIPT_SKIP_EOL while (*lp==SCRIPT_EOL) lp++; -// allocates all variable and presets them -int16_t Init_Scripter(char *script) { +// allocates all variables and presets them +int16_t Init_Scripter(void) { +char *script; + + script=glob_script_mem.script_ram; + // scan lines for >DEF uint16_t lines=0,nvars=0,svars=0,vars=0; char *lp=script; @@ -415,10 +462,7 @@ int16_t Init_Scripter(char *script) { #endif // now preset permanent vars - uint32_t lptr=(uint32_t)Settings.mems[0]; - lptr&=0xfffffffc; - float *fp=(float*)lptr; - fp++; + float *fp=(float*)glob_script_mem.script_pram; struct T_INDEX *vtp=glob_script_mem.type; for (uint8_t count=0; count0 ClaimSerial(); SetSerialBaudrate(9600); @@ -513,8 +570,13 @@ void Set_MFVal(uint8_t index,uint8_t bind,float val) { struct M_FILT *mflp=(struct M_FILT*)mp; if (count==index) { uint8_t maxind=mflp->numvals&0x7f; - if (bind<1 || bind>maxind) bind=maxind; - mflp->rbuff[bind-1]=val; + if (!bind) { + mflp->index=val; + } else { + if (bind<1 || bind>maxind) bind=maxind; + mflp->rbuff[bind-1]=val; + } + return; } mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); } @@ -610,7 +672,24 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso lp++; while (*lp!='"') { if (*lp==0 || *lp==SCRIPT_EOL) break; - if (sp) *sp++=*lp; + uint8_t iob=*lp; + if (iob=='\\') { + lp++; + if (*lp=='t') { + iob='\t'; + } else if (*lp=='n') { + iob='\n'; + } else if (*lp=='r') { + iob='\r'; + } else if (*lp=='\\') { + iob='\\'; + } else { + lp--; + } + if (sp) *sp++=iob; + } else { + if (sp) *sp++=iob; + } lp++; } if (sp) *sp=0; @@ -797,6 +876,141 @@ chknext: goto exit; } break; +#ifdef USE_SCRIPT_FATFS + case 'f': + if (!strncmp(vname,"fo(",3)) { + lp+=3; + char str[SCRIPT_MAXSSIZE]; + lp=GetStringResult(lp,OPER_EQU,str,0); + while (*lp==' ') lp++; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + uint8_t mode=fvar; + fvar=-1; + for (uint8_t cnt=0;cnt=SFS_MAX) ind=SFS_MAX-1; + glob_script_mem.files[ind].close(); + glob_script_mem.file_flags[ind]=0; + fvar=0; + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"fw(",3)) { + lp+=3; + char str[SCRIPT_MAXSSIZE]; + lp=ForceStringVar(lp,str); + while (*lp==' ') lp++; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + uint8_t ind=fvar; + if (ind>=SFS_MAX) ind=SFS_MAX-1; + if (glob_script_mem.file_flags[ind]&1) { + fvar=glob_script_mem.files[ind].print(str); + } else { + fvar=0; + } + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"fr(",3)) { + lp+=3; + struct T_INDEX ind; + uint8_t vtype; + uint8_t sindex=0; + lp=isvar(lp,&vtype,&ind,0,0,0); + if (vtype!=VAR_NV) { + // found variable as result + if ((vtype&STYPE)==0) { + // error + fvar=0; + goto exit; + } else { + // string result + sindex=glob_script_mem.type[ind.index].index; + } + } else { + // error + fvar=0; + goto exit; + } + while (*lp==' ') lp++; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + uint8_t find=fvar; + if (find>=SFS_MAX) find=SFS_MAX-1; + uint8_t index=0; + char str[glob_script_mem.max_ssize+1]; + char *cp=str; + if (glob_script_mem.file_flags[find]&1) { + while (glob_script_mem.files[find].available()) { + char buf[1]; + glob_script_mem.files[find].read(buf,1); + if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { + break; + } else { + *cp++=buf[0]; + index++; + if (index>=glob_script_mem.max_ssize-1) break; + } + } + *cp=0; + } else { + strcpy(str,"file error"); + } + lp++; + strlcpy(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); + fvar=index; + len=0; + goto exit; + } + if (!strncmp(vname,"fd(",3)) { + lp+=3; + char str[glob_script_mem.max_ssize+1]; + lp=GetStringResult(lp,OPER_EQU,str,0); + SD.remove(str); + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"fl1(",4) || !strncmp(vname,"fl2(",4) ) { + uint8_t lknum=*(lp+2)&3; + lp+=4; + char str[glob_script_mem.max_ssize+1]; + lp=GetStringResult(lp,OPER_EQU,str,0); + if (lknum<1 || lknum>2) lknum=1; + strlcpy(glob_script_mem.flink[lknum-1],str,14); + lp++; + fvar=0; + len=0; + goto exit; + } + if (!strncmp(vname,"fsm",3)) { + fvar=glob_script_mem.script_sd_found; + //card_init(); + goto exit; + } + break; + +#endif //USE_SCRIPT_FATFS case 'g': if (!strncmp(vname,"gtmp",4)) { fvar=global_temperature; @@ -974,7 +1188,7 @@ chknext: break; case 'r': if (!strncmp(vname,"ram",3)) { - fvar=glob_script_mem.script_mem_size+(MAX_RULE_SETS*MAX_RULE_SIZE)+(MAX_RULE_MEMS*10); + fvar=glob_script_mem.script_mem_size+(glob_script_mem.script_size)+(MAX_RULE_MEMS*10); goto exit; } break; @@ -996,7 +1210,7 @@ chknext: goto exit; } if (!strncmp(vname,"slen",4)) { - fvar=strlen(Settings.rules[0]); + fvar=strlen(glob_script_mem.script_ram); goto exit; } if (!strncmp(vname,"st(",3)) { @@ -1033,6 +1247,16 @@ chknext: } goto strexit; } + if (!strncmp(vname,"s(",2)) { + lp+=2; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + char str[glob_script_mem.max_ssize+1]; + dtostrfd(fvar,glob_script_mem.script_dprec,str); + if (sp) strlcpy(sp,str,glob_script_mem.max_ssize); + lp++; + len=0; + goto strexit; + } #if defined(USE_TIMERS) && defined(USE_SUNRISE) if (!strncmp(vname,"sunrise",7)) { fvar=SunMinutes(0); @@ -1416,6 +1640,20 @@ struct T_INDEX ind; } +char *ForceStringVar(char *lp,char *dstr) { + float fvar; + char *slp=lp; + glob_script_mem.var_not_found=0; + lp=GetStringResult(lp,OPER_EQU,dstr,0); + if (glob_script_mem.var_not_found) { + // mismatch + lp=GetNumericResult(slp,OPER_EQU,&fvar,0); + dtostrfd(fvar,6,dstr); + glob_script_mem.var_not_found=0; + } + return lp; +} + // replace vars in cmd %var% void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) { char *cp; @@ -1774,7 +2012,7 @@ int16_t Run_Scripter(const char *type, uint8_t tlen, char *js) { toLog(&tmp[5]); } else { snprintf_P(log_data, sizeof(log_data), PSTR("Script: performs \"%s\""), tmp); - AddLog(glob_script_mem.script_loglevel); + AddLog(glob_script_mem.script_loglevel&0x7f); tasm_cmd_activ=1; ExecuteCommand((char*)tmp, SRC_RULE); tasm_cmd_activ=0; @@ -2078,8 +2316,8 @@ int16_t Run_Scripter(const char *type, uint8_t tlen, char *js) { uint8_t script_xsns_index = 0; -void ScripterEvery100ms(void) -{ +void ScripterEvery100ms(void) { + if (Settings.rule_enabled && (uptime > 4)) { mqtt_data[0] = '\0'; uint16_t script_tele_period_save = tele_period; @@ -2098,11 +2336,8 @@ void ScripterEvery100ms(void) // can hold 11 floats or floats + strings // should report overflow later void Scripter_save_pvars(void) { - uint32_t lptr=(uint32_t)Settings.mems[0]; int16_t mlen=0; - lptr&=0xfffffffc; - float *fp=(float*)lptr; - fp++; + float *fp=(float*)glob_script_mem.script_pram; mlen+=sizeof(float); struct T_INDEX *vtp=glob_script_mem.type; for (uint8_t count=0; count " D_RULEVARS " " + "
 " D_SCRIPT " " "
"; const char HTTP_FORM_SCRIPT1[] PROGMEM = - "
script enable
" - "
"; + "" + ""; + +#ifdef USE_SCRIPT_FATFS +const char HTTP_FORM_SCRIPT1c[] PROGMEM = +""; +#endif + +#ifdef USE_SCRIPT_FATFS + +void script_download(uint8_t num) { + File download_file; + WiFiClient download_Client; + + if (!HttpCheckPriviledgedAccess()) { return; } + + if (!SD.exists(glob_script_mem.flink[num-1])) { + toLog("file not found"); + return; + } + + download_file=SD.open(glob_script_mem.flink[num-1],FILE_READ); + if (!download_file) { + toLog("could not open file"); + } + uint32_t flen=download_file.size(); + + download_Client = WebServer->client(); + WebServer->setContentLength(flen); + + char attachment[100]; + snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"),glob_script_mem.flink[num-1]); + WebServer->sendHeader(F("Content-Disposition"), attachment); + WSSend(200, CT_STREAM, ""); + + uint8_t buff[512]; + uint16_t bread; + + // transfer is about 150kb/s + uint8_t cnt=0; + while (download_file.available()) { + bread=download_file.read(buff,sizeof(buff)); + uint16_t bw=download_Client.write((const char*)buff,bread); + if (!bw) break; + cnt++; + if (cnt>7) { + cnt=0; + if (glob_script_mem.script_loglevel&0x80) { + // this indeed multitasks, but is slower 50 kB/s + loop(); + } + } + } + download_file.close(); + download_Client.stop(); +} +#endif void HandleScriptConfiguration(void) { @@ -2169,16 +2475,31 @@ void HandleScriptConfiguration(void) return; } +#ifdef USE_SCRIPT_FATFS + if (WebServer->hasArg("d1")) { + script_download(1); + } + if (WebServer->hasArg("d2")) { + script_download(2); + } +#endif + WSContentStart_P(S_CONFIGURE_SCRIPT); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_SCRIPT); - WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",1,1,MAX_RULE_SIZE*3); + WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",glob_script_mem.script_size); // script is to larg for WSContentSend_P - if (Settings.rules[0][0]) { - _WSContentSend(Settings.rules[0]); + if (glob_script_mem.script_ram[0]) { + _WSContentSend(glob_script_mem.script_ram); } WSContentSend_P(HTTP_FORM_SCRIPT1b); + +#ifdef USE_SCRIPT_FATFS + if (glob_script_mem.flink[0][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,1,glob_script_mem.flink[0]); + if (glob_script_mem.flink[1][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,2,glob_script_mem.flink[1]); +#endif + WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentStop(); @@ -2195,7 +2516,7 @@ void strrepl_inplace(char *str, const char *a, const char *b) { } } -#define MAX_SCRIPT_SIZE MAX_RULE_SIZE*3 + void ScriptSaveSettings(void) { @@ -2215,7 +2536,23 @@ void ScriptSaveSettings(void) { str.replace("\r\n","\n"); str.replace("\r","\n"); #endif - strlcpy(Settings.rules[0],str.c_str(), MAX_RULE_SIZE*3); + strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size); + +#ifdef USE_24C256 + if (glob_script_mem.flags&1) { + EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); + } +#endif + +#ifdef USE_SCRIPT_FATFS + if (glob_script_mem.flags&1) { + SD.remove(FAT_SCRIPT_NAME); + File file=SD.open(FAT_SCRIPT_NAME,FILE_WRITE); + file.write(glob_script_mem.script_ram,FAT_SCRIPT_SIZE); + file.close(); + } +#endif + } if (glob_script_mem.script_mem) { @@ -2226,7 +2563,7 @@ void ScriptSaveSettings(void) { } if (bitRead(Settings.rule_enabled, 0)) { - int16_t res=Init_Scripter(Settings.rules[0]); + int16_t res=Init_Scripter(); if (res) { snprintf_P(log_data, sizeof(log_data), PSTR("script init error: %d"),res); AddLog(LOG_LEVEL_INFO); @@ -2280,7 +2617,7 @@ bool ScriptCommand(void) { }*/ } } - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\",\"Free\":%d}"),command, GetStateText(bitRead(Settings.rule_enabled,0)),MAX_RULE_SIZE*3-strlen(Settings.rules[0])); + snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\",\"Free\":%d}"),command, GetStateText(bitRead(Settings.rule_enabled,0)),glob_script_mem.script_size-strlen(glob_script_mem.script_ram)); } else serviced = false; return serviced; @@ -2290,13 +2627,76 @@ bool ScriptCommand(void) { * Interface \*********************************************************************************************/ -bool Xdrv10(byte function) +bool Xdrv10(uint8_t function) { bool result = false; switch (function) { case FUNC_PRE_INIT: - if (bitRead(Settings.rule_enabled, 0)) Init_Scripter(Settings.rules[0]); + // set defaults to rules memory + glob_script_mem.script_ram=Settings.rules[0]; + glob_script_mem.script_size=MAX_SCRIPT_SIZE; + glob_script_mem.flags=0; + glob_script_mem.script_pram=(uint8_t*)Settings.mems[0]; + glob_script_mem.script_pram_size=MAX_RULE_MEMS*10; + +#ifdef USE_24C256 + if (i2c_flg) { + if (I2cDevice(EEPROM_ADDRESS)) { + // found 32kb eeprom + char *script; + script=(char*)calloc(EEP_SCRIPT_SIZE+4,1); + if (!script) break; + glob_script_mem.script_ram=script; + glob_script_mem.script_size=EEP_SCRIPT_SIZE; + EEP_READ(0,EEP_SCRIPT_SIZE,script); + if (*script==0xff) { + memset(script,EEP_SCRIPT_SIZE,0); + } + script[EEP_SCRIPT_SIZE-1]=0; + // use rules storage for permanent vars + glob_script_mem.script_pram=(uint8_t*)Settings.rules[0]; + glob_script_mem.script_pram_size=MAX_SCRIPT_SIZE; + + glob_script_mem.flags=1; + } + } +#endif + + + +#ifdef USE_SCRIPT_FATFS + if (SD.begin(USE_SCRIPT_FATFS)) { + glob_script_mem.script_sd_found=1; + char *script; + script=(char*)calloc(FAT_SCRIPT_SIZE+4,1); + if (!script) break; + glob_script_mem.script_ram=script; + glob_script_mem.script_size=FAT_SCRIPT_SIZE; + if (SD.exists(FAT_SCRIPT_NAME)) { + File file=SD.open(FAT_SCRIPT_NAME,FILE_READ); + file.read(script,FAT_SCRIPT_SIZE); + file.close(); + } + script[FAT_SCRIPT_SIZE-1]=0; + // use rules storage for permanent vars + glob_script_mem.script_pram=(uint8_t*)Settings.rules[0]; + glob_script_mem.script_pram_size=MAX_SCRIPT_SIZE; + + glob_script_mem.flags=1; + } else { + glob_script_mem.script_sd_found=0; + } +#endif + + // assure permanent memory is 4 byte aligned + { uint32_t ptr=(uint32_t)glob_script_mem.script_pram; + ptr&=0xfffffffc; + glob_script_mem.script_pram=(uint8_t*)ptr; + glob_script_mem.script_pram_size-=4; + } + + if (bitRead(Settings.rule_enabled, 0)) Init_Scripter(); break; case FUNC_INIT: if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">B",2,0); From 7505f7dd64dbd881aea7b3f33930f6492c014817 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 30 May 2019 13:34:48 +0200 Subject: [PATCH 1428/2222] Update my_user_config.h --- sonoff/my_user_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 4c3b3ae30..624eecf43 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -291,8 +291,8 @@ // -- Rules or Script ---------------------------- // Select none or only one of the below defines -#define USE_RULES // Add support for rules (+8k code) -//#define USE_SCRIPT // Add support for script (+15k code) +//#define USE_RULES // Add support for rules (+8k code) +#define USE_SCRIPT // Add support for script (+15k code) // #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) // #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) From 66dfbb59827aece9013fb846ac5ce3cd46265f77 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 30 May 2019 13:56:21 +0200 Subject: [PATCH 1429/2222] Update my_user_config.h --- sonoff/my_user_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 624eecf43..f3bd851f6 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -293,6 +293,7 @@ // Select none or only one of the below defines //#define USE_RULES // Add support for rules (+8k code) #define USE_SCRIPT // Add support for script (+15k code) +#define USE_SCRIPT_FATFS 4 // #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) // #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) From 19a7e2af901f51f985a4aa6b53f9d26f19f60c98 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 30 May 2019 14:11:03 +0200 Subject: [PATCH 1430/2222] Update xdrv_10_scripter.ino --- sonoff/xdrv_10_scripter.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index d5a3176da..3b21603de 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -962,7 +962,7 @@ chknext: char *cp=str; if (glob_script_mem.file_flags[find]&1) { while (glob_script_mem.files[find].available()) { - char buf[1]; + uint8_t buf[1]; glob_script_mem.files[find].read(buf,1); if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { break; @@ -2675,7 +2675,7 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_size=FAT_SCRIPT_SIZE; if (SD.exists(FAT_SCRIPT_NAME)) { File file=SD.open(FAT_SCRIPT_NAME,FILE_READ); - file.read(script,FAT_SCRIPT_SIZE); + file.read((uint8_t*)script,FAT_SCRIPT_SIZE); file.close(); } script[FAT_SCRIPT_SIZE-1]=0; From 86a606dd90ef43acdf5449d5cc8fc9560df2fad3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 30 May 2019 14:18:22 +0200 Subject: [PATCH 1431/2222] Update my_user_config.h Keep rules the default --- sonoff/my_user_config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index f3bd851f6..2dce8ed84 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -291,9 +291,9 @@ // -- Rules or Script ---------------------------- // Select none or only one of the below defines -//#define USE_RULES // Add support for rules (+8k code) -#define USE_SCRIPT // Add support for script (+15k code) -#define USE_SCRIPT_FATFS 4 +#define USE_RULES // Add support for rules (+8k code) +//#define USE_SCRIPT // Add support for script (+17k code) + #define USE_SCRIPT_FATFS 4 // #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) // #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) From ad11828e9d77ea72896c0c58923e6fbe4623a000 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 30 May 2019 21:47:19 +0200 Subject: [PATCH 1432/2222] Work-around for Philips Hue emulation issue (#5849) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_20_hue.ino | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 444375040..e0bc4395a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * Add command SetOption38 6..255 to set IRReceive protocol detection sensitivity mimizing UNKNOWN protocols (#5853) * Fix missing white channel for WS2812 (#5869) * Add reset of Energy values when connection to sensor is lost for over 4 seconds (#5874, #5881) + * Work-around for Philips Hue emulation issue (#5849) * * 6.5.0.12 20190521 * Add AriLux RF control GPIO option "ALux IrSel" (159) replacing "Led4i" (59) for full LED control (#5709) diff --git a/sonoff/xdrv_20_hue.ino b/sonoff/xdrv_20_hue.ino index d54becd66..966f65135 100644 --- a/sonoff/xdrv_20_hue.ino +++ b/sonoff/xdrv_20_hue.ino @@ -342,6 +342,13 @@ void HueLightStatus2(uint8_t device, String *response) response->replace("{j2", GetHueDeviceId(device)); } +// generate a unique lightId mixing local IP address and deice number +// it is limited to 16 devices. +uint32_t lightId(uint32_t idx) { + uint32_t ip_local = WiFi.localIP(); + return ((ip_local & 0xFF000000) >> 20) + idx % 16; // >> 24 * 16 is equivalent to >> 20 +} + void HueGlobalConfig(String *path) { String response; @@ -350,7 +357,7 @@ void HueGlobalConfig(String *path) path->remove(0,1); // cut leading / to get response = F("{\"lights\":{\""); for (uint8_t i = 1; i <= maxhue; i++) { - response += i; + response += lightId(i); response += F("\":{\"state\":"); HueLightStatus1(i, &response); HueLightStatus2(i, &response); @@ -394,7 +401,7 @@ void HueLights(String *path) if (path->endsWith("/lights")) { // Got /lights response = "{\""; for (uint8_t i = 1; i <= maxhue; i++) { - response += i; + response += lightId(i); response += F("\":{\"state\":"); HueLightStatus1(i, &response); HueLightStatus2(i, &response); @@ -562,7 +569,7 @@ void HueLights(String *path) } else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID path->remove(0,8); // Remove /lights/ - device = atoi(path->c_str()); + device = atoi(path->c_str()) % 16; if ((device < 1) || (device > maxhue)) { device = 1; } @@ -591,7 +598,7 @@ void HueGroups(String *path) String lights = F("\"1\""); for (uint8_t i = 2; i <= maxhue; i++) { lights += ",\""; - lights += String(i); + lights += lightId(i); lights += "\""; } response.replace("{l1", lights); From f9812840664362a5901b15b6aa5478190b7ada6f Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 30 May 2019 18:28:22 -0300 Subject: [PATCH 1433/2222] Add support for Arduino Stage Core The actual Stage ESP8266 Core of Arduino (next 2.6.0) had changed the SPIFFS defines of the memory to FS due to a change in the libraries (https://github.com/esp8266/Arduino/pull/5511) --- sonoff/settings.ino | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 246b503b5..f2bf1290e 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -235,11 +235,20 @@ extern "C" { } #include "eboot_command.h" -extern "C" uint32_t _SPIFFS_end; +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2) +extern "C" uint32_t _SPIFFS_end; // From libraries/EEPROM/EEPROM.cpp EEPROMClass const uint32_t SPIFFS_END = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; +#else // Core > 2.5.2 and STAGE + +extern "C" uint32_t _FS_end; +// From libraries/EEPROM/EEPROM.cpp EEPROMClass +const uint32_t SPIFFS_END = ((uint32_t)&_FS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; + +#endif + // Version 4.2 config = eeprom area const uint32_t SETTINGS_LOCATION = SPIFFS_END; // No need for SPIFFS as it uses EEPROM area // Version 5.2 allow for more flash space From 712ea8ec43241c022a05d46854fc14d9389c39e0 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 30 May 2019 18:32:07 -0300 Subject: [PATCH 1434/2222] Add support to Stage Arduino Core --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e0bc4395a..8f3b232d7 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Fix missing white channel for WS2812 (#5869) * Add reset of Energy values when connection to sensor is lost for over 4 seconds (#5874, #5881) * Work-around for Philips Hue emulation issue (#5849) + * Add support to Stage Arduino Core (next 2.6.0) * * 6.5.0.12 20190521 * Add AriLux RF control GPIO option "ALux IrSel" (159) replacing "Led4i" (59) for full LED control (#5709) From 1b229f5c9bb4b7df20a85afa50d9bda546b2e96f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 31 May 2019 11:28:47 +0200 Subject: [PATCH 1435/2222] Work-around for Philips Hue emulation issue by using part of MAC address for LightId Work-around for Philips Hue emulation issue by using part of MAC address for LightId (#5849) --- sonoff/_changelog.ino | 2 +- sonoff/xdrv_20_hue.ino | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 8f3b232d7..6bed2c3b5 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,7 +2,7 @@ * Add command SetOption38 6..255 to set IRReceive protocol detection sensitivity mimizing UNKNOWN protocols (#5853) * Fix missing white channel for WS2812 (#5869) * Add reset of Energy values when connection to sensor is lost for over 4 seconds (#5874, #5881) - * Work-around for Philips Hue emulation issue (#5849) + * Work-around for Philips Hue emulation issue by using part of MAC address for LightId (#5849) * Add support to Stage Arduino Core (next 2.6.0) * * 6.5.0.12 20190521 diff --git a/sonoff/xdrv_20_hue.ino b/sonoff/xdrv_20_hue.ino index 966f65135..4dd79e957 100644 --- a/sonoff/xdrv_20_hue.ino +++ b/sonoff/xdrv_20_hue.ino @@ -342,11 +342,19 @@ void HueLightStatus2(uint8_t device, String *response) response->replace("{j2", GetHueDeviceId(device)); } -// generate a unique lightId mixing local IP address and deice number +// generate a unique lightId mixing local IP address and device number // it is limited to 16 devices. -uint32_t lightId(uint32_t idx) { - uint32_t ip_local = WiFi.localIP(); - return ((ip_local & 0xFF000000) >> 20) + idx % 16; // >> 24 * 16 is equivalent to >> 20 +// last 16 bits of Mac address + 4 bits of local light +uint32_t EncodeLightId(uint8_t idx) +{ + uint8_t mac[6]; + WiFi.macAddress(mac); + uint32_t id = (mac[4] << 12) | (mac[5] << 4) | (idx & 0xF); + return id; +} + +uint32_t DecodeLightId(uint32_t id) { + return id & 0xF; } void HueGlobalConfig(String *path) @@ -357,7 +365,7 @@ void HueGlobalConfig(String *path) path->remove(0,1); // cut leading / to get response = F("{\"lights\":{\""); for (uint8_t i = 1; i <= maxhue; i++) { - response += lightId(i); + response += EncodeLightId(i); response += F("\":{\"state\":"); HueLightStatus1(i, &response); HueLightStatus2(i, &response); @@ -401,7 +409,7 @@ void HueLights(String *path) if (path->endsWith("/lights")) { // Got /lights response = "{\""; for (uint8_t i = 1; i <= maxhue; i++) { - response += lightId(i); + response += EncodeLightId(i); response += F("\":{\"state\":"); HueLightStatus1(i, &response); HueLightStatus2(i, &response); @@ -569,7 +577,7 @@ void HueLights(String *path) } else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID path->remove(0,8); // Remove /lights/ - device = atoi(path->c_str()) % 16; + device = DecodeLightId(atoi(path->c_str())); if ((device < 1) || (device > maxhue)) { device = 1; } @@ -598,7 +606,7 @@ void HueGroups(String *path) String lights = F("\"1\""); for (uint8_t i = 2; i <= maxhue; i++) { lights += ",\""; - lights += lightId(i); + lights += EncodeLightId(i); lights += "\""; } response.replace("{l1", lights); From f9c677fe7690070cc3448921469fcea43032d0ce Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 31 May 2019 13:37:51 +0200 Subject: [PATCH 1436/2222] Change Hue LightId from 20 bits to 28 bits Change Hue LightId from 20 bits to 28 bits (#5849) --- sonoff/xdrv_20_hue.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_20_hue.ino b/sonoff/xdrv_20_hue.ino index 4dd79e957..6a4617ffc 100644 --- a/sonoff/xdrv_20_hue.ino +++ b/sonoff/xdrv_20_hue.ino @@ -349,7 +349,7 @@ uint32_t EncodeLightId(uint8_t idx) { uint8_t mac[6]; WiFi.macAddress(mac); - uint32_t id = (mac[4] << 12) | (mac[5] << 4) | (idx & 0xF); + uint32_t id = (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4) | (idx & 0xF); return id; } From 6ee8d6be1650c9630cbcd918372266e1d89a3be1 Mon Sep 17 00:00:00 2001 From: tammo0 Date: Fri, 31 May 2019 18:24:56 +0200 Subject: [PATCH 1437/2222] save space for web frontend - changed
to
- "name" attributes of input, select, textarea, button items are removed and set by their id (only if ID is set and no name tag given) --- sonoff/language/bg-BG.h | 2 +- sonoff/language/cs-CZ.h | 2 +- sonoff/language/de-DE.h | 2 +- sonoff/language/el-GR.h | 2 +- sonoff/language/en-GB.h | 2 +- sonoff/language/es-ES.h | 2 +- sonoff/language/fr-FR.h | 2 +- sonoff/language/he-HE.h | 2 +- sonoff/language/hu-HU.h | 2 +- sonoff/language/it-IT.h | 2 +- sonoff/language/ko-KO.h | 2 +- sonoff/language/nl-NL.h | 2 +- sonoff/language/pl-PL.h | 2 +- sonoff/language/pt-BR.h | 2 +- sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 2 +- sonoff/language/sk-SK.h | 2 +- sonoff/language/sv-SE.h | 2 +- sonoff/language/tr-TR.h | 2 +- sonoff/language/uk-UK.h | 2 +- sonoff/language/zh-CN.h | 2 +- sonoff/language/zh-TW.h | 2 +- sonoff/xdrv_01_webserver.ino | 110 ++++++++++++++++++----------------- sonoff/xdrv_02_mqtt.ino | 14 ++--- sonoff/xdrv_09_timers.ino | 30 +++++----- sonoff/xdrv_10_scripter.ino | 4 +- sonoff/xdrv_11_knx.ino | 14 ++--- sonoff/xsns_34_hx711.ino | 8 +-- tools/decode-config.py | 2 +- 29 files changed, 115 insertions(+), 111 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 3209cc101..aa9b3095f 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Разрешете JavaScript, за да използвате Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуер
моля надградете го" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуер
моля надградете го" #define D_WEBSERVER_ACTIVE_ON "Уеб сървърът е активен на" #define D_WITH_IP_ADDRESS "с IP адрес" #define D_WEBSERVER_STOPPED "Уеб сървърът е спрян" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 8a919715a..b404b8a0f 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Pro používání prostředí Tasmota povolte JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ
prosím zaktualizujte" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ
prosím zaktualizujte" #define D_WEBSERVER_ACTIVE_ON "Aktivní Web server" #define D_WITH_IP_ADDRESS "na IP adrese" #define D_WEBSERVER_STOPPED "Web server zastaven" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index efc1b737a..bccdbdf30 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "JavaScript aktivieren um Tasmota benutzen zu können" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMUM-Firmware
bitte upgraden" +#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" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 155bf2f4f..4ddcc61d3 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -222,7 +222,7 @@ // webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
παρακαλώ αναβαθμίστε" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
παρακαλώ αναβαθμίστε" #define D_WEBSERVER_ACTIVE_ON "Ενεργός διακομιστής Web στο" #define D_WITH_IP_ADDRESS "με διεύθυνση IP" #define D_WEBSERVER_STOPPED "Ο διακομιστής Web σταμάτησε" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 8d300a711..c9aba7cfd 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
please upgrade" +#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" diff --git a/sonoff/language/es-ES.h b/sonoff/language/es-ES.h index 24200b752..917180216 100644 --- a/sonoff/language/es-ES.h +++ b/sonoff/language/es-ES.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Habilitar JavaScript para usar Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
actualice por favor" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
actualice por favor" #define D_WEBSERVER_ACTIVE_ON "Servidor web activo en" #define D_WITH_IP_ADDRESS "con dirección IP" #define D_WEBSERVER_STOPPED "Servidor web detenido" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 493e8b395..daf849264 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Pour utiliser Tasmota, veuillez activer JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL
merci de mettre à jour" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL
merci de mettre à jour" #define D_WEBSERVER_ACTIVE_ON "Serveur web actif sur" #define D_WITH_IP_ADDRESS "avec l'adresse IP" #define D_WEBSERVER_STOPPED "Serveur web éteint" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index c36f050a7..8f8d35cba 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "JavaScript - כדי להשתמש בקושחת אסמוטה אנא הפעל" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "קושחה מינימלית
בבקשה אנא שדרג" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "קושחה מינימלית
בבקשה אנא שדרג" #define D_WEBSERVER_ACTIVE_ON "שרת ווב פעיל" #define D_WITH_IP_ADDRESS "IP עם כתובת" #define D_WEBSERVER_STOPPED "שרת ווב הופסק" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 3b3ef7821..078169f61 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "A Tasmota használatához engedélyezd a Javascriptet!" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware
frissítsd!" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware
frissítsd!" #define D_WEBSERVER_ACTIVE_ON "Webszerver aktív:" #define D_WITH_IP_ADDRESS "IP cím:" #define D_WEBSERVER_STOPPED "Webszerver leállítva" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 9078bc81e..f498f9295 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Abilitare JavaScript per utilizzare Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
effettuare aggiornamento" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
effettuare aggiornamento" #define D_WEBSERVER_ACTIVE_ON "Web server attivo su" #define D_WITH_IP_ADDRESS "con indirizzo IP" #define D_WEBSERVER_STOPPED "Web server arrestato" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index 37c289963..4e553c36b 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Tasmota를 사용하려면 JavaScript를 활성화 하십시오." -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
업그레이드가 필요합니다" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
업그레이드가 필요합니다" #define D_WEBSERVER_ACTIVE_ON "Web 서버 작동 중" #define D_WITH_IP_ADDRESS "IP 주소" #define D_WEBSERVER_STOPPED "Web 서버 멈춤" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 4525ce5cb..364fea246 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Zet JavaScript aan voor Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
opwaarderen" +#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" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index a2ed0721c..a08e9ecc8 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Aby korzystać z Tasmota, włącz obsługę JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL
proszę uaktualnić" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL
proszę uaktualnić" #define D_WEBSERVER_ACTIVE_ON "Aktywny serwer Web" #define D_WITH_IP_ADDRESS "z adresem IP" #define D_WEBSERVER_STOPPED "Serwer Web zatrzymany" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index c66867178..863c40b0f 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo
Atualizar por favor" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo
Atualizar por favor" #define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" #define D_WITH_IP_ADDRESS "com o endereço IP" #define D_WEBSERVER_STOPPED "Servidor WEB parou" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 334844a72..f45e71a73 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMO firmware
Atualizar Por favor" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMO firmware
Atualizar Por favor" #define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" #define D_WITH_IP_ADDRESS "com o endereço IP" #define D_WEBSERVER_STOPPED "Servitor WEB parou" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 071be1394..b76f0e4b4 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
пожалуйста обновите" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
пожалуйста обновите" #define D_WEBSERVER_ACTIVE_ON "Веб-сервер активен" #define D_WITH_IP_ADDRESS "с IP-адресом" #define D_WEBSERVER_STOPPED "Веб-сервер остановлен" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 7cdea4177..2c5d126ef 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "Pre používanie prostredia Tasmota povoľte JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY
prosím aktualizujte" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY
prosím aktualizujte" #define D_WEBSERVER_ACTIVE_ON "Aktívny Web server" #define D_WITH_IP_ADDRESS "na IP adrese" #define D_WEBSERVER_STOPPED "Web server zastavený" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index f6b0638bd..35fec7e4c 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "För att använda Tasmota, aktivera JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
var god uppgradera" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
var god uppgradera" #define D_WEBSERVER_ACTIVE_ON "Webbserver aktiv på" #define D_WITH_IP_ADDRESS "med IP-adress" #define D_WEBSERVER_STOPPED "Webbserver stoppad" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index dc764d006..68da47c01 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük
lütfen yükseltin" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük
lütfen yükseltin" #define D_WEBSERVER_ACTIVE_ON "Web sunucusu aktif" #define D_WITH_IP_ADDRESS "IP adres ile" #define D_WEBSERVER_STOPPED "Web sunucusu durdu" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 6f4d6208c..55ef6781b 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
будь-ласка оновіть" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
будь-ласка оновіть" #define D_WEBSERVER_ACTIVE_ON "Веб-сервер активний" #define D_WITH_IP_ADDRESS "з IP-адресом" #define D_WEBSERVER_STOPPED "Веб-сервер зупинений" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index a1bca5a88..aa4a60492 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -222,7 +222,7 @@ // webserver.ino #define D_NOSCRIPT "Tasmota要求浏览器支持 JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件
请升级" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件
请升级" #define D_WEBSERVER_ACTIVE_ON "Web 服务器地址:" #define D_WITH_IP_ADDRESS "IP 地址:" #define D_WEBSERVER_STOPPED "Web 服务已停止" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 9b87d03f3..2171d1ea0 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -222,7 +222,7 @@ // xdrv_02_webserver.ino #define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低
請升級" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低
請升級" #define D_WEBSERVER_ACTIVE_ON "Web服務器:" #define D_WITH_IP_ADDRESS "IP地址:" #define D_WEBSERVER_STOPPED "Web 服務器已停止" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 28250adf1..433f8a1db 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -57,7 +57,11 @@ const char HTTP_HEAD[] PROGMEM = "var x=null,lt,to,tp,pc='';" // x=null allow for abortion "function eb(s){" "return document.getElementById(s);" // Save code space - "}"; + "}" + "function idn(){" + "var t=0,i=document.querySelectorAll('input,button,textarea,select'); while(i.length>=t){ if(i[t]) {i[t]['name']=(i[t].hasAttribute('id')&&(!i[t].hasAttribute('name')))?i[t]['id']:i[t]['name'];}t++;}" + "}" + "window.onload=idn;"; const char HTTP_SCRIPT_COUNTER[] PROGMEM = "var cn=180;" // seconds @@ -277,7 +281,7 @@ const char HTTP_HEAD_STYLE3[] PROGMEM = #ifdef FIRMWARE_MINIMAL "

" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "

" // COLOR_TEXT_WARNING #endif - "
" + "
" #ifdef LANGUAGE_MODULE_NAME "

" D_MODULE " %s

" #else @@ -292,14 +296,14 @@ const char HTTP_MSG_SLIDER2[] PROGMEM = "
" D_DARKLIGHT "" D_BRIGHTLIGHT "
" "
"; const char HTTP_MSG_RSTRT[] PROGMEM = - "
" D_DEVICE_WILL_RESTART "

"; + "
" D_DEVICE_WILL_RESTART "

"; const char HTTP_FORM_LOGIN[] PROGMEM = "
" "" - "

" D_USER "

" - "

" D_PASSWORD "

" - "
" + "

" D_USER "

" + "

" D_PASSWORD "

" + "
" "" "
"; @@ -307,84 +311,84 @@ const char HTTP_FORM_TEMPLATE[] PROGMEM = "
 " D_TEMPLATE_PARAMETERS " " "
"; const char HTTP_FORM_TEMPLATE_FLAG[] PROGMEM = - "

" // Keep close so do not use
+ "

" // Keep close so do not use
"
 " D_TEMPLATE_FLAGS " 

" -// "" D_OPTION_TEXT "
" +// "" D_OPTION_TEXT "
" "

"; const char HTTP_FORM_MODULE[] PROGMEM = "
 " D_MODULE_PARAMETERS " " "" - "

" D_MODULE_TYPE " (%s)

" - "
"; + "

" D_MODULE_TYPE " (%s)

" + "
"; const char HTTP_FORM_WIFI[] PROGMEM = "
 " D_WIFI_PARAMETERS " " "" - "

" D_AP1_SSID " (" STA_SSID1 ")

" - "

" D_AP1_PASSWORD "

" - "

" D_AP2_SSID " (" STA_SSID2 ")

" - "

" D_AP2_PASSWORD "

" - "

" D_HOSTNAME " (%s)

"; + "

" D_AP1_SSID " (" STA_SSID1 ")

" + "

" D_AP1_PASSWORD "

" + "

" D_AP2_SSID " (" STA_SSID2 ")

" + "

" D_AP2_PASSWORD "

" + "

" D_HOSTNAME " (%s)

"; const char HTTP_FORM_LOG1[] PROGMEM = "
 " D_LOGGING_PARAMETERS " " ""; const char HTTP_FORM_LOG2[] PROGMEM = - "

" D_SYSLOG_HOST " (" SYS_LOG_HOST ")

" - "

" D_SYSLOG_PORT " (" STR(SYS_LOG_PORT) ")

" - "

" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

"; + "

" D_SYSLOG_HOST " (" SYS_LOG_HOST ")

" + "

" D_SYSLOG_PORT " (" STR(SYS_LOG_PORT) ")

" + "

" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

"; const char HTTP_FORM_OTHER[] PROGMEM = "
 " D_OTHER_PARAMETERS " " "" "

" "
 " D_TEMPLATE " " - "

" - "

" D_ACTIVATE "

" + "

" + "

" D_ACTIVATE "

" "
" - "
" - "" D_WEB_ADMIN_PASSWORD "

" "
" - "" D_MQTT_ENABLE "
" - "
"; + "" D_WEB_ADMIN_PASSWORD "

" + "
" + "" D_MQTT_ENABLE "
" + "
"; const char HTTP_FORM_END[] PROGMEM = - "
" + "
" "" "
"; const char HTTP_FORM_RST[] PROGMEM = - "
" + "
" "
 " D_RESTORE_CONFIGURATION " "; const char HTTP_FORM_UPG[] PROGMEM = - "
" + "
" "
 " D_UPGRADE_BY_WEBSERVER " " "
" - "
" D_OTA_URL "

" - "
" - "


" + "
" D_OTA_URL "

" + "
" + "


" "
 " D_UPGRADE_BY_FILE_UPLOAD " "; const char HTTP_FORM_RST_UPG[] PROGMEM = "
" - "

" - "
" + "

" + "
" "
" "
" - ""; + ""; const char HTTP_FORM_CMND[] PROGMEM = - "


" + "


" "
" - "
" - // "
" + "
" + // "
" ""; const char HTTP_TABLE100[] PROGMEM = "
"; const char HTTP_COUNTER[] PROGMEM = - "
"; + "
"; const char HTTP_END[] PROGMEM = "" @@ -809,9 +813,9 @@ void WebRestart(uint8_t type) WSContentSend_P(HTTP_SCRIPT_RELOAD); WSContentSendStyle(); if (type) { - WSContentSend_P(PSTR("
" D_CONFIGURATION_SAVED "
")); + WSContentSend_P(PSTR("
" D_CONFIGURATION_SAVED "
")); if (2 == type) { - WSContentSend_P(PSTR("
" D_TRYING_TO_CONNECT "
")); + WSContentSend_P(PSTR("
" D_TRYING_TO_CONNECT "
")); } WSContentSend_P(PSTR("
")); } @@ -1112,8 +1116,8 @@ void HandleTemplateConfiguration(void) WSContentSendStyle(); WSContentSend_P(HTTP_FORM_TEMPLATE); WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("
" - "" + WSContentSend_P(PSTR("" + "" "
" D_TEMPLATE_NAME "
" D_BASE_TYPE "
" D_TEMPLATE_NAME "
" D_BASE_TYPE "
" "
")); WSContentSend_P(HTTP_TABLE100); @@ -1123,7 +1127,7 @@ void HandleTemplateConfiguration(void) ((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:200px'" : "", i, i); } } - WSContentSend_P(PSTR("" D_ADC "0"), WebColor(COL_TEXT)); + WSContentSend_P(PSTR("" D_ADC "0"), WebColor(COL_TEXT)); WSContentSend_P(PSTR("")); gpio_flag flag = ModuleFlag(); if (flag.data > ADC0_USER) { @@ -1249,7 +1253,7 @@ void HandleModuleConfiguration(void) } #ifndef USE_ADC_VCC if (ValidAdc()) { - WSContentSend_P(PSTR("%s " D_ADC "0"), (WEMOS==my_module_type)?"A0":""); + WSContentSend_P(PSTR("%s " D_ADC "0"), (WEMOS==my_module_type)?"A0":""); } #endif // USE_ADC_VCC WSContentSend_P(PSTR("")); @@ -1396,10 +1400,10 @@ void HandleWifiConfiguration(void) } } - WSContentSend_P(PSTR("
")); + WSContentSend_P(PSTR("
")); } } else { - WSContentSend_P(PSTR("
")); + WSContentSend_P(PSTR("
")); } // As WIFI_HOSTNAME may contain %s-%04d it cannot be part of HTTP_FORM_WIFI where it will exception @@ -1460,7 +1464,7 @@ void HandleLoggingConfiguration(void) uint8_t dlevel[3] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE }; for (uint8_t idx = 0; idx < 3; idx++) { uint8_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:Settings.syslog_level; - WSContentSend_P(PSTR("

%s (%s)
"), GetTextIndexed(stemp1, sizeof(stemp1), idx, kLoggingOptions), GetTextIndexed(stemp2, sizeof(stemp2), dlevel[idx], kLoggingLevels), idx, idx); @@ -1528,7 +1532,7 @@ void HandleOtherConfiguration(void) if (SONOFF_IFAN02 == my_module_type) { maxfn = 1; } for (uint8_t i = 0; i < maxfn; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i +1); - WSContentSend_P(PSTR("" D_FRIENDLY_NAME " %d (" FRIENDLY_NAME "%s)

"), + WSContentSend_P(PSTR("" D_FRIENDLY_NAME " %d (" FRIENDLY_NAME "%s)

"), i +1, (i) ? stemp : "", i, i, @@ -1537,7 +1541,7 @@ void HandleOtherConfiguration(void) } #ifdef USE_EMULATION - WSContentSend_P(PSTR("

 " D_EMULATION " 

")); // Keep close to Friendlynames so do not use
+ WSContentSend_P(PSTR("

 " D_EMULATION " 

")); // Keep close to Friendlynames so do not use
for (uint8_t i = 0; i < EMUL_MAX; i++) { #ifndef USE_EMULATION_WEMO if (i == EMUL_WEMO) { i++; } @@ -1546,7 +1550,7 @@ void HandleOtherConfiguration(void) if (i == EMUL_HUE) { i++; } #endif if (i < EMUL_MAX) { - WSContentSend_P(PSTR("%s %s
"), // Different id only used for labels + WSContentSend_P(PSTR("%s %s
"), // Different id only used for labels i, i, (i == Settings.flag2.emulation) ? " checked" : "", GetTextIndexed(stemp, sizeof(stemp), i, kEmulationOptions), @@ -1844,8 +1848,8 @@ void HandleUploadDone(void) WSContentSendStyle(); WSContentSend_P(PSTR("

" D_UPLOAD " " D_FAILED "

")); - WSContentSend_P(PSTR("%06x'>" D_FAILED "

"), WebColor(COL_TEXT_WARNING)); +// WSContentSend_P(PSTR(COLOR_TEXT_WARNING "'>" D_FAILED "

")); + WSContentSend_P(PSTR("%06x'>" D_FAILED "

"), WebColor(COL_TEXT_WARNING)); #ifdef USE_RF_FLASH if (upload_error < 14) { #else @@ -1859,13 +1863,13 @@ void HandleUploadDone(void) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_UPLOAD ": %s"), error); stop_flash_rotate = Settings.flag.stop_flash_rotate; } else { - WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "
"), WebColor(COL_TEXT_SUCCESS)); + WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "
"), WebColor(COL_TEXT_SUCCESS)); WSContentSend_P(HTTP_MSG_RSTRT); ShowWebSource(SRC_WEBGUI); restart_flag = 2; // Always restart to re-enable disabled features during update } SettingsBufferFree(); - WSContentSend_P(PSTR("

")); + WSContentSend_P(PSTR("

")); WSContentSpaceButton(BUTTON_MAIN); WSContentStop(); } diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 4d60e157b..23f9ebe5d 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -746,14 +746,14 @@ const char HTTP_BTN_MENU_MQTT[] PROGMEM = const char HTTP_FORM_MQTT1[] PROGMEM = "
 " D_MQTT_PARAMETERS " " "
" - "

" D_HOST " (" MQTT_HOST ")

" - "

" D_PORT " (" STR(MQTT_PORT) ")

" - "

" D_CLIENT " (%s)

"; + "

" D_HOST " (" MQTT_HOST ")

" + "

" D_PORT " (" STR(MQTT_PORT) ")

" + "

" D_CLIENT " (%s)

"; const char HTTP_FORM_MQTT2[] PROGMEM = - "

" D_USER " (" MQTT_USER ")

" - "

" D_PASSWORD "

" - "

" D_TOPIC " = %%topic%% (%s)

" - "

" D_FULL_TOPIC " (%s)

"; + "

" D_USER " (" MQTT_USER ")

" + "

" D_PASSWORD "

" + "

" D_TOPIC " = %%topic%% (%s)

" + "

" D_FULL_TOPIC " (%s)

"; void HandleMqttConfiguration(void) { diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 3f838ed7a..ade7ed3eb 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -660,37 +660,37 @@ const char HTTP_FORM_TIMER1[] PROGMEM = "
" " " D_TIMER_PARAMETERS " " "" - "
" D_TIMER_ENABLE "


" - "" D_TIMER_ENABLE "


" + "



" - "

" + "' hidden>



" + "

" "
" - "" D_TIMER_ARM " " - "" D_TIMER_REPEAT "" - "

" + "" D_TIMER_ARM " " + "" D_TIMER_REPEAT "" + "

" "
"; #ifdef USE_SUNRISE const char HTTP_FORM_TIMER3[] PROGMEM = "
" - "" D_TIMER_TIME "
" - "" D_SUNRISE " (%s)
" - "" D_SUNSET " (%s)
" + "" D_TIMER_TIME "
" + "" D_SUNRISE " (%s)
" + "" D_SUNSET " (%s)
" "
" "

" - "" + "" " "; #else const char HTTP_FORM_TIMER3[] PROGMEM = "" D_TIMER_TIME " "; #endif // USE_SUNRISE const char HTTP_FORM_TIMER4[] PROGMEM = - "" + "" " " D_HOUR_MINUTE_SEPARATOR " " - "" + "" " +/- " - "" - "

" + "" + "
" "
"; void HandleTimerConfiguration(void) diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index 3b21603de..1eee4a031 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -2387,8 +2387,8 @@ const char HTTP_FORM_SCRIPT[] PROGMEM = const char HTTP_FORM_SCRIPT1[] PROGMEM = "
" - "script enable
" - "
" ""; const char HTTP_HEAD_STYLE1[] PROGMEM = - "" - "" + + "" + "" + "
" +#ifdef FIRMWARE_MINIMAL + "

" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "

" +#endif + "
" +#ifdef LANGUAGE_MODULE_NAME + "

" D_MODULE " %s

" +#else + "

%s " D_MODULE "

" +#endif + "

%s

"; + +const char HTTP_MSG_SLIDER1[] PROGMEM = + "
" D_COLDLIGHT "" D_WARMLIGHT "
" + "
"; +const char HTTP_MSG_SLIDER2[] PROGMEM = + "
" D_DARKLIGHT "" D_BRIGHTLIGHT "
" + "
"; +const char HTTP_MSG_RSTRT[] PROGMEM = + "
" D_DEVICE_WILL_RESTART "

"; + +const char HTTP_FORM_LOGIN[] PROGMEM = + "
" + "" + "

" D_USER "

" + "

" D_PASSWORD "

" + "
" + "" + "
"; + +const char HTTP_FORM_TEMPLATE[] PROGMEM = + "
 " D_TEMPLATE_PARAMETERS " " + "
"; +const char HTTP_FORM_TEMPLATE_FLAG[] PROGMEM = + "

" + "
 " D_TEMPLATE_FLAGS " 

" + + "

"; + +const char HTTP_FORM_MODULE[] PROGMEM = + "
 " D_MODULE_PARAMETERS " " + "" + "

" D_MODULE_TYPE " (%s)

" + "
"; + +const char HTTP_FORM_WIFI[] PROGMEM = + "
 " D_WIFI_PARAMETERS " " + "" + "

" D_AP1_SSID " (" STA_SSID1 ")

" + "

" D_AP1_PASSWORD "

" + "

" D_AP2_SSID " (" STA_SSID2 ")

" + "

" D_AP2_PASSWORD "

" + "

" D_HOSTNAME " (%s)

"; + +const char HTTP_FORM_LOG1[] PROGMEM = + "
 " D_LOGGING_PARAMETERS " " + ""; +const char HTTP_FORM_LOG2[] PROGMEM = + "

" D_SYSLOG_HOST " (" SYS_LOG_HOST ")

" + "

" D_SYSLOG_PORT " (" STR(SYS_LOG_PORT) ")

" + "

" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

"; + +const char HTTP_FORM_OTHER[] PROGMEM = + "
 " D_OTHER_PARAMETERS " " + "" + "

" + "
 " D_TEMPLATE " " + "

" + "

" D_ACTIVATE "

" + "
" + "
" + "" D_WEB_ADMIN_PASSWORD "

" + "
" + "" D_MQTT_ENABLE "
" + "
"; + +const char HTTP_FORM_END[] PROGMEM = + "
" + "" + "
"; + +const char HTTP_FORM_RST[] PROGMEM = + "
" + "
 " D_RESTORE_CONFIGURATION " "; +const char HTTP_FORM_UPG[] PROGMEM = + "
" + "
 " D_UPGRADE_BY_WEBSERVER " " + "
" + "
" D_OTA_URL "

" + "
" + "


" + "
 " D_UPGRADE_BY_FILE_UPLOAD " "; +const char HTTP_FORM_RST_UPG[] PROGMEM = + "
" + "

" + "
" + "
" + "
" + ""; + +const char HTTP_FORM_CMND[] PROGMEM = + "


" + "
" + "
" + + ""; + +const char HTTP_TABLE100[] PROGMEM = + "
"; + +const char HTTP_COUNTER[] PROGMEM = + "
"; + +const char HTTP_END[] PROGMEM = + "" + "" + "" + ""; + +const char HTTP_DEVICE_CONTROL[] PROGMEM = ""; +const char HTTP_DEVICE_STATE[] PROGMEM = ""; + +enum ButtonTitle { + BUTTON_RESTART, BUTTON_RESET_CONFIGURATION, + BUTTON_MAIN, BUTTON_CONFIGURATION, BUTTON_INFORMATION, BUTTON_FIRMWARE_UPGRADE, BUTTON_CONSOLE, + BUTTON_MODULE, BUTTON_WIFI, BUTTON_LOGGING, BUTTON_OTHER, BUTTON_TEMPLATE, BUTTON_BACKUP, BUTTON_RESTORE }; +const char kButtonTitle[] PROGMEM = + D_RESTART "|" D_RESET_CONFIGURATION "|" + D_MAIN_MENU "|" D_CONFIGURATION "|" D_INFORMATION "|" D_FIRMWARE_UPGRADE "|" D_CONSOLE "|" + D_CONFIGURE_MODULE "|" D_CONFIGURE_WIFI"|" D_CONFIGURE_LOGGING "|" D_CONFIGURE_OTHER "|" D_CONFIGURE_TEMPLATE "|" D_BACKUP_CONFIGURATION "|" D_RESTORE_CONFIGURATION; +const char kButtonAction[] PROGMEM = + ".|rt|" + ".|cn|in|up|cs|" + "md|wi|lg|co|tp|dl|rs"; +const char kButtonConfirm[] PROGMEM = D_CONFIRM_RESTART "|" D_CONFIRM_RESET_CONFIGURATION; + +enum CTypes { CT_HTML, CT_PLAIN, CT_XML, CT_JSON, CT_STREAM }; +const char kContentTypes[] PROGMEM = "text/html|text/plain|text/xml|application/json|application/octet-stream"; + +const char kLoggingOptions[] PROGMEM = D_SERIAL_LOG_LEVEL "|" D_WEB_LOG_LEVEL "|" D_SYS_LOG_LEVEL; +const char kLoggingLevels[] PROGMEM = D_NONE "|" D_ERROR "|" D_INFO "|" D_DEBUG "|" D_MORE_DEBUG; + +const char kEmulationOptions[] PROGMEM = D_NONE "|" D_BELKIN_WEMO "|" D_HUE_BRIDGE; + +const char kUploadErrors[] PROGMEM = + D_UPLOAD_ERR_1 "|" D_UPLOAD_ERR_2 "|" D_UPLOAD_ERR_3 "|" D_UPLOAD_ERR_4 "|" D_UPLOAD_ERR_5 "|" D_UPLOAD_ERR_6 "|" D_UPLOAD_ERR_7 "|" D_UPLOAD_ERR_8 "|" D_UPLOAD_ERR_9 +#ifdef USE_RF_FLASH + "|" D_UPLOAD_ERR_10 "|" D_UPLOAD_ERR_11 "|" D_UPLOAD_ERR_12 "|" D_UPLOAD_ERR_13 +#endif + ; + +const uint16_t DNS_PORT = 53; +enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER, HTTP_MANAGER_RESET_ONLY}; + +DNSServer *DnsServer; +ESP8266WebServer *WebServer; + +struct WEB { + String chunk_buffer = ""; + bool reset_web_log_flag = false; + uint8_t state = HTTP_OFF; + uint8_t upload_error = 0; + uint8_t upload_file_type; + uint8_t upload_progress_dot_count; + uint8_t config_block_count = 0; + uint8_t config_xor_on = 0; + uint8_t config_xor_on_set = CONFIG_FILE_XOR; +} Web; + + +static void WebGetArg(const char* arg, char* out, size_t max) +{ + String s = WebServer->arg(arg); + strlcpy(out, s.c_str(), max); + +} + +static bool WifiIsInManagerMode(){ + return (HTTP_MANAGER == Web.state || HTTP_MANAGER_RESET_ONLY == Web.state); +} + +void ShowWebSource(uint32_t source) +{ + if ((source > 0) && (source < SRC_MAX)) { + char stemp1[20]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SRC: %s from %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource), WebServer->client().remoteIP().toString().c_str()); + } +} + +void ExecuteWebCommand(char* svalue, uint32_t source) +{ + ShowWebSource(source); + ExecuteCommand(svalue, SRC_IGNORE); +} + +void StartWebserver(int type, IPAddress ipweb) +{ + if (!Settings.web_refresh) { Settings.web_refresh = HTTP_REFRESH_TIME; } + if (!Web.state) { + if (!WebServer) { + WebServer = new ESP8266WebServer((HTTP_MANAGER == type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT); + WebServer->on("/", HandleRoot); + WebServer->onNotFound(HandleNotFound); + WebServer->on("/up", HandleUpgradeFirmware); + WebServer->on("/u1", HandleUpgradeFirmwareStart); + WebServer->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); + WebServer->on("/u2", HTTP_OPTIONS, HandlePreflightRequest); + WebServer->on("/cs", HTTP_GET, HandleConsole); + WebServer->on("/cs", HTTP_OPTIONS, HandlePreflightRequest); + WebServer->on("/cm", HandleHttpCommand); +#ifndef FIRMWARE_MINIMAL + WebServer->on("/cn", HandleConfiguration); + WebServer->on("/md", HandleModuleConfiguration); + WebServer->on("/wi", HandleWifiConfiguration); + WebServer->on("/lg", HandleLoggingConfiguration); + WebServer->on("/tp", HandleTemplateConfiguration); + WebServer->on("/co", HandleOtherConfiguration); + WebServer->on("/dl", HandleBackupConfiguration); + WebServer->on("/rs", HandleRestoreConfiguration); + WebServer->on("/rt", HandleResetConfiguration); + WebServer->on("/in", HandleInformation); + XdrvCall(FUNC_WEB_ADD_HANDLER); + XsnsCall(FUNC_WEB_ADD_HANDLER); +#endif + } + Web.reset_web_log_flag = false; + + + + WebServer->collectHeaders(HEADER_KEYS, sizeof(HEADER_KEYS)/sizeof(char*)); + + WebServer->begin(); + } + if (Web.state != type) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), my_hostname, (Wifi.mdns_begun) ? ".local" : "", ipweb.toString().c_str()); + rules_flag.http_init = 1; + } + if (type) { Web.state = type; } +} + +void StopWebserver(void) +{ + if (Web.state) { + WebServer->close(); + Web.state = HTTP_OFF; + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_STOPPED)); + } +} + +void WifiManagerBegin(bool reset_only) +{ + + if (!global_state.wifi_down) { + WiFi.mode(WIFI_AP_STA); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION)); + } else { + WiFi.mode(WIFI_AP); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_WIFIMANAGER_SET_ACCESSPOINT)); + } + + StopWebserver(); + + DnsServer = new DNSServer(); + + int channel = WIFI_SOFT_AP_CHANNEL; + if ((channel < 1) || (channel > 13)) { channel = 1; } + WiFi.softAP(my_hostname, nullptr, channel); + + delay(500); + + DnsServer->setErrorReplyCode(DNSReplyCode::NoError); + DnsServer->start(DNS_PORT, "*", WiFi.softAPIP()); + + StartWebserver((reset_only ? HTTP_MANAGER_RESET_ONLY : HTTP_MANAGER), WiFi.softAPIP()); +} + +void PollDnsWebserver(void) +{ + if (DnsServer) { DnsServer->processNextRequest(); } + if (WebServer) { WebServer->handleClient(); } +} + + + +bool WebAuthenticate(void) +{ + if (Settings.web_password[0] != 0 && HTTP_MANAGER_RESET_ONLY != Web.state) { + return WebServer->authenticate(WEB_USERNAME, Settings.web_password); + } else { + return true; + } +} + +bool HttpCheckPriviledgedAccess(bool autorequestauth = true) +{ + if (HTTP_USER == Web.state) { + HandleRoot(); + return false; + } + if (autorequestauth && !WebAuthenticate()) { + WebServer->requestAuthentication(); + return false; + } + return true; +} + +void WSHeaderSend(void) +{ + WebServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate")); + WebServer->sendHeader(F("Pragma"), F("no-cache")); + WebServer->sendHeader(F("Expires"), F("-1")); +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 + WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); +#endif +} + + + + + +void WSSend(int code, int ctype, const String& content) +{ + char ct[25]; + WebServer->send(code, GetTextIndexed(ct, sizeof(ct), ctype, kContentTypes), content); +} + + + + + +void WSContentBegin(int code, int ctype) +{ + WebServer->client().flush(); + WSHeaderSend(); +#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 + WebServer->sendHeader(F("Accept-Ranges"),F("none")); + WebServer->sendHeader(F("Transfer-Encoding"),F("chunked")); +#endif + WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); + WSSend(code, ctype, ""); + Web.chunk_buffer = ""; +} + +void _WSContentSend(const String& content) +{ + size_t len = content.length(); + +#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 + const char * footer = "\r\n"; + char chunk_size[11]; + sprintf(chunk_size, "%x\r\n", len); + WebServer->sendContent(String() + chunk_size + content + footer); +#else + WebServer->sendContent(content); +#endif + +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("WSContentSend")); +#endif + DEBUG_CORE_LOG(PSTR("WEB: Chunk size %d"), len); +} + +void WSContentFlush() +{ + if (Web.chunk_buffer.length() > 0) { + _WSContentSend(Web.chunk_buffer); + Web.chunk_buffer = ""; + } +} + +void _WSContentSendBuffer(void) +{ + int len = strlen(mqtt_data); + + if (0 == len) { + return; + } + else if (len == sizeof(mqtt_data)) { + AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: Content too large")); + } + else if (len < CHUNKED_BUFFER_SIZE) { + Web.chunk_buffer += mqtt_data; + len = Web.chunk_buffer.length(); + } + + if (len >= CHUNKED_BUFFER_SIZE) { + WSContentFlush(); + } + if (strlen(mqtt_data) >= CHUNKED_BUFFER_SIZE) { + _WSContentSend(mqtt_data); + } +} + +void WSContentSend_P(const char* formatP, ...) +{ + + va_list arg; + va_start(arg, formatP); + vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); + va_end(arg); + + _WSContentSendBuffer(); +} + +void WSContentSend_PD(const char* formatP, ...) +{ + + va_list arg; + va_start(arg, formatP); + int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); + va_end(arg); + + if (D_DECIMAL_SEPARATOR[0] != '.') { + for (uint32_t i = 0; i < len; i++) { + if ('.' == mqtt_data[i]) { + mqtt_data[i] = D_DECIMAL_SEPARATOR[0]; + } + } + } + + _WSContentSendBuffer(); +} + +void WSContentStart_P(const char* title, bool auth) +{ + if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) { + return WebServer->requestAuthentication(); + } + + WSContentBegin(200, CT_HTML); + + if (title != nullptr) { + char ctitle[strlen_P(title) +1]; + strcpy_P(ctitle, title); + WSContentSend_P(HTTP_HEADER, Settings.friendlyname[0], ctitle); + } +} + +void WSContentStart_P(const char* title) +{ + WSContentStart_P(title, true); +} + +void WSContentSendStyle_P(const char* formatP, ...) +{ + if (WifiIsInManagerMode()) { + if (WifiConfigCounter()) { + WSContentSend_P(HTTP_SCRIPT_COUNTER); + } + } + WSContentSend_P(HTTP_HEAD_LAST_SCRIPT); + + WSContentSend_P(HTTP_HEAD_STYLE1, WebColor(COL_FORM), WebColor(COL_INPUT), WebColor(COL_INPUT_TEXT), WebColor(COL_INPUT), WebColor(COL_INPUT_TEXT), WebColor(COL_CONSOLE), WebColor(COL_CONSOLE_TEXT), WebColor(COL_BACKGROUND)); + WSContentSend_P(HTTP_HEAD_STYLE2, WebColor(COL_BUTTON), WebColor(COL_BUTTON_TEXT), WebColor(COL_BUTTON_HOVER), WebColor(COL_BUTTON_RESET), WebColor(COL_BUTTON_RESET_HOVER), WebColor(COL_BUTTON_SAVE), WebColor(COL_BUTTON_SAVE_HOVER)); + if (formatP != nullptr) { + + va_list arg; + va_start(arg, formatP); + vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); + va_end(arg); + _WSContentSendBuffer(); + } + WSContentSend_P(HTTP_HEAD_STYLE3, WebColor(COL_TEXT), +#ifdef FIRMWARE_MINIMAL + WebColor(COL_TEXT_WARNING), +#endif + ModuleName().c_str(), Settings.friendlyname[0]); + if (Settings.flag3.gui_hostname_ip) { + bool lip = (static_cast(WiFi.localIP()) != 0); + bool sip = (static_cast(WiFi.softAPIP()) != 0); + WSContentSend_P(PSTR("

%s%s (%s%s%s)

"), + my_hostname, + (Wifi.mdns_begun) ? ".local" : "", + (lip) ? WiFi.localIP().toString().c_str() : "", + (lip && sip) ? ", " : "", + (sip) ? WiFi.softAPIP().toString().c_str() : ""); + } + WSContentSend_P(PSTR("")); +} + +void WSContentSendStyle(void) +{ + WSContentSendStyle_P(nullptr); +} + +void WSContentButton(uint32_t title_index) +{ + char action[4]; + char title[100]; + + if (title_index <= BUTTON_RESET_CONFIGURATION) { + char confirm[100]; + WSContentSend_P(PSTR("

"), + GetTextIndexed(action, sizeof(action), title_index, kButtonAction), + GetTextIndexed(confirm, sizeof(confirm), title_index, kButtonConfirm), + (!title_index) ? "rst" : "non", + GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); + } else { + WSContentSend_P(PSTR("

"), + GetTextIndexed(action, sizeof(action), title_index, kButtonAction), + GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); + } +} + +void WSContentSpaceButton(uint32_t title_index) +{ + WSContentSend_P(PSTR("
")); + WSContentButton(title_index); +} + +void WSContentEnd(void) +{ + WSContentFlush(); + _WSContentSend(""); + WebServer->client().stop(); +} + +void WSContentStop(void) +{ + if (WifiIsInManagerMode()) { + if (WifiConfigCounter()) { + WSContentSend_P(HTTP_COUNTER); + } + } + WSContentSend_P(HTTP_END, my_version); + WSContentEnd(); +} + + + +void WebRestart(uint32_t type) +{ + + + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTART); + + bool reset_only = (HTTP_MANAGER_RESET_ONLY == Web.state); + + WSContentStart_P((type) ? S_SAVE_CONFIGURATION : S_RESTART, !reset_only); + WSContentSend_P(HTTP_SCRIPT_RELOAD); + WSContentSendStyle(); + if (type) { + WSContentSend_P(PSTR("
" D_CONFIGURATION_SAVED "
")); + if (2 == type) { + WSContentSend_P(PSTR("
" D_TRYING_TO_CONNECT "
")); + } + WSContentSend_P(PSTR("
")); + } + WSContentSend_P(HTTP_MSG_RSTRT); + if (HTTP_MANAGER == Web.state || reset_only) { + Web.state = HTTP_ADMIN; + } else { + WSContentSpaceButton(BUTTON_MAIN); + } + WSContentStop(); + + ShowWebSource(SRC_WEBGUI); + restart_flag = 2; +} + + + +void HandleWifiLogin(void) +{ + WSContentStart_P(S_CONFIGURE_WIFI, false); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_LOGIN); + + if (HTTP_MANAGER_RESET_ONLY == Web.state) { + WSContentSpaceButton(BUTTON_RESTART); +#ifndef FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); +#endif + } + + WSContentStop(); +} + +void HandleRoot(void) +{ + if (CaptivePortal()) { return; } + + if (WebServer->hasArg("rst")) { + WebRestart(0); + return; + } + + if (WifiIsInManagerMode()) { +#ifndef FIRMWARE_MINIMAL + if ((Settings.web_password[0] != 0) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { + HandleWifiLogin(); + } else { + if (!(Settings.web_password[0] != 0) || (((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == Settings.web_password )) || HTTP_MANAGER_RESET_ONLY == Web.state)) { + HandleWifiConfiguration(); + } else { + + HandleWifiLogin(); + } + } +#endif + return; + } + + if (HandleRootStatusRefresh()) { + return; + } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_MAIN_MENU); + + char stemp[5]; + + WSContentStart_P(S_MAIN_MENU); +#ifdef USE_SCRIPT_WEB_DISPLAY + WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh, Settings.web_refresh); +#else + WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh); +#endif + WSContentSendStyle(); + + WSContentSend_P(PSTR("
")); + if (devices_present) { +#ifdef USE_LIGHT + if (light_type) { + if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { + WSContentSend_P(HTTP_MSG_SLIDER1, LightGetColorTemp()); + } + WSContentSend_P(HTTP_MSG_SLIDER2, Settings.light_dimmer); + } +#endif + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("
")); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); + for (uint32_t i = 0; i < MaxFanspeed(); i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); + WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i +2, stemp, ""); + } + } else { +#endif + for (uint32_t idx = 1; idx <= devices_present; idx++) { + snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); + } +#ifdef USE_SONOFF_IFAN + } +#endif + WSContentSend_P(PSTR("
%s
")); + } + if (SONOFF_BRIDGE == my_module_type) { + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("")); + uint32_t idx = 0; + for (uint32_t i = 0; i < 4; i++) { + if (idx > 0) { WSContentSend_P(PSTR("")); } + for (uint32_t j = 0; j < 4; j++) { + idx++; + WSContentSend_P(PSTR(""), idx, idx); + } + } + WSContentSend_P(PSTR("")); + } + +#ifndef FIRMWARE_MINIMAL + XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); + XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); +#endif + + if (HTTP_ADMIN == Web.state) { +#ifdef FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_FIRMWARE_UPGRADE); +#else + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentButton(BUTTON_INFORMATION); + WSContentButton(BUTTON_FIRMWARE_UPGRADE); +#endif + WSContentButton(BUTTON_CONSOLE); + WSContentButton(BUTTON_RESTART); + } + WSContentStop(); +} + +bool HandleRootStatusRefresh(void) +{ + if (!WebAuthenticate()) { + WebServer->requestAuthentication(); + return true; + } + + if (!WebServer->hasArg("m")) { + return false; + } + + #ifdef USE_SCRIPT_WEB_DISPLAY + Script_Check_HTML_Setvars(); + #endif + + char tmp[8]; + char svalue[32]; + + WebGetArg("o", tmp, sizeof(tmp)); + if (strlen(tmp)) { + ShowWebSource(SRC_WEBGUI); + uint32_t device = atoi(tmp); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + if (device < 2) { + ExecuteCommandPower(1, POWER_TOGGLE, SRC_IGNORE); + } else { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), device -2); + ExecuteCommand(svalue, SRC_WEBGUI); + } + } else { +#endif + ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); +#ifdef USE_SONOFF_IFAN + } +#endif + } + WebGetArg("d", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + WebGetArg("t", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + WebGetArg("k", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + + WSContentBegin(200, CT_HTML); + WSContentSend_P(PSTR("{t}")); + XsnsCall(FUNC_WEB_SENSOR); +#ifdef USE_SCRIPT_WEB_DISPLAY + XdrvCall(FUNC_WEB_SENSOR); +#endif + + WSContentSend_P(PSTR("")); + + if (devices_present) { + WSContentSend_P(PSTR("{t}")); + uint32_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32; +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + WSContentSend_P(HTTP_DEVICE_STATE, 36, (bitRead(power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(power, 0))); + uint32_t fanspeed = GetFanspeed(); + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fanspeed); + WSContentSend_P(HTTP_DEVICE_STATE, 64, (fanspeed) ? "bold" : "normal", 54, (fanspeed) ? svalue : GetStateText(0)); + } else { +#endif + for (uint32_t idx = 1; idx <= devices_present; idx++) { + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1)); + WSContentSend_P(HTTP_DEVICE_STATE, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue); + } +#ifdef USE_SONOFF_IFAN + } +#endif + WSContentSend_P(PSTR("")); + } + WSContentEnd(); + + return true; +} + + + +#ifndef FIRMWARE_MINIMAL + +void HandleConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURATION); + + WSContentStart_P(S_CONFIGURATION); + WSContentSendStyle(); + + WSContentButton(BUTTON_MODULE); + WSContentButton(BUTTON_WIFI); + + XdrvCall(FUNC_WEB_ADD_BUTTON); + XsnsCall(FUNC_WEB_ADD_BUTTON); + + WSContentButton(BUTTON_LOGGING); + WSContentButton(BUTTON_OTHER); + WSContentButton(BUTTON_TEMPLATE); + + WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); + WSContentButton(BUTTON_BACKUP); + WSContentButton(BUTTON_RESTORE); + + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); +} + + + +void HandleTemplateConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("save")) { + TemplateSaveSettings(); + WebRestart(1); + return; + } + + char stemp[30]; + + if (WebServer->hasArg("m")) { + WSContentBegin(200, CT_PLAIN); + for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { + uint32_t midx = pgm_read_byte(kModuleNiceList + i); + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1); + } + WSContentEnd(); + return; + } + + WebGetArg("t", stemp, sizeof(stemp)); + if (strlen(stemp)) { + uint32_t module = atoi(stemp); + uint32_t module_save = Settings.module; + Settings.module = module; + myio cmodule; + ModuleGpios(&cmodule); + gpio_flag flag = ModuleFlag(); + Settings.module = module_save; + + WSContentBegin(200, CT_PLAIN); + WSContentSend_P(PSTR("%s}1"), AnyModuleName(module).c_str()); + for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { + if (1 == i) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, 255, D_SENSOR_USER, 255); + } + uint32_t midx = pgm_read_byte(kGpioNiceList + i); + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); + } + WSContentSend_P(PSTR("}1")); + + for (uint32_t i = 0; i < ADC0_END; i++) { + if (1 == i) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, ADC0_USER, D_SENSOR_USER, ADC0_USER); + } + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, i, GetTextIndexed(stemp, sizeof(stemp), i, kAdc0Names), i); + } + WSContentSend_P(PSTR("}1")); + + for (uint32_t i = 0; i < sizeof(cmodule); i++) { + if ((i < 6) || ((i > 8) && (i != 11))) { + WSContentSend_P(PSTR("%s%d"), (i>0)?",":"", cmodule.io[i]); + } + } + WSContentSend_P(PSTR("}1%d}1%d"), flag, Settings.user_template_base); + WSContentEnd(); + return; + } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TEMPLATE); + + WSContentStart_P(S_CONFIGURE_TEMPLATE); + WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); + WSContentSend_P(HTTP_SCRIPT_TEMPLATE); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_TEMPLATE); + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("" D_TEMPLATE_NAME "" + "" D_BASE_TYPE "" + "" + "
")); + WSContentSend_P(HTTP_TABLE100); + for (uint32_t i = 0; i < 17; i++) { + if ((i < 6) || ((i > 8) && (i != 11))) { + WSContentSend_P(PSTR("" D_GPIO "%d"), + ((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:200px'" : "", i); + } + } + WSContentSend_P(PSTR("" D_ADC "0"), WebColor(COL_TEXT)); + WSContentSend_P(PSTR("")); + gpio_flag flag = ModuleFlag(); + if (flag.data > ADC0_USER) { + WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); + } + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void TemplateSaveSettings(void) +{ + char tmp[sizeof(Settings.user_template.name)]; + char webindex[5]; + char svalue[128]; + + WebGetArg("s1", tmp, sizeof(tmp)); + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp); + + uint32_t j = 0; + for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { + if (6 == i) { j = 9; } + if (8 == i) { j = 12; } + snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), j); + WebGetArg(webindex, tmp, sizeof(tmp)); + uint8_t gpio = atoi(tmp); + snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", gpio); + j++; + } + + WebGetArg("g17", tmp, sizeof(tmp)); + uint32_t flag = atoi(tmp); + for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) { + snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i); + uint32_t state = WebServer->hasArg(webindex) << i +4; + flag += state; + } + WebGetArg("g99", tmp, sizeof(tmp)); + uint32_t base = atoi(tmp) +1; + + snprintf_P(svalue, sizeof(svalue), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), svalue, flag, base); + ExecuteWebCommand(svalue, SRC_WEBGUI); +} + + + +void HandleModuleConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("save")) { + ModuleSaveSettings(); + WebRestart(1); + return; + } + + char stemp[30]; + uint32_t midx; + myio cmodule; + ModuleGpios(&cmodule); + + if (WebServer->hasArg("m")) { + WSContentBegin(200, CT_PLAIN); + uint32_t vidx = 0; + for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { + if (0 == i) { + midx = USER_MODULE; + vidx = 0; + } else { + midx = pgm_read_byte(kModuleNiceList + i -1); + vidx = midx +1; + } + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), vidx); + } + WSContentEnd(); + return; + } + + if (WebServer->hasArg("g")) { + WSContentBegin(200, CT_PLAIN); + for (uint32_t j = 0; j < sizeof(kGpioNiceList); j++) { + midx = pgm_read_byte(kGpioNiceList + j); + if (!GetUsedInModule(midx, cmodule.io)) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); + } + } + WSContentEnd(); + return; + } + +#ifndef USE_ADC_VCC + if (WebServer->hasArg("a")) { + WSContentBegin(200, CT_PLAIN); + for (uint32_t j = 0; j < ADC0_END; j++) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, j, GetTextIndexed(stemp, sizeof(stemp), j, kAdc0Names), j); + } + WSContentEnd(); + return; + } +#endif + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); + + WSContentStart_P(S_CONFIGURE_MODULE); + WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); + WSContentSend_P(HTTP_SCRIPT_MODULE1, Settings.module); + for (uint32_t i = 0; i < sizeof(cmodule); i++) { + if (ValidGPIO(i, cmodule.io[i])) { + WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); + } + } + WSContentSend_P(HTTP_SCRIPT_MODULE2, Settings.my_adc0); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); + for (uint32_t i = 0; i < sizeof(cmodule); i++) { + if (ValidGPIO(i, cmodule.io[i])) { + snprintf_P(stemp, 3, PINS_WEMOS +i*2); + char sesp8285[40]; + snprintf_P(sesp8285, sizeof(sesp8285), PSTR("ESP8285"), WebColor(COL_TEXT_WARNING)); + WSContentSend_P(PSTR("%s " D_GPIO "%d %s"), + (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? sesp8285 :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i); + } + } +#ifndef USE_ADC_VCC + if (ValidAdc()) { + WSContentSend_P(PSTR("%s " D_ADC "0"), (WEMOS==my_module_type)?"A0":""); + } +#endif + WSContentSend_P(PSTR("")); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void ModuleSaveSettings(void) +{ + char tmp[8]; + char webindex[5]; + + WebGetArg("g99", tmp, sizeof(tmp)); + uint32_t new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); + Settings.last_module = Settings.module; + Settings.module = new_module; + SetModuleType(); + myio cmodule; + ModuleGpios(&cmodule); + String gpios = ""; + for (uint32_t i = 0; i < sizeof(cmodule); i++) { + if (Settings.last_module != new_module) { + Settings.my_gp.io[i] = GPIO_NONE; + } else { + if (ValidGPIO(i, cmodule.io[i])) { + snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i); + WebGetArg(webindex, tmp, sizeof(tmp)); + Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); + gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); + } + } + } +#ifndef USE_ADC_VCC + WebGetArg("g17", tmp, sizeof(tmp)); + Settings.my_adc0 = (!strlen(tmp)) ? 0 : atoi(tmp); + gpios += F(", " D_ADC "0 "); gpios += String(Settings.my_adc0); +#endif + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), ModuleName().c_str(), gpios.c_str()); +} + + + +const char kUnescapeCode[] = "&><\"\'"; +const char kEscapeCode[] PROGMEM = "&|>|<|"|'"; + +String HtmlEscape(const String unescaped) { + char escaped[10]; + size_t ulen = unescaped.length(); + String result = ""; + for (size_t i = 0; i < ulen; i++) { + char c = unescaped[i]; + char *p = strchr(kUnescapeCode, c); + if (p != nullptr) { + result += GetTextIndexed(escaped, sizeof(escaped), p - kUnescapeCode, kEscapeCode); + } else { + result += c; + } + } + return result; +} + + +const char kEncryptionType[] PROGMEM = "|||" D_WPA_PSK "||" D_WPA2_PSK "|" D_WEP "||" D_NONE "|" D_AUTO; + +void HandleWifiConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); + + if (WebServer->hasArg("save") && HTTP_MANAGER_RESET_ONLY != Web.state) { + WifiSaveSettings(); + WebRestart(2); + return; + } + + WSContentStart_P(S_CONFIGURE_WIFI, !WifiIsInManagerMode()); + WSContentSend_P(HTTP_SCRIPT_WIFI); + WSContentSendStyle(); + + if (HTTP_MANAGER_RESET_ONLY != Web.state) { + if (WebServer->hasArg("scan")) { +#ifdef USE_EMULATION + UdpDisconnect(); +#endif + int n = WiFi.scanNetworks(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SCAN_DONE)); + + if (0 == n) { + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, S_NO_NETWORKS_FOUND); + WSContentSend_P(S_NO_NETWORKS_FOUND); + WSContentSend_P(PSTR(". " D_REFRESH_TO_SCAN_AGAIN ".")); + } else { + + int indices[n]; + for (uint32_t i = 0; i < n; i++) { + indices[i] = i; + } + + + for (uint32_t i = 0; i < n; i++) { + for (uint32_t j = i + 1; j < n; j++) { + if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) { + std::swap(indices[i], indices[j]); + } + } + } + + + String cssid; + for (uint32_t i = 0; i < n; i++) { + if (-1 == indices[i]) { continue; } + cssid = WiFi.SSID(indices[i]); + for (uint32_t j = i + 1; j < n; j++) { + if (cssid == WiFi.SSID(indices[j])) { + DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_DUPLICATE_ACCESSPOINT " %s"), WiFi.SSID(indices[j]).c_str()); + indices[j] = -1; + } + } + } + + + for (uint32_t i = 0; i < n; i++) { + if (-1 == indices[i]) { continue; } + DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), + WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i])); + int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); + int auth = WiFi.encryptionType(indices[i]); + char encryption[20]; + WSContentSend_P(PSTR("
%s (%d) %s %d%%
"), + HtmlEscape(WiFi.SSID(indices[i])).c_str(), + WiFi.channel(indices[i]), + GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), + quality + ); + delay(0); + + } + WSContentSend_P(PSTR("
")); + } + } else { + WSContentSend_P(PSTR("
")); + } + + + WSContentSend_P(HTTP_FORM_WIFI, Settings.sta_ssid[0], Settings.sta_ssid[1], WIFI_HOSTNAME, WIFI_HOSTNAME, Settings.hostname); + WSContentSend_P(HTTP_FORM_END); + } + + if (WifiIsInManagerMode()) { + WSContentSpaceButton(BUTTON_RESTART); +#ifndef FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); +#endif + } else { + WSContentSpaceButton(BUTTON_CONFIGURATION); + } + WSContentStop(); +} + +void WifiSaveSettings(void) +{ + char tmp[sizeof(Settings.sta_pwd[0])]; + + WebGetArg("h", tmp, sizeof(tmp)); + strlcpy(Settings.hostname, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp, sizeof(Settings.hostname)); + if (strstr(Settings.hostname, "%") != nullptr) { + strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); + } + WebGetArg("s1", tmp, sizeof(tmp)); + strlcpy(Settings.sta_ssid[0], (!strlen(tmp)) ? STA_SSID1 : tmp, sizeof(Settings.sta_ssid[0])); + WebGetArg("s2", tmp, sizeof(tmp)); + strlcpy(Settings.sta_ssid[1], (!strlen(tmp)) ? STA_SSID2 : tmp, sizeof(Settings.sta_ssid[1])); + WebGetArg("p1", tmp, sizeof(tmp)); + strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); + WebGetArg("p2", tmp, sizeof(tmp)); + strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s"), Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1]); +} + + + +void HandleLoggingConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_LOGGING); + + if (WebServer->hasArg("save")) { + LoggingSaveSettings(); + HandleConfiguration(); + return; + } + + WSContentStart_P(S_CONFIGURE_LOGGING); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_LOG1); + char stemp1[45]; + char stemp2[32]; + uint8_t dlevel[3] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE }; + for (uint32_t idx = 0; idx < 3; idx++) { + uint32_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:Settings.syslog_level; + WSContentSend_P(PSTR("

%s (%s)

")); + } + WSContentSend_P(HTTP_FORM_LOG2, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void LoggingSaveSettings(void) +{ + char tmp[sizeof(Settings.syslog_host)]; + + WebGetArg("l0", tmp, sizeof(tmp)); + SetSeriallog((!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp)); + WebGetArg("l1", tmp, sizeof(tmp)); + Settings.weblog_level = (!strlen(tmp)) ? WEB_LOG_LEVEL : atoi(tmp); + WebGetArg("l2", tmp, sizeof(tmp)); + SetSyslog((!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp)); + WebGetArg("lh", tmp, sizeof(tmp)); + strlcpy(Settings.syslog_host, (!strlen(tmp)) ? SYS_LOG_HOST : tmp, sizeof(Settings.syslog_host)); + WebGetArg("lp", tmp, sizeof(tmp)); + Settings.syslog_port = (!strlen(tmp)) ? SYS_LOG_PORT : atoi(tmp); + WebGetArg("lt", tmp, sizeof(tmp)); + Settings.tele_period = (!strlen(tmp)) ? TELE_PERIOD : atoi(tmp); + if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) { + Settings.tele_period = 10; + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_LOG D_CMND_SERIALLOG " %d, " D_CMND_WEBLOG " %d, " D_CMND_SYSLOG " %d, " D_CMND_LOGHOST " %s, " D_CMND_LOGPORT " %d, " D_CMND_TELEPERIOD " %d"), + Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); +} + + + +void HandleOtherConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_OTHER); + + if (WebServer->hasArg("save")) { + OtherSaveSettings(); + WebRestart(1); + return; + } + + WSContentStart_P(S_CONFIGURE_OTHER); + WSContentSendStyle(); + + TemplateJson(); + char stemp[strlen(mqtt_data) +1]; + strlcpy(stemp, mqtt_data, sizeof(stemp)); + WSContentSend_P(HTTP_FORM_OTHER, stemp, (USER_MODULE == Settings.module) ? " checked disabled" : "", (Settings.flag.mqtt_enabled) ? " checked" : ""); + + uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { maxfn = 1; } +#endif + for (uint32_t i = 0; i < maxfn; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i +1); + WSContentSend_P(PSTR("" D_FRIENDLY_NAME " %d (" FRIENDLY_NAME "%s)

"), + i +1, + (i) ? stemp : "", + i, + (i) ? stemp : "", + Settings.friendlyname[i]); + } + +#ifdef USE_EMULATION + WSContentSend_P(PSTR("

 " D_EMULATION " 

")); + for (uint32_t i = 0; i < EMUL_MAX; i++) { +#ifndef USE_EMULATION_WEMO + if (i == EMUL_WEMO) { i++; } +#endif +#ifndef USE_EMULATION_HUE + if (i == EMUL_HUE) { i++; } +#endif + if (i < EMUL_MAX) { + WSContentSend_P(PSTR("%s %s
"), + i, i, + (i == Settings.flag2.emulation) ? " checked" : "", + GetTextIndexed(stemp, sizeof(stemp), i, kEmulationOptions), + (i == EMUL_NONE) ? "" : (i == EMUL_WEMO) ? D_SINGLE_DEVICE : D_MULTI_DEVICE); + } + } + WSContentSend_P(PSTR("

")); +#endif + + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void OtherSaveSettings(void) +{ + char tmp[128]; + char webindex[5]; + char friendlyname[sizeof(Settings.friendlyname[0])]; + + WebGetArg("wp", tmp, sizeof(tmp)); + strlcpy(Settings.web_password, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.web_password : tmp, sizeof(Settings.web_password)); + Settings.flag.mqtt_enabled = WebServer->hasArg("b1"); +#ifdef USE_EMULATION + WebGetArg("b2", tmp, sizeof(tmp)); + Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); +#endif + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); + for (uint32_t i = 0; i < MAX_FRIENDLYNAMES; i++) { + snprintf_P(webindex, sizeof(webindex), PSTR("a%d"), i); + WebGetArg(webindex, tmp, sizeof(tmp)); + snprintf_P(friendlyname, sizeof(friendlyname), PSTR(FRIENDLY_NAME"%d"), i +1); + strlcpy(Settings.friendlyname[i], (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp, sizeof(Settings.friendlyname[i])); + snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", Settings.friendlyname[i]); + } + AddLog(LOG_LEVEL_INFO); + WebGetArg("t1", tmp, sizeof(tmp)); + if (strlen(tmp)) { + char svalue[128]; + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + + if (WebServer->hasArg("t2")) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_MODULE " 0")); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + + } +} + + + +void HandleBackupConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_BACKUP_CONFIGURATION)); + + if (!SettingsBufferAlloc()) { return; } + + WiFiClient myClient = WebServer->client(); + WebServer->setContentLength(sizeof(Settings)); + + char attachment[100]; + + + + + char hostname[sizeof(my_hostname)]; + snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(hostname, my_hostname), my_version); + + WebServer->sendHeader(F("Content-Disposition"), attachment); + + WSSend(200, CT_STREAM, ""); + + uint32_t cfg_crc32 = Settings.cfg_crc32; + Settings.cfg_crc32 = GetSettingsCrc32(); + + memcpy(settings_buffer, &Settings, sizeof(Settings)); + if (Web.config_xor_on_set) { + for (uint32_t i = 2; i < sizeof(Settings); i++) { + settings_buffer[i] ^= (Web.config_xor_on_set +i); + } + } + +#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 + size_t written = myClient.write((const char*)settings_buffer, sizeof(Settings)); + if (written < sizeof(Settings)) { + myClient.write((const char*)settings_buffer +written, sizeof(Settings) -written); + } +#else + myClient.write((const char*)settings_buffer, sizeof(Settings)); +#endif + + SettingsBufferFree(); + + Settings.cfg_crc32 = cfg_crc32; +} + + + +void HandleResetConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESET_CONFIGURATION); + + WSContentStart_P(S_RESET_CONFIGURATION, !WifiIsInManagerMode()); + WSContentSendStyle(); + WSContentSend_P(PSTR("
" D_CONFIGURATION_RESET "
")); + WSContentSend_P(HTTP_MSG_RSTRT); + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); + + char command[CMDSZ]; + snprintf_P(command, sizeof(command), PSTR(D_CMND_RESET " 1")); + ExecuteWebCommand(command, SRC_WEBGUI); +} + +void HandleRestoreConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTORE_CONFIGURATION); + + WSContentStart_P(S_RESTORE_CONFIGURATION); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_RST); + WSContentSend_P(HTTP_FORM_RST_UPG, D_RESTORE); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); + + Web.upload_error = 0; + Web.upload_file_type = UPL_SETTINGS; +} + + + +void HandleInformation(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_INFORMATION); + + char stopic[TOPSZ]; + + int freeMem = ESP.getFreeHeap(); + + WSContentStart_P(S_INFORMATION); + + + + WSContentSend_P(HTTP_SCRIPT_INFO_BEGIN); + WSContentSend_P(PSTR("
")); + WSContentSend_P(PSTR(D_PROGRAM_VERSION "}2%s%s"), my_version, my_image); + WSContentSend_P(PSTR("}1" D_BUILD_DATE_AND_TIME "}2%s"), GetBuildDateAndTime().c_str()); + WSContentSend_P(PSTR("}1" D_CORE_AND_SDK_VERSION "}2" ARDUINO_ESP8266_RELEASE "/%s"), ESP.getSdkVersion()); + WSContentSend_P(PSTR("}1" D_UPTIME "}2%s"), GetUptime().c_str()); + WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d at 0x%X"), Settings.save_flag, GetSettingsAddress()); + WSContentSend_P(PSTR("}1" D_BOOT_COUNT "}2%d"), Settings.bootcount); + WSContentSend_P(PSTR("}1" D_RESTART_REASON "}2%s"), GetResetReason().c_str()); + uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present; +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { maxfn = 1; } +#endif + for (uint32_t i = 0; i < maxfn; i++) { + WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, Settings.friendlyname[i]); + } + WSContentSend_P(PSTR("}1}2 ")); + WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%)"), Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI())); + WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Wifi.mdns_begun) ? ".local" : ""); + if (static_cast(WiFi.localIP()) != 0) { + WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.localIP().toString().c_str()); + WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), IPAddress(Settings.ip_address[1]).toString().c_str()); + WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%s"), IPAddress(Settings.ip_address[2]).toString().c_str()); + WSContentSend_P(PSTR("}1" D_DNS_SERVER "}2%s"), IPAddress(Settings.ip_address[3]).toString().c_str()); + WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.macAddress().c_str()); + } + if (static_cast(WiFi.softAPIP()) != 0) { + WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.softAPIP().toString().c_str()); + WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), WiFi.softAPIP().toString().c_str()); + WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.softAPmacAddress().c_str()); + } + WSContentSend_P(PSTR("}1}2 ")); + if (Settings.flag.mqtt_enabled) { +#ifdef USE_MQTT_AWS_IOT + WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s%s"), Settings.mqtt_user, Settings.mqtt_host); + WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port); +#else + WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), Settings.mqtt_host); + WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port); + WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), Settings.mqtt_user); +#endif + WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client); + WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), Settings.mqtt_topic); + WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), Settings.mqtt_grptopic); + WSContentSend_P(PSTR("}1" D_MQTT_FULL_TOPIC "}2%s"), GetTopic_P(stopic, CMND, mqtt_topic, "")); + WSContentSend_P(PSTR("}1" D_MQTT " " D_FALLBACK_TOPIC "}2%s"), GetFallbackTopic_P(stopic, CMND, "")); + } else { + WSContentSend_P(PSTR("}1" D_MQTT "}2" D_DISABLED)); + } + WSContentSend_P(PSTR("}1}2 ")); + +#ifdef USE_EMULATION + WSContentSend_P(PSTR("}1" D_EMULATION "}2%s"), GetTextIndexed(stopic, sizeof(stopic), Settings.flag2.emulation, kEmulationOptions)); +#else + WSContentSend_P(PSTR("}1" D_EMULATION "}2" D_DISABLED)); +#endif + +#ifdef USE_DISCOVERY + WSContentSend_P(PSTR("}1" D_MDNS_DISCOVERY "}2%s"), (Settings.flag3.mdns_enabled) ? D_ENABLED : D_DISABLED); + if (Settings.flag3.mdns_enabled) { +#ifdef WEBSERVER_ADVERTISE + WSContentSend_P(PSTR("}1" D_MDNS_ADVERTISE "}2" D_WEB_SERVER)); +#else + WSContentSend_P(PSTR("}1" D_MDNS_ADVERTISE "}2" D_DISABLED)); +#endif + } +#else + WSContentSend_P(PSTR("}1" D_MDNS_DISCOVERY "}2" D_DISABLED)); +#endif + + WSContentSend_P(PSTR("}1}2 ")); + WSContentSend_P(PSTR("}1" D_ESP_CHIP_ID "}2%d"), ESP.getChipId()); + WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X"), ESP.getFlashChipId()); + WSContentSend_P(PSTR("}1" D_FLASH_CHIP_SIZE "}2%dkB"), ESP.getFlashChipRealSize() / 1024); + WSContentSend_P(PSTR("}1" D_PROGRAM_FLASH_SIZE "}2%dkB"), ESP.getFlashChipSize() / 1024); + WSContentSend_P(PSTR("}1" D_PROGRAM_SIZE "}2%dkB"), ESP.getSketchSize() / 1024); + WSContentSend_P(PSTR("}1" D_FREE_PROGRAM_SPACE "}2%dkB"), ESP.getFreeSketchSpace() / 1024); + WSContentSend_P(PSTR("}1" D_FREE_MEMORY "}2%dkB"), freeMem / 1024); + WSContentSend_P(PSTR("
")); + + WSContentSend_P(HTTP_SCRIPT_INFO_END); + WSContentSendStyle(); + + WSContentSend_P(PSTR("" + "
")); + + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); +} +#endif + + + +void HandleUpgradeFirmware(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_FIRMWARE_UPGRADE); + + WSContentStart_P(S_FIRMWARE_UPGRADE); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_UPG, Settings.ota_url); + WSContentSend_P(HTTP_FORM_RST_UPG, D_UPGRADE); + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); + + Web.upload_error = 0; + Web.upload_file_type = UPL_TASMOTA; +} + +void HandleUpgradeFirmwareStart(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + char command[sizeof(Settings.ota_url) + 10]; + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPGRADE_STARTED)); + WifiConfigCounter(); + + char otaurl[sizeof(Settings.ota_url)]; + WebGetArg("o", otaurl, sizeof(otaurl)); + if (strlen(otaurl)) { + snprintf_P(command, sizeof(command), PSTR(D_CMND_OTAURL " %s"), otaurl); + ExecuteWebCommand(command, SRC_WEBGUI); + } + + WSContentStart_P(S_INFORMATION); + WSContentSend_P(HTTP_SCRIPT_RELOAD_OTA); + WSContentSendStyle(); + WSContentSend_P(PSTR("
" D_UPGRADE_STARTED " ...
")); + WSContentSend_P(HTTP_MSG_RSTRT); + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); + + snprintf_P(command, sizeof(command), PSTR(D_CMND_UPGRADE " 1")); + ExecuteWebCommand(command, SRC_WEBGUI); +} + +void HandleUploadDone(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPLOAD_DONE)); + + char error[100]; + + WifiConfigCounter(); + restart_flag = 0; + MqttRetryCounter(0); + + WSContentStart_P(S_INFORMATION); + if (!Web.upload_error) { + WSContentSend_P(HTTP_SCRIPT_RELOAD_OTA); + } + WSContentSendStyle(); + WSContentSend_P(PSTR("
" D_UPLOAD " " D_FAILED "

"), WebColor(COL_TEXT_WARNING)); +#ifdef USE_RF_FLASH + if (Web.upload_error < 14) { +#else + if (Web.upload_error < 10) { +#endif + GetTextIndexed(error, sizeof(error), Web.upload_error -1, kUploadErrors); + } else { + snprintf_P(error, sizeof(error), PSTR(D_UPLOAD_ERROR_CODE " %d"), Web.upload_error); + } + WSContentSend_P(error); + DEBUG_CORE_LOG(PSTR("UPL: %s"), error); + stop_flash_rotate = Settings.flag.stop_flash_rotate; + } else { + WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "
"), WebColor(COL_TEXT_SUCCESS)); + WSContentSend_P(HTTP_MSG_RSTRT); + ShowWebSource(SRC_WEBGUI); + restart_flag = 2; + } + SettingsBufferFree(); + WSContentSend_P(PSTR("

")); + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); +} + +void HandleUploadLoop(void) +{ + + bool _serialoutput = (LOG_LEVEL_DEBUG <= seriallog_level); + + if (HTTP_USER == Web.state) { return; } + if (Web.upload_error) { + if (UPL_TASMOTA == Web.upload_file_type) { Update.end(); } + return; + } + + HTTPUpload& upload = WebServer->upload(); + + if (UPLOAD_FILE_START == upload.status) { + restart_flag = 60; + if (0 == upload.filename.c_str()[0]) { + Web.upload_error = 1; + return; + } + SettingsSave(1); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_FILE " %s ..."), upload.filename.c_str()); + if (UPL_SETTINGS == Web.upload_file_type) { + if (!SettingsBufferAlloc()) { + Web.upload_error = 2; + return; + } + } else { + MqttRetryCounter(60); +#ifdef USE_EMULATION + UdpDisconnect(); +#endif +#ifdef USE_ARILUX_RF + AriluxRfDisable(); +#endif + if (Settings.flag.mqtt_enabled) MqttDisconnect(); + uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; + if (!Update.begin(maxSketchSpace)) { + + + + + + + Web.upload_error = 2; + return; + } + } + Web.upload_progress_dot_count = 0; + } else if (!Web.upload_error && (UPLOAD_FILE_WRITE == upload.status)) { + if (0 == upload.totalSize) { + if (UPL_SETTINGS == Web.upload_file_type) { + Web.config_block_count = 0; + } + else { +#ifdef USE_RF_FLASH + if ((SONOFF_BRIDGE == my_module_type) && (upload.buf[0] == ':')) { + Update.end(); + Web.upload_file_type = UPL_EFM8BB1; + + Web.upload_error = SnfBrUpdateInit(); + if (Web.upload_error != 0) { return; } + } else +#endif + { + if (upload.buf[0] != 0xE9) { + Web.upload_error = 3; + return; + } + uint32_t bin_flash_size = ESP.magicFlashChipSize((upload.buf[3] & 0xf0) >> 4); + if(bin_flash_size > ESP.getFlashChipRealSize()) { + Web.upload_error = 4; + return; + } + + } + } + } + if (UPL_SETTINGS == Web.upload_file_type) { + if (!Web.upload_error) { + if (upload.currentSize > (sizeof(Settings) - (Web.config_block_count * HTTP_UPLOAD_BUFLEN))) { + Web.upload_error = 9; + return; + } + memcpy(settings_buffer + (Web.config_block_count * HTTP_UPLOAD_BUFLEN), upload.buf, upload.currentSize); + Web.config_block_count++; + } + } +#ifdef USE_RF_FLASH + else if (UPL_EFM8BB1 == Web.upload_file_type) { + if (efm8bb1_update != nullptr) { + ssize_t result = rf_glue_remnant_with_new_data_and_write(efm8bb1_update, upload.buf, upload.currentSize); + free(efm8bb1_update); + efm8bb1_update = nullptr; + if (result != 0) { + Web.upload_error = abs(result); + return; + } + } + ssize_t result = rf_search_and_write(upload.buf, upload.currentSize); + if (result < 0) { + Web.upload_error = abs(result); + return; + } else if (result > 0) { + if ((size_t)result > upload.currentSize) { + + Web.upload_error = 9; + return; + } + + size_t remnant_sz = upload.currentSize - result; + efm8bb1_update = (uint8_t *) malloc(remnant_sz + 1); + if (efm8bb1_update == nullptr) { + Web.upload_error = 2; + return; + } + memcpy(efm8bb1_update, upload.buf + result, remnant_sz); + + efm8bb1_update[remnant_sz] = '\0'; + } + } +#endif + else { + if (!Web.upload_error && (Update.write(upload.buf, upload.currentSize) != upload.currentSize)) { + Web.upload_error = 5; + return; + } + if (_serialoutput) { + Serial.printf("."); + Web.upload_progress_dot_count++; + if (!(Web.upload_progress_dot_count % 80)) { Serial.println(); } + } + } + } else if(!Web.upload_error && (UPLOAD_FILE_END == upload.status)) { + if (_serialoutput && (Web.upload_progress_dot_count % 80)) { + Serial.println(); + } + if (UPL_SETTINGS == Web.upload_file_type) { + if (Web.config_xor_on_set) { + for (uint32_t i = 2; i < sizeof(Settings); i++) { + settings_buffer[i] ^= (Web.config_xor_on_set +i); + } + } + bool valid_settings = false; + unsigned long buffer_version = settings_buffer[11] << 24 | settings_buffer[10] << 16 | settings_buffer[9] << 8 | settings_buffer[8]; + if (buffer_version > 0x06000000) { + uint32_t buffer_size = settings_buffer[3] << 8 | settings_buffer[2]; + if (buffer_version > 0x0606000A) { + uint32_t buffer_crc32 = settings_buffer[4095] << 24 | settings_buffer[4094] << 16 | settings_buffer[4093] << 8 | settings_buffer[4092]; + valid_settings = (GetCfgCrc32(settings_buffer, buffer_size -4) == buffer_crc32); + } else { + uint16_t buffer_crc16 = settings_buffer[15] << 8 | settings_buffer[14]; + valid_settings = (GetCfgCrc16(settings_buffer, buffer_size) == buffer_crc16); + } + } else { + valid_settings = (settings_buffer[0] == CONFIG_FILE_SIGN); + } + if (valid_settings) { + SettingsDefaultSet2(); + memcpy((char*)&Settings +16, settings_buffer +16, sizeof(Settings) -16); + Settings.version = buffer_version; + SettingsBufferFree(); + } else { + Web.upload_error = 8; + return; + } + } +#ifdef USE_RF_FLASH + else if (UPL_EFM8BB1 == Web.upload_file_type) { + + Web.upload_file_type = UPL_TASMOTA; + } +#endif + else { + if (!Update.end(true)) { + if (_serialoutput) { Update.printError(Serial); } + Web.upload_error = 6; + return; + } + } + if (!Web.upload_error) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_SUCCESSFUL " %u bytes. " D_RESTARTING), upload.totalSize); + } + } else if (UPLOAD_FILE_ABORTED == upload.status) { + restart_flag = 0; + MqttRetryCounter(0); + Web.upload_error = 7; + if (UPL_TASMOTA == Web.upload_file_type) { Update.end(); } + } + delay(0); +} + + + +void HandlePreflightRequest(void) +{ + WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); + WebServer->sendHeader(F("Access-Control-Allow-Methods"), F("GET, POST")); + WebServer->sendHeader(F("Access-Control-Allow-Headers"), F("authorization")); + WSSend(200, CT_HTML, ""); +} + + + +void HandleHttpCommand(void) +{ + if (!HttpCheckPriviledgedAccess(false)) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_COMMAND)); + + bool valid = true; + if (Settings.web_password[0] != 0) { + char tmp1[sizeof(Settings.web_password)]; + WebGetArg("user", tmp1, sizeof(tmp1)); + char tmp2[sizeof(Settings.web_password)]; + WebGetArg("password", tmp2, sizeof(tmp2)); + if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, Settings.web_password))) { valid = false; } + } + + WSContentBegin(200, CT_JSON); + if (valid) { + uint32_t curridx = web_log_index; + String svalue = WebServer->arg("cmnd"); + if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { + ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCOMMAND); + if (web_log_index != curridx) { + uint32_t counter = curridx; + WSContentSend_P(PSTR("{")); + bool cflg = false; + do { + char* tmp; + size_t len; + GetLog(counter, &tmp, &len); + if (len) { + + char* JSON = (char*)memchr(tmp, '{', len); + if (JSON) { + size_t JSONlen = len - (JSON - tmp); + if (JSONlen > sizeof(mqtt_data)) { JSONlen = sizeof(mqtt_data); } + char stemp[JSONlen]; + strlcpy(stemp, JSON +1, JSONlen -2); + WSContentSend_P(PSTR("%s%s"), (cflg) ? "," : "", stemp); + cflg = true; + } + } + counter++; + counter &= 0xFF; + if (!counter) counter++; + } while (counter != web_log_index); + WSContentSend_P(PSTR("}")); + } else { + WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}")); + } + } else { + WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENTER_COMMAND " cmnd=\"}")); + } + } else { + WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_NEED_USER_AND_PASSWORD "\"}")); + } + WSContentEnd(); +} + + + +void HandleConsole(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("c2")) { + HandleConsoleRefresh(); + return; + } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONSOLE); + + WSContentStart_P(S_CONSOLE); + WSContentSend_P(HTTP_SCRIPT_CONSOL, Settings.web_refresh); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_CMND); + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); +} + +void HandleConsoleRefresh(void) +{ + bool cflg = true; + uint32_t counter = 0; + + String svalue = WebServer->arg("c1"); + if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), svalue.c_str()); + ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE); + } + + char stmp[8]; + WebGetArg("c2", stmp, sizeof(stmp)); + if (strlen(stmp)) { counter = atoi(stmp); } + + WSContentBegin(200, CT_PLAIN); + WSContentSend_P(PSTR("%d}1%d}1"), web_log_index, Web.reset_web_log_flag); + if (!Web.reset_web_log_flag) { + counter = 0; + Web.reset_web_log_flag = true; + } + if (counter != web_log_index) { + if (!counter) { + counter = web_log_index; + cflg = false; + } + do { + char* tmp; + size_t len; + GetLog(counter, &tmp, &len); + if (len) { + if (len > sizeof(mqtt_data) -2) { len = sizeof(mqtt_data); } + char stemp[len +1]; + strlcpy(stemp, tmp, len); + WSContentSend_P(PSTR("%s%s"), (cflg) ? "\n" : "", stemp); + cflg = true; + } + counter++; + counter &= 0xFF; + if (!counter) { counter++; } + } while (counter != web_log_index); + } + WSContentSend_P(PSTR("}1")); + WSContentEnd(); +} + + + +void HandleNotFound(void) +{ + + + if (CaptivePortal()) { return; } + +#ifdef USE_EMULATION +#ifdef USE_EMULATION_HUE + String path = WebServer->uri(); + if ((EMUL_HUE == Settings.flag2.emulation) && (path.startsWith("/api"))) { + HandleHueApi(&path); + } else +#endif +#endif + { + WSContentBegin(404, CT_PLAIN); + WSContentSend_P(PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args()); + for (uint32_t i = 0; i < WebServer->args(); i++) { + WSContentSend_P(PSTR(" %s: %s\n"), WebServer->argName(i).c_str(), WebServer->arg(i).c_str()); + } + WSContentEnd(); + } +} + + +bool CaptivePortal(void) +{ + + if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader().c_str())) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); + + WebServer->sendHeader(F("Location"), String("http://") + WebServer->client().localIP().toString(), true); + WSSend(302, CT_PLAIN, ""); + WebServer->client().stop(); + return true; + } + return false; +} + + + +String UrlEncode(const String& text) +{ + const char hex[] = "0123456789ABCDEF"; + + String encoded = ""; + int len = text.length(); + int i = 0; + while (i < len) { + char decodedChar = text.charAt(i++); +# 2374 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_01_webserver.ino" + if ((' ' == decodedChar) || ('+' == decodedChar)) { + encoded += '%'; + encoded += hex[decodedChar >> 4]; + encoded += hex[decodedChar & 0xF]; + } else { + encoded += decodedChar; + } + + } + return encoded; +} + +#ifdef USE_SENDMAIL + +#include "sendemail.h" + + + + + + + +#define SEND_MAIL_MINRAM 19*1024 + +uint16_t SendMail(char *buffer) { + uint16_t count; + char *params,*oparams; + char *mserv; + uint16_t port; + char *user; + char *pstr; + char *passwd; + char *from; + char *to; + char *subject; + char *cmd; + char secure=0,auth=0; + uint16_t status=1; + SendEmail *mail=0; + + + + + uint16_t mem=ESP.getFreeHeap(); + if (memsend(from,to,subject,cmd); + delete mail; + if (result==true) status=0; + } + + + if (oparams) free(oparams); + return status; +} + +#endif + +int WebSend(char *buffer) +{ + + + + + + char *host; + char *user; + char *password; + char *command; + int status = 1; + + + host = strtok_r(buffer, "]", &command); + if (host && command) { + RemoveSpace(host); + host++; + host = strtok_r(host, ",", &user); + String url = F("http://"); + url += host; + + command = Trim(command); + if (command[0] != '/') { + url += F("/cm?"); + if (user) { + user = strtok_r(user, ":", &password); + if (user && password) { + char userpass[128]; + snprintf_P(userpass, sizeof(userpass), PSTR("user=%s&password=%s&"), user, password); + url += userpass; + } + } + url += F("cmnd="); + } + url += command; + + DEBUG_CORE_LOG(PSTR("WEB: Uri |%s|"), url.c_str()); + +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) + HTTPClient http; + if (http.begin(UrlEncode(url))) { +#else + WiFiClient http_client; + HTTPClient http; + if (http.begin(http_client, UrlEncode(url))) { +#endif + int http_code = http.GET(); + if (http_code > 0) { + if (http_code == HTTP_CODE_OK || http_code == HTTP_CODE_MOVED_PERMANENTLY) { +#ifdef USE_WEBSEND_RESPONSE + + const char* read = http.getString().c_str(); + uint32_t j = 0; + char text = '.'; + while (text != '\0') { + text = *read++; + if (text > 31) { + mqtt_data[j++] = text; + if (j == sizeof(mqtt_data) -2) { break; } + } + } + mqtt_data[j] = '\0'; + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WEBSEND)); +#ifdef USE_SCRIPT +extern uint8_t tasm_cmd_activ; + + tasm_cmd_activ=0; + XdrvRulesProcess(); +#endif +#endif + } + status = 0; + } else { + status = 2; + } + http.end(); + } else { + status = 3; + } + } + return status; +} + +bool JsonWebColor(const char* dataBuf) +{ + + + + + + char dataBufLc[strlen(dataBuf) +1]; + LowerCase(dataBufLc, dataBuf); + RemoveSpace(dataBufLc); + if (strlen(dataBufLc) < 9) { return false; } + + StaticJsonBuffer<450> jb; + JsonObject& obj = jb.parseObject(dataBufLc); + if (!obj.success()) { return false; } + + char parm_lc[10]; + if (obj[LowerCase(parm_lc, D_CMND_WEBCOLOR)].success()) { + for (uint32_t i = 0; i < COL_LAST; i++) { + const char* color = obj[parm_lc][i]; + if (color != nullptr) { + WebHexCode(i, color); + } + } + } + return true; +} + +const char kWebSendStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND "|" D_JSON_MEMORY_ERROR; + +const char kWebCommands[] PROGMEM = "|" +#ifdef USE_EMULATION + D_CMND_EMULATION "|" +#endif +#ifdef USE_SENDMAIL + D_CMND_SENDMAIL "|" +#endif + D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" D_CMND_WEBSENSOR; + +void (* const WebCommand[])(void) PROGMEM = { +#ifdef USE_EMULATION + &CmndEmulation, +#endif +#ifdef USE_SENDMAIL + &CmndSendmail, +#endif + &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, &CmndWebSensor }; + + + + + +#ifdef USE_EMULATION +void CmndEmulation(void) +{ +#if defined(USE_EMULATION_WEMO) && defined(USE_EMULATION_HUE) + if ((XdrvMailbox.payload >= EMUL_NONE) && (XdrvMailbox.payload < EMUL_MAX)) { +#else +#ifndef USE_EMULATION_WEMO + if ((EMUL_NONE == XdrvMailbox.payload) || (EMUL_HUE == XdrvMailbox.payload)) { +#endif +#ifndef USE_EMULATION_HUE + if ((EMUL_NONE == XdrvMailbox.payload) || (EMUL_WEMO == XdrvMailbox.payload)) { +#endif +#endif + Settings.flag2.emulation = XdrvMailbox.payload; + restart_flag = 2; + } + ResponseCmndNumber(Settings.flag2.emulation); +} +#endif + +#ifdef USE_SENDMAIL +void CmndSendmail(void) +{ + if (XdrvMailbox.data_len > 0) { + uint8_t result = SendMail(XdrvMailbox.data); + char stemp1[20]; + ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus)); + } +} +#endif + + +void CmndWebServer(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + Settings.webserver = XdrvMailbox.payload; + } + if (Settings.webserver) { + Response_P(PSTR("{\"" D_CMND_WEBSERVER "\":\"" D_JSON_ACTIVE_FOR " %s " D_JSON_ON_DEVICE " %s " D_JSON_WITH_IP_ADDRESS " %s\"}"), + (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); + } else { + ResponseCmndStateText(0); + } +} + +void CmndWebPassword(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.web_password))) { + strlcpy(Settings.web_password, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data, sizeof(Settings.web_password)); + ResponseCmndChar(Settings.web_password); + } else { + Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); + } +} + +void CmndWeblog(void) +{ + if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { + Settings.weblog_level = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.weblog_level); +} + +void CmndWebRefresh(void) +{ + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload <= 10000)) { + Settings.web_refresh = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.web_refresh); +} + +void CmndWebSend(void) +{ + if (XdrvMailbox.data_len > 0) { + uint32_t result = WebSend(XdrvMailbox.data); + char stemp1[20]; + ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus)); + } +} + +void CmndWebColor(void) +{ + if (XdrvMailbox.data_len > 0) { + if (strstr(XdrvMailbox.data, "{") == nullptr) { + if ((XdrvMailbox.data_len > 3) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= COL_LAST)) { + WebHexCode(XdrvMailbox.index -1, XdrvMailbox.data); + } + else if (0 == XdrvMailbox.payload) { + SettingsDefaultWebColor(); + } + } + else { + JsonWebColor(XdrvMailbox.data); + } + } + Response_P(PSTR("{\"" D_CMND_WEBCOLOR "\":[")); + for (uint32_t i = 0; i < COL_LAST; i++) { + if (i) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"#%06x\""), WebColor(i)); + } + ResponseAppend_P(PSTR("]}")); +} + +void CmndWebSensor(void) +{ + if (XdrvMailbox.index < MAX_XSNS_DRIVERS) { + if (XdrvMailbox.payload >= 0) { + bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); + } + } + Response_P(PSTR("{\"" D_CMND_WEBSENSOR "\":")); + XsnsSensorState(); + ResponseJsonEnd(); +} + + + + + +bool Xdrv01(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_LOOP: + PollDnsWebserver(); +#ifdef USE_EMULATION + if (Settings.flag2.emulation) { PollUdp(); } +#endif + break; + case FUNC_COMMAND: + result = DecodeCommand(kWebCommands, WebCommand); + break; + } + return result; +} +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_02_mqtt.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_02_mqtt.ino" +#define XDRV_02 2 + + + +#ifdef USE_MQTT_TLS + #include "WiFiClientSecureLightBearSSL.h" + BearSSL::WiFiClientSecure_light *tlsClient; +#else + WiFiClient EspClient; +#endif + +const char kMqttCommands[] PROGMEM = "|" +#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) + D_CMND_MQTTFINGERPRINT "|" +#endif +#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) + D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" +#endif +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + D_CMND_TLSKEY "|" +#endif + D_CMND_MQTTHOST "|" D_CMND_MQTTPORT "|" D_CMND_MQTTRETRY "|" D_CMND_STATETEXT "|" D_CMND_MQTTCLIENT "|" + D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|" + D_CMND_BUTTONTOPIC "|" D_CMND_SWITCHTOPIC "|" D_CMND_BUTTONRETAIN "|" D_CMND_SWITCHRETAIN "|" D_CMND_POWERRETAIN "|" D_CMND_SENSORRETAIN ; + +void (* const MqttCommand[])(void) PROGMEM = { +#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) + &CmndMqttFingerprint, +#endif +#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) + &CmndMqttUser, &CmndMqttPassword, +#endif +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + &CmndTlsKey, +#endif + &CmndMqttHost, &CmndMqttPort, &CmndMqttRetry, &CmndStateText, &CmndMqttClient, + &CmndFullTopic, &CmndPrefix, &CmndGroupTopic, &CmndTopic, &CmndPublish, + &CmndButtonTopic, &CmndSwitchTopic, &CmndButtonRetain, &CmndSwitchRetain, &CmndPowerRetain, &CmndSensorRetain }; + +struct MQTT { + uint16_t connect_count = 0; + uint16_t retry_counter = 1; + uint8_t initial_connection_state = 2; + bool connected = false; + bool allowed = false; +} Mqtt; + +#ifdef USE_MQTT_TLS + +#ifdef USE_MQTT_AWS_IOT +#include + +const br_ec_private_key *AWS_IoT_Private_Key = nullptr; +const br_x509_certificate *AWS_IoT_Client_Certificate = nullptr; + +class tls_entry_t { +public: + uint32_t name; + uint16_t start; + uint16_t len; +}; + +const static uint32_t TLS_NAME_SKEY = 0x2079656B; +const static uint32_t TLS_NAME_CRT = 0x20747263; + +class tls_dir_t { +public: + tls_entry_t entry[4]; +}; + +tls_dir_t tls_dir; + +#endif + + + +char AWS_endpoint[65]; + + + + +bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value) { + for (uint32_t i = 0; i<20; i++) { + if (finger[i] != value) { + return false; + } + } + return true; +} + +#ifdef USE_MQTT_AWS_IOT +void setLongMqttHost(const char *mqtt_host) { + if (strlen(mqtt_host) <= sizeof(Settings.mqtt_host)) { + strlcpy(Settings.mqtt_host, mqtt_host, sizeof(Settings.mqtt_host)); + Settings.mqtt_user[0] = 0; + } else { + + strlcpy(Settings.mqtt_user, mqtt_host, sizeof(Settings.mqtt_user)); + strlcpy(Settings.mqtt_host, &mqtt_host[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host)); + } + strlcpy(AWS_endpoint, mqtt_host, sizeof(AWS_endpoint)); +} +#endif + +#endif + +void MakeValidMqtt(uint32_t option, char* str) +{ + + + uint32_t i = 0; + while (str[i] > 0) { + + if ((str[i] == '+') || (str[i] == '#') || (str[i] == ' ')) { + if (option) { + uint32_t j = i; + while (str[j] > 0) { + str[j] = str[j +1]; + j++; + } + i--; + } else { + str[i] = '_'; + } + } + i++; + } +} + +#ifdef USE_DISCOVERY +#ifdef MQTT_HOST_DISCOVERY +void MqttDiscoverServer(void) +{ + if (!Wifi.mdns_begun) { return; } + + int n = MDNS.queryService("mqtt", "tcp"); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_QUERY_DONE " %d"), n); + + if (n > 0) { + uint32_t i = 0; +#ifdef MDNS_HOSTNAME + for (i = n; i > 0; i--) { + if (!strcmp(MDNS.hostname(i).c_str(), MDNS_HOSTNAME)) { + break; + } + } +#endif + snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(i).toString().c_str()); + Settings.mqtt_port = MDNS.port(i); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), MDNS.hostname(i).c_str(), Settings.mqtt_host, Settings.mqtt_port); + } +} +#endif +#endif +# 186 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_02_mqtt.ino" +#include + + +#if (MQTT_MAX_PACKET_SIZE -TOPSZ -7) < MIN_MESSZ + #error "MQTT_MAX_PACKET_SIZE is too small in libraries/PubSubClient/src/PubSubClient.h, increase it to at least 1000" +#endif + +#ifdef USE_MQTT_TLS +PubSubClient MqttClient; +#else +PubSubClient MqttClient(EspClient); +#endif + +void MqttInit(void) +{ +#ifdef USE_MQTT_TLS + tlsClient = new BearSSL::WiFiClientSecure_light(1024,1024); + +#ifdef USE_MQTT_AWS_IOT + snprintf_P(AWS_endpoint, sizeof(AWS_endpoint), PSTR("%s%s"), Settings.mqtt_user, Settings.mqtt_host); + + loadTlsDir(); + tlsClient->setClientECCert(AWS_IoT_Client_Certificate, + AWS_IoT_Private_Key, + 0xFFFF , 0); +#endif + +#ifdef USE_MQTT_TLS_CA_CERT +#ifdef USE_MQTT_AWS_IOT + tlsClient->setTrustAnchor(&AmazonRootCA1_TA); +#else + tlsClient->setTrustAnchor(&LetsEncryptX3CrossSigned_TA); +#endif +#endif + + MqttClient.setClient(*tlsClient); +#endif +} + +bool MqttIsConnected(void) +{ + return MqttClient.connected(); +} + +void MqttDisconnect(void) +{ + MqttClient.disconnect(); +} + +void MqttSubscribeLib(const char *topic) +{ + MqttClient.subscribe(topic); + MqttClient.loop(); +} + +void MqttUnsubscribeLib(const char *topic) +{ + MqttClient.unsubscribe(topic); + MqttClient.loop(); +} + +bool MqttPublishLib(const char* topic, bool retained) +{ + bool result = MqttClient.publish(topic, mqtt_data, retained); + yield(); + return result; +} + +void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) +{ +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("MqttDataHandler")); +#endif + + + if (data_len >= MQTT_MAX_PACKET_SIZE) { return; } + + + if (!strcmp(Settings.mqtt_prefix[0], Settings.mqtt_prefix[1])) { + char *str = strstr(topic, Settings.mqtt_prefix[0]); + if ((str == topic) && mqtt_cmnd_publish) { + if (mqtt_cmnd_publish > 3) { + mqtt_cmnd_publish -= 3; + } else { + mqtt_cmnd_publish = 0; + } + return; + } + } + + data[data_len] = 0; + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_RECEIVED_TOPIC " %s, " D_DATA_SIZE " %d, " D_DATA " %s"), topic, data_len, data); + + + + if (XdrvMqttData(topic, strlen(topic), (char*)data, data_len)) { return; } + + ShowSource(SRC_MQTT); + + CommandHandler(topic, data, data_len); +} + + + +void MqttRetryCounter(uint8_t value) +{ + Mqtt.retry_counter = value; +} + +void MqttSubscribe(const char *topic) +{ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT D_SUBSCRIBE_TO " %s"), topic); + MqttSubscribeLib(topic); +} + +void MqttUnsubscribe(const char *topic) +{ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT D_UNSUBSCRIBE_FROM " %s"), topic); + MqttUnsubscribeLib(topic); +} + +void MqttPublishDirect(const char* topic, bool retained) +{ + char sretained[CMDSZ]; + char slog_type[10]; + +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("MqttPublishDirect")); +#endif + + sretained[0] = '\0'; + snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_RESULT)); + + if (Settings.flag.mqtt_enabled) { + if (MqttIsConnected()) { + if (MqttPublishLib(topic, retained)) { + snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_MQTT)); + if (retained) { + snprintf_P(sretained, sizeof(sretained), PSTR(" (" D_RETAINED ")")); + } + } + } + } + + snprintf_P(log_data, sizeof(log_data), PSTR("%s%s = %s"), slog_type, (Settings.flag.mqtt_enabled) ? topic : strrchr(topic,'/')+1, mqtt_data); + if (strlen(log_data) >= (sizeof(log_data) - strlen(sretained) -1)) { + log_data[sizeof(log_data) - strlen(sretained) -5] = '\0'; + snprintf_P(log_data, sizeof(log_data), PSTR("%s ..."), log_data); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s%s"), log_data, sretained); + AddLog(LOG_LEVEL_INFO); + + if (Settings.ledstate &0x04) { + blinks++; + } +} + +void MqttPublish(const char* topic, bool retained) +{ + char *me; +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + if (retained) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR("Retained are not supported by AWS IoT, using retained = false.")); + } + retained = false; +#endif + + if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1])) { + me = strstr(topic,Settings.mqtt_prefix[0]); + if (me == topic) { + mqtt_cmnd_publish += 3; + } + } + MqttPublishDirect(topic, retained); +} + +void MqttPublish(const char* topic) +{ + MqttPublish(topic, false); +} + +void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained) +{ + + + + + + + + char romram[33]; + char stopic[TOPSZ]; + + snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings.flag.mqtt_response) ? S_RSLT_RESULT : subtopic); + for (uint32_t i = 0; i < strlen(romram); i++) { + romram[i] = toupper(romram[i]); + } + prefix &= 3; + GetTopic_P(stopic, prefix, mqtt_topic, romram); + MqttPublish(stopic, retained); +} + +void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic) +{ + MqttPublishPrefixTopic_P(prefix, subtopic, false); +} + +void MqttPublishPowerState(uint32_t device) +{ + char stopic[TOPSZ]; + char scommand[33]; + + if ((device < 1) || (device > devices_present)) { device = 1; } + +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (device > 1)) { + if (GetFanspeed() < MaxFanspeed()) { +#ifdef USE_DOMOTICZ + DomoticzUpdateFanState(); +#endif + snprintf_P(scommand, sizeof(scommand), PSTR(D_CMND_FANSPEED)); + GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); + Response_P(S_JSON_COMMAND_NVALUE, scommand, GetFanspeed()); + MqttPublish(stopic); + } + } else { +#endif + GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable); + GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); + Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(power, device -1))); + MqttPublish(stopic); + + GetTopic_P(stopic, STAT, mqtt_topic, scommand); + Response_P(GetStateText(bitRead(power, device -1))); + MqttPublish(stopic, Settings.flag.mqtt_power_retain); +#ifdef USE_SONOFF_IFAN + } +#endif +} + +void MqttPublishAllPowerState() +{ + for (uint32_t i = 1; i <= devices_present; i++) { + MqttPublishPowerState(i); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { break; } +#endif + } +} + +void MqttPublishPowerBlinkState(uint32_t device) +{ + char scommand[33]; + + if ((device < 1) || (device > devices_present)) { + device = 1; + } + Response_P(PSTR("{\"%s\":\"" D_JSON_BLINK " %s\"}"), + GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable), GetStateText(bitRead(blink_mask, device -1))); + + MqttPublishPrefixTopic_P(RESULT_OR_STAT, S_RSLT_POWER); +} + + + +uint16_t MqttConnectCount() +{ + return Mqtt.connect_count; +} + +void MqttDisconnected(int state) +{ + Mqtt.connected = false; + Mqtt.retry_counter = Settings.mqtt_retry; + + MqttClient.disconnect(); + +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), AWS_endpoint, Settings.mqtt_port, state, Mqtt.retry_counter); +#else + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), Settings.mqtt_host, Settings.mqtt_port, state, Mqtt.retry_counter); +#endif + rules_flag.mqtt_disconnected = 1; +} + +void MqttConnected(void) +{ + char stopic[TOPSZ]; + + if (Mqtt.allowed) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_CONNECTED)); + Mqtt.connected = true; + Mqtt.retry_counter = 0; + Mqtt.connect_count++; + + GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); + Response_P(PSTR(D_ONLINE)); + MqttPublish(stopic, true); + + + mqtt_data[0] = '\0'; + MqttPublishPrefixTopic_P(CMND, S_RSLT_POWER); + + GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); + MqttSubscribe(stopic); + if (strstr_P(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != nullptr) { + GetTopic_P(stopic, CMND, Settings.mqtt_grptopic, PSTR("#")); + MqttSubscribe(stopic); + GetFallbackTopic_P(stopic, CMND, PSTR("#")); + MqttSubscribe(stopic); + } + + XdrvCall(FUNC_MQTT_SUBSCRIBE); + } + + if (Mqtt.initial_connection_state) { + Response_P(PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), + ModuleName().c_str(), my_version, my_image, GetFallbackTopic_P(stopic, CMND, ""), Settings.mqtt_grptopic); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); +#ifdef USE_WEBSERVER + if (Settings.webserver) { + Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"), + (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); + } +#endif + Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), (GetResetReason() == "Exception") ? ESP.getResetInfo().c_str() : GetResetReason().c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); + MqttPublishAllPowerState(); + if (Settings.tele_period) { tele_period = Settings.tele_period -9; } + rules_flag.system_boot = 1; + XdrvCall(FUNC_MQTT_INIT); + } + Mqtt.initial_connection_state = 0; + + global_state.mqtt_down = 0; + if (Settings.flag.mqtt_enabled) { + rules_flag.mqtt_connected = 1; + } +} + +void MqttReconnect(void) +{ + char stopic[TOPSZ]; + + Mqtt.allowed = Settings.flag.mqtt_enabled; + if (Mqtt.allowed) { +#ifdef USE_DISCOVERY +#ifdef MQTT_HOST_DISCOVERY + MqttDiscoverServer(); +#endif +#endif + if (!strlen(Settings.mqtt_host) || !Settings.mqtt_port) { + Mqtt.allowed = false; + } +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + + if (!AWS_IoT_Private_Key || !AWS_IoT_Client_Certificate) { + Mqtt.allowed = false; + } +#endif + } + if (!Mqtt.allowed) { + MqttConnected(); + return; + } + +#ifdef USE_EMULATION + UdpDisconnect(); +#endif + + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); + + Mqtt.connected = false; + Mqtt.retry_counter = Settings.mqtt_retry; + global_state.mqtt_down = 1; + + char *mqtt_user = nullptr; + char *mqtt_pwd = nullptr; + if (strlen(Settings.mqtt_user) > 0) mqtt_user = Settings.mqtt_user; + if (strlen(Settings.mqtt_pwd) > 0) mqtt_pwd = Settings.mqtt_pwd; + + GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); + Response_P(S_OFFLINE); + + if (MqttClient.connected()) { MqttClient.disconnect(); } +#ifdef USE_MQTT_TLS + tlsClient->stop(); +#else + EspClient = WiFiClient(); + MqttClient.setClient(EspClient); +#endif + + if (2 == Mqtt.initial_connection_state) { + Mqtt.initial_connection_state = 1; + } + + MqttClient.setCallback(MqttDataHandler); +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + + tlsClient->setClientECCert(AWS_IoT_Client_Certificate, + AWS_IoT_Private_Key, + 0xFFFF , 0); + MqttClient.setServer(AWS_endpoint, Settings.mqtt_port); +#else + MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); +#endif + + uint32_t mqtt_connect_time = millis(); +#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) + bool allow_all_fingerprints = false; + bool learn_fingerprint1 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[0], 0x00); + bool learn_fingerprint2 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[1], 0x00); + allow_all_fingerprints |= is_fingerprint_mono_value(Settings.mqtt_fingerprint[0], 0xff); + allow_all_fingerprints |= is_fingerprint_mono_value(Settings.mqtt_fingerprint[1], 0xff); + allow_all_fingerprints |= learn_fingerprint1; + allow_all_fingerprints |= learn_fingerprint2; + tlsClient->setPubKeyFingerprint(Settings.mqtt_fingerprint[0], Settings.mqtt_fingerprint[1], allow_all_fingerprints); +#endif +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "AWS IoT endpoint: %s"), AWS_endpoint); + + if (MqttClient.connect(mqtt_client, nullptr, nullptr, stopic, 1, false, mqtt_data, MQTT_CLEAN_SESSION)) { +#else + if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data, MQTT_CLEAN_SESSION)) { +#endif +#ifdef USE_MQTT_TLS + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connected in %d ms, max ThunkStack used %d"), + millis() - mqtt_connect_time, tlsClient->getMaxThunkStackUse()); + if (!tlsClient->getMFLNStatus()) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR("MFLN not supported by TLS server")); + } +#ifndef USE_MQTT_TLS_CA_CERT + + char buf_fingerprint[64]; + ToHex_P((unsigned char *)tlsClient->getRecvPubKeyFingerprint(), 20, buf_fingerprint, sizeof(buf_fingerprint), ' '); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Server fingerprint: %s"), buf_fingerprint); + + if (learn_fingerprint1 || learn_fingerprint2) { + + bool fingerprint_matched = false; + const uint8_t *recv_fingerprint = tlsClient->getRecvPubKeyFingerprint(); + if (0 == memcmp(recv_fingerprint, Settings.mqtt_fingerprint[0], 20)) { + fingerprint_matched = true; + } + if (0 == memcmp(recv_fingerprint, Settings.mqtt_fingerprint[1], 20)) { + fingerprint_matched = true; + } + if (!fingerprint_matched) { + + if (learn_fingerprint1) { + memcpy(Settings.mqtt_fingerprint[0], recv_fingerprint, 20); + } + if (learn_fingerprint2) { + memcpy(Settings.mqtt_fingerprint[1], recv_fingerprint, 20); + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "Fingerprint learned: %s"), buf_fingerprint); + + SettingsSaveAll(); + } + } +#endif +#endif + MqttConnected(); + } else { +#ifdef USE_MQTT_TLS + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connection error: %d"), tlsClient->getLastError()); +#endif + MqttDisconnected(MqttClient.state()); + } +} + +void MqttCheck(void) +{ + if (Settings.flag.mqtt_enabled) { + if (!MqttIsConnected()) { + global_state.mqtt_down = 1; + if (!Mqtt.retry_counter) { +#ifdef USE_DISCOVERY +#ifdef MQTT_HOST_DISCOVERY + if (!strlen(Settings.mqtt_host) && !Wifi.mdns_begun) { return; } +#endif +#endif + MqttReconnect(); + } else { + Mqtt.retry_counter--; + } + } else { + global_state.mqtt_down = 0; + } + } else { + global_state.mqtt_down = 0; + if (Mqtt.initial_connection_state) MqttReconnect(); + } +} + + + + + +#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) +void CmndMqttFingerprint(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { + char fingerprint[60]; + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(fingerprint))) { + strlcpy(fingerprint, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? MQTT_FINGERPRINT1 : MQTT_FINGERPRINT2 : XdrvMailbox.data, sizeof(fingerprint)); + char *p = fingerprint; + for (uint32_t i = 0; i < 20; i++) { + Settings.mqtt_fingerprint[XdrvMailbox.index -1][i] = strtol(p, &p, 16); + } + restart_flag = 2; + } + ResponseCmndIdxChar(ToHex_P((unsigned char *)Settings.mqtt_fingerprint[XdrvMailbox.index -1], 20, fingerprint, sizeof(fingerprint), ' ')); + } +} +#endif + +#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) +void CmndMqttUser(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_user))) { + strlcpy(Settings.mqtt_user, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_USER : XdrvMailbox.data, sizeof(Settings.mqtt_user)); + restart_flag = 2; + } + ResponseCmndChar(Settings.mqtt_user); +} + +void CmndMqttPassword(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_pwd))) { + strlcpy(Settings.mqtt_pwd, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_PASS : XdrvMailbox.data, sizeof(Settings.mqtt_pwd)); + ResponseCmndChar(Settings.mqtt_pwd); + restart_flag = 2; + } else { + Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); + } +} +#endif + +void CmndMqttHost(void) +{ +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len <= sizeof(Settings.mqtt_host) + sizeof(Settings.mqtt_user) - 2)) { + setLongMqttHost((SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data); + restart_flag = 2; + } + ResponseCmndChar(AWS_endpoint); +#else + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_host))) { + strlcpy(Settings.mqtt_host, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data, sizeof(Settings.mqtt_host)); + restart_flag = 2; + } + ResponseCmndChar(Settings.mqtt_host); +#endif +} + +void CmndMqttPort(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 65536)) { + Settings.mqtt_port = (1 == XdrvMailbox.payload) ? MQTT_PORT : XdrvMailbox.payload; + restart_flag = 2; + } + ResponseCmndNumber(Settings.mqtt_port); +} + +void CmndMqttRetry(void) +{ + if ((XdrvMailbox.payload >= MQTT_RETRY_SECS) && (XdrvMailbox.payload < 32001)) { + Settings.mqtt_retry = XdrvMailbox.payload; + Mqtt.retry_counter = Settings.mqtt_retry; + } + ResponseCmndNumber(Settings.mqtt_retry); +} + +void CmndStateText(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.state_text[0]))) { + for (uint32_t i = 0; i <= XdrvMailbox.data_len; i++) { + if (XdrvMailbox.data[i] == ' ') XdrvMailbox.data[i] = '_'; + } + strlcpy(Settings.state_text[XdrvMailbox.index -1], XdrvMailbox.data, sizeof(Settings.state_text[0])); + } + ResponseCmndIdxChar(GetStateText(XdrvMailbox.index -1)); + } +} + +void CmndMqttClient(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_client))) { + strlcpy(Settings.mqtt_client, (SC_DEFAULT == Shortcut()) ? MQTT_CLIENT_ID : XdrvMailbox.data, sizeof(Settings.mqtt_client)); + restart_flag = 2; + } + ResponseCmndChar(Settings.mqtt_client); +} + +void CmndFullTopic(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_fulltopic))) { + MakeValidMqtt(1, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + char stemp1[TOPSZ]; + strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_FULLTOPIC : XdrvMailbox.data, sizeof(stemp1)); + if (strcmp(stemp1, Settings.mqtt_fulltopic)) { + Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); + strlcpy(Settings.mqtt_fulltopic, stemp1, sizeof(Settings.mqtt_fulltopic)); + restart_flag = 2; + } + } + ResponseCmndChar(Settings.mqtt_fulltopic); +} + +void CmndPrefix(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_prefix[0]))) { + MakeValidMqtt(0, XdrvMailbox.data); + strlcpy(Settings.mqtt_prefix[XdrvMailbox.index -1], (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index)?SUB_PREFIX:(2==XdrvMailbox.index)?PUB_PREFIX:PUB_PREFIX2 : XdrvMailbox.data, sizeof(Settings.mqtt_prefix[0])); + + restart_flag = 2; + } + ResponseCmndIdxChar(Settings.mqtt_prefix[XdrvMailbox.index -1]); + } +} + +void CmndPublish(void) +{ + if (XdrvMailbox.data_len > 0) { + char *mqtt_part = strtok(XdrvMailbox.data, " "); + if (mqtt_part) { + char stemp1[TOPSZ]; + strlcpy(stemp1, mqtt_part, sizeof(stemp1)); + mqtt_part = strtok(nullptr, " "); + if (mqtt_part) { + strlcpy(mqtt_data, mqtt_part, sizeof(mqtt_data)); + } else { + mqtt_data[0] = '\0'; + } + MqttPublishDirect(stemp1, (XdrvMailbox.index == 2)); + + mqtt_data[0] = '\0'; + } + } +} + +void CmndGroupTopic(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_grptopic))) { + MakeValidMqtt(0, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + strlcpy(Settings.mqtt_grptopic, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data, sizeof(Settings.mqtt_grptopic)); + restart_flag = 2; + } + ResponseCmndChar(Settings.mqtt_grptopic); +} + +void CmndTopic(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_topic))) { + MakeValidMqtt(0, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + char stemp1[TOPSZ]; + strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_TOPIC : XdrvMailbox.data, sizeof(stemp1)); + if (strcmp(stemp1, Settings.mqtt_topic)) { + Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); + strlcpy(Settings.mqtt_topic, stemp1, sizeof(Settings.mqtt_topic)); + restart_flag = 2; + } + } + ResponseCmndChar(Settings.mqtt_topic); +} + +void CmndButtonTopic(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.button_topic))) { + MakeValidMqtt(0, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + switch (Shortcut()) { + case SC_CLEAR: strlcpy(Settings.button_topic, "", sizeof(Settings.button_topic)); break; + case SC_DEFAULT: strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic)); break; + case SC_USER: strlcpy(Settings.button_topic, MQTT_BUTTON_TOPIC, sizeof(Settings.button_topic)); break; + default: strlcpy(Settings.button_topic, XdrvMailbox.data, sizeof(Settings.button_topic)); + } + } + ResponseCmndChar(Settings.button_topic); +} + +void CmndSwitchTopic(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.switch_topic))) { + MakeValidMqtt(0, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + switch (Shortcut()) { + case SC_CLEAR: strlcpy(Settings.switch_topic, "", sizeof(Settings.switch_topic)); break; + case SC_DEFAULT: strlcpy(Settings.switch_topic, mqtt_topic, sizeof(Settings.switch_topic)); break; + case SC_USER: strlcpy(Settings.switch_topic, MQTT_SWITCH_TOPIC, sizeof(Settings.switch_topic)); break; + default: strlcpy(Settings.switch_topic, XdrvMailbox.data, sizeof(Settings.switch_topic)); + } + } + ResponseCmndChar(Settings.switch_topic); +} + +void CmndButtonRetain(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + if (!XdrvMailbox.payload) { + for (uint32_t i = 1; i <= MAX_KEYS; i++) { + SendKey(KEY_BUTTON, i, CLEAR_RETAIN); + } + } + Settings.flag.mqtt_button_retain = XdrvMailbox.payload; + } + ResponseCmndStateText(Settings.flag.mqtt_button_retain); +} + +void CmndSwitchRetain(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + if (!XdrvMailbox.payload) { + for (uint32_t i = 1; i <= MAX_SWITCHES; i++) { + SendKey(KEY_SWITCH, i, CLEAR_RETAIN); + } + } + Settings.flag.mqtt_switch_retain = XdrvMailbox.payload; + } + ResponseCmndStateText(Settings.flag.mqtt_switch_retain); +} + +void CmndPowerRetain(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + if (!XdrvMailbox.payload) { + char stemp1[TOPSZ]; + char scommand[CMDSZ]; + for (uint32_t i = 1; i <= devices_present; i++) { + GetTopic_P(stemp1, STAT, mqtt_topic, GetPowerDevice(scommand, i, sizeof(scommand), Settings.flag.device_index_enable)); + mqtt_data[0] = '\0'; + MqttPublish(stemp1, Settings.flag.mqtt_power_retain); + } + } + Settings.flag.mqtt_power_retain = XdrvMailbox.payload; + } + ResponseCmndStateText(Settings.flag.mqtt_power_retain); +} + +void CmndSensorRetain(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + if (!XdrvMailbox.payload) { + mqtt_data[0] = '\0'; + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_ENERGY), Settings.flag.mqtt_sensor_retain); + } + Settings.flag.mqtt_sensor_retain = XdrvMailbox.payload; + } + ResponseCmndStateText(Settings.flag.mqtt_sensor_retain); +} + + + + +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + +const static uint16_t tls_spi_start_sector = SPIFFS_END + 4; +const static uint8_t* tls_spi_start = (uint8_t*) ((tls_spi_start_sector * SPI_FLASH_SEC_SIZE) + 0x40200000); +const static size_t tls_spi_len = 0x1000; +const static size_t tls_block_offset = 0x0400; +const static size_t tls_block_len = 0x0400; +const static size_t tls_obj_store_offset = tls_block_offset + sizeof(tls_dir_t); + + +inline void TlsEraseBuffer(uint8_t *buffer) { + memset(buffer + tls_block_offset, 0xFF, tls_block_len); +} + + + +static br_ec_private_key EC = { + 23, + nullptr, 0 +}; + +static br_x509_certificate CHAIN[] = { + { nullptr, 0 } +}; + + + +void loadTlsDir(void) { + memcpy_P(&tls_dir, tls_spi_start + tls_block_offset, sizeof(tls_dir)); + + + if ((TLS_NAME_SKEY == tls_dir.entry[0].name) && (tls_dir.entry[0].len > 0)) { + EC.x = (unsigned char *)(tls_spi_start + tls_obj_store_offset + tls_dir.entry[0].start); + EC.xlen = tls_dir.entry[0].len; + AWS_IoT_Private_Key = &EC; + } else { + AWS_IoT_Private_Key = nullptr; + } + if ((TLS_NAME_CRT == tls_dir.entry[1].name) && (tls_dir.entry[1].len > 0)) { + CHAIN[0].data = (unsigned char *) (tls_spi_start + tls_obj_store_offset + tls_dir.entry[1].start); + CHAIN[0].data_len = tls_dir.entry[1].len; + AWS_IoT_Client_Certificate = CHAIN; + } else { + AWS_IoT_Client_Certificate = nullptr; + } + +} + +const char ALLOCATE_ERROR[] PROGMEM = "TLSKey " D_JSON_ERROR ": cannot allocate buffer."; + +void CmndTlsKey(void) { +#ifdef DEBUG_DUMP_TLS + if (0 == XdrvMailbox.index){ + CmndTlsDump(); + } +#endif + if ((XdrvMailbox.index >= 1) && (XdrvMailbox.index <= 2)) { + tls_dir_t *tls_dir_write; + + if (XdrvMailbox.data_len > 0) { + + uint8_t *spi_buffer = (uint8_t*) malloc(tls_spi_len); + if (!spi_buffer) { + AddLog_P(LOG_LEVEL_ERROR, ALLOCATE_ERROR); + return; + } + memcpy_P(spi_buffer, tls_spi_start, tls_spi_len); + + + uint32_t bin_len = decode_base64_length((unsigned char*)XdrvMailbox.data); + uint8_t *bin_buf = nullptr; + if (bin_len > 0) { + bin_buf = (uint8_t*) malloc(bin_len + 4); + if (!bin_buf) { + AddLog_P(LOG_LEVEL_ERROR, ALLOCATE_ERROR); + free(spi_buffer); + return; + } + } + + + if (bin_len > 0) { + decode_base64((unsigned char*)XdrvMailbox.data, bin_buf); + } + + + tls_dir_write = (tls_dir_t*) (spi_buffer + tls_block_offset); + + if (1 == XdrvMailbox.index) { + + + TlsEraseBuffer(spi_buffer); + if (bin_len > 0) { + if (bin_len != 32) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR("TLSKey: Certificate must be 32 bytes: %d."), bin_len); + free(spi_buffer); + free(bin_buf); + return; + } + tls_entry_t *entry = &tls_dir_write->entry[0]; + entry->name = TLS_NAME_SKEY; + entry->start = 0; + entry->len = bin_len; + memcpy(spi_buffer + tls_obj_store_offset + entry->start, bin_buf, entry->len); + } else { + + } + } else if (2 == XdrvMailbox.index) { + + if (TLS_NAME_SKEY != tls_dir.entry[0].name) { + + AddLog_P(LOG_LEVEL_INFO, PSTR("TLSKey: cannot store Cert if no Key previously stored.")); + free(spi_buffer); + free(bin_buf); + return; + } + if (bin_len <= 256) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR("TLSKey: Certificate length too short: %d."), bin_len); + free(spi_buffer); + free(bin_buf); + return; + } + tls_entry_t *entry = &tls_dir_write->entry[1]; + entry->name = TLS_NAME_CRT; + entry->start = (tls_dir_write->entry[0].start + tls_dir_write->entry[0].len + 3) & ~0x03; + entry->len = bin_len; + memcpy(spi_buffer + tls_obj_store_offset + entry->start, bin_buf, entry->len); + } + + TlsWriteSpiBuffer(spi_buffer); + free(spi_buffer); + free(bin_buf); + } + + loadTlsDir(); + Response_P(PSTR("{\"%s1\":%d,\"%s2\":%d}"), + XdrvMailbox.command, AWS_IoT_Private_Key ? tls_dir.entry[0].len : -1, + XdrvMailbox.command, AWS_IoT_Client_Certificate ? tls_dir.entry[1].len : -1); + } +} + + +extern "C" { +#include "spi_flash.h" +} + +void TlsWriteSpiBuffer(uint8_t *buf) { + bool ret = false; + SpiFlashOpResult res; + + noInterrupts(); + res = spi_flash_erase_sector(tls_spi_start_sector); + if (SPI_FLASH_RESULT_OK == res) { + res = spi_flash_write(tls_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) buf, SPI_FLASH_SEC_SIZE); + if (SPI_FLASH_RESULT_OK == res) { + ret = true; + } + } + interrupts(); +} + +#ifdef DEBUG_DUMP_TLS + +uint32_t bswap32(uint32_t x) { + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} +void CmndTlsDump(void) { + uint32_t start = (uint32_t)tls_spi_start + tls_block_offset; + uint32_t end = start + tls_block_len -1; + for (uint32_t pos = start; pos < end; pos += 0x10) { + uint32_t* values = (uint32_t*)(pos); + Serial.printf_P(PSTR("%08x: %08x %08x %08x %08x\n"), pos, bswap32(values[0]), bswap32(values[1]), bswap32(values[2]), bswap32(values[3])); + } +} +#endif +#endif + + + + + +#ifdef USE_WEBSERVER + +#define WEB_HANDLE_MQTT "mq" + +const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT; + +const char HTTP_BTN_MENU_MQTT[] PROGMEM = + "

"; + +const char HTTP_FORM_MQTT1[] PROGMEM = + "
 " D_MQTT_PARAMETERS " " + "
" + "

" D_HOST " (" MQTT_HOST ")

" + "

" D_PORT " (" STR(MQTT_PORT) ")

" + "

" D_CLIENT " (%s)

"; +const char HTTP_FORM_MQTT2[] PROGMEM = +#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) + "

" D_USER " (" MQTT_USER ")

" + "

" D_PASSWORD "

" +#endif + "

" D_TOPIC " = %%topic%% (%s)

" + "

" D_FULL_TOPIC " (%s)

"; + +void HandleMqttConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT); + + if (WebServer->hasArg("save")) { + MqttSaveSettings(); + WebRestart(1); + return; + } + + char str[sizeof(Settings.mqtt_client)]; + + WSContentStart_P(S_CONFIGURE_MQTT); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_MQTT1, +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + AWS_endpoint, +#else + Settings.mqtt_host, +#endif + Settings.mqtt_port, + Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, Settings.mqtt_client); + WSContentSend_P(HTTP_FORM_MQTT2, + (Settings.mqtt_user[0] == '\0') ? "0" : Settings.mqtt_user, + Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, Settings.mqtt_topic, + MQTT_FULLTOPIC, MQTT_FULLTOPIC, Settings.mqtt_fulltopic); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void MqttSaveSettings(void) +{ + char tmp[100]; + char stemp[TOPSZ]; + char stemp2[TOPSZ]; + + WebGetArg("mt", tmp, sizeof(tmp)); + strlcpy(stemp, (!strlen(tmp)) ? MQTT_TOPIC : tmp, sizeof(stemp)); + MakeValidMqtt(0, stemp); + WebGetArg("mf", tmp, sizeof(tmp)); + strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); + MakeValidMqtt(1, stemp2); + if ((strcmp(stemp, Settings.mqtt_topic)) || (strcmp(stemp2, Settings.mqtt_fulltopic))) { + Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + MqttPublishPrefixTopic_P(TELE, S_LWT, true); + } + strlcpy(Settings.mqtt_topic, stemp, sizeof(Settings.mqtt_topic)); + strlcpy(Settings.mqtt_fulltopic, stemp2, sizeof(Settings.mqtt_fulltopic)); + WebGetArg("mh", tmp, sizeof(tmp)); +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + setLongMqttHost((!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp); +#else + strlcpy(Settings.mqtt_host, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_host)); +#endif + WebGetArg("ml", tmp, sizeof(tmp)); + Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); + WebGetArg("mc", tmp, sizeof(tmp)); + strlcpy(Settings.mqtt_client, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp, sizeof(Settings.mqtt_client)); +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), + AWS_endpoint, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_topic, Settings.mqtt_fulltopic); +#else + WebGetArg("mu", tmp, sizeof(tmp)); + strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user)); + WebGetArg("mp", tmp, sizeof(tmp)); + strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? Settings.mqtt_pwd : tmp, sizeof(Settings.mqtt_pwd)); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), + Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_topic, Settings.mqtt_fulltopic); +#endif +} +#endif + + + + + +bool Xdrv02(uint8_t function) +{ + bool result = false; + + if (Settings.flag.mqtt_enabled) { + switch (function) { + case FUNC_PRE_INIT: + MqttInit(); + break; + case FUNC_EVERY_50_MSECOND: + MqttClient.loop(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_MQTT); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); + break; +#endif + case FUNC_COMMAND: + result = DecodeCommand(kMqttCommands, MqttCommand); + break; + } + } + return result; +} +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_03_energy.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_03_energy.ino" +#ifdef USE_ENERGY_SENSOR + + + + +#define XDRV_03 3 +#define XSNS_03 3 + + + + +#define ENERGY_NONE 0 +#define ENERGY_WATCHDOG 4 + +#include + +#define D_CMND_POWERCAL "PowerCal" +#define D_CMND_VOLTAGECAL "VoltageCal" +#define D_CMND_CURRENTCAL "CurrentCal" +#define D_CMND_TARIFF "Tariff" +#define D_CMND_MODULEADDRESS "ModuleAddress" + +enum EnergyCommands { + CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL, + CMND_POWERSET, CMND_VOLTAGESET, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_MODULEADDRESS }; + +const char kEnergyCommands[] PROGMEM = "|" + D_CMND_POWERCAL "|" D_CMND_VOLTAGECAL "|" D_CMND_CURRENTCAL "|" + D_CMND_POWERSET "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" D_CMND_MODULEADDRESS "|" +#ifdef USE_ENERGY_MARGIN_DETECTION + D_CMND_POWERDELTA "|" D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|" +#ifdef USE_ENERGY_POWER_LIMIT + D_CMND_MAXENERGY "|" D_CMND_MAXENERGYSTART "|" + D_CMND_MAXPOWER "|" D_CMND_MAXPOWERHOLD "|" D_CMND_MAXPOWERWINDOW "|" + D_CMND_SAFEPOWER "|" D_CMND_SAFEPOWERHOLD "|" D_CMND_SAFEPOWERWINDOW "|" +#endif +#endif + D_CMND_ENERGYRESET "|" D_CMND_TARIFF ; + +void (* const EnergyCommand[])(void) PROGMEM = { + &CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, + &CmndPowerSet, &CmndVoltageSet, &CmndCurrentSet, &CmndFrequencySet, &CmndModuleAddress, +#ifdef USE_ENERGY_MARGIN_DETECTION + &CmndPowerDelta, &CmndPowerLow, &CmndPowerHigh, &CmndVoltageLow, &CmndVoltageHigh, &CmndCurrentLow, &CmndCurrentHigh, +#ifdef USE_ENERGY_POWER_LIMIT + &CmndMaxEnergy, &CmndMaxEnergyStart, + &CmndMaxPower, &CmndMaxPowerHold, &CmndMaxPowerWindow, + &CmndSafePower, &CmndSafePowerHold, &CmndSafePowerWindow, +#endif +#endif + &CmndEnergyReset, &CmndTariff }; + +const char kEnergyPhases[] PROGMEM = "|%s / %s|%s / %s / %s||[%s,%s]|[%s,%s,%s]"; + +struct ENERGY { + float voltage[3] = { 0, 0, 0 }; + float current[3] = { 0, 0, 0 }; + float active_power[3] = { 0, 0, 0 }; + float apparent_power[3] = { NAN, NAN, NAN }; + float reactive_power[3] = { NAN, NAN, NAN }; + float power_factor[3] = { NAN, NAN, NAN }; + float frequency[3] = { NAN, NAN, NAN }; + + float start_energy = 0; + float daily = 0; + float total = 0; + float export_active = NAN; + + unsigned long kWhtoday_delta = 0; + unsigned long kWhtoday_offset = 0; + unsigned long kWhtoday; + unsigned long period = 0; + + uint8_t fifth_second = 0; + uint8_t command_code = 0; + uint8_t data_valid[3] = { 0, 0, 0 }; + + uint8_t phase_count = 1; + bool voltage_common = false; + + bool voltage_available = true; + bool current_available = true; + + bool type_dc = false; + bool power_on = true; + +#ifdef USE_ENERGY_MARGIN_DETECTION + float power_history[3] = { 0 }; + uint8_t power_steady_counter = 8; + uint8_t power_delta = 0; + bool min_power_flag = false; + bool max_power_flag = false; + bool min_voltage_flag = false; + bool max_voltage_flag = false; + bool min_current_flag = false; + bool max_current_flag = false; + +#ifdef USE_ENERGY_POWER_LIMIT + uint16_t mplh_counter = 0; + uint16_t mplw_counter = 0; + uint8_t mplr_counter = 0; + uint8_t max_energy_state = 0; +#endif +#endif +} Energy; + +Ticker ticker_energy; + + + +bool EnergyTariff1Active() +{ + uint8_t tariff1 = Settings.register8[R8_ENERGY_TARIFF1_ST]; + uint8_t tariff2 = Settings.register8[R8_ENERGY_TARIFF2_ST]; + if (IsDst() && (Settings.register8[R8_ENERGY_TARIFF1_DS] != Settings.register8[R8_ENERGY_TARIFF2_DS])) { + tariff1 = Settings.register8[R8_ENERGY_TARIFF1_DS]; + tariff2 = Settings.register8[R8_ENERGY_TARIFF2_DS]; + } + if (tariff1 != tariff2) { + return ((RtcTime.hour < tariff2) || + (RtcTime.hour >= tariff1) || + (Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) || + (RtcTime.day_of_week == 7))) + ); + } else { + return false; + } +} + +void EnergyUpdateToday(void) +{ + if (Energy.kWhtoday_delta > 1000) { + unsigned long delta = Energy.kWhtoday_delta / 1000; + Energy.kWhtoday_delta -= (delta * 1000); + Energy.kWhtoday += delta; + } + + RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset + Energy.kWhtoday; + Energy.daily = (float)(RtcSettings.energy_kWhtoday) / 100000; + Energy.total = (float)(RtcSettings.energy_kWhtotal + RtcSettings.energy_kWhtoday) / 100000; + + if (RtcTime.valid){ + + uint32_t energy_diff = (uint32_t)(Energy.total * 100000) - RtcSettings.energy_usage.last_usage_kWhtotal; + RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 100000); + + uint32_t return_diff = 0; + if (!isnan(Energy.export_active)) { + return_diff = (uint32_t)(Energy.export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal; + RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(Energy.export_active * 100000); + } + + if (EnergyTariff1Active()) { + RtcSettings.energy_usage.usage1_kWhtotal += energy_diff; + RtcSettings.energy_usage.return1_kWhtotal += return_diff; + } else { + RtcSettings.energy_usage.usage2_kWhtotal += energy_diff; + RtcSettings.energy_usage.return2_kWhtotal += return_diff; + } + } +} + +void EnergyUpdateTotal(float value, bool kwh) +{ + + + + + uint32_t multiplier = (kwh) ? 100000 : 100; + + if (0 == Energy.start_energy || (value < Energy.start_energy)) { + Energy.start_energy = value; + } + else if (value != Energy.start_energy) { + Energy.kWhtoday = (unsigned long)((value - Energy.start_energy) * multiplier); + } + + if (Energy.total < (value - 0.01)){ + RtcSettings.energy_kWhtotal = (unsigned long)((value * multiplier) - Energy.kWhtoday_offset - Energy.kWhtoday); + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; + Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: Energy Total updated with hardware value")); + } + EnergyUpdateToday(); +} + + + +void Energy200ms(void) +{ + Energy.power_on = (power != 0) | Settings.flag.no_power_on_check; + + Energy.fifth_second++; + if (5 == Energy.fifth_second) { + Energy.fifth_second = 0; + + XnrgCall(FUNC_ENERGY_EVERY_SECOND); + + if (RtcTime.valid) { + if (LocalTime() == Midnight()) { + Settings.energy_kWhyesterday = RtcSettings.energy_kWhtoday; + + RtcSettings.energy_kWhtotal += RtcSettings.energy_kWhtoday; + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + Energy.kWhtoday = 0; + Energy.kWhtoday_offset = 0; + RtcSettings.energy_kWhtoday = 0; + Energy.start_energy = 0; + + Energy.kWhtoday_delta = 0; + Energy.period = Energy.kWhtoday; + EnergyUpdateToday(); +#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT) + Energy.max_energy_state = 3; +#endif + } +#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT) + if ((RtcTime.hour == Settings.energy_max_energy_start) && (3 == Energy.max_energy_state )) { + Energy.max_energy_state = 0; + } +#endif + + } + } + + XnrgCall(FUNC_EVERY_200_MSECOND); +} + +void EnergySaveState(void) +{ + Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; + + Settings.energy_kWhtoday = RtcSettings.energy_kWhtoday; + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + + Settings.energy_usage = RtcSettings.energy_usage; +} + +#ifdef USE_ENERGY_MARGIN_DETECTION +bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag) +{ + bool change; + + if (!margin) return false; + change = save_flag; + if (type) { + flag = (value > margin); + } else { + flag = (value < margin); + } + save_flag = flag; + return (change != save_flag); +} + +void EnergyMarginCheck(void) +{ + uint16_t energy_daily_u = 0; + uint16_t energy_power_u = 0; + uint16_t energy_voltage_u = 0; + uint16_t energy_current_u = 0; + bool flag; + bool jsonflg; + + if (Energy.power_steady_counter) { + Energy.power_steady_counter--; + return; + } + + if (Settings.energy_power_delta) { + float delta = abs(Energy.power_history[0] - Energy.active_power[0]); + + float min_power = (Energy.power_history[0] > Energy.active_power[0]) ? Energy.active_power[0] : Energy.power_history[0]; + if (((delta / min_power) * 100) > Settings.energy_power_delta) { + Energy.power_delta = 1; + Energy.power_history[1] = Energy.active_power[0]; + Energy.power_history[2] = Energy.active_power[0]; + } + } + Energy.power_history[0] = Energy.power_history[1]; + Energy.power_history[1] = Energy.power_history[2]; + Energy.power_history[2] = Energy.active_power[0]; + + if (Energy.power_on && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) { + energy_power_u = (uint16_t)(Energy.active_power[0]); + energy_voltage_u = (uint16_t)(Energy.voltage[0]); + energy_current_u = (uint16_t)(Energy.current[0] * 1000); + + DEBUG_DRIVER_LOG(PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); + + Response_P(PSTR("{")); + jsonflg = false; + if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, Energy.min_power_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_POWERLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(true, Settings.energy_max_power, energy_power_u, flag, Energy.max_power_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_POWERHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(false, Settings.energy_min_voltage, energy_voltage_u, flag, Energy.min_voltage_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(true, Settings.energy_max_voltage, energy_voltage_u, flag, Energy.max_voltage_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(false, Settings.energy_min_current, energy_current_u, flag, Energy.min_current_flag)) { + ResponseAppend_P(PSTR("%s%s\"" D_CMND_CURRENTLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(true, Settings.energy_max_current, energy_current_u, flag, Energy.max_current_flag)) { + ResponseAppend_P(PSTR("%s%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (jsonflg) { + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_MARGINS), MQTT_TELE_RETAIN); + EnergyMqttShow(); + } + } + +#ifdef USE_ENERGY_POWER_LIMIT + + if (Settings.energy_max_power_limit) { + if (Energy.active_power[0] > Settings.energy_max_power_limit) { + if (!Energy.mplh_counter) { + Energy.mplh_counter = Settings.energy_max_power_limit_hold; + } else { + Energy.mplh_counter--; + if (!Energy.mplh_counter) { + ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); + MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); + EnergyMqttShow(); + SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); + if (!Energy.mplr_counter) { + Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1; + } + Energy.mplw_counter = Settings.energy_max_power_limit_window; + } + } + } + else if (power && (energy_power_u <= Settings.energy_max_power_limit)) { + Energy.mplh_counter = 0; + Energy.mplr_counter = 0; + Energy.mplw_counter = 0; + } + if (!power) { + if (Energy.mplw_counter) { + Energy.mplw_counter--; + } else { + if (Energy.mplr_counter) { + Energy.mplr_counter--; + if (Energy.mplr_counter) { + ResponseTime_P(PSTR(",\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); + RestorePower(true, SRC_MAXPOWER); + } else { + ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); + MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); + EnergyMqttShow(); + } + } + } + } + } + + + if (Settings.energy_max_energy) { + energy_daily_u = (uint16_t)(Energy.daily * 1000); + if (!Energy.max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) { + Energy.max_energy_state = 1; + ResponseTime_P(PSTR(",\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); + RestorePower(true, SRC_MAXENERGY); + } + else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) { + Energy.max_energy_state = 2; + dtostrfd(Energy.daily, 3, mqtt_data); + ResponseTime_P(PSTR(",\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); + MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); + EnergyMqttShow(); + SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY); + } + } +#endif + + if (Energy.power_delta) { EnergyMqttShow(); } +} + +void EnergyMqttShow(void) +{ + + int tele_period_save = tele_period; + tele_period = 2; + mqtt_data[0] = '\0'; + ResponseAppendTime(); + EnergyShow(true); + tele_period = tele_period_save; + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + Energy.power_delta = 0; +} +#endif + +void EnergyEverySecond() +{ + + if (global_update) { + if (power && (global_temperature != 9999) && (global_temperature > Settings.param[P_OVER_TEMP])) { + SetAllPower(POWER_ALL_OFF, SRC_OVERTEMP); + } + } + + + uint32_t data_valid = Energy.phase_count; + for (uint32_t i = 0; i < Energy.phase_count; i++) { + if (Energy.data_valid[i] <= ENERGY_WATCHDOG) { + Energy.data_valid[i]++; + if (Energy.data_valid[i] > ENERGY_WATCHDOG) { + + Energy.voltage[i] = 0; + Energy.current[i] = 0; + Energy.active_power[i] = 0; + if (!isnan(Energy.apparent_power[i])) { Energy.apparent_power[i] = 0; } + if (!isnan(Energy.reactive_power[i])) { Energy.reactive_power[i] = 0; } + if (!isnan(Energy.frequency[i])) { Energy.frequency[i] = 0; } + if (!isnan(Energy.power_factor[i])) { Energy.power_factor[i] = 0; } + + data_valid--; + } + } + } + if (!data_valid) { + if (!isnan(Energy.export_active)) { Energy.export_active = 0; } + Energy.start_energy = 0; + + XnrgCall(FUNC_ENERGY_RESET); + } + +#ifdef USE_ENERGY_MARGIN_DETECTION + EnergyMarginCheck(); +#endif +} + + + + + +void EnergyCommandResponse(uint32_t nvalue, uint32_t unit) +{ + if (UNIT_MILLISECOND == unit) { + snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command); + unit = UNIT_MICROSECOND; + } + + if (Settings.flag.value_units) { + char sunit[CMDSZ]; + Response_P(S_JSON_COMMAND_LVALUE_SPACE_UNIT, XdrvMailbox.command, nvalue, GetTextIndexed(sunit, sizeof(sunit), unit, kUnitNames)); + } else { + Response_P(S_JSON_COMMAND_LVALUE, XdrvMailbox.command, nvalue); + } +} + +void CmndEnergyReset(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { + char *p; + unsigned long lnum = strtoul(XdrvMailbox.data, &p, 10); + if (p != XdrvMailbox.data) { + switch (XdrvMailbox.index) { + case 1: + + Energy.kWhtoday_offset = lnum *100; + Energy.kWhtoday = 0; + Energy.kWhtoday_delta = 0; + Energy.period = Energy.kWhtoday_offset; + Settings.energy_kWhtoday = Energy.kWhtoday_offset; + RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset; + Energy.daily = (float)Energy.kWhtoday_offset / 100000; + if (!RtcSettings.energy_kWhtotal && !Energy.kWhtoday_offset) { + Settings.energy_kWhtotal_time = LocalTime(); + } + break; + case 2: + + Settings.energy_kWhyesterday = lnum *100; + break; + case 3: + + RtcSettings.energy_kWhtotal = lnum *100; + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; + Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); + RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 1000); + break; + } + } + } + + if ((XdrvMailbox.index > 3) && (XdrvMailbox.index <= 5)) { + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + int32_t position = -1; + uint32_t values[2]; + + while ((str != nullptr) && (position < 1)) { + uint32_t value = strtoul(str, nullptr, 10); + position++; + values[position] = value *100; + str = strtok_r(nullptr, ", ", &p); + } + + switch (XdrvMailbox.index) + { + case 4: + + if (position > -1) { + RtcSettings.energy_usage.usage1_kWhtotal = values[0]; + } + if (position > 0) { + RtcSettings.energy_usage.usage2_kWhtotal = values[1]; + } + Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal; + Settings.energy_usage.usage2_kWhtotal = RtcSettings.energy_usage.usage2_kWhtotal; + break; + case 5: + + if (position > -1) { + RtcSettings.energy_usage.return1_kWhtotal = values[0]; + } + if (position > 0) { + RtcSettings.energy_usage.return2_kWhtotal = values[1]; + } + Settings.energy_usage.return1_kWhtotal = RtcSettings.energy_usage.return1_kWhtotal; + Settings.energy_usage.return2_kWhtotal = RtcSettings.energy_usage.return2_kWhtotal; + + + + break; + } + } + + char energy_total_chr[FLOATSZ]; + dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr); + char energy_daily_chr[FLOATSZ]; + dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); + char energy_yesterday_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); + + char energy_usage1_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage1_chr); + char energy_usage2_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage2_chr); + char energy_return1_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return1_chr); + char energy_return2_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return2_chr); + + Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s,\"" D_JSON_USAGE "\":[%s,%s],\"" D_JSON_EXPORT "\":[%s,%s]}}"), + XdrvMailbox.command, energy_total_chr, energy_yesterday_chr, energy_daily_chr, energy_usage1_chr, energy_usage2_chr, energy_return1_chr, energy_return2_chr); +} + +void CmndTariff(void) +{ + + + + + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + uint32_t time_type = 0; + while ((str != nullptr) && (time_type <= 2)) { + uint8_t value = strtol(str, nullptr, 10); + if ((value >= 0) && (value < 24)) { + Settings.register8[R8_ENERGY_TARIFF1_ST + (XdrvMailbox.index -1) + time_type] = value; + } + str = strtok_r(nullptr, ", ", &p); + time_type += 2; + } + } + else if (XdrvMailbox.index == 9) { + Settings.flag3.energy_weekend = XdrvMailbox.payload & 1; + } + Response_P(PSTR("{\"%s\":{\"Off-Peak\":[%d,%d],\"Standard\":[%d,%d],\"Weekend\":\"%s\"}}"), + XdrvMailbox.command, + Settings.register8[R8_ENERGY_TARIFF1_ST], Settings.register8[R8_ENERGY_TARIFF1_DS], + Settings.register8[R8_ENERGY_TARIFF2_ST], Settings.register8[R8_ENERGY_TARIFF2_DS], + GetStateText(Settings.flag3.energy_weekend)); +} + +void CmndPowerCal(void) +{ + Energy.command_code = CMND_POWERCAL; + if (XnrgCall(FUNC_COMMAND)) { + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { + Settings.energy_power_calibration = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_power_calibration, UNIT_MICROSECOND); + } +} + +void CmndVoltageCal(void) +{ + Energy.command_code = CMND_VOLTAGECAL; + if (XnrgCall(FUNC_COMMAND)) { + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { + Settings.energy_voltage_calibration = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_voltage_calibration, UNIT_MICROSECOND); + } +} + +void CmndCurrentCal(void) +{ + Energy.command_code = CMND_CURRENTCAL; + if (XnrgCall(FUNC_COMMAND)) { + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { + Settings.energy_current_calibration = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_current_calibration, UNIT_MICROSECOND); + } +} + +void CmndPowerSet(void) +{ + Energy.command_code = CMND_POWERSET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandResponse(Settings.energy_power_calibration, UNIT_MILLISECOND); + } +} + +void CmndVoltageSet(void) +{ + Energy.command_code = CMND_VOLTAGESET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandResponse(Settings.energy_voltage_calibration, UNIT_MILLISECOND); + } +} + +void CmndCurrentSet(void) +{ + Energy.command_code = CMND_CURRENTSET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandResponse(Settings.energy_current_calibration, UNIT_MILLISECOND); + } +} + +void CmndFrequencySet(void) +{ + Energy.command_code = CMND_FREQUENCYSET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandResponse(Settings.energy_frequency_calibration, UNIT_MILLISECOND); + } +} + +void CmndModuleAddress(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4) && (1 == Energy.phase_count)) { + Energy.command_code = CMND_MODULEADDRESS; + if (XnrgCall(FUNC_COMMAND)) { + ResponseCmndDone(); + } + } +} + +#ifdef USE_ENERGY_MARGIN_DETECTION +void CmndPowerDelta(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 101)) { + Settings.energy_power_delta = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_power_delta, UNIT_PERCENTAGE); +} + +void CmndPowerLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_min_power = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_min_power, UNIT_WATT); +} + +void CmndPowerHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_max_power, UNIT_WATT); +} + +void CmndVoltageLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { + Settings.energy_min_voltage = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_min_voltage, UNIT_VOLT); +} + +void CmndVoltageHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { + Settings.energy_max_voltage = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_max_voltage, UNIT_VOLT); +} + +void CmndCurrentLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { + Settings.energy_min_current = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_min_current, UNIT_MILLIAMPERE); +} + +void CmndCurrentHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { + Settings.energy_max_current = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_max_current, UNIT_MILLIAMPERE); +} + +#ifdef USE_ENERGY_POWER_LIMIT +void CmndMaxPower(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_limit = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_max_power_limit, UNIT_WATT); +} + +void CmndMaxPowerHold(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_max_power_limit_hold, UNIT_SECOND); +} + +void CmndMaxPowerWindow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_max_power_limit_window, UNIT_SECOND); +} + +void CmndSafePower(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_safe_limit = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_max_power_safe_limit, UNIT_WATT); +} + +void CmndSafePowerHold(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_safe_limit_hold = (1 == XdrvMailbox.payload) ? SAFE_POWER_HOLD : XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_max_power_safe_limit_hold, UNIT_SECOND); +} + +void CmndSafePowerWindow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 1440)) { + Settings.energy_max_power_safe_limit_window = (1 == XdrvMailbox.payload) ? SAFE_POWER_WINDOW : XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_max_power_safe_limit_window, UNIT_MINUTE); +} + +void CmndMaxEnergy(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_energy = XdrvMailbox.payload; + Energy.max_energy_state = 3; + } + EnergyCommandResponse(Settings.energy_max_energy, UNIT_WATTHOUR); +} + +void CmndMaxEnergyStart(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) { + Settings.energy_max_energy_start = XdrvMailbox.payload; + } + EnergyCommandResponse(Settings.energy_max_energy_start, UNIT_HOUR); +} +#endif +#endif + +void EnergyDrvInit(void) +{ + energy_flg = ENERGY_NONE; + XnrgCall(FUNC_PRE_INIT); +} + +void EnergySnsInit(void) +{ + XnrgCall(FUNC_INIT); + + if (energy_flg) { + if (RtcSettingsValid()) { + Energy.kWhtoday_offset = RtcSettings.energy_kWhtoday; + } + else if (RtcTime.day_of_year == Settings.energy_kWhdoy) { + Energy.kWhtoday_offset = Settings.energy_kWhtoday; + } + else { + Energy.kWhtoday_offset = 0; + } + Energy.kWhtoday = 0; + Energy.kWhtoday_delta = 0; + Energy.period = Energy.kWhtoday_offset; + EnergyUpdateToday(); + ticker_energy.attach_ms(200, Energy200ms); + } +} + +#ifdef USE_WEBSERVER +const char HTTP_ENERGY_SNS1[] PROGMEM = + "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" + "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" + "{s}" D_POWER_FACTOR "{m}%s{e}"; + +const char HTTP_ENERGY_SNS2[] PROGMEM = + "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; + +const char HTTP_ENERGY_SNS3[] PROGMEM = + "{s}" D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; +#endif + +char* EnergyFormatIndex(char* result, char* input, bool json, uint32_t index, bool single = false) +{ + char layout[16]; + GetTextIndexed(layout, sizeof(layout), (index -1) + (3 * json), kEnergyPhases); + switch (index) { + case 2: + snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ); + break; + case 3: + snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ, input + FLOATSZ + FLOATSZ); + break; + default: + snprintf_P(result, FLOATSZ *3, input); + } + return result; +} + +char* EnergyFormat(char* result, char* input, bool json, bool single = false) +{ + uint8_t index = (single) ? 1 : Energy.phase_count; + return EnergyFormatIndex(result, input, json, index, single); +} + +void EnergyShow(bool json) +{ + for (uint32_t i = 0; i < Energy.phase_count; i++) { + if (Energy.voltage_common) { + Energy.voltage[i] = Energy.voltage[0]; + } + } + + float power_factor_knx = Energy.power_factor[0]; + + char apparent_power_chr[Energy.phase_count][FLOATSZ]; + char reactive_power_chr[Energy.phase_count][FLOATSZ]; + char power_factor_chr[Energy.phase_count][FLOATSZ]; + char frequency_chr[Energy.phase_count][FLOATSZ]; + if (!Energy.type_dc) { + if (Energy.current_available && Energy.voltage_available) { + for (uint32_t i = 0; i < Energy.phase_count; i++) { + float apparent_power = Energy.apparent_power[i]; + if (isnan(apparent_power)) { + apparent_power = Energy.voltage[i] * Energy.current[i]; + } + if (apparent_power < Energy.active_power[i]) { + Energy.active_power[i] = apparent_power; + } + + float power_factor = Energy.power_factor[i]; + if (isnan(power_factor)) { + power_factor = (Energy.active_power[i] && apparent_power) ? Energy.active_power[i] / apparent_power : 0; + if (power_factor > 1) { + power_factor = 1; + } + } + if (0 == i) { power_factor_knx = power_factor; } + + float reactive_power = Energy.reactive_power[i]; + if (isnan(reactive_power)) { + reactive_power = 0; + uint32_t difference = ((uint32_t)(apparent_power * 100) - (uint32_t)(Energy.active_power[i] * 100)) / 10; + if ((Energy.current[i] > 0.005) && ((difference > 15) || (difference > (uint32_t)(apparent_power * 100 / 1000)))) { + + + reactive_power = (float)(RoundSqrtInt((uint32_t)(apparent_power * apparent_power * 100) - (uint32_t)(Energy.active_power[i] * Energy.active_power[i] * 100))) / 10; + } + } + + dtostrfd(apparent_power, Settings.flag2.wattage_resolution, apparent_power_chr[i]); + dtostrfd(reactive_power, Settings.flag2.wattage_resolution, reactive_power_chr[i]); + dtostrfd(power_factor, 2, power_factor_chr[i]); + } + } + for (uint32_t i = 0; i < Energy.phase_count; i++) { + float frequency = Energy.frequency[i]; + if (isnan(Energy.frequency[i])) { + frequency = 0; + } + dtostrfd(frequency, Settings.flag2.frequency_resolution, frequency_chr[i]); + } + } + + char voltage_chr[Energy.phase_count][FLOATSZ]; + char current_chr[Energy.phase_count][FLOATSZ]; + char active_power_chr[Energy.phase_count][FLOATSZ]; + for (uint32_t i = 0; i < Energy.phase_count; i++) { + dtostrfd(Energy.voltage[i], Settings.flag2.voltage_resolution, voltage_chr[i]); + dtostrfd(Energy.current[i], Settings.flag2.current_resolution, current_chr[i]); + dtostrfd(Energy.active_power[i], Settings.flag2.wattage_resolution, active_power_chr[i]); + } + + char energy_daily_chr[FLOATSZ]; + dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); + char energy_yesterday_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); + + char energy_total_chr[3][FLOATSZ]; + dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr[0]); + char export_active_chr[3][FLOATSZ]; + dtostrfd(Energy.export_active, Settings.flag2.energy_resolution, export_active_chr[0]); + uint8_t energy_total_fields = 1; + if (Settings.register8[R8_ENERGY_TARIFF1_ST] != Settings.register8[R8_ENERGY_TARIFF2_ST]) { + dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[2]); + dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[2]); + energy_total_fields = 3; + } + + char value_chr[FLOATSZ *3]; + char value2_chr[FLOATSZ *3]; + char value3_chr[FLOATSZ *3]; + + if (json) { + bool show_energy_period = (0 == tele_period); + + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"), + GetDateAndTime(DT_ENERGY).c_str(), + EnergyFormatIndex(value_chr, energy_total_chr[0], json, energy_total_fields), + energy_yesterday_chr, + energy_daily_chr); + + if (!isnan(Energy.export_active)) { + ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"), + EnergyFormatIndex(value_chr, export_active_chr[0], json, energy_total_fields)); + } + + if (show_energy_period) { + float energy = 0; + if (Energy.period) { + energy = (float)(RtcSettings.energy_kWhtoday - Energy.period) / 100; + } + Energy.period = RtcSettings.energy_kWhtoday; + char energy_period_chr[FLOATSZ]; + dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr); + ResponseAppend_P(PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr); + } + ResponseAppend_P(PSTR(",\"" D_JSON_POWERUSAGE "\":%s"), + EnergyFormat(value_chr, active_power_chr[0], json)); + if (!Energy.type_dc) { + if (Energy.current_available && Energy.voltage_available) { + ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s"), + EnergyFormat(value_chr, apparent_power_chr[0], json), + EnergyFormat(value2_chr, reactive_power_chr[0], json), + EnergyFormat(value3_chr, power_factor_chr[0], json)); + } + if (!isnan(Energy.frequency[0])) { + ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), + EnergyFormat(value_chr, frequency_chr[0], json)); + } + } + if (Energy.voltage_available) { + ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"), + EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); + } + if (Energy.current_available) { + ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"), + EnergyFormat(value_chr, current_chr[0], json)); + } + XnrgCall(FUNC_JSON_APPEND); + ResponseJsonEnd(); + +#ifdef USE_DOMOTICZ + if (show_energy_period) { + dtostrfd(Energy.total * 1000, 1, energy_total_chr[0]); + DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr[0]); + + dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100, 1, energy_total_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100, 1, energy_total_chr[2]); + dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100, 1, export_active_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100, 1, export_active_chr[2]); + DomoticzSensorP1SmartMeter(energy_total_chr[1], energy_total_chr[2], export_active_chr[1], export_active_chr[2], (int)Energy.active_power[0]); + + if (Energy.voltage_available) { + DomoticzSensor(DZ_VOLTAGE, voltage_chr[0]); + } + if (Energy.current_available) { + DomoticzSensor(DZ_CURRENT, current_chr[0]); + } + } +#endif +#ifdef USE_KNX + if (show_energy_period) { + if (Energy.voltage_available) { + KnxSensor(KNX_ENERGY_VOLTAGE, Energy.voltage[0]); + } + if (Energy.current_available) { + KnxSensor(KNX_ENERGY_CURRENT, Energy.current[0]); + } + KnxSensor(KNX_ENERGY_POWER, Energy.active_power[0]); + if (!Energy.type_dc) { + KnxSensor(KNX_ENERGY_POWERFACTOR, power_factor_knx); + } + KnxSensor(KNX_ENERGY_DAILY, Energy.daily); + KnxSensor(KNX_ENERGY_TOTAL, Energy.total); + KnxSensor(KNX_ENERGY_START, Energy.start_energy); + } +#endif +#ifdef USE_WEBSERVER + } else { + if (Energy.voltage_available) { + WSContentSend_PD(PSTR("{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}"), + EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); + } + if (Energy.current_available) { + WSContentSend_PD(PSTR("{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}"), + EnergyFormat(value_chr, current_chr[0], json)); + } + WSContentSend_PD(PSTR("{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"), + EnergyFormat(value_chr, active_power_chr[0], json)); + if (!Energy.type_dc) { + if (Energy.current_available && Energy.voltage_available) { + WSContentSend_PD(HTTP_ENERGY_SNS1, EnergyFormat(value_chr, apparent_power_chr[0], json), + EnergyFormat(value2_chr, reactive_power_chr[0], json), + EnergyFormat(value3_chr, power_factor_chr[0], json)); + } + if (!isnan(Energy.frequency[0])) { + WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), + EnergyFormat(value_chr, frequency_chr[0], json)); + } + } + WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr[0]); + if (!isnan(Energy.export_active)) { + WSContentSend_PD(HTTP_ENERGY_SNS3, export_active_chr[0]); + } + + XnrgCall(FUNC_WEB_SENSOR); +#endif + } +} + + + + + +bool Xdrv03(uint8_t function) +{ + bool result = false; + + if (FUNC_PRE_INIT == function) { + EnergyDrvInit(); + } + else if (energy_flg) { + switch (function) { + case FUNC_LOOP: + XnrgCall(FUNC_LOOP); + break; + case FUNC_EVERY_250_MSECOND: + XnrgCall(FUNC_EVERY_250_MSECOND); + break; + case FUNC_SERIAL: + result = XnrgCall(FUNC_SERIAL); + break; +#ifdef USE_ENERGY_MARGIN_DETECTION + case FUNC_SET_POWER: + Energy.power_steady_counter = 2; + break; +#endif + case FUNC_COMMAND: + result = DecodeCommand(kEnergyCommands, EnergyCommand); + break; + } + } + return result; +} + +bool Xsns03(uint8_t function) +{ + bool result = false; + + if (energy_flg) { + switch (function) { + case FUNC_EVERY_SECOND: + EnergyEverySecond(); + break; + case FUNC_JSON_APPEND: + EnergyShow(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + EnergyShow(false); + break; +#endif + case FUNC_SAVE_BEFORE_RESTART: + EnergySaveState(); + break; + case FUNC_INIT: + EnergySnsInit(); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" +#ifdef USE_LIGHT +# 128 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" +#define XDRV_04 4 + + +const uint8_t LIGHT_COLOR_SIZE = 25; +const uint8_t WS2812_SCHEMES = 7; + +const char kLightCommands[] PROGMEM = "|" +#ifdef USE_WS2812 + D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH "|" +#endif + D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|" + D_CMND_RGBWWTABLE "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" + D_CMND_WHITE "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ; + +void (* const LightCommand[])(void) PROGMEM = { +#ifdef USE_WS2812 + &CmndLed, &CmndPixels, &CmndRotation, &CmndWidth, +#endif + &CmndColor, &CmndColorTemperature, &CmndDimmer, &CmndLedTable, &CmndFade, + &CmndRgbwwTable, &CmndScheme, &CmndSpeed, &CmndWakeup, &CmndWakeupDuration, + &CmndWhite, &CmndChannel, &CmndHsbColor, &CmndUndocA }; + + +enum LightColorModes { + LCM_RGB = 1, LCM_CT = 2, LCM_BOTH = 3 }; + +struct LRgbColor { + uint8_t R, G, B; +}; +const uint8_t MAX_FIXED_COLOR = 12; +const LRgbColor kFixedColor[MAX_FIXED_COLOR] PROGMEM = + { 255,0,0, 0,255,0, 0,0,255, 228,32,0, 0,228,32, 0,32,228, 188,64,0, 0,160,96, 160,32,240, 255,255,0, 255,0,170, 255,255,255 }; + +struct LWColor { + uint8_t W; +}; +const uint8_t MAX_FIXED_WHITE = 4; +const LWColor kFixedWhite[MAX_FIXED_WHITE] PROGMEM = { 0, 255, 128, 32 }; + +struct LCwColor { + uint8_t C, W; +}; +const uint8_t MAX_FIXED_COLD_WARM = 4; +const LCwColor kFixedColdWarm[MAX_FIXED_COLD_WARM] PROGMEM = { 0,0, 255,0, 0,255, 128,128 }; + + + + + +#ifdef XFUNC_PTR_IN_ROM +const uint8_t _ledTable[] PROGMEM = { +#else +const uint8_t _ledTable[] = { +#endif + + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, + 7, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 24, 25, 26, 28, 29, 30, 32, 33, 35, 37, 38, 40, 42, + + 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 36, 37, 38, 39, + 41, 42, 44, 45, 47, 48, 50, 51, 53, 55, 56, 58, 60, 62, 64, 65, + 67, 69, 71, 73, 75, 78, 80, 82, 84, 86, 89, 91, 93, 96, 98,101, + 103,106,108,111,114,116,119,122,125,128,131,134,137,140,143,146, + + 75, 77, 78, 80, 82, 84, 85, 87, 89, 91, 93, 94, 96, 98,100,102, + 104,106,108,110,112,115,117,119,121,123,125,128,130,132,135,137, + 140,142,144,147,149,152,155,157,160,163,165,168,171,173,176,179, + 182,185,188,191,194,197,200,203,206,209,212,215,219,222,225,229, + + 116,118,120,121,123,125,127,128,130,132,134,136,138,139,141,143, + 145,147,149,151,153,155,157,159,161,163,165,168,170,172,174,176, + 178,181,183,185,187,190,192,194,197,199,201,204,206,209,211,214, + 216,219,221,224,226,229,232,234,237,240,242,245,248,250,253,255 +}; +# 241 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" +struct LIGHT { + unsigned long strip_timer_counter = 0; + power_t power = 0; + + uint16_t wakeup_counter = 0; + + uint8_t entry_color[LST_MAX]; + uint8_t current_color[LST_MAX]; + uint8_t new_color[LST_MAX]; + uint8_t last_color[LST_MAX]; + uint8_t color_remap[LST_MAX]; + + uint8_t wheel = 0; + uint8_t subtype = 0; + uint8_t device = 0; + uint8_t old_power = 1; + uint8_t wakeup_active = 0; + uint8_t wakeup_dimmer = 0; + uint8_t fixed_color_index = 1; + + bool update = true; + bool pwm_multi_channels = false; +} Light; + +power_t LightPower(void) +{ + return Light.power; +} + +uint8_t LightDevice(void) +{ + return Light.device; +} + +static uint32_t min3(uint32_t a, uint32_t b, uint32_t c) { + return (a < b && a < c) ? a : (b < c) ? b : c; +} +# 316 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" +class LightStateClass { + private: + uint16_t _hue = 0; + uint8_t _sat = 255; + uint8_t _briRGB = 255; + + uint8_t _r = 255; + uint8_t _g = 255; + uint8_t _b = 255; + + uint8_t _subtype = 0; + uint16_t _ct = 153; + uint8_t _wc = 255; + uint8_t _ww = 0; + uint8_t _briCT = 255; + + uint8_t _color_mode = LCM_RGB; + + public: + LightStateClass() { + + } + + void setSubType(uint8_t sub_type) { + _subtype = sub_type; + } +# 351 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" + uint8_t setColorMode(uint8_t cm) { + uint8_t prev_cm = _color_mode; + if (cm < LCM_RGB) { cm = LCM_RGB; } + if (cm > LCM_BOTH) { cm = LCM_BOTH; } + uint8_t maxbri = (_briRGB >= _briCT) ? _briRGB : _briCT; + + switch (_subtype) { + case LST_COLDWARM: + _color_mode = LCM_CT; + break; + + case LST_NONE: + case LST_SINGLE: + case LST_RGB: + default: + _color_mode = LCM_RGB; + break; + + case LST_RGBW: + case LST_RGBWC: + _color_mode = cm; + break; + } + if (LCM_RGB == _color_mode) { + _briCT = 0; + if (0 == _briRGB) { _briRGB = maxbri; } + } + if (LCM_CT == _color_mode) { + _briRGB = 0; + if (0 == _briCT) { _briCT = maxbri; } + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setColorMode prev_cm (%d) req_cm (%d) new_cm (%d)", prev_cm, cm, _color_mode); +#endif + return prev_cm; + } + + inline uint8_t getColorMode() { + return _color_mode; + } + + void addRGBMode() { + setColorMode(_color_mode | LCM_RGB); + } + void addCTMode() { + setColorMode(_color_mode | LCM_CT); + } + + + void getRGB(uint8_t *r, uint8_t *g, uint8_t *b) { + if (r) { *r = _r; } + if (g) { *g = _g; } + if (b) { *b = _b; } + } + + + + void getCW(uint8_t *rc, uint8_t *rw) { + if (rc) { *rc = _wc; } + if (rw) { *rw = _ww; } + } + + + void getActualRGBCW(uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *c, uint8_t *w) { + bool rgb_channels_on = _color_mode & LCM_RGB; + bool ct_channels_on = _color_mode & LCM_CT; + + if (r) { *r = rgb_channels_on ? changeUIntScale(_r, 0, 255, 0, _briRGB) : 0; } + if (g) { *g = rgb_channels_on ? changeUIntScale(_g, 0, 255, 0, _briRGB) : 0; } + if (b) { *b = rgb_channels_on ? changeUIntScale(_b, 0, 255, 0, _briRGB) : 0; } + + if (c) { *c = ct_channels_on ? changeUIntScale(_wc, 0, 255, 0, _briCT) : 0; } + if (w) { *w = ct_channels_on ? changeUIntScale(_ww, 0, 255, 0, _briCT) : 0; } + } + + uint8_t getChannels(uint8_t *channels) { + getActualRGBCW(&channels[0], &channels[1], &channels[2], &channels[3], &channels[4]); + } + + void getHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { + if (hue) { *hue = _hue; } + if (sat) { *sat = _sat; } + if (bri) { *bri = _briRGB; } + } + + + uint8_t getBri(void) { + + return (_briRGB >= _briCT) ? _briRGB : _briCT; + } + + + inline uint8_t getBriCT() { + return _briCT; + } + + static inline uint8_t DimmerToBri(uint8_t dimmer) { + return changeUIntScale(dimmer, 0, 100, 0, 255); + } + static uint8_t BriToDimmer(uint8_t bri) { + uint8_t dimmer = changeUIntScale(bri, 0, 255, 0, 100); + + if ((dimmer == 0) && (bri > 0)) { dimmer = 1; } + return dimmer; + } + + uint8_t getDimmer() { + return BriToDimmer(getBri()); + } + + inline uint16_t getCT() { + return _ct; + } + + + void getXY(float *x, float *y) { + RgbToXy(_r, _g, _b, x, y); + } + + + + void setBri(uint8_t bri) { + setBriRGB(_color_mode & LCM_RGB ? bri : 0); + setBriCT(_color_mode & LCM_CT ? bri : 0); +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setBri RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); +#endif + } + + + uint8_t setBriRGB(uint8_t bri_rgb) { + uint8_t prev_bri = _briRGB; + _briRGB = bri_rgb; + if (bri_rgb > 0) { addRGBMode(); } + return prev_bri; + } + + + uint8_t setBriCT(uint8_t bri_ct) { + uint8_t prev_bri = _briCT; + _briCT = bri_ct; + if (bri_ct > 0) { addCTMode(); } + return prev_bri; + } + + inline uint8_t getBriRGB() { + return _briRGB; + } + + void setDimmer(uint8_t dimmer) { + setBri(DimmerToBri(dimmer)); + } + + void setCT(uint16_t ct) { + if (0 == ct) { + + setColorMode(LCM_RGB); + } else { + ct = (ct < 153 ? 153 : (ct > 500 ? 500 : ct)); + _ww = changeUIntScale(ct, 153, 500, 0, 255); + _wc = 255 - _ww; + _ct = ct; + addCTMode(); + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setCT RGB raw (%d %d %d) HS (%d %d) briRGB (%d) briCT (%d) CT (%d)", _r, _g, _b, _hue, _sat, _briRGB, _briCT, _ct); +#endif + } +# 534 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" + void setCW(uint8_t c, uint8_t w, bool free_range = false) { + uint16_t max = (w > c) ? w : c; + uint16_t sum = c + w; + + if (0 == max) { + _briCT = 0; + setColorMode(LCM_RGB); + } else { + if (!free_range) { + + _ww = changeUIntScale(w, 0, sum, 0, 255); + _wc = 255 - _ww; + } else { + _ww = changeUIntScale(w, 0, max, 0, 255); + _wc = changeUIntScale(c, 0, max, 0, 255); + } + _ct = changeUIntScale(w, 0, sum, 153, 500); + addCTMode(); + if (_color_mode & LCM_CT) { _briCT = free_range ? max : (sum > 255 ? 255 : sum); } + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setCW CW (%d %d) CT (%d) briCT (%d)", c, w, _ct, _briCT); +#endif + } + + + uint8_t setRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { + uint16_t hue; + uint8_t sat; +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setRGB RGB input (%d %d %d)", r, g, b); +#endif + + uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; + + if (0 == max) { + r = g = b = 255; + setColorMode(LCM_CT); + } else { + if (255 > max) { + + r = changeUIntScale(r, 0, max, 0, 255); + g = changeUIntScale(g, 0, max, 0, 255); + b = changeUIntScale(b, 0, max, 0, 255); + } + addRGBMode(); + } + if (!keep_bri) { + _briRGB = (_color_mode & LCM_RGB) ? max : 0; + } + + RgbToHsb(r, g, b, &hue, &sat, nullptr); + _r = r; + _g = g; + _b = b; + _hue = hue; + _sat = sat; +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setRGB RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); +#endif + return max; + } + + void setHS(uint16_t hue, uint8_t sat) { + uint8_t r, g, b; + HsToRgb(hue, sat, &r, &g, &b); + _r = r; + _g = g; + _b = b; + _hue = hue; + _sat = sat; + addRGBMode(); +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setHS HS (%d %d) rgb (%d %d %d)", hue, sat, r, g, b); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setHS RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); +#endif + } + + + + + void setChannels(uint8_t *channels) { + setRGB(channels[0], channels[1], channels[2]); + setCW(channels[3], channels[4], true); +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels (%d %d %d %d %d)", + channels[0], channels[1], channels[2], channels[3], channels[4]); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels CT (%d) briRGB (%d) briCT (%d)", _ct, _briRGB, _briCT); +#endif + } + + + static void RgbToHsb(uint8_t r, uint8_t g, uint8_t b, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri); + static void HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b); + static void RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y); + static void XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb); + +}; +# 640 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" +void LightStateClass::RgbToHsb(uint8_t ir, uint8_t ig, uint8_t ib, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri) { + uint32_t r = ir; + uint32_t g = ig; + uint32_t b = ib; + uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; + uint32_t min = (r < g && r < b) ? r : (g < b) ? g : b; + uint32_t d = max - min; + + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = max; + + if (d != 0) { + sat = changeUIntScale(d, 0, max, 0, 255); + if (r == max) { + hue = (g > b) ? changeUIntScale(g-b,0,d,0,60) : 360 - changeUIntScale(b-g,0,d,0,60); + } else if (g == max) { + hue = (b > r) ? 120 + changeUIntScale(b-r,0,d,0,60) : 120 - changeUIntScale(r-b,0,d,0,60); + } else { + hue = (r > g) ? 240 + changeUIntScale(r-g,0,d,0,60) : 240 - changeUIntScale(g-r,0,d,0,60); + } + hue = hue % 360; + } + + if (r_hue) *r_hue = hue; + if (r_sat) *r_sat = sat; + if (r_bri) *r_bri = bri; + +} + +void LightStateClass::HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { + uint32_t r = 255; + uint32_t g = 255; + uint32_t b = 255; + + hue = hue % 360; + + if (sat > 0) { + uint32_t i = hue / 60; + uint32_t f = hue % 60; + uint32_t q = 255 - changeUIntScale(f, 0, 60, 0, sat); + uint32_t p = 255 - sat; + uint32_t t = 255 - changeUIntScale(60 - f, 0, 60, 0, sat); + + switch (i) { + case 0: + + g = t; + b = p; + break; + case 1: + r = q; + + b = p; + break; + case 2: + r = p; + + b = t; + break; + case 3: + r = p; + g = q; + + break; + case 4: + r = t; + g = p; + + break; + default: + + g = p; + b = q; + break; + } + } + if (r_r) *r_r = r; + if (r_g) *r_g = g; + if (r_b) *r_b = b; +} + +#define POW FastPrecisePowf + +void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y) { + float x = 0.31271f; + float y = 0.32902f; + + if (i_r + i_b + i_g > 0) { + float r = (float)i_r / 255.0f; + float g = (float)i_g / 255.0f; + float b = (float)i_b / 255.0f; + + + r = (r > 0.04045f) ? POW((r + 0.055f) / (1.0f + 0.055f), 2.4f) : (r / 12.92f); + g = (g > 0.04045f) ? POW((g + 0.055f) / (1.0f + 0.055f), 2.4f) : (g / 12.92f); + b = (b > 0.04045f) ? POW((b + 0.055f) / (1.0f + 0.055f), 2.4f) : (b / 12.92f); + + + + float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; + float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; + float Z = r * 0.000000f + g * 0.053077f + b * 1.035763f; + + x = X / (X + Y + Z); + y = Y / (X + Y + Z); + + } + if (r_x) *r_x = x; + if (r_y) *r_y = y; +} + +void LightStateClass::XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb) +{ + x = (x > 0.99f ? 0.99f : (x < 0.01f ? 0.01f : x)); + y = (y > 0.99f ? 0.99f : (y < 0.01f ? 0.01f : y)); + float z = 1.0f - x - y; + + float X = x / y; + float Z = z / y; + + + + float r = X * 3.2406f - 1.5372f - Z * 0.4986f; + float g = -X * 0.9689f + 1.8758f + Z * 0.0415f; + float b = X * 0.0557f - 0.2040f + Z * 1.0570f; + float max = (r > g && r > b) ? r : (g > b) ? g : b; + r = r / max; + g = g / max; + b = b / max; + r = (r <= 0.0031308f) ? 12.92f * r : 1.055f * POW(r, (1.0f / 2.4f)) - 0.055f; + g = (g <= 0.0031308f) ? 12.92f * g : 1.055f * POW(g, (1.0f / 2.4f)) - 0.055f; + b = (b <= 0.0031308f) ? 12.92f * b : 1.055f * POW(b, (1.0f / 2.4f)) - 0.055f; + + + + + + int32_t ir = r * 255.0f + 0.5f; + int32_t ig = g * 255.0f + 0.5f; + int32_t ib = b * 255.0f + 0.5f; + if (rr) { *rr = (ir > 255 ? 255: (ir < 0 ? 0 : ir)); } + if (rg) { *rg = (ig > 255 ? 255: (ig < 0 ? 0 : ig)); } + if (rb) { *rb = (ib > 255 ? 255: (ib < 0 ? 0 : ib)); } +} + +class LightControllerClass { +private: + LightStateClass *_state; + + + bool _ct_rgb_linked = true; + bool _pwm_multi_channels = false; + +public: + LightControllerClass(LightStateClass& state) { + _state = &state; + } + + void setSubType(uint8_t sub_type) { + _state->setSubType(sub_type); + } + + inline bool setCTRGBLinked(bool ct_rgb_linked) { + bool prev = _ct_rgb_linked; + if (_pwm_multi_channels) { + _ct_rgb_linked = false; + } else { + _ct_rgb_linked = ct_rgb_linked; + } + return prev; + } + + inline bool isCTRGBLinked() { + return _ct_rgb_linked; + } + + inline bool setPWMMultiChannel(bool pwm_multi_channels) { + bool prev = _pwm_multi_channels; + _pwm_multi_channels = pwm_multi_channels; + if (pwm_multi_channels) setCTRGBLinked(false); + return prev; + } + + inline bool isPWMMultiChannel(void) { + return _pwm_multi_channels; + } + +#ifdef DEBUG_LIGHT + void debugLogs() { + uint8_t r,g,b,c,w; + _state->getActualRGBCW(&r,&g,&b,&c,&w); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::debugLogs rgb (%d %d %d) cw (%d %d)", + r, g, b, c, w); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::debugLogs lightCurrent (%d %d %d %d %d)", + Light.current_color[0], Light.current_color[1], Light.current_color[2], + Light.current_color[3], Light.current_color[4]); + } +#endif + + void loadSettings() { +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings Settings.light_color (%d %d %d %d %d - %d)", + Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], + Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings light_type/sub (%d %d)", + light_type, Light.subtype); +#endif + + _state->setCW(Settings.light_color[3], Settings.light_color[4], true); + _state->setRGB(Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); + if (!_pwm_multi_channels) { + + + uint8_t bri = _state->DimmerToBri(Settings.light_dimmer); + if (Settings.light_color[0] + Settings.light_color[1] + Settings.light_color[2] > 0) { + _state->setBriRGB(bri); + } else { + _state->setBriCT(bri); + } + } + } + + void changeCTB(uint16_t new_ct, uint8_t briCT) { + + + + + + + if ((LST_COLDWARM != Light.subtype) && (LST_RGBW > Light.subtype)) { + return; + } + _state->setCT(new_ct); + _state->setBriCT(briCT); + if (_ct_rgb_linked) { _state->setColorMode(LCM_CT); } + saveSettings(); + calcLevels(); + + } + + void changeDimmer(uint8_t dimmer) { + uint8_t bri = changeUIntScale(dimmer, 0, 100, 0, 255); + changeBri(bri); + } + + void changeBri(uint8_t bri) { + _state->setBri(bri); + saveSettings(); + calcLevels(); + } + + void changeRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { + _state->setRGB(r, g, b, keep_bri); + if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } + saveSettings(); + calcLevels(); + } + + + void calcLevels() { + uint8_t r,g,b,c,w,briRGB,briCT; + _state->getActualRGBCW(&r,&g,&b,&c,&w); + + if (_pwm_multi_channels) { + Light.current_color[0] = r; + Light.current_color[1] = g; + Light.current_color[2] = b; + Light.current_color[3] = c; + Light.current_color[4] = w; + return; + } + briRGB = _state->getBriRGB(); + briCT = _state->getBriCT(); + + Light.current_color[0] = Light.current_color[1] = Light.current_color[2] = 0; + Light.current_color[3] = Light.current_color[4] = 0; + switch (Light.subtype) { + case LST_NONE: + Light.current_color[0] = 255; + break; + case LST_SINGLE: + Light.current_color[0] = briRGB; + break; + case LST_COLDWARM: + Light.current_color[0] = c; + Light.current_color[1] = w; + break; + case LST_RGBW: + case LST_RGBWC: + if (LST_RGBWC == Light.subtype) { + Light.current_color[3] = c; + Light.current_color[4] = w; + } else { + Light.current_color[3] = briCT; + } + + case LST_RGB: + Light.current_color[0] = r; + Light.current_color[1] = g; + Light.current_color[2] = b; + break; + } + } + + void changeHSB(uint16_t hue, uint8_t sat, uint8_t briRGB) { + _state->setHS(hue, sat); + _state->setBriRGB(briRGB); + if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } + saveSettings(); + calcLevels(); + } + + + void saveSettings() { + if (Light.pwm_multi_channels) { + + _state->getActualRGBCW(&Settings.light_color[0], &Settings.light_color[1], + &Settings.light_color[2], &Settings.light_color[3], + &Settings.light_color[4]); + Settings.light_dimmer = 100; + } else { + uint8_t cm = _state->getColorMode(); + + memset(&Settings.light_color[0], 0, sizeof(Settings.light_color)); + if (LCM_RGB & cm) { + _state->getRGB(&Settings.light_color[0], &Settings.light_color[1], &Settings.light_color[2]); + Settings.light_dimmer = _state->BriToDimmer(_state->getBriRGB()); + + if (LCM_BOTH == cm) { + + _state->getActualRGBCW(nullptr, nullptr, nullptr, &Settings.light_color[3], &Settings.light_color[4]); + } + } else if (LCM_CT == cm) { + _state->getCW(&Settings.light_color[3], &Settings.light_color[4]); + Settings.light_dimmer = _state->BriToDimmer(_state->getBriCT()); + } + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::saveSettings Settings.light_color (%d %d %d %d %d - %d)", + Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], + Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); +#endif + } + + + + + void changeChannels(uint8_t *channels) { + if (LST_COLDWARM == Light.subtype) { + + uint8_t remapped_channels[5] = {0,0,0,channels[0],channels[1]}; + _state->setChannels(remapped_channels); + } else { + _state->setChannels(channels); + } + saveSettings(); + calcLevels(); + } +}; + + + +LightStateClass light_state = LightStateClass(); +LightControllerClass light_controller = LightControllerClass(light_state); + + + + + + +uint16_t ledGamma(uint8_t v, uint16_t bits_out = 8) { + uint16_t result; + + uint32_t bits_resolution = 11 - (v / 64); + int32_t bits_correction = bits_out - bits_resolution; +#ifdef XFUNC_PTR_IN_ROM + uint32_t uncorrected_value = pgm_read_byte(_ledTable + v); +#else + uint32_t uncorrected_value = _ledTable[v]; +#endif + if (0 == bits_correction) { + + result = uncorrected_value; + } else if (bits_correction > 0) { + + + uint32_t bits_mask = (1 << bits_correction) - 1; + result = (uncorrected_value << bits_correction) | bits_mask; + } else { + + + uint32_t bits_mask = (1 << -bits_correction) - 1; + result = ((uncorrected_value + bits_mask) >> -bits_correction); + } + return result; +} + +#ifdef USE_ARILUX_RF + + + + +const uint32_t ARILUX_RF_TIME_AVOID_DUPLICATE = 1000; + +const uint8_t ARILUX_RF_MAX_CHANGES = 51; +const uint32_t ARILUX_RF_SEPARATION_LIMIT = 4300; +const uint32_t ARILUX_RF_RECEIVE_TOLERANCE = 60; + +struct ARILUX { + unsigned int rf_timings[ARILUX_RF_MAX_CHANGES]; + + unsigned long rf_received_value = 0; + unsigned long rf_last_received_value = 0; + unsigned long rf_last_time = 0; + unsigned long rf_lasttime = 0; + + unsigned int rf_change_count = 0; + unsigned int rf_repeat_count = 0; + + uint8_t rf_toggle = 0; +} Arilux; + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 +#ifndef USE_WS2812_DMA +void AriluxRfInterrupt(void) ICACHE_RAM_ATTR; +#endif +#endif + +void AriluxRfInterrupt(void) +{ + unsigned long time = micros(); + unsigned int duration = time - Arilux.rf_lasttime; + + if (duration > ARILUX_RF_SEPARATION_LIMIT) { + if (abs(duration - Arilux.rf_timings[0]) < 200) { + Arilux.rf_repeat_count++; + if (Arilux.rf_repeat_count == 2) { + unsigned long code = 0; + const unsigned int delay = Arilux.rf_timings[0] / 31; + const unsigned int delayTolerance = delay * ARILUX_RF_RECEIVE_TOLERANCE / 100; + for (unsigned int i = 1; i < Arilux.rf_change_count -1; i += 2) { + code <<= 1; + if (abs(Arilux.rf_timings[i] - (delay *3)) < delayTolerance && abs(Arilux.rf_timings[i +1] - delay) < delayTolerance) { + code |= 1; + } + } + if (Arilux.rf_change_count > 49) { + Arilux.rf_received_value = code; + } + Arilux.rf_repeat_count = 0; + } + } + Arilux.rf_change_count = 0; + } + if (Arilux.rf_change_count >= ARILUX_RF_MAX_CHANGES) { + Arilux.rf_change_count = 0; + Arilux.rf_repeat_count = 0; + } + Arilux.rf_timings[Arilux.rf_change_count++] = duration; + Arilux.rf_lasttime = time; +} + +void AriluxRfHandler(void) +{ + unsigned long now = millis(); + if (Arilux.rf_received_value && !((Arilux.rf_received_value == Arilux.rf_last_received_value) && (now - Arilux.rf_last_time < ARILUX_RF_TIME_AVOID_DUPLICATE))) { + Arilux.rf_last_received_value = Arilux.rf_received_value; + Arilux.rf_last_time = now; + + uint16_t hostcode = Arilux.rf_received_value >> 8 & 0xFFFF; + if (Settings.rf_code[1][6] == Settings.rf_code[1][7]) { + Settings.rf_code[1][6] = hostcode >> 8 & 0xFF; + Settings.rf_code[1][7] = hostcode & 0xFF; + } + uint16_t stored_hostcode = Settings.rf_code[1][6] << 8 | Settings.rf_code[1][7]; + + DEBUG_DRIVER_LOG(PSTR(D_LOG_RFR D_HOST D_CODE " 0x%04X, " D_RECEIVED " 0x%06X"), stored_hostcode, Arilux.rf_received_value); + + if (hostcode == stored_hostcode) { + char command[33]; + char value = '-'; + command[0] = '\0'; + uint8_t keycode = Arilux.rf_received_value & 0xFF; + switch (keycode) { + case 1: + case 3: + snprintf_P(command, sizeof(command), PSTR(D_CMND_POWER " %d"), (1 == keycode) ? 1 : 0); + break; + case 2: + Arilux.rf_toggle++; + Arilux.rf_toggle &= 0x3; + snprintf_P(command, sizeof(command), PSTR(D_CMND_COLOR " %d"), 200 + Arilux.rf_toggle); + break; + case 4: + value = '+'; + case 7: + snprintf_P(command, sizeof(command), PSTR(D_CMND_SPEED " %c"), value); + break; + case 5: + value = '+'; + case 8: + snprintf_P(command, sizeof(command), PSTR(D_CMND_SCHEME " %c"), value); + break; + case 6: + value = '+'; + case 9: + snprintf_P(command, sizeof(command), PSTR(D_CMND_DIMMER " %c"), value); + break; + default: { + if ((keycode >= 10) && (keycode <= 21)) { + snprintf_P(command, sizeof(command), PSTR(D_CMND_COLOR " %d"), keycode -9); + } + } + } + if (strlen(command)) { + ExecuteCommand(command, SRC_LIGHT); + } + } + } + Arilux.rf_received_value = 0; +} + +void AriluxRfInit(void) +{ + if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) { + if (Settings.last_module != Settings.module) { + Settings.rf_code[1][6] = 0; + Settings.rf_code[1][7] = 0; + Settings.last_module = Settings.module; + } + Arilux.rf_received_value = 0; + + digitalWrite(pin[GPIO_ARIRFSEL], 0); + attachInterrupt(pin[GPIO_ARIRFRCV], AriluxRfInterrupt, CHANGE); + } +} + +void AriluxRfDisable(void) +{ + if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) { + detachInterrupt(pin[GPIO_ARIRFRCV]); + digitalWrite(pin[GPIO_ARIRFSEL], 1); + } +} +#endif + + + + + +extern "C" { + void os_delay_us(unsigned int); +} + +uint8_t light_pdi_pin; +uint8_t light_pdcki_pin; + +void LightDiPulse(uint8_t times) +{ + for (uint32_t i = 0; i < times; i++) { + digitalWrite(light_pdi_pin, HIGH); + digitalWrite(light_pdi_pin, LOW); + } +} + +void LightDckiPulse(uint8_t times) +{ + for (uint32_t i = 0; i < times; i++) { + digitalWrite(light_pdcki_pin, HIGH); + digitalWrite(light_pdcki_pin, LOW); + } +} + +void LightMy92x1Write(uint8_t data) +{ + for (uint32_t i = 0; i < 4; i++) { + digitalWrite(light_pdcki_pin, LOW); + digitalWrite(light_pdi_pin, (data & 0x80)); + digitalWrite(light_pdcki_pin, HIGH); + data = data << 1; + digitalWrite(light_pdi_pin, (data & 0x80)); + digitalWrite(light_pdcki_pin, LOW); + digitalWrite(light_pdi_pin, LOW); + data = data << 1; + } +} + +void LightMy92x1Init(void) +{ + uint8_t chips = 1; + if (LT_RGBWC == light_type) { + chips = 2; + } + + LightDckiPulse(chips * 32); + os_delay_us(12); + + + LightDiPulse(12); + os_delay_us(12); + for (uint32_t n = 0; n < chips; n++) { + LightMy92x1Write(0x18); + } + os_delay_us(12); + + + LightDiPulse(16); + os_delay_us(12); +} + +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 = 0; + if (LT_RGBWC == light_type) { + didx = 1; + } + + uint8_t duty[2][6] = {{ duty_r, duty_g, duty_b, duty_w, 0, 0 }, + { duty_w, duty_c, 0, duty_g, duty_r, duty_b }}; + + os_delay_us(12); + for (uint32_t channel = 0; channel < channels[didx]; channel++) { + LightMy92x1Write(duty[didx][channel]); + } + os_delay_us(12); + LightDiPulse(8); + os_delay_us(12); +} + +#ifdef USE_SM16716 +# 1281 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" +#define D_LOG_SM16716 "SM16716: " + +uint8_t sm16716_pin_clk = 100; +uint8_t sm16716_pin_dat = 100; +uint8_t sm16716_pin_sel = 100; +uint8_t sm16716_enabled = 0; + +void SM16716_SendBit(uint8_t v) +{ + + + + + + digitalWrite(sm16716_pin_dat, (v != 0) ? HIGH : LOW); + + digitalWrite(sm16716_pin_clk, HIGH); + + digitalWrite(sm16716_pin_clk, LOW); +} + +void SM16716_SendByte(uint8_t v) +{ + uint8_t mask; + + for (mask = 0x80; mask; mask >>= 1) { + SM16716_SendBit(v & mask); + } +} + +void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) +{ + if (sm16716_pin_sel < 99) { + uint8_t sm16716_should_enable = (duty_r | duty_g | duty_b); + if (!sm16716_enabled && sm16716_should_enable) { + DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color on")); + sm16716_enabled = 1; + digitalWrite(sm16716_pin_sel, HIGH); + + + delayMicroseconds(1000); + SM16716_Init(); + } + else if (sm16716_enabled && !sm16716_should_enable) { + DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color off")); + sm16716_enabled = 0; + digitalWrite(sm16716_pin_sel, LOW); + } + } + DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), duty_r, duty_g, duty_b); + + + SM16716_SendBit(1); + SM16716_SendByte(duty_r); + SM16716_SendByte(duty_g); + SM16716_SendByte(duty_b); + + + + + + SM16716_SendBit(0); + SM16716_SendByte(0); + SM16716_SendByte(0); + SM16716_SendByte(0); +} + +bool SM16716_ModuleSelected(void) +{ + sm16716_pin_clk = pin[GPIO_SM16716_CLK]; + sm16716_pin_dat = pin[GPIO_SM16716_DAT]; + sm16716_pin_sel = pin[GPIO_SM16716_SEL]; + DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), sm16716_pin_clk, sm16716_pin_dat); + return (sm16716_pin_clk < 99) && (sm16716_pin_dat < 99); +} + +void SM16716_Init(void) +{ + for (uint32_t t_init = 0; t_init < 50; ++t_init) { + SM16716_SendBit(0); + } +} + +#endif + + + +void LightInit(void) +{ + uint8_t max_scheme = LS_MAX -1; + + Light.device = devices_present; + Light.subtype = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + Light.pwm_multi_channels = Settings.flag3.pwm_multi_channels; + +#if defined(USE_WS2812) && (USE_WS2812_CTYPE > NEO_3LED) + if (LT_WS2812 == light_type) { + Light.subtype++; + } +#endif + + if ((LST_SINGLE < Light.subtype) && Light.pwm_multi_channels) { + + light_controller.setPWMMultiChannel(true); + Light.device = devices_present - Light.subtype + 1; + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightInit Light.pwm_multi_channels=%d Light.subtype=%d Light.device=%d devices_present=%d", + Light.pwm_multi_channels, Light.subtype, Light.device, devices_present); +#endif + + light_controller.setSubType(Light.subtype); + light_controller.loadSettings(); + + if (LST_SINGLE == Light.subtype) { + Settings.light_color[0] = 255; + } + if (light_type < LT_PWM6) { + for (uint32_t i = 0; i < light_type; i++) { + Settings.pwm_value[i] = 0; + if (pin[GPIO_PWM1 +i] < 99) { + pinMode(pin[GPIO_PWM1 +i], OUTPUT); + } + } + if (SONOFF_LED == my_module_type) { + if (!my_module.io[4]) { + pinMode(4, OUTPUT); + digitalWrite(4, LOW); + } + if (!my_module.io[5]) { + pinMode(5, OUTPUT); + digitalWrite(5, LOW); + } + if (!my_module.io[14]) { + pinMode(14, OUTPUT); + digitalWrite(14, LOW); + } + } + if (pin[GPIO_ARIRFRCV] < 99) { + if (pin[GPIO_ARIRFSEL] < 99) { + pinMode(pin[GPIO_ARIRFSEL], OUTPUT); + digitalWrite(pin[GPIO_ARIRFSEL], 1); + } + } + } +#ifdef USE_WS2812 + else if (LT_WS2812 == light_type) { + Ws2812Init(); + max_scheme = LS_MAX + WS2812_SCHEMES; + } +#endif +#ifdef USE_SM16716 + else if (LT_SM16716 == light_type - Light.subtype) { + + for (uint32_t i = 0; i < Light.subtype; i++) { + Settings.pwm_value[i] = 0; + if (pin[GPIO_PWM1 +i] < 99) { + pinMode(pin[GPIO_PWM1 +i], OUTPUT); + } + } + + pinMode(sm16716_pin_clk, OUTPUT); + digitalWrite(sm16716_pin_clk, LOW); + + pinMode(sm16716_pin_dat, OUTPUT); + digitalWrite(sm16716_pin_dat, LOW); + + if (sm16716_pin_sel < 99) { + pinMode(sm16716_pin_sel, OUTPUT); + digitalWrite(sm16716_pin_sel, LOW); + + } else { + + SM16716_Init(); + } + } +#endif + else { + light_pdi_pin = pin[GPIO_DI]; + light_pdcki_pin = pin[GPIO_DCKI]; + + pinMode(light_pdi_pin, OUTPUT); + pinMode(light_pdcki_pin, OUTPUT); + digitalWrite(light_pdi_pin, LOW); + digitalWrite(light_pdcki_pin, LOW); + + LightMy92x1Init(); + } + + 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 = true; + Light.wakeup_active = 0; + + LightUpdateColorMapping(); +} + +void LightUpdateColorMapping(void) +{ + uint8_t param = Settings.param[P_RGB_REMAP] & 127; + if (param > 119){ param = 0; } + + uint8_t tmp[] = {0,1,2,3,4}; + Light.color_remap[0] = tmp[param / 24]; + for (uint32_t i = param / 24; i<4; ++i){ + tmp[i] = tmp[i+1]; + } + param = param % 24; + Light.color_remap[1] = tmp[(param / 6)]; + for (uint32_t i = param / 6; i<3; ++i){ + tmp[i] = tmp[i+1]; + } + param = param % 6; + Light.color_remap[2] = tmp[(param / 2)]; + for (uint32_t i = param / 2; i<2; ++i){ + tmp[i] = tmp[i+1]; + } + param = param % 2; + Light.color_remap[3] = tmp[param]; + Light.color_remap[4] = tmp[1-param]; + + + bool ct_rgb_linked = !(Settings.param[P_RGB_REMAP] & 128); + light_controller.setCTRGBLinked(ct_rgb_linked); + + Light.update = true; + +} + +void LightSetDimmer(uint8_t dimmer) { + light_controller.changeDimmer(dimmer); +} + + +uint8_t LightGetBri(uint8_t device) { + uint8_t bri = 254; + if (Light.pwm_multi_channels) { + if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { + bri = Light.current_color[device - Light.device]; + } + } else if (device == Light.device) { + bri = light_state.getBri(); + } + return bri; +} + + + +void LightSetBri(uint8_t device, uint8_t bri) { + if (Light.pwm_multi_channels) { + if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { + Light.current_color[device - Light.device] = bri; + light_controller.changeChannels(Light.current_color); + } + } else if (device == Light.device) { + light_controller.changeBri(bri); + } +} + +void LightSetColorTemp(uint16_t ct) +{ + + + + + + + if ((LST_COLDWARM != Light.subtype) && (LST_RGBWC != Light.subtype)) { + return; + } + light_controller.changeCTB(ct, light_state.getBriCT()); +} + +uint16_t LightGetColorTemp(void) +{ + + if ((LST_COLDWARM != Light.subtype) && (LST_RGBWC != Light.subtype)) { + return 0; + } + return (light_state.getColorMode() & LCM_CT) ? light_state.getCT() : 0; +} + +void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value) +{ + + + + if (Settings.flag.light_signal) { + uint16_t signal = changeUIntScale(value, lo, hi, 0, 255); + + light_controller.changeRGB(signal, 255 - signal, 0, true); + Settings.light_scheme = 0; + if (0 == light_state.getBri()) { + light_controller.changeBri(50); + } + } +} + + +char* LightGetColor(char* scolor, boolean force_hex = false) +{ + light_controller.calcLevels(); + scolor[0] = '\0'; + for (uint32_t i = 0; i < Light.subtype; i++) { + if (!force_hex && Settings.flag.decimal_text) { + snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Light.current_color[i]); + } else { + snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%02X"), scolor, Light.current_color[i]); + } + } + return scolor; +} + +void LightPowerOn(void) +{ + if (light_state.getBri() && !(Light.power)) { + ExecuteCommandPower(Light.device, POWER_ON, SRC_LIGHT); + } +} + +void LightState(uint8_t append) +{ + char scolor[LIGHT_COLOR_SIZE]; + char scommand[33]; + + if (append) { + ResponseAppend_P(PSTR(",")); + } else { + Response_P(PSTR("{")); + } + if (!Light.pwm_multi_channels) { + GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); + ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power), light_state.getDimmer()); + + if (Light.subtype > LST_SINGLE) { + ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); + uint16_t hue; + uint8_t sat, bri; + light_state.getHSB(&hue, &sat, &bri); + sat = changeUIntScale(sat, 0, 255, 0, 100); + bri = changeUIntScale(bri, 0, 255, 0, 100); + + ResponseAppend_P(PSTR(",\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), hue,sat,bri); + + ResponseAppend_P(PSTR(",\"" D_CMND_CHANNEL "\":[" )); + for (uint32_t i = 0; i < Light.subtype; i++) { + uint8_t channel_raw = Light.current_color[i]; + uint8_t channel = changeUIntScale(channel_raw,0,255,0,100); + + if ((0 == channel) && (channel_raw > 0)) { channel = 1; } + ResponseAppend_P(PSTR("%s%d" ), (i > 0 ? "," : ""), channel); + } + ResponseAppend_P(PSTR("]")); + } + if ((LST_COLDWARM == Light.subtype) || (LST_RGBWC == Light.subtype)) { + ResponseAppend_P(PSTR(",\"" D_CMND_COLORTEMPERATURE "\":%d"), light_state.getCT()); + } + + if (append) { + if (Light.subtype >= LST_RGB) { + ResponseAppend_P(PSTR(",\"" D_CMND_SCHEME "\":%d"), Settings.light_scheme); + } + if (LT_WS2812 == light_type) { + ResponseAppend_P(PSTR(",\"" D_CMND_WIDTH "\":%d"), Settings.light_width); + } + ResponseAppend_P(PSTR(",\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""), + GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction)); + } + } else { + for (uint32_t i = 0; i < Light.subtype; i++) { + GetPowerDevice(scommand, Light.device + i, sizeof(scommand), 1); + uint32_t light_power_masked = Light.power & (1 << i); + light_power_masked = light_power_masked ? 1 : 0; + ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_CHANNEL "%d\":%d,"), scommand, GetStateText(light_power_masked), Light.device + i, + changeUIntScale(Light.current_color[i], 0, 255, 0, 100)); + } + ResponseAppend_P(PSTR("\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); + } + + if (!append) { + ResponseJsonEnd(); + } +} + +void LightPreparePower(void) +{ +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", power, Light.power); +#endif + + if (Light.pwm_multi_channels) { +# 1698 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" + } else { + if (light_state.getBri() && !(Light.power)) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); + } + } + else if (!light_state.getBri() && Light.power) { + ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); + } +#ifdef USE_DOMOTICZ + DomoticzUpdatePowerState(Light.device); +#endif + } + + if (Settings.flag3.hass_tele_on_power) { MqttPublishTeleState(); } + +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower End power=%d Light.power=%d", power, Light.power); +#endif + Light.power = power >> (Light.device - 1); + LightState(0); +} + +void LightFade(void) +{ + if (0 == Settings.light_fade) { + for (uint32_t 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 = (Light.strip_timer_counter % (Settings.light_speed -6)) ? 0 : 8; + } + if (shift) { + for (uint32_t 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; + } + } + } + } + } +} + +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 (uint32_t i = 0; i < LST_RGB; i++) { + float temp = (float)Light.entry_color[i] / dimmer + 0.5f; + Light.entry_color[i] = (uint8_t)temp; + } +} + +void LightCycleColor(int8_t direction) +{ + if (Light.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(void) +{ + bool update = false; + for (uint32_t i = 0; i < LST_RGB; i++) { + if (Light.new_color[i] != Light.current_color[i]) { + update = true; + } + } + if (!update) { + Light.wheel = random(255); + LightWheel(Light.wheel); + memcpy(Light.current_color, Light.entry_color, sizeof(Light.current_color)); + } + LightFade(); +} + +void LightSetPower(void) +{ + + Light.old_power = Light.power; + + uint32_t mask = 1; + if (Light.pwm_multi_channels) { + mask = (1 << Light.subtype) - 1; + } + uint32_t shift = Light.device - 1; + + + + + + Light.power = (XdrvMailbox.index & (mask << shift)) >> shift; + if (Light.wakeup_active) { + Light.wakeup_active--; + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightSetPower XdrvMailbox.index=%d Light.old_power=%d Light.power=%d mask=%d shift=%d", + XdrvMailbox.index, Light.old_power, Light.power, mask, shift); +#endif + if (Light.power != Light.old_power) { + Light.update = true; + } + LightAnimate(); +} + +void LightAnimate(void) +{ + uint8_t cur_col[LST_MAX]; + uint16_t light_still_on = 0; + + Light.strip_timer_counter++; + if (!Light.power) { + sleep = Settings.sleep; + Light.strip_timer_counter = 0; + for (uint32_t 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 (uint32_t i = 0; i < Light.subtype; i++) { + if (Light.new_color[i] > 0) { + Light.new_color[i] -= (Light.new_color[i] >> speed) +1; + } + } + } else { + for (uint32_t i = 0; i < Light.subtype; i++) { + Light.new_color[i] = 0; + } + } + } + else { +#ifdef PWM_LIGHTSCHEME0_IGNORE_SLEEP + sleep = (LS_POWER == Settings.light_scheme) ? Settings.sleep : 0; +#else + sleep = 0; +#endif + switch (Settings.light_scheme) { + case LS_POWER: + light_controller.calcLevels(); + LightFade(); + break; + case LS_WAKEUP: + if (2 == Light.wakeup_active) { + Light.wakeup_active = 1; + for (uint32_t i = 0; i < Light.subtype; i++) { + Light.new_color[i] = 0; + } + Light.wakeup_counter = 0; + Light.wakeup_dimmer = 0; + } + 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) { + light_state.setDimmer(Light.wakeup_dimmer); + light_controller.calcLevels(); + for (uint32_t i = 0; i < Light.subtype; i++) { + Light.new_color[i] = Light.current_color[i]; + } + } else { + Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"}")); + MqttPublishPrefixTopic_P(TELE, 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 (LT_WS2812 == light_type) { + Ws2812ShowScheme(Settings.light_scheme -LS_MAX); + } +#endif + } + } + + if ((Settings.light_scheme < LS_MAX) || !Light.power) { + + + if (Light.pwm_multi_channels) { + + for (uint32_t i = 0; i < LST_MAX; i++) { + if (0 == bitRead(Light.power,i)) { + Light.new_color[i] = 0; + } + } + + + + + + } + + if (memcmp(Light.last_color, Light.new_color, Light.subtype)) { + Light.update = true; + } + if (Light.update) { + uint16_t cur_col_10bits[LST_MAX]; + Light.update = false; + + + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col[i] = Light.last_color[i] = Light.new_color[i]; + + cur_col_10bits[i] = changeUIntScale(cur_col[i], 0, 255, 0, 1023); + } + + if (PHILIPS == my_module_type) { + calcGammaXiaomiBulbs(cur_col, cur_col_10bits); + } else if (Light.pwm_multi_channels) { + calcGammaMultiChannels(cur_col, cur_col_10bits); + } else { + calcGammaBulbs(cur_col, cur_col_10bits); + + + + if ((LST_RGBW <= Light.subtype) && (0 == Settings.rgbwwTable[4]) && (0 == cur_col[3]+cur_col[4])) { + uint32_t min_rgb_10 = min3(cur_col_10bits[0], cur_col_10bits[1], cur_col_10bits[2]); + uint8_t min_rgb = min3(cur_col[0], cur_col[1], cur_col[2]); + for (uint32_t i=0; i<3; i++) { + + cur_col_10bits[i] = changeUIntScale(cur_col_10bits[i] - min_rgb_10, 0, 255, 0, Settings.rgbwwTable[i]); + cur_col[i] = changeUIntScale(cur_col[i] - min_rgb, 0, 255, 0, Settings.rgbwwTable[i]); + } + + uint32_t white_10 = changeUIntScale(min_rgb_10, 0, 255, 0, Settings.rgbwwTable[3]); + uint32_t white = changeUIntScale(min_rgb, 0, 255, 0, Settings.rgbwwTable[3]); + if (LST_RGBW == Light.subtype) { + + cur_col_10bits[3] = white_10; + cur_col[3] = white; + } else { + + uint32_t ct = light_state.getCT(); + cur_col_10bits[4] = changeUIntScale(ct, 153, 500, 0, white_10); + cur_col_10bits[3] = white_10 - cur_col_10bits[4]; + cur_col[4] = changeUIntScale(ct, 153, 500, 0, white); + cur_col[3] = white - cur_col[4]; + } + } + } + + + for (uint32_t i = 0; i < LST_MAX; i++) { +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) + + + if ((cur_col_10bits[i] > 1008) && (cur_col_10bits[i] < 1023)) { + cur_col_10bits[i] = 1008; + } +#endif + + cur_col_10bits[i] = (cur_col_10bits[i] > 0) ? changeUIntScale(cur_col_10bits[i], 1, 1023, 1, Settings.pwm_range) : 0; + } + + + uint8_t orig_col[LST_MAX]; + uint16_t orig_col_10bits[LST_MAX]; + memcpy(orig_col, cur_col, sizeof(orig_col)); + memcpy(orig_col_10bits, cur_col_10bits, sizeof(orig_col_10bits)); + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col[i] = orig_col[Light.color_remap[i]]; + cur_col_10bits[i] = orig_col_10bits[Light.color_remap[i]]; + } + + + if (light_type < LT_PWM6) { + for (uint32_t i = 0; i < Light.subtype; i++) { + if (pin[GPIO_PWM1 +i] < 99) { + + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col_10bits[i] : cur_col_10bits[i]); + } + } + } + + char *tmp_data = XdrvMailbox.data; + uint16_t tmp_data_len = XdrvMailbox.data_len; + + XdrvMailbox.data = (char*)cur_col; + XdrvMailbox.data_len = sizeof(cur_col); + if (XdrvCall(FUNC_SET_CHANNELS)) { + + } +#ifdef USE_WS2812 + else if (LT_WS2812 == light_type) { + Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2], cur_col[3]); + } +#endif +#ifdef USE_SM16716 + else if (LT_SM16716 == light_type - Light.subtype) { + + for (uint32_t i = 3; i < Light.subtype; i++) { + if (pin[GPIO_PWM1 +i-3] < 99) { + + analogWrite(pin[GPIO_PWM1 +i-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - cur_col_10bits[i] : cur_col_10bits[i]); + } + } + + SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); + } +#endif + else if (light_type > LT_WS2812) { + + LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); + } + XdrvMailbox.data = tmp_data; + XdrvMailbox.data_len = tmp_data_len; + } + } +} + + +void calcGammaXiaomiBulbs(uint8_t cur_col[5], uint16_t cur_col_10bits[5]) { + + uint8_t cold; + light_state.getCW(&cold, nullptr); + cur_col[1] = cold; + cur_col_10bits[1] = changeUIntScale(cur_col[1], 0, 255, 0, 1023); + + uint8_t pxBri = light_state.getBriCT(); + + if (Settings.light_correction) { + cur_col[0] = ledGamma(pxBri); + cur_col_10bits[0] = ledGamma(pxBri, 10); + } else { + cur_col[0] = pxBri; + cur_col_10bits[0] = changeUIntScale(pxBri, 0, 255, 0, 1023); + } +} + + +void calcGammaMultiChannels(uint8_t cur_col[5], uint16_t cur_col_10bits[5]) { + + if (Settings.light_correction) { + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col_10bits[i] = ledGamma(cur_col[i], 10); + cur_col[i] = ledGamma(cur_col[i]); + } + } +} + +void calcGammaBulbs(uint8_t cur_col[5], uint16_t cur_col_10bits[5]) { + + if (Settings.light_correction) { + + if ((LST_COLDWARM == Light.subtype) || (LST_RGBWC == Light.subtype)) { + uint8_t w_idx[2] = {0, 1}; + if (LST_RGBWC == Light.subtype) { + w_idx[0] = 3; + w_idx[1] = 4; + } + uint16_t white_bri = cur_col[w_idx[0]] + cur_col[w_idx[1]]; + + if (white_bri <= 255) { + + uint16_t white_bri_10bits = ledGamma(white_bri, 10); + uint8_t white_bri_8bits = ledGamma(white_bri); + + cur_col_10bits[w_idx[0]] = changeUIntScale(cur_col[w_idx[0]], 0, white_bri, 0, white_bri_10bits); + cur_col_10bits[w_idx[1]] = changeUIntScale(cur_col[w_idx[1]], 0, white_bri, 0, white_bri_10bits); + cur_col[w_idx[0]] = changeUIntScale(cur_col[w_idx[0]], 0, white_bri, 0, white_bri_8bits); + cur_col[w_idx[1]] = changeUIntScale(cur_col[w_idx[1]], 0, white_bri, 0, white_bri_8bits); + } else { + cur_col_10bits[w_idx[0]] = ledGamma(cur_col[w_idx[0]], 10); + cur_col_10bits[w_idx[1]] = ledGamma(cur_col[w_idx[1]], 10); + cur_col[w_idx[0]] = ledGamma(cur_col[w_idx[0]]); + cur_col[w_idx[1]] = ledGamma(cur_col[w_idx[1]]); + } + } + + if (LST_RGB <= Light.subtype) { + for (uint32_t i = 0; i < 3; i++) { + cur_col_10bits[i] = ledGamma(cur_col[i], 10); + cur_col[i] = ledGamma(cur_col[i]); + } + } + + if (LST_COLDWARM != Light.subtype) { + cur_col_10bits[3] = ledGamma(cur_col[3], 10); + cur_col[3] = ledGamma(cur_col[3]); + } + } +} + + + + + +bool LightColorEntry(char *buffer, uint32_t buffer_length) +{ + char scolor[10]; + char *p; + char *str; + uint32_t entry_type = 0; + uint8_t value = Light.fixed_color_index; + + if (buffer[0] == '#') { + buffer++; + buffer_length--; + } + + if (Light.subtype >= LST_RGB) { + char option = (1 == buffer_length) ? buffer[0] : '\0'; + if (('+' == option) && (Light.fixed_color_index < MAX_FIXED_COLOR)) { + value++; + } + else if (('-' == option) && (Light.fixed_color_index > 1)) { + value--; + } else { + value = atoi(buffer); + } + } + + memset(&Light.entry_color, 0x00, sizeof(Light.entry_color)); + if (strstr(buffer, ",") != nullptr) { + int8_t i = 0; + for (str = strtok_r(buffer, ",", &p); str && i < 6; str = strtok_r(nullptr, ",", &p)) { + if (i < LST_MAX) { + Light.entry_color[i++] = atoi(str); + } + } + entry_type = 2; + } + else if (((2 * Light.subtype) == buffer_length) || (buffer_length > 3)) { + for (uint32_t i = 0; i < tmin((uint)(buffer_length / 2), sizeof(Light.entry_color)); i++) { + strlcpy(scolor, buffer + (i *2), 3); + Light.entry_color[i] = (uint8_t)strtol(scolor, &p, 16); + } + entry_type = 1; + } + else if ((Light.subtype >= LST_RGB) && (value > 0) && (value <= MAX_FIXED_COLOR)) { + Light.fixed_color_index = value; + memcpy_P(&Light.entry_color, &kFixedColor[value -1], 3); + entry_type = 1; + } + else if ((value > 199) && (value <= 199 + MAX_FIXED_COLD_WARM)) { + if (LST_RGBW == Light.subtype) { + memcpy_P(&Light.entry_color[3], &kFixedWhite[value -200], 1); + entry_type = 1; + } + else if (LST_COLDWARM == Light.subtype) { + memcpy_P(&Light.entry_color, &kFixedColdWarm[value -200], 2); + entry_type = 1; + } + else if (LST_RGBWC == Light.subtype) { + memcpy_P(&Light.entry_color[3], &kFixedColdWarm[value -200], 2); + entry_type = 1; + } + } + if (entry_type) { + Settings.flag.decimal_text = entry_type -1; + } + return (entry_type); +} + + + +void CmndSupportColor(void) +{ + bool valid_entry = false; + bool coldim = false; + + if (XdrvMailbox.data_len > 0) { + valid_entry = LightColorEntry(XdrvMailbox.data, XdrvMailbox.data_len); + if (valid_entry) { + if (XdrvMailbox.index <= 2) { + uint32_t old_bri = light_state.getBri(); + + light_controller.changeChannels(Light.entry_color); + if (2 == XdrvMailbox.index) { + + light_controller.changeBri(old_bri); + } + + Settings.light_scheme = 0; + coldim = true; + } else { + for (uint32_t i = 0; i < LST_RGB; i++) { + Settings.ws_color[XdrvMailbox.index -3][i] = Light.entry_color[i]; + } + } + } + } + char scolor[LIGHT_COLOR_SIZE]; + if (!valid_entry && (XdrvMailbox.index <= 2)) { + ResponseCmndChar(LightGetColor(scolor)); + } + if (XdrvMailbox.index >= 3) { + scolor[0] = '\0'; + for (uint32_t i = 0; i < LST_RGB; i++) { + if (Settings.flag.decimal_text) { + snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.ws_color[XdrvMailbox.index -3][i]); + } else { + snprintf_P(scolor, sizeof(scolor), PSTR("%s%02X"), scolor, Settings.ws_color[XdrvMailbox.index -3][i]); + } + } + ResponseCmndIdxChar(scolor); + } + if (coldim) { + LightPreparePower(); + } +} + +void CmndColor(void) +{ + if ((Light.subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { + CmndSupportColor(); + } +} + +void CmndWhite(void) +{ + if ((Light.subtype == LST_RGBW) && (XdrvMailbox.index == 1)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + uint32_t whiteBri = changeUIntScale(XdrvMailbox.payload,0,100,0,255); + char scolor[LIGHT_COLOR_SIZE]; + snprintf_P(scolor, sizeof(scolor), PSTR("0,0,0,%d"), whiteBri); + light_state.setBri(whiteBri); + XdrvMailbox.data = scolor; + XdrvMailbox.data_len = strlen(scolor); + } else { + XdrvMailbox.data_len = 0; + } + CmndSupportColor(); + } +} + +void CmndChannel(void) +{ + if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) { + bool coldim = false; + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + Light.current_color[XdrvMailbox.index - Light.device] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); + if (Light.pwm_multi_channels) { + + + + } else { + + if ((XdrvMailbox.index <= 3) && (light_controller.isCTRGBLinked())) { + Light.current_color[3] = Light.current_color[4] = 0; + } + } + light_controller.changeChannels(Light.current_color); + coldim = true; + } + ResponseCmndIdxNumber(Light.current_color[XdrvMailbox.index -1] * 100 / 255); + if (coldim) { + LightPreparePower(); + } + } +} + +void CmndHsbColor(void) +{ + if (Light.subtype >= LST_RGB) { + bool validHSB = (XdrvMailbox.data_len > 0); + if (validHSB) { + uint16_t HSB[3]; + if (strstr(XdrvMailbox.data, ",") != nullptr) { + for (uint32_t i = 0; i < 3; i++) { + char *substr; + + if (0 == i) { + substr = strtok(XdrvMailbox.data, ","); + } else { + substr = strtok(nullptr, ","); + } + if (substr != nullptr) { + HSB[i] = atoi(substr); + if (0 < i) { + HSB[i] = changeUIntScale(HSB[i], 0, 100, 0, 255); + } + } else { + validHSB = false; + } + } + } else { + uint16_t c_hue; + uint8_t c_sat; + light_state.getHSB(&c_hue, &c_sat, nullptr); + HSB[0] = c_hue; + HSB[1] = c_sat; + HSB[2] = light_state.getBri(); + + if (1 == XdrvMailbox.index) { + HSB[0] = XdrvMailbox.payload; + } else if ((XdrvMailbox.index > 1) && (XdrvMailbox.index < 4)) { + HSB[XdrvMailbox.index-1] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); + } else { + validHSB = false; + } + } + if (validHSB) { + light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); + LightPreparePower(); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR)); + } + } else { + LightState(0); + } + } +} + +#ifdef USE_WS2812 +void CmndLed(void) +{ + if ((LT_WS2812 == light_type) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= Settings.light_pixels)) { + if (XdrvMailbox.data_len > 0) { + char *p; + uint16_t idx = XdrvMailbox.index; + Ws2812ForceSuspend(); + for (char *color = strtok_r(XdrvMailbox.data, " ", &p); color; color = strtok_r(nullptr, " ", &p)) { + if (LightColorEntry(color, strlen(color))) { + Ws2812SetColor(idx, Light.entry_color[0], Light.entry_color[1], Light.entry_color[2], Light.entry_color[3]); + idx++; + if (idx > Settings.light_pixels) { break; } + } else { + break; + } + } + + Ws2812ForceUpdate(); + } + char scolor[LIGHT_COLOR_SIZE]; + ResponseCmndIdxChar(Ws2812GetColor(XdrvMailbox.index, scolor)); + } +} + +void CmndPixels(void) +{ + if (LT_WS2812 == light_type) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) { + Settings.light_pixels = XdrvMailbox.payload; + Settings.light_rotation = 0; + Ws2812Clear(); + Light.update = true; + } + ResponseCmndNumber(Settings.light_pixels); + } +} + +void CmndRotation(void) +{ + if (LT_WS2812 == light_type) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings.light_pixels)) { + Settings.light_rotation = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.light_rotation); + } +} + +void CmndWidth(void) +{ + if ((LT_WS2812 == light_type) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { + if (1 == XdrvMailbox.index) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 4)) { + Settings.light_width = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.light_width); + } else { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32)) { + Settings.ws_width[XdrvMailbox.index -2] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.ws_width[XdrvMailbox.index -2]); + } + } +} +#endif + +void CmndScheme(void) +{ + if (Light.subtype >= LST_RGB) { + uint32_t max_scheme = (LT_WS2812 == light_type) ? LS_MAX + WS2812_SCHEMES : LS_MAX -1; + if (1 == XdrvMailbox.data_len) { + if (('+' == XdrvMailbox.data[0]) && (Settings.light_scheme < max_scheme)) { + XdrvMailbox.payload = Settings.light_scheme + ((0 == Settings.light_scheme) ? 2 : 1); + } + else if (('-' == XdrvMailbox.data[0]) && (Settings.light_scheme > 0)) { + XdrvMailbox.payload = Settings.light_scheme - ((2 == Settings.light_scheme) ? 2 : 1); + } + } + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= max_scheme)) { + Settings.light_scheme = XdrvMailbox.payload; + if (LS_WAKEUP == Settings.light_scheme) { + Light.wakeup_active = 3; + } + LightPowerOn(); + Light.strip_timer_counter = 0; + + if (Settings.flag3.hass_tele_on_power) { MqttPublishTeleState(); } + } + ResponseCmndNumber(Settings.light_scheme); + } +} + +void CmndWakeup(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + Settings.light_dimmer = XdrvMailbox.payload; + } + Light.wakeup_active = 3; + Settings.light_scheme = LS_WAKEUP; + LightPowerOn(); + ResponseCmndChar(D_JSON_STARTED); +} + +void CmndColorTemperature(void) +{ + if ((LST_COLDWARM == Light.subtype) || (LST_RGBWC == Light.subtype)) { + uint32_t ct = light_state.getCT(); + if (1 == XdrvMailbox.data_len) { + if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (ct > (500-34)) ? 500 : ct + 34; + } + else if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (ct < (153+34)) ? 153 : ct - 34; + } + } + if ((XdrvMailbox.payload >= 153) && (XdrvMailbox.payload <= 500)) { + light_controller.changeCTB(XdrvMailbox.payload, light_state.getBri()); + LightPreparePower(); + } else { + ResponseCmndNumber(ct); + } + } +} + +void CmndDimmer(void) +{ + uint32_t dimmer = light_state.getDimmer(); + if (1 == XdrvMailbox.data_len) { + if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (dimmer > 89) ? 100 : dimmer + 10; + } + else if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (dimmer < 11) ? 1 : dimmer - 10; + } + } + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + light_controller.changeDimmer(XdrvMailbox.payload); + Light.update = true; + LightPreparePower(); + } else { + ResponseCmndNumber(Settings.light_dimmer); + } +} + +void CmndLedTable(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + switch (XdrvMailbox.payload) { + case 0: + case 1: + Settings.light_correction = XdrvMailbox.payload; + break; + case 2: + Settings.light_correction ^= 1; + break; + } + Light.update = true; + } + ResponseCmndStateText(Settings.light_correction); +} + +void CmndRgbwwTable(void) +{ + if ((XdrvMailbox.data_len > 0)) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + for (uint32_t i = 0; i < LST_RGBWC; i++) { + char *substr; + + if (0 == i) { + substr = strtok(XdrvMailbox.data, ","); + } else { + substr = strtok(nullptr, ","); + } + if (substr != nullptr) { + Settings.rgbwwTable[i] = atoi(substr); + } + } + } + Light.update = true; + } + char scolor[LIGHT_COLOR_SIZE]; + scolor[0] = '\0'; + for (uint32_t i = 0; i < LST_RGBWC; i++) { + snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); + } + ResponseCmndIdxChar(scolor); +} + +void CmndFade(void) +{ + switch (XdrvMailbox.payload) { + case 0: + case 1: + Settings.light_fade = XdrvMailbox.payload; + break; + case 2: + Settings.light_fade ^= 1; + break; + } + ResponseCmndStateText(Settings.light_fade); +} + +void CmndSpeed(void) +{ + if (1 == XdrvMailbox.data_len) { + if (('+' == XdrvMailbox.data[0]) && (Settings.light_speed > 1)) { + XdrvMailbox.payload = Settings.light_speed -1; + } + else if (('-' == XdrvMailbox.data[0]) && (Settings.light_speed < STATES)) { + XdrvMailbox.payload = Settings.light_speed +1; + } + } + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= STATES)) { + Settings.light_speed = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.light_speed); +} + +void CmndWakeupDuration(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3001)) { + Settings.light_wakeup = XdrvMailbox.payload; + Light.wakeup_active = 0; + } + ResponseCmndNumber(Settings.light_wakeup); +} + +void CmndUndocA(void) +{ + char scolor[LIGHT_COLOR_SIZE]; + LightGetColor(scolor, true); + scolor[6] = '\0'; + Response_P(PSTR("%s,%d,%d,%d,%d,%d"), scolor, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width); + MqttPublishPrefixTopic_P(STAT, XdrvMailbox.topic); + mqtt_data[0] = '\0'; +} + + + + + +bool Xdrv04(uint8_t function) +{ + bool result = false; + + if (light_type) { + switch (function) { + case FUNC_PRE_INIT: + LightInit(); + break; + case FUNC_EVERY_50_MSECOND: + LightAnimate(); +#ifdef USE_ARILUX_RF + if (pin[GPIO_ARIRFRCV] < 99) { AriluxRfHandler(); } +#endif + break; +#ifdef USE_ARILUX_RF + case FUNC_EVERY_SECOND: + if (10 == uptime) { AriluxRfInit(); } + break; +#endif + case FUNC_SET_POWER: + LightSetPower(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kLightCommands, LightCommand); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_05_irremote.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_05_irremote.ino" +#if defined(USE_IR_REMOTE) && !defined(USE_IR_REMOTE_FULL) + + + + +#define XDRV_05 5 + +#include + +enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC }; + +const char kIrRemoteCommands[] PROGMEM = "|" +#ifdef USE_IR_HVAC + D_CMND_IRHVAC "|" +#endif + D_CMND_IRSEND ; + +void (* const IrRemoteCommand[])(void) PROGMEM = { +#ifdef USE_IR_HVAC + &CmndIrHvac, +#endif + &CmndIrSend }; + + +static const uint8_t MAX_STANDARD_IR = SHARP; +enum IrVendors { IR_BASE = MAX_STANDARD_IR, +#ifdef USE_IR_SEND_PIONEER + IR_PIONEER, +#endif +}; +const char kIrRemoteProtocols[] PROGMEM = + "UNKNOWN|RC5|RC6|NEC|SONY|PANASONIC|JVC|SAMSUNG|WHYNTER|AIWA_RC_T501|LG|SANYO|MITSUBISHI|DISH|SHARP" + +#ifdef USE_IR_SEND_PIONEER + "|PIONEER" +#endif + ; + + + + + +#include + +IRsend *irsend = nullptr; +bool irsend_active = false; + +void IrSendInit(void) +{ + irsend = new IRsend(pin[GPIO_IRSEND]); + irsend->begin(); +} + +#ifdef USE_IR_RECEIVE + + + + +const bool IR_RCV_SAVE_BUFFER = false; +const uint32_t IR_TIME_AVOID_DUPLICATE = 500; + +#include + +IRrecv *irrecv = nullptr; + +unsigned long ir_lasttime = 0; + +void IrReceiveUpdateThreshold() +{ + if (irrecv != nullptr) { + if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); + } +} + +void IrReceiveInit(void) +{ + + irrecv = new IRrecv(pin[GPIO_IRRECV], IR_RCV_BUFFER_SIZE, IR_RCV_TIMEOUT, IR_RCV_SAVE_BUFFER); + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); + irrecv->enableIRIn(); + + +} + +void IrReceiveCheck(void) +{ + char sirtype[14]; + int8_t iridx = 0; + + decode_results results; + + if (irrecv->decode(&results)) { + char hvalue[65]; + + iridx = results.decode_type; + if ((iridx < 0) || (iridx > 14)) { iridx = 0; } + + if (iridx) { + if (results.bits > 64) { + + uint32_t digits2 = results.bits / 8; + if (results.bits % 8) { digits2++; } + ToHex_P((unsigned char*)results.state, digits2, hvalue, sizeof(hvalue)); + } else { + Uint64toHex(results.value, hvalue, results.bits); + } + } else { + Uint64toHex(results.value, hvalue, 32); + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value 0x%s, Decode %d"), + irsend_active, results.rawlen, results.overflow, results.bits, hvalue, results.decode_type); + + unsigned long now = millis(); + + if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { + ir_lasttime = now; + + char svalue[64]; + if (Settings.flag.ir_receive_decimal) { + ulltoa(results.value, svalue, 10); + } else { + snprintf_P(svalue, sizeof(svalue), PSTR("\"0x%s\""), hvalue); + } + ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d"), + GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits); + if (iridx) { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_DATA "\":%s"), svalue); + } else { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_HASH "\":%s"), svalue); + } + + if (Settings.flag3.receive_raw) { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); + uint16_t i; + for (i = 1; i < results.rawlen; i++) { + if (i > 1) { ResponseAppend_P(PSTR(",")); } + uint32_t usecs; + for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { + ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); + } + ResponseAppend_P(PSTR("%d"), usecs); + if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } + } + uint16_t extended_length = results.rawlen - 1; + for (uint32_t j = 0; j < results.rawlen - 1; j++) { + uint32_t usecs = results.rawbuf[j] * kRawTick; + + extended_length += (usecs / (UINT16_MAX + 1)) * 2; + } + ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); + } + + ResponseJsonEndEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); + + if (iridx) { + XdrvRulesProcess(); +#ifdef USE_DOMOTICZ + unsigned long value = results.value | (iridx << 28); + DomoticzSensor(DZ_COUNT, value); +#endif + } + } + + irrecv->resume(); + } +} +#endif + + +#ifdef USE_IR_HVAC + + + + +enum IrHvacVendors { VNDR_TOSHIBA, VNDR_MITSUBISHI, VNDR_LG, VNDR_FUJITSU, VNDR_MIDEA }; +const char kIrHvacVendors[] PROGMEM = "Toshiba|Mitsubishi|LG|Fujitsu|Midea" ; + +const char kFanSpeedOptions[] = "A12345S"; +const char kHvacModeOptions[] = "HDCA"; + +#ifdef USE_IR_HVAC_TOSHIBA + + + + +const uint16_t HVAC_TOSHIBA_HDR_MARK = 4400; +const uint16_t HVAC_TOSHIBA_HDR_SPACE = 4300; +const uint16_t HVAC_TOSHIBA_BIT_MARK = 543; +const uint16_t HVAC_TOSHIBA_ONE_SPACE = 1623; +const uint16_t HVAC_MISTUBISHI_ZERO_SPACE = 472; +const uint16_t HVAC_TOSHIBA_RPT_MARK = 440; +const uint16_t HVAC_TOSHIBA_RPT_SPACE = 7048; +const uint8_t HVAC_TOSHIBA_DATALEN = 9; + +uint8_t IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +{ + uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; + uint8_t data[HVAC_TOSHIBA_DATALEN] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}; + + char *p; + uint8_t mode; + + if (HVAC_Mode == nullptr) { + p = (char *)kHvacModeOptions; + } + else { + p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); + } + if (!p) { + return IE_SYNTAX_IRHVAC; + } + data[6] = (p - kHvacModeOptions) ^ 0x03; + + if (!HVAC_Power) { + data[6] = (uint8_t)0x07; + } + + if (HVAC_FanMode == nullptr) { + p = (char *)kFanSpeedOptions; + } + else { + p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); + } + if (!p) { + return IE_SYNTAX_IRHVAC; + } + mode = p - kFanSpeedOptions + 1; + if ((1 == mode) || (7 == mode)) { + mode = 0; + } + mode = mode << 5; + data[6] = data[6] | mode; + + uint8_t Temp; + if (HVAC_Temp > 30) { + Temp = 30; + } + else if (HVAC_Temp < 17) { + Temp = 17; + } + else { + Temp = HVAC_Temp; + } + data[5] = (uint8_t)(Temp - 17) << 4; + + data[HVAC_TOSHIBA_DATALEN - 1] = 0; + for (uint32_t x = 0; x < HVAC_TOSHIBA_DATALEN - 1; x++) { + data[HVAC_TOSHIBA_DATALEN - 1] = (uint8_t)data[x] ^ data[HVAC_TOSHIBA_DATALEN - 1]; + } + + int i = 0; + uint8_t mask = 1; + + + rawdata[i++] = HVAC_TOSHIBA_HDR_MARK; + rawdata[i++] = HVAC_TOSHIBA_HDR_SPACE; + + + for (uint32_t b = 0; b < HVAC_TOSHIBA_DATALEN; b++) { + for (mask = B10000000; mask > 0; mask >>= 1) { + if (data[b] & mask) { + rawdata[i++] = HVAC_TOSHIBA_BIT_MARK; + rawdata[i++] = HVAC_TOSHIBA_ONE_SPACE; + } + else { + rawdata[i++] = HVAC_TOSHIBA_BIT_MARK; + rawdata[i++] = HVAC_MISTUBISHI_ZERO_SPACE; + } + } + } + + + rawdata[i++] = HVAC_TOSHIBA_RPT_MARK; + rawdata[i++] = HVAC_TOSHIBA_RPT_SPACE; + + + irsend->sendRaw(rawdata, i, 38); + irsend->sendRaw(rawdata, i, 38); + + + return IE_NO_ERROR; +} +#endif + +#ifdef USE_IR_HVAC_MIDEA + + + + + + + +const uint16_t HVAC_MIDEA_HDR_MARK = 4420; +const uint16_t HVAC_MIDEA_HDR_SPACE = 4420; +const uint16_t HVAC_MIDEA_BIT_MARK = 553; +const uint16_t HVAC_MIDEA_ONE_SPACE = 1660; +const uint16_t HVAC_MIDEA_ZERO_SPACE = 553; +const uint16_t HVAC_MIDEA_RPT_MARK = 553; +const uint16_t HVAC_MIDEA_RPT_SPACE = 5530; +const uint8_t HVAC_MIDEA_DATALEN = 3; + +uint8_t IrHvacMidea(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +{ + uint16_t rawdata[2 + 2 * 2 * 8 * HVAC_MIDEA_DATALEN + 2]; + uint8_t data[HVAC_MIDEA_DATALEN] = {0xB2, 0x00, 0x00}; + + char *p; + uint8_t mode; + + if (!HVAC_Power) { + data[1] = 0x7B; + data[2] = 0xE0; + } else { + + if (HVAC_FanMode == nullptr) { + p = (char*)kFanSpeedOptions; + } + else { + p = (char*)HVAC_FanMode; + } + + switch(p[0]) { + case '1': data[1] = 0xBF; break; + case '2': data[1] = 0x9F; break; + case '3': data[1] = 0x5F; break; + case '4': data[1] = 0x3F; break; + case '5': data[1] = 0x1F; break; + case 'A': data[1] = 0x1F; break; + default: return IE_SYNTAX_IRHVAC; + } + + + uint8_t Temp; + if (HVAC_Temp > 30) { + Temp = 30; + } + else if (HVAC_Temp < 17) { + Temp = 17; + } + else { + Temp = HVAC_Temp-17; + } + if (10 == Temp) { + data[2] = 0x90; + } else if (11 == Temp) { + data[2] = 0x80; + } else { + Temp = (Temp >> 1) ^Temp; + data[2] = (Temp << 4); + } + + + if (HVAC_Mode == nullptr) { + p = (char*)kHvacModeOptions + 3; + } + else { + p = (char*)HVAC_Mode; + } + switch(toupper(p[0])) { + case 'D': data[2] = 0xE4; break; + case 'C': data[2] = 0x0 | data[2]; break; + case 'A': data[2] = 0x8 | data[2]; data[1] = 0x1F; break; + case 'H': data[2] = 0xC | data[2]; break; + default: return IE_SYNTAX_IRHVAC; + } + } + + int i = 0; + uint8_t mask = 1; + + + rawdata[i++] = HVAC_MIDEA_HDR_MARK; + rawdata[i++] = HVAC_MIDEA_HDR_SPACE; + + + for (int b = 0; b < HVAC_MIDEA_DATALEN; b++) { + for (mask = B10000000; mask > 0; mask >>= 1) { + if (data[b] & mask) { + rawdata[i++] = HVAC_MIDEA_BIT_MARK; + rawdata[i++] = HVAC_MIDEA_ONE_SPACE; + } + else { + rawdata[i++] = HVAC_MIDEA_BIT_MARK; + rawdata[i++] = HVAC_MIDEA_ZERO_SPACE; + } + } + for (mask = B10000000; mask > 0; mask >>= 1) { + if (data[b] & mask) { + rawdata[i++] = HVAC_MIDEA_BIT_MARK; + rawdata[i++] = HVAC_MIDEA_ZERO_SPACE; + } + else { + rawdata[i++] = HVAC_MIDEA_BIT_MARK; + rawdata[i++] = HVAC_MIDEA_ONE_SPACE; + } + } + + } + + + rawdata[i++] = HVAC_MIDEA_RPT_MARK; + rawdata[i++] = HVAC_MIDEA_RPT_SPACE; + + + irsend->sendRaw(rawdata, i, 38); + irsend->sendRaw(rawdata, i, 38); + + return IE_NO_ERROR; +} +#endif + +#ifdef USE_IR_HVAC_MITSUBISHI + + + + +#include + +uint8_t IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +{ + char *p; + uint8_t mode; + + IRMitsubishiAC mitsubir(pin[GPIO_IRSEND]); + + mitsubir.stateReset(); + + if (HVAC_Mode == nullptr) { + p = (char *)kHvacModeOptions; + } + else { + p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); + } + if (!p) { + return IE_SYNTAX_IRHVAC; + } + mode = (p - kHvacModeOptions + 1) << 3; + mitsubir.setMode(mode); + + mitsubir.setPower(HVAC_Power); + + if (HVAC_FanMode == nullptr) { + p = (char *)kFanSpeedOptions; + } + else { + p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); + } + if (!p) { + return IE_SYNTAX_IRHVAC; + } + mode = p - kFanSpeedOptions; + mitsubir.setFan(mode); + + mitsubir.setTemp(HVAC_Temp); + mitsubir.setVane(MITSUBISHI_AC_VANE_AUTO); + mitsubir.send(); + + + + + return IE_NO_ERROR; +} +#endif + +#ifdef USE_IR_HVAC_LG + + + + +const uint8_t HVAC_LG_DATALEN = 7; + +uint8_t IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +{ + uint32_t LG_Code; + uint8_t data[HVAC_LG_DATALEN]; + static bool hvacOn = false; + char *p; + uint8_t mode; + uint8_t Temp; + + + data[0] = 0x08; + data[1] = 0x08; + data[2] = 0x00; + + if (!HVAC_Power) { + data[2] = (uint8_t)0x0C; + data[3] = (uint8_t)0x00; + data[4] = (uint8_t)0x00; + data[5] = (uint8_t)0x05; + data[6] = (uint8_t)0x01; + hvacOn = false; + } + + else { + + + if (HVAC_Mode == nullptr) { + p = (char *)kHvacModeOptions; + } + else { + p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); + } + if (!p) { + return IE_SYNTAX_IRHVAC; + } + mode = (p - kHvacModeOptions) ^ 0x03; + switch (mode) { + case 0: + data[3] = 11; + break; + case 1: + data[3] = 8; + break; + case 2: + data[3] = 9; + break; + case 3: + data[3] = 12; + break; + } + if (!hvacOn) { + data[3] = data[3] & 7; + hvacOn = true; + } + + + + + if (HVAC_Temp > 30) { + Temp = 30; + } + else if (HVAC_Temp < 18) { + Temp = 18; + } + else { + Temp = HVAC_Temp; + } + data[4] = (uint8_t)(Temp - 15); + + + if (HVAC_FanMode == nullptr) { + p = (char *)kFanSpeedOptions; + } + else { + p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); + } + if (!p) { + return IE_SYNTAX_IRHVAC; + } + mode = p - kFanSpeedOptions; + if ((mode == 0) || (mode > 3)) { + data[5] = 5; + } + else { + data[5] = (mode * 2) - 2; + } + + + + + data[6] = (data[3] + data[4] + data[5]) & 0x0f; + + } + + LG_Code = data[0] << 4; + for (uint32_t i = 1; i < 6; i++) { + LG_Code = (LG_Code + data[i]) << 4; + } + LG_Code = LG_Code + data[6]; + + + + + irsend->sendLG(LG_Code, 28); + + return IE_NO_ERROR; +} +#endif + +#ifdef USE_IR_HVAC_FUJITSU + + + + +#include + +uint8_t IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +{ + const char kFujitsuHvacModeOptions[] = "HDCAF"; + + + + IRFujitsuAC ac(pin[GPIO_IRSEND]); + + if (0 == HVAC_Power) { + ac.off(); + ac.send(); + return IE_NO_ERROR; + } + + uint8_t modes[5] = {FUJITSU_AC_MODE_HEAT, FUJITSU_AC_MODE_DRY, FUJITSU_AC_MODE_COOL, FUJITSU_AC_MODE_AUTO, FUJITSU_AC_MODE_FAN}; + uint8_t fanModes[7] = {FUJITSU_AC_FAN_AUTO, FUJITSU_AC_FAN_LOW, FUJITSU_AC_FAN_MED, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_QUIET}; + ac.setCmd(FUJITSU_AC_CMD_TURN_ON); + ac.setSwing(FUJITSU_AC_SWING_VERT); + + char *p; + if (nullptr == HVAC_Mode) { + p = (char *)kFujitsuHvacModeOptions; + } + else { + p = strchr(kFujitsuHvacModeOptions, toupper(HVAC_Mode[0])); + } + if (!p) { + return IE_SYNTAX_IRHVAC; + } + ac.setMode(modes[p - kFujitsuHvacModeOptions]); + + if (HVAC_FanMode == nullptr) { + p = (char *)kFanSpeedOptions; + } + else { + p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); + } + if (!p) { + return IE_SYNTAX_IRHVAC; + } + ac.setFanSpeed(fanModes[p - kFanSpeedOptions]); + + ac.setTemp(HVAC_Temp); + ac.send(); + + return IE_NO_ERROR; +} +#endif + + + +uint32_t IrRemoteCmndIrHvacJson(void) +{ + + const char *HVAC_Mode; + const char *HVAC_FanMode; + const char *HVAC_Vendor; + char parm_uc[12]; + int HVAC_Temp = 21; + bool HVAC_Power = true; + + char dataBufUc[XdrvMailbox.data_len]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { + return IE_INVALID_JSON; + } + + StaticJsonBuffer<164> jsonBufer; + JsonObject &root = jsonBufer.parseObject(dataBufUc); + if (!root.success()) { + return IE_INVALID_JSON; + } + + HVAC_Vendor = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR))]; + HVAC_Power = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_POWER))]; + HVAC_Mode = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODE))]; + HVAC_FanMode = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FANSPEED))]; + HVAC_Temp = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TEMP))]; + + + + char vendor[20]; + int vendor_code = GetCommandCode(vendor, sizeof(vendor), HVAC_Vendor, kIrHvacVendors); + irsend_active = true; + switch (vendor_code) { +#ifdef USE_IR_HVAC_TOSHIBA + case VNDR_TOSHIBA: + return IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); +#endif +#ifdef USE_IR_HVAC_MITSUBISHI + case VNDR_MITSUBISHI: + return IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); +#endif +#ifdef USE_IR_HVAC_LG + case VNDR_LG: + return IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); +#endif +#ifdef USE_IR_HVAC_FUJITSU + case VNDR_FUJITSU: + return IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); +#endif +#ifdef USE_IR_HVAC_MIDEA + case VNDR_MIDEA: + return IrHvacMidea(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); +#endif + default: + irsend_active = false; + } + + return IE_SYNTAX_IRHVAC; +} + +void CmndIrHvac(void) +{ + uint8_t error = IE_SYNTAX_IRHVAC; + + if (XdrvMailbox.data_len) { + error = IrRemoteCmndIrHvacJson(); + } + IrRemoteCmndResponse(error); +} + +#endif + + + + + +uint32_t IrRemoteCmndIrSendRaw(void) +{ + + + + + + + + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + if (p == nullptr) { + return IE_INVALID_RAWDATA; + } + + + uint16_t repeat = XdrvMailbox.index > 0 ? XdrvMailbox.index - 1 : 0; + + uint16_t freq = atoi(str); + if (!freq && (*str != '0')) { + uint16_t count = 0; + char *q = p; + for (; *q; count += (*q++ == ',')); + if (count < 2) { + return IE_INVALID_RAWDATA; + } + + uint16_t parm[count]; + for (uint32_t i = 0; i < count; i++) { + parm[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); + if (!parm[i]) { + if (!i) { + parm[0] = 38000; + } else { + return IE_INVALID_RAWDATA; + } + } + } + + uint16_t i = 0; + if (count < 4) { + + uint16_t mark = parm[1] *2; + if (3 == count) { + if (parm[2] < parm[1]) { + + mark = parm[1] * parm[2]; + } else { + + mark = parm[2]; + } + } + uint16_t raw_array[strlen(p)]; + for (; *p; *p++) { + if (*p == '0') { + raw_array[i++] = parm[1]; + } + else if (*p == '1') { + raw_array[i++] = mark; + } + } + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, i, parm[0]); + if (r < repeat) { + irsend->space(40000); + } + } + } + else if (6 == count) { + + uint16_t raw_array[strlen(p)*2+3]; + raw_array[i++] = parm[1]; + raw_array[i++] = parm[2]; + uint32_t inter_message_32 = (parm[1] + parm[2]) * 3; + uint16_t inter_message = (inter_message_32 > 65000) ? 65000 : inter_message_32; + for (; *p; *p++) { + if (*p == '0') { + raw_array[i++] = parm[3]; + raw_array[i++] = parm[4]; + } + else if (*p == '1') { + raw_array[i++] = parm[3]; + raw_array[i++] = parm[5]; + } + } + raw_array[i++] = parm[3]; + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, i, parm[0]); + if (r < repeat) { + irsend->space(inter_message); + } + } + } + else { + return IE_INVALID_RAWDATA; + } + } else { + if (!freq) { freq = 38000; } + uint16_t count = 0; + char *q = p; + for (; *q; count += (*q++ == ',')); + if (0 == count) { + return IE_INVALID_RAWDATA; + } + + + count++; + if (count < 200) { + uint16_t raw_array[count]; + for (uint32_t i = 0; i < count; i++) { + raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); + } + + + + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, count, freq); + } + } else { + uint16_t *raw_array = reinterpret_cast(malloc(count * sizeof(uint16_t))); + if (raw_array == nullptr) { + return IE_INVALID_RAWDATA; + } + + for (uint32_t i = 0; i < count; i++) { + raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); + } + + + + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, count, freq); + } + free(raw_array); + } + } + + return IE_NO_ERROR; +} + +uint32_t IrRemoteCmndIrSendJson(void) +{ + + + + + char dataBufUc[XdrvMailbox.data_len]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { + return IE_INVALID_JSON; + } + + StaticJsonBuffer<140> jsonBuf; + JsonObject &root = jsonBuf.parseObject(dataBufUc); + if (!root.success()) { + return IE_INVALID_JSON; + } + + + + char parm_uc[10]; + const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; + uint16_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; + uint64_t data = strtoull(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); + uint16_t repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT))]; + + if (XdrvMailbox.index > repeat + 1) { + repeat = XdrvMailbox.index - 1; + } + if (!(protocol && bits)) { + return IE_SYNTAX_IRSEND; + } + + char protocol_text[20]; + int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); + + char dvalue[64]; + char hvalue[20]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %s (0x%s), repeat %d, protocol_code %d"), + protocol_text, protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat, protocol_code); + + irsend_active = true; + switch (protocol_code) { +#ifdef USE_IR_SEND_RC5 + case RC5: + irsend->sendRC5(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_RC6 + case RC6: + irsend->sendRC6(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_NEC + case NEC: + irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits, repeat); break; +#endif +#ifdef USE_IR_SEND_SONY + case SONY: + irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, repeat > kSonyMinRepeat ? repeat : kSonyMinRepeat); break; +#endif +#ifdef USE_IR_SEND_PANASONIC + case PANASONIC: + irsend->sendPanasonic64(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_JVC + case JVC: + irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, repeat > 1 ? repeat : 1); break; +#endif +#ifdef USE_IR_SEND_SAMSUNG + case SAMSUNG: + irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits, repeat); break; +#endif +#ifdef USE_IR_SEND_WHYNTER + case WHYNTER: + irsend->sendWhynter(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_AIWA + case AIWA_RC_T501: + irsend->sendAiwaRCT501(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_LG + case LG: + irsend->sendLG(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_SANYO + case SANYO: + irsend->sendSanyoLC7461(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_MITSUBISHI + case MITSUBISHI: + irsend->sendMitsubishi(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_DISH + case DISH: + irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits, repeat > kDishMinRepeat ? repeat : kDishMinRepeat); break; +#endif +#ifdef USE_IR_SEND_SHARP + case SHARP: + irsend->sendSharpRaw(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_PIONEER + case IR_PIONEER: + irsend->sendPioneer(data, bits, repeat); break; +#endif + default: + irsend_active = false; + ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); + } + + return IE_NO_ERROR; +} + +void CmndIrSend(void) +{ + uint8_t error = IE_SYNTAX_IRSEND; + + if (XdrvMailbox.data_len) { + + if (strstr(XdrvMailbox.data, "{") == nullptr) { + error = IrRemoteCmndIrSendRaw(); + } else { + error = IrRemoteCmndIrSendJson(); + } + } + IrRemoteCmndResponse(error); +} + +void IrRemoteCmndResponse(uint32_t error) +{ + switch (error) { + case IE_INVALID_RAWDATA: + ResponseCmndChar(D_JSON_INVALID_RAWDATA); + break; + case IE_INVALID_JSON: + ResponseCmndChar(D_JSON_INVALID_JSON); + break; + case IE_SYNTAX_IRSEND: + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); + break; +#ifdef USE_IR_HVAC + case IE_SYNTAX_IRHVAC: + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); + break; +#endif + default: + ResponseCmndDone(); + } +} + + + + + +bool Xdrv05(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { + switch (function) { + case FUNC_PRE_INIT: + if (pin[GPIO_IRSEND] < 99) { + IrSendInit(); + } +#ifdef USE_IR_RECEIVE + if (pin[GPIO_IRRECV] < 99) { + IrReceiveInit(); + } +#endif + break; + case FUNC_EVERY_50_MSECOND: +#ifdef USE_IR_RECEIVE + if (pin[GPIO_IRRECV] < 99) { + IrReceiveCheck(); + } +#endif + irsend_active = false; + break; + case FUNC_COMMAND: + if (pin[GPIO_IRSEND] < 99) { + result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); + } + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_05_irremote_full.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_05_irremote_full.ino" +#ifdef USE_IR_REMOTE_FULL + + + + +#define XDRV_05 5 + +#include +#include +#include +#include +#include + +enum IrErrors { IE_RESPONSE_PROVIDED, IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC, + IE_UNSUPPORTED_HVAC, IE_UNSUPPORTED_PROTOCOL }; + +const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRHVAC "|" D_CMND_IRSEND ; + +void (* const IrRemoteCommand[])(void) PROGMEM = { &CmndIrHvac, &CmndIrSend }; + + + + + +IRsend *irsend = nullptr; +bool irsend_active = false; + +void IrSendInit(void) +{ + irsend = new IRsend(pin[GPIO_IRSEND]); + irsend->begin(); +} + + + +uint8_t reverseBitsInByte(uint8_t b) { + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + return b; +} + + +uint64_t reverseBitsInBytes64(uint64_t b) { + union { + uint8_t b[8]; + uint64_t i; + } a; + a.i = b; + for (uint32_t i=0; i<8; i++) { + a.b[i] = reverseBitsInByte(a.b[i]); + } + return a.i; +} + + + + + +const bool IR_FULL_RCV_SAVE_BUFFER = false; +const uint32_t IR_TIME_AVOID_DUPLICATE = 500; + + + + +const uint16_t IR_FULL_BUFFER_SIZE = 1024; + + + +const uint8_t IR__FULL_RCV_TIMEOUT = 50; + +IRrecv *irrecv = nullptr; + +unsigned long ir_lasttime = 0; + +void IrReceiveUpdateThreshold() +{ + if (irrecv != nullptr) { + if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); + } +} + +void IrReceiveInit(void) +{ + + irrecv = new IRrecv(pin[GPIO_IRRECV], IR_FULL_BUFFER_SIZE, IR__FULL_RCV_TIMEOUT, IR_FULL_RCV_SAVE_BUFFER); + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); + irrecv->enableIRIn(); +} + +String sendACJsonState(const stdAc::state_t &state) { + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + json[D_JSON_IRHVAC_VENDOR] = typeToString(state.protocol); + json[D_JSON_IRHVAC_MODEL] = state.model; + json[D_JSON_IRHVAC_POWER] = IRac::boolToString(state.power); + json[D_JSON_IRHVAC_MODE] = IRac::opmodeToString(state.mode); + + if (state.mode == stdAc::opmode_t::kOff || !state.power) { + json[D_JSON_IRHVAC_MODE] = IRac::opmodeToString(stdAc::opmode_t::kOff); + json[D_JSON_IRHVAC_POWER] = IRac::boolToString(false); + } + json[D_JSON_IRHVAC_CELSIUS] = IRac::boolToString(state.celsius); + if (floorf(state.degrees) == state.degrees) { + json[D_JSON_IRHVAC_TEMP] = floorf(state.degrees); + } else { + json[D_JSON_IRHVAC_TEMP] = RawJson(String(state.degrees, 1)); + } + json[D_JSON_IRHVAC_FANSPEED] = IRac::fanspeedToString(state.fanspeed); + json[D_JSON_IRHVAC_SWINGV] = IRac::swingvToString(state.swingv); + json[D_JSON_IRHVAC_SWINGH] = IRac::swinghToString(state.swingh); + json[D_JSON_IRHVAC_QUIET] = IRac::boolToString(state.quiet); + json[D_JSON_IRHVAC_TURBO] = IRac::boolToString(state.turbo); + json[D_JSON_IRHVAC_ECONO] = IRac::boolToString(state.econo); + json[D_JSON_IRHVAC_LIGHT] = IRac::boolToString(state.light); + json[D_JSON_IRHVAC_FILTER] = IRac::boolToString(state.filter); + json[D_JSON_IRHVAC_CLEAN] = IRac::boolToString(state.clean); + json[D_JSON_IRHVAC_BEEP] = IRac::boolToString(state.beep); + json[D_JSON_IRHVAC_SLEEP] = state.sleep; + + String payload = ""; + payload.reserve(200); + json.printTo(payload); + return payload; +} + +String sendIRJsonState(const struct decode_results &results) { + String json("{"); + json += "\"" D_JSON_IR_PROTOCOL "\":\""; + json += typeToString(results.decode_type); + json += "\",\"" D_JSON_IR_BITS "\":"; + json += results.bits; + + if (hasACState(results.decode_type)) { + json += ",\"" D_JSON_IR_DATA "\":\"0x"; + json += resultToHexidecimal(&results); + json += "\""; + } else { + if (UNKNOWN != results.decode_type) { + json += ",\"" D_JSON_IR_DATA "\":"; + } else { + json += ",\"" D_JSON_IR_HASH "\":"; + } + if (Settings.flag.ir_receive_decimal) { + char svalue[32]; + ulltoa(results.value, svalue, 10); + json += svalue; + } else { + char hvalue[64]; + if (UNKNOWN != results.decode_type) { + Uint64toHex(results.value, hvalue, results.bits); + json += "\""; + json += hvalue; + json += "\",\"" D_JSON_IR_DATALSB "\":\""; + Uint64toHex(reverseBitsInBytes64(results.value), hvalue, results.bits); + json += hvalue; + json += "\""; + } else { + Uint64toHex(results.value, hvalue, 32); + json += "\""; + json += hvalue; + json += "\""; + } + } + } + json += ",\"" D_JSON_IR_REPEAT "\":"; + json += results.repeat; + + stdAc::state_t ac_result; + if (IRAcUtils::decodeToState(&results, &ac_result, nullptr)) { + + json += ",\"" D_CMND_IRHVAC "\":"; + json += sendACJsonState(ac_result); + } + + return json; +} + +void IrReceiveCheck(void) +{ + char sirtype[14]; + int8_t iridx = 0; + + decode_results results; + + if (irrecv->decode(&results)) { + uint32_t now = millis(); + + + + if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { + ir_lasttime = now; + ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str()); + + if (Settings.flag3.receive_raw) { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); + uint16_t i; + for (i = 1; i < results.rawlen; i++) { + if (i > 1) { ResponseAppend_P(PSTR(",")); } + uint32_t usecs; + for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { + ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); + } + ResponseAppend_P(PSTR("%d"), usecs); + if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } + } + uint16_t extended_length = results.rawlen - 1; + for (uint32_t j = 0; j < results.rawlen - 1; j++) { + uint32_t usecs = results.rawbuf[j] * kRawTick; + + extended_length += (usecs / (UINT16_MAX + 1)) * 2; + } + ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); + } + + ResponseJsonEndEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); + + if (iridx) { + XdrvRulesProcess(); +#ifdef USE_DOMOTICZ + unsigned long value = results.value | (iridx << 28); + DomoticzSensor(DZ_COUNT, value); +#endif + } + } + + irrecv->resume(); + } +} + + + + + + + +String listSupportedProtocols(bool hvac) { + String l(""); + bool first = true; + for (uint32_t i = UNUSED + 1; i <= kLastDecodeType; i++) { + bool found = false; + if (hvac) { + found = IRac::isProtocolSupported((decode_type_t)i); + } else { + found = (IRsend::defaultBits((decode_type_t)i) > 0) && (!IRac::isProtocolSupported((decode_type_t)i)); + } + if (found) { + if (first) { + first = false; + } else { + l += "|"; + } + l += typeToString((decode_type_t)i); + } + } + return l; +} + + +const stdAc::fanspeed_t IrHvacFanSpeed[] PROGMEM = { stdAc::fanspeed_t::kAuto, + stdAc::fanspeed_t::kMin, stdAc::fanspeed_t::kLow,stdAc::fanspeed_t::kMedium, + stdAc::fanspeed_t::kHigh, stdAc::fanspeed_t::kMax }; + +uint32_t IrRemoteCmndIrHvacJson(void) +{ + stdAc::state_t state, prev; + char parm_uc[12]; + + + char dataBufUc[XdrvMailbox.data_len]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } + + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(dataBufUc); + if (!json.success()) { return IE_INVALID_JSON; } + + + state.protocol = decode_type_t::UNKNOWN; + state.model = 1; + state.mode = stdAc::opmode_t::kAuto; + state.power = false; + state.celsius = true; + state.degrees = 21.0f; + state.fanspeed = stdAc::fanspeed_t::kMedium; + state.swingv = stdAc::swingv_t::kOff; + state.swingh = stdAc::swingh_t::kOff; + state.light = false; + state.beep = false; + state.econo = false; + state.filter = false; + state.turbo = false; + state.quiet = false; + state.sleep = -1; + state.clean = false; + state.clock = -1; + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR)); + if (json.containsKey(parm_uc)) { state.protocol = strToDecodeType(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_PROTOCOL)); + if (json.containsKey(parm_uc)) { state.protocol = strToDecodeType(json[parm_uc]); } + if (decode_type_t::UNKNOWN == state.protocol) { return IE_UNSUPPORTED_HVAC; } + if (!IRac::isProtocolSupported(state.protocol)) { return IE_UNSUPPORTED_HVAC; } + + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FANSPEED)); + if (json.containsKey(parm_uc)) { + uint32_t fan_speed = json[parm_uc]; + if ((fan_speed >= 1) && (fan_speed <= 5)) { + state.fanspeed = (stdAc::fanspeed_t) pgm_read_byte(&IrHvacFanSpeed[fan_speed]); + } else { + state.fanspeed = IRac::strToFanspeed(json[parm_uc]); + } + } + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODEL)); + if (json.containsKey(parm_uc)) { state.model = IRac::strToModel(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODE)); + if (json.containsKey(parm_uc)) { state.mode = IRac::strToOpmode(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SWINGV)); + if (json.containsKey(parm_uc)) { state.swingv = IRac::strToSwingV(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SWINGH)); + if (json.containsKey(parm_uc)) { state.swingh = IRac::strToSwingH(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TEMP)); + if (json.containsKey(parm_uc)) { state.degrees = json[parm_uc]; } + + + + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_POWER)); + if (json.containsKey(parm_uc)) { state.power = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_CELSIUS)); + if (json.containsKey(parm_uc)) { state.celsius = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_LIGHT)); + if (json.containsKey(parm_uc)) { state.light = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_BEEP)); + if (json.containsKey(parm_uc)) { state.beep = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_ECONO)); + if (json.containsKey(parm_uc)) { state.econo = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FILTER)); + if (json.containsKey(parm_uc)) { state.filter = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TURBO)); + if (json.containsKey(parm_uc)) { state.turbo = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_QUIET)); + if (json.containsKey(parm_uc)) { state.quiet = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_CLEAN)); + if (json.containsKey(parm_uc)) { state.clean = IRac::strToBool(json[parm_uc]); } + + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SLEEP)); + if (json[parm_uc]) { state.sleep = json[parm_uc]; } + + + IRac ac(pin[GPIO_IRSEND]); + bool success = ac.sendAc(state, &prev); + if (!success) { return IE_SYNTAX_IRHVAC; } + + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":%s}"), sendACJsonState(state).c_str()); + return IE_RESPONSE_PROVIDED; +} + +void CmndIrHvac(void) +{ + uint8_t error = IE_SYNTAX_IRHVAC; + + if (XdrvMailbox.data_len) { + error = IrRemoteCmndIrHvacJson(); + } + if (error != IE_RESPONSE_PROVIDED) { IrRemoteCmndResponse(error); } +} + + + + + +uint32_t IrRemoteCmndIrSendJson(void) +{ + char parm_uc[12]; + + + + char dataBufUc[XdrvMailbox.data_len]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } + + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(dataBufUc); + if (!json.success()) { return IE_INVALID_JSON; } + + + + decode_type_t protocol = decode_type_t::UNKNOWN; + uint16_t bits = 0; + uint64_t data; + uint8_t repeat = 0; + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR)); + if (json.containsKey(parm_uc)) { protocol = strToDecodeType(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_PROTOCOL)); + if (json.containsKey(parm_uc)) { protocol = strToDecodeType(json[parm_uc]); } + if (decode_type_t::UNKNOWN == protocol) { return IE_UNSUPPORTED_PROTOCOL; } + + UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS)); + if (json.containsKey(parm_uc)) { bits = json[parm_uc]; } + UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT)); + if (json.containsKey(parm_uc)) { repeat = json[parm_uc]; } + UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATALSB)); + if (json.containsKey(parm_uc)) { data = reverseBitsInBytes64(strtoull(json[parm_uc], nullptr, 0)); } + UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA)); + if (json.containsKey(parm_uc)) { data = strtoull(json[parm_uc], nullptr, 0); } + if (0 == bits) { return IE_SYNTAX_IRSEND; } + + + if (XdrvMailbox.index > repeat + 1) { repeat = XdrvMailbox.index - 1; } + + char dvalue[32]; + char hvalue[32]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol %d, bits %d, data %s (%s), repeat %d"), + protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat); + + irsend_active = true; + bool success = irsend->send(protocol, data, bits, repeat); + + if (!success) { + irsend_active = false; + ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); + } + return IE_NO_ERROR; +} + +uint32_t IrRemoteCmndIrSendRaw(void) +{ + + + + + + + + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + if (p == nullptr) { + return IE_INVALID_RAWDATA; + } + + + uint16_t repeat = XdrvMailbox.index > 0 ? XdrvMailbox.index - 1 : 0; + + uint16_t freq = atoi(str); + if (!freq && (*str != '0')) { + uint16_t count = 0; + char *q = p; + for (; *q; count += (*q++ == ',')); + if (count < 2) { + return IE_INVALID_RAWDATA; + } + + uint16_t parm[count]; + for (uint32_t i = 0; i < count; i++) { + parm[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); + if (!parm[i]) { + if (!i) { + parm[0] = 38000; + } else { + return IE_INVALID_RAWDATA; + } + } + } + + uint16_t i = 0; + if (count < 4) { + + uint16_t mark = parm[1] *2; + if (3 == count) { + if (parm[2] < parm[1]) { + + mark = parm[1] * parm[2]; + } else { + + mark = parm[2]; + } + } + uint16_t raw_array[strlen(p)]; + for (; *p; *p++) { + if (*p == '0') { + raw_array[i++] = parm[1]; + } + else if (*p == '1') { + raw_array[i++] = mark; + } + } + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, i, parm[0]); + if (r < repeat) { + irsend->space(40000); + } + } + } + else if (6 == count) { + + uint16_t raw_array[strlen(p)*2+3]; + raw_array[i++] = parm[1]; + raw_array[i++] = parm[2]; + uint32_t inter_message_32 = (parm[1] + parm[2]) * 3; + uint16_t inter_message = (inter_message_32 > 65000) ? 65000 : inter_message_32; + for (; *p; *p++) { + if (*p == '0') { + raw_array[i++] = parm[3]; + raw_array[i++] = parm[4]; + } + else if (*p == '1') { + raw_array[i++] = parm[3]; + raw_array[i++] = parm[5]; + } + } + raw_array[i++] = parm[3]; + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, i, parm[0]); + if (r < repeat) { + irsend->space(inter_message); + } + } + } + else { + return IE_INVALID_RAWDATA; + } + } else { + if (!freq) { freq = 38000; } + uint16_t count = 0; + char *q = p; + for (; *q; count += (*q++ == ',')); + if (0 == count) { + return IE_INVALID_RAWDATA; + } + + + count++; + if (count < 200) { + uint16_t raw_array[count]; + for (uint32_t i = 0; i < count; i++) { + raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); + } + + + + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, count, freq); + } + } else { + uint16_t *raw_array = reinterpret_cast(malloc(count * sizeof(uint16_t))); + if (raw_array == nullptr) { + return IE_INVALID_RAWDATA; + } + + for (uint32_t i = 0; i < count; i++) { + raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); + } + + + + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, count, freq); + } + free(raw_array); + } + } + + return IE_NO_ERROR; +} + +void CmndIrSend(void) +{ + uint8_t error = IE_SYNTAX_IRSEND; + + if (XdrvMailbox.data_len) { + if (strstr(XdrvMailbox.data, "{") == nullptr) { + error = IrRemoteCmndIrSendRaw(); + } else { + error = IrRemoteCmndIrSendJson(); + } + } + IrRemoteCmndResponse(error); +} + +void IrRemoteCmndResponse(uint32_t error) +{ + switch (error) { + case IE_INVALID_RAWDATA: + ResponseCmndChar(D_JSON_INVALID_RAWDATA); + break; + case IE_INVALID_JSON: + ResponseCmndChar(D_JSON_INVALID_JSON); + break; + case IE_SYNTAX_IRSEND: + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); + break; + case IE_SYNTAX_IRHVAC: + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); + break; + case IE_UNSUPPORTED_HVAC: + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR " (%s)\"}"), listSupportedProtocols(true).c_str()); + break; + case IE_UNSUPPORTED_PROTOCOL: + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_PROTOCOL " (%s)\"}"), listSupportedProtocols(false).c_str()); + break; + default: + ResponseCmndDone(); + } +} + + + + + +bool Xdrv05(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { + switch (function) { + case FUNC_PRE_INIT: + if (pin[GPIO_IRSEND] < 99) { + IrSendInit(); + } + if (pin[GPIO_IRRECV] < 99) { + IrReceiveInit(); + } + break; + case FUNC_EVERY_50_MSECOND: + if (pin[GPIO_IRRECV] < 99) { + IrReceiveCheck(); + } + irsend_active = false; + break; + case FUNC_COMMAND: + if (pin[GPIO_IRSEND] < 99) { + result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); + } + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_06_snfbridge.ino" +# 24 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_06_snfbridge.ino" +#define XDRV_06 6 + +const uint32_t SFB_TIME_AVOID_DUPLICATE = 2000; + +enum SonoffBridgeCommands { + CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE }; + +const char kSonoffBridgeCommands[] PROGMEM = "|" + D_CMND_RFSYNC "|" D_CMND_RFLOW "|" D_CMND_RFHIGH "|" D_CMND_RFHOST "|" D_CMND_RFCODE "|" D_CMND_RFKEY "|" D_CMND_RFRAW; + +void (* const SonoffBridgeCommand[])(void) PROGMEM = { + &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfKey, &CmndRfRaw }; + +struct SONOFFBRIDGE { + uint32_t last_received_id = 0; + uint32_t last_send_code = 0; + uint32_t last_time = 0; + uint32_t last_learn_time = 0; + uint8_t receive_flag = 0; + uint8_t receive_raw_flag = 0; + uint8_t learn_key = 1; + uint8_t learn_active = 0; + uint8_t expected_bytes = 0; +} SnfBridge; + +#ifdef USE_RF_FLASH + + + + + + + +#include "ihx.h" +#include "c2.h" + +const ssize_t RF_RECORD_NO_START_FOUND = -1; +const ssize_t RF_RECORD_NO_END_FOUND = -2; + +ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size) +{ + for (size_t i = 0; i < size; i++) { + if (buf[i] == ':') { + return i; + } + } + return RF_RECORD_NO_START_FOUND; +} + +ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size) +{ + for (size_t i = 0; i < size; i++) { + if (buf[i] == '\n') { + return i; + } + } + return RF_RECORD_NO_END_FOUND; +} + +ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uint8_t *new_data, size_t new_data_len) +{ + ssize_t record_start; + ssize_t record_end; + ssize_t glue_record_sz; + uint8_t *glue_buf; + ssize_t result; + + if (remnant_data[0] != ':') { return -8; } + + + record_end = rf_find_hex_record_end(new_data, new_data_len); + record_start = rf_find_hex_record_start(new_data, new_data_len); + + + + + if ((record_start != RF_RECORD_NO_START_FOUND) && (record_start < record_end)) { + return -8; + } + + glue_record_sz = strlen((const char *) remnant_data) + record_end; + + glue_buf = (uint8_t *) malloc(glue_record_sz); + if (glue_buf == nullptr) { return -2; } + + + memcpy(glue_buf, remnant_data, strlen((const char *) remnant_data)); + memcpy(glue_buf + strlen((const char *) remnant_data), new_data, record_end); + + result = rf_decode_and_write(glue_buf, glue_record_sz); + free(glue_buf); + return result; +} + +ssize_t rf_decode_and_write(uint8_t *record, size_t size) +{ + uint8_t err = ihx_decode(record, size); + if (err != IHX_SUCCESS) { return -13; } + + ihx_t *h = (ihx_t *) record; + if (h->record_type == IHX_RT_DATA) { + int retries = 5; + uint16_t address = h->address_high * 0x100 + h->address_low; + + do { + err = c2_programming_init(); + err = c2_block_write(address, h->data, h->len); + } while (err != C2_SUCCESS && retries--); + } else if (h->record_type == IHX_RT_END_OF_FILE) { + + err = c2_reset(); + } + + if (err != C2_SUCCESS) { return -12; } + + return 0; +} + +ssize_t rf_search_and_write(uint8_t *buf, size_t size) +{ + + ssize_t rec_end; + ssize_t rec_start; + ssize_t err; + + for (size_t i = 0; i < size; i++) { + + rec_start = rf_find_hex_record_start(buf + i, size - i); + if (rec_start == RF_RECORD_NO_START_FOUND) { + + return -8; + } + + + rec_start += i; + rec_end = rf_find_hex_record_end(buf + rec_start, size - rec_start); + if (rec_end == RF_RECORD_NO_END_FOUND) { + + return rec_start; + } + + + rec_end += rec_start; + + err = rf_decode_and_write(buf + rec_start, rec_end - rec_start); + if (err < 0) { return err; } + i = rec_end; + } + + return 0; +} + +uint8_t rf_erase_flash(void) +{ + uint8_t err; + + for (uint32_t i = 0; i < 4; i++) { + err = c2_programming_init(); + if (err != C2_SUCCESS) { + return 10; + } + err = c2_device_erase(); + if (err != C2_SUCCESS) { + if (i < 3) { + c2_reset(); + } else { + return 11; + } + } else { + break; + } + } + return 0; +} + +uint8_t SnfBrUpdateInit(void) +{ + pinMode(PIN_C2CK, OUTPUT); + pinMode(PIN_C2D, INPUT); + + return rf_erase_flash(); +} +#endif + + + +void SonoffBridgeReceivedRaw(void) +{ + + uint8_t buckets = 0; + + if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } + + ResponseTime_P(PSTR(",\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); + for (uint32_t i = 0; i < serial_in_byte_counter; i++) { + ResponseAppend_P(PSTR("%02X"), serial_in_buffer[i]); + if (0xB1 == serial_in_buffer[1]) { + if ((i > 3) && buckets) { buckets--; } + if ((i < 3) || (buckets % 2) || (i == serial_in_byte_counter -2)) { + ResponseAppend_P(PSTR(" ")); + } + } + } + ResponseAppend_P(PSTR("\"}}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW)); + + XdrvRulesProcess(); +} + + + +void SonoffBridgeLearnFailed(void) +{ + SnfBridge.learn_active = 0; + Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARN_FAILED); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); +} + +void SonoffBridgeReceived(void) +{ + uint16_t sync_time = 0; + uint16_t low_time = 0; + uint16_t high_time = 0; + uint32_t received_id = 0; + char rfkey[8]; + char stemp[16]; + + AddLogSerial(LOG_LEVEL_DEBUG); + + if (0xA2 == serial_in_buffer[0]) { + SonoffBridgeLearnFailed(); + } + else if (0xA3 == serial_in_buffer[0]) { + SnfBridge.learn_active = 0; + low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; + high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; + if (low_time && high_time) { + for (uint32_t i = 0; i < 9; i++) { + Settings.rf_code[SnfBridge.learn_key][i] = serial_in_buffer[i +1]; + } + Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARNED); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); + } else { + SonoffBridgeLearnFailed(); + } + } + else if (0xA4 == serial_in_buffer[0]) { + if (SnfBridge.learn_active) { + SonoffBridgeLearnFailed(); + } else { + sync_time = serial_in_buffer[1] << 8 | serial_in_buffer[2]; + low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; + high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; + received_id = serial_in_buffer[7] << 16 | serial_in_buffer[8] << 8 | serial_in_buffer[9]; + + unsigned long now = millis(); + if (!((received_id == SnfBridge.last_received_id) && (now - SnfBridge.last_time < SFB_TIME_AVOID_DUPLICATE))) { + SnfBridge.last_received_id = received_id; + SnfBridge.last_time = now; + strncpy_P(rfkey, PSTR("\"" D_JSON_NONE "\""), sizeof(rfkey)); + for (uint32_t 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; + } + } + } + if (Settings.flag.rf_receive_decimal) { + snprintf_P(stemp, sizeof(stemp), PSTR("%u"), received_id); + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("\"%06X\""), received_id); + } + ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"), + sync_time, low_time, high_time, stemp, rfkey); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); + XdrvRulesProcess(); + #ifdef USE_DOMOTICZ + DomoticzSensor(DZ_COUNT, received_id); + #endif + } + } + } +} + +bool SonoffBridgeSerialInput(void) +{ + + static int8_t receive_len = 0; + + if (SnfBridge.receive_flag) { + if (SnfBridge.receive_raw_flag) { + if (!serial_in_byte_counter) { + serial_in_buffer[serial_in_byte_counter++] = 0xAA; + } + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (serial_in_byte_counter == 3) { + if ((0xA6 == serial_in_buffer[1]) || (0xAB == serial_in_buffer[1])) { + receive_len = serial_in_buffer[2] + 4; + } + } + if ((!receive_len && (0x55 == serial_in_byte)) || (receive_len && (serial_in_byte_counter == receive_len))) { + SonoffBridgeReceivedRaw(); + SnfBridge.receive_flag = 0; + return 1; + } + } + else if (!((0 == serial_in_byte_counter) && (0 == serial_in_byte))) { + if (0 == serial_in_byte_counter) { + SnfBridge.expected_bytes = 2; + if (serial_in_byte >= 0xA3) { + SnfBridge.expected_bytes = 11; + } + if (serial_in_byte == 0xA6) { + SnfBridge.expected_bytes = 0; + serial_in_buffer[serial_in_byte_counter++] = 0xAA; + SnfBridge.receive_raw_flag = 1; + } + } + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if ((SnfBridge.expected_bytes == serial_in_byte_counter) && (0x55 == serial_in_byte)) { + SonoffBridgeReceived(); + SnfBridge.receive_flag = 0; + return 1; + } + } + serial_in_byte = 0; + } + if (0xAA == serial_in_byte) { + serial_in_byte_counter = 0; + serial_in_byte = 0; + SnfBridge.receive_flag = 1; + receive_len = 0; + } + return 0; +} + +void SonoffBridgeSendCommand(uint8_t code) +{ + Serial.write(0xAA); + Serial.write(code); + Serial.write(0x55); +} + +void SonoffBridgeSendAck(void) +{ + Serial.write(0xAA); + Serial.write(0xA0); + Serial.write(0x55); +} + +void SonoffBridgeSendCode(uint32_t code) +{ + Serial.write(0xAA); + Serial.write(0xA5); + for (uint32_t 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); + Serial.flush(); +} + +void SonoffBridgeSend(uint8_t idx, uint8_t key) +{ + uint8_t code; + + key--; + Serial.write(0xAA); + Serial.write(0xA5); + for (uint32_t i = 0; i < 8; i++) { + Serial.write(Settings.rf_code[idx][i]); + } + if (0 == idx) { + code = (0x10 << (key >> 2)) | (1 << (key & 3)); + } else { + code = Settings.rf_code[idx][8]; + } + Serial.write(code); + Serial.write(0x55); + Serial.flush(); +#ifdef USE_DOMOTICZ + + +#endif +} + +void SonoffBridgeLearn(uint8_t key) +{ + SnfBridge.learn_key = key; + SnfBridge.learn_active = 1; + SnfBridge.last_learn_time = millis(); + Serial.write(0xAA); + Serial.write(0xA1); + Serial.write(0x55); +} + + + + + +void CmndRfBridge(void) +{ + char *p; + char stemp [10]; + uint32_t code = 0; + uint8_t radix = 10; + + uint32_t set_index = XdrvMailbox.command_code *2; + + if (XdrvMailbox.data[0] == '#') { + XdrvMailbox.data++; + XdrvMailbox.data_len--; + radix = 16; + } + + if (XdrvMailbox.data_len) { + code = strtol(XdrvMailbox.data, &p, radix); + if (code) { + if (CMND_RFCODE == XdrvMailbox.command_code) { + SnfBridge.last_send_code = code; + SonoffBridgeSendCode(code); + } else { + if (1 == XdrvMailbox.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)) { + Settings.rf_code[0][set_index] = msb; + Settings.rf_code[0][set_index +1] = lsb; + } + } + } + } + if (CMND_RFCODE == XdrvMailbox.command_code) { + code = SnfBridge.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); + } + Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp); +} + +void CmndRfKey(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 16)) { + unsigned long now = millis(); + if ((!SnfBridge.learn_active) || (now - SnfBridge.last_learn_time > 60100)) { + SnfBridge.learn_active = 0; + if (2 == XdrvMailbox.payload) { + SonoffBridgeLearn(XdrvMailbox.index); + ResponseCmndIdxChar(D_JSON_START_LEARNING); + } + else if (3 == XdrvMailbox.payload) { + Settings.rf_code[XdrvMailbox.index][0] = 0; + ResponseCmndIdxChar(D_JSON_SET_TO_DEFAULT); + } + else if (4 == XdrvMailbox.payload) { + for (uint32_t i = 0; i < 6; i++) { + Settings.rf_code[XdrvMailbox.index][i] = Settings.rf_code[0][i]; + } + Settings.rf_code[XdrvMailbox.index][6] = (SnfBridge.last_send_code >> 16) & 0xff; + Settings.rf_code[XdrvMailbox.index][7] = (SnfBridge.last_send_code >> 8) & 0xff; + Settings.rf_code[XdrvMailbox.index][8] = SnfBridge.last_send_code & 0xff; + ResponseCmndIdxChar(D_JSON_SAVED); + } else if (5 == XdrvMailbox.payload) { + uint8_t key = XdrvMailbox.index; + uint8_t index = (0 == Settings.rf_code[key][0]) ? 0 : key; + uint16_t sync_time = (Settings.rf_code[index][0] << 8) | Settings.rf_code[index][1]; + uint16_t low_time = (Settings.rf_code[index][2] << 8) | Settings.rf_code[index][3]; + uint16_t high_time = (Settings.rf_code[index][4] << 8) | Settings.rf_code[index][5]; + uint32_t code = (Settings.rf_code[index][6] << 16) | (Settings.rf_code[index][7] << 8); + if (0 == index) { + key--; + code |= (uint8_t)((0x10 << (key >> 2)) | (1 << (key & 3))); + } else { + code |= Settings.rf_code[index][8]; + } + Response_P(PSTR("{\"%s%d\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\"}}"), + XdrvMailbox.command, XdrvMailbox.index, sync_time, low_time, high_time, code); + } else { + if ((1 == XdrvMailbox.payload) || (0 == Settings.rf_code[XdrvMailbox.index][0])) { + SonoffBridgeSend(0, XdrvMailbox.index); + ResponseCmndIdxChar(D_JSON_DEFAULT_SENT); + } else { + SonoffBridgeSend(XdrvMailbox.index, 0); + ResponseCmndIdxChar(D_JSON_LEARNED_SENT); + } + } + } else { + Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, SnfBridge.learn_key, D_JSON_LEARNING_ACTIVE); + } + } +} + +void CmndRfRaw(void) +{ + if (XdrvMailbox.data_len) { + if (XdrvMailbox.data_len < 6) { + switch (XdrvMailbox.payload) { + case 0: + SonoffBridgeSendCommand(0xA7); + case 1: + SnfBridge.receive_raw_flag = XdrvMailbox.payload; + break; + case 166: + case 167: + case 169: + case 176: + case 177: + case 255: + SonoffBridgeSendCommand(XdrvMailbox.payload); + SnfBridge.receive_raw_flag = 1; + break; + case 192: + char beep[] = "AAC000C055\0"; + SerialSendRaw(beep); + break; + } + } else { + SerialSendRaw(RemoveSpace(XdrvMailbox.data)); + SnfBridge.receive_raw_flag = 1; + } + } + ResponseCmndStateText(SnfBridge.receive_raw_flag); +} + + + + + +bool Xdrv06(uint8_t function) +{ + bool result = false; + + if (SONOFF_BRIDGE == my_module_type) { + switch (function) { + case FUNC_SERIAL: + result = SonoffBridgeSerialInput(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kSonoffBridgeCommands, SonoffBridgeCommand); + break; + case FUNC_INIT: + SnfBridge.receive_raw_flag = 0; + SonoffBridgeSendCommand(0xA7); + break; + case FUNC_PRE_INIT: + Settings.flag.mqtt_serial = 0; + baudrate = 19200; + break; + } + } + return result; +} +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_07_domoticz.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_07_domoticz.ino" +#ifdef USE_DOMOTICZ + +#define XDRV_07 7 + +#define D_PRFX_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" + +const char kDomoticzCommands[] PROGMEM = D_PRFX_DOMOTICZ "|" + D_CMND_IDX "|" D_CMND_KEYIDX "|" D_CMND_SWITCHIDX "|" D_CMND_SENSORIDX "|" D_CMND_UPDATETIMER ; + +void (* const DomoticzCommand[])(void) PROGMEM = { + &CmndDomoticzIdx, &CmndDomoticzKeyIdx, &CmndDomoticzSwitchIdx, &CmndDomoticzSensorIdx, &CmndDomoticzUpdateTimer }; + +const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\",\"Battery\":%d,\"RSSI\":%d}"; + +#if MAX_DOMOTICZ_SNS_IDX < DZ_MAX_SENSORS + #error "Domoticz: Too many sensors or change settings.h layout" +#endif + +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 "|" D_DOMOTICZ_AIRQUALITY "|" D_DOMOTICZ_P1_SMART_METER ; + +char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; +char domoticz_out_topic[] = DOMOTICZ_OUT_TOPIC; + +int domoticz_update_timer = 0; +uint32_t domoticz_fan_debounce = 0; +bool domoticz_subscribe = false; +bool domoticz_update_flag = true; + +int DomoticzBatteryQuality(void) +{ + + + + + int quality = 100; + +#ifdef USE_ADC_VCC + uint16_t voltage = ESP.getVcc(); + if (voltage <= 2600) { + quality = 0; + } else if (voltage >= 4600) { + quality = 200; + } else { + quality = (voltage - 2600) / 10; + } +#endif + return quality; +} + +int DomoticzRssiQuality(void) +{ + + + return WifiGetRssiAsQuality(WiFi.RSSI()) / 10; +} + +#ifdef USE_SONOFF_IFAN +void MqttPublishDomoticzFanState() +{ + if (Settings.flag.mqtt_enabled && Settings.domoticz_relay_idx[1]) { + char svalue[8]; + + int fan_speed = GetFanspeed(); + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fan_speed * 10); + Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); + MqttPublish(domoticz_in_topic); + + domoticz_fan_debounce = millis(); + } +} + +void DomoticzUpdateFanState() +{ + if (domoticz_update_flag) { + MqttPublishDomoticzFanState(); + } + domoticz_update_flag = true; +} +#endif + +void MqttPublishDomoticzPowerState(uint8_t device) +{ + if (Settings.flag.mqtt_enabled) { + if ((device < 1) || (device > devices_present)) { device = 1; } + if (Settings.domoticz_relay_idx[device -1]) { +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (device > 1)) { + + } else { +#endif + char svalue[8]; + + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); + Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); + MqttPublish(domoticz_in_topic); +#ifdef USE_SONOFF_IFAN + } +#endif + } + } +} + +void DomoticzUpdatePowerState(uint8_t device) +{ + if (domoticz_update_flag) { + MqttPublishDomoticzPowerState(device); + } + domoticz_update_flag = true; +} + +void DomoticzMqttUpdate(void) +{ + if (domoticz_subscribe && (Settings.domoticz_update_timer || domoticz_update_timer)) { + domoticz_update_timer--; + if (domoticz_update_timer <= 0) { + domoticz_update_timer = Settings.domoticz_update_timer; + for (uint32_t i = 1; i <= devices_present; i++) { +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (i > 1)) { + MqttPublishDomoticzFanState(); + break; + } else { +#endif + MqttPublishDomoticzPowerState(i); +#ifdef USE_SONOFF_IFAN + } +#endif + } + } + } +} + +void DomoticzMqttSubscribe(void) +{ + uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; + for (uint32_t 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); + MqttSubscribe(stopic); + } +} +# 200 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_07_domoticz.ino" +bool DomoticzMqttData(void) +{ + char stemp1[10]; + unsigned long idx = 0; + int16_t nvalue = -1; + bool found = false; + + domoticz_update_flag = true; + if (!strncmp(XdrvMailbox.topic, domoticz_out_topic, strlen(domoticz_out_topic))) { + if (XdrvMailbox.data_len < 20) { + return true; + } + StaticJsonBuffer<400> jsonBuf; + JsonObject& domoticz = jsonBuf.parseObject(XdrvMailbox.data); + if (!domoticz.success()) { + return true; + } + + + + idx = domoticz["idx"]; + if (domoticz.containsKey("nvalue")) { + nvalue = domoticz["nvalue"]; + } + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); + + if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) { + uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; + for (uint32_t i = 0; i < maxdev; i++) { + if (idx == Settings.domoticz_relay_idx[i]) { + bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; + snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (1 == i)) { + uint8_t svalue = 0; + if (domoticz.containsKey("svalue1")) { + svalue = domoticz["svalue1"]; + } else { + return true; + } + svalue = (nvalue == 2) ? svalue / 10 : 0; + if (GetFanspeed() == svalue) { + return true; + } + if (TimePassedSince(domoticz_fan_debounce) < 1000) { + return true; + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue); + found = true; + } else +#endif + if (iscolordimmer && 10 == nvalue) { + JsonObject& color = domoticz["Color"]; + uint16_t level = nvalue = domoticz["svalue1"]; + uint16_t r = color["r"]; r = r * level / 100; + uint16_t g = color["g"]; g = g * level / 100; + uint16_t b = color["b"]; b = b * level / 100; + uint16_t cw = color["cw"]; cw = cw * level / 100; + uint16_t ww = color["ww"]; ww = ww * level / 100; + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww); + found = true; + } + else if ((!iscolordimmer && 2 == nvalue) || + (iscolordimmer && 15 == nvalue)) { + if (domoticz.containsKey("svalue1")) { + nvalue = domoticz["svalue1"]; + } else { + return true; + } + if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) { + return true; + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); + found = true; + } + else if (1 == nvalue || 0 == nvalue) { + if (((power >> i) &1) == (power_t)nvalue) { + return true; + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : ""); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); + found = true; + } + break; + } + } + } + if (!found) { return true; } + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data); + + domoticz_update_flag = false; + } + return false; +} + + + +bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg) +{ + bool result = false; + + if (device <= MAX_DOMOTICZ_IDX) { + if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) { + Response_P(PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), + (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (POWER_TOGGLE == state) ? "Toggle" : "On" : "Off"); + MqttPublish(domoticz_in_topic); + result = true; + } + } + return result; +} +# 334 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_07_domoticz.ino" +uint8_t DomoticzHumidityState(char *hum) +{ + uint8_t h = atoi(hum); + return (!h) ? 0 : (h < 40) ? 2 : (h > 70) ? 3 : 1; +} + +void DomoticzSensor(uint8_t idx, char *data) +{ + if (Settings.domoticz_sensor_idx[idx]) { + char dmess[128]; + + memcpy(dmess, mqtt_data, sizeof(dmess)); + if (DZ_AIRQUALITY == idx) { + Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), + Settings.domoticz_sensor_idx[idx], data, DomoticzBatteryQuality(), DomoticzRssiQuality()); + } else { + Response_P(DOMOTICZ_MESSAGE, + Settings.domoticz_sensor_idx[idx], 0, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); + } + MqttPublish(domoticz_in_topic); + memcpy(mqtt_data, dmess, sizeof(dmess)); + } +} + +void DomoticzSensor(uint8_t idx, uint32_t value) +{ + char data[16]; + snprintf_P(data, sizeof(data), PSTR("%d"), value); + DomoticzSensor(idx, data); +} + +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, DomoticzHumidityState(hum), baro); + DomoticzSensor(DZ_TEMP_HUM_BARO, data); +} + +void DomoticzSensorPowerEnergy(int power, char *energy) +{ + char data[16]; + snprintf_P(data, sizeof(data), PSTR("%d;%s"), power, energy); + DomoticzSensor(DZ_POWER_ENERGY, data); +} + +void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int power) +{ + + + + + + int consumed = power; + int produced = 0; + if (power < 0) { + consumed = 0; + produced = -power; + } + char data[64]; + snprintf_P(data, sizeof(data), PSTR("%s;%s;%s;%s;%d;%d"), usage1, usage2, return1, return2, consumed, produced); + DomoticzSensor(DZ_P1_SMART_METER, data); +} + + + + + +void CmndDomoticzIdx(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { + if (XdrvMailbox.payload >= 0) { + Settings.domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; + restart_flag = 2; + } + ResponseCmndIdxNumber(Settings.domoticz_relay_idx[XdrvMailbox.index -1]); + } +} + +void CmndDomoticzKeyIdx(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { + if (XdrvMailbox.payload >= 0) { + Settings.domoticz_key_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.domoticz_key_idx[XdrvMailbox.index -1]); + } +} + +void CmndDomoticzSwitchIdx(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { + if (XdrvMailbox.payload >= 0) { + Settings.domoticz_switch_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.domoticz_switch_idx[XdrvMailbox.index -1]); + } +} + +void CmndDomoticzSensorIdx(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= DZ_MAX_SENSORS)) { + if (XdrvMailbox.payload >= 0) { + Settings.domoticz_sensor_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.domoticz_sensor_idx[XdrvMailbox.index -1]); + } +} + +void CmndDomoticzUpdateTimer(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.domoticz_update_timer = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.domoticz_update_timer); +} + + + + + +#ifdef USE_WEBSERVER + +#define WEB_HANDLE_DOMOTICZ "dm" + +const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ; + +const char HTTP_BTN_MENU_DOMOTICZ[] PROGMEM = + "

"; + +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_SENSOR[] PROGMEM = + ""; +const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM = + ""; + +void HandleDomoticzConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_DOMOTICZ); + + if (WebServer->hasArg("save")) { + DomoticzSaveSettings(); + WebRestart(1); + return; + } + + char stemp[40]; + + WSContentStart_P(S_CONFIGURE_DOMOTICZ); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_DOMOTICZ); + for (uint32_t i = 0; i < MAX_DOMOTICZ_IDX; i++) { + if (i < devices_present) { + WSContentSend_P(HTTP_FORM_DOMOTICZ_RELAY, + i +1, i, Settings.domoticz_relay_idx[i], + i +1, i, Settings.domoticz_key_idx[i]); + } + if (pin[GPIO_SWT1 +i] < 99) { + WSContentSend_P(HTTP_FORM_DOMOTICZ_SWITCH, + i +1, i, Settings.domoticz_switch_idx[i]); + } +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (1 == i)) { break; } +#endif + } + for (uint32_t i = 0; i < DZ_MAX_SENSORS; i++) { + WSContentSend_P(HTTP_FORM_DOMOTICZ_SENSOR, + i +1, GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors), i, Settings.domoticz_sensor_idx[i]); + } + WSContentSend_P(HTTP_FORM_DOMOTICZ_TIMER, Settings.domoticz_update_timer); + WSContentSend_P(PSTR("
" D_DOMOTICZ_IDX " %d
" D_DOMOTICZ_KEY_IDX " %d
" D_DOMOTICZ_SWITCH_IDX " %d
" D_DOMOTICZ_SENSOR_IDX " %d %s
" D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ")
")); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void DomoticzSaveSettings(void) +{ + char stemp[20]; + char ssensor_indices[6 * MAX_DOMOTICZ_SNS_IDX]; + char tmp[100]; + + for (uint32_t i = 0; i < MAX_DOMOTICZ_IDX; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("r%d"), i); + WebGetArg(stemp, tmp, sizeof(tmp)); + Settings.domoticz_relay_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); + snprintf_P(stemp, sizeof(stemp), PSTR("k%d"), i); + WebGetArg(stemp, tmp, sizeof(tmp)); + Settings.domoticz_key_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); + snprintf_P(stemp, sizeof(stemp), PSTR("s%d"), i); + WebGetArg(stemp, tmp, sizeof(tmp)); + Settings.domoticz_switch_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); + } + ssensor_indices[0] = '\0'; + for (uint32_t i = 0; i < DZ_MAX_SENSORS; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("l%d"), i); + WebGetArg(stemp, tmp, sizeof(tmp)); + Settings.domoticz_sensor_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); + snprintf_P(ssensor_indices, sizeof(ssensor_indices), PSTR("%s%s%d"), ssensor_indices, (strlen(ssensor_indices)) ? "," : "", Settings.domoticz_sensor_idx[i]); + } + WebGetArg("ut", tmp, sizeof(tmp)); + Settings.domoticz_update_timer = (!strlen(tmp)) ? DOMOTICZ_UPDATE_TIMER : atoi(tmp); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_DOMOTICZ D_CMND_IDX " %d,%d,%d,%d, " D_CMND_KEYIDX " %d,%d,%d,%d, " D_CMND_SWITCHIDX " %d,%d,%d,%d, " D_CMND_SENSORIDX " %s, " D_CMND_UPDATETIMER " %d"), + Settings.domoticz_relay_idx[0], Settings.domoticz_relay_idx[1], Settings.domoticz_relay_idx[2], Settings.domoticz_relay_idx[3], + 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], + ssensor_indices, Settings.domoticz_update_timer); +} +#endif + + + + + +bool Xdrv07(uint8_t function) +{ + bool result = false; + + if (Settings.flag.mqtt_enabled) { + switch (function) { + case FUNC_EVERY_SECOND: + DomoticzMqttUpdate(); + break; + case FUNC_MQTT_DATA: + result = DomoticzMqttData(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_DOMOTICZ); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration); + break; +#endif + case FUNC_MQTT_SUBSCRIBE: + DomoticzMqttSubscribe(); + break; + case FUNC_MQTT_INIT: + domoticz_update_timer = 2; + break; + case FUNC_SHOW_SENSOR: + + break; + case FUNC_COMMAND: + result = DecodeCommand(kDomoticzCommands, DomoticzCommand); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_08_serial_bridge.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_08_serial_bridge.ino" +#ifdef USE_SERIAL_BRIDGE + + + + +#define XDRV_08 8 + +const uint8_t SERIAL_BRIDGE_BUFFER_SIZE = 130; + +const char kSerialBridgeCommands[] PROGMEM = "|" + D_CMND_SSERIALSEND "|" D_CMND_SBAUDRATE; + +void (* const SerialBridgeCommand[])(void) PROGMEM = + { &CmndSSerialSend, &CmndSBaudrate }; + +#include + +TasmotaSerial *SerialBridgeSerial = nullptr; + +unsigned long serial_bridge_polling_window = 0; +char *serial_bridge_buffer = nullptr; +int serial_bridge_in_byte_counter = 0; +bool serial_bridge_active = true; +bool serial_bridge_raw = false; + +void SerialBridgeInput(void) +{ + while (SerialBridgeSerial->available()) { + yield(); + uint8_t serial_in_byte = SerialBridgeSerial->read(); + + if ((serial_in_byte > 127) && !serial_bridge_raw) { + serial_bridge_in_byte_counter = 0; + SerialBridgeSerial->flush(); + return; + } + if (serial_in_byte || serial_bridge_raw) { + + if ((serial_bridge_in_byte_counter < SERIAL_BRIDGE_BUFFER_SIZE -1) && + ((isprint(serial_in_byte) && (128 == Settings.serial_delimiter)) || + ((serial_in_byte != Settings.serial_delimiter) && (128 != Settings.serial_delimiter)) || + serial_bridge_raw)) { + serial_bridge_buffer[serial_bridge_in_byte_counter++] = serial_in_byte; + serial_bridge_polling_window = millis(); + } else { + serial_bridge_polling_window = 0; + break; + } + } + } + + if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) { + serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; + char hex_char[(serial_bridge_in_byte_counter * 2) + 2]; + ResponseTime_P(PSTR(",\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), + (serial_bridge_raw) ? ToHex_P((unsigned char*)serial_bridge_buffer, serial_bridge_in_byte_counter, hex_char, sizeof(hex_char)) : serial_bridge_buffer); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); + XdrvRulesProcess(); + serial_bridge_in_byte_counter = 0; + } +} + + + +void SerialBridgeInit(void) +{ + serial_bridge_active = false; + if ((pin[GPIO_SBR_RX] < 99) && (pin[GPIO_SBR_TX] < 99)) { + SerialBridgeSerial = new TasmotaSerial(pin[GPIO_SBR_RX], pin[GPIO_SBR_TX]); + if (SerialBridgeSerial->begin(Settings.sbaudrate * 300)) { + if (SerialBridgeSerial->hardwareSerial()) { + ClaimSerial(); + serial_bridge_buffer = serial_in_buffer; + } else { + serial_bridge_buffer = (char*)(malloc(SERIAL_BRIDGE_BUFFER_SIZE)); + } + serial_bridge_active = true; + SerialBridgeSerial->flush(); + } + } +} + + + + + +void CmndSSerialSend(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { + serial_bridge_raw = (XdrvMailbox.index > 3); + if (XdrvMailbox.data_len > 0) { + if (1 == XdrvMailbox.index) { + SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); + SerialBridgeSerial->write("\n"); + } + else if ((2 == XdrvMailbox.index) || (4 == XdrvMailbox.index)) { + SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); + } + else if (3 == XdrvMailbox.index) { + SerialBridgeSerial->write(Unescape(XdrvMailbox.data, &XdrvMailbox.data_len), XdrvMailbox.data_len); + } + else if (5 == XdrvMailbox.index) { + char *p; + char stemp[3]; + uint8_t code; + + char *codes = RemoveSpace(XdrvMailbox.data); + int size = strlen(XdrvMailbox.data); + + while (size > 0) { + strlcpy(stemp, codes, sizeof(stemp)); + code = strtol(stemp, &p, 16); + SerialBridgeSerial->write(code); + size -= 2; + codes += 2; + } + } + ResponseCmndDone(); + } + } +} + +void CmndSBaudrate(void) +{ + if (XdrvMailbox.payload >= 300) { + XdrvMailbox.payload /= 300; + Settings.sbaudrate = XdrvMailbox.payload; + SerialBridgeSerial->begin(Settings.sbaudrate * 300); + } + ResponseCmndNumber(Settings.sbaudrate * 300); +} + + + + + +bool Xdrv08(uint8_t function) +{ + bool result = false; + + if (serial_bridge_active) { + switch (function) { + case FUNC_LOOP: + if (SerialBridgeSerial) { SerialBridgeInput(); } + break; + case FUNC_PRE_INIT: + SerialBridgeInit(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kSerialBridgeCommands, SerialBridgeCommand); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_09_timers.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_09_timers.ino" +#ifdef USE_TIMERS +# 39 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_09_timers.ino" +#define XDRV_09 9 + +const char kTimerCommands[] PROGMEM = "|" + D_CMND_TIMER "|" D_CMND_TIMERS +#ifdef USE_SUNRISE + "|" D_CMND_LATITUDE "|" D_CMND_LONGITUDE +#endif + ; + +void (* const TimerCommand[])(void) PROGMEM = { + &CmndTimer, &CmndTimers +#ifdef USE_SUNRISE + , &CmndLatitude, &CmndLongitude +#endif + }; + +uint16_t timer_last_minute = 60; +int8_t timer_window[MAX_TIMERS] = { 0 }; + +#ifdef USE_SUNRISE +# 67 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_09_timers.ino" +const float pi2 = TWO_PI; +const float pi = PI; +const float RAD = DEG_TO_RAD; + +float JulianischesDatum(void) +{ + + int Gregor; + int Jahr = RtcTime.year; + int Monat = RtcTime.month; + int Tag = RtcTime.day_of_month; + + if (Monat <= 2) { + Monat += 12; + Jahr -= 1; + } + Gregor = (Jahr / 400) - (Jahr / 100) + (Jahr / 4); + return 2400000.5f + 365.0f*Jahr - 679004.0f + Gregor + (int)(30.6001f * (Monat +1)) + Tag + 0.5f; +} + +float InPi(float x) +{ + int n = (int)(x / pi2); + x = x - n*pi2; + if (x < 0) x += pi2; + return x; +} + +float eps(float T) +{ + + return RAD * (23.43929111f + (-46.8150f*T - 0.00059f*T*T + 0.001813f*T*T*T)/3600.0f); +} + +float BerechneZeitgleichung(float *DK,float T) +{ + float RA_Mittel = 18.71506921f + 2400.0513369f*T +(2.5862e-5f - 1.72e-9f*T)*T*T; + float M = InPi(pi2 * (0.993133f + 99.997361f*T)); + float L = InPi(pi2 * (0.7859453f + M/pi2 + (6893.0f*sinf(M)+72.0f*sinf(2.0f*M)+6191.2f*T) / 1296.0e3f)); + float e = eps(T); + float RA = atanf(tanf(L)*cosf(e)); + if (RA < 0.0) RA += pi; + if (L > pi) RA += pi; + RA = 24.0*RA/pi2; + *DK = asinf(sinf(e)*sinf(L)); + + RA_Mittel = 24.0f * InPi(pi2*RA_Mittel/24.0f)/pi2; + float dRA = RA_Mittel - RA; + if (dRA < -12.0f) dRA += 24.0f; + if (dRA > 12.0f) dRA -= 24.0f; + dRA = dRA * 1.0027379f; + return dRA; +} + +void DuskTillDawn(uint8_t *hour_up,uint8_t *minute_up, uint8_t *hour_down, uint8_t *minute_down) +{ + float JD2000 = 2451545.0f; + float JD = JulianischesDatum(); + float T = (JD - JD2000) / 36525.0f; + float DK; + + + + + + + + float h = SUNRISE_DAWN_ANGLE *RAD; + float B = (((float)Settings.latitude)/1000000) * RAD; + float GeographischeLaenge = ((float)Settings.longitude)/1000000; + + + + float Zeitzone = ((float)Rtc.time_timezone) / 60; + float Zeitgleichung = BerechneZeitgleichung(&DK, T); + float Zeitdifferenz = 12.0f*acosf((sinf(h) - sinf(B)*sinf(DK)) / (cosf(B)*cosf(DK)))/pi; + float AufgangOrtszeit = 12.0f - Zeitdifferenz - Zeitgleichung; + float UntergangOrtszeit = 12.0f + Zeitdifferenz - Zeitgleichung; + float AufgangWeltzeit = AufgangOrtszeit - GeographischeLaenge / 15.0f; + float UntergangWeltzeit = UntergangOrtszeit - GeographischeLaenge / 15.0f; + float Aufgang = AufgangWeltzeit + Zeitzone; + if (Aufgang < 0.0f) { + Aufgang += 24.0f; + } else { + if (Aufgang >= 24.0f) Aufgang -= 24.0f; + } + float Untergang = UntergangWeltzeit + Zeitzone; + if (Untergang < 0.0f) { + Untergang += 24.0f; + } else { + if (Untergang >= 24.0f) Untergang -= 24.0f; + } + int AufgangMinuten = (int)(60.0f*(Aufgang - (int)Aufgang)+0.5f); + int AufgangStunden = (int)Aufgang; + if (AufgangMinuten >= 60.0f) { + AufgangMinuten -= 60.0f; + AufgangStunden++; + } else { + if (AufgangMinuten < 0.0f) { + AufgangMinuten += 60.0f; + AufgangStunden--; + if (AufgangStunden < 0.0f) AufgangStunden += 24.0f; + } + } + int UntergangMinuten = (int)(60.0f*(Untergang - (int)Untergang)+0.5f); + int UntergangStunden = (int)Untergang; + if (UntergangMinuten >= 60.0f) { + UntergangMinuten -= 60.0f; + UntergangStunden++; + } else { + if (UntergangMinuten<0) { + UntergangMinuten += 60.0f; + UntergangStunden--; + if (UntergangStunden < 0.0f) UntergangStunden += 24.0f; + } + } + *hour_up = AufgangStunden; + *minute_up = AufgangMinuten; + *hour_down = UntergangStunden; + *minute_down = UntergangMinuten; +} + +void ApplyTimerOffsets(Timer *duskdawn) +{ + uint8_t hour[2]; + uint8_t minute[2]; + Timer stored = (Timer)*duskdawn; + + + DuskTillDawn(&hour[0], &minute[0], &hour[1], &minute[1]); + uint8_t mode = (duskdawn->mode -1) &1; + duskdawn->time = (hour[mode] *60) + minute[mode]; + + + uint16_t timeBuffer; + if ((uint16_t)stored.time > 719) { + + timeBuffer = (uint16_t)stored.time - 720; + + if (timeBuffer > (uint16_t)duskdawn->time) { + timeBuffer = 1440 - (timeBuffer - (uint16_t)duskdawn->time); + duskdawn->days = duskdawn->days >> 1; + duskdawn->days |= (stored.days << 6); + } else { + timeBuffer = (uint16_t)duskdawn->time - timeBuffer; + } + } else { + + timeBuffer = (uint16_t)duskdawn->time + (uint16_t)stored.time; + + if (timeBuffer > 1440) { + timeBuffer -= 1440; + duskdawn->days = duskdawn->days << 1; + duskdawn->days |= (stored.days >> 6); + } + } + duskdawn->time = timeBuffer; +} + +String GetSun(uint32_t dawn) +{ + char stime[6]; + + uint8_t hour[2]; + uint8_t minute[2]; + + DuskTillDawn(&hour[0], &minute[0], &hour[1], &minute[1]); + dawn &= 1; + snprintf_P(stime, sizeof(stime), PSTR("%02d:%02d"), hour[dawn], minute[dawn]); + return String(stime); +} + +uint16_t SunMinutes(uint32_t dawn) +{ + uint8_t hour[2]; + uint8_t minute[2]; + + DuskTillDawn(&hour[0], &minute[0], &hour[1], &minute[1]); + dawn &= 1; + return (hour[dawn] *60) + minute[dawn]; +} + +#endif + + + +void TimerSetRandomWindow(uint32_t index) +{ + timer_window[index] = 0; + if (Settings.timer[index].window) { + timer_window[index] = (random(0, (Settings.timer[index].window << 1) +1)) - Settings.timer[index].window; + } +} + +void TimerSetRandomWindows(void) +{ + for (uint32_t i = 0; i < MAX_TIMERS; i++) { TimerSetRandomWindow(i); } +} + +void TimerEverySecond(void) +{ + if (RtcTime.valid) { + if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second) { TimerSetRandomWindows(); } + if (Settings.flag3.timers_enable && (uptime > 60) && (RtcTime.minute != timer_last_minute)) { + timer_last_minute = RtcTime.minute; + int32_t time = (RtcTime.hour *60) + RtcTime.minute; + uint8_t days = 1 << (RtcTime.day_of_week -1); + + for (uint32_t i = 0; i < MAX_TIMERS; i++) { + + Timer xtimer = Settings.timer[i]; +#ifdef USE_SUNRISE + if ((1 == xtimer.mode) || (2 == xtimer.mode)) { + ApplyTimerOffsets(&xtimer); + } +#endif + if (xtimer.arm) { + int32_t set_time = xtimer.time + timer_window[i]; + if (set_time < 0) { + set_time = abs(timer_window[i]); + } + if (set_time > 1439) { + set_time = xtimer.time - abs(timer_window[i]); + } + if (set_time > 1439) { set_time = 1439; } + + DEBUG_DRIVER_LOG(PSTR("TIM: Timer %d, Time %d, Window %d, SetTime %d"), i +1, xtimer.time, timer_window[i], set_time); + + if (time == set_time) { + if (xtimer.days & days) { + Settings.timer[i].arm = xtimer.repeat; +#if defined(USE_RULES) || defined(USE_SCRIPT) + if (POWER_BLINK == xtimer.power) { + Response_P(PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1); + XdrvRulesProcess(); + } else +#endif + if (devices_present) { ExecuteCommandPower(xtimer.device +1, xtimer.power, SRC_TIMER); } + } + } + } + } + } + } +} + +void PrepShowTimer(uint32_t index) +{ + Timer xtimer = Settings.timer[index -1]; + + char days[8] = { 0 }; + for (uint32_t i = 0; i < 7; i++) { + uint8_t mask = 1 << i; + snprintf(days, sizeof(days), "%s%d", days, ((xtimer.days & mask) > 0)); + } + + char soutput[80]; + soutput[0] = '\0'; + if (devices_present) { + snprintf_P(soutput, sizeof(soutput), PSTR(",\"" D_JSON_TIMER_OUTPUT "\":%d"), xtimer.device +1); + } +#ifdef USE_SUNRISE + char sign[2] = { 0 }; + int16_t hour = xtimer.time / 60; + if ((1 == xtimer.mode) || (2 == xtimer.mode)) { + if (hour > 11) { + hour -= 12; + sign[0] = '-'; + } + } + ResponseAppend_P(PSTR("\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_MODE "\":%d,\"" D_JSON_TIMER_TIME "\":\"%s%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), + index, xtimer.arm, xtimer.mode, sign, hour, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); +#else + ResponseAppend_P(PSTR("\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_TIME "\":\"%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), + index, xtimer.arm, xtimer.time / 60, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); +#endif +} + + + + + +void CmndTimer(void) +{ + uint32_t index = XdrvMailbox.index; + if ((index > 0) && (index <= MAX_TIMERS)) { + uint32_t error = 0; + if (XdrvMailbox.data_len) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAX_TIMERS)) { + if (XdrvMailbox.payload == 0) { + Settings.timer[index -1].data = 0; + } else { + Settings.timer[index -1].data = Settings.timer[XdrvMailbox.payload -1].data; + } + } else { + +#if defined(USE_RULES)==0 && defined(USE_SCRIPT)==0 + if (devices_present) { +#endif + char dataBufUc[XdrvMailbox.data_len]; + UpperCase(dataBufUc, XdrvMailbox.data); + StaticJsonBuffer<256> jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(dataBufUc); + if (!root.success()) { + Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_INVALID_JSON "\"}"), index); + error = 1; + } + else { + char parm_uc[10]; + index--; + if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_ARM))].success()) { + Settings.timer[index].arm = (root[parm_uc] != 0); + } +#ifdef USE_SUNRISE + if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_MODE))].success()) { + Settings.timer[index].mode = (uint8_t)root[parm_uc] & 0x03; + } +#endif + if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_TIME))].success()) { + uint16_t itime = 0; + int8_t value = 0; + uint8_t sign = 0; + char time_str[10]; + + strlcpy(time_str, root[parm_uc], sizeof(time_str)); + const char *substr = strtok(time_str, ":"); + if (substr != nullptr) { + if (strchr(substr, '-')) { + sign = 1; + substr++; + } + value = atoi(substr); + if (sign) { value += 12; } + if (value > 23) { value = 23; } + itime = value * 60; + substr = strtok(nullptr, ":"); + if (substr != nullptr) { + value = atoi(substr); + if (value < 0) { value = 0; } + if (value > 59) { value = 59; } + itime += value; + } + } + Settings.timer[index].time = itime; + } + if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_WINDOW))].success()) { + Settings.timer[index].window = (uint8_t)root[parm_uc] & 0x0F; + TimerSetRandomWindow(index); + } + if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_DAYS))].success()) { + + Settings.timer[index].days = 0; + const char *tday = root[parm_uc]; + uint8_t i = 0; + char ch = *tday++; + while ((ch != '\0') && (i < 7)) { + if (ch == '-') { ch = '0'; } + uint8_t mask = 1 << i++; + Settings.timer[index].days |= (ch == '0') ? 0 : mask; + ch = *tday++; + } + } + if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_REPEAT))].success()) { + Settings.timer[index].repeat = (root[parm_uc] != 0); + } + if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_OUTPUT))].success()) { + uint8_t device = ((uint8_t)root[parm_uc] -1) & 0x0F; + Settings.timer[index].device = (device < devices_present) ? device : 0; + } + if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_ACTION))].success()) { + uint8_t action = (uint8_t)root[parm_uc] & 0x03; + Settings.timer[index].power = (devices_present) ? action : 3; + } + + index++; + } + +#if defined(USE_RULES)==0 && defined(USE_SCRIPT)==0 + } else { + Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_TIMER_NO_DEVICE "\"}"), index); + error = 1; + } +#endif + } + } + if (!error) { + Response_P(PSTR("{")); + PrepShowTimer(index); + ResponseJsonEnd(); + } + } +} + +void CmndTimers(void) +{ + if (XdrvMailbox.data_len) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.flag3.timers_enable = XdrvMailbox.payload; + } + if (XdrvMailbox.payload == 2) { + Settings.flag3.timers_enable = !Settings.flag3.timers_enable; + } + } + + ResponseCmndStateText(Settings.flag3.timers_enable); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command); + + uint32_t jsflg = 0; + uint32_t lines = 1; + for (uint32_t i = 0; i < MAX_TIMERS; i++) { + if (!jsflg) { + Response_P(PSTR("{\"" D_CMND_TIMERS "%d\":{"), lines++); + } else { + ResponseAppend_P(PSTR(",")); + } + jsflg++; + PrepShowTimer(i +1); + if (jsflg > 3) { + ResponseJsonEndEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_TIMERS)); + jsflg = 0; + } + } + mqtt_data[0] = '\0'; +} + +#ifdef USE_SUNRISE +void CmndLongitude(void) +{ + if (XdrvMailbox.data_len) { + Settings.longitude = (int)(CharToFloat(XdrvMailbox.data) *1000000); + } + char lbuff[33]; + dtostrfd(((float)Settings.longitude) /1000000, 6, lbuff); + ResponseCmndChar(lbuff); +} + +void CmndLatitude(void) +{ + if (XdrvMailbox.data_len) { + Settings.latitude = (int)(CharToFloat(XdrvMailbox.data) *1000000); + } + char lbuff[33]; + dtostrfd(((float)Settings.latitude) /1000000, 6, lbuff); + ResponseCmndChar(lbuff); +} +#endif + + + + + +#ifdef USE_WEBSERVER +#ifdef USE_TIMERS_WEB + +#define WEB_HANDLE_TIMER "tm" + +const char S_CONFIGURE_TIMER[] PROGMEM = D_CONFIGURE_TIMER; + +const char HTTP_BTN_MENU_TIMER[] PROGMEM = + "

"; + +const char HTTP_TIMER_SCRIPT1[] PROGMEM = + "var pt=[],ct=99;" + "function ce(i,q){" + "var o=document.createElement('option');" + "o.textContent=i;" + "q.appendChild(o);" + "}"; +#ifdef USE_SUNRISE +const char HTTP_TIMER_SCRIPT2[] PROGMEM = + "function gt(){" + "var m,p,q;" + "m=qs('input[name=\"rd\"]:checked').value;" + "p=pt[ct]&0x7FF;" + "if(m==0){" + "so(0);" + "q=Math.floor(p/60);if(q<10){q='0'+q;}qs('#ho').value=q;" + "q=p%%60;if(q<10){q='0'+q;}qs('#mi').value=q;" + "}" + "if((m==1)||(m==2)){" + "so(1);" + "q=Math.floor(p/60);" + "if(q>=12){q-=12;qs('#dr').selectedIndex=1;}" + "else{qs('#dr').selectedIndex=0;}" + "if(q<10){q='0'+q;}qs('#ho').value=q;" + "q=p%%60;if(q<10){q='0'+q;}qs('#mi').value=q;" + "}" + "}" + "function so(b){" + "o=qs('#ho');" + "e=o.childElementCount;" + "if(b==1){" + "qs('#dr').disabled='';" + "if(e>12){for(i=12;i<=23;i++){o.removeChild(o.lastElementChild);}}" + "}else{" + "qs('#dr').disabled='disabled';" + "if(e<23){for(i=12;i<=23;i++){ce(i,o);}}" + "}" + "}"; +#endif +const char HTTP_TIMER_SCRIPT3[] PROGMEM = + "function st(){" + "var i,l,m,n,p,s;" + "m=0;s=0;" + "n=1<<31;if(eb('a0').checked){s|=n;}" + "n=1<<15;if(eb('r0').checked){s|=n;}" + "for(i=0;i<7;i++){n=1<<(16+i);if(eb('w'+i).checked){s|=n;}}" +#ifdef USE_SUNRISE + "m=qs('input[name=\"rd\"]:checked').value;" + "s|=(qs('input[name=\"rd\"]:checked').value<<29);" +#endif + "if(%d>0){" + "i=qs('#d1').selectedIndex;if(i>=0){s|=(i<<23);}" + "s|=(qs('#p1').selectedIndex<<27);" + "}else{" + "s|=3<<27;" + "}" + "l=((qs('#ho').selectedIndex*60)+qs('#mi').selectedIndex)&0x7FF;" + "if(m==0){s|=l;}" +#ifdef USE_SUNRISE + "if((m==1)||(m==2)){" + "if(qs('#dr').selectedIndex>0){l+=720;}" + "s|=l&0x7FF;" + "}" +#endif + "s|=((qs('#mw').selectedIndex)&0x0F)<<11;" + "pt[ct]=s;" + "eb('t0').value=pt.join();" + "}"; +const char HTTP_TIMER_SCRIPT4[] PROGMEM = + "function ot(t,e){" + "var i,n,o,p,q,s;" + "if(ct<99){st();}" + "ct=t;" + "o=document.getElementsByClassName('tl');" + "for(i=0;i>29)&3;eb('b'+p).checked=1;" + "gt();" +#else + "p=s&0x7FF;" + "q=Math.floor(p/60);if(q<10){q='0'+q;}qs('#ho').value=q;" + "q=p%%60;if(q<10){q='0'+q;}qs('#mi').value=q;" +#endif + "q=(s>>11)&0xF;if(q<10){q='0'+q;}qs('#mw').value=q;" + "for(i=0;i<7;i++){p=(s>>(16+i))&1;eb('w'+i).checked=p;}" + "if(%d>0){" + "p=(s>>23)&0xF;qs('#d1').value=p+1;" + "p=(s>>27)&3;qs('#p1').selectedIndex=p;" + "}" + "p=(s>>15)&1;eb('r0').checked=p;" + "p=(s>>31)&1;eb('a0').checked=p;" + "}"; +const char HTTP_TIMER_SCRIPT5[] PROGMEM = + "function it(){" + "var b,i,o,s;" + "pt=eb('t0').value.split(',').map(Number);" + "s='';" + "for(i=0;i<%d;i++){" + "b='';" + "if(0==i){b=\" id='dP'\";}" + "s+=\"\"" + "}" + "eb('bt').innerHTML=s;" + "if(%d>0){" + "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" + "o=qs('#p1');ce('" D_OFF "',o);ce('" D_ON "',o);ce('" D_TOGGLE "',o);" +#if defined(USE_RULES) || defined(USE_SCRIPT) + "ce('" D_RULE "',o);" +#else + "ce('" D_BLINK "',o);" +#endif + "}else{" + "eb('oa').innerHTML=\"" D_TIMER_ACTION " " D_RULE "\";" + "}"; +const char HTTP_TIMER_SCRIPT6[] PROGMEM = +#ifdef USE_SUNRISE + "o=qs('#dr');ce('+',o);ce('-',o);" +#endif + "o=qs('#ho');for(i=0;i<=23;i++){ce((i<10)?('0'+i):i,o);}" + "o=qs('#mi');for(i=0;i<=59;i++){ce((i<10)?('0'+i):i,o);}" + "o=qs('#mw');for(i=0;i<=15;i++){ce((i<10)?('0'+i):i,o);}" + "o=qs('#d1');for(i=0;i<%d;i++){ce(i+1,o);}" + "var a='" D_DAY3LIST "';" + "s='';for(i=0;i<7;i++){s+=\"\"+a.substring(i*3,(i*3)+3)+\" \"}" + "eb('ds').innerHTML=s;" + "eb('dP').click();" + "}" + "wl(it);"; +const char HTTP_TIMER_STYLE[] PROGMEM = + ".tl{float:left;border-radius:0;border:1px solid #%06x;padding:1px;width:6.25%%;}"; +const char HTTP_FORM_TIMER1[] PROGMEM = + "
" + " " D_TIMER_PARAMETERS " " + "
" + "
" D_TIMER_ENABLE "


" + "



" + "

" + "
" + "" D_TIMER_ARM " " + "" D_TIMER_REPEAT "" + "

" + "
"; +#ifdef USE_SUNRISE +const char HTTP_FORM_TIMER3[] PROGMEM = + "
" + "" D_TIMER_TIME "
" + "" D_SUNRISE " (%s)
" + "" D_SUNSET " (%s)
" + "
" + "

" + "" + " "; +#else +const char HTTP_FORM_TIMER3[] PROGMEM = + "" D_TIMER_TIME " "; +#endif +const char HTTP_FORM_TIMER4[] PROGMEM = + "" + " " D_HOUR_MINUTE_SEPARATOR " " + "" + " +/- " + "" + "

" + "
"; + +void HandleTimerConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TIMER); + + if (WebServer->hasArg("save")) { + TimerSaveSettings(); + HandleConfiguration(); + return; + } + + WSContentStart_P(S_CONFIGURE_TIMER); + WSContentSend_P(HTTP_TIMER_SCRIPT1); +#ifdef USE_SUNRISE + WSContentSend_P(HTTP_TIMER_SCRIPT2); +#endif + WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT4, WebColor(COL_TIMER_TAB_BACKGROUND), WebColor(COL_TIMER_TAB_TEXT), WebColor(COL_FORM), WebColor(COL_TEXT), devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT5, MAX_TIMERS, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present); + WSContentSendStyle_P(HTTP_TIMER_STYLE, WebColor(COL_FORM)); + WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); + for (uint32_t i = 0; i < MAX_TIMERS; i++) { + WSContentSend_P(PSTR("%s%u"), (i > 0) ? "," : "", Settings.timer[i].data); + } + WSContentSend_P(HTTP_FORM_TIMER2); +#ifdef USE_SUNRISE + WSContentSend_P(HTTP_FORM_TIMER3, 100 + (strlen(D_SUNSET) *12), GetSun(0).c_str(), GetSun(1).c_str()); +#else + WSContentSend_P(HTTP_FORM_TIMER3); +#endif + WSContentSend_P(HTTP_FORM_TIMER4); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void TimerSaveSettings(void) +{ + char tmp[MAX_TIMERS *12]; + Timer timer; + + Settings.flag3.timers_enable = WebServer->hasArg("e0"); + WebGetArg("t0", tmp, sizeof(tmp)); + char *p = tmp; + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_TIMERS " %d"), Settings.flag3.timers_enable); + for (uint32_t i = 0; i < MAX_TIMERS; i++) { + timer.data = strtol(p, &p, 10); + p++; + if (timer.time < 1440) { + bool flag = (timer.window != Settings.timer[i].window); + Settings.timer[i].data = timer.data; + if (flag) TimerSetRandomWindow(i); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s,0x%08X"), log_data, Settings.timer[i].data); + } + AddLog(LOG_LEVEL_DEBUG); +} +#endif +#endif + + + + + +bool Xdrv09(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_PRE_INIT: + TimerSetRandomWindows(); + break; +#ifdef USE_WEBSERVER +#ifdef USE_TIMERS_WEB + case FUNC_WEB_ADD_BUTTON: +#if defined(USE_RULES) || defined(USE_SCRIPT) + WSContentSend_P(HTTP_BTN_MENU_TIMER); +#else + if (devices_present) { WSContentSend_P(HTTP_BTN_MENU_TIMER); } +#endif + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_TIMER, HandleTimerConfiguration); + break; +#endif +#endif + case FUNC_EVERY_SECOND: + TimerEverySecond(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kTimerCommands, TimerCommand); + break; + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +#ifdef USE_RULES +#ifndef USE_SCRIPT +# 67 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +#define XDRV_10 10 + +#define D_CMND_RULE "Rule" +#define D_CMND_RULETIMER "RuleTimer" +#define D_CMND_EVENT "Event" +#define D_CMND_VAR "Var" +#define D_CMND_MEM "Mem" +#define D_CMND_ADD "Add" +#define D_CMND_SUB "Sub" +#define D_CMND_MULT "Mult" +#define D_CMND_SCALE "Scale" +#define D_CMND_CALC_RESOLUTION "CalcRes" +#define D_CMND_SUBSCRIBE "Subscribe" +#define D_CMND_UNSUBSCRIBE "Unsubscribe" +#define D_CMND_IF "If" + +#define D_JSON_INITIATED "Initiated" + +#define COMPARE_OPERATOR_NONE -1 +#define COMPARE_OPERATOR_EQUAL 0 +#define COMPARE_OPERATOR_BIGGER 1 +#define COMPARE_OPERATOR_SMALLER 2 +#define COMPARE_OPERATOR_EXACT_DIVISION 3 +#define COMPARE_OPERATOR_NUMBER_EQUAL 4 +#define COMPARE_OPERATOR_NOT_EQUAL 5 +#define COMPARE_OPERATOR_BIGGER_EQUAL 6 +#define COMPARE_OPERATOR_SMALLER_EQUAL 7 +#define MAXIMUM_COMPARE_OPERATOR COMPARE_OPERATOR_SMALLER_EQUAL +const char kCompareOperators[] PROGMEM = "=\0>\0<\0|\0==!=>=<="; + +#ifdef USE_EXPRESSION + #include + + const char kExpressionOperators[] PROGMEM = "+-*/%^"; + #define EXPRESSION_OPERATOR_ADD 0 + #define EXPRESSION_OPERATOR_SUBTRACT 1 + #define EXPRESSION_OPERATOR_MULTIPLY 2 + #define EXPRESSION_OPERATOR_DIVIDEDBY 3 + #define EXPRESSION_OPERATOR_MODULO 4 + #define EXPRESSION_OPERATOR_POWER 5 + + const uint8_t kExpressionOperatorsPriorities[] PROGMEM = {1, 1, 2, 2, 3, 4}; + #define MAX_EXPRESSION_OPERATOR_PRIORITY 4 + + + #define LOGIC_OPERATOR_AND 1 + #define LOGIC_OPERATOR_OR 2 + + #define IF_BLOCK_INVALID -1 + #define IF_BLOCK_ANY 0 + #define IF_BLOCK_ELSEIF 1 + #define IF_BLOCK_ELSE 2 + #define IF_BLOCK_ENDIF 3 +#endif + +const char kRulesCommands[] PROGMEM = "|" + D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM "|" + D_CMND_ADD "|" D_CMND_SUB "|" D_CMND_MULT "|" D_CMND_SCALE "|" D_CMND_CALC_RESOLUTION +#ifdef SUPPORT_MQTT_EVENT + "|" D_CMND_SUBSCRIBE "|" D_CMND_UNSUBSCRIBE +#endif +#ifdef SUPPORT_IF_STATEMENT + "|" D_CMND_IF +#endif + ; + +void (* const RulesCommand[])(void) PROGMEM = { + &CmndRule, &CmndRuleTimer, &CmndEvent, &CmndVariable, &CmndMemory, + &CmndAddition, &CmndSubtract, &CmndMultiply, &CmndScale, &CmndCalcResolution +#ifdef SUPPORT_MQTT_EVENT + , &CmndSubscribe, &CmndUnsubscribe +#endif +#ifdef SUPPORT_IF_STATEMENT + , &CmndIf +#endif + }; + +#ifdef SUPPORT_MQTT_EVENT + #include + typedef struct { + String Event; + String Topic; + String Key; + } MQTT_Subscription; + LinkedList subscriptions; +#endif + +struct RULES { + String event_value; + unsigned long timer[MAX_RULE_TIMERS] = { 0 }; + uint32_t triggers[MAX_RULE_SETS] = { 0 }; + uint8_t trigger_count[MAX_RULE_SETS] = { 0 }; + + long new_power = -1; + long old_power = -1; + long old_dimm = -1; + + uint16_t last_minute = 60; + uint16_t vars_event = 0; + uint8_t mems_event = 0; + bool teleperiod = false; + + char event_data[100]; +} Rules; + +char rules_vars[MAX_RULE_VARS][33] = {{ 0 }}; + +#if (MAX_RULE_VARS>16) +#error MAX_RULE_VARS is bigger than 16 +#endif +#if (MAX_RULE_MEMS>5) +#error MAX_RULE_MEMS is bigger than 5 +#endif + + + +bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) +{ + + + + + bool match = false; + char stemp[10]; + + + int pos = rule.indexOf('#'); + if (pos == -1) { return false; } + + String rule_task = rule.substring(0, pos); + if (Rules.teleperiod) { + int ppos = rule_task.indexOf("TELE-"); + if (ppos == -1) { return false; } + rule_task = rule.substring(5, pos); + } + + String rule_expr = rule.substring(pos +1); + String rule_name, rule_param; + int8_t compareOperator = parseCompareExpression(rule_expr, rule_name, rule_param); + + char rule_svalue[CMDSZ] = { 0 }; + float rule_value = 0; + if (compareOperator != COMPARE_OPERATOR_NONE) { + for (uint32_t i = 0; i < MAX_RULE_VARS; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%%VAR%d%%"), i +1); + if (rule_param.startsWith(stemp)) { + rule_param = rules_vars[i]; + break; + } + } + for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1); + if (rule_param.startsWith(stemp)) { + rule_param = Settings.mems[i]; + break; + } + } + snprintf_P(stemp, sizeof(stemp), PSTR("%%TIME%%")); + if (rule_param.startsWith(stemp)) { + rule_param = String(MinutesPastMidnight()); + } + snprintf_P(stemp, sizeof(stemp), PSTR("%%UPTIME%%")); + if (rule_param.startsWith(stemp)) { + rule_param = String(MinutesUptime()); + } + snprintf_P(stemp, sizeof(stemp), PSTR("%%TIMESTAMP%%")); + if (rule_param.startsWith(stemp)) { + rule_param = GetDateAndTime(DT_LOCAL).c_str(); + } +#if defined(USE_TIMERS) && defined(USE_SUNRISE) + snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNRISE%%")); + if (rule_param.startsWith(stemp)) { + rule_param = String(SunMinutes(0)); + } + snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNSET%%")); + if (rule_param.startsWith(stemp)) { + rule_param = String(SunMinutes(1)); + } +#endif + rule_param.toUpperCase(); + strlcpy(rule_svalue, rule_param.c_str(), sizeof(rule_svalue)); + + int temp_value = GetStateNumber(rule_svalue); + if (temp_value > -1) { + rule_value = temp_value; + } else { + rule_value = CharToFloat((char*)rule_svalue); + } + } + + + StaticJsonBuffer<1024> jsonBuf; + JsonObject &root = jsonBuf.parseObject(event); + if (!root.success()) { return false; } + + const char* str_value; + if ((pos = rule_name.indexOf("[")) > 0) { + int rule_name_idx = rule_name.substring(pos +1).toInt(); + if ((rule_name_idx < 1) || (rule_name_idx > 6)) { + rule_name_idx = 1; + } + rule_name = rule_name.substring(0, pos); + str_value = root[rule_task][rule_name][rule_name_idx -1]; + } else { + str_value = root[rule_task][rule_name]; + } + + + + + if (!root[rule_task][rule_name].success()) { return false; } + + + Rules.event_value = str_value; + + + float value = 0; + if (str_value) { + value = CharToFloat((char*)str_value); + int int_value = int(value); + int int_rule_value = int(rule_value); + switch (compareOperator) { + case COMPARE_OPERATOR_EXACT_DIVISION: + match = (int_rule_value && (int_value % int_rule_value) == 0); + break; + case COMPARE_OPERATOR_EQUAL: + match = (!strcasecmp(str_value, rule_svalue)); + break; + case COMPARE_OPERATOR_BIGGER: + match = (value > rule_value); + break; + case COMPARE_OPERATOR_SMALLER: + match = (value < rule_value); + break; + case COMPARE_OPERATOR_NUMBER_EQUAL: + match = (value == rule_value); + break; + case COMPARE_OPERATOR_NOT_EQUAL: + match = (value != rule_value); + break; + case COMPARE_OPERATOR_BIGGER_EQUAL: + match = (value >= rule_value); + break; + case COMPARE_OPERATOR_SMALLER_EQUAL: + match = (value <= rule_value); + break; + default: + match = true; + } + } else match = true; + + if (bitRead(Settings.rule_once, rule_set)) { + if (match) { + if (!bitRead(Rules.triggers[rule_set], Rules.trigger_count[rule_set])) { + bitSet(Rules.triggers[rule_set], Rules.trigger_count[rule_set]); + } else { + match = false; + } + } else { + bitClear(Rules.triggers[rule_set], Rules.trigger_count[rule_set]); + } + } + + return match; +} +# 348 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +int8_t parseCompareExpression(String &expr, String &leftExpr, String &rightExpr) +{ + char compare_operator[3]; + int8_t compare = COMPARE_OPERATOR_NONE; + leftExpr = expr; + int position; + for (int8_t i = MAXIMUM_COMPARE_OPERATOR; i >= 0; i--) { + snprintf_P(compare_operator, sizeof(compare_operator), kCompareOperators + (i *2)); + if ((position = expr.indexOf(compare_operator)) > 0) { + compare = i; + leftExpr = expr.substring(0, position); + leftExpr.trim(); + rightExpr = expr.substring(position + strlen(compare_operator)); + rightExpr.trim(); + break; + } + } + return compare; +} + + + +bool RuleSetProcess(uint8_t rule_set, String &event_saved) +{ + bool serviced = false; + char stemp[10]; + + delay(0); + + + + String rules = Settings.rules[rule_set]; + + Rules.trigger_count[rule_set] = 0; + int plen = 0; + int plen2 = 0; + bool stop_all_rules = false; + while (true) { + rules = rules.substring(plen); + rules.trim(); + if (!rules.length()) { return serviced; } + + String rule = rules; + rule.toUpperCase(); + if (!rule.startsWith("ON ")) { return serviced; } + + int pevt = rule.indexOf(" DO "); + if (pevt == -1) { return serviced; } + String event_trigger = rule.substring(3, pevt); + + plen = rule.indexOf(" ENDON"); + plen2 = rule.indexOf(" BREAK"); + if ((plen == -1) && (plen2 == -1)) { return serviced; } + + if (plen == -1) { plen = 9999; } + if (plen2 == -1) { plen2 = 9999; } + plen = tmin(plen, plen2); + if (plen == plen2) { stop_all_rules = true; } + + String commands = rules.substring(pevt +4, plen); + plen += 6; + Rules.event_value = ""; + String event = event_saved; + + + + if (RulesRuleMatch(rule_set, event, event_trigger)) { + commands.trim(); + String ucommand = commands; + ucommand.toUpperCase(); + + if (ucommand.indexOf("EVENT ") != -1) { commands = "backlog " + commands; } + commands.replace(F("%value%"), Rules.event_value); + for (uint32_t i = 0; i < MAX_RULE_VARS; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%%var%d%%"), i +1); + commands.replace(stemp, rules_vars[i]); + } + for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%%mem%d%%"), i +1); + commands.replace(stemp, Settings.mems[i]); + } + commands.replace(F("%time%"), String(MinutesPastMidnight())); + commands.replace(F("%uptime%"), String(MinutesUptime())); + commands.replace(F("%timestamp%"), GetDateAndTime(DT_LOCAL).c_str()); +#if defined(USE_TIMERS) && defined(USE_SUNRISE) + commands.replace(F("%sunrise%"), String(SunMinutes(0))); + commands.replace(F("%sunset%"), String(SunMinutes(1))); +#endif + + char command[commands.length() +1]; + strlcpy(command, commands.c_str(), sizeof(command)); + + AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: %s performs \"%s\""), event_trigger.c_str(), command); + + + +#ifdef SUPPORT_IF_STATEMENT + char *pCmd = command; + RulesPreprocessCommand(pCmd); +#endif + ExecuteCommand(command, SRC_RULE); + serviced = true; + if (stop_all_rules) { return serviced; } + } + Rules.trigger_count[rule_set]++; + } + return serviced; +} + + + +bool RulesProcessEvent(char *json_event) +{ + bool serviced = false; + +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("RulesProcessEvent")); +#endif + + String event_saved = json_event; + + + + char *p = strchr(json_event, ':'); + if ((p != NULL) && !(strchr(++p, ':'))) { + event_saved.replace(F(":"), F(":{\"Data\":")); + event_saved += F("}"); + + } + event_saved.toUpperCase(); + + + + for (uint32_t i = 0; i < MAX_RULE_SETS; i++) { + if (strlen(Settings.rules[i]) && bitRead(Settings.rule_enabled, i)) { + if (RuleSetProcess(i, event_saved)) { serviced = true; } + } + } + return serviced; +} + +bool RulesProcess(void) +{ + return RulesProcessEvent(mqtt_data); +} + +void RulesInit(void) +{ + rules_flag.data = 0; + for (uint32_t i = 0; i < MAX_RULE_SETS; i++) { + if (Settings.rules[i][0] == '\0') { + bitWrite(Settings.rule_enabled, i, 0); + bitWrite(Settings.rule_once, i, 0); + } + } + Rules.teleperiod = false; +} + +void RulesEvery50ms(void) +{ + if (Settings.rule_enabled) { + char json_event[120]; + + if (-1 == Rules.new_power) { Rules.new_power = power; } + if (Rules.new_power != Rules.old_power) { + if (Rules.old_power != -1) { + for (uint32_t i = 0; i < devices_present; i++) { + uint8_t new_state = (Rules.new_power >> i) &1; + if (new_state != ((Rules.old_power >> i) &1)) { + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Power%d\":{\"State\":%d}}"), i +1, new_state); + RulesProcessEvent(json_event); + } + } + } else { + + for (uint32_t i = 0; i < devices_present; i++) { + uint8_t new_state = (Rules.new_power >> i) &1; + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Power%d\":{\"Boot\":%d}}"), i +1, new_state); + RulesProcessEvent(json_event); + } + + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { +#ifdef USE_TM1638 + if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { +#else + if (pin[GPIO_SWT1 +i] < 99) { +#endif + bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"" D_JSON_SWITCH "%d\":{\"Boot\":%d}}"), i +1, (swm ^ SwitchLastState(i))); + RulesProcessEvent(json_event); + } + } + } + Rules.old_power = Rules.new_power; + } + else if (Rules.old_dimm != Settings.light_dimmer) { + if (Rules.old_dimm != -1) { + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Dimmer\":{\"State\":%d}}"), Settings.light_dimmer); + } else { + + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Dimmer\":{\"Boot\":%d}}"), Settings.light_dimmer); + } + RulesProcessEvent(json_event); + Rules.old_dimm = Settings.light_dimmer; + } + else if (Rules.event_data[0]) { + char *event; + char *parameter; + event = strtok_r(Rules.event_data, "=", ¶meter); + if (event) { + event = Trim(event); + if (parameter) { + parameter = Trim(parameter); + } else { + parameter = event + strlen(event); + } + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Event\":{\"%s\":\"%s\"}}"), event, parameter); + Rules.event_data[0] ='\0'; + RulesProcessEvent(json_event); + } else { + Rules.event_data[0] ='\0'; + } + } + else if (Rules.vars_event || Rules.mems_event){ + if (Rules.vars_event) { + for (uint32_t i = 0; i < MAX_RULE_VARS; i++) { + if (bitRead(Rules.vars_event, i)) { + bitClear(Rules.vars_event, i); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Var%d\":{\"State\":%s}}"), i+1, rules_vars[i]); + RulesProcessEvent(json_event); + break; + } + } + } + if (Rules.mems_event) { + for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { + if (bitRead(Rules.mems_event, i)) { + bitClear(Rules.mems_event, i); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Mem%d\":{\"State\":%s}}"), i+1, Settings.mems[i]); + RulesProcessEvent(json_event); + break; + } + } + } + } + else if (rules_flag.data) { + uint16_t mask = 1; + for (uint32_t i = 0; i < MAX_RULES_FLAG; i++) { + if (rules_flag.data & mask) { + rules_flag.data ^= mask; + json_event[0] = '\0'; + switch (i) { + case 0: strncpy_P(json_event, PSTR("{\"System\":{\"Boot\":1}}"), sizeof(json_event)); break; + case 1: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Initialized\":%d}}"), MinutesPastMidnight()); break; + case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), MinutesPastMidnight()); break; + case 3: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Connected\":1}}"), sizeof(json_event)); break; + case 4: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Disconnected\":1}}"), sizeof(json_event)); break; + case 5: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Connected\":1}}"), sizeof(json_event)); break; + case 6: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Disconnected\":1}}"), sizeof(json_event)); break; + case 7: strncpy_P(json_event, PSTR("{\"HTTP\":{\"Initialized\":1}}"), sizeof(json_event)); break; + } + if (json_event[0]) { + RulesProcessEvent(json_event); + break; + } + } + mask <<= 1; + } + } + } +} + +uint8_t rules_xsns_index = 0; + +void RulesEvery100ms(void) +{ + if (Settings.rule_enabled && (uptime > 4)) { + mqtt_data[0] = '\0'; + int tele_period_save = tele_period; + tele_period = 2; + XsnsNextCall(FUNC_JSON_APPEND, rules_xsns_index); + tele_period = tele_period_save; + if (strlen(mqtt_data)) { + mqtt_data[0] = '{'; + ResponseJsonEnd(); + RulesProcess(); + } + } +} + +void RulesEverySecond(void) +{ + if (Settings.rule_enabled) { + char json_event[120]; + + if (RtcTime.valid) { + if ((uptime > 60) && (RtcTime.minute != Rules.last_minute)) { + Rules.last_minute = RtcTime.minute; + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Minute\":%d}}"), MinutesPastMidnight()); + RulesProcessEvent(json_event); + } + } + for (uint32_t i = 0; i < MAX_RULE_TIMERS; i++) { + if (Rules.timer[i] != 0L) { + if (TimeReached(Rules.timer[i])) { + Rules.timer[i] = 0L; + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Rules\":{\"Timer\":%d}}"), i +1); + RulesProcessEvent(json_event); + } + } + } + } +} + +void RulesSaveBeforeRestart(void) +{ + if (Settings.rule_enabled) { + char json_event[32]; + + strncpy_P(json_event, PSTR("{\"System\":{\"Save\":1}}"), sizeof(json_event)); + RulesProcessEvent(json_event); + } +} + +void RulesSetPower(void) +{ + Rules.new_power = XdrvMailbox.index; +} + +void RulesTeleperiod(void) +{ + Rules.teleperiod = true; + RulesProcess(); + Rules.teleperiod = false; +} + +#ifdef SUPPORT_MQTT_EVENT +# 695 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +bool RulesMqttData(void) +{ + bool serviced = false; + if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) { + return false; + } + String sTopic = XdrvMailbox.topic; + String sData = XdrvMailbox.data; + + MQTT_Subscription event_item; + + for (uint32_t index = 0; index < subscriptions.size(); index++) { + event_item = subscriptions.get(index); + + + if (sTopic.startsWith(event_item.Topic)) { + + serviced = true; + String value; + if (event_item.Key.length() == 0) { + value = sData; + } else { + StaticJsonBuffer<500> jsonBuf; + JsonObject& jsonData = jsonBuf.parseObject(sData); + String key1 = event_item.Key; + String key2; + if (!jsonData.success()) break; + int dot; + if ((dot = key1.indexOf('.')) > 0) { + key2 = key1.substring(dot+1); + key1 = key1.substring(0, dot); + if (!jsonData[key1][key2].success()) break; + value = (const char *)jsonData[key1][key2]; + } else { + if (!jsonData[key1].success()) break; + value = (const char *)jsonData[key1]; + } + } + value.trim(); + + snprintf_P(Rules.event_data, sizeof(Rules.event_data), PSTR("%s=%s"), event_item.Event.c_str(), value.c_str()); + } + } + return serviced; +} +# 757 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +void CmndSubscribe(void) +{ + MQTT_Subscription subscription_item; + String events; + if (XdrvMailbox.data_len > 0) { + char parameters[XdrvMailbox.data_len+1]; + memcpy(parameters, XdrvMailbox.data, XdrvMailbox.data_len); + parameters[XdrvMailbox.data_len] = '\0'; + String event_name, topic, key; + + char * pos = strtok(parameters, ","); + if (pos) { + event_name = Trim(pos); + pos = strtok(nullptr, ","); + if (pos) { + topic = Trim(pos); + pos = strtok(nullptr, ","); + if (pos) { + key = Trim(pos); + } + } + } + + event_name.toUpperCase(); + if (event_name.length() > 0 && topic.length() > 0) { + + for (uint32_t index=0; index < subscriptions.size(); index++) { + if (subscriptions.get(index).Event.equals(event_name)) { + + String stopic = subscriptions.get(index).Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + subscriptions.remove(index); + break; + } + } + + if (!topic.endsWith("#")) { + if (topic.endsWith("/")) { + topic.concat("#"); + } else { + topic.concat("/#"); + } + } + + + subscription_item.Event = event_name; + subscription_item.Topic = topic.substring(0, topic.length() - 2); + subscription_item.Key = key; + subscriptions.add(subscription_item); + + MqttSubscribe(topic.c_str()); + events.concat(event_name + "," + topic + + (key.length()>0 ? "," : "") + + key); + } else { + events = D_JSON_WRONG_PARAMETERS; + } + } else { + + for (uint32_t index=0; index < subscriptions.size(); index++) { + subscription_item = subscriptions.get(index); + events.concat(subscription_item.Event + "," + subscription_item.Topic + + (subscription_item.Key.length()>0 ? "," : "") + + subscription_item.Key + "; "); + } + } + ResponseCmndChar(events.c_str()); +} +# 837 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +void CmndUnsubscribe(void) +{ + MQTT_Subscription subscription_item; + String events; + if (XdrvMailbox.data_len > 0) { + for (uint32_t index = 0; index < subscriptions.size(); index++) { + subscription_item = subscriptions.get(index); + if (subscription_item.Event.equalsIgnoreCase(XdrvMailbox.data)) { + String stopic = subscription_item.Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + events = subscription_item.Event; + subscriptions.remove(index); + break; + } + } + } else { + + String stopic; + while (subscriptions.size() > 0) { + events.concat(subscriptions.get(0).Event + "; "); + stopic = subscriptions.get(0).Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + subscriptions.remove(0); + } + } + ResponseCmndChar(events.c_str()); +} + +#endif + +#ifdef USE_EXPRESSION +# 879 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +char * findClosureBracket(char * pStart) +{ + char * pointer = pStart + 1; + + bool bFindClosures = false; + uint8_t matchClosures = 1; + while (*pointer) + { + if (*pointer == ')') { + matchClosures--; + if (matchClosures == 0) { + bFindClosures = true; + break; + } + } else if (*pointer == '(') { + matchClosures++; + } + pointer++; + } + if (bFindClosures) { + return pointer; + } else { + return nullptr; + } +} +# 918 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +bool findNextNumber(char * &pNumber, float &value) +{ + bool bSucceed = false; + String sNumber = ""; + while (*pNumber) { + if (isdigit(*pNumber) || (*pNumber == '.')) { + sNumber += *pNumber; + pNumber++; + } else { + break; + } + } + if (sNumber.length() > 0) { + value = CharToFloat(sNumber.c_str()); + bSucceed = true; + } + return bSucceed; +} +# 950 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +bool findNextVariableValue(char * &pVarname, float &value) +{ + bool succeed = true; + value = 0; + String sVarName = ""; + while (*pVarname) { + if (isalpha(*pVarname) || isdigit(*pVarname)) { + sVarName.concat(*pVarname); + pVarname++; + } else { + break; + } + } + sVarName.toUpperCase(); + if (sVarName.startsWith(F("VAR"))) { + int index = sVarName.substring(3).toInt(); + if (index > 0 && index <= MAX_RULE_VARS) { + value = CharToFloat(rules_vars[index -1]); + } + } else if (sVarName.startsWith(F("MEM"))) { + int index = sVarName.substring(3).toInt(); + if (index > 0 && index <= MAX_RULE_MEMS) { + value = CharToFloat(Settings.mems[index -1]); + } + } else if (sVarName.equals(F("TIME"))) { + value = MinutesPastMidnight(); + } else if (sVarName.equals(F("UPTIME"))) { + value = MinutesUptime(); + } else if (sVarName.equals(F("UTCTIME"))) { + value = UtcTime(); + } else if (sVarName.equals(F("LOCALTIME"))) { + value = LocalTime(); +#if defined(USE_TIMERS) && defined(USE_SUNRISE) + } else if (sVarName.equals(F("SUNRISE"))) { + value = SunMinutes(0); + } else if (sVarName.equals(F("SUNSET"))) { + value = SunMinutes(1); +#endif + } else { + succeed = false; + } + + return succeed; +} +# 1012 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +bool findNextObjectValue(char * &pointer, float &value) +{ + bool bSucceed = false; + while (*pointer) + { + if (isspace(*pointer)) { + pointer++; + continue; + } + if (isdigit(*pointer)) { + bSucceed = findNextNumber(pointer, value); + break; + } else if (isalpha(*pointer)) { + bSucceed = findNextVariableValue(pointer, value); + break; + } else if (*pointer == '(') { + char * closureBracket = findClosureBracket(pointer); + if (closureBracket != nullptr) { + value = evaluateExpression(pointer+1, closureBracket - pointer - 2); + pointer = closureBracket + 1; + bSucceed = true; + } + break; + } else { + break; + } + } + return bSucceed; +} +# 1056 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +bool findNextOperator(char * &pointer, int8_t &op) +{ + bool bSucceed = false; + while (*pointer) + { + if (isspace(*pointer)) { + pointer++; + continue; + } + if (char *pch = strchr(kExpressionOperators, *pointer)) { + op = (int8_t)(pch - kExpressionOperators); + pointer++; + bSucceed = true; + } + break; + } + return bSucceed; +} +# 1087 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +float calculateTwoValues(float v1, float v2, uint8_t op) +{ + switch (op) + { + case EXPRESSION_OPERATOR_ADD: + return v1 + v2; + case EXPRESSION_OPERATOR_SUBTRACT: + return v1 - v2; + case EXPRESSION_OPERATOR_MULTIPLY: + return v1 * v2; + case EXPRESSION_OPERATOR_DIVIDEDBY: + return (0 == v2) ? 0 : (v1 / v2); + case EXPRESSION_OPERATOR_MODULO: + return (0 == v2) ? 0 : (int(v1) % int(v2)); + case EXPRESSION_OPERATOR_POWER: + return FastPrecisePow(v1, v2); + } + return 0; +} +# 1140 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +float evaluateExpression(const char * expression, unsigned int len) +{ + char expbuf[len + 1]; + memcpy(expbuf, expression, len); + expbuf[len] = '\0'; + char * scan_pointer = expbuf; + + LinkedList object_values; + LinkedList operators; + int8_t op; + float va; + + if (findNextObjectValue(scan_pointer, va)) { + object_values.add(va); + } else { + return 0; + } + while (*scan_pointer) + { + if (findNextOperator(scan_pointer, op) + && *scan_pointer + && findNextObjectValue(scan_pointer, va)) + { + operators.add(op); + object_values.add(va); + } else { + + break; + } + } + + + + for (int32_t priority = MAX_EXPRESSION_OPERATOR_PRIORITY; priority>0; priority--) { + int index = 0; + while (index < operators.size()) { + if (priority == kExpressionOperatorsPriorities[(operators.get(index))]) { + + va = calculateTwoValues(object_values.get(index), object_values.remove(index + 1), operators.remove(index)); + + object_values.set(index, va); + } else { + index++; + } + } + } + return object_values.get(0); +} +#endif + +#ifdef SUPPORT_IF_STATEMENT +void CmndIf() +{ + if (XdrvMailbox.data_len > 0) { + char parameters[XdrvMailbox.data_len+1]; + memcpy(parameters, XdrvMailbox.data, XdrvMailbox.data_len); + parameters[XdrvMailbox.data_len] = '\0'; + ProcessIfStatement(parameters); + } + ResponseCmndDone(); +} +# 1214 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +bool evaluateComparisonExpression(const char *expression, int len) +{ + bool bResult = true; + char expbuf[len + 1]; + memcpy(expbuf, expression, len); + expbuf[len] = '\0'; + String compare_expression = expbuf; + String leftExpr, rightExpr; + int8_t compareOp = parseCompareExpression(compare_expression, leftExpr, rightExpr); + + double leftValue = evaluateExpression(leftExpr.c_str(), leftExpr.length()); + double rightValue = evaluateExpression(rightExpr.c_str(), rightExpr.length()); + switch (compareOp) { + case COMPARE_OPERATOR_EXACT_DIVISION: + bResult = (rightValue != 0 && leftValue == int(leftValue) + && rightValue == int(rightValue) && (int(leftValue) % int(rightValue)) == 0); + break; + case COMPARE_OPERATOR_EQUAL: + bResult = leftExpr.equalsIgnoreCase(rightExpr); + break; + case COMPARE_OPERATOR_BIGGER: + bResult = (leftValue > rightValue); + break; + case COMPARE_OPERATOR_SMALLER: + bResult = (leftValue < rightValue); + break; + case COMPARE_OPERATOR_NUMBER_EQUAL: + bResult = (leftValue == rightValue); + break; + case COMPARE_OPERATOR_NOT_EQUAL: + bResult = (leftValue != rightValue); + break; + case COMPARE_OPERATOR_BIGGER_EQUAL: + bResult = (leftValue >= rightValue); + break; + case COMPARE_OPERATOR_SMALLER_EQUAL: + bResult = (leftValue <= rightValue); + break; + } + return bResult; +} +# 1270 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +bool findNextLogicOperator(char * &pointer, int8_t &op) +{ + bool bSucceed = false; + while (*pointer && isspace(*pointer)) { + + pointer++; + } + if (*pointer) { + if (strncasecmp_P(pointer, PSTR("AND "), 4) == 0) { + op = LOGIC_OPERATOR_AND; + pointer += 4; + bSucceed = true; + } else if (strncasecmp_P(pointer, PSTR("OR "), 3) == 0) { + op = LOGIC_OPERATOR_OR; + pointer += 3; + bSucceed = true; + } + } + return bSucceed; +} +# 1307 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +bool findNextLogicObjectValue(char * &pointer, bool &value) +{ + bool bSucceed = false; + while (*pointer && isspace(*pointer)) { + + pointer++; + } + char * pExpr = pointer; + while (*pointer) { + if (isalpha(*pointer) + && (strncasecmp_P(pointer, PSTR("AND "), 4) == 0 + || strncasecmp_P(pointer, PSTR("OR "), 3) == 0)) + { + value = evaluateComparisonExpression(pExpr, pointer - pExpr); + bSucceed = true; + break; + } else if (*pointer == '(') { + char * closureBracket = findClosureBracket(pointer); + if (closureBracket != nullptr) { + value = evaluateLogicalExpression(pointer+1, closureBracket - pointer - 2); + pointer = closureBracket + 1; + bSucceed = true; + } + break; + } + pointer++; + } + if (!bSucceed && pointer > pExpr) { + + value = evaluateComparisonExpression(pExpr, pointer - pExpr); + bSucceed = true; + } + return bSucceed; +} +# 1356 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +bool evaluateLogicalExpression(const char * expression, int len) +{ + bool bResult = false; + + char expbuff[len + 1]; + memcpy(expbuff, expression, len); + expbuff[len] = '\0'; + + + + char * pointer = expbuff; + LinkedList values; + LinkedList logicOperators; + + bool bValue; + if (findNextLogicObjectValue(pointer, bValue)) { + values.add(bValue); + } else { + return false; + } + int8_t op; + while (*pointer) { + if (findNextLogicOperator(pointer, op) + && (*pointer) && findNextLogicObjectValue(pointer, bValue)) + { + logicOperators.add(op); + values.add(bValue); + } else { + break; + } + } + + int index = 0; + while (index < logicOperators.size()) { + if (logicOperators.get(index) == LOGIC_OPERATOR_AND) { + values.set(index, values.get(index) && values.get(index+1)); + values.remove(index + 1); + logicOperators.remove(index); + } else { + index++; + } + } + + index = 0; + while (index < logicOperators.size()) { + if (logicOperators.get(index) == LOGIC_OPERATOR_OR) { + values.set(index, values.get(index) || values.get(index+1)); + values.remove(index + 1); + logicOperators.remove(index); + } else { + index++; + } + } + return values.get(0); +} +# 1428 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +int8_t findIfBlock(char * &pointer, int &lenWord, int8_t block_type) +{ + int8_t foundBlock = IF_BLOCK_INVALID; + + const char * word; + while (*pointer) { + if (!isalpha(*pointer)) { + pointer++; + continue; + } + word = pointer; + while (*pointer && isalpha(*pointer)) { + pointer++; + } + lenWord = pointer - word; + + if (2 == lenWord && 0 == strncasecmp_P(word, PSTR("IF"), 2)) { + + + if (findIfBlock(pointer, lenWord, IF_BLOCK_ENDIF) != IF_BLOCK_ENDIF) { + + break; + } + } else if ( (IF_BLOCK_ENDIF == block_type || IF_BLOCK_ANY == block_type) + && (5 == lenWord) && (0 == strncasecmp_P(word, PSTR("ENDIF"), 5))) + { + + foundBlock = IF_BLOCK_ENDIF; + break; + } else if ( (IF_BLOCK_ELSEIF == block_type || IF_BLOCK_ANY == block_type) + && (6 == lenWord) && (0 == strncasecmp_P(word, PSTR("ELSEIF"), 6))) + { + + foundBlock = IF_BLOCK_ELSEIF; + break; + } else if ( (IF_BLOCK_ELSE == block_type || IF_BLOCK_ANY == block_type) + && (4 == lenWord) && (0 == strncasecmp_P(word, PSTR("ELSE"), 4))) + { + + foundBlock = IF_BLOCK_ELSE; + break; + } + } + return foundBlock; +} +# 1485 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +void ExecuteCommandBlock(const char * commands, int len) +{ + char cmdbuff[len + 1]; + memcpy(cmdbuff, commands, len); + cmdbuff[len] = '\0'; + + + + char oneCommand[len + 1]; + int insertPosition = 0; + char * pos = cmdbuff; + int lenEndBlock = 0; + while (*pos) { + if (isspace(*pos) || '\x1e' == *pos || ';' == *pos) { + pos++; + continue; + } + if (strncasecmp_P(pos, PSTR("BACKLOG "), 8) == 0) { + + pos += 8; + continue; + } + if (strncasecmp_P(pos, PSTR("IF "), 3) == 0) { + + + char *pEndif = pos + 3; + if (IF_BLOCK_ENDIF != findIfBlock(pEndif, lenEndBlock, IF_BLOCK_ENDIF)) { + + break; + } + + memcpy(oneCommand, pos, pEndif - pos); + oneCommand[pEndif - pos] = '\0'; + pos = pEndif; + } else { + + char *pEndOfCommand = strpbrk(pos, "\x1e;"); + if (NULL == pEndOfCommand) { + pEndOfCommand = pos + strlen(pos); + } + memcpy(oneCommand, pos, pEndOfCommand - pos); + oneCommand[pEndOfCommand - pos] = '\0'; + pos = pEndOfCommand; + } + + + String sCurrentCommand = oneCommand; + sCurrentCommand.trim(); + if (sCurrentCommand.length() > 0 + && backlog.size() < MAX_BACKLOG && !backlog_mutex) + { + + backlog_mutex = true; + backlog.add(insertPosition, sCurrentCommand); + backlog_mutex = false; + insertPosition++; + } + } + return; +} +# 1556 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +void ProcessIfStatement(const char* statements) +{ + String conditionExpression; + int len = strlen(statements); + char statbuff[len + 1]; + memcpy(statbuff, statements, len + 1); + char *pos = statbuff; + int lenEndBlock = 0; + while (true) { + + + while (*pos && *pos != '(') { + pos++; + } + if (0 == *pos) { break; } + char * posEnd = findClosureBracket(pos); + + if (true == evaluateLogicalExpression(pos + 1, posEnd - (pos + 1))) { + + char * cmdBlockStart = posEnd + 1; + char * cmdBlockEnd = cmdBlockStart; + int8_t nextBlock = findIfBlock(cmdBlockEnd, lenEndBlock, IF_BLOCK_ANY); + if (IF_BLOCK_INVALID == nextBlock) { + + break; + } + ExecuteCommandBlock(cmdBlockStart, cmdBlockEnd - cmdBlockStart - lenEndBlock); + pos = cmdBlockEnd; + break; + } else { + pos = posEnd + 1; + int8_t nextBlock = findIfBlock(pos, lenEndBlock, IF_BLOCK_ANY); + if (IF_BLOCK_ELSEIF == nextBlock) { + + continue; + } else if (IF_BLOCK_ELSE == nextBlock) { + + char * cmdBlockEnd = pos; + int8_t nextBlock = findIfBlock(cmdBlockEnd, lenEndBlock, IF_BLOCK_ENDIF); + if (IF_BLOCK_ENDIF != nextBlock) { + + break; + } + ExecuteCommandBlock(pos, cmdBlockEnd - pos - lenEndBlock); + break; + } else { + + break; + } + } + } +} +# 1620 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" +void RulesPreprocessCommand(char *pCommands) +{ + char * cmd = pCommands; + int lenEndBlock = 0; + while (*cmd) { + + if (';' == *cmd || isspace(*cmd)) { + cmd++; + } + else if (strncasecmp_P(cmd, PSTR("IF "), 3) == 0) { + + char * pIfStart = cmd; + char * pIfEnd = pIfStart + 3; + + if (IF_BLOCK_ENDIF == findIfBlock(pIfEnd, lenEndBlock, IF_BLOCK_ENDIF)) { + + cmd = pIfEnd; + + + while (pIfStart < pIfEnd) { + if (';' == *pIfStart) + *pIfStart = '\x1e'; + pIfStart++; + } + } + else { + break; + } + } + else { + while (*cmd && ';' != *cmd) { + cmd++; + } + } + } + return; +} +#endif + + + + + +void CmndRule(void) +{ + uint8_t index = XdrvMailbox.index; + if ((index > 0) && (index <= MAX_RULE_SETS)) { + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.rules[index -1]))) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10)) { + switch (XdrvMailbox.payload) { + case 0: + case 1: + bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload); + break; + case 2: + bitWrite(Settings.rule_enabled, index -1, bitRead(Settings.rule_enabled, index -1) ^1); + break; + case 4: + case 5: + bitWrite(Settings.rule_once, index -1, XdrvMailbox.payload &1); + break; + case 6: + bitWrite(Settings.rule_once, index -1, bitRead(Settings.rule_once, index -1) ^1); + break; + case 8: + case 9: + bitWrite(Settings.rule_stop, index -1, XdrvMailbox.payload &1); + break; + case 10: + bitWrite(Settings.rule_stop, index -1, bitRead(Settings.rule_stop, index -1) ^1); + break; + } + } else { + int offset = 0; + if ('+' == XdrvMailbox.data[0]) { + offset = strlen(Settings.rules[index -1]); + if (XdrvMailbox.data_len < (sizeof(Settings.rules[index -1]) - offset -1)) { + XdrvMailbox.data[0] = ' '; + } else { + offset = -1; + } + } + if (offset != -1) { + strlcpy(Settings.rules[index -1] + offset, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.rules[index -1])); + } + } + Rules.triggers[index -1] = 0; + } + snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"StopOnError\":\"%s\",\"Free\":%d,\"Rules\":\"%s\"}"), + XdrvMailbox.command, index, GetStateText(bitRead(Settings.rule_enabled, index -1)), GetStateText(bitRead(Settings.rule_once, index -1)), + GetStateText(bitRead(Settings.rule_stop, index -1)), sizeof(Settings.rules[index -1]) - strlen(Settings.rules[index -1]) -1, Settings.rules[index -1]); + } +} + +void CmndRuleTimer(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_TIMERS)) { + if (XdrvMailbox.data_len > 0) { +#ifdef USE_EXPRESSION + float timer_set = evaluateExpression(XdrvMailbox.data, XdrvMailbox.data_len); + Rules.timer[XdrvMailbox.index -1] = (timer_set > 0) ? millis() + (1000 * timer_set) : 0; +#else + Rules.timer[XdrvMailbox.index -1] = (XdrvMailbox.payload > 0) ? millis() + (1000 * XdrvMailbox.payload) : 0; +#endif + } + mqtt_data[0] = '\0'; + for (uint32_t i = 0; i < MAX_RULE_TIMERS; i++) { + ResponseAppend_P(PSTR("%c\"T%d\":%d"), (i) ? ',' : '{', i +1, (Rules.timer[i]) ? (Rules.timer[i] - millis()) / 1000 : 0); + } + ResponseJsonEnd(); + } +} + +void CmndEvent(void) +{ + if (XdrvMailbox.data_len > 0) { + strlcpy(Rules.event_data, XdrvMailbox.data, sizeof(Rules.event_data)); + } + ResponseCmndDone(); +} + +void CmndVariable(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) { + if (!XdrvMailbox.usridx) { + mqtt_data[0] = '\0'; + for (uint32_t i = 0; i < MAX_RULE_VARS; i++) { + ResponseAppend_P(PSTR("%c\"Var%d\":\"%s\""), (i) ? ',' : '{', i +1, rules_vars[i]); + } + ResponseJsonEnd(); + } else { + if (XdrvMailbox.data_len > 0) { +#ifdef USE_EXPRESSION + if (XdrvMailbox.data[0] == '=') { + dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]); + } else { + strlcpy(rules_vars[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(rules_vars[XdrvMailbox.index -1])); + } +#else + strlcpy(rules_vars[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(rules_vars[XdrvMailbox.index -1])); +#endif + bitSet(Rules.vars_event, XdrvMailbox.index -1); + } + ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]); + } + } +} + +void CmndMemory(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_MEMS)) { + if (!XdrvMailbox.usridx) { + mqtt_data[0] = '\0'; + for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { + ResponseAppend_P(PSTR("%c\"Mem%d\":\"%s\""), (i) ? ',' : '{', i +1, Settings.mems[i]); + } + ResponseJsonEnd(); + } else { + if (XdrvMailbox.data_len > 0) { +#ifdef USE_EXPRESSION + if (XdrvMailbox.data[0] == '=') { + dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, Settings.mems[XdrvMailbox.index -1]); + } else { + strlcpy(Settings.mems[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[XdrvMailbox.index -1])); + } +#else + strlcpy(Settings.mems[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[XdrvMailbox.index -1])); +#endif + bitSet(Rules.mems_event, XdrvMailbox.index -1); + } + ResponseCmndIdxChar(Settings.mems[XdrvMailbox.index -1]); + } + } +} + +void CmndCalcResolution(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 7)) { + Settings.flag2.calc_resolution = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.flag2.calc_resolution); +} + +void CmndAddition(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) { + if (XdrvMailbox.data_len > 0) { + float tempvar = CharToFloat(rules_vars[XdrvMailbox.index -1]) + CharToFloat(XdrvMailbox.data); + dtostrfd(tempvar, Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]); + bitSet(Rules.vars_event, XdrvMailbox.index -1); + } + ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]); + } +} + +void CmndSubtract(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) { + if (XdrvMailbox.data_len > 0) { + float tempvar = CharToFloat(rules_vars[XdrvMailbox.index -1]) - CharToFloat(XdrvMailbox.data); + dtostrfd(tempvar, Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]); + bitSet(Rules.vars_event, XdrvMailbox.index -1); + } + ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]); + } +} + +void CmndMultiply(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) { + if (XdrvMailbox.data_len > 0) { + float tempvar = CharToFloat(rules_vars[XdrvMailbox.index -1]) * CharToFloat(XdrvMailbox.data); + dtostrfd(tempvar, Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]); + bitSet(Rules.vars_event, XdrvMailbox.index -1); + } + ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]); + } +} + +void CmndScale(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) { + if (XdrvMailbox.data_len > 0) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + char sub_string[XdrvMailbox.data_len +1]; + + float valueIN = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 1)); + float fromLow = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)); + float fromHigh = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 3)); + float toLow = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)); + float toHigh = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 5)); + float value = map_double(valueIN, fromLow, fromHigh, toLow, toHigh); + dtostrfd(value, Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]); + bitSet(Rules.vars_event, XdrvMailbox.index -1); + } + } + ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]); + } +} + +float map_double(float x, float in_min, float in_max, float out_min, float out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + + + + + +bool Xdrv10(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_PRE_INIT: + RulesInit(); + break; + case FUNC_EVERY_50_MSECOND: + RulesEvery50ms(); + break; + case FUNC_EVERY_100_MSECOND: + RulesEvery100ms(); + break; + case FUNC_EVERY_SECOND: + RulesEverySecond(); + break; + case FUNC_SET_POWER: + RulesSetPower(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kRulesCommands, RulesCommand); + break; + case FUNC_RULES_PROCESS: + result = RulesProcess(); + break; + case FUNC_SAVE_BEFORE_RESTART: + RulesSaveBeforeRestart(); + break; +#ifdef SUPPORT_MQTT_EVENT + case FUNC_MQTT_DATA: + result = RulesMqttData(); + break; +#endif + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_scripter.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_scripter.ino" +#ifdef USE_SCRIPT +#ifndef USE_RULES +# 40 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_scripter.ino" +#define XDRV_10 10 + +#define SCRIPT_DEBUG 0 + +#define MAXVARS 50 +#define MAXNVARS 45 +#define MAXSVARS 5 +#define MAXFILT 5 +#define SCRIPT_SVARSIZE 20 +#define SCRIPT_MAXSSIZE 48 +#define SCRIPT_EOL '\n' +#define SCRIPT_FLOAT_PRECISION 2 +#define SCRIPT_MAXPERM (MAX_RULE_MEMS*10)-4/sizeof(float) +#define MAX_SCRIPT_SIZE MAX_RULE_SIZE*MAX_RULE_SETS + + +#define EPOCH_OFFSET 1546300800 + +enum {OPER_EQU=1,OPER_PLS,OPER_MIN,OPER_MUL,OPER_DIV,OPER_PLSEQU,OPER_MINEQU,OPER_MULEQU,OPER_DIVEQU,OPER_EQUEQU,OPER_NOTEQU,OPER_GRTEQU,OPER_LOWEQU,OPER_GRT,OPER_LOW,OPER_PERC,OPER_XOR,OPER_AND,OPER_OR,OPER_ANDEQU,OPER_OREQU,OPER_XOREQU,OPER_PERCEQU}; +enum {SCRIPT_LOGLEVEL=1,SCRIPT_TELEPERIOD}; + +#ifdef USE_SCRIPT_FATFS +#include +#include +#define FAT_SCRIPT_SIZE 4096 +#define FAT_SCRIPT_NAME "script.txt" +#if USE_LONG_FILE_NAMES==1 +#warning ("FATFS long filenames not supported"); +#endif +#if USE_STANDARD_SPI_LIBRARY==0 +#warning ("FATFS standard spi should be used"); +#endif +#endif + +#ifdef SUPPORT_MQTT_EVENT + #include + typedef struct { + String Event; + String Topic; + String Key; + } MQTT_Subscription; + LinkedList subscriptions; +#endif + +#ifdef USE_DISPLAY +#ifdef USE_TOUCH_BUTTONS +#include +extern VButton *buttons[MAXBUTTONS]; +#endif +#endif + +typedef union { + uint8_t data; + struct { + uint8_t is_string : 1; + uint8_t is_permanent : 1; + uint8_t is_timer : 1; + uint8_t is_autoinc : 1; + uint8_t changed : 1; + uint8_t settable : 1; + uint8_t is_filter : 1; + uint8_t constant : 1; + }; +} SCRIPT_TYPE; + +struct T_INDEX { + uint8_t index; + SCRIPT_TYPE bits; +}; + +struct M_FILT { + uint8_t numvals; + uint8_t index; + float maccu; + float rbuff[1]; +}; + +typedef union { + uint8_t data; + struct { + uint8_t nutu8 : 1; + uint8_t nutu7 : 1; + uint8_t nutu6 : 1; + uint8_t nutu5 : 1; + uint8_t nutu4 : 1; + uint8_t nutu3 : 1; + uint8_t is_dir : 1; + uint8_t is_open : 1; + }; +} FILE_FLAGS; + +#define SFS_MAX 4 + +struct SCRIPT_MEM { + float *fvars; + float *s_fvars; + struct T_INDEX *type; + struct M_FILT *mfilt; + char *glob_vnp; + uint8_t *vnp_offset; + char *glob_snp; + char *scriptptr; + char *section_ptr; + char *scriptptr_bu; + char *script_ram; + uint16_t script_size; + uint8_t *script_pram; + uint16_t script_pram_size; + uint8_t numvars; + void *script_mem; + uint16_t script_mem_size; + uint8_t script_dprec; + uint8_t var_not_found; + uint8_t glob_error; + uint8_t max_ssize; + uint8_t script_loglevel; + uint8_t flags; +#ifdef USE_SCRIPT_FATFS + File files[SFS_MAX]; + FILE_FLAGS file_flags[SFS_MAX]; + uint8_t script_sd_found; + char flink[2][14]; +#endif +} glob_script_mem; + + +int16_t last_findex; +uint8_t tasm_cmd_activ=0; +uint8_t fast_script=0; +uint32_t script_lastmillis; + + +char *GetNumericResult(char *lp,uint8_t lastop,float *fp,JsonObject *jo); +char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo); +char *ForceStringVar(char *lp,char *dstr); +void send_download(void); +uint8_t reject(char *name); + +void ScriptEverySecond(void) { + + if (bitRead(Settings.rule_enabled, 0)) { + struct T_INDEX *vtp=glob_script_mem.type; + float delta=(millis()-script_lastmillis)/1000; + script_lastmillis=millis(); + for (uint8_t count=0; count0) { + + *fp-=delta; + if (*fp<0) *fp=0; + } + } + if (vtp[count].bits.is_autoinc) { + + float *fp=&glob_script_mem.fvars[vtp[count].index]; + if (*fp>=0) { + *fp+=delta; + } + } + } + Run_Scripter(">S",2,0); + } +} + +void RulesTeleperiod(void) { + if (bitRead(Settings.rule_enabled, 0) && mqtt_data[0]) Run_Scripter(">T",2, mqtt_data); +} + + +#ifdef USE_24C256 +#ifndef USE_SCRIPT_FATFS + +#include +#define EEPROM_ADDRESS 0x50 + +#define EEP_SCRIPT_SIZE 4095 +static Eeprom24C128_256 eeprom(EEPROM_ADDRESS); + +#define EEP_WRITE(A,B,C) eeprom.writeBytes(A,B,(uint8_t*)C); + +#define EEP_READ(A,B,C) eeprom.readBytes(A,B,(uint8_t*)C); +#endif +#endif + +#define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++; +#define SCRIPT_SKIP_EOL while (*lp==SCRIPT_EOL) lp++; + + +int16_t Init_Scripter(void) { +char *script; + + script=glob_script_mem.script_ram; + + + uint16_t lines=0,nvars=0,svars=0,vars=0; + char *lp=script; + char vnames[MAXVARS*10]; + char *vnames_p=vnames; + char *vnp[MAXVARS]; + char **vnp_p=vnp; + char strings[MAXSVARS*SCRIPT_MAXSSIZE]; + struct M_FILT mfilt[MAXFILT]; + + char *strings_p=strings; + char *snp[MAXSVARS]; + char **snp_p=snp; + uint8_t numperm=0,numflt=0,count; + + glob_script_mem.max_ssize=SCRIPT_SVARSIZE; + glob_script_mem.scriptptr=0; + + if (!*script) return -999; + + float fvalues[MAXVARS]; + struct T_INDEX vtypes[MAXVARS]; + char init=0; + while (1) { + + + SCRIPT_SKIP_SPACES + + if (*lp=='\n' || *lp=='\r') goto next_line; + + if (*lp==';') goto next_line; + if (init) { + + if (*lp=='>') { + init=0; + break; + } + char *op=strchr(lp,'='); + if (op) { + vtypes[vars].bits.data=0; + + if (*lp=='p' && *(lp+1)==':') { + lp+=2; + if (numpermMAXFILT) { + return -6; + } + } else { + vtypes[vars].bits.is_filter=0; + } + *vnp_p++=vnames_p; + while (lpMAXNVARS) { + return -1; + } + if (vtypes[vars].bits.is_filter) { + while (isdigit(*op) || *op=='.' || *op=='-') { + op++; + } + while (*op==' ') op++; + if (isdigit(*op)) { + + uint8_t flen=atoi(op); + mfilt[numflt-1].numvals&=0x80; + mfilt[numflt-1].numvals|=flen&0x7f; + } + } + + } else { + + op++; + *snp_p++=strings_p; + while (*op!='\"') { + if (*op==SCRIPT_EOL) break; + *strings_p++=*op++; + } + *strings_p++=0; + vtypes[vars].bits.is_string=1; + vtypes[vars].index=svars; + svars++; + if (svars>MAXSVARS) { + return -2; + } + } + vars++; + if (vars>MAXVARS) { + return -3; + } + } + } else { + if (!strncmp(lp,">D",2)) { + lp+=2; + SCRIPT_SKIP_SPACES + if (isdigit(*lp)) { + uint8_t ssize=atoi(lp)+1; + if (ssize<10 || ssize>SCRIPT_MAXSSIZE) ssize=SCRIPT_MAXSSIZE; + glob_script_mem.max_ssize=ssize; + } + init=1; + } + } + + next_line: + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + + uint16_t fsize=0; + for (count=0; countnumvals=mfilt[count].numvals; + mp+=sizeof(struct M_FILT)+((mfilt[count].numvals&0x7f)-1)*sizeof(float); + } + + glob_script_mem.numvars=vars; + glob_script_mem.script_dprec=SCRIPT_FLOAT_PRECISION; + glob_script_mem.script_loglevel=LOG_LEVEL_INFO; + + +#if SCRIPT_DEBUG>2 + struct T_INDEX *dvtp=glob_script_mem.type; + for (uint8_t count=0; count0 + ClaimSerial(); + SetSerialBaudrate(9600); +#endif + + + glob_script_mem.scriptptr=lp-1; + glob_script_mem.scriptptr_bu=glob_script_mem.scriptptr; + return 0; + +} + +#ifdef USE_LIGHT +#ifdef USE_WS2812 +void ws2812_set_array(float *array ,uint8_t len) { + + Ws2812ForceSuspend(); + for (uint8_t cnt=0;cntSettings.light_pixels) break; + uint32_t col=array[cnt]; + Ws2812SetColor(cnt+1,col>>16,col>>8,col,0); + } + Ws2812ForceUpdate(); +} +#endif +#endif + +#define NUM_RES 0xfe +#define STR_RES 0xfd +#define VAR_NV 0xff + +#define NTYPE 0 +#define STYPE 0x80 + +#define FLT_MAX 99999999 + +float median_array(float *array,uint8_t len) { + uint8_t ind[len]; + uint8_t mind=0,index=0,flg; + float min=FLT_MAX; + + for (uint8_t hcnt=0; hcntnumvals&0x7f; + return mflp->rbuff; + } + mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); + } + return 0; +} + + +float Get_MFVal(uint8_t index,uint8_t bind) { + uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; + for (uint8_t count=0; countnumvals&0x7f; + if (!bind) { + return mflp->index; + } + if (bind<1 || bind>maxind) bind=maxind; + return mflp->rbuff[bind-1]; + } + mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); + } + return 0; +} + +void Set_MFVal(uint8_t index,uint8_t bind,float val) { + uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; + for (uint8_t count=0; countnumvals&0x7f; + if (!bind) { + mflp->index=val; + } else { + if (bind<1 || bind>maxind) bind=maxind; + mflp->rbuff[bind-1]=val; + } + return; + } + mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); + } +} + + +float Get_MFilter(uint8_t index) { + uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; + for (uint8_t count=0; countnumvals&0x80) { + + return mflp->maccu/(mflp->numvals&0x7f); + } else { + + return median_array(mflp->rbuff,mflp->numvals); + } + } + mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); + } + return 0; +} + +void Set_MFilter(uint8_t index, float invar) { + uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; + for (uint8_t count=0; countnumvals&0x80) { + + mflp->maccu-=mflp->rbuff[mflp->index]; + mflp->maccu+=invar; + mflp->rbuff[mflp->index]=invar; + mflp->index++; + if (mflp->index>=(mflp->numvals&0x7f)) mflp->index=0; + } else { + + mflp->rbuff[mflp->index]=invar; + mflp->index++; + if (mflp->index>=mflp->numvals) mflp->index=0; + } + break; + } + mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); + } +} + +#define MEDIAN_SIZE 5 +#define MEDIAN_FILTER_NUM 2 + +struct MEDIAN_FILTER { +float buffer[MEDIAN_SIZE]; +int8_t index; +} script_mf[MEDIAN_FILTER_NUM]; + +float DoMedian5(uint8_t index, float in) { + + if (index>=MEDIAN_FILTER_NUM) index=0; + + struct MEDIAN_FILTER* mf=&script_mf[index]; + mf->buffer[mf->index]=in; + mf->index++; + if (mf->index>=MEDIAN_SIZE) mf->index=0; + return median_array(mf->buffer,MEDIAN_SIZE); +} + +#ifdef USE_LIGHT + +uint32_t HSVToRGB(uint16_t hue, uint8_t saturation, uint8_t value) { +float r = 0, g = 0, b = 0; +struct HSV { + float H; + float S; + float V; +} hsv; + +hsv.H=hue; +hsv.S=(float)saturation/100.0; +hsv.V=(float)value/100.0; + +if (hsv.S == 0) { + r = hsv.V; + g = hsv.V; + b = hsv.V; + } else { + int i; + float f, p, q, t; + + if (hsv.H == 360) + hsv.H = 0; + else + hsv.H = hsv.H / 60; + + i = (int)trunc(hsv.H); + f = hsv.H - i; + + p = hsv.V * (1.0 - hsv.S); + q = hsv.V * (1.0 - (hsv.S * f)); + t = hsv.V * (1.0 - (hsv.S * (1.0 - f))); + + switch (i) + { + case 0: + r = hsv.V; + g = t; + b = p; + break; + + case 1: + r = q; + g = hsv.V; + b = p; + break; + + case 2: + r = p; + g = hsv.V; + b = t; + break; + + case 3: + r = p; + g = q; + b = hsv.V; + break; + + case 4: + r = t; + g = p; + b = hsv.V; + break; + + default: + r = hsv.V; + g = p; + b = q; + break; + } + + } + + uint8_t ir,ig,ib; + ir=r*255; + ig=g*255; + ib=b*255; + + uint32_t rgb=(ir<<16)|(ig<<8)|ib; + return rgb; +} +#endif + + + + +char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,JsonObject *jo) { + uint16_t count,len=0; + uint8_t nres=0; + char vname[32]; + float fvar=0; + tind->index=0; + tind->bits.data=0; + + if (isdigit(*lp) || (*lp=='-' && isdigit(*(lp+1))) || *lp=='.') { + + if (fp) { + if (*lp=='0' && *(lp+1)=='x') { + lp+=2; + *fp=strtol(lp,0,16); + } else { + *fp=CharToFloat(lp); + } + } + if (*lp=='-') lp++; + while (isdigit(*lp) || *lp=='.') { + if (*lp==0 || *lp==SCRIPT_EOL) break; + lp++; + } + tind->bits.constant=1; + tind->bits.is_string=0; + *vtype=NUM_RES; + return lp; + } + if (*lp=='"') { + lp++; + while (*lp!='"') { + if (*lp==0 || *lp==SCRIPT_EOL) break; + uint8_t iob=*lp; + if (iob=='\\') { + lp++; + if (*lp=='t') { + iob='\t'; + } else if (*lp=='n') { + iob='\n'; + } else if (*lp=='r') { + iob='\r'; + } else if (*lp=='\\') { + iob='\\'; + } else { + lp--; + } + if (sp) *sp++=iob; + } else { + if (sp) *sp++=iob; + } + lp++; + } + if (sp) *sp=0; + *vtype=STR_RES; + tind->bits.constant=1; + tind->bits.is_string=1; + return lp+1; + } + + if (*lp=='-') { + + nres=1; + lp++; + } + + const char *term="\n\r ])=+-/*%>index=VAR_NV; + glob_script_mem.var_not_found=1; + return lp; + } + + struct T_INDEX *vtp=glob_script_mem.type; + char dvnam[32]; + strcpy (dvnam,vname); + uint8_t olen=len; + last_findex=-1; + char *ja=strchr(dvnam,'['); + if (ja) { + *ja=0; + ja++; + olen=strlen(dvnam); + } + for (count=0; countindex=count; + if (vtp[count].bits.is_string==0) { + *vtype=NTYPE|index; + if (vtp[count].bits.is_filter) { + if (ja) { + lp+=olen+1; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + last_findex=fvar; + fvar=Get_MFVal(index,fvar); + len=1; + } else { + fvar=Get_MFilter(index); + } + } else { + fvar=glob_script_mem.fvars[index]; + } + if (nres) fvar=-fvar; + if (fp) *fp=fvar; + } else { + *vtype=STYPE|index; + if (sp) strlcpy(sp,glob_script_mem.glob_snp+(index*glob_script_mem.max_ssize),SCRIPT_MAXSSIZE); + } + return lp+len; + } + } + } + + if (jo) { + + const char* str_value; + uint8_t aindex; + String vn; + char *ja=strchr(vname,'['); + if (ja) { + + *ja=0; + ja++; + + float fvar; + GetNumericResult(ja,OPER_EQU,&fvar,0); + aindex=fvar; + if (aindex<1 || aindex>6) aindex=1; + aindex--; + } + if (jo->success()) { + char *subtype=strchr(vname,'#'); + char *subtype2; + if (subtype) { + *subtype=0; + subtype++; + subtype2=strchr(subtype,'#'); + if (subtype2) { + *subtype2=0; + *subtype2++; + } + } + vn=vname; + str_value = (*jo)[vn]; + if ((*jo)[vn].success()) { + if (subtype) { + JsonObject &jobj1=(*jo)[vn]; + if (jobj1.success()) { + vn=subtype; + jo=&jobj1; + str_value = (*jo)[vn]; + if ((*jo)[vn].success()) { + + if (subtype2) { + JsonObject &jobj2=(*jo)[vn]; + if ((*jo)[vn].success()) { + vn=subtype2; + jo=&jobj2; + str_value = (*jo)[vn]; + if ((*jo)[vn].success()) { + goto skip; + } else { + goto chknext; + } + } else { + goto chknext; + } + } + + goto skip; + } + } else { + goto chknext; + } + } + skip: + if (ja) { + + str_value = (*jo)[vn][aindex]; + } + if (str_value && *str_value) { + if ((*jo).is(vn)) { + if (!strncmp(str_value,"ON",2)) { + if (fp) *fp=1; + } else if (!strncmp(str_value,"OFF",3)) { + if (fp) *fp=0; + } else { + *vtype=STR_RES; + tind->bits.constant=1; + tind->bits.is_string=1; + if (sp) strlcpy(sp,str_value,SCRIPT_MAXSSIZE); + return lp+len; + } + } else { + if (fp) { + if (!strncmp(vn.c_str(),"Epoch",5)) { + *fp=atoi(str_value)-(uint32_t)EPOCH_OFFSET; + } else { + *fp=CharToFloat((char*)str_value); + } + } + *vtype=NUM_RES; + tind->bits.constant=1; + tind->bits.is_string=0; + return lp+len; + } + } + } + } + } + +chknext: + switch (vname[0]) { + case 'b': + if (!strncmp(vname,"boot",4)) { + if (rules_flag.system_boot) { + rules_flag.system_boot=0; + fvar=1; + } + goto exit; + } + break; + case 'c': + if (!strncmp(vname,"chg[",4)) { + + struct T_INDEX ind; + uint8_t vtype; + isvar(vname+4,&vtype,&ind,0,0,0); + if (!ind.bits.constant) { + uint8_t index=glob_script_mem.type[ind.index].index; + if (glob_script_mem.fvars[index]!=glob_script_mem.s_fvars[index]) { + + glob_script_mem.s_fvars[index]=glob_script_mem.fvars[index]; + fvar=1; + len++; + goto exit; + } else { + fvar=0; + len++; + goto exit; + } + } + } + break; + case 'd': + if (!strncmp(vname,"day",3)) { + fvar=RtcTime.day_of_month; + goto exit; + } + break; + case 'e': + if (!strncmp(vname,"epoch",5)) { + fvar=UtcTime()-(uint32_t)EPOCH_OFFSET; + goto exit; + } + break; +#ifdef USE_SCRIPT_FATFS + case 'f': + if (!strncmp(vname,"fo(",3)) { + lp+=3; + char str[SCRIPT_MAXSSIZE]; + lp=GetStringResult(lp,OPER_EQU,str,0); + while (*lp==' ') lp++; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + uint8_t mode=fvar; + fvar=-1; + for (uint8_t cnt=0;cnt=SFS_MAX) ind=SFS_MAX-1; + glob_script_mem.files[ind].close(); + glob_script_mem.file_flags[ind].is_open=0; + fvar=0; + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"ff(",3)) { + lp+=3; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + uint8_t ind=fvar; + if (ind>=SFS_MAX) ind=SFS_MAX-1; + glob_script_mem.files[ind].flush(); + fvar=0; + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"fw(",3)) { + lp+=3; + char str[SCRIPT_MAXSSIZE]; + lp=ForceStringVar(lp,str); + while (*lp==' ') lp++; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + uint8_t ind=fvar; + if (ind>=SFS_MAX) ind=SFS_MAX-1; + if (glob_script_mem.file_flags[ind].is_open) { + fvar=glob_script_mem.files[ind].print(str); + } else { + fvar=0; + } + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"fr(",3)) { + lp+=3; + struct T_INDEX ind; + uint8_t vtype; + uint8_t sindex=0; + lp=isvar(lp,&vtype,&ind,0,0,0); + if (vtype!=VAR_NV) { + + if ((vtype&STYPE)==0) { + + fvar=0; + goto exit; + } else { + + sindex=glob_script_mem.type[ind.index].index; + } + } else { + + fvar=0; + goto exit; + } + while (*lp==' ') lp++; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + uint8_t find=fvar; + if (find>=SFS_MAX) find=SFS_MAX-1; + uint8_t index=0; + char str[glob_script_mem.max_ssize+1]; + char *cp=str; + if (glob_script_mem.file_flags[find].is_open) { + if (glob_script_mem.file_flags[find].is_dir) { + while (true) { + File entry=glob_script_mem.files[find].openNextFile(); + if (entry) { + if (!reject((char*)entry.name())) { + strcpy(str,entry.name()); + entry.close(); + break; + } + } else { + *cp=0; + break; + } + entry.close(); + } + index=strlen(str); + } else { + while (glob_script_mem.files[find].available()) { + uint8_t buf[1]; + glob_script_mem.files[find].read(buf,1); + if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { + break; + } else { + *cp++=buf[0]; + index++; + if (index>=glob_script_mem.max_ssize-1) break; + } + } + *cp=0; + } + } else { + strcpy(str,"file error"); + } + lp++; + strlcpy(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); + fvar=index; + len=0; + goto exit; + } + if (!strncmp(vname,"fd(",3)) { + lp+=3; + char str[glob_script_mem.max_ssize+1]; + lp=GetStringResult(lp,OPER_EQU,str,0); + SD.remove(str); + lp++; + len=0; + goto exit; + } +#ifdef USE_SCRIPT_FATFS_EXT + if (!strncmp(vname,"fe(",3)) { + lp+=3; + char str[glob_script_mem.max_ssize+1]; + lp=GetStringResult(lp,OPER_EQU,str,0); + + File ef=SD.open(str); + if (ef) { + uint16_t fsiz=ef.size(); + if (fsiz<2048) { + char *script=(char*)calloc(fsiz+16,1); + if (script) { + ef.read((uint8_t*)script,fsiz); + execute_script(script); + free(script); + fvar=1; + } + } + ef.close(); + } + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"fmd(",4)) { + lp+=4; + char str[glob_script_mem.max_ssize+1]; + lp=GetStringResult(lp,OPER_EQU,str,0); + fvar=SD.mkdir(str); + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"frd(",4)) { + lp+=4; + char str[glob_script_mem.max_ssize+1]; + lp=GetStringResult(lp,OPER_EQU,str,0); + fvar=SD.rmdir(str); + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"fx(",3)) { + lp+=3; + char str[glob_script_mem.max_ssize+1]; + lp=GetStringResult(lp,OPER_EQU,str,0); + if (SD.exists(str)) fvar=1; + else fvar=0; + lp++; + len=0; + goto exit; + } +#endif + if (!strncmp(vname,"fl1(",4) || !strncmp(vname,"fl2(",4) ) { + uint8_t lknum=*(lp+2)&3; + lp+=4; + char str[glob_script_mem.max_ssize+1]; + lp=GetStringResult(lp,OPER_EQU,str,0); + if (lknum<1 || lknum>2) lknum=1; + strlcpy(glob_script_mem.flink[lknum-1],str,14); + lp++; + fvar=0; + len=0; + goto exit; + } + if (!strncmp(vname,"fsm",3)) { + fvar=glob_script_mem.script_sd_found; + + goto exit; + } + break; + +#endif + case 'g': + if (!strncmp(vname,"gtmp",4)) { + fvar=global_temperature; + goto exit; + } + if (!strncmp(vname,"ghum",4)) { + fvar=global_humidity; + goto exit; + } + if (!strncmp(vname,"gprs",4)) { + fvar=global_pressure; + goto exit; + } + if (!strncmp(vname,"gtopic",6)) { + if (sp) strlcpy(sp,Settings.mqtt_grptopic,glob_script_mem.max_ssize); + goto strexit; + } + break; + case 'h': + if (!strncmp(vname,"hours",5)) { + fvar=RtcTime.hour; + goto exit; + } + if (!strncmp(vname,"heap",4)) { + fvar=ESP.getFreeHeap(); + goto exit; + } + if (!strncmp(vname,"hn(",3)) { + lp=GetNumericResult(lp+3,OPER_EQU,&fvar,0); + if (fvar<0 || fvar>255) fvar=0; + lp++; + len=0; + if (sp) { + sprintf(sp,"%02x",(uint8_t)fvar); + } + goto strexit; + } + if (!strncmp(vname,"hx(",3)) { + lp=GetNumericResult(lp+3,OPER_EQU,&fvar,0); + lp++; + len=0; + if (sp) { + sprintf(sp,"%08x",(uint32_t)fvar); + } + goto strexit; + } +#ifdef USE_LIGHT + + if (!strncmp(vname,"hsvrgb(",7)) { + lp=GetNumericResult(lp+7,OPER_EQU,&fvar,0); + if (fvar<0 || fvar>360) fvar=0; + SCRIPT_SKIP_SPACES + + float fvar2; + lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); + if (fvar2<0 || fvar2>100) fvar2=0; + SCRIPT_SKIP_SPACES + + float fvar3; + lp=GetNumericResult(lp,OPER_EQU,&fvar3,0); + if (fvar3<0 || fvar3>100) fvar3=0; + + fvar=HSVToRGB(fvar,fvar2,fvar3); + + lp++; + len=0; + goto exit; + } + +#endif + break; + case 'i': + if (!strncmp(vname,"int(",4)) { + lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0); + fvar=floor(fvar); + lp++; + len=0; + goto exit; + } + break; + case 'l': + if (!strncmp(vname,"loglvl",6)) { + fvar=glob_script_mem.script_loglevel; + tind->index=SCRIPT_LOGLEVEL; + exit_settable: + if (fp) *fp=fvar; + *vtype=NTYPE; + tind->bits.settable=1; + tind->bits.is_string=0; + return lp+len; + } + break; + case 'm': + if (!strncmp(vname,"med(",4)) { + float fvar1; + lp=GetNumericResult(lp+4,OPER_EQU,&fvar1,0); + SCRIPT_SKIP_SPACES + + float fvar2; + lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); + fvar=DoMedian5(fvar1,fvar2); + lp++; + len=0; + goto exit; + } + if (!strncmp(vname,"micros",6)) { + fvar=micros(); + goto exit; + } + if (!strncmp(vname,"millis",6)) { + fvar=millis(); + goto exit; + } + if (!strncmp(vname,"mins",4)) { + fvar=RtcTime.minute; + goto exit; + } + if (!strncmp(vname,"month",5)) { + fvar=RtcTime.month; + goto exit; + } + if (!strncmp(vname,"mqttc",5)) { + if (rules_flag.mqtt_connected) { + rules_flag.mqtt_connected=0; + fvar=1; + } + goto exit; + } + if (!strncmp(vname,"mqttd",5)) { + if (rules_flag.mqtt_disconnected) { + rules_flag.mqtt_disconnected=0; + fvar=1; + } + goto exit; + } + if (!strncmp(vname,"mqtts",5)) { + fvar=!global_state.mqtt_down; + goto exit; + } + break; + case 'p': + if (!strncmp(vname,"pin[",4)) { + + GetNumericResult(vname+4,OPER_EQU,&fvar,0); + fvar=digitalRead((uint8_t)fvar); + + len++; + goto exit; + } + if (!strncmp(vname,"pn[",3)) { + GetNumericResult(vname+3,OPER_EQU,&fvar,0); + fvar=pin[(uint8_t)fvar]; + + len++; + goto exit; + } + if (!strncmp(vname,"pd[",3)) { + GetNumericResult(vname+3,OPER_EQU,&fvar,0); + uint8_t gpiopin=fvar; + for (uint8_t i=0;iMAX_COUNTERS) index=1; + fvar=RtcSettings.pulse_counter[index-1]; + len+=1; + goto exit; + } + break; + + case 'r': + if (!strncmp(vname,"ram",3)) { + fvar=glob_script_mem.script_mem_size+(glob_script_mem.script_size)+(MAX_RULE_MEMS*10); + goto exit; + } + break; + case 's': + if (!strncmp(vname,"secs",4)) { + fvar=RtcTime.second; + goto exit; + } + if (!strncmp(vname,"sw[",3)) { + + GetNumericResult(vname+3,OPER_EQU,&fvar,0); + fvar=SwitchLastState((uint8_t)fvar); + + len++; + goto exit; + } + if (!strncmp(vname,"stack",5)) { + fvar=GetStack(); + goto exit; + } + if (!strncmp(vname,"slen",4)) { + fvar=strlen(glob_script_mem.script_ram); + goto exit; + } + if (!strncmp(vname,"sl(",3)) { + lp+=3; + char str[SCRIPT_MAXSSIZE]; + lp=GetStringResult(lp,OPER_EQU,str,0); + lp++; + len=0; + fvar=strlen(str); + goto exit; + } + if (!strncmp(vname,"sb(",3)) { + lp+=3; + char str[SCRIPT_MAXSSIZE]; + lp=GetStringResult(lp,OPER_EQU,str,0); + SCRIPT_SKIP_SPACES + float fvar1; + lp=GetNumericResult(lp,OPER_EQU,&fvar1,0); + SCRIPT_SKIP_SPACES + float fvar2; + lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); + lp++; + len=0; + if (fvar1<0) { + fvar1=strlen(str)+fvar1; + } + memcpy(sp,&str[(uint8_t)fvar1],(uint8_t)fvar2); + sp[(uint8_t)fvar2] = '\0'; + goto strexit; + } + if (!strncmp(vname,"st(",3)) { + lp+=3; + char str[SCRIPT_MAXSSIZE]; + lp=GetStringResult(lp,OPER_EQU,str,0); + while (*lp==' ') lp++; + char token[2]; + token[0]=*lp++; + token[1]=0; + while (*lp==' ') lp++; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + + lp++; + len=0; + if (sp) { + + char *st=strtok(str,token); + if (!st) { + *sp=0; + } else { + for (uint8_t cnt=1; cnt<=fvar; cnt++) { + if (cnt==fvar) { + strcpy(sp,st); + break; + } + st=strtok(NULL,token); + if (!st) { + *sp=0; + break; + } + } + } + } + goto strexit; + } + if (!strncmp(vname,"s(",2)) { + lp+=2; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + char str[glob_script_mem.max_ssize+1]; + dtostrfd(fvar,glob_script_mem.script_dprec,str); + if (sp) strlcpy(sp,str,glob_script_mem.max_ssize); + lp++; + len=0; + goto strexit; + } +#if defined(USE_TIMERS) && defined(USE_SUNRISE) + if (!strncmp(vname,"sunrise",7)) { + fvar=SunMinutes(0); + goto exit; + } + if (!strncmp(vname,"sunset",6)) { + fvar=SunMinutes(1); + goto exit; + } +#endif + break; + case 't': + if (!strncmp(vname,"time",4)) { + fvar=MinutesPastMidnight(); + goto exit; + } + if (!strncmp(vname,"tper",4)) { + fvar=Settings.tele_period; + tind->index=SCRIPT_TELEPERIOD; + goto exit_settable; + } + if (!strncmp(vname,"tinit",5)) { + if (rules_flag.time_init) { + rules_flag.time_init=0; + fvar=1; + } + goto exit; + } + if (!strncmp(vname,"tset",4)) { + if (rules_flag.time_set) { + rules_flag.time_set=0; + fvar=1; + } + goto exit; + } + if (!strncmp(vname,"tstamp",6)) { + if (sp) strlcpy(sp,GetDateAndTime(DT_LOCAL).c_str(),glob_script_mem.max_ssize); + goto strexit; + } + if (!strncmp(vname,"topic",5)) { + if (sp) strlcpy(sp,Settings.mqtt_topic,glob_script_mem.max_ssize); + goto strexit; + } +#ifdef USE_DISPLAY +#ifdef USE_TOUCH_BUTTONS + if (!strncmp(vname,"tbut[",5)) { + GetNumericResult(vname+5,OPER_EQU,&fvar,0); + uint8_t index=fvar; + if (index<1 || index>MAXBUTTONS) index=1; + index--; + if (buttons[index]) { + fvar=buttons[index]->vpower&0x80; + } else { + fvar=-1; + } + len+=1; + goto exit; + } + +#endif +#endif + break; + case 'u': + if (!strncmp(vname,"uptime",6)) { + fvar=MinutesUptime(); + goto exit; + } + if (!strncmp(vname,"upsecs",6)) { + fvar=uptime; + goto exit; + } + if (!strncmp(vname,"upd[",4)) { + + struct T_INDEX ind; + uint8_t vtype; + isvar(vname+4,&vtype,&ind,0,0,0); + if (!ind.bits.constant) { + if (!ind.bits.changed) { + fvar=0; + len++; + goto exit; + } else { + glob_script_mem.type[ind.index].bits.changed=0; + fvar=1; + len++; + goto exit; + } + } + goto notfound; + } + break; + + case 'w': + if (!strncmp(vname,"wday",4)) { + fvar=RtcTime.day_of_week; + goto exit; + } + if (!strncmp(vname,"wific",5)) { + if (rules_flag.wifi_connected) { + rules_flag.wifi_connected=0; + fvar=1; + } + goto exit; + } + if (!strncmp(vname,"wifid",5)) { + if (rules_flag.wifi_disconnected) { + rules_flag.wifi_disconnected=0; + fvar=1; + } + goto exit; + } + if (!strncmp(vname,"wifis",5)) { + fvar=!global_state.wifi_down; + goto exit; + } + break; + case 'y': + if (!strncmp(vname,"year",4)) { + fvar=RtcTime.year; + goto exit; + } + break; + default: + break; + } + +notfound: + if (fp) *fp=0; + *vtype=VAR_NV; + tind->index=VAR_NV; + glob_script_mem.var_not_found=1; + return lp; + +exit: + if (fp) *fp=fvar; + *vtype=NUM_RES; + tind->bits.constant=1; + tind->bits.is_string=0; + return lp+len; + +strexit: + *vtype=STYPE; + tind->bits.constant=1; + tind->bits.is_string=1; + return lp+len; +} + + + +char *getop(char *lp, uint8_t *operand) { + switch (*lp) { + case '=': + if (*(lp+1)=='=') { + *operand=OPER_EQUEQU; + return lp+2; + } else { + *operand=OPER_EQU; + return lp+1; + } + break; + case '+': + if (*(lp+1)=='=') { + *operand=OPER_PLSEQU; + return lp+2; + } else { + *operand=OPER_PLS; + return lp+1; + } + break; + case '-': + if (*(lp+1)=='=') { + *operand=OPER_MINEQU; + return lp+2; + } else { + *operand=OPER_MIN; + return lp+1; + } + break; + case '*': + if (*(lp+1)=='=') { + *operand=OPER_MULEQU; + return lp+2; + } else { + *operand=OPER_MUL; + return lp+1; + } + break; + case '/': + if (*(lp+1)=='=') { + *operand=OPER_DIVEQU; + return lp+2; + } else { + *operand=OPER_DIV; + return lp+1; + } + break; + case '!': + if (*(lp+1)=='=') { + *operand=OPER_NOTEQU; + return lp+2; + } + break; + case '>': + if (*(lp+1)=='=') { + *operand=OPER_GRTEQU; + return lp+2; + } else { + *operand=OPER_GRT; + return lp+1; + + } + break; + case '<': + if (*(lp+1)=='=') { + *operand=OPER_LOWEQU; + return lp+2; + } else { + *operand=OPER_LOW; + return lp+1; + } + break; + case '%': + if (*(lp+1)=='=') { + *operand=OPER_PERCEQU; + return lp+2; + } else { + *operand=OPER_PERC; + return lp+1; + } + break; + case '^': + if (*(lp+1)=='=') { + *operand=OPER_XOREQU; + return lp+2; + } else { + *operand=OPER_XOR; + return lp+1; + } + break; + case '&': + if (*(lp+1)=='=') { + *operand=OPER_ANDEQU; + return lp+2; + } else { + *operand=OPER_AND; + return lp+1; + } + break; + case '|': + if (*(lp+1)=='=') { + *operand=OPER_OREQU; + return lp+2; + } else { + *operand=OPER_OR; + return lp+1; + } + break; + } + *operand=0; + return lp; +} + + +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) + + +extern "C" { +#include + extern cont_t g_cont; +} +uint16_t GetStack(void) { + register uint32_t *sp asm("a1"); + return (4 * (sp - g_cont.stack)); +} + +#else +extern "C" { +#include + extern cont_t* g_pcont; +} +uint16_t GetStack(void) { + register uint32_t *sp asm("a1"); + return (4 * (sp - g_pcont->stack)); +} +#endif + +char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo) { + uint8_t operand=0; + uint8_t vtype; + char *slp; + struct T_INDEX ind; + char str[SCRIPT_MAXSSIZE],str1[SCRIPT_MAXSSIZE]; + while (1) { + lp=isvar(lp,&vtype,&ind,0,str1,jo); + if (vtype!=STR_RES && !(vtype&STYPE)) { + + glob_script_mem.glob_error=1; + return lp; + } + switch (lastop) { + case OPER_EQU: + strlcpy(str,str1,sizeof(str)); + break; + case OPER_PLS: + strncat(str,str1,sizeof(str)); + break; + } + slp=lp; + lp=getop(lp,&operand); + switch (operand) { + case OPER_EQUEQU: + case OPER_NOTEQU: + case OPER_LOW: + case OPER_LOWEQU: + case OPER_GRT: + case OPER_GRTEQU: + lp=slp; + strcpy(cp,str); + return lp; + break; + default: + break; + } + lastop=operand; + if (!operand) { + strcpy(cp,str); + return lp; + } + } +} + +char *GetNumericResult(char *lp,uint8_t lastop,float *fp,JsonObject *jo) { +uint8_t operand=0; +float fvar1,fvar; +char *slp; +uint8_t vtype; +struct T_INDEX ind; + while (1) { + + if (*lp=='(') { + lp++; + lp=GetNumericResult(lp,OPER_EQU,&fvar1,jo); + lp++; + + } else { + lp=isvar(lp,&vtype,&ind,&fvar1,0,jo); + if (vtype!=NUM_RES && vtype&STYPE) { + + glob_script_mem.glob_error=1; + } + } + switch (lastop) { + case OPER_EQU: + fvar=fvar1; + break; + case OPER_PLS: + fvar+=fvar1; + break; + case OPER_MIN: + fvar-=fvar1; + break; + case OPER_MUL: + fvar*=fvar1; + break; + case OPER_DIV: + fvar/=fvar1; + break; + case OPER_PERC: + fvar=fmodf(fvar,fvar1); + break; + case OPER_XOR: + fvar=(uint32_t)fvar^(uint32_t)fvar1; + break; + case OPER_AND: + fvar=(uint32_t)fvar&(uint32_t)fvar1; + break; + case OPER_OR: + fvar=(uint32_t)fvar|(uint32_t)fvar1; + break; + default: + break; + + } + slp=lp; + lp=getop(lp,&operand); + switch (operand) { + case OPER_EQUEQU: + case OPER_NOTEQU: + case OPER_LOW: + case OPER_LOWEQU: + case OPER_GRT: + case OPER_GRTEQU: + lp=slp; + *fp=fvar; + return lp; + break; + default: + break; + } + lastop=operand; + if (!operand) { + *fp=fvar; + return lp; + } + } +} + + +char *ForceStringVar(char *lp,char *dstr) { + float fvar; + char *slp=lp; + glob_script_mem.glob_error=0; + lp=GetStringResult(lp,OPER_EQU,dstr,0); + if (glob_script_mem.glob_error) { + + lp=GetNumericResult(slp,OPER_EQU,&fvar,0); + dtostrfd(fvar,6,dstr); + glob_script_mem.glob_error=0; + } + return lp; +} + + +void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) { + char *cp; + uint16_t count; + uint8_t vtype; + uint8_t dprec=glob_script_mem.script_dprec; + float fvar; + cp=srcbuf; + struct T_INDEX ind; + char string[SCRIPT_MAXSSIZE]; + for (count=0;count=sizeof(str)) len=len>=sizeof(str); + strlcpy(str,cp,len); + toSLog(str); +} + +void toLogEOL(const char *s1,const char *str) { + if (!str) return; + uint8_t index=0; + char *cp=log_data; + strcpy(cp,s1); + cp+=strlen(s1); + while (*str) { + if (*str==SCRIPT_EOL) break; + *cp++=*str++; + } + *cp=0; + AddLog(LOG_LEVEL_INFO); +} + + +void toSLog(const char *str) { + if (!str) return; +#if SCRIPT_DEBUG>0 + while (*str) { + Serial.write(*str); + str++; + } +#endif +} + +char *Evaluate_expression(char *lp,uint8_t and_or, uint8_t *result,JsonObject *jo) { + float fvar,*dfvar,fvar1; + uint8_t numeric; + struct T_INDEX ind; + uint8_t vtype=0,lastop; + uint8_t res=0; + + SCRIPT_SKIP_SPACES + + if (*lp=='(') { + lp++; + lp=Evaluate_expression(lp,and_or,result,jo); + lp++; + + SCRIPT_SKIP_SPACES + if (!strncmp(lp,"or",2)) { + lp+=2; + and_or=1; + SCRIPT_SKIP_SPACES + lp=Evaluate_expression(lp,and_or,result,jo); + } else if (!strncmp(lp,"and",3)) { + lp+=3; + and_or=2; + SCRIPT_SKIP_SPACES + lp=Evaluate_expression(lp,and_or,result,jo); + } + return lp; + } + + + dfvar=&fvar; + glob_script_mem.glob_error=0; + char *slp=lp; + numeric=1; + lp=GetNumericResult(lp,OPER_EQU,dfvar,0); + if (glob_script_mem.glob_error==1) { + + char cmpstr[SCRIPT_MAXSSIZE]; + lp=slp; + numeric=0; + + lp=isvar(lp,&vtype,&ind,0,cmpstr,0); + lp=getop(lp,&lastop); + + char str[SCRIPT_MAXSSIZE]; + lp=GetStringResult(lp,OPER_EQU,str,jo); + if (lastop==OPER_EQUEQU || lastop==OPER_NOTEQU) { + uint8_t res=0; + res=strcmp(cmpstr,str); + if (lastop==OPER_EQUEQU) res=!res; + if (!and_or) { + *result=res; + } else if (and_or==1) { + *result|=res; + } else { + *result&=res; + } + } + + } else { + + + lp=getop(lp,&lastop); + + lp=GetNumericResult(lp,OPER_EQU,&fvar1,jo); + switch (lastop) { + case OPER_EQUEQU: + res=(*dfvar==fvar1); + break; + case OPER_NOTEQU: + res=(*dfvar!=fvar1); + break; + case OPER_LOW: + res=(*dfvarfvar1); + break; + case OPER_GRTEQU: + res=(*dfvar>=fvar1); + break; + default: + + break; + } + + if (!and_or) { + *result=res; + } else if (and_or==1) { + *result|=res; + } else { + *result&=res; + } + } +exit: +#if SCRIPT_DEBUG>0 + char tbuff[128]; + sprintf(tbuff,"p1=%d,p2=%d,cmpres=%d line: ",(int32_t)*dfvar,(int32_t)fvar1,*result); + toLogEOL(tbuff,lp); +#endif + return lp; +} + + + +#define IF_NEST 8 + +int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { + + if (tasm_cmd_activ && tlen>0) return 0; + + uint8_t vtype=0,sindex,xflg,floop=0,globvindex,fromscriptcmd=0; + int8_t globaindex; + struct T_INDEX ind; + uint8_t operand,lastop,numeric=1,if_state[IF_NEST],if_exe[IF_NEST],if_result[IF_NEST],and_or,ifstck=0; + if_state[ifstck]=0; + if_result[ifstck]=0; + if_exe[ifstck]=1; + char cmpstr[SCRIPT_MAXSSIZE]; + uint8_t check=0; + if (tlen<0) { + tlen=abs(tlen); + check=1; + } + + float *dfvar,*cv_count,cv_max,cv_inc; + char *cv_ptr; + float fvar=0,fvar1,sysvar,swvar; + uint8_t section=0,sysv_type=0,swflg=0; + + if (!glob_script_mem.scriptptr) { + return -99; + } + + DynamicJsonBuffer jsonBuffer; + JsonObject &jobj=jsonBuffer.parseObject(js); + JsonObject *jo; + if (js) jo=&jobj; + else jo=0; + + char *lp=glob_script_mem.scriptptr; + + while (1) { + + + startline: + SCRIPT_SKIP_SPACES + + SCRIPT_SKIP_EOL + + if (*lp==';') goto next_line; + if (!*lp) break; + + if (section) { + + if (*lp=='>') { + return 0; + } + if (*lp=='#') { + return 0; + } + glob_script_mem.var_not_found=0; + + +#ifdef IFTHEN_DEBUG + char tbuff[128]; + sprintf(tbuff,"stack=%d,exe=%d,state=%d,cmpres=%d line: ",ifstck,if_exe[ifstck],if_state[ifstck],if_result[ifstck]); + toLogEOL(tbuff,lp); +#endif + + + + + if (!strncmp(lp,"if",2)) { + lp+=2; + if (ifstck=2) { + lp+=5; + if (ifstck>0) { + if_state[ifstck]=0; + ifstck--; + } + goto next_line; + } else if (!strncmp(lp,"or",2) && if_state[ifstck]==1) { + lp+=2; + and_or=1; + } else if (!strncmp(lp,"and",3) && if_state[ifstck]==1) { + lp+=3; + and_or=2; + } + + if (*lp=='{' && if_state[ifstck]==1) { + lp+=1; + if_state[ifstck]=2; + if (if_exe[ifstck-1]) if_exe[ifstck]=if_result[ifstck]; + } else if (*lp=='{' && if_state[ifstck]==3) { + lp+=1; + + } else if (*lp=='}' && if_state[ifstck]>=2) { + lp++; + char *slp=lp; + uint8_t iselse=0; + for (uint8_t count=0; count<8;count++) { + if (*lp=='}') { + + break; + } + if (!strncmp(lp,"else",4)) { + + if_state[ifstck]=3; + if (if_exe[ifstck-1]) if_exe[ifstck]=!if_result[ifstck]; + lp+=4; + iselse=1; + SCRIPT_SKIP_SPACES + if (*lp=='{') lp++; + break; + } + lp++; + } + if (!iselse) { + lp=slp; + + if (ifstck>0) { + if_state[ifstck]=0; + ifstck--; + } + goto next_line; + } + } + + if (!strncmp(lp,"for",3)) { + + + lp+=3; + SCRIPT_SKIP_SPACES + lp=isvar(lp,&vtype,&ind,0,0,0); + if ((vtype!=VAR_NV) && (vtype&STYPE)==0) { + + uint8_t index=glob_script_mem.type[ind.index].index; + cv_count=&glob_script_mem.fvars[index]; + SCRIPT_SKIP_SPACES + lp=GetNumericResult(lp,OPER_EQU,cv_count,0); + SCRIPT_SKIP_SPACES + lp=GetNumericResult(lp,OPER_EQU,&cv_max,0); + SCRIPT_SKIP_SPACES + lp=GetNumericResult(lp,OPER_EQU,&cv_inc,0); + + cv_ptr=lp; + floop=1; + } else { + + toLogEOL("for error",lp); + } + } else if (!strncmp(lp,"next",4) && floop>0) { + + *cv_count+=cv_inc; + if (*cv_count<=cv_max) { + lp=cv_ptr; + } else { + lp+=4; + floop=0; + } + } + + if (!strncmp(lp,"switch",6)) { + lp+=6; + SCRIPT_SKIP_SPACES + char *slp=lp; + lp=GetNumericResult(lp,OPER_EQU,&swvar,0); + if (glob_script_mem.glob_error==1) { + + lp=slp; + + lp=isvar(lp,&vtype,&ind,0,cmpstr,0); + swflg=0x81; + } else { + swflg=1; + } + } else if (!strncmp(lp,"case",4) && swflg>0) { + lp+=4; + SCRIPT_SKIP_SPACES + float cvar; + if (!(swflg&0x80)) { + lp=GetNumericResult(lp,OPER_EQU,&cvar,0); + if (swvar!=cvar) { + swflg=2; + } else { + swflg=1; + } + } else { + char str[SCRIPT_MAXSSIZE]; + lp=GetStringResult(lp,OPER_EQU,str,0); + if (!strcmp(cmpstr,str)) { + swflg=0x81; + } else { + swflg=0x82; + } + } + } else if (!strncmp(lp,"ends",4) && swflg>0) { + lp+=4; + swflg=0; + } + if ((swflg&3)==2) goto next_line; + + SCRIPT_SKIP_SPACES + + if (*lp==SCRIPT_EOL) { + goto next_line; + } + + + if (!if_exe[ifstck] && if_state[ifstck]!=1) goto next_line; + +#ifdef IFTHEN_DEBUG + sprintf(tbuff,"stack=%d,exe=%d,state=%d,cmpres=%d execute line: ",ifstck,if_exe[ifstck],if_state[ifstck],if_result[ifstck]); + toLogEOL(tbuff,lp); +#endif + + if (!strncmp(lp,"break",5)) { + if (floop) { + + floop=0; + } else { + section=0; + } + break; + } else if (!strncmp(lp,"dp",2) && isdigit(*(lp+2))) { + lp+=2; + + glob_script_mem.script_dprec=atoi(lp); + goto next_line; + } else if (!strncmp(lp,"delay(",6)) { + lp+=5; + + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + delay(fvar); + goto next_line; + } else if (!strncmp(lp,"spinm(",6)) { + lp+=6; + + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + int8_t pinnr=fvar; + SCRIPT_SKIP_SPACES + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + int8_t mode=fvar; + pinMode(pinnr,mode&3); + goto next_line; + } else if (!strncmp(lp,"spin(",5)) { + lp+=5; + + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + int8_t pinnr=fvar; + SCRIPT_SKIP_SPACES + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + int8_t mode=fvar; + digitalWrite(pinnr,mode&1); + goto next_line; + } else if (!strncmp(lp,"svars(",5)) { + lp+=5; + + Scripter_save_pvars(); + goto next_line; + } +#ifdef USE_LIGHT +#ifdef USE_WS2812 + else if (!strncmp(lp,"ws2812(",7)) { + lp+=7; + lp=isvar(lp,&vtype,&ind,0,0,0); + if (vtype!=VAR_NV) { + + uint8_t index=glob_script_mem.type[ind.index].index; + if ((vtype&STYPE)==0) { + + if (glob_script_mem.type[index].bits.is_filter) { + uint8_t len=0; + float *fa=Get_MFAddr(index,&len); + + if (fa && len) ws2812_set_array(fa,len); + } + } + } + goto next_line; + } +#endif +#endif + + else if (!strncmp(lp,"=>",2) || !strncmp(lp,"->",2) || !strncmp(lp,"print",5)) { + + uint8_t sflag=0,pflg=0,svmqtt,swll; + if (*lp=='p') { + pflg=1; + lp+=5; + } + else { + if (*lp=='-') sflag=1; + lp+=2; + } + char *slp=lp; + SCRIPT_SKIP_SPACES + #define SCRIPT_CMDMEM 512 + char *cmdmem=(char*)malloc(SCRIPT_CMDMEM); + if (cmdmem) { + char *cmd=cmdmem; + uint16_t count; + for (count=0; count=0) { + Set_MFVal(glob_script_mem.type[globvindex].index,globaindex,*dfvar); + } else { + Set_MFilter(glob_script_mem.type[globvindex].index,*dfvar); + } + } + + if (sysv_type) { + switch (sysv_type) { + case SCRIPT_LOGLEVEL: + glob_script_mem.script_loglevel=*dfvar; + break; + case SCRIPT_TELEPERIOD: + if (*dfvar<10) *dfvar=10; + if (*dfvar>300) *dfvar=300; + Settings.tele_period=*dfvar; + break; + } + sysv_type=0; + } + } else { + + numeric=0; + sindex=index; + + char str[SCRIPT_MAXSSIZE]; + lp=getop(lp,&lastop); + char *slp=lp; + glob_script_mem.glob_error=0; + lp=GetStringResult(lp,OPER_EQU,str,jo); + if (!js && glob_script_mem.glob_error) { + + lp=GetNumericResult(slp,OPER_EQU,&fvar,0); + dtostrfd(fvar,6,str); + glob_script_mem.glob_error=0; + } + + if (!glob_script_mem.var_not_found) { + + glob_script_mem.type[globvindex].bits.changed=1; + if (lastop==OPER_EQU) { + strlcpy(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); + } else if (lastop==OPER_PLSEQU) { + strncat(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); + } + } + } + + } + SCRIPT_SKIP_SPACES + if (*lp=='{' && if_state[ifstck]==3) { + lp+=1; + + } + goto next_line; + } + } else { + + if (*lp=='>' && tlen==1) { + + lp++; + section=1; + fromscriptcmd=1; + goto startline; + } + if (!strncmp(lp,type,tlen)) { + + section=1; + glob_script_mem.section_ptr=lp; + if (check) { + return 99; + } + + char *ctype=(char*)type; + if (*ctype=='#') { + + ctype+=tlen; + if (*ctype=='(' && *(lp+tlen)=='(') { + float fparam; + numeric=1; + glob_script_mem.glob_error=0; + GetNumericResult((char*)ctype,OPER_EQU,&fparam,0); + if (glob_script_mem.glob_error==1) { + + numeric=0; + + GetStringResult((char*)ctype+1,OPER_EQU,cmpstr,0); + } + lp+=tlen; + if (*lp=='(') { + + lp++; + lp=isvar(lp,&vtype,&ind,0,0,0); + if (vtype!=VAR_NV) { + + uint8_t index=glob_script_mem.type[ind.index].index; + if ((vtype&STYPE)==0) { + + dfvar=&glob_script_mem.fvars[index]; + if (numeric) { + *dfvar=fparam; + } else { + + *dfvar=CharToFloat(cmpstr); + } + } else { + + sindex=index; + if (!numeric) { + strlcpy(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),cmpstr,glob_script_mem.max_ssize); + } else { + + dtostrfd(fparam,6,glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize)); + } + } + } + } + } else { + lp+=tlen; + if (*ctype=='(' || (*lp!=SCRIPT_EOL && *lp!='?')) { + + section=0; + } + } + } + } + } + + next_line: + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) { + if (section) { + return 0; + } else { + return -1; + } + } + lp++; + } + } + return -1; +} + +uint8_t script_xsns_index = 0; + + +void ScripterEvery100ms(void) { + + if (Settings.rule_enabled && (uptime > 4)) { + mqtt_data[0] = '\0'; + uint16_t script_tele_period_save = tele_period; + tele_period = 2; + XsnsNextCall(FUNC_JSON_APPEND, script_xsns_index); + tele_period = script_tele_period_save; + if (strlen(mqtt_data)) { + mqtt_data[0] = '{'; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + Run_Scripter(">T",2, mqtt_data); + } + } + if (fast_script==99) Run_Scripter(">F",2,0); +} + + + + +void Scripter_save_pvars(void) { + int16_t mlen=0; + float *fp=(float*)glob_script_mem.script_pram; + mlen+=sizeof(float); + struct T_INDEX *vtp=glob_script_mem.type; + for (uint8_t count=0; countMAX_RULE_MEMS*10) { + vtp[count].bits.is_permanent=0; + return; + } + *fp++=glob_script_mem.fvars[index]; + } + } + char *cp=(char*)fp; + for (uint8_t count=0; countMAX_RULE_MEMS*10) { + vtp[count].bits.is_permanent=0; + return; + } + strcpy(cp,sp); + cp+=slen+1; + } + } +} + + +#ifdef USE_WEBSERVER + +#define WEB_HANDLE_SCRIPT "s10" +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" + +const char S_CONFIGURE_SCRIPT[] PROGMEM = D_CONFIGURE_SCRIPT; + +const char HTTP_BTN_MENU_RULES[] PROGMEM = + "

"; + + +const char HTTP_FORM_SCRIPT[] PROGMEM = + "
 " D_SCRIPT " " + "
"; + +const char HTTP_FORM_SCRIPT1[] PROGMEM = + "
" + "script enable
" + "
" + ""; + +const char HTTP_SCRIPT_FORM_END[] PROGMEM = + "
" + "" + "
"; + +#ifdef USE_SCRIPT_FATFS +const char HTTP_FORM_SCRIPT1c[] PROGMEM = +""; +#ifdef SDCARD_DIR +const char HTTP_FORM_SCRIPT1d[] PROGMEM = +""; +#else +const char HTTP_FORM_SCRIPT1d[] PROGMEM = +""; +#endif + +#ifdef SDCARD_DIR +const char S_SCRIPT_FILE_UPLOAD[] PROGMEM = D_SDCARD_DIR; +#else +const char S_SCRIPT_FILE_UPLOAD[] PROGMEM = D_SDCARD_UPLOAD; +#endif + +const char HTTP_FORM_FILE_UPLOAD[] PROGMEM = +"
" +"
 %s" " "; +const char HTTP_FORM_FILE_UPG[] PROGMEM = +"
" +"

" +"
"; + +const char HTTP_FORM_FILE_UPGb[] PROGMEM = +"
" +"
" +""; + +const char HTTP_FORM_SDC_DIRa[] PROGMEM = +"
"; +const char HTTP_FORM_SDC_DIRb[] PROGMEM = + "
%s    %d
"; +const char HTTP_FORM_SDC_DIRd[] PROGMEM = +"
%s
"; +const char HTTP_FORM_SDC_DIRc[] PROGMEM = +"
"; +const char HTTP_FORM_SDC_HREF[] PROGMEM = +"http://%s/upl?download=%s/%s"; +#endif + + + +#ifdef USE_SCRIPT_FATFS + +#if USE_LONG_FILE_NAMES>0 +#undef REJCMPL +#define REJCMPL 6 +#else +#undef REJCMPL +#define REJCMPL 8 +#endif + +uint8_t reject(char *name) { + + if (*name=='_') return 1; + if (*name=='.') return 1; + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 + if (!strncasecmp(name,"SPOTLI~1",REJCMPL)) return 1; + if (!strncasecmp(name,"TRASHE~1",REJCMPL)) return 1; + if (!strncasecmp(name,"FSEVEN~1",REJCMPL)) return 1; + if (!strncasecmp(name,"SYSTEM~1",REJCMPL)) return 1; +#else + if (!strcasecmp(name,"SPOTLI~1")) return 1; + if (!strcasecmp(name,"TRASHE~1")) return 1; + if (!strcasecmp(name,"FSEVEN~1")) return 1; + if (!strcasecmp(name,"SYSTEM~1")) return 1; +#endif + return 0; +} + +void ListDir(char *path, uint8_t depth) { + char name[32]; + char npath[128]; + char format[12]; + sprintf(format,"%%-%ds",24-depth); + + File dir=SD.open(path); + if (dir) { + dir.rewindDirectory(); + if (strlen(path)>1) { + snprintf_P(npath,sizeof(npath),PSTR("http://%s/upl?download=%s"),WiFi.localIP().toString().c_str(),path); + for (uint8_t cnt=strlen(npath)-1;cnt>0;cnt--) { + if (npath[cnt]=='/') { + if (npath[cnt-1]=='=') npath[cnt+1]=0; + else npath[cnt]=0; + break; + } + } + WSContentSend_P(HTTP_FORM_SDC_DIRd,npath,path,".."); + } + while (true) { + File entry=dir.openNextFile(); + if (!entry) { + break; + } + char *pp=path; + if (!*(pp+1)) pp++; + char *cp=name; + + if (reject((char*)entry.name())) goto fclose; + + for (uint8_t cnt=0;cnt1) { + strcat(path,"/"); + } + strcat(path,entry.name()); + ListDir(path,depth+4); + path[plen]=0; + } else { + snprintf_P(npath,sizeof(npath),HTTP_FORM_SDC_HREF,WiFi.localIP().toString().c_str(),pp,entry.name()); + WSContentSend_P(HTTP_FORM_SDC_DIRb,npath,entry.name(),name,entry.size()); + } + fclose: + entry.close(); + } + dir.close(); + } +} + +char path[48]; + +void Script_FileUploadConfiguration(void) +{ + uint8_t depth=0; + strcpy(path,"/"); + + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("download")) { + String stmp = WebServer->arg("download"); + char *cp=(char*)stmp.c_str(); + if (DownloadFile(cp)) { + + strcpy(path,cp); + } + } + + WSContentStart_P(S_SCRIPT_FILE_UPLOAD); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_FILE_UPLOAD,D_SDCARD_DIR); + WSContentSend_P(HTTP_FORM_FILE_UPG, "upload"); +#ifdef SDCARD_DIR + WSContentSend_P(HTTP_FORM_SDC_DIRa); + if (glob_script_mem.script_sd_found) { + ListDir(path,depth); + } + WSContentSend_P(HTTP_FORM_SDC_DIRc); +#endif + WSContentSend_P(HTTP_FORM_FILE_UPGb); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); + Web.upload_error = 0; +} + +File upload_file; + +void ScriptFileUploadSuccess(void) { + WSContentStart_P(S_INFORMATION); + WSContentSendStyle(); + WSContentSend_P(PSTR("
" D_UPLOAD " " D_SUCCESSFUL "
"), WebColor(COL_TEXT_SUCCESS)); + WSContentSend_P(PSTR("

")); + WSContentSend_P(PSTR("

"),"/upl",D_UPL_DONE); + + WSContentStop(); +} + + + +void script_upload(void) { + + + + HTTPUpload& upload = WebServer->upload(); + if (upload.status == UPLOAD_FILE_START) { + char npath[48]; + sprintf(npath,"%s/%s",path,upload.filename.c_str()); + SD.remove(npath); + upload_file=SD.open(npath,FILE_WRITE); + if (!upload_file) Web.upload_error=1; + } else if(upload.status == UPLOAD_FILE_WRITE) { + if (upload_file) upload_file.write(upload.buf,upload.currentSize); + } else if(upload.status == UPLOAD_FILE_END) { + if (upload_file) upload_file.close(); + if (Web.upload_error) { + AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload error")); + } + } else { + Web.upload_error=1; + WebServer->send(500, "text/plain", "500: couldn't create file"); + } +} + +uint8_t DownloadFile(char *file) { + File download_file; + WiFiClient download_Client; + + if (!SD.exists(file)) { + AddLog_P(LOG_LEVEL_INFO,PSTR("file not found")); + return 0; + } + + download_file=SD.open(file,FILE_READ); + if (!download_file) { + AddLog_P(LOG_LEVEL_INFO,PSTR("could not open file")); + return 0; + } + + if (download_file.isDirectory()) { + download_file.close(); + return 1; + } + + uint32_t flen=download_file.size(); + + download_Client = WebServer->client(); + WebServer->setContentLength(flen); + + char attachment[100]; + char *cp; + for (uint8_t cnt=strlen(file); cnt>=0; cnt--) { + if (file[cnt]=='/') { + cp=&file[cnt+1]; + break; + } + } + snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"),cp); + WebServer->sendHeader(F("Content-Disposition"), attachment); + WSSend(200, CT_STREAM, ""); + + uint8_t buff[512]; + uint16_t bread; + + + uint8_t cnt=0; + while (download_file.available()) { + bread=download_file.read(buff,sizeof(buff)); + uint16_t bw=download_Client.write((const char*)buff,bread); + if (!bw) break; + cnt++; + if (cnt>7) { + cnt=0; + if (glob_script_mem.script_loglevel&0x80) { + + loop(); + } + } + } + download_file.close(); + download_Client.stop(); + return 0; +} + +#endif + + +void HandleScriptTextareaConfiguration(void) { + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("save")) { + ScriptSaveSettings(); + HandleConfiguration(); + return; + } +} + +void HandleScriptConfiguration(void) { + + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_SCRIPT); + +#ifdef USE_SCRIPT_FATFS + if (WebServer->hasArg("d1")) { + DownloadFile(glob_script_mem.flink[0]); + } + if (WebServer->hasArg("d2")) { + DownloadFile(glob_script_mem.flink[1]); + } + if (WebServer->hasArg("upl")) { + Script_FileUploadConfiguration(); + } +#endif + + WSContentStart_P(S_CONFIGURE_SCRIPT); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_SCRIPT); + WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",glob_script_mem.script_size); + + + if (glob_script_mem.script_ram[0]) { + _WSContentSend(glob_script_mem.script_ram); + } + WSContentSend_P(HTTP_FORM_SCRIPT1b); + +#ifdef USE_SCRIPT_FATFS + if (glob_script_mem.script_sd_found) { + WSContentSend_P(HTTP_FORM_SCRIPT1d); + if (glob_script_mem.flink[0][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,1,glob_script_mem.flink[0]); + if (glob_script_mem.flink[1][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,2,glob_script_mem.flink[1]); + } +#endif + + WSContentSend_P(HTTP_SCRIPT_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); + } + + +void ScriptSaveSettings(void) { + + if (WebServer->hasArg("c1")) { + bitWrite(Settings.rule_enabled,0,1); + } else { + bitWrite(Settings.rule_enabled,0,0); + } + + + String str = WebServer->arg("t1"); + + if (*str.c_str()) { + + str.replace("\r\n","\n"); + str.replace("\r","\n"); + + strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size); + +#ifdef USE_24C256 +#ifndef USE_SCRIPT_FATFS + if (glob_script_mem.flags&1) { + EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); + } +#endif +#endif + +#ifdef USE_SCRIPT_FATFS + if (glob_script_mem.flags&1) { + SD.remove(FAT_SCRIPT_NAME); + File file=SD.open(FAT_SCRIPT_NAME,FILE_WRITE); + file.write(glob_script_mem.script_ram,FAT_SCRIPT_SIZE); + file.close(); + } +#endif + + } + + if (glob_script_mem.script_mem) { + Scripter_save_pvars(); + free(glob_script_mem.script_mem); + glob_script_mem.script_mem=0; + glob_script_mem.script_mem_size=0; + } + + if (bitRead(Settings.rule_enabled, 0)) { + int16_t res=Init_Scripter(); + if (res) { + snprintf_P(log_data, sizeof(log_data), PSTR("script init error: %d"),res); + AddLog(LOG_LEVEL_INFO); + return; + } + Run_Scripter(">B",2,0); + fast_script=Run_Scripter(">F",-2,0); + } +} + +#endif + + +#ifdef USE_SCRIPT_SUB_COMMAND +bool Script_SubCmd(void) { + if (!bitRead(Settings.rule_enabled, 0)) return false; + + char cmdbuff[128]; + char *cp=cmdbuff; + *cp++='#'; + strcpy(cp,XdrvMailbox.topic); + uint8_t tlen=strlen(XdrvMailbox.topic); + cp+=tlen; + if (XdrvMailbox.index > 0) { + *cp++=XdrvMailbox.index|0x30; + tlen++; + } + if ((XdrvMailbox.payload>0) || (XdrvMailbox.data_len>0)) { + *cp++='('; + strncpy(cp,XdrvMailbox.data,XdrvMailbox.data_len); + cp+=XdrvMailbox.data_len; + *cp++=')'; + *cp=0; + } + + uint32_t res=Run_Scripter(cmdbuff,tlen+1,0); + + if (res) return false; + else return true; +} +#endif + +void execute_script(char *script) { + char *svd_sp=glob_script_mem.scriptptr; + strcat(script,"\n#"); + glob_script_mem.scriptptr=script; + Run_Scripter(">",1,0); + glob_script_mem.scriptptr=svd_sp; +} +#define D_CMND_SCRIPT "Script" +#define D_CMND_SUBSCRIBE "Subscribe" +#define D_CMND_UNSUBSCRIBE "Unsubscribe" + +enum ScriptCommands { CMND_SCRIPT,CMND_SUBSCRIBE, CMND_UNSUBSCRIBE }; +const char kScriptCommands[] PROGMEM = D_CMND_SCRIPT "|" D_CMND_SUBSCRIBE "|" D_CMND_UNSUBSCRIBE; + +bool ScriptCommand(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t index = XdrvMailbox.index; + + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kScriptCommands); + if (-1 == command_code) { +#ifdef USE_SCRIPT_SUB_COMMAND + strlcpy(command,XdrvMailbox.topic,CMDSZ); + uint32_t pl=XdrvMailbox.payload; + char pld[64]; + strlcpy(pld,XdrvMailbox.data,sizeof(pld)); + if (Script_SubCmd()) { + if (pl>=0) { + Response_P(S_JSON_COMMAND_NVALUE, command, pl); + } else { + Response_P(S_JSON_COMMAND_SVALUE, command, pld); + } + return serviced; + } +#endif + serviced = false; + } + else if ((CMND_SCRIPT == command_code) && (index > 0)) { + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 2)) { + switch (XdrvMailbox.payload) { + case 0: + case 1: + bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload); + } + } else { + if ('>' == XdrvMailbox.data[0]) { + + snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"),command,XdrvMailbox.data); + if (bitRead(Settings.rule_enabled, 0)) { + for (uint8_t count=0; count> 1; +} + +void dateTime(uint16_t* date, uint16_t* time) { + + *date = xFAT_DATE(RtcTime.year,RtcTime.month, RtcTime.day_of_month); + + *time = xFAT_TIME(RtcTime.hour,RtcTime.minute,RtcTime.second); +} + +#endif + + + +#ifdef SUPPORT_MQTT_EVENT +# 3469 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_scripter.ino" +bool ScriptMqttData(void) +{ + bool serviced = false; + + toLog(XdrvMailbox.data); + if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) { + return false; + } + String sTopic = XdrvMailbox.topic; + String sData = XdrvMailbox.data; + + MQTT_Subscription event_item; + + for (uint32_t index = 0; index < subscriptions.size(); index++) { + event_item = subscriptions.get(index); + + + if (sTopic.startsWith(event_item.Topic)) { + + serviced = true; + String value; + String lkey; + if (event_item.Key.length() == 0) { + value = sData; + } else { + StaticJsonBuffer<400> jsonBuf; + JsonObject& jsonData = jsonBuf.parseObject(sData); + String key1 = event_item.Key; + String key2; + if (!jsonData.success()) break; + int dot; + if ((dot = key1.indexOf('.')) > 0) { + key2 = key1.substring(dot+1); + key1 = key1.substring(0, dot); + lkey=key2; + if (!jsonData[key1][key2].success()) break; + value = (const char *)jsonData[key1][key2]; + } else { + if (!jsonData[key1].success()) break; + value = (const char *)jsonData[key1]; + lkey=key1; + } + } + value.trim(); + char sbuffer[128]; + + if (!strncmp(lkey.c_str(),"Epoch",5)) { + uint32_t ep=atoi(value.c_str())-(uint32_t)EPOCH_OFFSET; + snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=%d\n"), event_item.Event.c_str(),ep); + } else { + snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str()); + } + + execute_script(sbuffer); + } + } + return serviced; +} +# 3544 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_scripter.ino" +String ScriptSubscribe(const char *data, int data_len) +{ + MQTT_Subscription subscription_item; + String events; + if (data_len > 0) { + char parameters[data_len+1]; + memcpy(parameters, data, data_len); + parameters[data_len] = '\0'; + String event_name, topic, key; + + char * pos = strtok(parameters, ","); + if (pos) { + event_name = Trim(pos); + pos = strtok(nullptr, ","); + if (pos) { + topic = Trim(pos); + pos = strtok(nullptr, ","); + if (pos) { + key = Trim(pos); + } + } + } + + + if (event_name.length() > 0 && topic.length() > 0) { + + for (uint32_t index=0; index < subscriptions.size(); index++) { + if (subscriptions.get(index).Event.equals(event_name)) { + + String stopic = subscriptions.get(index).Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + subscriptions.remove(index); + break; + } + } + + if (!topic.endsWith("#")) { + if (topic.endsWith("/")) { + topic.concat("#"); + } else { + topic.concat("/#"); + } + } + + + subscription_item.Event = event_name; + subscription_item.Topic = topic.substring(0, topic.length() - 2); + subscription_item.Key = key; + subscriptions.add(subscription_item); + + MqttSubscribe(topic.c_str()); + events.concat(event_name + "," + topic + + (key.length()>0 ? "," : "") + + key); + } else { + events = D_JSON_WRONG_PARAMETERS; + } + } else { + + for (uint32_t index=0; index < subscriptions.size(); index++) { + subscription_item = subscriptions.get(index); + events.concat(subscription_item.Event + "," + subscription_item.Topic + + (subscription_item.Key.length()>0 ? "," : "") + + subscription_item.Key + "; "); + } + } + return events; +} +# 3624 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_scripter.ino" +String ScriptUnsubscribe(const char * data, int data_len) +{ + MQTT_Subscription subscription_item; + String events; + if (data_len > 0) { + for (uint32_t index = 0; index < subscriptions.size(); index++) { + subscription_item = subscriptions.get(index); + if (subscription_item.Event.equalsIgnoreCase(data)) { + String stopic = subscription_item.Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + events = subscription_item.Event; + subscriptions.remove(index); + break; + } + } + } else { + + String stopic; + while (subscriptions.size() > 0) { + events.concat(subscriptions.get(0).Event + "; "); + stopic = subscriptions.get(0).Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + subscriptions.remove(0); + } + } + return events; +} +#endif + +#ifdef USE_SCRIPT_WEB_DISPLAY + + +void Script_Check_HTML_Setvars(void) { + + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("sv")) { + String stmp = WebServer->arg("sv"); + char cmdbuf[64]; + memset(cmdbuf,0,sizeof(cmdbuf)); + char *cp=cmdbuf; + *cp++='>'; + strncpy(cp,stmp.c_str(),sizeof(cmdbuf)-1); + char *cp1=strchr(cp,'_'); + if (!cp1) return; + *cp1=0; + char vname[32]; + strncpy(vname,cp,sizeof(vname)); + *cp1='='; + cp1++; + + struct T_INDEX ind; + uint8_t vtype; + isvar(vname,&vtype,&ind,0,0,0); + if (vtype!=NUM_RES && vtype&STYPE) { + + uint8_t tlen=strlen(cp1); + memmove(cp1+1,cp1,tlen); + *cp1='\"'; + *(cp1+tlen+1)='\"'; + } + + + execute_script(cmdbuf); + Run_Scripter(">E",2,0); + } +} + + +const char SCRIPT_MSG_BUTTONa[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUTTONa_TBL[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUTTONb[] PROGMEM = + "<\img>"; + +const char SCRIPT_MSG_BUT_START[] PROGMEM = + "
"; +const char SCRIPT_MSG_BUT_START_TBL[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUT_STOP[] PROGMEM = + ""; +const char SCRIPT_MSG_BUT_STOP_TBL[] PROGMEM = + "
"; + +const char SCRIPT_MSG_SLIDER[] PROGMEM = + "
%s
%s%s
" + "
"; + +const char SCRIPT_MSG_CHKBOX[] PROGMEM = + "
"; + +const char SCRIPT_MSG_TEXTINP[] PROGMEM = + "
"; + +const char SCRIPT_MSG_NUMINP[] PROGMEM = + "
"; + + +void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen) { +uint32_t cnt; + for (cnt=0;cntW",-2,0); + if (web_script==99) { + char line[128]; + char tmp[128]; + uint8_t optflg=0; + char *lp=glob_script_mem.section_ptr+2; + while (lp) { + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + memcpy(line,lp,sizeof(line)); + line[sizeof(line)-1]=0; + char *cp=line; + for (uint32_t i=0; i0) { + cp="checked='checked'"; + uval=0; + } else { + cp=""; + uval=1; + } + WSContentSend_PD(SCRIPT_MSG_CHKBOX,label,(char*)cp,uval,vname); + + } else if (!strncmp(lin,"bu(",3)) { + char *lp=lin+3; + uint8_t bcnt=0; + char *found=lin; + while (bcnt<4) { + found=strstr(found,"bu("); + if (!found) break; + found+=3; + bcnt++; + } + uint8_t proz=100/bcnt; + if (!optflg && bcnt>1) proz-=2; + if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_START_TBL); + else WSContentSend_PD(SCRIPT_MSG_BUT_START); + for (uint32_t cnt=0;cnt0) { + cp=ontxt; + uval=0; + } else { + cp=offtxt; + uval=1; + } + if (bcnt>1 && cnt==bcnt-1) { + if (!optflg) proz+=2; + } + if (!optflg) { + WSContentSend_PD(SCRIPT_MSG_BUTTONa,proz,uval,vname,cp); + } else { + WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL,proz,uval,vname,cp); + } + if (bcnt>1 && cnt%s
"),tmp); + } else { + WSContentSend_PD(PSTR("{s}%s{e}"),tmp); + } + } + } + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } + } +} +#endif + +#ifdef USE_SCRIPT_JSON_EXPORT +void ScriptJsonAppend(void) { + uint8_t web_script=Run_Scripter(">J",-2,0); + if (web_script==99) { + char line[128]; + char tmp[128]; + char *lp=glob_script_mem.section_ptr+2; + while (lp) { + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + memcpy(line,lp,sizeof(line)); + line[sizeof(line)-1]=0; + char *cp=line; + for (uint32_t i=0; iB",2,0); + fast_script=Run_Scripter(">F",-2,0); + } + break; + case FUNC_EVERY_100_MSECOND: + ScripterEvery100ms(); + break; + case FUNC_EVERY_SECOND: + ScriptEverySecond(); + break; + case FUNC_COMMAND: + result = ScriptCommand(); + break; + case FUNC_SET_POWER: + case FUNC_RULES_PROCESS: + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,mqtt_data); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_RULES); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); + WebServer->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration); + +#ifdef USE_SCRIPT_FATFS + WebServer->on("/u3", HTTP_POST,[]() { WebServer->sendHeader("Location","/u3");WebServer->send(303);},script_upload); + WebServer->on("/u3", HTTP_GET,ScriptFileUploadSuccess); + WebServer->on("/upl", HTTP_GET,Script_FileUploadConfiguration); +#endif + break; +#endif + case FUNC_SAVE_BEFORE_RESTART: + if (bitRead(Settings.rule_enabled, 0)) { + Run_Scripter(">R",2,0); + Scripter_save_pvars(); + } + break; +#ifdef SUPPORT_MQTT_EVENT + case FUNC_MQTT_DATA: + if (bitRead(Settings.rule_enabled, 0)) { + result = ScriptMqttData(); + } + break; +#endif +#ifdef USE_SCRIPT_WEB_DISPLAY + case FUNC_WEB_SENSOR: + if (bitRead(Settings.rule_enabled, 0)) { + ScriptWebShow(); + } + break; +#endif + +#ifdef USE_SCRIPT_JSON_EXPORT + case FUNC_JSON_APPEND: + ScriptJsonAppend(); + break; +#endif + + + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_11_knx.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_11_knx.ino" +#ifdef USE_KNX +# 51 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_11_knx.ino" +#define XDRV_11 11 + +#include + +address_t KNX_physs_addr; +address_t KNX_addr; + +#define KNX_Empty 255 + +#define TOGGLE_INHIBIT_TIME 15 + +float last_temp; +float last_hum; +uint8_t toggle_inhibit; + +typedef struct __device_parameters +{ + uint8_t type; + + + + + bool show; + + bool last_state; + + callback_id_t CB_id; + + + + + +} device_parameters_t; + + +device_parameters_t device_param[] = { + { 1, false, false, KNX_Empty }, + { 2, false, false, KNX_Empty }, + { 3, false, false, KNX_Empty }, + { 4, false, false, KNX_Empty }, + { 5, false, false, KNX_Empty }, + { 6, false, false, KNX_Empty }, + { 7, false, false, KNX_Empty }, + { 8, false, false, KNX_Empty }, + { 9, false, false, KNX_Empty }, + { 10, false, false, KNX_Empty }, + { 11, false, false, KNX_Empty }, + { 12, false, false, KNX_Empty }, + { 13, false, false, KNX_Empty }, + { 14, false, false, KNX_Empty }, + { 15, false, false, KNX_Empty }, + { 16, false, false, KNX_Empty }, + { KNX_TEMPERATURE, false, false, KNX_Empty }, + { KNX_HUMIDITY , false, false, KNX_Empty }, + { KNX_ENERGY_VOLTAGE , false, false, KNX_Empty }, + { KNX_ENERGY_CURRENT , false, false, KNX_Empty }, + { KNX_ENERGY_POWER , false, false, KNX_Empty }, + { KNX_ENERGY_POWERFACTOR , false, false, KNX_Empty }, + { KNX_ENERGY_DAILY , false, false, KNX_Empty }, + { KNX_ENERGY_START , false, false, KNX_Empty }, + { KNX_ENERGY_TOTAL , false, false, KNX_Empty }, + { KNX_SLOT1 , false, false, KNX_Empty }, + { KNX_SLOT2 , false, false, KNX_Empty }, + { KNX_SLOT3 , false, false, KNX_Empty }, + { KNX_SLOT4 , false, false, KNX_Empty }, + { KNX_SLOT5 , false, false, KNX_Empty }, + { KNX_Empty, false, false, KNX_Empty} +}; + + +const char * device_param_ga[] = { + D_TIMER_OUTPUT " 1", + D_TIMER_OUTPUT " 2", + D_TIMER_OUTPUT " 3", + D_TIMER_OUTPUT " 4", + D_TIMER_OUTPUT " 5", + D_TIMER_OUTPUT " 6", + D_TIMER_OUTPUT " 7", + D_TIMER_OUTPUT " 8", + D_SENSOR_BUTTON " 1", + D_SENSOR_BUTTON " 2", + D_SENSOR_BUTTON " 3", + D_SENSOR_BUTTON " 4", + D_SENSOR_BUTTON " 5", + D_SENSOR_BUTTON " 6", + D_SENSOR_BUTTON " 7", + D_SENSOR_BUTTON " 8", + D_TEMPERATURE , + D_HUMIDITY , + D_VOLTAGE , + D_CURRENT , + D_POWERUSAGE , + D_POWER_FACTOR , + D_ENERGY_TODAY , + D_ENERGY_YESTERDAY , + D_ENERGY_TOTAL , + D_KNX_TX_SLOT " 1", + D_KNX_TX_SLOT " 2", + D_KNX_TX_SLOT " 3", + D_KNX_TX_SLOT " 4", + D_KNX_TX_SLOT " 5", + nullptr +}; + + +const char *device_param_cb[] = { + D_TIMER_OUTPUT " 1", + D_TIMER_OUTPUT " 2", + D_TIMER_OUTPUT " 3", + D_TIMER_OUTPUT " 4", + D_TIMER_OUTPUT " 5", + D_TIMER_OUTPUT " 6", + D_TIMER_OUTPUT " 7", + D_TIMER_OUTPUT " 8", + D_TIMER_OUTPUT " 1 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 2 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 3 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 4 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 5 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 6 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 7 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 8 " D_BUTTON_TOGGLE, + D_REPLY " " D_TEMPERATURE, + D_REPLY " " D_HUMIDITY, + D_REPLY " " D_VOLTAGE , + D_REPLY " " D_CURRENT , + D_REPLY " " D_POWERUSAGE , + D_REPLY " " D_POWER_FACTOR , + D_REPLY " " D_ENERGY_TODAY , + D_REPLY " " D_ENERGY_YESTERDAY , + D_REPLY " " D_ENERGY_TOTAL , + D_KNX_RX_SLOT " 1", + D_KNX_RX_SLOT " 2", + D_KNX_RX_SLOT " 3", + D_KNX_RX_SLOT " 4", + D_KNX_RX_SLOT " 5", + nullptr +}; + + +#define D_PRFX_KNX "Knx" +#define D_CMND_KNXTXCMND "Tx_Cmnd" +#define D_CMND_KNXTXVAL "Tx_Val" +#define D_CMND_KNX_ENABLED "_Enabled" +#define D_CMND_KNX_ENHANCED "_Enhanced" +#define D_CMND_KNX_PA "_PA" +#define D_CMND_KNX_GA "_GA" +#define D_CMND_KNX_CB "_CB" + +const char kKnxCommands[] PROGMEM = D_PRFX_KNX "|" + D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL "|" D_CMND_KNX_ENABLED "|" D_CMND_KNX_ENHANCED "|" D_CMND_KNX_PA "|" D_CMND_KNX_GA "|" D_CMND_KNX_CB ; + +void (* const KnxCommand[])(void) PROGMEM = { + &CmndKnxTxCmnd, &CmndKnxTxVal, &CmndKnxEnabled, &CmndKnxEnhanced, &CmndKnxPa, &CmndKnxGa, &CmndKnxCb }; + +uint8_t KNX_GA_Search( uint8_t param, uint8_t start = 0 ) +{ + for (uint32_t i = start; i < Settings.knx_GA_registered; ++i) + { + if ( Settings.knx_GA_param[i] == param ) + { + if ( Settings.knx_GA_addr[i] != 0 ) + { + if ( i >= start ) { return i; } + } + } + } + return KNX_Empty; +} + + +uint8_t KNX_CB_Search( uint8_t param, uint8_t start = 0 ) +{ + for (uint32_t i = start; i < Settings.knx_CB_registered; ++i) + { + if ( Settings.knx_CB_param[i] == param ) + { + if ( Settings.knx_CB_addr[i] != 0 ) + { + if ( i >= start ) { return i; } + } + } + } + return KNX_Empty; +} + + +void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF ) +{ + + if ( Settings.knx_GA_registered >= MAX_KNX_GA ) { return; } + if ( GA_FNUM == 0 && GA_AREA == 0 && GA_FDEF == 0 ) { return; } + + + Settings.knx_GA_param[Settings.knx_GA_registered] = GAop; + KNX_addr.ga.area = GA_FNUM; + KNX_addr.ga.line = GA_AREA; + KNX_addr.ga.member = GA_FDEF; + Settings.knx_GA_addr[Settings.knx_GA_registered] = KNX_addr.value; + + Settings.knx_GA_registered++; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " GA #%d: %s " D_TO " %d/%d/%d"), + Settings.knx_GA_registered, + device_param_ga[GAop-1], + GA_FNUM, GA_AREA, GA_FDEF ); +} + + +void KNX_DEL_GA( uint8_t GAnum ) +{ + + uint8_t dest_offset = 0; + uint8_t src_offset = 0; + uint8_t len = 0; + + + Settings.knx_GA_param[GAnum-1] = 0; + + if (GAnum == 1) + { + + src_offset = 1; + + + + len = (Settings.knx_GA_registered - 1); + } + else if (GAnum == Settings.knx_GA_registered) + { + + } + else + { + + + + + dest_offset = GAnum -1 ; + src_offset = dest_offset + 1; + len = (Settings.knx_GA_registered - GAnum); + } + + if (len > 0) + { + memmove(Settings.knx_GA_param + dest_offset, Settings.knx_GA_param + src_offset, len * sizeof(uint8_t)); + memmove(Settings.knx_GA_addr + dest_offset, Settings.knx_GA_addr + src_offset, len * sizeof(uint16_t)); + } + + Settings.knx_GA_registered--; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " GA #%d"), + GAnum ); +} + + +void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF ) +{ + + if ( Settings.knx_CB_registered >= MAX_KNX_CB ) { return; } + if ( CB_FNUM == 0 && CB_AREA == 0 && CB_FDEF == 0 ) { return; } + + + if ( device_param[CBop-1].CB_id == KNX_Empty ) + { + + device_param[CBop-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[CBop-1]); + + + + + } + + Settings.knx_CB_param[Settings.knx_CB_registered] = CBop; + KNX_addr.ga.area = CB_FNUM; + KNX_addr.ga.line = CB_AREA; + KNX_addr.ga.member = CB_FDEF; + Settings.knx_CB_addr[Settings.knx_CB_registered] = KNX_addr.value; + + knx.callback_assign( device_param[CBop-1].CB_id, KNX_addr ); + + Settings.knx_CB_registered++; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " CB #%d: %d/%d/%d " D_TO " %s"), + Settings.knx_CB_registered, + CB_FNUM, CB_AREA, CB_FDEF, + device_param_cb[CBop-1] ); +} + + +void KNX_DEL_CB( uint8_t CBnum ) +{ + uint8_t oldparam = Settings.knx_CB_param[CBnum-1]; + uint8_t dest_offset = 0; + uint8_t src_offset = 0; + uint8_t len = 0; + + + knx.callback_unassign(CBnum-1); + Settings.knx_CB_param[CBnum-1] = 0; + + if (CBnum == 1) + { + + src_offset = 1; + + + + len = (Settings.knx_CB_registered - 1); + } + else if (CBnum == Settings.knx_CB_registered) + { + + } + else + { + + + + + dest_offset = CBnum -1 ; + src_offset = dest_offset + 1; + len = (Settings.knx_CB_registered - CBnum); + } + + if (len > 0) + { + memmove(Settings.knx_CB_param + dest_offset, Settings.knx_CB_param + src_offset, len * sizeof(uint8_t)); + memmove(Settings.knx_CB_addr + dest_offset, Settings.knx_CB_addr + src_offset, len * sizeof(uint16_t)); + } + + Settings.knx_CB_registered--; + + + if ( KNX_CB_Search( oldparam ) == KNX_Empty ) { + knx.callback_deregister( device_param[oldparam-1].CB_id ); + device_param[oldparam-1].CB_id = KNX_Empty; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " CB #%d"), CBnum ); +} + + +bool KNX_CONFIG_NOT_MATCH(void) +{ + + for (uint32_t i = 0; i < KNX_MAX_device_param; ++i) + { + if ( !device_param[i].show ) { + + + + if ( KNX_GA_Search(i+1) != KNX_Empty ) { return true; } + + if ( i < 8 ) + { + if ( KNX_CB_Search(i+1) != KNX_Empty ) { return true; } + if ( KNX_CB_Search(i+9) != KNX_Empty ) { return true; } + } + + if ( i > 15 ) + { + if ( KNX_CB_Search(i+1) != KNX_Empty ) { return true; } + } + } + } + + + for (uint32_t i = 0; i < Settings.knx_GA_registered; ++i) + { + if ( Settings.knx_GA_param[i] != 0 ) + { + if ( Settings.knx_GA_addr[i] == 0 ) + { + return true; + } + } + } + for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i) + { + if ( Settings.knx_CB_param[i] != 0 ) + { + if ( Settings.knx_CB_addr[i] == 0 ) + { + return true; + } + } + } + + return false; +} + + +void KNXStart(void) +{ + knx.start(nullptr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_START)); +} + + +void KNX_INIT(void) +{ + + if (Settings.knx_GA_registered > MAX_KNX_GA) { Settings.knx_GA_registered = MAX_KNX_GA; } + if (Settings.knx_CB_registered > MAX_KNX_CB) { Settings.knx_CB_registered = MAX_KNX_CB; } + + + KNX_physs_addr.value = Settings.knx_physsical_addr; + knx.physical_address_set( KNX_physs_addr ); +# 472 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_11_knx.ino" + for (uint32_t i = 0; i < devices_present; ++i) + { + device_param[i].show = true; + } + for (uint32_t i = GPIO_SWT1; i < GPIO_SWT4 + 1; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } + } + for (uint32_t i = GPIO_KEY1; i < GPIO_KEY4 + 1; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } + } + for (uint32_t i = GPIO_SWT1_NP; i < GPIO_SWT4_NP + 1; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1_NP + 8].show = true; } + } + for (uint32_t i = GPIO_KEY1_NP; i < GPIO_KEY4_NP + 1; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1_NP + 8].show = true; } + } + if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_DSB, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + + + if ( energy_flg != ENERGY_NONE ) { + device_param[KNX_ENERGY_POWER-1].show = true; + device_param[KNX_ENERGY_DAILY-1].show = true; + device_param[KNX_ENERGY_START-1].show = true; + device_param[KNX_ENERGY_TOTAL-1].show = true; + device_param[KNX_ENERGY_VOLTAGE-1].show = true; + device_param[KNX_ENERGY_CURRENT-1].show = true; + device_param[KNX_ENERGY_POWERFACTOR-1].show = true; + } + +#ifdef USE_RULES + device_param[KNX_SLOT1-1].show = true; + device_param[KNX_SLOT2-1].show = true; + device_param[KNX_SLOT3-1].show = true; + device_param[KNX_SLOT4-1].show = true; + device_param[KNX_SLOT5-1].show = true; +#endif + + + if (KNX_CONFIG_NOT_MATCH()) { + Settings.knx_GA_registered = 0; + Settings.knx_CB_registered = 0; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " " D_KNX_PARAMETERS)); + } + + + + + uint8_t j; + for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i) + { + j = Settings.knx_CB_param[i]; + if ( j > 0 ) + { + device_param[j-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[j-1]); + + + + KNX_addr.value = Settings.knx_CB_addr[i]; + knx.callback_assign( device_param[j-1].CB_id, KNX_addr ); + } + } +} + + +void KNX_CB_Action(message_t const &msg, void *arg) +{ + device_parameters_t *chan = (device_parameters_t *)arg; + if (!(Settings.flag.knx_enabled)) { return; } + + char tempchar[33]; + + if (msg.data_len == 1) { + + tempchar[0] = msg.data[0]; + tempchar[1] = '\0'; + } else { + + float tempvar = knx.data_to_2byte_float(msg.data); + dtostrfd(tempvar,2,tempchar); + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %s " D_TO " %s"), + msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member, + (msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER, + tempchar, + device_param_cb[(chan->type)-1]); + + switch (msg.ct) + { + case KNX_CT_WRITE: + if (chan->type < 9) + { + ExecuteCommandPower(chan->type, msg.data[0], SRC_KNX); + } + else if (chan->type < 17) + { + if (!toggle_inhibit) { + ExecuteCommandPower((chan->type) -8, POWER_TOGGLE, SRC_KNX); + if (Settings.flag.knx_enable_enhancement) { + toggle_inhibit = TOGGLE_INHIBIT_TIME; + } + } + } +#ifdef USE_RULES + else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) + { + if (!toggle_inhibit) { + char command[25]; + if (msg.data_len == 1) { + + snprintf_P(command, sizeof(command), PSTR("event KNXRX_CMND%d=%d"), ((chan->type) - KNX_SLOT1 + 1 ), msg.data[0]); + } else { + + snprintf_P(command, sizeof(command), PSTR("event KNXRX_VAL%d=%s"), ((chan->type) - KNX_SLOT1 + 1 ), tempchar); + } + ExecuteCommand(command, SRC_KNX); + if (Settings.flag.knx_enable_enhancement) { + toggle_inhibit = TOGGLE_INHIBIT_TIME; + } + } + } +#endif + break; + + case KNX_CT_READ: + if (chan->type < 9) + { + knx.answer_1bit(msg.received_on, chan->last_state); + if (Settings.flag.knx_enable_enhancement) { + knx.answer_1bit(msg.received_on, chan->last_state); + knx.answer_1bit(msg.received_on, chan->last_state); + } + } + else if (chan->type == KNX_TEMPERATURE) + { + knx.answer_2byte_float(msg.received_on, last_temp); + if (Settings.flag.knx_enable_enhancement) { + knx.answer_2byte_float(msg.received_on, last_temp); + knx.answer_2byte_float(msg.received_on, last_temp); + } + } + else if (chan->type == KNX_HUMIDITY) + { + knx.answer_2byte_float(msg.received_on, last_hum); + if (Settings.flag.knx_enable_enhancement) { + knx.answer_2byte_float(msg.received_on, last_hum); + knx.answer_2byte_float(msg.received_on, last_hum); + } + } +#ifdef USE_RULES + else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) + { + if (!toggle_inhibit) { + char command[25]; + snprintf_P(command, sizeof(command), PSTR("event KNXRX_REQ%d"), ((chan->type) - KNX_SLOT1 + 1 ) ); + ExecuteCommand(command, SRC_KNX); + if (Settings.flag.knx_enable_enhancement) { + toggle_inhibit = TOGGLE_INHIBIT_TIME; + } + } + } +#endif + break; + } +} + + +void KnxUpdatePowerState(uint8_t device, power_t state) +{ + if (!(Settings.flag.knx_enabled)) { return; } + + device_param[device -1].last_state = bitRead(state, device -1); + + + uint8_t i = KNX_GA_Search(device); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + knx.write_1bit(KNX_addr, device_param[device -1].last_state); + if (Settings.flag.knx_enable_enhancement) { + knx.write_1bit(KNX_addr, device_param[device -1].last_state); + knx.write_1bit(KNX_addr, device_param[device -1].last_state); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), + device_param_ga[device -1], device_param[device -1].last_state, + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(device, i + 1); + } +} + + +void KnxSendButtonPower(uint8_t key, uint8_t device, uint8_t state) +{ + + + + + + + + if (!(Settings.flag.knx_enabled)) { return; } + + + + + uint8_t i = KNX_GA_Search(device + 8); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + knx.write_1bit(KNX_addr, !(state == 0)); + if (Settings.flag.knx_enable_enhancement) { + knx.write_1bit(KNX_addr, !(state == 0)); + knx.write_1bit(KNX_addr, !(state == 0)); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), + device_param_ga[device + 7], !(state == 0), + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(device + 8, i + 1); + } + +} + + +void KnxSensor(uint8_t sensor_type, float value) +{ + if (sensor_type == KNX_TEMPERATURE) + { + last_temp = value; + } else if (sensor_type == KNX_HUMIDITY) + { + last_hum = value; + } + + if (!(Settings.flag.knx_enabled)) { return; } + + uint8_t i = KNX_GA_Search(sensor_type); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + knx.write_2byte_float(KNX_addr, value); + if (Settings.flag.knx_enable_enhancement) { + knx.write_2byte_float(KNX_addr, value); + knx.write_2byte_float(KNX_addr, value); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s " D_SENT_TO " %d.%d.%d "), + device_param_ga[sensor_type -1], + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(sensor_type, i+1); + } +} + + + + + + +#ifdef USE_WEBSERVER +#ifdef USE_KNX_WEB_MENU +const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX; + +const char HTTP_BTN_MENU_KNX[] PROGMEM = + "

"; + +const char HTTP_FORM_KNX[] PROGMEM = + "
" + " " D_KNX_PARAMETERS " " + "
" + "
" + "" D_KNX_PHYSICAL_ADDRESS " " + " . " + " . " + "" + "

" D_KNX_PHYSICAL_ADDRESS_NOTE "

" + "" D_KNX_ENABLE "" D_KNX_ENHANCEMENT "

" + + "
" + "" D_KNX_GROUP_ADDRESS_TO_WRITE "
" + + " / " + " / " + " "; + +const char HTTP_FORM_KNX_ADD_BTN[] PROGMEM = + "

" + ""; + +const char HTTP_FORM_KNX_ADD_TABLE_ROW[] PROGMEM = + "" + ""; + +const char HTTP_FORM_KNX3[] PROGMEM = + "
%s -> %d / %d / %d

" + "
" + "" D_KNX_GROUP_ADDRESS_TO_READ "
"; + +const char HTTP_FORM_KNX4[] PROGMEM = + "-> -> ")); + WSContentSend_P(HTTP_FORM_KNX_GA, "GA_FNUM", "GA_AREA", "GA_FDEF"); + WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "GAwarning", (Settings.knx_GA_registered < MAX_KNX_GA) ? "" : "disabled", 1); + for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i) + { + if ( Settings.knx_GA_param[i] ) + { + KNX_addr.value = Settings.knx_GA_addr[i]; + WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW, device_param_ga[Settings.knx_GA_param[i]-1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, i +1); + } + } + + WSContentSend_P(HTTP_FORM_KNX3); + WSContentSend_P(HTTP_FORM_KNX_GA, "CB_FNUM", "CB_AREA", "CB_FDEF"); + WSContentSend_P(HTTP_FORM_KNX4); + + uint8_t j; + for (uint32_t i = 0; i < KNX_MAX_device_param ; i++) + { + + if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; } + if ( i == 8 ) { j = 0; } + if ( device_param[j].show ) + { + WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_cb[i]); + } + } + WSContentSend_P(PSTR(" ")); + WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "CBwarning", (Settings.knx_CB_registered < MAX_KNX_CB) ? "" : "disabled", 2); + + for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i) + { + if ( Settings.knx_CB_param[i] ) + { + KNX_addr.value = Settings.knx_CB_addr[i]; + WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW2, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings.knx_CB_param[i]-1], i +1); + } + } + WSContentSend_P(PSTR("
")); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); + } + +} + + +void KNX_Save_Settings(void) +{ + String stmp; + address_t KNX_addr; + + Settings.flag.knx_enabled = WebServer->hasArg("b1"); + Settings.flag.knx_enable_enhancement = WebServer->hasArg("b2"); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ENABLED ": %d, " D_KNX_ENHANCEMENT ": %d"), + Settings.flag.knx_enabled, Settings.flag.knx_enable_enhancement ); + + stmp = WebServer->arg("area"); + KNX_addr.pa.area = stmp.toInt(); + stmp = WebServer->arg("line"); + KNX_addr.pa.line = stmp.toInt(); + stmp = WebServer->arg("member"); + KNX_addr.pa.member = stmp.toInt(); + Settings.knx_physsical_addr = KNX_addr.value; + knx.physical_address_set( KNX_addr ); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_KNX_PHYSICAL_ADDRESS ": %d.%d.%d "), + KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA: %d"), + Settings.knx_GA_registered ); + for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i) + { + KNX_addr.value = Settings.knx_GA_addr[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA #%d: %s " D_TO " %d/%d/%d"), + i+1, device_param_ga[Settings.knx_GA_param[i]-1], + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); + + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB: %d"), + Settings.knx_CB_registered ); + for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i) + { + KNX_addr.value = Settings.knx_CB_addr[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB #%d: %d/%d/%d " D_TO " %s"), + i+1, + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, + device_param_cb[Settings.knx_CB_param[i]-1] ); + } +} + +#endif +#endif + + + + + +void CmndKnxTxCmnd(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) { + + + + uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); + if (Settings.flag.knx_enable_enhancement) { + knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); + knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), + device_param_ga[XdrvMailbox.index + KNX_SLOT1 -2], !(XdrvMailbox.payload == 0), + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1, i + 1); + } + ResponseCmndIdxChar (XdrvMailbox.data ); + } +} + +void CmndKnxTxVal(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) { + + + + uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + + float tempvar = CharToFloat(XdrvMailbox.data); + dtostrfd(tempvar,2,XdrvMailbox.data); + + knx.write_2byte_float(KNX_addr, tempvar); + if (Settings.flag.knx_enable_enhancement) { + knx.write_2byte_float(KNX_addr, tempvar); + knx.write_2byte_float(KNX_addr, tempvar); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %s " D_SENT_TO " %d.%d.%d"), + device_param_ga[XdrvMailbox.index + KNX_SLOT1 -2], XdrvMailbox.data, + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1, i + 1); + } + ResponseCmndIdxChar (XdrvMailbox.data ); + } +} + +void CmndKnxEnabled(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.flag.knx_enabled = XdrvMailbox.payload; + } + ResponseCmndChar (GetStateText(Settings.flag.knx_enabled) ); +} + +void CmndKnxEnhanced(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.flag.knx_enable_enhancement = XdrvMailbox.payload; + } + ResponseCmndChar (GetStateText(Settings.flag.knx_enable_enhancement) ); +} + +void CmndKnxPa(void) +{ + if (XdrvMailbox.data_len) { + if (strstr(XdrvMailbox.data, ".") != nullptr) { + char sub_string[XdrvMailbox.data_len]; + + int pa_area = atoi(subStr(sub_string, XdrvMailbox.data, ".", 1)); + int pa_line = atoi(subStr(sub_string, XdrvMailbox.data, ".", 2)); + int pa_member = atoi(subStr(sub_string, XdrvMailbox.data, ".", 3)); + + if ( ((pa_area == 0) && (pa_line == 0) && (pa_member == 0)) + || (pa_area > 15) || (pa_line > 15) || (pa_member > 255) ) { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + + KNX_addr.pa.area = pa_area; + KNX_addr.pa.line = pa_line; + KNX_addr.pa.member = pa_member; + Settings.knx_physsical_addr = KNX_addr.value; + } + } + KNX_addr.value = Settings.knx_physsical_addr; + Response_P (PSTR("{\"%s\":\"%d.%d.%d\"}"), + XdrvMailbox.command, KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); +} + +void CmndKnxGa(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_GA)) { + if (XdrvMailbox.data_len) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + char sub_string[XdrvMailbox.data_len]; + + int ga_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); + int ga_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + int ga_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + int ga_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); + + if ( ((ga_area == 0) && (ga_line == 0) && (ga_member == 0)) + || (ga_area > 31) || (ga_line > 7) || (ga_member > 255) + || (ga_option < 0) || ((ga_option > KNX_MAX_device_param ) && (ga_option != KNX_Empty)) + || (!device_param[ga_option-1].show) ) { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + + KNX_addr.ga.area = ga_area; + KNX_addr.ga.line = ga_line; + KNX_addr.ga.member = ga_member; + + if ( XdrvMailbox.index > Settings.knx_GA_registered ) { + Settings.knx_GA_registered ++; + XdrvMailbox.index = Settings.knx_GA_registered; + } + + Settings.knx_GA_addr[XdrvMailbox.index -1] = KNX_addr.value; + Settings.knx_GA_param[XdrvMailbox.index -1] = ga_option; + } else { + if ( (XdrvMailbox.payload <= Settings.knx_GA_registered) && (XdrvMailbox.payload > 0) ) { + XdrvMailbox.index = XdrvMailbox.payload; + } else { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + } + if ( XdrvMailbox.index <= Settings.knx_GA_registered ) { + KNX_addr.value = Settings.knx_GA_addr[XdrvMailbox.index -1]; + Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"), + XdrvMailbox.command, XdrvMailbox.index, device_param_ga[Settings.knx_GA_param[XdrvMailbox.index-1]-1], + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); + } + } else { + ResponseCmndNumber (Settings.knx_GA_registered ); + } + } +} + +void CmndKnxCb(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_CB)) { + if (XdrvMailbox.data_len) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + char sub_string[XdrvMailbox.data_len]; + + int cb_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); + int cb_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + int cb_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + int cb_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); + + if ( ((cb_area == 0) && (cb_line == 0) && (cb_member == 0)) + || (cb_area > 31) || (cb_line > 7) || (cb_member > 255) + || (cb_option < 0) || ((cb_option > KNX_MAX_device_param ) && (cb_option != KNX_Empty)) + || (!device_param[cb_option-1].show) ) { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + + KNX_addr.ga.area = cb_area; + KNX_addr.ga.line = cb_line; + KNX_addr.ga.member = cb_member; + + if ( XdrvMailbox.index > Settings.knx_CB_registered ) { + Settings.knx_CB_registered ++; + XdrvMailbox.index = Settings.knx_CB_registered; + } + + Settings.knx_CB_addr[XdrvMailbox.index -1] = KNX_addr.value; + Settings.knx_CB_param[XdrvMailbox.index -1] = cb_option; + } else { + if ( (XdrvMailbox.payload <= Settings.knx_CB_registered) && (XdrvMailbox.payload > 0) ) { + XdrvMailbox.index = XdrvMailbox.payload; + } else { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + } + if ( XdrvMailbox.index <= Settings.knx_CB_registered ) { + KNX_addr.value = Settings.knx_CB_addr[XdrvMailbox.index -1]; + Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"), + XdrvMailbox.command, XdrvMailbox.index, device_param_cb[Settings.knx_CB_param[XdrvMailbox.index-1]-1], + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); + } + } else { + ResponseCmndNumber (Settings.knx_CB_registered ); + } + } +} + + + + + +bool Xdrv11(uint8_t function) +{ + bool result = false; + switch (function) { + case FUNC_LOOP: + if (!global_state.wifi_down) { knx.loop(); } + break; + case FUNC_PRE_INIT: + KNX_INIT(); + break; +#ifdef USE_WEBSERVER +#ifdef USE_KNX_WEB_MENU + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_KNX); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/kn", HandleKNXConfiguration); + break; +#endif +#endif + case FUNC_EVERY_50_MSECOND: + if (toggle_inhibit) { + toggle_inhibit--; + } + break; + case FUNC_COMMAND: + result = DecodeCommand(kKnxCommands, KnxCommand); + break; + + + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_12_home_assistant.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_12_home_assistant.ino" +#ifdef USE_HOME_ASSISTANT + +#define XDRV_12 12 + +const char HASS_DISCOVER_RELAY[] PROGMEM = + "{\"name\":\"%s\"," + "\"cmd_t\":\"%s\"," + "\"stat_t\":\"%s\"," + "\"val_tpl\":\"{{value_json.%s}}\"," + "\"pl_off\":\"%s\"," + "\"pl_on\":\"%s\"," + + "\"avty_t\":\"%s\"," + "\"pl_avail\":\"" D_ONLINE "\"," + "\"pl_not_avail\":\"" D_OFFLINE "\""; + +const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = + "{\"name\":\"%s\"," + "\"stat_t\":\"%s\"," + + "\"pl_on\":\"%s\"," + + "\"avty_t\":\"%s\"," + "\"pl_avail\":\"" D_ONLINE "\"," + "\"pl_not_avail\":\"" D_OFFLINE "\""; + +const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE[] PROGMEM = + ",\"off_delay\":1"; + +const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = + ",\"frc_upd\":true," + "\"pl_off\":\"%s\""; + +const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = + ",\"bri_cmd_t\":\"%s\"," + "\"bri_stat_t\":\"%s\"," + "\"bri_scl\":100," + "\"on_cmd_type\":\"%s\"," + "\"bri_val_tpl\":\"{{value_json." D_CMND_DIMMER "}}\""; + +const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = + ",\"rgb_cmd_t\":\"%s2\"," + "\"rgb_stat_t\":\"%s\"," + "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; + +const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = + ",\"whit_val_cmd_t\":\"%s\"," + "\"whit_val_stat_t\":\"%s\"," + "\"white_value_scale\":100," + "\"whit_val_tpl\":\"{{value_json.Channel[3]}}\""; + +const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = + ",\"clr_temp_cmd_t\":\"%s\"," + "\"clr_temp_stat_t\":\"%s\"," + "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; + +const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = + ",\"fx_cmd_t\":\"%s\"," + "\"fx_stat_t\":\"%s\"," + "\"fx_val_tpl\":\"{{value_json." D_CMND_SCHEME "}}\"," + "\"fx_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; + +const char HASS_DISCOVER_SENSOR[] PROGMEM = + "{\"name\":\"%s\"," + "\"stat_t\":\"%s\"," + "\"avty_t\":\"%s\"," + "\"pl_avail\":\"" D_ONLINE "\"," + "\"pl_not_avail\":\"" D_OFFLINE "\""; + +const char HASS_DISCOVER_SENSOR_TEMP[] PROGMEM = + ",\"unit_of_meas\":\"°%c\"," + "\"val_tpl\":\"{{value_json['%s'].Temperature}}\"," + "\"dev_cla\":\"temperature\""; + +const char HASS_DISCOVER_SENSOR_HUM[] PROGMEM = + ",\"unit_of_meas\":\"%%\"," + "\"val_tpl\":\"{{value_json['%s'].Humidity}}\"," + "\"dev_cla\":\"humidity\""; + +const char HASS_DISCOVER_SENSOR_PRESS[] PROGMEM = + ",\"unit_of_meas\":\"%s\"," + "\"val_tpl\":\"{{value_json['%s'].Pressure}}\"," + "\"dev_cla\":\"pressure\""; + + +const char HASS_DISCOVER_SENSOR_KWH[] PROGMEM = + ",\"unit_of_meas\":\"kWh\"," + "\"val_tpl\":\"{{value_json['%s'].%s}}\"," + "\"dev_cla\":\"power\""; + +const char HASS_DISCOVER_SENSOR_WATT[] PROGMEM = + ",\"unit_of_meas\":\"W\"," + "\"val_tpl\":\"{{value_json['%s'].%s}}\"," + "\"dev_cla\":\"power\""; +const char HASS_DISCOVER_SENSOR_VOLTAGE[] PROGMEM = + ",\"unit_of_meas\":\"V\"," + "\"val_tpl\":\"{{value_json['%s'].%s}}\"," + "\"dev_cla\":\"power\""; +const char HASS_DISCOVER_SENSOR_AMPERE[] PROGMEM = + ",\"unit_of_meas\":\"A\"," + "\"val_tpl\":\"{{value_json['%s'].%s}}\"," + "\"dev_cla\":\"power\""; + + +const char HASS_DISCOVER_SENSOR_ILLUMINANCE[] PROGMEM = + ",\"unit_of_meas\":\"LX\"," + "\"val_tpl\":\"{{value_json['%s'].Illuminance}}\"," + "\"dev_cla\":\"illuminance\""; + +const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = + ",\"unit_of_meas\":\" \"," + "\"val_tpl\":\"{{value_json['%s'].%s}}\""; + +const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = + ",\"json_attributes_topic\":\"%s\"," + "\"unit_of_meas\":\" \"," + "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\""; + +const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = + ",\"uniq_id\":\"%s\"," + "\"device\":{\"identifiers\":[\"%06X\"]," + "\"connections\":[[\"mac\",\"%s\"]]," + "\"name\":\"%s\"," + "\"model\":\"%s\"," + "\"sw_version\":\"%s%s\"," + "\"manufacturer\":\"Tasmota\"}"; + +const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = + ",\"uniq_id\":\"%s\"," + "\"device\":{\"identifiers\":[\"%06X\"]," + "\"connections\":[[\"mac\",\"%s\"]]}"; + +const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM = + ",\"~\":\"%s\""; + +uint8_t hass_init_step = 0; +uint8_t hass_mode = 0; +int hass_tele_period = 0; + +static void FindPrefix(char* s1, char* s2, char* out) +{ + int prefixlen = 0; + + while (s1[prefixlen] != '\0' && s2[prefixlen] != '\0' && s1[prefixlen] == s2[prefixlen]) { + prefixlen++; + } + strlcpy(out, s1, prefixlen+1); +} + +static void Shorten(char** s, char *prefix) +{ + size_t len = strlen(*s); + size_t prefixlen = strlen(prefix); + if (len > prefixlen && prefixlen != 0 && !strncmp(*s, prefix, prefixlen)) { + *s += prefixlen-1; + *s[0] = '~'; + } +} + +void TryResponseAppend_P(const char *format, ... ) +{ + va_list args; + va_start(args, format); + char dummy[2]; + int dlen = vsnprintf_P(dummy, 1, format, args); + + int mlen = strlen(mqtt_data); + int slen = sizeof(mqtt_data) -1 -mlen; + if (dlen >= slen) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: MQTT discovery failed due to too long topic or friendly name. " + "Please shorten topic and friendly name. Failed to format(%u/%u):"), dlen, slen); + va_start(args, format); + vsnprintf_P(log_data, sizeof(log_data), format, args); + AddLog(LOG_LEVEL_ERROR); + } else { + va_start(args, format); + vsnprintf_P(mqtt_data + mlen, slen, format, args); + } + va_end(args); +} + +void HAssAnnounceRelayLight(void) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char stemp3[TOPSZ]; + char unique_id[30]; + bool is_light = false; + bool is_topic_light = false; + + for (uint32_t i = 1; i <= MAX_RELAYS; i++) { + is_light = ((i == devices_present) && (light_type)); + is_topic_light = Settings.flag.hass_light || is_light; + + mqtt_data[0] = '\0'; + + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "RL" : "LI", i); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), + (is_topic_light) ? "switch" : "light", unique_id); + MqttPublish(stopic, true); + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "LI" : "RL", i); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), + (is_topic_light) ? "light" : "switch", unique_id); + + if (Settings.flag.hass_discovery && (i <= devices_present)) { + char name[33+2]; + char value_template[33]; + char prefix[TOPSZ]; + char *command_topic = stemp1; + char *state_topic = stemp2; + char *availability_topic = stemp3; + + if (i > MAX_FRIENDLYNAMES) { + snprintf_P(name, sizeof(name), PSTR("%s %d"), Settings.friendlyname[0], i); + } else { + snprintf_P(name, sizeof(name), Settings.friendlyname[i -1]); + } + GetPowerDevice(value_template, i, sizeof(value_template), Settings.flag.device_index_enable); + GetTopic_P(command_topic, CMND, mqtt_topic, value_template); + + GetTopic_P(state_topic, TELE, mqtt_topic, D_RSLT_STATE); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + FindPrefix(command_topic, state_topic, prefix); + Shorten(&command_topic, prefix); + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + + Response_P(HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); + TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); + +#ifdef USE_LIGHT + if (is_light) { + char *brightness_command_topic = stemp1; + + GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); + Shorten(&brightness_command_topic, prefix); + strncpy_P(stemp3, Settings.flag.not_power_linked?PSTR("last"):PSTR("brightness"), sizeof(stemp3)); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_DIMMER, brightness_command_topic, state_topic, stemp3); + + if (Light.subtype >= LST_RGB) { + char *rgb_command_topic = stemp1; + + GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); + Shorten(&rgb_command_topic, prefix); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_COLOR, rgb_command_topic, state_topic); + + char *effect_command_topic = stemp1; + GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); + Shorten(&effect_command_topic, prefix); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_SCHEME, effect_command_topic, state_topic); + + } + if (LST_RGBW == Light.subtype) { + char *white_temp_command_topic = stemp1; + + GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); + Shorten(&white_temp_command_topic, prefix); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_WHITE, white_temp_command_topic, state_topic); + } + if ((LST_COLDWARM == Light.subtype) || (LST_RGBWC == Light.subtype)) { + char *color_temp_command_topic = stemp1; + + GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); + Shorten(&color_temp_command_topic, prefix); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_CT, color_temp_command_topic, state_topic); + } + } +#endif + TryResponseAppend_P(PSTR("}")); + } + MqttPublish(stopic, true); + } +} + +void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint8_t key, uint8_t toggle) +{ + + + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + + mqtt_data[0] = '\0'; + + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), key?"SW":"BTN", device+1); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); + + if (Settings.flag.hass_discovery && present) { + char name[33+6]; + char value_template[33]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + + if (device+1 > MAX_FRIENDLYNAMES) { + snprintf_P(name, sizeof(name), PSTR("%s %s %d"), Settings.friendlyname[0], key?"SW":"BTN", device+1); + } else { + snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[device], key?"SW":"BTN"); + } + GetPowerDevice(value_template, device+1, sizeof(value_template), + key + Settings.flag.device_index_enable); + GetTopic_P(state_topic, CMND, topic, value_template); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + FindPrefix(state_topic, availability_topic, prefix); + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + Response_P(HASS_DISCOVER_BUTTON_SWITCH, name, state_topic, Settings.state_text[toggle?2:1], availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); + if (strlen(prefix) > 0 ) TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); + if (toggle) TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_TOGGLE); + else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, Settings.state_text[0]); + + TryResponseAppend_P(PSTR("}")); + } + MqttPublish(stopic, true); +} + +void HAssAnnounceSwitches(void) +{ + char sw_topic[sizeof(Settings.switch_topic)]; + + + char *tmp = Settings.switch_topic; + Format(sw_topic, tmp, sizeof(sw_topic)); + if ((strlen(sw_topic) != 0) && strcmp(sw_topic, "0")) { + for (uint32_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) { + uint8_t switch_present = 0; + uint8_t toggle = 1; + + if (pin[GPIO_SWT1 + switch_index] < 99) { + switch_present = 1; + } + + + if (Settings.switchmode[switch_index] == FOLLOW || Settings.switchmode[switch_index] == FOLLOW_INV || + Settings.flag3.button_switch_force_local || + !strcmp(mqtt_topic, sw_topic) || !strcmp(Settings.mqtt_grptopic, sw_topic)) + { + toggle = 0; + } + + HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 1, toggle); + } + } +} + +void HAssAnnounceButtons(void) +{ + char key_topic[sizeof(Settings.button_topic)]; + + + char *tmp = Settings.button_topic; + Format(key_topic, tmp, sizeof(key_topic)); + if ((strlen(key_topic) != 0) && strcmp(key_topic, "0")) { + for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { + uint8_t button_present = 0; + uint8_t toggle = 1; + + if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { + button_present = 1; + } else { + if (pin[GPIO_KEY1 + button_index] < 99) { + button_present = 1; + } + } + + + if (Settings.flag3.button_switch_force_local || + !strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) + { + toggle = 0; + } + + HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 0, toggle); + } + } +} + +void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + + + mqtt_data[0] = '\0'; + + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP.getChipId(), sensorname, subsensortype); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); + + if (Settings.flag.hass_discovery) { + char name[33+42]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + + snprintf_P(name, sizeof(name), PSTR("%s %s %s"), Settings.friendlyname[0], sensorname, subsensortype); + GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + FindPrefix(state_topic, availability_topic, prefix); + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + + Response_P(HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); + TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); + if (!strcmp_P(subsensortype, PSTR(D_JSON_TEMPERATURE))) { + TryResponseAppend_P(HASS_DISCOVER_SENSOR_TEMP, TempUnit(), sensorname); + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { + TryResponseAppend_P(HASS_DISCOVER_SENSOR_HUM, sensorname); + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE))) { + TryResponseAppend_P(HASS_DISCOVER_SENSOR_PRESS, PressureUnit().c_str(), sensorname); + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL)) + || !strcmp_P(subsensortype, PSTR(D_JSON_TODAY)) + || !strcmp_P(subsensortype, PSTR(D_JSON_YESTERDAY))){ + TryResponseAppend_P(HASS_DISCOVER_SENSOR_KWH, sensorname, subsensortype); + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_POWERUSAGE))){ + TryResponseAppend_P(HASS_DISCOVER_SENSOR_WATT, sensorname, subsensortype); + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_VOLTAGE))){ + TryResponseAppend_P(HASS_DISCOVER_SENSOR_VOLTAGE, sensorname, subsensortype); + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_CURRENT))){ + TryResponseAppend_P(HASS_DISCOVER_SENSOR_AMPERE, sensorname, subsensortype); + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_ILLUMINANCE))){ + TryResponseAppend_P(HASS_DISCOVER_SENSOR_ILLUMINANCE, sensorname, subsensortype); + } + else { + TryResponseAppend_P(HASS_DISCOVER_SENSOR_ANY, sensorname, subsensortype); + } + TryResponseAppend_P(PSTR("}")); + } + MqttPublish(stopic, true); +} + +void HAssAnnounceSensors(void) +{ + uint8_t hass_xsns_index = 0; + + do { + mqtt_data[0] = '\0'; + int tele_period_save = tele_period; + tele_period = 2; + XsnsNextCall(FUNC_JSON_APPEND, hass_xsns_index); + tele_period = tele_period_save; + + char sensordata[256]; + strlcpy(sensordata, mqtt_data, sizeof(sensordata)); + + if (strlen(sensordata)) { + sensordata[0] = '{'; + snprintf_P(sensordata, sizeof(sensordata), PSTR("%s}"), sensordata); + + + + + + StaticJsonBuffer<500> jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(sensordata); + if (!root.success()) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: failed to parse '%s'"), sensordata); + continue; + } + for (auto sensor : root) { + const char* sensorname = sensor.key; + JsonObject& sensors = sensor.value.as(); + if (!sensors.success()) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: failed to parse '%s'"), sensordata); + continue; + } + for (auto subsensor : sensors) { + HAssAnnounceSensor(sensorname, subsensor.key); + } + } + } + yield(); + } while (hass_xsns_index != 0); +} + +void HAssAnnounceStatusSensor(void) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + + + mqtt_data[0] = '\0'; + + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_status"), ESP.getChipId()); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); + + if (Settings.flag.hass_discovery) { + char name[33+7]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + + snprintf_P(name, sizeof(name), PSTR("%s status"), Settings.friendlyname[0]); + GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + FindPrefix(state_topic, availability_topic, prefix); + Shorten(&state_topic, prefix); + Shorten(&availability_topic, prefix); + + Response_P(HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(), WiFi.macAddress().c_str(), + Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image); + TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); + TryResponseAppend_P(PSTR("}")); + } + MqttPublish(stopic, true); +} + +void HAssPublishStatus(void) +{ + Response_P(PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"," + "\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," + "\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"," + "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d," + "\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_CMND_IPADDRESS "\":\"%s\"," + "\"" D_JSON_RSSI "\":\"%d\",\"LoadAvg\":%lu}"), + my_version, my_image, GetBuildDateAndTime().c_str(), ESP.getSdkVersion(), ModuleName().c_str(), + GetResetReason().c_str(), GetUptime().c_str(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), + Settings.bootcount, Settings.save_flag, WiFi.localIP().toString().c_str(), + WifiGetRssiAsQuality(WiFi.RSSI()), loop_load_avg); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE)); +} + +void HAssDiscovery(void) +{ + + if (Settings.flag.hass_discovery) { + Settings.flag.mqtt_response = 0; + Settings.flag.decimal_text = 1; + Settings.flag3.hass_tele_on_power = 1; + + if (strcmp_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"))) { + strncpy_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"), sizeof(Settings.mqtt_fulltopic)); + restart_flag = 2; + return; + } + } + + if (Settings.flag.hass_discovery || (1 == hass_mode)) { + + HAssAnnounceRelayLight(); + + + HAssAnnounceButtons(); + + + HAssAnnounceSwitches(); + + + HAssAnnounceSensors(); + + + HAssAnnounceStatusSensor(); + } +} + +void HAssDiscover(void) +{ + hass_mode = 1; + hass_init_step = 1; +} + + + + + +bool Xdrv12(uint8_t function) +{ + bool result = false; + + if (Settings.flag.mqtt_enabled) { + switch (function) { + case FUNC_MQTT_INIT: + hass_mode = 0; + hass_init_step = 2; + break; + case FUNC_EVERY_SECOND: + if (hass_init_step) { + hass_init_step--; + if (!hass_init_step) { + HAssDiscovery(); + } + } else if (Settings.flag.hass_discovery && Settings.tele_period) { + hass_tele_period++; + if (hass_tele_period >= Settings.tele_period) { + hass_tele_period = 0; + + mqtt_data[0] = '\0'; + HAssPublishStatus(); + } + } + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_13_display.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_13_display.ino" +#if defined(USE_I2C) || defined(USE_SPI) +#ifdef USE_DISPLAY + +#define XDRV_13 13 + +#include +#include + +Renderer *renderer; + +enum ColorType { COLOR_BW, COLOR_COLOR }; + +#ifndef MAXBUTTONS +#define MAXBUTTONS 16 +#endif + +#ifdef USE_TOUCH_BUTTONS +VButton *buttons[MAXBUTTONS]; +#endif + + + +uint16_t fg_color = 1; +uint16_t bg_color = 0; +uint8_t color_type = COLOR_BW; +uint8_t auto_draw=1; + +const uint8_t DISPLAY_MAX_DRIVERS = 16; +const uint8_t DISPLAY_MAX_COLS = 44; +const uint8_t DISPLAY_MAX_ROWS = 32; + +const uint8_t DISPLAY_LOG_ROWS = 32; + +#define D_PRFX_DISPLAY "Display" +#define D_CMND_DISP_ADDRESS "Address" +#define D_CMND_DISP_COLS "Cols" +#define D_CMND_DISP_DIMMER "Dimmer" +#define D_CMND_DISP_MODE "Mode" +#define D_CMND_DISP_MODEL "Model" +#define D_CMND_DISP_REFRESH "Refresh" +#define D_CMND_DISP_ROWS "Rows" +#define D_CMND_DISP_SIZE "Size" +#define D_CMND_DISP_FONT "Font" +#define D_CMND_DISP_ROTATE "Rotate" +#define D_CMND_DISP_TEXT "Text" +#define D_CMND_DISP_WIDTH "Width" +#define D_CMND_DISP_HEIGHT "Height" + +enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_EVERY_50_MSECOND, FUNC_DISPLAY_EVERY_SECOND, + FUNC_DISPLAY_MODEL, FUNC_DISPLAY_MODE, FUNC_DISPLAY_POWER, + FUNC_DISPLAY_CLEAR, FUNC_DISPLAY_DRAW_FRAME, + FUNC_DISPLAY_DRAW_HLINE, FUNC_DISPLAY_DRAW_VLINE, FUNC_DISPLAY_DRAW_LINE, + FUNC_DISPLAY_DRAW_CIRCLE, FUNC_DISPLAY_FILL_CIRCLE, + FUNC_DISPLAY_DRAW_RECTANGLE, FUNC_DISPLAY_FILL_RECTANGLE, + FUNC_DISPLAY_TEXT_SIZE, FUNC_DISPLAY_FONT_SIZE, FUNC_DISPLAY_ROTATION, FUNC_DISPLAY_DRAW_STRING, FUNC_DISPLAY_ONOFF }; + +enum DisplayInitModes { DISPLAY_INIT_MODE, DISPLAY_INIT_PARTIAL, DISPLAY_INIT_FULL }; + +const char kDisplayCommands[] PROGMEM = D_PRFX_DISPLAY "|" + "|" D_CMND_DISP_MODEL "|" D_CMND_DISP_WIDTH "|" D_CMND_DISP_HEIGHT "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|" + D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|" D_CMND_DISP_SIZE "|" D_CMND_DISP_FONT "|" + D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS ; + +void (* const DisplayCommand[])(void) PROGMEM = { + &CmndDisplay, &CmndDisplayModel, &CmndDisplayWidth, &CmndDisplayHeight, &CmndDisplayMode, &CmndDisplayRefresh, + &CmndDisplayDimmer, &CmndDisplayColumns, &CmndDisplayRows, &CmndDisplaySize, &CmndDisplayFont, + &CmndDisplayRotate, &CmndDisplayText, &CmndDisplayAddress }; + +char *dsp_str; + +uint16_t dsp_x; +uint16_t dsp_y; +uint16_t dsp_x2; +uint16_t dsp_y2; +uint16_t dsp_rad; +uint16_t dsp_color; +int16_t dsp_len; +int16_t disp_xpos = 0; +int16_t disp_ypos = 0; + +uint8_t disp_power = 0; +uint8_t disp_device = 0; +uint8_t disp_refresh = 1; +uint8_t disp_autodraw = 1; +uint8_t dsp_init; +uint8_t dsp_font; +uint8_t dsp_flag; +uint8_t dsp_on; + +#ifdef USE_DISPLAY_MODES1TO5 + +char **disp_log_buffer; +char **disp_screen_buffer; +char disp_temp[2]; + +uint8_t disp_log_buffer_cols = 0; +uint8_t disp_log_buffer_idx = 0; +uint8_t disp_log_buffer_ptr = 0; +uint8_t disp_screen_buffer_cols = 0; +uint8_t disp_screen_buffer_rows = 0; +bool disp_subscribed = false; + +#endif + + + +void DisplayInit(uint8_t mode) +{ + if (renderer) { + renderer->DisplayInit(mode,Settings.display_size,Settings.display_rotate,Settings.display_font); + } + else { + dsp_init = mode; + XdspCall(FUNC_DISPLAY_INIT); + } +} + +void DisplayClear(void) +{ + XdspCall(FUNC_DISPLAY_CLEAR); +} + +void DisplayDrawHLine(uint16_t x, uint16_t y, int16_t len, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_len = len; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_HLINE); +} + +void DisplayDrawVLine(uint16_t x, uint16_t y, int16_t len, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_len = len; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_VLINE); +} + +void DisplayDrawLine(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_x2 = x2; + dsp_y2 = y2; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_LINE); +} + +void DisplayDrawCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_rad = rad; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_CIRCLE); +} + +void DisplayDrawFilledCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_rad = rad; + dsp_color = color; + XdspCall(FUNC_DISPLAY_FILL_CIRCLE); +} + +void DisplayDrawRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_x2 = x2; + dsp_y2 = y2; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_RECTANGLE); +} + +void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_x2 = x2; + dsp_y2 = y2; + dsp_color = color; + XdspCall(FUNC_DISPLAY_FILL_RECTANGLE); +} + +void DisplayDrawFrame(void) +{ + XdspCall(FUNC_DISPLAY_DRAW_FRAME); +} + +void DisplaySetSize(uint8_t size) +{ + Settings.display_size = size &3; + XdspCall(FUNC_DISPLAY_TEXT_SIZE); +} + +void DisplaySetFont(uint8_t font) +{ + Settings.display_font = font &3; + XdspCall(FUNC_DISPLAY_FONT_SIZE); +} + +void DisplaySetRotation(uint8_t rotation) +{ + Settings.display_rotate = rotation &3; + XdspCall(FUNC_DISPLAY_ROTATION); +} + +void DisplayDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + dsp_x = x; + dsp_y = y; + dsp_str = str; + dsp_color = color; + dsp_flag = flag; + XdspCall(FUNC_DISPLAY_DRAW_STRING); +} + +void DisplayOnOff(uint8_t on) +{ + dsp_on = on; + XdspCall(FUNC_DISPLAY_ONOFF); +} + + + + +uint8_t fatoiv(char *cp,float *res) { + uint8_t index=0; + *res=CharToFloat(cp); + while (*cp) { + if ((*cp>='0' && *cp<='9') || (*cp=='-') || (*cp=='.')) { + cp++; + index++; + } else { + break; + } + } + return index; +} + + +uint8_t atoiv(char *cp, int16_t *res) +{ + uint8_t index = 0; + *res = atoi(cp); + while (*cp) { + if ((*cp>='0' && *cp<='9') || (*cp=='-')) { + cp++; + index++; + } else { + break; + } + } + return index; +} + + +uint8_t atoiV(char *cp, uint16_t *res) +{ + uint8_t index = 0; + *res = atoi(cp); + while (*cp) { + if (*cp>='0' && *cp<='9') { + cp++; + index++; + } else { + break; + } + } + return index; +} + + +void alignright(char *string) { + uint16_t slen=strlen(string); + uint16_t len=slen; + while (len) { + + if (string[len-1]!=' ') { + break; + } + len--; + } + uint16_t diff=slen-len; + if (diff>0) { + + memmove(&string[diff],string,len); + memset(string,' ',diff); + } +} + +char *get_string(char *buff,uint8_t len,char *cp) { +uint8_t index=0; + while (*cp!=':') { + buff[index]=*cp++; + index++; + if (index>=len) break; + } + buff[index]=0; + cp++; + return cp; +} + +#define ESCAPE_CHAR '~' + + +void decode_te(char *line) { + char sbuf[3],*cp; + while (*line) { + if (*line==ESCAPE_CHAR) { + cp=line+1; + if (*cp!=0 && *cp==ESCAPE_CHAR) { + + memmove(cp,cp+1,strlen(cp)); + } else { + + if (strlen(cp)<2) { + + return; + } + + sbuf[0]=*(cp); + sbuf[1]=*(cp+1); + sbuf[2]=0; + *line=strtol(sbuf,0,16); + + memmove(cp,cp+2,strlen(cp)-1); + } + } + line++; + } +} + + + +#define DISPLAY_BUFFER_COLS 128 + +void DisplayText(void) +{ + uint8_t lpos; + uint8_t escape = 0; + uint8_t var; + int16_t lin = 0; + int16_t col = 0; + int16_t fill = 0; + int16_t temp; + int16_t temp1; + float ftemp; + + char linebuf[DISPLAY_BUFFER_COLS]; + char *dp = linebuf; + char *cp = XdrvMailbox.data; + + memset(linebuf, ' ', sizeof(linebuf)); + linebuf[sizeof(linebuf)-1] = 0; + *dp = 0; + + while (*cp) { + if (!escape) { + + if (*cp == '[') { + escape = 1; + cp++; + + if ((uint32_t)dp - (uint32_t)linebuf) { + if (!fill) { *dp = 0; } + if (col > 0 && lin > 0) { + + if (!renderer) DisplayDrawStringAt(col, lin, linebuf, fg_color, 1); + else renderer->DrawStringAt(col, lin, linebuf, fg_color, 1); + } else { + + if (!renderer) DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); + else renderer->DrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); + } + memset(linebuf, ' ', sizeof(linebuf)); + linebuf[sizeof(linebuf)-1] = 0; + dp = linebuf; + } + } else { + + if (dp < (linebuf + DISPLAY_BUFFER_COLS)) { *dp++ = *cp++; } + } + } else { + + if (*cp == ']') { + escape = 0; + cp++; + } else { + + switch (*cp++) { + case 'z': + + if (!renderer) DisplayClear(); + else renderer->fillScreen(bg_color); + disp_xpos = 0; + disp_ypos = 0; + col = 0; + lin = 0; + break; + case 'i': + + DisplayInit(DISPLAY_INIT_PARTIAL); + break; + case 'I': + + DisplayInit(DISPLAY_INIT_FULL); + break; + case 'o': + if (!renderer) { + DisplayOnOff(0); + } else { + renderer->DisplayOnff(0); + } + break; + case 'O': + if (!renderer) { + DisplayOnOff(1); + } else { + renderer->DisplayOnff(1); + } + break; + case 'x': + + var = atoiv(cp, &disp_xpos); + cp += var; + break; + case 'y': + + var = atoiv(cp, &disp_ypos); + cp += var; + break; + case 'l': + + var = atoiv(cp, &lin); + cp += var; + + break; + case 'c': + + var = atoiv(cp, &col); + cp += var; + + break; + case 'C': + + if (*cp=='i') { + + cp++; + var = atoiv(cp, &temp); + if (renderer) ftemp=renderer->GetColorFromIndex(temp); + } else { + + var = fatoiv(cp,&ftemp); + } + fg_color=ftemp; + cp += var; + if (renderer) renderer->setTextColor(fg_color,bg_color); + break; + case 'B': + + if (*cp=='i') { + + cp++; + var = atoiv(cp, &temp); + if (renderer) ftemp=renderer->GetColorFromIndex(temp); + } else { + var = fatoiv(cp,&ftemp); + } + bg_color=ftemp; + cp += var; + if (renderer) renderer->setTextColor(fg_color,bg_color); + break; + case 'p': + + var = atoiv(cp, &fill); + cp += var; + linebuf[fill] = 0; + break; +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) + case 'P': + { char *ep=strchr(cp,':'); + if (ep) { + *ep=0; + ep++; + Draw_RGB_Bitmap(cp,disp_xpos,disp_ypos); + cp=ep; + } + } + break; +#endif + case 'h': + + var = atoiv(cp, &temp); + cp += var; + if (temp < 0) { + if (renderer) renderer->writeFastHLine(disp_xpos + temp, disp_ypos, -temp, fg_color); + else DisplayDrawHLine(disp_xpos + temp, disp_ypos, -temp, fg_color); + } else { + if (renderer) renderer->writeFastHLine(disp_xpos, disp_ypos, temp, fg_color); + else DisplayDrawHLine(disp_xpos, disp_ypos, temp, fg_color); + } + disp_xpos += temp; + break; + case 'v': + + var = atoiv(cp, &temp); + cp += var; + if (temp < 0) { + if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos + temp, -temp, fg_color); + else DisplayDrawVLine(disp_xpos, disp_ypos + temp, -temp, fg_color); + } else { + if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos, temp, fg_color); + else DisplayDrawVLine(disp_xpos, disp_ypos, temp, fg_color); + } + disp_ypos += temp; + break; + case 'L': + + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + if (renderer) renderer->writeLine(disp_xpos, disp_ypos, temp, temp1, fg_color); + else DisplayDrawLine(disp_xpos, disp_ypos, temp, temp1, fg_color); + disp_xpos += temp; + disp_ypos += temp1; + break; + case 'k': + + var = atoiv(cp, &temp); + cp += var; + if (renderer) renderer->drawCircle(disp_xpos, disp_ypos, temp, fg_color); + else DisplayDrawCircle(disp_xpos, disp_ypos, temp, fg_color); + break; + case 'K': + + var = atoiv(cp, &temp); + cp += var; + if (renderer) renderer->fillCircle(disp_xpos, disp_ypos, temp, fg_color); + else DisplayDrawFilledCircle(disp_xpos, disp_ypos, temp, fg_color); + break; + case 'r': + + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + if (renderer) renderer->drawRect(disp_xpos, disp_ypos, temp, temp1, fg_color); + else DisplayDrawRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color); + break; + case 'R': + + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + if (renderer) renderer->fillRect(disp_xpos, disp_ypos, temp, temp1, fg_color); + else DisplayDrawFilledRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color); + break; + case 'u': + + { int16_t rad; + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + cp++; + var = atoiv(cp, &rad); + cp += var; + if (renderer) renderer->drawRoundRect(disp_xpos, disp_ypos, temp, temp1, rad, fg_color); + + } + break; + case 'U': + + { int16_t rad; + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + cp++; + var = atoiv(cp, &rad); + cp += var; + if (renderer) renderer->fillRoundRect(disp_xpos, disp_ypos, temp, temp1, rad, fg_color); + + } + break; + + case 't': + if (*cp=='S') { + cp++; + if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { + snprintf_P(dp, 9, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + dp += 8; + } + } else { + if (dp < (linebuf + DISPLAY_BUFFER_COLS) -5) { + snprintf_P(dp, 6, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute); + dp += 5; + } + } + break; + case 'T': + if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { + snprintf_P(dp, 9, PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year%2000); + dp += 8; + } + break; + case 'd': + + if (renderer) renderer->Updateframe(); + else DisplayDrawFrame(); + break; + case 'D': + + auto_draw=*cp&3; + if (renderer) renderer->setDrawMode(auto_draw>>1); + cp += 1; + break; + case 's': + + if (renderer) renderer->setTextSize(*cp&7); + else DisplaySetSize(*cp&3); + cp += 1; + break; + case 'f': + + if (renderer) renderer->setTextFont(*cp&7); + else DisplaySetFont(*cp&7); + cp += 1; + break; + case 'a': + + if (renderer) renderer->setRotation(*cp&3); + else DisplaySetRotation(*cp&3); + cp+=1; + break; + +#ifdef USE_GRAPH + case 'G': + + if (*cp=='d') { + cp++; + var=atoiv(cp,&temp); + cp+=var; + cp++; + var=atoiv(cp,&temp1); + cp+=var; + RedrawGraph(temp,temp1); + break; + } +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) + if (*cp=='s') { + cp++; + var=atoiv(cp,&temp); + cp+=var; + cp++; + + char bbuff[128]; + cp=get_string(bbuff,sizeof(bbuff),cp); + Save_graph(temp,bbuff); + break; + } + if (*cp=='r') { + cp++; + var=atoiv(cp,&temp); + cp+=var; + cp++; + + char bbuff[128]; + cp=get_string(bbuff,sizeof(bbuff),cp); + Restore_graph(temp,bbuff); + break; + } +#endif + { int16_t num,gxp,gyp,gxs,gys,dec,icol; + float ymin,ymax; + var=atoiv(cp,&num); + cp+=var; + cp++; + var=atoiv(cp,&gxp); + cp+=var; + cp++; + var=atoiv(cp,&gyp); + cp+=var; + cp++; + var=atoiv(cp,&gxs); + cp+=var; + cp++; + var=atoiv(cp,&gys); + cp+=var; + cp++; + var=atoiv(cp,&dec); + cp+=var; + cp++; + var=fatoiv(cp,&ymin); + cp+=var; + cp++; + var=fatoiv(cp,&ymax); + cp+=var; + if (color_type==COLOR_COLOR) { + + cp++; + var=atoiv(cp,&icol); + cp+=var; + } else { + icol=0; + } + DefineGraph(num,gxp,gyp,gxs,gys,dec,ymin,ymax,icol); + } + break; + case 'g': + { float temp; + int16_t num; + var=atoiv(cp,&num); + cp+=var; + cp++; + var=fatoiv(cp,&temp); + cp+=var; + AddValue(num,temp); + } + break; +#endif + +#ifdef USE_AWATCH + case 'w': + var = atoiv(cp, &temp); + cp += var; + DrawAClock(temp); + break; +#endif + +#ifdef USE_TOUCH_BUTTONS + case 'b': + { int16_t num,gxp,gyp,gxs,gys,outline,fill,textcolor,textsize; + var=atoiv(cp,&num); + cp+=var; + cp++; + uint8_t bflags=num>>8; + num=num%MAXBUTTONS; + var=atoiv(cp,&gxp); + cp+=var; + cp++; + var=atoiv(cp,&gyp); + cp+=var; + cp++; + var=atoiv(cp,&gxs); + cp+=var; + cp++; + var=atoiv(cp,&gys); + cp+=var; + cp++; + var=atoiv(cp,&outline); + cp+=var; + cp++; + var=atoiv(cp,&fill); + cp+=var; + cp++; + var=atoiv(cp,&textcolor); + cp+=var; + cp++; + var=atoiv(cp,&textsize); + cp+=var; + cp++; + + char bbuff[32]; + cp=get_string(bbuff,sizeof(bbuff),cp); + + if (buttons[num]) { + delete buttons[num]; + } + if (renderer) { + buttons[num]= new VButton(); + if (buttons[num]) { + buttons[num]->vpower=bflags; + buttons[num]->initButtonUL(renderer,gxp,gyp,gxs,gys,renderer->GetColorFromIndex(outline),\ + renderer->GetColorFromIndex(fill),renderer->GetColorFromIndex(textcolor),bbuff,textsize); + if (!bflags) { + + buttons[num]->xdrawButton(bitRead(power,num)); + } else { + + buttons[num]->vpower&=0x7f; + buttons[num]->xdrawButton(buttons[num]->vpower&0x80); + } + } + } + } + break; +#endif + default: + + Response_P(PSTR("Unknown Escape")); + goto exit; + break; + } + } + } + } + exit: + + decode_te(linebuf); + if ((uint32_t)dp - (uint32_t)linebuf) { + if (!fill) *dp = 0; + else linebuf[abs(fill)] = 0; + if (fill<0) { + + alignright(linebuf); + } + if (col > 0 && lin > 0) { + + if (!renderer) DisplayDrawStringAt(col, lin, linebuf, fg_color, 1); + else renderer->DrawStringAt(col, lin, linebuf, fg_color, 1); + } else { + + if (!renderer) DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); + else renderer->DrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); + } + } + + if (auto_draw&1) { + if (renderer) renderer->Updateframe(); + else DisplayDrawFrame(); + } +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void DisplayClearScreenBuffer(void) +{ + if (disp_screen_buffer_cols) { + for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { + memset(disp_screen_buffer[i], 0, disp_screen_buffer_cols); + } + } +} + +void DisplayFreeScreenBuffer(void) +{ + if (disp_screen_buffer != nullptr) { + for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { + if (disp_screen_buffer[i] != nullptr) { free(disp_screen_buffer[i]); } + } + free(disp_screen_buffer); + disp_screen_buffer_cols = 0; + disp_screen_buffer_rows = 0; + } +} + +void DisplayAllocScreenBuffer(void) +{ + if (!disp_screen_buffer_cols) { + disp_screen_buffer_rows = Settings.display_rows; + disp_screen_buffer = (char**)malloc(sizeof(*disp_screen_buffer) * disp_screen_buffer_rows); + if (disp_screen_buffer != nullptr) { + for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { + disp_screen_buffer[i] = (char*)malloc(sizeof(*disp_screen_buffer[i]) * (Settings.display_cols[0] +1)); + if (disp_screen_buffer[i] == nullptr) { + DisplayFreeScreenBuffer(); + break; + } + } + } + if (disp_screen_buffer != nullptr) { + disp_screen_buffer_cols = Settings.display_cols[0] +1; + DisplayClearScreenBuffer(); + } + } +} + +void DisplayReAllocScreenBuffer(void) +{ + DisplayFreeScreenBuffer(); + DisplayAllocScreenBuffer(); +} + +void DisplayFillScreen(uint32_t line) +{ + uint32_t len = disp_screen_buffer_cols - strlen(disp_screen_buffer[line]); + if (len) { + memset(disp_screen_buffer[line] + strlen(disp_screen_buffer[line]), 0x20, len); + disp_screen_buffer[line][disp_screen_buffer_cols -1] = 0; + } +} + + + +void DisplayClearLogBuffer(void) +{ + if (disp_log_buffer_cols) { + for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { + memset(disp_log_buffer[i], 0, disp_log_buffer_cols); + } + } +} + +void DisplayFreeLogBuffer(void) +{ + if (disp_log_buffer != nullptr) { + for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { + if (disp_log_buffer[i] != nullptr) { free(disp_log_buffer[i]); } + } + free(disp_log_buffer); + disp_log_buffer_cols = 0; + } +} + +void DisplayAllocLogBuffer(void) +{ + if (!disp_log_buffer_cols) { + disp_log_buffer = (char**)malloc(sizeof(*disp_log_buffer) * DISPLAY_LOG_ROWS); + if (disp_log_buffer != nullptr) { + for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { + disp_log_buffer[i] = (char*)malloc(sizeof(*disp_log_buffer[i]) * (Settings.display_cols[0] +1)); + if (disp_log_buffer[i] == nullptr) { + DisplayFreeLogBuffer(); + break; + } + } + } + if (disp_log_buffer != nullptr) { + disp_log_buffer_cols = Settings.display_cols[0] +1; + DisplayClearLogBuffer(); + } + } +} + +void DisplayReAllocLogBuffer(void) +{ + DisplayFreeLogBuffer(); + DisplayAllocLogBuffer(); +} + +void DisplayLogBufferAdd(char* txt) +{ + if (disp_log_buffer_cols) { + strlcpy(disp_log_buffer[disp_log_buffer_idx], txt, disp_log_buffer_cols); + disp_log_buffer_idx++; + if (DISPLAY_LOG_ROWS == disp_log_buffer_idx) { disp_log_buffer_idx = 0; } + } +} + +char* DisplayLogBuffer(char temp_code) +{ + char* result = nullptr; + if (disp_log_buffer_cols) { + if (disp_log_buffer_idx != disp_log_buffer_ptr) { + result = disp_log_buffer[disp_log_buffer_ptr]; + disp_log_buffer_ptr++; + if (DISPLAY_LOG_ROWS == disp_log_buffer_ptr) { disp_log_buffer_ptr = 0; } + + char *pch = strchr(result, '~'); + if (pch != nullptr) { result[pch - result] = temp_code; } + } + } + return result; +} + +void DisplayLogBufferInit(void) +{ + if (Settings.display_mode) { + disp_log_buffer_idx = 0; + disp_log_buffer_ptr = 0; + disp_refresh = Settings.display_refresh; + + snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit()); + + DisplayReAllocLogBuffer(); + + char buffer[40]; + snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s%s"), my_version, my_image); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings.display_mode); + DisplayLogBufferAdd(buffer); + + snprintf_P(buffer, sizeof(buffer), PSTR(D_CMND_HOSTNAME " %s"), my_hostname); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), Settings.sta_ssid[Settings.sta_active]); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), WiFi.macAddress().c_str()); + DisplayLogBufferAdd(buffer); + if (!global_state.wifi_down) { + snprintf_P(buffer, sizeof(buffer), PSTR("IP %s"), WiFi.localIP().toString().c_str()); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_RSSI " %d%%"), WifiGetRssiAsQuality(WiFi.RSSI())); + DisplayLogBufferAdd(buffer); + } + } +} + + + + + +enum SensorQuantity { + JSON_TEMPERATURE, + JSON_HUMIDITY, JSON_LIGHT, JSON_NOISE, JSON_AIRQUALITY, + JSON_PRESSURE, JSON_PRESSUREATSEALEVEL, + JSON_ILLUMINANCE, + JSON_GAS, + JSON_YESTERDAY, JSON_TOTAL, JSON_TODAY, + JSON_PERIOD, + JSON_POWERFACTOR, JSON_COUNTER, JSON_ANALOG_INPUT, JSON_UV_LEVEL, + JSON_CURRENT, + JSON_VOLTAGE, + JSON_POWERUSAGE, + JSON_CO2, + JSON_FREQUENCY }; +const char kSensorQuantity[] PROGMEM = + D_JSON_TEMPERATURE "|" + D_JSON_HUMIDITY "|" D_JSON_LIGHT "|" D_JSON_NOISE "|" D_JSON_AIRQUALITY "|" + D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" + D_JSON_ILLUMINANCE "|" + D_JSON_GAS "|" + D_JSON_YESTERDAY "|" D_JSON_TOTAL "|" D_JSON_TODAY "|" + D_JSON_PERIOD "|" + D_JSON_POWERFACTOR "|" D_JSON_COUNTER "|" D_JSON_ANALOG_INPUT "|" D_JSON_UV_LEVEL "|" + D_JSON_CURRENT "|" + D_JSON_VOLTAGE "|" + D_JSON_POWERUSAGE "|" + D_JSON_CO2 "|" + D_JSON_FREQUENCY ; + +void DisplayJsonValue(const char* topic, const char* device, const char* mkey, const char* value) +{ + char quantity[TOPSZ]; + char buffer[Settings.display_cols[0] +1]; + char spaces[Settings.display_cols[0]]; + char source[Settings.display_cols[0] - Settings.display_cols[1]]; + char svalue[Settings.display_cols[1] +1]; + +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("DisplayJsonValue")); +#endif + + memset(spaces, 0x20, sizeof(spaces)); + spaces[sizeof(spaces) -1] = '\0'; + snprintf_P(source, sizeof(source), PSTR("%s%s%s%s"), topic, (strlen(topic))?"/":"", mkey, spaces); + + int quantity_code = GetCommandCode(quantity, sizeof(quantity), mkey, kSensorQuantity); + if ((-1 == quantity_code) || !strcmp_P(mkey, S_RSLT_POWER)) { + return; + } + if (JSON_TEMPERATURE == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s~%s"), value, disp_temp); + } + else if ((quantity_code >= JSON_HUMIDITY) && (quantity_code <= JSON_AIRQUALITY)) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s%%"), value); + } + else if ((quantity_code >= JSON_PRESSURE) && (quantity_code <= JSON_PRESSUREATSEALEVEL)) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PRESSURE), value); + } + else if (JSON_ILLUMINANCE == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_LUX), value); + } + else if (JSON_GAS == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOOHM), value); + } + else if ((quantity_code >= JSON_YESTERDAY) && (quantity_code <= JSON_TODAY)) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOWATTHOUR), value); + } + else if (JSON_PERIOD == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATTHOUR), value); + } + else if ((quantity_code >= JSON_POWERFACTOR) && (quantity_code <= JSON_UV_LEVEL)) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s"), value); + } + else if (JSON_CURRENT == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_AMPERE), value); + } + else if (JSON_VOLTAGE == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_VOLT), value); + } + else if (JSON_POWERUSAGE == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATT), value); + } + else if (JSON_CO2 == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PARTS_PER_MILLION), value); + } + else if (JSON_FREQUENCY == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_HERTZ), value); + } + snprintf_P(buffer, sizeof(buffer), PSTR("%s %s"), source, svalue); + + + + DisplayLogBufferAdd(buffer); +} + +void DisplayAnalyzeJson(char *topic, char *json) +{ +# 1133 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_13_display.ino" + const char *tempunit; + + + + String jsonStr = json; + + StaticJsonBuffer<1024> jsonBuf; + JsonObject &root = jsonBuf.parseObject(jsonStr); + if (root.success()) { + + tempunit = root[D_JSON_TEMPERATURE_UNIT]; + if (tempunit) { + snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%s"), tempunit); + + } + + for (JsonObject::iterator it = root.begin(); it != root.end(); ++it) { + JsonVariant value = it->value; + if (value.is()) { + JsonObject& Object2 = value; + for (JsonObject::iterator it2 = Object2.begin(); it2 != Object2.end(); ++it2) { + JsonVariant value2 = it2->value; + if (value2.is()) { + JsonObject& Object3 = value2; + for (JsonObject::iterator it3 = Object3.begin(); it3 != Object3.end(); ++it3) { + const char* value = it3->value; + if (value != nullptr) { + DisplayJsonValue(topic, it->key, it3->key, value); + } + } + } else { + const char* value = it2->value; + if (value != nullptr) { + DisplayJsonValue(topic, it->key, it2->key, value); + } + } + } + } else { + const char* value = it->value; + if (value != nullptr) { + DisplayJsonValue(topic, it->key, it->key, value); + } + } + } + } +} + +void DisplayMqttSubscribe(void) +{ + + + + + + + if (Settings.display_model && (Settings.display_mode &0x04)) { + + char stopic[TOPSZ]; + char ntopic[TOPSZ]; + + ntopic[0] = '\0'; + strlcpy(stopic, Settings.mqtt_fulltopic, sizeof(stopic)); + char *tp = strtok(stopic, "/"); + while (tp != nullptr) { + if (!strcmp_P(tp, MQTT_TOKEN_PREFIX)) { + break; + } + strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); + tp = strtok(nullptr, "/"); + } + strncat(ntopic, Settings.mqtt_prefix[2], sizeof(ntopic) - strlen(ntopic) -1); + strncat_P(ntopic, PSTR("/#"), sizeof(ntopic) - strlen(ntopic) -1); + MqttSubscribe(ntopic); + disp_subscribed = true; + } else { + disp_subscribed = false; + } +} + +bool DisplayMqttData(void) +{ + if (disp_subscribed) { + char stopic[TOPSZ]; + + snprintf_P(stopic, sizeof(stopic) , PSTR("%s/"), Settings.mqtt_prefix[2]); + char *tp = strstr(XdrvMailbox.topic, stopic); + if (tp) { + if (Settings.display_mode &0x04) { + tp = tp + strlen(stopic); + char *topic = strtok(tp, "/"); + DisplayAnalyzeJson(topic, XdrvMailbox.data); + } + return true; + } + } + return false; +} + +void DisplayLocalSensor(void) +{ + if ((Settings.display_mode &0x02) && (0 == tele_period)) { + char no_topic[1] = { 0 }; + + DisplayAnalyzeJson(no_topic, mqtt_data); + } +} + +#endif + + + + + +void DisplayInitDriver(void) +{ + XdspCall(FUNC_DISPLAY_INIT_DRIVER); + + if (renderer) { + renderer->setTextFont(Settings.display_font); + renderer->setTextSize(Settings.display_size); + } + + + + + if (Settings.display_model) { + devices_present++; + disp_device = devices_present; + +#ifndef USE_DISPLAY_MODES1TO5 + Settings.display_mode = 0; +#else + DisplayLogBufferInit(); +#endif + } +} + +void DisplaySetPower(void) +{ + disp_power = bitRead(XdrvMailbox.index, disp_device -1); + +AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DSP: Power %d"), disp_power); + + if (Settings.display_model) { + if (!renderer) { + XdspCall(FUNC_DISPLAY_POWER); + } else { + renderer->DisplayOnff(disp_power); + } + } +} + + + + + +void CmndDisplay(void) +{ + Response_P(PSTR("{\"" D_PRFX_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_WIDTH "\":%d,\"" D_CMND_DISP_HEIGHT "\":%d,\"" + D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" D_CMND_DISP_SIZE "\":%d,\"" D_CMND_DISP_FONT "\":%d,\"" + D_CMND_DISP_ROTATE "\":%d,\"" D_CMND_DISP_REFRESH "\":%d,\"" D_CMND_DISP_COLS "\":[%d,%d],\"" D_CMND_DISP_ROWS "\":%d}}"), + Settings.display_model, Settings.display_width, Settings.display_height, + Settings.display_mode, Settings.display_dimmer, Settings.display_size, Settings.display_font, + Settings.display_rotate, Settings.display_refresh, Settings.display_cols[0], Settings.display_cols[1], Settings.display_rows); +} + +void CmndDisplayModel(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < DISPLAY_MAX_DRIVERS)) { + uint32_t last_display_model = Settings.display_model; + Settings.display_model = XdrvMailbox.payload; + if (XdspCall(FUNC_DISPLAY_MODEL)) { + restart_flag = 2; + } else { + Settings.display_model = last_display_model; + } + } + ResponseCmndNumber(Settings.display_model); +} + +void CmndDisplayWidth(void) +{ + if (XdrvMailbox.payload > 0) { + if (XdrvMailbox.payload != Settings.display_width) { + Settings.display_width = XdrvMailbox.payload; + restart_flag = 2; + } + } + ResponseCmndNumber(Settings.display_width); +} + +void CmndDisplayHeight(void) +{ + if (XdrvMailbox.payload > 0) { + if (XdrvMailbox.payload != Settings.display_height) { + Settings.display_height = XdrvMailbox.payload; + restart_flag = 2; + } + } + ResponseCmndNumber(Settings.display_height); +} + +void CmndDisplayMode(void) +{ +#ifdef USE_DISPLAY_MODES1TO5 + + + + + + + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { + uint32_t last_display_mode = Settings.display_mode; + Settings.display_mode = XdrvMailbox.payload; + + if (disp_subscribed != (Settings.display_mode &0x04)) { + restart_flag = 2; + } else { + if (last_display_mode && !Settings.display_mode) { + DisplayInit(DISPLAY_INIT_MODE); + if (renderer) renderer->fillScreen(bg_color); + else DisplayClear(); + } else { + DisplayLogBufferInit(); + DisplayInit(DISPLAY_INIT_MODE); + } + } + } +#endif + ResponseCmndNumber(Settings.display_mode); +} + +void CmndDisplayDimmer(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + Settings.display_dimmer = ((XdrvMailbox.payload +1) * 100) / 666; + if (Settings.display_dimmer && !(disp_power)) { + ExecuteCommandPower(disp_device, POWER_ON, SRC_DISPLAY); + } + else if (!Settings.display_dimmer && disp_power) { + ExecuteCommandPower(disp_device, POWER_OFF, SRC_DISPLAY); + } + if (renderer) renderer->dim(Settings.display_dimmer); + } + ResponseCmndNumber(Settings.display_dimmer); +} + +void CmndDisplaySize(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { + Settings.display_size = XdrvMailbox.payload; + if (renderer) renderer->setTextSize(Settings.display_size); + else DisplaySetSize(Settings.display_size); + } + ResponseCmndNumber(Settings.display_size); +} + +void CmndDisplayFont(void) +{ + if ((XdrvMailbox.payload >=0) && (XdrvMailbox.payload <= 4)) { + Settings.display_font = XdrvMailbox.payload; + if (renderer) renderer->setTextFont(Settings.display_font); + else DisplaySetFont(Settings.display_font); + } + ResponseCmndNumber(Settings.display_font); +} + +void CmndDisplayRotate(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { + if (Settings.display_rotate != XdrvMailbox.payload) { +# 1416 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_13_display.ino" + Settings.display_rotate = XdrvMailbox.payload; + DisplayInit(DISPLAY_INIT_MODE); +#ifdef USE_DISPLAY_MODES1TO5 + DisplayLogBufferInit(); +#endif + } + } + ResponseCmndNumber(Settings.display_rotate); +} + +void CmndDisplayText(void) +{ + if (disp_device && XdrvMailbox.data_len > 0) { +#ifndef USE_DISPLAY_MODES1TO5 + DisplayText(); +#else + if (!Settings.display_mode) { + DisplayText(); + } else { + DisplayLogBufferAdd(XdrvMailbox.data); + } +#endif + ResponseCmndChar(XdrvMailbox.data); + } +} + +void CmndDisplayAddress(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { + Settings.display_address[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.display_address[XdrvMailbox.index -1]); + } +} + +void CmndDisplayRefresh(void) +{ + if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) { + Settings.display_refresh = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.display_refresh); +} + +void CmndDisplayColumns(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) { + Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload; +#ifdef USE_DISPLAY_MODES1TO5 + if (1 == XdrvMailbox.index) { + DisplayLogBufferInit(); + DisplayReAllocScreenBuffer(); + } +#endif + } + ResponseCmndIdxNumber(Settings.display_cols[XdrvMailbox.index -1]); + } +} + +void CmndDisplayRows(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) { + Settings.display_rows = XdrvMailbox.payload; +#ifdef USE_DISPLAY_MODES1TO5 + DisplayLogBufferInit(); + DisplayReAllocScreenBuffer(); +#endif + } + ResponseCmndNumber(Settings.display_rows); +} + + + + + +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) +void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp) { + if (!renderer) return; + + + File fp; + fp=SD.open(file,FILE_READ); + if (!fp) return; + uint16_t xsize; + fp.read((uint8_t*)&xsize,2); + uint16_t ysize; + fp.read((uint8_t*)&ysize,2); + +#if 1 +#define XBUFF 128 + uint16_t xdiv=xsize/XBUFF; + renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize); + for(int16_t j=0; j=2) renderer->pushColors(rgb,len/2,true); + } + OsWatchLoop(); + } + renderer->setAddrWindow(0,0,0,0); +#else + for(int16_t j=0; jwritePixel(xp+i,yp,rgb); + } + delay(0); + OsWatchLoop(); + yp++; + } +#endif + fp.close(); +} +#endif + +#ifdef USE_AWATCH +#define MINUTE_REDUCT 4 + +#ifndef pi +#define pi 3.14159265359 +#endif + + +void DrawAClock(uint16_t rad) { + if (!renderer) return; + float frad=rad; + uint16_t hred=frad/3.0; + renderer->fillCircle(disp_xpos, disp_ypos, rad, bg_color); + renderer->drawCircle(disp_xpos, disp_ypos, rad, fg_color); + renderer->fillCircle(disp_xpos, disp_ypos, 4, fg_color); + for (uint8_t count=0; count<60; count+=5) { + float p1=((float)count*(pi/30)-(pi/2)); + uint8_t len; + if ((count%15)==0) { + len=4; + } else { + len=2; + } + renderer->writeLine(disp_xpos+((float)(rad-len)*cosf(p1)), disp_ypos+((float)(rad-len)*sinf(p1)), disp_xpos+(frad*cosf(p1)), disp_ypos+(frad*sinf(p1)), fg_color); + } + + + float hour=((float)RtcTime.hour*60.0+(float)RtcTime.minute)/60.0; + float temp=(hour*(pi/6.0)-(pi/2.0)); + renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-hred)*cosf(temp),disp_ypos+(frad-hred)*sinf(temp), fg_color); + + + temp=((float)RtcTime.minute*(pi/30.0)-(pi/2.0)); + renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-MINUTE_REDUCT)*cosf(temp),disp_ypos+(frad-MINUTE_REDUCT)*sinf(temp), fg_color); +} +#endif + + +#ifdef USE_GRAPH + +typedef union { + uint8_t data; + struct { + uint8_t overlay : 1; + uint8_t draw : 1; + uint8_t nu3 : 1; + uint8_t nu4 : 1; + uint8_t nu5 : 1; + uint8_t nu6 : 1; + uint8_t nu7 : 1; + uint8_t nu8 : 1; + }; +} GFLAGS; + +struct GRAPH { + uint16_t xp; + uint16_t yp; + uint16_t xs; + uint16_t ys; + float ymin; + float ymax; + float range; + uint32_t x_time; + uint32_t last_ms; + uint32_t last_ms_redrawn; + int16_t decimation; + uint16_t dcnt; + uint32_t summ; + uint16_t xcnt; + uint8_t *values; + uint8_t xticks; + uint8_t yticks; + uint8_t last_val; + uint8_t color_index; + GFLAGS flags; +}; + + +struct GRAPH *graph[NUM_GRAPHS]; + +#define TICKLEN 4 +void ClrGraph(uint16_t num) { + struct GRAPH *gp=graph[num]; + + uint16_t xticks=gp->xticks; + uint16_t yticks=gp->yticks; + uint16_t count; + + + if (gp->flags.overlay) return; + + renderer->fillRect(gp->xp+1,gp->yp+1,gp->xs-2,gp->ys-2,bg_color); + + if (xticks) { + float cxp=gp->xp,xd=(float)gp->xs/(float)xticks; + for (count=0; countwriteFastVLine(cxp,gp->yp+gp->ys-TICKLEN,TICKLEN,fg_color); + cxp+=xd; + } + } + if (yticks) { + if (gp->ymin<0 && gp->ymax>0) { + + float cxp=0; + float czp=gp->yp+(gp->ymax/gp->range); + while (cxpxs) { + renderer->writeFastHLine(gp->xp+cxp,czp,2,fg_color); + cxp+=6.0; + } + + float cyp=0,yd=gp->ys/yticks; + for (count=0; countgp->yp) { + renderer->writeFastHLine(gp->xp,czp-cyp,TICKLEN,fg_color); + renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,czp-cyp,TICKLEN,fg_color); + } + if ((czp+cyp)<(gp->yp+gp->ys)) { + renderer->writeFastHLine(gp->xp,czp+cyp,TICKLEN,fg_color); + renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,czp+cyp,TICKLEN,fg_color); + } + cyp+=yd; + } + } else { + float cyp=gp->yp,yd=gp->ys/yticks; + for (count=0; countwriteFastHLine(gp->xp,cyp,TICKLEN,fg_color); + renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,cyp,TICKLEN,fg_color); + cyp+=yd; + } + } + } +} + + +void DefineGraph(uint16_t num,uint16_t xp,uint16_t yp,int16_t xs,uint16_t ys,int16_t dec,float ymin, float ymax,uint8_t icol) { + if (!renderer) return; + uint8_t rflg=0; + if (xs<0) { + rflg=1; + xs=abs(xs); + } + struct GRAPH *gp; + uint16_t count; + uint16_t index=num%NUM_GRAPHS; + if (!graph[index]) { + gp=(struct GRAPH*)calloc(sizeof(struct GRAPH),1); + if (!gp) return; + graph[index]=gp; + } else { + gp=graph[index]; + if (rflg) { + RedrawGraph(index,1); + return; + } + } + + + gp->xticks=(num>>4)&0x3f; + gp->yticks=(num>>10)&0x3f; + gp->xp=xp; + gp->yp=yp; + gp->xs=xs; + gp->ys=ys; + if (!dec) dec=1; + gp->decimation=dec; + if (dec>0) { + + gp->x_time=((float)dec*60000.0)/(float)xs; + gp->last_ms=millis()+gp->x_time; + } + gp->ymin=ymin; + gp->ymax=ymax; + gp->range=(ymax-ymin)/ys; + gp->xcnt=0; + gp->dcnt=0; + gp->summ=0; + if (gp->values) free(gp->values); + gp->values=(uint8_t*) calloc(1,xs+2); + if (!gp->values) { + free(gp); + graph[index]=0; + return; + } + + gp->values[0]=0; + + gp->last_ms_redrawn=millis(); + + if (!icol) icol=1; + gp->color_index=icol; + gp->flags.overlay=0; + gp->flags.draw=1; + + + if (index>0) { + for (uint8_t count=0; countxp==gp1->xp) && (gp->yp==gp1->yp)) { + gp->flags.overlay=1; + break; + } + } + } + } + + + renderer->drawRect(xp,yp,xs,ys,fg_color); + + ClrGraph(index); + +} + + +void DisplayCheckGraph() { + int16_t count; + struct GRAPH *gp; + for (count=0;countdecimation>0) { + + while (millis()>gp->last_ms) { + gp->last_ms+=gp->x_time; + uint8_t val; + if (gp->dcnt) { + val=gp->summ/gp->dcnt; + gp->dcnt=0; + gp->summ=0; + gp->last_val=val; + } else { + val=gp->last_val; + } + AddGraph(count,val); + } + } + } + } +} + + +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) +#include + +void Save_graph(uint8_t num, char *path) { + if (!renderer) return; + uint16_t index=num%NUM_GRAPHS; + struct GRAPH *gp=graph[index]; + if (!gp) return; + File fp; + SD.remove(path); + fp=SD.open(path,FILE_WRITE); + if (!fp) return; + char str[32]; + sprintf_P(str,PSTR("%d\t%d\t%d\t"),gp->xcnt,gp->xs,gp->ys); + fp.print(str); + dtostrfd(gp->ymin,2,str); + fp.print(str); + fp.print("\t"); + dtostrfd(gp->ymax,2,str); + fp.print(str); + fp.print("\t"); + for (uint32_t count=0;countxs;count++) { + dtostrfd(gp->values[count],0,str); + fp.print(str); + fp.print("\t"); + } + fp.print("\n"); + fp.close(); +} +void Restore_graph(uint8_t num, char *path) { + if (!renderer) return; + uint16_t index=num%NUM_GRAPHS; + struct GRAPH *gp=graph[index]; + if (!gp) return; + File fp; + fp=SD.open(path,FILE_READ); + if (!fp) return; + char vbuff[32]; + char *cp=vbuff; + uint8_t buf[2]; + uint8_t findex=0; + + for (uint32_t count=0;count<=gp->xs+4;count++) { + cp=vbuff; + findex=0; + while (fp.available()) { + fp.read(buf,1); + if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { + break; + } else { + *cp++=buf[0]; + findex++; + if (findex>=sizeof(vbuff)-1) break; + } + } + *cp=0; + if (count<=4) { + if (count==0) gp->xcnt=atoi(vbuff); + } else { + gp->values[count-5]=atoi(vbuff); + } + } + fp.close(); + RedrawGraph(num,1); +} +#endif + +void RedrawGraph(uint8_t num, uint8_t flags) { + uint16_t index=num%NUM_GRAPHS; + struct GRAPH *gp=graph[index]; + if (!gp) return; + if (!flags) { + gp->flags.draw=0; + return; + } + if (!renderer) return; + + gp->flags.draw=1; + uint16_t linecol=fg_color; + + if (color_type==COLOR_COLOR) { + linecol=renderer->GetColorFromIndex(gp->color_index); + } + + if (!gp->flags.overlay) { + + renderer->drawRect(gp->xp,gp->yp,gp->xs,gp->ys,fg_color); + + ClrGraph(index); + } + + for (uint16_t count=0;countxs-1;count++) { + renderer->writeLine(gp->xp+count,gp->yp+gp->ys-gp->values[count]-1,gp->xp+count+1,gp->yp+gp->ys-gp->values[count+1]-1,linecol); + } +} + + +void AddGraph(uint8_t num,uint8_t val) { + struct GRAPH *gp=graph[num]; + if (!renderer) return; + + uint16_t linecol=fg_color; + if (color_type==COLOR_COLOR) { + linecol=renderer->GetColorFromIndex(gp->color_index); + } + gp->xcnt++; + if (gp->xcnt>gp->xs) { + gp->xcnt=gp->xs; + int16_t count; + + for (count=0;countxs-1;count++) { + gp->values[count]=gp->values[count+1]; + } + gp->values[gp->xcnt-1]=val; + + if (!gp->flags.draw) return; + + + if (millis()-gp->last_ms_redrawn>1000) { + gp->last_ms_redrawn=millis(); + + if (!gp->flags.overlay) { + + renderer->drawRect(gp->xp,gp->yp,gp->xs,gp->ys,fg_color); + + ClrGraph(num); + } + + for (count=0;countxs-1;count++) { + renderer->writeLine(gp->xp+count,gp->yp+gp->ys-gp->values[count]-1,gp->xp+count+1,gp->yp+gp->ys-gp->values[count+1]-1,linecol); + } + } + } else { + + gp->values[gp->xcnt]=val; + if (!gp->flags.draw) return; + renderer->writeLine(gp->xp+gp->xcnt-1,gp->yp+gp->ys-gp->values[gp->xcnt-1]-1,gp->xp+gp->xcnt,gp->yp+gp->ys-gp->values[gp->xcnt]-1,linecol); + } +} + + + +void AddValue(uint8_t num,float fval) { + + num=num%NUM_GRAPHS; + struct GRAPH *gp=graph[num]; + if (!gp) return; + + if (fval>gp->ymax) fval=gp->ymax; + if (fvalymin) fval=gp->ymin; + + int16_t val; + val=(fval-gp->ymin)/gp->range; + + if (val>gp->ys-1) val=gp->ys-1; + if (val<0) val=0; + + + gp->summ+=val; + gp->dcnt++; + + + if (gp->decimation<0) { + if (gp->dcnt>=-gp->decimation) { + gp->dcnt=0; + + val=gp->summ/-gp->decimation; + gp->summ=0; + + AddGraph(num,val); + } + } +} +#endif + + + + + +bool Xdrv13(uint8_t function) +{ + bool result = false; + + if ((i2c_flg || spi_flg || soft_spi_flg) && XdspPresent()) { + switch (function) { + case FUNC_PRE_INIT: + DisplayInitDriver(); +#ifdef USE_GRAPH + for (uint8_t count=0;count + +TasmotaSerial *MP3Player; + + + + + +#define D_CMND_MP3 "MP3" + +const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}"; +const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}"; +const char kMP3_Commands[] PROGMEM = "Track|Play|Pause|Stop|Volume|EQ|Device|Reset|DAC"; + + + + + +enum MP3_Commands { + CMND_MP3_TRACK, + CMND_MP3_PLAY, + CMND_MP3_PAUSE, + CMND_MP3_STOP, + CMND_MP3_VOLUME, + CMND_MP3_EQ, + CMND_MP3_DEVICE, + CMND_MP3_RESET, + CMND_MP3_DAC }; + + + + + + +#define MP3_CMD_RESET_VALUE 0 + +#define MP3_CMD_TRACK 0x03 +#define MP3_CMD_PLAY 0x0d +#define MP3_CMD_PAUSE 0x0e +#define MP3_CMD_STOP 0x16 +#define MP3_CMD_VOLUME 0x06 +#define MP3_CMD_EQ 0x07 +#define MP3_CMD_DEVICE 0x09 +#define MP3_CMD_RESET 0x0C +#define MP3_CMD_DAC 0x1A + + + + + + +uint16_t MP3_Checksum(uint8_t *array) +{ + uint16_t checksum = 0; + for (uint32_t i = 0; i < 6; i++) { + checksum += array[i]; + } + checksum = checksum^0xffff; + return (checksum+1); +} + + + + + + +void MP3PlayerInit(void) { + MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3_DFR562]); + + if (MP3Player->begin(9600)) { + MP3Player->flush(); + delay(1000); + MP3_CMD(MP3_CMD_RESET, MP3_CMD_RESET_VALUE); + delay(3000); + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); + } + return; +} +# 159 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_14_mp3.ino" +void MP3_CMD(uint8_t mp3cmd,uint16_t val) { + uint8_t i = 0; + uint8_t cmd[10] = {0x7e,0xff,6,0,0,0,0,0,0,0xef}; + cmd[3] = mp3cmd; + cmd[4] = 0; + cmd[5] = val>>8; + cmd[6] = val; + uint16_t chks = MP3_Checksum(&cmd[1]); + cmd[7] = chks>>8; + cmd[8] = chks; + MP3Player->write(cmd, sizeof(cmd)); + delay(1000); + if (mp3cmd == MP3_CMD_RESET) { + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); + } + return; +} + + + + + +bool MP3PlayerCmd(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t disp_len = strlen(D_CMND_MP3); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMP3_Commands); + + switch (command_code) { + case CMND_MP3_TRACK: + case CMND_MP3_VOLUME: + case CMND_MP3_EQ: + case CMND_MP3_DEVICE: + case CMND_MP3_DAC: + + if (XdrvMailbox.data_len > 0) { + if (command_code == CMND_MP3_TRACK) { MP3_CMD(MP3_CMD_TRACK, XdrvMailbox.payload); } + if (command_code == CMND_MP3_VOLUME) { MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100); } + if (command_code == CMND_MP3_EQ) { MP3_CMD(MP3_CMD_EQ, XdrvMailbox.payload); } + if (command_code == CMND_MP3_DEVICE) { MP3_CMD(MP3_CMD_DEVICE, XdrvMailbox.payload); } + if (command_code == CMND_MP3_DAC) { MP3_CMD(MP3_CMD_DAC, XdrvMailbox.payload); } + } + Response_P(S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_MP3_PLAY: + case CMND_MP3_PAUSE: + case CMND_MP3_STOP: + case CMND_MP3_RESET: + + if (command_code == CMND_MP3_PLAY) { MP3_CMD(MP3_CMD_PLAY, 0); } + if (command_code == CMND_MP3_PAUSE) { MP3_CMD(MP3_CMD_PAUSE, 0); } + if (command_code == CMND_MP3_STOP) { MP3_CMD(MP3_CMD_STOP, 0); } + if (command_code == CMND_MP3_RESET) { MP3_CMD(MP3_CMD_RESET, 0); } + Response_P(S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); + break; + default: + + serviced = false; + break; + } + } else { + return false; + } + return serviced; +} + + + + + +bool Xdrv14(uint8_t function) +{ + bool result = false; + + if (pin[GPIO_MP3_DFR562] < 99) { + switch (function) { + case FUNC_PRE_INIT: + MP3PlayerInit(); + break; + case FUNC_COMMAND: + result = MP3PlayerCmd(); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_15_pca9685.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_15_pca9685.ino" +#ifdef USE_I2C +#ifdef USE_PCA9685 + +#define XDRV_15 15 + +#define PCA9685_REG_MODE1 0x00 +#define PCA9685_REG_LED0_ON_L 0x06 +#define PCA9685_REG_PRE_SCALE 0xFE + +#ifndef USE_PCA9685_FREQ + #define USE_PCA9685_FREQ 50 +#endif + +uint8_t pca9685_detected = 0; +uint16_t pca9685_freq = USE_PCA9685_FREQ; +uint16_t pca9685_pin_pwm_value[16]; + +void PCA9685_Detect(void) +{ + if (pca9685_detected) { return; } + + uint8_t buffer; + + if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x20); + if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { + if (0x20 == buffer) { + pca9685_detected = 1; + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "PCA9685", USE_PCA9685_ADDR); + PCA9685_Reset(); + } + } + } +} + +void PCA9685_Reset(void) +{ + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x80); + PCA9685_SetPWMfreq(USE_PCA9685_FREQ); + for (uint32_t pin=0;pin<16;pin++) { + PCA9685_SetPWM(pin,0,false); + pca9685_pin_pwm_value[pin] = 0; + } + Response_P(PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); +} + +void PCA9685_SetPWMfreq(double freq) { + + + + + if (freq > 23 && freq < 1527) { + pca9685_freq=freq; + } else { + pca9685_freq=50; + } + uint8_t pre_scale_osc = round(25000000/(4096*pca9685_freq))-1; + if (1526 == pca9685_freq) pre_scale_osc=0xFF; + uint8_t current_mode1 = I2cRead8(USE_PCA9685_ADDR, PCA9685_REG_MODE1); + uint8_t sleep_mode1 = (current_mode1&0x7F) | 0x10; + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, sleep_mode1); + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_PRE_SCALE, pre_scale_osc); + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, current_mode1 | 0xA0); +} + +void PCA9685_SetPWM_Reg(uint8_t pin, uint16_t on, uint16_t off) { + uint8_t led_reg = PCA9685_REG_LED0_ON_L + 4 * pin; + uint32_t led_data = 0; + I2cWrite8(USE_PCA9685_ADDR, led_reg, on); + I2cWrite8(USE_PCA9685_ADDR, led_reg+1, (on >> 8)); + I2cWrite8(USE_PCA9685_ADDR, led_reg+2, off); + I2cWrite8(USE_PCA9685_ADDR, led_reg+3, (off >> 8)); +} + +void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted) { + if (4096 == pwm) { + PCA9685_SetPWM_Reg(pin, 4096, 0); + } else { + PCA9685_SetPWM_Reg(pin, 0, pwm); + } + pca9685_pin_pwm_value[pin] = pwm; +} + +bool PCA9685_Command(void) +{ + bool serviced = true; + bool validpin = false; + uint8_t paramcount = 0; + if (XdrvMailbox.data_len > 0) { + paramcount=1; + } else { + serviced = false; + return serviced; + } + char sub_string[XdrvMailbox.data_len]; + for (uint32_t ca=0;ca 1) { + uint16_t new_freq = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if ((new_freq >= 24) && (new_freq <= 1526)) { + PCA9685_SetPWMfreq(new_freq); + Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}"),new_freq); + return serviced; + } + } else { + Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i}}"),pca9685_freq); + return serviced; + } + } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"PWM")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (paramcount > 2) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "ON")) { + PCA9685_SetPWM(pin, 4096, false); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,4096); + serviced = true; + return serviced; + } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "OFF")) { + PCA9685_SetPWM(pin, 0, false); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,0); + serviced = true; + return serviced; + } + uint16_t pwm = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((pin >= 0 && pin <= 15) && (pwm >= 0 && pwm <= 4096)) { + PCA9685_SetPWM(pin, pwm, false); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,pwm); + serviced = true; + return serviced; + } + } + } + } + return serviced; +} + +void PCA9685_OutputTelemetry(bool telemetry) { + if (0 == pca9685_detected) { return; } + ResponseTime_P(PSTR(",\"PCA9685\":{\"PWM_FREQ\":%i,"),pca9685_freq); + for (uint32_t pin=0;pin<16;pin++) { + ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pca9685_pin_pwm_value[pin]); + } + ResponseAppend_P(PSTR("\"END\":1}}")); + if (telemetry) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + } +} + +bool Xdrv15(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_EVERY_SECOND: + PCA9685_Detect(); + if (tele_period == 0) { + PCA9685_OutputTelemetry(true); + } + break; + case FUNC_COMMAND_DRIVER: + if (XDRV_15 == XdrvMailbox.index) { + result = PCA9685_Command(); + } + break; + default: + break; + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_16_tuyamcu.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_16_tuyamcu.ino" +#ifdef USE_LIGHT +#ifdef USE_TUYA_MCU + +#define XDRV_16 16 +#define XNRG_16 16 + +#ifndef TUYA_DIMMER_ID +#define TUYA_DIMMER_ID 0 +#endif + +#define TUYA_CMD_HEARTBEAT 0x00 +#define TUYA_CMD_QUERY_PRODUCT 0x01 +#define TUYA_CMD_MCU_CONF 0x02 +#define TUYA_CMD_WIFI_STATE 0x03 +#define TUYA_CMD_WIFI_RESET 0x04 +#define TUYA_CMD_WIFI_SELECT 0x05 +#define TUYA_CMD_SET_DP 0x06 +#define TUYA_CMD_STATE 0x07 +#define TUYA_CMD_QUERY_STATE 0x08 + +#define TUYA_TYPE_BOOL 0x01 +#define TUYA_TYPE_VALUE 0x02 + +#define TUYA_BUFFER_SIZE 256 + +#include + +TasmotaSerial *TuyaSerial = nullptr; + +struct TUYA { + uint8_t new_dim = 0; + bool ignore_dim = false; + uint8_t cmd_status = 0; + uint8_t cmd_checksum = 0; + uint8_t data_len = 0; + int8_t wifi_state = -2; + uint8_t heartbeat_timer = 0; +#ifdef USE_ENERGY_SENSOR + uint32_t lastPowerCheckTime = 0; +#endif + char *buffer = nullptr; + int byte_counter = 0; +} Tuya; + + +enum TuyaSupportedFunctions { + TUYA_MCU_FUNC_NONE, + TUYA_MCU_FUNC_SWT1 = 1, + TUYA_MCU_FUNC_SWT2, + TUYA_MCU_FUNC_SWT3, + TUYA_MCU_FUNC_SWT4, + TUYA_MCU_FUNC_REL1 = 11, + TUYA_MCU_FUNC_REL2, + TUYA_MCU_FUNC_REL3, + TUYA_MCU_FUNC_REL4, + TUYA_MCU_FUNC_REL5, + TUYA_MCU_FUNC_REL6, + TUYA_MCU_FUNC_REL7, + TUYA_MCU_FUNC_REL8, + TUYA_MCU_FUNC_DIMMER = 21, + TUYA_MCU_FUNC_POWER = 31, + TUYA_MCU_FUNC_CURRENT, + TUYA_MCU_FUNC_VOLTAGE, + TUYA_MCU_FUNC_REL1_INV = 41, + TUYA_MCU_FUNC_REL2_INV, + TUYA_MCU_FUNC_REL3_INV, + TUYA_MCU_FUNC_REL4_INV, + TUYA_MCU_FUNC_REL5_INV, + TUYA_MCU_FUNC_REL6_INV, + TUYA_MCU_FUNC_REL7_INV, + TUYA_MCU_FUNC_REL8_INV, + TUYA_MCU_FUNC_LAST = 255 +}; + +const char kTuyaCommand[] PROGMEM = "|" + D_CMND_TUYA_MCU; + +void (* const TuyaCommand[])(void) PROGMEM = { + &CmndTuyaMcu +}; +# 108 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_16_tuyamcu.ino" +void CmndTuyaMcu(void) { + if (XdrvMailbox.data_len > 0) { + char *p; + uint8_t i = 0; + uint8_t parm[3] = { 0 }; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { + parm[i] = strtoul(str, nullptr, 0); + i++; + } + + if (TuyaFuncIdValid(parm[0])) { + TuyaAddMcuFunc(parm[0], parm[1]); + restart_flag = 2; + } else { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]); + } + + } + + Response_P(PSTR("[")); + bool added = false; + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].fnid != 0) { + if (added) { + ResponseAppend_P(PSTR(",")); + } + ResponseAppend_P(PSTR("{\"fnId\":%d, \"dpId\":%d}" ), Settings.tuya_fnid_map[i].fnid, Settings.tuya_fnid_map[i].dpid); + added = true; + } + } + ResponseAppend_P(PSTR("]")); +} + + + + + +void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) { + bool added = false; + + if (fnId == 0 || dpId == 0) { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if ((dpId > 0 && Settings.tuya_fnid_map[i].dpid == dpId) || (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].fnid == fnId)) { + Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; + Settings.tuya_fnid_map[i].dpid = 0; + break; + } + } + } else { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].dpid == 0 || Settings.tuya_fnid_map[i].fnid == fnId || Settings.tuya_fnid_map[i].fnid == 0) { + if (!added) { + Settings.tuya_fnid_map[i].fnid = fnId; + Settings.tuya_fnid_map[i].dpid = dpId; + added = true; + } else if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].fnid == fnId) { + Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; + Settings.tuya_fnid_map[i].dpid = 0; + } + } + } + } + UpdateDevices(); +} + +void UpdateDevices() { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + uint8_t fnId = Settings.tuya_fnid_map[i].fnid; + if (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].dpid > 0) { + + if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { + bitClear(rel_inverted, fnId - TUYA_MCU_FUNC_REL1); + } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { + bitSet(rel_inverted, fnId - TUYA_MCU_FUNC_REL1_INV); + } + + } + } +} + +inline bool TuyaFuncIdValid(uint8_t fnId) { + return (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) || + (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) || + fnId == TUYA_MCU_FUNC_DIMMER || + (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE) || + (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV); +} + +uint8_t TuyaGetFuncId(uint8_t dpid) { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].dpid == dpid) { + return Settings.tuya_fnid_map[i].fnid; + } + } + return TUYA_MCU_FUNC_NONE; +} + +uint8_t TuyaGetDpId(uint8_t fnId) { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].fnid == fnId) { + return Settings.tuya_fnid_map[i].dpid; + } + } + return 0; +} + +void TuyaSendCmd(uint8_t cmd, uint8_t payload[] = nullptr, uint16_t payload_len = 0) +{ + uint8_t checksum = (0xFF + cmd + (payload_len >> 8) + (payload_len & 0xFF)); + TuyaSerial->write(0x55); + TuyaSerial->write(0xAA); + TuyaSerial->write((uint8_t)0x00); + TuyaSerial->write(cmd); + TuyaSerial->write(payload_len >> 8); + TuyaSerial->write(payload_len & 0xFF); + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send \"55aa00%02x%02x%02x"), cmd, payload_len >> 8, payload_len & 0xFF); + for (uint32_t i = 0; i < payload_len; ++i) { + TuyaSerial->write(payload[i]); + checksum += payload[i]; + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, payload[i]); + } + TuyaSerial->write(checksum); + TuyaSerial->flush(); + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x\""), log_data, checksum); + AddLog(LOG_LEVEL_DEBUG); +} + +void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value) +{ + uint16_t payload_len = 4; + uint8_t payload_buffer[8]; + payload_buffer[0] = id; + payload_buffer[1] = type; + switch (type) { + case TUYA_TYPE_BOOL: + payload_len += 1; + payload_buffer[2] = 0x00; + payload_buffer[3] = 0x01; + payload_buffer[4] = value[0]; + break; + case TUYA_TYPE_VALUE: + payload_len += 4; + payload_buffer[2] = 0x00; + payload_buffer[3] = 0x04; + payload_buffer[4] = value[3]; + payload_buffer[5] = value[2]; + payload_buffer[6] = value[1]; + payload_buffer[7] = value[0]; + break; + } + + TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} + +void TuyaSendBool(uint8_t id, bool value) +{ + TuyaSendState(id, TUYA_TYPE_BOOL, (uint8_t*)&value); +} + +void TuyaSendValue(uint8_t id, uint32_t value) +{ + TuyaSendState(id, TUYA_TYPE_VALUE, (uint8_t*)(&value)); +} + +bool TuyaSetPower(void) +{ + bool status = false; + + uint8_t rpower = XdrvMailbox.index; + int16_t source = XdrvMailbox.payload; + + if (source != SRC_SWITCH && TuyaSerial) { + TuyaSendBool(active_device, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); + status = true; + } + return status; +} + +bool TuyaSetChannels(void) +{ + LightSerialDuty(((uint8_t*)XdrvMailbox.data)[0]); + delay(20); + return true; +} + +void LightSerialDuty(uint8_t duty) +{ + uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER); + if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { + if (Settings.flag3.tuya_dimmer_min_limit) { + if (duty < 25) { duty = 25; } + } + duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]); + if (Tuya.new_dim != duty) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); + TuyaSendValue(dpid, duty); + } + } else if (dpid > 0) { + Tuya.ignore_dim = false; + duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); + } +} + +void TuyaRequestState(void) +{ + if (TuyaSerial) { + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Read MCU state")); + + TuyaSendCmd(TUYA_CMD_QUERY_STATE); + } +} + +void TuyaResetWifi(void) +{ + if (!Settings.flag.button_restrict) { + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2); + ExecuteCommand(scmnd, SRC_BUTTON); + } +} + +void TuyaPacketProcess(void) +{ + char scmnd[20]; + uint8_t fnId = TUYA_MCU_FUNC_NONE; + + switch (Tuya.buffer[3]) { + + case TUYA_CMD_HEARTBEAT: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); + if (Tuya.buffer[6] == 0) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Detected MCU restart")); + Tuya.wifi_state = -2; + } + break; + + case TUYA_CMD_STATE: + fnId = TuyaGetFuncId(Tuya.buffer[6]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: FnId=%d is set for dpId=%d"), fnId, Tuya.buffer[6]); + + if (Tuya.buffer[5] == 5) { + + if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); + if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { + ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10], SRC_SWITCH); + } + } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[10]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); + if (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { + ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[10] ^ 1, SRC_SWITCH); + } + } else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[10], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1)); + + if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[10]) { + SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[10]); + SwitchHandler(1); + } + } + + } + else if (Tuya.buffer[5] == 8) { + bool tuya_energy_enabled = (XNRG_16 == energy_flg); + if (fnId == TUYA_MCU_FUNC_DIMMER) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]); + Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_TUYA_DIMMER_MAX], 0, 100); + if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { + Tuya.ignore_dim = true; + + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + + #ifdef USE_ENERGY_SENSOR + else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) { + Energy.voltage[0] = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); + } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) { + Energy.current[0] = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 1000; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); + } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) { + Energy.active_power[0] = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); + + if (Tuya.lastPowerCheckTime != 0 && Energy.active_power[0] > 0) { + Energy.kWhtoday += (float)Energy.active_power[0] * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36; + EnergyUpdateToday(); + } + Tuya.lastPowerCheckTime = Rtc.utc_time; + } + #endif + + } + + + + break; + + case TUYA_CMD_WIFI_RESET: + case TUYA_CMD_WIFI_SELECT: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi Reset")); + TuyaResetWifi(); + break; + + case TUYA_CMD_WIFI_STATE: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi LED set ACK")); + Tuya.wifi_state = WifiState(); + break; + + case TUYA_CMD_MCU_CONF: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration Mode=%d"), Tuya.buffer[5]); + + if (Tuya.buffer[5] == 2) { + uint8_t led1_gpio = Tuya.buffer[6]; + uint8_t key1_gpio = Tuya.buffer[7]; + bool key1_set = false; + bool led1_set = false; + for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { + if (Settings.my_gp.io[i] == GPIO_LED1) led1_set = true; + else if (Settings.my_gp.io[i] == GPIO_KEY1) key1_set = true; + } + if (!Settings.my_gp.io[led1_gpio] && !led1_set) { + Settings.my_gp.io[led1_gpio] = GPIO_LED1; + restart_flag = 2; + } + if (!Settings.my_gp.io[key1_gpio] && !key1_set) { + Settings.my_gp.io[key1_gpio] = GPIO_KEY1; + restart_flag = 2; + } + } + TuyaRequestState(); + break; + + default: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX unknown command")); + } +} + + + + + +bool TuyaModuleSelected(void) +{ + if (!(pin[GPIO_TUYA_RX] < 99) || !(pin[GPIO_TUYA_TX] < 99)) { + pin[GPIO_TUYA_TX] = 1; + pin[GPIO_TUYA_RX] = 3; + Settings.my_gp.io[1] = GPIO_TUYA_TX; + Settings.my_gp.io[3] = GPIO_TUYA_RX; + restart_flag = 2; + } + + if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) == 0 && TUYA_DIMMER_ID > 0) { + TuyaAddMcuFunc(TUYA_MCU_FUNC_DIMMER, TUYA_DIMMER_ID); + } + + bool relaySet = false; + + devices_present--; + + for (uint8_t i = 0 ; i < MAX_TUYA_FUNCTIONS; i++) { + if ((Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) || + (Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) { + relaySet = true; + devices_present++; + } + } + + if (!relaySet) { + TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); + devices_present++; + SettingsSaveAll(); + } + + if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { + light_type = LT_SERIAL1; + } else { + light_type = LT_BASIC; + } + + UpdateDevices(); + return true; +} + +void TuyaInit(void) +{ + Tuya.buffer = (char*)(malloc(TUYA_BUFFER_SIZE)); + if (Tuya.buffer != nullptr) { + TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); + if (TuyaSerial->begin(9600)) { + if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Request MCU configuration")); + + TuyaSendCmd(TUYA_CMD_MCU_CONF); + } + } + Tuya.heartbeat_timer = 0; +} + +void TuyaSerialInput(void) +{ + while (TuyaSerial->available()) { + yield(); + uint8_t serial_in_byte = TuyaSerial->read(); + + if (serial_in_byte == 0x55) { + Tuya.cmd_status = 1; + Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; + Tuya.cmd_checksum += serial_in_byte; + } + else if (Tuya.cmd_status == 1 && serial_in_byte == 0xAA) { + Tuya.cmd_status = 2; + + Tuya.byte_counter = 0; + Tuya.buffer[Tuya.byte_counter++] = 0x55; + Tuya.buffer[Tuya.byte_counter++] = 0xAA; + Tuya.cmd_checksum = 0xFF; + } + else if (Tuya.cmd_status == 2) { + if (Tuya.byte_counter == 5) { + Tuya.cmd_status = 3; + Tuya.data_len = serial_in_byte; + } + Tuya.cmd_checksum += serial_in_byte; + Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; + } + else if ((Tuya.cmd_status == 3) && (Tuya.byte_counter == (6 + Tuya.data_len)) && (Tuya.cmd_checksum == serial_in_byte)) { + Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: RX Packet: \"")); + for (uint32_t i = 0; i < Tuya.byte_counter; i++) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, Tuya.buffer[i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); + AddLog(LOG_LEVEL_DEBUG); + + TuyaPacketProcess(); + Tuya.byte_counter = 0; + Tuya.cmd_status = 0; + Tuya.cmd_checksum = 0; + Tuya.data_len = 0; + } + else if (Tuya.byte_counter < TUYA_BUFFER_SIZE -1) { + Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; + Tuya.cmd_checksum += serial_in_byte; + } else { + Tuya.byte_counter = 0; + Tuya.cmd_status = 0; + Tuya.cmd_checksum = 0; + Tuya.data_len = 0; + } + } +} + +bool TuyaButtonPressed(void) +{ + if (!XdrvMailbox.index && ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == Button.last_state[XdrvMailbox.index]))) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Reset GPIO triggered")); + TuyaResetWifi(); + return true; + } + return false; +} + +void TuyaSetWifiLed(void) +{ + uint8_t wifi_state = 0x02; + switch(WifiState()){ + case WIFI_SMARTCONFIG: + wifi_state = 0x00; + break; + case WIFI_MANAGER: + case WIFI_WPSCONFIG: + wifi_state = 0x01; + break; + case WIFI_RESTART: + wifi_state = 0x03; + break; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Set WiFi LED %d (%d)"), wifi_state, WifiState()); + + TuyaSendCmd(TUYA_CMD_WIFI_STATE, &wifi_state, 1); +} + +#ifdef USE_ENERGY_SENSOR + + + + +bool Xnrg16(uint8_t function) +{ + bool result = false; + + if (TUYA_DIMMER == my_module_type) { + if (FUNC_PRE_INIT == function) { + if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0) { + if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0) { + Energy.current_available = false; + } + if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0) { + Energy.voltage_available = false; + } + energy_flg = XNRG_16; + } + } + } + return result; +} +#endif + + + + + +bool Xdrv16(uint8_t function) +{ + bool result = false; + + if (TUYA_DIMMER == my_module_type) { + switch (function) { + case FUNC_LOOP: + if (TuyaSerial) { TuyaSerialInput(); } + break; + case FUNC_MODULE_INIT: + result = TuyaModuleSelected(); + break; + case FUNC_INIT: + TuyaInit(); + break; + case FUNC_SET_DEVICE_POWER: + result = TuyaSetPower(); + break; + case FUNC_BUTTON_PRESSED: + result = TuyaButtonPressed(); + break; + case FUNC_EVERY_SECOND: + if (TuyaSerial && Tuya.wifi_state != WifiState()) { TuyaSetWifiLed(); } + Tuya.heartbeat_timer++; + if (Tuya.heartbeat_timer > 10) { + Tuya.heartbeat_timer = 0; + TuyaSendCmd(TUYA_CMD_HEARTBEAT); + } + break; + case FUNC_SET_CHANNELS: + result = TuyaSetChannels(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kTuyaCommand, TuyaCommand); + break; + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_17_rcswitch.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_17_rcswitch.ino" +#ifdef USE_RC_SWITCH + + + + +#define XDRV_17 17 + +#define D_JSON_RF_PROTOCOL "Protocol" +#define D_JSON_RF_BITS "Bits" +#define D_JSON_RF_DATA "Data" + +#define D_CMND_RFSEND "RFSend" +#define D_JSON_RF_PULSE "Pulse" +#define D_JSON_RF_REPEAT "Repeat" + +const char kRfSendCommands[] PROGMEM = "|" + D_CMND_RFSEND; + +void (* const RfSendCommand[])(void) PROGMEM = + { &CmndRfSend }; + +#include + +RCSwitch mySwitch = RCSwitch(); + +#define RF_TIME_AVOID_DUPLICATE 1000 + +uint32_t rf_lasttime = 0; + +void RfReceiveCheck(void) +{ + if (mySwitch.available()) { + + unsigned long data = mySwitch.getReceivedValue(); + unsigned int bits = mySwitch.getReceivedBitlength(); + int protocol = mySwitch.getReceivedProtocol(); + int delay = mySwitch.getReceivedDelay(); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFR: Data 0x%lX (%u), Bits %d, Protocol %d, Delay %d"), data, data, bits, protocol, delay); + + uint32_t now = millis(); + if ((now - rf_lasttime > RF_TIME_AVOID_DUPLICATE) && (data > 0)) { + rf_lasttime = now; + + char stemp[16]; + if (Settings.flag.rf_receive_decimal) { + snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)data); + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data); + } + ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), + stemp, bits, protocol, delay); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); + XdrvRulesProcess(); +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_COUNT, data); +#endif + } + mySwitch.resetAvailable(); + } +} + +void RfInit(void) +{ + if (pin[GPIO_RFSEND] < 99) { + mySwitch.enableTransmit(pin[GPIO_RFSEND]); + } + if (pin[GPIO_RFRECV] < 99) { + mySwitch.enableReceive(pin[GPIO_RFRECV]); + } +} + + + + + +void CmndRfSend(void) +{ + bool error = false; + + if (XdrvMailbox.data_len) { + unsigned long data = 0; + unsigned int bits = 24; + int protocol = 1; + int repeat = 10; + int pulse = 350; + + char dataBufUc[XdrvMailbox.data_len]; + UpperCase(dataBufUc, XdrvMailbox.data); + StaticJsonBuffer<150> jsonBuf; + JsonObject &root = jsonBuf.parseObject(dataBufUc); + if (root.success()) { + + char parm_uc[10]; + data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], nullptr, 0); + bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_BITS))]; + protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PROTOCOL))]; + repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_REPEAT))]; + pulse = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PULSE))]; + } else { + + char *p; + uint8_t i = 0; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 5; str = strtok_r(nullptr, ", ", &p)) { + switch (i++) { + case 0: + data = strtoul(str, nullptr, 0); + break; + case 1: + bits = atoi(str); + break; + case 2: + protocol = atoi(str); + break; + case 3: + repeat = atoi(str); + break; + case 4: + pulse = atoi(str); + } + } + } + + if (!protocol) { protocol = 1; } + mySwitch.setProtocol(protocol); + if (!pulse) { pulse = 350; } + mySwitch.setPulseLength(pulse); + if (!repeat) { repeat = 10; } + mySwitch.setRepeatTransmit(repeat); + if (!bits) { bits = 24; } + if (data) { + mySwitch.send(data, bits); + ResponseCmndDone(); + } else { + error = true; + } + } else { + error = true; + } + if (error) { + Response_P(PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_DATA ", " D_JSON_RF_BITS ", " D_JSON_RF_PROTOCOL ", " D_JSON_RF_REPEAT " " D_JSON_OR " " D_JSON_RF_PULSE "\"}")); + } +} + + + + + +bool Xdrv17(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_RFSEND] < 99) || (pin[GPIO_RFRECV] < 99)) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (pin[GPIO_RFRECV] < 99) { + RfReceiveCheck(); + } + break; + case FUNC_COMMAND: + if (pin[GPIO_RFSEND] < 99) { + result = DecodeCommand(kRfSendCommands, RfSendCommand); + } + break; + case FUNC_INIT: + RfInit(); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_18_armtronix_dimmers.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_18_armtronix_dimmers.ino" +#ifdef USE_LIGHT +#ifdef USE_ARMTRONIX_DIMMERS + + + + + + + +#define XDRV_18 18 + +#include + +TasmotaSerial *ArmtronixSerial = nullptr; + +struct ARMTRONIX { + bool ignore_dim = false; + int8_t wifi_state = -2; + int8_t dim_state[2]; + int8_t knob_state[2]; +} Armtronix; + + + + + +bool ArmtronixSetChannels(void) +{ + LightSerial2Duty(((uint8_t*)XdrvMailbox.data)[0], ((uint8_t*)XdrvMailbox.data)[1]); + return true; +} + +void LightSerial2Duty(uint8_t duty1, uint8_t duty2) +{ + if (ArmtronixSerial && !Armtronix.ignore_dim) { + duty1 = ((float)duty1)/2.575757; + duty2 = ((float)duty2)/2.575757; + Armtronix.dim_state[0] = duty1; + Armtronix.dim_state[1] = duty2; + ArmtronixSerial->print("Dimmer1:"); + ArmtronixSerial->print(duty1); + ArmtronixSerial->print("\nDimmer2:"); + ArmtronixSerial->println(duty2); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Serial Packet Dim Values=%d,%d"), Armtronix.dim_state[0],Armtronix.dim_state[1]); + + } else { + Armtronix.ignore_dim = false; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Dim Level skipped due to already set. Value=%d,%d"), Armtronix.dim_state[0],Armtronix.dim_state[1]); + + } +} + +void ArmtronixRequestState(void) +{ + if (ArmtronixSerial) { + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("ARM: Request MCU state")); + ArmtronixSerial->println("Status"); + + } +} + + + + + +bool ArmtronixModuleSelected(void) +{ + light_type = LT_SERIAL2; + return true; +} + +void ArmtronixInit(void) +{ + Armtronix.dim_state[0] = -1; + Armtronix.dim_state[1] = -1; + Armtronix.knob_state[0] = -1; + Armtronix.knob_state[1] = -1; + ArmtronixSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (ArmtronixSerial->begin(115200)) { + if (ArmtronixSerial->hardwareSerial()) { ClaimSerial(); } + ArmtronixSerial->println("Status"); + } +} + +void ArmtronixSerialInput(void) +{ + String answer; + int8_t newDimState[2]; + uint8_t temp; + int commaIndex; + char scmnd[20]; + if (ArmtronixSerial->available()) { + yield(); + answer = ArmtronixSerial->readStringUntil('\n'); + if (answer.substring(0,7) == "Status:") { + commaIndex = 6; + for (uint32_t i =0; i<2; i++) { + newDimState[i] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); + if (newDimState[i] != Armtronix.dim_state[i]) { + temp = ((float)newDimState[i])*1.01010101010101; + Armtronix.dim_state[i] = newDimState[i]; + Armtronix.ignore_dim = true; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "%d %d"),i+1, temp); + ExecuteCommand(scmnd,SRC_SWITCH); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send CMND_CHANNEL=%s"), scmnd ); + } + commaIndex = answer.indexOf(',',commaIndex+1); + } + Armtronix.knob_state[0] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); + commaIndex = answer.indexOf(',',commaIndex+1); + Armtronix.knob_state[1] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); + } + } +} + +void ArmtronixSetWifiLed(void) +{ + uint8_t wifi_state = 0x02; + + switch (WifiState()) { + case WIFI_SMARTCONFIG: + wifi_state = 0x00; + break; + case WIFI_MANAGER: + case WIFI_WPSCONFIG: + wifi_state = 0x01; + break; + case WIFI_RESTART: + wifi_state = 0x03; + break; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Set WiFi LED to state %d (%d)"), wifi_state, WifiState()); + + char state = '0' + ((wifi_state & 1) > 0); + ArmtronixSerial->print("Setled:"); + ArmtronixSerial->write(state); + ArmtronixSerial->write(','); + state = '0' + ((wifi_state & 2) > 0); + ArmtronixSerial->write(state); + ArmtronixSerial->write(10); + Armtronix.wifi_state = WifiState(); +} + + + + + +bool Xdrv18(uint8_t function) +{ + bool result = false; + + if (ARMTRONIX_DIMMERS == my_module_type) { + switch (function) { + case FUNC_LOOP: + if (ArmtronixSerial) { ArmtronixSerialInput(); } + break; + case FUNC_MODULE_INIT: + result = ArmtronixModuleSelected(); + break; + case FUNC_INIT: + ArmtronixInit(); + break; + case FUNC_EVERY_SECOND: + if (ArmtronixSerial) { + if (Armtronix.wifi_state!=WifiState()) { ArmtronixSetWifiLed(); } + if (uptime &1) { + ArmtronixSerial->println("Status"); + } + } + break; + case FUNC_SET_CHANNELS: + result = ArmtronixSetChannels(); + break; + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_19_ps16dz_dimmer.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_19_ps16dz_dimmer.ino" +#ifdef USE_LIGHT +#ifdef USE_PS_16_DZ + + + + +#define XDRV_19 19 + +#define PS16DZ_BUFFER_SIZE 140 + +#define PS16DZ_SONOFF_L1_MODE_COLORFUL 1 +#define PS16DZ_SONOFF_L1_MODE_COLORFUL_GRADIENT 2 +#define PS16DZ_SONOFF_L1_MODE_COLORFUL_BREATH 3 +#define PS16DZ_SONOFF_L1_MODE_DIY_GRADIENT 4 +#define PS16DZ_SONOFF_L1_MODE_DIY_PULSE 5 +#define PS16DZ_SONOFF_L1_MODE_DIY_BREATH 6 +#define PS16DZ_SONOFF_L1_MODE_DIY_STROBE 7 +#define PS16DZ_SONOFF_L1_MODE_RGB_GRADIENT 8 +#define PS16DZ_SONOFF_L1_MODE_RGB_PULSE 9 +#define PS16DZ_SONOFF_L1_MODE_RGB_BREATH 10 +#define PS16DZ_SONOFF_L1_MODE_RGB_STROBE 11 +#define PS16DZ_SONOFF_L1_MODE_SYNC_TO_MUSIC 12 + +#include + +TasmotaSerial *PS16DZSerial = nullptr; + +struct PS16DZ { + char *tx_buffer = nullptr; + char *rx_buffer = nullptr; + int byte_counter = 0; + uint8_t color[3]; + uint8_t dimmer = 0; + bool supports_color = false; + bool switch_state = false; +} Ps16dz; + + + + + +void PS16DZSerialSendTxBuffer(void) +{ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Send %s"), Ps16dz.tx_buffer); + + PS16DZSerial->print(Ps16dz.tx_buffer); + PS16DZSerial->write(0x1B); + PS16DZSerial->flush(); +} + +void PS16DZSerialSendOkCommand(void) +{ + snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("AT+SEND=ok")); + PS16DZSerialSendTxBuffer(); +} + + + + + + +void PS16DZSerialSendUpdateCommand(void) +{ + uint8_t light_state_dimmer = light_state.getDimmer(); + + light_state_dimmer = (light_state_dimmer < 10) ? 10 : light_state_dimmer; + + snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), + LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer); + + if (Ps16dz.supports_color) { + uint8_t light_state_rgb[3]; + light_state.getRGB(&light_state_rgb[0], &light_state_rgb[1], &light_state_rgb[2]); + + snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("%s,\"mode\":%d,\"colorR\":%d,\"colorG\":%d,\"colorB\":%d,\"light_types\":1"), + Ps16dz.tx_buffer, PS16DZ_SONOFF_L1_MODE_COLORFUL, light_state_rgb[0], light_state_rgb[1], light_state_rgb[2]); + } + PS16DZSerialSendTxBuffer(); +} + + + + + +bool PS16DZSerialSendUpdateCommandIfRequired(void) +{ + if (!PS16DZSerial) { return true; } + + bool is_switch_change = (XdrvMailbox.payload != SRC_SWITCH); + bool is_brightness_change = (light_state.getDimmer() != Ps16dz.dimmer); + + uint8_t light_state_rgb[3]; + light_state.getRGB(&light_state_rgb[0], &light_state_rgb[1], &light_state_rgb[2]); + bool is_color_change = (Ps16dz.supports_color && (memcmp(light_state_rgb, Ps16dz.color, 3) != 0)); + + if (is_switch_change || is_brightness_change || is_color_change) { + PS16DZSerialSendUpdateCommand(); + } + + return true; +} + +bool PS16DZModuleSelected(void) +{ + switch (my_module_type) + { + case PS_16_DZ: + light_type = LT_SERIAL1; + break; + + case SONOFF_L1: + light_type = LT_PWM3; + break; + } + + return true; +} + +void PS16DZInit(void) +{ + Ps16dz.supports_color = (light_state.getColorMode() == LCM_RGB); + + Ps16dz.tx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); + if (Ps16dz.tx_buffer != nullptr) { + Ps16dz.rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); + if (Ps16dz.rx_buffer != nullptr) { + PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (PS16DZSerial->begin(19200)) { + if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } + } + } + } +} + +void PS16DZSerialInput(void) +{ + char scmnd[20]; + while (PS16DZSerial->available()) { + yield(); + uint8_t serial_in_byte = PS16DZSerial->read(); + if (serial_in_byte != 0x1B) { + if (Ps16dz.byte_counter >= PS16DZ_BUFFER_SIZE - 1) { + memset(Ps16dz.rx_buffer, 0, PS16DZ_BUFFER_SIZE); + Ps16dz.byte_counter = 0; + } + if (Ps16dz.byte_counter || (!Ps16dz.byte_counter && ('A' == serial_in_byte))) { + Ps16dz.rx_buffer[Ps16dz.byte_counter++] = serial_in_byte; + } + } else { + Ps16dz.rx_buffer[Ps16dz.byte_counter++] = 0x00; + + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Received %s"), Ps16dz.rx_buffer); + + if (!strncmp(Ps16dz.rx_buffer+3, "UPDATE", 6)) { + + char *end_str; + char *string = Ps16dz.rx_buffer+10; + char *token = strtok_r(string, ",", &end_str); + + bool color_updated[3] = { false, false, false }; + memcpy(Ps16dz.color, Settings.light_color, 3); + bool is_switch_change = false; + bool is_color_change = false; + bool is_brightness_change = false; + + while (token != nullptr) { + char* end_token; + char* token2 = strtok_r(token, ":", &end_token); + char* token3 = strtok_r(nullptr, ":", &end_token); + + if (!strncmp(token2, "\"switch\"", 8)) { + Ps16dz.switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Switch %d"), Ps16dz.switch_state); + + is_switch_change = (Ps16dz.switch_state != power); + if (is_switch_change) { + ExecuteCommandPower(1, Ps16dz.switch_state, SRC_SWITCH); + } + } + else if (!strncmp(token2, "\"color", 6)) { + + char color_channel_name = token2[6]; + int color_index; + switch(color_channel_name) + { + case 'R': color_index = 0; + break; + case 'G': color_index = 1; + break; + case 'B': color_index = 2; + break; + } + int color_value = atoi(token3); + Ps16dz.color[color_index] = color_value; + color_updated[color_index] = true; + + bool all_color_channels_updated = color_updated[0] && color_updated[1] && color_updated[2]; + if (all_color_channels_updated) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Color R:%d, G:%d, B:%d"), Ps16dz.color[0], Ps16dz.color[1], Ps16dz.color[2]); + + is_color_change = (memcmp(Ps16dz.color, Settings.light_color, 3) != 0); + } + + if (power && is_color_change) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_COLOR "2 %02x%02x%02x"), Ps16dz.color[0], Ps16dz.color[1], Ps16dz.color[2]); + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + else if (!strncmp(token2, "\"bright\"", 8)) { + Ps16dz.dimmer = atoi(token3); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Brightness %d"), Ps16dz.dimmer); + + is_brightness_change = Ps16dz.dimmer != Settings.light_dimmer; + if (power && (Ps16dz.dimmer > 0) && is_brightness_change) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Ps16dz.dimmer); + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + else if (!strncmp(token2, "\"sequence\"", 10)) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Sequence %s"), token3); + + } + token = strtok_r(nullptr, ",", &end_str); + } + + if (!is_color_change && !is_brightness_change) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Update")); + + PS16DZSerialSendOkCommand(); + } + } + else if (!strncmp(Ps16dz.rx_buffer+3, "SETTING", 7)) { + + + if (!Settings.flag.button_restrict) { + int state = WIFI_MANAGER; + if (!strncmp(Ps16dz.rx_buffer+10, "=exit", 5)) { state = WIFI_RETRY; } + if (state != Settings.sta_config) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " %d"), state); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } + } + memset(Ps16dz.rx_buffer, 0, PS16DZ_BUFFER_SIZE); + Ps16dz.byte_counter = 0; + } + } +} + + + + + +bool Xdrv19(uint8_t function) +{ + bool result = false; + + if ((PS_16_DZ == my_module_type) || (SONOFF_L1 == my_module_type)) { + switch (function) { + case FUNC_LOOP: + if (PS16DZSerial) { PS16DZSerialInput(); } + break; + case FUNC_MODULE_INIT: + result = PS16DZModuleSelected(); + break; + case FUNC_INIT: + PS16DZInit(); + break; + case FUNC_SET_DEVICE_POWER: + case FUNC_SET_CHANNELS: + result = PS16DZSerialSendUpdateCommandIfRequired(); + break; + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_20_hue.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_20_hue.ino" +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) +# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_20_hue.ino" +#define XDRV_20 20 + +const char HUE_RESPONSE[] PROGMEM = + "HTTP/1.1 200 OK\r\n" + "HOST: 239.255.255.250:1900\r\n" + "CACHE-CONTROL: max-age=100\r\n" + "EXT:\r\n" + "LOCATION: http://%s:80/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.17.0\r\n" + "hue-bridgeid: %s\r\n"; +const char HUE_ST1[] PROGMEM = + "ST: upnp:rootdevice\r\n" + "USN: uuid:%s::upnp:rootdevice\r\n" + "\r\n"; +const char HUE_ST2[] PROGMEM = + "ST: uuid:%s\r\n" + "USN: uuid:%s\r\n" + "\r\n"; +const char HUE_ST3[] PROGMEM = + "ST: urn:schemas-upnp-org:device:basic:1\r\n" + "USN: uuid:%s\r\n" + "\r\n"; + +String HueBridgeId(void) +{ + String temp = WiFi.macAddress(); + temp.replace(":", ""); + String bridgeid = temp.substring(0, 6) + "FFFE" + temp.substring(6); + return bridgeid; +} + +String HueSerialnumber(void) +{ + String serial = WiFi.macAddress(); + serial.replace(":", ""); + serial.toLowerCase(); + return serial; +} + +String HueUuid(void) +{ + String uuid = F("f6543a06-da50-11ba-8d8f-"); + uuid += HueSerialnumber(); + return uuid; +} + +void HueRespondToMSearch(void) +{ + char message[TOPSZ]; + + TickerMSearch.detach(); + if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { + char response[320]; + snprintf_P(response, sizeof(response), HUE_RESPONSE, WiFi.localIP().toString().c_str(), HueBridgeId().c_str()); + int len = strlen(response); + + snprintf_P(response + len, sizeof(response) - len, HUE_ST1, HueUuid().c_str()); + PortUdp.write(response); + PortUdp.endPacket(); + + snprintf_P(response + len, sizeof(response) - len, HUE_ST2, HueUuid().c_str(), HueUuid().c_str()); + PortUdp.write(response); + PortUdp.endPacket(); + + snprintf_P(response + len, sizeof(response) - len, HUE_ST3, HueUuid().c_str()); + PortUdp.write(response); + 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)); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"), + message, udp_remote_ip.toString().c_str(), udp_remote_port); + + udp_response_mutex = false; +} + + + + + +const char HUE_DESCRIPTION_XML[] PROGMEM = + "" + "" + "" + "1" + "0" + "" + + "http://{x1:80/" + "" + "urn:schemas-upnp-org:device:Basic:1" + "Amazon-Echo-HA-Bridge ({x1)" + + "Royal Philips Electronics" + "Philips hue Personal Wireless Lighting" + "Philips hue bridge 2012" + "929000226503" + "{x3" + "uuid:{x2" + "" + "\r\n" + "\r\n"; +const char HUE_LIGHTS_STATUS_JSON1[] PROGMEM = + "{\"on\":{state}," + "{light_status}" + "\"alert\":\"none\"," + "\"effect\":\"none\"," + "\"reachable\":true}"; +const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = + ",\"type\":\"Extended color light\"," + "\"name\":\"{j1\"," + "\"modelid\":\"LCT007\"," + "\"uniqueid\":\"{j2\"," + "\"swversion\":\"5.50.1.19085\"}"; +const char HUE_GROUP0_STATUS_JSON[] PROGMEM = + "{\"name\":\"Group 0\"," + "\"lights\":[{l1]," + "\"type\":\"LightGroup\"," + "\"action\":"; + +const char HueConfigResponse_JSON[] PROGMEM = + "{\"name\":\"Philips hue\"," + "\"mac\":\"{ma\"," + "\"dhcp\":true," + "\"ipaddress\":\"{ip\"," + "\"netmask\":\"{ms\"," + "\"gateway\":\"{gw\"," + "\"proxyaddress\":\"none\"," + "\"proxyport\":0," + "\"bridgeid\":\"{br\"," + "\"UTC\":\"{dt\"," + "\"whitelist\":{\"{id\":{" + "\"last use date\":\"{dt\"," + "\"create date\":\"{dt\"," + "\"name\":\"Remote\"}}," + "\"swversion\":\"01041302\"," + "\"apiversion\":\"1.17.0\"," + "\"swupdate\":{\"updatestate\":0,\"url\":\"\",\"text\":\"\",\"notify\": false}," + "\"linkbutton\":false," + "\"portalservices\":false" + "}"; +const char HUE_LIGHT_RESPONSE_JSON[] PROGMEM = + "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; +const char HUE_ERROR_JSON[] PROGMEM = + "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; + + + +String GetHueDeviceId(uint8_t id) +{ + String deviceid = WiFi.macAddress() + F(":00:11-") + String(id); + deviceid.toLowerCase(); + return deviceid; +} + +String GetHueUserId(void) +{ + char userid[7]; + + snprintf_P(userid, sizeof(userid), PSTR("%03x"), ESP.getChipId()); + return String(userid); +} + +void HandleUpnpSetupHue(void) +{ + 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", HueUuid()); + description_xml.replace("{x3", HueSerialnumber()); + WSSend(200, CT_XML, description_xml); +} + +void HueNotImplemented(String *path) +{ + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API_NOT_IMPLEMENTED " (%s)"), path->c_str()); + + WSSend(200, CT_JSON, "{}"); +} + +void HueConfigResponse(String *response) +{ + *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", GetDateAndTime(DT_UTC)); + response->replace("{id", GetHueUserId()); +} + +void HueConfig(String *path) +{ + String response = ""; + HueConfigResponse(&response); + WSSend(200, CT_JSON, response); +} + + + +bool g_gotct = false; + + + + +uint16_t prev_hue = 0; +uint8_t prev_sat = 0; +uint8_t prev_bri = 254; +uint16_t prev_ct = 254; +char prev_x_str[24] = "\0"; +char prev_y_str[24] = "\0"; + +uint8_t getLocalLightSubtype(uint8_t device) { + if (light_type) { + if (device >= Light.device) { + if (Settings.flag3.pwm_multi_channels) { + return LST_SINGLE; + } else { + return Light.subtype; + } + } else { + return LST_NONE; + } + } else { + return LST_NONE; + } +} + +void HueLightStatus1(uint8_t device, String *response) +{ + uint16_t ct = 0; + uint8_t color_mode; + String light_status = ""; + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = 254; + uint32_t echo_gen = findEchoGeneration(); + + + uint8_t local_light_subtype = getLocalLightSubtype(device); + + bri = LightGetBri(device); + if (bri > 254) bri = 254; + if (bri < 1) bri = 1; + + if (light_type) { + light_state.getHSB(&hue, &sat, nullptr); + + if ((bri > prev_bri ? bri - prev_bri : prev_bri - bri) < 1) + bri = prev_bri; + + if (sat > 254) sat = 254; + if ((sat > prev_sat ? sat - prev_sat : prev_sat - sat) < 1) { + sat = prev_sat; + } else { + prev_x_str[0] = prev_y_str[0] = 0; + } + + hue = changeUIntScale(hue, 0, 359, 0, 65535); + if ((hue > prev_hue ? hue - prev_hue : prev_hue - hue) < 400) { + hue = prev_hue; + } else { + prev_x_str[0] = prev_y_str[0] = 0; + } + + color_mode = light_state.getColorMode(); + ct = light_state.getCT(); + if (LCM_RGB == color_mode) { g_gotct = false; } + if (LCM_CT == color_mode) { g_gotct = true; } + + + + if ((ct > prev_ct ? ct - prev_ct : prev_ct - ct) < 1) + ct = prev_ct; + + + + } + + *response += FPSTR(HUE_LIGHTS_STATUS_JSON1); + response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); + + if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { + light_status += "\"bri\":"; + light_status += String(bri); + light_status += ","; + } + if (LST_COLDWARM <= local_light_subtype) { + light_status += F("\"colormode\":\""); + light_status += (g_gotct ? "ct" : "hs"); + light_status += "\","; + } + if (LST_RGB <= local_light_subtype) { + if (prev_x_str[0] && prev_y_str[0]) { + light_status += "\"xy\":["; + light_status += prev_x_str; + light_status += ","; + light_status += prev_y_str; + light_status += "],"; + } else { + float x, y; + light_state.getXY(&x, &y); + light_status += "\"xy\":["; + light_status += String(x, 5); + light_status += ","; + light_status += String(y, 5); + light_status += "],"; + } + light_status += "\"hue\":"; + light_status += String(hue); + light_status += ","; + + light_status += "\"sat\":"; + light_status += String(sat); + light_status += ","; + } + if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { + light_status += "\"ct\":"; + light_status += String(ct > 0 ? ct : 284); + light_status += ","; + } + response->replace("{light_status}", light_status); +} + +void HueLightStatus2(uint8_t device, String *response) +{ + *response += FPSTR(HUE_LIGHTS_STATUS_JSON2); + if (device <= MAX_FRIENDLYNAMES) { + response->replace("{j1", Settings.friendlyname[device-1]); + } else { + char fname[33]; + strcpy(fname, Settings.friendlyname[MAX_FRIENDLYNAMES-1]); + uint32_t fname_len = strlen(fname); + if (fname_len >= 33-3) { + fname[33-3] = 0x00; + fname_len = 33-3; + } + fname[fname_len++] = '-'; + fname[fname_len++] = '0' + device - MAX_FRIENDLYNAMES; + response->replace("{j1", fname); + } + response->replace("{j2", GetHueDeviceId(device)); +} + + + + +uint32_t EncodeLightId(uint8_t relay_id) +{ + uint8_t mac[6]; + WiFi.macAddress(mac); + uint32_t id = 0; + + if (relay_id >= 32) { + relay_id = 0; + } + if (relay_id > 15) { + id = (1 << 28); + } + + id |= (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4) | (relay_id & 0xF); + return id; +} + + + +uint32_t DecodeLightId(uint32_t hue_id) { + uint8_t relay_id = hue_id & 0xF; + if (hue_id & (1 << 28)) { + relay_id += 16; + } + if (0 == relay_id) { + relay_id = 32; + } + return relay_id; +} + +static const char * FIRST_GEN_UA[] = { + "AEOBC", +}; + + +uint32_t findEchoGeneration(void) { + + String user_agent = WebServer->header("User-Agent"); + uint32_t gen = 2; + + for (uint32_t i = 0; i < sizeof(FIRST_GEN_UA)/sizeof(char*); i++) { + if (user_agent.indexOf(FIRST_GEN_UA[i]) >= 0) { + gen = 1; + break; + } + } + if (0 == user_agent.length()) { + gen = 1; + } + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, D_LOG_HTTP D_HUE " User-Agent: %s, gen=%d", user_agent.c_str(), gen); + + return gen; +} + +void HueGlobalConfig(String *path) +{ + String response; + uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + + path->remove(0,1); + response = F("{\"lights\":{\""); + for (uint32_t i = 1; i <= maxhue; i++) { + response += EncodeLightId(i); + response += F("\":{\"state\":"); + HueLightStatus1(i, &response); + HueLightStatus2(i, &response); + if (i < maxhue) { + response += ",\""; + } + } + response += F("},\"groups\":{},\"schedules\":{},\"config\":"); + HueConfigResponse(&response); + response += "}"; + WSSend(200, CT_JSON, response); +} + +void HueAuthentication(String *path) +{ + char response[38]; + + snprintf_P(response, sizeof(response), PSTR("[{\"success\":{\"username\":\"%s\"}}]"), GetHueUserId().c_str()); + WSSend(200, CT_JSON, response); +} + +void HueLights(String *path) +{ + + + + String response; + int code = 200; + uint16_t tmp = 0; + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = 254; + uint16_t ct = 0; + bool resp = false; + bool on = false; + bool change = false; + uint8_t device = 1; + uint8_t local_light_subtype = Light.subtype; + uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + + path->remove(0,path->indexOf("/lights")); + if (path->endsWith("/lights")) { + response = "{\""; + for (uint32_t i = 1; i <= maxhue; i++) { + response += EncodeLightId(i); + response += F("\":{\"state\":"); + HueLightStatus1(i, &response); + HueLightStatus2(i, &response); + if (i < maxhue) { + response += ",\""; + } + } + response += "}"; + } + else if (path->endsWith("/state")) { + path->remove(0,8); + path->remove(path->indexOf("/state")); + device = DecodeLightId(atoi(path->c_str())); + if ((device < 1) || (device > maxhue)) { + device = 1; + } + local_light_subtype = getLocalLightSubtype(device); + + if (WebServer->args()) { + response = "["; + + StaticJsonBuffer<400> jsonBuffer; + JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); + if (hue_json.containsKey("on")) { + + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "on"); + + on = hue_json["on"]; + switch(on) + { + case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); + response.replace("{re", "false"); + break; + case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); + response.replace("{re", "true"); + break; + default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); + break; + } + resp = true; + } + + if (light_type && (local_light_subtype >= LST_SINGLE)) { + if (!Settings.flag3.pwm_multi_channels) { + light_state.getHSB(&hue, &sat, nullptr); + bri = light_state.getBri(); + ct = light_state.getCT(); + uint8_t color_mode = light_state.getColorMode(); + if (LCM_RGB == color_mode) { g_gotct = false; } + if (LCM_CT == color_mode) { g_gotct = true; } + + } else { + bri = LightGetBri(device); + } + } + prev_x_str[0] = prev_y_str[0] = 0; + + if (hue_json.containsKey("bri")) { + tmp = hue_json["bri"]; + prev_bri = bri = tmp; + + if (254 <= bri) { bri = 255; } + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "bri"); + response.replace("{re", String(tmp)); + if (LST_SINGLE <= Light.subtype) { + change = true; + } + resp = true; + } + + + if (hue_json.containsKey("xy")) { + float x, y; + x = hue_json["xy"][0]; + y = hue_json["xy"][1]; + const String &x_str = hue_json["xy"][0]; + const String &y_str = hue_json["xy"][1]; + x_str.toCharArray(prev_x_str, sizeof(prev_x_str)); + y_str.toCharArray(prev_y_str, sizeof(prev_y_str)); + + uint8_t rr,gg,bb; + LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); + LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); + prev_hue = changeUIntScale(hue, 0, 359, 0, 65535); + prev_sat = (sat > 254 ? 254 : sat); + + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "xy"); + response.replace("{re", "[" + x_str + "," + y_str + "]"); + g_gotct = false; + resp = true; + change = true; + } + if (hue_json.containsKey("hue")) { + tmp = hue_json["hue"]; + prev_hue = tmp; + + hue = changeUIntScale(tmp, 0, 65535, 0, 359); + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "hue"); + response.replace("{re", String(tmp)); + if (LST_RGB <= Light.subtype) { + g_gotct = false; + change = true; + } + resp = true; + } + if (hue_json.containsKey("sat")) { + tmp = hue_json["sat"]; + prev_sat = sat = tmp; + + if (254 <= sat) { sat = 255; } + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "sat"); + response.replace("{re", String(tmp)); + if (LST_RGB <= Light.subtype) { + g_gotct = false; + change = true; + } + resp = true; + } + if (hue_json.containsKey("ct")) { + ct = hue_json["ct"]; + prev_ct = ct; + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "ct"); + response.replace("{re", String(ct)); + if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { + g_gotct = true; + change = true; + } + resp = true; + } + if (change) { + if (light_type && (local_light_subtype > LST_NONE)) { + if (!Settings.flag3.pwm_multi_channels) { + if (g_gotct) { + light_controller.changeCTB(ct, bri); + } else { + light_controller.changeHSB(hue, sat, bri); + } + LightPreparePower(); + } else { + LightSetBri(device, bri); + } + if (LST_COLDWARM <= local_light_subtype) { + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR)); + } else { + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_DIMMER)); + } + XdrvRulesProcess(); + } + change = false; + } + response += "]"; + if (2 == response.length()) { + response = FPSTR(HUE_ERROR_JSON); + } + } + else { + response = FPSTR(HUE_ERROR_JSON); + } + } + else if(path->indexOf("/lights/") >= 0) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "/lights path=%s", path->c_str()); + path->remove(0,8); + device = DecodeLightId(atoi(path->c_str())); + if ((device < 1) || (device > maxhue)) { + device = 1; + } + response += F("{\"state\":"); + HueLightStatus1(device, &response); + HueLightStatus2(device, &response); + } + else { + response = "{}"; + code = 406; + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); + WSSend(code, CT_JSON, response); +} + +void HueGroups(String *path) +{ + + + + String response = "{}"; + uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + + if (path->endsWith("/0")) { + response = FPSTR(HUE_GROUP0_STATUS_JSON); + String lights = F("\"1\""); + for (uint32_t i = 2; i <= maxhue; i++) { + lights += ",\""; + lights += EncodeLightId(i); + lights += "\""; + } + response.replace("{l1", lights); + HueLightStatus1(1, &response); + response += F("}"); + } + + WSSend(200, CT_JSON, response); +} + +void HandleHueApi(String *path) +{ +# 723 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_20_hue.ino" + uint8_t args = 0; + + path->remove(0, 4); + uint16_t apilen = path->length(); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API " (%s)"), path->c_str()); + for (args = 0; args < WebServer->args(); args++) { + String json = WebServer->arg(args); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_POST_ARGS " (%s)"), json.c_str()); + } + + if (path->endsWith("/invalid/")) {} + else if (!apilen) HueAuthentication(path); + else if (path->endsWith("/")) HueAuthentication(path); + 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 if (path->endsWith("/resourcelinks")) HueNotImplemented(path); + else HueGlobalConfig(path); +} + + + + + +bool Xdrv20(uint8_t function) +{ + bool result = false; + + if (devices_present && (EMUL_HUE == Settings.flag2.emulation)) { + switch (function) { + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/description.xml", HandleUpnpSetupHue); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_21_wemo.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_21_wemo.ino" +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined (USE_EMULATION_WEMO) + + + + +#define XDRV_21 21 + +const char WEMO_MSEARCH[] PROGMEM = + "HTTP/1.1 200 OK\r\n" + "CACHE-CONTROL: max-age=86400\r\n" + "DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n" + "EXT:\r\n" + "LOCATION: http://%s: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: %s\r\n" + "USN: uuid:%s::%s\r\n" + "X-User-Agent: redsonic\r\n" + "\r\n"; + +String WemoSerialnumber(void) +{ + char serial[16]; + + snprintf_P(serial, sizeof(serial), PSTR("201612K%08X"), ESP.getChipId()); + return String(serial); +} + +String WemoUuid(void) +{ + char uuid[27]; + + snprintf_P(uuid, sizeof(uuid), PSTR("Socket-1_0-%s"), WemoSerialnumber().c_str()); + return String(uuid); +} + +void WemoRespondToMSearch(int echo_type) +{ + char message[TOPSZ]; + + TickerMSearch.detach(); + if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { + char type[24]; + if (1 == echo_type) { + strcpy_P(type, URN_BELKIN_DEVICE_CAP); + } else { + strcpy_P(type, UPNP_ROOTDEVICE); + } + char response[400]; + snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), type, WemoUuid().c_str(), type); + PortUdp.write(response); + PortUdp.endPacket(); + snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT)); + } else { + snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"), + echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port); + + udp_response_mutex = false; +} + + + + + +const char WEMO_EVENTSERVICE_XML[] PROGMEM = + "" + "" + "" + "SetBinaryState" + "" + "" + "" + "BinaryState" + "BinaryState" + "in" + "" + "" + "" + "" + "GetBinaryState" + "" + "" + "" + "BinaryState" + "BinaryState" + "out" + "" + "" + "" + "" + "" + "" + "BinaryState" + "bool" + "0" + "" + "" + "level" + "string" + "0" + "" + "" + "\r\n\r\n"; + +const char WEMO_METASERVICE_XML[] PROGMEM = + "" + "" + "1" + "0" + "" + "" + "" + "GetMetaInfo" + "" + "" + "GetMetaInfo" + "MetaInfo" + "in" + "" + "" + "" + "" + "" + "MetaInfo" + "string" + "0" + "" + "" + "\r\n\r\n"; + +const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = + "" + "" + "" + "%d" + "" + "" + "\r\n"; + +const char WEMO_SETUP_XML[] PROGMEM = + "" + "" + "" + "urn:Belkin:device:controllee:1" + "{x1" + "Belkin International Inc." + "Socket" + "3.1415" + "uuid:{x2" + "{x3" + "0" + "" + "" + "urn:Belkin:service:basicevent:1" + "urn:Belkin:serviceId:basicevent1" + "/upnp/control/basicevent1" + "/upnp/event/basicevent1" + "/eventservice.xml" + "" + "" + "urn:Belkin:service:metainfo:1" + "urn:Belkin:serviceId:metainfo1" + "/upnp/control/metainfo1" + "/upnp/event/metainfo1" + "/metainfoservice.xml" + "" + "" + "" + "\r\n"; + + + +void HandleUpnpEvent(void) +{ + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); + + char event[500]; + strlcpy(event, WebServer->arg(0).c_str(), sizeof(event)); + + + + + char state = 'G'; + if (strstr_P(event, PSTR("SetBinaryState")) != nullptr) { + state = 'S'; + uint8_t power = POWER_TOGGLE; + if (strstr_P(event, PSTR("State>10on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); + WebServer->on("/eventservice.xml", HandleUpnpService); + WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); + WebServer->on("/setup.xml", HandleUpnpSetupWemo); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_22_sonoff_ifan.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_22_sonoff_ifan.ino" +#ifdef USE_SONOFF_IFAN + + + + +#define XDRV_22 22 + +const uint8_t MAX_FAN_SPEED = 4; + +const uint8_t kIFan02Speed[MAX_FAN_SPEED] = { 0x00, 0x01, 0x03, 0x05 }; +const uint8_t kIFan03Speed[MAX_FAN_SPEED +2] = { 0x00, 0x01, 0x03, 0x04, 0x05, 0x06 }; +const uint8_t kIFan03Sequence[MAX_FAN_SPEED][MAX_FAN_SPEED] = {{0, 2, 2, 2}, {0, 1, 2, 4}, {1, 1, 2, 5}, {4, 4, 5, 3}}; + +const char kSonoffIfanCommands[] PROGMEM = "|" + D_CMND_FANSPEED; + +void (* const SonoffIfanCommand[])(void) PROGMEM = + { &CmndFanspeed }; + +uint8_t ifan_fanspeed_timer = 0; +uint8_t ifan_fanspeed_goal = 0; +bool ifan_receive_flag = false; +bool ifan_restart_flag = true; + + + +bool IsModuleIfan() +{ + return ((SONOFF_IFAN02 == my_module_type) || (SONOFF_IFAN03 == my_module_type)); +} + +uint8_t MaxFanspeed(void) +{ + return MAX_FAN_SPEED; +} + +uint8_t GetFanspeed(void) +{ + if (ifan_fanspeed_timer) { + return ifan_fanspeed_goal; + } else { + + + + + + + uint8_t fanspeed = (uint8_t)(power &0xF) >> 1; + if (fanspeed) { fanspeed = (fanspeed >> 1) +1; } + return fanspeed; + } +} + + + +void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence) +{ + ifan_fanspeed_timer = 0; + ifan_fanspeed_goal = fanspeed; + + uint8_t fanspeed_now = GetFanspeed(); + + if (fanspeed == fanspeed_now) { return; } + + uint8_t fans = kIFan02Speed[fanspeed]; + if (SONOFF_IFAN03 == my_module_type) { + if (sequence) { + fanspeed = kIFan03Sequence[fanspeed_now][ifan_fanspeed_goal]; + if (fanspeed != ifan_fanspeed_goal) { + if (0 == fanspeed_now) { + ifan_fanspeed_timer = 20; + } else { + ifan_fanspeed_timer = 2; + } + } + } + fans = kIFan03Speed[fanspeed]; + } + for (uint32_t i = 2; i < 5; i++) { + uint8_t state = (fans &1) + POWER_OFF_NO_STATE; + ExecuteCommandPower(i, state, SRC_IGNORE); + fans >>= 1; + } + +#ifdef USE_DOMOTICZ + if (sequence) { DomoticzUpdateFanState(); } +#endif +} + + + +void SonoffIfanReceived(void) +{ + char svalue[32]; + + uint8_t mode = serial_in_buffer[3]; + uint8_t action = serial_in_buffer[6]; + + if (4 == mode) { + if (action < 4) { + + + + + if (action != GetFanspeed()) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), action); + ExecuteCommand(svalue, SRC_REMOTE); +#ifdef USE_BUZZER + BuzzerEnabledBeep(1); +#endif + } + } else { + + ExecuteCommandPower(1, POWER_TOGGLE, SRC_REMOTE); + } + } + if (6 == mode) { + + Settings.flag3.buzzer_enable = !Settings.flag3.buzzer_enable; + } + if (7 == mode) { + +#ifdef USE_BUZZER + BuzzerEnabledBeep(3); +#endif + } + + + + serial_in_buffer[5] = 0; + serial_in_buffer[6] = 0; + for (uint32_t i = 0; i < 7; i++) { + if ((i > 1) && (i < 6)) { serial_in_buffer[6] += serial_in_buffer[i]; } + Serial.write(serial_in_buffer[i]); + } +} + +bool SonoffIfanSerialInput(void) +{ + if (SONOFF_IFAN03 == my_module_type) { + if (0xAA == serial_in_byte) { + serial_in_byte_counter = 0; + ifan_receive_flag = true; + } + if (ifan_receive_flag) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (serial_in_byte_counter == 8) { +# 176 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_22_sonoff_ifan.ino" + AddLogSerial(LOG_LEVEL_DEBUG); + uint8_t crc = 0; + for (uint32_t i = 2; i < 7; i++) { + crc += serial_in_buffer[i]; + } + if (crc == serial_in_buffer[7]) { + SonoffIfanReceived(); + ifan_receive_flag = false; + return true; + } + } + serial_in_byte = 0; + } + return false; + } +} + + + + + +void CmndFanspeed(void) +{ + if (XdrvMailbox.data_len > 0) { + if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (int16_t)GetFanspeed() -1; + if (XdrvMailbox.payload < 0) { XdrvMailbox.payload = MAX_FAN_SPEED -1; } + } + else if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = GetFanspeed() +1; + if (XdrvMailbox.payload > MAX_FAN_SPEED -1) { XdrvMailbox.payload = 0; } + } + } + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_FAN_SPEED)) { + SonoffIFanSetFanspeed(XdrvMailbox.payload, true); + } + ResponseCmndNumber(GetFanspeed()); +} + + + +bool SonoffIfanInit(void) +{ + if (SONOFF_IFAN03 == my_module_type) { + Settings.flag.mqtt_serial = 0; + baudrate = 9600; + SetSeriallog(LOG_LEVEL_NONE); + } + return false; +} + +void SonoffIfanUpdate(void) +{ + if (SONOFF_IFAN03 == my_module_type) { + if (ifan_fanspeed_timer) { + ifan_fanspeed_timer--; + if (!ifan_fanspeed_timer) { + SonoffIFanSetFanspeed(ifan_fanspeed_goal, false); + } + } + } + + if (ifan_restart_flag && (4 == uptime) && (SONOFF_IFAN02 == my_module_type)) { + ifan_restart_flag = false; + SetDevicePower(1, SRC_RETRY); + SetDevicePower(power, SRC_RETRY); + } +} + + + + + +bool Xdrv22(uint8_t function) +{ + bool result = false; + + if (IsModuleIfan()) { + switch (function) { + case FUNC_EVERY_250_MSECOND: + SonoffIfanUpdate(); + break; + case FUNC_SERIAL: + result = SonoffIfanSerialInput(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kSonoffIfanCommands, SonoffIfanCommand); + break; + case FUNC_MODULE_INIT: + result = SonoffIfanInit(); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_0_constants.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_0_constants.ino" +#ifdef USE_ZIGBEE + +typedef uint64_t Z_IEEEAddress; +typedef uint16_t Z_ShortAddress; + +enum ZnpCommandType { + Z_POLL = 0x00, + Z_SREQ = 0x20, + Z_AREQ = 0x40, + Z_SRSP = 0x60 +}; + +enum ZnpSubsystem { + Z_RPC_Error = 0x00, + Z_SYS = 0x01, + Z_MAC = 0x02, + Z_NWK = 0x03, + Z_AF = 0x04, + Z_ZDO = 0x05, + Z_SAPI = 0x06, + Z_UTIL = 0x07, + Z_DEBUG = 0x08, + Z_APP = 0x09 +}; + + +enum SysCommand { + SYS_RESET = 0x00, + SYS_PING = 0x01, + SYS_VERSION = 0x02, + SYS_SET_EXTADDR = 0x03, + SYS_GET_EXTADDR = 0x04, + SYS_RAM_READ = 0x05, + SYS_RAM_WRITE = 0x06, + SYS_OSAL_NV_ITEM_INIT = 0x07, + SYS_OSAL_NV_READ = 0x08, + SYS_OSAL_NV_WRITE = 0x09, + SYS_OSAL_START_TIMER = 0x0A, + SYS_OSAL_STOP_TIMER = 0x0B, + SYS_RANDOM = 0x0C, + SYS_ADC_READ = 0x0D, + SYS_GPIO = 0x0E, + SYS_STACK_TUNE = 0x0F, + SYS_SET_TIME = 0x10, + SYS_GET_TIME = 0x11, + SYS_OSAL_NV_DELETE = 0x12, + SYS_OSAL_NV_LENGTH = 0x13, + SYS_TEST_RF = 0x40, + SYS_TEST_LOOPBACK = 0x41, + SYS_RESET_IND = 0x80, + SYS_OSAL_TIMER_EXPIRED = 0x81, +}; + +enum SapiCommand { + SAPI_START_REQUEST = 0x00, + SAPI_BIND_DEVICE = 0x01, + SAPI_ALLOW_BIND = 0x02, + SAPI_SEND_DATA_REQUEST = 0x03, + SAPI_READ_CONFIGURATION = 0x04, + SAPI_WRITE_CONFIGURATION = 0x05, + SAPI_GET_DEVICE_INFO = 0x06, + SAPI_FIND_DEVICE_REQUEST = 0x07, + SAPI_PERMIT_JOINING_REQUEST = 0x08, + SAPI_SYSTEM_RESET = 0x09, + SAPI_START_CONFIRM = 0x80, + SAPI_BIND_CONFIRM = 0x81, + SAPI_ALLOW_BIND_CONFIRM = 0x82, + SAPI_SEND_DATA_CONFIRM = 0x83, + SAPI_FIND_DEVICE_CONFIRM = 0x85, + SAPI_RECEIVE_DATA_INDICATION = 0x87, +}; +enum Z_configuration { + CONF_EXTADDR = 0x01, + CONF_BOOTCOUNTER = 0x02, + CONF_STARTUP_OPTION = 0x03, + CONF_START_DELAY = 0x04, + CONF_NIB = 0x21, + CONF_DEVICE_LIST = 0x22, + CONF_ADDRMGR = 0x23, + CONF_POLL_RATE = 0x24, + CONF_QUEUED_POLL_RATE = 0x25, + CONF_RESPONSE_POLL_RATE = 0x26, + CONF_REJOIN_POLL_RATE = 0x27, + CONF_DATA_RETRIES = 0x28, + CONF_POLL_FAILURE_RETRIES = 0x29, + CONF_STACK_PROFILE = 0x2A, + CONF_INDIRECT_MSG_TIMEOUT = 0x2B, + CONF_ROUTE_EXPIRY_TIME = 0x2C, + CONF_EXTENDED_PAN_ID = 0x2D, + CONF_BCAST_RETRIES = 0x2E, + CONF_PASSIVE_ACK_TIMEOUT = 0x2F, + CONF_BCAST_DELIVERY_TIME = 0x30, + CONF_NWK_MODE = 0x31, + CONF_CONCENTRATOR_ENABLE = 0x32, + CONF_CONCENTRATOR_DISCOVERY = 0x33, + CONF_CONCENTRATOR_RADIUS = 0x34, + CONF_CONCENTRATOR_RC = 0x36, + CONF_NWK_MGR_MODE = 0x37, + CONF_SRC_RTG_EXPIRY_TIME = 0x38, + CONF_ROUTE_DISCOVERY_TIME = 0x39, + CONF_NWK_ACTIVE_KEY_INFO = 0x3A, + CONF_NWK_ALTERN_KEY_INFO = 0x3B, + CONF_ROUTER_OFF_ASSOC_CLEANUP = 0x3C, + CONF_NWK_LEAVE_REQ_ALLOWED = 0x3D, + CONF_NWK_CHILD_AGE_ENABLE = 0x3E, + CONF_DEVICE_LIST_KA_TIMEOUT = 0x3F, + CONF_BINDING_TABLE = 0x41, + CONF_GROUP_TABLE = 0x42, + CONF_APS_FRAME_RETRIES = 0x43, + CONF_APS_ACK_WAIT_DURATION = 0x44, + CONF_APS_ACK_WAIT_MULTIPLIER = 0x45, + CONF_BINDING_TIME = 0x46, + CONF_APS_USE_EXT_PANID = 0x47, + CONF_APS_USE_INSECURE_JOIN = 0x48, + CONF_COMMISSIONED_NWK_ADDR = 0x49, + CONF_APS_NONMEMBER_RADIUS = 0x4B, + CONF_APS_LINK_KEY_TABLE = 0x4C, + CONF_APS_DUPREJ_TIMEOUT_INC = 0x4D, + CONF_APS_DUPREJ_TIMEOUT_COUNT = 0x4E, + CONF_APS_DUPREJ_TABLE_SIZE = 0x4F, + CONF_DIAGNOSTIC_STATS = 0x50, + CONF_SECURITY_LEVEL = 0x61, + CONF_PRECFGKEY = 0x62, + CONF_PRECFGKEYS_ENABLE = 0x63, + CONF_SECURITY_MODE = 0x64, + CONF_SECURE_PERMIT_JOIN = 0x65, + CONF_APS_LINK_KEY_TYPE = 0x66, + CONF_APS_ALLOW_R19_SECURITY = 0x67, + CONF_IMPLICIT_CERTIFICATE = 0x69, + CONF_DEVICE_PRIVATE_KEY = 0x6A, + CONF_CA_PUBLIC_KEY = 0x6B, + CONF_KE_MAX_DEVICES = 0x6C, + CONF_USE_DEFAULT_TCLK = 0x6D, + CONF_RNG_COUNTER = 0x6F, + CONF_RANDOM_SEED = 0x70, + CONF_TRUSTCENTER_ADDR = 0x71, + CONF_USERDESC = 0x81, + CONF_NWKKEY = 0x82, + CONF_PANID = 0x83, + CONF_CHANLIST = 0x84, + CONF_LEAVE_CTRL = 0x85, + CONF_SCAN_DURATION = 0x86, + CONF_LOGICAL_TYPE = 0x87, + CONF_NWKMGR_MIN_TX = 0x88, + CONF_NWKMGR_ADDR = 0x89, + CONF_ZDO_DIRECT_CB = 0x8F, + CONF_TCLK_TABLE_START = 0x0101, + ZNP_HAS_CONFIGURED = 0xF00 +}; +# 208 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_0_constants.ino" +enum Z_Status { + Z_Success = 0x00, + Z_Failure = 0x01, + Z_InvalidParameter = 0x02, + Z_MemError = 0x03, + Z_Created = 0x09, + Z_BufferFull = 0x11 +}; + +enum Z_App_Profiles { + Z_PROF_IPM = 0x0101, + Z_PROF_HA = 0x0104, + Z_PROF_CBA = 0x0105, + Z_PROF_TA = 0x0107, + Z_PROF_PHHC = 0x0108, + Z_PROF_AMI = 0x0109, +}; + +enum Z_Device_Ids { + Z_DEVID_CONF_TOOL = 0x0005, +# 260 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_0_constants.ino" +}; +# 273 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_0_constants.ino" +enum AfCommand : uint8_t { + AF_REGISTER = 0x00, + AF_DATA_REQUEST = 0x01, + AF_DATA_REQUEST_EXT = 0x02, + AF_DATA_REQUEST_SRC_RTG = 0x03, + AF_INTER_PAN_CTL = 0x10, + AF_DATA_STORE = 0x11, + AF_DATA_RETRIEVE = 0x12, + AF_APSF_CONFIG_SET = 0x13, + AF_DATA_CONFIRM = 0x80, + AF_REFLECT_ERROR = 0x83, + AF_INCOMING_MSG = 0x81, + AF_INCOMING_MSG_EXT = 0x82 +}; + + +enum : uint8_t { + ZDO_NWK_ADDR_REQ = 0x00, + ZDO_IEEE_ADDR_REQ = 0x01, + ZDO_NODE_DESC_REQ = 0x02, + ZDO_POWER_DESC_REQ = 0x03, + ZDO_SIMPLE_DESC_REQ = 0x04, + ZDO_ACTIVE_EP_REQ = 0x05, + ZDO_MATCH_DESC_REQ = 0x06, + ZDO_COMPLEX_DESC_REQ = 0x07, + ZDO_USER_DESC_REQ = 0x08, + ZDO_DEVICE_ANNCE = 0x0A, + ZDO_USER_DESC_SET = 0x0B, + ZDO_SERVER_DISC_REQ = 0x0C, + ZDO_END_DEVICE_BIND_REQ = 0x20, + ZDO_BIND_REQ = 0x21, + ZDO_UNBIND_REQ = 0x22, + ZDO_SET_LINK_KEY = 0x23, + ZDO_REMOVE_LINK_KEY = 0x24, + ZDO_GET_LINK_KEY = 0x25, + ZDO_MGMT_NWK_DISC_REQ = 0x30, + ZDO_MGMT_LQI_REQ = 0x31, + ZDO_MGMT_RTQ_REQ = 0x32, + ZDO_MGMT_BIND_REQ = 0x33, + ZDO_MGMT_LEAVE_REQ = 0x34, + ZDO_MGMT_DIRECT_JOIN_REQ = 0x35, + ZDO_MGMT_PERMIT_JOIN_REQ = 0x36, + ZDO_MGMT_NWK_UPDATE_REQ = 0x37, + ZDO_MSG_CB_REGISTER = 0x3E, + ZDO_MGS_CB_REMOVE = 0x3F, + ZDO_STARTUP_FROM_APP = 0x40, + ZDO_AUTO_FIND_DESTINATION = 0x41, + ZDO_EXT_REMOVE_GROUP = 0x47, + ZDO_EXT_REMOVE_ALL_GROUP = 0x48, + ZDO_EXT_FIND_ALL_GROUPS_ENDPOINT = 0x49, + ZDO_EXT_FIND_GROUP = 0x4A, + ZDO_EXT_ADD_GROUP = 0x4B, + ZDO_EXT_COUNT_ALL_GROUPS = 0x4C, + ZDO_NWK_ADDR_RSP = 0x80, + ZDO_IEEE_ADDR_RSP = 0x81, + ZDO_NODE_DESC_RSP = 0x82, + ZDO_POWER_DESC_RSP = 0x83, + ZDO_SIMPLE_DESC_RSP = 0x84, + ZDO_ACTIVE_EP_RSP = 0x85, + ZDO_MATCH_DESC_RSP = 0x86, + ZDO_COMPLEX_DESC_RSP = 0x87, + ZDO_USER_DESC_RSP = 0x88, + ZDO_USER_DESC_CONF = 0x89, + ZDO_SERVER_DISC_RSP = 0x8A, + ZDO_END_DEVICE_BIND_RSP = 0xA0, + ZDO_BIND_RSP = 0xA1, + ZDO_UNBIND_RSP = 0xA2, + ZDO_MGMT_NWK_DISC_RSP = 0xB0, + ZDO_MGMT_LQI_RSP = 0xB1, + ZDO_MGMT_RTG_RSP = 0xB2, + ZDO_MGMT_BIND_RSP = 0xB3, + ZDO_MGMT_LEAVE_RSP = 0xB4, + ZDO_MGMT_DIRECT_JOIN_RSP = 0xB5, + ZDO_MGMT_PERMIT_JOIN_RSP = 0xB6, + ZDO_STATE_CHANGE_IND = 0xC0, + ZDO_END_DEVICE_ANNCE_IND = 0xC1, + ZDO_MATCH_DESC_RSP_SENT = 0xC2, + ZDO_STATUS_ERROR_RSP = 0xC3, + ZDO_SRC_RTG_IND = 0xC4, + ZDO_LEAVE_IND = 0xC9, + ZDO_TC_DEV_IND = 0xCA, + ZDO_PERMIT_JOIN_IND = 0xCB, + ZDO_MSG_CB_INCOMING = 0xFF +}; + + +enum ZdoStates { + ZDO_DEV_HOLD = 0x00, + ZDO_DEV_INIT = 0x01, + ZDO_DEV_NWK_DISC = 0x02, + ZDO_DEV_NWK_JOINING = 0x03, + ZDO_DEV_NWK_REJOIN = 0x04, + ZDO_DEV_END_DEVICE_UNAUTH = 0x05, + ZDO_DEV_END_DEVICE = 0x06, + ZDO_DEV_ROUTER = 0x07, + ZDO_DEV_COORD_STARTING = 0x08, + ZDO_DEV_ZB_COORD = 0x09, + ZDO_DEV_NWK_ORPHAN = 0x0A, +}; + + +enum Z_Util { + Z_UTIL_GET_DEVICE_INFO = 0x00, + Z_UTIL_GET_NV_INFO = 0x01, + Z_UTIL_SET_PANID = 0x02, + Z_UTIL_SET_CHANNELS = 0x03, + Z_UTIL_SET_SECLEVEL = 0x04, + Z_UTIL_SET_PRECFGKEY = 0x05, + Z_UTIL_CALLBACK_SUB_CMD = 0x06, + Z_UTIL_KEY_EVENT = 0x07, + Z_UTIL_TIME_ALIVE = 0x09, + Z_UTIL_LED_CONTROL = 0x0A, + Z_UTIL_TEST_LOOPBACK = 0x10, + Z_UTIL_DATA_REQ = 0x11, + Z_UTIL_SRC_MATCH_ENABLE = 0x20, + Z_UTIL_SRC_MATCH_ADD_ENTRY = 0x21, + Z_UTIL_SRC_MATCH_DEL_ENTRY = 0x22, + Z_UTIL_SRC_MATCH_CHECK_SRC_ADDR = 0x23, + Z_UTIL_SRC_MATCH_ACK_ALL_PENDING = 0x24, + Z_UTIL_SRC_MATCH_CHECK_ALL_PENDING = 0x25, + Z_UTIL_ADDRMGR_EXT_ADDR_LOOKUP = 0x40, + Z_UTIL_ADDRMGR_NWK_ADDR_LOOKUP = 0x41, + Z_UTIL_APSME_LINK_KEY_DATA_GET = 0x44, + Z_UTIL_APSME_LINK_KEY_NV_ID_GET = 0x45, + Z_UTIL_ASSOC_COUNT = 0x48, + Z_UTIL_ASSOC_FIND_DEVICE = 0x49, + Z_UTIL_ASSOC_GET_WITH_ADDRESS = 0x4A, + Z_UTIL_APSME_REQUEST_KEY_CMD = 0x4B, + Z_UTIL_ZCL_KEY_EST_INIT_EST = 0x80, + Z_UTIL_ZCL_KEY_EST_SIGN = 0x81, + Z_UTIL_UTIL_SYNC_REQ = 0xE0, + Z_UTIL_ZCL_KEY_ESTABLISH_IND = 0xE1 +}; + +enum ZCL_Global_Commands { + ZCL_READ_ATTRIBUTES = 0x00, + ZCL_READ_ATTRIBUTES_RESPONSE = 0x01, + ZCL_WRITE_ATTRIBUTES = 0x02, + ZCL_WRITE_ATTRIBUTES_UNDIVIDED = 0x03, + ZCL_WRITE_ATTRIBUTES_RESPONSE = 0x04, + ZCL_WRITE_ATTRIBUTES_NORESPONSE = 0x05, + ZCL_CONFIGURE_REPORTING = 0x06, + ZCL_CONFIGURE_REPORTING_RESPONSE = 0x07, + ZCL_READ_REPORTING_CONFIGURATION = 0x08, + ZCL_READ_REPORTING_CONFIGURATION_RESPONSE = 0x09, + ZCL_REPORT_ATTRIBUTES = 0x0a, + ZCL_DEFAULT_RESPONSE = 0x0b, + ZCL_DISCOVER_ATTRIBUTES = 0x0c, + ZCL_DISCOVER_ATTRIBUTES_RESPONSE = 0x0d + +}; + +enum class ZclGlobalCommandId : uint8_t { +}; + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_4_converters.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_4_converters.ino" +#ifdef USE_ZIGBEE + + + + + +typedef union ZCLHeaderFrameControl_t { + struct { + uint8_t frame_type : 2; + uint8_t manuf_specific : 1; + uint8_t direction : 1; + uint8_t disable_def_resp : 1; + uint8_t reserved : 3; + } b; + uint32_t d8; +} ZCLHeaderFrameControl_t; + + +class ZCLFrame { +public: + + ZCLFrame(uint8_t frame_control, uint16_t manuf_code, uint8_t transact_seq, uint8_t cmd_id, + const char *buf, size_t buf_len, uint16_t clusterid = 0, uint16_t groupid = 0): + _cmd_id(cmd_id), _manuf_code(manuf_code), _transact_seq(transact_seq), + _payload(buf_len ? buf_len : 250), + _cluster_id(clusterid), _group_id(groupid) + { + _frame_control.d8 = frame_control; + _payload.addBuffer(buf, buf_len); + }; + + + void publishMQTTReceived(uint16_t groupid, uint16_t clusterid, Z_ShortAddress srcaddr, + uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, + uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, + uint32_t timestamp) { + char hex_char[_payload.len()*2+2]; + ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); + Response_P(PSTR("{\"" D_JSON_ZIGBEEZCLRECEIVED "\":{" + "\"groupid\":%d," "\"clusterid\":%d," "\"srcaddr\":\"0x%04X\"," + "\"srcendpoint\":%d," "\"dstendpoint\":%d," "\"wasbroadcast\":%d," + "\"linkquality\":%d," "\"securityuse\":%d," "\"seqnumber\":%d," + "\"timestamp\":%d," + "\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," + "\"cmdid\":\"0x%02X\",\"payload\":\"%s\""), + groupid, clusterid, srcaddr, + srcendpoint, dstendpoint, wasbroadcast, + linkquality, securityuse, seqnumber, + timestamp, + _frame_control, _manuf_code, _transact_seq, _cmd_id, + hex_char); + + ResponseJsonEnd(); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLSENT)); + XdrvRulesProcess(); + } + + static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid) { + uint32_t i = offset; + ZCLHeaderFrameControl_t frame_control; + uint16_t manuf_code = 0; + uint8_t transact_seq; + uint8_t cmd_id; + + frame_control.d8 = buf.get8(i++); + if (frame_control.b.manuf_specific) { + manuf_code = buf.get16(i); + i += 2; + } + transact_seq = buf.get8(i++); + cmd_id = buf.get8(i++); + ZCLFrame zcl_frame(frame_control.d8, manuf_code, transact_seq, cmd_id, + (const char *)(buf.buf() + i), len + offset - i, + clusterid, groupid); + return zcl_frame; + } + + bool isClusterSpecificCommand(void) { + return _frame_control.b.frame_type & 1; + } + + void parseRawAttributes(JsonObject& json, uint8_t offset = 0); + void parseClusterSpecificCommand(JsonObject& json, uint8_t offset = 0); + void postProcessAttributes(JsonObject& json); + + inline void setGroupId(uint16_t groupid) { + _group_id = groupid; + } + + inline void setClusterId(uint16_t clusterid) { + _cluster_id = clusterid; + } + + inline uint8_t getCmdId(void) const { + return _cmd_id; + } + + inline uint16_t getClusterId(void) const { + return _cluster_id; + } + + const SBuffer &getPayload(void) const { + return _payload; + } + +private: + ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 }; + uint16_t _manuf_code = 0; + uint8_t _transact_seq = 0; + uint8_t _cmd_id = 0; + uint16_t _cluster_id = 0; + uint16_t _group_id = 0; + SBuffer _payload; +}; + + + + + + + +uint8_t toPercentageCR2032(uint32_t voltage) { + uint32_t percentage; + if (voltage < 2100) { + percentage = 0; + } else if (voltage < 2440) { + percentage = 6 - ((2440 - voltage) * 6) / 340; + } else if (voltage < 2740) { + percentage = 18 - ((2740 - voltage) * 12) / 300; + } else if (voltage < 2900) { + percentage = 42 - ((2900 - voltage) * 24) / 160; + } else if (voltage < 3000) { + percentage = 100 - ((3000 - voltage) * 58) / 100; + } else if (voltage >= 3000) { + percentage = 100; + } + return percentage; +} + + +uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer &buf, + uint32_t offset, uint32_t len) { + + uint32_t i = offset; + uint32_t attrtype = buf.get8(i++); + + + json[attrid_str] = (char*) nullptr; + + + switch (attrtype) { + case 0x00: + case 0xFF: + break; + case 0x10: + { + uint8_t val_bool = buf.get8(i++); + if (0xFF != val_bool) { + json[attrid_str] = (bool) (val_bool ? true : false); + } + } + break; + case 0x20: + { + uint8_t uint8_val = buf.get8(i); + i += 1; + if (0xFF != uint8_val) { + json[attrid_str] = uint8_val; + } + } + break; + case 0x21: + { + uint16_t uint16_val = buf.get16(i); + i += 2; + if (0xFFFF != uint16_val) { + json[attrid_str] = uint16_val; + } + } + break; + case 0x23: + { + uint32_t uint32_val = buf.get32(i); + i += 4; + if (0xFFFFFFFF != uint32_val) { + json[attrid_str] = uint32_val; + } + } + break; + + case 0x24: + case 0x25: + case 0x26: + case 0x27: + i += attrtype - 0x1F; + break; + case 0x28: + { + int8_t int8_val = buf.get8(i); + i += 1; + if (0x80 != int8_val) { + json[attrid_str] = int8_val; + } + } + break; + case 0x29: + { + int16_t int16_val = buf.get16(i); + i += 2; + if (0x8000 != int16_val) { + json[attrid_str] = int16_val; + } + } + break; + case 0x2B: + { + int32_t int32_val = buf.get32(i); + i += 4; + if (0x80000000 != int32_val) { + json[attrid_str] = int32_val; + } + } + break; + + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + i += attrtype - 0x27; + break; + + case 0x41: + case 0x42: + case 0x43: + case 0x44: + + { + bool parse_as_string = true; + uint32_t len = (attrtype <= 0x42) ? buf.get8(i) : buf.get16(i); + i += (attrtype <= 0x42) ? 1 : 2; + + + if ((0x41 == attrtype) || (0x43 == attrtype)) { parse_as_string = false; } + else { + for (uint32_t j = 0; j < len; j++) { + if (0x00 == buf.get8(i+j)) { + parse_as_string = false; + break; + } + } + } + + if (parse_as_string) { + char str[len+1]; + strncpy(str, buf.charptr(i), len); + str[len] = 0x00; + json[attrid_str] = str; + } else { + + char hex[2*len+1]; + ToHex_P(buf.buf(i), len, hex, sizeof(hex)); + json[attrid_str] = hex; + } + + i += len; + break; + } + i += buf.get8(i) + 1; + break; + + + + case 0x08: + i++; + break; + case 0x18: + i++; + break; + case 0x19: + i += 2; + break; + case 0x1B: + i += 4; + break; + + case 0x30: + case 0x31: + i += attrtype - 0x2F; + break; + + case 0x39: + i += 4; + break; + + case 0xE0: + case 0xE1: + case 0xE2: + i += 4; + break; + + case 0xE8: + case 0xE9: + i += 2; + break; + case 0xEA: + i += 4; + break; + + case 0xF0: + i += 8; + break; + case 0xF1: + i += 16; + break; + + + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + i += attrtype - 0x07; + break; + + case 0x1A: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + i += attrtype - 0x17; + break; + + case 0x38: + i += 2; + break; + case 0x3A: + i += 8; + break; + } + + + + + + + return i - offset; +} + + + + +void ZCLFrame::parseRawAttributes(JsonObject& json, uint8_t offset) { + uint32_t i = offset; + uint32_t len = _payload.len(); + uint32_t attrid = _cluster_id << 16; + + while (len + offset - i >= 3) { + attrid = (attrid & 0xFFFF0000) | _payload.get16(i); + i += 2; + + char shortaddr[12]; + snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%08X"), attrid); + + + if (0x0000FF01 == attrid) { + if (0x42 == _payload.get8(i)) { + _payload.set8(i, 0x41); + } + } + i += parseSingleAttribute(json, shortaddr, _payload, i, len); + } +} + + + +void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { + uint32_t i = offset; + uint32_t len = _payload.len(); + uint32_t attrid = _cluster_id << 8 | _cmd_id; + + char attrid_str[12]; + snprintf_P(attrid_str, sizeof(attrid_str), PSTR("0x%06X"), attrid); + + char hex_char[_payload.len()*2+2]; + ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); + + json[attrid_str] = hex_char; +} + +#define ZCL_MODELID "0x00000005" +#define ZCL_TEMPERATURE "0x04020000" +#define ZCL_PRESSURE "0x04030000" +#define ZCL_PRESSURE_SCALED "0x04030010" +#define ZCL_PRESSURE_SCALE "0x04030014" +#define ZCL_HUMIDITY "0x04050000" +#define ZCL_LUMI_WEATHER "0x0000FF01" + +#define ZCL_OO_OFF "0x000600" +#define ZCL_OO_ON "0x000601" +#define ZCL_COLORTEMP_MOVE "0x03000A" +#define ZCL_LC_MOVE "0x000800" +#define ZCL_LC_MOVE_1 "0x000801" +#define ZCL_LC_STEP "0x000802" +#define ZCL_LC_STOP "0x000803" +#define ZCL_LC_MOVE_WOO "0x000804" +#define ZCL_LC_MOVE_1_WOO "0x000805" +#define ZCL_LC_STEP_WOO "0x000806" +#define ZCL_LC_STOP_WOO "0x000807" + +void ZCLFrame::postProcessAttributes(JsonObject& json) { + const __FlashStringHelper *key; + + + key = F(ZCL_MODELID); + if (json.containsKey(key)) { + json[F(D_JSON_MODEL D_JSON_ID)] = json[key]; + json.remove(key); + } + + + key = F(ZCL_TEMPERATURE); + if (json.containsKey(key)) { + + int32_t temperature = json[key]; + json.remove(key); + json[F(D_JSON_TEMPERATURE)] = temperature / 100.0f; + } + + + key = F(ZCL_PRESSURE); + if (json.containsKey(key)) { + json[F(D_JSON_PRESSURE)] = json[key]; + json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); + json.remove(key); + } + json.remove(F(ZCL_PRESSURE_SCALE)); + json.remove(F(ZCL_PRESSURE_SCALED)); + + + key = F(ZCL_HUMIDITY); + if (json.containsKey(key)) { + + uint32_t humidity = json[key]; + json.remove(key); + json[F(D_JSON_HUMIDITY)] = humidity / 100.0f; + } + + + key = F(ZCL_OO_OFF); + if (json.containsKey(key)) { + json.remove(key); + json[F(D_CMND_POWER)] = F("Off"); + } + key = F(ZCL_OO_ON); + if (json.containsKey(key)) { + json.remove(key); + json[F(D_CMND_POWER)] = F("On"); + } + key = F(ZCL_COLORTEMP_MOVE); + if (json.containsKey(key)) { + String hex = json[key]; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + uint16_t color_temp = buf2.get16(0); + uint16_t transition_time = buf2.get16(2); + json.remove(key); + json[F("ColorTemp")] = color_temp; + json[F("TransitionTime")] = transition_time / 10.0f; + } + key = F(ZCL_LC_MOVE_WOO); + if (json.containsKey(key)) { + String hex = json[key]; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + uint8_t level = buf2.get8(0); + uint16_t transition_time = buf2.get16(1); + json.remove(key); + json[F("Dimmer")] = changeUIntScale(level, 0, 255, 0, 100); + json[F("TransitionTime")] = transition_time / 10.0f; + if (0 == level) { + json[F(D_CMND_POWER)] = F("Off"); + } else { + json[F(D_CMND_POWER)] = F("On"); + } + } + key = F(ZCL_LC_MOVE); + if (json.containsKey(key)) { + String hex = json[key]; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + uint8_t level = buf2.get8(0); + uint16_t transition_time = buf2.get16(1); + json.remove(key); + json[F("Dimmer")] = changeUIntScale(level, 0, 255, 0, 100); + json[F("TransitionTime")] = transition_time / 10.0f; + } + key = F(ZCL_LC_MOVE_1); + if (json.containsKey(key)) { + String hex = json[key]; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + uint8_t move_mode = buf2.get8(0); + uint8_t move_rate = buf2.get8(1); + json.remove(key); + json[F("Move")] = move_mode ? F("Down") : F("Up"); + json[F("Rate")] = move_rate; + } + key = F(ZCL_LC_MOVE_1_WOO); + if (json.containsKey(key)) { + String hex = json[key]; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + uint8_t move_mode = buf2.get8(0); + uint8_t move_rate = buf2.get8(1); + json.remove(key); + json[F("Move")] = move_mode ? F("Down") : F("Up"); + json[F("Rate")] = move_rate; + if (0 == move_mode) { + json[F(D_CMND_POWER)] = F("On"); + } + } + key = F(ZCL_LC_STEP); + if (json.containsKey(key)) { + String hex = json[key]; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + uint8_t step_mode = buf2.get8(0); + uint8_t step_size = buf2.get8(1); + uint16_t transition_time = buf2.get16(2); + json.remove(key); + json[F("Step")] = step_mode ? F("Down") : F("Up"); + json[F("StepSize")] = step_size; + json[F("TransitionTime")] = transition_time / 10.0f; + } + key = F(ZCL_LC_STEP_WOO); + if (json.containsKey(key)) { + String hex = json[key]; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + uint8_t step_mode = buf2.get8(0); + uint8_t step_size = buf2.get8(1); + uint16_t transition_time = buf2.get16(2); + json.remove(key); + json[F("Step")] = step_mode ? F("Down") : F("Up"); + json[F("StepSize")] = step_size; + json[F("TransitionTime")] = transition_time / 10.0f; + if (0 == step_mode) { + json[F(D_CMND_POWER)] = F("On"); + } + } + key = F(ZCL_LC_STOP); + if (json.containsKey(key)) { + json.remove(key); + json[F("Stop")] = 1; + } + key = F(ZCL_LC_STOP_WOO); + if (json.containsKey(key)) { + json.remove(key); + json[F("Stop")] = 1; + } + + + key = F(ZCL_LUMI_WEATHER); + if (json.containsKey(key)) { + String hex = json[key]; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + DynamicJsonBuffer jsonBuffer; + JsonObject& json_lumi = jsonBuffer.createObject(); + uint32_t i = 0; + uint32_t len = buf2.len(); + char shortaddr[8]; + + while (len - i >= 2) { + uint8_t attrid = buf2.get8(i++); + + snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%02X"), attrid); + + i += parseSingleAttribute(json_lumi, shortaddr, buf2, i, len); + } + + if (json_lumi.containsKey("0x64")) { + int32_t temperature = json_lumi["0x64"]; + json[F(D_JSON_TEMPERATURE)] = temperature / 100.0f; + } + if (json_lumi.containsKey("0x65")) { + uint32_t humidity = json_lumi["0x65"]; + json[F(D_JSON_HUMIDITY)] = humidity / 100.0f; + } + if (json_lumi.containsKey("0x66")) { + int32_t pressure = json_lumi["0x66"]; + json[F(D_JSON_PRESSURE)] = pressure / 100.0f; + json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); + } + if (json_lumi.containsKey("0x01")) { + uint32_t voltage = json_lumi["0x01"]; + json[F(D_JSON_VOLTAGE)] = voltage / 1000.0f; + json[F("Battery")] = toPercentageCR2032(voltage); + } + json.remove(key); + } + +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_9_impl.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_9_impl.ino" +#ifdef USE_ZIGBEE + +#define XDRV_23 23 + +const uint32_t ZIGBEE_BUFFER_SIZE = 256; +const uint8_t ZIGBEE_SOF = 0xFE; + + + +const uint8_t ZIGBEE_STATUS_OK = 0; +const uint8_t ZIGBEE_STATUS_BOOT = 1; +const uint8_t ZIGBEE_STATUS_RESET_CONF = 2; +const uint8_t ZIGBEE_STATUS_STARTING = 3; +const uint8_t ZIGBEE_STATUS_PERMITJOIN_CLOSE = 20; +const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_60 = 21; +const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_XX = 22; +const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; +const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; +const uint8_t ZIGBEE_STATUS_CC_INFO = 51; +const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; +const uint8_t ZIGBEE_STATUS_ABORT = 99; + + + +#ifdef Z_USE_SOFTWARE_SERIAL +#include +SoftwareSerial *ZigbeeSerial = nullptr; +#else +#include +TasmotaSerial *ZigbeeSerial = nullptr; +#endif + + +const char kZigbeeCommands[] PROGMEM = "|" D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN; + +void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZigbeeZNPSend, &CmndZigbeePermitJoin }; + +typedef int32_t (*ZB_Func)(uint8_t value); +typedef int32_t (*ZB_RecvMsgFunc)(int32_t res, class SBuffer &buf); + +typedef union Zigbee_Instruction { + struct { + uint8_t i; + uint8_t d8; + uint16_t d16; + } i; + const void *p; + + + +} Zigbee_Instruction; + + + + +typedef struct Zigbee_Instruction_Type { + uint8_t instr; + uint8_t data; +} Zigbee_Instruction_Type; + +enum Zigbee_StateMachine_Instruction_Set { + + ZGB_INSTR_4_BYTES = 0, + ZGB_INSTR_NOOP = 0, + ZGB_INSTR_LABEL, + ZGB_INSTR_GOTO, + ZGB_INSTR_ON_ERROR_GOTO, + ZGB_INSTR_ON_TIMEOUT_GOTO, + ZGB_INSTR_WAIT, + ZGB_INSTR_WAIT_FOREVER, + ZGB_INSTR_STOP, + + + ZGB_INSTR_8_BYTES = 0x80, + ZGB_INSTR_CALL = 0x80, + ZGB_INSTR_LOG, + ZGB_INSTR_MQTT_STATUS, + ZGB_INSTR_SEND, + ZGB_INSTR_WAIT_UNTIL, + ZGB_INSTR_WAIT_RECV, + ZGB_ON_RECV_UNEXPECTED, + + + ZGB_INSTR_12_BYTES = 0xF0, + ZGB_INSTR_WAIT_RECV_CALL, +}; + +#define ZI_NOOP() { .i = { ZGB_INSTR_NOOP, 0x00, 0x0000} }, +#define ZI_LABEL(x) { .i = { ZGB_INSTR_LABEL, (x), 0x0000} }, +#define ZI_GOTO(x) { .i = { ZGB_INSTR_GOTO, (x), 0x0000} }, +#define ZI_ON_ERROR_GOTO(x) { .i = { ZGB_INSTR_ON_ERROR_GOTO, (x), 0x0000} }, +#define ZI_ON_TIMEOUT_GOTO(x) { .i = { ZGB_INSTR_ON_TIMEOUT_GOTO, (x), 0x0000} }, +#define ZI_WAIT(x) { .i = { ZGB_INSTR_WAIT, 0x00, (x)} }, +#define ZI_WAIT_FOREVER() { .i = { ZGB_INSTR_WAIT_FOREVER, 0x00, 0x0000} }, +#define ZI_STOP(x) { .i = { ZGB_INSTR_STOP, (x), 0x0000} }, + +#define ZI_CALL(f,x) { .i = { ZGB_INSTR_CALL, (x), 0x0000} }, { .p = (const void*)(f) }, +#define ZI_LOG(x,m) { .i = { ZGB_INSTR_LOG, (x), 0x0000 } }, { .p = ((const void*)(m)) }, +#define ZI_MQTT_STATUS(x,m) { .i = { ZGB_INSTR_MQTT_STATUS, (x), 0x0000 } }, { .p = ((const void*)(m)) }, +#define ZI_ON_RECV_UNEXPECTED(f) { .i = { ZGB_ON_RECV_UNEXPECTED, 0x00, 0x0000} }, { .p = (const void*)(f) }, +#define ZI_SEND(m) { .i = { ZGB_INSTR_SEND, sizeof(m), 0x0000} }, { .p = (const void*)(m) }, +#define ZI_WAIT_RECV(x,m) { .i = { ZGB_INSTR_WAIT_RECV, sizeof(m), (x)} }, { .p = (const void*)(m) }, +#define ZI_WAIT_UNTIL(x,m) { .i = { ZGB_INSTR_WAIT_UNTIL, sizeof(m), (x)} }, { .p = (const void*)(m) }, +#define ZI_WAIT_RECV_FUNC(x,m,f) { .i = { ZGB_INSTR_WAIT_RECV_CALL, sizeof(m), (x)} }, { .p = (const void*)(m) }, { .p = (const void*)(f) }, + + +const uint8_t ZIGBEE_LABEL_START = 10; +const uint8_t ZIGBEE_LABEL_READY = 20; +const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; +const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_CLOSE = 30; +const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60 = 31; +const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX = 32; + +const uint8_t ZIGBEE_LABEL_ABORT = 99; +const uint8_t ZIGBEE_LABEL_UNSUPPORTED_VERSION = 98; + +struct ZigbeeStatus { + bool active = true; + bool state_machine = false; + bool state_waiting = false; + bool state_no_timeout = false; + bool ready = false; + uint8_t on_error_goto = ZIGBEE_LABEL_ABORT; + uint8_t on_timeout_goto = ZIGBEE_LABEL_ABORT; + int16_t pc = 0; + uint32_t next_timeout = 0; + + uint8_t *recv_filter = nullptr; + bool recv_until = false; + size_t recv_filter_len = 0; + ZB_RecvMsgFunc recv_func = nullptr; + ZB_RecvMsgFunc recv_unexpected = nullptr; + + bool init_phase = true; +}; +struct ZigbeeStatus zigbee; + +SBuffer *zigbee_buffer = nullptr; + + + + + +#define Z_B0(a) (uint8_t)( ((a) ) & 0xFF ) +#define Z_B1(a) (uint8_t)( ((a) >> 8) & 0xFF ) +#define Z_B2(a) (uint8_t)( ((a) >> 16) & 0xFF ) +#define Z_B3(a) (uint8_t)( ((a) >> 24) & 0xFF ) +#define Z_B4(a) (uint8_t)( ((a) >> 32) & 0xFF ) +#define Z_B5(a) (uint8_t)( ((a) >> 40) & 0xFF ) +#define Z_B6(a) (uint8_t)( ((a) >> 48) & 0xFF ) +#define Z_B7(a) (uint8_t)( ((a) >> 56) & 0xFF ) + +#define ZBM(n,x...) const uint8_t n[] PROGMEM = { x }; + +#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL)) + + + +ZBM(ZBS_RESET, Z_AREQ | Z_SYS, SYS_RESET, 0x00 ) +ZBM(ZBR_RESET, Z_AREQ | Z_SYS, SYS_RESET_IND ) + +ZBM(ZBS_VERSION, Z_SREQ | Z_SYS, SYS_VERSION ) +ZBM(ZBR_VERSION, Z_SRSP | Z_SYS, SYS_VERSION ) + + +ZBM(ZBS_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, 0x00 ) +ZBM(ZBR_ZNPHC, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_Success, 0x01 , 0x55) + + +ZBM(ZBS_PAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PANID ) +ZBM(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PANID, 0x02 , + Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) + +ZBM(ZBS_EXTPAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_EXTENDED_PAN_ID ) +ZBM(ZBR_EXTPAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_EXTENDED_PAN_ID, + 0x08 , + Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), + Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID), + ) + +ZBM(ZBS_CHANN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_CHANLIST ) +ZBM(ZBR_CHANN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_CHANLIST, + 0x04 , + Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), + ) + +ZBM(ZBS_PFGK, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEY ) +ZBM(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEY, + 0x10 , + Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), + Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), + Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), + Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), + + ) + +ZBM(ZBS_PFGKEN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEYS_ENABLE ) +ZBM(ZBR_PFGKEN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEYS_ENABLE, + 0x01 , 0x00 ) + + + +ZBM(ZBR_W_OK, Z_SRSP | Z_SAPI, SAPI_WRITE_CONFIGURATION, Z_Success ) +ZBM(ZBR_WNV_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_WRITE, Z_Success ) + + +ZBM(ZBS_FACTRES, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 , 0x02 ) + +ZBM(ZBS_W_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 , Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) + +ZBM(ZBS_W_EXTPAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_EXTENDED_PAN_ID, 0x08 , + Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), + Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID) + ) + +ZBM(ZBS_W_CHANN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_CHANLIST, 0x04 , + Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), + ) + +ZBM(ZBS_W_LOGTYP, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 , 0x00 ) + +ZBM(ZBS_W_PFGK, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEY, + 0x10 , + Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), + Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), + Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), + Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), + + ) + +ZBM(ZBS_W_PFGKEN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEYS_ENABLE, 0x01 , 0x00 ) + +ZBM(ZBS_WNV_SECMODE, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(CONF_TCLK_TABLE_START), Z_B1(CONF_TCLK_TABLE_START), + 0x00 , 0x20 , + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x5a, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6c, + 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) + +ZBM(ZBS_W_ZDODCB, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_ZDO_DIRECT_CB, 0x01 , 0x01 ) + +ZBM(ZBS_WNV_INITZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_ITEM_INIT, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, + 0x01, 0x00 , 0x01 , 0x00 ) + + +ZBM(ZBR_WNV_INIT_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_ITEM_INIT ) + + +ZBM(ZBS_WNV_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(ZNP_HAS_CONFIGURED), Z_B1(ZNP_HAS_CONFIGURED), + 0x00 , 0x01 , 0x55 ) + +ZBM(ZBS_STARTUPFROMAPP, Z_SREQ | Z_ZDO, ZDO_STARTUP_FROM_APP, 100, 0 ) +ZBM(ZBR_STARTUPFROMAPP, Z_SRSP | Z_ZDO, ZDO_STARTUP_FROM_APP ) +ZBM(AREQ_STARTUPFROMAPP, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ZB_COORD ) + +ZBM(ZBS_GETDEVICEINFO, Z_SREQ | Z_UTIL, Z_UTIL_GET_DEVICE_INFO ) +ZBM(ZBR_GETDEVICEINFO, Z_SRSP | Z_UTIL, Z_UTIL_GET_DEVICE_INFO, Z_Success ) +# 287 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_9_impl.ino" +ZBM(ZBS_ZDO_NODEDESCREQ, Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, 0x00, 0x00 , 0x00, 0x00 ) +ZBM(ZBR_ZDO_NODEDESCREQ, Z_SRSP | Z_ZDO, ZDO_NODE_DESC_REQ, Z_Success ) + +ZBM(AREQ_ZDO_NODEDESCREQ, Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP) +# 305 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_9_impl.ino" +ZBM(ZBS_ZDO_ACTIVEEPREQ, Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, 0x00, 0x00, 0x00, 0x00) +ZBM(ZBR_ZDO_ACTIVEEPREQ, Z_SRSP | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_Success) +ZBM(ZBR_ZDO_ACTIVEEPRSP_NONE, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 , Z_Success, + 0x00, 0x00 , 0x00 ) +ZBM(ZBR_ZDO_ACTIVEEPRSP_OK, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 , Z_Success, + 0x00, 0x00 , 0x02 , 0x0B, 0x01 ) + + +ZBM(ZBS_AF_REGISTER01, Z_SREQ | Z_AF, AF_REGISTER, 0x01 , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), + 0x05, 0x00 , 0x00 , 0x00 , + 0x00 , 0x00 ) +ZBM(ZBR_AF_REGISTER, Z_SRSP | Z_AF, AF_REGISTER, Z_Success) +ZBM(ZBS_AF_REGISTER0B, Z_SREQ | Z_AF, AF_REGISTER, 0x0B , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), + 0x05, 0x00 , 0x00 , 0x00 , + 0x00 , 0x00 ) + +ZBM(ZBS_PERMITJOINREQ_CLOSE, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x02 , + 0x00, 0x00 , 0x00 , 0x00 ) +ZBM(ZBS_PERMITJOINREQ_OPEN_60, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F , + 0xFC, 0xFF , 60 , 0x00 ) +ZBM(ZBS_PERMITJOINREQ_OPEN_XX, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F , + 0xFC, 0xFF , 0xFF , 0x00 ) +ZBM(ZBR_PERMITJOINREQ, Z_SRSP | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, Z_Success) +ZBM(ZBR_PERMITJOIN_AREQ_CLOSE, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0x00 ) +ZBM(ZBR_PERMITJOIN_AREQ_OPEN_60, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 60 ) +ZBM(ZBR_PERMITJOIN_AREQ_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0xFF ) +ZBM(ZBR_PERMITJOIN_AREQ_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_RSP, 0x00, 0x00 , Z_Success ) + + +ZBM(ZBR_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) +ZBM(ZBR_END_DEVICE_ANNCE_IND, Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND) + +static const Zigbee_Instruction zb_prog[] PROGMEM = { + ZI_LABEL(0) + ZI_NOOP() + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) + ZI_ON_RECV_UNEXPECTED(&Z_Recv_Default) + ZI_WAIT(15000) + ZI_ON_ERROR_GOTO(50) + + ZI_MQTT_STATUS(ZIGBEE_STATUS_BOOT, "Booting") + + ZI_SEND(ZBS_RESET) + ZI_WAIT_RECV(5000, ZBR_RESET) + ZI_LOG(LOG_LEVEL_INFO, "ZIG: checking device configuration") + ZI_SEND(ZBS_ZNPHC) + ZI_WAIT_RECV(2000, ZBR_ZNPHC) + ZI_SEND(ZBS_VERSION) + ZI_WAIT_RECV_FUNC(2000, ZBR_VERSION, &Z_ReceiveCheckVersion) + ZI_SEND(ZBS_PAN) + ZI_WAIT_RECV(1000, ZBR_PAN) + ZI_SEND(ZBS_EXTPAN) + ZI_WAIT_RECV(1000, ZBR_EXTPAN) + ZI_SEND(ZBS_CHANN) + ZI_WAIT_RECV(1000, ZBR_CHANN) + ZI_SEND(ZBS_PFGK) + ZI_WAIT_RECV(1000, ZBR_PFGK) + ZI_SEND(ZBS_PFGKEN) + ZI_WAIT_RECV(1000, ZBR_PFGKEN) + + + + ZI_LABEL(ZIGBEE_LABEL_START) + ZI_MQTT_STATUS(ZIGBEE_STATUS_STARTING, "Configured, starting coordinator") + + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + + +ZI_SEND(ZBS_STARTUPFROMAPP) + ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) + ZI_WAIT_UNTIL(5000, AREQ_STARTUPFROMAPP) + ZI_SEND(ZBS_GETDEVICEINFO) + ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &Z_ReceiveDeviceInfo) + + ZI_SEND(ZBS_ZDO_NODEDESCREQ) + ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ) + ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCREQ) + ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) + ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) + ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_NONE) + ZI_SEND(ZBS_AF_REGISTER01) + ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) + ZI_SEND(ZBS_AF_REGISTER0B) + ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) + + + ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) + ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) + ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_OK) + ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) + + + + + + + ZI_LABEL(ZIGBEE_LABEL_READY) + ZI_MQTT_STATUS(ZIGBEE_STATUS_OK, "Started") + ZI_LOG(LOG_LEVEL_INFO, "ZIG: zigbee device ready, listening...") + ZI_CALL(&Z_State_Ready, 1) + ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) + ZI_WAIT_FOREVER() + ZI_GOTO(ZIGBEE_LABEL_READY) + + ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE) + ZI_MQTT_STATUS(ZIGBEE_STATUS_PERMITJOIN_CLOSE, "Disable Pairing mode") + ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + + + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60) + ZI_MQTT_STATUS(ZIGBEE_STATUS_PERMITJOIN_OPEN_60, "Enable Pairing mode for 60 seconds") + ZI_SEND(ZBS_PERMITJOINREQ_OPEN_60) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + + + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX) + ZI_MQTT_STATUS(ZIGBEE_STATUS_PERMITJOIN_OPEN_XX, "Enable Pairing mode until next boot") + ZI_SEND(ZBS_PERMITJOINREQ_OPEN_XX) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + + + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + ZI_LABEL(50) + ZI_MQTT_STATUS(ZIGBEE_STATUS_RESET_CONF, "Reseting configuration") + + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + ZI_SEND(ZBS_FACTRES) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_RESET) + ZI_WAIT_RECV(5000, ZBR_RESET) + ZI_SEND(ZBS_W_PAN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_EXTPAN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_CHANN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_LOGTYP) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_PFGK) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_PFGKEN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_WNV_SECMODE) + ZI_WAIT_RECV(1000, ZBR_WNV_OK) + ZI_SEND(ZBS_W_ZDODCB) + ZI_WAIT_RECV(1000, ZBR_W_OK) + + ZI_SEND(ZBS_WNV_INITZNPHC) + ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &Z_CheckNVWrite) + ZI_SEND(ZBS_WNV_ZNPHC) + ZI_WAIT_RECV(1000, ZBR_WNV_OK) + + + ZI_GOTO(ZIGBEE_LABEL_START) + + ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION) + ZI_MQTT_STATUS(ZIGBEE_STATUS_UNSUPPORTED_VERSION, "Only ZNP 1.2 is currently supported") + ZI_GOTO(ZIGBEE_LABEL_ABORT) + + ZI_LABEL(ZIGBEE_LABEL_ABORT) + ZI_MQTT_STATUS(ZIGBEE_STATUS_ABORT, "Abort") + ZI_LOG(LOG_LEVEL_ERROR, "ZIG: Abort") + ZI_STOP(ZIGBEE_LABEL_ABORT) +}; + +int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) { + + + + + + + + Z_IEEEAddress long_adr = buf.get64(3); + Z_ShortAddress short_adr = buf.get16(11); + uint8_t device_type = buf.get8(13); + uint8_t device_state = buf.get8(14); + uint8_t device_associated = buf.get8(15); + + char hex[20]; + Uint64toHex(long_adr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + ",\"DeviceType\":%d,\"DeviceState\":%d" + ",\"NumAssocDevices\":%d"), + ZIGBEE_STATUS_CC_INFO, hex, short_adr, device_type, device_state, + device_associated); + + if (device_associated > 0) { + uint idx = 16; + ResponseAppend_P(PSTR(",\"AssocDevicesList\":[")); + for (uint32_t i = 0; i < device_associated; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(idx)); + idx += 2; + } + ResponseAppend_P(PSTR("]")); + } + + ResponseJsonEnd(); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); + XdrvRulesProcess(); + + return res; +} + +int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf) { + + + + uint8_t status = buf.get8(2); + if ((0x00 == status) || (0x09 == status)) { + return 0; + } else { + return -2; + } +} + +int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { +# 543 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_9_impl.ino" + uint8_t major_rel = buf.get8(4); + uint8_t minor_rel = buf.get8(5); + uint8_t maint_rel = buf.get8(6); + uint32_t revision = buf.get32(7); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" + "\"Status\":%d,\"MajorRel\":%d,\"MinorRel\":%d" + ",\"MaintRel\":%d,\"Revision\":%d}}"), + ZIGBEE_STATUS_CC_VERSION, major_rel, minor_rel, + maint_rel, revision); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); + XdrvRulesProcess(); + + if ((0x02 == major_rel) && (0x06 == minor_rel)) { + return 0; + } else { + return ZIGBEE_LABEL_UNSUPPORTED_VERSION; + } +} + +bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match) { + if ( (pgm_read_byte(&match[0]) == buf.get8(0)) && + (pgm_read_byte(&match[1]) == buf.get8(1)) ) { + return true; + } else { + return false; + } +} + +int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { + Z_ShortAddress srcAddr = buf.get16(2); + Z_ShortAddress nwkAddr = buf.get16(4); + Z_IEEEAddress ieeeAddr = buf.get64(6); + uint8_t capabilities = buf.get8(14); + + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + ",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"), + ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr, + (capabilities & 0x04) ? "true" : "false", + (capabilities & 0x08) ? "true" : "false", + (capabilities & 0x40) ? "true" : "false" + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLRECEIVED)); + XdrvRulesProcess(); + return -1; +} + +int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { + uint16_t groupid = buf.get16(2); + uint16_t clusterid = buf.get16(4); + Z_ShortAddress srcaddr = buf.get16(6); + uint8_t srcendpoint = buf.get8(8); + uint8_t dstendpoint = buf.get8(9); + uint8_t wasbroadcast = buf.get8(10); + uint8_t linkquality = buf.get8(11); + uint8_t securityuse = buf.get8(12); + uint32_t timestamp = buf.get32(13); + uint8_t seqnumber = buf.get8(17); + + ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid); + + zcl_received.publishMQTTReceived(groupid, clusterid, srcaddr, + srcendpoint, dstendpoint, wasbroadcast, + linkquality, securityuse, seqnumber, + timestamp); + + char shortaddr[8]; + snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); + + DynamicJsonBuffer jsonBuffer; + JsonObject& json_root = jsonBuffer.createObject(); + JsonObject& json = json_root.createNestedObject(shortaddr); + if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { + zcl_received.parseRawAttributes(json); + } else if (zcl_received.isClusterSpecificCommand()) { + zcl_received.parseClusterSpecificCommand(json); + } + zcl_received.postProcessAttributes(json); + + String msg(""); + msg.reserve(100); + json_root.printTo(msg); + + Response_P(PSTR("%s"), msg.c_str()); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLRECEIVED)); + XdrvRulesProcess(); + return -1; +} + +int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: Z_Recv_Default")); + if (zigbee.init_phase) { + + return -1; + } else { + if (Z_ReceiveMatchPrefix(buf, ZBR_AF_INCOMING_MESSAGE)) { + return Z_ReceiveAfIncomingMessage(res, buf); + } else if (Z_ReceiveMatchPrefix(buf, ZBR_END_DEVICE_ANNCE_IND)) { + return Z_ReceiveEndDeviceAnnonce(res, buf); + } + return -1; + } +} + +int32_t Z_State_Ready(uint8_t value) { + zigbee.init_phase = false; + return 0; +} + +uint8_t ZigbeeGetInstructionSize(uint8_t instr) { + if (instr >= ZGB_INSTR_12_BYTES) { + return 3; + } else if (instr >= ZGB_INSTR_8_BYTES) { + return 2; + } else { + return 1; + } +} + +void ZigbeeGotoLabel(uint8_t label) { + + uint16_t goto_pc = 0xFFFF; + uint8_t cur_instr = 0; + uint8_t cur_d8 = 0; + uint8_t cur_instr_len = 1; + + for (uint32_t i = 0; i < sizeof(zb_prog)/sizeof(zb_prog[0]); i += cur_instr_len) { + const Zigbee_Instruction *cur_instr_line = &zb_prog[i]; + cur_instr = pgm_read_byte(&cur_instr_line->i.i); + cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); + + + if (ZGB_INSTR_LABEL == cur_instr) { + + if (label == cur_d8) { + + zigbee.pc = i; + zigbee.state_machine = true; + zigbee.state_waiting = false; + return; + } + } + + cur_instr_len = ZigbeeGetInstructionSize(cur_instr); + } + + + AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Goto label not found, label=%d pc=%d"), label, zigbee.pc); + if (ZIGBEE_LABEL_ABORT != label) { + + ZigbeeGotoLabel(ZIGBEE_LABEL_ABORT); + } else { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Label Abort (%d) not present, aborting Zigbee"), ZIGBEE_LABEL_ABORT); + zigbee.state_machine = false; + zigbee.active = false; + } +} + +void ZigbeeStateMachine_Run(void) { + uint8_t cur_instr = 0; + uint8_t cur_d8 = 0; + uint16_t cur_d16 = 0; + const void* cur_ptr1 = nullptr; + const void* cur_ptr2 = nullptr; + uint32_t now = millis(); + + if (zigbee.state_waiting) { + + if ((zigbee.next_timeout) && (now > zigbee.next_timeout)) { + + if (!zigbee.state_no_timeout) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: timeout, goto label %d"), zigbee.on_timeout_goto); + ZigbeeGotoLabel(zigbee.on_timeout_goto); + } else { + zigbee.state_waiting = false; + } + } + } + + while ((zigbee.state_machine) && (!zigbee.state_waiting)) { + + zigbee.recv_filter = nullptr; + zigbee.recv_func = nullptr; + zigbee.recv_until = false; + zigbee.state_no_timeout = false; + + if (zigbee.pc > (sizeof(zb_prog)/sizeof(zb_prog[0]))) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Invalid pc: %d, aborting"), zigbee.pc); + zigbee.pc = -1; + } + if (zigbee.pc < 0) { + zigbee.state_machine = false; + return; + } + + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: Executing instruction pc=%d"), zigbee.pc); + const Zigbee_Instruction *cur_instr_line = &zb_prog[zigbee.pc]; + cur_instr = pgm_read_byte(&cur_instr_line->i.i); + cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); + cur_d16 = pgm_read_word(&cur_instr_line->i.d16); + if (cur_instr >= ZGB_INSTR_8_BYTES) { + cur_instr_line++; + cur_ptr1 = cur_instr_line->p; + } + if (cur_instr >= ZGB_INSTR_12_BYTES) { + cur_instr_line++; + cur_ptr2 = cur_instr_line->p; + } + + zigbee.pc += ZigbeeGetInstructionSize(cur_instr); + + switch (cur_instr) { + case ZGB_INSTR_NOOP: + case ZGB_INSTR_LABEL: + break; + case ZGB_INSTR_GOTO: + ZigbeeGotoLabel(cur_d8); + break; + case ZGB_INSTR_ON_ERROR_GOTO: + zigbee.on_error_goto = cur_d8; + break; + case ZGB_INSTR_ON_TIMEOUT_GOTO: + zigbee.on_timeout_goto = cur_d8; + break; + case ZGB_INSTR_WAIT: + zigbee.next_timeout = now + cur_d16; + zigbee.state_waiting = true; + zigbee.state_no_timeout = true; + break; + case ZGB_INSTR_WAIT_FOREVER: + zigbee.next_timeout = 0; + zigbee.state_waiting = true; + + break; + case ZGB_INSTR_STOP: + zigbee.state_machine = false; + if (cur_d8) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Stopping (%d)"), cur_d8); + } + break; + case ZGB_INSTR_CALL: + if (cur_ptr1) { + uint32_t res; + res = (*((ZB_Func)cur_ptr1))(cur_d8); + if (res > 0) { + ZigbeeGotoLabel(res); + continue; + } else if (res == 0) { + + } else if (res == -1) { + + } else { + ZigbeeGotoLabel(zigbee.on_error_goto); + continue; + } + } + break; + case ZGB_INSTR_LOG: + AddLog_P(cur_d8, (char*) cur_ptr1); + break; + case ZGB_INSTR_MQTT_STATUS: + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{\"Status\":%d,\"Message\":\"%s\"}}"), + cur_d8, (char*) cur_ptr1); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); + XdrvRulesProcess(); + break; + case ZGB_INSTR_SEND: + ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 ); + break; + case ZGB_INSTR_WAIT_UNTIL: + zigbee.recv_until = true; + case ZGB_INSTR_WAIT_RECV: + zigbee.recv_filter = (uint8_t *) cur_ptr1; + zigbee.recv_filter_len = cur_d8; + zigbee.next_timeout = now + cur_d16; + zigbee.state_waiting = true; + break; + case ZGB_ON_RECV_UNEXPECTED: + zigbee.recv_unexpected = (ZB_RecvMsgFunc) cur_ptr1; + break; + case ZGB_INSTR_WAIT_RECV_CALL: + zigbee.recv_filter = (uint8_t *) cur_ptr1; + zigbee.recv_filter_len = cur_d8; + zigbee.recv_func = (ZB_RecvMsgFunc) cur_ptr2; + zigbee.next_timeout = now + cur_d16; + zigbee.state_waiting = true; + break; + } + } +} + +int32_t ZigbeeProcessInput(class SBuffer &buf) { + if (!zigbee.state_machine) { return -1; } + + + bool recv_filter_match = true; + bool recv_prefix_match = false; + if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { + if (zigbee.recv_filter_len >= 2) { + recv_prefix_match = false; + if ( (pgm_read_byte(&zigbee.recv_filter[0]) == buf.get8(0)) && + (pgm_read_byte(&zigbee.recv_filter[1]) == buf.get8(1)) ) { + recv_prefix_match = true; + } + } + + for (uint32_t i = 0; i < zigbee.recv_filter_len; i++) { + if (pgm_read_byte(&zigbee.recv_filter[i]) != buf.get8(i)) { + recv_filter_match = false; + break; + } + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: ZigbeeProcessInput: recv_prefix_match = %d, recv_filter_match = %d"), recv_prefix_match, recv_filter_match); + } + + + int32_t res = -1; + + + + + + if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { + if (!recv_prefix_match) { + res = -1; + } else { + if (recv_filter_match) { + res = 0; + } else { + if (zigbee.recv_until) { + res = -1; + } else { + res = -2; + } + } + } + } else { + res = -1; + } + + if (recv_prefix_match) { + if (zigbee.recv_func) { + res = (*zigbee.recv_func)(res, buf); + } + } + if (-1 == res) { + + if (zigbee.recv_unexpected) { + res = (*zigbee.recv_unexpected)(res, buf); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: ZigbeeProcessInput: res = %d"), res); + + + if (0 == res) { + + zigbee.state_waiting = false; + } else if (res > 0) { + ZigbeeGotoLabel(res); + } else if (-1 == res) { + + + } else { + + ZigbeeGotoLabel(zigbee.on_error_goto); + } +} + +void ZigbeeInput(void) +{ + static uint32_t zigbee_polling_window = 0; + static uint8_t fcs = ZIGBEE_SOF; + static uint32_t zigbee_frame_len = 5; +# 932 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_9_impl.ino" + while (ZigbeeSerial->available()) { + yield(); + uint8_t zigbee_in_byte = ZigbeeSerial->read(); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZigbeeInput byte=%d len=%d"), zigbee_in_byte, zigbee_buffer->len()); + + if (0 == zigbee_buffer->len()) { + zigbee_frame_len = 5; + fcs = ZIGBEE_SOF; + } + + if ((0 == zigbee_buffer->len()) && (ZIGBEE_SOF != zigbee_in_byte)) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeInput discarding byte %02X"), zigbee_in_byte); + continue; + } + + if (zigbee_buffer->len() < zigbee_frame_len) { + zigbee_buffer->add8(zigbee_in_byte); + zigbee_polling_window = millis(); + fcs ^= zigbee_in_byte; + } + + if (zigbee_buffer->len() >= zigbee_frame_len) { + zigbee_polling_window = 0; + break; + } + + + if (02 == zigbee_buffer->len()) { + + uint8_t len_byte = zigbee_buffer->get8(1); + if (len_byte > 250) len_byte = 250; + + zigbee_frame_len = len_byte + 5; + } + } + + if (zigbee_buffer->len() && (millis() > (zigbee_polling_window + ZIGBEE_POLLING))) { + char hex_char[(zigbee_buffer->len() * 2) + 2]; + ToHex_P((unsigned char*)zigbee_buffer->getBuffer(), zigbee_buffer->len(), hex_char, sizeof(hex_char)); + +#ifndef Z_USE_SOFTWARE_SERIAL + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: Bytes follor_read_metric = %0d"), ZigbeeSerial->getLoopReadMetric()); +#endif + + if (zigbee_buffer->len() != zigbee_frame_len) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received frame of wrong size %s, len %d, expected %d"), hex_char, zigbee_buffer->len(), zigbee_frame_len); + } else if (0x00 != fcs) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received bad FCS frame %s, %d"), hex_char, fcs); + } else { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received correct frame %s"), hex_char); + + SBuffer znp_buffer = zigbee_buffer->subBuffer(2, zigbee_frame_len - 3); + + ToHex_P((unsigned char*)znp_buffer.getBuffer(), znp_buffer.len(), hex_char, sizeof(hex_char)); + Response_P(PSTR("{\"" D_JSON_ZIGBEEZNPRECEIVED "\":\"%s\"}"), hex_char); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZNPRECEIVED)); + XdrvRulesProcess(); + + + ZigbeeProcessInput(znp_buffer); + } + zigbee_buffer->setLen(0); + } +} + + + +void ZigbeeInit(void) +{ + zigbee.active = false; + if ((pin[GPIO_ZIGBEE_RX] < 99) && (pin[GPIO_ZIGBEE_TX] < 99)) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("Zigbee: GPIOs Rx:%d Tx:%d"), pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX]); +#ifdef Z_USE_SOFTWARE_SERIAL + ZigbeeSerial = new SoftwareSerial(); + ZigbeeSerial->begin(115200, pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX], SWSERIAL_8N1, false, 256); + ZigbeeSerial->enableIntTx(false); + zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); +#else + ZigbeeSerial = new TasmotaSerial(pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX], 0, 0, 256); + ZigbeeSerial->begin(115200); + if (ZigbeeSerial->hardwareSerial()) { + ClaimSerial(); + zigbee_buffer = new PreAllocatedSBuffer(sizeof(serial_in_buffer), serial_in_buffer); + } else { + zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); + } +#endif + zigbee.active = true; + zigbee.init_phase = true; + zigbee.state_machine = true; + ZigbeeSerial->flush(); + } +} + + + + + +void CmndZigbeeZNPSend(void) +{ + if (ZigbeeSerial && (XdrvMailbox.data_len > 0)) { + uint8_t code; + + char *codes = RemoveSpace(XdrvMailbox.data); + int32_t size = strlen(XdrvMailbox.data); + + SBuffer buf((size+1)/2); + + while (size > 0) { + char stemp[3]; + strlcpy(stemp, codes, sizeof(stemp)); + code = strtol(stemp, nullptr, 16); + buf.add8(code); + size -= 2; + codes += 2; + } + ZigbeeZNPSend(buf.getBuffer(), buf.len()); + } + ResponseCmndDone(); +} + +void ZigbeeZNPSend(const uint8_t *msg, size_t len) { + if ((len < 2) || (len > 252)) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEEZNPSENT ": bad message len %d"), len); + return; + } + uint8_t data_len = len - 2; + + if (ZigbeeSerial) { + uint8_t fcs = data_len; + + ZigbeeSerial->write(ZIGBEE_SOF); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend SOF %02X"), ZIGBEE_SOF); + ZigbeeSerial->write(data_len); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend LEN %02X"), data_len); + for (uint32_t i = 0; i < len; i++) { + uint8_t b = pgm_read_byte(msg + i); + ZigbeeSerial->write(b); + fcs ^= b; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend byt %02X"), b); + } + ZigbeeSerial->write(fcs); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend FCS %02X"), fcs); + } + + char hex_char[(len * 2) + 2]; + Response_P(PSTR("{\"" D_JSON_ZIGBEEZNPSENT "\":\"%s\"}"), + ToHex_P(msg, len, hex_char, sizeof(hex_char))); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZNPSENT)); + XdrvRulesProcess(); +} + + +void CmndZigbeePermitJoin(void) +{ + uint32_t payload = XdrvMailbox.payload; + if (payload < 0) { payload = 0; } + if ((99 != payload) && (payload > 1)) { payload = 1; } + + if (1 == payload) { + ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60); + } else if (99 == payload){ + ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX); + } else { + ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE); + } + ResponseCmndDone(); +} + + + + + +bool Xdrv23(uint8_t function) +{ + bool result = false; + + if (zigbee.active) { + switch (function) { + case FUNC_LOOP: + if (ZigbeeSerial) { ZigbeeInput(); } + if (zigbee.state_machine) { + + ZigbeeStateMachine_Run(); + } + break; + case FUNC_PRE_INIT: + ZigbeeInit(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kZigbeeCommands, ZigbeeCommand); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_24_buzzer.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_24_buzzer.ino" +#ifdef USE_BUZZER + + + + +#define XDRV_24 24 + +struct BUZZER { + uint32_t tune = 0; + bool active = true; + bool enable = false; + uint8_t inverted = 0; + uint8_t count = 0; + uint8_t set[2]; + uint8_t duration; + uint8_t state = 0; +} Buzzer; + + + + +void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune) +{ + Buzzer.set[0] = off; + Buzzer.set[1] = on; + Buzzer.duration = 1; + Buzzer.tune = 0; + if (tune) { + uint32_t tune1 = tune; + uint32_t tune2 = tune; + for (uint32_t i = 0; i < 32; i++) { + if (!(tune2 & 0x80000000)) { + tune2 <<= 1; + } else { + Buzzer.tune <<= 1; + Buzzer.tune |= tune1 & 1; + tune1 >>= 1; + } + } + Buzzer.count = 1; + } else { + Buzzer.count = count * 2; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BUZ: %d(%d),%d,%d,0x%08X(0x%08X)"), count, Buzzer.count, on, off, tune, Buzzer.tune); + + Buzzer.enable = true; +} + +void BuzzerBeep(uint32_t count) { + BuzzerBeep(count, 1, 1, 0); +} + +void BuzzerEnabledBeep(uint32_t count) +{ + if (Settings.flag3.buzzer_enable) { + BuzzerBeep(count); + } +} + + + +bool BuzzerPinState(void) +{ + if (XdrvMailbox.index == GPIO_BUZZER_INV) { + Buzzer.inverted = 1; + XdrvMailbox.index -= (GPIO_BUZZER_INV - GPIO_BUZZER); + return true; + } + return false; +} + +void BuzzerInit(void) +{ + if (pin[GPIO_BUZZER] < 99) { + pinMode(pin[GPIO_BUZZER], OUTPUT); + digitalWrite(pin[GPIO_BUZZER], Buzzer.inverted); + } else { + Buzzer.active = false; + } +} + +void BuzzerEvery100mSec(void) +{ + if (Buzzer.enable) { + if (Buzzer.count) { + if (Buzzer.duration) { + Buzzer.duration--; + if (!Buzzer.duration) { + if (Buzzer.tune) { + Buzzer.state = Buzzer.tune & 1; + Buzzer.tune >>= 1; + } else { + Buzzer.count--; + Buzzer.state = Buzzer.count & 1; + } + Buzzer.duration = Buzzer.set[Buzzer.state]; + } + } + digitalWrite(pin[GPIO_BUZZER], (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); + } else { + Buzzer.enable = false; + } + } +} + + + + + +const char kBuzzerCommands[] PROGMEM = "|" + "Buzzer" ; + +void (* const BuzzerCommand[])(void) PROGMEM = { + &CmndBuzzer }; + +void CmndBuzzer(void) +{ +# 147 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_24_buzzer.ino" + if (XdrvMailbox.data_len > 0) { + char *p; + uint32_t i = 0; + uint32_t parm[4] = { 0 }; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 4; str = strtok_r(nullptr, ", ", &p)) { + parm[i] = strtoul(str, nullptr, 0); + i++; + } + for (uint32_t i = 0; i < 3; i++) { + if (parm[i] < 1) { parm[i] = 1; } + } + BuzzerBeep(parm[0], parm[1], parm[2], parm[3]); + } else { + BuzzerBeep(1); + } + ResponseCmndDone(); +} + + + + + +bool Xdrv24(uint8_t function) +{ + bool result = false; + + if (Buzzer.active) { + switch (function) { + case FUNC_EVERY_100_MSECOND: + BuzzerEvery100mSec(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kBuzzerCommands, BuzzerCommand); + break; + case FUNC_PRE_INIT: + BuzzerInit(); + break; + case FUNC_PIN_STATE: + result = BuzzerPinState(); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_25_A4988_Stepper.ino" +# 21 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_25_A4988_Stepper.ino" +#ifdef USE_A4988_Stepper +#include +#define XDRV_25 25 + +short A4988_dir_pin = pin[GPIO_MAX]; +short A4988_stp_pin = pin[GPIO_MAX]; +short A4988_ms1_pin = pin[GPIO_MAX]; +short A4988_ms2_pin = pin[GPIO_MAX]; +short A4988_ms3_pin = pin[GPIO_MAX]; +short A4988_ena_pin = pin[GPIO_MAX]; +int A4988_spr = 0; +float A4988_rpm = 0; +short A4988_mis = 0; + +A4988_Stepper* myA4988 = nullptr; + +void A4988Init(void) +{ + A4988_dir_pin = pin[GPIO_A4988_DIR]; + A4988_stp_pin = pin[GPIO_A4988_STP]; + A4988_ena_pin = pin[GPIO_A4988_ENA]; + A4988_ms1_pin = pin[GPIO_A4988_MS1]; + A4988_ms2_pin = pin[GPIO_A4988_MS2]; + A4988_ms3_pin = pin[GPIO_A4988_MS3]; + A4988_spr = 200; + A4988_rpm = 30; + A4988_mis = 1; + + myA4988 = new A4988_Stepper( A4988_spr + , A4988_rpm + , A4988_mis + , A4988_dir_pin + , A4988_stp_pin + , A4988_ena_pin + , A4988_ms1_pin + , A4988_ms2_pin + , A4988_ms3_pin ); +} + +const char kA4988Commands[] PROGMEM = "Motor|" + "Move|Rotate|Turn|MIS|SPR|RPM"; + +void (* const A4988Command[])(void) PROGMEM = { + &CmndDoMove,&CmndDoRotate,&CmndDoTurn,&CmndSetMIS,&CmndSetSPR,&CmndSetRPM}; + +void CmndDoMove(void) { + if (XdrvMailbox.data_len > 0) { + long stepsPlease = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->doMove(stepsPlease); + ResponseCmndDone(); + } +} + +void CmndDoRotate(void) { + if (XdrvMailbox.data_len > 0) { + long degrsPlease = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->doRotate(degrsPlease); + ResponseCmndDone(); + } +} + +void CmndDoTurn(void) { + if (XdrvMailbox.data_len > 0) { + float turnsPlease = strtod(XdrvMailbox.data,nullptr); + myA4988->doTurn(turnsPlease); + ResponseCmndDone(); + } +} + +void CmndSetMIS(void) { + if ((pin[GPIO_A4988_MS1] < 99) && (pin[GPIO_A4988_MS2] < 99) && (pin[GPIO_A4988_MS3] < 99) && (XdrvMailbox.data_len > 0)) { + short newMIS = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->setMIS(newMIS); + ResponseCmndDone(); + } +} + +void CmndSetSPR(void) { + if (XdrvMailbox.data_len > 0) { + int newSPR = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->setSPR(newSPR); + ResponseCmndDone(); + } +} + +void CmndSetRPM(void) { + if (XdrvMailbox.data_len > 0) { + short newRPM = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->setRPM(newRPM); + ResponseCmndDone(); + } +} + + + + +bool Xdrv25(uint8_t function) +{ + bool result = false; + if ((pin[GPIO_A4988_DIR] < 99) && (pin[GPIO_A4988_STP] < 99)) { + switch (function) { + case FUNC_INIT: + A4988Init(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kA4988Commands, A4988Command); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_99_debug.ino" +# 22 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_99_debug.ino" +#ifdef DEBUG_THEO +#ifndef USE_DEBUG_DRIVER +#define USE_DEBUG_DRIVER +#endif +#endif + + + +#ifdef USE_DEBUG_DRIVER + + + + + + +#define XDRV_99 99 + +#ifndef CPU_LOAD_CHECK +#define CPU_LOAD_CHECK 1 +#endif + + + + + +#define D_CMND_CFGDUMP "CfgDump" +#define D_CMND_CFGPEEK "CfgPeek" +#define D_CMND_CFGPOKE "CfgPoke" +#define D_CMND_CFGSHOW "CfgShow" +#define D_CMND_CFGXOR "CfgXor" +#define D_CMND_CPUCHECK "CpuChk" +#define D_CMND_EXCEPTION "Exception" +#define D_CMND_FLASHDUMP "FlashDump" +#define D_CMND_FLASHMODE "FlashMode" +#define D_CMND_FREEMEM "FreeMem" +#define D_CMND_HELP "Help" +#define D_CMND_RTCDUMP "RtcDump" +#define D_CMND_SETSENSOR "SetSensor" + +const char kDebugCommands[] PROGMEM = "|" + D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" +#ifdef USE_DEBUG_SETTING_NAMES + D_CMND_CFGSHOW "|" +#endif +#ifdef USE_WEBSERVER + D_CMND_CFGXOR "|" +#endif + D_CMND_CPUCHECK "|" +#ifdef DEBUG_THEO + D_CMND_EXCEPTION "|" +#endif + D_CMND_FLASHDUMP "|" D_CMND_FLASHMODE "|" D_CMND_FREEMEM"|" D_CMND_HELP "|" D_CMND_RTCDUMP "|" D_CMND_SETSENSOR ; + +void (* const DebugCommand[])(void) PROGMEM = { + &CmndCfgDump, &CmndCfgPeek, &CmndCfgPoke, +#ifdef USE_DEBUG_SETTING_NAMES + &CmndCfgShow, +#endif +#ifdef USE_WEBSERVER + &CmndCfgXor, +#endif + &CmndCpuCheck, +#ifdef DEBUG_THEO + &CmndException, +#endif + &CmndFlashDump, &CmndFlashMode, &CmndFreemem, &CmndHelp, &CmndRtcDump, &CmndSetSensor }; + +uint32_t CPU_loops = 0; +uint32_t CPU_last_millis = 0; +uint32_t CPU_last_loop_time = 0; +uint8_t CPU_load_check = 0; +uint8_t CPU_show_freemem = 0; + + + +#ifdef DEBUG_THEO +void ExceptionTest(uint8_t type) +{ +# 141 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_99_debug.ino" + if (1 == type) { + char svalue[10]; + snprintf_P(svalue, sizeof(svalue), PSTR("%s"), 7); + } +# 155 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_99_debug.ino" + if (2 == type) { + while(1) delay(1000); + } +} + +#endif + + + +void CpuLoadLoop(void) +{ + CPU_last_loop_time = millis(); + if (CPU_load_check && CPU_last_millis) { + CPU_loops ++; + if ((CPU_last_millis + (CPU_load_check *1000)) <= CPU_last_loop_time) { +#if defined(F_CPU) && (F_CPU == 160000000L) + int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *800) ); + CPU_loops = CPU_loops / CPU_load_check; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(160MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); +#else + int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *400) ); + CPU_loops = CPU_loops / CPU_load_check; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(80MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); +#endif + CPU_last_millis = CPU_last_loop_time; + CPU_loops = 0; + } + } +} + + + +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) + + + +extern "C" { +#include + extern cont_t g_cont; +} + +void DebugFreeMem(void) +{ + register uint32_t *sp asm("a1"); + + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_cont.stack), XdrvMailbox.data); +} + +#else + + + + +extern "C" { +#include + extern cont_t* g_pcont; +} + +void DebugFreeMem(void) +{ + register uint32_t *sp asm("a1"); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_pcont->stack), XdrvMailbox.data); +} + +#endif + + + +void DebugRtcDump(char* parms) +{ + #define CFG_COLS 16 + + uint16_t idx; + uint16_t maxrow; + uint16_t row; + uint16_t col; + char *p; +# 242 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_99_debug.ino" + uint8_t buffer[768]; + + system_rtc_mem_read(0, (uint32_t*)&buffer, sizeof(buffer)); + + maxrow = ((sizeof(buffer)+CFG_COLS)/CFG_COLS); + + uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; + uint16_t mrow = strtol(p, &p, 10); + + + + if (0 == mrow) { + mrow = 8; + } + if (srow > maxrow) { + srow = maxrow - mrow; + } + if (mrow < (maxrow - srow)) { + maxrow = srow + mrow; + } + + for (row = srow; row < maxrow; row++) { + idx = row * CFG_COLS; + snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); + for (col = 0; col < CFG_COLS; col++) { + if (!(col%4)) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + for (col = 0; col < CFG_COLS; col++) { + + + + 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); + } +} + + + +void DebugCfgDump(char* parms) +{ + #define CFG_COLS 16 + + uint16_t idx; + uint16_t maxrow; + uint16_t row; + uint16_t col; + char *p; + + 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); + + + + if (0 == mrow) { + mrow = 8; + } + if (srow > maxrow) { + srow = maxrow - mrow; + } + if (mrow < (maxrow - srow)) { + maxrow = srow + mrow; + } + + for (row = srow; row < maxrow; row++) { + idx = row * CFG_COLS; + snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); + for (col = 0; col < CFG_COLS; col++) { + if (!(col%4)) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + for (col = 0; col < CFG_COLS; col++) { + + + + 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); + delay(1); + } +} + +void DebugCfgPeek(char* parms) +{ + char *p; + + uint16_t address = strtol(parms, &p, 16); + if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; + address = (address >> 2) << 2; + + uint8_t *buffer = (uint8_t *) &Settings; + uint8_t data8 = buffer[address]; + uint16_t data16 = (buffer[address +1] << 8) + buffer[address]; + uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + data16; + + snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), address); + for (uint32_t i = 0; i < 4; i++) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[address +i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + for (uint32_t i = 0; i < 4; i++) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[address +i] > 0x20) && (buffer[address +i] < 0x7F)) ? (char)buffer[address +i] : ' '); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s| 0x%02X (%d), 0x%04X (%d), 0x%0LX (%lu)"), log_data, data8, data8, data16, data16, data32, data32); + AddLog(LOG_LEVEL_INFO); +} + +void DebugCfgPoke(char* parms) +{ + char *p; + + uint16_t address = strtol(parms, &p, 16); + if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; + address = (address >> 2) << 2; + + uint32_t data = strtol(p, &p, 16); + + uint8_t *buffer = (uint8_t *) &Settings; + uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; + + uint8_t *nbuffer = (uint8_t *) &data; + for (uint32_t i = 0; i < 4; i++) { buffer[address +i] = nbuffer[+i]; } + + uint32_t ndata32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; + + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: 0x%0LX (%lu) poked to 0x%0LX (%lu)"), address, data32, data32, ndata32, ndata32); +} + +#ifdef USE_DEBUG_SETTING_NAMES +void DebugCfgShow(uint8_t more) +{ + uint8_t *SetAddr; + SetAddr = (uint8_t *)&Settings; + + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Hostname (%d) [%s]"), (uint8_t *)&Settings.hostname - SetAddr, sizeof(Settings.hostname)-1, Settings.hostname); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: SSids (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_ssid - SetAddr, sizeof(Settings.sta_ssid[0])-1, Settings.sta_ssid[0], Settings.sta_ssid[1]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Friendlynames (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.friendlyname - SetAddr, sizeof(Settings.friendlyname[0])-1, Settings.friendlyname[0], Settings.friendlyname[1], Settings.friendlyname[2], Settings.friendlyname[3]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: OTA Url (%d) [%s]"), (uint8_t *)&Settings.ota_url - SetAddr, sizeof(Settings.ota_url)-1, Settings.ota_url); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: StateText (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.state_text - SetAddr, sizeof(Settings.state_text[0])-1, Settings.state_text[0], Settings.state_text[1], Settings.state_text[2], Settings.state_text[3]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Syslog Host (%d) [%s]"), (uint8_t *)&Settings.syslog_host - SetAddr, sizeof(Settings.syslog_host)-1, Settings.syslog_host); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: NTP Servers (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.ntp_server - SetAddr, sizeof(Settings.ntp_server[0])-1, Settings.ntp_server[0], Settings.ntp_server[1], Settings.ntp_server[2]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Host (%d) [%s]"), (uint8_t *)&Settings.mqtt_host - SetAddr, sizeof(Settings.mqtt_host)-1, Settings.mqtt_host); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Client (%d) [%s]"), (uint8_t *)&Settings.mqtt_client - SetAddr, sizeof(Settings.mqtt_client)-1, Settings.mqtt_client); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT User (%d) [%s]"), (uint8_t *)&Settings.mqtt_user - SetAddr, sizeof(Settings.mqtt_user)-1, Settings.mqtt_user); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT FullTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_fulltopic - SetAddr, sizeof(Settings.mqtt_fulltopic)-1, Settings.mqtt_fulltopic); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Topic (%d) [%s]"), (uint8_t *)&Settings.mqtt_topic - SetAddr, sizeof(Settings.mqtt_topic)-1, Settings.mqtt_topic); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT GroupTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_grptopic - SetAddr, sizeof(Settings.mqtt_grptopic)-1, Settings.mqtt_grptopic); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT ButtonTopic (%d) [%s]"), (uint8_t *)&Settings.button_topic - SetAddr, sizeof(Settings.button_topic)-1, Settings.button_topic); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT SwitchTopic (%d) [%s]"), (uint8_t *)&Settings.switch_topic - SetAddr, sizeof(Settings.switch_topic)-1, Settings.switch_topic); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Prefixes (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.mqtt_prefix - SetAddr, sizeof(Settings.mqtt_prefix[0])-1, Settings.mqtt_prefix[0], Settings.mqtt_prefix[1], Settings.mqtt_prefix[2]); + if (17 == more) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: AP Passwords (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_pwd - SetAddr, sizeof(Settings.sta_pwd[0])-1, Settings.sta_pwd[0], Settings.sta_pwd[1]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Password (%d) [%s]"), (uint8_t *)&Settings.mqtt_pwd - SetAddr, sizeof(Settings.mqtt_pwd)-1, Settings.mqtt_pwd); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Web Password (%d) [%s]"), (uint8_t *)&Settings.web_password - SetAddr, sizeof(Settings.web_password)-1, Settings.web_password); + } +} +#endif + +void SetFlashMode(uint8_t mode) +{ + uint8_t *_buffer; + uint32_t address; + + address = 0; + _buffer = new uint8_t[FLASH_SECTOR_SIZE]; + + if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) { + if (_buffer[2] != mode) { + _buffer[2] = mode; + if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) { + ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); + } + } + } + delete[] _buffer; +} + + + + + +void CmndHelp(void) +{ + AddLog_P(LOG_LEVEL_INFO, PSTR("HLP: "), kDebugCommands); + ResponseCmndDone(); +} + +void CmndRtcDump(void) +{ + DebugRtcDump(XdrvMailbox.data); + ResponseCmndDone(); +} + +void CmndCfgDump(void) +{ + DebugCfgDump(XdrvMailbox.data); + ResponseCmndDone(); +} + +void CmndCfgPeek(void) +{ + DebugCfgPeek(XdrvMailbox.data); + ResponseCmndDone(); +} + +void CmndCfgPoke(void) +{ + DebugCfgPoke(XdrvMailbox.data); + ResponseCmndDone(); +} + +#ifdef USE_DEBUG_SETTING_NAMES +void CmndCfgShow(void) +{ + DebugCfgShow(XdrvMailbox.payload); + ResponseCmndDone(); +} +#endif + +#ifdef USE_WEBSERVER +void CmndCfgXor(void) +{ + if (XdrvMailbox.data_len > 0) { + Web.config_xor_on_set = XdrvMailbox.payload; + } + ResponseCmndNumber(Web.config_xor_on_set); +} +#endif + +#ifdef DEBUG_THEO +void CmndException(void) +{ + if (XdrvMailbox.data_len > 0) { ExceptionTest(XdrvMailbox.payload); } + ResponseCmndDone(); +} +#endif + +void CmndCpuCheck(void) +{ + if (XdrvMailbox.data_len > 0) { + CPU_load_check = XdrvMailbox.payload; + CPU_last_millis = CPU_last_loop_time; + } + ResponseCmndNumber(CPU_load_check); +} + +void CmndFreemem(void) +{ + if (XdrvMailbox.data_len > 0) { + CPU_show_freemem = XdrvMailbox.payload; + } + ResponseCmndNumber(CPU_show_freemem); +} + +void CmndSetSensor(void) +{ + if (XdrvMailbox.index < MAX_XSNS_DRIVERS) { + if (XdrvMailbox.payload >= 0) { + bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); + if (1 == XdrvMailbox.payload) { + restart_flag = 2; + } + } + Response_P(PSTR("{\"" D_CMND_SETSENSOR "\":")); + XsnsSensorState(); + ResponseJsonEnd(); + } +} + +void CmndFlashMode(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + SetFlashMode(XdrvMailbox.payload); + } + ResponseCmndNumber(ESP.getFlashChipMode()); +} + +uint32_t DebugSwap32(uint32_t x) { + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} + +void CmndFlashDump(void) +{ + + + + const uint32_t flash_start = 0x40200000; + const uint8_t bytes_per_cols = 0x20; + const uint32_t max = (SPIFFS_END + 5) * SPI_FLASH_SEC_SIZE; + + uint32_t start = flash_start; + uint32_t rows = 8; + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= (max - bytes_per_cols))) { + start += (XdrvMailbox.payload &0x7FFFFFFC); + + char *p; + uint32_t is_payload = strtol(XdrvMailbox.data, &p, 16); + rows = strtol(p, &p, 10); + if (0 == rows) { rows = 8; } + } + uint32_t end = start + (rows * bytes_per_cols); + if ((end - flash_start) > max) { + end = flash_start + max; + } + + for (uint32_t pos = start; pos < end; pos += bytes_per_cols) { + uint32_t* values = (uint32_t*)(pos); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%06X: %08X %08X %08X %08X %08X %08X %08X %08X"), pos - flash_start, + DebugSwap32(values[0]), DebugSwap32(values[1]), DebugSwap32(values[2]), DebugSwap32(values[3]), + DebugSwap32(values[4]), DebugSwap32(values[5]), DebugSwap32(values[6]), DebugSwap32(values[7])); + } + ResponseCmndDone(); +} + + + + + +bool Xdrv99(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_LOOP: + CpuLoadLoop(); + break; + case FUNC_FREE_MEM: + if (CPU_show_freemem) { DebugFreeMem(); } + break; + case FUNC_PRE_INIT: + CPU_last_millis = millis(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kDebugCommands, DebugCommand); + break; + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_interface.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_interface.ino" +#ifdef XFUNC_PTR_IN_ROM +bool (* const xdrv_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xdrv_func_ptr[])(uint8_t) = { +#endif + +#ifdef XDRV_01 + &Xdrv01, +#endif + +#ifdef XDRV_02 + &Xdrv02, +#endif + +#ifdef XDRV_03 + &Xdrv03, +#endif + +#ifdef XDRV_04 + &Xdrv04, +#endif + +#ifdef XDRV_05 + &Xdrv05, +#endif + +#ifdef XDRV_06 + &Xdrv06, +#endif + +#ifdef XDRV_07 + &Xdrv07, +#endif + +#ifdef XDRV_08 + &Xdrv08, +#endif + +#ifdef XDRV_09 + &Xdrv09, +#endif + +#ifdef XDRV_10 + &Xdrv10, +#endif + +#ifdef XDRV_11 + &Xdrv11, +#endif + +#ifdef XDRV_12 + &Xdrv12, +#endif + +#ifdef XDRV_13 + &Xdrv13, +#endif + +#ifdef XDRV_14 + &Xdrv14, +#endif + +#ifdef XDRV_15 + &Xdrv15, +#endif + +#ifdef XDRV_16 + &Xdrv16, +#endif + +#ifdef XDRV_17 + &Xdrv17, +#endif + +#ifdef XDRV_18 + &Xdrv18, +#endif + +#ifdef XDRV_19 + &Xdrv19, +#endif + +#ifdef XDRV_20 + &Xdrv20, +#endif + +#ifdef XDRV_21 + &Xdrv21, +#endif + +#ifdef XDRV_22 + &Xdrv22, +#endif + +#ifdef XDRV_23 + &Xdrv23, +#endif + +#ifdef XDRV_24 + &Xdrv24, +#endif + +#ifdef XDRV_25 + &Xdrv25, +#endif + +#ifdef XDRV_26 + &Xdrv26, +#endif + +#ifdef XDRV_27 + &Xdrv27, +#endif + +#ifdef XDRV_28 + &Xdrv28, +#endif + +#ifdef XDRV_29 + &Xdrv29, +#endif + +#ifdef XDRV_30 + &Xdrv30, +#endif + +#ifdef XDRV_31 + &Xdrv31, +#endif + +#ifdef XDRV_32 + &Xdrv32, +#endif + +#ifdef XDRV_33 + &Xdrv33, +#endif + +#ifdef XDRV_34 + &Xdrv34, +#endif + +#ifdef XDRV_35 + &Xdrv35, +#endif + +#ifdef XDRV_36 + &Xdrv36, +#endif + +#ifdef XDRV_37 + &Xdrv37, +#endif + +#ifdef XDRV_38 + &Xdrv38, +#endif + +#ifdef XDRV_39 + &Xdrv39, +#endif + +#ifdef XDRV_40 + &Xdrv40, +#endif + +#ifdef XDRV_41 + &Xdrv41, +#endif + +#ifdef XDRV_42 + &Xdrv42, +#endif + +#ifdef XDRV_43 + &Xdrv43, +#endif + +#ifdef XDRV_44 + &Xdrv44, +#endif + +#ifdef XDRV_45 + &Xdrv45, +#endif + +#ifdef XDRV_46 + &Xdrv46, +#endif + +#ifdef XDRV_47 + &Xdrv47, +#endif + +#ifdef XDRV_48 + &Xdrv48, +#endif + +#ifdef XDRV_49 + &Xdrv49, +#endif + +#ifdef XDRV_50 + &Xdrv50, +#endif + +#ifdef XDRV_51 + &Xdrv51, +#endif + +#ifdef XDRV_52 + &Xdrv52, +#endif + +#ifdef XDRV_53 + &Xdrv53, +#endif + +#ifdef XDRV_54 + &Xdrv54, +#endif + +#ifdef XDRV_55 + &Xdrv55, +#endif + +#ifdef XDRV_56 + &Xdrv56, +#endif + +#ifdef XDRV_57 + &Xdrv57, +#endif + +#ifdef XDRV_58 + &Xdrv58, +#endif + +#ifdef XDRV_59 + &Xdrv59, +#endif + +#ifdef XDRV_60 + &Xdrv60, +#endif + +#ifdef XDRV_61 + &Xdrv61, +#endif + +#ifdef XDRV_62 + &Xdrv62, +#endif + +#ifdef XDRV_63 + &Xdrv63, +#endif + +#ifdef XDRV_64 + &Xdrv64, +#endif + +#ifdef XDRV_65 + &Xdrv65, +#endif + +#ifdef XDRV_66 + &Xdrv66, +#endif + +#ifdef XDRV_67 + &Xdrv67, +#endif + +#ifdef XDRV_68 + &Xdrv68, +#endif + +#ifdef XDRV_69 + &Xdrv69, +#endif + +#ifdef XDRV_70 + &Xdrv70, +#endif + +#ifdef XDRV_71 + &Xdrv71, +#endif + +#ifdef XDRV_72 + &Xdrv72, +#endif + +#ifdef XDRV_73 + &Xdrv73, +#endif + +#ifdef XDRV_74 + &Xdrv74, +#endif + +#ifdef XDRV_75 + &Xdrv75, +#endif + +#ifdef XDRV_76 + &Xdrv76, +#endif + +#ifdef XDRV_77 + &Xdrv77, +#endif + +#ifdef XDRV_78 + &Xdrv78, +#endif + +#ifdef XDRV_79 + &Xdrv79, +#endif + +#ifdef XDRV_80 + &Xdrv80, +#endif + +#ifdef XDRV_81 + &Xdrv81, +#endif + +#ifdef XDRV_82 + &Xdrv82, +#endif + +#ifdef XDRV_83 + &Xdrv83, +#endif + +#ifdef XDRV_84 + &Xdrv84, +#endif + +#ifdef XDRV_85 + &Xdrv85, +#endif + +#ifdef XDRV_86 + &Xdrv86, +#endif + +#ifdef XDRV_87 + &Xdrv87, +#endif + +#ifdef XDRV_88 + &Xdrv88, +#endif + +#ifdef XDRV_89 + &Xdrv89, +#endif + +#ifdef XDRV_90 + &Xdrv90, +#endif + +#ifdef XDRV_91 + &Xdrv91, +#endif + +#ifdef XDRV_92 + &Xdrv92, +#endif + +#ifdef XDRV_93 + &Xdrv93, +#endif + +#ifdef XDRV_94 + &Xdrv94, +#endif + +#ifdef XDRV_95 + &Xdrv95, +#endif + +#ifdef XDRV_96 + &Xdrv96, +#endif + +#ifdef XDRV_97 + &Xdrv97, +#endif + +#ifdef XDRV_98 + &Xdrv98, +#endif + +#ifdef XDRV_99 + &Xdrv99 +#endif +}; + +const uint8_t xdrv_present = sizeof(xdrv_func_ptr) / sizeof(xdrv_func_ptr[0]); + + + + + +#ifdef XFUNC_PTR_IN_ROM +const uint8_t kXdrvList[] PROGMEM = { +#else +const uint8_t kXdrvList[] = { +#endif + +#ifdef XDRV_01 + XDRV_01, +#endif + +#ifdef XDRV_02 + XDRV_02, +#endif + +#ifdef XDRV_03 + XDRV_03, +#endif + +#ifdef XDRV_04 + XDRV_04, +#endif + +#ifdef XDRV_05 + XDRV_05, +#endif + +#ifdef XDRV_06 + XDRV_06, +#endif + +#ifdef XDRV_07 + XDRV_07, +#endif + +#ifdef XDRV_08 + XDRV_08, +#endif + +#ifdef XDRV_09 + XDRV_09, +#endif + +#ifdef XDRV_10 + XDRV_10, +#endif + +#ifdef XDRV_11 + XDRV_11, +#endif + +#ifdef XDRV_12 + XDRV_12, +#endif + +#ifdef XDRV_13 + XDRV_13, +#endif + +#ifdef XDRV_14 + XDRV_14, +#endif + +#ifdef XDRV_15 + XDRV_15, +#endif + +#ifdef XDRV_16 + XDRV_16, +#endif + +#ifdef XDRV_17 + XDRV_17, +#endif + +#ifdef XDRV_18 + XDRV_18, +#endif + +#ifdef XDRV_19 + XDRV_19, +#endif + +#ifdef XDRV_20 + XDRV_20, +#endif + +#ifdef XDRV_21 + XDRV_21, +#endif + +#ifdef XDRV_22 + XDRV_22, +#endif + +#ifdef XDRV_23 + XDRV_23, +#endif + +#ifdef XDRV_24 + XDRV_24, +#endif + +#ifdef XDRV_25 + XDRV_25, +#endif + +#ifdef XDRV_26 + XDRV_26, +#endif + +#ifdef XDRV_27 + XDRV_27, +#endif + +#ifdef XDRV_28 + XDRV_28, +#endif + +#ifdef XDRV_29 + XDRV_29, +#endif + +#ifdef XDRV_30 + XDRV_30, +#endif + +#ifdef XDRV_31 + XDRV_31, +#endif + +#ifdef XDRV_32 + XDRV_32, +#endif + +#ifdef XDRV_33 + XDRV_33, +#endif + +#ifdef XDRV_34 + XDRV_34, +#endif + +#ifdef XDRV_35 + XDRV_35, +#endif + +#ifdef XDRV_36 + XDRV_36, +#endif + +#ifdef XDRV_37 + XDRV_37, +#endif + +#ifdef XDRV_38 + XDRV_38, +#endif + +#ifdef XDRV_39 + XDRV_39, +#endif + +#ifdef XDRV_40 + XDRV_40, +#endif + +#ifdef XDRV_41 + XDRV_41, +#endif + +#ifdef XDRV_42 + XDRV_42, +#endif + +#ifdef XDRV_43 + XDRV_43, +#endif + +#ifdef XDRV_44 + XDRV_44, +#endif + +#ifdef XDRV_45 + XDRV_45, +#endif + +#ifdef XDRV_46 + XDRV_46, +#endif + +#ifdef XDRV_47 + XDRV_47, +#endif + +#ifdef XDRV_48 + XDRV_48, +#endif + +#ifdef XDRV_49 + XDRV_49, +#endif + +#ifdef XDRV_50 + XDRV_50, +#endif + +#ifdef XDRV_51 + XDRV_51, +#endif + +#ifdef XDRV_52 + XDRV_52, +#endif + +#ifdef XDRV_53 + XDRV_53, +#endif + +#ifdef XDRV_54 + XDRV_54, +#endif + +#ifdef XDRV_55 + XDRV_55, +#endif + +#ifdef XDRV_56 + XDRV_56, +#endif + +#ifdef XDRV_57 + XDRV_57, +#endif + +#ifdef XDRV_58 + XDRV_58, +#endif + +#ifdef XDRV_59 + XDRV_59, +#endif + +#ifdef XDRV_60 + XDRV_60, +#endif + +#ifdef XDRV_61 + XDRV_61, +#endif + +#ifdef XDRV_62 + XDRV_62, +#endif + +#ifdef XDRV_63 + XDRV_63, +#endif + +#ifdef XDRV_64 + XDRV_64, +#endif + +#ifdef XDRV_65 + XDRV_65, +#endif + +#ifdef XDRV_66 + XDRV_66, +#endif + +#ifdef XDRV_67 + XDRV_67, +#endif + +#ifdef XDRV_68 + XDRV_68, +#endif + +#ifdef XDRV_69 + XDRV_69, +#endif + +#ifdef XDRV_70 + XDRV_70, +#endif + +#ifdef XDRV_71 + XDRV_71, +#endif + +#ifdef XDRV_72 + XDRV_72, +#endif + +#ifdef XDRV_73 + XDRV_73, +#endif + +#ifdef XDRV_74 + XDRV_74, +#endif + +#ifdef XDRV_75 + XDRV_75, +#endif + +#ifdef XDRV_76 + XDRV_76, +#endif + +#ifdef XDRV_77 + XDRV_77, +#endif + +#ifdef XDRV_78 + XDRV_78, +#endif + +#ifdef XDRV_79 + XDRV_79, +#endif + +#ifdef XDRV_80 + XDRV_80, +#endif + +#ifdef XDRV_81 + XDRV_81, +#endif + +#ifdef XDRV_82 + XDRV_82, +#endif + +#ifdef XDRV_83 + XDRV_83, +#endif + +#ifdef XDRV_84 + XDRV_84, +#endif + +#ifdef XDRV_85 + XDRV_85, +#endif + +#ifdef XDRV_86 + XDRV_86, +#endif + +#ifdef XDRV_87 + XDRV_87, +#endif + +#ifdef XDRV_88 + XDRV_88, +#endif + +#ifdef XDRV_89 + XDRV_89, +#endif + +#ifdef XDRV_90 + XDRV_90, +#endif + +#ifdef XDRV_91 + XDRV_91, +#endif + +#ifdef XDRV_92 + XDRV_92, +#endif + +#ifdef XDRV_93 + XDRV_93, +#endif + +#ifdef XDRV_94 + XDRV_94, +#endif + +#ifdef XDRV_95 + XDRV_95, +#endif + +#ifdef XDRV_96 + XDRV_96, +#endif + +#ifdef XDRV_97 + XDRV_97, +#endif + +#ifdef XDRV_98 + XDRV_98, +#endif + +#ifdef XDRV_99 + XDRV_99 +#endif +}; + + + +void XsnsDriverState(void) +{ + ResponseAppend_P(PSTR(",\"Drivers\":\"")); + for (uint32_t i = 0; i < sizeof(kXdrvList); i++) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t driverid = pgm_read_byte(kXdrvList + i); +#else + uint32_t driverid = kXdrvList[i]; +#endif + ResponseAppend_P(PSTR("%s%d"), (i) ? "," : "", driverid); + } + ResponseAppend_P(PSTR("\"")); +} + + + +bool XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t sdataBuf) +{ + XdrvMailbox.index = stopicBuf; + XdrvMailbox.data_len = sdataBuf; + XdrvMailbox.topic = topicBuf; + XdrvMailbox.data = dataBuf; + + return XdrvCall(FUNC_MQTT_DATA); +} + +bool XdrvRulesProcess(void) +{ + return XdrvCallDriver(10, FUNC_RULES_PROCESS); +} + +#ifdef USE_DEBUG_DRIVER +void ShowFreeMem(const char *where) +{ + char stemp[30]; + snprintf_P(stemp, sizeof(stemp), where); + XdrvMailbox.data = stemp; + XdrvCall(FUNC_FREE_MEM); +} +#endif + + + + + +bool XdrvCallDriver(uint32_t driver, uint8_t Function) +{ + for (uint32_t x = 0; x < xdrv_present; x++) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t listed = pgm_read_byte(kXdrvList + x); +#else + uint32_t listed = kXdrvList[x]; +#endif + if (driver == listed) { + return xdrv_func_ptr[x](Function); + } + } + return false; +} + + + + + +bool XdrvCall(uint8_t Function) +{ + bool result = false; + + for (uint32_t x = 0; x < xdrv_present; x++) { + result = xdrv_func_ptr[x](Function); + + if (result && ((FUNC_COMMAND == Function) || + (FUNC_COMMAND_DRIVER == Function) || + (FUNC_MQTT_DATA == Function) || + (FUNC_RULES_PROCESS == Function) || + (FUNC_BUTTON_PRESSED == Function) || + (FUNC_SERIAL == Function) || + (FUNC_MODULE_INIT == Function) || + (FUNC_SET_CHANNELS == Function) || + (FUNC_PIN_STATE == Function) || + (FUNC_SET_DEVICE_POWER == Function) + )) { + break; + } + } + + return result; +} +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_01_lcd.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_01_lcd.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_LCD + +#define XDSP_01 1 + +#define LCD_ADDRESS1 0x27 +#define LCD_ADDRESS2 0x3F + +#include +#include + +LiquidCrystal_I2C *lcd; + + + +void LcdInitMode(void) +{ + lcd->init(); + lcd->clear(); +} + +void LcdInit(uint8_t mode) +{ + switch(mode) { + case DISPLAY_INIT_MODE: + LcdInitMode(); +#ifdef USE_DISPLAY_MODES1TO5 + DisplayClearScreenBuffer(); +#endif + break; + case DISPLAY_INIT_PARTIAL: + case DISPLAY_INIT_FULL: + break; + } +} + +void LcdInitDriver(void) +{ + if (!Settings.display_model) { + if (I2cDevice(LCD_ADDRESS1)) { + Settings.display_address[0] = LCD_ADDRESS1; + Settings.display_model = XDSP_01; + } + else if (I2cDevice(LCD_ADDRESS2)) { + Settings.display_address[0] = LCD_ADDRESS2; + Settings.display_model = XDSP_01; + } + } + + if (XDSP_01 == Settings.display_model) { + Settings.display_width = Settings.display_cols[0]; + Settings.display_height = Settings.display_rows; + lcd = new LiquidCrystal_I2C(Settings.display_address[0], Settings.display_cols[0], Settings.display_rows); + +#ifdef USE_DISPLAY_MODES1TO5 + DisplayAllocScreenBuffer(); +#endif + + LcdInitMode(); + } +} + +void LcdDrawStringAt(void) +{ + lcd->setCursor(dsp_x, dsp_y); + lcd->print(dsp_str); +} + +void LcdDisplayOnOff(uint8_t on) +{ + if (on) { + lcd->backlight(); + } else { + lcd->noBacklight(); + } +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void LcdCenter(uint8_t row, char* txt) +{ + char line[Settings.display_cols[0] +2]; + + int len = strlen(txt); + int offset = 0; + if (len >= Settings.display_cols[0]) { + len = Settings.display_cols[0]; + } else { + offset = (Settings.display_cols[0] - len) / 2; + } + memset(line, 0x20, Settings.display_cols[0]); + line[Settings.display_cols[0]] = 0; + for (uint32_t i = 0; i < len; i++) { + line[offset +i] = txt[i]; + } + lcd->setCursor(0, row); + lcd->print(line); +} + +bool LcdPrintLog(void) +{ + bool result = false; + + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\337'); + if (txt != nullptr) { + uint8_t last_row = Settings.display_rows -1; + + for (uint32_t i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + lcd->setCursor(0, i); + lcd->print(disp_screen_buffer[i +1]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + lcd->setCursor(0, last_row); + lcd->print(disp_screen_buffer[last_row]); + + result = true; + } + } + return result; +} + +void LcdTime(void) +{ + char line[Settings.display_cols[0] +1]; + + snprintf_P(line, sizeof(line), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + LcdCenter(0, line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + LcdCenter(1, line); +} + +void LcdRefresh(void) +{ + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + LcdTime(); + break; + case 2: + case 4: + LcdPrintLog(); + break; + case 3: + case 5: { + if (!LcdPrintLog()) { LcdTime(); } + break; + } + } + } +} + +#endif + + + + + +bool Xdsp01(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + if (FUNC_DISPLAY_INIT_DRIVER == function) { + LcdInitDriver(); + } + else if (XDSP_01 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_INIT: + LcdInit(dsp_init); + break; + case FUNC_DISPLAY_POWER: + LcdDisplayOnOff(disp_power); + break; + case FUNC_DISPLAY_CLEAR: + lcd->clear(); + break; +# 230 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_01_lcd.ino" + case FUNC_DISPLAY_DRAW_STRING: + LcdDrawStringAt(); + break; + case FUNC_DISPLAY_ONOFF: + LcdDisplayOnOff(dsp_on); + break; + + +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + LcdRefresh(); + break; +#endif + } + } + } + return result; +} + +#endif +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_02_ssd1306.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_02_ssd1306.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_SSD1306 + +#define XDSP_02 2 + +#define OLED_RESET 4 + +#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str); + +#define OLED_ADDRESS1 0x3C +#define OLED_ADDRESS2 0x3D + +#define OLED_BUFFER_COLS 40 +#define OLED_BUFFER_ROWS 16 + +#define OLED_FONT_WIDTH 6 +#define OLED_FONT_HEIGTH 8 + +#include +#include +#include + +Adafruit_SSD1306 *oled1306; + +extern uint8_t *buffer; + + + +void SSD1306InitDriver() +{ + if (!Settings.display_model) { + if (I2cDevice(OLED_ADDRESS1)) { + Settings.display_address[0] = OLED_ADDRESS1; + Settings.display_model = XDSP_02; + } + else if (I2cDevice(OLED_ADDRESS2)) { + Settings.display_address[0] = OLED_ADDRESS2; + Settings.display_model = XDSP_02; + } + } + + if (XDSP_02 == Settings.display_model) { + + if ((Settings.display_width != 96) && (Settings.display_width != 128)) { + Settings.display_width = 128; + } + if ((Settings.display_height != 16) && (Settings.display_height != 32) && (Settings.display_height != 64)) { + Settings.display_height = 64; + } + + uint8_t reset_pin = -1; + if (pin[GPIO_OLED_RESET] < 99) { + reset_pin = pin[GPIO_OLED_RESET]; + } + + + if (buffer) { free(buffer); } + buffer = (unsigned char*)calloc((Settings.display_width * Settings.display_height) / 8,1); + if (!buffer) { return; } + + + + oled1306 = new Adafruit_SSD1306(Settings.display_width, Settings.display_height, &Wire, reset_pin); + oled1306->begin(SSD1306_SWITCHCAPVCC, Settings.display_address[0], 0); + renderer = oled1306; + renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font); + + renderer->setTextColor(1,0); + +#ifdef SHOW_SPLASH + renderer->setTextFont(0); + renderer->setTextSize(2); + renderer->setCursor(20,20); + renderer->println(F("SSD1306")); + renderer->Updateframe(); + renderer->DisplayOnff(1); +#endif + + } +} + + +#ifdef USE_DISPLAY_MODES1TO5 + +void Ssd1306PrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\370'); + if (txt != NULL) { + uint8_t last_row = Settings.display_rows -1; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setCursor(0,0); + for (byte i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->println(disp_screen_buffer[i]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + AddLog(LOG_LEVEL_DEBUG); + + renderer->println(disp_screen_buffer[last_row]); + renderer->Updateframe(); + } + } +} + +void Ssd1306Time(void) +{ + char line[12]; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setTextFont(Settings.display_font); + renderer->setCursor(0, 0); + snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + renderer->println(line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + renderer->println(line); + renderer->Updateframe(); +} + +void Ssd1306Refresh(void) +{ + if (!renderer) return; + + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + Ssd1306Time(); + break; + case 2: + case 3: + case 4: + case 5: + Ssd1306PrintLog(); + break; + } + } +} + +#endif + + + + + +bool Xdsp02(byte function) +{ + bool result = false; + + if (i2c_flg) { + if (FUNC_DISPLAY_INIT_DRIVER == function) { + SSD1306InitDriver(); + } + else if (XDSP_02 == Settings.display_model) { + switch (function) { +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + Ssd1306Refresh(); + break; +#endif + case FUNC_DISPLAY_MODEL: + result = true; + break; + } + } + } + return result; +} + +#endif +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_03_matrix.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_03_matrix.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_MATRIX + +#define XDSP_03 3 + +#define MTX_MAX_SCREEN_BUFFER 80 + +#include +#include +#include + +Adafruit_8x8matrix *matrix[8]; +uint8_t mtx_matrices = 0; +uint8_t mtx_state = 0; +uint8_t mtx_counter = 0; +int16_t mtx_x = 0; +int16_t mtx_y = 0; + + +char *mtx_buffer = nullptr; + +uint8_t mtx_mode = 0; +uint8_t mtx_loop = 0; +uint8_t mtx_done = 0; + + + +void MatrixWrite(void) +{ + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->writeDisplay(); + } +} + +void MatrixClear(void) +{ + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + } + MatrixWrite(); +} + +void MatrixFixed(char* txt) +{ + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + matrix[i]->setCursor(-i *8, 0); + matrix[i]->print(txt); + matrix[i]->setBrightness(Settings.display_dimmer); + } + MatrixWrite(); +} + +void MatrixCenter(char* txt) +{ + int offset; + + int len = strlen(txt); + offset = (len < 8) ? offset = ((mtx_matrices *8) - (len *6)) / 2 : 0; + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + matrix[i]->setCursor(-(i *8)+offset, 0); + matrix[i]->print(txt); + matrix[i]->setBrightness(Settings.display_dimmer); + } + MatrixWrite(); +} + +void MatrixScrollLeft(char* txt, int loop) +{ + switch (mtx_state) { + case 1: + mtx_state = 2; + + mtx_x = 8 * mtx_matrices; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), txt); + + disp_refresh = Settings.display_refresh; + case 2: + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + matrix[i]->setCursor(mtx_x - i *8, 0); + matrix[i]->print(txt); + matrix[i]->setBrightness(Settings.display_dimmer); + } + MatrixWrite(); + + mtx_x--; + int16_t len = strlen(txt); + if (mtx_x < -(len *6)) { mtx_state = loop; } + } + break; + } +} + +void MatrixScrollUp(char* txt, int loop) +{ + int wordcounter = 0; + char tmpbuf[200]; + char *words[100]; + + + + char separators[] = " /"; + + switch (mtx_state) { + case 1: + mtx_state = 2; + + mtx_y = 8; + mtx_counter = 0; + disp_refresh = Settings.display_refresh; + case 2: + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + strlcpy(tmpbuf, txt, sizeof(tmpbuf)); + char *p = strtok(tmpbuf, separators); + while (p != nullptr && wordcounter < 40) { + words[wordcounter++] = p; + p = strtok(nullptr, separators); + } + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + for (uint32_t j = 0; j < wordcounter; j++) { + matrix[i]->setCursor(-i *8, mtx_y + (j *8)); + matrix[i]->println(words[j]); + } + matrix[i]->setBrightness(Settings.display_dimmer); + } + MatrixWrite(); + if (((mtx_y %8) == 0) && mtx_counter) { + mtx_counter--; + } else { + mtx_y--; + mtx_counter = STATES * 1; + } + if (mtx_y < -(wordcounter *8)) { mtx_state = loop; } + } + break; + } +} + + + +void MatrixInitMode(void) +{ + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->setRotation(Settings.display_rotate); + matrix[i]->setBrightness(Settings.display_dimmer); + matrix[i]->blinkRate(0); + matrix[i]->setTextWrap(false); + + + matrix[i]->cp437(true); + } + MatrixClear(); +} + +void MatrixInit(uint8_t mode) +{ + switch(mode) { + case DISPLAY_INIT_MODE: + MatrixInitMode(); + break; + case DISPLAY_INIT_PARTIAL: + case DISPLAY_INIT_FULL: + break; + } +} + +void MatrixInitDriver(void) +{ + mtx_buffer = (char*)(malloc(MTX_MAX_SCREEN_BUFFER)); + if (mtx_buffer != nullptr) { + if (!Settings.display_model) { + if (I2cDevice(Settings.display_address[1])) { + Settings.display_model = XDSP_03; + } + } + + if (XDSP_03 == Settings.display_model) { + mtx_state = 1; + for (mtx_matrices = 0; mtx_matrices < 8; mtx_matrices++) { + if (Settings.display_address[mtx_matrices]) { + matrix[mtx_matrices] = new Adafruit_8x8matrix(); + matrix[mtx_matrices]->begin(Settings.display_address[mtx_matrices]); + } else { + break; + } + } + + Settings.display_width = mtx_matrices * 8; + Settings.display_height = 8; + + MatrixInitMode(); + } + } +} + +void MatrixOnOff(void) +{ + if (!disp_power) { MatrixClear(); } +} + +void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + strlcpy(mtx_buffer, str, MTX_MAX_SCREEN_BUFFER); + mtx_mode = x &1; + mtx_loop = y &1; + if (!mtx_state) { mtx_state = 1; } +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void MatrixPrintLog(uint8_t direction) +{ + char* txt = (!mtx_done) ? DisplayLogBuffer('\370') : mtx_buffer; + if (txt != nullptr) { + if (!mtx_state) { mtx_state = 1; } + + if (!mtx_done) { + + uint8_t space = 0; + uint8_t max_cols = (disp_log_buffer_cols < MTX_MAX_SCREEN_BUFFER) ? disp_log_buffer_cols : MTX_MAX_SCREEN_BUFFER; + mtx_buffer[0] = '\0'; + uint8_t i = 0; + while ((txt[i] != '\0') && (i < max_cols)) { + if (txt[i] == ' ') { + space++; + } else { + space = 0; + } + if (space < 2) { + strncat(mtx_buffer, (const char*)txt +i, (strlen(mtx_buffer) < MTX_MAX_SCREEN_BUFFER -1) ? 1 : 0); + } + i++; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), mtx_buffer); + + mtx_done = 1; + } + + if (direction) { + MatrixScrollUp(mtx_buffer, 0); + } else { + MatrixScrollLeft(mtx_buffer, 0); + } + if (!mtx_state) { mtx_done = 0; } + } else { + char disp_time[9]; + + snprintf_P(disp_time, sizeof(disp_time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + MatrixFixed(disp_time); + } +} + +#endif + +void MatrixRefresh(void) +{ + if (disp_power) { + switch (Settings.display_mode) { + case 0: { + switch (mtx_mode) { + case 0: + MatrixScrollLeft(mtx_buffer, mtx_loop); + break; + case 1: + MatrixScrollUp(mtx_buffer, mtx_loop); + break; + } + break; + } +#ifdef USE_DISPLAY_MODES1TO5 + case 2: { + char disp_date[9]; + snprintf_P(disp_date, sizeof(disp_date), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year -2000); + MatrixFixed(disp_date); + break; + } + case 3: { + char disp_day[10]; + snprintf_P(disp_day, sizeof(disp_day), PSTR("%d %s"), RtcTime.day_of_month, RtcTime.name_of_month); + MatrixCenter(disp_day); + break; + } + case 4: + MatrixPrintLog(0); + break; + case 1: + case 5: + MatrixPrintLog(1); + break; +#endif + } + } +} + + + + + +bool Xdsp03(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + if (FUNC_DISPLAY_INIT_DRIVER == function) { + MatrixInitDriver(); + } + else if (XDSP_03 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_INIT: + MatrixInit(dsp_init); + break; + case FUNC_DISPLAY_EVERY_50_MSECOND: + MatrixRefresh(); + break; + case FUNC_DISPLAY_POWER: + MatrixOnOff(); + break; + case FUNC_DISPLAY_DRAW_STRING: + MatrixDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); + break; + } + } + } + return result; +} + +#endif +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_04_ili9341.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_04_ili9341.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_ILI9341 + +#define XDSP_04 4 + +#define TFT_TOP 16 +#define TFT_BOTTOM 16 +#define TFT_FONT_WIDTH 6 +#define TFT_FONT_HEIGTH 8 + +#include +#include +#include + +Adafruit_ILI9341 *tft; + +uint16_t tft_scroll; + + + +void Ili9341InitMode(void) +{ + tft->setRotation(Settings.display_rotate); + tft->invertDisplay(0); + tft->fillScreen(ILI9341_BLACK); + tft->setTextWrap(false); + tft->cp437(true); + if (!Settings.display_mode) { + tft->setCursor(0, 0); + tft->setTextColor(ILI9341_WHITE, ILI9341_BLACK); + tft->setTextSize(1); + } else { + tft->setScrollMargins(TFT_TOP, TFT_BOTTOM); + tft->setCursor(0, 0); + tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK); + tft->setTextSize(2); + + + tft_scroll = TFT_TOP; + } +} + +void Ili9341Init(uint8_t mode) +{ + switch(mode) { + case DISPLAY_INIT_MODE: + Ili9341InitMode(); +#ifdef USE_DISPLAY_MODES1TO5 + if (Settings.display_rotate) { + DisplayClearScreenBuffer(); + } +#endif + break; + case DISPLAY_INIT_PARTIAL: + case DISPLAY_INIT_FULL: + break; + } +} + +void Ili9341InitDriver(void) +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_04; + } + + if (XDSP_04 == Settings.display_model) { + if (Settings.display_width != ILI9341_TFTWIDTH) { + Settings.display_width = ILI9341_TFTWIDTH; + } + if (Settings.display_height != ILI9341_TFTHEIGHT) { + Settings.display_height = ILI9341_TFTHEIGHT; + } + tft = new Adafruit_ILI9341(pin[GPIO_SPI_CS], pin[GPIO_SPI_DC]); + tft->begin(); + +#ifdef USE_DISPLAY_MODES1TO5 + if (Settings.display_rotate) { + DisplayAllocScreenBuffer(); + } +#endif + + Ili9341InitMode(); + } +} + +void Ili9341Clear(void) +{ + tft->fillScreen(ILI9341_BLACK); + tft->setCursor(0, 0); +} + +void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + uint16_t active_color = ILI9341_WHITE; + + tft->setTextSize(Settings.display_size); + if (!flag) { + tft->setCursor(x, y); + } else { + tft->setCursor((x-1) * TFT_FONT_WIDTH * Settings.display_size, (y-1) * TFT_FONT_HEIGTH * Settings.display_size); + } + if (color) { active_color = color; } + tft->setTextColor(active_color, ILI9341_BLACK); + tft->println(str); +} + +void Ili9341DisplayOnOff(uint8_t on) +{ + + + if (pin[GPIO_BACKLIGHT] < 99) { + pinMode(pin[GPIO_BACKLIGHT], OUTPUT); + digitalWrite(pin[GPIO_BACKLIGHT], on); + } +} + +void Ili9341OnOff(void) +{ + Ili9341DisplayOnOff(disp_power); +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void Ili9341PrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (Settings.display_rotate) { + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + } + + char* txt = DisplayLogBuffer('\370'); + if (txt != nullptr) { + uint8_t size = Settings.display_size; + uint16_t theight = size * TFT_FONT_HEIGTH; + + tft->setTextSize(size); + tft->setTextColor(ILI9341_CYAN, ILI9341_BLACK); + if (!Settings.display_rotate) { + tft->setCursor(0, tft_scroll); + tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK); + tft->print(txt); + tft_scroll += theight; + if (tft_scroll >= (tft->height() - TFT_BOTTOM)) { + tft_scroll = TFT_TOP; + } + tft->scrollTo(tft_scroll); + } else { + uint8_t last_row = Settings.display_rows -1; + + tft_scroll = theight; + tft->setCursor(0, tft_scroll); + for (uint32_t i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + + tft->print(disp_screen_buffer[i]); + tft_scroll += theight; + tft->setCursor(0, tft_scroll); + delay(1); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + tft->print(disp_screen_buffer[last_row]); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); + } + } +} + +void Ili9341Refresh(void) +{ + if (Settings.display_mode) { + char tftdt[Settings.display_cols[0] +1]; + char date4[11]; + char space[Settings.display_cols[0] - 17]; + char time[9]; + + tft->setTextSize(2); + tft->setTextColor(ILI9341_YELLOW, ILI9341_RED); + tft->setCursor(0, 0); + + snprintf_P(date4, sizeof(date4), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + memset(space, 0x20, sizeof(space)); + space[sizeof(space) -1] = '\0'; + snprintf_P(time, sizeof(time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + snprintf_P(tftdt, sizeof(tftdt), PSTR("%s%s%s"), date4, space, time); + + tft->print(tftdt); + + switch (Settings.display_mode) { + case 1: + case 2: + case 3: + case 4: + case 5: + Ili9341PrintLog(); + break; + } + } +} + +#endif + + + + + +bool Xdsp04(uint8_t function) +{ + bool result = false; + + if (spi_flg) { + if (FUNC_DISPLAY_INIT_DRIVER == function) { + Ili9341InitDriver(); + } + else if (XDSP_04 == Settings.display_model) { + + if (!dsp_color) { dsp_color = ILI9341_WHITE; } + + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_INIT: + Ili9341Init(dsp_init); + break; + case FUNC_DISPLAY_POWER: + Ili9341OnOff(); + break; + case FUNC_DISPLAY_CLEAR: + Ili9341Clear(); + break; + case FUNC_DISPLAY_DRAW_HLINE: + tft->writeFastHLine(dsp_x, dsp_y, dsp_len, dsp_color); + break; + case FUNC_DISPLAY_DRAW_VLINE: + tft->writeFastVLine(dsp_x, dsp_y, dsp_len, dsp_color); + break; + case FUNC_DISPLAY_DRAW_LINE: + tft->writeLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); + break; + case FUNC_DISPLAY_DRAW_CIRCLE: + tft->drawCircle(dsp_x, dsp_y, dsp_rad, dsp_color); + break; + case FUNC_DISPLAY_FILL_CIRCLE: + tft->fillCircle(dsp_x, dsp_y, dsp_rad, dsp_color); + break; + case FUNC_DISPLAY_DRAW_RECTANGLE: + tft->drawRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); + break; + case FUNC_DISPLAY_FILL_RECTANGLE: + tft->fillRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); + break; + + + + case FUNC_DISPLAY_TEXT_SIZE: + tft->setTextSize(Settings.display_size); + break; + case FUNC_DISPLAY_FONT_SIZE: + + break; + case FUNC_DISPLAY_DRAW_STRING: + Ili9341DrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); + break; + case FUNC_DISPLAY_ONOFF: + Ili9341DisplayOnOff(dsp_on); + break; + case FUNC_DISPLAY_ROTATION: + tft->setRotation(Settings.display_rotate); + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + Ili9341Refresh(); + break; +#endif + } + } + } + return result; +} + +#endif +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_05_epaper_29.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_05_epaper_29.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_EPAPER_29 + +#define XDSP_05 5 + +#define EPD_TOP 12 +#define EPD_FONT_HEIGTH 12 + +#define COLORED 1 +#define UNCOLORED 0 + + + +#define USE_TINY_FONT + +#include +#include + + +extern uint8_t *buffer; +uint16_t epd_scroll; + +Epd *epd; + + + +void EpdInitDriver29() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_05; + } + + if (XDSP_05 == Settings.display_model) { + if (Settings.display_width != EPD_WIDTH) { + Settings.display_width = EPD_WIDTH; + } + if (Settings.display_height != EPD_HEIGHT) { + Settings.display_height = EPD_HEIGHT; + } + + + if (buffer) free(buffer); + buffer=(unsigned char*)calloc((EPD_WIDTH * EPD_HEIGHT) / 8,1); + if (!buffer) return; + + + epd = new Epd(EPD_WIDTH,EPD_HEIGHT); + + + if ((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CLK] < 99) && (pin[GPIO_SPI_MOSI] < 99)) { + epd->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SPI_CS], pin[GPIO_SPI_CLK], pin[GPIO_SPI_MOSI]); + } + else if ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_MOSI] < 99)) { + epd->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SSPI_CS], pin[GPIO_SSPI_SCLK], pin[GPIO_SSPI_MOSI]); + } else { + free(buffer); + return; + } + + renderer = epd; + epd->Init(DISPLAY_INIT_FULL); + epd->Init(DISPLAY_INIT_PARTIAL); + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + + renderer->setTextColor(1,0); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(1); + renderer->DrawStringAt(50, 50, "Waveshare E-Paper Display!", COLORED,0); + renderer->Updateframe(); + delay(1000); + renderer->fillScreen(0); +#endif + + } +} + + + + + + + +#ifdef USE_DISPLAY_MODES1TO5 +#define EPD_FONT_HEIGTH 12 +void EpdPrintLog29(void) +{ + + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + + char* txt = DisplayLogBuffer('\040'); + if (txt != nullptr) { + uint8_t size = Settings.display_size; + uint16_t theight = size * EPD_FONT_HEIGTH; + + renderer->setTextFont(size); + uint8_t last_row = Settings.display_rows -1; + + + epd_scroll = 0; + for (uint32_t i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[i], COLORED, 0); + epd_scroll += theight; + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[last_row], COLORED, 0); + + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); + } + } +} + +void EpdRefresh29(void) +{ + if (Settings.display_mode) { + + if (!renderer) return; +# 165 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_05_epaper_29.ino" + switch (Settings.display_mode) { + case 1: + case 2: + case 3: + case 4: + case 5: + EpdPrintLog29(); + renderer->Updateframe(); + break; + } + + + } +} + +#endif + + + + + +bool Xdsp05(uint8_t function) +{ + bool result = false; + if (FUNC_DISPLAY_INIT_DRIVER == function) { + EpdInitDriver29(); + } + else if (XDSP_05 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + EpdRefresh29(); + break; +#endif + } + } + return result; +} + +#endif +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_06_epaper_42.ino" +# 21 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_06_epaper_42.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_EPAPER_42 + +#define XDSP_06 6 + +#define COLORED42 1 +#define UNCOLORED42 0 + + + +#define USE_TINY_FONT + +#include +#include + +extern uint8_t *buffer; + +Epd42 *epd42; + + + + +void EpdInitDriver42() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_06; + } + + if (XDSP_06 == Settings.display_model) { + + if (Settings.display_width != EPD_WIDTH42) { + Settings.display_width = EPD_WIDTH42; + } + if (Settings.display_height != EPD_HEIGHT42) { + Settings.display_height = EPD_HEIGHT42; + } + + + if (buffer) free(buffer); + buffer=(unsigned char*)calloc((EPD_WIDTH42 * EPD_HEIGHT42) / 8,1); + if (!buffer) return; + + + epd42 = new Epd42(EPD_WIDTH42,EPD_HEIGHT42); + + #ifdef USE_SPI + if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)) { + epd42->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); + } else { + free(buffer); + return; + } + #else + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) { + epd42->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); + } else { + free(buffer); + return; + } + #endif + + renderer = epd42; + + epd42->Init(); + + renderer->fillScreen(0); + + + epd42->Init(DISPLAY_INIT_FULL); + + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + + epd42->ClearFrame(); + renderer->Updateframe(); + delay(3000); + renderer->setTextColor(1,0); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->DrawStringAt(50, 140, "Waveshare E-Paper!", COLORED42,0); + renderer->Updateframe(); + delay(350); + renderer->fillScreen(0); +#endif + + } +} + + + + + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void EpdRefresh42() +{ + if (Settings.display_mode) { + + } +} + +#endif + + + + + + +bool Xdsp06(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + EpdInitDriver42(); + } + else if (XDSP_06 == Settings.display_model) { + + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + EpdRefresh42(); + break; +#endif + } + } + return result; +} + + +#endif +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_07_sh1106.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_07_sh1106.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_SH1106 + +#define OLED_RESET 4 + +#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str); + +extern uint8_t *buffer; + +#define XDSP_07 7 + +#define OLED_ADDRESS1 0x3C +#define OLED_ADDRESS2 0x3D + +#define OLED_BUFFER_COLS 40 +#define OLED_BUFFER_ROWS 16 + +#define OLED_FONT_WIDTH 6 +#define OLED_FONT_HEIGTH 8 + +#include +#include +#include + +Adafruit_SH1106 *oled1106; + + + + +void SH1106InitDriver() +{ + if (!Settings.display_model) { + if (I2cDevice(OLED_ADDRESS1)) { + Settings.display_address[0] = OLED_ADDRESS1; + Settings.display_model = XDSP_07; + } + else if (I2cDevice(OLED_ADDRESS2)) { + Settings.display_address[0] = OLED_ADDRESS2; + Settings.display_model = XDSP_07; + } + } + + if (XDSP_07 == Settings.display_model) { + + if (Settings.display_width != SH1106_LCDWIDTH) { + Settings.display_width = SH1106_LCDWIDTH; + } + if (Settings.display_height != SH1106_LCDHEIGHT) { + Settings.display_height = SH1106_LCDHEIGHT; + } + + + if (buffer) free(buffer); + buffer=(unsigned char*)calloc((SH1106_LCDWIDTH * SH1106_LCDHEIGHT) / 8,1); + if (!buffer) return; + + + oled1106 = new Adafruit_SH1106(SH1106_LCDWIDTH,SH1106_LCDHEIGHT); + renderer=oled1106; + renderer->Begin(SH1106_SWITCHCAPVCC, Settings.display_address[0],0); + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + renderer->setTextColor(1,0); + +#ifdef SHOW_SPLASH + renderer->setTextFont(0); + renderer->setTextSize(2); + renderer->setCursor(20,20); + renderer->println(F("SH1106")); + renderer->Updateframe(); + renderer->DisplayOnff(1); +#endif + } +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void SH1106PrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\370'); + if (txt != NULL) { + uint8_t last_row = Settings.display_rows -1; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setCursor(0,0); + for (byte i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->println(disp_screen_buffer[i]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + AddLog(LOG_LEVEL_DEBUG); + + renderer->println(disp_screen_buffer[last_row]); + renderer->Updateframe(); + } + } +} + +void SH1106Time(void) +{ + char line[12]; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setTextFont(Settings.display_font); + renderer->setCursor(0, 0); + snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + renderer->println(line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + renderer->println(line); + renderer->Updateframe(); +} + +void SH1106Refresh(void) +{ + if (!renderer) return; + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + SH1106Time(); + break; + case 2: + case 3: + case 4: + case 5: + SH1106PrintLog(); + break; + } + } +} + +#endif + + + + + +bool Xdsp07(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + if (FUNC_DISPLAY_INIT_DRIVER == function) { + SH1106InitDriver(); + } + else if (XDSP_07 == Settings.display_model) { + + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + SH1106Refresh(); + break; +#endif + } + } + } + return result; +} + +#endif +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_08_ILI9488.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_08_ILI9488.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_ILI9488 + +#define XDSP_08 8 + +#define COLORED 1 +#define UNCOLORED 0 + + +#define FT6236_address 0x38 + + + +#define USE_TINY_FONT + + +#include +#include + +TouchLocation ili9488_pLoc; +uint8_t ili9488_ctouch_counter = 0; + + +#define BACKPLANE_PIN 2 + +extern uint8_t *buffer; +extern uint8_t color_type; +ILI9488 *ili9488; + +#ifdef USE_TOUCH_BUTTONS +extern VButton *buttons[]; +#endif + +extern const uint16_t picture[]; +uint8_t FT6236_found; + + + +void ILI9488_InitDriver() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_08; + } + + if (XDSP_08 == Settings.display_model) { + + if (Settings.display_width != ILI9488_TFTWIDTH) { + Settings.display_width = ILI9488_TFTWIDTH; + } + if (Settings.display_height != ILI9488_TFTHEIGHT) { + Settings.display_height = ILI9488_TFTHEIGHT; + } + + + buffer=NULL; + + + fg_color = ILI9488_WHITE; + bg_color = ILI9488_BLACK; + + uint8_t bppin=BACKPLANE_PIN; + if (pin[GPIO_BACKLIGHT]<99) { + bppin=pin[GPIO_BACKLIGHT]; + } + + + if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){ + ili9488 = new ILI9488(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK],bppin); + } else { + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) { + ili9488 = new ILI9488(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK],bppin); + } else { + return; + } + } + + SPI.begin(); + ili9488->begin(); + renderer = ili9488; + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->setTextColor(ILI9488_WHITE,ILI9488_BLACK); + renderer->DrawStringAt(50, 50, "ILI9488 TFT Display!", ILI9488_WHITE,0); + delay(1000); + + +#endif + + color_type = COLOR_COLOR; + + + if (i2c_flg && I2cDevice(FT6236_address)) { + FT6236begin(FT6236_address); + FT6236_found=1; + } else { + FT6236_found=0; + } + + } +} + +#ifdef USE_TOUCH_BUTTONS +void ILI9488_MQTT(uint8_t count,const char *cp) { + ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +} + +void ILI9488_RDW_BUTT(uint32_t count,uint32_t pwr) { + buttons[count]->xdrawButton(pwr); + if (pwr) buttons[count]->vpower|=0x80; + else buttons[count]->vpower&=0x7f; +} + +void FT6236Check() { +uint16_t temp; +uint8_t rbutt=0,vbutt=0; +ili9488_ctouch_counter++; +if (2 == ili9488_ctouch_counter) { + + ili9488_ctouch_counter=0; + if (FT6236readTouchLocation(&ili9488_pLoc,1)) { + + if (renderer) { + uint8_t rot=renderer->getRotation(); + switch (rot) { + case 0: + temp=ili9488_pLoc.y; + ili9488_pLoc.y=renderer->height()-ili9488_pLoc.x; + ili9488_pLoc.x=temp; + break; + case 1: + break; + case 2: + break; + case 3: + temp=ili9488_pLoc.y; + ili9488_pLoc.y=ili9488_pLoc.x; + ili9488_pLoc.x=renderer->width()-temp; + break; + } + + for (uint8_t count=0; countvpower&0x7f; + if (buttons[count]->contains(ili9488_pLoc.x,ili9488_pLoc.y)) { + + buttons[count]->press(true); + if (buttons[count]->justPressed()) { + if (!bflags) { + uint8_t pwr=bitRead(power,rbutt); + if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { + ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); + ILI9488_RDW_BUTT(count,!pwr); + } + } else { + + const char *cp; + if (bflags==1) { + + buttons[count]->vpower^=0x80; + cp="TBT"; + } else { + + buttons[count]->vpower|=0x80; + cp="PBT"; + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + ILI9488_MQTT(count,cp); + } + } + } + if (!bflags) { + rbutt++; + } else { + vbutt++; + } + } + } + } + } else { + + for (uint8_t count=0; countvpower&0x7f; + buttons[count]->press(false); + if (buttons[count]->justReleased()) { + uint8_t bflags=buttons[count]->vpower&0x7f; + if (bflags>0) { + if (bflags>1) { + + buttons[count]->vpower&=0x7f; + ILI9488_MQTT(count,"PBT"); + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + } + } + if (!bflags) { + + uint8_t pwr=bitRead(power,rbutt); + uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; + if (pwr!=vpwr) { + ILI9488_RDW_BUTT(count,pwr); + } + rbutt++; + } + } + } + ili9488_pLoc.x=0; + ili9488_pLoc.y=0; + } +} +} +#endif + + + + +bool Xdsp08(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + ILI9488_InitDriver(); + } + else if (XDSP_08 == Settings.display_model) { + + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_EVERY_50_MSECOND: +#ifdef USE_TOUCH_BUTTONS + if (FT6236_found) FT6236Check(); +#endif + break; + } + } + + return result; +} + +#endif +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_09_SSD1351.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_09_SSD1351.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_SSD1351 + +#define XDSP_09 9 + +#define COLORED 1 +#define UNCOLORED 0 + + + + +#define USE_TINY_FONT + +#include + +extern uint8_t *buffer; +extern uint8_t color_type; +SSD1351 *ssd1351; + + + +void SSD1351_InitDriver() { + if (!Settings.display_model) { + Settings.display_model = XDSP_09; + } + + if (XDSP_09 == Settings.display_model) { + + if (Settings.display_width != SSD1351_WIDTH) { + Settings.display_width = SSD1351_WIDTH; + } + if (Settings.display_height != SSD1351_HEIGHT) { + Settings.display_height = SSD1351_HEIGHT; + } + + buffer=0; + + + fg_color = SSD1351_WHITE; + bg_color = SSD1351_BLACK; + + + if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){ + ssd1351 = new SSD1351(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); + } else { + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)){ + ssd1351 = new SSD1351(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); + } else { + return; + } + } + + delay(100); + SPI.begin(); + ssd1351->begin(); + renderer = ssd1351; + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + renderer->dim(Settings.display_dimmer); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->setTextColor(SSD1351_WHITE,SSD1351_BLACK); + renderer->DrawStringAt(10, 60, "SSD1351", SSD1351_RED,0); + delay(1000); + +#endif + color_type = COLOR_COLOR; + } +} + +#ifdef USE_DISPLAY_MODES1TO5 + +void SSD1351PrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\370'); + if (txt != NULL) { + uint8_t last_row = Settings.display_rows -1; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setCursor(0,0); + for (byte i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->println(disp_screen_buffer[i]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + AddLog(LOG_LEVEL_DEBUG); + + renderer->println(disp_screen_buffer[last_row]); + renderer->Updateframe(); + } + } +} + +void SSD1351Time(void) +{ + char line[12]; + + renderer->clearDisplay(); + renderer->setTextSize(2); + renderer->setCursor(0, 0); + snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + renderer->println(line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + renderer->println(line); + renderer->Updateframe(); +} + +void SSD1351Refresh(void) +{ + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + SSD1351Time(); + break; + case 2: + case 3: + case 4: + case 5: + SSD1351PrintLog(); + break; + } + } +} + +#endif + + + + +bool Xdsp09(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + SSD1351_InitDriver(); + } + else if (XDSP_09 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + SSD1351Refresh(); + break; +#endif + } + } + return result; +} +#endif +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_10_RA8876.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_10_RA8876.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_RA8876 + +#define XDSP_10 10 + +#define COLORED 1 +#define UNCOLORED 0 + + +#define FT5316_address 0x38 + + + +#define USE_TINY_FONT + +#include +#include + +TouchLocation ra8876_pLoc; +uint8_t ra8876_ctouch_counter = 0; + +#ifdef USE_TOUCH_BUTTONS +extern VButton *buttons[]; +#endif + +extern uint8_t *buffer; +extern uint8_t color_type; +RA8876 *ra8876; + +uint8_t FT5316_found; + + +void RA8876_InitDriver() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_10; + } + + if (XDSP_10 == Settings.display_model) { + + if (Settings.display_width != RA8876_TFTWIDTH) { + Settings.display_width = RA8876_TFTWIDTH; + } + if (Settings.display_height != RA8876_TFTHEIGHT) { + Settings.display_height = RA8876_TFTHEIGHT; + } + buffer=0; + + + fg_color = RA8876_WHITE; + bg_color = RA8876_BLACK; + + + if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]==13) && (pin[GPIO_SSPI_MISO]==12) && (pin[GPIO_SSPI_SCLK]==14)) { + ra8876 = new RA8876(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_MISO],pin[GPIO_SSPI_SCLK],pin[GPIO_BACKLIGHT]); + } else { + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]==13) && (pin[GPIO_SPI_MISO]==12) && (pin[GPIO_SPI_CLK]==14)) { + ra8876 = new RA8876(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_MISO],pin[GPIO_SPI_CLK],pin[GPIO_BACKLIGHT]); + } else { + return; + } + } + + ra8876->begin(); + renderer = ra8876; + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + renderer->dim(Settings.display_dimmer); + + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->setTextColor(RA8876_WHITE,RA8876_BLACK); + renderer->DrawStringAt(600, 300, "RA8876", RA8876_RED,0); + delay(1000); + +#endif + color_type = COLOR_COLOR; + + if (i2c_flg && I2cDevice(FT5316_address)) { + FT6236begin(FT5316_address); + FT5316_found=1; + } else { + FT5316_found=0; + } + + } +} + +#ifdef USE_TOUCH_BUTTONS +void RA8876_MQTT(uint8_t count,const char *cp) { + ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +} + +void RA8876_RDW_BUTT(uint32_t count,uint32_t pwr) { + buttons[count]->xdrawButton(pwr); + if (pwr) buttons[count]->vpower|=0x80; + else buttons[count]->vpower&=0x7f; +} + + +void FT5316Check() { +uint16_t temp; +uint8_t rbutt=0,vbutt=0; +ra8876_ctouch_counter++; +if (2 == ra8876_ctouch_counter) { + + ra8876_ctouch_counter=0; + + if (FT6236readTouchLocation(&ra8876_pLoc,1)) { + ra8876_pLoc.x=ra8876_pLoc.x*RA8876_TFTWIDTH/800; + ra8876_pLoc.y=ra8876_pLoc.y*RA8876_TFTHEIGHT/480; + + + if (renderer) { + + + ra8876_pLoc.x=RA8876_TFTWIDTH-ra8876_pLoc.x; + ra8876_pLoc.y=RA8876_TFTHEIGHT-ra8876_pLoc.y; +# 168 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_10_RA8876.ino" + for (uint8_t count=0; countvpower&0x7f; + if (buttons[count]->contains(ra8876_pLoc.x,ra8876_pLoc.y)) { + + buttons[count]->press(true); + if (buttons[count]->justPressed()) { + if (!bflags) { + + uint8_t pwr=bitRead(power,rbutt); + if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { + ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); + RA8876_RDW_BUTT(count,!pwr); + } + } else { + + const char *cp; + if (bflags==1) { + + buttons[count]->vpower^=0x80; + cp="TBT"; + } else { + + buttons[count]->vpower|=0x80; + cp="PBT"; + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + RA8876_MQTT(count,cp); + } + } + } + if (!bflags) { + rbutt++; + } else { + vbutt++; + } + } + } + } + } else { + + for (uint8_t count=0; countvpower&0x7f; + buttons[count]->press(false); + if (buttons[count]->justReleased()) { + if (bflags>0) { + if (bflags>1) { + + buttons[count]->vpower&=0x7f; + RA8876_MQTT(count,"PBT"); + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + } + } + if (!bflags) { + + uint8_t pwr=bitRead(power,rbutt); + uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; + if (pwr!=vpwr) { + RA8876_RDW_BUTT(count,pwr); + } + rbutt++; + } + } + } + ra8876_pLoc.x=0; + ra8876_pLoc.y=0; + } +} +} +#endif +# 424 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_10_RA8876.ino" +bool Xdsp10(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + RA8876_InitDriver(); + } + else if (XDSP_10 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_EVERY_50_MSECOND: +#ifdef USE_TOUCH_BUTTONS + if (FT5316_found) FT5316Check(); +#endif + break; + } + } + return result; +} +#endif +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_interface.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_interface.ino" +#ifdef USE_DISPLAY + +#ifdef XFUNC_PTR_IN_ROM +bool (* const xdsp_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xdsp_func_ptr[])(uint8_t) = { +#endif + +#ifdef XDSP_01 + &Xdsp01, +#endif + +#ifdef XDSP_02 + &Xdsp02, +#endif + +#ifdef XDSP_03 + &Xdsp03, +#endif + +#ifdef XDSP_04 + &Xdsp04, +#endif + +#ifdef XDSP_05 + &Xdsp05, +#endif + +#ifdef XDSP_06 + &Xdsp06, +#endif + +#ifdef XDSP_07 + &Xdsp07, +#endif + +#ifdef XDSP_08 + &Xdsp08, +#endif + +#ifdef XDSP_09 + &Xdsp09, +#endif + +#ifdef XDSP_10 + &Xdsp10, +#endif + +#ifdef XDSP_11 + &Xdsp11, +#endif + +#ifdef XDSP_12 + &Xdsp12, +#endif + +#ifdef XDSP_13 + &Xdsp13, +#endif + +#ifdef XDSP_14 + &Xdsp14, +#endif + +#ifdef XDSP_15 + &Xdsp15, +#endif + +#ifdef XDSP_16 + &Xdsp16 +#endif +}; + +const uint8_t xdsp_present = sizeof(xdsp_func_ptr) / sizeof(xdsp_func_ptr[0]); +# 117 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_interface.ino" +uint8_t XdspPresent(void) +{ + return xdsp_present; +} + +bool XdspCall(uint8_t Function) +{ + bool result = false; + + for (uint32_t x = 0; x < xdsp_present; x++) { + result = xdsp_func_ptr[x](Function); + + if (result && (FUNC_DISPLAY_MODEL == Function)) { + break; + } + } + + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_01_hlw8012.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_01_hlw8012.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_HLW8012 + + + + + + +#define XNRG_01 1 + + +#define HLW_PREF 10000 +#define HLW_UREF 2200 +#define HLW_IREF 4545 + + +#define HJL_PREF 1362 +#define HJL_UREF 822 +#define HJL_IREF 3300 + +#define HLW_POWER_PROBE_TIME 10 +#define HLW_SAMPLE_COUNT 10 + + + +struct HLW { +#ifdef HLW_DEBUG + unsigned long debug[HLW_SAMPLE_COUNT]; +#endif + unsigned long cf_pulse_length = 0; + unsigned long cf_pulse_last_time = 0; + unsigned long cf_power_pulse_length = 0; + + unsigned long cf1_pulse_length = 0; + unsigned long cf1_pulse_last_time = 0; + unsigned long cf1_summed_pulse_length = 0; + unsigned long cf1_pulse_counter = 0; + unsigned long cf1_voltage_pulse_length = 0; + unsigned long cf1_current_pulse_length = 0; + + unsigned long energy_period_counter = 0; + + unsigned long power_ratio = 0; + unsigned long voltage_ratio = 0; + unsigned long current_ratio = 0; + + uint8_t model_type = 0; + uint8_t cf1_timer = 0; + uint8_t power_retry = 0; + bool select_ui_flag = false; + bool ui_flag = true; + bool load_off = true; +} Hlw; + + +#ifndef USE_WS2812_DMA +void HlwCfInterrupt(void) ICACHE_RAM_ATTR; +void HlwCf1Interrupt(void) ICACHE_RAM_ATTR; +#endif + +void HlwCfInterrupt(void) +{ + unsigned long us = micros(); + + if (Hlw.load_off) { + Hlw.cf_pulse_last_time = us; + Hlw.load_off = false; + } else { + Hlw.cf_pulse_length = us - Hlw.cf_pulse_last_time; + Hlw.cf_pulse_last_time = us; + Hlw.energy_period_counter++; + } + Energy.data_valid[0] = 0; +} + +void HlwCf1Interrupt(void) +{ + unsigned long us = micros(); + + 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)) { + Hlw.cf1_summed_pulse_length += Hlw.cf1_pulse_length; +#ifdef HLW_DEBUG + Hlw.debug[Hlw.cf1_pulse_counter] = Hlw.cf1_pulse_length; +#endif + Hlw.cf1_pulse_counter++; + if (HLW_SAMPLE_COUNT == Hlw.cf1_pulse_counter) { + Hlw.cf1_timer = 8; + } + } + Energy.data_valid[0] = 0; +} + + + +void HlwEvery200ms(void) +{ + unsigned long cf1_pulse_length = 0; + unsigned long hlw_w = 0; + unsigned long hlw_u = 0; + unsigned long hlw_i = 0; + + if (micros() - Hlw.cf_pulse_last_time > (HLW_POWER_PROBE_TIME * 1000000)) { + Hlw.cf_pulse_length = 0; + Hlw.load_off = true; + } + Hlw.cf_power_pulse_length = Hlw.cf_pulse_length; + + if (Hlw.cf_power_pulse_length && Energy.power_on && !Hlw.load_off) { + hlw_w = (Hlw.power_ratio * Settings.energy_power_calibration) / Hlw.cf_power_pulse_length ; + Energy.active_power[0] = (float)hlw_w / 10; + Hlw.power_retry = 1; + } else { + if (Hlw.power_retry) { + Hlw.power_retry--; + } else { + Energy.active_power[0] = 0; + } + } + + if (pin[GPIO_NRG_CF1] < 99) { + Hlw.cf1_timer++; + if (Hlw.cf1_timer >= 8) { + Hlw.cf1_timer = 0; + Hlw.select_ui_flag = (Hlw.select_ui_flag) ? false : true; + if (pin[GPIO_NRG_SEL] < 99) { + digitalWrite(pin[GPIO_NRG_SEL], Hlw.select_ui_flag); + } + + if (Hlw.cf1_pulse_counter) { + cf1_pulse_length = Hlw.cf1_summed_pulse_length / Hlw.cf1_pulse_counter; + } + +#ifdef HLW_DEBUG + + char stemp[100]; + stemp[0] = '\0'; + for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, Hlw.debug[i]); + } + for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) { + for (uint32_t j = i + 1; j < Hlw.cf1_pulse_counter; j++) { + if (Hlw.debug[i] > Hlw.debug[j]) { + std::swap(Hlw.debug[i], Hlw.debug[j]); + } + } + } + unsigned long median = Hlw.debug[(Hlw.cf1_pulse_counter +1) / 2]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: power %d, ui %d, cnt %d, smpl%s, sum %d, mean %d, median %d"), + Hlw.cf_power_pulse_length , Hlw.select_ui_flag, Hlw.cf1_pulse_counter, stemp, Hlw.cf1_summed_pulse_length, cf1_pulse_length, median); +#endif + + if (Hlw.select_ui_flag == Hlw.ui_flag) { + Hlw.cf1_voltage_pulse_length = cf1_pulse_length; + + if (Hlw.cf1_voltage_pulse_length && Energy.power_on) { + hlw_u = (Hlw.voltage_ratio * Settings.energy_voltage_calibration) / Hlw.cf1_voltage_pulse_length ; + Energy.voltage[0] = (float)hlw_u / 10; + } else { + Energy.voltage[0] = 0; + } + + } else { + Hlw.cf1_current_pulse_length = cf1_pulse_length; + + if (Hlw.cf1_current_pulse_length && Energy.active_power[0]) { + hlw_i = (Hlw.current_ratio * Settings.energy_current_calibration) / Hlw.cf1_current_pulse_length; + Energy.current[0] = (float)hlw_i / 1000; + } else { + Energy.current[0] = 0; + } + + } + Hlw.cf1_summed_pulse_length = 0; + Hlw.cf1_pulse_counter = 0; + } + } +} + +void HlwEverySecond(void) +{ + if (Energy.data_valid[0] > ENERGY_WATCHDOG) { + Hlw.cf1_voltage_pulse_length = 0; + Hlw.cf1_current_pulse_length = 0; + Hlw.cf_power_pulse_length = 0; + } else { + unsigned long hlw_len; + + if (Hlw.energy_period_counter) { + hlw_len = 10000 / Hlw.energy_period_counter; + Hlw.energy_period_counter = 0; + if (hlw_len) { + Energy.kWhtoday_delta += ((Hlw.power_ratio * Settings.energy_power_calibration) / hlw_len) / 36; + EnergyUpdateToday(); + } + } + } +} + +void HlwSnsInit(void) +{ + if (!Settings.energy_power_calibration || (4975 == Settings.energy_power_calibration)) { + Settings.energy_power_calibration = HLW_PREF_PULSE; + Settings.energy_voltage_calibration = HLW_UREF_PULSE; + Settings.energy_current_calibration = HLW_IREF_PULSE; + } + + if (Hlw.model_type) { + Hlw.power_ratio = HJL_PREF; + Hlw.voltage_ratio = HJL_UREF; + Hlw.current_ratio = HJL_IREF; + } else { + Hlw.power_ratio = HLW_PREF; + Hlw.voltage_ratio = HLW_UREF; + Hlw.current_ratio = HLW_IREF; + } + + if (pin[GPIO_NRG_SEL] < 99) { + pinMode(pin[GPIO_NRG_SEL], OUTPUT); + digitalWrite(pin[GPIO_NRG_SEL], Hlw.select_ui_flag); + } + if (pin[GPIO_NRG_CF1] < 99) { + pinMode(pin[GPIO_NRG_CF1], INPUT_PULLUP); + attachInterrupt(pin[GPIO_NRG_CF1], HlwCf1Interrupt, FALLING); + } + pinMode(pin[GPIO_HLW_CF], INPUT_PULLUP); + attachInterrupt(pin[GPIO_HLW_CF], HlwCfInterrupt, FALLING); +} + +void HlwDrvInit(void) +{ + Hlw.model_type = 0; + if (pin[GPIO_HJL_CF] < 99) { + pin[GPIO_HLW_CF] = pin[GPIO_HJL_CF]; + pin[GPIO_HJL_CF] = 99; + Hlw.model_type = 1; + } + + if (pin[GPIO_HLW_CF] < 99) { + + Hlw.ui_flag = true; + if (pin[GPIO_NRG_SEL_INV] < 99) { + pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV]; + pin[GPIO_NRG_SEL_INV] = 99; + Hlw.ui_flag = false; + } + + if (pin[GPIO_NRG_CF1] < 99) { + if (99 == pin[GPIO_NRG_SEL]) { + Energy.current_available = false; + } + } else { + Energy.current_available = false; + Energy.voltage_available = false; + } + + energy_flg = XNRG_01; + } +} + +bool HlwCommand(void) +{ + bool serviced = true; + + if ((CMND_POWERCAL == Energy.command_code) || (CMND_VOLTAGECAL == Energy.command_code) || (CMND_CURRENTCAL == Energy.command_code)) { + + } + else if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && Hlw.cf_power_pulse_length ) { + Settings.energy_power_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf_power_pulse_length ) / Hlw.power_ratio; + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && Hlw.cf1_voltage_pulse_length ) { + Settings.energy_voltage_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf1_voltage_pulse_length ) / Hlw.voltage_ratio; + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && Hlw.cf1_current_pulse_length) { + Settings.energy_current_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data)) * Hlw.cf1_current_pulse_length) / Hlw.current_ratio; + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg01(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_200_MSECOND: + HlwEvery200ms(); + break; + case FUNC_ENERGY_EVERY_SECOND: + HlwEverySecond(); + break; + case FUNC_COMMAND: + result = HlwCommand(); + break; + case FUNC_INIT: + HlwSnsInit(); + break; + case FUNC_PRE_INIT: + HlwDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_02_cse7766.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_02_cse7766.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_CSE7766 + + + + + + + +#define XNRG_02 2 + +#define CSE_MAX_INVALID_POWER 128 + +#define CSE_NOT_CALIBRATED 0xAA + +#define CSE_PULSES_NOT_INITIALIZED -1 + +#define CSE_PREF 1000 +#define CSE_UREF 100 + +struct CSE { + long voltage_cycle = 0; + long current_cycle = 0; + long power_cycle = 0; + long power_cycle_first = 0; + long cf_pulses = 0; + long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; + + uint8_t power_invalid = 0; + bool received = false; +} Cse; + +void CseReceived(void) +{ + + + + + + + uint8_t header = serial_in_buffer[0]; + if ((header & 0xFC) == 0xFC) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Abnormal hardware")); + return; + } + + + if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) { + long voltage_coefficient = 191200; + if (CSE_NOT_CALIBRATED != header) { + voltage_coefficient = serial_in_buffer[2] << 16 | serial_in_buffer[3] << 8 | serial_in_buffer[4]; + } + Settings.energy_voltage_calibration = voltage_coefficient / CSE_UREF; + } + if (HLW_IREF_PULSE == Settings.energy_current_calibration) { + long current_coefficient = 16140; + if (CSE_NOT_CALIBRATED != header) { + current_coefficient = serial_in_buffer[8] << 16 | serial_in_buffer[9] << 8 | serial_in_buffer[10]; + } + Settings.energy_current_calibration = current_coefficient; + } + if (HLW_PREF_PULSE == Settings.energy_power_calibration) { + long power_coefficient = 5364000; + if (CSE_NOT_CALIBRATED != header) { + power_coefficient = serial_in_buffer[14] << 16 | serial_in_buffer[15] << 8 | serial_in_buffer[16]; + } + Settings.energy_power_calibration = power_coefficient / CSE_PREF; + } + + uint8_t adjustement = serial_in_buffer[20]; + Cse.voltage_cycle = serial_in_buffer[5] << 16 | serial_in_buffer[6] << 8 | serial_in_buffer[7]; + Cse.current_cycle = serial_in_buffer[11] << 16 | serial_in_buffer[12] << 8 | serial_in_buffer[13]; + Cse.power_cycle = serial_in_buffer[17] << 16 | serial_in_buffer[18] << 8 | serial_in_buffer[19]; + Cse.cf_pulses = serial_in_buffer[21] << 8 | serial_in_buffer[22]; + + if (Energy.power_on) { + if (adjustement & 0x40) { + Energy.voltage[0] = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)Cse.voltage_cycle; + } + if (adjustement & 0x10) { + Cse.power_invalid = 0; + if ((header & 0xF2) == 0xF2) { + Energy.active_power[0] = 0; + } else { + if (0 == Cse.power_cycle_first) { Cse.power_cycle_first = Cse.power_cycle; } + if (Cse.power_cycle_first != Cse.power_cycle) { + Cse.power_cycle_first = -1; + Energy.active_power[0] = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)Cse.power_cycle; + } else { + Energy.active_power[0] = 0; + } + } + } else { + if (Cse.power_invalid < Settings.param[P_CSE7766_INVALID_POWER]) { + Cse.power_invalid++; + } else { + Cse.power_cycle_first = 0; + Energy.active_power[0] = 0; + } + } + if (adjustement & 0x20) { + if (0 == Energy.active_power[0]) { + Energy.current[0] = 0; + } else { + Energy.current[0] = (float)Settings.energy_current_calibration / (float)Cse.current_cycle; + } + } + } else { + Cse.power_cycle_first = 0; + Energy.voltage[0] = 0; + Energy.active_power[0] = 0; + Energy.current[0] = 0; + } +} + +bool CseSerialInput(void) +{ + if (Cse.received) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (24 == serial_in_byte_counter) { + + AddLogSerial(LOG_LEVEL_DEBUG_MORE); + + uint8_t checksum = 0; + for (uint32_t i = 2; i < 23; i++) { checksum += serial_in_buffer[i]; } + if (checksum == serial_in_buffer[23]) { + Energy.data_valid[0] = 0; + CseReceived(); + Cse.received = false; + return true; + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); + do { + memmove(serial_in_buffer, serial_in_buffer +1, 24); + serial_in_byte_counter--; + } while ((serial_in_byte_counter > 2) && (0x5A != serial_in_buffer[1])); + if (0x5A != serial_in_buffer[1]) { + Cse.received = false; + serial_in_byte_counter = 0; + } + } + } + } else { + if ((0x5A == serial_in_byte) && (1 == serial_in_byte_counter)) { + Cse.received = true; + } else { + serial_in_byte_counter = 0; + } + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + } + serial_in_byte = 0; + return false; +} + + + +void CseEverySecond(void) +{ + if (Energy.data_valid[0] > ENERGY_WATCHDOG) { + Cse.voltage_cycle = 0; + Cse.current_cycle = 0; + Cse.power_cycle = 0; + } else { + long cf_frequency = 0; + + if (CSE_PULSES_NOT_INITIALIZED == Cse.cf_pulses_last_time) { + Cse.cf_pulses_last_time = Cse.cf_pulses; + } else { + if (Cse.cf_pulses < Cse.cf_pulses_last_time) { + cf_frequency = (65536 - Cse.cf_pulses_last_time) + Cse.cf_pulses; + } else { + cf_frequency = Cse.cf_pulses - Cse.cf_pulses_last_time; + } + if (cf_frequency && Energy.active_power[0]) { + unsigned long delta = (cf_frequency * Settings.energy_power_calibration) / 36; + + if (delta <= (3680*100/36) * 10 ) { + Cse.cf_pulses_last_time = Cse.cf_pulses; + Energy.kWhtoday_delta += delta; + } + else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Load overflow")); + Cse.cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; + } + EnergyUpdateToday(); + } + } + } +} + +void CseDrvInit(void) +{ + if ((3 == pin[GPIO_CSE7766_RX]) && (1 == pin[GPIO_CSE7766_TX])) { + baudrate = 4800; + serial_config = SERIAL_8E1; + if (0 == Settings.param[P_CSE7766_INVALID_POWER]) { + Settings.param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; + } + Cse.power_invalid = Settings.param[P_CSE7766_INVALID_POWER]; + energy_flg = XNRG_02; + } +} + +bool CseCommand(void) +{ + bool serviced = true; + + if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && Cse.power_cycle) { + Settings.energy_power_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.power_cycle) / CSE_PREF; + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && Cse.voltage_cycle) { + Settings.energy_voltage_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.voltage_cycle) / CSE_UREF; + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && Cse.current_cycle) { + Settings.energy_current_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.current_cycle) / 1000; + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg02(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SERIAL: + result = CseSerialInput(); + break; + case FUNC_ENERGY_EVERY_SECOND: + CseEverySecond(); + break; + case FUNC_COMMAND: + result = CseCommand(); + break; + case FUNC_PRE_INIT: + CseDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_03_pzem004t.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_03_pzem004t.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM004T +# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_03_pzem004t.ino" +#define XNRG_03 3 + +#include + +TasmotaSerial *PzemSerial = nullptr; + +#define PZEM_VOLTAGE (uint8_t)0xB0 +#define RESP_VOLTAGE (uint8_t)0xA0 + +#define PZEM_CURRENT (uint8_t)0xB1 +#define RESP_CURRENT (uint8_t)0xA1 + +#define PZEM_POWER (uint8_t)0xB2 +#define RESP_POWER (uint8_t)0xA2 + +#define PZEM_ENERGY (uint8_t)0xB3 +#define RESP_ENERGY (uint8_t)0xA3 + +#define PZEM_SET_ADDRESS (uint8_t)0xB4 +#define RESP_SET_ADDRESS (uint8_t)0xA4 + +#define PZEM_POWER_ALARM (uint8_t)0xB5 +#define RESP_POWER_ALARM (uint8_t)0xA5 + +#define PZEM_DEFAULT_READ_TIMEOUT 500 + + + +struct PZEM { + float energy = 0; + uint8_t send_retry = 0; + uint8_t read_state = 0; + uint8_t phase = 0; + uint8_t address = 0; +} Pzem; + +struct PZEMCommand { + uint8_t command; + uint8_t addr[4]; + uint8_t data; + uint8_t crc; +}; + +uint8_t PzemCrc(uint8_t *data) +{ + uint16_t crc = 0; + for (uint32_t i = 0; i < sizeof(PZEMCommand) -1; i++) { + crc += *data++; + } + return (uint8_t)(crc & 0xFF); +} + +void PzemSend(uint8_t cmd) +{ + PZEMCommand pzem; + + pzem.command = cmd; + pzem.addr[0] = 0; + pzem.addr[1] = 0; + pzem.addr[2] = 0; + pzem.addr[3] = ((PZEM_SET_ADDRESS == cmd) && Pzem.address) ? Pzem.address : 1 + Pzem.phase; + pzem.data = 0; + + uint8_t *bytes = (uint8_t*)&pzem; + pzem.crc = PzemCrc(bytes); + + PzemSerial->flush(); + PzemSerial->write(bytes, sizeof(pzem)); + + Pzem.address = 0; +} + +bool PzemReceiveReady(void) +{ + return PzemSerial->available() >= (int)sizeof(PZEMCommand); +} + +bool PzemRecieve(uint8_t resp, float *data) +{ +# 120 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_03_pzem004t.ino" + uint8_t buffer[sizeof(PZEMCommand)] = { 0 }; + + unsigned long start = millis(); + uint8_t len = 0; + while ((len < sizeof(PZEMCommand)) && (millis() - start < PZEM_DEFAULT_READ_TIMEOUT)) { + if (PzemSerial->available() > 0) { + uint8_t c = (uint8_t)PzemSerial->read(); + if (!c && !len) { + continue; + } + if ((1 == len) && (buffer[0] == c)) { + len--; + continue; + } + buffer[len++] = c; + } + } + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, len); + + if (len != sizeof(PZEMCommand)) { + + return false; + } + if (buffer[6] != PzemCrc(buffer)) { + + return false; + } + if (buffer[0] != resp) { + + return false; + } + + switch (resp) { + case RESP_VOLTAGE: + *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 10.0); + break; + case RESP_CURRENT: + *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 100.0); + break; + case RESP_POWER: + *data = (float)(buffer[1] << 8) + buffer[2]; + break; + case RESP_ENERGY: + *data = (float)((uint32_t)buffer[1] << 16) + ((uint16_t)buffer[2] << 8) + buffer[3]; + break; + } + return true; +} + + + +const uint8_t pzem_commands[] { PZEM_SET_ADDRESS, PZEM_VOLTAGE, PZEM_CURRENT, PZEM_POWER, PZEM_ENERGY }; +const uint8_t pzem_responses[] { RESP_SET_ADDRESS, RESP_VOLTAGE, RESP_CURRENT, RESP_POWER, RESP_ENERGY }; + +void PzemEvery200ms(void) +{ + bool data_ready = PzemReceiveReady(); + + if (data_ready) { + float value = 0; + if (PzemRecieve(pzem_responses[Pzem.read_state], &value)) { + Energy.data_valid[Pzem.phase] = 0; + switch (Pzem.read_state) { + case 1: + Energy.voltage[Pzem.phase] = value; + break; + case 2: + Energy.current[Pzem.phase] = value; + break; + case 3: + Energy.active_power[Pzem.phase] = value; + break; + case 4: + Pzem.energy += value; + if (Pzem.phase == Energy.phase_count -1) { + EnergyUpdateTotal(Pzem.energy, false); + Pzem.energy = 0; + } + break; + } + Pzem.read_state++; + if (5 == Pzem.read_state) { + Pzem.read_state = 1; + } + } + } + + if (0 == Pzem.send_retry || data_ready) { + Pzem.phase++; + if (Pzem.phase >= Energy.phase_count) { + Pzem.phase = 0; + } + if (Pzem.address) { + Pzem.read_state = 0; + } + Pzem.send_retry = 5; + PzemSend(pzem_commands[Pzem.read_state]); + } + else { + Pzem.send_retry--; + if ((Energy.phase_count > 1) && (0 == Pzem.send_retry) && (uptime < 30)) { + Energy.phase_count--; + } + } +} + +void PzemSnsInit(void) +{ + + PzemSerial = new TasmotaSerial(pin[GPIO_PZEM004_RX], pin[GPIO_PZEM0XX_TX], 1); + if (PzemSerial->begin(9600)) { + if (PzemSerial->hardwareSerial()) { + ClaimSerial(); + } + Energy.phase_count = 3; + Pzem.phase = 2; + Pzem.read_state = 1; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemDrvInit(void) +{ + if ((pin[GPIO_PZEM004_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_03; + } +} + +bool PzemCommand(void) +{ + bool serviced = true; + + if (CMND_MODULEADDRESS == Energy.command_code) { + Pzem.address = XdrvMailbox.payload; + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg03(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_200_MSECOND: + if (PzemSerial) { PzemEvery200ms(); } + break; + case FUNC_COMMAND: + result = PzemCommand(); + break; + case FUNC_INIT: + PzemSnsInit(); + break; + case FUNC_PRE_INIT: + PzemDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_04_mcp39f501.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_04_mcp39f501.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_MCP39F501 + + + + + + + +#define XNRG_04 4 + +#define MCP_BAUDRATE 4800 +#define MCP_TIMEOUT 4 +#define MCP_CALIBRATION_TIMEOUT 2 + +#define MCP_CALIBRATE_POWER 0x001 +#define MCP_CALIBRATE_VOLTAGE 0x002 +#define MCP_CALIBRATE_CURRENT 0x004 +#define MCP_CALIBRATE_FREQUENCY 0x008 +#define MCP_SINGLE_WIRE_FLAG 0x100 + +#define MCP_START_FRAME 0xA5 +#define MCP_ACK_FRAME 0x06 +#define MCP_ERROR_NAK 0x15 +#define MCP_ERROR_CRC 0x51 + +#define MCP_SINGLE_WIRE 0xAB + +#define MCP_SET_ADDRESS 0x41 + +#define MCP_READ 0x4E +#define MCP_READ_16 0x52 +#define MCP_READ_32 0x44 + +#define MCP_WRITE 0x4D +#define MCP_WRITE_16 0x57 +#define MCP_WRITE_32 0x45 + +#define MCP_SAVE_REGISTERS 0x53 + +#define MCP_CALIBRATION_BASE 0x0028 +#define MCP_CALIBRATION_LEN 52 + +#define MCP_FREQUENCY_REF_BASE 0x0094 +#define MCP_FREQUENCY_GAIN_BASE 0x00AE +#define MCP_FREQUENCY_LEN 4 + +#define MCP_BUFFER_SIZE 60 + +#include +TasmotaSerial *McpSerial = nullptr; + +typedef struct mcp_cal_registers_type { + uint16_t gain_current_rms; + uint16_t gain_voltage_rms; + uint16_t gain_active_power; + uint16_t gain_reactive_power; + sint32_t offset_current_rms; + sint32_t offset_active_power; + sint32_t offset_reactive_power; + sint16_t dc_offset_current; + sint16_t phase_compensation; + uint16_t apparent_power_divisor; + + uint32_t system_configuration; + uint16_t dio_configuration; + uint32_t range; + + uint32_t calibration_current; + uint16_t calibration_voltage; + uint32_t calibration_active_power; + uint32_t calibration_reactive_power; + uint16_t accumulation_interval; +} mcp_cal_registers_type; + +char *mcp_buffer = nullptr; +unsigned long mcp_window = 0; +unsigned long mcp_kWhcounter = 0; +uint32_t mcp_system_configuration = 0x03000000; +uint32_t mcp_active_power; + + +uint32_t mcp_current_rms; +uint16_t mcp_voltage_rms; +uint16_t mcp_line_frequency; + +uint8_t mcp_address = 0; +uint8_t mcp_calibration_active = 0; +uint8_t mcp_init = 0; +uint8_t mcp_timeout = 0; +uint8_t mcp_calibrate = 0; +uint8_t mcp_byte_counter = 0; + + + + + + +uint8_t McpChecksum(uint8_t *data) +{ + uint8_t checksum = 0; + uint8_t offset = 0; + uint8_t len = data[1] -1; + + for (uint32_t i = offset; i < len; i++) { checksum += data[i]; } + return checksum; +} + +unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size) +{ + unsigned long result = 0; + unsigned long pow = 1; + + for (uint32_t i = 0; i < size; i++) { + result = result + (uint8_t)data[offset + i] * pow; + pow = pow * 256; + } + return result; +} + +void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size) +{ + for (uint32_t i = 0; i < size; i++) { + data[offset + i] = ((value >> (i * 8)) & 0xFF); + } +} + +void McpSend(uint8_t *data) +{ + if (mcp_timeout) { return; } + mcp_timeout = MCP_TIMEOUT; + + data[0] = MCP_START_FRAME; + data[data[1] -1] = McpChecksum(data); + + + + for (uint32_t i = 0; i < data[1]; i++) { + McpSerial->write(data[i]); + } +} + + + +void McpGetAddress(void) +{ + uint8_t data[] = { MCP_START_FRAME, 7, MCP_SET_ADDRESS, 0x00, 0x26, MCP_READ_16, 0x00 }; + + McpSend(data); +} + +void McpAddressReceive(void) +{ + + mcp_address = mcp_buffer[3]; +} + + + +void McpGetCalibration(void) +{ + if (mcp_calibration_active) { return; } + mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; + + uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, (MCP_CALIBRATION_BASE >> 8) & 0xFF, MCP_CALIBRATION_BASE & 0xFF, MCP_READ, MCP_CALIBRATION_LEN, 0x00 }; + + McpSend(data); +} + +void McpParseCalibration(void) +{ + bool action = false; + mcp_cal_registers_type cal_registers; + + + cal_registers.gain_current_rms = McpExtractInt(mcp_buffer, 2, 2); + cal_registers.gain_voltage_rms = McpExtractInt(mcp_buffer, 4, 2); + cal_registers.gain_active_power = McpExtractInt(mcp_buffer, 6, 2); + cal_registers.gain_reactive_power = McpExtractInt(mcp_buffer, 8, 2); + cal_registers.offset_current_rms = McpExtractInt(mcp_buffer, 10, 4); + cal_registers.offset_active_power = McpExtractInt(mcp_buffer, 14, 4); + cal_registers.offset_reactive_power = McpExtractInt(mcp_buffer, 18, 4); + cal_registers.dc_offset_current = McpExtractInt(mcp_buffer, 22, 2); + cal_registers.phase_compensation = McpExtractInt(mcp_buffer, 24, 2); + cal_registers.apparent_power_divisor = McpExtractInt(mcp_buffer, 26, 2); + + cal_registers.system_configuration = McpExtractInt(mcp_buffer, 28, 4); + cal_registers.dio_configuration = McpExtractInt(mcp_buffer, 32, 2); + cal_registers.range = McpExtractInt(mcp_buffer, 34, 4); + + cal_registers.calibration_current = McpExtractInt(mcp_buffer, 38, 4); + cal_registers.calibration_voltage = McpExtractInt(mcp_buffer, 42, 2); + cal_registers.calibration_active_power = McpExtractInt(mcp_buffer, 44, 4); + cal_registers.calibration_reactive_power = McpExtractInt(mcp_buffer, 48, 4); + cal_registers.accumulation_interval = McpExtractInt(mcp_buffer, 52, 2); + + if (mcp_calibrate & MCP_CALIBRATE_POWER) { + cal_registers.calibration_active_power = Settings.energy_power_calibration; + if (McpCalibrationCalc(&cal_registers, 16)) { action = true; } + } + if (mcp_calibrate & MCP_CALIBRATE_VOLTAGE) { + cal_registers.calibration_voltage = Settings.energy_voltage_calibration; + if (McpCalibrationCalc(&cal_registers, 0)) { action = true; } + } + if (mcp_calibrate & MCP_CALIBRATE_CURRENT) { + cal_registers.calibration_current = Settings.energy_current_calibration; + if (McpCalibrationCalc(&cal_registers, 8)) { action = true; } + } + mcp_timeout = 0; + if (action) { McpSetCalibration(&cal_registers); } + + mcp_calibrate = 0; + + Settings.energy_power_calibration = cal_registers.calibration_active_power; + Settings.energy_voltage_calibration = cal_registers.calibration_voltage; + Settings.energy_current_calibration = cal_registers.calibration_current; + + mcp_system_configuration = cal_registers.system_configuration; + + if (mcp_system_configuration & MCP_SINGLE_WIRE_FLAG) { + mcp_system_configuration &= ~MCP_SINGLE_WIRE_FLAG; + McpSetSystemConfiguration(2); + } +} + +bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t range_shift) +{ + uint32_t measured; + uint32_t expected; + uint16_t *gain; + uint32_t new_gain; + + if (range_shift == 0) { + measured = mcp_voltage_rms; + expected = cal_registers->calibration_voltage; + gain = &(cal_registers->gain_voltage_rms); + } else if (range_shift == 8) { + measured = mcp_current_rms; + expected = cal_registers->calibration_current; + gain = &(cal_registers->gain_current_rms); + } else if (range_shift == 16) { + measured = mcp_active_power; + expected = cal_registers->calibration_active_power; + gain = &(cal_registers->gain_active_power); + } else { + return false; + } + + if (measured == 0) { + return false; + } + + uint32_t range = (cal_registers->range >> range_shift) & 0xFF; + +calc: + new_gain = (*gain) * expected / measured; + + if (new_gain < 25000) { + range++; + if (measured > 6) { + measured = measured / 2; + goto calc; + } + } + + if (new_gain > 55000) { + range--; + measured = measured * 2; + goto calc; + } + + *gain = new_gain; + uint32_t old_range = (cal_registers->range >> range_shift) & 0xFF; + cal_registers->range = cal_registers->range ^ (old_range << range_shift); + cal_registers->range = cal_registers->range | (range << range_shift); + + return true; +} + + + + + + +void McpSetCalibration(struct mcp_cal_registers_type *cal_registers) +{ + uint8_t data[7 + MCP_CALIBRATION_LEN + 2 + 1]; + + data[1] = sizeof(data); + data[2] = MCP_SET_ADDRESS; + data[3] = (MCP_CALIBRATION_BASE >> 8) & 0xFF; + data[4] = (MCP_CALIBRATION_BASE >> 0) & 0xFF; + + data[5] = MCP_WRITE; + data[6] = MCP_CALIBRATION_LEN; + + McpSetInt(cal_registers->gain_current_rms, data, 0+7, 2); + McpSetInt(cal_registers->gain_voltage_rms, data, 2+7, 2); + McpSetInt(cal_registers->gain_active_power, data, 4+7, 2); + McpSetInt(cal_registers->gain_reactive_power, data, 6+7, 2); + McpSetInt(cal_registers->offset_current_rms, data, 8+7, 4); + McpSetInt(cal_registers->offset_active_power, data, 12+7, 4); + McpSetInt(cal_registers->offset_reactive_power, data, 16+7, 4); + McpSetInt(cal_registers->dc_offset_current, data, 20+7, 2); + McpSetInt(cal_registers->phase_compensation, data, 22+7, 2); + McpSetInt(cal_registers->apparent_power_divisor, data, 24+7, 2); + + McpSetInt(cal_registers->system_configuration, data, 26+7, 4); + McpSetInt(cal_registers->dio_configuration, data, 30+7, 2); + McpSetInt(cal_registers->range, data, 32+7, 4); + + McpSetInt(cal_registers->calibration_current, data, 36+7, 4); + McpSetInt(cal_registers->calibration_voltage, data, 40+7, 2); + McpSetInt(cal_registers->calibration_active_power, data, 42+7, 4); + McpSetInt(cal_registers->calibration_reactive_power, data, 46+7, 4); + McpSetInt(cal_registers->accumulation_interval, data, 50+7, 2); + + data[MCP_CALIBRATION_LEN+7] = MCP_SAVE_REGISTERS; + data[MCP_CALIBRATION_LEN+8] = mcp_address; + + McpSend(data); +} + + + +void McpSetSystemConfiguration(uint16 interval) +{ + + uint8_t data[17]; + + data[ 1] = sizeof(data); + data[ 2] = MCP_SET_ADDRESS; + data[ 3] = 0x00; + data[ 4] = 0x42; + data[ 5] = MCP_WRITE_32; + data[ 6] = (mcp_system_configuration >> 24) & 0xFF; + data[ 7] = (mcp_system_configuration >> 16) & 0xFF; + data[ 8] = (mcp_system_configuration >> 8) & 0xFF; + data[ 9] = (mcp_system_configuration >> 0) & 0xFF; + data[10] = MCP_SET_ADDRESS; + data[11] = 0x00; + data[12] = 0x5A; + data[13] = MCP_WRITE_16; + data[14] = (interval >> 8) & 0xFF; + data[15] = (interval >> 0) & 0xFF; + + McpSend(data); +} + + + +void McpGetFrequency(void) +{ + if (mcp_calibration_active) { return; } + mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; + + uint8_t data[] = { MCP_START_FRAME, 11, MCP_SET_ADDRESS, (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF, MCP_FREQUENCY_REF_BASE & 0xFF, MCP_READ_16, + MCP_SET_ADDRESS, (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF, MCP_FREQUENCY_GAIN_BASE & 0xFF, MCP_READ_16, 0x00 }; + + McpSend(data); +} + +void McpParseFrequency(void) +{ + + uint16_t line_frequency_ref = mcp_buffer[2] * 256 + mcp_buffer[3]; + uint16_t gain_line_frequency = mcp_buffer[4] * 256 + mcp_buffer[5]; + + if (mcp_calibrate & MCP_CALIBRATE_FREQUENCY) { + line_frequency_ref = Settings.energy_frequency_calibration; + + if ((0xFFFF == mcp_line_frequency) || (0 == gain_line_frequency)) { + mcp_line_frequency = 50000; + gain_line_frequency = 0x8000; + } + gain_line_frequency = gain_line_frequency * line_frequency_ref / mcp_line_frequency; + + mcp_timeout = 0; + McpSetFrequency(line_frequency_ref, gain_line_frequency); + } + + Settings.energy_frequency_calibration = line_frequency_ref; + + mcp_calibrate = 0; +} + +void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency) +{ + + uint8_t data[17]; + + data[ 1] = sizeof(data); + data[ 2] = MCP_SET_ADDRESS; + data[ 3] = (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF; + data[ 4] = (MCP_FREQUENCY_REF_BASE >> 0) & 0xFF; + + data[ 5] = MCP_WRITE_16; + data[ 6] = (line_frequency_ref >> 8) & 0xFF; + data[ 7] = (line_frequency_ref >> 0) & 0xFF; + + data[ 8] = MCP_SET_ADDRESS; + data[ 9] = (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF; + data[10] = (MCP_FREQUENCY_GAIN_BASE >> 0) & 0xFF; + + data[11] = MCP_WRITE_16; + data[12] = (gain_line_frequency >> 8) & 0xFF; + data[13] = (gain_line_frequency >> 0) & 0xFF; + + data[14] = MCP_SAVE_REGISTERS; + data[15] = mcp_address; + + McpSend(data); +} + + + +void McpGetData(void) +{ + uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, 0x00, 0x04, MCP_READ, 22, 0x00 }; + + McpSend(data); +} + +void McpParseData(void) +{ + + + + + + mcp_current_rms = McpExtractInt(mcp_buffer, 2, 4); + mcp_voltage_rms = McpExtractInt(mcp_buffer, 6, 2); + mcp_active_power = McpExtractInt(mcp_buffer, 8, 4); + + + mcp_line_frequency = McpExtractInt(mcp_buffer, 22, 2); + + if (Energy.power_on) { + Energy.data_valid[0] = 0; + Energy.frequency[0] = (float)mcp_line_frequency / 1000; + Energy.voltage[0] = (float)mcp_voltage_rms / 10; + Energy.active_power[0] = (float)mcp_active_power / 100; + if (0 == Energy.active_power[0]) { + Energy.current[0] = 0; + } else { + Energy.current[0] = (float)mcp_current_rms / 10000; + } + } else { + Energy.data_valid[0] = ENERGY_WATCHDOG; + } +} + + + +void McpSerialInput(void) +{ + while ((McpSerial->available()) && (mcp_byte_counter < MCP_BUFFER_SIZE)) { + yield(); + mcp_buffer[mcp_byte_counter++] = McpSerial->read(); + mcp_window = millis(); + } + + + if ((mcp_byte_counter) && (millis() - mcp_window > (24000 / MCP_BAUDRATE) +1)) { + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)mcp_buffer, mcp_byte_counter); + + if (MCP_BUFFER_SIZE == mcp_byte_counter) { + + } + else if (1 == mcp_byte_counter) { + if (MCP_ERROR_CRC == mcp_buffer[0]) { + + mcp_timeout = 0; + } + else if (MCP_ERROR_NAK == mcp_buffer[0]) { + + mcp_timeout = 0; + } + } + else if (MCP_ACK_FRAME == mcp_buffer[0]) { + if (mcp_byte_counter == mcp_buffer[1]) { + + if (McpChecksum((uint8_t *)mcp_buffer) != mcp_buffer[mcp_byte_counter -1]) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); + } else { + if (5 == mcp_buffer[1]) { McpAddressReceive(); } + if (25 == mcp_buffer[1]) { McpParseData(); } + if (MCP_CALIBRATION_LEN + 3 == mcp_buffer[1]) { McpParseCalibration(); } + if (MCP_FREQUENCY_LEN + 3 == mcp_buffer[1]) { McpParseFrequency(); } + } + + } + mcp_timeout = 0; + } + else if (MCP_SINGLE_WIRE == mcp_buffer[0]) { + mcp_timeout = 0; + } + + mcp_byte_counter = 0; + McpSerial->flush(); + } +} + + + +void McpEverySecond(void) +{ + if (Energy.data_valid[0] > ENERGY_WATCHDOG) { + mcp_voltage_rms = 0; + mcp_current_rms = 0; + mcp_active_power = 0; + mcp_line_frequency = 0; + } + + if (mcp_active_power) { + Energy.kWhtoday_delta += ((mcp_active_power * 10) / 36); + EnergyUpdateToday(); + } + + if (mcp_timeout) { + mcp_timeout--; + } + else if (mcp_calibration_active) { + mcp_calibration_active--; + } + else if (mcp_init) { + if (2 == mcp_init) { + McpGetCalibration(); + } + else if (1 == mcp_init) { + McpGetFrequency(); + } + mcp_init--; + } + else if (!mcp_address) { + McpGetAddress(); + } + else { + McpGetData(); + } +} + +void McpSnsInit(void) +{ + + McpSerial = new TasmotaSerial(pin[GPIO_MCP39F5_RX], pin[GPIO_MCP39F5_TX], 1); + if (McpSerial->begin(MCP_BAUDRATE)) { + if (McpSerial->hardwareSerial()) { + ClaimSerial(); + mcp_buffer = serial_in_buffer; + } else { + mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); + } + if (pin[GPIO_MCP39F5_RST] < 99) { + digitalWrite(pin[GPIO_MCP39F5_RST], 1); + } + } else { + energy_flg = ENERGY_NONE; + } +} + +void McpDrvInit(void) +{ + if ((pin[GPIO_MCP39F5_RX] < 99) && (pin[GPIO_MCP39F5_TX] < 99)) { + if (pin[GPIO_MCP39F5_RST] < 99) { + pinMode(pin[GPIO_MCP39F5_RST], OUTPUT); + digitalWrite(pin[GPIO_MCP39F5_RST], 0); + } + mcp_calibrate = 0; + mcp_timeout = 2; + mcp_init = 2; + energy_flg = XNRG_04; + } +} + +bool McpCommand(void) +{ + bool serviced = true; + unsigned long value = 0; + + if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && mcp_active_power) { + value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 100); + if ((value > 100) && (value < 200000)) { + Settings.energy_power_calibration = value; + mcp_calibrate |= MCP_CALIBRATE_POWER; + McpGetCalibration(); + } + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && mcp_voltage_rms) { + value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10); + if ((value > 1000) && (value < 2600)) { + Settings.energy_voltage_calibration = value; + mcp_calibrate |= MCP_CALIBRATE_VOLTAGE; + McpGetCalibration(); + } + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && mcp_current_rms) { + value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10); + if ((value > 100) && (value < 80000)) { + Settings.energy_current_calibration = value; + mcp_calibrate |= MCP_CALIBRATE_CURRENT; + McpGetCalibration(); + } + } + } + else if (CMND_FREQUENCYSET == Energy.command_code) { + if (XdrvMailbox.data_len && mcp_line_frequency) { + value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 1000); + if ((value > 45000) && (value < 65000)) { + Settings.energy_frequency_calibration = value; + mcp_calibrate |= MCP_CALIBRATE_FREQUENCY; + McpGetFrequency(); + } + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg04(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_LOOP: + if (McpSerial) { McpSerialInput(); } + break; + case FUNC_ENERGY_EVERY_SECOND: + if (McpSerial) { McpEverySecond(); } + break; + case FUNC_COMMAND: + result = McpCommand(); + break; + case FUNC_INIT: + McpSnsInit(); + break; + case FUNC_PRE_INIT: + McpDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_05_pzem_ac.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_05_pzem_ac.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM_AC +# 32 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_05_pzem_ac.ino" +#define XNRG_05 5 + +#define PZEM_AC_DEVICE_ADDRESS 0x01 + +#include +TasmotaModbus *PzemAcModbus; + +struct PZEMAC { + float energy = 0; + uint8_t send_retry = 0; + uint8_t phase = 0; + uint8_t address = 0; + uint8_t address_step = ADDR_IDLE; +} PzemAc; + +void PzemAcEverySecond(void) +{ + bool data_ready = PzemAcModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[30]; + + uint8_t registers = 10; + if (ADDR_RECEIVE == PzemAc.address_step) { + registers = 2; + PzemAc.address_step--; + } + uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, registers); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, PzemAcModbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAC: PzemAc %d error %d"), PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, error); + } else { + Energy.data_valid[PzemAc.phase] = 0; + if (10 == registers) { + + + + + Energy.voltage[PzemAc.phase] = (float)((buffer[3] << 8) + buffer[4]) / 10.0; + Energy.current[PzemAc.phase] = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; + Energy.active_power[PzemAc.phase] = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; + Energy.frequency[PzemAc.phase] = (float)((buffer[17] << 8) + buffer[18]) / 10.0; + Energy.power_factor[PzemAc.phase] = (float)((buffer[19] << 8) + buffer[20]) / 100.0; + + PzemAc.energy += (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); + if (PzemAc.phase == Energy.phase_count -1) { + EnergyUpdateTotal(PzemAc.energy, false); + PzemAc.energy = 0; + } + } + } + } + + if (0 == PzemAc.send_retry || data_ready) { + PzemAc.phase++; + if (PzemAc.phase >= Energy.phase_count) { + PzemAc.phase = 0; + } + PzemAc.send_retry = ENERGY_WATCHDOG; + if (ADDR_SEND == PzemAc.address_step) { + PzemAcModbus->Send(0xF8, 0x06, 0x0002, (uint16_t)PzemAc.address); + PzemAc.address_step--; + } else { + PzemAcModbus->Send(PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, 0x04, 0, 10); + } + } + else { + PzemAc.send_retry--; + if ((Energy.phase_count > 1) && (0 == PzemAc.send_retry) && (uptime < 30)) { + Energy.phase_count--; + } + } +} + +void PzemAcSnsInit(void) +{ + PzemAcModbus = new TasmotaModbus(pin[GPIO_PZEM016_RX], pin[GPIO_PZEM0XX_TX]); + uint8_t result = PzemAcModbus->Begin(9600); + if (result) { + if (2 == result) { ClaimSerial(); } + Energy.phase_count = 3; + PzemAc.phase = 2; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemAcDrvInit(void) +{ + if ((pin[GPIO_PZEM016_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_05; + } +} + +bool PzemAcCommand(void) +{ + bool serviced = true; + + if (CMND_MODULEADDRESS == Energy.command_code) { + PzemAc.address = XdrvMailbox.payload; + PzemAc.address_step = ADDR_SEND; + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg05(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_ENERGY_EVERY_SECOND: + if (uptime > 4) { PzemAcEverySecond(); } + break; + case FUNC_COMMAND: + result = PzemAcCommand(); + break; + case FUNC_INIT: + PzemAcSnsInit(); + break; + case FUNC_PRE_INIT: + PzemAcDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_06_pzem_dc.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_06_pzem_dc.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM_DC +# 32 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_06_pzem_dc.ino" +#define XNRG_06 6 + +#define PZEM_DC_DEVICE_ADDRESS 0x01 + +#include +TasmotaModbus *PzemDcModbus; + +struct PZEMDC { + float energy = 0; + uint8_t send_retry = 0; + uint8_t channel = 0; + uint8_t address = 0; + uint8_t address_step = ADDR_IDLE; +} PzemDc; + +void PzemDcEverySecond(void) +{ + bool data_ready = PzemDcModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[26]; + + uint8_t registers = 8; + if (ADDR_RECEIVE == PzemDc.address_step) { + registers = 2; + PzemDc.address_step--; + } + uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, registers); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, PzemDcModbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PDC: PzemDc %d error %d"), PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, error); + } else { + Energy.data_valid[PzemDc.channel] = 0; + if (8 == registers) { + + + + + Energy.voltage[PzemDc.channel] = (float)((buffer[3] << 8) + buffer[4]) / 100.0; + Energy.current[PzemDc.channel] = (float)((buffer[5] << 8) + buffer[6]) / 100.0; + Energy.active_power[PzemDc.channel] = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; + + PzemDc.energy += (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); + if (PzemDc.channel == Energy.phase_count -1) { + EnergyUpdateTotal(PzemDc.energy, false); + PzemDc.energy = 0; + } + } + } + } + + if (0 == PzemDc.send_retry || data_ready) { + PzemDc.channel++; + if (PzemDc.channel >= Energy.phase_count) { + PzemDc.channel = 0; + } + PzemDc.send_retry = ENERGY_WATCHDOG; + if (ADDR_SEND == PzemDc.address_step) { + PzemDcModbus->Send(0xF8, 0x06, 0x0002, (uint16_t)PzemDc.address); + PzemDc.address_step--; + } else { + PzemDcModbus->Send(PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, 0x04, 0, 8); + } + } + else { + PzemDc.send_retry--; + if ((Energy.phase_count > 1) && (0 == PzemDc.send_retry) && (uptime < 30)) { + Energy.phase_count--; + } + } +} + +void PzemDcSnsInit(void) +{ + PzemDcModbus = new TasmotaModbus(pin[GPIO_PZEM017_RX], pin[GPIO_PZEM0XX_TX]); + uint8_t result = PzemDcModbus->Begin(9600, 2); + if (result) { + if (2 == result) { ClaimSerial(); } + Energy.type_dc = true; + Energy.phase_count = 3; + PzemDc.channel = 2; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemDcDrvInit(void) +{ + if ((pin[GPIO_PZEM017_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_06; + } +} + +bool PzemDcCommand(void) +{ + bool serviced = true; + + if (CMND_MODULEADDRESS == Energy.command_code) { + PzemDc.address = XdrvMailbox.payload; + PzemDc.address_step = ADDR_SEND; + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg06(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_ENERGY_EVERY_SECOND: + if (uptime > 4) { PzemDcEverySecond(); } + break; + case FUNC_COMMAND: + result = PzemDcCommand(); + break; + case FUNC_INIT: + PzemDcSnsInit(); + break; + case FUNC_PRE_INIT: + PzemDcDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_07_ade7953.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_07_ade7953.ino" +#ifdef USE_I2C +#ifdef USE_ENERGY_SENSOR +#ifdef USE_ADE7953 +# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_07_ade7953.ino" +#define XNRG_07 7 + +#define ADE7953_PREF 1540 +#define ADE7953_UREF 26000 +#define ADE7953_IREF 10000 + +#define ADE7953_ADDR 0x38 + +const uint8_t Ade7953Registers[] { + 0x1B, + 0x13, + 0x11, + 0x15, + 0x1A, + 0x12, + 0x10, + 0x14, + 0x1C +}; + +struct Ade7953 { + uint32_t voltage_rms = 0; + uint32_t current_rms[2] = { 0, 0 }; + uint32_t active_power[2] = { 0, 0 }; + uint8_t init_step = 0; +} Ade7953; + +int Ade7953RegSize(uint16_t reg) +{ + int size = 0; + switch ((reg >> 8) & 0x0F) { + case 0x03: + size++; + case 0x02: + size++; + case 0x01: + size++; + case 0x00: + case 0x07: + case 0x08: + size++; + } + return size; +} + +void Ade7953Write(uint16_t reg, uint32_t val) +{ + int size = Ade7953RegSize(reg); + if (size) { + Wire.beginTransmission(ADE7953_ADDR); + Wire.write((reg >> 8) & 0xFF); + Wire.write(reg & 0xFF); + while (size--) { + Wire.write((val >> (8 * size)) & 0xFF); + } + Wire.endTransmission(); + delayMicroseconds(5); + } +} + +int32_t Ade7953Read(uint16_t reg) +{ + uint32_t response = 0; + + int size = Ade7953RegSize(reg); + if (size) { + Wire.beginTransmission(ADE7953_ADDR); + Wire.write((reg >> 8) & 0xFF); + Wire.write(reg & 0xFF); + Wire.endTransmission(0); + Wire.requestFrom(ADE7953_ADDR, size); + if (size <= Wire.available()) { + for (uint32_t i = 0; i < size; i++) { + response = response << 8 | Wire.read(); + } + } + } + return response; +} + +void Ade7953Init(void) +{ + Ade7953Write(0x102, 0x0004); + Ade7953Write(0x0FE, 0x00AD); + Ade7953Write(0x120, 0x0030); +} + +void Ade7953GetData(void) +{ + int32_t reg[2][4]; + for (uint32_t i = 0; i < sizeof(Ade7953Registers); i++) { + int32_t value = Ade7953Read(0x300 + Ade7953Registers[i]); + if (8 == i) { + Ade7953.voltage_rms = value; + } else { + reg[i >> 2][i &3] = value; + } + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: %d, [%d, %d, %d, %d], [%d, %d, %d, %d]"), + Ade7953.voltage_rms, reg[0][0], reg[0][1], reg[0][2], reg[0][3], + reg[1][0], reg[1][1], reg[1][2], reg[1][3]); + + uint32_t apparent_power[2] = { 0, 0 }; + uint32_t reactive_power[2] = { 0, 0 }; + + for (uint32_t channel = 0; channel < 2; channel++) { + Ade7953.current_rms[channel] = reg[channel][0]; + if (Ade7953.current_rms[channel] < 2000) { + Ade7953.current_rms[channel] = 0; + Ade7953.active_power[channel] = 0; + } else { + Ade7953.active_power[channel] = abs(reg[channel][1]); + apparent_power[channel] = abs(reg[channel][2]); + reactive_power[channel] = abs(reg[channel][3]); + } + } + + uint32_t current_rms_sum = Ade7953.current_rms[0] + Ade7953.current_rms[1]; + uint32_t active_power_sum = Ade7953.active_power[0] + Ade7953.active_power[1]; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ADE: U %d, I %d + %d = %d, P %d + %d = %d"), + Ade7953.voltage_rms, Ade7953.current_rms[0], Ade7953.current_rms[1], current_rms_sum, Ade7953.active_power[0], Ade7953.active_power[1], active_power_sum); + + if (Energy.power_on) { + Energy.voltage[0] = (float)Ade7953.voltage_rms / Settings.energy_voltage_calibration; + + for (uint32_t channel = 0; channel < 2; channel++) { + Energy.data_valid[channel] = 0; + Energy.active_power[channel] = (float)Ade7953.active_power[channel] / (Settings.energy_power_calibration / 10); + Energy.reactive_power[channel] = (float)reactive_power[channel] / (Settings.energy_power_calibration / 10); + Energy.apparent_power[channel] = (float)apparent_power[channel] / (Settings.energy_power_calibration / 10); + if (0 == Energy.active_power[channel]) { + Energy.current[channel] = 0; + } else { + Energy.current[channel] = (float)Ade7953.current_rms[channel] / (Settings.energy_current_calibration * 10); + } + } + } else { + Energy.data_valid[0] = ENERGY_WATCHDOG; + Energy.data_valid[1] = ENERGY_WATCHDOG; + } + + if (active_power_sum) { + Energy.kWhtoday_delta += ((active_power_sum * (100000 / (Settings.energy_power_calibration / 10))) / 3600); + EnergyUpdateToday(); + } +} + +void Ade7953EnergyEverySecond() +{ + if (Ade7953.init_step) { + if (1 == Ade7953.init_step) { + Ade7953Init(); + } + Ade7953.init_step--; + } else { + Ade7953GetData(); + } +} + +void Ade7953DrvInit(void) +{ + if (i2c_flg && (pin[GPIO_ADE7953_IRQ] < 99)) { + delay(100); + if (I2cDevice(ADE7953_ADDR)) { + if (HLW_PREF_PULSE == Settings.energy_power_calibration) { + Settings.energy_power_calibration = ADE7953_PREF; + Settings.energy_voltage_calibration = ADE7953_UREF; + Settings.energy_current_calibration = ADE7953_IREF; + } + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "ADE7953", ADE7953_ADDR); + Ade7953.init_step = 2; + + Energy.phase_count = 2; + Energy.voltage_common = true; + + energy_flg = XNRG_07; + } + } +} + +bool Ade7953Command(void) +{ + bool serviced = true; + + uint32_t channel = (2 == XdrvMailbox.index) ? 1 : 0; + uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); + + if (CMND_POWERCAL == Energy.command_code) { + if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_PREF; } + + } + else if (CMND_VOLTAGECAL == Energy.command_code) { + if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_UREF; } + + } + else if (CMND_CURRENTCAL == Energy.command_code) { + if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_IREF; } + + } + else if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && Ade7953.active_power[channel]) { + if ((value > 100) && (value < 200000)) { + Settings.energy_power_calibration = (Ade7953.active_power[channel] * 1000) / value; + } + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && Ade7953.voltage_rms) { + if ((value > 10000) && (value < 26000)) { + Settings.energy_voltage_calibration = (Ade7953.voltage_rms * 100) / value; + } + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && Ade7953.current_rms[channel]) { + if ((value > 2000) && (value < 1000000)) { + Settings.energy_current_calibration = ((Ade7953.current_rms[channel] * 100) / value) * 100; + } + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg07(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_ENERGY_EVERY_SECOND: + Ade7953EnergyEverySecond(); + break; + case FUNC_COMMAND: + result = Ade7953Command(); + break; + case FUNC_PRE_INIT: + Ade7953DrvInit(); + break; + } + return result; +} + +#endif +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_08_sdm120.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_08_sdm120.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SDM120_2 + + + + + + +#define XNRG_08 8 + + +#ifndef SDM120_SPEED + #define SDM120_SPEED 2400 +#endif + +#ifndef SDM120_ADDR + #define SDM120_ADDR 1 +#endif + +#include +TasmotaModbus *Sdm120Modbus; + +const uint8_t sdm120_table = 8; +const uint8_t sdm220_table = 13; + +const uint16_t sdm120_start_addresses[] { + 0x0000, + 0x0006, + 0x000C, + 0x0012, + 0x0018, + 0x001E, + 0x0046, + 0x0156, + + 0X0048, + 0X004A, + 0X004C, + 0X004E, + 0X0024 +}; + +struct SDM120 { + float total_active = 0; + float import_active = NAN; + float import_reactive = 0; + float export_reactive = 0; + float phase_angle = 0; + uint8_t read_state = 0; + uint8_t send_retry = 0; + uint8_t start_address_count = sdm220_table; +} Sdm120; + + + +void SDM120Every250ms(void) +{ + bool data_ready = Sdm120Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; + + uint32_t error = Sdm120Modbus->ReceiveBuffer(buffer, 2); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm120Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM120 error %d"), error); + } else { + Energy.data_valid[0] = 0; + + + + + float value; + ((uint8_t*)&value)[3] = buffer[3]; + ((uint8_t*)&value)[2] = buffer[4]; + ((uint8_t*)&value)[1] = buffer[5]; + ((uint8_t*)&value)[0] = buffer[6]; + + switch(Sdm120.read_state) { + case 0: + Energy.voltage[0] = value; + break; + + case 1: + Energy.current[0] = value; + break; + + case 2: + Energy.active_power[0] = value; + break; + + case 3: + Energy.apparent_power[0] = value; + break; + + case 4: + Energy.reactive_power[0] = value; + break; + + case 5: + Energy.power_factor[0] = value; + break; + + case 6: + Energy.frequency[0] = value; + break; + + case 7: + Sdm120.total_active = value; + break; + + case 8: + Sdm120.import_active = value; + break; + + case 9: + Energy.export_active = value; + break; + + case 10: + Sdm120.import_reactive = value; + break; + + case 11: + Sdm120.export_reactive = value; + break; + + case 12: + Sdm120.phase_angle = value; + break; + } + + Sdm120.read_state++; + if (Sdm120.read_state == Sdm120.start_address_count) { + Sdm120.read_state = 0; + + if (Sdm120.start_address_count > sdm120_table) { + if (!isnan(Sdm120.import_active)) { + Sdm120.total_active = Sdm120.import_active; + } else { + Sdm120.start_address_count = sdm120_table; + } + } + EnergyUpdateTotal(Sdm120.total_active, true); + } + } + } + + if (0 == Sdm120.send_retry || data_ready) { + Sdm120.send_retry = 5; + Sdm120Modbus->Send(SDM120_ADDR, 0x04, sdm120_start_addresses[Sdm120.read_state], 2); + } else { + Sdm120.send_retry--; + } +} + +void Sdm120SnsInit(void) +{ + Sdm120Modbus = new TasmotaModbus(pin[GPIO_SDM120_RX], pin[GPIO_SDM120_TX]); + uint8_t result = Sdm120Modbus->Begin(SDM120_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void Sdm120DrvInit(void) +{ + if ((pin[GPIO_SDM120_RX] < 99) && (pin[GPIO_SDM120_TX] < 99)) { + energy_flg = XNRG_08; + } +} + +void Sdm220Reset(void) +{ + if (isnan(Sdm120.import_active)) { return; } + + Sdm120.import_active = 0; + Sdm120.import_reactive = 0; + Sdm120.export_reactive = 0; + Sdm120.phase_angle = 0; +} + +#ifdef USE_WEBSERVER +const char HTTP_ENERGY_SDM220[] PROGMEM = + "{s}" D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + "{s}" D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + "{s}" D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}"; +#endif + +void Sdm220Show(bool json) +{ + if (isnan(Sdm120.import_active)) { return; } + + char import_active_chr[FLOATSZ]; + dtostrfd(Sdm120.import_active, Settings.flag2.energy_resolution, import_active_chr); + char import_reactive_chr[FLOATSZ]; + dtostrfd(Sdm120.import_reactive, Settings.flag2.energy_resolution, import_reactive_chr); + char export_reactive_chr[FLOATSZ]; + dtostrfd(Sdm120.export_reactive, Settings.flag2.energy_resolution, export_reactive_chr); + char phase_angle_chr[FLOATSZ]; + dtostrfd(Sdm120.phase_angle, 2, phase_angle_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s"), + import_active_chr, import_reactive_chr, export_reactive_chr, phase_angle_chr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_ENERGY_SDM220, import_reactive_chr, export_reactive_chr, phase_angle_chr); +#endif + } +} + + + + + +bool Xnrg08(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { SDM120Every250ms(); } + break; + case FUNC_JSON_APPEND: + Sdm220Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sdm220Show(0); + break; +#endif + case FUNC_ENERGY_RESET: + Sdm220Reset(); + break; + case FUNC_INIT: + Sdm120SnsInit(); + break; + case FUNC_PRE_INIT: + Sdm120DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_09_dds2382.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_09_dds2382.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_DDS2382 + + + + + + +#define XNRG_09 9 + +#ifndef DDS2382_SPEED +#define DDS2382_SPEED 9600 +#endif +#ifndef DDS2382_ADDR +#define DDS2382_ADDR 1 +#endif + +#include +TasmotaModbus *Dds2382Modbus; + +uint8_t Dds2382_send_retry = 0; + +void Dds2382EverySecond(void) +{ + bool data_ready = Dds2382Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[46]; + + uint32_t error = Dds2382Modbus->ReceiveBuffer(buffer, 18); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Dds2382Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "DDS2382 response error %d"), error); + } else { + Energy.data_valid[0] = 0; + + + + + Energy.voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0; + Energy.current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0; + Energy.active_power[0] = (float)((buffer[31] << 8) + buffer[32]); + Energy.reactive_power[0] = (float)((buffer[33] << 8) + buffer[34]); + Energy.power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0; + Energy.frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0; + Energy.export_active = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[13] << 8) + buffer[14]) / 100.0; + + float import_active = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[17] << 8) + buffer[18]) / 100.0; + + EnergyUpdateTotal(import_active, false); + } + } + + if (0 == Dds2382_send_retry || data_ready) { + Dds2382_send_retry = 5; + Dds2382Modbus->Send(DDS2382_ADDR, 0x03, 0, 18); + } else { + Dds2382_send_retry--; + } +} + +void Dds2382SnsInit(void) +{ + Dds2382Modbus = new TasmotaModbus(pin[GPIO_DDS2382_RX], pin[GPIO_DDS2382_TX]); + uint8_t result = Dds2382Modbus->Begin(DDS2382_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void Dds2382DrvInit(void) +{ + if ((pin[GPIO_DDS2382_RX] < 99) && (pin[GPIO_DDS2382_TX] < 99)) { + energy_flg = XNRG_09; + } +} + + + + + +bool Xnrg09(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_ENERGY_EVERY_SECOND: + if (uptime > 4) { Dds2382EverySecond(); } + break; + case FUNC_INIT: + Dds2382SnsInit(); + break; + case FUNC_PRE_INIT: + Dds2382DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_10_sdm630.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_10_sdm630.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SDM630_2 + + + + + + +#define XNRG_10 10 + + +#ifndef SDM630_SPEED + #define SDM630_SPEED 9600 +#endif + +#ifndef SDM630_ADDR + #define SDM630_ADDR 1 +#endif + +#include +TasmotaModbus *Sdm630Modbus; + +const uint16_t sdm630_start_addresses[] { + 0x0000, + 0x0002, + 0x0004, + 0x0006, + 0x0008, + 0x000A, + 0x000C, + 0x000E, + 0x0010, + 0x0018, + 0x001A, + 0x001C, + 0x001E, + 0x0020, + 0x0022, + 0x0156 +}; + +struct SDM630 { + uint8_t read_state = 0; + uint8_t send_retry = 0; +} Sdm630; + + + +void SDM630Every250ms(void) +{ + bool data_ready = Sdm630Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; + + uint32_t error = Sdm630Modbus->ReceiveBuffer(buffer, 2); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm630Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM630 error %d"), error); + } else { + Energy.data_valid[0] = 0; + Energy.data_valid[1] = 0; + Energy.data_valid[2] = 0; + + + + + float value; + ((uint8_t*)&value)[3] = buffer[3]; + ((uint8_t*)&value)[2] = buffer[4]; + ((uint8_t*)&value)[1] = buffer[5]; + ((uint8_t*)&value)[0] = buffer[6]; + + switch(Sdm630.read_state) { + case 0: + Energy.voltage[0] = value; + break; + + case 1: + Energy.voltage[1] = value; + break; + + case 2: + Energy.voltage[2] = value; + break; + + case 3: + Energy.current[0] = value; + break; + + case 4: + Energy.current[1] = value; + break; + + case 5: + Energy.current[2] = value; + break; + + case 6: + Energy.active_power[0] = value; + break; + + case 7: + Energy.active_power[1] = value; + break; + + case 8: + Energy.active_power[2] = value; + break; + + case 9: + Energy.reactive_power[0] = value; + break; + + case 10: + Energy.reactive_power[1] = value; + break; + + case 11: + Energy.reactive_power[2] = value; + break; + + case 12: + Energy.power_factor[0] = value; + break; + + case 13: + Energy.power_factor[1] = value; + break; + + case 14: + Energy.power_factor[2] = value; + break; + + case 15: + EnergyUpdateTotal(value, true); + break; + } + + Sdm630.read_state++; + if (sizeof(sdm630_start_addresses)/2 == Sdm630.read_state) { + Sdm630.read_state = 0; + } + } + } + + if (0 == Sdm630.send_retry || data_ready) { + Sdm630.send_retry = 5; + Sdm630Modbus->Send(SDM630_ADDR, 0x04, sdm630_start_addresses[Sdm630.read_state], 2); + } else { + Sdm630.send_retry--; + } +} + +void Sdm630SnsInit(void) +{ + Sdm630Modbus = new TasmotaModbus(pin[GPIO_SDM630_RX], pin[GPIO_SDM630_TX]); + uint8_t result = Sdm630Modbus->Begin(SDM630_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + Energy.phase_count = 3; + } else { + energy_flg = ENERGY_NONE; + } +} + +void Sdm630DrvInit(void) +{ + if ((pin[GPIO_SDM630_RX] < 99) && (pin[GPIO_SDM630_TX] < 99)) { + energy_flg = XNRG_10; + } +} + + + + + +bool Xnrg10(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { SDM630Every250ms(); } + break; + case FUNC_INIT: + Sdm630SnsInit(); + break; + case FUNC_PRE_INIT: + Sdm630DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_interface.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_interface.ino" +#ifdef USE_ENERGY_SENSOR + +#ifdef XFUNC_PTR_IN_ROM +bool (* const xnrg_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xnrg_func_ptr[])(uint8_t) = { +#endif + +#ifdef XNRG_01 + &Xnrg01, +#endif + +#ifdef XNRG_02 + &Xnrg02, +#endif + +#ifdef XNRG_03 + &Xnrg03, +#endif + +#ifdef XNRG_04 + &Xnrg04, +#endif + +#ifdef XNRG_05 + &Xnrg05, +#endif + +#ifdef XNRG_06 + &Xnrg06, +#endif + +#ifdef XNRG_07 + &Xnrg07, +#endif + +#ifdef XNRG_08 + &Xnrg08, +#endif + +#ifdef XNRG_09 + &Xnrg09, +#endif + +#ifdef XNRG_10 + &Xnrg10, +#endif + +#ifdef XNRG_11 + &Xnrg11, +#endif + +#ifdef XNRG_12 + &Xnrg12, +#endif + +#ifdef XNRG_13 + &Xnrg13, +#endif + +#ifdef XNRG_14 + &Xnrg14, +#endif + +#ifdef XNRG_15 + &Xnrg15, +#endif + +#ifdef XNRG_16 + &Xnrg16 +#endif +}; + +const uint8_t xnrg_present = sizeof(xnrg_func_ptr) / sizeof(xnrg_func_ptr[0]); + +uint8_t xnrg_active = 0; + +bool XnrgCall(uint8_t function) +{ + if (FUNC_PRE_INIT == function) { + for (uint32_t x = 0; x < xnrg_present; x++) { + xnrg_func_ptr[x](function); + if (energy_flg) { + xnrg_active = x; + return true; + } + } + } + else if (energy_flg) { + return xnrg_func_ptr[xnrg_active](function); + } + return false; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xplg_ws2812.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xplg_ws2812.ino" +#ifdef USE_LIGHT +#ifdef USE_WS2812 + + + + +#include + +#if (USE_WS2812_CTYPE == NEO_GRB) + typedef NeoGrbFeature selectedNeoFeatureType; +#elif (USE_WS2812_CTYPE == NEO_BRG) + typedef NeoBrgFeature selectedNeoFeatureType; +#elif (USE_WS2812_CTYPE == NEO_RBG) + typedef NeoRbgFeature selectedNeoFeatureType; +#elif (USE_WS2812_CTYPE == NEO_RGBW) + typedef NeoRgbwFeature selectedNeoFeatureType; +#elif (USE_WS2812_CTYPE == NEO_GRBW) + typedef NeoGrbwFeature selectedNeoFeatureType; +#else + typedef NeoRgbFeature selectedNeoFeatureType; +#endif + +#ifdef USE_WS2812_DMA + + +#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) + typedef NeoEsp8266DmaWs2812xMethod selectedNeoSpeedType; +#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) + typedef NeoEsp8266DmaSk6812Method selectedNeoSpeedType; +#elif (USE_WS2812_HARDWARE == NEO_HW_APA106) + typedef NeoEsp8266DmaApa106Method selectedNeoSpeedType; +#else + typedef NeoEsp8266Dma800KbpsMethod selectedNeoSpeedType; +#endif + +#else + + +#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) + typedef NeoEsp8266BitBangWs2812xMethod selectedNeoSpeedType; +#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) + typedef NeoEsp8266BitBangSk6812Method selectedNeoSpeedType; +#else + typedef NeoEsp8266BitBang800KbpsMethod selectedNeoSpeedType; +#endif + +#endif + +NeoPixelBus *strip = nullptr; + +struct WsColor { + uint8_t red, green, blue; +}; + +struct ColorScheme { + WsColor* colors; + uint8_t count; +}; + +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[WS2812_SCHEMES] = { + kIncandescent, 2, + kRgb, 3, + kChristmas, 2, + kHanukkah, 2, + kwanzaa, 3, + kRainbow, 7, + kFire, 3 }; + +uint8_t kWidth[5] = { + 1, + 2, + 4, + 8, + 255 }; +uint8_t kWsRepeat[5] = { + 8, + 6, + 4, + 2, + 1 }; + +uint8_t ws_show_next = 1; +bool ws_suspend_update = false; + + + +void Ws2812StripShow(void) +{ +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor c; +#else + RgbColor c; +#endif + + if (Settings.light_correction) { + for (uint32_t i = 0; i < Settings.light_pixels; i++) { + c = strip->GetPixelColor(i); + c.R = ledGamma(c.R); + c.G = ledGamma(c.G); + c.B = ledGamma(c.B); +#if (USE_WS2812_CTYPE > NEO_3LED) + c.W = ledGamma(c.W); +#endif + strip->SetPixelColor(i, c); + } + } + strip->Show(); +} + +int mod(int a, int b) +{ + int ret = a % b; + if (ret < 0) ret += b; + return ret; +} + +void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offset) +{ +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor color; +#else + RgbColor color; +#endif + + uint32_t mod_position = mod(position, (int)Settings.light_pixels); + + color = strip->GetPixelColor(mod_position); + float dimmer = 100 / (float)Settings.light_dimmer; + color.R = tmin(color.R + ((hand_color.red / dimmer) * offset), 255); + color.G = tmin(color.G + ((hand_color.green / dimmer) * offset), 255); + color.B = tmin(color.B + ((hand_color.blue / dimmer) * offset), 255); + strip->SetPixelColor(mod_position, color); +} + +void Ws2812UpdateHand(int position, uint32_t index) +{ + uint32_t width = Settings.light_width; + if (index < WS_MARKER) { width = Settings.ws_width[index]; } + if (!width) { return; } + + position = (position + Settings.light_rotation) % Settings.light_pixels; + + if (Settings.flag.ws_clock_reverse) position = Settings.light_pixels -position; + WsColor hand_color = { Settings.ws_color[index][WS_RED], Settings.ws_color[index][WS_GREEN], Settings.ws_color[index][WS_BLUE] }; + + Ws2812UpdatePixelColor(position, hand_color, 1); + + uint32_t range = ((width -1) / 2) +1; + for (uint32_t h = 1; h < range; h++) { + float offset = (float)(range - h) / (float)range; + Ws2812UpdatePixelColor(position -h, hand_color, offset); + Ws2812UpdatePixelColor(position +h, hand_color, offset); + } +} + +void Ws2812Clock(void) +{ + strip->ClearTo(0); + int clksize = 60000 / (int)Settings.light_pixels; + + Ws2812UpdateHand((RtcTime.second * 1000) / clksize, WS_SECOND); + Ws2812UpdateHand((RtcTime.minute * 1000) / clksize, WS_MINUTE); + Ws2812UpdateHand((((RtcTime.hour % 12) * 5000) + ((RtcTime.minute * 1000) / 12 )) / clksize, WS_HOUR); + if (Settings.ws_color[WS_MARKER][WS_RED] + Settings.ws_color[WS_MARKER][WS_GREEN] + Settings.ws_color[WS_MARKER][WS_BLUE]) { + for (uint32_t i = 0; i < 12; i++) { + Ws2812UpdateHand((i * 5000) / clksize, WS_MARKER); + } + } + + Ws2812StripShow(); +} + +void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t range, uint32_t gradRange, uint32_t i) +{ + + + + + ColorScheme scheme = kSchemes[schemenr]; + uint32_t curRange = i / range; + uint32_t rangeIndex = i % range; + uint32_t colorIndex = rangeIndex / gradRange; + uint32_t start = colorIndex; + uint32_t end = colorIndex +1; + if (curRange % 2 != 0) { + start = (scheme.count -1) - start; + end = (scheme.count -1) - end; + } + 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 Ws2812Gradient(uint32_t schemenr) +{ + + + + + +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor c; + c.W = 0; +#else + RgbColor c; +#endif + + ColorScheme scheme = kSchemes[schemenr]; + if (scheme.count < 2) { return; } + + uint32_t repeat = kWsRepeat[Settings.light_width]; + uint32_t range = (uint32_t)ceil((float)Settings.light_pixels / (float)repeat); + uint32_t gradRange = (uint32_t)ceil((float)range / (float)(scheme.count - 1)); + uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); + uint32_t offset = speed > 0 ? Light.strip_timer_counter / speed : 0; + + WsColor oldColor, currentColor; + Ws2812GradientColor(schemenr, &oldColor, range, gradRange, offset); + currentColor = oldColor; + for (uint32_t i = 0; i < Settings.light_pixels; i++) { + if (kWsRepeat[Settings.light_width] > 1) { + Ws2812GradientColor(schemenr, ¤tColor, range, gradRange, i +offset); + } + if (Settings.light_speed > 0) { + + c.R = map(Light.strip_timer_counter % speed, 0, speed, oldColor.red, currentColor.red); + c.G = map(Light.strip_timer_counter % speed, 0, speed, oldColor.green, currentColor.green); + c.B = map(Light.strip_timer_counter % speed, 0, speed, oldColor.blue, currentColor.blue); + } + else { + + c.R = currentColor.red; + c.G = currentColor.green; + c.B = currentColor.blue; + } + strip->SetPixelColor(i, c); + oldColor = currentColor; + } + Ws2812StripShow(); +} + +void Ws2812Bars(uint32_t schemenr) +{ + + + + + +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor c; + c.W = 0; +#else + RgbColor c; +#endif + + ColorScheme scheme = kSchemes[schemenr]; + + uint32_t maxSize = Settings.light_pixels / scheme.count; + if (kWidth[Settings.light_width] > maxSize) { maxSize = 0; } + + uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); + uint32_t offset = (speed > 0) ? Light.strip_timer_counter / speed : 0; + + WsColor mcolor[scheme.count]; + memcpy(mcolor, scheme.colors, sizeof(mcolor)); + float dimmer = 100 / (float)Settings.light_dimmer; + for (uint32_t i = 0; i < scheme.count; i++) { + 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; + } + uint32_t colorIndex = offset % scheme.count; + for (uint32_t i = 0; i < Settings.light_pixels; i++) { + if (maxSize) { 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); + } + Ws2812StripShow(); +} + + + + + +void Ws2812Init(void) +{ + + strip = new NeoPixelBus(WS2812_MAX_LEDS, pin[GPIO_WS2812]); + strip->Begin(); + Ws2812Clear(); +} + +void Ws2812Clear(void) +{ + strip->ClearTo(0); + strip->Show(); + ws_show_next = 1; +} + +void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white) +{ +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor lcolor; + lcolor.W = white; +#else + RgbColor lcolor; +#endif + + lcolor.R = red; + lcolor.G = green; + lcolor.B = blue; + if (led) { + strip->SetPixelColor(led -1, lcolor); + } else { + + for (uint32_t i = 0; i < Settings.light_pixels; i++) { + strip->SetPixelColor(i, lcolor); + } + } + + if (!ws_suspend_update) { + strip->Show(); + ws_show_next = 1; + } +} + +void Ws2812ForceSuspend (void) { + ws_suspend_update = true; +} + +void Ws2812ForceUpdate (void) { + ws_suspend_update = false; + strip->Show(); + ws_show_next = 1; +} + +char* Ws2812GetColor(uint32_t led, char* scolor) +{ + uint8_t sl_ledcolor[4]; + + #if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor lcolor = strip->GetPixelColor(led -1); + sl_ledcolor[3] = lcolor.W; + #else + RgbColor lcolor = strip->GetPixelColor(led -1); + #endif + sl_ledcolor[0] = lcolor.R; + sl_ledcolor[1] = lcolor.G; + sl_ledcolor[2] = lcolor.B; + scolor[0] = '\0'; + for (uint32_t i = 0; i < Light.subtype; 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 Ws2812ShowScheme(uint32_t scheme) +{ + switch (scheme) { + case 0: + if ((1 == state_250mS) || (ws_show_next)) { + Ws2812Clock(); + ws_show_next = 0; + } + break; + default: + if (1 == Settings.light_fade) { + Ws2812Gradient(scheme -1); + } else { + Ws2812Bars(scheme -1); + } + ws_show_next = 1; + break; + } +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_01_counter.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_01_counter.ino" +#ifdef USE_COUNTER + + + + +#define XSNS_01 1 + +#define D_PRFX_COUNTER "Counter" +#define D_CMND_COUNTERTYPE "Type" +#define D_CMND_COUNTERDEBOUNCE "Debounce" + +const char kCounterCommands[] PROGMEM = D_PRFX_COUNTER "|" + "|" D_CMND_COUNTERTYPE "|" D_CMND_COUNTERDEBOUNCE ; + +void (* const CounterCommand[])(void) PROGMEM = + { &CmndCounter, &CmndCounterType, &CmndCounterDebounce }; + +unsigned long last_counter_timer[MAX_COUNTERS]; +uint8_t counter_no_pullup = 0; + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 +void CounterUpdate(uint8_t index) ICACHE_RAM_ATTR; +void CounterUpdate1(void) ICACHE_RAM_ATTR; +void CounterUpdate2(void) ICACHE_RAM_ATTR; +void CounterUpdate3(void) ICACHE_RAM_ATTR; +void CounterUpdate4(void) ICACHE_RAM_ATTR; +#endif + +void CounterUpdate(uint8_t index) +{ + unsigned long counter_debounce_time = micros() - last_counter_timer[index -1]; + if (counter_debounce_time > Settings.pulse_counter_debounce * 1000) { + last_counter_timer[index -1] = micros(); + if (bitRead(Settings.pulse_counter_type, index -1)) { + RtcSettings.pulse_counter[index -1] = counter_debounce_time; + } else { + RtcSettings.pulse_counter[index -1]++; + } + + + } +} + +void CounterUpdate1(void) +{ + CounterUpdate(1); +} + +void CounterUpdate2(void) +{ + CounterUpdate(2); +} + +void CounterUpdate3(void) +{ + CounterUpdate(3); +} + +void CounterUpdate4(void) +{ + CounterUpdate(4); +} + + + +bool CounterPinState(void) +{ + if ((XdrvMailbox.index >= GPIO_CNTR1_NP) && (XdrvMailbox.index < (GPIO_CNTR1_NP + MAX_COUNTERS))) { + bitSet(counter_no_pullup, XdrvMailbox.index - GPIO_CNTR1_NP); + XdrvMailbox.index -= (GPIO_CNTR1_NP - GPIO_CNTR1); + return true; + } + return false; +} + +void CounterInit(void) +{ + typedef void (*function) () ; + function counter_callbacks[] = { CounterUpdate1, CounterUpdate2, CounterUpdate3, CounterUpdate4 }; + + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + pinMode(pin[GPIO_CNTR1 +i], bitRead(counter_no_pullup, i) ? INPUT : INPUT_PULLUP); + attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); + } + } +} + +void CounterSaveState(void) +{ + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + Settings.pulse_counter[i] = RtcSettings.pulse_counter[i]; + } + } +} + +void CounterShow(bool json) +{ + bool header = false; + uint8_t dsxflg = 0; + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + char counter[33]; + if (bitRead(Settings.pulse_counter_type, i)) { + dtostrfd((double)RtcSettings.pulse_counter[i] / 1000000, 6, counter); + } else { + dsxflg++; + snprintf_P(counter, sizeof(counter), PSTR("%lu"), RtcSettings.pulse_counter[i]); + } + + if (json) { + if (!header) { + ResponseAppend_P(PSTR(",\"COUNTER\":{")); + } + ResponseAppend_P(PSTR("%s\"C%d\":%s"), (header)?",":"", i +1, counter); + header = true; +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (1 == dsxflg)) { + DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]); + dsxflg++; + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(PSTR("{s}" D_COUNTER "%d{m}%s%s{e}"), + i +1, counter, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : ""); +#endif + } + } + if (bitRead(Settings.pulse_counter_type, i)) { + RtcSettings.pulse_counter[i] = 0xFFFFFFFF; + } + } + if (header) { + ResponseJsonEnd(); + } +} + + + + + +void CmndCounter(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { + if ((XdrvMailbox.data_len > 0) && (pin[GPIO_CNTR1 + XdrvMailbox.index -1] < 99)) { + if ((XdrvMailbox.data[0] == '-') || (XdrvMailbox.data[0] == '+')) { + RtcSettings.pulse_counter[XdrvMailbox.index -1] += XdrvMailbox.payload; + Settings.pulse_counter[XdrvMailbox.index -1] += XdrvMailbox.payload; + } else { + RtcSettings.pulse_counter[XdrvMailbox.index -1] = XdrvMailbox.payload; + Settings.pulse_counter[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + } + ResponseCmndIdxNumber(RtcSettings.pulse_counter[XdrvMailbox.index -1]); + } +} + +void CmndCounterType(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1) && (pin[GPIO_CNTR1 + XdrvMailbox.index -1] < 99)) { + bitWrite(Settings.pulse_counter_type, XdrvMailbox.index -1, XdrvMailbox.payload &1); + RtcSettings.pulse_counter[XdrvMailbox.index -1] = 0; + Settings.pulse_counter[XdrvMailbox.index -1] = 0; + } + ResponseCmndIdxNumber(bitRead(Settings.pulse_counter_type, XdrvMailbox.index -1)); + } +} + +void CmndCounterDebounce(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { + Settings.pulse_counter_debounce = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.pulse_counter_debounce); +} + + + + + +bool Xsns01(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_JSON_APPEND: + CounterShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + CounterShow(0); + break; +#endif + case FUNC_SAVE_BEFORE_RESTART: + case FUNC_SAVE_AT_MIDNIGHT: + CounterSaveState(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kCounterCommands, CounterCommand); + break; + case FUNC_INIT: + CounterInit(); + break; + case FUNC_PIN_STATE: + result = CounterPinState(); + break; + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_02_analog.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_02_analog.ino" +#ifndef USE_ADC_VCC + + + + +#define XSNS_02 2 + +#define TO_CELSIUS(x) ((x) - 273.15) +#define TO_KELVIN(x) ((x) + 273.15) + + +#define ANALOG_V33 3.3 +#define ANALOG_T0 TO_KELVIN(25.0) + + + + + +#define ANALOG_NTC_BRIDGE_RESISTANCE 32000 +#define ANALOG_NTC_RESISTANCE 10000 +#define ANALOG_NTC_B_COEFFICIENT 3350 + + + + + +#define ANALOG_LDR_BRIDGE_RESISTANCE 10000 +#define ANALOG_LDR_LUX_CALC_SCALAR 12518931 +#define ANALOG_LDR_LUX_CALC_EXPONENT -1.4050 + +uint16_t adc_last_value = 0; +float adc_temp = 0; + +void AdcInit(void) +{ + if ((Settings.adc_param_type != my_adc0) || (Settings.adc_param1 > 1000000) || (Settings.adc_param1 < 100)) { + if (ADC0_TEMP == my_adc0) { + + Settings.adc_param_type = ADC0_TEMP; + Settings.adc_param1 = ANALOG_NTC_BRIDGE_RESISTANCE; + Settings.adc_param2 = ANALOG_NTC_RESISTANCE; + Settings.adc_param3 = ANALOG_NTC_B_COEFFICIENT * 10000; + } + else if (ADC0_LIGHT == my_adc0) { + Settings.adc_param_type = ADC0_LIGHT; + Settings.adc_param1 = ANALOG_LDR_BRIDGE_RESISTANCE; + Settings.adc_param2 = ANALOG_LDR_LUX_CALC_SCALAR; + Settings.adc_param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000; + } + } +} + +uint16_t AdcRead(uint8_t factor) +{ + + + + + + uint8_t samples = 1 << factor; + uint16_t analog = 0; + for (uint32_t i = 0; i < samples; i++) { + analog += analogRead(A0); + delay(1); + } + analog >>= factor; + return analog; +} + +#ifdef USE_RULES +void AdcEvery250ms(void) +{ + if (ADC0_INPUT == my_adc0) { + uint16_t new_value = AdcRead(5); + if ((new_value < adc_last_value -10) || (new_value > adc_last_value +10)) { + adc_last_value = new_value; + uint16_t value = adc_last_value / 10; + Response_P(PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); + XdrvRulesProcess(); + } + } +} +#endif + +uint16_t AdcGetLux() +{ + int adc = AdcRead(2); + + double resistorVoltage = ((double)adc / 1023) * ANALOG_V33; + double ldrVoltage = ANALOG_V33 - resistorVoltage; + double ldrResistance = ldrVoltage / resistorVoltage * (double)Settings.adc_param1; + double ldrLux = (double)Settings.adc_param2 * FastPrecisePow(ldrResistance, (double)Settings.adc_param3 / 10000); + + return (uint16_t)ldrLux; +} + +void AdcEverySecond(void) +{ + if (ADC0_TEMP == my_adc0) { + int adc = AdcRead(2); + + double Rt = (adc * Settings.adc_param1) / (1024.0 * ANALOG_V33 - (double)adc); + double BC = (double)Settings.adc_param3 / 10000; + double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Settings.adc_param2)); + adc_temp = ConvertTemp(TO_CELSIUS(T)); + } +} + +void AdcShow(bool json) +{ + if (ADC0_INPUT == my_adc0) { + uint16_t analog = AdcRead(5); + + if (json) { + ResponseAppend_P(PSTR(",\"ANALOG\":{\"A0\":%d}"), analog); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ANALOG, "", 0, analog); +#endif + } + } + else if (ADC0_TEMP == my_adc0) { + char temperature[33]; + dtostrfd(adc_temp, Settings.flag2.temperature_resolution, temperature); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMP, "ANALOG", temperature); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, adc_temp); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); +#endif + } + } + else if (ADC0_LIGHT == my_adc0) { + uint16_t adc_light = AdcGetLux(); + + if (json) { + ResponseAppend_P(JSON_SNS_ILLUMINANCE, "ANALOG", adc_light); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_ILLUMINANCE, adc_light); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, "", adc_light); +#endif + } + } +} + + + + + +#define D_CMND_ADCPARAM "AdcParam" +const char kAdcCommands[] PROGMEM = "|" + D_CMND_ADC "|" D_CMND_ADCS "|" D_CMND_ADCPARAM; + +void (* const AdcCommand[])(void) PROGMEM = + { &CmndAdc, &CmndAdcs, &CmndAdcParam }; + +void CmndAdc(void) +{ + if (ValidAdc() && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < ADC0_END)) { + Settings.my_adc0 = XdrvMailbox.payload; + restart_flag = 2; + } + char stemp1[TOPSZ]; + Response_P(PSTR("{\"" D_CMND_ADC "0\":{\"%d\":\"%s\"}}"), Settings.my_adc0, GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_adc0, kAdc0Names)); +} + +void CmndAdcs(void) +{ + Response_P(PSTR("{\"" D_CMND_ADCS "\":{")); + bool jsflg = false; + char stemp1[TOPSZ]; + for (uint32_t i = 0; i < ADC0_END; i++) { + if (jsflg) { + ResponseAppend_P(PSTR(",")); + } + jsflg = true; + ResponseAppend_P(PSTR("\"%d\":\"%s\""), i, GetTextIndexed(stemp1, sizeof(stemp1), i, kAdc0Names)); + } + ResponseJsonEndEnd(); +} + +void CmndAdcParam(void) +{ + if (XdrvMailbox.data_len) { + if ((ADC0_TEMP == XdrvMailbox.payload) || (ADC0_LIGHT == XdrvMailbox.payload)) { + + if (strstr(XdrvMailbox.data, ",") != nullptr) { + char sub_string[XdrvMailbox.data_len +1]; + + + Settings.adc_param_type = XdrvMailbox.payload; + + Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); + Settings.adc_param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); + } else { + + + Settings.adc_param_type = 0; + AdcInit(); + } + } + } + + + int value = Settings.adc_param3; + uint8_t precision; + for (precision = 4; precision > 0; precision--) { + if (value % 10) { break; } + value /= 10; + } + char param3[33]; + dtostrfd(((double)Settings.adc_param3)/10000, precision, param3); + Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d,%s]}"), + Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2, param3); +} + + + + + +bool Xsns02(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_COMMAND: + result = DecodeCommand(kAdcCommands, AdcCommand); + break; + default: + if ((ADC0_INPUT == my_adc0) || (ADC0_TEMP == my_adc0) || (ADC0_LIGHT == my_adc0)) { + switch (function) { +#ifdef USE_RULES + case FUNC_EVERY_250_MSECOND: + AdcEvery250ms(); + break; +#endif + case FUNC_EVERY_SECOND: + AdcEverySecond(); + break; + case FUNC_INIT: + AdcInit(); + break; + case FUNC_JSON_APPEND: + AdcShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + AdcShow(0); + break; +#endif + } + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_04_snfsc.ino" +# 56 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_04_snfsc.ino" +#define XSNS_04 4 + +uint16_t sc_value[5] = { 0 }; + +void SonoffScSend(const char *data) +{ + Serial.write(data); + Serial.write('\x1B'); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_TRANSMIT " %s"), data); +} + +void SonoffScInit(void) +{ + + SonoffScSend("AT+START"); + +} + +void SonoffScSerialInput(char *rcvstat) +{ + char *p; + char *str; + uint16_t value[5] = { 0 }; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_RECEIVED " %s"), rcvstat); + + if (!strncasecmp_P(rcvstat, PSTR("AT+UPDATE="), 10)) { + int8_t i = -1; + for (str = strtok_r(rcvstat, ":", &p); str && i < 5; str = strtok_r(nullptr, ":", &p)) { + value[i++] = atoi(str); + } + if (value[0] > 0) { + for (uint32_t i = 0; i < 5; i++) { + sc_value[i] = value[i]; + } + sc_value[2] = (11 - sc_value[2]) * 10; + sc_value[3] *= 10; + sc_value[4] = (11 - sc_value[4]) * 10; + SonoffScSend("AT+SEND=ok"); + } else { + SonoffScSend("AT+SEND=fail"); + } + } + else if (!strcasecmp_P(rcvstat, PSTR("AT+STATUS?"))) { + SonoffScSend("AT+STATUS=4"); + } +} + + + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SCPLUS[] PROGMEM = + "{s}" D_LIGHT "{m}%d%%{e}{s}" D_NOISE "{m}%d%%{e}{s}" D_AIR_QUALITY "{m}%d%%{e}"; +#endif + +void SonoffScShow(bool json) +{ + if (sc_value[0] > 0) { + float t = ConvertTemp(sc_value[1]); + float h = ConvertHumidity(sc_value[0]); + + char temperature[33]; + dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(PSTR(",\"SonoffSC\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), + temperature, humidity, sc_value[2], sc_value[3], sc_value[4]); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]); + DomoticzSensor(DZ_COUNT, sc_value[3]); + DomoticzSensor(DZ_AIRQUALITY, 500 + ((100 - sc_value[4]) * 20)); + } +#endif + +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, t); + KnxSensor(KNX_HUMIDITY, h); + } +#endif + +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, "", humidity); + WSContentSend_PD(HTTP_SNS_SCPLUS, sc_value[2], sc_value[3], sc_value[4]); +#endif + } + } +} + + + + + +bool Xsns04(uint8_t function) +{ + bool result = false; + + if (SONOFF_SC == my_module_type) { + switch (function) { + case FUNC_INIT: + SonoffScInit(); + break; + case FUNC_JSON_APPEND: + SonoffScShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SonoffScShow(0); + break; +#endif + } + } + return result; +} +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_05_ds18b20.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_05_ds18b20.ino" +#ifdef USE_DS18B20 + + + + +#define XSNS_05 5 + +#define W1_SKIP_ROM 0xCC +#define W1_CONVERT_TEMP 0x44 +#define W1_READ_SCRATCHPAD 0xBE + +float ds18b20_temperature = 0; +uint8_t ds18b20_valid = 0; +uint8_t ds18x20_pin = 0; +char ds18b20_types[] = "DS18B20"; + + + + + +uint8_t OneWireReset(void) +{ + uint8_t retries = 125; + + +#ifdef DS18B20_INTERNAL_PULLUP + pinMode(ds18x20_pin, INPUT_PULLUP); +#else + pinMode(ds18x20_pin, INPUT); +#endif + do { + if (--retries == 0) { + return 0; + } + delayMicroseconds(2); + } while (!digitalRead(ds18x20_pin)); + pinMode(ds18x20_pin, OUTPUT); + digitalWrite(ds18x20_pin, LOW); + delayMicroseconds(480); +#ifdef DS18B20_INTERNAL_PULLUP + pinMode(ds18x20_pin, INPUT_PULLUP); +#else + pinMode(ds18x20_pin, INPUT); +#endif + delayMicroseconds(70); + uint8_t r = !digitalRead(ds18x20_pin); + + delayMicroseconds(410); + return r; +} + +void OneWireWriteBit(uint8_t v) +{ + static const uint8_t delay_low[2] = { 65, 10 }; + static const uint8_t delay_high[2] = { 5, 55 }; + + v &= 1; + + digitalWrite(ds18x20_pin, LOW); + pinMode(ds18x20_pin, OUTPUT); + delayMicroseconds(delay_low[v]); + digitalWrite(ds18x20_pin, HIGH); + + delayMicroseconds(delay_high[v]); +} + +uint8_t OneWireReadBit(void) +{ + + pinMode(ds18x20_pin, OUTPUT); + digitalWrite(ds18x20_pin, LOW); + delayMicroseconds(3); +#ifdef DS18B20_INTERNAL_PULLUP + pinMode(ds18x20_pin, INPUT_PULLUP); +#else + pinMode(ds18x20_pin, INPUT); +#endif + delayMicroseconds(10); + uint8_t r = digitalRead(ds18x20_pin); + + delayMicroseconds(53); + return r; +} + +void OneWireWrite(uint8_t v) +{ + for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { + OneWireWriteBit((bit_mask & v) ? 1 : 0); + } +} + +uint8_t OneWireRead(void) +{ + uint8_t r = 0; + + for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { + if (OneWireReadBit()) { + r |= bit_mask; + } + } + return r; +} + +bool OneWireCrc8(uint8_t *addr) +{ + uint8_t crc = 0; + uint8_t len = 8; + + while (len--) { + uint8_t inbyte = *addr++; + for (uint32_t i = 8; i; i--) { + uint8_t mix = (crc ^ inbyte) & 0x01; + crc >>= 1; + if (mix) { + crc ^= 0x8C; + } + inbyte >>= 1; + } + } + return (crc == *addr); +} + + + +void Ds18b20Convert(void) +{ + OneWireReset(); + OneWireWrite(W1_SKIP_ROM); + OneWireWrite(W1_CONVERT_TEMP); + +} + +bool Ds18b20Read(void) +{ + uint8_t data[9]; + int8_t sign = 1; + + if (ds18b20_valid) { ds18b20_valid--; } + + + + + + + for (uint32_t retry = 0; retry < 3; retry++) { + OneWireReset(); + OneWireWrite(W1_SKIP_ROM); + OneWireWrite(W1_READ_SCRATCHPAD); + for (uint32_t i = 0; i < 9; i++) { + data[i] = OneWireRead(); + } + if (OneWireCrc8(data)) { + uint16_t temp12 = (data[1] << 8) + data[0]; + if (temp12 > 2047) { + temp12 = (~temp12) +1; + sign = -1; + } + ds18b20_temperature = ConvertTemp(sign * temp12 * 0.0625); + ds18b20_valid = SENSOR_MAX_MISS; + return true; + } + } + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); + return false; +} + + + +void Ds18b20EverySecond(void) +{ + ds18x20_pin = pin[GPIO_DSB]; + if (uptime &1) { + + Ds18b20Convert(); + } else { + + if (!Ds18b20Read()) { + AddLogMissed(ds18b20_types, ds18b20_valid); + } + } +} + +void Ds18b20Show(bool json) +{ + if (ds18b20_valid) { + char temperature[33]; + dtostrfd(ds18b20_temperature, Settings.flag2.temperature_resolution, temperature); + if(json) { + ResponseAppend_P(JSON_SNS_TEMP, ds18b20_types, temperature); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, ds18b20_temperature); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, ds18b20_types, temperature, TempUnit()); +#endif + } + } +} + + + + + +bool Xsns05(uint8_t function) +{ + bool result = false; + + if (pin[GPIO_DSB] < 99) { + switch (function) { + case FUNC_EVERY_SECOND: + Ds18b20EverySecond(); + break; + case FUNC_JSON_APPEND: + Ds18b20Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ds18b20Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_05_ds18x20.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_05_ds18x20.ino" +#ifdef USE_DS18x20 + + + + +#define XSNS_05 5 + + + +#define DS18S20_CHIPID 0x10 +#define DS1822_CHIPID 0x22 +#define DS18B20_CHIPID 0x28 +#define MAX31850_CHIPID 0x3B + +#define W1_SKIP_ROM 0xCC +#define W1_CONVERT_TEMP 0x44 +#define W1_WRITE_EEPROM 0x48 +#define W1_WRITE_SCRATCHPAD 0x4E +#define W1_READ_SCRATCHPAD 0xBE + +#define DS18X20_MAX_SENSORS 8 + +const char kDs18x20Types[] PROGMEM = "DS18x20|DS18S20|DS1822|DS18B20|MAX31850"; + +uint8_t ds18x20_chipids[] = { 0, DS18S20_CHIPID, DS1822_CHIPID, DS18B20_CHIPID, MAX31850_CHIPID }; + +struct DS18X20STRUCT { + uint8_t address[8]; + uint8_t index; + uint8_t valid; + float temperature; +} ds18x20_sensor[DS18X20_MAX_SENSORS]; +uint8_t ds18x20_sensors = 0; +uint8_t ds18x20_pin = 0; +char ds18x20_types[12]; +#ifdef W1_PARASITE_POWER +uint8_t ds18x20_sensor_curr = 0; +unsigned long w1_power_until = 0; +#endif + + + + + +#define W1_MATCH_ROM 0x55 +#define W1_SEARCH_ROM 0xF0 + +uint8_t onewire_last_discrepancy = 0; +uint8_t onewire_last_family_discrepancy = 0; +bool onewire_last_device_flag = false; +unsigned char onewire_rom_id[8] = { 0 }; + +uint8_t OneWireReset(void) +{ + uint8_t retries = 125; + + + pinMode(ds18x20_pin, INPUT); + do { + if (--retries == 0) { + return 0; + } + delayMicroseconds(2); + } while (!digitalRead(ds18x20_pin)); + pinMode(ds18x20_pin, OUTPUT); + digitalWrite(ds18x20_pin, LOW); + delayMicroseconds(480); + pinMode(ds18x20_pin, INPUT); + delayMicroseconds(70); + uint8_t r = !digitalRead(ds18x20_pin); + + delayMicroseconds(410); + return r; +} + +void OneWireWriteBit(uint8_t v) +{ + static const uint8_t delay_low[2] = { 65, 10 }; + static const uint8_t delay_high[2] = { 5, 55 }; + + v &= 1; + + digitalWrite(ds18x20_pin, LOW); + pinMode(ds18x20_pin, OUTPUT); + delayMicroseconds(delay_low[v]); + digitalWrite(ds18x20_pin, HIGH); + + delayMicroseconds(delay_high[v]); +} + +uint8_t OneWireReadBit(void) +{ + + pinMode(ds18x20_pin, OUTPUT); + digitalWrite(ds18x20_pin, LOW); + delayMicroseconds(3); + pinMode(ds18x20_pin, INPUT); + delayMicroseconds(10); + uint8_t r = digitalRead(ds18x20_pin); + + delayMicroseconds(53); + return r; +} + +void OneWireWrite(uint8_t v) +{ + for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { + OneWireWriteBit((bit_mask & v) ? 1 : 0); + } +} + +uint8_t OneWireRead(void) +{ + uint8_t r = 0; + + for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { + if (OneWireReadBit()) { + r |= bit_mask; + } + } + return r; +} + +void OneWireSelect(const uint8_t rom[8]) +{ + OneWireWrite(W1_MATCH_ROM); + for (uint32_t i = 0; i < 8; i++) { + OneWireWrite(rom[i]); + } +} + +void OneWireResetSearch(void) +{ + onewire_last_discrepancy = 0; + onewire_last_device_flag = false; + onewire_last_family_discrepancy = 0; + for (uint32_t i = 0; i < 8; i++) { + onewire_rom_id[i] = 0; + } +} + +uint8_t OneWireSearch(uint8_t *newAddr) +{ + uint8_t id_bit_number = 1; + uint8_t last_zero = 0; + uint8_t rom_byte_number = 0; + uint8_t search_result = 0; + uint8_t id_bit; + uint8_t cmp_id_bit; + unsigned char rom_byte_mask = 1; + unsigned char search_direction; + + if (!onewire_last_device_flag) { + if (!OneWireReset()) { + onewire_last_discrepancy = 0; + onewire_last_device_flag = false; + onewire_last_family_discrepancy = 0; + return false; + } + OneWireWrite(W1_SEARCH_ROM); + do { + id_bit = OneWireReadBit(); + cmp_id_bit = OneWireReadBit(); + + if ((id_bit == 1) && (cmp_id_bit == 1)) { + break; + } else { + if (id_bit != cmp_id_bit) { + search_direction = id_bit; + } else { + if (id_bit_number < onewire_last_discrepancy) { + search_direction = ((onewire_rom_id[rom_byte_number] & rom_byte_mask) > 0); + } else { + search_direction = (id_bit_number == onewire_last_discrepancy); + } + if (search_direction == 0) { + last_zero = id_bit_number; + if (last_zero < 9) { + onewire_last_family_discrepancy = last_zero; + } + } + } + if (search_direction == 1) { + onewire_rom_id[rom_byte_number] |= rom_byte_mask; + } else { + onewire_rom_id[rom_byte_number] &= ~rom_byte_mask; + } + OneWireWriteBit(search_direction); + id_bit_number++; + rom_byte_mask <<= 1; + if (rom_byte_mask == 0) { + rom_byte_number++; + rom_byte_mask = 1; + } + } + } while (rom_byte_number < 8); + if (!(id_bit_number < 65)) { + onewire_last_discrepancy = last_zero; + if (onewire_last_discrepancy == 0) { + onewire_last_device_flag = true; + } + search_result = true; + } + } + if (!search_result || !onewire_rom_id[0]) { + onewire_last_discrepancy = 0; + onewire_last_device_flag = false; + onewire_last_family_discrepancy = 0; + search_result = false; + } + for (uint32_t i = 0; i < 8; i++) { + newAddr[i] = onewire_rom_id[i]; + } + return search_result; +} + +bool OneWireCrc8(uint8_t *addr) +{ + uint8_t crc = 0; + uint8_t len = 8; + + while (len--) { + uint8_t inbyte = *addr++; + for (uint32_t i = 8; i; i--) { + uint8_t mix = (crc ^ inbyte) & 0x01; + crc >>= 1; + if (mix) { + crc ^= 0x8C; + } + inbyte >>= 1; + } + } + return (crc == *addr); +} + + + +void Ds18x20Init(void) +{ + uint64_t ids[DS18X20_MAX_SENSORS]; + + ds18x20_pin = pin[GPIO_DSB]; + + OneWireResetSearch(); + + ds18x20_sensors = 0; + while (ds18x20_sensors < DS18X20_MAX_SENSORS) { + if (!OneWireSearch(ds18x20_sensor[ds18x20_sensors].address)) { + break; + } + if (OneWireCrc8(ds18x20_sensor[ds18x20_sensors].address) && + ((ds18x20_sensor[ds18x20_sensors].address[0] == DS18S20_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == DS1822_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == DS18B20_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == MAX31850_CHIPID))) { + ds18x20_sensor[ds18x20_sensors].index = ds18x20_sensors; + ids[ds18x20_sensors] = ds18x20_sensor[ds18x20_sensors].address[0]; + for (uint32_t j = 6; j > 0; j--) { + ids[ds18x20_sensors] = ids[ds18x20_sensors] << 8 | ds18x20_sensor[ds18x20_sensors].address[j]; + } + ds18x20_sensors++; + } + } + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + for (uint32_t j = i + 1; j < ds18x20_sensors; j++) { + if (ids[ds18x20_sensor[i].index] > ids[ds18x20_sensor[j].index]) { + std::swap(ds18x20_sensor[i].index, ds18x20_sensor[j].index); + } + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSORS_FOUND " %d"), ds18x20_sensors); +} + +void Ds18x20Convert(void) +{ + OneWireReset(); +#ifdef W1_PARASITE_POWER + + if (++ds18x20_sensor_curr >= ds18x20_sensors) + ds18x20_sensor_curr = 0; + OneWireSelect(ds18x20_sensor[ds18x20_sensor_curr].address); +#else + OneWireWrite(W1_SKIP_ROM); +#endif + OneWireWrite(W1_CONVERT_TEMP); + +} + +bool Ds18x20Read(uint8_t sensor) +{ + uint8_t data[9]; + int8_t sign = 1; + + uint8_t index = ds18x20_sensor[sensor].index; + if (ds18x20_sensor[index].valid) { ds18x20_sensor[index].valid--; } + for (uint32_t retry = 0; retry < 3; retry++) { + OneWireReset(); + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_READ_SCRATCHPAD); + for (uint32_t i = 0; i < 9; i++) { + data[i] = OneWireRead(); + } + if (OneWireCrc8(data)) { + switch(ds18x20_sensor[index].address[0]) { + case DS18S20_CHIPID: { + if (data[1] > 0x80) { + data[0] = (~data[0]) +1; + sign = -1; + } + float temp9 = (float)(data[0] >> 1) * sign; + ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; + } + case DS1822_CHIPID: + case DS18B20_CHIPID: { + if (data[4] != 0x7F) { + data[4] = 0x7F; + OneWireReset(); + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_WRITE_SCRATCHPAD); + OneWireWrite(data[2]); + OneWireWrite(data[3]); + OneWireWrite(data[4]); + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_WRITE_EEPROM); +#ifdef W1_PARASITE_POWER + w1_power_until = millis() + 10; +#endif + } + uint16_t temp12 = (data[1] << 8) + data[0]; + if (temp12 > 2047) { + temp12 = (~temp12) +1; + sign = -1; + } + ds18x20_sensor[index].temperature = ConvertTemp(sign * temp12 * 0.0625); + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; + } + case MAX31850_CHIPID: { + int16_t temp14 = (data[1] << 8) + (data[0] & 0xFC); + ds18x20_sensor[index].temperature = ConvertTemp(temp14 * 0.0625); + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; + } + } + } + } + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); + return false; +} + +void Ds18x20Name(uint8_t sensor) +{ + uint8_t index = sizeof(ds18x20_chipids); + while (index) { + if (ds18x20_sensor[ds18x20_sensor[sensor].index].address[0] == ds18x20_chipids[index]) { + break; + } + index--; + } + GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), index, kDs18x20Types); + if (ds18x20_sensors > 1) { + snprintf_P(ds18x20_types, sizeof(ds18x20_types), PSTR("%s%c%d"), ds18x20_types, IndexSeparator(), sensor +1); + } +} + + + +void Ds18x20EverySecond(void) +{ +#ifdef W1_PARASITE_POWER + + unsigned long now = millis(); + if (now < w1_power_until) + return; +#endif + if (uptime & 1 +#ifdef W1_PARASITE_POWER + + || ds18x20_sensors >= 2 +#endif + ) { + + Ds18x20Convert(); + } else { + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + + if (!Ds18x20Read(i)) { + Ds18x20Name(i); + AddLogMissed(ds18x20_types, ds18x20_sensor[ds18x20_sensor[i].index].valid); +#ifdef USE_DS18x20_RECONFIGURE + if (!ds18x20_sensor[ds18x20_sensor[i].index].valid) { + memset(&ds18x20_sensor, 0, sizeof(ds18x20_sensor)); + Ds18x20Init(); + } +#endif + } + } + } +} + +void Ds18x20Show(bool json) +{ + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + uint8_t index = ds18x20_sensor[i].index; + + if (ds18x20_sensor[index].valid) { + char temperature[33]; + dtostrfd(ds18x20_sensor[index].temperature, Settings.flag2.temperature_resolution, temperature); + + Ds18x20Name(i); + + if (json) { + if (1 == ds18x20_sensors) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, temperature); + } else { + char address[17]; + for (uint32_t j = 0; j < 6; j++) { + sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); + } + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); + } +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, ds18x20_sensor[index].temperature); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, ds18x20_types, temperature, TempUnit()); +#endif + } + } + } +} + + + + + +bool Xsns05(uint8_t function) +{ + bool result = false; + + if (pin[GPIO_DSB] < 99) { + switch (function) { + case FUNC_INIT: + Ds18x20Init(); + break; + case FUNC_EVERY_SECOND: + Ds18x20EverySecond(); + break; + case FUNC_JSON_APPEND: + Ds18x20Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ds18x20Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_05_ds18x20_legacy.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_05_ds18x20_legacy.ino" +#ifdef USE_DS18x20_LEGACY + + + + +#define XSNS_05 5 + +#define DS18S20_CHIPID 0x10 +#define DS18B20_CHIPID 0x28 +#define MAX31850_CHIPID 0x3B + +#define W1_SKIP_ROM 0xCC +#define W1_CONVERT_TEMP 0x44 +#define W1_READ_SCRATCHPAD 0xBE + +#define DS18X20_MAX_SENSORS 8 + +#include + +OneWire *ds = nullptr; + +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 Ds18x20Init(void) +{ + ds = new OneWire(pin[GPIO_DSB]); +} + +void Ds18x20Search(void) +{ + uint8_t num_sensors=0; + uint8_t sensor = 0; + + ds->reset_search(); + for (num_sensors = 0; num_sensors < DS18X20_MAX_SENSORS; num_sensors) { + if (!ds->search(ds18x20_address[num_sensors])) { + ds->reset_search(); + break; + } + + 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 (uint32_t i = 0; i < num_sensors; i++) { + ds18x20_index[i] = i; + } + for (uint32_t i = 0; i < num_sensors; i++) { + for (uint32_t 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_sensors = num_sensors; +} + +uint8_t Ds18x20Sensors(void) +{ + return ds18x20_sensors; +} + +String Ds18x20Addresses(uint8_t sensor) +{ + char address[20]; + + for (uint32_t i = 0; i < 8; i++) { + sprintf(address+2*i, "%02X", ds18x20_address[ds18x20_index[sensor]][i]); + } + return String(address); +} + +void Ds18x20Convert(void) +{ + ds->reset(); + ds->write(W1_SKIP_ROM); + ds->write(W1_CONVERT_TEMP); + +} + +bool Ds18x20Read(uint8_t sensor, float &t) +{ + uint8_t data[12]; + int8_t sign = 1; + uint16_t temp12 = 0; + int16_t temp14 = 0; + float temp9 = 0.0; + uint8_t present = 0; + + t = NAN; + + ds->reset(); + ds->select(ds18x20_address[ds18x20_index[sensor]]); + ds->write(W1_READ_SCRATCHPAD); + + for (uint32_t i = 0; i < 9; i++) { + data[i] = ds->read(); + } + if (OneWire::crc8(data, 8) == data[8]) { + switch(ds18x20_address[ds18x20_index[sensor]][0]) { + case DS18S20_CHIPID: + if (data[1] > 0x80) { + data[0] = (~data[0]) +1; + sign = -1; + } + temp9 = (float)(data[0] >> 1) * sign; + t = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); + break; + case DS18B20_CHIPID: + temp12 = (data[1] << 8) + data[0]; + if (temp12 > 2047) { + temp12 = (~temp12) +1; + sign = -1; + } + t = ConvertTemp(sign * temp12 * 0.0625); + break; + case MAX31850_CHIPID: + temp14 = (data[1] << 8) + (data[0] & 0xFC); + t = ConvertTemp(temp14 * 0.0625); + break; + } + } + return (!isnan(t)); +} + + + +void Ds18x20Type(uint8_t sensor) +{ + strcpy_P(ds18x20_types, PSTR("DS18x20")); + switch(ds18x20_address[ds18x20_index[sensor]][0]) { + case DS18S20_CHIPID: + strcpy_P(ds18x20_types, PSTR("DS18S20")); + break; + case DS18B20_CHIPID: + strcpy_P(ds18x20_types, PSTR("DS18B20")); + break; + case MAX31850_CHIPID: + strcpy_P(ds18x20_types, PSTR("MAX31850")); + break; + } +} + +void Ds18x20Show(bool json) +{ + char stemp[10]; + float t; + + uint8_t dsxflg = 0; + for (uint32_t i = 0; i < Ds18x20Sensors(); i++) { + if (Ds18x20Read(i, t)) { + Ds18x20Type(i); + char temperature[33]; + dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + + if (json) { + if (!dsxflg) { + ResponseAppend_P(PSTR(",\"DS18x20\":{")); + stemp[0] = '\0'; + } + dsxflg++; + ResponseAppend_P(PSTR("%s\"DS%d\":{\"" D_JSON_TYPE "\":\"%s\",\"" D_JSON_ADDRESS "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), + stemp, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), temperature); + strlcpy(stemp, ",", sizeof(stemp)); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (1 == dsxflg)) { + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (1 == dsxflg)) { + KnxSensor(KNX_TEMPERATURE, t); + } +#endif +#ifdef USE_WEBSERVER + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("%s%c%d"), ds18x20_types, IndexSeparator(), i +1); + WSContentSend_PD(HTTP_SNS_TEMP, stemp, temperature, TempUnit()); +#endif + } + } + } + if (json) { + if (dsxflg) { + ResponseJsonEnd(); + } + } + Ds18x20Search(); + Ds18x20Convert(); +} + + + + + +bool Xsns05(uint8_t function) +{ + bool result = false; + + if (pin[GPIO_DSB] < 99) { + switch (function) { + case FUNC_INIT: + Ds18x20Init(); + break; + case FUNC_PREP_BEFORE_TELEPERIOD: + Ds18x20Search(); + Ds18x20Convert(); + break; + case FUNC_JSON_APPEND: + Ds18x20Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ds18x20Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_06_dht.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_06_dht.ino" +#ifdef USE_DHT +# 29 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_06_dht.ino" +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 3 +#define DHT_MAX_RETRY 8 + +uint32_t dht_max_cycles; +uint8_t dht_data[5]; +uint8_t dht_sensors = 0; +bool dht_active = true; + +struct DHTSTRUCT { + uint8_t pin; + uint8_t type; + char stype[12]; + uint32_t lastreadtime; + uint8_t lastresult; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +void DhtReadPrep(void) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + digitalWrite(Dht[i].pin, HIGH); + } +} + +int32_t DhtExpectPulse(uint8_t sensor, bool level) +{ + int32_t count = 0; + + while (digitalRead(Dht[sensor].pin) == level) { + if (count++ >= (int32_t)dht_max_cycles) { + return -1; + } + } + return count; +} + +bool DhtRead(uint8_t sensor) +{ + int32_t cycles[80]; + uint8_t error = 0; + + dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; + + + + + if (Dht[sensor].lastresult > DHT_MAX_RETRY) { + Dht[sensor].lastresult = 0; + digitalWrite(Dht[sensor].pin, HIGH); + delay(250); + } + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); + + if (GPIO_SI7021 == Dht[sensor].type) { + delayMicroseconds(500); + } else { + delay(20); + } + + noInterrupts(); + digitalWrite(Dht[sensor].pin, HIGH); + delayMicroseconds(40); + pinMode(Dht[sensor].pin, INPUT_PULLUP); + delayMicroseconds(10); + if (-1 == DhtExpectPulse(sensor, LOW)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); + error = 1; + } + else if (-1 == DhtExpectPulse(sensor, HIGH)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); + error = 1; + } + else { + for (uint32_t i = 0; i < 80; i += 2) { + cycles[i] = DhtExpectPulse(sensor, LOW); + cycles[i+1] = DhtExpectPulse(sensor, HIGH); + } + } + interrupts(); + if (error) { return false; } + + for (uint32_t i = 0; i < 40; ++i) { + int32_t lowCycles = cycles[2*i]; + int32_t highCycles = cycles[2*i+1]; + if ((-1 == lowCycles) || (-1 == highCycles)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); + return false; + } + dht_data[i/8] <<= 1; + if (highCycles > lowCycles) { + dht_data[i / 8] |= 1; + } + } + + uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; + if (dht_data[4] != checksum) { + char hex_char[15]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), + ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); + return false; + } + + return true; +} + +void DhtReadTempHum(uint8_t sensor) +{ + if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + if (DhtRead(sensor)) { + switch (Dht[sensor].type) { + case GPIO_DHT11: + Dht[sensor].h = dht_data[0]; + Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); + break; + case GPIO_DHT22: + case GPIO_SI7021: + Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + if (dht_data[2] & 0x80) { + Dht[sensor].t *= -1; + } + break; + } + Dht[sensor].t = ConvertTemp(Dht[sensor].t); + Dht[sensor].h = ConvertHumidity(Dht[sensor].h); + Dht[sensor].lastresult = 0; + } else { + Dht[sensor].lastresult++; + } +} + + + +bool DhtPinState() +{ + if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = XdrvMailbox.index; + dht_sensors++; + XdrvMailbox.index = GPIO_DHT11; + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) +{ + if (dht_sensors) { + dht_max_cycles = microsecondsToClockCycles(1000); + + for (uint32_t i = 0; i < dht_sensors; i++) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastreadtime = 0; + Dht[i].lastresult = 0; + GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); + if (dht_sensors > 1) { + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); + } + } + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) +{ + if (uptime &1) { + + DhtReadPrep(); + } else { + for (uint32_t i = 0; i < dht_sensors; i++) { + + DhtReadTempHum(i); + } + } +} + +void DhtShow(bool json) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + char temperature[33]; + dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, Dht[i].t); + KnxSensor(KNX_HUMIDITY, Dht[i].h); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); +#endif + } + } +} + + + + + +bool Xsns06(uint8_t function) +{ + bool result = false; + + if (dht_active) { + switch (function) { + case FUNC_EVERY_SECOND: + DhtEverySecond(); + break; + case FUNC_JSON_APPEND: + DhtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DhtShow(0); + break; +#endif + case FUNC_INIT: + DhtInit(); + break; + case FUNC_PIN_STATE: + result = DhtPinState(); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_07_sht1x.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_07_sht1x.ino" +#ifdef USE_I2C +#ifdef USE_SHT +# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_07_sht1x.ino" +#define XSNS_07 7 + +enum { + SHT1X_CMD_MEASURE_TEMP = B00000011, + SHT1X_CMD_MEASURE_RH = B00000101, + SHT1X_CMD_SOFT_RESET = B00011110 +}; + +uint8_t sht_sda_pin; +uint8_t sht_scl_pin; +uint8_t sht_type = 0; +char sht_types[] = "SHT1X"; +uint8_t sht_valid = 0; +float sht_temperature = 0; +float sht_humidity = 0; + +bool ShtReset(void) +{ + pinMode(sht_sda_pin, INPUT_PULLUP); + pinMode(sht_scl_pin, OUTPUT); + delay(11); + for (uint32_t i = 0; i < 9; i++) { + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_scl_pin, LOW); + } + bool success = ShtSendCommand(SHT1X_CMD_SOFT_RESET); + delay(11); + return success; +} + +bool ShtSendCommand(const uint8_t cmd) +{ + pinMode(sht_sda_pin, OUTPUT); + + digitalWrite(sht_sda_pin, HIGH); + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_sda_pin, LOW); + digitalWrite(sht_scl_pin, LOW); + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_sda_pin, HIGH); + digitalWrite(sht_scl_pin, LOW); + + shiftOut(sht_sda_pin, sht_scl_pin, MSBFIRST, cmd); + + bool ackerror = false; + digitalWrite(sht_scl_pin, HIGH); + pinMode(sht_sda_pin, INPUT_PULLUP); + if (digitalRead(sht_sda_pin) != LOW) { + ackerror = true; + } + digitalWrite(sht_scl_pin, LOW); + delayMicroseconds(1); + if (digitalRead(sht_sda_pin) != HIGH) { + ackerror = true; + } + if (ackerror) { + sht_type = 0; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_DID_NOT_ACK_COMMAND)); + } + return (!ackerror); +} + +bool ShtAwaitResult(void) +{ + + for (uint32_t i = 0; i < 16; i++) { + if (LOW == digitalRead(sht_sda_pin)) { + return true; + } + delay(20); + } + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_BUSY)); + sht_type = 0; + return false; +} + +int ShtReadData(void) +{ + int val = 0; + + + val = shiftIn(sht_sda_pin, sht_scl_pin, 8); + val <<= 8; + + pinMode(sht_sda_pin, OUTPUT); + digitalWrite(sht_sda_pin, LOW); + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_scl_pin, LOW); + pinMode(sht_sda_pin, INPUT_PULLUP); + + val |= shiftIn(sht_sda_pin, sht_scl_pin, 8); + + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_scl_pin, LOW); + return val; +} + +bool ShtRead(void) +{ + if (sht_valid) { sht_valid--; } + if (!ShtReset()) { return false; } + if (!ShtSendCommand(SHT1X_CMD_MEASURE_TEMP)) { return false; } + if (!ShtAwaitResult()) { return false; } + float tempRaw = ShtReadData(); + if (!ShtSendCommand(SHT1X_CMD_MEASURE_RH)) { return false; } + if (!ShtAwaitResult()) { return false; } + float humRaw = ShtReadData(); + + + const float d1 = -39.7; + const float d2 = 0.01; + sht_temperature = d1 + (tempRaw * d2); + const float c1 = -2.0468; + const float c2 = 0.0367; + const float c3 = -1.5955E-6; + const float t1 = 0.01; + const float t2 = 0.00008; + float rhLinear = c1 + c2 * humRaw + c3 * humRaw * humRaw; + sht_humidity = (sht_temperature - 25) * (t1 + t2 * humRaw) + rhLinear; + sht_temperature = ConvertTemp(sht_temperature); + ConvertHumidity(sht_humidity); + + sht_valid = SENSOR_MAX_MISS; + return true; +} + + + +void ShtDetect(void) +{ + if (sht_type) { + return; + } + + sht_sda_pin = pin[GPIO_I2C_SDA]; + sht_scl_pin = pin[GPIO_I2C_SCL]; + if (ShtRead()) { + sht_type = 1; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C D_SHT1X_FOUND)); + } else { + Wire.begin(sht_sda_pin, sht_scl_pin); + sht_type = 0; + } +} + +void ShtEverySecond(void) +{ + if (sht_type && !(uptime %4)) { + + if (!ShtRead()) { + AddLogMissed(sht_types, sht_valid); + + } + } +} + +void ShtShow(bool json) +{ + if (sht_valid) { + char temperature[33]; + dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, sht_types, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, sht_temperature); + KnxSensor(KNX_HUMIDITY, sht_humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, sht_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, sht_types, humidity); +#endif + } + } +} + + + + + +bool Xsns07(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + + case FUNC_INIT: + ShtDetect(); + break; + case FUNC_EVERY_SECOND: + ShtEverySecond(); + break; + case FUNC_JSON_APPEND: + ShtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + ShtShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_08_htu21.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_08_htu21.ino" +#ifdef USE_I2C +#ifdef USE_HTU +# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_08_htu21.ino" +#define XSNS_08 8 + +#define HTU21_ADDR 0x40 + +#define SI7013_CHIPID 0x0D +#define SI7020_CHIPID 0x14 +#define SI7021_CHIPID 0x15 +#define HTU21_CHIPID 0x32 + +#define HTU21_READTEMP 0xE3 +#define HTU21_READHUM 0xE5 +#define HTU21_WRITEREG 0xE6 +#define HTU21_READREG 0xE7 +#define HTU21_RESET 0xFE +#define HTU21_HEATER_WRITE 0x51 +#define HTU21_HEATER_READ 0x11 +#define HTU21_SERIAL2_READ1 0xFC +#define HTU21_SERIAL2_READ2 0xC9 + +#define HTU21_HEATER_ON 0x04 +#define HTU21_HEATER_OFF 0xFB + +#define HTU21_RES_RH12_T14 0x00 +#define HTU21_RES_RH8_T12 0x01 +#define HTU21_RES_RH10_T13 0x80 +#define HTU21_RES_RH11_T11 0x81 + +#define HTU21_CRC8_POLYNOM 0x13100 + +const char kHtuTypes[] PROGMEM = "HTU21|SI7013|SI7020|SI7021|T/RH?"; + +uint8_t htu_address; +uint8_t htu_type = 0; +uint8_t htu_delay_temp; +uint8_t htu_delay_humidity = 50; +uint8_t htu_valid = 0; +float htu_temperature = 0; +float htu_humidity = 0; +char htu_types[7]; + +uint8_t HtuCheckCrc8(uint16_t data) +{ + for (uint32_t bit = 0; bit < 16; bit++) { + if (data & 0x8000) { + data = (data << 1) ^ HTU21_CRC8_POLYNOM; + } else { + data <<= 1; + } + } + return data >>= 8; +} + +uint8_t HtuReadDeviceId(void) +{ + uint16_t deviceID = 0; + uint8_t checksum = 0; + + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_SERIAL2_READ1); + Wire.write(HTU21_SERIAL2_READ2); + Wire.endTransmission(); + + Wire.requestFrom(HTU21_ADDR, 3); + deviceID = Wire.read() << 8; + deviceID |= Wire.read(); + checksum = Wire.read(); + if (HtuCheckCrc8(deviceID) == checksum) { + deviceID = deviceID >> 8; + } else { + deviceID = 0; + } + return (uint8_t)deviceID; +} + +void HtuSetResolution(uint8_t resolution) +{ + uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); + current &= 0x7E; + current |= resolution; + I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); +} + +void HtuReset(void) +{ + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_RESET); + Wire.endTransmission(); + delay(15); +} + +void HtuHeater(uint8_t heater) +{ + uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); + + switch(heater) + { + case HTU21_HEATER_ON : current |= heater; + break; + case HTU21_HEATER_OFF : current &= heater; + break; + default : current &= heater; + break; + } + I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); +} + +void HtuInit(void) +{ + HtuReset(); + HtuHeater(HTU21_HEATER_OFF); + HtuSetResolution(HTU21_RES_RH12_T14); +} + +bool HtuRead(void) +{ + uint8_t checksum = 0; + uint16_t sensorval = 0; + + if (htu_valid) { htu_valid--; } + + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_READTEMP); + if (Wire.endTransmission() != 0) { return false; } + delay(htu_delay_temp); + + Wire.requestFrom(HTU21_ADDR, 3); + if (3 == Wire.available()) { + sensorval = Wire.read() << 8; + sensorval |= Wire.read(); + checksum = Wire.read(); + } + if (HtuCheckCrc8(sensorval) != checksum) { return false; } + + htu_temperature = ConvertTemp(0.002681 * (float)sensorval - 46.85); + + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_READHUM); + if (Wire.endTransmission() != 0) { return false; } + delay(htu_delay_humidity); + + Wire.requestFrom(HTU21_ADDR, 3); + if (3 <= Wire.available()) { + sensorval = Wire.read() << 8; + sensorval |= Wire.read(); + checksum = Wire.read(); + } + if (HtuCheckCrc8(sensorval) != checksum) { return false; } + + sensorval ^= 0x02; + htu_humidity = 0.001907 * (float)sensorval - 6; + if (htu_humidity > 100) { htu_humidity = 100.0; } + if (htu_humidity < 0) { htu_humidity = 0.01; } + + if ((0.00 == htu_humidity) && (0.00 == htu_temperature)) { + htu_humidity = 0.0; + } + if ((htu_temperature > 0.00) && (htu_temperature < 80.00)) { + htu_humidity = (-0.15) * (25 - htu_temperature) + htu_humidity; + } + ConvertHumidity(htu_humidity); + + htu_valid = SENSOR_MAX_MISS; + return true; +} + + + +void HtuDetect(void) +{ + if (htu_type) { return; } + + htu_address = HTU21_ADDR; + htu_type = HtuReadDeviceId(); + if (htu_type) { + uint8_t index = 0; + HtuInit(); + switch (htu_type) { + case HTU21_CHIPID: + htu_delay_temp = 50; + htu_delay_humidity = 16; + break; + case SI7021_CHIPID: + index++; + case SI7020_CHIPID: + index++; + case SI7013_CHIPID: + index++; + htu_delay_temp = 12; + htu_delay_humidity = 23; + break; + default: + index = 4; + htu_delay_temp = 50; + htu_delay_humidity = 23; + } + GetTextIndexed(htu_types, sizeof(htu_types), index, kHtuTypes); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, htu_types, htu_address); + } +} + +void HtuEverySecond(void) +{ + if (92 == (uptime %100)) { + + HtuDetect(); + } + else if (uptime &1) { + + if (htu_type) { + if (!HtuRead()) { + AddLogMissed(htu_types, htu_valid); + + } + } + } +} + +void HtuShow(bool json) +{ + if (htu_valid) { + char temperature[33]; + dtostrfd(htu_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(htu_humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, htu_types, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, htu_temperature); + KnxSensor(KNX_HUMIDITY, htu_humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, htu_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, htu_types, humidity); +#endif + } + } +} + + + + + +bool Xsns08(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + HtuDetect(); + break; + case FUNC_EVERY_SECOND: + HtuEverySecond(); + break; + case FUNC_JSON_APPEND: + HtuShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HtuShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_09_bmp.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_09_bmp.ino" +#ifdef USE_I2C +#ifdef USE_BMP +# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_09_bmp.ino" +#define XSNS_09 9 + +#define BMP_ADDR1 0x76 +#define BMP_ADDR2 0x77 + +#define BMP180_CHIPID 0x55 +#define BMP280_CHIPID 0x58 +#define BME280_CHIPID 0x60 +#define BME680_CHIPID 0x61 + +#define BMP_REGISTER_CHIPID 0xD0 + +#define BMP_MAX_SENSORS 2 + +const char kBmpTypes[] PROGMEM = "BMP180|BMP280|BME280|BME680"; + +typedef struct { + uint8_t bmp_address; + char bmp_name[7]; + uint8_t bmp_type; + uint8_t bmp_model; +#ifdef USE_BME680 + uint8_t bme680_state; + float bmp_gas_resistance; +#endif + float bmp_temperature; + float bmp_pressure; + float bmp_humidity; +} bmp_sensors_t; + +uint8_t bmp_addresses[] = { BMP_ADDR1, BMP_ADDR2 }; +uint8_t bmp_count = 0; +uint8_t bmp_once = 1; + +bmp_sensors_t *bmp_sensors = nullptr; + + + + + +#define BMP180_REG_CONTROL 0xF4 +#define BMP180_REG_RESULT 0xF6 +#define BMP180_TEMPERATURE 0x2E +#define BMP180_PRESSURE3 0xF4 + +#define BMP180_AC1 0xAA +#define BMP180_AC2 0xAC +#define BMP180_AC3 0xAE +#define BMP180_AC4 0xB0 +#define BMP180_AC5 0xB2 +#define BMP180_AC6 0xB4 +#define BMP180_VB1 0xB6 +#define BMP180_VB2 0xB8 +#define BMP180_MB 0xBA +#define BMP180_MC 0xBC +#define BMP180_MD 0xBE + +#define BMP180_OSS 3 + +typedef struct { + int16_t cal_ac1; + int16_t cal_ac2; + int16_t cal_ac3; + int16_t cal_b1; + int16_t cal_b2; + int16_t cal_mc; + int16_t cal_md; + uint16_t cal_ac4; + uint16_t cal_ac5; + uint16_t cal_ac6; +} bmp180_cal_data_t; + +bmp180_cal_data_t *bmp180_cal_data = nullptr; + +bool Bmp180Calibration(uint8_t bmp_idx) +{ + if (!bmp180_cal_data) { + bmp180_cal_data = (bmp180_cal_data_t*)malloc(BMP_MAX_SENSORS * sizeof(bmp180_cal_data_t)); + } + if (!bmp180_cal_data) { return false; } + + bmp180_cal_data[bmp_idx].cal_ac1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC1); + bmp180_cal_data[bmp_idx].cal_ac2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC2); + bmp180_cal_data[bmp_idx].cal_ac3 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC3); + bmp180_cal_data[bmp_idx].cal_ac4 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC4); + bmp180_cal_data[bmp_idx].cal_ac5 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC5); + bmp180_cal_data[bmp_idx].cal_ac6 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC6); + bmp180_cal_data[bmp_idx].cal_b1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB1); + bmp180_cal_data[bmp_idx].cal_b2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB2); + bmp180_cal_data[bmp_idx].cal_mc = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MC); + bmp180_cal_data[bmp_idx].cal_md = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MD); + + + if (!bmp180_cal_data[bmp_idx].cal_ac1 | + !bmp180_cal_data[bmp_idx].cal_ac2 | + !bmp180_cal_data[bmp_idx].cal_ac3 | + !bmp180_cal_data[bmp_idx].cal_ac4 | + !bmp180_cal_data[bmp_idx].cal_ac5 | + !bmp180_cal_data[bmp_idx].cal_ac6 | + !bmp180_cal_data[bmp_idx].cal_b1 | + !bmp180_cal_data[bmp_idx].cal_b2 | + !bmp180_cal_data[bmp_idx].cal_mc | + !bmp180_cal_data[bmp_idx].cal_md) { + return false; + } + + if ((bmp180_cal_data[bmp_idx].cal_ac1 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac2 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac3 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac4 == 0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac5 == 0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac6 == 0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_b1 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_b2 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_mc == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_md == (int16_t)0xFFFF)) { + return false; + } + return true; +} + +void Bmp180Read(uint8_t bmp_idx) +{ + if (!bmp180_cal_data) { return; } + + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_TEMPERATURE); + delay(5); + int ut = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); + int32_t xt1 = (ut - (int32_t)bmp180_cal_data[bmp_idx].cal_ac6) * ((int32_t)bmp180_cal_data[bmp_idx].cal_ac5) >> 15; + int32_t xt2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_mc << 11) / (xt1 + (int32_t)bmp180_cal_data[bmp_idx].cal_md); + int32_t bmp180_b5 = xt1 + xt2; + bmp_sensors[bmp_idx].bmp_temperature = ((bmp180_b5 + 8) >> 4) / 10.0; + + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_PRESSURE3); + delay(2 + (4 << BMP180_OSS)); + uint32_t up = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); + up >>= (8 - BMP180_OSS); + + int32_t b6 = bmp180_b5 - 4000; + int32_t x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b2 * ((b6 * b6) >> 12)) >> 11; + int32_t x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac2 * b6) >> 11; + int32_t x3 = x1 + x2; + int32_t b3 = ((((int32_t)bmp180_cal_data[bmp_idx].cal_ac1 * 4 + x3) << BMP180_OSS) + 2) >> 2; + + x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac3 * b6) >> 13; + x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b1 * ((b6 * b6) >> 12)) >> 16; + x3 = ((x1 + x2) + 2) >> 2; + uint32_t b4 = ((uint32_t)bmp180_cal_data[bmp_idx].cal_ac4 * (uint32_t)(x3 + 32768)) >> 15; + uint32_t b7 = ((uint32_t)up - b3) * (uint32_t)(50000UL >> BMP180_OSS); + + int32_t p; + if (b7 < 0x80000000) { + p = (b7 * 2) / b4; + } + else { + p = (b7 / b4) * 2; + } + x1 = (p >> 8) * (p >> 8); + x1 = (x1 * 3038) >> 16; + x2 = (-7357 * p) >> 16; + p += ((x1 + x2 + (int32_t)3791) >> 4); + bmp_sensors[bmp_idx].bmp_pressure = (float)p / 100.0; +} + + + + + + + +#define BME280_REGISTER_CONTROLHUMID 0xF2 +#define BME280_REGISTER_CONTROL 0xF4 +#define BME280_REGISTER_CONFIG 0xF5 +#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 + +typedef struct { + uint16_t dig_T1; + int16_t dig_T2; + int16_t dig_T3; + uint16_t dig_P1; + int16_t dig_P2; + int16_t dig_P3; + int16_t dig_P4; + int16_t dig_P5; + int16_t dig_P6; + int16_t dig_P7; + int16_t dig_P8; + int16_t dig_P9; + int16_t dig_H2; + int16_t dig_H4; + int16_t dig_H5; + uint8_t dig_H1; + uint8_t dig_H3; + int8_t dig_H6; +} Bme280CalibrationData_t; + +Bme280CalibrationData_t *Bme280CalibrationData = nullptr; + +bool Bmx280Calibrate(uint8_t bmp_idx) +{ + + + if (!Bme280CalibrationData) { + Bme280CalibrationData = (Bme280CalibrationData_t*)malloc(BMP_MAX_SENSORS * sizeof(Bme280CalibrationData_t)); + } + if (!Bme280CalibrationData) { return false; } + + Bme280CalibrationData[bmp_idx].dig_T1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T1); + Bme280CalibrationData[bmp_idx].dig_T2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T2); + Bme280CalibrationData[bmp_idx].dig_T3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T3); + Bme280CalibrationData[bmp_idx].dig_P1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P1); + Bme280CalibrationData[bmp_idx].dig_P2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P2); + Bme280CalibrationData[bmp_idx].dig_P3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P3); + Bme280CalibrationData[bmp_idx].dig_P4 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P4); + Bme280CalibrationData[bmp_idx].dig_P5 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P5); + Bme280CalibrationData[bmp_idx].dig_P6 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P6); + Bme280CalibrationData[bmp_idx].dig_P7 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P7); + Bme280CalibrationData[bmp_idx].dig_P8 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P8); + Bme280CalibrationData[bmp_idx].dig_P9 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P9); + if (BME280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { + Bme280CalibrationData[bmp_idx].dig_H1 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H1); + Bme280CalibrationData[bmp_idx].dig_H2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H2); + Bme280CalibrationData[bmp_idx].dig_H3 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H3); + Bme280CalibrationData[bmp_idx].dig_H4 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4 + 1) & 0xF); + Bme280CalibrationData[bmp_idx].dig_H5 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5 + 1) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5) >> 4); + Bme280CalibrationData[bmp_idx].dig_H6 = (int8_t)I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H6); + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x00); + + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROLHUMID, 0x01); + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONFIG, 0xA0); + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x27); + } else { + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0xB7); + } + + return true; +} + +void Bme280Read(uint8_t bmp_idx) +{ + if (!Bme280CalibrationData) { return; } + + int32_t adc_T = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_TEMPDATA); + adc_T >>= 4; + + int32_t vart1 = ((((adc_T >> 3) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1 << 1))) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_T2)) >> 11; + int32_t vart2 = (((((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1)) * ((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1))) >> 12) * + ((int32_t)Bme280CalibrationData[bmp_idx].dig_T3)) >> 14; + int32_t t_fine = vart1 + vart2; + float T = (t_fine * 5 + 128) >> 8; + bmp_sensors[bmp_idx].bmp_temperature = T / 100.0; + + int32_t adc_P = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_PRESSUREDATA); + adc_P >>= 4; + + int64_t var1 = ((int64_t)t_fine) - 128000; + int64_t var2 = var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P6; + var2 = var2 + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P5) << 17); + var2 = var2 + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P4) << 35); + var1 = ((var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P3) >> 8) + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P2) << 12); + var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)Bme280CalibrationData[bmp_idx].dig_P1) >> 33; + if (0 == var1) { + return; + } + int64_t p = 1048576 - adc_P; + p = (((p << 31) - var2) * 3125) / var1; + var1 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P9) * (p >> 13) * (p >> 13)) >> 25; + var2 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P8) * p) >> 19; + p = ((p + var1 + var2) >> 8) + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P7) << 4); + bmp_sensors[bmp_idx].bmp_pressure = (float)p / 25600.0; + + if (BMP280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { return; } + + int32_t adc_H = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_HUMIDDATA); + + int32_t v_x1_u32r = (t_fine - ((int32_t)76800)); + v_x1_u32r = (((((adc_H << 14) - (((int32_t)Bme280CalibrationData[bmp_idx].dig_H4) << 20) - + (((int32_t)Bme280CalibrationData[bmp_idx].dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * + (((((((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H6)) >> 10) * + (((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + + ((int32_t)2097152)) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H2) + 8192) >> 14)); + v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * + ((int32_t)Bme280CalibrationData[bmp_idx].dig_H1)) >> 4)); + v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; + v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; + float h = (v_x1_u32r >> 12); + bmp_sensors[bmp_idx].bmp_humidity = h / 1024.0; +} + +#ifdef USE_BME680 + + + + +#include + +struct bme680_dev *gas_sensor = nullptr; + +static void BmeDelayMs(uint32_t ms) +{ + delay(ms); +} + +bool Bme680Init(uint8_t bmp_idx) +{ + if (!gas_sensor) { + gas_sensor = (bme680_dev*)malloc(BMP_MAX_SENSORS * sizeof(bme680_dev)); + } + if (!gas_sensor) { return false; } + + gas_sensor[bmp_idx].dev_id = bmp_sensors[bmp_idx].bmp_address; + gas_sensor[bmp_idx].intf = BME680_I2C_INTF; + gas_sensor[bmp_idx].read = &I2cReadBuffer; + gas_sensor[bmp_idx].write = &I2cWriteBuffer; + gas_sensor[bmp_idx].delay_ms = BmeDelayMs; + + + + gas_sensor[bmp_idx].amb_temp = 25; + + int8_t rslt = BME680_OK; + rslt = bme680_init(&gas_sensor[bmp_idx]); + if (rslt != BME680_OK) { return false; } + + + gas_sensor[bmp_idx].tph_sett.os_hum = BME680_OS_2X; + gas_sensor[bmp_idx].tph_sett.os_pres = BME680_OS_4X; + gas_sensor[bmp_idx].tph_sett.os_temp = BME680_OS_8X; + gas_sensor[bmp_idx].tph_sett.filter = BME680_FILTER_SIZE_3; + + + gas_sensor[bmp_idx].gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; + + gas_sensor[bmp_idx].gas_sett.heatr_temp = 320; + gas_sensor[bmp_idx].gas_sett.heatr_dur = 150; + + + + gas_sensor[bmp_idx].power_mode = BME680_FORCED_MODE; + + + uint8_t set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; + + + rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor[bmp_idx]); + if (rslt != BME680_OK) { return false; } + + bmp_sensors[bmp_idx].bme680_state = 0; + + return true; +} + +void Bme680Read(uint8_t bmp_idx) +{ + if (!gas_sensor) { return; } + + int8_t rslt = BME680_OK; + + if (BME680_CHIPID == bmp_sensors[bmp_idx].bmp_type) { + if (0 == bmp_sensors[bmp_idx].bme680_state) { + + rslt = bme680_set_sensor_mode(&gas_sensor[bmp_idx]); + if (rslt != BME680_OK) { return; } + + + + + + + + bmp_sensors[bmp_idx].bme680_state = 1; + } else { + bmp_sensors[bmp_idx].bme680_state = 0; + + struct bme680_field_data data; + rslt = bme680_get_sensor_data(&data, &gas_sensor[bmp_idx]); + if (rslt != BME680_OK) { return; } + + bmp_sensors[bmp_idx].bmp_temperature = data.temperature / 100.0; + bmp_sensors[bmp_idx].bmp_humidity = data.humidity / 1000.0; + bmp_sensors[bmp_idx].bmp_pressure = data.pressure / 100.0; + + if (data.status & BME680_GASM_VALID_MSK) { + bmp_sensors[bmp_idx].bmp_gas_resistance = data.gas_resistance / 1000.0; + } else { + bmp_sensors[bmp_idx].bmp_gas_resistance = 0; + } + } + } + return; +} + +#endif + + + +void BmpDetect(void) +{ + if (bmp_count) return; + + int bmp_sensor_size = BMP_MAX_SENSORS * sizeof(bmp_sensors_t); + if (!bmp_sensors) { + bmp_sensors = (bmp_sensors_t*)malloc(bmp_sensor_size); + } + if (!bmp_sensors) { return; } + memset(bmp_sensors, 0, bmp_sensor_size); + + for (uint32_t i = 0; i < BMP_MAX_SENSORS; i++) { + uint8_t bmp_type = I2cRead8(bmp_addresses[i], BMP_REGISTER_CHIPID); + if (bmp_type) { + bmp_sensors[bmp_count].bmp_address = bmp_addresses[i]; + bmp_sensors[bmp_count].bmp_type = bmp_type; + bmp_sensors[bmp_count].bmp_model = 0; + + bool success = false; + switch (bmp_type) { + case BMP180_CHIPID: + success = Bmp180Calibration(bmp_count); + break; + case BME280_CHIPID: + bmp_sensors[bmp_count].bmp_model++; + case BMP280_CHIPID: + bmp_sensors[bmp_count].bmp_model++; + success = Bmx280Calibrate(bmp_count); + break; +#ifdef USE_BME680 + case BME680_CHIPID: + bmp_sensors[bmp_count].bmp_model = 3; + success = Bme680Init(bmp_count); + break; +#endif + } + if (success) { + GetTextIndexed(bmp_sensors[bmp_count].bmp_name, sizeof(bmp_sensors[bmp_count].bmp_name), bmp_sensors[bmp_count].bmp_model, kBmpTypes); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, bmp_sensors[bmp_count].bmp_name, bmp_sensors[bmp_count].bmp_address); + bmp_count++; + } + } + } +} + +void BmpRead(void) +{ + if (!bmp_sensors) { return; } + + for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + switch (bmp_sensors[bmp_idx].bmp_type) { + case BMP180_CHIPID: + Bmp180Read(bmp_idx); + break; + case BMP280_CHIPID: + case BME280_CHIPID: + Bme280Read(bmp_idx); + break; +#ifdef USE_BME680 + case BME680_CHIPID: + Bme680Read(bmp_idx); + break; +#endif + } + } + ConvertTemp(bmp_sensors[0].bmp_temperature); + ConvertHumidity(bmp_sensors[0].bmp_humidity); +} + +void BmpEverySecond(void) +{ + if (91 == (uptime %100)) { + + BmpDetect(); + } + else { + + BmpRead(); + } +} + +void BmpShow(bool json) +{ + if (!bmp_sensors) { return; } + + for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + if (bmp_sensors[bmp_idx].bmp_type) { + float bmp_sealevel = 0.0; + if (bmp_sensors[bmp_idx].bmp_pressure != 0.0) { + bmp_sealevel = (bmp_sensors[bmp_idx].bmp_pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; + bmp_sealevel = ConvertPressure(bmp_sealevel); + } + float bmp_temperature = ConvertTemp(bmp_sensors[bmp_idx].bmp_temperature); + float bmp_pressure = ConvertPressure(bmp_sensors[bmp_idx].bmp_pressure); + + char name[10]; + strlcpy(name, bmp_sensors[bmp_idx].bmp_name, sizeof(name)); + if (bmp_count > 1) { + snprintf_P(name, sizeof(name), PSTR("%s%c%02X"), name, IndexSeparator(), bmp_sensors[bmp_idx].bmp_address); + } + + char temperature[33]; + dtostrfd(bmp_temperature, Settings.flag2.temperature_resolution, temperature); + char pressure[33]; + dtostrfd(bmp_pressure, Settings.flag2.pressure_resolution, pressure); + char sea_pressure[33]; + dtostrfd(bmp_sealevel, Settings.flag2.pressure_resolution, sea_pressure); + char humidity[33]; + dtostrfd(bmp_sensors[bmp_idx].bmp_humidity, Settings.flag2.humidity_resolution, humidity); +#ifdef USE_BME680 + char gas_resistance[33]; + dtostrfd(bmp_sensors[bmp_idx].bmp_gas_resistance, 2, gas_resistance); +#endif + + if (json) { + char json_humidity[40]; + snprintf_P(json_humidity, sizeof(json_humidity), PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); + char json_sealevel[40]; + snprintf_P(json_sealevel, sizeof(json_sealevel), PSTR(",\"" D_JSON_PRESSUREATSEALEVEL "\":%s"), sea_pressure); +#ifdef USE_BME680 + char json_gas[40]; + snprintf_P(json_gas, sizeof(json_gas), PSTR(",\"" D_JSON_GAS "\":%s"), gas_resistance); + + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), + name, + temperature, + (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", + pressure, + (Settings.altitude != 0) ? json_sealevel : "", + (bmp_sensors[bmp_idx].bmp_model >= 3) ? json_gas : ""); +#else + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), + name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); +#endif + +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == bmp_idx)) { + DomoticzTempHumPressureSensor(temperature, humidity, pressure); +#ifdef USE_BME680 + if (bmp_sensors[bmp_idx].bmp_model >= 3) { DomoticzSensor(DZ_AIRQUALITY, (uint32_t)bmp_sensors[bmp_idx].bmp_gas_resistance); } +#endif + } +#endif + +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, bmp_temperature); + KnxSensor(KNX_HUMIDITY, bmp_sensors[bmp_idx].bmp_humidity); + } +#endif + +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, name, temperature, TempUnit()); + if (bmp_sensors[bmp_idx].bmp_model >= 2) { + WSContentSend_PD(HTTP_SNS_HUM, name, humidity); + } + WSContentSend_PD(HTTP_SNS_PRESSURE, name, pressure, PressureUnit().c_str()); + if (Settings.altitude != 0) { + WSContentSend_PD(HTTP_SNS_SEAPRESSURE, name, sea_pressure, PressureUnit().c_str()); + } +#ifdef USE_BME680 + if (bmp_sensors[bmp_idx].bmp_model >= 3) { + WSContentSend_PD(PSTR("{s}%s " D_GAS "{m}%s " D_UNIT_KILOOHM "{e}"), name, gas_resistance); + } +#endif + +#endif + } + } + } +} + + + + + +bool Xsns09(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + BmpDetect(); + break; + case FUNC_EVERY_SECOND: + BmpEverySecond(); + break; + case FUNC_JSON_APPEND: + BmpShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + BmpShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_10_bh1750.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_10_bh1750.ino" +#ifdef USE_I2C +#ifdef USE_BH1750 + + + + + + +#define XSNS_10 10 + +#define BH1750_ADDR1 0x23 +#define BH1750_ADDR2 0x5C + +#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 + +uint8_t bh1750_address; +uint8_t bh1750_addresses[] = { BH1750_ADDR1, BH1750_ADDR2 }; +uint8_t bh1750_type = 0; +uint8_t bh1750_valid = 0; +uint16_t bh1750_illuminance = 0; +char bh1750_types[] = "BH1750"; + +bool Bh1750Read(void) +{ + if (bh1750_valid) { bh1750_valid--; } + + if (2 != Wire.requestFrom(bh1750_address, (uint8_t)2)) { return false; } + uint8_t msb = Wire.read(); + uint8_t lsb = Wire.read(); + bh1750_illuminance = ((msb << 8) | lsb) / 1.2; + bh1750_valid = SENSOR_MAX_MISS; + return true; +} + + + +void Bh1750Detect(void) +{ + if (bh1750_type) { + return; + } + + for (uint32_t i = 0; i < sizeof(bh1750_addresses); i++) { + bh1750_address = bh1750_addresses[i]; + Wire.beginTransmission(bh1750_address); + Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE); + if (!Wire.endTransmission()) { + bh1750_type = 1; + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, bh1750_types, bh1750_address); + break; + } + } +} + +void Bh1750EverySecond(void) +{ + if (90 == (uptime %100)) { + + Bh1750Detect(); + } + else { + + if (bh1750_type) { + if (!Bh1750Read()) { + AddLogMissed(bh1750_types, bh1750_valid); + + } + } + } +} + +void Bh1750Show(bool json) +{ + if (bh1750_valid) { + if (json) { + ResponseAppend_P(JSON_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_ILLUMINANCE, bh1750_illuminance); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); +#endif + } + } +} + + + + + +bool Xsns10(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + Bh1750Detect(); + break; + case FUNC_EVERY_SECOND: + Bh1750EverySecond(); + break; + case FUNC_JSON_APPEND: + Bh1750Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Bh1750Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_11_veml6070.ino" +# 89 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_11_veml6070.ino" +#ifdef USE_I2C +#ifdef USE_VEML6070 + + + + + + +#define XSNS_11 11 + +#define VEML6070_ADDR_H 0x39 +#define VEML6070_ADDR_L 0x38 +#define VEML6070_INTEGRATION_TIME 3 +#define VEML6070_ENABLE 1 +#define VEML6070_DISABLE 0 +#define VEML6070_RSET_DEFAULT 270000 +#define VEML6070_UV_MAX_INDEX 15 +#define VEML6070_UV_MAX_DEFAULT 11 +#define VEML6070_POWER_COEFFCIENT 0.025 +#define VEML6070_TABLE_COEFFCIENT 32.86270591 + + + + + +const char kVemlTypes[] PROGMEM = "VEML6070"; +double uv_risk_map[VEML6070_UV_MAX_INDEX] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +double uvrisk = 0; +double uvpower = 0; +uint16_t uvlevel = 0; +uint8_t veml6070_addr_low = VEML6070_ADDR_L; +uint8_t veml6070_addr_high = VEML6070_ADDR_H; +uint8_t itime = VEML6070_INTEGRATION_TIME; +uint8_t veml6070_type = 0; +uint8_t veml6070_valid = 0; +char veml6070_name[9]; +char str_uvrisk_text[10]; + + + +void Veml6070Detect(void) +{ + if (veml6070_type) { + return; + } + + Wire.beginTransmission(VEML6070_ADDR_L); + Wire.write((itime << 2) | 0x02); + uint8_t status = Wire.endTransmission(); + + if (!status) { + veml6070_type = 1; + uint8_t veml_model = 0; + GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "VEML6070", VEML6070_ADDR_L); + } +} + + + +void Veml6070UvTableInit(void) +{ + + for (uint32_t i = 0; i < VEML6070_UV_MAX_INDEX; i++) { +#ifdef USE_VEML6070_RSET + if ( (USE_VEML6070_RSET >= 220000) && (USE_VEML6070_RSET <= 1000000) ) { + uv_risk_map[i] = ( (USE_VEML6070_RSET / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); + } else { + uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor error %d"), USE_VEML6070_RSET); + } +#else + uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor default used %d"), VEML6070_RSET_DEFAULT); +#endif + } +} + + + +void Veml6070EverySecond(void) +{ + + if (11 == (uptime %100)) { + Veml6070ModeCmd(1); + Veml6070Detect(); + Veml6070ModeCmd(0); + } else { + Veml6070ModeCmd(1); + uvlevel = Veml6070ReadUv(); + uvrisk = Veml6070UvRiskLevel(uvlevel); + uvpower = Veml6070UvPower(uvrisk); + Veml6070ModeCmd(0); + } +} + + + +void Veml6070ModeCmd(bool mode_cmd) +{ + + + Wire.beginTransmission(VEML6070_ADDR_L); + Wire.write((mode_cmd << 0) | 0x02 | (itime << 2)); + uint8_t status = Wire.endTransmission(); + + if (!status) { + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "VEML6070 mode_cmd", VEML6070_ADDR_L); + } +} + + + +uint16_t Veml6070ReadUv(void) +{ + uint16_t uv_raw = 0; + + if (Wire.requestFrom(VEML6070_ADDR_H, 1) != 1) { + return -1; + } + uv_raw = Wire.read(); + uv_raw <<= 8; + + if (Wire.requestFrom(VEML6070_ADDR_L, 1) != 1) { + return -1; + } + uv_raw |= Wire.read(); + + return uv_raw; +} + + + +double Veml6070UvRiskLevel(uint16_t uv_level) +{ + double risk = 0; + if (uv_level < uv_risk_map[VEML6070_UV_MAX_INDEX-1]) { + risk = (double)uv_level / uv_risk_map[0]; + + if ( (risk >= 0) && (risk <= 2.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_1); } + else if ( (risk >= 3.0) && (risk <= 5.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_2); } + else if ( (risk >= 6.0) && (risk <= 7.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_3); } + else if ( (risk >= 8.0) && (risk <= 10.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_4); } + else if ( (risk >= 11.0) && (risk <= 12.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_5); } + else if ( (risk >= 13.0) && (risk <= 25.0) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_6); } + else { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); } + return risk; + } else { + + snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); + return ( risk = 99 ); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 out of range %d"), risk); + } +} + + + +double Veml6070UvPower(double uvrisk) +{ + + double power = 0; + return ( power = VEML6070_POWER_COEFFCIENT * uvrisk ); +} + + + + +#ifdef USE_WEBSERVER + +#ifdef USE_VEML6070_SHOW_RAW + const char HTTP_SNS_UV_LEVEL[] PROGMEM = "{s}VEML6070 " D_UV_LEVEL "{m}%s " D_UNIT_INCREMENTS "{e}"; +#endif + + const char HTTP_SNS_UV_INDEX[] PROGMEM = "{s}VEML6070 " D_UV_INDEX "{m}%s %s{e}"; + const char HTTP_SNS_UV_POWER[] PROGMEM = "{s}VEML6070 " D_UV_POWER "{m}%s " D_UNIT_WATT_METER_QUADRAT "{e}"; +#endif + + + +void Veml6070Show(bool json) +{ + if (veml6070_type) { + + char str_uvlevel[33]; + dtostrfd((double)uvlevel, 0, str_uvlevel); + char str_uvrisk[33]; + dtostrfd(uvrisk, 2, str_uvrisk); + char str_uvpower[33]; + dtostrfd(uvpower, 3, str_uvpower); + if (json) { +#ifdef USE_VEML6070_SHOW_RAW + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), + veml6070_name, str_uvlevel, str_uvrisk, str_uvrisk_text, str_uvpower); +#else + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), + veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); +#endif +#ifdef USE_DOMOTICZ + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); } +#endif +#ifdef USE_WEBSERVER + } else { +#ifdef USE_VEML6070_SHOW_RAW + WSContentSend_PD(HTTP_SNS_UV_LEVEL, str_uvlevel); +#endif + WSContentSend_PD(HTTP_SNS_UV_INDEX, str_uvrisk, str_uvrisk_text); + WSContentSend_PD(HTTP_SNS_UV_POWER, str_uvpower); +#endif + } + } +} + + + + + +bool Xsns11(uint8_t function) +{ + bool result = false; + + if (i2c_flg && !(pin[GPIO_ADE7953_IRQ] < 99)) { + switch (function) { + case FUNC_INIT: + Veml6070Detect(); + Veml6070UvTableInit(); + break; + case FUNC_EVERY_SECOND: + Veml6070EverySecond(); + break; + case FUNC_JSON_APPEND: + Veml6070Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Veml6070Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_12_ads1115.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_12_ads1115.ino" +#ifdef USE_I2C +#ifdef USE_ADS1115 +# 43 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_12_ads1115.ino" +#define XSNS_12 12 + +#define ADS1115_ADDRESS_ADDR_GND 0x48 +#define ADS1115_ADDRESS_ADDR_VDD 0x49 +#define ADS1115_ADDRESS_ADDR_SDA 0x4A +#define ADS1115_ADDRESS_ADDR_SCL 0x4B + +#define ADS1115_CONVERSIONDELAY (8) + + + + +#define ADS1115_REG_POINTER_MASK (0x03) +#define ADS1115_REG_POINTER_CONVERT (0x00) +#define ADS1115_REG_POINTER_CONFIG (0x01) +#define ADS1115_REG_POINTER_LOWTHRESH (0x02) +#define ADS1115_REG_POINTER_HITHRESH (0x03) + + + + +#define ADS1115_REG_CONFIG_OS_MASK (0x8000) +#define ADS1115_REG_CONFIG_OS_SINGLE (0x8000) +#define ADS1115_REG_CONFIG_OS_BUSY (0x0000) +#define ADS1115_REG_CONFIG_OS_NOTBUSY (0x8000) + +#define ADS1115_REG_CONFIG_MUX_MASK (0x7000) +#define ADS1115_REG_CONFIG_MUX_DIFF_0_1 (0x0000) +#define ADS1115_REG_CONFIG_MUX_DIFF_0_3 (0x1000) +#define ADS1115_REG_CONFIG_MUX_DIFF_1_3 (0x2000) +#define ADS1115_REG_CONFIG_MUX_DIFF_2_3 (0x3000) +#define ADS1115_REG_CONFIG_MUX_SINGLE_0 (0x4000) +#define ADS1115_REG_CONFIG_MUX_SINGLE_1 (0x5000) +#define ADS1115_REG_CONFIG_MUX_SINGLE_2 (0x6000) +#define ADS1115_REG_CONFIG_MUX_SINGLE_3 (0x7000) + +#define ADS1115_REG_CONFIG_PGA_MASK (0x0E00) +#define ADS1115_REG_CONFIG_PGA_6_144V (0x0000) +#define ADS1115_REG_CONFIG_PGA_4_096V (0x0200) +#define ADS1115_REG_CONFIG_PGA_2_048V (0x0400) +#define ADS1115_REG_CONFIG_PGA_1_024V (0x0600) +#define ADS1115_REG_CONFIG_PGA_0_512V (0x0800) +#define ADS1115_REG_CONFIG_PGA_0_256V (0x0A00) + +#define ADS1115_REG_CONFIG_MODE_MASK (0x0100) +#define ADS1115_REG_CONFIG_MODE_CONTIN (0x0000) +#define ADS1115_REG_CONFIG_MODE_SINGLE (0x0100) + +#define ADS1115_REG_CONFIG_DR_MASK (0x00E0) +#define ADS1115_REG_CONFIG_DR_128SPS (0x0000) +#define ADS1115_REG_CONFIG_DR_250SPS (0x0020) +#define ADS1115_REG_CONFIG_DR_490SPS (0x0040) +#define ADS1115_REG_CONFIG_DR_920SPS (0x0060) +#define ADS1115_REG_CONFIG_DR_1600SPS (0x0080) +#define ADS1115_REG_CONFIG_DR_2400SPS (0x00A0) +#define ADS1115_REG_CONFIG_DR_3300SPS (0x00C0) +#define ADS1115_REG_CONFIG_DR_6000SPS (0x00E0) + +#define ADS1115_REG_CONFIG_CMODE_MASK (0x0010) +#define ADS1115_REG_CONFIG_CMODE_TRAD (0x0000) +#define ADS1115_REG_CONFIG_CMODE_WINDOW (0x0010) + +#define ADS1115_REG_CONFIG_CPOL_MASK (0x0008) +#define ADS1115_REG_CONFIG_CPOL_ACTVLOW (0x0000) +#define ADS1115_REG_CONFIG_CPOL_ACTVHI (0x0008) + +#define ADS1115_REG_CONFIG_CLAT_MASK (0x0004) +#define ADS1115_REG_CONFIG_CLAT_NONLAT (0x0000) +#define ADS1115_REG_CONFIG_CLAT_LATCH (0x0004) + +#define ADS1115_REG_CONFIG_CQUE_MASK (0x0003) +#define ADS1115_REG_CONFIG_CQUE_1CONV (0x0000) +#define ADS1115_REG_CONFIG_CQUE_2CONV (0x0001) +#define ADS1115_REG_CONFIG_CQUE_4CONV (0x0002) +#define ADS1115_REG_CONFIG_CQUE_NONE (0x0003) + +uint8_t ads1115_type = 0; +uint8_t ads1115_address; +uint8_t ads1115_addresses[] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL }; +uint8_t ads1115_found[] = {false,false,false,false}; +int16_t ads1115_values[4]; + + +void Ads1115StartComparator(uint8_t channel, uint16_t mode) +{ + + uint16_t config = mode | + ADS1115_REG_CONFIG_CQUE_NONE | + ADS1115_REG_CONFIG_CLAT_NONLAT | + ADS1115_REG_CONFIG_PGA_6_144V | + ADS1115_REG_CONFIG_CPOL_ACTVLOW | + ADS1115_REG_CONFIG_CMODE_TRAD | + ADS1115_REG_CONFIG_DR_6000SPS; + + + config |= (ADS1115_REG_CONFIG_MUX_SINGLE_0 + (0x1000 * channel)); + + + I2cWrite16(ads1115_address, ADS1115_REG_POINTER_CONFIG, config); +} + +int16_t Ads1115GetConversion(uint8_t channel) +{ + Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE); + + delay(ADS1115_CONVERSIONDELAY); + + I2cRead16(ads1115_address, ADS1115_REG_POINTER_CONVERT); + + Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN); + delay(ADS1115_CONVERSIONDELAY); + + uint16_t res = I2cRead16(ads1115_address, ADS1115_REG_POINTER_CONVERT); + return (int16_t)res; +} + + + +void Ads1115Detect(void) +{ + uint16_t buffer; + for (uint32_t i = 0; i < sizeof(ads1115_addresses); i++) { + if (!ads1115_found[i]) { + ads1115_address = ads1115_addresses[i]; + if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT) && + I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONFIG)) { + Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); + ads1115_type = 1; + ads1115_found[i] = 1; + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); + } + } + } +} + +void Ads1115GetValues(uint8_t address) +{ + uint8_t old_address = ads1115_address; + ads1115_address = address; + for (uint32_t i = 0; i < 4; i++) { + ads1115_values[i] = Ads1115GetConversion(i); + + } + ads1115_address = old_address; +} + +void Ads1115toJSON(char *comma_j) +{ + ResponseAppend_P(PSTR("%s{"), comma_j); + char *comma = (char*)""; + for (uint32_t i = 0; i < 4; i++) { + ResponseAppend_P(PSTR("%s\"A%d\":%d"), comma, i, ads1115_values[i]); + comma = (char*)","; + } + ResponseJsonEnd(); +} + +void Ads1115toString(uint8_t address) +{ + char label[15]; + snprintf_P(label, sizeof(label), "ADS1115(%02x)", address); + + for (uint32_t i = 0; i < 4; i++) { + WSContentSend_PD(HTTP_SNS_ANALOG, label, i, ads1115_values[i]); + } +} + +void Ads1115Show(bool json) +{ + if (!ads1115_type) { return; } + + if (json) { + ResponseAppend_P(PSTR(",\"ADS1115\":")); + } + + char *comma = (char*)""; + + for (uint32_t t = 0; t < sizeof(ads1115_addresses); t++) { + + if (ads1115_found[t]) { + Ads1115GetValues(ads1115_addresses[t]); + if (json) { + Ads1115toJSON(comma); + comma = (char*)","; + } +#ifdef USE_WEBSERVER + else { + Ads1115toString(ads1115_addresses[t]); + } +#endif + } + } + +} + + + + + +bool Xsns12(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_PREP_BEFORE_TELEPERIOD: + Ads1115Detect(); + break; + case FUNC_JSON_APPEND: + Ads1115Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ads1115Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_12_ads1115_i2cdev.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_12_ads1115_i2cdev.ino" +#ifdef USE_I2C +#ifdef USE_ADS1115_I2CDEV +# 43 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_12_ads1115_i2cdev.ino" +#define XSNS_12 12 + +#include + +ADS1115 adc0; + +uint8_t ads1115_type = 0; +uint8_t ads1115_address; +uint8_t ads1115_addresses[] = { + ADS1115_ADDRESS_ADDR_GND, + ADS1115_ADDRESS_ADDR_VDD, + ADS1115_ADDRESS_ADDR_SDA, + ADS1115_ADDRESS_ADDR_SCL +}; + +int16_t Ads1115GetConversion(uint8_t channel) +{ + switch (channel) { + case 0: + adc0.getConversionP0GND(); + break; + case 1: + adc0.getConversionP1GND(); + break; + case 2: + adc0.getConversionP2GND(); + break; + case 3: + adc0.getConversionP3GND(); + break; + } +} + + + +void Ads1115Detect(void) +{ + if (ads1115_type) { + return; + } + + for (uint32_t i = 0; i < sizeof(ads1115_addresses); i++) { + ads1115_address = ads1115_addresses[i]; + ADS1115 adc0(ads1115_address); + if (adc0.testConnection()) { + adc0.initialize(); + adc0.setGain(ADS1115_PGA_6P144); + adc0.setRate(ADS1115_RATE_860); + adc0.setMode(ADS1115_MODE_CONTINUOUS); + ads1115_type = 1; + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); + break; + } + } +} + +void Ads1115Show(bool json) +{ + if (ads1115_type) { + + uint8_t dsxflg = 0; + for (uint32_t i = 0; i < 4; i++) { + int16_t adc_value = Ads1115GetConversion(i); + + if (json) { + if (!dsxflg ) { + ResponseAppend_P(PSTR(",\"ADS1115\":{")); + } + ResponseAppend_P(PSTR("%s\"A%d\":%d"), (dsxflg) ? "," : "", i, adc_value); + dsxflg++; +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ANALOG, "ADS1115", i, adc_value); +#endif + } + } + if (json) { + if (dsxflg) { + ResponseJsonEnd(); + } + } + } +} + + + + + +bool Xsns12(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_PREP_BEFORE_TELEPERIOD: + Ads1115Detect(); + break; + case FUNC_JSON_APPEND: + Ads1115Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ads1115Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_13_ina219.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_13_ina219.ino" +#ifdef USE_I2C +#ifdef USE_INA219 +# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_13_ina219.ino" +#define XSNS_13 13 + +#define INA219_ADDRESS1 (0x40) +#define INA219_ADDRESS2 (0x41) +#define INA219_ADDRESS3 (0x44) +#define INA219_ADDRESS4 (0x45) + +#define INA219_READ (0x01) +#define INA219_REG_CONFIG (0x00) + +#define INA219_CONFIG_RESET (0x8000) + +#define INA219_CONFIG_BVOLTAGERANGE_MASK (0x2000) +#define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) +#define INA219_CONFIG_BVOLTAGERANGE_32V (0x2000) + +#define INA219_CONFIG_GAIN_MASK (0x1800) +#define INA219_CONFIG_GAIN_1_40MV (0x0000) +#define INA219_CONFIG_GAIN_2_80MV (0x0800) +#define INA219_CONFIG_GAIN_4_160MV (0x1000) +#define INA219_CONFIG_GAIN_8_320MV (0x1800) + +#define INA219_CONFIG_BADCRES_MASK (0x0780) +#define INA219_CONFIG_BADCRES_9BIT (0x0080) +#define INA219_CONFIG_BADCRES_10BIT (0x0100) +#define INA219_CONFIG_BADCRES_11BIT (0x0200) +#define INA219_CONFIG_BADCRES_12BIT (0x0400) + +#define INA219_CONFIG_SADCRES_MASK (0x0078) +#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) +#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) +#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) +#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) +#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) +#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) +#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) +#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) +#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) +#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) +#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) + +#define INA219_CONFIG_MODE_MASK (0x0007) +#define INA219_CONFIG_MODE_POWERDOWN (0x0000) +#define INA219_CONFIG_MODE_SVOLT_TRIGGERED (0x0001) +#define INA219_CONFIG_MODE_BVOLT_TRIGGERED (0x0002) +#define INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED (0x0003) +#define INA219_CONFIG_MODE_ADCOFF (0x0004) +#define INA219_CONFIG_MODE_SVOLT_CONTINUOUS (0x0005) +#define INA219_CONFIG_MODE_BVOLT_CONTINUOUS (0x0006) +#define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS (0x0007) + +#define INA219_REG_SHUNTVOLTAGE (0x01) +#define INA219_REG_BUSVOLTAGE (0x02) +#define INA219_REG_POWER (0x03) +#define INA219_REG_CURRENT (0x04) +#define INA219_REG_CALIBRATION (0x05) + +uint8_t ina219_type[4] = {0,0,0,0}; +uint8_t ina219_addresses[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; + +uint32_t ina219_cal_value = 0; + +uint32_t ina219_current_divider_ma = 0; + +uint8_t ina219_valid[4] = {0,0,0,0}; +float ina219_voltage[4] = {0,0,0,0}; +float ina219_current[4] = {0,0,0,0}; +char ina219_types[] = "INA219"; + +bool Ina219SetCalibration(uint8_t mode, uint16_t addr) +{ + uint16_t config = 0; + + switch (mode &3) { + case 0: + case 3: + ina219_cal_value = 4096; + ina219_current_divider_ma = 10; + config = INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + break; + case 1: + ina219_cal_value = 10240; + ina219_current_divider_ma = 25; + config |= INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + break; + case 2: + ina219_cal_value = 8192; + ina219_current_divider_ma = 20; + config |= INA219_CONFIG_BVOLTAGERANGE_16V | INA219_CONFIG_GAIN_1_40MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + break; + } + + bool success = I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); + if (success) { + + I2cWrite16(addr, INA219_REG_CONFIG, config); + } + return success; +} + +float Ina219GetShuntVoltage_mV(uint16_t addr) +{ + + int16_t value = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); + + return value * 0.01; +} + +float Ina219GetBusVoltage_V(uint16_t addr) +{ + + + int16_t value = (int16_t)(((uint16_t)I2cReadS16(addr, INA219_REG_BUSVOLTAGE) >> 3) * 4); + + return value * 0.001; +} + +float Ina219GetCurrent_mA(uint16_t addr) +{ + + + + I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); + + + float value = I2cReadS16(addr, INA219_REG_CURRENT); + value /= ina219_current_divider_ma; + + return value; +} + +bool Ina219Read(void) +{ + for (int i=0; i= 0) && (XdrvMailbox.payload <= 2)) { + Settings.ina219_mode = XdrvMailbox.payload; + restart_flag = 2; + } + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); + + return serviced; +} + + + +void Ina219Detect(void) +{ + for (int i=0; i1) + snprintf_P(name, sizeof(name), PSTR("%s%c%d"), ina219_types, IndexSeparator(), sensor_num); + else + snprintf_P(name, sizeof(name), PSTR("%s"), ina219_types); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%02x,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), + name, ina219_addresses[i], voltage, current, power); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_VOLTAGE, voltage); + DomoticzSensor(DZ_CURRENT, current); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_INA219_DATA, name, voltage, name, current, name, power); +#endif + } + } +} + + + + + +bool Xsns13(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_COMMAND_SENSOR: + if ((XSNS_13 == XdrvMailbox.index) && (ina219_type)) { + result = Ina219CommandSensor(); + } + break; + case FUNC_INIT: + Ina219Detect(); + break; + case FUNC_EVERY_SECOND: + Ina219EverySecond(); + break; + case FUNC_JSON_APPEND: + Ina219Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ina219Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_14_sht3x.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_14_sht3x.ino" +#ifdef USE_I2C +#ifdef USE_SHT3X + + + + + + +#define XSNS_14 14 + +#define SHT3X_ADDR_GND 0x44 +#define SHT3X_ADDR_VDD 0x45 +#define SHTC3_ADDR 0x70 + +#define SHT3X_MAX_SENSORS 3 + +const char kShtTypes[] PROGMEM = "SHT3X|SHT3X|SHTC3"; +uint8_t sht3x_addresses[] = { SHT3X_ADDR_GND, SHT3X_ADDR_VDD, SHTC3_ADDR }; + +uint8_t sht3x_count = 0; +struct SHT3XSTRUCT { + uint8_t address; + char types[6]; +} sht3x_sensors[SHT3X_MAX_SENSORS]; + +bool Sht3xRead(float &t, float &h, uint8_t sht3x_address) +{ + unsigned int data[6]; + + t = NAN; + h = NAN; + + Wire.beginTransmission(sht3x_address); + if (SHTC3_ADDR == sht3x_address) { + Wire.write(0x35); + Wire.write(0x17); + Wire.endTransmission(); + Wire.beginTransmission(sht3x_address); + Wire.write(0x78); + Wire.write(0x66); + } else { + Wire.write(0x2C); + Wire.write(0x06); + } + if (Wire.endTransmission() != 0) { + return false; + } + delay(30); + Wire.requestFrom(sht3x_address, (uint8_t)6); + for (uint32_t i = 0; i < 6; i++) { + data[i] = Wire.read(); + }; + t = ConvertTemp((float)((((data[0] << 8) | data[1]) * 175) / 65535.0) - 45); + h = ConvertHumidity((float)((((data[3] << 8) | data[4]) * 100) / 65535.0)); + return (!isnan(t) && !isnan(h) && (h != 0)); +} + + + +void Sht3xDetect(void) +{ + if (sht3x_count) return; + + float t; + float h; + for (uint32_t i = 0; i < SHT3X_MAX_SENSORS; i++) { + if (Sht3xRead(t, h, sht3x_addresses[i])) { + sht3x_sensors[sht3x_count].address = sht3x_addresses[i]; + GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), i, kShtTypes); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, sht3x_sensors[sht3x_count].types, sht3x_sensors[sht3x_count].address); + sht3x_count++; + } + } +} + +void Sht3xShow(bool json) +{ + if (sht3x_count) { + float t; + float h; + char types[11]; + for (uint32_t i = 0; i < sht3x_count; i++) { + if (Sht3xRead(t, h, sht3x_sensors[i].address)) { + char temperature[33]; + dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(h, Settings.flag2.humidity_resolution, humidity); + snprintf_P(types, sizeof(types), PSTR("%s%c0x%02X"), sht3x_sensors[i].types, IndexSeparator(), sht3x_sensors[i].address); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, types, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif + +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, t); + KnxSensor(KNX_HUMIDITY, h); + } +#endif + +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, types, humidity); +#endif + } + } + } + } +} + + + + + +bool Xsns14(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + Sht3xDetect(); + break; + case FUNC_JSON_APPEND: + Sht3xShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sht3xShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_15_mhz19.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_15_mhz19.ino" +#ifdef USE_MHZ19 +# 33 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_15_mhz19.ino" +#define XSNS_15 15 + +enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILTER_FAST, MHZ19_FILTER_MEDIUM, MHZ19_FILTER_SLOW}; + +#define MHZ19_FILTER_OPTION MHZ19_FILTER_FAST +# 58 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_15_mhz19.ino" +#include + +#ifndef CO2_LOW +#define CO2_LOW 800 +#endif +#ifndef CO2_HIGH +#define CO2_HIGH 1200 +#endif + +#define MHZ19_READ_TIMEOUT 400 +#define MHZ19_RETRY_COUNT 8 + +TasmotaSerial *MhzSerial; + +const char kMhzModels[] PROGMEM = "|B"; + +const char ABC_ENABLED[] = "ABC is Enabled"; +const char ABC_DISABLED[] = "ABC is Disabled"; + +enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; +const uint8_t kMhzCommands[][4] PROGMEM = { + + {0x86,0x00,0x00,0x00}, + {0x79,0xA0,0x00,0x00}, + {0x79,0x00,0x00,0x00}, + {0x87,0x00,0x00,0x00}, + {0x8D,0x00,0x00,0x00}, + {0x99,0x00,0x03,0xE8}, + {0x99,0x00,0x07,0xD0}, + {0x99,0x00,0x0B,0xB8}, + {0x99,0x00,0x13,0x88}}; + +uint8_t mhz_type = 1; +uint16_t mhz_last_ppm = 0; +uint8_t mhz_filter = MHZ19_FILTER_OPTION; +bool mhz_abc_must_apply = false; + +float mhz_temperature = 0; +uint8_t mhz_retry = MHZ19_RETRY_COUNT; +uint8_t mhz_received = 0; +uint8_t mhz_state = 0; + + + +uint8_t MhzCalculateChecksum(uint8_t *array) +{ + uint8_t checksum = 0; + for (uint32_t i = 1; i < 8; i++) { + checksum += array[i]; + } + checksum = 255 - checksum; + return (checksum +1); +} + +size_t MhzSendCmd(uint8_t command_id) +{ + uint8_t mhz_send[9] = { 0 }; + + mhz_send[0] = 0xFF; + mhz_send[1] = 0x01; + memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(uint16_t)); + + + + + memcpy_P(&mhz_send[6], kMhzCommands[command_id] + sizeof(uint16_t), sizeof(uint16_t)); + mhz_send[8] = MhzCalculateChecksum(mhz_send); + + + + return MhzSerial->write(mhz_send, sizeof(mhz_send)); +} + + + +bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) +{ + if (1 == s) { + return false; + } + if (mhz_last_ppm < 400 || mhz_last_ppm > 5000) { + + + mhz_last_ppm = ppm; + return true; + } + int32_t difference = ppm - mhz_last_ppm; + if (s > 0 && s < 64 && mhz_filter != MHZ19_FILTER_OFF) { +# 154 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_15_mhz19.ino" + difference *= s; + difference /= 64; + } + if (MHZ19_FILTER_OFF == mhz_filter) { + if (s != 0 && s != 64) { + return false; + } + } else { + difference >>= (mhz_filter -1); + } + mhz_last_ppm = static_cast(mhz_last_ppm + difference); + return true; +} + +void MhzEverySecond(void) +{ + mhz_state++; + if (8 == mhz_state) { + mhz_state = 0; + + if (mhz_retry) { + mhz_retry--; + if (!mhz_retry) { + mhz_last_ppm = 0; + mhz_temperature = 0; + } + } + + MhzSerial->flush(); + MhzSendCmd(MHZ_CMND_READPPM); + mhz_received = 0; + } + + if ((mhz_state > 2) && !mhz_received) { + uint8_t mhz_response[9]; + + unsigned long start = millis(); + uint8_t counter = 0; + while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { + if (MhzSerial->available() > 0) { + mhz_response[counter++] = MhzSerial->read(); + } else { + delay(5); + } + } + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); + + if (counter < 9) { + + return; + } + + uint8_t crc = MhzCalculateChecksum(mhz_response); + if (mhz_response[8] != crc) { + + return; + } + if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { + + return; + } + + mhz_received = 1; + + uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; + if (15000 == u) { + if (Settings.SensorBits1.mhz19b_abc_disable) { + + + mhz_abc_must_apply = true; + } + } else { + uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; + mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); + uint8_t s = mhz_response[5]; + mhz_type = (s) ? 1 : 2; + if (MhzCheckAndApplyFilter(ppm, s)) { + mhz_retry = MHZ19_RETRY_COUNT; + LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); + + if (0 == s || 64 == s) { + if (mhz_abc_must_apply) { + mhz_abc_must_apply = false; + if (!Settings.SensorBits1.mhz19b_abc_disable) { + MhzSendCmd(MHZ_CMND_ABCENABLE); + } else { + MhzSendCmd(MHZ_CMND_ABCDISABLE); + } + } + } + + } + } + + } +} +# 266 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_15_mhz19.ino" +#define D_JSON_RANGE_1000 "1000 ppm range" +#define D_JSON_RANGE_2000 "2000 ppm range" +#define D_JSON_RANGE_3000 "3000 ppm range" +#define D_JSON_RANGE_5000 "5000 ppm range" + +bool MhzCommandSensor(void) +{ + bool serviced = true; + + switch (XdrvMailbox.payload) { + case 0: + Settings.SensorBits1.mhz19b_abc_disable = true; + MhzSendCmd(MHZ_CMND_ABCDISABLE); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + break; + case 1: + Settings.SensorBits1.mhz19b_abc_disable = false; + MhzSendCmd(MHZ_CMND_ABCENABLE); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + break; + case 2: + MhzSendCmd(MHZ_CMND_ZEROPOINT); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); + break; + case 9: + MhzSendCmd(MHZ_CMND_RESET); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); + break; + case 1000: + MhzSendCmd(MHZ_CMND_RANGE_1000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_1000); + break; + case 2000: + MhzSendCmd(MHZ_CMND_RANGE_2000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_2000); + break; + case 3000: + MhzSendCmd(MHZ_CMND_RANGE_3000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_3000); + break; + case 5000: + MhzSendCmd(MHZ_CMND_RANGE_5000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); + break; + default: + if (!Settings.SensorBits1.mhz19b_abc_disable) { + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + } else { + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + } + } + + return serviced; +} + + + +void MhzInit(void) +{ + mhz_type = 0; + if ((pin[GPIO_MHZ_RXD] < 99) && (pin[GPIO_MHZ_TXD] < 99)) { + MhzSerial = new TasmotaSerial(pin[GPIO_MHZ_RXD], pin[GPIO_MHZ_TXD], 1); + if (MhzSerial->begin(9600)) { + if (MhzSerial->hardwareSerial()) { ClaimSerial(); } + mhz_type = 1; + } + + } +} + +void MhzShow(bool json) +{ + char types[7] = "MHZ19B"; + char temperature[33]; + dtostrfd(mhz_temperature, Settings.flag2.temperature_resolution, temperature); + char model[3]; + GetTextIndexed(model, sizeof(model), mhz_type -1, kMhzModels); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), types, model, mhz_last_ppm, temperature); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm); + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2, types, mhz_last_ppm); + WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); +#endif + } +} + + + + + +bool Xsns15(uint8_t function) +{ + bool result = false; + + if (mhz_type) { + switch (function) { + case FUNC_INIT: + MhzInit(); + break; + case FUNC_EVERY_SECOND: + MhzEverySecond(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_15 == XdrvMailbox.index) { + result = MhzCommandSensor(); + } + break; + case FUNC_JSON_APPEND: + MhzShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MhzShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_16_tsl2561.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_16_tsl2561.ino" +#ifdef USE_I2C +#ifdef USE_TSL2561 +# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_16_tsl2561.ino" +#define XSNS_16 16 + +#include + +Tsl2561 Tsl(Wire); + +uint8_t tsl2561_type = 0; +uint8_t tsl2561_valid = 0; +uint32_t tsl2561_milliLux = 0; +char tsl2561_types[] = "TSL2561"; + +bool Tsl2561Read(void) +{ + if (tsl2561_valid) { tsl2561_valid--; } + + uint8_t id; + bool gain; + Tsl2561::exposure_t exposure; + uint16_t scaledFull, scaledIr; + uint32_t full, ir; + + if (Tsl.on()) { + if (Tsl.id(id) + && Tsl2561Util::autoGain(Tsl, gain, exposure, scaledFull, scaledIr) + && Tsl2561Util::normalizedLuminosity(gain, exposure, full = scaledFull, ir = scaledIr) + && Tsl2561Util::milliLux(full, ir, tsl2561_milliLux, Tsl2561::packageCS(id))) { + } else{ + tsl2561_milliLux = 0; + } + } + tsl2561_valid = SENSOR_MAX_MISS; + return true; +} + +void Tsl2561Detect(void) +{ + if (tsl2561_type) { return; } + uint8_t id; + + if (I2cDevice(0x29) || I2cDevice(0x39) || I2cDevice(0x49)) { + Tsl.begin(); + if (!Tsl.id(id)) return; + if (Tsl.on()) { + tsl2561_type = 1; + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, tsl2561_types, Tsl.address(), id); + } + } +} + +void Tsl2561EverySecond(void) +{ + if (90 == (uptime %100)) { + + Tsl2561Detect(); + } + else if (!(uptime %2)) { + + if (tsl2561_type) { + if (!Tsl2561Read()) { + AddLogMissed(tsl2561_types, tsl2561_valid); + if (!tsl2561_valid) { tsl2561_type = 0; } + } + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_TSL2561[] PROGMEM = + "{s}TSL2561 " D_ILLUMINANCE "{m}%u.%03u " D_UNIT_LUX "{e}"; +#endif + +void Tsl2561Show(bool json) +{ + if (tsl2561_valid) { + if (json) { + ResponseAppend_P(PSTR(",\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), + tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, (tsl2561_milliLux + 500) / 1000); } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TSL2561, tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); +#endif + } + } +} + + + + + +bool Xsns16(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + Tsl2561Detect(); + break; + case FUNC_EVERY_SECOND: + Tsl2561EverySecond(); + break; + case FUNC_JSON_APPEND: + Tsl2561Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Tsl2561Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_17_senseair.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_17_senseair.ino" +#ifdef USE_SENSEAIR +# 29 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_17_senseair.ino" +#define XSNS_17 17 + +#define SENSEAIR_MODBUS_SPEED 9600 +#define SENSEAIR_DEVICE_ADDRESS 0xFE +#define SENSEAIR_READ_REGISTER 0x04 + +#ifndef CO2_LOW +#define CO2_LOW 800 +#endif +#ifndef CO2_HIGH +#define CO2_HIGH 1200 +#endif + +#include +TasmotaModbus *SenseairModbus; + +const char kSenseairTypes[] PROGMEM = "Kx0|S8"; + +uint8_t senseair_type = 1; +char senseair_types[7]; + +uint16_t senseair_co2 = 0; +float senseair_temperature = 0; +float senseair_humidity = 0; + + + +const uint8_t start_addresses[] { 0x1A, 0x00, 0x03, 0x04, 0x05, 0x1C, 0x0A }; + +uint8_t senseair_read_state = 0; +uint8_t senseair_send_retry = 0; + +void Senseair250ms(void) +{ + + + + + uint16_t value = 0; + bool data_ready = SenseairModbus->ReceiveReady(); + + if (data_ready) { + uint8_t error = SenseairModbus->Receive16BitRegister(&value); + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir response error %d"), error); + } else { + switch(senseair_read_state) { + case 0: + senseair_type = 2; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir type id low %04X"), value); + break; + case 1: + if (value) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir error %04X"), value); + } + break; + case 2: + senseair_co2 = value; + LightSetSignal(CO2_LOW, CO2_HIGH, senseair_co2); + break; + case 3: + senseair_temperature = ConvertTemp((float)value / 100); + break; + case 4: + senseair_humidity = ConvertHumidity((float)value / 100); + break; + case 5: + { + bool relay_state = value >> 8 & 1; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir relay state %d"), relay_state); + break; + } + case 6: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir temp adjustment %d"), value); + break; + } + } + senseair_read_state++; + if (2 == senseair_type) { + if (3 == senseair_read_state) { + senseair_read_state = 1; + } + } else { + if (sizeof(start_addresses) == senseair_read_state) { + senseair_read_state = 1; + } + } + } + + if (0 == senseair_send_retry || data_ready) { + senseair_send_retry = 5; + SenseairModbus->Send(SENSEAIR_DEVICE_ADDRESS, SENSEAIR_READ_REGISTER, (uint16_t)start_addresses[senseair_read_state], 1); + } else { + senseair_send_retry--; + } + + +} + + + +void SenseairInit(void) +{ + senseair_type = 0; + if ((pin[GPIO_SAIR_RX] < 99) && (pin[GPIO_SAIR_TX] < 99)) { + SenseairModbus = new TasmotaModbus(pin[GPIO_SAIR_RX], pin[GPIO_SAIR_TX]); + uint8_t result = SenseairModbus->Begin(SENSEAIR_MODBUS_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + senseair_type = 1; + } + } +} + +void SenseairShow(bool json) +{ + char temperature[33]; + dtostrfd(senseair_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(senseair_humidity, Settings.flag2.temperature_resolution, humidity); + GetTextIndexed(senseair_types, sizeof(senseair_types), senseair_type -1, kSenseairTypes); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d"), senseair_types, senseair_co2); + if (senseair_type != 2) { + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), temperature, humidity); + } + ResponseJsonEnd(); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, senseair_co2); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2, senseair_types, senseair_co2); + if (senseair_type != 2) { + WSContentSend_PD(HTTP_SNS_TEMP, senseair_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, senseair_types, humidity); + } +#endif + } +} + + + + + +bool Xsns17(uint8_t function) +{ + bool result = false; + + if (senseair_type) { + switch (function) { + case FUNC_INIT: + SenseairInit(); + break; + case FUNC_EVERY_250_MSECOND: + Senseair250ms(); + break; + case FUNC_JSON_APPEND: + SenseairShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SenseairShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_18_pms5003.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_18_pms5003.ino" +#ifdef USE_PMS5003 + + + + + + + +#define XSNS_18 18 + +#include + +TasmotaSerial *PmsSerial; + +uint8_t pms_type = 1; +uint8_t pms_valid = 0; + +struct pms5003data { + uint16_t framelen; + uint16_t pm10_standard, pm25_standard, pm100_standard; + uint16_t pm10_env, pm25_env, pm100_env; + uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um; + uint16_t unused; + uint16_t checksum; +} pms_data; + + + +bool PmsReadData(void) +{ + if (! PmsSerial->available()) { + return false; + } + while ((PmsSerial->peek() != 0x42) && PmsSerial->available()) { + PmsSerial->read(); + } + if (PmsSerial->available() < 32) { + return false; + } + + uint8_t buffer[32]; + uint16_t sum = 0; + PmsSerial->readBytes(buffer, 32); + PmsSerial->flush(); + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 32); + + + for (uint32_t i = 0; i < 30; i++) { + sum += buffer[i]; + } + + uint16_t buffer_u16[15]; + for (uint32_t i = 0; i < 15; i++) { + buffer_u16[i] = buffer[2 + i*2 + 1]; + buffer_u16[i] += (buffer[2 + i*2] << 8); + } + if (sum != buffer_u16[14]) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("PMS: " D_CHECKSUM_FAILURE)); + return false; + } + + memcpy((void *)&pms_data, (void *)buffer_u16, 30); + pms_valid = 10; + + return true; +} + + + +void PmsSecond(void) +{ + if (PmsReadData()) { + pms_valid = 10; + } else { + if (pms_valid) { + pms_valid--; + } + } +} + + + +void PmsInit(void) +{ + pms_type = 0; + if (pin[GPIO_PMS5003] < 99) { + PmsSerial = new TasmotaSerial(pin[GPIO_PMS5003], -1, 1); + if (PmsSerial->begin(9600)) { + if (PmsSerial->hardwareSerial()) { ClaimSerial(); } + pms_type = 1; + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_PMS5003_SNS[] PROGMEM = + + + + "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 0.3 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 0.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"; +#endif + +void PmsShow(bool json) +{ + if (pms_valid) { + if (json) { + ResponseAppend_P(PSTR(",\"PMS5003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d,\"PB0.3\":%d,\"PB0.5\":%d,\"PB1\":%d,\"PB2.5\":%d,\"PB5\":%d,\"PB10\":%d}"), + pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, + pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_COUNT, pms_data.pm10_env); + DomoticzSensor(DZ_VOLTAGE, pms_data.pm25_env); + DomoticzSensor(DZ_CURRENT, pms_data.pm100_env); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_PMS5003_SNS, + + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, + pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); +#endif + } + } +} + + + + + +bool Xsns18(uint8_t function) +{ + bool result = false; + + if (pms_type) { + switch (function) { + case FUNC_INIT: + PmsInit(); + break; + case FUNC_EVERY_SECOND: + PmsSecond(); + break; + case FUNC_JSON_APPEND: + PmsShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + PmsShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_19_mgs.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_19_mgs.ino" +#ifdef USE_I2C +#ifdef USE_MGS + + + + + + + +#define XSNS_19 19 + +#ifndef MGS_SENSOR_ADDR +#define MGS_SENSOR_ADDR 0x04 +#endif + +#include "MutichannelGasSensor.h" + +void MGSInit(void) { + gas.begin(MGS_SENSOR_ADDR); +} + +bool MGSPrepare(void) +{ + gas.begin(MGS_SENSOR_ADDR); + if (!gas.isError()) { + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "MultiGasSensor", MGS_SENSOR_ADDR); + return true; + } else { + return false; + } +} + +char* measure_gas(int gas_type, char* buffer) +{ + float f = gas.calcGas(gas_type); + dtostrfd(f, 2, buffer); + return buffer; +} + +#ifdef USE_WEBSERVER +const char HTTP_MGS_GAS[] PROGMEM = "{s}MGS %s{m}%s " D_UNIT_PARTS_PER_MILLION "{e}"; +#endif + +void MGSShow(bool json) +{ + char buffer[33]; + if (json) { + ResponseAppend_P(PSTR(",\"MGS\":{\"NH3\":%s"), measure_gas(NH3, buffer)); + ResponseAppend_P(PSTR(",\"CO\":%s"), measure_gas(CO, buffer)); + ResponseAppend_P(PSTR(",\"NO2\":%s"), measure_gas(NO2, buffer)); + ResponseAppend_P(PSTR(",\"C3H8\":%s"), measure_gas(C3H8, buffer)); + ResponseAppend_P(PSTR(",\"C4H10\":%s"), measure_gas(C4H10, buffer)); + ResponseAppend_P(PSTR(",\"CH4\":%s"), measure_gas(GAS_CH4, buffer)); + ResponseAppend_P(PSTR(",\"H2\":%s"), measure_gas(H2, buffer)); + ResponseAppend_P(PSTR(",\"C2H5OH\":%s}"), measure_gas(C2H5OH, buffer)); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_MGS_GAS, "NH3", measure_gas(NH3, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "CO", measure_gas(CO, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "NO2", measure_gas(NO2, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "C3H8", measure_gas(C3H8, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "C4H10", measure_gas(C4H10, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "CH4", measure_gas(GAS_CH4, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "H2", measure_gas(H2, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "C2H5OH", measure_gas(C2H5OH, buffer)); +#endif + } +} + + + + + +bool Xsns19(uint8_t function) +{ + bool result = false; + static int detected = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + + break; + case FUNC_PREP_BEFORE_TELEPERIOD: + detected = MGSPrepare(); + break; + case FUNC_JSON_APPEND: + if (detected) MGSShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + if (detected) MGSShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_20_novasds.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_20_novasds.ino" +#ifdef USE_NOVA_SDS +# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_20_novasds.ino" +#define XSNS_20 20 + +#include + +#ifndef WORKING_PERIOD +#define WORKING_PERIOD 5 +#endif +#ifndef NOVA_SDS_REINIT_CHECK +#define NOVA_SDS_REINIT_CHECK 80 +#endif +#ifndef NOVA_SDS_QUERY_INTERVAL +#define NOVA_SDS_QUERY_INTERVAL 3 +#endif +#ifndef NOVA_SDS_RECDATA_TIMEOUT +#define NOVA_SDS_RECDATA_TIMEOUT 150 +#endif +#ifndef NOVA_SDS_DEVICE_ID +#define NOVA_SDS_DEVICE_ID 0xFFFF +#endif + +TasmotaSerial *NovaSdsSerial; + +uint8_t novasds_type = 1; +uint8_t novasds_valid = 0; + +struct sds011data { + uint16_t pm100; + uint16_t pm25; +} novasds_data; + + +#define NOVA_SDS_REPORTING_MODE 2 +#define NOVA_SDS_QUERY_DATA 4 +#define NOVA_SDS_SET_DEVICE_ID 5 +#define NOVA_SDS_SLEEP_AND_WORK 6 +#define NOVA_SDS_WORKING_PERIOD 8 +#define NOVA_SDS_CHECK_FIRMWARE_VER 7 + #define NOVA_SDS_QUERY_MODE 0 + #define NOVA_SDS_SET_MODE 1 + #define NOVA_SDS_REPORT_ACTIVE 0 + #define NOVA_SDS_REPORT_QUERY 1 + #define NOVA_SDS_WORK 0 + #define NOVA_SDS_SLEEP 1 + + +bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer) +{ + uint8_t novasds_cmnd[19] = {0xAA, 0xB4, byte1, byte2, byte3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (uint8_t)(sensorid & 0xFF), (uint8_t)((sensorid>>8) & 0xFF), 0x00, 0xAB}; + + + for (uint32_t i = 2; i < 17; i++) { + novasds_cmnd[17] += novasds_cmnd[i]; + } + + + + + + NovaSdsSerial->write(novasds_cmnd, sizeof(novasds_cmnd)); + NovaSdsSerial->flush(); + + + unsigned long cmndtime = millis(); + while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( ! NovaSdsSerial->available() ) ); + if ( ! NovaSdsSerial->available() ) { + + return false; + } + uint8_t recbuf[10]; + memset(recbuf, 0, sizeof(recbuf)); + + while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( NovaSdsSerial->available() > 0) && (0xAA != (recbuf[0] = NovaSdsSerial->read())) ); + if ( 0xAA != recbuf[0] ) { + + return false; + } + + + NovaSdsSerial->readBytes(&recbuf[1], 9); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, recbuf, sizeof(recbuf)); + + if ( nullptr != buffer ) { + + memcpy(buffer, recbuf, sizeof(recbuf)); + } + + + if ((0xAB != recbuf[9] ) || (recbuf[8] != ((recbuf[2] + recbuf[3] + recbuf[4] + recbuf[5] + recbuf[6] + recbuf[7]) & 0xFF))) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SDS: " D_CHECKSUM_FAILURE)); + return false; + } + + return true; +} + +void NovaSdsSetWorkPeriod(void) +{ + + NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, Settings.novasds_period, NOVA_SDS_DEVICE_ID, nullptr); + + NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); +} + +bool NovaSdsReadData(void) +{ + uint8_t d[10]; + if ( ! NovaSdsCommand(NOVA_SDS_QUERY_DATA, 0, 0, NOVA_SDS_DEVICE_ID, d) ) { + return false; + } + novasds_data.pm25 = (d[2] + 256 * d[3]); + novasds_data.pm100 = (d[4] + 256 * d[5]); + + return true; +} + + + +void NovaSdsSecond(void) +{ + if (0 == (uptime % NOVA_SDS_REINIT_CHECK)) { + if (!novasds_valid) { + NovaSdsSetWorkPeriod(); + } + } else if (0 == (uptime % NOVA_SDS_QUERY_INTERVAL)) { + if (NovaSdsReadData()) { + novasds_valid = 10; + } else { + if (novasds_valid) { + novasds_valid--; + } + } + } +} + + + + + + + +bool NovaSdsCommandSensor(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 256)) { + Settings.novasds_period = XdrvMailbox.payload; + NovaSdsSetWorkPeriod(); + } + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_20, Settings.novasds_period); + + return true; +} + +void NovaSdsInit(void) +{ + novasds_type = 0; + if (pin[GPIO_SDS0X1_RX] < 99 && pin[GPIO_SDS0X1_TX] < 99) { + NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1_RX], pin[GPIO_SDS0X1_TX], 1); + if (NovaSdsSerial->begin(9600)) { + if (NovaSdsSerial->hardwareSerial()) { + ClaimSerial(); + } + novasds_type = 1; + NovaSdsSetWorkPeriod(); + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SDS0X1_SNS[] PROGMEM = + "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; +#endif + +void NovaSdsShow(bool json) +{ + if (novasds_valid) { + float pm10f = (float)(novasds_data.pm100) / 10.0f; + float pm2_5f = (float)(novasds_data.pm25) / 10.0f; + char pm10[33]; + dtostrfd(pm10f, 1, pm10); + char pm2_5[33]; + dtostrfd(pm2_5f, 1, pm2_5); + if (json) { + ResponseAppend_P(PSTR(",\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), pm2_5, pm10); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_VOLTAGE, pm2_5); + DomoticzSensor(DZ_CURRENT, pm10); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SDS0X1_SNS, pm2_5, pm10); +#endif + } + } +} + + + + + +bool Xsns20(uint8_t function) +{ + bool result = false; + + if (novasds_type) { + switch (function) { + case FUNC_INIT: + NovaSdsInit(); + break; + case FUNC_EVERY_SECOND: + NovaSdsSecond(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_20 == XdrvMailbox.index) { + result = NovaSdsCommandSensor(); + } + break; + case FUNC_JSON_APPEND: + NovaSdsShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + NovaSdsShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_21_sgp30.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_21_sgp30.ino" +#ifdef USE_I2C +#ifdef USE_SGP30 +# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_21_sgp30.ino" +#define XSNS_21 21 + +#include "Adafruit_SGP30.h" +Adafruit_SGP30 sgp; + +uint8_t sgp30_type = 0; +uint8_t sgp30_ready = 0; +float sgp30_abshum; + + + +void sgp30_Init(void) { + if (sgp.begin()) { + sgp30_type = 1; + + + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "SGP30", 0x58); + AddLog(LOG_LEVEL_DEBUG); + } +} + + +#define POW_FUNC FastPrecisePow + +float sgp30_AbsoluteHumidity(float temperature, float humidity,char tempUnit) { + + + + + + float temp = NAN; + const float mw = 18.01534; + const float r = 8.31447215; + + if (isnan(temperature) || isnan(humidity) ) { + return NAN; + } + + if (tempUnit != 'C') { + temperature = (temperature - 32.0) * (5.0 / 9.0); + } + + temp = POW_FUNC(2.718281828, (17.67 * temperature) / (temperature + 243.5)); + + + + + return (6.112 * temp * humidity * mw) / ((273.15 + temperature) * r); +} + +#define SAVE_PERIOD 30 + +void Sgp30Update(void) +{ + sgp30_ready = 0; + if (!sgp.IAQmeasure() || !sgp30_type) { + + if (21 == (uptime %100)) { + sgp30_Init(); + } + return; + } + if (global_update && global_humidity>0 && global_temperature!=9999) { + + sgp30_abshum=sgp30_AbsoluteHumidity(global_temperature,global_humidity,TempUnit()); + sgp.setHumidity(sgp30_abshum*1000); + } + sgp30_ready = 1; + + + if (!(uptime%SAVE_PERIOD)) { + + uint16_t TVOC_base; + uint16_t eCO2_base; + + if (!sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) return; + + + + } +} + + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SGP30[] PROGMEM = + "{s}SGP30 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" + "{s}SGP30 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; +const char HTTP_SNS_AHUM[] PROGMEM = "{s}SGP30 " "Abs Humidity" "{m}%s g/m3{e}"; +#endif + +#define D_JSON_AHUM "aHumidity" + +void Sgp30Show(bool json) +{ + if (sgp30_ready) { + char abs_hum[33]; + + if (json) { + ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d"), sgp.eCO2, sgp.TVOC); + if (global_update && global_humidity>0 && global_temperature!=9999) { + + dtostrfd(sgp30_abshum,4,abs_hum); + ResponseAppend_P(PSTR(",\"" D_JSON_AHUM "\":%s"),abs_hum); + } + ResponseJsonEnd(); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, sgp.eCO2); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_SGP30, sgp.eCO2, sgp.TVOC); + if (global_update) { + WSContentSend_PD(HTTP_SNS_AHUM, abs_hum); + } +#endif + } + } +} + + + + + + +bool Xsns21(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + sgp30_Init(); + break; + case FUNC_EVERY_SECOND: + Sgp30Update(); + break; + case FUNC_JSON_APPEND: + Sgp30Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sgp30Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_22_sr04.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_22_sr04.ino" +#ifdef USE_SR04 + +#include +# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_22_sr04.ino" +#define XSNS_22 22 + +uint8_t sr04_echo_pin = 0; +uint8_t sr04_trig_pin = 0; +real64_t distance; + +NewPing* sonar = nullptr; + +void Sr04Init(void) +{ + sr04_echo_pin = pin[GPIO_SR04_ECHO]; + sr04_trig_pin = pin[GPIO_SR04_TRIG]; + sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300); +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_DISTANCE[] PROGMEM = + "{s}SR04 " D_DISTANCE "{m}%s" D_UNIT_CENTIMETER "{e}"; +#endif + +void Sr04Show(bool json) +{ + distance = (real64_t)(sonar->ping_median(5))/ US_ROUNDTRIP_CM; + + if (distance != 0) { + char distance_chr[33]; + dtostrfd(distance, 3, distance_chr); + + if(json) { + ResponseAppend_P(PSTR(",\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), distance_chr); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_COUNT, distance_chr); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_DISTANCE, distance_chr); +#endif + } + } +} + + + + + +bool Xsns22(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_SR04_ECHO] < 99) && (pin[GPIO_SR04_TRIG] < 99)) { + switch (function) { + case FUNC_INIT: + Sr04Init(); + break; + case FUNC_JSON_APPEND: + Sr04Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sr04Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_23_sdm120.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_23_sdm120.ino" +#ifdef USE_SDM120 + + + + + + + +#define XSNS_23 23 + + +#ifndef SDM120_SPEED + #define SDM120_SPEED 2400 +#endif + +#ifndef SDM120_ADDR + #define SDM120_ADDR 1 +#endif + + +#include + +enum SDM120_Error {SDM120_ERR_NO_ERROR=0, SDM120_ERR_CRC_ERROR, SDM120_ERR_WRONG_BYTES, SDM120_ERR_NOT_ENOUGHT_BYTES}; + +TasmotaSerial *SDM120Serial; + +uint8_t sdm120_type = 1; + + +float sdm120_voltage = 0; +float sdm120_current = 0; +float sdm120_active_power = 0; +float sdm120_apparent_power = 0; +float sdm120_reactive_power = 0; +float sdm120_power_factor = 0; +float sdm120_frequency = 0; +float sdm120_energy_total = 0; +float sdm120_phase_angle = 0; +float sdm120_import_active = 0; +float sdm120_export_active = 0; +float sdm120_import_reactive = 0; +float sdm120_export_reactive = 0; +float sdm120_total_reactive = 0; + +bool SDM120_ModbusReceiveReady(void) +{ + return (SDM120Serial->available() > 1); +} + +void SDM120_ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count) +{ + uint8_t frame[8]; + + frame[0] = SDM120_ADDR; + frame[1] = function_code; + frame[2] = (uint8_t)(start_address >> 8); + frame[3] = (uint8_t)(start_address); + frame[4] = (uint8_t)(register_count >> 8); + frame[5] = (uint8_t)(register_count); + + uint16_t crc = SDM120_calculateCRC(frame, 6); + frame[6] = lowByte(crc); + frame[7] = highByte(crc); + + while (SDM120Serial->available() > 0) { + SDM120Serial->read(); + } + + SDM120Serial->flush(); + SDM120Serial->write(frame, sizeof(frame)); +} + +uint8_t SDM120_ModbusReceive(float *value) +{ + uint8_t buffer[9]; + + *value = NAN; + uint8_t len = 0; + while (SDM120Serial->available() > 0) { + buffer[len++] = (uint8_t)SDM120Serial->read(); + } + + if (len < 9) { + return SDM120_ERR_NOT_ENOUGHT_BYTES; + } + + if (9 == len) { + if (0x01 == buffer[0] && 0x04 == buffer[1] && 4 == buffer[2]) { + if((SDM120_calculateCRC(buffer, 7)) == ((buffer[8] << 8) | buffer[7])) { + + ((uint8_t*)value)[3] = buffer[3]; + ((uint8_t*)value)[2] = buffer[4]; + ((uint8_t*)value)[1] = buffer[5]; + ((uint8_t*)value)[0] = buffer[6]; + + } else { + return SDM120_ERR_CRC_ERROR; + } + + } else { + return SDM120_ERR_WRONG_BYTES; + } + } + + return SDM120_ERR_NO_ERROR; +} + +uint16_t SDM120_calculateCRC(uint8_t *frame, uint8_t num) +{ + uint16_t crc, flag; + crc = 0xFFFF; + for (uint32_t i = 0; i < num; i++) { + crc ^= frame[i]; + for (uint32_t j = 8; j; j--) { + if ((crc & 0x0001) != 0) { + crc >>= 1; + crc ^= 0xA001; + } else { + crc >>= 1; + } + } + } + return crc; +} + + + +const uint16_t sdm120_start_addresses[] { + 0x0000, + 0x0006, + 0x000C, + 0x0012, + 0x0018, + 0x001E, + 0x0046, +#ifdef USE_SDM220 + 0x0156, + 0X0024, + 0X0048, + 0X004A, + 0X004C, + 0X004E, + 0X0158 +#else + 0x0156 +#endif +}; + +uint8_t sdm120_read_state = 0; +uint8_t sdm120_send_retry = 0; +uint8_t sdm120_nodata_count = 0; + +void SDM120250ms(void) +{ + + + + + float value = 0; + bool data_ready = SDM120_ModbusReceiveReady(); + + if (data_ready) { + sdm120_nodata_count = 0; + uint8_t error = SDM120_ModbusReceive(&value); + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM120 response error %d"), error); + } else { + switch(sdm120_read_state) { + case 0: + sdm120_voltage = value; + break; + + case 1: + sdm120_current = value; + break; + + case 2: + sdm120_active_power = value; + break; + + case 3: + sdm120_apparent_power = value; + break; + + case 4: + sdm120_reactive_power = value; + break; + + case 5: + sdm120_power_factor = value; + break; + + case 6: + sdm120_frequency = value; + break; + + case 7: + sdm120_energy_total = value; + break; +#ifdef USE_SDM220 + case 8: + sdm120_phase_angle = value; + break; + + case 9: + sdm120_import_active = value; + break; + + case 10: + sdm120_export_active = value; + break; + + case 11: + sdm120_import_reactive = value; + break; + + case 12: + sdm120_export_reactive = value; + break; + + case 13: + sdm120_total_reactive = value; + break; +#endif + } + + sdm120_read_state++; + + if (sizeof(sdm120_start_addresses)/2 == sdm120_read_state) { + sdm120_read_state = 0; + } + } + } + else { + if (sdm120_nodata_count <= (1000/250) * 4) { + sdm120_nodata_count++; + } else if (sdm120_nodata_count != 255) { + + sdm120_nodata_count = 255; + sdm120_voltage = sdm120_current = sdm120_active_power = sdm120_apparent_power = sdm120_reactive_power = sdm120_power_factor = sdm120_frequency = sdm120_energy_total = 0; +#ifdef USE_SDM220 + sdm120_phase_angle = sdm120_import_active = sdm120_export_active = sdm120_import_reactive = sdm120_export_reactive = sdm120_total_reactive = 0; +#endif + } + } + + if (0 == sdm120_send_retry || data_ready) { + sdm120_send_retry = 5; + SDM120_ModbusSend(0x04, sdm120_start_addresses[sdm120_read_state], 2); + } else { + sdm120_send_retry--; + } + +} + +void SDM120Init(void) +{ + sdm120_type = 0; + if ((pin[GPIO_SDM120_RX] < 99) && (pin[GPIO_SDM120_TX] < 99)) { + SDM120Serial = new TasmotaSerial(pin[GPIO_SDM120_RX], pin[GPIO_SDM120_TX], 1); + if (SDM120Serial->begin(SDM120_SPEED)) { + if (SDM120Serial->hardwareSerial()) { ClaimSerial(); } + sdm120_type = 1; + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SDM120_DATA[] PROGMEM = + "{s}SDM120 " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}SDM120 " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}SDM120 " D_POWERUSAGE_ACTIVE "{m}%s " D_UNIT_WATT "{e}" + "{s}SDM120 " D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" + "{s}SDM120 " D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" + "{s}SDM120 " D_POWER_FACTOR "{m}%s{e}" + "{s}SDM120 " D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}" + "{s}SDM120 " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}" +#ifdef USE_SDM220 + "{s}SDM120 " D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}" + "{s}SDM120 " D_IMPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}SDM120 " D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}SDM120 " D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + "{s}SDM120 " D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + "{s}SDM120 " D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" +#endif + ; +#endif + +void SDM120Show(bool json) +{ + char voltage[33]; + dtostrfd(sdm120_voltage, Settings.flag2.voltage_resolution, voltage); + char current[33]; + dtostrfd(sdm120_current, Settings.flag2.current_resolution, current); + char active_power[33]; + dtostrfd(sdm120_active_power, Settings.flag2.wattage_resolution, active_power); + char apparent_power[33]; + dtostrfd(sdm120_apparent_power, Settings.flag2.wattage_resolution, apparent_power); + char reactive_power[33]; + dtostrfd(sdm120_reactive_power, Settings.flag2.wattage_resolution, reactive_power); + char power_factor[33]; + dtostrfd(sdm120_power_factor, 2, power_factor); + char frequency[33]; + dtostrfd(sdm120_frequency, Settings.flag2.frequency_resolution, frequency); + char energy_total[33]; + dtostrfd(sdm120_energy_total, Settings.flag2.energy_resolution, energy_total); +#ifdef USE_SDM220 + char phase_angle[33]; + dtostrfd(sdm120_phase_angle, 2, phase_angle); + char import_active[33]; + dtostrfd(sdm120_import_active, Settings.flag2.wattage_resolution, import_active); + char export_active[33]; + dtostrfd(sdm120_export_active, Settings.flag2.wattage_resolution, export_active); + char import_reactive[33]; + dtostrfd(sdm120_import_reactive,Settings.flag2.wattage_resolution, import_reactive); + char export_reactive[33]; + dtostrfd(sdm120_export_reactive,Settings.flag2.wattage_resolution, export_reactive); + char total_reactive[33]; + dtostrfd(sdm120_total_reactive, Settings.flag2.wattage_resolution, total_reactive); +#endif + if (json) { +#ifdef USE_SDM220 + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s,\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_EXPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s}"), + energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current, phase_angle, import_active, export_active, import_reactive, export_reactive, total_reactive); +#else + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), + energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current); +#endif +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + char energy_total_chr[33]; + dtostrfd(sdm120_energy_total * 1000, 1, energy_total_chr); + DomoticzSensor(DZ_VOLTAGE, voltage); + DomoticzSensor(DZ_CURRENT, current); + DomoticzSensorPowerEnergy((int)sdm120_active_power, energy_total_chr); + } +#endif +#ifdef USE_WEBSERVER + } else { +#ifdef USE_SDM220 + WSContentSend_PD(HTTP_SNS_SDM120_DATA, voltage, current, active_power, apparent_power, reactive_power, power_factor, frequency, energy_total, phase_angle,import_active,export_active,import_reactive,export_reactive,total_reactive); +#else + WSContentSend_PD(HTTP_SNS_SDM120_DATA, voltage, current, active_power, apparent_power, reactive_power, power_factor, frequency, energy_total); +#endif +#endif + } +} + + + + + +bool Xsns23(uint8_t function) +{ + bool result = false; + + if (sdm120_type) { + switch (function) { + case FUNC_INIT: + SDM120Init(); + break; + case FUNC_EVERY_250_MSECOND: + SDM120250ms(); + break; + case FUNC_JSON_APPEND: + SDM120Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SDM120Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_24_si1145.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_24_si1145.ino" +#ifdef USE_I2C +#ifdef USE_SI1145 +# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_24_si1145.ino" +#define XSNS_24 24 + +#define SI114X_ADDR 0X60 + + + +#define SI114X_QUERY 0X80 +#define SI114X_SET 0XA0 +#define SI114X_NOP 0X00 +#define SI114X_RESET 0X01 +#define SI114X_BUSADDR 0X02 +#define SI114X_PS_FORCE 0X05 +#define SI114X_GET_CAL 0X12 +#define SI114X_ALS_FORCE 0X06 +#define SI114X_PSALS_FORCE 0X07 +#define SI114X_PS_PAUSE 0X09 +#define SI114X_ALS_PAUSE 0X0A +#define SI114X_PSALS_PAUSE 0X0B +#define SI114X_PS_AUTO 0X0D +#define SI114X_ALS_AUTO 0X0E +#define SI114X_PSALS_AUTO 0X0F + + + +#define SI114X_PART_ID 0X00 +#define SI114X_REV_ID 0X01 +#define SI114X_SEQ_ID 0X02 +#define SI114X_INT_CFG 0X03 +#define SI114X_IRQ_ENABLE 0X04 +#define SI114X_IRQ_MODE1 0x05 +#define SI114X_IRQ_MODE2 0x06 +#define SI114X_HW_KEY 0X07 +#define SI114X_MEAS_RATE0 0X08 +#define SI114X_MEAS_RATE1 0X09 +#define SI114X_PS_RATE 0X0A +#define SI114X_PS_LED21 0X0F +#define SI114X_PS_LED3 0X10 +#define SI114X_UCOEFF0 0X13 +#define SI114X_UCOEFF1 0X14 +#define SI114X_UCOEFF2 0X15 +#define SI114X_UCOEFF3 0X16 +#define SI114X_WR 0X17 +#define SI114X_COMMAND 0X18 +#define SI114X_RESPONSE 0X20 +#define SI114X_IRQ_STATUS 0X21 +#define SI114X_ALS_VIS_DATA0 0X22 +#define SI114X_ALS_VIS_DATA1 0X23 +#define SI114X_ALS_IR_DATA0 0X24 +#define SI114X_ALS_IR_DATA1 0X25 +#define SI114X_PS1_DATA0 0X26 +#define SI114X_PS1_DATA1 0X27 +#define SI114X_PS2_DATA0 0X28 +#define SI114X_PS2_DATA1 0X29 +#define SI114X_PS3_DATA0 0X2A +#define SI114X_PS3_DATA1 0X2B +#define SI114X_AUX_DATA0_UVINDEX0 0X2C +#define SI114X_AUX_DATA1_UVINDEX1 0X2D +#define SI114X_RD 0X2E +#define SI114X_CHIP_STAT 0X30 + + + +#define SI114X_CHLIST 0X01 +#define SI114X_CHLIST_ENUV 0x80 +#define SI114X_CHLIST_ENAUX 0x40 +#define SI114X_CHLIST_ENALSIR 0x20 +#define SI114X_CHLIST_ENALSVIS 0x10 +#define SI114X_CHLIST_ENPS1 0x01 +#define SI114X_CHLIST_ENPS2 0x02 +#define SI114X_CHLIST_ENPS3 0x04 + +#define SI114X_PSLED12_SELECT 0X02 +#define SI114X_PSLED3_SELECT 0X03 + +#define SI114X_PS_ENCODE 0X05 +#define SI114X_ALS_ENCODE 0X06 + +#define SI114X_PS1_ADCMUX 0X07 +#define SI114X_PS2_ADCMUX 0X08 +#define SI114X_PS3_ADCMUX 0X09 + +#define SI114X_PS_ADC_COUNTER 0X0A +#define SI114X_PS_ADC_GAIN 0X0B +#define SI114X_PS_ADC_MISC 0X0C + +#define SI114X_ALS_IR_ADC_MUX 0X0E +#define SI114X_AUX_ADC_MUX 0X0F + +#define SI114X_ALS_VIS_ADC_COUNTER 0X10 +#define SI114X_ALS_VIS_ADC_GAIN 0X11 +#define SI114X_ALS_VIS_ADC_MISC 0X12 + +#define SI114X_LED_REC 0X1C + +#define SI114X_ALS_IR_ADC_COUNTER 0X1D +#define SI114X_ALS_IR_ADC_GAIN 0X1E +#define SI114X_ALS_IR_ADC_MISC 0X1F + + + + +#define SI114X_ADCMUX_SMALL_IR 0x00 +#define SI114X_ADCMUX_VISIABLE 0x02 +#define SI114X_ADCMUX_LARGE_IR 0x03 +#define SI114X_ADCMUX_NO 0x06 +#define SI114X_ADCMUX_GND 0x25 +#define SI114X_ADCMUX_TEMPERATURE 0x65 +#define SI114X_ADCMUX_VDD 0x75 + +#define SI114X_PSLED12_SELECT_PS1_NONE 0x00 +#define SI114X_PSLED12_SELECT_PS1_LED1 0x01 +#define SI114X_PSLED12_SELECT_PS1_LED2 0x02 +#define SI114X_PSLED12_SELECT_PS1_LED3 0x04 +#define SI114X_PSLED12_SELECT_PS2_NONE 0x00 +#define SI114X_PSLED12_SELECT_PS2_LED1 0x10 +#define SI114X_PSLED12_SELECT_PS2_LED2 0x20 +#define SI114X_PSLED12_SELECT_PS2_LED3 0x40 +#define SI114X_PSLED3_SELECT_PS2_NONE 0x00 +#define SI114X_PSLED3_SELECT_PS2_LED1 0x10 +#define SI114X_PSLED3_SELECT_PS2_LED2 0x20 +#define SI114X_PSLED3_SELECT_PS2_LED3 0x40 + +#define SI114X_ADC_GAIN_DIV1 0X00 +#define SI114X_ADC_GAIN_DIV2 0X01 +#define SI114X_ADC_GAIN_DIV4 0X02 +#define SI114X_ADC_GAIN_DIV8 0X03 +#define SI114X_ADC_GAIN_DIV16 0X04 +#define SI114X_ADC_GAIN_DIV32 0X05 + +#define SI114X_LED_CURRENT_5MA 0X01 +#define SI114X_LED_CURRENT_11MA 0X02 +#define SI114X_LED_CURRENT_22MA 0X03 +#define SI114X_LED_CURRENT_45MA 0X04 + +#define SI114X_ADC_COUNTER_1ADCCLK 0X00 +#define SI114X_ADC_COUNTER_7ADCCLK 0X01 +#define SI114X_ADC_COUNTER_15ADCCLK 0X02 +#define SI114X_ADC_COUNTER_31ADCCLK 0X03 +#define SI114X_ADC_COUNTER_63ADCCLK 0X04 +#define SI114X_ADC_COUNTER_127ADCCLK 0X05 +#define SI114X_ADC_COUNTER_255ADCCLK 0X06 +#define SI114X_ADC_COUNTER_511ADCCLK 0X07 + +#define SI114X_ADC_MISC_LOWRANGE 0X00 +#define SI114X_ADC_MISC_HIGHRANGE 0X20 +#define SI114X_ADC_MISC_ADC_NORMALPROXIMITY 0X00 +#define SI114X_ADC_MISC_ADC_RAWADC 0X04 + +#define SI114X_INT_CFG_INTOE 0X01 + +#define SI114X_IRQEN_ALS 0x01 +#define SI114X_IRQEN_PS1 0x04 +#define SI114X_IRQEN_PS2 0x08 +#define SI114X_IRQEN_PS3 0x10 + +uint8_t si1145_type = 0; + + + +uint8_t Si1145ReadByte(uint8_t reg) +{ + return I2cRead8(SI114X_ADDR, reg); +} + +uint16_t Si1145ReadHalfWord(uint8_t reg) +{ + return I2cRead16LE(SI114X_ADDR, reg); +} + +bool Si1145WriteByte(uint8_t reg, uint16_t val) +{ + I2cWrite8(SI114X_ADDR, reg, val); +} + +uint8_t Si1145WriteParamData(uint8_t p, uint8_t v) +{ + Si1145WriteByte(SI114X_WR, v); + Si1145WriteByte(SI114X_COMMAND, p | SI114X_SET); + return Si1145ReadByte(SI114X_RD); +} + + + +bool Si1145Present(void) +{ + return (Si1145ReadByte(SI114X_PART_ID) == 0X45); +} + +void Si1145Reset(void) +{ + Si1145WriteByte(SI114X_MEAS_RATE0, 0); + Si1145WriteByte(SI114X_MEAS_RATE1, 0); + Si1145WriteByte(SI114X_IRQ_ENABLE, 0); + Si1145WriteByte(SI114X_IRQ_MODE1, 0); + Si1145WriteByte(SI114X_IRQ_MODE2, 0); + Si1145WriteByte(SI114X_INT_CFG, 0); + Si1145WriteByte(SI114X_IRQ_STATUS, 0xFF); + + Si1145WriteByte(SI114X_COMMAND, SI114X_RESET); + delay(10); + Si1145WriteByte(SI114X_HW_KEY, 0x17); + delay(10); +} + +void Si1145DeInit(void) +{ + + + Si1145WriteByte(SI114X_UCOEFF0, 0x29); + Si1145WriteByte(SI114X_UCOEFF1, 0x89); + Si1145WriteByte(SI114X_UCOEFF2, 0x02); + Si1145WriteByte(SI114X_UCOEFF3, 0x00); + Si1145WriteParamData(SI114X_CHLIST, SI114X_CHLIST_ENUV | SI114X_CHLIST_ENALSIR | SI114X_CHLIST_ENALSVIS | SI114X_CHLIST_ENPS1); + + + + Si1145WriteParamData(SI114X_PS1_ADCMUX, SI114X_ADCMUX_LARGE_IR); + Si1145WriteByte(SI114X_PS_LED21, SI114X_LED_CURRENT_22MA); + Si1145WriteParamData(SI114X_PSLED12_SELECT, SI114X_PSLED12_SELECT_PS1_LED1); + + + + Si1145WriteParamData(SI114X_PS_ADC_GAIN, SI114X_ADC_GAIN_DIV1); + Si1145WriteParamData(SI114X_PS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); + Si1145WriteParamData(SI114X_PS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE | SI114X_ADC_MISC_ADC_RAWADC); + + + + Si1145WriteParamData(SI114X_ALS_VIS_ADC_GAIN, SI114X_ADC_GAIN_DIV1); + Si1145WriteParamData(SI114X_ALS_VIS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); + Si1145WriteParamData(SI114X_ALS_VIS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE); + + + + Si1145WriteParamData(SI114X_ALS_IR_ADC_GAIN, SI114X_ADC_GAIN_DIV1); + Si1145WriteParamData(SI114X_ALS_IR_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); + Si1145WriteParamData(SI114X_ALS_IR_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE); + + + + Si1145WriteByte(SI114X_INT_CFG, SI114X_INT_CFG_INTOE); + Si1145WriteByte(SI114X_IRQ_ENABLE, SI114X_IRQEN_ALS); + + + + Si1145WriteByte(SI114X_MEAS_RATE0, 0xFF); + Si1145WriteByte(SI114X_COMMAND, SI114X_PSALS_AUTO); +} + +bool Si1145Begin(void) +{ + if (!Si1145Present()) { return false; } + + Si1145Reset(); + Si1145DeInit(); + return true; +} + + +uint16_t Si1145ReadUV(void) +{ + return Si1145ReadHalfWord(SI114X_AUX_DATA0_UVINDEX0); +} + + +uint16_t Si1145ReadVisible(void) +{ + return Si1145ReadHalfWord(SI114X_ALS_VIS_DATA0); +} + + +uint16_t Si1145ReadIR(void) +{ + return Si1145ReadHalfWord(SI114X_ALS_IR_DATA0); +} + + + +void Si1145Update(void) +{ + if (!si1145_type) { + if (Si1145Begin()) { + si1145_type = 1; + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "SI1145", SI114X_ADDR); + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SI1145[] PROGMEM = + "{s}SI1145 " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}" + "{s}SI1145 " D_INFRARED "{m}%d " D_UNIT_LUX "{e}" + "{s}SI1145 " D_UV_INDEX "{m}%d.%d{e}"; +#endif + +void Si1145Show(bool json) +{ + if (si1145_type && Si1145Present()) { + uint16_t visible = Si1145ReadVisible(); + uint16_t infrared = Si1145ReadIR(); + uint16_t uvindex = Si1145ReadUV(); + if (json) { + ResponseAppend_P(PSTR(",\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), + visible, infrared, uvindex /100, uvindex %100); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, visible); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_SI1145, visible, infrared, uvindex /100, uvindex %100); +#endif + } + } else { + si1145_type = 0; + } +} + + + + + +bool Xsns24(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_EVERY_SECOND: + Si1145Update(); + break; + case FUNC_JSON_APPEND: + Si1145Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Si1145Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_25_sdm630.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_25_sdm630.ino" +#ifdef USE_SDM630 + + + + + + + +#define XSNS_25 25 + +#include + +TasmotaSerial *SDM630Serial; + +uint8_t sdm630_type = 1; + + +float sdm630_voltage[] = {0,0,0}; +float sdm630_current[] = {0,0,0}; +float sdm630_active_power[] = {0,0,0}; +float sdm630_reactive_power[] = {0,0,0}; +float sdm630_power_factor[] = {0,0,0}; +float sdm630_energy_total = 0; + +bool SDM630_ModbusReceiveReady(void) +{ + return (SDM630Serial->available() > 1); +} + +void SDM630_ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count) +{ + uint8_t frame[8]; + + frame[0] = 0x01; + frame[1] = function_code; + frame[2] = (uint8_t)(start_address >> 8); + frame[3] = (uint8_t)(start_address); + frame[4] = (uint8_t)(register_count >> 8); + frame[5] = (uint8_t)(register_count); + + uint16_t crc = SDM630_calculateCRC(frame, 6); + frame[6] = lowByte(crc); + frame[7] = highByte(crc); + + while (SDM630Serial->available() > 0) { + SDM630Serial->read(); + } + + SDM630Serial->flush(); + SDM630Serial->write(frame, sizeof(frame)); +} + +uint8_t SDM630_ModbusReceive(float *value) +{ + uint8_t buffer[9]; + + *value = NAN; + uint8_t len = 0; + while (SDM630Serial->available() > 0) { + buffer[len++] = (uint8_t)SDM630Serial->read(); + } + + if (len < 9) + return 3; + + if (len == 9) { + + if (buffer[0] == 0x01 && buffer[1] == 0x04 && buffer[2] == 4) { + + if((SDM630_calculateCRC(buffer, 7)) == ((buffer[8] << 8) | buffer[7])) { + + ((uint8_t*)value)[3] = buffer[3]; + ((uint8_t*)value)[2] = buffer[4]; + ((uint8_t*)value)[1] = buffer[5]; + ((uint8_t*)value)[0] = buffer[6]; + + } else return 1; + + } else return 2; + } + + return 0; +} + +uint16_t SDM630_calculateCRC(uint8_t *frame, uint8_t num) +{ + uint16_t crc, flag; + crc = 0xFFFF; + for (uint32_t i = 0; i < num; i++) { + crc ^= frame[i]; + for (uint32_t j = 8; j; j--) { + if ((crc & 0x0001) != 0) { + crc >>= 1; + crc ^= 0xA001; + } else { + crc >>= 1; + } + } + } + return crc; +} + + + +const uint16_t sdm630_start_addresses[] { + 0x0000, + 0x0002, + 0x0004, + 0x0006, + 0x0008, + 0x000A, + 0x000C, + 0x000E, + 0x0010, + 0x0018, + 0x001A, + 0x001C, + 0x001E, + 0x0020, + 0x0022, + 0x0156 +}; + +uint8_t sdm630_read_state = 0; +uint8_t sdm630_send_retry = 0; + +void SDM630250ms(void) +{ + + + + + float value = 0; + bool data_ready = SDM630_ModbusReceiveReady(); + + if (data_ready) { + uint8_t error = SDM630_ModbusReceive(&value); + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM630 response error %d"), error); + } else { + switch(sdm630_read_state) { + case 0: + sdm630_voltage[0] = value; + break; + + case 1: + sdm630_voltage[1] = value; + break; + + case 2: + sdm630_voltage[2] = value; + break; + + case 3: + sdm630_current[0] = value; + break; + + case 4: + sdm630_current[1] = value; + break; + + case 5: + sdm630_current[2] = value; + break; + + case 6: + sdm630_active_power[0] = value; + break; + + case 7: + sdm630_active_power[1] = value; + break; + + case 8: + sdm630_active_power[2] = value; + break; + + case 9: + sdm630_reactive_power[0] = value; + break; + + case 10: + sdm630_reactive_power[1] = value; + break; + + case 11: + sdm630_reactive_power[2] = value; + break; + + case 12: + sdm630_power_factor[0] = value; + break; + + case 13: + sdm630_power_factor[1] = value; + break; + + case 14: + sdm630_power_factor[2] = value; + break; + + case 15: + sdm630_energy_total = value; + break; + } + + sdm630_read_state++; + + if (sizeof(sdm630_start_addresses)/2 == sdm630_read_state) { + sdm630_read_state = 0; + } + } + } + + if (0 == sdm630_send_retry || data_ready) { + sdm630_send_retry = 5; + SDM630_ModbusSend(0x04, sdm630_start_addresses[sdm630_read_state], 2); + } else { + sdm630_send_retry--; + } + +} + +void SDM630Init(void) +{ + sdm630_type = 0; + if ((pin[GPIO_SDM630_RX] < 99) && (pin[GPIO_SDM630_TX] < 99)) { + SDM630Serial = new TasmotaSerial(pin[GPIO_SDM630_RX], pin[GPIO_SDM630_TX], 1); +#ifdef SDM630_SPEED + if (SDM630Serial->begin(SDM630_SPEED)) { +#else + if (SDM630Serial->begin(2400)) { +#endif + if (SDM630Serial->hardwareSerial()) { ClaimSerial(); } + sdm630_type = 1; + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SDM630_DATA[] PROGMEM = + "{s}SDM630 " D_VOLTAGE "{m}%s/%s/%s " D_UNIT_VOLT "{e}" + "{s}SDM630 " D_CURRENT "{m}%s/%s/%s " D_UNIT_AMPERE "{e}" + "{s}SDM630 " D_POWERUSAGE_ACTIVE "{m}%s/%s/%s " D_UNIT_WATT "{e}" + "{s}SDM630 " D_POWERUSAGE_REACTIVE "{m}%s/%s/%s " D_UNIT_VAR "{e}" + "{s}SDM630 " D_POWER_FACTOR "{m}%s/%s/%s{e}" + "{s}SDM630 " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; +#endif + +void SDM630Show(bool json) +{ + char voltage_l1[33]; + dtostrfd(sdm630_voltage[0], Settings.flag2.voltage_resolution, voltage_l1); + char voltage_l2[33]; + dtostrfd(sdm630_voltage[1], Settings.flag2.voltage_resolution, voltage_l2); + char voltage_l3[33]; + dtostrfd(sdm630_voltage[2], Settings.flag2.voltage_resolution, voltage_l3); + char current_l1[33]; + dtostrfd(sdm630_current[0], Settings.flag2.current_resolution, current_l1); + char current_l2[33]; + dtostrfd(sdm630_current[1], Settings.flag2.current_resolution, current_l2); + char current_l3[33]; + dtostrfd(sdm630_current[2], Settings.flag2.current_resolution, current_l3); + char active_power_l1[33]; + dtostrfd(sdm630_active_power[0], Settings.flag2.wattage_resolution, active_power_l1); + char active_power_l2[33]; + dtostrfd(sdm630_active_power[1], Settings.flag2.wattage_resolution, active_power_l2); + char active_power_l3[33]; + dtostrfd(sdm630_active_power[2], Settings.flag2.wattage_resolution, active_power_l3); + char reactive_power_l1[33]; + dtostrfd(sdm630_reactive_power[0], Settings.flag2.wattage_resolution, reactive_power_l1); + char reactive_power_l2[33]; + dtostrfd(sdm630_reactive_power[1], Settings.flag2.wattage_resolution, reactive_power_l2); + char reactive_power_l3[33]; + dtostrfd(sdm630_reactive_power[2], Settings.flag2.wattage_resolution, reactive_power_l3); + char power_factor_l1[33]; + dtostrfd(sdm630_power_factor[0], 2, power_factor_l1); + char power_factor_l2[33]; + dtostrfd(sdm630_power_factor[1], 2, power_factor_l2); + char power_factor_l3[33]; + dtostrfd(sdm630_power_factor[2], 2, power_factor_l3); + char energy_total[33]; + dtostrfd(sdm630_energy_total, Settings.flag2.energy_resolution, energy_total); + + if (json) { + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" + D_JSON_ACTIVE_POWERUSAGE "\":[%s,%s,%s],\"" D_JSON_REACTIVE_POWERUSAGE "\":[%s,%s,%s],\"" + D_JSON_POWERFACTOR "\":[%s,%s,%s],\"" D_JSON_VOLTAGE "\":[%s,%s,%s],\"" D_JSON_CURRENT "\":[%s,%s,%s]}"), + energy_total, active_power_l1, active_power_l2, active_power_l3, + reactive_power_l1, reactive_power_l2, reactive_power_l3, + power_factor_l1, power_factor_l2, power_factor_l3, + voltage_l1, voltage_l2, voltage_l3, + current_l1, current_l2, current_l3); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + char energy_total_chr[33]; + dtostrfd(sdm630_energy_total * 1000, 1, energy_total_chr); + DomoticzSensor(DZ_VOLTAGE, voltage_l1); + DomoticzSensor(DZ_CURRENT, current_l1); + DomoticzSensorPowerEnergy((int)sdm630_active_power[0], energy_total_chr); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_SDM630_DATA, + voltage_l1, voltage_l2, voltage_l3, current_l1, current_l2, current_l3, + active_power_l1, active_power_l2, active_power_l3, + reactive_power_l1, reactive_power_l2, reactive_power_l3, + power_factor_l1, power_factor_l2, power_factor_l3, energy_total); +#endif + } +} + + + + + +bool Xsns25(uint8_t function) +{ + bool result = false; + + if (sdm630_type) { + switch (function) { + case FUNC_INIT: + SDM630Init(); + break; + case FUNC_EVERY_250_MSECOND: + SDM630250ms(); + break; + case FUNC_JSON_APPEND: + SDM630Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SDM630Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_26_lm75ad.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_26_lm75ad.ino" +#ifdef USE_I2C +#ifdef USE_LM75AD +# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_26_lm75ad.ino" +#define XSNS_26 26 + +#define LM75AD_ADDRESS1 0x48 +#define LM75AD_ADDRESS2 0x49 +#define LM75AD_ADDRESS3 0x4A +#define LM75AD_ADDRESS4 0x4B +#define LM75AD_ADDRESS5 0x4C +#define LM75AD_ADDRESS6 0x4D +#define LM75AD_ADDRESS7 0x4E +#define LM75AD_ADDRESS8 0x4F + +#define LM75_TEMP_REGISTER 0x00 +#define LM75_CONF_REGISTER 0x01 +#define LM75_THYST_REGISTER 0x02 +#define LM75_TOS_REGISTER 0x03 + +uint8_t lm75ad_type = 0; +uint8_t lm75ad_address; +uint8_t lm75ad_addresses[] = { LM75AD_ADDRESS1, LM75AD_ADDRESS2, LM75AD_ADDRESS3, LM75AD_ADDRESS4, LM75AD_ADDRESS5, LM75AD_ADDRESS6, LM75AD_ADDRESS7, LM75AD_ADDRESS8 }; + +void LM75ADDetect(void) +{ + if (lm75ad_type) { return; } + + uint16_t buffer; + for (uint32_t i = 0; i < sizeof(lm75ad_addresses); i++) { + lm75ad_address = lm75ad_addresses[i]; + if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) { + if (buffer == 0x4B00) { + lm75ad_type = 1; + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "LM75AD", lm75ad_address); + break; + } + } + } +} + +float LM75ADGetTemp(void) { + int16_t sign = 1; + + uint16_t t = I2cRead16(lm75ad_address, LM75_TEMP_REGISTER); + if (t & 0x8000) { + t = (~t) +0x20; + sign = -1; + } + t = t >> 5; + return ConvertTemp(sign * t * 0.125); +} + +void LM75ADShow(bool json) +{ + if (lm75ad_type) { + float t = LM75ADGetTemp(); + char temperature[33]; + dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + + if (json) { + ResponseAppend_P(PSTR(",\"LM75AD\":{\"" D_JSON_TEMPERATURE "\":%s}"), temperature); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_TEMP, temperature); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "LM75AD", temperature, TempUnit()); +#endif + } + } +} + + + + + +bool Xsns26(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_EVERY_SECOND: + LM75ADDetect(); + break; + case FUNC_JSON_APPEND: + LM75ADShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + LM75ADShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" +# 28 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" +#ifdef USE_I2C +#ifdef USE_APDS9960 +# 39 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" +#define XSNS_27 27 + +#if defined(USE_SHT) || defined(USE_VEML6070) || defined(USE_TSL2561) + #warning **** Turned off conflicting drivers SHT and VEML6070 **** + #ifdef USE_SHT + #undef USE_SHT + #endif + #ifdef USE_VEML6070 + #undef USE_VEML6070 + #endif + #ifdef USE_TSL2561 + #undef USE_TSL2561 + #endif +#endif + +#define APDS9960_I2C_ADDR 0x39 + +#define APDS9960_CHIPID_1 0xAB +#define APDS9960_CHIPID_2 0x9C + +#define APDS9930_CHIPID_1 0x12 +#define APDS9930_CHIPID_2 0x39 + + +#define GESTURE_THRESHOLD_OUT 10 +#define GESTURE_SENSITIVITY_1 50 +#define GESTURE_SENSITIVITY_2 20 + +uint8_t APDS9960addr; +uint8_t APDS9960type = 0; +char APDS9960stype[9]; +char currentGesture[6]; +uint8_t gesture_mode = 1; + + +volatile uint8_t recovery_loop_counter = 0; +#define APDS9960_LONG_RECOVERY 50 +#define APDS9960_MAX_GESTURE_CYCLES 50 +bool APDS9960_overload = false; + +#ifdef USE_WEBSERVER +const char HTTP_APDS_9960_SNS[] PROGMEM = + "{s}" "Red" "{m}%s{e}" + "{s}" "Green" "{m}%s{e}" + "{s}" "Blue" "{m}%s{e}" + "{s}" "Ambient" "{m}%s " D_UNIT_LUX "{e}" + "{s}" "CCT" "{m}%s " "K" "{e}" + "{s}" "Proximity" "{m}%s{e}"; +#endif +# 96 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" +#define FIFO_PAUSE_TIME 30 + + +#define APDS9960_ENABLE 0x80 +#define APDS9960_ATIME 0x81 +#define APDS9960_WTIME 0x83 +#define APDS9960_AILTL 0x84 +#define APDS9960_AILTH 0x85 +#define APDS9960_AIHTL 0x86 +#define APDS9960_AIHTH 0x87 +#define APDS9960_PILT 0x89 +#define APDS9960_PIHT 0x8B +#define APDS9960_PERS 0x8C +#define APDS9960_CONFIG1 0x8D +#define APDS9960_PPULSE 0x8E +#define APDS9960_CONTROL 0x8F +#define APDS9960_CONFIG2 0x90 +#define APDS9960_ID 0x92 +#define APDS9960_STATUS 0x93 +#define APDS9960_CDATAL 0x94 +#define APDS9960_CDATAH 0x95 +#define APDS9960_RDATAL 0x96 +#define APDS9960_RDATAH 0x97 +#define APDS9960_GDATAL 0x98 +#define APDS9960_GDATAH 0x99 +#define APDS9960_BDATAL 0x9A +#define APDS9960_BDATAH 0x9B +#define APDS9960_PDATA 0x9C +#define APDS9960_POFFSET_UR 0x9D +#define APDS9960_POFFSET_DL 0x9E +#define APDS9960_CONFIG3 0x9F +#define APDS9960_GPENTH 0xA0 +#define APDS9960_GEXTH 0xA1 +#define APDS9960_GCONF1 0xA2 +#define APDS9960_GCONF2 0xA3 +#define APDS9960_GOFFSET_U 0xA4 +#define APDS9960_GOFFSET_D 0xA5 +#define APDS9960_GOFFSET_L 0xA7 +#define APDS9960_GOFFSET_R 0xA9 +#define APDS9960_GPULSE 0xA6 +#define APDS9960_GCONF3 0xAA +#define APDS9960_GCONF4 0xAB +#define APDS9960_GFLVL 0xAE +#define APDS9960_GSTATUS 0xAF +#define APDS9960_IFORCE 0xE4 +#define APDS9960_PICLEAR 0xE5 +#define APDS9960_CICLEAR 0xE6 +#define APDS9960_AICLEAR 0xE7 +#define APDS9960_GFIFO_U 0xFC +#define APDS9960_GFIFO_D 0xFD +#define APDS9960_GFIFO_L 0xFE +#define APDS9960_GFIFO_R 0xFF + + +#define APDS9960_PON 0b00000001 +#define APDS9960_AEN 0b00000010 +#define APDS9960_PEN 0b00000100 +#define APDS9960_WEN 0b00001000 +#define APSD9960_AIEN 0b00010000 +#define APDS9960_PIEN 0b00100000 +#define APDS9960_GEN 0b01000000 +#define APDS9960_GVALID 0b00000001 + + +#define OFF 0 +#define ON 1 + + +#define POWER 0 +#define AMBIENT_LIGHT 1 +#define PROXIMITY 2 +#define WAIT 3 +#define AMBIENT_LIGHT_INT 4 +#define PROXIMITY_INT 5 +#define GESTURE 6 +#define ALL 7 + + +#define LED_DRIVE_100MA 0 +#define LED_DRIVE_50MA 1 +#define LED_DRIVE_25MA 2 +#define LED_DRIVE_12_5MA 3 + + +#define PGAIN_1X 0 +#define PGAIN_2X 1 +#define PGAIN_4X 2 +#define PGAIN_8X 3 + + +#define AGAIN_1X 0 +#define AGAIN_4X 1 +#define AGAIN_16X 2 +#define AGAIN_64X 3 + + +#define GGAIN_1X 0 +#define GGAIN_2X 1 +#define GGAIN_4X 2 +#define GGAIN_8X 3 + + +#define LED_BOOST_100 0 +#define LED_BOOST_150 1 +#define LED_BOOST_200 2 +#define LED_BOOST_300 3 + + +#define GWTIME_0MS 0 +#define GWTIME_2_8MS 1 +#define GWTIME_5_6MS 2 +#define GWTIME_8_4MS 3 +#define GWTIME_14_0MS 4 +#define GWTIME_22_4MS 5 +#define GWTIME_30_8MS 6 +#define GWTIME_39_2MS 7 + + +#define DEFAULT_ATIME 0xdb +#define DEFAULT_WTIME 246 +#define DEFAULT_PROX_PPULSE 0x87 +#define DEFAULT_GESTURE_PPULSE 0x89 +#define DEFAULT_POFFSET_UR 0 +#define DEFAULT_POFFSET_DL 0 +#define DEFAULT_CONFIG1 0x60 +#define DEFAULT_LDRIVE LED_DRIVE_100MA +#define DEFAULT_PGAIN PGAIN_4X +#define DEFAULT_AGAIN AGAIN_4X +#define DEFAULT_PILT 0 +#define DEFAULT_PIHT 50 +#define DEFAULT_AILT 0xFFFF +#define DEFAULT_AIHT 0 +#define DEFAULT_PERS 0x11 +#define DEFAULT_CONFIG2 0x01 +#define DEFAULT_CONFIG3 0 +#define DEFAULT_GPENTH 40 +#define DEFAULT_GEXTH 30 +#define DEFAULT_GCONF1 0x40 +#define DEFAULT_GGAIN GGAIN_4X +#define DEFAULT_GLDRIVE LED_DRIVE_100MA +#define DEFAULT_GWTIME GWTIME_2_8MS +#define DEFAULT_GOFFSET 0 +#define DEFAULT_GPULSE 0xC9 +#define DEFAULT_GCONF3 0 +#define DEFAULT_GIEN 0 + +#define ERROR 0xFF + + +enum { + DIR_NONE, + DIR_LEFT, + DIR_RIGHT, + DIR_UP, + DIR_DOWN, + DIR_ALL +}; + + +enum { + APDS9960_NA_STATE, + APDS9960_ALL_STATE +}; + + +typedef struct gesture_data_type { + uint8_t u_data[32]; + uint8_t d_data[32]; + uint8_t l_data[32]; + uint8_t r_data[32]; + uint8_t index; + uint8_t total_gestures; + uint8_t in_threshold; + uint8_t out_threshold; +} gesture_data_type; + + + gesture_data_type gesture_data_; + int16_t gesture_ud_delta_ = 0; + int16_t gesture_lr_delta_ = 0; + int16_t gesture_ud_count_ = 0; + int16_t gesture_lr_count_ = 0; + int16_t gesture_state_ = 0; + int16_t gesture_motion_ = DIR_NONE; + + typedef struct color_data_type { + uint16_t a; + uint16_t r; + uint16_t g; + uint16_t b; + uint8_t p; + uint16_t cct; + uint16_t lux; + } color_data_type; + + color_data_type color_data; + uint8_t APDS9960_aTime = DEFAULT_ATIME; +# 305 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + bool wireWriteByte(uint8_t val) + { + Wire.beginTransmission(APDS9960_I2C_ADDR); + Wire.write(val); + if( Wire.endTransmission() != 0 ) { + return false; + } + + return true; + } +# 324 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" +int8_t wireReadDataBlock( uint8_t reg, + uint8_t *val, + uint16_t len) +{ + unsigned char i = 0; + + + if (!wireWriteByte(reg)) { + return -1; + } + + + Wire.requestFrom(APDS9960_I2C_ADDR, len); + while (Wire.available()) { + if (i >= len) { + return -1; + } + val[i] = Wire.read(); + i++; + } + + return i; +} + + + + + + + +void calculateColorTemperature(void) +{ + float X, Y, Z; + float xc, yc; + float n; + float cct; + + + + + + X = (-0.14282F * color_data.r) + (1.54924F * color_data.g) + (-0.95641F * color_data.b); + Y = (-0.32466F * color_data.r) + (1.57837F * color_data.g) + (-0.73191F * color_data.b); + Z = (-0.68202F * color_data.r) + (0.77073F * color_data.g) + ( 0.56332F * color_data.b); + + + xc = (X) / (X + Y + Z); + yc = (Y) / (X + Y + Z); + + + n = (xc - 0.3320F) / (0.1858F - yc); + + + color_data.cct = (449.0F * FastPrecisePowf(n, 3)) + (3525.0F * FastPrecisePowf(n, 2)) + (6823.3F * n) + 5520.33F; + + return; +} +# 391 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + uint8_t getProxIntLowThresh(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT) ; + return val; + } + + + + + + + void setProxIntLowThresh(uint8_t threshold) + { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold); + } + + + + + + + uint8_t getProxIntHighThresh(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; + return val; + } + + + + + + + + void setProxIntHighThresh(uint8_t threshold) + { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold); + } +# 447 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + uint8_t getLEDDrive(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; + + val = (val >> 6) & 0b00000011; + + return val; + } +# 470 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + void setLEDDrive(uint8_t drive) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + + drive &= 0b00000011; + drive = drive << 6; + val &= 0b00111111; + val |= drive; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); + } +# 499 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + uint8_t getProximityGain(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; + + val = (val >> 2) & 0b00000011; + + return val; + } +# 522 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + void setProximityGain(uint8_t drive) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + + drive &= 0b00000011; + drive = drive << 2; + val &= 0b11110011; + val |= drive; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); + } +# 563 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + void setAmbientLightGain(uint8_t drive) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + + drive &= 0b00000011; + val &= 0b11111100; + val |= drive; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); + } +# 590 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + uint8_t getLEDBoost(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; + + + val = (val >> 4) & 0b00000011; + + return val; + } +# 614 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + void setLEDBoost(uint8_t boost) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; + + boost &= 0b00000011; + boost = boost << 4; + val &= 0b11001111; + val |= boost; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, val) ; + } + + + + + + + uint8_t getProxGainCompEnable(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; + + + val = (val >> 5) & 0b00000001; + + return val; + } + + + + + + + void setProxGainCompEnable(uint8_t enable) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; + + + enable &= 0b00000001; + enable = enable << 5; + val &= 0b11011111; + val |= enable; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; + } +# 682 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + uint8_t getProxPhotoMask(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; + + + val &= 0b00001111; + + return val; + } +# 707 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + void setProxPhotoMask(uint8_t mask) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; + + + mask &= 0b00001111; + val &= 0b11110000; + val |= mask; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; + } + + + + + + + uint8_t getGestureEnterThresh(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GPENTH) ; + + return val; + } + + + + + + + void setGestureEnterThresh(uint8_t threshold) + { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPENTH, threshold) ; + + } + + + + + + + uint8_t getGestureExitThresh(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GEXTH) ; + + return val; + } + + + + + + + void setGestureExitThresh(uint8_t threshold) + { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GEXTH, threshold) ; + } +# 785 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + uint8_t getGestureGain(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + val = (val >> 5) & 0b00000011; + + return val; + } +# 809 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + void setGestureGain(uint8_t gain) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + gain &= 0b00000011; + gain = gain << 5; + val &= 0b10011111; + val |= gain; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; + } +# 837 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + uint8_t getGestureLEDDrive(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + val = (val >> 3) & 0b00000011; + + return val; + } +# 861 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + void setGestureLEDDrive(uint8_t drive) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + drive &= 0b00000011; + drive = drive << 3; + val &= 0b11100111; + val |= drive; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; + } +# 893 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + uint8_t getGestureWaitTime(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + val &= 0b00000111; + + return val; + } +# 921 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + void setGestureWaitTime(uint8_t time) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + time &= 0b00000111; + val &= 0b11111000; + val |= time; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; + } + + + + + + + void getLightIntLowThreshold(uint16_t &threshold) + { + uint8_t val_byte; + threshold = 0; + + + val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AILTL) ; + threshold = val_byte; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_byte) ; + threshold = threshold + ((uint16_t)val_byte << 8); + } + + + + + + + + void setLightIntLowThreshold(uint16_t threshold) + { + uint8_t val_low; + uint8_t val_high; + + + val_low = threshold & 0x00FF; + val_high = (threshold & 0xFF00) >> 8; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTL, val_low) ; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_high) ; + + } + + + + + + + + void getLightIntHighThreshold(uint16_t &threshold) + { + uint8_t val_byte; + threshold = 0; + + + val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AIHTL); + threshold = val_byte; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_byte) ; + threshold = threshold + ((uint16_t)val_byte << 8); + } + + + + + + + void setLightIntHighThreshold(uint16_t threshold) + { + uint8_t val_low; + uint8_t val_high; + + + val_low = threshold & 0x00FF; + val_high = (threshold & 0xFF00) >> 8; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTL, val_low); + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_high) ; + } + + + + + + + + void getProximityIntLowThreshold(uint8_t &threshold) + { + threshold = 0; + + + threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT); + + } + + + + + + + void setProximityIntLowThreshold(uint8_t threshold) + { + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold) ; + } +# 1054 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" + void getProximityIntHighThreshold(uint8_t &threshold) + { + threshold = 0; + + + threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; + + } + + + + + + + void setProximityIntHighThreshold(uint8_t threshold) + { + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold) ; + } + + + + + + + uint8_t getAmbientLightIntEnable(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + + + val = (val >> 4) & 0b00000001; + + return val; + } + + + + + + + void setAmbientLightIntEnable(uint8_t enable) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE); + + + enable &= 0b00000001; + enable = enable << 4; + val &= 0b11101111; + val |= enable; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; + } + + + + + + + uint8_t getProximityIntEnable(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + + + val = (val >> 5) & 0b00000001; + + return val; + } + + + + + + + void setProximityIntEnable(uint8_t enable) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + + + enable &= 0b00000001; + enable = enable << 5; + val &= 0b11011111; + val |= enable; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; + } + + + + + + + uint8_t getGestureIntEnable(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; + + + val = (val >> 1) & 0b00000001; + + return val; + } + + + + + + + void setGestureIntEnable(uint8_t enable) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; + + + enable &= 0b00000001; + enable = enable << 1; + val &= 0b11111101; + val |= enable; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; + } + + + + + + void clearAmbientLightInt(void) + { + uint8_t throwaway; + throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AICLEAR); + } + + + + + + void clearProximityInt(void) + { + uint8_t throwaway; + throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PICLEAR) ; + + } + + + + + + + uint8_t getGestureMode(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; + + + val &= 0b00000001; + + return val; + } + + + + + + + void setGestureMode(uint8_t mode) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; + + + mode &= 0b00000001; + val &= 0b11111110; + val |= mode; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; + } + + +bool APDS9960_init(void) +{ + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, DEFAULT_ATIME) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, DEFAULT_WTIME) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_PROX_PPULSE) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_UR, DEFAULT_POFFSET_UR) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_DL, DEFAULT_POFFSET_DL) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG1, DEFAULT_CONFIG1) ; + + setLEDDrive(DEFAULT_LDRIVE); + + setProximityGain(DEFAULT_PGAIN); + + setAmbientLightGain(DEFAULT_AGAIN); + + setProxIntLowThresh(DEFAULT_PILT) ; + + setProxIntHighThresh(DEFAULT_PIHT); + + setLightIntLowThreshold(DEFAULT_AILT) ; + + setLightIntHighThreshold(DEFAULT_AIHT) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PERS, DEFAULT_PERS) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, DEFAULT_CONFIG2) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, DEFAULT_CONFIG3) ; + + + setGestureEnterThresh(DEFAULT_GPENTH); + + setGestureExitThresh(DEFAULT_GEXTH) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF1, DEFAULT_GCONF1) ; + + setGestureGain(DEFAULT_GGAIN) ; + + setGestureLEDDrive(DEFAULT_GLDRIVE) ; + + setGestureWaitTime(DEFAULT_GWTIME) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_U, DEFAULT_GOFFSET) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_D, DEFAULT_GOFFSET) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_L, DEFAULT_GOFFSET) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_R, DEFAULT_GOFFSET) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPULSE, DEFAULT_GPULSE) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF3, DEFAULT_GCONF3) ; + + setGestureIntEnable(DEFAULT_GIEN); + + disablePower(); + + return true; +} +# 1332 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" +uint8_t getMode(void) +{ + uint8_t enable_value; + + + enable_value = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + + return enable_value; +} + + + + + + + +void setMode(uint8_t mode, uint8_t enable) +{ + uint8_t reg_val; + + + reg_val = getMode(); + + + + enable = enable & 0x01; + if( mode >= 0 && mode <= 6 ) { + if (enable) { + reg_val |= (1 << mode); + } else { + reg_val &= ~(1 << mode); + } + } else if( mode == ALL ) { + if (enable) { + reg_val = 0x7F; + } else { + reg_val = 0x00; + } + } + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, reg_val) ; +} + + + + + + +void enableLightSensor(void) +{ + + setAmbientLightGain(DEFAULT_AGAIN); + setAmbientLightIntEnable(0); + enablePower() ; + setMode(AMBIENT_LIGHT, 1) ; +} + + + + + +void disableLightSensor(void) +{ + setAmbientLightIntEnable(0) ; + setMode(AMBIENT_LIGHT, 0) ; +} + + + + + + +void enableProximitySensor(void) +{ + + setProximityGain(DEFAULT_PGAIN); + setLEDDrive(DEFAULT_LDRIVE) ; + setProximityIntEnable(0) ; + enablePower(); + setMode(PROXIMITY, 1) ; +} + + + + + +void disableProximitySensor(void) +{ + setProximityIntEnable(0) ; + setMode(PROXIMITY, 0) ; +} + + + + + + +void enableGestureSensor(void) +{ + + + + + + + + resetGestureParameters(); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, 0xFF) ; + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) ; + setLEDBoost(LED_BOOST_100); + setGestureIntEnable(0) ; + setGestureMode(1); + enablePower() ; + setMode(WAIT, 1) ; + setMode(PROXIMITY, 1) ; + setMode(GESTURE, 1); +} + + + + + +void disableGestureSensor(void) +{ + resetGestureParameters(); + setGestureIntEnable(0) ; + setGestureMode(0) ; + setMode(GESTURE, 0) ; +} + + + + + + +bool isGestureAvailable(void) +{ + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS) ; + + + val &= APDS9960_GVALID; + + + if( val == 1) { + return true; + } else { + return false; + } +} + + + + + + +int16_t readGesture(void) +{ + uint8_t fifo_level = 0; + uint8_t bytes_read = 0; + uint8_t fifo_data[128]; + uint8_t gstatus; + uint16_t motion; + uint16_t i; + uint8_t gesture_loop_counter = 0; + + + if( !isGestureAvailable() || !(getMode() & 0b01000001) ) { + return DIR_NONE; + } + + + while(1) { + if (gesture_loop_counter == APDS9960_MAX_GESTURE_CYCLES){ + disableGestureSensor(); + APDS9960_overload = true; + AddLog_P(LOG_LEVEL_DEBUG, PSTR("Sensor overload")); + } + gesture_loop_counter += 1; + + delay(FIFO_PAUSE_TIME); + + + gstatus = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS); + + + if( (gstatus & APDS9960_GVALID) == APDS9960_GVALID ) { + + + fifo_level = I2cRead8(APDS9960_I2C_ADDR,APDS9960_GFLVL) ; + + + if( fifo_level > 0) { + bytes_read = wireReadDataBlock( APDS9960_GFIFO_U, + (uint8_t*)fifo_data, + (fifo_level * 4) ); + if( bytes_read == -1 ) { + return ERROR; + } + + + if( bytes_read >= 4 ) { + for( i = 0; i < bytes_read; i += 4 ) { + gesture_data_.u_data[gesture_data_.index] = \ + fifo_data[i + 0]; + gesture_data_.d_data[gesture_data_.index] = \ + fifo_data[i + 1]; + gesture_data_.l_data[gesture_data_.index] = \ + fifo_data[i + 2]; + gesture_data_.r_data[gesture_data_.index] = \ + fifo_data[i + 3]; + gesture_data_.index++; + gesture_data_.total_gestures++; + } + + if( processGestureData() ) { + if( decodeGesture() ) { + + } + } + + gesture_data_.index = 0; + gesture_data_.total_gestures = 0; + } + } + } else { + + + delay(FIFO_PAUSE_TIME); + decodeGesture(); + motion = gesture_motion_; + resetGestureParameters(); + return motion; + } + } +} + + + + + +void enablePower(void) +{ + setMode(POWER, 1) ; +} + + + + + +void disablePower(void) +{ + setMode(POWER, 0) ; +} +# 1599 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" +void readAllColorAndProximityData(void) +{ + if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9)) + { + + + } +} +# 1615 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" +void resetGestureParameters(void) +{ + gesture_data_.index = 0; + gesture_data_.total_gestures = 0; + + gesture_ud_delta_ = 0; + gesture_lr_delta_ = 0; + + gesture_ud_count_ = 0; + gesture_lr_count_ = 0; + + gesture_state_ = 0; + gesture_motion_ = DIR_NONE; +} + + + + + + +bool processGestureData(void) +{ + uint8_t u_first = 0; + uint8_t d_first = 0; + uint8_t l_first = 0; + uint8_t r_first = 0; + uint8_t u_last = 0; + uint8_t d_last = 0; + uint8_t l_last = 0; + uint8_t r_last = 0; + uint16_t ud_ratio_first; + uint16_t lr_ratio_first; + uint16_t ud_ratio_last; + uint16_t lr_ratio_last; + uint16_t ud_delta; + uint16_t lr_delta; + uint16_t i; + + + if( gesture_data_.total_gestures <= 4 ) { + return false; + } + + + if( (gesture_data_.total_gestures <= 32) && \ + (gesture_data_.total_gestures > 0) ) { + + + for( i = 0; i < gesture_data_.total_gestures; i++ ) { + if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { + + u_first = gesture_data_.u_data[i]; + d_first = gesture_data_.d_data[i]; + l_first = gesture_data_.l_data[i]; + r_first = gesture_data_.r_data[i]; + break; + } + } + + + if( (u_first == 0) || (d_first == 0) || \ + (l_first == 0) || (r_first == 0) ) { + + return false; + } + + for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) { + + if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { + + u_last = gesture_data_.u_data[i]; + d_last = gesture_data_.d_data[i]; + l_last = gesture_data_.l_data[i]; + r_last = gesture_data_.r_data[i]; + break; + } + } + } + + + ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first); + lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first); + ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last); + lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last); + + + ud_delta = ud_ratio_last - ud_ratio_first; + lr_delta = lr_ratio_last - lr_ratio_first; + + + gesture_ud_delta_ += ud_delta; + gesture_lr_delta_ += lr_delta; + + + if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) { + gesture_ud_count_ = 1; + } else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 ) { + gesture_ud_count_ = -1; + } else { + gesture_ud_count_ = 0; + } + + + if( gesture_lr_delta_ >= GESTURE_SENSITIVITY_1 ) { + gesture_lr_count_ = 1; + } else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 ) { + gesture_lr_count_ = -1; + } else { + gesture_lr_count_ = 0; + } + return false; +} + + + + + + +bool decodeGesture(void) +{ + + + if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 0) ) { + gesture_motion_ = DIR_UP; + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 0) ) { + gesture_motion_ = DIR_DOWN; + } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 1) ) { + gesture_motion_ = DIR_RIGHT; + } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == -1) ) { + gesture_motion_ = DIR_LEFT; + } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_UP; + } else { + gesture_motion_ = DIR_RIGHT; + } + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == -1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_DOWN; + } else { + gesture_motion_ = DIR_LEFT; + } + } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == -1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_UP; + } else { + gesture_motion_ = DIR_LEFT; + } + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_DOWN; + } else { + gesture_motion_ = DIR_RIGHT; + } + } else { + return false; + } + + return true; +} + +void handleGesture(void) { + if (isGestureAvailable() ) { + switch (readGesture()) { + case DIR_UP: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("UP")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Up")); + break; + case DIR_DOWN: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("DOWN")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Down")); + break; + case DIR_LEFT: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("LEFT")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Left")); + break; + case DIR_RIGHT: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("RIGHT")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Right")); + break; + default: + if(APDS9960_overload) + { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("LONG")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Long")); + } + else{ + AddLog_P(LOG_LEVEL_DEBUG, PSTR("NONE")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("None")); + } + } + + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +#ifdef USE_RULES + RulesTeleperiod(); +#endif + } + } +} + +void APDS9960_adjustATime(void) +{ + + I2cValidRead16LE(&color_data.a, APDS9960_I2C_ADDR, APDS9960_CDATAL); + + + if (color_data.a < (uint16_t)20){ + APDS9960_aTime = 0x40; + } + else if (color_data.a < (uint16_t)40){ + APDS9960_aTime = 0x80; + } + else if (color_data.a < (uint16_t)50){ + APDS9960_aTime = DEFAULT_ATIME; + } + else if (color_data.a < (uint16_t)70){ + APDS9960_aTime = 0xc0; + } + if (color_data.a < 200){ + APDS9960_aTime = 0xe9; + } + + + + else{ + APDS9960_aTime = 0xff; + } + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, APDS9960_aTime); + enablePower(); + enableLightSensor(); + delay(20); +} + + +void APDS9960_loop(void) +{ + if (recovery_loop_counter > 0){ + recovery_loop_counter -= 1; + } + if (recovery_loop_counter == 1 && APDS9960_overload){ + enableGestureSensor(); + APDS9960_overload = false; + Response_P(PSTR("{\"Gesture\":\"On\"}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + gesture_mode = 1; + } + + if (gesture_mode) { + if (recovery_loop_counter == 0){ + handleGesture(); + + if (APDS9960_overload) + { + disableGestureSensor(); + recovery_loop_counter = APDS9960_LONG_RECOVERY; + Response_P(PSTR("{\"Gesture\":\"Off\"}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + gesture_mode = 0; + } + } + } +} + +bool APDS9960_detect(void) +{ + if (APDS9960type) { + return true; + } + + bool success = false; + APDS9960type = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ID); + + if (APDS9960type == APDS9960_CHIPID_1 || APDS9960type == APDS9960_CHIPID_2) { + strcpy_P(APDS9960stype, PSTR("APDS9960")); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, APDS9960stype, APDS9960_I2C_ADDR); + if (APDS9960_init()) { + success = true; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "APDS9960 initialized")); + enableProximitySensor(); + enableGestureSensor(); + } + } + else { + if (APDS9960type == APDS9930_CHIPID_1 || APDS9960type == APDS9930_CHIPID_2) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("APDS9930 found at address 0x%x, unsupported chip"), APDS9960_I2C_ADDR); + } + else{ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("APDS9960 not found at address 0x%x"), APDS9960_I2C_ADDR); + } + } + currentGesture[0] = '\0'; + return success; +} + + + + + +void APDS9960_show(bool json) +{ + if (!APDS9960type) { + return; + } + if (!gesture_mode && !APDS9960_overload) { + char red_chr[10]; + char green_chr[10]; + char blue_chr[10]; + char ambient_chr[10]; + char cct_chr[10]; + char prox_chr[10]; + + readAllColorAndProximityData(); + + sprintf (ambient_chr, "%u", color_data.a/4); + sprintf (red_chr, "%u", color_data.r); + sprintf (green_chr, "%u", color_data.g); + sprintf (blue_chr, "%u", color_data.b ); + sprintf (prox_chr, "%u", color_data.p ); + + + + + + calculateColorTemperature(); + sprintf (cct_chr, "%u", color_data.cct); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"CCT\":%s,\"Proximity\":%s}"), + APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_APDS_9960_SNS, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr ); +#endif + } + } + else { + if (json && (currentGesture[0] != '\0' )) { + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":1}"), APDS9960stype, currentGesture); + currentGesture[0] = '\0'; + } + } +} +# 1979 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" +bool APDS9960CommandSensor(void) +{ + bool serviced = true; + + switch (XdrvMailbox.payload) { + case 0: + disableGestureSensor(); + gesture_mode = 0; + enableLightSensor(); + APDS9960_overload = false; + break; + case 1: + if (APDS9960type) { + setGestureGain(DEFAULT_GGAIN); + setProximityGain(DEFAULT_PGAIN); + disableLightSensor(); + enableGestureSensor(); + gesture_mode = 1; + } + break; + case 2: + if (APDS9960type) { + setGestureGain(GGAIN_2X); + setProximityGain(PGAIN_2X); + disableLightSensor(); + enableGestureSensor(); + gesture_mode = 1; + } + break; + default: + int temp_aTime = (uint8_t)XdrvMailbox.payload; + if (temp_aTime > 2 && temp_aTime < 256){ + disablePower(); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, temp_aTime); + enablePower(); + enableLightSensor(); + } + break; + } + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_27, GetStateText(gesture_mode)); + + return serviced; +} + + + + + +bool Xsns27(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + if (FUNC_INIT == function) { + APDS9960_detect(); + } else if (APDS9960type) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + APDS9960_loop(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_27 == XdrvMailbox.index) { + result = APDS9960CommandSensor(); + } + break; + case FUNC_JSON_APPEND: + APDS9960_show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + APDS9960_show(0); + break; +#endif + } + } + } + return result; +} +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_28_tm1638.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_28_tm1638.ino" +#ifdef USE_TM1638 + + + + + + +#define XSNS_28 28 + +#define TM1638_COLOR_NONE 0 +#define TM1638_COLOR_RED 1 +#define TM1638_COLOR_GREEN 2 + +#define TM1638_CLOCK_DELAY 1 + +uint8_t tm1638_type = 1; +uint8_t tm1638_clock_pin = 0; +uint8_t tm1638_data_pin = 0; +uint8_t tm1638_strobe_pin = 0; +uint8_t tm1638_displays = 8; +uint8_t tm1638_active_display = 1; +uint8_t tm1638_intensity = 0; +uint8_t tm1638_state = 0; + + + + + + +void Tm16XXSend(uint8_t data) +{ + for (uint32_t i = 0; i < 8; i++) { + digitalWrite(tm1638_data_pin, !!(data & (1 << i))); + digitalWrite(tm1638_clock_pin, LOW); + delayMicroseconds(TM1638_CLOCK_DELAY); + digitalWrite(tm1638_clock_pin, HIGH); + } +} + +void Tm16XXSendCommand(uint8_t cmd) +{ + digitalWrite(tm1638_strobe_pin, LOW); + Tm16XXSend(cmd); + digitalWrite(tm1638_strobe_pin, HIGH); +} + +void TM16XXSendData(uint8_t address, uint8_t data) +{ + Tm16XXSendCommand(0x44); + digitalWrite(tm1638_strobe_pin, LOW); + Tm16XXSend(0xC0 | address); + Tm16XXSend(data); + digitalWrite(tm1638_strobe_pin, HIGH); +} + +uint8_t Tm16XXReceive(void) +{ + uint8_t temp = 0; + + + pinMode(tm1638_data_pin, INPUT); + digitalWrite(tm1638_data_pin, HIGH); + + for (uint32_t i = 0; i < 8; ++i) { + digitalWrite(tm1638_clock_pin, LOW); + delayMicroseconds(TM1638_CLOCK_DELAY); + temp |= digitalRead(tm1638_data_pin) << i; + digitalWrite(tm1638_clock_pin, HIGH); + } + + + pinMode(tm1638_data_pin, OUTPUT); + digitalWrite(tm1638_data_pin, LOW); + + return temp; +} + + + +void Tm16XXClearDisplay(void) +{ + for (uint32_t i = 0; i < tm1638_displays; i++) { + TM16XXSendData(i << 1, 0); + } +} + +void Tm1638SetLED(uint8_t color, uint8_t pos) +{ + TM16XXSendData((pos << 1) + 1, color); +} + +void Tm1638SetLEDs(word leds) +{ + for (uint32_t i = 0; i < tm1638_displays; i++) { + uint8_t color = 0; + + if ((leds & (1 << i)) != 0) { + color |= TM1638_COLOR_RED; + } + + if ((leds & (1 << (i + 8))) != 0) { + color |= TM1638_COLOR_GREEN; + } + + Tm1638SetLED(color, i); + } +} + +uint8_t Tm1638GetButtons(void) +{ + uint8_t keys = 0; + + digitalWrite(tm1638_strobe_pin, LOW); + Tm16XXSend(0x42); + for (uint32_t i = 0; i < 4; i++) { + keys |= Tm16XXReceive() << i; + } + digitalWrite(tm1638_strobe_pin, HIGH); + + return keys; +} + + + +void TmInit(void) +{ + tm1638_type = 0; + if ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99)) { + tm1638_clock_pin = pin[GPIO_TM16CLK]; + tm1638_data_pin = pin[GPIO_TM16DIO]; + tm1638_strobe_pin = pin[GPIO_TM16STB]; + + pinMode(tm1638_data_pin, OUTPUT); + pinMode(tm1638_clock_pin, OUTPUT); + pinMode(tm1638_strobe_pin, OUTPUT); + + digitalWrite(tm1638_strobe_pin, HIGH); + digitalWrite(tm1638_clock_pin, HIGH); + + Tm16XXSendCommand(0x40); + Tm16XXSendCommand(0x80 | (tm1638_active_display ? 8 : 0) | tmin(7, tm1638_intensity)); + + digitalWrite(tm1638_strobe_pin, LOW); + Tm16XXSend(0xC0); + for (uint32_t i = 0; i < 16; i++) { + Tm16XXSend(0x00); + } + digitalWrite(tm1638_strobe_pin, HIGH); + + tm1638_type = 1; + tm1638_state = 1; + } +} + +void TmLoop(void) +{ + if (tm1638_state) { + uint8_t buttons = Tm1638GetButtons(); + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { + SwitchSetVirtual(i, (buttons &1) ^1); + uint8_t color = (SwitchGetVirtual(i)) ? TM1638_COLOR_NONE : TM1638_COLOR_RED; + Tm1638SetLED(color, i); + buttons >>= 1; + } + SwitchHandler(1); + } +} +# 201 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_28_tm1638.ino" +bool Xsns28(uint8_t function) +{ + bool result = false; + + if (tm1638_type) { + switch (function) { + case FUNC_INIT: + TmInit(); + break; + case FUNC_EVERY_50_MSECOND: + TmLoop(); + break; +# 223 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_28_tm1638.ino" + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_29_mcp230xx.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_29_mcp230xx.ino" +#ifdef USE_I2C +#ifdef USE_MCP230xx +# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_29_mcp230xx.ino" +#define XSNS_29 29 + + + + + +uint8_t MCP230xx_IODIR = 0x00; +uint8_t MCP230xx_GPINTEN = 0x02; +uint8_t MCP230xx_IOCON = 0x05; +uint8_t MCP230xx_GPPU = 0x06; +uint8_t MCP230xx_INTF = 0x07; +uint8_t MCP230xx_INTCAP = 0x08; +uint8_t MCP230xx_GPIO = 0x09; + +uint8_t mcp230xx_type = 0; +uint8_t mcp230xx_pincount = 0; +uint8_t mcp230xx_int_en = 0; +uint8_t mcp230xx_int_prio_counter = 0; +uint8_t mcp230xx_int_counter_en = 0; +uint8_t mcp230xx_int_retainer_en = 0; +uint8_t mcp230xx_int_sec_counter = 0; + +uint8_t mcp230xx_int_report_defer_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +uint16_t mcp230xx_int_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +uint8_t mcp230xx_int_retainer[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +unsigned long int_millis[16]; + +const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL_UP\":\"%s\",\"INT_MODE\":\"%s\",\"STATE\":\"%s\"}}"; + +const char MCP230XX_INTCFG_RESPONSE[] PROGMEM = "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + +#ifdef USE_MCP230xx_OUTPUT +const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"}}"; +#endif + +void MCP230xx_CheckForIntCounter(void) { + uint8_t en = 0; + for (uint32_t ca=0;ca<16;ca++) { + if (Settings.mcp230xx_config[ca].int_count_en) { + en=1; + } + } + if (!Settings.mcp230xx_int_timer) en=0; + mcp230xx_int_counter_en=en; + if (!mcp230xx_int_counter_en) { + for (uint32_t ca=0;ca<16;ca++) { + mcp230xx_int_counter[ca] = 0; + } + } +} + +void MCP230xx_CheckForIntRetainer(void) { + uint8_t en = 0; + for (uint32_t ca=0;ca<16;ca++) { + if (Settings.mcp230xx_config[ca].int_retain_flag) { + en=1; + } + } + mcp230xx_int_retainer_en=en; + if (!mcp230xx_int_retainer_en) { + for (uint32_t ca=0;ca<16;ca++) { + mcp230xx_int_retainer[ca] = 0; + } + } +} + +const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) { +#ifdef USE_MCP230xx_OUTPUT +if ((6 == pinmod) && (statu < 2)) { statu = abs(statu-1); } +#endif + switch (statu) { + case 0: + return "OFF"; + break; + case 1: + return "ON"; + break; +#ifdef USE_MCP230xx_OUTPUT + case 2: + return "TOGGLE"; + break; +#endif + } + return ""; +} + +const char* IntModeTxt(uint8_t intmo) { + switch (intmo) { + case 0: + return "ALL"; + break; + case 1: + return "EVENT"; + break; + case 2: + return "TELE"; + break; + case 3: + return "DISABLED"; + break; + } + return ""; +} + +uint8_t MCP230xx_readGPIO(uint8_t port) { + return I2cRead8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port); +} + +void MCP230xx_ApplySettings(void) { + uint8_t int_en = 0; + for (uint32_t mcp230xx_port=0;mcp230xx_port 0) { + if (I2cValidRead8(&mcp230xx_intcap, USE_MCP230xx_ADDR, MCP230xx_INTCAP+mcp230xx_port)) { + for (uint32_t intp = 0; intp < 8; intp++) { + if ((intf >> intp) & 0x01) { + report_int = 0; + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode > 1) { + switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode) { + case 2: + report_int = 1; + break; + case 3: + if (((mcp230xx_intcap >> intp) & 0x01) == 0) report_int = 1; + break; + case 4: + if (((mcp230xx_intcap >> intp) & 0x01) == 1) report_int = 1; + break; + default: + break; + } + + if ((mcp230xx_int_counter_en) && (report_int)) { + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { + mcp230xx_int_counter[intp+(mcp230xx_port*8)]++; + } + } + + if (report_int) { + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_defer) { + mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)]++; + if (mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)] >= Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_defer) { + mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)]=0; + } else { + report_int = 0; + } + } + } + + if (report_int) { + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_retain_flag) { + mcp230xx_int_retainer[intp+(mcp230xx_port*8)] = 1; + report_int = 0; + } + } + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { + report_int = 0; + } + if (report_int) { + bool int_tele = false; + bool int_event = false; + unsigned long millis_now = millis(); + unsigned long millis_since_last_int = millis_now - int_millis[intp+(mcp230xx_port*8)]; + int_millis[intp+(mcp230xx_port*8)]=millis_now; + switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_mode) { + case 0: + int_tele=true; + int_event=true; + break; + case 1: + int_event=true; + break; + case 2: + int_tele=true; + break; + } + if (int_tele) { + ResponseTime_P(PSTR(",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"), + intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("MCP230XX_INT")); + } + if (int_event) { + char command[19]; + sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01)); + ExecuteCommand(command, SRC_RULE); + } + } + } + } + } + } + } + } + } +} + +void MCP230xx_Show(bool json) +{ + if (mcp230xx_type) { + if (json) { + if (mcp230xx_type > 0) { + uint8_t gpio = MCP230xx_readGPIO(0); + ResponseAppend_P(PSTR(",\"MCP230XX\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i"), + (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); + if (2 == mcp230xx_type) { + gpio = MCP230xx_readGPIO(1); + ResponseAppend_P(PSTR(",\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), + (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); + } + ResponseJsonEnd(); + } + } + } +} + +#ifdef USE_MCP230xx_OUTPUT + +void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { + uint8_t portpins; + uint8_t port = 0; + uint8_t pinmo = Settings.mcp230xx_config[pin].pinmode; + uint8_t interlock = Settings.flag.interlock; + int pinadd = (pin % 2)+1-(3*(pin % 2)); + char cmnd[7], stt[4]; + if (pin > 7) { port = 1; } + portpins = MCP230xx_readGPIO(port); + if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { + if (pinstate < 2) { + if (6 == pinmo) { + if (pinstate) portpins |= (1 << (pin-(port*8))); else portpins |= (1 << (pin+pinadd-(port*8))),portpins &= ~(1 << (pin-(port*8))); + } else { + if (pinstate) portpins &= ~(1 << (pin+pinadd-(port*8))),portpins |= (1 << (pin-(port*8))); else portpins &= ~(1 << (pin-(port*8))); + } + } else { + if (6 == pinmo) { + portpins |= (1 << (pin+pinadd-(port*8))),portpins ^= (1 << (pin-(port*8))); + } else { + portpins &= ~(1 << (pin+pinadd-(port*8))),portpins ^= (1 << (pin-(port*8))); + } + } + } else { + if (pinstate < 2) { + if (pinstate) portpins |= (1 << (pin-(port*8))); else portpins &= ~(1 << (pin-(port*8))); + } else { + portpins ^= (1 << (pin-(port*8))); + } + } + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port, portpins); + if (Settings.flag.save_state) { + Settings.mcp230xx_config[pin].saved_state=portpins>>(pin-(port*8))&1; + Settings.mcp230xx_config[pin+pinadd].saved_state=portpins>>(pin+pinadd-(port*8))&1; + } + sprintf(cmnd,ConvertNumTxt(pinstate, pinmo)); + sprintf(stt,ConvertNumTxt((portpins >> (pin-(port*8))&1), pinmo)); + if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { + char stt1[4]; + sprintf(stt1,ConvertNumTxt((portpins >> (pin+pinadd-(port*8))&1), pinmo)); + Response_P(PSTR("{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"},\"S29cmnd_D%i\":{\"STATE\":\"%s\"}}"),pin, cmnd, stt, pin+pinadd, stt1); + } else { + Response_P(MCP230XX_CMND_RESPONSE, pin, cmnd, stt); + } +} + +#endif + +void MCP230xx_Reset(uint8_t pinmode) { + uint8_t pullup = 0; + if ((pinmode > 1) && (pinmode < 5)) { pullup=1; } + for (uint32_t pinx=0;pinx<16;pinx++) { + Settings.mcp230xx_config[pinx].pinmode=pinmode; + Settings.mcp230xx_config[pinx].pullup=pullup; + Settings.mcp230xx_config[pinx].saved_state=0; + if ((pinmode > 1) && (pinmode < 5)) { + Settings.mcp230xx_config[pinx].int_report_mode=0; + } else { + Settings.mcp230xx_config[pinx].int_report_mode=3; + } + Settings.mcp230xx_config[pinx].int_report_defer=0; + Settings.mcp230xx_config[pinx].int_count_en=0; + Settings.mcp230xx_config[pinx].int_retain_flag=0; + Settings.mcp230xx_config[pinx].spare13=0; + Settings.mcp230xx_config[pinx].spare14=0; + Settings.mcp230xx_config[pinx].spare15=0; + } + Settings.mcp230xx_int_prio = 0; + Settings.mcp230xx_int_timer = 0; + MCP230xx_ApplySettings(); + char pulluptxt[7]; + char intmodetxt[9]; + sprintf(pulluptxt,ConvertNumTxt(pullup)); + uint8_t intmode = 3; + if ((pinmode > 1) && (pinmode < 5)) { intmode = 0; } + sprintf(intmodetxt,IntModeTxt(intmode)); + Response_P(MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,""); +} + +bool MCP230xx_Command(void) { + bool serviced = true; + bool validpin = false; + uint8_t paramcount = 0; + if (XdrvMailbox.data_len > 0) { + paramcount=1; + } else { + serviced = false; + return serviced; + } + char sub_string[XdrvMailbox.data_len]; + for (uint32_t ca=0;ca 1) { + uint8_t intpri = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if ((intpri >= 0) && (intpri <= 20)) { + Settings.mcp230xx_int_prio = intpri; + Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); + return serviced; + } + } + + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTTIMER")) { + if (paramcount > 1) { + uint8_t inttim = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if ((inttim >= 0) && (inttim <= 3600)) { + Settings.mcp230xx_int_timer = inttim; + MCP230xx_CheckForIntCounter(); + Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); + return serviced; + } + } + + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTDEF")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (pin < mcp230xx_pincount) { + if (pin == 0) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; + } else { + validpin = true; + } + } + if (validpin) { + if (paramcount > 2) { + uint8_t intdef = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((intdef >= 0) && (intdef <= 15)) { + Settings.mcp230xx_config[pin].int_report_defer=intdef; + if (Settings.mcp230xx_config[pin].int_count_en) { + Settings.mcp230xx_config[pin].int_count_en=0; + MCP230xx_CheckForIntCounter(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTCNT for pin D%i"),pin); + } + Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); + return serviced; + } else { + serviced=false; + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); + return serviced; + } + } + serviced = false; + return serviced; + } else { + serviced = false; + return serviced; + } + } + + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTCNT")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (pin < mcp230xx_pincount) { + if (pin == 0) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; + } else { + validpin = true; + } + } + if (validpin) { + if (paramcount > 2) { + uint8_t intcnt = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((intcnt >= 0) && (intcnt <= 1)) { + Settings.mcp230xx_config[pin].int_count_en=intcnt; + if (Settings.mcp230xx_config[pin].int_report_defer) { + Settings.mcp230xx_config[pin].int_report_defer=0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTDEF for pin D%i"),pin); + } + if (Settings.mcp230xx_config[pin].int_report_mode < 3) { + Settings.mcp230xx_config[pin].int_report_mode=3; + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled immediate interrupt/telemetry reporting for pin D%i"),pin); + } + if ((Settings.mcp230xx_config[pin].int_count_en) && (!Settings.mcp230xx_int_timer)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - INTCNT enabled for pin D%i but global INTTIMER is disabled!"),pin); + } + MCP230xx_CheckForIntCounter(); + Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); + return serviced; + } else { + serviced=false; + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); + return serviced; + } + } + serviced = false; + return serviced; + } else { + serviced = false; + return serviced; + } + } + + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTRETAIN")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (pin < mcp230xx_pincount) { + if (pin == 0) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; + } else { + validpin = true; + } + } + if (validpin) { + if (paramcount > 2) { + uint8_t int_retain = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((int_retain >= 0) && (int_retain <= 1)) { + Settings.mcp230xx_config[pin].int_retain_flag=int_retain; + Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); + MCP230xx_CheckForIntRetainer(); + return serviced; + } else { + serviced=false; + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); + return serviced; + } + } + serviced = false; + return serviced; + } else { + serviced = false; + return serviced; + } + } + + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); + + if (pin < mcp230xx_pincount) { + if (0 == pin) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1), "0")) validpin=true; + } else { + validpin=true; + } + } + if (validpin && (paramcount > 1)) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "?")) { + uint8_t port = 0; + if (pin > 7) { port = 1; } + uint8_t portdata = MCP230xx_readGPIO(port); + char pulluptxtr[7],pinstatustxtr[7]; + char intmodetxt[9]; + sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); + sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup)); +#ifdef USE_MCP230xx_OUTPUT + uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode; + sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); + Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr); +#else + sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); + Response_P(MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,intmodetxt,pinstatustxtr); +#endif + return serviced; + } +#ifdef USE_MCP230xx_OUTPUT + if (Settings.mcp230xx_config[pin].pinmode >= 5) { + uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "ON")) { + MCP230xx_SetOutPin(pin,abs(pincmd-1)); + return serviced; + } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "OFF")) { + MCP230xx_SetOutPin(pin,pincmd); + return serviced; + } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "T")) { + MCP230xx_SetOutPin(pin,2); + return serviced; + } + } +#endif + uint8_t pinmode = 0; + uint8_t pullup = 0; + uint8_t intmode = 0; + if (paramcount > 1) { + pinmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + } + if (paramcount > 2) { + pullup = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + } + if (paramcount > 3) { + intmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); + } +#ifdef USE_MCP230xx_OUTPUT + if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 7) && (pullup < 2)) { +#else + if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 5) && (pullup < 2)) { +#endif + Settings.mcp230xx_config[pin].pinmode=pinmode; + Settings.mcp230xx_config[pin].pullup=pullup; + if ((pinmode > 1) && (pinmode < 5)) { + if ((intmode >= 0) && (intmode <= 3)) { + Settings.mcp230xx_config[pin].int_report_mode=intmode; + } + } else { + Settings.mcp230xx_config[pin].int_report_mode=3; + } + MCP230xx_ApplySettings(); + uint8_t port = 0; + if (pin > 7) { port = 1; } + uint8_t portdata = MCP230xx_readGPIO(port); + char pulluptxtc[7], pinstatustxtc[7]; + char intmodetxt[9]; + sprintf(pulluptxtc,ConvertNumTxt(pullup)); + sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); +#ifdef USE_MCP230xx_OUTPUT + sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1,Settings.mcp230xx_config[pin].pinmode)); +#else + sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1)); +#endif + Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); + return serviced; + } + } else { + serviced=false; + return serviced; + } + return serviced; +} + +#ifdef USE_MCP230xx_DISPLAYOUTPUT + +const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "{s}MCP230XX D%d{m}%s{e}"; + +void MCP230xx_UpdateWebData(void) { + uint8_t gpio1 = MCP230xx_readGPIO(0); + uint8_t gpio2 = 0; + if (2 == mcp230xx_type) { + gpio2 = MCP230xx_readGPIO(1); + } + uint16_t gpio = (gpio2 << 8) + gpio1; + for (uint32_t pin = 0; pin < mcp230xx_pincount; pin++) { + if (Settings.mcp230xx_config[pin].pinmode >= 5) { + char stt[7]; + sprintf(stt,ConvertNumTxt((gpio>>pin)&1,Settings.mcp230xx_config[pin].pinmode)); + WSContentSend_PD(HTTP_SNS_MCP230xx_OUTPUT, pin, stt); + } + } +} + +#endif + +#ifdef USE_MCP230xx_OUTPUT + +void MCP230xx_OutputTelemetry(void) { + if (0 == mcp230xx_type) { return; } + uint8_t outputcount = 0; + uint16_t gpiototal = 0; + uint8_t gpioa = 0; + uint8_t gpiob = 0; + gpioa=MCP230xx_readGPIO(0); + if (2 == mcp230xx_type) { gpiob=MCP230xx_readGPIO(1); } + gpiototal=((uint16_t)gpiob << 8) | gpioa; + for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].pinmode >= 5) outputcount++; + } + if (outputcount) { + char stt[7]; + ResponseTime_P(PSTR(",\"MCP230_OUT\":{")); + for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].pinmode >= 5) { + sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); + ResponseAppend_P(PSTR("\"OUT_D%i\":\"%s\","),pinx,stt); + } + } + ResponseAppend_P(PSTR("\"END\":1}}")); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + } +} + +#endif + +void MCP230xx_Interrupt_Counter_Report(void) { + ResponseTime_P(PSTR(",\"MCP230_INTTIMER\":{")); + for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].int_count_en) { + ResponseAppend_P(PSTR("\"INTCNT_D%i\":%i,"),pinx,mcp230xx_int_counter[pinx]); + mcp230xx_int_counter[pinx]=0; + } + } + ResponseAppend_P(PSTR("\"END\":1}}")); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + mcp230xx_int_sec_counter = 0; +} + +void MCP230xx_Interrupt_Retain_Report(void) { + uint16_t retainresult = 0; + ResponseTime_P(PSTR(",\"MCP_INTRETAIN\":{")); + for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].int_retain_flag) { + ResponseAppend_P(PSTR("\"D%i\":%i,"),pinx,mcp230xx_int_retainer[pinx]); + retainresult |= (((mcp230xx_int_retainer[pinx])&1) << pinx); + mcp230xx_int_retainer[pinx]=0; + } + } + ResponseAppend_P(PSTR("\"Value\":%u}}"),retainresult); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +} + + + + + +bool Xsns29(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_EVERY_SECOND: + MCP230xx_Detect(); + if (mcp230xx_int_counter_en) { + mcp230xx_int_sec_counter++; + if (mcp230xx_int_sec_counter >= Settings.mcp230xx_int_timer) { + MCP230xx_Interrupt_Counter_Report(); + } + } + if (tele_period == 0) { + if (mcp230xx_int_retainer_en) { + MCP230xx_Interrupt_Retain_Report(); + } + } +#ifdef USE_MCP230xx_OUTPUT + if (tele_period == 0) { + MCP230xx_OutputTelemetry(); + } +#endif + break; + case FUNC_EVERY_50_MSECOND: + if ((mcp230xx_int_en) && (mcp230xx_type)) { + mcp230xx_int_prio_counter++; + if ((mcp230xx_int_prio_counter) >= (Settings.mcp230xx_int_prio)) { + MCP230xx_CheckForInterrupt(); + mcp230xx_int_prio_counter=0; + } + } + break; + case FUNC_JSON_APPEND: + MCP230xx_Show(1); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_29 == XdrvMailbox.index) { + result = MCP230xx_Command(); + } + break; +#ifdef USE_WEBSERVER +#ifdef USE_MCP230xx_OUTPUT +#ifdef USE_MCP230xx_DISPLAYOUTPUT + case FUNC_WEB_SENSOR: + MCP230xx_UpdateWebData(); + break; +#endif +#endif +#endif + default: + break; + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_30_mpr121.ino" +# 43 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_30_mpr121.ino" +#ifdef USE_I2C +#ifdef USE_MPR121 + + + + + +#define XSNS_30 30 + + + + + + + +#define MPR121_ELEX_REG 0x00 + + +#define MPR121_MHDR_REG 0x2B + + +#define MPR121_MHDR_VAL 0x01 + + +#define MPR121_NHDR_REG 0x2C + + +#define MPR121_NHDR_VAL 0x01 + + +#define MPR121_NCLR_REG 0x2D + + +#define MPR121_NCLR_VAL 0x0E + + +#define MPR121_MHDF_REG 0x2F + + +#define MPR121_MHDF_VAL 0x01 + + +#define MPR121_NHDF_REG 0x30 + + +#define MPR121_NHDF_VAL 0x05 + + +#define MPR121_NCLF_REG 0x31 + + +#define MPR121_NCLF_VAL 0x01 + + +#define MPR121_MHDPROXR_REG 0x36 + + +#define MPR121_MHDPROXR_VAL 0x3F + + +#define MPR121_NHDPROXR_REG 0x37 + + +#define MPR121_NHDPROXR_VAL 0x5F + + +#define MPR121_NCLPROXR_REG 0x38 + + +#define MPR121_NCLPROXR_VAL 0x04 + + +#define MPR121_FDLPROXR_REG 0x39 + + +#define MPR121_FDLPROXR_VAL 0x00 + + +#define MPR121_MHDPROXF_REG 0x3A + + +#define MPR121_MHDPROXF_VAL 0x01 + + +#define MPR121_NHDPROXF_REG 0x3B + + +#define MPR121_NHDPROXF_VAL 0x01 + + +#define MPR121_NCLPROXF_REG 0x3C + + +#define MPR121_NCLPROXF_VAL 0x1F + + +#define MPR121_FDLPROXF_REG 0x3D + + +#define MPR121_FDLPROXF_VAL 0x04 + + +#define MPR121_E0TTH_REG 0x41 + + +#define MPR121_E0TTH_VAL 12 + + +#define MPR121_E0RTH_REG 0x42 + + +#define MPR121_E0RTH_VAL 6 + + +#define MPR121_CDT_REG 0x5D + + +#define MPR121_CDT_VAL 0x20 + + +#define MPR121_ECR_REG 0x5E + + +#define MPR121_ECR_VAL 0x8F + + + +#define MPR121_SRST_REG 0x80 + + +#define MPR121_SRST_VAL 0x63 + + +#define BITC(sensor,position) ((pS->current[sensor] >> position) & 1) + + +#define BITP(sensor,position) ((pS->previous[sensor] >> position) & 1) +# 191 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_30_mpr121.ino" +typedef struct mpr121 mpr121; +struct mpr121 { + const uint8_t i2c_addr[4] = { 0x5A, 0x5B, 0x5C, 0x5D }; + const char id[4] = { 'A', 'B', 'C', 'D' }; + bool connected[4] = { false, false, false, false }; + bool running[4] = { false, false, false, false }; + uint16_t current[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; + uint16_t previous[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; +}; +# 211 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_30_mpr121.ino" +void Mpr121Init(struct mpr121 *pS) +{ + + + for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { + + + pS->connected[i] = (I2cWrite8(pS->i2c_addr[i], MPR121_SRST_REG, MPR121_SRST_VAL) + && (0x24 == I2cRead8(pS->i2c_addr[i], 0x5D))); + if (pS->connected[i]) { + + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "MPR121(%c) " D_FOUND_AT " 0x%X"), pS->id[i], pS->i2c_addr[i]); + + + for (uint32_t j = 0; j < 13; j++) { + + + I2cWrite8(pS->i2c_addr[i], MPR121_E0TTH_REG + 2 * j, MPR121_E0TTH_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_E0RTH_REG + 2 * j, MPR121_E0RTH_VAL); + } + + + I2cWrite8(pS->i2c_addr[i], MPR121_MHDR_REG, MPR121_MHDR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NHDR_REG, MPR121_NHDR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NCLR_REG, MPR121_NCLR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_MHDF_REG, MPR121_MHDF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NHDF_REG, MPR121_NHDF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NCLF_REG, MPR121_NCLF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXR_REG, MPR121_MHDPROXR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXR_REG, MPR121_NHDPROXR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXR_REG, MPR121_NCLPROXR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXR_REG, MPR121_FDLPROXR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXF_REG, MPR121_MHDPROXF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXF_REG, MPR121_NHDPROXF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXF_REG, MPR121_NCLPROXF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXF_REG, MPR121_FDLPROXF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_CDT_REG, MPR121_CDT_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_ECR_REG, MPR121_ECR_VAL); + + + pS->running[i] = (0x00 != I2cRead8(pS->i2c_addr[i], MPR121_ECR_REG)); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "MPR121%c: %sRunning"), pS->id[i], (pS->running[i]) ? "" : "NOT"); + + } else { + + + pS->running[i] = false; + } + } + + + if (!(pS->connected[0] || pS->connected[1] || pS->connected[2] + || pS->connected[3])) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C "MPR121: No sensors found")); + } +} +# 316 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_30_mpr121.ino" +void Mpr121Show(struct mpr121 *pS, uint8_t function) +{ + + + for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { + + + if (pS->connected[i]) { + + + if (!I2cValidRead16LE(&pS->current[i], pS->i2c_addr[i], MPR121_ELEX_REG)) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Cannot read data!"), pS->id[i]); + Mpr121Init(pS); + return; + } + + if (BITC(i, 15)) { + + + I2cWrite8(pS->i2c_addr[i], MPR121_ELEX_REG, 0x00); + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Excess current detected! Fix circuits if it happens repeatedly! Soft-resetting MPR121 ..."), pS->id[i]); + Mpr121Init(pS); + return; + } + } + + if (pS->running[i]) { + + + if (FUNC_JSON_APPEND == function) { + ResponseAppend_P(PSTR(",\"MPR121%c\":{"), pS->id[i]); + } + + for (uint32_t j = 0; j < 13; j++) { + + + if ((FUNC_EVERY_50_MSECOND == function) + && (BITC(i, j) != BITP(i, j))) { + Response_P(PSTR("{\"MPR121%c\":{\"Button%i\":%i}}"), pS->id[i], j, BITC(i, j)); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); + } + +#ifdef USE_WEBSERVER + if (FUNC_WEB_SENSOR == function) { + WSContentSend_PD(PSTR("{s}MPR121%c Button%d{m}%d{e}"), pS->id[i], j, BITC(i, j)); + } +#endif + + + if (FUNC_JSON_APPEND == function) { + ResponseAppend_P(PSTR("%s\"Button%i\":%i"), (j > 0 ? "," : ""), j, BITC(i, j)); + } + } + + + pS->previous[i] = pS->current[i]; + + + if (FUNC_JSON_APPEND == function) { + ResponseJsonEnd(); + } + } + } +} +# 400 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_30_mpr121.ino" +bool Xsns30(uint8_t function) +{ + + bool result = false; + + + static struct mpr121 mpr121; + + + if (i2c_flg) { + switch (function) { + + + case FUNC_INIT: + Mpr121Init(&mpr121); + break; + + + case FUNC_EVERY_50_MSECOND: + Mpr121Show(&mpr121, FUNC_EVERY_50_MSECOND); + break; + + + case FUNC_JSON_APPEND: + Mpr121Show(&mpr121, FUNC_JSON_APPEND); + break; + +#ifdef USE_WEBSERVER + + case FUNC_WEB_SENSOR: + Mpr121Show(&mpr121, FUNC_WEB_SENSOR); + break; +#endif + } + } + + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_31_ccs811.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_31_ccs811.ino" +#ifdef USE_I2C +#ifdef USE_CCS811 +# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_31_ccs811.ino" +#define XSNS_31 31 + +#include "Adafruit_CCS811.h" + +Adafruit_CCS811 ccs; +uint8_t CCS811_ready; +uint8_t CCS811_type; +uint16_t eCO2; +uint16_t TVOC; +uint8_t tcnt = 0; +uint8_t ecnt = 0; + + +#define EVERYNSECONDS 5 + +void CCS811Update(void) +{ + tcnt++; + if (tcnt >= EVERYNSECONDS) { + tcnt = 0; + CCS811_ready = 0; + if (!CCS811_type) { + sint8_t res = ccs.begin(CCS811_ADDRESS); + if (!res) { + CCS811_type = 1; + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "CCS811", 0x5A); + } else { + + } + } else { + if (ccs.available()) { + if (!ccs.readData()){ + TVOC = ccs.getTVOC(); + eCO2 = ccs.geteCO2(); + CCS811_ready = 1; + if (global_update && global_humidity>0 && global_temperature!=9999) { ccs.setEnvironmentalData((uint8_t)global_humidity, global_temperature); } + ecnt = 0; + } + } else { + + ecnt++; + if (ecnt > 6) { + + ccs.begin(CCS811_ADDRESS); + } + } + } + } +} + +const char HTTP_SNS_CCS811[] PROGMEM = + "{s}CCS811 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" + "{s}CCS811 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; + +void CCS811Show(bool json) +{ + if (CCS811_ready) { + if (json) { + ResponseAppend_P(PSTR(",\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), eCO2,TVOC); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, eCO2); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CCS811, eCO2, TVOC); +#endif + } + } +} + + + + + +bool Xsns31(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_EVERY_SECOND: + CCS811Update(); + break; + case FUNC_JSON_APPEND: + CCS811Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + CCS811Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_32_mpu6050.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_32_mpu6050.ino" +#ifdef USE_I2C +#ifdef USE_MPU6050 +# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_32_mpu6050.ino" +#define XSNS_32 32 + +#define D_SENSOR_MPU6050 "MPU6050" + +#define MPU_6050_ADDR_AD0_LOW 0x68 +#define MPU_6050_ADDR_AD0_HIGH 0x69 + +uint8_t MPU_6050_address; +uint8_t MPU_6050_addresses[] = { MPU_6050_ADDR_AD0_LOW, MPU_6050_ADDR_AD0_HIGH }; +uint8_t MPU_6050_found; + +int16_t MPU_6050_ax = 0, MPU_6050_ay = 0, MPU_6050_az = 0; +int16_t MPU_6050_gx = 0, MPU_6050_gy = 0, MPU_6050_gz = 0; +int16_t MPU_6050_temperature = 0; + +#ifdef USE_MPU6050_DMP + #include "MPU6050_6Axis_MotionApps20.h" + #include "I2Cdev.h" + #include + typedef struct MPU6050_DMP{ + uint8_t devStatus; + uint16_t packetSize; + uint16_t fifoCount; + uint8_t fifoBuffer[64]; + Quaternion q; + VectorInt16 aa; + VectorInt16 aaReal; + VectorFloat gravity; + float euler[3]; + } MPU6050_DMP; + + MPU6050_DMP MPU6050_dmp; +#else + #include +#endif +MPU6050 mpu6050; + +void MPU_6050PerformReading(void) +{ +#ifdef USE_MPU6050_DMP + mpu6050.resetFIFO(); + MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); + while (MPU6050_dmp.fifoCount < MPU6050_dmp.packetSize) MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); + mpu6050.getFIFOBytes(MPU6050_dmp.fifoBuffer, MPU6050_dmp.packetSize); + MPU6050_dmp.fifoCount -= MPU6050_dmp.packetSize; + + mpu6050.dmpGetQuaternion(&MPU6050_dmp.q, MPU6050_dmp.fifoBuffer); + mpu6050.dmpGetEuler(MPU6050_dmp.euler, &MPU6050_dmp.q); + mpu6050.dmpGetAccel(&MPU6050_dmp.aa, MPU6050_dmp.fifoBuffer); + mpu6050.dmpGetGravity(&MPU6050_dmp.gravity, &MPU6050_dmp.q); + mpu6050.dmpGetLinearAccel(&MPU6050_dmp.aaReal, &MPU6050_dmp.aa, &MPU6050_dmp.gravity); + MPU_6050_gx = MPU6050_dmp.euler[0] * 180/M_PI; + MPU_6050_gy = MPU6050_dmp.euler[1] * 180/M_PI; + MPU_6050_gz = MPU6050_dmp.euler[2] * 180/M_PI; + MPU_6050_ax = MPU6050_dmp.aaReal.x; + MPU_6050_ay = MPU6050_dmp.aaReal.y; + MPU_6050_az = MPU6050_dmp.aaReal.z; +#else + mpu6050.getMotion6( + &MPU_6050_ax, + &MPU_6050_ay, + &MPU_6050_az, + &MPU_6050_gx, + &MPU_6050_gy, + &MPU_6050_gz + ); +#endif + MPU_6050_temperature = mpu6050.getTemperature(); +} +# 116 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_32_mpu6050.ino" +void MPU_6050Detect(void) +{ + if (MPU_6050_found) + { + return; + } + + for (uint32_t i = 0; i < sizeof(MPU_6050_addresses); i++) + { + if(!I2cDevice(MPU_6050_addresses[i])) + { + break; + } + MPU_6050_address = MPU_6050_addresses[i]; + mpu6050.setAddr(MPU_6050_addresses[i]); + +#ifdef USE_MPU6050_DMP + MPU6050_dmp.devStatus = mpu6050.dmpInitialize(); + mpu6050.setXGyroOffset(220); + mpu6050.setYGyroOffset(76); + mpu6050.setZGyroOffset(-85); + mpu6050.setZAccelOffset(1788); + if (MPU6050_dmp.devStatus == 0) { + mpu6050.setDMPEnabled(true); + MPU6050_dmp.packetSize = mpu6050.dmpGetFIFOPacketSize(); + MPU_6050_found = true; + } +#else + mpu6050.initialize(); + MPU_6050_found = mpu6050.testConnection(); +#endif + Settings.flag2.axis_resolution = 2; + + } + + if (MPU_6050_found) + { + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, D_SENSOR_MPU6050, MPU_6050_address); + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_AXIS[] PROGMEM = + "{s}" D_SENSOR_MPU6050 " " D_AX_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_AY_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_AZ_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_GX_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_GY_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_GZ_AXIS "{m}%s{e}"; +#endif + +#define D_JSON_AXIS_AX "AccelXAxis" +#define D_JSON_AXIS_AY "AccelYAxis" +#define D_JSON_AXIS_AZ "AccelZAxis" +#define D_JSON_AXIS_GX "GyroXAxis" +#define D_JSON_AXIS_GY "GyroYAxis" +#define D_JSON_AXIS_GZ "GyroZAxis" + +void MPU_6050Show(bool json) +{ + if (MPU_6050_found) { + MPU_6050PerformReading(); + + double tempConv = (MPU_6050_temperature / 340.0 + 35.53); + char temperature[33]; + dtostrfd(tempConv, Settings.flag2.temperature_resolution, temperature); + char axis_ax[33]; + dtostrfd(MPU_6050_ax, Settings.flag2.axis_resolution, axis_ax); + char axis_ay[33]; + dtostrfd(MPU_6050_ay, Settings.flag2.axis_resolution, axis_ay); + char axis_az[33]; + dtostrfd(MPU_6050_az, Settings.flag2.axis_resolution, axis_az); + char axis_gx[33]; + dtostrfd(MPU_6050_gx, Settings.flag2.axis_resolution, axis_gx); + char axis_gy[33]; + dtostrfd(MPU_6050_gy, Settings.flag2.axis_resolution, axis_gy); + char axis_gz[33]; + dtostrfd(MPU_6050_gz, Settings.flag2.axis_resolution, axis_gz); + + if (json) { + char json_axis_ax[25]; + snprintf_P(json_axis_ax, sizeof(json_axis_ax), PSTR(",\"" D_JSON_AXIS_AX "\":%s"), axis_ax); + char json_axis_ay[25]; + snprintf_P(json_axis_ay, sizeof(json_axis_ay), PSTR(",\"" D_JSON_AXIS_AY "\":%s"), axis_ay); + char json_axis_az[25]; + snprintf_P(json_axis_az, sizeof(json_axis_az), PSTR(",\"" D_JSON_AXIS_AZ "\":%s"), axis_az); + char json_axis_gx[25]; + snprintf_P(json_axis_gx, sizeof(json_axis_gx), PSTR(",\"" D_JSON_AXIS_GX "\":%s"), axis_gx); + char json_axis_gy[25]; + snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy); + char json_axis_gz[25]; + snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), + D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_TEMP, temperature); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, D_SENSOR_MPU6050, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_AXIS, axis_ax, axis_ay, axis_az, axis_gx, axis_gy, axis_gz); +#endif + } + } +} + + + + + +bool Xsns32(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_PREP_BEFORE_TELEPERIOD: + MPU_6050Detect(); + break; + case FUNC_EVERY_SECOND: + if (tele_period == Settings.tele_period -3) { + MPU_6050PerformReading(); + } + break; + case FUNC_JSON_APPEND: + MPU_6050Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MPU_6050Show(0); + MPU_6050PerformReading(); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_33_ds3231.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_33_ds3231.ino" +#ifdef USE_I2C +#ifdef USE_DS3231 +# 35 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_33_ds3231.ino" +#define XSNS_33 33 + + +#ifndef USE_RTC_ADDR +#define USE_RTC_ADDR 0x68 +#endif + + +#define RTC_SECONDS 0x00 +#define RTC_MINUTES 0x01 +#define RTC_HOURS 0x02 +#define RTC_DAY 0x03 +#define RTC_DATE 0x04 +#define RTC_MONTH 0x05 +#define RTC_YEAR 0x06 +#define RTC_CONTROL 0x0E +#define RTC_STATUS 0x0F + +#define OSF 7 +#define EOSC 7 +#define BBSQW 6 +#define CONV 5 +#define RS2 4 +#define RS1 3 +#define INTCN 2 + + +#define HR1224 6 +#define CENTURY 7 +#define DYDT 6 +bool ds3231ReadStatus = false; +bool ds3231WriteStatus = false; +bool DS3231chipDetected = false; + + + + +void DS3231Detect(void) +{ + DS3231chipDetected = false; + if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) { + AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, "DS3231", USE_RTC_ADDR); + DS3231chipDetected = true; + } else { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "DS3231 NOT " D_FOUND_AT " 0x%x"), USE_RTC_ADDR); + } +} + + + + +uint8_t bcd2dec(uint8_t n) +{ + return n - 6 * (n >> 4); +} + + + + +uint8_t dec2bcd(uint8_t n) +{ + return n + 6 * (n / 10); +} + + + + +uint32_t ReadFromDS3231(void) +{ + TIME_T tm; + tm.second = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_SECONDS)); + tm.minute = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MINUTES)); + tm.hour = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_HOURS) & ~_BV(HR1224)); + tm.day_of_week = I2cRead8(USE_RTC_ADDR, RTC_DAY); + tm.day_of_month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_DATE)); + tm.month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MONTH) & ~_BV(CENTURY)); + tm.year = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_YEAR)); + return MakeTime(tm); +} + + + +void SetDS3231Time (uint32_t epoch_time) { + TIME_T tm; + BreakTime(epoch_time, tm); + I2cWrite8(USE_RTC_ADDR, RTC_SECONDS, dec2bcd(tm.second)); + I2cWrite8(USE_RTC_ADDR, RTC_MINUTES, dec2bcd(tm.minute)); + I2cWrite8(USE_RTC_ADDR, RTC_HOURS, dec2bcd(tm.hour)); + I2cWrite8(USE_RTC_ADDR, RTC_DAY, tm.day_of_week); + I2cWrite8(USE_RTC_ADDR, RTC_DATE, dec2bcd(tm.day_of_month)); + I2cWrite8(USE_RTC_ADDR, RTC_MONTH, dec2bcd(tm.month)); + I2cWrite8(USE_RTC_ADDR, RTC_YEAR, dec2bcd(tm.year)); + I2cWrite8(USE_RTC_ADDR, RTC_STATUS, I2cRead8(USE_RTC_ADDR, RTC_STATUS) & ~_BV(OSF)); +} + + + + + +bool Xsns33(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + DS3231Detect(); + break; + case FUNC_EVERY_SECOND: + TIME_T tmpTime; + if (!ds3231ReadStatus && DS3231chipDetected && Rtc.utc_time < START_VALID_TIME ) { + ntp_force_sync = true; + Rtc.utc_time = ReadFromDS3231(); + + + BreakTime(Rtc.utc_time, tmpTime); + if (Rtc.utc_time < START_VALID_TIME ) { + ds3231ReadStatus = true; + } + RtcTime.year = tmpTime.year + 1970; + Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); + Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); + AddLog_P2(LOG_LEVEL_INFO, PSTR("Set time from DS3231 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + if (Rtc.local_time < START_VALID_TIME) { + rules_flag.time_init = 1; + } else { + rules_flag.time_set = 1; + } + } + else if (!ds3231WriteStatus && DS3231chipDetected && Rtc.utc_time > START_VALID_TIME && abs(Rtc.utc_time - ReadFromDS3231()) > 60) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + SetDS3231Time (Rtc.utc_time); + ds3231WriteStatus = true; + } + break; + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_34_hx711.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_34_hx711.ino" +#ifdef USE_HX711 +# 35 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_34_hx711.ino" +#define XSNS_34 34 + +#ifndef HX_MAX_WEIGHT +#define HX_MAX_WEIGHT 20000 +#endif +#ifndef HX_REFERENCE +#define HX_REFERENCE 250 +#endif +#ifndef HX_SCALE +#define HX_SCALE 120 +#endif + +#define HX_TIMEOUT 120 +#define HX_SAMPLES 10 +#define HX_CAL_TIMEOUT 15 + +#define HX_GAIN_128 1 +#define HX_GAIN_32 2 +#define HX_GAIN_64 3 + +#define D_JSON_WEIGHT_REF "WeightRef" +#define D_JSON_WEIGHT_CAL "WeightCal" +#define D_JSON_WEIGHT_MAX "WeightMax" +#define D_JSON_WEIGHT_ITEM "WeightItem" +#define D_JSON_WEIGHT_CHANGE "WeightChange" + +enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, HX_CAL_DONE, HX_CAL_FIRST, HX_CAL_RESET, HX_CAL_START }; + +const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" D_HX_CAL_REFERENCE "|" D_HX_CAL_REMOVE; + +struct HX { + long weight = 0; + long last_weight = 0; + long sum_weight = 0; + long offset = 0; + long scale = 1; + long weight_diff = 0; + uint8_t type = 1; + uint8_t sample_count = 0; + uint8_t calibrate_step = HX_CAL_END; + uint8_t calibrate_timer = 0; + uint8_t calibrate_msg = 0; + uint8_t pin_sck; + uint8_t pin_dout; + bool tare_flg = false; + bool weight_changed = false; +} Hx; + + + +bool HxIsReady(uint16_t timeout) +{ + + uint32_t start = millis(); + while ((digitalRead(Hx.pin_dout) == HIGH) && (millis() - start < timeout)) { yield(); } + return (digitalRead(Hx.pin_dout) == LOW); +} + +long HxRead() +{ + if (!HxIsReady(HX_TIMEOUT)) { return -1; } + + uint8_t data[3] = { 0 }; + uint8_t filler = 0x00; + + + data[2] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); + data[1] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); + data[0] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); + + + for (unsigned int i = 0; i < HX_GAIN_128; i++) { + digitalWrite(Hx.pin_sck, HIGH); + digitalWrite(Hx.pin_sck, LOW); + } + + + if (data[2] & 0x80) { filler = 0xFF; } + + + unsigned long value = ( static_cast(filler) << 24 + | static_cast(data[2]) << 16 + | static_cast(data[1]) << 8 + | static_cast(data[0]) ); + + return static_cast(value); +} + + + +void HxResetPart(void) +{ + Hx.tare_flg = true; + Hx.sum_weight = 0; + Hx.sample_count = 0; + Hx.last_weight = 0; +} + +void HxReset(void) +{ + HxResetPart(); + Settings.energy_frequency_calibration = 0; +} + +void HxCalibrationStateTextJson(uint8_t msg_id) +{ + char cal_text[30]; + + Hx.calibrate_msg = msg_id; + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); + + if (msg_id < 3) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("Sensor34")); } +} +# 168 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_34_hx711.ino" +bool HxCommand(void) +{ + bool serviced = true; + bool show_parms = false; + char sub_string[XdrvMailbox.data_len +1]; + + for (uint32_t ca = 0; ca < XdrvMailbox.data_len; ca++) { + if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; } + } + + switch (XdrvMailbox.payload) { + case 1: + HxReset(); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); + break; + case 2: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + } + Hx.scale = 1; + HxReset(); + Hx.calibrate_step = HX_CAL_START; + Hx.calibrate_timer = 1; + HxCalibrationStateTextJson(3); + break; + case 3: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + } + show_parms = true; + break; + case 4: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_calibration = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + Hx.scale = Settings.weight_calibration; + } + show_parms = true; + break; + case 5: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_max = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) / 1000; + } + show_parms = true; + break; + case 6: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_item = (unsigned long)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10); + } + show_parms = true; + break; + case 7: + Settings.energy_frequency_calibration = Hx.weight; + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, D_JSON_DONE); + break; + case 8: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.SensorBits1.hx711_json_weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) & 1; + } + show_parms = true; + break; + default: + show_parms = true; + } + + if (show_parms) { + char item[33]; + dtostrfd((float)Settings.weight_item / 10, 1, item); + Response_P(PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" D_JSON_WEIGHT_ITEM "\":%s,\"" D_JSON_WEIGHT_CHANGE "\":\"%s\"}}"), + Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, item, GetStateText(Settings.SensorBits1.hx711_json_weight_change)); + } + + return serviced; +} + + + +long HxWeight() +{ + return (Hx.calibrate_step < HX_CAL_FAIL) ? Hx.weight : 0; +} + +void HxInit(void) +{ + Hx.type = 0; + if ((pin[GPIO_HX711_DAT] < 99) && (pin[GPIO_HX711_SCK] < 99)) { + Hx.pin_sck = pin[GPIO_HX711_SCK]; + Hx.pin_dout = pin[GPIO_HX711_DAT]; + + pinMode(Hx.pin_sck, OUTPUT); + pinMode(Hx.pin_dout, INPUT); + + digitalWrite(Hx.pin_sck, LOW); + + if (HxIsReady(8 * HX_TIMEOUT)) { + if (!Settings.weight_max) { Settings.weight_max = HX_MAX_WEIGHT / 1000; } + if (!Settings.weight_calibration) { Settings.weight_calibration = HX_SCALE; } + if (!Settings.weight_reference) { Settings.weight_reference = HX_REFERENCE; } + Hx.scale = Settings.weight_calibration; + HxRead(); + HxResetPart(); + Hx.type = 1; + } + } +} + +void HxEvery100mSecond(void) +{ + Hx.sum_weight += HxRead(); + + Hx.sample_count++; + if (HX_SAMPLES == Hx.sample_count) { + long average = Hx.sum_weight / Hx.sample_count; + long value = average - Hx.offset; + Hx.weight = value / Hx.scale; + if (Hx.weight < 0) { + if (Settings.energy_frequency_calibration) { + long difference = Settings.energy_frequency_calibration + Hx.weight; + Hx.last_weight = difference; + if (difference < 0) { HxReset(); } + } + Hx.weight = 0; + } else { + Hx.last_weight = Settings.energy_frequency_calibration; + } + + if (Hx.tare_flg) { + Hx.tare_flg = false; + Hx.offset = average; + } + + if (Hx.calibrate_step) { + Hx.calibrate_timer--; + + if (HX_CAL_START == Hx.calibrate_step) { + Hx.calibrate_step--; + Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); + } + else if (HX_CAL_RESET == Hx.calibrate_step) { + if (Hx.calibrate_timer) { + if (Hx.weight < (long)Settings.weight_reference) { + Hx.calibrate_step--; + Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); + HxCalibrationStateTextJson(2); + } + } else { + Hx.calibrate_step = HX_CAL_FAIL; + } + } + else if (HX_CAL_FIRST == Hx.calibrate_step) { + if (Hx.calibrate_timer) { + if (Hx.weight > (long)Settings.weight_reference) { + Hx.calibrate_step--; + } + } else { + Hx.calibrate_step = HX_CAL_FAIL; + } + } + else if (HX_CAL_DONE == Hx.calibrate_step) { + if (Hx.weight > (long)Settings.weight_reference) { + Hx.calibrate_step = HX_CAL_FINISH; + Settings.weight_calibration = Hx.weight / Settings.weight_reference; + Hx.weight = 0; + HxCalibrationStateTextJson(1); + } else { + Hx.calibrate_step = HX_CAL_FAIL; + } + } + + if (HX_CAL_FAIL == Hx.calibrate_step) { + Hx.calibrate_step--; + Hx.tare_flg = true; + HxCalibrationStateTextJson(0); + } + if (HX_CAL_FINISH == Hx.calibrate_step) { + Hx.calibrate_step--; + Hx.calibrate_timer = 3 * (10 / HX_SAMPLES); + Hx.scale = Settings.weight_calibration; + } + + if (!Hx.calibrate_timer) { + Hx.calibrate_step = HX_CAL_END; + } + } else { + Hx.weight += Hx.last_weight; + + if (Settings.SensorBits1.hx711_json_weight_change) { + if (abs(Hx.weight - Hx.weight_diff) > 4) { + Hx.weight_diff = Hx.weight; + Hx.weight_changed = true; + } + else if (Hx.weight_changed && (Hx.weight == Hx.weight_diff)) { + mqtt_data[0] = '\0'; + ResponseAppendTime(); + HxShow(true); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + Hx.weight_changed = false; + } + } + } + + Hx.sum_weight = 0; + Hx.sample_count = 0; + } +} + +void HxSaveBeforeRestart() +{ + Settings.energy_frequency_calibration = Hx.weight; + Hx.sample_count = HX_SAMPLES +1; +} + +#ifdef USE_WEBSERVER +const char HTTP_HX711_WEIGHT[] PROGMEM = + "{s}HX711 " D_WEIGHT "{m}%s " D_UNIT_KILOGRAM "{e}"; +const char HTTP_HX711_COUNT[] PROGMEM = + "{s}HX711 " D_COUNT "{m}%d{e}"; +const char HTTP_HX711_CAL[] PROGMEM = + "{s}HX711 %s{m}{e}"; +#endif + +void HxShow(bool json) +{ + char scount[30] = { 0 }; + + uint16_t count = 0; + float weight = 0; + if (Hx.calibrate_step < HX_CAL_FAIL) { + if (Hx.weight && Settings.weight_item) { + count = (Hx.weight * 10) / Settings.weight_item; + if (count > 1) { + snprintf_P(scount, sizeof(scount), PSTR(",\"" D_JSON_COUNT "\":%d"), count); + } + } + weight = (float)Hx.weight / 1000; + } + char weight_chr[33]; + dtostrfd(weight, Settings.flag2.weight_resolution, weight_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s}"), weight_chr, scount); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr); + if (count > 1) { + WSContentSend_PD(HTTP_HX711_COUNT, count); + } + if (Hx.calibrate_step) { + char cal_text[30]; + WSContentSend_PD(HTTP_HX711_CAL, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); + } +#endif + } +} + +#ifdef USE_WEBSERVER +#ifdef USE_HX711_GUI + + + + +#define WEB_HANDLE_HX711 "s34" + +const char S_CONFIGURE_HX711[] PROGMEM = D_CONFIGURE_HX711; + +const char HTTP_BTN_MENU_MAIN_HX711[] PROGMEM = + "

"; + +const char HTTP_BTN_MENU_HX711[] PROGMEM = + "

"; + +const char HTTP_FORM_HX711[] PROGMEM = + "
 " D_CALIBRATION " " + "
" + "

" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" + "
" + "
" + "


" + + "
 " D_HX711_PARAMETERS " " + "
" + "

" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; + +void HandleHxAction(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_HX711); + + if (WebServer->hasArg("save")) { + HxSaveSettings(); + HandleConfiguration(); + return; + } + + char stemp1[20]; + + if (WebServer->hasArg("reset")) { + snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 1")); + ExecuteWebCommand(stemp1, SRC_WEBGUI); + + HandleRoot(); + return; + } + + if (WebServer->hasArg("calibrate")) { + WebGetArg("p1", stemp1, sizeof(stemp1)); + Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000); + + HxLogUpdates(); + + snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 2")); + ExecuteWebCommand(stemp1, SRC_WEBGUI); + + HandleRoot(); + return; + } + + WSContentStart_P(S_CONFIGURE_HX711); + WSContentSendStyle(); + dtostrfd((float)Settings.weight_reference / 1000, 3, stemp1); + char stemp2[20]; + dtostrfd((float)Settings.weight_item / 10000, 4, stemp2); + WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void HxSaveSettings(void) +{ + char tmp[100]; + + WebGetArg("p2", tmp, sizeof(tmp)); + Settings.weight_item = (!strlen(tmp)) ? 0 : (unsigned long)(CharToFloat(tmp) * 10000); + + HxLogUpdates(); +} + +void HxLogUpdates(void) +{ + char weigth_ref_chr[33]; + dtostrfd((float)Settings.weight_reference / 1000, Settings.flag2.weight_resolution, weigth_ref_chr); + char weigth_item_chr[33]; + dtostrfd((float)Settings.weight_item / 10000, 4, weigth_item_chr); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_JSON_WEIGHT_REF " %s, " D_JSON_WEIGHT_ITEM " %s"), weigth_ref_chr, weigth_item_chr); +} + +#endif +#endif + + + + + +bool Xsns34(uint8_t function) +{ + bool result = false; + + if (Hx.type) { + switch (function) { + case FUNC_EVERY_100_MSECOND: + HxEvery100mSecond(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_34 == XdrvMailbox.index) { + result = HxCommand(); + } + break; + case FUNC_JSON_APPEND: + HxShow(1); + break; + case FUNC_SAVE_BEFORE_RESTART: + HxSaveBeforeRestart(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HxShow(0); + break; +#ifdef USE_HX711_GUI + case FUNC_WEB_ADD_MAIN_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_MAIN_HX711); + break; + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_HX711); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); + break; +#endif +#endif + case FUNC_INIT: + HxInit(); + break; + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_35_tx20.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_35_tx20.ino" +#ifdef USE_TX20_WIND_SENSOR +# 29 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_35_tx20.ino" +#define XSNS_35 35 + +#define TX20_BIT_TIME 1220 +#define TX20_RESET_VALUES 60 + + + +extern "C" { +#include "gpio.h" +} + +#ifdef USE_WEBSERVER + +const char HTTP_SNS_TX20[] PROGMEM = + "{s}TX20 " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}TX20 " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}TX20 " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}TX20 " D_TX20_WIND_DIRECTION "{m}%s{e}"; + +#endif + +const char kTx20Directions[] PROGMEM = D_TX20_NORTH "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" + D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST "|" + D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST "|" + D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; + +uint8_t tx20_sa = 0; +uint8_t tx20_sb = 0; +uint8_t tx20_sd = 0; +uint8_t tx20_se = 0; +uint16_t tx20_sc = 0; +uint16_t tx20_sf = 0; + +float tx20_wind_speed_kmh = 0; +float tx20_wind_speed_max = 0; +float tx20_wind_speed_avg = 0; +float tx20_wind_sum = 0; +int tx20_count = 0; +uint8_t tx20_wind_direction = 0; + +bool tx20_available = false; + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 +void Tx20StartRead(void) ICACHE_RAM_ATTR; +#endif + +void Tx20StartRead(void) +{ +# 101 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_35_tx20.ino" + tx20_available = false; + + tx20_sa = 0; + tx20_sb = 0; + tx20_sd = 0; + tx20_se = 0; + tx20_sc = 0; + tx20_sf = 0; + + delayMicroseconds(TX20_BIT_TIME / 2); + + for (int32_t bitcount = 41; bitcount > 0; bitcount--) { + uint8_t dpin = (digitalRead(pin[GPIO_TX20_TXD_BLACK])); + if (bitcount > 41 - 5) { + + tx20_sa = (tx20_sa << 1) | (dpin ^ 1); + } else if (bitcount > 41 - 5 - 4) { + + tx20_sb = tx20_sb >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12) { + + tx20_sc = tx20_sc >> 1 | ((dpin ^ 1) << 11); + } else if (bitcount > 41 - 5 - 4 - 12 - 4) { + + tx20_sd = tx20_sd >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { + + tx20_se = tx20_se >> 1 | (dpin << 3); + } else { + + tx20_sf = tx20_sf >> 1 | (dpin << 11); + } + + delayMicroseconds(TX20_BIT_TIME); + } + + uint8_t chk = (tx20_sb + (tx20_sc & 0xf) + ((tx20_sc >> 4) & 0xf) + ((tx20_sc >> 8) & 0xf)); + chk &= 0xf; + + if ((chk == tx20_sd) && (tx20_sc < 400)) { + tx20_available = true; + } + + + + + + + + GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX20_TXD_BLACK]); +} + +void Tx20Read(void) +{ + if (!(uptime % TX20_RESET_VALUES)) { + tx20_count = 0; + tx20_wind_sum = 0; + tx20_wind_speed_max = 0; + } + else if (tx20_available) { + tx20_wind_speed_kmh = float(tx20_sc) * 0.36; + if (tx20_wind_speed_kmh > tx20_wind_speed_max) { + tx20_wind_speed_max = tx20_wind_speed_kmh; + } + tx20_count++; + tx20_wind_sum += tx20_wind_speed_kmh; + tx20_wind_speed_avg = tx20_wind_sum / tx20_count; + tx20_wind_direction = tx20_sb; + } +} + +void Tx20Init(void) { + pinMode(pin[GPIO_TX20_TXD_BLACK], INPUT); + attachInterrupt(pin[GPIO_TX20_TXD_BLACK], Tx20StartRead, RISING); +} + +void Tx20Show(bool json) +{ + char wind_speed_string[33]; + dtostrfd(tx20_wind_speed_kmh, 2, wind_speed_string); + char wind_speed_max_string[33]; + dtostrfd(tx20_wind_speed_max, 2, wind_speed_max_string); + char wind_speed_avg_string[33]; + dtostrfd(tx20_wind_speed_avg, 2, wind_speed_avg_string); + char wind_direction_string[4]; + GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx20_wind_direction, kTx20Directions); + + if (json) { + ResponseAppend_P(PSTR(",\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"), + wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TX20, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); +#endif + } +} + + + + + +bool Xsns35(uint8_t function) +{ + bool result = false; + + if (pin[GPIO_TX20_TXD_BLACK] < 99) { + switch (function) { + case FUNC_INIT: + Tx20Init(); + break; + case FUNC_EVERY_SECOND: + Tx20Read(); + break; + case FUNC_JSON_APPEND: + Tx20Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Tx20Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_36_mgc3130.ino" +# 22 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_36_mgc3130.ino" +#ifdef USE_I2C +#ifdef USE_MGC3130 +# 35 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_36_mgc3130.ino" +#define XSNS_36 36 + +#warning **** MGC3130: It is recommended to disable all unneeded I2C-drivers **** + +#define MGC3130_I2C_ADDR 0x42 + +#define MGC3130_xfer pin[GPIO_MGC3130_XFER] +#define MGC3130_reset pin[GPIO_MGC3130_RESET] + + +bool MGC3130_type = false; +char MGC3130stype[8]; + + +#define MGC3130_SYSTEM_STATUS 0x15 +#define MGC3130_REQUEST_MSG 0x06 +#define MGC3130_FW_VERSION 0x83 +#define MGC3130_SET_RUNTIME 0xA2 +#define MGC3130_SENSOR_DATA 0x91 + + +#define MGC3130_GESTURE_GARBAGE 1 +#define MGC3130_FLICK_WEST_EAST 2 +#define MGC3130_FLICK_EAST_WEST 3 +#define MGC3130_FLICK_SOUTH_NORTH 4 +#define MGC3130_FLICK_NORTH_SOUTH 5 +#define MGC3130_CIRCLE_CLOCKWISE 6 +#define MGC3130_CIRCLE_CCLOCKWISE 7 + +#define MGC3130_MIN_ROTVALUE 0 +#define MGC3130_MAX_ROTVALUE 1023 +#define MGC3130_MIN_ZVALUE 32768 + + +#ifdef USE_WEBSERVER +const char HTTP_MGC_3130_SNS[] PROGMEM = + "{s}" "%s" "{m}%s{e}" + "{s}" "HwRev" "{m}%u.%u{e}" + "{s}" "loaderVer" "{m}%u.%u{e}" + "{s}" "platVer" "{m}%u{e}"; +#endif + + + + + + + +#pragma pack(1) +union MGC3130_Union{ + uint8_t buffer[132]; + struct + { + + uint8_t msgSize; + uint8_t flag; + uint8_t counter; + uint8_t id; + + struct { + uint8_t DSPStatus:1; + uint8_t gestureInfo:1; + uint8_t touchInfo:1; + uint8_t airWheelInfo:1; + uint8_t xyzPosition:1; + uint8_t noisePower:1; + uint8_t reserved:2; + uint8_t electrodeConfiguration:3; + uint8_t CICData:1; + uint8_t SDData:1; + uint16_t reserved2:3; + } outputConfigMask; + uint8_t timestamp; + struct { + uint8_t positionValid:1; + uint8_t airWheelValid:1; + uint8_t rawDataValid:1; + uint8_t noisePowerValid:1; + uint8_t environmentalNoise:1; + uint8_t clipping:1; + uint8_t reserved:1; + uint8_t DSPRunning:1; + } systemInfo; + uint16_t dspInfo; + struct { + uint8_t gestureCode:8; + uint8_t reserved:4; + uint8_t gestureType:4; + uint8_t edgeFlick:1; + uint16_t reserved2:14; + uint8_t gestureInProgress:1; + } gestureInfo; + struct { + uint8_t touchSouth:1; + uint8_t touchWest:1; + uint8_t touchNorth:1; + uint8_t touchEast:1; + uint8_t touchCentre:1; + uint8_t tapSouth:1; + uint8_t tapWest:1; + uint8_t tapNorth:1; + uint8_t tapEast :1; + uint8_t tapCentre:1; + uint8_t doubleTapSouth:1; + uint8_t doubleTapWest:1; + uint8_t doubleTapNorth:1; + uint8_t doubleTapEast:1; + uint8_t doubleTapCentre:1; + uint8_t reserved:1; + uint8_t touchCounter; + uint8_t reserved2; + } touchInfo; + int8_t airWheel; + uint8_t reserved; + uint16_t x; + uint16_t y; + uint16_t z; + float noisePower; + float CICData[4]; + float SDData[4]; + } out; + struct { + uint8_t header[3]; + + uint8_t valid; + uint8_t hwRev[2]; + uint8_t parameterStartAddr; + uint8_t loaderVersion[2]; + uint8_t loaderPlatform; + uint8_t fwStartAddr; + char fwVersion[120]; + } fw; + struct{ + uint8_t id; + uint8_t size; + uint16_t error; + uint32_t reserved; + uint32_t reserved1; + } status; +} MGC_data; +#pragma pack() + +char MGC3130_currentGesture[12]; + +int8_t MGC3130_delta, MGC3130_lastrotation = 0; +int16_t MGC3130_rotValue, MGC3130_lastSentRotValue = 0; + +uint16_t MGC3130_lastSentX, MGC3130_lastSentY, MGC3130_lastSentZ = 0; + +uint8_t hwRev[2], loaderVersion[2], loaderPlatform = 0; +char MGC3130_firmwareInfo[20]; + +uint8_t MGC3130_touchTimeout = 0; +uint16_t MGC3130_touchCounter = 1; +uint32_t MGC3130_touchTimeStamp = millis(); +bool MGC3130_triggeredByTouch = false; + +uint8_t MGC3130_mode = 1; + + + +uint8_t MGC3130autoCal[] = {0x10, 0x00, 0x00, 0xA2, 0x80, 0x00 , 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; +uint8_t MGC3130disableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; +uint8_t MGC3130enableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; + +void MGC3130_triggerTele(){ + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + #ifdef USE_RULES + RulesTeleperiod(); + #endif + } +} + +void MGC3130_handleSensorData(){ + if ( MGC_data.out.outputConfigMask.touchInfo && MGC3130_touchTimeout == 0){ + if (MGC3130_handleTouch()){ + MGC3130_triggeredByTouch = true; + MGC3130_triggerTele(); + } + } + + if(MGC3130_mode == 1){ + if( MGC_data.out.outputConfigMask.gestureInfo && MGC_data.out.gestureInfo.gestureCode > 0){ + MGC3130_handleGesture(); + MGC3130_triggerTele(); + } + } + if(MGC3130_mode == 2){ + if(MGC_data.out.outputConfigMask.airWheelInfo && MGC_data.out.systemInfo.airWheelValid){ + MGC3130_handleAirWheel(); + MGC3130_triggerTele(); + } + } + if(MGC3130_mode == 3){ + if(MGC_data.out.systemInfo.positionValid && (MGC_data.out.z > MGC3130_MIN_ZVALUE)){ + MGC3130_triggerTele(); + } + } +} + +void MGC3130_sendMessage(uint8_t data[], uint8_t length){ + Wire.beginTransmission(MGC3130_I2C_ADDR); + Wire.write(data,length); + Wire.endTransmission(); + delay(2); + MGC3130_receiveMessage(); +} + + +void MGC3130_handleGesture(){ + + char edge[5]; + if (MGC_data.out.gestureInfo.edgeFlick){ + snprintf_P(edge, sizeof(edge), PSTR("ED_")); + } + else{ + snprintf_P(edge, sizeof(edge), PSTR("")); + } + switch(MGC_data.out.gestureInfo.gestureCode){ + case MGC3130_GESTURE_GARBAGE: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("NONE")); + break; + case MGC3130_FLICK_WEST_EAST: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_WE"), edge); + break; + case MGC3130_FLICK_EAST_WEST: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_EW"), edge); + break; + case MGC3130_FLICK_SOUTH_NORTH: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_SN"), edge); + break; + case MGC3130_FLICK_NORTH_SOUTH: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_NS"), edge); + break; + case MGC3130_CIRCLE_CLOCKWISE: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CW")); + break; + case MGC3130_CIRCLE_CCLOCKWISE: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CCW")); + break; + } + +} + +bool MGC3130_handleTouch(){ + + bool success = false; + if (MGC_data.out.touchInfo.doubleTapCentre && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_C")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapEast && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_E")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapNorth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_N")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapWest && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_W")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapSouth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_S")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + if (MGC_data.out.touchInfo.tapCentre && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_C")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapEast && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_E")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapNorth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_N")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapWest && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_W")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapSouth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_S")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.touchCentre && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_C")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchEast && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_E")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchNorth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_N")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchWest && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_W")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchSouth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_S")); + success = true; + MGC3130_touchCounter++; + } + + return success; +} + +void MGC3130_handleAirWheel(){ + MGC3130_delta = MGC_data.out.airWheel - MGC3130_lastrotation; + MGC3130_lastrotation = MGC_data.out.airWheel; + + MGC3130_rotValue = MGC3130_rotValue + MGC3130_delta; + if(MGC3130_rotValue < MGC3130_MIN_ROTVALUE){ + MGC3130_rotValue = MGC3130_MIN_ROTVALUE; + } + if(MGC3130_rotValue > MGC3130_MAX_ROTVALUE){ + MGC3130_rotValue = MGC3130_MAX_ROTVALUE; + } +} + +void MGC3130_handleSystemStatus(){ + +} + +bool MGC3130_receiveMessage(){ + if(MGC3130_readData()){ + switch(MGC_data.out.id){ + case MGC3130_SENSOR_DATA: + MGC3130_handleSensorData(); + break; + case MGC3130_SYSTEM_STATUS: + MGC3130_handleSystemStatus(); + break; + case MGC3130_FW_VERSION: + hwRev[0] = MGC_data.fw.hwRev[1]; + hwRev[1] = MGC_data.fw.hwRev[0]; + loaderVersion[0] = MGC_data.fw.loaderVersion[0]; + loaderVersion[1] = MGC_data.fw.loaderVersion[1]; + loaderPlatform = MGC_data.fw.loaderPlatform; + snprintf_P(MGC3130_firmwareInfo, sizeof(MGC3130_firmwareInfo), PSTR("FW: %s"), MGC_data.fw.fwVersion); + MGC3130_firmwareInfo[20] = '\0'; + + break; + } + return true; + } + return false; +} + +bool MGC3130_readData() +{ + bool success = false; + if (!digitalRead(MGC3130_xfer)){ + pinMode(MGC3130_xfer, OUTPUT); + digitalWrite(MGC3130_xfer, LOW); + Wire.requestFrom(MGC3130_I2C_ADDR, (uint16_t)32); + + MGC_data.buffer[0] = 4; + unsigned char i = 0; + while(Wire.available() && (i < MGC_data.buffer[0])){ + MGC_data.buffer[i] = Wire.read(); + i++; + } + digitalWrite(MGC3130_xfer, HIGH); + pinMode(MGC3130_xfer, INPUT); + success = true; + } + return success; +} + +void MGC3130_nextMode(){ + if (MGC3130_mode < 3){ + MGC3130_mode++; + } + else{ + MGC3130_mode = 1; + } + switch(MGC3130_mode){ + case 1: + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + case 2: + MGC3130_sendMessage(MGC3130enableAirwheel,16); + break; + case 3: + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + } +} + +void MGC3130_loop() +{ + if(MGC3130_touchTimeout > 0){ + MGC3130_touchTimeout--; + } + MGC3130_receiveMessage(); +} + + +bool MGC3130_detect(void) +{ + if (MGC3130_type){ + return true; + } + + pinMode(MGC3130_xfer, INPUT_PULLUP); + pinMode(MGC3130_reset, OUTPUT); + digitalWrite(MGC3130_reset, LOW); + delay(10); + digitalWrite(MGC3130_reset, HIGH); + delay(50); + + bool success = false; + success = MGC3130_receiveMessage(); + if (success) { + strcpy_P(MGC3130stype, PSTR("MGC3130")); + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, MGC3130stype, MGC3130_I2C_ADDR); + MGC3130_currentGesture[0] = '\0'; + MGC3130_type = true; + } else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MGC3130 did not respond at address 0x%x"), MGC3130_I2C_ADDR); + } + return success; +} + + + + + +void MGC3130_show(bool json) +{ + if (!MGC3130_type) { return; } + + char status_chr[2]; + if (MGC_data.out.systemInfo.DSPRunning) { + sprintf (status_chr, "1"); + } + else{ + sprintf (status_chr, "0"); + } + + if (json) { + if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch) { + if (MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)) { + ResponseAppend_P(PSTR(",\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), + MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); + MGC3130_lastSentX = MGC_data.out.x; + MGC3130_lastSentY = MGC_data.out.y; + MGC3130_lastSentZ = MGC_data.out.z; + } + } + MGC3130_triggeredByTouch = false; + + if (MGC3130_mode == 2) { + if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)) { + ResponseAppend_P(PSTR(",\"%s\":{\"AW\":%i}"), MGC3130stype, MGC3130_rotValue); + MGC3130_lastSentRotValue = MGC3130_rotValue; + } + } + + if (MGC3130_currentGesture[0] != '\0') { + if (millis() - MGC3130_touchTimeStamp > 220 ) { + MGC3130_touchCounter = 1; + } + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); + MGC3130_currentGesture[0] = '\0'; + MGC3130_touchTimeStamp = millis(); + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_MGC_3130_SNS, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform ); +#endif + } +} +# 575 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_36_mgc3130.ino" +bool MGC3130CommandSensor() +{ + bool serviced = true; + + switch (XdrvMailbox.payload) { + case 0: + MGC3130_nextMode(); + break; + case 1: + MGC3130_mode = 1; + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + case 2: + MGC3130_mode = 2; + MGC3130_sendMessage(MGC3130enableAirwheel,16); + break; + case 3: + MGC3130_mode = 3; + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + } + return serviced; +} + + + + + +bool Xsns36(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + if ((FUNC_INIT == function) && (pin[GPIO_MGC3130_XFER] < 99) && (pin[GPIO_MGC3130_RESET] < 99)) { + MGC3130_detect(); + } + else if (MGC3130_type) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + MGC3130_loop(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_36 == XdrvMailbox.index) { + result = MGC3130CommandSensor(); + } + break; + case FUNC_JSON_APPEND: + MGC3130_show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MGC3130_show(0); + break; +#endif + } + } + } + return result; +} +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_37_rfsensor.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_37_rfsensor.ino" +#ifdef USE_RF_SENSOR +# 33 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_37_rfsensor.ino" +#define XSNS_37 37 + + + + +#define RFSNS_VALID_WINDOW 1800 + +#define RFSNS_LOOPS_PER_MILLI 1900 +#define RFSNS_RAW_BUFFER_SIZE 180 +#define RFSNS_MIN_RAW_PULSES 112 + +#define RFSNS_MIN_PULSE_LENGTH 300 +#define RFSNS_RAWSIGNAL_SAMPLE 50 +#define RFSNS_SIGNAL_TIMEOUT 10 +#define RFSNS_SIGNAL_REPEAT_TIME 500 + +typedef struct RawSignalStruct +{ + int Number; + uint8_t Repeats; + uint8_t Multiply; + unsigned long Time; + uint8_t Pulses[RFSNS_RAW_BUFFER_SIZE+2]; + +} raw_signal_t; + +raw_signal_t *rfsns_raw_signal = nullptr; +uint8_t rfsns_rf_bit; +uint8_t rfsns_rf_port; +uint8_t rfsns_any_sensor = 0; + + + + + +bool RfSnsFetchSignal(uint8_t DataPin, bool StateSignal) +{ + uint8_t Fbit = digitalPinToBitMask(DataPin); + uint8_t Fport = digitalPinToPort(DataPin); + uint8_t FstateMask = (StateSignal ? Fbit : 0); + + if ((*portInputRegister(Fport) & Fbit) == FstateMask) { + const unsigned long LoopsPerMilli = RFSNS_LOOPS_PER_MILLI; + + + + + + + unsigned long PulseLength = 0; + if (rfsns_raw_signal->Time) { + if (rfsns_raw_signal->Repeats && (rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) { + PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; + while (((rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && (PulseLength > micros())) { + if ((*portInputRegister(Fport) & Fbit) == FstateMask) { + PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; + } + } + while (((rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && ((*portInputRegister(Fport) & Fbit) != FstateMask)); + } + } + + int RawCodeLength = 1; + bool Ftoggle = false; + unsigned long numloops = 0; + unsigned long maxloops = RFSNS_SIGNAL_TIMEOUT * LoopsPerMilli; + rfsns_raw_signal->Multiply = RFSNS_RAWSIGNAL_SAMPLE; + do { + numloops = 0; + while(((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) { + if (numloops++ == maxloops) { break; } + } + PulseLength = (numloops *1000) / LoopsPerMilli; + if (PulseLength < RFSNS_MIN_PULSE_LENGTH) { break; } + Ftoggle = !Ftoggle; + rfsns_raw_signal->Pulses[RawCodeLength++] = PulseLength / (unsigned long)rfsns_raw_signal->Multiply; + } + while(RawCodeLength < RFSNS_RAW_BUFFER_SIZE && numloops <= maxloops); + + if ((RawCodeLength >= RFSNS_MIN_RAW_PULSES) && (RawCodeLength < RFSNS_RAW_BUFFER_SIZE -1)) { + rfsns_raw_signal->Repeats = 0; + rfsns_raw_signal->Number = RawCodeLength -1; + rfsns_raw_signal->Pulses[rfsns_raw_signal->Number] = 0; + rfsns_raw_signal->Time = millis(); + return true; + } + else + rfsns_raw_signal->Number = 0; + } + + return false; +} + +#ifdef USE_THEO_V2 +# 149 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_37_rfsensor.ino" +#define RFSNS_THEOV2_MAX_CHANNEL 2 + +#define RFSNS_THEOV2_PULSECOUNT 114 +#define RFSNS_THEOV2_RF_PULSE_MID 1000 + +typedef struct { + uint32_t time; + int16_t temp; + uint16_t lux; + uint8_t volt; +} theo_v2_t1_t; + +typedef struct { + uint32_t time; + int16_t temp; + uint16_t hum; + uint8_t volt; +} theo_v2_t2_t; + +theo_v2_t1_t *rfsns_theo_v2_t1 = nullptr; +theo_v2_t2_t *rfsns_theo_v2_t2 = nullptr; + +void RfSnsInitTheoV2(void) +{ + rfsns_theo_v2_t1 = (theo_v2_t1_t*)malloc(RFSNS_THEOV2_MAX_CHANNEL * sizeof(theo_v2_t1_t)); + rfsns_theo_v2_t2 = (theo_v2_t2_t*)malloc(RFSNS_THEOV2_MAX_CHANNEL * sizeof(theo_v2_t2_t)); + rfsns_any_sensor++; +} + +void RfSnsAnalyzeTheov2(void) +{ + if (rfsns_raw_signal->Number != RFSNS_THEOV2_PULSECOUNT) { return; } + + uint8_t Checksum; + uint8_t Channel; + uint8_t Type; + uint8_t Voltage; + int Payload1; + int Payload2; + + uint8_t b, bytes, bits, id; + + uint8_t idx = 3; + uint8_t chksum = 0; + for (bytes = 0; bytes < 7; bytes++) { + b = 0; + for (bits = 0; bits <= 7; bits++) + { + if ((rfsns_raw_signal->Pulses[idx] * rfsns_raw_signal->Multiply) > RFSNS_THEOV2_RF_PULSE_MID) { + b |= 1 << bits; + } + idx += 2; + } + if (bytes > 0) { chksum += b; } + + switch (bytes) { + case 0: + Checksum = b; + break; + case 1: + id = b; + Channel = b & 0x7; + Type = (b >> 3) & 0x1f; + break; + case 2: + Voltage = b; + break; + case 3: + Payload1 = b; + break; + case 4: + Payload1 = (b << 8) | Payload1; + break; + case 5: + Payload2 = b; + break; + case 6: + Payload2 = (b << 8) | Payload2; + break; + } + } + + if (Checksum != chksum) { return; } + if ((Channel == 0) || (Channel > RFSNS_THEOV2_MAX_CHANNEL)) { return; } + Channel--; + + rfsns_raw_signal->Repeats = 1; + + int Payload3 = Voltage & 0x3f; + + switch (Type) { + case 1: + rfsns_theo_v2_t1[Channel].time = LocalTime(); + rfsns_theo_v2_t1[Channel].volt = Payload3; + rfsns_theo_v2_t1[Channel].temp = Payload1; + rfsns_theo_v2_t1[Channel].lux = Payload2; + break; + case 2: + rfsns_theo_v2_t2[Channel].time = LocalTime(); + rfsns_theo_v2_t2[Channel].volt = Payload3; + rfsns_theo_v2_t2[Channel].temp = Payload1; + rfsns_theo_v2_t2[Channel].hum = Payload2; + break; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: TheoV2, ChkCalc %d, Chksum %d, id %d, Type %d, Ch %d, Volt %d, BattLo %d, Pld1 %d, Pld2 %d"), + chksum, Checksum, id, Type, Channel +1, Payload3, (Voltage & 0x80) >> 7, Payload1, Payload2); +} + +void RfSnsTheoV2Show(bool json) +{ + bool sensor_once = false; + + for (uint32_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { + if (rfsns_theo_v2_t1[i].time) { + char sensor[10]; + snprintf_P(sensor, sizeof(sensor), PSTR("TV2T1C%d"), i +1); + char voltage[33]; + dtostrfd((float)rfsns_theo_v2_t1[i].volt / 10, 1, voltage); + + if (rfsns_theo_v2_t1[i].time < LocalTime() - RFSNS_VALID_WINDOW) { + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), + sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage); + } + } else { + char temperature[33]; + dtostrfd(ConvertTemp((float)rfsns_theo_v2_t1[i].temp / 100), Settings.flag2.temperature_resolution, temperature); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"), + sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && !sensor_once) { + DomoticzSensor(DZ_TEMP, temperature); + DomoticzSensor(DZ_ILLUMINANCE, rfsns_theo_v2_t1[i].lux); + sensor_once = true; + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, sensor, rfsns_theo_v2_t1[i].lux); +#endif + } + } + } + } + + sensor_once = false; + for (uint32_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { + if (rfsns_theo_v2_t2[i].time) { + char sensor[10]; + snprintf_P(sensor, sizeof(sensor), PSTR("TV2T2C%d"), i +1); + char voltage[33]; + dtostrfd((float)rfsns_theo_v2_t2[i].volt / 10, 1, voltage); + + if (rfsns_theo_v2_t2[i].time < LocalTime() - RFSNS_VALID_WINDOW) { + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED" \":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), + sensor, GetDT(rfsns_theo_v2_t2[i].time).c_str(), voltage); + } + } else { + float temp = ConvertTemp((float)rfsns_theo_v2_t2[i].temp / 100); + float humi = ConvertHumidity((float)rfsns_theo_v2_t2[i].hum / 100); + char temperature[33]; + dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_VOLTAGE "\":%s}"), + sensor, temperature, humidity, voltage); + if ((0 == tele_period) && !sensor_once) { +#ifdef USE_DOMOTICZ + DomoticzTempHumSensor(temperature, humidity); +#endif +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, temp); + KnxSensor(KNX_HUMIDITY, humi); +#endif + sensor_once = true; + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, sensor, humidity); +#endif + } + } + } + } +} + +#endif + +#ifdef USE_ALECTO_V2 +# 392 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_37_rfsensor.ino" +#define RFSNS_DKW2012_PULSECOUNT 176 +#define RFSNS_ACH2010_MIN_PULSECOUNT 160 +#define RFSNS_ACH2010_MAX_PULSECOUNT 160 + +#define D_ALECTOV2 "AlectoV2" + +const char kAlectoV2Directions[] PROGMEM = D_TX20_NORTH "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" + D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST "|" + D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST "|" + D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; + +typedef struct { + uint32_t time; + float temp; + float rain; + float wind; + float gust; + uint8_t type; + uint8_t humi; + uint8_t wdir; +} alecto_v2_t; + +alecto_v2_t *rfsns_alecto_v2 = nullptr; +uint16_t rfsns_alecto_rain_base = 0; + +void RfSnsInitAlectoV2(void) +{ + rfsns_alecto_v2 = (alecto_v2_t*)malloc(sizeof(alecto_v2_t)); + rfsns_any_sensor++; +} + +void RfSnsAnalyzeAlectov2() +{ + if (!(((rfsns_raw_signal->Number >= RFSNS_ACH2010_MIN_PULSECOUNT) && + (rfsns_raw_signal->Number <= RFSNS_ACH2010_MAX_PULSECOUNT)) || (rfsns_raw_signal->Number == RFSNS_DKW2012_PULSECOUNT))) { return; } + + uint8_t c = 0; + uint8_t rfbit; + uint8_t data[9] = { 0 }; + uint8_t msgtype = 0; + uint8_t rc = 0; + int temp; + uint8_t checksum = 0; + uint8_t checksumcalc = 0; + uint8_t maxidx = 8; + unsigned long atime; + float factor; + char buf1[16]; + + if (rfsns_raw_signal->Number > RFSNS_ACH2010_MAX_PULSECOUNT) { maxidx = 9; } + + uint8_t idx = maxidx; + for (uint32_t x = rfsns_raw_signal->Number; x > 0; x = x-2) { + if (rfsns_raw_signal->Pulses[x-1] * rfsns_raw_signal->Multiply < 0x300) { + rfbit = 0x80; + } else { + rfbit = 0; + } + data[idx] = (data[idx] >> 1) | rfbit; + c++; + if (c == 8) { + if (idx == 0) { break; } + c = 0; + idx--; + } + } + + checksum = data[maxidx]; + checksumcalc = RfSnsAlectoCRC8(data, maxidx); + + msgtype = (data[0] >> 4) & 0xf; + rc = (data[0] << 4) | (data[1] >> 4); + + if (checksum != checksumcalc) { return; } + if ((msgtype != 10) && (msgtype != 5)) { return; } + + rfsns_raw_signal->Repeats = 1; + + + + + + factor = 1.22; + + + + + + rfsns_alecto_v2->time = LocalTime(); + rfsns_alecto_v2->type = (RFSNS_DKW2012_PULSECOUNT == rfsns_raw_signal->Number); + rfsns_alecto_v2->temp = (float)(((data[1] & 0x3) * 256 + data[2]) - 400) / 10; + rfsns_alecto_v2->humi = data[3]; + uint16_t rain = (data[6] * 256) + data[7]; + + if (rain < rfsns_alecto_rain_base) { rfsns_alecto_rain_base = rain; } + if (rfsns_alecto_rain_base > 0) { + rfsns_alecto_v2->rain += ((float)rain - rfsns_alecto_rain_base) * 0.30; + } + rfsns_alecto_rain_base = rain; + rfsns_alecto_v2->wind = (float)data[4] * factor; + rfsns_alecto_v2->gust = (float)data[5] * factor; + if (rfsns_alecto_v2->type) { + rfsns_alecto_v2->wdir = data[8] & 0xf; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: " D_ALECTOV2 ", ChkCalc %d, Chksum %d, rc %d, Temp %d, Hum %d, Rain %d, Wind %d, Gust %d, Dir %d, Factor %s"), + checksumcalc, checksum, rc, ((data[1] & 0x3) * 256 + data[2]) - 400, data[3], (data[6] * 256) + data[7], data[4], data[5], data[8] & 0xf, dtostrfd(factor, 3, buf1)); +} + +void RfSnsAlectoResetRain(void) +{ + if ((RtcTime.hour == 0) && (RtcTime.minute == 0) && (RtcTime.second == 5)) { + rfsns_alecto_v2->rain = 0; + } +} + + + + + + + +uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len) +{ + uint8_t crc = 0; + while (len--) { + uint8_t inbyte = *addr++; + for (uint32_t i = 8; i; i--) { + uint8_t mix = (crc ^ inbyte) & 0x80; + crc <<= 1; + if (mix) { crc ^= 0x31; } + inbyte <<= 1; + } + } + return crc; +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_ALECTOV2[] PROGMEM = + "{s}" D_ALECTOV2 " " D_RAIN "{m}%s " D_UNIT_MILLIMETER "{e}" + "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"; +const char HTTP_SNS_ALECTOV2_WDIR[] PROGMEM = + "{s}" D_ALECTOV2 " " D_TX20_WIND_DIRECTION "{m}%s{e}"; +#endif + +void RfSnsAlectoV2Show(bool json) +{ + if (rfsns_alecto_v2->time) { + if (rfsns_alecto_v2->time < LocalTime() - RFSNS_VALID_WINDOW) { + if (json) { + ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), GetDT(rfsns_alecto_v2->time).c_str()); + } + } else { + float temp = ConvertTemp(rfsns_alecto_v2->temp); + char temperature[33]; + dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); + float humi = ConvertHumidity((float)rfsns_alecto_v2->humi); + char humidity[33]; + dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); + char rain[33]; + dtostrfd(rfsns_alecto_v2->rain, 2, rain); + char wind[33]; + dtostrfd(rfsns_alecto_v2->wind, 2, wind); + char gust[33]; + dtostrfd(rfsns_alecto_v2->gust, 2, gust); + char wdir[4]; + char direction[20]; + if (rfsns_alecto_v2->type) { + GetTextIndexed(wdir, sizeof(wdir), rfsns_alecto_v2->wdir, kAlectoV2Directions); + snprintf_P(direction, sizeof(direction), PSTR(",\"Direction\":\"%s\""), wdir); + } + + if (json) { + ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), + temperature, humidity, rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); + if (0 == tele_period) { +#ifdef USE_DOMOTICZ + + + + +#endif + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, D_ALECTOV2, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, D_ALECTOV2, humidity); + WSContentSend_PD(HTTP_SNS_ALECTOV2, rain, wind, gust); + if (rfsns_alecto_v2->type) { + WSContentSend_PD(HTTP_SNS_ALECTOV2_WDIR, wdir); + } +#endif + } + } + } +} +#endif + +void RfSnsInit(void) +{ + rfsns_raw_signal = (raw_signal_t*)(malloc(sizeof(raw_signal_t))); + if (rfsns_raw_signal) { + memset(rfsns_raw_signal, 0, sizeof(raw_signal_t)); +#ifdef USE_THEO_V2 + RfSnsInitTheoV2(); +#endif +#ifdef USE_ALECTO_V2 + RfSnsInitAlectoV2(); +#endif + if (rfsns_any_sensor) { + rfsns_rf_bit = digitalPinToBitMask(pin[GPIO_RF_SENSOR]); + rfsns_rf_port = digitalPinToPort(pin[GPIO_RF_SENSOR]); + pinMode(pin[GPIO_RF_SENSOR], INPUT); + } else { + free(rfsns_raw_signal); + rfsns_raw_signal = nullptr; + } + } +} + +void RfSnsAnalyzeRawSignal(void) +{ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: Pulses %d"), (int)rfsns_raw_signal->Number); + +#ifdef USE_THEO_V2 + RfSnsAnalyzeTheov2(); +#endif +#ifdef USE_ALECTO_V2 + RfSnsAnalyzeAlectov2(); +#endif +} + +void RfSnsEverySecond(void) +{ +#ifdef USE_ALECTO_V2 + RfSnsAlectoResetRain(); +#endif +} + +void RfSnsShow(bool json) +{ +#ifdef USE_THEO_V2 + RfSnsTheoV2Show(json); +#endif +#ifdef USE_ALECTO_V2 + RfSnsAlectoV2Show(json); +#endif +} + + + + + +bool Xsns37(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_RF_SENSOR] < 99) && (FUNC_INIT == function)) { + RfSnsInit(); + } + else if (rfsns_raw_signal) { + switch (function) { + case FUNC_LOOP: + if ((*portInputRegister(rfsns_rf_port) &rfsns_rf_bit) == rfsns_rf_bit) { + if (RfSnsFetchSignal(pin[GPIO_RF_SENSOR], HIGH)) { + RfSnsAnalyzeRawSignal(); + } + } + sleep = 0; + break; + case FUNC_EVERY_SECOND: + RfSnsEverySecond(); + break; + case FUNC_JSON_APPEND: + RfSnsShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + RfSnsShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_38_az7798.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_38_az7798.ino" +#ifdef USE_AZ7798 + +#define XSNS_38 38 +# 112 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_38_az7798.ino" +#include + +#ifndef CO2_LOW +#define CO2_LOW 800 +#endif +#ifndef CO2_HIGH +#define CO2_HIGH 1200 +#endif + +#define AZ_READ_TIMEOUT 400 + +#define AZ_CLOCK_UPDATE_INTERVAL (24UL * 60 * 60) +#define AZ_EPOCH (946684800UL) + +TasmotaSerial *AzSerial; + +const char ktype[] = "AZ7798"; +uint8_t az_type = 1; +uint16_t az_co2 = 0; +double az_temperature = 0; +double az_humidity = 0; +uint8_t az_received = 0; +uint8_t az_state = 0; +unsigned long az_clock_update = 10; + + + +void AzEverySecond(void) +{ + unsigned long start = millis(); + + az_state++; + if (5 == az_state) { + az_state = 0; + + AzSerial->flush(); + AzSerial->write(":\r", 2); + az_received = 0; + + uint8_t az_response[32]; + uint8_t counter = 0; + uint8_t i, j; + uint8_t response_substr[16]; + + do { + if (AzSerial->available() > 0) { + az_response[counter] = AzSerial->read(); + if(az_response[counter] == 0x0d) { az_received = 1; } + counter++; + } else { + delay(5); + } + } while(((millis() - start) < AZ_READ_TIMEOUT) && (counter < sizeof(az_response)) && !az_received); + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, az_response, counter); + + if (!az_received) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 comms timeout")); + return; + } + + i = 0; + while((az_response[i] != 'T') && (i < counter)) {i++;} + if(az_response[i] != 'T') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find start of response")); + return; + } + i++; + j = 0; + + while((az_response[i] != 'C') && (az_response[i] != 'F') && (i < counter)) { + response_substr[j++] = az_response[i++]; + } + if((az_response[i] != 'C') && (az_response[i] != 'F')){ + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of temperature")); + return; + } + response_substr[j] = 0; + az_temperature = CharToFloat((char*)response_substr); + if(az_response[i] == 'C') { + az_temperature = ConvertTemp((float)az_temperature); + } else { + az_temperature = ConvertTemp((az_temperature - 32) / 1.8); + } + i++; + if(az_response[i] != ':') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error first delimiter")); + return; + } + i++; + if(az_response[i] != 'C') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of CO2")); + return; + } + i++; + j = 0; + + while((az_response[i] != 'p') && (i < counter)) { + response_substr[j++] = az_response[i++]; + } + if(az_response[i] != 'p') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of CO2")); + return; + } + response_substr[j] = 0; + az_co2 = atoi((char*)response_substr); + LightSetSignal(CO2_LOW, CO2_HIGH, az_co2); + i += 3; + if(az_response[i] != ':') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error second delimiter")); + return; + } + i++; + if(az_response[i] != 'H') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of humidity")); + return; + } + i++; + j = 0; + + while((az_response[i] != '%') && (i < counter)) { + response_substr[j++] = az_response[i++]; + } + if(az_response[i] != '%') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of humidity")); + return; + } + response_substr[j] = 0; + az_humidity = ConvertHumidity(CharToFloat((char*)response_substr)); + } + + + if ((az_clock_update == 0) && (LocalTime() > AZ_EPOCH)) { + char tmpString[16]; + sprintf(tmpString, "C %d\r", (int)(LocalTime() - AZ_EPOCH)); + AzSerial->write(tmpString); + + do { + if (AzSerial->available() > 0) { + if(AzSerial->read() == 0x0d) { break; } + } else { + delay(5); + } + } while(((millis() - start) < AZ_READ_TIMEOUT)); + az_clock_update = AZ_CLOCK_UPDATE_INTERVAL; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 clock updated")); + } else { + az_clock_update--; + } +} + + + +void AzInit(void) +{ + az_type = 0; + if ((pin[GPIO_AZ_RXD] < 99) && (pin[GPIO_AZ_TXD] < 99)) { + AzSerial = new TasmotaSerial(pin[GPIO_AZ_RXD], pin[GPIO_AZ_TXD], 1); + if (AzSerial->begin(9600)) { + if (AzSerial->hardwareSerial()) { ClaimSerial(); } + az_type = 1; + } + } +} + +void AzShow(bool json) +{ + char temperature[33]; + dtostrfd(az_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(az_humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), ktype, az_co2, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, az_co2); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2, ktype, az_co2); + WSContentSend_PD(HTTP_SNS_TEMP, ktype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, ktype, humidity); +#endif + } +} + + + + + +bool Xsns38(uint8_t function) +{ + bool result = false; + + if(az_type){ + switch (function) { + case FUNC_INIT: + AzInit(); + break; + case FUNC_EVERY_SECOND: + AzEverySecond(); + break; + case FUNC_JSON_APPEND: + AzShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + AzShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_39_max31855.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_39_max31855.ino" +#ifdef USE_MAX31855 + +#define XSNS_39 39 + +bool initialized = false; + +struct MAX31855_ResultStruct{ + uint8_t ErrorCode; + float ProbeTemperature; + float ReferenceTemperature; +} MAX31855_Result; + +void MAX31855_Init(void){ + if(initialized) + return; + + + pinMode(pin[GPIO_MAX31855CS], OUTPUT); + pinMode(pin[GPIO_MAX31855CLK], OUTPUT); + pinMode(pin[GPIO_MAX31855DO], INPUT); + + + digitalWrite(pin[GPIO_MAX31855CS], HIGH); + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + + initialized = true; +} + + + + + +void MAX31855_GetResult(void){ + int32_t RawData = MAX31855_ShiftIn(32); + uint8_t probeerror = RawData & 0x7; + + MAX31855_Result.ErrorCode = probeerror; + MAX31855_Result.ReferenceTemperature = MAX31855_GetReferenceTemperature(RawData); + if(probeerror) + MAX31855_Result.ProbeTemperature = NAN; + else + MAX31855_Result.ProbeTemperature = MAX31855_GetProbeTemperature(RawData); +} + + + + + + +float MAX31855_GetProbeTemperature(int32_t RawData){ + if(RawData & 0x80000000) + RawData = (RawData >> 18) | 0xFFFFC000; + else + RawData >>= 18; + + float result = (RawData * 0.25); + + return (Settings.flag.temperature_conversion) ? ConvertTemp(result) : result; +} + + + + + +float MAX31855_GetReferenceTemperature(int32_t RawData){ + if(RawData & 0x8000) + RawData = (RawData >> 4) | 0xFFFFF000; + else + RawData = (RawData >> 4) & 0x00000FFF; + + float result = (RawData * 0.0625); + + return (Settings.flag.temperature_conversion) ? ConvertTemp(result) : result; +} + + + + + +int32_t MAX31855_ShiftIn(uint8_t Length){ + int32_t dataIn = 0; + + digitalWrite(pin[GPIO_MAX31855CS], LOW); + delayMicroseconds(1); + + for (uint32_t i = 0; i < Length; i++) + { + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + delayMicroseconds(1); + dataIn <<= 1; + if(digitalRead(pin[GPIO_MAX31855DO])) + dataIn |= 1; + digitalWrite(pin[GPIO_MAX31855CLK], HIGH); + delayMicroseconds(1); + } + + digitalWrite(pin[GPIO_MAX31855CS], HIGH); + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + return dataIn; +} + +void MAX31855_Show(bool Json){ + char probetemp[33]; + char referencetemp[33]; + dtostrfd(MAX31855_Result.ProbeTemperature, Settings.flag2.temperature_resolution, probetemp); + dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); + + if(Json){ + ResponseAppend_P(PSTR(",\"MAX31855\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ + probetemp, referencetemp, MAX31855_Result.ErrorCode); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, probetemp); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, MAX31855_Result.ProbeTemperature); + } +#endif + } else { +#ifdef USE_WEBSERVER + WSContentSend_PD(HTTP_SNS_TEMP, "MAX31855", probetemp, TempUnit()); +#endif + } +} + + + + + +bool Xsns39(uint8_t function) +{ + bool result = false; + if((pin[GPIO_MAX31855CS] < 99) && (pin[GPIO_MAX31855CLK] < 99) && (pin[GPIO_MAX31855DO] < 99)){ + + switch (function) { + case FUNC_INIT: + MAX31855_Init(); + break; + case FUNC_EVERY_SECOND: + MAX31855_GetResult(); + break; + case FUNC_JSON_APPEND: + MAX31855_Show(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MAX31855_Show(false); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_40_pn532.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_40_pn532.ino" +#ifdef USE_PN532_HSU + +#define XSNS_40 40 + +#include + +TasmotaSerial *PN532_Serial; + +#define PN532_INVALID_ACK -1 +#define PN532_TIMEOUT -2 +#define PN532_INVALID_FRAME -3 +#define PN532_NO_SPACE -4 + +#define PN532_PREAMBLE 0x00 +#define PN532_STARTCODE1 0x00 +#define PN532_STARTCODE2 0xFF +#define PN532_POSTAMBLE 0x00 + +#define PN532_HOSTTOPN532 0xD4 +#define PN532_PN532TOHOST 0xD5 + +#define PN532_ACK_WAIT_TIME 0x0A + +#define PN532_COMMAND_GETFIRMWAREVERSION 0x02 +#define PN532_COMMAND_SAMCONFIGURATION 0x14 +#define PN532_COMMAND_RFCONFIGURATION 0x32 +#define PN532_COMMAND_INDATAEXCHANGE 0x40 +#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A + +#define PN532_MIFARE_ISO14443A 0x00 +#define MIFARE_CMD_READ 0x30 +#define MIFARE_CMD_AUTH_A 0x60 +#define MIFARE_CMD_AUTH_B 0x61 +#define MIFARE_CMD_WRITE 0xA0 + +uint8_t pn532_model = 0; +uint8_t pn532_command = 0; +uint8_t pn532_scantimer = 0; + +uint8_t pn532_packetbuffer[64]; + +#ifdef USE_PN532_DATA_FUNCTION +uint8_t pn532_function = 0; +uint8_t pn532_newdata[16]; +uint8_t pn532_newdata_len = 0; +#endif + +void PN532_Init(void) +{ + if ((pin[GPIO_PN532_RXD] < 99) && (pin[GPIO_PN532_TXD] < 99)) { + PN532_Serial = new TasmotaSerial(pin[GPIO_PN532_RXD], pin[GPIO_PN532_TXD], 1); + if (PN532_Serial->begin(115200)) { + if (PN532_Serial->hardwareSerial()) { ClaimSerial(); } + PN532_wakeup(); + uint32_t ver = PN532_getFirmwareVersion(); + if (ver) { + PN532_setPassiveActivationRetries(0xFF); + PN532_SAMConfig(); + pn532_model = 1; + AddLog_P2(LOG_LEVEL_INFO,"NFC: PN532 NFC Reader detected (V%u.%u)",(ver>>16) & 0xFF, (ver>>8) & 0xFF); + } + } + } +} + +int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout) +{ + int read_bytes = 0; + int ret; + unsigned long start_millis; + while (read_bytes < len) { + start_millis = millis(); + do { + ret = PN532_Serial->read(); + if (ret >= 0) { + break; + } + } while((timeout == 0) || ((millis()- start_millis ) < timeout)); + + if (ret < 0) { + if (read_bytes) { + return read_bytes; + } else { + return PN532_TIMEOUT; + } + } + buf[read_bytes] = (uint8_t)ret; + read_bytes++; + } + return read_bytes; +} + +int8_t PN532_readAckFrame(void) +{ + const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; + uint8_t ackBuf[sizeof(PN532_ACK)]; + + if (PN532_receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0) { + return PN532_TIMEOUT; + } + + if (memcmp(&ackBuf, &PN532_ACK, sizeof(PN532_ACK))) { + return PN532_INVALID_ACK; + } + return 0; +} + +int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) +{ + + PN532_Serial->flush(); + + pn532_command = header[0]; + PN532_Serial->write((uint8_t)PN532_PREAMBLE); + PN532_Serial->write((uint8_t)PN532_STARTCODE1); + PN532_Serial->write(PN532_STARTCODE2); + + uint8_t length = hlen + blen + 1; + PN532_Serial->write(length); + PN532_Serial->write(~length + 1); + + PN532_Serial->write(PN532_HOSTTOPN532); + uint8_t sum = PN532_HOSTTOPN532; + + PN532_Serial->write(header, hlen); + for (uint32_t i = 0; i < hlen; i++) { + sum += header[i]; + } + + PN532_Serial->write(body, blen); + for (uint32_t i = 0; i < blen; i++) { + sum += body[i]; + } + + uint8_t checksum = ~sum + 1; + PN532_Serial->write(checksum); + PN532_Serial->write((uint8_t)PN532_POSTAMBLE); + + return PN532_readAckFrame(); +} + +int16_t PN532_readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 50) +{ + uint8_t tmp[3]; + + + if (PN532_receive(tmp, 3, timeout)<=0) { + return PN532_TIMEOUT; + } + if (0 != tmp[0] || 0!= tmp[1] || 0xFF != tmp[2]) { + return PN532_INVALID_FRAME; + } + + + uint8_t length[2]; + if (PN532_receive(length, 2, timeout) <= 0) { + return PN532_TIMEOUT; + } + + if (0 != (uint8_t)(length[0] + length[1])) { + return PN532_INVALID_FRAME; + } + length[0] -= 2; + if (length[0] > len) { + return PN532_NO_SPACE; + } + + + uint8_t cmd = pn532_command + 1; + if (PN532_receive(tmp, 2, timeout) <= 0) { + return PN532_TIMEOUT; + } + if (PN532_PN532TOHOST != tmp[0] || cmd != tmp[1]) { + return PN532_INVALID_FRAME; + } + + if (PN532_receive(buf, length[0], timeout) != length[0]) { + return PN532_TIMEOUT; + } + + uint8_t sum = PN532_PN532TOHOST + cmd; + for (uint32_t i=0; i status) { + return 0; + } + + response = pn532_packetbuffer[0]; + response <<= 8; + response |= pn532_packetbuffer[1]; + response <<= 8; + response |= pn532_packetbuffer[2]; + response <<= 8; + response |= pn532_packetbuffer[3]; + + return response; +} + +void PN532_wakeup(void) +{ + uint8_t wakeup[5] = {0x55, 0x55, 0, 0, 0 }; + PN532_Serial->write(wakeup,sizeof(wakeup)); + + + PN532_Serial->flush(); +} + +bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 50) +{ + pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = cardbaudrate; + if (PN532_writeCommand(pn532_packetbuffer, 3)) { + return 0x0; + } + + if (PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) { + return 0x0; + } +# 274 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_40_pn532.ino" + if (pn532_packetbuffer[0] != 1) { + return 0; + } + + uint16_t sens_res = pn532_packetbuffer[2]; + sens_res <<= 8; + sens_res |= pn532_packetbuffer[3]; + + + *uidLength = pn532_packetbuffer[5]; + + for (uint32_t i = 0; i < pn532_packetbuffer[5]; i++) { + uid[i] = pn532_packetbuffer[6 + i]; + } + + return 1; +} + +bool PN532_setPassiveActivationRetries(uint8_t maxRetries) +{ + pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; + pn532_packetbuffer[1] = 5; + pn532_packetbuffer[2] = 0xFF; + pn532_packetbuffer[3] = 0x01; + pn532_packetbuffer[4] = maxRetries; + if (PN532_writeCommand(pn532_packetbuffer, 5)) { + return 0; + } + return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +bool PN532_SAMConfig(void) +{ + pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; + pn532_packetbuffer[1] = 0x01; + pn532_packetbuffer[2] = 0x14; + pn532_packetbuffer[3] = 0x00; + if (PN532_writeCommand(pn532_packetbuffer, 4)) { + return false; + } + return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +#ifdef USE_PN532_DATA_FUNCTION + +uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData) +{ + uint8_t i; + uint8_t _key[6]; + uint8_t _uid[7]; + uint8_t _uidLen; + + + memcpy(&_key, keyData, 6); + memcpy(&_uid, uid, uidLen); + _uidLen = uidLen; + + + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; + pn532_packetbuffer[3] = blockNumber; + memcpy(&pn532_packetbuffer[4], &_key, 6); + for (i = 0; i < _uidLen; i++) { + pn532_packetbuffer[10 + i] = _uid[i]; + } + + if (PN532_writeCommand(pn532_packetbuffer, 10 + _uidLen)) { return 0; } + + + PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + + + + + if (pn532_packetbuffer[0] != 0x00) { + + return 0; + } + + return 1; +} + +uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data) +{ + + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = MIFARE_CMD_READ; + pn532_packetbuffer[3] = blockNumber; + + + if (PN532_writeCommand(pn532_packetbuffer, 4)) { + return 0; + } + + + PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + + + if (pn532_packetbuffer[0] != 0x00) { + return 0; + } + + + + memcpy (data, &pn532_packetbuffer[1], 16); + + return 1; +} + +uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data) +{ + + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = MIFARE_CMD_WRITE; + pn532_packetbuffer[3] = blockNumber; + memcpy(&pn532_packetbuffer[4], data, 16); + + + if (PN532_writeCommand(pn532_packetbuffer, 20)) { + return 0; + } + + + return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +#endif + +void PN532_ScanForTag(void) +{ + if (!pn532_model) { return; } + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; + uint8_t uid_len = 0; + uint8_t card_data[16]; + bool erase_success = false; + bool set_success = false; + if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) { + char uids[15]; + +#ifdef USE_PN532_DATA_FUNCTION + char card_datas[34]; +#endif + + ToHex_P((unsigned char*)uid, uid_len, uids, sizeof(uids)); + +#ifdef USE_PN532_DATA_FUNCTION + if (uid_len == 4) { + uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) { + if (mifareclassic_ReadDataBlock(1, card_data)) { +#ifdef USE_PN532_DATA_RAW + memcpy(&card_datas,&card_data,sizeof(card_data)); +#else + for (uint32_t i = 0;i < sizeof(card_data);i++) { + if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) { + card_datas[i] = char(card_data[i]); + } else { + card_datas[i] = '\0'; + } + } +#endif + } + if (pn532_function == 1) { + for (uint32_t i = 0;i<16;i++) { + card_data[i] = 0x00; + } + if (mifareclassic_WriteDataBlock(1, card_data)) { + erase_success = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase success")); + memcpy(&card_datas,&card_data,sizeof(card_data)); + } + } + if (pn532_function == 2) { +#ifdef USE_PN532_DATA_RAW + memcpy(&card_data,&pn532_newdata,sizeof(card_data)); + if (mifareclassic_WriteDataBlock(1, card_data)) { + set_success = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); + memcpy(&card_datas,&card_data,sizeof(card_data)); + } +#else + bool IsAlphaNumeric = true; + for (uint32_t i = 0;i < pn532_newdata_len;i++) { + if ((!isalpha(pn532_newdata[i])) && (!isdigit(pn532_newdata[i]))) { + IsAlphaNumeric = false; + } + } + if (IsAlphaNumeric) { + memcpy(&card_data,&pn532_newdata,pn532_newdata_len); + card_data[pn532_newdata_len] = '\0'; + if (mifareclassic_WriteDataBlock(1, card_data)) { + set_success = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); + memcpy(&card_datas,&card_data,sizeof(card_data)); + } + } else { + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data must be alphanumeric")); + } +#endif + } + } else { + sprintf(card_datas,"AUTHFAIL"); + } + } + switch (pn532_function) { + case 0x01: + if (!erase_success) { + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase fail - exiting erase mode")); + } + break; + case 0x02: + if (!set_success) { + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Write failed - exiting set mode")); + } + default: + break; + } + pn532_function = 0; +#endif + +#ifdef USE_PN532_DATA_FUNCTION + ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), uids, card_datas); +#else + ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids); +#endif + + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + +#ifdef USE_PN532_CAUSE_EVENTS + + char command[71]; +#ifdef USE_PN532_DATA_FUNCTION + sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas); +#else + sprintf(command,"event PN532_UID=%s",uids); +#endif + ExecuteCommand(command, SRC_RULE); +#endif + + pn532_scantimer = 7; + } +} + +#ifdef USE_PN532_DATA_FUNCTION + +bool PN532_Command(void) +{ + bool serviced = true; + uint8_t paramcount = 0; + if (XdrvMailbox.data_len > 0) { + paramcount=1; + } else { + serviced = false; + return serviced; + } + char sub_string[XdrvMailbox.data_len]; + char sub_string_tmp[XdrvMailbox.data_len]; + for (uint32_t ca=0;ca 1) { + if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') { + serviced = false; + return serviced; + } + sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2)); + pn532_newdata_len = strlen(sub_string_tmp); + if (pn532_newdata_len > 15) { pn532_newdata_len = 15; } + memcpy(&pn532_newdata,&sub_string_tmp,pn532_newdata_len); + pn532_newdata[pn532_newdata_len] = 0x00; + pn532_function = 2; + AddLog_P2(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'"), pn532_newdata); + ResponseTime_P(PSTR(",\"PN532\":{\"COMMAND\":\"S\"}}")); + return serviced; + } + } +} + +#endif + +bool Xsns40(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_INIT: + PN532_Init(); + result = true; + break; + case FUNC_EVERY_50_MSECOND: + break; + case FUNC_EVERY_100_MSECOND: + break; + case FUNC_EVERY_250_MSECOND: + if (pn532_scantimer > 0) { + pn532_scantimer--; + } else { + PN532_ScanForTag(); + } + break; + case FUNC_EVERY_SECOND: + break; +#ifdef USE_PN532_DATA_FUNCTION + case FUNC_COMMAND_SENSOR: + if (XSNS_40 == XdrvMailbox.index) { + result = PN532_Command(); + } + break; +#endif + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_41_max44009.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_41_max44009.ino" +#ifdef USE_I2C +#ifdef USE_MAX44009 + + + + + + +#define XSNS_41 41 + +#define MAX44009_ADDR1 0x4A +#define MAX44009_ADDR2 0x4B +#define MAX44009_NO_REGISTERS 8 +#define REG_CONFIG 0x02 +#define REG_LUMINANCE 0x03 +#define REG_LOWER_THRESHOLD 0x06 +#define REG_THRESHOLD_TIMER 0x07 + +#define MAX44009_CONTINUOUS_AUTO_MODE 0x80 + +uint8_t max44009_address; +uint8_t max44009_addresses[] = { MAX44009_ADDR1, MAX44009_ADDR2, 0 }; +uint8_t max44009_found = 0; +uint8_t max44009_valid = 0; +float max44009_illuminance = 0; +char max44009_types[] = "MAX44009"; + +bool Max4409Read_lum(void) +{ + max44009_valid = 0; + uint8_t regdata[2]; + + + if (I2cValidRead16((uint16_t *)®data, max44009_address, REG_LUMINANCE)) { + int exponent = (regdata[0] & 0xF0) >> 4; + int mantissa = ((regdata[0] & 0x0F) << 4) | (regdata[1] & 0x0F); + max44009_illuminance = (float)(((0x00000001 << exponent) * (float)mantissa) * 0.045); + max44009_valid = 1; + return true; + } else { + return false; + } +} + + + +void Max4409Detect(void) +{ + uint8_t reg[8]; + bool failed = false; + + if (max44009_found) { + return; + } + + uint8_t buffer1; + uint8_t buffer2; + for (uint32_t i = 0; 0 != max44009_addresses[i]; i++) { + + max44009_address = max44009_addresses[i]; + + if ((I2cValidRead8(&buffer1, max44009_address, REG_LOWER_THRESHOLD)) && + (I2cValidRead8(&buffer2, max44009_address, REG_THRESHOLD_TIMER))) { + + + if ((0x00 == buffer1) && + (0xFF == buffer2)) { + + + + Wire.beginTransmission(max44009_address); + + + Wire.write(REG_CONFIG); + Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); + if (0 == Wire.endTransmission()) { + max44009_found = 1; + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, max44009_types, max44009_address); + break; + } + } + } + } +} + +void Max4409EverySecond(void) +{ + if (max44009_found) { + Max4409Read_lum(); + } +} + +void Max4409Show(bool json) +{ + char illum_str[8]; + + if (max44009_valid) { + + + + uint8_t prec = 0; + if (10 > max44009_illuminance ) { + prec = 3; + } else if (100 > max44009_illuminance) { + prec = 2; + } else if (1000 > max44009_illuminance) { + prec = 1; + } + dtostrf(max44009_illuminance, sizeof(illum_str) -1, prec, illum_str); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), max44009_types, illum_str); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_ILLUMINANCE, illum_str); + } +#endif +#ifdef USE_WEBSERVER + } else { + + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, max44009_types, (int)max44009_illuminance); +#endif + } + } +} + + + + + +bool Xsns41(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + Max4409Detect(); + break; + case FUNC_EVERY_SECOND: + Max4409EverySecond(); + break; + case FUNC_JSON_APPEND: + Max4409Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Max4409Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_42_scd30.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_42_scd30.ino" +#ifdef USE_I2C +#ifdef USE_SCD30 + +#define XSNS_42 42 + +#define SCD30_MAX_MISSED_READS 3 +#define SONOFF_SCD30_STATE_NO_ERROR 0 +#define SONOFF_SCD30_STATE_ERROR_DATA_CRC 1 +#define SONOFF_SCD30_STATE_ERROR_READ_MEAS 2 +#define SONOFF_SCD30_STATE_ERROR_SOFT_RESET 3 +#define SONOFF_SCD30_STATE_ERROR_I2C_RESET 4 +#define SONOFF_SCD30_STATE_ERROR_UNKNOWN 5 + +#include "Arduino.h" +#include + +#define D_CMND_SCD30 "SCD30" + +const char S_JSON_SCD30_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d}"; +const char S_JSON_SCD30_COMMAND_NFW_VALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d.%d}"; +const char S_JSON_SCD30_COMMAND[] PROGMEM = "{\"" D_CMND_SCD30 "%s\"}"; +const char kSCD30_Commands[] PROGMEM = "Alt|Auto|Cal|FW|Int|Pres|TOff"; + + + + + +enum SCD30_Commands { + CMND_SCD30_ALTITUDE, + CMND_SCD30_AUTOMODE, + CMND_SCD30_CALIBRATE, + CMND_SCD30_FW, + CMND_SCD30_INTERVAL, + CMND_SCD30_PRESSURE, + CMND_SCD30_TEMPOFFSET +}; + + + +FrogmoreScd30 scd30; + +bool scd30Found = false; +bool scd30IsDataValid = false; +int scd30ErrorState = SONOFF_SCD30_STATE_NO_ERROR; +uint16_t scd30Interval_sec; +int scd30Loop_count = 0; +int scd30DataNotAvailable_count = 0; +int scd30GoodMeas_count = 0; +int scd30Reset_count = 0; +int scd30CrcError_count = 0; +int scd30Co2Zero_count = 0; +int i2cReset_count = 0; +uint16_t scd30_CO2 = 0; +uint16_t scd30_CO2EAvg = 0; +float scd30_Humid = 0.0; +float scd30_Temp = 0.0; + +bool Scd30Init() +{ + int error; + bool i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); + if (i2c_flg) + { + uint8_t major = 0; + uint8_t minor = 0; + uint16_t interval_sec; + scd30.begin(); + error = scd30.getFirmwareVersion(&major, &minor); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: did not find an SCD30: 0x%lX", error); + AddLog(LOG_LEVEL_DEBUG); +#endif + return false; + } + else + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: found an SCD30: FW v%d.%d", major, minor); + AddLog(LOG_LEVEL_INFO); +#endif + } + + error = scd30.getMeasurementInterval(&scd30Interval_sec); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: error getMeasurementInterval: 0x%lX", error); + AddLog(LOG_LEVEL_ERROR); +#endif + return false; + } + + error = scd30.beginMeasuring(); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "Error: Scd30BeginMeasuring: 0x%lX", error); + AddLog(LOG_LEVEL_ERROR); +#endif + return false; + } + + return true; + } +} + + +int Scd30Update() +{ + int error = 0; + int16_t delta = 0; + scd30Loop_count++; + + if (!scd30Found) + { + scd30Found = Scd30Init(); +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "Scd30Update: found: %d ", scd30Found); + AddLog(LOG_LEVEL_INFO); +#endif + if (!scd30Found) + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "Scd30Update: found: %d ", scd30Found); + AddLog(LOG_LEVEL_INFO); +#endif + return (ERROR_SCD30_NOT_FOUND_ERROR); + } + } + else + { + if (scd30Loop_count > (scd30Interval_sec - 1)) + { + switch (scd30ErrorState) + { + case SONOFF_SCD30_STATE_NO_ERROR: + { + error = scd30.readMeasurement(&scd30_CO2, &scd30_CO2EAvg, &scd30_Temp, &scd30_Humid); + switch (error) + { + case ERROR_SCD30_NO_ERROR: + scd30Loop_count = 0; + scd30IsDataValid = true; + scd30GoodMeas_count++; + break; + + case ERROR_SCD30_NO_DATA: + scd30DataNotAvailable_count++; + break; + + case ERROR_SCD30_CRC_ERROR: + scd30ErrorState = SONOFF_SCD30_STATE_ERROR_DATA_CRC; + scd30CrcError_count++; +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: CRC error, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld", scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog(LOG_LEVEL_ERROR); +#endif + break; + + case ERROR_SCD30_CO2_ZERO: + scd30Co2Zero_count++; +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: CO2 zero, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld", scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog(LOG_LEVEL_ERROR); +#endif + break; + + default: + { + scd30ErrorState = SONOFF_SCD30_STATE_ERROR_READ_MEAS; +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld", error, scd30Loop_count); + AddLog(LOG_LEVEL_ERROR); +#endif + return (error); + } + break; + } + } + break; + + case SONOFF_SCD30_STATE_ERROR_DATA_CRC: + { + +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld", scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog(LOG_LEVEL_ERROR); + snprintf_P(log_data, sizeof(log_data), "SCD30: got CRC error, try again, counter: %ld", scd30Loop_count); + AddLog(LOG_LEVEL_ERROR); +#endif + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + break; + + case SONOFF_SCD30_STATE_ERROR_READ_MEAS: + { + +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld", scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog(LOG_LEVEL_ERROR); + snprintf_P(log_data, sizeof(log_data), "SCD30: not answering, sending soft reset, counter: %ld", scd30Loop_count); + AddLog(LOG_LEVEL_ERROR); +#endif + scd30Reset_count++; + error = scd30.softReset(); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: resetting got error: 0x%lX", error); + AddLog(LOG_LEVEL_ERROR); +#endif + error >>= 8; + if (error == 4) + { + scd30ErrorState = SONOFF_SCD30_STATE_ERROR_SOFT_RESET; + } + else + { + scd30ErrorState = SONOFF_SCD30_STATE_ERROR_UNKNOWN; + } + } + else + { + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + } + break; + + case SONOFF_SCD30_STATE_ERROR_SOFT_RESET: + { + +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld", scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog(LOG_LEVEL_ERROR); + snprintf_P(log_data, sizeof(log_data), "SCD30: clearing i2c bus"); + AddLog(LOG_LEVEL_ERROR); +#endif + i2cReset_count++; + error = scd30.clearI2CBus(); + if (error) + { + scd30ErrorState = SONOFF_SCD30_STATE_ERROR_I2C_RESET; +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: error clearing i2c bus: 0x%lX", error); + AddLog(LOG_LEVEL_ERROR); +#endif + } + else + { + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + } + break; + + default: + { + +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: unknown error state: 0x%lX", scd30ErrorState); + AddLog(LOG_LEVEL_ERROR); +#endif + scd30ErrorState = SONOFF_SCD30_STATE_ERROR_SOFT_RESET; + } + } + + if (scd30Loop_count > (SCD30_MAX_MISSED_READS * scd30Interval_sec)) + { + scd30IsDataValid = false; + } + } + } + return (ERROR_SCD30_NO_ERROR); +} + + +int Scd30GetCommand(int command_code, uint16_t *pvalue) +{ + switch (command_code) + { + case CMND_SCD30_ALTITUDE: + return scd30.getAltitudeCompensation(pvalue); + break; + + case CMND_SCD30_AUTOMODE: + return scd30.getCalibrationType(pvalue); + break; + + case CMND_SCD30_CALIBRATE: + return scd30.getForcedRecalibrationFactor(pvalue); + break; + + case CMND_SCD30_INTERVAL: + return scd30.getMeasurementInterval(pvalue); + break; + + case CMND_SCD30_PRESSURE: + return scd30.getAmbientPressure(pvalue); + break; + + case CMND_SCD30_TEMPOFFSET: + return scd30.getTemperatureOffset(pvalue); + break; + + default: + + break; + } +} + +int Scd30SetCommand(int command_code, uint16_t value) +{ + switch (command_code) + { + case CMND_SCD30_ALTITUDE: + return scd30.setAltitudeCompensation(value); + break; + + case CMND_SCD30_AUTOMODE: + return scd30.setCalibrationType(value); + break; + + case CMND_SCD30_CALIBRATE: + return scd30.setForcedRecalibrationFactor(value); + break; + + case CMND_SCD30_INTERVAL: + { + int error = scd30.setMeasurementInterval(value); + if (!error) + { + scd30Interval_sec = value; + } + + return error; + } + break; + + case CMND_SCD30_PRESSURE: + return scd30.setAmbientPressure(value); + break; + + case CMND_SCD30_TEMPOFFSET: + return scd30.setTemperatureOffset(value); + break; + + default: + + break; + } +} + + + + +bool Scd30CommandSensor() +{ + char command[CMDSZ]; + bool serviced = true; + uint8_t prefix_len = strlen(D_CMND_SCD30); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_SCD30), prefix_len)) { + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + prefix_len, kSCD30_Commands); + + switch (command_code) { + case CMND_SCD30_ALTITUDE: + case CMND_SCD30_AUTOMODE: + case CMND_SCD30_CALIBRATE: + case CMND_SCD30_INTERVAL: + case CMND_SCD30_PRESSURE: + case CMND_SCD30_TEMPOFFSET: + { + uint16_t value = 0; + if (XdrvMailbox.data_len > 0) + { + value = XdrvMailbox.payload; + Scd30SetCommand(command_code, value); + } + else + { + Scd30GetCommand(command_code, &value); + } + + Response_P(S_JSON_SCD30_COMMAND_NVALUE, command, value); + } + break; + + case CMND_SCD30_FW: + { + uint8_t major = 0; + uint8_t minor = 0; + int error; + error = scd30.getFirmwareVersion(&major, &minor); + if (error) + { +#ifdef SCD30_DEBUG + snprintf_P(log_data, sizeof(log_data), "SCD30: error getting FW version: 0x%lX", error); + AddLog(LOG_LEVEL_ERROR); +#endif + serviced = false; + } + else + { + Response_P(S_JSON_SCD30_COMMAND_NFW_VALUE, command, major, minor); + } + } + break; + + default: + + serviced = false; + break; + } + } + return serviced; +} + +void Scd30Show(bool json) +{ + char humidity[10]; + char temperature[10]; + + if (scd30Found && scd30IsDataValid) + { + dtostrfd(ConvertHumidity(scd30_Humid), Settings.flag2.humidity_resolution, humidity); + dtostrfd(ConvertTemp(scd30_Temp), Settings.flag2.temperature_resolution, temperature); + if (json) { + + ResponseAppend_P(PSTR(",\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), + scd30_CO2, scd30_CO2EAvg, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) + { + DomoticzSensor(DZ_AIRQUALITY, scd30_CO2); + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2EAVG, "SCD30", scd30_CO2EAvg); + WSContentSend_PD(HTTP_SNS_CO2, "SCD30", scd30_CO2); + WSContentSend_PD(HTTP_SNS_TEMP, "SCD30", temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, "SCD30", humidity); +#endif + } + } +} + + + + + +bool Xsns42(byte function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_EVERY_SECOND: + Scd30Update(); + break; + case FUNC_COMMAND: + result = Scd30CommandSensor(); + break; + case FUNC_JSON_APPEND: + Scd30Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Scd30Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_43_hre.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_43_hre.ino" +#ifdef USE_HRE +# 49 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_43_hre.ino" +#define XSNS_43 43 + +enum hre_states { + hre_idle, + hre_sync, + hre_syncing, + hre_read, + hre_reading, + hre_sleep, + hre_sleeping +}; + +hre_states hre_state = hre_idle; + +float hre_usage = 0; +float hre_rate = 0; +uint32_t hre_usage_time = 0; + +int hre_read_errors = 0; +bool hre_good = false; + + + +int hreReadBit() +{ + digitalWrite(pin[GPIO_HRE_CLOCK], HIGH); + delay(1); + int bit = digitalRead(pin[GPIO_HRE_DATA]); + digitalWrite(pin[GPIO_HRE_CLOCK], LOW); + delay(1); + return bit; +} + + + +char hreReadChar(int &parity_errors) +{ + + hreReadBit(); + + unsigned ch=0; + int sum=0; + for (uint32_t i=0; i<7; i++) + { + int b = hreReadBit(); + ch |= b << i; + sum += b; + } + + + if ( (sum & 0x1) != hreReadBit()) + parity_errors++; + + + hreReadBit(); + + return ch; +} + +void hreInit(void) +{ + hre_read_errors = 0; + hre_good = false; + + pinMode(pin[GPIO_HRE_CLOCK], OUTPUT); + pinMode(pin[GPIO_HRE_DATA], INPUT); + + + + digitalWrite(pin[GPIO_HRE_CLOCK], LOW); + + hre_state = hre_sync; +} + + +void hreEvery50ms(void) +{ + static int sync_counter = 0; + static int sync_run = 0; + + static uint32_t curr_start = 0; + static int read_counter = 0; + static int parity_errors = 0; + static char buff[46]; + + static char ch; + static size_t i; + + switch (hre_state) + { + case hre_sync: + if (uptime < 10) + break; + sync_run = 0; + sync_counter = 0; + hre_state = hre_syncing; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_syncing")); + break; + + case hre_syncing: + + + for (uint32_t i=0; i<20; i++) + { + if (hreReadBit()) + sync_run++; + else + sync_run = 0; + if (sync_run == 62) + { + hre_state = hre_read; + break; + } + sync_counter++; + } + + if (sync_counter > 1000) + { + hre_state = hre_sleep; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE D_ERROR)); + } + break; + + + case hre_read: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "sync_run:%d, sync_counter:%d"), sync_run, sync_counter); + read_counter = 0; + parity_errors = 0; + curr_start = uptime; + memset(buff, 0, sizeof(buff)); + hre_state = hre_reading; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_reading")); + + + + + + case hre_reading: + + buff[read_counter++] = hreReadChar(parity_errors); + buff[read_counter++] = hreReadChar(parity_errors); + + if (read_counter == 46) + { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "pe:%d, re:%d, buff:%s"), + parity_errors, hre_read_errors, buff); + if (parity_errors == 0) + { + float curr_usage; + curr_usage = 0.01 * atol(buff+24); + if (hre_usage_time) + { + double dt = 1.666e-2 * (curr_start - hre_usage_time); + hre_rate = (curr_usage - hre_usage)/dt; + } + hre_usage = curr_usage; + hre_usage_time = curr_start; + hre_good = true; + + hre_state = hre_sleep; + } + else + { + hre_read_errors++; + hre_state = hre_sleep; + } + } + break; + + case hre_sleep: + hre_usage_time = curr_start; + hre_state = hre_sleeping; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_sleeping")); + + case hre_sleeping: + + + if (uptime - hre_usage_time >= 27) + hre_state = hre_sync; + } +} + +void hreShow(boolean json) +{ + if (!hre_good) + return; + + const char *id = "HRE"; + + char usage[16]; + char rate[16]; + dtostrfd(hre_usage, 2, usage); + dtostrfd(hre_rate, 3, rate); + + if (json) + { + ResponseAppend_P(JSON_SNS_GNGPM, id, usage, rate); +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_SNS_GALLONS, id, usage); + WSContentSend_PD(HTTP_SNS_GPM, id, rate); +#endif + } +} + + + + + +bool Xsns43(byte function) +{ + + if (pin[GPIO_HRE_CLOCK] >= 99 || pin[GPIO_HRE_DATA] >= 99) + return false; + + switch (function) + { + case FUNC_INIT: + hreInit(); + break; + case FUNC_EVERY_50_MSECOND: + hreEvery50ms(); + break; + case FUNC_EVERY_SECOND: + break; + case FUNC_JSON_APPEND: + hreShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + hreShow(0); + break; +#endif + } + return false; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_44_sps30.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_44_sps30.ino" +#ifdef USE_I2C +#ifdef USE_SPS30 + +#define XSNS_44 44 + +#define SPS30_ADDR 0x69 + +#include +#include + +uint8_t sps30_ready = 0; +uint8_t sps30_running; + +struct SPS30 { + float PM1_0; + float PM2_5; + float PM4_0; + float PM10; + float NCPM0_5; + float NCPM1_0; + float NCPM2_5; + float NCPM4_0; + float NCPM10; + float TYPSIZ; +} sps30_result; + +#define SPS_CMD_START_MEASUREMENT 0x0010 +#define SPS_CMD_START_MEASUREMENT_ARG 0x0300 +#define SPS_CMD_STOP_MEASUREMENT 0x0104 +#define SPS_CMD_READ_MEASUREMENT 0x0300 +#define SPS_CMD_GET_DATA_READY 0x0202 +#define SPS_CMD_AUTOCLEAN_INTERVAL 0x8004 +#define SPS_CMD_CLEAN 0x5607 +#define SPS_CMD_GET_ACODE 0xd025 +#define SPS_CMD_GET_SERIAL 0xd033 +#define SPS_CMD_RESET 0xd304 +#define SPS_WRITE_DELAY_US 20000 +#define SPS_MAX_SERIAL_LEN 32 + +uint8_t sps30_calc_CRC(uint8_t *data) { + uint8_t crc = 0xFF; + for (uint32_t i = 0; i < 2; i++) { + crc ^= data[i]; + for (uint32_t bit = 8; bit > 0; --bit) { + if(crc & 0x80) { + crc = (crc << 1) ^ 0x31u; + } else { + crc = (crc << 1); + } + } + } + return crc; +} + +void CmdClean(void); + +unsigned char twi_readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop); + +void sps30_get_data(uint16_t cmd, uint8_t *data, uint8_t dlen) { +unsigned char cmdb[2]; +uint8_t tmp[3]; +uint8_t index=0; +memset(data,0,dlen); +uint8_t twi_buff[64]; + + Wire.beginTransmission(SPS30_ADDR); + cmdb[0]=cmd>>8; + cmdb[1]=cmd; + Wire.write(cmdb,2); + Wire.endTransmission(); + + + dlen/=2; + dlen*=3; + + twi_readFrom(SPS30_ADDR,twi_buff,dlen,1); + + uint8_t bind=0; + while (bind>8; + cmdb[1]=cmd; + + if (cmd==SPS_CMD_START_MEASUREMENT) { + cmdb[2]=SPS_CMD_START_MEASUREMENT_ARG>>8; + cmdb[3]=SPS_CMD_START_MEASUREMENT_ARG&0xff; + cmdb[4]=sps30_calc_CRC(&cmdb[2]); + Wire.write(cmdb,5); + } else { + Wire.write(cmdb,2); + } + Wire.endTransmission(); +} + +void SPS30_Detect() { + + if (!I2cDevice(SPS30_ADDR)) { + return; + } + uint8_t dcode[32]; + sps30_get_data(SPS_CMD_GET_SERIAL,dcode,sizeof(dcode)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("sps30 found with serial: %s"),dcode); + sps30_cmd(SPS_CMD_START_MEASUREMENT); + sps30_running = 1; + sps30_ready = 1; +} + +#define D_UNIT_PM "ug/m3" +#define D_UNIT_NCPM "#/m3" + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SPS30_a[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_PM "{e}"; +const char HTTP_SNS_SPS30_b[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_NCPM "{e}"; +const char HTTP_SNS_SPS30_c[] PROGMEM ="{s}SPS30 " "TYPSIZ" "{m}%s " "um" "{e}"; +#endif + +#define PMDP 2 + +#define SPS30_HOURS Settings.sps30_inuse_hours + + + +void SPS30_Every_Second() { + + if (!sps30_ready) return; + if (!sps30_running) return; + + + if (uptime%10==0) { + uint8_t vars[sizeof(float)*10]; + sps30_get_data(SPS_CMD_READ_MEASUREMENT,vars,sizeof(vars)); + float *fp=&sps30_result.PM1_0; + + typedef union { + uint8_t array[4]; + float value; + } ByteToFloat; + + ByteToFloat conv; + + for (uint32_t count=0; count<10; count++) { + for (uint32_t i = 0; i < 4; i++){ + conv.array[3-i] = vars[count*sizeof(float)+i]; + } + *fp++=conv.value; + } + } + + if (uptime%3600==0 && uptime>60) { + + + SPS30_HOURS++; + if (SPS30_HOURS>(7*24)) { + CmdClean(); + SPS30_HOURS=0; + } + } + +} + +void SPS30_Show(bool json) { + char str[64]; + if (!sps30_ready) { + return; + } + + if (!sps30_running) { + return; + } + + if (json) { + dtostrfd(sps30_result.PM1_0,PMDP,str); + ResponseAppend_P(PSTR(",\"SPS30\":{\"" "PM1_0" "\":%s"), str); + dtostrfd(sps30_result.PM2_5,PMDP,str); + ResponseAppend_P(PSTR(",\"" "PM2_5" "\":%s"), str); + dtostrfd(sps30_result.PM4_0,PMDP,str); + ResponseAppend_P(PSTR(",\"" "PM4_0" "\":%s"), str); + dtostrfd(sps30_result.PM10,PMDP,str); + ResponseAppend_P(PSTR(",\"" "PM10" "\":%s"), str); + dtostrfd(sps30_result.NCPM0_5,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM0_5" "\":%s"), str); + dtostrfd(sps30_result.NCPM1_0,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM1_0" "\":%s"), str); + dtostrfd(sps30_result.NCPM2_5,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM2_5" "\":%s"), str); + dtostrfd(sps30_result.NCPM4_0,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM4_0" "\":%s"), str); + dtostrfd(sps30_result.NCPM10,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM10" "\":%s"), str); + dtostrfd(sps30_result.TYPSIZ,PMDP,str); + ResponseAppend_P(PSTR(",\"" "TYPSIZ" "\":%s}"), str); + +#ifdef USE_WEBSERVER + } else { + dtostrfd(sps30_result.PM1_0,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 1.0",str); + dtostrfd(sps30_result.PM2_5,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 2.5",str); + dtostrfd(sps30_result.PM4_0,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 4.0",str); + dtostrfd(sps30_result.PM10,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 10",str); + dtostrfd(sps30_result.NCPM0_5,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 0.5",str); + dtostrfd(sps30_result.NCPM1_0,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 1.0",str); + dtostrfd(sps30_result.NCPM2_5,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 2.5",str); + dtostrfd(sps30_result.NCPM4_0,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 4.0",str); + dtostrfd(sps30_result.NCPM10,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 10",str); + dtostrfd(sps30_result.TYPSIZ,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_c,str); +#endif + } + +} + +void CmdClean(void) { + sps30_cmd(SPS_CMD_CLEAN); + ResponseTime_P(PSTR(",\"SPS30\":{\"CFAN\":\"true\"}}")); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +} + +bool SPS30_cmd(void) { + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + char *cp=XdrvMailbox.data; + if (*cp=='c') { + + CmdClean(); + } else if (*cp=='0' || *cp=='1') { + sps30_running=*cp&1; + sps30_cmd(sps30_running?SPS_CMD_START_MEASUREMENT:SPS_CMD_STOP_MEASUREMENT); + } else { + serviced=false; + } + } + Response_P(PSTR("{\"SPS30\":\"%s\"}"), sps30_running?"running":"stopped"); + + return serviced; +} + + + + + + +bool Xsns44(byte function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + SPS30_Detect(); + break; + case FUNC_EVERY_SECOND: + SPS30_Every_Second(); + break; + case FUNC_JSON_APPEND: + SPS30_Show(1); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_44 == XdrvMailbox.index) { + result = SPS30_cmd(); + } + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SPS30_Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_45_vl53l0x.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_45_vl53l0x.ino" +#ifdef USE_I2C +#ifdef USE_VL53L0X + +#include +#include "VL53L0X.h" +VL53L0X sensor; + +uint8_t vl53l0x_ready = 0; +uint16_t vl53l0x_distance; +uint16_t Vl53l0_buffer[5]; +uint8_t Vl53l0_index; + + + + +void Vl53l0Detect() +{ + + if (!I2cDevice(0x29)) { + return; + } + + if (vl53l0x_ready) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("VL53L1X is ready")); + return; + } + + if (sensor.init()==true) { + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VL53L0X", sensor.getAddress()); + AddLog(LOG_LEVEL_DEBUG); + } else { + return; + } + + sensor.setTimeout(500); + + + + + + sensor.startContinuous(); + vl53l0x_ready = 1; + + Vl53l0_index=0; + +} + +#define D_UNIT_MILLIMETER "mm" + +#ifdef USE_WEBSERVER +const char HTTP_SNS_VL53L0X[] PROGMEM = + "{s}VL53L0X " D_DISTANCE "{m}%d" D_UNIT_MILLIMETER "{e}"; +#endif + +#define USE_VL_MEDIAN + +void Vl53l0Every_250MSecond() { + uint16_t tbuff[5],tmp; + uint8_t flag; + + if (!vl53l0x_ready) return; + + + uint16_t dist = sensor.readRangeContinuousMillimeters(); + if (dist==0 || dist>2000) { + dist=9999; + } + +#ifdef USE_VL_MEDIAN + + Vl53l0_buffer[Vl53l0_index]=dist; + Vl53l0_index++; + if (Vl53l0_index>=5) Vl53l0_index=0; + + + memmove(tbuff,Vl53l0_buffer,sizeof(tbuff)); + for (byte ocnt=0; ocnt<5; ocnt++) { + flag=0; + for (byte count=0; count<4; count++) { + if (tbuff[count]>tbuff[count+1]) { + tmp=tbuff[count]; + tbuff[count]=tbuff[count+1]; + tbuff[count+1]=tmp; + flag=1; + } + } + if (!flag) break; + } + vl53l0x_distance=tbuff[2]; +#else + vl53l0x_distance=dist; +#endif +} + +void Vl53l0Show(boolean json) +{ + if (!vl53l0x_ready) { + return; + } + + if (json) { + ResponseAppend_P(PSTR(",\"VL53L0X\":{\"" D_JSON_DISTANCE "\":%d}"), vl53l0x_distance); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_VL53L0X, vl53l0x_distance); +#endif + } + +} + + + + + +#define XSNS_45 45 + +bool Xsns45(byte function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + Vl53l0Detect(); + break; + case FUNC_EVERY_250_MSECOND: + Vl53l0Every_250MSecond(); + break; + case FUNC_JSON_APPEND: + Vl53l0Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Vl53l0Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_46_MLX90614.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_46_MLX90614.ino" +#ifdef USE_I2C +#ifdef USE_MLX90614 + +#define XSNS_46 46 + +#define I2_ADR_IRT 0x5a + +uint8_t mlx_ready; +float obj_temp; +float amb_temp; + +void MLX90614_Init() { + + if (!I2cDevice(I2_ADR_IRT)) { + return; + } + + mlx_ready=1; + + + + +} + +#define MLX90614_RAWIR1 0x04 +#define MLX90614_RAWIR2 0x05 +#define MLX90614_TA 0x06 +#define MLX90614_TOBJ1 0x07 +#define MLX90614_TOBJ2 0x08 + + + + +uint16_t read_irtmp(uint8_t flag) { + uint8_t hig,low; + uint16_t val; + + Wire.beginTransmission(I2_ADR_IRT); + if (!flag) Wire.write(MLX90614_TA); + else Wire.write(MLX90614_TOBJ1); + Wire.endTransmission(false); + + Wire.requestFrom(I2_ADR_IRT, (uint8_t)3); + low=Wire.read(); + hig=Wire.read(); + Wire.read(); + + val=((uint16_t)hig<<8)|low; + return val; +} + +void MLX90614_Every_Second(void) { + + if (!mlx_ready) return; + uint16_t uval=read_irtmp(1); + if (uval&0x8000) { + obj_temp=-999; + } else { + obj_temp=((float)uval*0.02)-273.15; + } + uval=read_irtmp(0); + if (uval&0x8000) { + amb_temp=-999; + } else { + amb_temp=((float)uval*0.02)-273.15; + } +} + +#ifdef USE_WEBSERVER + const char HTTP_IRTMP[] PROGMEM = + "{s}MXL90614 " "OBJ-" D_TEMPERATURE "{m}%s C" "{e}" + "{s}MXL90614 " "AMB-" D_TEMPERATURE "{m}%s C" "{e}"; + +void MLX90614_Show(uint8_t json) { + + if (!mlx_ready) return; + + char obj_tstr[16]; + dtostrfd(obj_temp, Settings.flag2.temperature_resolution, obj_tstr); + char amb_tstr[16]; + dtostrfd(amb_temp, Settings.flag2.temperature_resolution, amb_tstr); + + if (json) { + ResponseAppend_P(PSTR(",\"MLX90614\":{\"OBJTMP\":%s,\"AMBTMP\":%s}"), obj_tstr,amb_tstr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_IRTMP,obj_tstr,amb_tstr); +#endif + } + +} +#endif + + + + + +bool Xsns46(byte function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + MLX90614_Init(); + break; + case FUNC_EVERY_SECOND: + MLX90614_Every_Second(); + break; + case FUNC_JSON_APPEND: + MLX90614_Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MLX90614_Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_47_max31865.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_47_max31865.ino" +#ifdef USE_MAX31865 + +#ifndef USE_SPI +#error "MAX31865 requires USE_SPI enabled" +#endif + +#include "Adafruit_MAX31865.h" + +#define XSNS_47 47 + +#if MAX31865_PTD_WIRES == 4 + #define PTD_WIRES MAX31865_4WIRE +#elif MAX31865_PTD_WIRES == 3 + #define PTD_WIRES MAX31865_3WIRE +#else + #define PTD_WIRES MAX31865_2WIRE +#endif + +int8_t init_status = 0; + +Adafruit_MAX31865 max31865; + +struct MAX31865_Result_Struct { + uint8_t ErrorCode; + uint16_t Rtd; + float PtdResistance; + float PtdTemp; +} MAX31865_Result; + +void MAX31865_Init(void){ + if(init_status) + return; + + max31865.setPins( + pin[GPIO_SSPI_CS], + pin[GPIO_SSPI_MOSI], + pin[GPIO_SSPI_MISO], + pin[GPIO_SSPI_SCLK] + ); + + if(max31865.begin(PTD_WIRES)) + init_status = 1; + else + init_status = -1; +} + + + + + +void MAX31865_GetResult(void){ + uint16_t rtd; + + rtd = max31865.readRTD(); + MAX31865_Result.Rtd = rtd; + MAX31865_Result.PtdResistance = max31865.rtd_to_resistance(rtd, MAX31865_REF_RES); + MAX31865_Result.PtdTemp = max31865.rtd_to_temperature(rtd, MAX31865_PTD_RES, MAX31865_REF_RES) + MAX31865_PTD_BIAS; +} + +void MAX31865_Show(bool Json){ + char temperature[33]; + char resistance[33]; + + dtostrfd(MAX31865_Result.PtdResistance, Settings.flag2.temperature_resolution, resistance); + dtostrfd(MAX31865_Result.PtdTemp, Settings.flag2.temperature_resolution, temperature); + + if(Json){ + ResponseAppend_P(PSTR(",\"MAX31865\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RESISTANCE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ + temperature, resistance, MAX31865_Result.ErrorCode); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, MAX31865_Result.PtdTemp); + } +#endif + } else { +#ifdef USE_WEBSERVER + WSContentSend_PD(HTTP_SNS_TEMP, "MAX31865", temperature, TempUnit()); +#endif + } +} + + + + + +bool Xsns47(uint8_t function) +{ + bool result = false; + if((pin[GPIO_SSPI_MISO] < 99) && (pin[GPIO_SSPI_MOSI] < 99) && + (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_CS] < 99)) { + + switch (function) { + case FUNC_INIT: + MAX31865_Init(); + break; + + case FUNC_EVERY_SECOND: + MAX31865_GetResult(); + break; + + case FUNC_JSON_APPEND: + MAX31865_Show(true); + break; + +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MAX31865_Show(false); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_48_chirp.ino" +# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_48_chirp.ino" +#ifdef USE_I2C +#ifdef USE_CHIRP + + + + + + + +#define XSNS_48 48 +#define CHIRP_MAX_SENSOR_COUNT 3 + +#define CHIRP_ADDR_STANDARD 0x20 + + + + + +#define D_CMND_CHIRP "CHIRP" + +const char S_JSON_CHIRP_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_CHIRP "%s\":%d}"; +const char S_JSON_CHIRP_COMMAND[] PROGMEM = "{\"" D_CMND_CHIRP "%s\"}"; +const char kCHIRP_Commands[] PROGMEM = "Select|Set|Scan|Reset|Sleep|Wake"; + +const char kChirpTypes[] PROGMEM = "CHIRP"; + + + + + +enum CHIRP_Commands { + CMND_CHIRP_SELECT, + CMND_CHIRP_SET, + CMND_CHIRP_SCAN, + CMND_CHIRP_RESET, + CMND_CHIRP_SLEEP, + CMND_CHIRP_WAKE }; + + + + + + +#define CHIRP_GET_CAPACITANCE 0x00 +#define CHIRP_SET_ADDRESS 0x01 +#define CHIRP_GET_ADDRESS 0x02 +#define CHIRP_MEASURE_LIGHT 0x03 +#define CHIRP_GET_LIGHT 0x04 +#define CHIRP_GET_TEMPERATURE 0x05 +#define CHIRP_RESET 0x06 +#define CHIRP_GET_VERSION 0x07 +#define CHIRP_SLEEP 0x08 +#define CHIRP_GET_BUSY 0x09 + + + + + +bool I2cWriteReg(uint8_t addr, uint8_t reg) +{ + return I2cWrite(addr, reg, 0, 0); +} + + + + + +uint8_t chirp_current = 0; +uint8_t chirp_found_sensors = 0; + +char chirp_name[7]; +uint8_t chirp_next_job = 0; +uint32_t chirp_timeout_count = 0; + +#pragma pack(1) +struct ChirpSensor_t{ + uint16_t moisture = 0; + uint16_t light = 0; + int16_t temperature= 0; + uint8_t version = 0; + uint8_t address:7; + uint8_t explicitSleep:1; +}; +#pragma pack() + +ChirpSensor_t chirp_sensor[CHIRP_MAX_SENSOR_COUNT]; + + + +void ChirpReset(uint8_t addr) { + I2cWriteReg(addr, CHIRP_RESET); +} + + + +void ChirpResetAll(void) { + for (uint32_t i = 0; i < chirp_found_sensors; i++) { + if (chirp_sensor[i].version) { + ChirpReset(chirp_sensor[i].address); + } + } +} + + +void ChirpClockSet() { + Wire.setClockStretchLimit(4000); + Wire.setClock(50000); +} + + + +void ChirpSleep(uint8_t addr) { + I2cWriteReg(addr, CHIRP_SLEEP); +} +# 168 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_48_chirp.ino" +void ChirpSelect(uint8_t sensor) { + if(sensor < chirp_found_sensors) { + chirp_current = sensor; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: Sensor %u now active."), chirp_current); + } + if (sensor == 255) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: Sensor %u active at address 0x%x."), chirp_current, chirp_sensor[chirp_current].address); + } +} + + + +bool ChirpMeasureLight(void) { + for (uint32_t i = 0; i < chirp_found_sensors; i++) { + if (chirp_sensor[i].version && !chirp_sensor[i].explicitSleep) { + uint8_t lightReady = I2cRead8(chirp_sensor[i].address, CHIRP_GET_BUSY); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: busy status for light for sensor %u"), lightReady); + if (lightReady == 1) { + return false; + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: init measure light for sensor %u"), i); + I2cWriteReg(chirp_sensor[i].address, CHIRP_MEASURE_LIGHT); + } + } + return true; +} + + + +void ChirpReadCapTemp() { + for (uint32_t i = 0; i < chirp_found_sensors; i++) { + if (chirp_sensor[i].version && !chirp_sensor[i].explicitSleep) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: now really read CapTemp for sensor at address 0x%x"), chirp_sensor[i].address); + chirp_sensor[i].moisture = I2cRead16(chirp_sensor[i].address, CHIRP_GET_CAPACITANCE); + chirp_sensor[i].temperature = I2cRead16(chirp_sensor[i].address, CHIRP_GET_TEMPERATURE); + } + } +} + + + +bool ChirpReadLight() { + bool success = false; + for (uint32_t i = 0; i < chirp_found_sensors; i++) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: will read light for sensor %u"), i); + if (chirp_sensor[i].version) { + if (I2cValidRead16(&chirp_sensor[i].light, chirp_sensor[i].address, CHIRP_GET_LIGHT)){ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: light read success")); + success = true; + } + if(!chirp_sensor[i].explicitSleep){ success = true;} + } + } + return success; +} + + + +uint8_t ChirpReadVersion(uint8_t addr) { + return (I2cRead8(addr, CHIRP_GET_VERSION)); +} + + + +bool ChirpSet(uint8_t addr) { + if(addr < 128){ + if (I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr)){ + I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: Wrote adress %u "), addr); + ChirpReset(chirp_sensor[chirp_current].address); + chirp_sensor[chirp_current].address = addr; + return true; + } + } + return false; +} + + + +bool ChirpScan() { + ChirpClockSet(); + chirp_found_sensors = 0; + for (uint8_t address = 1; address <= 127; address++) { + chirp_sensor[chirp_found_sensors].version = 0; + chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); + delay(2); + chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); + if(chirp_sensor[chirp_found_sensors].version > 0) { + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "CHIRP:", address); + if(chirp_found_sensors 0) { + return; + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: scan will start ...")); + if (ChirpScan()) { + uint8_t chirp_model = 0; + GetTextIndexed(chirp_name, sizeof(chirp_name), chirp_model, kChirpTypes); + } +} + + + + +void ChirpEverySecond(void) +{ + + if(chirp_timeout_count == 0) { + switch(chirp_next_job) { + case 0: + AddLog_P2(LOG_LEVEL_DEBUG,PSTR( "CHIRP: reset all")); + ChirpResetAll(); + chirp_timeout_count = 1; + chirp_next_job++; + break; + case 1: + + + chirp_next_job++; + break; + case 2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: call CapTemp twice")); + ChirpReadCapTemp(); + ChirpReadCapTemp(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: call measure light")); + ChirpMeasureLight(); + chirp_timeout_count = 2; + chirp_next_job++; + break; + case 3: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: call read light")); + if (ChirpReadLight()){ + + + chirp_next_job++; + } + break; + case 4: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: paused, waiting for TELE")); + break; + case 5: + if (Settings.tele_period > 9){ + chirp_timeout_count = Settings.tele_period - 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: timeout: %u, tele: %u"), chirp_timeout_count, Settings.tele_period); + } + chirp_next_job = 1; + break; + } + } + else { + chirp_timeout_count--; + } +} + + + + +#define D_JSON_MOISTURE "Moisture" + +#ifdef USE_WEBSERVER + + + const char HTTP_SNS_MOISTURE[] PROGMEM = "{s} " D_JSON_MOISTURE ": {m}%s %{e}"; + const char HTTP_SNS_CHIRPVER[] PROGMEM = "{s} CHIRP-sensor %u at address: {m}0x%x{e}" + "{s} FW-version: {m}%s {e}"; ; + const char HTTP_SNS_CHIRPSLEEP[] PROGMEM = "{s} {m} is sleeping ...{e}"; +#endif + + + + +void ChirpShow(bool json) +{ + for (uint32_t i = 0; i < chirp_found_sensors; i++) { + if (chirp_sensor[i].version) { + + char str_moisture[33]; + dtostrfd(chirp_sensor[i].moisture, 0, str_moisture); + char str_temperature[33]; + double t_temperature = ((double) chirp_sensor[i].temperature )/10.0; + dtostrfd(t_temperature, Settings.flag2.temperature_resolution, str_temperature); + char str_light[33]; + dtostrfd(chirp_sensor[i].light, 0, str_light); + char str_version[33]; + dtostrfd(chirp_sensor[i].version, 0, str_version); + if (json) { + if(!chirp_sensor[i].explicitSleep){ + ResponseAppend_P(PSTR(",\"%s%u\":{\"" D_JSON_MOISTURE "\":%s,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":\"%s}"), + chirp_name, i, str_moisture, str_temperature, str_light);} + else { + ResponseAppend_P(PSTR(",\"%s%u\":{\"sleeping\"}"), + chirp_name, i); + } + #ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(str_temperature, str_moisture); + DomoticzSensor(DZ_ILLUMINANCE,chirp_sensor[i].light); + } + #endif + #ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CHIRPVER, i, chirp_sensor[i].address, str_version); + if (chirp_sensor[i].explicitSleep){ + WSContentSend_PD(HTTP_SNS_CHIRPSLEEP); + } + else { + WSContentSend_PD(HTTP_SNS_MOISTURE, str_moisture); + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, " ", chirp_sensor[i].light); + WSContentSend_PD(HTTP_SNS_TEMP, " ",str_temperature, TempUnit()); + } + + #endif + } + } + } +} + + + + + +bool ChirpCmd(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t disp_len = strlen(D_CMND_CHIRP); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_CHIRP), disp_len)) { + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kCHIRP_Commands); + + switch (command_code) { + case CMND_CHIRP_SELECT: + case CMND_CHIRP_SET: + if (XdrvMailbox.data_len > 0) { + if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(XdrvMailbox.payload); } + if (command_code == CMND_CHIRP_SET) { ChirpSet((uint8_t)XdrvMailbox.payload); } + Response_P(S_JSON_CHIRP_COMMAND_NVALUE, command, XdrvMailbox.payload); + } + else { + if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(255); } + Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); + } + break; + case CMND_CHIRP_SCAN: + case CMND_CHIRP_SLEEP: + case CMND_CHIRP_WAKE: + case CMND_CHIRP_RESET: + if (command_code == CMND_CHIRP_SCAN) { chirp_next_job = 0; + ChirpDetect(); } + if (command_code == CMND_CHIRP_SLEEP) { chirp_sensor[chirp_current].explicitSleep = true; + ChirpSleep(chirp_sensor[chirp_current].address); } + if (command_code == CMND_CHIRP_WAKE) { chirp_sensor[chirp_current].explicitSleep = false; + ChirpReadVersion(chirp_sensor[chirp_current].address); } + if (command_code == CMND_CHIRP_RESET) { ChirpReset(chirp_sensor[chirp_current].address); } + Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); + break; + default: + + serviced = false; + break; + } + } + return serviced; +} + + + + + +bool Xsns48(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + ChirpDetect(); + break; + case FUNC_EVERY_SECOND: + if(chirp_found_sensors > 0){ + ChirpEverySecond(); + } + break; + case FUNC_COMMAND: + result = ChirpCmd(); + break; + case FUNC_JSON_APPEND: + ChirpShow(1); + chirp_next_job = 5; + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + ChirpShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_49_solaxX1.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_49_solaxX1.ino" +#ifdef USE_SOLAX_X1 + + + + +#define XSNS_49 49 + +#ifndef SOLAXX1_SPEED +#define SOLAXX1_SPEED 9600 +#endif + +#define INVERTER_ADDRESS 0x0A + +#define D_SOLAX_X1 "SolaxX1" + +#include + +enum solaxX1_Error +{ + solaxX1_ERR_NO_ERROR, + solaxX1_ERR_CRC_ERROR +}; + +union { + uint32_t ErrMessage; + struct { + + uint8_t TzProtectFault:1; + uint8_t MainsLostFault:1; + uint8_t GridVoltFault:1; + uint8_t GridFreqFault:1; + uint8_t PLLLostFault:1; + uint8_t BusVoltFault:1; + uint8_t ErrBit06:1; + uint8_t OciFault:1; + + uint8_t Dci_OCP_Fault:1; + uint8_t ResidualCurrentFault:1; + uint8_t PvVoltFault:1; + uint8_t Ac10Mins_Voltage_Fault:1; + uint8_t IsolationFault:1; + uint8_t TemperatureOverFault:1; + uint8_t FanFault:1; + uint8_t ErrBit15:1; + + uint8_t SpiCommsFault:1; + uint8_t SciCommsFault:1; + uint8_t ErrBit18:1; + uint8_t InputConfigFault:1; + uint8_t EepromFault:1; + uint8_t RelayFault:1; + uint8_t SampleConsistenceFault:1; + uint8_t ResidualCurrent_DeviceFault:1; + + uint8_t ErrBit24:1; + uint8_t ErrBit25:1; + uint8_t ErrBit26:1; + uint8_t ErrBit27:1; + uint8_t ErrBit28:1; + uint8_t DCI_DeviceFault:1; + uint8_t OtherDeviceFault:1; + uint8_t ErrBit31:1; + }; +} ErrCode; + +const char kSolaxMode[] PROGMEM = D_WAITING "|" D_CHECKING "|" D_WORKING "|" D_FAILURE; + +const char kSolaxError[] PROGMEM = + D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|" + D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8; + + + +TasmotaSerial *solaxX1Serial; + +uint8_t solaxX1_Init = 1; + +uint8_t solaxX1_status = 0; +uint32_t solaxX1_errorCode = 0; + +float solaxX1_temperature = 0; +float solaxX1_energy_today = 0; +float solaxX1_dc1_voltage = 0; +float solaxX1_dc2_voltage = 0; +float solaxX1_dc1_current = 0; +float solaxX1_dc2_current = 0; +float solaxX1_ac_current = 0; +float solaxX1_ac_voltage = 0; +float solaxX1_frequency = 0; +float solaxX1_power = 0; +float solaxX1_energy_total = 0; +float solaxX1_runtime_total = 0; + +float solaxX1_dc1_power = 0; +float solaxX1_dc2_power = 0; + +bool queryOffline = false; +bool queryOfflineSend = false; +bool hasAddress = true; +bool inverterAddressSend = false; +bool inverterSnReceived = false; + +uint8_t header[2] = {0xAA, 0x55}; +uint8_t source[2] = {0x00, 0x00}; +uint8_t destination[2] = {0x00, 0x00}; +uint8_t controlCode[1] = {0x00}; +uint8_t functionCode[1] = {0x00}; +uint8_t dataLength[1] = {0x00}; +uint8_t data[16] = {0}; + +uint8_t message[30]; + + + +bool solaxX1_RS485ReceiveReady(void) +{ + return (solaxX1Serial->available() > 1); +} + +void solaxX1_RS485Send(uint8_t *msg, uint16_t msgLen) +{ + + uint16_t crc = solaxX1_calculateCRC(msg, msgLen - 1); + + while (solaxX1Serial->available() > 0) + { + solaxX1Serial->read(); + } + + solaxX1Serial->flush(); + solaxX1Serial->write(msg, msgLen); + solaxX1Serial->write(highByte(crc)); + solaxX1Serial->write(lowByte(crc)); +} + +uint8_t solaxX1_RS485Receive(uint8_t *value) +{ + uint8_t len = 0; + + while (solaxX1Serial->available() > 0) + { + value[len++] = (uint8_t)solaxX1Serial->read(); + } + + uint16_t crc = solaxX1_calculateCRC(value, len - 3); + + if (value[len - 1] == lowByte(crc) && value[len - 2] == highByte(crc)) + { + return solaxX1_ERR_NO_ERROR; + } + else + { + return solaxX1_ERR_CRC_ERROR; + } +} + +uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) +{ + uint8_t i; + uint16_t wChkSum; + wChkSum = 0; + + for (i = 0; i <= bLen; i++) + { + wChkSum = wChkSum + bExternTxPackage[i]; + } + return wChkSum; +} + +void solaxX1_setMessage(uint8_t *message) +{ + memcpy(message, header, 2); + memcpy(message + 2, source, 2); + memcpy(message + 4, destination, 2); + memcpy(message + 6, controlCode, 1); + memcpy(message + 7, functionCode, 1); + memcpy(message + 8, dataLength, 1); + memcpy(message + 9, data, sizeof(data)); +} + +void solaxX1_SendInverterAddress() +{ + source[0] = 0x00; + destination[0] = 0x00; + destination[1] = 0x00; + controlCode[0] = 0x10; + functionCode[0] = 0x01; + dataLength[0] = 0x0F; + + + data[14] = INVERTER_ADDRESS; + + solaxX1_setMessage(message); + solaxX1_RS485Send(message, 24); +} + +void solaxX1_QueryLiveData() +{ + source[0] = 0x01; + destination[0] = 0x00; + destination[1] = INVERTER_ADDRESS; + controlCode[0] = 0x11; + functionCode[0] = 0x02; + dataLength[0] = 0x00; + + solaxX1_setMessage(message); + solaxX1_RS485Send(message, 9); +} + +uint8_t solaxX1_ParseErrorCode(uint32_t code){ + ErrCode.ErrMessage = code; + + if (code == 0) return 0; + if (ErrCode.MainsLostFault) return 1; + if (ErrCode.GridVoltFault) return 2; + if (ErrCode.GridFreqFault) return 3; + if (ErrCode.PvVoltFault) return 4; + if (ErrCode.IsolationFault) return 5; + if (ErrCode.TemperatureOverFault) return 6; + if (ErrCode.FanFault) return 7; + if (ErrCode.OtherDeviceFault) return 8; +} + + + +uint8_t solaxX1_send_retry = 0; +uint8_t solaxX1_nodata_count = 0; + +void solaxX1_Update(void) +{ + uint8_t value[61] = {0}; + + bool data_ready = solaxX1_RS485ReceiveReady(); + + DEBUG_SENSOR_LOG(PSTR("SX1: queryOffline: %d , queryOfflineSend: %d, hasAddress: %d, inverterAddressSend: %d, solaxX1_send_retry: %d"), + queryOffline, queryOfflineSend, hasAddress, inverterAddressSend, solaxX1_send_retry); + + if (!hasAddress && (data_ready || solaxX1_send_retry == 0)) + { + + if (data_ready) + { + + if (inverterAddressSend) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Address confirmation response CRC error")); + } + else + { + if (value[6] == 0x10 && value[7] == 0x81 && value[9] == 0x06) + { + inverterAddressSend = false; + queryOfflineSend = false; + hasAddress = true; + } + } + } + + + if (queryOfflineSend) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline response CRC error")); + } + else + { + + if (value[6] == 0x10 && value[7] == 0x80 && inverterSnReceived == false) + { + for (uint8_t i = 9; i <= 22; i++) + { + data[i - 9] = value[i]; + } + inverterSnReceived = true; + } + + solaxX1_SendInverterAddress(); + + inverterAddressSend = true; + queryOfflineSend = false; + queryOffline = false; + } + } + } + + + if (queryOffline) + { + + source[0] = 0x01; + destination[1] = 0x00; + controlCode[0] = 0x10; + functionCode[0] = 0x00; + dataLength[0] = 0x00; + + solaxX1_setMessage(message); + solaxX1_RS485Send(message, 9); + + queryOfflineSend = true; + queryOffline = false; + } + + if (solaxX1_send_retry == 0) + { + + if (inverterAddressSend) + { + solaxX1_SendInverterAddress(); + } + if (queryOfflineSend) + { + queryOffline = true; + queryOfflineSend = false; + } + solaxX1_send_retry = 2; + } + + } + + if (hasAddress && (data_ready || solaxX1_send_retry == 0)) + { + + if (data_ready) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error")); + } + else + { + + + solaxX1_nodata_count = 0; + solaxX1_send_retry = 2; + uint32_t temporal = 0; + + temporal = (value[9] << 8) | value[10]; + solaxX1_temperature = temporal; + + temporal = (value[11] << 8) | value[12]; + solaxX1_energy_today = temporal * 0.1f; + + temporal = (value[13] << 8) | value[14]; + solaxX1_dc1_voltage = temporal * 0.1f; + + temporal = (value[15] << 8) | value[16]; + solaxX1_dc2_voltage = temporal * 0.1f; + + temporal = (value[17] << 8) | value[18]; + solaxX1_dc1_current = temporal * 0.1f; + + temporal = (value[19] << 8) | value[20]; + solaxX1_dc2_current = temporal * 0.1f; + + temporal = (value[21] << 8) | value[22]; + solaxX1_ac_current = temporal * 0.1f; + + temporal = (value[23] << 8) | value[24]; + solaxX1_ac_voltage = temporal * 0.1f; + + temporal = (value[25] << 8) | value[26]; + solaxX1_frequency = temporal * 0.01f; + + temporal = (value[27] << 8) | value[28]; + solaxX1_power = temporal; + + + + + temporal = (value[31] << 8) | (value[32] << 8) | (value[33] << 8) | value[34]; + solaxX1_energy_total = temporal * 0.1f; + + temporal = (value[35] << 8) | (value[36] << 8) | (value[37] << 8) | value[38]; + solaxX1_runtime_total = temporal; + + temporal = (value[39] << 8) | value[40]; + solaxX1_status = (uint8_t)temporal; +# 412 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_49_solaxX1.ino" + temporal = (value[58] << 8) | (value[57] << 8) | (value[56] << 8) | value[55]; + solaxX1_errorCode = (uint32_t)temporal; + + solaxX1_dc1_power = solaxX1_dc1_voltage * solaxX1_dc1_current; + solaxX1_dc2_power = solaxX1_dc2_voltage * solaxX1_dc2_current; + + solaxX1_QueryLiveData(); + } + } + + if (solaxX1_send_retry == 0) + { + solaxX1_send_retry = 2; + solaxX1_QueryLiveData(); + } + } + else + { + + if (solaxX1_nodata_count <= 10) + { + solaxX1_nodata_count++; + } + else if (solaxX1_nodata_count != 255) + { + + solaxX1_nodata_count = 255; + queryOffline = true; + queryOfflineSend = false; + hasAddress = false; + inverterAddressSend = false; + inverterSnReceived = false; + + solaxX1_temperature = solaxX1_dc1_voltage = solaxX1_dc2_voltage = solaxX1_dc1_current = solaxX1_dc2_current = solaxX1_ac_current = 0; + solaxX1_ac_voltage = solaxX1_frequency = solaxX1_power = solaxX1_dc1_power = solaxX1_dc2_power = solaxX1_status = 0; + + + } + } + + if (!data_ready) + solaxX1_send_retry--; +} + +void solaxX1Init(void) +{ + AddLog_P(LOG_LEVEL_DEBUG, PSTR("Solax X1 Inverter Init")); + DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX]); + solaxX1_Init = 0; + if ((pin[GPIO_SOLAXX1_RX] < 99) && (pin[GPIO_SOLAXX1_TX] < 99)) + { + solaxX1Serial = new TasmotaSerial(pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX], 1); + if (solaxX1Serial->begin(SOLAXX1_SPEED)) + { + if (solaxX1Serial->hardwareSerial()) + { + ClaimSerial(); + } + solaxX1_Init = 1; + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_solaxX1_DATA1[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}" D_SOLAX_X1 " " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}" D_SOLAX_X1 " " D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}" + "{s}" D_SOLAX_X1 " " D_INVERTER_POWER "{m}%s " D_UNIT_WATT "{e}" + "{s}" D_SOLAX_X1 " " D_SOLAR_POWER "{m}%s " D_UNIT_WATT "{e}" + "{s}" D_SOLAX_X1 " " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_SOLAX_X1 " " D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_POWER "{m}%s " D_UNIT_WATT "{e}"; +#ifdef SOLAXX1_PV2 +const char HTTP_SNS_solaxX1_DATA2[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_PV2_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}" D_SOLAX_X1 " " D_PV2_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}"; +#endif +const char HTTP_SNS_solaxX1_DATA3[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%s " D_UNIT_HOUR "{e}" + "{s}" D_SOLAX_X1 " " D_STATUS "{m}%s" + "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s"; +#endif + +void solaxX1Show(bool json) +{ + char voltage[33]; + dtostrfd(solaxX1_ac_voltage, Settings.flag2.voltage_resolution, voltage); + char current[33]; + dtostrfd(solaxX1_ac_current, Settings.flag2.current_resolution, current); + char inverter_power[33]; + dtostrfd(solaxX1_power, Settings.flag2.wattage_resolution, inverter_power); + char solar_power[33]; + dtostrfd(solaxX1_dc1_power + solaxX1_dc2_power, Settings.flag2.wattage_resolution, solar_power); + char frequency[33]; + dtostrfd(solaxX1_frequency, Settings.flag2.frequency_resolution, frequency); + char energy_total[33]; + dtostrfd(solaxX1_energy_total, Settings.flag2.energy_resolution, energy_total); + char energy_today[33]; + dtostrfd(solaxX1_energy_today, Settings.flag2.energy_resolution, energy_today); + char pv1_voltage[33]; + dtostrfd(solaxX1_dc1_voltage, Settings.flag2.voltage_resolution, pv1_voltage); + char pv1_current[33]; + dtostrfd(solaxX1_dc1_current, Settings.flag2.current_resolution, pv1_current); + char pv1_power[33]; + dtostrfd(solaxX1_dc1_power, Settings.flag2.wattage_resolution, pv1_power); +#ifdef SOLAXX1_PV2 + char pv2_voltage[33]; + dtostrfd(solaxX1_dc2_voltage, Settings.flag2.voltage_resolution, pv2_voltage); + char pv2_current[33]; + dtostrfd(solaxX1_dc2_current, Settings.flag2.current_resolution, pv2_current); + char pv2_power[33]; + dtostrfd(solaxX1_dc2_power, Settings.flag2.wattage_resolution, pv2_power); +#endif + char temperature[33]; + dtostrfd(solaxX1_temperature, Settings.flag2.temperature_resolution, temperature); + char runtime[33]; + dtostrfd(solaxX1_runtime_total, 0, runtime); + char status[33]; + GetTextIndexed(status, sizeof(status), solaxX1_status, kSolaxMode); + + if (json) + { + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" + D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_TOTAL "\":%s,\"" D_JSON_TODAY "\":%s,\"" + D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"), + voltage, current, inverter_power, + solar_power, frequency, energy_total, energy_today, + pv1_voltage, pv1_current, pv1_power); +#ifdef SOLAXX1_PV2 + ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), + pv2_voltage, pv2_current, pv2_power); +#endif + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d}"), + temperature, runtime, status, solaxX1_errorCode); + + +#ifdef USE_DOMOTICZ + if (0 == tele_period) + { + char energy_total_chr[33]; + dtostrfd(solaxX1_energy_total * 1000, 1, energy_total_chr); + + DomoticzSensor(DZ_VOLTAGE, voltage); + DomoticzSensor(DZ_CURRENT, current); + + if (solaxX1_temperature > 0) DomoticzSensor(DZ_TEMP, temperature); + if (solaxX1_energy_total > 0) DomoticzSensorPowerEnergy((int)solaxX1_power, energy_total_chr); + } +#endif +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_SNS_solaxX1_DATA1, voltage, current, frequency, inverter_power, solar_power, energy_total, energy_today, pv1_voltage, pv1_current, pv1_power); +#ifdef SOLAXX1_PV2 + WSContentSend_PD(HTTP_SNS_solaxX1_DATA2, pv2_voltage, pv2_current, pv2_power); +#endif + WSContentSend_PD(HTTP_SNS_TEMP, D_SOLAX_X1, temperature, TempUnit()); + char errorCodeString[33]; + WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, runtime, status, + GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1_errorCode), kSolaxError)); +#endif + } +} + + + + + +bool Xsns49(uint8_t function) +{ + bool result = false; + + if (solaxX1_Init) + { + switch (function) + { + case FUNC_INIT: + solaxX1Init(); + break; + case FUNC_EVERY_SECOND: + solaxX1_Update(); + break; + case FUNC_JSON_APPEND: + solaxX1Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + solaxX1Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_50_paj7620.ino" +# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_50_paj7620.ino" +#ifdef USE_I2C +#ifdef USE_PAJ7620 + + + + + + + +#define XSNS_50 50 + +#define PAJ7620_ADDR 0x73 + +#define PAJ7620_BANK_SEL 0xEF + + + +#define PAJ7620_GET_GESTURE 0x43 +#define PAJ7620_PROXIMITY_AVG_Y 0x6c + +#define PAJ7620_OBJECT_CENTER_X 0xad +#define PAJ7620_OBJECT_CENTER_Y 0xaf + +#define PAJ7620_DOWN 1 +#define PAJ7620_UP 2 +#define PAJ7620_RIGHT 4 +#define PAJ7620_LEFT 8 +#define PAJ7620_NEAR 16 +#define PAJ7620_FAR 32 +#define PAJ7620_CW 64 +#define PAJ7620_CCW 128 + + + + +const uint8_t PAJ7620initRegisterArray[][2] PROGMEM = { + {0xEF,0x00}, + {0x32,0x29}, {0x33,0x01}, {0x34,0x00}, {0x35,0x01}, {0x36,0x00}, {0x37,0x07}, {0x38,0x17}, {0x39,0x06}, + {0x3A,0x12}, {0x3F,0x00}, {0x40,0x02}, {0x41,0xFF}, {0x42,0x01}, {0x46,0x2D}, {0x47,0x0F}, {0x48,0x3C}, + {0x49,0x00}, {0x4A,0x1E}, {0x4B,0x00}, {0x4C,0x20}, {0x4D,0x00}, {0x4E,0x1A}, {0x4F,0x14}, {0x50,0x00}, + {0x51,0x10}, {0x52,0x00}, {0x5C,0x02}, {0x5D,0x00}, {0x5E,0x10}, {0x5F,0x3F}, {0x60,0x27}, {0x61,0x28}, + {0x62,0x00}, {0x63,0x03}, {0x64,0xF7}, {0x65,0x03}, {0x66,0xD9}, {0x67,0x03}, {0x68,0x01}, {0x69,0xC8}, + {0x6A,0x40}, {0x6D,0x04}, {0x6E,0x00}, {0x6F,0x00}, {0x70,0x80}, {0x71,0x00}, {0x72,0x00}, {0x73,0x00}, + {0x74,0xF0}, {0x75,0x00}, {0x80,0x42}, {0x81,0x44}, {0x82,0x04}, {0x83,0x20}, {0x84,0x20}, {0x85,0x00}, + {0x86,0x10}, {0x87,0x00}, {0x88,0x05}, {0x89,0x18}, {0x8A,0x10}, {0x8B,0x01}, {0x8C,0x37}, {0x8D,0x00}, + {0x8E,0xF0}, {0x8F,0x81}, {0x90,0x06}, {0x91,0x06}, {0x92,0x1E}, {0x93,0x0D}, {0x94,0x0A}, {0x95,0x0A}, + {0x96,0x0C}, {0x97,0x05}, {0x98,0x0A}, {0x99,0x41}, {0x9A,0x14}, {0x9B,0x0A}, {0x9C,0x3F}, {0x9D,0x33}, + {0x9E,0xAE}, {0x9F,0xF9}, {0xA0,0x48}, {0xA1,0x13}, {0xA2,0x10}, {0xA3,0x08}, {0xA4,0x30}, {0xA5,0x19}, + {0xA6,0x10}, {0xA7,0x08}, {0xA8,0x24}, {0xA9,0x04}, {0xAA,0x1E}, {0xAB,0x1E}, {0xCC,0x19}, {0xCD,0x0B}, + {0xCE,0x13}, {0xCF,0x64}, {0xD0,0x21}, {0xD1,0x0F}, {0xD2,0x88}, {0xE0,0x01}, {0xE1,0x04}, {0xE2,0x41}, + {0xE3,0xD6}, {0xE4,0x00}, {0xE5,0x0C}, {0xE6,0x0A}, {0xE7,0x00}, {0xE8,0x00}, {0xE9,0x00}, {0xEE,0x07}, + {0xEF,0x01}, + {0x00,0x1E}, {0x01,0x1E}, {0x02,0x0F}, {0x03,0x10}, {0x04,0x02}, {0x05,0x00}, {0x06,0xB0}, {0x07,0x04}, + {0x08,0x0D}, {0x09,0x0E}, {0x0A,0x9C}, {0x0B,0x04}, {0x0C,0x05}, {0x0D,0x0F}, {0x0E,0x02}, {0x0F,0x12}, + {0x10,0x02}, {0x11,0x02}, {0x12,0x00}, {0x13,0x01}, {0x14,0x05}, {0x15,0x07}, {0x16,0x05}, {0x17,0x07}, + {0x18,0x01}, {0x19,0x04}, {0x1A,0x05}, {0x1B,0x0C}, {0x1C,0x2A}, {0x1D,0x01}, {0x1E,0x00}, {0x21,0x00}, + {0x22,0x00}, {0x23,0x00}, {0x25,0x01}, {0x26,0x00}, {0x27,0x39}, {0x28,0x7F}, {0x29,0x08}, {0x30,0x03}, + {0x31,0x00}, {0x32,0x1A}, {0x33,0x1A}, {0x34,0x07}, {0x35,0x07}, {0x36,0x01}, {0x37,0xFF}, {0x38,0x36}, + {0x39,0x07}, {0x3A,0x00}, {0x3E,0xFF}, {0x3F,0x00}, {0x40,0x77}, {0x41,0x40}, {0x42,0x00}, {0x43,0x30}, + {0x44,0xA0}, {0x45,0x5C}, {0x46,0x00}, {0x47,0x00}, {0x48,0x58}, {0x4A,0x1E}, {0x4B,0x1E}, {0x4C,0x00}, + {0x4D,0x00}, {0x4E,0xA0}, {0x4F,0x80}, {0x50,0x00}, {0x51,0x00}, {0x52,0x00}, {0x53,0x00}, {0x54,0x00}, + {0x57,0x80}, {0x59,0x10}, {0x5A,0x08}, {0x5B,0x94}, {0x5C,0xE8}, {0x5D,0x08}, {0x5E,0x3D}, {0x5F,0x99}, + {0x60,0x45}, {0x61,0x40}, {0x63,0x2D}, {0x64,0x02}, {0x65,0x96}, {0x66,0x00}, {0x67,0x97}, {0x68,0x01}, + {0x69,0xCD}, {0x6A,0x01}, {0x6B,0xB0}, {0x6C,0x04}, {0x6D,0x2C}, {0x6E,0x01}, {0x6F,0x32}, {0x71,0x00}, + {0x72,0x01}, {0x73,0x35}, {0x74,0x00}, {0x75,0x33}, {0x76,0x31}, {0x77,0x01}, {0x7C,0x84}, {0x7D,0x03}, + {0x7E,0x01}, + {0xEF,0x00} +}; + + + + + +#define D_CMND_PAJ7620 "PAJ7620" + +const char S_JSON_PAJ7620_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_PAJ7620 "%s\":%d}"; + +const char kPAJ7620Types[] PROGMEM = "PAJ7620"; + +const uint8_t PAJ7620_PIN[]= {1,2,3,4}; + + + + + + +void PAJ7620SelectBank(uint8_t bank) +{ + switch(bank){ + case 0: + I2cWrite(PAJ7620_ADDR, PAJ7620_BANK_SEL, 0, 1); + break; + case 1: + I2cWrite(PAJ7620_ADDR, PAJ7620_BANK_SEL, 1, 1); + break; + default: + break; + } +} + + + +void PAJ7620TriggerTele(){ + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +#ifdef USE_RULES + RulesTeleperiod(); +#endif + } +} + + + + + +char PAJ7620_name[9]; + +uint32_t PAJ7620_timeout_counter = 10; +uint32_t PAJ7620_next_job = 0; +uint32_t PAJ7620_mode = 1; + +struct { + uint8_t current; + uint8_t last; + uint8_t same; + uint8_t unfinished; +} PAJ7620_gesture; + +bool PAJ7620_finished_gesture = false; +char PAJ7620_currentGestureName[6]; + +struct{ + uint8_t x; + uint8_t y; + uint8_t last_x; + uint8_t last_y; + uint8_t proximity; + uint8_t last_proximity; + uint8_t corner; + struct { + uint8_t step:3; + uint8_t countdown:3; + uint8_t valid:1; + } PIN; +} PAJ7620_state; + + + + +void PAJ7620DecodeGesture(void) +{ + switch (PAJ7620_gesture.current) { + case PAJ7620_DOWN: + DEBUG_SENSOR_LOG(PSTR("DOWN")); + snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("Down")); + if(PAJ7620_gesture.unfinished){ + PAJ7620_finished_gesture = true; + break; + } + PAJ7620_gesture.unfinished = PAJ7620_gesture.current; + PAJ7620_timeout_counter = 5; + break; + case PAJ7620_UP: + DEBUG_SENSOR_LOG(PSTR("UP")); + snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("Up")); + if(PAJ7620_gesture.unfinished){ + PAJ7620_finished_gesture = true; + break; + } + PAJ7620_gesture.unfinished = PAJ7620_gesture.current; + PAJ7620_timeout_counter = 5; + break; + case PAJ7620_RIGHT: + DEBUG_SENSOR_LOG(PSTR("RIGHT")); + snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("Right")); + if(PAJ7620_gesture.unfinished){ + PAJ7620_finished_gesture = true; + break; + } + PAJ7620_gesture.unfinished = PAJ7620_gesture.current; + PAJ7620_timeout_counter = 5; + break; + case PAJ7620_LEFT: + DEBUG_SENSOR_LOG(PSTR("LEFT")); + snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("Left")); + if(PAJ7620_gesture.unfinished){ + PAJ7620_finished_gesture = true; + break; + } + PAJ7620_gesture.unfinished = PAJ7620_gesture.current; + PAJ7620_timeout_counter = 5; + break; + case PAJ7620_NEAR: + DEBUG_SENSOR_LOG(PSTR("NEAR")); + snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("Near")); + PAJ7620_finished_gesture = true; + PAJ7620_timeout_counter = 25; + break; + case PAJ7620_FAR: + DEBUG_SENSOR_LOG(PSTR("FAR")); + snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("Far")); + PAJ7620_finished_gesture = true; + PAJ7620_timeout_counter = 25; + break; + case PAJ7620_CW: + DEBUG_SENSOR_LOG(PSTR("ClockWise")); + snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("CW")); + PAJ7620_finished_gesture = true; + break; + case PAJ7620_CCW: + DEBUG_SENSOR_LOG(PSTR("CounterClockWise")); + snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("CCW")); + PAJ7620_finished_gesture = true; + break; + default: + if(PAJ7620_gesture.unfinished){ + PAJ7620_finished_gesture = true; + break; + } + break; + } +if(PAJ7620_finished_gesture){ + if (PAJ7620_gesture.unfinished){ + if(PAJ7620_gesture.current!=PAJ7620_NEAR && PAJ7620_gesture.current!=PAJ7620_FAR){ + PAJ7620_gesture.current = PAJ7620_gesture.unfinished; + } + } + if (PAJ7620_gesture.current == PAJ7620_gesture.last){ + PAJ7620_gesture.same++; + } + else{ + PAJ7620_gesture.same = 1; + } + PAJ7620_gesture.last = PAJ7620_gesture.current; + PAJ7620_finished_gesture = false; + PAJ7620_gesture.unfinished = 0; + PAJ7620_timeout_counter += 3; + PAJ7620TriggerTele(); + } +} + + +void PAJ7620ReadGesture(void){ + switch(PAJ7620_mode){ + case 1: + PAJ7620_gesture.current = I2cRead8(PAJ7620_ADDR,PAJ7620_GET_GESTURE); + if(PAJ7620_gesture.current > 0 || PAJ7620_gesture.unfinished){ + DEBUG_SENSOR_LOG(PSTR("PAJ7620: gesture: %u"),PAJ7620_gesture.current ); + PAJ7620DecodeGesture(); + } + + break; + case 2: + PAJ7620_state.proximity = I2cRead8(PAJ7620_ADDR, PAJ7620_PROXIMITY_AVG_Y); + if((PAJ7620_state.proximity>0)||(PAJ7620_state.last_proximity>0)) + { + if(PAJ7620_state.proximity!=PAJ7620_state.last_proximity){ + PAJ7620_state.last_proximity = PAJ7620_state.proximity; + DEBUG_SENSOR_LOG(PSTR("PAJ7620: Proximity: %u"),PAJ7620_state.proximity ); + PAJ7620TriggerTele(); + } + } + break; + case 3: case 4: case 5: + PAJ7620_state.x = I2cRead8(PAJ7620_ADDR, PAJ7620_OBJECT_CENTER_X); + PAJ7620_state.y = I2cRead8(PAJ7620_ADDR, PAJ7620_OBJECT_CENTER_Y); + if(PAJ7620_state.y>0 && PAJ7620_state.x>0){ + if(PAJ7620_state.y!=PAJ7620_state.last_y || PAJ7620_state.x!=PAJ7620_state.last_x){ + PAJ7620_state.last_y = PAJ7620_state.y; + PAJ7620_state.last_x = PAJ7620_state.x; + DEBUG_SENSOR_LOG(PSTR("PAJ7620: x: %u y: %u"), PAJ7620_state.x, PAJ7620_state.y); + + PAJ7620_state.corner = 0; + + + + switch(PAJ7620_state.y){ + case 0: case 1: case 2: case 3: case 4: case 5: + PAJ7620_state.corner = 3; + break; + case 9: case 10: case 11: case 12: case 13: case 14: + PAJ7620_state.corner = 1; + break; + default: + break; + } + if(PAJ7620_state.corner!=0){ + switch(PAJ7620_state.x){ + case 0: case 1: case 2: case 3: case 4: case 5: + break; + case 9: case 10: case 11: case 12: case 13: case 14: + PAJ7620_state.corner++; + break; + default: + PAJ7620_state.corner = 0; + break; + } + } + DEBUG_SENSOR_LOG(PSTR("PAJ7620: corner: %u"), PAJ7620_state.corner); + + if(PAJ7620_state.PIN.countdown == 0){ + PAJ7620_state.PIN.step=0; + PAJ7620_state.PIN.valid=0; + } + if(!PAJ7620_state.PIN.step){ + if(PAJ7620_state.corner == PAJ7620_PIN[PAJ7620_state.PIN.step]){ + PAJ7620_state.PIN.step=1; + PAJ7620_state.PIN.countdown=7; + } + } + else{ + if(PAJ7620_state.corner == PAJ7620_PIN[PAJ7620_state.PIN.step]){ + PAJ7620_state.PIN.step+=1; + PAJ7620_state.PIN.countdown=7; + } + else{ + PAJ7620_state.PIN.countdown-=1; + } + } + if(PAJ7620_state.PIN.step == 4){ + PAJ7620_state.PIN.valid = 1; + DEBUG_SENSOR_LOG(PSTR("PAJ7620: PIN valid!!")); + PAJ7620_state.PIN.countdown = 0; + } + PAJ7620TriggerTele(); + } + } + break; + default: + break; + } +} + + + +void PAJ7620Detect(void) +{ + DEBUG_SENSOR_LOG(PSTR("PAJ7620: scan will start ...")); + PAJ7620SelectBank(0); + PAJ7620SelectBank(0); + uint16_t PAJ7620_id = I2cRead16LE(PAJ7620_ADDR,0); + uint8_t PAJ7620_ver = I2cRead8(PAJ7620_ADDR,2); + if (PAJ7620_id == 0x7620) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAJ7620: sensor found with ID: 0x%x and VER: %u"), PAJ7620_id, PAJ7620_ver); + uint8_t PAJ7620_model = 0; + GetTextIndexed(PAJ7620_name, sizeof(PAJ7620_name), PAJ7620_model, kPAJ7620Types); + PAJ7620_next_job = 1; + } + else { + DEBUG_SENSOR_LOG(PSTR("PAJ7620: sensor not found, false ID 0x%x"), PAJ7620_id); + PAJ7620_next_job = 255; + } +} + + +void PAJ7620Init(void) +{ + DEBUG_SENSOR_LOG(PSTR("PAJ7620: init sensor start %u"),millis()); + union{ + uint32_t raw; + uint8_t reg_val[4]; + } buf; + for(uint32_t i = 0; i < (sizeof(PAJ7620initRegisterArray)/2); i+=2) + { + buf.raw = pgm_read_dword(PAJ7620initRegisterArray+i); + DEBUG_SENSOR_LOG("%x %x %x %x",buf.reg_val[0],buf.reg_val[1],buf.reg_val[2],buf.reg_val[3]); + I2cWrite(PAJ7620_ADDR, buf.reg_val[0], buf.reg_val[1], 1); + I2cWrite(PAJ7620_ADDR, buf.reg_val[2], buf.reg_val[3], 1); + } + DEBUG_SENSOR_LOG(PSTR("PAJ7620: init sensor done %u"),millis()); + PAJ7620_next_job = 2; +} + + + +void PAJ7620SelectMode(uint16_t mode){ + DEBUG_SENSOR_LOG(PSTR("PAJ7620: set mode to %u"),mode); + switch(mode){ + case 0: + PAJ7620_mode = 0; + break; + case 1: + PAJ7620_mode = 1; + break; + case 2: + PAJ7620_mode = 2; + break; + case 3: + PAJ7620_mode = 3; + break; + case 4: + PAJ7620_mode = 4; + break; + case 5: + PAJ7620_mode = 5; + break; + default: + break; + } +} + + +void PAJ7620Loop(void) +{ + if(PAJ7620_timeout_counter == 0){ + switch(PAJ7620_next_job){ + case 0: + PAJ7620Detect(); + break; + case 1: + PAJ7620Init(); + break; + case 2: + if(PAJ7620_mode != 0){ + PAJ7620ReadGesture(); + } + break; + default: + break; + } + } + else { + PAJ7620_timeout_counter--; + } +} + + + + +#define D_JSON_PAJ7620 "PAJ7620" + +#ifdef USE_WEBSERVER + + + const char HTTP_SNS_PAJ7620[] PROGMEM = "{s} " D_JSON_PAJ7620 ": {m}%s {e}"; + const char HTTP_SNS_PAJ7620VER[] PROGMEM = "{s} PAJ7620 at address: {m}0x73{e}" + "{s} version: {m}1 {e}"; + +#endif + + + + +void PAJ7620Show(bool json) +{ + if (json) { + if((PAJ7620_currentGestureName[0] != '\0' )){ + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), PAJ7620_name, PAJ7620_currentGestureName, PAJ7620_gesture.same); + PAJ7620_currentGestureName[0] = '\0'; + return; + } + switch(PAJ7620_mode){ + case 2: + if(PAJ7620_mode>1){ + ResponseAppend_P(PSTR(",\"%s\":{\"Proximity\":%u}"), PAJ7620_name, PAJ7620_state.proximity); + } + break; + case 3: + if(PAJ7620_mode>1 && PAJ7620_state.corner>0){ + ResponseAppend_P(PSTR(",\"%s\":{\"Corner\":%u}"), PAJ7620_name, PAJ7620_state.corner); + } + break; + case 4: + if(PAJ7620_mode>1 && PAJ7620_state.PIN.valid){ + ResponseAppend_P(PSTR(",\"%s\":{\"PIN\":%u}"), PAJ7620_name, 1); + PAJ7620_state.PIN.valid = 0; + } + break; + case 5: + if(PAJ7620_mode>1){ + ResponseAppend_P(PSTR(",\"%s\":{\"x\":%u,\"y\":%u}"), PAJ7620_name, PAJ7620_state.x, PAJ7620_state.y); + } + break; + default: + break; + } + #ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_PAJ7620VER); + #endif + } +} + + + + + +bool PAJ7620Cmd(void) { + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + DEBUG_SENSOR_LOG(PSTR("PAJ7620: got argument for mode")); + PAJ7620SelectMode(XdrvMailbox.payload); + Response_P(S_JSON_PAJ7620_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); + } + else { + DEBUG_SENSOR_LOG(PSTR("PAJ7620: show mode")); + Response_P(S_JSON_PAJ7620_COMMAND_NVALUE, XdrvMailbox.command, PAJ7620_mode); + } + return serviced; +} + + + + + +bool Xsns50(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + DEBUG_SENSOR_LOG(PSTR("PAJ7620: 1 second until init")); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_50 == XdrvMailbox.index){ + result = PAJ7620Cmd(); + } + break; + case FUNC_EVERY_100_MSECOND: + if(PAJ7620_next_job <255) { + PAJ7620Loop(); + } + break; + case FUNC_JSON_APPEND: + PAJ7620Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + PAJ7620Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_51_rdm6300.ino" +# 21 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_51_rdm6300.ino" +#ifdef USE_RDM6300 + +#define XSNS_51 51 + +#define RDM6300_BAUDRATE 9600 + +#include + +#define RDM_TIMEOUT 100 +char rdm_uid_str[10]; + + +#define RDM6300_BLOCK 2*10 + +uint8_t rdm_blcnt; +TasmotaSerial *RDM6300_Serial = nullptr; + +void RDM6300_Init() { + if (pin[GPIO_RDM6300_RX] < 99) { + RDM6300_Serial = new TasmotaSerial(pin[GPIO_RDM6300_RX],-1,1); + if (RDM6300_Serial->begin(RDM6300_BAUDRATE)) { + if (RDM6300_Serial->hardwareSerial()) { + ClaimSerial(); + } + } + } + rdm_blcnt=0; +} + + +void RDM6300_ScanForTag() { + char rdm_buffer[14]; + uint8_t rdm_index; + uint8_t rdm_array[6]; + + if (!RDM6300_Serial) return; + + if (rdm_blcnt>0) { + rdm_blcnt--; + while (RDM6300_Serial->available()) RDM6300_Serial->read(); + return; + } + + if (RDM6300_Serial->available()) { + + char c=RDM6300_Serial->read(); + if (c!=2) return; + + + rdm_index=0; + uint32_t cmillis=millis(); + while (1) { + if (RDM6300_Serial->available()) { + char c=RDM6300_Serial->read(); + if (c==3) { + + break; + } + rdm_buffer[rdm_index++]=c; + if (rdm_index>13) { + + return; + } + } + if ((millis()-cmillis)>RDM_TIMEOUT) { + + return; + } + } + + + rdm_blcnt=RDM6300_BLOCK; + + + rm6300_hstring_to_array(rdm_array,sizeof(rdm_array),rdm_buffer); + uint8_t accu=0; + for (uint8_t count=0;count<5;count++) { + accu^=rdm_array[count]; + } + if (accu!=rdm_array[5]) { + + return; + } + + + memcpy(rdm_uid_str,&rdm_buffer[2],8); + rdm_uid_str[9]=0; + + ResponseTime_P(PSTR(",\"RDM6300\":{\"UID\":\"%s\"}}"), rdm_uid_str); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + + + + + + } + + +} + +uint8_t rm6300_hexnibble(char chr) { + uint8_t rVal = 0; + if (isdigit(chr)) { + rVal = chr - '0'; + } else { + if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; + if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; + } + return rVal; +} + + +void rm6300_hstring_to_array(uint8_t array[], uint8_t len, char buffer[]) +{ + char *cp=buffer; + for (uint8_t i = 0; i < len; i++) { + uint8_t val = rm6300_hexnibble(*cp++) << 4; + array[i]= val | rm6300_hexnibble(*cp++); + } +} + +#ifdef USE_WEBSERVER +const char HTTP_RDM6300[] PROGMEM = + "{s}RDM6300 " "UID" "{m}%s" "{e}"; + +void RDM6300_Show(void) { + if (!RDM6300_Serial) return; + if (!rdm_uid_str[0]) strcpy(rdm_uid_str,"????"); + WSContentSend_PD(HTTP_RDM6300,rdm_uid_str); +} +#endif + + + + + +bool Xsns51(byte function) +{ + bool result = false; + + switch (function) { + case FUNC_INIT: + RDM6300_Init(); + break; + case FUNC_EVERY_100_MSECOND: + RDM6300_ScanForTag(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + RDM6300_Show(); + break; +#endif + } + return result; +} + +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_52_ibeacon.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_52_ibeacon.ino" +#ifdef USE_IBEACON + + + +#define XSNS_52 52 + +#include + +#define HM17_BAUDRATE 9600 + + + + +#define IB_TIMEOUT_INTERVAL 30 + +#define IB_UPDATE_TIME_INTERVAL 10 + +TasmotaSerial *IBEACON_Serial = nullptr; + + +uint8_t hm17_found,hm17_cmd,hm17_flag; + +#ifdef IBEACON_DEBUG +uint8_t hm17_debug=0; +#endif + + + +#define HM17_BSIZ 128 +char hm17_sbuffer[HM17_BSIZ]; +uint8_t hm17_sindex,hm17_result,hm17_scanning,hm17_connecting; +uint32_t hm17_lastms; +char ib_mac[14]; + + +#if 1 +uint8_t ib_upd_interval,ib_tout_interval; +#define IB_UPDATE_TIME ib_upd_interval +#define IB_TIMEOUT_TIME ib_tout_interval +#else +#undef IB_UPDATE_TIME +#undef IB_TIMEOUT_TIME +#define IB_UPDATE_TIME Settings.ib_upd_interval +#define IB_TIMEOUT_TIME Settings.ib_tout_interval +#endif + +enum {HM17_TEST,HM17_ROLE,HM17_IMME,HM17_DISI,HM17_IBEA,HM17_SCAN,HM17_DISC,HM17_RESET,HM17_RENEW,HM17_CON}; +#define HM17_SUCESS 99 + +struct IBEACON { + char FACID[8]; + char UID[32]; + char MAJOR[4]; + char MINOR[4]; + char PWR[2]; + char MAC[12]; + char RSSI[4]; +}; + +#define MAX_IBEACONS 16 + +struct IBEACON_UID { + char MAC[12]; + char RSSI[4]; + uint8_t FLAGS; + uint8_t TIME; +} ibeacons[MAX_IBEACONS]; + + +void IBEACON_Init() { + + hm17_found=0; + + + if ((pin[GPIO_IBEACON_RX] < 99) && (pin[GPIO_IBEACON_TX] < 99)) { + IBEACON_Serial = new TasmotaSerial(pin[GPIO_IBEACON_RX], pin[GPIO_IBEACON_TX],1); + if (IBEACON_Serial->begin(HM17_BAUDRATE)) { + if (IBEACON_Serial->hardwareSerial()) { + ClaimSerial(); + } + hm17_sendcmd(HM17_TEST); + hm17_lastms=millis(); + + IB_UPDATE_TIME=IB_UPDATE_TIME_INTERVAL; + IB_TIMEOUT_TIME=IB_TIMEOUT_INTERVAL; + } + } +} + +void hm17_every_second(void) { + if (!IBEACON_Serial) return; + + if (hm17_found) { + if (IB_UPDATE_TIME && (uptime%IB_UPDATE_TIME==0)) { + if (hm17_cmd!=99) { + if (hm17_flag&2) { + ib_sendbeep(); + } else { + if (!hm17_connecting) { + hm17_sendcmd(HM17_DISI); + } + } + } + } + for (uint32_t cnt=0;cntIB_TIMEOUT_TIME) { + ibeacons[cnt].FLAGS=0; + ibeacon_mqtt(ibeacons[cnt].MAC,"0000"); + } + } + } + } else { + if (uptime%20==0) { + hm17_sendcmd(HM17_TEST); + } + } +} + +void hm17_sbclr(void) { + memset(hm17_sbuffer,0,HM17_BSIZ); + hm17_sindex=0; + IBEACON_Serial->flush(); +} + +void hm17_sendcmd(uint8_t cmd) { + hm17_sbclr(); + hm17_cmd=cmd; +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("hm17cmd %d"),cmd); +#endif + switch (cmd) { + case HM17_TEST: + IBEACON_Serial->write("AT"); + break; + case HM17_ROLE: + IBEACON_Serial->write("AT+ROLE1"); + break; + case HM17_IMME: + IBEACON_Serial->write("AT+IMME1"); + break; + case HM17_DISI: + IBEACON_Serial->write("AT+DISI?"); + hm17_scanning=1; + break; + case HM17_IBEA: + IBEACON_Serial->write("AT+IBEA1"); + break; + case HM17_RESET: + IBEACON_Serial->write("AT+RESET"); + break; + case HM17_RENEW: + IBEACON_Serial->write("AT+RENEW"); + break; + case HM17_SCAN: + IBEACON_Serial->write("AT+SCAN5"); + break; + case HM17_DISC: + IBEACON_Serial->write("AT+DISC?"); + hm17_scanning=1; + break; + case HM17_CON: + IBEACON_Serial->write((const uint8_t*)"AT+CON",6); + IBEACON_Serial->write((const uint8_t*)ib_mac,12); + hm17_connecting=1; + break; + } +} + +uint32_t ibeacon_add(struct IBEACON *ib) { + + if (!strncmp(ib->MAC,"FFFF",4) || strncmp(ib->FACID,"00000000",8)) { + for (uint32_t cnt=0;cntMAC,12)) { + + memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); + ibeacons[cnt].TIME=0; + return 1; + } + } + } + for (uint32_t cnt=0;cntMAC,12); + memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); + ibeacons[cnt].FLAGS=1; + ibeacons[cnt].TIME=0; + return 1; + } + } + } + return 0; +} + +void hm17_decode(void) { + struct IBEACON ib; + switch (hm17_cmd) { + case HM17_TEST: + if (!strncmp(hm17_sbuffer,"OK",2)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("AT OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + hm17_found=1; + } + break; + case HM17_ROLE: + if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("ROLE OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_IMME: + if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("IMME OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_IBEA: + if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("IBEA OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_SCAN: + if (!strncmp(hm17_sbuffer,"OK+Set:5",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("SCAN OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_RESET: + if (!strncmp(hm17_sbuffer,"OK+RESET",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("RESET OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_RENEW: + if (!strncmp(hm17_sbuffer,"OK+RENEW",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("RENEW OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_CON: + if (!strncmp(hm17_sbuffer,"OK+CONNA",8)) { + hm17_sbclr(); +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNA OK")); +#endif + hm17_connecting=2; + break; + } + if (!strncmp(hm17_sbuffer,"OK+CONNE",8)) { + hm17_sbclr(); +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNE ERROR")); +#endif + break; + } + if (!strncmp(hm17_sbuffer,"OK+CONNF",8)) { + hm17_sbclr(); +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNF ERROR")); +#endif + break; + } + if (hm17_connecting==2 && !strncmp(hm17_sbuffer,"OK+CONN",7)) { + hm17_sbclr(); +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONN OK")); +#endif + hm17_connecting=3; + hm17_sendcmd(HM17_TEST); + hm17_connecting=0; + break; + } + break; + + case HM17_DISI: + case HM17_DISC: + if (!strncmp(hm17_sbuffer,"OK+DISCS",8)) { + hm17_sbclr(); + hm17_result=1; +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISCS OK")); +#endif + break; + } + if (!strncmp(hm17_sbuffer,"OK+DISCE",8)) { + hm17_sbclr(); + hm17_result=HM17_SUCESS; +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISCE OK")); +#endif + hm17_scanning=0; + break; + } + if (!strncmp(hm17_sbuffer,"OK+NAME:",8)) { + if (hm17_sbuffer[hm17_sindex-1]=='\n') { + hm17_result=HM17_SUCESS; +#ifdef IBEACON_DEBUG + if (hm17_debug) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("NAME OK")); + AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); + } +#endif + hm17_sbclr(); + } + break; + } + if (!strncmp(hm17_sbuffer,"OK+DIS0:",8)) { + if (hm17_sindex==20) { + hm17_result=HM17_SUCESS; +#ifdef IBEACON_DEBUG + if (hm17_debug) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("DIS0 OK")); + AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); + } +#endif + hm17_sbclr(); + } + break; + } + if (!strncmp(hm17_sbuffer,"OK+DISC:",8)) { + if (hm17_cmd==HM17_DISI) { + if (hm17_sindex==78) { +#ifdef IBEACON_DEBUG + if (hm17_debug) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("DISC: OK")); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); + } +#endif + memcpy(ib.FACID,&hm17_sbuffer[8],8); + memcpy(ib.UID,&hm17_sbuffer[8+8+1],32); + memcpy(ib.MAJOR,&hm17_sbuffer[8+8+1+32+1],4); + memcpy(ib.MINOR,&hm17_sbuffer[8+8+1+32+1+4],4); + memcpy(ib.PWR,&hm17_sbuffer[8+8+1+32+1+4+4],2); + memcpy(ib.MAC,&hm17_sbuffer[8+8+1+32+1+4+4+2+1],12); + memcpy(ib.RSSI,&hm17_sbuffer[8+8+1+32+1+4+4+2+1+12+1],4); + + if (ibeacon_add(&ib)) { + ibeacon_mqtt(ib.MAC,ib.RSSI); + } + hm17_sbclr(); + hm17_result=1; + } + } else { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); +#endif + } + break; + } + } +} + +void IBEACON_loop() { + + if (!IBEACON_Serial) return; + +uint32_t difftime=millis()-hm17_lastms; + + while (IBEACON_Serial->available()) { + hm17_lastms=millis(); + + if (hm17_sindexread(); + hm17_sindex++; + hm17_decode(); + } else { + hm17_sindex=0; + break; + } + } + + if (hm17_cmd==99) { + if (hm17_sindex>=HM17_BSIZ-2 || (hm17_sindex && (difftime>100))) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),hm17_sbuffer); + hm17_sbclr(); + } + } + +} + +#ifdef USE_WEBSERVER +const char HTTP_IBEACON[] PROGMEM = + "{s}IBEACON-UID : %s" " - RSSI : %s" "{m}{e}"; + +void IBEACON_Show(void) { +char mac[14]; +char rssi[6]; + + for (uint32_t cnt=0;cnt 0) { + char *cp=XdrvMailbox.data; + if (*cp>='0' && *cp<='8') { + hm17_sendcmd(*cp&7); + Response_P(S_JSON_IBEACON, XSNS_52,"hm17cmd",*cp&7); + } else if (*cp=='s') { + cp++; + len--; + while (*cp==' ') { + len--; + cp++; + } + IBEACON_Serial->write((uint8_t*)cp,len); + hm17_cmd=99; + Response_P(S_JSON_IBEACON1, XSNS_52,"hm17cmd",cp); + } else if (*cp=='u') { + cp++; + if (*cp) IB_UPDATE_TIME=atoi(cp); + Response_P(S_JSON_IBEACON, XSNS_52,"uintv",IB_UPDATE_TIME); + } else if (*cp=='t') { + cp++; + if (*cp) IB_TIMEOUT_TIME=atoi(cp); + Response_P(S_JSON_IBEACON, XSNS_52,"lintv",IB_TIMEOUT_TIME); + } else if (*cp=='c') { + for (uint32_t cnt=0;cnt + + +#define SPECIAL_SS + + + + + +#if DMY_LANGUAGE==de-DE + +#define D_TPWRIN "Verbrauch" +#define D_TPWROUT "Einspeisung" +#define D_TPWRCURR "Aktueller Verbrauch" +#define D_TPWRCURR1 "Verbrauch P1" +#define D_TPWRCURR2 "Verbrauch P2" +#define D_TPWRCURR3 "Verbrauch P3" +#define D_Strom_L1 "Strom L1" +#define D_Strom_L2 "Strom L2" +#define D_Strom_L3 "Strom L3" +#define D_Spannung_L1 "Spannung L1" +#define D_Spannung_L2 "Spannung L2" +#define D_Spannung_L3 "Spannung L3" +#define D_METERNR "Zähler Nr" +#define D_METERSID "Service ID" +#define D_GasIN "Zählerstand" +#define D_H2oIN "Zählerstand" +#define D_StL1L2L3 "Ströme L1+L2+L3" +#define D_SpL1L2L3 "Spannung L1+L2+L3/3" + +#else + +#undef D_TPWRIN +#undef D_TPWROUT +#undef D_TPWRCURR +#undef D_TPWRCURR1 +#undef D_TPWRCURR2 +#undef D_TPWRCURR3 +#undef D_Strom_L1 +#undef D_Strom_L2 +#undef D_Strom_L3 +#undef D_Spannung_L1 +#undef D_Spannung_L2 +#undef D_Spannung_L3 +#undef D_METERNR +#undef D_METERSID +#undef D_GasIN +#undef D_H2oIN +#undef D_StL1L2L3 +#undef D_SpL1L2L3 + +#define D_TPWRIN "Total-In" +#define D_TPWROUT "Total-Out" +#define D_TPWRCURR "Current-In/Out" +#define D_TPWRCURR1 "Current-In p1" +#define D_TPWRCURR2 "Current-In p2" +#define D_TPWRCURR3 "Current-In p3" +#define D_Strom_L1 "Current L1" +#define D_Strom_L2 "Current L2" +#define D_Strom_L3 "Current L3" +#define D_Spannung_L1 "Voltage L1" +#define D_Spannung_L2 "Voltage L2" +#define D_Spannung_L3 "Voltage L3" +#define D_METERNR "Meter_number" +#define D_METERSID "Service ID" +#define D_GasIN "Counter" +#define D_H2oIN "Counter" +#define D_StL1L2L3 "Current L1+L2+L3" +#define D_SpL1L2L3 "Voltage L1+L2+L3/3" + +#endif + + + +#define DJ_TPWRIN "Total_in" +#define DJ_TPWROUT "Total_out" +#define DJ_TPWRCURR "Power_curr" +#define DJ_TPWRCURR1 "Power_p1" +#define DJ_TPWRCURR2 "Power_p2" +#define DJ_TPWRCURR3 "Power_p3" +#define DJ_CURR1 "Curr_p1" +#define DJ_CURR2 "Curr_p2" +#define DJ_CURR3 "Curr_p3" +#define DJ_VOLT1 "Volt_p1" +#define DJ_VOLT2 "Volt_p2" +#define DJ_VOLT3 "Volt_p3" +#define DJ_METERNR "Meter_number" +#define DJ_METERSID "Meter_id" +#define DJ_CSUM "Curr_summ" +#define DJ_VAVG "Volt_avg" +#define DJ_COUNTER "Count" + +struct METER_DESC { + uint8_t srcpin; + uint8_t type; + uint16_t flag; + int32_t params; + char prefix[8]; + int8_t trxpin; + uint8_t tsecs; + char *txmem; + uint8_t index; + uint8_t max_index; +}; + + + + + + +#define EHZ161_0 1 +#define EHZ161_1 2 +#define EHZ363 3 +#define EHZH 4 +#define EDL300 5 +#define Q3B 6 +#define COMBO3 7 +#define COMBO2 8 +#define COMBO3a 9 +#define Q3B_V1 10 +#define EHZ363_2 11 +#define COMBO3b 12 +#define WGS_COMBO 13 +#define EBZD_G 14 + + +#define METER EHZ161_1 + + +#if METER==EHZ161_0 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; +const uint8_t meter[]= +"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,1-0:21.7.0*255(@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",0|" +"1,1-0:41.7.0*255(@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",0|" +"1,1-0:61.7.0*255(@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",0|" +"1,=m 3+4+5 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; + +#endif + + + +#if METER==EHZ161_1 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; +const uint8_t meter[]= +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; +#endif + + + +#if METER==EHZ363 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" + +"1,77070100000009ff@#," D_METERNR ",," DJ_METERNR ",0"; +#endif + + + +#if METER==EHZH +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + + +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,770701000f0700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; +#endif + + + +#if METER==EDL300 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + + +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020801ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,770701000f0700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; +#endif + +#if METER==EBZD_G +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"strom",-1,1,0}}; +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,77070100010801ff@1000," D_TPWRCURR1 ",KWh," DJ_TPWRCURR1 ",4|" + +"1,77070100010802ff@1000," D_TPWRCURR2 ",KWh," DJ_TPWRCURR2 ",4|" + +"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" + +"1,77070100600100ff@#," D_METERNR ",," DJ_METERNR ",0"; +#endif + + + + +#if METER==Q3B +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020801ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,77070100010700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; +#endif + +#if METER==COMBO3 + +#undef METERS_USED +#define METERS_USED 3 + +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, + [1]={14,'s',0,SML_BAUDRATE,"SML",-1,1,0}, + [2]={4,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; + + +const uint8_t meter[]= +"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,1-0:21.7.0*255(@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",0|" +"1,1-0:41.7.0*255(@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",0|" +"1,1-0:61.7.0*255(@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",0|" +"1,=m 3+4+5 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" +"2,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"2,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"2,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"3,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"3,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"3,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"3,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; + +#endif + +#if METER==COMBO2 + +#undef METERS_USED +#define METERS_USED 2 + +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, + [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; + + +const uint8_t meter[]= +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" + +"2,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"2,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"2,=d 6 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"2,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; + +#endif + +#if METER==COMBO3a +#undef METERS_USED +#define METERS_USED 3 + +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, + [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}, + [2]={1,'o',0,SML_BAUDRATE,"OBIS3",-1,1,0}}; + + +const uint8_t meter[]= +"1,=h --- Zähler Nr 1 ---|" +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" +"2,=h --- Zähler Nr 2 ---|" +"2,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"2,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"2,=d 6 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"2,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" +"3,=h --- Zähler Nr 3 ---|" +"3,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"3,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"3,=d 10 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"3,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; + +#endif + + + +#if METER==Q3B_V1 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ +[0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; +const uint8_t meter[]= +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,=d 1 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; +#endif + + + +#if METER==EHZ363_2 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ +[0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,77070100010801ff@1000," D_TPWRCURR1 ",KWh," DJ_TPWRCURR1 ",4|" + +"1,77070100010802ff@1000," D_TPWRCURR2 ",KWh," DJ_TPWRCURR2 ",4|" + +"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" + +"1,77070100000009ff@#," D_METERNR ",," DJ_METERNR ",0"; +#endif + + +#if METER==COMBO3b +#undef METERS_USED +#define METERS_USED 3 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, + [1]={14,'c',0,50,"Gas"}, + [2]={1,'c',0,10,"Wasser"}}; + + +const uint8_t meter[]= +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" + + +"2,1-0:1.8.0*255(@100," D_GasIN ",cbm," DJ_COUNTER ",2|" + +"3,1-0:1.8.0*255(@100," D_H2oIN ",cbm," DJ_COUNTER ",2"; +#endif + + +#if METER==WGS_COMBO +#undef METERS_USED +#define METERS_USED 3 + +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={1,'c',0,10,"H20",-1,1,0}, + [1]={4,'c',0,50,"GAS",-1,1,0}, + [2]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + +const uint8_t meter[]= + + +"1,1-0:1.8.0*255(@10000," D_H2oIN ",cbm," DJ_COUNTER ",4|" + + +"2,=h==================|" +"2,1-0:1.8.0*255(@100," D_GasIN ",cbm," DJ_COUNTER ",3|" + +"3,=h==================|" + +"3,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",3|" +"3,=h==================|" + +"3,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",2|" +"3,=h -------------------------------|" +"3,=m 10+11+12 @100," D_StL1L2L3 ",A," DJ_CSUM ",2|" + +"3,=m 13+14+15/#3 @100," D_SpL1L2L3 ",V," DJ_VAVG ",2|" +"3,=h==================|" + +"3,77070100240700ff@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",2|" + +"3,77070100380700ff@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",2|" + +"3,770701004c0700ff@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",2|" +"3,=h -------------------------------|" + +"3,770701001f0700ff@100," D_Strom_L1 ",A," DJ_CURR1 ",2|" + +"3,77070100330700ff@100," D_Strom_L2 ",A," DJ_CURR2 ",2|" + +"3,77070100470700ff@100," D_Strom_L3 ",A," DJ_CURR3 ",2|" +"3,=h -------------------------------|" + +"3,77070100200700ff@100," D_Spannung_L1 ",V," DJ_VOLT1 ",2|" + +"3,77070100340700ff@100," D_Spannung_L2 ",V," DJ_VOLT2 ",2|" + +"3,77070100480700ff@100," D_Spannung_L3 ",V," DJ_VOLT3 ",2|" +"3,=h==================|" + +"3,77070100000009ff@#," D_METERSID ",," DJ_METERSID ",0|" +"3,=h--------------------------------"; +#endif +# 499 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_53_sml.ino" +#define USE_SML_MEDIAN_FILTER + + +#define MAX_VARS 20 + +#define MAX_METERS 5 +double meter_vars[MAX_VARS]; + +#define MAX_DVARS MAX_METERS*2 +double dvalues[MAX_DVARS]; +uint32_t dtimes[MAX_DVARS]; +uint8_t meters_used; + +struct METER_DESC const *meter_desc_p; +const uint8_t *meter_p; +uint8_t meter_spos[MAX_METERS]; + + +TasmotaSerial *meter_ss[MAX_METERS]; + + +#define SML_BSIZ 48 +uint8_t smltbuf[MAX_METERS][SML_BSIZ]; + + +#define METER_ID_SIZE 24 +char meter_id[MAX_METERS][METER_ID_SIZE]; + +#define EBUS_SYNC 0xaa +#define EBUS_ESC 0xa9 + +uint8_t sml_send_blocks; +uint8_t sml_100ms_cnt; +uint8_t sml_desc_cnt; + +#ifdef USE_SML_MEDIAN_FILTER + +#define MEDIAN_SIZE 5 +struct SML_MEDIAN_FILTER { +double buffer[MEDIAN_SIZE]; +int8_t index; +} sml_mf[MAX_VARS]; + + +double sml_median_array(double *array,uint8_t len) { + uint8_t ind[len]; + uint8_t mind=0,index=0,flg; + double min=FLT_MAX; + + for (uint8_t hcnt=0; hcntbuffer[mf->index]=in; + mf->index++; + if (mf->index>=MEDIAN_SIZE) mf->index=0; + + return sml_median_array(mf->buffer,MEDIAN_SIZE); +# 597 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_53_sml.ino" +} +#endif + +#ifdef ANALOG_OPTO_SENSOR + +uint8_t ads1115_up; + + +#define SAMPLE_BIT (0x8000) + +#define ADS1115_COMP_QUEUE_SHIFT 0 +#define ADS1115_COMP_LATCH_SHIFT 2 +#define ADS1115_COMP_POLARITY_SHIFT 3 +#define ADS1115_COMP_MODE_SHIFT 4 +#define ADS1115_DATA_RATE_SHIFT 5 +#define ADS1115_MODE_SHIFT 8 +#define ADS1115_PGA_SHIFT 9 +#define ADS1115_MUX_SHIFT 12 + +enum ads1115_comp_queue { + ADS1115_COMP_QUEUE_AFTER_ONE = 0, + ADS1115_COMP_QUEUE_AFTER_TWO = 0x1 << ADS1115_COMP_QUEUE_SHIFT, + ADS1115_COMP_QUEUE_AFTER_FOUR = 0x2 << ADS1115_COMP_QUEUE_SHIFT, + ADS1115_COMP_QUEUE_DISABLE = 0x3 << ADS1115_COMP_QUEUE_SHIFT, + ADS1115_COMP_QUEUE_MASK = 0x3 << ADS1115_COMP_QUEUE_SHIFT, +}; + +enum ads1115_comp_latch { + ADS1115_COMP_LATCH_NO = 0, + ADS1115_COMP_LATCH_YES = 1 << ADS1115_COMP_LATCH_SHIFT, + ADS1115_COMP_LATCH_MASK = 1 << ADS1115_COMP_LATCH_SHIFT, +}; + +enum ads1115_comp_polarity { + ADS1115_COMP_POLARITY_ACTIVE_LOW = 0, + ADS1115_COMP_POLARITY_ACTIVE_HIGH = 1 << ADS1115_COMP_POLARITY_SHIFT, + ADS1115_COMP_POLARITY_MASK = 1 << ADS1115_COMP_POLARITY_SHIFT, +}; + +enum ads1115_comp_mode { + ADS1115_COMP_MODE_WINDOW = 0, + ADS1115_COMP_MODE_HYSTERESIS = 1 << ADS1115_COMP_MODE_SHIFT, + ADS1115_COMP_MODE_MASK = 1 << ADS1115_COMP_MODE_SHIFT, +}; + +enum ads1115_data_rate { + ADS1115_DATA_RATE_8_SPS = 0, + ADS1115_DATA_RATE_16_SPS = 0x1 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_32_SPS = 0x2 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_64_SPS = 0x3 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_128_SPS = 0x4 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_250_SPS = 0x5 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_475_SPS = 0x6 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_860_SPS = 0x7 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_MASK = 0x7 << ADS1115_DATA_RATE_SHIFT, +}; + +enum ads1115_mode { + ADS1115_MODE_CONTINUOUS = 0, + ADS1115_MODE_SINGLE_SHOT = 1 << ADS1115_MODE_SHIFT, + ADS1115_MODE_MASK = 1 << ADS1115_MODE_SHIFT, +}; + +enum ads1115_pga { + ADS1115_PGA_TWO_THIRDS = 0, + ADS1115_PGA_ONE = 0x1 << ADS1115_PGA_SHIFT, + ADS1115_PGA_TWO = 0x2 << ADS1115_PGA_SHIFT, + ADS1115_PGA_FOUR = 0x3 << ADS1115_PGA_SHIFT, + ADS1115_PGA_EIGHT = 0x4 << ADS1115_PGA_SHIFT, + ADS1115_PGA_SIXTEEN = 0x5 << ADS1115_PGA_SHIFT, + ADS1115_PGA_MASK = 0x7 << ADS1115_PGA_SHIFT, +}; + + +enum ads1115_mux { + ADS1115_MUX_DIFF_AIN0_AIN1 = 0, + ADS1115_MUX_DIFF_AIN0_AIN3 = 0x1 << ADS1115_MUX_SHIFT, + ADS1115_MUX_DIFF_AIN1_AIN3 = 0x2 << ADS1115_MUX_SHIFT, + ADS1115_MUX_DIFF_AIN2_AIN3 = 0x3 << ADS1115_MUX_SHIFT, + ADS1115_MUX_GND_AIN0 = 0x4 << ADS1115_MUX_SHIFT, + ADS1115_MUX_GND_AIN1 = 0x5 << ADS1115_MUX_SHIFT, + ADS1115_MUX_GND_AIN2 = 0x6 << ADS1115_MUX_SHIFT, + ADS1115_MUX_GND_AIN3 = 0x7 << ADS1115_MUX_SHIFT, + ADS1115_MUX_MASK = 0x7 << ADS1115_MUX_SHIFT, +}; + +class ADS1115 { +public: + ADS1115(uint8_t address = 0x48); + + void begin(); + uint8_t trigger_sample(); + uint8_t reset(); + bool is_sample_in_progress(); + int16_t read_sample(); + float sample_to_float(int16_t val); + float read_sample_float(); + + void set_comp_queue(enum ads1115_comp_queue val) { set_config(val, ADS1115_COMP_QUEUE_MASK); } + void set_comp_latching(enum ads1115_comp_latch val) { set_config(val, ADS1115_COMP_LATCH_MASK); } + void set_comp_polarity(enum ads1115_comp_polarity val) { set_config(val, ADS1115_COMP_POLARITY_MASK); } + void set_comp_mode(enum ads1115_comp_mode val) { set_config(val, ADS1115_COMP_MODE_MASK); } + void set_data_rate(enum ads1115_data_rate val) { set_config(val, ADS1115_DATA_RATE_MASK); } + void set_mode(enum ads1115_mode val) { set_config(val, ADS1115_MODE_MASK); } + void set_pga(enum ads1115_pga val) { set_config(val, ADS1115_PGA_MASK); m_voltage_range = val >> ADS1115_PGA_SHIFT; } + void set_mux(enum ads1115_mux val) { set_config(val, ADS1115_MUX_MASK); } + +private: + void set_config(uint16_t val, uint16_t mask) { + m_config = (m_config & ~mask) | val; + } + + uint8_t write_register(uint8_t reg, uint16_t val); + uint16_t read_register(uint8_t reg); + + uint8_t m_address; + uint16_t m_config; + int m_voltage_range; +}; + + +enum ads1115_register { + ADS1115_REGISTER_CONVERSION = 0, + ADS1115_REGISTER_CONFIG = 1, + ADS1115_REGISTER_LOW_THRESH = 2, + ADS1115_REGISTER_HIGH_THRESH = 3, +}; + +#define FACTOR 32768.0 +static float ranges[] = { 6.144 / FACTOR, 4.096 / FACTOR, 2.048 / FACTOR, 1.024 / FACTOR, 0.512 / FACTOR, 0.256 / FACTOR}; + +ADS1115::ADS1115(uint8_t address) +{ + m_address = address; + m_config = ADS1115_COMP_QUEUE_AFTER_ONE | + ADS1115_COMP_LATCH_NO | + ADS1115_COMP_POLARITY_ACTIVE_LOW | + ADS1115_COMP_MODE_WINDOW | + ADS1115_DATA_RATE_128_SPS | + ADS1115_MODE_SINGLE_SHOT | + ADS1115_MUX_GND_AIN0; + set_pga(ADS1115_PGA_ONE); +} + +uint8_t ADS1115::write_register(uint8_t reg, uint16_t val) +{ + Wire.beginTransmission(m_address); + Wire.write(reg); + Wire.write(val>>8); + Wire.write(val & 0xFF); + return Wire.endTransmission(); +} + +uint16_t ADS1115::read_register(uint8_t reg) +{ + Wire.beginTransmission(m_address); + Wire.write(reg); + Wire.endTransmission(); + + uint8_t result = Wire.requestFrom((int)m_address, 2, 1); + if (result != 2) { + return 0; + } + + uint16_t val; + + val = Wire.read() << 8; + val |= Wire.read(); + return val; +} + +void ADS1115::begin() +{ + Wire.begin(); +} + +uint8_t ADS1115::trigger_sample() +{ + return write_register(ADS1115_REGISTER_CONFIG, m_config | SAMPLE_BIT); +} + +uint8_t ADS1115::reset() +{ + Wire.beginTransmission(0); + Wire.write(0x6); + return Wire.endTransmission(); +} + +bool ADS1115::is_sample_in_progress() +{ + uint16_t val = read_register(ADS1115_REGISTER_CONFIG); + return (val & SAMPLE_BIT) == 0; +} + +int16_t ADS1115::read_sample() +{ + return read_register(ADS1115_REGISTER_CONVERSION); +} + +float ADS1115::sample_to_float(int16_t val) +{ + return val * ranges[m_voltage_range]; +} + +float ADS1115::read_sample_float() +{ + return sample_to_float(read_sample()); +} + +ADS1115 adc; + +void ADS1115_init(void) { + + ads1115_up=0; + if (!i2c_flg) return; + + adc.begin(); + adc.set_data_rate(ADS1115_DATA_RATE_128_SPS); + adc.set_mode(ADS1115_MODE_CONTINUOUS); + adc.set_mux(ADS1115_MUX_DIFF_AIN0_AIN3); + adc.set_pga(ADS1115_PGA_TWO); + + int16_t val = adc.read_sample(); + ads1115_up=1; +} + +#endif + +char sml_start; +uint8_t dump2log=0; + +#define SML_SAVAILABLE Serial_available() +#define SML_SREAD Serial_read() +#define SML_SPEAK Serial_peek() + +bool Serial_available() { + uint8_t num=dump2log&7; + if (num<1 || num>meters_used) num=1; + return meter_ss[num-1]->available(); +} + +uint8_t Serial_read() { + uint8_t num=dump2log&7; + if (num<1 || num>meters_used) num=1; + return meter_ss[num-1]->read(); +} + +uint8_t Serial_peek() { + uint8_t num=dump2log&7; + if (num<1 || num>meters_used) num=1; + return meter_ss[num-1]->peek(); +} + +void Dump2log(void) { + +int16_t index=0,hcnt=0; +uint32_t d_lastms; +uint8_t dchars[16]; + + if (!SML_SAVAILABLE) return; + + if (dump2log&8) { + + while (SML_SAVAILABLE) { + log_data[index]=':'; + index++; + log_data[index]=' '; + index++; + d_lastms=millis(); + while ((millis()-d_lastms)<40) { + if (SML_SAVAILABLE) { + uint8_t c=SML_SREAD; + sprintf(&log_data[index],"%02x ",c); + dchars[hcnt]=c; + index+=3; + hcnt++; + if (hcnt>15) { + + log_data[index]='='; + index++; + log_data[index]='>'; + index++; + log_data[index]=' '; + index++; + for (uint8_t ccnt=0; ccnt<16; ccnt++) { + if (isprint(dchars[ccnt])) { + log_data[index]=dchars[ccnt]; + } else { + log_data[index]=' '; + } + index++; + } + break; + } + } + } + if (index>0) { + log_data[index]=0; + AddLog(LOG_LEVEL_INFO); + index=0; + hcnt=0; + } + } + } else { + + index=0; + log_data[index]=':'; + index++; + log_data[index]=' '; + index++; + d_lastms=millis(); + while ((millis()-d_lastms)<40) { + if (SML_SAVAILABLE) { + if (meter_desc_p[(dump2log&7)-1].type=='o') { + + char c=SML_SREAD&0x7f; + if (c=='\n' || c=='\r') break; + log_data[index]=c; + index++; + } else { + unsigned char c; + if (meter_desc_p[(dump2log&7)-1].type=='e') { + + c=SML_SREAD; + sprintf(&log_data[index],"%02x ",c); + index+=3; + if (c==EBUS_SYNC) break; + } else { + + if (sml_start==0x77) { + sml_start=0; + } else { + c=SML_SPEAK; + if (c==0x77) { + sml_start=c; + break; + } + } + c=SML_SREAD; + sprintf(&log_data[index],"%02x ",c); + index+=3; + } + } + } + } + if (index>0) { + log_data[index]=0; + AddLog(LOG_LEVEL_INFO); + } + } + + +} + + +uint8_t *skip_sml(uint8_t *cp,int16_t *res) { + uint8_t len,len1,type; + len=*cp&0xf; + type=*cp&0x70; + if (type==0x70) { + + + cp++; + while (len--) { + len1=*cp&0x0f; + cp+=len1; + } + *res=0; + } else { + + *res=(signed char)*(cp+1); + cp+=len; + } + return cp; +} + + + +double sml_getvalue(unsigned char *cp,uint8_t index) { +uint8_t len,unit,type; +int16_t scaler,result; +int64_t value; +double dval; + + + + cp=skip_sml(cp,&result); + + cp=skip_sml(cp,&result); + + cp=skip_sml(cp,&result); + + cp=skip_sml(cp,&result); + scaler=result; + + type=*cp&0x70; + len=*cp&0x0f; + cp++; + if (type==0x50 || type==0x60) { + + uint64_t uvalue=0; + uint8_t nlen=len; + while (--nlen) { + uvalue<<=8; + uvalue|=*cp++; + } + if (type==0x50) { + + switch (len-1) { + case 1: + + value=(signed char)uvalue; + break; + case 2: + +#ifdef DWS74_BUG + if (scaler==-2) { + value=(uint32_t)uvalue; + } else { + value=(int16_t)uvalue; + } +#else + value=(int16_t)uvalue; +#endif + break; + case 3: + case 4: + + value=(int32_t)uvalue; + break; + case 5: + case 6: + case 7: + case 8: + + value=(int64_t)uvalue; + break; + } + } else { + + value=uvalue; + } + + } else { + if (!(type&0xf0)) { + + + + if (len==9) { + + cp++; + uint32_t s1,s2; + s1=*cp<<16|*(cp+1)<<8|*(cp+2); + cp+=4; + s2=*cp<<16|*(cp+1)<<8|*(cp+2); + sprintf(&meter_id[index][0],"%u-%u",s1,s2); + } else { + + char *str=&meter_id[index][0]; + for (type=0; type= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; + } + return rVal; +} + +uint8_t sb_counter; + + +double CharToDouble(const char *str) +{ + + char strbuf[24]; + + strlcpy(strbuf, str, sizeof(strbuf)); + char *pt = strbuf; + while ((*pt != '\0') && isblank(*pt)) { pt++; } + + signed char sign = 1; + if (*pt == '-') { sign = -1; } + if (*pt == '-' || *pt=='+') { pt++; } + + double left = 0; + if (*pt != '.') { + left = atoi(pt); + while (isdigit(*pt)) { pt++; } + } + + double right = 0; + if (*pt == '.') { + pt++; + right = atoi(pt); + while (isdigit(*pt)) { + pt++; + right /= 10.0; + } + } + + double result = left + right; + if (sign < 0) { + return -result; + } + return result; +} + + + +void ebus_esc(uint8_t *ebus_buffer, unsigned char len) { + short count,count1; + for (count=0; countavailable()) { + meter_ss[meters]->read(); + } +} + + +void sml_shift_in(uint32_t meters,uint32_t shard) { + uint32_t count; + if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='p') { + + for (count=0; countread(); + + if (meter_desc_p[meters].type=='o') { + smltbuf[meters][SML_BSIZ-1]=iob&0x7f; + } else if (meter_desc_p[meters].type=='s') { + smltbuf[meters][SML_BSIZ-1]=iob; + } else if (meter_desc_p[meters].type=='r') { + smltbuf[meters][SML_BSIZ-1]=iob; + } else if (meter_desc_p[meters].type=='m') { + smltbuf[meters][meter_spos[meters]] = iob; + meter_spos[meters]++; + if (meter_spos[meters]>=9) { + SML_Decode(meters); + sml_empty_receiver(meters); + meter_spos[meters]=0; + } + } else if (meter_desc_p[meters].type=='p') { + smltbuf[meters][meter_spos[meters]] = iob; + meter_spos[meters]++; + if (meter_spos[meters]>=7) { + SML_Decode(meters); + sml_empty_receiver(meters); + meter_spos[meters]=0; + } + } else { + if (iob==EBUS_SYNC) { + + + if (meter_spos[meters]>4+5) { + + uint8_t tlen=smltbuf[meters][4]+5; + + if (smltbuf[meters][tlen]=ebus_CalculateCRC(smltbuf[meters],tlen)) { + ebus_esc(smltbuf[meters],tlen); + SML_Decode(meters); + } else { + + + } + } + meter_spos[meters]=0; + return; + } + smltbuf[meters][meter_spos[meters]] = iob; + meter_spos[meters]++; + if (meter_spos[meters]>=SML_BSIZ) { + meter_spos[meters]=0; + } + } + sb_counter++; + if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='p') SML_Decode(meters); +} + + + +void SML_Poll(void) { +uint32_t meters; + + for (meters=0; metersavailable()) { + sml_shift_in(meters,0); + } + } + } +} + + +void SML_Decode(uint8_t index) { + const char *mp=(const char*)meter_p; + int8_t mindex; + uint8_t *cp; + uint8_t dindex=0,vindex=0; + delay(0); + while (mp != NULL) { + + + + mindex=((*mp)&7)-1; + + if (mindex<0 || mindex>=meters_used) mindex=0; + mp+=2; + if (*mp=='=' && *(mp+1)=='h') { + mp = strchr(mp, '|'); + if (mp) mp++; + continue; + } + + if (index!=mindex) goto nextsect; + + + cp=&smltbuf[mindex][0]; + + + if (*mp=='=') { + + mp++; + + if (*mp=='m' && !sb_counter) { + + + mp++; + while (*mp==' ') mp++; + + double dvar; + uint8_t opr; + uint32_t ind; + ind=atoi(mp); + while (*mp>='0' && *mp<='9') mp++; + if (ind<1 || ind>MAX_VARS) ind=1; + dvar=meter_vars[ind-1]; + for (uint8_t p=0;p<5;p++) { + if (*mp=='@') { + + meter_vars[vindex]=dvar; + mp++; + SML_Immediate_MQTT((const char*)mp,vindex,mindex); + break; + } + opr=*mp; + mp++; + uint8_t iflg=0; + if (*mp=='#') { + iflg=1; + mp++; + } + ind=atoi(mp); + while (*mp>='0' && *mp<='9') mp++; + if (ind<1 || ind>MAX_VARS) ind=1; + switch (opr) { + case '+': + if (iflg) dvar+=ind; + else dvar+=meter_vars[ind-1]; + break; + case '-': + if (iflg) dvar-=ind; + else dvar-=meter_vars[ind-1]; + break; + case '*': + if (iflg) dvar*=ind; + else dvar*=meter_vars[ind-1]; + break; + case '/': + if (iflg) dvar/=ind; + else dvar/=meter_vars[ind-1]; + break; + } + while (*mp==' ') mp++; + if (*mp=='@') { + + meter_vars[vindex]=dvar; + mp++; + SML_Immediate_MQTT((const char*)mp,vindex,mindex); + break; + } + } + } else if (*mp=='d') { + + if (dindex='0' && *mp<='9') mp++; + if (ind<1 || ind>MAX_VARS) ind=1; + uint32_t delay=atoi(mp)*1000; + uint32_t dtime=millis()-dtimes[dindex]; + if (dtime>delay) { + + dtimes[dindex]=millis(); + double vdiff = meter_vars[ind-1]-dvalues[dindex]; + dvalues[dindex]=meter_vars[ind-1]; + meter_vars[vindex]=(double)360000.0*vdiff/((double)dtime/10000.0); + + mp=strchr(mp,'@'); + if (mp) { + mp++; + SML_Immediate_MQTT((const char*)mp,vindex,mindex); + } + } + dindex++; + } + } else if (*mp=='h') { + + mp = strchr(mp, '|'); + if (mp) mp++; + continue; + } + } else { + + uint8_t found=1; + uint32_t ebus_dval=99; + float mbus_dval=99; + while (*mp!='@') { + if (meter_desc_p[mindex].type=='o' || meter_desc_p[mindex].type=='c') { + if (*mp++!=*cp++) { + found=0; + } + } else { + if (meter_desc_p[mindex].type=='s') { + + uint8_t val = hexnibble(*mp++) << 4; + val |= hexnibble(*mp++); + if (val!=*cp++) { + found=0; + } + } else { + + + if (*mp=='x' && *(mp+1)=='x') { + + mp+=2; + cp++; + } else if (!strncmp(mp,"uuuuuuuu",8)) { + uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); + ebus_dval=val; + mbus_dval=val; + mp+=8; + cp+=4; + } + else if (*mp=='u' && *(mp+1)=='u' && *(mp+2)=='u' && *(mp+3)=='u'){ + uint16_t val = cp[0]|(cp[1]<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } else if (*mp=='u' && *(mp+1)=='u') { + uint8_t val = *cp++; + ebus_dval=val; + mp+=2; + } + else if (*mp=='s' && *(mp+1)=='s' && *(mp+2)=='s' && *(mp+3)=='s') { + int16_t val = *cp|(*(cp+1)<<8); + ebus_dval=val; + mp+=4; + cp+=2; + } + else if (*mp=='s' && *(mp+1)=='s') { + int8_t val = *cp++; + ebus_dval=val; + mp+=2; + } + else if (!strncmp(mp,"ffffffff",8)) { + uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); + float *fp=(float*)&val; + ebus_dval=*fp; + mbus_dval=*fp; + mp+=8; + cp+=4; + } + else if (!strncmp(mp,"FFffFFff",8)) { + + uint32_t val= (cp[1]<<0)|(cp[0]<<8)|(cp[3]<<16)|(cp[2]<<24); + float *fp=(float*)&val; + ebus_dval=*fp; + mbus_dval=*fp; + mp+=8; + cp+=4; + } + else if (!strncmp(mp,"eeeeee",6)) { + uint32_t val=(cp[0]<<16)|(cp[1]<<8)|(cp[2]<<0); + mbus_dval=val; + mp+=6; + cp+=3; + } + else if (!strncmp(mp,"vvvvvv",6)) { + mbus_dval=(float)((cp[0]<<8)|(cp[1])) + ((float)cp[2]/10.0); + mp+=6; + cp+=3; + } + else if (!strncmp(mp,"cccccc",6)) { + mbus_dval=(float)((cp[0]<<8)|(cp[1])) + ((float)cp[2]/100.0); + mp+=6; + cp+=3; + } + else if (!strncmp(mp,"pppp",4)) { + mbus_dval=(float)((cp[0]<<8)|cp[1]); + mp+=4; + cp+=2; + } + else { + uint8_t val = hexnibble(*mp++) << 4; + val |= hexnibble(*mp++); + if (val!=*cp++) { + found=0; + } + } + } + } + } + if (found) { + + mp++; + if (*mp=='#') { + + mp++; + if (meter_desc_p[mindex].type=='o') { + for (uint8_t p=0;p>=shift; + ebus_dval&=1; + mp+=2; + } + if (*mp=='i') { + + mp++; + uint8_t mb_index=strtol((char*)mp,(char**)&mp,10); + if (mb_index!=meter_desc_p[mindex].index) { + goto nextsect; + } + uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],7); + if (lowByte(crc)!=smltbuf[mindex][7]) goto nextsect; + if (highByte(crc)!=smltbuf[mindex][8]) goto nextsect; + dval=mbus_dval; + + mp++; + } else { + if (meter_desc_p[mindex].type=='p') { + uint8_t crc = SML_PzemCrc(&smltbuf[mindex][0],6); + if (crc!=smltbuf[mindex][6]) goto nextsect; + dval=mbus_dval; + } else { + dval=ebus_dval; + } + } + + } +#ifdef USE_SML_MEDIAN_FILTER + if (meter_desc_p[mindex].flag&16) { + meter_vars[vindex]=sml_median(&sml_mf[vindex],dval); + } else { + meter_vars[vindex]=dval; + } +#else + meter_vars[vindex]=dval; +#endif + + + double fac=CharToDouble((char*)mp); + meter_vars[vindex]/=fac; + SML_Immediate_MQTT((const char*)mp,vindex,mindex); + } + } + } +nextsect: + + if (vindex=meters_used) lastmind=0; + while (mp != NULL) { + + mindex=((*mp)&7)-1; + if (mindex<0 || mindex>=meters_used) mindex=0; + mp+=2; + if (*mp=='=' && *(mp+1)=='h') { + mp+=2; + + if (json) { + mp = strchr(mp, '|'); + if (mp) mp++; + continue; + } + + uint8_t i; + for (i=0;isml_counters[index].sml_debounce) { + RtcSettings.pulse_counter[index]++; + InjektCounterValue(sml_counters[index].sml_cnt_old_state,RtcSettings.pulse_counter[index]); + } +} + +void SML_CounterUpd1(void) { + SML_CounterUpd(0); +} + +void SML_CounterUpd2(void) { + SML_CounterUpd(1); +} + +void SML_CounterUpd3(void) { + SML_CounterUpd(2); +} + +void SML_CounterUpd4(void) { + SML_CounterUpd(3); +} + +#ifdef USE_SCRIPT +struct METER_DESC script_meter_desc[MAX_METERS]; +uint8_t *script_meter; +#endif + +#define METER_DEF_SIZE 2000 + +bool Gpio_used(uint8_t gpiopin) { + for (uint16_t i=0;iM",-2,0); + if (meter_script==99) { + + if (script_meter) free(script_meter); + script_meter=0; + uint8_t *tp=0; + uint16_t index=0; + uint8_t section=0; + uint8_t srcpin=0; + char *lp=glob_script_mem.scriptptr; + sml_send_blocks=0; + while (lp) { + if (!section) { + if (*lp=='>' && *(lp+1)=='M') { + lp+=2; + meters_used=strtol(lp,0,10); + section=1; + uint32_t mlen=0; + for (uint32_t cnt=0;cnt') { + if (*(tp-1)=='|') *(tp-1)=0; + break; + } + if (*lp=='+') { + + + lp++; + index=*lp&7; + lp+=2; + if (index<1 || index>meters_used) goto next_line; + index--; + srcpin=strtol(lp,&lp,10); + if (Gpio_used(srcpin)) { + AddLog_P(LOG_LEVEL_INFO, PSTR("gpio rx double define!")); +dddef_exit: + if (script_meter) free(script_meter); + script_meter=0; + meters_used=METERS_USED; + goto init10; + } + script_meter_desc[index].srcpin=srcpin; + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].type=*lp; + lp+=2; + script_meter_desc[index].flag=strtol(lp,&lp,10); + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].params=strtol(lp,&lp,10); + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].prefix[7]=0; + for (uint32_t cnt=0; cnt<8; cnt++) { + if (*lp==SCRIPT_EOL || *lp==',') { + script_meter_desc[index].prefix[cnt]=0; + break; + } + script_meter_desc[index].prefix[cnt]=*lp++; + } + if (*lp==',') { + lp++; + script_meter_desc[index].trxpin=strtol(lp,&lp,10); + if (Gpio_used(script_meter_desc[index].trxpin)) { + AddLog_P(LOG_LEVEL_INFO, PSTR("gpio tx double define!")); + goto dddef_exit; + } + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].tsecs=strtol(lp,&lp,10); + if (*lp==',') { + lp++; + char txbuff[256]; + uint32_t txlen=0,tx_entries=1; + for (uint32_t cnt=0; cntmeters_used) goto next_line; + while (1) { + if (*lp==SCRIPT_EOL) { + if (*(tp-1)!='|') *tp++='|'; + goto next_line; + } + *tp++=*lp++; + index++; + if (index>=METER_DEF_SIZE) break; + } + } + + } + +next_line: + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } + *tp=0; + meter_desc_p=script_meter_desc; + meter_p=script_meter; + } +#endif + +init10: + typedef void (*function)(); + function counter_callbacks[] = {SML_CounterUpd1,SML_CounterUpd2,SML_CounterUpd3,SML_CounterUpd4}; + uint8_t cindex=0; + + for (byte i = 0; i < MAX_COUNTERS; i++) { + RtcSettings.pulse_counter[i]=Settings.pulse_counter[i]; + sml_counters[i].sml_cnt_last_ts=millis(); + } + for (uint8_t meters=0; metersbegin(meter_desc_p[meters].params)) { + meter_ss[meters]->flush(); + } + if (meter_ss[meters]->hardwareSerial()) { ClaimSerial(); } + + } + } + +} + + +void SetDBGLed(uint8_t srcpin, uint8_t ledpin) { + pinMode(ledpin, OUTPUT); + if (digitalRead(srcpin)) { + digitalWrite(ledpin,LOW); + } else { + digitalWrite(ledpin,HIGH); + } +} + + +void SML_Counter_Poll(void) { +uint16_t meters,cindex=0; +uint32_t ctime=millis(); + + for (meters=0; meters0) { + if (ctime-sml_counters[cindex].sml_cnt_last_ts>meter_desc_p[meters].params) { + sml_counters[cindex].sml_cnt_last_ts=ctime; + + if (meter_desc_p[meters].flag&2) { + +#ifdef ANALOG_OPTO_SENSOR + if (ads1115_up) { + int16_t val = adc.read_sample(); + if (val>sml_counters[cindex].ana_max) sml_counters[cindex].ana_max=val; + if (val10) { + sml_counters[cindex].sml_cnt_last_ts=ctime; +#ifdef DEBUG_CNT_LED1 + if (cindex==0) SetDBGLed(meter_desc_p[meters].srcpin,DEBUG_CNT_LED1); +#endif +#ifdef DEBUG_CNT_LED2 + if (cindex==1) SetDBGLed(meter_desc_p[meters].srcpin,DEBUG_CNT_LED2); +#endif + } + } + cindex++; + } + } +} + +#ifdef USE_SCRIPT +char *SML_Get_Sequence(char *cp,uint32_t index) { + if (!index) return cp; + uint32_t cindex=0; + while (cp) { + cp=strchr(cp,','); + if (cp) { + cp++; + cindex++; + if (cindex==index) { + return cp; + } + } + } +} + +void SML_Check_Send(void) { + sml_100ms_cnt++; + char *cp; + for (uint32_t cnt=sml_desc_cnt; cnt=0 && script_meter_desc[cnt].txmem) { + if ((sml_100ms_cnt%script_meter_desc[cnt].tsecs)==0) { + if (script_meter_desc[cnt].max_index>1) { + script_meter_desc[cnt].index++; + if (script_meter_desc[cnt].index>=script_meter_desc[cnt].max_index) { + script_meter_desc[cnt].index=0; + sml_desc_cnt++; + } + cp=SML_Get_Sequence(script_meter_desc[cnt].txmem,script_meter_desc[cnt].index); + + } else { + cp=script_meter_desc[cnt].txmem; + + sml_desc_cnt++; + } + + SML_Send_Seq(cnt,cp); + if (sml_desc_cnt>=meters_used) { + sml_desc_cnt=0; + } + break; + } + } else { + sml_desc_cnt++; + } + + if (sml_desc_cnt>=meters_used) { + sml_desc_cnt=0; + } + } +} + +uint8_t sml_hexnibble(char chr) { + uint8_t rVal = 0; + if (isdigit(chr)) { + rVal = chr - '0'; + } else { + if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; + if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; + } + return rVal; +} + + +void SML_Send_Seq(uint32_t meter,char *seq) { + uint8_t sbuff[32]; + uint8_t *ucp=sbuff,slen=0; + char *cp=seq; + while (*cp) { + if (!*cp || !*(cp+1)) break; + if (*cp==',') break; + uint8_t iob=(sml_hexnibble(*cp) << 4) | sml_hexnibble(*(cp+1)); + cp+=2; + *ucp++=iob; + slen++; + if (slen>=sizeof(sbuff)) break; + } + if (script_meter_desc[meter].type=='m') { + *ucp++=0; + *ucp++=2; + + uint16_t crc = MBUS_calculateCRC(sbuff,6); + *ucp++=lowByte(crc); + *ucp++=highByte(crc); + slen+=4; + } + if (script_meter_desc[meter].type=='p') { + *ucp++=0xc0; + *ucp++=0xa8; + *ucp++=1; + *ucp++=1; + *ucp++=0; + *ucp++=SML_PzemCrc(sbuff,6); + slen+=6; + } + meter_ss[meter]->write(sbuff,slen); +} +#endif + +uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num) { + uint16_t crc, flag; + crc = 0xFFFF; + for (uint32_t i = 0; i < num; i++) { + crc ^= frame[i]; + for (uint32_t j = 8; j; j--) { + if ((crc & 0x0001) != 0) { + crc >>= 1; + crc ^= 0xA001; + } else { + crc >>= 1; + } + } + } + return crc; +} + +uint8_t SML_PzemCrc(uint8_t *data, uint8_t len) { + uint16_t crc = 0; + for (uint32_t i = 0; i < len; i++) crc += *data++; + return (uint8_t)(crc & 0xFF); +} +# 2277 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_53_sml.ino" +bool XSNS_53_cmd(void) { + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + char *cp=XdrvMailbox.data; + if (*cp=='d') { + + cp++; + dump2log=atoi(cp); + ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"dump: %d\"}}"),dump2log); + } else if (*cp=='c') { + + cp++; + uint8_t index=*cp&7; + if (index<1 || index>MAX_COUNTERS) index=1; + cp++; + while (*cp==' ') cp++; + if (isdigit(*cp)) { + uint32_t cval=atoi(cp); + while (isdigit(*cp)) cp++; + RtcSettings.pulse_counter[index-1]=cval; + uint8_t cindex=0; + for (uint8_t meters=0; metersaddress, INA226_REG_CALIBRATION, si->calibrationValue); + +} + + + + + + +bool Ina226TestPresence(uint8_t device) +{ + + + + uint16_t config = I2cRead16( slaveInfo[device].address, INA226_REG_CONFIG ); + + + if (config != slaveInfo[device].config) + return false; + + return true; + +} + + + + + + +void Ina226Init() +{ + + + uint32_t i; + + slavesFound = 0; + + Ina226SlaveInfo_t *p = slaveInfo; + + + + AddLog_P2( LOG_LEVEL_NONE, "Size of Settings: %d bytes", sizeof(Settings)); + + if (!i2c_flg) + AddLog_P2(LOG_LEVEL_DEBUG, "INA226: Initialization failed: No I2C support"); + + + + + for (i = 0; i < 4; i++){ + *p = {0}; + } + + + + + + for (i = 0; (i < INA226_MAX_ADDRESSES); i++){ + uint8_t addr = pgm_read_byte(probeAddresses + i); + + + + + if (!Settings.ina226_i_fs[i]) + continue; + + + + + + + if (!I2cWrite16( addr, INA226_REG_CONFIG, INA226_CONFIG_RESET)){ + + AddLog_P2( LOG_LEVEL_DEBUG, "No INA226 at address: %02X", addr); + continue; + } + + + + uint16_t config = I2cRead16( addr, INA226_REG_CONFIG ); + + + if (INA226_RES_CONFIG != config) + continue; + + + config = INA226_DEF_CONFIG; + + + if (!I2cWrite16( addr, INA226_REG_CONFIG, config)) + continue; + + + + p = &slaveInfo[i]; + + p->address = addr; + + p->config = config; + + + p->i_lsb = (((float) Settings.ina226_i_fs[i])/10.0f)/32768.0f; + + + + uint32_t r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[i]); + + + + p->calibrationValue = ((uint16_t) (0.00512/(p->i_lsb * r_shunt_uohms/1000000.0f))); + + p->present = true; + + + Ina226SetCalibration(i); + + + slavesFound++; + + } +} + + + + + +float Ina226ReadBus_v(uint8_t device) +{ + uint8_t addr = slaveInfo[device].address; + int16_t reg_bus_v = I2cReadS16( addr, INA226_REG_BUSVOLTAGE); + + float result = ((float) reg_bus_v) * 0.00125f; + + return result; + +} + + + + + +float Ina226ReadShunt_i(uint8_t device) +{ + uint8_t addr = slaveInfo[device].address; + int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_CURRENT); + + float result = ((float) reg_shunt_i) * slaveInfo[device].i_lsb; + + return result; +} + + + + + +float Ina226ReadPower_w(uint8_t device) +{ + uint8_t addr = slaveInfo[device].address; + int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_POWER); + + float result = ((float) reg_shunt_i) * (slaveInfo[device].i_lsb * 25.0); + + return result; +} + + + + + + +void Ina226Read(uint8_t device) +{ + + voltages[device] = Ina226ReadBus_v(device); + currents[device] = Ina226ReadShunt_i(device); + powers[device] = Ina226ReadPower_w(device); + + + + +} + + + + + +void Ina226EverySecond() +{ + + for (uint8_t device = 0; device < INA226_MAX_ADDRESSES; device++){ + + if (slavesFound && slaveInfo[device].present && Ina226TestPresence(device)){ + Ina226Read(device); + } + else { + powers[device] = currents[device] = voltages[device] = 0.0f; + + + + + + + slaveInfo[device].present = false; + } + } +} + + + + + +bool Ina226CommandSensor() +{ + bool serviced = true; + bool show_config = false; + char param_str[64]; + char *cp, *params[4]; + uint8_t i, param_count, device, p1 = XdrvMailbox.payload; + uint32_t r_shunt_uohms; + uint16_t compact_r_shunt_uohms; + + + + + + if (XdrvMailbox.data_len > 62){ + return false; + } + + strncpy(param_str, XdrvMailbox.data, XdrvMailbox.data_len + 1); + param_str[XdrvMailbox.data_len] = 0; + + + for (cp = param_str, i = 0, param_count = 0; *cp && (i < XdrvMailbox.data_len + 1) && (param_count <= 3); i++) + if (param_str[i] == ' ' || param_str[i] == ',' || param_str[i] == 0){ + param_str[i] = 0; + params[param_count] = cp; + + param_count++; + cp = param_str + i + 1; + } + + + if (p1 < 10 || p1 >= 50){ + + switch (p1){ + case 1: + Ina226Init(); + Response_P(PSTR("{\"Sensor54-Command-Result\":{\"SlavesFound\":%d}}"),slavesFound); + break; + + case 2: + restart_flag = 2; + Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Restart_flag\":%d}}"),restart_flag); + break; + + default: + serviced = false; + } + } + else if (p1 < 50){ + + device = (p1 / 10) - 1; + switch (p1 % 10){ + case 0: + show_config = true; + break; + + case 1: + r_shunt_uohms = (uint32_t) ((CharToFloat(params[1])) * 1000000.0f); + + + + if (r_shunt_uohms > 32767){ + uint32_t r_shunt_mohms = r_shunt_uohms/1000UL; + Settings.ina226_r_shunt[device] = (uint16_t) (r_shunt_mohms | 0x8000); + } + else + Settings.ina226_r_shunt[device] = (uint16_t) r_shunt_uohms; + + + show_config = true; + break; + + case 2: + Settings.ina226_i_fs[device] = (uint16_t) ((CharToFloat(params[1])) * 10.0f); + + show_config = true; + break; + + + default: + serviced = false; + break; + } + } + else + serviced = false; + + if (show_config) { + char shunt_r_str[16]; + char fs_i_str[16]; + + + r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[device]); + dtostrfd(((float)r_shunt_uohms)/1000000.0f, 6, shunt_r_str); + + dtostrfd(((float)Settings.ina226_i_fs[device])/10.0f, 1, fs_i_str); + + Response_P(PSTR("{\"Sensor54-device-settings-%d\":{\"SHUNT_R\":%s,\"FS_I\":%s}}"), + device + 1, shunt_r_str, fs_i_str); + } + + return serviced; +} + + + + + +#ifdef USE_WEBSERVER +const char HTTP_SNS_INA226_DATA[] PROGMEM = + "{s}%s " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}%s " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}%s " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; +#endif + +void Ina226Show(bool json) +{ + int i, num_found; + for (num_found = 0, i = 0; i < INA226_MAX_ADDRESSES; i++) { + + if (!slaveInfo[i].present) + continue; + + num_found++; + + char voltage[16]; + dtostrfd(voltages[i], Settings.flag2.voltage_resolution, voltage); + char current[16]; + dtostrfd(currents[i], Settings.flag2.current_resolution, current); + char power[16]; + dtostrfd(powers[i], Settings.flag2.wattage_resolution, power); + char name[16]; + snprintf_P(name, sizeof(name), PSTR("INA226%c%d"),IndexSeparator(), i + 1); + + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%02x,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), + name, i, voltage, current, power); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_VOLTAGE, voltage); + DomoticzSensor(DZ_CURRENT, current); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_INA226_DATA, name, voltage, name, current, name, power); +#endif + } + + } + +} +# 532 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_54_ina226.ino" +bool Xsns54(byte callback_id) { + + + bool result = false; + + + if(i2c_flg) { + + + switch (callback_id) { + case FUNC_EVERY_SECOND: + Ina226EverySecond(); + break; + case FUNC_INIT: + Ina226Init(); + break; + case FUNC_JSON_APPEND: + Ina226Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ina226Show(0); + break; +#endif + case FUNC_COMMAND_SENSOR: + if (XSNS_54 == XdrvMailbox.index) { + result = Ina226CommandSensor(); + } + break; + } + } + + return result; +} + +#endif +#endif +# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_interface.ino" +# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_interface.ino" +#ifdef XFUNC_PTR_IN_ROM +bool (* const xsns_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xsns_func_ptr[])(uint8_t) = { +#endif + +#ifdef XSNS_01 + &Xsns01, +#endif + +#ifdef XSNS_02 + &Xsns02, +#endif + +#ifdef XSNS_03 + &Xsns03, +#endif + +#ifdef XSNS_04 + &Xsns04, +#endif + +#ifdef XSNS_05 + &Xsns05, +#endif + +#ifdef XSNS_06 + &Xsns06, +#endif + +#ifdef XSNS_07 + &Xsns07, +#endif + +#ifdef XSNS_08 + &Xsns08, +#endif + +#ifdef XSNS_09 + &Xsns09, +#endif + +#ifdef XSNS_10 + &Xsns10, +#endif + +#ifdef XSNS_11 + &Xsns11, +#endif + +#ifdef XSNS_12 + &Xsns12, +#endif + +#ifdef XSNS_13 + &Xsns13, +#endif + +#ifdef XSNS_14 + &Xsns14, +#endif + +#ifdef XSNS_15 + &Xsns15, +#endif + +#ifdef XSNS_16 + &Xsns16, +#endif + +#ifdef XSNS_17 + &Xsns17, +#endif + +#ifdef XSNS_18 + &Xsns18, +#endif + +#ifdef XSNS_19 + &Xsns19, +#endif + +#ifdef XSNS_20 + &Xsns20, +#endif + +#ifdef XSNS_21 + &Xsns21, +#endif + +#ifdef XSNS_22 + &Xsns22, +#endif + +#ifdef XSNS_23 + &Xsns23, +#endif + +#ifdef XSNS_24 + &Xsns24, +#endif + +#ifdef XSNS_25 + &Xsns25, +#endif + +#ifdef XSNS_26 + &Xsns26, +#endif + +#ifdef XSNS_27 + &Xsns27, +#endif + +#ifdef XSNS_28 + &Xsns28, +#endif + +#ifdef XSNS_29 + &Xsns29, +#endif + +#ifdef XSNS_30 + &Xsns30, +#endif + +#ifdef XSNS_31 + &Xsns31, +#endif + +#ifdef XSNS_32 + &Xsns32, +#endif + +#ifdef XSNS_33 + &Xsns33, +#endif + +#ifdef XSNS_34 + &Xsns34, +#endif + +#ifdef XSNS_35 + &Xsns35, +#endif + +#ifdef XSNS_36 + &Xsns36, +#endif + +#ifdef XSNS_37 + &Xsns37, +#endif + +#ifdef XSNS_38 + &Xsns38, +#endif + +#ifdef XSNS_39 + &Xsns39, +#endif + +#ifdef XSNS_40 + &Xsns40, +#endif + +#ifdef XSNS_41 + &Xsns41, +#endif + +#ifdef XSNS_42 + &Xsns42, +#endif + +#ifdef XSNS_43 + &Xsns43, +#endif + +#ifdef XSNS_44 + &Xsns44, +#endif + +#ifdef XSNS_45 + &Xsns45, +#endif + +#ifdef XSNS_46 + &Xsns46, +#endif + +#ifdef XSNS_47 + &Xsns47, +#endif + +#ifdef XSNS_48 + &Xsns48, +#endif + +#ifdef XSNS_49 + &Xsns49, +#endif + +#ifdef XSNS_50 + &Xsns50, +#endif + +#ifdef XSNS_51 + &Xsns51, +#endif + +#ifdef XSNS_52 + &Xsns52, +#endif + +#ifdef XSNS_53 + &Xsns53, +#endif + +#ifdef XSNS_54 + &Xsns54, +#endif + +#ifdef XSNS_55 + &Xsns55, +#endif + +#ifdef XSNS_56 + &Xsns56, +#endif + +#ifdef XSNS_57 + &Xsns57, +#endif + +#ifdef XSNS_58 + &Xsns58, +#endif + +#ifdef XSNS_59 + &Xsns59, +#endif + +#ifdef XSNS_60 + &Xsns60, +#endif + +#ifdef XSNS_61 + &Xsns61, +#endif + +#ifdef XSNS_62 + &Xsns62, +#endif + +#ifdef XSNS_63 + &Xsns63, +#endif + +#ifdef XSNS_64 + &Xsns64, +#endif + +#ifdef XSNS_65 + &Xsns65, +#endif + +#ifdef XSNS_66 + &Xsns66, +#endif + +#ifdef XSNS_67 + &Xsns67, +#endif + +#ifdef XSNS_68 + &Xsns68, +#endif + +#ifdef XSNS_69 + &Xsns69, +#endif + +#ifdef XSNS_70 + &Xsns70, +#endif + +#ifdef XSNS_71 + &Xsns71, +#endif + +#ifdef XSNS_72 + &Xsns72, +#endif + +#ifdef XSNS_73 + &Xsns73, +#endif + +#ifdef XSNS_74 + &Xsns74, +#endif + +#ifdef XSNS_75 + &Xsns75, +#endif + +#ifdef XSNS_76 + &Xsns76, +#endif + +#ifdef XSNS_77 + &Xsns77, +#endif + +#ifdef XSNS_78 + &Xsns78, +#endif + +#ifdef XSNS_79 + &Xsns79, +#endif + +#ifdef XSNS_80 + &Xsns80, +#endif + +#ifdef XSNS_81 + &Xsns81, +#endif + +#ifdef XSNS_82 + &Xsns82, +#endif + +#ifdef XSNS_83 + &Xsns83, +#endif + +#ifdef XSNS_84 + &Xsns84, +#endif + +#ifdef XSNS_85 + &Xsns85, +#endif + +#ifdef XSNS_86 + &Xsns86, +#endif + +#ifdef XSNS_87 + &Xsns87, +#endif + +#ifdef XSNS_88 + &Xsns88, +#endif + +#ifdef XSNS_89 + &Xsns89, +#endif + +#ifdef XSNS_90 + &Xsns90, +#endif + +#ifdef XSNS_91 + &Xsns91, +#endif + +#ifdef XSNS_92 + &Xsns92, +#endif + +#ifdef XSNS_93 + &Xsns93, +#endif + +#ifdef XSNS_94 + &Xsns94, +#endif + +#ifdef XSNS_95 + &Xsns95, +#endif + +#ifdef XSNS_96 + &Xsns96, +#endif + +#ifdef XSNS_97 + &Xsns97, +#endif + +#ifdef XSNS_98 + &Xsns98, +#endif + +#ifdef XSNS_99 + &Xsns99 +#endif +}; + +const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); + + + + + +#ifdef XFUNC_PTR_IN_ROM +const uint8_t kXsnsList[] PROGMEM = { +#else +const uint8_t kXsnsList[] = { +#endif + +#ifdef XSNS_01 + XSNS_01, +#endif + +#ifdef XSNS_02 + XSNS_02, +#endif + +#ifdef XSNS_03 + XSNS_03, +#endif + +#ifdef XSNS_04 + XSNS_04, +#endif + +#ifdef XSNS_05 + XSNS_05, +#endif + +#ifdef XSNS_06 + XSNS_06, +#endif + +#ifdef XSNS_07 + XSNS_07, +#endif + +#ifdef XSNS_08 + XSNS_08, +#endif + +#ifdef XSNS_09 + XSNS_09, +#endif + +#ifdef XSNS_10 + XSNS_10, +#endif + +#ifdef XSNS_11 + XSNS_11, +#endif + +#ifdef XSNS_12 + XSNS_12, +#endif + +#ifdef XSNS_13 + XSNS_13, +#endif + +#ifdef XSNS_14 + XSNS_14, +#endif + +#ifdef XSNS_15 + XSNS_15, +#endif + +#ifdef XSNS_16 + XSNS_16, +#endif + +#ifdef XSNS_17 + XSNS_17, +#endif + +#ifdef XSNS_18 + XSNS_18, +#endif + +#ifdef XSNS_19 + XSNS_19, +#endif + +#ifdef XSNS_20 + XSNS_20, +#endif + +#ifdef XSNS_21 + XSNS_21, +#endif + +#ifdef XSNS_22 + XSNS_22, +#endif + +#ifdef XSNS_23 + XSNS_23, +#endif + +#ifdef XSNS_24 + XSNS_24, +#endif + +#ifdef XSNS_25 + XSNS_25, +#endif + +#ifdef XSNS_26 + XSNS_26, +#endif + +#ifdef XSNS_27 + XSNS_27, +#endif + +#ifdef XSNS_28 + XSNS_28, +#endif + +#ifdef XSNS_29 + XSNS_29, +#endif + +#ifdef XSNS_30 + XSNS_30, +#endif + +#ifdef XSNS_31 + XSNS_31, +#endif + +#ifdef XSNS_32 + XSNS_32, +#endif + +#ifdef XSNS_33 + XSNS_33, +#endif + +#ifdef XSNS_34 + XSNS_34, +#endif + +#ifdef XSNS_35 + XSNS_35, +#endif + +#ifdef XSNS_36 + XSNS_36, +#endif + +#ifdef XSNS_37 + XSNS_37, +#endif + +#ifdef XSNS_38 + XSNS_38, +#endif + +#ifdef XSNS_39 + XSNS_39, +#endif + +#ifdef XSNS_40 + XSNS_40, +#endif + +#ifdef XSNS_41 + XSNS_41, +#endif + +#ifdef XSNS_42 + XSNS_42, +#endif + +#ifdef XSNS_43 + XSNS_43, +#endif + +#ifdef XSNS_44 + XSNS_44, +#endif + +#ifdef XSNS_45 + XSNS_45, +#endif + +#ifdef XSNS_46 + XSNS_46, +#endif + +#ifdef XSNS_47 + XSNS_47, +#endif + +#ifdef XSNS_48 + XSNS_48, +#endif + +#ifdef XSNS_49 + XSNS_49, +#endif + +#ifdef XSNS_50 + XSNS_50, +#endif + +#ifdef XSNS_51 + XSNS_51, +#endif + +#ifdef XSNS_52 + XSNS_52, +#endif + +#ifdef XSNS_53 + XSNS_53, +#endif + +#ifdef XSNS_54 + XSNS_54, +#endif + +#ifdef XSNS_55 + XSNS_55, +#endif + +#ifdef XSNS_56 + XSNS_56, +#endif + +#ifdef XSNS_57 + XSNS_57, +#endif + +#ifdef XSNS_58 + XSNS_58, +#endif + +#ifdef XSNS_59 + XSNS_59, +#endif + +#ifdef XSNS_60 + XSNS_60, +#endif + +#ifdef XSNS_61 + XSNS_61, +#endif + +#ifdef XSNS_62 + XSNS_62, +#endif + +#ifdef XSNS_63 + XSNS_63, +#endif + +#ifdef XSNS_64 + XSNS_64, +#endif + +#ifdef XSNS_65 + XSNS_65, +#endif + +#ifdef XSNS_66 + XSNS_66, +#endif + +#ifdef XSNS_67 + XSNS_67, +#endif + +#ifdef XSNS_68 + XSNS_68, +#endif + +#ifdef XSNS_69 + XSNS_69, +#endif + +#ifdef XSNS_70 + XSNS_70, +#endif + +#ifdef XSNS_71 + XSNS_71, +#endif + +#ifdef XSNS_72 + XSNS_72, +#endif + +#ifdef XSNS_73 + XSNS_73, +#endif + +#ifdef XSNS_74 + XSNS_74, +#endif + +#ifdef XSNS_75 + XSNS_75, +#endif + +#ifdef XSNS_76 + XSNS_76, +#endif + +#ifdef XSNS_77 + XSNS_77, +#endif + +#ifdef XSNS_78 + XSNS_78, +#endif + +#ifdef XSNS_79 + XSNS_79, +#endif + +#ifdef XSNS_80 + XSNS_80, +#endif + +#ifdef XSNS_81 + XSNS_81, +#endif + +#ifdef XSNS_82 + XSNS_82, +#endif + +#ifdef XSNS_83 + XSNS_83, +#endif + +#ifdef XSNS_84 + XSNS_84, +#endif + +#ifdef XSNS_85 + XSNS_85, +#endif + +#ifdef XSNS_86 + XSNS_86, +#endif + +#ifdef XSNS_87 + XSNS_87, +#endif + +#ifdef XSNS_88 + XSNS_88, +#endif + +#ifdef XSNS_89 + XSNS_89, +#endif + +#ifdef XSNS_90 + XSNS_90, +#endif + +#ifdef XSNS_91 + XSNS_91, +#endif + +#ifdef XSNS_92 + XSNS_92, +#endif + +#ifdef XSNS_93 + XSNS_93, +#endif + +#ifdef XSNS_94 + XSNS_94, +#endif + +#ifdef XSNS_95 + XSNS_95, +#endif + +#ifdef XSNS_96 + XSNS_96, +#endif + +#ifdef XSNS_97 + XSNS_97, +#endif + +#ifdef XSNS_98 + XSNS_98, +#endif + +#ifdef XSNS_99 + XSNS_99 +#endif +}; + + + +bool XsnsEnabled(uint32_t sns_index) +{ + if (sns_index < sizeof(kXsnsList)) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t index = pgm_read_byte(kXsnsList + sns_index); +#else + uint32_t index = kXsnsList[sns_index]; +#endif + return bitRead(Settings.sensors[index / 32], index % 32); + } + return true; +} + +void XsnsSensorState(void) +{ + ResponseAppend_P(PSTR("\"")); + for (uint32_t i = 0; i < sizeof(kXsnsList); i++) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t sensorid = pgm_read_byte(kXsnsList + i); +#else + uint32_t sensorid = kXsnsList[i]; +#endif + bool disabled = false; + if (sensorid < MAX_XSNS_DRIVERS) { + disabled = !bitRead(Settings.sensors[sensorid / 32], sensorid % 32); + } + ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (disabled) ? "!" : "", sensorid); + } + ResponseAppend_P(PSTR("\"")); +} + + + + + +bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index) +{ + xsns_index++; + if (xsns_index == xsns_present) { xsns_index = 0; } + +#ifndef USE_DEBUG_DRIVER + if (FUNC_WEB_SENSOR == Function) { +#endif + uint32_t max_disabled = xsns_present; + while (!XsnsEnabled(xsns_index) && max_disabled--) { + xsns_index++; + if (xsns_index == xsns_present) { xsns_index = 0; } + } +#ifndef USE_DEBUG_DRIVER + } +#endif + + return xsns_func_ptr[xsns_index](Function); +} + +bool XsnsCall(uint8_t Function) +{ + bool result = false; + +#ifdef PROFILE_XSNS_EVERY_SECOND + uint32_t profile_start_millis = millis(); +#endif + + for (uint32_t x = 0; x < xsns_present; x++) { +#ifdef USE_DEBUG_DRIVER + if (XsnsEnabled(x)) { +#endif + + if ((FUNC_WEB_SENSOR == Function) && !XsnsEnabled(x)) { continue; } + +#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND + uint32_t profile_start_millis = millis(); +#endif + result = xsns_func_ptr[x](Function); + +#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND + uint32_t profile_millis = millis() - profile_start_millis; + if (profile_millis) { + if (FUNC_EVERY_SECOND == Function) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), uptime, Function, x, profile_millis); + } + } +#endif + + if (result && ((FUNC_COMMAND == Function) || + (FUNC_PIN_STATE == Function) || + (FUNC_COMMAND_SENSOR == Function) + )) { + break; + } +#ifdef USE_DEBUG_DRIVER + } +#endif + } + +#ifdef PROFILE_XSNS_EVERY_SECOND + uint32_t profile_millis = millis() - profile_start_millis; + if (profile_millis) { + if (FUNC_EVERY_SECOND == Function) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d took %u mS"), uptime, Function, profile_millis); + } + } +#endif + + return result; +} \ No newline at end of file diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index ec1303c33..2ae92dd50 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -92,7 +92,7 @@ const char HTTP_SCRIPT_COUNTER[] PROGMEM = "wl(u);"; const char HTTP_SCRIPT_ROOT[] PROGMEM = - + "var rfsh=1;" "function la(p){" "var a='';" "if(la.arguments.length==1){" @@ -107,14 +107,30 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "eb('l1').innerHTML=s;" "}" "};" - "x.open('GET','.?m=1'+a,true);" // ?m related to WebServer->hasArg("m") - "x.send();" - "lt=setTimeout(la,%d);" // Settings.web_refresh + "if (rfsh) {" + "x.open('GET','.?m=1'+a,true);" // ?m related to WebServer->hasArg("m") + "x.send();" + "lt=setTimeout(la,%d);" // Settings.web_refresh + "}" "}" #ifdef USE_SCRIPT_WEB_DISPLAY "function seva(par,ivar){" "la('&sv='+ivar+'_'+par);" "}" + "function siva(par,ivar){" + "rfsh=1;" + "la('&sv='+ivar+'_'+par);" + "rfsh=0;" + "}" + "function pr(f){" + "if (f) {" + "lt=setTimeout(la,%d);" + "rfsh=1;" + "} else {" + "clearTimeout(lt);" + "rfsh=0;" + "}" + "}" #endif @@ -939,7 +955,11 @@ void HandleRoot(void) char stemp[5]; WSContentStart_P(S_MAIN_MENU); +#ifdef USE_SCRIPT_WEB_DISPLAY + WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh, Settings.web_refresh); +#else WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh); +#endif WSContentSendStyle(); WSContentSend_P(PSTR("
")); diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index 265411637..5c7b7b6ae 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -1103,7 +1103,7 @@ chknext: fvar=cnt; glob_script_mem.file_flags[cnt].is_open=1; } else { - toLog("file open failed"); + AddLog_P(LOG_LEVEL_INFO,PSTR("file open failed")); } break; } @@ -2103,6 +2103,7 @@ void toLog(const char *str) { AddLog(LOG_LEVEL_INFO); } + void toLogN(const char *cp,uint8_t len) { if (!cp) return; char str[32]; @@ -2295,12 +2296,10 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { if (section) { // we are in section if (*lp=='>') { - section=0; - break; + return 0; } if (*lp=='#') { - section=0; - break; + return 0; } glob_script_mem.var_not_found=0; @@ -2734,6 +2733,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { char str[SCRIPT_MAXSSIZE]; lp=getop(lp,&lastop); char *slp=lp; + glob_script_mem.glob_error=0; lp=GetStringResult(lp,OPER_EQU,str,jo); if (!js && glob_script_mem.glob_error) { // mismatch @@ -2778,19 +2778,20 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { return 99; } // check for subroutine - if (*type=='#') { + char *ctype=(char*)type; + if (*ctype=='#') { // check for parameter - type+=tlen; - if (*type=='(') { + ctype+=tlen; + if (*ctype=='(' && *(lp+tlen)=='(') { float fparam; numeric=1; glob_script_mem.glob_error=0; - GetNumericResult((char*)type,OPER_EQU,&fparam,0); + GetNumericResult((char*)ctype,OPER_EQU,&fparam,0); if (glob_script_mem.glob_error==1) { // was string, not number numeric=0; // get the string - GetStringResult((char*)type+1,OPER_EQU,cmpstr,0); + GetStringResult((char*)ctype+1,OPER_EQU,cmpstr,0); } lp+=tlen; if (*lp=='(') { @@ -2821,6 +2822,12 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { } } } + } else { + lp+=tlen; + if (*ctype=='(' || (*lp!=SCRIPT_EOL && *lp!='?')) { + // revert + section=0; + } } } } @@ -2831,11 +2838,17 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { lp++; } else { lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; + if (!lp) { + if (section) { + return 0; + } else { + return -1; + } + } lp++; } } - return 0; + return -1; } uint8_t script_xsns_index = 0; @@ -3151,13 +3164,13 @@ uint8_t DownloadFile(char *file) { WiFiClient download_Client; if (!SD.exists(file)) { - toLog("file not found"); + AddLog_P(LOG_LEVEL_INFO,PSTR("file not found")); return 0; } download_file=SD.open(file,FILE_READ); if (!download_file) { - toLog("could not open file"); + AddLog_P(LOG_LEVEL_INFO,PSTR("could not open file")); return 0; } @@ -3320,6 +3333,36 @@ void ScriptSaveSettings(void) { #endif + +#ifdef USE_SCRIPT_SUB_COMMAND +bool Script_SubCmd(void) { + if (!bitRead(Settings.rule_enabled, 0)) return false; + + char cmdbuff[128]; + char *cp=cmdbuff; + *cp++='#'; + strcpy(cp,XdrvMailbox.topic); + uint8_t tlen=strlen(XdrvMailbox.topic); + cp+=tlen; + if (XdrvMailbox.index > 0) { + *cp++=XdrvMailbox.index|0x30; + tlen++; + } + if ((XdrvMailbox.payload>0) || (XdrvMailbox.data_len>0)) { + *cp++='('; + strncpy(cp,XdrvMailbox.data,XdrvMailbox.data_len); + cp+=XdrvMailbox.data_len; + *cp++=')'; + *cp=0; + } + //toLog(cmdbuff); + uint32_t res=Run_Scripter(cmdbuff,tlen+1,0); + //AddLog_P2(LOG_LEVEL_INFO,">>%d",res); + if (res) return false; + else return true; +} +#endif + void execute_script(char *script) { char *svd_sp=glob_script_mem.scriptptr; strcat(script,"\n#"); @@ -3341,6 +3384,20 @@ bool ScriptCommand(void) { int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kScriptCommands); if (-1 == command_code) { +#ifdef USE_SCRIPT_SUB_COMMAND + strlcpy(command,XdrvMailbox.topic,CMDSZ); + uint32_t pl=XdrvMailbox.payload; + char pld[64]; + strlcpy(pld,XdrvMailbox.data,sizeof(pld)); + if (Script_SubCmd()) { + if (pl>=0) { + Response_P(S_JSON_COMMAND_NVALUE, command, pl); + } else { + Response_P(S_JSON_COMMAND_SVALUE, command, pld); + } + return serviced; + } +#endif serviced = false; // Unknown command } else if ((CMND_SCRIPT == command_code) && (index > 0)) { @@ -3365,15 +3422,15 @@ bool ScriptCommand(void) { return serviced; } snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\",\"Free\":%d}"),command, GetStateText(bitRead(Settings.rule_enabled,0)),glob_script_mem.script_size-strlen(glob_script_mem.script_ram)); - #ifdef SUPPORT_MQTT_EVENT +#ifdef SUPPORT_MQTT_EVENT } else if (CMND_SUBSCRIBE == command_code) { //MQTT Subscribe command. Subscribe , [, ] String result = ScriptSubscribe(XdrvMailbox.data, XdrvMailbox.data_len); Response_P(S_JSON_COMMAND_SVALUE, command, result.c_str()); } else if (CMND_UNSUBSCRIBE == command_code) { //MQTT Un-subscribe command. UnSubscribe String result = ScriptUnsubscribe(XdrvMailbox.data, XdrvMailbox.data_len); Response_P(S_JSON_COMMAND_SVALUE, command, result.c_str()); - #endif //SUPPORT_MQTT_EVENT - } +#endif //SUPPORT_MQTT_EVENT + } return serviced; } @@ -3628,24 +3685,43 @@ void Script_Check_HTML_Setvars(void) { //toLog(cmdbuf); execute_script(cmdbuf); + Run_Scripter(">E",2,0); } } + +const char SCRIPT_MSG_BUTTONa[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUTTONa_TBL[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUTTONb[] PROGMEM = + "<\img>"; + +const char SCRIPT_MSG_BUT_START[] PROGMEM = + "
"; +const char SCRIPT_MSG_BUT_START_TBL[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUT_STOP[] PROGMEM = + ""; +const char SCRIPT_MSG_BUT_STOP_TBL[] PROGMEM = + "
"; + const char SCRIPT_MSG_SLIDER[] PROGMEM = "
%s
%s%s
" "
"; -const char SCRIPT_MSG_BUTTON[] PROGMEM = - "
"; - const char SCRIPT_MSG_CHKBOX[] PROGMEM = "
"; const char SCRIPT_MSG_TEXTINP[] PROGMEM = - "
"; + "
"; + +const char SCRIPT_MSG_NUMINP[] PROGMEM = + "
"; -// -// void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen) { uint32_t cnt; @@ -3663,6 +3739,7 @@ void ScriptWebShow(void) { if (web_script==99) { char line[128]; char tmp[128]; + uint8_t optflg=0; char *lp=glob_script_mem.section_ptr+2; while (lp) { while (*lp==SCRIPT_EOL) { @@ -3683,10 +3760,17 @@ void ScriptWebShow(void) { } cp++; } + char *lin=line; + if (*lin=='@') { + lin++; + optflg=1; + } else { + optflg=0; + } // check for input elements - if (!strncmp(line,"sl(",3)) { + if (!strncmp(lin,"sl(",3)) { // insert slider sl(min max var left mid right) - char *lp=line; + char *lp=lin; float min; lp=GetNumericResult(lp+3,OPER_EQU,&min,0); SCRIPT_SKIP_SPACES @@ -3715,8 +3799,8 @@ void ScriptWebShow(void) { WSContentSend_PD(SCRIPT_MSG_SLIDER,left,mid,right,(uint32_t)min,(uint32_t)max,(uint32_t)val,vname); - } else if (!strncmp(line,"ck(",3)) { - char *lp=line+3; + } else if (!strncmp(lin,"ck(",3)) { + char *lp=lin+3; char *slp=lp; float val; lp=GetNumericResult(lp,OPER_EQU,&val,0); @@ -3727,7 +3811,7 @@ void ScriptWebShow(void) { char label[SCRIPT_MAXSSIZE]; lp=GetStringResult(lp,OPER_EQU,label,0); - char *cp; + const char *cp; uint8_t uval; if (val>0) { cp="checked='checked'"; @@ -3736,38 +3820,64 @@ void ScriptWebShow(void) { cp=""; uval=1; } - WSContentSend_PD(SCRIPT_MSG_CHKBOX,label,cp,uval,vname); + WSContentSend_PD(SCRIPT_MSG_CHKBOX,label,(char*)cp,uval,vname); - } else if (!strncmp(line,"bu(",3)) { - char *lp=line+3; - char *slp=lp; - float val; - lp=GetNumericResult(lp,OPER_EQU,&val,0); - SCRIPT_SKIP_SPACES - - char vname[16]; - ScriptGetVarname(vname,slp,sizeof(vname)); - - SCRIPT_SKIP_SPACES - char ontxt[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,ontxt,0); - SCRIPT_SKIP_SPACES - char offtxt[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,offtxt,0); - - char *cp; - uint8_t uval; - if (val>0) { - cp=ontxt; - uval=0; - } else { - cp=offtxt; - uval=1; + } else if (!strncmp(lin,"bu(",3)) { + char *lp=lin+3; + uint8_t bcnt=0; + char *found=lin; + while (bcnt<4) { + found=strstr(found,"bu("); + if (!found) break; + found+=3; + bcnt++; } - WSContentSend_PD(SCRIPT_MSG_BUTTON,uval,vname,cp); + uint8_t proz=100/bcnt; + if (!optflg && bcnt>1) proz-=2; + if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_START_TBL); + else WSContentSend_PD(SCRIPT_MSG_BUT_START); + for (uint32_t cnt=0;cnt0) { + cp=ontxt; + uval=0; + } else { + cp=offtxt; + uval=1; + } + if (bcnt>1 && cnt==bcnt-1) { + if (!optflg) proz+=2; + } + if (!optflg) { + WSContentSend_PD(SCRIPT_MSG_BUTTONa,proz,uval,vname,cp); + } else { + WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL,proz,uval,vname,cp); + } + if (bcnt>1 && cnt%s
"),&tmp[1]); + } else if (!strncmp(lin,"nm(",3)) { + char *lp=lin; + float min; + lp=GetNumericResult(lp+3,OPER_EQU,&min,0); + SCRIPT_SKIP_SPACES + float max; + lp=GetNumericResult(lp,OPER_EQU,&max,0); + SCRIPT_SKIP_SPACES + float step; + lp=GetNumericResult(lp,OPER_EQU,&step,0); + SCRIPT_SKIP_SPACES + float val; + char *slp=lp; + lp=GetNumericResult(lp,OPER_EQU,&val,0); + SCRIPT_SKIP_SPACES + char vname[16]; + ScriptGetVarname(vname,slp,sizeof(vname)); + + char label[SCRIPT_MAXSSIZE]; + lp=GetStringResult(lp,OPER_EQU,label,0); + + char vstr[16],minstr[16],maxstr[16],stepstr[16]; + dtostrfd(val,4,vstr); + dtostrfd(min,4,minstr); + dtostrfd(max,4,maxstr); + dtostrfd(step,4,stepstr); + WSContentSend_PD(SCRIPT_MSG_NUMINP,label,minstr,maxstr,stepstr,vstr,vname); + + } else { + Replace_Cmd_Vars(lin,tmp,sizeof(tmp)); + if (optflg) { + WSContentSend_PD(PSTR("
%s
"),tmp); } else { WSContentSend_PD(PSTR("{s}%s{e}"),tmp); } From 5e5fc79ca1a097f91b7bf3cc33867c78f8bd576d Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 24 Sep 2019 08:27:43 +0200 Subject: [PATCH 1980/2222] Delete sonoff.ino.cpp --- sonoff/sonoff.ino.cpp | 63483 ---------------------------------------- 1 file changed, 63483 deletions(-) delete mode 100644 sonoff/sonoff.ino.cpp diff --git a/sonoff/sonoff.ino.cpp b/sonoff/sonoff.ino.cpp deleted file mode 100644 index fb7072f47..000000000 --- a/sonoff/sonoff.ino.cpp +++ /dev/null @@ -1,63483 +0,0 @@ -# 1 "/var/folders/vn/7y9hnjrw8xl9lm006s6r35t80000gr/T/tmpQqdpT0" -#include -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/sonoff.ino" -# 29 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/sonoff.ino" -#include -#include "sonoff_version.h" -#include "sonoff.h" -#include "my_user_config.h" -#ifdef USE_MQTT_TLS - #include -#endif -#include "sonoff_post.h" -#include "i18n.h" -#include "sonoff_template.h" - - -#ifdef ARDUINO_ESP8266_RELEASE_2_4_0 -#include "lwip/init.h" -#if LWIP_VERSION_MAJOR != 1 - #error Please use stable lwIP v1.4 -#endif -#endif - - -#include -#include -#include -#include -#ifdef USE_ARDUINO_OTA - #include - #ifndef USE_DISCOVERY - #define USE_DISCOVERY - #endif -#endif -#ifdef USE_DISCOVERY - #include -#endif -#ifdef USE_I2C - #include -#endif -#ifdef USE_SPI - #include -#endif - - -#include "settings.h" - -const char kSleepMode[] PROGMEM = "Dynamic|Normal"; - - -SerialConfig serial_config = SERIAL_8N1; - -WiFiUDP PortUdp; - -unsigned long feature_drv1; -unsigned long feature_drv2; -unsigned long feature_sns1; -unsigned long feature_sns2; -unsigned long feature5; -unsigned long serial_polling_window = 0; -unsigned long state_second = 0; -unsigned long state_50msecond = 0; -unsigned long state_100msecond = 0; -unsigned long state_250msecond = 0; -unsigned long pulse_timer[MAX_PULSETIMERS] = { 0 }; -unsigned long blink_timer = 0; -unsigned long backlog_delay = 0; -power_t power = 0; -power_t last_power = 0; -power_t blink_power; -power_t blink_mask = 0; -power_t blink_powersave; -power_t latching_power = 0; -power_t rel_inverted = 0; -int baudrate = APP_BAUDRATE; -int serial_in_byte_counter = 0; -int ota_state_flag = 0; -int ota_result = 0; -int restart_flag = 0; -int wifi_state_flag = WIFI_RESTART; -int tele_period = 1; -int blinks = 201; -uint32_t uptime = 0; -uint32_t loop_load_avg = 0; -uint32_t global_update = 0; -uint32_t web_log_index = 1; -float global_temperature = 9999; -float global_humidity = 0; -float global_pressure = 0; -char *ota_url; -uint16_t mqtt_cmnd_publish = 0; -uint16_t blink_counter = 0; -uint16_t seriallog_timer = 0; -uint16_t syslog_timer = 0; -int16_t save_data_counter; -RulesBitfield rules_flag; -uint8_t state_250mS = 0; -uint8_t latching_relay_pulse = 0; -uint8_t sleep; -uint8_t blinkspeed = 1; -uint8_t pin[GPIO_MAX]; -uint8_t active_device = 1; -uint8_t leds_present = 0; -uint8_t led_inverted = 0; -uint8_t led_power = 0; -uint8_t ledlnk_inverted = 0; -uint8_t pwm_inverted = 0; -uint8_t energy_flg = 0; -uint8_t light_type = 0; -uint8_t serial_in_byte; -uint8_t ota_retry_counter = OTA_ATTEMPTS; -uint8_t devices_present = 0; -uint8_t seriallog_level; -uint8_t syslog_level; -uint8_t my_module_type; -uint8_t my_adc0; - -bool serial_local = false; -bool fallback_topic_flag = false; -bool backlog_mutex = false; -bool interlock_mutex = false; -bool stop_flash_rotate = false; -bool blinkstate = false; - -bool pwm_present = false; -bool i2c_flg = false; -bool spi_flg = false; -bool soft_spi_flg = false; -bool ntp_force_sync = false; -bool ntp_synced_message = false; -myio my_module; -gpio_flag my_module_flag; -StateBitfield global_state; -char my_version[33]; -char my_image[33]; -char my_hostname[33]; -char mqtt_client[33]; -char mqtt_topic[33]; -char serial_in_buffer[INPUT_BUFFER_SIZE]; -char mqtt_data[MESSZ]; -char log_data[LOGSZ]; -char web_log[WEB_LOG_SIZE] = {'\0'}; -#ifdef SUPPORT_IF_STATEMENT - #include - LinkedList backlog; - #define BACKLOG_EMPTY (backlog.size() == 0) -#else - uint8_t backlog_index = 0; - uint8_t backlog_pointer = 0; - String backlog[MAX_BACKLOG]; - #define BACKLOG_EMPTY (backlog_pointer == backlog_index) -#endif -char* Format(char* output, const char* input, int size); -char* GetOtaUrl(char *otaurl, size_t otaurl_size); -char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic); -char* GetFallbackTopic_P(char *stopic, uint32_t prefix, const char* subtopic); -char* GetStateText(uint32_t state); -void SetLatchingRelay(power_t lpower, uint32_t state); -void SetDevicePower(power_t rpower, uint32_t source); -void RestorePower(bool publish_power, uint32_t source); -void SetAllPower(uint32_t state, uint32_t source); -void SetLedPowerIdx(uint32_t led, uint32_t state); -void SetLedPower(uint32_t state); -void SetLedPowerAll(uint32_t state); -void SetLedLink(uint32_t state); -void SetPulseTimer(uint32_t index, uint32_t time); -uint32_t GetPulseTimer(uint32_t index); -bool SendKey(uint32_t key, uint32_t device, uint32_t state); -void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source); -void StopAllPowerBlink(void); -void MqttShowPWMState(void); -void MqttShowState(void); -void MqttPublishTeleState(void); -bool MqttShowSensor(void); -void PerformEverySecond(void); -void Every100mSeconds(void); -void Every250mSeconds(void); -void ArduinoOTAInit(void); -void SerialInput(void); -void GpioInit(void); -void setup(void); -void loop(void); -uint32_t GetRtcSettingsCrc(void); -void RtcSettingsSave(void); -void RtcSettingsLoad(void); -bool RtcSettingsValid(void); -uint32_t GetRtcRebootCrc(void); -void RtcRebootSave(void); -void RtcRebootLoad(void); -bool RtcRebootValid(void); -void SetFlashModeDout(void); -void SettingsBufferFree(void); -bool SettingsBufferAlloc(void); -uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size); -uint16_t GetSettingsCrc(void); -uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size); -uint32_t GetSettingsCrc32(void); -void SettingsSaveAll(void); -uint32_t GetSettingsAddress(void); -void SettingsSave(uint8_t rotate); -void SettingsLoad(void); -void SettingsErase(uint8_t type); -bool SettingsEraseConfig(void); -void SettingsSdkErase(void); -void SettingsDefault(void); -void SettingsDefaultSet1(void); -void SettingsDefaultSet2(void); -void SettingsDefaultSet_5_8_1(void); -void SettingsDefaultSet_5_10_1(void); -void SettingsResetStd(void); -void SettingsResetDst(void); -void SettingsDefaultSet_5_13_1c(void); -void SettingsDefaultWebColor(void); -void SettingsDelta(void); -void OsWatchTicker(void); -void OsWatchInit(void); -void OsWatchLoop(void); -String GetResetReason(void); -bool OsWatchBlockedLoop(void); -void* memchr(const void* ptr, int value, size_t num); -size_t strcspn(const char *str1, const char *str2); -char* strpbrk(const char *s1, const char *s2); -size_t strchrspn(const char *str1, int character); -char* subStr(char* dest, char* str, const char *delim, int index); -float CharToFloat(const char *str); -int TextToInt(char *str); -char* ulltoa(unsigned long long value, char *str, int radix); -char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween); -char* Uint64toHex(uint64_t value, char *str, uint16_t bits); -char* dtostrfd(double number, unsigned char prec, char *s); -char* Unescape(char* buffer, uint32_t* size); -char* RemoveSpace(char* p); -char* LowerCase(char* dest, const char* source); -char* UpperCase(char* dest, const char* source); -char* UpperCase_P(char* dest, const char* source); -char* Trim(char* p); -char* NoAlNumToUnderscore(char* dest, const char* source); -char IndexSeparator(); -void SetShortcutDefault(void); -uint8_t Shortcut(); -bool ValidIpAddress(const char* str); -bool ParseIp(uint32_t* addr, const char* str); -bool NewerVersion(char* version_str); -char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option); -char* GetPowerDevice(char* dest, uint32_t idx, size_t size); -float ConvertTemp(float c); -float ConvertTempToCelsius(float c); -char TempUnit(void); -float ConvertHumidity(float h); -float ConvertPressure(float p); -String PressureUnit(void); -void ResetGlobalValues(void); -uint32_t SqrtInt(uint32_t num); -uint32_t RoundSqrtInt(uint32_t num); -char* GetTextIndexed(char* destination, size_t destination_size, uint32_t index, const char* haystack); -int GetCommandCode(char* destination, size_t destination_size, const char* needle, const char* haystack); -int GetStateNumber(char *state_text); -void SetSerialBaudrate(int baudrate); -void ClaimSerial(void); -void SerialSendRaw(char *codes); -uint32_t GetHash(const char *buffer, size_t size); -void ShowSource(uint32_t source); -void WebHexCode(uint32_t i, const char* code); -uint32_t WebColor(uint32_t i); -char* ResponseGetTime(uint32_t format, char* time_str); -int Response_P(const char* format, ...); -int ResponseTime_P(const char* format, ...); -int ResponseAppend_P(const char* format, ...); -int ResponseAppendTimeFormat(uint32_t format); -int ResponseAppendTime(void); -int ResponseJsonEnd(void); -int ResponseJsonEndEnd(void); -uint8_t ModuleNr(); -bool ValidTemplateModule(uint32_t index); -bool ValidModule(uint32_t index); -String AnyModuleName(uint32_t index); -String ModuleName(); -void ModuleGpios(myio *gp); -gpio_flag ModuleFlag(); -void ModuleDefault(uint32_t module); -void SetModuleType(); -uint8_t ValidPin(uint32_t pin, uint32_t gpio); -bool ValidGPIO(uint32_t pin, uint32_t gpio); -bool ValidAdc(); -bool GetUsedInModule(uint32_t val, uint8_t *arr); -bool JsonTemplate(const char* dataBuf); -void TemplateJson(); -long TimeDifference(unsigned long prev, unsigned long next); -long TimePassedSince(unsigned long timestamp); -bool TimeReached(unsigned long timer); -void SetNextTimeInterval(unsigned long& timer, const unsigned long step); -bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size); -bool I2cValidRead8(uint8_t *data, uint8_t addr, uint8_t reg); -bool I2cValidRead16(uint16_t *data, uint8_t addr, uint8_t reg); -bool I2cValidReadS16(int16_t *data, uint8_t addr, uint8_t reg); -bool I2cValidRead16LE(uint16_t *data, uint8_t addr, uint8_t reg); -bool I2cValidReadS16_LE(int16_t *data, uint8_t addr, uint8_t reg); -bool I2cValidRead24(int32_t *data, uint8_t addr, uint8_t reg); -uint8_t I2cRead8(uint8_t addr, uint8_t reg); -uint16_t I2cRead16(uint8_t addr, uint8_t reg); -int16_t I2cReadS16(uint8_t addr, uint8_t reg); -uint16_t I2cRead16LE(uint8_t addr, uint8_t reg); -int16_t I2cReadS16_LE(uint8_t addr, uint8_t reg); -int32_t I2cRead24(uint8_t addr, uint8_t reg); -bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size); -bool I2cWrite8(uint8_t addr, uint8_t reg, uint16_t val); -bool I2cWrite16(uint8_t addr, uint8_t reg, uint16_t val); -int8_t I2cReadBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len); -int8_t I2cWriteBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len); -void I2cScan(char *devs, unsigned int devs_len); -bool I2cDevice(uint8_t addr); -void SetSeriallog(uint32_t loglevel); -void SetSyslog(uint32_t loglevel); -void GetLog(uint32_t idx, char** entry_pp, size_t* len_p); -void Syslog(void); -void AddLog(uint32_t loglevel); -void AddLog_P(uint32_t loglevel, const char *formatP); -void AddLog_P(uint32_t loglevel, const char *formatP, const char *formatP2); -void AddLog_P2(uint32_t loglevel, PGM_P formatP, ...); -void AddLog_Debug(PGM_P formatP, ...); -void AddLogBuffer(uint32_t loglevel, uint8_t *buffer, uint32_t count); -void AddLogSerial(uint32_t loglevel); -void AddLogMissed(char *sensor, uint32_t misses); -void ButtonPullupFlag(uint8 button_bit); -void ButtonInvertFlag(uint8 button_bit); -void ButtonInit(void); -uint8_t ButtonSerial(uint8_t serial_in_byte); -void ButtonHandler(void); -void ButtonLoop(void); -void ResponseCmndNumber(int value); -void ResponseCmndIdxNumber(int value); -void ResponseCmndChar(const char* value); -void ResponseCmndStateText(uint32_t value); -void ResponseCmndDone(void); -void ResponseCmndIdxChar(const char* value); -void ExecuteCommand(char *cmnd, uint32_t source); -void CommandHandler(char* topic, uint8_t* data, uint32_t data_len); -void CmndBacklog(void); -void CmndDelay(void); -void CmndPower(void); -void CmndStatus(void); -void CmndState(void); -void CmndSleep(void); -void CmndUpgrade(void); -void CmndOtaUrl(void); -void CmndSeriallog(void); -void CmndRestart(void); -void CmndPowerOnState(void); -void CmndPulsetime(void); -void CmndBlinktime(void); -void CmndBlinkcount(void); -void CmndSavedata(void); -void CmndSetoption(void); -void CmndTemperatureResolution(void); -void CmndHumidityResolution(void); -void CmndPressureResolution(void); -void CmndPowerResolution(void); -void CmndVoltageResolution(void); -void CmndFrequencyResolution(void); -void CmndCurrentResolution(void); -void CmndEnergyResolution(void); -void CmndWeightResolution(void); -void CmndModule(void); -void CmndModules(void); -void CmndGpio(void); -void CmndGpios(void); -void CmndTemplate(void); -void CmndPwm(void); -void CmndPwmfrequency(void); -void CmndPwmrange(void); -void CmndButtonDebounce(void); -void CmndSwitchDebounce(void); -void CmndBaudrate(void); -void CmndSerialSend(void); -void CmndSerialDelimiter(void); -void CmndSyslog(void); -void CmndLoghost(void); -void CmndLogport(void); -void CmndIpAddress(void); -void CmndNtpServer(void); -void CmndAp(void); -void CmndSsid(void); -void CmndPassword(void); -void CmndHostname(void); -void CmndWifiConfig(void); -void CmndFriendlyname(void); -void CmndSwitchMode(void); -void CmndInterlock(void); -void CmndTeleperiod(void); -void CmndReset(void); -void CmndTime(void); -void CmndTimezone(void); -void CmndTimeStdDst(uint32_t ts); -void CmndTimeStd(void); -void CmndTimeDst(void); -void CmndAltitude(void); -void CmndLedPower(void); -void CmndLedState(void); -void CmndLedMask(void); -void CmndI2cScan(void); -void CmndSensor(void); -void CmndDriver(void); -void GetFeatures(void); -float fmodf(float x, float y); -double FastPrecisePow(double a, double b); -float FastPrecisePowf(const float x, const float y); -double TaylorLog(double x); -inline float sinf(float x); -inline float cosf(float x); -inline float tanf(float x); -inline float atanf(float x); -inline float asinf(float x); -inline float acosf(float x); -inline float sqrtf(float x); -inline float powf(float x, float y); -float cos_52s(float x); -float cos_52(float x); -float sin_52(float x); -float tan_56s(float x); -float tan_56(float x); -float atan_66s(float x); -float atan_66(float x); -float asinf1(float x); -float acosf1(float x); -float sqrt1(const float x); -uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max, - uint16_t ito_min, uint16_t ito_max); -void update_position(void); -void update_rotary(void); -bool RotaryButtonPressed(void); -void RotaryInit(void); -void RotaryHandler(void); -void RotaryLoop(void); -uint32_t UtcTime(void); -uint32_t LocalTime(void); -int32_t DriftTime(void); -uint32_t Midnight(void); -bool MidnightNow(void); -bool IsDst(void); -String GetBuildDateAndTime(void); -String GetTimeZone(void); -String GetDuration(uint32_t time); -String GetDT(uint32_t time); -String GetDateAndTime(uint8_t time_type); -String GetTime(int type); -uint32_t UpTime(void); -uint32_t MinutesUptime(void); -String GetUptime(void); -uint32_t MinutesPastMidnight(void); -void BreakTime(uint32_t time_input, TIME_T &tm); -uint32_t MakeTime(TIME_T &tm); -uint32_t RuleToTime(TimeRule r, int yr); -void RtcSecond(void); -void RtcSetTime(uint32_t epoch); -void RtcInit(void); -void SwitchPullupFlag(uint16 switch_bit); -uint8_t SwitchLastState(uint8_t index); -void SwitchSetVirtual(uint8_t index, uint8_t state); -uint8_t SwitchGetVirtual(uint8_t index); -void SwitchProbe(void); -void SwitchInit(void); -void SwitchHandler(uint8_t mode); -void SwitchLoop(void); -bool UdpDisconnect(void); -bool UdpConnect(void); -void PollUdp(void); -int WifiGetRssiAsQuality(int rssi); -bool WifiConfigCounter(void); -bool WifiWpsConfigDone(void); -bool WifiWpsConfigBegin(void); -void WifiConfig(uint8_t type); -void WiFiSetSleepMode(void); -void WifiBegin(uint8_t flag, uint8_t channel); -void WifiBeginAfterScan(); -uint16_t WifiLinkCount(); -String WifiDowntime(); -void WifiSetState(uint8_t state); -void WifiCheckIp(void); -void WifiCheck(uint8_t param); -int WifiState(void); -void WifiConnect(void); -void WifiDisconnect(void); -void EspRestart(void); -static void WebGetArg(const char* arg, char* out, size_t max); -static bool WifiIsInManagerMode(); -void ShowWebSource(uint32_t source); -void ExecuteWebCommand(char* svalue, uint32_t source); -void StartWebserver(int type, IPAddress ipweb); -void StopWebserver(void); -void WifiManagerBegin(bool reset_only); -void PollDnsWebserver(void); -bool WebAuthenticate(void); -void WSHeaderSend(void); -void WSSend(int code, int ctype, const String& content); -void WSContentBegin(int code, int ctype); -void _WSContentSend(const String& content); -void WSContentFlush(); -void _WSContentSendBuffer(void); -void WSContentSend_P(const char* formatP, ...); -void WSContentSend_PD(const char* formatP, ...); -void WSContentStart_P(const char* title, bool auth); -void WSContentStart_P(const char* title); -void WSContentSendStyle_P(const char* formatP, ...); -void WSContentSendStyle(void); -void WSContentButton(uint32_t title_index); -void WSContentSpaceButton(uint32_t title_index); -void WSContentEnd(void); -void WSContentStop(void); -void WebRestart(uint32_t type); -void HandleWifiLogin(void); -void HandleRoot(void); -bool HandleRootStatusRefresh(void); -void HandleConfiguration(void); -void HandleTemplateConfiguration(void); -void TemplateSaveSettings(void); -void HandleModuleConfiguration(void); -void ModuleSaveSettings(void); -String HtmlEscape(const String unescaped); -void HandleWifiConfiguration(void); -void WifiSaveSettings(void); -void HandleLoggingConfiguration(void); -void LoggingSaveSettings(void); -void HandleOtherConfiguration(void); -void OtherSaveSettings(void); -void HandleBackupConfiguration(void); -void HandleResetConfiguration(void); -void HandleRestoreConfiguration(void); -void HandleInformation(void); -void HandleUpgradeFirmware(void); -void HandleUpgradeFirmwareStart(void); -void HandleUploadDone(void); -void HandleUploadLoop(void); -void HandlePreflightRequest(void); -void HandleHttpCommand(void); -void HandleConsole(void); -void HandleConsoleRefresh(void); -void HandleNotFound(void); -bool CaptivePortal(void); -String UrlEncode(const String& text); -uint16_t SendMail(char *buffer); -int WebSend(char *buffer); -bool JsonWebColor(const char* dataBuf); -void CmndEmulation(void); -void CmndSendmail(void); -void CmndWebServer(void); -void CmndWebPassword(void); -void CmndWeblog(void); -void CmndWebRefresh(void); -void CmndWebSend(void); -void CmndWebColor(void); -void CmndWebSensor(void); -bool Xdrv01(uint8_t function); -bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value); -void setLongMqttHost(const char *mqtt_host); -void MakeValidMqtt(uint32_t option, char* str); -void MqttDiscoverServer(void); -void MqttInit(void); -bool MqttIsConnected(void); -void MqttDisconnect(void); -void MqttSubscribeLib(const char *topic); -void MqttUnsubscribeLib(const char *topic); -bool MqttPublishLib(const char* topic, bool retained); -void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len); -void MqttRetryCounter(uint8_t value); -void MqttSubscribe(const char *topic); -void MqttUnsubscribe(const char *topic); -void MqttPublishDirect(const char* topic, bool retained); -void MqttPublish(const char* topic, bool retained); -void MqttPublish(const char* topic); -void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained); -void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic); -void MqttPublishPowerState(uint32_t device); -void MqttPublishAllPowerState(); -void MqttPublishPowerBlinkState(uint32_t device); -uint16_t MqttConnectCount(); -void MqttDisconnected(int state); -void MqttConnected(void); -void MqttReconnect(void); -void MqttCheck(void); -void CmndMqttFingerprint(void); -void CmndMqttUser(void); -void CmndMqttPassword(void); -void CmndMqttHost(void); -void CmndMqttPort(void); -void CmndMqttRetry(void); -void CmndStateText(void); -void CmndMqttClient(void); -void CmndFullTopic(void); -void CmndPrefix(void); -void CmndPublish(void); -void CmndGroupTopic(void); -void CmndTopic(void); -void CmndButtonTopic(void); -void CmndSwitchTopic(void); -void CmndButtonRetain(void); -void CmndSwitchRetain(void); -void CmndPowerRetain(void); -void CmndSensorRetain(void); -inline void TlsEraseBuffer(uint8_t *buffer); -void loadTlsDir(void); -void CmndTlsKey(void); -void TlsWriteSpiBuffer(uint8_t *buf); -uint32_t bswap32(uint32_t x); -void CmndTlsDump(void); -void HandleMqttConfiguration(void); -void MqttSaveSettings(void); -bool Xdrv02(uint8_t function); -bool EnergyTariff1Active(); -void EnergyUpdateToday(void); -void EnergyUpdateTotal(float value, bool kwh); -void Energy200ms(void); -void EnergySaveState(void); -bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag); -void EnergyMarginCheck(void); -void EnergyMqttShow(void); -void EnergyEverySecond(); -void EnergyCommandResponse(uint32_t nvalue, uint32_t unit); -void CmndEnergyReset(void); -void CmndTariff(void); -void CmndPowerCal(void); -void CmndVoltageCal(void); -void CmndCurrentCal(void); -void CmndPowerSet(void); -void CmndVoltageSet(void); -void CmndCurrentSet(void); -void CmndFrequencySet(void); -void CmndModuleAddress(void); -void CmndPowerDelta(void); -void CmndPowerLow(void); -void CmndPowerHigh(void); -void CmndVoltageLow(void); -void CmndVoltageHigh(void); -void CmndCurrentLow(void); -void CmndCurrentHigh(void); -void CmndMaxPower(void); -void CmndMaxPowerHold(void); -void CmndMaxPowerWindow(void); -void CmndSafePower(void); -void CmndSafePowerHold(void); -void CmndSafePowerWindow(void); -void CmndMaxEnergy(void); -void CmndMaxEnergyStart(void); -void EnergyDrvInit(void); -void EnergySnsInit(void); -void EnergyShow(bool json); -bool Xdrv03(uint8_t function); -bool Xsns03(uint8_t function); -power_t LightPower(void); -uint8_t LightDevice(void); -static uint32_t min3(uint32_t a, uint32_t b, uint32_t c); -void AriluxRfInterrupt(void); -void AriluxRfHandler(void); -void AriluxRfInit(void); -void AriluxRfDisable(void); -void LightDiPulse(uint8_t times); -void LightDckiPulse(uint8_t times); -void LightMy92x1Write(uint8_t data); -void LightMy92x1Init(void); -void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c); -void SM16716_SendBit(uint8_t v); -void SM16716_SendByte(uint8_t v); -void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b); -bool SM16716_ModuleSelected(void); -void SM16716_Init(void); -void LightInit(void); -void LightUpdateColorMapping(void); -void LightSetDimmer(uint8_t dimmer); -uint8_t LightGetBri(uint8_t device); -void LightSetBri(uint8_t device, uint8_t bri); -void LightSetColorTemp(uint16_t ct); -uint16_t LightGetColorTemp(void); -void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value); -void LightPowerOn(void); -void LightState(uint8_t append); -void LightPreparePower(void); -void LightFade(void); -void LightWheel(uint8_t wheel_pos); -void LightCycleColor(int8_t direction); -void LightRandomColor(void); -void LightSetPower(void); -void LightAnimate(void); -void calcGammaXiaomiBulbs(uint8_t cur_col[5], uint16_t cur_col_10bits[5]); -void calcGammaMultiChannels(uint8_t cur_col[5], uint16_t cur_col_10bits[5]); -void calcGammaBulbs(uint8_t cur_col[5], uint16_t cur_col_10bits[5]); -bool LightColorEntry(char *buffer, uint32_t buffer_length); -void CmndSupportColor(void); -void CmndColor(void); -void CmndWhite(void); -void CmndChannel(void); -void CmndHsbColor(void); -void CmndLed(void); -void CmndPixels(void); -void CmndRotation(void); -void CmndWidth(void); -void CmndScheme(void); -void CmndWakeup(void); -void CmndColorTemperature(void); -void CmndDimmer(void); -void CmndLedTable(void); -void CmndRgbwwTable(void); -void CmndFade(void); -void CmndSpeed(void); -void CmndWakeupDuration(void); -void CmndUndocA(void); -bool Xdrv04(uint8_t function); -void IrSendInit(void); -void IrReceiveUpdateThreshold(); -void IrReceiveInit(void); -void IrReceiveCheck(void); -uint8_t IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp); -uint8_t IrHvacMidea(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp); -uint8_t IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp); -uint8_t IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp); -uint8_t IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp); -uint32_t IrRemoteCmndIrHvacJson(void); -void CmndIrHvac(void); -uint32_t IrRemoteCmndIrSendRaw(void); -uint32_t IrRemoteCmndIrSendJson(void); -void CmndIrSend(void); -void IrRemoteCmndResponse(uint32_t error); -bool Xdrv05(uint8_t function); -void IrSendInit(void); -uint8_t reverseBitsInByte(uint8_t b); -uint64_t reverseBitsInBytes64(uint64_t b); -void IrReceiveUpdateThreshold(); -void IrReceiveInit(void); -String sendIRJsonState(const struct decode_results &results); -void IrReceiveCheck(void); -String listSupportedProtocols(bool hvac); -uint32_t IrRemoteCmndIrHvacJson(void); -void CmndIrHvac(void); -uint32_t IrRemoteCmndIrSendJson(void); -uint32_t IrRemoteCmndIrSendRaw(void); -void CmndIrSend(void); -void IrRemoteCmndResponse(uint32_t error); -bool Xdrv05(uint8_t function); -ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size); -ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size); -ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uint8_t *new_data, size_t new_data_len); -ssize_t rf_decode_and_write(uint8_t *record, size_t size); -ssize_t rf_search_and_write(uint8_t *buf, size_t size); -uint8_t rf_erase_flash(void); -uint8_t SnfBrUpdateInit(void); -void SonoffBridgeReceivedRaw(void); -void SonoffBridgeLearnFailed(void); -void SonoffBridgeReceived(void); -bool SonoffBridgeSerialInput(void); -void SonoffBridgeSendCommand(uint8_t code); -void SonoffBridgeSendAck(void); -void SonoffBridgeSendCode(uint32_t code); -void SonoffBridgeSend(uint8_t idx, uint8_t key); -void SonoffBridgeLearn(uint8_t key); -void CmndRfBridge(void); -void CmndRfKey(void); -void CmndRfRaw(void); -bool Xdrv06(uint8_t function); -int DomoticzBatteryQuality(void); -int DomoticzRssiQuality(void); -void MqttPublishDomoticzFanState(); -void DomoticzUpdateFanState(); -void MqttPublishDomoticzPowerState(uint8_t device); -void DomoticzUpdatePowerState(uint8_t device); -void DomoticzMqttUpdate(void); -void DomoticzMqttSubscribe(void); -bool DomoticzMqttData(void); -bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg); -uint8_t DomoticzHumidityState(char *hum); -void DomoticzSensor(uint8_t idx, char *data); -void DomoticzSensor(uint8_t idx, uint32_t value); -void DomoticzTempHumSensor(char *temp, char *hum); -void DomoticzTempHumPressureSensor(char *temp, char *hum, char *baro); -void DomoticzSensorPowerEnergy(int power, char *energy); -void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int power); -void CmndDomoticzIdx(void); -void CmndDomoticzKeyIdx(void); -void CmndDomoticzSwitchIdx(void); -void CmndDomoticzSensorIdx(void); -void CmndDomoticzUpdateTimer(void); -void HandleDomoticzConfiguration(void); -void DomoticzSaveSettings(void); -bool Xdrv07(uint8_t function); -void SerialBridgeInput(void); -void SerialBridgeInit(void); -void CmndSSerialSend(void); -void CmndSBaudrate(void); -bool Xdrv08(uint8_t function); -float JulianischesDatum(void); -float InPi(float x); -float eps(float T); -float BerechneZeitgleichung(float *DK,float T); -void DuskTillDawn(uint8_t *hour_up,uint8_t *minute_up, uint8_t *hour_down, uint8_t *minute_down); -void ApplyTimerOffsets(Timer *duskdawn); -String GetSun(uint32_t dawn); -uint16_t SunMinutes(uint32_t dawn); -void TimerSetRandomWindow(uint32_t index); -void TimerSetRandomWindows(void); -void TimerEverySecond(void); -void PrepShowTimer(uint32_t index); -void CmndTimer(void); -void CmndTimers(void); -void CmndLongitude(void); -void CmndLatitude(void); -void HandleTimerConfiguration(void); -void TimerSaveSettings(void); -bool Xdrv09(uint8_t function); -bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule); -int8_t parseCompareExpression(String &expr, String &leftExpr, String &rightExpr); -bool RuleSetProcess(uint8_t rule_set, String &event_saved); -bool RulesProcessEvent(char *json_event); -bool RulesProcess(void); -void RulesInit(void); -void RulesEvery50ms(void); -void RulesEvery100ms(void); -void RulesEverySecond(void); -void RulesSaveBeforeRestart(void); -void RulesSetPower(void); -void RulesTeleperiod(void); -bool RulesMqttData(void); -void CmndSubscribe(void); -void CmndUnsubscribe(void); -bool findNextNumber(char * &pNumber, float &value); -bool findNextVariableValue(char * &pVarname, float &value); -bool findNextObjectValue(char * &pointer, float &value); -bool findNextOperator(char * &pointer, int8_t &op); -float calculateTwoValues(float v1, float v2, uint8_t op); -float evaluateExpression(const char * expression, unsigned int len); -void CmndIf(); -bool evaluateComparisonExpression(const char *expression, int len); -bool findNextLogicOperator(char * &pointer, int8_t &op); -bool findNextLogicObjectValue(char * &pointer, bool &value); -bool evaluateLogicalExpression(const char * expression, int len); -int8_t findIfBlock(char * &pointer, int &lenWord, int8_t block_type); -void ExecuteCommandBlock(const char * commands, int len); -void ProcessIfStatement(const char* statements); -void RulesPreprocessCommand(char *pCommands); -void CmndRule(void); -void CmndRuleTimer(void); -void CmndEvent(void); -void CmndVariable(void); -void CmndMemory(void); -void CmndCalcResolution(void); -void CmndAddition(void); -void CmndSubtract(void); -void CmndMultiply(void); -void CmndScale(void); -float map_double(float x, float in_min, float in_max, float out_min, float out_max); -bool Xdrv10(uint8_t function); -void ScriptEverySecond(void); -void RulesTeleperiod(void); -int16_t Init_Scripter(void); -void ws2812_set_array(float *array ,uint8_t len); -float median_array(float *array,uint8_t len); -float Get_MFVal(uint8_t index,uint8_t bind); -void Set_MFVal(uint8_t index,uint8_t bind,float val); -float Get_MFilter(uint8_t index); -void Set_MFilter(uint8_t index, float invar); -float DoMedian5(uint8_t index, float in); -uint32_t HSVToRGB(uint16_t hue, uint8_t saturation, uint8_t value); -uint16_t GetStack(void); -uint16_t GetStack(void); -void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize); -void toLog(const char *str); -void toLogN(const char *cp,uint8_t len); -void toLogEOL(const char *s1,const char *str); -void toSLog(const char *str); -int16_t Run_Scripter(const char *type, int8_t tlen, char *js); -void ScripterEvery100ms(void); -void Scripter_save_pvars(void); -void ListDir(char *path, uint8_t depth); -void Script_FileUploadConfiguration(void); -void ScriptFileUploadSuccess(void); -void script_upload(void); -uint8_t DownloadFile(char *file); -void HandleScriptTextareaConfiguration(void); -void HandleScriptConfiguration(void); -void ScriptSaveSettings(void); -bool Script_SubCmd(void); -void execute_script(char *script); -bool ScriptCommand(void); -uint16_t xFAT_DATE(uint16_t year, uint8_t month, uint8_t day); -uint16_t xFAT_TIME(uint8_t hour, uint8_t minute, uint8_t second); -void dateTime(uint16_t* date, uint16_t* time); -bool ScriptMqttData(void); -String ScriptSubscribe(const char *data, int data_len); -String ScriptUnsubscribe(const char * data, int data_len); -void Script_Check_HTML_Setvars(void); -void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen); -void ScriptWebShow(void); -void ScriptJsonAppend(void); -bool Xdrv10(uint8_t function); -void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF ); -void KNX_DEL_GA( uint8_t GAnum ); -void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF ); -void KNX_DEL_CB( uint8_t CBnum ); -bool KNX_CONFIG_NOT_MATCH(void); -void KNXStart(void); -void KNX_INIT(void); -void KNX_CB_Action(message_t const &msg, void *arg); -void KnxUpdatePowerState(uint8_t device, power_t state); -void KnxSendButtonPower(uint8_t key, uint8_t device, uint8_t state); -void KnxSensor(uint8_t sensor_type, float value); -void HandleKNXConfiguration(void); -void KNX_Save_Settings(void); -void CmndKnxTxCmnd(void); -void CmndKnxTxVal(void); -void CmndKnxEnabled(void); -void CmndKnxEnhanced(void); -void CmndKnxPa(void); -void CmndKnxGa(void); -void CmndKnxCb(void); -bool Xdrv11(uint8_t function); -static void FindPrefix(char* s1, char* s2, char* out); -static void Shorten(char** s, char *prefix); -void TryResponseAppend_P(const char *format, ... ); -void HAssAnnounceRelayLight(void); -void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint8_t key, uint8_t toggle); -void HAssAnnounceSwitches(void); -void HAssAnnounceButtons(void); -void HAssAnnounceSensor(const char* sensorname, const char* subsensortype); -void HAssAnnounceSensors(void); -void HAssAnnounceStatusSensor(void); -void HAssPublishStatus(void); -void HAssDiscovery(void); -void HAssDiscover(void); -bool Xdrv12(uint8_t function); -void DisplayInit(uint8_t mode); -void DisplayClear(void); -void DisplayDrawHLine(uint16_t x, uint16_t y, int16_t len, uint16_t color); -void DisplayDrawVLine(uint16_t x, uint16_t y, int16_t len, uint16_t color); -void DisplayDrawLine(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color); -void DisplayDrawCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color); -void DisplayDrawFilledCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color); -void DisplayDrawRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color); -void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color); -void DisplayDrawFrame(void); -void DisplaySetSize(uint8_t size); -void DisplaySetFont(uint8_t font); -void DisplaySetRotation(uint8_t rotation); -void DisplayDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); -void DisplayOnOff(uint8_t on); -uint8_t fatoiv(char *cp,float *res); -uint8_t atoiv(char *cp, int16_t *res); -uint8_t atoiV(char *cp, uint16_t *res); -void alignright(char *string); -void decode_te(char *line); -void DisplayText(void); -void DisplayClearScreenBuffer(void); -void DisplayFreeScreenBuffer(void); -void DisplayAllocScreenBuffer(void); -void DisplayReAllocScreenBuffer(void); -void DisplayFillScreen(uint32_t line); -void DisplayClearLogBuffer(void); -void DisplayFreeLogBuffer(void); -void DisplayAllocLogBuffer(void); -void DisplayReAllocLogBuffer(void); -void DisplayLogBufferAdd(char* txt); -char* DisplayLogBuffer(char temp_code); -void DisplayLogBufferInit(void); -void DisplayJsonValue(const char* topic, const char* device, const char* mkey, const char* value); -void DisplayAnalyzeJson(char *topic, char *json); -void DisplayMqttSubscribe(void); -bool DisplayMqttData(void); -void DisplayLocalSensor(void); -void DisplayInitDriver(void); -void DisplaySetPower(void); -void CmndDisplay(void); -void CmndDisplayModel(void); -void CmndDisplayWidth(void); -void CmndDisplayHeight(void); -void CmndDisplayMode(void); -void CmndDisplayDimmer(void); -void CmndDisplaySize(void); -void CmndDisplayFont(void); -void CmndDisplayRotate(void); -void CmndDisplayText(void); -void CmndDisplayAddress(void); -void CmndDisplayRefresh(void); -void CmndDisplayColumns(void); -void CmndDisplayRows(void); -void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp); -void DrawAClock(uint16_t rad); -void ClrGraph(uint16_t num); -void DefineGraph(uint16_t num,uint16_t xp,uint16_t yp,int16_t xs,uint16_t ys,int16_t dec,float ymin, float ymax,uint8_t icol); -void DisplayCheckGraph(); -void Save_graph(uint8_t num, char *path); -void Restore_graph(uint8_t num, char *path); -void RedrawGraph(uint8_t num, uint8_t flags); -void AddGraph(uint8_t num,uint8_t val); -void AddValue(uint8_t num,float fval); -bool Xdrv13(uint8_t function); -uint16_t MP3_Checksum(uint8_t *array); -void MP3PlayerInit(void); -void MP3_CMD(uint8_t mp3cmd,uint16_t val); -bool MP3PlayerCmd(void); -bool Xdrv14(uint8_t function); -void PCA9685_Detect(void); -void PCA9685_Reset(void); -void PCA9685_SetPWMfreq(double freq); -void PCA9685_SetPWM_Reg(uint8_t pin, uint16_t on, uint16_t off); -void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted); -bool PCA9685_Command(void); -void PCA9685_OutputTelemetry(bool telemetry); -bool Xdrv15(uint8_t function); -void CmndTuyaMcu(void); -void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId); -void UpdateDevices(); -inline bool TuyaFuncIdValid(uint8_t fnId); -uint8_t TuyaGetFuncId(uint8_t dpid); -uint8_t TuyaGetDpId(uint8_t fnId); -void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value); -void TuyaSendBool(uint8_t id, bool value); -void TuyaSendValue(uint8_t id, uint32_t value); -bool TuyaSetPower(void); -bool TuyaSetChannels(void); -void LightSerialDuty(uint8_t duty); -void TuyaRequestState(void); -void TuyaResetWifi(void); -void TuyaPacketProcess(void); -bool TuyaModuleSelected(void); -void TuyaInit(void); -void TuyaSerialInput(void); -bool TuyaButtonPressed(void); -void TuyaSetWifiLed(void); -bool Xnrg16(uint8_t function); -bool Xdrv16(uint8_t function); -void RfReceiveCheck(void); -void RfInit(void); -void CmndRfSend(void); -bool Xdrv17(uint8_t function); -bool ArmtronixSetChannels(void); -void LightSerial2Duty(uint8_t duty1, uint8_t duty2); -void ArmtronixRequestState(void); -bool ArmtronixModuleSelected(void); -void ArmtronixInit(void); -void ArmtronixSerialInput(void); -void ArmtronixSetWifiLed(void); -bool Xdrv18(uint8_t function); -void PS16DZSerialSendTxBuffer(void); -void PS16DZSerialSendOkCommand(void); -void PS16DZSerialSendUpdateCommand(void); -bool PS16DZSerialSendUpdateCommandIfRequired(void); -bool PS16DZModuleSelected(void); -void PS16DZInit(void); -void PS16DZSerialInput(void); -bool Xdrv19(uint8_t function); -String HueBridgeId(void); -String HueSerialnumber(void); -String HueUuid(void); -void HueRespondToMSearch(void); -String GetHueDeviceId(uint8_t id); -String GetHueUserId(void); -void HandleUpnpSetupHue(void); -void HueNotImplemented(String *path); -void HueConfigResponse(String *response); -void HueConfig(String *path); -uint8_t getLocalLightSubtype(uint8_t device); -void HueLightStatus1(uint8_t device, String *response); -void HueLightStatus2(uint8_t device, String *response); -uint32_t EncodeLightId(uint8_t relay_id); -uint32_t DecodeLightId(uint32_t hue_id); -uint32_t findEchoGeneration(void); -void HueGlobalConfig(String *path); -void HueAuthentication(String *path); -void HueLights(String *path); -void HueGroups(String *path); -void HandleHueApi(String *path); -bool Xdrv20(uint8_t function); -String WemoSerialnumber(void); -String WemoUuid(void); -void WemoRespondToMSearch(int echo_type); -void HandleUpnpEvent(void); -void HandleUpnpService(void); -void HandleUpnpMetaService(void); -void HandleUpnpSetupWemo(void); -bool Xdrv21(uint8_t function); -bool IsModuleIfan(); -uint8_t MaxFanspeed(void); -uint8_t GetFanspeed(void); -void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence); -void SonoffIfanReceived(void); -bool SonoffIfanSerialInput(void); -void CmndFanspeed(void); -bool SonoffIfanInit(void); -void SonoffIfanUpdate(void); -bool Xdrv22(uint8_t function); -uint8_t toPercentageCR2032(uint32_t voltage); -uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer &buf, - uint32_t offset, uint32_t len); -int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf); -int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf); -int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf); -bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match); -int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf); -int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf); -int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf); -int32_t Z_State_Ready(uint8_t value); -uint8_t ZigbeeGetInstructionSize(uint8_t instr); -void ZigbeeGotoLabel(uint8_t label); -void ZigbeeStateMachine_Run(void); -int32_t ZigbeeProcessInput(class SBuffer &buf); -void ZigbeeInput(void); -void ZigbeeInit(void); -void CmndZigbeeZNPSend(void); -void ZigbeeZNPSend(const uint8_t *msg, size_t len); -void CmndZigbeePermitJoin(void); -bool Xdrv23(uint8_t function); -void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune); -void BuzzerBeep(uint32_t count); -void BuzzerEnabledBeep(uint32_t count); -bool BuzzerPinState(void); -void BuzzerInit(void); -void BuzzerEvery100mSec(void); -void CmndBuzzer(void); -bool Xdrv24(uint8_t function); -void A4988Init(void); -void CmndDoMove(void); -void CmndDoRotate(void); -void CmndDoTurn(void); -void CmndSetMIS(void); -void CmndSetSPR(void); -void CmndSetRPM(void); -bool Xdrv25(uint8_t function); -void ExceptionTest(uint8_t type); -void CpuLoadLoop(void); -void DebugFreeMem(void); -void DebugFreeMem(void); -void DebugRtcDump(char* parms); -void DebugCfgDump(char* parms); -void DebugCfgPeek(char* parms); -void DebugCfgPoke(char* parms); -void DebugCfgShow(uint8_t more); -void SetFlashMode(uint8_t mode); -void CmndHelp(void); -void CmndRtcDump(void); -void CmndCfgDump(void); -void CmndCfgPeek(void); -void CmndCfgPoke(void); -void CmndCfgShow(void); -void CmndCfgXor(void); -void CmndException(void); -void CmndCpuCheck(void); -void CmndFreemem(void); -void CmndSetSensor(void); -void CmndFlashMode(void); -uint32_t DebugSwap32(uint32_t x); -void CmndFlashDump(void); -bool Xdrv99(uint8_t function); -void XsnsDriverState(void); -bool XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t sdataBuf); -bool XdrvRulesProcess(void); -void ShowFreeMem(const char *where); -bool XdrvCallDriver(uint32_t driver, uint8_t Function); -bool XdrvCall(uint8_t Function); -void LcdInitMode(void); -void LcdInit(uint8_t mode); -void LcdInitDriver(void); -void LcdDrawStringAt(void); -void LcdDisplayOnOff(uint8_t on); -void LcdCenter(uint8_t row, char* txt); -bool LcdPrintLog(void); -void LcdTime(void); -void LcdRefresh(void); -bool Xdsp01(uint8_t function); -void SSD1306InitDriver(); -void Ssd1306PrintLog(void); -void Ssd1306Time(void); -void Ssd1306Refresh(void); -bool Xdsp02(byte function); -void MatrixWrite(void); -void MatrixClear(void); -void MatrixFixed(char* txt); -void MatrixCenter(char* txt); -void MatrixScrollLeft(char* txt, int loop); -void MatrixScrollUp(char* txt, int loop); -void MatrixInitMode(void); -void MatrixInit(uint8_t mode); -void MatrixInitDriver(void); -void MatrixOnOff(void); -void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); -void MatrixPrintLog(uint8_t direction); -void MatrixRefresh(void); -bool Xdsp03(uint8_t function); -void Ili9341InitMode(void); -void Ili9341Init(uint8_t mode); -void Ili9341InitDriver(void); -void Ili9341Clear(void); -void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); -void Ili9341DisplayOnOff(uint8_t on); -void Ili9341OnOff(void); -void Ili9341PrintLog(void); -void Ili9341Refresh(void); -bool Xdsp04(uint8_t function); -void EpdInitDriver29(); -void EpdPrintLog29(void); -void EpdRefresh29(void); -bool Xdsp05(uint8_t function); -void EpdInitDriver42(); -void EpdRefresh42(); -bool Xdsp06(uint8_t function); -void SH1106InitDriver(); -void SH1106PrintLog(void); -void SH1106Time(void); -void SH1106Refresh(void); -bool Xdsp07(uint8_t function); -void ILI9488_InitDriver(); -void ILI9488_MQTT(uint8_t count,const char *cp); -void ILI9488_RDW_BUTT(uint32_t count,uint32_t pwr); -void FT6236Check(); -bool Xdsp08(uint8_t function); -void SSD1351_InitDriver(); -void SSD1351PrintLog(void); -void SSD1351Time(void); -void SSD1351Refresh(void); -bool Xdsp09(uint8_t function); -void RA8876_InitDriver(); -void RA8876_MQTT(uint8_t count,const char *cp); -void RA8876_RDW_BUTT(uint32_t count,uint32_t pwr); -void FT5316Check(); -bool Xdsp10(uint8_t function); -uint8_t XdspPresent(void); -bool XdspCall(uint8_t Function); -void HlwCfInterrupt(void); -void HlwCf1Interrupt(void); -void HlwEvery200ms(void); -void HlwEverySecond(void); -void HlwSnsInit(void); -void HlwDrvInit(void); -bool HlwCommand(void); -bool Xnrg01(uint8_t function); -void CseReceived(void); -bool CseSerialInput(void); -void CseEverySecond(void); -void CseDrvInit(void); -bool CseCommand(void); -bool Xnrg02(uint8_t function); -uint8_t PzemCrc(uint8_t *data); -void PzemSend(uint8_t cmd); -bool PzemReceiveReady(void); -bool PzemRecieve(uint8_t resp, float *data); -void PzemEvery200ms(void); -void PzemSnsInit(void); -void PzemDrvInit(void); -bool PzemCommand(void); -bool Xnrg03(uint8_t function); -uint8_t McpChecksum(uint8_t *data); -unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size); -void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size); -void McpSend(uint8_t *data); -void McpGetAddress(void); -void McpAddressReceive(void); -void McpGetCalibration(void); -void McpParseCalibration(void); -bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t range_shift); -void McpSetCalibration(struct mcp_cal_registers_type *cal_registers); -void McpSetSystemConfiguration(uint16 interval); -void McpGetFrequency(void); -void McpParseFrequency(void); -void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency); -void McpGetData(void); -void McpParseData(void); -void McpSerialInput(void); -void McpEverySecond(void); -void McpSnsInit(void); -void McpDrvInit(void); -bool McpCommand(void); -bool Xnrg04(uint8_t function); -void PzemAcEverySecond(void); -void PzemAcSnsInit(void); -void PzemAcDrvInit(void); -bool PzemAcCommand(void); -bool Xnrg05(uint8_t function); -void PzemDcEverySecond(void); -void PzemDcSnsInit(void); -void PzemDcDrvInit(void); -bool PzemDcCommand(void); -bool Xnrg06(uint8_t function); -int Ade7953RegSize(uint16_t reg); -void Ade7953Write(uint16_t reg, uint32_t val); -int32_t Ade7953Read(uint16_t reg); -void Ade7953Init(void); -void Ade7953GetData(void); -void Ade7953EnergyEverySecond(); -void Ade7953DrvInit(void); -bool Ade7953Command(void); -bool Xnrg07(uint8_t function); -void SDM120Every250ms(void); -void Sdm120SnsInit(void); -void Sdm120DrvInit(void); -void Sdm220Reset(void); -void Sdm220Show(bool json); -bool Xnrg08(uint8_t function); -void Dds2382EverySecond(void); -void Dds2382SnsInit(void); -void Dds2382DrvInit(void); -bool Xnrg09(uint8_t function); -void SDM630Every250ms(void); -void Sdm630SnsInit(void); -void Sdm630DrvInit(void); -bool Xnrg10(uint8_t function); -bool XnrgCall(uint8_t function); -void Ws2812StripShow(void); -int mod(int a, int b); -void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offset); -void Ws2812UpdateHand(int position, uint32_t index); -void Ws2812Clock(void); -void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t range, uint32_t gradRange, uint32_t i); -void Ws2812Gradient(uint32_t schemenr); -void Ws2812Bars(uint32_t schemenr); -void Ws2812Init(void); -void Ws2812Clear(void); -void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white); -void Ws2812ForceSuspend (void); -void Ws2812ForceUpdate (void); -char* Ws2812GetColor(uint32_t led, char* scolor); -void Ws2812ShowScheme(uint32_t scheme); -void CounterUpdate(uint8_t index); -void CounterUpdate1(void); -void CounterUpdate2(void); -void CounterUpdate3(void); -void CounterUpdate4(void); -bool CounterPinState(void); -void CounterInit(void); -void CounterSaveState(void); -void CounterShow(bool json); -void CmndCounter(void); -void CmndCounterType(void); -void CmndCounterDebounce(void); -bool Xsns01(uint8_t function); -void AdcInit(void); -uint16_t AdcRead(uint8_t factor); -void AdcEvery250ms(void); -uint16_t AdcGetLux(); -void AdcEverySecond(void); -void AdcShow(bool json); -void CmndAdc(void); -void CmndAdcs(void); -void CmndAdcParam(void); -bool Xsns02(uint8_t function); -void SonoffScSend(const char *data); -void SonoffScInit(void); -void SonoffScSerialInput(char *rcvstat); -void SonoffScShow(bool json); -bool Xsns04(uint8_t function); -uint8_t OneWireReset(void); -void OneWireWriteBit(uint8_t v); -uint8_t OneWireReadBit(void); -void OneWireWrite(uint8_t v); -uint8_t OneWireRead(void); -bool OneWireCrc8(uint8_t *addr); -void Ds18b20Convert(void); -bool Ds18b20Read(void); -void Ds18b20EverySecond(void); -void Ds18b20Show(bool json); -bool Xsns05(uint8_t function); -uint8_t OneWireReset(void); -void OneWireWriteBit(uint8_t v); -uint8_t OneWireReadBit(void); -void OneWireWrite(uint8_t v); -uint8_t OneWireRead(void); -void OneWireSelect(const uint8_t rom[8]); -void OneWireResetSearch(void); -uint8_t OneWireSearch(uint8_t *newAddr); -bool OneWireCrc8(uint8_t *addr); -void Ds18x20Init(void); -void Ds18x20Convert(void); -bool Ds18x20Read(uint8_t sensor); -void Ds18x20Name(uint8_t sensor); -void Ds18x20EverySecond(void); -void Ds18x20Show(bool json); -bool Xsns05(uint8_t function); -void Ds18x20Init(void); -void Ds18x20Search(void); -uint8_t Ds18x20Sensors(void); -String Ds18x20Addresses(uint8_t sensor); -void Ds18x20Convert(void); -bool Ds18x20Read(uint8_t sensor, float &t); -void Ds18x20Type(uint8_t sensor); -void Ds18x20Show(bool json); -bool Xsns05(uint8_t function); -void DhtReadPrep(void); -int32_t DhtExpectPulse(uint8_t sensor, bool level); -bool DhtRead(uint8_t sensor); -void DhtReadTempHum(uint8_t sensor); -bool DhtPinState(); -void DhtInit(void); -void DhtEverySecond(void); -void DhtShow(bool json); -bool Xsns06(uint8_t function); -bool ShtReset(void); -bool ShtSendCommand(const uint8_t cmd); -bool ShtAwaitResult(void); -int ShtReadData(void); -bool ShtRead(void); -void ShtDetect(void); -void ShtEverySecond(void); -void ShtShow(bool json); -bool Xsns07(uint8_t function); -uint8_t HtuCheckCrc8(uint16_t data); -uint8_t HtuReadDeviceId(void); -void HtuSetResolution(uint8_t resolution); -void HtuReset(void); -void HtuHeater(uint8_t heater); -void HtuInit(void); -bool HtuRead(void); -void HtuDetect(void); -void HtuEverySecond(void); -void HtuShow(bool json); -bool Xsns08(uint8_t function); -bool Bmp180Calibration(uint8_t bmp_idx); -void Bmp180Read(uint8_t bmp_idx); -bool Bmx280Calibrate(uint8_t bmp_idx); -void Bme280Read(uint8_t bmp_idx); -static void BmeDelayMs(uint32_t ms); -bool Bme680Init(uint8_t bmp_idx); -void Bme680Read(uint8_t bmp_idx); -void BmpDetect(void); -void BmpRead(void); -void BmpEverySecond(void); -void BmpShow(bool json); -bool Xsns09(uint8_t function); -bool Bh1750Read(void); -void Bh1750Detect(void); -void Bh1750EverySecond(void); -void Bh1750Show(bool json); -bool Xsns10(uint8_t function); -void Veml6070Detect(void); -void Veml6070UvTableInit(void); -void Veml6070EverySecond(void); -void Veml6070ModeCmd(bool mode_cmd); -uint16_t Veml6070ReadUv(void); -double Veml6070UvRiskLevel(uint16_t uv_level); -double Veml6070UvPower(double uvrisk); -void Veml6070Show(bool json); -bool Xsns11(uint8_t function); -void Ads1115StartComparator(uint8_t channel, uint16_t mode); -int16_t Ads1115GetConversion(uint8_t channel); -void Ads1115Detect(void); -void Ads1115GetValues(uint8_t address); -void Ads1115toJSON(char *comma_j); -void Ads1115toString(uint8_t address); -void Ads1115Show(bool json); -bool Xsns12(uint8_t function); -int16_t Ads1115GetConversion(uint8_t channel); -void Ads1115Detect(void); -void Ads1115Show(bool json); -bool Xsns12(uint8_t function); -bool Ina219SetCalibration(uint8_t mode, uint16_t addr); -float Ina219GetShuntVoltage_mV(uint16_t addr); -float Ina219GetBusVoltage_V(uint16_t addr); -float Ina219GetCurrent_mA(uint16_t addr); -bool Ina219Read(void); -bool Ina219CommandSensor(void); -void Ina219Detect(void); -void Ina219EverySecond(void); -void Ina219Show(bool json); -bool Xsns13(uint8_t function); -bool Sht3xRead(float &t, float &h, uint8_t sht3x_address); -void Sht3xDetect(void); -void Sht3xShow(bool json); -bool Xsns14(uint8_t function); -uint8_t MhzCalculateChecksum(uint8_t *array); -size_t MhzSendCmd(uint8_t command_id); -bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s); -void MhzEverySecond(void); -bool MhzCommandSensor(void); -void MhzInit(void); -void MhzShow(bool json); -bool Xsns15(uint8_t function); -bool Tsl2561Read(void); -void Tsl2561Detect(void); -void Tsl2561EverySecond(void); -void Tsl2561Show(bool json); -bool Xsns16(uint8_t function); -void Senseair250ms(void); -void SenseairInit(void); -void SenseairShow(bool json); -bool Xsns17(uint8_t function); -bool PmsReadData(void); -void PmsSecond(void); -void PmsInit(void); -void PmsShow(bool json); -bool Xsns18(uint8_t function); -void MGSInit(void); -bool MGSPrepare(void); -char* measure_gas(int gas_type, char* buffer); -void MGSShow(bool json); -bool Xsns19(uint8_t function); -bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer); -void NovaSdsSetWorkPeriod(void); -bool NovaSdsReadData(void); -void NovaSdsSecond(void); -bool NovaSdsCommandSensor(void); -void NovaSdsInit(void); -void NovaSdsShow(bool json); -bool Xsns20(uint8_t function); -void sgp30_Init(void); -float sgp30_AbsoluteHumidity(float temperature, float humidity,char tempUnit); -void Sgp30Update(void); -void Sgp30Show(bool json); -bool Xsns21(uint8_t function); -void Sr04Init(void); -void Sr04Show(bool json); -bool Xsns22(uint8_t function); -bool SDM120_ModbusReceiveReady(void); -void SDM120_ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count); -uint8_t SDM120_ModbusReceive(float *value); -uint16_t SDM120_calculateCRC(uint8_t *frame, uint8_t num); -void SDM120250ms(void); -void SDM120Init(void); -void SDM120Show(bool json); -bool Xsns23(uint8_t function); -uint8_t Si1145ReadByte(uint8_t reg); -uint16_t Si1145ReadHalfWord(uint8_t reg); -bool Si1145WriteByte(uint8_t reg, uint16_t val); -uint8_t Si1145WriteParamData(uint8_t p, uint8_t v); -bool Si1145Present(void); -void Si1145Reset(void); -void Si1145DeInit(void); -bool Si1145Begin(void); -uint16_t Si1145ReadUV(void); -uint16_t Si1145ReadVisible(void); -uint16_t Si1145ReadIR(void); -void Si1145Update(void); -void Si1145Show(bool json); -bool Xsns24(uint8_t function); -bool SDM630_ModbusReceiveReady(void); -void SDM630_ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count); -uint8_t SDM630_ModbusReceive(float *value); -uint16_t SDM630_calculateCRC(uint8_t *frame, uint8_t num); -void SDM630250ms(void); -void SDM630Init(void); -void SDM630Show(bool json); -bool Xsns25(uint8_t function); -void LM75ADDetect(void); -float LM75ADGetTemp(void); -void LM75ADShow(bool json); -bool Xsns26(uint8_t function); -int8_t wireReadDataBlock( uint8_t reg, - uint8_t *val, - uint16_t len); -void calculateColorTemperature(void); -bool APDS9960_init(void); -uint8_t getMode(void); -void setMode(uint8_t mode, uint8_t enable); -void enableLightSensor(void); -void disableLightSensor(void); -void enableProximitySensor(void); -void disableProximitySensor(void); -void enableGestureSensor(void); -void disableGestureSensor(void); -bool isGestureAvailable(void); -int16_t readGesture(void); -void enablePower(void); -void disablePower(void); -void readAllColorAndProximityData(void); -void resetGestureParameters(void); -bool processGestureData(void); -bool decodeGesture(void); -void handleGesture(void); -void APDS9960_adjustATime(void); -void APDS9960_loop(void); -bool APDS9960_detect(void); -void APDS9960_show(bool json); -bool APDS9960CommandSensor(void); -bool Xsns27(uint8_t function); -void Tm16XXSend(uint8_t data); -void Tm16XXSendCommand(uint8_t cmd); -void TM16XXSendData(uint8_t address, uint8_t data); -uint8_t Tm16XXReceive(void); -void Tm16XXClearDisplay(void); -void Tm1638SetLED(uint8_t color, uint8_t pos); -void Tm1638SetLEDs(word leds); -uint8_t Tm1638GetButtons(void); -void TmInit(void); -void TmLoop(void); -bool Xsns28(uint8_t function); -void MCP230xx_CheckForIntCounter(void); -void MCP230xx_CheckForIntRetainer(void); -const char* IntModeTxt(uint8_t intmo); -uint8_t MCP230xx_readGPIO(uint8_t port); -void MCP230xx_ApplySettings(void); -void MCP230xx_Detect(void); -void MCP230xx_CheckForInterrupt(void); -void MCP230xx_Show(bool json); -void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate); -void MCP230xx_Reset(uint8_t pinmode); -bool MCP230xx_Command(void); -void MCP230xx_UpdateWebData(void); -void MCP230xx_OutputTelemetry(void); -void MCP230xx_Interrupt_Counter_Report(void); -void MCP230xx_Interrupt_Retain_Report(void); -bool Xsns29(uint8_t function); -void Mpr121Init(struct mpr121 *pS); -void Mpr121Show(struct mpr121 *pS, uint8_t function); -bool Xsns30(uint8_t function); -void CCS811Update(void); -void CCS811Show(bool json); -bool Xsns31(uint8_t function); -void MPU_6050PerformReading(void); -void MPU_6050Detect(void); -void MPU_6050Show(bool json); -bool Xsns32(uint8_t function); -void DS3231Detect(void); -uint8_t bcd2dec(uint8_t n); -uint8_t dec2bcd(uint8_t n); -uint32_t ReadFromDS3231(void); -void SetDS3231Time (uint32_t epoch_time); -bool Xsns33(uint8_t function); -bool HxIsReady(uint16_t timeout); -long HxRead(); -void HxResetPart(void); -void HxReset(void); -void HxCalibrationStateTextJson(uint8_t msg_id); -bool HxCommand(void); -long HxWeight(); -void HxInit(void); -void HxEvery100mSecond(void); -void HxSaveBeforeRestart(); -void HxShow(bool json); -void HandleHxAction(void); -void HxSaveSettings(void); -void HxLogUpdates(void); -bool Xsns34(uint8_t function); -void Tx20StartRead(void); -void Tx20Read(void); -void Tx20Init(void); -void Tx20Show(bool json); -bool Xsns35(uint8_t function); -void MGC3130_triggerTele(); -void MGC3130_handleSensorData(); -void MGC3130_sendMessage(uint8_t data[], uint8_t length); -void MGC3130_handleGesture(); -bool MGC3130_handleTouch(); -void MGC3130_handleAirWheel(); -void MGC3130_handleSystemStatus(); -bool MGC3130_receiveMessage(); -bool MGC3130_readData(); -void MGC3130_nextMode(); -void MGC3130_loop(); -bool MGC3130_detect(void); -void MGC3130_show(bool json); -bool MGC3130CommandSensor(); -bool Xsns36(uint8_t function); -bool RfSnsFetchSignal(uint8_t DataPin, bool StateSignal); -void RfSnsInitTheoV2(void); -void RfSnsAnalyzeTheov2(void); -void RfSnsTheoV2Show(bool json); -void RfSnsInitAlectoV2(void); -void RfSnsAnalyzeAlectov2(); -void RfSnsAlectoResetRain(void); -uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len); -void RfSnsAlectoV2Show(bool json); -void RfSnsInit(void); -void RfSnsAnalyzeRawSignal(void); -void RfSnsEverySecond(void); -void RfSnsShow(bool json); -bool Xsns37(uint8_t function); -void AzEverySecond(void); -void AzInit(void); -void AzShow(bool json); -bool Xsns38(uint8_t function); -void MAX31855_Init(void); -void MAX31855_GetResult(void); -float MAX31855_GetProbeTemperature(int32_t RawData); -float MAX31855_GetReferenceTemperature(int32_t RawData); -int32_t MAX31855_ShiftIn(uint8_t Length); -void MAX31855_Show(bool Json); -bool Xsns39(uint8_t function); -void PN532_Init(void); -int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout); -int8_t PN532_readAckFrame(void); -uint32_t PN532_getFirmwareVersion(void); -void PN532_wakeup(void); -bool PN532_setPassiveActivationRetries(uint8_t maxRetries); -bool PN532_SAMConfig(void); -uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData); -uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data); -uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data); -void PN532_ScanForTag(void); -bool PN532_Command(void); -bool Xsns40(uint8_t function); -bool Max4409Read_lum(void); -void Max4409Detect(void); -void Max4409EverySecond(void); -void Max4409Show(bool json); -bool Xsns41(uint8_t function); -bool Scd30Init(); -int Scd30Update(); -int Scd30GetCommand(int command_code, uint16_t *pvalue); -int Scd30SetCommand(int command_code, uint16_t value); -bool Scd30CommandSensor(); -void Scd30Show(bool json); -bool Xsns42(byte function); -int hreReadBit(); -char hreReadChar(int &parity_errors); -void hreInit(void); -void hreEvery50ms(void); -void hreShow(boolean json); -bool Xsns43(byte function); -uint8_t sps30_calc_CRC(uint8_t *data); -void sps30_get_data(uint16_t cmd, uint8_t *data, uint8_t dlen); -void sps30_cmd(uint16_t cmd); -void SPS30_Detect(); -void SPS30_Every_Second(); -void SPS30_Show(bool json); -bool SPS30_cmd(void); -bool Xsns44(byte function); -void Vl53l0Detect(); -void Vl53l0Every_250MSecond(); -void Vl53l0Show(boolean json); -bool Xsns45(byte function); -void MLX90614_Init(); -uint16_t read_irtmp(uint8_t flag); -void MLX90614_Every_Second(void); -void MLX90614_Show(uint8_t json); -bool Xsns46(byte function); -void MAX31865_Init(void); -void MAX31865_GetResult(void); -void MAX31865_Show(bool Json); -bool Xsns47(uint8_t function); -bool I2cWriteReg(uint8_t addr, uint8_t reg); -void ChirpReset(uint8_t addr); -void ChirpResetAll(void); -void ChirpClockSet(); -void ChirpSleep(uint8_t addr); -void ChirpSelect(uint8_t sensor); -bool ChirpMeasureLight(void); -void ChirpReadCapTemp(); -bool ChirpReadLight(); -uint8_t ChirpReadVersion(uint8_t addr); -bool ChirpSet(uint8_t addr); -bool ChirpScan(); -void ChirpDetect(void); -void ChirpEverySecond(void); -void ChirpShow(bool json); -bool ChirpCmd(void); -bool Xsns48(uint8_t function); -bool solaxX1_RS485ReceiveReady(void); -void solaxX1_RS485Send(uint8_t *msg, uint16_t msgLen); -uint8_t solaxX1_RS485Receive(uint8_t *value); -uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen); -void solaxX1_setMessage(uint8_t *message); -void solaxX1_SendInverterAddress(); -void solaxX1_QueryLiveData(); -uint8_t solaxX1_ParseErrorCode(uint32_t code); -void solaxX1_Update(void); -void solaxX1Init(void); -void solaxX1Show(bool json); -bool Xsns49(uint8_t function); -void PAJ7620SelectBank(uint8_t bank); -void PAJ7620TriggerTele(); -void PAJ7620DecodeGesture(void); -void PAJ7620ReadGesture(void); -void PAJ7620Detect(void); -void PAJ7620Init(void); -void PAJ7620SelectMode(uint16_t mode); -void PAJ7620Loop(void); -void PAJ7620Show(bool json); -bool PAJ7620Cmd(void); -bool Xsns50(uint8_t function); -void RDM6300_Init(); -void RDM6300_ScanForTag(); -uint8_t rm6300_hexnibble(char chr); -void rm6300_hstring_to_array(uint8_t array[], uint8_t len, char buffer[]); -void RDM6300_Show(void); -bool Xsns51(byte function); -void IBEACON_Init(); -void hm17_every_second(void); -void hm17_sbclr(void); -void hm17_sendcmd(uint8_t cmd); -uint32_t ibeacon_add(struct IBEACON *ib); -void hm17_decode(void); -void IBEACON_loop(); -void IBEACON_Show(void); -bool xsns52_cmd(void); -bool ibeacon_cmd(void); -void ib_sendbeep(void); -void ibeacon_mqtt(const char *mac,const char *rssi); -bool Xsns52(byte function); -double sml_median_array(double *array,uint8_t len); -double sml_median(struct SML_MEDIAN_FILTER* mf, double in); -void ADS1115_init(void); -bool Serial_available(); -uint8_t Serial_read(); -uint8_t Serial_peek(); -void Dump2log(void); -double sml_getvalue(unsigned char *cp,uint8_t index); -uint8_t hexnibble(char chr); -double CharToDouble(const char *str); -void ebus_esc(uint8_t *ebus_buffer, unsigned char len); -uint8_t ebus_crc8(uint8_t data, uint8_t crc_init); -uint8_t ebus_CalculateCRC( uint8_t *Data, uint16_t DataLen ); -void sml_empty_receiver(uint32_t meters); -void sml_shift_in(uint32_t meters,uint32_t shard); -void SML_Poll(void); -void SML_Decode(uint8_t index); -void SML_Immediate_MQTT(const char *mp,uint8_t index,uint8_t mindex); -void SML_Show(boolean json); -void SML_CounterUpd(uint8_t index); -void SML_CounterUpd1(void); -void SML_CounterUpd2(void); -void SML_CounterUpd3(void); -void SML_CounterUpd4(void); -bool Gpio_used(uint8_t gpiopin); -void SML_Init(void); -void SetDBGLed(uint8_t srcpin, uint8_t ledpin); -void SML_Counter_Poll(void); -void SML_Check_Send(void); -uint8_t sml_hexnibble(char chr); -void SML_Send_Seq(uint32_t meter,char *seq); -uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num); -uint8_t SML_PzemCrc(uint8_t *data, uint8_t len); -bool XSNS_53_cmd(void); -void InjektCounterValue(uint8_t meter,uint32_t counter); -void SML_CounterSaveState(void); -bool Xsns53(byte function); -static uint32_t _expand_r_shunt(uint16_t compact_r_shunt); -void Ina226SetCalibration(uint8_t slaveIndex); -bool Ina226TestPresence(uint8_t device); -void Ina226Init(); -float Ina226ReadBus_v(uint8_t device); -float Ina226ReadShunt_i(uint8_t device); -float Ina226ReadPower_w(uint8_t device); -void Ina226Read(uint8_t device); -void Ina226EverySecond(); -bool Ina226CommandSensor(); -void Ina226Show(bool json); -bool Xsns54(byte callback_id); -bool XsnsEnabled(uint32_t sns_index); -void XsnsSensorState(void); -bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index); -bool XsnsCall(uint8_t Function); -#line 180 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/sonoff.ino" -char* Format(char* output, const char* input, int size) -{ - char *token; - uint32_t digits = 0; - - if (strstr(input, "%") != nullptr) { - strlcpy(output, input, size); - token = strtok(output, "%"); - if (strstr(input, "%") == input) { - output[0] = '\0'; - } else { - token = strtok(nullptr, ""); - } - if (token != nullptr) { - digits = atoi(token); - if (digits) { - char tmp[size]; - if (strchr(token, 'd')) { - snprintf_P(tmp, size, PSTR("%s%c0%dd"), output, '%', digits); - snprintf_P(output, size, tmp, ESP.getChipId() & 0x1fff); - } else { - snprintf_P(tmp, size, PSTR("%s%c0%dX"), output, '%', digits); - snprintf_P(output, size, tmp, ESP.getChipId()); - } - } else { - if (strchr(token, 'd')) { - snprintf_P(output, size, PSTR("%s%d"), output, ESP.getChipId()); - digits = 8; - } - } - } - } - if (!digits) { - strlcpy(output, input, size); - } - return output; -} - -char* GetOtaUrl(char *otaurl, size_t otaurl_size) -{ - if (strstr(Settings.ota_url, "%04d") != nullptr) { - snprintf(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId() & 0x1fff); - } - else if (strstr(Settings.ota_url, "%d") != nullptr) { - snprintf_P(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId()); - } - else { - strlcpy(otaurl, Settings.ota_url, otaurl_size); - } - return otaurl; -} - -char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic) -{ - - - - - - - - char romram[CMDSZ]; - String fulltopic; - - snprintf_P(romram, sizeof(romram), subtopic); - if (fallback_topic_flag || (prefix > 3)) { - prefix &= 3; - fulltopic = FPSTR(kPrefixes[prefix]); - fulltopic += F("/"); - fulltopic += mqtt_client; - fulltopic += F("_fb"); - } else { - fulltopic = Settings.mqtt_fulltopic; - if ((0 == prefix) && (-1 == fulltopic.indexOf(FPSTR(MQTT_TOKEN_PREFIX)))) { - fulltopic += F("/"); - fulltopic += FPSTR(MQTT_TOKEN_PREFIX); - } - for (uint32_t i = 0; i < 3; i++) { - if ('\0' == Settings.mqtt_prefix[i][0]) { - snprintf_P(Settings.mqtt_prefix[i], sizeof(Settings.mqtt_prefix[i]), kPrefixes[i]); - } - } - fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), Settings.mqtt_prefix[prefix]); - fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), topic); - fulltopic.replace(F("%hostname%"), my_hostname); - String token_id = WiFi.macAddress(); - token_id.replace(":", ""); - fulltopic.replace(F("%id%"), token_id); - } - fulltopic.replace(F("#"), ""); - fulltopic.replace(F("//"), "/"); - if (!fulltopic.endsWith("/")) { - fulltopic += "/"; - } - snprintf_P(stopic, TOPSZ, PSTR("%s%s"), fulltopic.c_str(), romram); - return stopic; -} - -char* GetFallbackTopic_P(char *stopic, uint32_t prefix, const char* subtopic) -{ - return GetTopic_P(stopic, prefix +4, nullptr, subtopic); -} - -char* GetStateText(uint32_t state) -{ - if (state > 3) { - state = 1; - } - return Settings.state_text[state]; -} - - - -void SetLatchingRelay(power_t lpower, uint32_t state) -{ - - - - - - if (state && !latching_relay_pulse) { - latching_power = lpower; - latching_relay_pulse = 2; - } - - for (uint32_t i = 0; i < devices_present; i++) { - uint32_t port = (i << 1) + ((latching_power >> i) &1); - if (pin[GPIO_REL1 +port] < 99) { - digitalWrite(pin[GPIO_REL1 +port], bitRead(rel_inverted, port) ? !state : state); - } - } -} - -void SetDevicePower(power_t rpower, uint32_t source) -{ - ShowSource(source); - - if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - power = (1 << devices_present) -1; - rpower = power; - } - - if (Settings.flag.interlock) { - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { - power_t mask = 1; - uint32_t count = 0; - for (uint32_t j = 0; j < devices_present; j++) { - if ((Settings.interlock[i] & mask) && (rpower & mask)) { - count++; - } - mask <<= 1; - } - if (count > 1) { - mask = ~Settings.interlock[i]; - power &= mask; - rpower &= mask; - } - } - } - - if (rpower) { - last_power = rpower; - } - - XdrvMailbox.index = rpower; - XdrvCall(FUNC_SET_POWER); - - XdrvMailbox.index = rpower; - XdrvMailbox.payload = source; - if (XdrvCall(FUNC_SET_DEVICE_POWER)) { - - } - else if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - Serial.write(0xA0); - Serial.write(0x04); - Serial.write(rpower &0xFF); - Serial.write(0xA1); - Serial.write('\n'); - Serial.flush(); - } - else if (EXS_RELAY == my_module_type) { - SetLatchingRelay(rpower, 1); - } - else { - for (uint32_t i = 0; i < devices_present; i++) { - power_t state = rpower &1; - if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) { - digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? !state : state); - } - rpower >>= 1; - } - } -} - -void RestorePower(bool publish_power, uint32_t source) -{ - if (power != last_power) { - SetDevicePower(last_power, source); - if (publish_power) { - MqttPublishAllPowerState(); - } - } -} - -void SetAllPower(uint32_t state, uint32_t source) -{ -# 394 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/sonoff.ino" - bool publish_power = true; - if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { - state &= 3; - publish_power = false; - } - if ((state >= POWER_OFF) && (state <= POWER_TOGGLE)) { - power_t all_on = (1 << devices_present) -1; - switch (state) { - case POWER_OFF: - power = 0; - break; - case POWER_ON: - power = all_on; - break; - case POWER_TOGGLE: - power ^= all_on; - } - SetDevicePower(power, source); - } - if (publish_power) { - MqttPublishAllPowerState(); - } -} - -void SetLedPowerIdx(uint32_t led, uint32_t state) -{ - if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { - if (pin[GPIO_LED2] < 99) { - led = 1; - } - } - if (pin[GPIO_LED1 + led] < 99) { - uint32_t mask = 1 << led; - if (state) { - state = 1; - led_power |= mask; - } else { - led_power &= (0xFF ^ mask); - } - digitalWrite(pin[GPIO_LED1 + led], bitRead(led_inverted, led) ? !state : state); - } -} - -void SetLedPower(uint32_t state) -{ - if (99 == pin[GPIO_LEDLNK]) { - SetLedPowerIdx(0, state); - } else { - power_t mask = 1; - for (uint32_t i = 0; i < leds_present; i++) { - bool tstate = (power & mask); - SetLedPowerIdx(i, tstate); - mask <<= 1; - } - } -} - -void SetLedPowerAll(uint32_t state) -{ - for (uint32_t i = 0; i < leds_present; i++) { - SetLedPowerIdx(i, state); - } -} - -void SetLedLink(uint32_t state) -{ - uint32_t led_pin = pin[GPIO_LEDLNK]; - uint32_t led_inv = ledlnk_inverted; - if (99 == led_pin) { - led_pin = pin[GPIO_LED1]; - led_inv = bitRead(led_inverted, 0); - } - if (led_pin < 99) { - if (state) { state = 1; } - digitalWrite(led_pin, (led_inv) ? !state : state); - } -} - -void SetPulseTimer(uint32_t index, uint32_t time) -{ - pulse_timer[index] = (time > 111) ? millis() + (1000 * (time - 100)) : (time > 0) ? millis() + (100 * time) : 0L; -} - -uint32_t GetPulseTimer(uint32_t index) -{ - long time = TimePassedSince(pulse_timer[index]); - if (time < 0) { - time *= -1; - return (time > 11100) ? (time / 1000) + 100 : (time > 0) ? time / 100 : 0; - } - return 0; -} - - - -bool SendKey(uint32_t key, uint32_t device, uint32_t state) -{ -# 499 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/sonoff.ino" - char stopic[TOPSZ]; - char scommand[CMDSZ]; - char key_topic[sizeof(Settings.button_topic)]; - bool result = false; - - char *tmp = (key) ? Settings.switch_topic : Settings.button_topic; - Format(key_topic, tmp, sizeof(key_topic)); - if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { - if (!key && (device > devices_present)) { - device = 1; - } - GetTopic_P(stopic, CMND, key_topic, - GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); - if (CLEAR_RETAIN == state) { - mqtt_data[0] = '\0'; - } else { - if ((Settings.flag3.button_switch_force_local || !strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) && (POWER_TOGGLE == state)) { - state = ~(power >> (device -1)) &1; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(state)); - } -#ifdef USE_DOMOTICZ - if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) { - MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); - } -#else - MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); -#endif - result = !Settings.flag3.button_switch_force_local; - } else { - Response_P(PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); - result = XdrvRulesProcess(); - } -#ifdef USE_KNX - KnxSendButtonPower(key, device, state); -#endif - return result; -} - -void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) -{ -# 553 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/sonoff.ino" -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - blink_mask &= 1; - Settings.flag.interlock = 0; - Settings.pulse_timer[1] = 0; - Settings.pulse_timer[2] = 0; - Settings.pulse_timer[3] = 0; - } -#endif - - bool publish_power = true; - if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { - state &= 3; - publish_power = false; - } - - if ((device < 1) || (device > devices_present)) { - device = 1; - } - active_device = device; - - if (device <= MAX_PULSETIMERS) { - SetPulseTimer(device -1, 0); - } - power_t mask = 1 << (device -1); - if (state <= POWER_TOGGLE) { - if ((blink_mask & mask)) { - blink_mask &= (POWER_MASK ^ mask); - MqttPublishPowerBlinkState(device); - } - - if (Settings.flag.interlock && - !interlock_mutex && - ((POWER_ON == state) || ((POWER_TOGGLE == state) && !(power & mask))) - ) { - interlock_mutex = true; - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { - if (Settings.interlock[i] & mask) { - for (uint32_t j = 0; j < devices_present; j++) { - power_t imask = 1 << j; - if ((Settings.interlock[i] & imask) && (power & imask) && (mask != imask)) { - ExecuteCommandPower(j +1, POWER_OFF, SRC_IGNORE); - delay(50); - } - } - break; - } - } - interlock_mutex = false; - } - - switch (state) { - case POWER_OFF: { - power &= (POWER_MASK ^ mask); - break; } - case POWER_ON: - power |= mask; - break; - case POWER_TOGGLE: - power ^= mask; - } - SetDevicePower(power, source); -#ifdef USE_DOMOTICZ - DomoticzUpdatePowerState(device); -#endif -#ifdef USE_KNX - KnxUpdatePowerState(device, power); -#endif - if (publish_power && Settings.flag3.hass_tele_on_power) { - MqttPublishTeleState(); - } - if (device <= MAX_PULSETIMERS) { - SetPulseTimer(device -1, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[device -1] : 0); - } - } - else if (POWER_BLINK == state) { - if (!(blink_mask & mask)) { - blink_powersave = (blink_powersave & (POWER_MASK ^ mask)) | (power & mask); - blink_power = (power >> (device -1))&1; - } - blink_timer = millis() + 100; - blink_counter = ((!Settings.blinkcount) ? 64000 : (Settings.blinkcount *2)) +1; - blink_mask |= mask; - MqttPublishPowerBlinkState(device); - return; - } - else if (POWER_BLINK_STOP == state) { - bool flag = (blink_mask & mask); - blink_mask &= (POWER_MASK ^ mask); - MqttPublishPowerBlinkState(device); - if (flag) { - ExecuteCommandPower(device, (blink_powersave >> (device -1))&1, SRC_IGNORE); - } - return; - } - if (publish_power) { - MqttPublishPowerState(device); - } -} - -void StopAllPowerBlink(void) -{ - power_t mask; - - for (uint32_t i = 1; i <= devices_present; i++) { - mask = 1 << (i -1); - if (blink_mask & mask) { - blink_mask &= (POWER_MASK ^ mask); - MqttPublishPowerBlinkState(i); - ExecuteCommandPower(i, (blink_powersave >> (i -1))&1, SRC_IGNORE); - } - } -} - -void MqttShowPWMState(void) -{ - ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{")); - bool first = true; - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (pin[GPIO_PWM1 + i] < 99) { - ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings.pwm_value[i]); - first = false; - } - } - ResponseJsonEnd(); -} - -void MqttShowState(void) -{ - char stemp1[33]; - - ResponseAppendTime(); - ResponseAppend_P(PSTR(",\"" D_JSON_UPTIME "\":\"%s\",\"UptimeSec\":%u"), GetUptime().c_str(), UpTime()); - -#ifdef USE_ADC_VCC - dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); - ResponseAppend_P(PSTR(",\"" D_JSON_VCC "\":%s"), stemp1); -#endif - - ResponseAppend_P(PSTR(",\"" D_JSON_HEAPSIZE "\":%d,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u,\"MqttCount\":%u"), - ESP.getFreeHeap()/1024, GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), sleep, loop_load_avg, MqttConnectCount()); - - for (uint32_t i = 1; i <= devices_present; i++) { -#ifdef USE_LIGHT - if ((LightDevice()) && (i >= LightDevice())) { - if (i == LightDevice()) { LightState(1); } - } else { -#endif - ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), GetStateText(bitRead(power, i-1))); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - ResponseAppend_P(PSTR(",\"" D_CMND_FANSPEED "\":%d"), GetFanspeed()); - break; - } -#endif -#ifdef USE_LIGHT - } -#endif - } - - if (pwm_present) { - ResponseAppend_P(PSTR(",")); - MqttShowPWMState(); - } - - ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), - Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount(), WifiDowntime().c_str()); -} - -void MqttPublishTeleState(void) -{ - mqtt_data[0] = '\0'; - MqttShowState(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); -#ifdef USE_SCRIPT - RulesTeleperiod(); -#endif -} - -bool MqttShowSensor(void) -{ - ResponseAppendTime(); - - int json_data_start = strlen(mqtt_data); - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { -#ifdef USE_TM1638 - if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { -#else - if (pin[GPIO_SWT1 +i] < 99) { -#endif - bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); - ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(swm ^ SwitchLastState(i))); - } - } - XsnsCall(FUNC_JSON_APPEND); - -#ifdef USE_SCRIPT_JSON_EXPORT - XdrvCall(FUNC_JSON_APPEND); -#endif - - bool json_data_available = (strlen(mqtt_data) - json_data_start); - if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE)) != nullptr) { - ResponseAppend_P(PSTR(",\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), PressureUnit().c_str()); - } - if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE)) != nullptr) { - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); - } - ResponseJsonEnd(); - - if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } - return json_data_available; -} - - - -void PerformEverySecond(void) -{ - uptime++; - - if (ntp_synced_message) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Drift %d, (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - DriftTime(), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - ntp_synced_message = false; - } - - if (BOOT_LOOP_TIME == uptime) { - RtcReboot.fast_reboot_count = 0; - RtcRebootSave(); - - Settings.bootcount++; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); - } - - if (seriallog_timer) { - seriallog_timer--; - if (!seriallog_timer) { - if (seriallog_level) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SERIAL_LOGGING_DISABLED)); - } - seriallog_level = 0; - } - } - - if (syslog_timer) { - syslog_timer--; - if (!syslog_timer) { - syslog_level = Settings.syslog_level; - if (Settings.syslog_level) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_LOGGING_REENABLED)); - } - } - } - - ResetGlobalValues(); - - if (Settings.tele_period) { - tele_period++; - if (tele_period == Settings.tele_period -1) { - XsnsCall(FUNC_PREP_BEFORE_TELEPERIOD); - } - if (tele_period >= Settings.tele_period) { - tele_period = 0; - - MqttPublishTeleState(); - - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -#if defined(USE_RULES) || defined(USE_SCRIPT) - RulesTeleperiod(); -#endif - } - } - } - - XdrvCall(FUNC_EVERY_SECOND); - XsnsCall(FUNC_EVERY_SECOND); -} -# 840 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/sonoff.ino" -void Every100mSeconds(void) -{ - - power_t power_now; - - if (latching_relay_pulse) { - latching_relay_pulse--; - if (!latching_relay_pulse) SetLatchingRelay(0, 0); - } - - for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { - if (pulse_timer[i] != 0L) { - if (TimeReached(pulse_timer[i])) { - pulse_timer[i] = 0L; - ExecuteCommandPower(i +1, (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? POWER_ON : POWER_OFF, SRC_PULSETIMER); - } - } - } - - if (blink_mask) { - if (TimeReached(blink_timer)) { - SetNextTimeInterval(blink_timer, 100 * Settings.blinktime); - blink_counter--; - if (!blink_counter) { - StopAllPowerBlink(); - } else { - blink_power ^= 1; - power_now = (power & (POWER_MASK ^ blink_mask)) | ((blink_power) ? blink_mask : 0); - SetDevicePower(power_now, SRC_IGNORE); - } - } - } - - - if (TimeReached(backlog_delay)) { - if (!BACKLOG_EMPTY && !backlog_mutex) { - backlog_mutex = true; -#ifdef SUPPORT_IF_STATEMENT - ExecuteCommand((char*)backlog.shift().c_str(), SRC_BACKLOG); -#else - ExecuteCommand((char*)backlog[backlog_pointer].c_str(), SRC_BACKLOG); - backlog_pointer++; - if (backlog_pointer >= MAX_BACKLOG) { backlog_pointer = 0; } -#endif - backlog_mutex = false; - } - } -} - - - - - -void Every250mSeconds(void) -{ - - - uint32_t blinkinterval = 1; - - state_250mS++; - state_250mS &= 0x3; - - if (mqtt_cmnd_publish) mqtt_cmnd_publish--; - - if (!Settings.flag.global_state) { - if (global_state.data) { - if (global_state.mqtt_down) { blinkinterval = 7; } - if (global_state.wifi_down) { blinkinterval = 3; } - blinks = 201; - } - } - if (blinks || restart_flag || ota_state_flag) { - if (restart_flag || ota_state_flag) { - blinkstate = true; - } else { - blinkspeed--; - if (!blinkspeed) { - blinkspeed = blinkinterval; - blinkstate ^= 1; - } - } - if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) { - SetLedLink(blinkstate); - } - if (!blinkstate) { - blinks--; - if (200 == blinks) blinks = 0; - } - } - if (Settings.ledstate &1 && (pin[GPIO_LEDLNK] < 99 || !(blinks || restart_flag || ota_state_flag)) ) { - bool tstate = power & Settings.ledmask; - if ((SONOFF_TOUCH == my_module_type) || (SONOFF_T11 == my_module_type) || (SONOFF_T12 == my_module_type) || (SONOFF_T13 == my_module_type)) { - tstate = (!power) ? 1 : 0; - } - SetLedPower(tstate); - } - - - - - - switch (state_250mS) { - case 0: - PerformEverySecond(); - - if (ota_state_flag && BACKLOG_EMPTY) { - ota_state_flag--; - if (2 == ota_state_flag) { - ota_url = Settings.ota_url; - RtcSettings.ota_loader = 0; - ota_retry_counter = OTA_ATTEMPTS; - ESPhttpUpdate.rebootOnUpdate(false); - SettingsSave(1); - } - if (ota_state_flag <= 0) { -#ifdef USE_WEBSERVER - if (Settings.webserver) StopWebserver(); -#endif -#ifdef USE_ARILUX_RF - AriluxRfDisable(); -#endif - ota_state_flag = 92; - ota_result = 0; - ota_retry_counter--; - if (ota_retry_counter) { - strlcpy(mqtt_data, GetOtaUrl(log_data, sizeof(log_data)), sizeof(mqtt_data)); -#ifndef FIRMWARE_MINIMAL - if (RtcSettings.ota_loader) { - char *bch = strrchr(mqtt_data, '/'); - char *pch = strrchr((bch != nullptr) ? bch : mqtt_data, '-'); - char *ech = strrchr((bch != nullptr) ? bch : mqtt_data, '.'); - if (!pch) { pch = ech; } - if (pch) { - mqtt_data[pch - mqtt_data] = '\0'; - char *ech = strrchr(Settings.ota_url, '.'); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ech); - } - } -#endif - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), mqtt_data); -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) - ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(mqtt_data)); -#else - - WiFiClient OTAclient; - ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); -#endif - if (!ota_result) { -#ifndef FIRMWARE_MINIMAL - int ota_error = ESPhttpUpdate.getLastError(); - DEBUG_CORE_LOG(PSTR("OTA: Error %d"), ota_error); - if ((HTTP_UE_TOO_LESS_SPACE == ota_error) || (HTTP_UE_BIN_FOR_WRONG_FLASH == ota_error)) { - RtcSettings.ota_loader = 1; - } -#endif - ota_state_flag = 2; - } - } - } - if (90 == ota_state_flag) { - ota_state_flag = 0; - if (ota_result) { - - Response_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); - } else { - Response_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); - } - restart_flag = 2; - MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE)); - } - } - break; - case 1: - if (MidnightNow()) { - XsnsCall(FUNC_SAVE_AT_MIDNIGHT); - } - if (save_data_counter && BACKLOG_EMPTY) { - save_data_counter--; - if (save_data_counter <= 0) { - if (Settings.flag.save_state) { - power_t mask = POWER_MASK; - for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { - if ((Settings.pulse_timer[i] > 0) && (Settings.pulse_timer[i] < 30)) { - mask &= ~(1 << i); - } - } - if (!((Settings.power &mask) == (power &mask))) { - Settings.power = power; - } - } else { - Settings.power = 0; - } - SettingsSave(0); - save_data_counter = Settings.save_data; - } - } - if (restart_flag && BACKLOG_EMPTY) { - if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) { - char storage_wifi[sizeof(Settings.sta_ssid) + - sizeof(Settings.sta_pwd)]; - char storage_mqtt[sizeof(Settings.mqtt_host) + - sizeof(Settings.mqtt_port) + - sizeof(Settings.mqtt_client) + - sizeof(Settings.mqtt_user) + - sizeof(Settings.mqtt_pwd) + - sizeof(Settings.mqtt_topic)]; - memcpy(storage_wifi, Settings.sta_ssid, sizeof(storage_wifi)); - if (216 == restart_flag) { - memcpy(storage_mqtt, Settings.mqtt_host, sizeof(storage_mqtt)); - } - if ((215 == restart_flag) || (216 == restart_flag)) { - SettingsErase(0); - } - SettingsDefault(); - memcpy(Settings.sta_ssid, storage_wifi, sizeof(storage_wifi)); - if (216 == restart_flag) { - memcpy(Settings.mqtt_host, storage_mqtt, sizeof(storage_mqtt)); - strlcpy(Settings.mqtt_client, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)); - } - restart_flag = 2; - } - else if (213 == restart_flag) { - SettingsSdkErase(); - restart_flag = 2; - } - else if (212 == restart_flag) { - SettingsErase(0); - restart_flag = 211; - } - if (211 == restart_flag) { - SettingsDefault(); - restart_flag = 2; - } - if (2 == restart_flag) { - SettingsSaveAll(); - } - restart_flag--; - if (restart_flag <= 0) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); - EspRestart(); - } - } - break; - case 2: - WifiCheck(wifi_state_flag); - wifi_state_flag = WIFI_RESTART; - break; - case 3: - if (!global_state.wifi_down) { MqttCheck(); } - break; - } -} - -#ifdef USE_ARDUINO_OTA - - - - - - - -bool arduino_ota_triggered = false; -uint16_t arduino_ota_progress_dot_count = 0; - -void ArduinoOTAInit(void) -{ - ArduinoOTA.setPort(8266); - ArduinoOTA.setHostname(my_hostname); - if (Settings.web_password[0] !=0) { ArduinoOTA.setPassword(Settings.web_password); } - - ArduinoOTA.onStart([]() - { - SettingsSave(1); -#ifdef USE_WEBSERVER - if (Settings.webserver) { StopWebserver(); } -#endif -#ifdef USE_ARILUX_RF - AriluxRfDisable(); -#endif - if (Settings.flag.mqtt_enabled) { MqttDisconnect(); } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_UPLOAD_STARTED)); - arduino_ota_triggered = true; - arduino_ota_progress_dot_count = 0; - delay(100); - }); - - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) - { - if ((LOG_LEVEL_DEBUG <= seriallog_level)) { - arduino_ota_progress_dot_count++; - Serial.printf("."); - if (!(arduino_ota_progress_dot_count % 80)) { Serial.println(); } - } - }); - - ArduinoOTA.onError([](ota_error_t error) - { - - - - - char error_str[100]; - - if ((LOG_LEVEL_DEBUG <= seriallog_level) && arduino_ota_progress_dot_count) { Serial.println(); } - switch (error) { - case OTA_BEGIN_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_2), sizeof(error_str)); break; - case OTA_RECEIVE_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_5), sizeof(error_str)); break; - case OTA_END_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_7), sizeof(error_str)); break; - default: - snprintf_P(error_str, sizeof(error_str), PSTR(D_UPLOAD_ERROR_CODE " %d"), error); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA %s. " D_RESTARTING), error_str); - EspRestart(); - }); - - ArduinoOTA.onEnd([]() - { - if ((LOG_LEVEL_DEBUG <= seriallog_level)) { Serial.println(); } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_SUCCESSFUL ". " D_RESTARTING)); - EspRestart(); - }); - - ArduinoOTA.begin(); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_ENABLED " " D_PORT " 8266")); -} -#endif - - - -void SerialInput(void) -{ - while (Serial.available()) { - - delay(0); - serial_in_byte = Serial.read(); - - - - - if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - serial_in_byte = ButtonSerial(serial_in_byte); - } - - - - if (XdrvCall(FUNC_SERIAL)) { - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - - - - if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - if (!Settings.flag.mqtt_serial) { - if (isprint(serial_in_byte)) { - if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - } else { - serial_in_byte_counter = 0; - } - } - } else { - if (serial_in_byte || Settings.flag.mqtt_serial_raw) { - if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && - ((isprint(serial_in_byte) && (128 == Settings.serial_delimiter)) || - ((serial_in_byte != Settings.serial_delimiter) && (128 != Settings.serial_delimiter)) || - Settings.flag.mqtt_serial_raw)) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - serial_polling_window = millis(); - } else { - serial_polling_window = 0; - break; - } - } - } - - - - - if (SONOFF_SC == my_module_type) { - if (serial_in_byte == '\x1B') { - serial_in_buffer[serial_in_byte_counter] = 0; - SonoffScSerialInput(serial_in_buffer); - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - } - - - - else if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) { - serial_in_buffer[serial_in_byte_counter] = 0; - seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings.seriallog_level; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), serial_in_buffer); - ExecuteCommand(serial_in_buffer, SRC_SERIAL); - serial_in_byte_counter = 0; - serial_polling_window = 0; - Serial.flush(); - return; - } - } - - if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { - serial_in_buffer[serial_in_byte_counter] = 0; - char hex_char[(serial_in_byte_counter * 2) + 2]; - ResponseTime_P(PSTR(",\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), - (Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); - XdrvRulesProcess(); - serial_in_byte_counter = 0; - } -} - - - -void GpioInit(void) -{ - uint32_t mpin; - - if (!ValidModule(Settings.module)) { - uint32_t module = MODULE; - if (!ValidModule(MODULE)) { module = SONOFF_BASIC; } - Settings.module = module; - Settings.last_module = module; - } - SetModuleType(); - - if (Settings.module != Settings.last_module) { - baudrate = APP_BAUDRATE; - } - - for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - if ((Settings.user_template.gp.io[i] >= GPIO_SENSOR_END) && (Settings.user_template.gp.io[i] < GPIO_USER)) { - Settings.user_template.gp.io[i] = GPIO_USER; - } - } - - myio def_gp; - ModuleGpios(&def_gp); - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if ((Settings.my_gp.io[i] >= GPIO_SENSOR_END) && (Settings.my_gp.io[i] < GPIO_USER)) { - Settings.my_gp.io[i] = GPIO_NONE; - } - else if (Settings.my_gp.io[i] > GPIO_NONE) { - my_module.io[i] = Settings.my_gp.io[i]; - } - if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < GPIO_USER)) { - my_module.io[i] = def_gp.io[i]; - } - } - if ((Settings.my_adc0 >= ADC0_END) && (Settings.my_adc0 < ADC0_USER)) { - Settings.my_adc0 = ADC0_NONE; - } - else if (Settings.my_adc0 > ADC0_NONE) { - my_adc0 = Settings.my_adc0; - } - my_module_flag = ModuleFlag(); - uint32_t template_adc0 = my_module_flag.data &15; - if ((template_adc0 > ADC0_NONE) && (template_adc0 < ADC0_USER)) { - my_adc0 = template_adc0; - } - - for (uint32_t i = 0; i < GPIO_MAX; i++) { - pin[i] = 99; - } - for (uint32_t i = 0; i < sizeof(my_module.io); i++) { - mpin = ValidPin(i, my_module.io[i]); - - DEBUG_CORE_LOG(PSTR("INI: gpio pin %d, mpin %d"), i, mpin); - - if (mpin) { - XdrvMailbox.index = mpin; - XdrvMailbox.payload = i; - - if ((mpin >= GPIO_SWT1_NP) && (mpin < (GPIO_SWT1_NP + MAX_SWITCHES))) { - SwitchPullupFlag(mpin - GPIO_SWT1_NP); - mpin -= (GPIO_SWT1_NP - GPIO_SWT1); - } - else if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) { - ButtonPullupFlag(mpin - GPIO_KEY1_NP); - mpin -= (GPIO_KEY1_NP - GPIO_KEY1); - } - else if ((mpin >= GPIO_KEY1_INV) && (mpin < (GPIO_KEY1_INV + MAX_KEYS))) { - ButtonInvertFlag(mpin - GPIO_KEY1_INV); - mpin -= (GPIO_KEY1_INV - GPIO_KEY1); - } - else if ((mpin >= GPIO_KEY1_INV_NP) && (mpin < (GPIO_KEY1_INV_NP + MAX_KEYS))) { - ButtonPullupFlag(mpin - GPIO_KEY1_INV_NP); - ButtonInvertFlag(mpin - GPIO_KEY1_INV_NP); - mpin -= (GPIO_KEY1_INV_NP - GPIO_KEY1); - } - else 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_LED1_INV + MAX_LEDS))) { - bitSet(led_inverted, mpin - GPIO_LED1_INV); - mpin -= (GPIO_LED1_INV - GPIO_LED1); - } - else if (mpin == GPIO_LEDLNK_INV) { - ledlnk_inverted = 1; - mpin -= (GPIO_LEDLNK_INV - GPIO_LEDLNK); - } - 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); - } - else if (XdrvCall(FUNC_PIN_STATE)) { - mpin = XdrvMailbox.index; - } - else if (XsnsCall(FUNC_PIN_STATE)) { - mpin = XdrvMailbox.index; - }; - } - if (mpin) pin[mpin] = i; - } - - if ((2 == pin[GPIO_TXD]) || (H801 == my_module_type)) { Serial.set_tx(2); } - - analogWriteRange(Settings.pwm_range); - analogWriteFreq(Settings.pwm_frequency); - -#ifdef USE_SPI - spi_flg = ((((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CS] > 14)) || (pin[GPIO_SPI_CS] < 12)) || (((pin[GPIO_SPI_DC] < 99) && (pin[GPIO_SPI_DC] > 14)) || (pin[GPIO_SPI_DC] < 12))); - if (spi_flg) { - for (uint32_t i = 0; i < GPIO_MAX; i++) { - if ((pin[i] >= 12) && (pin[i] <=14)) pin[i] = 99; - } - my_module.io[12] = GPIO_SPI_MISO; - pin[GPIO_SPI_MISO] = 12; - my_module.io[13] = GPIO_SPI_MOSI; - pin[GPIO_SPI_MOSI] = 13; - my_module.io[14] = GPIO_SPI_CLK; - pin[GPIO_SPI_CLK] = 14; - } - soft_spi_flg = ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && ((pin[GPIO_SSPI_MOSI] < 99) || (pin[GPIO_SSPI_MOSI] < 99))); -#endif - -#ifdef USE_I2C - i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); - if (i2c_flg) { - Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]); - } -#endif - - devices_present = 1; - - light_type = LT_BASIC; -#ifdef USE_LIGHT - if (Settings.flag.pwm_control) { - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (pin[GPIO_PWM1 +i] < 99) { light_type++; } - } - } -#endif - - if (XdrvCall(FUNC_MODULE_INIT)) { - - } - else if (YTF_IR_BRIDGE == my_module_type) { - ClaimSerial(); - } - else if (SONOFF_DUAL == my_module_type) { - Settings.flag.mqtt_serial = 0; - devices_present = 2; - baudrate = 19200; - } - else if (CH4 == my_module_type) { - Settings.flag.mqtt_serial = 0; - devices_present = 4; - baudrate = 19200; - } - else if (SONOFF_SC == my_module_type) { - Settings.flag.mqtt_serial = 0; - devices_present = 0; - baudrate = 19200; - } -#ifdef USE_LIGHT - else if (SONOFF_BN == my_module_type) { - light_type = LT_PWM1; - } - else if (SONOFF_LED == my_module_type) { - light_type = LT_PWM2; - } - else if (AILIGHT == my_module_type) { - light_type = LT_RGBW; - } - else if (SONOFF_B1 == my_module_type) { - light_type = LT_RGBWC; - } -#endif - else { - if (!light_type) { devices_present = 0; } - for (uint32_t i = 0; i < MAX_RELAYS; i++) { - if (pin[GPIO_REL1 +i] < 99) { - pinMode(pin[GPIO_REL1 +i], OUTPUT); - devices_present++; - if (EXS_RELAY == my_module_type) { - digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? 1 : 0); - if (i &1) { devices_present--; } - } - } - } - } - - for (uint32_t i = 0; i < MAX_LEDS; i++) { - if (pin[GPIO_LED1 +i] < 99) { -#ifdef USE_ARILUX_RF - if ((3 == i) && (leds_present < 2) && (99 == pin[GPIO_ARIRFSEL])) { - pin[GPIO_ARIRFSEL] = pin[GPIO_LED4]; - pin[GPIO_LED4] = 99; - } else { -#endif - pinMode(pin[GPIO_LED1 +i], OUTPUT); - leds_present++; - digitalWrite(pin[GPIO_LED1 +i], bitRead(led_inverted, i)); -#ifdef USE_ARILUX_RF - } -#endif - } - } - if (pin[GPIO_LEDLNK] < 99) { - pinMode(pin[GPIO_LEDLNK], OUTPUT); - digitalWrite(pin[GPIO_LEDLNK], ledlnk_inverted); - } - - ButtonInit(); - SwitchInit(); -#ifdef ROTARY_V1 - RotaryInit(); -#endif - -#ifdef USE_LIGHT -#ifdef USE_WS2812 - if (!light_type && (pin[GPIO_WS2812] < 99)) { - devices_present++; - light_type = LT_WS2812; - } -#endif -#ifdef USE_SM16716 - if (SM16716_ModuleSelected()) { - light_type += 3; - light_type |= LT_SM16716; - } -#endif - - - if (Settings.flag3.pwm_multi_channels) { - uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); - if (0 == pwm_channels) { pwm_channels = 1; } - devices_present += pwm_channels - 1; - } -#endif - if (!light_type) { - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (pin[GPIO_PWM1 +i] < 99) { - pwm_present = true; - 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]); - } - } - } - - SetLedPower(Settings.ledstate &8); - SetLedLink(Settings.ledstate &8); - - XdrvCall(FUNC_PRE_INIT); -} - -extern "C" { -extern struct rst_info resetInfo; -} - -void setup(void) -{ - global_state.data = 3; - - RtcRebootLoad(); - if (!RtcRebootValid()) { RtcReboot.fast_reboot_count = 0; } - RtcReboot.fast_reboot_count++; - RtcRebootSave(); - - Serial.begin(baudrate); - delay(10); - Serial.println(); - seriallog_level = LOG_LEVEL_INFO; - - snprintf_P(my_version, sizeof(my_version), PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff); - if (VERSION & 0xff) { - snprintf_P(my_version, sizeof(my_version), PSTR("%s.%d"), my_version, VERSION & 0xff); - } - char code_image[20]; - snprintf_P(my_image, sizeof(my_image), PSTR("(%s)"), GetTextIndexed(code_image, sizeof(code_image), CODE_IMAGE, kCodeImage)); - - SettingsLoad(); - SettingsDelta(); - - OsWatchInit(); - - GetFeatures(); - - if (1 == RtcReboot.fast_reboot_count) { - XdrvCall(FUNC_SETTINGS_OVERRIDE); - } - - baudrate = Settings.baudrate * 300; - - seriallog_level = Settings.seriallog_level; - seriallog_timer = SERIALLOG_TIMER; - syslog_level = Settings.syslog_level; - stop_flash_rotate = Settings.flag.stop_flash_rotate; - save_data_counter = Settings.save_data; - sleep = Settings.sleep; -#ifndef USE_EMULATION - Settings.flag2.emulation = 0; -#else -#ifndef USE_EMULATION_WEMO - if (EMUL_WEMO == Settings.flag2.emulation) { Settings.flag2.emulation = 0; } -#endif -#ifndef USE_EMULATION_HUE - if (EMUL_HUE == Settings.flag2.emulation) { Settings.flag2.emulation = 0; } -#endif -#endif - - if (Settings.param[P_BOOT_LOOP_OFFSET]) { - - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET]) { - Settings.flag3.user_esp8285_enable = 0; - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +1) { - for (uint32_t i = 0; i < MAX_RULE_SETS; i++) { - if (bitRead(Settings.rule_stop, i)) { - bitWrite(Settings.rule_enabled, i, 0); - } - } - } - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +2) { - Settings.rule_enabled = 0; - } - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +3) { - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - Settings.my_gp.io[i] = GPIO_NONE; - } - Settings.my_adc0 = ADC0_NONE; - } - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { - Settings.module = SONOFF_BASIC; - - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); - } - } - - Format(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); - Format(mqtt_topic, Settings.mqtt_topic, sizeof(mqtt_topic)); - if (strstr(Settings.hostname, "%") != nullptr) { - strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); - snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname, mqtt_topic, ESP.getChipId() & 0x1FFF); - } else { - snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname); - } - - GpioInit(); - - SetSerialBaudrate(baudrate); - - WifiConnect(); - - if (MOTOR == my_module_type) { Settings.poweronstate = POWER_ALL_ON; } - if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - SetDevicePower(1, SRC_RESTART); - } else { - if ((resetInfo.reason == REASON_DEFAULT_RST) || (resetInfo.reason == REASON_EXT_SYS_RST)) { - switch (Settings.poweronstate) { - case POWER_ALL_OFF: - case POWER_ALL_OFF_PULSETIME_ON: - power = 0; - SetDevicePower(power, SRC_RESTART); - break; - case POWER_ALL_ON: - power = (1 << devices_present) -1; - SetDevicePower(power, SRC_RESTART); - break; - case POWER_ALL_SAVED_TOGGLE: - power = (Settings.power & ((1 << devices_present) -1)) ^ POWER_MASK; - if (Settings.flag.save_state) { - SetDevicePower(power, SRC_RESTART); - } - break; - case POWER_ALL_SAVED: - power = Settings.power & ((1 << devices_present) -1); - if (Settings.flag.save_state) { - SetDevicePower(power, SRC_RESTART); - } - break; - } - } else { - power = Settings.power & ((1 << devices_present) -1); - if (Settings.flag.save_state) { - SetDevicePower(power, SRC_RESTART); - } - } - } - - - for (uint32_t i = 0; i < devices_present; i++) { - if (!Settings.flag3.no_power_feedback) { - 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) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate))) { - SetPulseTimer(i, Settings.pulse_timer[i]); - } - } - blink_powersave = power; - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), PROJECT, Settings.friendlyname[0], my_version, my_image); -#ifdef FIRMWARE_MINIMAL - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_WARNING_MINIMAL_VERSION)); -#endif - - RtcInit(); - -#ifdef USE_ARDUINO_OTA - ArduinoOTAInit(); -#endif - - XdrvCall(FUNC_INIT); - XsnsCall(FUNC_INIT); -} - -void loop(void) -{ - uint32_t my_sleep = millis(); - - XdrvCall(FUNC_LOOP); - XsnsCall(FUNC_LOOP); - - OsWatchLoop(); - - ButtonLoop(); - SwitchLoop(); -#ifdef ROTARY_V1 - RotaryLoop(); -#endif - - if (TimeReached(state_50msecond)) { - SetNextTimeInterval(state_50msecond, 50); - XdrvCall(FUNC_EVERY_50_MSECOND); - XsnsCall(FUNC_EVERY_50_MSECOND); - } - if (TimeReached(state_100msecond)) { - SetNextTimeInterval(state_100msecond, 100); - Every100mSeconds(); - XdrvCall(FUNC_EVERY_100_MSECOND); - XsnsCall(FUNC_EVERY_100_MSECOND); - } - if (TimeReached(state_250msecond)) { - SetNextTimeInterval(state_250msecond, 250); - Every250mSeconds(); - XdrvCall(FUNC_EVERY_250_MSECOND); - XsnsCall(FUNC_EVERY_250_MSECOND); - } - - if (!serial_local) { SerialInput(); } - -#ifdef USE_ARDUINO_OTA - MDNS.update(); - ArduinoOTA.handle(); - - while (arduino_ota_triggered) ArduinoOTA.handle(); -#endif - - uint32_t my_activity = millis() - my_sleep; - - if (Settings.flag3.sleep_normal) { - - delay(sleep); - } else { - if (my_activity < (uint32_t)sleep) { - delay((uint32_t)sleep - my_activity); - } else { - if (global_state.wifi_down) { - delay(my_activity /2); - } - } - } - - if (!my_activity) { my_activity++; } - uint32_t loop_delay = sleep; - if (!loop_delay) { loop_delay++; } - uint32_t loops_per_second = 1000 / loop_delay; - uint32_t this_cycle_ratio = 100 * my_activity / loop_delay; - loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + (this_cycle_ratio / loops_per_second); -} -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/_changelog.ino" -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/settings.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/settings.ino" -#ifndef DOMOTICZ_UPDATE_TIMER -#define DOMOTICZ_UPDATE_TIMER 0 -#endif - -#ifndef EMULATION -#define EMULATION EMUL_NONE -#endif - -#ifndef MTX_ADDRESS1 -#define MTX_ADDRESS1 0 -#endif -#ifndef MTX_ADDRESS2 -#define MTX_ADDRESS2 0 -#endif -#ifndef MTX_ADDRESS3 -#define MTX_ADDRESS3 0 -#endif -#ifndef MTX_ADDRESS4 -#define MTX_ADDRESS4 0 -#endif -#ifndef MTX_ADDRESS5 -#define MTX_ADDRESS5 0 -#endif -#ifndef MTX_ADDRESS6 -#define MTX_ADDRESS6 0 -#endif -#ifndef MTX_ADDRESS7 -#define MTX_ADDRESS7 0 -#endif -#ifndef MTX_ADDRESS8 -#define MTX_ADDRESS8 0 -#endif - -#ifndef HOME_ASSISTANT_DISCOVERY_ENABLE -#define HOME_ASSISTANT_DISCOVERY_ENABLE 0 -#endif - -#ifndef LATITUDE -#define LATITUDE 48.858360 -#endif -#ifndef LONGITUDE -#define LONGITUDE 2.294442 -#endif - -#ifndef WORKING_PERIOD -#define WORKING_PERIOD 5 -#endif - -#ifndef COLOR_TEXT -#define COLOR_TEXT "#000" -#endif -#ifndef COLOR_BACKGROUND -#define COLOR_BACKGROUND "#fff" -#endif -#ifndef COLOR_FORM -#define COLOR_FORM "#f2f2f2" -#endif -#ifndef COLOR_INPUT_TEXT -#define COLOR_INPUT_TEXT "#000" -#endif -#ifndef COLOR_INPUT -#define COLOR_INPUT "#fff" -#endif -#ifndef COLOR_CONSOLE_TEXT -#define COLOR_CONSOLE_TEXT "#000" -#endif -#ifndef COLOR_CONSOLE -#define COLOR_CONSOLE "#fff" -#endif -#ifndef COLOR_TEXT_WARNING -#define COLOR_TEXT_WARNING "#f00" -#endif -#ifndef COLOR_TEXT_SUCCESS -#define COLOR_TEXT_SUCCESS "#008000" -#endif -#ifndef COLOR_BUTTON_TEXT -#define COLOR_BUTTON_TEXT "#fff" -#endif -#ifndef COLOR_BUTTON -#define COLOR_BUTTON "#1fa3ec" -#endif -#ifndef COLOR_BUTTON_HOVER -#define COLOR_BUTTON_HOVER "#0e70a4" -#endif -#ifndef COLOR_BUTTON_RESET -#define COLOR_BUTTON_RESET "#d43535" -#endif -#ifndef COLOR_BUTTON_RESET_HOVER -#define COLOR_BUTTON_RESET_HOVER "#931f1f" -#endif -#ifndef COLOR_BUTTON_SAVE -#define COLOR_BUTTON_SAVE "#47c266" -#endif -#ifndef COLOR_BUTTON_SAVE_HOVER -#define COLOR_BUTTON_SAVE_HOVER "#5aaf6f" -#endif -#ifndef COLOR_TIMER_TAB_TEXT -#define COLOR_TIMER_TAB_TEXT "#fff" -#endif -#ifndef COLOR_TIMER_TAB_BACKGROUND -#define COLOR_TIMER_TAB_BACKGROUND "#999" -#endif -#ifndef IR_RCV_MIN_UNKNOWN_SIZE -#define IR_RCV_MIN_UNKNOWN_SIZE 6 -#endif -#ifndef ENERGY_OVERTEMP -#define ENERGY_OVERTEMP 90 -#endif -#ifndef TUYA_DIMMER_MAX -#define TUYA_DIMMER_MAX 100 -#endif - -enum WebColors { - COL_TEXT, COL_BACKGROUND, COL_FORM, - COL_INPUT_TEXT, COL_INPUT, COL_CONSOLE_TEXT, COL_CONSOLE, - COL_TEXT_WARNING, COL_TEXT_SUCCESS, - COL_BUTTON_TEXT, COL_BUTTON, COL_BUTTON_HOVER, COL_BUTTON_RESET, COL_BUTTON_RESET_HOVER, COL_BUTTON_SAVE, COL_BUTTON_SAVE_HOVER, - COL_TIMER_TAB_TEXT, COL_TIMER_TAB_BACKGROUND, - COL_LAST }; - -const char kWebColors[] PROGMEM = - COLOR_TEXT "|" COLOR_BACKGROUND "|" COLOR_FORM "|" - COLOR_INPUT_TEXT "|" COLOR_INPUT "|" COLOR_CONSOLE_TEXT "|" COLOR_CONSOLE "|" - COLOR_TEXT_WARNING "|" COLOR_TEXT_SUCCESS "|" - COLOR_BUTTON_TEXT "|" COLOR_BUTTON "|" COLOR_BUTTON_HOVER "|" COLOR_BUTTON_RESET "|" COLOR_BUTTON_RESET_HOVER "|" COLOR_BUTTON_SAVE "|" COLOR_BUTTON_SAVE_HOVER "|" - COLOR_TIMER_TAB_TEXT "|" COLOR_TIMER_TAB_BACKGROUND; - - - - - -const uint16_t RTC_MEM_VALID = 0xA55A; - -uint32_t rtc_settings_crc = 0; - -uint32_t GetRtcSettingsCrc(void) -{ - uint32_t crc = 0; - uint8_t *bytes = (uint8_t*)&RtcSettings; - - for (uint32_t i = 0; i < sizeof(RTCMEM); i++) { - crc += bytes[i]*(i+1); - } - return crc; -} - -void RtcSettingsSave(void) -{ - if (GetRtcSettingsCrc() != rtc_settings_crc) { - RtcSettings.valid = RTC_MEM_VALID; - ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); - rtc_settings_crc = GetRtcSettingsCrc(); - } -} - -void RtcSettingsLoad(void) -{ - ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); - if (RtcSettings.valid != RTC_MEM_VALID) { - memset(&RtcSettings, 0, sizeof(RTCMEM)); - RtcSettings.valid = RTC_MEM_VALID; - RtcSettings.energy_kWhtoday = Settings.energy_kWhtoday; - RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal; - RtcSettings.energy_usage = Settings.energy_usage; - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - RtcSettings.pulse_counter[i] = Settings.pulse_counter[i]; - } - RtcSettings.power = Settings.power; - RtcSettingsSave(); - } - rtc_settings_crc = GetRtcSettingsCrc(); -} - -bool RtcSettingsValid(void) -{ - return (RTC_MEM_VALID == RtcSettings.valid); -} - - - -uint32_t rtc_reboot_crc = 0; - -uint32_t GetRtcRebootCrc(void) -{ - uint32_t crc = 0; - uint8_t *bytes = (uint8_t*)&RtcReboot; - - for (uint32_t i = 0; i < sizeof(RTCRBT); i++) { - crc += bytes[i]*(i+1); - } - return crc; -} - -void RtcRebootSave(void) -{ - if (GetRtcRebootCrc() != rtc_reboot_crc) { - RtcReboot.valid = RTC_MEM_VALID; - ESP.rtcUserMemoryWrite(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); - rtc_reboot_crc = GetRtcRebootCrc(); - } -} - -void RtcRebootLoad(void) -{ - ESP.rtcUserMemoryRead(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); - if (RtcReboot.valid != RTC_MEM_VALID) { - memset(&RtcReboot, 0, sizeof(RTCRBT)); - RtcReboot.valid = RTC_MEM_VALID; - - RtcRebootSave(); - } - rtc_reboot_crc = GetRtcRebootCrc(); -} - -bool RtcRebootValid(void) -{ - return (RTC_MEM_VALID == RtcReboot.valid); -} - - - - - -extern "C" { -#include "spi_flash.h" -} -#include "eboot_command.h" - -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2) - -extern "C" uint32_t _SPIFFS_end; - -const uint32_t SPIFFS_END = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; - -#else - -extern "C" uint32_t _FS_end; - -const uint32_t SPIFFS_END = ((uint32_t)&_FS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; - -#endif - - -const uint32_t SETTINGS_LOCATION = SPIFFS_END; - -const uint8_t CFG_ROTATES = 8; - -uint32_t settings_location = SETTINGS_LOCATION; -uint32_t settings_crc32 = 0; -uint8_t *settings_buffer = nullptr; - - - - - -void SetFlashModeDout(void) -{ - uint8_t *_buffer; - uint32_t address; - - eboot_command ebcmd; - eboot_command_read(&ebcmd); - address = ebcmd.args[0]; - _buffer = new uint8_t[FLASH_SECTOR_SIZE]; - - if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) { - if (_buffer[2] != 3) { - _buffer[2] = 3; - if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); - } - } - delete[] _buffer; -} - -void SettingsBufferFree(void) -{ - if (settings_buffer != nullptr) { - free(settings_buffer); - settings_buffer = nullptr; - } -} - -bool SettingsBufferAlloc(void) -{ - SettingsBufferFree(); - if (!(settings_buffer = (uint8_t *)malloc(sizeof(Settings)))) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_UPLOAD_ERR_2)); - return false; - } - return true; -} - -uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size) -{ - uint16_t crc = 0; - - for (uint32_t i = 0; i < size; i++) { - if ((i < 14) || (i > 15)) { crc += bytes[i]*(i+1); } - } - return crc; -} - -uint16_t GetSettingsCrc(void) -{ - - uint32_t size = ((Settings.version < 0x06060007) || (Settings.version > 0x0606000A)) ? 3584 : sizeof(SYSCFG); - return GetCfgCrc16((uint8_t*)&Settings, size); -} - -uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size) -{ - - uint32_t crc = 0; - - while (size--) { - crc ^= *bytes++; - for (uint32_t j = 0; j < 8; j++) { - crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320); - } - } - return ~crc; -} - -uint32_t GetSettingsCrc32(void) -{ - return GetCfgCrc32((uint8_t*)&Settings, sizeof(SYSCFG) -4); -} - -void SettingsSaveAll(void) -{ - if (Settings.flag.save_state) { - Settings.power = power; - } else { - Settings.power = 0; - } - XsnsCall(FUNC_SAVE_BEFORE_RESTART); - XdrvCall(FUNC_SAVE_BEFORE_RESTART); - SettingsSave(0); -} - - - - - -uint32_t GetSettingsAddress(void) -{ - return settings_location * SPI_FLASH_SEC_SIZE; -} - -void SettingsSave(uint8_t rotate) -{ -# 379 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/settings.ino" -#ifndef FIRMWARE_MINIMAL - if ((GetSettingsCrc32() != settings_crc32) || rotate) { - if (1 == rotate) { - stop_flash_rotate = 1; - } - if (2 == rotate) { - settings_location = SETTINGS_LOCATION +1; - } - if (stop_flash_rotate) { - settings_location = SETTINGS_LOCATION; - } else { - settings_location--; - if (settings_location <= (SETTINGS_LOCATION - CFG_ROTATES)) { - settings_location = SETTINGS_LOCATION; - } - } - - Settings.save_flag++; - if (UtcTime() > START_VALID_TIME) { - Settings.cfg_timestamp = UtcTime(); - } else { - Settings.cfg_timestamp++; - } - Settings.cfg_size = sizeof(SYSCFG); - Settings.cfg_crc = GetSettingsCrc(); - Settings.cfg_crc32 = GetSettingsCrc32(); - - ESP.flashEraseSector(settings_location); - ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - - if (!stop_flash_rotate && rotate) { - for (uint32_t i = 1; i < CFG_ROTATES; i++) { - ESP.flashEraseSector(settings_location -i); - delay(1); - } - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG)); - - settings_crc32 = Settings.cfg_crc32; - } -#endif - RtcSettingsSave(); -} - -void SettingsLoad(void) -{ - - struct SYSCFGH { - uint16_t cfg_holder; - uint16_t cfg_size; - unsigned long save_flag; - } _SettingsH; - unsigned long save_flag = 0; - - settings_location = 0; - uint32_t flash_location = SETTINGS_LOCATION +1; - uint16_t cfg_holder = 0; - for (uint32_t i = 0; i < CFG_ROTATES; i++) { - flash_location--; - ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - - bool valid = false; - if (Settings.version > 0x06000000) { - bool almost_valid = (Settings.cfg_crc32 == GetSettingsCrc32()); - if (Settings.version < 0x0606000B) { - almost_valid = (Settings.cfg_crc == GetSettingsCrc()); - } - - if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } - valid = (cfg_holder == Settings.cfg_holder); - } else { - ESP.flashRead((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); - valid = (Settings.cfg_holder == _SettingsH.cfg_holder); - } - if (valid) { - if (Settings.save_flag > save_flag) { - save_flag = Settings.save_flag; - settings_location = flash_location; - if (Settings.flag.stop_flash_rotate && (0 == i)) { - break; - } - } - } - - delay(1); - } - if (settings_location > 0) { - ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); - } - -#ifndef FIRMWARE_MINIMAL - if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { - SettingsDefault(); - } - settings_crc32 = GetSettingsCrc32(); -#endif - - RtcSettingsLoad(); -} - -void SettingsErase(uint8_t type) -{ - - - - - -#ifndef FIRMWARE_MINIMAL - bool result; - - uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; - uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; - if (1 == type) { - _sectorStart = SETTINGS_LOCATION +2; - _sectorEnd = SETTINGS_LOCATION +5; - } - - bool _serialoutput = (LOG_LEVEL_DEBUG_MORE <= seriallog_level); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " %d " D_UNIT_SECTORS), _sectorEnd - _sectorStart); - - for (uint32_t _sector = _sectorStart; _sector < _sectorEnd; _sector++) { - result = ESP.flashEraseSector(_sector); - if (_serialoutput) { - Serial.print(F(D_LOG_APPLICATION D_ERASED_SECTOR " ")); - Serial.print(_sector); - if (result) { - Serial.println(F(" " D_OK)); - } else { - Serial.println(F(" " D_ERROR)); - } - delay(10); - } - OsWatchLoop(); - } -#endif -} - - -bool SettingsEraseConfig(void) { - const size_t cfgSize = 0x4000; - size_t cfgAddr = ESP.getFlashChipSize() - cfgSize; - - for (size_t offset = 0; offset < cfgSize; offset += SPI_FLASH_SEC_SIZE) { - if (!ESP.flashEraseSector((cfgAddr + offset) / SPI_FLASH_SEC_SIZE)) { - return false; - } - } - return true; -} - -void SettingsSdkErase(void) -{ - WiFi.disconnect(true); - SettingsErase(1); - SettingsEraseConfig(); - delay(1000); -} - - - -void SettingsDefault(void) -{ - AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_USE_DEFAULTS)); - SettingsDefaultSet1(); - SettingsDefaultSet2(); - SettingsSave(2); -} - -void SettingsDefaultSet1(void) -{ - memset(&Settings, 0x00, sizeof(SYSCFG)); - - Settings.cfg_holder = (uint16_t)CFG_HOLDER; - Settings.cfg_size = sizeof(SYSCFG); - - Settings.version = VERSION; - - -} - -void SettingsDefaultSet2(void) -{ - memset((char*)&Settings +16, 0x00, sizeof(SYSCFG) -16); - - - - Settings.save_data = SAVE_DATA; - Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; - Settings.param[P_RGB_REMAP] = RGB_REMAP_RGBW; - Settings.sleep = APP_SLEEP; - if (Settings.sleep < 50) { - Settings.sleep = 50; - } - - - - Settings.interlock[0] = 0xFF; - Settings.module = MODULE; - ModuleDefault(WEMOS); - - 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])); - strlcpy(Settings.ota_url, OTA_URL, sizeof(Settings.ota_url)); - - - Settings.flag.save_state = SAVE_STATE; - Settings.power = APP_POWER; - Settings.poweronstate = APP_POWERON_STATE; - Settings.blinktime = APP_BLINKTIME; - Settings.blinkcount = APP_BLINKCOUNT; - Settings.ledstate = APP_LEDSTATE; - Settings.ledmask = APP_LEDMASK; - Settings.pulse_timer[0] = APP_PULSETIME; - - - - Settings.baudrate = APP_BAUDRATE / 300; - Settings.sbaudrate = SOFT_BAUDRATE / 300; - Settings.serial_delimiter = 0xff; - Settings.seriallog_level = SERIAL_LOG_LEVEL; - - - 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); - Settings.sta_config = WIFI_CONFIG_TOOL; - - 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)); - - - strlcpy(Settings.syslog_host, SYS_LOG_HOST, sizeof(Settings.syslog_host)); - Settings.syslog_port = SYS_LOG_PORT; - Settings.syslog_level = SYS_LOG_LEVEL; - - - Settings.flag2.emulation = EMULATION; - Settings.webserver = WEB_SERVER; - Settings.weblog_level = WEB_LOG_LEVEL; - strlcpy(Settings.web_password, WEB_PASSWORD, sizeof(Settings.web_password)); - Settings.flag3.mdns_enabled = MDNS_ENABLED; - - - - - - Settings.param[P_HOLD_TIME] = KEY_HOLD_TIME; - - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { Settings.switchmode[i] = SWITCH_MODE; } - - - Settings.flag.mqtt_enabled = MQTT_USE; - - Settings.flag.mqtt_power_retain = MQTT_POWER_RETAIN; - Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN; - Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; - Settings.flag3.button_switch_force_local = MQTT_BUTTON_SWITCH_FORCE_LOCAL; - Settings.flag3.hass_tele_on_power = TELE_ON_POWER; - - - - - 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, MQTT_BUTTON_TOPIC, sizeof(Settings.button_topic)); - strlcpy(Settings.switch_topic, MQTT_SWITCH_TOPIC, sizeof(Settings.switch_topic)); - strlcpy(Settings.mqtt_grptopic, MQTT_GRPTOPIC, sizeof(Settings.mqtt_grptopic)); - strlcpy(Settings.mqtt_fulltopic, MQTT_FULLTOPIC, sizeof(Settings.mqtt_fulltopic)); - Settings.mqtt_retry = MQTT_RETRY_SECS; - 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])); - 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])); - char fingerprint[60]; - strlcpy(fingerprint, MQTT_FINGERPRINT1, sizeof(fingerprint)); - char *p = fingerprint; - for (uint32_t i = 0; i < 20; i++) { - Settings.mqtt_fingerprint[0][i] = strtol(p, &p, 16); - } - strlcpy(fingerprint, MQTT_FINGERPRINT2, sizeof(fingerprint)); - p = fingerprint; - for (uint32_t i = 0; i < 20; i++) { - Settings.mqtt_fingerprint[1][i] = strtol(p, &p, 16); - } - Settings.tele_period = TELE_PERIOD; - - - Settings.flag2.current_resolution = 3; - - - Settings.flag2.energy_resolution = ENERGY_RESOLUTION; - Settings.param[P_MAX_POWER_RETRY] = MAX_POWER_RETRY; - - Settings.energy_power_calibration = HLW_PREF_PULSE; - Settings.energy_voltage_calibration = HLW_UREF_PULSE; - Settings.energy_current_calibration = HLW_IREF_PULSE; -# 702 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/settings.ino" - Settings.energy_max_power_limit_hold = MAX_POWER_HOLD; - Settings.energy_max_power_limit_window = MAX_POWER_WINDOW; - - Settings.energy_max_power_safe_limit_hold = SAFE_POWER_HOLD; - Settings.energy_max_power_safe_limit_window = SAFE_POWER_WINDOW; - - - - RtcSettings.energy_kWhtotal = 0; - - memset((char*)&RtcSettings.energy_usage, 0x00, sizeof(RtcSettings.energy_usage)); - Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP; - - - Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; - - - - memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); - - - Settings.domoticz_update_timer = DOMOTICZ_UPDATE_TIMER; -# 734 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/settings.ino" - Settings.flag.temperature_conversion = TEMP_CONVERSION; - Settings.flag.pressure_conversion = PRESSURE_CONVERSION; - Settings.flag2.pressure_resolution = PRESSURE_RESOLUTION; - Settings.flag2.humidity_resolution = HUMIDITY_RESOLUTION; - Settings.flag2.temperature_resolution = TEMP_RESOLUTION; - - - - - - - Settings.flag2.calc_resolution = CALC_RESOLUTION; - - - Settings.flag.hass_discovery = HOME_ASSISTANT_DISCOVERY_ENABLE; - - - - - - - Settings.flag.pwm_control = 1; - - - - - Settings.pwm_frequency = PWM_FREQ; - Settings.pwm_range = PWM_RANGE; - for (uint32_t i = 0; i < MAX_PWMS; i++) { - Settings.light_color[i] = 255; - - } - Settings.light_correction = 1; - Settings.light_dimmer = 10; - - Settings.light_speed = 1; - - Settings.light_width = 1; - - Settings.light_pixels = WS2812_LEDS; - - SettingsDefaultSet_5_8_1(); - - Settings.param[P_TUYA_DIMMER_MAX] = TUYA_DIMMER_MAX; - - - SettingsDefaultSet_5_10_1(); - - - if (((APP_TIMEZONE > -14) && (APP_TIMEZONE < 15)) || (99 == APP_TIMEZONE)) { - Settings.timezone = APP_TIMEZONE; - Settings.timezone_minutes = 0; - } else { - Settings.timezone = APP_TIMEZONE / 60; - Settings.timezone_minutes = abs(APP_TIMEZONE % 60); - } - 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 (uint32_t j = 0; j < 3; j++) { - for (uint32_t i = 0; i < strlen(Settings.ntp_server[j]); i++) { - if (Settings.ntp_server[j][i] == ',') { - Settings.ntp_server[j][i] = '.'; - } - } - } - Settings.latitude = (int)((double)LATITUDE * 1000000); - Settings.longitude = (int)((double)LONGITUDE * 1000000); - SettingsDefaultSet_5_13_1c(); - - Settings.button_debounce = KEY_DEBOUNCE_TIME; - Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; - - for (uint32_t j = 0; j < 5; j++) { - Settings.rgbwwTable[j] = 255; - } - - Settings.novasds_period = WORKING_PERIOD; - - SettingsDefaultWebColor(); - - memset(&Settings.monitors, 0xFF, 20); -} - - - -void SettingsDefaultSet_5_8_1(void) -{ - - 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 SettingsDefaultSet_5_10_1(void) -{ - Settings.display_model = 0; - Settings.display_mode = 1; - Settings.display_refresh = 2; - Settings.display_rows = 2; - Settings.display_cols[0] = 16; - Settings.display_cols[1] = 8; - Settings.display_dimmer = 1; - Settings.display_size = 1; - Settings.display_font = 1; - Settings.display_rotate = 0; - Settings.display_address[0] = MTX_ADDRESS1; - Settings.display_address[1] = MTX_ADDRESS2; - Settings.display_address[2] = MTX_ADDRESS3; - Settings.display_address[3] = MTX_ADDRESS4; - Settings.display_address[4] = MTX_ADDRESS5; - Settings.display_address[5] = MTX_ADDRESS6; - Settings.display_address[6] = MTX_ADDRESS7; - Settings.display_address[7] = MTX_ADDRESS8; -} - -void SettingsResetStd(void) -{ - Settings.tflag[0].hemis = TIME_STD_HEMISPHERE; - Settings.tflag[0].week = TIME_STD_WEEK; - Settings.tflag[0].dow = TIME_STD_DAY; - Settings.tflag[0].month = TIME_STD_MONTH; - Settings.tflag[0].hour = TIME_STD_HOUR; - Settings.toffset[0] = TIME_STD_OFFSET; -} - -void SettingsResetDst(void) -{ - Settings.tflag[1].hemis = TIME_DST_HEMISPHERE; - Settings.tflag[1].week = TIME_DST_WEEK; - Settings.tflag[1].dow = TIME_DST_DAY; - Settings.tflag[1].month = TIME_DST_MONTH; - Settings.tflag[1].hour = TIME_DST_HOUR; - Settings.toffset[1] = TIME_DST_OFFSET; -} - -void SettingsDefaultSet_5_13_1c(void) -{ - SettingsResetStd(); - SettingsResetDst(); -} - -void SettingsDefaultWebColor(void) -{ - char scolor[10]; - for (uint32_t i = 0; i < COL_LAST; i++) { - WebHexCode(i, GetTextIndexed(scolor, sizeof(scolor), i, kWebColors)); - } -} - - - -void SettingsDelta(void) -{ - if (Settings.version != VERSION) { - - if (Settings.version < 0x05050000) { - for (uint32_t i = 0; i < 17; i++) { Settings.rf_code[i][0] = 0; } - memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); - } - if (Settings.version < 0x05080000) { - Settings.light_pixels = WS2812_LEDS; - Settings.light_width = 1; - Settings.light_color[0] = 255; - Settings.light_color[1] = 0; - Settings.light_color[2] = 0; - Settings.light_dimmer = 10; - Settings.light_correction = 1; - Settings.light_fade = 0; - Settings.light_speed = 1; - Settings.light_scheme = 0; - Settings.light_width = 1; - Settings.light_wakeup = 0; - } - if (Settings.version < 0x0508000A) { - Settings.power = 0; - Settings.altitude = 0; - } - if (Settings.version < 0x0508000B) { - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if ((Settings.my_gp.io[i] >= 25) && (Settings.my_gp.io[i] <= 32)) { - Settings.my_gp.io[i] += 23; - } - } - for (uint32_t i = 0; i < MAX_PWMS; i++) { - 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(); - } - if (Settings.version < 0x05090102) { - Settings.flag2.data = Settings.flag.data; - Settings.flag2.data &= 0xFFE80000; - Settings.flag2.voltage_resolution = Settings.flag.not_power_linked; - Settings.flag2.current_resolution = 3; - Settings.ina219_mode = 0; - } - if (Settings.version < 0x050A0009) { - SettingsDefaultSet_5_10_1(); - } - if (Settings.version < 0x050B0107) { - Settings.flag.not_power_linked = 0; - } - if (Settings.version < 0x050C0005) { - Settings.light_rotation = 0; - Settings.energy_power_delta = 0; - char fingerprint[60]; - memcpy(fingerprint, Settings.mqtt_fingerprint, sizeof(fingerprint)); - char *p = fingerprint; - for (uint32_t i = 0; i < 20; i++) { - Settings.mqtt_fingerprint[0][i] = strtol(p, &p, 16); - Settings.mqtt_fingerprint[1][i] = Settings.mqtt_fingerprint[0][i]; - } - } - if (Settings.version < 0x050C0007) { - Settings.baudrate = APP_BAUDRATE / 300; - } - if (Settings.version < 0x050C0008) { - Settings.sbaudrate = SOFT_BAUDRATE / 300; - Settings.serial_delimiter = 0xff; - } - if (Settings.version < 0x050C000A) { - Settings.latitude = (int)((double)LATITUDE * 1000000); - Settings.longitude = (int)((double)LONGITUDE * 1000000); - } - if (Settings.version < 0x050C000B) { - Settings.rules[0][0] = '\0'; - } - if (Settings.version < 0x050C000D) { - memmove(Settings.rules, Settings.rules -256, sizeof(Settings.rules)); - memset(&Settings.timer, 0x00, sizeof(Timer) * MAX_TIMERS); - Settings.knx_GA_registered = 0; - Settings.knx_CB_registered = 0; - memset(&Settings.knx_physsical_addr, 0x00, 0x800 - 0x6b8); - } - if (Settings.version < 0x050C000F) { - Settings.energy_kWhtoday /= 1000; - Settings.energy_kWhyesterday /= 1000; - RtcSettings.energy_kWhtoday /= 1000; - } - if (Settings.version < 0x050D0103) { - SettingsDefaultSet_5_13_1c(); - } - if (Settings.version < 0x050E0002) { - for (uint32_t i = 1; i < MAX_RULE_SETS; i++) { Settings.rules[i][0] = '\0'; } - Settings.rule_enabled = Settings.flag.mqtt_serial_raw; - Settings.rule_once = Settings.flag.pressure_conversion; - } - if (Settings.version < 0x06000000) { - Settings.cfg_size = sizeof(SYSCFG); - Settings.cfg_crc = GetSettingsCrc(); - } - if (Settings.version < 0x06000002) { - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - if (i < 4) { - Settings.switchmode[i] = Settings.interlock[i]; - } else { - Settings.switchmode[i] = SWITCH_MODE; - } - } - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (Settings.my_gp.io[i] >= GPIO_SWT5) { - Settings.my_gp.io[i] += 4; - } - } - } - if (Settings.version < 0x06000003) { - Settings.flag.mqtt_serial_raw = 0; - Settings.flag.pressure_conversion = 0; - Settings.flag3.data = 0; - } - if (Settings.version < 0x06010103) { - Settings.flag3.timers_enable = 1; - } - if (Settings.version < 0x0601010C) { - Settings.button_debounce = KEY_DEBOUNCE_TIME; - Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; - } - if (Settings.version < 0x0602010A) { - for (uint32_t j = 0; j < 5; j++) { - Settings.rgbwwTable[j] = 255; - } - } - if (Settings.version < 0x06030002) { - Settings.timezone_minutes = 0; - } - if (Settings.version < 0x06030004) { - memset(&Settings.monitors, 0xFF, 20); - } - if (Settings.version < 0x0603000E) { - Settings.flag2.calc_resolution = CALC_RESOLUTION; - } - if (Settings.version < 0x0603000F) { - if (Settings.sleep < 50) { - Settings.sleep = 50; - } - } - if (Settings.version < 0x06040105) { - Settings.flag3.mdns_enabled = MDNS_ENABLED; - Settings.param[P_MDNS_DELAYED_START] = 0; - } - if (Settings.version < 0x0604010B) { - Settings.interlock[0] = 0xFF; - for (uint32_t i = 1; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } - } - if (Settings.version < 0x0604010D) { - Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; - } - if (Settings.version < 0x06040110) { - ModuleDefault(WEMOS); - } - if (Settings.version < 0x06040113) { - Settings.param[P_RGB_REMAP] = RGB_REMAP_RGBW; - } - if (Settings.version < 0x06050003) { - Settings.novasds_period = WORKING_PERIOD; - } - if (Settings.version < 0x06050006) { - SettingsDefaultWebColor(); - } - if (Settings.version < 0x06050007) { - Settings.ledmask = APP_LEDMASK; - } - if (Settings.version < 0x0605000A) { - Settings.my_adc0 = ADC0_NONE; - } - if (Settings.version < 0x0605000D) { - Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; - } - if (Settings.version < 0x06060001) { - Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP; - } - if (Settings.version < 0x06060007) { - memset((char*)&Settings +0xE00, 0x00, sizeof(SYSCFG) -0xE00); - } - if (Settings.version < 0x06060008) { - - if (Settings.flag3.tuya_dimmer_range_255) { - Settings.param[P_TUYA_DIMMER_MAX] = 100; - } else { - Settings.param[P_TUYA_DIMMER_MAX] = 255; - } - } - if (Settings.version < 0x06060009) { - Settings.baudrate = Settings.ex_baudrate * 4; - Settings.sbaudrate = Settings.ex_sbaudrate * 4; - } - - if (Settings.version < 0x0606000A) { - uint8_t tuyaindex = 0; - if (Settings.param[P_ex_TUYA_DIMMER_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 21; - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_DIMMER_ID]; - tuyaindex++; - } else if (Settings.flag3.ex_tuya_disable_dimmer == 1) { - Settings.tuya_fnid_map[tuyaindex].fnid = 11; - Settings.tuya_fnid_map[tuyaindex].dpid = 1; - tuyaindex++; - } - if (Settings.param[P_ex_TUYA_RELAYS] > 0) { - for (uint8_t i = 0 ; i < Settings.param[P_ex_TUYA_RELAYS]; i++) { - Settings.tuya_fnid_map[tuyaindex].fnid = 12 + i; - Settings.tuya_fnid_map[tuyaindex].dpid = i + 2; - tuyaindex++; - } - } - if (Settings.param[P_ex_TUYA_POWER_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 31; - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_POWER_ID]; - tuyaindex++; - } - if (Settings.param[P_ex_TUYA_VOLTAGE_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 33; - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_VOLTAGE_ID]; - tuyaindex++; - } - if (Settings.param[P_ex_TUYA_CURRENT_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 32; - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_CURRENT_ID]; - tuyaindex++; - } - } - if (Settings.version < 0x0606000C) { - memset(&Settings.register8, 0x00, sizeof(Settings.register8)); - } - - Settings.version = VERSION; - SettingsSave(1); - } -} -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/sonoff_ca.ino" -# 24 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/sonoff_ca.ino" -#ifdef USE_MQTT_TLS_CA_CERT - -#ifndef USE_MQTT_AWS_IOT -# 38 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/sonoff_ca.ino" -static const unsigned char PROGMEM TA0_DN[] = { - 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x13, 0x0D, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x1A, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, - 0x79, 0x20, 0x58, 0x33 -}; - -static const unsigned char PROGMEM TA0_RSA_N[] = { - 0x9C, 0xD3, 0x0C, 0xF0, 0x5A, 0xE5, 0x2E, 0x47, 0xB7, 0x72, 0x5D, 0x37, - 0x83, 0xB3, 0x68, 0x63, 0x30, 0xEA, 0xD7, 0x35, 0x26, 0x19, 0x25, 0xE1, - 0xBD, 0xBE, 0x35, 0xF1, 0x70, 0x92, 0x2F, 0xB7, 0xB8, 0x4B, 0x41, 0x05, - 0xAB, 0xA9, 0x9E, 0x35, 0x08, 0x58, 0xEC, 0xB1, 0x2A, 0xC4, 0x68, 0x87, - 0x0B, 0xA3, 0xE3, 0x75, 0xE4, 0xE6, 0xF3, 0xA7, 0x62, 0x71, 0xBA, 0x79, - 0x81, 0x60, 0x1F, 0xD7, 0x91, 0x9A, 0x9F, 0xF3, 0xD0, 0x78, 0x67, 0x71, - 0xC8, 0x69, 0x0E, 0x95, 0x91, 0xCF, 0xFE, 0xE6, 0x99, 0xE9, 0x60, 0x3C, - 0x48, 0xCC, 0x7E, 0xCA, 0x4D, 0x77, 0x12, 0x24, 0x9D, 0x47, 0x1B, 0x5A, - 0xEB, 0xB9, 0xEC, 0x1E, 0x37, 0x00, 0x1C, 0x9C, 0xAC, 0x7B, 0xA7, 0x05, - 0xEA, 0xCE, 0x4A, 0xEB, 0xBD, 0x41, 0xE5, 0x36, 0x98, 0xB9, 0xCB, 0xFD, - 0x6D, 0x3C, 0x96, 0x68, 0xDF, 0x23, 0x2A, 0x42, 0x90, 0x0C, 0x86, 0x74, - 0x67, 0xC8, 0x7F, 0xA5, 0x9A, 0xB8, 0x52, 0x61, 0x14, 0x13, 0x3F, 0x65, - 0xE9, 0x82, 0x87, 0xCB, 0xDB, 0xFA, 0x0E, 0x56, 0xF6, 0x86, 0x89, 0xF3, - 0x85, 0x3F, 0x97, 0x86, 0xAF, 0xB0, 0xDC, 0x1A, 0xEF, 0x6B, 0x0D, 0x95, - 0x16, 0x7D, 0xC4, 0x2B, 0xA0, 0x65, 0xB2, 0x99, 0x04, 0x36, 0x75, 0x80, - 0x6B, 0xAC, 0x4A, 0xF3, 0x1B, 0x90, 0x49, 0x78, 0x2F, 0xA2, 0x96, 0x4F, - 0x2A, 0x20, 0x25, 0x29, 0x04, 0xC6, 0x74, 0xC0, 0xD0, 0x31, 0xCD, 0x8F, - 0x31, 0x38, 0x95, 0x16, 0xBA, 0xA8, 0x33, 0xB8, 0x43, 0xF1, 0xB1, 0x1F, - 0xC3, 0x30, 0x7F, 0xA2, 0x79, 0x31, 0x13, 0x3D, 0x2D, 0x36, 0xF8, 0xE3, - 0xFC, 0xF2, 0x33, 0x6A, 0xB9, 0x39, 0x31, 0xC5, 0xAF, 0xC4, 0x8D, 0x0D, - 0x1D, 0x64, 0x16, 0x33, 0xAA, 0xFA, 0x84, 0x29, 0xB6, 0xD4, 0x0B, 0xC0, - 0xD8, 0x7D, 0xC3, 0x93 -}; - -static const unsigned char TA0_RSA_E[] = { - 0x01, 0x00, 0x01 -}; - -static const br_x509_trust_anchor PROGMEM LetsEncryptX3CrossSigned_TA = { - { (unsigned char *)TA0_DN, sizeof TA0_DN }, - BR_X509_TA_CA, - { - BR_KEYTYPE_RSA, - { .rsa = { - (unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N, - (unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E, - } } - } -}; - -#define TAs_NUM 1 - -#endif - -#ifdef USE_MQTT_AWS_IOT -# 106 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/sonoff_ca.ino" -const unsigned char PROGMEM TA0_DN[] = { - 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, - 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 -}; - -const unsigned char PROGMEM TA0_RSA_N[] = { - 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, - 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, - 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, - 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, - 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, - 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, - 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, - 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, - 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, - 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, - 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, - 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, - 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, - 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, - 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, - 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, - 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, - 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, - 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, - 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, - 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, - 0x9A, 0xC8, 0xAA, 0x0D -}; - -static const unsigned char PROGMEM TA0_RSA_E[] = { - 0x01, 0x00, 0x01 -}; - -const br_x509_trust_anchor PROGMEM AmazonRootCA1_TA = { - { (unsigned char *)TA0_DN, sizeof TA0_DN }, - BR_X509_TA_CA, - { - BR_KEYTYPE_RSA, - { .rsa = { - (unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N, - (unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E, - } } - } -}; - -#define TAs_NUM 1 - -#endif - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support.ino" -IPAddress syslog_host_addr; -uint32_t syslog_host_hash = 0; - - - - - -#include - -Ticker tickerOSWatch; - -const uint32_t OSWATCH_RESET_TIME = 120; - -static unsigned long oswatch_last_loop_time; -uint8_t oswatch_blocked_loop = 0; - -#ifndef USE_WS2812_DMA - -#endif - -#ifdef USE_KNX -bool knx_started = false; -#endif - -void OsWatchTicker(void) -{ - uint32_t t = millis(); - uint32_t last_run = abs(t - oswatch_last_loop_time); - -#ifdef DEBUG_THEO - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d, last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(WiFi.RSSI()), last_run); -#endif - if (last_run >= (OSWATCH_RESET_TIME * 1000)) { - - RtcSettings.oswatch_blocked_loop = 1; - RtcSettingsSave(); - - ESP.reset(); - } -} - -void OsWatchInit(void) -{ - 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 OsWatchLoop(void) -{ - oswatch_last_loop_time = millis(); - -} - -String GetResetReason(void) -{ - char buff[32]; - if (oswatch_blocked_loop) { - strncpy_P(buff, PSTR(D_JSON_BLOCKED_LOOP), sizeof(buff)); - return String(buff); - } else { - return ESP.getResetReason(); - } -} - -bool OsWatchBlockedLoop(void) -{ - return oswatch_blocked_loop; -} - - - - -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 - - - -void* memchr(const void* ptr, int value, size_t num) -{ - unsigned char *p = (unsigned char*)ptr; - while (num--) { - if (*p != (unsigned char)value) { - p++; - } else { - return p; - } - } - return 0; -} - - - -size_t strcspn(const char *str1, const char *str2) -{ - size_t ret = 0; - while (*str1) { - if (strchr(str2, *str1)) { - return ret; - } else { - str1++; - ret++; - } - } - return ret; -} - - - -char* strpbrk(const char *s1, const char *s2) -{ - while(*s1) { - if (strchr(s2, *s1++)) { - return (char*)--s1; - } - } - return 0; -} - - - -#ifndef __LONG_LONG_MAX__ -#define __LONG_LONG_MAX__ 9223372036854775807LL -#endif -#ifndef ULLONG_MAX -#define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1) -#endif - -unsigned long long strtoull(const char *__restrict nptr, char **__restrict endptr, int base) -{ - const char *s = nptr; - char c; - do { c = *s++; } while (isspace((unsigned char)c)); - - int neg = 0; - if (c == '-') { - neg = 1; - c = *s++; - } else { - if (c == '+') { - c = *s++; - } - } - - if ((base == 0 || base == 16) && (c == '0') && (*s == 'x' || *s == 'X')) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) { base = (c == '0') ? 8 : 10; } - - unsigned long long acc = 0; - int any = 0; - if (base > 1 && base < 37) { - unsigned long long cutoff = ULLONG_MAX / base; - int cutlim = ULLONG_MAX % base; - for ( ; ; c = *s++) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'A' && c <= 'Z') - c -= 'A' - 10; - else if (c >= 'a' && c <= 'z') - c -= 'a' - 10; - else - break; - - if (c >= base) - break; - - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = ULLONG_MAX; - } - else if (any && neg) { - acc = -acc; - } - } - - if (endptr != nullptr) { *endptr = (char *)(any ? s - 1 : nptr); } - - return acc; -} -#endif - - -size_t strchrspn(const char *str1, int character) -{ - size_t ret = 0; - char *start = (char*)str1; - char *end = strchr(str1, character); - if (end) ret = end - start; - return ret; -} - - -char* subStr(char* dest, char* str, const char *delim, int index) -{ - char *act; - char *sub = nullptr; - char *ptr; - int i; - - - strncpy(dest, str, strlen(str)+1); - for (i = 1, act = dest; i <= index; i++, act = nullptr) { - sub = strtok_r(act, delim, &ptr); - if (sub == nullptr) break; - } - sub = Trim(sub); - return sub; -} - -float CharToFloat(const char *str) -{ - - char strbuf[24]; - - strlcpy(strbuf, str, sizeof(strbuf)); - char *pt = strbuf; - while ((*pt != '\0') && isblank(*pt)) { pt++; } - - signed char sign = 1; - if (*pt == '-') { sign = -1; } - if (*pt == '-' || *pt=='+') { pt++; } - - float left = 0; - if (*pt != '.') { - left = atoi(pt); - while (isdigit(*pt)) { pt++; } - } - - float right = 0; - if (*pt == '.') { - pt++; - right = atoi(pt); - while (isdigit(*pt)) { - pt++; - right /= 10.0f; - } - } - - float result = left + right; - if (sign < 0) { - return -result; - } - return result; -} - -int TextToInt(char *str) -{ - char *p; - uint8_t radix = 10; - if ('#' == str[0]) { - radix = 16; - str++; - } - return strtol(str, &p, radix); -} - -char* ulltoa(unsigned long long value, char *str, int radix) -{ - char digits[64]; - char *dst = str; - int i = 0; - int n = 0; - - - - do { - n = value % radix; - digits[i++] = (n < 10) ? (char)n+'0' : (char)n-10+'A'; - value /= radix; - } while (value != 0); - - while (i > 0) { *dst++ = digits[--i]; } - - *dst = 0; - return str; -} - - - -char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween) -{ - - - - static const char * hex = "0123456789ABCDEF"; - int between = (inbetween) ? 3 : 2; - const unsigned char * pin = in; - char * pout = out; - for (; pin < in+insz; pout += between, pin++) { - pout[0] = hex[(pgm_read_byte(pin)>>4) & 0xF]; - pout[1] = hex[ pgm_read_byte(pin) & 0xF]; - if (inbetween) { pout[2] = inbetween; } - if (pout + 3 - out > outsz) { break; } - } - pout[(inbetween && insz) ? -1 : 0] = 0; - return out; -} - -char* Uint64toHex(uint64_t value, char *str, uint16_t bits) -{ - ulltoa(value, str, 16); - - int fill = 8; - if ((bits > 3) && (bits < 65)) { - fill = bits / 4; - if (bits % 4) { fill++; } - } - int len = strlen(str); - fill -= len; - if (fill > 0) { - memmove(str + fill, str, len +1); - memset(str, '0', fill); - } - return str; -} - -char* dtostrfd(double number, unsigned char prec, char *s) -{ - if ((isnan(number)) || (isinf(number))) { - strcpy(s, "null"); - return s; - } else { - return dtostrf(number, 1, prec, s); - } -} - -char* Unescape(char* buffer, uint32_t* size) -{ - uint8_t* read = (uint8_t*)buffer; - uint8_t* write = (uint8_t*)buffer; - int32_t start_size = *size; - int32_t end_size = *size; - uint8_t che = 0; - - - - while (start_size > 0) { - uint8_t ch = *read++; - start_size--; - if (ch != '\\') { - *write++ = ch; - } else { - if (start_size > 0) { - uint8_t chi = *read++; - start_size--; - end_size--; - switch (chi) { - case '\\': che = '\\'; break; - case 'a': che = '\a'; break; - case 'b': che = '\b'; break; - case 'e': che = '\e'; break; - case 'f': che = '\f'; break; - case 'n': che = '\n'; break; - case 'r': che = '\r'; break; - case 's': che = ' '; break; - case 't': che = '\t'; break; - case 'v': che = '\v'; break; - case 'x': { - uint8_t* start = read; - che = (uint8_t)strtol((const char*)read, (char**)&read, 16); - start_size -= (uint16_t)(read - start); - end_size -= (uint16_t)(read - start); - break; - } - case '"': che = '\"'; break; - - default : { - che = chi; - *write++ = ch; - end_size++; - } - } - *write++ = che; - } - } - } - *size = end_size; - *write++ = 0; - - - return buffer; -} - -char* RemoveSpace(char* p) -{ - char* write = p; - char* read = p; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - if (!isspace(ch)) { - *write++ = ch; - } - } - - return p; -} - -char* LowerCase(char* dest, const char* source) -{ - char* write = dest; - const char* read = source; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - *write++ = tolower(ch); - } - return dest; -} - -char* UpperCase(char* dest, const char* source) -{ - char* write = dest; - const char* read = source; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - *write++ = toupper(ch); - } - return dest; -} - -char* UpperCase_P(char* dest, const char* source) -{ - char* write = dest; - const char* read = source; - char ch = '.'; - - while (ch != '\0') { - ch = pgm_read_byte(read++); - *write++ = toupper(ch); - } - return dest; -} - -char* Trim(char* p) -{ - while ((*p != '\0') && isblank(*p)) { p++; } - char* q = p + strlen(p) -1; - while ((q >= p) && isblank(*q)) { q--; } - q++; - *q = '\0'; - return p; -} - -char* NoAlNumToUnderscore(char* dest, const char* source) -{ - char* write = dest; - const char* read = source; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - *write++ = (isalnum(ch) || ('\0' == ch)) ? ch : '_'; - } - return dest; -} - -char IndexSeparator() -{ - - - - - - - if (Settings.flag3.use_underscore) { - return '_'; - } else { - return '-'; - } -} - -void SetShortcutDefault(void) -{ - if ('\0' != XdrvMailbox.data[0]) { - XdrvMailbox.data[0] = '0' + SC_DEFAULT; - XdrvMailbox.data[1] = '\0'; - } -} - -uint8_t Shortcut() -{ - uint8_t result = 10; - - if ('\0' == XdrvMailbox.data[1]) { - if (('"' == XdrvMailbox.data[0]) || ('0' == XdrvMailbox.data[0])) { - result = SC_CLEAR; - } else { - result = atoi(XdrvMailbox.data); - if (0 == result) { - result = 10; - } - } - } - return result; -} - -bool ValidIpAddress(const char* str) -{ - const char* p = str; - - while (*p && ((*p == '.') || ((*p >= '0') && (*p <= '9')))) { p++; } - return (*p == '\0'); -} - -bool ParseIp(uint32_t* addr, const char* str) -{ - uint8_t *part = (uint8_t*)addr; - uint8_t i; - - *addr = 0; - for (i = 0; i < 4; i++) { - part[i] = strtoul(str, nullptr, 10); - str = strchr(str, '.'); - if (str == nullptr || *str == '\0') { - break; - } - str++; - } - return (3 == i); -} - - -bool NewerVersion(char* version_str) -{ - uint32_t version = 0; - uint32_t i = 0; - char *str_ptr; - char* version_dup = strdup(version_str); - - if (!version_dup) { - return false; - } - - for (char *str = strtok_r(version_dup, ".", &str_ptr); str && i < sizeof(VERSION); str = strtok_r(nullptr, ".", &str_ptr), i++) { - int field = atoi(str); - - if ((field < 0) || (field > 255)) { - free(version_dup); - return false; - } - - version = (version << 8) + field; - - if ((2 == i) && isalpha(str[strlen(str)-1])) { - field = str[strlen(str)-1] & 0x1f; - version = (version << 8) + field; - i++; - } - } - free(version_dup); - - - if ((i < 2) || (i > sizeof(VERSION))) { - return false; - } - - - while (i < sizeof(VERSION)) { - version <<= 8; - i++; - } - - return (version > VERSION); -} - -char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option) -{ - char sidx[8]; - - strncpy_P(dest, S_RSLT_POWER, size); - if ((devices_present + option) > 1) { - snprintf_P(sidx, sizeof(sidx), PSTR("%d"), idx); - strncat(dest, sidx, size - strlen(dest) -1); - } - return dest; -} - -char* GetPowerDevice(char* dest, uint32_t idx, size_t size) -{ - return GetPowerDevice(dest, idx, size, 0); -} - -float ConvertTemp(float c) -{ - float result = c; - - global_update = uptime; - global_temperature = c; - - if (!isnan(c) && Settings.flag.temperature_conversion) { - result = c * 1.8 + 32; - } - return result; -} - -float ConvertTempToCelsius(float c) -{ - float result = c; - - if (!isnan(c) && Settings.flag.temperature_conversion) { - result = (c - 32) / 1.8; - } - return result; -} - -char TempUnit(void) -{ - return (Settings.flag.temperature_conversion) ? 'F' : 'C'; -} - -float ConvertHumidity(float h) -{ - global_update = uptime; - global_humidity = h; - - return h; -} - -float ConvertPressure(float p) -{ - float result = p; - - global_update = uptime; - global_pressure = p; - - if (!isnan(p) && Settings.flag.pressure_conversion) { - result = p * 0.75006375541921; - } - return result; -} - -String PressureUnit(void) -{ - return (Settings.flag.pressure_conversion) ? String(D_UNIT_MILLIMETER_MERCURY) : String(D_UNIT_PRESSURE); -} - -void ResetGlobalValues(void) -{ - if ((uptime - global_update) > GLOBAL_VALUES_VALID) { - global_update = 0; - global_temperature = 9999; - global_humidity = 0; - global_pressure = 0; - } -} - -uint32_t SqrtInt(uint32_t num) -{ - if (num <= 1) { - return num; - } - - uint32_t x = num / 2; - uint32_t y; - do { - y = (x + num / x) / 2; - if (y >= x) { - return x; - } - x = y; - } while (true); -} - -uint32_t RoundSqrtInt(uint32_t num) -{ - uint32_t s = SqrtInt(4 * num); - if (s & 1) { - s++; - } - return s / 2; -} - -char* GetTextIndexed(char* destination, size_t destination_size, uint32_t index, const char* haystack) -{ - - - 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) -{ - - - int result = -1; - const char* read = haystack; - char* write = destination; - - 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; -} - -bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void)) -{ - GetTextIndexed(XdrvMailbox.command, CMDSZ, 0, haystack); - int prefix_length = strlen(XdrvMailbox.command); - int command_code = GetCommandCode(XdrvMailbox.command + prefix_length, CMDSZ, XdrvMailbox.topic + prefix_length, haystack); - if (command_code > 0) { - XdrvMailbox.command_code = command_code -1; - MyCommand[XdrvMailbox.command_code](); - return true; - } - return false; -} - -const char kOptions[] PROGMEM = "OFF|" D_OFF "|" D_FALSE "|" D_STOP "|" D_CELSIUS "|" - "ON|" D_ON "|" D_TRUE "|" D_START "|" D_FAHRENHEIT "|" D_USER "|" - "TOGGLE|" D_TOGGLE "|" D_ADMIN "|" - "BLINK|" D_BLINK "|" - "BLINKOFF|" D_BLINKOFF "|" - "ALL" ; - -const uint8_t sNumbers[] PROGMEM = { 0,0,0,0,0, - 1,1,1,1,1,1, - 2,2,2, - 3,3, - 4,4, - 255 }; - -int GetStateNumber(char *state_text) -{ - char command[CMDSZ]; - int state_number = GetCommandCode(command, sizeof(command), state_text, kOptions); - if (state_number >= 0) { - state_number = pgm_read_byte(sNumbers + state_number); - } - return state_number; -} - -void SetSerialBaudrate(int baudrate) -{ - Settings.baudrate = baudrate / 300; - if (Serial.baudRate() != baudrate) { - if (seriallog_level) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SET_BAUDRATE_TO " %d"), baudrate); - } - delay(100); - Serial.flush(); - Serial.begin(baudrate, serial_config); - delay(10); - Serial.println(); - } -} - -void ClaimSerial(void) -{ - serial_local = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("SNS: Hardware Serial")); - SetSeriallog(LOG_LEVEL_NONE); - baudrate = Serial.baudRate(); - Settings.baudrate = baudrate / 300; -} - -void SerialSendRaw(char *codes) -{ - char *p; - char stemp[3]; - uint8_t code; - - int size = strlen(codes); - - while (size > 0) { - strlcpy(stemp, codes, sizeof(stemp)); - code = strtol(stemp, &p, 16); - Serial.write(code); - size -= 2; - codes += 2; - } -} - -uint32_t GetHash(const char *buffer, size_t size) -{ - uint32_t hash = 0; - for (uint32_t i = 0; i <= size; i++) { - hash += (uint8_t)*buffer++ * (i +1); - } - return hash; -} - -void ShowSource(uint32_t source) -{ - if ((source > 0) && (source < SRC_MAX)) { - char stemp1[20]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SRC: %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource)); - } -} - -void WebHexCode(uint32_t i, const char* code) -{ - char scolor[10]; - - strlcpy(scolor, code, sizeof(scolor)); - char* p = scolor; - if ('#' == p[0]) { p++; } - - if (3 == strlen(p)) { - p[6] = p[3]; - p[5] = p[2]; - p[4] = p[2]; - p[3] = p[1]; - p[2] = p[1]; - p[1] = p[0]; - } - - uint32_t color = strtol(p, nullptr, 16); - - - - - - - - Settings.web_color[i][0] = (color >> 16) & 0xFF; - Settings.web_color[i][1] = (color >> 8) & 0xFF; - Settings.web_color[i][2] = color & 0xFF; -} - -uint32_t WebColor(uint32_t i) -{ - uint32_t tcolor = (Settings.web_color[i][0] << 16) | (Settings.web_color[i][1] << 8) | Settings.web_color[i][2]; - return tcolor; -} - - - - - -const uint16_t TIMESZ = 100; - -char* ResponseGetTime(uint32_t format, char* time_str) -{ - switch (format) { - case 1: - snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%u"), GetDateAndTime(DT_LOCAL).c_str(), UtcTime()); - break; - case 2: - snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":%u"), UtcTime()); - break; - default: - snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - } - return time_str; -} - -int Response_P(const char* format, ...) -{ - - va_list args; - va_start(args, format); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), format, args); - va_end(args); - return len; -} - -int ResponseTime_P(const char* format, ...) -{ - - va_list args; - va_start(args, format); - - ResponseGetTime(Settings.flag2.time_format, mqtt_data); - - int mlen = strlen(mqtt_data); - int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); - va_end(args); - return len + mlen; -} - -int ResponseAppend_P(const char* format, ...) -{ - - va_list args; - va_start(args, format); - int mlen = strlen(mqtt_data); - int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); - va_end(args); - return len + mlen; -} - -int ResponseAppendTimeFormat(uint32_t format) -{ - char time_str[TIMESZ]; - return ResponseAppend_P(ResponseGetTime(format, time_str)); -} - -int ResponseAppendTime(void) -{ - return ResponseAppendTimeFormat(Settings.flag2.time_format); -} - -int ResponseJsonEnd(void) -{ - return ResponseAppend_P(PSTR("}")); -} - -int ResponseJsonEndEnd(void) -{ - return ResponseAppend_P(PSTR("}}")); -} - - - - - -uint8_t ModuleNr() -{ - - - return (USER_MODULE == Settings.module) ? 0 : Settings.module +1; -} - -bool ValidTemplateModule(uint32_t index) -{ - for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { - if (index == pgm_read_byte(kModuleNiceList + i)) { - return true; - } - } - return false; -} - -bool ValidModule(uint32_t index) -{ - if (index == USER_MODULE) { return true; } - return ValidTemplateModule(index); -} - -String AnyModuleName(uint32_t index) -{ - if (USER_MODULE == index) { - return String(Settings.user_template.name); - } else { - return FPSTR(kModules[index].name); - } -} - -String ModuleName() -{ - return AnyModuleName(Settings.module); -} - -void ModuleGpios(myio *gp) -{ - uint8_t *dest = (uint8_t *)gp; - memset(dest, GPIO_NONE, sizeof(myio)); - - uint8_t src[sizeof(mycfgio)]; - if (USER_MODULE == Settings.module) { - memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio)); - } else { - memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio)); - } - - - - - uint32_t j = 0; - for (uint32_t i = 0; i < sizeof(mycfgio); i++) { - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - dest[j] = src[i]; - j++; - } - - - -} - -gpio_flag ModuleFlag() -{ - gpio_flag flag; - - if (USER_MODULE == Settings.module) { - flag = Settings.user_template.flag; - } else { - memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag)); - } - - return flag; -} - -void ModuleDefault(uint32_t module) -{ - if (USER_MODULE == module) { module = WEMOS; } - Settings.user_template_base = module; - memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt)); -} - -void SetModuleType() -{ - my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module; -} - -uint8_t ValidPin(uint32_t pin, uint32_t gpio) -{ - uint8_t result = gpio; - - if (((pin > 5) && (pin < 9)) || (11 == pin)) { - result = GPIO_NONE; - } - if ((WEMOS == Settings.module) && (!Settings.flag3.user_esp8285_enable)) { - if ((pin == 9) || (pin == 10)) { result = GPIO_NONE; } - } - return result; -} - -bool ValidGPIO(uint32_t pin, uint32_t gpio) -{ - return (GPIO_USER == ValidPin(pin, gpio)); -} - -bool ValidAdc() -{ - gpio_flag flag = ModuleFlag(); - uint32_t template_adc0 = flag.data &15; - return (ADC0_USER == template_adc0); -} - -bool GetUsedInModule(uint32_t val, uint8_t *arr) -{ - int offset = 0; - - if (!val) { return false; } - - if ((val >= GPIO_KEY1) && (val < GPIO_KEY1 + MAX_KEYS)) { - offset = (GPIO_KEY1_NP - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) { - offset = -(GPIO_KEY1_NP - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_INV) && (val < GPIO_KEY1_INV + MAX_KEYS)) { - offset = -(GPIO_KEY1_INV - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_INV_NP) && (val < GPIO_KEY1_INV_NP + MAX_KEYS)) { - offset = -(GPIO_KEY1_INV_NP - GPIO_KEY1); - } - - if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) { - offset = (GPIO_SWT1_NP - GPIO_SWT1); - } - if ((val >= GPIO_SWT1_NP) && (val < GPIO_SWT1_NP + MAX_SWITCHES)) { - offset = -(GPIO_SWT1_NP - GPIO_SWT1); - } - - if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { - offset = (GPIO_REL1_INV - GPIO_REL1); - } - if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) { - offset = -(GPIO_REL1_INV - GPIO_REL1); - } - - if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) { - offset = (GPIO_LED1_INV - GPIO_LED1); - } - if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) { - offset = -(GPIO_LED1_INV - GPIO_LED1); - } - - if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) { - offset = (GPIO_PWM1_INV - GPIO_PWM1); - } - if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) { - offset = -(GPIO_PWM1_INV - GPIO_PWM1); - } - - if ((val >= GPIO_CNTR1) && (val < GPIO_CNTR1 + MAX_COUNTERS)) { - offset = (GPIO_CNTR1_NP - GPIO_CNTR1); - } - if ((val >= GPIO_CNTR1_NP) && (val < GPIO_CNTR1_NP + MAX_COUNTERS)) { - offset = -(GPIO_CNTR1_NP - GPIO_CNTR1); - } - - for (uint32_t i = 0; i < MAX_GPIO_PIN; i++) { - if (arr[i] == val) { return true; } - if (arr[i] == val + offset) { return true; } - } - return false; -} - -bool JsonTemplate(const char* dataBuf) -{ - - - if (strlen(dataBuf) < 9) { return false; } - - StaticJsonBuffer<350> jb; - JsonObject& obj = jb.parseObject(dataBuf); - if (!obj.success()) { return false; } - - - const char* name = obj[D_JSON_NAME]; - if (name != nullptr) { - strlcpy(Settings.user_template.name, name, sizeof(Settings.user_template.name)); - } - if (obj[D_JSON_GPIO].success()) { - for (uint32_t i = 0; i < sizeof(mycfgio); i++) { - Settings.user_template.gp.io[i] = obj[D_JSON_GPIO][i] | 0; - } - } - if (obj[D_JSON_FLAG].success()) { - uint8_t flag = obj[D_JSON_FLAG] | 0; - memcpy(&Settings.user_template.flag, &flag, sizeof(gpio_flag)); - } - if (obj[D_JSON_BASE].success()) { - uint8_t base = obj[D_JSON_BASE]; - if ((0 == base) || !ValidTemplateModule(base -1)) { base = 18; } - Settings.user_template_base = base -1; - } - return true; -} - -void TemplateJson() -{ - Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); - for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", Settings.user_template.gp.io[i]); - } - ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1); -} - - - - - -long TimeDifference(unsigned long prev, unsigned long next) -{ - - - - long signed_diff = 0; - - const unsigned long half_max_unsigned_long = 2147483647u; - if (next >= prev) { - const unsigned long diff = next - prev; - if (diff <= half_max_unsigned_long) { - signed_diff = static_cast(diff); - } else { - - signed_diff = static_cast((0xffffffffUL - next) + prev + 1u); - signed_diff = -1 * signed_diff; - } - } else { - - const unsigned long diff = prev - next; - if (diff <= half_max_unsigned_long) { - signed_diff = static_cast(diff); - signed_diff = -1 * signed_diff; - } else { - - signed_diff = static_cast((0xffffffffUL - prev) + next + 1u); - } - } - return signed_diff; -} - -long TimePassedSince(unsigned long timestamp) -{ - - - return TimeDifference(timestamp, millis()); -} - -bool TimeReached(unsigned long timer) -{ - - const long passed = TimePassedSince(timer); - return (passed >= 0); -} - -void SetNextTimeInterval(unsigned long& timer, const unsigned long step) -{ - timer += step; - const long passed = TimePassedSince(timer); - if (passed < 0) { return; } - if (static_cast(passed) > step) { - - timer = millis() + step; - return; - } - - timer = millis() + (step - passed); -} - - - - - -#ifdef USE_I2C -const uint8_t I2C_RETRY_COUNTER = 3; - -uint32_t i2c_buffer = 0; - -bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size) -{ - uint8_t retry = I2C_RETRY_COUNTER; - bool status = false; - - i2c_buffer = 0; - while (!status && retry) { - Wire.beginTransmission(addr); - Wire.write(reg); - if (0 == Wire.endTransmission(false)) { - Wire.requestFrom((int)addr, (int)size); - if (Wire.available() == size) { - for (uint32_t i = 0; i < size; i++) { - i2c_buffer = i2c_buffer << 8 | Wire.read(); - } - status = true; - } - } - retry--; - } - return status; -} - -bool I2cValidRead8(uint8_t *data, uint8_t addr, uint8_t reg) -{ - bool status = I2cValidRead(addr, reg, 1); - *data = (uint8_t)i2c_buffer; - return status; -} - -bool I2cValidRead16(uint16_t *data, uint8_t addr, uint8_t reg) -{ - bool status = I2cValidRead(addr, reg, 2); - *data = (uint16_t)i2c_buffer; - return status; -} - -bool I2cValidReadS16(int16_t *data, uint8_t addr, uint8_t reg) -{ - bool status = I2cValidRead(addr, reg, 2); - *data = (int16_t)i2c_buffer; - return status; -} - -bool I2cValidRead16LE(uint16_t *data, uint8_t addr, uint8_t reg) -{ - uint16_t ldata; - bool status = I2cValidRead16(&ldata, addr, reg); - *data = (ldata >> 8) | (ldata << 8); - return status; -} - -bool I2cValidReadS16_LE(int16_t *data, uint8_t addr, uint8_t reg) -{ - uint16_t ldata; - bool status = I2cValidRead16LE(&ldata, addr, reg); - *data = (int16_t)ldata; - return status; -} - -bool I2cValidRead24(int32_t *data, uint8_t addr, uint8_t reg) -{ - bool status = I2cValidRead(addr, reg, 3); - *data = i2c_buffer; - return status; -} - -uint8_t I2cRead8(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 1); - return (uint8_t)i2c_buffer; -} - -uint16_t I2cRead16(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 2); - return (uint16_t)i2c_buffer; -} - -int16_t I2cReadS16(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 2); - return (int16_t)i2c_buffer; -} - -uint16_t I2cRead16LE(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 2); - uint16_t temp = (uint16_t)i2c_buffer; - return (temp >> 8) | (temp << 8); -} - -int16_t I2cReadS16_LE(uint8_t addr, uint8_t reg) -{ - return (int16_t)I2cRead16LE(addr, reg); -} - -int32_t I2cRead24(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 3); - return i2c_buffer; -} - -bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size) -{ - uint8_t x = I2C_RETRY_COUNTER; - - do { - Wire.beginTransmission((uint8_t)addr); - Wire.write(reg); - uint8_t bytes = size; - while (bytes--) { - Wire.write((val >> (8 * bytes)) & 0xFF); - } - x--; - } while (Wire.endTransmission(true) != 0 && x != 0); - return (x); -} - -bool I2cWrite8(uint8_t addr, uint8_t reg, uint16_t val) -{ - return I2cWrite(addr, reg, val, 1); -} - -bool I2cWrite16(uint8_t addr, uint8_t reg, uint16_t val) -{ - return I2cWrite(addr, reg, val, 2); -} - -int8_t I2cReadBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len) -{ - Wire.beginTransmission((uint8_t)addr); - Wire.write((uint8_t)reg); - Wire.endTransmission(); - if (len != Wire.requestFrom((uint8_t)addr, (uint8_t)len)) { - return 1; - } - while (len--) { - *reg_data = (uint8_t)Wire.read(); - reg_data++; - } - return 0; -} - -int8_t I2cWriteBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len) -{ - Wire.beginTransmission((uint8_t)addr); - Wire.write((uint8_t)reg); - while (len--) { - Wire.write(*reg_data); - reg_data++; - } - Wire.endTransmission(); - return 0; -} - -void I2cScan(char *devs, unsigned int devs_len) -{ - - - - - - - - uint8_t error = 0; - uint8_t address = 0; - uint8_t any = 0; - - snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_DEVICES_FOUND_AT)); - for (address = 1; address <= 127; address++) { - Wire.beginTransmission(address); - error = Wire.endTransmission(); - if (0 == error) { - any = 1; - snprintf_P(devs, devs_len, PSTR("%s 0x%02x"), devs, address); - } - else if (error != 2) { - any = 2; - snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"Error %d at 0x%02x"), error, address); - break; - } - } - if (any) { - strncat(devs, "\"}", devs_len - strlen(devs) -1); - } - else { - snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_NO_DEVICES_FOUND "\"}")); - } -} - -bool I2cDevice(uint8_t addr) -{ - for (uint8_t address = 1; address <= 127; address++) { - Wire.beginTransmission(address); - if (!Wire.endTransmission() && (address == addr)) { - return true; - } - } - return false; -} -#endif -# 1480 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support.ino" -void SetSeriallog(uint32_t loglevel) -{ - Settings.seriallog_level = loglevel; - seriallog_level = loglevel; - seriallog_timer = 0; -} - -void SetSyslog(uint32_t loglevel) -{ - Settings.syslog_level = loglevel; - syslog_level = loglevel; - syslog_timer = 0; -} - -#ifdef USE_WEBSERVER -void GetLog(uint32_t idx, char** entry_pp, size_t* len_p) -{ - char* entry_p = nullptr; - size_t len = 0; - - if (idx) { - char* it = web_log; - do { - uint32_t cur_idx = *it; - it++; - size_t tmp = strchrspn(it, '\1'); - tmp++; - if (cur_idx == idx) { - len = tmp; - entry_p = it; - break; - } - it += tmp; - } while (it < web_log + WEB_LOG_SIZE && *it != '\0'); - } - *entry_pp = entry_p; - *len_p = len; -} -#endif - -void Syslog(void) -{ - - char syslog_preamble[64]; - - uint32_t current_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); - if (syslog_host_hash != current_hash) { - syslog_host_hash = current_hash; - WiFi.hostByName(Settings.syslog_host, syslog_host_addr); - } - 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, strlen(log_data)); - PortUdp.endPacket(); - delay(1); - } else { - syslog_level = 0; - syslog_timer = SYSLOG_TIMER; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_HOST_NOT_FOUND ". " D_RETRY_IN " %d " D_UNIT_SECOND), SYSLOG_TIMER); - } -} - -void AddLog(uint32_t loglevel) -{ - char mxtime[10]; - - 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\r\n", mxtime, log_data); - } -#ifdef USE_WEBSERVER - if (Settings.webserver && (loglevel <= Settings.weblog_level)) { - - - web_log_index &= 0xFF; - if (!web_log_index) web_log_index++; - while (web_log_index == web_log[0] || - strlen(web_log) + strlen(log_data) + 13 > WEB_LOG_SIZE) - { - char* it = web_log; - it++; - it += strchrspn(it, '\1'); - it++; - memmove(web_log, it, WEB_LOG_SIZE -(it-web_log)); - } - snprintf_P(web_log, sizeof(web_log), PSTR("%s%c%s%s\1"), web_log, web_log_index++, mxtime, log_data); - web_log_index &= 0xFF; - if (!web_log_index) web_log_index++; - } -#endif - if (!global_state.wifi_down && (loglevel <= syslog_level)) { Syslog(); } -} - -void AddLog_P(uint32_t loglevel, const char *formatP) -{ - snprintf_P(log_data, sizeof(log_data), formatP); - AddLog(loglevel); -} - -void AddLog_P(uint32_t loglevel, const char *formatP, const char *formatP2) -{ - char message[sizeof(log_data)]; - - snprintf_P(log_data, sizeof(log_data), formatP); - snprintf_P(message, sizeof(message), formatP2); - strncat(log_data, message, sizeof(log_data) - strlen(log_data) -1); - AddLog(loglevel); -} - -void AddLog_P2(uint32_t loglevel, PGM_P formatP, ...) -{ - va_list arg; - va_start(arg, formatP); - vsnprintf_P(log_data, sizeof(log_data), formatP, arg); - va_end(arg); - - AddLog(loglevel); -} - -void AddLog_Debug(PGM_P formatP, ...) -{ - va_list arg; - va_start(arg, formatP); - vsnprintf_P(log_data, sizeof(log_data), formatP, arg); - va_end(arg); - - AddLog(LOG_LEVEL_DEBUG); -} - -void AddLogBuffer(uint32_t loglevel, uint8_t *buffer, uint32_t count) -{ -# 1627 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support.ino" - char hex_char[(count * 3) + 2]; - AddLog_P2(loglevel, PSTR("DMP: %s"), ToHex_P(buffer, count, hex_char, sizeof(hex_char), ' ')); -} - -void AddLogSerial(uint32_t loglevel) -{ - AddLogBuffer(loglevel, (uint8_t*)serial_in_buffer, serial_in_byte_counter); -} - -void AddLogMissed(char *sensor, uint32_t misses) -{ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses); -} -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_button.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_button.ino" -#define BUTTON_V1 -#ifdef BUTTON_V1 - - - - -struct BUTTON { - unsigned long debounce = 0; - uint16_t hold_timer[MAX_KEYS] = { 0 }; - uint16_t dual_code = 0; - - uint8_t last_state[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; - uint8_t window_timer[MAX_KEYS] = { 0 }; - uint8_t press_counter[MAX_KEYS] = { 0 }; - - uint8_t dual_receive_count = 0; - uint8_t no_pullup_mask = 0; - uint8_t inverted_mask = 0; - uint8_t present = 0; - uint8_t adc = 99; -} Button; - - - -void ButtonPullupFlag(uint8 button_bit) -{ - bitSet(Button.no_pullup_mask, button_bit); -} - -void ButtonInvertFlag(uint8 button_bit) -{ - bitSet(Button.inverted_mask, button_bit); -} - -void ButtonInit(void) -{ - Button.present = 0; - for (uint32_t i = 0; i < MAX_KEYS; i++) { - if (pin[GPIO_KEY1 +i] < 99) { - Button.present++; - pinMode(pin[GPIO_KEY1 +i], bitRead(Button.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); - } -#ifndef USE_ADC_VCC - else if ((99 == Button.adc) && ((ADC0_BUTTON == my_adc0) || (ADC0_BUTTON_INV == my_adc0))) { - Button.present++; - Button.adc = i; - } -#endif - } -} - -uint8_t ButtonSerial(uint8_t serial_in_byte) -{ - if (Button.dual_receive_count) { - Button.dual_receive_count--; - if (Button.dual_receive_count) { - Button.dual_code = (Button.dual_code << 8) | serial_in_byte; - serial_in_byte = 0; - } else { - if (serial_in_byte != 0xA1) { - Button.dual_code = 0; - } - } - } - if (0xA0 == serial_in_byte) { - serial_in_byte = 0; - Button.dual_code = 0; - Button.dual_receive_count = 3; - } - - return serial_in_byte; -} -# 104 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_button.ino" -void ButtonHandler(void) -{ - if (uptime < 4) { return; } - - uint8_t button = NOT_PRESSED; - uint8_t button_present = 0; - uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; - uint16_t loops_per_second = 1000 / Settings.button_debounce; - char scmnd[20]; - - - - for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { - button = NOT_PRESSED; - button_present = 0; - - if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { - button_present = 1; - if (Button.dual_code) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), Button.dual_code); - button = PRESSED; - if (0xF500 == Button.dual_code) { - Button.hold_timer[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; - hold_time_extent = 1; - } - Button.dual_code = 0; - } - } - else if (pin[GPIO_KEY1 +button_index] < 99) { - button_present = 1; - button = (digitalRead(pin[GPIO_KEY1 +button_index]) != bitRead(Button.inverted_mask, button_index)); - } -#ifndef USE_ADC_VCC - if (Button.adc == button_index) { - button_present = 1; - if (ADC0_BUTTON_INV == my_adc0) { - button = (AdcRead(1) < 128); - } - else if (ADC0_BUTTON == my_adc0) { - button = (AdcRead(1) > 128); - } - } -#endif - - if (button_present) { - XdrvMailbox.index = button_index; - XdrvMailbox.payload = button; - if (XdrvCall(FUNC_BUTTON_PRESSED)) { - - } - else if (SONOFF_4CHPRO == my_module_type) { - if (Button.hold_timer[button_index]) { Button.hold_timer[button_index]--; } - - bool button_pressed = false; - if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); - Button.hold_timer[button_index] = loops_per_second; - button_pressed = true; - } - if ((NOT_PRESSED == button) && (PRESSED == Button.last_state[button_index])) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_01), button_index +1); - if (!Button.hold_timer[button_index]) { button_pressed = true; } - } - if (button_pressed) { - if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { - ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); - } - } - } - else { - if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { - if (Settings.flag.button_single) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1); - if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { - ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); - } - } else { - Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, Button.press_counter[button_index]); - Button.window_timer[button_index] = loops_per_second / 2; - } - blinks = 201; - } - - if (NOT_PRESSED == button) { - Button.hold_timer[button_index] = 0; - } else { - Button.hold_timer[button_index]++; - if (Settings.flag.button_single) { - if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { - - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } else { - if (Settings.flag.button_restrict) { - if (Settings.param[P_HOLD_IGNORE] > 0) { - if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) { - Button.hold_timer[button_index] = 0; - Button.press_counter[button_index] = 0; - DEBUG_CORE_LOG(PSTR("BTN: " D_BUTTON "%d cancel by " D_CMND_SETOPTION "40 %d"), button_index +1, Settings.param[P_HOLD_IGNORE]); - } - } - if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { - Button.press_counter[button_index] = 0; - SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); - } - } else { - if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { - Button.press_counter[button_index] = 0; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - } - } - - if (!Settings.flag.button_single) { - if (Button.window_timer[button_index]) { - Button.window_timer[button_index]--; - } else { - if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS +3)) { - bool single_press = false; - if (Button.press_counter[button_index] < 3) { - if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - single_press = true; - } else { - single_press = (Settings.flag.button_swap +1 == Button.press_counter[button_index]); - if ((1 == Button.present) && (2 == devices_present)) { - if (Settings.flag.button_swap) { - Button.press_counter[button_index] = (single_press) ? 1 : 2; - } - } else { - Button.press_counter[button_index] = 1; - } - } - } -#if defined(USE_LIGHT) && defined(ROTARY_V1) - if (!((0 == button_index) && RotaryButtonPressed())) { -#endif - if (single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { - - } else { - if (Button.press_counter[button_index] < 3) { - if (WifiState() > WIFI_RESTART) { - restart_flag = 1; - } else { - ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); - } - } else { - if (!Settings.flag.button_restrict) { - snprintf_P(scmnd, sizeof(scmnd), kCommands[Button.press_counter[button_index] -3]); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - } -#if defined(USE_LIGHT) && defined(ROTARY_V1) - } -#endif - Button.press_counter[button_index] = 0; - } - } - } - } - } - Button.last_state[button_index] = button; - } -} - -void ButtonLoop(void) -{ - if (Button.present) { - if (TimeReached(Button.debounce)) { - SetNextTimeInterval(Button.debounce, Settings.button_debounce); - ButtonHandler(); - } - } -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_command.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_command.ino" -const char kTasmotaCommands[] PROGMEM = "|" - D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_SLEEP "|" D_CMND_UPGRADE "|" D_CMND_UPLOAD "|" D_CMND_OTAURL "|" - D_CMND_SERIALLOG "|" D_CMND_RESTART "|" 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_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|" - D_CMND_MODULE "|" D_CMND_MODULES "|" D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_TEMPLATE "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" - D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" - D_CMND_SERIALDELIMITER "|" 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_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" - D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" -#ifdef USE_I2C - D_CMND_I2CSCAN "|" -#endif - D_CMND_SENSOR "|" D_CMND_DRIVER; - -void (* const TasmotaCommand[])(void) PROGMEM = { - &CmndBacklog, &CmndDelay, &CmndPower, &CmndStatus, &CmndState, &CmndSleep, &CmndUpgrade, &CmndUpgrade, &CmndOtaUrl, - &CmndSeriallog, &CmndRestart, &CmndPowerOnState, &CmndPulsetime, &CmndBlinktime, &CmndBlinkcount, &CmndSavedata, - &CmndSetoption, &CmndTemperatureResolution, &CmndHumidityResolution, &CmndPressureResolution, &CmndPowerResolution, - &CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution, - &CmndModule, &CmndModules, &CmndGpio, &CmndGpios, &CmndTemplate, &CmndPwm, &CmndPwmfrequency, &CmndPwmrange, - &CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndBaudrate, - &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, - &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, - &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, -#ifdef USE_I2C - &CmndI2cScan, -#endif - &CmndSensor, &CmndDriver }; - - - -void ResponseCmndNumber(int value) -{ - Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, value); -} - -void ResponseCmndIdxNumber(int value) -{ - Response_P(S_JSON_COMMAND_INDEX_NVALUE, XdrvMailbox.command, XdrvMailbox.index, value); -} - -void ResponseCmndChar(const char* value) -{ - Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, value); -} - -void ResponseCmndStateText(uint32_t value) -{ - ResponseCmndChar(GetStateText(value)); -} - -void ResponseCmndDone(void) -{ - ResponseCmndChar(D_JSON_DONE); -} - -void ResponseCmndIdxChar(const char* value) -{ - Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, XdrvMailbox.index, value); -} - - - -void ExecuteCommand(char *cmnd, uint32_t source) -{ - char *start; - char *token; - -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("ExecuteCommand")); -#endif - ShowSource(source); - - token = strtok(cmnd, " "); - if (token != nullptr) { - start = strrchr(token, '/'); - if (start) { token = start +1; } - } - uint32_t size = (token != nullptr) ? strlen(token) : 0; - char stopic[size +2]; - snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == nullptr) ? "" : token); - - token = strtok(nullptr, ""); - size = (token != nullptr) ? strlen(token) : 0; - char svalue[size +1]; - strlcpy(svalue, (token == nullptr) ? "" : token, sizeof(svalue)); - CommandHandler(stopic, (uint8_t*)svalue, strlen(svalue)); -} -# 117 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_command.ino" -void CommandHandler(char* topic, uint8_t* data, uint32_t data_len) -{ -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("CommandHandler")); -#endif - - char topicBuf[TOPSZ]; - strlcpy(topicBuf, topic, sizeof(topicBuf)); - - uint32_t i = 0; - for (i = 0; i < data_len; i++) { - if (!isspace(data[i])) { break; } - } - data_len -= i; - char dataBuf[data_len+1]; - memcpy(dataBuf, data +i, sizeof(dataBuf)); - - bool grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != nullptr); - - char stemp1[TOPSZ]; - GetFallbackTopic_P(stemp1, CMND, ""); - fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); - - char *type = strrchr(topicBuf, '/'); - - uint32_t index = 1; - bool user_index = false; - if (type != nullptr) { - type++; - for (i = 0; i < strlen(type); i++) { - type[i] = toupper(type[i]); - } - while (isdigit(type[i-1])) { - i--; - } - if (i < strlen(type)) { - index = atoi(type +i); - user_index = true; - } - type[i] = '\0'; - } - - DEBUG_CORE_LOG(PSTR("CMD: " D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " \"%s\", " D_DATA " \"%s\""), grpflg, index, type, dataBuf); - - if (type != nullptr) { - Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); - - if (Settings.ledstate &0x02) { blinks++; } - - if (!strcmp(dataBuf,"?")) { data_len = 0; } - - char *p; - int32_t payload = strtol(dataBuf, &p, 0); - if (p == dataBuf) { payload = -99; } - int temp_payload = GetStateNumber(dataBuf); - if (temp_payload > -1) { payload = temp_payload; } - - DEBUG_CORE_LOG(PSTR("CMD: Payload %d"), payload); - - backlog_delay = millis() + (100 * MIN_BACKLOG_DELAY); - - char command[CMDSZ]; - XdrvMailbox.command = command; - XdrvMailbox.index = index; - XdrvMailbox.data_len = data_len; - XdrvMailbox.payload = payload; - XdrvMailbox.grpflg = grpflg; - XdrvMailbox.usridx = user_index; - XdrvMailbox.topic = type; - XdrvMailbox.data = dataBuf; - - if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { - if (!XdrvCall(FUNC_COMMAND)) { - if (!XsnsCall(FUNC_COMMAND)) { - type = nullptr; - } - } - } - } - - if (type == nullptr) { - blinks = 201; - snprintf_P(topicBuf, sizeof(topicBuf), PSTR(D_JSON_COMMAND)); - Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); - type = (char*)topicBuf; - } - - if (mqtt_data[0] != '\0') { - MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); -#ifdef USE_SCRIPT - XdrvRulesProcess(); -#endif - } - fallback_topic_flag = false; -} - - - -void CmndBacklog(void) -{ - if (XdrvMailbox.data_len) { - -#ifdef SUPPORT_IF_STATEMENT - char *blcommand = strtok(XdrvMailbox.data, ";"); - while ((blcommand != nullptr) && (backlog.size() < MAX_BACKLOG)) -#else - uint32_t bl_pointer = (!backlog_pointer) ? MAX_BACKLOG -1 : backlog_pointer; - bl_pointer--; - char *blcommand = strtok(XdrvMailbox.data, ";"); - while ((blcommand != nullptr) && (backlog_index != bl_pointer)) -#endif - { - while(true) { - blcommand = Trim(blcommand); - if (!strncasecmp_P(blcommand, PSTR(D_CMND_BACKLOG), strlen(D_CMND_BACKLOG))) { - blcommand += strlen(D_CMND_BACKLOG); - } else { - break; - } - } - if (*blcommand != '\0') { -#ifdef SUPPORT_IF_STATEMENT - if (backlog.size() < MAX_BACKLOG) { - backlog.add(blcommand); - } -#else - backlog[backlog_index] = String(blcommand); - backlog_index++; - if (backlog_index >= MAX_BACKLOG) backlog_index = 0; -#endif - } - blcommand = strtok(nullptr, ";"); - } - - mqtt_data[0] = '\0'; - } else { - bool blflag = BACKLOG_EMPTY; -#ifdef SUPPORT_IF_STATEMENT - backlog.clear(); -#else - backlog_pointer = backlog_index; -#endif - ResponseCmndChar(blflag ? D_JSON_EMPTY : D_JSON_ABORTED); - } -} - -void CmndDelay(void) -{ - if ((XdrvMailbox.payload >= MIN_BACKLOG_DELAY) && (XdrvMailbox.payload <= 3600)) { - backlog_delay = millis() + (100 * XdrvMailbox.payload); - } - uint32_t bl_delay = 0; - long bl_delta = TimePassedSince(backlog_delay); - if (bl_delta < 0) { bl_delay = (bl_delta *-1) / 100; } - ResponseCmndNumber(bl_delay); -} - -void CmndPower(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= devices_present)) { - if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_BLINK_STOP)) { - XdrvMailbox.payload = POWER_SHOW_STATE; - } - - ExecuteCommandPower(XdrvMailbox.index, XdrvMailbox.payload, SRC_IGNORE); - mqtt_data[0] = '\0'; - } - else if (0 == XdrvMailbox.index) { - if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_TOGGLE)) { - XdrvMailbox.payload = POWER_SHOW_STATE; - } - SetAllPower(XdrvMailbox.payload, SRC_IGNORE); - mqtt_data[0] = '\0'; - } -} - -void CmndStatus(void) -{ - uint32_t payload = ((XdrvMailbox.payload < 0) || (XdrvMailbox.payload > MAX_STATUS)) ? 99 : XdrvMailbox.payload; - - uint32_t option = STAT; - char stemp[MAX_FRIENDLYNAMES * (sizeof(Settings.friendlyname[0]) +MAX_FRIENDLYNAMES)]; - char stemp2[100]; - - - if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) { option++; } - - if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } - if (!energy_flg && (9 == payload)) { payload = 99; } - - if ((0 == payload) || (99 == payload)) { - uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { maxfn = 1; } -#endif - stemp[0] = '\0'; - for (uint32_t i = 0; i < maxfn; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%s%s\"%s\"" ), stemp, (i > 0 ? "," : ""), Settings.friendlyname[i]); - } - stemp2[0] = '\0'; - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%d" ), stemp2, (i > 0 ? "," : ""), Settings.switchmode[i]); - } - Response_P(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_LEDMASK "\":\"%04X\",\"" D_CMND_SAVEDATA "\":%d,\"" D_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" - D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), - ModuleNr(), stemp, mqtt_topic, - Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, - Settings.ledmask, Settings.save_data, Settings.flag.save_state, Settings.switch_topic, - stemp2, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_switch_retain, Settings.flag.mqtt_sensor_retain, Settings.flag.mqtt_power_retain); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS)); - } - - if ((0 == payload) || (1 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" - D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" - D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), - baudrate, Settings.mqtt_grptopic, Settings.ota_url, - GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, - Settings.cfg_holder, Settings.bootcount, Settings.save_flag, GetSettingsAddress()); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); - } - - if ((0 == payload) || (2 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" - D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"}}"), - my_version, my_image, GetBuildDateAndTime().c_str(), - ESP.getBootVersion(), ESP.getSdkVersion()); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); - } - - if ((0 == payload) || (3 == payload)) { - Response_P(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 "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" - D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\"]}}"), - 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.flag2.data, Settings.flag.data, ToHex_P((unsigned char*)Settings.param, PARAM8_SIZE, stemp2, sizeof(stemp2)), Settings.flag3.data); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "3")); - } - - if ((0 == payload) || (4 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" - D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\"" - D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"), - ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, - ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipId(), ESP.getFlashChipMode(), - LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5); - XsnsDriverState(); - ResponseAppend_P(PSTR(",\"Sensors\":")); - XsnsSensorState(); - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "4")); - } - - if ((0 == payload) || (5 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_GATEWAY "\":\"%s\",\"" - D_JSON_SUBNETMASK "\":\"%s\",\"" D_JSON_DNSSERVER "\":\"%s\",\"" D_JSON_MAC "\":\"%s\",\"" - D_CMND_WEBSERVER "\":%d,\"" D_CMND_WIFICONFIG "\":%d}}"), - 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)) && Settings.flag.mqtt_enabled) { -#ifdef USE_MQTT_AWS_IOT - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" - D_CMND_MQTTCLIENT "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), - Settings.mqtt_user, Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, - mqtt_client, MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); -#else - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" - D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), - Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, - mqtt_client, Settings.mqtt_user, MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); -#endif - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6")); - } - - if ((0 == payload) || (7 == payload)) { - if (99 == Settings.timezone) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d" ), Settings.timezone); - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"%s\"" ), GetTimeZone().c_str()); - } -#if defined(USE_TIMERS) && defined(USE_SUNRISE) - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" - D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s,\"" D_JSON_SUNRISE "\":\"%s\",\"" D_JSON_SUNSET "\":\"%s\"}}"), - GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), - GetTime(3).c_str(), stemp, GetSun(0).c_str(), GetSun(1).c_str()); -#else - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" - D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s}}"), - GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), - GetTime(3).c_str(), stemp); -#endif - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "7")); - } - -#if defined(USE_ENERGY_SENSOR) && defined(USE_ENERGY_MARGIN_DETECTION) - if (energy_flg) { - if ((0 == payload) || (9 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS9_MARGIN "\":{\"" D_CMND_POWERDELTA "\":%d,\"" D_CMND_POWERLOW "\":%d,\"" D_CMND_POWERHIGH "\":%d,\"" - D_CMND_VOLTAGELOW "\":%d,\"" D_CMND_VOLTAGEHIGH "\":%d,\"" D_CMND_CURRENTLOW "\":%d,\"" D_CMND_CURRENTHIGH "\":%d}}"), - Settings.energy_power_delta, Settings.energy_min_power, Settings.energy_max_power, - Settings.energy_min_voltage, Settings.energy_max_voltage, Settings.energy_min_current, Settings.energy_max_current); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "9")); - } - } -#endif - - if ((0 == payload) || (8 == payload) || (10 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":")); - MqttShowSensor(); - ResponseJsonEnd(); - if (8 == payload) { - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "8")); - } else { - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "10")); - } - } - - if ((0 == payload) || (11 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS11_STATUS "\":")); - MqttShowState(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); - } - mqtt_data[0] = '\0'; -} - -void CmndState(void) -{ - mqtt_data[0] = '\0'; - MqttShowState(); - if (Settings.flag3.hass_tele_on_power) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); - } -#ifdef USE_HOME_ASSISTANT - if (Settings.flag.hass_discovery) { - HAssPublishStatus(); - } -#endif -} - -void CmndSleep(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 251)) { - Settings.sleep = XdrvMailbox.payload; - sleep = XdrvMailbox.payload; - WiFiSetSleepMode(); - } - Response_P(S_JSON_COMMAND_NVALUE_UNIT_NVALUE_UNIT, XdrvMailbox.command, sleep, (Settings.flag.value_units) ? " " D_UNIT_MILLISECOND : "", Settings.sleep, (Settings.flag.value_units) ? " " D_UNIT_MILLISECOND : ""); -} - -void CmndUpgrade(void) -{ - - - - - if (((1 == XdrvMailbox.data_len) && (1 == XdrvMailbox.payload)) || ((XdrvMailbox.data_len >= 3) && NewerVersion(XdrvMailbox.data))) { - ota_state_flag = 3; - char stemp1[TOPSZ]; - Response_P(PSTR("{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}"), XdrvMailbox.command, my_version, GetOtaUrl(stemp1, sizeof(stemp1))); - } else { - Response_P(PSTR("{\"%s\":\"" D_JSON_ONE_OR_GT "\"}"), XdrvMailbox.command, my_version); - } -} - -void CmndOtaUrl(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.ota_url))) { - strlcpy(Settings.ota_url, (SC_DEFAULT == Shortcut()) ? OTA_URL : XdrvMailbox.data, sizeof(Settings.ota_url)); - } - ResponseCmndChar(Settings.ota_url); -} - -void CmndSeriallog(void) -{ - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { - Settings.flag.mqtt_serial = 0; - SetSeriallog(XdrvMailbox.payload); - } - Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.seriallog_level, seriallog_level); -} - -void CmndRestart(void) -{ - switch (XdrvMailbox.payload) { - case 1: - restart_flag = 2; - ResponseCmndChar(D_JSON_RESTARTING); - break; - case 99: - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); - EspRestart(); - break; - default: - ResponseCmndChar(D_JSON_ONE_TO_RESTART); - } -} - -void CmndPowerOnState(void) -{ - if (my_module_type != MOTOR) { - - - - - - - - if ((XdrvMailbox.payload >= POWER_ALL_OFF) && (XdrvMailbox.payload <= POWER_ALL_OFF_PULSETIME_ON)) { - Settings.poweronstate = XdrvMailbox.payload; - if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - for (uint32_t i = 1; i <= devices_present; i++) { - ExecuteCommandPower(i, POWER_ON, SRC_IGNORE); - } - } - } - ResponseCmndNumber(Settings.poweronstate); - } -} - -void CmndPulsetime(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PULSETIMERS)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { - Settings.pulse_timer[XdrvMailbox.index -1] = XdrvMailbox.payload; - SetPulseTimer(XdrvMailbox.index -1, XdrvMailbox.payload); - } - Response_P(S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, XdrvMailbox.index, Settings.pulse_timer[XdrvMailbox.index -1], GetPulseTimer(XdrvMailbox.index -1)); - } -} - -void CmndBlinktime(void) -{ - if ((XdrvMailbox.payload > 1) && (XdrvMailbox.payload <= 3600)) { - Settings.blinktime = XdrvMailbox.payload; - if (blink_timer > 0) { blink_timer = millis() + (100 * XdrvMailbox.payload); } - } - ResponseCmndNumber(Settings.blinktime); -} - -void CmndBlinkcount(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { - Settings.blinkcount = XdrvMailbox.payload; - if (blink_counter) { blink_counter = Settings.blinkcount *2; } - } - ResponseCmndNumber(Settings.blinkcount); -} - -void CmndSavedata(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3600)) { - Settings.save_data = XdrvMailbox.payload; - save_data_counter = Settings.save_data; - } - SettingsSaveAll(); - char stemp1[TOPSZ]; - if (Settings.save_data > 1) { - snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_EVERY " %d " D_UNIT_SECOND), Settings.save_data); - } - ResponseCmndChar((Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data)); -} - -void CmndSetoption(void) -{ - if (XdrvMailbox.index < 82) { - uint32_t ptype; - uint32_t pindex; - if (XdrvMailbox.index <= 31) { - ptype = 0; - pindex = XdrvMailbox.index; - } - else if (XdrvMailbox.index <= 49) { - ptype = 2; - pindex = XdrvMailbox.index -32; - } - else { - ptype = 1; - pindex = XdrvMailbox.index -50; - } - if (XdrvMailbox.payload >= 0) { - if (0 == ptype) { - if (XdrvMailbox.payload <= 1) { - switch (pindex) { - case 5: - case 6: - case 7: - case 9: - case 14: - case 22: - case 23: - case 25: - case 27: - ptype = 99; - break; - case 3: - case 15: - restart_flag = 2; - default: - bitWrite(Settings.flag.data, pindex, XdrvMailbox.payload); - } - if (12 == pindex) { - stop_flash_rotate = XdrvMailbox.payload; - SettingsSave(2); - } -#ifdef USE_HOME_ASSISTANT - if ((19 == pindex) || (30 == pindex)) { - HAssDiscover(); - } -#endif - } - } - else if (1 == ptype) { - if (XdrvMailbox.payload <= 1) { - bitWrite(Settings.flag3.data, pindex, XdrvMailbox.payload); - if (5 == pindex) { - if (0 == XdrvMailbox.payload) { - restart_flag = 2; - } - } - if (10 == pindex) { - WiFiSetSleepMode(); - } - if (18 == pindex) { - restart_flag = 2; - } - } - } - else { - uint32_t param_low = 0; - uint32_t param_high = 255; - switch (pindex) { - case P_HOLD_TIME: - case P_MAX_POWER_RETRY: - param_low = 1; - param_high = 250; - break; - } - if ((XdrvMailbox.payload >= param_low) && (XdrvMailbox.payload <= param_high)) { - Settings.param[pindex] = XdrvMailbox.payload; - switch (pindex) { -#ifdef USE_LIGHT - case P_RGB_REMAP: - LightUpdateColorMapping(); - break; -#endif -#if (defined(USE_IR_REMOTE) && defined(USE_IR_RECEIVE)) || defined(USE_IR_REMOTE_FULL) - case P_IR_UNKNOW_THRESHOLD: - IrReceiveUpdateThreshold(); - break; -#endif -#ifdef USE_TUYA_MCU - case P_TUYA_DIMMER_MAX: - restart_flag = 2; - break; -#endif - } - } - } - } - if (ptype < 99) { - char stemp1[TOPSZ]; - if (2 == ptype) { snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), Settings.param[pindex]); } - ResponseCmndIdxChar((2 == ptype) ? stemp1 : (1 == ptype) ? GetStateText(bitRead(Settings.flag3.data, pindex)) : GetStateText(bitRead(Settings.flag.data, pindex))); - } - } -} - -void CmndTemperatureResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.temperature_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.temperature_resolution); -} - -void CmndHumidityResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.humidity_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.humidity_resolution); -} - -void CmndPressureResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.pressure_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.pressure_resolution); -} - -void CmndPowerResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.wattage_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.wattage_resolution); -} - -void CmndVoltageResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.voltage_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.voltage_resolution); -} - -void CmndFrequencyResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.frequency_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.frequency_resolution); -} - -void CmndCurrentResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.current_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.current_resolution); -} - -void CmndEnergyResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { - Settings.flag2.energy_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.energy_resolution); -} - -void CmndWeightResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.weight_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.weight_resolution); -} - -void CmndModule(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAXMODULE)) { - bool present = false; - if (0 == XdrvMailbox.payload) { - XdrvMailbox.payload = USER_MODULE; - present = true; - } else { - XdrvMailbox.payload--; - present = ValidTemplateModule(XdrvMailbox.payload); - } - if (present) { - Settings.last_module = Settings.module; - Settings.module = XdrvMailbox.payload; - SetModuleType(); - if (Settings.last_module != XdrvMailbox.payload) { - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - Settings.my_gp.io[i] = GPIO_NONE; - } - } - restart_flag = 2; - } - } - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, ModuleNr(), ModuleName().c_str()); -} - -void CmndModules(void) -{ - uint32_t midx = USER_MODULE; - uint32_t lines = 1; - bool jsflg = false; - for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { - if (i > 0) { midx = pgm_read_byte(kModuleNiceList + i -1); } - if (!jsflg) { - Response_P(PSTR("{\"" D_CMND_MODULES "%d\":{"), lines); - } else { - ResponseAppend_P(PSTR(",")); - } - jsflg = true; - uint32_t j = i ? midx +1 : 0; - if ((ResponseAppend_P(PSTR("\"%d\":\"%s\""), j, AnyModuleName(midx).c_str()) > (LOGSZ - TOPSZ)) || (i == sizeof(kModuleNiceList))) { - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, UpperCase(XdrvMailbox.command, XdrvMailbox.command)); - jsflg = false; - lines++; - } - } - mqtt_data[0] = '\0'; -} - -void CmndGpio(void) -{ - if (XdrvMailbox.index < sizeof(Settings.my_gp)) { - myio cmodule; - ModuleGpios(&cmodule); - if (ValidGPIO(XdrvMailbox.index, cmodule.io[XdrvMailbox.index]) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < GPIO_SENSOR_END)) { - bool present = false; - for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { - uint32_t midx = pgm_read_byte(kGpioNiceList + i); - if (midx == XdrvMailbox.payload) { present = true; } - } - if (present) { - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (ValidGPIO(i, cmodule.io[i]) && (Settings.my_gp.io[i] == XdrvMailbox.payload)) { - Settings.my_gp.io[i] = GPIO_NONE; - } - } - Settings.my_gp.io[XdrvMailbox.index] = XdrvMailbox.payload; - restart_flag = 2; - } - } - Response_P(PSTR("{")); - bool jsflg = false; - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (ValidGPIO(i, cmodule.io[i])) { - if (jsflg) { ResponseAppend_P(PSTR(",")); } - jsflg = true; - char stemp1[TOPSZ]; - ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":{\"%d\":\"%s\"}"), i, Settings.my_gp.io[i], GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_gp.io[i], kSensorNames)); - } - } - if (jsflg) { - ResponseJsonEnd(); - } else { - ResponseCmndChar(D_JSON_NOT_SUPPORTED); - } - } -} - -void CmndGpios(void) -{ - myio cmodule; - ModuleGpios(&cmodule); - uint32_t midx; - uint32_t lines = 1; - bool jsflg = false; - for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { - midx = pgm_read_byte(kGpioNiceList + i); - if ((XdrvMailbox.payload != 255) && GetUsedInModule(midx, cmodule.io)) { continue; } - if (!jsflg) { - Response_P(PSTR("{\"" D_CMND_GPIOS "%d\":{"), lines); - } else { - ResponseAppend_P(PSTR(",")); - } - jsflg = true; - char stemp1[TOPSZ]; - if ((ResponseAppend_P(PSTR("\"%d\":\"%s\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, UpperCase(XdrvMailbox.command, XdrvMailbox.command)); - jsflg = false; - lines++; - } - } - mqtt_data[0] = '\0'; -} - -void CmndTemplate(void) -{ - - bool error = false; - - if (strstr(XdrvMailbox.data, "{") == nullptr) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= MAXMODULE)) { - XdrvMailbox.payload--; - if (ValidTemplateModule(XdrvMailbox.payload)) { - ModuleDefault(XdrvMailbox.payload); - if (USER_MODULE == Settings.module) { restart_flag = 2; } - } - } - else if (0 == XdrvMailbox.payload) { - if (Settings.module != USER_MODULE) { - ModuleDefault(Settings.module); - } - } - else if (255 == XdrvMailbox.payload) { - if (Settings.module != USER_MODULE) { - ModuleDefault(Settings.module); - } - snprintf_P(Settings.user_template.name, sizeof(Settings.user_template.name), PSTR("Merged")); - uint32_t j = 0; - for (uint32_t i = 0; i < sizeof(mycfgio); i++) { - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - if (my_module.io[j] > GPIO_NONE) { - Settings.user_template.gp.io[i] = my_module.io[j]; - } - j++; - } - } - } - else { - if (JsonTemplate(XdrvMailbox.data)) { - if (USER_MODULE == Settings.module) { restart_flag = 2; } - } else { - ResponseCmndChar(D_JSON_INVALID_JSON); - error = true; - } - } - if (!error) { TemplateJson(); } -} - -void CmndPwm(void) -{ - if (pwm_present && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PWMS)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= Settings.pwm_range) && (pin[GPIO_PWM1 + XdrvMailbox.index -1] < 99)) { - Settings.pwm_value[XdrvMailbox.index -1] = XdrvMailbox.payload; - analogWrite(pin[GPIO_PWM1 + XdrvMailbox.index -1], bitRead(pwm_inverted, XdrvMailbox.index -1) ? Settings.pwm_range - XdrvMailbox.payload : XdrvMailbox.payload); - } - Response_P(PSTR("{")); - MqttShowPWMState(); - ResponseJsonEnd(); - } -} - -void CmndPwmfrequency(void) -{ - if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload >= PWM_MIN) && (XdrvMailbox.payload <= PWM_MAX))) { - Settings.pwm_frequency = (1 == XdrvMailbox.payload) ? PWM_FREQ : XdrvMailbox.payload; - analogWriteFreq(Settings.pwm_frequency); - } - ResponseCmndNumber(Settings.pwm_frequency); -} - -void CmndPwmrange(void) -{ - if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload > 254) && (XdrvMailbox.payload < 1024))) { - Settings.pwm_range = (1 == XdrvMailbox.payload) ? PWM_RANGE : XdrvMailbox.payload; - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (Settings.pwm_value[i] > Settings.pwm_range) { - Settings.pwm_value[i] = Settings.pwm_range; - } - } - analogWriteRange(Settings.pwm_range); - } - ResponseCmndNumber(Settings.pwm_range); -} - -void CmndButtonDebounce(void) -{ - if ((XdrvMailbox.payload > 39) && (XdrvMailbox.payload < 1001)) { - Settings.button_debounce = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.button_debounce); -} - -void CmndSwitchDebounce(void) -{ - if ((XdrvMailbox.payload > 39) && (XdrvMailbox.payload < 1001)) { - Settings.switch_debounce = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.switch_debounce); -} - -void CmndBaudrate(void) -{ - if (XdrvMailbox.payload >= 300) { - XdrvMailbox.payload /= 300; - baudrate = (XdrvMailbox.payload & 0xFFFF) * 300; - SetSerialBaudrate(baudrate); - } - ResponseCmndNumber(Settings.baudrate * 300); -} - -void CmndSerialSend(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { - SetSeriallog(LOG_LEVEL_NONE); - Settings.flag.mqtt_serial = 1; - Settings.flag.mqtt_serial_raw = (XdrvMailbox.index > 3) ? 1 : 0; - if (XdrvMailbox.data_len > 0) { - if (1 == XdrvMailbox.index) { - Serial.printf("%s\n", XdrvMailbox.data); - } - else if (2 == XdrvMailbox.index || 4 == XdrvMailbox.index) { - for (uint32_t i = 0; i < XdrvMailbox.data_len; i++) { - Serial.write(XdrvMailbox.data[i]); - } - } - else if (3 == XdrvMailbox.index) { - uint32_t dat_len = XdrvMailbox.data_len; - Serial.printf("%s", Unescape(XdrvMailbox.data, &dat_len)); - } - else if (5 == XdrvMailbox.index) { - SerialSendRaw(RemoveSpace(XdrvMailbox.data)); - } - ResponseCmndDone(); - } - } -} - -void CmndSerialDelimiter(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.payload < 256)) { - if (XdrvMailbox.payload > 0) { - Settings.serial_delimiter = XdrvMailbox.payload; - } else { - uint32_t dat_len = XdrvMailbox.data_len; - Unescape(XdrvMailbox.data, &dat_len); - Settings.serial_delimiter = XdrvMailbox.data[0]; - } - } - ResponseCmndNumber(Settings.serial_delimiter); -} - -void CmndSyslog(void) -{ - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { - SetSyslog(XdrvMailbox.payload); - } - Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.syslog_level, syslog_level); -} - -void CmndLoghost(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.syslog_host))) { - strlcpy(Settings.syslog_host, (SC_DEFAULT == Shortcut()) ? SYS_LOG_HOST : XdrvMailbox.data, sizeof(Settings.syslog_host)); - } - ResponseCmndChar(Settings.syslog_host); -} - -void CmndLogport(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 65536)) { - Settings.syslog_port = (1 == XdrvMailbox.payload) ? SYS_LOG_PORT : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.syslog_port); -} - -void CmndIpAddress(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { - uint32_t address; - if (ParseIp(&address, XdrvMailbox.data)) { - Settings.ip_address[XdrvMailbox.index -1] = address; - - } - char stemp1[TOPSZ]; - snprintf_P(stemp1, sizeof(stemp1), PSTR(" (%s)"), WiFi.localIP().toString().c_str()); - Response_P(S_JSON_COMMAND_INDEX_SVALUE_SVALUE, XdrvMailbox.command, XdrvMailbox.index, IPAddress(Settings.ip_address[XdrvMailbox.index -1]).toString().c_str(), (1 == XdrvMailbox.index) ? stemp1:""); - } -} - -void CmndNtpServer(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.ntp_server[0]))) { - strlcpy(Settings.ntp_server[XdrvMailbox.index -1], - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index)?NTP_SERVER1:(2==XdrvMailbox.index)?NTP_SERVER2:NTP_SERVER3 : XdrvMailbox.data, - sizeof(Settings.ntp_server[0])); - for (uint32_t i = 0; i < strlen(Settings.ntp_server[XdrvMailbox.index -1]); i++) { - if (Settings.ntp_server[XdrvMailbox.index -1][i] == ',') Settings.ntp_server[XdrvMailbox.index -1][i] = '.'; - } - - ntp_force_sync = true; - } - ResponseCmndIdxChar(Settings.ntp_server[XdrvMailbox.index -1]); - } -} - -void CmndAp(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - switch (XdrvMailbox.payload) { - case 0: - Settings.sta_active ^= 1; - break; - case 1: - case 2: - Settings.sta_active = XdrvMailbox.payload -1; - } - restart_flag = 2; - } - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active]); -} - -void CmndSsid(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.sta_ssid[0]))) { - strlcpy(Settings.sta_ssid[XdrvMailbox.index -1], - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data, - sizeof(Settings.sta_ssid[0])); - Settings.sta_active = XdrvMailbox.index -1; - restart_flag = 2; - } - ResponseCmndIdxChar(Settings.sta_ssid[XdrvMailbox.index -1]); - } -} - -void CmndPassword(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if ((XdrvMailbox.data_len > 4 || SC_CLEAR == Shortcut() || SC_DEFAULT == Shortcut()) && (XdrvMailbox.data_len < sizeof(Settings.sta_pwd[0]))) { - strlcpy(Settings.sta_pwd[XdrvMailbox.index -1], - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data, - sizeof(Settings.sta_pwd[0])); - Settings.sta_active = XdrvMailbox.index -1; - restart_flag = 2; - ResponseCmndIdxChar(Settings.sta_pwd[XdrvMailbox.index -1]); - } else { - Response_P(S_JSON_COMMAND_INDEX_ASTERISK, XdrvMailbox.command, XdrvMailbox.index); - } - } -} - -void CmndHostname(void) -{ - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.hostname))) { - strlcpy(Settings.hostname, (SC_DEFAULT == Shortcut()) ? WIFI_HOSTNAME : XdrvMailbox.data, sizeof(Settings.hostname)); - if (strstr(Settings.hostname, "%") != nullptr) { - strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); - } - restart_flag = 2; - } - ResponseCmndChar(Settings.hostname); -} - -void CmndWifiConfig(void) -{ - char stemp1[TOPSZ]; - if ((XdrvMailbox.payload >= WIFI_RESTART) && (XdrvMailbox.payload < MAX_WIFI_OPTION)) { - Settings.sta_config = XdrvMailbox.payload; - wifi_state_flag = Settings.sta_config; - snprintf_P(stemp1, sizeof(stemp1), kWifiConfig[Settings.sta_config]); - Response_P(PSTR("{\"" D_CMND_WIFICONFIG "\":\"%s " D_JSON_SELECTED "\"}"), stemp1); - if (WifiState() > WIFI_RESTART) { - - restart_flag = 2; - } - } else { - snprintf_P(stemp1, sizeof(stemp1), kWifiConfig[Settings.sta_config]); - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_config, stemp1); - } -} - -void CmndFriendlyname(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_FRIENDLYNAMES)) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.friendlyname[0]))) { - char stemp1[TOPSZ]; - if (1 == XdrvMailbox.index) { - snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME)); - } else { - snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), XdrvMailbox.index); - } - strlcpy(Settings.friendlyname[XdrvMailbox.index -1], (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data, sizeof(Settings.friendlyname[XdrvMailbox.index -1])); - } - ResponseCmndIdxChar(Settings.friendlyname[XdrvMailbox.index -1]); - } -} - -void CmndSwitchMode(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SWITCHES)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_SWITCH_OPTION)) { - Settings.switchmode[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.switchmode[XdrvMailbox.index-1]); - } -} - -void CmndInterlock(void) -{ - - uint32_t max_relays = devices_present; - if (light_type) { max_relays--; } - if (max_relays > sizeof(Settings.interlock[0]) * 8) { max_relays = sizeof(Settings.interlock[0]) * 8; } - if (max_relays > 1) { - if (XdrvMailbox.data_len > 0) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } - char *group; - char *q; - uint32_t group_index = 0; - power_t relay_mask = 0; - for (group = strtok_r(XdrvMailbox.data, " ", &q); group && group_index < MAX_INTERLOCKS; group = strtok_r(nullptr, " ", &q)) { - char *str; - char *p; - for (str = strtok_r(group, ",", &p); str; str = strtok_r(nullptr, ",", &p)) { - int pbit = atoi(str); - if ((pbit > 0) && (pbit <= max_relays)) { - pbit--; - if (!bitRead(relay_mask, pbit)) { - bitSet(relay_mask, pbit); - bitSet(Settings.interlock[group_index], pbit); - } - } - } - group_index++; - } - for (uint32_t i = 0; i < group_index; i++) { - uint32_t minimal_bits = 0; - for (uint32_t j = 0; j < max_relays; j++) { - if (bitRead(Settings.interlock[i], j)) { minimal_bits++; } - } - if (minimal_bits < 2) { Settings.interlock[i] = 0; } - } - } else { - Settings.flag.interlock = XdrvMailbox.payload &1; - if (Settings.flag.interlock) { - SetDevicePower(power, SRC_IGNORE); - } - } - } - Response_P(PSTR("{\"" D_CMND_INTERLOCK "\":\"%s\",\"" D_JSON_GROUPS "\":\""), GetStateText(Settings.flag.interlock)); - uint32_t anygroup = 0; - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { - if (Settings.interlock[i]) { - anygroup++; - ResponseAppend_P(PSTR("%s"), (anygroup > 1) ? " " : ""); - uint32_t anybit = 0; - power_t mask = 1; - for (uint32_t j = 0; j < max_relays; j++) { - if (Settings.interlock[i] & mask) { - anybit++; - ResponseAppend_P(PSTR("%s%d"), (anybit > 1) ? "," : "", j +1); - } - mask <<= 1; - } - } - } - if (!anygroup) { - for (uint32_t j = 1; j <= max_relays; j++) { - ResponseAppend_P(PSTR("%s%d"), (j > 1) ? "," : "", j); - } - } - ResponseAppend_P(PSTR("\"}")); - } else { - Settings.flag.interlock = 0; - ResponseCmndStateText(Settings.flag.interlock); - } -} - -void CmndTeleperiod(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.tele_period = (1 == XdrvMailbox.payload) ? TELE_PERIOD : XdrvMailbox.payload; - if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) Settings.tele_period = 10; - tele_period = Settings.tele_period; - } - Response_P(S_JSON_COMMAND_NVALUE_UNIT, XdrvMailbox.command, Settings.tele_period, (Settings.flag.value_units) ? " " D_UNIT_SECOND : ""); -} - -void CmndReset(void) -{ - switch (XdrvMailbox.payload) { - case 1: - restart_flag = 211; - ResponseCmndChar(D_JSON_RESET_AND_RESTARTING); - break; - case 2 ... 6: - restart_flag = 210 + XdrvMailbox.payload; - Response_P(PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); - break; - case 99: - Settings.bootcount = 0; - ResponseCmndDone(); - break; - default: - ResponseCmndChar(D_JSON_ONE_TO_RESET); - } -} - -void CmndTime(void) -{ - - - - - - - - uint32_t format = Settings.flag2.time_format; - if (XdrvMailbox.data_len > 0) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) { - Settings.flag2.time_format = XdrvMailbox.payload -1; - format = Settings.flag2.time_format; - } else { - format = 1; - RtcSetTime(XdrvMailbox.payload); - } - } - mqtt_data[0] = '\0'; - ResponseAppendTimeFormat(format); - ResponseJsonEnd(); -} - -void CmndTimezone(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.payload >= -13)) { - Settings.timezone = XdrvMailbox.payload; - Settings.timezone_minutes = 0; - if (XdrvMailbox.payload < 15) { - char *p = strtok (XdrvMailbox.data, ":"); - if (p) { - p = strtok (nullptr, ":"); - if (p) { - Settings.timezone_minutes = strtol(p, nullptr, 10); - if (Settings.timezone_minutes > 59) { Settings.timezone_minutes = 59; } - } - } - } else { - Settings.timezone = 99; - } - ntp_force_sync = true; - } - if (99 == Settings.timezone) { - ResponseCmndNumber(Settings.timezone); - } else { - char stemp1[TOPSZ]; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%+03d:%02d"), Settings.timezone, Settings.timezone_minutes); - ResponseCmndChar(stemp1); - } -} - -void CmndTimeStdDst(uint32_t ts) -{ - - if (XdrvMailbox.data_len > 0) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - uint32_t tpos = 0; - int value = 0; - char *p = XdrvMailbox.data; - char *q = p; - while (p && (tpos < 7)) { - if (p > q) { - if (1 == tpos) { Settings.tflag[ts].hemis = value &1; } - if (2 == tpos) { Settings.tflag[ts].week = (value < 0) ? 0 : (value > 4) ? 4 : value; } - if (3 == tpos) { Settings.tflag[ts].month = (value < 1) ? 1 : (value > 12) ? 12 : value; } - if (4 == tpos) { Settings.tflag[ts].dow = (value < 1) ? 1 : (value > 7) ? 7 : value; } - if (5 == tpos) { Settings.tflag[ts].hour = (value < 0) ? 0 : (value > 23) ? 23 : value; } - if (6 == tpos) { Settings.toffset[ts] = (value < -900) ? -900 : (value > 900) ? 900 : value; } - } - p = Trim(p); - if (tpos && (*p == ',')) { p++; } - p = Trim(p); - q = p; - value = strtol(p, &p, 10); - tpos++; - } - ntp_force_sync = true; - } else { - if (0 == XdrvMailbox.payload) { - if (0 == ts) { - SettingsResetStd(); - } else { - SettingsResetDst(); - } - } - ntp_force_sync = true; - } - } - Response_P(PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d}}"), - XdrvMailbox.command, Settings.tflag[ts].hemis, Settings.tflag[ts].week, Settings.tflag[ts].month, Settings.tflag[ts].dow, Settings.tflag[ts].hour, Settings.toffset[ts]); -} - -void CmndTimeStd(void) -{ - CmndTimeStdDst(0); -} - -void CmndTimeDst(void) -{ - CmndTimeStdDst(1); -} - -void CmndAltitude(void) -{ - if ((XdrvMailbox.data_len > 0) && ((XdrvMailbox.payload >= -30000) && (XdrvMailbox.payload <= 30000))) { - Settings.altitude = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.altitude); -} - -void CmndLedPower(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_LEDS)) { - if (99 == pin[GPIO_LEDLNK]) { XdrvMailbox.index = 1; } - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - Settings.ledstate &= 8; - uint32_t mask = 1 << (XdrvMailbox.index -1); - switch (XdrvMailbox.payload) { - case 0: - led_power &= (0xFF ^ mask); - Settings.ledstate = 0; - break; - case 1: - led_power |= mask; - Settings.ledstate = 8; - break; - case 2: - led_power ^= mask; - Settings.ledstate ^= 8; - break; - } - blinks = 0; - if (99 == pin[GPIO_LEDLNK]) { - SetLedPower(Settings.ledstate &8); - } else { - SetLedPowerIdx(XdrvMailbox.index -1, (led_power & mask)); - } - } - bool state = bitRead(led_power, XdrvMailbox.index -1); - if (99 == pin[GPIO_LEDLNK]) { - state = bitRead(Settings.ledstate, 3); - } - ResponseCmndIdxChar(GetStateText(state)); - } -} - -void CmndLedState(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_LED_OPTION)) { - Settings.ledstate = XdrvMailbox.payload; - if (!Settings.ledstate) { - SetLedPowerAll(0); - SetLedLink(0); - } - } - ResponseCmndNumber(Settings.ledstate); -} - -void CmndLedMask(void) -{ - if (XdrvMailbox.data_len > 0) { - Settings.ledmask = XdrvMailbox.payload; - } - char stemp1[TOPSZ]; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%d (0x%04X)"), Settings.ledmask, Settings.ledmask); - ResponseCmndChar(stemp1); -} - -#ifdef USE_I2C -void CmndI2cScan(void) -{ - if (i2c_flg) { - I2cScan(mqtt_data, sizeof(mqtt_data)); - } -} -#endif - -void CmndSensor(void) -{ - XsnsCall(FUNC_COMMAND_SENSOR); -} - -void CmndDriver(void) -{ - XdrvCall(FUNC_COMMAND_DRIVER); -} -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_features.ino" -# 24 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_features.ino" -void GetFeatures(void) -{ - feature_drv1 = 0x00000000; - -#ifdef USE_ENERGY_MARGIN_DETECTION - feature_drv1 |= 0x00000001; -#endif -#ifdef USE_LIGHT - feature_drv1 |= 0x00000002; -#endif -#ifdef USE_I2C - feature_drv1 |= 0x00000004; -#endif -#ifdef USE_SPI - feature_drv1 |= 0x00000008; -#endif -#ifdef USE_DISCOVERY - feature_drv1 |= 0x00000010; -#endif -#ifdef USE_ARDUINO_OTA - feature_drv1 |= 0x00000020; -#endif -#ifdef USE_MQTT_TLS - feature_drv1 |= 0x00000040; -#endif -#ifdef USE_WEBSERVER - feature_drv1 |= 0x00000080; -#endif -#ifdef WEBSERVER_ADVERTISE - feature_drv1 |= 0x00000100; -#endif -#ifdef USE_EMULATION_HUE - feature_drv1 |= 0x00000200; -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT) - feature_drv1 |= 0x00000400; -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) - -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) - -#endif -#ifdef MQTT_HOST_DISCOVERY - feature_drv1 |= 0x00002000; -#endif -#ifdef USE_ARILUX_RF - feature_drv1 |= 0x00004000; -#endif -#if defined(USE_LIGHT) && defined(USE_WS2812) - feature_drv1 |= 0x00008000; -#endif -#ifdef USE_WS2812_DMA - feature_drv1 |= 0x00010000; -#endif -#if defined(USE_IR_REMOTE) || defined(USE_IR_REMOTE_FULL) - feature_drv1 |= 0x00020000; -#endif -#ifdef USE_IR_HVAC - feature_drv1 |= 0x00040000; -#endif -#ifdef USE_IR_RECEIVE - feature_drv1 |= 0x00080000; -#endif -#ifdef USE_DOMOTICZ - feature_drv1 |= 0x00100000; -#endif -#ifdef USE_DISPLAY - feature_drv1 |= 0x00200000; -#endif -#ifdef USE_HOME_ASSISTANT - feature_drv1 |= 0x00400000; -#endif -#ifdef USE_SERIAL_BRIDGE - feature_drv1 |= 0x00800000; -#endif -#ifdef USE_TIMERS - feature_drv1 |= 0x01000000; -#endif -#ifdef USE_SUNRISE - feature_drv1 |= 0x02000000; -#endif -#ifdef USE_TIMERS_WEB - feature_drv1 |= 0x04000000; -#endif -#ifdef USE_RULES - feature_drv1 |= 0x08000000; -#endif -#ifdef USE_KNX - feature_drv1 |= 0x10000000; -#endif -#ifdef USE_WPS - feature_drv1 |= 0x20000000; -#endif -#ifdef USE_SMARTCONFIG - feature_drv1 |= 0x40000000; -#endif -#ifdef USE_ENERGY_POWER_LIMIT - feature_drv1 |= 0x80000000; -#endif - - - - feature_drv2 = 0x00000000; - -#ifdef USE_CONFIG_OVERRIDE - feature_drv2 |= 0x00000001; -#endif -#ifdef FIRMWARE_MINIMAL - feature_drv2 |= 0x00000002; -#endif -#ifdef FIRMWARE_SENSORS - feature_drv2 |= 0x00000004; -#endif -#ifdef FIRMWARE_CLASSIC - feature_drv2 |= 0x00000008; -#endif -#ifdef FIRMWARE_KNX_NO_EMULATION - feature_drv2 |= 0x00000010; -#endif -#ifdef USE_DISPLAY_MODES1TO5 - feature_drv2 |= 0x00000020; -#endif -#ifdef USE_DISPLAY_GRAPH - feature_drv2 |= 0x00000040; -#endif -#ifdef USE_DISPLAY_LCD - feature_drv2 |= 0x00000080; -#endif -#ifdef USE_DISPLAY_SSD1306 - feature_drv2 |= 0x00000100; -#endif -#ifdef USE_DISPLAY_MATRIX - feature_drv2 |= 0x00000200; -#endif -#ifdef USE_DISPLAY_ILI9341 - feature_drv2 |= 0x00000400; -#endif -#ifdef USE_DISPLAY_EPAPER_29 - feature_drv2 |= 0x00000800; -#endif -#ifdef USE_DISPLAY_SH1106 - feature_drv2 |= 0x00001000; -#endif -#ifdef USE_MP3_PLAYER - feature_drv2 |= 0x00002000; -#endif -#ifdef USE_PCA9685 - feature_drv2 |= 0x00004000; -#endif -#if defined(USE_LIGHT) && defined(USE_TUYA_MCU) - feature_drv2 |= 0x00008000; -#endif -#ifdef USE_RC_SWITCH - feature_drv2 |= 0x00010000; -#endif -#if defined(USE_LIGHT) && defined(USE_ARMTRONIX_DIMMERS) - feature_drv2 |= 0x00020000; -#endif -#if defined(USE_LIGHT) && defined(USE_SM16716) - feature_drv2 |= 0x00040000; -#endif -#ifdef USE_SCRIPT - feature_drv2 |= 0x00080000; -#endif -#ifdef USE_EMULATION_WEMO - feature_drv2 |= 0x00100000; -#endif -#ifdef USE_SONOFF_IFAN - feature_drv2 |= 0x00200000; -#endif -#ifdef USE_ZIGBEE - feature_drv2 |= 0x00400000; -#endif -#ifdef NO_EXTRA_4K_HEAP - feature_drv2 |= 0x00800000; -#endif -#ifdef VTABLES_IN_IRAM - feature_drv2 |= 0x01000000; -#endif -#ifdef VTABLES_IN_DRAM - feature_drv2 |= 0x02000000; -#endif -#ifdef VTABLES_IN_FLASH - feature_drv2 |= 0x04000000; -#endif -#ifdef PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH - feature_drv2 |= 0x08000000; -#endif -#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY - feature_drv2 |= 0x10000000; -#endif -#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH - feature_drv2 |= 0x20000000; -#endif -#ifdef DEBUG_THEO - feature_drv2 |= 0x40000000; -#endif -#ifdef USE_DEBUG_DRIVER - feature_drv2 |= 0x80000000; -#endif - - - - feature_sns1 = 0x00000000; - -#ifdef USE_COUNTER - feature_sns1 |= 0x00000001; -#endif -#ifdef USE_ADC_VCC - feature_sns1 |= 0x00000002; -#endif -#ifdef USE_ENERGY_SENSOR - feature_sns1 |= 0x00000004; -#endif -#ifdef USE_PZEM004T - feature_sns1 |= 0x00000008; -#endif -#ifdef USE_DS18B20 - feature_sns1 |= 0x00000010; -#endif -#ifdef USE_DS18x20_LEGACY - feature_sns1 |= 0x00000020; -#endif -#ifdef USE_DS18x20 - feature_sns1 |= 0x00000040; -#endif -#ifdef USE_DHT - feature_sns1 |= 0x00000080; -#endif -#ifdef USE_SHT - feature_sns1 |= 0x00000100; -#endif -#ifdef USE_HTU - feature_sns1 |= 0x00000200; -#endif -#ifdef USE_BMP - feature_sns1 |= 0x00000400; -#endif -#ifdef USE_BME680 - feature_sns1 |= 0x00000800; -#endif -#ifdef USE_BH1750 - feature_sns1 |= 0x00001000; -#endif -#ifdef USE_VEML6070 - feature_sns1 |= 0x00002000; -#endif -#ifdef USE_ADS1115_I2CDEV - feature_sns1 |= 0x00004000; -#endif -#ifdef USE_ADS1115 - feature_sns1 |= 0x00008000; -#endif -#ifdef USE_INA219 - feature_sns1 |= 0x00010000; -#endif -#ifdef USE_SHT3X - feature_sns1 |= 0x00020000; -#endif -#ifdef USE_MHZ19 - feature_sns1 |= 0x00040000; -#endif -#ifdef USE_TSL2561 - feature_sns1 |= 0x00080000; -#endif -#ifdef USE_SENSEAIR - feature_sns1 |= 0x00100000; -#endif -#ifdef USE_PMS5003 - feature_sns1 |= 0x00200000; -#endif -#ifdef USE_MGS - feature_sns1 |= 0x00400000; -#endif -#ifdef USE_NOVA_SDS - feature_sns1 |= 0x00800000; -#endif -#ifdef USE_SGP30 - feature_sns1 |= 0x01000000; -#endif -#ifdef USE_SR04 - feature_sns1 |= 0x02000000; -#endif -#ifdef USE_SDM120 - feature_sns1 |= 0x04000000; -#endif -#ifdef USE_SI1145 - feature_sns1 |= 0x08000000; -#endif -#ifdef USE_SDM630 - feature_sns1 |= 0x10000000; -#endif -#ifdef USE_LM75AD - feature_sns1 |= 0x20000000; -#endif -#ifdef USE_APDS9960 - feature_sns1 |= 0x40000000; -#endif -#ifdef USE_TM1638 - feature_sns1 |= 0x80000000; -#endif - - - - feature_sns2 = 0x00000000; - -#ifdef USE_MCP230xx - feature_sns2 |= 0x00000001; -#endif -#ifdef USE_MPR121 - feature_sns2 |= 0x00000002; -#endif -#ifdef USE_CCS811 - feature_sns2 |= 0x00000004; -#endif -#ifdef USE_MPU6050 - feature_sns2 |= 0x00000008; -#endif -#ifdef USE_MCP230xx_OUTPUT - feature_sns2 |= 0x00000010; -#endif -#ifdef USE_MCP230xx_DISPLAYOUTPUT - feature_sns2 |= 0x00000020; -#endif -#ifdef USE_HLW8012 - feature_sns2 |= 0x00000040; -#endif -#ifdef USE_CSE7766 - feature_sns2 |= 0x00000080; -#endif -#ifdef USE_MCP39F501 - feature_sns2 |= 0x00000100; -#endif -#ifdef USE_PZEM_AC - feature_sns2 |= 0x00000200; -#endif -#ifdef USE_DS3231 - feature_sns2 |= 0x00000400; -#endif -#ifdef USE_HX711 - feature_sns2 |= 0x00000800; -#endif -#ifdef USE_PZEM_DC - feature_sns2 |= 0x00001000; -#endif -#ifdef USE_TX20_WIND_SENSOR - feature_sns2 |= 0x00002000; -#endif -#ifdef USE_MGC3130 - feature_sns2 |= 0x00004000; -#endif -#ifdef USE_RF_SENSOR - feature_sns2 |= 0x00008000; -#endif -#ifdef USE_THEO_V2 - feature_sns2 |= 0x00010000; -#endif -#ifdef USE_ALECTO_V2 - feature_sns2 |= 0x00020000; -#endif -#ifdef USE_AZ7798 - feature_sns2 |= 0x00040000; -#endif -#ifdef USE_MAX31855 - feature_sns2 |= 0x00080000; -#endif -#ifdef USE_PN532_HSU - feature_sns2 |= 0x00100000; -#endif -#ifdef USE_MAX44009 - feature_sns2 |= 0x00200000; -#endif -#ifdef USE_SCD30 - feature_sns2 |= 0x00400000; -#endif -#ifdef USE_HRE - feature_sns2 |= 0x00800000; -#endif -#ifdef USE_ADE7953 - feature_sns2 |= 0x01000000; -#endif -#ifdef USE_SPS30 - feature_sns2 |= 0x02000000; -#endif -#ifdef USE_VL53L0X - feature_sns2 |= 0x04000000; -#endif -#ifdef USE_MLX90614 - feature_sns2 |= 0x08000000; -#endif -#ifdef USE_MAX31865 - feature_sns2 |= 0x10000000; -#endif -#ifdef USE_CHIRP - feature_sns2 |= 0x20000000; -#endif -#ifdef USE_SOLAX_X1 - feature_sns2 |= 0x40000000; -#endif -#ifdef USE_PAJ7620 - feature_sns2 |= 0x80000000; -#endif - - - - feature5 = 0x00000000; - -#ifdef USE_BUZZER - feature5 |= 0x00000001; -#endif -#ifdef USE_RDM6300 - feature5 |= 0x00000002; -#endif -#ifdef USE_IBEACON - feature5 |= 0x00000004; -#endif -#ifdef USE_SML_M - feature5 |= 0x00000008; -#endif -#ifdef USE_INA226 - feature5 |= 0x00000010; -#endif -#ifdef USE_A4988_Stepper - feature5 |= 0x00000020; -#endif -#ifdef USE_DDS2382 - feature5 |= 0x00000040; -#endif -# 485 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_features.ino" -} -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_float.ino" -# 23 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_float.ino" -float fmodf(float x, float y) -{ - - union {float f; uint32_t i;} ux = {x}, uy = {y}; - int ex = ux.i>>23 & 0xff; - int ey = uy.i>>23 & 0xff; - uint32_t sx = ux.i & 0x80000000; - uint32_t i; - uint32_t uxi = ux.i; - - if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) - return (x*y)/(x*y); - if (uxi<<1 <= uy.i<<1) { - if (uxi<<1 == uy.i<<1) - return 0*x; - return x; - } - - - if (!ex) { - for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1); - uxi <<= -ex + 1; - } else { - uxi &= -1U >> 9; - uxi |= 1U << 23; - } - if (!ey) { - for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); - uy.i <<= -ey + 1; - } else { - uy.i &= -1U >> 9; - uy.i |= 1U << 23; - } - - - for (; ex > ey; ex--) { - i = uxi - uy.i; - if (i >> 31 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - uxi <<= 1; - } - i = uxi - uy.i; - if (i >> 31 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - for (; uxi>>23 == 0; uxi <<= 1, ex--); - - - if (ex > 0) { - uxi -= 1U << 23; - uxi |= (uint32_t)ex << 23; - } else { - uxi >>= -ex + 1; - } - uxi |= sx; - ux.i = uxi; - return ux.f; -} - - -double FastPrecisePow(double a, double b) -{ - - - int e = abs((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; - - - double r = 1.0; - while (e) { - if (e & 1) { - r *= a; - } - a *= a; - e >>= 1; - } - return r * u.d; -} - -float FastPrecisePowf(const float x, const float y) -{ - - return (float)FastPrecisePow(x, y); -} - -double TaylorLog(double x) -{ - - - if (x <= 0.0) { return NAN; } - double z = (x + 1) / (x - 1); - double step = ((x - 1) * (x - 1)) / ((x + 1) * (x + 1)); - double totalValue = 0; - double powe = 1; - double y; - for (uint32_t count = 0; count < 10; count++) { - z *= step; - y = (1 / powe) * z; - totalValue = totalValue + y; - powe = powe + 2; - } - totalValue *= 2; -# 145 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_float.ino" - return totalValue; -} -# 155 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_float.ino" -inline float sinf(float x) { return sin_52(x); } -inline float cosf(float x) { return cos_52(x); } -inline float tanf(float x) { return tan_56(x); } -inline float atanf(float x) { return atan_66(x); } -inline float asinf(float x) { return asinf1(x); } -inline float acosf(float x) { return acosf1(x); } -inline float sqrtf(float x) { return sqrt1(x); } -inline float powf(float x, float y) { return FastPrecisePow(x, y); } - - -double const f_pi = 3.1415926535897932384626433; -double const f_twopi = 2.0 * f_pi; -double const f_two_over_pi = 2.0 / f_pi; -double const f_halfpi = f_pi / 2.0; -double const f_threehalfpi = 3.0 * f_pi / 2.0; -double const f_four_over_pi = 4.0 / f_pi; -double const f_qtrpi = f_pi / 4.0; -double const f_sixthpi = f_pi / 6.0; -double const f_tansixthpi = tan(f_sixthpi); -double const f_twelfthpi = f_pi / 12.0; -double const f_tantwelfthpi = tan(f_twelfthpi); -# 194 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_float.ino" -float cos_52s(float x) -{ - const float c1 = 0.9999932946; - const float c2 = -0.4999124376; - const float c3 = 0.0414877472; - const float c4 = -0.0012712095; - - float x2 = x * x; - return (c1 + x2 * (c2 + x2 * (c3 + c4 * x2))); -} - - - - - - -float cos_52(float x) -{ - x = fmodf(x, f_twopi); - if (x < 0) { x = -x; } - int quad = int(x * (float)f_two_over_pi); - switch (quad) { - case 0: return cos_52s(x); - case 1: return -cos_52s((float)f_pi - x); - case 2: return -cos_52s(x-(float)f_pi); - case 3: return cos_52s((float)f_twopi - x); - } -} - - - - -float sin_52(float x) -{ - return cos_52((float)f_halfpi - x); -} -# 247 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_float.ino" -float tan_56s(float x) -{ - const float c1 = -3.16783027; - const float c2 = 0.134516124; - const float c3 = -4.033321984; - - float x2 = x * x; - return (x * (c1 + c2 * x2) / (c3 + x2)); -} -# 267 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_float.ino" -float tan_56(float x) -{ - x = fmodf(x, (float)f_twopi); - int octant = int(x * (float)f_four_over_pi); - switch (octant){ - case 0: return tan_56s(x * (float)f_four_over_pi); - case 1: return 1.0f / tan_56s(((float)f_halfpi - x) * (float)f_four_over_pi); - case 2: return -1.0f / tan_56s((x-(float)f_halfpi) * (float)f_four_over_pi); - case 3: return - tan_56s(((float)f_pi - x) * (float)f_four_over_pi); - case 4: return tan_56s((x-(float)f_pi) * (float)f_four_over_pi); - case 5: return 1.0f / tan_56s(((float)f_threehalfpi - x) * (float)f_four_over_pi); - case 6: return -1.0f / tan_56s((x-(float)f_threehalfpi) * (float)f_four_over_pi); - case 7: return - tan_56s(((float)f_twopi - x) * (float)f_four_over_pi); - } -} -# 296 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_float.ino" -float atan_66s(float x) -{ - const float c1 = 1.6867629106; - const float c2 = 0.4378497304; - const float c3 = 1.6867633134; - - float x2 = x * x; - return (x * (c1 + x2 * c2) / (c3 + x2)); -} - - - - - -float atan_66(float x) -{ - float y; - bool complement= false; - bool region= false; - bool sign= false; - - if (x < 0) { - x = -x; - sign = true; - } - if (x > 1.0) { - x = 1.0 / x; - complement = true; - } - if (x > (float)f_tantwelfthpi) { - x = (x - (float)f_tansixthpi) / (1 + (float)f_tansixthpi * x); - region = true; - } - - y = atan_66s(x); - if (region) { y += (float)f_sixthpi; } - if (complement) { y = (float)f_halfpi-y; } - if (sign) { y = -y; } - return (y); -} - -float asinf1(float x) -{ - float d = 1.0f - x * x; - if (d < 0.0f) { return NAN; } - return 2 * atan_66(x / (1 + sqrt1(d))); -} - -float acosf1(float x) -{ - float d = 1.0f - x * x; - if (d < 0.0f) { return NAN; } - float y = asinf1(sqrt1(d)); - if (x >= 0.0f) { - return y; - } else { - return (float)f_pi - y; - } -} - - -float sqrt1(const float x) -{ - union { - int i; - float x; - } u; - u.x = x; - u.i = (1 << 29) + (u.i >> 1) - (1 << 22); - - - - - u.x = u.x + x / u.x; - u.x = 0.25f * u.x + x / u.x; - - return u.x; -} -# 386 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_float.ino" -uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max, - uint16_t ito_min, uint16_t ito_max) { - - if ((ito_min >= ito_max) || (ifrom_min >= ifrom_max)) { - return ito_min; - } - - uint32_t num = inum; - uint32_t from_min = ifrom_min; - uint32_t from_max = ifrom_max; - uint32_t to_min = ito_min; - uint32_t to_max = ito_max; - - - num = (num > from_max ? from_max : (num < from_min ? from_min : num)); - uint32_t numerator = (num - from_min) * (to_max - to_min); - uint32_t result; - if (numerator >= 0x80000000L) { - - result = numerator / (from_max - from_min) + to_min; - } else { - result = (((numerator * 2) / (from_max - from_min)) + 1) / 2 + to_min; - } - return (uint32_t) (result > to_max ? to_max : (result < to_min ? to_min : result)); -} -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_rotary.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_rotary.ino" -#ifdef USE_LIGHT - -#ifdef ROTARY_V1 - - - - -struct ROTARY { - unsigned long debounce = 0; - uint8_t present = 0; - uint8_t state = 0; - uint8_t position = 128; - uint8_t last_position = 128; - uint8_t interrupts_in_use_count = 0; - uint8_t changed = 0; -} Rotary; - - - -void update_position(void) -{ - uint8_t s; - - - - - - s = Rotary.state & 3; - if (digitalRead(pin[GPIO_ROT1A])) s |= 4; - if (digitalRead(pin[GPIO_ROT1B])) s |= 8; - switch (s) { - case 0: case 5: case 10: case 15: - break; - case 1: case 7: case 8: case 14: - Rotary.position++; break; - case 2: case 4: case 11: case 13: - Rotary.position--; break; - case 3: case 12: - Rotary.position = Rotary.position + 2; break; - default: - Rotary.position = Rotary.position - 2; break; - } - Rotary.state = (s >> 2); -} - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -void update_rotary(void) ICACHE_RAM_ATTR; -#endif - -void update_rotary(void) -{ - if (MI_DESK_LAMP == my_module_type){ - if (LightPower()) { - update_position(); - } - } -} - -bool RotaryButtonPressed(void) -{ - if ((MI_DESK_LAMP == my_module_type) && (Rotary.changed) && LightPower()) { - Rotary.changed = 0; - return true; - } - return false; -} - -void RotaryInit(void) -{ - Rotary.present = 0; - if ((pin[GPIO_ROT1A] < 99) && (pin[GPIO_ROT1B] < 99)) { - Rotary.present++; - pinMode(pin[GPIO_ROT1A], INPUT_PULLUP); - pinMode(pin[GPIO_ROT1B], INPUT_PULLUP); - - - - - if ((pin[GPIO_ROT1A] < 6) || (pin[GPIO_ROT1A] > 11)) { - attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1A]), update_rotary, CHANGE); - Rotary.interrupts_in_use_count++; - } - if ((pin[GPIO_ROT1B] < 6) || (pin[GPIO_ROT1B] > 11)) { - attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1B]), update_rotary, CHANGE); - Rotary.interrupts_in_use_count++; - } - } -} - - - - - -void RotaryHandler(void) -{ - if (Rotary.interrupts_in_use_count < 2) { - noInterrupts(); - update_rotary(); - } else { - noInterrupts(); - } - if (Rotary.last_position != Rotary.position) { - if (MI_DESK_LAMP == my_module_type) { - if (Button.hold_timer[0]) { - Rotary.changed = 1; - - int16_t t = LightGetColorTemp(); - t = t + (Rotary.position - Rotary.last_position); - if (t < 153) { - t = 153; - } - if (t > 500) { - t = 500; - } - DEBUG_CORE_LOG(PSTR("ROT: " D_CMND_COLORTEMPERATURE " %d"), Rotary.position - Rotary.last_position); - LightSetColorTemp((uint16_t)t); - } else { - int8_t d = Settings.light_dimmer; - d = d + (Rotary.position - Rotary.last_position); - if (d < 1) { - d = 1; - } - if (d > 100) { - d = 100; - } - DEBUG_CORE_LOG(PSTR("ROT: " D_CMND_DIMMER " %d"), Rotary.position - Rotary.last_position); - - LightSetDimmer((uint8_t)d); - Settings.light_dimmer = d; - } - } - Rotary.last_position = 128; - Rotary.position = 128; - } - interrupts(); -} - -void RotaryLoop(void) -{ - if (Rotary.present) { - if (TimeReached(Rotary.debounce)) { - SetNextTimeInterval(Rotary.debounce, Settings.button_debounce); - RotaryHandler(); - } - } -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_rtc.ino" -# 25 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_rtc.ino" -const uint32_t SECS_PER_MIN = 60UL; -const uint32_t SECS_PER_HOUR = 3600UL; -const uint32_t SECS_PER_DAY = SECS_PER_HOUR * 24UL; -const uint32_t MINS_PER_HOUR = 60UL; - -#define LEAP_YEAR(Y) (((1970+Y)>0) && !((1970+Y)%4) && (((1970+Y)%100) || !((1970+Y)%400))) - -extern "C" { -#include "sntp.h" -} -#include - -Ticker TickerRtc; - -static const uint8_t kDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -static const char kMonthNamesEnglish[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; - -struct RTC { - 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 = 0; - uint32_t restart_time = 0; - int32_t drift_time = 0; - int32_t time_timezone = 0; - uint8_t ntp_sync_minute = 0; - bool midnight_now = false; - bool user_time_entry = false; -} Rtc; - -uint32_t UtcTime(void) -{ - return Rtc.utc_time; -} - -uint32_t LocalTime(void) -{ - return Rtc.local_time; -} - -int32_t DriftTime(void) -{ - return Rtc.drift_time; -} - -uint32_t Midnight(void) -{ - return Rtc.midnight; -} - -bool MidnightNow(void) -{ - if (Rtc.midnight_now) { - Rtc.midnight_now = false; - return true; - } - return false; -} - -bool IsDst(void) -{ - if (Rtc.time_timezone == Settings.toffset[1]) { - return true; - } - return false; -} - -String GetBuildDateAndTime(void) -{ - - char bdt[21]; - char *p; - char mdate[] = __DATE__; - char *smonth = mdate; - int day = 0; - int year = 0; - - - uint8_t i = 0; - for (char *str = strtok_r(mdate, " ", &p); str && i < 3; str = strtok_r(nullptr, " ", &p)) { - switch (i++) { - case 0: - smonth = str; - break; - case 1: - day = atoi(str); - break; - case 2: - year = atoi(str); - } - } - int month = (strstr(kMonthNamesEnglish, smonth) -kMonthNamesEnglish) /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 GetTimeZone(void) -{ - char tz[7]; - - snprintf_P(tz, sizeof(tz), PSTR("%+03d:%02d"), Rtc.time_timezone / 60, abs(Rtc.time_timezone % 60)); - - return String(tz); -} - -String GetDuration(uint32_t time) -{ - char dt[16]; - - TIME_T ut; - BreakTime(time, ut); - - - - - - - snprintf_P(dt, sizeof(dt), PSTR("%dT%02d:%02d:%02d"), ut.days, ut.hour, ut.minute, ut.second); - - return String(dt); -} - -String GetDT(uint32_t time) -{ - - - char dt[20]; - TIME_T tmpTime; - - BreakTime(time, tmpTime); - snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), - tmpTime.year +1970, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); - - return String(dt); -} -# 174 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_rtc.ino" -String GetDateAndTime(uint8_t time_type) -{ - - uint32_t time = Rtc.local_time; - - switch (time_type) { - case DT_ENERGY: - time = Settings.energy_kWhtotal_time; - break; - case DT_UTC: - time = Rtc.utc_time; - break; - case DT_RESTART: - if (Rtc.restart_time == 0) { - return ""; - } - time = Rtc.restart_time; - break; - } - String dt = GetDT(time); - if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { - dt += GetTimeZone(); - } - return dt; -} - -String GetTime(int type) -{ - - - - - char stime[25]; - - uint32_t time = Rtc.utc_time; - if (1 == type) time = Rtc.local_time; - if (2 == type) time = Rtc.daylight_saving_time; - if (3 == type) time = Rtc.standard_time; - snprintf_P(stime, sizeof(stime), sntp_get_real_time(time)); - - return String(stime); -} - -uint32_t UpTime(void) -{ - if (Rtc.restart_time) { - return Rtc.utc_time - Rtc.restart_time; - } else { - return uptime; - } -} - -uint32_t MinutesUptime(void) -{ - return (UpTime() / 60); -} - -String GetUptime(void) -{ - return GetDuration(UpTime()); -} - -uint32_t MinutesPastMidnight(void) -{ - uint32_t minutes = 0; - - if (RtcTime.valid) { - minutes = (RtcTime.hour *60) + RtcTime.minute; - } - return minutes; -} - -void BreakTime(uint32_t time_input, TIME_T &tm) -{ - - - - - uint8_t year; - uint8_t month; - uint8_t month_length; - uint32_t time; - unsigned long days; - - time = time_input; - tm.second = time % 60; - time /= 60; - tm.minute = time % 60; - time /= 60; - tm.hour = time % 24; - time /= 24; - tm.days = time; - tm.day_of_week = ((time + 4) % 7) + 1; - - year = 0; - days = 0; - while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { - year++; - } - tm.year = year; - - days -= LEAP_YEAR(year) ? 366 : 365; - time -= days; - tm.day_of_year = time; - - days = 0; - month = 0; - month_length = 0; - for (month = 0; month < 12; month++) { - if (1 == month) { - if (LEAP_YEAR(year)) { - month_length = 29; - } else { - month_length = 28; - } - } else { - month_length = kDaysInMonth[month]; - } - - if (time >= month_length) { - time -= month_length; - } else { - break; - } - } - strlcpy(tm.name_of_month, kMonthNames + (month *3), 4); - tm.month = month + 1; - tm.day_of_month = time + 1; - tm.valid = (time_input > START_VALID_TIME); -} - -uint32_t MakeTime(TIME_T &tm) -{ - - - - int i; - uint32_t seconds; - - - seconds = tm.year * (SECS_PER_DAY * 365); - for (i = 0; i < tm.year; i++) { - if (LEAP_YEAR(i)) { - seconds += SECS_PER_DAY; - } - } - - - for (i = 1; i < tm.month; i++) { - if ((2 == i) && LEAP_YEAR(tm.year)) { - seconds += SECS_PER_DAY * 29; - } else { - seconds += SECS_PER_DAY * kDaysInMonth[i-1]; - } - } - 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 RuleToTime(TimeRule r, int yr) -{ - TIME_T tm; - uint32_t t; - uint8_t m; - uint8_t w; - - m = r.month; - w = r.week; - if (0 == w) { - if (++m > 12) { - m = 1; - yr++; - } - w = 1; - } - - 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); - 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; - } - return t; -} - -void RtcSecond(void) -{ - TIME_T tmpTime; - - if (!Rtc.user_time_entry) { - if ((Rtc.ntp_sync_minute > 59) && (RtcTime.minute > 2)) Rtc.ntp_sync_minute = 1; - uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP.getChipId() & 0xF) * 3) + 3) ; - if (!global_state.wifi_down && (((offset == RtcTime.second) && ((RtcTime.year < 2016) || (Rtc.ntp_sync_minute == RtcTime.minute))) || ntp_force_sync)) { - Rtc.ntp_time = sntp_get_current_timestamp(); - if (Rtc.ntp_time > START_VALID_TIME) { - ntp_force_sync = false; - if (Rtc.utc_time > START_VALID_TIME) { Rtc.drift_time = Rtc.ntp_time - Rtc.utc_time; } - Rtc.utc_time = Rtc.ntp_time; - Rtc.ntp_sync_minute = 60; - if (Rtc.restart_time == 0) { - Rtc.restart_time = Rtc.utc_time - uptime; - } - BreakTime(Rtc.utc_time, tmpTime); - RtcTime.year = tmpTime.year + 1970; - Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); - Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); - - - - ntp_synced_message = true; - - if (Rtc.local_time < START_VALID_TIME) { - rules_flag.time_init = 1; - } else { - rules_flag.time_set = 1; - } - } else { - Rtc.ntp_sync_minute++; - } - } - } - Rtc.utc_time++; - Rtc.local_time = Rtc.utc_time; - if (Rtc.local_time > START_VALID_TIME) { - int16_t timezone_minutes = Settings.timezone_minutes; - if (Settings.timezone < 0) { timezone_minutes *= -1; } - Rtc.time_timezone = (Settings.timezone * SECS_PER_HOUR) + (timezone_minutes * SECS_PER_MIN); - if (99 == Settings.timezone) { - int32_t dstoffset = Settings.toffset[1] * SECS_PER_MIN; - int32_t stdoffset = Settings.toffset[0] * SECS_PER_MIN; - if (Settings.tflag[1].hemis) { - - if ((Rtc.utc_time >= (Rtc.standard_time - dstoffset)) && (Rtc.utc_time < (Rtc.daylight_saving_time - stdoffset))) { - Rtc.time_timezone = stdoffset; - } else { - Rtc.time_timezone = dstoffset; - } - } else { - - if ((Rtc.utc_time >= (Rtc.daylight_saving_time - stdoffset)) && (Rtc.utc_time < (Rtc.standard_time - dstoffset))) { - Rtc.time_timezone = dstoffset; - } else { - Rtc.time_timezone = stdoffset; - } - } - } - Rtc.local_time += Rtc.time_timezone; - Rtc.time_timezone /= 60; - if (!Settings.energy_kWhtotal_time) { Settings.energy_kWhtotal_time = Rtc.local_time; } - } - BreakTime(Rtc.local_time, RtcTime); - - if (RtcTime.valid) { - if (!Rtc.midnight) { - Rtc.midnight = Rtc.local_time - (RtcTime.hour * 3600) - (RtcTime.minute * 60) - RtcTime.second; - } - if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second) { - Rtc.midnight = Rtc.local_time; - Rtc.midnight_now = true; - } - } - - RtcTime.year += 1970; -} - -void RtcSetTime(uint32_t epoch) -{ - if (epoch < START_VALID_TIME) { - Rtc.user_time_entry = false; - ntp_force_sync = true; - } else { - Rtc.user_time_entry = true; - Rtc.utc_time = epoch -1; - } - RtcSecond(); -} - -void RtcInit(void) -{ - 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); - sntp_init(); - Rtc.utc_time = 0; - BreakTime(Rtc.utc_time, RtcTime); - TickerRtc.attach(1, RtcSecond); -} -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_static_buffer.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_static_buffer.ino" -typedef struct SBuffer_impl { - uint16_t size; - uint16_t len; - uint8_t buf[]; -} SBuffer_impl; - - - -typedef class SBuffer { - -protected: - SBuffer(void) { - - } - -public: - SBuffer(const size_t size) { - _buf = (SBuffer_impl*) new char[size+4]; - _buf->size = size; - _buf->len = 0; - - } - - inline size_t getSize(void) const { return _buf->size; } - inline size_t size(void) const { return _buf->size; } - inline size_t getLen(void) const { return _buf->len; } - inline size_t len(void) const { return _buf->len; } - inline uint8_t *getBuffer(void) const { return _buf->buf; } - inline uint8_t *buf(size_t i = 0) const { return &_buf->buf[i]; } - inline char *charptr(size_t i = 0) const { return (char*) &_buf->buf[i]; } - - virtual ~SBuffer(void) { - delete[] _buf; - } - - inline void setLen(const size_t len) { - uint16_t old_len = _buf->len; - _buf->len = (len <= _buf->size) ? len : _buf->size; - if (old_len < _buf->len) { - memset((void*) &_buf->buf[old_len], 0, _buf->len - old_len); - } - } - - void set8(const size_t offset, const uint8_t data) { - if (offset < _buf->len) { - _buf->buf[offset] = data; - } - } - - size_t add8(const uint8_t data) { - if (_buf->len < _buf->size) { - _buf->buf[_buf->len++] = data; - } - return _buf->len; - } - size_t add16(const uint16_t data) { - if (_buf->len < _buf->size - 1) { - _buf->buf[_buf->len++] = data; - _buf->buf[_buf->len++] = data >> 8; - } - return _buf->len; - } - size_t add32(const uint32_t data) { - if (_buf->len < _buf->size - 3) { - _buf->buf[_buf->len++] = data; - _buf->buf[_buf->len++] = data >> 8; - _buf->buf[_buf->len++] = data >> 16; - _buf->buf[_buf->len++] = data >> 24; - } - return _buf->len; - } - - size_t addBuffer(const SBuffer &buf2) { - if (len() + buf2.len() <= size()) { - for (uint32_t i = 0; i < buf2.len(); i++) { - _buf->buf[_buf->len++] = buf2.buf()[i]; - } - } - return _buf->len; - } - - size_t addBuffer(const char *buf2, size_t len2) { - if (len() + len2 <= size()) { - for (uint32_t i = 0; i < len2; i++) { - _buf->buf[_buf->len++] = pgm_read_byte(&buf2[i]); - } - } - return _buf->len; - } - - uint8_t get8(size_t offset) const { - if (offset < _buf->len) { - return _buf->buf[offset]; - } else { - return 0; - } - } - uint8_t read8(const size_t offset) const { - if (offset < len()) { - return _buf->buf[offset]; - } - return 0; - } - uint16_t get16(const size_t offset) const { - if (offset < len() - 1) { - return _buf->buf[offset] | (_buf->buf[offset+1] << 8); - } - return 0; - } - uint32_t get32(const size_t offset) const { - if (offset < len() - 3) { - return _buf->buf[offset] | (_buf->buf[offset+1] << 8) | - (_buf->buf[offset+2] << 16) | (_buf->buf[offset+3] << 24); - } - return 0; - } - uint64_t get64(const size_t offset) const { - if (offset < len() - 7) { - return (uint64_t)_buf->buf[offset] | ((uint64_t)_buf->buf[offset+1] << 8) | - ((uint64_t)_buf->buf[offset+2] << 16) | ((uint64_t)_buf->buf[offset+3] << 24) | - ((uint64_t)_buf->buf[offset+4] << 32) | ((uint64_t)_buf->buf[offset+5] << 40) | - ((uint64_t)_buf->buf[offset+6] << 48) | ((uint64_t)_buf->buf[offset+7] << 56); - } - return 0; - } - - SBuffer subBuffer(const size_t start, size_t len) const { - if (start >= _buf->len) { - len = 0; - } else if (start + len > _buf->len) { - len = _buf->len - start; - } - - SBuffer buf2(len); - memcpy(buf2.buf(), buf()+start, len); - buf2._buf->len = len; - return buf2; - } - - static SBuffer SBufferFromHex(const char *hex, size_t len) { - size_t buf_len = (len + 3) / 2; - SBuffer buf2(buf_len); - uint8_t val; - - for (; len > 1; len -= 2) { - val = asc2byte(*hex++) << 4; - val |= asc2byte(*hex++); - buf2.add8(val); - } - return buf2; - } - -protected: - - static uint8_t asc2byte(char chr) { - uint8_t rVal = 0; - if (isdigit(chr)) { rVal = chr - '0'; } - else if (chr >= 'A' && chr <= 'F') { rVal = chr + 10 - 'A'; } - else if (chr >= 'a' && chr <= 'f') { rVal = chr + 10 - 'a'; } - return rVal; - } - - static void unHex(const char* in, uint8_t *out, size_t len) { - } - -protected: - SBuffer_impl * _buf; - -} SBuffer; - -typedef class PreAllocatedSBuffer : public SBuffer { - -public: - PreAllocatedSBuffer(const size_t size, void * buffer) { - _buf = (SBuffer_impl*) buffer; - _buf->size = size - 4; - _buf->len = 0; - } - - ~PreAllocatedSBuffer(void) { - - _buf = nullptr; - } -} PreAllocatedSBuffer; -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_switch.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_switch.ino" -#define SWITCH_V2 -#ifdef SWITCH_V2 - - - - - - -const uint8_t SWITCH_PROBE_INTERVAL = 10; - -#include - -Ticker TickerSwitch; - -struct SWITCH { - unsigned long debounce = 0; - uint16_t no_pullup_mask = 0; - uint8_t state[MAX_SWITCHES] = { 0 }; - uint8_t last_state[MAX_SWITCHES]; - uint8_t hold_timer[MAX_SWITCHES] = { 0 }; - uint8_t virtual_state[MAX_SWITCHES]; - uint8_t present = 0; -} Switch; - - - -void SwitchPullupFlag(uint16 switch_bit) -{ - bitSet(Switch.no_pullup_mask, switch_bit); -} - -uint8_t SwitchLastState(uint8_t index) -{ - return Switch.last_state[index]; -} - -void SwitchSetVirtual(uint8_t index, uint8_t state) -{ - Switch.virtual_state[index] = state; -} - -uint8_t SwitchGetVirtual(uint8_t index) -{ - return Switch.virtual_state[index]; -} - - - -void SwitchProbe(void) -{ - if (uptime < 4) { return; } - - uint8_t state_filter = Settings.switch_debounce / SWITCH_PROBE_INTERVAL; - uint8_t force_high = (Settings.switch_debounce % 50) &1; - uint8_t force_low = (Settings.switch_debounce % 50) &2; - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - if (pin[GPIO_SWT1 +i] < 99) { - - if (1 == digitalRead(pin[GPIO_SWT1 +i])) { - - if (force_high) { - if (1 == Switch.virtual_state[i]) { - Switch.state[i] = state_filter; - } - } - - if (Switch.state[i] < state_filter) { - Switch.state[i]++; - if (state_filter == Switch.state[i]) { - Switch.virtual_state[i] = 1; - } - } - } else { - - if (force_low) { - if (0 == Switch.virtual_state[i]) { - Switch.state[i] = 0; - } - } - - if (Switch.state[i] > 0) { - Switch.state[i]--; - if (0 == Switch.state[i]) { - Switch.virtual_state[i] = 0; - } - } - } - } - } - TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); -} - -void SwitchInit(void) -{ - Switch.present = 0; - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - Switch.last_state[i] = 1; - if (pin[GPIO_SWT1 +i] < 99) { - Switch.present++; - pinMode(pin[GPIO_SWT1 +i], bitRead(Switch.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); - Switch.last_state[i] = digitalRead(pin[GPIO_SWT1 +i]); - } - Switch.virtual_state[i] = Switch.last_state[i]; - } - if (Switch.present) { TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); } -} - - - - - -void SwitchHandler(uint8_t mode) -{ - if (uptime < 4) { return; } - - uint8_t button = NOT_PRESSED; - uint8_t switchflag; - uint16_t loops_per_second = 1000 / Settings.switch_debounce; - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - if ((pin[GPIO_SWT1 +i] < 99) || (mode)) { - - if (Switch.hold_timer[i]) { - Switch.hold_timer[i]--; - if (0 == Switch.hold_timer[i]) { - SendKey(KEY_SWITCH, i +1, POWER_HOLD); - } - } - - button = Switch.virtual_state[i]; - - - - if (button != Switch.last_state[i]) { - switchflag = POWER_TOGGLE +1; - switch (Settings.switchmode[i]) { - case TOGGLE: - switchflag = POWER_TOGGLE; - break; - case FOLLOW: - switchflag = button &1; - break; - case FOLLOW_INV: - switchflag = ~button &1; - break; - case PUSHBUTTON: - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTON_INV: - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTON_TOGGLE: - if (button != Switch.last_state[i]) { - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTONHOLD: - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) { - Switch.hold_timer[i] = 0; - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTONHOLD_INV: - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) { - Switch.hold_timer[i] = 0; - switchflag = POWER_TOGGLE; - } - break; - } - - if (switchflag <= POWER_TOGGLE) { - if (!SendKey(KEY_SWITCH, i +1, switchflag)) { - ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); - } - } - - Switch.last_state[i] = button; - } - } - } -} - -void SwitchLoop(void) -{ - if (Switch.present) { - if (TimeReached(Switch.debounce)) { - SetNextTimeInterval(Switch.debounce, Settings.switch_debounce); - SwitchHandler(0); - } - } -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_udp.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_udp.ino" -#ifdef USE_EMULATION - -#define UDP_BUFFER_SIZE 200 -#define UDP_MSEARCH_SEND_DELAY 1500 - -#include -Ticker TickerMSearch; - -IPAddress udp_remote_ip; -uint16_t udp_remote_port; - -bool udp_connected = false; -bool udp_response_mutex = false; - - - - - -const char URN_BELKIN_DEVICE[] PROGMEM = "urn:belkin:device:**"; -const char URN_BELKIN_DEVICE_CAP[] PROGMEM = "urn:Belkin:device:**"; -const char UPNP_ROOTDEVICE[] PROGMEM = "upnp:rootdevice"; -const char SSDPSEARCH_ALL[] PROGMEM = "ssdpsearch:all"; -const char SSDP_ALL[] PROGMEM = "ssdp:all"; - - - - - -bool UdpDisconnect(void) -{ - if (udp_connected) { - PortUdp.flush(); - WiFiUDP::stopAll(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_MULTICAST_DISABLED)); - udp_connected = false; - } - return udp_connected; -} - -bool UdpConnect(void) -{ - if (!udp_connected) { - - if (PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), 1900)) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED)); - udp_response_mutex = false; - udp_connected = true; - } else { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_JOIN_FAILED)); - udp_connected = false; - } - } - return udp_connected; -} - -void PollUdp(void) -{ - if (udp_connected) { - if (PortUdp.parsePacket()) { - char packet_buffer[UDP_BUFFER_SIZE]; - - int len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1); - packet_buffer[len] = 0; - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); - - - - if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { - udp_response_mutex = true; - - udp_remote_ip = PortUdp.remoteIP(); - udp_remote_port = PortUdp.remotePort(); - - - - - uint32_t response_delay = UDP_MSEARCH_SEND_DELAY + ((millis() &0x7) * 100); - - LowerCase(packet_buffer, packet_buffer); - RemoveSpace(packet_buffer); - -#ifdef USE_EMULATION_WEMO - if (EMUL_WEMO == Settings.flag2.emulation) { - if (strstr_P(packet_buffer, URN_BELKIN_DEVICE) != nullptr) { - TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1); - return; - } - else if ((strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || - (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || - (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { - TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2); - return; - } - } -#endif - -#ifdef USE_EMULATION_HUE - if (EMUL_HUE == Settings.flag2.emulation) { - if ((strstr_P(packet_buffer, PSTR(":device:basic:1")) != nullptr) || - (strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || - (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || - (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { - TickerMSearch.attach_ms(response_delay, HueRespondToMSearch); - return; - } - } -#endif - - udp_response_mutex = false; - } - - } - delay(1); - } -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_wifi.ino" -# 24 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_wifi.ino" -#ifndef WIFI_RSSI_THRESHOLD -#define WIFI_RSSI_THRESHOLD 10 -#endif -#ifndef WIFI_RESCAN_MINUTES -#define WIFI_RESCAN_MINUTES 44 -#endif - -const uint8_t WIFI_CONFIG_SEC = 180; -const uint8_t WIFI_CHECK_SEC = 20; -const uint8_t WIFI_RETRY_OFFSET_SEC = 20; - -#include - -struct WIFI { - uint32_t last_event = 0; - uint32_t downtime = 0; - uint16_t link_count = 0; - uint8_t counter; - uint8_t retry_init; - uint8_t retry; - uint8_t status; - uint8_t wps_result; - uint8_t config_type = 0; - uint8_t config_counter = 0; - uint8_t mdns_begun = 0; - uint8_t scan_state; - uint8_t bssid[6]; -} Wifi; - -int WifiGetRssiAsQuality(int rssi) -{ - int quality = 0; - - if (rssi <= -100) { - quality = 0; - } else if (rssi >= -50) { - quality = 100; - } else { - quality = 2 * (rssi + 100); - } - return quality; -} - -bool WifiConfigCounter(void) -{ - if (Wifi.config_counter) { - Wifi.config_counter = WIFI_CONFIG_SEC; - } - return (Wifi.config_counter); -} - -extern "C" { -#include "user_interface.h" -} - -void WifiWpsStatusCallback(wps_cb_status status); - -void WifiWpsStatusCallback(wps_cb_status status) -{ -# 92 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_wifi.ino" - Wifi.wps_result = status; - if (WPS_CB_ST_SUCCESS == Wifi.wps_result) { - wifi_wps_disable(); - } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_WPS_FAILED_WITH_STATUS " %d"), Wifi.wps_result); - Wifi.config_counter = 2; - } -} - -bool WifiWpsConfigDone(void) -{ - return (!Wifi.wps_result); -} - -bool WifiWpsConfigBegin(void) -{ - Wifi.wps_result = 99; - if (!wifi_wps_disable()) { return false; } - if (!wifi_wps_enable(WPS_TYPE_PBC)) { return false; } - if (!wifi_set_wps_cb((wps_st_cb_t) &WifiWpsStatusCallback)) { return false; } - if (!wifi_wps_start()) { return false; } - return true; -} - -void WifiConfig(uint8_t type) -{ - if (!Wifi.config_type) { - if ((WIFI_RETRY == type) || (WIFI_WAIT == type)) { return; } -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - WiFi.disconnect(); - Wifi.config_type = type; - -#ifndef USE_WPS - if (WIFI_WPSCONFIG == Wifi.config_type) { Wifi.config_type = WIFI_MANAGER; } -#endif -#ifndef USE_WEBSERVER - if (WIFI_MANAGER == Wifi.config_type) { Wifi.config_type = WIFI_SMARTCONFIG; } -#endif -#ifndef USE_SMARTCONFIG - if (WIFI_SMARTCONFIG == Wifi.config_type) { Wifi.config_type = WIFI_SERIAL; } -#endif - - Wifi.config_counter = WIFI_CONFIG_SEC; - Wifi.counter = Wifi.config_counter +5; - blinks = 1999; - if (WIFI_RESTART == Wifi.config_type) { - restart_flag = 2; - } - else if (WIFI_SERIAL == Wifi.config_type) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_6_SERIAL " " D_ACTIVE_FOR_3_MINUTES)); - } -#ifdef USE_SMARTCONFIG - else if (WIFI_SMARTCONFIG == Wifi.config_type) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_1_SMARTCONFIG " " D_ACTIVE_FOR_3_MINUTES)); - WiFi.mode(WIFI_STA); - WiFi.beginSmartConfig(); - } -#endif -#ifdef USE_WPS - 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_3_MINUTES)); - } else { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_3_WPSCONFIG " " D_FAILED_TO_START)); - Wifi.config_counter = 3; - } - } -#endif -#ifdef USE_WEBSERVER - else if (WIFI_MANAGER == Wifi.config_type || WIFI_MANAGER_RESET_ONLY == Wifi.config_type) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_2_WIFIMANAGER " " D_ACTIVE_FOR_3_MINUTES)); - WifiManagerBegin(WIFI_MANAGER_RESET_ONLY == Wifi.config_type); - } -#endif - } -} - -void WiFiSetSleepMode(void) -{ -# 186 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/support_wifi.ino" -#if defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) -#else - if (sleep && Settings.flag3.sleep_normal) { - WiFi.setSleepMode(WIFI_LIGHT_SLEEP); - } else { - WiFi.setSleepMode(WIFI_MODEM_SLEEP); - } -#endif -} - -void WifiBegin(uint8_t flag, uint8_t channel) -{ - const char kWifiPhyMode[] = " BGN"; - -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_PATCH_ISSUE_2186)); - WiFi.mode(WIFI_OFF); -#endif - - WiFi.persistent(false); - WiFi.disconnect(true); - delay(200); - WiFi.mode(WIFI_STA); - WiFiSetSleepMode(); - - - if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } - - switch (flag) { - case 0: - case 1: - Settings.sta_active = flag; - break; - case 2: - Settings.sta_active ^= 1; - } - if ('\0' == Settings.sta_ssid[Settings.sta_active][0]) { Settings.sta_active ^= 1; } - if (Settings.ip_address[0]) { - WiFi.config(Settings.ip_address[0], Settings.ip_address[1], Settings.ip_address[2], Settings.ip_address[3]); - } - WiFi.hostname(my_hostname); - if (channel) { - WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active], channel, Wifi.bssid); - } else { - WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active]); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s " D_IN_MODE " 11%c " D_AS " %s..."), - Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); -} - -void WifiBeginAfterScan() -{ - static int8_t best_network_db; - - - if (0 == Wifi.scan_state) { return; } - - if (1 == Wifi.scan_state) { - memset((void*) &Wifi.bssid, 0, sizeof(Wifi.bssid)); - best_network_db = -127; - Wifi.scan_state = 3; - } - - if (2 == Wifi.scan_state) { - uint8_t* bssid = WiFi.BSSID(); - memcpy((void*) &Wifi.bssid, (void*) bssid, sizeof(Wifi.bssid)); - best_network_db = WiFi.RSSI(); - if (best_network_db < -WIFI_RSSI_THRESHOLD) { best_network_db += WIFI_RSSI_THRESHOLD; } - Wifi.scan_state = 3; - } - - if (3 == Wifi.scan_state) { - if (WiFi.scanComplete() != WIFI_SCAN_RUNNING) { - WiFi.scanNetworks(true); - Wifi.scan_state++; - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR("Network (re)scan started...")); - return; - } - } - int8_t wifi_scan_result = WiFi.scanComplete(); - - if (4 == Wifi.scan_state) { - if (wifi_scan_result != WIFI_SCAN_RUNNING) { - Wifi.scan_state++; - } - } - - if (5 == Wifi.scan_state) { - int32_t channel = 0; - int8_t ap = 3; - uint8_t last_bssid[6]; - memcpy((void*) &last_bssid, (void*) &Wifi.bssid, sizeof(last_bssid)); - - if (wifi_scan_result > 0) { - - for (uint32_t i = 0; i < wifi_scan_result; ++i) { - - String ssid_scan; - int32_t rssi_scan; - uint8_t sec_scan; - uint8_t* bssid_scan; - int32_t chan_scan; - bool hidden_scan; - - WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, bssid_scan, chan_scan, hidden_scan); - - bool known = false; - uint32_t j; - for (j = 0; j < 2; j++) { - if (ssid_scan == Settings.sta_ssid[j]) { - known = true; - if (rssi_scan > best_network_db) { - if (sec_scan == ENC_TYPE_NONE || Settings.sta_pwd[j]) { - best_network_db = (int8_t)rssi_scan; - channel = chan_scan; - ap = j; - memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid)); - } - } - break; - } - } - char hex_char[18]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI "Network %d, AP%c, SSId %s, Channel %d, BSSId %s, RSSI %d, Encryption %d"), - i, - (known) ? (j) ? '2' : '1' : '-', - ssid_scan.c_str(), - chan_scan, - ToHex_P((unsigned char*)bssid_scan, 6, hex_char, sizeof(hex_char), ':'), - rssi_scan, - (sec_scan == ENC_TYPE_NONE) ? 0 : 1); - delay(0); - } - WiFi.scanDelete(); - delay(0); - } - Wifi.scan_state = 0; - - for (uint32_t i = 0; i < sizeof(Wifi.bssid); i++) { - if (last_bssid[i] != Wifi.bssid[i]) { - WifiBegin(ap, channel); - break; - } - } - } -} - -uint16_t WifiLinkCount() -{ - return Wifi.link_count; -} - -String WifiDowntime() -{ - return GetDuration(Wifi.downtime); -} - -void WifiSetState(uint8_t state) -{ - if (state == global_state.wifi_down) { - if (state) { - rules_flag.wifi_connected = 1; - Wifi.link_count++; - Wifi.downtime += UpTime() - Wifi.last_event; - } else { - rules_flag.wifi_disconnected = 1; - Wifi.last_event = UpTime(); - } - } - global_state.wifi_down = state ^1; -} - -void WifiCheckIp(void) -{ - if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { - WifiSetState(1); - Wifi.counter = WIFI_CHECK_SEC; - Wifi.retry = Wifi.retry_init; - AddLog_P((Wifi.status != WL_CONNECTED) ? LOG_LEVEL_INFO : LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CONNECTED)); - if (Wifi.status != WL_CONNECTED) { - - Settings.ip_address[1] = (uint32_t)WiFi.gatewayIP(); - Settings.ip_address[2] = (uint32_t)WiFi.subnetMask(); - Settings.ip_address[3] = (uint32_t)WiFi.dnsIP(); - } - Wifi.status = WL_CONNECTED; -#ifdef USE_DISCOVERY -#ifdef WEBSERVER_ADVERTISE - if (2 == Wifi.mdns_begun) { - MDNS.update(); - AddLog_P(LOG_LEVEL_DEBUG_MORE, D_LOG_MDNS, "MDNS.update"); - } -#endif -#endif - } else { - WifiSetState(0); - uint8_t wifi_config_tool = Settings.sta_config; - 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)); - Wifi.status = 0; - Wifi.retry = Wifi.retry_init; - break; - case WL_NO_SSID_AVAIL: - 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_init; - } else { - if (Wifi.retry > (Wifi.retry_init / 2)) { - Wifi.retry = Wifi.retry_init / 2; - } - 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 (Wifi.retry > (Wifi.retry_init / 2)) { - Wifi.retry = Wifi.retry_init / 2; - } - else if (Wifi.retry) { - Wifi.retry = 0; - } - break; - default: - if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); - } else { - if (('\0' == Settings.sta_ssid[0][0]) && ('\0' == Settings.sta_ssid[1][0])) { - wifi_config_tool = WIFI_CONFIG_NO_SSID; - Wifi.retry = 0; - } else { - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_ATTEMPTING_CONNECTION)); - } - } - } - if (Wifi.retry) { - if (Settings.flag3.use_wifi_scan) { - if (Wifi.retry_init == Wifi.retry) { - Wifi.scan_state = 1; - } - } else { - if (Wifi.retry_init == Wifi.retry) { - WifiBegin(3, 0); - } - if ((Settings.sta_config != WIFI_WAIT) && ((Wifi.retry_init / 2) == Wifi.retry)) { - WifiBegin(2, 0); - } - } - Wifi.counter = 1; - Wifi.retry--; - } else { - WifiConfig(wifi_config_tool); - Wifi.counter = 1; - Wifi.retry = Wifi.retry_init; - } - } -} - -void WifiCheck(uint8_t param) -{ - Wifi.counter--; - switch (param) { - case WIFI_SERIAL: - case WIFI_SMARTCONFIG: - case WIFI_MANAGER: - case WIFI_WPSCONFIG: - WifiConfig(param); - break; - default: - if (Wifi.config_counter) { - Wifi.config_counter--; - Wifi.counter = Wifi.config_counter +5; - if (Wifi.config_counter) { -#ifdef USE_SMARTCONFIG - if ((WIFI_SMARTCONFIG == Wifi.config_type) && WiFi.smartConfigDone()) { - Wifi.config_counter = 0; - } -#endif -#ifdef USE_WPS - if ((WIFI_WPSCONFIG == Wifi.config_type) && WifiWpsConfigDone()) { - Wifi.config_counter = 0; - } -#endif - if (!Wifi.config_counter) { - if (strlen(WiFi.SSID().c_str())) { - strlcpy(Settings.sta_ssid[0], WiFi.SSID().c_str(), sizeof(Settings.sta_ssid[0])); - } - if (strlen(WiFi.psk().c_str())) { - strlcpy(Settings.sta_pwd[0], WiFi.psk().c_str(), sizeof(Settings.sta_pwd[0])); - } - Settings.sta_active = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_1_SMARTCONFIG D_CMND_SSID "1 %s"), Settings.sta_ssid[0]); - } - } - if (!Wifi.config_counter) { -#ifdef USE_SMARTCONFIG - if (WIFI_SMARTCONFIG == Wifi.config_type) { WiFi.stopSmartConfig(); } -#endif - - restart_flag = 2; - } - } else { - if (Wifi.scan_state) { WifiBeginAfterScan(); } - - 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) && !Wifi.config_type) { - WifiSetState(1); - - if (Settings.flag3.use_wifi_rescan) { - if (!(uptime % (60 * WIFI_RESCAN_MINUTES))) { - Wifi.scan_state = 2; - } - } - -#ifdef FIRMWARE_MINIMAL - if (1 == RtcSettings.ota_loader) { - RtcSettings.ota_loader = 0; - ota_state_flag = 3; - } -#endif - -#ifdef USE_DISCOVERY - if (Settings.flag3.mdns_enabled) { - if (!Wifi.mdns_begun) { - - - - - - Wifi.mdns_begun = (uint8_t)MDNS.begin(my_hostname); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Wifi.mdns_begun) ? D_INITIALIZED : D_FAILED); - - } - } -#endif - -#ifdef USE_WEBSERVER - if (Settings.webserver) { - StartWebserver(Settings.webserver, WiFi.localIP()); -#ifdef USE_DISCOVERY -#ifdef WEBSERVER_ADVERTISE - if (1 == Wifi.mdns_begun) { - Wifi.mdns_begun = 2; - MDNS.addService("http", "tcp", WEB_PORT); - } -#endif -#endif - } else { - StopWebserver(); - } -#ifdef USE_EMULATION - if (Settings.flag2.emulation) { UdpConnect(); } -#endif -#endif - -#ifdef USE_KNX - if (!knx_started && Settings.flag.knx_enabled) { - KNXStart(); - knx_started = true; - } -#endif - - } else { - WifiSetState(0); -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - Wifi.mdns_begun = 0; -#ifdef USE_KNX - knx_started = false; -#endif - } - } - } -} - -int WifiState(void) -{ - int state = -1; - - if (!global_state.wifi_down) { state = WIFI_RESTART; } - if (Wifi.config_type) { state = Wifi.config_type; } - return state; -} - -void WifiConnect(void) -{ - WifiSetState(0); - WiFi.persistent(false); - Wifi.status = 0; - Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); - Wifi.retry = Wifi.retry_init; - Wifi.counter = 1; -} - - - -void WifiDisconnect(void) -{ - - WiFi.persistent(true); - ETS_UART_INTR_DISABLE(); - wifi_station_disconnect(); - ETS_UART_INTR_ENABLE(); - WiFi.persistent(false); -} - -void EspRestart(void) -{ - delay(100); - if (Settings.flag.mqtt_enabled) MqttDisconnect(); - WifiDisconnect(); - - ESP.reset(); -} -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_01_webserver.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_01_webserver.ino" -#ifdef USE_WEBSERVER - - - - - - - -#define XDRV_01 1 - -#ifndef WIFI_SOFT_AP_CHANNEL -#define WIFI_SOFT_AP_CHANNEL 1 -#endif - -const uint16_t CHUNKED_BUFFER_SIZE = 400; - -const uint16_t HTTP_REFRESH_TIME = 2345; -#define HTTP_RESTART_RECONNECT_TIME 9000 -#define HTTP_OTA_RESTART_RECONNECT_TIME 20000 - -#include -#include - -#ifdef USE_RF_FLASH -uint8_t *efm8bb1_update = nullptr; -#endif - -enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1 }; - -static const char * HEADER_KEYS[] = { "User-Agent", }; - -const char HTTP_HEADER[] PROGMEM = - "" - "" - "" - "" - "%s - %s" - - ""; - -const char HTTP_HEAD_STYLE1[] PROGMEM = - "" - - "" - "" - "
" -#ifdef FIRMWARE_MINIMAL - "

" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "

" -#endif - "
" -#ifdef LANGUAGE_MODULE_NAME - "

" D_MODULE " %s

" -#else - "

%s " D_MODULE "

" -#endif - "

%s

"; - -const char HTTP_MSG_SLIDER1[] PROGMEM = - "
" D_COLDLIGHT "" D_WARMLIGHT "
" - "
"; -const char HTTP_MSG_SLIDER2[] PROGMEM = - "
" D_DARKLIGHT "" D_BRIGHTLIGHT "
" - "
"; -const char HTTP_MSG_RSTRT[] PROGMEM = - "
" D_DEVICE_WILL_RESTART "

"; - -const char HTTP_FORM_LOGIN[] PROGMEM = - "
" - "" - "

" D_USER "

" - "

" D_PASSWORD "

" - "
" - "" - "
"; - -const char HTTP_FORM_TEMPLATE[] PROGMEM = - "
 " D_TEMPLATE_PARAMETERS " " - "
"; -const char HTTP_FORM_TEMPLATE_FLAG[] PROGMEM = - "

" - "
 " D_TEMPLATE_FLAGS " 

" - - "

"; - -const char HTTP_FORM_MODULE[] PROGMEM = - "
 " D_MODULE_PARAMETERS " " - "" - "

" D_MODULE_TYPE " (%s)

" - "
"; - -const char HTTP_FORM_WIFI[] PROGMEM = - "
 " D_WIFI_PARAMETERS " " - "" - "

" D_AP1_SSID " (" STA_SSID1 ")

" - "

" D_AP1_PASSWORD "

" - "

" D_AP2_SSID " (" STA_SSID2 ")

" - "

" D_AP2_PASSWORD "

" - "

" D_HOSTNAME " (%s)

"; - -const char HTTP_FORM_LOG1[] PROGMEM = - "
 " D_LOGGING_PARAMETERS " " - ""; -const char HTTP_FORM_LOG2[] PROGMEM = - "

" D_SYSLOG_HOST " (" SYS_LOG_HOST ")

" - "

" D_SYSLOG_PORT " (" STR(SYS_LOG_PORT) ")

" - "

" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

"; - -const char HTTP_FORM_OTHER[] PROGMEM = - "
 " D_OTHER_PARAMETERS " " - "" - "

" - "
 " D_TEMPLATE " " - "

" - "

" D_ACTIVATE "

" - "
" - "
" - "" D_WEB_ADMIN_PASSWORD "

" - "
" - "" D_MQTT_ENABLE "
" - "
"; - -const char HTTP_FORM_END[] PROGMEM = - "
" - "" - "
"; - -const char HTTP_FORM_RST[] PROGMEM = - "
" - "
 " D_RESTORE_CONFIGURATION " "; -const char HTTP_FORM_UPG[] PROGMEM = - "
" - "
 " D_UPGRADE_BY_WEBSERVER " " - "
" - "
" D_OTA_URL "

" - "
" - "


" - "
 " D_UPGRADE_BY_FILE_UPLOAD " "; -const char HTTP_FORM_RST_UPG[] PROGMEM = - "
" - "

" - "
" - "
" - "
" - ""; - -const char HTTP_FORM_CMND[] PROGMEM = - "


" - "
" - "
" - - ""; - -const char HTTP_TABLE100[] PROGMEM = - "
"; - -const char HTTP_COUNTER[] PROGMEM = - "
"; - -const char HTTP_END[] PROGMEM = - "" - "" - "" - ""; - -const char HTTP_DEVICE_CONTROL[] PROGMEM = ""; -const char HTTP_DEVICE_STATE[] PROGMEM = ""; - -enum ButtonTitle { - BUTTON_RESTART, BUTTON_RESET_CONFIGURATION, - BUTTON_MAIN, BUTTON_CONFIGURATION, BUTTON_INFORMATION, BUTTON_FIRMWARE_UPGRADE, BUTTON_CONSOLE, - BUTTON_MODULE, BUTTON_WIFI, BUTTON_LOGGING, BUTTON_OTHER, BUTTON_TEMPLATE, BUTTON_BACKUP, BUTTON_RESTORE }; -const char kButtonTitle[] PROGMEM = - D_RESTART "|" D_RESET_CONFIGURATION "|" - D_MAIN_MENU "|" D_CONFIGURATION "|" D_INFORMATION "|" D_FIRMWARE_UPGRADE "|" D_CONSOLE "|" - D_CONFIGURE_MODULE "|" D_CONFIGURE_WIFI"|" D_CONFIGURE_LOGGING "|" D_CONFIGURE_OTHER "|" D_CONFIGURE_TEMPLATE "|" D_BACKUP_CONFIGURATION "|" D_RESTORE_CONFIGURATION; -const char kButtonAction[] PROGMEM = - ".|rt|" - ".|cn|in|up|cs|" - "md|wi|lg|co|tp|dl|rs"; -const char kButtonConfirm[] PROGMEM = D_CONFIRM_RESTART "|" D_CONFIRM_RESET_CONFIGURATION; - -enum CTypes { CT_HTML, CT_PLAIN, CT_XML, CT_JSON, CT_STREAM }; -const char kContentTypes[] PROGMEM = "text/html|text/plain|text/xml|application/json|application/octet-stream"; - -const char kLoggingOptions[] PROGMEM = D_SERIAL_LOG_LEVEL "|" D_WEB_LOG_LEVEL "|" D_SYS_LOG_LEVEL; -const char kLoggingLevels[] PROGMEM = D_NONE "|" D_ERROR "|" D_INFO "|" D_DEBUG "|" D_MORE_DEBUG; - -const char kEmulationOptions[] PROGMEM = D_NONE "|" D_BELKIN_WEMO "|" D_HUE_BRIDGE; - -const char kUploadErrors[] PROGMEM = - D_UPLOAD_ERR_1 "|" D_UPLOAD_ERR_2 "|" D_UPLOAD_ERR_3 "|" D_UPLOAD_ERR_4 "|" D_UPLOAD_ERR_5 "|" D_UPLOAD_ERR_6 "|" D_UPLOAD_ERR_7 "|" D_UPLOAD_ERR_8 "|" D_UPLOAD_ERR_9 -#ifdef USE_RF_FLASH - "|" D_UPLOAD_ERR_10 "|" D_UPLOAD_ERR_11 "|" D_UPLOAD_ERR_12 "|" D_UPLOAD_ERR_13 -#endif - ; - -const uint16_t DNS_PORT = 53; -enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER, HTTP_MANAGER_RESET_ONLY}; - -DNSServer *DnsServer; -ESP8266WebServer *WebServer; - -struct WEB { - String chunk_buffer = ""; - bool reset_web_log_flag = false; - uint8_t state = HTTP_OFF; - uint8_t upload_error = 0; - uint8_t upload_file_type; - uint8_t upload_progress_dot_count; - uint8_t config_block_count = 0; - uint8_t config_xor_on = 0; - uint8_t config_xor_on_set = CONFIG_FILE_XOR; -} Web; - - -static void WebGetArg(const char* arg, char* out, size_t max) -{ - String s = WebServer->arg(arg); - strlcpy(out, s.c_str(), max); - -} - -static bool WifiIsInManagerMode(){ - return (HTTP_MANAGER == Web.state || HTTP_MANAGER_RESET_ONLY == Web.state); -} - -void ShowWebSource(uint32_t source) -{ - if ((source > 0) && (source < SRC_MAX)) { - char stemp1[20]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SRC: %s from %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource), WebServer->client().remoteIP().toString().c_str()); - } -} - -void ExecuteWebCommand(char* svalue, uint32_t source) -{ - ShowWebSource(source); - ExecuteCommand(svalue, SRC_IGNORE); -} - -void StartWebserver(int type, IPAddress ipweb) -{ - if (!Settings.web_refresh) { Settings.web_refresh = HTTP_REFRESH_TIME; } - if (!Web.state) { - if (!WebServer) { - WebServer = new ESP8266WebServer((HTTP_MANAGER == type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT); - WebServer->on("/", HandleRoot); - WebServer->onNotFound(HandleNotFound); - WebServer->on("/up", HandleUpgradeFirmware); - WebServer->on("/u1", HandleUpgradeFirmwareStart); - WebServer->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); - WebServer->on("/u2", HTTP_OPTIONS, HandlePreflightRequest); - WebServer->on("/cs", HTTP_GET, HandleConsole); - WebServer->on("/cs", HTTP_OPTIONS, HandlePreflightRequest); - WebServer->on("/cm", HandleHttpCommand); -#ifndef FIRMWARE_MINIMAL - WebServer->on("/cn", HandleConfiguration); - WebServer->on("/md", HandleModuleConfiguration); - WebServer->on("/wi", HandleWifiConfiguration); - WebServer->on("/lg", HandleLoggingConfiguration); - WebServer->on("/tp", HandleTemplateConfiguration); - WebServer->on("/co", HandleOtherConfiguration); - WebServer->on("/dl", HandleBackupConfiguration); - WebServer->on("/rs", HandleRestoreConfiguration); - WebServer->on("/rt", HandleResetConfiguration); - WebServer->on("/in", HandleInformation); - XdrvCall(FUNC_WEB_ADD_HANDLER); - XsnsCall(FUNC_WEB_ADD_HANDLER); -#endif - } - Web.reset_web_log_flag = false; - - - - WebServer->collectHeaders(HEADER_KEYS, sizeof(HEADER_KEYS)/sizeof(char*)); - - WebServer->begin(); - } - if (Web.state != type) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), my_hostname, (Wifi.mdns_begun) ? ".local" : "", ipweb.toString().c_str()); - rules_flag.http_init = 1; - } - if (type) { Web.state = type; } -} - -void StopWebserver(void) -{ - if (Web.state) { - WebServer->close(); - Web.state = HTTP_OFF; - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_STOPPED)); - } -} - -void WifiManagerBegin(bool reset_only) -{ - - if (!global_state.wifi_down) { - WiFi.mode(WIFI_AP_STA); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION)); - } else { - WiFi.mode(WIFI_AP); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_WIFIMANAGER_SET_ACCESSPOINT)); - } - - StopWebserver(); - - DnsServer = new DNSServer(); - - int channel = WIFI_SOFT_AP_CHANNEL; - if ((channel < 1) || (channel > 13)) { channel = 1; } - WiFi.softAP(my_hostname, nullptr, channel); - - delay(500); - - DnsServer->setErrorReplyCode(DNSReplyCode::NoError); - DnsServer->start(DNS_PORT, "*", WiFi.softAPIP()); - - StartWebserver((reset_only ? HTTP_MANAGER_RESET_ONLY : HTTP_MANAGER), WiFi.softAPIP()); -} - -void PollDnsWebserver(void) -{ - if (DnsServer) { DnsServer->processNextRequest(); } - if (WebServer) { WebServer->handleClient(); } -} - - - -bool WebAuthenticate(void) -{ - if (Settings.web_password[0] != 0 && HTTP_MANAGER_RESET_ONLY != Web.state) { - return WebServer->authenticate(WEB_USERNAME, Settings.web_password); - } else { - return true; - } -} - -bool HttpCheckPriviledgedAccess(bool autorequestauth = true) -{ - if (HTTP_USER == Web.state) { - HandleRoot(); - return false; - } - if (autorequestauth && !WebAuthenticate()) { - WebServer->requestAuthentication(); - return false; - } - return true; -} - -void WSHeaderSend(void) -{ - WebServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate")); - WebServer->sendHeader(F("Pragma"), F("no-cache")); - WebServer->sendHeader(F("Expires"), F("-1")); -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 - WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); -#endif -} - - - - - -void WSSend(int code, int ctype, const String& content) -{ - char ct[25]; - WebServer->send(code, GetTextIndexed(ct, sizeof(ct), ctype, kContentTypes), content); -} - - - - - -void WSContentBegin(int code, int ctype) -{ - WebServer->client().flush(); - WSHeaderSend(); -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 - WebServer->sendHeader(F("Accept-Ranges"),F("none")); - WebServer->sendHeader(F("Transfer-Encoding"),F("chunked")); -#endif - WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); - WSSend(code, ctype, ""); - Web.chunk_buffer = ""; -} - -void _WSContentSend(const String& content) -{ - size_t len = content.length(); - -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 - const char * footer = "\r\n"; - char chunk_size[11]; - sprintf(chunk_size, "%x\r\n", len); - WebServer->sendContent(String() + chunk_size + content + footer); -#else - WebServer->sendContent(content); -#endif - -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("WSContentSend")); -#endif - DEBUG_CORE_LOG(PSTR("WEB: Chunk size %d"), len); -} - -void WSContentFlush() -{ - if (Web.chunk_buffer.length() > 0) { - _WSContentSend(Web.chunk_buffer); - Web.chunk_buffer = ""; - } -} - -void _WSContentSendBuffer(void) -{ - int len = strlen(mqtt_data); - - if (0 == len) { - return; - } - else if (len == sizeof(mqtt_data)) { - AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: Content too large")); - } - else if (len < CHUNKED_BUFFER_SIZE) { - Web.chunk_buffer += mqtt_data; - len = Web.chunk_buffer.length(); - } - - if (len >= CHUNKED_BUFFER_SIZE) { - WSContentFlush(); - } - if (strlen(mqtt_data) >= CHUNKED_BUFFER_SIZE) { - _WSContentSend(mqtt_data); - } -} - -void WSContentSend_P(const char* formatP, ...) -{ - - va_list arg; - va_start(arg, formatP); - vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); - va_end(arg); - - _WSContentSendBuffer(); -} - -void WSContentSend_PD(const char* formatP, ...) -{ - - va_list arg; - va_start(arg, formatP); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); - va_end(arg); - - if (D_DECIMAL_SEPARATOR[0] != '.') { - for (uint32_t i = 0; i < len; i++) { - if ('.' == mqtt_data[i]) { - mqtt_data[i] = D_DECIMAL_SEPARATOR[0]; - } - } - } - - _WSContentSendBuffer(); -} - -void WSContentStart_P(const char* title, bool auth) -{ - if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) { - return WebServer->requestAuthentication(); - } - - WSContentBegin(200, CT_HTML); - - if (title != nullptr) { - char ctitle[strlen_P(title) +1]; - strcpy_P(ctitle, title); - WSContentSend_P(HTTP_HEADER, Settings.friendlyname[0], ctitle); - } -} - -void WSContentStart_P(const char* title) -{ - WSContentStart_P(title, true); -} - -void WSContentSendStyle_P(const char* formatP, ...) -{ - if (WifiIsInManagerMode()) { - if (WifiConfigCounter()) { - WSContentSend_P(HTTP_SCRIPT_COUNTER); - } - } - WSContentSend_P(HTTP_HEAD_LAST_SCRIPT); - - WSContentSend_P(HTTP_HEAD_STYLE1, WebColor(COL_FORM), WebColor(COL_INPUT), WebColor(COL_INPUT_TEXT), WebColor(COL_INPUT), WebColor(COL_INPUT_TEXT), WebColor(COL_CONSOLE), WebColor(COL_CONSOLE_TEXT), WebColor(COL_BACKGROUND)); - WSContentSend_P(HTTP_HEAD_STYLE2, WebColor(COL_BUTTON), WebColor(COL_BUTTON_TEXT), WebColor(COL_BUTTON_HOVER), WebColor(COL_BUTTON_RESET), WebColor(COL_BUTTON_RESET_HOVER), WebColor(COL_BUTTON_SAVE), WebColor(COL_BUTTON_SAVE_HOVER)); - if (formatP != nullptr) { - - va_list arg; - va_start(arg, formatP); - vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); - va_end(arg); - _WSContentSendBuffer(); - } - WSContentSend_P(HTTP_HEAD_STYLE3, WebColor(COL_TEXT), -#ifdef FIRMWARE_MINIMAL - WebColor(COL_TEXT_WARNING), -#endif - ModuleName().c_str(), Settings.friendlyname[0]); - if (Settings.flag3.gui_hostname_ip) { - bool lip = (static_cast(WiFi.localIP()) != 0); - bool sip = (static_cast(WiFi.softAPIP()) != 0); - WSContentSend_P(PSTR("

%s%s (%s%s%s)

"), - my_hostname, - (Wifi.mdns_begun) ? ".local" : "", - (lip) ? WiFi.localIP().toString().c_str() : "", - (lip && sip) ? ", " : "", - (sip) ? WiFi.softAPIP().toString().c_str() : ""); - } - WSContentSend_P(PSTR("")); -} - -void WSContentSendStyle(void) -{ - WSContentSendStyle_P(nullptr); -} - -void WSContentButton(uint32_t title_index) -{ - char action[4]; - char title[100]; - - if (title_index <= BUTTON_RESET_CONFIGURATION) { - char confirm[100]; - WSContentSend_P(PSTR("

"), - GetTextIndexed(action, sizeof(action), title_index, kButtonAction), - GetTextIndexed(confirm, sizeof(confirm), title_index, kButtonConfirm), - (!title_index) ? "rst" : "non", - GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); - } else { - WSContentSend_P(PSTR("

"), - GetTextIndexed(action, sizeof(action), title_index, kButtonAction), - GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); - } -} - -void WSContentSpaceButton(uint32_t title_index) -{ - WSContentSend_P(PSTR("
")); - WSContentButton(title_index); -} - -void WSContentEnd(void) -{ - WSContentFlush(); - _WSContentSend(""); - WebServer->client().stop(); -} - -void WSContentStop(void) -{ - if (WifiIsInManagerMode()) { - if (WifiConfigCounter()) { - WSContentSend_P(HTTP_COUNTER); - } - } - WSContentSend_P(HTTP_END, my_version); - WSContentEnd(); -} - - - -void WebRestart(uint32_t type) -{ - - - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTART); - - bool reset_only = (HTTP_MANAGER_RESET_ONLY == Web.state); - - WSContentStart_P((type) ? S_SAVE_CONFIGURATION : S_RESTART, !reset_only); - WSContentSend_P(HTTP_SCRIPT_RELOAD); - WSContentSendStyle(); - if (type) { - WSContentSend_P(PSTR("
" D_CONFIGURATION_SAVED "
")); - if (2 == type) { - WSContentSend_P(PSTR("
" D_TRYING_TO_CONNECT "
")); - } - WSContentSend_P(PSTR("
")); - } - WSContentSend_P(HTTP_MSG_RSTRT); - if (HTTP_MANAGER == Web.state || reset_only) { - Web.state = HTTP_ADMIN; - } else { - WSContentSpaceButton(BUTTON_MAIN); - } - WSContentStop(); - - ShowWebSource(SRC_WEBGUI); - restart_flag = 2; -} - - - -void HandleWifiLogin(void) -{ - WSContentStart_P(S_CONFIGURE_WIFI, false); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_LOGIN); - - if (HTTP_MANAGER_RESET_ONLY == Web.state) { - WSContentSpaceButton(BUTTON_RESTART); -#ifndef FIRMWARE_MINIMAL - WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); -#endif - } - - WSContentStop(); -} - -void HandleRoot(void) -{ - if (CaptivePortal()) { return; } - - if (WebServer->hasArg("rst")) { - WebRestart(0); - return; - } - - if (WifiIsInManagerMode()) { -#ifndef FIRMWARE_MINIMAL - if ((Settings.web_password[0] != 0) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { - HandleWifiLogin(); - } else { - if (!(Settings.web_password[0] != 0) || (((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == Settings.web_password )) || HTTP_MANAGER_RESET_ONLY == Web.state)) { - HandleWifiConfiguration(); - } else { - - HandleWifiLogin(); - } - } -#endif - return; - } - - if (HandleRootStatusRefresh()) { - return; - } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_MAIN_MENU); - - char stemp[5]; - - WSContentStart_P(S_MAIN_MENU); -#ifdef USE_SCRIPT_WEB_DISPLAY - WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh, Settings.web_refresh); -#else - WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh); -#endif - WSContentSendStyle(); - - WSContentSend_P(PSTR("
")); - if (devices_present) { -#ifdef USE_LIGHT - if (light_type) { - if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { - WSContentSend_P(HTTP_MSG_SLIDER1, LightGetColorTemp()); - } - WSContentSend_P(HTTP_MSG_SLIDER2, Settings.light_dimmer); - } -#endif - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("
")); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); - for (uint32_t i = 0; i < MaxFanspeed(); i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); - WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i +2, stemp, ""); - } - } else { -#endif - for (uint32_t idx = 1; idx <= devices_present; idx++) { - snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); - WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); - } -#ifdef USE_SONOFF_IFAN - } -#endif - WSContentSend_P(PSTR("
%s
")); - } - if (SONOFF_BRIDGE == my_module_type) { - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("")); - uint32_t idx = 0; - for (uint32_t i = 0; i < 4; i++) { - if (idx > 0) { WSContentSend_P(PSTR("")); } - for (uint32_t j = 0; j < 4; j++) { - idx++; - WSContentSend_P(PSTR(""), idx, idx); - } - } - WSContentSend_P(PSTR("")); - } - -#ifndef FIRMWARE_MINIMAL - XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); - XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); -#endif - - if (HTTP_ADMIN == Web.state) { -#ifdef FIRMWARE_MINIMAL - WSContentSpaceButton(BUTTON_FIRMWARE_UPGRADE); -#else - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentButton(BUTTON_INFORMATION); - WSContentButton(BUTTON_FIRMWARE_UPGRADE); -#endif - WSContentButton(BUTTON_CONSOLE); - WSContentButton(BUTTON_RESTART); - } - WSContentStop(); -} - -bool HandleRootStatusRefresh(void) -{ - if (!WebAuthenticate()) { - WebServer->requestAuthentication(); - return true; - } - - if (!WebServer->hasArg("m")) { - return false; - } - - #ifdef USE_SCRIPT_WEB_DISPLAY - Script_Check_HTML_Setvars(); - #endif - - char tmp[8]; - char svalue[32]; - - WebGetArg("o", tmp, sizeof(tmp)); - if (strlen(tmp)) { - ShowWebSource(SRC_WEBGUI); - uint32_t device = atoi(tmp); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - if (device < 2) { - ExecuteCommandPower(1, POWER_TOGGLE, SRC_IGNORE); - } else { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), device -2); - ExecuteCommand(svalue, SRC_WEBGUI); - } - } else { -#endif - ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); -#ifdef USE_SONOFF_IFAN - } -#endif - } - WebGetArg("d", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - WebGetArg("t", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - WebGetArg("k", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - - WSContentBegin(200, CT_HTML); - WSContentSend_P(PSTR("{t}")); - XsnsCall(FUNC_WEB_SENSOR); -#ifdef USE_SCRIPT_WEB_DISPLAY - XdrvCall(FUNC_WEB_SENSOR); -#endif - - WSContentSend_P(PSTR("")); - - if (devices_present) { - WSContentSend_P(PSTR("{t}")); - uint32_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32; -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - WSContentSend_P(HTTP_DEVICE_STATE, 36, (bitRead(power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(power, 0))); - uint32_t fanspeed = GetFanspeed(); - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fanspeed); - WSContentSend_P(HTTP_DEVICE_STATE, 64, (fanspeed) ? "bold" : "normal", 54, (fanspeed) ? svalue : GetStateText(0)); - } else { -#endif - for (uint32_t idx = 1; idx <= devices_present; idx++) { - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1)); - WSContentSend_P(HTTP_DEVICE_STATE, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue); - } -#ifdef USE_SONOFF_IFAN - } -#endif - WSContentSend_P(PSTR("")); - } - WSContentEnd(); - - return true; -} - - - -#ifndef FIRMWARE_MINIMAL - -void HandleConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURATION); - - WSContentStart_P(S_CONFIGURATION); - WSContentSendStyle(); - - WSContentButton(BUTTON_MODULE); - WSContentButton(BUTTON_WIFI); - - XdrvCall(FUNC_WEB_ADD_BUTTON); - XsnsCall(FUNC_WEB_ADD_BUTTON); - - WSContentButton(BUTTON_LOGGING); - WSContentButton(BUTTON_OTHER); - WSContentButton(BUTTON_TEMPLATE); - - WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); - WSContentButton(BUTTON_BACKUP); - WSContentButton(BUTTON_RESTORE); - - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); -} - - - -void HandleTemplateConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("save")) { - TemplateSaveSettings(); - WebRestart(1); - return; - } - - char stemp[30]; - - if (WebServer->hasArg("m")) { - WSContentBegin(200, CT_PLAIN); - for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { - uint32_t midx = pgm_read_byte(kModuleNiceList + i); - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1); - } - WSContentEnd(); - return; - } - - WebGetArg("t", stemp, sizeof(stemp)); - if (strlen(stemp)) { - uint32_t module = atoi(stemp); - uint32_t module_save = Settings.module; - Settings.module = module; - myio cmodule; - ModuleGpios(&cmodule); - gpio_flag flag = ModuleFlag(); - Settings.module = module_save; - - WSContentBegin(200, CT_PLAIN); - WSContentSend_P(PSTR("%s}1"), AnyModuleName(module).c_str()); - for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { - if (1 == i) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, 255, D_SENSOR_USER, 255); - } - uint32_t midx = pgm_read_byte(kGpioNiceList + i); - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); - } - WSContentSend_P(PSTR("}1")); - - for (uint32_t i = 0; i < ADC0_END; i++) { - if (1 == i) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, ADC0_USER, D_SENSOR_USER, ADC0_USER); - } - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, i, GetTextIndexed(stemp, sizeof(stemp), i, kAdc0Names), i); - } - WSContentSend_P(PSTR("}1")); - - for (uint32_t i = 0; i < sizeof(cmodule); i++) { - if ((i < 6) || ((i > 8) && (i != 11))) { - WSContentSend_P(PSTR("%s%d"), (i>0)?",":"", cmodule.io[i]); - } - } - WSContentSend_P(PSTR("}1%d}1%d"), flag, Settings.user_template_base); - WSContentEnd(); - return; - } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TEMPLATE); - - WSContentStart_P(S_CONFIGURE_TEMPLATE); - WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); - WSContentSend_P(HTTP_SCRIPT_TEMPLATE); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_TEMPLATE); - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("" D_TEMPLATE_NAME "" - "" D_BASE_TYPE "" - "" - "
")); - WSContentSend_P(HTTP_TABLE100); - for (uint32_t i = 0; i < 17; i++) { - if ((i < 6) || ((i > 8) && (i != 11))) { - WSContentSend_P(PSTR("" D_GPIO "%d"), - ((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:200px'" : "", i); - } - } - WSContentSend_P(PSTR("" D_ADC "0"), WebColor(COL_TEXT)); - WSContentSend_P(PSTR("")); - gpio_flag flag = ModuleFlag(); - if (flag.data > ADC0_USER) { - WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); - } - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void TemplateSaveSettings(void) -{ - char tmp[sizeof(Settings.user_template.name)]; - char webindex[5]; - char svalue[128]; - - WebGetArg("s1", tmp, sizeof(tmp)); - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp); - - uint32_t j = 0; - for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), j); - WebGetArg(webindex, tmp, sizeof(tmp)); - uint8_t gpio = atoi(tmp); - snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", gpio); - j++; - } - - WebGetArg("g17", tmp, sizeof(tmp)); - uint32_t flag = atoi(tmp); - for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) { - snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i); - uint32_t state = WebServer->hasArg(webindex) << i +4; - flag += state; - } - WebGetArg("g99", tmp, sizeof(tmp)); - uint32_t base = atoi(tmp) +1; - - snprintf_P(svalue, sizeof(svalue), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), svalue, flag, base); - ExecuteWebCommand(svalue, SRC_WEBGUI); -} - - - -void HandleModuleConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("save")) { - ModuleSaveSettings(); - WebRestart(1); - return; - } - - char stemp[30]; - uint32_t midx; - myio cmodule; - ModuleGpios(&cmodule); - - if (WebServer->hasArg("m")) { - WSContentBegin(200, CT_PLAIN); - uint32_t vidx = 0; - for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { - if (0 == i) { - midx = USER_MODULE; - vidx = 0; - } else { - midx = pgm_read_byte(kModuleNiceList + i -1); - vidx = midx +1; - } - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), vidx); - } - WSContentEnd(); - return; - } - - if (WebServer->hasArg("g")) { - WSContentBegin(200, CT_PLAIN); - for (uint32_t j = 0; j < sizeof(kGpioNiceList); j++) { - midx = pgm_read_byte(kGpioNiceList + j); - if (!GetUsedInModule(midx, cmodule.io)) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); - } - } - WSContentEnd(); - return; - } - -#ifndef USE_ADC_VCC - if (WebServer->hasArg("a")) { - WSContentBegin(200, CT_PLAIN); - for (uint32_t j = 0; j < ADC0_END; j++) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, j, GetTextIndexed(stemp, sizeof(stemp), j, kAdc0Names), j); - } - WSContentEnd(); - return; - } -#endif - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); - - WSContentStart_P(S_CONFIGURE_MODULE); - WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); - WSContentSend_P(HTTP_SCRIPT_MODULE1, Settings.module); - for (uint32_t i = 0; i < sizeof(cmodule); i++) { - if (ValidGPIO(i, cmodule.io[i])) { - WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); - } - } - WSContentSend_P(HTTP_SCRIPT_MODULE2, Settings.my_adc0); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); - for (uint32_t i = 0; i < sizeof(cmodule); i++) { - if (ValidGPIO(i, cmodule.io[i])) { - snprintf_P(stemp, 3, PINS_WEMOS +i*2); - char sesp8285[40]; - snprintf_P(sesp8285, sizeof(sesp8285), PSTR("ESP8285"), WebColor(COL_TEXT_WARNING)); - WSContentSend_P(PSTR("%s " D_GPIO "%d %s"), - (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? sesp8285 :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i); - } - } -#ifndef USE_ADC_VCC - if (ValidAdc()) { - WSContentSend_P(PSTR("%s " D_ADC "0"), (WEMOS==my_module_type)?"A0":""); - } -#endif - WSContentSend_P(PSTR("")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void ModuleSaveSettings(void) -{ - char tmp[8]; - char webindex[5]; - - WebGetArg("g99", tmp, sizeof(tmp)); - uint32_t new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); - Settings.last_module = Settings.module; - Settings.module = new_module; - SetModuleType(); - myio cmodule; - ModuleGpios(&cmodule); - String gpios = ""; - for (uint32_t i = 0; i < sizeof(cmodule); i++) { - if (Settings.last_module != new_module) { - Settings.my_gp.io[i] = GPIO_NONE; - } else { - if (ValidGPIO(i, cmodule.io[i])) { - snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i); - WebGetArg(webindex, tmp, sizeof(tmp)); - Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); - } - } - } -#ifndef USE_ADC_VCC - WebGetArg("g17", tmp, sizeof(tmp)); - Settings.my_adc0 = (!strlen(tmp)) ? 0 : atoi(tmp); - gpios += F(", " D_ADC "0 "); gpios += String(Settings.my_adc0); -#endif - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), ModuleName().c_str(), gpios.c_str()); -} - - - -const char kUnescapeCode[] = "&><\"\'"; -const char kEscapeCode[] PROGMEM = "&|>|<|"|'"; - -String HtmlEscape(const String unescaped) { - char escaped[10]; - size_t ulen = unescaped.length(); - String result = ""; - for (size_t i = 0; i < ulen; i++) { - char c = unescaped[i]; - char *p = strchr(kUnescapeCode, c); - if (p != nullptr) { - result += GetTextIndexed(escaped, sizeof(escaped), p - kUnescapeCode, kEscapeCode); - } else { - result += c; - } - } - return result; -} - - -const char kEncryptionType[] PROGMEM = "|||" D_WPA_PSK "||" D_WPA2_PSK "|" D_WEP "||" D_NONE "|" D_AUTO; - -void HandleWifiConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); - - if (WebServer->hasArg("save") && HTTP_MANAGER_RESET_ONLY != Web.state) { - WifiSaveSettings(); - WebRestart(2); - return; - } - - WSContentStart_P(S_CONFIGURE_WIFI, !WifiIsInManagerMode()); - WSContentSend_P(HTTP_SCRIPT_WIFI); - WSContentSendStyle(); - - if (HTTP_MANAGER_RESET_ONLY != Web.state) { - if (WebServer->hasArg("scan")) { -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - int n = WiFi.scanNetworks(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SCAN_DONE)); - - if (0 == n) { - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, S_NO_NETWORKS_FOUND); - WSContentSend_P(S_NO_NETWORKS_FOUND); - WSContentSend_P(PSTR(". " D_REFRESH_TO_SCAN_AGAIN ".")); - } else { - - int indices[n]; - for (uint32_t i = 0; i < n; i++) { - indices[i] = i; - } - - - for (uint32_t i = 0; i < n; i++) { - for (uint32_t j = i + 1; j < n; j++) { - if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) { - std::swap(indices[i], indices[j]); - } - } - } - - - String cssid; - for (uint32_t i = 0; i < n; i++) { - if (-1 == indices[i]) { continue; } - cssid = WiFi.SSID(indices[i]); - for (uint32_t j = i + 1; j < n; j++) { - if (cssid == WiFi.SSID(indices[j])) { - DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_DUPLICATE_ACCESSPOINT " %s"), WiFi.SSID(indices[j]).c_str()); - indices[j] = -1; - } - } - } - - - for (uint32_t i = 0; i < n; i++) { - if (-1 == indices[i]) { continue; } - DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), - WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i])); - int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); - int auth = WiFi.encryptionType(indices[i]); - char encryption[20]; - WSContentSend_P(PSTR("
%s (%d) %s %d%%
"), - HtmlEscape(WiFi.SSID(indices[i])).c_str(), - WiFi.channel(indices[i]), - GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), - quality - ); - delay(0); - - } - WSContentSend_P(PSTR("
")); - } - } else { - WSContentSend_P(PSTR("
")); - } - - - WSContentSend_P(HTTP_FORM_WIFI, Settings.sta_ssid[0], Settings.sta_ssid[1], WIFI_HOSTNAME, WIFI_HOSTNAME, Settings.hostname); - WSContentSend_P(HTTP_FORM_END); - } - - if (WifiIsInManagerMode()) { - WSContentSpaceButton(BUTTON_RESTART); -#ifndef FIRMWARE_MINIMAL - WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); -#endif - } else { - WSContentSpaceButton(BUTTON_CONFIGURATION); - } - WSContentStop(); -} - -void WifiSaveSettings(void) -{ - char tmp[sizeof(Settings.sta_pwd[0])]; - - WebGetArg("h", tmp, sizeof(tmp)); - strlcpy(Settings.hostname, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp, sizeof(Settings.hostname)); - if (strstr(Settings.hostname, "%") != nullptr) { - strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); - } - WebGetArg("s1", tmp, sizeof(tmp)); - strlcpy(Settings.sta_ssid[0], (!strlen(tmp)) ? STA_SSID1 : tmp, sizeof(Settings.sta_ssid[0])); - WebGetArg("s2", tmp, sizeof(tmp)); - strlcpy(Settings.sta_ssid[1], (!strlen(tmp)) ? STA_SSID2 : tmp, sizeof(Settings.sta_ssid[1])); - WebGetArg("p1", tmp, sizeof(tmp)); - strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); - WebGetArg("p2", tmp, sizeof(tmp)); - strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s"), Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1]); -} - - - -void HandleLoggingConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_LOGGING); - - if (WebServer->hasArg("save")) { - LoggingSaveSettings(); - HandleConfiguration(); - return; - } - - WSContentStart_P(S_CONFIGURE_LOGGING); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_LOG1); - char stemp1[45]; - char stemp2[32]; - uint8_t dlevel[3] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE }; - for (uint32_t idx = 0; idx < 3; idx++) { - uint32_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:Settings.syslog_level; - WSContentSend_P(PSTR("

%s (%s)

")); - } - WSContentSend_P(HTTP_FORM_LOG2, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void LoggingSaveSettings(void) -{ - char tmp[sizeof(Settings.syslog_host)]; - - WebGetArg("l0", tmp, sizeof(tmp)); - SetSeriallog((!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp)); - WebGetArg("l1", tmp, sizeof(tmp)); - Settings.weblog_level = (!strlen(tmp)) ? WEB_LOG_LEVEL : atoi(tmp); - WebGetArg("l2", tmp, sizeof(tmp)); - SetSyslog((!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp)); - WebGetArg("lh", tmp, sizeof(tmp)); - strlcpy(Settings.syslog_host, (!strlen(tmp)) ? SYS_LOG_HOST : tmp, sizeof(Settings.syslog_host)); - WebGetArg("lp", tmp, sizeof(tmp)); - Settings.syslog_port = (!strlen(tmp)) ? SYS_LOG_PORT : atoi(tmp); - WebGetArg("lt", tmp, sizeof(tmp)); - Settings.tele_period = (!strlen(tmp)) ? TELE_PERIOD : atoi(tmp); - if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) { - Settings.tele_period = 10; - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_LOG D_CMND_SERIALLOG " %d, " D_CMND_WEBLOG " %d, " D_CMND_SYSLOG " %d, " D_CMND_LOGHOST " %s, " D_CMND_LOGPORT " %d, " D_CMND_TELEPERIOD " %d"), - Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); -} - - - -void HandleOtherConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_OTHER); - - if (WebServer->hasArg("save")) { - OtherSaveSettings(); - WebRestart(1); - return; - } - - WSContentStart_P(S_CONFIGURE_OTHER); - WSContentSendStyle(); - - TemplateJson(); - char stemp[strlen(mqtt_data) +1]; - strlcpy(stemp, mqtt_data, sizeof(stemp)); - WSContentSend_P(HTTP_FORM_OTHER, stemp, (USER_MODULE == Settings.module) ? " checked disabled" : "", (Settings.flag.mqtt_enabled) ? " checked" : ""); - - uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { maxfn = 1; } -#endif - for (uint32_t i = 0; i < maxfn; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i +1); - WSContentSend_P(PSTR("" D_FRIENDLY_NAME " %d (" FRIENDLY_NAME "%s)

"), - i +1, - (i) ? stemp : "", - i, - (i) ? stemp : "", - Settings.friendlyname[i]); - } - -#ifdef USE_EMULATION - WSContentSend_P(PSTR("

 " D_EMULATION " 

")); - for (uint32_t i = 0; i < EMUL_MAX; i++) { -#ifndef USE_EMULATION_WEMO - if (i == EMUL_WEMO) { i++; } -#endif -#ifndef USE_EMULATION_HUE - if (i == EMUL_HUE) { i++; } -#endif - if (i < EMUL_MAX) { - WSContentSend_P(PSTR("%s %s
"), - i, i, - (i == Settings.flag2.emulation) ? " checked" : "", - GetTextIndexed(stemp, sizeof(stemp), i, kEmulationOptions), - (i == EMUL_NONE) ? "" : (i == EMUL_WEMO) ? D_SINGLE_DEVICE : D_MULTI_DEVICE); - } - } - WSContentSend_P(PSTR("

")); -#endif - - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void OtherSaveSettings(void) -{ - char tmp[128]; - char webindex[5]; - char friendlyname[sizeof(Settings.friendlyname[0])]; - - WebGetArg("wp", tmp, sizeof(tmp)); - strlcpy(Settings.web_password, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.web_password : tmp, sizeof(Settings.web_password)); - Settings.flag.mqtt_enabled = WebServer->hasArg("b1"); -#ifdef USE_EMULATION - WebGetArg("b2", tmp, sizeof(tmp)); - Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); -#endif - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); - for (uint32_t i = 0; i < MAX_FRIENDLYNAMES; i++) { - snprintf_P(webindex, sizeof(webindex), PSTR("a%d"), i); - WebGetArg(webindex, tmp, sizeof(tmp)); - snprintf_P(friendlyname, sizeof(friendlyname), PSTR(FRIENDLY_NAME"%d"), i +1); - strlcpy(Settings.friendlyname[i], (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp, sizeof(Settings.friendlyname[i])); - snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", Settings.friendlyname[i]); - } - AddLog(LOG_LEVEL_INFO); - WebGetArg("t1", tmp, sizeof(tmp)); - if (strlen(tmp)) { - char svalue[128]; - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - - if (WebServer->hasArg("t2")) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_MODULE " 0")); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - - } -} - - - -void HandleBackupConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_BACKUP_CONFIGURATION)); - - if (!SettingsBufferAlloc()) { return; } - - WiFiClient myClient = WebServer->client(); - WebServer->setContentLength(sizeof(Settings)); - - char attachment[100]; - - - - - char hostname[sizeof(my_hostname)]; - snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(hostname, my_hostname), my_version); - - WebServer->sendHeader(F("Content-Disposition"), attachment); - - WSSend(200, CT_STREAM, ""); - - uint32_t cfg_crc32 = Settings.cfg_crc32; - Settings.cfg_crc32 = GetSettingsCrc32(); - - memcpy(settings_buffer, &Settings, sizeof(Settings)); - if (Web.config_xor_on_set) { - for (uint32_t i = 2; i < sizeof(Settings); i++) { - settings_buffer[i] ^= (Web.config_xor_on_set +i); - } - } - -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 - size_t written = myClient.write((const char*)settings_buffer, sizeof(Settings)); - if (written < sizeof(Settings)) { - myClient.write((const char*)settings_buffer +written, sizeof(Settings) -written); - } -#else - myClient.write((const char*)settings_buffer, sizeof(Settings)); -#endif - - SettingsBufferFree(); - - Settings.cfg_crc32 = cfg_crc32; -} - - - -void HandleResetConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESET_CONFIGURATION); - - WSContentStart_P(S_RESET_CONFIGURATION, !WifiIsInManagerMode()); - WSContentSendStyle(); - WSContentSend_P(PSTR("
" D_CONFIGURATION_RESET "
")); - WSContentSend_P(HTTP_MSG_RSTRT); - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); - - char command[CMDSZ]; - snprintf_P(command, sizeof(command), PSTR(D_CMND_RESET " 1")); - ExecuteWebCommand(command, SRC_WEBGUI); -} - -void HandleRestoreConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTORE_CONFIGURATION); - - WSContentStart_P(S_RESTORE_CONFIGURATION); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_RST); - WSContentSend_P(HTTP_FORM_RST_UPG, D_RESTORE); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); - - Web.upload_error = 0; - Web.upload_file_type = UPL_SETTINGS; -} - - - -void HandleInformation(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_INFORMATION); - - char stopic[TOPSZ]; - - int freeMem = ESP.getFreeHeap(); - - WSContentStart_P(S_INFORMATION); - - - - WSContentSend_P(HTTP_SCRIPT_INFO_BEGIN); - WSContentSend_P(PSTR("
")); - WSContentSend_P(PSTR(D_PROGRAM_VERSION "}2%s%s"), my_version, my_image); - WSContentSend_P(PSTR("}1" D_BUILD_DATE_AND_TIME "}2%s"), GetBuildDateAndTime().c_str()); - WSContentSend_P(PSTR("}1" D_CORE_AND_SDK_VERSION "}2" ARDUINO_ESP8266_RELEASE "/%s"), ESP.getSdkVersion()); - WSContentSend_P(PSTR("}1" D_UPTIME "}2%s"), GetUptime().c_str()); - WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d at 0x%X"), Settings.save_flag, GetSettingsAddress()); - WSContentSend_P(PSTR("}1" D_BOOT_COUNT "}2%d"), Settings.bootcount); - WSContentSend_P(PSTR("}1" D_RESTART_REASON "}2%s"), GetResetReason().c_str()); - uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present; -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { maxfn = 1; } -#endif - for (uint32_t i = 0; i < maxfn; i++) { - WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, Settings.friendlyname[i]); - } - WSContentSend_P(PSTR("}1}2 ")); - WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%)"), Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI())); - WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Wifi.mdns_begun) ? ".local" : ""); - if (static_cast(WiFi.localIP()) != 0) { - WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.localIP().toString().c_str()); - WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), IPAddress(Settings.ip_address[1]).toString().c_str()); - WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%s"), IPAddress(Settings.ip_address[2]).toString().c_str()); - WSContentSend_P(PSTR("}1" D_DNS_SERVER "}2%s"), IPAddress(Settings.ip_address[3]).toString().c_str()); - WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.macAddress().c_str()); - } - if (static_cast(WiFi.softAPIP()) != 0) { - WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.softAPIP().toString().c_str()); - WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), WiFi.softAPIP().toString().c_str()); - WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.softAPmacAddress().c_str()); - } - WSContentSend_P(PSTR("}1}2 ")); - if (Settings.flag.mqtt_enabled) { -#ifdef USE_MQTT_AWS_IOT - WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s%s"), Settings.mqtt_user, Settings.mqtt_host); - WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port); -#else - WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), Settings.mqtt_host); - WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port); - WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), Settings.mqtt_user); -#endif - WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client); - WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), Settings.mqtt_topic); - WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), Settings.mqtt_grptopic); - WSContentSend_P(PSTR("}1" D_MQTT_FULL_TOPIC "}2%s"), GetTopic_P(stopic, CMND, mqtt_topic, "")); - WSContentSend_P(PSTR("}1" D_MQTT " " D_FALLBACK_TOPIC "}2%s"), GetFallbackTopic_P(stopic, CMND, "")); - } else { - WSContentSend_P(PSTR("}1" D_MQTT "}2" D_DISABLED)); - } - WSContentSend_P(PSTR("}1}2 ")); - -#ifdef USE_EMULATION - WSContentSend_P(PSTR("}1" D_EMULATION "}2%s"), GetTextIndexed(stopic, sizeof(stopic), Settings.flag2.emulation, kEmulationOptions)); -#else - WSContentSend_P(PSTR("}1" D_EMULATION "}2" D_DISABLED)); -#endif - -#ifdef USE_DISCOVERY - WSContentSend_P(PSTR("}1" D_MDNS_DISCOVERY "}2%s"), (Settings.flag3.mdns_enabled) ? D_ENABLED : D_DISABLED); - if (Settings.flag3.mdns_enabled) { -#ifdef WEBSERVER_ADVERTISE - WSContentSend_P(PSTR("}1" D_MDNS_ADVERTISE "}2" D_WEB_SERVER)); -#else - WSContentSend_P(PSTR("}1" D_MDNS_ADVERTISE "}2" D_DISABLED)); -#endif - } -#else - WSContentSend_P(PSTR("}1" D_MDNS_DISCOVERY "}2" D_DISABLED)); -#endif - - WSContentSend_P(PSTR("}1}2 ")); - WSContentSend_P(PSTR("}1" D_ESP_CHIP_ID "}2%d"), ESP.getChipId()); - WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X"), ESP.getFlashChipId()); - WSContentSend_P(PSTR("}1" D_FLASH_CHIP_SIZE "}2%dkB"), ESP.getFlashChipRealSize() / 1024); - WSContentSend_P(PSTR("}1" D_PROGRAM_FLASH_SIZE "}2%dkB"), ESP.getFlashChipSize() / 1024); - WSContentSend_P(PSTR("}1" D_PROGRAM_SIZE "}2%dkB"), ESP.getSketchSize() / 1024); - WSContentSend_P(PSTR("}1" D_FREE_PROGRAM_SPACE "}2%dkB"), ESP.getFreeSketchSpace() / 1024); - WSContentSend_P(PSTR("}1" D_FREE_MEMORY "}2%dkB"), freeMem / 1024); - WSContentSend_P(PSTR("
")); - - WSContentSend_P(HTTP_SCRIPT_INFO_END); - WSContentSendStyle(); - - WSContentSend_P(PSTR("" - "
")); - - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); -} -#endif - - - -void HandleUpgradeFirmware(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_FIRMWARE_UPGRADE); - - WSContentStart_P(S_FIRMWARE_UPGRADE); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_UPG, Settings.ota_url); - WSContentSend_P(HTTP_FORM_RST_UPG, D_UPGRADE); - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); - - Web.upload_error = 0; - Web.upload_file_type = UPL_TASMOTA; -} - -void HandleUpgradeFirmwareStart(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - char command[sizeof(Settings.ota_url) + 10]; - - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPGRADE_STARTED)); - WifiConfigCounter(); - - char otaurl[sizeof(Settings.ota_url)]; - WebGetArg("o", otaurl, sizeof(otaurl)); - if (strlen(otaurl)) { - snprintf_P(command, sizeof(command), PSTR(D_CMND_OTAURL " %s"), otaurl); - ExecuteWebCommand(command, SRC_WEBGUI); - } - - WSContentStart_P(S_INFORMATION); - WSContentSend_P(HTTP_SCRIPT_RELOAD_OTA); - WSContentSendStyle(); - WSContentSend_P(PSTR("
" D_UPGRADE_STARTED " ...
")); - WSContentSend_P(HTTP_MSG_RSTRT); - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); - - snprintf_P(command, sizeof(command), PSTR(D_CMND_UPGRADE " 1")); - ExecuteWebCommand(command, SRC_WEBGUI); -} - -void HandleUploadDone(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPLOAD_DONE)); - - char error[100]; - - WifiConfigCounter(); - restart_flag = 0; - MqttRetryCounter(0); - - WSContentStart_P(S_INFORMATION); - if (!Web.upload_error) { - WSContentSend_P(HTTP_SCRIPT_RELOAD_OTA); - } - WSContentSendStyle(); - WSContentSend_P(PSTR("
" D_UPLOAD " " D_FAILED "

"), WebColor(COL_TEXT_WARNING)); -#ifdef USE_RF_FLASH - if (Web.upload_error < 14) { -#else - if (Web.upload_error < 10) { -#endif - GetTextIndexed(error, sizeof(error), Web.upload_error -1, kUploadErrors); - } else { - snprintf_P(error, sizeof(error), PSTR(D_UPLOAD_ERROR_CODE " %d"), Web.upload_error); - } - WSContentSend_P(error); - DEBUG_CORE_LOG(PSTR("UPL: %s"), error); - stop_flash_rotate = Settings.flag.stop_flash_rotate; - } else { - WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "
"), WebColor(COL_TEXT_SUCCESS)); - WSContentSend_P(HTTP_MSG_RSTRT); - ShowWebSource(SRC_WEBGUI); - restart_flag = 2; - } - SettingsBufferFree(); - WSContentSend_P(PSTR("

")); - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); -} - -void HandleUploadLoop(void) -{ - - bool _serialoutput = (LOG_LEVEL_DEBUG <= seriallog_level); - - if (HTTP_USER == Web.state) { return; } - if (Web.upload_error) { - if (UPL_TASMOTA == Web.upload_file_type) { Update.end(); } - return; - } - - HTTPUpload& upload = WebServer->upload(); - - if (UPLOAD_FILE_START == upload.status) { - restart_flag = 60; - if (0 == upload.filename.c_str()[0]) { - Web.upload_error = 1; - return; - } - SettingsSave(1); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_FILE " %s ..."), upload.filename.c_str()); - if (UPL_SETTINGS == Web.upload_file_type) { - if (!SettingsBufferAlloc()) { - Web.upload_error = 2; - return; - } - } else { - MqttRetryCounter(60); -#ifdef USE_EMULATION - UdpDisconnect(); -#endif -#ifdef USE_ARILUX_RF - AriluxRfDisable(); -#endif - if (Settings.flag.mqtt_enabled) MqttDisconnect(); - uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; - if (!Update.begin(maxSketchSpace)) { - - - - - - - Web.upload_error = 2; - return; - } - } - Web.upload_progress_dot_count = 0; - } else if (!Web.upload_error && (UPLOAD_FILE_WRITE == upload.status)) { - if (0 == upload.totalSize) { - if (UPL_SETTINGS == Web.upload_file_type) { - Web.config_block_count = 0; - } - else { -#ifdef USE_RF_FLASH - if ((SONOFF_BRIDGE == my_module_type) && (upload.buf[0] == ':')) { - Update.end(); - Web.upload_file_type = UPL_EFM8BB1; - - Web.upload_error = SnfBrUpdateInit(); - if (Web.upload_error != 0) { return; } - } else -#endif - { - if (upload.buf[0] != 0xE9) { - Web.upload_error = 3; - return; - } - uint32_t bin_flash_size = ESP.magicFlashChipSize((upload.buf[3] & 0xf0) >> 4); - if(bin_flash_size > ESP.getFlashChipRealSize()) { - Web.upload_error = 4; - return; - } - - } - } - } - if (UPL_SETTINGS == Web.upload_file_type) { - if (!Web.upload_error) { - if (upload.currentSize > (sizeof(Settings) - (Web.config_block_count * HTTP_UPLOAD_BUFLEN))) { - Web.upload_error = 9; - return; - } - memcpy(settings_buffer + (Web.config_block_count * HTTP_UPLOAD_BUFLEN), upload.buf, upload.currentSize); - Web.config_block_count++; - } - } -#ifdef USE_RF_FLASH - else if (UPL_EFM8BB1 == Web.upload_file_type) { - if (efm8bb1_update != nullptr) { - ssize_t result = rf_glue_remnant_with_new_data_and_write(efm8bb1_update, upload.buf, upload.currentSize); - free(efm8bb1_update); - efm8bb1_update = nullptr; - if (result != 0) { - Web.upload_error = abs(result); - return; - } - } - ssize_t result = rf_search_and_write(upload.buf, upload.currentSize); - if (result < 0) { - Web.upload_error = abs(result); - return; - } else if (result > 0) { - if ((size_t)result > upload.currentSize) { - - Web.upload_error = 9; - return; - } - - size_t remnant_sz = upload.currentSize - result; - efm8bb1_update = (uint8_t *) malloc(remnant_sz + 1); - if (efm8bb1_update == nullptr) { - Web.upload_error = 2; - return; - } - memcpy(efm8bb1_update, upload.buf + result, remnant_sz); - - efm8bb1_update[remnant_sz] = '\0'; - } - } -#endif - else { - if (!Web.upload_error && (Update.write(upload.buf, upload.currentSize) != upload.currentSize)) { - Web.upload_error = 5; - return; - } - if (_serialoutput) { - Serial.printf("."); - Web.upload_progress_dot_count++; - if (!(Web.upload_progress_dot_count % 80)) { Serial.println(); } - } - } - } else if(!Web.upload_error && (UPLOAD_FILE_END == upload.status)) { - if (_serialoutput && (Web.upload_progress_dot_count % 80)) { - Serial.println(); - } - if (UPL_SETTINGS == Web.upload_file_type) { - if (Web.config_xor_on_set) { - for (uint32_t i = 2; i < sizeof(Settings); i++) { - settings_buffer[i] ^= (Web.config_xor_on_set +i); - } - } - bool valid_settings = false; - unsigned long buffer_version = settings_buffer[11] << 24 | settings_buffer[10] << 16 | settings_buffer[9] << 8 | settings_buffer[8]; - if (buffer_version > 0x06000000) { - uint32_t buffer_size = settings_buffer[3] << 8 | settings_buffer[2]; - if (buffer_version > 0x0606000A) { - uint32_t buffer_crc32 = settings_buffer[4095] << 24 | settings_buffer[4094] << 16 | settings_buffer[4093] << 8 | settings_buffer[4092]; - valid_settings = (GetCfgCrc32(settings_buffer, buffer_size -4) == buffer_crc32); - } else { - uint16_t buffer_crc16 = settings_buffer[15] << 8 | settings_buffer[14]; - valid_settings = (GetCfgCrc16(settings_buffer, buffer_size) == buffer_crc16); - } - } else { - valid_settings = (settings_buffer[0] == CONFIG_FILE_SIGN); - } - if (valid_settings) { - SettingsDefaultSet2(); - memcpy((char*)&Settings +16, settings_buffer +16, sizeof(Settings) -16); - Settings.version = buffer_version; - SettingsBufferFree(); - } else { - Web.upload_error = 8; - return; - } - } -#ifdef USE_RF_FLASH - else if (UPL_EFM8BB1 == Web.upload_file_type) { - - Web.upload_file_type = UPL_TASMOTA; - } -#endif - else { - if (!Update.end(true)) { - if (_serialoutput) { Update.printError(Serial); } - Web.upload_error = 6; - return; - } - } - if (!Web.upload_error) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_SUCCESSFUL " %u bytes. " D_RESTARTING), upload.totalSize); - } - } else if (UPLOAD_FILE_ABORTED == upload.status) { - restart_flag = 0; - MqttRetryCounter(0); - Web.upload_error = 7; - if (UPL_TASMOTA == Web.upload_file_type) { Update.end(); } - } - delay(0); -} - - - -void HandlePreflightRequest(void) -{ - WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); - WebServer->sendHeader(F("Access-Control-Allow-Methods"), F("GET, POST")); - WebServer->sendHeader(F("Access-Control-Allow-Headers"), F("authorization")); - WSSend(200, CT_HTML, ""); -} - - - -void HandleHttpCommand(void) -{ - if (!HttpCheckPriviledgedAccess(false)) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_COMMAND)); - - bool valid = true; - if (Settings.web_password[0] != 0) { - char tmp1[sizeof(Settings.web_password)]; - WebGetArg("user", tmp1, sizeof(tmp1)); - char tmp2[sizeof(Settings.web_password)]; - WebGetArg("password", tmp2, sizeof(tmp2)); - if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, Settings.web_password))) { valid = false; } - } - - WSContentBegin(200, CT_JSON); - if (valid) { - uint32_t curridx = web_log_index; - String svalue = WebServer->arg("cmnd"); - if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { - ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCOMMAND); - if (web_log_index != curridx) { - uint32_t counter = curridx; - WSContentSend_P(PSTR("{")); - bool cflg = false; - do { - char* tmp; - size_t len; - GetLog(counter, &tmp, &len); - if (len) { - - char* JSON = (char*)memchr(tmp, '{', len); - if (JSON) { - size_t JSONlen = len - (JSON - tmp); - if (JSONlen > sizeof(mqtt_data)) { JSONlen = sizeof(mqtt_data); } - char stemp[JSONlen]; - strlcpy(stemp, JSON +1, JSONlen -2); - WSContentSend_P(PSTR("%s%s"), (cflg) ? "," : "", stemp); - cflg = true; - } - } - counter++; - counter &= 0xFF; - if (!counter) counter++; - } while (counter != web_log_index); - WSContentSend_P(PSTR("}")); - } else { - WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}")); - } - } else { - WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENTER_COMMAND " cmnd=\"}")); - } - } else { - WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_NEED_USER_AND_PASSWORD "\"}")); - } - WSContentEnd(); -} - - - -void HandleConsole(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("c2")) { - HandleConsoleRefresh(); - return; - } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONSOLE); - - WSContentStart_P(S_CONSOLE); - WSContentSend_P(HTTP_SCRIPT_CONSOL, Settings.web_refresh); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_CMND); - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); -} - -void HandleConsoleRefresh(void) -{ - bool cflg = true; - uint32_t counter = 0; - - String svalue = WebServer->arg("c1"); - if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), svalue.c_str()); - ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE); - } - - char stmp[8]; - WebGetArg("c2", stmp, sizeof(stmp)); - if (strlen(stmp)) { counter = atoi(stmp); } - - WSContentBegin(200, CT_PLAIN); - WSContentSend_P(PSTR("%d}1%d}1"), web_log_index, Web.reset_web_log_flag); - if (!Web.reset_web_log_flag) { - counter = 0; - Web.reset_web_log_flag = true; - } - if (counter != web_log_index) { - if (!counter) { - counter = web_log_index; - cflg = false; - } - do { - char* tmp; - size_t len; - GetLog(counter, &tmp, &len); - if (len) { - if (len > sizeof(mqtt_data) -2) { len = sizeof(mqtt_data); } - char stemp[len +1]; - strlcpy(stemp, tmp, len); - WSContentSend_P(PSTR("%s%s"), (cflg) ? "\n" : "", stemp); - cflg = true; - } - counter++; - counter &= 0xFF; - if (!counter) { counter++; } - } while (counter != web_log_index); - } - WSContentSend_P(PSTR("}1")); - WSContentEnd(); -} - - - -void HandleNotFound(void) -{ - - - if (CaptivePortal()) { return; } - -#ifdef USE_EMULATION -#ifdef USE_EMULATION_HUE - String path = WebServer->uri(); - if ((EMUL_HUE == Settings.flag2.emulation) && (path.startsWith("/api"))) { - HandleHueApi(&path); - } else -#endif -#endif - { - WSContentBegin(404, CT_PLAIN); - WSContentSend_P(PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args()); - for (uint32_t i = 0; i < WebServer->args(); i++) { - WSContentSend_P(PSTR(" %s: %s\n"), WebServer->argName(i).c_str(), WebServer->arg(i).c_str()); - } - WSContentEnd(); - } -} - - -bool CaptivePortal(void) -{ - - if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader().c_str())) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); - - WebServer->sendHeader(F("Location"), String("http://") + WebServer->client().localIP().toString(), true); - WSSend(302, CT_PLAIN, ""); - WebServer->client().stop(); - return true; - } - return false; -} - - - -String UrlEncode(const String& text) -{ - const char hex[] = "0123456789ABCDEF"; - - String encoded = ""; - int len = text.length(); - int i = 0; - while (i < len) { - char decodedChar = text.charAt(i++); -# 2374 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_01_webserver.ino" - if ((' ' == decodedChar) || ('+' == decodedChar)) { - encoded += '%'; - encoded += hex[decodedChar >> 4]; - encoded += hex[decodedChar & 0xF]; - } else { - encoded += decodedChar; - } - - } - return encoded; -} - -#ifdef USE_SENDMAIL - -#include "sendemail.h" - - - - - - - -#define SEND_MAIL_MINRAM 19*1024 - -uint16_t SendMail(char *buffer) { - uint16_t count; - char *params,*oparams; - char *mserv; - uint16_t port; - char *user; - char *pstr; - char *passwd; - char *from; - char *to; - char *subject; - char *cmd; - char secure=0,auth=0; - uint16_t status=1; - SendEmail *mail=0; - - - - - uint16_t mem=ESP.getFreeHeap(); - if (memsend(from,to,subject,cmd); - delete mail; - if (result==true) status=0; - } - - - if (oparams) free(oparams); - return status; -} - -#endif - -int WebSend(char *buffer) -{ - - - - - - char *host; - char *user; - char *password; - char *command; - int status = 1; - - - host = strtok_r(buffer, "]", &command); - if (host && command) { - RemoveSpace(host); - host++; - host = strtok_r(host, ",", &user); - String url = F("http://"); - url += host; - - command = Trim(command); - if (command[0] != '/') { - url += F("/cm?"); - if (user) { - user = strtok_r(user, ":", &password); - if (user && password) { - char userpass[128]; - snprintf_P(userpass, sizeof(userpass), PSTR("user=%s&password=%s&"), user, password); - url += userpass; - } - } - url += F("cmnd="); - } - url += command; - - DEBUG_CORE_LOG(PSTR("WEB: Uri |%s|"), url.c_str()); - -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) - HTTPClient http; - if (http.begin(UrlEncode(url))) { -#else - WiFiClient http_client; - HTTPClient http; - if (http.begin(http_client, UrlEncode(url))) { -#endif - int http_code = http.GET(); - if (http_code > 0) { - if (http_code == HTTP_CODE_OK || http_code == HTTP_CODE_MOVED_PERMANENTLY) { -#ifdef USE_WEBSEND_RESPONSE - - const char* read = http.getString().c_str(); - uint32_t j = 0; - char text = '.'; - while (text != '\0') { - text = *read++; - if (text > 31) { - mqtt_data[j++] = text; - if (j == sizeof(mqtt_data) -2) { break; } - } - } - mqtt_data[j] = '\0'; - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WEBSEND)); -#ifdef USE_SCRIPT -extern uint8_t tasm_cmd_activ; - - tasm_cmd_activ=0; - XdrvRulesProcess(); -#endif -#endif - } - status = 0; - } else { - status = 2; - } - http.end(); - } else { - status = 3; - } - } - return status; -} - -bool JsonWebColor(const char* dataBuf) -{ - - - - - - char dataBufLc[strlen(dataBuf) +1]; - LowerCase(dataBufLc, dataBuf); - RemoveSpace(dataBufLc); - if (strlen(dataBufLc) < 9) { return false; } - - StaticJsonBuffer<450> jb; - JsonObject& obj = jb.parseObject(dataBufLc); - if (!obj.success()) { return false; } - - char parm_lc[10]; - if (obj[LowerCase(parm_lc, D_CMND_WEBCOLOR)].success()) { - for (uint32_t i = 0; i < COL_LAST; i++) { - const char* color = obj[parm_lc][i]; - if (color != nullptr) { - WebHexCode(i, color); - } - } - } - return true; -} - -const char kWebSendStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND "|" D_JSON_MEMORY_ERROR; - -const char kWebCommands[] PROGMEM = "|" -#ifdef USE_EMULATION - D_CMND_EMULATION "|" -#endif -#ifdef USE_SENDMAIL - D_CMND_SENDMAIL "|" -#endif - D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" D_CMND_WEBSENSOR; - -void (* const WebCommand[])(void) PROGMEM = { -#ifdef USE_EMULATION - &CmndEmulation, -#endif -#ifdef USE_SENDMAIL - &CmndSendmail, -#endif - &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, &CmndWebSensor }; - - - - - -#ifdef USE_EMULATION -void CmndEmulation(void) -{ -#if defined(USE_EMULATION_WEMO) && defined(USE_EMULATION_HUE) - if ((XdrvMailbox.payload >= EMUL_NONE) && (XdrvMailbox.payload < EMUL_MAX)) { -#else -#ifndef USE_EMULATION_WEMO - if ((EMUL_NONE == XdrvMailbox.payload) || (EMUL_HUE == XdrvMailbox.payload)) { -#endif -#ifndef USE_EMULATION_HUE - if ((EMUL_NONE == XdrvMailbox.payload) || (EMUL_WEMO == XdrvMailbox.payload)) { -#endif -#endif - Settings.flag2.emulation = XdrvMailbox.payload; - restart_flag = 2; - } - ResponseCmndNumber(Settings.flag2.emulation); -} -#endif - -#ifdef USE_SENDMAIL -void CmndSendmail(void) -{ - if (XdrvMailbox.data_len > 0) { - uint8_t result = SendMail(XdrvMailbox.data); - char stemp1[20]; - ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus)); - } -} -#endif - - -void CmndWebServer(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - Settings.webserver = XdrvMailbox.payload; - } - if (Settings.webserver) { - Response_P(PSTR("{\"" D_CMND_WEBSERVER "\":\"" D_JSON_ACTIVE_FOR " %s " D_JSON_ON_DEVICE " %s " D_JSON_WITH_IP_ADDRESS " %s\"}"), - (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); - } else { - ResponseCmndStateText(0); - } -} - -void CmndWebPassword(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.web_password))) { - strlcpy(Settings.web_password, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data, sizeof(Settings.web_password)); - ResponseCmndChar(Settings.web_password); - } else { - Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); - } -} - -void CmndWeblog(void) -{ - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { - Settings.weblog_level = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.weblog_level); -} - -void CmndWebRefresh(void) -{ - if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload <= 10000)) { - Settings.web_refresh = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.web_refresh); -} - -void CmndWebSend(void) -{ - if (XdrvMailbox.data_len > 0) { - uint32_t result = WebSend(XdrvMailbox.data); - char stemp1[20]; - ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus)); - } -} - -void CmndWebColor(void) -{ - if (XdrvMailbox.data_len > 0) { - if (strstr(XdrvMailbox.data, "{") == nullptr) { - if ((XdrvMailbox.data_len > 3) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= COL_LAST)) { - WebHexCode(XdrvMailbox.index -1, XdrvMailbox.data); - } - else if (0 == XdrvMailbox.payload) { - SettingsDefaultWebColor(); - } - } - else { - JsonWebColor(XdrvMailbox.data); - } - } - Response_P(PSTR("{\"" D_CMND_WEBCOLOR "\":[")); - for (uint32_t i = 0; i < COL_LAST; i++) { - if (i) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"#%06x\""), WebColor(i)); - } - ResponseAppend_P(PSTR("]}")); -} - -void CmndWebSensor(void) -{ - if (XdrvMailbox.index < MAX_XSNS_DRIVERS) { - if (XdrvMailbox.payload >= 0) { - bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); - } - } - Response_P(PSTR("{\"" D_CMND_WEBSENSOR "\":")); - XsnsSensorState(); - ResponseJsonEnd(); -} - - - - - -bool Xdrv01(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_LOOP: - PollDnsWebserver(); -#ifdef USE_EMULATION - if (Settings.flag2.emulation) { PollUdp(); } -#endif - break; - case FUNC_COMMAND: - result = DecodeCommand(kWebCommands, WebCommand); - break; - } - return result; -} -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_02_mqtt.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_02_mqtt.ino" -#define XDRV_02 2 - - - -#ifdef USE_MQTT_TLS - #include "WiFiClientSecureLightBearSSL.h" - BearSSL::WiFiClientSecure_light *tlsClient; -#else - WiFiClient EspClient; -#endif - -const char kMqttCommands[] PROGMEM = "|" -#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) - D_CMND_MQTTFINGERPRINT "|" -#endif -#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) - D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" -#endif -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - D_CMND_TLSKEY "|" -#endif - D_CMND_MQTTHOST "|" D_CMND_MQTTPORT "|" D_CMND_MQTTRETRY "|" D_CMND_STATETEXT "|" D_CMND_MQTTCLIENT "|" - D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|" - D_CMND_BUTTONTOPIC "|" D_CMND_SWITCHTOPIC "|" D_CMND_BUTTONRETAIN "|" D_CMND_SWITCHRETAIN "|" D_CMND_POWERRETAIN "|" D_CMND_SENSORRETAIN ; - -void (* const MqttCommand[])(void) PROGMEM = { -#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) - &CmndMqttFingerprint, -#endif -#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) - &CmndMqttUser, &CmndMqttPassword, -#endif -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - &CmndTlsKey, -#endif - &CmndMqttHost, &CmndMqttPort, &CmndMqttRetry, &CmndStateText, &CmndMqttClient, - &CmndFullTopic, &CmndPrefix, &CmndGroupTopic, &CmndTopic, &CmndPublish, - &CmndButtonTopic, &CmndSwitchTopic, &CmndButtonRetain, &CmndSwitchRetain, &CmndPowerRetain, &CmndSensorRetain }; - -struct MQTT { - uint16_t connect_count = 0; - uint16_t retry_counter = 1; - uint8_t initial_connection_state = 2; - bool connected = false; - bool allowed = false; -} Mqtt; - -#ifdef USE_MQTT_TLS - -#ifdef USE_MQTT_AWS_IOT -#include - -const br_ec_private_key *AWS_IoT_Private_Key = nullptr; -const br_x509_certificate *AWS_IoT_Client_Certificate = nullptr; - -class tls_entry_t { -public: - uint32_t name; - uint16_t start; - uint16_t len; -}; - -const static uint32_t TLS_NAME_SKEY = 0x2079656B; -const static uint32_t TLS_NAME_CRT = 0x20747263; - -class tls_dir_t { -public: - tls_entry_t entry[4]; -}; - -tls_dir_t tls_dir; - -#endif - - - -char AWS_endpoint[65]; - - - - -bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value) { - for (uint32_t i = 0; i<20; i++) { - if (finger[i] != value) { - return false; - } - } - return true; -} - -#ifdef USE_MQTT_AWS_IOT -void setLongMqttHost(const char *mqtt_host) { - if (strlen(mqtt_host) <= sizeof(Settings.mqtt_host)) { - strlcpy(Settings.mqtt_host, mqtt_host, sizeof(Settings.mqtt_host)); - Settings.mqtt_user[0] = 0; - } else { - - strlcpy(Settings.mqtt_user, mqtt_host, sizeof(Settings.mqtt_user)); - strlcpy(Settings.mqtt_host, &mqtt_host[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host)); - } - strlcpy(AWS_endpoint, mqtt_host, sizeof(AWS_endpoint)); -} -#endif - -#endif - -void MakeValidMqtt(uint32_t option, char* str) -{ - - - uint32_t i = 0; - while (str[i] > 0) { - - if ((str[i] == '+') || (str[i] == '#') || (str[i] == ' ')) { - if (option) { - uint32_t j = i; - while (str[j] > 0) { - str[j] = str[j +1]; - j++; - } - i--; - } else { - str[i] = '_'; - } - } - i++; - } -} - -#ifdef USE_DISCOVERY -#ifdef MQTT_HOST_DISCOVERY -void MqttDiscoverServer(void) -{ - if (!Wifi.mdns_begun) { return; } - - int n = MDNS.queryService("mqtt", "tcp"); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_QUERY_DONE " %d"), n); - - if (n > 0) { - uint32_t i = 0; -#ifdef MDNS_HOSTNAME - for (i = n; i > 0; i--) { - if (!strcmp(MDNS.hostname(i).c_str(), MDNS_HOSTNAME)) { - break; - } - } -#endif - snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(i).toString().c_str()); - Settings.mqtt_port = MDNS.port(i); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), MDNS.hostname(i).c_str(), Settings.mqtt_host, Settings.mqtt_port); - } -} -#endif -#endif -# 186 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_02_mqtt.ino" -#include - - -#if (MQTT_MAX_PACKET_SIZE -TOPSZ -7) < MIN_MESSZ - #error "MQTT_MAX_PACKET_SIZE is too small in libraries/PubSubClient/src/PubSubClient.h, increase it to at least 1000" -#endif - -#ifdef USE_MQTT_TLS -PubSubClient MqttClient; -#else -PubSubClient MqttClient(EspClient); -#endif - -void MqttInit(void) -{ -#ifdef USE_MQTT_TLS - tlsClient = new BearSSL::WiFiClientSecure_light(1024,1024); - -#ifdef USE_MQTT_AWS_IOT - snprintf_P(AWS_endpoint, sizeof(AWS_endpoint), PSTR("%s%s"), Settings.mqtt_user, Settings.mqtt_host); - - loadTlsDir(); - tlsClient->setClientECCert(AWS_IoT_Client_Certificate, - AWS_IoT_Private_Key, - 0xFFFF , 0); -#endif - -#ifdef USE_MQTT_TLS_CA_CERT -#ifdef USE_MQTT_AWS_IOT - tlsClient->setTrustAnchor(&AmazonRootCA1_TA); -#else - tlsClient->setTrustAnchor(&LetsEncryptX3CrossSigned_TA); -#endif -#endif - - MqttClient.setClient(*tlsClient); -#endif -} - -bool MqttIsConnected(void) -{ - return MqttClient.connected(); -} - -void MqttDisconnect(void) -{ - MqttClient.disconnect(); -} - -void MqttSubscribeLib(const char *topic) -{ - MqttClient.subscribe(topic); - MqttClient.loop(); -} - -void MqttUnsubscribeLib(const char *topic) -{ - MqttClient.unsubscribe(topic); - MqttClient.loop(); -} - -bool MqttPublishLib(const char* topic, bool retained) -{ - bool result = MqttClient.publish(topic, mqtt_data, retained); - yield(); - return result; -} - -void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) -{ -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("MqttDataHandler")); -#endif - - - if (data_len >= MQTT_MAX_PACKET_SIZE) { return; } - - - if (!strcmp(Settings.mqtt_prefix[0], Settings.mqtt_prefix[1])) { - char *str = strstr(topic, Settings.mqtt_prefix[0]); - if ((str == topic) && mqtt_cmnd_publish) { - if (mqtt_cmnd_publish > 3) { - mqtt_cmnd_publish -= 3; - } else { - mqtt_cmnd_publish = 0; - } - return; - } - } - - data[data_len] = 0; - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_RECEIVED_TOPIC " %s, " D_DATA_SIZE " %d, " D_DATA " %s"), topic, data_len, data); - - - - if (XdrvMqttData(topic, strlen(topic), (char*)data, data_len)) { return; } - - ShowSource(SRC_MQTT); - - CommandHandler(topic, data, data_len); -} - - - -void MqttRetryCounter(uint8_t value) -{ - Mqtt.retry_counter = value; -} - -void MqttSubscribe(const char *topic) -{ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT D_SUBSCRIBE_TO " %s"), topic); - MqttSubscribeLib(topic); -} - -void MqttUnsubscribe(const char *topic) -{ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT D_UNSUBSCRIBE_FROM " %s"), topic); - MqttUnsubscribeLib(topic); -} - -void MqttPublishDirect(const char* topic, bool retained) -{ - char sretained[CMDSZ]; - char slog_type[10]; - -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("MqttPublishDirect")); -#endif - - sretained[0] = '\0'; - snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_RESULT)); - - if (Settings.flag.mqtt_enabled) { - if (MqttIsConnected()) { - if (MqttPublishLib(topic, retained)) { - snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_MQTT)); - if (retained) { - snprintf_P(sretained, sizeof(sretained), PSTR(" (" D_RETAINED ")")); - } - } - } - } - - snprintf_P(log_data, sizeof(log_data), PSTR("%s%s = %s"), slog_type, (Settings.flag.mqtt_enabled) ? topic : strrchr(topic,'/')+1, mqtt_data); - if (strlen(log_data) >= (sizeof(log_data) - strlen(sretained) -1)) { - log_data[sizeof(log_data) - strlen(sretained) -5] = '\0'; - snprintf_P(log_data, sizeof(log_data), PSTR("%s ..."), log_data); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s%s"), log_data, sretained); - AddLog(LOG_LEVEL_INFO); - - if (Settings.ledstate &0x04) { - blinks++; - } -} - -void MqttPublish(const char* topic, bool retained) -{ - char *me; -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - if (retained) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR("Retained are not supported by AWS IoT, using retained = false.")); - } - retained = false; -#endif - - if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1])) { - me = strstr(topic,Settings.mqtt_prefix[0]); - if (me == topic) { - mqtt_cmnd_publish += 3; - } - } - MqttPublishDirect(topic, retained); -} - -void MqttPublish(const char* topic) -{ - MqttPublish(topic, false); -} - -void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained) -{ - - - - - - - - char romram[33]; - char stopic[TOPSZ]; - - snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings.flag.mqtt_response) ? S_RSLT_RESULT : subtopic); - for (uint32_t i = 0; i < strlen(romram); i++) { - romram[i] = toupper(romram[i]); - } - prefix &= 3; - GetTopic_P(stopic, prefix, mqtt_topic, romram); - MqttPublish(stopic, retained); -} - -void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic) -{ - MqttPublishPrefixTopic_P(prefix, subtopic, false); -} - -void MqttPublishPowerState(uint32_t device) -{ - char stopic[TOPSZ]; - char scommand[33]; - - if ((device < 1) || (device > devices_present)) { device = 1; } - -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (device > 1)) { - if (GetFanspeed() < MaxFanspeed()) { -#ifdef USE_DOMOTICZ - DomoticzUpdateFanState(); -#endif - snprintf_P(scommand, sizeof(scommand), PSTR(D_CMND_FANSPEED)); - GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); - Response_P(S_JSON_COMMAND_NVALUE, scommand, GetFanspeed()); - MqttPublish(stopic); - } - } else { -#endif - GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable); - GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); - Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(power, device -1))); - MqttPublish(stopic); - - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P(GetStateText(bitRead(power, device -1))); - MqttPublish(stopic, Settings.flag.mqtt_power_retain); -#ifdef USE_SONOFF_IFAN - } -#endif -} - -void MqttPublishAllPowerState() -{ - for (uint32_t i = 1; i <= devices_present; i++) { - MqttPublishPowerState(i); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { break; } -#endif - } -} - -void MqttPublishPowerBlinkState(uint32_t device) -{ - char scommand[33]; - - if ((device < 1) || (device > devices_present)) { - device = 1; - } - Response_P(PSTR("{\"%s\":\"" D_JSON_BLINK " %s\"}"), - GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable), GetStateText(bitRead(blink_mask, device -1))); - - MqttPublishPrefixTopic_P(RESULT_OR_STAT, S_RSLT_POWER); -} - - - -uint16_t MqttConnectCount() -{ - return Mqtt.connect_count; -} - -void MqttDisconnected(int state) -{ - Mqtt.connected = false; - Mqtt.retry_counter = Settings.mqtt_retry; - - MqttClient.disconnect(); - -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), AWS_endpoint, Settings.mqtt_port, state, Mqtt.retry_counter); -#else - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), Settings.mqtt_host, Settings.mqtt_port, state, Mqtt.retry_counter); -#endif - rules_flag.mqtt_disconnected = 1; -} - -void MqttConnected(void) -{ - char stopic[TOPSZ]; - - if (Mqtt.allowed) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_CONNECTED)); - Mqtt.connected = true; - Mqtt.retry_counter = 0; - Mqtt.connect_count++; - - GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); - Response_P(PSTR(D_ONLINE)); - MqttPublish(stopic, true); - - - mqtt_data[0] = '\0'; - MqttPublishPrefixTopic_P(CMND, S_RSLT_POWER); - - GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); - MqttSubscribe(stopic); - if (strstr_P(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != nullptr) { - GetTopic_P(stopic, CMND, Settings.mqtt_grptopic, PSTR("#")); - MqttSubscribe(stopic); - GetFallbackTopic_P(stopic, CMND, PSTR("#")); - MqttSubscribe(stopic); - } - - XdrvCall(FUNC_MQTT_SUBSCRIBE); - } - - if (Mqtt.initial_connection_state) { - Response_P(PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), - ModuleName().c_str(), my_version, my_image, GetFallbackTopic_P(stopic, CMND, ""), Settings.mqtt_grptopic); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); -#ifdef USE_WEBSERVER - if (Settings.webserver) { - Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"), - (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); - } -#endif - Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), (GetResetReason() == "Exception") ? ESP.getResetInfo().c_str() : GetResetReason().c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); - MqttPublishAllPowerState(); - if (Settings.tele_period) { tele_period = Settings.tele_period -9; } - rules_flag.system_boot = 1; - XdrvCall(FUNC_MQTT_INIT); - } - Mqtt.initial_connection_state = 0; - - global_state.mqtt_down = 0; - if (Settings.flag.mqtt_enabled) { - rules_flag.mqtt_connected = 1; - } -} - -void MqttReconnect(void) -{ - char stopic[TOPSZ]; - - Mqtt.allowed = Settings.flag.mqtt_enabled; - if (Mqtt.allowed) { -#ifdef USE_DISCOVERY -#ifdef MQTT_HOST_DISCOVERY - MqttDiscoverServer(); -#endif -#endif - if (!strlen(Settings.mqtt_host) || !Settings.mqtt_port) { - Mqtt.allowed = false; - } -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - - if (!AWS_IoT_Private_Key || !AWS_IoT_Client_Certificate) { - Mqtt.allowed = false; - } -#endif - } - if (!Mqtt.allowed) { - MqttConnected(); - return; - } - -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); - - Mqtt.connected = false; - Mqtt.retry_counter = Settings.mqtt_retry; - global_state.mqtt_down = 1; - - char *mqtt_user = nullptr; - char *mqtt_pwd = nullptr; - if (strlen(Settings.mqtt_user) > 0) mqtt_user = Settings.mqtt_user; - if (strlen(Settings.mqtt_pwd) > 0) mqtt_pwd = Settings.mqtt_pwd; - - GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); - Response_P(S_OFFLINE); - - if (MqttClient.connected()) { MqttClient.disconnect(); } -#ifdef USE_MQTT_TLS - tlsClient->stop(); -#else - EspClient = WiFiClient(); - MqttClient.setClient(EspClient); -#endif - - if (2 == Mqtt.initial_connection_state) { - Mqtt.initial_connection_state = 1; - } - - MqttClient.setCallback(MqttDataHandler); -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - - tlsClient->setClientECCert(AWS_IoT_Client_Certificate, - AWS_IoT_Private_Key, - 0xFFFF , 0); - MqttClient.setServer(AWS_endpoint, Settings.mqtt_port); -#else - MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); -#endif - - uint32_t mqtt_connect_time = millis(); -#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) - bool allow_all_fingerprints = false; - bool learn_fingerprint1 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[0], 0x00); - bool learn_fingerprint2 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[1], 0x00); - allow_all_fingerprints |= is_fingerprint_mono_value(Settings.mqtt_fingerprint[0], 0xff); - allow_all_fingerprints |= is_fingerprint_mono_value(Settings.mqtt_fingerprint[1], 0xff); - allow_all_fingerprints |= learn_fingerprint1; - allow_all_fingerprints |= learn_fingerprint2; - tlsClient->setPubKeyFingerprint(Settings.mqtt_fingerprint[0], Settings.mqtt_fingerprint[1], allow_all_fingerprints); -#endif -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "AWS IoT endpoint: %s"), AWS_endpoint); - - if (MqttClient.connect(mqtt_client, nullptr, nullptr, stopic, 1, false, mqtt_data, MQTT_CLEAN_SESSION)) { -#else - if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data, MQTT_CLEAN_SESSION)) { -#endif -#ifdef USE_MQTT_TLS - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connected in %d ms, max ThunkStack used %d"), - millis() - mqtt_connect_time, tlsClient->getMaxThunkStackUse()); - if (!tlsClient->getMFLNStatus()) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR("MFLN not supported by TLS server")); - } -#ifndef USE_MQTT_TLS_CA_CERT - - char buf_fingerprint[64]; - ToHex_P((unsigned char *)tlsClient->getRecvPubKeyFingerprint(), 20, buf_fingerprint, sizeof(buf_fingerprint), ' '); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Server fingerprint: %s"), buf_fingerprint); - - if (learn_fingerprint1 || learn_fingerprint2) { - - bool fingerprint_matched = false; - const uint8_t *recv_fingerprint = tlsClient->getRecvPubKeyFingerprint(); - if (0 == memcmp(recv_fingerprint, Settings.mqtt_fingerprint[0], 20)) { - fingerprint_matched = true; - } - if (0 == memcmp(recv_fingerprint, Settings.mqtt_fingerprint[1], 20)) { - fingerprint_matched = true; - } - if (!fingerprint_matched) { - - if (learn_fingerprint1) { - memcpy(Settings.mqtt_fingerprint[0], recv_fingerprint, 20); - } - if (learn_fingerprint2) { - memcpy(Settings.mqtt_fingerprint[1], recv_fingerprint, 20); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "Fingerprint learned: %s"), buf_fingerprint); - - SettingsSaveAll(); - } - } -#endif -#endif - MqttConnected(); - } else { -#ifdef USE_MQTT_TLS - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connection error: %d"), tlsClient->getLastError()); -#endif - MqttDisconnected(MqttClient.state()); - } -} - -void MqttCheck(void) -{ - if (Settings.flag.mqtt_enabled) { - if (!MqttIsConnected()) { - global_state.mqtt_down = 1; - if (!Mqtt.retry_counter) { -#ifdef USE_DISCOVERY -#ifdef MQTT_HOST_DISCOVERY - if (!strlen(Settings.mqtt_host) && !Wifi.mdns_begun) { return; } -#endif -#endif - MqttReconnect(); - } else { - Mqtt.retry_counter--; - } - } else { - global_state.mqtt_down = 0; - } - } else { - global_state.mqtt_down = 0; - if (Mqtt.initial_connection_state) MqttReconnect(); - } -} - - - - - -#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) -void CmndMqttFingerprint(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - char fingerprint[60]; - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(fingerprint))) { - strlcpy(fingerprint, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? MQTT_FINGERPRINT1 : MQTT_FINGERPRINT2 : XdrvMailbox.data, sizeof(fingerprint)); - char *p = fingerprint; - for (uint32_t i = 0; i < 20; i++) { - Settings.mqtt_fingerprint[XdrvMailbox.index -1][i] = strtol(p, &p, 16); - } - restart_flag = 2; - } - ResponseCmndIdxChar(ToHex_P((unsigned char *)Settings.mqtt_fingerprint[XdrvMailbox.index -1], 20, fingerprint, sizeof(fingerprint), ' ')); - } -} -#endif - -#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) -void CmndMqttUser(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_user))) { - strlcpy(Settings.mqtt_user, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_USER : XdrvMailbox.data, sizeof(Settings.mqtt_user)); - restart_flag = 2; - } - ResponseCmndChar(Settings.mqtt_user); -} - -void CmndMqttPassword(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_pwd))) { - strlcpy(Settings.mqtt_pwd, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_PASS : XdrvMailbox.data, sizeof(Settings.mqtt_pwd)); - ResponseCmndChar(Settings.mqtt_pwd); - restart_flag = 2; - } else { - Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); - } -} -#endif - -void CmndMqttHost(void) -{ -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len <= sizeof(Settings.mqtt_host) + sizeof(Settings.mqtt_user) - 2)) { - setLongMqttHost((SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data); - restart_flag = 2; - } - ResponseCmndChar(AWS_endpoint); -#else - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_host))) { - strlcpy(Settings.mqtt_host, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data, sizeof(Settings.mqtt_host)); - restart_flag = 2; - } - ResponseCmndChar(Settings.mqtt_host); -#endif -} - -void CmndMqttPort(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 65536)) { - Settings.mqtt_port = (1 == XdrvMailbox.payload) ? MQTT_PORT : XdrvMailbox.payload; - restart_flag = 2; - } - ResponseCmndNumber(Settings.mqtt_port); -} - -void CmndMqttRetry(void) -{ - if ((XdrvMailbox.payload >= MQTT_RETRY_SECS) && (XdrvMailbox.payload < 32001)) { - Settings.mqtt_retry = XdrvMailbox.payload; - Mqtt.retry_counter = Settings.mqtt_retry; - } - ResponseCmndNumber(Settings.mqtt_retry); -} - -void CmndStateText(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.state_text[0]))) { - for (uint32_t i = 0; i <= XdrvMailbox.data_len; i++) { - if (XdrvMailbox.data[i] == ' ') XdrvMailbox.data[i] = '_'; - } - strlcpy(Settings.state_text[XdrvMailbox.index -1], XdrvMailbox.data, sizeof(Settings.state_text[0])); - } - ResponseCmndIdxChar(GetStateText(XdrvMailbox.index -1)); - } -} - -void CmndMqttClient(void) -{ - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_client))) { - strlcpy(Settings.mqtt_client, (SC_DEFAULT == Shortcut()) ? MQTT_CLIENT_ID : XdrvMailbox.data, sizeof(Settings.mqtt_client)); - restart_flag = 2; - } - ResponseCmndChar(Settings.mqtt_client); -} - -void CmndFullTopic(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_fulltopic))) { - MakeValidMqtt(1, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } - char stemp1[TOPSZ]; - strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_FULLTOPIC : XdrvMailbox.data, sizeof(stemp1)); - if (strcmp(stemp1, Settings.mqtt_fulltopic)) { - Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); - MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); - strlcpy(Settings.mqtt_fulltopic, stemp1, sizeof(Settings.mqtt_fulltopic)); - restart_flag = 2; - } - } - ResponseCmndChar(Settings.mqtt_fulltopic); -} - -void CmndPrefix(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_prefix[0]))) { - MakeValidMqtt(0, XdrvMailbox.data); - strlcpy(Settings.mqtt_prefix[XdrvMailbox.index -1], (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index)?SUB_PREFIX:(2==XdrvMailbox.index)?PUB_PREFIX:PUB_PREFIX2 : XdrvMailbox.data, sizeof(Settings.mqtt_prefix[0])); - - restart_flag = 2; - } - ResponseCmndIdxChar(Settings.mqtt_prefix[XdrvMailbox.index -1]); - } -} - -void CmndPublish(void) -{ - if (XdrvMailbox.data_len > 0) { - char *mqtt_part = strtok(XdrvMailbox.data, " "); - if (mqtt_part) { - char stemp1[TOPSZ]; - strlcpy(stemp1, mqtt_part, sizeof(stemp1)); - mqtt_part = strtok(nullptr, " "); - if (mqtt_part) { - strlcpy(mqtt_data, mqtt_part, sizeof(mqtt_data)); - } else { - mqtt_data[0] = '\0'; - } - MqttPublishDirect(stemp1, (XdrvMailbox.index == 2)); - - mqtt_data[0] = '\0'; - } - } -} - -void CmndGroupTopic(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_grptopic))) { - MakeValidMqtt(0, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } - strlcpy(Settings.mqtt_grptopic, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data, sizeof(Settings.mqtt_grptopic)); - restart_flag = 2; - } - ResponseCmndChar(Settings.mqtt_grptopic); -} - -void CmndTopic(void) -{ - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_topic))) { - MakeValidMqtt(0, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } - char stemp1[TOPSZ]; - strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_TOPIC : XdrvMailbox.data, sizeof(stemp1)); - if (strcmp(stemp1, Settings.mqtt_topic)) { - Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); - MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); - strlcpy(Settings.mqtt_topic, stemp1, sizeof(Settings.mqtt_topic)); - restart_flag = 2; - } - } - ResponseCmndChar(Settings.mqtt_topic); -} - -void CmndButtonTopic(void) -{ - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.button_topic))) { - MakeValidMqtt(0, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } - switch (Shortcut()) { - case SC_CLEAR: strlcpy(Settings.button_topic, "", sizeof(Settings.button_topic)); break; - case SC_DEFAULT: strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic)); break; - case SC_USER: strlcpy(Settings.button_topic, MQTT_BUTTON_TOPIC, sizeof(Settings.button_topic)); break; - default: strlcpy(Settings.button_topic, XdrvMailbox.data, sizeof(Settings.button_topic)); - } - } - ResponseCmndChar(Settings.button_topic); -} - -void CmndSwitchTopic(void) -{ - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.switch_topic))) { - MakeValidMqtt(0, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } - switch (Shortcut()) { - case SC_CLEAR: strlcpy(Settings.switch_topic, "", sizeof(Settings.switch_topic)); break; - case SC_DEFAULT: strlcpy(Settings.switch_topic, mqtt_topic, sizeof(Settings.switch_topic)); break; - case SC_USER: strlcpy(Settings.switch_topic, MQTT_SWITCH_TOPIC, sizeof(Settings.switch_topic)); break; - default: strlcpy(Settings.switch_topic, XdrvMailbox.data, sizeof(Settings.switch_topic)); - } - } - ResponseCmndChar(Settings.switch_topic); -} - -void CmndButtonRetain(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - if (!XdrvMailbox.payload) { - for (uint32_t i = 1; i <= MAX_KEYS; i++) { - SendKey(KEY_BUTTON, i, CLEAR_RETAIN); - } - } - Settings.flag.mqtt_button_retain = XdrvMailbox.payload; - } - ResponseCmndStateText(Settings.flag.mqtt_button_retain); -} - -void CmndSwitchRetain(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - if (!XdrvMailbox.payload) { - for (uint32_t i = 1; i <= MAX_SWITCHES; i++) { - SendKey(KEY_SWITCH, i, CLEAR_RETAIN); - } - } - Settings.flag.mqtt_switch_retain = XdrvMailbox.payload; - } - ResponseCmndStateText(Settings.flag.mqtt_switch_retain); -} - -void CmndPowerRetain(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - if (!XdrvMailbox.payload) { - char stemp1[TOPSZ]; - char scommand[CMDSZ]; - for (uint32_t i = 1; i <= devices_present; i++) { - GetTopic_P(stemp1, STAT, mqtt_topic, GetPowerDevice(scommand, i, sizeof(scommand), Settings.flag.device_index_enable)); - mqtt_data[0] = '\0'; - MqttPublish(stemp1, Settings.flag.mqtt_power_retain); - } - } - Settings.flag.mqtt_power_retain = XdrvMailbox.payload; - } - ResponseCmndStateText(Settings.flag.mqtt_power_retain); -} - -void CmndSensorRetain(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - if (!XdrvMailbox.payload) { - mqtt_data[0] = '\0'; - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_ENERGY), Settings.flag.mqtt_sensor_retain); - } - Settings.flag.mqtt_sensor_retain = XdrvMailbox.payload; - } - ResponseCmndStateText(Settings.flag.mqtt_sensor_retain); -} - - - - -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - -const static uint16_t tls_spi_start_sector = SPIFFS_END + 4; -const static uint8_t* tls_spi_start = (uint8_t*) ((tls_spi_start_sector * SPI_FLASH_SEC_SIZE) + 0x40200000); -const static size_t tls_spi_len = 0x1000; -const static size_t tls_block_offset = 0x0400; -const static size_t tls_block_len = 0x0400; -const static size_t tls_obj_store_offset = tls_block_offset + sizeof(tls_dir_t); - - -inline void TlsEraseBuffer(uint8_t *buffer) { - memset(buffer + tls_block_offset, 0xFF, tls_block_len); -} - - - -static br_ec_private_key EC = { - 23, - nullptr, 0 -}; - -static br_x509_certificate CHAIN[] = { - { nullptr, 0 } -}; - - - -void loadTlsDir(void) { - memcpy_P(&tls_dir, tls_spi_start + tls_block_offset, sizeof(tls_dir)); - - - if ((TLS_NAME_SKEY == tls_dir.entry[0].name) && (tls_dir.entry[0].len > 0)) { - EC.x = (unsigned char *)(tls_spi_start + tls_obj_store_offset + tls_dir.entry[0].start); - EC.xlen = tls_dir.entry[0].len; - AWS_IoT_Private_Key = &EC; - } else { - AWS_IoT_Private_Key = nullptr; - } - if ((TLS_NAME_CRT == tls_dir.entry[1].name) && (tls_dir.entry[1].len > 0)) { - CHAIN[0].data = (unsigned char *) (tls_spi_start + tls_obj_store_offset + tls_dir.entry[1].start); - CHAIN[0].data_len = tls_dir.entry[1].len; - AWS_IoT_Client_Certificate = CHAIN; - } else { - AWS_IoT_Client_Certificate = nullptr; - } - -} - -const char ALLOCATE_ERROR[] PROGMEM = "TLSKey " D_JSON_ERROR ": cannot allocate buffer."; - -void CmndTlsKey(void) { -#ifdef DEBUG_DUMP_TLS - if (0 == XdrvMailbox.index){ - CmndTlsDump(); - } -#endif - if ((XdrvMailbox.index >= 1) && (XdrvMailbox.index <= 2)) { - tls_dir_t *tls_dir_write; - - if (XdrvMailbox.data_len > 0) { - - uint8_t *spi_buffer = (uint8_t*) malloc(tls_spi_len); - if (!spi_buffer) { - AddLog_P(LOG_LEVEL_ERROR, ALLOCATE_ERROR); - return; - } - memcpy_P(spi_buffer, tls_spi_start, tls_spi_len); - - - uint32_t bin_len = decode_base64_length((unsigned char*)XdrvMailbox.data); - uint8_t *bin_buf = nullptr; - if (bin_len > 0) { - bin_buf = (uint8_t*) malloc(bin_len + 4); - if (!bin_buf) { - AddLog_P(LOG_LEVEL_ERROR, ALLOCATE_ERROR); - free(spi_buffer); - return; - } - } - - - if (bin_len > 0) { - decode_base64((unsigned char*)XdrvMailbox.data, bin_buf); - } - - - tls_dir_write = (tls_dir_t*) (spi_buffer + tls_block_offset); - - if (1 == XdrvMailbox.index) { - - - TlsEraseBuffer(spi_buffer); - if (bin_len > 0) { - if (bin_len != 32) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR("TLSKey: Certificate must be 32 bytes: %d."), bin_len); - free(spi_buffer); - free(bin_buf); - return; - } - tls_entry_t *entry = &tls_dir_write->entry[0]; - entry->name = TLS_NAME_SKEY; - entry->start = 0; - entry->len = bin_len; - memcpy(spi_buffer + tls_obj_store_offset + entry->start, bin_buf, entry->len); - } else { - - } - } else if (2 == XdrvMailbox.index) { - - if (TLS_NAME_SKEY != tls_dir.entry[0].name) { - - AddLog_P(LOG_LEVEL_INFO, PSTR("TLSKey: cannot store Cert if no Key previously stored.")); - free(spi_buffer); - free(bin_buf); - return; - } - if (bin_len <= 256) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR("TLSKey: Certificate length too short: %d."), bin_len); - free(spi_buffer); - free(bin_buf); - return; - } - tls_entry_t *entry = &tls_dir_write->entry[1]; - entry->name = TLS_NAME_CRT; - entry->start = (tls_dir_write->entry[0].start + tls_dir_write->entry[0].len + 3) & ~0x03; - entry->len = bin_len; - memcpy(spi_buffer + tls_obj_store_offset + entry->start, bin_buf, entry->len); - } - - TlsWriteSpiBuffer(spi_buffer); - free(spi_buffer); - free(bin_buf); - } - - loadTlsDir(); - Response_P(PSTR("{\"%s1\":%d,\"%s2\":%d}"), - XdrvMailbox.command, AWS_IoT_Private_Key ? tls_dir.entry[0].len : -1, - XdrvMailbox.command, AWS_IoT_Client_Certificate ? tls_dir.entry[1].len : -1); - } -} - - -extern "C" { -#include "spi_flash.h" -} - -void TlsWriteSpiBuffer(uint8_t *buf) { - bool ret = false; - SpiFlashOpResult res; - - noInterrupts(); - res = spi_flash_erase_sector(tls_spi_start_sector); - if (SPI_FLASH_RESULT_OK == res) { - res = spi_flash_write(tls_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) buf, SPI_FLASH_SEC_SIZE); - if (SPI_FLASH_RESULT_OK == res) { - ret = true; - } - } - interrupts(); -} - -#ifdef DEBUG_DUMP_TLS - -uint32_t bswap32(uint32_t x) { - return ((x << 24) & 0xff000000 ) | - ((x << 8) & 0x00ff0000 ) | - ((x >> 8) & 0x0000ff00 ) | - ((x >> 24) & 0x000000ff ); -} -void CmndTlsDump(void) { - uint32_t start = (uint32_t)tls_spi_start + tls_block_offset; - uint32_t end = start + tls_block_len -1; - for (uint32_t pos = start; pos < end; pos += 0x10) { - uint32_t* values = (uint32_t*)(pos); - Serial.printf_P(PSTR("%08x: %08x %08x %08x %08x\n"), pos, bswap32(values[0]), bswap32(values[1]), bswap32(values[2]), bswap32(values[3])); - } -} -#endif -#endif - - - - - -#ifdef USE_WEBSERVER - -#define WEB_HANDLE_MQTT "mq" - -const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT; - -const char HTTP_BTN_MENU_MQTT[] PROGMEM = - "

"; - -const char HTTP_FORM_MQTT1[] PROGMEM = - "
 " D_MQTT_PARAMETERS " " - "
" - "

" D_HOST " (" MQTT_HOST ")

" - "

" D_PORT " (" STR(MQTT_PORT) ")

" - "

" D_CLIENT " (%s)

"; -const char HTTP_FORM_MQTT2[] PROGMEM = -#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) - "

" D_USER " (" MQTT_USER ")

" - "

" D_PASSWORD "

" -#endif - "

" D_TOPIC " = %%topic%% (%s)

" - "

" D_FULL_TOPIC " (%s)

"; - -void HandleMqttConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT); - - if (WebServer->hasArg("save")) { - MqttSaveSettings(); - WebRestart(1); - return; - } - - char str[sizeof(Settings.mqtt_client)]; - - WSContentStart_P(S_CONFIGURE_MQTT); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_MQTT1, -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - AWS_endpoint, -#else - Settings.mqtt_host, -#endif - Settings.mqtt_port, - Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, Settings.mqtt_client); - WSContentSend_P(HTTP_FORM_MQTT2, - (Settings.mqtt_user[0] == '\0') ? "0" : Settings.mqtt_user, - Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, Settings.mqtt_topic, - MQTT_FULLTOPIC, MQTT_FULLTOPIC, Settings.mqtt_fulltopic); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void MqttSaveSettings(void) -{ - char tmp[100]; - char stemp[TOPSZ]; - char stemp2[TOPSZ]; - - WebGetArg("mt", tmp, sizeof(tmp)); - strlcpy(stemp, (!strlen(tmp)) ? MQTT_TOPIC : tmp, sizeof(stemp)); - MakeValidMqtt(0, stemp); - WebGetArg("mf", tmp, sizeof(tmp)); - strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); - MakeValidMqtt(1, stemp2); - if ((strcmp(stemp, Settings.mqtt_topic)) || (strcmp(stemp2, Settings.mqtt_fulltopic))) { - Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); - MqttPublishPrefixTopic_P(TELE, S_LWT, true); - } - strlcpy(Settings.mqtt_topic, stemp, sizeof(Settings.mqtt_topic)); - strlcpy(Settings.mqtt_fulltopic, stemp2, sizeof(Settings.mqtt_fulltopic)); - WebGetArg("mh", tmp, sizeof(tmp)); -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - setLongMqttHost((!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp); -#else - strlcpy(Settings.mqtt_host, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_host)); -#endif - WebGetArg("ml", tmp, sizeof(tmp)); - Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); - WebGetArg("mc", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_client, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp, sizeof(Settings.mqtt_client)); -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), - AWS_endpoint, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_topic, Settings.mqtt_fulltopic); -#else - WebGetArg("mu", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user)); - WebGetArg("mp", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? Settings.mqtt_pwd : tmp, sizeof(Settings.mqtt_pwd)); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), - Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_topic, Settings.mqtt_fulltopic); -#endif -} -#endif - - - - - -bool Xdrv02(uint8_t function) -{ - bool result = false; - - if (Settings.flag.mqtt_enabled) { - switch (function) { - case FUNC_PRE_INIT: - MqttInit(); - break; - case FUNC_EVERY_50_MSECOND: - MqttClient.loop(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_MQTT); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); - break; -#endif - case FUNC_COMMAND: - result = DecodeCommand(kMqttCommands, MqttCommand); - break; - } - } - return result; -} -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_03_energy.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_03_energy.ino" -#ifdef USE_ENERGY_SENSOR - - - - -#define XDRV_03 3 -#define XSNS_03 3 - - - - -#define ENERGY_NONE 0 -#define ENERGY_WATCHDOG 4 - -#include - -#define D_CMND_POWERCAL "PowerCal" -#define D_CMND_VOLTAGECAL "VoltageCal" -#define D_CMND_CURRENTCAL "CurrentCal" -#define D_CMND_TARIFF "Tariff" -#define D_CMND_MODULEADDRESS "ModuleAddress" - -enum EnergyCommands { - CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL, - CMND_POWERSET, CMND_VOLTAGESET, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_MODULEADDRESS }; - -const char kEnergyCommands[] PROGMEM = "|" - D_CMND_POWERCAL "|" D_CMND_VOLTAGECAL "|" D_CMND_CURRENTCAL "|" - D_CMND_POWERSET "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" D_CMND_MODULEADDRESS "|" -#ifdef USE_ENERGY_MARGIN_DETECTION - D_CMND_POWERDELTA "|" D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|" -#ifdef USE_ENERGY_POWER_LIMIT - D_CMND_MAXENERGY "|" D_CMND_MAXENERGYSTART "|" - D_CMND_MAXPOWER "|" D_CMND_MAXPOWERHOLD "|" D_CMND_MAXPOWERWINDOW "|" - D_CMND_SAFEPOWER "|" D_CMND_SAFEPOWERHOLD "|" D_CMND_SAFEPOWERWINDOW "|" -#endif -#endif - D_CMND_ENERGYRESET "|" D_CMND_TARIFF ; - -void (* const EnergyCommand[])(void) PROGMEM = { - &CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, - &CmndPowerSet, &CmndVoltageSet, &CmndCurrentSet, &CmndFrequencySet, &CmndModuleAddress, -#ifdef USE_ENERGY_MARGIN_DETECTION - &CmndPowerDelta, &CmndPowerLow, &CmndPowerHigh, &CmndVoltageLow, &CmndVoltageHigh, &CmndCurrentLow, &CmndCurrentHigh, -#ifdef USE_ENERGY_POWER_LIMIT - &CmndMaxEnergy, &CmndMaxEnergyStart, - &CmndMaxPower, &CmndMaxPowerHold, &CmndMaxPowerWindow, - &CmndSafePower, &CmndSafePowerHold, &CmndSafePowerWindow, -#endif -#endif - &CmndEnergyReset, &CmndTariff }; - -const char kEnergyPhases[] PROGMEM = "|%s / %s|%s / %s / %s||[%s,%s]|[%s,%s,%s]"; - -struct ENERGY { - float voltage[3] = { 0, 0, 0 }; - float current[3] = { 0, 0, 0 }; - float active_power[3] = { 0, 0, 0 }; - float apparent_power[3] = { NAN, NAN, NAN }; - float reactive_power[3] = { NAN, NAN, NAN }; - float power_factor[3] = { NAN, NAN, NAN }; - float frequency[3] = { NAN, NAN, NAN }; - - float start_energy = 0; - float daily = 0; - float total = 0; - float export_active = NAN; - - unsigned long kWhtoday_delta = 0; - unsigned long kWhtoday_offset = 0; - unsigned long kWhtoday; - unsigned long period = 0; - - uint8_t fifth_second = 0; - uint8_t command_code = 0; - uint8_t data_valid[3] = { 0, 0, 0 }; - - uint8_t phase_count = 1; - bool voltage_common = false; - - bool voltage_available = true; - bool current_available = true; - - bool type_dc = false; - bool power_on = true; - -#ifdef USE_ENERGY_MARGIN_DETECTION - float power_history[3] = { 0 }; - uint8_t power_steady_counter = 8; - uint8_t power_delta = 0; - bool min_power_flag = false; - bool max_power_flag = false; - bool min_voltage_flag = false; - bool max_voltage_flag = false; - bool min_current_flag = false; - bool max_current_flag = false; - -#ifdef USE_ENERGY_POWER_LIMIT - uint16_t mplh_counter = 0; - uint16_t mplw_counter = 0; - uint8_t mplr_counter = 0; - uint8_t max_energy_state = 0; -#endif -#endif -} Energy; - -Ticker ticker_energy; - - - -bool EnergyTariff1Active() -{ - uint8_t tariff1 = Settings.register8[R8_ENERGY_TARIFF1_ST]; - uint8_t tariff2 = Settings.register8[R8_ENERGY_TARIFF2_ST]; - if (IsDst() && (Settings.register8[R8_ENERGY_TARIFF1_DS] != Settings.register8[R8_ENERGY_TARIFF2_DS])) { - tariff1 = Settings.register8[R8_ENERGY_TARIFF1_DS]; - tariff2 = Settings.register8[R8_ENERGY_TARIFF2_DS]; - } - if (tariff1 != tariff2) { - return ((RtcTime.hour < tariff2) || - (RtcTime.hour >= tariff1) || - (Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) || - (RtcTime.day_of_week == 7))) - ); - } else { - return false; - } -} - -void EnergyUpdateToday(void) -{ - if (Energy.kWhtoday_delta > 1000) { - unsigned long delta = Energy.kWhtoday_delta / 1000; - Energy.kWhtoday_delta -= (delta * 1000); - Energy.kWhtoday += delta; - } - - RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset + Energy.kWhtoday; - Energy.daily = (float)(RtcSettings.energy_kWhtoday) / 100000; - Energy.total = (float)(RtcSettings.energy_kWhtotal + RtcSettings.energy_kWhtoday) / 100000; - - if (RtcTime.valid){ - - uint32_t energy_diff = (uint32_t)(Energy.total * 100000) - RtcSettings.energy_usage.last_usage_kWhtotal; - RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 100000); - - uint32_t return_diff = 0; - if (!isnan(Energy.export_active)) { - return_diff = (uint32_t)(Energy.export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal; - RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(Energy.export_active * 100000); - } - - if (EnergyTariff1Active()) { - RtcSettings.energy_usage.usage1_kWhtotal += energy_diff; - RtcSettings.energy_usage.return1_kWhtotal += return_diff; - } else { - RtcSettings.energy_usage.usage2_kWhtotal += energy_diff; - RtcSettings.energy_usage.return2_kWhtotal += return_diff; - } - } -} - -void EnergyUpdateTotal(float value, bool kwh) -{ - - - - - uint32_t multiplier = (kwh) ? 100000 : 100; - - if (0 == Energy.start_energy || (value < Energy.start_energy)) { - Energy.start_energy = value; - } - else if (value != Energy.start_energy) { - Energy.kWhtoday = (unsigned long)((value - Energy.start_energy) * multiplier); - } - - if (Energy.total < (value - 0.01)){ - RtcSettings.energy_kWhtotal = (unsigned long)((value * multiplier) - Energy.kWhtoday_offset - Energy.kWhtoday); - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; - Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: Energy Total updated with hardware value")); - } - EnergyUpdateToday(); -} - - - -void Energy200ms(void) -{ - Energy.power_on = (power != 0) | Settings.flag.no_power_on_check; - - Energy.fifth_second++; - if (5 == Energy.fifth_second) { - Energy.fifth_second = 0; - - XnrgCall(FUNC_ENERGY_EVERY_SECOND); - - if (RtcTime.valid) { - if (LocalTime() == Midnight()) { - Settings.energy_kWhyesterday = RtcSettings.energy_kWhtoday; - - RtcSettings.energy_kWhtotal += RtcSettings.energy_kWhtoday; - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - Energy.kWhtoday = 0; - Energy.kWhtoday_offset = 0; - RtcSettings.energy_kWhtoday = 0; - Energy.start_energy = 0; - - Energy.kWhtoday_delta = 0; - Energy.period = Energy.kWhtoday; - EnergyUpdateToday(); -#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT) - Energy.max_energy_state = 3; -#endif - } -#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT) - if ((RtcTime.hour == Settings.energy_max_energy_start) && (3 == Energy.max_energy_state )) { - Energy.max_energy_state = 0; - } -#endif - - } - } - - XnrgCall(FUNC_EVERY_200_MSECOND); -} - -void EnergySaveState(void) -{ - Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; - - Settings.energy_kWhtoday = RtcSettings.energy_kWhtoday; - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - - Settings.energy_usage = RtcSettings.energy_usage; -} - -#ifdef USE_ENERGY_MARGIN_DETECTION -bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag) -{ - bool change; - - if (!margin) return false; - change = save_flag; - if (type) { - flag = (value > margin); - } else { - flag = (value < margin); - } - save_flag = flag; - return (change != save_flag); -} - -void EnergyMarginCheck(void) -{ - uint16_t energy_daily_u = 0; - uint16_t energy_power_u = 0; - uint16_t energy_voltage_u = 0; - uint16_t energy_current_u = 0; - bool flag; - bool jsonflg; - - if (Energy.power_steady_counter) { - Energy.power_steady_counter--; - return; - } - - if (Settings.energy_power_delta) { - float delta = abs(Energy.power_history[0] - Energy.active_power[0]); - - float min_power = (Energy.power_history[0] > Energy.active_power[0]) ? Energy.active_power[0] : Energy.power_history[0]; - if (((delta / min_power) * 100) > Settings.energy_power_delta) { - Energy.power_delta = 1; - Energy.power_history[1] = Energy.active_power[0]; - Energy.power_history[2] = Energy.active_power[0]; - } - } - Energy.power_history[0] = Energy.power_history[1]; - Energy.power_history[1] = Energy.power_history[2]; - Energy.power_history[2] = Energy.active_power[0]; - - if (Energy.power_on && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) { - energy_power_u = (uint16_t)(Energy.active_power[0]); - energy_voltage_u = (uint16_t)(Energy.voltage[0]); - energy_current_u = (uint16_t)(Energy.current[0] * 1000); - - DEBUG_DRIVER_LOG(PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); - - Response_P(PSTR("{")); - jsonflg = false; - if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, Energy.min_power_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_POWERLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(true, Settings.energy_max_power, energy_power_u, flag, Energy.max_power_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_POWERHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(false, Settings.energy_min_voltage, energy_voltage_u, flag, Energy.min_voltage_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(true, Settings.energy_max_voltage, energy_voltage_u, flag, Energy.max_voltage_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(false, Settings.energy_min_current, energy_current_u, flag, Energy.min_current_flag)) { - ResponseAppend_P(PSTR("%s%s\"" D_CMND_CURRENTLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(true, Settings.energy_max_current, energy_current_u, flag, Energy.max_current_flag)) { - ResponseAppend_P(PSTR("%s%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (jsonflg) { - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_MARGINS), MQTT_TELE_RETAIN); - EnergyMqttShow(); - } - } - -#ifdef USE_ENERGY_POWER_LIMIT - - if (Settings.energy_max_power_limit) { - if (Energy.active_power[0] > Settings.energy_max_power_limit) { - if (!Energy.mplh_counter) { - Energy.mplh_counter = Settings.energy_max_power_limit_hold; - } else { - Energy.mplh_counter--; - if (!Energy.mplh_counter) { - ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); - MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); - EnergyMqttShow(); - SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); - if (!Energy.mplr_counter) { - Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1; - } - Energy.mplw_counter = Settings.energy_max_power_limit_window; - } - } - } - else if (power && (energy_power_u <= Settings.energy_max_power_limit)) { - Energy.mplh_counter = 0; - Energy.mplr_counter = 0; - Energy.mplw_counter = 0; - } - if (!power) { - if (Energy.mplw_counter) { - Energy.mplw_counter--; - } else { - if (Energy.mplr_counter) { - Energy.mplr_counter--; - if (Energy.mplr_counter) { - ResponseTime_P(PSTR(",\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); - RestorePower(true, SRC_MAXPOWER); - } else { - ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); - MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); - EnergyMqttShow(); - } - } - } - } - } - - - if (Settings.energy_max_energy) { - energy_daily_u = (uint16_t)(Energy.daily * 1000); - if (!Energy.max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) { - Energy.max_energy_state = 1; - ResponseTime_P(PSTR(",\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); - RestorePower(true, SRC_MAXENERGY); - } - else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) { - Energy.max_energy_state = 2; - dtostrfd(Energy.daily, 3, mqtt_data); - ResponseTime_P(PSTR(",\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); - MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); - EnergyMqttShow(); - SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY); - } - } -#endif - - if (Energy.power_delta) { EnergyMqttShow(); } -} - -void EnergyMqttShow(void) -{ - - int tele_period_save = tele_period; - tele_period = 2; - mqtt_data[0] = '\0'; - ResponseAppendTime(); - EnergyShow(true); - tele_period = tele_period_save; - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - Energy.power_delta = 0; -} -#endif - -void EnergyEverySecond() -{ - - if (global_update) { - if (power && (global_temperature != 9999) && (global_temperature > Settings.param[P_OVER_TEMP])) { - SetAllPower(POWER_ALL_OFF, SRC_OVERTEMP); - } - } - - - uint32_t data_valid = Energy.phase_count; - for (uint32_t i = 0; i < Energy.phase_count; i++) { - if (Energy.data_valid[i] <= ENERGY_WATCHDOG) { - Energy.data_valid[i]++; - if (Energy.data_valid[i] > ENERGY_WATCHDOG) { - - Energy.voltage[i] = 0; - Energy.current[i] = 0; - Energy.active_power[i] = 0; - if (!isnan(Energy.apparent_power[i])) { Energy.apparent_power[i] = 0; } - if (!isnan(Energy.reactive_power[i])) { Energy.reactive_power[i] = 0; } - if (!isnan(Energy.frequency[i])) { Energy.frequency[i] = 0; } - if (!isnan(Energy.power_factor[i])) { Energy.power_factor[i] = 0; } - - data_valid--; - } - } - } - if (!data_valid) { - if (!isnan(Energy.export_active)) { Energy.export_active = 0; } - Energy.start_energy = 0; - - XnrgCall(FUNC_ENERGY_RESET); - } - -#ifdef USE_ENERGY_MARGIN_DETECTION - EnergyMarginCheck(); -#endif -} - - - - - -void EnergyCommandResponse(uint32_t nvalue, uint32_t unit) -{ - if (UNIT_MILLISECOND == unit) { - snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command); - unit = UNIT_MICROSECOND; - } - - if (Settings.flag.value_units) { - char sunit[CMDSZ]; - Response_P(S_JSON_COMMAND_LVALUE_SPACE_UNIT, XdrvMailbox.command, nvalue, GetTextIndexed(sunit, sizeof(sunit), unit, kUnitNames)); - } else { - Response_P(S_JSON_COMMAND_LVALUE, XdrvMailbox.command, nvalue); - } -} - -void CmndEnergyReset(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { - char *p; - unsigned long lnum = strtoul(XdrvMailbox.data, &p, 10); - if (p != XdrvMailbox.data) { - switch (XdrvMailbox.index) { - case 1: - - Energy.kWhtoday_offset = lnum *100; - Energy.kWhtoday = 0; - Energy.kWhtoday_delta = 0; - Energy.period = Energy.kWhtoday_offset; - Settings.energy_kWhtoday = Energy.kWhtoday_offset; - RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset; - Energy.daily = (float)Energy.kWhtoday_offset / 100000; - if (!RtcSettings.energy_kWhtotal && !Energy.kWhtoday_offset) { - Settings.energy_kWhtotal_time = LocalTime(); - } - break; - case 2: - - Settings.energy_kWhyesterday = lnum *100; - break; - case 3: - - RtcSettings.energy_kWhtotal = lnum *100; - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; - Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); - RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 1000); - break; - } - } - } - - if ((XdrvMailbox.index > 3) && (XdrvMailbox.index <= 5)) { - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - int32_t position = -1; - uint32_t values[2]; - - while ((str != nullptr) && (position < 1)) { - uint32_t value = strtoul(str, nullptr, 10); - position++; - values[position] = value *100; - str = strtok_r(nullptr, ", ", &p); - } - - switch (XdrvMailbox.index) - { - case 4: - - if (position > -1) { - RtcSettings.energy_usage.usage1_kWhtotal = values[0]; - } - if (position > 0) { - RtcSettings.energy_usage.usage2_kWhtotal = values[1]; - } - Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal; - Settings.energy_usage.usage2_kWhtotal = RtcSettings.energy_usage.usage2_kWhtotal; - break; - case 5: - - if (position > -1) { - RtcSettings.energy_usage.return1_kWhtotal = values[0]; - } - if (position > 0) { - RtcSettings.energy_usage.return2_kWhtotal = values[1]; - } - Settings.energy_usage.return1_kWhtotal = RtcSettings.energy_usage.return1_kWhtotal; - Settings.energy_usage.return2_kWhtotal = RtcSettings.energy_usage.return2_kWhtotal; - - - - break; - } - } - - char energy_total_chr[FLOATSZ]; - dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr); - char energy_daily_chr[FLOATSZ]; - dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); - char energy_yesterday_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); - - char energy_usage1_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage1_chr); - char energy_usage2_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage2_chr); - char energy_return1_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return1_chr); - char energy_return2_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return2_chr); - - Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s,\"" D_JSON_USAGE "\":[%s,%s],\"" D_JSON_EXPORT "\":[%s,%s]}}"), - XdrvMailbox.command, energy_total_chr, energy_yesterday_chr, energy_daily_chr, energy_usage1_chr, energy_usage2_chr, energy_return1_chr, energy_return2_chr); -} - -void CmndTariff(void) -{ - - - - - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - uint32_t time_type = 0; - while ((str != nullptr) && (time_type <= 2)) { - uint8_t value = strtol(str, nullptr, 10); - if ((value >= 0) && (value < 24)) { - Settings.register8[R8_ENERGY_TARIFF1_ST + (XdrvMailbox.index -1) + time_type] = value; - } - str = strtok_r(nullptr, ", ", &p); - time_type += 2; - } - } - else if (XdrvMailbox.index == 9) { - Settings.flag3.energy_weekend = XdrvMailbox.payload & 1; - } - Response_P(PSTR("{\"%s\":{\"Off-Peak\":[%d,%d],\"Standard\":[%d,%d],\"Weekend\":\"%s\"}}"), - XdrvMailbox.command, - Settings.register8[R8_ENERGY_TARIFF1_ST], Settings.register8[R8_ENERGY_TARIFF1_DS], - Settings.register8[R8_ENERGY_TARIFF2_ST], Settings.register8[R8_ENERGY_TARIFF2_DS], - GetStateText(Settings.flag3.energy_weekend)); -} - -void CmndPowerCal(void) -{ - Energy.command_code = CMND_POWERCAL; - if (XnrgCall(FUNC_COMMAND)) { - if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { - Settings.energy_power_calibration = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_power_calibration, UNIT_MICROSECOND); - } -} - -void CmndVoltageCal(void) -{ - Energy.command_code = CMND_VOLTAGECAL; - if (XnrgCall(FUNC_COMMAND)) { - if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { - Settings.energy_voltage_calibration = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_voltage_calibration, UNIT_MICROSECOND); - } -} - -void CmndCurrentCal(void) -{ - Energy.command_code = CMND_CURRENTCAL; - if (XnrgCall(FUNC_COMMAND)) { - if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { - Settings.energy_current_calibration = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_current_calibration, UNIT_MICROSECOND); - } -} - -void CmndPowerSet(void) -{ - Energy.command_code = CMND_POWERSET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandResponse(Settings.energy_power_calibration, UNIT_MILLISECOND); - } -} - -void CmndVoltageSet(void) -{ - Energy.command_code = CMND_VOLTAGESET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandResponse(Settings.energy_voltage_calibration, UNIT_MILLISECOND); - } -} - -void CmndCurrentSet(void) -{ - Energy.command_code = CMND_CURRENTSET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandResponse(Settings.energy_current_calibration, UNIT_MILLISECOND); - } -} - -void CmndFrequencySet(void) -{ - Energy.command_code = CMND_FREQUENCYSET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandResponse(Settings.energy_frequency_calibration, UNIT_MILLISECOND); - } -} - -void CmndModuleAddress(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4) && (1 == Energy.phase_count)) { - Energy.command_code = CMND_MODULEADDRESS; - if (XnrgCall(FUNC_COMMAND)) { - ResponseCmndDone(); - } - } -} - -#ifdef USE_ENERGY_MARGIN_DETECTION -void CmndPowerDelta(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 101)) { - Settings.energy_power_delta = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_power_delta, UNIT_PERCENTAGE); -} - -void CmndPowerLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_min_power = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_min_power, UNIT_WATT); -} - -void CmndPowerHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_max_power, UNIT_WATT); -} - -void CmndVoltageLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { - Settings.energy_min_voltage = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_min_voltage, UNIT_VOLT); -} - -void CmndVoltageHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { - Settings.energy_max_voltage = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_max_voltage, UNIT_VOLT); -} - -void CmndCurrentLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { - Settings.energy_min_current = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_min_current, UNIT_MILLIAMPERE); -} - -void CmndCurrentHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { - Settings.energy_max_current = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_max_current, UNIT_MILLIAMPERE); -} - -#ifdef USE_ENERGY_POWER_LIMIT -void CmndMaxPower(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_limit = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_max_power_limit, UNIT_WATT); -} - -void CmndMaxPowerHold(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_max_power_limit_hold, UNIT_SECOND); -} - -void CmndMaxPowerWindow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_max_power_limit_window, UNIT_SECOND); -} - -void CmndSafePower(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_safe_limit = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_max_power_safe_limit, UNIT_WATT); -} - -void CmndSafePowerHold(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_safe_limit_hold = (1 == XdrvMailbox.payload) ? SAFE_POWER_HOLD : XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_max_power_safe_limit_hold, UNIT_SECOND); -} - -void CmndSafePowerWindow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 1440)) { - Settings.energy_max_power_safe_limit_window = (1 == XdrvMailbox.payload) ? SAFE_POWER_WINDOW : XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_max_power_safe_limit_window, UNIT_MINUTE); -} - -void CmndMaxEnergy(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_energy = XdrvMailbox.payload; - Energy.max_energy_state = 3; - } - EnergyCommandResponse(Settings.energy_max_energy, UNIT_WATTHOUR); -} - -void CmndMaxEnergyStart(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) { - Settings.energy_max_energy_start = XdrvMailbox.payload; - } - EnergyCommandResponse(Settings.energy_max_energy_start, UNIT_HOUR); -} -#endif -#endif - -void EnergyDrvInit(void) -{ - energy_flg = ENERGY_NONE; - XnrgCall(FUNC_PRE_INIT); -} - -void EnergySnsInit(void) -{ - XnrgCall(FUNC_INIT); - - if (energy_flg) { - if (RtcSettingsValid()) { - Energy.kWhtoday_offset = RtcSettings.energy_kWhtoday; - } - else if (RtcTime.day_of_year == Settings.energy_kWhdoy) { - Energy.kWhtoday_offset = Settings.energy_kWhtoday; - } - else { - Energy.kWhtoday_offset = 0; - } - Energy.kWhtoday = 0; - Energy.kWhtoday_delta = 0; - Energy.period = Energy.kWhtoday_offset; - EnergyUpdateToday(); - ticker_energy.attach_ms(200, Energy200ms); - } -} - -#ifdef USE_WEBSERVER -const char HTTP_ENERGY_SNS1[] PROGMEM = - "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" - "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" - "{s}" D_POWER_FACTOR "{m}%s{e}"; - -const char HTTP_ENERGY_SNS2[] PROGMEM = - "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; - -const char HTTP_ENERGY_SNS3[] PROGMEM = - "{s}" D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; -#endif - -char* EnergyFormatIndex(char* result, char* input, bool json, uint32_t index, bool single = false) -{ - char layout[16]; - GetTextIndexed(layout, sizeof(layout), (index -1) + (3 * json), kEnergyPhases); - switch (index) { - case 2: - snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ); - break; - case 3: - snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ, input + FLOATSZ + FLOATSZ); - break; - default: - snprintf_P(result, FLOATSZ *3, input); - } - return result; -} - -char* EnergyFormat(char* result, char* input, bool json, bool single = false) -{ - uint8_t index = (single) ? 1 : Energy.phase_count; - return EnergyFormatIndex(result, input, json, index, single); -} - -void EnergyShow(bool json) -{ - for (uint32_t i = 0; i < Energy.phase_count; i++) { - if (Energy.voltage_common) { - Energy.voltage[i] = Energy.voltage[0]; - } - } - - float power_factor_knx = Energy.power_factor[0]; - - char apparent_power_chr[Energy.phase_count][FLOATSZ]; - char reactive_power_chr[Energy.phase_count][FLOATSZ]; - char power_factor_chr[Energy.phase_count][FLOATSZ]; - char frequency_chr[Energy.phase_count][FLOATSZ]; - if (!Energy.type_dc) { - if (Energy.current_available && Energy.voltage_available) { - for (uint32_t i = 0; i < Energy.phase_count; i++) { - float apparent_power = Energy.apparent_power[i]; - if (isnan(apparent_power)) { - apparent_power = Energy.voltage[i] * Energy.current[i]; - } - if (apparent_power < Energy.active_power[i]) { - Energy.active_power[i] = apparent_power; - } - - float power_factor = Energy.power_factor[i]; - if (isnan(power_factor)) { - power_factor = (Energy.active_power[i] && apparent_power) ? Energy.active_power[i] / apparent_power : 0; - if (power_factor > 1) { - power_factor = 1; - } - } - if (0 == i) { power_factor_knx = power_factor; } - - float reactive_power = Energy.reactive_power[i]; - if (isnan(reactive_power)) { - reactive_power = 0; - uint32_t difference = ((uint32_t)(apparent_power * 100) - (uint32_t)(Energy.active_power[i] * 100)) / 10; - if ((Energy.current[i] > 0.005) && ((difference > 15) || (difference > (uint32_t)(apparent_power * 100 / 1000)))) { - - - reactive_power = (float)(RoundSqrtInt((uint32_t)(apparent_power * apparent_power * 100) - (uint32_t)(Energy.active_power[i] * Energy.active_power[i] * 100))) / 10; - } - } - - dtostrfd(apparent_power, Settings.flag2.wattage_resolution, apparent_power_chr[i]); - dtostrfd(reactive_power, Settings.flag2.wattage_resolution, reactive_power_chr[i]); - dtostrfd(power_factor, 2, power_factor_chr[i]); - } - } - for (uint32_t i = 0; i < Energy.phase_count; i++) { - float frequency = Energy.frequency[i]; - if (isnan(Energy.frequency[i])) { - frequency = 0; - } - dtostrfd(frequency, Settings.flag2.frequency_resolution, frequency_chr[i]); - } - } - - char voltage_chr[Energy.phase_count][FLOATSZ]; - char current_chr[Energy.phase_count][FLOATSZ]; - char active_power_chr[Energy.phase_count][FLOATSZ]; - for (uint32_t i = 0; i < Energy.phase_count; i++) { - dtostrfd(Energy.voltage[i], Settings.flag2.voltage_resolution, voltage_chr[i]); - dtostrfd(Energy.current[i], Settings.flag2.current_resolution, current_chr[i]); - dtostrfd(Energy.active_power[i], Settings.flag2.wattage_resolution, active_power_chr[i]); - } - - char energy_daily_chr[FLOATSZ]; - dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); - char energy_yesterday_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); - - char energy_total_chr[3][FLOATSZ]; - dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr[0]); - char export_active_chr[3][FLOATSZ]; - dtostrfd(Energy.export_active, Settings.flag2.energy_resolution, export_active_chr[0]); - uint8_t energy_total_fields = 1; - if (Settings.register8[R8_ENERGY_TARIFF1_ST] != Settings.register8[R8_ENERGY_TARIFF2_ST]) { - dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[2]); - dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[2]); - energy_total_fields = 3; - } - - char value_chr[FLOATSZ *3]; - char value2_chr[FLOATSZ *3]; - char value3_chr[FLOATSZ *3]; - - if (json) { - bool show_energy_period = (0 == tele_period); - - ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"), - GetDateAndTime(DT_ENERGY).c_str(), - EnergyFormatIndex(value_chr, energy_total_chr[0], json, energy_total_fields), - energy_yesterday_chr, - energy_daily_chr); - - if (!isnan(Energy.export_active)) { - ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"), - EnergyFormatIndex(value_chr, export_active_chr[0], json, energy_total_fields)); - } - - if (show_energy_period) { - float energy = 0; - if (Energy.period) { - energy = (float)(RtcSettings.energy_kWhtoday - Energy.period) / 100; - } - Energy.period = RtcSettings.energy_kWhtoday; - char energy_period_chr[FLOATSZ]; - dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr); - ResponseAppend_P(PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr); - } - ResponseAppend_P(PSTR(",\"" D_JSON_POWERUSAGE "\":%s"), - EnergyFormat(value_chr, active_power_chr[0], json)); - if (!Energy.type_dc) { - if (Energy.current_available && Energy.voltage_available) { - ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s"), - EnergyFormat(value_chr, apparent_power_chr[0], json), - EnergyFormat(value2_chr, reactive_power_chr[0], json), - EnergyFormat(value3_chr, power_factor_chr[0], json)); - } - if (!isnan(Energy.frequency[0])) { - ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), - EnergyFormat(value_chr, frequency_chr[0], json)); - } - } - if (Energy.voltage_available) { - ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"), - EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); - } - if (Energy.current_available) { - ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"), - EnergyFormat(value_chr, current_chr[0], json)); - } - XnrgCall(FUNC_JSON_APPEND); - ResponseJsonEnd(); - -#ifdef USE_DOMOTICZ - if (show_energy_period) { - dtostrfd(Energy.total * 1000, 1, energy_total_chr[0]); - DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr[0]); - - dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100, 1, energy_total_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100, 1, energy_total_chr[2]); - dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100, 1, export_active_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100, 1, export_active_chr[2]); - DomoticzSensorP1SmartMeter(energy_total_chr[1], energy_total_chr[2], export_active_chr[1], export_active_chr[2], (int)Energy.active_power[0]); - - if (Energy.voltage_available) { - DomoticzSensor(DZ_VOLTAGE, voltage_chr[0]); - } - if (Energy.current_available) { - DomoticzSensor(DZ_CURRENT, current_chr[0]); - } - } -#endif -#ifdef USE_KNX - if (show_energy_period) { - if (Energy.voltage_available) { - KnxSensor(KNX_ENERGY_VOLTAGE, Energy.voltage[0]); - } - if (Energy.current_available) { - KnxSensor(KNX_ENERGY_CURRENT, Energy.current[0]); - } - KnxSensor(KNX_ENERGY_POWER, Energy.active_power[0]); - if (!Energy.type_dc) { - KnxSensor(KNX_ENERGY_POWERFACTOR, power_factor_knx); - } - KnxSensor(KNX_ENERGY_DAILY, Energy.daily); - KnxSensor(KNX_ENERGY_TOTAL, Energy.total); - KnxSensor(KNX_ENERGY_START, Energy.start_energy); - } -#endif -#ifdef USE_WEBSERVER - } else { - if (Energy.voltage_available) { - WSContentSend_PD(PSTR("{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}"), - EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); - } - if (Energy.current_available) { - WSContentSend_PD(PSTR("{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}"), - EnergyFormat(value_chr, current_chr[0], json)); - } - WSContentSend_PD(PSTR("{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"), - EnergyFormat(value_chr, active_power_chr[0], json)); - if (!Energy.type_dc) { - if (Energy.current_available && Energy.voltage_available) { - WSContentSend_PD(HTTP_ENERGY_SNS1, EnergyFormat(value_chr, apparent_power_chr[0], json), - EnergyFormat(value2_chr, reactive_power_chr[0], json), - EnergyFormat(value3_chr, power_factor_chr[0], json)); - } - if (!isnan(Energy.frequency[0])) { - WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), - EnergyFormat(value_chr, frequency_chr[0], json)); - } - } - WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr[0]); - if (!isnan(Energy.export_active)) { - WSContentSend_PD(HTTP_ENERGY_SNS3, export_active_chr[0]); - } - - XnrgCall(FUNC_WEB_SENSOR); -#endif - } -} - - - - - -bool Xdrv03(uint8_t function) -{ - bool result = false; - - if (FUNC_PRE_INIT == function) { - EnergyDrvInit(); - } - else if (energy_flg) { - switch (function) { - case FUNC_LOOP: - XnrgCall(FUNC_LOOP); - break; - case FUNC_EVERY_250_MSECOND: - XnrgCall(FUNC_EVERY_250_MSECOND); - break; - case FUNC_SERIAL: - result = XnrgCall(FUNC_SERIAL); - break; -#ifdef USE_ENERGY_MARGIN_DETECTION - case FUNC_SET_POWER: - Energy.power_steady_counter = 2; - break; -#endif - case FUNC_COMMAND: - result = DecodeCommand(kEnergyCommands, EnergyCommand); - break; - } - } - return result; -} - -bool Xsns03(uint8_t function) -{ - bool result = false; - - if (energy_flg) { - switch (function) { - case FUNC_EVERY_SECOND: - EnergyEverySecond(); - break; - case FUNC_JSON_APPEND: - EnergyShow(true); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - EnergyShow(false); - break; -#endif - case FUNC_SAVE_BEFORE_RESTART: - EnergySaveState(); - break; - case FUNC_INIT: - EnergySnsInit(); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" -#ifdef USE_LIGHT -# 128 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" -#define XDRV_04 4 - - -const uint8_t LIGHT_COLOR_SIZE = 25; -const uint8_t WS2812_SCHEMES = 7; - -const char kLightCommands[] PROGMEM = "|" -#ifdef USE_WS2812 - D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH "|" -#endif - D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|" - D_CMND_RGBWWTABLE "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" - D_CMND_WHITE "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ; - -void (* const LightCommand[])(void) PROGMEM = { -#ifdef USE_WS2812 - &CmndLed, &CmndPixels, &CmndRotation, &CmndWidth, -#endif - &CmndColor, &CmndColorTemperature, &CmndDimmer, &CmndLedTable, &CmndFade, - &CmndRgbwwTable, &CmndScheme, &CmndSpeed, &CmndWakeup, &CmndWakeupDuration, - &CmndWhite, &CmndChannel, &CmndHsbColor, &CmndUndocA }; - - -enum LightColorModes { - LCM_RGB = 1, LCM_CT = 2, LCM_BOTH = 3 }; - -struct LRgbColor { - uint8_t R, G, B; -}; -const uint8_t MAX_FIXED_COLOR = 12; -const LRgbColor kFixedColor[MAX_FIXED_COLOR] PROGMEM = - { 255,0,0, 0,255,0, 0,0,255, 228,32,0, 0,228,32, 0,32,228, 188,64,0, 0,160,96, 160,32,240, 255,255,0, 255,0,170, 255,255,255 }; - -struct LWColor { - uint8_t W; -}; -const uint8_t MAX_FIXED_WHITE = 4; -const LWColor kFixedWhite[MAX_FIXED_WHITE] PROGMEM = { 0, 255, 128, 32 }; - -struct LCwColor { - uint8_t C, W; -}; -const uint8_t MAX_FIXED_COLD_WARM = 4; -const LCwColor kFixedColdWarm[MAX_FIXED_COLD_WARM] PROGMEM = { 0,0, 255,0, 0,255, 128,128 }; - - - - - -#ifdef XFUNC_PTR_IN_ROM -const uint8_t _ledTable[] PROGMEM = { -#else -const uint8_t _ledTable[] = { -#endif - - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, - 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, - 7, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 24, 25, 26, 28, 29, 30, 32, 33, 35, 37, 38, 40, 42, - - 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 36, 37, 38, 39, - 41, 42, 44, 45, 47, 48, 50, 51, 53, 55, 56, 58, 60, 62, 64, 65, - 67, 69, 71, 73, 75, 78, 80, 82, 84, 86, 89, 91, 93, 96, 98,101, - 103,106,108,111,114,116,119,122,125,128,131,134,137,140,143,146, - - 75, 77, 78, 80, 82, 84, 85, 87, 89, 91, 93, 94, 96, 98,100,102, - 104,106,108,110,112,115,117,119,121,123,125,128,130,132,135,137, - 140,142,144,147,149,152,155,157,160,163,165,168,171,173,176,179, - 182,185,188,191,194,197,200,203,206,209,212,215,219,222,225,229, - - 116,118,120,121,123,125,127,128,130,132,134,136,138,139,141,143, - 145,147,149,151,153,155,157,159,161,163,165,168,170,172,174,176, - 178,181,183,185,187,190,192,194,197,199,201,204,206,209,211,214, - 216,219,221,224,226,229,232,234,237,240,242,245,248,250,253,255 -}; -# 241 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" -struct LIGHT { - unsigned long strip_timer_counter = 0; - power_t power = 0; - - uint16_t wakeup_counter = 0; - - uint8_t entry_color[LST_MAX]; - uint8_t current_color[LST_MAX]; - uint8_t new_color[LST_MAX]; - uint8_t last_color[LST_MAX]; - uint8_t color_remap[LST_MAX]; - - uint8_t wheel = 0; - uint8_t subtype = 0; - uint8_t device = 0; - uint8_t old_power = 1; - uint8_t wakeup_active = 0; - uint8_t wakeup_dimmer = 0; - uint8_t fixed_color_index = 1; - - bool update = true; - bool pwm_multi_channels = false; -} Light; - -power_t LightPower(void) -{ - return Light.power; -} - -uint8_t LightDevice(void) -{ - return Light.device; -} - -static uint32_t min3(uint32_t a, uint32_t b, uint32_t c) { - return (a < b && a < c) ? a : (b < c) ? b : c; -} -# 316 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" -class LightStateClass { - private: - uint16_t _hue = 0; - uint8_t _sat = 255; - uint8_t _briRGB = 255; - - uint8_t _r = 255; - uint8_t _g = 255; - uint8_t _b = 255; - - uint8_t _subtype = 0; - uint16_t _ct = 153; - uint8_t _wc = 255; - uint8_t _ww = 0; - uint8_t _briCT = 255; - - uint8_t _color_mode = LCM_RGB; - - public: - LightStateClass() { - - } - - void setSubType(uint8_t sub_type) { - _subtype = sub_type; - } -# 351 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" - uint8_t setColorMode(uint8_t cm) { - uint8_t prev_cm = _color_mode; - if (cm < LCM_RGB) { cm = LCM_RGB; } - if (cm > LCM_BOTH) { cm = LCM_BOTH; } - uint8_t maxbri = (_briRGB >= _briCT) ? _briRGB : _briCT; - - switch (_subtype) { - case LST_COLDWARM: - _color_mode = LCM_CT; - break; - - case LST_NONE: - case LST_SINGLE: - case LST_RGB: - default: - _color_mode = LCM_RGB; - break; - - case LST_RGBW: - case LST_RGBWC: - _color_mode = cm; - break; - } - if (LCM_RGB == _color_mode) { - _briCT = 0; - if (0 == _briRGB) { _briRGB = maxbri; } - } - if (LCM_CT == _color_mode) { - _briRGB = 0; - if (0 == _briCT) { _briCT = maxbri; } - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setColorMode prev_cm (%d) req_cm (%d) new_cm (%d)", prev_cm, cm, _color_mode); -#endif - return prev_cm; - } - - inline uint8_t getColorMode() { - return _color_mode; - } - - void addRGBMode() { - setColorMode(_color_mode | LCM_RGB); - } - void addCTMode() { - setColorMode(_color_mode | LCM_CT); - } - - - void getRGB(uint8_t *r, uint8_t *g, uint8_t *b) { - if (r) { *r = _r; } - if (g) { *g = _g; } - if (b) { *b = _b; } - } - - - - void getCW(uint8_t *rc, uint8_t *rw) { - if (rc) { *rc = _wc; } - if (rw) { *rw = _ww; } - } - - - void getActualRGBCW(uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *c, uint8_t *w) { - bool rgb_channels_on = _color_mode & LCM_RGB; - bool ct_channels_on = _color_mode & LCM_CT; - - if (r) { *r = rgb_channels_on ? changeUIntScale(_r, 0, 255, 0, _briRGB) : 0; } - if (g) { *g = rgb_channels_on ? changeUIntScale(_g, 0, 255, 0, _briRGB) : 0; } - if (b) { *b = rgb_channels_on ? changeUIntScale(_b, 0, 255, 0, _briRGB) : 0; } - - if (c) { *c = ct_channels_on ? changeUIntScale(_wc, 0, 255, 0, _briCT) : 0; } - if (w) { *w = ct_channels_on ? changeUIntScale(_ww, 0, 255, 0, _briCT) : 0; } - } - - uint8_t getChannels(uint8_t *channels) { - getActualRGBCW(&channels[0], &channels[1], &channels[2], &channels[3], &channels[4]); - } - - void getHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { - if (hue) { *hue = _hue; } - if (sat) { *sat = _sat; } - if (bri) { *bri = _briRGB; } - } - - - uint8_t getBri(void) { - - return (_briRGB >= _briCT) ? _briRGB : _briCT; - } - - - inline uint8_t getBriCT() { - return _briCT; - } - - static inline uint8_t DimmerToBri(uint8_t dimmer) { - return changeUIntScale(dimmer, 0, 100, 0, 255); - } - static uint8_t BriToDimmer(uint8_t bri) { - uint8_t dimmer = changeUIntScale(bri, 0, 255, 0, 100); - - if ((dimmer == 0) && (bri > 0)) { dimmer = 1; } - return dimmer; - } - - uint8_t getDimmer() { - return BriToDimmer(getBri()); - } - - inline uint16_t getCT() { - return _ct; - } - - - void getXY(float *x, float *y) { - RgbToXy(_r, _g, _b, x, y); - } - - - - void setBri(uint8_t bri) { - setBriRGB(_color_mode & LCM_RGB ? bri : 0); - setBriCT(_color_mode & LCM_CT ? bri : 0); -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setBri RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); -#endif - } - - - uint8_t setBriRGB(uint8_t bri_rgb) { - uint8_t prev_bri = _briRGB; - _briRGB = bri_rgb; - if (bri_rgb > 0) { addRGBMode(); } - return prev_bri; - } - - - uint8_t setBriCT(uint8_t bri_ct) { - uint8_t prev_bri = _briCT; - _briCT = bri_ct; - if (bri_ct > 0) { addCTMode(); } - return prev_bri; - } - - inline uint8_t getBriRGB() { - return _briRGB; - } - - void setDimmer(uint8_t dimmer) { - setBri(DimmerToBri(dimmer)); - } - - void setCT(uint16_t ct) { - if (0 == ct) { - - setColorMode(LCM_RGB); - } else { - ct = (ct < 153 ? 153 : (ct > 500 ? 500 : ct)); - _ww = changeUIntScale(ct, 153, 500, 0, 255); - _wc = 255 - _ww; - _ct = ct; - addCTMode(); - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setCT RGB raw (%d %d %d) HS (%d %d) briRGB (%d) briCT (%d) CT (%d)", _r, _g, _b, _hue, _sat, _briRGB, _briCT, _ct); -#endif - } -# 534 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" - void setCW(uint8_t c, uint8_t w, bool free_range = false) { - uint16_t max = (w > c) ? w : c; - uint16_t sum = c + w; - - if (0 == max) { - _briCT = 0; - setColorMode(LCM_RGB); - } else { - if (!free_range) { - - _ww = changeUIntScale(w, 0, sum, 0, 255); - _wc = 255 - _ww; - } else { - _ww = changeUIntScale(w, 0, max, 0, 255); - _wc = changeUIntScale(c, 0, max, 0, 255); - } - _ct = changeUIntScale(w, 0, sum, 153, 500); - addCTMode(); - if (_color_mode & LCM_CT) { _briCT = free_range ? max : (sum > 255 ? 255 : sum); } - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setCW CW (%d %d) CT (%d) briCT (%d)", c, w, _ct, _briCT); -#endif - } - - - uint8_t setRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { - uint16_t hue; - uint8_t sat; -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setRGB RGB input (%d %d %d)", r, g, b); -#endif - - uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; - - if (0 == max) { - r = g = b = 255; - setColorMode(LCM_CT); - } else { - if (255 > max) { - - r = changeUIntScale(r, 0, max, 0, 255); - g = changeUIntScale(g, 0, max, 0, 255); - b = changeUIntScale(b, 0, max, 0, 255); - } - addRGBMode(); - } - if (!keep_bri) { - _briRGB = (_color_mode & LCM_RGB) ? max : 0; - } - - RgbToHsb(r, g, b, &hue, &sat, nullptr); - _r = r; - _g = g; - _b = b; - _hue = hue; - _sat = sat; -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setRGB RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); -#endif - return max; - } - - void setHS(uint16_t hue, uint8_t sat) { - uint8_t r, g, b; - HsToRgb(hue, sat, &r, &g, &b); - _r = r; - _g = g; - _b = b; - _hue = hue; - _sat = sat; - addRGBMode(); -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setHS HS (%d %d) rgb (%d %d %d)", hue, sat, r, g, b); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setHS RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); -#endif - } - - - - - void setChannels(uint8_t *channels) { - setRGB(channels[0], channels[1], channels[2]); - setCW(channels[3], channels[4], true); -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels (%d %d %d %d %d)", - channels[0], channels[1], channels[2], channels[3], channels[4]); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels CT (%d) briRGB (%d) briCT (%d)", _ct, _briRGB, _briCT); -#endif - } - - - static void RgbToHsb(uint8_t r, uint8_t g, uint8_t b, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri); - static void HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b); - static void RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y); - static void XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb); - -}; -# 640 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" -void LightStateClass::RgbToHsb(uint8_t ir, uint8_t ig, uint8_t ib, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri) { - uint32_t r = ir; - uint32_t g = ig; - uint32_t b = ib; - uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; - uint32_t min = (r < g && r < b) ? r : (g < b) ? g : b; - uint32_t d = max - min; - - uint16_t hue = 0; - uint8_t sat = 0; - uint8_t bri = max; - - if (d != 0) { - sat = changeUIntScale(d, 0, max, 0, 255); - if (r == max) { - hue = (g > b) ? changeUIntScale(g-b,0,d,0,60) : 360 - changeUIntScale(b-g,0,d,0,60); - } else if (g == max) { - hue = (b > r) ? 120 + changeUIntScale(b-r,0,d,0,60) : 120 - changeUIntScale(r-b,0,d,0,60); - } else { - hue = (r > g) ? 240 + changeUIntScale(r-g,0,d,0,60) : 240 - changeUIntScale(g-r,0,d,0,60); - } - hue = hue % 360; - } - - if (r_hue) *r_hue = hue; - if (r_sat) *r_sat = sat; - if (r_bri) *r_bri = bri; - -} - -void LightStateClass::HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { - uint32_t r = 255; - uint32_t g = 255; - uint32_t b = 255; - - hue = hue % 360; - - if (sat > 0) { - uint32_t i = hue / 60; - uint32_t f = hue % 60; - uint32_t q = 255 - changeUIntScale(f, 0, 60, 0, sat); - uint32_t p = 255 - sat; - uint32_t t = 255 - changeUIntScale(60 - f, 0, 60, 0, sat); - - switch (i) { - case 0: - - g = t; - b = p; - break; - case 1: - r = q; - - b = p; - break; - case 2: - r = p; - - b = t; - break; - case 3: - r = p; - g = q; - - break; - case 4: - r = t; - g = p; - - break; - default: - - g = p; - b = q; - break; - } - } - if (r_r) *r_r = r; - if (r_g) *r_g = g; - if (r_b) *r_b = b; -} - -#define POW FastPrecisePowf - -void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y) { - float x = 0.31271f; - float y = 0.32902f; - - if (i_r + i_b + i_g > 0) { - float r = (float)i_r / 255.0f; - float g = (float)i_g / 255.0f; - float b = (float)i_b / 255.0f; - - - r = (r > 0.04045f) ? POW((r + 0.055f) / (1.0f + 0.055f), 2.4f) : (r / 12.92f); - g = (g > 0.04045f) ? POW((g + 0.055f) / (1.0f + 0.055f), 2.4f) : (g / 12.92f); - b = (b > 0.04045f) ? POW((b + 0.055f) / (1.0f + 0.055f), 2.4f) : (b / 12.92f); - - - - float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; - float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; - float Z = r * 0.000000f + g * 0.053077f + b * 1.035763f; - - x = X / (X + Y + Z); - y = Y / (X + Y + Z); - - } - if (r_x) *r_x = x; - if (r_y) *r_y = y; -} - -void LightStateClass::XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb) -{ - x = (x > 0.99f ? 0.99f : (x < 0.01f ? 0.01f : x)); - y = (y > 0.99f ? 0.99f : (y < 0.01f ? 0.01f : y)); - float z = 1.0f - x - y; - - float X = x / y; - float Z = z / y; - - - - float r = X * 3.2406f - 1.5372f - Z * 0.4986f; - float g = -X * 0.9689f + 1.8758f + Z * 0.0415f; - float b = X * 0.0557f - 0.2040f + Z * 1.0570f; - float max = (r > g && r > b) ? r : (g > b) ? g : b; - r = r / max; - g = g / max; - b = b / max; - r = (r <= 0.0031308f) ? 12.92f * r : 1.055f * POW(r, (1.0f / 2.4f)) - 0.055f; - g = (g <= 0.0031308f) ? 12.92f * g : 1.055f * POW(g, (1.0f / 2.4f)) - 0.055f; - b = (b <= 0.0031308f) ? 12.92f * b : 1.055f * POW(b, (1.0f / 2.4f)) - 0.055f; - - - - - - int32_t ir = r * 255.0f + 0.5f; - int32_t ig = g * 255.0f + 0.5f; - int32_t ib = b * 255.0f + 0.5f; - if (rr) { *rr = (ir > 255 ? 255: (ir < 0 ? 0 : ir)); } - if (rg) { *rg = (ig > 255 ? 255: (ig < 0 ? 0 : ig)); } - if (rb) { *rb = (ib > 255 ? 255: (ib < 0 ? 0 : ib)); } -} - -class LightControllerClass { -private: - LightStateClass *_state; - - - bool _ct_rgb_linked = true; - bool _pwm_multi_channels = false; - -public: - LightControllerClass(LightStateClass& state) { - _state = &state; - } - - void setSubType(uint8_t sub_type) { - _state->setSubType(sub_type); - } - - inline bool setCTRGBLinked(bool ct_rgb_linked) { - bool prev = _ct_rgb_linked; - if (_pwm_multi_channels) { - _ct_rgb_linked = false; - } else { - _ct_rgb_linked = ct_rgb_linked; - } - return prev; - } - - inline bool isCTRGBLinked() { - return _ct_rgb_linked; - } - - inline bool setPWMMultiChannel(bool pwm_multi_channels) { - bool prev = _pwm_multi_channels; - _pwm_multi_channels = pwm_multi_channels; - if (pwm_multi_channels) setCTRGBLinked(false); - return prev; - } - - inline bool isPWMMultiChannel(void) { - return _pwm_multi_channels; - } - -#ifdef DEBUG_LIGHT - void debugLogs() { - uint8_t r,g,b,c,w; - _state->getActualRGBCW(&r,&g,&b,&c,&w); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::debugLogs rgb (%d %d %d) cw (%d %d)", - r, g, b, c, w); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::debugLogs lightCurrent (%d %d %d %d %d)", - Light.current_color[0], Light.current_color[1], Light.current_color[2], - Light.current_color[3], Light.current_color[4]); - } -#endif - - void loadSettings() { -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings Settings.light_color (%d %d %d %d %d - %d)", - Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], - Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings light_type/sub (%d %d)", - light_type, Light.subtype); -#endif - - _state->setCW(Settings.light_color[3], Settings.light_color[4], true); - _state->setRGB(Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); - if (!_pwm_multi_channels) { - - - uint8_t bri = _state->DimmerToBri(Settings.light_dimmer); - if (Settings.light_color[0] + Settings.light_color[1] + Settings.light_color[2] > 0) { - _state->setBriRGB(bri); - } else { - _state->setBriCT(bri); - } - } - } - - void changeCTB(uint16_t new_ct, uint8_t briCT) { - - - - - - - if ((LST_COLDWARM != Light.subtype) && (LST_RGBW > Light.subtype)) { - return; - } - _state->setCT(new_ct); - _state->setBriCT(briCT); - if (_ct_rgb_linked) { _state->setColorMode(LCM_CT); } - saveSettings(); - calcLevels(); - - } - - void changeDimmer(uint8_t dimmer) { - uint8_t bri = changeUIntScale(dimmer, 0, 100, 0, 255); - changeBri(bri); - } - - void changeBri(uint8_t bri) { - _state->setBri(bri); - saveSettings(); - calcLevels(); - } - - void changeRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { - _state->setRGB(r, g, b, keep_bri); - if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } - saveSettings(); - calcLevels(); - } - - - void calcLevels() { - uint8_t r,g,b,c,w,briRGB,briCT; - _state->getActualRGBCW(&r,&g,&b,&c,&w); - - if (_pwm_multi_channels) { - Light.current_color[0] = r; - Light.current_color[1] = g; - Light.current_color[2] = b; - Light.current_color[3] = c; - Light.current_color[4] = w; - return; - } - briRGB = _state->getBriRGB(); - briCT = _state->getBriCT(); - - Light.current_color[0] = Light.current_color[1] = Light.current_color[2] = 0; - Light.current_color[3] = Light.current_color[4] = 0; - switch (Light.subtype) { - case LST_NONE: - Light.current_color[0] = 255; - break; - case LST_SINGLE: - Light.current_color[0] = briRGB; - break; - case LST_COLDWARM: - Light.current_color[0] = c; - Light.current_color[1] = w; - break; - case LST_RGBW: - case LST_RGBWC: - if (LST_RGBWC == Light.subtype) { - Light.current_color[3] = c; - Light.current_color[4] = w; - } else { - Light.current_color[3] = briCT; - } - - case LST_RGB: - Light.current_color[0] = r; - Light.current_color[1] = g; - Light.current_color[2] = b; - break; - } - } - - void changeHSB(uint16_t hue, uint8_t sat, uint8_t briRGB) { - _state->setHS(hue, sat); - _state->setBriRGB(briRGB); - if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } - saveSettings(); - calcLevels(); - } - - - void saveSettings() { - if (Light.pwm_multi_channels) { - - _state->getActualRGBCW(&Settings.light_color[0], &Settings.light_color[1], - &Settings.light_color[2], &Settings.light_color[3], - &Settings.light_color[4]); - Settings.light_dimmer = 100; - } else { - uint8_t cm = _state->getColorMode(); - - memset(&Settings.light_color[0], 0, sizeof(Settings.light_color)); - if (LCM_RGB & cm) { - _state->getRGB(&Settings.light_color[0], &Settings.light_color[1], &Settings.light_color[2]); - Settings.light_dimmer = _state->BriToDimmer(_state->getBriRGB()); - - if (LCM_BOTH == cm) { - - _state->getActualRGBCW(nullptr, nullptr, nullptr, &Settings.light_color[3], &Settings.light_color[4]); - } - } else if (LCM_CT == cm) { - _state->getCW(&Settings.light_color[3], &Settings.light_color[4]); - Settings.light_dimmer = _state->BriToDimmer(_state->getBriCT()); - } - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::saveSettings Settings.light_color (%d %d %d %d %d - %d)", - Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], - Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); -#endif - } - - - - - void changeChannels(uint8_t *channels) { - if (LST_COLDWARM == Light.subtype) { - - uint8_t remapped_channels[5] = {0,0,0,channels[0],channels[1]}; - _state->setChannels(remapped_channels); - } else { - _state->setChannels(channels); - } - saveSettings(); - calcLevels(); - } -}; - - - -LightStateClass light_state = LightStateClass(); -LightControllerClass light_controller = LightControllerClass(light_state); - - - - - - -uint16_t ledGamma(uint8_t v, uint16_t bits_out = 8) { - uint16_t result; - - uint32_t bits_resolution = 11 - (v / 64); - int32_t bits_correction = bits_out - bits_resolution; -#ifdef XFUNC_PTR_IN_ROM - uint32_t uncorrected_value = pgm_read_byte(_ledTable + v); -#else - uint32_t uncorrected_value = _ledTable[v]; -#endif - if (0 == bits_correction) { - - result = uncorrected_value; - } else if (bits_correction > 0) { - - - uint32_t bits_mask = (1 << bits_correction) - 1; - result = (uncorrected_value << bits_correction) | bits_mask; - } else { - - - uint32_t bits_mask = (1 << -bits_correction) - 1; - result = ((uncorrected_value + bits_mask) >> -bits_correction); - } - return result; -} - -#ifdef USE_ARILUX_RF - - - - -const uint32_t ARILUX_RF_TIME_AVOID_DUPLICATE = 1000; - -const uint8_t ARILUX_RF_MAX_CHANGES = 51; -const uint32_t ARILUX_RF_SEPARATION_LIMIT = 4300; -const uint32_t ARILUX_RF_RECEIVE_TOLERANCE = 60; - -struct ARILUX { - unsigned int rf_timings[ARILUX_RF_MAX_CHANGES]; - - unsigned long rf_received_value = 0; - unsigned long rf_last_received_value = 0; - unsigned long rf_last_time = 0; - unsigned long rf_lasttime = 0; - - unsigned int rf_change_count = 0; - unsigned int rf_repeat_count = 0; - - uint8_t rf_toggle = 0; -} Arilux; - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -#ifndef USE_WS2812_DMA -void AriluxRfInterrupt(void) ICACHE_RAM_ATTR; -#endif -#endif - -void AriluxRfInterrupt(void) -{ - unsigned long time = micros(); - unsigned int duration = time - Arilux.rf_lasttime; - - if (duration > ARILUX_RF_SEPARATION_LIMIT) { - if (abs(duration - Arilux.rf_timings[0]) < 200) { - Arilux.rf_repeat_count++; - if (Arilux.rf_repeat_count == 2) { - unsigned long code = 0; - const unsigned int delay = Arilux.rf_timings[0] / 31; - const unsigned int delayTolerance = delay * ARILUX_RF_RECEIVE_TOLERANCE / 100; - for (unsigned int i = 1; i < Arilux.rf_change_count -1; i += 2) { - code <<= 1; - if (abs(Arilux.rf_timings[i] - (delay *3)) < delayTolerance && abs(Arilux.rf_timings[i +1] - delay) < delayTolerance) { - code |= 1; - } - } - if (Arilux.rf_change_count > 49) { - Arilux.rf_received_value = code; - } - Arilux.rf_repeat_count = 0; - } - } - Arilux.rf_change_count = 0; - } - if (Arilux.rf_change_count >= ARILUX_RF_MAX_CHANGES) { - Arilux.rf_change_count = 0; - Arilux.rf_repeat_count = 0; - } - Arilux.rf_timings[Arilux.rf_change_count++] = duration; - Arilux.rf_lasttime = time; -} - -void AriluxRfHandler(void) -{ - unsigned long now = millis(); - if (Arilux.rf_received_value && !((Arilux.rf_received_value == Arilux.rf_last_received_value) && (now - Arilux.rf_last_time < ARILUX_RF_TIME_AVOID_DUPLICATE))) { - Arilux.rf_last_received_value = Arilux.rf_received_value; - Arilux.rf_last_time = now; - - uint16_t hostcode = Arilux.rf_received_value >> 8 & 0xFFFF; - if (Settings.rf_code[1][6] == Settings.rf_code[1][7]) { - Settings.rf_code[1][6] = hostcode >> 8 & 0xFF; - Settings.rf_code[1][7] = hostcode & 0xFF; - } - uint16_t stored_hostcode = Settings.rf_code[1][6] << 8 | Settings.rf_code[1][7]; - - DEBUG_DRIVER_LOG(PSTR(D_LOG_RFR D_HOST D_CODE " 0x%04X, " D_RECEIVED " 0x%06X"), stored_hostcode, Arilux.rf_received_value); - - if (hostcode == stored_hostcode) { - char command[33]; - char value = '-'; - command[0] = '\0'; - uint8_t keycode = Arilux.rf_received_value & 0xFF; - switch (keycode) { - case 1: - case 3: - snprintf_P(command, sizeof(command), PSTR(D_CMND_POWER " %d"), (1 == keycode) ? 1 : 0); - break; - case 2: - Arilux.rf_toggle++; - Arilux.rf_toggle &= 0x3; - snprintf_P(command, sizeof(command), PSTR(D_CMND_COLOR " %d"), 200 + Arilux.rf_toggle); - break; - case 4: - value = '+'; - case 7: - snprintf_P(command, sizeof(command), PSTR(D_CMND_SPEED " %c"), value); - break; - case 5: - value = '+'; - case 8: - snprintf_P(command, sizeof(command), PSTR(D_CMND_SCHEME " %c"), value); - break; - case 6: - value = '+'; - case 9: - snprintf_P(command, sizeof(command), PSTR(D_CMND_DIMMER " %c"), value); - break; - default: { - if ((keycode >= 10) && (keycode <= 21)) { - snprintf_P(command, sizeof(command), PSTR(D_CMND_COLOR " %d"), keycode -9); - } - } - } - if (strlen(command)) { - ExecuteCommand(command, SRC_LIGHT); - } - } - } - Arilux.rf_received_value = 0; -} - -void AriluxRfInit(void) -{ - if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) { - if (Settings.last_module != Settings.module) { - Settings.rf_code[1][6] = 0; - Settings.rf_code[1][7] = 0; - Settings.last_module = Settings.module; - } - Arilux.rf_received_value = 0; - - digitalWrite(pin[GPIO_ARIRFSEL], 0); - attachInterrupt(pin[GPIO_ARIRFRCV], AriluxRfInterrupt, CHANGE); - } -} - -void AriluxRfDisable(void) -{ - if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) { - detachInterrupt(pin[GPIO_ARIRFRCV]); - digitalWrite(pin[GPIO_ARIRFSEL], 1); - } -} -#endif - - - - - -extern "C" { - void os_delay_us(unsigned int); -} - -uint8_t light_pdi_pin; -uint8_t light_pdcki_pin; - -void LightDiPulse(uint8_t times) -{ - for (uint32_t i = 0; i < times; i++) { - digitalWrite(light_pdi_pin, HIGH); - digitalWrite(light_pdi_pin, LOW); - } -} - -void LightDckiPulse(uint8_t times) -{ - for (uint32_t i = 0; i < times; i++) { - digitalWrite(light_pdcki_pin, HIGH); - digitalWrite(light_pdcki_pin, LOW); - } -} - -void LightMy92x1Write(uint8_t data) -{ - for (uint32_t i = 0; i < 4; i++) { - digitalWrite(light_pdcki_pin, LOW); - digitalWrite(light_pdi_pin, (data & 0x80)); - digitalWrite(light_pdcki_pin, HIGH); - data = data << 1; - digitalWrite(light_pdi_pin, (data & 0x80)); - digitalWrite(light_pdcki_pin, LOW); - digitalWrite(light_pdi_pin, LOW); - data = data << 1; - } -} - -void LightMy92x1Init(void) -{ - uint8_t chips = 1; - if (LT_RGBWC == light_type) { - chips = 2; - } - - LightDckiPulse(chips * 32); - os_delay_us(12); - - - LightDiPulse(12); - os_delay_us(12); - for (uint32_t n = 0; n < chips; n++) { - LightMy92x1Write(0x18); - } - os_delay_us(12); - - - LightDiPulse(16); - os_delay_us(12); -} - -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 = 0; - if (LT_RGBWC == light_type) { - didx = 1; - } - - uint8_t duty[2][6] = {{ duty_r, duty_g, duty_b, duty_w, 0, 0 }, - { duty_w, duty_c, 0, duty_g, duty_r, duty_b }}; - - os_delay_us(12); - for (uint32_t channel = 0; channel < channels[didx]; channel++) { - LightMy92x1Write(duty[didx][channel]); - } - os_delay_us(12); - LightDiPulse(8); - os_delay_us(12); -} - -#ifdef USE_SM16716 -# 1281 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" -#define D_LOG_SM16716 "SM16716: " - -uint8_t sm16716_pin_clk = 100; -uint8_t sm16716_pin_dat = 100; -uint8_t sm16716_pin_sel = 100; -uint8_t sm16716_enabled = 0; - -void SM16716_SendBit(uint8_t v) -{ - - - - - - digitalWrite(sm16716_pin_dat, (v != 0) ? HIGH : LOW); - - digitalWrite(sm16716_pin_clk, HIGH); - - digitalWrite(sm16716_pin_clk, LOW); -} - -void SM16716_SendByte(uint8_t v) -{ - uint8_t mask; - - for (mask = 0x80; mask; mask >>= 1) { - SM16716_SendBit(v & mask); - } -} - -void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) -{ - if (sm16716_pin_sel < 99) { - uint8_t sm16716_should_enable = (duty_r | duty_g | duty_b); - if (!sm16716_enabled && sm16716_should_enable) { - DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color on")); - sm16716_enabled = 1; - digitalWrite(sm16716_pin_sel, HIGH); - - - delayMicroseconds(1000); - SM16716_Init(); - } - else if (sm16716_enabled && !sm16716_should_enable) { - DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color off")); - sm16716_enabled = 0; - digitalWrite(sm16716_pin_sel, LOW); - } - } - DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), duty_r, duty_g, duty_b); - - - SM16716_SendBit(1); - SM16716_SendByte(duty_r); - SM16716_SendByte(duty_g); - SM16716_SendByte(duty_b); - - - - - - SM16716_SendBit(0); - SM16716_SendByte(0); - SM16716_SendByte(0); - SM16716_SendByte(0); -} - -bool SM16716_ModuleSelected(void) -{ - sm16716_pin_clk = pin[GPIO_SM16716_CLK]; - sm16716_pin_dat = pin[GPIO_SM16716_DAT]; - sm16716_pin_sel = pin[GPIO_SM16716_SEL]; - DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), sm16716_pin_clk, sm16716_pin_dat); - return (sm16716_pin_clk < 99) && (sm16716_pin_dat < 99); -} - -void SM16716_Init(void) -{ - for (uint32_t t_init = 0; t_init < 50; ++t_init) { - SM16716_SendBit(0); - } -} - -#endif - - - -void LightInit(void) -{ - uint8_t max_scheme = LS_MAX -1; - - Light.device = devices_present; - Light.subtype = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); - Light.pwm_multi_channels = Settings.flag3.pwm_multi_channels; - -#if defined(USE_WS2812) && (USE_WS2812_CTYPE > NEO_3LED) - if (LT_WS2812 == light_type) { - Light.subtype++; - } -#endif - - if ((LST_SINGLE < Light.subtype) && Light.pwm_multi_channels) { - - light_controller.setPWMMultiChannel(true); - Light.device = devices_present - Light.subtype + 1; - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightInit Light.pwm_multi_channels=%d Light.subtype=%d Light.device=%d devices_present=%d", - Light.pwm_multi_channels, Light.subtype, Light.device, devices_present); -#endif - - light_controller.setSubType(Light.subtype); - light_controller.loadSettings(); - - if (LST_SINGLE == Light.subtype) { - Settings.light_color[0] = 255; - } - if (light_type < LT_PWM6) { - for (uint32_t i = 0; i < light_type; i++) { - Settings.pwm_value[i] = 0; - if (pin[GPIO_PWM1 +i] < 99) { - pinMode(pin[GPIO_PWM1 +i], OUTPUT); - } - } - if (SONOFF_LED == my_module_type) { - if (!my_module.io[4]) { - pinMode(4, OUTPUT); - digitalWrite(4, LOW); - } - if (!my_module.io[5]) { - pinMode(5, OUTPUT); - digitalWrite(5, LOW); - } - if (!my_module.io[14]) { - pinMode(14, OUTPUT); - digitalWrite(14, LOW); - } - } - if (pin[GPIO_ARIRFRCV] < 99) { - if (pin[GPIO_ARIRFSEL] < 99) { - pinMode(pin[GPIO_ARIRFSEL], OUTPUT); - digitalWrite(pin[GPIO_ARIRFSEL], 1); - } - } - } -#ifdef USE_WS2812 - else if (LT_WS2812 == light_type) { - Ws2812Init(); - max_scheme = LS_MAX + WS2812_SCHEMES; - } -#endif -#ifdef USE_SM16716 - else if (LT_SM16716 == light_type - Light.subtype) { - - for (uint32_t i = 0; i < Light.subtype; i++) { - Settings.pwm_value[i] = 0; - if (pin[GPIO_PWM1 +i] < 99) { - pinMode(pin[GPIO_PWM1 +i], OUTPUT); - } - } - - pinMode(sm16716_pin_clk, OUTPUT); - digitalWrite(sm16716_pin_clk, LOW); - - pinMode(sm16716_pin_dat, OUTPUT); - digitalWrite(sm16716_pin_dat, LOW); - - if (sm16716_pin_sel < 99) { - pinMode(sm16716_pin_sel, OUTPUT); - digitalWrite(sm16716_pin_sel, LOW); - - } else { - - SM16716_Init(); - } - } -#endif - else { - light_pdi_pin = pin[GPIO_DI]; - light_pdcki_pin = pin[GPIO_DCKI]; - - pinMode(light_pdi_pin, OUTPUT); - pinMode(light_pdcki_pin, OUTPUT); - digitalWrite(light_pdi_pin, LOW); - digitalWrite(light_pdcki_pin, LOW); - - LightMy92x1Init(); - } - - 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 = true; - Light.wakeup_active = 0; - - LightUpdateColorMapping(); -} - -void LightUpdateColorMapping(void) -{ - uint8_t param = Settings.param[P_RGB_REMAP] & 127; - if (param > 119){ param = 0; } - - uint8_t tmp[] = {0,1,2,3,4}; - Light.color_remap[0] = tmp[param / 24]; - for (uint32_t i = param / 24; i<4; ++i){ - tmp[i] = tmp[i+1]; - } - param = param % 24; - Light.color_remap[1] = tmp[(param / 6)]; - for (uint32_t i = param / 6; i<3; ++i){ - tmp[i] = tmp[i+1]; - } - param = param % 6; - Light.color_remap[2] = tmp[(param / 2)]; - for (uint32_t i = param / 2; i<2; ++i){ - tmp[i] = tmp[i+1]; - } - param = param % 2; - Light.color_remap[3] = tmp[param]; - Light.color_remap[4] = tmp[1-param]; - - - bool ct_rgb_linked = !(Settings.param[P_RGB_REMAP] & 128); - light_controller.setCTRGBLinked(ct_rgb_linked); - - Light.update = true; - -} - -void LightSetDimmer(uint8_t dimmer) { - light_controller.changeDimmer(dimmer); -} - - -uint8_t LightGetBri(uint8_t device) { - uint8_t bri = 254; - if (Light.pwm_multi_channels) { - if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { - bri = Light.current_color[device - Light.device]; - } - } else if (device == Light.device) { - bri = light_state.getBri(); - } - return bri; -} - - - -void LightSetBri(uint8_t device, uint8_t bri) { - if (Light.pwm_multi_channels) { - if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { - Light.current_color[device - Light.device] = bri; - light_controller.changeChannels(Light.current_color); - } - } else if (device == Light.device) { - light_controller.changeBri(bri); - } -} - -void LightSetColorTemp(uint16_t ct) -{ - - - - - - - if ((LST_COLDWARM != Light.subtype) && (LST_RGBWC != Light.subtype)) { - return; - } - light_controller.changeCTB(ct, light_state.getBriCT()); -} - -uint16_t LightGetColorTemp(void) -{ - - if ((LST_COLDWARM != Light.subtype) && (LST_RGBWC != Light.subtype)) { - return 0; - } - return (light_state.getColorMode() & LCM_CT) ? light_state.getCT() : 0; -} - -void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value) -{ - - - - if (Settings.flag.light_signal) { - uint16_t signal = changeUIntScale(value, lo, hi, 0, 255); - - light_controller.changeRGB(signal, 255 - signal, 0, true); - Settings.light_scheme = 0; - if (0 == light_state.getBri()) { - light_controller.changeBri(50); - } - } -} - - -char* LightGetColor(char* scolor, boolean force_hex = false) -{ - light_controller.calcLevels(); - scolor[0] = '\0'; - for (uint32_t i = 0; i < Light.subtype; i++) { - if (!force_hex && Settings.flag.decimal_text) { - snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Light.current_color[i]); - } else { - snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%02X"), scolor, Light.current_color[i]); - } - } - return scolor; -} - -void LightPowerOn(void) -{ - if (light_state.getBri() && !(Light.power)) { - ExecuteCommandPower(Light.device, POWER_ON, SRC_LIGHT); - } -} - -void LightState(uint8_t append) -{ - char scolor[LIGHT_COLOR_SIZE]; - char scommand[33]; - - if (append) { - ResponseAppend_P(PSTR(",")); - } else { - Response_P(PSTR("{")); - } - if (!Light.pwm_multi_channels) { - GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); - ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power), light_state.getDimmer()); - - if (Light.subtype > LST_SINGLE) { - ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); - uint16_t hue; - uint8_t sat, bri; - light_state.getHSB(&hue, &sat, &bri); - sat = changeUIntScale(sat, 0, 255, 0, 100); - bri = changeUIntScale(bri, 0, 255, 0, 100); - - ResponseAppend_P(PSTR(",\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), hue,sat,bri); - - ResponseAppend_P(PSTR(",\"" D_CMND_CHANNEL "\":[" )); - for (uint32_t i = 0; i < Light.subtype; i++) { - uint8_t channel_raw = Light.current_color[i]; - uint8_t channel = changeUIntScale(channel_raw,0,255,0,100); - - if ((0 == channel) && (channel_raw > 0)) { channel = 1; } - ResponseAppend_P(PSTR("%s%d" ), (i > 0 ? "," : ""), channel); - } - ResponseAppend_P(PSTR("]")); - } - if ((LST_COLDWARM == Light.subtype) || (LST_RGBWC == Light.subtype)) { - ResponseAppend_P(PSTR(",\"" D_CMND_COLORTEMPERATURE "\":%d"), light_state.getCT()); - } - - if (append) { - if (Light.subtype >= LST_RGB) { - ResponseAppend_P(PSTR(",\"" D_CMND_SCHEME "\":%d"), Settings.light_scheme); - } - if (LT_WS2812 == light_type) { - ResponseAppend_P(PSTR(",\"" D_CMND_WIDTH "\":%d"), Settings.light_width); - } - ResponseAppend_P(PSTR(",\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""), - GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction)); - } - } else { - for (uint32_t i = 0; i < Light.subtype; i++) { - GetPowerDevice(scommand, Light.device + i, sizeof(scommand), 1); - uint32_t light_power_masked = Light.power & (1 << i); - light_power_masked = light_power_masked ? 1 : 0; - ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_CHANNEL "%d\":%d,"), scommand, GetStateText(light_power_masked), Light.device + i, - changeUIntScale(Light.current_color[i], 0, 255, 0, 100)); - } - ResponseAppend_P(PSTR("\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); - } - - if (!append) { - ResponseJsonEnd(); - } -} - -void LightPreparePower(void) -{ -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", power, Light.power); -#endif - - if (Light.pwm_multi_channels) { -# 1698 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_04_light.ino" - } else { - if (light_state.getBri() && !(Light.power)) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); - } - } - else if (!light_state.getBri() && Light.power) { - ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); - } -#ifdef USE_DOMOTICZ - DomoticzUpdatePowerState(Light.device); -#endif - } - - if (Settings.flag3.hass_tele_on_power) { MqttPublishTeleState(); } - -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower End power=%d Light.power=%d", power, Light.power); -#endif - Light.power = power >> (Light.device - 1); - LightState(0); -} - -void LightFade(void) -{ - if (0 == Settings.light_fade) { - for (uint32_t 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 = (Light.strip_timer_counter % (Settings.light_speed -6)) ? 0 : 8; - } - if (shift) { - for (uint32_t 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; - } - } - } - } - } -} - -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 (uint32_t i = 0; i < LST_RGB; i++) { - float temp = (float)Light.entry_color[i] / dimmer + 0.5f; - Light.entry_color[i] = (uint8_t)temp; - } -} - -void LightCycleColor(int8_t direction) -{ - if (Light.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(void) -{ - bool update = false; - for (uint32_t i = 0; i < LST_RGB; i++) { - if (Light.new_color[i] != Light.current_color[i]) { - update = true; - } - } - if (!update) { - Light.wheel = random(255); - LightWheel(Light.wheel); - memcpy(Light.current_color, Light.entry_color, sizeof(Light.current_color)); - } - LightFade(); -} - -void LightSetPower(void) -{ - - Light.old_power = Light.power; - - uint32_t mask = 1; - if (Light.pwm_multi_channels) { - mask = (1 << Light.subtype) - 1; - } - uint32_t shift = Light.device - 1; - - - - - - Light.power = (XdrvMailbox.index & (mask << shift)) >> shift; - if (Light.wakeup_active) { - Light.wakeup_active--; - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightSetPower XdrvMailbox.index=%d Light.old_power=%d Light.power=%d mask=%d shift=%d", - XdrvMailbox.index, Light.old_power, Light.power, mask, shift); -#endif - if (Light.power != Light.old_power) { - Light.update = true; - } - LightAnimate(); -} - -void LightAnimate(void) -{ - uint8_t cur_col[LST_MAX]; - uint16_t light_still_on = 0; - - Light.strip_timer_counter++; - if (!Light.power) { - sleep = Settings.sleep; - Light.strip_timer_counter = 0; - for (uint32_t 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 (uint32_t i = 0; i < Light.subtype; i++) { - if (Light.new_color[i] > 0) { - Light.new_color[i] -= (Light.new_color[i] >> speed) +1; - } - } - } else { - for (uint32_t i = 0; i < Light.subtype; i++) { - Light.new_color[i] = 0; - } - } - } - else { -#ifdef PWM_LIGHTSCHEME0_IGNORE_SLEEP - sleep = (LS_POWER == Settings.light_scheme) ? Settings.sleep : 0; -#else - sleep = 0; -#endif - switch (Settings.light_scheme) { - case LS_POWER: - light_controller.calcLevels(); - LightFade(); - break; - case LS_WAKEUP: - if (2 == Light.wakeup_active) { - Light.wakeup_active = 1; - for (uint32_t i = 0; i < Light.subtype; i++) { - Light.new_color[i] = 0; - } - Light.wakeup_counter = 0; - Light.wakeup_dimmer = 0; - } - 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) { - light_state.setDimmer(Light.wakeup_dimmer); - light_controller.calcLevels(); - for (uint32_t i = 0; i < Light.subtype; i++) { - Light.new_color[i] = Light.current_color[i]; - } - } else { - Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"}")); - MqttPublishPrefixTopic_P(TELE, 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 (LT_WS2812 == light_type) { - Ws2812ShowScheme(Settings.light_scheme -LS_MAX); - } -#endif - } - } - - if ((Settings.light_scheme < LS_MAX) || !Light.power) { - - - if (Light.pwm_multi_channels) { - - for (uint32_t i = 0; i < LST_MAX; i++) { - if (0 == bitRead(Light.power,i)) { - Light.new_color[i] = 0; - } - } - - - - - - } - - if (memcmp(Light.last_color, Light.new_color, Light.subtype)) { - Light.update = true; - } - if (Light.update) { - uint16_t cur_col_10bits[LST_MAX]; - Light.update = false; - - - for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col[i] = Light.last_color[i] = Light.new_color[i]; - - cur_col_10bits[i] = changeUIntScale(cur_col[i], 0, 255, 0, 1023); - } - - if (PHILIPS == my_module_type) { - calcGammaXiaomiBulbs(cur_col, cur_col_10bits); - } else if (Light.pwm_multi_channels) { - calcGammaMultiChannels(cur_col, cur_col_10bits); - } else { - calcGammaBulbs(cur_col, cur_col_10bits); - - - - if ((LST_RGBW <= Light.subtype) && (0 == Settings.rgbwwTable[4]) && (0 == cur_col[3]+cur_col[4])) { - uint32_t min_rgb_10 = min3(cur_col_10bits[0], cur_col_10bits[1], cur_col_10bits[2]); - uint8_t min_rgb = min3(cur_col[0], cur_col[1], cur_col[2]); - for (uint32_t i=0; i<3; i++) { - - cur_col_10bits[i] = changeUIntScale(cur_col_10bits[i] - min_rgb_10, 0, 255, 0, Settings.rgbwwTable[i]); - cur_col[i] = changeUIntScale(cur_col[i] - min_rgb, 0, 255, 0, Settings.rgbwwTable[i]); - } - - uint32_t white_10 = changeUIntScale(min_rgb_10, 0, 255, 0, Settings.rgbwwTable[3]); - uint32_t white = changeUIntScale(min_rgb, 0, 255, 0, Settings.rgbwwTable[3]); - if (LST_RGBW == Light.subtype) { - - cur_col_10bits[3] = white_10; - cur_col[3] = white; - } else { - - uint32_t ct = light_state.getCT(); - cur_col_10bits[4] = changeUIntScale(ct, 153, 500, 0, white_10); - cur_col_10bits[3] = white_10 - cur_col_10bits[4]; - cur_col[4] = changeUIntScale(ct, 153, 500, 0, white); - cur_col[3] = white - cur_col[4]; - } - } - } - - - for (uint32_t i = 0; i < LST_MAX; i++) { -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) - - - if ((cur_col_10bits[i] > 1008) && (cur_col_10bits[i] < 1023)) { - cur_col_10bits[i] = 1008; - } -#endif - - cur_col_10bits[i] = (cur_col_10bits[i] > 0) ? changeUIntScale(cur_col_10bits[i], 1, 1023, 1, Settings.pwm_range) : 0; - } - - - uint8_t orig_col[LST_MAX]; - uint16_t orig_col_10bits[LST_MAX]; - memcpy(orig_col, cur_col, sizeof(orig_col)); - memcpy(orig_col_10bits, cur_col_10bits, sizeof(orig_col_10bits)); - for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col[i] = orig_col[Light.color_remap[i]]; - cur_col_10bits[i] = orig_col_10bits[Light.color_remap[i]]; - } - - - if (light_type < LT_PWM6) { - for (uint32_t i = 0; i < Light.subtype; i++) { - if (pin[GPIO_PWM1 +i] < 99) { - - analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col_10bits[i] : cur_col_10bits[i]); - } - } - } - - char *tmp_data = XdrvMailbox.data; - uint16_t tmp_data_len = XdrvMailbox.data_len; - - XdrvMailbox.data = (char*)cur_col; - XdrvMailbox.data_len = sizeof(cur_col); - if (XdrvCall(FUNC_SET_CHANNELS)) { - - } -#ifdef USE_WS2812 - else if (LT_WS2812 == light_type) { - Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2], cur_col[3]); - } -#endif -#ifdef USE_SM16716 - else if (LT_SM16716 == light_type - Light.subtype) { - - for (uint32_t i = 3; i < Light.subtype; i++) { - if (pin[GPIO_PWM1 +i-3] < 99) { - - analogWrite(pin[GPIO_PWM1 +i-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - cur_col_10bits[i] : cur_col_10bits[i]); - } - } - - SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); - } -#endif - else if (light_type > LT_WS2812) { - - LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); - } - XdrvMailbox.data = tmp_data; - XdrvMailbox.data_len = tmp_data_len; - } - } -} - - -void calcGammaXiaomiBulbs(uint8_t cur_col[5], uint16_t cur_col_10bits[5]) { - - uint8_t cold; - light_state.getCW(&cold, nullptr); - cur_col[1] = cold; - cur_col_10bits[1] = changeUIntScale(cur_col[1], 0, 255, 0, 1023); - - uint8_t pxBri = light_state.getBriCT(); - - if (Settings.light_correction) { - cur_col[0] = ledGamma(pxBri); - cur_col_10bits[0] = ledGamma(pxBri, 10); - } else { - cur_col[0] = pxBri; - cur_col_10bits[0] = changeUIntScale(pxBri, 0, 255, 0, 1023); - } -} - - -void calcGammaMultiChannels(uint8_t cur_col[5], uint16_t cur_col_10bits[5]) { - - if (Settings.light_correction) { - for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col_10bits[i] = ledGamma(cur_col[i], 10); - cur_col[i] = ledGamma(cur_col[i]); - } - } -} - -void calcGammaBulbs(uint8_t cur_col[5], uint16_t cur_col_10bits[5]) { - - if (Settings.light_correction) { - - if ((LST_COLDWARM == Light.subtype) || (LST_RGBWC == Light.subtype)) { - uint8_t w_idx[2] = {0, 1}; - if (LST_RGBWC == Light.subtype) { - w_idx[0] = 3; - w_idx[1] = 4; - } - uint16_t white_bri = cur_col[w_idx[0]] + cur_col[w_idx[1]]; - - if (white_bri <= 255) { - - uint16_t white_bri_10bits = ledGamma(white_bri, 10); - uint8_t white_bri_8bits = ledGamma(white_bri); - - cur_col_10bits[w_idx[0]] = changeUIntScale(cur_col[w_idx[0]], 0, white_bri, 0, white_bri_10bits); - cur_col_10bits[w_idx[1]] = changeUIntScale(cur_col[w_idx[1]], 0, white_bri, 0, white_bri_10bits); - cur_col[w_idx[0]] = changeUIntScale(cur_col[w_idx[0]], 0, white_bri, 0, white_bri_8bits); - cur_col[w_idx[1]] = changeUIntScale(cur_col[w_idx[1]], 0, white_bri, 0, white_bri_8bits); - } else { - cur_col_10bits[w_idx[0]] = ledGamma(cur_col[w_idx[0]], 10); - cur_col_10bits[w_idx[1]] = ledGamma(cur_col[w_idx[1]], 10); - cur_col[w_idx[0]] = ledGamma(cur_col[w_idx[0]]); - cur_col[w_idx[1]] = ledGamma(cur_col[w_idx[1]]); - } - } - - if (LST_RGB <= Light.subtype) { - for (uint32_t i = 0; i < 3; i++) { - cur_col_10bits[i] = ledGamma(cur_col[i], 10); - cur_col[i] = ledGamma(cur_col[i]); - } - } - - if (LST_COLDWARM != Light.subtype) { - cur_col_10bits[3] = ledGamma(cur_col[3], 10); - cur_col[3] = ledGamma(cur_col[3]); - } - } -} - - - - - -bool LightColorEntry(char *buffer, uint32_t buffer_length) -{ - char scolor[10]; - char *p; - char *str; - uint32_t entry_type = 0; - uint8_t value = Light.fixed_color_index; - - if (buffer[0] == '#') { - buffer++; - buffer_length--; - } - - if (Light.subtype >= LST_RGB) { - char option = (1 == buffer_length) ? buffer[0] : '\0'; - if (('+' == option) && (Light.fixed_color_index < MAX_FIXED_COLOR)) { - value++; - } - else if (('-' == option) && (Light.fixed_color_index > 1)) { - value--; - } else { - value = atoi(buffer); - } - } - - memset(&Light.entry_color, 0x00, sizeof(Light.entry_color)); - if (strstr(buffer, ",") != nullptr) { - int8_t i = 0; - for (str = strtok_r(buffer, ",", &p); str && i < 6; str = strtok_r(nullptr, ",", &p)) { - if (i < LST_MAX) { - Light.entry_color[i++] = atoi(str); - } - } - entry_type = 2; - } - else if (((2 * Light.subtype) == buffer_length) || (buffer_length > 3)) { - for (uint32_t i = 0; i < tmin((uint)(buffer_length / 2), sizeof(Light.entry_color)); i++) { - strlcpy(scolor, buffer + (i *2), 3); - Light.entry_color[i] = (uint8_t)strtol(scolor, &p, 16); - } - entry_type = 1; - } - else if ((Light.subtype >= LST_RGB) && (value > 0) && (value <= MAX_FIXED_COLOR)) { - Light.fixed_color_index = value; - memcpy_P(&Light.entry_color, &kFixedColor[value -1], 3); - entry_type = 1; - } - else if ((value > 199) && (value <= 199 + MAX_FIXED_COLD_WARM)) { - if (LST_RGBW == Light.subtype) { - memcpy_P(&Light.entry_color[3], &kFixedWhite[value -200], 1); - entry_type = 1; - } - else if (LST_COLDWARM == Light.subtype) { - memcpy_P(&Light.entry_color, &kFixedColdWarm[value -200], 2); - entry_type = 1; - } - else if (LST_RGBWC == Light.subtype) { - memcpy_P(&Light.entry_color[3], &kFixedColdWarm[value -200], 2); - entry_type = 1; - } - } - if (entry_type) { - Settings.flag.decimal_text = entry_type -1; - } - return (entry_type); -} - - - -void CmndSupportColor(void) -{ - bool valid_entry = false; - bool coldim = false; - - if (XdrvMailbox.data_len > 0) { - valid_entry = LightColorEntry(XdrvMailbox.data, XdrvMailbox.data_len); - if (valid_entry) { - if (XdrvMailbox.index <= 2) { - uint32_t old_bri = light_state.getBri(); - - light_controller.changeChannels(Light.entry_color); - if (2 == XdrvMailbox.index) { - - light_controller.changeBri(old_bri); - } - - Settings.light_scheme = 0; - coldim = true; - } else { - for (uint32_t i = 0; i < LST_RGB; i++) { - Settings.ws_color[XdrvMailbox.index -3][i] = Light.entry_color[i]; - } - } - } - } - char scolor[LIGHT_COLOR_SIZE]; - if (!valid_entry && (XdrvMailbox.index <= 2)) { - ResponseCmndChar(LightGetColor(scolor)); - } - if (XdrvMailbox.index >= 3) { - scolor[0] = '\0'; - for (uint32_t i = 0; i < LST_RGB; i++) { - if (Settings.flag.decimal_text) { - snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.ws_color[XdrvMailbox.index -3][i]); - } else { - snprintf_P(scolor, sizeof(scolor), PSTR("%s%02X"), scolor, Settings.ws_color[XdrvMailbox.index -3][i]); - } - } - ResponseCmndIdxChar(scolor); - } - if (coldim) { - LightPreparePower(); - } -} - -void CmndColor(void) -{ - if ((Light.subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { - CmndSupportColor(); - } -} - -void CmndWhite(void) -{ - if ((Light.subtype == LST_RGBW) && (XdrvMailbox.index == 1)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - uint32_t whiteBri = changeUIntScale(XdrvMailbox.payload,0,100,0,255); - char scolor[LIGHT_COLOR_SIZE]; - snprintf_P(scolor, sizeof(scolor), PSTR("0,0,0,%d"), whiteBri); - light_state.setBri(whiteBri); - XdrvMailbox.data = scolor; - XdrvMailbox.data_len = strlen(scolor); - } else { - XdrvMailbox.data_len = 0; - } - CmndSupportColor(); - } -} - -void CmndChannel(void) -{ - if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) { - bool coldim = false; - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Light.current_color[XdrvMailbox.index - Light.device] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); - if (Light.pwm_multi_channels) { - - - - } else { - - if ((XdrvMailbox.index <= 3) && (light_controller.isCTRGBLinked())) { - Light.current_color[3] = Light.current_color[4] = 0; - } - } - light_controller.changeChannels(Light.current_color); - coldim = true; - } - ResponseCmndIdxNumber(Light.current_color[XdrvMailbox.index -1] * 100 / 255); - if (coldim) { - LightPreparePower(); - } - } -} - -void CmndHsbColor(void) -{ - if (Light.subtype >= LST_RGB) { - bool validHSB = (XdrvMailbox.data_len > 0); - if (validHSB) { - uint16_t HSB[3]; - if (strstr(XdrvMailbox.data, ",") != nullptr) { - for (uint32_t i = 0; i < 3; i++) { - char *substr; - - if (0 == i) { - substr = strtok(XdrvMailbox.data, ","); - } else { - substr = strtok(nullptr, ","); - } - if (substr != nullptr) { - HSB[i] = atoi(substr); - if (0 < i) { - HSB[i] = changeUIntScale(HSB[i], 0, 100, 0, 255); - } - } else { - validHSB = false; - } - } - } else { - uint16_t c_hue; - uint8_t c_sat; - light_state.getHSB(&c_hue, &c_sat, nullptr); - HSB[0] = c_hue; - HSB[1] = c_sat; - HSB[2] = light_state.getBri(); - - if (1 == XdrvMailbox.index) { - HSB[0] = XdrvMailbox.payload; - } else if ((XdrvMailbox.index > 1) && (XdrvMailbox.index < 4)) { - HSB[XdrvMailbox.index-1] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); - } else { - validHSB = false; - } - } - if (validHSB) { - light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); - LightPreparePower(); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR)); - } - } else { - LightState(0); - } - } -} - -#ifdef USE_WS2812 -void CmndLed(void) -{ - if ((LT_WS2812 == light_type) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= Settings.light_pixels)) { - if (XdrvMailbox.data_len > 0) { - char *p; - uint16_t idx = XdrvMailbox.index; - Ws2812ForceSuspend(); - for (char *color = strtok_r(XdrvMailbox.data, " ", &p); color; color = strtok_r(nullptr, " ", &p)) { - if (LightColorEntry(color, strlen(color))) { - Ws2812SetColor(idx, Light.entry_color[0], Light.entry_color[1], Light.entry_color[2], Light.entry_color[3]); - idx++; - if (idx > Settings.light_pixels) { break; } - } else { - break; - } - } - - Ws2812ForceUpdate(); - } - char scolor[LIGHT_COLOR_SIZE]; - ResponseCmndIdxChar(Ws2812GetColor(XdrvMailbox.index, scolor)); - } -} - -void CmndPixels(void) -{ - if (LT_WS2812 == light_type) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) { - Settings.light_pixels = XdrvMailbox.payload; - Settings.light_rotation = 0; - Ws2812Clear(); - Light.update = true; - } - ResponseCmndNumber(Settings.light_pixels); - } -} - -void CmndRotation(void) -{ - if (LT_WS2812 == light_type) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings.light_pixels)) { - Settings.light_rotation = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.light_rotation); - } -} - -void CmndWidth(void) -{ - if ((LT_WS2812 == light_type) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { - if (1 == XdrvMailbox.index) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 4)) { - Settings.light_width = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.light_width); - } else { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32)) { - Settings.ws_width[XdrvMailbox.index -2] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.ws_width[XdrvMailbox.index -2]); - } - } -} -#endif - -void CmndScheme(void) -{ - if (Light.subtype >= LST_RGB) { - uint32_t max_scheme = (LT_WS2812 == light_type) ? LS_MAX + WS2812_SCHEMES : LS_MAX -1; - if (1 == XdrvMailbox.data_len) { - if (('+' == XdrvMailbox.data[0]) && (Settings.light_scheme < max_scheme)) { - XdrvMailbox.payload = Settings.light_scheme + ((0 == Settings.light_scheme) ? 2 : 1); - } - else if (('-' == XdrvMailbox.data[0]) && (Settings.light_scheme > 0)) { - XdrvMailbox.payload = Settings.light_scheme - ((2 == Settings.light_scheme) ? 2 : 1); - } - } - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= max_scheme)) { - Settings.light_scheme = XdrvMailbox.payload; - if (LS_WAKEUP == Settings.light_scheme) { - Light.wakeup_active = 3; - } - LightPowerOn(); - Light.strip_timer_counter = 0; - - if (Settings.flag3.hass_tele_on_power) { MqttPublishTeleState(); } - } - ResponseCmndNumber(Settings.light_scheme); - } -} - -void CmndWakeup(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Settings.light_dimmer = XdrvMailbox.payload; - } - Light.wakeup_active = 3; - Settings.light_scheme = LS_WAKEUP; - LightPowerOn(); - ResponseCmndChar(D_JSON_STARTED); -} - -void CmndColorTemperature(void) -{ - if ((LST_COLDWARM == Light.subtype) || (LST_RGBWC == Light.subtype)) { - uint32_t ct = light_state.getCT(); - if (1 == XdrvMailbox.data_len) { - if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (ct > (500-34)) ? 500 : ct + 34; - } - else if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (ct < (153+34)) ? 153 : ct - 34; - } - } - if ((XdrvMailbox.payload >= 153) && (XdrvMailbox.payload <= 500)) { - light_controller.changeCTB(XdrvMailbox.payload, light_state.getBri()); - LightPreparePower(); - } else { - ResponseCmndNumber(ct); - } - } -} - -void CmndDimmer(void) -{ - uint32_t dimmer = light_state.getDimmer(); - if (1 == XdrvMailbox.data_len) { - if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (dimmer > 89) ? 100 : dimmer + 10; - } - else if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (dimmer < 11) ? 1 : dimmer - 10; - } - } - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - light_controller.changeDimmer(XdrvMailbox.payload); - Light.update = true; - LightPreparePower(); - } else { - ResponseCmndNumber(Settings.light_dimmer); - } -} - -void CmndLedTable(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - switch (XdrvMailbox.payload) { - case 0: - case 1: - Settings.light_correction = XdrvMailbox.payload; - break; - case 2: - Settings.light_correction ^= 1; - break; - } - Light.update = true; - } - ResponseCmndStateText(Settings.light_correction); -} - -void CmndRgbwwTable(void) -{ - if ((XdrvMailbox.data_len > 0)) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - for (uint32_t i = 0; i < LST_RGBWC; i++) { - char *substr; - - if (0 == i) { - substr = strtok(XdrvMailbox.data, ","); - } else { - substr = strtok(nullptr, ","); - } - if (substr != nullptr) { - Settings.rgbwwTable[i] = atoi(substr); - } - } - } - Light.update = true; - } - char scolor[LIGHT_COLOR_SIZE]; - scolor[0] = '\0'; - for (uint32_t i = 0; i < LST_RGBWC; i++) { - snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); - } - ResponseCmndIdxChar(scolor); -} - -void CmndFade(void) -{ - switch (XdrvMailbox.payload) { - case 0: - case 1: - Settings.light_fade = XdrvMailbox.payload; - break; - case 2: - Settings.light_fade ^= 1; - break; - } - ResponseCmndStateText(Settings.light_fade); -} - -void CmndSpeed(void) -{ - if (1 == XdrvMailbox.data_len) { - if (('+' == XdrvMailbox.data[0]) && (Settings.light_speed > 1)) { - XdrvMailbox.payload = Settings.light_speed -1; - } - else if (('-' == XdrvMailbox.data[0]) && (Settings.light_speed < STATES)) { - XdrvMailbox.payload = Settings.light_speed +1; - } - } - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= STATES)) { - Settings.light_speed = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.light_speed); -} - -void CmndWakeupDuration(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3001)) { - Settings.light_wakeup = XdrvMailbox.payload; - Light.wakeup_active = 0; - } - ResponseCmndNumber(Settings.light_wakeup); -} - -void CmndUndocA(void) -{ - char scolor[LIGHT_COLOR_SIZE]; - LightGetColor(scolor, true); - scolor[6] = '\0'; - Response_P(PSTR("%s,%d,%d,%d,%d,%d"), scolor, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width); - MqttPublishPrefixTopic_P(STAT, XdrvMailbox.topic); - mqtt_data[0] = '\0'; -} - - - - - -bool Xdrv04(uint8_t function) -{ - bool result = false; - - if (light_type) { - switch (function) { - case FUNC_PRE_INIT: - LightInit(); - break; - case FUNC_EVERY_50_MSECOND: - LightAnimate(); -#ifdef USE_ARILUX_RF - if (pin[GPIO_ARIRFRCV] < 99) { AriluxRfHandler(); } -#endif - break; -#ifdef USE_ARILUX_RF - case FUNC_EVERY_SECOND: - if (10 == uptime) { AriluxRfInit(); } - break; -#endif - case FUNC_SET_POWER: - LightSetPower(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kLightCommands, LightCommand); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_05_irremote.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_05_irremote.ino" -#if defined(USE_IR_REMOTE) && !defined(USE_IR_REMOTE_FULL) - - - - -#define XDRV_05 5 - -#include - -enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC }; - -const char kIrRemoteCommands[] PROGMEM = "|" -#ifdef USE_IR_HVAC - D_CMND_IRHVAC "|" -#endif - D_CMND_IRSEND ; - -void (* const IrRemoteCommand[])(void) PROGMEM = { -#ifdef USE_IR_HVAC - &CmndIrHvac, -#endif - &CmndIrSend }; - - -static const uint8_t MAX_STANDARD_IR = SHARP; -enum IrVendors { IR_BASE = MAX_STANDARD_IR, -#ifdef USE_IR_SEND_PIONEER - IR_PIONEER, -#endif -}; -const char kIrRemoteProtocols[] PROGMEM = - "UNKNOWN|RC5|RC6|NEC|SONY|PANASONIC|JVC|SAMSUNG|WHYNTER|AIWA_RC_T501|LG|SANYO|MITSUBISHI|DISH|SHARP" - -#ifdef USE_IR_SEND_PIONEER - "|PIONEER" -#endif - ; - - - - - -#include - -IRsend *irsend = nullptr; -bool irsend_active = false; - -void IrSendInit(void) -{ - irsend = new IRsend(pin[GPIO_IRSEND]); - irsend->begin(); -} - -#ifdef USE_IR_RECEIVE - - - - -const bool IR_RCV_SAVE_BUFFER = false; -const uint32_t IR_TIME_AVOID_DUPLICATE = 500; - -#include - -IRrecv *irrecv = nullptr; - -unsigned long ir_lasttime = 0; - -void IrReceiveUpdateThreshold() -{ - if (irrecv != nullptr) { - if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } - irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); - } -} - -void IrReceiveInit(void) -{ - - irrecv = new IRrecv(pin[GPIO_IRRECV], IR_RCV_BUFFER_SIZE, IR_RCV_TIMEOUT, IR_RCV_SAVE_BUFFER); - irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); - irrecv->enableIRIn(); - - -} - -void IrReceiveCheck(void) -{ - char sirtype[14]; - int8_t iridx = 0; - - decode_results results; - - if (irrecv->decode(&results)) { - char hvalue[65]; - - iridx = results.decode_type; - if ((iridx < 0) || (iridx > 14)) { iridx = 0; } - - if (iridx) { - if (results.bits > 64) { - - uint32_t digits2 = results.bits / 8; - if (results.bits % 8) { digits2++; } - ToHex_P((unsigned char*)results.state, digits2, hvalue, sizeof(hvalue)); - } else { - Uint64toHex(results.value, hvalue, results.bits); - } - } else { - Uint64toHex(results.value, hvalue, 32); - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value 0x%s, Decode %d"), - irsend_active, results.rawlen, results.overflow, results.bits, hvalue, results.decode_type); - - unsigned long now = millis(); - - if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { - ir_lasttime = now; - - char svalue[64]; - if (Settings.flag.ir_receive_decimal) { - ulltoa(results.value, svalue, 10); - } else { - snprintf_P(svalue, sizeof(svalue), PSTR("\"0x%s\""), hvalue); - } - ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d"), - GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits); - if (iridx) { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_DATA "\":%s"), svalue); - } else { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_HASH "\":%s"), svalue); - } - - if (Settings.flag3.receive_raw) { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); - uint16_t i; - for (i = 1; i < results.rawlen; i++) { - if (i > 1) { ResponseAppend_P(PSTR(",")); } - uint32_t usecs; - for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { - ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); - } - ResponseAppend_P(PSTR("%d"), usecs); - if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } - } - uint16_t extended_length = results.rawlen - 1; - for (uint32_t j = 0; j < results.rawlen - 1; j++) { - uint32_t usecs = results.rawbuf[j] * kRawTick; - - extended_length += (usecs / (UINT16_MAX + 1)) * 2; - } - ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); - } - - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); - - if (iridx) { - XdrvRulesProcess(); -#ifdef USE_DOMOTICZ - unsigned long value = results.value | (iridx << 28); - DomoticzSensor(DZ_COUNT, value); -#endif - } - } - - irrecv->resume(); - } -} -#endif - - -#ifdef USE_IR_HVAC - - - - -enum IrHvacVendors { VNDR_TOSHIBA, VNDR_MITSUBISHI, VNDR_LG, VNDR_FUJITSU, VNDR_MIDEA }; -const char kIrHvacVendors[] PROGMEM = "Toshiba|Mitsubishi|LG|Fujitsu|Midea" ; - -const char kFanSpeedOptions[] = "A12345S"; -const char kHvacModeOptions[] = "HDCA"; - -#ifdef USE_IR_HVAC_TOSHIBA - - - - -const uint16_t HVAC_TOSHIBA_HDR_MARK = 4400; -const uint16_t HVAC_TOSHIBA_HDR_SPACE = 4300; -const uint16_t HVAC_TOSHIBA_BIT_MARK = 543; -const uint16_t HVAC_TOSHIBA_ONE_SPACE = 1623; -const uint16_t HVAC_MISTUBISHI_ZERO_SPACE = 472; -const uint16_t HVAC_TOSHIBA_RPT_MARK = 440; -const uint16_t HVAC_TOSHIBA_RPT_SPACE = 7048; -const uint8_t HVAC_TOSHIBA_DATALEN = 9; - -uint8_t IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) -{ - uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; - uint8_t data[HVAC_TOSHIBA_DATALEN] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}; - - char *p; - uint8_t mode; - - if (HVAC_Mode == nullptr) { - p = (char *)kHvacModeOptions; - } - else { - p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - data[6] = (p - kHvacModeOptions) ^ 0x03; - - if (!HVAC_Power) { - data[6] = (uint8_t)0x07; - } - - if (HVAC_FanMode == nullptr) { - p = (char *)kFanSpeedOptions; - } - else { - p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - mode = p - kFanSpeedOptions + 1; - if ((1 == mode) || (7 == mode)) { - mode = 0; - } - mode = mode << 5; - data[6] = data[6] | mode; - - uint8_t Temp; - if (HVAC_Temp > 30) { - Temp = 30; - } - else if (HVAC_Temp < 17) { - Temp = 17; - } - else { - Temp = HVAC_Temp; - } - data[5] = (uint8_t)(Temp - 17) << 4; - - data[HVAC_TOSHIBA_DATALEN - 1] = 0; - for (uint32_t x = 0; x < HVAC_TOSHIBA_DATALEN - 1; x++) { - data[HVAC_TOSHIBA_DATALEN - 1] = (uint8_t)data[x] ^ data[HVAC_TOSHIBA_DATALEN - 1]; - } - - int i = 0; - uint8_t mask = 1; - - - rawdata[i++] = HVAC_TOSHIBA_HDR_MARK; - rawdata[i++] = HVAC_TOSHIBA_HDR_SPACE; - - - for (uint32_t b = 0; b < HVAC_TOSHIBA_DATALEN; b++) { - for (mask = B10000000; mask > 0; mask >>= 1) { - if (data[b] & mask) { - rawdata[i++] = HVAC_TOSHIBA_BIT_MARK; - rawdata[i++] = HVAC_TOSHIBA_ONE_SPACE; - } - else { - rawdata[i++] = HVAC_TOSHIBA_BIT_MARK; - rawdata[i++] = HVAC_MISTUBISHI_ZERO_SPACE; - } - } - } - - - rawdata[i++] = HVAC_TOSHIBA_RPT_MARK; - rawdata[i++] = HVAC_TOSHIBA_RPT_SPACE; - - - irsend->sendRaw(rawdata, i, 38); - irsend->sendRaw(rawdata, i, 38); - - - return IE_NO_ERROR; -} -#endif - -#ifdef USE_IR_HVAC_MIDEA - - - - - - - -const uint16_t HVAC_MIDEA_HDR_MARK = 4420; -const uint16_t HVAC_MIDEA_HDR_SPACE = 4420; -const uint16_t HVAC_MIDEA_BIT_MARK = 553; -const uint16_t HVAC_MIDEA_ONE_SPACE = 1660; -const uint16_t HVAC_MIDEA_ZERO_SPACE = 553; -const uint16_t HVAC_MIDEA_RPT_MARK = 553; -const uint16_t HVAC_MIDEA_RPT_SPACE = 5530; -const uint8_t HVAC_MIDEA_DATALEN = 3; - -uint8_t IrHvacMidea(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) -{ - uint16_t rawdata[2 + 2 * 2 * 8 * HVAC_MIDEA_DATALEN + 2]; - uint8_t data[HVAC_MIDEA_DATALEN] = {0xB2, 0x00, 0x00}; - - char *p; - uint8_t mode; - - if (!HVAC_Power) { - data[1] = 0x7B; - data[2] = 0xE0; - } else { - - if (HVAC_FanMode == nullptr) { - p = (char*)kFanSpeedOptions; - } - else { - p = (char*)HVAC_FanMode; - } - - switch(p[0]) { - case '1': data[1] = 0xBF; break; - case '2': data[1] = 0x9F; break; - case '3': data[1] = 0x5F; break; - case '4': data[1] = 0x3F; break; - case '5': data[1] = 0x1F; break; - case 'A': data[1] = 0x1F; break; - default: return IE_SYNTAX_IRHVAC; - } - - - uint8_t Temp; - if (HVAC_Temp > 30) { - Temp = 30; - } - else if (HVAC_Temp < 17) { - Temp = 17; - } - else { - Temp = HVAC_Temp-17; - } - if (10 == Temp) { - data[2] = 0x90; - } else if (11 == Temp) { - data[2] = 0x80; - } else { - Temp = (Temp >> 1) ^Temp; - data[2] = (Temp << 4); - } - - - if (HVAC_Mode == nullptr) { - p = (char*)kHvacModeOptions + 3; - } - else { - p = (char*)HVAC_Mode; - } - switch(toupper(p[0])) { - case 'D': data[2] = 0xE4; break; - case 'C': data[2] = 0x0 | data[2]; break; - case 'A': data[2] = 0x8 | data[2]; data[1] = 0x1F; break; - case 'H': data[2] = 0xC | data[2]; break; - default: return IE_SYNTAX_IRHVAC; - } - } - - int i = 0; - uint8_t mask = 1; - - - rawdata[i++] = HVAC_MIDEA_HDR_MARK; - rawdata[i++] = HVAC_MIDEA_HDR_SPACE; - - - for (int b = 0; b < HVAC_MIDEA_DATALEN; b++) { - for (mask = B10000000; mask > 0; mask >>= 1) { - if (data[b] & mask) { - rawdata[i++] = HVAC_MIDEA_BIT_MARK; - rawdata[i++] = HVAC_MIDEA_ONE_SPACE; - } - else { - rawdata[i++] = HVAC_MIDEA_BIT_MARK; - rawdata[i++] = HVAC_MIDEA_ZERO_SPACE; - } - } - for (mask = B10000000; mask > 0; mask >>= 1) { - if (data[b] & mask) { - rawdata[i++] = HVAC_MIDEA_BIT_MARK; - rawdata[i++] = HVAC_MIDEA_ZERO_SPACE; - } - else { - rawdata[i++] = HVAC_MIDEA_BIT_MARK; - rawdata[i++] = HVAC_MIDEA_ONE_SPACE; - } - } - - } - - - rawdata[i++] = HVAC_MIDEA_RPT_MARK; - rawdata[i++] = HVAC_MIDEA_RPT_SPACE; - - - irsend->sendRaw(rawdata, i, 38); - irsend->sendRaw(rawdata, i, 38); - - return IE_NO_ERROR; -} -#endif - -#ifdef USE_IR_HVAC_MITSUBISHI - - - - -#include - -uint8_t IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) -{ - char *p; - uint8_t mode; - - IRMitsubishiAC mitsubir(pin[GPIO_IRSEND]); - - mitsubir.stateReset(); - - if (HVAC_Mode == nullptr) { - p = (char *)kHvacModeOptions; - } - else { - p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - mode = (p - kHvacModeOptions + 1) << 3; - mitsubir.setMode(mode); - - mitsubir.setPower(HVAC_Power); - - if (HVAC_FanMode == nullptr) { - p = (char *)kFanSpeedOptions; - } - else { - p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - mode = p - kFanSpeedOptions; - mitsubir.setFan(mode); - - mitsubir.setTemp(HVAC_Temp); - mitsubir.setVane(MITSUBISHI_AC_VANE_AUTO); - mitsubir.send(); - - - - - return IE_NO_ERROR; -} -#endif - -#ifdef USE_IR_HVAC_LG - - - - -const uint8_t HVAC_LG_DATALEN = 7; - -uint8_t IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) -{ - uint32_t LG_Code; - uint8_t data[HVAC_LG_DATALEN]; - static bool hvacOn = false; - char *p; - uint8_t mode; - uint8_t Temp; - - - data[0] = 0x08; - data[1] = 0x08; - data[2] = 0x00; - - if (!HVAC_Power) { - data[2] = (uint8_t)0x0C; - data[3] = (uint8_t)0x00; - data[4] = (uint8_t)0x00; - data[5] = (uint8_t)0x05; - data[6] = (uint8_t)0x01; - hvacOn = false; - } - - else { - - - if (HVAC_Mode == nullptr) { - p = (char *)kHvacModeOptions; - } - else { - p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - mode = (p - kHvacModeOptions) ^ 0x03; - switch (mode) { - case 0: - data[3] = 11; - break; - case 1: - data[3] = 8; - break; - case 2: - data[3] = 9; - break; - case 3: - data[3] = 12; - break; - } - if (!hvacOn) { - data[3] = data[3] & 7; - hvacOn = true; - } - - - - - if (HVAC_Temp > 30) { - Temp = 30; - } - else if (HVAC_Temp < 18) { - Temp = 18; - } - else { - Temp = HVAC_Temp; - } - data[4] = (uint8_t)(Temp - 15); - - - if (HVAC_FanMode == nullptr) { - p = (char *)kFanSpeedOptions; - } - else { - p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - mode = p - kFanSpeedOptions; - if ((mode == 0) || (mode > 3)) { - data[5] = 5; - } - else { - data[5] = (mode * 2) - 2; - } - - - - - data[6] = (data[3] + data[4] + data[5]) & 0x0f; - - } - - LG_Code = data[0] << 4; - for (uint32_t i = 1; i < 6; i++) { - LG_Code = (LG_Code + data[i]) << 4; - } - LG_Code = LG_Code + data[6]; - - - - - irsend->sendLG(LG_Code, 28); - - return IE_NO_ERROR; -} -#endif - -#ifdef USE_IR_HVAC_FUJITSU - - - - -#include - -uint8_t IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) -{ - const char kFujitsuHvacModeOptions[] = "HDCAF"; - - - - IRFujitsuAC ac(pin[GPIO_IRSEND]); - - if (0 == HVAC_Power) { - ac.off(); - ac.send(); - return IE_NO_ERROR; - } - - uint8_t modes[5] = {FUJITSU_AC_MODE_HEAT, FUJITSU_AC_MODE_DRY, FUJITSU_AC_MODE_COOL, FUJITSU_AC_MODE_AUTO, FUJITSU_AC_MODE_FAN}; - uint8_t fanModes[7] = {FUJITSU_AC_FAN_AUTO, FUJITSU_AC_FAN_LOW, FUJITSU_AC_FAN_MED, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_HIGH, FUJITSU_AC_FAN_QUIET}; - ac.setCmd(FUJITSU_AC_CMD_TURN_ON); - ac.setSwing(FUJITSU_AC_SWING_VERT); - - char *p; - if (nullptr == HVAC_Mode) { - p = (char *)kFujitsuHvacModeOptions; - } - else { - p = strchr(kFujitsuHvacModeOptions, toupper(HVAC_Mode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - ac.setMode(modes[p - kFujitsuHvacModeOptions]); - - if (HVAC_FanMode == nullptr) { - p = (char *)kFanSpeedOptions; - } - else { - p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); - } - if (!p) { - return IE_SYNTAX_IRHVAC; - } - ac.setFanSpeed(fanModes[p - kFanSpeedOptions]); - - ac.setTemp(HVAC_Temp); - ac.send(); - - return IE_NO_ERROR; -} -#endif - - - -uint32_t IrRemoteCmndIrHvacJson(void) -{ - - const char *HVAC_Mode; - const char *HVAC_FanMode; - const char *HVAC_Vendor; - char parm_uc[12]; - int HVAC_Temp = 21; - bool HVAC_Power = true; - - char dataBufUc[XdrvMailbox.data_len]; - UpperCase(dataBufUc, XdrvMailbox.data); - RemoveSpace(dataBufUc); - if (strlen(dataBufUc) < 8) { - return IE_INVALID_JSON; - } - - StaticJsonBuffer<164> jsonBufer; - JsonObject &root = jsonBufer.parseObject(dataBufUc); - if (!root.success()) { - return IE_INVALID_JSON; - } - - HVAC_Vendor = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR))]; - HVAC_Power = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_POWER))]; - HVAC_Mode = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODE))]; - HVAC_FanMode = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FANSPEED))]; - HVAC_Temp = root[UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TEMP))]; - - - - char vendor[20]; - int vendor_code = GetCommandCode(vendor, sizeof(vendor), HVAC_Vendor, kIrHvacVendors); - irsend_active = true; - switch (vendor_code) { -#ifdef USE_IR_HVAC_TOSHIBA - case VNDR_TOSHIBA: - return IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); -#endif -#ifdef USE_IR_HVAC_MITSUBISHI - case VNDR_MITSUBISHI: - return IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); -#endif -#ifdef USE_IR_HVAC_LG - case VNDR_LG: - return IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); -#endif -#ifdef USE_IR_HVAC_FUJITSU - case VNDR_FUJITSU: - return IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); -#endif -#ifdef USE_IR_HVAC_MIDEA - case VNDR_MIDEA: - return IrHvacMidea(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); -#endif - default: - irsend_active = false; - } - - return IE_SYNTAX_IRHVAC; -} - -void CmndIrHvac(void) -{ - uint8_t error = IE_SYNTAX_IRHVAC; - - if (XdrvMailbox.data_len) { - error = IrRemoteCmndIrHvacJson(); - } - IrRemoteCmndResponse(error); -} - -#endif - - - - - -uint32_t IrRemoteCmndIrSendRaw(void) -{ - - - - - - - - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - if (p == nullptr) { - return IE_INVALID_RAWDATA; - } - - - uint16_t repeat = XdrvMailbox.index > 0 ? XdrvMailbox.index - 1 : 0; - - uint16_t freq = atoi(str); - if (!freq && (*str != '0')) { - uint16_t count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - if (count < 2) { - return IE_INVALID_RAWDATA; - } - - uint16_t parm[count]; - for (uint32_t i = 0; i < count; i++) { - parm[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - if (!parm[i]) { - if (!i) { - parm[0] = 38000; - } else { - return IE_INVALID_RAWDATA; - } - } - } - - uint16_t i = 0; - if (count < 4) { - - uint16_t mark = parm[1] *2; - if (3 == count) { - if (parm[2] < parm[1]) { - - mark = parm[1] * parm[2]; - } else { - - mark = parm[2]; - } - } - uint16_t raw_array[strlen(p)]; - for (; *p; *p++) { - if (*p == '0') { - raw_array[i++] = parm[1]; - } - else if (*p == '1') { - raw_array[i++] = mark; - } - } - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, i, parm[0]); - if (r < repeat) { - irsend->space(40000); - } - } - } - else if (6 == count) { - - uint16_t raw_array[strlen(p)*2+3]; - raw_array[i++] = parm[1]; - raw_array[i++] = parm[2]; - uint32_t inter_message_32 = (parm[1] + parm[2]) * 3; - uint16_t inter_message = (inter_message_32 > 65000) ? 65000 : inter_message_32; - for (; *p; *p++) { - if (*p == '0') { - raw_array[i++] = parm[3]; - raw_array[i++] = parm[4]; - } - else if (*p == '1') { - raw_array[i++] = parm[3]; - raw_array[i++] = parm[5]; - } - } - raw_array[i++] = parm[3]; - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, i, parm[0]); - if (r < repeat) { - irsend->space(inter_message); - } - } - } - else { - return IE_INVALID_RAWDATA; - } - } else { - if (!freq) { freq = 38000; } - uint16_t count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - if (0 == count) { - return IE_INVALID_RAWDATA; - } - - - count++; - if (count < 200) { - uint16_t raw_array[count]; - for (uint32_t i = 0; i < count; i++) { - raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - } - - - - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, count, freq); - } - } else { - uint16_t *raw_array = reinterpret_cast(malloc(count * sizeof(uint16_t))); - if (raw_array == nullptr) { - return IE_INVALID_RAWDATA; - } - - for (uint32_t i = 0; i < count; i++) { - raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - } - - - - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, count, freq); - } - free(raw_array); - } - } - - return IE_NO_ERROR; -} - -uint32_t IrRemoteCmndIrSendJson(void) -{ - - - - - char dataBufUc[XdrvMailbox.data_len]; - UpperCase(dataBufUc, XdrvMailbox.data); - RemoveSpace(dataBufUc); - if (strlen(dataBufUc) < 8) { - return IE_INVALID_JSON; - } - - StaticJsonBuffer<140> jsonBuf; - JsonObject &root = jsonBuf.parseObject(dataBufUc); - if (!root.success()) { - return IE_INVALID_JSON; - } - - - - char parm_uc[10]; - const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; - uint16_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; - uint64_t data = strtoull(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); - uint16_t repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT))]; - - if (XdrvMailbox.index > repeat + 1) { - repeat = XdrvMailbox.index - 1; - } - if (!(protocol && bits)) { - return IE_SYNTAX_IRSEND; - } - - char protocol_text[20]; - int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); - - char dvalue[64]; - char hvalue[20]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %s (0x%s), repeat %d, protocol_code %d"), - protocol_text, protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat, protocol_code); - - irsend_active = true; - switch (protocol_code) { -#ifdef USE_IR_SEND_RC5 - case RC5: - irsend->sendRC5(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_RC6 - case RC6: - irsend->sendRC6(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_NEC - case NEC: - irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits, repeat); break; -#endif -#ifdef USE_IR_SEND_SONY - case SONY: - irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, repeat > kSonyMinRepeat ? repeat : kSonyMinRepeat); break; -#endif -#ifdef USE_IR_SEND_PANASONIC - case PANASONIC: - irsend->sendPanasonic64(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_JVC - case JVC: - irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, repeat > 1 ? repeat : 1); break; -#endif -#ifdef USE_IR_SEND_SAMSUNG - case SAMSUNG: - irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits, repeat); break; -#endif -#ifdef USE_IR_SEND_WHYNTER - case WHYNTER: - irsend->sendWhynter(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_AIWA - case AIWA_RC_T501: - irsend->sendAiwaRCT501(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_LG - case LG: - irsend->sendLG(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_SANYO - case SANYO: - irsend->sendSanyoLC7461(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_MITSUBISHI - case MITSUBISHI: - irsend->sendMitsubishi(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_DISH - case DISH: - irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits, repeat > kDishMinRepeat ? repeat : kDishMinRepeat); break; -#endif -#ifdef USE_IR_SEND_SHARP - case SHARP: - irsend->sendSharpRaw(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_PIONEER - case IR_PIONEER: - irsend->sendPioneer(data, bits, repeat); break; -#endif - default: - irsend_active = false; - ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); - } - - return IE_NO_ERROR; -} - -void CmndIrSend(void) -{ - uint8_t error = IE_SYNTAX_IRSEND; - - if (XdrvMailbox.data_len) { - - if (strstr(XdrvMailbox.data, "{") == nullptr) { - error = IrRemoteCmndIrSendRaw(); - } else { - error = IrRemoteCmndIrSendJson(); - } - } - IrRemoteCmndResponse(error); -} - -void IrRemoteCmndResponse(uint32_t error) -{ - switch (error) { - case IE_INVALID_RAWDATA: - ResponseCmndChar(D_JSON_INVALID_RAWDATA); - break; - case IE_INVALID_JSON: - ResponseCmndChar(D_JSON_INVALID_JSON); - break; - case IE_SYNTAX_IRSEND: - Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); - break; -#ifdef USE_IR_HVAC - case IE_SYNTAX_IRHVAC: - Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); - break; -#endif - default: - ResponseCmndDone(); - } -} - - - - - -bool Xdrv05(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { - switch (function) { - case FUNC_PRE_INIT: - if (pin[GPIO_IRSEND] < 99) { - IrSendInit(); - } -#ifdef USE_IR_RECEIVE - if (pin[GPIO_IRRECV] < 99) { - IrReceiveInit(); - } -#endif - break; - case FUNC_EVERY_50_MSECOND: -#ifdef USE_IR_RECEIVE - if (pin[GPIO_IRRECV] < 99) { - IrReceiveCheck(); - } -#endif - irsend_active = false; - break; - case FUNC_COMMAND: - if (pin[GPIO_IRSEND] < 99) { - result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); - } - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_05_irremote_full.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_05_irremote_full.ino" -#ifdef USE_IR_REMOTE_FULL - - - - -#define XDRV_05 5 - -#include -#include -#include -#include -#include - -enum IrErrors { IE_RESPONSE_PROVIDED, IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC, - IE_UNSUPPORTED_HVAC, IE_UNSUPPORTED_PROTOCOL }; - -const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRHVAC "|" D_CMND_IRSEND ; - -void (* const IrRemoteCommand[])(void) PROGMEM = { &CmndIrHvac, &CmndIrSend }; - - - - - -IRsend *irsend = nullptr; -bool irsend_active = false; - -void IrSendInit(void) -{ - irsend = new IRsend(pin[GPIO_IRSEND]); - irsend->begin(); -} - - - -uint8_t reverseBitsInByte(uint8_t b) { - b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; - b = (b & 0xCC) >> 2 | (b & 0x33) << 2; - b = (b & 0xAA) >> 1 | (b & 0x55) << 1; - return b; -} - - -uint64_t reverseBitsInBytes64(uint64_t b) { - union { - uint8_t b[8]; - uint64_t i; - } a; - a.i = b; - for (uint32_t i=0; i<8; i++) { - a.b[i] = reverseBitsInByte(a.b[i]); - } - return a.i; -} - - - - - -const bool IR_FULL_RCV_SAVE_BUFFER = false; -const uint32_t IR_TIME_AVOID_DUPLICATE = 500; - - - - -const uint16_t IR_FULL_BUFFER_SIZE = 1024; - - - -const uint8_t IR__FULL_RCV_TIMEOUT = 50; - -IRrecv *irrecv = nullptr; - -unsigned long ir_lasttime = 0; - -void IrReceiveUpdateThreshold() -{ - if (irrecv != nullptr) { - if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } - irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); - } -} - -void IrReceiveInit(void) -{ - - irrecv = new IRrecv(pin[GPIO_IRRECV], IR_FULL_BUFFER_SIZE, IR__FULL_RCV_TIMEOUT, IR_FULL_RCV_SAVE_BUFFER); - irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); - irrecv->enableIRIn(); -} - -String sendACJsonState(const stdAc::state_t &state) { - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.createObject(); - json[D_JSON_IRHVAC_VENDOR] = typeToString(state.protocol); - json[D_JSON_IRHVAC_MODEL] = state.model; - json[D_JSON_IRHVAC_POWER] = IRac::boolToString(state.power); - json[D_JSON_IRHVAC_MODE] = IRac::opmodeToString(state.mode); - - if (state.mode == stdAc::opmode_t::kOff || !state.power) { - json[D_JSON_IRHVAC_MODE] = IRac::opmodeToString(stdAc::opmode_t::kOff); - json[D_JSON_IRHVAC_POWER] = IRac::boolToString(false); - } - json[D_JSON_IRHVAC_CELSIUS] = IRac::boolToString(state.celsius); - if (floorf(state.degrees) == state.degrees) { - json[D_JSON_IRHVAC_TEMP] = floorf(state.degrees); - } else { - json[D_JSON_IRHVAC_TEMP] = RawJson(String(state.degrees, 1)); - } - json[D_JSON_IRHVAC_FANSPEED] = IRac::fanspeedToString(state.fanspeed); - json[D_JSON_IRHVAC_SWINGV] = IRac::swingvToString(state.swingv); - json[D_JSON_IRHVAC_SWINGH] = IRac::swinghToString(state.swingh); - json[D_JSON_IRHVAC_QUIET] = IRac::boolToString(state.quiet); - json[D_JSON_IRHVAC_TURBO] = IRac::boolToString(state.turbo); - json[D_JSON_IRHVAC_ECONO] = IRac::boolToString(state.econo); - json[D_JSON_IRHVAC_LIGHT] = IRac::boolToString(state.light); - json[D_JSON_IRHVAC_FILTER] = IRac::boolToString(state.filter); - json[D_JSON_IRHVAC_CLEAN] = IRac::boolToString(state.clean); - json[D_JSON_IRHVAC_BEEP] = IRac::boolToString(state.beep); - json[D_JSON_IRHVAC_SLEEP] = state.sleep; - - String payload = ""; - payload.reserve(200); - json.printTo(payload); - return payload; -} - -String sendIRJsonState(const struct decode_results &results) { - String json("{"); - json += "\"" D_JSON_IR_PROTOCOL "\":\""; - json += typeToString(results.decode_type); - json += "\",\"" D_JSON_IR_BITS "\":"; - json += results.bits; - - if (hasACState(results.decode_type)) { - json += ",\"" D_JSON_IR_DATA "\":\"0x"; - json += resultToHexidecimal(&results); - json += "\""; - } else { - if (UNKNOWN != results.decode_type) { - json += ",\"" D_JSON_IR_DATA "\":"; - } else { - json += ",\"" D_JSON_IR_HASH "\":"; - } - if (Settings.flag.ir_receive_decimal) { - char svalue[32]; - ulltoa(results.value, svalue, 10); - json += svalue; - } else { - char hvalue[64]; - if (UNKNOWN != results.decode_type) { - Uint64toHex(results.value, hvalue, results.bits); - json += "\""; - json += hvalue; - json += "\",\"" D_JSON_IR_DATALSB "\":\""; - Uint64toHex(reverseBitsInBytes64(results.value), hvalue, results.bits); - json += hvalue; - json += "\""; - } else { - Uint64toHex(results.value, hvalue, 32); - json += "\""; - json += hvalue; - json += "\""; - } - } - } - json += ",\"" D_JSON_IR_REPEAT "\":"; - json += results.repeat; - - stdAc::state_t ac_result; - if (IRAcUtils::decodeToState(&results, &ac_result, nullptr)) { - - json += ",\"" D_CMND_IRHVAC "\":"; - json += sendACJsonState(ac_result); - } - - return json; -} - -void IrReceiveCheck(void) -{ - char sirtype[14]; - int8_t iridx = 0; - - decode_results results; - - if (irrecv->decode(&results)) { - uint32_t now = millis(); - - - - if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { - ir_lasttime = now; - ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str()); - - if (Settings.flag3.receive_raw) { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); - uint16_t i; - for (i = 1; i < results.rawlen; i++) { - if (i > 1) { ResponseAppend_P(PSTR(",")); } - uint32_t usecs; - for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { - ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); - } - ResponseAppend_P(PSTR("%d"), usecs); - if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } - } - uint16_t extended_length = results.rawlen - 1; - for (uint32_t j = 0; j < results.rawlen - 1; j++) { - uint32_t usecs = results.rawbuf[j] * kRawTick; - - extended_length += (usecs / (UINT16_MAX + 1)) * 2; - } - ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); - } - - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); - - if (iridx) { - XdrvRulesProcess(); -#ifdef USE_DOMOTICZ - unsigned long value = results.value | (iridx << 28); - DomoticzSensor(DZ_COUNT, value); -#endif - } - } - - irrecv->resume(); - } -} - - - - - - - -String listSupportedProtocols(bool hvac) { - String l(""); - bool first = true; - for (uint32_t i = UNUSED + 1; i <= kLastDecodeType; i++) { - bool found = false; - if (hvac) { - found = IRac::isProtocolSupported((decode_type_t)i); - } else { - found = (IRsend::defaultBits((decode_type_t)i) > 0) && (!IRac::isProtocolSupported((decode_type_t)i)); - } - if (found) { - if (first) { - first = false; - } else { - l += "|"; - } - l += typeToString((decode_type_t)i); - } - } - return l; -} - - -const stdAc::fanspeed_t IrHvacFanSpeed[] PROGMEM = { stdAc::fanspeed_t::kAuto, - stdAc::fanspeed_t::kMin, stdAc::fanspeed_t::kLow,stdAc::fanspeed_t::kMedium, - stdAc::fanspeed_t::kHigh, stdAc::fanspeed_t::kMax }; - -uint32_t IrRemoteCmndIrHvacJson(void) -{ - stdAc::state_t state, prev; - char parm_uc[12]; - - - char dataBufUc[XdrvMailbox.data_len]; - UpperCase(dataBufUc, XdrvMailbox.data); - RemoveSpace(dataBufUc); - if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } - - DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(dataBufUc); - if (!json.success()) { return IE_INVALID_JSON; } - - - state.protocol = decode_type_t::UNKNOWN; - state.model = 1; - state.mode = stdAc::opmode_t::kAuto; - state.power = false; - state.celsius = true; - state.degrees = 21.0f; - state.fanspeed = stdAc::fanspeed_t::kMedium; - state.swingv = stdAc::swingv_t::kOff; - state.swingh = stdAc::swingh_t::kOff; - state.light = false; - state.beep = false; - state.econo = false; - state.filter = false; - state.turbo = false; - state.quiet = false; - state.sleep = -1; - state.clean = false; - state.clock = -1; - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR)); - if (json.containsKey(parm_uc)) { state.protocol = strToDecodeType(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_PROTOCOL)); - if (json.containsKey(parm_uc)) { state.protocol = strToDecodeType(json[parm_uc]); } - if (decode_type_t::UNKNOWN == state.protocol) { return IE_UNSUPPORTED_HVAC; } - if (!IRac::isProtocolSupported(state.protocol)) { return IE_UNSUPPORTED_HVAC; } - - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FANSPEED)); - if (json.containsKey(parm_uc)) { - uint32_t fan_speed = json[parm_uc]; - if ((fan_speed >= 1) && (fan_speed <= 5)) { - state.fanspeed = (stdAc::fanspeed_t) pgm_read_byte(&IrHvacFanSpeed[fan_speed]); - } else { - state.fanspeed = IRac::strToFanspeed(json[parm_uc]); - } - } - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODEL)); - if (json.containsKey(parm_uc)) { state.model = IRac::strToModel(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODE)); - if (json.containsKey(parm_uc)) { state.mode = IRac::strToOpmode(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SWINGV)); - if (json.containsKey(parm_uc)) { state.swingv = IRac::strToSwingV(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SWINGH)); - if (json.containsKey(parm_uc)) { state.swingh = IRac::strToSwingH(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TEMP)); - if (json.containsKey(parm_uc)) { state.degrees = json[parm_uc]; } - - - - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_POWER)); - if (json.containsKey(parm_uc)) { state.power = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_CELSIUS)); - if (json.containsKey(parm_uc)) { state.celsius = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_LIGHT)); - if (json.containsKey(parm_uc)) { state.light = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_BEEP)); - if (json.containsKey(parm_uc)) { state.beep = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_ECONO)); - if (json.containsKey(parm_uc)) { state.econo = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FILTER)); - if (json.containsKey(parm_uc)) { state.filter = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TURBO)); - if (json.containsKey(parm_uc)) { state.turbo = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_QUIET)); - if (json.containsKey(parm_uc)) { state.quiet = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_CLEAN)); - if (json.containsKey(parm_uc)) { state.clean = IRac::strToBool(json[parm_uc]); } - - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SLEEP)); - if (json[parm_uc]) { state.sleep = json[parm_uc]; } - - - IRac ac(pin[GPIO_IRSEND]); - bool success = ac.sendAc(state, &prev); - if (!success) { return IE_SYNTAX_IRHVAC; } - - Response_P(PSTR("{\"" D_CMND_IRHVAC "\":%s}"), sendACJsonState(state).c_str()); - return IE_RESPONSE_PROVIDED; -} - -void CmndIrHvac(void) -{ - uint8_t error = IE_SYNTAX_IRHVAC; - - if (XdrvMailbox.data_len) { - error = IrRemoteCmndIrHvacJson(); - } - if (error != IE_RESPONSE_PROVIDED) { IrRemoteCmndResponse(error); } -} - - - - - -uint32_t IrRemoteCmndIrSendJson(void) -{ - char parm_uc[12]; - - - - char dataBufUc[XdrvMailbox.data_len]; - UpperCase(dataBufUc, XdrvMailbox.data); - RemoveSpace(dataBufUc); - if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } - - DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(dataBufUc); - if (!json.success()) { return IE_INVALID_JSON; } - - - - decode_type_t protocol = decode_type_t::UNKNOWN; - uint16_t bits = 0; - uint64_t data; - uint8_t repeat = 0; - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR)); - if (json.containsKey(parm_uc)) { protocol = strToDecodeType(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_PROTOCOL)); - if (json.containsKey(parm_uc)) { protocol = strToDecodeType(json[parm_uc]); } - if (decode_type_t::UNKNOWN == protocol) { return IE_UNSUPPORTED_PROTOCOL; } - - UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS)); - if (json.containsKey(parm_uc)) { bits = json[parm_uc]; } - UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT)); - if (json.containsKey(parm_uc)) { repeat = json[parm_uc]; } - UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATALSB)); - if (json.containsKey(parm_uc)) { data = reverseBitsInBytes64(strtoull(json[parm_uc], nullptr, 0)); } - UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA)); - if (json.containsKey(parm_uc)) { data = strtoull(json[parm_uc], nullptr, 0); } - if (0 == bits) { return IE_SYNTAX_IRSEND; } - - - if (XdrvMailbox.index > repeat + 1) { repeat = XdrvMailbox.index - 1; } - - char dvalue[32]; - char hvalue[32]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol %d, bits %d, data %s (%s), repeat %d"), - protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat); - - irsend_active = true; - bool success = irsend->send(protocol, data, bits, repeat); - - if (!success) { - irsend_active = false; - ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); - } - return IE_NO_ERROR; -} - -uint32_t IrRemoteCmndIrSendRaw(void) -{ - - - - - - - - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - if (p == nullptr) { - return IE_INVALID_RAWDATA; - } - - - uint16_t repeat = XdrvMailbox.index > 0 ? XdrvMailbox.index - 1 : 0; - - uint16_t freq = atoi(str); - if (!freq && (*str != '0')) { - uint16_t count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - if (count < 2) { - return IE_INVALID_RAWDATA; - } - - uint16_t parm[count]; - for (uint32_t i = 0; i < count; i++) { - parm[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - if (!parm[i]) { - if (!i) { - parm[0] = 38000; - } else { - return IE_INVALID_RAWDATA; - } - } - } - - uint16_t i = 0; - if (count < 4) { - - uint16_t mark = parm[1] *2; - if (3 == count) { - if (parm[2] < parm[1]) { - - mark = parm[1] * parm[2]; - } else { - - mark = parm[2]; - } - } - uint16_t raw_array[strlen(p)]; - for (; *p; *p++) { - if (*p == '0') { - raw_array[i++] = parm[1]; - } - else if (*p == '1') { - raw_array[i++] = mark; - } - } - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, i, parm[0]); - if (r < repeat) { - irsend->space(40000); - } - } - } - else if (6 == count) { - - uint16_t raw_array[strlen(p)*2+3]; - raw_array[i++] = parm[1]; - raw_array[i++] = parm[2]; - uint32_t inter_message_32 = (parm[1] + parm[2]) * 3; - uint16_t inter_message = (inter_message_32 > 65000) ? 65000 : inter_message_32; - for (; *p; *p++) { - if (*p == '0') { - raw_array[i++] = parm[3]; - raw_array[i++] = parm[4]; - } - else if (*p == '1') { - raw_array[i++] = parm[3]; - raw_array[i++] = parm[5]; - } - } - raw_array[i++] = parm[3]; - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, i, parm[0]); - if (r < repeat) { - irsend->space(inter_message); - } - } - } - else { - return IE_INVALID_RAWDATA; - } - } else { - if (!freq) { freq = 38000; } - uint16_t count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - if (0 == count) { - return IE_INVALID_RAWDATA; - } - - - count++; - if (count < 200) { - uint16_t raw_array[count]; - for (uint32_t i = 0; i < count; i++) { - raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - } - - - - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, count, freq); - } - } else { - uint16_t *raw_array = reinterpret_cast(malloc(count * sizeof(uint16_t))); - if (raw_array == nullptr) { - return IE_INVALID_RAWDATA; - } - - for (uint32_t i = 0; i < count; i++) { - raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - } - - - - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, count, freq); - } - free(raw_array); - } - } - - return IE_NO_ERROR; -} - -void CmndIrSend(void) -{ - uint8_t error = IE_SYNTAX_IRSEND; - - if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, "{") == nullptr) { - error = IrRemoteCmndIrSendRaw(); - } else { - error = IrRemoteCmndIrSendJson(); - } - } - IrRemoteCmndResponse(error); -} - -void IrRemoteCmndResponse(uint32_t error) -{ - switch (error) { - case IE_INVALID_RAWDATA: - ResponseCmndChar(D_JSON_INVALID_RAWDATA); - break; - case IE_INVALID_JSON: - ResponseCmndChar(D_JSON_INVALID_JSON); - break; - case IE_SYNTAX_IRSEND: - Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); - break; - case IE_SYNTAX_IRHVAC: - Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); - break; - case IE_UNSUPPORTED_HVAC: - Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR " (%s)\"}"), listSupportedProtocols(true).c_str()); - break; - case IE_UNSUPPORTED_PROTOCOL: - Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_PROTOCOL " (%s)\"}"), listSupportedProtocols(false).c_str()); - break; - default: - ResponseCmndDone(); - } -} - - - - - -bool Xdrv05(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { - switch (function) { - case FUNC_PRE_INIT: - if (pin[GPIO_IRSEND] < 99) { - IrSendInit(); - } - if (pin[GPIO_IRRECV] < 99) { - IrReceiveInit(); - } - break; - case FUNC_EVERY_50_MSECOND: - if (pin[GPIO_IRRECV] < 99) { - IrReceiveCheck(); - } - irsend_active = false; - break; - case FUNC_COMMAND: - if (pin[GPIO_IRSEND] < 99) { - result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); - } - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_06_snfbridge.ino" -# 24 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_06_snfbridge.ino" -#define XDRV_06 6 - -const uint32_t SFB_TIME_AVOID_DUPLICATE = 2000; - -enum SonoffBridgeCommands { - CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE }; - -const char kSonoffBridgeCommands[] PROGMEM = "|" - D_CMND_RFSYNC "|" D_CMND_RFLOW "|" D_CMND_RFHIGH "|" D_CMND_RFHOST "|" D_CMND_RFCODE "|" D_CMND_RFKEY "|" D_CMND_RFRAW; - -void (* const SonoffBridgeCommand[])(void) PROGMEM = { - &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfKey, &CmndRfRaw }; - -struct SONOFFBRIDGE { - uint32_t last_received_id = 0; - uint32_t last_send_code = 0; - uint32_t last_time = 0; - uint32_t last_learn_time = 0; - uint8_t receive_flag = 0; - uint8_t receive_raw_flag = 0; - uint8_t learn_key = 1; - uint8_t learn_active = 0; - uint8_t expected_bytes = 0; -} SnfBridge; - -#ifdef USE_RF_FLASH - - - - - - - -#include "ihx.h" -#include "c2.h" - -const ssize_t RF_RECORD_NO_START_FOUND = -1; -const ssize_t RF_RECORD_NO_END_FOUND = -2; - -ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size) -{ - for (size_t i = 0; i < size; i++) { - if (buf[i] == ':') { - return i; - } - } - return RF_RECORD_NO_START_FOUND; -} - -ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size) -{ - for (size_t i = 0; i < size; i++) { - if (buf[i] == '\n') { - return i; - } - } - return RF_RECORD_NO_END_FOUND; -} - -ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uint8_t *new_data, size_t new_data_len) -{ - ssize_t record_start; - ssize_t record_end; - ssize_t glue_record_sz; - uint8_t *glue_buf; - ssize_t result; - - if (remnant_data[0] != ':') { return -8; } - - - record_end = rf_find_hex_record_end(new_data, new_data_len); - record_start = rf_find_hex_record_start(new_data, new_data_len); - - - - - if ((record_start != RF_RECORD_NO_START_FOUND) && (record_start < record_end)) { - return -8; - } - - glue_record_sz = strlen((const char *) remnant_data) + record_end; - - glue_buf = (uint8_t *) malloc(glue_record_sz); - if (glue_buf == nullptr) { return -2; } - - - memcpy(glue_buf, remnant_data, strlen((const char *) remnant_data)); - memcpy(glue_buf + strlen((const char *) remnant_data), new_data, record_end); - - result = rf_decode_and_write(glue_buf, glue_record_sz); - free(glue_buf); - return result; -} - -ssize_t rf_decode_and_write(uint8_t *record, size_t size) -{ - uint8_t err = ihx_decode(record, size); - if (err != IHX_SUCCESS) { return -13; } - - ihx_t *h = (ihx_t *) record; - if (h->record_type == IHX_RT_DATA) { - int retries = 5; - uint16_t address = h->address_high * 0x100 + h->address_low; - - do { - err = c2_programming_init(); - err = c2_block_write(address, h->data, h->len); - } while (err != C2_SUCCESS && retries--); - } else if (h->record_type == IHX_RT_END_OF_FILE) { - - err = c2_reset(); - } - - if (err != C2_SUCCESS) { return -12; } - - return 0; -} - -ssize_t rf_search_and_write(uint8_t *buf, size_t size) -{ - - ssize_t rec_end; - ssize_t rec_start; - ssize_t err; - - for (size_t i = 0; i < size; i++) { - - rec_start = rf_find_hex_record_start(buf + i, size - i); - if (rec_start == RF_RECORD_NO_START_FOUND) { - - return -8; - } - - - rec_start += i; - rec_end = rf_find_hex_record_end(buf + rec_start, size - rec_start); - if (rec_end == RF_RECORD_NO_END_FOUND) { - - return rec_start; - } - - - rec_end += rec_start; - - err = rf_decode_and_write(buf + rec_start, rec_end - rec_start); - if (err < 0) { return err; } - i = rec_end; - } - - return 0; -} - -uint8_t rf_erase_flash(void) -{ - uint8_t err; - - for (uint32_t i = 0; i < 4; i++) { - err = c2_programming_init(); - if (err != C2_SUCCESS) { - return 10; - } - err = c2_device_erase(); - if (err != C2_SUCCESS) { - if (i < 3) { - c2_reset(); - } else { - return 11; - } - } else { - break; - } - } - return 0; -} - -uint8_t SnfBrUpdateInit(void) -{ - pinMode(PIN_C2CK, OUTPUT); - pinMode(PIN_C2D, INPUT); - - return rf_erase_flash(); -} -#endif - - - -void SonoffBridgeReceivedRaw(void) -{ - - uint8_t buckets = 0; - - if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } - - ResponseTime_P(PSTR(",\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); - for (uint32_t i = 0; i < serial_in_byte_counter; i++) { - ResponseAppend_P(PSTR("%02X"), serial_in_buffer[i]); - if (0xB1 == serial_in_buffer[1]) { - if ((i > 3) && buckets) { buckets--; } - if ((i < 3) || (buckets % 2) || (i == serial_in_byte_counter -2)) { - ResponseAppend_P(PSTR(" ")); - } - } - } - ResponseAppend_P(PSTR("\"}}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW)); - - XdrvRulesProcess(); -} - - - -void SonoffBridgeLearnFailed(void) -{ - SnfBridge.learn_active = 0; - Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARN_FAILED); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); -} - -void SonoffBridgeReceived(void) -{ - uint16_t sync_time = 0; - uint16_t low_time = 0; - uint16_t high_time = 0; - uint32_t received_id = 0; - char rfkey[8]; - char stemp[16]; - - AddLogSerial(LOG_LEVEL_DEBUG); - - if (0xA2 == serial_in_buffer[0]) { - SonoffBridgeLearnFailed(); - } - else if (0xA3 == serial_in_buffer[0]) { - SnfBridge.learn_active = 0; - low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; - high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; - if (low_time && high_time) { - for (uint32_t i = 0; i < 9; i++) { - Settings.rf_code[SnfBridge.learn_key][i] = serial_in_buffer[i +1]; - } - Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARNED); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); - } else { - SonoffBridgeLearnFailed(); - } - } - else if (0xA4 == serial_in_buffer[0]) { - if (SnfBridge.learn_active) { - SonoffBridgeLearnFailed(); - } else { - sync_time = serial_in_buffer[1] << 8 | serial_in_buffer[2]; - low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; - high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; - received_id = serial_in_buffer[7] << 16 | serial_in_buffer[8] << 8 | serial_in_buffer[9]; - - unsigned long now = millis(); - if (!((received_id == SnfBridge.last_received_id) && (now - SnfBridge.last_time < SFB_TIME_AVOID_DUPLICATE))) { - SnfBridge.last_received_id = received_id; - SnfBridge.last_time = now; - strncpy_P(rfkey, PSTR("\"" D_JSON_NONE "\""), sizeof(rfkey)); - for (uint32_t 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; - } - } - } - if (Settings.flag.rf_receive_decimal) { - snprintf_P(stemp, sizeof(stemp), PSTR("%u"), received_id); - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"%06X\""), received_id); - } - ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"), - sync_time, low_time, high_time, stemp, rfkey); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); - XdrvRulesProcess(); - #ifdef USE_DOMOTICZ - DomoticzSensor(DZ_COUNT, received_id); - #endif - } - } - } -} - -bool SonoffBridgeSerialInput(void) -{ - - static int8_t receive_len = 0; - - if (SnfBridge.receive_flag) { - if (SnfBridge.receive_raw_flag) { - if (!serial_in_byte_counter) { - serial_in_buffer[serial_in_byte_counter++] = 0xAA; - } - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (serial_in_byte_counter == 3) { - if ((0xA6 == serial_in_buffer[1]) || (0xAB == serial_in_buffer[1])) { - receive_len = serial_in_buffer[2] + 4; - } - } - if ((!receive_len && (0x55 == serial_in_byte)) || (receive_len && (serial_in_byte_counter == receive_len))) { - SonoffBridgeReceivedRaw(); - SnfBridge.receive_flag = 0; - return 1; - } - } - else if (!((0 == serial_in_byte_counter) && (0 == serial_in_byte))) { - if (0 == serial_in_byte_counter) { - SnfBridge.expected_bytes = 2; - if (serial_in_byte >= 0xA3) { - SnfBridge.expected_bytes = 11; - } - if (serial_in_byte == 0xA6) { - SnfBridge.expected_bytes = 0; - serial_in_buffer[serial_in_byte_counter++] = 0xAA; - SnfBridge.receive_raw_flag = 1; - } - } - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if ((SnfBridge.expected_bytes == serial_in_byte_counter) && (0x55 == serial_in_byte)) { - SonoffBridgeReceived(); - SnfBridge.receive_flag = 0; - return 1; - } - } - serial_in_byte = 0; - } - if (0xAA == serial_in_byte) { - serial_in_byte_counter = 0; - serial_in_byte = 0; - SnfBridge.receive_flag = 1; - receive_len = 0; - } - return 0; -} - -void SonoffBridgeSendCommand(uint8_t code) -{ - Serial.write(0xAA); - Serial.write(code); - Serial.write(0x55); -} - -void SonoffBridgeSendAck(void) -{ - Serial.write(0xAA); - Serial.write(0xA0); - Serial.write(0x55); -} - -void SonoffBridgeSendCode(uint32_t code) -{ - Serial.write(0xAA); - Serial.write(0xA5); - for (uint32_t 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); - Serial.flush(); -} - -void SonoffBridgeSend(uint8_t idx, uint8_t key) -{ - uint8_t code; - - key--; - Serial.write(0xAA); - Serial.write(0xA5); - for (uint32_t i = 0; i < 8; i++) { - Serial.write(Settings.rf_code[idx][i]); - } - if (0 == idx) { - code = (0x10 << (key >> 2)) | (1 << (key & 3)); - } else { - code = Settings.rf_code[idx][8]; - } - Serial.write(code); - Serial.write(0x55); - Serial.flush(); -#ifdef USE_DOMOTICZ - - -#endif -} - -void SonoffBridgeLearn(uint8_t key) -{ - SnfBridge.learn_key = key; - SnfBridge.learn_active = 1; - SnfBridge.last_learn_time = millis(); - Serial.write(0xAA); - Serial.write(0xA1); - Serial.write(0x55); -} - - - - - -void CmndRfBridge(void) -{ - char *p; - char stemp [10]; - uint32_t code = 0; - uint8_t radix = 10; - - uint32_t set_index = XdrvMailbox.command_code *2; - - if (XdrvMailbox.data[0] == '#') { - XdrvMailbox.data++; - XdrvMailbox.data_len--; - radix = 16; - } - - if (XdrvMailbox.data_len) { - code = strtol(XdrvMailbox.data, &p, radix); - if (code) { - if (CMND_RFCODE == XdrvMailbox.command_code) { - SnfBridge.last_send_code = code; - SonoffBridgeSendCode(code); - } else { - if (1 == XdrvMailbox.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)) { - Settings.rf_code[0][set_index] = msb; - Settings.rf_code[0][set_index +1] = lsb; - } - } - } - } - if (CMND_RFCODE == XdrvMailbox.command_code) { - code = SnfBridge.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); - } - Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp); -} - -void CmndRfKey(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 16)) { - unsigned long now = millis(); - if ((!SnfBridge.learn_active) || (now - SnfBridge.last_learn_time > 60100)) { - SnfBridge.learn_active = 0; - if (2 == XdrvMailbox.payload) { - SonoffBridgeLearn(XdrvMailbox.index); - ResponseCmndIdxChar(D_JSON_START_LEARNING); - } - else if (3 == XdrvMailbox.payload) { - Settings.rf_code[XdrvMailbox.index][0] = 0; - ResponseCmndIdxChar(D_JSON_SET_TO_DEFAULT); - } - else if (4 == XdrvMailbox.payload) { - for (uint32_t i = 0; i < 6; i++) { - Settings.rf_code[XdrvMailbox.index][i] = Settings.rf_code[0][i]; - } - Settings.rf_code[XdrvMailbox.index][6] = (SnfBridge.last_send_code >> 16) & 0xff; - Settings.rf_code[XdrvMailbox.index][7] = (SnfBridge.last_send_code >> 8) & 0xff; - Settings.rf_code[XdrvMailbox.index][8] = SnfBridge.last_send_code & 0xff; - ResponseCmndIdxChar(D_JSON_SAVED); - } else if (5 == XdrvMailbox.payload) { - uint8_t key = XdrvMailbox.index; - uint8_t index = (0 == Settings.rf_code[key][0]) ? 0 : key; - uint16_t sync_time = (Settings.rf_code[index][0] << 8) | Settings.rf_code[index][1]; - uint16_t low_time = (Settings.rf_code[index][2] << 8) | Settings.rf_code[index][3]; - uint16_t high_time = (Settings.rf_code[index][4] << 8) | Settings.rf_code[index][5]; - uint32_t code = (Settings.rf_code[index][6] << 16) | (Settings.rf_code[index][7] << 8); - if (0 == index) { - key--; - code |= (uint8_t)((0x10 << (key >> 2)) | (1 << (key & 3))); - } else { - code |= Settings.rf_code[index][8]; - } - Response_P(PSTR("{\"%s%d\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\"}}"), - XdrvMailbox.command, XdrvMailbox.index, sync_time, low_time, high_time, code); - } else { - if ((1 == XdrvMailbox.payload) || (0 == Settings.rf_code[XdrvMailbox.index][0])) { - SonoffBridgeSend(0, XdrvMailbox.index); - ResponseCmndIdxChar(D_JSON_DEFAULT_SENT); - } else { - SonoffBridgeSend(XdrvMailbox.index, 0); - ResponseCmndIdxChar(D_JSON_LEARNED_SENT); - } - } - } else { - Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, SnfBridge.learn_key, D_JSON_LEARNING_ACTIVE); - } - } -} - -void CmndRfRaw(void) -{ - if (XdrvMailbox.data_len) { - if (XdrvMailbox.data_len < 6) { - switch (XdrvMailbox.payload) { - case 0: - SonoffBridgeSendCommand(0xA7); - case 1: - SnfBridge.receive_raw_flag = XdrvMailbox.payload; - break; - case 166: - case 167: - case 169: - case 176: - case 177: - case 255: - SonoffBridgeSendCommand(XdrvMailbox.payload); - SnfBridge.receive_raw_flag = 1; - break; - case 192: - char beep[] = "AAC000C055\0"; - SerialSendRaw(beep); - break; - } - } else { - SerialSendRaw(RemoveSpace(XdrvMailbox.data)); - SnfBridge.receive_raw_flag = 1; - } - } - ResponseCmndStateText(SnfBridge.receive_raw_flag); -} - - - - - -bool Xdrv06(uint8_t function) -{ - bool result = false; - - if (SONOFF_BRIDGE == my_module_type) { - switch (function) { - case FUNC_SERIAL: - result = SonoffBridgeSerialInput(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kSonoffBridgeCommands, SonoffBridgeCommand); - break; - case FUNC_INIT: - SnfBridge.receive_raw_flag = 0; - SonoffBridgeSendCommand(0xA7); - break; - case FUNC_PRE_INIT: - Settings.flag.mqtt_serial = 0; - baudrate = 19200; - break; - } - } - return result; -} -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_07_domoticz.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_07_domoticz.ino" -#ifdef USE_DOMOTICZ - -#define XDRV_07 7 - -#define D_PRFX_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" - -const char kDomoticzCommands[] PROGMEM = D_PRFX_DOMOTICZ "|" - D_CMND_IDX "|" D_CMND_KEYIDX "|" D_CMND_SWITCHIDX "|" D_CMND_SENSORIDX "|" D_CMND_UPDATETIMER ; - -void (* const DomoticzCommand[])(void) PROGMEM = { - &CmndDomoticzIdx, &CmndDomoticzKeyIdx, &CmndDomoticzSwitchIdx, &CmndDomoticzSensorIdx, &CmndDomoticzUpdateTimer }; - -const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\",\"Battery\":%d,\"RSSI\":%d}"; - -#if MAX_DOMOTICZ_SNS_IDX < DZ_MAX_SENSORS - #error "Domoticz: Too many sensors or change settings.h layout" -#endif - -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 "|" D_DOMOTICZ_AIRQUALITY "|" D_DOMOTICZ_P1_SMART_METER ; - -char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; -char domoticz_out_topic[] = DOMOTICZ_OUT_TOPIC; - -int domoticz_update_timer = 0; -uint32_t domoticz_fan_debounce = 0; -bool domoticz_subscribe = false; -bool domoticz_update_flag = true; - -int DomoticzBatteryQuality(void) -{ - - - - - int quality = 100; - -#ifdef USE_ADC_VCC - uint16_t voltage = ESP.getVcc(); - if (voltage <= 2600) { - quality = 0; - } else if (voltage >= 4600) { - quality = 200; - } else { - quality = (voltage - 2600) / 10; - } -#endif - return quality; -} - -int DomoticzRssiQuality(void) -{ - - - return WifiGetRssiAsQuality(WiFi.RSSI()) / 10; -} - -#ifdef USE_SONOFF_IFAN -void MqttPublishDomoticzFanState() -{ - if (Settings.flag.mqtt_enabled && Settings.domoticz_relay_idx[1]) { - char svalue[8]; - - int fan_speed = GetFanspeed(); - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fan_speed * 10); - Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); - MqttPublish(domoticz_in_topic); - - domoticz_fan_debounce = millis(); - } -} - -void DomoticzUpdateFanState() -{ - if (domoticz_update_flag) { - MqttPublishDomoticzFanState(); - } - domoticz_update_flag = true; -} -#endif - -void MqttPublishDomoticzPowerState(uint8_t device) -{ - if (Settings.flag.mqtt_enabled) { - if ((device < 1) || (device > devices_present)) { device = 1; } - if (Settings.domoticz_relay_idx[device -1]) { -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (device > 1)) { - - } else { -#endif - char svalue[8]; - - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); - Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); - MqttPublish(domoticz_in_topic); -#ifdef USE_SONOFF_IFAN - } -#endif - } - } -} - -void DomoticzUpdatePowerState(uint8_t device) -{ - if (domoticz_update_flag) { - MqttPublishDomoticzPowerState(device); - } - domoticz_update_flag = true; -} - -void DomoticzMqttUpdate(void) -{ - if (domoticz_subscribe && (Settings.domoticz_update_timer || domoticz_update_timer)) { - domoticz_update_timer--; - if (domoticz_update_timer <= 0) { - domoticz_update_timer = Settings.domoticz_update_timer; - for (uint32_t i = 1; i <= devices_present; i++) { -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (i > 1)) { - MqttPublishDomoticzFanState(); - break; - } else { -#endif - MqttPublishDomoticzPowerState(i); -#ifdef USE_SONOFF_IFAN - } -#endif - } - } - } -} - -void DomoticzMqttSubscribe(void) -{ - uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; - for (uint32_t 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); - MqttSubscribe(stopic); - } -} -# 200 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_07_domoticz.ino" -bool DomoticzMqttData(void) -{ - char stemp1[10]; - unsigned long idx = 0; - int16_t nvalue = -1; - bool found = false; - - domoticz_update_flag = true; - if (!strncmp(XdrvMailbox.topic, domoticz_out_topic, strlen(domoticz_out_topic))) { - if (XdrvMailbox.data_len < 20) { - return true; - } - StaticJsonBuffer<400> jsonBuf; - JsonObject& domoticz = jsonBuf.parseObject(XdrvMailbox.data); - if (!domoticz.success()) { - return true; - } - - - - idx = domoticz["idx"]; - if (domoticz.containsKey("nvalue")) { - nvalue = domoticz["nvalue"]; - } - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); - - if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) { - uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; - for (uint32_t i = 0; i < maxdev; i++) { - if (idx == Settings.domoticz_relay_idx[i]) { - bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (1 == i)) { - uint8_t svalue = 0; - if (domoticz.containsKey("svalue1")) { - svalue = domoticz["svalue1"]; - } else { - return true; - } - svalue = (nvalue == 2) ? svalue / 10 : 0; - if (GetFanspeed() == svalue) { - return true; - } - if (TimePassedSince(domoticz_fan_debounce) < 1000) { - return true; - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue); - found = true; - } else -#endif - if (iscolordimmer && 10 == nvalue) { - JsonObject& color = domoticz["Color"]; - uint16_t level = nvalue = domoticz["svalue1"]; - uint16_t r = color["r"]; r = r * level / 100; - uint16_t g = color["g"]; g = g * level / 100; - uint16_t b = color["b"]; b = b * level / 100; - uint16_t cw = color["cw"]; cw = cw * level / 100; - uint16_t ww = color["ww"]; ww = ww * level / 100; - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww); - found = true; - } - else if ((!iscolordimmer && 2 == nvalue) || - (iscolordimmer && 15 == nvalue)) { - if (domoticz.containsKey("svalue1")) { - nvalue = domoticz["svalue1"]; - } else { - return true; - } - if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) { - return true; - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); - found = true; - } - else if (1 == nvalue || 0 == nvalue) { - if (((power >> i) &1) == (power_t)nvalue) { - return true; - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : ""); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); - found = true; - } - break; - } - } - } - if (!found) { return true; } - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data); - - domoticz_update_flag = false; - } - return false; -} - - - -bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg) -{ - bool result = false; - - if (device <= MAX_DOMOTICZ_IDX) { - if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) { - Response_P(PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), - (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (POWER_TOGGLE == state) ? "Toggle" : "On" : "Off"); - MqttPublish(domoticz_in_topic); - result = true; - } - } - return result; -} -# 334 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_07_domoticz.ino" -uint8_t DomoticzHumidityState(char *hum) -{ - uint8_t h = atoi(hum); - return (!h) ? 0 : (h < 40) ? 2 : (h > 70) ? 3 : 1; -} - -void DomoticzSensor(uint8_t idx, char *data) -{ - if (Settings.domoticz_sensor_idx[idx]) { - char dmess[128]; - - memcpy(dmess, mqtt_data, sizeof(dmess)); - if (DZ_AIRQUALITY == idx) { - Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), - Settings.domoticz_sensor_idx[idx], data, DomoticzBatteryQuality(), DomoticzRssiQuality()); - } else { - Response_P(DOMOTICZ_MESSAGE, - Settings.domoticz_sensor_idx[idx], 0, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); - } - MqttPublish(domoticz_in_topic); - memcpy(mqtt_data, dmess, sizeof(dmess)); - } -} - -void DomoticzSensor(uint8_t idx, uint32_t value) -{ - char data[16]; - snprintf_P(data, sizeof(data), PSTR("%d"), value); - DomoticzSensor(idx, data); -} - -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, DomoticzHumidityState(hum), baro); - DomoticzSensor(DZ_TEMP_HUM_BARO, data); -} - -void DomoticzSensorPowerEnergy(int power, char *energy) -{ - char data[16]; - snprintf_P(data, sizeof(data), PSTR("%d;%s"), power, energy); - DomoticzSensor(DZ_POWER_ENERGY, data); -} - -void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int power) -{ - - - - - - int consumed = power; - int produced = 0; - if (power < 0) { - consumed = 0; - produced = -power; - } - char data[64]; - snprintf_P(data, sizeof(data), PSTR("%s;%s;%s;%s;%d;%d"), usage1, usage2, return1, return2, consumed, produced); - DomoticzSensor(DZ_P1_SMART_METER, data); -} - - - - - -void CmndDomoticzIdx(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { - if (XdrvMailbox.payload >= 0) { - Settings.domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - restart_flag = 2; - } - ResponseCmndIdxNumber(Settings.domoticz_relay_idx[XdrvMailbox.index -1]); - } -} - -void CmndDomoticzKeyIdx(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { - if (XdrvMailbox.payload >= 0) { - Settings.domoticz_key_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.domoticz_key_idx[XdrvMailbox.index -1]); - } -} - -void CmndDomoticzSwitchIdx(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { - if (XdrvMailbox.payload >= 0) { - Settings.domoticz_switch_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.domoticz_switch_idx[XdrvMailbox.index -1]); - } -} - -void CmndDomoticzSensorIdx(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= DZ_MAX_SENSORS)) { - if (XdrvMailbox.payload >= 0) { - Settings.domoticz_sensor_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.domoticz_sensor_idx[XdrvMailbox.index -1]); - } -} - -void CmndDomoticzUpdateTimer(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.domoticz_update_timer = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.domoticz_update_timer); -} - - - - - -#ifdef USE_WEBSERVER - -#define WEB_HANDLE_DOMOTICZ "dm" - -const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ; - -const char HTTP_BTN_MENU_DOMOTICZ[] PROGMEM = - "

"; - -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_SENSOR[] PROGMEM = - ""; -const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM = - ""; - -void HandleDomoticzConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_DOMOTICZ); - - if (WebServer->hasArg("save")) { - DomoticzSaveSettings(); - WebRestart(1); - return; - } - - char stemp[40]; - - WSContentStart_P(S_CONFIGURE_DOMOTICZ); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_DOMOTICZ); - for (uint32_t i = 0; i < MAX_DOMOTICZ_IDX; i++) { - if (i < devices_present) { - WSContentSend_P(HTTP_FORM_DOMOTICZ_RELAY, - i +1, i, Settings.domoticz_relay_idx[i], - i +1, i, Settings.domoticz_key_idx[i]); - } - if (pin[GPIO_SWT1 +i] < 99) { - WSContentSend_P(HTTP_FORM_DOMOTICZ_SWITCH, - i +1, i, Settings.domoticz_switch_idx[i]); - } -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (1 == i)) { break; } -#endif - } - for (uint32_t i = 0; i < DZ_MAX_SENSORS; i++) { - WSContentSend_P(HTTP_FORM_DOMOTICZ_SENSOR, - i +1, GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors), i, Settings.domoticz_sensor_idx[i]); - } - WSContentSend_P(HTTP_FORM_DOMOTICZ_TIMER, Settings.domoticz_update_timer); - WSContentSend_P(PSTR("
" D_DOMOTICZ_IDX " %d
" D_DOMOTICZ_KEY_IDX " %d
" D_DOMOTICZ_SWITCH_IDX " %d
" D_DOMOTICZ_SENSOR_IDX " %d %s
" D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ")
")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void DomoticzSaveSettings(void) -{ - char stemp[20]; - char ssensor_indices[6 * MAX_DOMOTICZ_SNS_IDX]; - char tmp[100]; - - for (uint32_t i = 0; i < MAX_DOMOTICZ_IDX; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("r%d"), i); - WebGetArg(stemp, tmp, sizeof(tmp)); - Settings.domoticz_relay_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - snprintf_P(stemp, sizeof(stemp), PSTR("k%d"), i); - WebGetArg(stemp, tmp, sizeof(tmp)); - Settings.domoticz_key_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - snprintf_P(stemp, sizeof(stemp), PSTR("s%d"), i); - WebGetArg(stemp, tmp, sizeof(tmp)); - Settings.domoticz_switch_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - } - ssensor_indices[0] = '\0'; - for (uint32_t i = 0; i < DZ_MAX_SENSORS; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("l%d"), i); - WebGetArg(stemp, tmp, sizeof(tmp)); - Settings.domoticz_sensor_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - snprintf_P(ssensor_indices, sizeof(ssensor_indices), PSTR("%s%s%d"), ssensor_indices, (strlen(ssensor_indices)) ? "," : "", Settings.domoticz_sensor_idx[i]); - } - WebGetArg("ut", tmp, sizeof(tmp)); - Settings.domoticz_update_timer = (!strlen(tmp)) ? DOMOTICZ_UPDATE_TIMER : atoi(tmp); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_DOMOTICZ D_CMND_IDX " %d,%d,%d,%d, " D_CMND_KEYIDX " %d,%d,%d,%d, " D_CMND_SWITCHIDX " %d,%d,%d,%d, " D_CMND_SENSORIDX " %s, " D_CMND_UPDATETIMER " %d"), - Settings.domoticz_relay_idx[0], Settings.domoticz_relay_idx[1], Settings.domoticz_relay_idx[2], Settings.domoticz_relay_idx[3], - 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], - ssensor_indices, Settings.domoticz_update_timer); -} -#endif - - - - - -bool Xdrv07(uint8_t function) -{ - bool result = false; - - if (Settings.flag.mqtt_enabled) { - switch (function) { - case FUNC_EVERY_SECOND: - DomoticzMqttUpdate(); - break; - case FUNC_MQTT_DATA: - result = DomoticzMqttData(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_DOMOTICZ); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration); - break; -#endif - case FUNC_MQTT_SUBSCRIBE: - DomoticzMqttSubscribe(); - break; - case FUNC_MQTT_INIT: - domoticz_update_timer = 2; - break; - case FUNC_SHOW_SENSOR: - - break; - case FUNC_COMMAND: - result = DecodeCommand(kDomoticzCommands, DomoticzCommand); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_08_serial_bridge.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_08_serial_bridge.ino" -#ifdef USE_SERIAL_BRIDGE - - - - -#define XDRV_08 8 - -const uint8_t SERIAL_BRIDGE_BUFFER_SIZE = 130; - -const char kSerialBridgeCommands[] PROGMEM = "|" - D_CMND_SSERIALSEND "|" D_CMND_SBAUDRATE; - -void (* const SerialBridgeCommand[])(void) PROGMEM = - { &CmndSSerialSend, &CmndSBaudrate }; - -#include - -TasmotaSerial *SerialBridgeSerial = nullptr; - -unsigned long serial_bridge_polling_window = 0; -char *serial_bridge_buffer = nullptr; -int serial_bridge_in_byte_counter = 0; -bool serial_bridge_active = true; -bool serial_bridge_raw = false; - -void SerialBridgeInput(void) -{ - while (SerialBridgeSerial->available()) { - yield(); - uint8_t serial_in_byte = SerialBridgeSerial->read(); - - if ((serial_in_byte > 127) && !serial_bridge_raw) { - serial_bridge_in_byte_counter = 0; - SerialBridgeSerial->flush(); - return; - } - if (serial_in_byte || serial_bridge_raw) { - - if ((serial_bridge_in_byte_counter < SERIAL_BRIDGE_BUFFER_SIZE -1) && - ((isprint(serial_in_byte) && (128 == Settings.serial_delimiter)) || - ((serial_in_byte != Settings.serial_delimiter) && (128 != Settings.serial_delimiter)) || - serial_bridge_raw)) { - serial_bridge_buffer[serial_bridge_in_byte_counter++] = serial_in_byte; - serial_bridge_polling_window = millis(); - } else { - serial_bridge_polling_window = 0; - break; - } - } - } - - if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) { - serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; - char hex_char[(serial_bridge_in_byte_counter * 2) + 2]; - ResponseTime_P(PSTR(",\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), - (serial_bridge_raw) ? ToHex_P((unsigned char*)serial_bridge_buffer, serial_bridge_in_byte_counter, hex_char, sizeof(hex_char)) : serial_bridge_buffer); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); - XdrvRulesProcess(); - serial_bridge_in_byte_counter = 0; - } -} - - - -void SerialBridgeInit(void) -{ - serial_bridge_active = false; - if ((pin[GPIO_SBR_RX] < 99) && (pin[GPIO_SBR_TX] < 99)) { - SerialBridgeSerial = new TasmotaSerial(pin[GPIO_SBR_RX], pin[GPIO_SBR_TX]); - if (SerialBridgeSerial->begin(Settings.sbaudrate * 300)) { - if (SerialBridgeSerial->hardwareSerial()) { - ClaimSerial(); - serial_bridge_buffer = serial_in_buffer; - } else { - serial_bridge_buffer = (char*)(malloc(SERIAL_BRIDGE_BUFFER_SIZE)); - } - serial_bridge_active = true; - SerialBridgeSerial->flush(); - } - } -} - - - - - -void CmndSSerialSend(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { - serial_bridge_raw = (XdrvMailbox.index > 3); - if (XdrvMailbox.data_len > 0) { - if (1 == XdrvMailbox.index) { - SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); - SerialBridgeSerial->write("\n"); - } - else if ((2 == XdrvMailbox.index) || (4 == XdrvMailbox.index)) { - SerialBridgeSerial->write(XdrvMailbox.data, XdrvMailbox.data_len); - } - else if (3 == XdrvMailbox.index) { - SerialBridgeSerial->write(Unescape(XdrvMailbox.data, &XdrvMailbox.data_len), XdrvMailbox.data_len); - } - else if (5 == XdrvMailbox.index) { - char *p; - char stemp[3]; - uint8_t code; - - char *codes = RemoveSpace(XdrvMailbox.data); - int size = strlen(XdrvMailbox.data); - - while (size > 0) { - strlcpy(stemp, codes, sizeof(stemp)); - code = strtol(stemp, &p, 16); - SerialBridgeSerial->write(code); - size -= 2; - codes += 2; - } - } - ResponseCmndDone(); - } - } -} - -void CmndSBaudrate(void) -{ - if (XdrvMailbox.payload >= 300) { - XdrvMailbox.payload /= 300; - Settings.sbaudrate = XdrvMailbox.payload; - SerialBridgeSerial->begin(Settings.sbaudrate * 300); - } - ResponseCmndNumber(Settings.sbaudrate * 300); -} - - - - - -bool Xdrv08(uint8_t function) -{ - bool result = false; - - if (serial_bridge_active) { - switch (function) { - case FUNC_LOOP: - if (SerialBridgeSerial) { SerialBridgeInput(); } - break; - case FUNC_PRE_INIT: - SerialBridgeInit(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kSerialBridgeCommands, SerialBridgeCommand); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_09_timers.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_09_timers.ino" -#ifdef USE_TIMERS -# 39 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_09_timers.ino" -#define XDRV_09 9 - -const char kTimerCommands[] PROGMEM = "|" - D_CMND_TIMER "|" D_CMND_TIMERS -#ifdef USE_SUNRISE - "|" D_CMND_LATITUDE "|" D_CMND_LONGITUDE -#endif - ; - -void (* const TimerCommand[])(void) PROGMEM = { - &CmndTimer, &CmndTimers -#ifdef USE_SUNRISE - , &CmndLatitude, &CmndLongitude -#endif - }; - -uint16_t timer_last_minute = 60; -int8_t timer_window[MAX_TIMERS] = { 0 }; - -#ifdef USE_SUNRISE -# 67 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_09_timers.ino" -const float pi2 = TWO_PI; -const float pi = PI; -const float RAD = DEG_TO_RAD; - -float JulianischesDatum(void) -{ - - int Gregor; - int Jahr = RtcTime.year; - int Monat = RtcTime.month; - int Tag = RtcTime.day_of_month; - - if (Monat <= 2) { - Monat += 12; - Jahr -= 1; - } - Gregor = (Jahr / 400) - (Jahr / 100) + (Jahr / 4); - return 2400000.5f + 365.0f*Jahr - 679004.0f + Gregor + (int)(30.6001f * (Monat +1)) + Tag + 0.5f; -} - -float InPi(float x) -{ - int n = (int)(x / pi2); - x = x - n*pi2; - if (x < 0) x += pi2; - return x; -} - -float eps(float T) -{ - - return RAD * (23.43929111f + (-46.8150f*T - 0.00059f*T*T + 0.001813f*T*T*T)/3600.0f); -} - -float BerechneZeitgleichung(float *DK,float T) -{ - float RA_Mittel = 18.71506921f + 2400.0513369f*T +(2.5862e-5f - 1.72e-9f*T)*T*T; - float M = InPi(pi2 * (0.993133f + 99.997361f*T)); - float L = InPi(pi2 * (0.7859453f + M/pi2 + (6893.0f*sinf(M)+72.0f*sinf(2.0f*M)+6191.2f*T) / 1296.0e3f)); - float e = eps(T); - float RA = atanf(tanf(L)*cosf(e)); - if (RA < 0.0) RA += pi; - if (L > pi) RA += pi; - RA = 24.0*RA/pi2; - *DK = asinf(sinf(e)*sinf(L)); - - RA_Mittel = 24.0f * InPi(pi2*RA_Mittel/24.0f)/pi2; - float dRA = RA_Mittel - RA; - if (dRA < -12.0f) dRA += 24.0f; - if (dRA > 12.0f) dRA -= 24.0f; - dRA = dRA * 1.0027379f; - return dRA; -} - -void DuskTillDawn(uint8_t *hour_up,uint8_t *minute_up, uint8_t *hour_down, uint8_t *minute_down) -{ - float JD2000 = 2451545.0f; - float JD = JulianischesDatum(); - float T = (JD - JD2000) / 36525.0f; - float DK; - - - - - - - - float h = SUNRISE_DAWN_ANGLE *RAD; - float B = (((float)Settings.latitude)/1000000) * RAD; - float GeographischeLaenge = ((float)Settings.longitude)/1000000; - - - - float Zeitzone = ((float)Rtc.time_timezone) / 60; - float Zeitgleichung = BerechneZeitgleichung(&DK, T); - float Zeitdifferenz = 12.0f*acosf((sinf(h) - sinf(B)*sinf(DK)) / (cosf(B)*cosf(DK)))/pi; - float AufgangOrtszeit = 12.0f - Zeitdifferenz - Zeitgleichung; - float UntergangOrtszeit = 12.0f + Zeitdifferenz - Zeitgleichung; - float AufgangWeltzeit = AufgangOrtszeit - GeographischeLaenge / 15.0f; - float UntergangWeltzeit = UntergangOrtszeit - GeographischeLaenge / 15.0f; - float Aufgang = AufgangWeltzeit + Zeitzone; - if (Aufgang < 0.0f) { - Aufgang += 24.0f; - } else { - if (Aufgang >= 24.0f) Aufgang -= 24.0f; - } - float Untergang = UntergangWeltzeit + Zeitzone; - if (Untergang < 0.0f) { - Untergang += 24.0f; - } else { - if (Untergang >= 24.0f) Untergang -= 24.0f; - } - int AufgangMinuten = (int)(60.0f*(Aufgang - (int)Aufgang)+0.5f); - int AufgangStunden = (int)Aufgang; - if (AufgangMinuten >= 60.0f) { - AufgangMinuten -= 60.0f; - AufgangStunden++; - } else { - if (AufgangMinuten < 0.0f) { - AufgangMinuten += 60.0f; - AufgangStunden--; - if (AufgangStunden < 0.0f) AufgangStunden += 24.0f; - } - } - int UntergangMinuten = (int)(60.0f*(Untergang - (int)Untergang)+0.5f); - int UntergangStunden = (int)Untergang; - if (UntergangMinuten >= 60.0f) { - UntergangMinuten -= 60.0f; - UntergangStunden++; - } else { - if (UntergangMinuten<0) { - UntergangMinuten += 60.0f; - UntergangStunden--; - if (UntergangStunden < 0.0f) UntergangStunden += 24.0f; - } - } - *hour_up = AufgangStunden; - *minute_up = AufgangMinuten; - *hour_down = UntergangStunden; - *minute_down = UntergangMinuten; -} - -void ApplyTimerOffsets(Timer *duskdawn) -{ - uint8_t hour[2]; - uint8_t minute[2]; - Timer stored = (Timer)*duskdawn; - - - DuskTillDawn(&hour[0], &minute[0], &hour[1], &minute[1]); - uint8_t mode = (duskdawn->mode -1) &1; - duskdawn->time = (hour[mode] *60) + minute[mode]; - - - uint16_t timeBuffer; - if ((uint16_t)stored.time > 719) { - - timeBuffer = (uint16_t)stored.time - 720; - - if (timeBuffer > (uint16_t)duskdawn->time) { - timeBuffer = 1440 - (timeBuffer - (uint16_t)duskdawn->time); - duskdawn->days = duskdawn->days >> 1; - duskdawn->days |= (stored.days << 6); - } else { - timeBuffer = (uint16_t)duskdawn->time - timeBuffer; - } - } else { - - timeBuffer = (uint16_t)duskdawn->time + (uint16_t)stored.time; - - if (timeBuffer > 1440) { - timeBuffer -= 1440; - duskdawn->days = duskdawn->days << 1; - duskdawn->days |= (stored.days >> 6); - } - } - duskdawn->time = timeBuffer; -} - -String GetSun(uint32_t dawn) -{ - char stime[6]; - - uint8_t hour[2]; - uint8_t minute[2]; - - DuskTillDawn(&hour[0], &minute[0], &hour[1], &minute[1]); - dawn &= 1; - snprintf_P(stime, sizeof(stime), PSTR("%02d:%02d"), hour[dawn], minute[dawn]); - return String(stime); -} - -uint16_t SunMinutes(uint32_t dawn) -{ - uint8_t hour[2]; - uint8_t minute[2]; - - DuskTillDawn(&hour[0], &minute[0], &hour[1], &minute[1]); - dawn &= 1; - return (hour[dawn] *60) + minute[dawn]; -} - -#endif - - - -void TimerSetRandomWindow(uint32_t index) -{ - timer_window[index] = 0; - if (Settings.timer[index].window) { - timer_window[index] = (random(0, (Settings.timer[index].window << 1) +1)) - Settings.timer[index].window; - } -} - -void TimerSetRandomWindows(void) -{ - for (uint32_t i = 0; i < MAX_TIMERS; i++) { TimerSetRandomWindow(i); } -} - -void TimerEverySecond(void) -{ - if (RtcTime.valid) { - if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second) { TimerSetRandomWindows(); } - if (Settings.flag3.timers_enable && (uptime > 60) && (RtcTime.minute != timer_last_minute)) { - timer_last_minute = RtcTime.minute; - int32_t time = (RtcTime.hour *60) + RtcTime.minute; - uint8_t days = 1 << (RtcTime.day_of_week -1); - - for (uint32_t i = 0; i < MAX_TIMERS; i++) { - - Timer xtimer = Settings.timer[i]; -#ifdef USE_SUNRISE - if ((1 == xtimer.mode) || (2 == xtimer.mode)) { - ApplyTimerOffsets(&xtimer); - } -#endif - if (xtimer.arm) { - int32_t set_time = xtimer.time + timer_window[i]; - if (set_time < 0) { - set_time = abs(timer_window[i]); - } - if (set_time > 1439) { - set_time = xtimer.time - abs(timer_window[i]); - } - if (set_time > 1439) { set_time = 1439; } - - DEBUG_DRIVER_LOG(PSTR("TIM: Timer %d, Time %d, Window %d, SetTime %d"), i +1, xtimer.time, timer_window[i], set_time); - - if (time == set_time) { - if (xtimer.days & days) { - Settings.timer[i].arm = xtimer.repeat; -#if defined(USE_RULES) || defined(USE_SCRIPT) - if (POWER_BLINK == xtimer.power) { - Response_P(PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1); - XdrvRulesProcess(); - } else -#endif - if (devices_present) { ExecuteCommandPower(xtimer.device +1, xtimer.power, SRC_TIMER); } - } - } - } - } - } - } -} - -void PrepShowTimer(uint32_t index) -{ - Timer xtimer = Settings.timer[index -1]; - - char days[8] = { 0 }; - for (uint32_t i = 0; i < 7; i++) { - uint8_t mask = 1 << i; - snprintf(days, sizeof(days), "%s%d", days, ((xtimer.days & mask) > 0)); - } - - char soutput[80]; - soutput[0] = '\0'; - if (devices_present) { - snprintf_P(soutput, sizeof(soutput), PSTR(",\"" D_JSON_TIMER_OUTPUT "\":%d"), xtimer.device +1); - } -#ifdef USE_SUNRISE - char sign[2] = { 0 }; - int16_t hour = xtimer.time / 60; - if ((1 == xtimer.mode) || (2 == xtimer.mode)) { - if (hour > 11) { - hour -= 12; - sign[0] = '-'; - } - } - ResponseAppend_P(PSTR("\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_MODE "\":%d,\"" D_JSON_TIMER_TIME "\":\"%s%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), - index, xtimer.arm, xtimer.mode, sign, hour, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); -#else - ResponseAppend_P(PSTR("\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_TIME "\":\"%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), - index, xtimer.arm, xtimer.time / 60, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); -#endif -} - - - - - -void CmndTimer(void) -{ - uint32_t index = XdrvMailbox.index; - if ((index > 0) && (index <= MAX_TIMERS)) { - uint32_t error = 0; - if (XdrvMailbox.data_len) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAX_TIMERS)) { - if (XdrvMailbox.payload == 0) { - Settings.timer[index -1].data = 0; - } else { - Settings.timer[index -1].data = Settings.timer[XdrvMailbox.payload -1].data; - } - } else { - -#if defined(USE_RULES)==0 && defined(USE_SCRIPT)==0 - if (devices_present) { -#endif - char dataBufUc[XdrvMailbox.data_len]; - UpperCase(dataBufUc, XdrvMailbox.data); - StaticJsonBuffer<256> jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(dataBufUc); - if (!root.success()) { - Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_INVALID_JSON "\"}"), index); - error = 1; - } - else { - char parm_uc[10]; - index--; - if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_ARM))].success()) { - Settings.timer[index].arm = (root[parm_uc] != 0); - } -#ifdef USE_SUNRISE - if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_MODE))].success()) { - Settings.timer[index].mode = (uint8_t)root[parm_uc] & 0x03; - } -#endif - if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_TIME))].success()) { - uint16_t itime = 0; - int8_t value = 0; - uint8_t sign = 0; - char time_str[10]; - - strlcpy(time_str, root[parm_uc], sizeof(time_str)); - const char *substr = strtok(time_str, ":"); - if (substr != nullptr) { - if (strchr(substr, '-')) { - sign = 1; - substr++; - } - value = atoi(substr); - if (sign) { value += 12; } - if (value > 23) { value = 23; } - itime = value * 60; - substr = strtok(nullptr, ":"); - if (substr != nullptr) { - value = atoi(substr); - if (value < 0) { value = 0; } - if (value > 59) { value = 59; } - itime += value; - } - } - Settings.timer[index].time = itime; - } - if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_WINDOW))].success()) { - Settings.timer[index].window = (uint8_t)root[parm_uc] & 0x0F; - TimerSetRandomWindow(index); - } - if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_DAYS))].success()) { - - Settings.timer[index].days = 0; - const char *tday = root[parm_uc]; - uint8_t i = 0; - char ch = *tday++; - while ((ch != '\0') && (i < 7)) { - if (ch == '-') { ch = '0'; } - uint8_t mask = 1 << i++; - Settings.timer[index].days |= (ch == '0') ? 0 : mask; - ch = *tday++; - } - } - if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_REPEAT))].success()) { - Settings.timer[index].repeat = (root[parm_uc] != 0); - } - if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_OUTPUT))].success()) { - uint8_t device = ((uint8_t)root[parm_uc] -1) & 0x0F; - Settings.timer[index].device = (device < devices_present) ? device : 0; - } - if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_ACTION))].success()) { - uint8_t action = (uint8_t)root[parm_uc] & 0x03; - Settings.timer[index].power = (devices_present) ? action : 3; - } - - index++; - } - -#if defined(USE_RULES)==0 && defined(USE_SCRIPT)==0 - } else { - Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_TIMER_NO_DEVICE "\"}"), index); - error = 1; - } -#endif - } - } - if (!error) { - Response_P(PSTR("{")); - PrepShowTimer(index); - ResponseJsonEnd(); - } - } -} - -void CmndTimers(void) -{ - if (XdrvMailbox.data_len) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.flag3.timers_enable = XdrvMailbox.payload; - } - if (XdrvMailbox.payload == 2) { - Settings.flag3.timers_enable = !Settings.flag3.timers_enable; - } - } - - ResponseCmndStateText(Settings.flag3.timers_enable); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command); - - uint32_t jsflg = 0; - uint32_t lines = 1; - for (uint32_t i = 0; i < MAX_TIMERS; i++) { - if (!jsflg) { - Response_P(PSTR("{\"" D_CMND_TIMERS "%d\":{"), lines++); - } else { - ResponseAppend_P(PSTR(",")); - } - jsflg++; - PrepShowTimer(i +1); - if (jsflg > 3) { - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_TIMERS)); - jsflg = 0; - } - } - mqtt_data[0] = '\0'; -} - -#ifdef USE_SUNRISE -void CmndLongitude(void) -{ - if (XdrvMailbox.data_len) { - Settings.longitude = (int)(CharToFloat(XdrvMailbox.data) *1000000); - } - char lbuff[33]; - dtostrfd(((float)Settings.longitude) /1000000, 6, lbuff); - ResponseCmndChar(lbuff); -} - -void CmndLatitude(void) -{ - if (XdrvMailbox.data_len) { - Settings.latitude = (int)(CharToFloat(XdrvMailbox.data) *1000000); - } - char lbuff[33]; - dtostrfd(((float)Settings.latitude) /1000000, 6, lbuff); - ResponseCmndChar(lbuff); -} -#endif - - - - - -#ifdef USE_WEBSERVER -#ifdef USE_TIMERS_WEB - -#define WEB_HANDLE_TIMER "tm" - -const char S_CONFIGURE_TIMER[] PROGMEM = D_CONFIGURE_TIMER; - -const char HTTP_BTN_MENU_TIMER[] PROGMEM = - "

"; - -const char HTTP_TIMER_SCRIPT1[] PROGMEM = - "var pt=[],ct=99;" - "function ce(i,q){" - "var o=document.createElement('option');" - "o.textContent=i;" - "q.appendChild(o);" - "}"; -#ifdef USE_SUNRISE -const char HTTP_TIMER_SCRIPT2[] PROGMEM = - "function gt(){" - "var m,p,q;" - "m=qs('input[name=\"rd\"]:checked').value;" - "p=pt[ct]&0x7FF;" - "if(m==0){" - "so(0);" - "q=Math.floor(p/60);if(q<10){q='0'+q;}qs('#ho').value=q;" - "q=p%%60;if(q<10){q='0'+q;}qs('#mi').value=q;" - "}" - "if((m==1)||(m==2)){" - "so(1);" - "q=Math.floor(p/60);" - "if(q>=12){q-=12;qs('#dr').selectedIndex=1;}" - "else{qs('#dr').selectedIndex=0;}" - "if(q<10){q='0'+q;}qs('#ho').value=q;" - "q=p%%60;if(q<10){q='0'+q;}qs('#mi').value=q;" - "}" - "}" - "function so(b){" - "o=qs('#ho');" - "e=o.childElementCount;" - "if(b==1){" - "qs('#dr').disabled='';" - "if(e>12){for(i=12;i<=23;i++){o.removeChild(o.lastElementChild);}}" - "}else{" - "qs('#dr').disabled='disabled';" - "if(e<23){for(i=12;i<=23;i++){ce(i,o);}}" - "}" - "}"; -#endif -const char HTTP_TIMER_SCRIPT3[] PROGMEM = - "function st(){" - "var i,l,m,n,p,s;" - "m=0;s=0;" - "n=1<<31;if(eb('a0').checked){s|=n;}" - "n=1<<15;if(eb('r0').checked){s|=n;}" - "for(i=0;i<7;i++){n=1<<(16+i);if(eb('w'+i).checked){s|=n;}}" -#ifdef USE_SUNRISE - "m=qs('input[name=\"rd\"]:checked').value;" - "s|=(qs('input[name=\"rd\"]:checked').value<<29);" -#endif - "if(%d>0){" - "i=qs('#d1').selectedIndex;if(i>=0){s|=(i<<23);}" - "s|=(qs('#p1').selectedIndex<<27);" - "}else{" - "s|=3<<27;" - "}" - "l=((qs('#ho').selectedIndex*60)+qs('#mi').selectedIndex)&0x7FF;" - "if(m==0){s|=l;}" -#ifdef USE_SUNRISE - "if((m==1)||(m==2)){" - "if(qs('#dr').selectedIndex>0){l+=720;}" - "s|=l&0x7FF;" - "}" -#endif - "s|=((qs('#mw').selectedIndex)&0x0F)<<11;" - "pt[ct]=s;" - "eb('t0').value=pt.join();" - "}"; -const char HTTP_TIMER_SCRIPT4[] PROGMEM = - "function ot(t,e){" - "var i,n,o,p,q,s;" - "if(ct<99){st();}" - "ct=t;" - "o=document.getElementsByClassName('tl');" - "for(i=0;i>29)&3;eb('b'+p).checked=1;" - "gt();" -#else - "p=s&0x7FF;" - "q=Math.floor(p/60);if(q<10){q='0'+q;}qs('#ho').value=q;" - "q=p%%60;if(q<10){q='0'+q;}qs('#mi').value=q;" -#endif - "q=(s>>11)&0xF;if(q<10){q='0'+q;}qs('#mw').value=q;" - "for(i=0;i<7;i++){p=(s>>(16+i))&1;eb('w'+i).checked=p;}" - "if(%d>0){" - "p=(s>>23)&0xF;qs('#d1').value=p+1;" - "p=(s>>27)&3;qs('#p1').selectedIndex=p;" - "}" - "p=(s>>15)&1;eb('r0').checked=p;" - "p=(s>>31)&1;eb('a0').checked=p;" - "}"; -const char HTTP_TIMER_SCRIPT5[] PROGMEM = - "function it(){" - "var b,i,o,s;" - "pt=eb('t0').value.split(',').map(Number);" - "s='';" - "for(i=0;i<%d;i++){" - "b='';" - "if(0==i){b=\" id='dP'\";}" - "s+=\"\"" - "}" - "eb('bt').innerHTML=s;" - "if(%d>0){" - "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" - "o=qs('#p1');ce('" D_OFF "',o);ce('" D_ON "',o);ce('" D_TOGGLE "',o);" -#if defined(USE_RULES) || defined(USE_SCRIPT) - "ce('" D_RULE "',o);" -#else - "ce('" D_BLINK "',o);" -#endif - "}else{" - "eb('oa').innerHTML=\"" D_TIMER_ACTION " " D_RULE "\";" - "}"; -const char HTTP_TIMER_SCRIPT6[] PROGMEM = -#ifdef USE_SUNRISE - "o=qs('#dr');ce('+',o);ce('-',o);" -#endif - "o=qs('#ho');for(i=0;i<=23;i++){ce((i<10)?('0'+i):i,o);}" - "o=qs('#mi');for(i=0;i<=59;i++){ce((i<10)?('0'+i):i,o);}" - "o=qs('#mw');for(i=0;i<=15;i++){ce((i<10)?('0'+i):i,o);}" - "o=qs('#d1');for(i=0;i<%d;i++){ce(i+1,o);}" - "var a='" D_DAY3LIST "';" - "s='';for(i=0;i<7;i++){s+=\"\"+a.substring(i*3,(i*3)+3)+\" \"}" - "eb('ds').innerHTML=s;" - "eb('dP').click();" - "}" - "wl(it);"; -const char HTTP_TIMER_STYLE[] PROGMEM = - ".tl{float:left;border-radius:0;border:1px solid #%06x;padding:1px;width:6.25%%;}"; -const char HTTP_FORM_TIMER1[] PROGMEM = - "
" - " " D_TIMER_PARAMETERS " " - "
" - "
" D_TIMER_ENABLE "


" - "



" - "

" - "
" - "" D_TIMER_ARM " " - "" D_TIMER_REPEAT "" - "

" - "
"; -#ifdef USE_SUNRISE -const char HTTP_FORM_TIMER3[] PROGMEM = - "
" - "" D_TIMER_TIME "
" - "" D_SUNRISE " (%s)
" - "" D_SUNSET " (%s)
" - "
" - "

" - "" - " "; -#else -const char HTTP_FORM_TIMER3[] PROGMEM = - "" D_TIMER_TIME " "; -#endif -const char HTTP_FORM_TIMER4[] PROGMEM = - "" - " " D_HOUR_MINUTE_SEPARATOR " " - "" - " +/- " - "" - "

" - "
"; - -void HandleTimerConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TIMER); - - if (WebServer->hasArg("save")) { - TimerSaveSettings(); - HandleConfiguration(); - return; - } - - WSContentStart_P(S_CONFIGURE_TIMER); - WSContentSend_P(HTTP_TIMER_SCRIPT1); -#ifdef USE_SUNRISE - WSContentSend_P(HTTP_TIMER_SCRIPT2); -#endif - WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present); - WSContentSend_P(HTTP_TIMER_SCRIPT4, WebColor(COL_TIMER_TAB_BACKGROUND), WebColor(COL_TIMER_TAB_TEXT), WebColor(COL_FORM), WebColor(COL_TEXT), devices_present); - WSContentSend_P(HTTP_TIMER_SCRIPT5, MAX_TIMERS, devices_present); - WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present); - WSContentSendStyle_P(HTTP_TIMER_STYLE, WebColor(COL_FORM)); - WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); - for (uint32_t i = 0; i < MAX_TIMERS; i++) { - WSContentSend_P(PSTR("%s%u"), (i > 0) ? "," : "", Settings.timer[i].data); - } - WSContentSend_P(HTTP_FORM_TIMER2); -#ifdef USE_SUNRISE - WSContentSend_P(HTTP_FORM_TIMER3, 100 + (strlen(D_SUNSET) *12), GetSun(0).c_str(), GetSun(1).c_str()); -#else - WSContentSend_P(HTTP_FORM_TIMER3); -#endif - WSContentSend_P(HTTP_FORM_TIMER4); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void TimerSaveSettings(void) -{ - char tmp[MAX_TIMERS *12]; - Timer timer; - - Settings.flag3.timers_enable = WebServer->hasArg("e0"); - WebGetArg("t0", tmp, sizeof(tmp)); - char *p = tmp; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_TIMERS " %d"), Settings.flag3.timers_enable); - for (uint32_t i = 0; i < MAX_TIMERS; i++) { - timer.data = strtol(p, &p, 10); - p++; - if (timer.time < 1440) { - bool flag = (timer.window != Settings.timer[i].window); - Settings.timer[i].data = timer.data; - if (flag) TimerSetRandomWindow(i); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s,0x%08X"), log_data, Settings.timer[i].data); - } - AddLog(LOG_LEVEL_DEBUG); -} -#endif -#endif - - - - - -bool Xdrv09(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_PRE_INIT: - TimerSetRandomWindows(); - break; -#ifdef USE_WEBSERVER -#ifdef USE_TIMERS_WEB - case FUNC_WEB_ADD_BUTTON: -#if defined(USE_RULES) || defined(USE_SCRIPT) - WSContentSend_P(HTTP_BTN_MENU_TIMER); -#else - if (devices_present) { WSContentSend_P(HTTP_BTN_MENU_TIMER); } -#endif - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_TIMER, HandleTimerConfiguration); - break; -#endif -#endif - case FUNC_EVERY_SECOND: - TimerEverySecond(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kTimerCommands, TimerCommand); - break; - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -#ifdef USE_RULES -#ifndef USE_SCRIPT -# 67 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -#define XDRV_10 10 - -#define D_CMND_RULE "Rule" -#define D_CMND_RULETIMER "RuleTimer" -#define D_CMND_EVENT "Event" -#define D_CMND_VAR "Var" -#define D_CMND_MEM "Mem" -#define D_CMND_ADD "Add" -#define D_CMND_SUB "Sub" -#define D_CMND_MULT "Mult" -#define D_CMND_SCALE "Scale" -#define D_CMND_CALC_RESOLUTION "CalcRes" -#define D_CMND_SUBSCRIBE "Subscribe" -#define D_CMND_UNSUBSCRIBE "Unsubscribe" -#define D_CMND_IF "If" - -#define D_JSON_INITIATED "Initiated" - -#define COMPARE_OPERATOR_NONE -1 -#define COMPARE_OPERATOR_EQUAL 0 -#define COMPARE_OPERATOR_BIGGER 1 -#define COMPARE_OPERATOR_SMALLER 2 -#define COMPARE_OPERATOR_EXACT_DIVISION 3 -#define COMPARE_OPERATOR_NUMBER_EQUAL 4 -#define COMPARE_OPERATOR_NOT_EQUAL 5 -#define COMPARE_OPERATOR_BIGGER_EQUAL 6 -#define COMPARE_OPERATOR_SMALLER_EQUAL 7 -#define MAXIMUM_COMPARE_OPERATOR COMPARE_OPERATOR_SMALLER_EQUAL -const char kCompareOperators[] PROGMEM = "=\0>\0<\0|\0==!=>=<="; - -#ifdef USE_EXPRESSION - #include - - const char kExpressionOperators[] PROGMEM = "+-*/%^"; - #define EXPRESSION_OPERATOR_ADD 0 - #define EXPRESSION_OPERATOR_SUBTRACT 1 - #define EXPRESSION_OPERATOR_MULTIPLY 2 - #define EXPRESSION_OPERATOR_DIVIDEDBY 3 - #define EXPRESSION_OPERATOR_MODULO 4 - #define EXPRESSION_OPERATOR_POWER 5 - - const uint8_t kExpressionOperatorsPriorities[] PROGMEM = {1, 1, 2, 2, 3, 4}; - #define MAX_EXPRESSION_OPERATOR_PRIORITY 4 - - - #define LOGIC_OPERATOR_AND 1 - #define LOGIC_OPERATOR_OR 2 - - #define IF_BLOCK_INVALID -1 - #define IF_BLOCK_ANY 0 - #define IF_BLOCK_ELSEIF 1 - #define IF_BLOCK_ELSE 2 - #define IF_BLOCK_ENDIF 3 -#endif - -const char kRulesCommands[] PROGMEM = "|" - D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM "|" - D_CMND_ADD "|" D_CMND_SUB "|" D_CMND_MULT "|" D_CMND_SCALE "|" D_CMND_CALC_RESOLUTION -#ifdef SUPPORT_MQTT_EVENT - "|" D_CMND_SUBSCRIBE "|" D_CMND_UNSUBSCRIBE -#endif -#ifdef SUPPORT_IF_STATEMENT - "|" D_CMND_IF -#endif - ; - -void (* const RulesCommand[])(void) PROGMEM = { - &CmndRule, &CmndRuleTimer, &CmndEvent, &CmndVariable, &CmndMemory, - &CmndAddition, &CmndSubtract, &CmndMultiply, &CmndScale, &CmndCalcResolution -#ifdef SUPPORT_MQTT_EVENT - , &CmndSubscribe, &CmndUnsubscribe -#endif -#ifdef SUPPORT_IF_STATEMENT - , &CmndIf -#endif - }; - -#ifdef SUPPORT_MQTT_EVENT - #include - typedef struct { - String Event; - String Topic; - String Key; - } MQTT_Subscription; - LinkedList subscriptions; -#endif - -struct RULES { - String event_value; - unsigned long timer[MAX_RULE_TIMERS] = { 0 }; - uint32_t triggers[MAX_RULE_SETS] = { 0 }; - uint8_t trigger_count[MAX_RULE_SETS] = { 0 }; - - long new_power = -1; - long old_power = -1; - long old_dimm = -1; - - uint16_t last_minute = 60; - uint16_t vars_event = 0; - uint8_t mems_event = 0; - bool teleperiod = false; - - char event_data[100]; -} Rules; - -char rules_vars[MAX_RULE_VARS][33] = {{ 0 }}; - -#if (MAX_RULE_VARS>16) -#error MAX_RULE_VARS is bigger than 16 -#endif -#if (MAX_RULE_MEMS>5) -#error MAX_RULE_MEMS is bigger than 5 -#endif - - - -bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) -{ - - - - - bool match = false; - char stemp[10]; - - - int pos = rule.indexOf('#'); - if (pos == -1) { return false; } - - String rule_task = rule.substring(0, pos); - if (Rules.teleperiod) { - int ppos = rule_task.indexOf("TELE-"); - if (ppos == -1) { return false; } - rule_task = rule.substring(5, pos); - } - - String rule_expr = rule.substring(pos +1); - String rule_name, rule_param; - int8_t compareOperator = parseCompareExpression(rule_expr, rule_name, rule_param); - - char rule_svalue[CMDSZ] = { 0 }; - float rule_value = 0; - if (compareOperator != COMPARE_OPERATOR_NONE) { - for (uint32_t i = 0; i < MAX_RULE_VARS; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%%VAR%d%%"), i +1); - if (rule_param.startsWith(stemp)) { - rule_param = rules_vars[i]; - break; - } - } - for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1); - if (rule_param.startsWith(stemp)) { - rule_param = Settings.mems[i]; - break; - } - } - snprintf_P(stemp, sizeof(stemp), PSTR("%%TIME%%")); - if (rule_param.startsWith(stemp)) { - rule_param = String(MinutesPastMidnight()); - } - snprintf_P(stemp, sizeof(stemp), PSTR("%%UPTIME%%")); - if (rule_param.startsWith(stemp)) { - rule_param = String(MinutesUptime()); - } - snprintf_P(stemp, sizeof(stemp), PSTR("%%TIMESTAMP%%")); - if (rule_param.startsWith(stemp)) { - rule_param = GetDateAndTime(DT_LOCAL).c_str(); - } -#if defined(USE_TIMERS) && defined(USE_SUNRISE) - snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNRISE%%")); - if (rule_param.startsWith(stemp)) { - rule_param = String(SunMinutes(0)); - } - snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNSET%%")); - if (rule_param.startsWith(stemp)) { - rule_param = String(SunMinutes(1)); - } -#endif - rule_param.toUpperCase(); - strlcpy(rule_svalue, rule_param.c_str(), sizeof(rule_svalue)); - - int temp_value = GetStateNumber(rule_svalue); - if (temp_value > -1) { - rule_value = temp_value; - } else { - rule_value = CharToFloat((char*)rule_svalue); - } - } - - - StaticJsonBuffer<1024> jsonBuf; - JsonObject &root = jsonBuf.parseObject(event); - if (!root.success()) { return false; } - - const char* str_value; - if ((pos = rule_name.indexOf("[")) > 0) { - int rule_name_idx = rule_name.substring(pos +1).toInt(); - if ((rule_name_idx < 1) || (rule_name_idx > 6)) { - rule_name_idx = 1; - } - rule_name = rule_name.substring(0, pos); - str_value = root[rule_task][rule_name][rule_name_idx -1]; - } else { - str_value = root[rule_task][rule_name]; - } - - - - - if (!root[rule_task][rule_name].success()) { return false; } - - - Rules.event_value = str_value; - - - float value = 0; - if (str_value) { - value = CharToFloat((char*)str_value); - int int_value = int(value); - int int_rule_value = int(rule_value); - switch (compareOperator) { - case COMPARE_OPERATOR_EXACT_DIVISION: - match = (int_rule_value && (int_value % int_rule_value) == 0); - break; - case COMPARE_OPERATOR_EQUAL: - match = (!strcasecmp(str_value, rule_svalue)); - break; - case COMPARE_OPERATOR_BIGGER: - match = (value > rule_value); - break; - case COMPARE_OPERATOR_SMALLER: - match = (value < rule_value); - break; - case COMPARE_OPERATOR_NUMBER_EQUAL: - match = (value == rule_value); - break; - case COMPARE_OPERATOR_NOT_EQUAL: - match = (value != rule_value); - break; - case COMPARE_OPERATOR_BIGGER_EQUAL: - match = (value >= rule_value); - break; - case COMPARE_OPERATOR_SMALLER_EQUAL: - match = (value <= rule_value); - break; - default: - match = true; - } - } else match = true; - - if (bitRead(Settings.rule_once, rule_set)) { - if (match) { - if (!bitRead(Rules.triggers[rule_set], Rules.trigger_count[rule_set])) { - bitSet(Rules.triggers[rule_set], Rules.trigger_count[rule_set]); - } else { - match = false; - } - } else { - bitClear(Rules.triggers[rule_set], Rules.trigger_count[rule_set]); - } - } - - return match; -} -# 348 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -int8_t parseCompareExpression(String &expr, String &leftExpr, String &rightExpr) -{ - char compare_operator[3]; - int8_t compare = COMPARE_OPERATOR_NONE; - leftExpr = expr; - int position; - for (int8_t i = MAXIMUM_COMPARE_OPERATOR; i >= 0; i--) { - snprintf_P(compare_operator, sizeof(compare_operator), kCompareOperators + (i *2)); - if ((position = expr.indexOf(compare_operator)) > 0) { - compare = i; - leftExpr = expr.substring(0, position); - leftExpr.trim(); - rightExpr = expr.substring(position + strlen(compare_operator)); - rightExpr.trim(); - break; - } - } - return compare; -} - - - -bool RuleSetProcess(uint8_t rule_set, String &event_saved) -{ - bool serviced = false; - char stemp[10]; - - delay(0); - - - - String rules = Settings.rules[rule_set]; - - Rules.trigger_count[rule_set] = 0; - int plen = 0; - int plen2 = 0; - bool stop_all_rules = false; - while (true) { - rules = rules.substring(plen); - rules.trim(); - if (!rules.length()) { return serviced; } - - String rule = rules; - rule.toUpperCase(); - if (!rule.startsWith("ON ")) { return serviced; } - - int pevt = rule.indexOf(" DO "); - if (pevt == -1) { return serviced; } - String event_trigger = rule.substring(3, pevt); - - plen = rule.indexOf(" ENDON"); - plen2 = rule.indexOf(" BREAK"); - if ((plen == -1) && (plen2 == -1)) { return serviced; } - - if (plen == -1) { plen = 9999; } - if (plen2 == -1) { plen2 = 9999; } - plen = tmin(plen, plen2); - if (plen == plen2) { stop_all_rules = true; } - - String commands = rules.substring(pevt +4, plen); - plen += 6; - Rules.event_value = ""; - String event = event_saved; - - - - if (RulesRuleMatch(rule_set, event, event_trigger)) { - commands.trim(); - String ucommand = commands; - ucommand.toUpperCase(); - - if (ucommand.indexOf("EVENT ") != -1) { commands = "backlog " + commands; } - commands.replace(F("%value%"), Rules.event_value); - for (uint32_t i = 0; i < MAX_RULE_VARS; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%%var%d%%"), i +1); - commands.replace(stemp, rules_vars[i]); - } - for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%%mem%d%%"), i +1); - commands.replace(stemp, Settings.mems[i]); - } - commands.replace(F("%time%"), String(MinutesPastMidnight())); - commands.replace(F("%uptime%"), String(MinutesUptime())); - commands.replace(F("%timestamp%"), GetDateAndTime(DT_LOCAL).c_str()); -#if defined(USE_TIMERS) && defined(USE_SUNRISE) - commands.replace(F("%sunrise%"), String(SunMinutes(0))); - commands.replace(F("%sunset%"), String(SunMinutes(1))); -#endif - - char command[commands.length() +1]; - strlcpy(command, commands.c_str(), sizeof(command)); - - AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: %s performs \"%s\""), event_trigger.c_str(), command); - - - -#ifdef SUPPORT_IF_STATEMENT - char *pCmd = command; - RulesPreprocessCommand(pCmd); -#endif - ExecuteCommand(command, SRC_RULE); - serviced = true; - if (stop_all_rules) { return serviced; } - } - Rules.trigger_count[rule_set]++; - } - return serviced; -} - - - -bool RulesProcessEvent(char *json_event) -{ - bool serviced = false; - -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("RulesProcessEvent")); -#endif - - String event_saved = json_event; - - - - char *p = strchr(json_event, ':'); - if ((p != NULL) && !(strchr(++p, ':'))) { - event_saved.replace(F(":"), F(":{\"Data\":")); - event_saved += F("}"); - - } - event_saved.toUpperCase(); - - - - for (uint32_t i = 0; i < MAX_RULE_SETS; i++) { - if (strlen(Settings.rules[i]) && bitRead(Settings.rule_enabled, i)) { - if (RuleSetProcess(i, event_saved)) { serviced = true; } - } - } - return serviced; -} - -bool RulesProcess(void) -{ - return RulesProcessEvent(mqtt_data); -} - -void RulesInit(void) -{ - rules_flag.data = 0; - for (uint32_t i = 0; i < MAX_RULE_SETS; i++) { - if (Settings.rules[i][0] == '\0') { - bitWrite(Settings.rule_enabled, i, 0); - bitWrite(Settings.rule_once, i, 0); - } - } - Rules.teleperiod = false; -} - -void RulesEvery50ms(void) -{ - if (Settings.rule_enabled) { - char json_event[120]; - - if (-1 == Rules.new_power) { Rules.new_power = power; } - if (Rules.new_power != Rules.old_power) { - if (Rules.old_power != -1) { - for (uint32_t i = 0; i < devices_present; i++) { - uint8_t new_state = (Rules.new_power >> i) &1; - if (new_state != ((Rules.old_power >> i) &1)) { - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Power%d\":{\"State\":%d}}"), i +1, new_state); - RulesProcessEvent(json_event); - } - } - } else { - - for (uint32_t i = 0; i < devices_present; i++) { - uint8_t new_state = (Rules.new_power >> i) &1; - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Power%d\":{\"Boot\":%d}}"), i +1, new_state); - RulesProcessEvent(json_event); - } - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { -#ifdef USE_TM1638 - if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { -#else - if (pin[GPIO_SWT1 +i] < 99) { -#endif - bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); - snprintf_P(json_event, sizeof(json_event), PSTR("{\"" D_JSON_SWITCH "%d\":{\"Boot\":%d}}"), i +1, (swm ^ SwitchLastState(i))); - RulesProcessEvent(json_event); - } - } - } - Rules.old_power = Rules.new_power; - } - else if (Rules.old_dimm != Settings.light_dimmer) { - if (Rules.old_dimm != -1) { - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Dimmer\":{\"State\":%d}}"), Settings.light_dimmer); - } else { - - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Dimmer\":{\"Boot\":%d}}"), Settings.light_dimmer); - } - RulesProcessEvent(json_event); - Rules.old_dimm = Settings.light_dimmer; - } - else if (Rules.event_data[0]) { - char *event; - char *parameter; - event = strtok_r(Rules.event_data, "=", ¶meter); - if (event) { - event = Trim(event); - if (parameter) { - parameter = Trim(parameter); - } else { - parameter = event + strlen(event); - } - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Event\":{\"%s\":\"%s\"}}"), event, parameter); - Rules.event_data[0] ='\0'; - RulesProcessEvent(json_event); - } else { - Rules.event_data[0] ='\0'; - } - } - else if (Rules.vars_event || Rules.mems_event){ - if (Rules.vars_event) { - for (uint32_t i = 0; i < MAX_RULE_VARS; i++) { - if (bitRead(Rules.vars_event, i)) { - bitClear(Rules.vars_event, i); - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Var%d\":{\"State\":%s}}"), i+1, rules_vars[i]); - RulesProcessEvent(json_event); - break; - } - } - } - if (Rules.mems_event) { - for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { - if (bitRead(Rules.mems_event, i)) { - bitClear(Rules.mems_event, i); - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Mem%d\":{\"State\":%s}}"), i+1, Settings.mems[i]); - RulesProcessEvent(json_event); - break; - } - } - } - } - else if (rules_flag.data) { - uint16_t mask = 1; - for (uint32_t i = 0; i < MAX_RULES_FLAG; i++) { - if (rules_flag.data & mask) { - rules_flag.data ^= mask; - json_event[0] = '\0'; - switch (i) { - case 0: strncpy_P(json_event, PSTR("{\"System\":{\"Boot\":1}}"), sizeof(json_event)); break; - case 1: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Initialized\":%d}}"), MinutesPastMidnight()); break; - case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), MinutesPastMidnight()); break; - case 3: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Connected\":1}}"), sizeof(json_event)); break; - case 4: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Disconnected\":1}}"), sizeof(json_event)); break; - case 5: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Connected\":1}}"), sizeof(json_event)); break; - case 6: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Disconnected\":1}}"), sizeof(json_event)); break; - case 7: strncpy_P(json_event, PSTR("{\"HTTP\":{\"Initialized\":1}}"), sizeof(json_event)); break; - } - if (json_event[0]) { - RulesProcessEvent(json_event); - break; - } - } - mask <<= 1; - } - } - } -} - -uint8_t rules_xsns_index = 0; - -void RulesEvery100ms(void) -{ - if (Settings.rule_enabled && (uptime > 4)) { - mqtt_data[0] = '\0'; - int tele_period_save = tele_period; - tele_period = 2; - XsnsNextCall(FUNC_JSON_APPEND, rules_xsns_index); - tele_period = tele_period_save; - if (strlen(mqtt_data)) { - mqtt_data[0] = '{'; - ResponseJsonEnd(); - RulesProcess(); - } - } -} - -void RulesEverySecond(void) -{ - if (Settings.rule_enabled) { - char json_event[120]; - - if (RtcTime.valid) { - if ((uptime > 60) && (RtcTime.minute != Rules.last_minute)) { - Rules.last_minute = RtcTime.minute; - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Minute\":%d}}"), MinutesPastMidnight()); - RulesProcessEvent(json_event); - } - } - for (uint32_t i = 0; i < MAX_RULE_TIMERS; i++) { - if (Rules.timer[i] != 0L) { - if (TimeReached(Rules.timer[i])) { - Rules.timer[i] = 0L; - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Rules\":{\"Timer\":%d}}"), i +1); - RulesProcessEvent(json_event); - } - } - } - } -} - -void RulesSaveBeforeRestart(void) -{ - if (Settings.rule_enabled) { - char json_event[32]; - - strncpy_P(json_event, PSTR("{\"System\":{\"Save\":1}}"), sizeof(json_event)); - RulesProcessEvent(json_event); - } -} - -void RulesSetPower(void) -{ - Rules.new_power = XdrvMailbox.index; -} - -void RulesTeleperiod(void) -{ - Rules.teleperiod = true; - RulesProcess(); - Rules.teleperiod = false; -} - -#ifdef SUPPORT_MQTT_EVENT -# 695 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -bool RulesMqttData(void) -{ - bool serviced = false; - if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) { - return false; - } - String sTopic = XdrvMailbox.topic; - String sData = XdrvMailbox.data; - - MQTT_Subscription event_item; - - for (uint32_t index = 0; index < subscriptions.size(); index++) { - event_item = subscriptions.get(index); - - - if (sTopic.startsWith(event_item.Topic)) { - - serviced = true; - String value; - if (event_item.Key.length() == 0) { - value = sData; - } else { - StaticJsonBuffer<500> jsonBuf; - JsonObject& jsonData = jsonBuf.parseObject(sData); - String key1 = event_item.Key; - String key2; - if (!jsonData.success()) break; - int dot; - if ((dot = key1.indexOf('.')) > 0) { - key2 = key1.substring(dot+1); - key1 = key1.substring(0, dot); - if (!jsonData[key1][key2].success()) break; - value = (const char *)jsonData[key1][key2]; - } else { - if (!jsonData[key1].success()) break; - value = (const char *)jsonData[key1]; - } - } - value.trim(); - - snprintf_P(Rules.event_data, sizeof(Rules.event_data), PSTR("%s=%s"), event_item.Event.c_str(), value.c_str()); - } - } - return serviced; -} -# 757 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -void CmndSubscribe(void) -{ - MQTT_Subscription subscription_item; - String events; - if (XdrvMailbox.data_len > 0) { - char parameters[XdrvMailbox.data_len+1]; - memcpy(parameters, XdrvMailbox.data, XdrvMailbox.data_len); - parameters[XdrvMailbox.data_len] = '\0'; - String event_name, topic, key; - - char * pos = strtok(parameters, ","); - if (pos) { - event_name = Trim(pos); - pos = strtok(nullptr, ","); - if (pos) { - topic = Trim(pos); - pos = strtok(nullptr, ","); - if (pos) { - key = Trim(pos); - } - } - } - - event_name.toUpperCase(); - if (event_name.length() > 0 && topic.length() > 0) { - - for (uint32_t index=0; index < subscriptions.size(); index++) { - if (subscriptions.get(index).Event.equals(event_name)) { - - String stopic = subscriptions.get(index).Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - subscriptions.remove(index); - break; - } - } - - if (!topic.endsWith("#")) { - if (topic.endsWith("/")) { - topic.concat("#"); - } else { - topic.concat("/#"); - } - } - - - subscription_item.Event = event_name; - subscription_item.Topic = topic.substring(0, topic.length() - 2); - subscription_item.Key = key; - subscriptions.add(subscription_item); - - MqttSubscribe(topic.c_str()); - events.concat(event_name + "," + topic - + (key.length()>0 ? "," : "") - + key); - } else { - events = D_JSON_WRONG_PARAMETERS; - } - } else { - - for (uint32_t index=0; index < subscriptions.size(); index++) { - subscription_item = subscriptions.get(index); - events.concat(subscription_item.Event + "," + subscription_item.Topic - + (subscription_item.Key.length()>0 ? "," : "") - + subscription_item.Key + "; "); - } - } - ResponseCmndChar(events.c_str()); -} -# 837 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -void CmndUnsubscribe(void) -{ - MQTT_Subscription subscription_item; - String events; - if (XdrvMailbox.data_len > 0) { - for (uint32_t index = 0; index < subscriptions.size(); index++) { - subscription_item = subscriptions.get(index); - if (subscription_item.Event.equalsIgnoreCase(XdrvMailbox.data)) { - String stopic = subscription_item.Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - events = subscription_item.Event; - subscriptions.remove(index); - break; - } - } - } else { - - String stopic; - while (subscriptions.size() > 0) { - events.concat(subscriptions.get(0).Event + "; "); - stopic = subscriptions.get(0).Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - subscriptions.remove(0); - } - } - ResponseCmndChar(events.c_str()); -} - -#endif - -#ifdef USE_EXPRESSION -# 879 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -char * findClosureBracket(char * pStart) -{ - char * pointer = pStart + 1; - - bool bFindClosures = false; - uint8_t matchClosures = 1; - while (*pointer) - { - if (*pointer == ')') { - matchClosures--; - if (matchClosures == 0) { - bFindClosures = true; - break; - } - } else if (*pointer == '(') { - matchClosures++; - } - pointer++; - } - if (bFindClosures) { - return pointer; - } else { - return nullptr; - } -} -# 918 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -bool findNextNumber(char * &pNumber, float &value) -{ - bool bSucceed = false; - String sNumber = ""; - while (*pNumber) { - if (isdigit(*pNumber) || (*pNumber == '.')) { - sNumber += *pNumber; - pNumber++; - } else { - break; - } - } - if (sNumber.length() > 0) { - value = CharToFloat(sNumber.c_str()); - bSucceed = true; - } - return bSucceed; -} -# 950 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -bool findNextVariableValue(char * &pVarname, float &value) -{ - bool succeed = true; - value = 0; - String sVarName = ""; - while (*pVarname) { - if (isalpha(*pVarname) || isdigit(*pVarname)) { - sVarName.concat(*pVarname); - pVarname++; - } else { - break; - } - } - sVarName.toUpperCase(); - if (sVarName.startsWith(F("VAR"))) { - int index = sVarName.substring(3).toInt(); - if (index > 0 && index <= MAX_RULE_VARS) { - value = CharToFloat(rules_vars[index -1]); - } - } else if (sVarName.startsWith(F("MEM"))) { - int index = sVarName.substring(3).toInt(); - if (index > 0 && index <= MAX_RULE_MEMS) { - value = CharToFloat(Settings.mems[index -1]); - } - } else if (sVarName.equals(F("TIME"))) { - value = MinutesPastMidnight(); - } else if (sVarName.equals(F("UPTIME"))) { - value = MinutesUptime(); - } else if (sVarName.equals(F("UTCTIME"))) { - value = UtcTime(); - } else if (sVarName.equals(F("LOCALTIME"))) { - value = LocalTime(); -#if defined(USE_TIMERS) && defined(USE_SUNRISE) - } else if (sVarName.equals(F("SUNRISE"))) { - value = SunMinutes(0); - } else if (sVarName.equals(F("SUNSET"))) { - value = SunMinutes(1); -#endif - } else { - succeed = false; - } - - return succeed; -} -# 1012 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -bool findNextObjectValue(char * &pointer, float &value) -{ - bool bSucceed = false; - while (*pointer) - { - if (isspace(*pointer)) { - pointer++; - continue; - } - if (isdigit(*pointer)) { - bSucceed = findNextNumber(pointer, value); - break; - } else if (isalpha(*pointer)) { - bSucceed = findNextVariableValue(pointer, value); - break; - } else if (*pointer == '(') { - char * closureBracket = findClosureBracket(pointer); - if (closureBracket != nullptr) { - value = evaluateExpression(pointer+1, closureBracket - pointer - 2); - pointer = closureBracket + 1; - bSucceed = true; - } - break; - } else { - break; - } - } - return bSucceed; -} -# 1056 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -bool findNextOperator(char * &pointer, int8_t &op) -{ - bool bSucceed = false; - while (*pointer) - { - if (isspace(*pointer)) { - pointer++; - continue; - } - if (char *pch = strchr(kExpressionOperators, *pointer)) { - op = (int8_t)(pch - kExpressionOperators); - pointer++; - bSucceed = true; - } - break; - } - return bSucceed; -} -# 1087 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -float calculateTwoValues(float v1, float v2, uint8_t op) -{ - switch (op) - { - case EXPRESSION_OPERATOR_ADD: - return v1 + v2; - case EXPRESSION_OPERATOR_SUBTRACT: - return v1 - v2; - case EXPRESSION_OPERATOR_MULTIPLY: - return v1 * v2; - case EXPRESSION_OPERATOR_DIVIDEDBY: - return (0 == v2) ? 0 : (v1 / v2); - case EXPRESSION_OPERATOR_MODULO: - return (0 == v2) ? 0 : (int(v1) % int(v2)); - case EXPRESSION_OPERATOR_POWER: - return FastPrecisePow(v1, v2); - } - return 0; -} -# 1140 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -float evaluateExpression(const char * expression, unsigned int len) -{ - char expbuf[len + 1]; - memcpy(expbuf, expression, len); - expbuf[len] = '\0'; - char * scan_pointer = expbuf; - - LinkedList object_values; - LinkedList operators; - int8_t op; - float va; - - if (findNextObjectValue(scan_pointer, va)) { - object_values.add(va); - } else { - return 0; - } - while (*scan_pointer) - { - if (findNextOperator(scan_pointer, op) - && *scan_pointer - && findNextObjectValue(scan_pointer, va)) - { - operators.add(op); - object_values.add(va); - } else { - - break; - } - } - - - - for (int32_t priority = MAX_EXPRESSION_OPERATOR_PRIORITY; priority>0; priority--) { - int index = 0; - while (index < operators.size()) { - if (priority == kExpressionOperatorsPriorities[(operators.get(index))]) { - - va = calculateTwoValues(object_values.get(index), object_values.remove(index + 1), operators.remove(index)); - - object_values.set(index, va); - } else { - index++; - } - } - } - return object_values.get(0); -} -#endif - -#ifdef SUPPORT_IF_STATEMENT -void CmndIf() -{ - if (XdrvMailbox.data_len > 0) { - char parameters[XdrvMailbox.data_len+1]; - memcpy(parameters, XdrvMailbox.data, XdrvMailbox.data_len); - parameters[XdrvMailbox.data_len] = '\0'; - ProcessIfStatement(parameters); - } - ResponseCmndDone(); -} -# 1214 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -bool evaluateComparisonExpression(const char *expression, int len) -{ - bool bResult = true; - char expbuf[len + 1]; - memcpy(expbuf, expression, len); - expbuf[len] = '\0'; - String compare_expression = expbuf; - String leftExpr, rightExpr; - int8_t compareOp = parseCompareExpression(compare_expression, leftExpr, rightExpr); - - double leftValue = evaluateExpression(leftExpr.c_str(), leftExpr.length()); - double rightValue = evaluateExpression(rightExpr.c_str(), rightExpr.length()); - switch (compareOp) { - case COMPARE_OPERATOR_EXACT_DIVISION: - bResult = (rightValue != 0 && leftValue == int(leftValue) - && rightValue == int(rightValue) && (int(leftValue) % int(rightValue)) == 0); - break; - case COMPARE_OPERATOR_EQUAL: - bResult = leftExpr.equalsIgnoreCase(rightExpr); - break; - case COMPARE_OPERATOR_BIGGER: - bResult = (leftValue > rightValue); - break; - case COMPARE_OPERATOR_SMALLER: - bResult = (leftValue < rightValue); - break; - case COMPARE_OPERATOR_NUMBER_EQUAL: - bResult = (leftValue == rightValue); - break; - case COMPARE_OPERATOR_NOT_EQUAL: - bResult = (leftValue != rightValue); - break; - case COMPARE_OPERATOR_BIGGER_EQUAL: - bResult = (leftValue >= rightValue); - break; - case COMPARE_OPERATOR_SMALLER_EQUAL: - bResult = (leftValue <= rightValue); - break; - } - return bResult; -} -# 1270 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -bool findNextLogicOperator(char * &pointer, int8_t &op) -{ - bool bSucceed = false; - while (*pointer && isspace(*pointer)) { - - pointer++; - } - if (*pointer) { - if (strncasecmp_P(pointer, PSTR("AND "), 4) == 0) { - op = LOGIC_OPERATOR_AND; - pointer += 4; - bSucceed = true; - } else if (strncasecmp_P(pointer, PSTR("OR "), 3) == 0) { - op = LOGIC_OPERATOR_OR; - pointer += 3; - bSucceed = true; - } - } - return bSucceed; -} -# 1307 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -bool findNextLogicObjectValue(char * &pointer, bool &value) -{ - bool bSucceed = false; - while (*pointer && isspace(*pointer)) { - - pointer++; - } - char * pExpr = pointer; - while (*pointer) { - if (isalpha(*pointer) - && (strncasecmp_P(pointer, PSTR("AND "), 4) == 0 - || strncasecmp_P(pointer, PSTR("OR "), 3) == 0)) - { - value = evaluateComparisonExpression(pExpr, pointer - pExpr); - bSucceed = true; - break; - } else if (*pointer == '(') { - char * closureBracket = findClosureBracket(pointer); - if (closureBracket != nullptr) { - value = evaluateLogicalExpression(pointer+1, closureBracket - pointer - 2); - pointer = closureBracket + 1; - bSucceed = true; - } - break; - } - pointer++; - } - if (!bSucceed && pointer > pExpr) { - - value = evaluateComparisonExpression(pExpr, pointer - pExpr); - bSucceed = true; - } - return bSucceed; -} -# 1356 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -bool evaluateLogicalExpression(const char * expression, int len) -{ - bool bResult = false; - - char expbuff[len + 1]; - memcpy(expbuff, expression, len); - expbuff[len] = '\0'; - - - - char * pointer = expbuff; - LinkedList values; - LinkedList logicOperators; - - bool bValue; - if (findNextLogicObjectValue(pointer, bValue)) { - values.add(bValue); - } else { - return false; - } - int8_t op; - while (*pointer) { - if (findNextLogicOperator(pointer, op) - && (*pointer) && findNextLogicObjectValue(pointer, bValue)) - { - logicOperators.add(op); - values.add(bValue); - } else { - break; - } - } - - int index = 0; - while (index < logicOperators.size()) { - if (logicOperators.get(index) == LOGIC_OPERATOR_AND) { - values.set(index, values.get(index) && values.get(index+1)); - values.remove(index + 1); - logicOperators.remove(index); - } else { - index++; - } - } - - index = 0; - while (index < logicOperators.size()) { - if (logicOperators.get(index) == LOGIC_OPERATOR_OR) { - values.set(index, values.get(index) || values.get(index+1)); - values.remove(index + 1); - logicOperators.remove(index); - } else { - index++; - } - } - return values.get(0); -} -# 1428 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -int8_t findIfBlock(char * &pointer, int &lenWord, int8_t block_type) -{ - int8_t foundBlock = IF_BLOCK_INVALID; - - const char * word; - while (*pointer) { - if (!isalpha(*pointer)) { - pointer++; - continue; - } - word = pointer; - while (*pointer && isalpha(*pointer)) { - pointer++; - } - lenWord = pointer - word; - - if (2 == lenWord && 0 == strncasecmp_P(word, PSTR("IF"), 2)) { - - - if (findIfBlock(pointer, lenWord, IF_BLOCK_ENDIF) != IF_BLOCK_ENDIF) { - - break; - } - } else if ( (IF_BLOCK_ENDIF == block_type || IF_BLOCK_ANY == block_type) - && (5 == lenWord) && (0 == strncasecmp_P(word, PSTR("ENDIF"), 5))) - { - - foundBlock = IF_BLOCK_ENDIF; - break; - } else if ( (IF_BLOCK_ELSEIF == block_type || IF_BLOCK_ANY == block_type) - && (6 == lenWord) && (0 == strncasecmp_P(word, PSTR("ELSEIF"), 6))) - { - - foundBlock = IF_BLOCK_ELSEIF; - break; - } else if ( (IF_BLOCK_ELSE == block_type || IF_BLOCK_ANY == block_type) - && (4 == lenWord) && (0 == strncasecmp_P(word, PSTR("ELSE"), 4))) - { - - foundBlock = IF_BLOCK_ELSE; - break; - } - } - return foundBlock; -} -# 1485 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -void ExecuteCommandBlock(const char * commands, int len) -{ - char cmdbuff[len + 1]; - memcpy(cmdbuff, commands, len); - cmdbuff[len] = '\0'; - - - - char oneCommand[len + 1]; - int insertPosition = 0; - char * pos = cmdbuff; - int lenEndBlock = 0; - while (*pos) { - if (isspace(*pos) || '\x1e' == *pos || ';' == *pos) { - pos++; - continue; - } - if (strncasecmp_P(pos, PSTR("BACKLOG "), 8) == 0) { - - pos += 8; - continue; - } - if (strncasecmp_P(pos, PSTR("IF "), 3) == 0) { - - - char *pEndif = pos + 3; - if (IF_BLOCK_ENDIF != findIfBlock(pEndif, lenEndBlock, IF_BLOCK_ENDIF)) { - - break; - } - - memcpy(oneCommand, pos, pEndif - pos); - oneCommand[pEndif - pos] = '\0'; - pos = pEndif; - } else { - - char *pEndOfCommand = strpbrk(pos, "\x1e;"); - if (NULL == pEndOfCommand) { - pEndOfCommand = pos + strlen(pos); - } - memcpy(oneCommand, pos, pEndOfCommand - pos); - oneCommand[pEndOfCommand - pos] = '\0'; - pos = pEndOfCommand; - } - - - String sCurrentCommand = oneCommand; - sCurrentCommand.trim(); - if (sCurrentCommand.length() > 0 - && backlog.size() < MAX_BACKLOG && !backlog_mutex) - { - - backlog_mutex = true; - backlog.add(insertPosition, sCurrentCommand); - backlog_mutex = false; - insertPosition++; - } - } - return; -} -# 1556 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -void ProcessIfStatement(const char* statements) -{ - String conditionExpression; - int len = strlen(statements); - char statbuff[len + 1]; - memcpy(statbuff, statements, len + 1); - char *pos = statbuff; - int lenEndBlock = 0; - while (true) { - - - while (*pos && *pos != '(') { - pos++; - } - if (0 == *pos) { break; } - char * posEnd = findClosureBracket(pos); - - if (true == evaluateLogicalExpression(pos + 1, posEnd - (pos + 1))) { - - char * cmdBlockStart = posEnd + 1; - char * cmdBlockEnd = cmdBlockStart; - int8_t nextBlock = findIfBlock(cmdBlockEnd, lenEndBlock, IF_BLOCK_ANY); - if (IF_BLOCK_INVALID == nextBlock) { - - break; - } - ExecuteCommandBlock(cmdBlockStart, cmdBlockEnd - cmdBlockStart - lenEndBlock); - pos = cmdBlockEnd; - break; - } else { - pos = posEnd + 1; - int8_t nextBlock = findIfBlock(pos, lenEndBlock, IF_BLOCK_ANY); - if (IF_BLOCK_ELSEIF == nextBlock) { - - continue; - } else if (IF_BLOCK_ELSE == nextBlock) { - - char * cmdBlockEnd = pos; - int8_t nextBlock = findIfBlock(cmdBlockEnd, lenEndBlock, IF_BLOCK_ENDIF); - if (IF_BLOCK_ENDIF != nextBlock) { - - break; - } - ExecuteCommandBlock(pos, cmdBlockEnd - pos - lenEndBlock); - break; - } else { - - break; - } - } - } -} -# 1620 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_rules.ino" -void RulesPreprocessCommand(char *pCommands) -{ - char * cmd = pCommands; - int lenEndBlock = 0; - while (*cmd) { - - if (';' == *cmd || isspace(*cmd)) { - cmd++; - } - else if (strncasecmp_P(cmd, PSTR("IF "), 3) == 0) { - - char * pIfStart = cmd; - char * pIfEnd = pIfStart + 3; - - if (IF_BLOCK_ENDIF == findIfBlock(pIfEnd, lenEndBlock, IF_BLOCK_ENDIF)) { - - cmd = pIfEnd; - - - while (pIfStart < pIfEnd) { - if (';' == *pIfStart) - *pIfStart = '\x1e'; - pIfStart++; - } - } - else { - break; - } - } - else { - while (*cmd && ';' != *cmd) { - cmd++; - } - } - } - return; -} -#endif - - - - - -void CmndRule(void) -{ - uint8_t index = XdrvMailbox.index; - if ((index > 0) && (index <= MAX_RULE_SETS)) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.rules[index -1]))) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10)) { - switch (XdrvMailbox.payload) { - case 0: - case 1: - bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload); - break; - case 2: - bitWrite(Settings.rule_enabled, index -1, bitRead(Settings.rule_enabled, index -1) ^1); - break; - case 4: - case 5: - bitWrite(Settings.rule_once, index -1, XdrvMailbox.payload &1); - break; - case 6: - bitWrite(Settings.rule_once, index -1, bitRead(Settings.rule_once, index -1) ^1); - break; - case 8: - case 9: - bitWrite(Settings.rule_stop, index -1, XdrvMailbox.payload &1); - break; - case 10: - bitWrite(Settings.rule_stop, index -1, bitRead(Settings.rule_stop, index -1) ^1); - break; - } - } else { - int offset = 0; - if ('+' == XdrvMailbox.data[0]) { - offset = strlen(Settings.rules[index -1]); - if (XdrvMailbox.data_len < (sizeof(Settings.rules[index -1]) - offset -1)) { - XdrvMailbox.data[0] = ' '; - } else { - offset = -1; - } - } - if (offset != -1) { - strlcpy(Settings.rules[index -1] + offset, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.rules[index -1])); - } - } - Rules.triggers[index -1] = 0; - } - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"StopOnError\":\"%s\",\"Free\":%d,\"Rules\":\"%s\"}"), - XdrvMailbox.command, index, GetStateText(bitRead(Settings.rule_enabled, index -1)), GetStateText(bitRead(Settings.rule_once, index -1)), - GetStateText(bitRead(Settings.rule_stop, index -1)), sizeof(Settings.rules[index -1]) - strlen(Settings.rules[index -1]) -1, Settings.rules[index -1]); - } -} - -void CmndRuleTimer(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_TIMERS)) { - if (XdrvMailbox.data_len > 0) { -#ifdef USE_EXPRESSION - float timer_set = evaluateExpression(XdrvMailbox.data, XdrvMailbox.data_len); - Rules.timer[XdrvMailbox.index -1] = (timer_set > 0) ? millis() + (1000 * timer_set) : 0; -#else - Rules.timer[XdrvMailbox.index -1] = (XdrvMailbox.payload > 0) ? millis() + (1000 * XdrvMailbox.payload) : 0; -#endif - } - mqtt_data[0] = '\0'; - for (uint32_t i = 0; i < MAX_RULE_TIMERS; i++) { - ResponseAppend_P(PSTR("%c\"T%d\":%d"), (i) ? ',' : '{', i +1, (Rules.timer[i]) ? (Rules.timer[i] - millis()) / 1000 : 0); - } - ResponseJsonEnd(); - } -} - -void CmndEvent(void) -{ - if (XdrvMailbox.data_len > 0) { - strlcpy(Rules.event_data, XdrvMailbox.data, sizeof(Rules.event_data)); - } - ResponseCmndDone(); -} - -void CmndVariable(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) { - if (!XdrvMailbox.usridx) { - mqtt_data[0] = '\0'; - for (uint32_t i = 0; i < MAX_RULE_VARS; i++) { - ResponseAppend_P(PSTR("%c\"Var%d\":\"%s\""), (i) ? ',' : '{', i +1, rules_vars[i]); - } - ResponseJsonEnd(); - } else { - if (XdrvMailbox.data_len > 0) { -#ifdef USE_EXPRESSION - if (XdrvMailbox.data[0] == '=') { - dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]); - } else { - strlcpy(rules_vars[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(rules_vars[XdrvMailbox.index -1])); - } -#else - strlcpy(rules_vars[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(rules_vars[XdrvMailbox.index -1])); -#endif - bitSet(Rules.vars_event, XdrvMailbox.index -1); - } - ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]); - } - } -} - -void CmndMemory(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_MEMS)) { - if (!XdrvMailbox.usridx) { - mqtt_data[0] = '\0'; - for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { - ResponseAppend_P(PSTR("%c\"Mem%d\":\"%s\""), (i) ? ',' : '{', i +1, Settings.mems[i]); - } - ResponseJsonEnd(); - } else { - if (XdrvMailbox.data_len > 0) { -#ifdef USE_EXPRESSION - if (XdrvMailbox.data[0] == '=') { - dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, Settings.mems[XdrvMailbox.index -1]); - } else { - strlcpy(Settings.mems[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[XdrvMailbox.index -1])); - } -#else - strlcpy(Settings.mems[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[XdrvMailbox.index -1])); -#endif - bitSet(Rules.mems_event, XdrvMailbox.index -1); - } - ResponseCmndIdxChar(Settings.mems[XdrvMailbox.index -1]); - } - } -} - -void CmndCalcResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 7)) { - Settings.flag2.calc_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.calc_resolution); -} - -void CmndAddition(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) { - if (XdrvMailbox.data_len > 0) { - float tempvar = CharToFloat(rules_vars[XdrvMailbox.index -1]) + CharToFloat(XdrvMailbox.data); - dtostrfd(tempvar, Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]); - bitSet(Rules.vars_event, XdrvMailbox.index -1); - } - ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]); - } -} - -void CmndSubtract(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) { - if (XdrvMailbox.data_len > 0) { - float tempvar = CharToFloat(rules_vars[XdrvMailbox.index -1]) - CharToFloat(XdrvMailbox.data); - dtostrfd(tempvar, Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]); - bitSet(Rules.vars_event, XdrvMailbox.index -1); - } - ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]); - } -} - -void CmndMultiply(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) { - if (XdrvMailbox.data_len > 0) { - float tempvar = CharToFloat(rules_vars[XdrvMailbox.index -1]) * CharToFloat(XdrvMailbox.data); - dtostrfd(tempvar, Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]); - bitSet(Rules.vars_event, XdrvMailbox.index -1); - } - ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]); - } -} - -void CmndScale(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) { - if (XdrvMailbox.data_len > 0) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - char sub_string[XdrvMailbox.data_len +1]; - - float valueIN = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 1)); - float fromLow = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)); - float fromHigh = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 3)); - float toLow = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)); - float toHigh = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 5)); - float value = map_double(valueIN, fromLow, fromHigh, toLow, toHigh); - dtostrfd(value, Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]); - bitSet(Rules.vars_event, XdrvMailbox.index -1); - } - } - ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]); - } -} - -float map_double(float x, float in_min, float in_max, float out_min, float out_max) -{ - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; -} - - - - - -bool Xdrv10(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_PRE_INIT: - RulesInit(); - break; - case FUNC_EVERY_50_MSECOND: - RulesEvery50ms(); - break; - case FUNC_EVERY_100_MSECOND: - RulesEvery100ms(); - break; - case FUNC_EVERY_SECOND: - RulesEverySecond(); - break; - case FUNC_SET_POWER: - RulesSetPower(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kRulesCommands, RulesCommand); - break; - case FUNC_RULES_PROCESS: - result = RulesProcess(); - break; - case FUNC_SAVE_BEFORE_RESTART: - RulesSaveBeforeRestart(); - break; -#ifdef SUPPORT_MQTT_EVENT - case FUNC_MQTT_DATA: - result = RulesMqttData(); - break; -#endif - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_scripter.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_scripter.ino" -#ifdef USE_SCRIPT -#ifndef USE_RULES -# 40 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_scripter.ino" -#define XDRV_10 10 - -#define SCRIPT_DEBUG 0 - -#define MAXVARS 50 -#define MAXNVARS 45 -#define MAXSVARS 5 -#define MAXFILT 5 -#define SCRIPT_SVARSIZE 20 -#define SCRIPT_MAXSSIZE 48 -#define SCRIPT_EOL '\n' -#define SCRIPT_FLOAT_PRECISION 2 -#define SCRIPT_MAXPERM (MAX_RULE_MEMS*10)-4/sizeof(float) -#define MAX_SCRIPT_SIZE MAX_RULE_SIZE*MAX_RULE_SETS - - -#define EPOCH_OFFSET 1546300800 - -enum {OPER_EQU=1,OPER_PLS,OPER_MIN,OPER_MUL,OPER_DIV,OPER_PLSEQU,OPER_MINEQU,OPER_MULEQU,OPER_DIVEQU,OPER_EQUEQU,OPER_NOTEQU,OPER_GRTEQU,OPER_LOWEQU,OPER_GRT,OPER_LOW,OPER_PERC,OPER_XOR,OPER_AND,OPER_OR,OPER_ANDEQU,OPER_OREQU,OPER_XOREQU,OPER_PERCEQU}; -enum {SCRIPT_LOGLEVEL=1,SCRIPT_TELEPERIOD}; - -#ifdef USE_SCRIPT_FATFS -#include -#include -#define FAT_SCRIPT_SIZE 4096 -#define FAT_SCRIPT_NAME "script.txt" -#if USE_LONG_FILE_NAMES==1 -#warning ("FATFS long filenames not supported"); -#endif -#if USE_STANDARD_SPI_LIBRARY==0 -#warning ("FATFS standard spi should be used"); -#endif -#endif - -#ifdef SUPPORT_MQTT_EVENT - #include - typedef struct { - String Event; - String Topic; - String Key; - } MQTT_Subscription; - LinkedList subscriptions; -#endif - -#ifdef USE_DISPLAY -#ifdef USE_TOUCH_BUTTONS -#include -extern VButton *buttons[MAXBUTTONS]; -#endif -#endif - -typedef union { - uint8_t data; - struct { - uint8_t is_string : 1; - uint8_t is_permanent : 1; - uint8_t is_timer : 1; - uint8_t is_autoinc : 1; - uint8_t changed : 1; - uint8_t settable : 1; - uint8_t is_filter : 1; - uint8_t constant : 1; - }; -} SCRIPT_TYPE; - -struct T_INDEX { - uint8_t index; - SCRIPT_TYPE bits; -}; - -struct M_FILT { - uint8_t numvals; - uint8_t index; - float maccu; - float rbuff[1]; -}; - -typedef union { - uint8_t data; - struct { - uint8_t nutu8 : 1; - uint8_t nutu7 : 1; - uint8_t nutu6 : 1; - uint8_t nutu5 : 1; - uint8_t nutu4 : 1; - uint8_t nutu3 : 1; - uint8_t is_dir : 1; - uint8_t is_open : 1; - }; -} FILE_FLAGS; - -#define SFS_MAX 4 - -struct SCRIPT_MEM { - float *fvars; - float *s_fvars; - struct T_INDEX *type; - struct M_FILT *mfilt; - char *glob_vnp; - uint8_t *vnp_offset; - char *glob_snp; - char *scriptptr; - char *section_ptr; - char *scriptptr_bu; - char *script_ram; - uint16_t script_size; - uint8_t *script_pram; - uint16_t script_pram_size; - uint8_t numvars; - void *script_mem; - uint16_t script_mem_size; - uint8_t script_dprec; - uint8_t var_not_found; - uint8_t glob_error; - uint8_t max_ssize; - uint8_t script_loglevel; - uint8_t flags; -#ifdef USE_SCRIPT_FATFS - File files[SFS_MAX]; - FILE_FLAGS file_flags[SFS_MAX]; - uint8_t script_sd_found; - char flink[2][14]; -#endif -} glob_script_mem; - - -int16_t last_findex; -uint8_t tasm_cmd_activ=0; -uint8_t fast_script=0; -uint32_t script_lastmillis; - - -char *GetNumericResult(char *lp,uint8_t lastop,float *fp,JsonObject *jo); -char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo); -char *ForceStringVar(char *lp,char *dstr); -void send_download(void); -uint8_t reject(char *name); - -void ScriptEverySecond(void) { - - if (bitRead(Settings.rule_enabled, 0)) { - struct T_INDEX *vtp=glob_script_mem.type; - float delta=(millis()-script_lastmillis)/1000; - script_lastmillis=millis(); - for (uint8_t count=0; count0) { - - *fp-=delta; - if (*fp<0) *fp=0; - } - } - if (vtp[count].bits.is_autoinc) { - - float *fp=&glob_script_mem.fvars[vtp[count].index]; - if (*fp>=0) { - *fp+=delta; - } - } - } - Run_Scripter(">S",2,0); - } -} - -void RulesTeleperiod(void) { - if (bitRead(Settings.rule_enabled, 0) && mqtt_data[0]) Run_Scripter(">T",2, mqtt_data); -} - - -#ifdef USE_24C256 -#ifndef USE_SCRIPT_FATFS - -#include -#define EEPROM_ADDRESS 0x50 - -#define EEP_SCRIPT_SIZE 4095 -static Eeprom24C128_256 eeprom(EEPROM_ADDRESS); - -#define EEP_WRITE(A,B,C) eeprom.writeBytes(A,B,(uint8_t*)C); - -#define EEP_READ(A,B,C) eeprom.readBytes(A,B,(uint8_t*)C); -#endif -#endif - -#define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++; -#define SCRIPT_SKIP_EOL while (*lp==SCRIPT_EOL) lp++; - - -int16_t Init_Scripter(void) { -char *script; - - script=glob_script_mem.script_ram; - - - uint16_t lines=0,nvars=0,svars=0,vars=0; - char *lp=script; - char vnames[MAXVARS*10]; - char *vnames_p=vnames; - char *vnp[MAXVARS]; - char **vnp_p=vnp; - char strings[MAXSVARS*SCRIPT_MAXSSIZE]; - struct M_FILT mfilt[MAXFILT]; - - char *strings_p=strings; - char *snp[MAXSVARS]; - char **snp_p=snp; - uint8_t numperm=0,numflt=0,count; - - glob_script_mem.max_ssize=SCRIPT_SVARSIZE; - glob_script_mem.scriptptr=0; - - if (!*script) return -999; - - float fvalues[MAXVARS]; - struct T_INDEX vtypes[MAXVARS]; - char init=0; - while (1) { - - - SCRIPT_SKIP_SPACES - - if (*lp=='\n' || *lp=='\r') goto next_line; - - if (*lp==';') goto next_line; - if (init) { - - if (*lp=='>') { - init=0; - break; - } - char *op=strchr(lp,'='); - if (op) { - vtypes[vars].bits.data=0; - - if (*lp=='p' && *(lp+1)==':') { - lp+=2; - if (numpermMAXFILT) { - return -6; - } - } else { - vtypes[vars].bits.is_filter=0; - } - *vnp_p++=vnames_p; - while (lpMAXNVARS) { - return -1; - } - if (vtypes[vars].bits.is_filter) { - while (isdigit(*op) || *op=='.' || *op=='-') { - op++; - } - while (*op==' ') op++; - if (isdigit(*op)) { - - uint8_t flen=atoi(op); - mfilt[numflt-1].numvals&=0x80; - mfilt[numflt-1].numvals|=flen&0x7f; - } - } - - } else { - - op++; - *snp_p++=strings_p; - while (*op!='\"') { - if (*op==SCRIPT_EOL) break; - *strings_p++=*op++; - } - *strings_p++=0; - vtypes[vars].bits.is_string=1; - vtypes[vars].index=svars; - svars++; - if (svars>MAXSVARS) { - return -2; - } - } - vars++; - if (vars>MAXVARS) { - return -3; - } - } - } else { - if (!strncmp(lp,">D",2)) { - lp+=2; - SCRIPT_SKIP_SPACES - if (isdigit(*lp)) { - uint8_t ssize=atoi(lp)+1; - if (ssize<10 || ssize>SCRIPT_MAXSSIZE) ssize=SCRIPT_MAXSSIZE; - glob_script_mem.max_ssize=ssize; - } - init=1; - } - } - - next_line: - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - - uint16_t fsize=0; - for (count=0; countnumvals=mfilt[count].numvals; - mp+=sizeof(struct M_FILT)+((mfilt[count].numvals&0x7f)-1)*sizeof(float); - } - - glob_script_mem.numvars=vars; - glob_script_mem.script_dprec=SCRIPT_FLOAT_PRECISION; - glob_script_mem.script_loglevel=LOG_LEVEL_INFO; - - -#if SCRIPT_DEBUG>2 - struct T_INDEX *dvtp=glob_script_mem.type; - for (uint8_t count=0; count0 - ClaimSerial(); - SetSerialBaudrate(9600); -#endif - - - glob_script_mem.scriptptr=lp-1; - glob_script_mem.scriptptr_bu=glob_script_mem.scriptptr; - return 0; - -} - -#ifdef USE_LIGHT -#ifdef USE_WS2812 -void ws2812_set_array(float *array ,uint8_t len) { - - Ws2812ForceSuspend(); - for (uint8_t cnt=0;cntSettings.light_pixels) break; - uint32_t col=array[cnt]; - Ws2812SetColor(cnt+1,col>>16,col>>8,col,0); - } - Ws2812ForceUpdate(); -} -#endif -#endif - -#define NUM_RES 0xfe -#define STR_RES 0xfd -#define VAR_NV 0xff - -#define NTYPE 0 -#define STYPE 0x80 - -#define FLT_MAX 99999999 - -float median_array(float *array,uint8_t len) { - uint8_t ind[len]; - uint8_t mind=0,index=0,flg; - float min=FLT_MAX; - - for (uint8_t hcnt=0; hcntnumvals&0x7f; - return mflp->rbuff; - } - mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); - } - return 0; -} - - -float Get_MFVal(uint8_t index,uint8_t bind) { - uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; - for (uint8_t count=0; countnumvals&0x7f; - if (!bind) { - return mflp->index; - } - if (bind<1 || bind>maxind) bind=maxind; - return mflp->rbuff[bind-1]; - } - mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); - } - return 0; -} - -void Set_MFVal(uint8_t index,uint8_t bind,float val) { - uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; - for (uint8_t count=0; countnumvals&0x7f; - if (!bind) { - mflp->index=val; - } else { - if (bind<1 || bind>maxind) bind=maxind; - mflp->rbuff[bind-1]=val; - } - return; - } - mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); - } -} - - -float Get_MFilter(uint8_t index) { - uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; - for (uint8_t count=0; countnumvals&0x80) { - - return mflp->maccu/(mflp->numvals&0x7f); - } else { - - return median_array(mflp->rbuff,mflp->numvals); - } - } - mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); - } - return 0; -} - -void Set_MFilter(uint8_t index, float invar) { - uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; - for (uint8_t count=0; countnumvals&0x80) { - - mflp->maccu-=mflp->rbuff[mflp->index]; - mflp->maccu+=invar; - mflp->rbuff[mflp->index]=invar; - mflp->index++; - if (mflp->index>=(mflp->numvals&0x7f)) mflp->index=0; - } else { - - mflp->rbuff[mflp->index]=invar; - mflp->index++; - if (mflp->index>=mflp->numvals) mflp->index=0; - } - break; - } - mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); - } -} - -#define MEDIAN_SIZE 5 -#define MEDIAN_FILTER_NUM 2 - -struct MEDIAN_FILTER { -float buffer[MEDIAN_SIZE]; -int8_t index; -} script_mf[MEDIAN_FILTER_NUM]; - -float DoMedian5(uint8_t index, float in) { - - if (index>=MEDIAN_FILTER_NUM) index=0; - - struct MEDIAN_FILTER* mf=&script_mf[index]; - mf->buffer[mf->index]=in; - mf->index++; - if (mf->index>=MEDIAN_SIZE) mf->index=0; - return median_array(mf->buffer,MEDIAN_SIZE); -} - -#ifdef USE_LIGHT - -uint32_t HSVToRGB(uint16_t hue, uint8_t saturation, uint8_t value) { -float r = 0, g = 0, b = 0; -struct HSV { - float H; - float S; - float V; -} hsv; - -hsv.H=hue; -hsv.S=(float)saturation/100.0; -hsv.V=(float)value/100.0; - -if (hsv.S == 0) { - r = hsv.V; - g = hsv.V; - b = hsv.V; - } else { - int i; - float f, p, q, t; - - if (hsv.H == 360) - hsv.H = 0; - else - hsv.H = hsv.H / 60; - - i = (int)trunc(hsv.H); - f = hsv.H - i; - - p = hsv.V * (1.0 - hsv.S); - q = hsv.V * (1.0 - (hsv.S * f)); - t = hsv.V * (1.0 - (hsv.S * (1.0 - f))); - - switch (i) - { - case 0: - r = hsv.V; - g = t; - b = p; - break; - - case 1: - r = q; - g = hsv.V; - b = p; - break; - - case 2: - r = p; - g = hsv.V; - b = t; - break; - - case 3: - r = p; - g = q; - b = hsv.V; - break; - - case 4: - r = t; - g = p; - b = hsv.V; - break; - - default: - r = hsv.V; - g = p; - b = q; - break; - } - - } - - uint8_t ir,ig,ib; - ir=r*255; - ig=g*255; - ib=b*255; - - uint32_t rgb=(ir<<16)|(ig<<8)|ib; - return rgb; -} -#endif - - - - -char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,JsonObject *jo) { - uint16_t count,len=0; - uint8_t nres=0; - char vname[32]; - float fvar=0; - tind->index=0; - tind->bits.data=0; - - if (isdigit(*lp) || (*lp=='-' && isdigit(*(lp+1))) || *lp=='.') { - - if (fp) { - if (*lp=='0' && *(lp+1)=='x') { - lp+=2; - *fp=strtol(lp,0,16); - } else { - *fp=CharToFloat(lp); - } - } - if (*lp=='-') lp++; - while (isdigit(*lp) || *lp=='.') { - if (*lp==0 || *lp==SCRIPT_EOL) break; - lp++; - } - tind->bits.constant=1; - tind->bits.is_string=0; - *vtype=NUM_RES; - return lp; - } - if (*lp=='"') { - lp++; - while (*lp!='"') { - if (*lp==0 || *lp==SCRIPT_EOL) break; - uint8_t iob=*lp; - if (iob=='\\') { - lp++; - if (*lp=='t') { - iob='\t'; - } else if (*lp=='n') { - iob='\n'; - } else if (*lp=='r') { - iob='\r'; - } else if (*lp=='\\') { - iob='\\'; - } else { - lp--; - } - if (sp) *sp++=iob; - } else { - if (sp) *sp++=iob; - } - lp++; - } - if (sp) *sp=0; - *vtype=STR_RES; - tind->bits.constant=1; - tind->bits.is_string=1; - return lp+1; - } - - if (*lp=='-') { - - nres=1; - lp++; - } - - const char *term="\n\r ])=+-/*%>index=VAR_NV; - glob_script_mem.var_not_found=1; - return lp; - } - - struct T_INDEX *vtp=glob_script_mem.type; - char dvnam[32]; - strcpy (dvnam,vname); - uint8_t olen=len; - last_findex=-1; - char *ja=strchr(dvnam,'['); - if (ja) { - *ja=0; - ja++; - olen=strlen(dvnam); - } - for (count=0; countindex=count; - if (vtp[count].bits.is_string==0) { - *vtype=NTYPE|index; - if (vtp[count].bits.is_filter) { - if (ja) { - lp+=olen+1; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - last_findex=fvar; - fvar=Get_MFVal(index,fvar); - len=1; - } else { - fvar=Get_MFilter(index); - } - } else { - fvar=glob_script_mem.fvars[index]; - } - if (nres) fvar=-fvar; - if (fp) *fp=fvar; - } else { - *vtype=STYPE|index; - if (sp) strlcpy(sp,glob_script_mem.glob_snp+(index*glob_script_mem.max_ssize),SCRIPT_MAXSSIZE); - } - return lp+len; - } - } - } - - if (jo) { - - const char* str_value; - uint8_t aindex; - String vn; - char *ja=strchr(vname,'['); - if (ja) { - - *ja=0; - ja++; - - float fvar; - GetNumericResult(ja,OPER_EQU,&fvar,0); - aindex=fvar; - if (aindex<1 || aindex>6) aindex=1; - aindex--; - } - if (jo->success()) { - char *subtype=strchr(vname,'#'); - char *subtype2; - if (subtype) { - *subtype=0; - subtype++; - subtype2=strchr(subtype,'#'); - if (subtype2) { - *subtype2=0; - *subtype2++; - } - } - vn=vname; - str_value = (*jo)[vn]; - if ((*jo)[vn].success()) { - if (subtype) { - JsonObject &jobj1=(*jo)[vn]; - if (jobj1.success()) { - vn=subtype; - jo=&jobj1; - str_value = (*jo)[vn]; - if ((*jo)[vn].success()) { - - if (subtype2) { - JsonObject &jobj2=(*jo)[vn]; - if ((*jo)[vn].success()) { - vn=subtype2; - jo=&jobj2; - str_value = (*jo)[vn]; - if ((*jo)[vn].success()) { - goto skip; - } else { - goto chknext; - } - } else { - goto chknext; - } - } - - goto skip; - } - } else { - goto chknext; - } - } - skip: - if (ja) { - - str_value = (*jo)[vn][aindex]; - } - if (str_value && *str_value) { - if ((*jo).is(vn)) { - if (!strncmp(str_value,"ON",2)) { - if (fp) *fp=1; - } else if (!strncmp(str_value,"OFF",3)) { - if (fp) *fp=0; - } else { - *vtype=STR_RES; - tind->bits.constant=1; - tind->bits.is_string=1; - if (sp) strlcpy(sp,str_value,SCRIPT_MAXSSIZE); - return lp+len; - } - } else { - if (fp) { - if (!strncmp(vn.c_str(),"Epoch",5)) { - *fp=atoi(str_value)-(uint32_t)EPOCH_OFFSET; - } else { - *fp=CharToFloat((char*)str_value); - } - } - *vtype=NUM_RES; - tind->bits.constant=1; - tind->bits.is_string=0; - return lp+len; - } - } - } - } - } - -chknext: - switch (vname[0]) { - case 'b': - if (!strncmp(vname,"boot",4)) { - if (rules_flag.system_boot) { - rules_flag.system_boot=0; - fvar=1; - } - goto exit; - } - break; - case 'c': - if (!strncmp(vname,"chg[",4)) { - - struct T_INDEX ind; - uint8_t vtype; - isvar(vname+4,&vtype,&ind,0,0,0); - if (!ind.bits.constant) { - uint8_t index=glob_script_mem.type[ind.index].index; - if (glob_script_mem.fvars[index]!=glob_script_mem.s_fvars[index]) { - - glob_script_mem.s_fvars[index]=glob_script_mem.fvars[index]; - fvar=1; - len++; - goto exit; - } else { - fvar=0; - len++; - goto exit; - } - } - } - break; - case 'd': - if (!strncmp(vname,"day",3)) { - fvar=RtcTime.day_of_month; - goto exit; - } - break; - case 'e': - if (!strncmp(vname,"epoch",5)) { - fvar=UtcTime()-(uint32_t)EPOCH_OFFSET; - goto exit; - } - break; -#ifdef USE_SCRIPT_FATFS - case 'f': - if (!strncmp(vname,"fo(",3)) { - lp+=3; - char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,0); - while (*lp==' ') lp++; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - uint8_t mode=fvar; - fvar=-1; - for (uint8_t cnt=0;cnt=SFS_MAX) ind=SFS_MAX-1; - glob_script_mem.files[ind].close(); - glob_script_mem.file_flags[ind].is_open=0; - fvar=0; - lp++; - len=0; - goto exit; - } - if (!strncmp(vname,"ff(",3)) { - lp+=3; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - uint8_t ind=fvar; - if (ind>=SFS_MAX) ind=SFS_MAX-1; - glob_script_mem.files[ind].flush(); - fvar=0; - lp++; - len=0; - goto exit; - } - if (!strncmp(vname,"fw(",3)) { - lp+=3; - char str[SCRIPT_MAXSSIZE]; - lp=ForceStringVar(lp,str); - while (*lp==' ') lp++; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - uint8_t ind=fvar; - if (ind>=SFS_MAX) ind=SFS_MAX-1; - if (glob_script_mem.file_flags[ind].is_open) { - fvar=glob_script_mem.files[ind].print(str); - } else { - fvar=0; - } - lp++; - len=0; - goto exit; - } - if (!strncmp(vname,"fr(",3)) { - lp+=3; - struct T_INDEX ind; - uint8_t vtype; - uint8_t sindex=0; - lp=isvar(lp,&vtype,&ind,0,0,0); - if (vtype!=VAR_NV) { - - if ((vtype&STYPE)==0) { - - fvar=0; - goto exit; - } else { - - sindex=glob_script_mem.type[ind.index].index; - } - } else { - - fvar=0; - goto exit; - } - while (*lp==' ') lp++; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - uint8_t find=fvar; - if (find>=SFS_MAX) find=SFS_MAX-1; - uint8_t index=0; - char str[glob_script_mem.max_ssize+1]; - char *cp=str; - if (glob_script_mem.file_flags[find].is_open) { - if (glob_script_mem.file_flags[find].is_dir) { - while (true) { - File entry=glob_script_mem.files[find].openNextFile(); - if (entry) { - if (!reject((char*)entry.name())) { - strcpy(str,entry.name()); - entry.close(); - break; - } - } else { - *cp=0; - break; - } - entry.close(); - } - index=strlen(str); - } else { - while (glob_script_mem.files[find].available()) { - uint8_t buf[1]; - glob_script_mem.files[find].read(buf,1); - if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { - break; - } else { - *cp++=buf[0]; - index++; - if (index>=glob_script_mem.max_ssize-1) break; - } - } - *cp=0; - } - } else { - strcpy(str,"file error"); - } - lp++; - strlcpy(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); - fvar=index; - len=0; - goto exit; - } - if (!strncmp(vname,"fd(",3)) { - lp+=3; - char str[glob_script_mem.max_ssize+1]; - lp=GetStringResult(lp,OPER_EQU,str,0); - SD.remove(str); - lp++; - len=0; - goto exit; - } -#ifdef USE_SCRIPT_FATFS_EXT - if (!strncmp(vname,"fe(",3)) { - lp+=3; - char str[glob_script_mem.max_ssize+1]; - lp=GetStringResult(lp,OPER_EQU,str,0); - - File ef=SD.open(str); - if (ef) { - uint16_t fsiz=ef.size(); - if (fsiz<2048) { - char *script=(char*)calloc(fsiz+16,1); - if (script) { - ef.read((uint8_t*)script,fsiz); - execute_script(script); - free(script); - fvar=1; - } - } - ef.close(); - } - lp++; - len=0; - goto exit; - } - if (!strncmp(vname,"fmd(",4)) { - lp+=4; - char str[glob_script_mem.max_ssize+1]; - lp=GetStringResult(lp,OPER_EQU,str,0); - fvar=SD.mkdir(str); - lp++; - len=0; - goto exit; - } - if (!strncmp(vname,"frd(",4)) { - lp+=4; - char str[glob_script_mem.max_ssize+1]; - lp=GetStringResult(lp,OPER_EQU,str,0); - fvar=SD.rmdir(str); - lp++; - len=0; - goto exit; - } - if (!strncmp(vname,"fx(",3)) { - lp+=3; - char str[glob_script_mem.max_ssize+1]; - lp=GetStringResult(lp,OPER_EQU,str,0); - if (SD.exists(str)) fvar=1; - else fvar=0; - lp++; - len=0; - goto exit; - } -#endif - if (!strncmp(vname,"fl1(",4) || !strncmp(vname,"fl2(",4) ) { - uint8_t lknum=*(lp+2)&3; - lp+=4; - char str[glob_script_mem.max_ssize+1]; - lp=GetStringResult(lp,OPER_EQU,str,0); - if (lknum<1 || lknum>2) lknum=1; - strlcpy(glob_script_mem.flink[lknum-1],str,14); - lp++; - fvar=0; - len=0; - goto exit; - } - if (!strncmp(vname,"fsm",3)) { - fvar=glob_script_mem.script_sd_found; - - goto exit; - } - break; - -#endif - case 'g': - if (!strncmp(vname,"gtmp",4)) { - fvar=global_temperature; - goto exit; - } - if (!strncmp(vname,"ghum",4)) { - fvar=global_humidity; - goto exit; - } - if (!strncmp(vname,"gprs",4)) { - fvar=global_pressure; - goto exit; - } - if (!strncmp(vname,"gtopic",6)) { - if (sp) strlcpy(sp,Settings.mqtt_grptopic,glob_script_mem.max_ssize); - goto strexit; - } - break; - case 'h': - if (!strncmp(vname,"hours",5)) { - fvar=RtcTime.hour; - goto exit; - } - if (!strncmp(vname,"heap",4)) { - fvar=ESP.getFreeHeap(); - goto exit; - } - if (!strncmp(vname,"hn(",3)) { - lp=GetNumericResult(lp+3,OPER_EQU,&fvar,0); - if (fvar<0 || fvar>255) fvar=0; - lp++; - len=0; - if (sp) { - sprintf(sp,"%02x",(uint8_t)fvar); - } - goto strexit; - } - if (!strncmp(vname,"hx(",3)) { - lp=GetNumericResult(lp+3,OPER_EQU,&fvar,0); - lp++; - len=0; - if (sp) { - sprintf(sp,"%08x",(uint32_t)fvar); - } - goto strexit; - } -#ifdef USE_LIGHT - - if (!strncmp(vname,"hsvrgb(",7)) { - lp=GetNumericResult(lp+7,OPER_EQU,&fvar,0); - if (fvar<0 || fvar>360) fvar=0; - SCRIPT_SKIP_SPACES - - float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); - if (fvar2<0 || fvar2>100) fvar2=0; - SCRIPT_SKIP_SPACES - - float fvar3; - lp=GetNumericResult(lp,OPER_EQU,&fvar3,0); - if (fvar3<0 || fvar3>100) fvar3=0; - - fvar=HSVToRGB(fvar,fvar2,fvar3); - - lp++; - len=0; - goto exit; - } - -#endif - break; - case 'i': - if (!strncmp(vname,"int(",4)) { - lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0); - fvar=floor(fvar); - lp++; - len=0; - goto exit; - } - break; - case 'l': - if (!strncmp(vname,"loglvl",6)) { - fvar=glob_script_mem.script_loglevel; - tind->index=SCRIPT_LOGLEVEL; - exit_settable: - if (fp) *fp=fvar; - *vtype=NTYPE; - tind->bits.settable=1; - tind->bits.is_string=0; - return lp+len; - } - break; - case 'm': - if (!strncmp(vname,"med(",4)) { - float fvar1; - lp=GetNumericResult(lp+4,OPER_EQU,&fvar1,0); - SCRIPT_SKIP_SPACES - - float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); - fvar=DoMedian5(fvar1,fvar2); - lp++; - len=0; - goto exit; - } - if (!strncmp(vname,"micros",6)) { - fvar=micros(); - goto exit; - } - if (!strncmp(vname,"millis",6)) { - fvar=millis(); - goto exit; - } - if (!strncmp(vname,"mins",4)) { - fvar=RtcTime.minute; - goto exit; - } - if (!strncmp(vname,"month",5)) { - fvar=RtcTime.month; - goto exit; - } - if (!strncmp(vname,"mqttc",5)) { - if (rules_flag.mqtt_connected) { - rules_flag.mqtt_connected=0; - fvar=1; - } - goto exit; - } - if (!strncmp(vname,"mqttd",5)) { - if (rules_flag.mqtt_disconnected) { - rules_flag.mqtt_disconnected=0; - fvar=1; - } - goto exit; - } - if (!strncmp(vname,"mqtts",5)) { - fvar=!global_state.mqtt_down; - goto exit; - } - break; - case 'p': - if (!strncmp(vname,"pin[",4)) { - - GetNumericResult(vname+4,OPER_EQU,&fvar,0); - fvar=digitalRead((uint8_t)fvar); - - len++; - goto exit; - } - if (!strncmp(vname,"pn[",3)) { - GetNumericResult(vname+3,OPER_EQU,&fvar,0); - fvar=pin[(uint8_t)fvar]; - - len++; - goto exit; - } - if (!strncmp(vname,"pd[",3)) { - GetNumericResult(vname+3,OPER_EQU,&fvar,0); - uint8_t gpiopin=fvar; - for (uint8_t i=0;iMAX_COUNTERS) index=1; - fvar=RtcSettings.pulse_counter[index-1]; - len+=1; - goto exit; - } - break; - - case 'r': - if (!strncmp(vname,"ram",3)) { - fvar=glob_script_mem.script_mem_size+(glob_script_mem.script_size)+(MAX_RULE_MEMS*10); - goto exit; - } - break; - case 's': - if (!strncmp(vname,"secs",4)) { - fvar=RtcTime.second; - goto exit; - } - if (!strncmp(vname,"sw[",3)) { - - GetNumericResult(vname+3,OPER_EQU,&fvar,0); - fvar=SwitchLastState((uint8_t)fvar); - - len++; - goto exit; - } - if (!strncmp(vname,"stack",5)) { - fvar=GetStack(); - goto exit; - } - if (!strncmp(vname,"slen",4)) { - fvar=strlen(glob_script_mem.script_ram); - goto exit; - } - if (!strncmp(vname,"sl(",3)) { - lp+=3; - char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,0); - lp++; - len=0; - fvar=strlen(str); - goto exit; - } - if (!strncmp(vname,"sb(",3)) { - lp+=3; - char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,0); - SCRIPT_SKIP_SPACES - float fvar1; - lp=GetNumericResult(lp,OPER_EQU,&fvar1,0); - SCRIPT_SKIP_SPACES - float fvar2; - lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); - lp++; - len=0; - if (fvar1<0) { - fvar1=strlen(str)+fvar1; - } - memcpy(sp,&str[(uint8_t)fvar1],(uint8_t)fvar2); - sp[(uint8_t)fvar2] = '\0'; - goto strexit; - } - if (!strncmp(vname,"st(",3)) { - lp+=3; - char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,0); - while (*lp==' ') lp++; - char token[2]; - token[0]=*lp++; - token[1]=0; - while (*lp==' ') lp++; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - - lp++; - len=0; - if (sp) { - - char *st=strtok(str,token); - if (!st) { - *sp=0; - } else { - for (uint8_t cnt=1; cnt<=fvar; cnt++) { - if (cnt==fvar) { - strcpy(sp,st); - break; - } - st=strtok(NULL,token); - if (!st) { - *sp=0; - break; - } - } - } - } - goto strexit; - } - if (!strncmp(vname,"s(",2)) { - lp+=2; - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - char str[glob_script_mem.max_ssize+1]; - dtostrfd(fvar,glob_script_mem.script_dprec,str); - if (sp) strlcpy(sp,str,glob_script_mem.max_ssize); - lp++; - len=0; - goto strexit; - } -#if defined(USE_TIMERS) && defined(USE_SUNRISE) - if (!strncmp(vname,"sunrise",7)) { - fvar=SunMinutes(0); - goto exit; - } - if (!strncmp(vname,"sunset",6)) { - fvar=SunMinutes(1); - goto exit; - } -#endif - break; - case 't': - if (!strncmp(vname,"time",4)) { - fvar=MinutesPastMidnight(); - goto exit; - } - if (!strncmp(vname,"tper",4)) { - fvar=Settings.tele_period; - tind->index=SCRIPT_TELEPERIOD; - goto exit_settable; - } - if (!strncmp(vname,"tinit",5)) { - if (rules_flag.time_init) { - rules_flag.time_init=0; - fvar=1; - } - goto exit; - } - if (!strncmp(vname,"tset",4)) { - if (rules_flag.time_set) { - rules_flag.time_set=0; - fvar=1; - } - goto exit; - } - if (!strncmp(vname,"tstamp",6)) { - if (sp) strlcpy(sp,GetDateAndTime(DT_LOCAL).c_str(),glob_script_mem.max_ssize); - goto strexit; - } - if (!strncmp(vname,"topic",5)) { - if (sp) strlcpy(sp,Settings.mqtt_topic,glob_script_mem.max_ssize); - goto strexit; - } -#ifdef USE_DISPLAY -#ifdef USE_TOUCH_BUTTONS - if (!strncmp(vname,"tbut[",5)) { - GetNumericResult(vname+5,OPER_EQU,&fvar,0); - uint8_t index=fvar; - if (index<1 || index>MAXBUTTONS) index=1; - index--; - if (buttons[index]) { - fvar=buttons[index]->vpower&0x80; - } else { - fvar=-1; - } - len+=1; - goto exit; - } - -#endif -#endif - break; - case 'u': - if (!strncmp(vname,"uptime",6)) { - fvar=MinutesUptime(); - goto exit; - } - if (!strncmp(vname,"upsecs",6)) { - fvar=uptime; - goto exit; - } - if (!strncmp(vname,"upd[",4)) { - - struct T_INDEX ind; - uint8_t vtype; - isvar(vname+4,&vtype,&ind,0,0,0); - if (!ind.bits.constant) { - if (!ind.bits.changed) { - fvar=0; - len++; - goto exit; - } else { - glob_script_mem.type[ind.index].bits.changed=0; - fvar=1; - len++; - goto exit; - } - } - goto notfound; - } - break; - - case 'w': - if (!strncmp(vname,"wday",4)) { - fvar=RtcTime.day_of_week; - goto exit; - } - if (!strncmp(vname,"wific",5)) { - if (rules_flag.wifi_connected) { - rules_flag.wifi_connected=0; - fvar=1; - } - goto exit; - } - if (!strncmp(vname,"wifid",5)) { - if (rules_flag.wifi_disconnected) { - rules_flag.wifi_disconnected=0; - fvar=1; - } - goto exit; - } - if (!strncmp(vname,"wifis",5)) { - fvar=!global_state.wifi_down; - goto exit; - } - break; - case 'y': - if (!strncmp(vname,"year",4)) { - fvar=RtcTime.year; - goto exit; - } - break; - default: - break; - } - -notfound: - if (fp) *fp=0; - *vtype=VAR_NV; - tind->index=VAR_NV; - glob_script_mem.var_not_found=1; - return lp; - -exit: - if (fp) *fp=fvar; - *vtype=NUM_RES; - tind->bits.constant=1; - tind->bits.is_string=0; - return lp+len; - -strexit: - *vtype=STYPE; - tind->bits.constant=1; - tind->bits.is_string=1; - return lp+len; -} - - - -char *getop(char *lp, uint8_t *operand) { - switch (*lp) { - case '=': - if (*(lp+1)=='=') { - *operand=OPER_EQUEQU; - return lp+2; - } else { - *operand=OPER_EQU; - return lp+1; - } - break; - case '+': - if (*(lp+1)=='=') { - *operand=OPER_PLSEQU; - return lp+2; - } else { - *operand=OPER_PLS; - return lp+1; - } - break; - case '-': - if (*(lp+1)=='=') { - *operand=OPER_MINEQU; - return lp+2; - } else { - *operand=OPER_MIN; - return lp+1; - } - break; - case '*': - if (*(lp+1)=='=') { - *operand=OPER_MULEQU; - return lp+2; - } else { - *operand=OPER_MUL; - return lp+1; - } - break; - case '/': - if (*(lp+1)=='=') { - *operand=OPER_DIVEQU; - return lp+2; - } else { - *operand=OPER_DIV; - return lp+1; - } - break; - case '!': - if (*(lp+1)=='=') { - *operand=OPER_NOTEQU; - return lp+2; - } - break; - case '>': - if (*(lp+1)=='=') { - *operand=OPER_GRTEQU; - return lp+2; - } else { - *operand=OPER_GRT; - return lp+1; - - } - break; - case '<': - if (*(lp+1)=='=') { - *operand=OPER_LOWEQU; - return lp+2; - } else { - *operand=OPER_LOW; - return lp+1; - } - break; - case '%': - if (*(lp+1)=='=') { - *operand=OPER_PERCEQU; - return lp+2; - } else { - *operand=OPER_PERC; - return lp+1; - } - break; - case '^': - if (*(lp+1)=='=') { - *operand=OPER_XOREQU; - return lp+2; - } else { - *operand=OPER_XOR; - return lp+1; - } - break; - case '&': - if (*(lp+1)=='=') { - *operand=OPER_ANDEQU; - return lp+2; - } else { - *operand=OPER_AND; - return lp+1; - } - break; - case '|': - if (*(lp+1)=='=') { - *operand=OPER_OREQU; - return lp+2; - } else { - *operand=OPER_OR; - return lp+1; - } - break; - } - *operand=0; - return lp; -} - - -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) - - -extern "C" { -#include - extern cont_t g_cont; -} -uint16_t GetStack(void) { - register uint32_t *sp asm("a1"); - return (4 * (sp - g_cont.stack)); -} - -#else -extern "C" { -#include - extern cont_t* g_pcont; -} -uint16_t GetStack(void) { - register uint32_t *sp asm("a1"); - return (4 * (sp - g_pcont->stack)); -} -#endif - -char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo) { - uint8_t operand=0; - uint8_t vtype; - char *slp; - struct T_INDEX ind; - char str[SCRIPT_MAXSSIZE],str1[SCRIPT_MAXSSIZE]; - while (1) { - lp=isvar(lp,&vtype,&ind,0,str1,jo); - if (vtype!=STR_RES && !(vtype&STYPE)) { - - glob_script_mem.glob_error=1; - return lp; - } - switch (lastop) { - case OPER_EQU: - strlcpy(str,str1,sizeof(str)); - break; - case OPER_PLS: - strncat(str,str1,sizeof(str)); - break; - } - slp=lp; - lp=getop(lp,&operand); - switch (operand) { - case OPER_EQUEQU: - case OPER_NOTEQU: - case OPER_LOW: - case OPER_LOWEQU: - case OPER_GRT: - case OPER_GRTEQU: - lp=slp; - strcpy(cp,str); - return lp; - break; - default: - break; - } - lastop=operand; - if (!operand) { - strcpy(cp,str); - return lp; - } - } -} - -char *GetNumericResult(char *lp,uint8_t lastop,float *fp,JsonObject *jo) { -uint8_t operand=0; -float fvar1,fvar; -char *slp; -uint8_t vtype; -struct T_INDEX ind; - while (1) { - - if (*lp=='(') { - lp++; - lp=GetNumericResult(lp,OPER_EQU,&fvar1,jo); - lp++; - - } else { - lp=isvar(lp,&vtype,&ind,&fvar1,0,jo); - if (vtype!=NUM_RES && vtype&STYPE) { - - glob_script_mem.glob_error=1; - } - } - switch (lastop) { - case OPER_EQU: - fvar=fvar1; - break; - case OPER_PLS: - fvar+=fvar1; - break; - case OPER_MIN: - fvar-=fvar1; - break; - case OPER_MUL: - fvar*=fvar1; - break; - case OPER_DIV: - fvar/=fvar1; - break; - case OPER_PERC: - fvar=fmodf(fvar,fvar1); - break; - case OPER_XOR: - fvar=(uint32_t)fvar^(uint32_t)fvar1; - break; - case OPER_AND: - fvar=(uint32_t)fvar&(uint32_t)fvar1; - break; - case OPER_OR: - fvar=(uint32_t)fvar|(uint32_t)fvar1; - break; - default: - break; - - } - slp=lp; - lp=getop(lp,&operand); - switch (operand) { - case OPER_EQUEQU: - case OPER_NOTEQU: - case OPER_LOW: - case OPER_LOWEQU: - case OPER_GRT: - case OPER_GRTEQU: - lp=slp; - *fp=fvar; - return lp; - break; - default: - break; - } - lastop=operand; - if (!operand) { - *fp=fvar; - return lp; - } - } -} - - -char *ForceStringVar(char *lp,char *dstr) { - float fvar; - char *slp=lp; - glob_script_mem.glob_error=0; - lp=GetStringResult(lp,OPER_EQU,dstr,0); - if (glob_script_mem.glob_error) { - - lp=GetNumericResult(slp,OPER_EQU,&fvar,0); - dtostrfd(fvar,6,dstr); - glob_script_mem.glob_error=0; - } - return lp; -} - - -void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) { - char *cp; - uint16_t count; - uint8_t vtype; - uint8_t dprec=glob_script_mem.script_dprec; - float fvar; - cp=srcbuf; - struct T_INDEX ind; - char string[SCRIPT_MAXSSIZE]; - for (count=0;count=sizeof(str)) len=len>=sizeof(str); - strlcpy(str,cp,len); - toSLog(str); -} - -void toLogEOL(const char *s1,const char *str) { - if (!str) return; - uint8_t index=0; - char *cp=log_data; - strcpy(cp,s1); - cp+=strlen(s1); - while (*str) { - if (*str==SCRIPT_EOL) break; - *cp++=*str++; - } - *cp=0; - AddLog(LOG_LEVEL_INFO); -} - - -void toSLog(const char *str) { - if (!str) return; -#if SCRIPT_DEBUG>0 - while (*str) { - Serial.write(*str); - str++; - } -#endif -} - -char *Evaluate_expression(char *lp,uint8_t and_or, uint8_t *result,JsonObject *jo) { - float fvar,*dfvar,fvar1; - uint8_t numeric; - struct T_INDEX ind; - uint8_t vtype=0,lastop; - uint8_t res=0; - - SCRIPT_SKIP_SPACES - - if (*lp=='(') { - lp++; - lp=Evaluate_expression(lp,and_or,result,jo); - lp++; - - SCRIPT_SKIP_SPACES - if (!strncmp(lp,"or",2)) { - lp+=2; - and_or=1; - SCRIPT_SKIP_SPACES - lp=Evaluate_expression(lp,and_or,result,jo); - } else if (!strncmp(lp,"and",3)) { - lp+=3; - and_or=2; - SCRIPT_SKIP_SPACES - lp=Evaluate_expression(lp,and_or,result,jo); - } - return lp; - } - - - dfvar=&fvar; - glob_script_mem.glob_error=0; - char *slp=lp; - numeric=1; - lp=GetNumericResult(lp,OPER_EQU,dfvar,0); - if (glob_script_mem.glob_error==1) { - - char cmpstr[SCRIPT_MAXSSIZE]; - lp=slp; - numeric=0; - - lp=isvar(lp,&vtype,&ind,0,cmpstr,0); - lp=getop(lp,&lastop); - - char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,jo); - if (lastop==OPER_EQUEQU || lastop==OPER_NOTEQU) { - uint8_t res=0; - res=strcmp(cmpstr,str); - if (lastop==OPER_EQUEQU) res=!res; - if (!and_or) { - *result=res; - } else if (and_or==1) { - *result|=res; - } else { - *result&=res; - } - } - - } else { - - - lp=getop(lp,&lastop); - - lp=GetNumericResult(lp,OPER_EQU,&fvar1,jo); - switch (lastop) { - case OPER_EQUEQU: - res=(*dfvar==fvar1); - break; - case OPER_NOTEQU: - res=(*dfvar!=fvar1); - break; - case OPER_LOW: - res=(*dfvarfvar1); - break; - case OPER_GRTEQU: - res=(*dfvar>=fvar1); - break; - default: - - break; - } - - if (!and_or) { - *result=res; - } else if (and_or==1) { - *result|=res; - } else { - *result&=res; - } - } -exit: -#if SCRIPT_DEBUG>0 - char tbuff[128]; - sprintf(tbuff,"p1=%d,p2=%d,cmpres=%d line: ",(int32_t)*dfvar,(int32_t)fvar1,*result); - toLogEOL(tbuff,lp); -#endif - return lp; -} - - - -#define IF_NEST 8 - -int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { - - if (tasm_cmd_activ && tlen>0) return 0; - - uint8_t vtype=0,sindex,xflg,floop=0,globvindex,fromscriptcmd=0; - int8_t globaindex; - struct T_INDEX ind; - uint8_t operand,lastop,numeric=1,if_state[IF_NEST],if_exe[IF_NEST],if_result[IF_NEST],and_or,ifstck=0; - if_state[ifstck]=0; - if_result[ifstck]=0; - if_exe[ifstck]=1; - char cmpstr[SCRIPT_MAXSSIZE]; - uint8_t check=0; - if (tlen<0) { - tlen=abs(tlen); - check=1; - } - - float *dfvar,*cv_count,cv_max,cv_inc; - char *cv_ptr; - float fvar=0,fvar1,sysvar,swvar; - uint8_t section=0,sysv_type=0,swflg=0; - - if (!glob_script_mem.scriptptr) { - return -99; - } - - DynamicJsonBuffer jsonBuffer; - JsonObject &jobj=jsonBuffer.parseObject(js); - JsonObject *jo; - if (js) jo=&jobj; - else jo=0; - - char *lp=glob_script_mem.scriptptr; - - while (1) { - - - startline: - SCRIPT_SKIP_SPACES - - SCRIPT_SKIP_EOL - - if (*lp==';') goto next_line; - if (!*lp) break; - - if (section) { - - if (*lp=='>') { - return 0; - } - if (*lp=='#') { - return 0; - } - glob_script_mem.var_not_found=0; - - -#ifdef IFTHEN_DEBUG - char tbuff[128]; - sprintf(tbuff,"stack=%d,exe=%d,state=%d,cmpres=%d line: ",ifstck,if_exe[ifstck],if_state[ifstck],if_result[ifstck]); - toLogEOL(tbuff,lp); -#endif - - - - - if (!strncmp(lp,"if",2)) { - lp+=2; - if (ifstck=2) { - lp+=5; - if (ifstck>0) { - if_state[ifstck]=0; - ifstck--; - } - goto next_line; - } else if (!strncmp(lp,"or",2) && if_state[ifstck]==1) { - lp+=2; - and_or=1; - } else if (!strncmp(lp,"and",3) && if_state[ifstck]==1) { - lp+=3; - and_or=2; - } - - if (*lp=='{' && if_state[ifstck]==1) { - lp+=1; - if_state[ifstck]=2; - if (if_exe[ifstck-1]) if_exe[ifstck]=if_result[ifstck]; - } else if (*lp=='{' && if_state[ifstck]==3) { - lp+=1; - - } else if (*lp=='}' && if_state[ifstck]>=2) { - lp++; - char *slp=lp; - uint8_t iselse=0; - for (uint8_t count=0; count<8;count++) { - if (*lp=='}') { - - break; - } - if (!strncmp(lp,"else",4)) { - - if_state[ifstck]=3; - if (if_exe[ifstck-1]) if_exe[ifstck]=!if_result[ifstck]; - lp+=4; - iselse=1; - SCRIPT_SKIP_SPACES - if (*lp=='{') lp++; - break; - } - lp++; - } - if (!iselse) { - lp=slp; - - if (ifstck>0) { - if_state[ifstck]=0; - ifstck--; - } - goto next_line; - } - } - - if (!strncmp(lp,"for",3)) { - - - lp+=3; - SCRIPT_SKIP_SPACES - lp=isvar(lp,&vtype,&ind,0,0,0); - if ((vtype!=VAR_NV) && (vtype&STYPE)==0) { - - uint8_t index=glob_script_mem.type[ind.index].index; - cv_count=&glob_script_mem.fvars[index]; - SCRIPT_SKIP_SPACES - lp=GetNumericResult(lp,OPER_EQU,cv_count,0); - SCRIPT_SKIP_SPACES - lp=GetNumericResult(lp,OPER_EQU,&cv_max,0); - SCRIPT_SKIP_SPACES - lp=GetNumericResult(lp,OPER_EQU,&cv_inc,0); - - cv_ptr=lp; - floop=1; - } else { - - toLogEOL("for error",lp); - } - } else if (!strncmp(lp,"next",4) && floop>0) { - - *cv_count+=cv_inc; - if (*cv_count<=cv_max) { - lp=cv_ptr; - } else { - lp+=4; - floop=0; - } - } - - if (!strncmp(lp,"switch",6)) { - lp+=6; - SCRIPT_SKIP_SPACES - char *slp=lp; - lp=GetNumericResult(lp,OPER_EQU,&swvar,0); - if (glob_script_mem.glob_error==1) { - - lp=slp; - - lp=isvar(lp,&vtype,&ind,0,cmpstr,0); - swflg=0x81; - } else { - swflg=1; - } - } else if (!strncmp(lp,"case",4) && swflg>0) { - lp+=4; - SCRIPT_SKIP_SPACES - float cvar; - if (!(swflg&0x80)) { - lp=GetNumericResult(lp,OPER_EQU,&cvar,0); - if (swvar!=cvar) { - swflg=2; - } else { - swflg=1; - } - } else { - char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,0); - if (!strcmp(cmpstr,str)) { - swflg=0x81; - } else { - swflg=0x82; - } - } - } else if (!strncmp(lp,"ends",4) && swflg>0) { - lp+=4; - swflg=0; - } - if ((swflg&3)==2) goto next_line; - - SCRIPT_SKIP_SPACES - - if (*lp==SCRIPT_EOL) { - goto next_line; - } - - - if (!if_exe[ifstck] && if_state[ifstck]!=1) goto next_line; - -#ifdef IFTHEN_DEBUG - sprintf(tbuff,"stack=%d,exe=%d,state=%d,cmpres=%d execute line: ",ifstck,if_exe[ifstck],if_state[ifstck],if_result[ifstck]); - toLogEOL(tbuff,lp); -#endif - - if (!strncmp(lp,"break",5)) { - if (floop) { - - floop=0; - } else { - section=0; - } - break; - } else if (!strncmp(lp,"dp",2) && isdigit(*(lp+2))) { - lp+=2; - - glob_script_mem.script_dprec=atoi(lp); - goto next_line; - } else if (!strncmp(lp,"delay(",6)) { - lp+=5; - - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - delay(fvar); - goto next_line; - } else if (!strncmp(lp,"spinm(",6)) { - lp+=6; - - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - int8_t pinnr=fvar; - SCRIPT_SKIP_SPACES - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - int8_t mode=fvar; - pinMode(pinnr,mode&3); - goto next_line; - } else if (!strncmp(lp,"spin(",5)) { - lp+=5; - - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - int8_t pinnr=fvar; - SCRIPT_SKIP_SPACES - lp=GetNumericResult(lp,OPER_EQU,&fvar,0); - int8_t mode=fvar; - digitalWrite(pinnr,mode&1); - goto next_line; - } else if (!strncmp(lp,"svars(",5)) { - lp+=5; - - Scripter_save_pvars(); - goto next_line; - } -#ifdef USE_LIGHT -#ifdef USE_WS2812 - else if (!strncmp(lp,"ws2812(",7)) { - lp+=7; - lp=isvar(lp,&vtype,&ind,0,0,0); - if (vtype!=VAR_NV) { - - uint8_t index=glob_script_mem.type[ind.index].index; - if ((vtype&STYPE)==0) { - - if (glob_script_mem.type[index].bits.is_filter) { - uint8_t len=0; - float *fa=Get_MFAddr(index,&len); - - if (fa && len) ws2812_set_array(fa,len); - } - } - } - goto next_line; - } -#endif -#endif - - else if (!strncmp(lp,"=>",2) || !strncmp(lp,"->",2) || !strncmp(lp,"print",5)) { - - uint8_t sflag=0,pflg=0,svmqtt,swll; - if (*lp=='p') { - pflg=1; - lp+=5; - } - else { - if (*lp=='-') sflag=1; - lp+=2; - } - char *slp=lp; - SCRIPT_SKIP_SPACES - #define SCRIPT_CMDMEM 512 - char *cmdmem=(char*)malloc(SCRIPT_CMDMEM); - if (cmdmem) { - char *cmd=cmdmem; - uint16_t count; - for (count=0; count=0) { - Set_MFVal(glob_script_mem.type[globvindex].index,globaindex,*dfvar); - } else { - Set_MFilter(glob_script_mem.type[globvindex].index,*dfvar); - } - } - - if (sysv_type) { - switch (sysv_type) { - case SCRIPT_LOGLEVEL: - glob_script_mem.script_loglevel=*dfvar; - break; - case SCRIPT_TELEPERIOD: - if (*dfvar<10) *dfvar=10; - if (*dfvar>300) *dfvar=300; - Settings.tele_period=*dfvar; - break; - } - sysv_type=0; - } - } else { - - numeric=0; - sindex=index; - - char str[SCRIPT_MAXSSIZE]; - lp=getop(lp,&lastop); - char *slp=lp; - glob_script_mem.glob_error=0; - lp=GetStringResult(lp,OPER_EQU,str,jo); - if (!js && glob_script_mem.glob_error) { - - lp=GetNumericResult(slp,OPER_EQU,&fvar,0); - dtostrfd(fvar,6,str); - glob_script_mem.glob_error=0; - } - - if (!glob_script_mem.var_not_found) { - - glob_script_mem.type[globvindex].bits.changed=1; - if (lastop==OPER_EQU) { - strlcpy(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); - } else if (lastop==OPER_PLSEQU) { - strncat(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),str,glob_script_mem.max_ssize); - } - } - } - - } - SCRIPT_SKIP_SPACES - if (*lp=='{' && if_state[ifstck]==3) { - lp+=1; - - } - goto next_line; - } - } else { - - if (*lp=='>' && tlen==1) { - - lp++; - section=1; - fromscriptcmd=1; - goto startline; - } - if (!strncmp(lp,type,tlen)) { - - section=1; - glob_script_mem.section_ptr=lp; - if (check) { - return 99; - } - - char *ctype=(char*)type; - if (*ctype=='#') { - - ctype+=tlen; - if (*ctype=='(' && *(lp+tlen)=='(') { - float fparam; - numeric=1; - glob_script_mem.glob_error=0; - GetNumericResult((char*)ctype,OPER_EQU,&fparam,0); - if (glob_script_mem.glob_error==1) { - - numeric=0; - - GetStringResult((char*)ctype+1,OPER_EQU,cmpstr,0); - } - lp+=tlen; - if (*lp=='(') { - - lp++; - lp=isvar(lp,&vtype,&ind,0,0,0); - if (vtype!=VAR_NV) { - - uint8_t index=glob_script_mem.type[ind.index].index; - if ((vtype&STYPE)==0) { - - dfvar=&glob_script_mem.fvars[index]; - if (numeric) { - *dfvar=fparam; - } else { - - *dfvar=CharToFloat(cmpstr); - } - } else { - - sindex=index; - if (!numeric) { - strlcpy(glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize),cmpstr,glob_script_mem.max_ssize); - } else { - - dtostrfd(fparam,6,glob_script_mem.glob_snp+(sindex*glob_script_mem.max_ssize)); - } - } - } - } - } else { - lp+=tlen; - if (*ctype=='(' || (*lp!=SCRIPT_EOL && *lp!='?')) { - - section=0; - } - } - } - } - } - - next_line: - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) { - if (section) { - return 0; - } else { - return -1; - } - } - lp++; - } - } - return -1; -} - -uint8_t script_xsns_index = 0; - - -void ScripterEvery100ms(void) { - - if (Settings.rule_enabled && (uptime > 4)) { - mqtt_data[0] = '\0'; - uint16_t script_tele_period_save = tele_period; - tele_period = 2; - XsnsNextCall(FUNC_JSON_APPEND, script_xsns_index); - tele_period = script_tele_period_save; - if (strlen(mqtt_data)) { - mqtt_data[0] = '{'; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); - Run_Scripter(">T",2, mqtt_data); - } - } - if (fast_script==99) Run_Scripter(">F",2,0); -} - - - - -void Scripter_save_pvars(void) { - int16_t mlen=0; - float *fp=(float*)glob_script_mem.script_pram; - mlen+=sizeof(float); - struct T_INDEX *vtp=glob_script_mem.type; - for (uint8_t count=0; countMAX_RULE_MEMS*10) { - vtp[count].bits.is_permanent=0; - return; - } - *fp++=glob_script_mem.fvars[index]; - } - } - char *cp=(char*)fp; - for (uint8_t count=0; countMAX_RULE_MEMS*10) { - vtp[count].bits.is_permanent=0; - return; - } - strcpy(cp,sp); - cp+=slen+1; - } - } -} - - -#ifdef USE_WEBSERVER - -#define WEB_HANDLE_SCRIPT "s10" -#define D_CONFIGURE_SCRIPT "Edit script" -#define D_SCRIPT "edit script" -#define D_SDCARD_UPLOAD "file upload" -#define D_SDCARD_DIR "sd card directory" -#define D_UPL_DONE "Done" - -const char S_CONFIGURE_SCRIPT[] PROGMEM = D_CONFIGURE_SCRIPT; - -const char HTTP_BTN_MENU_RULES[] PROGMEM = - "

"; - - -const char HTTP_FORM_SCRIPT[] PROGMEM = - "
 " D_SCRIPT " " - "
"; - -const char HTTP_FORM_SCRIPT1[] PROGMEM = - "
" - "script enable
" - "
" - ""; - -const char HTTP_SCRIPT_FORM_END[] PROGMEM = - "
" - "" - "
"; - -#ifdef USE_SCRIPT_FATFS -const char HTTP_FORM_SCRIPT1c[] PROGMEM = -""; -#ifdef SDCARD_DIR -const char HTTP_FORM_SCRIPT1d[] PROGMEM = -""; -#else -const char HTTP_FORM_SCRIPT1d[] PROGMEM = -""; -#endif - -#ifdef SDCARD_DIR -const char S_SCRIPT_FILE_UPLOAD[] PROGMEM = D_SDCARD_DIR; -#else -const char S_SCRIPT_FILE_UPLOAD[] PROGMEM = D_SDCARD_UPLOAD; -#endif - -const char HTTP_FORM_FILE_UPLOAD[] PROGMEM = -"
" -"
 %s" " "; -const char HTTP_FORM_FILE_UPG[] PROGMEM = -"
" -"

" -"
"; - -const char HTTP_FORM_FILE_UPGb[] PROGMEM = -"
" -"
" -""; - -const char HTTP_FORM_SDC_DIRa[] PROGMEM = -"
"; -const char HTTP_FORM_SDC_DIRb[] PROGMEM = - "
%s    %d
"; -const char HTTP_FORM_SDC_DIRd[] PROGMEM = -"
%s
"; -const char HTTP_FORM_SDC_DIRc[] PROGMEM = -"
"; -const char HTTP_FORM_SDC_HREF[] PROGMEM = -"http://%s/upl?download=%s/%s"; -#endif - - - -#ifdef USE_SCRIPT_FATFS - -#if USE_LONG_FILE_NAMES>0 -#undef REJCMPL -#define REJCMPL 6 -#else -#undef REJCMPL -#define REJCMPL 8 -#endif - -uint8_t reject(char *name) { - - if (*name=='_') return 1; - if (*name=='.') return 1; - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 - if (!strncasecmp(name,"SPOTLI~1",REJCMPL)) return 1; - if (!strncasecmp(name,"TRASHE~1",REJCMPL)) return 1; - if (!strncasecmp(name,"FSEVEN~1",REJCMPL)) return 1; - if (!strncasecmp(name,"SYSTEM~1",REJCMPL)) return 1; -#else - if (!strcasecmp(name,"SPOTLI~1")) return 1; - if (!strcasecmp(name,"TRASHE~1")) return 1; - if (!strcasecmp(name,"FSEVEN~1")) return 1; - if (!strcasecmp(name,"SYSTEM~1")) return 1; -#endif - return 0; -} - -void ListDir(char *path, uint8_t depth) { - char name[32]; - char npath[128]; - char format[12]; - sprintf(format,"%%-%ds",24-depth); - - File dir=SD.open(path); - if (dir) { - dir.rewindDirectory(); - if (strlen(path)>1) { - snprintf_P(npath,sizeof(npath),PSTR("http://%s/upl?download=%s"),WiFi.localIP().toString().c_str(),path); - for (uint8_t cnt=strlen(npath)-1;cnt>0;cnt--) { - if (npath[cnt]=='/') { - if (npath[cnt-1]=='=') npath[cnt+1]=0; - else npath[cnt]=0; - break; - } - } - WSContentSend_P(HTTP_FORM_SDC_DIRd,npath,path,".."); - } - while (true) { - File entry=dir.openNextFile(); - if (!entry) { - break; - } - char *pp=path; - if (!*(pp+1)) pp++; - char *cp=name; - - if (reject((char*)entry.name())) goto fclose; - - for (uint8_t cnt=0;cnt1) { - strcat(path,"/"); - } - strcat(path,entry.name()); - ListDir(path,depth+4); - path[plen]=0; - } else { - snprintf_P(npath,sizeof(npath),HTTP_FORM_SDC_HREF,WiFi.localIP().toString().c_str(),pp,entry.name()); - WSContentSend_P(HTTP_FORM_SDC_DIRb,npath,entry.name(),name,entry.size()); - } - fclose: - entry.close(); - } - dir.close(); - } -} - -char path[48]; - -void Script_FileUploadConfiguration(void) -{ - uint8_t depth=0; - strcpy(path,"/"); - - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("download")) { - String stmp = WebServer->arg("download"); - char *cp=(char*)stmp.c_str(); - if (DownloadFile(cp)) { - - strcpy(path,cp); - } - } - - WSContentStart_P(S_SCRIPT_FILE_UPLOAD); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_FILE_UPLOAD,D_SDCARD_DIR); - WSContentSend_P(HTTP_FORM_FILE_UPG, "upload"); -#ifdef SDCARD_DIR - WSContentSend_P(HTTP_FORM_SDC_DIRa); - if (glob_script_mem.script_sd_found) { - ListDir(path,depth); - } - WSContentSend_P(HTTP_FORM_SDC_DIRc); -#endif - WSContentSend_P(HTTP_FORM_FILE_UPGb); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); - Web.upload_error = 0; -} - -File upload_file; - -void ScriptFileUploadSuccess(void) { - WSContentStart_P(S_INFORMATION); - WSContentSendStyle(); - WSContentSend_P(PSTR("
" D_UPLOAD " " D_SUCCESSFUL "
"), WebColor(COL_TEXT_SUCCESS)); - WSContentSend_P(PSTR("

")); - WSContentSend_P(PSTR("

"),"/upl",D_UPL_DONE); - - WSContentStop(); -} - - - -void script_upload(void) { - - - - HTTPUpload& upload = WebServer->upload(); - if (upload.status == UPLOAD_FILE_START) { - char npath[48]; - sprintf(npath,"%s/%s",path,upload.filename.c_str()); - SD.remove(npath); - upload_file=SD.open(npath,FILE_WRITE); - if (!upload_file) Web.upload_error=1; - } else if(upload.status == UPLOAD_FILE_WRITE) { - if (upload_file) upload_file.write(upload.buf,upload.currentSize); - } else if(upload.status == UPLOAD_FILE_END) { - if (upload_file) upload_file.close(); - if (Web.upload_error) { - AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload error")); - } - } else { - Web.upload_error=1; - WebServer->send(500, "text/plain", "500: couldn't create file"); - } -} - -uint8_t DownloadFile(char *file) { - File download_file; - WiFiClient download_Client; - - if (!SD.exists(file)) { - AddLog_P(LOG_LEVEL_INFO,PSTR("file not found")); - return 0; - } - - download_file=SD.open(file,FILE_READ); - if (!download_file) { - AddLog_P(LOG_LEVEL_INFO,PSTR("could not open file")); - return 0; - } - - if (download_file.isDirectory()) { - download_file.close(); - return 1; - } - - uint32_t flen=download_file.size(); - - download_Client = WebServer->client(); - WebServer->setContentLength(flen); - - char attachment[100]; - char *cp; - for (uint8_t cnt=strlen(file); cnt>=0; cnt--) { - if (file[cnt]=='/') { - cp=&file[cnt+1]; - break; - } - } - snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"),cp); - WebServer->sendHeader(F("Content-Disposition"), attachment); - WSSend(200, CT_STREAM, ""); - - uint8_t buff[512]; - uint16_t bread; - - - uint8_t cnt=0; - while (download_file.available()) { - bread=download_file.read(buff,sizeof(buff)); - uint16_t bw=download_Client.write((const char*)buff,bread); - if (!bw) break; - cnt++; - if (cnt>7) { - cnt=0; - if (glob_script_mem.script_loglevel&0x80) { - - loop(); - } - } - } - download_file.close(); - download_Client.stop(); - return 0; -} - -#endif - - -void HandleScriptTextareaConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("save")) { - ScriptSaveSettings(); - HandleConfiguration(); - return; - } -} - -void HandleScriptConfiguration(void) { - - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_SCRIPT); - -#ifdef USE_SCRIPT_FATFS - if (WebServer->hasArg("d1")) { - DownloadFile(glob_script_mem.flink[0]); - } - if (WebServer->hasArg("d2")) { - DownloadFile(glob_script_mem.flink[1]); - } - if (WebServer->hasArg("upl")) { - Script_FileUploadConfiguration(); - } -#endif - - WSContentStart_P(S_CONFIGURE_SCRIPT); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_SCRIPT); - WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",glob_script_mem.script_size); - - - if (glob_script_mem.script_ram[0]) { - _WSContentSend(glob_script_mem.script_ram); - } - WSContentSend_P(HTTP_FORM_SCRIPT1b); - -#ifdef USE_SCRIPT_FATFS - if (glob_script_mem.script_sd_found) { - WSContentSend_P(HTTP_FORM_SCRIPT1d); - if (glob_script_mem.flink[0][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,1,glob_script_mem.flink[0]); - if (glob_script_mem.flink[1][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,2,glob_script_mem.flink[1]); - } -#endif - - WSContentSend_P(HTTP_SCRIPT_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); - } - - -void ScriptSaveSettings(void) { - - if (WebServer->hasArg("c1")) { - bitWrite(Settings.rule_enabled,0,1); - } else { - bitWrite(Settings.rule_enabled,0,0); - } - - - String str = WebServer->arg("t1"); - - if (*str.c_str()) { - - str.replace("\r\n","\n"); - str.replace("\r","\n"); - - strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size); - -#ifdef USE_24C256 -#ifndef USE_SCRIPT_FATFS - if (glob_script_mem.flags&1) { - EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); - } -#endif -#endif - -#ifdef USE_SCRIPT_FATFS - if (glob_script_mem.flags&1) { - SD.remove(FAT_SCRIPT_NAME); - File file=SD.open(FAT_SCRIPT_NAME,FILE_WRITE); - file.write(glob_script_mem.script_ram,FAT_SCRIPT_SIZE); - file.close(); - } -#endif - - } - - if (glob_script_mem.script_mem) { - Scripter_save_pvars(); - free(glob_script_mem.script_mem); - glob_script_mem.script_mem=0; - glob_script_mem.script_mem_size=0; - } - - if (bitRead(Settings.rule_enabled, 0)) { - int16_t res=Init_Scripter(); - if (res) { - snprintf_P(log_data, sizeof(log_data), PSTR("script init error: %d"),res); - AddLog(LOG_LEVEL_INFO); - return; - } - Run_Scripter(">B",2,0); - fast_script=Run_Scripter(">F",-2,0); - } -} - -#endif - - -#ifdef USE_SCRIPT_SUB_COMMAND -bool Script_SubCmd(void) { - if (!bitRead(Settings.rule_enabled, 0)) return false; - - char cmdbuff[128]; - char *cp=cmdbuff; - *cp++='#'; - strcpy(cp,XdrvMailbox.topic); - uint8_t tlen=strlen(XdrvMailbox.topic); - cp+=tlen; - if (XdrvMailbox.index > 0) { - *cp++=XdrvMailbox.index|0x30; - tlen++; - } - if ((XdrvMailbox.payload>0) || (XdrvMailbox.data_len>0)) { - *cp++='('; - strncpy(cp,XdrvMailbox.data,XdrvMailbox.data_len); - cp+=XdrvMailbox.data_len; - *cp++=')'; - *cp=0; - } - - uint32_t res=Run_Scripter(cmdbuff,tlen+1,0); - - if (res) return false; - else return true; -} -#endif - -void execute_script(char *script) { - char *svd_sp=glob_script_mem.scriptptr; - strcat(script,"\n#"); - glob_script_mem.scriptptr=script; - Run_Scripter(">",1,0); - glob_script_mem.scriptptr=svd_sp; -} -#define D_CMND_SCRIPT "Script" -#define D_CMND_SUBSCRIBE "Subscribe" -#define D_CMND_UNSUBSCRIBE "Unsubscribe" - -enum ScriptCommands { CMND_SCRIPT,CMND_SUBSCRIBE, CMND_UNSUBSCRIBE }; -const char kScriptCommands[] PROGMEM = D_CMND_SCRIPT "|" D_CMND_SUBSCRIBE "|" D_CMND_UNSUBSCRIBE; - -bool ScriptCommand(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t index = XdrvMailbox.index; - - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kScriptCommands); - if (-1 == command_code) { -#ifdef USE_SCRIPT_SUB_COMMAND - strlcpy(command,XdrvMailbox.topic,CMDSZ); - uint32_t pl=XdrvMailbox.payload; - char pld[64]; - strlcpy(pld,XdrvMailbox.data,sizeof(pld)); - if (Script_SubCmd()) { - if (pl>=0) { - Response_P(S_JSON_COMMAND_NVALUE, command, pl); - } else { - Response_P(S_JSON_COMMAND_SVALUE, command, pld); - } - return serviced; - } -#endif - serviced = false; - } - else if ((CMND_SCRIPT == command_code) && (index > 0)) { - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 2)) { - switch (XdrvMailbox.payload) { - case 0: - case 1: - bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload); - } - } else { - if ('>' == XdrvMailbox.data[0]) { - - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"),command,XdrvMailbox.data); - if (bitRead(Settings.rule_enabled, 0)) { - for (uint8_t count=0; count> 1; -} - -void dateTime(uint16_t* date, uint16_t* time) { - - *date = xFAT_DATE(RtcTime.year,RtcTime.month, RtcTime.day_of_month); - - *time = xFAT_TIME(RtcTime.hour,RtcTime.minute,RtcTime.second); -} - -#endif - - - -#ifdef SUPPORT_MQTT_EVENT -# 3469 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_scripter.ino" -bool ScriptMqttData(void) -{ - bool serviced = false; - - toLog(XdrvMailbox.data); - if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) { - return false; - } - String sTopic = XdrvMailbox.topic; - String sData = XdrvMailbox.data; - - MQTT_Subscription event_item; - - for (uint32_t index = 0; index < subscriptions.size(); index++) { - event_item = subscriptions.get(index); - - - if (sTopic.startsWith(event_item.Topic)) { - - serviced = true; - String value; - String lkey; - if (event_item.Key.length() == 0) { - value = sData; - } else { - StaticJsonBuffer<400> jsonBuf; - JsonObject& jsonData = jsonBuf.parseObject(sData); - String key1 = event_item.Key; - String key2; - if (!jsonData.success()) break; - int dot; - if ((dot = key1.indexOf('.')) > 0) { - key2 = key1.substring(dot+1); - key1 = key1.substring(0, dot); - lkey=key2; - if (!jsonData[key1][key2].success()) break; - value = (const char *)jsonData[key1][key2]; - } else { - if (!jsonData[key1].success()) break; - value = (const char *)jsonData[key1]; - lkey=key1; - } - } - value.trim(); - char sbuffer[128]; - - if (!strncmp(lkey.c_str(),"Epoch",5)) { - uint32_t ep=atoi(value.c_str())-(uint32_t)EPOCH_OFFSET; - snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=%d\n"), event_item.Event.c_str(),ep); - } else { - snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str()); - } - - execute_script(sbuffer); - } - } - return serviced; -} -# 3544 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_scripter.ino" -String ScriptSubscribe(const char *data, int data_len) -{ - MQTT_Subscription subscription_item; - String events; - if (data_len > 0) { - char parameters[data_len+1]; - memcpy(parameters, data, data_len); - parameters[data_len] = '\0'; - String event_name, topic, key; - - char * pos = strtok(parameters, ","); - if (pos) { - event_name = Trim(pos); - pos = strtok(nullptr, ","); - if (pos) { - topic = Trim(pos); - pos = strtok(nullptr, ","); - if (pos) { - key = Trim(pos); - } - } - } - - - if (event_name.length() > 0 && topic.length() > 0) { - - for (uint32_t index=0; index < subscriptions.size(); index++) { - if (subscriptions.get(index).Event.equals(event_name)) { - - String stopic = subscriptions.get(index).Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - subscriptions.remove(index); - break; - } - } - - if (!topic.endsWith("#")) { - if (topic.endsWith("/")) { - topic.concat("#"); - } else { - topic.concat("/#"); - } - } - - - subscription_item.Event = event_name; - subscription_item.Topic = topic.substring(0, topic.length() - 2); - subscription_item.Key = key; - subscriptions.add(subscription_item); - - MqttSubscribe(topic.c_str()); - events.concat(event_name + "," + topic - + (key.length()>0 ? "," : "") - + key); - } else { - events = D_JSON_WRONG_PARAMETERS; - } - } else { - - for (uint32_t index=0; index < subscriptions.size(); index++) { - subscription_item = subscriptions.get(index); - events.concat(subscription_item.Event + "," + subscription_item.Topic - + (subscription_item.Key.length()>0 ? "," : "") - + subscription_item.Key + "; "); - } - } - return events; -} -# 3624 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_10_scripter.ino" -String ScriptUnsubscribe(const char * data, int data_len) -{ - MQTT_Subscription subscription_item; - String events; - if (data_len > 0) { - for (uint32_t index = 0; index < subscriptions.size(); index++) { - subscription_item = subscriptions.get(index); - if (subscription_item.Event.equalsIgnoreCase(data)) { - String stopic = subscription_item.Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - events = subscription_item.Event; - subscriptions.remove(index); - break; - } - } - } else { - - String stopic; - while (subscriptions.size() > 0) { - events.concat(subscriptions.get(0).Event + "; "); - stopic = subscriptions.get(0).Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - subscriptions.remove(0); - } - } - return events; -} -#endif - -#ifdef USE_SCRIPT_WEB_DISPLAY - - -void Script_Check_HTML_Setvars(void) { - - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("sv")) { - String stmp = WebServer->arg("sv"); - char cmdbuf[64]; - memset(cmdbuf,0,sizeof(cmdbuf)); - char *cp=cmdbuf; - *cp++='>'; - strncpy(cp,stmp.c_str(),sizeof(cmdbuf)-1); - char *cp1=strchr(cp,'_'); - if (!cp1) return; - *cp1=0; - char vname[32]; - strncpy(vname,cp,sizeof(vname)); - *cp1='='; - cp1++; - - struct T_INDEX ind; - uint8_t vtype; - isvar(vname,&vtype,&ind,0,0,0); - if (vtype!=NUM_RES && vtype&STYPE) { - - uint8_t tlen=strlen(cp1); - memmove(cp1+1,cp1,tlen); - *cp1='\"'; - *(cp1+tlen+1)='\"'; - } - - - execute_script(cmdbuf); - Run_Scripter(">E",2,0); - } -} - - -const char SCRIPT_MSG_BUTTONa[] PROGMEM = - ""; - -const char SCRIPT_MSG_BUTTONa_TBL[] PROGMEM = - ""; - -const char SCRIPT_MSG_BUTTONb[] PROGMEM = - "<\img>"; - -const char SCRIPT_MSG_BUT_START[] PROGMEM = - "
"; -const char SCRIPT_MSG_BUT_START_TBL[] PROGMEM = - ""; - -const char SCRIPT_MSG_BUT_STOP[] PROGMEM = - ""; -const char SCRIPT_MSG_BUT_STOP_TBL[] PROGMEM = - "
"; - -const char SCRIPT_MSG_SLIDER[] PROGMEM = - "
%s
%s%s
" - "
"; - -const char SCRIPT_MSG_CHKBOX[] PROGMEM = - "
"; - -const char SCRIPT_MSG_TEXTINP[] PROGMEM = - "
"; - -const char SCRIPT_MSG_NUMINP[] PROGMEM = - "
"; - - -void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen) { -uint32_t cnt; - for (cnt=0;cntW",-2,0); - if (web_script==99) { - char line[128]; - char tmp[128]; - uint8_t optflg=0; - char *lp=glob_script_mem.section_ptr+2; - while (lp) { - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - memcpy(line,lp,sizeof(line)); - line[sizeof(line)-1]=0; - char *cp=line; - for (uint32_t i=0; i0) { - cp="checked='checked'"; - uval=0; - } else { - cp=""; - uval=1; - } - WSContentSend_PD(SCRIPT_MSG_CHKBOX,label,(char*)cp,uval,vname); - - } else if (!strncmp(lin,"bu(",3)) { - char *lp=lin+3; - uint8_t bcnt=0; - char *found=lin; - while (bcnt<4) { - found=strstr(found,"bu("); - if (!found) break; - found+=3; - bcnt++; - } - uint8_t proz=100/bcnt; - if (!optflg && bcnt>1) proz-=2; - if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_START_TBL); - else WSContentSend_PD(SCRIPT_MSG_BUT_START); - for (uint32_t cnt=0;cnt0) { - cp=ontxt; - uval=0; - } else { - cp=offtxt; - uval=1; - } - if (bcnt>1 && cnt==bcnt-1) { - if (!optflg) proz+=2; - } - if (!optflg) { - WSContentSend_PD(SCRIPT_MSG_BUTTONa,proz,uval,vname,cp); - } else { - WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL,proz,uval,vname,cp); - } - if (bcnt>1 && cnt%s
"),tmp); - } else { - WSContentSend_PD(PSTR("{s}%s{e}"),tmp); - } - } - } - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } - } -} -#endif - -#ifdef USE_SCRIPT_JSON_EXPORT -void ScriptJsonAppend(void) { - uint8_t web_script=Run_Scripter(">J",-2,0); - if (web_script==99) { - char line[128]; - char tmp[128]; - char *lp=glob_script_mem.section_ptr+2; - while (lp) { - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - memcpy(line,lp,sizeof(line)); - line[sizeof(line)-1]=0; - char *cp=line; - for (uint32_t i=0; iB",2,0); - fast_script=Run_Scripter(">F",-2,0); - } - break; - case FUNC_EVERY_100_MSECOND: - ScripterEvery100ms(); - break; - case FUNC_EVERY_SECOND: - ScriptEverySecond(); - break; - case FUNC_COMMAND: - result = ScriptCommand(); - break; - case FUNC_SET_POWER: - case FUNC_RULES_PROCESS: - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,mqtt_data); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_RULES); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); - WebServer->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration); - -#ifdef USE_SCRIPT_FATFS - WebServer->on("/u3", HTTP_POST,[]() { WebServer->sendHeader("Location","/u3");WebServer->send(303);},script_upload); - WebServer->on("/u3", HTTP_GET,ScriptFileUploadSuccess); - WebServer->on("/upl", HTTP_GET,Script_FileUploadConfiguration); -#endif - break; -#endif - case FUNC_SAVE_BEFORE_RESTART: - if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">R",2,0); - Scripter_save_pvars(); - } - break; -#ifdef SUPPORT_MQTT_EVENT - case FUNC_MQTT_DATA: - if (bitRead(Settings.rule_enabled, 0)) { - result = ScriptMqttData(); - } - break; -#endif -#ifdef USE_SCRIPT_WEB_DISPLAY - case FUNC_WEB_SENSOR: - if (bitRead(Settings.rule_enabled, 0)) { - ScriptWebShow(); - } - break; -#endif - -#ifdef USE_SCRIPT_JSON_EXPORT - case FUNC_JSON_APPEND: - ScriptJsonAppend(); - break; -#endif - - - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_11_knx.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_11_knx.ino" -#ifdef USE_KNX -# 51 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_11_knx.ino" -#define XDRV_11 11 - -#include - -address_t KNX_physs_addr; -address_t KNX_addr; - -#define KNX_Empty 255 - -#define TOGGLE_INHIBIT_TIME 15 - -float last_temp; -float last_hum; -uint8_t toggle_inhibit; - -typedef struct __device_parameters -{ - uint8_t type; - - - - - bool show; - - bool last_state; - - callback_id_t CB_id; - - - - - -} device_parameters_t; - - -device_parameters_t device_param[] = { - { 1, false, false, KNX_Empty }, - { 2, false, false, KNX_Empty }, - { 3, false, false, KNX_Empty }, - { 4, false, false, KNX_Empty }, - { 5, false, false, KNX_Empty }, - { 6, false, false, KNX_Empty }, - { 7, false, false, KNX_Empty }, - { 8, false, false, KNX_Empty }, - { 9, false, false, KNX_Empty }, - { 10, false, false, KNX_Empty }, - { 11, false, false, KNX_Empty }, - { 12, false, false, KNX_Empty }, - { 13, false, false, KNX_Empty }, - { 14, false, false, KNX_Empty }, - { 15, false, false, KNX_Empty }, - { 16, false, false, KNX_Empty }, - { KNX_TEMPERATURE, false, false, KNX_Empty }, - { KNX_HUMIDITY , false, false, KNX_Empty }, - { KNX_ENERGY_VOLTAGE , false, false, KNX_Empty }, - { KNX_ENERGY_CURRENT , false, false, KNX_Empty }, - { KNX_ENERGY_POWER , false, false, KNX_Empty }, - { KNX_ENERGY_POWERFACTOR , false, false, KNX_Empty }, - { KNX_ENERGY_DAILY , false, false, KNX_Empty }, - { KNX_ENERGY_START , false, false, KNX_Empty }, - { KNX_ENERGY_TOTAL , false, false, KNX_Empty }, - { KNX_SLOT1 , false, false, KNX_Empty }, - { KNX_SLOT2 , false, false, KNX_Empty }, - { KNX_SLOT3 , false, false, KNX_Empty }, - { KNX_SLOT4 , false, false, KNX_Empty }, - { KNX_SLOT5 , false, false, KNX_Empty }, - { KNX_Empty, false, false, KNX_Empty} -}; - - -const char * device_param_ga[] = { - D_TIMER_OUTPUT " 1", - D_TIMER_OUTPUT " 2", - D_TIMER_OUTPUT " 3", - D_TIMER_OUTPUT " 4", - D_TIMER_OUTPUT " 5", - D_TIMER_OUTPUT " 6", - D_TIMER_OUTPUT " 7", - D_TIMER_OUTPUT " 8", - D_SENSOR_BUTTON " 1", - D_SENSOR_BUTTON " 2", - D_SENSOR_BUTTON " 3", - D_SENSOR_BUTTON " 4", - D_SENSOR_BUTTON " 5", - D_SENSOR_BUTTON " 6", - D_SENSOR_BUTTON " 7", - D_SENSOR_BUTTON " 8", - D_TEMPERATURE , - D_HUMIDITY , - D_VOLTAGE , - D_CURRENT , - D_POWERUSAGE , - D_POWER_FACTOR , - D_ENERGY_TODAY , - D_ENERGY_YESTERDAY , - D_ENERGY_TOTAL , - D_KNX_TX_SLOT " 1", - D_KNX_TX_SLOT " 2", - D_KNX_TX_SLOT " 3", - D_KNX_TX_SLOT " 4", - D_KNX_TX_SLOT " 5", - nullptr -}; - - -const char *device_param_cb[] = { - D_TIMER_OUTPUT " 1", - D_TIMER_OUTPUT " 2", - D_TIMER_OUTPUT " 3", - D_TIMER_OUTPUT " 4", - D_TIMER_OUTPUT " 5", - D_TIMER_OUTPUT " 6", - D_TIMER_OUTPUT " 7", - D_TIMER_OUTPUT " 8", - D_TIMER_OUTPUT " 1 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 2 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 3 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 4 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 5 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 6 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 7 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 8 " D_BUTTON_TOGGLE, - D_REPLY " " D_TEMPERATURE, - D_REPLY " " D_HUMIDITY, - D_REPLY " " D_VOLTAGE , - D_REPLY " " D_CURRENT , - D_REPLY " " D_POWERUSAGE , - D_REPLY " " D_POWER_FACTOR , - D_REPLY " " D_ENERGY_TODAY , - D_REPLY " " D_ENERGY_YESTERDAY , - D_REPLY " " D_ENERGY_TOTAL , - D_KNX_RX_SLOT " 1", - D_KNX_RX_SLOT " 2", - D_KNX_RX_SLOT " 3", - D_KNX_RX_SLOT " 4", - D_KNX_RX_SLOT " 5", - nullptr -}; - - -#define D_PRFX_KNX "Knx" -#define D_CMND_KNXTXCMND "Tx_Cmnd" -#define D_CMND_KNXTXVAL "Tx_Val" -#define D_CMND_KNX_ENABLED "_Enabled" -#define D_CMND_KNX_ENHANCED "_Enhanced" -#define D_CMND_KNX_PA "_PA" -#define D_CMND_KNX_GA "_GA" -#define D_CMND_KNX_CB "_CB" - -const char kKnxCommands[] PROGMEM = D_PRFX_KNX "|" - D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL "|" D_CMND_KNX_ENABLED "|" D_CMND_KNX_ENHANCED "|" D_CMND_KNX_PA "|" D_CMND_KNX_GA "|" D_CMND_KNX_CB ; - -void (* const KnxCommand[])(void) PROGMEM = { - &CmndKnxTxCmnd, &CmndKnxTxVal, &CmndKnxEnabled, &CmndKnxEnhanced, &CmndKnxPa, &CmndKnxGa, &CmndKnxCb }; - -uint8_t KNX_GA_Search( uint8_t param, uint8_t start = 0 ) -{ - for (uint32_t i = start; i < Settings.knx_GA_registered; ++i) - { - if ( Settings.knx_GA_param[i] == param ) - { - if ( Settings.knx_GA_addr[i] != 0 ) - { - if ( i >= start ) { return i; } - } - } - } - return KNX_Empty; -} - - -uint8_t KNX_CB_Search( uint8_t param, uint8_t start = 0 ) -{ - for (uint32_t i = start; i < Settings.knx_CB_registered; ++i) - { - if ( Settings.knx_CB_param[i] == param ) - { - if ( Settings.knx_CB_addr[i] != 0 ) - { - if ( i >= start ) { return i; } - } - } - } - return KNX_Empty; -} - - -void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF ) -{ - - if ( Settings.knx_GA_registered >= MAX_KNX_GA ) { return; } - if ( GA_FNUM == 0 && GA_AREA == 0 && GA_FDEF == 0 ) { return; } - - - Settings.knx_GA_param[Settings.knx_GA_registered] = GAop; - KNX_addr.ga.area = GA_FNUM; - KNX_addr.ga.line = GA_AREA; - KNX_addr.ga.member = GA_FDEF; - Settings.knx_GA_addr[Settings.knx_GA_registered] = KNX_addr.value; - - Settings.knx_GA_registered++; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " GA #%d: %s " D_TO " %d/%d/%d"), - Settings.knx_GA_registered, - device_param_ga[GAop-1], - GA_FNUM, GA_AREA, GA_FDEF ); -} - - -void KNX_DEL_GA( uint8_t GAnum ) -{ - - uint8_t dest_offset = 0; - uint8_t src_offset = 0; - uint8_t len = 0; - - - Settings.knx_GA_param[GAnum-1] = 0; - - if (GAnum == 1) - { - - src_offset = 1; - - - - len = (Settings.knx_GA_registered - 1); - } - else if (GAnum == Settings.knx_GA_registered) - { - - } - else - { - - - - - dest_offset = GAnum -1 ; - src_offset = dest_offset + 1; - len = (Settings.knx_GA_registered - GAnum); - } - - if (len > 0) - { - memmove(Settings.knx_GA_param + dest_offset, Settings.knx_GA_param + src_offset, len * sizeof(uint8_t)); - memmove(Settings.knx_GA_addr + dest_offset, Settings.knx_GA_addr + src_offset, len * sizeof(uint16_t)); - } - - Settings.knx_GA_registered--; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " GA #%d"), - GAnum ); -} - - -void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF ) -{ - - if ( Settings.knx_CB_registered >= MAX_KNX_CB ) { return; } - if ( CB_FNUM == 0 && CB_AREA == 0 && CB_FDEF == 0 ) { return; } - - - if ( device_param[CBop-1].CB_id == KNX_Empty ) - { - - device_param[CBop-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[CBop-1]); - - - - - } - - Settings.knx_CB_param[Settings.knx_CB_registered] = CBop; - KNX_addr.ga.area = CB_FNUM; - KNX_addr.ga.line = CB_AREA; - KNX_addr.ga.member = CB_FDEF; - Settings.knx_CB_addr[Settings.knx_CB_registered] = KNX_addr.value; - - knx.callback_assign( device_param[CBop-1].CB_id, KNX_addr ); - - Settings.knx_CB_registered++; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " CB #%d: %d/%d/%d " D_TO " %s"), - Settings.knx_CB_registered, - CB_FNUM, CB_AREA, CB_FDEF, - device_param_cb[CBop-1] ); -} - - -void KNX_DEL_CB( uint8_t CBnum ) -{ - uint8_t oldparam = Settings.knx_CB_param[CBnum-1]; - uint8_t dest_offset = 0; - uint8_t src_offset = 0; - uint8_t len = 0; - - - knx.callback_unassign(CBnum-1); - Settings.knx_CB_param[CBnum-1] = 0; - - if (CBnum == 1) - { - - src_offset = 1; - - - - len = (Settings.knx_CB_registered - 1); - } - else if (CBnum == Settings.knx_CB_registered) - { - - } - else - { - - - - - dest_offset = CBnum -1 ; - src_offset = dest_offset + 1; - len = (Settings.knx_CB_registered - CBnum); - } - - if (len > 0) - { - memmove(Settings.knx_CB_param + dest_offset, Settings.knx_CB_param + src_offset, len * sizeof(uint8_t)); - memmove(Settings.knx_CB_addr + dest_offset, Settings.knx_CB_addr + src_offset, len * sizeof(uint16_t)); - } - - Settings.knx_CB_registered--; - - - if ( KNX_CB_Search( oldparam ) == KNX_Empty ) { - knx.callback_deregister( device_param[oldparam-1].CB_id ); - device_param[oldparam-1].CB_id = KNX_Empty; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " CB #%d"), CBnum ); -} - - -bool KNX_CONFIG_NOT_MATCH(void) -{ - - for (uint32_t i = 0; i < KNX_MAX_device_param; ++i) - { - if ( !device_param[i].show ) { - - - - if ( KNX_GA_Search(i+1) != KNX_Empty ) { return true; } - - if ( i < 8 ) - { - if ( KNX_CB_Search(i+1) != KNX_Empty ) { return true; } - if ( KNX_CB_Search(i+9) != KNX_Empty ) { return true; } - } - - if ( i > 15 ) - { - if ( KNX_CB_Search(i+1) != KNX_Empty ) { return true; } - } - } - } - - - for (uint32_t i = 0; i < Settings.knx_GA_registered; ++i) - { - if ( Settings.knx_GA_param[i] != 0 ) - { - if ( Settings.knx_GA_addr[i] == 0 ) - { - return true; - } - } - } - for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i) - { - if ( Settings.knx_CB_param[i] != 0 ) - { - if ( Settings.knx_CB_addr[i] == 0 ) - { - return true; - } - } - } - - return false; -} - - -void KNXStart(void) -{ - knx.start(nullptr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_START)); -} - - -void KNX_INIT(void) -{ - - if (Settings.knx_GA_registered > MAX_KNX_GA) { Settings.knx_GA_registered = MAX_KNX_GA; } - if (Settings.knx_CB_registered > MAX_KNX_CB) { Settings.knx_CB_registered = MAX_KNX_CB; } - - - KNX_physs_addr.value = Settings.knx_physsical_addr; - knx.physical_address_set( KNX_physs_addr ); -# 472 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_11_knx.ino" - for (uint32_t i = 0; i < devices_present; ++i) - { - device_param[i].show = true; - } - for (uint32_t i = GPIO_SWT1; i < GPIO_SWT4 + 1; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } - } - for (uint32_t i = GPIO_KEY1; i < GPIO_KEY4 + 1; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } - } - for (uint32_t i = GPIO_SWT1_NP; i < GPIO_SWT4_NP + 1; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1_NP + 8].show = true; } - } - for (uint32_t i = GPIO_KEY1_NP; i < GPIO_KEY4_NP + 1; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1_NP + 8].show = true; } - } - if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_DSB, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } - if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } - if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } - - - if ( energy_flg != ENERGY_NONE ) { - device_param[KNX_ENERGY_POWER-1].show = true; - device_param[KNX_ENERGY_DAILY-1].show = true; - device_param[KNX_ENERGY_START-1].show = true; - device_param[KNX_ENERGY_TOTAL-1].show = true; - device_param[KNX_ENERGY_VOLTAGE-1].show = true; - device_param[KNX_ENERGY_CURRENT-1].show = true; - device_param[KNX_ENERGY_POWERFACTOR-1].show = true; - } - -#ifdef USE_RULES - device_param[KNX_SLOT1-1].show = true; - device_param[KNX_SLOT2-1].show = true; - device_param[KNX_SLOT3-1].show = true; - device_param[KNX_SLOT4-1].show = true; - device_param[KNX_SLOT5-1].show = true; -#endif - - - if (KNX_CONFIG_NOT_MATCH()) { - Settings.knx_GA_registered = 0; - Settings.knx_CB_registered = 0; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " " D_KNX_PARAMETERS)); - } - - - - - uint8_t j; - for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i) - { - j = Settings.knx_CB_param[i]; - if ( j > 0 ) - { - device_param[j-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[j-1]); - - - - KNX_addr.value = Settings.knx_CB_addr[i]; - knx.callback_assign( device_param[j-1].CB_id, KNX_addr ); - } - } -} - - -void KNX_CB_Action(message_t const &msg, void *arg) -{ - device_parameters_t *chan = (device_parameters_t *)arg; - if (!(Settings.flag.knx_enabled)) { return; } - - char tempchar[33]; - - if (msg.data_len == 1) { - - tempchar[0] = msg.data[0]; - tempchar[1] = '\0'; - } else { - - float tempvar = knx.data_to_2byte_float(msg.data); - dtostrfd(tempvar,2,tempchar); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %s " D_TO " %s"), - msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member, - (msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER, - tempchar, - device_param_cb[(chan->type)-1]); - - switch (msg.ct) - { - case KNX_CT_WRITE: - if (chan->type < 9) - { - ExecuteCommandPower(chan->type, msg.data[0], SRC_KNX); - } - else if (chan->type < 17) - { - if (!toggle_inhibit) { - ExecuteCommandPower((chan->type) -8, POWER_TOGGLE, SRC_KNX); - if (Settings.flag.knx_enable_enhancement) { - toggle_inhibit = TOGGLE_INHIBIT_TIME; - } - } - } -#ifdef USE_RULES - else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) - { - if (!toggle_inhibit) { - char command[25]; - if (msg.data_len == 1) { - - snprintf_P(command, sizeof(command), PSTR("event KNXRX_CMND%d=%d"), ((chan->type) - KNX_SLOT1 + 1 ), msg.data[0]); - } else { - - snprintf_P(command, sizeof(command), PSTR("event KNXRX_VAL%d=%s"), ((chan->type) - KNX_SLOT1 + 1 ), tempchar); - } - ExecuteCommand(command, SRC_KNX); - if (Settings.flag.knx_enable_enhancement) { - toggle_inhibit = TOGGLE_INHIBIT_TIME; - } - } - } -#endif - break; - - case KNX_CT_READ: - if (chan->type < 9) - { - knx.answer_1bit(msg.received_on, chan->last_state); - if (Settings.flag.knx_enable_enhancement) { - knx.answer_1bit(msg.received_on, chan->last_state); - knx.answer_1bit(msg.received_on, chan->last_state); - } - } - else if (chan->type == KNX_TEMPERATURE) - { - knx.answer_2byte_float(msg.received_on, last_temp); - if (Settings.flag.knx_enable_enhancement) { - knx.answer_2byte_float(msg.received_on, last_temp); - knx.answer_2byte_float(msg.received_on, last_temp); - } - } - else if (chan->type == KNX_HUMIDITY) - { - knx.answer_2byte_float(msg.received_on, last_hum); - if (Settings.flag.knx_enable_enhancement) { - knx.answer_2byte_float(msg.received_on, last_hum); - knx.answer_2byte_float(msg.received_on, last_hum); - } - } -#ifdef USE_RULES - else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) - { - if (!toggle_inhibit) { - char command[25]; - snprintf_P(command, sizeof(command), PSTR("event KNXRX_REQ%d"), ((chan->type) - KNX_SLOT1 + 1 ) ); - ExecuteCommand(command, SRC_KNX); - if (Settings.flag.knx_enable_enhancement) { - toggle_inhibit = TOGGLE_INHIBIT_TIME; - } - } - } -#endif - break; - } -} - - -void KnxUpdatePowerState(uint8_t device, power_t state) -{ - if (!(Settings.flag.knx_enabled)) { return; } - - device_param[device -1].last_state = bitRead(state, device -1); - - - uint8_t i = KNX_GA_Search(device); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - knx.write_1bit(KNX_addr, device_param[device -1].last_state); - if (Settings.flag.knx_enable_enhancement) { - knx.write_1bit(KNX_addr, device_param[device -1].last_state); - knx.write_1bit(KNX_addr, device_param[device -1].last_state); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), - device_param_ga[device -1], device_param[device -1].last_state, - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(device, i + 1); - } -} - - -void KnxSendButtonPower(uint8_t key, uint8_t device, uint8_t state) -{ - - - - - - - - if (!(Settings.flag.knx_enabled)) { return; } - - - - - uint8_t i = KNX_GA_Search(device + 8); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - knx.write_1bit(KNX_addr, !(state == 0)); - if (Settings.flag.knx_enable_enhancement) { - knx.write_1bit(KNX_addr, !(state == 0)); - knx.write_1bit(KNX_addr, !(state == 0)); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), - device_param_ga[device + 7], !(state == 0), - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(device + 8, i + 1); - } - -} - - -void KnxSensor(uint8_t sensor_type, float value) -{ - if (sensor_type == KNX_TEMPERATURE) - { - last_temp = value; - } else if (sensor_type == KNX_HUMIDITY) - { - last_hum = value; - } - - if (!(Settings.flag.knx_enabled)) { return; } - - uint8_t i = KNX_GA_Search(sensor_type); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - knx.write_2byte_float(KNX_addr, value); - if (Settings.flag.knx_enable_enhancement) { - knx.write_2byte_float(KNX_addr, value); - knx.write_2byte_float(KNX_addr, value); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s " D_SENT_TO " %d.%d.%d "), - device_param_ga[sensor_type -1], - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(sensor_type, i+1); - } -} - - - - - - -#ifdef USE_WEBSERVER -#ifdef USE_KNX_WEB_MENU -const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX; - -const char HTTP_BTN_MENU_KNX[] PROGMEM = - "

"; - -const char HTTP_FORM_KNX[] PROGMEM = - "
" - " " D_KNX_PARAMETERS " " - "
" - "
" - "" D_KNX_PHYSICAL_ADDRESS " " - " . " - " . " - "" - "

" D_KNX_PHYSICAL_ADDRESS_NOTE "

" - "" D_KNX_ENABLE "" D_KNX_ENHANCEMENT "

" - - "
" - "" D_KNX_GROUP_ADDRESS_TO_WRITE "
" - - " / " - " / " - " "; - -const char HTTP_FORM_KNX_ADD_BTN[] PROGMEM = - "

" - ""; - -const char HTTP_FORM_KNX_ADD_TABLE_ROW[] PROGMEM = - "" - ""; - -const char HTTP_FORM_KNX3[] PROGMEM = - "
%s -> %d / %d / %d

" - "
" - "" D_KNX_GROUP_ADDRESS_TO_READ "
"; - -const char HTTP_FORM_KNX4[] PROGMEM = - "-> -> ")); - WSContentSend_P(HTTP_FORM_KNX_GA, "GA_FNUM", "GA_AREA", "GA_FDEF"); - WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "GAwarning", (Settings.knx_GA_registered < MAX_KNX_GA) ? "" : "disabled", 1); - for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i) - { - if ( Settings.knx_GA_param[i] ) - { - KNX_addr.value = Settings.knx_GA_addr[i]; - WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW, device_param_ga[Settings.knx_GA_param[i]-1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, i +1); - } - } - - WSContentSend_P(HTTP_FORM_KNX3); - WSContentSend_P(HTTP_FORM_KNX_GA, "CB_FNUM", "CB_AREA", "CB_FDEF"); - WSContentSend_P(HTTP_FORM_KNX4); - - uint8_t j; - for (uint32_t i = 0; i < KNX_MAX_device_param ; i++) - { - - if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; } - if ( i == 8 ) { j = 0; } - if ( device_param[j].show ) - { - WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_cb[i]); - } - } - WSContentSend_P(PSTR(" ")); - WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "CBwarning", (Settings.knx_CB_registered < MAX_KNX_CB) ? "" : "disabled", 2); - - for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i) - { - if ( Settings.knx_CB_param[i] ) - { - KNX_addr.value = Settings.knx_CB_addr[i]; - WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW2, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings.knx_CB_param[i]-1], i +1); - } - } - WSContentSend_P(PSTR("
")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); - } - -} - - -void KNX_Save_Settings(void) -{ - String stmp; - address_t KNX_addr; - - Settings.flag.knx_enabled = WebServer->hasArg("b1"); - Settings.flag.knx_enable_enhancement = WebServer->hasArg("b2"); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ENABLED ": %d, " D_KNX_ENHANCEMENT ": %d"), - Settings.flag.knx_enabled, Settings.flag.knx_enable_enhancement ); - - stmp = WebServer->arg("area"); - KNX_addr.pa.area = stmp.toInt(); - stmp = WebServer->arg("line"); - KNX_addr.pa.line = stmp.toInt(); - stmp = WebServer->arg("member"); - KNX_addr.pa.member = stmp.toInt(); - Settings.knx_physsical_addr = KNX_addr.value; - knx.physical_address_set( KNX_addr ); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_KNX_PHYSICAL_ADDRESS ": %d.%d.%d "), - KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA: %d"), - Settings.knx_GA_registered ); - for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i) - { - KNX_addr.value = Settings.knx_GA_addr[i]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA #%d: %s " D_TO " %d/%d/%d"), - i+1, device_param_ga[Settings.knx_GA_param[i]-1], - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); - - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB: %d"), - Settings.knx_CB_registered ); - for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i) - { - KNX_addr.value = Settings.knx_CB_addr[i]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB #%d: %d/%d/%d " D_TO " %s"), - i+1, - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, - device_param_cb[Settings.knx_CB_param[i]-1] ); - } -} - -#endif -#endif - - - - - -void CmndKnxTxCmnd(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) { - - - - uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); - if (Settings.flag.knx_enable_enhancement) { - knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); - knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), - device_param_ga[XdrvMailbox.index + KNX_SLOT1 -2], !(XdrvMailbox.payload == 0), - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1, i + 1); - } - ResponseCmndIdxChar (XdrvMailbox.data ); - } -} - -void CmndKnxTxVal(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) { - - - - uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - - float tempvar = CharToFloat(XdrvMailbox.data); - dtostrfd(tempvar,2,XdrvMailbox.data); - - knx.write_2byte_float(KNX_addr, tempvar); - if (Settings.flag.knx_enable_enhancement) { - knx.write_2byte_float(KNX_addr, tempvar); - knx.write_2byte_float(KNX_addr, tempvar); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %s " D_SENT_TO " %d.%d.%d"), - device_param_ga[XdrvMailbox.index + KNX_SLOT1 -2], XdrvMailbox.data, - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1, i + 1); - } - ResponseCmndIdxChar (XdrvMailbox.data ); - } -} - -void CmndKnxEnabled(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.flag.knx_enabled = XdrvMailbox.payload; - } - ResponseCmndChar (GetStateText(Settings.flag.knx_enabled) ); -} - -void CmndKnxEnhanced(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.flag.knx_enable_enhancement = XdrvMailbox.payload; - } - ResponseCmndChar (GetStateText(Settings.flag.knx_enable_enhancement) ); -} - -void CmndKnxPa(void) -{ - if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ".") != nullptr) { - char sub_string[XdrvMailbox.data_len]; - - int pa_area = atoi(subStr(sub_string, XdrvMailbox.data, ".", 1)); - int pa_line = atoi(subStr(sub_string, XdrvMailbox.data, ".", 2)); - int pa_member = atoi(subStr(sub_string, XdrvMailbox.data, ".", 3)); - - if ( ((pa_area == 0) && (pa_line == 0) && (pa_member == 0)) - || (pa_area > 15) || (pa_line > 15) || (pa_member > 255) ) { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - - KNX_addr.pa.area = pa_area; - KNX_addr.pa.line = pa_line; - KNX_addr.pa.member = pa_member; - Settings.knx_physsical_addr = KNX_addr.value; - } - } - KNX_addr.value = Settings.knx_physsical_addr; - Response_P (PSTR("{\"%s\":\"%d.%d.%d\"}"), - XdrvMailbox.command, KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); -} - -void CmndKnxGa(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_GA)) { - if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - char sub_string[XdrvMailbox.data_len]; - - int ga_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); - int ga_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - int ga_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - int ga_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); - - if ( ((ga_area == 0) && (ga_line == 0) && (ga_member == 0)) - || (ga_area > 31) || (ga_line > 7) || (ga_member > 255) - || (ga_option < 0) || ((ga_option > KNX_MAX_device_param ) && (ga_option != KNX_Empty)) - || (!device_param[ga_option-1].show) ) { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - - KNX_addr.ga.area = ga_area; - KNX_addr.ga.line = ga_line; - KNX_addr.ga.member = ga_member; - - if ( XdrvMailbox.index > Settings.knx_GA_registered ) { - Settings.knx_GA_registered ++; - XdrvMailbox.index = Settings.knx_GA_registered; - } - - Settings.knx_GA_addr[XdrvMailbox.index -1] = KNX_addr.value; - Settings.knx_GA_param[XdrvMailbox.index -1] = ga_option; - } else { - if ( (XdrvMailbox.payload <= Settings.knx_GA_registered) && (XdrvMailbox.payload > 0) ) { - XdrvMailbox.index = XdrvMailbox.payload; - } else { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - } - if ( XdrvMailbox.index <= Settings.knx_GA_registered ) { - KNX_addr.value = Settings.knx_GA_addr[XdrvMailbox.index -1]; - Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"), - XdrvMailbox.command, XdrvMailbox.index, device_param_ga[Settings.knx_GA_param[XdrvMailbox.index-1]-1], - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); - } - } else { - ResponseCmndNumber (Settings.knx_GA_registered ); - } - } -} - -void CmndKnxCb(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_CB)) { - if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - char sub_string[XdrvMailbox.data_len]; - - int cb_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); - int cb_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - int cb_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - int cb_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); - - if ( ((cb_area == 0) && (cb_line == 0) && (cb_member == 0)) - || (cb_area > 31) || (cb_line > 7) || (cb_member > 255) - || (cb_option < 0) || ((cb_option > KNX_MAX_device_param ) && (cb_option != KNX_Empty)) - || (!device_param[cb_option-1].show) ) { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - - KNX_addr.ga.area = cb_area; - KNX_addr.ga.line = cb_line; - KNX_addr.ga.member = cb_member; - - if ( XdrvMailbox.index > Settings.knx_CB_registered ) { - Settings.knx_CB_registered ++; - XdrvMailbox.index = Settings.knx_CB_registered; - } - - Settings.knx_CB_addr[XdrvMailbox.index -1] = KNX_addr.value; - Settings.knx_CB_param[XdrvMailbox.index -1] = cb_option; - } else { - if ( (XdrvMailbox.payload <= Settings.knx_CB_registered) && (XdrvMailbox.payload > 0) ) { - XdrvMailbox.index = XdrvMailbox.payload; - } else { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - } - if ( XdrvMailbox.index <= Settings.knx_CB_registered ) { - KNX_addr.value = Settings.knx_CB_addr[XdrvMailbox.index -1]; - Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"), - XdrvMailbox.command, XdrvMailbox.index, device_param_cb[Settings.knx_CB_param[XdrvMailbox.index-1]-1], - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); - } - } else { - ResponseCmndNumber (Settings.knx_CB_registered ); - } - } -} - - - - - -bool Xdrv11(uint8_t function) -{ - bool result = false; - switch (function) { - case FUNC_LOOP: - if (!global_state.wifi_down) { knx.loop(); } - break; - case FUNC_PRE_INIT: - KNX_INIT(); - break; -#ifdef USE_WEBSERVER -#ifdef USE_KNX_WEB_MENU - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_KNX); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/kn", HandleKNXConfiguration); - break; -#endif -#endif - case FUNC_EVERY_50_MSECOND: - if (toggle_inhibit) { - toggle_inhibit--; - } - break; - case FUNC_COMMAND: - result = DecodeCommand(kKnxCommands, KnxCommand); - break; - - - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_12_home_assistant.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_12_home_assistant.ino" -#ifdef USE_HOME_ASSISTANT - -#define XDRV_12 12 - -const char HASS_DISCOVER_RELAY[] PROGMEM = - "{\"name\":\"%s\"," - "\"cmd_t\":\"%s\"," - "\"stat_t\":\"%s\"," - "\"val_tpl\":\"{{value_json.%s}}\"," - "\"pl_off\":\"%s\"," - "\"pl_on\":\"%s\"," - - "\"avty_t\":\"%s\"," - "\"pl_avail\":\"" D_ONLINE "\"," - "\"pl_not_avail\":\"" D_OFFLINE "\""; - -const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = - "{\"name\":\"%s\"," - "\"stat_t\":\"%s\"," - - "\"pl_on\":\"%s\"," - - "\"avty_t\":\"%s\"," - "\"pl_avail\":\"" D_ONLINE "\"," - "\"pl_not_avail\":\"" D_OFFLINE "\""; - -const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE[] PROGMEM = - ",\"off_delay\":1"; - -const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = - ",\"frc_upd\":true," - "\"pl_off\":\"%s\""; - -const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = - ",\"bri_cmd_t\":\"%s\"," - "\"bri_stat_t\":\"%s\"," - "\"bri_scl\":100," - "\"on_cmd_type\":\"%s\"," - "\"bri_val_tpl\":\"{{value_json." D_CMND_DIMMER "}}\""; - -const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = - ",\"rgb_cmd_t\":\"%s2\"," - "\"rgb_stat_t\":\"%s\"," - "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; - -const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = - ",\"whit_val_cmd_t\":\"%s\"," - "\"whit_val_stat_t\":\"%s\"," - "\"white_value_scale\":100," - "\"whit_val_tpl\":\"{{value_json.Channel[3]}}\""; - -const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = - ",\"clr_temp_cmd_t\":\"%s\"," - "\"clr_temp_stat_t\":\"%s\"," - "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; - -const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = - ",\"fx_cmd_t\":\"%s\"," - "\"fx_stat_t\":\"%s\"," - "\"fx_val_tpl\":\"{{value_json." D_CMND_SCHEME "}}\"," - "\"fx_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; - -const char HASS_DISCOVER_SENSOR[] PROGMEM = - "{\"name\":\"%s\"," - "\"stat_t\":\"%s\"," - "\"avty_t\":\"%s\"," - "\"pl_avail\":\"" D_ONLINE "\"," - "\"pl_not_avail\":\"" D_OFFLINE "\""; - -const char HASS_DISCOVER_SENSOR_TEMP[] PROGMEM = - ",\"unit_of_meas\":\"°%c\"," - "\"val_tpl\":\"{{value_json['%s'].Temperature}}\"," - "\"dev_cla\":\"temperature\""; - -const char HASS_DISCOVER_SENSOR_HUM[] PROGMEM = - ",\"unit_of_meas\":\"%%\"," - "\"val_tpl\":\"{{value_json['%s'].Humidity}}\"," - "\"dev_cla\":\"humidity\""; - -const char HASS_DISCOVER_SENSOR_PRESS[] PROGMEM = - ",\"unit_of_meas\":\"%s\"," - "\"val_tpl\":\"{{value_json['%s'].Pressure}}\"," - "\"dev_cla\":\"pressure\""; - - -const char HASS_DISCOVER_SENSOR_KWH[] PROGMEM = - ",\"unit_of_meas\":\"kWh\"," - "\"val_tpl\":\"{{value_json['%s'].%s}}\"," - "\"dev_cla\":\"power\""; - -const char HASS_DISCOVER_SENSOR_WATT[] PROGMEM = - ",\"unit_of_meas\":\"W\"," - "\"val_tpl\":\"{{value_json['%s'].%s}}\"," - "\"dev_cla\":\"power\""; -const char HASS_DISCOVER_SENSOR_VOLTAGE[] PROGMEM = - ",\"unit_of_meas\":\"V\"," - "\"val_tpl\":\"{{value_json['%s'].%s}}\"," - "\"dev_cla\":\"power\""; -const char HASS_DISCOVER_SENSOR_AMPERE[] PROGMEM = - ",\"unit_of_meas\":\"A\"," - "\"val_tpl\":\"{{value_json['%s'].%s}}\"," - "\"dev_cla\":\"power\""; - - -const char HASS_DISCOVER_SENSOR_ILLUMINANCE[] PROGMEM = - ",\"unit_of_meas\":\"LX\"," - "\"val_tpl\":\"{{value_json['%s'].Illuminance}}\"," - "\"dev_cla\":\"illuminance\""; - -const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = - ",\"unit_of_meas\":\" \"," - "\"val_tpl\":\"{{value_json['%s'].%s}}\""; - -const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = - ",\"json_attributes_topic\":\"%s\"," - "\"unit_of_meas\":\" \"," - "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\""; - -const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = - ",\"uniq_id\":\"%s\"," - "\"device\":{\"identifiers\":[\"%06X\"]," - "\"connections\":[[\"mac\",\"%s\"]]," - "\"name\":\"%s\"," - "\"model\":\"%s\"," - "\"sw_version\":\"%s%s\"," - "\"manufacturer\":\"Tasmota\"}"; - -const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = - ",\"uniq_id\":\"%s\"," - "\"device\":{\"identifiers\":[\"%06X\"]," - "\"connections\":[[\"mac\",\"%s\"]]}"; - -const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM = - ",\"~\":\"%s\""; - -uint8_t hass_init_step = 0; -uint8_t hass_mode = 0; -int hass_tele_period = 0; - -static void FindPrefix(char* s1, char* s2, char* out) -{ - int prefixlen = 0; - - while (s1[prefixlen] != '\0' && s2[prefixlen] != '\0' && s1[prefixlen] == s2[prefixlen]) { - prefixlen++; - } - strlcpy(out, s1, prefixlen+1); -} - -static void Shorten(char** s, char *prefix) -{ - size_t len = strlen(*s); - size_t prefixlen = strlen(prefix); - if (len > prefixlen && prefixlen != 0 && !strncmp(*s, prefix, prefixlen)) { - *s += prefixlen-1; - *s[0] = '~'; - } -} - -void TryResponseAppend_P(const char *format, ... ) -{ - va_list args; - va_start(args, format); - char dummy[2]; - int dlen = vsnprintf_P(dummy, 1, format, args); - - int mlen = strlen(mqtt_data); - int slen = sizeof(mqtt_data) -1 -mlen; - if (dlen >= slen) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: MQTT discovery failed due to too long topic or friendly name. " - "Please shorten topic and friendly name. Failed to format(%u/%u):"), dlen, slen); - va_start(args, format); - vsnprintf_P(log_data, sizeof(log_data), format, args); - AddLog(LOG_LEVEL_ERROR); - } else { - va_start(args, format); - vsnprintf_P(mqtt_data + mlen, slen, format, args); - } - va_end(args); -} - -void HAssAnnounceRelayLight(void) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char stemp3[TOPSZ]; - char unique_id[30]; - bool is_light = false; - bool is_topic_light = false; - - for (uint32_t i = 1; i <= MAX_RELAYS; i++) { - is_light = ((i == devices_present) && (light_type)); - is_topic_light = Settings.flag.hass_light || is_light; - - mqtt_data[0] = '\0'; - - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "RL" : "LI", i); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), - (is_topic_light) ? "switch" : "light", unique_id); - MqttPublish(stopic, true); - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "LI" : "RL", i); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), - (is_topic_light) ? "light" : "switch", unique_id); - - if (Settings.flag.hass_discovery && (i <= devices_present)) { - char name[33+2]; - char value_template[33]; - char prefix[TOPSZ]; - char *command_topic = stemp1; - char *state_topic = stemp2; - char *availability_topic = stemp3; - - if (i > MAX_FRIENDLYNAMES) { - snprintf_P(name, sizeof(name), PSTR("%s %d"), Settings.friendlyname[0], i); - } else { - snprintf_P(name, sizeof(name), Settings.friendlyname[i -1]); - } - GetPowerDevice(value_template, i, sizeof(value_template), Settings.flag.device_index_enable); - GetTopic_P(command_topic, CMND, mqtt_topic, value_template); - - GetTopic_P(state_topic, TELE, mqtt_topic, D_RSLT_STATE); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - FindPrefix(command_topic, state_topic, prefix); - Shorten(&command_topic, prefix); - Shorten(&state_topic, prefix); - Shorten(&availability_topic, prefix); - - Response_P(HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); - TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); - -#ifdef USE_LIGHT - if (is_light) { - char *brightness_command_topic = stemp1; - - GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); - Shorten(&brightness_command_topic, prefix); - strncpy_P(stemp3, Settings.flag.not_power_linked?PSTR("last"):PSTR("brightness"), sizeof(stemp3)); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_DIMMER, brightness_command_topic, state_topic, stemp3); - - if (Light.subtype >= LST_RGB) { - char *rgb_command_topic = stemp1; - - GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); - Shorten(&rgb_command_topic, prefix); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_COLOR, rgb_command_topic, state_topic); - - char *effect_command_topic = stemp1; - GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); - Shorten(&effect_command_topic, prefix); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_SCHEME, effect_command_topic, state_topic); - - } - if (LST_RGBW == Light.subtype) { - char *white_temp_command_topic = stemp1; - - GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); - Shorten(&white_temp_command_topic, prefix); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_WHITE, white_temp_command_topic, state_topic); - } - if ((LST_COLDWARM == Light.subtype) || (LST_RGBWC == Light.subtype)) { - char *color_temp_command_topic = stemp1; - - GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); - Shorten(&color_temp_command_topic, prefix); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_CT, color_temp_command_topic, state_topic); - } - } -#endif - TryResponseAppend_P(PSTR("}")); - } - MqttPublish(stopic, true); - } -} - -void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint8_t key, uint8_t toggle) -{ - - - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - - mqtt_data[0] = '\0'; - - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), key?"SW":"BTN", device+1); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); - - if (Settings.flag.hass_discovery && present) { - char name[33+6]; - char value_template[33]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - - if (device+1 > MAX_FRIENDLYNAMES) { - snprintf_P(name, sizeof(name), PSTR("%s %s %d"), Settings.friendlyname[0], key?"SW":"BTN", device+1); - } else { - snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[device], key?"SW":"BTN"); - } - GetPowerDevice(value_template, device+1, sizeof(value_template), - key + Settings.flag.device_index_enable); - GetTopic_P(state_topic, CMND, topic, value_template); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - FindPrefix(state_topic, availability_topic, prefix); - Shorten(&state_topic, prefix); - Shorten(&availability_topic, prefix); - Response_P(HASS_DISCOVER_BUTTON_SWITCH, name, state_topic, Settings.state_text[toggle?2:1], availability_topic); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); - if (strlen(prefix) > 0 ) TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); - if (toggle) TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_TOGGLE); - else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, Settings.state_text[0]); - - TryResponseAppend_P(PSTR("}")); - } - MqttPublish(stopic, true); -} - -void HAssAnnounceSwitches(void) -{ - char sw_topic[sizeof(Settings.switch_topic)]; - - - char *tmp = Settings.switch_topic; - Format(sw_topic, tmp, sizeof(sw_topic)); - if ((strlen(sw_topic) != 0) && strcmp(sw_topic, "0")) { - for (uint32_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) { - uint8_t switch_present = 0; - uint8_t toggle = 1; - - if (pin[GPIO_SWT1 + switch_index] < 99) { - switch_present = 1; - } - - - if (Settings.switchmode[switch_index] == FOLLOW || Settings.switchmode[switch_index] == FOLLOW_INV || - Settings.flag3.button_switch_force_local || - !strcmp(mqtt_topic, sw_topic) || !strcmp(Settings.mqtt_grptopic, sw_topic)) - { - toggle = 0; - } - - HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 1, toggle); - } - } -} - -void HAssAnnounceButtons(void) -{ - char key_topic[sizeof(Settings.button_topic)]; - - - char *tmp = Settings.button_topic; - Format(key_topic, tmp, sizeof(key_topic)); - if ((strlen(key_topic) != 0) && strcmp(key_topic, "0")) { - for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { - uint8_t button_present = 0; - uint8_t toggle = 1; - - if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { - button_present = 1; - } else { - if (pin[GPIO_KEY1 + button_index] < 99) { - button_present = 1; - } - } - - - if (Settings.flag3.button_switch_force_local || - !strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) - { - toggle = 0; - } - - HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 0, toggle); - } - } -} - -void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - - - mqtt_data[0] = '\0'; - - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP.getChipId(), sensorname, subsensortype); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); - - if (Settings.flag.hass_discovery) { - char name[33+42]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - - snprintf_P(name, sizeof(name), PSTR("%s %s %s"), Settings.friendlyname[0], sensorname, subsensortype); - GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - FindPrefix(state_topic, availability_topic, prefix); - Shorten(&state_topic, prefix); - Shorten(&availability_topic, prefix); - - Response_P(HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); - TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); - if (!strcmp_P(subsensortype, PSTR(D_JSON_TEMPERATURE))) { - TryResponseAppend_P(HASS_DISCOVER_SENSOR_TEMP, TempUnit(), sensorname); - } else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { - TryResponseAppend_P(HASS_DISCOVER_SENSOR_HUM, sensorname); - } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE))) { - TryResponseAppend_P(HASS_DISCOVER_SENSOR_PRESS, PressureUnit().c_str(), sensorname); - } else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL)) - || !strcmp_P(subsensortype, PSTR(D_JSON_TODAY)) - || !strcmp_P(subsensortype, PSTR(D_JSON_YESTERDAY))){ - TryResponseAppend_P(HASS_DISCOVER_SENSOR_KWH, sensorname, subsensortype); - } else if (!strcmp_P(subsensortype, PSTR(D_JSON_POWERUSAGE))){ - TryResponseAppend_P(HASS_DISCOVER_SENSOR_WATT, sensorname, subsensortype); - } else if (!strcmp_P(subsensortype, PSTR(D_JSON_VOLTAGE))){ - TryResponseAppend_P(HASS_DISCOVER_SENSOR_VOLTAGE, sensorname, subsensortype); - } else if (!strcmp_P(subsensortype, PSTR(D_JSON_CURRENT))){ - TryResponseAppend_P(HASS_DISCOVER_SENSOR_AMPERE, sensorname, subsensortype); - } else if (!strcmp_P(subsensortype, PSTR(D_JSON_ILLUMINANCE))){ - TryResponseAppend_P(HASS_DISCOVER_SENSOR_ILLUMINANCE, sensorname, subsensortype); - } - else { - TryResponseAppend_P(HASS_DISCOVER_SENSOR_ANY, sensorname, subsensortype); - } - TryResponseAppend_P(PSTR("}")); - } - MqttPublish(stopic, true); -} - -void HAssAnnounceSensors(void) -{ - uint8_t hass_xsns_index = 0; - - do { - mqtt_data[0] = '\0'; - int tele_period_save = tele_period; - tele_period = 2; - XsnsNextCall(FUNC_JSON_APPEND, hass_xsns_index); - tele_period = tele_period_save; - - char sensordata[256]; - strlcpy(sensordata, mqtt_data, sizeof(sensordata)); - - if (strlen(sensordata)) { - sensordata[0] = '{'; - snprintf_P(sensordata, sizeof(sensordata), PSTR("%s}"), sensordata); - - - - - - StaticJsonBuffer<500> jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(sensordata); - if (!root.success()) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: failed to parse '%s'"), sensordata); - continue; - } - for (auto sensor : root) { - const char* sensorname = sensor.key; - JsonObject& sensors = sensor.value.as(); - if (!sensors.success()) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: failed to parse '%s'"), sensordata); - continue; - } - for (auto subsensor : sensors) { - HAssAnnounceSensor(sensorname, subsensor.key); - } - } - } - yield(); - } while (hass_xsns_index != 0); -} - -void HAssAnnounceStatusSensor(void) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - - - mqtt_data[0] = '\0'; - - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_status"), ESP.getChipId()); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); - - if (Settings.flag.hass_discovery) { - char name[33+7]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - - snprintf_P(name, sizeof(name), PSTR("%s status"), Settings.friendlyname[0]); - GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - FindPrefix(state_topic, availability_topic, prefix); - Shorten(&state_topic, prefix); - Shorten(&availability_topic, prefix); - - Response_P(HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); - TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(), WiFi.macAddress().c_str(), - Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image); - TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); - TryResponseAppend_P(PSTR("}")); - } - MqttPublish(stopic, true); -} - -void HAssPublishStatus(void) -{ - Response_P(PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"," - "\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," - "\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"," - "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d," - "\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_CMND_IPADDRESS "\":\"%s\"," - "\"" D_JSON_RSSI "\":\"%d\",\"LoadAvg\":%lu}"), - my_version, my_image, GetBuildDateAndTime().c_str(), ESP.getSdkVersion(), ModuleName().c_str(), - GetResetReason().c_str(), GetUptime().c_str(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), - Settings.bootcount, Settings.save_flag, WiFi.localIP().toString().c_str(), - WifiGetRssiAsQuality(WiFi.RSSI()), loop_load_avg); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE)); -} - -void HAssDiscovery(void) -{ - - if (Settings.flag.hass_discovery) { - Settings.flag.mqtt_response = 0; - Settings.flag.decimal_text = 1; - Settings.flag3.hass_tele_on_power = 1; - - if (strcmp_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"))) { - strncpy_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"), sizeof(Settings.mqtt_fulltopic)); - restart_flag = 2; - return; - } - } - - if (Settings.flag.hass_discovery || (1 == hass_mode)) { - - HAssAnnounceRelayLight(); - - - HAssAnnounceButtons(); - - - HAssAnnounceSwitches(); - - - HAssAnnounceSensors(); - - - HAssAnnounceStatusSensor(); - } -} - -void HAssDiscover(void) -{ - hass_mode = 1; - hass_init_step = 1; -} - - - - - -bool Xdrv12(uint8_t function) -{ - bool result = false; - - if (Settings.flag.mqtt_enabled) { - switch (function) { - case FUNC_MQTT_INIT: - hass_mode = 0; - hass_init_step = 2; - break; - case FUNC_EVERY_SECOND: - if (hass_init_step) { - hass_init_step--; - if (!hass_init_step) { - HAssDiscovery(); - } - } else if (Settings.flag.hass_discovery && Settings.tele_period) { - hass_tele_period++; - if (hass_tele_period >= Settings.tele_period) { - hass_tele_period = 0; - - mqtt_data[0] = '\0'; - HAssPublishStatus(); - } - } - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_13_display.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_13_display.ino" -#if defined(USE_I2C) || defined(USE_SPI) -#ifdef USE_DISPLAY - -#define XDRV_13 13 - -#include -#include - -Renderer *renderer; - -enum ColorType { COLOR_BW, COLOR_COLOR }; - -#ifndef MAXBUTTONS -#define MAXBUTTONS 16 -#endif - -#ifdef USE_TOUCH_BUTTONS -VButton *buttons[MAXBUTTONS]; -#endif - - - -uint16_t fg_color = 1; -uint16_t bg_color = 0; -uint8_t color_type = COLOR_BW; -uint8_t auto_draw=1; - -const uint8_t DISPLAY_MAX_DRIVERS = 16; -const uint8_t DISPLAY_MAX_COLS = 44; -const uint8_t DISPLAY_MAX_ROWS = 32; - -const uint8_t DISPLAY_LOG_ROWS = 32; - -#define D_PRFX_DISPLAY "Display" -#define D_CMND_DISP_ADDRESS "Address" -#define D_CMND_DISP_COLS "Cols" -#define D_CMND_DISP_DIMMER "Dimmer" -#define D_CMND_DISP_MODE "Mode" -#define D_CMND_DISP_MODEL "Model" -#define D_CMND_DISP_REFRESH "Refresh" -#define D_CMND_DISP_ROWS "Rows" -#define D_CMND_DISP_SIZE "Size" -#define D_CMND_DISP_FONT "Font" -#define D_CMND_DISP_ROTATE "Rotate" -#define D_CMND_DISP_TEXT "Text" -#define D_CMND_DISP_WIDTH "Width" -#define D_CMND_DISP_HEIGHT "Height" - -enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_EVERY_50_MSECOND, FUNC_DISPLAY_EVERY_SECOND, - FUNC_DISPLAY_MODEL, FUNC_DISPLAY_MODE, FUNC_DISPLAY_POWER, - FUNC_DISPLAY_CLEAR, FUNC_DISPLAY_DRAW_FRAME, - FUNC_DISPLAY_DRAW_HLINE, FUNC_DISPLAY_DRAW_VLINE, FUNC_DISPLAY_DRAW_LINE, - FUNC_DISPLAY_DRAW_CIRCLE, FUNC_DISPLAY_FILL_CIRCLE, - FUNC_DISPLAY_DRAW_RECTANGLE, FUNC_DISPLAY_FILL_RECTANGLE, - FUNC_DISPLAY_TEXT_SIZE, FUNC_DISPLAY_FONT_SIZE, FUNC_DISPLAY_ROTATION, FUNC_DISPLAY_DRAW_STRING, FUNC_DISPLAY_ONOFF }; - -enum DisplayInitModes { DISPLAY_INIT_MODE, DISPLAY_INIT_PARTIAL, DISPLAY_INIT_FULL }; - -const char kDisplayCommands[] PROGMEM = D_PRFX_DISPLAY "|" - "|" D_CMND_DISP_MODEL "|" D_CMND_DISP_WIDTH "|" D_CMND_DISP_HEIGHT "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|" - D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|" D_CMND_DISP_SIZE "|" D_CMND_DISP_FONT "|" - D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS ; - -void (* const DisplayCommand[])(void) PROGMEM = { - &CmndDisplay, &CmndDisplayModel, &CmndDisplayWidth, &CmndDisplayHeight, &CmndDisplayMode, &CmndDisplayRefresh, - &CmndDisplayDimmer, &CmndDisplayColumns, &CmndDisplayRows, &CmndDisplaySize, &CmndDisplayFont, - &CmndDisplayRotate, &CmndDisplayText, &CmndDisplayAddress }; - -char *dsp_str; - -uint16_t dsp_x; -uint16_t dsp_y; -uint16_t dsp_x2; -uint16_t dsp_y2; -uint16_t dsp_rad; -uint16_t dsp_color; -int16_t dsp_len; -int16_t disp_xpos = 0; -int16_t disp_ypos = 0; - -uint8_t disp_power = 0; -uint8_t disp_device = 0; -uint8_t disp_refresh = 1; -uint8_t disp_autodraw = 1; -uint8_t dsp_init; -uint8_t dsp_font; -uint8_t dsp_flag; -uint8_t dsp_on; - -#ifdef USE_DISPLAY_MODES1TO5 - -char **disp_log_buffer; -char **disp_screen_buffer; -char disp_temp[2]; - -uint8_t disp_log_buffer_cols = 0; -uint8_t disp_log_buffer_idx = 0; -uint8_t disp_log_buffer_ptr = 0; -uint8_t disp_screen_buffer_cols = 0; -uint8_t disp_screen_buffer_rows = 0; -bool disp_subscribed = false; - -#endif - - - -void DisplayInit(uint8_t mode) -{ - if (renderer) { - renderer->DisplayInit(mode,Settings.display_size,Settings.display_rotate,Settings.display_font); - } - else { - dsp_init = mode; - XdspCall(FUNC_DISPLAY_INIT); - } -} - -void DisplayClear(void) -{ - XdspCall(FUNC_DISPLAY_CLEAR); -} - -void DisplayDrawHLine(uint16_t x, uint16_t y, int16_t len, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_len = len; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_HLINE); -} - -void DisplayDrawVLine(uint16_t x, uint16_t y, int16_t len, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_len = len; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_VLINE); -} - -void DisplayDrawLine(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_x2 = x2; - dsp_y2 = y2; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_LINE); -} - -void DisplayDrawCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_rad = rad; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_CIRCLE); -} - -void DisplayDrawFilledCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_rad = rad; - dsp_color = color; - XdspCall(FUNC_DISPLAY_FILL_CIRCLE); -} - -void DisplayDrawRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_x2 = x2; - dsp_y2 = y2; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_RECTANGLE); -} - -void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_x2 = x2; - dsp_y2 = y2; - dsp_color = color; - XdspCall(FUNC_DISPLAY_FILL_RECTANGLE); -} - -void DisplayDrawFrame(void) -{ - XdspCall(FUNC_DISPLAY_DRAW_FRAME); -} - -void DisplaySetSize(uint8_t size) -{ - Settings.display_size = size &3; - XdspCall(FUNC_DISPLAY_TEXT_SIZE); -} - -void DisplaySetFont(uint8_t font) -{ - Settings.display_font = font &3; - XdspCall(FUNC_DISPLAY_FONT_SIZE); -} - -void DisplaySetRotation(uint8_t rotation) -{ - Settings.display_rotate = rotation &3; - XdspCall(FUNC_DISPLAY_ROTATION); -} - -void DisplayDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ - dsp_x = x; - dsp_y = y; - dsp_str = str; - dsp_color = color; - dsp_flag = flag; - XdspCall(FUNC_DISPLAY_DRAW_STRING); -} - -void DisplayOnOff(uint8_t on) -{ - dsp_on = on; - XdspCall(FUNC_DISPLAY_ONOFF); -} - - - - -uint8_t fatoiv(char *cp,float *res) { - uint8_t index=0; - *res=CharToFloat(cp); - while (*cp) { - if ((*cp>='0' && *cp<='9') || (*cp=='-') || (*cp=='.')) { - cp++; - index++; - } else { - break; - } - } - return index; -} - - -uint8_t atoiv(char *cp, int16_t *res) -{ - uint8_t index = 0; - *res = atoi(cp); - while (*cp) { - if ((*cp>='0' && *cp<='9') || (*cp=='-')) { - cp++; - index++; - } else { - break; - } - } - return index; -} - - -uint8_t atoiV(char *cp, uint16_t *res) -{ - uint8_t index = 0; - *res = atoi(cp); - while (*cp) { - if (*cp>='0' && *cp<='9') { - cp++; - index++; - } else { - break; - } - } - return index; -} - - -void alignright(char *string) { - uint16_t slen=strlen(string); - uint16_t len=slen; - while (len) { - - if (string[len-1]!=' ') { - break; - } - len--; - } - uint16_t diff=slen-len; - if (diff>0) { - - memmove(&string[diff],string,len); - memset(string,' ',diff); - } -} - -char *get_string(char *buff,uint8_t len,char *cp) { -uint8_t index=0; - while (*cp!=':') { - buff[index]=*cp++; - index++; - if (index>=len) break; - } - buff[index]=0; - cp++; - return cp; -} - -#define ESCAPE_CHAR '~' - - -void decode_te(char *line) { - char sbuf[3],*cp; - while (*line) { - if (*line==ESCAPE_CHAR) { - cp=line+1; - if (*cp!=0 && *cp==ESCAPE_CHAR) { - - memmove(cp,cp+1,strlen(cp)); - } else { - - if (strlen(cp)<2) { - - return; - } - - sbuf[0]=*(cp); - sbuf[1]=*(cp+1); - sbuf[2]=0; - *line=strtol(sbuf,0,16); - - memmove(cp,cp+2,strlen(cp)-1); - } - } - line++; - } -} - - - -#define DISPLAY_BUFFER_COLS 128 - -void DisplayText(void) -{ - uint8_t lpos; - uint8_t escape = 0; - uint8_t var; - int16_t lin = 0; - int16_t col = 0; - int16_t fill = 0; - int16_t temp; - int16_t temp1; - float ftemp; - - char linebuf[DISPLAY_BUFFER_COLS]; - char *dp = linebuf; - char *cp = XdrvMailbox.data; - - memset(linebuf, ' ', sizeof(linebuf)); - linebuf[sizeof(linebuf)-1] = 0; - *dp = 0; - - while (*cp) { - if (!escape) { - - if (*cp == '[') { - escape = 1; - cp++; - - if ((uint32_t)dp - (uint32_t)linebuf) { - if (!fill) { *dp = 0; } - if (col > 0 && lin > 0) { - - if (!renderer) DisplayDrawStringAt(col, lin, linebuf, fg_color, 1); - else renderer->DrawStringAt(col, lin, linebuf, fg_color, 1); - } else { - - if (!renderer) DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); - else renderer->DrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); - } - memset(linebuf, ' ', sizeof(linebuf)); - linebuf[sizeof(linebuf)-1] = 0; - dp = linebuf; - } - } else { - - if (dp < (linebuf + DISPLAY_BUFFER_COLS)) { *dp++ = *cp++; } - } - } else { - - if (*cp == ']') { - escape = 0; - cp++; - } else { - - switch (*cp++) { - case 'z': - - if (!renderer) DisplayClear(); - else renderer->fillScreen(bg_color); - disp_xpos = 0; - disp_ypos = 0; - col = 0; - lin = 0; - break; - case 'i': - - DisplayInit(DISPLAY_INIT_PARTIAL); - break; - case 'I': - - DisplayInit(DISPLAY_INIT_FULL); - break; - case 'o': - if (!renderer) { - DisplayOnOff(0); - } else { - renderer->DisplayOnff(0); - } - break; - case 'O': - if (!renderer) { - DisplayOnOff(1); - } else { - renderer->DisplayOnff(1); - } - break; - case 'x': - - var = atoiv(cp, &disp_xpos); - cp += var; - break; - case 'y': - - var = atoiv(cp, &disp_ypos); - cp += var; - break; - case 'l': - - var = atoiv(cp, &lin); - cp += var; - - break; - case 'c': - - var = atoiv(cp, &col); - cp += var; - - break; - case 'C': - - if (*cp=='i') { - - cp++; - var = atoiv(cp, &temp); - if (renderer) ftemp=renderer->GetColorFromIndex(temp); - } else { - - var = fatoiv(cp,&ftemp); - } - fg_color=ftemp; - cp += var; - if (renderer) renderer->setTextColor(fg_color,bg_color); - break; - case 'B': - - if (*cp=='i') { - - cp++; - var = atoiv(cp, &temp); - if (renderer) ftemp=renderer->GetColorFromIndex(temp); - } else { - var = fatoiv(cp,&ftemp); - } - bg_color=ftemp; - cp += var; - if (renderer) renderer->setTextColor(fg_color,bg_color); - break; - case 'p': - - var = atoiv(cp, &fill); - cp += var; - linebuf[fill] = 0; - break; -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) - case 'P': - { char *ep=strchr(cp,':'); - if (ep) { - *ep=0; - ep++; - Draw_RGB_Bitmap(cp,disp_xpos,disp_ypos); - cp=ep; - } - } - break; -#endif - case 'h': - - var = atoiv(cp, &temp); - cp += var; - if (temp < 0) { - if (renderer) renderer->writeFastHLine(disp_xpos + temp, disp_ypos, -temp, fg_color); - else DisplayDrawHLine(disp_xpos + temp, disp_ypos, -temp, fg_color); - } else { - if (renderer) renderer->writeFastHLine(disp_xpos, disp_ypos, temp, fg_color); - else DisplayDrawHLine(disp_xpos, disp_ypos, temp, fg_color); - } - disp_xpos += temp; - break; - case 'v': - - var = atoiv(cp, &temp); - cp += var; - if (temp < 0) { - if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos + temp, -temp, fg_color); - else DisplayDrawVLine(disp_xpos, disp_ypos + temp, -temp, fg_color); - } else { - if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos, temp, fg_color); - else DisplayDrawVLine(disp_xpos, disp_ypos, temp, fg_color); - } - disp_ypos += temp; - break; - case 'L': - - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - if (renderer) renderer->writeLine(disp_xpos, disp_ypos, temp, temp1, fg_color); - else DisplayDrawLine(disp_xpos, disp_ypos, temp, temp1, fg_color); - disp_xpos += temp; - disp_ypos += temp1; - break; - case 'k': - - var = atoiv(cp, &temp); - cp += var; - if (renderer) renderer->drawCircle(disp_xpos, disp_ypos, temp, fg_color); - else DisplayDrawCircle(disp_xpos, disp_ypos, temp, fg_color); - break; - case 'K': - - var = atoiv(cp, &temp); - cp += var; - if (renderer) renderer->fillCircle(disp_xpos, disp_ypos, temp, fg_color); - else DisplayDrawFilledCircle(disp_xpos, disp_ypos, temp, fg_color); - break; - case 'r': - - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - if (renderer) renderer->drawRect(disp_xpos, disp_ypos, temp, temp1, fg_color); - else DisplayDrawRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color); - break; - case 'R': - - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - if (renderer) renderer->fillRect(disp_xpos, disp_ypos, temp, temp1, fg_color); - else DisplayDrawFilledRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color); - break; - case 'u': - - { int16_t rad; - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - cp++; - var = atoiv(cp, &rad); - cp += var; - if (renderer) renderer->drawRoundRect(disp_xpos, disp_ypos, temp, temp1, rad, fg_color); - - } - break; - case 'U': - - { int16_t rad; - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - cp++; - var = atoiv(cp, &rad); - cp += var; - if (renderer) renderer->fillRoundRect(disp_xpos, disp_ypos, temp, temp1, rad, fg_color); - - } - break; - - case 't': - if (*cp=='S') { - cp++; - if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { - snprintf_P(dp, 9, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - dp += 8; - } - } else { - if (dp < (linebuf + DISPLAY_BUFFER_COLS) -5) { - snprintf_P(dp, 6, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute); - dp += 5; - } - } - break; - case 'T': - if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { - snprintf_P(dp, 9, PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year%2000); - dp += 8; - } - break; - case 'd': - - if (renderer) renderer->Updateframe(); - else DisplayDrawFrame(); - break; - case 'D': - - auto_draw=*cp&3; - if (renderer) renderer->setDrawMode(auto_draw>>1); - cp += 1; - break; - case 's': - - if (renderer) renderer->setTextSize(*cp&7); - else DisplaySetSize(*cp&3); - cp += 1; - break; - case 'f': - - if (renderer) renderer->setTextFont(*cp&7); - else DisplaySetFont(*cp&7); - cp += 1; - break; - case 'a': - - if (renderer) renderer->setRotation(*cp&3); - else DisplaySetRotation(*cp&3); - cp+=1; - break; - -#ifdef USE_GRAPH - case 'G': - - if (*cp=='d') { - cp++; - var=atoiv(cp,&temp); - cp+=var; - cp++; - var=atoiv(cp,&temp1); - cp+=var; - RedrawGraph(temp,temp1); - break; - } -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) - if (*cp=='s') { - cp++; - var=atoiv(cp,&temp); - cp+=var; - cp++; - - char bbuff[128]; - cp=get_string(bbuff,sizeof(bbuff),cp); - Save_graph(temp,bbuff); - break; - } - if (*cp=='r') { - cp++; - var=atoiv(cp,&temp); - cp+=var; - cp++; - - char bbuff[128]; - cp=get_string(bbuff,sizeof(bbuff),cp); - Restore_graph(temp,bbuff); - break; - } -#endif - { int16_t num,gxp,gyp,gxs,gys,dec,icol; - float ymin,ymax; - var=atoiv(cp,&num); - cp+=var; - cp++; - var=atoiv(cp,&gxp); - cp+=var; - cp++; - var=atoiv(cp,&gyp); - cp+=var; - cp++; - var=atoiv(cp,&gxs); - cp+=var; - cp++; - var=atoiv(cp,&gys); - cp+=var; - cp++; - var=atoiv(cp,&dec); - cp+=var; - cp++; - var=fatoiv(cp,&ymin); - cp+=var; - cp++; - var=fatoiv(cp,&ymax); - cp+=var; - if (color_type==COLOR_COLOR) { - - cp++; - var=atoiv(cp,&icol); - cp+=var; - } else { - icol=0; - } - DefineGraph(num,gxp,gyp,gxs,gys,dec,ymin,ymax,icol); - } - break; - case 'g': - { float temp; - int16_t num; - var=atoiv(cp,&num); - cp+=var; - cp++; - var=fatoiv(cp,&temp); - cp+=var; - AddValue(num,temp); - } - break; -#endif - -#ifdef USE_AWATCH - case 'w': - var = atoiv(cp, &temp); - cp += var; - DrawAClock(temp); - break; -#endif - -#ifdef USE_TOUCH_BUTTONS - case 'b': - { int16_t num,gxp,gyp,gxs,gys,outline,fill,textcolor,textsize; - var=atoiv(cp,&num); - cp+=var; - cp++; - uint8_t bflags=num>>8; - num=num%MAXBUTTONS; - var=atoiv(cp,&gxp); - cp+=var; - cp++; - var=atoiv(cp,&gyp); - cp+=var; - cp++; - var=atoiv(cp,&gxs); - cp+=var; - cp++; - var=atoiv(cp,&gys); - cp+=var; - cp++; - var=atoiv(cp,&outline); - cp+=var; - cp++; - var=atoiv(cp,&fill); - cp+=var; - cp++; - var=atoiv(cp,&textcolor); - cp+=var; - cp++; - var=atoiv(cp,&textsize); - cp+=var; - cp++; - - char bbuff[32]; - cp=get_string(bbuff,sizeof(bbuff),cp); - - if (buttons[num]) { - delete buttons[num]; - } - if (renderer) { - buttons[num]= new VButton(); - if (buttons[num]) { - buttons[num]->vpower=bflags; - buttons[num]->initButtonUL(renderer,gxp,gyp,gxs,gys,renderer->GetColorFromIndex(outline),\ - renderer->GetColorFromIndex(fill),renderer->GetColorFromIndex(textcolor),bbuff,textsize); - if (!bflags) { - - buttons[num]->xdrawButton(bitRead(power,num)); - } else { - - buttons[num]->vpower&=0x7f; - buttons[num]->xdrawButton(buttons[num]->vpower&0x80); - } - } - } - } - break; -#endif - default: - - Response_P(PSTR("Unknown Escape")); - goto exit; - break; - } - } - } - } - exit: - - decode_te(linebuf); - if ((uint32_t)dp - (uint32_t)linebuf) { - if (!fill) *dp = 0; - else linebuf[abs(fill)] = 0; - if (fill<0) { - - alignright(linebuf); - } - if (col > 0 && lin > 0) { - - if (!renderer) DisplayDrawStringAt(col, lin, linebuf, fg_color, 1); - else renderer->DrawStringAt(col, lin, linebuf, fg_color, 1); - } else { - - if (!renderer) DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); - else renderer->DrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); - } - } - - if (auto_draw&1) { - if (renderer) renderer->Updateframe(); - else DisplayDrawFrame(); - } -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void DisplayClearScreenBuffer(void) -{ - if (disp_screen_buffer_cols) { - for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { - memset(disp_screen_buffer[i], 0, disp_screen_buffer_cols); - } - } -} - -void DisplayFreeScreenBuffer(void) -{ - if (disp_screen_buffer != nullptr) { - for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { - if (disp_screen_buffer[i] != nullptr) { free(disp_screen_buffer[i]); } - } - free(disp_screen_buffer); - disp_screen_buffer_cols = 0; - disp_screen_buffer_rows = 0; - } -} - -void DisplayAllocScreenBuffer(void) -{ - if (!disp_screen_buffer_cols) { - disp_screen_buffer_rows = Settings.display_rows; - disp_screen_buffer = (char**)malloc(sizeof(*disp_screen_buffer) * disp_screen_buffer_rows); - if (disp_screen_buffer != nullptr) { - for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { - disp_screen_buffer[i] = (char*)malloc(sizeof(*disp_screen_buffer[i]) * (Settings.display_cols[0] +1)); - if (disp_screen_buffer[i] == nullptr) { - DisplayFreeScreenBuffer(); - break; - } - } - } - if (disp_screen_buffer != nullptr) { - disp_screen_buffer_cols = Settings.display_cols[0] +1; - DisplayClearScreenBuffer(); - } - } -} - -void DisplayReAllocScreenBuffer(void) -{ - DisplayFreeScreenBuffer(); - DisplayAllocScreenBuffer(); -} - -void DisplayFillScreen(uint32_t line) -{ - uint32_t len = disp_screen_buffer_cols - strlen(disp_screen_buffer[line]); - if (len) { - memset(disp_screen_buffer[line] + strlen(disp_screen_buffer[line]), 0x20, len); - disp_screen_buffer[line][disp_screen_buffer_cols -1] = 0; - } -} - - - -void DisplayClearLogBuffer(void) -{ - if (disp_log_buffer_cols) { - for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { - memset(disp_log_buffer[i], 0, disp_log_buffer_cols); - } - } -} - -void DisplayFreeLogBuffer(void) -{ - if (disp_log_buffer != nullptr) { - for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { - if (disp_log_buffer[i] != nullptr) { free(disp_log_buffer[i]); } - } - free(disp_log_buffer); - disp_log_buffer_cols = 0; - } -} - -void DisplayAllocLogBuffer(void) -{ - if (!disp_log_buffer_cols) { - disp_log_buffer = (char**)malloc(sizeof(*disp_log_buffer) * DISPLAY_LOG_ROWS); - if (disp_log_buffer != nullptr) { - for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { - disp_log_buffer[i] = (char*)malloc(sizeof(*disp_log_buffer[i]) * (Settings.display_cols[0] +1)); - if (disp_log_buffer[i] == nullptr) { - DisplayFreeLogBuffer(); - break; - } - } - } - if (disp_log_buffer != nullptr) { - disp_log_buffer_cols = Settings.display_cols[0] +1; - DisplayClearLogBuffer(); - } - } -} - -void DisplayReAllocLogBuffer(void) -{ - DisplayFreeLogBuffer(); - DisplayAllocLogBuffer(); -} - -void DisplayLogBufferAdd(char* txt) -{ - if (disp_log_buffer_cols) { - strlcpy(disp_log_buffer[disp_log_buffer_idx], txt, disp_log_buffer_cols); - disp_log_buffer_idx++; - if (DISPLAY_LOG_ROWS == disp_log_buffer_idx) { disp_log_buffer_idx = 0; } - } -} - -char* DisplayLogBuffer(char temp_code) -{ - char* result = nullptr; - if (disp_log_buffer_cols) { - if (disp_log_buffer_idx != disp_log_buffer_ptr) { - result = disp_log_buffer[disp_log_buffer_ptr]; - disp_log_buffer_ptr++; - if (DISPLAY_LOG_ROWS == disp_log_buffer_ptr) { disp_log_buffer_ptr = 0; } - - char *pch = strchr(result, '~'); - if (pch != nullptr) { result[pch - result] = temp_code; } - } - } - return result; -} - -void DisplayLogBufferInit(void) -{ - if (Settings.display_mode) { - disp_log_buffer_idx = 0; - disp_log_buffer_ptr = 0; - disp_refresh = Settings.display_refresh; - - snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit()); - - DisplayReAllocLogBuffer(); - - char buffer[40]; - snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s%s"), my_version, my_image); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings.display_mode); - DisplayLogBufferAdd(buffer); - - snprintf_P(buffer, sizeof(buffer), PSTR(D_CMND_HOSTNAME " %s"), my_hostname); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), Settings.sta_ssid[Settings.sta_active]); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), WiFi.macAddress().c_str()); - DisplayLogBufferAdd(buffer); - if (!global_state.wifi_down) { - snprintf_P(buffer, sizeof(buffer), PSTR("IP %s"), WiFi.localIP().toString().c_str()); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_RSSI " %d%%"), WifiGetRssiAsQuality(WiFi.RSSI())); - DisplayLogBufferAdd(buffer); - } - } -} - - - - - -enum SensorQuantity { - JSON_TEMPERATURE, - JSON_HUMIDITY, JSON_LIGHT, JSON_NOISE, JSON_AIRQUALITY, - JSON_PRESSURE, JSON_PRESSUREATSEALEVEL, - JSON_ILLUMINANCE, - JSON_GAS, - JSON_YESTERDAY, JSON_TOTAL, JSON_TODAY, - JSON_PERIOD, - JSON_POWERFACTOR, JSON_COUNTER, JSON_ANALOG_INPUT, JSON_UV_LEVEL, - JSON_CURRENT, - JSON_VOLTAGE, - JSON_POWERUSAGE, - JSON_CO2, - JSON_FREQUENCY }; -const char kSensorQuantity[] PROGMEM = - D_JSON_TEMPERATURE "|" - D_JSON_HUMIDITY "|" D_JSON_LIGHT "|" D_JSON_NOISE "|" D_JSON_AIRQUALITY "|" - D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" - D_JSON_ILLUMINANCE "|" - D_JSON_GAS "|" - D_JSON_YESTERDAY "|" D_JSON_TOTAL "|" D_JSON_TODAY "|" - D_JSON_PERIOD "|" - D_JSON_POWERFACTOR "|" D_JSON_COUNTER "|" D_JSON_ANALOG_INPUT "|" D_JSON_UV_LEVEL "|" - D_JSON_CURRENT "|" - D_JSON_VOLTAGE "|" - D_JSON_POWERUSAGE "|" - D_JSON_CO2 "|" - D_JSON_FREQUENCY ; - -void DisplayJsonValue(const char* topic, const char* device, const char* mkey, const char* value) -{ - char quantity[TOPSZ]; - char buffer[Settings.display_cols[0] +1]; - char spaces[Settings.display_cols[0]]; - char source[Settings.display_cols[0] - Settings.display_cols[1]]; - char svalue[Settings.display_cols[1] +1]; - -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("DisplayJsonValue")); -#endif - - memset(spaces, 0x20, sizeof(spaces)); - spaces[sizeof(spaces) -1] = '\0'; - snprintf_P(source, sizeof(source), PSTR("%s%s%s%s"), topic, (strlen(topic))?"/":"", mkey, spaces); - - int quantity_code = GetCommandCode(quantity, sizeof(quantity), mkey, kSensorQuantity); - if ((-1 == quantity_code) || !strcmp_P(mkey, S_RSLT_POWER)) { - return; - } - if (JSON_TEMPERATURE == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s~%s"), value, disp_temp); - } - else if ((quantity_code >= JSON_HUMIDITY) && (quantity_code <= JSON_AIRQUALITY)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s%%"), value); - } - else if ((quantity_code >= JSON_PRESSURE) && (quantity_code <= JSON_PRESSUREATSEALEVEL)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PRESSURE), value); - } - else if (JSON_ILLUMINANCE == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_LUX), value); - } - else if (JSON_GAS == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOOHM), value); - } - else if ((quantity_code >= JSON_YESTERDAY) && (quantity_code <= JSON_TODAY)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOWATTHOUR), value); - } - else if (JSON_PERIOD == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATTHOUR), value); - } - else if ((quantity_code >= JSON_POWERFACTOR) && (quantity_code <= JSON_UV_LEVEL)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s"), value); - } - else if (JSON_CURRENT == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_AMPERE), value); - } - else if (JSON_VOLTAGE == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_VOLT), value); - } - else if (JSON_POWERUSAGE == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATT), value); - } - else if (JSON_CO2 == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PARTS_PER_MILLION), value); - } - else if (JSON_FREQUENCY == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_HERTZ), value); - } - snprintf_P(buffer, sizeof(buffer), PSTR("%s %s"), source, svalue); - - - - DisplayLogBufferAdd(buffer); -} - -void DisplayAnalyzeJson(char *topic, char *json) -{ -# 1133 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_13_display.ino" - const char *tempunit; - - - - String jsonStr = json; - - StaticJsonBuffer<1024> jsonBuf; - JsonObject &root = jsonBuf.parseObject(jsonStr); - if (root.success()) { - - tempunit = root[D_JSON_TEMPERATURE_UNIT]; - if (tempunit) { - snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%s"), tempunit); - - } - - for (JsonObject::iterator it = root.begin(); it != root.end(); ++it) { - JsonVariant value = it->value; - if (value.is()) { - JsonObject& Object2 = value; - for (JsonObject::iterator it2 = Object2.begin(); it2 != Object2.end(); ++it2) { - JsonVariant value2 = it2->value; - if (value2.is()) { - JsonObject& Object3 = value2; - for (JsonObject::iterator it3 = Object3.begin(); it3 != Object3.end(); ++it3) { - const char* value = it3->value; - if (value != nullptr) { - DisplayJsonValue(topic, it->key, it3->key, value); - } - } - } else { - const char* value = it2->value; - if (value != nullptr) { - DisplayJsonValue(topic, it->key, it2->key, value); - } - } - } - } else { - const char* value = it->value; - if (value != nullptr) { - DisplayJsonValue(topic, it->key, it->key, value); - } - } - } - } -} - -void DisplayMqttSubscribe(void) -{ - - - - - - - if (Settings.display_model && (Settings.display_mode &0x04)) { - - char stopic[TOPSZ]; - char ntopic[TOPSZ]; - - ntopic[0] = '\0'; - strlcpy(stopic, Settings.mqtt_fulltopic, sizeof(stopic)); - char *tp = strtok(stopic, "/"); - while (tp != nullptr) { - if (!strcmp_P(tp, MQTT_TOKEN_PREFIX)) { - break; - } - strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); - tp = strtok(nullptr, "/"); - } - strncat(ntopic, Settings.mqtt_prefix[2], sizeof(ntopic) - strlen(ntopic) -1); - strncat_P(ntopic, PSTR("/#"), sizeof(ntopic) - strlen(ntopic) -1); - MqttSubscribe(ntopic); - disp_subscribed = true; - } else { - disp_subscribed = false; - } -} - -bool DisplayMqttData(void) -{ - if (disp_subscribed) { - char stopic[TOPSZ]; - - snprintf_P(stopic, sizeof(stopic) , PSTR("%s/"), Settings.mqtt_prefix[2]); - char *tp = strstr(XdrvMailbox.topic, stopic); - if (tp) { - if (Settings.display_mode &0x04) { - tp = tp + strlen(stopic); - char *topic = strtok(tp, "/"); - DisplayAnalyzeJson(topic, XdrvMailbox.data); - } - return true; - } - } - return false; -} - -void DisplayLocalSensor(void) -{ - if ((Settings.display_mode &0x02) && (0 == tele_period)) { - char no_topic[1] = { 0 }; - - DisplayAnalyzeJson(no_topic, mqtt_data); - } -} - -#endif - - - - - -void DisplayInitDriver(void) -{ - XdspCall(FUNC_DISPLAY_INIT_DRIVER); - - if (renderer) { - renderer->setTextFont(Settings.display_font); - renderer->setTextSize(Settings.display_size); - } - - - - - if (Settings.display_model) { - devices_present++; - disp_device = devices_present; - -#ifndef USE_DISPLAY_MODES1TO5 - Settings.display_mode = 0; -#else - DisplayLogBufferInit(); -#endif - } -} - -void DisplaySetPower(void) -{ - disp_power = bitRead(XdrvMailbox.index, disp_device -1); - -AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DSP: Power %d"), disp_power); - - if (Settings.display_model) { - if (!renderer) { - XdspCall(FUNC_DISPLAY_POWER); - } else { - renderer->DisplayOnff(disp_power); - } - } -} - - - - - -void CmndDisplay(void) -{ - Response_P(PSTR("{\"" D_PRFX_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_WIDTH "\":%d,\"" D_CMND_DISP_HEIGHT "\":%d,\"" - D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" D_CMND_DISP_SIZE "\":%d,\"" D_CMND_DISP_FONT "\":%d,\"" - D_CMND_DISP_ROTATE "\":%d,\"" D_CMND_DISP_REFRESH "\":%d,\"" D_CMND_DISP_COLS "\":[%d,%d],\"" D_CMND_DISP_ROWS "\":%d}}"), - Settings.display_model, Settings.display_width, Settings.display_height, - Settings.display_mode, Settings.display_dimmer, Settings.display_size, Settings.display_font, - Settings.display_rotate, Settings.display_refresh, Settings.display_cols[0], Settings.display_cols[1], Settings.display_rows); -} - -void CmndDisplayModel(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < DISPLAY_MAX_DRIVERS)) { - uint32_t last_display_model = Settings.display_model; - Settings.display_model = XdrvMailbox.payload; - if (XdspCall(FUNC_DISPLAY_MODEL)) { - restart_flag = 2; - } else { - Settings.display_model = last_display_model; - } - } - ResponseCmndNumber(Settings.display_model); -} - -void CmndDisplayWidth(void) -{ - if (XdrvMailbox.payload > 0) { - if (XdrvMailbox.payload != Settings.display_width) { - Settings.display_width = XdrvMailbox.payload; - restart_flag = 2; - } - } - ResponseCmndNumber(Settings.display_width); -} - -void CmndDisplayHeight(void) -{ - if (XdrvMailbox.payload > 0) { - if (XdrvMailbox.payload != Settings.display_height) { - Settings.display_height = XdrvMailbox.payload; - restart_flag = 2; - } - } - ResponseCmndNumber(Settings.display_height); -} - -void CmndDisplayMode(void) -{ -#ifdef USE_DISPLAY_MODES1TO5 - - - - - - - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { - uint32_t last_display_mode = Settings.display_mode; - Settings.display_mode = XdrvMailbox.payload; - - if (disp_subscribed != (Settings.display_mode &0x04)) { - restart_flag = 2; - } else { - if (last_display_mode && !Settings.display_mode) { - DisplayInit(DISPLAY_INIT_MODE); - if (renderer) renderer->fillScreen(bg_color); - else DisplayClear(); - } else { - DisplayLogBufferInit(); - DisplayInit(DISPLAY_INIT_MODE); - } - } - } -#endif - ResponseCmndNumber(Settings.display_mode); -} - -void CmndDisplayDimmer(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Settings.display_dimmer = ((XdrvMailbox.payload +1) * 100) / 666; - if (Settings.display_dimmer && !(disp_power)) { - ExecuteCommandPower(disp_device, POWER_ON, SRC_DISPLAY); - } - else if (!Settings.display_dimmer && disp_power) { - ExecuteCommandPower(disp_device, POWER_OFF, SRC_DISPLAY); - } - if (renderer) renderer->dim(Settings.display_dimmer); - } - ResponseCmndNumber(Settings.display_dimmer); -} - -void CmndDisplaySize(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { - Settings.display_size = XdrvMailbox.payload; - if (renderer) renderer->setTextSize(Settings.display_size); - else DisplaySetSize(Settings.display_size); - } - ResponseCmndNumber(Settings.display_size); -} - -void CmndDisplayFont(void) -{ - if ((XdrvMailbox.payload >=0) && (XdrvMailbox.payload <= 4)) { - Settings.display_font = XdrvMailbox.payload; - if (renderer) renderer->setTextFont(Settings.display_font); - else DisplaySetFont(Settings.display_font); - } - ResponseCmndNumber(Settings.display_font); -} - -void CmndDisplayRotate(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { - if (Settings.display_rotate != XdrvMailbox.payload) { -# 1416 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_13_display.ino" - Settings.display_rotate = XdrvMailbox.payload; - DisplayInit(DISPLAY_INIT_MODE); -#ifdef USE_DISPLAY_MODES1TO5 - DisplayLogBufferInit(); -#endif - } - } - ResponseCmndNumber(Settings.display_rotate); -} - -void CmndDisplayText(void) -{ - if (disp_device && XdrvMailbox.data_len > 0) { -#ifndef USE_DISPLAY_MODES1TO5 - DisplayText(); -#else - if (!Settings.display_mode) { - DisplayText(); - } else { - DisplayLogBufferAdd(XdrvMailbox.data); - } -#endif - ResponseCmndChar(XdrvMailbox.data); - } -} - -void CmndDisplayAddress(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { - Settings.display_address[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.display_address[XdrvMailbox.index -1]); - } -} - -void CmndDisplayRefresh(void) -{ - if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) { - Settings.display_refresh = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.display_refresh); -} - -void CmndDisplayColumns(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) { - Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload; -#ifdef USE_DISPLAY_MODES1TO5 - if (1 == XdrvMailbox.index) { - DisplayLogBufferInit(); - DisplayReAllocScreenBuffer(); - } -#endif - } - ResponseCmndIdxNumber(Settings.display_cols[XdrvMailbox.index -1]); - } -} - -void CmndDisplayRows(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) { - Settings.display_rows = XdrvMailbox.payload; -#ifdef USE_DISPLAY_MODES1TO5 - DisplayLogBufferInit(); - DisplayReAllocScreenBuffer(); -#endif - } - ResponseCmndNumber(Settings.display_rows); -} - - - - - -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) -void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp) { - if (!renderer) return; - - - File fp; - fp=SD.open(file,FILE_READ); - if (!fp) return; - uint16_t xsize; - fp.read((uint8_t*)&xsize,2); - uint16_t ysize; - fp.read((uint8_t*)&ysize,2); - -#if 1 -#define XBUFF 128 - uint16_t xdiv=xsize/XBUFF; - renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize); - for(int16_t j=0; j=2) renderer->pushColors(rgb,len/2,true); - } - OsWatchLoop(); - } - renderer->setAddrWindow(0,0,0,0); -#else - for(int16_t j=0; jwritePixel(xp+i,yp,rgb); - } - delay(0); - OsWatchLoop(); - yp++; - } -#endif - fp.close(); -} -#endif - -#ifdef USE_AWATCH -#define MINUTE_REDUCT 4 - -#ifndef pi -#define pi 3.14159265359 -#endif - - -void DrawAClock(uint16_t rad) { - if (!renderer) return; - float frad=rad; - uint16_t hred=frad/3.0; - renderer->fillCircle(disp_xpos, disp_ypos, rad, bg_color); - renderer->drawCircle(disp_xpos, disp_ypos, rad, fg_color); - renderer->fillCircle(disp_xpos, disp_ypos, 4, fg_color); - for (uint8_t count=0; count<60; count+=5) { - float p1=((float)count*(pi/30)-(pi/2)); - uint8_t len; - if ((count%15)==0) { - len=4; - } else { - len=2; - } - renderer->writeLine(disp_xpos+((float)(rad-len)*cosf(p1)), disp_ypos+((float)(rad-len)*sinf(p1)), disp_xpos+(frad*cosf(p1)), disp_ypos+(frad*sinf(p1)), fg_color); - } - - - float hour=((float)RtcTime.hour*60.0+(float)RtcTime.minute)/60.0; - float temp=(hour*(pi/6.0)-(pi/2.0)); - renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-hred)*cosf(temp),disp_ypos+(frad-hred)*sinf(temp), fg_color); - - - temp=((float)RtcTime.minute*(pi/30.0)-(pi/2.0)); - renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-MINUTE_REDUCT)*cosf(temp),disp_ypos+(frad-MINUTE_REDUCT)*sinf(temp), fg_color); -} -#endif - - -#ifdef USE_GRAPH - -typedef union { - uint8_t data; - struct { - uint8_t overlay : 1; - uint8_t draw : 1; - uint8_t nu3 : 1; - uint8_t nu4 : 1; - uint8_t nu5 : 1; - uint8_t nu6 : 1; - uint8_t nu7 : 1; - uint8_t nu8 : 1; - }; -} GFLAGS; - -struct GRAPH { - uint16_t xp; - uint16_t yp; - uint16_t xs; - uint16_t ys; - float ymin; - float ymax; - float range; - uint32_t x_time; - uint32_t last_ms; - uint32_t last_ms_redrawn; - int16_t decimation; - uint16_t dcnt; - uint32_t summ; - uint16_t xcnt; - uint8_t *values; - uint8_t xticks; - uint8_t yticks; - uint8_t last_val; - uint8_t color_index; - GFLAGS flags; -}; - - -struct GRAPH *graph[NUM_GRAPHS]; - -#define TICKLEN 4 -void ClrGraph(uint16_t num) { - struct GRAPH *gp=graph[num]; - - uint16_t xticks=gp->xticks; - uint16_t yticks=gp->yticks; - uint16_t count; - - - if (gp->flags.overlay) return; - - renderer->fillRect(gp->xp+1,gp->yp+1,gp->xs-2,gp->ys-2,bg_color); - - if (xticks) { - float cxp=gp->xp,xd=(float)gp->xs/(float)xticks; - for (count=0; countwriteFastVLine(cxp,gp->yp+gp->ys-TICKLEN,TICKLEN,fg_color); - cxp+=xd; - } - } - if (yticks) { - if (gp->ymin<0 && gp->ymax>0) { - - float cxp=0; - float czp=gp->yp+(gp->ymax/gp->range); - while (cxpxs) { - renderer->writeFastHLine(gp->xp+cxp,czp,2,fg_color); - cxp+=6.0; - } - - float cyp=0,yd=gp->ys/yticks; - for (count=0; countgp->yp) { - renderer->writeFastHLine(gp->xp,czp-cyp,TICKLEN,fg_color); - renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,czp-cyp,TICKLEN,fg_color); - } - if ((czp+cyp)<(gp->yp+gp->ys)) { - renderer->writeFastHLine(gp->xp,czp+cyp,TICKLEN,fg_color); - renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,czp+cyp,TICKLEN,fg_color); - } - cyp+=yd; - } - } else { - float cyp=gp->yp,yd=gp->ys/yticks; - for (count=0; countwriteFastHLine(gp->xp,cyp,TICKLEN,fg_color); - renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,cyp,TICKLEN,fg_color); - cyp+=yd; - } - } - } -} - - -void DefineGraph(uint16_t num,uint16_t xp,uint16_t yp,int16_t xs,uint16_t ys,int16_t dec,float ymin, float ymax,uint8_t icol) { - if (!renderer) return; - uint8_t rflg=0; - if (xs<0) { - rflg=1; - xs=abs(xs); - } - struct GRAPH *gp; - uint16_t count; - uint16_t index=num%NUM_GRAPHS; - if (!graph[index]) { - gp=(struct GRAPH*)calloc(sizeof(struct GRAPH),1); - if (!gp) return; - graph[index]=gp; - } else { - gp=graph[index]; - if (rflg) { - RedrawGraph(index,1); - return; - } - } - - - gp->xticks=(num>>4)&0x3f; - gp->yticks=(num>>10)&0x3f; - gp->xp=xp; - gp->yp=yp; - gp->xs=xs; - gp->ys=ys; - if (!dec) dec=1; - gp->decimation=dec; - if (dec>0) { - - gp->x_time=((float)dec*60000.0)/(float)xs; - gp->last_ms=millis()+gp->x_time; - } - gp->ymin=ymin; - gp->ymax=ymax; - gp->range=(ymax-ymin)/ys; - gp->xcnt=0; - gp->dcnt=0; - gp->summ=0; - if (gp->values) free(gp->values); - gp->values=(uint8_t*) calloc(1,xs+2); - if (!gp->values) { - free(gp); - graph[index]=0; - return; - } - - gp->values[0]=0; - - gp->last_ms_redrawn=millis(); - - if (!icol) icol=1; - gp->color_index=icol; - gp->flags.overlay=0; - gp->flags.draw=1; - - - if (index>0) { - for (uint8_t count=0; countxp==gp1->xp) && (gp->yp==gp1->yp)) { - gp->flags.overlay=1; - break; - } - } - } - } - - - renderer->drawRect(xp,yp,xs,ys,fg_color); - - ClrGraph(index); - -} - - -void DisplayCheckGraph() { - int16_t count; - struct GRAPH *gp; - for (count=0;countdecimation>0) { - - while (millis()>gp->last_ms) { - gp->last_ms+=gp->x_time; - uint8_t val; - if (gp->dcnt) { - val=gp->summ/gp->dcnt; - gp->dcnt=0; - gp->summ=0; - gp->last_val=val; - } else { - val=gp->last_val; - } - AddGraph(count,val); - } - } - } - } -} - - -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) -#include - -void Save_graph(uint8_t num, char *path) { - if (!renderer) return; - uint16_t index=num%NUM_GRAPHS; - struct GRAPH *gp=graph[index]; - if (!gp) return; - File fp; - SD.remove(path); - fp=SD.open(path,FILE_WRITE); - if (!fp) return; - char str[32]; - sprintf_P(str,PSTR("%d\t%d\t%d\t"),gp->xcnt,gp->xs,gp->ys); - fp.print(str); - dtostrfd(gp->ymin,2,str); - fp.print(str); - fp.print("\t"); - dtostrfd(gp->ymax,2,str); - fp.print(str); - fp.print("\t"); - for (uint32_t count=0;countxs;count++) { - dtostrfd(gp->values[count],0,str); - fp.print(str); - fp.print("\t"); - } - fp.print("\n"); - fp.close(); -} -void Restore_graph(uint8_t num, char *path) { - if (!renderer) return; - uint16_t index=num%NUM_GRAPHS; - struct GRAPH *gp=graph[index]; - if (!gp) return; - File fp; - fp=SD.open(path,FILE_READ); - if (!fp) return; - char vbuff[32]; - char *cp=vbuff; - uint8_t buf[2]; - uint8_t findex=0; - - for (uint32_t count=0;count<=gp->xs+4;count++) { - cp=vbuff; - findex=0; - while (fp.available()) { - fp.read(buf,1); - if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { - break; - } else { - *cp++=buf[0]; - findex++; - if (findex>=sizeof(vbuff)-1) break; - } - } - *cp=0; - if (count<=4) { - if (count==0) gp->xcnt=atoi(vbuff); - } else { - gp->values[count-5]=atoi(vbuff); - } - } - fp.close(); - RedrawGraph(num,1); -} -#endif - -void RedrawGraph(uint8_t num, uint8_t flags) { - uint16_t index=num%NUM_GRAPHS; - struct GRAPH *gp=graph[index]; - if (!gp) return; - if (!flags) { - gp->flags.draw=0; - return; - } - if (!renderer) return; - - gp->flags.draw=1; - uint16_t linecol=fg_color; - - if (color_type==COLOR_COLOR) { - linecol=renderer->GetColorFromIndex(gp->color_index); - } - - if (!gp->flags.overlay) { - - renderer->drawRect(gp->xp,gp->yp,gp->xs,gp->ys,fg_color); - - ClrGraph(index); - } - - for (uint16_t count=0;countxs-1;count++) { - renderer->writeLine(gp->xp+count,gp->yp+gp->ys-gp->values[count]-1,gp->xp+count+1,gp->yp+gp->ys-gp->values[count+1]-1,linecol); - } -} - - -void AddGraph(uint8_t num,uint8_t val) { - struct GRAPH *gp=graph[num]; - if (!renderer) return; - - uint16_t linecol=fg_color; - if (color_type==COLOR_COLOR) { - linecol=renderer->GetColorFromIndex(gp->color_index); - } - gp->xcnt++; - if (gp->xcnt>gp->xs) { - gp->xcnt=gp->xs; - int16_t count; - - for (count=0;countxs-1;count++) { - gp->values[count]=gp->values[count+1]; - } - gp->values[gp->xcnt-1]=val; - - if (!gp->flags.draw) return; - - - if (millis()-gp->last_ms_redrawn>1000) { - gp->last_ms_redrawn=millis(); - - if (!gp->flags.overlay) { - - renderer->drawRect(gp->xp,gp->yp,gp->xs,gp->ys,fg_color); - - ClrGraph(num); - } - - for (count=0;countxs-1;count++) { - renderer->writeLine(gp->xp+count,gp->yp+gp->ys-gp->values[count]-1,gp->xp+count+1,gp->yp+gp->ys-gp->values[count+1]-1,linecol); - } - } - } else { - - gp->values[gp->xcnt]=val; - if (!gp->flags.draw) return; - renderer->writeLine(gp->xp+gp->xcnt-1,gp->yp+gp->ys-gp->values[gp->xcnt-1]-1,gp->xp+gp->xcnt,gp->yp+gp->ys-gp->values[gp->xcnt]-1,linecol); - } -} - - - -void AddValue(uint8_t num,float fval) { - - num=num%NUM_GRAPHS; - struct GRAPH *gp=graph[num]; - if (!gp) return; - - if (fval>gp->ymax) fval=gp->ymax; - if (fvalymin) fval=gp->ymin; - - int16_t val; - val=(fval-gp->ymin)/gp->range; - - if (val>gp->ys-1) val=gp->ys-1; - if (val<0) val=0; - - - gp->summ+=val; - gp->dcnt++; - - - if (gp->decimation<0) { - if (gp->dcnt>=-gp->decimation) { - gp->dcnt=0; - - val=gp->summ/-gp->decimation; - gp->summ=0; - - AddGraph(num,val); - } - } -} -#endif - - - - - -bool Xdrv13(uint8_t function) -{ - bool result = false; - - if ((i2c_flg || spi_flg || soft_spi_flg) && XdspPresent()) { - switch (function) { - case FUNC_PRE_INIT: - DisplayInitDriver(); -#ifdef USE_GRAPH - for (uint8_t count=0;count - -TasmotaSerial *MP3Player; - - - - - -#define D_CMND_MP3 "MP3" - -const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}"; -const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}"; -const char kMP3_Commands[] PROGMEM = "Track|Play|Pause|Stop|Volume|EQ|Device|Reset|DAC"; - - - - - -enum MP3_Commands { - CMND_MP3_TRACK, - CMND_MP3_PLAY, - CMND_MP3_PAUSE, - CMND_MP3_STOP, - CMND_MP3_VOLUME, - CMND_MP3_EQ, - CMND_MP3_DEVICE, - CMND_MP3_RESET, - CMND_MP3_DAC }; - - - - - - -#define MP3_CMD_RESET_VALUE 0 - -#define MP3_CMD_TRACK 0x03 -#define MP3_CMD_PLAY 0x0d -#define MP3_CMD_PAUSE 0x0e -#define MP3_CMD_STOP 0x16 -#define MP3_CMD_VOLUME 0x06 -#define MP3_CMD_EQ 0x07 -#define MP3_CMD_DEVICE 0x09 -#define MP3_CMD_RESET 0x0C -#define MP3_CMD_DAC 0x1A - - - - - - -uint16_t MP3_Checksum(uint8_t *array) -{ - uint16_t checksum = 0; - for (uint32_t i = 0; i < 6; i++) { - checksum += array[i]; - } - checksum = checksum^0xffff; - return (checksum+1); -} - - - - - - -void MP3PlayerInit(void) { - MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3_DFR562]); - - if (MP3Player->begin(9600)) { - MP3Player->flush(); - delay(1000); - MP3_CMD(MP3_CMD_RESET, MP3_CMD_RESET_VALUE); - delay(3000); - MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); - } - return; -} -# 159 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_14_mp3.ino" -void MP3_CMD(uint8_t mp3cmd,uint16_t val) { - uint8_t i = 0; - uint8_t cmd[10] = {0x7e,0xff,6,0,0,0,0,0,0,0xef}; - cmd[3] = mp3cmd; - cmd[4] = 0; - cmd[5] = val>>8; - cmd[6] = val; - uint16_t chks = MP3_Checksum(&cmd[1]); - cmd[7] = chks>>8; - cmd[8] = chks; - MP3Player->write(cmd, sizeof(cmd)); - delay(1000); - if (mp3cmd == MP3_CMD_RESET) { - MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); - } - return; -} - - - - - -bool MP3PlayerCmd(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t disp_len = strlen(D_CMND_MP3); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMP3_Commands); - - switch (command_code) { - case CMND_MP3_TRACK: - case CMND_MP3_VOLUME: - case CMND_MP3_EQ: - case CMND_MP3_DEVICE: - case CMND_MP3_DAC: - - if (XdrvMailbox.data_len > 0) { - if (command_code == CMND_MP3_TRACK) { MP3_CMD(MP3_CMD_TRACK, XdrvMailbox.payload); } - if (command_code == CMND_MP3_VOLUME) { MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100); } - if (command_code == CMND_MP3_EQ) { MP3_CMD(MP3_CMD_EQ, XdrvMailbox.payload); } - if (command_code == CMND_MP3_DEVICE) { MP3_CMD(MP3_CMD_DEVICE, XdrvMailbox.payload); } - if (command_code == CMND_MP3_DAC) { MP3_CMD(MP3_CMD_DAC, XdrvMailbox.payload); } - } - Response_P(S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_MP3_PLAY: - case CMND_MP3_PAUSE: - case CMND_MP3_STOP: - case CMND_MP3_RESET: - - if (command_code == CMND_MP3_PLAY) { MP3_CMD(MP3_CMD_PLAY, 0); } - if (command_code == CMND_MP3_PAUSE) { MP3_CMD(MP3_CMD_PAUSE, 0); } - if (command_code == CMND_MP3_STOP) { MP3_CMD(MP3_CMD_STOP, 0); } - if (command_code == CMND_MP3_RESET) { MP3_CMD(MP3_CMD_RESET, 0); } - Response_P(S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); - break; - default: - - serviced = false; - break; - } - } else { - return false; - } - return serviced; -} - - - - - -bool Xdrv14(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_MP3_DFR562] < 99) { - switch (function) { - case FUNC_PRE_INIT: - MP3PlayerInit(); - break; - case FUNC_COMMAND: - result = MP3PlayerCmd(); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_15_pca9685.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_15_pca9685.ino" -#ifdef USE_I2C -#ifdef USE_PCA9685 - -#define XDRV_15 15 - -#define PCA9685_REG_MODE1 0x00 -#define PCA9685_REG_LED0_ON_L 0x06 -#define PCA9685_REG_PRE_SCALE 0xFE - -#ifndef USE_PCA9685_FREQ - #define USE_PCA9685_FREQ 50 -#endif - -uint8_t pca9685_detected = 0; -uint16_t pca9685_freq = USE_PCA9685_FREQ; -uint16_t pca9685_pin_pwm_value[16]; - -void PCA9685_Detect(void) -{ - if (pca9685_detected) { return; } - - uint8_t buffer; - - if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x20); - if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { - if (0x20 == buffer) { - pca9685_detected = 1; - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "PCA9685", USE_PCA9685_ADDR); - PCA9685_Reset(); - } - } - } -} - -void PCA9685_Reset(void) -{ - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x80); - PCA9685_SetPWMfreq(USE_PCA9685_FREQ); - for (uint32_t pin=0;pin<16;pin++) { - PCA9685_SetPWM(pin,0,false); - pca9685_pin_pwm_value[pin] = 0; - } - Response_P(PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); -} - -void PCA9685_SetPWMfreq(double freq) { - - - - - if (freq > 23 && freq < 1527) { - pca9685_freq=freq; - } else { - pca9685_freq=50; - } - uint8_t pre_scale_osc = round(25000000/(4096*pca9685_freq))-1; - if (1526 == pca9685_freq) pre_scale_osc=0xFF; - uint8_t current_mode1 = I2cRead8(USE_PCA9685_ADDR, PCA9685_REG_MODE1); - uint8_t sleep_mode1 = (current_mode1&0x7F) | 0x10; - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, sleep_mode1); - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_PRE_SCALE, pre_scale_osc); - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, current_mode1 | 0xA0); -} - -void PCA9685_SetPWM_Reg(uint8_t pin, uint16_t on, uint16_t off) { - uint8_t led_reg = PCA9685_REG_LED0_ON_L + 4 * pin; - uint32_t led_data = 0; - I2cWrite8(USE_PCA9685_ADDR, led_reg, on); - I2cWrite8(USE_PCA9685_ADDR, led_reg+1, (on >> 8)); - I2cWrite8(USE_PCA9685_ADDR, led_reg+2, off); - I2cWrite8(USE_PCA9685_ADDR, led_reg+3, (off >> 8)); -} - -void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted) { - if (4096 == pwm) { - PCA9685_SetPWM_Reg(pin, 4096, 0); - } else { - PCA9685_SetPWM_Reg(pin, 0, pwm); - } - pca9685_pin_pwm_value[pin] = pwm; -} - -bool PCA9685_Command(void) -{ - bool serviced = true; - bool validpin = false; - uint8_t paramcount = 0; - if (XdrvMailbox.data_len > 0) { - paramcount=1; - } else { - serviced = false; - return serviced; - } - char sub_string[XdrvMailbox.data_len]; - for (uint32_t ca=0;ca 1) { - uint16_t new_freq = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if ((new_freq >= 24) && (new_freq <= 1526)) { - PCA9685_SetPWMfreq(new_freq); - Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}"),new_freq); - return serviced; - } - } else { - Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i}}"),pca9685_freq); - return serviced; - } - } - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"PWM")) { - if (paramcount > 1) { - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if (paramcount > 2) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "ON")) { - PCA9685_SetPWM(pin, 4096, false); - Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,4096); - serviced = true; - return serviced; - } - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "OFF")) { - PCA9685_SetPWM(pin, 0, false); - Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,0); - serviced = true; - return serviced; - } - uint16_t pwm = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - if ((pin >= 0 && pin <= 15) && (pwm >= 0 && pwm <= 4096)) { - PCA9685_SetPWM(pin, pwm, false); - Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,pwm); - serviced = true; - return serviced; - } - } - } - } - return serviced; -} - -void PCA9685_OutputTelemetry(bool telemetry) { - if (0 == pca9685_detected) { return; } - ResponseTime_P(PSTR(",\"PCA9685\":{\"PWM_FREQ\":%i,"),pca9685_freq); - for (uint32_t pin=0;pin<16;pin++) { - ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pca9685_pin_pwm_value[pin]); - } - ResponseAppend_P(PSTR("\"END\":1}}")); - if (telemetry) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - } -} - -bool Xdrv15(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_EVERY_SECOND: - PCA9685_Detect(); - if (tele_period == 0) { - PCA9685_OutputTelemetry(true); - } - break; - case FUNC_COMMAND_DRIVER: - if (XDRV_15 == XdrvMailbox.index) { - result = PCA9685_Command(); - } - break; - default: - break; - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_16_tuyamcu.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_16_tuyamcu.ino" -#ifdef USE_LIGHT -#ifdef USE_TUYA_MCU - -#define XDRV_16 16 -#define XNRG_16 16 - -#ifndef TUYA_DIMMER_ID -#define TUYA_DIMMER_ID 0 -#endif - -#define TUYA_CMD_HEARTBEAT 0x00 -#define TUYA_CMD_QUERY_PRODUCT 0x01 -#define TUYA_CMD_MCU_CONF 0x02 -#define TUYA_CMD_WIFI_STATE 0x03 -#define TUYA_CMD_WIFI_RESET 0x04 -#define TUYA_CMD_WIFI_SELECT 0x05 -#define TUYA_CMD_SET_DP 0x06 -#define TUYA_CMD_STATE 0x07 -#define TUYA_CMD_QUERY_STATE 0x08 - -#define TUYA_TYPE_BOOL 0x01 -#define TUYA_TYPE_VALUE 0x02 - -#define TUYA_BUFFER_SIZE 256 - -#include - -TasmotaSerial *TuyaSerial = nullptr; - -struct TUYA { - uint8_t new_dim = 0; - bool ignore_dim = false; - uint8_t cmd_status = 0; - uint8_t cmd_checksum = 0; - uint8_t data_len = 0; - int8_t wifi_state = -2; - uint8_t heartbeat_timer = 0; -#ifdef USE_ENERGY_SENSOR - uint32_t lastPowerCheckTime = 0; -#endif - char *buffer = nullptr; - int byte_counter = 0; -} Tuya; - - -enum TuyaSupportedFunctions { - TUYA_MCU_FUNC_NONE, - TUYA_MCU_FUNC_SWT1 = 1, - TUYA_MCU_FUNC_SWT2, - TUYA_MCU_FUNC_SWT3, - TUYA_MCU_FUNC_SWT4, - TUYA_MCU_FUNC_REL1 = 11, - TUYA_MCU_FUNC_REL2, - TUYA_MCU_FUNC_REL3, - TUYA_MCU_FUNC_REL4, - TUYA_MCU_FUNC_REL5, - TUYA_MCU_FUNC_REL6, - TUYA_MCU_FUNC_REL7, - TUYA_MCU_FUNC_REL8, - TUYA_MCU_FUNC_DIMMER = 21, - TUYA_MCU_FUNC_POWER = 31, - TUYA_MCU_FUNC_CURRENT, - TUYA_MCU_FUNC_VOLTAGE, - TUYA_MCU_FUNC_REL1_INV = 41, - TUYA_MCU_FUNC_REL2_INV, - TUYA_MCU_FUNC_REL3_INV, - TUYA_MCU_FUNC_REL4_INV, - TUYA_MCU_FUNC_REL5_INV, - TUYA_MCU_FUNC_REL6_INV, - TUYA_MCU_FUNC_REL7_INV, - TUYA_MCU_FUNC_REL8_INV, - TUYA_MCU_FUNC_LAST = 255 -}; - -const char kTuyaCommand[] PROGMEM = "|" - D_CMND_TUYA_MCU; - -void (* const TuyaCommand[])(void) PROGMEM = { - &CmndTuyaMcu -}; -# 108 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_16_tuyamcu.ino" -void CmndTuyaMcu(void) { - if (XdrvMailbox.data_len > 0) { - char *p; - uint8_t i = 0; - uint8_t parm[3] = { 0 }; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { - parm[i] = strtoul(str, nullptr, 0); - i++; - } - - if (TuyaFuncIdValid(parm[0])) { - TuyaAddMcuFunc(parm[0], parm[1]); - restart_flag = 2; - } else { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]); - } - - } - - Response_P(PSTR("[")); - bool added = false; - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if (Settings.tuya_fnid_map[i].fnid != 0) { - if (added) { - ResponseAppend_P(PSTR(",")); - } - ResponseAppend_P(PSTR("{\"fnId\":%d, \"dpId\":%d}" ), Settings.tuya_fnid_map[i].fnid, Settings.tuya_fnid_map[i].dpid); - added = true; - } - } - ResponseAppend_P(PSTR("]")); -} - - - - - -void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) { - bool added = false; - - if (fnId == 0 || dpId == 0) { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if ((dpId > 0 && Settings.tuya_fnid_map[i].dpid == dpId) || (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].fnid == fnId)) { - Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; - Settings.tuya_fnid_map[i].dpid = 0; - break; - } - } - } else { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].dpid == 0 || Settings.tuya_fnid_map[i].fnid == fnId || Settings.tuya_fnid_map[i].fnid == 0) { - if (!added) { - Settings.tuya_fnid_map[i].fnid = fnId; - Settings.tuya_fnid_map[i].dpid = dpId; - added = true; - } else if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].fnid == fnId) { - Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; - Settings.tuya_fnid_map[i].dpid = 0; - } - } - } - } - UpdateDevices(); -} - -void UpdateDevices() { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - uint8_t fnId = Settings.tuya_fnid_map[i].fnid; - if (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].dpid > 0) { - - if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { - bitClear(rel_inverted, fnId - TUYA_MCU_FUNC_REL1); - } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { - bitSet(rel_inverted, fnId - TUYA_MCU_FUNC_REL1_INV); - } - - } - } -} - -inline bool TuyaFuncIdValid(uint8_t fnId) { - return (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) || - (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) || - fnId == TUYA_MCU_FUNC_DIMMER || - (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE) || - (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV); -} - -uint8_t TuyaGetFuncId(uint8_t dpid) { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if (Settings.tuya_fnid_map[i].dpid == dpid) { - return Settings.tuya_fnid_map[i].fnid; - } - } - return TUYA_MCU_FUNC_NONE; -} - -uint8_t TuyaGetDpId(uint8_t fnId) { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if (Settings.tuya_fnid_map[i].fnid == fnId) { - return Settings.tuya_fnid_map[i].dpid; - } - } - return 0; -} - -void TuyaSendCmd(uint8_t cmd, uint8_t payload[] = nullptr, uint16_t payload_len = 0) -{ - uint8_t checksum = (0xFF + cmd + (payload_len >> 8) + (payload_len & 0xFF)); - TuyaSerial->write(0x55); - TuyaSerial->write(0xAA); - TuyaSerial->write((uint8_t)0x00); - TuyaSerial->write(cmd); - TuyaSerial->write(payload_len >> 8); - TuyaSerial->write(payload_len & 0xFF); - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send \"55aa00%02x%02x%02x"), cmd, payload_len >> 8, payload_len & 0xFF); - for (uint32_t i = 0; i < payload_len; ++i) { - TuyaSerial->write(payload[i]); - checksum += payload[i]; - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, payload[i]); - } - TuyaSerial->write(checksum); - TuyaSerial->flush(); - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x\""), log_data, checksum); - AddLog(LOG_LEVEL_DEBUG); -} - -void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value) -{ - uint16_t payload_len = 4; - uint8_t payload_buffer[8]; - payload_buffer[0] = id; - payload_buffer[1] = type; - switch (type) { - case TUYA_TYPE_BOOL: - payload_len += 1; - payload_buffer[2] = 0x00; - payload_buffer[3] = 0x01; - payload_buffer[4] = value[0]; - break; - case TUYA_TYPE_VALUE: - payload_len += 4; - payload_buffer[2] = 0x00; - payload_buffer[3] = 0x04; - payload_buffer[4] = value[3]; - payload_buffer[5] = value[2]; - payload_buffer[6] = value[1]; - payload_buffer[7] = value[0]; - break; - } - - TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); -} - -void TuyaSendBool(uint8_t id, bool value) -{ - TuyaSendState(id, TUYA_TYPE_BOOL, (uint8_t*)&value); -} - -void TuyaSendValue(uint8_t id, uint32_t value) -{ - TuyaSendState(id, TUYA_TYPE_VALUE, (uint8_t*)(&value)); -} - -bool TuyaSetPower(void) -{ - bool status = false; - - uint8_t rpower = XdrvMailbox.index; - int16_t source = XdrvMailbox.payload; - - if (source != SRC_SWITCH && TuyaSerial) { - TuyaSendBool(active_device, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); - status = true; - } - return status; -} - -bool TuyaSetChannels(void) -{ - LightSerialDuty(((uint8_t*)XdrvMailbox.data)[0]); - delay(20); - return true; -} - -void LightSerialDuty(uint8_t duty) -{ - uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER); - if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { - if (Settings.flag3.tuya_dimmer_min_limit) { - if (duty < 25) { duty = 25; } - } - duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]); - if (Tuya.new_dim != duty) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); - TuyaSendValue(dpid, duty); - } - } else if (dpid > 0) { - Tuya.ignore_dim = false; - duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); - } -} - -void TuyaRequestState(void) -{ - if (TuyaSerial) { - - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Read MCU state")); - - TuyaSendCmd(TUYA_CMD_QUERY_STATE); - } -} - -void TuyaResetWifi(void) -{ - if (!Settings.flag.button_restrict) { - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2); - ExecuteCommand(scmnd, SRC_BUTTON); - } -} - -void TuyaPacketProcess(void) -{ - char scmnd[20]; - uint8_t fnId = TUYA_MCU_FUNC_NONE; - - switch (Tuya.buffer[3]) { - - case TUYA_CMD_HEARTBEAT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); - if (Tuya.buffer[6] == 0) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Detected MCU restart")); - Tuya.wifi_state = -2; - } - break; - - case TUYA_CMD_STATE: - fnId = TuyaGetFuncId(Tuya.buffer[6]); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: FnId=%d is set for dpId=%d"), fnId, Tuya.buffer[6]); - - if (Tuya.buffer[5] == 5) { - - if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); - if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { - ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10], SRC_SWITCH); - } - } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[10]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); - if (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { - ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[10] ^ 1, SRC_SWITCH); - } - } else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[10], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1)); - - if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[10]) { - SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[10]); - SwitchHandler(1); - } - } - - } - else if (Tuya.buffer[5] == 8) { - bool tuya_energy_enabled = (XNRG_16 == energy_flg); - if (fnId == TUYA_MCU_FUNC_DIMMER) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]); - Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_TUYA_DIMMER_MAX], 0, 100); - if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { - Tuya.ignore_dim = true; - - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); - ExecuteCommand(scmnd, SRC_SWITCH); - } - } - - #ifdef USE_ENERGY_SENSOR - else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) { - Energy.voltage[0] = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); - } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) { - Energy.current[0] = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 1000; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); - } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) { - Energy.active_power[0] = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); - - if (Tuya.lastPowerCheckTime != 0 && Energy.active_power[0] > 0) { - Energy.kWhtoday += (float)Energy.active_power[0] * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36; - EnergyUpdateToday(); - } - Tuya.lastPowerCheckTime = Rtc.utc_time; - } - #endif - - } - - - - break; - - case TUYA_CMD_WIFI_RESET: - case TUYA_CMD_WIFI_SELECT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi Reset")); - TuyaResetWifi(); - break; - - case TUYA_CMD_WIFI_STATE: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi LED set ACK")); - Tuya.wifi_state = WifiState(); - break; - - case TUYA_CMD_MCU_CONF: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration Mode=%d"), Tuya.buffer[5]); - - if (Tuya.buffer[5] == 2) { - uint8_t led1_gpio = Tuya.buffer[6]; - uint8_t key1_gpio = Tuya.buffer[7]; - bool key1_set = false; - bool led1_set = false; - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (Settings.my_gp.io[i] == GPIO_LED1) led1_set = true; - else if (Settings.my_gp.io[i] == GPIO_KEY1) key1_set = true; - } - if (!Settings.my_gp.io[led1_gpio] && !led1_set) { - Settings.my_gp.io[led1_gpio] = GPIO_LED1; - restart_flag = 2; - } - if (!Settings.my_gp.io[key1_gpio] && !key1_set) { - Settings.my_gp.io[key1_gpio] = GPIO_KEY1; - restart_flag = 2; - } - } - TuyaRequestState(); - break; - - default: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX unknown command")); - } -} - - - - - -bool TuyaModuleSelected(void) -{ - if (!(pin[GPIO_TUYA_RX] < 99) || !(pin[GPIO_TUYA_TX] < 99)) { - pin[GPIO_TUYA_TX] = 1; - pin[GPIO_TUYA_RX] = 3; - Settings.my_gp.io[1] = GPIO_TUYA_TX; - Settings.my_gp.io[3] = GPIO_TUYA_RX; - restart_flag = 2; - } - - if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) == 0 && TUYA_DIMMER_ID > 0) { - TuyaAddMcuFunc(TUYA_MCU_FUNC_DIMMER, TUYA_DIMMER_ID); - } - - bool relaySet = false; - - devices_present--; - - for (uint8_t i = 0 ; i < MAX_TUYA_FUNCTIONS; i++) { - if ((Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) || - (Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) { - relaySet = true; - devices_present++; - } - } - - if (!relaySet) { - TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); - devices_present++; - SettingsSaveAll(); - } - - if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { - light_type = LT_SERIAL1; - } else { - light_type = LT_BASIC; - } - - UpdateDevices(); - return true; -} - -void TuyaInit(void) -{ - Tuya.buffer = (char*)(malloc(TUYA_BUFFER_SIZE)); - if (Tuya.buffer != nullptr) { - TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); - if (TuyaSerial->begin(9600)) { - if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } - - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Request MCU configuration")); - - TuyaSendCmd(TUYA_CMD_MCU_CONF); - } - } - Tuya.heartbeat_timer = 0; -} - -void TuyaSerialInput(void) -{ - while (TuyaSerial->available()) { - yield(); - uint8_t serial_in_byte = TuyaSerial->read(); - - if (serial_in_byte == 0x55) { - Tuya.cmd_status = 1; - Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - Tuya.cmd_checksum += serial_in_byte; - } - else if (Tuya.cmd_status == 1 && serial_in_byte == 0xAA) { - Tuya.cmd_status = 2; - - Tuya.byte_counter = 0; - Tuya.buffer[Tuya.byte_counter++] = 0x55; - Tuya.buffer[Tuya.byte_counter++] = 0xAA; - Tuya.cmd_checksum = 0xFF; - } - else if (Tuya.cmd_status == 2) { - if (Tuya.byte_counter == 5) { - Tuya.cmd_status = 3; - Tuya.data_len = serial_in_byte; - } - Tuya.cmd_checksum += serial_in_byte; - Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - } - else if ((Tuya.cmd_status == 3) && (Tuya.byte_counter == (6 + Tuya.data_len)) && (Tuya.cmd_checksum == serial_in_byte)) { - Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: RX Packet: \"")); - for (uint32_t i = 0; i < Tuya.byte_counter; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, Tuya.buffer[i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); - AddLog(LOG_LEVEL_DEBUG); - - TuyaPacketProcess(); - Tuya.byte_counter = 0; - Tuya.cmd_status = 0; - Tuya.cmd_checksum = 0; - Tuya.data_len = 0; - } - else if (Tuya.byte_counter < TUYA_BUFFER_SIZE -1) { - Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - Tuya.cmd_checksum += serial_in_byte; - } else { - Tuya.byte_counter = 0; - Tuya.cmd_status = 0; - Tuya.cmd_checksum = 0; - Tuya.data_len = 0; - } - } -} - -bool TuyaButtonPressed(void) -{ - if (!XdrvMailbox.index && ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == Button.last_state[XdrvMailbox.index]))) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Reset GPIO triggered")); - TuyaResetWifi(); - return true; - } - return false; -} - -void TuyaSetWifiLed(void) -{ - uint8_t wifi_state = 0x02; - switch(WifiState()){ - case WIFI_SMARTCONFIG: - wifi_state = 0x00; - break; - case WIFI_MANAGER: - case WIFI_WPSCONFIG: - wifi_state = 0x01; - break; - case WIFI_RESTART: - wifi_state = 0x03; - break; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Set WiFi LED %d (%d)"), wifi_state, WifiState()); - - TuyaSendCmd(TUYA_CMD_WIFI_STATE, &wifi_state, 1); -} - -#ifdef USE_ENERGY_SENSOR - - - - -bool Xnrg16(uint8_t function) -{ - bool result = false; - - if (TUYA_DIMMER == my_module_type) { - if (FUNC_PRE_INIT == function) { - if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0) { - if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0) { - Energy.current_available = false; - } - if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0) { - Energy.voltage_available = false; - } - energy_flg = XNRG_16; - } - } - } - return result; -} -#endif - - - - - -bool Xdrv16(uint8_t function) -{ - bool result = false; - - if (TUYA_DIMMER == my_module_type) { - switch (function) { - case FUNC_LOOP: - if (TuyaSerial) { TuyaSerialInput(); } - break; - case FUNC_MODULE_INIT: - result = TuyaModuleSelected(); - break; - case FUNC_INIT: - TuyaInit(); - break; - case FUNC_SET_DEVICE_POWER: - result = TuyaSetPower(); - break; - case FUNC_BUTTON_PRESSED: - result = TuyaButtonPressed(); - break; - case FUNC_EVERY_SECOND: - if (TuyaSerial && Tuya.wifi_state != WifiState()) { TuyaSetWifiLed(); } - Tuya.heartbeat_timer++; - if (Tuya.heartbeat_timer > 10) { - Tuya.heartbeat_timer = 0; - TuyaSendCmd(TUYA_CMD_HEARTBEAT); - } - break; - case FUNC_SET_CHANNELS: - result = TuyaSetChannels(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kTuyaCommand, TuyaCommand); - break; - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_17_rcswitch.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_17_rcswitch.ino" -#ifdef USE_RC_SWITCH - - - - -#define XDRV_17 17 - -#define D_JSON_RF_PROTOCOL "Protocol" -#define D_JSON_RF_BITS "Bits" -#define D_JSON_RF_DATA "Data" - -#define D_CMND_RFSEND "RFSend" -#define D_JSON_RF_PULSE "Pulse" -#define D_JSON_RF_REPEAT "Repeat" - -const char kRfSendCommands[] PROGMEM = "|" - D_CMND_RFSEND; - -void (* const RfSendCommand[])(void) PROGMEM = - { &CmndRfSend }; - -#include - -RCSwitch mySwitch = RCSwitch(); - -#define RF_TIME_AVOID_DUPLICATE 1000 - -uint32_t rf_lasttime = 0; - -void RfReceiveCheck(void) -{ - if (mySwitch.available()) { - - unsigned long data = mySwitch.getReceivedValue(); - unsigned int bits = mySwitch.getReceivedBitlength(); - int protocol = mySwitch.getReceivedProtocol(); - int delay = mySwitch.getReceivedDelay(); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFR: Data 0x%lX (%u), Bits %d, Protocol %d, Delay %d"), data, data, bits, protocol, delay); - - uint32_t now = millis(); - if ((now - rf_lasttime > RF_TIME_AVOID_DUPLICATE) && (data > 0)) { - rf_lasttime = now; - - char stemp[16]; - if (Settings.flag.rf_receive_decimal) { - snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)data); - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data); - } - ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), - stemp, bits, protocol, delay); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); - XdrvRulesProcess(); -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_COUNT, data); -#endif - } - mySwitch.resetAvailable(); - } -} - -void RfInit(void) -{ - if (pin[GPIO_RFSEND] < 99) { - mySwitch.enableTransmit(pin[GPIO_RFSEND]); - } - if (pin[GPIO_RFRECV] < 99) { - mySwitch.enableReceive(pin[GPIO_RFRECV]); - } -} - - - - - -void CmndRfSend(void) -{ - bool error = false; - - if (XdrvMailbox.data_len) { - unsigned long data = 0; - unsigned int bits = 24; - int protocol = 1; - int repeat = 10; - int pulse = 350; - - char dataBufUc[XdrvMailbox.data_len]; - UpperCase(dataBufUc, XdrvMailbox.data); - StaticJsonBuffer<150> jsonBuf; - JsonObject &root = jsonBuf.parseObject(dataBufUc); - if (root.success()) { - - char parm_uc[10]; - data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], nullptr, 0); - bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_BITS))]; - protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PROTOCOL))]; - repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_REPEAT))]; - pulse = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PULSE))]; - } else { - - char *p; - uint8_t i = 0; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 5; str = strtok_r(nullptr, ", ", &p)) { - switch (i++) { - case 0: - data = strtoul(str, nullptr, 0); - break; - case 1: - bits = atoi(str); - break; - case 2: - protocol = atoi(str); - break; - case 3: - repeat = atoi(str); - break; - case 4: - pulse = atoi(str); - } - } - } - - if (!protocol) { protocol = 1; } - mySwitch.setProtocol(protocol); - if (!pulse) { pulse = 350; } - mySwitch.setPulseLength(pulse); - if (!repeat) { repeat = 10; } - mySwitch.setRepeatTransmit(repeat); - if (!bits) { bits = 24; } - if (data) { - mySwitch.send(data, bits); - ResponseCmndDone(); - } else { - error = true; - } - } else { - error = true; - } - if (error) { - Response_P(PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_DATA ", " D_JSON_RF_BITS ", " D_JSON_RF_PROTOCOL ", " D_JSON_RF_REPEAT " " D_JSON_OR " " D_JSON_RF_PULSE "\"}")); - } -} - - - - - -bool Xdrv17(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_RFSEND] < 99) || (pin[GPIO_RFRECV] < 99)) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (pin[GPIO_RFRECV] < 99) { - RfReceiveCheck(); - } - break; - case FUNC_COMMAND: - if (pin[GPIO_RFSEND] < 99) { - result = DecodeCommand(kRfSendCommands, RfSendCommand); - } - break; - case FUNC_INIT: - RfInit(); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_18_armtronix_dimmers.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_18_armtronix_dimmers.ino" -#ifdef USE_LIGHT -#ifdef USE_ARMTRONIX_DIMMERS - - - - - - - -#define XDRV_18 18 - -#include - -TasmotaSerial *ArmtronixSerial = nullptr; - -struct ARMTRONIX { - bool ignore_dim = false; - int8_t wifi_state = -2; - int8_t dim_state[2]; - int8_t knob_state[2]; -} Armtronix; - - - - - -bool ArmtronixSetChannels(void) -{ - LightSerial2Duty(((uint8_t*)XdrvMailbox.data)[0], ((uint8_t*)XdrvMailbox.data)[1]); - return true; -} - -void LightSerial2Duty(uint8_t duty1, uint8_t duty2) -{ - if (ArmtronixSerial && !Armtronix.ignore_dim) { - duty1 = ((float)duty1)/2.575757; - duty2 = ((float)duty2)/2.575757; - Armtronix.dim_state[0] = duty1; - Armtronix.dim_state[1] = duty2; - ArmtronixSerial->print("Dimmer1:"); - ArmtronixSerial->print(duty1); - ArmtronixSerial->print("\nDimmer2:"); - ArmtronixSerial->println(duty2); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Serial Packet Dim Values=%d,%d"), Armtronix.dim_state[0],Armtronix.dim_state[1]); - - } else { - Armtronix.ignore_dim = false; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Dim Level skipped due to already set. Value=%d,%d"), Armtronix.dim_state[0],Armtronix.dim_state[1]); - - } -} - -void ArmtronixRequestState(void) -{ - if (ArmtronixSerial) { - - AddLog_P(LOG_LEVEL_DEBUG, PSTR("ARM: Request MCU state")); - ArmtronixSerial->println("Status"); - - } -} - - - - - -bool ArmtronixModuleSelected(void) -{ - light_type = LT_SERIAL2; - return true; -} - -void ArmtronixInit(void) -{ - Armtronix.dim_state[0] = -1; - Armtronix.dim_state[1] = -1; - Armtronix.knob_state[0] = -1; - Armtronix.knob_state[1] = -1; - ArmtronixSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); - if (ArmtronixSerial->begin(115200)) { - if (ArmtronixSerial->hardwareSerial()) { ClaimSerial(); } - ArmtronixSerial->println("Status"); - } -} - -void ArmtronixSerialInput(void) -{ - String answer; - int8_t newDimState[2]; - uint8_t temp; - int commaIndex; - char scmnd[20]; - if (ArmtronixSerial->available()) { - yield(); - answer = ArmtronixSerial->readStringUntil('\n'); - if (answer.substring(0,7) == "Status:") { - commaIndex = 6; - for (uint32_t i =0; i<2; i++) { - newDimState[i] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); - if (newDimState[i] != Armtronix.dim_state[i]) { - temp = ((float)newDimState[i])*1.01010101010101; - Armtronix.dim_state[i] = newDimState[i]; - Armtronix.ignore_dim = true; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "%d %d"),i+1, temp); - ExecuteCommand(scmnd,SRC_SWITCH); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send CMND_CHANNEL=%s"), scmnd ); - } - commaIndex = answer.indexOf(',',commaIndex+1); - } - Armtronix.knob_state[0] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); - commaIndex = answer.indexOf(',',commaIndex+1); - Armtronix.knob_state[1] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); - } - } -} - -void ArmtronixSetWifiLed(void) -{ - uint8_t wifi_state = 0x02; - - switch (WifiState()) { - case WIFI_SMARTCONFIG: - wifi_state = 0x00; - break; - case WIFI_MANAGER: - case WIFI_WPSCONFIG: - wifi_state = 0x01; - break; - case WIFI_RESTART: - wifi_state = 0x03; - break; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Set WiFi LED to state %d (%d)"), wifi_state, WifiState()); - - char state = '0' + ((wifi_state & 1) > 0); - ArmtronixSerial->print("Setled:"); - ArmtronixSerial->write(state); - ArmtronixSerial->write(','); - state = '0' + ((wifi_state & 2) > 0); - ArmtronixSerial->write(state); - ArmtronixSerial->write(10); - Armtronix.wifi_state = WifiState(); -} - - - - - -bool Xdrv18(uint8_t function) -{ - bool result = false; - - if (ARMTRONIX_DIMMERS == my_module_type) { - switch (function) { - case FUNC_LOOP: - if (ArmtronixSerial) { ArmtronixSerialInput(); } - break; - case FUNC_MODULE_INIT: - result = ArmtronixModuleSelected(); - break; - case FUNC_INIT: - ArmtronixInit(); - break; - case FUNC_EVERY_SECOND: - if (ArmtronixSerial) { - if (Armtronix.wifi_state!=WifiState()) { ArmtronixSetWifiLed(); } - if (uptime &1) { - ArmtronixSerial->println("Status"); - } - } - break; - case FUNC_SET_CHANNELS: - result = ArmtronixSetChannels(); - break; - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_19_ps16dz_dimmer.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_19_ps16dz_dimmer.ino" -#ifdef USE_LIGHT -#ifdef USE_PS_16_DZ - - - - -#define XDRV_19 19 - -#define PS16DZ_BUFFER_SIZE 140 - -#define PS16DZ_SONOFF_L1_MODE_COLORFUL 1 -#define PS16DZ_SONOFF_L1_MODE_COLORFUL_GRADIENT 2 -#define PS16DZ_SONOFF_L1_MODE_COLORFUL_BREATH 3 -#define PS16DZ_SONOFF_L1_MODE_DIY_GRADIENT 4 -#define PS16DZ_SONOFF_L1_MODE_DIY_PULSE 5 -#define PS16DZ_SONOFF_L1_MODE_DIY_BREATH 6 -#define PS16DZ_SONOFF_L1_MODE_DIY_STROBE 7 -#define PS16DZ_SONOFF_L1_MODE_RGB_GRADIENT 8 -#define PS16DZ_SONOFF_L1_MODE_RGB_PULSE 9 -#define PS16DZ_SONOFF_L1_MODE_RGB_BREATH 10 -#define PS16DZ_SONOFF_L1_MODE_RGB_STROBE 11 -#define PS16DZ_SONOFF_L1_MODE_SYNC_TO_MUSIC 12 - -#include - -TasmotaSerial *PS16DZSerial = nullptr; - -struct PS16DZ { - char *tx_buffer = nullptr; - char *rx_buffer = nullptr; - int byte_counter = 0; - uint8_t color[3]; - uint8_t dimmer = 0; - bool supports_color = false; - bool switch_state = false; -} Ps16dz; - - - - - -void PS16DZSerialSendTxBuffer(void) -{ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Send %s"), Ps16dz.tx_buffer); - - PS16DZSerial->print(Ps16dz.tx_buffer); - PS16DZSerial->write(0x1B); - PS16DZSerial->flush(); -} - -void PS16DZSerialSendOkCommand(void) -{ - snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("AT+SEND=ok")); - PS16DZSerialSendTxBuffer(); -} - - - - - - -void PS16DZSerialSendUpdateCommand(void) -{ - uint8_t light_state_dimmer = light_state.getDimmer(); - - light_state_dimmer = (light_state_dimmer < 10) ? 10 : light_state_dimmer; - - snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), - LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer); - - if (Ps16dz.supports_color) { - uint8_t light_state_rgb[3]; - light_state.getRGB(&light_state_rgb[0], &light_state_rgb[1], &light_state_rgb[2]); - - snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("%s,\"mode\":%d,\"colorR\":%d,\"colorG\":%d,\"colorB\":%d,\"light_types\":1"), - Ps16dz.tx_buffer, PS16DZ_SONOFF_L1_MODE_COLORFUL, light_state_rgb[0], light_state_rgb[1], light_state_rgb[2]); - } - PS16DZSerialSendTxBuffer(); -} - - - - - -bool PS16DZSerialSendUpdateCommandIfRequired(void) -{ - if (!PS16DZSerial) { return true; } - - bool is_switch_change = (XdrvMailbox.payload != SRC_SWITCH); - bool is_brightness_change = (light_state.getDimmer() != Ps16dz.dimmer); - - uint8_t light_state_rgb[3]; - light_state.getRGB(&light_state_rgb[0], &light_state_rgb[1], &light_state_rgb[2]); - bool is_color_change = (Ps16dz.supports_color && (memcmp(light_state_rgb, Ps16dz.color, 3) != 0)); - - if (is_switch_change || is_brightness_change || is_color_change) { - PS16DZSerialSendUpdateCommand(); - } - - return true; -} - -bool PS16DZModuleSelected(void) -{ - switch (my_module_type) - { - case PS_16_DZ: - light_type = LT_SERIAL1; - break; - - case SONOFF_L1: - light_type = LT_PWM3; - break; - } - - return true; -} - -void PS16DZInit(void) -{ - Ps16dz.supports_color = (light_state.getColorMode() == LCM_RGB); - - Ps16dz.tx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); - if (Ps16dz.tx_buffer != nullptr) { - Ps16dz.rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); - if (Ps16dz.rx_buffer != nullptr) { - PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); - if (PS16DZSerial->begin(19200)) { - if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } - } - } - } -} - -void PS16DZSerialInput(void) -{ - char scmnd[20]; - while (PS16DZSerial->available()) { - yield(); - uint8_t serial_in_byte = PS16DZSerial->read(); - if (serial_in_byte != 0x1B) { - if (Ps16dz.byte_counter >= PS16DZ_BUFFER_SIZE - 1) { - memset(Ps16dz.rx_buffer, 0, PS16DZ_BUFFER_SIZE); - Ps16dz.byte_counter = 0; - } - if (Ps16dz.byte_counter || (!Ps16dz.byte_counter && ('A' == serial_in_byte))) { - Ps16dz.rx_buffer[Ps16dz.byte_counter++] = serial_in_byte; - } - } else { - Ps16dz.rx_buffer[Ps16dz.byte_counter++] = 0x00; - - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Received %s"), Ps16dz.rx_buffer); - - if (!strncmp(Ps16dz.rx_buffer+3, "UPDATE", 6)) { - - char *end_str; - char *string = Ps16dz.rx_buffer+10; - char *token = strtok_r(string, ",", &end_str); - - bool color_updated[3] = { false, false, false }; - memcpy(Ps16dz.color, Settings.light_color, 3); - bool is_switch_change = false; - bool is_color_change = false; - bool is_brightness_change = false; - - while (token != nullptr) { - char* end_token; - char* token2 = strtok_r(token, ":", &end_token); - char* token3 = strtok_r(nullptr, ":", &end_token); - - if (!strncmp(token2, "\"switch\"", 8)) { - Ps16dz.switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Switch %d"), Ps16dz.switch_state); - - is_switch_change = (Ps16dz.switch_state != power); - if (is_switch_change) { - ExecuteCommandPower(1, Ps16dz.switch_state, SRC_SWITCH); - } - } - else if (!strncmp(token2, "\"color", 6)) { - - char color_channel_name = token2[6]; - int color_index; - switch(color_channel_name) - { - case 'R': color_index = 0; - break; - case 'G': color_index = 1; - break; - case 'B': color_index = 2; - break; - } - int color_value = atoi(token3); - Ps16dz.color[color_index] = color_value; - color_updated[color_index] = true; - - bool all_color_channels_updated = color_updated[0] && color_updated[1] && color_updated[2]; - if (all_color_channels_updated) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Color R:%d, G:%d, B:%d"), Ps16dz.color[0], Ps16dz.color[1], Ps16dz.color[2]); - - is_color_change = (memcmp(Ps16dz.color, Settings.light_color, 3) != 0); - } - - if (power && is_color_change) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_COLOR "2 %02x%02x%02x"), Ps16dz.color[0], Ps16dz.color[1], Ps16dz.color[2]); - ExecuteCommand(scmnd, SRC_SWITCH); - } - } - else if (!strncmp(token2, "\"bright\"", 8)) { - Ps16dz.dimmer = atoi(token3); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Brightness %d"), Ps16dz.dimmer); - - is_brightness_change = Ps16dz.dimmer != Settings.light_dimmer; - if (power && (Ps16dz.dimmer > 0) && is_brightness_change) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Ps16dz.dimmer); - ExecuteCommand(scmnd, SRC_SWITCH); - } - } - else if (!strncmp(token2, "\"sequence\"", 10)) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Sequence %s"), token3); - - } - token = strtok_r(nullptr, ",", &end_str); - } - - if (!is_color_change && !is_brightness_change) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Update")); - - PS16DZSerialSendOkCommand(); - } - } - else if (!strncmp(Ps16dz.rx_buffer+3, "SETTING", 7)) { - - - if (!Settings.flag.button_restrict) { - int state = WIFI_MANAGER; - if (!strncmp(Ps16dz.rx_buffer+10, "=exit", 5)) { state = WIFI_RETRY; } - if (state != Settings.sta_config) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " %d"), state); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - } - memset(Ps16dz.rx_buffer, 0, PS16DZ_BUFFER_SIZE); - Ps16dz.byte_counter = 0; - } - } -} - - - - - -bool Xdrv19(uint8_t function) -{ - bool result = false; - - if ((PS_16_DZ == my_module_type) || (SONOFF_L1 == my_module_type)) { - switch (function) { - case FUNC_LOOP: - if (PS16DZSerial) { PS16DZSerialInput(); } - break; - case FUNC_MODULE_INIT: - result = PS16DZModuleSelected(); - break; - case FUNC_INIT: - PS16DZInit(); - break; - case FUNC_SET_DEVICE_POWER: - case FUNC_SET_CHANNELS: - result = PS16DZSerialSendUpdateCommandIfRequired(); - break; - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_20_hue.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_20_hue.ino" -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) -# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_20_hue.ino" -#define XDRV_20 20 - -const char HUE_RESPONSE[] PROGMEM = - "HTTP/1.1 200 OK\r\n" - "HOST: 239.255.255.250:1900\r\n" - "CACHE-CONTROL: max-age=100\r\n" - "EXT:\r\n" - "LOCATION: http://%s:80/description.xml\r\n" - "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.17.0\r\n" - "hue-bridgeid: %s\r\n"; -const char HUE_ST1[] PROGMEM = - "ST: upnp:rootdevice\r\n" - "USN: uuid:%s::upnp:rootdevice\r\n" - "\r\n"; -const char HUE_ST2[] PROGMEM = - "ST: uuid:%s\r\n" - "USN: uuid:%s\r\n" - "\r\n"; -const char HUE_ST3[] PROGMEM = - "ST: urn:schemas-upnp-org:device:basic:1\r\n" - "USN: uuid:%s\r\n" - "\r\n"; - -String HueBridgeId(void) -{ - String temp = WiFi.macAddress(); - temp.replace(":", ""); - String bridgeid = temp.substring(0, 6) + "FFFE" + temp.substring(6); - return bridgeid; -} - -String HueSerialnumber(void) -{ - String serial = WiFi.macAddress(); - serial.replace(":", ""); - serial.toLowerCase(); - return serial; -} - -String HueUuid(void) -{ - String uuid = F("f6543a06-da50-11ba-8d8f-"); - uuid += HueSerialnumber(); - return uuid; -} - -void HueRespondToMSearch(void) -{ - char message[TOPSZ]; - - TickerMSearch.detach(); - if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { - char response[320]; - snprintf_P(response, sizeof(response), HUE_RESPONSE, WiFi.localIP().toString().c_str(), HueBridgeId().c_str()); - int len = strlen(response); - - snprintf_P(response + len, sizeof(response) - len, HUE_ST1, HueUuid().c_str()); - PortUdp.write(response); - PortUdp.endPacket(); - - snprintf_P(response + len, sizeof(response) - len, HUE_ST2, HueUuid().c_str(), HueUuid().c_str()); - PortUdp.write(response); - PortUdp.endPacket(); - - snprintf_P(response + len, sizeof(response) - len, HUE_ST3, HueUuid().c_str()); - PortUdp.write(response); - 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)); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"), - message, udp_remote_ip.toString().c_str(), udp_remote_port); - - udp_response_mutex = false; -} - - - - - -const char HUE_DESCRIPTION_XML[] PROGMEM = - "" - "" - "" - "1" - "0" - "" - - "http://{x1:80/" - "" - "urn:schemas-upnp-org:device:Basic:1" - "Amazon-Echo-HA-Bridge ({x1)" - - "Royal Philips Electronics" - "Philips hue Personal Wireless Lighting" - "Philips hue bridge 2012" - "929000226503" - "{x3" - "uuid:{x2" - "" - "\r\n" - "\r\n"; -const char HUE_LIGHTS_STATUS_JSON1[] PROGMEM = - "{\"on\":{state}," - "{light_status}" - "\"alert\":\"none\"," - "\"effect\":\"none\"," - "\"reachable\":true}"; -const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = - ",\"type\":\"Extended color light\"," - "\"name\":\"{j1\"," - "\"modelid\":\"LCT007\"," - "\"uniqueid\":\"{j2\"," - "\"swversion\":\"5.50.1.19085\"}"; -const char HUE_GROUP0_STATUS_JSON[] PROGMEM = - "{\"name\":\"Group 0\"," - "\"lights\":[{l1]," - "\"type\":\"LightGroup\"," - "\"action\":"; - -const char HueConfigResponse_JSON[] PROGMEM = - "{\"name\":\"Philips hue\"," - "\"mac\":\"{ma\"," - "\"dhcp\":true," - "\"ipaddress\":\"{ip\"," - "\"netmask\":\"{ms\"," - "\"gateway\":\"{gw\"," - "\"proxyaddress\":\"none\"," - "\"proxyport\":0," - "\"bridgeid\":\"{br\"," - "\"UTC\":\"{dt\"," - "\"whitelist\":{\"{id\":{" - "\"last use date\":\"{dt\"," - "\"create date\":\"{dt\"," - "\"name\":\"Remote\"}}," - "\"swversion\":\"01041302\"," - "\"apiversion\":\"1.17.0\"," - "\"swupdate\":{\"updatestate\":0,\"url\":\"\",\"text\":\"\",\"notify\": false}," - "\"linkbutton\":false," - "\"portalservices\":false" - "}"; -const char HUE_LIGHT_RESPONSE_JSON[] PROGMEM = - "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; -const char HUE_ERROR_JSON[] PROGMEM = - "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; - - - -String GetHueDeviceId(uint8_t id) -{ - String deviceid = WiFi.macAddress() + F(":00:11-") + String(id); - deviceid.toLowerCase(); - return deviceid; -} - -String GetHueUserId(void) -{ - char userid[7]; - - snprintf_P(userid, sizeof(userid), PSTR("%03x"), ESP.getChipId()); - return String(userid); -} - -void HandleUpnpSetupHue(void) -{ - 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", HueUuid()); - description_xml.replace("{x3", HueSerialnumber()); - WSSend(200, CT_XML, description_xml); -} - -void HueNotImplemented(String *path) -{ - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API_NOT_IMPLEMENTED " (%s)"), path->c_str()); - - WSSend(200, CT_JSON, "{}"); -} - -void HueConfigResponse(String *response) -{ - *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", GetDateAndTime(DT_UTC)); - response->replace("{id", GetHueUserId()); -} - -void HueConfig(String *path) -{ - String response = ""; - HueConfigResponse(&response); - WSSend(200, CT_JSON, response); -} - - - -bool g_gotct = false; - - - - -uint16_t prev_hue = 0; -uint8_t prev_sat = 0; -uint8_t prev_bri = 254; -uint16_t prev_ct = 254; -char prev_x_str[24] = "\0"; -char prev_y_str[24] = "\0"; - -uint8_t getLocalLightSubtype(uint8_t device) { - if (light_type) { - if (device >= Light.device) { - if (Settings.flag3.pwm_multi_channels) { - return LST_SINGLE; - } else { - return Light.subtype; - } - } else { - return LST_NONE; - } - } else { - return LST_NONE; - } -} - -void HueLightStatus1(uint8_t device, String *response) -{ - uint16_t ct = 0; - uint8_t color_mode; - String light_status = ""; - uint16_t hue = 0; - uint8_t sat = 0; - uint8_t bri = 254; - uint32_t echo_gen = findEchoGeneration(); - - - uint8_t local_light_subtype = getLocalLightSubtype(device); - - bri = LightGetBri(device); - if (bri > 254) bri = 254; - if (bri < 1) bri = 1; - - if (light_type) { - light_state.getHSB(&hue, &sat, nullptr); - - if ((bri > prev_bri ? bri - prev_bri : prev_bri - bri) < 1) - bri = prev_bri; - - if (sat > 254) sat = 254; - if ((sat > prev_sat ? sat - prev_sat : prev_sat - sat) < 1) { - sat = prev_sat; - } else { - prev_x_str[0] = prev_y_str[0] = 0; - } - - hue = changeUIntScale(hue, 0, 359, 0, 65535); - if ((hue > prev_hue ? hue - prev_hue : prev_hue - hue) < 400) { - hue = prev_hue; - } else { - prev_x_str[0] = prev_y_str[0] = 0; - } - - color_mode = light_state.getColorMode(); - ct = light_state.getCT(); - if (LCM_RGB == color_mode) { g_gotct = false; } - if (LCM_CT == color_mode) { g_gotct = true; } - - - - if ((ct > prev_ct ? ct - prev_ct : prev_ct - ct) < 1) - ct = prev_ct; - - - - } - - *response += FPSTR(HUE_LIGHTS_STATUS_JSON1); - response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); - - if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { - light_status += "\"bri\":"; - light_status += String(bri); - light_status += ","; - } - if (LST_COLDWARM <= local_light_subtype) { - light_status += F("\"colormode\":\""); - light_status += (g_gotct ? "ct" : "hs"); - light_status += "\","; - } - if (LST_RGB <= local_light_subtype) { - if (prev_x_str[0] && prev_y_str[0]) { - light_status += "\"xy\":["; - light_status += prev_x_str; - light_status += ","; - light_status += prev_y_str; - light_status += "],"; - } else { - float x, y; - light_state.getXY(&x, &y); - light_status += "\"xy\":["; - light_status += String(x, 5); - light_status += ","; - light_status += String(y, 5); - light_status += "],"; - } - light_status += "\"hue\":"; - light_status += String(hue); - light_status += ","; - - light_status += "\"sat\":"; - light_status += String(sat); - light_status += ","; - } - if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { - light_status += "\"ct\":"; - light_status += String(ct > 0 ? ct : 284); - light_status += ","; - } - response->replace("{light_status}", light_status); -} - -void HueLightStatus2(uint8_t device, String *response) -{ - *response += FPSTR(HUE_LIGHTS_STATUS_JSON2); - if (device <= MAX_FRIENDLYNAMES) { - response->replace("{j1", Settings.friendlyname[device-1]); - } else { - char fname[33]; - strcpy(fname, Settings.friendlyname[MAX_FRIENDLYNAMES-1]); - uint32_t fname_len = strlen(fname); - if (fname_len >= 33-3) { - fname[33-3] = 0x00; - fname_len = 33-3; - } - fname[fname_len++] = '-'; - fname[fname_len++] = '0' + device - MAX_FRIENDLYNAMES; - response->replace("{j1", fname); - } - response->replace("{j2", GetHueDeviceId(device)); -} - - - - -uint32_t EncodeLightId(uint8_t relay_id) -{ - uint8_t mac[6]; - WiFi.macAddress(mac); - uint32_t id = 0; - - if (relay_id >= 32) { - relay_id = 0; - } - if (relay_id > 15) { - id = (1 << 28); - } - - id |= (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4) | (relay_id & 0xF); - return id; -} - - - -uint32_t DecodeLightId(uint32_t hue_id) { - uint8_t relay_id = hue_id & 0xF; - if (hue_id & (1 << 28)) { - relay_id += 16; - } - if (0 == relay_id) { - relay_id = 32; - } - return relay_id; -} - -static const char * FIRST_GEN_UA[] = { - "AEOBC", -}; - - -uint32_t findEchoGeneration(void) { - - String user_agent = WebServer->header("User-Agent"); - uint32_t gen = 2; - - for (uint32_t i = 0; i < sizeof(FIRST_GEN_UA)/sizeof(char*); i++) { - if (user_agent.indexOf(FIRST_GEN_UA[i]) >= 0) { - gen = 1; - break; - } - } - if (0 == user_agent.length()) { - gen = 1; - } - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, D_LOG_HTTP D_HUE " User-Agent: %s, gen=%d", user_agent.c_str(), gen); - - return gen; -} - -void HueGlobalConfig(String *path) -{ - String response; - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; - - path->remove(0,1); - response = F("{\"lights\":{\""); - for (uint32_t i = 1; i <= maxhue; i++) { - response += EncodeLightId(i); - response += F("\":{\"state\":"); - HueLightStatus1(i, &response); - HueLightStatus2(i, &response); - if (i < maxhue) { - response += ",\""; - } - } - response += F("},\"groups\":{},\"schedules\":{},\"config\":"); - HueConfigResponse(&response); - response += "}"; - WSSend(200, CT_JSON, response); -} - -void HueAuthentication(String *path) -{ - char response[38]; - - snprintf_P(response, sizeof(response), PSTR("[{\"success\":{\"username\":\"%s\"}}]"), GetHueUserId().c_str()); - WSSend(200, CT_JSON, response); -} - -void HueLights(String *path) -{ - - - - String response; - int code = 200; - uint16_t tmp = 0; - uint16_t hue = 0; - uint8_t sat = 0; - uint8_t bri = 254; - uint16_t ct = 0; - bool resp = false; - bool on = false; - bool change = false; - uint8_t device = 1; - uint8_t local_light_subtype = Light.subtype; - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; - - path->remove(0,path->indexOf("/lights")); - if (path->endsWith("/lights")) { - response = "{\""; - for (uint32_t i = 1; i <= maxhue; i++) { - response += EncodeLightId(i); - response += F("\":{\"state\":"); - HueLightStatus1(i, &response); - HueLightStatus2(i, &response); - if (i < maxhue) { - response += ",\""; - } - } - response += "}"; - } - else if (path->endsWith("/state")) { - path->remove(0,8); - path->remove(path->indexOf("/state")); - device = DecodeLightId(atoi(path->c_str())); - if ((device < 1) || (device > maxhue)) { - device = 1; - } - local_light_subtype = getLocalLightSubtype(device); - - if (WebServer->args()) { - response = "["; - - StaticJsonBuffer<400> jsonBuffer; - JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); - if (hue_json.containsKey("on")) { - - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "on"); - - on = hue_json["on"]; - switch(on) - { - case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); - response.replace("{re", "false"); - break; - case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); - response.replace("{re", "true"); - break; - default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); - break; - } - resp = true; - } - - if (light_type && (local_light_subtype >= LST_SINGLE)) { - if (!Settings.flag3.pwm_multi_channels) { - light_state.getHSB(&hue, &sat, nullptr); - bri = light_state.getBri(); - ct = light_state.getCT(); - uint8_t color_mode = light_state.getColorMode(); - if (LCM_RGB == color_mode) { g_gotct = false; } - if (LCM_CT == color_mode) { g_gotct = true; } - - } else { - bri = LightGetBri(device); - } - } - prev_x_str[0] = prev_y_str[0] = 0; - - if (hue_json.containsKey("bri")) { - tmp = hue_json["bri"]; - prev_bri = bri = tmp; - - if (254 <= bri) { bri = 255; } - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "bri"); - response.replace("{re", String(tmp)); - if (LST_SINGLE <= Light.subtype) { - change = true; - } - resp = true; - } - - - if (hue_json.containsKey("xy")) { - float x, y; - x = hue_json["xy"][0]; - y = hue_json["xy"][1]; - const String &x_str = hue_json["xy"][0]; - const String &y_str = hue_json["xy"][1]; - x_str.toCharArray(prev_x_str, sizeof(prev_x_str)); - y_str.toCharArray(prev_y_str, sizeof(prev_y_str)); - - uint8_t rr,gg,bb; - LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); - LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); - prev_hue = changeUIntScale(hue, 0, 359, 0, 65535); - prev_sat = (sat > 254 ? 254 : sat); - - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "xy"); - response.replace("{re", "[" + x_str + "," + y_str + "]"); - g_gotct = false; - resp = true; - change = true; - } - if (hue_json.containsKey("hue")) { - tmp = hue_json["hue"]; - prev_hue = tmp; - - hue = changeUIntScale(tmp, 0, 65535, 0, 359); - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "hue"); - response.replace("{re", String(tmp)); - if (LST_RGB <= Light.subtype) { - g_gotct = false; - change = true; - } - resp = true; - } - if (hue_json.containsKey("sat")) { - tmp = hue_json["sat"]; - prev_sat = sat = tmp; - - if (254 <= sat) { sat = 255; } - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "sat"); - response.replace("{re", String(tmp)); - if (LST_RGB <= Light.subtype) { - g_gotct = false; - change = true; - } - resp = true; - } - if (hue_json.containsKey("ct")) { - ct = hue_json["ct"]; - prev_ct = ct; - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "ct"); - response.replace("{re", String(ct)); - if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { - g_gotct = true; - change = true; - } - resp = true; - } - if (change) { - if (light_type && (local_light_subtype > LST_NONE)) { - if (!Settings.flag3.pwm_multi_channels) { - if (g_gotct) { - light_controller.changeCTB(ct, bri); - } else { - light_controller.changeHSB(hue, sat, bri); - } - LightPreparePower(); - } else { - LightSetBri(device, bri); - } - if (LST_COLDWARM <= local_light_subtype) { - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR)); - } else { - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_DIMMER)); - } - XdrvRulesProcess(); - } - change = false; - } - response += "]"; - if (2 == response.length()) { - response = FPSTR(HUE_ERROR_JSON); - } - } - else { - response = FPSTR(HUE_ERROR_JSON); - } - } - else if(path->indexOf("/lights/") >= 0) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "/lights path=%s", path->c_str()); - path->remove(0,8); - device = DecodeLightId(atoi(path->c_str())); - if ((device < 1) || (device > maxhue)) { - device = 1; - } - response += F("{\"state\":"); - HueLightStatus1(device, &response); - HueLightStatus2(device, &response); - } - else { - response = "{}"; - code = 406; - } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); - WSSend(code, CT_JSON, response); -} - -void HueGroups(String *path) -{ - - - - String response = "{}"; - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; - - if (path->endsWith("/0")) { - response = FPSTR(HUE_GROUP0_STATUS_JSON); - String lights = F("\"1\""); - for (uint32_t i = 2; i <= maxhue; i++) { - lights += ",\""; - lights += EncodeLightId(i); - lights += "\""; - } - response.replace("{l1", lights); - HueLightStatus1(1, &response); - response += F("}"); - } - - WSSend(200, CT_JSON, response); -} - -void HandleHueApi(String *path) -{ -# 723 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_20_hue.ino" - uint8_t args = 0; - - path->remove(0, 4); - uint16_t apilen = path->length(); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API " (%s)"), path->c_str()); - for (args = 0; args < WebServer->args(); args++) { - String json = WebServer->arg(args); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_POST_ARGS " (%s)"), json.c_str()); - } - - if (path->endsWith("/invalid/")) {} - else if (!apilen) HueAuthentication(path); - else if (path->endsWith("/")) HueAuthentication(path); - 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 if (path->endsWith("/resourcelinks")) HueNotImplemented(path); - else HueGlobalConfig(path); -} - - - - - -bool Xdrv20(uint8_t function) -{ - bool result = false; - - if (devices_present && (EMUL_HUE == Settings.flag2.emulation)) { - switch (function) { - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/description.xml", HandleUpnpSetupHue); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_21_wemo.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_21_wemo.ino" -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined (USE_EMULATION_WEMO) - - - - -#define XDRV_21 21 - -const char WEMO_MSEARCH[] PROGMEM = - "HTTP/1.1 200 OK\r\n" - "CACHE-CONTROL: max-age=86400\r\n" - "DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n" - "EXT:\r\n" - "LOCATION: http://%s: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: %s\r\n" - "USN: uuid:%s::%s\r\n" - "X-User-Agent: redsonic\r\n" - "\r\n"; - -String WemoSerialnumber(void) -{ - char serial[16]; - - snprintf_P(serial, sizeof(serial), PSTR("201612K%08X"), ESP.getChipId()); - return String(serial); -} - -String WemoUuid(void) -{ - char uuid[27]; - - snprintf_P(uuid, sizeof(uuid), PSTR("Socket-1_0-%s"), WemoSerialnumber().c_str()); - return String(uuid); -} - -void WemoRespondToMSearch(int echo_type) -{ - char message[TOPSZ]; - - TickerMSearch.detach(); - if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { - char type[24]; - if (1 == echo_type) { - strcpy_P(type, URN_BELKIN_DEVICE_CAP); - } else { - strcpy_P(type, UPNP_ROOTDEVICE); - } - char response[400]; - snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), type, WemoUuid().c_str(), type); - PortUdp.write(response); - PortUdp.endPacket(); - snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT)); - } else { - snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"), - echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port); - - udp_response_mutex = false; -} - - - - - -const char WEMO_EVENTSERVICE_XML[] PROGMEM = - "" - "" - "" - "SetBinaryState" - "" - "" - "" - "BinaryState" - "BinaryState" - "in" - "" - "" - "" - "" - "GetBinaryState" - "" - "" - "" - "BinaryState" - "BinaryState" - "out" - "" - "" - "" - "" - "" - "" - "BinaryState" - "bool" - "0" - "" - "" - "level" - "string" - "0" - "" - "" - "\r\n\r\n"; - -const char WEMO_METASERVICE_XML[] PROGMEM = - "" - "" - "1" - "0" - "" - "" - "" - "GetMetaInfo" - "" - "" - "GetMetaInfo" - "MetaInfo" - "in" - "" - "" - "" - "" - "" - "MetaInfo" - "string" - "0" - "" - "" - "\r\n\r\n"; - -const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = - "" - "" - "" - "%d" - "" - "" - "\r\n"; - -const char WEMO_SETUP_XML[] PROGMEM = - "" - "" - "" - "urn:Belkin:device:controllee:1" - "{x1" - "Belkin International Inc." - "Socket" - "3.1415" - "uuid:{x2" - "{x3" - "0" - "" - "" - "urn:Belkin:service:basicevent:1" - "urn:Belkin:serviceId:basicevent1" - "/upnp/control/basicevent1" - "/upnp/event/basicevent1" - "/eventservice.xml" - "" - "" - "urn:Belkin:service:metainfo:1" - "urn:Belkin:serviceId:metainfo1" - "/upnp/control/metainfo1" - "/upnp/event/metainfo1" - "/metainfoservice.xml" - "" - "" - "" - "\r\n"; - - - -void HandleUpnpEvent(void) -{ - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); - - char event[500]; - strlcpy(event, WebServer->arg(0).c_str(), sizeof(event)); - - - - - char state = 'G'; - if (strstr_P(event, PSTR("SetBinaryState")) != nullptr) { - state = 'S'; - uint8_t power = POWER_TOGGLE; - if (strstr_P(event, PSTR("State>10on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); - WebServer->on("/eventservice.xml", HandleUpnpService); - WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); - WebServer->on("/setup.xml", HandleUpnpSetupWemo); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_22_sonoff_ifan.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_22_sonoff_ifan.ino" -#ifdef USE_SONOFF_IFAN - - - - -#define XDRV_22 22 - -const uint8_t MAX_FAN_SPEED = 4; - -const uint8_t kIFan02Speed[MAX_FAN_SPEED] = { 0x00, 0x01, 0x03, 0x05 }; -const uint8_t kIFan03Speed[MAX_FAN_SPEED +2] = { 0x00, 0x01, 0x03, 0x04, 0x05, 0x06 }; -const uint8_t kIFan03Sequence[MAX_FAN_SPEED][MAX_FAN_SPEED] = {{0, 2, 2, 2}, {0, 1, 2, 4}, {1, 1, 2, 5}, {4, 4, 5, 3}}; - -const char kSonoffIfanCommands[] PROGMEM = "|" - D_CMND_FANSPEED; - -void (* const SonoffIfanCommand[])(void) PROGMEM = - { &CmndFanspeed }; - -uint8_t ifan_fanspeed_timer = 0; -uint8_t ifan_fanspeed_goal = 0; -bool ifan_receive_flag = false; -bool ifan_restart_flag = true; - - - -bool IsModuleIfan() -{ - return ((SONOFF_IFAN02 == my_module_type) || (SONOFF_IFAN03 == my_module_type)); -} - -uint8_t MaxFanspeed(void) -{ - return MAX_FAN_SPEED; -} - -uint8_t GetFanspeed(void) -{ - if (ifan_fanspeed_timer) { - return ifan_fanspeed_goal; - } else { - - - - - - - uint8_t fanspeed = (uint8_t)(power &0xF) >> 1; - if (fanspeed) { fanspeed = (fanspeed >> 1) +1; } - return fanspeed; - } -} - - - -void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence) -{ - ifan_fanspeed_timer = 0; - ifan_fanspeed_goal = fanspeed; - - uint8_t fanspeed_now = GetFanspeed(); - - if (fanspeed == fanspeed_now) { return; } - - uint8_t fans = kIFan02Speed[fanspeed]; - if (SONOFF_IFAN03 == my_module_type) { - if (sequence) { - fanspeed = kIFan03Sequence[fanspeed_now][ifan_fanspeed_goal]; - if (fanspeed != ifan_fanspeed_goal) { - if (0 == fanspeed_now) { - ifan_fanspeed_timer = 20; - } else { - ifan_fanspeed_timer = 2; - } - } - } - fans = kIFan03Speed[fanspeed]; - } - for (uint32_t i = 2; i < 5; i++) { - uint8_t state = (fans &1) + POWER_OFF_NO_STATE; - ExecuteCommandPower(i, state, SRC_IGNORE); - fans >>= 1; - } - -#ifdef USE_DOMOTICZ - if (sequence) { DomoticzUpdateFanState(); } -#endif -} - - - -void SonoffIfanReceived(void) -{ - char svalue[32]; - - uint8_t mode = serial_in_buffer[3]; - uint8_t action = serial_in_buffer[6]; - - if (4 == mode) { - if (action < 4) { - - - - - if (action != GetFanspeed()) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), action); - ExecuteCommand(svalue, SRC_REMOTE); -#ifdef USE_BUZZER - BuzzerEnabledBeep(1); -#endif - } - } else { - - ExecuteCommandPower(1, POWER_TOGGLE, SRC_REMOTE); - } - } - if (6 == mode) { - - Settings.flag3.buzzer_enable = !Settings.flag3.buzzer_enable; - } - if (7 == mode) { - -#ifdef USE_BUZZER - BuzzerEnabledBeep(3); -#endif - } - - - - serial_in_buffer[5] = 0; - serial_in_buffer[6] = 0; - for (uint32_t i = 0; i < 7; i++) { - if ((i > 1) && (i < 6)) { serial_in_buffer[6] += serial_in_buffer[i]; } - Serial.write(serial_in_buffer[i]); - } -} - -bool SonoffIfanSerialInput(void) -{ - if (SONOFF_IFAN03 == my_module_type) { - if (0xAA == serial_in_byte) { - serial_in_byte_counter = 0; - ifan_receive_flag = true; - } - if (ifan_receive_flag) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (serial_in_byte_counter == 8) { -# 176 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_22_sonoff_ifan.ino" - AddLogSerial(LOG_LEVEL_DEBUG); - uint8_t crc = 0; - for (uint32_t i = 2; i < 7; i++) { - crc += serial_in_buffer[i]; - } - if (crc == serial_in_buffer[7]) { - SonoffIfanReceived(); - ifan_receive_flag = false; - return true; - } - } - serial_in_byte = 0; - } - return false; - } -} - - - - - -void CmndFanspeed(void) -{ - if (XdrvMailbox.data_len > 0) { - if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (int16_t)GetFanspeed() -1; - if (XdrvMailbox.payload < 0) { XdrvMailbox.payload = MAX_FAN_SPEED -1; } - } - else if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = GetFanspeed() +1; - if (XdrvMailbox.payload > MAX_FAN_SPEED -1) { XdrvMailbox.payload = 0; } - } - } - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_FAN_SPEED)) { - SonoffIFanSetFanspeed(XdrvMailbox.payload, true); - } - ResponseCmndNumber(GetFanspeed()); -} - - - -bool SonoffIfanInit(void) -{ - if (SONOFF_IFAN03 == my_module_type) { - Settings.flag.mqtt_serial = 0; - baudrate = 9600; - SetSeriallog(LOG_LEVEL_NONE); - } - return false; -} - -void SonoffIfanUpdate(void) -{ - if (SONOFF_IFAN03 == my_module_type) { - if (ifan_fanspeed_timer) { - ifan_fanspeed_timer--; - if (!ifan_fanspeed_timer) { - SonoffIFanSetFanspeed(ifan_fanspeed_goal, false); - } - } - } - - if (ifan_restart_flag && (4 == uptime) && (SONOFF_IFAN02 == my_module_type)) { - ifan_restart_flag = false; - SetDevicePower(1, SRC_RETRY); - SetDevicePower(power, SRC_RETRY); - } -} - - - - - -bool Xdrv22(uint8_t function) -{ - bool result = false; - - if (IsModuleIfan()) { - switch (function) { - case FUNC_EVERY_250_MSECOND: - SonoffIfanUpdate(); - break; - case FUNC_SERIAL: - result = SonoffIfanSerialInput(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kSonoffIfanCommands, SonoffIfanCommand); - break; - case FUNC_MODULE_INIT: - result = SonoffIfanInit(); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_0_constants.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_0_constants.ino" -#ifdef USE_ZIGBEE - -typedef uint64_t Z_IEEEAddress; -typedef uint16_t Z_ShortAddress; - -enum ZnpCommandType { - Z_POLL = 0x00, - Z_SREQ = 0x20, - Z_AREQ = 0x40, - Z_SRSP = 0x60 -}; - -enum ZnpSubsystem { - Z_RPC_Error = 0x00, - Z_SYS = 0x01, - Z_MAC = 0x02, - Z_NWK = 0x03, - Z_AF = 0x04, - Z_ZDO = 0x05, - Z_SAPI = 0x06, - Z_UTIL = 0x07, - Z_DEBUG = 0x08, - Z_APP = 0x09 -}; - - -enum SysCommand { - SYS_RESET = 0x00, - SYS_PING = 0x01, - SYS_VERSION = 0x02, - SYS_SET_EXTADDR = 0x03, - SYS_GET_EXTADDR = 0x04, - SYS_RAM_READ = 0x05, - SYS_RAM_WRITE = 0x06, - SYS_OSAL_NV_ITEM_INIT = 0x07, - SYS_OSAL_NV_READ = 0x08, - SYS_OSAL_NV_WRITE = 0x09, - SYS_OSAL_START_TIMER = 0x0A, - SYS_OSAL_STOP_TIMER = 0x0B, - SYS_RANDOM = 0x0C, - SYS_ADC_READ = 0x0D, - SYS_GPIO = 0x0E, - SYS_STACK_TUNE = 0x0F, - SYS_SET_TIME = 0x10, - SYS_GET_TIME = 0x11, - SYS_OSAL_NV_DELETE = 0x12, - SYS_OSAL_NV_LENGTH = 0x13, - SYS_TEST_RF = 0x40, - SYS_TEST_LOOPBACK = 0x41, - SYS_RESET_IND = 0x80, - SYS_OSAL_TIMER_EXPIRED = 0x81, -}; - -enum SapiCommand { - SAPI_START_REQUEST = 0x00, - SAPI_BIND_DEVICE = 0x01, - SAPI_ALLOW_BIND = 0x02, - SAPI_SEND_DATA_REQUEST = 0x03, - SAPI_READ_CONFIGURATION = 0x04, - SAPI_WRITE_CONFIGURATION = 0x05, - SAPI_GET_DEVICE_INFO = 0x06, - SAPI_FIND_DEVICE_REQUEST = 0x07, - SAPI_PERMIT_JOINING_REQUEST = 0x08, - SAPI_SYSTEM_RESET = 0x09, - SAPI_START_CONFIRM = 0x80, - SAPI_BIND_CONFIRM = 0x81, - SAPI_ALLOW_BIND_CONFIRM = 0x82, - SAPI_SEND_DATA_CONFIRM = 0x83, - SAPI_FIND_DEVICE_CONFIRM = 0x85, - SAPI_RECEIVE_DATA_INDICATION = 0x87, -}; -enum Z_configuration { - CONF_EXTADDR = 0x01, - CONF_BOOTCOUNTER = 0x02, - CONF_STARTUP_OPTION = 0x03, - CONF_START_DELAY = 0x04, - CONF_NIB = 0x21, - CONF_DEVICE_LIST = 0x22, - CONF_ADDRMGR = 0x23, - CONF_POLL_RATE = 0x24, - CONF_QUEUED_POLL_RATE = 0x25, - CONF_RESPONSE_POLL_RATE = 0x26, - CONF_REJOIN_POLL_RATE = 0x27, - CONF_DATA_RETRIES = 0x28, - CONF_POLL_FAILURE_RETRIES = 0x29, - CONF_STACK_PROFILE = 0x2A, - CONF_INDIRECT_MSG_TIMEOUT = 0x2B, - CONF_ROUTE_EXPIRY_TIME = 0x2C, - CONF_EXTENDED_PAN_ID = 0x2D, - CONF_BCAST_RETRIES = 0x2E, - CONF_PASSIVE_ACK_TIMEOUT = 0x2F, - CONF_BCAST_DELIVERY_TIME = 0x30, - CONF_NWK_MODE = 0x31, - CONF_CONCENTRATOR_ENABLE = 0x32, - CONF_CONCENTRATOR_DISCOVERY = 0x33, - CONF_CONCENTRATOR_RADIUS = 0x34, - CONF_CONCENTRATOR_RC = 0x36, - CONF_NWK_MGR_MODE = 0x37, - CONF_SRC_RTG_EXPIRY_TIME = 0x38, - CONF_ROUTE_DISCOVERY_TIME = 0x39, - CONF_NWK_ACTIVE_KEY_INFO = 0x3A, - CONF_NWK_ALTERN_KEY_INFO = 0x3B, - CONF_ROUTER_OFF_ASSOC_CLEANUP = 0x3C, - CONF_NWK_LEAVE_REQ_ALLOWED = 0x3D, - CONF_NWK_CHILD_AGE_ENABLE = 0x3E, - CONF_DEVICE_LIST_KA_TIMEOUT = 0x3F, - CONF_BINDING_TABLE = 0x41, - CONF_GROUP_TABLE = 0x42, - CONF_APS_FRAME_RETRIES = 0x43, - CONF_APS_ACK_WAIT_DURATION = 0x44, - CONF_APS_ACK_WAIT_MULTIPLIER = 0x45, - CONF_BINDING_TIME = 0x46, - CONF_APS_USE_EXT_PANID = 0x47, - CONF_APS_USE_INSECURE_JOIN = 0x48, - CONF_COMMISSIONED_NWK_ADDR = 0x49, - CONF_APS_NONMEMBER_RADIUS = 0x4B, - CONF_APS_LINK_KEY_TABLE = 0x4C, - CONF_APS_DUPREJ_TIMEOUT_INC = 0x4D, - CONF_APS_DUPREJ_TIMEOUT_COUNT = 0x4E, - CONF_APS_DUPREJ_TABLE_SIZE = 0x4F, - CONF_DIAGNOSTIC_STATS = 0x50, - CONF_SECURITY_LEVEL = 0x61, - CONF_PRECFGKEY = 0x62, - CONF_PRECFGKEYS_ENABLE = 0x63, - CONF_SECURITY_MODE = 0x64, - CONF_SECURE_PERMIT_JOIN = 0x65, - CONF_APS_LINK_KEY_TYPE = 0x66, - CONF_APS_ALLOW_R19_SECURITY = 0x67, - CONF_IMPLICIT_CERTIFICATE = 0x69, - CONF_DEVICE_PRIVATE_KEY = 0x6A, - CONF_CA_PUBLIC_KEY = 0x6B, - CONF_KE_MAX_DEVICES = 0x6C, - CONF_USE_DEFAULT_TCLK = 0x6D, - CONF_RNG_COUNTER = 0x6F, - CONF_RANDOM_SEED = 0x70, - CONF_TRUSTCENTER_ADDR = 0x71, - CONF_USERDESC = 0x81, - CONF_NWKKEY = 0x82, - CONF_PANID = 0x83, - CONF_CHANLIST = 0x84, - CONF_LEAVE_CTRL = 0x85, - CONF_SCAN_DURATION = 0x86, - CONF_LOGICAL_TYPE = 0x87, - CONF_NWKMGR_MIN_TX = 0x88, - CONF_NWKMGR_ADDR = 0x89, - CONF_ZDO_DIRECT_CB = 0x8F, - CONF_TCLK_TABLE_START = 0x0101, - ZNP_HAS_CONFIGURED = 0xF00 -}; -# 208 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_0_constants.ino" -enum Z_Status { - Z_Success = 0x00, - Z_Failure = 0x01, - Z_InvalidParameter = 0x02, - Z_MemError = 0x03, - Z_Created = 0x09, - Z_BufferFull = 0x11 -}; - -enum Z_App_Profiles { - Z_PROF_IPM = 0x0101, - Z_PROF_HA = 0x0104, - Z_PROF_CBA = 0x0105, - Z_PROF_TA = 0x0107, - Z_PROF_PHHC = 0x0108, - Z_PROF_AMI = 0x0109, -}; - -enum Z_Device_Ids { - Z_DEVID_CONF_TOOL = 0x0005, -# 260 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_0_constants.ino" -}; -# 273 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_0_constants.ino" -enum AfCommand : uint8_t { - AF_REGISTER = 0x00, - AF_DATA_REQUEST = 0x01, - AF_DATA_REQUEST_EXT = 0x02, - AF_DATA_REQUEST_SRC_RTG = 0x03, - AF_INTER_PAN_CTL = 0x10, - AF_DATA_STORE = 0x11, - AF_DATA_RETRIEVE = 0x12, - AF_APSF_CONFIG_SET = 0x13, - AF_DATA_CONFIRM = 0x80, - AF_REFLECT_ERROR = 0x83, - AF_INCOMING_MSG = 0x81, - AF_INCOMING_MSG_EXT = 0x82 -}; - - -enum : uint8_t { - ZDO_NWK_ADDR_REQ = 0x00, - ZDO_IEEE_ADDR_REQ = 0x01, - ZDO_NODE_DESC_REQ = 0x02, - ZDO_POWER_DESC_REQ = 0x03, - ZDO_SIMPLE_DESC_REQ = 0x04, - ZDO_ACTIVE_EP_REQ = 0x05, - ZDO_MATCH_DESC_REQ = 0x06, - ZDO_COMPLEX_DESC_REQ = 0x07, - ZDO_USER_DESC_REQ = 0x08, - ZDO_DEVICE_ANNCE = 0x0A, - ZDO_USER_DESC_SET = 0x0B, - ZDO_SERVER_DISC_REQ = 0x0C, - ZDO_END_DEVICE_BIND_REQ = 0x20, - ZDO_BIND_REQ = 0x21, - ZDO_UNBIND_REQ = 0x22, - ZDO_SET_LINK_KEY = 0x23, - ZDO_REMOVE_LINK_KEY = 0x24, - ZDO_GET_LINK_KEY = 0x25, - ZDO_MGMT_NWK_DISC_REQ = 0x30, - ZDO_MGMT_LQI_REQ = 0x31, - ZDO_MGMT_RTQ_REQ = 0x32, - ZDO_MGMT_BIND_REQ = 0x33, - ZDO_MGMT_LEAVE_REQ = 0x34, - ZDO_MGMT_DIRECT_JOIN_REQ = 0x35, - ZDO_MGMT_PERMIT_JOIN_REQ = 0x36, - ZDO_MGMT_NWK_UPDATE_REQ = 0x37, - ZDO_MSG_CB_REGISTER = 0x3E, - ZDO_MGS_CB_REMOVE = 0x3F, - ZDO_STARTUP_FROM_APP = 0x40, - ZDO_AUTO_FIND_DESTINATION = 0x41, - ZDO_EXT_REMOVE_GROUP = 0x47, - ZDO_EXT_REMOVE_ALL_GROUP = 0x48, - ZDO_EXT_FIND_ALL_GROUPS_ENDPOINT = 0x49, - ZDO_EXT_FIND_GROUP = 0x4A, - ZDO_EXT_ADD_GROUP = 0x4B, - ZDO_EXT_COUNT_ALL_GROUPS = 0x4C, - ZDO_NWK_ADDR_RSP = 0x80, - ZDO_IEEE_ADDR_RSP = 0x81, - ZDO_NODE_DESC_RSP = 0x82, - ZDO_POWER_DESC_RSP = 0x83, - ZDO_SIMPLE_DESC_RSP = 0x84, - ZDO_ACTIVE_EP_RSP = 0x85, - ZDO_MATCH_DESC_RSP = 0x86, - ZDO_COMPLEX_DESC_RSP = 0x87, - ZDO_USER_DESC_RSP = 0x88, - ZDO_USER_DESC_CONF = 0x89, - ZDO_SERVER_DISC_RSP = 0x8A, - ZDO_END_DEVICE_BIND_RSP = 0xA0, - ZDO_BIND_RSP = 0xA1, - ZDO_UNBIND_RSP = 0xA2, - ZDO_MGMT_NWK_DISC_RSP = 0xB0, - ZDO_MGMT_LQI_RSP = 0xB1, - ZDO_MGMT_RTG_RSP = 0xB2, - ZDO_MGMT_BIND_RSP = 0xB3, - ZDO_MGMT_LEAVE_RSP = 0xB4, - ZDO_MGMT_DIRECT_JOIN_RSP = 0xB5, - ZDO_MGMT_PERMIT_JOIN_RSP = 0xB6, - ZDO_STATE_CHANGE_IND = 0xC0, - ZDO_END_DEVICE_ANNCE_IND = 0xC1, - ZDO_MATCH_DESC_RSP_SENT = 0xC2, - ZDO_STATUS_ERROR_RSP = 0xC3, - ZDO_SRC_RTG_IND = 0xC4, - ZDO_LEAVE_IND = 0xC9, - ZDO_TC_DEV_IND = 0xCA, - ZDO_PERMIT_JOIN_IND = 0xCB, - ZDO_MSG_CB_INCOMING = 0xFF -}; - - -enum ZdoStates { - ZDO_DEV_HOLD = 0x00, - ZDO_DEV_INIT = 0x01, - ZDO_DEV_NWK_DISC = 0x02, - ZDO_DEV_NWK_JOINING = 0x03, - ZDO_DEV_NWK_REJOIN = 0x04, - ZDO_DEV_END_DEVICE_UNAUTH = 0x05, - ZDO_DEV_END_DEVICE = 0x06, - ZDO_DEV_ROUTER = 0x07, - ZDO_DEV_COORD_STARTING = 0x08, - ZDO_DEV_ZB_COORD = 0x09, - ZDO_DEV_NWK_ORPHAN = 0x0A, -}; - - -enum Z_Util { - Z_UTIL_GET_DEVICE_INFO = 0x00, - Z_UTIL_GET_NV_INFO = 0x01, - Z_UTIL_SET_PANID = 0x02, - Z_UTIL_SET_CHANNELS = 0x03, - Z_UTIL_SET_SECLEVEL = 0x04, - Z_UTIL_SET_PRECFGKEY = 0x05, - Z_UTIL_CALLBACK_SUB_CMD = 0x06, - Z_UTIL_KEY_EVENT = 0x07, - Z_UTIL_TIME_ALIVE = 0x09, - Z_UTIL_LED_CONTROL = 0x0A, - Z_UTIL_TEST_LOOPBACK = 0x10, - Z_UTIL_DATA_REQ = 0x11, - Z_UTIL_SRC_MATCH_ENABLE = 0x20, - Z_UTIL_SRC_MATCH_ADD_ENTRY = 0x21, - Z_UTIL_SRC_MATCH_DEL_ENTRY = 0x22, - Z_UTIL_SRC_MATCH_CHECK_SRC_ADDR = 0x23, - Z_UTIL_SRC_MATCH_ACK_ALL_PENDING = 0x24, - Z_UTIL_SRC_MATCH_CHECK_ALL_PENDING = 0x25, - Z_UTIL_ADDRMGR_EXT_ADDR_LOOKUP = 0x40, - Z_UTIL_ADDRMGR_NWK_ADDR_LOOKUP = 0x41, - Z_UTIL_APSME_LINK_KEY_DATA_GET = 0x44, - Z_UTIL_APSME_LINK_KEY_NV_ID_GET = 0x45, - Z_UTIL_ASSOC_COUNT = 0x48, - Z_UTIL_ASSOC_FIND_DEVICE = 0x49, - Z_UTIL_ASSOC_GET_WITH_ADDRESS = 0x4A, - Z_UTIL_APSME_REQUEST_KEY_CMD = 0x4B, - Z_UTIL_ZCL_KEY_EST_INIT_EST = 0x80, - Z_UTIL_ZCL_KEY_EST_SIGN = 0x81, - Z_UTIL_UTIL_SYNC_REQ = 0xE0, - Z_UTIL_ZCL_KEY_ESTABLISH_IND = 0xE1 -}; - -enum ZCL_Global_Commands { - ZCL_READ_ATTRIBUTES = 0x00, - ZCL_READ_ATTRIBUTES_RESPONSE = 0x01, - ZCL_WRITE_ATTRIBUTES = 0x02, - ZCL_WRITE_ATTRIBUTES_UNDIVIDED = 0x03, - ZCL_WRITE_ATTRIBUTES_RESPONSE = 0x04, - ZCL_WRITE_ATTRIBUTES_NORESPONSE = 0x05, - ZCL_CONFIGURE_REPORTING = 0x06, - ZCL_CONFIGURE_REPORTING_RESPONSE = 0x07, - ZCL_READ_REPORTING_CONFIGURATION = 0x08, - ZCL_READ_REPORTING_CONFIGURATION_RESPONSE = 0x09, - ZCL_REPORT_ATTRIBUTES = 0x0a, - ZCL_DEFAULT_RESPONSE = 0x0b, - ZCL_DISCOVER_ATTRIBUTES = 0x0c, - ZCL_DISCOVER_ATTRIBUTES_RESPONSE = 0x0d - -}; - -enum class ZclGlobalCommandId : uint8_t { -}; - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_4_converters.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_4_converters.ino" -#ifdef USE_ZIGBEE - - - - - -typedef union ZCLHeaderFrameControl_t { - struct { - uint8_t frame_type : 2; - uint8_t manuf_specific : 1; - uint8_t direction : 1; - uint8_t disable_def_resp : 1; - uint8_t reserved : 3; - } b; - uint32_t d8; -} ZCLHeaderFrameControl_t; - - -class ZCLFrame { -public: - - ZCLFrame(uint8_t frame_control, uint16_t manuf_code, uint8_t transact_seq, uint8_t cmd_id, - const char *buf, size_t buf_len, uint16_t clusterid = 0, uint16_t groupid = 0): - _cmd_id(cmd_id), _manuf_code(manuf_code), _transact_seq(transact_seq), - _payload(buf_len ? buf_len : 250), - _cluster_id(clusterid), _group_id(groupid) - { - _frame_control.d8 = frame_control; - _payload.addBuffer(buf, buf_len); - }; - - - void publishMQTTReceived(uint16_t groupid, uint16_t clusterid, Z_ShortAddress srcaddr, - uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, - uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, - uint32_t timestamp) { - char hex_char[_payload.len()*2+2]; - ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); - Response_P(PSTR("{\"" D_JSON_ZIGBEEZCLRECEIVED "\":{" - "\"groupid\":%d," "\"clusterid\":%d," "\"srcaddr\":\"0x%04X\"," - "\"srcendpoint\":%d," "\"dstendpoint\":%d," "\"wasbroadcast\":%d," - "\"linkquality\":%d," "\"securityuse\":%d," "\"seqnumber\":%d," - "\"timestamp\":%d," - "\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," - "\"cmdid\":\"0x%02X\",\"payload\":\"%s\""), - groupid, clusterid, srcaddr, - srcendpoint, dstendpoint, wasbroadcast, - linkquality, securityuse, seqnumber, - timestamp, - _frame_control, _manuf_code, _transact_seq, _cmd_id, - hex_char); - - ResponseJsonEnd(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLSENT)); - XdrvRulesProcess(); - } - - static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid) { - uint32_t i = offset; - ZCLHeaderFrameControl_t frame_control; - uint16_t manuf_code = 0; - uint8_t transact_seq; - uint8_t cmd_id; - - frame_control.d8 = buf.get8(i++); - if (frame_control.b.manuf_specific) { - manuf_code = buf.get16(i); - i += 2; - } - transact_seq = buf.get8(i++); - cmd_id = buf.get8(i++); - ZCLFrame zcl_frame(frame_control.d8, manuf_code, transact_seq, cmd_id, - (const char *)(buf.buf() + i), len + offset - i, - clusterid, groupid); - return zcl_frame; - } - - bool isClusterSpecificCommand(void) { - return _frame_control.b.frame_type & 1; - } - - void parseRawAttributes(JsonObject& json, uint8_t offset = 0); - void parseClusterSpecificCommand(JsonObject& json, uint8_t offset = 0); - void postProcessAttributes(JsonObject& json); - - inline void setGroupId(uint16_t groupid) { - _group_id = groupid; - } - - inline void setClusterId(uint16_t clusterid) { - _cluster_id = clusterid; - } - - inline uint8_t getCmdId(void) const { - return _cmd_id; - } - - inline uint16_t getClusterId(void) const { - return _cluster_id; - } - - const SBuffer &getPayload(void) const { - return _payload; - } - -private: - ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 }; - uint16_t _manuf_code = 0; - uint8_t _transact_seq = 0; - uint8_t _cmd_id = 0; - uint16_t _cluster_id = 0; - uint16_t _group_id = 0; - SBuffer _payload; -}; - - - - - - - -uint8_t toPercentageCR2032(uint32_t voltage) { - uint32_t percentage; - if (voltage < 2100) { - percentage = 0; - } else if (voltage < 2440) { - percentage = 6 - ((2440 - voltage) * 6) / 340; - } else if (voltage < 2740) { - percentage = 18 - ((2740 - voltage) * 12) / 300; - } else if (voltage < 2900) { - percentage = 42 - ((2900 - voltage) * 24) / 160; - } else if (voltage < 3000) { - percentage = 100 - ((3000 - voltage) * 58) / 100; - } else if (voltage >= 3000) { - percentage = 100; - } - return percentage; -} - - -uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer &buf, - uint32_t offset, uint32_t len) { - - uint32_t i = offset; - uint32_t attrtype = buf.get8(i++); - - - json[attrid_str] = (char*) nullptr; - - - switch (attrtype) { - case 0x00: - case 0xFF: - break; - case 0x10: - { - uint8_t val_bool = buf.get8(i++); - if (0xFF != val_bool) { - json[attrid_str] = (bool) (val_bool ? true : false); - } - } - break; - case 0x20: - { - uint8_t uint8_val = buf.get8(i); - i += 1; - if (0xFF != uint8_val) { - json[attrid_str] = uint8_val; - } - } - break; - case 0x21: - { - uint16_t uint16_val = buf.get16(i); - i += 2; - if (0xFFFF != uint16_val) { - json[attrid_str] = uint16_val; - } - } - break; - case 0x23: - { - uint32_t uint32_val = buf.get32(i); - i += 4; - if (0xFFFFFFFF != uint32_val) { - json[attrid_str] = uint32_val; - } - } - break; - - case 0x24: - case 0x25: - case 0x26: - case 0x27: - i += attrtype - 0x1F; - break; - case 0x28: - { - int8_t int8_val = buf.get8(i); - i += 1; - if (0x80 != int8_val) { - json[attrid_str] = int8_val; - } - } - break; - case 0x29: - { - int16_t int16_val = buf.get16(i); - i += 2; - if (0x8000 != int16_val) { - json[attrid_str] = int16_val; - } - } - break; - case 0x2B: - { - int32_t int32_val = buf.get32(i); - i += 4; - if (0x80000000 != int32_val) { - json[attrid_str] = int32_val; - } - } - break; - - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - i += attrtype - 0x27; - break; - - case 0x41: - case 0x42: - case 0x43: - case 0x44: - - { - bool parse_as_string = true; - uint32_t len = (attrtype <= 0x42) ? buf.get8(i) : buf.get16(i); - i += (attrtype <= 0x42) ? 1 : 2; - - - if ((0x41 == attrtype) || (0x43 == attrtype)) { parse_as_string = false; } - else { - for (uint32_t j = 0; j < len; j++) { - if (0x00 == buf.get8(i+j)) { - parse_as_string = false; - break; - } - } - } - - if (parse_as_string) { - char str[len+1]; - strncpy(str, buf.charptr(i), len); - str[len] = 0x00; - json[attrid_str] = str; - } else { - - char hex[2*len+1]; - ToHex_P(buf.buf(i), len, hex, sizeof(hex)); - json[attrid_str] = hex; - } - - i += len; - break; - } - i += buf.get8(i) + 1; - break; - - - - case 0x08: - i++; - break; - case 0x18: - i++; - break; - case 0x19: - i += 2; - break; - case 0x1B: - i += 4; - break; - - case 0x30: - case 0x31: - i += attrtype - 0x2F; - break; - - case 0x39: - i += 4; - break; - - case 0xE0: - case 0xE1: - case 0xE2: - i += 4; - break; - - case 0xE8: - case 0xE9: - i += 2; - break; - case 0xEA: - i += 4; - break; - - case 0xF0: - i += 8; - break; - case 0xF1: - i += 16; - break; - - - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - i += attrtype - 0x07; - break; - - case 0x1A: - case 0x1C: - case 0x1D: - case 0x1E: - case 0x1F: - i += attrtype - 0x17; - break; - - case 0x38: - i += 2; - break; - case 0x3A: - i += 8; - break; - } - - - - - - - return i - offset; -} - - - - -void ZCLFrame::parseRawAttributes(JsonObject& json, uint8_t offset) { - uint32_t i = offset; - uint32_t len = _payload.len(); - uint32_t attrid = _cluster_id << 16; - - while (len + offset - i >= 3) { - attrid = (attrid & 0xFFFF0000) | _payload.get16(i); - i += 2; - - char shortaddr[12]; - snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%08X"), attrid); - - - if (0x0000FF01 == attrid) { - if (0x42 == _payload.get8(i)) { - _payload.set8(i, 0x41); - } - } - i += parseSingleAttribute(json, shortaddr, _payload, i, len); - } -} - - - -void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { - uint32_t i = offset; - uint32_t len = _payload.len(); - uint32_t attrid = _cluster_id << 8 | _cmd_id; - - char attrid_str[12]; - snprintf_P(attrid_str, sizeof(attrid_str), PSTR("0x%06X"), attrid); - - char hex_char[_payload.len()*2+2]; - ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); - - json[attrid_str] = hex_char; -} - -#define ZCL_MODELID "0x00000005" -#define ZCL_TEMPERATURE "0x04020000" -#define ZCL_PRESSURE "0x04030000" -#define ZCL_PRESSURE_SCALED "0x04030010" -#define ZCL_PRESSURE_SCALE "0x04030014" -#define ZCL_HUMIDITY "0x04050000" -#define ZCL_LUMI_WEATHER "0x0000FF01" - -#define ZCL_OO_OFF "0x000600" -#define ZCL_OO_ON "0x000601" -#define ZCL_COLORTEMP_MOVE "0x03000A" -#define ZCL_LC_MOVE "0x000800" -#define ZCL_LC_MOVE_1 "0x000801" -#define ZCL_LC_STEP "0x000802" -#define ZCL_LC_STOP "0x000803" -#define ZCL_LC_MOVE_WOO "0x000804" -#define ZCL_LC_MOVE_1_WOO "0x000805" -#define ZCL_LC_STEP_WOO "0x000806" -#define ZCL_LC_STOP_WOO "0x000807" - -void ZCLFrame::postProcessAttributes(JsonObject& json) { - const __FlashStringHelper *key; - - - key = F(ZCL_MODELID); - if (json.containsKey(key)) { - json[F(D_JSON_MODEL D_JSON_ID)] = json[key]; - json.remove(key); - } - - - key = F(ZCL_TEMPERATURE); - if (json.containsKey(key)) { - - int32_t temperature = json[key]; - json.remove(key); - json[F(D_JSON_TEMPERATURE)] = temperature / 100.0f; - } - - - key = F(ZCL_PRESSURE); - if (json.containsKey(key)) { - json[F(D_JSON_PRESSURE)] = json[key]; - json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); - json.remove(key); - } - json.remove(F(ZCL_PRESSURE_SCALE)); - json.remove(F(ZCL_PRESSURE_SCALED)); - - - key = F(ZCL_HUMIDITY); - if (json.containsKey(key)) { - - uint32_t humidity = json[key]; - json.remove(key); - json[F(D_JSON_HUMIDITY)] = humidity / 100.0f; - } - - - key = F(ZCL_OO_OFF); - if (json.containsKey(key)) { - json.remove(key); - json[F(D_CMND_POWER)] = F("Off"); - } - key = F(ZCL_OO_ON); - if (json.containsKey(key)) { - json.remove(key); - json[F(D_CMND_POWER)] = F("On"); - } - key = F(ZCL_COLORTEMP_MOVE); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint16_t color_temp = buf2.get16(0); - uint16_t transition_time = buf2.get16(2); - json.remove(key); - json[F("ColorTemp")] = color_temp; - json[F("TransitionTime")] = transition_time / 10.0f; - } - key = F(ZCL_LC_MOVE_WOO); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint8_t level = buf2.get8(0); - uint16_t transition_time = buf2.get16(1); - json.remove(key); - json[F("Dimmer")] = changeUIntScale(level, 0, 255, 0, 100); - json[F("TransitionTime")] = transition_time / 10.0f; - if (0 == level) { - json[F(D_CMND_POWER)] = F("Off"); - } else { - json[F(D_CMND_POWER)] = F("On"); - } - } - key = F(ZCL_LC_MOVE); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint8_t level = buf2.get8(0); - uint16_t transition_time = buf2.get16(1); - json.remove(key); - json[F("Dimmer")] = changeUIntScale(level, 0, 255, 0, 100); - json[F("TransitionTime")] = transition_time / 10.0f; - } - key = F(ZCL_LC_MOVE_1); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint8_t move_mode = buf2.get8(0); - uint8_t move_rate = buf2.get8(1); - json.remove(key); - json[F("Move")] = move_mode ? F("Down") : F("Up"); - json[F("Rate")] = move_rate; - } - key = F(ZCL_LC_MOVE_1_WOO); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint8_t move_mode = buf2.get8(0); - uint8_t move_rate = buf2.get8(1); - json.remove(key); - json[F("Move")] = move_mode ? F("Down") : F("Up"); - json[F("Rate")] = move_rate; - if (0 == move_mode) { - json[F(D_CMND_POWER)] = F("On"); - } - } - key = F(ZCL_LC_STEP); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint8_t step_mode = buf2.get8(0); - uint8_t step_size = buf2.get8(1); - uint16_t transition_time = buf2.get16(2); - json.remove(key); - json[F("Step")] = step_mode ? F("Down") : F("Up"); - json[F("StepSize")] = step_size; - json[F("TransitionTime")] = transition_time / 10.0f; - } - key = F(ZCL_LC_STEP_WOO); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint8_t step_mode = buf2.get8(0); - uint8_t step_size = buf2.get8(1); - uint16_t transition_time = buf2.get16(2); - json.remove(key); - json[F("Step")] = step_mode ? F("Down") : F("Up"); - json[F("StepSize")] = step_size; - json[F("TransitionTime")] = transition_time / 10.0f; - if (0 == step_mode) { - json[F(D_CMND_POWER)] = F("On"); - } - } - key = F(ZCL_LC_STOP); - if (json.containsKey(key)) { - json.remove(key); - json[F("Stop")] = 1; - } - key = F(ZCL_LC_STOP_WOO); - if (json.containsKey(key)) { - json.remove(key); - json[F("Stop")] = 1; - } - - - key = F(ZCL_LUMI_WEATHER); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - DynamicJsonBuffer jsonBuffer; - JsonObject& json_lumi = jsonBuffer.createObject(); - uint32_t i = 0; - uint32_t len = buf2.len(); - char shortaddr[8]; - - while (len - i >= 2) { - uint8_t attrid = buf2.get8(i++); - - snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%02X"), attrid); - - i += parseSingleAttribute(json_lumi, shortaddr, buf2, i, len); - } - - if (json_lumi.containsKey("0x64")) { - int32_t temperature = json_lumi["0x64"]; - json[F(D_JSON_TEMPERATURE)] = temperature / 100.0f; - } - if (json_lumi.containsKey("0x65")) { - uint32_t humidity = json_lumi["0x65"]; - json[F(D_JSON_HUMIDITY)] = humidity / 100.0f; - } - if (json_lumi.containsKey("0x66")) { - int32_t pressure = json_lumi["0x66"]; - json[F(D_JSON_PRESSURE)] = pressure / 100.0f; - json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); - } - if (json_lumi.containsKey("0x01")) { - uint32_t voltage = json_lumi["0x01"]; - json[F(D_JSON_VOLTAGE)] = voltage / 1000.0f; - json[F("Battery")] = toPercentageCR2032(voltage); - } - json.remove(key); - } - -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_9_impl.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_9_impl.ino" -#ifdef USE_ZIGBEE - -#define XDRV_23 23 - -const uint32_t ZIGBEE_BUFFER_SIZE = 256; -const uint8_t ZIGBEE_SOF = 0xFE; - - - -const uint8_t ZIGBEE_STATUS_OK = 0; -const uint8_t ZIGBEE_STATUS_BOOT = 1; -const uint8_t ZIGBEE_STATUS_RESET_CONF = 2; -const uint8_t ZIGBEE_STATUS_STARTING = 3; -const uint8_t ZIGBEE_STATUS_PERMITJOIN_CLOSE = 20; -const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_60 = 21; -const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_XX = 22; -const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; -const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; -const uint8_t ZIGBEE_STATUS_CC_INFO = 51; -const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; -const uint8_t ZIGBEE_STATUS_ABORT = 99; - - - -#ifdef Z_USE_SOFTWARE_SERIAL -#include -SoftwareSerial *ZigbeeSerial = nullptr; -#else -#include -TasmotaSerial *ZigbeeSerial = nullptr; -#endif - - -const char kZigbeeCommands[] PROGMEM = "|" D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN; - -void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZigbeeZNPSend, &CmndZigbeePermitJoin }; - -typedef int32_t (*ZB_Func)(uint8_t value); -typedef int32_t (*ZB_RecvMsgFunc)(int32_t res, class SBuffer &buf); - -typedef union Zigbee_Instruction { - struct { - uint8_t i; - uint8_t d8; - uint16_t d16; - } i; - const void *p; - - - -} Zigbee_Instruction; - - - - -typedef struct Zigbee_Instruction_Type { - uint8_t instr; - uint8_t data; -} Zigbee_Instruction_Type; - -enum Zigbee_StateMachine_Instruction_Set { - - ZGB_INSTR_4_BYTES = 0, - ZGB_INSTR_NOOP = 0, - ZGB_INSTR_LABEL, - ZGB_INSTR_GOTO, - ZGB_INSTR_ON_ERROR_GOTO, - ZGB_INSTR_ON_TIMEOUT_GOTO, - ZGB_INSTR_WAIT, - ZGB_INSTR_WAIT_FOREVER, - ZGB_INSTR_STOP, - - - ZGB_INSTR_8_BYTES = 0x80, - ZGB_INSTR_CALL = 0x80, - ZGB_INSTR_LOG, - ZGB_INSTR_MQTT_STATUS, - ZGB_INSTR_SEND, - ZGB_INSTR_WAIT_UNTIL, - ZGB_INSTR_WAIT_RECV, - ZGB_ON_RECV_UNEXPECTED, - - - ZGB_INSTR_12_BYTES = 0xF0, - ZGB_INSTR_WAIT_RECV_CALL, -}; - -#define ZI_NOOP() { .i = { ZGB_INSTR_NOOP, 0x00, 0x0000} }, -#define ZI_LABEL(x) { .i = { ZGB_INSTR_LABEL, (x), 0x0000} }, -#define ZI_GOTO(x) { .i = { ZGB_INSTR_GOTO, (x), 0x0000} }, -#define ZI_ON_ERROR_GOTO(x) { .i = { ZGB_INSTR_ON_ERROR_GOTO, (x), 0x0000} }, -#define ZI_ON_TIMEOUT_GOTO(x) { .i = { ZGB_INSTR_ON_TIMEOUT_GOTO, (x), 0x0000} }, -#define ZI_WAIT(x) { .i = { ZGB_INSTR_WAIT, 0x00, (x)} }, -#define ZI_WAIT_FOREVER() { .i = { ZGB_INSTR_WAIT_FOREVER, 0x00, 0x0000} }, -#define ZI_STOP(x) { .i = { ZGB_INSTR_STOP, (x), 0x0000} }, - -#define ZI_CALL(f,x) { .i = { ZGB_INSTR_CALL, (x), 0x0000} }, { .p = (const void*)(f) }, -#define ZI_LOG(x,m) { .i = { ZGB_INSTR_LOG, (x), 0x0000 } }, { .p = ((const void*)(m)) }, -#define ZI_MQTT_STATUS(x,m) { .i = { ZGB_INSTR_MQTT_STATUS, (x), 0x0000 } }, { .p = ((const void*)(m)) }, -#define ZI_ON_RECV_UNEXPECTED(f) { .i = { ZGB_ON_RECV_UNEXPECTED, 0x00, 0x0000} }, { .p = (const void*)(f) }, -#define ZI_SEND(m) { .i = { ZGB_INSTR_SEND, sizeof(m), 0x0000} }, { .p = (const void*)(m) }, -#define ZI_WAIT_RECV(x,m) { .i = { ZGB_INSTR_WAIT_RECV, sizeof(m), (x)} }, { .p = (const void*)(m) }, -#define ZI_WAIT_UNTIL(x,m) { .i = { ZGB_INSTR_WAIT_UNTIL, sizeof(m), (x)} }, { .p = (const void*)(m) }, -#define ZI_WAIT_RECV_FUNC(x,m,f) { .i = { ZGB_INSTR_WAIT_RECV_CALL, sizeof(m), (x)} }, { .p = (const void*)(m) }, { .p = (const void*)(f) }, - - -const uint8_t ZIGBEE_LABEL_START = 10; -const uint8_t ZIGBEE_LABEL_READY = 20; -const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; -const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_CLOSE = 30; -const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60 = 31; -const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX = 32; - -const uint8_t ZIGBEE_LABEL_ABORT = 99; -const uint8_t ZIGBEE_LABEL_UNSUPPORTED_VERSION = 98; - -struct ZigbeeStatus { - bool active = true; - bool state_machine = false; - bool state_waiting = false; - bool state_no_timeout = false; - bool ready = false; - uint8_t on_error_goto = ZIGBEE_LABEL_ABORT; - uint8_t on_timeout_goto = ZIGBEE_LABEL_ABORT; - int16_t pc = 0; - uint32_t next_timeout = 0; - - uint8_t *recv_filter = nullptr; - bool recv_until = false; - size_t recv_filter_len = 0; - ZB_RecvMsgFunc recv_func = nullptr; - ZB_RecvMsgFunc recv_unexpected = nullptr; - - bool init_phase = true; -}; -struct ZigbeeStatus zigbee; - -SBuffer *zigbee_buffer = nullptr; - - - - - -#define Z_B0(a) (uint8_t)( ((a) ) & 0xFF ) -#define Z_B1(a) (uint8_t)( ((a) >> 8) & 0xFF ) -#define Z_B2(a) (uint8_t)( ((a) >> 16) & 0xFF ) -#define Z_B3(a) (uint8_t)( ((a) >> 24) & 0xFF ) -#define Z_B4(a) (uint8_t)( ((a) >> 32) & 0xFF ) -#define Z_B5(a) (uint8_t)( ((a) >> 40) & 0xFF ) -#define Z_B6(a) (uint8_t)( ((a) >> 48) & 0xFF ) -#define Z_B7(a) (uint8_t)( ((a) >> 56) & 0xFF ) - -#define ZBM(n,x...) const uint8_t n[] PROGMEM = { x }; - -#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL)) - - - -ZBM(ZBS_RESET, Z_AREQ | Z_SYS, SYS_RESET, 0x00 ) -ZBM(ZBR_RESET, Z_AREQ | Z_SYS, SYS_RESET_IND ) - -ZBM(ZBS_VERSION, Z_SREQ | Z_SYS, SYS_VERSION ) -ZBM(ZBR_VERSION, Z_SRSP | Z_SYS, SYS_VERSION ) - - -ZBM(ZBS_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, 0x00 ) -ZBM(ZBR_ZNPHC, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_Success, 0x01 , 0x55) - - -ZBM(ZBS_PAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PANID ) -ZBM(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PANID, 0x02 , - Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) - -ZBM(ZBS_EXTPAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_EXTENDED_PAN_ID ) -ZBM(ZBR_EXTPAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_EXTENDED_PAN_ID, - 0x08 , - Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), - Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID), - ) - -ZBM(ZBS_CHANN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_CHANLIST ) -ZBM(ZBR_CHANN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_CHANLIST, - 0x04 , - Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), - ) - -ZBM(ZBS_PFGK, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEY ) -ZBM(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEY, - 0x10 , - Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), - Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), - Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), - Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), - - ) - -ZBM(ZBS_PFGKEN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEYS_ENABLE ) -ZBM(ZBR_PFGKEN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEYS_ENABLE, - 0x01 , 0x00 ) - - - -ZBM(ZBR_W_OK, Z_SRSP | Z_SAPI, SAPI_WRITE_CONFIGURATION, Z_Success ) -ZBM(ZBR_WNV_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_WRITE, Z_Success ) - - -ZBM(ZBS_FACTRES, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 , 0x02 ) - -ZBM(ZBS_W_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 , Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) - -ZBM(ZBS_W_EXTPAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_EXTENDED_PAN_ID, 0x08 , - Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), - Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID) - ) - -ZBM(ZBS_W_CHANN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_CHANLIST, 0x04 , - Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), - ) - -ZBM(ZBS_W_LOGTYP, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 , 0x00 ) - -ZBM(ZBS_W_PFGK, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEY, - 0x10 , - Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), - Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), - Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), - Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), - - ) - -ZBM(ZBS_W_PFGKEN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEYS_ENABLE, 0x01 , 0x00 ) - -ZBM(ZBS_WNV_SECMODE, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(CONF_TCLK_TABLE_START), Z_B1(CONF_TCLK_TABLE_START), - 0x00 , 0x20 , - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x5a, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6c, - 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) - -ZBM(ZBS_W_ZDODCB, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_ZDO_DIRECT_CB, 0x01 , 0x01 ) - -ZBM(ZBS_WNV_INITZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_ITEM_INIT, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, - 0x01, 0x00 , 0x01 , 0x00 ) - - -ZBM(ZBR_WNV_INIT_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_ITEM_INIT ) - - -ZBM(ZBS_WNV_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(ZNP_HAS_CONFIGURED), Z_B1(ZNP_HAS_CONFIGURED), - 0x00 , 0x01 , 0x55 ) - -ZBM(ZBS_STARTUPFROMAPP, Z_SREQ | Z_ZDO, ZDO_STARTUP_FROM_APP, 100, 0 ) -ZBM(ZBR_STARTUPFROMAPP, Z_SRSP | Z_ZDO, ZDO_STARTUP_FROM_APP ) -ZBM(AREQ_STARTUPFROMAPP, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ZB_COORD ) - -ZBM(ZBS_GETDEVICEINFO, Z_SREQ | Z_UTIL, Z_UTIL_GET_DEVICE_INFO ) -ZBM(ZBR_GETDEVICEINFO, Z_SRSP | Z_UTIL, Z_UTIL_GET_DEVICE_INFO, Z_Success ) -# 287 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_9_impl.ino" -ZBM(ZBS_ZDO_NODEDESCREQ, Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, 0x00, 0x00 , 0x00, 0x00 ) -ZBM(ZBR_ZDO_NODEDESCREQ, Z_SRSP | Z_ZDO, ZDO_NODE_DESC_REQ, Z_Success ) - -ZBM(AREQ_ZDO_NODEDESCREQ, Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP) -# 305 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_9_impl.ino" -ZBM(ZBS_ZDO_ACTIVEEPREQ, Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, 0x00, 0x00, 0x00, 0x00) -ZBM(ZBR_ZDO_ACTIVEEPREQ, Z_SRSP | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_Success) -ZBM(ZBR_ZDO_ACTIVEEPRSP_NONE, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 , Z_Success, - 0x00, 0x00 , 0x00 ) -ZBM(ZBR_ZDO_ACTIVEEPRSP_OK, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 , Z_Success, - 0x00, 0x00 , 0x02 , 0x0B, 0x01 ) - - -ZBM(ZBS_AF_REGISTER01, Z_SREQ | Z_AF, AF_REGISTER, 0x01 , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), - 0x05, 0x00 , 0x00 , 0x00 , - 0x00 , 0x00 ) -ZBM(ZBR_AF_REGISTER, Z_SRSP | Z_AF, AF_REGISTER, Z_Success) -ZBM(ZBS_AF_REGISTER0B, Z_SREQ | Z_AF, AF_REGISTER, 0x0B , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), - 0x05, 0x00 , 0x00 , 0x00 , - 0x00 , 0x00 ) - -ZBM(ZBS_PERMITJOINREQ_CLOSE, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x02 , - 0x00, 0x00 , 0x00 , 0x00 ) -ZBM(ZBS_PERMITJOINREQ_OPEN_60, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F , - 0xFC, 0xFF , 60 , 0x00 ) -ZBM(ZBS_PERMITJOINREQ_OPEN_XX, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F , - 0xFC, 0xFF , 0xFF , 0x00 ) -ZBM(ZBR_PERMITJOINREQ, Z_SRSP | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, Z_Success) -ZBM(ZBR_PERMITJOIN_AREQ_CLOSE, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0x00 ) -ZBM(ZBR_PERMITJOIN_AREQ_OPEN_60, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 60 ) -ZBM(ZBR_PERMITJOIN_AREQ_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0xFF ) -ZBM(ZBR_PERMITJOIN_AREQ_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_RSP, 0x00, 0x00 , Z_Success ) - - -ZBM(ZBR_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) -ZBM(ZBR_END_DEVICE_ANNCE_IND, Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND) - -static const Zigbee_Instruction zb_prog[] PROGMEM = { - ZI_LABEL(0) - ZI_NOOP() - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) - ZI_ON_RECV_UNEXPECTED(&Z_Recv_Default) - ZI_WAIT(15000) - ZI_ON_ERROR_GOTO(50) - - ZI_MQTT_STATUS(ZIGBEE_STATUS_BOOT, "Booting") - - ZI_SEND(ZBS_RESET) - ZI_WAIT_RECV(5000, ZBR_RESET) - ZI_LOG(LOG_LEVEL_INFO, "ZIG: checking device configuration") - ZI_SEND(ZBS_ZNPHC) - ZI_WAIT_RECV(2000, ZBR_ZNPHC) - ZI_SEND(ZBS_VERSION) - ZI_WAIT_RECV_FUNC(2000, ZBR_VERSION, &Z_ReceiveCheckVersion) - ZI_SEND(ZBS_PAN) - ZI_WAIT_RECV(1000, ZBR_PAN) - ZI_SEND(ZBS_EXTPAN) - ZI_WAIT_RECV(1000, ZBR_EXTPAN) - ZI_SEND(ZBS_CHANN) - ZI_WAIT_RECV(1000, ZBR_CHANN) - ZI_SEND(ZBS_PFGK) - ZI_WAIT_RECV(1000, ZBR_PFGK) - ZI_SEND(ZBS_PFGKEN) - ZI_WAIT_RECV(1000, ZBR_PFGKEN) - - - - ZI_LABEL(ZIGBEE_LABEL_START) - ZI_MQTT_STATUS(ZIGBEE_STATUS_STARTING, "Configured, starting coordinator") - - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - - -ZI_SEND(ZBS_STARTUPFROMAPP) - ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) - ZI_WAIT_UNTIL(5000, AREQ_STARTUPFROMAPP) - ZI_SEND(ZBS_GETDEVICEINFO) - ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &Z_ReceiveDeviceInfo) - - ZI_SEND(ZBS_ZDO_NODEDESCREQ) - ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ) - ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCREQ) - ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) - ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) - ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_NONE) - ZI_SEND(ZBS_AF_REGISTER01) - ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) - ZI_SEND(ZBS_AF_REGISTER0B) - ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) - - - ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) - ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) - ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_OK) - ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) - - - - - - - ZI_LABEL(ZIGBEE_LABEL_READY) - ZI_MQTT_STATUS(ZIGBEE_STATUS_OK, "Started") - ZI_LOG(LOG_LEVEL_INFO, "ZIG: zigbee device ready, listening...") - ZI_CALL(&Z_State_Ready, 1) - ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) - ZI_WAIT_FOREVER() - ZI_GOTO(ZIGBEE_LABEL_READY) - - ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE) - ZI_MQTT_STATUS(ZIGBEE_STATUS_PERMITJOIN_CLOSE, "Disable Pairing mode") - ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - - - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60) - ZI_MQTT_STATUS(ZIGBEE_STATUS_PERMITJOIN_OPEN_60, "Enable Pairing mode for 60 seconds") - ZI_SEND(ZBS_PERMITJOINREQ_OPEN_60) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - - - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX) - ZI_MQTT_STATUS(ZIGBEE_STATUS_PERMITJOIN_OPEN_XX, "Enable Pairing mode until next boot") - ZI_SEND(ZBS_PERMITJOINREQ_OPEN_XX) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - - - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - ZI_LABEL(50) - ZI_MQTT_STATUS(ZIGBEE_STATUS_RESET_CONF, "Reseting configuration") - - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - ZI_SEND(ZBS_FACTRES) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_RESET) - ZI_WAIT_RECV(5000, ZBR_RESET) - ZI_SEND(ZBS_W_PAN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_EXTPAN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_CHANN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_LOGTYP) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_PFGK) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_PFGKEN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_WNV_SECMODE) - ZI_WAIT_RECV(1000, ZBR_WNV_OK) - ZI_SEND(ZBS_W_ZDODCB) - ZI_WAIT_RECV(1000, ZBR_W_OK) - - ZI_SEND(ZBS_WNV_INITZNPHC) - ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &Z_CheckNVWrite) - ZI_SEND(ZBS_WNV_ZNPHC) - ZI_WAIT_RECV(1000, ZBR_WNV_OK) - - - ZI_GOTO(ZIGBEE_LABEL_START) - - ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION) - ZI_MQTT_STATUS(ZIGBEE_STATUS_UNSUPPORTED_VERSION, "Only ZNP 1.2 is currently supported") - ZI_GOTO(ZIGBEE_LABEL_ABORT) - - ZI_LABEL(ZIGBEE_LABEL_ABORT) - ZI_MQTT_STATUS(ZIGBEE_STATUS_ABORT, "Abort") - ZI_LOG(LOG_LEVEL_ERROR, "ZIG: Abort") - ZI_STOP(ZIGBEE_LABEL_ABORT) -}; - -int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) { - - - - - - - - Z_IEEEAddress long_adr = buf.get64(3); - Z_ShortAddress short_adr = buf.get16(11); - uint8_t device_type = buf.get8(13); - uint8_t device_state = buf.get8(14); - uint8_t device_associated = buf.get8(15); - - char hex[20]; - Uint64toHex(long_adr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - ",\"DeviceType\":%d,\"DeviceState\":%d" - ",\"NumAssocDevices\":%d"), - ZIGBEE_STATUS_CC_INFO, hex, short_adr, device_type, device_state, - device_associated); - - if (device_associated > 0) { - uint idx = 16; - ResponseAppend_P(PSTR(",\"AssocDevicesList\":[")); - for (uint32_t i = 0; i < device_associated; i++) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(idx)); - idx += 2; - } - ResponseAppend_P(PSTR("]")); - } - - ResponseJsonEnd(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); - XdrvRulesProcess(); - - return res; -} - -int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf) { - - - - uint8_t status = buf.get8(2); - if ((0x00 == status) || (0x09 == status)) { - return 0; - } else { - return -2; - } -} - -int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { -# 543 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_9_impl.ino" - uint8_t major_rel = buf.get8(4); - uint8_t minor_rel = buf.get8(5); - uint8_t maint_rel = buf.get8(6); - uint32_t revision = buf.get32(7); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" - "\"Status\":%d,\"MajorRel\":%d,\"MinorRel\":%d" - ",\"MaintRel\":%d,\"Revision\":%d}}"), - ZIGBEE_STATUS_CC_VERSION, major_rel, minor_rel, - maint_rel, revision); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); - XdrvRulesProcess(); - - if ((0x02 == major_rel) && (0x06 == minor_rel)) { - return 0; - } else { - return ZIGBEE_LABEL_UNSUPPORTED_VERSION; - } -} - -bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match) { - if ( (pgm_read_byte(&match[0]) == buf.get8(0)) && - (pgm_read_byte(&match[1]) == buf.get8(1)) ) { - return true; - } else { - return false; - } -} - -int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { - Z_ShortAddress srcAddr = buf.get16(2); - Z_ShortAddress nwkAddr = buf.get16(4); - Z_IEEEAddress ieeeAddr = buf.get64(6); - uint8_t capabilities = buf.get8(14); - - char hex[20]; - Uint64toHex(ieeeAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - ",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"), - ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr, - (capabilities & 0x04) ? "true" : "false", - (capabilities & 0x08) ? "true" : "false", - (capabilities & 0x40) ? "true" : "false" - ); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLRECEIVED)); - XdrvRulesProcess(); - return -1; -} - -int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { - uint16_t groupid = buf.get16(2); - uint16_t clusterid = buf.get16(4); - Z_ShortAddress srcaddr = buf.get16(6); - uint8_t srcendpoint = buf.get8(8); - uint8_t dstendpoint = buf.get8(9); - uint8_t wasbroadcast = buf.get8(10); - uint8_t linkquality = buf.get8(11); - uint8_t securityuse = buf.get8(12); - uint32_t timestamp = buf.get32(13); - uint8_t seqnumber = buf.get8(17); - - ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid); - - zcl_received.publishMQTTReceived(groupid, clusterid, srcaddr, - srcendpoint, dstendpoint, wasbroadcast, - linkquality, securityuse, seqnumber, - timestamp); - - char shortaddr[8]; - snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); - - DynamicJsonBuffer jsonBuffer; - JsonObject& json_root = jsonBuffer.createObject(); - JsonObject& json = json_root.createNestedObject(shortaddr); - if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { - zcl_received.parseRawAttributes(json); - } else if (zcl_received.isClusterSpecificCommand()) { - zcl_received.parseClusterSpecificCommand(json); - } - zcl_received.postProcessAttributes(json); - - String msg(""); - msg.reserve(100); - json_root.printTo(msg); - - Response_P(PSTR("%s"), msg.c_str()); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLRECEIVED)); - XdrvRulesProcess(); - return -1; -} - -int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: Z_Recv_Default")); - if (zigbee.init_phase) { - - return -1; - } else { - if (Z_ReceiveMatchPrefix(buf, ZBR_AF_INCOMING_MESSAGE)) { - return Z_ReceiveAfIncomingMessage(res, buf); - } else if (Z_ReceiveMatchPrefix(buf, ZBR_END_DEVICE_ANNCE_IND)) { - return Z_ReceiveEndDeviceAnnonce(res, buf); - } - return -1; - } -} - -int32_t Z_State_Ready(uint8_t value) { - zigbee.init_phase = false; - return 0; -} - -uint8_t ZigbeeGetInstructionSize(uint8_t instr) { - if (instr >= ZGB_INSTR_12_BYTES) { - return 3; - } else if (instr >= ZGB_INSTR_8_BYTES) { - return 2; - } else { - return 1; - } -} - -void ZigbeeGotoLabel(uint8_t label) { - - uint16_t goto_pc = 0xFFFF; - uint8_t cur_instr = 0; - uint8_t cur_d8 = 0; - uint8_t cur_instr_len = 1; - - for (uint32_t i = 0; i < sizeof(zb_prog)/sizeof(zb_prog[0]); i += cur_instr_len) { - const Zigbee_Instruction *cur_instr_line = &zb_prog[i]; - cur_instr = pgm_read_byte(&cur_instr_line->i.i); - cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); - - - if (ZGB_INSTR_LABEL == cur_instr) { - - if (label == cur_d8) { - - zigbee.pc = i; - zigbee.state_machine = true; - zigbee.state_waiting = false; - return; - } - } - - cur_instr_len = ZigbeeGetInstructionSize(cur_instr); - } - - - AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Goto label not found, label=%d pc=%d"), label, zigbee.pc); - if (ZIGBEE_LABEL_ABORT != label) { - - ZigbeeGotoLabel(ZIGBEE_LABEL_ABORT); - } else { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Label Abort (%d) not present, aborting Zigbee"), ZIGBEE_LABEL_ABORT); - zigbee.state_machine = false; - zigbee.active = false; - } -} - -void ZigbeeStateMachine_Run(void) { - uint8_t cur_instr = 0; - uint8_t cur_d8 = 0; - uint16_t cur_d16 = 0; - const void* cur_ptr1 = nullptr; - const void* cur_ptr2 = nullptr; - uint32_t now = millis(); - - if (zigbee.state_waiting) { - - if ((zigbee.next_timeout) && (now > zigbee.next_timeout)) { - - if (!zigbee.state_no_timeout) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: timeout, goto label %d"), zigbee.on_timeout_goto); - ZigbeeGotoLabel(zigbee.on_timeout_goto); - } else { - zigbee.state_waiting = false; - } - } - } - - while ((zigbee.state_machine) && (!zigbee.state_waiting)) { - - zigbee.recv_filter = nullptr; - zigbee.recv_func = nullptr; - zigbee.recv_until = false; - zigbee.state_no_timeout = false; - - if (zigbee.pc > (sizeof(zb_prog)/sizeof(zb_prog[0]))) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Invalid pc: %d, aborting"), zigbee.pc); - zigbee.pc = -1; - } - if (zigbee.pc < 0) { - zigbee.state_machine = false; - return; - } - - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: Executing instruction pc=%d"), zigbee.pc); - const Zigbee_Instruction *cur_instr_line = &zb_prog[zigbee.pc]; - cur_instr = pgm_read_byte(&cur_instr_line->i.i); - cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); - cur_d16 = pgm_read_word(&cur_instr_line->i.d16); - if (cur_instr >= ZGB_INSTR_8_BYTES) { - cur_instr_line++; - cur_ptr1 = cur_instr_line->p; - } - if (cur_instr >= ZGB_INSTR_12_BYTES) { - cur_instr_line++; - cur_ptr2 = cur_instr_line->p; - } - - zigbee.pc += ZigbeeGetInstructionSize(cur_instr); - - switch (cur_instr) { - case ZGB_INSTR_NOOP: - case ZGB_INSTR_LABEL: - break; - case ZGB_INSTR_GOTO: - ZigbeeGotoLabel(cur_d8); - break; - case ZGB_INSTR_ON_ERROR_GOTO: - zigbee.on_error_goto = cur_d8; - break; - case ZGB_INSTR_ON_TIMEOUT_GOTO: - zigbee.on_timeout_goto = cur_d8; - break; - case ZGB_INSTR_WAIT: - zigbee.next_timeout = now + cur_d16; - zigbee.state_waiting = true; - zigbee.state_no_timeout = true; - break; - case ZGB_INSTR_WAIT_FOREVER: - zigbee.next_timeout = 0; - zigbee.state_waiting = true; - - break; - case ZGB_INSTR_STOP: - zigbee.state_machine = false; - if (cur_d8) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Stopping (%d)"), cur_d8); - } - break; - case ZGB_INSTR_CALL: - if (cur_ptr1) { - uint32_t res; - res = (*((ZB_Func)cur_ptr1))(cur_d8); - if (res > 0) { - ZigbeeGotoLabel(res); - continue; - } else if (res == 0) { - - } else if (res == -1) { - - } else { - ZigbeeGotoLabel(zigbee.on_error_goto); - continue; - } - } - break; - case ZGB_INSTR_LOG: - AddLog_P(cur_d8, (char*) cur_ptr1); - break; - case ZGB_INSTR_MQTT_STATUS: - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{\"Status\":%d,\"Message\":\"%s\"}}"), - cur_d8, (char*) cur_ptr1); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); - XdrvRulesProcess(); - break; - case ZGB_INSTR_SEND: - ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 ); - break; - case ZGB_INSTR_WAIT_UNTIL: - zigbee.recv_until = true; - case ZGB_INSTR_WAIT_RECV: - zigbee.recv_filter = (uint8_t *) cur_ptr1; - zigbee.recv_filter_len = cur_d8; - zigbee.next_timeout = now + cur_d16; - zigbee.state_waiting = true; - break; - case ZGB_ON_RECV_UNEXPECTED: - zigbee.recv_unexpected = (ZB_RecvMsgFunc) cur_ptr1; - break; - case ZGB_INSTR_WAIT_RECV_CALL: - zigbee.recv_filter = (uint8_t *) cur_ptr1; - zigbee.recv_filter_len = cur_d8; - zigbee.recv_func = (ZB_RecvMsgFunc) cur_ptr2; - zigbee.next_timeout = now + cur_d16; - zigbee.state_waiting = true; - break; - } - } -} - -int32_t ZigbeeProcessInput(class SBuffer &buf) { - if (!zigbee.state_machine) { return -1; } - - - bool recv_filter_match = true; - bool recv_prefix_match = false; - if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { - if (zigbee.recv_filter_len >= 2) { - recv_prefix_match = false; - if ( (pgm_read_byte(&zigbee.recv_filter[0]) == buf.get8(0)) && - (pgm_read_byte(&zigbee.recv_filter[1]) == buf.get8(1)) ) { - recv_prefix_match = true; - } - } - - for (uint32_t i = 0; i < zigbee.recv_filter_len; i++) { - if (pgm_read_byte(&zigbee.recv_filter[i]) != buf.get8(i)) { - recv_filter_match = false; - break; - } - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: ZigbeeProcessInput: recv_prefix_match = %d, recv_filter_match = %d"), recv_prefix_match, recv_filter_match); - } - - - int32_t res = -1; - - - - - - if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { - if (!recv_prefix_match) { - res = -1; - } else { - if (recv_filter_match) { - res = 0; - } else { - if (zigbee.recv_until) { - res = -1; - } else { - res = -2; - } - } - } - } else { - res = -1; - } - - if (recv_prefix_match) { - if (zigbee.recv_func) { - res = (*zigbee.recv_func)(res, buf); - } - } - if (-1 == res) { - - if (zigbee.recv_unexpected) { - res = (*zigbee.recv_unexpected)(res, buf); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: ZigbeeProcessInput: res = %d"), res); - - - if (0 == res) { - - zigbee.state_waiting = false; - } else if (res > 0) { - ZigbeeGotoLabel(res); - } else if (-1 == res) { - - - } else { - - ZigbeeGotoLabel(zigbee.on_error_goto); - } -} - -void ZigbeeInput(void) -{ - static uint32_t zigbee_polling_window = 0; - static uint8_t fcs = ZIGBEE_SOF; - static uint32_t zigbee_frame_len = 5; -# 932 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_23_zigbee_9_impl.ino" - while (ZigbeeSerial->available()) { - yield(); - uint8_t zigbee_in_byte = ZigbeeSerial->read(); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZigbeeInput byte=%d len=%d"), zigbee_in_byte, zigbee_buffer->len()); - - if (0 == zigbee_buffer->len()) { - zigbee_frame_len = 5; - fcs = ZIGBEE_SOF; - } - - if ((0 == zigbee_buffer->len()) && (ZIGBEE_SOF != zigbee_in_byte)) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeInput discarding byte %02X"), zigbee_in_byte); - continue; - } - - if (zigbee_buffer->len() < zigbee_frame_len) { - zigbee_buffer->add8(zigbee_in_byte); - zigbee_polling_window = millis(); - fcs ^= zigbee_in_byte; - } - - if (zigbee_buffer->len() >= zigbee_frame_len) { - zigbee_polling_window = 0; - break; - } - - - if (02 == zigbee_buffer->len()) { - - uint8_t len_byte = zigbee_buffer->get8(1); - if (len_byte > 250) len_byte = 250; - - zigbee_frame_len = len_byte + 5; - } - } - - if (zigbee_buffer->len() && (millis() > (zigbee_polling_window + ZIGBEE_POLLING))) { - char hex_char[(zigbee_buffer->len() * 2) + 2]; - ToHex_P((unsigned char*)zigbee_buffer->getBuffer(), zigbee_buffer->len(), hex_char, sizeof(hex_char)); - -#ifndef Z_USE_SOFTWARE_SERIAL - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: Bytes follor_read_metric = %0d"), ZigbeeSerial->getLoopReadMetric()); -#endif - - if (zigbee_buffer->len() != zigbee_frame_len) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received frame of wrong size %s, len %d, expected %d"), hex_char, zigbee_buffer->len(), zigbee_frame_len); - } else if (0x00 != fcs) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received bad FCS frame %s, %d"), hex_char, fcs); - } else { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received correct frame %s"), hex_char); - - SBuffer znp_buffer = zigbee_buffer->subBuffer(2, zigbee_frame_len - 3); - - ToHex_P((unsigned char*)znp_buffer.getBuffer(), znp_buffer.len(), hex_char, sizeof(hex_char)); - Response_P(PSTR("{\"" D_JSON_ZIGBEEZNPRECEIVED "\":\"%s\"}"), hex_char); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZNPRECEIVED)); - XdrvRulesProcess(); - - - ZigbeeProcessInput(znp_buffer); - } - zigbee_buffer->setLen(0); - } -} - - - -void ZigbeeInit(void) -{ - zigbee.active = false; - if ((pin[GPIO_ZIGBEE_RX] < 99) && (pin[GPIO_ZIGBEE_TX] < 99)) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("Zigbee: GPIOs Rx:%d Tx:%d"), pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX]); -#ifdef Z_USE_SOFTWARE_SERIAL - ZigbeeSerial = new SoftwareSerial(); - ZigbeeSerial->begin(115200, pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX], SWSERIAL_8N1, false, 256); - ZigbeeSerial->enableIntTx(false); - zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); -#else - ZigbeeSerial = new TasmotaSerial(pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX], 0, 0, 256); - ZigbeeSerial->begin(115200); - if (ZigbeeSerial->hardwareSerial()) { - ClaimSerial(); - zigbee_buffer = new PreAllocatedSBuffer(sizeof(serial_in_buffer), serial_in_buffer); - } else { - zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); - } -#endif - zigbee.active = true; - zigbee.init_phase = true; - zigbee.state_machine = true; - ZigbeeSerial->flush(); - } -} - - - - - -void CmndZigbeeZNPSend(void) -{ - if (ZigbeeSerial && (XdrvMailbox.data_len > 0)) { - uint8_t code; - - char *codes = RemoveSpace(XdrvMailbox.data); - int32_t size = strlen(XdrvMailbox.data); - - SBuffer buf((size+1)/2); - - while (size > 0) { - char stemp[3]; - strlcpy(stemp, codes, sizeof(stemp)); - code = strtol(stemp, nullptr, 16); - buf.add8(code); - size -= 2; - codes += 2; - } - ZigbeeZNPSend(buf.getBuffer(), buf.len()); - } - ResponseCmndDone(); -} - -void ZigbeeZNPSend(const uint8_t *msg, size_t len) { - if ((len < 2) || (len > 252)) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEEZNPSENT ": bad message len %d"), len); - return; - } - uint8_t data_len = len - 2; - - if (ZigbeeSerial) { - uint8_t fcs = data_len; - - ZigbeeSerial->write(ZIGBEE_SOF); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend SOF %02X"), ZIGBEE_SOF); - ZigbeeSerial->write(data_len); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend LEN %02X"), data_len); - for (uint32_t i = 0; i < len; i++) { - uint8_t b = pgm_read_byte(msg + i); - ZigbeeSerial->write(b); - fcs ^= b; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend byt %02X"), b); - } - ZigbeeSerial->write(fcs); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend FCS %02X"), fcs); - } - - char hex_char[(len * 2) + 2]; - Response_P(PSTR("{\"" D_JSON_ZIGBEEZNPSENT "\":\"%s\"}"), - ToHex_P(msg, len, hex_char, sizeof(hex_char))); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZNPSENT)); - XdrvRulesProcess(); -} - - -void CmndZigbeePermitJoin(void) -{ - uint32_t payload = XdrvMailbox.payload; - if (payload < 0) { payload = 0; } - if ((99 != payload) && (payload > 1)) { payload = 1; } - - if (1 == payload) { - ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60); - } else if (99 == payload){ - ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX); - } else { - ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE); - } - ResponseCmndDone(); -} - - - - - -bool Xdrv23(uint8_t function) -{ - bool result = false; - - if (zigbee.active) { - switch (function) { - case FUNC_LOOP: - if (ZigbeeSerial) { ZigbeeInput(); } - if (zigbee.state_machine) { - - ZigbeeStateMachine_Run(); - } - break; - case FUNC_PRE_INIT: - ZigbeeInit(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kZigbeeCommands, ZigbeeCommand); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_24_buzzer.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_24_buzzer.ino" -#ifdef USE_BUZZER - - - - -#define XDRV_24 24 - -struct BUZZER { - uint32_t tune = 0; - bool active = true; - bool enable = false; - uint8_t inverted = 0; - uint8_t count = 0; - uint8_t set[2]; - uint8_t duration; - uint8_t state = 0; -} Buzzer; - - - - -void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune) -{ - Buzzer.set[0] = off; - Buzzer.set[1] = on; - Buzzer.duration = 1; - Buzzer.tune = 0; - if (tune) { - uint32_t tune1 = tune; - uint32_t tune2 = tune; - for (uint32_t i = 0; i < 32; i++) { - if (!(tune2 & 0x80000000)) { - tune2 <<= 1; - } else { - Buzzer.tune <<= 1; - Buzzer.tune |= tune1 & 1; - tune1 >>= 1; - } - } - Buzzer.count = 1; - } else { - Buzzer.count = count * 2; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BUZ: %d(%d),%d,%d,0x%08X(0x%08X)"), count, Buzzer.count, on, off, tune, Buzzer.tune); - - Buzzer.enable = true; -} - -void BuzzerBeep(uint32_t count) { - BuzzerBeep(count, 1, 1, 0); -} - -void BuzzerEnabledBeep(uint32_t count) -{ - if (Settings.flag3.buzzer_enable) { - BuzzerBeep(count); - } -} - - - -bool BuzzerPinState(void) -{ - if (XdrvMailbox.index == GPIO_BUZZER_INV) { - Buzzer.inverted = 1; - XdrvMailbox.index -= (GPIO_BUZZER_INV - GPIO_BUZZER); - return true; - } - return false; -} - -void BuzzerInit(void) -{ - if (pin[GPIO_BUZZER] < 99) { - pinMode(pin[GPIO_BUZZER], OUTPUT); - digitalWrite(pin[GPIO_BUZZER], Buzzer.inverted); - } else { - Buzzer.active = false; - } -} - -void BuzzerEvery100mSec(void) -{ - if (Buzzer.enable) { - if (Buzzer.count) { - if (Buzzer.duration) { - Buzzer.duration--; - if (!Buzzer.duration) { - if (Buzzer.tune) { - Buzzer.state = Buzzer.tune & 1; - Buzzer.tune >>= 1; - } else { - Buzzer.count--; - Buzzer.state = Buzzer.count & 1; - } - Buzzer.duration = Buzzer.set[Buzzer.state]; - } - } - digitalWrite(pin[GPIO_BUZZER], (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); - } else { - Buzzer.enable = false; - } - } -} - - - - - -const char kBuzzerCommands[] PROGMEM = "|" - "Buzzer" ; - -void (* const BuzzerCommand[])(void) PROGMEM = { - &CmndBuzzer }; - -void CmndBuzzer(void) -{ -# 147 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_24_buzzer.ino" - if (XdrvMailbox.data_len > 0) { - char *p; - uint32_t i = 0; - uint32_t parm[4] = { 0 }; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 4; str = strtok_r(nullptr, ", ", &p)) { - parm[i] = strtoul(str, nullptr, 0); - i++; - } - for (uint32_t i = 0; i < 3; i++) { - if (parm[i] < 1) { parm[i] = 1; } - } - BuzzerBeep(parm[0], parm[1], parm[2], parm[3]); - } else { - BuzzerBeep(1); - } - ResponseCmndDone(); -} - - - - - -bool Xdrv24(uint8_t function) -{ - bool result = false; - - if (Buzzer.active) { - switch (function) { - case FUNC_EVERY_100_MSECOND: - BuzzerEvery100mSec(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kBuzzerCommands, BuzzerCommand); - break; - case FUNC_PRE_INIT: - BuzzerInit(); - break; - case FUNC_PIN_STATE: - result = BuzzerPinState(); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_25_A4988_Stepper.ino" -# 21 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_25_A4988_Stepper.ino" -#ifdef USE_A4988_Stepper -#include -#define XDRV_25 25 - -short A4988_dir_pin = pin[GPIO_MAX]; -short A4988_stp_pin = pin[GPIO_MAX]; -short A4988_ms1_pin = pin[GPIO_MAX]; -short A4988_ms2_pin = pin[GPIO_MAX]; -short A4988_ms3_pin = pin[GPIO_MAX]; -short A4988_ena_pin = pin[GPIO_MAX]; -int A4988_spr = 0; -float A4988_rpm = 0; -short A4988_mis = 0; - -A4988_Stepper* myA4988 = nullptr; - -void A4988Init(void) -{ - A4988_dir_pin = pin[GPIO_A4988_DIR]; - A4988_stp_pin = pin[GPIO_A4988_STP]; - A4988_ena_pin = pin[GPIO_A4988_ENA]; - A4988_ms1_pin = pin[GPIO_A4988_MS1]; - A4988_ms2_pin = pin[GPIO_A4988_MS2]; - A4988_ms3_pin = pin[GPIO_A4988_MS3]; - A4988_spr = 200; - A4988_rpm = 30; - A4988_mis = 1; - - myA4988 = new A4988_Stepper( A4988_spr - , A4988_rpm - , A4988_mis - , A4988_dir_pin - , A4988_stp_pin - , A4988_ena_pin - , A4988_ms1_pin - , A4988_ms2_pin - , A4988_ms3_pin ); -} - -const char kA4988Commands[] PROGMEM = "Motor|" - "Move|Rotate|Turn|MIS|SPR|RPM"; - -void (* const A4988Command[])(void) PROGMEM = { - &CmndDoMove,&CmndDoRotate,&CmndDoTurn,&CmndSetMIS,&CmndSetSPR,&CmndSetRPM}; - -void CmndDoMove(void) { - if (XdrvMailbox.data_len > 0) { - long stepsPlease = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->doMove(stepsPlease); - ResponseCmndDone(); - } -} - -void CmndDoRotate(void) { - if (XdrvMailbox.data_len > 0) { - long degrsPlease = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->doRotate(degrsPlease); - ResponseCmndDone(); - } -} - -void CmndDoTurn(void) { - if (XdrvMailbox.data_len > 0) { - float turnsPlease = strtod(XdrvMailbox.data,nullptr); - myA4988->doTurn(turnsPlease); - ResponseCmndDone(); - } -} - -void CmndSetMIS(void) { - if ((pin[GPIO_A4988_MS1] < 99) && (pin[GPIO_A4988_MS2] < 99) && (pin[GPIO_A4988_MS3] < 99) && (XdrvMailbox.data_len > 0)) { - short newMIS = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->setMIS(newMIS); - ResponseCmndDone(); - } -} - -void CmndSetSPR(void) { - if (XdrvMailbox.data_len > 0) { - int newSPR = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->setSPR(newSPR); - ResponseCmndDone(); - } -} - -void CmndSetRPM(void) { - if (XdrvMailbox.data_len > 0) { - short newRPM = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->setRPM(newRPM); - ResponseCmndDone(); - } -} - - - - -bool Xdrv25(uint8_t function) -{ - bool result = false; - if ((pin[GPIO_A4988_DIR] < 99) && (pin[GPIO_A4988_STP] < 99)) { - switch (function) { - case FUNC_INIT: - A4988Init(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kA4988Commands, A4988Command); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_99_debug.ino" -# 22 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_99_debug.ino" -#ifdef DEBUG_THEO -#ifndef USE_DEBUG_DRIVER -#define USE_DEBUG_DRIVER -#endif -#endif - - - -#ifdef USE_DEBUG_DRIVER - - - - - - -#define XDRV_99 99 - -#ifndef CPU_LOAD_CHECK -#define CPU_LOAD_CHECK 1 -#endif - - - - - -#define D_CMND_CFGDUMP "CfgDump" -#define D_CMND_CFGPEEK "CfgPeek" -#define D_CMND_CFGPOKE "CfgPoke" -#define D_CMND_CFGSHOW "CfgShow" -#define D_CMND_CFGXOR "CfgXor" -#define D_CMND_CPUCHECK "CpuChk" -#define D_CMND_EXCEPTION "Exception" -#define D_CMND_FLASHDUMP "FlashDump" -#define D_CMND_FLASHMODE "FlashMode" -#define D_CMND_FREEMEM "FreeMem" -#define D_CMND_HELP "Help" -#define D_CMND_RTCDUMP "RtcDump" -#define D_CMND_SETSENSOR "SetSensor" - -const char kDebugCommands[] PROGMEM = "|" - D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" -#ifdef USE_DEBUG_SETTING_NAMES - D_CMND_CFGSHOW "|" -#endif -#ifdef USE_WEBSERVER - D_CMND_CFGXOR "|" -#endif - D_CMND_CPUCHECK "|" -#ifdef DEBUG_THEO - D_CMND_EXCEPTION "|" -#endif - D_CMND_FLASHDUMP "|" D_CMND_FLASHMODE "|" D_CMND_FREEMEM"|" D_CMND_HELP "|" D_CMND_RTCDUMP "|" D_CMND_SETSENSOR ; - -void (* const DebugCommand[])(void) PROGMEM = { - &CmndCfgDump, &CmndCfgPeek, &CmndCfgPoke, -#ifdef USE_DEBUG_SETTING_NAMES - &CmndCfgShow, -#endif -#ifdef USE_WEBSERVER - &CmndCfgXor, -#endif - &CmndCpuCheck, -#ifdef DEBUG_THEO - &CmndException, -#endif - &CmndFlashDump, &CmndFlashMode, &CmndFreemem, &CmndHelp, &CmndRtcDump, &CmndSetSensor }; - -uint32_t CPU_loops = 0; -uint32_t CPU_last_millis = 0; -uint32_t CPU_last_loop_time = 0; -uint8_t CPU_load_check = 0; -uint8_t CPU_show_freemem = 0; - - - -#ifdef DEBUG_THEO -void ExceptionTest(uint8_t type) -{ -# 141 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_99_debug.ino" - if (1 == type) { - char svalue[10]; - snprintf_P(svalue, sizeof(svalue), PSTR("%s"), 7); - } -# 155 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_99_debug.ino" - if (2 == type) { - while(1) delay(1000); - } -} - -#endif - - - -void CpuLoadLoop(void) -{ - CPU_last_loop_time = millis(); - if (CPU_load_check && CPU_last_millis) { - CPU_loops ++; - if ((CPU_last_millis + (CPU_load_check *1000)) <= CPU_last_loop_time) { -#if defined(F_CPU) && (F_CPU == 160000000L) - int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *800) ); - CPU_loops = CPU_loops / CPU_load_check; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(160MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); -#else - int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *400) ); - CPU_loops = CPU_loops / CPU_load_check; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(80MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); -#endif - CPU_last_millis = CPU_last_loop_time; - CPU_loops = 0; - } - } -} - - - -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) - - - -extern "C" { -#include - extern cont_t g_cont; -} - -void DebugFreeMem(void) -{ - register uint32_t *sp asm("a1"); - - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_cont.stack), XdrvMailbox.data); -} - -#else - - - - -extern "C" { -#include - extern cont_t* g_pcont; -} - -void DebugFreeMem(void) -{ - register uint32_t *sp asm("a1"); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_pcont->stack), XdrvMailbox.data); -} - -#endif - - - -void DebugRtcDump(char* parms) -{ - #define CFG_COLS 16 - - uint16_t idx; - uint16_t maxrow; - uint16_t row; - uint16_t col; - char *p; -# 242 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_99_debug.ino" - uint8_t buffer[768]; - - system_rtc_mem_read(0, (uint32_t*)&buffer, sizeof(buffer)); - - maxrow = ((sizeof(buffer)+CFG_COLS)/CFG_COLS); - - uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; - uint16_t mrow = strtol(p, &p, 10); - - - - if (0 == mrow) { - mrow = 8; - } - if (srow > maxrow) { - srow = maxrow - mrow; - } - if (mrow < (maxrow - srow)) { - maxrow = srow + mrow; - } - - for (row = srow; row < maxrow; row++) { - idx = row * CFG_COLS; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); - for (col = 0; col < CFG_COLS; col++) { - if (!(col%4)) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (col = 0; col < CFG_COLS; col++) { - - - - 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); - } -} - - - -void DebugCfgDump(char* parms) -{ - #define CFG_COLS 16 - - uint16_t idx; - uint16_t maxrow; - uint16_t row; - uint16_t col; - char *p; - - 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); - - - - if (0 == mrow) { - mrow = 8; - } - if (srow > maxrow) { - srow = maxrow - mrow; - } - if (mrow < (maxrow - srow)) { - maxrow = srow + mrow; - } - - for (row = srow; row < maxrow; row++) { - idx = row * CFG_COLS; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); - for (col = 0; col < CFG_COLS; col++) { - if (!(col%4)) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (col = 0; col < CFG_COLS; col++) { - - - - 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); - delay(1); - } -} - -void DebugCfgPeek(char* parms) -{ - char *p; - - uint16_t address = strtol(parms, &p, 16); - if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; - address = (address >> 2) << 2; - - uint8_t *buffer = (uint8_t *) &Settings; - uint8_t data8 = buffer[address]; - uint16_t data16 = (buffer[address +1] << 8) + buffer[address]; - uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + data16; - - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), address); - for (uint32_t i = 0; i < 4; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[address +i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (uint32_t i = 0; i < 4; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[address +i] > 0x20) && (buffer[address +i] < 0x7F)) ? (char)buffer[address +i] : ' '); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s| 0x%02X (%d), 0x%04X (%d), 0x%0LX (%lu)"), log_data, data8, data8, data16, data16, data32, data32); - AddLog(LOG_LEVEL_INFO); -} - -void DebugCfgPoke(char* parms) -{ - char *p; - - uint16_t address = strtol(parms, &p, 16); - if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; - address = (address >> 2) << 2; - - uint32_t data = strtol(p, &p, 16); - - uint8_t *buffer = (uint8_t *) &Settings; - uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; - - uint8_t *nbuffer = (uint8_t *) &data; - for (uint32_t i = 0; i < 4; i++) { buffer[address +i] = nbuffer[+i]; } - - uint32_t ndata32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; - - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: 0x%0LX (%lu) poked to 0x%0LX (%lu)"), address, data32, data32, ndata32, ndata32); -} - -#ifdef USE_DEBUG_SETTING_NAMES -void DebugCfgShow(uint8_t more) -{ - uint8_t *SetAddr; - SetAddr = (uint8_t *)&Settings; - - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Hostname (%d) [%s]"), (uint8_t *)&Settings.hostname - SetAddr, sizeof(Settings.hostname)-1, Settings.hostname); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: SSids (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_ssid - SetAddr, sizeof(Settings.sta_ssid[0])-1, Settings.sta_ssid[0], Settings.sta_ssid[1]); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Friendlynames (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.friendlyname - SetAddr, sizeof(Settings.friendlyname[0])-1, Settings.friendlyname[0], Settings.friendlyname[1], Settings.friendlyname[2], Settings.friendlyname[3]); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: OTA Url (%d) [%s]"), (uint8_t *)&Settings.ota_url - SetAddr, sizeof(Settings.ota_url)-1, Settings.ota_url); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: StateText (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.state_text - SetAddr, sizeof(Settings.state_text[0])-1, Settings.state_text[0], Settings.state_text[1], Settings.state_text[2], Settings.state_text[3]); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Syslog Host (%d) [%s]"), (uint8_t *)&Settings.syslog_host - SetAddr, sizeof(Settings.syslog_host)-1, Settings.syslog_host); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: NTP Servers (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.ntp_server - SetAddr, sizeof(Settings.ntp_server[0])-1, Settings.ntp_server[0], Settings.ntp_server[1], Settings.ntp_server[2]); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Host (%d) [%s]"), (uint8_t *)&Settings.mqtt_host - SetAddr, sizeof(Settings.mqtt_host)-1, Settings.mqtt_host); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Client (%d) [%s]"), (uint8_t *)&Settings.mqtt_client - SetAddr, sizeof(Settings.mqtt_client)-1, Settings.mqtt_client); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT User (%d) [%s]"), (uint8_t *)&Settings.mqtt_user - SetAddr, sizeof(Settings.mqtt_user)-1, Settings.mqtt_user); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT FullTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_fulltopic - SetAddr, sizeof(Settings.mqtt_fulltopic)-1, Settings.mqtt_fulltopic); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Topic (%d) [%s]"), (uint8_t *)&Settings.mqtt_topic - SetAddr, sizeof(Settings.mqtt_topic)-1, Settings.mqtt_topic); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT GroupTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_grptopic - SetAddr, sizeof(Settings.mqtt_grptopic)-1, Settings.mqtt_grptopic); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT ButtonTopic (%d) [%s]"), (uint8_t *)&Settings.button_topic - SetAddr, sizeof(Settings.button_topic)-1, Settings.button_topic); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT SwitchTopic (%d) [%s]"), (uint8_t *)&Settings.switch_topic - SetAddr, sizeof(Settings.switch_topic)-1, Settings.switch_topic); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Prefixes (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.mqtt_prefix - SetAddr, sizeof(Settings.mqtt_prefix[0])-1, Settings.mqtt_prefix[0], Settings.mqtt_prefix[1], Settings.mqtt_prefix[2]); - if (17 == more) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: AP Passwords (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_pwd - SetAddr, sizeof(Settings.sta_pwd[0])-1, Settings.sta_pwd[0], Settings.sta_pwd[1]); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Password (%d) [%s]"), (uint8_t *)&Settings.mqtt_pwd - SetAddr, sizeof(Settings.mqtt_pwd)-1, Settings.mqtt_pwd); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Web Password (%d) [%s]"), (uint8_t *)&Settings.web_password - SetAddr, sizeof(Settings.web_password)-1, Settings.web_password); - } -} -#endif - -void SetFlashMode(uint8_t mode) -{ - uint8_t *_buffer; - uint32_t address; - - address = 0; - _buffer = new uint8_t[FLASH_SECTOR_SIZE]; - - if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) { - if (_buffer[2] != mode) { - _buffer[2] = mode; - if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) { - ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); - } - } - } - delete[] _buffer; -} - - - - - -void CmndHelp(void) -{ - AddLog_P(LOG_LEVEL_INFO, PSTR("HLP: "), kDebugCommands); - ResponseCmndDone(); -} - -void CmndRtcDump(void) -{ - DebugRtcDump(XdrvMailbox.data); - ResponseCmndDone(); -} - -void CmndCfgDump(void) -{ - DebugCfgDump(XdrvMailbox.data); - ResponseCmndDone(); -} - -void CmndCfgPeek(void) -{ - DebugCfgPeek(XdrvMailbox.data); - ResponseCmndDone(); -} - -void CmndCfgPoke(void) -{ - DebugCfgPoke(XdrvMailbox.data); - ResponseCmndDone(); -} - -#ifdef USE_DEBUG_SETTING_NAMES -void CmndCfgShow(void) -{ - DebugCfgShow(XdrvMailbox.payload); - ResponseCmndDone(); -} -#endif - -#ifdef USE_WEBSERVER -void CmndCfgXor(void) -{ - if (XdrvMailbox.data_len > 0) { - Web.config_xor_on_set = XdrvMailbox.payload; - } - ResponseCmndNumber(Web.config_xor_on_set); -} -#endif - -#ifdef DEBUG_THEO -void CmndException(void) -{ - if (XdrvMailbox.data_len > 0) { ExceptionTest(XdrvMailbox.payload); } - ResponseCmndDone(); -} -#endif - -void CmndCpuCheck(void) -{ - if (XdrvMailbox.data_len > 0) { - CPU_load_check = XdrvMailbox.payload; - CPU_last_millis = CPU_last_loop_time; - } - ResponseCmndNumber(CPU_load_check); -} - -void CmndFreemem(void) -{ - if (XdrvMailbox.data_len > 0) { - CPU_show_freemem = XdrvMailbox.payload; - } - ResponseCmndNumber(CPU_show_freemem); -} - -void CmndSetSensor(void) -{ - if (XdrvMailbox.index < MAX_XSNS_DRIVERS) { - if (XdrvMailbox.payload >= 0) { - bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); - if (1 == XdrvMailbox.payload) { - restart_flag = 2; - } - } - Response_P(PSTR("{\"" D_CMND_SETSENSOR "\":")); - XsnsSensorState(); - ResponseJsonEnd(); - } -} - -void CmndFlashMode(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - SetFlashMode(XdrvMailbox.payload); - } - ResponseCmndNumber(ESP.getFlashChipMode()); -} - -uint32_t DebugSwap32(uint32_t x) { - return ((x << 24) & 0xff000000 ) | - ((x << 8) & 0x00ff0000 ) | - ((x >> 8) & 0x0000ff00 ) | - ((x >> 24) & 0x000000ff ); -} - -void CmndFlashDump(void) -{ - - - - const uint32_t flash_start = 0x40200000; - const uint8_t bytes_per_cols = 0x20; - const uint32_t max = (SPIFFS_END + 5) * SPI_FLASH_SEC_SIZE; - - uint32_t start = flash_start; - uint32_t rows = 8; - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= (max - bytes_per_cols))) { - start += (XdrvMailbox.payload &0x7FFFFFFC); - - char *p; - uint32_t is_payload = strtol(XdrvMailbox.data, &p, 16); - rows = strtol(p, &p, 10); - if (0 == rows) { rows = 8; } - } - uint32_t end = start + (rows * bytes_per_cols); - if ((end - flash_start) > max) { - end = flash_start + max; - } - - for (uint32_t pos = start; pos < end; pos += bytes_per_cols) { - uint32_t* values = (uint32_t*)(pos); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%06X: %08X %08X %08X %08X %08X %08X %08X %08X"), pos - flash_start, - DebugSwap32(values[0]), DebugSwap32(values[1]), DebugSwap32(values[2]), DebugSwap32(values[3]), - DebugSwap32(values[4]), DebugSwap32(values[5]), DebugSwap32(values[6]), DebugSwap32(values[7])); - } - ResponseCmndDone(); -} - - - - - -bool Xdrv99(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_LOOP: - CpuLoadLoop(); - break; - case FUNC_FREE_MEM: - if (CPU_show_freemem) { DebugFreeMem(); } - break; - case FUNC_PRE_INIT: - CPU_last_millis = millis(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kDebugCommands, DebugCommand); - break; - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_interface.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdrv_interface.ino" -#ifdef XFUNC_PTR_IN_ROM -bool (* const xdrv_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xdrv_func_ptr[])(uint8_t) = { -#endif - -#ifdef XDRV_01 - &Xdrv01, -#endif - -#ifdef XDRV_02 - &Xdrv02, -#endif - -#ifdef XDRV_03 - &Xdrv03, -#endif - -#ifdef XDRV_04 - &Xdrv04, -#endif - -#ifdef XDRV_05 - &Xdrv05, -#endif - -#ifdef XDRV_06 - &Xdrv06, -#endif - -#ifdef XDRV_07 - &Xdrv07, -#endif - -#ifdef XDRV_08 - &Xdrv08, -#endif - -#ifdef XDRV_09 - &Xdrv09, -#endif - -#ifdef XDRV_10 - &Xdrv10, -#endif - -#ifdef XDRV_11 - &Xdrv11, -#endif - -#ifdef XDRV_12 - &Xdrv12, -#endif - -#ifdef XDRV_13 - &Xdrv13, -#endif - -#ifdef XDRV_14 - &Xdrv14, -#endif - -#ifdef XDRV_15 - &Xdrv15, -#endif - -#ifdef XDRV_16 - &Xdrv16, -#endif - -#ifdef XDRV_17 - &Xdrv17, -#endif - -#ifdef XDRV_18 - &Xdrv18, -#endif - -#ifdef XDRV_19 - &Xdrv19, -#endif - -#ifdef XDRV_20 - &Xdrv20, -#endif - -#ifdef XDRV_21 - &Xdrv21, -#endif - -#ifdef XDRV_22 - &Xdrv22, -#endif - -#ifdef XDRV_23 - &Xdrv23, -#endif - -#ifdef XDRV_24 - &Xdrv24, -#endif - -#ifdef XDRV_25 - &Xdrv25, -#endif - -#ifdef XDRV_26 - &Xdrv26, -#endif - -#ifdef XDRV_27 - &Xdrv27, -#endif - -#ifdef XDRV_28 - &Xdrv28, -#endif - -#ifdef XDRV_29 - &Xdrv29, -#endif - -#ifdef XDRV_30 - &Xdrv30, -#endif - -#ifdef XDRV_31 - &Xdrv31, -#endif - -#ifdef XDRV_32 - &Xdrv32, -#endif - -#ifdef XDRV_33 - &Xdrv33, -#endif - -#ifdef XDRV_34 - &Xdrv34, -#endif - -#ifdef XDRV_35 - &Xdrv35, -#endif - -#ifdef XDRV_36 - &Xdrv36, -#endif - -#ifdef XDRV_37 - &Xdrv37, -#endif - -#ifdef XDRV_38 - &Xdrv38, -#endif - -#ifdef XDRV_39 - &Xdrv39, -#endif - -#ifdef XDRV_40 - &Xdrv40, -#endif - -#ifdef XDRV_41 - &Xdrv41, -#endif - -#ifdef XDRV_42 - &Xdrv42, -#endif - -#ifdef XDRV_43 - &Xdrv43, -#endif - -#ifdef XDRV_44 - &Xdrv44, -#endif - -#ifdef XDRV_45 - &Xdrv45, -#endif - -#ifdef XDRV_46 - &Xdrv46, -#endif - -#ifdef XDRV_47 - &Xdrv47, -#endif - -#ifdef XDRV_48 - &Xdrv48, -#endif - -#ifdef XDRV_49 - &Xdrv49, -#endif - -#ifdef XDRV_50 - &Xdrv50, -#endif - -#ifdef XDRV_51 - &Xdrv51, -#endif - -#ifdef XDRV_52 - &Xdrv52, -#endif - -#ifdef XDRV_53 - &Xdrv53, -#endif - -#ifdef XDRV_54 - &Xdrv54, -#endif - -#ifdef XDRV_55 - &Xdrv55, -#endif - -#ifdef XDRV_56 - &Xdrv56, -#endif - -#ifdef XDRV_57 - &Xdrv57, -#endif - -#ifdef XDRV_58 - &Xdrv58, -#endif - -#ifdef XDRV_59 - &Xdrv59, -#endif - -#ifdef XDRV_60 - &Xdrv60, -#endif - -#ifdef XDRV_61 - &Xdrv61, -#endif - -#ifdef XDRV_62 - &Xdrv62, -#endif - -#ifdef XDRV_63 - &Xdrv63, -#endif - -#ifdef XDRV_64 - &Xdrv64, -#endif - -#ifdef XDRV_65 - &Xdrv65, -#endif - -#ifdef XDRV_66 - &Xdrv66, -#endif - -#ifdef XDRV_67 - &Xdrv67, -#endif - -#ifdef XDRV_68 - &Xdrv68, -#endif - -#ifdef XDRV_69 - &Xdrv69, -#endif - -#ifdef XDRV_70 - &Xdrv70, -#endif - -#ifdef XDRV_71 - &Xdrv71, -#endif - -#ifdef XDRV_72 - &Xdrv72, -#endif - -#ifdef XDRV_73 - &Xdrv73, -#endif - -#ifdef XDRV_74 - &Xdrv74, -#endif - -#ifdef XDRV_75 - &Xdrv75, -#endif - -#ifdef XDRV_76 - &Xdrv76, -#endif - -#ifdef XDRV_77 - &Xdrv77, -#endif - -#ifdef XDRV_78 - &Xdrv78, -#endif - -#ifdef XDRV_79 - &Xdrv79, -#endif - -#ifdef XDRV_80 - &Xdrv80, -#endif - -#ifdef XDRV_81 - &Xdrv81, -#endif - -#ifdef XDRV_82 - &Xdrv82, -#endif - -#ifdef XDRV_83 - &Xdrv83, -#endif - -#ifdef XDRV_84 - &Xdrv84, -#endif - -#ifdef XDRV_85 - &Xdrv85, -#endif - -#ifdef XDRV_86 - &Xdrv86, -#endif - -#ifdef XDRV_87 - &Xdrv87, -#endif - -#ifdef XDRV_88 - &Xdrv88, -#endif - -#ifdef XDRV_89 - &Xdrv89, -#endif - -#ifdef XDRV_90 - &Xdrv90, -#endif - -#ifdef XDRV_91 - &Xdrv91, -#endif - -#ifdef XDRV_92 - &Xdrv92, -#endif - -#ifdef XDRV_93 - &Xdrv93, -#endif - -#ifdef XDRV_94 - &Xdrv94, -#endif - -#ifdef XDRV_95 - &Xdrv95, -#endif - -#ifdef XDRV_96 - &Xdrv96, -#endif - -#ifdef XDRV_97 - &Xdrv97, -#endif - -#ifdef XDRV_98 - &Xdrv98, -#endif - -#ifdef XDRV_99 - &Xdrv99 -#endif -}; - -const uint8_t xdrv_present = sizeof(xdrv_func_ptr) / sizeof(xdrv_func_ptr[0]); - - - - - -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kXdrvList[] PROGMEM = { -#else -const uint8_t kXdrvList[] = { -#endif - -#ifdef XDRV_01 - XDRV_01, -#endif - -#ifdef XDRV_02 - XDRV_02, -#endif - -#ifdef XDRV_03 - XDRV_03, -#endif - -#ifdef XDRV_04 - XDRV_04, -#endif - -#ifdef XDRV_05 - XDRV_05, -#endif - -#ifdef XDRV_06 - XDRV_06, -#endif - -#ifdef XDRV_07 - XDRV_07, -#endif - -#ifdef XDRV_08 - XDRV_08, -#endif - -#ifdef XDRV_09 - XDRV_09, -#endif - -#ifdef XDRV_10 - XDRV_10, -#endif - -#ifdef XDRV_11 - XDRV_11, -#endif - -#ifdef XDRV_12 - XDRV_12, -#endif - -#ifdef XDRV_13 - XDRV_13, -#endif - -#ifdef XDRV_14 - XDRV_14, -#endif - -#ifdef XDRV_15 - XDRV_15, -#endif - -#ifdef XDRV_16 - XDRV_16, -#endif - -#ifdef XDRV_17 - XDRV_17, -#endif - -#ifdef XDRV_18 - XDRV_18, -#endif - -#ifdef XDRV_19 - XDRV_19, -#endif - -#ifdef XDRV_20 - XDRV_20, -#endif - -#ifdef XDRV_21 - XDRV_21, -#endif - -#ifdef XDRV_22 - XDRV_22, -#endif - -#ifdef XDRV_23 - XDRV_23, -#endif - -#ifdef XDRV_24 - XDRV_24, -#endif - -#ifdef XDRV_25 - XDRV_25, -#endif - -#ifdef XDRV_26 - XDRV_26, -#endif - -#ifdef XDRV_27 - XDRV_27, -#endif - -#ifdef XDRV_28 - XDRV_28, -#endif - -#ifdef XDRV_29 - XDRV_29, -#endif - -#ifdef XDRV_30 - XDRV_30, -#endif - -#ifdef XDRV_31 - XDRV_31, -#endif - -#ifdef XDRV_32 - XDRV_32, -#endif - -#ifdef XDRV_33 - XDRV_33, -#endif - -#ifdef XDRV_34 - XDRV_34, -#endif - -#ifdef XDRV_35 - XDRV_35, -#endif - -#ifdef XDRV_36 - XDRV_36, -#endif - -#ifdef XDRV_37 - XDRV_37, -#endif - -#ifdef XDRV_38 - XDRV_38, -#endif - -#ifdef XDRV_39 - XDRV_39, -#endif - -#ifdef XDRV_40 - XDRV_40, -#endif - -#ifdef XDRV_41 - XDRV_41, -#endif - -#ifdef XDRV_42 - XDRV_42, -#endif - -#ifdef XDRV_43 - XDRV_43, -#endif - -#ifdef XDRV_44 - XDRV_44, -#endif - -#ifdef XDRV_45 - XDRV_45, -#endif - -#ifdef XDRV_46 - XDRV_46, -#endif - -#ifdef XDRV_47 - XDRV_47, -#endif - -#ifdef XDRV_48 - XDRV_48, -#endif - -#ifdef XDRV_49 - XDRV_49, -#endif - -#ifdef XDRV_50 - XDRV_50, -#endif - -#ifdef XDRV_51 - XDRV_51, -#endif - -#ifdef XDRV_52 - XDRV_52, -#endif - -#ifdef XDRV_53 - XDRV_53, -#endif - -#ifdef XDRV_54 - XDRV_54, -#endif - -#ifdef XDRV_55 - XDRV_55, -#endif - -#ifdef XDRV_56 - XDRV_56, -#endif - -#ifdef XDRV_57 - XDRV_57, -#endif - -#ifdef XDRV_58 - XDRV_58, -#endif - -#ifdef XDRV_59 - XDRV_59, -#endif - -#ifdef XDRV_60 - XDRV_60, -#endif - -#ifdef XDRV_61 - XDRV_61, -#endif - -#ifdef XDRV_62 - XDRV_62, -#endif - -#ifdef XDRV_63 - XDRV_63, -#endif - -#ifdef XDRV_64 - XDRV_64, -#endif - -#ifdef XDRV_65 - XDRV_65, -#endif - -#ifdef XDRV_66 - XDRV_66, -#endif - -#ifdef XDRV_67 - XDRV_67, -#endif - -#ifdef XDRV_68 - XDRV_68, -#endif - -#ifdef XDRV_69 - XDRV_69, -#endif - -#ifdef XDRV_70 - XDRV_70, -#endif - -#ifdef XDRV_71 - XDRV_71, -#endif - -#ifdef XDRV_72 - XDRV_72, -#endif - -#ifdef XDRV_73 - XDRV_73, -#endif - -#ifdef XDRV_74 - XDRV_74, -#endif - -#ifdef XDRV_75 - XDRV_75, -#endif - -#ifdef XDRV_76 - XDRV_76, -#endif - -#ifdef XDRV_77 - XDRV_77, -#endif - -#ifdef XDRV_78 - XDRV_78, -#endif - -#ifdef XDRV_79 - XDRV_79, -#endif - -#ifdef XDRV_80 - XDRV_80, -#endif - -#ifdef XDRV_81 - XDRV_81, -#endif - -#ifdef XDRV_82 - XDRV_82, -#endif - -#ifdef XDRV_83 - XDRV_83, -#endif - -#ifdef XDRV_84 - XDRV_84, -#endif - -#ifdef XDRV_85 - XDRV_85, -#endif - -#ifdef XDRV_86 - XDRV_86, -#endif - -#ifdef XDRV_87 - XDRV_87, -#endif - -#ifdef XDRV_88 - XDRV_88, -#endif - -#ifdef XDRV_89 - XDRV_89, -#endif - -#ifdef XDRV_90 - XDRV_90, -#endif - -#ifdef XDRV_91 - XDRV_91, -#endif - -#ifdef XDRV_92 - XDRV_92, -#endif - -#ifdef XDRV_93 - XDRV_93, -#endif - -#ifdef XDRV_94 - XDRV_94, -#endif - -#ifdef XDRV_95 - XDRV_95, -#endif - -#ifdef XDRV_96 - XDRV_96, -#endif - -#ifdef XDRV_97 - XDRV_97, -#endif - -#ifdef XDRV_98 - XDRV_98, -#endif - -#ifdef XDRV_99 - XDRV_99 -#endif -}; - - - -void XsnsDriverState(void) -{ - ResponseAppend_P(PSTR(",\"Drivers\":\"")); - for (uint32_t i = 0; i < sizeof(kXdrvList); i++) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t driverid = pgm_read_byte(kXdrvList + i); -#else - uint32_t driverid = kXdrvList[i]; -#endif - ResponseAppend_P(PSTR("%s%d"), (i) ? "," : "", driverid); - } - ResponseAppend_P(PSTR("\"")); -} - - - -bool XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t sdataBuf) -{ - XdrvMailbox.index = stopicBuf; - XdrvMailbox.data_len = sdataBuf; - XdrvMailbox.topic = topicBuf; - XdrvMailbox.data = dataBuf; - - return XdrvCall(FUNC_MQTT_DATA); -} - -bool XdrvRulesProcess(void) -{ - return XdrvCallDriver(10, FUNC_RULES_PROCESS); -} - -#ifdef USE_DEBUG_DRIVER -void ShowFreeMem(const char *where) -{ - char stemp[30]; - snprintf_P(stemp, sizeof(stemp), where); - XdrvMailbox.data = stemp; - XdrvCall(FUNC_FREE_MEM); -} -#endif - - - - - -bool XdrvCallDriver(uint32_t driver, uint8_t Function) -{ - for (uint32_t x = 0; x < xdrv_present; x++) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t listed = pgm_read_byte(kXdrvList + x); -#else - uint32_t listed = kXdrvList[x]; -#endif - if (driver == listed) { - return xdrv_func_ptr[x](Function); - } - } - return false; -} - - - - - -bool XdrvCall(uint8_t Function) -{ - bool result = false; - - for (uint32_t x = 0; x < xdrv_present; x++) { - result = xdrv_func_ptr[x](Function); - - if (result && ((FUNC_COMMAND == Function) || - (FUNC_COMMAND_DRIVER == Function) || - (FUNC_MQTT_DATA == Function) || - (FUNC_RULES_PROCESS == Function) || - (FUNC_BUTTON_PRESSED == Function) || - (FUNC_SERIAL == Function) || - (FUNC_MODULE_INIT == Function) || - (FUNC_SET_CHANNELS == Function) || - (FUNC_PIN_STATE == Function) || - (FUNC_SET_DEVICE_POWER == Function) - )) { - break; - } - } - - return result; -} -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_01_lcd.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_01_lcd.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_LCD - -#define XDSP_01 1 - -#define LCD_ADDRESS1 0x27 -#define LCD_ADDRESS2 0x3F - -#include -#include - -LiquidCrystal_I2C *lcd; - - - -void LcdInitMode(void) -{ - lcd->init(); - lcd->clear(); -} - -void LcdInit(uint8_t mode) -{ - switch(mode) { - case DISPLAY_INIT_MODE: - LcdInitMode(); -#ifdef USE_DISPLAY_MODES1TO5 - DisplayClearScreenBuffer(); -#endif - break; - case DISPLAY_INIT_PARTIAL: - case DISPLAY_INIT_FULL: - break; - } -} - -void LcdInitDriver(void) -{ - if (!Settings.display_model) { - if (I2cDevice(LCD_ADDRESS1)) { - Settings.display_address[0] = LCD_ADDRESS1; - Settings.display_model = XDSP_01; - } - else if (I2cDevice(LCD_ADDRESS2)) { - Settings.display_address[0] = LCD_ADDRESS2; - Settings.display_model = XDSP_01; - } - } - - if (XDSP_01 == Settings.display_model) { - Settings.display_width = Settings.display_cols[0]; - Settings.display_height = Settings.display_rows; - lcd = new LiquidCrystal_I2C(Settings.display_address[0], Settings.display_cols[0], Settings.display_rows); - -#ifdef USE_DISPLAY_MODES1TO5 - DisplayAllocScreenBuffer(); -#endif - - LcdInitMode(); - } -} - -void LcdDrawStringAt(void) -{ - lcd->setCursor(dsp_x, dsp_y); - lcd->print(dsp_str); -} - -void LcdDisplayOnOff(uint8_t on) -{ - if (on) { - lcd->backlight(); - } else { - lcd->noBacklight(); - } -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void LcdCenter(uint8_t row, char* txt) -{ - char line[Settings.display_cols[0] +2]; - - int len = strlen(txt); - int offset = 0; - if (len >= Settings.display_cols[0]) { - len = Settings.display_cols[0]; - } else { - offset = (Settings.display_cols[0] - len) / 2; - } - memset(line, 0x20, Settings.display_cols[0]); - line[Settings.display_cols[0]] = 0; - for (uint32_t i = 0; i < len; i++) { - line[offset +i] = txt[i]; - } - lcd->setCursor(0, row); - lcd->print(line); -} - -bool LcdPrintLog(void) -{ - bool result = false; - - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - char* txt = DisplayLogBuffer('\337'); - if (txt != nullptr) { - uint8_t last_row = Settings.display_rows -1; - - for (uint32_t i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - lcd->setCursor(0, i); - lcd->print(disp_screen_buffer[i +1]); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - - lcd->setCursor(0, last_row); - lcd->print(disp_screen_buffer[last_row]); - - result = true; - } - } - return result; -} - -void LcdTime(void) -{ - char line[Settings.display_cols[0] +1]; - - snprintf_P(line, sizeof(line), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - LcdCenter(0, line); - snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - LcdCenter(1, line); -} - -void LcdRefresh(void) -{ - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - LcdTime(); - break; - case 2: - case 4: - LcdPrintLog(); - break; - case 3: - case 5: { - if (!LcdPrintLog()) { LcdTime(); } - break; - } - } - } -} - -#endif - - - - - -bool Xdsp01(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - if (FUNC_DISPLAY_INIT_DRIVER == function) { - LcdInitDriver(); - } - else if (XDSP_01 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_INIT: - LcdInit(dsp_init); - break; - case FUNC_DISPLAY_POWER: - LcdDisplayOnOff(disp_power); - break; - case FUNC_DISPLAY_CLEAR: - lcd->clear(); - break; -# 230 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_01_lcd.ino" - case FUNC_DISPLAY_DRAW_STRING: - LcdDrawStringAt(); - break; - case FUNC_DISPLAY_ONOFF: - LcdDisplayOnOff(dsp_on); - break; - - -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - LcdRefresh(); - break; -#endif - } - } - } - return result; -} - -#endif -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_02_ssd1306.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_02_ssd1306.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_SSD1306 - -#define XDSP_02 2 - -#define OLED_RESET 4 - -#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str); - -#define OLED_ADDRESS1 0x3C -#define OLED_ADDRESS2 0x3D - -#define OLED_BUFFER_COLS 40 -#define OLED_BUFFER_ROWS 16 - -#define OLED_FONT_WIDTH 6 -#define OLED_FONT_HEIGTH 8 - -#include -#include -#include - -Adafruit_SSD1306 *oled1306; - -extern uint8_t *buffer; - - - -void SSD1306InitDriver() -{ - if (!Settings.display_model) { - if (I2cDevice(OLED_ADDRESS1)) { - Settings.display_address[0] = OLED_ADDRESS1; - Settings.display_model = XDSP_02; - } - else if (I2cDevice(OLED_ADDRESS2)) { - Settings.display_address[0] = OLED_ADDRESS2; - Settings.display_model = XDSP_02; - } - } - - if (XDSP_02 == Settings.display_model) { - - if ((Settings.display_width != 96) && (Settings.display_width != 128)) { - Settings.display_width = 128; - } - if ((Settings.display_height != 16) && (Settings.display_height != 32) && (Settings.display_height != 64)) { - Settings.display_height = 64; - } - - uint8_t reset_pin = -1; - if (pin[GPIO_OLED_RESET] < 99) { - reset_pin = pin[GPIO_OLED_RESET]; - } - - - if (buffer) { free(buffer); } - buffer = (unsigned char*)calloc((Settings.display_width * Settings.display_height) / 8,1); - if (!buffer) { return; } - - - - oled1306 = new Adafruit_SSD1306(Settings.display_width, Settings.display_height, &Wire, reset_pin); - oled1306->begin(SSD1306_SWITCHCAPVCC, Settings.display_address[0], 0); - renderer = oled1306; - renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font); - - renderer->setTextColor(1,0); - -#ifdef SHOW_SPLASH - renderer->setTextFont(0); - renderer->setTextSize(2); - renderer->setCursor(20,20); - renderer->println(F("SSD1306")); - renderer->Updateframe(); - renderer->DisplayOnff(1); -#endif - - } -} - - -#ifdef USE_DISPLAY_MODES1TO5 - -void Ssd1306PrintLog(void) -{ - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { - uint8_t last_row = Settings.display_rows -1; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setCursor(0,0); - for (byte i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - renderer->println(disp_screen_buffer[i]); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - AddLog(LOG_LEVEL_DEBUG); - - renderer->println(disp_screen_buffer[last_row]); - renderer->Updateframe(); - } - } -} - -void Ssd1306Time(void) -{ - char line[12]; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setTextFont(Settings.display_font); - renderer->setCursor(0, 0); - snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - renderer->println(line); - snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - renderer->println(line); - renderer->Updateframe(); -} - -void Ssd1306Refresh(void) -{ - if (!renderer) return; - - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - Ssd1306Time(); - break; - case 2: - case 3: - case 4: - case 5: - Ssd1306PrintLog(); - break; - } - } -} - -#endif - - - - - -bool Xdsp02(byte function) -{ - bool result = false; - - if (i2c_flg) { - if (FUNC_DISPLAY_INIT_DRIVER == function) { - SSD1306InitDriver(); - } - else if (XDSP_02 == Settings.display_model) { - switch (function) { -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - Ssd1306Refresh(); - break; -#endif - case FUNC_DISPLAY_MODEL: - result = true; - break; - } - } - } - return result; -} - -#endif -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_03_matrix.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_03_matrix.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_MATRIX - -#define XDSP_03 3 - -#define MTX_MAX_SCREEN_BUFFER 80 - -#include -#include -#include - -Adafruit_8x8matrix *matrix[8]; -uint8_t mtx_matrices = 0; -uint8_t mtx_state = 0; -uint8_t mtx_counter = 0; -int16_t mtx_x = 0; -int16_t mtx_y = 0; - - -char *mtx_buffer = nullptr; - -uint8_t mtx_mode = 0; -uint8_t mtx_loop = 0; -uint8_t mtx_done = 0; - - - -void MatrixWrite(void) -{ - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->writeDisplay(); - } -} - -void MatrixClear(void) -{ - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - } - MatrixWrite(); -} - -void MatrixFixed(char* txt) -{ - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - matrix[i]->setCursor(-i *8, 0); - matrix[i]->print(txt); - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); -} - -void MatrixCenter(char* txt) -{ - int offset; - - int len = strlen(txt); - offset = (len < 8) ? offset = ((mtx_matrices *8) - (len *6)) / 2 : 0; - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - matrix[i]->setCursor(-(i *8)+offset, 0); - matrix[i]->print(txt); - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); -} - -void MatrixScrollLeft(char* txt, int loop) -{ - switch (mtx_state) { - case 1: - mtx_state = 2; - - mtx_x = 8 * mtx_matrices; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), txt); - - disp_refresh = Settings.display_refresh; - case 2: - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - matrix[i]->setCursor(mtx_x - i *8, 0); - matrix[i]->print(txt); - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); - - mtx_x--; - int16_t len = strlen(txt); - if (mtx_x < -(len *6)) { mtx_state = loop; } - } - break; - } -} - -void MatrixScrollUp(char* txt, int loop) -{ - int wordcounter = 0; - char tmpbuf[200]; - char *words[100]; - - - - char separators[] = " /"; - - switch (mtx_state) { - case 1: - mtx_state = 2; - - mtx_y = 8; - mtx_counter = 0; - disp_refresh = Settings.display_refresh; - case 2: - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - strlcpy(tmpbuf, txt, sizeof(tmpbuf)); - char *p = strtok(tmpbuf, separators); - while (p != nullptr && wordcounter < 40) { - words[wordcounter++] = p; - p = strtok(nullptr, separators); - } - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - for (uint32_t j = 0; j < wordcounter; j++) { - matrix[i]->setCursor(-i *8, mtx_y + (j *8)); - matrix[i]->println(words[j]); - } - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); - if (((mtx_y %8) == 0) && mtx_counter) { - mtx_counter--; - } else { - mtx_y--; - mtx_counter = STATES * 1; - } - if (mtx_y < -(wordcounter *8)) { mtx_state = loop; } - } - break; - } -} - - - -void MatrixInitMode(void) -{ - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->setRotation(Settings.display_rotate); - matrix[i]->setBrightness(Settings.display_dimmer); - matrix[i]->blinkRate(0); - matrix[i]->setTextWrap(false); - - - matrix[i]->cp437(true); - } - MatrixClear(); -} - -void MatrixInit(uint8_t mode) -{ - switch(mode) { - case DISPLAY_INIT_MODE: - MatrixInitMode(); - break; - case DISPLAY_INIT_PARTIAL: - case DISPLAY_INIT_FULL: - break; - } -} - -void MatrixInitDriver(void) -{ - mtx_buffer = (char*)(malloc(MTX_MAX_SCREEN_BUFFER)); - if (mtx_buffer != nullptr) { - if (!Settings.display_model) { - if (I2cDevice(Settings.display_address[1])) { - Settings.display_model = XDSP_03; - } - } - - if (XDSP_03 == Settings.display_model) { - mtx_state = 1; - for (mtx_matrices = 0; mtx_matrices < 8; mtx_matrices++) { - if (Settings.display_address[mtx_matrices]) { - matrix[mtx_matrices] = new Adafruit_8x8matrix(); - matrix[mtx_matrices]->begin(Settings.display_address[mtx_matrices]); - } else { - break; - } - } - - Settings.display_width = mtx_matrices * 8; - Settings.display_height = 8; - - MatrixInitMode(); - } - } -} - -void MatrixOnOff(void) -{ - if (!disp_power) { MatrixClear(); } -} - -void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ - strlcpy(mtx_buffer, str, MTX_MAX_SCREEN_BUFFER); - mtx_mode = x &1; - mtx_loop = y &1; - if (!mtx_state) { mtx_state = 1; } -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void MatrixPrintLog(uint8_t direction) -{ - char* txt = (!mtx_done) ? DisplayLogBuffer('\370') : mtx_buffer; - if (txt != nullptr) { - if (!mtx_state) { mtx_state = 1; } - - if (!mtx_done) { - - uint8_t space = 0; - uint8_t max_cols = (disp_log_buffer_cols < MTX_MAX_SCREEN_BUFFER) ? disp_log_buffer_cols : MTX_MAX_SCREEN_BUFFER; - mtx_buffer[0] = '\0'; - uint8_t i = 0; - while ((txt[i] != '\0') && (i < max_cols)) { - if (txt[i] == ' ') { - space++; - } else { - space = 0; - } - if (space < 2) { - strncat(mtx_buffer, (const char*)txt +i, (strlen(mtx_buffer) < MTX_MAX_SCREEN_BUFFER -1) ? 1 : 0); - } - i++; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), mtx_buffer); - - mtx_done = 1; - } - - if (direction) { - MatrixScrollUp(mtx_buffer, 0); - } else { - MatrixScrollLeft(mtx_buffer, 0); - } - if (!mtx_state) { mtx_done = 0; } - } else { - char disp_time[9]; - - snprintf_P(disp_time, sizeof(disp_time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - MatrixFixed(disp_time); - } -} - -#endif - -void MatrixRefresh(void) -{ - if (disp_power) { - switch (Settings.display_mode) { - case 0: { - switch (mtx_mode) { - case 0: - MatrixScrollLeft(mtx_buffer, mtx_loop); - break; - case 1: - MatrixScrollUp(mtx_buffer, mtx_loop); - break; - } - break; - } -#ifdef USE_DISPLAY_MODES1TO5 - case 2: { - char disp_date[9]; - snprintf_P(disp_date, sizeof(disp_date), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year -2000); - MatrixFixed(disp_date); - break; - } - case 3: { - char disp_day[10]; - snprintf_P(disp_day, sizeof(disp_day), PSTR("%d %s"), RtcTime.day_of_month, RtcTime.name_of_month); - MatrixCenter(disp_day); - break; - } - case 4: - MatrixPrintLog(0); - break; - case 1: - case 5: - MatrixPrintLog(1); - break; -#endif - } - } -} - - - - - -bool Xdsp03(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - if (FUNC_DISPLAY_INIT_DRIVER == function) { - MatrixInitDriver(); - } - else if (XDSP_03 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_INIT: - MatrixInit(dsp_init); - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: - MatrixRefresh(); - break; - case FUNC_DISPLAY_POWER: - MatrixOnOff(); - break; - case FUNC_DISPLAY_DRAW_STRING: - MatrixDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); - break; - } - } - } - return result; -} - -#endif -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_04_ili9341.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_04_ili9341.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_ILI9341 - -#define XDSP_04 4 - -#define TFT_TOP 16 -#define TFT_BOTTOM 16 -#define TFT_FONT_WIDTH 6 -#define TFT_FONT_HEIGTH 8 - -#include -#include -#include - -Adafruit_ILI9341 *tft; - -uint16_t tft_scroll; - - - -void Ili9341InitMode(void) -{ - tft->setRotation(Settings.display_rotate); - tft->invertDisplay(0); - tft->fillScreen(ILI9341_BLACK); - tft->setTextWrap(false); - tft->cp437(true); - if (!Settings.display_mode) { - tft->setCursor(0, 0); - tft->setTextColor(ILI9341_WHITE, ILI9341_BLACK); - tft->setTextSize(1); - } else { - tft->setScrollMargins(TFT_TOP, TFT_BOTTOM); - tft->setCursor(0, 0); - tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK); - tft->setTextSize(2); - - - tft_scroll = TFT_TOP; - } -} - -void Ili9341Init(uint8_t mode) -{ - switch(mode) { - case DISPLAY_INIT_MODE: - Ili9341InitMode(); -#ifdef USE_DISPLAY_MODES1TO5 - if (Settings.display_rotate) { - DisplayClearScreenBuffer(); - } -#endif - break; - case DISPLAY_INIT_PARTIAL: - case DISPLAY_INIT_FULL: - break; - } -} - -void Ili9341InitDriver(void) -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_04; - } - - if (XDSP_04 == Settings.display_model) { - if (Settings.display_width != ILI9341_TFTWIDTH) { - Settings.display_width = ILI9341_TFTWIDTH; - } - if (Settings.display_height != ILI9341_TFTHEIGHT) { - Settings.display_height = ILI9341_TFTHEIGHT; - } - tft = new Adafruit_ILI9341(pin[GPIO_SPI_CS], pin[GPIO_SPI_DC]); - tft->begin(); - -#ifdef USE_DISPLAY_MODES1TO5 - if (Settings.display_rotate) { - DisplayAllocScreenBuffer(); - } -#endif - - Ili9341InitMode(); - } -} - -void Ili9341Clear(void) -{ - tft->fillScreen(ILI9341_BLACK); - tft->setCursor(0, 0); -} - -void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ - uint16_t active_color = ILI9341_WHITE; - - tft->setTextSize(Settings.display_size); - if (!flag) { - tft->setCursor(x, y); - } else { - tft->setCursor((x-1) * TFT_FONT_WIDTH * Settings.display_size, (y-1) * TFT_FONT_HEIGTH * Settings.display_size); - } - if (color) { active_color = color; } - tft->setTextColor(active_color, ILI9341_BLACK); - tft->println(str); -} - -void Ili9341DisplayOnOff(uint8_t on) -{ - - - if (pin[GPIO_BACKLIGHT] < 99) { - pinMode(pin[GPIO_BACKLIGHT], OUTPUT); - digitalWrite(pin[GPIO_BACKLIGHT], on); - } -} - -void Ili9341OnOff(void) -{ - Ili9341DisplayOnOff(disp_power); -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void Ili9341PrintLog(void) -{ - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (Settings.display_rotate) { - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - } - - char* txt = DisplayLogBuffer('\370'); - if (txt != nullptr) { - uint8_t size = Settings.display_size; - uint16_t theight = size * TFT_FONT_HEIGTH; - - tft->setTextSize(size); - tft->setTextColor(ILI9341_CYAN, ILI9341_BLACK); - if (!Settings.display_rotate) { - tft->setCursor(0, tft_scroll); - tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK); - tft->print(txt); - tft_scroll += theight; - if (tft_scroll >= (tft->height() - TFT_BOTTOM)) { - tft_scroll = TFT_TOP; - } - tft->scrollTo(tft_scroll); - } else { - uint8_t last_row = Settings.display_rows -1; - - tft_scroll = theight; - tft->setCursor(0, tft_scroll); - for (uint32_t i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - - tft->print(disp_screen_buffer[i]); - tft_scroll += theight; - tft->setCursor(0, tft_scroll); - delay(1); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - tft->print(disp_screen_buffer[last_row]); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); - } - } -} - -void Ili9341Refresh(void) -{ - if (Settings.display_mode) { - char tftdt[Settings.display_cols[0] +1]; - char date4[11]; - char space[Settings.display_cols[0] - 17]; - char time[9]; - - tft->setTextSize(2); - tft->setTextColor(ILI9341_YELLOW, ILI9341_RED); - tft->setCursor(0, 0); - - snprintf_P(date4, sizeof(date4), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - memset(space, 0x20, sizeof(space)); - space[sizeof(space) -1] = '\0'; - snprintf_P(time, sizeof(time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - snprintf_P(tftdt, sizeof(tftdt), PSTR("%s%s%s"), date4, space, time); - - tft->print(tftdt); - - switch (Settings.display_mode) { - case 1: - case 2: - case 3: - case 4: - case 5: - Ili9341PrintLog(); - break; - } - } -} - -#endif - - - - - -bool Xdsp04(uint8_t function) -{ - bool result = false; - - if (spi_flg) { - if (FUNC_DISPLAY_INIT_DRIVER == function) { - Ili9341InitDriver(); - } - else if (XDSP_04 == Settings.display_model) { - - if (!dsp_color) { dsp_color = ILI9341_WHITE; } - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_INIT: - Ili9341Init(dsp_init); - break; - case FUNC_DISPLAY_POWER: - Ili9341OnOff(); - break; - case FUNC_DISPLAY_CLEAR: - Ili9341Clear(); - break; - case FUNC_DISPLAY_DRAW_HLINE: - tft->writeFastHLine(dsp_x, dsp_y, dsp_len, dsp_color); - break; - case FUNC_DISPLAY_DRAW_VLINE: - tft->writeFastVLine(dsp_x, dsp_y, dsp_len, dsp_color); - break; - case FUNC_DISPLAY_DRAW_LINE: - tft->writeLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); - break; - case FUNC_DISPLAY_DRAW_CIRCLE: - tft->drawCircle(dsp_x, dsp_y, dsp_rad, dsp_color); - break; - case FUNC_DISPLAY_FILL_CIRCLE: - tft->fillCircle(dsp_x, dsp_y, dsp_rad, dsp_color); - break; - case FUNC_DISPLAY_DRAW_RECTANGLE: - tft->drawRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); - break; - case FUNC_DISPLAY_FILL_RECTANGLE: - tft->fillRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); - break; - - - - case FUNC_DISPLAY_TEXT_SIZE: - tft->setTextSize(Settings.display_size); - break; - case FUNC_DISPLAY_FONT_SIZE: - - break; - case FUNC_DISPLAY_DRAW_STRING: - Ili9341DrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); - break; - case FUNC_DISPLAY_ONOFF: - Ili9341DisplayOnOff(dsp_on); - break; - case FUNC_DISPLAY_ROTATION: - tft->setRotation(Settings.display_rotate); - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - Ili9341Refresh(); - break; -#endif - } - } - } - return result; -} - -#endif -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_05_epaper_29.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_05_epaper_29.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_EPAPER_29 - -#define XDSP_05 5 - -#define EPD_TOP 12 -#define EPD_FONT_HEIGTH 12 - -#define COLORED 1 -#define UNCOLORED 0 - - - -#define USE_TINY_FONT - -#include -#include - - -extern uint8_t *buffer; -uint16_t epd_scroll; - -Epd *epd; - - - -void EpdInitDriver29() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_05; - } - - if (XDSP_05 == Settings.display_model) { - if (Settings.display_width != EPD_WIDTH) { - Settings.display_width = EPD_WIDTH; - } - if (Settings.display_height != EPD_HEIGHT) { - Settings.display_height = EPD_HEIGHT; - } - - - if (buffer) free(buffer); - buffer=(unsigned char*)calloc((EPD_WIDTH * EPD_HEIGHT) / 8,1); - if (!buffer) return; - - - epd = new Epd(EPD_WIDTH,EPD_HEIGHT); - - - if ((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CLK] < 99) && (pin[GPIO_SPI_MOSI] < 99)) { - epd->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SPI_CS], pin[GPIO_SPI_CLK], pin[GPIO_SPI_MOSI]); - } - else if ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_MOSI] < 99)) { - epd->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SSPI_CS], pin[GPIO_SSPI_SCLK], pin[GPIO_SSPI_MOSI]); - } else { - free(buffer); - return; - } - - renderer = epd; - epd->Init(DISPLAY_INIT_FULL); - epd->Init(DISPLAY_INIT_PARTIAL); - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - - renderer->setTextColor(1,0); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(1); - renderer->DrawStringAt(50, 50, "Waveshare E-Paper Display!", COLORED,0); - renderer->Updateframe(); - delay(1000); - renderer->fillScreen(0); -#endif - - } -} - - - - - - - -#ifdef USE_DISPLAY_MODES1TO5 -#define EPD_FONT_HEIGTH 12 -void EpdPrintLog29(void) -{ - - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - - char* txt = DisplayLogBuffer('\040'); - if (txt != nullptr) { - uint8_t size = Settings.display_size; - uint16_t theight = size * EPD_FONT_HEIGTH; - - renderer->setTextFont(size); - uint8_t last_row = Settings.display_rows -1; - - - epd_scroll = 0; - for (uint32_t i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[i], COLORED, 0); - epd_scroll += theight; - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[last_row], COLORED, 0); - - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); - } - } -} - -void EpdRefresh29(void) -{ - if (Settings.display_mode) { - - if (!renderer) return; -# 165 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_05_epaper_29.ino" - switch (Settings.display_mode) { - case 1: - case 2: - case 3: - case 4: - case 5: - EpdPrintLog29(); - renderer->Updateframe(); - break; - } - - - } -} - -#endif - - - - - -bool Xdsp05(uint8_t function) -{ - bool result = false; - if (FUNC_DISPLAY_INIT_DRIVER == function) { - EpdInitDriver29(); - } - else if (XDSP_05 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - EpdRefresh29(); - break; -#endif - } - } - return result; -} - -#endif -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_06_epaper_42.ino" -# 21 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_06_epaper_42.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_EPAPER_42 - -#define XDSP_06 6 - -#define COLORED42 1 -#define UNCOLORED42 0 - - - -#define USE_TINY_FONT - -#include -#include - -extern uint8_t *buffer; - -Epd42 *epd42; - - - - -void EpdInitDriver42() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_06; - } - - if (XDSP_06 == Settings.display_model) { - - if (Settings.display_width != EPD_WIDTH42) { - Settings.display_width = EPD_WIDTH42; - } - if (Settings.display_height != EPD_HEIGHT42) { - Settings.display_height = EPD_HEIGHT42; - } - - - if (buffer) free(buffer); - buffer=(unsigned char*)calloc((EPD_WIDTH42 * EPD_HEIGHT42) / 8,1); - if (!buffer) return; - - - epd42 = new Epd42(EPD_WIDTH42,EPD_HEIGHT42); - - #ifdef USE_SPI - if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)) { - epd42->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); - } else { - free(buffer); - return; - } - #else - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) { - epd42->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); - } else { - free(buffer); - return; - } - #endif - - renderer = epd42; - - epd42->Init(); - - renderer->fillScreen(0); - - - epd42->Init(DISPLAY_INIT_FULL); - - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - - epd42->ClearFrame(); - renderer->Updateframe(); - delay(3000); - renderer->setTextColor(1,0); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->DrawStringAt(50, 140, "Waveshare E-Paper!", COLORED42,0); - renderer->Updateframe(); - delay(350); - renderer->fillScreen(0); -#endif - - } -} - - - - - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void EpdRefresh42() -{ - if (Settings.display_mode) { - - } -} - -#endif - - - - - - -bool Xdsp06(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - EpdInitDriver42(); - } - else if (XDSP_06 == Settings.display_model) { - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - EpdRefresh42(); - break; -#endif - } - } - return result; -} - - -#endif -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_07_sh1106.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_07_sh1106.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_SH1106 - -#define OLED_RESET 4 - -#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str); - -extern uint8_t *buffer; - -#define XDSP_07 7 - -#define OLED_ADDRESS1 0x3C -#define OLED_ADDRESS2 0x3D - -#define OLED_BUFFER_COLS 40 -#define OLED_BUFFER_ROWS 16 - -#define OLED_FONT_WIDTH 6 -#define OLED_FONT_HEIGTH 8 - -#include -#include -#include - -Adafruit_SH1106 *oled1106; - - - - -void SH1106InitDriver() -{ - if (!Settings.display_model) { - if (I2cDevice(OLED_ADDRESS1)) { - Settings.display_address[0] = OLED_ADDRESS1; - Settings.display_model = XDSP_07; - } - else if (I2cDevice(OLED_ADDRESS2)) { - Settings.display_address[0] = OLED_ADDRESS2; - Settings.display_model = XDSP_07; - } - } - - if (XDSP_07 == Settings.display_model) { - - if (Settings.display_width != SH1106_LCDWIDTH) { - Settings.display_width = SH1106_LCDWIDTH; - } - if (Settings.display_height != SH1106_LCDHEIGHT) { - Settings.display_height = SH1106_LCDHEIGHT; - } - - - if (buffer) free(buffer); - buffer=(unsigned char*)calloc((SH1106_LCDWIDTH * SH1106_LCDHEIGHT) / 8,1); - if (!buffer) return; - - - oled1106 = new Adafruit_SH1106(SH1106_LCDWIDTH,SH1106_LCDHEIGHT); - renderer=oled1106; - renderer->Begin(SH1106_SWITCHCAPVCC, Settings.display_address[0],0); - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - renderer->setTextColor(1,0); - -#ifdef SHOW_SPLASH - renderer->setTextFont(0); - renderer->setTextSize(2); - renderer->setCursor(20,20); - renderer->println(F("SH1106")); - renderer->Updateframe(); - renderer->DisplayOnff(1); -#endif - } -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void SH1106PrintLog(void) -{ - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { - uint8_t last_row = Settings.display_rows -1; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setCursor(0,0); - for (byte i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - renderer->println(disp_screen_buffer[i]); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - AddLog(LOG_LEVEL_DEBUG); - - renderer->println(disp_screen_buffer[last_row]); - renderer->Updateframe(); - } - } -} - -void SH1106Time(void) -{ - char line[12]; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setTextFont(Settings.display_font); - renderer->setCursor(0, 0); - snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - renderer->println(line); - snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - renderer->println(line); - renderer->Updateframe(); -} - -void SH1106Refresh(void) -{ - if (!renderer) return; - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - SH1106Time(); - break; - case 2: - case 3: - case 4: - case 5: - SH1106PrintLog(); - break; - } - } -} - -#endif - - - - - -bool Xdsp07(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - if (FUNC_DISPLAY_INIT_DRIVER == function) { - SH1106InitDriver(); - } - else if (XDSP_07 == Settings.display_model) { - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - SH1106Refresh(); - break; -#endif - } - } - } - return result; -} - -#endif -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_08_ILI9488.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_08_ILI9488.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_ILI9488 - -#define XDSP_08 8 - -#define COLORED 1 -#define UNCOLORED 0 - - -#define FT6236_address 0x38 - - - -#define USE_TINY_FONT - - -#include -#include - -TouchLocation ili9488_pLoc; -uint8_t ili9488_ctouch_counter = 0; - - -#define BACKPLANE_PIN 2 - -extern uint8_t *buffer; -extern uint8_t color_type; -ILI9488 *ili9488; - -#ifdef USE_TOUCH_BUTTONS -extern VButton *buttons[]; -#endif - -extern const uint16_t picture[]; -uint8_t FT6236_found; - - - -void ILI9488_InitDriver() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_08; - } - - if (XDSP_08 == Settings.display_model) { - - if (Settings.display_width != ILI9488_TFTWIDTH) { - Settings.display_width = ILI9488_TFTWIDTH; - } - if (Settings.display_height != ILI9488_TFTHEIGHT) { - Settings.display_height = ILI9488_TFTHEIGHT; - } - - - buffer=NULL; - - - fg_color = ILI9488_WHITE; - bg_color = ILI9488_BLACK; - - uint8_t bppin=BACKPLANE_PIN; - if (pin[GPIO_BACKLIGHT]<99) { - bppin=pin[GPIO_BACKLIGHT]; - } - - - if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){ - ili9488 = new ILI9488(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK],bppin); - } else { - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) { - ili9488 = new ILI9488(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK],bppin); - } else { - return; - } - } - - SPI.begin(); - ili9488->begin(); - renderer = ili9488; - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->setTextColor(ILI9488_WHITE,ILI9488_BLACK); - renderer->DrawStringAt(50, 50, "ILI9488 TFT Display!", ILI9488_WHITE,0); - delay(1000); - - -#endif - - color_type = COLOR_COLOR; - - - if (i2c_flg && I2cDevice(FT6236_address)) { - FT6236begin(FT6236_address); - FT6236_found=1; - } else { - FT6236_found=0; - } - - } -} - -#ifdef USE_TOUCH_BUTTONS -void ILI9488_MQTT(uint8_t count,const char *cp) { - ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -} - -void ILI9488_RDW_BUTT(uint32_t count,uint32_t pwr) { - buttons[count]->xdrawButton(pwr); - if (pwr) buttons[count]->vpower|=0x80; - else buttons[count]->vpower&=0x7f; -} - -void FT6236Check() { -uint16_t temp; -uint8_t rbutt=0,vbutt=0; -ili9488_ctouch_counter++; -if (2 == ili9488_ctouch_counter) { - - ili9488_ctouch_counter=0; - if (FT6236readTouchLocation(&ili9488_pLoc,1)) { - - if (renderer) { - uint8_t rot=renderer->getRotation(); - switch (rot) { - case 0: - temp=ili9488_pLoc.y; - ili9488_pLoc.y=renderer->height()-ili9488_pLoc.x; - ili9488_pLoc.x=temp; - break; - case 1: - break; - case 2: - break; - case 3: - temp=ili9488_pLoc.y; - ili9488_pLoc.y=ili9488_pLoc.x; - ili9488_pLoc.x=renderer->width()-temp; - break; - } - - for (uint8_t count=0; countvpower&0x7f; - if (buttons[count]->contains(ili9488_pLoc.x,ili9488_pLoc.y)) { - - buttons[count]->press(true); - if (buttons[count]->justPressed()) { - if (!bflags) { - uint8_t pwr=bitRead(power,rbutt); - if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { - ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); - ILI9488_RDW_BUTT(count,!pwr); - } - } else { - - const char *cp; - if (bflags==1) { - - buttons[count]->vpower^=0x80; - cp="TBT"; - } else { - - buttons[count]->vpower|=0x80; - cp="PBT"; - } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); - ILI9488_MQTT(count,cp); - } - } - } - if (!bflags) { - rbutt++; - } else { - vbutt++; - } - } - } - } - } else { - - for (uint8_t count=0; countvpower&0x7f; - buttons[count]->press(false); - if (buttons[count]->justReleased()) { - uint8_t bflags=buttons[count]->vpower&0x7f; - if (bflags>0) { - if (bflags>1) { - - buttons[count]->vpower&=0x7f; - ILI9488_MQTT(count,"PBT"); - } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); - } - } - if (!bflags) { - - uint8_t pwr=bitRead(power,rbutt); - uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; - if (pwr!=vpwr) { - ILI9488_RDW_BUTT(count,pwr); - } - rbutt++; - } - } - } - ili9488_pLoc.x=0; - ili9488_pLoc.y=0; - } -} -} -#endif - - - - -bool Xdsp08(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - ILI9488_InitDriver(); - } - else if (XDSP_08 == Settings.display_model) { - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: -#ifdef USE_TOUCH_BUTTONS - if (FT6236_found) FT6236Check(); -#endif - break; - } - } - - return result; -} - -#endif -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_09_SSD1351.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_09_SSD1351.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_SSD1351 - -#define XDSP_09 9 - -#define COLORED 1 -#define UNCOLORED 0 - - - - -#define USE_TINY_FONT - -#include - -extern uint8_t *buffer; -extern uint8_t color_type; -SSD1351 *ssd1351; - - - -void SSD1351_InitDriver() { - if (!Settings.display_model) { - Settings.display_model = XDSP_09; - } - - if (XDSP_09 == Settings.display_model) { - - if (Settings.display_width != SSD1351_WIDTH) { - Settings.display_width = SSD1351_WIDTH; - } - if (Settings.display_height != SSD1351_HEIGHT) { - Settings.display_height = SSD1351_HEIGHT; - } - - buffer=0; - - - fg_color = SSD1351_WHITE; - bg_color = SSD1351_BLACK; - - - if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){ - ssd1351 = new SSD1351(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); - } else { - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)){ - ssd1351 = new SSD1351(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); - } else { - return; - } - } - - delay(100); - SPI.begin(); - ssd1351->begin(); - renderer = ssd1351; - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - renderer->dim(Settings.display_dimmer); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->setTextColor(SSD1351_WHITE,SSD1351_BLACK); - renderer->DrawStringAt(10, 60, "SSD1351", SSD1351_RED,0); - delay(1000); - -#endif - color_type = COLOR_COLOR; - } -} - -#ifdef USE_DISPLAY_MODES1TO5 - -void SSD1351PrintLog(void) -{ - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { - uint8_t last_row = Settings.display_rows -1; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setCursor(0,0); - for (byte i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - renderer->println(disp_screen_buffer[i]); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - AddLog(LOG_LEVEL_DEBUG); - - renderer->println(disp_screen_buffer[last_row]); - renderer->Updateframe(); - } - } -} - -void SSD1351Time(void) -{ - char line[12]; - - renderer->clearDisplay(); - renderer->setTextSize(2); - renderer->setCursor(0, 0); - snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - renderer->println(line); - snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - renderer->println(line); - renderer->Updateframe(); -} - -void SSD1351Refresh(void) -{ - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - SSD1351Time(); - break; - case 2: - case 3: - case 4: - case 5: - SSD1351PrintLog(); - break; - } - } -} - -#endif - - - - -bool Xdsp09(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - SSD1351_InitDriver(); - } - else if (XDSP_09 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - SSD1351Refresh(); - break; -#endif - } - } - return result; -} -#endif -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_10_RA8876.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_10_RA8876.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_RA8876 - -#define XDSP_10 10 - -#define COLORED 1 -#define UNCOLORED 0 - - -#define FT5316_address 0x38 - - - -#define USE_TINY_FONT - -#include -#include - -TouchLocation ra8876_pLoc; -uint8_t ra8876_ctouch_counter = 0; - -#ifdef USE_TOUCH_BUTTONS -extern VButton *buttons[]; -#endif - -extern uint8_t *buffer; -extern uint8_t color_type; -RA8876 *ra8876; - -uint8_t FT5316_found; - - -void RA8876_InitDriver() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_10; - } - - if (XDSP_10 == Settings.display_model) { - - if (Settings.display_width != RA8876_TFTWIDTH) { - Settings.display_width = RA8876_TFTWIDTH; - } - if (Settings.display_height != RA8876_TFTHEIGHT) { - Settings.display_height = RA8876_TFTHEIGHT; - } - buffer=0; - - - fg_color = RA8876_WHITE; - bg_color = RA8876_BLACK; - - - if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]==13) && (pin[GPIO_SSPI_MISO]==12) && (pin[GPIO_SSPI_SCLK]==14)) { - ra8876 = new RA8876(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_MISO],pin[GPIO_SSPI_SCLK],pin[GPIO_BACKLIGHT]); - } else { - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]==13) && (pin[GPIO_SPI_MISO]==12) && (pin[GPIO_SPI_CLK]==14)) { - ra8876 = new RA8876(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_MISO],pin[GPIO_SPI_CLK],pin[GPIO_BACKLIGHT]); - } else { - return; - } - } - - ra8876->begin(); - renderer = ra8876; - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - renderer->dim(Settings.display_dimmer); - - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->setTextColor(RA8876_WHITE,RA8876_BLACK); - renderer->DrawStringAt(600, 300, "RA8876", RA8876_RED,0); - delay(1000); - -#endif - color_type = COLOR_COLOR; - - if (i2c_flg && I2cDevice(FT5316_address)) { - FT6236begin(FT5316_address); - FT5316_found=1; - } else { - FT5316_found=0; - } - - } -} - -#ifdef USE_TOUCH_BUTTONS -void RA8876_MQTT(uint8_t count,const char *cp) { - ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -} - -void RA8876_RDW_BUTT(uint32_t count,uint32_t pwr) { - buttons[count]->xdrawButton(pwr); - if (pwr) buttons[count]->vpower|=0x80; - else buttons[count]->vpower&=0x7f; -} - - -void FT5316Check() { -uint16_t temp; -uint8_t rbutt=0,vbutt=0; -ra8876_ctouch_counter++; -if (2 == ra8876_ctouch_counter) { - - ra8876_ctouch_counter=0; - - if (FT6236readTouchLocation(&ra8876_pLoc,1)) { - ra8876_pLoc.x=ra8876_pLoc.x*RA8876_TFTWIDTH/800; - ra8876_pLoc.y=ra8876_pLoc.y*RA8876_TFTHEIGHT/480; - - - if (renderer) { - - - ra8876_pLoc.x=RA8876_TFTWIDTH-ra8876_pLoc.x; - ra8876_pLoc.y=RA8876_TFTHEIGHT-ra8876_pLoc.y; -# 168 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_10_RA8876.ino" - for (uint8_t count=0; countvpower&0x7f; - if (buttons[count]->contains(ra8876_pLoc.x,ra8876_pLoc.y)) { - - buttons[count]->press(true); - if (buttons[count]->justPressed()) { - if (!bflags) { - - uint8_t pwr=bitRead(power,rbutt); - if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { - ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); - RA8876_RDW_BUTT(count,!pwr); - } - } else { - - const char *cp; - if (bflags==1) { - - buttons[count]->vpower^=0x80; - cp="TBT"; - } else { - - buttons[count]->vpower|=0x80; - cp="PBT"; - } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); - RA8876_MQTT(count,cp); - } - } - } - if (!bflags) { - rbutt++; - } else { - vbutt++; - } - } - } - } - } else { - - for (uint8_t count=0; countvpower&0x7f; - buttons[count]->press(false); - if (buttons[count]->justReleased()) { - if (bflags>0) { - if (bflags>1) { - - buttons[count]->vpower&=0x7f; - RA8876_MQTT(count,"PBT"); - } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); - } - } - if (!bflags) { - - uint8_t pwr=bitRead(power,rbutt); - uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; - if (pwr!=vpwr) { - RA8876_RDW_BUTT(count,pwr); - } - rbutt++; - } - } - } - ra8876_pLoc.x=0; - ra8876_pLoc.y=0; - } -} -} -#endif -# 424 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_10_RA8876.ino" -bool Xdsp10(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - RA8876_InitDriver(); - } - else if (XDSP_10 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: -#ifdef USE_TOUCH_BUTTONS - if (FT5316_found) FT5316Check(); -#endif - break; - } - } - return result; -} -#endif -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_interface.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_interface.ino" -#ifdef USE_DISPLAY - -#ifdef XFUNC_PTR_IN_ROM -bool (* const xdsp_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xdsp_func_ptr[])(uint8_t) = { -#endif - -#ifdef XDSP_01 - &Xdsp01, -#endif - -#ifdef XDSP_02 - &Xdsp02, -#endif - -#ifdef XDSP_03 - &Xdsp03, -#endif - -#ifdef XDSP_04 - &Xdsp04, -#endif - -#ifdef XDSP_05 - &Xdsp05, -#endif - -#ifdef XDSP_06 - &Xdsp06, -#endif - -#ifdef XDSP_07 - &Xdsp07, -#endif - -#ifdef XDSP_08 - &Xdsp08, -#endif - -#ifdef XDSP_09 - &Xdsp09, -#endif - -#ifdef XDSP_10 - &Xdsp10, -#endif - -#ifdef XDSP_11 - &Xdsp11, -#endif - -#ifdef XDSP_12 - &Xdsp12, -#endif - -#ifdef XDSP_13 - &Xdsp13, -#endif - -#ifdef XDSP_14 - &Xdsp14, -#endif - -#ifdef XDSP_15 - &Xdsp15, -#endif - -#ifdef XDSP_16 - &Xdsp16 -#endif -}; - -const uint8_t xdsp_present = sizeof(xdsp_func_ptr) / sizeof(xdsp_func_ptr[0]); -# 117 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xdsp_interface.ino" -uint8_t XdspPresent(void) -{ - return xdsp_present; -} - -bool XdspCall(uint8_t Function) -{ - bool result = false; - - for (uint32_t x = 0; x < xdsp_present; x++) { - result = xdsp_func_ptr[x](Function); - - if (result && (FUNC_DISPLAY_MODEL == Function)) { - break; - } - } - - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_01_hlw8012.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_01_hlw8012.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_HLW8012 - - - - - - -#define XNRG_01 1 - - -#define HLW_PREF 10000 -#define HLW_UREF 2200 -#define HLW_IREF 4545 - - -#define HJL_PREF 1362 -#define HJL_UREF 822 -#define HJL_IREF 3300 - -#define HLW_POWER_PROBE_TIME 10 -#define HLW_SAMPLE_COUNT 10 - - - -struct HLW { -#ifdef HLW_DEBUG - unsigned long debug[HLW_SAMPLE_COUNT]; -#endif - unsigned long cf_pulse_length = 0; - unsigned long cf_pulse_last_time = 0; - unsigned long cf_power_pulse_length = 0; - - unsigned long cf1_pulse_length = 0; - unsigned long cf1_pulse_last_time = 0; - unsigned long cf1_summed_pulse_length = 0; - unsigned long cf1_pulse_counter = 0; - unsigned long cf1_voltage_pulse_length = 0; - unsigned long cf1_current_pulse_length = 0; - - unsigned long energy_period_counter = 0; - - unsigned long power_ratio = 0; - unsigned long voltage_ratio = 0; - unsigned long current_ratio = 0; - - uint8_t model_type = 0; - uint8_t cf1_timer = 0; - uint8_t power_retry = 0; - bool select_ui_flag = false; - bool ui_flag = true; - bool load_off = true; -} Hlw; - - -#ifndef USE_WS2812_DMA -void HlwCfInterrupt(void) ICACHE_RAM_ATTR; -void HlwCf1Interrupt(void) ICACHE_RAM_ATTR; -#endif - -void HlwCfInterrupt(void) -{ - unsigned long us = micros(); - - if (Hlw.load_off) { - Hlw.cf_pulse_last_time = us; - Hlw.load_off = false; - } else { - Hlw.cf_pulse_length = us - Hlw.cf_pulse_last_time; - Hlw.cf_pulse_last_time = us; - Hlw.energy_period_counter++; - } - Energy.data_valid[0] = 0; -} - -void HlwCf1Interrupt(void) -{ - unsigned long us = micros(); - - 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)) { - Hlw.cf1_summed_pulse_length += Hlw.cf1_pulse_length; -#ifdef HLW_DEBUG - Hlw.debug[Hlw.cf1_pulse_counter] = Hlw.cf1_pulse_length; -#endif - Hlw.cf1_pulse_counter++; - if (HLW_SAMPLE_COUNT == Hlw.cf1_pulse_counter) { - Hlw.cf1_timer = 8; - } - } - Energy.data_valid[0] = 0; -} - - - -void HlwEvery200ms(void) -{ - unsigned long cf1_pulse_length = 0; - unsigned long hlw_w = 0; - unsigned long hlw_u = 0; - unsigned long hlw_i = 0; - - if (micros() - Hlw.cf_pulse_last_time > (HLW_POWER_PROBE_TIME * 1000000)) { - Hlw.cf_pulse_length = 0; - Hlw.load_off = true; - } - Hlw.cf_power_pulse_length = Hlw.cf_pulse_length; - - if (Hlw.cf_power_pulse_length && Energy.power_on && !Hlw.load_off) { - hlw_w = (Hlw.power_ratio * Settings.energy_power_calibration) / Hlw.cf_power_pulse_length ; - Energy.active_power[0] = (float)hlw_w / 10; - Hlw.power_retry = 1; - } else { - if (Hlw.power_retry) { - Hlw.power_retry--; - } else { - Energy.active_power[0] = 0; - } - } - - if (pin[GPIO_NRG_CF1] < 99) { - Hlw.cf1_timer++; - if (Hlw.cf1_timer >= 8) { - Hlw.cf1_timer = 0; - Hlw.select_ui_flag = (Hlw.select_ui_flag) ? false : true; - if (pin[GPIO_NRG_SEL] < 99) { - digitalWrite(pin[GPIO_NRG_SEL], Hlw.select_ui_flag); - } - - if (Hlw.cf1_pulse_counter) { - cf1_pulse_length = Hlw.cf1_summed_pulse_length / Hlw.cf1_pulse_counter; - } - -#ifdef HLW_DEBUG - - char stemp[100]; - stemp[0] = '\0'; - for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, Hlw.debug[i]); - } - for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) { - for (uint32_t j = i + 1; j < Hlw.cf1_pulse_counter; j++) { - if (Hlw.debug[i] > Hlw.debug[j]) { - std::swap(Hlw.debug[i], Hlw.debug[j]); - } - } - } - unsigned long median = Hlw.debug[(Hlw.cf1_pulse_counter +1) / 2]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: power %d, ui %d, cnt %d, smpl%s, sum %d, mean %d, median %d"), - Hlw.cf_power_pulse_length , Hlw.select_ui_flag, Hlw.cf1_pulse_counter, stemp, Hlw.cf1_summed_pulse_length, cf1_pulse_length, median); -#endif - - if (Hlw.select_ui_flag == Hlw.ui_flag) { - Hlw.cf1_voltage_pulse_length = cf1_pulse_length; - - if (Hlw.cf1_voltage_pulse_length && Energy.power_on) { - hlw_u = (Hlw.voltage_ratio * Settings.energy_voltage_calibration) / Hlw.cf1_voltage_pulse_length ; - Energy.voltage[0] = (float)hlw_u / 10; - } else { - Energy.voltage[0] = 0; - } - - } else { - Hlw.cf1_current_pulse_length = cf1_pulse_length; - - if (Hlw.cf1_current_pulse_length && Energy.active_power[0]) { - hlw_i = (Hlw.current_ratio * Settings.energy_current_calibration) / Hlw.cf1_current_pulse_length; - Energy.current[0] = (float)hlw_i / 1000; - } else { - Energy.current[0] = 0; - } - - } - Hlw.cf1_summed_pulse_length = 0; - Hlw.cf1_pulse_counter = 0; - } - } -} - -void HlwEverySecond(void) -{ - if (Energy.data_valid[0] > ENERGY_WATCHDOG) { - Hlw.cf1_voltage_pulse_length = 0; - Hlw.cf1_current_pulse_length = 0; - Hlw.cf_power_pulse_length = 0; - } else { - unsigned long hlw_len; - - if (Hlw.energy_period_counter) { - hlw_len = 10000 / Hlw.energy_period_counter; - Hlw.energy_period_counter = 0; - if (hlw_len) { - Energy.kWhtoday_delta += ((Hlw.power_ratio * Settings.energy_power_calibration) / hlw_len) / 36; - EnergyUpdateToday(); - } - } - } -} - -void HlwSnsInit(void) -{ - if (!Settings.energy_power_calibration || (4975 == Settings.energy_power_calibration)) { - Settings.energy_power_calibration = HLW_PREF_PULSE; - Settings.energy_voltage_calibration = HLW_UREF_PULSE; - Settings.energy_current_calibration = HLW_IREF_PULSE; - } - - if (Hlw.model_type) { - Hlw.power_ratio = HJL_PREF; - Hlw.voltage_ratio = HJL_UREF; - Hlw.current_ratio = HJL_IREF; - } else { - Hlw.power_ratio = HLW_PREF; - Hlw.voltage_ratio = HLW_UREF; - Hlw.current_ratio = HLW_IREF; - } - - if (pin[GPIO_NRG_SEL] < 99) { - pinMode(pin[GPIO_NRG_SEL], OUTPUT); - digitalWrite(pin[GPIO_NRG_SEL], Hlw.select_ui_flag); - } - if (pin[GPIO_NRG_CF1] < 99) { - pinMode(pin[GPIO_NRG_CF1], INPUT_PULLUP); - attachInterrupt(pin[GPIO_NRG_CF1], HlwCf1Interrupt, FALLING); - } - pinMode(pin[GPIO_HLW_CF], INPUT_PULLUP); - attachInterrupt(pin[GPIO_HLW_CF], HlwCfInterrupt, FALLING); -} - -void HlwDrvInit(void) -{ - Hlw.model_type = 0; - if (pin[GPIO_HJL_CF] < 99) { - pin[GPIO_HLW_CF] = pin[GPIO_HJL_CF]; - pin[GPIO_HJL_CF] = 99; - Hlw.model_type = 1; - } - - if (pin[GPIO_HLW_CF] < 99) { - - Hlw.ui_flag = true; - if (pin[GPIO_NRG_SEL_INV] < 99) { - pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV]; - pin[GPIO_NRG_SEL_INV] = 99; - Hlw.ui_flag = false; - } - - if (pin[GPIO_NRG_CF1] < 99) { - if (99 == pin[GPIO_NRG_SEL]) { - Energy.current_available = false; - } - } else { - Energy.current_available = false; - Energy.voltage_available = false; - } - - energy_flg = XNRG_01; - } -} - -bool HlwCommand(void) -{ - bool serviced = true; - - if ((CMND_POWERCAL == Energy.command_code) || (CMND_VOLTAGECAL == Energy.command_code) || (CMND_CURRENTCAL == Energy.command_code)) { - - } - else if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && Hlw.cf_power_pulse_length ) { - Settings.energy_power_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf_power_pulse_length ) / Hlw.power_ratio; - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && Hlw.cf1_voltage_pulse_length ) { - Settings.energy_voltage_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf1_voltage_pulse_length ) / Hlw.voltage_ratio; - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && Hlw.cf1_current_pulse_length) { - Settings.energy_current_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data)) * Hlw.cf1_current_pulse_length) / Hlw.current_ratio; - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg01(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_200_MSECOND: - HlwEvery200ms(); - break; - case FUNC_ENERGY_EVERY_SECOND: - HlwEverySecond(); - break; - case FUNC_COMMAND: - result = HlwCommand(); - break; - case FUNC_INIT: - HlwSnsInit(); - break; - case FUNC_PRE_INIT: - HlwDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_02_cse7766.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_02_cse7766.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_CSE7766 - - - - - - - -#define XNRG_02 2 - -#define CSE_MAX_INVALID_POWER 128 - -#define CSE_NOT_CALIBRATED 0xAA - -#define CSE_PULSES_NOT_INITIALIZED -1 - -#define CSE_PREF 1000 -#define CSE_UREF 100 - -struct CSE { - long voltage_cycle = 0; - long current_cycle = 0; - long power_cycle = 0; - long power_cycle_first = 0; - long cf_pulses = 0; - long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; - - uint8_t power_invalid = 0; - bool received = false; -} Cse; - -void CseReceived(void) -{ - - - - - - - uint8_t header = serial_in_buffer[0]; - if ((header & 0xFC) == 0xFC) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Abnormal hardware")); - return; - } - - - if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) { - long voltage_coefficient = 191200; - if (CSE_NOT_CALIBRATED != header) { - voltage_coefficient = serial_in_buffer[2] << 16 | serial_in_buffer[3] << 8 | serial_in_buffer[4]; - } - Settings.energy_voltage_calibration = voltage_coefficient / CSE_UREF; - } - if (HLW_IREF_PULSE == Settings.energy_current_calibration) { - long current_coefficient = 16140; - if (CSE_NOT_CALIBRATED != header) { - current_coefficient = serial_in_buffer[8] << 16 | serial_in_buffer[9] << 8 | serial_in_buffer[10]; - } - Settings.energy_current_calibration = current_coefficient; - } - if (HLW_PREF_PULSE == Settings.energy_power_calibration) { - long power_coefficient = 5364000; - if (CSE_NOT_CALIBRATED != header) { - power_coefficient = serial_in_buffer[14] << 16 | serial_in_buffer[15] << 8 | serial_in_buffer[16]; - } - Settings.energy_power_calibration = power_coefficient / CSE_PREF; - } - - uint8_t adjustement = serial_in_buffer[20]; - Cse.voltage_cycle = serial_in_buffer[5] << 16 | serial_in_buffer[6] << 8 | serial_in_buffer[7]; - Cse.current_cycle = serial_in_buffer[11] << 16 | serial_in_buffer[12] << 8 | serial_in_buffer[13]; - Cse.power_cycle = serial_in_buffer[17] << 16 | serial_in_buffer[18] << 8 | serial_in_buffer[19]; - Cse.cf_pulses = serial_in_buffer[21] << 8 | serial_in_buffer[22]; - - if (Energy.power_on) { - if (adjustement & 0x40) { - Energy.voltage[0] = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)Cse.voltage_cycle; - } - if (adjustement & 0x10) { - Cse.power_invalid = 0; - if ((header & 0xF2) == 0xF2) { - Energy.active_power[0] = 0; - } else { - if (0 == Cse.power_cycle_first) { Cse.power_cycle_first = Cse.power_cycle; } - if (Cse.power_cycle_first != Cse.power_cycle) { - Cse.power_cycle_first = -1; - Energy.active_power[0] = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)Cse.power_cycle; - } else { - Energy.active_power[0] = 0; - } - } - } else { - if (Cse.power_invalid < Settings.param[P_CSE7766_INVALID_POWER]) { - Cse.power_invalid++; - } else { - Cse.power_cycle_first = 0; - Energy.active_power[0] = 0; - } - } - if (adjustement & 0x20) { - if (0 == Energy.active_power[0]) { - Energy.current[0] = 0; - } else { - Energy.current[0] = (float)Settings.energy_current_calibration / (float)Cse.current_cycle; - } - } - } else { - Cse.power_cycle_first = 0; - Energy.voltage[0] = 0; - Energy.active_power[0] = 0; - Energy.current[0] = 0; - } -} - -bool CseSerialInput(void) -{ - if (Cse.received) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (24 == serial_in_byte_counter) { - - AddLogSerial(LOG_LEVEL_DEBUG_MORE); - - uint8_t checksum = 0; - for (uint32_t i = 2; i < 23; i++) { checksum += serial_in_buffer[i]; } - if (checksum == serial_in_buffer[23]) { - Energy.data_valid[0] = 0; - CseReceived(); - Cse.received = false; - return true; - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); - do { - memmove(serial_in_buffer, serial_in_buffer +1, 24); - serial_in_byte_counter--; - } while ((serial_in_byte_counter > 2) && (0x5A != serial_in_buffer[1])); - if (0x5A != serial_in_buffer[1]) { - Cse.received = false; - serial_in_byte_counter = 0; - } - } - } - } else { - if ((0x5A == serial_in_byte) && (1 == serial_in_byte_counter)) { - Cse.received = true; - } else { - serial_in_byte_counter = 0; - } - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - } - serial_in_byte = 0; - return false; -} - - - -void CseEverySecond(void) -{ - if (Energy.data_valid[0] > ENERGY_WATCHDOG) { - Cse.voltage_cycle = 0; - Cse.current_cycle = 0; - Cse.power_cycle = 0; - } else { - long cf_frequency = 0; - - if (CSE_PULSES_NOT_INITIALIZED == Cse.cf_pulses_last_time) { - Cse.cf_pulses_last_time = Cse.cf_pulses; - } else { - if (Cse.cf_pulses < Cse.cf_pulses_last_time) { - cf_frequency = (65536 - Cse.cf_pulses_last_time) + Cse.cf_pulses; - } else { - cf_frequency = Cse.cf_pulses - Cse.cf_pulses_last_time; - } - if (cf_frequency && Energy.active_power[0]) { - unsigned long delta = (cf_frequency * Settings.energy_power_calibration) / 36; - - if (delta <= (3680*100/36) * 10 ) { - Cse.cf_pulses_last_time = Cse.cf_pulses; - Energy.kWhtoday_delta += delta; - } - else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Load overflow")); - Cse.cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; - } - EnergyUpdateToday(); - } - } - } -} - -void CseDrvInit(void) -{ - if ((3 == pin[GPIO_CSE7766_RX]) && (1 == pin[GPIO_CSE7766_TX])) { - baudrate = 4800; - serial_config = SERIAL_8E1; - if (0 == Settings.param[P_CSE7766_INVALID_POWER]) { - Settings.param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; - } - Cse.power_invalid = Settings.param[P_CSE7766_INVALID_POWER]; - energy_flg = XNRG_02; - } -} - -bool CseCommand(void) -{ - bool serviced = true; - - if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && Cse.power_cycle) { - Settings.energy_power_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.power_cycle) / CSE_PREF; - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && Cse.voltage_cycle) { - Settings.energy_voltage_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.voltage_cycle) / CSE_UREF; - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && Cse.current_cycle) { - Settings.energy_current_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.current_cycle) / 1000; - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg02(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SERIAL: - result = CseSerialInput(); - break; - case FUNC_ENERGY_EVERY_SECOND: - CseEverySecond(); - break; - case FUNC_COMMAND: - result = CseCommand(); - break; - case FUNC_PRE_INIT: - CseDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_03_pzem004t.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_03_pzem004t.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM004T -# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_03_pzem004t.ino" -#define XNRG_03 3 - -#include - -TasmotaSerial *PzemSerial = nullptr; - -#define PZEM_VOLTAGE (uint8_t)0xB0 -#define RESP_VOLTAGE (uint8_t)0xA0 - -#define PZEM_CURRENT (uint8_t)0xB1 -#define RESP_CURRENT (uint8_t)0xA1 - -#define PZEM_POWER (uint8_t)0xB2 -#define RESP_POWER (uint8_t)0xA2 - -#define PZEM_ENERGY (uint8_t)0xB3 -#define RESP_ENERGY (uint8_t)0xA3 - -#define PZEM_SET_ADDRESS (uint8_t)0xB4 -#define RESP_SET_ADDRESS (uint8_t)0xA4 - -#define PZEM_POWER_ALARM (uint8_t)0xB5 -#define RESP_POWER_ALARM (uint8_t)0xA5 - -#define PZEM_DEFAULT_READ_TIMEOUT 500 - - - -struct PZEM { - float energy = 0; - uint8_t send_retry = 0; - uint8_t read_state = 0; - uint8_t phase = 0; - uint8_t address = 0; -} Pzem; - -struct PZEMCommand { - uint8_t command; - uint8_t addr[4]; - uint8_t data; - uint8_t crc; -}; - -uint8_t PzemCrc(uint8_t *data) -{ - uint16_t crc = 0; - for (uint32_t i = 0; i < sizeof(PZEMCommand) -1; i++) { - crc += *data++; - } - return (uint8_t)(crc & 0xFF); -} - -void PzemSend(uint8_t cmd) -{ - PZEMCommand pzem; - - pzem.command = cmd; - pzem.addr[0] = 0; - pzem.addr[1] = 0; - pzem.addr[2] = 0; - pzem.addr[3] = ((PZEM_SET_ADDRESS == cmd) && Pzem.address) ? Pzem.address : 1 + Pzem.phase; - pzem.data = 0; - - uint8_t *bytes = (uint8_t*)&pzem; - pzem.crc = PzemCrc(bytes); - - PzemSerial->flush(); - PzemSerial->write(bytes, sizeof(pzem)); - - Pzem.address = 0; -} - -bool PzemReceiveReady(void) -{ - return PzemSerial->available() >= (int)sizeof(PZEMCommand); -} - -bool PzemRecieve(uint8_t resp, float *data) -{ -# 120 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_03_pzem004t.ino" - uint8_t buffer[sizeof(PZEMCommand)] = { 0 }; - - unsigned long start = millis(); - uint8_t len = 0; - while ((len < sizeof(PZEMCommand)) && (millis() - start < PZEM_DEFAULT_READ_TIMEOUT)) { - if (PzemSerial->available() > 0) { - uint8_t c = (uint8_t)PzemSerial->read(); - if (!c && !len) { - continue; - } - if ((1 == len) && (buffer[0] == c)) { - len--; - continue; - } - buffer[len++] = c; - } - } - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, len); - - if (len != sizeof(PZEMCommand)) { - - return false; - } - if (buffer[6] != PzemCrc(buffer)) { - - return false; - } - if (buffer[0] != resp) { - - return false; - } - - switch (resp) { - case RESP_VOLTAGE: - *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 10.0); - break; - case RESP_CURRENT: - *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 100.0); - break; - case RESP_POWER: - *data = (float)(buffer[1] << 8) + buffer[2]; - break; - case RESP_ENERGY: - *data = (float)((uint32_t)buffer[1] << 16) + ((uint16_t)buffer[2] << 8) + buffer[3]; - break; - } - return true; -} - - - -const uint8_t pzem_commands[] { PZEM_SET_ADDRESS, PZEM_VOLTAGE, PZEM_CURRENT, PZEM_POWER, PZEM_ENERGY }; -const uint8_t pzem_responses[] { RESP_SET_ADDRESS, RESP_VOLTAGE, RESP_CURRENT, RESP_POWER, RESP_ENERGY }; - -void PzemEvery200ms(void) -{ - bool data_ready = PzemReceiveReady(); - - if (data_ready) { - float value = 0; - if (PzemRecieve(pzem_responses[Pzem.read_state], &value)) { - Energy.data_valid[Pzem.phase] = 0; - switch (Pzem.read_state) { - case 1: - Energy.voltage[Pzem.phase] = value; - break; - case 2: - Energy.current[Pzem.phase] = value; - break; - case 3: - Energy.active_power[Pzem.phase] = value; - break; - case 4: - Pzem.energy += value; - if (Pzem.phase == Energy.phase_count -1) { - EnergyUpdateTotal(Pzem.energy, false); - Pzem.energy = 0; - } - break; - } - Pzem.read_state++; - if (5 == Pzem.read_state) { - Pzem.read_state = 1; - } - } - } - - if (0 == Pzem.send_retry || data_ready) { - Pzem.phase++; - if (Pzem.phase >= Energy.phase_count) { - Pzem.phase = 0; - } - if (Pzem.address) { - Pzem.read_state = 0; - } - Pzem.send_retry = 5; - PzemSend(pzem_commands[Pzem.read_state]); - } - else { - Pzem.send_retry--; - if ((Energy.phase_count > 1) && (0 == Pzem.send_retry) && (uptime < 30)) { - Energy.phase_count--; - } - } -} - -void PzemSnsInit(void) -{ - - PzemSerial = new TasmotaSerial(pin[GPIO_PZEM004_RX], pin[GPIO_PZEM0XX_TX], 1); - if (PzemSerial->begin(9600)) { - if (PzemSerial->hardwareSerial()) { - ClaimSerial(); - } - Energy.phase_count = 3; - Pzem.phase = 2; - Pzem.read_state = 1; - } else { - energy_flg = ENERGY_NONE; - } -} - -void PzemDrvInit(void) -{ - if ((pin[GPIO_PZEM004_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { - energy_flg = XNRG_03; - } -} - -bool PzemCommand(void) -{ - bool serviced = true; - - if (CMND_MODULEADDRESS == Energy.command_code) { - Pzem.address = XdrvMailbox.payload; - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg03(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_200_MSECOND: - if (PzemSerial) { PzemEvery200ms(); } - break; - case FUNC_COMMAND: - result = PzemCommand(); - break; - case FUNC_INIT: - PzemSnsInit(); - break; - case FUNC_PRE_INIT: - PzemDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_04_mcp39f501.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_04_mcp39f501.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_MCP39F501 - - - - - - - -#define XNRG_04 4 - -#define MCP_BAUDRATE 4800 -#define MCP_TIMEOUT 4 -#define MCP_CALIBRATION_TIMEOUT 2 - -#define MCP_CALIBRATE_POWER 0x001 -#define MCP_CALIBRATE_VOLTAGE 0x002 -#define MCP_CALIBRATE_CURRENT 0x004 -#define MCP_CALIBRATE_FREQUENCY 0x008 -#define MCP_SINGLE_WIRE_FLAG 0x100 - -#define MCP_START_FRAME 0xA5 -#define MCP_ACK_FRAME 0x06 -#define MCP_ERROR_NAK 0x15 -#define MCP_ERROR_CRC 0x51 - -#define MCP_SINGLE_WIRE 0xAB - -#define MCP_SET_ADDRESS 0x41 - -#define MCP_READ 0x4E -#define MCP_READ_16 0x52 -#define MCP_READ_32 0x44 - -#define MCP_WRITE 0x4D -#define MCP_WRITE_16 0x57 -#define MCP_WRITE_32 0x45 - -#define MCP_SAVE_REGISTERS 0x53 - -#define MCP_CALIBRATION_BASE 0x0028 -#define MCP_CALIBRATION_LEN 52 - -#define MCP_FREQUENCY_REF_BASE 0x0094 -#define MCP_FREQUENCY_GAIN_BASE 0x00AE -#define MCP_FREQUENCY_LEN 4 - -#define MCP_BUFFER_SIZE 60 - -#include -TasmotaSerial *McpSerial = nullptr; - -typedef struct mcp_cal_registers_type { - uint16_t gain_current_rms; - uint16_t gain_voltage_rms; - uint16_t gain_active_power; - uint16_t gain_reactive_power; - sint32_t offset_current_rms; - sint32_t offset_active_power; - sint32_t offset_reactive_power; - sint16_t dc_offset_current; - sint16_t phase_compensation; - uint16_t apparent_power_divisor; - - uint32_t system_configuration; - uint16_t dio_configuration; - uint32_t range; - - uint32_t calibration_current; - uint16_t calibration_voltage; - uint32_t calibration_active_power; - uint32_t calibration_reactive_power; - uint16_t accumulation_interval; -} mcp_cal_registers_type; - -char *mcp_buffer = nullptr; -unsigned long mcp_window = 0; -unsigned long mcp_kWhcounter = 0; -uint32_t mcp_system_configuration = 0x03000000; -uint32_t mcp_active_power; - - -uint32_t mcp_current_rms; -uint16_t mcp_voltage_rms; -uint16_t mcp_line_frequency; - -uint8_t mcp_address = 0; -uint8_t mcp_calibration_active = 0; -uint8_t mcp_init = 0; -uint8_t mcp_timeout = 0; -uint8_t mcp_calibrate = 0; -uint8_t mcp_byte_counter = 0; - - - - - - -uint8_t McpChecksum(uint8_t *data) -{ - uint8_t checksum = 0; - uint8_t offset = 0; - uint8_t len = data[1] -1; - - for (uint32_t i = offset; i < len; i++) { checksum += data[i]; } - return checksum; -} - -unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size) -{ - unsigned long result = 0; - unsigned long pow = 1; - - for (uint32_t i = 0; i < size; i++) { - result = result + (uint8_t)data[offset + i] * pow; - pow = pow * 256; - } - return result; -} - -void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size) -{ - for (uint32_t i = 0; i < size; i++) { - data[offset + i] = ((value >> (i * 8)) & 0xFF); - } -} - -void McpSend(uint8_t *data) -{ - if (mcp_timeout) { return; } - mcp_timeout = MCP_TIMEOUT; - - data[0] = MCP_START_FRAME; - data[data[1] -1] = McpChecksum(data); - - - - for (uint32_t i = 0; i < data[1]; i++) { - McpSerial->write(data[i]); - } -} - - - -void McpGetAddress(void) -{ - uint8_t data[] = { MCP_START_FRAME, 7, MCP_SET_ADDRESS, 0x00, 0x26, MCP_READ_16, 0x00 }; - - McpSend(data); -} - -void McpAddressReceive(void) -{ - - mcp_address = mcp_buffer[3]; -} - - - -void McpGetCalibration(void) -{ - if (mcp_calibration_active) { return; } - mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; - - uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, (MCP_CALIBRATION_BASE >> 8) & 0xFF, MCP_CALIBRATION_BASE & 0xFF, MCP_READ, MCP_CALIBRATION_LEN, 0x00 }; - - McpSend(data); -} - -void McpParseCalibration(void) -{ - bool action = false; - mcp_cal_registers_type cal_registers; - - - cal_registers.gain_current_rms = McpExtractInt(mcp_buffer, 2, 2); - cal_registers.gain_voltage_rms = McpExtractInt(mcp_buffer, 4, 2); - cal_registers.gain_active_power = McpExtractInt(mcp_buffer, 6, 2); - cal_registers.gain_reactive_power = McpExtractInt(mcp_buffer, 8, 2); - cal_registers.offset_current_rms = McpExtractInt(mcp_buffer, 10, 4); - cal_registers.offset_active_power = McpExtractInt(mcp_buffer, 14, 4); - cal_registers.offset_reactive_power = McpExtractInt(mcp_buffer, 18, 4); - cal_registers.dc_offset_current = McpExtractInt(mcp_buffer, 22, 2); - cal_registers.phase_compensation = McpExtractInt(mcp_buffer, 24, 2); - cal_registers.apparent_power_divisor = McpExtractInt(mcp_buffer, 26, 2); - - cal_registers.system_configuration = McpExtractInt(mcp_buffer, 28, 4); - cal_registers.dio_configuration = McpExtractInt(mcp_buffer, 32, 2); - cal_registers.range = McpExtractInt(mcp_buffer, 34, 4); - - cal_registers.calibration_current = McpExtractInt(mcp_buffer, 38, 4); - cal_registers.calibration_voltage = McpExtractInt(mcp_buffer, 42, 2); - cal_registers.calibration_active_power = McpExtractInt(mcp_buffer, 44, 4); - cal_registers.calibration_reactive_power = McpExtractInt(mcp_buffer, 48, 4); - cal_registers.accumulation_interval = McpExtractInt(mcp_buffer, 52, 2); - - if (mcp_calibrate & MCP_CALIBRATE_POWER) { - cal_registers.calibration_active_power = Settings.energy_power_calibration; - if (McpCalibrationCalc(&cal_registers, 16)) { action = true; } - } - if (mcp_calibrate & MCP_CALIBRATE_VOLTAGE) { - cal_registers.calibration_voltage = Settings.energy_voltage_calibration; - if (McpCalibrationCalc(&cal_registers, 0)) { action = true; } - } - if (mcp_calibrate & MCP_CALIBRATE_CURRENT) { - cal_registers.calibration_current = Settings.energy_current_calibration; - if (McpCalibrationCalc(&cal_registers, 8)) { action = true; } - } - mcp_timeout = 0; - if (action) { McpSetCalibration(&cal_registers); } - - mcp_calibrate = 0; - - Settings.energy_power_calibration = cal_registers.calibration_active_power; - Settings.energy_voltage_calibration = cal_registers.calibration_voltage; - Settings.energy_current_calibration = cal_registers.calibration_current; - - mcp_system_configuration = cal_registers.system_configuration; - - if (mcp_system_configuration & MCP_SINGLE_WIRE_FLAG) { - mcp_system_configuration &= ~MCP_SINGLE_WIRE_FLAG; - McpSetSystemConfiguration(2); - } -} - -bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t range_shift) -{ - uint32_t measured; - uint32_t expected; - uint16_t *gain; - uint32_t new_gain; - - if (range_shift == 0) { - measured = mcp_voltage_rms; - expected = cal_registers->calibration_voltage; - gain = &(cal_registers->gain_voltage_rms); - } else if (range_shift == 8) { - measured = mcp_current_rms; - expected = cal_registers->calibration_current; - gain = &(cal_registers->gain_current_rms); - } else if (range_shift == 16) { - measured = mcp_active_power; - expected = cal_registers->calibration_active_power; - gain = &(cal_registers->gain_active_power); - } else { - return false; - } - - if (measured == 0) { - return false; - } - - uint32_t range = (cal_registers->range >> range_shift) & 0xFF; - -calc: - new_gain = (*gain) * expected / measured; - - if (new_gain < 25000) { - range++; - if (measured > 6) { - measured = measured / 2; - goto calc; - } - } - - if (new_gain > 55000) { - range--; - measured = measured * 2; - goto calc; - } - - *gain = new_gain; - uint32_t old_range = (cal_registers->range >> range_shift) & 0xFF; - cal_registers->range = cal_registers->range ^ (old_range << range_shift); - cal_registers->range = cal_registers->range | (range << range_shift); - - return true; -} - - - - - - -void McpSetCalibration(struct mcp_cal_registers_type *cal_registers) -{ - uint8_t data[7 + MCP_CALIBRATION_LEN + 2 + 1]; - - data[1] = sizeof(data); - data[2] = MCP_SET_ADDRESS; - data[3] = (MCP_CALIBRATION_BASE >> 8) & 0xFF; - data[4] = (MCP_CALIBRATION_BASE >> 0) & 0xFF; - - data[5] = MCP_WRITE; - data[6] = MCP_CALIBRATION_LEN; - - McpSetInt(cal_registers->gain_current_rms, data, 0+7, 2); - McpSetInt(cal_registers->gain_voltage_rms, data, 2+7, 2); - McpSetInt(cal_registers->gain_active_power, data, 4+7, 2); - McpSetInt(cal_registers->gain_reactive_power, data, 6+7, 2); - McpSetInt(cal_registers->offset_current_rms, data, 8+7, 4); - McpSetInt(cal_registers->offset_active_power, data, 12+7, 4); - McpSetInt(cal_registers->offset_reactive_power, data, 16+7, 4); - McpSetInt(cal_registers->dc_offset_current, data, 20+7, 2); - McpSetInt(cal_registers->phase_compensation, data, 22+7, 2); - McpSetInt(cal_registers->apparent_power_divisor, data, 24+7, 2); - - McpSetInt(cal_registers->system_configuration, data, 26+7, 4); - McpSetInt(cal_registers->dio_configuration, data, 30+7, 2); - McpSetInt(cal_registers->range, data, 32+7, 4); - - McpSetInt(cal_registers->calibration_current, data, 36+7, 4); - McpSetInt(cal_registers->calibration_voltage, data, 40+7, 2); - McpSetInt(cal_registers->calibration_active_power, data, 42+7, 4); - McpSetInt(cal_registers->calibration_reactive_power, data, 46+7, 4); - McpSetInt(cal_registers->accumulation_interval, data, 50+7, 2); - - data[MCP_CALIBRATION_LEN+7] = MCP_SAVE_REGISTERS; - data[MCP_CALIBRATION_LEN+8] = mcp_address; - - McpSend(data); -} - - - -void McpSetSystemConfiguration(uint16 interval) -{ - - uint8_t data[17]; - - data[ 1] = sizeof(data); - data[ 2] = MCP_SET_ADDRESS; - data[ 3] = 0x00; - data[ 4] = 0x42; - data[ 5] = MCP_WRITE_32; - data[ 6] = (mcp_system_configuration >> 24) & 0xFF; - data[ 7] = (mcp_system_configuration >> 16) & 0xFF; - data[ 8] = (mcp_system_configuration >> 8) & 0xFF; - data[ 9] = (mcp_system_configuration >> 0) & 0xFF; - data[10] = MCP_SET_ADDRESS; - data[11] = 0x00; - data[12] = 0x5A; - data[13] = MCP_WRITE_16; - data[14] = (interval >> 8) & 0xFF; - data[15] = (interval >> 0) & 0xFF; - - McpSend(data); -} - - - -void McpGetFrequency(void) -{ - if (mcp_calibration_active) { return; } - mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; - - uint8_t data[] = { MCP_START_FRAME, 11, MCP_SET_ADDRESS, (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF, MCP_FREQUENCY_REF_BASE & 0xFF, MCP_READ_16, - MCP_SET_ADDRESS, (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF, MCP_FREQUENCY_GAIN_BASE & 0xFF, MCP_READ_16, 0x00 }; - - McpSend(data); -} - -void McpParseFrequency(void) -{ - - uint16_t line_frequency_ref = mcp_buffer[2] * 256 + mcp_buffer[3]; - uint16_t gain_line_frequency = mcp_buffer[4] * 256 + mcp_buffer[5]; - - if (mcp_calibrate & MCP_CALIBRATE_FREQUENCY) { - line_frequency_ref = Settings.energy_frequency_calibration; - - if ((0xFFFF == mcp_line_frequency) || (0 == gain_line_frequency)) { - mcp_line_frequency = 50000; - gain_line_frequency = 0x8000; - } - gain_line_frequency = gain_line_frequency * line_frequency_ref / mcp_line_frequency; - - mcp_timeout = 0; - McpSetFrequency(line_frequency_ref, gain_line_frequency); - } - - Settings.energy_frequency_calibration = line_frequency_ref; - - mcp_calibrate = 0; -} - -void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency) -{ - - uint8_t data[17]; - - data[ 1] = sizeof(data); - data[ 2] = MCP_SET_ADDRESS; - data[ 3] = (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF; - data[ 4] = (MCP_FREQUENCY_REF_BASE >> 0) & 0xFF; - - data[ 5] = MCP_WRITE_16; - data[ 6] = (line_frequency_ref >> 8) & 0xFF; - data[ 7] = (line_frequency_ref >> 0) & 0xFF; - - data[ 8] = MCP_SET_ADDRESS; - data[ 9] = (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF; - data[10] = (MCP_FREQUENCY_GAIN_BASE >> 0) & 0xFF; - - data[11] = MCP_WRITE_16; - data[12] = (gain_line_frequency >> 8) & 0xFF; - data[13] = (gain_line_frequency >> 0) & 0xFF; - - data[14] = MCP_SAVE_REGISTERS; - data[15] = mcp_address; - - McpSend(data); -} - - - -void McpGetData(void) -{ - uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, 0x00, 0x04, MCP_READ, 22, 0x00 }; - - McpSend(data); -} - -void McpParseData(void) -{ - - - - - - mcp_current_rms = McpExtractInt(mcp_buffer, 2, 4); - mcp_voltage_rms = McpExtractInt(mcp_buffer, 6, 2); - mcp_active_power = McpExtractInt(mcp_buffer, 8, 4); - - - mcp_line_frequency = McpExtractInt(mcp_buffer, 22, 2); - - if (Energy.power_on) { - Energy.data_valid[0] = 0; - Energy.frequency[0] = (float)mcp_line_frequency / 1000; - Energy.voltage[0] = (float)mcp_voltage_rms / 10; - Energy.active_power[0] = (float)mcp_active_power / 100; - if (0 == Energy.active_power[0]) { - Energy.current[0] = 0; - } else { - Energy.current[0] = (float)mcp_current_rms / 10000; - } - } else { - Energy.data_valid[0] = ENERGY_WATCHDOG; - } -} - - - -void McpSerialInput(void) -{ - while ((McpSerial->available()) && (mcp_byte_counter < MCP_BUFFER_SIZE)) { - yield(); - mcp_buffer[mcp_byte_counter++] = McpSerial->read(); - mcp_window = millis(); - } - - - if ((mcp_byte_counter) && (millis() - mcp_window > (24000 / MCP_BAUDRATE) +1)) { - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)mcp_buffer, mcp_byte_counter); - - if (MCP_BUFFER_SIZE == mcp_byte_counter) { - - } - else if (1 == mcp_byte_counter) { - if (MCP_ERROR_CRC == mcp_buffer[0]) { - - mcp_timeout = 0; - } - else if (MCP_ERROR_NAK == mcp_buffer[0]) { - - mcp_timeout = 0; - } - } - else if (MCP_ACK_FRAME == mcp_buffer[0]) { - if (mcp_byte_counter == mcp_buffer[1]) { - - if (McpChecksum((uint8_t *)mcp_buffer) != mcp_buffer[mcp_byte_counter -1]) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); - } else { - if (5 == mcp_buffer[1]) { McpAddressReceive(); } - if (25 == mcp_buffer[1]) { McpParseData(); } - if (MCP_CALIBRATION_LEN + 3 == mcp_buffer[1]) { McpParseCalibration(); } - if (MCP_FREQUENCY_LEN + 3 == mcp_buffer[1]) { McpParseFrequency(); } - } - - } - mcp_timeout = 0; - } - else if (MCP_SINGLE_WIRE == mcp_buffer[0]) { - mcp_timeout = 0; - } - - mcp_byte_counter = 0; - McpSerial->flush(); - } -} - - - -void McpEverySecond(void) -{ - if (Energy.data_valid[0] > ENERGY_WATCHDOG) { - mcp_voltage_rms = 0; - mcp_current_rms = 0; - mcp_active_power = 0; - mcp_line_frequency = 0; - } - - if (mcp_active_power) { - Energy.kWhtoday_delta += ((mcp_active_power * 10) / 36); - EnergyUpdateToday(); - } - - if (mcp_timeout) { - mcp_timeout--; - } - else if (mcp_calibration_active) { - mcp_calibration_active--; - } - else if (mcp_init) { - if (2 == mcp_init) { - McpGetCalibration(); - } - else if (1 == mcp_init) { - McpGetFrequency(); - } - mcp_init--; - } - else if (!mcp_address) { - McpGetAddress(); - } - else { - McpGetData(); - } -} - -void McpSnsInit(void) -{ - - McpSerial = new TasmotaSerial(pin[GPIO_MCP39F5_RX], pin[GPIO_MCP39F5_TX], 1); - if (McpSerial->begin(MCP_BAUDRATE)) { - if (McpSerial->hardwareSerial()) { - ClaimSerial(); - mcp_buffer = serial_in_buffer; - } else { - mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); - } - if (pin[GPIO_MCP39F5_RST] < 99) { - digitalWrite(pin[GPIO_MCP39F5_RST], 1); - } - } else { - energy_flg = ENERGY_NONE; - } -} - -void McpDrvInit(void) -{ - if ((pin[GPIO_MCP39F5_RX] < 99) && (pin[GPIO_MCP39F5_TX] < 99)) { - if (pin[GPIO_MCP39F5_RST] < 99) { - pinMode(pin[GPIO_MCP39F5_RST], OUTPUT); - digitalWrite(pin[GPIO_MCP39F5_RST], 0); - } - mcp_calibrate = 0; - mcp_timeout = 2; - mcp_init = 2; - energy_flg = XNRG_04; - } -} - -bool McpCommand(void) -{ - bool serviced = true; - unsigned long value = 0; - - if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && mcp_active_power) { - value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 100); - if ((value > 100) && (value < 200000)) { - Settings.energy_power_calibration = value; - mcp_calibrate |= MCP_CALIBRATE_POWER; - McpGetCalibration(); - } - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && mcp_voltage_rms) { - value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10); - if ((value > 1000) && (value < 2600)) { - Settings.energy_voltage_calibration = value; - mcp_calibrate |= MCP_CALIBRATE_VOLTAGE; - McpGetCalibration(); - } - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && mcp_current_rms) { - value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10); - if ((value > 100) && (value < 80000)) { - Settings.energy_current_calibration = value; - mcp_calibrate |= MCP_CALIBRATE_CURRENT; - McpGetCalibration(); - } - } - } - else if (CMND_FREQUENCYSET == Energy.command_code) { - if (XdrvMailbox.data_len && mcp_line_frequency) { - value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 1000); - if ((value > 45000) && (value < 65000)) { - Settings.energy_frequency_calibration = value; - mcp_calibrate |= MCP_CALIBRATE_FREQUENCY; - McpGetFrequency(); - } - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg04(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_LOOP: - if (McpSerial) { McpSerialInput(); } - break; - case FUNC_ENERGY_EVERY_SECOND: - if (McpSerial) { McpEverySecond(); } - break; - case FUNC_COMMAND: - result = McpCommand(); - break; - case FUNC_INIT: - McpSnsInit(); - break; - case FUNC_PRE_INIT: - McpDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_05_pzem_ac.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_05_pzem_ac.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM_AC -# 32 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_05_pzem_ac.ino" -#define XNRG_05 5 - -#define PZEM_AC_DEVICE_ADDRESS 0x01 - -#include -TasmotaModbus *PzemAcModbus; - -struct PZEMAC { - float energy = 0; - uint8_t send_retry = 0; - uint8_t phase = 0; - uint8_t address = 0; - uint8_t address_step = ADDR_IDLE; -} PzemAc; - -void PzemAcEverySecond(void) -{ - bool data_ready = PzemAcModbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[30]; - - uint8_t registers = 10; - if (ADDR_RECEIVE == PzemAc.address_step) { - registers = 2; - PzemAc.address_step--; - } - uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, registers); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, PzemAcModbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAC: PzemAc %d error %d"), PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, error); - } else { - Energy.data_valid[PzemAc.phase] = 0; - if (10 == registers) { - - - - - Energy.voltage[PzemAc.phase] = (float)((buffer[3] << 8) + buffer[4]) / 10.0; - Energy.current[PzemAc.phase] = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; - Energy.active_power[PzemAc.phase] = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; - Energy.frequency[PzemAc.phase] = (float)((buffer[17] << 8) + buffer[18]) / 10.0; - Energy.power_factor[PzemAc.phase] = (float)((buffer[19] << 8) + buffer[20]) / 100.0; - - PzemAc.energy += (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); - if (PzemAc.phase == Energy.phase_count -1) { - EnergyUpdateTotal(PzemAc.energy, false); - PzemAc.energy = 0; - } - } - } - } - - if (0 == PzemAc.send_retry || data_ready) { - PzemAc.phase++; - if (PzemAc.phase >= Energy.phase_count) { - PzemAc.phase = 0; - } - PzemAc.send_retry = ENERGY_WATCHDOG; - if (ADDR_SEND == PzemAc.address_step) { - PzemAcModbus->Send(0xF8, 0x06, 0x0002, (uint16_t)PzemAc.address); - PzemAc.address_step--; - } else { - PzemAcModbus->Send(PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, 0x04, 0, 10); - } - } - else { - PzemAc.send_retry--; - if ((Energy.phase_count > 1) && (0 == PzemAc.send_retry) && (uptime < 30)) { - Energy.phase_count--; - } - } -} - -void PzemAcSnsInit(void) -{ - PzemAcModbus = new TasmotaModbus(pin[GPIO_PZEM016_RX], pin[GPIO_PZEM0XX_TX]); - uint8_t result = PzemAcModbus->Begin(9600); - if (result) { - if (2 == result) { ClaimSerial(); } - Energy.phase_count = 3; - PzemAc.phase = 2; - } else { - energy_flg = ENERGY_NONE; - } -} - -void PzemAcDrvInit(void) -{ - if ((pin[GPIO_PZEM016_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { - energy_flg = XNRG_05; - } -} - -bool PzemAcCommand(void) -{ - bool serviced = true; - - if (CMND_MODULEADDRESS == Energy.command_code) { - PzemAc.address = XdrvMailbox.payload; - PzemAc.address_step = ADDR_SEND; - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg05(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_ENERGY_EVERY_SECOND: - if (uptime > 4) { PzemAcEverySecond(); } - break; - case FUNC_COMMAND: - result = PzemAcCommand(); - break; - case FUNC_INIT: - PzemAcSnsInit(); - break; - case FUNC_PRE_INIT: - PzemAcDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_06_pzem_dc.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_06_pzem_dc.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM_DC -# 32 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_06_pzem_dc.ino" -#define XNRG_06 6 - -#define PZEM_DC_DEVICE_ADDRESS 0x01 - -#include -TasmotaModbus *PzemDcModbus; - -struct PZEMDC { - float energy = 0; - uint8_t send_retry = 0; - uint8_t channel = 0; - uint8_t address = 0; - uint8_t address_step = ADDR_IDLE; -} PzemDc; - -void PzemDcEverySecond(void) -{ - bool data_ready = PzemDcModbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[26]; - - uint8_t registers = 8; - if (ADDR_RECEIVE == PzemDc.address_step) { - registers = 2; - PzemDc.address_step--; - } - uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, registers); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, PzemDcModbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PDC: PzemDc %d error %d"), PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, error); - } else { - Energy.data_valid[PzemDc.channel] = 0; - if (8 == registers) { - - - - - Energy.voltage[PzemDc.channel] = (float)((buffer[3] << 8) + buffer[4]) / 100.0; - Energy.current[PzemDc.channel] = (float)((buffer[5] << 8) + buffer[6]) / 100.0; - Energy.active_power[PzemDc.channel] = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; - - PzemDc.energy += (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); - if (PzemDc.channel == Energy.phase_count -1) { - EnergyUpdateTotal(PzemDc.energy, false); - PzemDc.energy = 0; - } - } - } - } - - if (0 == PzemDc.send_retry || data_ready) { - PzemDc.channel++; - if (PzemDc.channel >= Energy.phase_count) { - PzemDc.channel = 0; - } - PzemDc.send_retry = ENERGY_WATCHDOG; - if (ADDR_SEND == PzemDc.address_step) { - PzemDcModbus->Send(0xF8, 0x06, 0x0002, (uint16_t)PzemDc.address); - PzemDc.address_step--; - } else { - PzemDcModbus->Send(PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, 0x04, 0, 8); - } - } - else { - PzemDc.send_retry--; - if ((Energy.phase_count > 1) && (0 == PzemDc.send_retry) && (uptime < 30)) { - Energy.phase_count--; - } - } -} - -void PzemDcSnsInit(void) -{ - PzemDcModbus = new TasmotaModbus(pin[GPIO_PZEM017_RX], pin[GPIO_PZEM0XX_TX]); - uint8_t result = PzemDcModbus->Begin(9600, 2); - if (result) { - if (2 == result) { ClaimSerial(); } - Energy.type_dc = true; - Energy.phase_count = 3; - PzemDc.channel = 2; - } else { - energy_flg = ENERGY_NONE; - } -} - -void PzemDcDrvInit(void) -{ - if ((pin[GPIO_PZEM017_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { - energy_flg = XNRG_06; - } -} - -bool PzemDcCommand(void) -{ - bool serviced = true; - - if (CMND_MODULEADDRESS == Energy.command_code) { - PzemDc.address = XdrvMailbox.payload; - PzemDc.address_step = ADDR_SEND; - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg06(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_ENERGY_EVERY_SECOND: - if (uptime > 4) { PzemDcEverySecond(); } - break; - case FUNC_COMMAND: - result = PzemDcCommand(); - break; - case FUNC_INIT: - PzemDcSnsInit(); - break; - case FUNC_PRE_INIT: - PzemDcDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_07_ade7953.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_07_ade7953.ino" -#ifdef USE_I2C -#ifdef USE_ENERGY_SENSOR -#ifdef USE_ADE7953 -# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_07_ade7953.ino" -#define XNRG_07 7 - -#define ADE7953_PREF 1540 -#define ADE7953_UREF 26000 -#define ADE7953_IREF 10000 - -#define ADE7953_ADDR 0x38 - -const uint8_t Ade7953Registers[] { - 0x1B, - 0x13, - 0x11, - 0x15, - 0x1A, - 0x12, - 0x10, - 0x14, - 0x1C -}; - -struct Ade7953 { - uint32_t voltage_rms = 0; - uint32_t current_rms[2] = { 0, 0 }; - uint32_t active_power[2] = { 0, 0 }; - uint8_t init_step = 0; -} Ade7953; - -int Ade7953RegSize(uint16_t reg) -{ - int size = 0; - switch ((reg >> 8) & 0x0F) { - case 0x03: - size++; - case 0x02: - size++; - case 0x01: - size++; - case 0x00: - case 0x07: - case 0x08: - size++; - } - return size; -} - -void Ade7953Write(uint16_t reg, uint32_t val) -{ - int size = Ade7953RegSize(reg); - if (size) { - Wire.beginTransmission(ADE7953_ADDR); - Wire.write((reg >> 8) & 0xFF); - Wire.write(reg & 0xFF); - while (size--) { - Wire.write((val >> (8 * size)) & 0xFF); - } - Wire.endTransmission(); - delayMicroseconds(5); - } -} - -int32_t Ade7953Read(uint16_t reg) -{ - uint32_t response = 0; - - int size = Ade7953RegSize(reg); - if (size) { - Wire.beginTransmission(ADE7953_ADDR); - Wire.write((reg >> 8) & 0xFF); - Wire.write(reg & 0xFF); - Wire.endTransmission(0); - Wire.requestFrom(ADE7953_ADDR, size); - if (size <= Wire.available()) { - for (uint32_t i = 0; i < size; i++) { - response = response << 8 | Wire.read(); - } - } - } - return response; -} - -void Ade7953Init(void) -{ - Ade7953Write(0x102, 0x0004); - Ade7953Write(0x0FE, 0x00AD); - Ade7953Write(0x120, 0x0030); -} - -void Ade7953GetData(void) -{ - int32_t reg[2][4]; - for (uint32_t i = 0; i < sizeof(Ade7953Registers); i++) { - int32_t value = Ade7953Read(0x300 + Ade7953Registers[i]); - if (8 == i) { - Ade7953.voltage_rms = value; - } else { - reg[i >> 2][i &3] = value; - } - } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: %d, [%d, %d, %d, %d], [%d, %d, %d, %d]"), - Ade7953.voltage_rms, reg[0][0], reg[0][1], reg[0][2], reg[0][3], - reg[1][0], reg[1][1], reg[1][2], reg[1][3]); - - uint32_t apparent_power[2] = { 0, 0 }; - uint32_t reactive_power[2] = { 0, 0 }; - - for (uint32_t channel = 0; channel < 2; channel++) { - Ade7953.current_rms[channel] = reg[channel][0]; - if (Ade7953.current_rms[channel] < 2000) { - Ade7953.current_rms[channel] = 0; - Ade7953.active_power[channel] = 0; - } else { - Ade7953.active_power[channel] = abs(reg[channel][1]); - apparent_power[channel] = abs(reg[channel][2]); - reactive_power[channel] = abs(reg[channel][3]); - } - } - - uint32_t current_rms_sum = Ade7953.current_rms[0] + Ade7953.current_rms[1]; - uint32_t active_power_sum = Ade7953.active_power[0] + Ade7953.active_power[1]; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ADE: U %d, I %d + %d = %d, P %d + %d = %d"), - Ade7953.voltage_rms, Ade7953.current_rms[0], Ade7953.current_rms[1], current_rms_sum, Ade7953.active_power[0], Ade7953.active_power[1], active_power_sum); - - if (Energy.power_on) { - Energy.voltage[0] = (float)Ade7953.voltage_rms / Settings.energy_voltage_calibration; - - for (uint32_t channel = 0; channel < 2; channel++) { - Energy.data_valid[channel] = 0; - Energy.active_power[channel] = (float)Ade7953.active_power[channel] / (Settings.energy_power_calibration / 10); - Energy.reactive_power[channel] = (float)reactive_power[channel] / (Settings.energy_power_calibration / 10); - Energy.apparent_power[channel] = (float)apparent_power[channel] / (Settings.energy_power_calibration / 10); - if (0 == Energy.active_power[channel]) { - Energy.current[channel] = 0; - } else { - Energy.current[channel] = (float)Ade7953.current_rms[channel] / (Settings.energy_current_calibration * 10); - } - } - } else { - Energy.data_valid[0] = ENERGY_WATCHDOG; - Energy.data_valid[1] = ENERGY_WATCHDOG; - } - - if (active_power_sum) { - Energy.kWhtoday_delta += ((active_power_sum * (100000 / (Settings.energy_power_calibration / 10))) / 3600); - EnergyUpdateToday(); - } -} - -void Ade7953EnergyEverySecond() -{ - if (Ade7953.init_step) { - if (1 == Ade7953.init_step) { - Ade7953Init(); - } - Ade7953.init_step--; - } else { - Ade7953GetData(); - } -} - -void Ade7953DrvInit(void) -{ - if (i2c_flg && (pin[GPIO_ADE7953_IRQ] < 99)) { - delay(100); - if (I2cDevice(ADE7953_ADDR)) { - if (HLW_PREF_PULSE == Settings.energy_power_calibration) { - Settings.energy_power_calibration = ADE7953_PREF; - Settings.energy_voltage_calibration = ADE7953_UREF; - Settings.energy_current_calibration = ADE7953_IREF; - } - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "ADE7953", ADE7953_ADDR); - Ade7953.init_step = 2; - - Energy.phase_count = 2; - Energy.voltage_common = true; - - energy_flg = XNRG_07; - } - } -} - -bool Ade7953Command(void) -{ - bool serviced = true; - - uint32_t channel = (2 == XdrvMailbox.index) ? 1 : 0; - uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); - - if (CMND_POWERCAL == Energy.command_code) { - if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_PREF; } - - } - else if (CMND_VOLTAGECAL == Energy.command_code) { - if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_UREF; } - - } - else if (CMND_CURRENTCAL == Energy.command_code) { - if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_IREF; } - - } - else if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && Ade7953.active_power[channel]) { - if ((value > 100) && (value < 200000)) { - Settings.energy_power_calibration = (Ade7953.active_power[channel] * 1000) / value; - } - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && Ade7953.voltage_rms) { - if ((value > 10000) && (value < 26000)) { - Settings.energy_voltage_calibration = (Ade7953.voltage_rms * 100) / value; - } - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && Ade7953.current_rms[channel]) { - if ((value > 2000) && (value < 1000000)) { - Settings.energy_current_calibration = ((Ade7953.current_rms[channel] * 100) / value) * 100; - } - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg07(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_ENERGY_EVERY_SECOND: - Ade7953EnergyEverySecond(); - break; - case FUNC_COMMAND: - result = Ade7953Command(); - break; - case FUNC_PRE_INIT: - Ade7953DrvInit(); - break; - } - return result; -} - -#endif -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_08_sdm120.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_08_sdm120.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_SDM120_2 - - - - - - -#define XNRG_08 8 - - -#ifndef SDM120_SPEED - #define SDM120_SPEED 2400 -#endif - -#ifndef SDM120_ADDR - #define SDM120_ADDR 1 -#endif - -#include -TasmotaModbus *Sdm120Modbus; - -const uint8_t sdm120_table = 8; -const uint8_t sdm220_table = 13; - -const uint16_t sdm120_start_addresses[] { - 0x0000, - 0x0006, - 0x000C, - 0x0012, - 0x0018, - 0x001E, - 0x0046, - 0x0156, - - 0X0048, - 0X004A, - 0X004C, - 0X004E, - 0X0024 -}; - -struct SDM120 { - float total_active = 0; - float import_active = NAN; - float import_reactive = 0; - float export_reactive = 0; - float phase_angle = 0; - uint8_t read_state = 0; - uint8_t send_retry = 0; - uint8_t start_address_count = sdm220_table; -} Sdm120; - - - -void SDM120Every250ms(void) -{ - bool data_ready = Sdm120Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[14]; - - uint32_t error = Sdm120Modbus->ReceiveBuffer(buffer, 2); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm120Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM120 error %d"), error); - } else { - Energy.data_valid[0] = 0; - - - - - float value; - ((uint8_t*)&value)[3] = buffer[3]; - ((uint8_t*)&value)[2] = buffer[4]; - ((uint8_t*)&value)[1] = buffer[5]; - ((uint8_t*)&value)[0] = buffer[6]; - - switch(Sdm120.read_state) { - case 0: - Energy.voltage[0] = value; - break; - - case 1: - Energy.current[0] = value; - break; - - case 2: - Energy.active_power[0] = value; - break; - - case 3: - Energy.apparent_power[0] = value; - break; - - case 4: - Energy.reactive_power[0] = value; - break; - - case 5: - Energy.power_factor[0] = value; - break; - - case 6: - Energy.frequency[0] = value; - break; - - case 7: - Sdm120.total_active = value; - break; - - case 8: - Sdm120.import_active = value; - break; - - case 9: - Energy.export_active = value; - break; - - case 10: - Sdm120.import_reactive = value; - break; - - case 11: - Sdm120.export_reactive = value; - break; - - case 12: - Sdm120.phase_angle = value; - break; - } - - Sdm120.read_state++; - if (Sdm120.read_state == Sdm120.start_address_count) { - Sdm120.read_state = 0; - - if (Sdm120.start_address_count > sdm120_table) { - if (!isnan(Sdm120.import_active)) { - Sdm120.total_active = Sdm120.import_active; - } else { - Sdm120.start_address_count = sdm120_table; - } - } - EnergyUpdateTotal(Sdm120.total_active, true); - } - } - } - - if (0 == Sdm120.send_retry || data_ready) { - Sdm120.send_retry = 5; - Sdm120Modbus->Send(SDM120_ADDR, 0x04, sdm120_start_addresses[Sdm120.read_state], 2); - } else { - Sdm120.send_retry--; - } -} - -void Sdm120SnsInit(void) -{ - Sdm120Modbus = new TasmotaModbus(pin[GPIO_SDM120_RX], pin[GPIO_SDM120_TX]); - uint8_t result = Sdm120Modbus->Begin(SDM120_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void Sdm120DrvInit(void) -{ - if ((pin[GPIO_SDM120_RX] < 99) && (pin[GPIO_SDM120_TX] < 99)) { - energy_flg = XNRG_08; - } -} - -void Sdm220Reset(void) -{ - if (isnan(Sdm120.import_active)) { return; } - - Sdm120.import_active = 0; - Sdm120.import_reactive = 0; - Sdm120.export_reactive = 0; - Sdm120.phase_angle = 0; -} - -#ifdef USE_WEBSERVER -const char HTTP_ENERGY_SDM220[] PROGMEM = - "{s}" D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - "{s}" D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - "{s}" D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}"; -#endif - -void Sdm220Show(bool json) -{ - if (isnan(Sdm120.import_active)) { return; } - - char import_active_chr[FLOATSZ]; - dtostrfd(Sdm120.import_active, Settings.flag2.energy_resolution, import_active_chr); - char import_reactive_chr[FLOATSZ]; - dtostrfd(Sdm120.import_reactive, Settings.flag2.energy_resolution, import_reactive_chr); - char export_reactive_chr[FLOATSZ]; - dtostrfd(Sdm120.export_reactive, Settings.flag2.energy_resolution, export_reactive_chr); - char phase_angle_chr[FLOATSZ]; - dtostrfd(Sdm120.phase_angle, 2, phase_angle_chr); - - if (json) { - ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s"), - import_active_chr, import_reactive_chr, export_reactive_chr, phase_angle_chr); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_ENERGY_SDM220, import_reactive_chr, export_reactive_chr, phase_angle_chr); -#endif - } -} - - - - - -bool Xnrg08(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { SDM120Every250ms(); } - break; - case FUNC_JSON_APPEND: - Sdm220Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sdm220Show(0); - break; -#endif - case FUNC_ENERGY_RESET: - Sdm220Reset(); - break; - case FUNC_INIT: - Sdm120SnsInit(); - break; - case FUNC_PRE_INIT: - Sdm120DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_09_dds2382.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_09_dds2382.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_DDS2382 - - - - - - -#define XNRG_09 9 - -#ifndef DDS2382_SPEED -#define DDS2382_SPEED 9600 -#endif -#ifndef DDS2382_ADDR -#define DDS2382_ADDR 1 -#endif - -#include -TasmotaModbus *Dds2382Modbus; - -uint8_t Dds2382_send_retry = 0; - -void Dds2382EverySecond(void) -{ - bool data_ready = Dds2382Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[46]; - - uint32_t error = Dds2382Modbus->ReceiveBuffer(buffer, 18); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Dds2382Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "DDS2382 response error %d"), error); - } else { - Energy.data_valid[0] = 0; - - - - - Energy.voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0; - Energy.current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0; - Energy.active_power[0] = (float)((buffer[31] << 8) + buffer[32]); - Energy.reactive_power[0] = (float)((buffer[33] << 8) + buffer[34]); - Energy.power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0; - Energy.frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0; - Energy.export_active = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[13] << 8) + buffer[14]) / 100.0; - - float import_active = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[17] << 8) + buffer[18]) / 100.0; - - EnergyUpdateTotal(import_active, false); - } - } - - if (0 == Dds2382_send_retry || data_ready) { - Dds2382_send_retry = 5; - Dds2382Modbus->Send(DDS2382_ADDR, 0x03, 0, 18); - } else { - Dds2382_send_retry--; - } -} - -void Dds2382SnsInit(void) -{ - Dds2382Modbus = new TasmotaModbus(pin[GPIO_DDS2382_RX], pin[GPIO_DDS2382_TX]); - uint8_t result = Dds2382Modbus->Begin(DDS2382_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void Dds2382DrvInit(void) -{ - if ((pin[GPIO_DDS2382_RX] < 99) && (pin[GPIO_DDS2382_TX] < 99)) { - energy_flg = XNRG_09; - } -} - - - - - -bool Xnrg09(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_ENERGY_EVERY_SECOND: - if (uptime > 4) { Dds2382EverySecond(); } - break; - case FUNC_INIT: - Dds2382SnsInit(); - break; - case FUNC_PRE_INIT: - Dds2382DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_10_sdm630.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_10_sdm630.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_SDM630_2 - - - - - - -#define XNRG_10 10 - - -#ifndef SDM630_SPEED - #define SDM630_SPEED 9600 -#endif - -#ifndef SDM630_ADDR - #define SDM630_ADDR 1 -#endif - -#include -TasmotaModbus *Sdm630Modbus; - -const uint16_t sdm630_start_addresses[] { - 0x0000, - 0x0002, - 0x0004, - 0x0006, - 0x0008, - 0x000A, - 0x000C, - 0x000E, - 0x0010, - 0x0018, - 0x001A, - 0x001C, - 0x001E, - 0x0020, - 0x0022, - 0x0156 -}; - -struct SDM630 { - uint8_t read_state = 0; - uint8_t send_retry = 0; -} Sdm630; - - - -void SDM630Every250ms(void) -{ - bool data_ready = Sdm630Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[14]; - - uint32_t error = Sdm630Modbus->ReceiveBuffer(buffer, 2); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm630Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM630 error %d"), error); - } else { - Energy.data_valid[0] = 0; - Energy.data_valid[1] = 0; - Energy.data_valid[2] = 0; - - - - - float value; - ((uint8_t*)&value)[3] = buffer[3]; - ((uint8_t*)&value)[2] = buffer[4]; - ((uint8_t*)&value)[1] = buffer[5]; - ((uint8_t*)&value)[0] = buffer[6]; - - switch(Sdm630.read_state) { - case 0: - Energy.voltage[0] = value; - break; - - case 1: - Energy.voltage[1] = value; - break; - - case 2: - Energy.voltage[2] = value; - break; - - case 3: - Energy.current[0] = value; - break; - - case 4: - Energy.current[1] = value; - break; - - case 5: - Energy.current[2] = value; - break; - - case 6: - Energy.active_power[0] = value; - break; - - case 7: - Energy.active_power[1] = value; - break; - - case 8: - Energy.active_power[2] = value; - break; - - case 9: - Energy.reactive_power[0] = value; - break; - - case 10: - Energy.reactive_power[1] = value; - break; - - case 11: - Energy.reactive_power[2] = value; - break; - - case 12: - Energy.power_factor[0] = value; - break; - - case 13: - Energy.power_factor[1] = value; - break; - - case 14: - Energy.power_factor[2] = value; - break; - - case 15: - EnergyUpdateTotal(value, true); - break; - } - - Sdm630.read_state++; - if (sizeof(sdm630_start_addresses)/2 == Sdm630.read_state) { - Sdm630.read_state = 0; - } - } - } - - if (0 == Sdm630.send_retry || data_ready) { - Sdm630.send_retry = 5; - Sdm630Modbus->Send(SDM630_ADDR, 0x04, sdm630_start_addresses[Sdm630.read_state], 2); - } else { - Sdm630.send_retry--; - } -} - -void Sdm630SnsInit(void) -{ - Sdm630Modbus = new TasmotaModbus(pin[GPIO_SDM630_RX], pin[GPIO_SDM630_TX]); - uint8_t result = Sdm630Modbus->Begin(SDM630_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - Energy.phase_count = 3; - } else { - energy_flg = ENERGY_NONE; - } -} - -void Sdm630DrvInit(void) -{ - if ((pin[GPIO_SDM630_RX] < 99) && (pin[GPIO_SDM630_TX] < 99)) { - energy_flg = XNRG_10; - } -} - - - - - -bool Xnrg10(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { SDM630Every250ms(); } - break; - case FUNC_INIT: - Sdm630SnsInit(); - break; - case FUNC_PRE_INIT: - Sdm630DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_interface.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xnrg_interface.ino" -#ifdef USE_ENERGY_SENSOR - -#ifdef XFUNC_PTR_IN_ROM -bool (* const xnrg_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xnrg_func_ptr[])(uint8_t) = { -#endif - -#ifdef XNRG_01 - &Xnrg01, -#endif - -#ifdef XNRG_02 - &Xnrg02, -#endif - -#ifdef XNRG_03 - &Xnrg03, -#endif - -#ifdef XNRG_04 - &Xnrg04, -#endif - -#ifdef XNRG_05 - &Xnrg05, -#endif - -#ifdef XNRG_06 - &Xnrg06, -#endif - -#ifdef XNRG_07 - &Xnrg07, -#endif - -#ifdef XNRG_08 - &Xnrg08, -#endif - -#ifdef XNRG_09 - &Xnrg09, -#endif - -#ifdef XNRG_10 - &Xnrg10, -#endif - -#ifdef XNRG_11 - &Xnrg11, -#endif - -#ifdef XNRG_12 - &Xnrg12, -#endif - -#ifdef XNRG_13 - &Xnrg13, -#endif - -#ifdef XNRG_14 - &Xnrg14, -#endif - -#ifdef XNRG_15 - &Xnrg15, -#endif - -#ifdef XNRG_16 - &Xnrg16 -#endif -}; - -const uint8_t xnrg_present = sizeof(xnrg_func_ptr) / sizeof(xnrg_func_ptr[0]); - -uint8_t xnrg_active = 0; - -bool XnrgCall(uint8_t function) -{ - if (FUNC_PRE_INIT == function) { - for (uint32_t x = 0; x < xnrg_present; x++) { - xnrg_func_ptr[x](function); - if (energy_flg) { - xnrg_active = x; - return true; - } - } - } - else if (energy_flg) { - return xnrg_func_ptr[xnrg_active](function); - } - return false; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xplg_ws2812.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xplg_ws2812.ino" -#ifdef USE_LIGHT -#ifdef USE_WS2812 - - - - -#include - -#if (USE_WS2812_CTYPE == NEO_GRB) - typedef NeoGrbFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_BRG) - typedef NeoBrgFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_RBG) - typedef NeoRbgFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_RGBW) - typedef NeoRgbwFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_GRBW) - typedef NeoGrbwFeature selectedNeoFeatureType; -#else - typedef NeoRgbFeature selectedNeoFeatureType; -#endif - -#ifdef USE_WS2812_DMA - - -#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) - typedef NeoEsp8266DmaWs2812xMethod selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) - typedef NeoEsp8266DmaSk6812Method selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_APA106) - typedef NeoEsp8266DmaApa106Method selectedNeoSpeedType; -#else - typedef NeoEsp8266Dma800KbpsMethod selectedNeoSpeedType; -#endif - -#else - - -#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) - typedef NeoEsp8266BitBangWs2812xMethod selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) - typedef NeoEsp8266BitBangSk6812Method selectedNeoSpeedType; -#else - typedef NeoEsp8266BitBang800KbpsMethod selectedNeoSpeedType; -#endif - -#endif - -NeoPixelBus *strip = nullptr; - -struct WsColor { - uint8_t red, green, blue; -}; - -struct ColorScheme { - WsColor* colors; - uint8_t count; -}; - -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[WS2812_SCHEMES] = { - kIncandescent, 2, - kRgb, 3, - kChristmas, 2, - kHanukkah, 2, - kwanzaa, 3, - kRainbow, 7, - kFire, 3 }; - -uint8_t kWidth[5] = { - 1, - 2, - 4, - 8, - 255 }; -uint8_t kWsRepeat[5] = { - 8, - 6, - 4, - 2, - 1 }; - -uint8_t ws_show_next = 1; -bool ws_suspend_update = false; - - - -void Ws2812StripShow(void) -{ -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor c; -#else - RgbColor c; -#endif - - if (Settings.light_correction) { - for (uint32_t i = 0; i < Settings.light_pixels; i++) { - c = strip->GetPixelColor(i); - c.R = ledGamma(c.R); - c.G = ledGamma(c.G); - c.B = ledGamma(c.B); -#if (USE_WS2812_CTYPE > NEO_3LED) - c.W = ledGamma(c.W); -#endif - strip->SetPixelColor(i, c); - } - } - strip->Show(); -} - -int mod(int a, int b) -{ - int ret = a % b; - if (ret < 0) ret += b; - return ret; -} - -void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offset) -{ -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor color; -#else - RgbColor color; -#endif - - uint32_t mod_position = mod(position, (int)Settings.light_pixels); - - color = strip->GetPixelColor(mod_position); - float dimmer = 100 / (float)Settings.light_dimmer; - color.R = tmin(color.R + ((hand_color.red / dimmer) * offset), 255); - color.G = tmin(color.G + ((hand_color.green / dimmer) * offset), 255); - color.B = tmin(color.B + ((hand_color.blue / dimmer) * offset), 255); - strip->SetPixelColor(mod_position, color); -} - -void Ws2812UpdateHand(int position, uint32_t index) -{ - uint32_t width = Settings.light_width; - if (index < WS_MARKER) { width = Settings.ws_width[index]; } - if (!width) { return; } - - position = (position + Settings.light_rotation) % Settings.light_pixels; - - if (Settings.flag.ws_clock_reverse) position = Settings.light_pixels -position; - WsColor hand_color = { Settings.ws_color[index][WS_RED], Settings.ws_color[index][WS_GREEN], Settings.ws_color[index][WS_BLUE] }; - - Ws2812UpdatePixelColor(position, hand_color, 1); - - uint32_t range = ((width -1) / 2) +1; - for (uint32_t h = 1; h < range; h++) { - float offset = (float)(range - h) / (float)range; - Ws2812UpdatePixelColor(position -h, hand_color, offset); - Ws2812UpdatePixelColor(position +h, hand_color, offset); - } -} - -void Ws2812Clock(void) -{ - strip->ClearTo(0); - int clksize = 60000 / (int)Settings.light_pixels; - - Ws2812UpdateHand((RtcTime.second * 1000) / clksize, WS_SECOND); - Ws2812UpdateHand((RtcTime.minute * 1000) / clksize, WS_MINUTE); - Ws2812UpdateHand((((RtcTime.hour % 12) * 5000) + ((RtcTime.minute * 1000) / 12 )) / clksize, WS_HOUR); - if (Settings.ws_color[WS_MARKER][WS_RED] + Settings.ws_color[WS_MARKER][WS_GREEN] + Settings.ws_color[WS_MARKER][WS_BLUE]) { - for (uint32_t i = 0; i < 12; i++) { - Ws2812UpdateHand((i * 5000) / clksize, WS_MARKER); - } - } - - Ws2812StripShow(); -} - -void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t range, uint32_t gradRange, uint32_t i) -{ - - - - - ColorScheme scheme = kSchemes[schemenr]; - uint32_t curRange = i / range; - uint32_t rangeIndex = i % range; - uint32_t colorIndex = rangeIndex / gradRange; - uint32_t start = colorIndex; - uint32_t end = colorIndex +1; - if (curRange % 2 != 0) { - start = (scheme.count -1) - start; - end = (scheme.count -1) - end; - } - 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 Ws2812Gradient(uint32_t schemenr) -{ - - - - - -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor c; - c.W = 0; -#else - RgbColor c; -#endif - - ColorScheme scheme = kSchemes[schemenr]; - if (scheme.count < 2) { return; } - - uint32_t repeat = kWsRepeat[Settings.light_width]; - uint32_t range = (uint32_t)ceil((float)Settings.light_pixels / (float)repeat); - uint32_t gradRange = (uint32_t)ceil((float)range / (float)(scheme.count - 1)); - uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); - uint32_t offset = speed > 0 ? Light.strip_timer_counter / speed : 0; - - WsColor oldColor, currentColor; - Ws2812GradientColor(schemenr, &oldColor, range, gradRange, offset); - currentColor = oldColor; - for (uint32_t i = 0; i < Settings.light_pixels; i++) { - if (kWsRepeat[Settings.light_width] > 1) { - Ws2812GradientColor(schemenr, ¤tColor, range, gradRange, i +offset); - } - if (Settings.light_speed > 0) { - - c.R = map(Light.strip_timer_counter % speed, 0, speed, oldColor.red, currentColor.red); - c.G = map(Light.strip_timer_counter % speed, 0, speed, oldColor.green, currentColor.green); - c.B = map(Light.strip_timer_counter % speed, 0, speed, oldColor.blue, currentColor.blue); - } - else { - - c.R = currentColor.red; - c.G = currentColor.green; - c.B = currentColor.blue; - } - strip->SetPixelColor(i, c); - oldColor = currentColor; - } - Ws2812StripShow(); -} - -void Ws2812Bars(uint32_t schemenr) -{ - - - - - -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor c; - c.W = 0; -#else - RgbColor c; -#endif - - ColorScheme scheme = kSchemes[schemenr]; - - uint32_t maxSize = Settings.light_pixels / scheme.count; - if (kWidth[Settings.light_width] > maxSize) { maxSize = 0; } - - uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); - uint32_t offset = (speed > 0) ? Light.strip_timer_counter / speed : 0; - - WsColor mcolor[scheme.count]; - memcpy(mcolor, scheme.colors, sizeof(mcolor)); - float dimmer = 100 / (float)Settings.light_dimmer; - for (uint32_t i = 0; i < scheme.count; i++) { - 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; - } - uint32_t colorIndex = offset % scheme.count; - for (uint32_t i = 0; i < Settings.light_pixels; i++) { - if (maxSize) { 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); - } - Ws2812StripShow(); -} - - - - - -void Ws2812Init(void) -{ - - strip = new NeoPixelBus(WS2812_MAX_LEDS, pin[GPIO_WS2812]); - strip->Begin(); - Ws2812Clear(); -} - -void Ws2812Clear(void) -{ - strip->ClearTo(0); - strip->Show(); - ws_show_next = 1; -} - -void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white) -{ -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor lcolor; - lcolor.W = white; -#else - RgbColor lcolor; -#endif - - lcolor.R = red; - lcolor.G = green; - lcolor.B = blue; - if (led) { - strip->SetPixelColor(led -1, lcolor); - } else { - - for (uint32_t i = 0; i < Settings.light_pixels; i++) { - strip->SetPixelColor(i, lcolor); - } - } - - if (!ws_suspend_update) { - strip->Show(); - ws_show_next = 1; - } -} - -void Ws2812ForceSuspend (void) { - ws_suspend_update = true; -} - -void Ws2812ForceUpdate (void) { - ws_suspend_update = false; - strip->Show(); - ws_show_next = 1; -} - -char* Ws2812GetColor(uint32_t led, char* scolor) -{ - uint8_t sl_ledcolor[4]; - - #if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor lcolor = strip->GetPixelColor(led -1); - sl_ledcolor[3] = lcolor.W; - #else - RgbColor lcolor = strip->GetPixelColor(led -1); - #endif - sl_ledcolor[0] = lcolor.R; - sl_ledcolor[1] = lcolor.G; - sl_ledcolor[2] = lcolor.B; - scolor[0] = '\0'; - for (uint32_t i = 0; i < Light.subtype; 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 Ws2812ShowScheme(uint32_t scheme) -{ - switch (scheme) { - case 0: - if ((1 == state_250mS) || (ws_show_next)) { - Ws2812Clock(); - ws_show_next = 0; - } - break; - default: - if (1 == Settings.light_fade) { - Ws2812Gradient(scheme -1); - } else { - Ws2812Bars(scheme -1); - } - ws_show_next = 1; - break; - } -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_01_counter.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_01_counter.ino" -#ifdef USE_COUNTER - - - - -#define XSNS_01 1 - -#define D_PRFX_COUNTER "Counter" -#define D_CMND_COUNTERTYPE "Type" -#define D_CMND_COUNTERDEBOUNCE "Debounce" - -const char kCounterCommands[] PROGMEM = D_PRFX_COUNTER "|" - "|" D_CMND_COUNTERTYPE "|" D_CMND_COUNTERDEBOUNCE ; - -void (* const CounterCommand[])(void) PROGMEM = - { &CmndCounter, &CmndCounterType, &CmndCounterDebounce }; - -unsigned long last_counter_timer[MAX_COUNTERS]; -uint8_t counter_no_pullup = 0; - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -void CounterUpdate(uint8_t index) ICACHE_RAM_ATTR; -void CounterUpdate1(void) ICACHE_RAM_ATTR; -void CounterUpdate2(void) ICACHE_RAM_ATTR; -void CounterUpdate3(void) ICACHE_RAM_ATTR; -void CounterUpdate4(void) ICACHE_RAM_ATTR; -#endif - -void CounterUpdate(uint8_t index) -{ - unsigned long counter_debounce_time = micros() - last_counter_timer[index -1]; - if (counter_debounce_time > Settings.pulse_counter_debounce * 1000) { - last_counter_timer[index -1] = micros(); - if (bitRead(Settings.pulse_counter_type, index -1)) { - RtcSettings.pulse_counter[index -1] = counter_debounce_time; - } else { - RtcSettings.pulse_counter[index -1]++; - } - - - } -} - -void CounterUpdate1(void) -{ - CounterUpdate(1); -} - -void CounterUpdate2(void) -{ - CounterUpdate(2); -} - -void CounterUpdate3(void) -{ - CounterUpdate(3); -} - -void CounterUpdate4(void) -{ - CounterUpdate(4); -} - - - -bool CounterPinState(void) -{ - if ((XdrvMailbox.index >= GPIO_CNTR1_NP) && (XdrvMailbox.index < (GPIO_CNTR1_NP + MAX_COUNTERS))) { - bitSet(counter_no_pullup, XdrvMailbox.index - GPIO_CNTR1_NP); - XdrvMailbox.index -= (GPIO_CNTR1_NP - GPIO_CNTR1); - return true; - } - return false; -} - -void CounterInit(void) -{ - typedef void (*function) () ; - function counter_callbacks[] = { CounterUpdate1, CounterUpdate2, CounterUpdate3, CounterUpdate4 }; - - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - pinMode(pin[GPIO_CNTR1 +i], bitRead(counter_no_pullup, i) ? INPUT : INPUT_PULLUP); - attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); - } - } -} - -void CounterSaveState(void) -{ - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - Settings.pulse_counter[i] = RtcSettings.pulse_counter[i]; - } - } -} - -void CounterShow(bool json) -{ - bool header = false; - uint8_t dsxflg = 0; - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - char counter[33]; - if (bitRead(Settings.pulse_counter_type, i)) { - dtostrfd((double)RtcSettings.pulse_counter[i] / 1000000, 6, counter); - } else { - dsxflg++; - snprintf_P(counter, sizeof(counter), PSTR("%lu"), RtcSettings.pulse_counter[i]); - } - - if (json) { - if (!header) { - ResponseAppend_P(PSTR(",\"COUNTER\":{")); - } - ResponseAppend_P(PSTR("%s\"C%d\":%s"), (header)?",":"", i +1, counter); - header = true; -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (1 == dsxflg)) { - DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]); - dsxflg++; - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(PSTR("{s}" D_COUNTER "%d{m}%s%s{e}"), - i +1, counter, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : ""); -#endif - } - } - if (bitRead(Settings.pulse_counter_type, i)) { - RtcSettings.pulse_counter[i] = 0xFFFFFFFF; - } - } - if (header) { - ResponseJsonEnd(); - } -} - - - - - -void CmndCounter(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { - if ((XdrvMailbox.data_len > 0) && (pin[GPIO_CNTR1 + XdrvMailbox.index -1] < 99)) { - if ((XdrvMailbox.data[0] == '-') || (XdrvMailbox.data[0] == '+')) { - RtcSettings.pulse_counter[XdrvMailbox.index -1] += XdrvMailbox.payload; - Settings.pulse_counter[XdrvMailbox.index -1] += XdrvMailbox.payload; - } else { - RtcSettings.pulse_counter[XdrvMailbox.index -1] = XdrvMailbox.payload; - Settings.pulse_counter[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - } - ResponseCmndIdxNumber(RtcSettings.pulse_counter[XdrvMailbox.index -1]); - } -} - -void CmndCounterType(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1) && (pin[GPIO_CNTR1 + XdrvMailbox.index -1] < 99)) { - bitWrite(Settings.pulse_counter_type, XdrvMailbox.index -1, XdrvMailbox.payload &1); - RtcSettings.pulse_counter[XdrvMailbox.index -1] = 0; - Settings.pulse_counter[XdrvMailbox.index -1] = 0; - } - ResponseCmndIdxNumber(bitRead(Settings.pulse_counter_type, XdrvMailbox.index -1)); - } -} - -void CmndCounterDebounce(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { - Settings.pulse_counter_debounce = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.pulse_counter_debounce); -} - - - - - -bool Xsns01(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_JSON_APPEND: - CounterShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - CounterShow(0); - break; -#endif - case FUNC_SAVE_BEFORE_RESTART: - case FUNC_SAVE_AT_MIDNIGHT: - CounterSaveState(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kCounterCommands, CounterCommand); - break; - case FUNC_INIT: - CounterInit(); - break; - case FUNC_PIN_STATE: - result = CounterPinState(); - break; - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_02_analog.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_02_analog.ino" -#ifndef USE_ADC_VCC - - - - -#define XSNS_02 2 - -#define TO_CELSIUS(x) ((x) - 273.15) -#define TO_KELVIN(x) ((x) + 273.15) - - -#define ANALOG_V33 3.3 -#define ANALOG_T0 TO_KELVIN(25.0) - - - - - -#define ANALOG_NTC_BRIDGE_RESISTANCE 32000 -#define ANALOG_NTC_RESISTANCE 10000 -#define ANALOG_NTC_B_COEFFICIENT 3350 - - - - - -#define ANALOG_LDR_BRIDGE_RESISTANCE 10000 -#define ANALOG_LDR_LUX_CALC_SCALAR 12518931 -#define ANALOG_LDR_LUX_CALC_EXPONENT -1.4050 - -uint16_t adc_last_value = 0; -float adc_temp = 0; - -void AdcInit(void) -{ - if ((Settings.adc_param_type != my_adc0) || (Settings.adc_param1 > 1000000) || (Settings.adc_param1 < 100)) { - if (ADC0_TEMP == my_adc0) { - - Settings.adc_param_type = ADC0_TEMP; - Settings.adc_param1 = ANALOG_NTC_BRIDGE_RESISTANCE; - Settings.adc_param2 = ANALOG_NTC_RESISTANCE; - Settings.adc_param3 = ANALOG_NTC_B_COEFFICIENT * 10000; - } - else if (ADC0_LIGHT == my_adc0) { - Settings.adc_param_type = ADC0_LIGHT; - Settings.adc_param1 = ANALOG_LDR_BRIDGE_RESISTANCE; - Settings.adc_param2 = ANALOG_LDR_LUX_CALC_SCALAR; - Settings.adc_param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000; - } - } -} - -uint16_t AdcRead(uint8_t factor) -{ - - - - - - uint8_t samples = 1 << factor; - uint16_t analog = 0; - for (uint32_t i = 0; i < samples; i++) { - analog += analogRead(A0); - delay(1); - } - analog >>= factor; - return analog; -} - -#ifdef USE_RULES -void AdcEvery250ms(void) -{ - if (ADC0_INPUT == my_adc0) { - uint16_t new_value = AdcRead(5); - if ((new_value < adc_last_value -10) || (new_value > adc_last_value +10)) { - adc_last_value = new_value; - uint16_t value = adc_last_value / 10; - Response_P(PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); - XdrvRulesProcess(); - } - } -} -#endif - -uint16_t AdcGetLux() -{ - int adc = AdcRead(2); - - double resistorVoltage = ((double)adc / 1023) * ANALOG_V33; - double ldrVoltage = ANALOG_V33 - resistorVoltage; - double ldrResistance = ldrVoltage / resistorVoltage * (double)Settings.adc_param1; - double ldrLux = (double)Settings.adc_param2 * FastPrecisePow(ldrResistance, (double)Settings.adc_param3 / 10000); - - return (uint16_t)ldrLux; -} - -void AdcEverySecond(void) -{ - if (ADC0_TEMP == my_adc0) { - int adc = AdcRead(2); - - double Rt = (adc * Settings.adc_param1) / (1024.0 * ANALOG_V33 - (double)adc); - double BC = (double)Settings.adc_param3 / 10000; - double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Settings.adc_param2)); - adc_temp = ConvertTemp(TO_CELSIUS(T)); - } -} - -void AdcShow(bool json) -{ - if (ADC0_INPUT == my_adc0) { - uint16_t analog = AdcRead(5); - - if (json) { - ResponseAppend_P(PSTR(",\"ANALOG\":{\"A0\":%d}"), analog); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ANALOG, "", 0, analog); -#endif - } - } - else if (ADC0_TEMP == my_adc0) { - char temperature[33]; - dtostrfd(adc_temp, Settings.flag2.temperature_resolution, temperature); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMP, "ANALOG", temperature); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, adc_temp); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); -#endif - } - } - else if (ADC0_LIGHT == my_adc0) { - uint16_t adc_light = AdcGetLux(); - - if (json) { - ResponseAppend_P(JSON_SNS_ILLUMINANCE, "ANALOG", adc_light); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_ILLUMINANCE, adc_light); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, "", adc_light); -#endif - } - } -} - - - - - -#define D_CMND_ADCPARAM "AdcParam" -const char kAdcCommands[] PROGMEM = "|" - D_CMND_ADC "|" D_CMND_ADCS "|" D_CMND_ADCPARAM; - -void (* const AdcCommand[])(void) PROGMEM = - { &CmndAdc, &CmndAdcs, &CmndAdcParam }; - -void CmndAdc(void) -{ - if (ValidAdc() && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < ADC0_END)) { - Settings.my_adc0 = XdrvMailbox.payload; - restart_flag = 2; - } - char stemp1[TOPSZ]; - Response_P(PSTR("{\"" D_CMND_ADC "0\":{\"%d\":\"%s\"}}"), Settings.my_adc0, GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_adc0, kAdc0Names)); -} - -void CmndAdcs(void) -{ - Response_P(PSTR("{\"" D_CMND_ADCS "\":{")); - bool jsflg = false; - char stemp1[TOPSZ]; - for (uint32_t i = 0; i < ADC0_END; i++) { - if (jsflg) { - ResponseAppend_P(PSTR(",")); - } - jsflg = true; - ResponseAppend_P(PSTR("\"%d\":\"%s\""), i, GetTextIndexed(stemp1, sizeof(stemp1), i, kAdc0Names)); - } - ResponseJsonEndEnd(); -} - -void CmndAdcParam(void) -{ - if (XdrvMailbox.data_len) { - if ((ADC0_TEMP == XdrvMailbox.payload) || (ADC0_LIGHT == XdrvMailbox.payload)) { - - if (strstr(XdrvMailbox.data, ",") != nullptr) { - char sub_string[XdrvMailbox.data_len +1]; - - - Settings.adc_param_type = XdrvMailbox.payload; - - Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); - Settings.adc_param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); - } else { - - - Settings.adc_param_type = 0; - AdcInit(); - } - } - } - - - int value = Settings.adc_param3; - uint8_t precision; - for (precision = 4; precision > 0; precision--) { - if (value % 10) { break; } - value /= 10; - } - char param3[33]; - dtostrfd(((double)Settings.adc_param3)/10000, precision, param3); - Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d,%s]}"), - Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2, param3); -} - - - - - -bool Xsns02(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_COMMAND: - result = DecodeCommand(kAdcCommands, AdcCommand); - break; - default: - if ((ADC0_INPUT == my_adc0) || (ADC0_TEMP == my_adc0) || (ADC0_LIGHT == my_adc0)) { - switch (function) { -#ifdef USE_RULES - case FUNC_EVERY_250_MSECOND: - AdcEvery250ms(); - break; -#endif - case FUNC_EVERY_SECOND: - AdcEverySecond(); - break; - case FUNC_INIT: - AdcInit(); - break; - case FUNC_JSON_APPEND: - AdcShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - AdcShow(0); - break; -#endif - } - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_04_snfsc.ino" -# 56 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_04_snfsc.ino" -#define XSNS_04 4 - -uint16_t sc_value[5] = { 0 }; - -void SonoffScSend(const char *data) -{ - Serial.write(data); - Serial.write('\x1B'); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_TRANSMIT " %s"), data); -} - -void SonoffScInit(void) -{ - - SonoffScSend("AT+START"); - -} - -void SonoffScSerialInput(char *rcvstat) -{ - char *p; - char *str; - uint16_t value[5] = { 0 }; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_RECEIVED " %s"), rcvstat); - - if (!strncasecmp_P(rcvstat, PSTR("AT+UPDATE="), 10)) { - int8_t i = -1; - for (str = strtok_r(rcvstat, ":", &p); str && i < 5; str = strtok_r(nullptr, ":", &p)) { - value[i++] = atoi(str); - } - if (value[0] > 0) { - for (uint32_t i = 0; i < 5; i++) { - sc_value[i] = value[i]; - } - sc_value[2] = (11 - sc_value[2]) * 10; - sc_value[3] *= 10; - sc_value[4] = (11 - sc_value[4]) * 10; - SonoffScSend("AT+SEND=ok"); - } else { - SonoffScSend("AT+SEND=fail"); - } - } - else if (!strcasecmp_P(rcvstat, PSTR("AT+STATUS?"))) { - SonoffScSend("AT+STATUS=4"); - } -} - - - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SCPLUS[] PROGMEM = - "{s}" D_LIGHT "{m}%d%%{e}{s}" D_NOISE "{m}%d%%{e}{s}" D_AIR_QUALITY "{m}%d%%{e}"; -#endif - -void SonoffScShow(bool json) -{ - if (sc_value[0] > 0) { - float t = ConvertTemp(sc_value[1]); - float h = ConvertHumidity(sc_value[0]); - - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(PSTR(",\"SonoffSC\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), - temperature, humidity, sc_value[2], sc_value[3], sc_value[4]); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(temperature, humidity); - DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]); - DomoticzSensor(DZ_COUNT, sc_value[3]); - DomoticzSensor(DZ_AIRQUALITY, 500 + ((100 - sc_value[4]) * 20)); - } -#endif - -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, t); - KnxSensor(KNX_HUMIDITY, h); - } -#endif - -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, "", humidity); - WSContentSend_PD(HTTP_SNS_SCPLUS, sc_value[2], sc_value[3], sc_value[4]); -#endif - } - } -} - - - - - -bool Xsns04(uint8_t function) -{ - bool result = false; - - if (SONOFF_SC == my_module_type) { - switch (function) { - case FUNC_INIT: - SonoffScInit(); - break; - case FUNC_JSON_APPEND: - SonoffScShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SonoffScShow(0); - break; -#endif - } - } - return result; -} -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_05_ds18b20.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_05_ds18b20.ino" -#ifdef USE_DS18B20 - - - - -#define XSNS_05 5 - -#define W1_SKIP_ROM 0xCC -#define W1_CONVERT_TEMP 0x44 -#define W1_READ_SCRATCHPAD 0xBE - -float ds18b20_temperature = 0; -uint8_t ds18b20_valid = 0; -uint8_t ds18x20_pin = 0; -char ds18b20_types[] = "DS18B20"; - - - - - -uint8_t OneWireReset(void) -{ - uint8_t retries = 125; - - -#ifdef DS18B20_INTERNAL_PULLUP - pinMode(ds18x20_pin, INPUT_PULLUP); -#else - pinMode(ds18x20_pin, INPUT); -#endif - do { - if (--retries == 0) { - return 0; - } - delayMicroseconds(2); - } while (!digitalRead(ds18x20_pin)); - pinMode(ds18x20_pin, OUTPUT); - digitalWrite(ds18x20_pin, LOW); - delayMicroseconds(480); -#ifdef DS18B20_INTERNAL_PULLUP - pinMode(ds18x20_pin, INPUT_PULLUP); -#else - pinMode(ds18x20_pin, INPUT); -#endif - delayMicroseconds(70); - uint8_t r = !digitalRead(ds18x20_pin); - - delayMicroseconds(410); - return r; -} - -void OneWireWriteBit(uint8_t v) -{ - static const uint8_t delay_low[2] = { 65, 10 }; - static const uint8_t delay_high[2] = { 5, 55 }; - - v &= 1; - - digitalWrite(ds18x20_pin, LOW); - pinMode(ds18x20_pin, OUTPUT); - delayMicroseconds(delay_low[v]); - digitalWrite(ds18x20_pin, HIGH); - - delayMicroseconds(delay_high[v]); -} - -uint8_t OneWireReadBit(void) -{ - - pinMode(ds18x20_pin, OUTPUT); - digitalWrite(ds18x20_pin, LOW); - delayMicroseconds(3); -#ifdef DS18B20_INTERNAL_PULLUP - pinMode(ds18x20_pin, INPUT_PULLUP); -#else - pinMode(ds18x20_pin, INPUT); -#endif - delayMicroseconds(10); - uint8_t r = digitalRead(ds18x20_pin); - - delayMicroseconds(53); - return r; -} - -void OneWireWrite(uint8_t v) -{ - for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { - OneWireWriteBit((bit_mask & v) ? 1 : 0); - } -} - -uint8_t OneWireRead(void) -{ - uint8_t r = 0; - - for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { - if (OneWireReadBit()) { - r |= bit_mask; - } - } - return r; -} - -bool OneWireCrc8(uint8_t *addr) -{ - uint8_t crc = 0; - uint8_t len = 8; - - while (len--) { - uint8_t inbyte = *addr++; - for (uint32_t i = 8; i; i--) { - uint8_t mix = (crc ^ inbyte) & 0x01; - crc >>= 1; - if (mix) { - crc ^= 0x8C; - } - inbyte >>= 1; - } - } - return (crc == *addr); -} - - - -void Ds18b20Convert(void) -{ - OneWireReset(); - OneWireWrite(W1_SKIP_ROM); - OneWireWrite(W1_CONVERT_TEMP); - -} - -bool Ds18b20Read(void) -{ - uint8_t data[9]; - int8_t sign = 1; - - if (ds18b20_valid) { ds18b20_valid--; } - - - - - - - for (uint32_t retry = 0; retry < 3; retry++) { - OneWireReset(); - OneWireWrite(W1_SKIP_ROM); - OneWireWrite(W1_READ_SCRATCHPAD); - for (uint32_t i = 0; i < 9; i++) { - data[i] = OneWireRead(); - } - if (OneWireCrc8(data)) { - uint16_t temp12 = (data[1] << 8) + data[0]; - if (temp12 > 2047) { - temp12 = (~temp12) +1; - sign = -1; - } - ds18b20_temperature = ConvertTemp(sign * temp12 * 0.0625); - ds18b20_valid = SENSOR_MAX_MISS; - return true; - } - } - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); - return false; -} - - - -void Ds18b20EverySecond(void) -{ - ds18x20_pin = pin[GPIO_DSB]; - if (uptime &1) { - - Ds18b20Convert(); - } else { - - if (!Ds18b20Read()) { - AddLogMissed(ds18b20_types, ds18b20_valid); - } - } -} - -void Ds18b20Show(bool json) -{ - if (ds18b20_valid) { - char temperature[33]; - dtostrfd(ds18b20_temperature, Settings.flag2.temperature_resolution, temperature); - if(json) { - ResponseAppend_P(JSON_SNS_TEMP, ds18b20_types, temperature); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, ds18b20_temperature); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, ds18b20_types, temperature, TempUnit()); -#endif - } - } -} - - - - - -bool Xsns05(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_DSB] < 99) { - switch (function) { - case FUNC_EVERY_SECOND: - Ds18b20EverySecond(); - break; - case FUNC_JSON_APPEND: - Ds18b20Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ds18b20Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_05_ds18x20.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_05_ds18x20.ino" -#ifdef USE_DS18x20 - - - - -#define XSNS_05 5 - - - -#define DS18S20_CHIPID 0x10 -#define DS1822_CHIPID 0x22 -#define DS18B20_CHIPID 0x28 -#define MAX31850_CHIPID 0x3B - -#define W1_SKIP_ROM 0xCC -#define W1_CONVERT_TEMP 0x44 -#define W1_WRITE_EEPROM 0x48 -#define W1_WRITE_SCRATCHPAD 0x4E -#define W1_READ_SCRATCHPAD 0xBE - -#define DS18X20_MAX_SENSORS 8 - -const char kDs18x20Types[] PROGMEM = "DS18x20|DS18S20|DS1822|DS18B20|MAX31850"; - -uint8_t ds18x20_chipids[] = { 0, DS18S20_CHIPID, DS1822_CHIPID, DS18B20_CHIPID, MAX31850_CHIPID }; - -struct DS18X20STRUCT { - uint8_t address[8]; - uint8_t index; - uint8_t valid; - float temperature; -} ds18x20_sensor[DS18X20_MAX_SENSORS]; -uint8_t ds18x20_sensors = 0; -uint8_t ds18x20_pin = 0; -char ds18x20_types[12]; -#ifdef W1_PARASITE_POWER -uint8_t ds18x20_sensor_curr = 0; -unsigned long w1_power_until = 0; -#endif - - - - - -#define W1_MATCH_ROM 0x55 -#define W1_SEARCH_ROM 0xF0 - -uint8_t onewire_last_discrepancy = 0; -uint8_t onewire_last_family_discrepancy = 0; -bool onewire_last_device_flag = false; -unsigned char onewire_rom_id[8] = { 0 }; - -uint8_t OneWireReset(void) -{ - uint8_t retries = 125; - - - pinMode(ds18x20_pin, INPUT); - do { - if (--retries == 0) { - return 0; - } - delayMicroseconds(2); - } while (!digitalRead(ds18x20_pin)); - pinMode(ds18x20_pin, OUTPUT); - digitalWrite(ds18x20_pin, LOW); - delayMicroseconds(480); - pinMode(ds18x20_pin, INPUT); - delayMicroseconds(70); - uint8_t r = !digitalRead(ds18x20_pin); - - delayMicroseconds(410); - return r; -} - -void OneWireWriteBit(uint8_t v) -{ - static const uint8_t delay_low[2] = { 65, 10 }; - static const uint8_t delay_high[2] = { 5, 55 }; - - v &= 1; - - digitalWrite(ds18x20_pin, LOW); - pinMode(ds18x20_pin, OUTPUT); - delayMicroseconds(delay_low[v]); - digitalWrite(ds18x20_pin, HIGH); - - delayMicroseconds(delay_high[v]); -} - -uint8_t OneWireReadBit(void) -{ - - pinMode(ds18x20_pin, OUTPUT); - digitalWrite(ds18x20_pin, LOW); - delayMicroseconds(3); - pinMode(ds18x20_pin, INPUT); - delayMicroseconds(10); - uint8_t r = digitalRead(ds18x20_pin); - - delayMicroseconds(53); - return r; -} - -void OneWireWrite(uint8_t v) -{ - for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { - OneWireWriteBit((bit_mask & v) ? 1 : 0); - } -} - -uint8_t OneWireRead(void) -{ - uint8_t r = 0; - - for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { - if (OneWireReadBit()) { - r |= bit_mask; - } - } - return r; -} - -void OneWireSelect(const uint8_t rom[8]) -{ - OneWireWrite(W1_MATCH_ROM); - for (uint32_t i = 0; i < 8; i++) { - OneWireWrite(rom[i]); - } -} - -void OneWireResetSearch(void) -{ - onewire_last_discrepancy = 0; - onewire_last_device_flag = false; - onewire_last_family_discrepancy = 0; - for (uint32_t i = 0; i < 8; i++) { - onewire_rom_id[i] = 0; - } -} - -uint8_t OneWireSearch(uint8_t *newAddr) -{ - uint8_t id_bit_number = 1; - uint8_t last_zero = 0; - uint8_t rom_byte_number = 0; - uint8_t search_result = 0; - uint8_t id_bit; - uint8_t cmp_id_bit; - unsigned char rom_byte_mask = 1; - unsigned char search_direction; - - if (!onewire_last_device_flag) { - if (!OneWireReset()) { - onewire_last_discrepancy = 0; - onewire_last_device_flag = false; - onewire_last_family_discrepancy = 0; - return false; - } - OneWireWrite(W1_SEARCH_ROM); - do { - id_bit = OneWireReadBit(); - cmp_id_bit = OneWireReadBit(); - - if ((id_bit == 1) && (cmp_id_bit == 1)) { - break; - } else { - if (id_bit != cmp_id_bit) { - search_direction = id_bit; - } else { - if (id_bit_number < onewire_last_discrepancy) { - search_direction = ((onewire_rom_id[rom_byte_number] & rom_byte_mask) > 0); - } else { - search_direction = (id_bit_number == onewire_last_discrepancy); - } - if (search_direction == 0) { - last_zero = id_bit_number; - if (last_zero < 9) { - onewire_last_family_discrepancy = last_zero; - } - } - } - if (search_direction == 1) { - onewire_rom_id[rom_byte_number] |= rom_byte_mask; - } else { - onewire_rom_id[rom_byte_number] &= ~rom_byte_mask; - } - OneWireWriteBit(search_direction); - id_bit_number++; - rom_byte_mask <<= 1; - if (rom_byte_mask == 0) { - rom_byte_number++; - rom_byte_mask = 1; - } - } - } while (rom_byte_number < 8); - if (!(id_bit_number < 65)) { - onewire_last_discrepancy = last_zero; - if (onewire_last_discrepancy == 0) { - onewire_last_device_flag = true; - } - search_result = true; - } - } - if (!search_result || !onewire_rom_id[0]) { - onewire_last_discrepancy = 0; - onewire_last_device_flag = false; - onewire_last_family_discrepancy = 0; - search_result = false; - } - for (uint32_t i = 0; i < 8; i++) { - newAddr[i] = onewire_rom_id[i]; - } - return search_result; -} - -bool OneWireCrc8(uint8_t *addr) -{ - uint8_t crc = 0; - uint8_t len = 8; - - while (len--) { - uint8_t inbyte = *addr++; - for (uint32_t i = 8; i; i--) { - uint8_t mix = (crc ^ inbyte) & 0x01; - crc >>= 1; - if (mix) { - crc ^= 0x8C; - } - inbyte >>= 1; - } - } - return (crc == *addr); -} - - - -void Ds18x20Init(void) -{ - uint64_t ids[DS18X20_MAX_SENSORS]; - - ds18x20_pin = pin[GPIO_DSB]; - - OneWireResetSearch(); - - ds18x20_sensors = 0; - while (ds18x20_sensors < DS18X20_MAX_SENSORS) { - if (!OneWireSearch(ds18x20_sensor[ds18x20_sensors].address)) { - break; - } - if (OneWireCrc8(ds18x20_sensor[ds18x20_sensors].address) && - ((ds18x20_sensor[ds18x20_sensors].address[0] == DS18S20_CHIPID) || - (ds18x20_sensor[ds18x20_sensors].address[0] == DS1822_CHIPID) || - (ds18x20_sensor[ds18x20_sensors].address[0] == DS18B20_CHIPID) || - (ds18x20_sensor[ds18x20_sensors].address[0] == MAX31850_CHIPID))) { - ds18x20_sensor[ds18x20_sensors].index = ds18x20_sensors; - ids[ds18x20_sensors] = ds18x20_sensor[ds18x20_sensors].address[0]; - for (uint32_t j = 6; j > 0; j--) { - ids[ds18x20_sensors] = ids[ds18x20_sensors] << 8 | ds18x20_sensor[ds18x20_sensors].address[j]; - } - ds18x20_sensors++; - } - } - for (uint32_t i = 0; i < ds18x20_sensors; i++) { - for (uint32_t j = i + 1; j < ds18x20_sensors; j++) { - if (ids[ds18x20_sensor[i].index] > ids[ds18x20_sensor[j].index]) { - std::swap(ds18x20_sensor[i].index, ds18x20_sensor[j].index); - } - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSORS_FOUND " %d"), ds18x20_sensors); -} - -void Ds18x20Convert(void) -{ - OneWireReset(); -#ifdef W1_PARASITE_POWER - - if (++ds18x20_sensor_curr >= ds18x20_sensors) - ds18x20_sensor_curr = 0; - OneWireSelect(ds18x20_sensor[ds18x20_sensor_curr].address); -#else - OneWireWrite(W1_SKIP_ROM); -#endif - OneWireWrite(W1_CONVERT_TEMP); - -} - -bool Ds18x20Read(uint8_t sensor) -{ - uint8_t data[9]; - int8_t sign = 1; - - uint8_t index = ds18x20_sensor[sensor].index; - if (ds18x20_sensor[index].valid) { ds18x20_sensor[index].valid--; } - for (uint32_t retry = 0; retry < 3; retry++) { - OneWireReset(); - OneWireSelect(ds18x20_sensor[index].address); - OneWireWrite(W1_READ_SCRATCHPAD); - for (uint32_t i = 0; i < 9; i++) { - data[i] = OneWireRead(); - } - if (OneWireCrc8(data)) { - switch(ds18x20_sensor[index].address[0]) { - case DS18S20_CHIPID: { - if (data[1] > 0x80) { - data[0] = (~data[0]) +1; - sign = -1; - } - float temp9 = (float)(data[0] >> 1) * sign; - ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); - ds18x20_sensor[index].valid = SENSOR_MAX_MISS; - return true; - } - case DS1822_CHIPID: - case DS18B20_CHIPID: { - if (data[4] != 0x7F) { - data[4] = 0x7F; - OneWireReset(); - OneWireSelect(ds18x20_sensor[index].address); - OneWireWrite(W1_WRITE_SCRATCHPAD); - OneWireWrite(data[2]); - OneWireWrite(data[3]); - OneWireWrite(data[4]); - OneWireSelect(ds18x20_sensor[index].address); - OneWireWrite(W1_WRITE_EEPROM); -#ifdef W1_PARASITE_POWER - w1_power_until = millis() + 10; -#endif - } - uint16_t temp12 = (data[1] << 8) + data[0]; - if (temp12 > 2047) { - temp12 = (~temp12) +1; - sign = -1; - } - ds18x20_sensor[index].temperature = ConvertTemp(sign * temp12 * 0.0625); - ds18x20_sensor[index].valid = SENSOR_MAX_MISS; - return true; - } - case MAX31850_CHIPID: { - int16_t temp14 = (data[1] << 8) + (data[0] & 0xFC); - ds18x20_sensor[index].temperature = ConvertTemp(temp14 * 0.0625); - ds18x20_sensor[index].valid = SENSOR_MAX_MISS; - return true; - } - } - } - } - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); - return false; -} - -void Ds18x20Name(uint8_t sensor) -{ - uint8_t index = sizeof(ds18x20_chipids); - while (index) { - if (ds18x20_sensor[ds18x20_sensor[sensor].index].address[0] == ds18x20_chipids[index]) { - break; - } - index--; - } - GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), index, kDs18x20Types); - if (ds18x20_sensors > 1) { - snprintf_P(ds18x20_types, sizeof(ds18x20_types), PSTR("%s%c%d"), ds18x20_types, IndexSeparator(), sensor +1); - } -} - - - -void Ds18x20EverySecond(void) -{ -#ifdef W1_PARASITE_POWER - - unsigned long now = millis(); - if (now < w1_power_until) - return; -#endif - if (uptime & 1 -#ifdef W1_PARASITE_POWER - - || ds18x20_sensors >= 2 -#endif - ) { - - Ds18x20Convert(); - } else { - for (uint32_t i = 0; i < ds18x20_sensors; i++) { - - if (!Ds18x20Read(i)) { - Ds18x20Name(i); - AddLogMissed(ds18x20_types, ds18x20_sensor[ds18x20_sensor[i].index].valid); -#ifdef USE_DS18x20_RECONFIGURE - if (!ds18x20_sensor[ds18x20_sensor[i].index].valid) { - memset(&ds18x20_sensor, 0, sizeof(ds18x20_sensor)); - Ds18x20Init(); - } -#endif - } - } - } -} - -void Ds18x20Show(bool json) -{ - for (uint32_t i = 0; i < ds18x20_sensors; i++) { - uint8_t index = ds18x20_sensor[i].index; - - if (ds18x20_sensor[index].valid) { - char temperature[33]; - dtostrfd(ds18x20_sensor[index].temperature, Settings.flag2.temperature_resolution, temperature); - - Ds18x20Name(i); - - if (json) { - if (1 == ds18x20_sensors) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, temperature); - } else { - char address[17]; - for (uint32_t j = 0; j < 6; j++) { - sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); - } - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); - } -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, ds18x20_sensor[index].temperature); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, ds18x20_types, temperature, TempUnit()); -#endif - } - } - } -} - - - - - -bool Xsns05(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_DSB] < 99) { - switch (function) { - case FUNC_INIT: - Ds18x20Init(); - break; - case FUNC_EVERY_SECOND: - Ds18x20EverySecond(); - break; - case FUNC_JSON_APPEND: - Ds18x20Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ds18x20Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_05_ds18x20_legacy.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_05_ds18x20_legacy.ino" -#ifdef USE_DS18x20_LEGACY - - - - -#define XSNS_05 5 - -#define DS18S20_CHIPID 0x10 -#define DS18B20_CHIPID 0x28 -#define MAX31850_CHIPID 0x3B - -#define W1_SKIP_ROM 0xCC -#define W1_CONVERT_TEMP 0x44 -#define W1_READ_SCRATCHPAD 0xBE - -#define DS18X20_MAX_SENSORS 8 - -#include - -OneWire *ds = nullptr; - -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 Ds18x20Init(void) -{ - ds = new OneWire(pin[GPIO_DSB]); -} - -void Ds18x20Search(void) -{ - uint8_t num_sensors=0; - uint8_t sensor = 0; - - ds->reset_search(); - for (num_sensors = 0; num_sensors < DS18X20_MAX_SENSORS; num_sensors) { - if (!ds->search(ds18x20_address[num_sensors])) { - ds->reset_search(); - break; - } - - 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 (uint32_t i = 0; i < num_sensors; i++) { - ds18x20_index[i] = i; - } - for (uint32_t i = 0; i < num_sensors; i++) { - for (uint32_t 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_sensors = num_sensors; -} - -uint8_t Ds18x20Sensors(void) -{ - return ds18x20_sensors; -} - -String Ds18x20Addresses(uint8_t sensor) -{ - char address[20]; - - for (uint32_t i = 0; i < 8; i++) { - sprintf(address+2*i, "%02X", ds18x20_address[ds18x20_index[sensor]][i]); - } - return String(address); -} - -void Ds18x20Convert(void) -{ - ds->reset(); - ds->write(W1_SKIP_ROM); - ds->write(W1_CONVERT_TEMP); - -} - -bool Ds18x20Read(uint8_t sensor, float &t) -{ - uint8_t data[12]; - int8_t sign = 1; - uint16_t temp12 = 0; - int16_t temp14 = 0; - float temp9 = 0.0; - uint8_t present = 0; - - t = NAN; - - ds->reset(); - ds->select(ds18x20_address[ds18x20_index[sensor]]); - ds->write(W1_READ_SCRATCHPAD); - - for (uint32_t i = 0; i < 9; i++) { - data[i] = ds->read(); - } - if (OneWire::crc8(data, 8) == data[8]) { - switch(ds18x20_address[ds18x20_index[sensor]][0]) { - case DS18S20_CHIPID: - if (data[1] > 0x80) { - data[0] = (~data[0]) +1; - sign = -1; - } - temp9 = (float)(data[0] >> 1) * sign; - t = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); - break; - case DS18B20_CHIPID: - temp12 = (data[1] << 8) + data[0]; - if (temp12 > 2047) { - temp12 = (~temp12) +1; - sign = -1; - } - t = ConvertTemp(sign * temp12 * 0.0625); - break; - case MAX31850_CHIPID: - temp14 = (data[1] << 8) + (data[0] & 0xFC); - t = ConvertTemp(temp14 * 0.0625); - break; - } - } - return (!isnan(t)); -} - - - -void Ds18x20Type(uint8_t sensor) -{ - strcpy_P(ds18x20_types, PSTR("DS18x20")); - switch(ds18x20_address[ds18x20_index[sensor]][0]) { - case DS18S20_CHIPID: - strcpy_P(ds18x20_types, PSTR("DS18S20")); - break; - case DS18B20_CHIPID: - strcpy_P(ds18x20_types, PSTR("DS18B20")); - break; - case MAX31850_CHIPID: - strcpy_P(ds18x20_types, PSTR("MAX31850")); - break; - } -} - -void Ds18x20Show(bool json) -{ - char stemp[10]; - float t; - - uint8_t dsxflg = 0; - for (uint32_t i = 0; i < Ds18x20Sensors(); i++) { - if (Ds18x20Read(i, t)) { - Ds18x20Type(i); - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - - if (json) { - if (!dsxflg) { - ResponseAppend_P(PSTR(",\"DS18x20\":{")); - stemp[0] = '\0'; - } - dsxflg++; - ResponseAppend_P(PSTR("%s\"DS%d\":{\"" D_JSON_TYPE "\":\"%s\",\"" D_JSON_ADDRESS "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), - stemp, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), temperature); - strlcpy(stemp, ",", sizeof(stemp)); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (1 == dsxflg)) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (1 == dsxflg)) { - KnxSensor(KNX_TEMPERATURE, t); - } -#endif -#ifdef USE_WEBSERVER - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("%s%c%d"), ds18x20_types, IndexSeparator(), i +1); - WSContentSend_PD(HTTP_SNS_TEMP, stemp, temperature, TempUnit()); -#endif - } - } - } - if (json) { - if (dsxflg) { - ResponseJsonEnd(); - } - } - Ds18x20Search(); - Ds18x20Convert(); -} - - - - - -bool Xsns05(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_DSB] < 99) { - switch (function) { - case FUNC_INIT: - Ds18x20Init(); - break; - case FUNC_PREP_BEFORE_TELEPERIOD: - Ds18x20Search(); - Ds18x20Convert(); - break; - case FUNC_JSON_APPEND: - Ds18x20Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ds18x20Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_06_dht.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_06_dht.ino" -#ifdef USE_DHT -# 29 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_06_dht.ino" -#define XSNS_06 6 - -#define DHT_MAX_SENSORS 3 -#define DHT_MAX_RETRY 8 - -uint32_t dht_max_cycles; -uint8_t dht_data[5]; -uint8_t dht_sensors = 0; -bool dht_active = true; - -struct DHTSTRUCT { - uint8_t pin; - uint8_t type; - char stype[12]; - uint32_t lastreadtime; - uint8_t lastresult; - float t = NAN; - float h = NAN; -} Dht[DHT_MAX_SENSORS]; - -void DhtReadPrep(void) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - digitalWrite(Dht[i].pin, HIGH); - } -} - -int32_t DhtExpectPulse(uint8_t sensor, bool level) -{ - int32_t count = 0; - - while (digitalRead(Dht[sensor].pin) == level) { - if (count++ >= (int32_t)dht_max_cycles) { - return -1; - } - } - return count; -} - -bool DhtRead(uint8_t sensor) -{ - int32_t cycles[80]; - uint8_t error = 0; - - dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; - - - - - if (Dht[sensor].lastresult > DHT_MAX_RETRY) { - Dht[sensor].lastresult = 0; - digitalWrite(Dht[sensor].pin, HIGH); - delay(250); - } - pinMode(Dht[sensor].pin, OUTPUT); - digitalWrite(Dht[sensor].pin, LOW); - - if (GPIO_SI7021 == Dht[sensor].type) { - delayMicroseconds(500); - } else { - delay(20); - } - - noInterrupts(); - digitalWrite(Dht[sensor].pin, HIGH); - delayMicroseconds(40); - pinMode(Dht[sensor].pin, INPUT_PULLUP); - delayMicroseconds(10); - if (-1 == DhtExpectPulse(sensor, LOW)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); - error = 1; - } - else if (-1 == DhtExpectPulse(sensor, HIGH)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); - error = 1; - } - else { - for (uint32_t i = 0; i < 80; i += 2) { - cycles[i] = DhtExpectPulse(sensor, LOW); - cycles[i+1] = DhtExpectPulse(sensor, HIGH); - } - } - interrupts(); - if (error) { return false; } - - for (uint32_t i = 0; i < 40; ++i) { - int32_t lowCycles = cycles[2*i]; - int32_t highCycles = cycles[2*i+1]; - if ((-1 == lowCycles) || (-1 == highCycles)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); - return false; - } - dht_data[i/8] <<= 1; - if (highCycles > lowCycles) { - dht_data[i / 8] |= 1; - } - } - - uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; - if (dht_data[4] != checksum) { - char hex_char[15]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), - ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); - return false; - } - - return true; -} - -void DhtReadTempHum(uint8_t sensor) -{ - if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - if (DhtRead(sensor)) { - switch (Dht[sensor].type) { - case GPIO_DHT11: - Dht[sensor].h = dht_data[0]; - Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); - break; - case GPIO_DHT22: - case GPIO_SI7021: - Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; - if (dht_data[2] & 0x80) { - Dht[sensor].t *= -1; - } - break; - } - Dht[sensor].t = ConvertTemp(Dht[sensor].t); - Dht[sensor].h = ConvertHumidity(Dht[sensor].h); - Dht[sensor].lastresult = 0; - } else { - Dht[sensor].lastresult++; - } -} - - - -bool DhtPinState() -{ - if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { - if (dht_sensors < DHT_MAX_SENSORS) { - Dht[dht_sensors].pin = XdrvMailbox.payload; - Dht[dht_sensors].type = XdrvMailbox.index; - dht_sensors++; - XdrvMailbox.index = GPIO_DHT11; - } else { - XdrvMailbox.index = 0; - } - return true; - } - return false; -} - -void DhtInit(void) -{ - if (dht_sensors) { - dht_max_cycles = microsecondsToClockCycles(1000); - - for (uint32_t i = 0; i < dht_sensors; i++) { - pinMode(Dht[i].pin, INPUT_PULLUP); - Dht[i].lastreadtime = 0; - Dht[i].lastresult = 0; - GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); - if (dht_sensors > 1) { - snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); - } - } - } else { - dht_active = false; - } -} - -void DhtEverySecond(void) -{ - if (uptime &1) { - - DhtReadPrep(); - } else { - for (uint32_t i = 0; i < dht_sensors; i++) { - - DhtReadTempHum(i); - } - } -} - -void DhtShow(bool json) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - char temperature[33]; - dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, Dht[i].t); - KnxSensor(KNX_HUMIDITY, Dht[i].h); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); -#endif - } - } -} - - - - - -bool Xsns06(uint8_t function) -{ - bool result = false; - - if (dht_active) { - switch (function) { - case FUNC_EVERY_SECOND: - DhtEverySecond(); - break; - case FUNC_JSON_APPEND: - DhtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DhtShow(0); - break; -#endif - case FUNC_INIT: - DhtInit(); - break; - case FUNC_PIN_STATE: - result = DhtPinState(); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_07_sht1x.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_07_sht1x.ino" -#ifdef USE_I2C -#ifdef USE_SHT -# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_07_sht1x.ino" -#define XSNS_07 7 - -enum { - SHT1X_CMD_MEASURE_TEMP = B00000011, - SHT1X_CMD_MEASURE_RH = B00000101, - SHT1X_CMD_SOFT_RESET = B00011110 -}; - -uint8_t sht_sda_pin; -uint8_t sht_scl_pin; -uint8_t sht_type = 0; -char sht_types[] = "SHT1X"; -uint8_t sht_valid = 0; -float sht_temperature = 0; -float sht_humidity = 0; - -bool ShtReset(void) -{ - pinMode(sht_sda_pin, INPUT_PULLUP); - pinMode(sht_scl_pin, OUTPUT); - delay(11); - for (uint32_t i = 0; i < 9; i++) { - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_scl_pin, LOW); - } - bool success = ShtSendCommand(SHT1X_CMD_SOFT_RESET); - delay(11); - return success; -} - -bool ShtSendCommand(const uint8_t cmd) -{ - pinMode(sht_sda_pin, OUTPUT); - - digitalWrite(sht_sda_pin, HIGH); - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_sda_pin, LOW); - digitalWrite(sht_scl_pin, LOW); - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_sda_pin, HIGH); - digitalWrite(sht_scl_pin, LOW); - - shiftOut(sht_sda_pin, sht_scl_pin, MSBFIRST, cmd); - - bool ackerror = false; - digitalWrite(sht_scl_pin, HIGH); - pinMode(sht_sda_pin, INPUT_PULLUP); - if (digitalRead(sht_sda_pin) != LOW) { - ackerror = true; - } - digitalWrite(sht_scl_pin, LOW); - delayMicroseconds(1); - if (digitalRead(sht_sda_pin) != HIGH) { - ackerror = true; - } - if (ackerror) { - sht_type = 0; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_DID_NOT_ACK_COMMAND)); - } - return (!ackerror); -} - -bool ShtAwaitResult(void) -{ - - for (uint32_t i = 0; i < 16; i++) { - if (LOW == digitalRead(sht_sda_pin)) { - return true; - } - delay(20); - } - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_BUSY)); - sht_type = 0; - return false; -} - -int ShtReadData(void) -{ - int val = 0; - - - val = shiftIn(sht_sda_pin, sht_scl_pin, 8); - val <<= 8; - - pinMode(sht_sda_pin, OUTPUT); - digitalWrite(sht_sda_pin, LOW); - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_scl_pin, LOW); - pinMode(sht_sda_pin, INPUT_PULLUP); - - val |= shiftIn(sht_sda_pin, sht_scl_pin, 8); - - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_scl_pin, LOW); - return val; -} - -bool ShtRead(void) -{ - if (sht_valid) { sht_valid--; } - if (!ShtReset()) { return false; } - if (!ShtSendCommand(SHT1X_CMD_MEASURE_TEMP)) { return false; } - if (!ShtAwaitResult()) { return false; } - float tempRaw = ShtReadData(); - if (!ShtSendCommand(SHT1X_CMD_MEASURE_RH)) { return false; } - if (!ShtAwaitResult()) { return false; } - float humRaw = ShtReadData(); - - - const float d1 = -39.7; - const float d2 = 0.01; - sht_temperature = d1 + (tempRaw * d2); - const float c1 = -2.0468; - const float c2 = 0.0367; - const float c3 = -1.5955E-6; - const float t1 = 0.01; - const float t2 = 0.00008; - float rhLinear = c1 + c2 * humRaw + c3 * humRaw * humRaw; - sht_humidity = (sht_temperature - 25) * (t1 + t2 * humRaw) + rhLinear; - sht_temperature = ConvertTemp(sht_temperature); - ConvertHumidity(sht_humidity); - - sht_valid = SENSOR_MAX_MISS; - return true; -} - - - -void ShtDetect(void) -{ - if (sht_type) { - return; - } - - sht_sda_pin = pin[GPIO_I2C_SDA]; - sht_scl_pin = pin[GPIO_I2C_SCL]; - if (ShtRead()) { - sht_type = 1; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C D_SHT1X_FOUND)); - } else { - Wire.begin(sht_sda_pin, sht_scl_pin); - sht_type = 0; - } -} - -void ShtEverySecond(void) -{ - if (sht_type && !(uptime %4)) { - - if (!ShtRead()) { - AddLogMissed(sht_types, sht_valid); - - } - } -} - -void ShtShow(bool json) -{ - if (sht_valid) { - char temperature[33]; - dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, sht_types, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, sht_temperature); - KnxSensor(KNX_HUMIDITY, sht_humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, sht_types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, sht_types, humidity); -#endif - } - } -} - - - - - -bool Xsns07(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - - case FUNC_INIT: - ShtDetect(); - break; - case FUNC_EVERY_SECOND: - ShtEverySecond(); - break; - case FUNC_JSON_APPEND: - ShtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - ShtShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_08_htu21.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_08_htu21.ino" -#ifdef USE_I2C -#ifdef USE_HTU -# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_08_htu21.ino" -#define XSNS_08 8 - -#define HTU21_ADDR 0x40 - -#define SI7013_CHIPID 0x0D -#define SI7020_CHIPID 0x14 -#define SI7021_CHIPID 0x15 -#define HTU21_CHIPID 0x32 - -#define HTU21_READTEMP 0xE3 -#define HTU21_READHUM 0xE5 -#define HTU21_WRITEREG 0xE6 -#define HTU21_READREG 0xE7 -#define HTU21_RESET 0xFE -#define HTU21_HEATER_WRITE 0x51 -#define HTU21_HEATER_READ 0x11 -#define HTU21_SERIAL2_READ1 0xFC -#define HTU21_SERIAL2_READ2 0xC9 - -#define HTU21_HEATER_ON 0x04 -#define HTU21_HEATER_OFF 0xFB - -#define HTU21_RES_RH12_T14 0x00 -#define HTU21_RES_RH8_T12 0x01 -#define HTU21_RES_RH10_T13 0x80 -#define HTU21_RES_RH11_T11 0x81 - -#define HTU21_CRC8_POLYNOM 0x13100 - -const char kHtuTypes[] PROGMEM = "HTU21|SI7013|SI7020|SI7021|T/RH?"; - -uint8_t htu_address; -uint8_t htu_type = 0; -uint8_t htu_delay_temp; -uint8_t htu_delay_humidity = 50; -uint8_t htu_valid = 0; -float htu_temperature = 0; -float htu_humidity = 0; -char htu_types[7]; - -uint8_t HtuCheckCrc8(uint16_t data) -{ - for (uint32_t bit = 0; bit < 16; bit++) { - if (data & 0x8000) { - data = (data << 1) ^ HTU21_CRC8_POLYNOM; - } else { - data <<= 1; - } - } - return data >>= 8; -} - -uint8_t HtuReadDeviceId(void) -{ - uint16_t deviceID = 0; - uint8_t checksum = 0; - - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_SERIAL2_READ1); - Wire.write(HTU21_SERIAL2_READ2); - Wire.endTransmission(); - - Wire.requestFrom(HTU21_ADDR, 3); - deviceID = Wire.read() << 8; - deviceID |= Wire.read(); - checksum = Wire.read(); - if (HtuCheckCrc8(deviceID) == checksum) { - deviceID = deviceID >> 8; - } else { - deviceID = 0; - } - return (uint8_t)deviceID; -} - -void HtuSetResolution(uint8_t resolution) -{ - uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); - current &= 0x7E; - current |= resolution; - I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); -} - -void HtuReset(void) -{ - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_RESET); - Wire.endTransmission(); - delay(15); -} - -void HtuHeater(uint8_t heater) -{ - uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); - - switch(heater) - { - case HTU21_HEATER_ON : current |= heater; - break; - case HTU21_HEATER_OFF : current &= heater; - break; - default : current &= heater; - break; - } - I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); -} - -void HtuInit(void) -{ - HtuReset(); - HtuHeater(HTU21_HEATER_OFF); - HtuSetResolution(HTU21_RES_RH12_T14); -} - -bool HtuRead(void) -{ - uint8_t checksum = 0; - uint16_t sensorval = 0; - - if (htu_valid) { htu_valid--; } - - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_READTEMP); - if (Wire.endTransmission() != 0) { return false; } - delay(htu_delay_temp); - - Wire.requestFrom(HTU21_ADDR, 3); - if (3 == Wire.available()) { - sensorval = Wire.read() << 8; - sensorval |= Wire.read(); - checksum = Wire.read(); - } - if (HtuCheckCrc8(sensorval) != checksum) { return false; } - - htu_temperature = ConvertTemp(0.002681 * (float)sensorval - 46.85); - - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_READHUM); - if (Wire.endTransmission() != 0) { return false; } - delay(htu_delay_humidity); - - Wire.requestFrom(HTU21_ADDR, 3); - if (3 <= Wire.available()) { - sensorval = Wire.read() << 8; - sensorval |= Wire.read(); - checksum = Wire.read(); - } - if (HtuCheckCrc8(sensorval) != checksum) { return false; } - - sensorval ^= 0x02; - htu_humidity = 0.001907 * (float)sensorval - 6; - if (htu_humidity > 100) { htu_humidity = 100.0; } - if (htu_humidity < 0) { htu_humidity = 0.01; } - - if ((0.00 == htu_humidity) && (0.00 == htu_temperature)) { - htu_humidity = 0.0; - } - if ((htu_temperature > 0.00) && (htu_temperature < 80.00)) { - htu_humidity = (-0.15) * (25 - htu_temperature) + htu_humidity; - } - ConvertHumidity(htu_humidity); - - htu_valid = SENSOR_MAX_MISS; - return true; -} - - - -void HtuDetect(void) -{ - if (htu_type) { return; } - - htu_address = HTU21_ADDR; - htu_type = HtuReadDeviceId(); - if (htu_type) { - uint8_t index = 0; - HtuInit(); - switch (htu_type) { - case HTU21_CHIPID: - htu_delay_temp = 50; - htu_delay_humidity = 16; - break; - case SI7021_CHIPID: - index++; - case SI7020_CHIPID: - index++; - case SI7013_CHIPID: - index++; - htu_delay_temp = 12; - htu_delay_humidity = 23; - break; - default: - index = 4; - htu_delay_temp = 50; - htu_delay_humidity = 23; - } - GetTextIndexed(htu_types, sizeof(htu_types), index, kHtuTypes); - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, htu_types, htu_address); - } -} - -void HtuEverySecond(void) -{ - if (92 == (uptime %100)) { - - HtuDetect(); - } - else if (uptime &1) { - - if (htu_type) { - if (!HtuRead()) { - AddLogMissed(htu_types, htu_valid); - - } - } - } -} - -void HtuShow(bool json) -{ - if (htu_valid) { - char temperature[33]; - dtostrfd(htu_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(htu_humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, htu_types, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, htu_temperature); - KnxSensor(KNX_HUMIDITY, htu_humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, htu_types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, htu_types, humidity); -#endif - } - } -} - - - - - -bool Xsns08(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - HtuDetect(); - break; - case FUNC_EVERY_SECOND: - HtuEverySecond(); - break; - case FUNC_JSON_APPEND: - HtuShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HtuShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_09_bmp.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_09_bmp.ino" -#ifdef USE_I2C -#ifdef USE_BMP -# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_09_bmp.ino" -#define XSNS_09 9 - -#define BMP_ADDR1 0x76 -#define BMP_ADDR2 0x77 - -#define BMP180_CHIPID 0x55 -#define BMP280_CHIPID 0x58 -#define BME280_CHIPID 0x60 -#define BME680_CHIPID 0x61 - -#define BMP_REGISTER_CHIPID 0xD0 - -#define BMP_MAX_SENSORS 2 - -const char kBmpTypes[] PROGMEM = "BMP180|BMP280|BME280|BME680"; - -typedef struct { - uint8_t bmp_address; - char bmp_name[7]; - uint8_t bmp_type; - uint8_t bmp_model; -#ifdef USE_BME680 - uint8_t bme680_state; - float bmp_gas_resistance; -#endif - float bmp_temperature; - float bmp_pressure; - float bmp_humidity; -} bmp_sensors_t; - -uint8_t bmp_addresses[] = { BMP_ADDR1, BMP_ADDR2 }; -uint8_t bmp_count = 0; -uint8_t bmp_once = 1; - -bmp_sensors_t *bmp_sensors = nullptr; - - - - - -#define BMP180_REG_CONTROL 0xF4 -#define BMP180_REG_RESULT 0xF6 -#define BMP180_TEMPERATURE 0x2E -#define BMP180_PRESSURE3 0xF4 - -#define BMP180_AC1 0xAA -#define BMP180_AC2 0xAC -#define BMP180_AC3 0xAE -#define BMP180_AC4 0xB0 -#define BMP180_AC5 0xB2 -#define BMP180_AC6 0xB4 -#define BMP180_VB1 0xB6 -#define BMP180_VB2 0xB8 -#define BMP180_MB 0xBA -#define BMP180_MC 0xBC -#define BMP180_MD 0xBE - -#define BMP180_OSS 3 - -typedef struct { - int16_t cal_ac1; - int16_t cal_ac2; - int16_t cal_ac3; - int16_t cal_b1; - int16_t cal_b2; - int16_t cal_mc; - int16_t cal_md; - uint16_t cal_ac4; - uint16_t cal_ac5; - uint16_t cal_ac6; -} bmp180_cal_data_t; - -bmp180_cal_data_t *bmp180_cal_data = nullptr; - -bool Bmp180Calibration(uint8_t bmp_idx) -{ - if (!bmp180_cal_data) { - bmp180_cal_data = (bmp180_cal_data_t*)malloc(BMP_MAX_SENSORS * sizeof(bmp180_cal_data_t)); - } - if (!bmp180_cal_data) { return false; } - - bmp180_cal_data[bmp_idx].cal_ac1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC1); - bmp180_cal_data[bmp_idx].cal_ac2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC2); - bmp180_cal_data[bmp_idx].cal_ac3 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC3); - bmp180_cal_data[bmp_idx].cal_ac4 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC4); - bmp180_cal_data[bmp_idx].cal_ac5 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC5); - bmp180_cal_data[bmp_idx].cal_ac6 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC6); - bmp180_cal_data[bmp_idx].cal_b1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB1); - bmp180_cal_data[bmp_idx].cal_b2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB2); - bmp180_cal_data[bmp_idx].cal_mc = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MC); - bmp180_cal_data[bmp_idx].cal_md = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MD); - - - if (!bmp180_cal_data[bmp_idx].cal_ac1 | - !bmp180_cal_data[bmp_idx].cal_ac2 | - !bmp180_cal_data[bmp_idx].cal_ac3 | - !bmp180_cal_data[bmp_idx].cal_ac4 | - !bmp180_cal_data[bmp_idx].cal_ac5 | - !bmp180_cal_data[bmp_idx].cal_ac6 | - !bmp180_cal_data[bmp_idx].cal_b1 | - !bmp180_cal_data[bmp_idx].cal_b2 | - !bmp180_cal_data[bmp_idx].cal_mc | - !bmp180_cal_data[bmp_idx].cal_md) { - return false; - } - - if ((bmp180_cal_data[bmp_idx].cal_ac1 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac2 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac3 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac4 == 0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac5 == 0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac6 == 0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_b1 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_b2 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_mc == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_md == (int16_t)0xFFFF)) { - return false; - } - return true; -} - -void Bmp180Read(uint8_t bmp_idx) -{ - if (!bmp180_cal_data) { return; } - - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_TEMPERATURE); - delay(5); - int ut = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); - int32_t xt1 = (ut - (int32_t)bmp180_cal_data[bmp_idx].cal_ac6) * ((int32_t)bmp180_cal_data[bmp_idx].cal_ac5) >> 15; - int32_t xt2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_mc << 11) / (xt1 + (int32_t)bmp180_cal_data[bmp_idx].cal_md); - int32_t bmp180_b5 = xt1 + xt2; - bmp_sensors[bmp_idx].bmp_temperature = ((bmp180_b5 + 8) >> 4) / 10.0; - - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_PRESSURE3); - delay(2 + (4 << BMP180_OSS)); - uint32_t up = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); - up >>= (8 - BMP180_OSS); - - int32_t b6 = bmp180_b5 - 4000; - int32_t x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b2 * ((b6 * b6) >> 12)) >> 11; - int32_t x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac2 * b6) >> 11; - int32_t x3 = x1 + x2; - int32_t b3 = ((((int32_t)bmp180_cal_data[bmp_idx].cal_ac1 * 4 + x3) << BMP180_OSS) + 2) >> 2; - - x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac3 * b6) >> 13; - x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b1 * ((b6 * b6) >> 12)) >> 16; - x3 = ((x1 + x2) + 2) >> 2; - uint32_t b4 = ((uint32_t)bmp180_cal_data[bmp_idx].cal_ac4 * (uint32_t)(x3 + 32768)) >> 15; - uint32_t b7 = ((uint32_t)up - b3) * (uint32_t)(50000UL >> BMP180_OSS); - - int32_t p; - if (b7 < 0x80000000) { - p = (b7 * 2) / b4; - } - else { - p = (b7 / b4) * 2; - } - x1 = (p >> 8) * (p >> 8); - x1 = (x1 * 3038) >> 16; - x2 = (-7357 * p) >> 16; - p += ((x1 + x2 + (int32_t)3791) >> 4); - bmp_sensors[bmp_idx].bmp_pressure = (float)p / 100.0; -} - - - - - - - -#define BME280_REGISTER_CONTROLHUMID 0xF2 -#define BME280_REGISTER_CONTROL 0xF4 -#define BME280_REGISTER_CONFIG 0xF5 -#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 - -typedef struct { - uint16_t dig_T1; - int16_t dig_T2; - int16_t dig_T3; - uint16_t dig_P1; - int16_t dig_P2; - int16_t dig_P3; - int16_t dig_P4; - int16_t dig_P5; - int16_t dig_P6; - int16_t dig_P7; - int16_t dig_P8; - int16_t dig_P9; - int16_t dig_H2; - int16_t dig_H4; - int16_t dig_H5; - uint8_t dig_H1; - uint8_t dig_H3; - int8_t dig_H6; -} Bme280CalibrationData_t; - -Bme280CalibrationData_t *Bme280CalibrationData = nullptr; - -bool Bmx280Calibrate(uint8_t bmp_idx) -{ - - - if (!Bme280CalibrationData) { - Bme280CalibrationData = (Bme280CalibrationData_t*)malloc(BMP_MAX_SENSORS * sizeof(Bme280CalibrationData_t)); - } - if (!Bme280CalibrationData) { return false; } - - Bme280CalibrationData[bmp_idx].dig_T1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T1); - Bme280CalibrationData[bmp_idx].dig_T2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T2); - Bme280CalibrationData[bmp_idx].dig_T3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T3); - Bme280CalibrationData[bmp_idx].dig_P1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P1); - Bme280CalibrationData[bmp_idx].dig_P2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P2); - Bme280CalibrationData[bmp_idx].dig_P3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P3); - Bme280CalibrationData[bmp_idx].dig_P4 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P4); - Bme280CalibrationData[bmp_idx].dig_P5 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P5); - Bme280CalibrationData[bmp_idx].dig_P6 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P6); - Bme280CalibrationData[bmp_idx].dig_P7 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P7); - Bme280CalibrationData[bmp_idx].dig_P8 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P8); - Bme280CalibrationData[bmp_idx].dig_P9 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P9); - if (BME280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { - Bme280CalibrationData[bmp_idx].dig_H1 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H1); - Bme280CalibrationData[bmp_idx].dig_H2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H2); - Bme280CalibrationData[bmp_idx].dig_H3 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H3); - Bme280CalibrationData[bmp_idx].dig_H4 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4 + 1) & 0xF); - Bme280CalibrationData[bmp_idx].dig_H5 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5 + 1) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5) >> 4); - Bme280CalibrationData[bmp_idx].dig_H6 = (int8_t)I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H6); - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x00); - - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROLHUMID, 0x01); - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONFIG, 0xA0); - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x27); - } else { - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0xB7); - } - - return true; -} - -void Bme280Read(uint8_t bmp_idx) -{ - if (!Bme280CalibrationData) { return; } - - int32_t adc_T = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_TEMPDATA); - adc_T >>= 4; - - int32_t vart1 = ((((adc_T >> 3) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1 << 1))) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_T2)) >> 11; - int32_t vart2 = (((((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1)) * ((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1))) >> 12) * - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T3)) >> 14; - int32_t t_fine = vart1 + vart2; - float T = (t_fine * 5 + 128) >> 8; - bmp_sensors[bmp_idx].bmp_temperature = T / 100.0; - - int32_t adc_P = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_PRESSUREDATA); - adc_P >>= 4; - - int64_t var1 = ((int64_t)t_fine) - 128000; - int64_t var2 = var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P6; - var2 = var2 + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P5) << 17); - var2 = var2 + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P4) << 35); - var1 = ((var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P3) >> 8) + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P2) << 12); - var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)Bme280CalibrationData[bmp_idx].dig_P1) >> 33; - if (0 == var1) { - return; - } - int64_t p = 1048576 - adc_P; - p = (((p << 31) - var2) * 3125) / var1; - var1 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P9) * (p >> 13) * (p >> 13)) >> 25; - var2 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P8) * p) >> 19; - p = ((p + var1 + var2) >> 8) + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P7) << 4); - bmp_sensors[bmp_idx].bmp_pressure = (float)p / 25600.0; - - if (BMP280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { return; } - - int32_t adc_H = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_HUMIDDATA); - - int32_t v_x1_u32r = (t_fine - ((int32_t)76800)); - v_x1_u32r = (((((adc_H << 14) - (((int32_t)Bme280CalibrationData[bmp_idx].dig_H4) << 20) - - (((int32_t)Bme280CalibrationData[bmp_idx].dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * - (((((((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H6)) >> 10) * - (((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + - ((int32_t)2097152)) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H2) + 8192) >> 14)); - v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * - ((int32_t)Bme280CalibrationData[bmp_idx].dig_H1)) >> 4)); - v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; - v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; - float h = (v_x1_u32r >> 12); - bmp_sensors[bmp_idx].bmp_humidity = h / 1024.0; -} - -#ifdef USE_BME680 - - - - -#include - -struct bme680_dev *gas_sensor = nullptr; - -static void BmeDelayMs(uint32_t ms) -{ - delay(ms); -} - -bool Bme680Init(uint8_t bmp_idx) -{ - if (!gas_sensor) { - gas_sensor = (bme680_dev*)malloc(BMP_MAX_SENSORS * sizeof(bme680_dev)); - } - if (!gas_sensor) { return false; } - - gas_sensor[bmp_idx].dev_id = bmp_sensors[bmp_idx].bmp_address; - gas_sensor[bmp_idx].intf = BME680_I2C_INTF; - gas_sensor[bmp_idx].read = &I2cReadBuffer; - gas_sensor[bmp_idx].write = &I2cWriteBuffer; - gas_sensor[bmp_idx].delay_ms = BmeDelayMs; - - - - gas_sensor[bmp_idx].amb_temp = 25; - - int8_t rslt = BME680_OK; - rslt = bme680_init(&gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return false; } - - - gas_sensor[bmp_idx].tph_sett.os_hum = BME680_OS_2X; - gas_sensor[bmp_idx].tph_sett.os_pres = BME680_OS_4X; - gas_sensor[bmp_idx].tph_sett.os_temp = BME680_OS_8X; - gas_sensor[bmp_idx].tph_sett.filter = BME680_FILTER_SIZE_3; - - - gas_sensor[bmp_idx].gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; - - gas_sensor[bmp_idx].gas_sett.heatr_temp = 320; - gas_sensor[bmp_idx].gas_sett.heatr_dur = 150; - - - - gas_sensor[bmp_idx].power_mode = BME680_FORCED_MODE; - - - uint8_t set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; - - - rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return false; } - - bmp_sensors[bmp_idx].bme680_state = 0; - - return true; -} - -void Bme680Read(uint8_t bmp_idx) -{ - if (!gas_sensor) { return; } - - int8_t rslt = BME680_OK; - - if (BME680_CHIPID == bmp_sensors[bmp_idx].bmp_type) { - if (0 == bmp_sensors[bmp_idx].bme680_state) { - - rslt = bme680_set_sensor_mode(&gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return; } - - - - - - - - bmp_sensors[bmp_idx].bme680_state = 1; - } else { - bmp_sensors[bmp_idx].bme680_state = 0; - - struct bme680_field_data data; - rslt = bme680_get_sensor_data(&data, &gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return; } - - bmp_sensors[bmp_idx].bmp_temperature = data.temperature / 100.0; - bmp_sensors[bmp_idx].bmp_humidity = data.humidity / 1000.0; - bmp_sensors[bmp_idx].bmp_pressure = data.pressure / 100.0; - - if (data.status & BME680_GASM_VALID_MSK) { - bmp_sensors[bmp_idx].bmp_gas_resistance = data.gas_resistance / 1000.0; - } else { - bmp_sensors[bmp_idx].bmp_gas_resistance = 0; - } - } - } - return; -} - -#endif - - - -void BmpDetect(void) -{ - if (bmp_count) return; - - int bmp_sensor_size = BMP_MAX_SENSORS * sizeof(bmp_sensors_t); - if (!bmp_sensors) { - bmp_sensors = (bmp_sensors_t*)malloc(bmp_sensor_size); - } - if (!bmp_sensors) { return; } - memset(bmp_sensors, 0, bmp_sensor_size); - - for (uint32_t i = 0; i < BMP_MAX_SENSORS; i++) { - uint8_t bmp_type = I2cRead8(bmp_addresses[i], BMP_REGISTER_CHIPID); - if (bmp_type) { - bmp_sensors[bmp_count].bmp_address = bmp_addresses[i]; - bmp_sensors[bmp_count].bmp_type = bmp_type; - bmp_sensors[bmp_count].bmp_model = 0; - - bool success = false; - switch (bmp_type) { - case BMP180_CHIPID: - success = Bmp180Calibration(bmp_count); - break; - case BME280_CHIPID: - bmp_sensors[bmp_count].bmp_model++; - case BMP280_CHIPID: - bmp_sensors[bmp_count].bmp_model++; - success = Bmx280Calibrate(bmp_count); - break; -#ifdef USE_BME680 - case BME680_CHIPID: - bmp_sensors[bmp_count].bmp_model = 3; - success = Bme680Init(bmp_count); - break; -#endif - } - if (success) { - GetTextIndexed(bmp_sensors[bmp_count].bmp_name, sizeof(bmp_sensors[bmp_count].bmp_name), bmp_sensors[bmp_count].bmp_model, kBmpTypes); - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, bmp_sensors[bmp_count].bmp_name, bmp_sensors[bmp_count].bmp_address); - bmp_count++; - } - } - } -} - -void BmpRead(void) -{ - if (!bmp_sensors) { return; } - - for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { - switch (bmp_sensors[bmp_idx].bmp_type) { - case BMP180_CHIPID: - Bmp180Read(bmp_idx); - break; - case BMP280_CHIPID: - case BME280_CHIPID: - Bme280Read(bmp_idx); - break; -#ifdef USE_BME680 - case BME680_CHIPID: - Bme680Read(bmp_idx); - break; -#endif - } - } - ConvertTemp(bmp_sensors[0].bmp_temperature); - ConvertHumidity(bmp_sensors[0].bmp_humidity); -} - -void BmpEverySecond(void) -{ - if (91 == (uptime %100)) { - - BmpDetect(); - } - else { - - BmpRead(); - } -} - -void BmpShow(bool json) -{ - if (!bmp_sensors) { return; } - - for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { - if (bmp_sensors[bmp_idx].bmp_type) { - float bmp_sealevel = 0.0; - if (bmp_sensors[bmp_idx].bmp_pressure != 0.0) { - bmp_sealevel = (bmp_sensors[bmp_idx].bmp_pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; - bmp_sealevel = ConvertPressure(bmp_sealevel); - } - float bmp_temperature = ConvertTemp(bmp_sensors[bmp_idx].bmp_temperature); - float bmp_pressure = ConvertPressure(bmp_sensors[bmp_idx].bmp_pressure); - - char name[10]; - strlcpy(name, bmp_sensors[bmp_idx].bmp_name, sizeof(name)); - if (bmp_count > 1) { - snprintf_P(name, sizeof(name), PSTR("%s%c%02X"), name, IndexSeparator(), bmp_sensors[bmp_idx].bmp_address); - } - - char temperature[33]; - dtostrfd(bmp_temperature, Settings.flag2.temperature_resolution, temperature); - char pressure[33]; - dtostrfd(bmp_pressure, Settings.flag2.pressure_resolution, pressure); - char sea_pressure[33]; - dtostrfd(bmp_sealevel, Settings.flag2.pressure_resolution, sea_pressure); - char humidity[33]; - dtostrfd(bmp_sensors[bmp_idx].bmp_humidity, Settings.flag2.humidity_resolution, humidity); -#ifdef USE_BME680 - char gas_resistance[33]; - dtostrfd(bmp_sensors[bmp_idx].bmp_gas_resistance, 2, gas_resistance); -#endif - - if (json) { - char json_humidity[40]; - snprintf_P(json_humidity, sizeof(json_humidity), PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); - char json_sealevel[40]; - snprintf_P(json_sealevel, sizeof(json_sealevel), PSTR(",\"" D_JSON_PRESSUREATSEALEVEL "\":%s"), sea_pressure); -#ifdef USE_BME680 - char json_gas[40]; - snprintf_P(json_gas, sizeof(json_gas), PSTR(",\"" D_JSON_GAS "\":%s"), gas_resistance); - - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), - name, - temperature, - (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", - pressure, - (Settings.altitude != 0) ? json_sealevel : "", - (bmp_sensors[bmp_idx].bmp_model >= 3) ? json_gas : ""); -#else - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), - name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); -#endif - -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == bmp_idx)) { - DomoticzTempHumPressureSensor(temperature, humidity, pressure); -#ifdef USE_BME680 - if (bmp_sensors[bmp_idx].bmp_model >= 3) { DomoticzSensor(DZ_AIRQUALITY, (uint32_t)bmp_sensors[bmp_idx].bmp_gas_resistance); } -#endif - } -#endif - -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, bmp_temperature); - KnxSensor(KNX_HUMIDITY, bmp_sensors[bmp_idx].bmp_humidity); - } -#endif - -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, name, temperature, TempUnit()); - if (bmp_sensors[bmp_idx].bmp_model >= 2) { - WSContentSend_PD(HTTP_SNS_HUM, name, humidity); - } - WSContentSend_PD(HTTP_SNS_PRESSURE, name, pressure, PressureUnit().c_str()); - if (Settings.altitude != 0) { - WSContentSend_PD(HTTP_SNS_SEAPRESSURE, name, sea_pressure, PressureUnit().c_str()); - } -#ifdef USE_BME680 - if (bmp_sensors[bmp_idx].bmp_model >= 3) { - WSContentSend_PD(PSTR("{s}%s " D_GAS "{m}%s " D_UNIT_KILOOHM "{e}"), name, gas_resistance); - } -#endif - -#endif - } - } - } -} - - - - - -bool Xsns09(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - BmpDetect(); - break; - case FUNC_EVERY_SECOND: - BmpEverySecond(); - break; - case FUNC_JSON_APPEND: - BmpShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - BmpShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_10_bh1750.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_10_bh1750.ino" -#ifdef USE_I2C -#ifdef USE_BH1750 - - - - - - -#define XSNS_10 10 - -#define BH1750_ADDR1 0x23 -#define BH1750_ADDR2 0x5C - -#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 - -uint8_t bh1750_address; -uint8_t bh1750_addresses[] = { BH1750_ADDR1, BH1750_ADDR2 }; -uint8_t bh1750_type = 0; -uint8_t bh1750_valid = 0; -uint16_t bh1750_illuminance = 0; -char bh1750_types[] = "BH1750"; - -bool Bh1750Read(void) -{ - if (bh1750_valid) { bh1750_valid--; } - - if (2 != Wire.requestFrom(bh1750_address, (uint8_t)2)) { return false; } - uint8_t msb = Wire.read(); - uint8_t lsb = Wire.read(); - bh1750_illuminance = ((msb << 8) | lsb) / 1.2; - bh1750_valid = SENSOR_MAX_MISS; - return true; -} - - - -void Bh1750Detect(void) -{ - if (bh1750_type) { - return; - } - - for (uint32_t i = 0; i < sizeof(bh1750_addresses); i++) { - bh1750_address = bh1750_addresses[i]; - Wire.beginTransmission(bh1750_address); - Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE); - if (!Wire.endTransmission()) { - bh1750_type = 1; - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, bh1750_types, bh1750_address); - break; - } - } -} - -void Bh1750EverySecond(void) -{ - if (90 == (uptime %100)) { - - Bh1750Detect(); - } - else { - - if (bh1750_type) { - if (!Bh1750Read()) { - AddLogMissed(bh1750_types, bh1750_valid); - - } - } - } -} - -void Bh1750Show(bool json) -{ - if (bh1750_valid) { - if (json) { - ResponseAppend_P(JSON_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_ILLUMINANCE, bh1750_illuminance); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); -#endif - } - } -} - - - - - -bool Xsns10(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - Bh1750Detect(); - break; - case FUNC_EVERY_SECOND: - Bh1750EverySecond(); - break; - case FUNC_JSON_APPEND: - Bh1750Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Bh1750Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_11_veml6070.ino" -# 89 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_11_veml6070.ino" -#ifdef USE_I2C -#ifdef USE_VEML6070 - - - - - - -#define XSNS_11 11 - -#define VEML6070_ADDR_H 0x39 -#define VEML6070_ADDR_L 0x38 -#define VEML6070_INTEGRATION_TIME 3 -#define VEML6070_ENABLE 1 -#define VEML6070_DISABLE 0 -#define VEML6070_RSET_DEFAULT 270000 -#define VEML6070_UV_MAX_INDEX 15 -#define VEML6070_UV_MAX_DEFAULT 11 -#define VEML6070_POWER_COEFFCIENT 0.025 -#define VEML6070_TABLE_COEFFCIENT 32.86270591 - - - - - -const char kVemlTypes[] PROGMEM = "VEML6070"; -double uv_risk_map[VEML6070_UV_MAX_INDEX] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -double uvrisk = 0; -double uvpower = 0; -uint16_t uvlevel = 0; -uint8_t veml6070_addr_low = VEML6070_ADDR_L; -uint8_t veml6070_addr_high = VEML6070_ADDR_H; -uint8_t itime = VEML6070_INTEGRATION_TIME; -uint8_t veml6070_type = 0; -uint8_t veml6070_valid = 0; -char veml6070_name[9]; -char str_uvrisk_text[10]; - - - -void Veml6070Detect(void) -{ - if (veml6070_type) { - return; - } - - Wire.beginTransmission(VEML6070_ADDR_L); - Wire.write((itime << 2) | 0x02); - uint8_t status = Wire.endTransmission(); - - if (!status) { - veml6070_type = 1; - uint8_t veml_model = 0; - GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes); - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "VEML6070", VEML6070_ADDR_L); - } -} - - - -void Veml6070UvTableInit(void) -{ - - for (uint32_t i = 0; i < VEML6070_UV_MAX_INDEX; i++) { -#ifdef USE_VEML6070_RSET - if ( (USE_VEML6070_RSET >= 220000) && (USE_VEML6070_RSET <= 1000000) ) { - uv_risk_map[i] = ( (USE_VEML6070_RSET / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); - } else { - uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor error %d"), USE_VEML6070_RSET); - } -#else - uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor default used %d"), VEML6070_RSET_DEFAULT); -#endif - } -} - - - -void Veml6070EverySecond(void) -{ - - if (11 == (uptime %100)) { - Veml6070ModeCmd(1); - Veml6070Detect(); - Veml6070ModeCmd(0); - } else { - Veml6070ModeCmd(1); - uvlevel = Veml6070ReadUv(); - uvrisk = Veml6070UvRiskLevel(uvlevel); - uvpower = Veml6070UvPower(uvrisk); - Veml6070ModeCmd(0); - } -} - - - -void Veml6070ModeCmd(bool mode_cmd) -{ - - - Wire.beginTransmission(VEML6070_ADDR_L); - Wire.write((mode_cmd << 0) | 0x02 | (itime << 2)); - uint8_t status = Wire.endTransmission(); - - if (!status) { - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "VEML6070 mode_cmd", VEML6070_ADDR_L); - } -} - - - -uint16_t Veml6070ReadUv(void) -{ - uint16_t uv_raw = 0; - - if (Wire.requestFrom(VEML6070_ADDR_H, 1) != 1) { - return -1; - } - uv_raw = Wire.read(); - uv_raw <<= 8; - - if (Wire.requestFrom(VEML6070_ADDR_L, 1) != 1) { - return -1; - } - uv_raw |= Wire.read(); - - return uv_raw; -} - - - -double Veml6070UvRiskLevel(uint16_t uv_level) -{ - double risk = 0; - if (uv_level < uv_risk_map[VEML6070_UV_MAX_INDEX-1]) { - risk = (double)uv_level / uv_risk_map[0]; - - if ( (risk >= 0) && (risk <= 2.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_1); } - else if ( (risk >= 3.0) && (risk <= 5.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_2); } - else if ( (risk >= 6.0) && (risk <= 7.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_3); } - else if ( (risk >= 8.0) && (risk <= 10.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_4); } - else if ( (risk >= 11.0) && (risk <= 12.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_5); } - else if ( (risk >= 13.0) && (risk <= 25.0) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_6); } - else { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); } - return risk; - } else { - - snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); - return ( risk = 99 ); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 out of range %d"), risk); - } -} - - - -double Veml6070UvPower(double uvrisk) -{ - - double power = 0; - return ( power = VEML6070_POWER_COEFFCIENT * uvrisk ); -} - - - - -#ifdef USE_WEBSERVER - -#ifdef USE_VEML6070_SHOW_RAW - const char HTTP_SNS_UV_LEVEL[] PROGMEM = "{s}VEML6070 " D_UV_LEVEL "{m}%s " D_UNIT_INCREMENTS "{e}"; -#endif - - const char HTTP_SNS_UV_INDEX[] PROGMEM = "{s}VEML6070 " D_UV_INDEX "{m}%s %s{e}"; - const char HTTP_SNS_UV_POWER[] PROGMEM = "{s}VEML6070 " D_UV_POWER "{m}%s " D_UNIT_WATT_METER_QUADRAT "{e}"; -#endif - - - -void Veml6070Show(bool json) -{ - if (veml6070_type) { - - char str_uvlevel[33]; - dtostrfd((double)uvlevel, 0, str_uvlevel); - char str_uvrisk[33]; - dtostrfd(uvrisk, 2, str_uvrisk); - char str_uvpower[33]; - dtostrfd(uvpower, 3, str_uvpower); - if (json) { -#ifdef USE_VEML6070_SHOW_RAW - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), - veml6070_name, str_uvlevel, str_uvrisk, str_uvrisk_text, str_uvpower); -#else - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), - veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); -#endif -#ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); } -#endif -#ifdef USE_WEBSERVER - } else { -#ifdef USE_VEML6070_SHOW_RAW - WSContentSend_PD(HTTP_SNS_UV_LEVEL, str_uvlevel); -#endif - WSContentSend_PD(HTTP_SNS_UV_INDEX, str_uvrisk, str_uvrisk_text); - WSContentSend_PD(HTTP_SNS_UV_POWER, str_uvpower); -#endif - } - } -} - - - - - -bool Xsns11(uint8_t function) -{ - bool result = false; - - if (i2c_flg && !(pin[GPIO_ADE7953_IRQ] < 99)) { - switch (function) { - case FUNC_INIT: - Veml6070Detect(); - Veml6070UvTableInit(); - break; - case FUNC_EVERY_SECOND: - Veml6070EverySecond(); - break; - case FUNC_JSON_APPEND: - Veml6070Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Veml6070Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_12_ads1115.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_12_ads1115.ino" -#ifdef USE_I2C -#ifdef USE_ADS1115 -# 43 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_12_ads1115.ino" -#define XSNS_12 12 - -#define ADS1115_ADDRESS_ADDR_GND 0x48 -#define ADS1115_ADDRESS_ADDR_VDD 0x49 -#define ADS1115_ADDRESS_ADDR_SDA 0x4A -#define ADS1115_ADDRESS_ADDR_SCL 0x4B - -#define ADS1115_CONVERSIONDELAY (8) - - - - -#define ADS1115_REG_POINTER_MASK (0x03) -#define ADS1115_REG_POINTER_CONVERT (0x00) -#define ADS1115_REG_POINTER_CONFIG (0x01) -#define ADS1115_REG_POINTER_LOWTHRESH (0x02) -#define ADS1115_REG_POINTER_HITHRESH (0x03) - - - - -#define ADS1115_REG_CONFIG_OS_MASK (0x8000) -#define ADS1115_REG_CONFIG_OS_SINGLE (0x8000) -#define ADS1115_REG_CONFIG_OS_BUSY (0x0000) -#define ADS1115_REG_CONFIG_OS_NOTBUSY (0x8000) - -#define ADS1115_REG_CONFIG_MUX_MASK (0x7000) -#define ADS1115_REG_CONFIG_MUX_DIFF_0_1 (0x0000) -#define ADS1115_REG_CONFIG_MUX_DIFF_0_3 (0x1000) -#define ADS1115_REG_CONFIG_MUX_DIFF_1_3 (0x2000) -#define ADS1115_REG_CONFIG_MUX_DIFF_2_3 (0x3000) -#define ADS1115_REG_CONFIG_MUX_SINGLE_0 (0x4000) -#define ADS1115_REG_CONFIG_MUX_SINGLE_1 (0x5000) -#define ADS1115_REG_CONFIG_MUX_SINGLE_2 (0x6000) -#define ADS1115_REG_CONFIG_MUX_SINGLE_3 (0x7000) - -#define ADS1115_REG_CONFIG_PGA_MASK (0x0E00) -#define ADS1115_REG_CONFIG_PGA_6_144V (0x0000) -#define ADS1115_REG_CONFIG_PGA_4_096V (0x0200) -#define ADS1115_REG_CONFIG_PGA_2_048V (0x0400) -#define ADS1115_REG_CONFIG_PGA_1_024V (0x0600) -#define ADS1115_REG_CONFIG_PGA_0_512V (0x0800) -#define ADS1115_REG_CONFIG_PGA_0_256V (0x0A00) - -#define ADS1115_REG_CONFIG_MODE_MASK (0x0100) -#define ADS1115_REG_CONFIG_MODE_CONTIN (0x0000) -#define ADS1115_REG_CONFIG_MODE_SINGLE (0x0100) - -#define ADS1115_REG_CONFIG_DR_MASK (0x00E0) -#define ADS1115_REG_CONFIG_DR_128SPS (0x0000) -#define ADS1115_REG_CONFIG_DR_250SPS (0x0020) -#define ADS1115_REG_CONFIG_DR_490SPS (0x0040) -#define ADS1115_REG_CONFIG_DR_920SPS (0x0060) -#define ADS1115_REG_CONFIG_DR_1600SPS (0x0080) -#define ADS1115_REG_CONFIG_DR_2400SPS (0x00A0) -#define ADS1115_REG_CONFIG_DR_3300SPS (0x00C0) -#define ADS1115_REG_CONFIG_DR_6000SPS (0x00E0) - -#define ADS1115_REG_CONFIG_CMODE_MASK (0x0010) -#define ADS1115_REG_CONFIG_CMODE_TRAD (0x0000) -#define ADS1115_REG_CONFIG_CMODE_WINDOW (0x0010) - -#define ADS1115_REG_CONFIG_CPOL_MASK (0x0008) -#define ADS1115_REG_CONFIG_CPOL_ACTVLOW (0x0000) -#define ADS1115_REG_CONFIG_CPOL_ACTVHI (0x0008) - -#define ADS1115_REG_CONFIG_CLAT_MASK (0x0004) -#define ADS1115_REG_CONFIG_CLAT_NONLAT (0x0000) -#define ADS1115_REG_CONFIG_CLAT_LATCH (0x0004) - -#define ADS1115_REG_CONFIG_CQUE_MASK (0x0003) -#define ADS1115_REG_CONFIG_CQUE_1CONV (0x0000) -#define ADS1115_REG_CONFIG_CQUE_2CONV (0x0001) -#define ADS1115_REG_CONFIG_CQUE_4CONV (0x0002) -#define ADS1115_REG_CONFIG_CQUE_NONE (0x0003) - -uint8_t ads1115_type = 0; -uint8_t ads1115_address; -uint8_t ads1115_addresses[] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL }; -uint8_t ads1115_found[] = {false,false,false,false}; -int16_t ads1115_values[4]; - - -void Ads1115StartComparator(uint8_t channel, uint16_t mode) -{ - - uint16_t config = mode | - ADS1115_REG_CONFIG_CQUE_NONE | - ADS1115_REG_CONFIG_CLAT_NONLAT | - ADS1115_REG_CONFIG_PGA_6_144V | - ADS1115_REG_CONFIG_CPOL_ACTVLOW | - ADS1115_REG_CONFIG_CMODE_TRAD | - ADS1115_REG_CONFIG_DR_6000SPS; - - - config |= (ADS1115_REG_CONFIG_MUX_SINGLE_0 + (0x1000 * channel)); - - - I2cWrite16(ads1115_address, ADS1115_REG_POINTER_CONFIG, config); -} - -int16_t Ads1115GetConversion(uint8_t channel) -{ - Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE); - - delay(ADS1115_CONVERSIONDELAY); - - I2cRead16(ads1115_address, ADS1115_REG_POINTER_CONVERT); - - Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN); - delay(ADS1115_CONVERSIONDELAY); - - uint16_t res = I2cRead16(ads1115_address, ADS1115_REG_POINTER_CONVERT); - return (int16_t)res; -} - - - -void Ads1115Detect(void) -{ - uint16_t buffer; - for (uint32_t i = 0; i < sizeof(ads1115_addresses); i++) { - if (!ads1115_found[i]) { - ads1115_address = ads1115_addresses[i]; - if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT) && - I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONFIG)) { - Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); - ads1115_type = 1; - ads1115_found[i] = 1; - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); - } - } - } -} - -void Ads1115GetValues(uint8_t address) -{ - uint8_t old_address = ads1115_address; - ads1115_address = address; - for (uint32_t i = 0; i < 4; i++) { - ads1115_values[i] = Ads1115GetConversion(i); - - } - ads1115_address = old_address; -} - -void Ads1115toJSON(char *comma_j) -{ - ResponseAppend_P(PSTR("%s{"), comma_j); - char *comma = (char*)""; - for (uint32_t i = 0; i < 4; i++) { - ResponseAppend_P(PSTR("%s\"A%d\":%d"), comma, i, ads1115_values[i]); - comma = (char*)","; - } - ResponseJsonEnd(); -} - -void Ads1115toString(uint8_t address) -{ - char label[15]; - snprintf_P(label, sizeof(label), "ADS1115(%02x)", address); - - for (uint32_t i = 0; i < 4; i++) { - WSContentSend_PD(HTTP_SNS_ANALOG, label, i, ads1115_values[i]); - } -} - -void Ads1115Show(bool json) -{ - if (!ads1115_type) { return; } - - if (json) { - ResponseAppend_P(PSTR(",\"ADS1115\":")); - } - - char *comma = (char*)""; - - for (uint32_t t = 0; t < sizeof(ads1115_addresses); t++) { - - if (ads1115_found[t]) { - Ads1115GetValues(ads1115_addresses[t]); - if (json) { - Ads1115toJSON(comma); - comma = (char*)","; - } -#ifdef USE_WEBSERVER - else { - Ads1115toString(ads1115_addresses[t]); - } -#endif - } - } - -} - - - - - -bool Xsns12(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_PREP_BEFORE_TELEPERIOD: - Ads1115Detect(); - break; - case FUNC_JSON_APPEND: - Ads1115Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ads1115Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_12_ads1115_i2cdev.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_12_ads1115_i2cdev.ino" -#ifdef USE_I2C -#ifdef USE_ADS1115_I2CDEV -# 43 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_12_ads1115_i2cdev.ino" -#define XSNS_12 12 - -#include - -ADS1115 adc0; - -uint8_t ads1115_type = 0; -uint8_t ads1115_address; -uint8_t ads1115_addresses[] = { - ADS1115_ADDRESS_ADDR_GND, - ADS1115_ADDRESS_ADDR_VDD, - ADS1115_ADDRESS_ADDR_SDA, - ADS1115_ADDRESS_ADDR_SCL -}; - -int16_t Ads1115GetConversion(uint8_t channel) -{ - switch (channel) { - case 0: - adc0.getConversionP0GND(); - break; - case 1: - adc0.getConversionP1GND(); - break; - case 2: - adc0.getConversionP2GND(); - break; - case 3: - adc0.getConversionP3GND(); - break; - } -} - - - -void Ads1115Detect(void) -{ - if (ads1115_type) { - return; - } - - for (uint32_t i = 0; i < sizeof(ads1115_addresses); i++) { - ads1115_address = ads1115_addresses[i]; - ADS1115 adc0(ads1115_address); - if (adc0.testConnection()) { - adc0.initialize(); - adc0.setGain(ADS1115_PGA_6P144); - adc0.setRate(ADS1115_RATE_860); - adc0.setMode(ADS1115_MODE_CONTINUOUS); - ads1115_type = 1; - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); - break; - } - } -} - -void Ads1115Show(bool json) -{ - if (ads1115_type) { - - uint8_t dsxflg = 0; - for (uint32_t i = 0; i < 4; i++) { - int16_t adc_value = Ads1115GetConversion(i); - - if (json) { - if (!dsxflg ) { - ResponseAppend_P(PSTR(",\"ADS1115\":{")); - } - ResponseAppend_P(PSTR("%s\"A%d\":%d"), (dsxflg) ? "," : "", i, adc_value); - dsxflg++; -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ANALOG, "ADS1115", i, adc_value); -#endif - } - } - if (json) { - if (dsxflg) { - ResponseJsonEnd(); - } - } - } -} - - - - - -bool Xsns12(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_PREP_BEFORE_TELEPERIOD: - Ads1115Detect(); - break; - case FUNC_JSON_APPEND: - Ads1115Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ads1115Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_13_ina219.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_13_ina219.ino" -#ifdef USE_I2C -#ifdef USE_INA219 -# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_13_ina219.ino" -#define XSNS_13 13 - -#define INA219_ADDRESS1 (0x40) -#define INA219_ADDRESS2 (0x41) -#define INA219_ADDRESS3 (0x44) -#define INA219_ADDRESS4 (0x45) - -#define INA219_READ (0x01) -#define INA219_REG_CONFIG (0x00) - -#define INA219_CONFIG_RESET (0x8000) - -#define INA219_CONFIG_BVOLTAGERANGE_MASK (0x2000) -#define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) -#define INA219_CONFIG_BVOLTAGERANGE_32V (0x2000) - -#define INA219_CONFIG_GAIN_MASK (0x1800) -#define INA219_CONFIG_GAIN_1_40MV (0x0000) -#define INA219_CONFIG_GAIN_2_80MV (0x0800) -#define INA219_CONFIG_GAIN_4_160MV (0x1000) -#define INA219_CONFIG_GAIN_8_320MV (0x1800) - -#define INA219_CONFIG_BADCRES_MASK (0x0780) -#define INA219_CONFIG_BADCRES_9BIT (0x0080) -#define INA219_CONFIG_BADCRES_10BIT (0x0100) -#define INA219_CONFIG_BADCRES_11BIT (0x0200) -#define INA219_CONFIG_BADCRES_12BIT (0x0400) - -#define INA219_CONFIG_SADCRES_MASK (0x0078) -#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) -#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) -#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) -#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) -#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) -#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) -#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) -#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) -#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) -#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) -#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) - -#define INA219_CONFIG_MODE_MASK (0x0007) -#define INA219_CONFIG_MODE_POWERDOWN (0x0000) -#define INA219_CONFIG_MODE_SVOLT_TRIGGERED (0x0001) -#define INA219_CONFIG_MODE_BVOLT_TRIGGERED (0x0002) -#define INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED (0x0003) -#define INA219_CONFIG_MODE_ADCOFF (0x0004) -#define INA219_CONFIG_MODE_SVOLT_CONTINUOUS (0x0005) -#define INA219_CONFIG_MODE_BVOLT_CONTINUOUS (0x0006) -#define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS (0x0007) - -#define INA219_REG_SHUNTVOLTAGE (0x01) -#define INA219_REG_BUSVOLTAGE (0x02) -#define INA219_REG_POWER (0x03) -#define INA219_REG_CURRENT (0x04) -#define INA219_REG_CALIBRATION (0x05) - -uint8_t ina219_type[4] = {0,0,0,0}; -uint8_t ina219_addresses[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; - -uint32_t ina219_cal_value = 0; - -uint32_t ina219_current_divider_ma = 0; - -uint8_t ina219_valid[4] = {0,0,0,0}; -float ina219_voltage[4] = {0,0,0,0}; -float ina219_current[4] = {0,0,0,0}; -char ina219_types[] = "INA219"; - -bool Ina219SetCalibration(uint8_t mode, uint16_t addr) -{ - uint16_t config = 0; - - switch (mode &3) { - case 0: - case 3: - ina219_cal_value = 4096; - ina219_current_divider_ma = 10; - config = INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - break; - case 1: - ina219_cal_value = 10240; - ina219_current_divider_ma = 25; - config |= INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - break; - case 2: - ina219_cal_value = 8192; - ina219_current_divider_ma = 20; - config |= INA219_CONFIG_BVOLTAGERANGE_16V | INA219_CONFIG_GAIN_1_40MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - break; - } - - bool success = I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); - if (success) { - - I2cWrite16(addr, INA219_REG_CONFIG, config); - } - return success; -} - -float Ina219GetShuntVoltage_mV(uint16_t addr) -{ - - int16_t value = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); - - return value * 0.01; -} - -float Ina219GetBusVoltage_V(uint16_t addr) -{ - - - int16_t value = (int16_t)(((uint16_t)I2cReadS16(addr, INA219_REG_BUSVOLTAGE) >> 3) * 4); - - return value * 0.001; -} - -float Ina219GetCurrent_mA(uint16_t addr) -{ - - - - I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); - - - float value = I2cReadS16(addr, INA219_REG_CURRENT); - value /= ina219_current_divider_ma; - - return value; -} - -bool Ina219Read(void) -{ - for (int i=0; i= 0) && (XdrvMailbox.payload <= 2)) { - Settings.ina219_mode = XdrvMailbox.payload; - restart_flag = 2; - } - Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); - - return serviced; -} - - - -void Ina219Detect(void) -{ - for (int i=0; i1) - snprintf_P(name, sizeof(name), PSTR("%s%c%d"), ina219_types, IndexSeparator(), sensor_num); - else - snprintf_P(name, sizeof(name), PSTR("%s"), ina219_types); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%02x,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), - name, ina219_addresses[i], voltage, current, power); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_VOLTAGE, voltage); - DomoticzSensor(DZ_CURRENT, current); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_INA219_DATA, name, voltage, name, current, name, power); -#endif - } - } -} - - - - - -bool Xsns13(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_COMMAND_SENSOR: - if ((XSNS_13 == XdrvMailbox.index) && (ina219_type)) { - result = Ina219CommandSensor(); - } - break; - case FUNC_INIT: - Ina219Detect(); - break; - case FUNC_EVERY_SECOND: - Ina219EverySecond(); - break; - case FUNC_JSON_APPEND: - Ina219Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ina219Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_14_sht3x.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_14_sht3x.ino" -#ifdef USE_I2C -#ifdef USE_SHT3X - - - - - - -#define XSNS_14 14 - -#define SHT3X_ADDR_GND 0x44 -#define SHT3X_ADDR_VDD 0x45 -#define SHTC3_ADDR 0x70 - -#define SHT3X_MAX_SENSORS 3 - -const char kShtTypes[] PROGMEM = "SHT3X|SHT3X|SHTC3"; -uint8_t sht3x_addresses[] = { SHT3X_ADDR_GND, SHT3X_ADDR_VDD, SHTC3_ADDR }; - -uint8_t sht3x_count = 0; -struct SHT3XSTRUCT { - uint8_t address; - char types[6]; -} sht3x_sensors[SHT3X_MAX_SENSORS]; - -bool Sht3xRead(float &t, float &h, uint8_t sht3x_address) -{ - unsigned int data[6]; - - t = NAN; - h = NAN; - - Wire.beginTransmission(sht3x_address); - if (SHTC3_ADDR == sht3x_address) { - Wire.write(0x35); - Wire.write(0x17); - Wire.endTransmission(); - Wire.beginTransmission(sht3x_address); - Wire.write(0x78); - Wire.write(0x66); - } else { - Wire.write(0x2C); - Wire.write(0x06); - } - if (Wire.endTransmission() != 0) { - return false; - } - delay(30); - Wire.requestFrom(sht3x_address, (uint8_t)6); - for (uint32_t i = 0; i < 6; i++) { - data[i] = Wire.read(); - }; - t = ConvertTemp((float)((((data[0] << 8) | data[1]) * 175) / 65535.0) - 45); - h = ConvertHumidity((float)((((data[3] << 8) | data[4]) * 100) / 65535.0)); - return (!isnan(t) && !isnan(h) && (h != 0)); -} - - - -void Sht3xDetect(void) -{ - if (sht3x_count) return; - - float t; - float h; - for (uint32_t i = 0; i < SHT3X_MAX_SENSORS; i++) { - if (Sht3xRead(t, h, sht3x_addresses[i])) { - sht3x_sensors[sht3x_count].address = sht3x_addresses[i]; - GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), i, kShtTypes); - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, sht3x_sensors[sht3x_count].types, sht3x_sensors[sht3x_count].address); - sht3x_count++; - } - } -} - -void Sht3xShow(bool json) -{ - if (sht3x_count) { - float t; - float h; - char types[11]; - for (uint32_t i = 0; i < sht3x_count; i++) { - if (Sht3xRead(t, h, sht3x_sensors[i].address)) { - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(h, Settings.flag2.humidity_resolution, humidity); - snprintf_P(types, sizeof(types), PSTR("%s%c0x%02X"), sht3x_sensors[i].types, IndexSeparator(), sht3x_sensors[i].address); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, types, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif - -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, t); - KnxSensor(KNX_HUMIDITY, h); - } -#endif - -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, types, humidity); -#endif - } - } - } - } -} - - - - - -bool Xsns14(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - Sht3xDetect(); - break; - case FUNC_JSON_APPEND: - Sht3xShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sht3xShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_15_mhz19.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_15_mhz19.ino" -#ifdef USE_MHZ19 -# 33 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_15_mhz19.ino" -#define XSNS_15 15 - -enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILTER_FAST, MHZ19_FILTER_MEDIUM, MHZ19_FILTER_SLOW}; - -#define MHZ19_FILTER_OPTION MHZ19_FILTER_FAST -# 58 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_15_mhz19.ino" -#include - -#ifndef CO2_LOW -#define CO2_LOW 800 -#endif -#ifndef CO2_HIGH -#define CO2_HIGH 1200 -#endif - -#define MHZ19_READ_TIMEOUT 400 -#define MHZ19_RETRY_COUNT 8 - -TasmotaSerial *MhzSerial; - -const char kMhzModels[] PROGMEM = "|B"; - -const char ABC_ENABLED[] = "ABC is Enabled"; -const char ABC_DISABLED[] = "ABC is Disabled"; - -enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; -const uint8_t kMhzCommands[][4] PROGMEM = { - - {0x86,0x00,0x00,0x00}, - {0x79,0xA0,0x00,0x00}, - {0x79,0x00,0x00,0x00}, - {0x87,0x00,0x00,0x00}, - {0x8D,0x00,0x00,0x00}, - {0x99,0x00,0x03,0xE8}, - {0x99,0x00,0x07,0xD0}, - {0x99,0x00,0x0B,0xB8}, - {0x99,0x00,0x13,0x88}}; - -uint8_t mhz_type = 1; -uint16_t mhz_last_ppm = 0; -uint8_t mhz_filter = MHZ19_FILTER_OPTION; -bool mhz_abc_must_apply = false; - -float mhz_temperature = 0; -uint8_t mhz_retry = MHZ19_RETRY_COUNT; -uint8_t mhz_received = 0; -uint8_t mhz_state = 0; - - - -uint8_t MhzCalculateChecksum(uint8_t *array) -{ - uint8_t checksum = 0; - for (uint32_t i = 1; i < 8; i++) { - checksum += array[i]; - } - checksum = 255 - checksum; - return (checksum +1); -} - -size_t MhzSendCmd(uint8_t command_id) -{ - uint8_t mhz_send[9] = { 0 }; - - mhz_send[0] = 0xFF; - mhz_send[1] = 0x01; - memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(uint16_t)); - - - - - memcpy_P(&mhz_send[6], kMhzCommands[command_id] + sizeof(uint16_t), sizeof(uint16_t)); - mhz_send[8] = MhzCalculateChecksum(mhz_send); - - - - return MhzSerial->write(mhz_send, sizeof(mhz_send)); -} - - - -bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) -{ - if (1 == s) { - return false; - } - if (mhz_last_ppm < 400 || mhz_last_ppm > 5000) { - - - mhz_last_ppm = ppm; - return true; - } - int32_t difference = ppm - mhz_last_ppm; - if (s > 0 && s < 64 && mhz_filter != MHZ19_FILTER_OFF) { -# 154 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_15_mhz19.ino" - difference *= s; - difference /= 64; - } - if (MHZ19_FILTER_OFF == mhz_filter) { - if (s != 0 && s != 64) { - return false; - } - } else { - difference >>= (mhz_filter -1); - } - mhz_last_ppm = static_cast(mhz_last_ppm + difference); - return true; -} - -void MhzEverySecond(void) -{ - mhz_state++; - if (8 == mhz_state) { - mhz_state = 0; - - if (mhz_retry) { - mhz_retry--; - if (!mhz_retry) { - mhz_last_ppm = 0; - mhz_temperature = 0; - } - } - - MhzSerial->flush(); - MhzSendCmd(MHZ_CMND_READPPM); - mhz_received = 0; - } - - if ((mhz_state > 2) && !mhz_received) { - uint8_t mhz_response[9]; - - unsigned long start = millis(); - uint8_t counter = 0; - while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { - if (MhzSerial->available() > 0) { - mhz_response[counter++] = MhzSerial->read(); - } else { - delay(5); - } - } - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); - - if (counter < 9) { - - return; - } - - uint8_t crc = MhzCalculateChecksum(mhz_response); - if (mhz_response[8] != crc) { - - return; - } - if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { - - return; - } - - mhz_received = 1; - - uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; - if (15000 == u) { - if (Settings.SensorBits1.mhz19b_abc_disable) { - - - mhz_abc_must_apply = true; - } - } else { - uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; - mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); - uint8_t s = mhz_response[5]; - mhz_type = (s) ? 1 : 2; - if (MhzCheckAndApplyFilter(ppm, s)) { - mhz_retry = MHZ19_RETRY_COUNT; - LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); - - if (0 == s || 64 == s) { - if (mhz_abc_must_apply) { - mhz_abc_must_apply = false; - if (!Settings.SensorBits1.mhz19b_abc_disable) { - MhzSendCmd(MHZ_CMND_ABCENABLE); - } else { - MhzSendCmd(MHZ_CMND_ABCDISABLE); - } - } - } - - } - } - - } -} -# 266 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_15_mhz19.ino" -#define D_JSON_RANGE_1000 "1000 ppm range" -#define D_JSON_RANGE_2000 "2000 ppm range" -#define D_JSON_RANGE_3000 "3000 ppm range" -#define D_JSON_RANGE_5000 "5000 ppm range" - -bool MhzCommandSensor(void) -{ - bool serviced = true; - - switch (XdrvMailbox.payload) { - case 0: - Settings.SensorBits1.mhz19b_abc_disable = true; - MhzSendCmd(MHZ_CMND_ABCDISABLE); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); - break; - case 1: - Settings.SensorBits1.mhz19b_abc_disable = false; - MhzSendCmd(MHZ_CMND_ABCENABLE); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); - break; - case 2: - MhzSendCmd(MHZ_CMND_ZEROPOINT); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); - break; - case 9: - MhzSendCmd(MHZ_CMND_RESET); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); - break; - case 1000: - MhzSendCmd(MHZ_CMND_RANGE_1000); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_1000); - break; - case 2000: - MhzSendCmd(MHZ_CMND_RANGE_2000); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_2000); - break; - case 3000: - MhzSendCmd(MHZ_CMND_RANGE_3000); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_3000); - break; - case 5000: - MhzSendCmd(MHZ_CMND_RANGE_5000); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); - break; - default: - if (!Settings.SensorBits1.mhz19b_abc_disable) { - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); - } else { - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); - } - } - - return serviced; -} - - - -void MhzInit(void) -{ - mhz_type = 0; - if ((pin[GPIO_MHZ_RXD] < 99) && (pin[GPIO_MHZ_TXD] < 99)) { - MhzSerial = new TasmotaSerial(pin[GPIO_MHZ_RXD], pin[GPIO_MHZ_TXD], 1); - if (MhzSerial->begin(9600)) { - if (MhzSerial->hardwareSerial()) { ClaimSerial(); } - mhz_type = 1; - } - - } -} - -void MhzShow(bool json) -{ - char types[7] = "MHZ19B"; - char temperature[33]; - dtostrfd(mhz_temperature, Settings.flag2.temperature_resolution, temperature); - char model[3]; - GetTextIndexed(model, sizeof(model), mhz_type -1, kMhzModels); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), types, model, mhz_last_ppm, temperature); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm); - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2, types, mhz_last_ppm); - WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); -#endif - } -} - - - - - -bool Xsns15(uint8_t function) -{ - bool result = false; - - if (mhz_type) { - switch (function) { - case FUNC_INIT: - MhzInit(); - break; - case FUNC_EVERY_SECOND: - MhzEverySecond(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_15 == XdrvMailbox.index) { - result = MhzCommandSensor(); - } - break; - case FUNC_JSON_APPEND: - MhzShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MhzShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_16_tsl2561.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_16_tsl2561.ino" -#ifdef USE_I2C -#ifdef USE_TSL2561 -# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_16_tsl2561.ino" -#define XSNS_16 16 - -#include - -Tsl2561 Tsl(Wire); - -uint8_t tsl2561_type = 0; -uint8_t tsl2561_valid = 0; -uint32_t tsl2561_milliLux = 0; -char tsl2561_types[] = "TSL2561"; - -bool Tsl2561Read(void) -{ - if (tsl2561_valid) { tsl2561_valid--; } - - uint8_t id; - bool gain; - Tsl2561::exposure_t exposure; - uint16_t scaledFull, scaledIr; - uint32_t full, ir; - - if (Tsl.on()) { - if (Tsl.id(id) - && Tsl2561Util::autoGain(Tsl, gain, exposure, scaledFull, scaledIr) - && Tsl2561Util::normalizedLuminosity(gain, exposure, full = scaledFull, ir = scaledIr) - && Tsl2561Util::milliLux(full, ir, tsl2561_milliLux, Tsl2561::packageCS(id))) { - } else{ - tsl2561_milliLux = 0; - } - } - tsl2561_valid = SENSOR_MAX_MISS; - return true; -} - -void Tsl2561Detect(void) -{ - if (tsl2561_type) { return; } - uint8_t id; - - if (I2cDevice(0x29) || I2cDevice(0x39) || I2cDevice(0x49)) { - Tsl.begin(); - if (!Tsl.id(id)) return; - if (Tsl.on()) { - tsl2561_type = 1; - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, tsl2561_types, Tsl.address(), id); - } - } -} - -void Tsl2561EverySecond(void) -{ - if (90 == (uptime %100)) { - - Tsl2561Detect(); - } - else if (!(uptime %2)) { - - if (tsl2561_type) { - if (!Tsl2561Read()) { - AddLogMissed(tsl2561_types, tsl2561_valid); - if (!tsl2561_valid) { tsl2561_type = 0; } - } - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_TSL2561[] PROGMEM = - "{s}TSL2561 " D_ILLUMINANCE "{m}%u.%03u " D_UNIT_LUX "{e}"; -#endif - -void Tsl2561Show(bool json) -{ - if (tsl2561_valid) { - if (json) { - ResponseAppend_P(PSTR(",\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), - tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, (tsl2561_milliLux + 500) / 1000); } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TSL2561, tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); -#endif - } - } -} - - - - - -bool Xsns16(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - Tsl2561Detect(); - break; - case FUNC_EVERY_SECOND: - Tsl2561EverySecond(); - break; - case FUNC_JSON_APPEND: - Tsl2561Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Tsl2561Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_17_senseair.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_17_senseair.ino" -#ifdef USE_SENSEAIR -# 29 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_17_senseair.ino" -#define XSNS_17 17 - -#define SENSEAIR_MODBUS_SPEED 9600 -#define SENSEAIR_DEVICE_ADDRESS 0xFE -#define SENSEAIR_READ_REGISTER 0x04 - -#ifndef CO2_LOW -#define CO2_LOW 800 -#endif -#ifndef CO2_HIGH -#define CO2_HIGH 1200 -#endif - -#include -TasmotaModbus *SenseairModbus; - -const char kSenseairTypes[] PROGMEM = "Kx0|S8"; - -uint8_t senseair_type = 1; -char senseair_types[7]; - -uint16_t senseair_co2 = 0; -float senseair_temperature = 0; -float senseair_humidity = 0; - - - -const uint8_t start_addresses[] { 0x1A, 0x00, 0x03, 0x04, 0x05, 0x1C, 0x0A }; - -uint8_t senseair_read_state = 0; -uint8_t senseair_send_retry = 0; - -void Senseair250ms(void) -{ - - - - - uint16_t value = 0; - bool data_ready = SenseairModbus->ReceiveReady(); - - if (data_ready) { - uint8_t error = SenseairModbus->Receive16BitRegister(&value); - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir response error %d"), error); - } else { - switch(senseair_read_state) { - case 0: - senseair_type = 2; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir type id low %04X"), value); - break; - case 1: - if (value) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir error %04X"), value); - } - break; - case 2: - senseair_co2 = value; - LightSetSignal(CO2_LOW, CO2_HIGH, senseair_co2); - break; - case 3: - senseair_temperature = ConvertTemp((float)value / 100); - break; - case 4: - senseair_humidity = ConvertHumidity((float)value / 100); - break; - case 5: - { - bool relay_state = value >> 8 & 1; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir relay state %d"), relay_state); - break; - } - case 6: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir temp adjustment %d"), value); - break; - } - } - senseair_read_state++; - if (2 == senseair_type) { - if (3 == senseair_read_state) { - senseair_read_state = 1; - } - } else { - if (sizeof(start_addresses) == senseair_read_state) { - senseair_read_state = 1; - } - } - } - - if (0 == senseair_send_retry || data_ready) { - senseair_send_retry = 5; - SenseairModbus->Send(SENSEAIR_DEVICE_ADDRESS, SENSEAIR_READ_REGISTER, (uint16_t)start_addresses[senseair_read_state], 1); - } else { - senseair_send_retry--; - } - - -} - - - -void SenseairInit(void) -{ - senseair_type = 0; - if ((pin[GPIO_SAIR_RX] < 99) && (pin[GPIO_SAIR_TX] < 99)) { - SenseairModbus = new TasmotaModbus(pin[GPIO_SAIR_RX], pin[GPIO_SAIR_TX]); - uint8_t result = SenseairModbus->Begin(SENSEAIR_MODBUS_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - senseair_type = 1; - } - } -} - -void SenseairShow(bool json) -{ - char temperature[33]; - dtostrfd(senseair_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(senseair_humidity, Settings.flag2.temperature_resolution, humidity); - GetTextIndexed(senseair_types, sizeof(senseair_types), senseair_type -1, kSenseairTypes); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d"), senseair_types, senseair_co2); - if (senseair_type != 2) { - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), temperature, humidity); - } - ResponseJsonEnd(); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, senseair_co2); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2, senseair_types, senseair_co2); - if (senseair_type != 2) { - WSContentSend_PD(HTTP_SNS_TEMP, senseair_types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, senseair_types, humidity); - } -#endif - } -} - - - - - -bool Xsns17(uint8_t function) -{ - bool result = false; - - if (senseair_type) { - switch (function) { - case FUNC_INIT: - SenseairInit(); - break; - case FUNC_EVERY_250_MSECOND: - Senseair250ms(); - break; - case FUNC_JSON_APPEND: - SenseairShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SenseairShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_18_pms5003.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_18_pms5003.ino" -#ifdef USE_PMS5003 - - - - - - - -#define XSNS_18 18 - -#include - -TasmotaSerial *PmsSerial; - -uint8_t pms_type = 1; -uint8_t pms_valid = 0; - -struct pms5003data { - uint16_t framelen; - uint16_t pm10_standard, pm25_standard, pm100_standard; - uint16_t pm10_env, pm25_env, pm100_env; - uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um; - uint16_t unused; - uint16_t checksum; -} pms_data; - - - -bool PmsReadData(void) -{ - if (! PmsSerial->available()) { - return false; - } - while ((PmsSerial->peek() != 0x42) && PmsSerial->available()) { - PmsSerial->read(); - } - if (PmsSerial->available() < 32) { - return false; - } - - uint8_t buffer[32]; - uint16_t sum = 0; - PmsSerial->readBytes(buffer, 32); - PmsSerial->flush(); - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 32); - - - for (uint32_t i = 0; i < 30; i++) { - sum += buffer[i]; - } - - uint16_t buffer_u16[15]; - for (uint32_t i = 0; i < 15; i++) { - buffer_u16[i] = buffer[2 + i*2 + 1]; - buffer_u16[i] += (buffer[2 + i*2] << 8); - } - if (sum != buffer_u16[14]) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("PMS: " D_CHECKSUM_FAILURE)); - return false; - } - - memcpy((void *)&pms_data, (void *)buffer_u16, 30); - pms_valid = 10; - - return true; -} - - - -void PmsSecond(void) -{ - if (PmsReadData()) { - pms_valid = 10; - } else { - if (pms_valid) { - pms_valid--; - } - } -} - - - -void PmsInit(void) -{ - pms_type = 0; - if (pin[GPIO_PMS5003] < 99) { - PmsSerial = new TasmotaSerial(pin[GPIO_PMS5003], -1, 1); - if (PmsSerial->begin(9600)) { - if (PmsSerial->hardwareSerial()) { ClaimSerial(); } - pms_type = 1; - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_PMS5003_SNS[] PROGMEM = - - - - "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 0.3 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 0.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"; -#endif - -void PmsShow(bool json) -{ - if (pms_valid) { - if (json) { - ResponseAppend_P(PSTR(",\"PMS5003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d,\"PB0.3\":%d,\"PB0.5\":%d,\"PB1\":%d,\"PB2.5\":%d,\"PB5\":%d,\"PB10\":%d}"), - pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, - pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, - pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_COUNT, pms_data.pm10_env); - DomoticzSensor(DZ_VOLTAGE, pms_data.pm25_env); - DomoticzSensor(DZ_CURRENT, pms_data.pm100_env); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_PMS5003_SNS, - - pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, - pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); -#endif - } - } -} - - - - - -bool Xsns18(uint8_t function) -{ - bool result = false; - - if (pms_type) { - switch (function) { - case FUNC_INIT: - PmsInit(); - break; - case FUNC_EVERY_SECOND: - PmsSecond(); - break; - case FUNC_JSON_APPEND: - PmsShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - PmsShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_19_mgs.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_19_mgs.ino" -#ifdef USE_I2C -#ifdef USE_MGS - - - - - - - -#define XSNS_19 19 - -#ifndef MGS_SENSOR_ADDR -#define MGS_SENSOR_ADDR 0x04 -#endif - -#include "MutichannelGasSensor.h" - -void MGSInit(void) { - gas.begin(MGS_SENSOR_ADDR); -} - -bool MGSPrepare(void) -{ - gas.begin(MGS_SENSOR_ADDR); - if (!gas.isError()) { - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "MultiGasSensor", MGS_SENSOR_ADDR); - return true; - } else { - return false; - } -} - -char* measure_gas(int gas_type, char* buffer) -{ - float f = gas.calcGas(gas_type); - dtostrfd(f, 2, buffer); - return buffer; -} - -#ifdef USE_WEBSERVER -const char HTTP_MGS_GAS[] PROGMEM = "{s}MGS %s{m}%s " D_UNIT_PARTS_PER_MILLION "{e}"; -#endif - -void MGSShow(bool json) -{ - char buffer[33]; - if (json) { - ResponseAppend_P(PSTR(",\"MGS\":{\"NH3\":%s"), measure_gas(NH3, buffer)); - ResponseAppend_P(PSTR(",\"CO\":%s"), measure_gas(CO, buffer)); - ResponseAppend_P(PSTR(",\"NO2\":%s"), measure_gas(NO2, buffer)); - ResponseAppend_P(PSTR(",\"C3H8\":%s"), measure_gas(C3H8, buffer)); - ResponseAppend_P(PSTR(",\"C4H10\":%s"), measure_gas(C4H10, buffer)); - ResponseAppend_P(PSTR(",\"CH4\":%s"), measure_gas(GAS_CH4, buffer)); - ResponseAppend_P(PSTR(",\"H2\":%s"), measure_gas(H2, buffer)); - ResponseAppend_P(PSTR(",\"C2H5OH\":%s}"), measure_gas(C2H5OH, buffer)); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_MGS_GAS, "NH3", measure_gas(NH3, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "CO", measure_gas(CO, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "NO2", measure_gas(NO2, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "C3H8", measure_gas(C3H8, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "C4H10", measure_gas(C4H10, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "CH4", measure_gas(GAS_CH4, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "H2", measure_gas(H2, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "C2H5OH", measure_gas(C2H5OH, buffer)); -#endif - } -} - - - - - -bool Xsns19(uint8_t function) -{ - bool result = false; - static int detected = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - - break; - case FUNC_PREP_BEFORE_TELEPERIOD: - detected = MGSPrepare(); - break; - case FUNC_JSON_APPEND: - if (detected) MGSShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - if (detected) MGSShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_20_novasds.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_20_novasds.ino" -#ifdef USE_NOVA_SDS -# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_20_novasds.ino" -#define XSNS_20 20 - -#include - -#ifndef WORKING_PERIOD -#define WORKING_PERIOD 5 -#endif -#ifndef NOVA_SDS_REINIT_CHECK -#define NOVA_SDS_REINIT_CHECK 80 -#endif -#ifndef NOVA_SDS_QUERY_INTERVAL -#define NOVA_SDS_QUERY_INTERVAL 3 -#endif -#ifndef NOVA_SDS_RECDATA_TIMEOUT -#define NOVA_SDS_RECDATA_TIMEOUT 150 -#endif -#ifndef NOVA_SDS_DEVICE_ID -#define NOVA_SDS_DEVICE_ID 0xFFFF -#endif - -TasmotaSerial *NovaSdsSerial; - -uint8_t novasds_type = 1; -uint8_t novasds_valid = 0; - -struct sds011data { - uint16_t pm100; - uint16_t pm25; -} novasds_data; - - -#define NOVA_SDS_REPORTING_MODE 2 -#define NOVA_SDS_QUERY_DATA 4 -#define NOVA_SDS_SET_DEVICE_ID 5 -#define NOVA_SDS_SLEEP_AND_WORK 6 -#define NOVA_SDS_WORKING_PERIOD 8 -#define NOVA_SDS_CHECK_FIRMWARE_VER 7 - #define NOVA_SDS_QUERY_MODE 0 - #define NOVA_SDS_SET_MODE 1 - #define NOVA_SDS_REPORT_ACTIVE 0 - #define NOVA_SDS_REPORT_QUERY 1 - #define NOVA_SDS_WORK 0 - #define NOVA_SDS_SLEEP 1 - - -bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer) -{ - uint8_t novasds_cmnd[19] = {0xAA, 0xB4, byte1, byte2, byte3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (uint8_t)(sensorid & 0xFF), (uint8_t)((sensorid>>8) & 0xFF), 0x00, 0xAB}; - - - for (uint32_t i = 2; i < 17; i++) { - novasds_cmnd[17] += novasds_cmnd[i]; - } - - - - - - NovaSdsSerial->write(novasds_cmnd, sizeof(novasds_cmnd)); - NovaSdsSerial->flush(); - - - unsigned long cmndtime = millis(); - while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( ! NovaSdsSerial->available() ) ); - if ( ! NovaSdsSerial->available() ) { - - return false; - } - uint8_t recbuf[10]; - memset(recbuf, 0, sizeof(recbuf)); - - while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( NovaSdsSerial->available() > 0) && (0xAA != (recbuf[0] = NovaSdsSerial->read())) ); - if ( 0xAA != recbuf[0] ) { - - return false; - } - - - NovaSdsSerial->readBytes(&recbuf[1], 9); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, recbuf, sizeof(recbuf)); - - if ( nullptr != buffer ) { - - memcpy(buffer, recbuf, sizeof(recbuf)); - } - - - if ((0xAB != recbuf[9] ) || (recbuf[8] != ((recbuf[2] + recbuf[3] + recbuf[4] + recbuf[5] + recbuf[6] + recbuf[7]) & 0xFF))) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("SDS: " D_CHECKSUM_FAILURE)); - return false; - } - - return true; -} - -void NovaSdsSetWorkPeriod(void) -{ - - NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, Settings.novasds_period, NOVA_SDS_DEVICE_ID, nullptr); - - NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); -} - -bool NovaSdsReadData(void) -{ - uint8_t d[10]; - if ( ! NovaSdsCommand(NOVA_SDS_QUERY_DATA, 0, 0, NOVA_SDS_DEVICE_ID, d) ) { - return false; - } - novasds_data.pm25 = (d[2] + 256 * d[3]); - novasds_data.pm100 = (d[4] + 256 * d[5]); - - return true; -} - - - -void NovaSdsSecond(void) -{ - if (0 == (uptime % NOVA_SDS_REINIT_CHECK)) { - if (!novasds_valid) { - NovaSdsSetWorkPeriod(); - } - } else if (0 == (uptime % NOVA_SDS_QUERY_INTERVAL)) { - if (NovaSdsReadData()) { - novasds_valid = 10; - } else { - if (novasds_valid) { - novasds_valid--; - } - } - } -} - - - - - - - -bool NovaSdsCommandSensor(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 256)) { - Settings.novasds_period = XdrvMailbox.payload; - NovaSdsSetWorkPeriod(); - } - Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_20, Settings.novasds_period); - - return true; -} - -void NovaSdsInit(void) -{ - novasds_type = 0; - if (pin[GPIO_SDS0X1_RX] < 99 && pin[GPIO_SDS0X1_TX] < 99) { - NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1_RX], pin[GPIO_SDS0X1_TX], 1); - if (NovaSdsSerial->begin(9600)) { - if (NovaSdsSerial->hardwareSerial()) { - ClaimSerial(); - } - novasds_type = 1; - NovaSdsSetWorkPeriod(); - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SDS0X1_SNS[] PROGMEM = - "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; -#endif - -void NovaSdsShow(bool json) -{ - if (novasds_valid) { - float pm10f = (float)(novasds_data.pm100) / 10.0f; - float pm2_5f = (float)(novasds_data.pm25) / 10.0f; - char pm10[33]; - dtostrfd(pm10f, 1, pm10); - char pm2_5[33]; - dtostrfd(pm2_5f, 1, pm2_5); - if (json) { - ResponseAppend_P(PSTR(",\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), pm2_5, pm10); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_VOLTAGE, pm2_5); - DomoticzSensor(DZ_CURRENT, pm10); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SDS0X1_SNS, pm2_5, pm10); -#endif - } - } -} - - - - - -bool Xsns20(uint8_t function) -{ - bool result = false; - - if (novasds_type) { - switch (function) { - case FUNC_INIT: - NovaSdsInit(); - break; - case FUNC_EVERY_SECOND: - NovaSdsSecond(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_20 == XdrvMailbox.index) { - result = NovaSdsCommandSensor(); - } - break; - case FUNC_JSON_APPEND: - NovaSdsShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - NovaSdsShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_21_sgp30.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_21_sgp30.ino" -#ifdef USE_I2C -#ifdef USE_SGP30 -# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_21_sgp30.ino" -#define XSNS_21 21 - -#include "Adafruit_SGP30.h" -Adafruit_SGP30 sgp; - -uint8_t sgp30_type = 0; -uint8_t sgp30_ready = 0; -float sgp30_abshum; - - - -void sgp30_Init(void) { - if (sgp.begin()) { - sgp30_type = 1; - - - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "SGP30", 0x58); - AddLog(LOG_LEVEL_DEBUG); - } -} - - -#define POW_FUNC FastPrecisePow - -float sgp30_AbsoluteHumidity(float temperature, float humidity,char tempUnit) { - - - - - - float temp = NAN; - const float mw = 18.01534; - const float r = 8.31447215; - - if (isnan(temperature) || isnan(humidity) ) { - return NAN; - } - - if (tempUnit != 'C') { - temperature = (temperature - 32.0) * (5.0 / 9.0); - } - - temp = POW_FUNC(2.718281828, (17.67 * temperature) / (temperature + 243.5)); - - - - - return (6.112 * temp * humidity * mw) / ((273.15 + temperature) * r); -} - -#define SAVE_PERIOD 30 - -void Sgp30Update(void) -{ - sgp30_ready = 0; - if (!sgp.IAQmeasure() || !sgp30_type) { - - if (21 == (uptime %100)) { - sgp30_Init(); - } - return; - } - if (global_update && global_humidity>0 && global_temperature!=9999) { - - sgp30_abshum=sgp30_AbsoluteHumidity(global_temperature,global_humidity,TempUnit()); - sgp.setHumidity(sgp30_abshum*1000); - } - sgp30_ready = 1; - - - if (!(uptime%SAVE_PERIOD)) { - - uint16_t TVOC_base; - uint16_t eCO2_base; - - if (!sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) return; - - - - } -} - - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SGP30[] PROGMEM = - "{s}SGP30 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" - "{s}SGP30 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; -const char HTTP_SNS_AHUM[] PROGMEM = "{s}SGP30 " "Abs Humidity" "{m}%s g/m3{e}"; -#endif - -#define D_JSON_AHUM "aHumidity" - -void Sgp30Show(bool json) -{ - if (sgp30_ready) { - char abs_hum[33]; - - if (json) { - ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d"), sgp.eCO2, sgp.TVOC); - if (global_update && global_humidity>0 && global_temperature!=9999) { - - dtostrfd(sgp30_abshum,4,abs_hum); - ResponseAppend_P(PSTR(",\"" D_JSON_AHUM "\":%s"),abs_hum); - } - ResponseJsonEnd(); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, sgp.eCO2); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_SGP30, sgp.eCO2, sgp.TVOC); - if (global_update) { - WSContentSend_PD(HTTP_SNS_AHUM, abs_hum); - } -#endif - } - } -} - - - - - - -bool Xsns21(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - sgp30_Init(); - break; - case FUNC_EVERY_SECOND: - Sgp30Update(); - break; - case FUNC_JSON_APPEND: - Sgp30Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sgp30Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_22_sr04.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_22_sr04.ino" -#ifdef USE_SR04 - -#include -# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_22_sr04.ino" -#define XSNS_22 22 - -uint8_t sr04_echo_pin = 0; -uint8_t sr04_trig_pin = 0; -real64_t distance; - -NewPing* sonar = nullptr; - -void Sr04Init(void) -{ - sr04_echo_pin = pin[GPIO_SR04_ECHO]; - sr04_trig_pin = pin[GPIO_SR04_TRIG]; - sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300); -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_DISTANCE[] PROGMEM = - "{s}SR04 " D_DISTANCE "{m}%s" D_UNIT_CENTIMETER "{e}"; -#endif - -void Sr04Show(bool json) -{ - distance = (real64_t)(sonar->ping_median(5))/ US_ROUNDTRIP_CM; - - if (distance != 0) { - char distance_chr[33]; - dtostrfd(distance, 3, distance_chr); - - if(json) { - ResponseAppend_P(PSTR(",\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), distance_chr); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_COUNT, distance_chr); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_DISTANCE, distance_chr); -#endif - } - } -} - - - - - -bool Xsns22(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_SR04_ECHO] < 99) && (pin[GPIO_SR04_TRIG] < 99)) { - switch (function) { - case FUNC_INIT: - Sr04Init(); - break; - case FUNC_JSON_APPEND: - Sr04Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sr04Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_23_sdm120.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_23_sdm120.ino" -#ifdef USE_SDM120 - - - - - - - -#define XSNS_23 23 - - -#ifndef SDM120_SPEED - #define SDM120_SPEED 2400 -#endif - -#ifndef SDM120_ADDR - #define SDM120_ADDR 1 -#endif - - -#include - -enum SDM120_Error {SDM120_ERR_NO_ERROR=0, SDM120_ERR_CRC_ERROR, SDM120_ERR_WRONG_BYTES, SDM120_ERR_NOT_ENOUGHT_BYTES}; - -TasmotaSerial *SDM120Serial; - -uint8_t sdm120_type = 1; - - -float sdm120_voltage = 0; -float sdm120_current = 0; -float sdm120_active_power = 0; -float sdm120_apparent_power = 0; -float sdm120_reactive_power = 0; -float sdm120_power_factor = 0; -float sdm120_frequency = 0; -float sdm120_energy_total = 0; -float sdm120_phase_angle = 0; -float sdm120_import_active = 0; -float sdm120_export_active = 0; -float sdm120_import_reactive = 0; -float sdm120_export_reactive = 0; -float sdm120_total_reactive = 0; - -bool SDM120_ModbusReceiveReady(void) -{ - return (SDM120Serial->available() > 1); -} - -void SDM120_ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count) -{ - uint8_t frame[8]; - - frame[0] = SDM120_ADDR; - frame[1] = function_code; - frame[2] = (uint8_t)(start_address >> 8); - frame[3] = (uint8_t)(start_address); - frame[4] = (uint8_t)(register_count >> 8); - frame[5] = (uint8_t)(register_count); - - uint16_t crc = SDM120_calculateCRC(frame, 6); - frame[6] = lowByte(crc); - frame[7] = highByte(crc); - - while (SDM120Serial->available() > 0) { - SDM120Serial->read(); - } - - SDM120Serial->flush(); - SDM120Serial->write(frame, sizeof(frame)); -} - -uint8_t SDM120_ModbusReceive(float *value) -{ - uint8_t buffer[9]; - - *value = NAN; - uint8_t len = 0; - while (SDM120Serial->available() > 0) { - buffer[len++] = (uint8_t)SDM120Serial->read(); - } - - if (len < 9) { - return SDM120_ERR_NOT_ENOUGHT_BYTES; - } - - if (9 == len) { - if (0x01 == buffer[0] && 0x04 == buffer[1] && 4 == buffer[2]) { - if((SDM120_calculateCRC(buffer, 7)) == ((buffer[8] << 8) | buffer[7])) { - - ((uint8_t*)value)[3] = buffer[3]; - ((uint8_t*)value)[2] = buffer[4]; - ((uint8_t*)value)[1] = buffer[5]; - ((uint8_t*)value)[0] = buffer[6]; - - } else { - return SDM120_ERR_CRC_ERROR; - } - - } else { - return SDM120_ERR_WRONG_BYTES; - } - } - - return SDM120_ERR_NO_ERROR; -} - -uint16_t SDM120_calculateCRC(uint8_t *frame, uint8_t num) -{ - uint16_t crc, flag; - crc = 0xFFFF; - for (uint32_t i = 0; i < num; i++) { - crc ^= frame[i]; - for (uint32_t j = 8; j; j--) { - if ((crc & 0x0001) != 0) { - crc >>= 1; - crc ^= 0xA001; - } else { - crc >>= 1; - } - } - } - return crc; -} - - - -const uint16_t sdm120_start_addresses[] { - 0x0000, - 0x0006, - 0x000C, - 0x0012, - 0x0018, - 0x001E, - 0x0046, -#ifdef USE_SDM220 - 0x0156, - 0X0024, - 0X0048, - 0X004A, - 0X004C, - 0X004E, - 0X0158 -#else - 0x0156 -#endif -}; - -uint8_t sdm120_read_state = 0; -uint8_t sdm120_send_retry = 0; -uint8_t sdm120_nodata_count = 0; - -void SDM120250ms(void) -{ - - - - - float value = 0; - bool data_ready = SDM120_ModbusReceiveReady(); - - if (data_ready) { - sdm120_nodata_count = 0; - uint8_t error = SDM120_ModbusReceive(&value); - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM120 response error %d"), error); - } else { - switch(sdm120_read_state) { - case 0: - sdm120_voltage = value; - break; - - case 1: - sdm120_current = value; - break; - - case 2: - sdm120_active_power = value; - break; - - case 3: - sdm120_apparent_power = value; - break; - - case 4: - sdm120_reactive_power = value; - break; - - case 5: - sdm120_power_factor = value; - break; - - case 6: - sdm120_frequency = value; - break; - - case 7: - sdm120_energy_total = value; - break; -#ifdef USE_SDM220 - case 8: - sdm120_phase_angle = value; - break; - - case 9: - sdm120_import_active = value; - break; - - case 10: - sdm120_export_active = value; - break; - - case 11: - sdm120_import_reactive = value; - break; - - case 12: - sdm120_export_reactive = value; - break; - - case 13: - sdm120_total_reactive = value; - break; -#endif - } - - sdm120_read_state++; - - if (sizeof(sdm120_start_addresses)/2 == sdm120_read_state) { - sdm120_read_state = 0; - } - } - } - else { - if (sdm120_nodata_count <= (1000/250) * 4) { - sdm120_nodata_count++; - } else if (sdm120_nodata_count != 255) { - - sdm120_nodata_count = 255; - sdm120_voltage = sdm120_current = sdm120_active_power = sdm120_apparent_power = sdm120_reactive_power = sdm120_power_factor = sdm120_frequency = sdm120_energy_total = 0; -#ifdef USE_SDM220 - sdm120_phase_angle = sdm120_import_active = sdm120_export_active = sdm120_import_reactive = sdm120_export_reactive = sdm120_total_reactive = 0; -#endif - } - } - - if (0 == sdm120_send_retry || data_ready) { - sdm120_send_retry = 5; - SDM120_ModbusSend(0x04, sdm120_start_addresses[sdm120_read_state], 2); - } else { - sdm120_send_retry--; - } - -} - -void SDM120Init(void) -{ - sdm120_type = 0; - if ((pin[GPIO_SDM120_RX] < 99) && (pin[GPIO_SDM120_TX] < 99)) { - SDM120Serial = new TasmotaSerial(pin[GPIO_SDM120_RX], pin[GPIO_SDM120_TX], 1); - if (SDM120Serial->begin(SDM120_SPEED)) { - if (SDM120Serial->hardwareSerial()) { ClaimSerial(); } - sdm120_type = 1; - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SDM120_DATA[] PROGMEM = - "{s}SDM120 " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}SDM120 " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}SDM120 " D_POWERUSAGE_ACTIVE "{m}%s " D_UNIT_WATT "{e}" - "{s}SDM120 " D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" - "{s}SDM120 " D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" - "{s}SDM120 " D_POWER_FACTOR "{m}%s{e}" - "{s}SDM120 " D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}" - "{s}SDM120 " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}" -#ifdef USE_SDM220 - "{s}SDM120 " D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}" - "{s}SDM120 " D_IMPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}SDM120 " D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}SDM120 " D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - "{s}SDM120 " D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - "{s}SDM120 " D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" -#endif - ; -#endif - -void SDM120Show(bool json) -{ - char voltage[33]; - dtostrfd(sdm120_voltage, Settings.flag2.voltage_resolution, voltage); - char current[33]; - dtostrfd(sdm120_current, Settings.flag2.current_resolution, current); - char active_power[33]; - dtostrfd(sdm120_active_power, Settings.flag2.wattage_resolution, active_power); - char apparent_power[33]; - dtostrfd(sdm120_apparent_power, Settings.flag2.wattage_resolution, apparent_power); - char reactive_power[33]; - dtostrfd(sdm120_reactive_power, Settings.flag2.wattage_resolution, reactive_power); - char power_factor[33]; - dtostrfd(sdm120_power_factor, 2, power_factor); - char frequency[33]; - dtostrfd(sdm120_frequency, Settings.flag2.frequency_resolution, frequency); - char energy_total[33]; - dtostrfd(sdm120_energy_total, Settings.flag2.energy_resolution, energy_total); -#ifdef USE_SDM220 - char phase_angle[33]; - dtostrfd(sdm120_phase_angle, 2, phase_angle); - char import_active[33]; - dtostrfd(sdm120_import_active, Settings.flag2.wattage_resolution, import_active); - char export_active[33]; - dtostrfd(sdm120_export_active, Settings.flag2.wattage_resolution, export_active); - char import_reactive[33]; - dtostrfd(sdm120_import_reactive,Settings.flag2.wattage_resolution, import_reactive); - char export_reactive[33]; - dtostrfd(sdm120_export_reactive,Settings.flag2.wattage_resolution, export_reactive); - char total_reactive[33]; - dtostrfd(sdm120_total_reactive, Settings.flag2.wattage_resolution, total_reactive); -#endif - if (json) { -#ifdef USE_SDM220 - ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s,\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_EXPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s}"), - energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current, phase_angle, import_active, export_active, import_reactive, export_reactive, total_reactive); -#else - ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), - energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current); -#endif -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - char energy_total_chr[33]; - dtostrfd(sdm120_energy_total * 1000, 1, energy_total_chr); - DomoticzSensor(DZ_VOLTAGE, voltage); - DomoticzSensor(DZ_CURRENT, current); - DomoticzSensorPowerEnergy((int)sdm120_active_power, energy_total_chr); - } -#endif -#ifdef USE_WEBSERVER - } else { -#ifdef USE_SDM220 - WSContentSend_PD(HTTP_SNS_SDM120_DATA, voltage, current, active_power, apparent_power, reactive_power, power_factor, frequency, energy_total, phase_angle,import_active,export_active,import_reactive,export_reactive,total_reactive); -#else - WSContentSend_PD(HTTP_SNS_SDM120_DATA, voltage, current, active_power, apparent_power, reactive_power, power_factor, frequency, energy_total); -#endif -#endif - } -} - - - - - -bool Xsns23(uint8_t function) -{ - bool result = false; - - if (sdm120_type) { - switch (function) { - case FUNC_INIT: - SDM120Init(); - break; - case FUNC_EVERY_250_MSECOND: - SDM120250ms(); - break; - case FUNC_JSON_APPEND: - SDM120Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SDM120Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_24_si1145.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_24_si1145.ino" -#ifdef USE_I2C -#ifdef USE_SI1145 -# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_24_si1145.ino" -#define XSNS_24 24 - -#define SI114X_ADDR 0X60 - - - -#define SI114X_QUERY 0X80 -#define SI114X_SET 0XA0 -#define SI114X_NOP 0X00 -#define SI114X_RESET 0X01 -#define SI114X_BUSADDR 0X02 -#define SI114X_PS_FORCE 0X05 -#define SI114X_GET_CAL 0X12 -#define SI114X_ALS_FORCE 0X06 -#define SI114X_PSALS_FORCE 0X07 -#define SI114X_PS_PAUSE 0X09 -#define SI114X_ALS_PAUSE 0X0A -#define SI114X_PSALS_PAUSE 0X0B -#define SI114X_PS_AUTO 0X0D -#define SI114X_ALS_AUTO 0X0E -#define SI114X_PSALS_AUTO 0X0F - - - -#define SI114X_PART_ID 0X00 -#define SI114X_REV_ID 0X01 -#define SI114X_SEQ_ID 0X02 -#define SI114X_INT_CFG 0X03 -#define SI114X_IRQ_ENABLE 0X04 -#define SI114X_IRQ_MODE1 0x05 -#define SI114X_IRQ_MODE2 0x06 -#define SI114X_HW_KEY 0X07 -#define SI114X_MEAS_RATE0 0X08 -#define SI114X_MEAS_RATE1 0X09 -#define SI114X_PS_RATE 0X0A -#define SI114X_PS_LED21 0X0F -#define SI114X_PS_LED3 0X10 -#define SI114X_UCOEFF0 0X13 -#define SI114X_UCOEFF1 0X14 -#define SI114X_UCOEFF2 0X15 -#define SI114X_UCOEFF3 0X16 -#define SI114X_WR 0X17 -#define SI114X_COMMAND 0X18 -#define SI114X_RESPONSE 0X20 -#define SI114X_IRQ_STATUS 0X21 -#define SI114X_ALS_VIS_DATA0 0X22 -#define SI114X_ALS_VIS_DATA1 0X23 -#define SI114X_ALS_IR_DATA0 0X24 -#define SI114X_ALS_IR_DATA1 0X25 -#define SI114X_PS1_DATA0 0X26 -#define SI114X_PS1_DATA1 0X27 -#define SI114X_PS2_DATA0 0X28 -#define SI114X_PS2_DATA1 0X29 -#define SI114X_PS3_DATA0 0X2A -#define SI114X_PS3_DATA1 0X2B -#define SI114X_AUX_DATA0_UVINDEX0 0X2C -#define SI114X_AUX_DATA1_UVINDEX1 0X2D -#define SI114X_RD 0X2E -#define SI114X_CHIP_STAT 0X30 - - - -#define SI114X_CHLIST 0X01 -#define SI114X_CHLIST_ENUV 0x80 -#define SI114X_CHLIST_ENAUX 0x40 -#define SI114X_CHLIST_ENALSIR 0x20 -#define SI114X_CHLIST_ENALSVIS 0x10 -#define SI114X_CHLIST_ENPS1 0x01 -#define SI114X_CHLIST_ENPS2 0x02 -#define SI114X_CHLIST_ENPS3 0x04 - -#define SI114X_PSLED12_SELECT 0X02 -#define SI114X_PSLED3_SELECT 0X03 - -#define SI114X_PS_ENCODE 0X05 -#define SI114X_ALS_ENCODE 0X06 - -#define SI114X_PS1_ADCMUX 0X07 -#define SI114X_PS2_ADCMUX 0X08 -#define SI114X_PS3_ADCMUX 0X09 - -#define SI114X_PS_ADC_COUNTER 0X0A -#define SI114X_PS_ADC_GAIN 0X0B -#define SI114X_PS_ADC_MISC 0X0C - -#define SI114X_ALS_IR_ADC_MUX 0X0E -#define SI114X_AUX_ADC_MUX 0X0F - -#define SI114X_ALS_VIS_ADC_COUNTER 0X10 -#define SI114X_ALS_VIS_ADC_GAIN 0X11 -#define SI114X_ALS_VIS_ADC_MISC 0X12 - -#define SI114X_LED_REC 0X1C - -#define SI114X_ALS_IR_ADC_COUNTER 0X1D -#define SI114X_ALS_IR_ADC_GAIN 0X1E -#define SI114X_ALS_IR_ADC_MISC 0X1F - - - - -#define SI114X_ADCMUX_SMALL_IR 0x00 -#define SI114X_ADCMUX_VISIABLE 0x02 -#define SI114X_ADCMUX_LARGE_IR 0x03 -#define SI114X_ADCMUX_NO 0x06 -#define SI114X_ADCMUX_GND 0x25 -#define SI114X_ADCMUX_TEMPERATURE 0x65 -#define SI114X_ADCMUX_VDD 0x75 - -#define SI114X_PSLED12_SELECT_PS1_NONE 0x00 -#define SI114X_PSLED12_SELECT_PS1_LED1 0x01 -#define SI114X_PSLED12_SELECT_PS1_LED2 0x02 -#define SI114X_PSLED12_SELECT_PS1_LED3 0x04 -#define SI114X_PSLED12_SELECT_PS2_NONE 0x00 -#define SI114X_PSLED12_SELECT_PS2_LED1 0x10 -#define SI114X_PSLED12_SELECT_PS2_LED2 0x20 -#define SI114X_PSLED12_SELECT_PS2_LED3 0x40 -#define SI114X_PSLED3_SELECT_PS2_NONE 0x00 -#define SI114X_PSLED3_SELECT_PS2_LED1 0x10 -#define SI114X_PSLED3_SELECT_PS2_LED2 0x20 -#define SI114X_PSLED3_SELECT_PS2_LED3 0x40 - -#define SI114X_ADC_GAIN_DIV1 0X00 -#define SI114X_ADC_GAIN_DIV2 0X01 -#define SI114X_ADC_GAIN_DIV4 0X02 -#define SI114X_ADC_GAIN_DIV8 0X03 -#define SI114X_ADC_GAIN_DIV16 0X04 -#define SI114X_ADC_GAIN_DIV32 0X05 - -#define SI114X_LED_CURRENT_5MA 0X01 -#define SI114X_LED_CURRENT_11MA 0X02 -#define SI114X_LED_CURRENT_22MA 0X03 -#define SI114X_LED_CURRENT_45MA 0X04 - -#define SI114X_ADC_COUNTER_1ADCCLK 0X00 -#define SI114X_ADC_COUNTER_7ADCCLK 0X01 -#define SI114X_ADC_COUNTER_15ADCCLK 0X02 -#define SI114X_ADC_COUNTER_31ADCCLK 0X03 -#define SI114X_ADC_COUNTER_63ADCCLK 0X04 -#define SI114X_ADC_COUNTER_127ADCCLK 0X05 -#define SI114X_ADC_COUNTER_255ADCCLK 0X06 -#define SI114X_ADC_COUNTER_511ADCCLK 0X07 - -#define SI114X_ADC_MISC_LOWRANGE 0X00 -#define SI114X_ADC_MISC_HIGHRANGE 0X20 -#define SI114X_ADC_MISC_ADC_NORMALPROXIMITY 0X00 -#define SI114X_ADC_MISC_ADC_RAWADC 0X04 - -#define SI114X_INT_CFG_INTOE 0X01 - -#define SI114X_IRQEN_ALS 0x01 -#define SI114X_IRQEN_PS1 0x04 -#define SI114X_IRQEN_PS2 0x08 -#define SI114X_IRQEN_PS3 0x10 - -uint8_t si1145_type = 0; - - - -uint8_t Si1145ReadByte(uint8_t reg) -{ - return I2cRead8(SI114X_ADDR, reg); -} - -uint16_t Si1145ReadHalfWord(uint8_t reg) -{ - return I2cRead16LE(SI114X_ADDR, reg); -} - -bool Si1145WriteByte(uint8_t reg, uint16_t val) -{ - I2cWrite8(SI114X_ADDR, reg, val); -} - -uint8_t Si1145WriteParamData(uint8_t p, uint8_t v) -{ - Si1145WriteByte(SI114X_WR, v); - Si1145WriteByte(SI114X_COMMAND, p | SI114X_SET); - return Si1145ReadByte(SI114X_RD); -} - - - -bool Si1145Present(void) -{ - return (Si1145ReadByte(SI114X_PART_ID) == 0X45); -} - -void Si1145Reset(void) -{ - Si1145WriteByte(SI114X_MEAS_RATE0, 0); - Si1145WriteByte(SI114X_MEAS_RATE1, 0); - Si1145WriteByte(SI114X_IRQ_ENABLE, 0); - Si1145WriteByte(SI114X_IRQ_MODE1, 0); - Si1145WriteByte(SI114X_IRQ_MODE2, 0); - Si1145WriteByte(SI114X_INT_CFG, 0); - Si1145WriteByte(SI114X_IRQ_STATUS, 0xFF); - - Si1145WriteByte(SI114X_COMMAND, SI114X_RESET); - delay(10); - Si1145WriteByte(SI114X_HW_KEY, 0x17); - delay(10); -} - -void Si1145DeInit(void) -{ - - - Si1145WriteByte(SI114X_UCOEFF0, 0x29); - Si1145WriteByte(SI114X_UCOEFF1, 0x89); - Si1145WriteByte(SI114X_UCOEFF2, 0x02); - Si1145WriteByte(SI114X_UCOEFF3, 0x00); - Si1145WriteParamData(SI114X_CHLIST, SI114X_CHLIST_ENUV | SI114X_CHLIST_ENALSIR | SI114X_CHLIST_ENALSVIS | SI114X_CHLIST_ENPS1); - - - - Si1145WriteParamData(SI114X_PS1_ADCMUX, SI114X_ADCMUX_LARGE_IR); - Si1145WriteByte(SI114X_PS_LED21, SI114X_LED_CURRENT_22MA); - Si1145WriteParamData(SI114X_PSLED12_SELECT, SI114X_PSLED12_SELECT_PS1_LED1); - - - - Si1145WriteParamData(SI114X_PS_ADC_GAIN, SI114X_ADC_GAIN_DIV1); - Si1145WriteParamData(SI114X_PS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); - Si1145WriteParamData(SI114X_PS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE | SI114X_ADC_MISC_ADC_RAWADC); - - - - Si1145WriteParamData(SI114X_ALS_VIS_ADC_GAIN, SI114X_ADC_GAIN_DIV1); - Si1145WriteParamData(SI114X_ALS_VIS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); - Si1145WriteParamData(SI114X_ALS_VIS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE); - - - - Si1145WriteParamData(SI114X_ALS_IR_ADC_GAIN, SI114X_ADC_GAIN_DIV1); - Si1145WriteParamData(SI114X_ALS_IR_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); - Si1145WriteParamData(SI114X_ALS_IR_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE); - - - - Si1145WriteByte(SI114X_INT_CFG, SI114X_INT_CFG_INTOE); - Si1145WriteByte(SI114X_IRQ_ENABLE, SI114X_IRQEN_ALS); - - - - Si1145WriteByte(SI114X_MEAS_RATE0, 0xFF); - Si1145WriteByte(SI114X_COMMAND, SI114X_PSALS_AUTO); -} - -bool Si1145Begin(void) -{ - if (!Si1145Present()) { return false; } - - Si1145Reset(); - Si1145DeInit(); - return true; -} - - -uint16_t Si1145ReadUV(void) -{ - return Si1145ReadHalfWord(SI114X_AUX_DATA0_UVINDEX0); -} - - -uint16_t Si1145ReadVisible(void) -{ - return Si1145ReadHalfWord(SI114X_ALS_VIS_DATA0); -} - - -uint16_t Si1145ReadIR(void) -{ - return Si1145ReadHalfWord(SI114X_ALS_IR_DATA0); -} - - - -void Si1145Update(void) -{ - if (!si1145_type) { - if (Si1145Begin()) { - si1145_type = 1; - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "SI1145", SI114X_ADDR); - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SI1145[] PROGMEM = - "{s}SI1145 " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}" - "{s}SI1145 " D_INFRARED "{m}%d " D_UNIT_LUX "{e}" - "{s}SI1145 " D_UV_INDEX "{m}%d.%d{e}"; -#endif - -void Si1145Show(bool json) -{ - if (si1145_type && Si1145Present()) { - uint16_t visible = Si1145ReadVisible(); - uint16_t infrared = Si1145ReadIR(); - uint16_t uvindex = Si1145ReadUV(); - if (json) { - ResponseAppend_P(PSTR(",\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), - visible, infrared, uvindex /100, uvindex %100); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, visible); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_SI1145, visible, infrared, uvindex /100, uvindex %100); -#endif - } - } else { - si1145_type = 0; - } -} - - - - - -bool Xsns24(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_EVERY_SECOND: - Si1145Update(); - break; - case FUNC_JSON_APPEND: - Si1145Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Si1145Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_25_sdm630.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_25_sdm630.ino" -#ifdef USE_SDM630 - - - - - - - -#define XSNS_25 25 - -#include - -TasmotaSerial *SDM630Serial; - -uint8_t sdm630_type = 1; - - -float sdm630_voltage[] = {0,0,0}; -float sdm630_current[] = {0,0,0}; -float sdm630_active_power[] = {0,0,0}; -float sdm630_reactive_power[] = {0,0,0}; -float sdm630_power_factor[] = {0,0,0}; -float sdm630_energy_total = 0; - -bool SDM630_ModbusReceiveReady(void) -{ - return (SDM630Serial->available() > 1); -} - -void SDM630_ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count) -{ - uint8_t frame[8]; - - frame[0] = 0x01; - frame[1] = function_code; - frame[2] = (uint8_t)(start_address >> 8); - frame[3] = (uint8_t)(start_address); - frame[4] = (uint8_t)(register_count >> 8); - frame[5] = (uint8_t)(register_count); - - uint16_t crc = SDM630_calculateCRC(frame, 6); - frame[6] = lowByte(crc); - frame[7] = highByte(crc); - - while (SDM630Serial->available() > 0) { - SDM630Serial->read(); - } - - SDM630Serial->flush(); - SDM630Serial->write(frame, sizeof(frame)); -} - -uint8_t SDM630_ModbusReceive(float *value) -{ - uint8_t buffer[9]; - - *value = NAN; - uint8_t len = 0; - while (SDM630Serial->available() > 0) { - buffer[len++] = (uint8_t)SDM630Serial->read(); - } - - if (len < 9) - return 3; - - if (len == 9) { - - if (buffer[0] == 0x01 && buffer[1] == 0x04 && buffer[2] == 4) { - - if((SDM630_calculateCRC(buffer, 7)) == ((buffer[8] << 8) | buffer[7])) { - - ((uint8_t*)value)[3] = buffer[3]; - ((uint8_t*)value)[2] = buffer[4]; - ((uint8_t*)value)[1] = buffer[5]; - ((uint8_t*)value)[0] = buffer[6]; - - } else return 1; - - } else return 2; - } - - return 0; -} - -uint16_t SDM630_calculateCRC(uint8_t *frame, uint8_t num) -{ - uint16_t crc, flag; - crc = 0xFFFF; - for (uint32_t i = 0; i < num; i++) { - crc ^= frame[i]; - for (uint32_t j = 8; j; j--) { - if ((crc & 0x0001) != 0) { - crc >>= 1; - crc ^= 0xA001; - } else { - crc >>= 1; - } - } - } - return crc; -} - - - -const uint16_t sdm630_start_addresses[] { - 0x0000, - 0x0002, - 0x0004, - 0x0006, - 0x0008, - 0x000A, - 0x000C, - 0x000E, - 0x0010, - 0x0018, - 0x001A, - 0x001C, - 0x001E, - 0x0020, - 0x0022, - 0x0156 -}; - -uint8_t sdm630_read_state = 0; -uint8_t sdm630_send_retry = 0; - -void SDM630250ms(void) -{ - - - - - float value = 0; - bool data_ready = SDM630_ModbusReceiveReady(); - - if (data_ready) { - uint8_t error = SDM630_ModbusReceive(&value); - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM630 response error %d"), error); - } else { - switch(sdm630_read_state) { - case 0: - sdm630_voltage[0] = value; - break; - - case 1: - sdm630_voltage[1] = value; - break; - - case 2: - sdm630_voltage[2] = value; - break; - - case 3: - sdm630_current[0] = value; - break; - - case 4: - sdm630_current[1] = value; - break; - - case 5: - sdm630_current[2] = value; - break; - - case 6: - sdm630_active_power[0] = value; - break; - - case 7: - sdm630_active_power[1] = value; - break; - - case 8: - sdm630_active_power[2] = value; - break; - - case 9: - sdm630_reactive_power[0] = value; - break; - - case 10: - sdm630_reactive_power[1] = value; - break; - - case 11: - sdm630_reactive_power[2] = value; - break; - - case 12: - sdm630_power_factor[0] = value; - break; - - case 13: - sdm630_power_factor[1] = value; - break; - - case 14: - sdm630_power_factor[2] = value; - break; - - case 15: - sdm630_energy_total = value; - break; - } - - sdm630_read_state++; - - if (sizeof(sdm630_start_addresses)/2 == sdm630_read_state) { - sdm630_read_state = 0; - } - } - } - - if (0 == sdm630_send_retry || data_ready) { - sdm630_send_retry = 5; - SDM630_ModbusSend(0x04, sdm630_start_addresses[sdm630_read_state], 2); - } else { - sdm630_send_retry--; - } - -} - -void SDM630Init(void) -{ - sdm630_type = 0; - if ((pin[GPIO_SDM630_RX] < 99) && (pin[GPIO_SDM630_TX] < 99)) { - SDM630Serial = new TasmotaSerial(pin[GPIO_SDM630_RX], pin[GPIO_SDM630_TX], 1); -#ifdef SDM630_SPEED - if (SDM630Serial->begin(SDM630_SPEED)) { -#else - if (SDM630Serial->begin(2400)) { -#endif - if (SDM630Serial->hardwareSerial()) { ClaimSerial(); } - sdm630_type = 1; - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SDM630_DATA[] PROGMEM = - "{s}SDM630 " D_VOLTAGE "{m}%s/%s/%s " D_UNIT_VOLT "{e}" - "{s}SDM630 " D_CURRENT "{m}%s/%s/%s " D_UNIT_AMPERE "{e}" - "{s}SDM630 " D_POWERUSAGE_ACTIVE "{m}%s/%s/%s " D_UNIT_WATT "{e}" - "{s}SDM630 " D_POWERUSAGE_REACTIVE "{m}%s/%s/%s " D_UNIT_VAR "{e}" - "{s}SDM630 " D_POWER_FACTOR "{m}%s/%s/%s{e}" - "{s}SDM630 " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; -#endif - -void SDM630Show(bool json) -{ - char voltage_l1[33]; - dtostrfd(sdm630_voltage[0], Settings.flag2.voltage_resolution, voltage_l1); - char voltage_l2[33]; - dtostrfd(sdm630_voltage[1], Settings.flag2.voltage_resolution, voltage_l2); - char voltage_l3[33]; - dtostrfd(sdm630_voltage[2], Settings.flag2.voltage_resolution, voltage_l3); - char current_l1[33]; - dtostrfd(sdm630_current[0], Settings.flag2.current_resolution, current_l1); - char current_l2[33]; - dtostrfd(sdm630_current[1], Settings.flag2.current_resolution, current_l2); - char current_l3[33]; - dtostrfd(sdm630_current[2], Settings.flag2.current_resolution, current_l3); - char active_power_l1[33]; - dtostrfd(sdm630_active_power[0], Settings.flag2.wattage_resolution, active_power_l1); - char active_power_l2[33]; - dtostrfd(sdm630_active_power[1], Settings.flag2.wattage_resolution, active_power_l2); - char active_power_l3[33]; - dtostrfd(sdm630_active_power[2], Settings.flag2.wattage_resolution, active_power_l3); - char reactive_power_l1[33]; - dtostrfd(sdm630_reactive_power[0], Settings.flag2.wattage_resolution, reactive_power_l1); - char reactive_power_l2[33]; - dtostrfd(sdm630_reactive_power[1], Settings.flag2.wattage_resolution, reactive_power_l2); - char reactive_power_l3[33]; - dtostrfd(sdm630_reactive_power[2], Settings.flag2.wattage_resolution, reactive_power_l3); - char power_factor_l1[33]; - dtostrfd(sdm630_power_factor[0], 2, power_factor_l1); - char power_factor_l2[33]; - dtostrfd(sdm630_power_factor[1], 2, power_factor_l2); - char power_factor_l3[33]; - dtostrfd(sdm630_power_factor[2], 2, power_factor_l3); - char energy_total[33]; - dtostrfd(sdm630_energy_total, Settings.flag2.energy_resolution, energy_total); - - if (json) { - ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" - D_JSON_ACTIVE_POWERUSAGE "\":[%s,%s,%s],\"" D_JSON_REACTIVE_POWERUSAGE "\":[%s,%s,%s],\"" - D_JSON_POWERFACTOR "\":[%s,%s,%s],\"" D_JSON_VOLTAGE "\":[%s,%s,%s],\"" D_JSON_CURRENT "\":[%s,%s,%s]}"), - energy_total, active_power_l1, active_power_l2, active_power_l3, - reactive_power_l1, reactive_power_l2, reactive_power_l3, - power_factor_l1, power_factor_l2, power_factor_l3, - voltage_l1, voltage_l2, voltage_l3, - current_l1, current_l2, current_l3); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - char energy_total_chr[33]; - dtostrfd(sdm630_energy_total * 1000, 1, energy_total_chr); - DomoticzSensor(DZ_VOLTAGE, voltage_l1); - DomoticzSensor(DZ_CURRENT, current_l1); - DomoticzSensorPowerEnergy((int)sdm630_active_power[0], energy_total_chr); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_SDM630_DATA, - voltage_l1, voltage_l2, voltage_l3, current_l1, current_l2, current_l3, - active_power_l1, active_power_l2, active_power_l3, - reactive_power_l1, reactive_power_l2, reactive_power_l3, - power_factor_l1, power_factor_l2, power_factor_l3, energy_total); -#endif - } -} - - - - - -bool Xsns25(uint8_t function) -{ - bool result = false; - - if (sdm630_type) { - switch (function) { - case FUNC_INIT: - SDM630Init(); - break; - case FUNC_EVERY_250_MSECOND: - SDM630250ms(); - break; - case FUNC_JSON_APPEND: - SDM630Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SDM630Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_26_lm75ad.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_26_lm75ad.ino" -#ifdef USE_I2C -#ifdef USE_LM75AD -# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_26_lm75ad.ino" -#define XSNS_26 26 - -#define LM75AD_ADDRESS1 0x48 -#define LM75AD_ADDRESS2 0x49 -#define LM75AD_ADDRESS3 0x4A -#define LM75AD_ADDRESS4 0x4B -#define LM75AD_ADDRESS5 0x4C -#define LM75AD_ADDRESS6 0x4D -#define LM75AD_ADDRESS7 0x4E -#define LM75AD_ADDRESS8 0x4F - -#define LM75_TEMP_REGISTER 0x00 -#define LM75_CONF_REGISTER 0x01 -#define LM75_THYST_REGISTER 0x02 -#define LM75_TOS_REGISTER 0x03 - -uint8_t lm75ad_type = 0; -uint8_t lm75ad_address; -uint8_t lm75ad_addresses[] = { LM75AD_ADDRESS1, LM75AD_ADDRESS2, LM75AD_ADDRESS3, LM75AD_ADDRESS4, LM75AD_ADDRESS5, LM75AD_ADDRESS6, LM75AD_ADDRESS7, LM75AD_ADDRESS8 }; - -void LM75ADDetect(void) -{ - if (lm75ad_type) { return; } - - uint16_t buffer; - for (uint32_t i = 0; i < sizeof(lm75ad_addresses); i++) { - lm75ad_address = lm75ad_addresses[i]; - if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) { - if (buffer == 0x4B00) { - lm75ad_type = 1; - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "LM75AD", lm75ad_address); - break; - } - } - } -} - -float LM75ADGetTemp(void) { - int16_t sign = 1; - - uint16_t t = I2cRead16(lm75ad_address, LM75_TEMP_REGISTER); - if (t & 0x8000) { - t = (~t) +0x20; - sign = -1; - } - t = t >> 5; - return ConvertTemp(sign * t * 0.125); -} - -void LM75ADShow(bool json) -{ - if (lm75ad_type) { - float t = LM75ADGetTemp(); - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - - if (json) { - ResponseAppend_P(PSTR(",\"LM75AD\":{\"" D_JSON_TEMPERATURE "\":%s}"), temperature); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_TEMP, temperature); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, "LM75AD", temperature, TempUnit()); -#endif - } - } -} - - - - - -bool Xsns26(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_EVERY_SECOND: - LM75ADDetect(); - break; - case FUNC_JSON_APPEND: - LM75ADShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - LM75ADShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" -# 28 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" -#ifdef USE_I2C -#ifdef USE_APDS9960 -# 39 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" -#define XSNS_27 27 - -#if defined(USE_SHT) || defined(USE_VEML6070) || defined(USE_TSL2561) - #warning **** Turned off conflicting drivers SHT and VEML6070 **** - #ifdef USE_SHT - #undef USE_SHT - #endif - #ifdef USE_VEML6070 - #undef USE_VEML6070 - #endif - #ifdef USE_TSL2561 - #undef USE_TSL2561 - #endif -#endif - -#define APDS9960_I2C_ADDR 0x39 - -#define APDS9960_CHIPID_1 0xAB -#define APDS9960_CHIPID_2 0x9C - -#define APDS9930_CHIPID_1 0x12 -#define APDS9930_CHIPID_2 0x39 - - -#define GESTURE_THRESHOLD_OUT 10 -#define GESTURE_SENSITIVITY_1 50 -#define GESTURE_SENSITIVITY_2 20 - -uint8_t APDS9960addr; -uint8_t APDS9960type = 0; -char APDS9960stype[9]; -char currentGesture[6]; -uint8_t gesture_mode = 1; - - -volatile uint8_t recovery_loop_counter = 0; -#define APDS9960_LONG_RECOVERY 50 -#define APDS9960_MAX_GESTURE_CYCLES 50 -bool APDS9960_overload = false; - -#ifdef USE_WEBSERVER -const char HTTP_APDS_9960_SNS[] PROGMEM = - "{s}" "Red" "{m}%s{e}" - "{s}" "Green" "{m}%s{e}" - "{s}" "Blue" "{m}%s{e}" - "{s}" "Ambient" "{m}%s " D_UNIT_LUX "{e}" - "{s}" "CCT" "{m}%s " "K" "{e}" - "{s}" "Proximity" "{m}%s{e}"; -#endif -# 96 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" -#define FIFO_PAUSE_TIME 30 - - -#define APDS9960_ENABLE 0x80 -#define APDS9960_ATIME 0x81 -#define APDS9960_WTIME 0x83 -#define APDS9960_AILTL 0x84 -#define APDS9960_AILTH 0x85 -#define APDS9960_AIHTL 0x86 -#define APDS9960_AIHTH 0x87 -#define APDS9960_PILT 0x89 -#define APDS9960_PIHT 0x8B -#define APDS9960_PERS 0x8C -#define APDS9960_CONFIG1 0x8D -#define APDS9960_PPULSE 0x8E -#define APDS9960_CONTROL 0x8F -#define APDS9960_CONFIG2 0x90 -#define APDS9960_ID 0x92 -#define APDS9960_STATUS 0x93 -#define APDS9960_CDATAL 0x94 -#define APDS9960_CDATAH 0x95 -#define APDS9960_RDATAL 0x96 -#define APDS9960_RDATAH 0x97 -#define APDS9960_GDATAL 0x98 -#define APDS9960_GDATAH 0x99 -#define APDS9960_BDATAL 0x9A -#define APDS9960_BDATAH 0x9B -#define APDS9960_PDATA 0x9C -#define APDS9960_POFFSET_UR 0x9D -#define APDS9960_POFFSET_DL 0x9E -#define APDS9960_CONFIG3 0x9F -#define APDS9960_GPENTH 0xA0 -#define APDS9960_GEXTH 0xA1 -#define APDS9960_GCONF1 0xA2 -#define APDS9960_GCONF2 0xA3 -#define APDS9960_GOFFSET_U 0xA4 -#define APDS9960_GOFFSET_D 0xA5 -#define APDS9960_GOFFSET_L 0xA7 -#define APDS9960_GOFFSET_R 0xA9 -#define APDS9960_GPULSE 0xA6 -#define APDS9960_GCONF3 0xAA -#define APDS9960_GCONF4 0xAB -#define APDS9960_GFLVL 0xAE -#define APDS9960_GSTATUS 0xAF -#define APDS9960_IFORCE 0xE4 -#define APDS9960_PICLEAR 0xE5 -#define APDS9960_CICLEAR 0xE6 -#define APDS9960_AICLEAR 0xE7 -#define APDS9960_GFIFO_U 0xFC -#define APDS9960_GFIFO_D 0xFD -#define APDS9960_GFIFO_L 0xFE -#define APDS9960_GFIFO_R 0xFF - - -#define APDS9960_PON 0b00000001 -#define APDS9960_AEN 0b00000010 -#define APDS9960_PEN 0b00000100 -#define APDS9960_WEN 0b00001000 -#define APSD9960_AIEN 0b00010000 -#define APDS9960_PIEN 0b00100000 -#define APDS9960_GEN 0b01000000 -#define APDS9960_GVALID 0b00000001 - - -#define OFF 0 -#define ON 1 - - -#define POWER 0 -#define AMBIENT_LIGHT 1 -#define PROXIMITY 2 -#define WAIT 3 -#define AMBIENT_LIGHT_INT 4 -#define PROXIMITY_INT 5 -#define GESTURE 6 -#define ALL 7 - - -#define LED_DRIVE_100MA 0 -#define LED_DRIVE_50MA 1 -#define LED_DRIVE_25MA 2 -#define LED_DRIVE_12_5MA 3 - - -#define PGAIN_1X 0 -#define PGAIN_2X 1 -#define PGAIN_4X 2 -#define PGAIN_8X 3 - - -#define AGAIN_1X 0 -#define AGAIN_4X 1 -#define AGAIN_16X 2 -#define AGAIN_64X 3 - - -#define GGAIN_1X 0 -#define GGAIN_2X 1 -#define GGAIN_4X 2 -#define GGAIN_8X 3 - - -#define LED_BOOST_100 0 -#define LED_BOOST_150 1 -#define LED_BOOST_200 2 -#define LED_BOOST_300 3 - - -#define GWTIME_0MS 0 -#define GWTIME_2_8MS 1 -#define GWTIME_5_6MS 2 -#define GWTIME_8_4MS 3 -#define GWTIME_14_0MS 4 -#define GWTIME_22_4MS 5 -#define GWTIME_30_8MS 6 -#define GWTIME_39_2MS 7 - - -#define DEFAULT_ATIME 0xdb -#define DEFAULT_WTIME 246 -#define DEFAULT_PROX_PPULSE 0x87 -#define DEFAULT_GESTURE_PPULSE 0x89 -#define DEFAULT_POFFSET_UR 0 -#define DEFAULT_POFFSET_DL 0 -#define DEFAULT_CONFIG1 0x60 -#define DEFAULT_LDRIVE LED_DRIVE_100MA -#define DEFAULT_PGAIN PGAIN_4X -#define DEFAULT_AGAIN AGAIN_4X -#define DEFAULT_PILT 0 -#define DEFAULT_PIHT 50 -#define DEFAULT_AILT 0xFFFF -#define DEFAULT_AIHT 0 -#define DEFAULT_PERS 0x11 -#define DEFAULT_CONFIG2 0x01 -#define DEFAULT_CONFIG3 0 -#define DEFAULT_GPENTH 40 -#define DEFAULT_GEXTH 30 -#define DEFAULT_GCONF1 0x40 -#define DEFAULT_GGAIN GGAIN_4X -#define DEFAULT_GLDRIVE LED_DRIVE_100MA -#define DEFAULT_GWTIME GWTIME_2_8MS -#define DEFAULT_GOFFSET 0 -#define DEFAULT_GPULSE 0xC9 -#define DEFAULT_GCONF3 0 -#define DEFAULT_GIEN 0 - -#define ERROR 0xFF - - -enum { - DIR_NONE, - DIR_LEFT, - DIR_RIGHT, - DIR_UP, - DIR_DOWN, - DIR_ALL -}; - - -enum { - APDS9960_NA_STATE, - APDS9960_ALL_STATE -}; - - -typedef struct gesture_data_type { - uint8_t u_data[32]; - uint8_t d_data[32]; - uint8_t l_data[32]; - uint8_t r_data[32]; - uint8_t index; - uint8_t total_gestures; - uint8_t in_threshold; - uint8_t out_threshold; -} gesture_data_type; - - - gesture_data_type gesture_data_; - int16_t gesture_ud_delta_ = 0; - int16_t gesture_lr_delta_ = 0; - int16_t gesture_ud_count_ = 0; - int16_t gesture_lr_count_ = 0; - int16_t gesture_state_ = 0; - int16_t gesture_motion_ = DIR_NONE; - - typedef struct color_data_type { - uint16_t a; - uint16_t r; - uint16_t g; - uint16_t b; - uint8_t p; - uint16_t cct; - uint16_t lux; - } color_data_type; - - color_data_type color_data; - uint8_t APDS9960_aTime = DEFAULT_ATIME; -# 305 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - bool wireWriteByte(uint8_t val) - { - Wire.beginTransmission(APDS9960_I2C_ADDR); - Wire.write(val); - if( Wire.endTransmission() != 0 ) { - return false; - } - - return true; - } -# 324 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" -int8_t wireReadDataBlock( uint8_t reg, - uint8_t *val, - uint16_t len) -{ - unsigned char i = 0; - - - if (!wireWriteByte(reg)) { - return -1; - } - - - Wire.requestFrom(APDS9960_I2C_ADDR, len); - while (Wire.available()) { - if (i >= len) { - return -1; - } - val[i] = Wire.read(); - i++; - } - - return i; -} - - - - - - - -void calculateColorTemperature(void) -{ - float X, Y, Z; - float xc, yc; - float n; - float cct; - - - - - - X = (-0.14282F * color_data.r) + (1.54924F * color_data.g) + (-0.95641F * color_data.b); - Y = (-0.32466F * color_data.r) + (1.57837F * color_data.g) + (-0.73191F * color_data.b); - Z = (-0.68202F * color_data.r) + (0.77073F * color_data.g) + ( 0.56332F * color_data.b); - - - xc = (X) / (X + Y + Z); - yc = (Y) / (X + Y + Z); - - - n = (xc - 0.3320F) / (0.1858F - yc); - - - color_data.cct = (449.0F * FastPrecisePowf(n, 3)) + (3525.0F * FastPrecisePowf(n, 2)) + (6823.3F * n) + 5520.33F; - - return; -} -# 391 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - uint8_t getProxIntLowThresh(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT) ; - return val; - } - - - - - - - void setProxIntLowThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold); - } - - - - - - - uint8_t getProxIntHighThresh(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; - return val; - } - - - - - - - - void setProxIntHighThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold); - } -# 447 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - uint8_t getLEDDrive(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; - - val = (val >> 6) & 0b00000011; - - return val; - } -# 470 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - void setLEDDrive(uint8_t drive) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - - drive &= 0b00000011; - drive = drive << 6; - val &= 0b00111111; - val |= drive; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); - } -# 499 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - uint8_t getProximityGain(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; - - val = (val >> 2) & 0b00000011; - - return val; - } -# 522 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - void setProximityGain(uint8_t drive) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - - drive &= 0b00000011; - drive = drive << 2; - val &= 0b11110011; - val |= drive; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); - } -# 563 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - void setAmbientLightGain(uint8_t drive) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - - drive &= 0b00000011; - val &= 0b11111100; - val |= drive; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); - } -# 590 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - uint8_t getLEDBoost(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; - - - val = (val >> 4) & 0b00000011; - - return val; - } -# 614 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - void setLEDBoost(uint8_t boost) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; - - boost &= 0b00000011; - boost = boost << 4; - val &= 0b11001111; - val |= boost; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, val) ; - } - - - - - - - uint8_t getProxGainCompEnable(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - - val = (val >> 5) & 0b00000001; - - return val; - } - - - - - - - void setProxGainCompEnable(uint8_t enable) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - - enable &= 0b00000001; - enable = enable << 5; - val &= 0b11011111; - val |= enable; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; - } -# 682 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - uint8_t getProxPhotoMask(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - - val &= 0b00001111; - - return val; - } -# 707 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - void setProxPhotoMask(uint8_t mask) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - - mask &= 0b00001111; - val &= 0b11110000; - val |= mask; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; - } - - - - - - - uint8_t getGestureEnterThresh(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GPENTH) ; - - return val; - } - - - - - - - void setGestureEnterThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPENTH, threshold) ; - - } - - - - - - - uint8_t getGestureExitThresh(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GEXTH) ; - - return val; - } - - - - - - - void setGestureExitThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GEXTH, threshold) ; - } -# 785 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - uint8_t getGestureGain(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - val = (val >> 5) & 0b00000011; - - return val; - } -# 809 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - void setGestureGain(uint8_t gain) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - gain &= 0b00000011; - gain = gain << 5; - val &= 0b10011111; - val |= gain; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; - } -# 837 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - uint8_t getGestureLEDDrive(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - val = (val >> 3) & 0b00000011; - - return val; - } -# 861 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - void setGestureLEDDrive(uint8_t drive) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - drive &= 0b00000011; - drive = drive << 3; - val &= 0b11100111; - val |= drive; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; - } -# 893 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - uint8_t getGestureWaitTime(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - val &= 0b00000111; - - return val; - } -# 921 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - void setGestureWaitTime(uint8_t time) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - time &= 0b00000111; - val &= 0b11111000; - val |= time; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; - } - - - - - - - void getLightIntLowThreshold(uint16_t &threshold) - { - uint8_t val_byte; - threshold = 0; - - - val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AILTL) ; - threshold = val_byte; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_byte) ; - threshold = threshold + ((uint16_t)val_byte << 8); - } - - - - - - - - void setLightIntLowThreshold(uint16_t threshold) - { - uint8_t val_low; - uint8_t val_high; - - - val_low = threshold & 0x00FF; - val_high = (threshold & 0xFF00) >> 8; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTL, val_low) ; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_high) ; - - } - - - - - - - - void getLightIntHighThreshold(uint16_t &threshold) - { - uint8_t val_byte; - threshold = 0; - - - val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AIHTL); - threshold = val_byte; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_byte) ; - threshold = threshold + ((uint16_t)val_byte << 8); - } - - - - - - - void setLightIntHighThreshold(uint16_t threshold) - { - uint8_t val_low; - uint8_t val_high; - - - val_low = threshold & 0x00FF; - val_high = (threshold & 0xFF00) >> 8; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTL, val_low); - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_high) ; - } - - - - - - - - void getProximityIntLowThreshold(uint8_t &threshold) - { - threshold = 0; - - - threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT); - - } - - - - - - - void setProximityIntLowThreshold(uint8_t threshold) - { - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold) ; - } -# 1054 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" - void getProximityIntHighThreshold(uint8_t &threshold) - { - threshold = 0; - - - threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; - - } - - - - - - - void setProximityIntHighThreshold(uint8_t threshold) - { - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold) ; - } - - - - - - - uint8_t getAmbientLightIntEnable(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - - val = (val >> 4) & 0b00000001; - - return val; - } - - - - - - - void setAmbientLightIntEnable(uint8_t enable) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE); - - - enable &= 0b00000001; - enable = enable << 4; - val &= 0b11101111; - val |= enable; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; - } - - - - - - - uint8_t getProximityIntEnable(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - - val = (val >> 5) & 0b00000001; - - return val; - } - - - - - - - void setProximityIntEnable(uint8_t enable) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - - enable &= 0b00000001; - enable = enable << 5; - val &= 0b11011111; - val |= enable; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; - } - - - - - - - uint8_t getGestureIntEnable(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - - val = (val >> 1) & 0b00000001; - - return val; - } - - - - - - - void setGestureIntEnable(uint8_t enable) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - - enable &= 0b00000001; - enable = enable << 1; - val &= 0b11111101; - val |= enable; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; - } - - - - - - void clearAmbientLightInt(void) - { - uint8_t throwaway; - throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AICLEAR); - } - - - - - - void clearProximityInt(void) - { - uint8_t throwaway; - throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PICLEAR) ; - - } - - - - - - - uint8_t getGestureMode(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - - val &= 0b00000001; - - return val; - } - - - - - - - void setGestureMode(uint8_t mode) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - - mode &= 0b00000001; - val &= 0b11111110; - val |= mode; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; - } - - -bool APDS9960_init(void) -{ - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, DEFAULT_ATIME) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, DEFAULT_WTIME) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_PROX_PPULSE) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_UR, DEFAULT_POFFSET_UR) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_DL, DEFAULT_POFFSET_DL) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG1, DEFAULT_CONFIG1) ; - - setLEDDrive(DEFAULT_LDRIVE); - - setProximityGain(DEFAULT_PGAIN); - - setAmbientLightGain(DEFAULT_AGAIN); - - setProxIntLowThresh(DEFAULT_PILT) ; - - setProxIntHighThresh(DEFAULT_PIHT); - - setLightIntLowThreshold(DEFAULT_AILT) ; - - setLightIntHighThreshold(DEFAULT_AIHT) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PERS, DEFAULT_PERS) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, DEFAULT_CONFIG2) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, DEFAULT_CONFIG3) ; - - - setGestureEnterThresh(DEFAULT_GPENTH); - - setGestureExitThresh(DEFAULT_GEXTH) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF1, DEFAULT_GCONF1) ; - - setGestureGain(DEFAULT_GGAIN) ; - - setGestureLEDDrive(DEFAULT_GLDRIVE) ; - - setGestureWaitTime(DEFAULT_GWTIME) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_U, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_D, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_L, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_R, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPULSE, DEFAULT_GPULSE) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF3, DEFAULT_GCONF3) ; - - setGestureIntEnable(DEFAULT_GIEN); - - disablePower(); - - return true; -} -# 1332 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" -uint8_t getMode(void) -{ - uint8_t enable_value; - - - enable_value = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - return enable_value; -} - - - - - - - -void setMode(uint8_t mode, uint8_t enable) -{ - uint8_t reg_val; - - - reg_val = getMode(); - - - - enable = enable & 0x01; - if( mode >= 0 && mode <= 6 ) { - if (enable) { - reg_val |= (1 << mode); - } else { - reg_val &= ~(1 << mode); - } - } else if( mode == ALL ) { - if (enable) { - reg_val = 0x7F; - } else { - reg_val = 0x00; - } - } - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, reg_val) ; -} - - - - - - -void enableLightSensor(void) -{ - - setAmbientLightGain(DEFAULT_AGAIN); - setAmbientLightIntEnable(0); - enablePower() ; - setMode(AMBIENT_LIGHT, 1) ; -} - - - - - -void disableLightSensor(void) -{ - setAmbientLightIntEnable(0) ; - setMode(AMBIENT_LIGHT, 0) ; -} - - - - - - -void enableProximitySensor(void) -{ - - setProximityGain(DEFAULT_PGAIN); - setLEDDrive(DEFAULT_LDRIVE) ; - setProximityIntEnable(0) ; - enablePower(); - setMode(PROXIMITY, 1) ; -} - - - - - -void disableProximitySensor(void) -{ - setProximityIntEnable(0) ; - setMode(PROXIMITY, 0) ; -} - - - - - - -void enableGestureSensor(void) -{ - - - - - - - - resetGestureParameters(); - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, 0xFF) ; - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) ; - setLEDBoost(LED_BOOST_100); - setGestureIntEnable(0) ; - setGestureMode(1); - enablePower() ; - setMode(WAIT, 1) ; - setMode(PROXIMITY, 1) ; - setMode(GESTURE, 1); -} - - - - - -void disableGestureSensor(void) -{ - resetGestureParameters(); - setGestureIntEnable(0) ; - setGestureMode(0) ; - setMode(GESTURE, 0) ; -} - - - - - - -bool isGestureAvailable(void) -{ - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS) ; - - - val &= APDS9960_GVALID; - - - if( val == 1) { - return true; - } else { - return false; - } -} - - - - - - -int16_t readGesture(void) -{ - uint8_t fifo_level = 0; - uint8_t bytes_read = 0; - uint8_t fifo_data[128]; - uint8_t gstatus; - uint16_t motion; - uint16_t i; - uint8_t gesture_loop_counter = 0; - - - if( !isGestureAvailable() || !(getMode() & 0b01000001) ) { - return DIR_NONE; - } - - - while(1) { - if (gesture_loop_counter == APDS9960_MAX_GESTURE_CYCLES){ - disableGestureSensor(); - APDS9960_overload = true; - AddLog_P(LOG_LEVEL_DEBUG, PSTR("Sensor overload")); - } - gesture_loop_counter += 1; - - delay(FIFO_PAUSE_TIME); - - - gstatus = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS); - - - if( (gstatus & APDS9960_GVALID) == APDS9960_GVALID ) { - - - fifo_level = I2cRead8(APDS9960_I2C_ADDR,APDS9960_GFLVL) ; - - - if( fifo_level > 0) { - bytes_read = wireReadDataBlock( APDS9960_GFIFO_U, - (uint8_t*)fifo_data, - (fifo_level * 4) ); - if( bytes_read == -1 ) { - return ERROR; - } - - - if( bytes_read >= 4 ) { - for( i = 0; i < bytes_read; i += 4 ) { - gesture_data_.u_data[gesture_data_.index] = \ - fifo_data[i + 0]; - gesture_data_.d_data[gesture_data_.index] = \ - fifo_data[i + 1]; - gesture_data_.l_data[gesture_data_.index] = \ - fifo_data[i + 2]; - gesture_data_.r_data[gesture_data_.index] = \ - fifo_data[i + 3]; - gesture_data_.index++; - gesture_data_.total_gestures++; - } - - if( processGestureData() ) { - if( decodeGesture() ) { - - } - } - - gesture_data_.index = 0; - gesture_data_.total_gestures = 0; - } - } - } else { - - - delay(FIFO_PAUSE_TIME); - decodeGesture(); - motion = gesture_motion_; - resetGestureParameters(); - return motion; - } - } -} - - - - - -void enablePower(void) -{ - setMode(POWER, 1) ; -} - - - - - -void disablePower(void) -{ - setMode(POWER, 0) ; -} -# 1599 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" -void readAllColorAndProximityData(void) -{ - if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9)) - { - - - } -} -# 1615 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" -void resetGestureParameters(void) -{ - gesture_data_.index = 0; - gesture_data_.total_gestures = 0; - - gesture_ud_delta_ = 0; - gesture_lr_delta_ = 0; - - gesture_ud_count_ = 0; - gesture_lr_count_ = 0; - - gesture_state_ = 0; - gesture_motion_ = DIR_NONE; -} - - - - - - -bool processGestureData(void) -{ - uint8_t u_first = 0; - uint8_t d_first = 0; - uint8_t l_first = 0; - uint8_t r_first = 0; - uint8_t u_last = 0; - uint8_t d_last = 0; - uint8_t l_last = 0; - uint8_t r_last = 0; - uint16_t ud_ratio_first; - uint16_t lr_ratio_first; - uint16_t ud_ratio_last; - uint16_t lr_ratio_last; - uint16_t ud_delta; - uint16_t lr_delta; - uint16_t i; - - - if( gesture_data_.total_gestures <= 4 ) { - return false; - } - - - if( (gesture_data_.total_gestures <= 32) && \ - (gesture_data_.total_gestures > 0) ) { - - - for( i = 0; i < gesture_data_.total_gestures; i++ ) { - if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { - - u_first = gesture_data_.u_data[i]; - d_first = gesture_data_.d_data[i]; - l_first = gesture_data_.l_data[i]; - r_first = gesture_data_.r_data[i]; - break; - } - } - - - if( (u_first == 0) || (d_first == 0) || \ - (l_first == 0) || (r_first == 0) ) { - - return false; - } - - for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) { - - if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { - - u_last = gesture_data_.u_data[i]; - d_last = gesture_data_.d_data[i]; - l_last = gesture_data_.l_data[i]; - r_last = gesture_data_.r_data[i]; - break; - } - } - } - - - ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first); - lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first); - ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last); - lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last); - - - ud_delta = ud_ratio_last - ud_ratio_first; - lr_delta = lr_ratio_last - lr_ratio_first; - - - gesture_ud_delta_ += ud_delta; - gesture_lr_delta_ += lr_delta; - - - if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) { - gesture_ud_count_ = 1; - } else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 ) { - gesture_ud_count_ = -1; - } else { - gesture_ud_count_ = 0; - } - - - if( gesture_lr_delta_ >= GESTURE_SENSITIVITY_1 ) { - gesture_lr_count_ = 1; - } else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 ) { - gesture_lr_count_ = -1; - } else { - gesture_lr_count_ = 0; - } - return false; -} - - - - - - -bool decodeGesture(void) -{ - - - if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 0) ) { - gesture_motion_ = DIR_UP; - } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 0) ) { - gesture_motion_ = DIR_DOWN; - } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 1) ) { - gesture_motion_ = DIR_RIGHT; - } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == -1) ) { - gesture_motion_ = DIR_LEFT; - } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_UP; - } else { - gesture_motion_ = DIR_RIGHT; - } - } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == -1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_DOWN; - } else { - gesture_motion_ = DIR_LEFT; - } - } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == -1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_UP; - } else { - gesture_motion_ = DIR_LEFT; - } - } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_DOWN; - } else { - gesture_motion_ = DIR_RIGHT; - } - } else { - return false; - } - - return true; -} - -void handleGesture(void) { - if (isGestureAvailable() ) { - switch (readGesture()) { - case DIR_UP: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("UP")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Up")); - break; - case DIR_DOWN: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("DOWN")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Down")); - break; - case DIR_LEFT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("LEFT")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Left")); - break; - case DIR_RIGHT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("RIGHT")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Right")); - break; - default: - if(APDS9960_overload) - { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("LONG")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Long")); - } - else{ - AddLog_P(LOG_LEVEL_DEBUG, PSTR("NONE")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("None")); - } - } - - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -#ifdef USE_RULES - RulesTeleperiod(); -#endif - } - } -} - -void APDS9960_adjustATime(void) -{ - - I2cValidRead16LE(&color_data.a, APDS9960_I2C_ADDR, APDS9960_CDATAL); - - - if (color_data.a < (uint16_t)20){ - APDS9960_aTime = 0x40; - } - else if (color_data.a < (uint16_t)40){ - APDS9960_aTime = 0x80; - } - else if (color_data.a < (uint16_t)50){ - APDS9960_aTime = DEFAULT_ATIME; - } - else if (color_data.a < (uint16_t)70){ - APDS9960_aTime = 0xc0; - } - if (color_data.a < 200){ - APDS9960_aTime = 0xe9; - } - - - - else{ - APDS9960_aTime = 0xff; - } - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, APDS9960_aTime); - enablePower(); - enableLightSensor(); - delay(20); -} - - -void APDS9960_loop(void) -{ - if (recovery_loop_counter > 0){ - recovery_loop_counter -= 1; - } - if (recovery_loop_counter == 1 && APDS9960_overload){ - enableGestureSensor(); - APDS9960_overload = false; - Response_P(PSTR("{\"Gesture\":\"On\"}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); - gesture_mode = 1; - } - - if (gesture_mode) { - if (recovery_loop_counter == 0){ - handleGesture(); - - if (APDS9960_overload) - { - disableGestureSensor(); - recovery_loop_counter = APDS9960_LONG_RECOVERY; - Response_P(PSTR("{\"Gesture\":\"Off\"}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); - gesture_mode = 0; - } - } - } -} - -bool APDS9960_detect(void) -{ - if (APDS9960type) { - return true; - } - - bool success = false; - APDS9960type = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ID); - - if (APDS9960type == APDS9960_CHIPID_1 || APDS9960type == APDS9960_CHIPID_2) { - strcpy_P(APDS9960stype, PSTR("APDS9960")); - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, APDS9960stype, APDS9960_I2C_ADDR); - if (APDS9960_init()) { - success = true; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "APDS9960 initialized")); - enableProximitySensor(); - enableGestureSensor(); - } - } - else { - if (APDS9960type == APDS9930_CHIPID_1 || APDS9960type == APDS9930_CHIPID_2) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("APDS9930 found at address 0x%x, unsupported chip"), APDS9960_I2C_ADDR); - } - else{ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("APDS9960 not found at address 0x%x"), APDS9960_I2C_ADDR); - } - } - currentGesture[0] = '\0'; - return success; -} - - - - - -void APDS9960_show(bool json) -{ - if (!APDS9960type) { - return; - } - if (!gesture_mode && !APDS9960_overload) { - char red_chr[10]; - char green_chr[10]; - char blue_chr[10]; - char ambient_chr[10]; - char cct_chr[10]; - char prox_chr[10]; - - readAllColorAndProximityData(); - - sprintf (ambient_chr, "%u", color_data.a/4); - sprintf (red_chr, "%u", color_data.r); - sprintf (green_chr, "%u", color_data.g); - sprintf (blue_chr, "%u", color_data.b ); - sprintf (prox_chr, "%u", color_data.p ); - - - - - - calculateColorTemperature(); - sprintf (cct_chr, "%u", color_data.cct); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"CCT\":%s,\"Proximity\":%s}"), - APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_APDS_9960_SNS, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr ); -#endif - } - } - else { - if (json && (currentGesture[0] != '\0' )) { - ResponseAppend_P(PSTR(",\"%s\":{\"%s\":1}"), APDS9960stype, currentGesture); - currentGesture[0] = '\0'; - } - } -} -# 1979 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_27_apds9960.ino" -bool APDS9960CommandSensor(void) -{ - bool serviced = true; - - switch (XdrvMailbox.payload) { - case 0: - disableGestureSensor(); - gesture_mode = 0; - enableLightSensor(); - APDS9960_overload = false; - break; - case 1: - if (APDS9960type) { - setGestureGain(DEFAULT_GGAIN); - setProximityGain(DEFAULT_PGAIN); - disableLightSensor(); - enableGestureSensor(); - gesture_mode = 1; - } - break; - case 2: - if (APDS9960type) { - setGestureGain(GGAIN_2X); - setProximityGain(PGAIN_2X); - disableLightSensor(); - enableGestureSensor(); - gesture_mode = 1; - } - break; - default: - int temp_aTime = (uint8_t)XdrvMailbox.payload; - if (temp_aTime > 2 && temp_aTime < 256){ - disablePower(); - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, temp_aTime); - enablePower(); - enableLightSensor(); - } - break; - } - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_27, GetStateText(gesture_mode)); - - return serviced; -} - - - - - -bool Xsns27(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - if (FUNC_INIT == function) { - APDS9960_detect(); - } else if (APDS9960type) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - APDS9960_loop(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_27 == XdrvMailbox.index) { - result = APDS9960CommandSensor(); - } - break; - case FUNC_JSON_APPEND: - APDS9960_show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - APDS9960_show(0); - break; -#endif - } - } - } - return result; -} -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_28_tm1638.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_28_tm1638.ino" -#ifdef USE_TM1638 - - - - - - -#define XSNS_28 28 - -#define TM1638_COLOR_NONE 0 -#define TM1638_COLOR_RED 1 -#define TM1638_COLOR_GREEN 2 - -#define TM1638_CLOCK_DELAY 1 - -uint8_t tm1638_type = 1; -uint8_t tm1638_clock_pin = 0; -uint8_t tm1638_data_pin = 0; -uint8_t tm1638_strobe_pin = 0; -uint8_t tm1638_displays = 8; -uint8_t tm1638_active_display = 1; -uint8_t tm1638_intensity = 0; -uint8_t tm1638_state = 0; - - - - - - -void Tm16XXSend(uint8_t data) -{ - for (uint32_t i = 0; i < 8; i++) { - digitalWrite(tm1638_data_pin, !!(data & (1 << i))); - digitalWrite(tm1638_clock_pin, LOW); - delayMicroseconds(TM1638_CLOCK_DELAY); - digitalWrite(tm1638_clock_pin, HIGH); - } -} - -void Tm16XXSendCommand(uint8_t cmd) -{ - digitalWrite(tm1638_strobe_pin, LOW); - Tm16XXSend(cmd); - digitalWrite(tm1638_strobe_pin, HIGH); -} - -void TM16XXSendData(uint8_t address, uint8_t data) -{ - Tm16XXSendCommand(0x44); - digitalWrite(tm1638_strobe_pin, LOW); - Tm16XXSend(0xC0 | address); - Tm16XXSend(data); - digitalWrite(tm1638_strobe_pin, HIGH); -} - -uint8_t Tm16XXReceive(void) -{ - uint8_t temp = 0; - - - pinMode(tm1638_data_pin, INPUT); - digitalWrite(tm1638_data_pin, HIGH); - - for (uint32_t i = 0; i < 8; ++i) { - digitalWrite(tm1638_clock_pin, LOW); - delayMicroseconds(TM1638_CLOCK_DELAY); - temp |= digitalRead(tm1638_data_pin) << i; - digitalWrite(tm1638_clock_pin, HIGH); - } - - - pinMode(tm1638_data_pin, OUTPUT); - digitalWrite(tm1638_data_pin, LOW); - - return temp; -} - - - -void Tm16XXClearDisplay(void) -{ - for (uint32_t i = 0; i < tm1638_displays; i++) { - TM16XXSendData(i << 1, 0); - } -} - -void Tm1638SetLED(uint8_t color, uint8_t pos) -{ - TM16XXSendData((pos << 1) + 1, color); -} - -void Tm1638SetLEDs(word leds) -{ - for (uint32_t i = 0; i < tm1638_displays; i++) { - uint8_t color = 0; - - if ((leds & (1 << i)) != 0) { - color |= TM1638_COLOR_RED; - } - - if ((leds & (1 << (i + 8))) != 0) { - color |= TM1638_COLOR_GREEN; - } - - Tm1638SetLED(color, i); - } -} - -uint8_t Tm1638GetButtons(void) -{ - uint8_t keys = 0; - - digitalWrite(tm1638_strobe_pin, LOW); - Tm16XXSend(0x42); - for (uint32_t i = 0; i < 4; i++) { - keys |= Tm16XXReceive() << i; - } - digitalWrite(tm1638_strobe_pin, HIGH); - - return keys; -} - - - -void TmInit(void) -{ - tm1638_type = 0; - if ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99)) { - tm1638_clock_pin = pin[GPIO_TM16CLK]; - tm1638_data_pin = pin[GPIO_TM16DIO]; - tm1638_strobe_pin = pin[GPIO_TM16STB]; - - pinMode(tm1638_data_pin, OUTPUT); - pinMode(tm1638_clock_pin, OUTPUT); - pinMode(tm1638_strobe_pin, OUTPUT); - - digitalWrite(tm1638_strobe_pin, HIGH); - digitalWrite(tm1638_clock_pin, HIGH); - - Tm16XXSendCommand(0x40); - Tm16XXSendCommand(0x80 | (tm1638_active_display ? 8 : 0) | tmin(7, tm1638_intensity)); - - digitalWrite(tm1638_strobe_pin, LOW); - Tm16XXSend(0xC0); - for (uint32_t i = 0; i < 16; i++) { - Tm16XXSend(0x00); - } - digitalWrite(tm1638_strobe_pin, HIGH); - - tm1638_type = 1; - tm1638_state = 1; - } -} - -void TmLoop(void) -{ - if (tm1638_state) { - uint8_t buttons = Tm1638GetButtons(); - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - SwitchSetVirtual(i, (buttons &1) ^1); - uint8_t color = (SwitchGetVirtual(i)) ? TM1638_COLOR_NONE : TM1638_COLOR_RED; - Tm1638SetLED(color, i); - buttons >>= 1; - } - SwitchHandler(1); - } -} -# 201 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_28_tm1638.ino" -bool Xsns28(uint8_t function) -{ - bool result = false; - - if (tm1638_type) { - switch (function) { - case FUNC_INIT: - TmInit(); - break; - case FUNC_EVERY_50_MSECOND: - TmLoop(); - break; -# 223 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_28_tm1638.ino" - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_29_mcp230xx.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_29_mcp230xx.ino" -#ifdef USE_I2C -#ifdef USE_MCP230xx -# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_29_mcp230xx.ino" -#define XSNS_29 29 - - - - - -uint8_t MCP230xx_IODIR = 0x00; -uint8_t MCP230xx_GPINTEN = 0x02; -uint8_t MCP230xx_IOCON = 0x05; -uint8_t MCP230xx_GPPU = 0x06; -uint8_t MCP230xx_INTF = 0x07; -uint8_t MCP230xx_INTCAP = 0x08; -uint8_t MCP230xx_GPIO = 0x09; - -uint8_t mcp230xx_type = 0; -uint8_t mcp230xx_pincount = 0; -uint8_t mcp230xx_int_en = 0; -uint8_t mcp230xx_int_prio_counter = 0; -uint8_t mcp230xx_int_counter_en = 0; -uint8_t mcp230xx_int_retainer_en = 0; -uint8_t mcp230xx_int_sec_counter = 0; - -uint8_t mcp230xx_int_report_defer_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -uint16_t mcp230xx_int_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -uint8_t mcp230xx_int_retainer[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -unsigned long int_millis[16]; - -const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL_UP\":\"%s\",\"INT_MODE\":\"%s\",\"STATE\":\"%s\"}}"; - -const char MCP230XX_INTCFG_RESPONSE[] PROGMEM = "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; - -#ifdef USE_MCP230xx_OUTPUT -const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"}}"; -#endif - -void MCP230xx_CheckForIntCounter(void) { - uint8_t en = 0; - for (uint32_t ca=0;ca<16;ca++) { - if (Settings.mcp230xx_config[ca].int_count_en) { - en=1; - } - } - if (!Settings.mcp230xx_int_timer) en=0; - mcp230xx_int_counter_en=en; - if (!mcp230xx_int_counter_en) { - for (uint32_t ca=0;ca<16;ca++) { - mcp230xx_int_counter[ca] = 0; - } - } -} - -void MCP230xx_CheckForIntRetainer(void) { - uint8_t en = 0; - for (uint32_t ca=0;ca<16;ca++) { - if (Settings.mcp230xx_config[ca].int_retain_flag) { - en=1; - } - } - mcp230xx_int_retainer_en=en; - if (!mcp230xx_int_retainer_en) { - for (uint32_t ca=0;ca<16;ca++) { - mcp230xx_int_retainer[ca] = 0; - } - } -} - -const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) { -#ifdef USE_MCP230xx_OUTPUT -if ((6 == pinmod) && (statu < 2)) { statu = abs(statu-1); } -#endif - switch (statu) { - case 0: - return "OFF"; - break; - case 1: - return "ON"; - break; -#ifdef USE_MCP230xx_OUTPUT - case 2: - return "TOGGLE"; - break; -#endif - } - return ""; -} - -const char* IntModeTxt(uint8_t intmo) { - switch (intmo) { - case 0: - return "ALL"; - break; - case 1: - return "EVENT"; - break; - case 2: - return "TELE"; - break; - case 3: - return "DISABLED"; - break; - } - return ""; -} - -uint8_t MCP230xx_readGPIO(uint8_t port) { - return I2cRead8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port); -} - -void MCP230xx_ApplySettings(void) { - uint8_t int_en = 0; - for (uint32_t mcp230xx_port=0;mcp230xx_port 0) { - if (I2cValidRead8(&mcp230xx_intcap, USE_MCP230xx_ADDR, MCP230xx_INTCAP+mcp230xx_port)) { - for (uint32_t intp = 0; intp < 8; intp++) { - if ((intf >> intp) & 0x01) { - report_int = 0; - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode > 1) { - switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode) { - case 2: - report_int = 1; - break; - case 3: - if (((mcp230xx_intcap >> intp) & 0x01) == 0) report_int = 1; - break; - case 4: - if (((mcp230xx_intcap >> intp) & 0x01) == 1) report_int = 1; - break; - default: - break; - } - - if ((mcp230xx_int_counter_en) && (report_int)) { - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { - mcp230xx_int_counter[intp+(mcp230xx_port*8)]++; - } - } - - if (report_int) { - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_defer) { - mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)]++; - if (mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)] >= Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_defer) { - mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)]=0; - } else { - report_int = 0; - } - } - } - - if (report_int) { - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_retain_flag) { - mcp230xx_int_retainer[intp+(mcp230xx_port*8)] = 1; - report_int = 0; - } - } - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { - report_int = 0; - } - if (report_int) { - bool int_tele = false; - bool int_event = false; - unsigned long millis_now = millis(); - unsigned long millis_since_last_int = millis_now - int_millis[intp+(mcp230xx_port*8)]; - int_millis[intp+(mcp230xx_port*8)]=millis_now; - switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_mode) { - case 0: - int_tele=true; - int_event=true; - break; - case 1: - int_event=true; - break; - case 2: - int_tele=true; - break; - } - if (int_tele) { - ResponseTime_P(PSTR(",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"), - intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("MCP230XX_INT")); - } - if (int_event) { - char command[19]; - sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01)); - ExecuteCommand(command, SRC_RULE); - } - } - } - } - } - } - } - } - } -} - -void MCP230xx_Show(bool json) -{ - if (mcp230xx_type) { - if (json) { - if (mcp230xx_type > 0) { - uint8_t gpio = MCP230xx_readGPIO(0); - ResponseAppend_P(PSTR(",\"MCP230XX\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i"), - (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); - if (2 == mcp230xx_type) { - gpio = MCP230xx_readGPIO(1); - ResponseAppend_P(PSTR(",\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), - (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); - } - ResponseJsonEnd(); - } - } - } -} - -#ifdef USE_MCP230xx_OUTPUT - -void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { - uint8_t portpins; - uint8_t port = 0; - uint8_t pinmo = Settings.mcp230xx_config[pin].pinmode; - uint8_t interlock = Settings.flag.interlock; - int pinadd = (pin % 2)+1-(3*(pin % 2)); - char cmnd[7], stt[4]; - if (pin > 7) { port = 1; } - portpins = MCP230xx_readGPIO(port); - if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { - if (pinstate < 2) { - if (6 == pinmo) { - if (pinstate) portpins |= (1 << (pin-(port*8))); else portpins |= (1 << (pin+pinadd-(port*8))),portpins &= ~(1 << (pin-(port*8))); - } else { - if (pinstate) portpins &= ~(1 << (pin+pinadd-(port*8))),portpins |= (1 << (pin-(port*8))); else portpins &= ~(1 << (pin-(port*8))); - } - } else { - if (6 == pinmo) { - portpins |= (1 << (pin+pinadd-(port*8))),portpins ^= (1 << (pin-(port*8))); - } else { - portpins &= ~(1 << (pin+pinadd-(port*8))),portpins ^= (1 << (pin-(port*8))); - } - } - } else { - if (pinstate < 2) { - if (pinstate) portpins |= (1 << (pin-(port*8))); else portpins &= ~(1 << (pin-(port*8))); - } else { - portpins ^= (1 << (pin-(port*8))); - } - } - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port, portpins); - if (Settings.flag.save_state) { - Settings.mcp230xx_config[pin].saved_state=portpins>>(pin-(port*8))&1; - Settings.mcp230xx_config[pin+pinadd].saved_state=portpins>>(pin+pinadd-(port*8))&1; - } - sprintf(cmnd,ConvertNumTxt(pinstate, pinmo)); - sprintf(stt,ConvertNumTxt((portpins >> (pin-(port*8))&1), pinmo)); - if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { - char stt1[4]; - sprintf(stt1,ConvertNumTxt((portpins >> (pin+pinadd-(port*8))&1), pinmo)); - Response_P(PSTR("{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"},\"S29cmnd_D%i\":{\"STATE\":\"%s\"}}"),pin, cmnd, stt, pin+pinadd, stt1); - } else { - Response_P(MCP230XX_CMND_RESPONSE, pin, cmnd, stt); - } -} - -#endif - -void MCP230xx_Reset(uint8_t pinmode) { - uint8_t pullup = 0; - if ((pinmode > 1) && (pinmode < 5)) { pullup=1; } - for (uint32_t pinx=0;pinx<16;pinx++) { - Settings.mcp230xx_config[pinx].pinmode=pinmode; - Settings.mcp230xx_config[pinx].pullup=pullup; - Settings.mcp230xx_config[pinx].saved_state=0; - if ((pinmode > 1) && (pinmode < 5)) { - Settings.mcp230xx_config[pinx].int_report_mode=0; - } else { - Settings.mcp230xx_config[pinx].int_report_mode=3; - } - Settings.mcp230xx_config[pinx].int_report_defer=0; - Settings.mcp230xx_config[pinx].int_count_en=0; - Settings.mcp230xx_config[pinx].int_retain_flag=0; - Settings.mcp230xx_config[pinx].spare13=0; - Settings.mcp230xx_config[pinx].spare14=0; - Settings.mcp230xx_config[pinx].spare15=0; - } - Settings.mcp230xx_int_prio = 0; - Settings.mcp230xx_int_timer = 0; - MCP230xx_ApplySettings(); - char pulluptxt[7]; - char intmodetxt[9]; - sprintf(pulluptxt,ConvertNumTxt(pullup)); - uint8_t intmode = 3; - if ((pinmode > 1) && (pinmode < 5)) { intmode = 0; } - sprintf(intmodetxt,IntModeTxt(intmode)); - Response_P(MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,""); -} - -bool MCP230xx_Command(void) { - bool serviced = true; - bool validpin = false; - uint8_t paramcount = 0; - if (XdrvMailbox.data_len > 0) { - paramcount=1; - } else { - serviced = false; - return serviced; - } - char sub_string[XdrvMailbox.data_len]; - for (uint32_t ca=0;ca 1) { - uint8_t intpri = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if ((intpri >= 0) && (intpri <= 20)) { - Settings.mcp230xx_int_prio = intpri; - Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); - return serviced; - } - } - - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTTIMER")) { - if (paramcount > 1) { - uint8_t inttim = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if ((inttim >= 0) && (inttim <= 3600)) { - Settings.mcp230xx_int_timer = inttim; - MCP230xx_CheckForIntCounter(); - Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); - return serviced; - } - } - - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTDEF")) { - if (paramcount > 1) { - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if (pin < mcp230xx_pincount) { - if (pin == 0) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; - } else { - validpin = true; - } - } - if (validpin) { - if (paramcount > 2) { - uint8_t intdef = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - if ((intdef >= 0) && (intdef <= 15)) { - Settings.mcp230xx_config[pin].int_report_defer=intdef; - if (Settings.mcp230xx_config[pin].int_count_en) { - Settings.mcp230xx_config[pin].int_count_en=0; - MCP230xx_CheckForIntCounter(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTCNT for pin D%i"),pin); - } - Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); - return serviced; - } else { - serviced=false; - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); - return serviced; - } - } - serviced = false; - return serviced; - } else { - serviced = false; - return serviced; - } - } - - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTCNT")) { - if (paramcount > 1) { - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if (pin < mcp230xx_pincount) { - if (pin == 0) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; - } else { - validpin = true; - } - } - if (validpin) { - if (paramcount > 2) { - uint8_t intcnt = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - if ((intcnt >= 0) && (intcnt <= 1)) { - Settings.mcp230xx_config[pin].int_count_en=intcnt; - if (Settings.mcp230xx_config[pin].int_report_defer) { - Settings.mcp230xx_config[pin].int_report_defer=0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTDEF for pin D%i"),pin); - } - if (Settings.mcp230xx_config[pin].int_report_mode < 3) { - Settings.mcp230xx_config[pin].int_report_mode=3; - AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled immediate interrupt/telemetry reporting for pin D%i"),pin); - } - if ((Settings.mcp230xx_config[pin].int_count_en) && (!Settings.mcp230xx_int_timer)) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - INTCNT enabled for pin D%i but global INTTIMER is disabled!"),pin); - } - MCP230xx_CheckForIntCounter(); - Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); - return serviced; - } else { - serviced=false; - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); - return serviced; - } - } - serviced = false; - return serviced; - } else { - serviced = false; - return serviced; - } - } - - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTRETAIN")) { - if (paramcount > 1) { - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if (pin < mcp230xx_pincount) { - if (pin == 0) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; - } else { - validpin = true; - } - } - if (validpin) { - if (paramcount > 2) { - uint8_t int_retain = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - if ((int_retain >= 0) && (int_retain <= 1)) { - Settings.mcp230xx_config[pin].int_retain_flag=int_retain; - Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); - MCP230xx_CheckForIntRetainer(); - return serviced; - } else { - serviced=false; - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); - return serviced; - } - } - serviced = false; - return serviced; - } else { - serviced = false; - return serviced; - } - } - - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); - - if (pin < mcp230xx_pincount) { - if (0 == pin) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1), "0")) validpin=true; - } else { - validpin=true; - } - } - if (validpin && (paramcount > 1)) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "?")) { - uint8_t port = 0; - if (pin > 7) { port = 1; } - uint8_t portdata = MCP230xx_readGPIO(port); - char pulluptxtr[7],pinstatustxtr[7]; - char intmodetxt[9]; - sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); - sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup)); -#ifdef USE_MCP230xx_OUTPUT - uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode; - sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); - Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr); -#else - sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); - Response_P(MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,intmodetxt,pinstatustxtr); -#endif - return serviced; - } -#ifdef USE_MCP230xx_OUTPUT - if (Settings.mcp230xx_config[pin].pinmode >= 5) { - uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "ON")) { - MCP230xx_SetOutPin(pin,abs(pincmd-1)); - return serviced; - } - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "OFF")) { - MCP230xx_SetOutPin(pin,pincmd); - return serviced; - } - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "T")) { - MCP230xx_SetOutPin(pin,2); - return serviced; - } - } -#endif - uint8_t pinmode = 0; - uint8_t pullup = 0; - uint8_t intmode = 0; - if (paramcount > 1) { - pinmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - } - if (paramcount > 2) { - pullup = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - } - if (paramcount > 3) { - intmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); - } -#ifdef USE_MCP230xx_OUTPUT - if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 7) && (pullup < 2)) { -#else - if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 5) && (pullup < 2)) { -#endif - Settings.mcp230xx_config[pin].pinmode=pinmode; - Settings.mcp230xx_config[pin].pullup=pullup; - if ((pinmode > 1) && (pinmode < 5)) { - if ((intmode >= 0) && (intmode <= 3)) { - Settings.mcp230xx_config[pin].int_report_mode=intmode; - } - } else { - Settings.mcp230xx_config[pin].int_report_mode=3; - } - MCP230xx_ApplySettings(); - uint8_t port = 0; - if (pin > 7) { port = 1; } - uint8_t portdata = MCP230xx_readGPIO(port); - char pulluptxtc[7], pinstatustxtc[7]; - char intmodetxt[9]; - sprintf(pulluptxtc,ConvertNumTxt(pullup)); - sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); -#ifdef USE_MCP230xx_OUTPUT - sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1,Settings.mcp230xx_config[pin].pinmode)); -#else - sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1)); -#endif - Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); - return serviced; - } - } else { - serviced=false; - return serviced; - } - return serviced; -} - -#ifdef USE_MCP230xx_DISPLAYOUTPUT - -const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "{s}MCP230XX D%d{m}%s{e}"; - -void MCP230xx_UpdateWebData(void) { - uint8_t gpio1 = MCP230xx_readGPIO(0); - uint8_t gpio2 = 0; - if (2 == mcp230xx_type) { - gpio2 = MCP230xx_readGPIO(1); - } - uint16_t gpio = (gpio2 << 8) + gpio1; - for (uint32_t pin = 0; pin < mcp230xx_pincount; pin++) { - if (Settings.mcp230xx_config[pin].pinmode >= 5) { - char stt[7]; - sprintf(stt,ConvertNumTxt((gpio>>pin)&1,Settings.mcp230xx_config[pin].pinmode)); - WSContentSend_PD(HTTP_SNS_MCP230xx_OUTPUT, pin, stt); - } - } -} - -#endif - -#ifdef USE_MCP230xx_OUTPUT - -void MCP230xx_OutputTelemetry(void) { - if (0 == mcp230xx_type) { return; } - uint8_t outputcount = 0; - uint16_t gpiototal = 0; - uint8_t gpioa = 0; - uint8_t gpiob = 0; - gpioa=MCP230xx_readGPIO(0); - if (2 == mcp230xx_type) { gpiob=MCP230xx_readGPIO(1); } - gpiototal=((uint16_t)gpiob << 8) | gpioa; - for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].pinmode >= 5) outputcount++; - } - if (outputcount) { - char stt[7]; - ResponseTime_P(PSTR(",\"MCP230_OUT\":{")); - for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].pinmode >= 5) { - sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); - ResponseAppend_P(PSTR("\"OUT_D%i\":\"%s\","),pinx,stt); - } - } - ResponseAppend_P(PSTR("\"END\":1}}")); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - } -} - -#endif - -void MCP230xx_Interrupt_Counter_Report(void) { - ResponseTime_P(PSTR(",\"MCP230_INTTIMER\":{")); - for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].int_count_en) { - ResponseAppend_P(PSTR("\"INTCNT_D%i\":%i,"),pinx,mcp230xx_int_counter[pinx]); - mcp230xx_int_counter[pinx]=0; - } - } - ResponseAppend_P(PSTR("\"END\":1}}")); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - mcp230xx_int_sec_counter = 0; -} - -void MCP230xx_Interrupt_Retain_Report(void) { - uint16_t retainresult = 0; - ResponseTime_P(PSTR(",\"MCP_INTRETAIN\":{")); - for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].int_retain_flag) { - ResponseAppend_P(PSTR("\"D%i\":%i,"),pinx,mcp230xx_int_retainer[pinx]); - retainresult |= (((mcp230xx_int_retainer[pinx])&1) << pinx); - mcp230xx_int_retainer[pinx]=0; - } - } - ResponseAppend_P(PSTR("\"Value\":%u}}"),retainresult); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -} - - - - - -bool Xsns29(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_EVERY_SECOND: - MCP230xx_Detect(); - if (mcp230xx_int_counter_en) { - mcp230xx_int_sec_counter++; - if (mcp230xx_int_sec_counter >= Settings.mcp230xx_int_timer) { - MCP230xx_Interrupt_Counter_Report(); - } - } - if (tele_period == 0) { - if (mcp230xx_int_retainer_en) { - MCP230xx_Interrupt_Retain_Report(); - } - } -#ifdef USE_MCP230xx_OUTPUT - if (tele_period == 0) { - MCP230xx_OutputTelemetry(); - } -#endif - break; - case FUNC_EVERY_50_MSECOND: - if ((mcp230xx_int_en) && (mcp230xx_type)) { - mcp230xx_int_prio_counter++; - if ((mcp230xx_int_prio_counter) >= (Settings.mcp230xx_int_prio)) { - MCP230xx_CheckForInterrupt(); - mcp230xx_int_prio_counter=0; - } - } - break; - case FUNC_JSON_APPEND: - MCP230xx_Show(1); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_29 == XdrvMailbox.index) { - result = MCP230xx_Command(); - } - break; -#ifdef USE_WEBSERVER -#ifdef USE_MCP230xx_OUTPUT -#ifdef USE_MCP230xx_DISPLAYOUTPUT - case FUNC_WEB_SENSOR: - MCP230xx_UpdateWebData(); - break; -#endif -#endif -#endif - default: - break; - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_30_mpr121.ino" -# 43 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_30_mpr121.ino" -#ifdef USE_I2C -#ifdef USE_MPR121 - - - - - -#define XSNS_30 30 - - - - - - - -#define MPR121_ELEX_REG 0x00 - - -#define MPR121_MHDR_REG 0x2B - - -#define MPR121_MHDR_VAL 0x01 - - -#define MPR121_NHDR_REG 0x2C - - -#define MPR121_NHDR_VAL 0x01 - - -#define MPR121_NCLR_REG 0x2D - - -#define MPR121_NCLR_VAL 0x0E - - -#define MPR121_MHDF_REG 0x2F - - -#define MPR121_MHDF_VAL 0x01 - - -#define MPR121_NHDF_REG 0x30 - - -#define MPR121_NHDF_VAL 0x05 - - -#define MPR121_NCLF_REG 0x31 - - -#define MPR121_NCLF_VAL 0x01 - - -#define MPR121_MHDPROXR_REG 0x36 - - -#define MPR121_MHDPROXR_VAL 0x3F - - -#define MPR121_NHDPROXR_REG 0x37 - - -#define MPR121_NHDPROXR_VAL 0x5F - - -#define MPR121_NCLPROXR_REG 0x38 - - -#define MPR121_NCLPROXR_VAL 0x04 - - -#define MPR121_FDLPROXR_REG 0x39 - - -#define MPR121_FDLPROXR_VAL 0x00 - - -#define MPR121_MHDPROXF_REG 0x3A - - -#define MPR121_MHDPROXF_VAL 0x01 - - -#define MPR121_NHDPROXF_REG 0x3B - - -#define MPR121_NHDPROXF_VAL 0x01 - - -#define MPR121_NCLPROXF_REG 0x3C - - -#define MPR121_NCLPROXF_VAL 0x1F - - -#define MPR121_FDLPROXF_REG 0x3D - - -#define MPR121_FDLPROXF_VAL 0x04 - - -#define MPR121_E0TTH_REG 0x41 - - -#define MPR121_E0TTH_VAL 12 - - -#define MPR121_E0RTH_REG 0x42 - - -#define MPR121_E0RTH_VAL 6 - - -#define MPR121_CDT_REG 0x5D - - -#define MPR121_CDT_VAL 0x20 - - -#define MPR121_ECR_REG 0x5E - - -#define MPR121_ECR_VAL 0x8F - - - -#define MPR121_SRST_REG 0x80 - - -#define MPR121_SRST_VAL 0x63 - - -#define BITC(sensor,position) ((pS->current[sensor] >> position) & 1) - - -#define BITP(sensor,position) ((pS->previous[sensor] >> position) & 1) -# 191 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_30_mpr121.ino" -typedef struct mpr121 mpr121; -struct mpr121 { - const uint8_t i2c_addr[4] = { 0x5A, 0x5B, 0x5C, 0x5D }; - const char id[4] = { 'A', 'B', 'C', 'D' }; - bool connected[4] = { false, false, false, false }; - bool running[4] = { false, false, false, false }; - uint16_t current[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; - uint16_t previous[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; -}; -# 211 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_30_mpr121.ino" -void Mpr121Init(struct mpr121 *pS) -{ - - - for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { - - - pS->connected[i] = (I2cWrite8(pS->i2c_addr[i], MPR121_SRST_REG, MPR121_SRST_VAL) - && (0x24 == I2cRead8(pS->i2c_addr[i], 0x5D))); - if (pS->connected[i]) { - - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "MPR121(%c) " D_FOUND_AT " 0x%X"), pS->id[i], pS->i2c_addr[i]); - - - for (uint32_t j = 0; j < 13; j++) { - - - I2cWrite8(pS->i2c_addr[i], MPR121_E0TTH_REG + 2 * j, MPR121_E0TTH_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_E0RTH_REG + 2 * j, MPR121_E0RTH_VAL); - } - - - I2cWrite8(pS->i2c_addr[i], MPR121_MHDR_REG, MPR121_MHDR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NHDR_REG, MPR121_NHDR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NCLR_REG, MPR121_NCLR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_MHDF_REG, MPR121_MHDF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NHDF_REG, MPR121_NHDF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NCLF_REG, MPR121_NCLF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXR_REG, MPR121_MHDPROXR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXR_REG, MPR121_NHDPROXR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXR_REG, MPR121_NCLPROXR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXR_REG, MPR121_FDLPROXR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXF_REG, MPR121_MHDPROXF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXF_REG, MPR121_NHDPROXF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXF_REG, MPR121_NCLPROXF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXF_REG, MPR121_FDLPROXF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_CDT_REG, MPR121_CDT_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_ECR_REG, MPR121_ECR_VAL); - - - pS->running[i] = (0x00 != I2cRead8(pS->i2c_addr[i], MPR121_ECR_REG)); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "MPR121%c: %sRunning"), pS->id[i], (pS->running[i]) ? "" : "NOT"); - - } else { - - - pS->running[i] = false; - } - } - - - if (!(pS->connected[0] || pS->connected[1] || pS->connected[2] - || pS->connected[3])) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C "MPR121: No sensors found")); - } -} -# 316 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_30_mpr121.ino" -void Mpr121Show(struct mpr121 *pS, uint8_t function) -{ - - - for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { - - - if (pS->connected[i]) { - - - if (!I2cValidRead16LE(&pS->current[i], pS->i2c_addr[i], MPR121_ELEX_REG)) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Cannot read data!"), pS->id[i]); - Mpr121Init(pS); - return; - } - - if (BITC(i, 15)) { - - - I2cWrite8(pS->i2c_addr[i], MPR121_ELEX_REG, 0x00); - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Excess current detected! Fix circuits if it happens repeatedly! Soft-resetting MPR121 ..."), pS->id[i]); - Mpr121Init(pS); - return; - } - } - - if (pS->running[i]) { - - - if (FUNC_JSON_APPEND == function) { - ResponseAppend_P(PSTR(",\"MPR121%c\":{"), pS->id[i]); - } - - for (uint32_t j = 0; j < 13; j++) { - - - if ((FUNC_EVERY_50_MSECOND == function) - && (BITC(i, j) != BITP(i, j))) { - Response_P(PSTR("{\"MPR121%c\":{\"Button%i\":%i}}"), pS->id[i], j, BITC(i, j)); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); - } - -#ifdef USE_WEBSERVER - if (FUNC_WEB_SENSOR == function) { - WSContentSend_PD(PSTR("{s}MPR121%c Button%d{m}%d{e}"), pS->id[i], j, BITC(i, j)); - } -#endif - - - if (FUNC_JSON_APPEND == function) { - ResponseAppend_P(PSTR("%s\"Button%i\":%i"), (j > 0 ? "," : ""), j, BITC(i, j)); - } - } - - - pS->previous[i] = pS->current[i]; - - - if (FUNC_JSON_APPEND == function) { - ResponseJsonEnd(); - } - } - } -} -# 400 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_30_mpr121.ino" -bool Xsns30(uint8_t function) -{ - - bool result = false; - - - static struct mpr121 mpr121; - - - if (i2c_flg) { - switch (function) { - - - case FUNC_INIT: - Mpr121Init(&mpr121); - break; - - - case FUNC_EVERY_50_MSECOND: - Mpr121Show(&mpr121, FUNC_EVERY_50_MSECOND); - break; - - - case FUNC_JSON_APPEND: - Mpr121Show(&mpr121, FUNC_JSON_APPEND); - break; - -#ifdef USE_WEBSERVER - - case FUNC_WEB_SENSOR: - Mpr121Show(&mpr121, FUNC_WEB_SENSOR); - break; -#endif - } - } - - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_31_ccs811.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_31_ccs811.ino" -#ifdef USE_I2C -#ifdef USE_CCS811 -# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_31_ccs811.ino" -#define XSNS_31 31 - -#include "Adafruit_CCS811.h" - -Adafruit_CCS811 ccs; -uint8_t CCS811_ready; -uint8_t CCS811_type; -uint16_t eCO2; -uint16_t TVOC; -uint8_t tcnt = 0; -uint8_t ecnt = 0; - - -#define EVERYNSECONDS 5 - -void CCS811Update(void) -{ - tcnt++; - if (tcnt >= EVERYNSECONDS) { - tcnt = 0; - CCS811_ready = 0; - if (!CCS811_type) { - sint8_t res = ccs.begin(CCS811_ADDRESS); - if (!res) { - CCS811_type = 1; - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "CCS811", 0x5A); - } else { - - } - } else { - if (ccs.available()) { - if (!ccs.readData()){ - TVOC = ccs.getTVOC(); - eCO2 = ccs.geteCO2(); - CCS811_ready = 1; - if (global_update && global_humidity>0 && global_temperature!=9999) { ccs.setEnvironmentalData((uint8_t)global_humidity, global_temperature); } - ecnt = 0; - } - } else { - - ecnt++; - if (ecnt > 6) { - - ccs.begin(CCS811_ADDRESS); - } - } - } - } -} - -const char HTTP_SNS_CCS811[] PROGMEM = - "{s}CCS811 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" - "{s}CCS811 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; - -void CCS811Show(bool json) -{ - if (CCS811_ready) { - if (json) { - ResponseAppend_P(PSTR(",\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), eCO2,TVOC); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, eCO2); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CCS811, eCO2, TVOC); -#endif - } - } -} - - - - - -bool Xsns31(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_EVERY_SECOND: - CCS811Update(); - break; - case FUNC_JSON_APPEND: - CCS811Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - CCS811Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_32_mpu6050.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_32_mpu6050.ino" -#ifdef USE_I2C -#ifdef USE_MPU6050 -# 30 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_32_mpu6050.ino" -#define XSNS_32 32 - -#define D_SENSOR_MPU6050 "MPU6050" - -#define MPU_6050_ADDR_AD0_LOW 0x68 -#define MPU_6050_ADDR_AD0_HIGH 0x69 - -uint8_t MPU_6050_address; -uint8_t MPU_6050_addresses[] = { MPU_6050_ADDR_AD0_LOW, MPU_6050_ADDR_AD0_HIGH }; -uint8_t MPU_6050_found; - -int16_t MPU_6050_ax = 0, MPU_6050_ay = 0, MPU_6050_az = 0; -int16_t MPU_6050_gx = 0, MPU_6050_gy = 0, MPU_6050_gz = 0; -int16_t MPU_6050_temperature = 0; - -#ifdef USE_MPU6050_DMP - #include "MPU6050_6Axis_MotionApps20.h" - #include "I2Cdev.h" - #include - typedef struct MPU6050_DMP{ - uint8_t devStatus; - uint16_t packetSize; - uint16_t fifoCount; - uint8_t fifoBuffer[64]; - Quaternion q; - VectorInt16 aa; - VectorInt16 aaReal; - VectorFloat gravity; - float euler[3]; - } MPU6050_DMP; - - MPU6050_DMP MPU6050_dmp; -#else - #include -#endif -MPU6050 mpu6050; - -void MPU_6050PerformReading(void) -{ -#ifdef USE_MPU6050_DMP - mpu6050.resetFIFO(); - MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); - while (MPU6050_dmp.fifoCount < MPU6050_dmp.packetSize) MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); - mpu6050.getFIFOBytes(MPU6050_dmp.fifoBuffer, MPU6050_dmp.packetSize); - MPU6050_dmp.fifoCount -= MPU6050_dmp.packetSize; - - mpu6050.dmpGetQuaternion(&MPU6050_dmp.q, MPU6050_dmp.fifoBuffer); - mpu6050.dmpGetEuler(MPU6050_dmp.euler, &MPU6050_dmp.q); - mpu6050.dmpGetAccel(&MPU6050_dmp.aa, MPU6050_dmp.fifoBuffer); - mpu6050.dmpGetGravity(&MPU6050_dmp.gravity, &MPU6050_dmp.q); - mpu6050.dmpGetLinearAccel(&MPU6050_dmp.aaReal, &MPU6050_dmp.aa, &MPU6050_dmp.gravity); - MPU_6050_gx = MPU6050_dmp.euler[0] * 180/M_PI; - MPU_6050_gy = MPU6050_dmp.euler[1] * 180/M_PI; - MPU_6050_gz = MPU6050_dmp.euler[2] * 180/M_PI; - MPU_6050_ax = MPU6050_dmp.aaReal.x; - MPU_6050_ay = MPU6050_dmp.aaReal.y; - MPU_6050_az = MPU6050_dmp.aaReal.z; -#else - mpu6050.getMotion6( - &MPU_6050_ax, - &MPU_6050_ay, - &MPU_6050_az, - &MPU_6050_gx, - &MPU_6050_gy, - &MPU_6050_gz - ); -#endif - MPU_6050_temperature = mpu6050.getTemperature(); -} -# 116 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_32_mpu6050.ino" -void MPU_6050Detect(void) -{ - if (MPU_6050_found) - { - return; - } - - for (uint32_t i = 0; i < sizeof(MPU_6050_addresses); i++) - { - if(!I2cDevice(MPU_6050_addresses[i])) - { - break; - } - MPU_6050_address = MPU_6050_addresses[i]; - mpu6050.setAddr(MPU_6050_addresses[i]); - -#ifdef USE_MPU6050_DMP - MPU6050_dmp.devStatus = mpu6050.dmpInitialize(); - mpu6050.setXGyroOffset(220); - mpu6050.setYGyroOffset(76); - mpu6050.setZGyroOffset(-85); - mpu6050.setZAccelOffset(1788); - if (MPU6050_dmp.devStatus == 0) { - mpu6050.setDMPEnabled(true); - MPU6050_dmp.packetSize = mpu6050.dmpGetFIFOPacketSize(); - MPU_6050_found = true; - } -#else - mpu6050.initialize(); - MPU_6050_found = mpu6050.testConnection(); -#endif - Settings.flag2.axis_resolution = 2; - - } - - if (MPU_6050_found) - { - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, D_SENSOR_MPU6050, MPU_6050_address); - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_AXIS[] PROGMEM = - "{s}" D_SENSOR_MPU6050 " " D_AX_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_AY_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_AZ_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_GX_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_GY_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_GZ_AXIS "{m}%s{e}"; -#endif - -#define D_JSON_AXIS_AX "AccelXAxis" -#define D_JSON_AXIS_AY "AccelYAxis" -#define D_JSON_AXIS_AZ "AccelZAxis" -#define D_JSON_AXIS_GX "GyroXAxis" -#define D_JSON_AXIS_GY "GyroYAxis" -#define D_JSON_AXIS_GZ "GyroZAxis" - -void MPU_6050Show(bool json) -{ - if (MPU_6050_found) { - MPU_6050PerformReading(); - - double tempConv = (MPU_6050_temperature / 340.0 + 35.53); - char temperature[33]; - dtostrfd(tempConv, Settings.flag2.temperature_resolution, temperature); - char axis_ax[33]; - dtostrfd(MPU_6050_ax, Settings.flag2.axis_resolution, axis_ax); - char axis_ay[33]; - dtostrfd(MPU_6050_ay, Settings.flag2.axis_resolution, axis_ay); - char axis_az[33]; - dtostrfd(MPU_6050_az, Settings.flag2.axis_resolution, axis_az); - char axis_gx[33]; - dtostrfd(MPU_6050_gx, Settings.flag2.axis_resolution, axis_gx); - char axis_gy[33]; - dtostrfd(MPU_6050_gy, Settings.flag2.axis_resolution, axis_gy); - char axis_gz[33]; - dtostrfd(MPU_6050_gz, Settings.flag2.axis_resolution, axis_gz); - - if (json) { - char json_axis_ax[25]; - snprintf_P(json_axis_ax, sizeof(json_axis_ax), PSTR(",\"" D_JSON_AXIS_AX "\":%s"), axis_ax); - char json_axis_ay[25]; - snprintf_P(json_axis_ay, sizeof(json_axis_ay), PSTR(",\"" D_JSON_AXIS_AY "\":%s"), axis_ay); - char json_axis_az[25]; - snprintf_P(json_axis_az, sizeof(json_axis_az), PSTR(",\"" D_JSON_AXIS_AZ "\":%s"), axis_az); - char json_axis_gx[25]; - snprintf_P(json_axis_gx, sizeof(json_axis_gx), PSTR(",\"" D_JSON_AXIS_GX "\":%s"), axis_gx); - char json_axis_gy[25]; - snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy); - char json_axis_gz[25]; - snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), - D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_TEMP, temperature); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, D_SENSOR_MPU6050, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_AXIS, axis_ax, axis_ay, axis_az, axis_gx, axis_gy, axis_gz); -#endif - } - } -} - - - - - -bool Xsns32(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_PREP_BEFORE_TELEPERIOD: - MPU_6050Detect(); - break; - case FUNC_EVERY_SECOND: - if (tele_period == Settings.tele_period -3) { - MPU_6050PerformReading(); - } - break; - case FUNC_JSON_APPEND: - MPU_6050Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MPU_6050Show(0); - MPU_6050PerformReading(); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_33_ds3231.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_33_ds3231.ino" -#ifdef USE_I2C -#ifdef USE_DS3231 -# 35 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_33_ds3231.ino" -#define XSNS_33 33 - - -#ifndef USE_RTC_ADDR -#define USE_RTC_ADDR 0x68 -#endif - - -#define RTC_SECONDS 0x00 -#define RTC_MINUTES 0x01 -#define RTC_HOURS 0x02 -#define RTC_DAY 0x03 -#define RTC_DATE 0x04 -#define RTC_MONTH 0x05 -#define RTC_YEAR 0x06 -#define RTC_CONTROL 0x0E -#define RTC_STATUS 0x0F - -#define OSF 7 -#define EOSC 7 -#define BBSQW 6 -#define CONV 5 -#define RS2 4 -#define RS1 3 -#define INTCN 2 - - -#define HR1224 6 -#define CENTURY 7 -#define DYDT 6 -bool ds3231ReadStatus = false; -bool ds3231WriteStatus = false; -bool DS3231chipDetected = false; - - - - -void DS3231Detect(void) -{ - DS3231chipDetected = false; - if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) { - AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, "DS3231", USE_RTC_ADDR); - DS3231chipDetected = true; - } else { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "DS3231 NOT " D_FOUND_AT " 0x%x"), USE_RTC_ADDR); - } -} - - - - -uint8_t bcd2dec(uint8_t n) -{ - return n - 6 * (n >> 4); -} - - - - -uint8_t dec2bcd(uint8_t n) -{ - return n + 6 * (n / 10); -} - - - - -uint32_t ReadFromDS3231(void) -{ - TIME_T tm; - tm.second = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_SECONDS)); - tm.minute = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MINUTES)); - tm.hour = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_HOURS) & ~_BV(HR1224)); - tm.day_of_week = I2cRead8(USE_RTC_ADDR, RTC_DAY); - tm.day_of_month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_DATE)); - tm.month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MONTH) & ~_BV(CENTURY)); - tm.year = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_YEAR)); - return MakeTime(tm); -} - - - -void SetDS3231Time (uint32_t epoch_time) { - TIME_T tm; - BreakTime(epoch_time, tm); - I2cWrite8(USE_RTC_ADDR, RTC_SECONDS, dec2bcd(tm.second)); - I2cWrite8(USE_RTC_ADDR, RTC_MINUTES, dec2bcd(tm.minute)); - I2cWrite8(USE_RTC_ADDR, RTC_HOURS, dec2bcd(tm.hour)); - I2cWrite8(USE_RTC_ADDR, RTC_DAY, tm.day_of_week); - I2cWrite8(USE_RTC_ADDR, RTC_DATE, dec2bcd(tm.day_of_month)); - I2cWrite8(USE_RTC_ADDR, RTC_MONTH, dec2bcd(tm.month)); - I2cWrite8(USE_RTC_ADDR, RTC_YEAR, dec2bcd(tm.year)); - I2cWrite8(USE_RTC_ADDR, RTC_STATUS, I2cRead8(USE_RTC_ADDR, RTC_STATUS) & ~_BV(OSF)); -} - - - - - -bool Xsns33(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - DS3231Detect(); - break; - case FUNC_EVERY_SECOND: - TIME_T tmpTime; - if (!ds3231ReadStatus && DS3231chipDetected && Rtc.utc_time < START_VALID_TIME ) { - ntp_force_sync = true; - Rtc.utc_time = ReadFromDS3231(); - - - BreakTime(Rtc.utc_time, tmpTime); - if (Rtc.utc_time < START_VALID_TIME ) { - ds3231ReadStatus = true; - } - RtcTime.year = tmpTime.year + 1970; - Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); - Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); - AddLog_P2(LOG_LEVEL_INFO, PSTR("Set time from DS3231 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - if (Rtc.local_time < START_VALID_TIME) { - rules_flag.time_init = 1; - } else { - rules_flag.time_set = 1; - } - } - else if (!ds3231WriteStatus && DS3231chipDetected && Rtc.utc_time > START_VALID_TIME && abs(Rtc.utc_time - ReadFromDS3231()) > 60) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - SetDS3231Time (Rtc.utc_time); - ds3231WriteStatus = true; - } - break; - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_34_hx711.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_34_hx711.ino" -#ifdef USE_HX711 -# 35 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_34_hx711.ino" -#define XSNS_34 34 - -#ifndef HX_MAX_WEIGHT -#define HX_MAX_WEIGHT 20000 -#endif -#ifndef HX_REFERENCE -#define HX_REFERENCE 250 -#endif -#ifndef HX_SCALE -#define HX_SCALE 120 -#endif - -#define HX_TIMEOUT 120 -#define HX_SAMPLES 10 -#define HX_CAL_TIMEOUT 15 - -#define HX_GAIN_128 1 -#define HX_GAIN_32 2 -#define HX_GAIN_64 3 - -#define D_JSON_WEIGHT_REF "WeightRef" -#define D_JSON_WEIGHT_CAL "WeightCal" -#define D_JSON_WEIGHT_MAX "WeightMax" -#define D_JSON_WEIGHT_ITEM "WeightItem" -#define D_JSON_WEIGHT_CHANGE "WeightChange" - -enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, HX_CAL_DONE, HX_CAL_FIRST, HX_CAL_RESET, HX_CAL_START }; - -const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" D_HX_CAL_REFERENCE "|" D_HX_CAL_REMOVE; - -struct HX { - long weight = 0; - long last_weight = 0; - long sum_weight = 0; - long offset = 0; - long scale = 1; - long weight_diff = 0; - uint8_t type = 1; - uint8_t sample_count = 0; - uint8_t calibrate_step = HX_CAL_END; - uint8_t calibrate_timer = 0; - uint8_t calibrate_msg = 0; - uint8_t pin_sck; - uint8_t pin_dout; - bool tare_flg = false; - bool weight_changed = false; -} Hx; - - - -bool HxIsReady(uint16_t timeout) -{ - - uint32_t start = millis(); - while ((digitalRead(Hx.pin_dout) == HIGH) && (millis() - start < timeout)) { yield(); } - return (digitalRead(Hx.pin_dout) == LOW); -} - -long HxRead() -{ - if (!HxIsReady(HX_TIMEOUT)) { return -1; } - - uint8_t data[3] = { 0 }; - uint8_t filler = 0x00; - - - data[2] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); - data[1] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); - data[0] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); - - - for (unsigned int i = 0; i < HX_GAIN_128; i++) { - digitalWrite(Hx.pin_sck, HIGH); - digitalWrite(Hx.pin_sck, LOW); - } - - - if (data[2] & 0x80) { filler = 0xFF; } - - - unsigned long value = ( static_cast(filler) << 24 - | static_cast(data[2]) << 16 - | static_cast(data[1]) << 8 - | static_cast(data[0]) ); - - return static_cast(value); -} - - - -void HxResetPart(void) -{ - Hx.tare_flg = true; - Hx.sum_weight = 0; - Hx.sample_count = 0; - Hx.last_weight = 0; -} - -void HxReset(void) -{ - HxResetPart(); - Settings.energy_frequency_calibration = 0; -} - -void HxCalibrationStateTextJson(uint8_t msg_id) -{ - char cal_text[30]; - - Hx.calibrate_msg = msg_id; - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); - - if (msg_id < 3) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("Sensor34")); } -} -# 168 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_34_hx711.ino" -bool HxCommand(void) -{ - bool serviced = true; - bool show_parms = false; - char sub_string[XdrvMailbox.data_len +1]; - - for (uint32_t ca = 0; ca < XdrvMailbox.data_len; ca++) { - if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; } - } - - switch (XdrvMailbox.payload) { - case 1: - HxReset(); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); - break; - case 2: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - } - Hx.scale = 1; - HxReset(); - Hx.calibrate_step = HX_CAL_START; - Hx.calibrate_timer = 1; - HxCalibrationStateTextJson(3); - break; - case 3: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - } - show_parms = true; - break; - case 4: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_calibration = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - Hx.scale = Settings.weight_calibration; - } - show_parms = true; - break; - case 5: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_max = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) / 1000; - } - show_parms = true; - break; - case 6: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_item = (unsigned long)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10); - } - show_parms = true; - break; - case 7: - Settings.energy_frequency_calibration = Hx.weight; - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, D_JSON_DONE); - break; - case 8: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.SensorBits1.hx711_json_weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) & 1; - } - show_parms = true; - break; - default: - show_parms = true; - } - - if (show_parms) { - char item[33]; - dtostrfd((float)Settings.weight_item / 10, 1, item); - Response_P(PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" D_JSON_WEIGHT_ITEM "\":%s,\"" D_JSON_WEIGHT_CHANGE "\":\"%s\"}}"), - Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, item, GetStateText(Settings.SensorBits1.hx711_json_weight_change)); - } - - return serviced; -} - - - -long HxWeight() -{ - return (Hx.calibrate_step < HX_CAL_FAIL) ? Hx.weight : 0; -} - -void HxInit(void) -{ - Hx.type = 0; - if ((pin[GPIO_HX711_DAT] < 99) && (pin[GPIO_HX711_SCK] < 99)) { - Hx.pin_sck = pin[GPIO_HX711_SCK]; - Hx.pin_dout = pin[GPIO_HX711_DAT]; - - pinMode(Hx.pin_sck, OUTPUT); - pinMode(Hx.pin_dout, INPUT); - - digitalWrite(Hx.pin_sck, LOW); - - if (HxIsReady(8 * HX_TIMEOUT)) { - if (!Settings.weight_max) { Settings.weight_max = HX_MAX_WEIGHT / 1000; } - if (!Settings.weight_calibration) { Settings.weight_calibration = HX_SCALE; } - if (!Settings.weight_reference) { Settings.weight_reference = HX_REFERENCE; } - Hx.scale = Settings.weight_calibration; - HxRead(); - HxResetPart(); - Hx.type = 1; - } - } -} - -void HxEvery100mSecond(void) -{ - Hx.sum_weight += HxRead(); - - Hx.sample_count++; - if (HX_SAMPLES == Hx.sample_count) { - long average = Hx.sum_weight / Hx.sample_count; - long value = average - Hx.offset; - Hx.weight = value / Hx.scale; - if (Hx.weight < 0) { - if (Settings.energy_frequency_calibration) { - long difference = Settings.energy_frequency_calibration + Hx.weight; - Hx.last_weight = difference; - if (difference < 0) { HxReset(); } - } - Hx.weight = 0; - } else { - Hx.last_weight = Settings.energy_frequency_calibration; - } - - if (Hx.tare_flg) { - Hx.tare_flg = false; - Hx.offset = average; - } - - if (Hx.calibrate_step) { - Hx.calibrate_timer--; - - if (HX_CAL_START == Hx.calibrate_step) { - Hx.calibrate_step--; - Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); - } - else if (HX_CAL_RESET == Hx.calibrate_step) { - if (Hx.calibrate_timer) { - if (Hx.weight < (long)Settings.weight_reference) { - Hx.calibrate_step--; - Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); - HxCalibrationStateTextJson(2); - } - } else { - Hx.calibrate_step = HX_CAL_FAIL; - } - } - else if (HX_CAL_FIRST == Hx.calibrate_step) { - if (Hx.calibrate_timer) { - if (Hx.weight > (long)Settings.weight_reference) { - Hx.calibrate_step--; - } - } else { - Hx.calibrate_step = HX_CAL_FAIL; - } - } - else if (HX_CAL_DONE == Hx.calibrate_step) { - if (Hx.weight > (long)Settings.weight_reference) { - Hx.calibrate_step = HX_CAL_FINISH; - Settings.weight_calibration = Hx.weight / Settings.weight_reference; - Hx.weight = 0; - HxCalibrationStateTextJson(1); - } else { - Hx.calibrate_step = HX_CAL_FAIL; - } - } - - if (HX_CAL_FAIL == Hx.calibrate_step) { - Hx.calibrate_step--; - Hx.tare_flg = true; - HxCalibrationStateTextJson(0); - } - if (HX_CAL_FINISH == Hx.calibrate_step) { - Hx.calibrate_step--; - Hx.calibrate_timer = 3 * (10 / HX_SAMPLES); - Hx.scale = Settings.weight_calibration; - } - - if (!Hx.calibrate_timer) { - Hx.calibrate_step = HX_CAL_END; - } - } else { - Hx.weight += Hx.last_weight; - - if (Settings.SensorBits1.hx711_json_weight_change) { - if (abs(Hx.weight - Hx.weight_diff) > 4) { - Hx.weight_diff = Hx.weight; - Hx.weight_changed = true; - } - else if (Hx.weight_changed && (Hx.weight == Hx.weight_diff)) { - mqtt_data[0] = '\0'; - ResponseAppendTime(); - HxShow(true); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - Hx.weight_changed = false; - } - } - } - - Hx.sum_weight = 0; - Hx.sample_count = 0; - } -} - -void HxSaveBeforeRestart() -{ - Settings.energy_frequency_calibration = Hx.weight; - Hx.sample_count = HX_SAMPLES +1; -} - -#ifdef USE_WEBSERVER -const char HTTP_HX711_WEIGHT[] PROGMEM = - "{s}HX711 " D_WEIGHT "{m}%s " D_UNIT_KILOGRAM "{e}"; -const char HTTP_HX711_COUNT[] PROGMEM = - "{s}HX711 " D_COUNT "{m}%d{e}"; -const char HTTP_HX711_CAL[] PROGMEM = - "{s}HX711 %s{m}{e}"; -#endif - -void HxShow(bool json) -{ - char scount[30] = { 0 }; - - uint16_t count = 0; - float weight = 0; - if (Hx.calibrate_step < HX_CAL_FAIL) { - if (Hx.weight && Settings.weight_item) { - count = (Hx.weight * 10) / Settings.weight_item; - if (count > 1) { - snprintf_P(scount, sizeof(scount), PSTR(",\"" D_JSON_COUNT "\":%d"), count); - } - } - weight = (float)Hx.weight / 1000; - } - char weight_chr[33]; - dtostrfd(weight, Settings.flag2.weight_resolution, weight_chr); - - if (json) { - ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s}"), weight_chr, scount); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr); - if (count > 1) { - WSContentSend_PD(HTTP_HX711_COUNT, count); - } - if (Hx.calibrate_step) { - char cal_text[30]; - WSContentSend_PD(HTTP_HX711_CAL, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); - } -#endif - } -} - -#ifdef USE_WEBSERVER -#ifdef USE_HX711_GUI - - - - -#define WEB_HANDLE_HX711 "s34" - -const char S_CONFIGURE_HX711[] PROGMEM = D_CONFIGURE_HX711; - -const char HTTP_BTN_MENU_MAIN_HX711[] PROGMEM = - "

"; - -const char HTTP_BTN_MENU_HX711[] PROGMEM = - "

"; - -const char HTTP_FORM_HX711[] PROGMEM = - "
 " D_CALIBRATION " " - "
" - "

" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" - "
" - "
" - "


" - - "
 " D_HX711_PARAMETERS " " - "
" - "

" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; - -void HandleHxAction(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_HX711); - - if (WebServer->hasArg("save")) { - HxSaveSettings(); - HandleConfiguration(); - return; - } - - char stemp1[20]; - - if (WebServer->hasArg("reset")) { - snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 1")); - ExecuteWebCommand(stemp1, SRC_WEBGUI); - - HandleRoot(); - return; - } - - if (WebServer->hasArg("calibrate")) { - WebGetArg("p1", stemp1, sizeof(stemp1)); - Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000); - - HxLogUpdates(); - - snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 2")); - ExecuteWebCommand(stemp1, SRC_WEBGUI); - - HandleRoot(); - return; - } - - WSContentStart_P(S_CONFIGURE_HX711); - WSContentSendStyle(); - dtostrfd((float)Settings.weight_reference / 1000, 3, stemp1); - char stemp2[20]; - dtostrfd((float)Settings.weight_item / 10000, 4, stemp2); - WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void HxSaveSettings(void) -{ - char tmp[100]; - - WebGetArg("p2", tmp, sizeof(tmp)); - Settings.weight_item = (!strlen(tmp)) ? 0 : (unsigned long)(CharToFloat(tmp) * 10000); - - HxLogUpdates(); -} - -void HxLogUpdates(void) -{ - char weigth_ref_chr[33]; - dtostrfd((float)Settings.weight_reference / 1000, Settings.flag2.weight_resolution, weigth_ref_chr); - char weigth_item_chr[33]; - dtostrfd((float)Settings.weight_item / 10000, 4, weigth_item_chr); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_JSON_WEIGHT_REF " %s, " D_JSON_WEIGHT_ITEM " %s"), weigth_ref_chr, weigth_item_chr); -} - -#endif -#endif - - - - - -bool Xsns34(uint8_t function) -{ - bool result = false; - - if (Hx.type) { - switch (function) { - case FUNC_EVERY_100_MSECOND: - HxEvery100mSecond(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_34 == XdrvMailbox.index) { - result = HxCommand(); - } - break; - case FUNC_JSON_APPEND: - HxShow(1); - break; - case FUNC_SAVE_BEFORE_RESTART: - HxSaveBeforeRestart(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HxShow(0); - break; -#ifdef USE_HX711_GUI - case FUNC_WEB_ADD_MAIN_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_MAIN_HX711); - break; - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_HX711); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); - break; -#endif -#endif - case FUNC_INIT: - HxInit(); - break; - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_35_tx20.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_35_tx20.ino" -#ifdef USE_TX20_WIND_SENSOR -# 29 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_35_tx20.ino" -#define XSNS_35 35 - -#define TX20_BIT_TIME 1220 -#define TX20_RESET_VALUES 60 - - - -extern "C" { -#include "gpio.h" -} - -#ifdef USE_WEBSERVER - -const char HTTP_SNS_TX20[] PROGMEM = - "{s}TX20 " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}TX20 " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}TX20 " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}TX20 " D_TX20_WIND_DIRECTION "{m}%s{e}"; - -#endif - -const char kTx20Directions[] PROGMEM = D_TX20_NORTH "|" - D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" - D_TX20_NORTH D_TX20_EAST "|" - D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" - D_TX20_EAST "|" - D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH "|" - D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_WEST "|" - D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" - D_TX20_NORTH D_TX20_WEST "|" - D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; - -uint8_t tx20_sa = 0; -uint8_t tx20_sb = 0; -uint8_t tx20_sd = 0; -uint8_t tx20_se = 0; -uint16_t tx20_sc = 0; -uint16_t tx20_sf = 0; - -float tx20_wind_speed_kmh = 0; -float tx20_wind_speed_max = 0; -float tx20_wind_speed_avg = 0; -float tx20_wind_sum = 0; -int tx20_count = 0; -uint8_t tx20_wind_direction = 0; - -bool tx20_available = false; - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -void Tx20StartRead(void) ICACHE_RAM_ATTR; -#endif - -void Tx20StartRead(void) -{ -# 101 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_35_tx20.ino" - tx20_available = false; - - tx20_sa = 0; - tx20_sb = 0; - tx20_sd = 0; - tx20_se = 0; - tx20_sc = 0; - tx20_sf = 0; - - delayMicroseconds(TX20_BIT_TIME / 2); - - for (int32_t bitcount = 41; bitcount > 0; bitcount--) { - uint8_t dpin = (digitalRead(pin[GPIO_TX20_TXD_BLACK])); - if (bitcount > 41 - 5) { - - tx20_sa = (tx20_sa << 1) | (dpin ^ 1); - } else if (bitcount > 41 - 5 - 4) { - - tx20_sb = tx20_sb >> 1 | ((dpin ^ 1) << 3); - } else if (bitcount > 41 - 5 - 4 - 12) { - - tx20_sc = tx20_sc >> 1 | ((dpin ^ 1) << 11); - } else if (bitcount > 41 - 5 - 4 - 12 - 4) { - - tx20_sd = tx20_sd >> 1 | ((dpin ^ 1) << 3); - } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { - - tx20_se = tx20_se >> 1 | (dpin << 3); - } else { - - tx20_sf = tx20_sf >> 1 | (dpin << 11); - } - - delayMicroseconds(TX20_BIT_TIME); - } - - uint8_t chk = (tx20_sb + (tx20_sc & 0xf) + ((tx20_sc >> 4) & 0xf) + ((tx20_sc >> 8) & 0xf)); - chk &= 0xf; - - if ((chk == tx20_sd) && (tx20_sc < 400)) { - tx20_available = true; - } - - - - - - - - GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX20_TXD_BLACK]); -} - -void Tx20Read(void) -{ - if (!(uptime % TX20_RESET_VALUES)) { - tx20_count = 0; - tx20_wind_sum = 0; - tx20_wind_speed_max = 0; - } - else if (tx20_available) { - tx20_wind_speed_kmh = float(tx20_sc) * 0.36; - if (tx20_wind_speed_kmh > tx20_wind_speed_max) { - tx20_wind_speed_max = tx20_wind_speed_kmh; - } - tx20_count++; - tx20_wind_sum += tx20_wind_speed_kmh; - tx20_wind_speed_avg = tx20_wind_sum / tx20_count; - tx20_wind_direction = tx20_sb; - } -} - -void Tx20Init(void) { - pinMode(pin[GPIO_TX20_TXD_BLACK], INPUT); - attachInterrupt(pin[GPIO_TX20_TXD_BLACK], Tx20StartRead, RISING); -} - -void Tx20Show(bool json) -{ - char wind_speed_string[33]; - dtostrfd(tx20_wind_speed_kmh, 2, wind_speed_string); - char wind_speed_max_string[33]; - dtostrfd(tx20_wind_speed_max, 2, wind_speed_max_string); - char wind_speed_avg_string[33]; - dtostrfd(tx20_wind_speed_avg, 2, wind_speed_avg_string); - char wind_direction_string[4]; - GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx20_wind_direction, kTx20Directions); - - if (json) { - ResponseAppend_P(PSTR(",\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"), - wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TX20, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); -#endif - } -} - - - - - -bool Xsns35(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_TX20_TXD_BLACK] < 99) { - switch (function) { - case FUNC_INIT: - Tx20Init(); - break; - case FUNC_EVERY_SECOND: - Tx20Read(); - break; - case FUNC_JSON_APPEND: - Tx20Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Tx20Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_36_mgc3130.ino" -# 22 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_36_mgc3130.ino" -#ifdef USE_I2C -#ifdef USE_MGC3130 -# 35 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_36_mgc3130.ino" -#define XSNS_36 36 - -#warning **** MGC3130: It is recommended to disable all unneeded I2C-drivers **** - -#define MGC3130_I2C_ADDR 0x42 - -#define MGC3130_xfer pin[GPIO_MGC3130_XFER] -#define MGC3130_reset pin[GPIO_MGC3130_RESET] - - -bool MGC3130_type = false; -char MGC3130stype[8]; - - -#define MGC3130_SYSTEM_STATUS 0x15 -#define MGC3130_REQUEST_MSG 0x06 -#define MGC3130_FW_VERSION 0x83 -#define MGC3130_SET_RUNTIME 0xA2 -#define MGC3130_SENSOR_DATA 0x91 - - -#define MGC3130_GESTURE_GARBAGE 1 -#define MGC3130_FLICK_WEST_EAST 2 -#define MGC3130_FLICK_EAST_WEST 3 -#define MGC3130_FLICK_SOUTH_NORTH 4 -#define MGC3130_FLICK_NORTH_SOUTH 5 -#define MGC3130_CIRCLE_CLOCKWISE 6 -#define MGC3130_CIRCLE_CCLOCKWISE 7 - -#define MGC3130_MIN_ROTVALUE 0 -#define MGC3130_MAX_ROTVALUE 1023 -#define MGC3130_MIN_ZVALUE 32768 - - -#ifdef USE_WEBSERVER -const char HTTP_MGC_3130_SNS[] PROGMEM = - "{s}" "%s" "{m}%s{e}" - "{s}" "HwRev" "{m}%u.%u{e}" - "{s}" "loaderVer" "{m}%u.%u{e}" - "{s}" "platVer" "{m}%u{e}"; -#endif - - - - - - - -#pragma pack(1) -union MGC3130_Union{ - uint8_t buffer[132]; - struct - { - - uint8_t msgSize; - uint8_t flag; - uint8_t counter; - uint8_t id; - - struct { - uint8_t DSPStatus:1; - uint8_t gestureInfo:1; - uint8_t touchInfo:1; - uint8_t airWheelInfo:1; - uint8_t xyzPosition:1; - uint8_t noisePower:1; - uint8_t reserved:2; - uint8_t electrodeConfiguration:3; - uint8_t CICData:1; - uint8_t SDData:1; - uint16_t reserved2:3; - } outputConfigMask; - uint8_t timestamp; - struct { - uint8_t positionValid:1; - uint8_t airWheelValid:1; - uint8_t rawDataValid:1; - uint8_t noisePowerValid:1; - uint8_t environmentalNoise:1; - uint8_t clipping:1; - uint8_t reserved:1; - uint8_t DSPRunning:1; - } systemInfo; - uint16_t dspInfo; - struct { - uint8_t gestureCode:8; - uint8_t reserved:4; - uint8_t gestureType:4; - uint8_t edgeFlick:1; - uint16_t reserved2:14; - uint8_t gestureInProgress:1; - } gestureInfo; - struct { - uint8_t touchSouth:1; - uint8_t touchWest:1; - uint8_t touchNorth:1; - uint8_t touchEast:1; - uint8_t touchCentre:1; - uint8_t tapSouth:1; - uint8_t tapWest:1; - uint8_t tapNorth:1; - uint8_t tapEast :1; - uint8_t tapCentre:1; - uint8_t doubleTapSouth:1; - uint8_t doubleTapWest:1; - uint8_t doubleTapNorth:1; - uint8_t doubleTapEast:1; - uint8_t doubleTapCentre:1; - uint8_t reserved:1; - uint8_t touchCounter; - uint8_t reserved2; - } touchInfo; - int8_t airWheel; - uint8_t reserved; - uint16_t x; - uint16_t y; - uint16_t z; - float noisePower; - float CICData[4]; - float SDData[4]; - } out; - struct { - uint8_t header[3]; - - uint8_t valid; - uint8_t hwRev[2]; - uint8_t parameterStartAddr; - uint8_t loaderVersion[2]; - uint8_t loaderPlatform; - uint8_t fwStartAddr; - char fwVersion[120]; - } fw; - struct{ - uint8_t id; - uint8_t size; - uint16_t error; - uint32_t reserved; - uint32_t reserved1; - } status; -} MGC_data; -#pragma pack() - -char MGC3130_currentGesture[12]; - -int8_t MGC3130_delta, MGC3130_lastrotation = 0; -int16_t MGC3130_rotValue, MGC3130_lastSentRotValue = 0; - -uint16_t MGC3130_lastSentX, MGC3130_lastSentY, MGC3130_lastSentZ = 0; - -uint8_t hwRev[2], loaderVersion[2], loaderPlatform = 0; -char MGC3130_firmwareInfo[20]; - -uint8_t MGC3130_touchTimeout = 0; -uint16_t MGC3130_touchCounter = 1; -uint32_t MGC3130_touchTimeStamp = millis(); -bool MGC3130_triggeredByTouch = false; - -uint8_t MGC3130_mode = 1; - - - -uint8_t MGC3130autoCal[] = {0x10, 0x00, 0x00, 0xA2, 0x80, 0x00 , 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; -uint8_t MGC3130disableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; -uint8_t MGC3130enableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; - -void MGC3130_triggerTele(){ - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - #ifdef USE_RULES - RulesTeleperiod(); - #endif - } -} - -void MGC3130_handleSensorData(){ - if ( MGC_data.out.outputConfigMask.touchInfo && MGC3130_touchTimeout == 0){ - if (MGC3130_handleTouch()){ - MGC3130_triggeredByTouch = true; - MGC3130_triggerTele(); - } - } - - if(MGC3130_mode == 1){ - if( MGC_data.out.outputConfigMask.gestureInfo && MGC_data.out.gestureInfo.gestureCode > 0){ - MGC3130_handleGesture(); - MGC3130_triggerTele(); - } - } - if(MGC3130_mode == 2){ - if(MGC_data.out.outputConfigMask.airWheelInfo && MGC_data.out.systemInfo.airWheelValid){ - MGC3130_handleAirWheel(); - MGC3130_triggerTele(); - } - } - if(MGC3130_mode == 3){ - if(MGC_data.out.systemInfo.positionValid && (MGC_data.out.z > MGC3130_MIN_ZVALUE)){ - MGC3130_triggerTele(); - } - } -} - -void MGC3130_sendMessage(uint8_t data[], uint8_t length){ - Wire.beginTransmission(MGC3130_I2C_ADDR); - Wire.write(data,length); - Wire.endTransmission(); - delay(2); - MGC3130_receiveMessage(); -} - - -void MGC3130_handleGesture(){ - - char edge[5]; - if (MGC_data.out.gestureInfo.edgeFlick){ - snprintf_P(edge, sizeof(edge), PSTR("ED_")); - } - else{ - snprintf_P(edge, sizeof(edge), PSTR("")); - } - switch(MGC_data.out.gestureInfo.gestureCode){ - case MGC3130_GESTURE_GARBAGE: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("NONE")); - break; - case MGC3130_FLICK_WEST_EAST: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_WE"), edge); - break; - case MGC3130_FLICK_EAST_WEST: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_EW"), edge); - break; - case MGC3130_FLICK_SOUTH_NORTH: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_SN"), edge); - break; - case MGC3130_FLICK_NORTH_SOUTH: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_NS"), edge); - break; - case MGC3130_CIRCLE_CLOCKWISE: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CW")); - break; - case MGC3130_CIRCLE_CCLOCKWISE: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CCW")); - break; - } - -} - -bool MGC3130_handleTouch(){ - - bool success = false; - if (MGC_data.out.touchInfo.doubleTapCentre && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_C")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.doubleTapEast && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_E")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.doubleTapNorth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_N")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.doubleTapWest && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_W")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.doubleTapSouth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_S")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - if (MGC_data.out.touchInfo.tapCentre && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_C")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.tapEast && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_E")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.tapNorth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_N")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.tapWest && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_W")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.tapSouth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_S")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.touchCentre && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_C")); - success = true; - MGC3130_touchCounter++; - } - else if (MGC_data.out.touchInfo.touchEast && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_E")); - success = true; - MGC3130_touchCounter++; - } - else if (MGC_data.out.touchInfo.touchNorth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_N")); - success = true; - MGC3130_touchCounter++; - } - else if (MGC_data.out.touchInfo.touchWest && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_W")); - success = true; - MGC3130_touchCounter++; - } - else if (MGC_data.out.touchInfo.touchSouth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_S")); - success = true; - MGC3130_touchCounter++; - } - - return success; -} - -void MGC3130_handleAirWheel(){ - MGC3130_delta = MGC_data.out.airWheel - MGC3130_lastrotation; - MGC3130_lastrotation = MGC_data.out.airWheel; - - MGC3130_rotValue = MGC3130_rotValue + MGC3130_delta; - if(MGC3130_rotValue < MGC3130_MIN_ROTVALUE){ - MGC3130_rotValue = MGC3130_MIN_ROTVALUE; - } - if(MGC3130_rotValue > MGC3130_MAX_ROTVALUE){ - MGC3130_rotValue = MGC3130_MAX_ROTVALUE; - } -} - -void MGC3130_handleSystemStatus(){ - -} - -bool MGC3130_receiveMessage(){ - if(MGC3130_readData()){ - switch(MGC_data.out.id){ - case MGC3130_SENSOR_DATA: - MGC3130_handleSensorData(); - break; - case MGC3130_SYSTEM_STATUS: - MGC3130_handleSystemStatus(); - break; - case MGC3130_FW_VERSION: - hwRev[0] = MGC_data.fw.hwRev[1]; - hwRev[1] = MGC_data.fw.hwRev[0]; - loaderVersion[0] = MGC_data.fw.loaderVersion[0]; - loaderVersion[1] = MGC_data.fw.loaderVersion[1]; - loaderPlatform = MGC_data.fw.loaderPlatform; - snprintf_P(MGC3130_firmwareInfo, sizeof(MGC3130_firmwareInfo), PSTR("FW: %s"), MGC_data.fw.fwVersion); - MGC3130_firmwareInfo[20] = '\0'; - - break; - } - return true; - } - return false; -} - -bool MGC3130_readData() -{ - bool success = false; - if (!digitalRead(MGC3130_xfer)){ - pinMode(MGC3130_xfer, OUTPUT); - digitalWrite(MGC3130_xfer, LOW); - Wire.requestFrom(MGC3130_I2C_ADDR, (uint16_t)32); - - MGC_data.buffer[0] = 4; - unsigned char i = 0; - while(Wire.available() && (i < MGC_data.buffer[0])){ - MGC_data.buffer[i] = Wire.read(); - i++; - } - digitalWrite(MGC3130_xfer, HIGH); - pinMode(MGC3130_xfer, INPUT); - success = true; - } - return success; -} - -void MGC3130_nextMode(){ - if (MGC3130_mode < 3){ - MGC3130_mode++; - } - else{ - MGC3130_mode = 1; - } - switch(MGC3130_mode){ - case 1: - MGC3130_sendMessage(MGC3130disableAirwheel,16); - break; - case 2: - MGC3130_sendMessage(MGC3130enableAirwheel,16); - break; - case 3: - MGC3130_sendMessage(MGC3130disableAirwheel,16); - break; - } -} - -void MGC3130_loop() -{ - if(MGC3130_touchTimeout > 0){ - MGC3130_touchTimeout--; - } - MGC3130_receiveMessage(); -} - - -bool MGC3130_detect(void) -{ - if (MGC3130_type){ - return true; - } - - pinMode(MGC3130_xfer, INPUT_PULLUP); - pinMode(MGC3130_reset, OUTPUT); - digitalWrite(MGC3130_reset, LOW); - delay(10); - digitalWrite(MGC3130_reset, HIGH); - delay(50); - - bool success = false; - success = MGC3130_receiveMessage(); - if (success) { - strcpy_P(MGC3130stype, PSTR("MGC3130")); - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, MGC3130stype, MGC3130_I2C_ADDR); - MGC3130_currentGesture[0] = '\0'; - MGC3130_type = true; - } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MGC3130 did not respond at address 0x%x"), MGC3130_I2C_ADDR); - } - return success; -} - - - - - -void MGC3130_show(bool json) -{ - if (!MGC3130_type) { return; } - - char status_chr[2]; - if (MGC_data.out.systemInfo.DSPRunning) { - sprintf (status_chr, "1"); - } - else{ - sprintf (status_chr, "0"); - } - - if (json) { - if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch) { - if (MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)) { - ResponseAppend_P(PSTR(",\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), - MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); - MGC3130_lastSentX = MGC_data.out.x; - MGC3130_lastSentY = MGC_data.out.y; - MGC3130_lastSentZ = MGC_data.out.z; - } - } - MGC3130_triggeredByTouch = false; - - if (MGC3130_mode == 2) { - if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)) { - ResponseAppend_P(PSTR(",\"%s\":{\"AW\":%i}"), MGC3130stype, MGC3130_rotValue); - MGC3130_lastSentRotValue = MGC3130_rotValue; - } - } - - if (MGC3130_currentGesture[0] != '\0') { - if (millis() - MGC3130_touchTimeStamp > 220 ) { - MGC3130_touchCounter = 1; - } - ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); - MGC3130_currentGesture[0] = '\0'; - MGC3130_touchTimeStamp = millis(); - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_MGC_3130_SNS, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform ); -#endif - } -} -# 575 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_36_mgc3130.ino" -bool MGC3130CommandSensor() -{ - bool serviced = true; - - switch (XdrvMailbox.payload) { - case 0: - MGC3130_nextMode(); - break; - case 1: - MGC3130_mode = 1; - MGC3130_sendMessage(MGC3130disableAirwheel,16); - break; - case 2: - MGC3130_mode = 2; - MGC3130_sendMessage(MGC3130enableAirwheel,16); - break; - case 3: - MGC3130_mode = 3; - MGC3130_sendMessage(MGC3130disableAirwheel,16); - break; - } - return serviced; -} - - - - - -bool Xsns36(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - if ((FUNC_INIT == function) && (pin[GPIO_MGC3130_XFER] < 99) && (pin[GPIO_MGC3130_RESET] < 99)) { - MGC3130_detect(); - } - else if (MGC3130_type) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - MGC3130_loop(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_36 == XdrvMailbox.index) { - result = MGC3130CommandSensor(); - } - break; - case FUNC_JSON_APPEND: - MGC3130_show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MGC3130_show(0); - break; -#endif - } - } - } - return result; -} -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_37_rfsensor.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_37_rfsensor.ino" -#ifdef USE_RF_SENSOR -# 33 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_37_rfsensor.ino" -#define XSNS_37 37 - - - - -#define RFSNS_VALID_WINDOW 1800 - -#define RFSNS_LOOPS_PER_MILLI 1900 -#define RFSNS_RAW_BUFFER_SIZE 180 -#define RFSNS_MIN_RAW_PULSES 112 - -#define RFSNS_MIN_PULSE_LENGTH 300 -#define RFSNS_RAWSIGNAL_SAMPLE 50 -#define RFSNS_SIGNAL_TIMEOUT 10 -#define RFSNS_SIGNAL_REPEAT_TIME 500 - -typedef struct RawSignalStruct -{ - int Number; - uint8_t Repeats; - uint8_t Multiply; - unsigned long Time; - uint8_t Pulses[RFSNS_RAW_BUFFER_SIZE+2]; - -} raw_signal_t; - -raw_signal_t *rfsns_raw_signal = nullptr; -uint8_t rfsns_rf_bit; -uint8_t rfsns_rf_port; -uint8_t rfsns_any_sensor = 0; - - - - - -bool RfSnsFetchSignal(uint8_t DataPin, bool StateSignal) -{ - uint8_t Fbit = digitalPinToBitMask(DataPin); - uint8_t Fport = digitalPinToPort(DataPin); - uint8_t FstateMask = (StateSignal ? Fbit : 0); - - if ((*portInputRegister(Fport) & Fbit) == FstateMask) { - const unsigned long LoopsPerMilli = RFSNS_LOOPS_PER_MILLI; - - - - - - - unsigned long PulseLength = 0; - if (rfsns_raw_signal->Time) { - if (rfsns_raw_signal->Repeats && (rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) { - PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; - while (((rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && (PulseLength > micros())) { - if ((*portInputRegister(Fport) & Fbit) == FstateMask) { - PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; - } - } - while (((rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && ((*portInputRegister(Fport) & Fbit) != FstateMask)); - } - } - - int RawCodeLength = 1; - bool Ftoggle = false; - unsigned long numloops = 0; - unsigned long maxloops = RFSNS_SIGNAL_TIMEOUT * LoopsPerMilli; - rfsns_raw_signal->Multiply = RFSNS_RAWSIGNAL_SAMPLE; - do { - numloops = 0; - while(((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) { - if (numloops++ == maxloops) { break; } - } - PulseLength = (numloops *1000) / LoopsPerMilli; - if (PulseLength < RFSNS_MIN_PULSE_LENGTH) { break; } - Ftoggle = !Ftoggle; - rfsns_raw_signal->Pulses[RawCodeLength++] = PulseLength / (unsigned long)rfsns_raw_signal->Multiply; - } - while(RawCodeLength < RFSNS_RAW_BUFFER_SIZE && numloops <= maxloops); - - if ((RawCodeLength >= RFSNS_MIN_RAW_PULSES) && (RawCodeLength < RFSNS_RAW_BUFFER_SIZE -1)) { - rfsns_raw_signal->Repeats = 0; - rfsns_raw_signal->Number = RawCodeLength -1; - rfsns_raw_signal->Pulses[rfsns_raw_signal->Number] = 0; - rfsns_raw_signal->Time = millis(); - return true; - } - else - rfsns_raw_signal->Number = 0; - } - - return false; -} - -#ifdef USE_THEO_V2 -# 149 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_37_rfsensor.ino" -#define RFSNS_THEOV2_MAX_CHANNEL 2 - -#define RFSNS_THEOV2_PULSECOUNT 114 -#define RFSNS_THEOV2_RF_PULSE_MID 1000 - -typedef struct { - uint32_t time; - int16_t temp; - uint16_t lux; - uint8_t volt; -} theo_v2_t1_t; - -typedef struct { - uint32_t time; - int16_t temp; - uint16_t hum; - uint8_t volt; -} theo_v2_t2_t; - -theo_v2_t1_t *rfsns_theo_v2_t1 = nullptr; -theo_v2_t2_t *rfsns_theo_v2_t2 = nullptr; - -void RfSnsInitTheoV2(void) -{ - rfsns_theo_v2_t1 = (theo_v2_t1_t*)malloc(RFSNS_THEOV2_MAX_CHANNEL * sizeof(theo_v2_t1_t)); - rfsns_theo_v2_t2 = (theo_v2_t2_t*)malloc(RFSNS_THEOV2_MAX_CHANNEL * sizeof(theo_v2_t2_t)); - rfsns_any_sensor++; -} - -void RfSnsAnalyzeTheov2(void) -{ - if (rfsns_raw_signal->Number != RFSNS_THEOV2_PULSECOUNT) { return; } - - uint8_t Checksum; - uint8_t Channel; - uint8_t Type; - uint8_t Voltage; - int Payload1; - int Payload2; - - uint8_t b, bytes, bits, id; - - uint8_t idx = 3; - uint8_t chksum = 0; - for (bytes = 0; bytes < 7; bytes++) { - b = 0; - for (bits = 0; bits <= 7; bits++) - { - if ((rfsns_raw_signal->Pulses[idx] * rfsns_raw_signal->Multiply) > RFSNS_THEOV2_RF_PULSE_MID) { - b |= 1 << bits; - } - idx += 2; - } - if (bytes > 0) { chksum += b; } - - switch (bytes) { - case 0: - Checksum = b; - break; - case 1: - id = b; - Channel = b & 0x7; - Type = (b >> 3) & 0x1f; - break; - case 2: - Voltage = b; - break; - case 3: - Payload1 = b; - break; - case 4: - Payload1 = (b << 8) | Payload1; - break; - case 5: - Payload2 = b; - break; - case 6: - Payload2 = (b << 8) | Payload2; - break; - } - } - - if (Checksum != chksum) { return; } - if ((Channel == 0) || (Channel > RFSNS_THEOV2_MAX_CHANNEL)) { return; } - Channel--; - - rfsns_raw_signal->Repeats = 1; - - int Payload3 = Voltage & 0x3f; - - switch (Type) { - case 1: - rfsns_theo_v2_t1[Channel].time = LocalTime(); - rfsns_theo_v2_t1[Channel].volt = Payload3; - rfsns_theo_v2_t1[Channel].temp = Payload1; - rfsns_theo_v2_t1[Channel].lux = Payload2; - break; - case 2: - rfsns_theo_v2_t2[Channel].time = LocalTime(); - rfsns_theo_v2_t2[Channel].volt = Payload3; - rfsns_theo_v2_t2[Channel].temp = Payload1; - rfsns_theo_v2_t2[Channel].hum = Payload2; - break; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: TheoV2, ChkCalc %d, Chksum %d, id %d, Type %d, Ch %d, Volt %d, BattLo %d, Pld1 %d, Pld2 %d"), - chksum, Checksum, id, Type, Channel +1, Payload3, (Voltage & 0x80) >> 7, Payload1, Payload2); -} - -void RfSnsTheoV2Show(bool json) -{ - bool sensor_once = false; - - for (uint32_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { - if (rfsns_theo_v2_t1[i].time) { - char sensor[10]; - snprintf_P(sensor, sizeof(sensor), PSTR("TV2T1C%d"), i +1); - char voltage[33]; - dtostrfd((float)rfsns_theo_v2_t1[i].volt / 10, 1, voltage); - - if (rfsns_theo_v2_t1[i].time < LocalTime() - RFSNS_VALID_WINDOW) { - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), - sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage); - } - } else { - char temperature[33]; - dtostrfd(ConvertTemp((float)rfsns_theo_v2_t1[i].temp / 100), Settings.flag2.temperature_resolution, temperature); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"), - sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && !sensor_once) { - DomoticzSensor(DZ_TEMP, temperature); - DomoticzSensor(DZ_ILLUMINANCE, rfsns_theo_v2_t1[i].lux); - sensor_once = true; - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, sensor, rfsns_theo_v2_t1[i].lux); -#endif - } - } - } - } - - sensor_once = false; - for (uint32_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { - if (rfsns_theo_v2_t2[i].time) { - char sensor[10]; - snprintf_P(sensor, sizeof(sensor), PSTR("TV2T2C%d"), i +1); - char voltage[33]; - dtostrfd((float)rfsns_theo_v2_t2[i].volt / 10, 1, voltage); - - if (rfsns_theo_v2_t2[i].time < LocalTime() - RFSNS_VALID_WINDOW) { - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED" \":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), - sensor, GetDT(rfsns_theo_v2_t2[i].time).c_str(), voltage); - } - } else { - float temp = ConvertTemp((float)rfsns_theo_v2_t2[i].temp / 100); - float humi = ConvertHumidity((float)rfsns_theo_v2_t2[i].hum / 100); - char temperature[33]; - dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_VOLTAGE "\":%s}"), - sensor, temperature, humidity, voltage); - if ((0 == tele_period) && !sensor_once) { -#ifdef USE_DOMOTICZ - DomoticzTempHumSensor(temperature, humidity); -#endif -#ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, temp); - KnxSensor(KNX_HUMIDITY, humi); -#endif - sensor_once = true; - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, sensor, humidity); -#endif - } - } - } - } -} - -#endif - -#ifdef USE_ALECTO_V2 -# 392 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_37_rfsensor.ino" -#define RFSNS_DKW2012_PULSECOUNT 176 -#define RFSNS_ACH2010_MIN_PULSECOUNT 160 -#define RFSNS_ACH2010_MAX_PULSECOUNT 160 - -#define D_ALECTOV2 "AlectoV2" - -const char kAlectoV2Directions[] PROGMEM = D_TX20_NORTH "|" - D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" - D_TX20_NORTH D_TX20_EAST "|" - D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" - D_TX20_EAST "|" - D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH "|" - D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_WEST "|" - D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" - D_TX20_NORTH D_TX20_WEST "|" - D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; - -typedef struct { - uint32_t time; - float temp; - float rain; - float wind; - float gust; - uint8_t type; - uint8_t humi; - uint8_t wdir; -} alecto_v2_t; - -alecto_v2_t *rfsns_alecto_v2 = nullptr; -uint16_t rfsns_alecto_rain_base = 0; - -void RfSnsInitAlectoV2(void) -{ - rfsns_alecto_v2 = (alecto_v2_t*)malloc(sizeof(alecto_v2_t)); - rfsns_any_sensor++; -} - -void RfSnsAnalyzeAlectov2() -{ - if (!(((rfsns_raw_signal->Number >= RFSNS_ACH2010_MIN_PULSECOUNT) && - (rfsns_raw_signal->Number <= RFSNS_ACH2010_MAX_PULSECOUNT)) || (rfsns_raw_signal->Number == RFSNS_DKW2012_PULSECOUNT))) { return; } - - uint8_t c = 0; - uint8_t rfbit; - uint8_t data[9] = { 0 }; - uint8_t msgtype = 0; - uint8_t rc = 0; - int temp; - uint8_t checksum = 0; - uint8_t checksumcalc = 0; - uint8_t maxidx = 8; - unsigned long atime; - float factor; - char buf1[16]; - - if (rfsns_raw_signal->Number > RFSNS_ACH2010_MAX_PULSECOUNT) { maxidx = 9; } - - uint8_t idx = maxidx; - for (uint32_t x = rfsns_raw_signal->Number; x > 0; x = x-2) { - if (rfsns_raw_signal->Pulses[x-1] * rfsns_raw_signal->Multiply < 0x300) { - rfbit = 0x80; - } else { - rfbit = 0; - } - data[idx] = (data[idx] >> 1) | rfbit; - c++; - if (c == 8) { - if (idx == 0) { break; } - c = 0; - idx--; - } - } - - checksum = data[maxidx]; - checksumcalc = RfSnsAlectoCRC8(data, maxidx); - - msgtype = (data[0] >> 4) & 0xf; - rc = (data[0] << 4) | (data[1] >> 4); - - if (checksum != checksumcalc) { return; } - if ((msgtype != 10) && (msgtype != 5)) { return; } - - rfsns_raw_signal->Repeats = 1; - - - - - - factor = 1.22; - - - - - - rfsns_alecto_v2->time = LocalTime(); - rfsns_alecto_v2->type = (RFSNS_DKW2012_PULSECOUNT == rfsns_raw_signal->Number); - rfsns_alecto_v2->temp = (float)(((data[1] & 0x3) * 256 + data[2]) - 400) / 10; - rfsns_alecto_v2->humi = data[3]; - uint16_t rain = (data[6] * 256) + data[7]; - - if (rain < rfsns_alecto_rain_base) { rfsns_alecto_rain_base = rain; } - if (rfsns_alecto_rain_base > 0) { - rfsns_alecto_v2->rain += ((float)rain - rfsns_alecto_rain_base) * 0.30; - } - rfsns_alecto_rain_base = rain; - rfsns_alecto_v2->wind = (float)data[4] * factor; - rfsns_alecto_v2->gust = (float)data[5] * factor; - if (rfsns_alecto_v2->type) { - rfsns_alecto_v2->wdir = data[8] & 0xf; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: " D_ALECTOV2 ", ChkCalc %d, Chksum %d, rc %d, Temp %d, Hum %d, Rain %d, Wind %d, Gust %d, Dir %d, Factor %s"), - checksumcalc, checksum, rc, ((data[1] & 0x3) * 256 + data[2]) - 400, data[3], (data[6] * 256) + data[7], data[4], data[5], data[8] & 0xf, dtostrfd(factor, 3, buf1)); -} - -void RfSnsAlectoResetRain(void) -{ - if ((RtcTime.hour == 0) && (RtcTime.minute == 0) && (RtcTime.second == 5)) { - rfsns_alecto_v2->rain = 0; - } -} - - - - - - - -uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len) -{ - uint8_t crc = 0; - while (len--) { - uint8_t inbyte = *addr++; - for (uint32_t i = 8; i; i--) { - uint8_t mix = (crc ^ inbyte) & 0x80; - crc <<= 1; - if (mix) { crc ^= 0x31; } - inbyte <<= 1; - } - } - return crc; -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_ALECTOV2[] PROGMEM = - "{s}" D_ALECTOV2 " " D_RAIN "{m}%s " D_UNIT_MILLIMETER "{e}" - "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"; -const char HTTP_SNS_ALECTOV2_WDIR[] PROGMEM = - "{s}" D_ALECTOV2 " " D_TX20_WIND_DIRECTION "{m}%s{e}"; -#endif - -void RfSnsAlectoV2Show(bool json) -{ - if (rfsns_alecto_v2->time) { - if (rfsns_alecto_v2->time < LocalTime() - RFSNS_VALID_WINDOW) { - if (json) { - ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), GetDT(rfsns_alecto_v2->time).c_str()); - } - } else { - float temp = ConvertTemp(rfsns_alecto_v2->temp); - char temperature[33]; - dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); - float humi = ConvertHumidity((float)rfsns_alecto_v2->humi); - char humidity[33]; - dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); - char rain[33]; - dtostrfd(rfsns_alecto_v2->rain, 2, rain); - char wind[33]; - dtostrfd(rfsns_alecto_v2->wind, 2, wind); - char gust[33]; - dtostrfd(rfsns_alecto_v2->gust, 2, gust); - char wdir[4]; - char direction[20]; - if (rfsns_alecto_v2->type) { - GetTextIndexed(wdir, sizeof(wdir), rfsns_alecto_v2->wdir, kAlectoV2Directions); - snprintf_P(direction, sizeof(direction), PSTR(",\"Direction\":\"%s\""), wdir); - } - - if (json) { - ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), - temperature, humidity, rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); - if (0 == tele_period) { -#ifdef USE_DOMOTICZ - - - - -#endif - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, D_ALECTOV2, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, D_ALECTOV2, humidity); - WSContentSend_PD(HTTP_SNS_ALECTOV2, rain, wind, gust); - if (rfsns_alecto_v2->type) { - WSContentSend_PD(HTTP_SNS_ALECTOV2_WDIR, wdir); - } -#endif - } - } - } -} -#endif - -void RfSnsInit(void) -{ - rfsns_raw_signal = (raw_signal_t*)(malloc(sizeof(raw_signal_t))); - if (rfsns_raw_signal) { - memset(rfsns_raw_signal, 0, sizeof(raw_signal_t)); -#ifdef USE_THEO_V2 - RfSnsInitTheoV2(); -#endif -#ifdef USE_ALECTO_V2 - RfSnsInitAlectoV2(); -#endif - if (rfsns_any_sensor) { - rfsns_rf_bit = digitalPinToBitMask(pin[GPIO_RF_SENSOR]); - rfsns_rf_port = digitalPinToPort(pin[GPIO_RF_SENSOR]); - pinMode(pin[GPIO_RF_SENSOR], INPUT); - } else { - free(rfsns_raw_signal); - rfsns_raw_signal = nullptr; - } - } -} - -void RfSnsAnalyzeRawSignal(void) -{ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: Pulses %d"), (int)rfsns_raw_signal->Number); - -#ifdef USE_THEO_V2 - RfSnsAnalyzeTheov2(); -#endif -#ifdef USE_ALECTO_V2 - RfSnsAnalyzeAlectov2(); -#endif -} - -void RfSnsEverySecond(void) -{ -#ifdef USE_ALECTO_V2 - RfSnsAlectoResetRain(); -#endif -} - -void RfSnsShow(bool json) -{ -#ifdef USE_THEO_V2 - RfSnsTheoV2Show(json); -#endif -#ifdef USE_ALECTO_V2 - RfSnsAlectoV2Show(json); -#endif -} - - - - - -bool Xsns37(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_RF_SENSOR] < 99) && (FUNC_INIT == function)) { - RfSnsInit(); - } - else if (rfsns_raw_signal) { - switch (function) { - case FUNC_LOOP: - if ((*portInputRegister(rfsns_rf_port) &rfsns_rf_bit) == rfsns_rf_bit) { - if (RfSnsFetchSignal(pin[GPIO_RF_SENSOR], HIGH)) { - RfSnsAnalyzeRawSignal(); - } - } - sleep = 0; - break; - case FUNC_EVERY_SECOND: - RfSnsEverySecond(); - break; - case FUNC_JSON_APPEND: - RfSnsShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - RfSnsShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_38_az7798.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_38_az7798.ino" -#ifdef USE_AZ7798 - -#define XSNS_38 38 -# 112 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_38_az7798.ino" -#include - -#ifndef CO2_LOW -#define CO2_LOW 800 -#endif -#ifndef CO2_HIGH -#define CO2_HIGH 1200 -#endif - -#define AZ_READ_TIMEOUT 400 - -#define AZ_CLOCK_UPDATE_INTERVAL (24UL * 60 * 60) -#define AZ_EPOCH (946684800UL) - -TasmotaSerial *AzSerial; - -const char ktype[] = "AZ7798"; -uint8_t az_type = 1; -uint16_t az_co2 = 0; -double az_temperature = 0; -double az_humidity = 0; -uint8_t az_received = 0; -uint8_t az_state = 0; -unsigned long az_clock_update = 10; - - - -void AzEverySecond(void) -{ - unsigned long start = millis(); - - az_state++; - if (5 == az_state) { - az_state = 0; - - AzSerial->flush(); - AzSerial->write(":\r", 2); - az_received = 0; - - uint8_t az_response[32]; - uint8_t counter = 0; - uint8_t i, j; - uint8_t response_substr[16]; - - do { - if (AzSerial->available() > 0) { - az_response[counter] = AzSerial->read(); - if(az_response[counter] == 0x0d) { az_received = 1; } - counter++; - } else { - delay(5); - } - } while(((millis() - start) < AZ_READ_TIMEOUT) && (counter < sizeof(az_response)) && !az_received); - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, az_response, counter); - - if (!az_received) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 comms timeout")); - return; - } - - i = 0; - while((az_response[i] != 'T') && (i < counter)) {i++;} - if(az_response[i] != 'T') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find start of response")); - return; - } - i++; - j = 0; - - while((az_response[i] != 'C') && (az_response[i] != 'F') && (i < counter)) { - response_substr[j++] = az_response[i++]; - } - if((az_response[i] != 'C') && (az_response[i] != 'F')){ - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of temperature")); - return; - } - response_substr[j] = 0; - az_temperature = CharToFloat((char*)response_substr); - if(az_response[i] == 'C') { - az_temperature = ConvertTemp((float)az_temperature); - } else { - az_temperature = ConvertTemp((az_temperature - 32) / 1.8); - } - i++; - if(az_response[i] != ':') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error first delimiter")); - return; - } - i++; - if(az_response[i] != 'C') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of CO2")); - return; - } - i++; - j = 0; - - while((az_response[i] != 'p') && (i < counter)) { - response_substr[j++] = az_response[i++]; - } - if(az_response[i] != 'p') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of CO2")); - return; - } - response_substr[j] = 0; - az_co2 = atoi((char*)response_substr); - LightSetSignal(CO2_LOW, CO2_HIGH, az_co2); - i += 3; - if(az_response[i] != ':') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error second delimiter")); - return; - } - i++; - if(az_response[i] != 'H') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of humidity")); - return; - } - i++; - j = 0; - - while((az_response[i] != '%') && (i < counter)) { - response_substr[j++] = az_response[i++]; - } - if(az_response[i] != '%') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of humidity")); - return; - } - response_substr[j] = 0; - az_humidity = ConvertHumidity(CharToFloat((char*)response_substr)); - } - - - if ((az_clock_update == 0) && (LocalTime() > AZ_EPOCH)) { - char tmpString[16]; - sprintf(tmpString, "C %d\r", (int)(LocalTime() - AZ_EPOCH)); - AzSerial->write(tmpString); - - do { - if (AzSerial->available() > 0) { - if(AzSerial->read() == 0x0d) { break; } - } else { - delay(5); - } - } while(((millis() - start) < AZ_READ_TIMEOUT)); - az_clock_update = AZ_CLOCK_UPDATE_INTERVAL; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 clock updated")); - } else { - az_clock_update--; - } -} - - - -void AzInit(void) -{ - az_type = 0; - if ((pin[GPIO_AZ_RXD] < 99) && (pin[GPIO_AZ_TXD] < 99)) { - AzSerial = new TasmotaSerial(pin[GPIO_AZ_RXD], pin[GPIO_AZ_TXD], 1); - if (AzSerial->begin(9600)) { - if (AzSerial->hardwareSerial()) { ClaimSerial(); } - az_type = 1; - } - } -} - -void AzShow(bool json) -{ - char temperature[33]; - dtostrfd(az_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(az_humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), ktype, az_co2, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, az_co2); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2, ktype, az_co2); - WSContentSend_PD(HTTP_SNS_TEMP, ktype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, ktype, humidity); -#endif - } -} - - - - - -bool Xsns38(uint8_t function) -{ - bool result = false; - - if(az_type){ - switch (function) { - case FUNC_INIT: - AzInit(); - break; - case FUNC_EVERY_SECOND: - AzEverySecond(); - break; - case FUNC_JSON_APPEND: - AzShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - AzShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_39_max31855.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_39_max31855.ino" -#ifdef USE_MAX31855 - -#define XSNS_39 39 - -bool initialized = false; - -struct MAX31855_ResultStruct{ - uint8_t ErrorCode; - float ProbeTemperature; - float ReferenceTemperature; -} MAX31855_Result; - -void MAX31855_Init(void){ - if(initialized) - return; - - - pinMode(pin[GPIO_MAX31855CS], OUTPUT); - pinMode(pin[GPIO_MAX31855CLK], OUTPUT); - pinMode(pin[GPIO_MAX31855DO], INPUT); - - - digitalWrite(pin[GPIO_MAX31855CS], HIGH); - digitalWrite(pin[GPIO_MAX31855CLK], LOW); - - initialized = true; -} - - - - - -void MAX31855_GetResult(void){ - int32_t RawData = MAX31855_ShiftIn(32); - uint8_t probeerror = RawData & 0x7; - - MAX31855_Result.ErrorCode = probeerror; - MAX31855_Result.ReferenceTemperature = MAX31855_GetReferenceTemperature(RawData); - if(probeerror) - MAX31855_Result.ProbeTemperature = NAN; - else - MAX31855_Result.ProbeTemperature = MAX31855_GetProbeTemperature(RawData); -} - - - - - - -float MAX31855_GetProbeTemperature(int32_t RawData){ - if(RawData & 0x80000000) - RawData = (RawData >> 18) | 0xFFFFC000; - else - RawData >>= 18; - - float result = (RawData * 0.25); - - return (Settings.flag.temperature_conversion) ? ConvertTemp(result) : result; -} - - - - - -float MAX31855_GetReferenceTemperature(int32_t RawData){ - if(RawData & 0x8000) - RawData = (RawData >> 4) | 0xFFFFF000; - else - RawData = (RawData >> 4) & 0x00000FFF; - - float result = (RawData * 0.0625); - - return (Settings.flag.temperature_conversion) ? ConvertTemp(result) : result; -} - - - - - -int32_t MAX31855_ShiftIn(uint8_t Length){ - int32_t dataIn = 0; - - digitalWrite(pin[GPIO_MAX31855CS], LOW); - delayMicroseconds(1); - - for (uint32_t i = 0; i < Length; i++) - { - digitalWrite(pin[GPIO_MAX31855CLK], LOW); - delayMicroseconds(1); - dataIn <<= 1; - if(digitalRead(pin[GPIO_MAX31855DO])) - dataIn |= 1; - digitalWrite(pin[GPIO_MAX31855CLK], HIGH); - delayMicroseconds(1); - } - - digitalWrite(pin[GPIO_MAX31855CS], HIGH); - digitalWrite(pin[GPIO_MAX31855CLK], LOW); - return dataIn; -} - -void MAX31855_Show(bool Json){ - char probetemp[33]; - char referencetemp[33]; - dtostrfd(MAX31855_Result.ProbeTemperature, Settings.flag2.temperature_resolution, probetemp); - dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); - - if(Json){ - ResponseAppend_P(PSTR(",\"MAX31855\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ - probetemp, referencetemp, MAX31855_Result.ErrorCode); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_TEMP, probetemp); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, MAX31855_Result.ProbeTemperature); - } -#endif - } else { -#ifdef USE_WEBSERVER - WSContentSend_PD(HTTP_SNS_TEMP, "MAX31855", probetemp, TempUnit()); -#endif - } -} - - - - - -bool Xsns39(uint8_t function) -{ - bool result = false; - if((pin[GPIO_MAX31855CS] < 99) && (pin[GPIO_MAX31855CLK] < 99) && (pin[GPIO_MAX31855DO] < 99)){ - - switch (function) { - case FUNC_INIT: - MAX31855_Init(); - break; - case FUNC_EVERY_SECOND: - MAX31855_GetResult(); - break; - case FUNC_JSON_APPEND: - MAX31855_Show(true); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MAX31855_Show(false); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_40_pn532.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_40_pn532.ino" -#ifdef USE_PN532_HSU - -#define XSNS_40 40 - -#include - -TasmotaSerial *PN532_Serial; - -#define PN532_INVALID_ACK -1 -#define PN532_TIMEOUT -2 -#define PN532_INVALID_FRAME -3 -#define PN532_NO_SPACE -4 - -#define PN532_PREAMBLE 0x00 -#define PN532_STARTCODE1 0x00 -#define PN532_STARTCODE2 0xFF -#define PN532_POSTAMBLE 0x00 - -#define PN532_HOSTTOPN532 0xD4 -#define PN532_PN532TOHOST 0xD5 - -#define PN532_ACK_WAIT_TIME 0x0A - -#define PN532_COMMAND_GETFIRMWAREVERSION 0x02 -#define PN532_COMMAND_SAMCONFIGURATION 0x14 -#define PN532_COMMAND_RFCONFIGURATION 0x32 -#define PN532_COMMAND_INDATAEXCHANGE 0x40 -#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A - -#define PN532_MIFARE_ISO14443A 0x00 -#define MIFARE_CMD_READ 0x30 -#define MIFARE_CMD_AUTH_A 0x60 -#define MIFARE_CMD_AUTH_B 0x61 -#define MIFARE_CMD_WRITE 0xA0 - -uint8_t pn532_model = 0; -uint8_t pn532_command = 0; -uint8_t pn532_scantimer = 0; - -uint8_t pn532_packetbuffer[64]; - -#ifdef USE_PN532_DATA_FUNCTION -uint8_t pn532_function = 0; -uint8_t pn532_newdata[16]; -uint8_t pn532_newdata_len = 0; -#endif - -void PN532_Init(void) -{ - if ((pin[GPIO_PN532_RXD] < 99) && (pin[GPIO_PN532_TXD] < 99)) { - PN532_Serial = new TasmotaSerial(pin[GPIO_PN532_RXD], pin[GPIO_PN532_TXD], 1); - if (PN532_Serial->begin(115200)) { - if (PN532_Serial->hardwareSerial()) { ClaimSerial(); } - PN532_wakeup(); - uint32_t ver = PN532_getFirmwareVersion(); - if (ver) { - PN532_setPassiveActivationRetries(0xFF); - PN532_SAMConfig(); - pn532_model = 1; - AddLog_P2(LOG_LEVEL_INFO,"NFC: PN532 NFC Reader detected (V%u.%u)",(ver>>16) & 0xFF, (ver>>8) & 0xFF); - } - } - } -} - -int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout) -{ - int read_bytes = 0; - int ret; - unsigned long start_millis; - while (read_bytes < len) { - start_millis = millis(); - do { - ret = PN532_Serial->read(); - if (ret >= 0) { - break; - } - } while((timeout == 0) || ((millis()- start_millis ) < timeout)); - - if (ret < 0) { - if (read_bytes) { - return read_bytes; - } else { - return PN532_TIMEOUT; - } - } - buf[read_bytes] = (uint8_t)ret; - read_bytes++; - } - return read_bytes; -} - -int8_t PN532_readAckFrame(void) -{ - const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; - uint8_t ackBuf[sizeof(PN532_ACK)]; - - if (PN532_receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0) { - return PN532_TIMEOUT; - } - - if (memcmp(&ackBuf, &PN532_ACK, sizeof(PN532_ACK))) { - return PN532_INVALID_ACK; - } - return 0; -} - -int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) -{ - - PN532_Serial->flush(); - - pn532_command = header[0]; - PN532_Serial->write((uint8_t)PN532_PREAMBLE); - PN532_Serial->write((uint8_t)PN532_STARTCODE1); - PN532_Serial->write(PN532_STARTCODE2); - - uint8_t length = hlen + blen + 1; - PN532_Serial->write(length); - PN532_Serial->write(~length + 1); - - PN532_Serial->write(PN532_HOSTTOPN532); - uint8_t sum = PN532_HOSTTOPN532; - - PN532_Serial->write(header, hlen); - for (uint32_t i = 0; i < hlen; i++) { - sum += header[i]; - } - - PN532_Serial->write(body, blen); - for (uint32_t i = 0; i < blen; i++) { - sum += body[i]; - } - - uint8_t checksum = ~sum + 1; - PN532_Serial->write(checksum); - PN532_Serial->write((uint8_t)PN532_POSTAMBLE); - - return PN532_readAckFrame(); -} - -int16_t PN532_readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 50) -{ - uint8_t tmp[3]; - - - if (PN532_receive(tmp, 3, timeout)<=0) { - return PN532_TIMEOUT; - } - if (0 != tmp[0] || 0!= tmp[1] || 0xFF != tmp[2]) { - return PN532_INVALID_FRAME; - } - - - uint8_t length[2]; - if (PN532_receive(length, 2, timeout) <= 0) { - return PN532_TIMEOUT; - } - - if (0 != (uint8_t)(length[0] + length[1])) { - return PN532_INVALID_FRAME; - } - length[0] -= 2; - if (length[0] > len) { - return PN532_NO_SPACE; - } - - - uint8_t cmd = pn532_command + 1; - if (PN532_receive(tmp, 2, timeout) <= 0) { - return PN532_TIMEOUT; - } - if (PN532_PN532TOHOST != tmp[0] || cmd != tmp[1]) { - return PN532_INVALID_FRAME; - } - - if (PN532_receive(buf, length[0], timeout) != length[0]) { - return PN532_TIMEOUT; - } - - uint8_t sum = PN532_PN532TOHOST + cmd; - for (uint32_t i=0; i status) { - return 0; - } - - response = pn532_packetbuffer[0]; - response <<= 8; - response |= pn532_packetbuffer[1]; - response <<= 8; - response |= pn532_packetbuffer[2]; - response <<= 8; - response |= pn532_packetbuffer[3]; - - return response; -} - -void PN532_wakeup(void) -{ - uint8_t wakeup[5] = {0x55, 0x55, 0, 0, 0 }; - PN532_Serial->write(wakeup,sizeof(wakeup)); - - - PN532_Serial->flush(); -} - -bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 50) -{ - pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; - pn532_packetbuffer[1] = 1; - pn532_packetbuffer[2] = cardbaudrate; - if (PN532_writeCommand(pn532_packetbuffer, 3)) { - return 0x0; - } - - if (PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) { - return 0x0; - } -# 274 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_40_pn532.ino" - if (pn532_packetbuffer[0] != 1) { - return 0; - } - - uint16_t sens_res = pn532_packetbuffer[2]; - sens_res <<= 8; - sens_res |= pn532_packetbuffer[3]; - - - *uidLength = pn532_packetbuffer[5]; - - for (uint32_t i = 0; i < pn532_packetbuffer[5]; i++) { - uid[i] = pn532_packetbuffer[6 + i]; - } - - return 1; -} - -bool PN532_setPassiveActivationRetries(uint8_t maxRetries) -{ - pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; - pn532_packetbuffer[1] = 5; - pn532_packetbuffer[2] = 0xFF; - pn532_packetbuffer[3] = 0x01; - pn532_packetbuffer[4] = maxRetries; - if (PN532_writeCommand(pn532_packetbuffer, 5)) { - return 0; - } - return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); -} - -bool PN532_SAMConfig(void) -{ - pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; - pn532_packetbuffer[1] = 0x01; - pn532_packetbuffer[2] = 0x14; - pn532_packetbuffer[3] = 0x00; - if (PN532_writeCommand(pn532_packetbuffer, 4)) { - return false; - } - return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); -} - -#ifdef USE_PN532_DATA_FUNCTION - -uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData) -{ - uint8_t i; - uint8_t _key[6]; - uint8_t _uid[7]; - uint8_t _uidLen; - - - memcpy(&_key, keyData, 6); - memcpy(&_uid, uid, uidLen); - _uidLen = uidLen; - - - pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; - pn532_packetbuffer[1] = 1; - pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; - pn532_packetbuffer[3] = blockNumber; - memcpy(&pn532_packetbuffer[4], &_key, 6); - for (i = 0; i < _uidLen; i++) { - pn532_packetbuffer[10 + i] = _uid[i]; - } - - if (PN532_writeCommand(pn532_packetbuffer, 10 + _uidLen)) { return 0; } - - - PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); - - - - - if (pn532_packetbuffer[0] != 0x00) { - - return 0; - } - - return 1; -} - -uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data) -{ - - pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; - pn532_packetbuffer[1] = 1; - pn532_packetbuffer[2] = MIFARE_CMD_READ; - pn532_packetbuffer[3] = blockNumber; - - - if (PN532_writeCommand(pn532_packetbuffer, 4)) { - return 0; - } - - - PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); - - - if (pn532_packetbuffer[0] != 0x00) { - return 0; - } - - - - memcpy (data, &pn532_packetbuffer[1], 16); - - return 1; -} - -uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data) -{ - - pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; - pn532_packetbuffer[1] = 1; - pn532_packetbuffer[2] = MIFARE_CMD_WRITE; - pn532_packetbuffer[3] = blockNumber; - memcpy(&pn532_packetbuffer[4], data, 16); - - - if (PN532_writeCommand(pn532_packetbuffer, 20)) { - return 0; - } - - - return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); -} - -#endif - -void PN532_ScanForTag(void) -{ - if (!pn532_model) { return; } - uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; - uint8_t uid_len = 0; - uint8_t card_data[16]; - bool erase_success = false; - bool set_success = false; - if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) { - char uids[15]; - -#ifdef USE_PN532_DATA_FUNCTION - char card_datas[34]; -#endif - - ToHex_P((unsigned char*)uid, uid_len, uids, sizeof(uids)); - -#ifdef USE_PN532_DATA_FUNCTION - if (uid_len == 4) { - uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) { - if (mifareclassic_ReadDataBlock(1, card_data)) { -#ifdef USE_PN532_DATA_RAW - memcpy(&card_datas,&card_data,sizeof(card_data)); -#else - for (uint32_t i = 0;i < sizeof(card_data);i++) { - if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) { - card_datas[i] = char(card_data[i]); - } else { - card_datas[i] = '\0'; - } - } -#endif - } - if (pn532_function == 1) { - for (uint32_t i = 0;i<16;i++) { - card_data[i] = 0x00; - } - if (mifareclassic_WriteDataBlock(1, card_data)) { - erase_success = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase success")); - memcpy(&card_datas,&card_data,sizeof(card_data)); - } - } - if (pn532_function == 2) { -#ifdef USE_PN532_DATA_RAW - memcpy(&card_data,&pn532_newdata,sizeof(card_data)); - if (mifareclassic_WriteDataBlock(1, card_data)) { - set_success = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); - memcpy(&card_datas,&card_data,sizeof(card_data)); - } -#else - bool IsAlphaNumeric = true; - for (uint32_t i = 0;i < pn532_newdata_len;i++) { - if ((!isalpha(pn532_newdata[i])) && (!isdigit(pn532_newdata[i]))) { - IsAlphaNumeric = false; - } - } - if (IsAlphaNumeric) { - memcpy(&card_data,&pn532_newdata,pn532_newdata_len); - card_data[pn532_newdata_len] = '\0'; - if (mifareclassic_WriteDataBlock(1, card_data)) { - set_success = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); - memcpy(&card_datas,&card_data,sizeof(card_data)); - } - } else { - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data must be alphanumeric")); - } -#endif - } - } else { - sprintf(card_datas,"AUTHFAIL"); - } - } - switch (pn532_function) { - case 0x01: - if (!erase_success) { - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase fail - exiting erase mode")); - } - break; - case 0x02: - if (!set_success) { - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Write failed - exiting set mode")); - } - default: - break; - } - pn532_function = 0; -#endif - -#ifdef USE_PN532_DATA_FUNCTION - ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), uids, card_datas); -#else - ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids); -#endif - - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - -#ifdef USE_PN532_CAUSE_EVENTS - - char command[71]; -#ifdef USE_PN532_DATA_FUNCTION - sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas); -#else - sprintf(command,"event PN532_UID=%s",uids); -#endif - ExecuteCommand(command, SRC_RULE); -#endif - - pn532_scantimer = 7; - } -} - -#ifdef USE_PN532_DATA_FUNCTION - -bool PN532_Command(void) -{ - bool serviced = true; - uint8_t paramcount = 0; - if (XdrvMailbox.data_len > 0) { - paramcount=1; - } else { - serviced = false; - return serviced; - } - char sub_string[XdrvMailbox.data_len]; - char sub_string_tmp[XdrvMailbox.data_len]; - for (uint32_t ca=0;ca 1) { - if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') { - serviced = false; - return serviced; - } - sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2)); - pn532_newdata_len = strlen(sub_string_tmp); - if (pn532_newdata_len > 15) { pn532_newdata_len = 15; } - memcpy(&pn532_newdata,&sub_string_tmp,pn532_newdata_len); - pn532_newdata[pn532_newdata_len] = 0x00; - pn532_function = 2; - AddLog_P2(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'"), pn532_newdata); - ResponseTime_P(PSTR(",\"PN532\":{\"COMMAND\":\"S\"}}")); - return serviced; - } - } -} - -#endif - -bool Xsns40(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_INIT: - PN532_Init(); - result = true; - break; - case FUNC_EVERY_50_MSECOND: - break; - case FUNC_EVERY_100_MSECOND: - break; - case FUNC_EVERY_250_MSECOND: - if (pn532_scantimer > 0) { - pn532_scantimer--; - } else { - PN532_ScanForTag(); - } - break; - case FUNC_EVERY_SECOND: - break; -#ifdef USE_PN532_DATA_FUNCTION - case FUNC_COMMAND_SENSOR: - if (XSNS_40 == XdrvMailbox.index) { - result = PN532_Command(); - } - break; -#endif - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_41_max44009.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_41_max44009.ino" -#ifdef USE_I2C -#ifdef USE_MAX44009 - - - - - - -#define XSNS_41 41 - -#define MAX44009_ADDR1 0x4A -#define MAX44009_ADDR2 0x4B -#define MAX44009_NO_REGISTERS 8 -#define REG_CONFIG 0x02 -#define REG_LUMINANCE 0x03 -#define REG_LOWER_THRESHOLD 0x06 -#define REG_THRESHOLD_TIMER 0x07 - -#define MAX44009_CONTINUOUS_AUTO_MODE 0x80 - -uint8_t max44009_address; -uint8_t max44009_addresses[] = { MAX44009_ADDR1, MAX44009_ADDR2, 0 }; -uint8_t max44009_found = 0; -uint8_t max44009_valid = 0; -float max44009_illuminance = 0; -char max44009_types[] = "MAX44009"; - -bool Max4409Read_lum(void) -{ - max44009_valid = 0; - uint8_t regdata[2]; - - - if (I2cValidRead16((uint16_t *)®data, max44009_address, REG_LUMINANCE)) { - int exponent = (regdata[0] & 0xF0) >> 4; - int mantissa = ((regdata[0] & 0x0F) << 4) | (regdata[1] & 0x0F); - max44009_illuminance = (float)(((0x00000001 << exponent) * (float)mantissa) * 0.045); - max44009_valid = 1; - return true; - } else { - return false; - } -} - - - -void Max4409Detect(void) -{ - uint8_t reg[8]; - bool failed = false; - - if (max44009_found) { - return; - } - - uint8_t buffer1; - uint8_t buffer2; - for (uint32_t i = 0; 0 != max44009_addresses[i]; i++) { - - max44009_address = max44009_addresses[i]; - - if ((I2cValidRead8(&buffer1, max44009_address, REG_LOWER_THRESHOLD)) && - (I2cValidRead8(&buffer2, max44009_address, REG_THRESHOLD_TIMER))) { - - - if ((0x00 == buffer1) && - (0xFF == buffer2)) { - - - - Wire.beginTransmission(max44009_address); - - - Wire.write(REG_CONFIG); - Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); - if (0 == Wire.endTransmission()) { - max44009_found = 1; - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, max44009_types, max44009_address); - break; - } - } - } - } -} - -void Max4409EverySecond(void) -{ - if (max44009_found) { - Max4409Read_lum(); - } -} - -void Max4409Show(bool json) -{ - char illum_str[8]; - - if (max44009_valid) { - - - - uint8_t prec = 0; - if (10 > max44009_illuminance ) { - prec = 3; - } else if (100 > max44009_illuminance) { - prec = 2; - } else if (1000 > max44009_illuminance) { - prec = 1; - } - dtostrf(max44009_illuminance, sizeof(illum_str) -1, prec, illum_str); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), max44009_types, illum_str); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_ILLUMINANCE, illum_str); - } -#endif -#ifdef USE_WEBSERVER - } else { - - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, max44009_types, (int)max44009_illuminance); -#endif - } - } -} - - - - - -bool Xsns41(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - Max4409Detect(); - break; - case FUNC_EVERY_SECOND: - Max4409EverySecond(); - break; - case FUNC_JSON_APPEND: - Max4409Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Max4409Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_42_scd30.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_42_scd30.ino" -#ifdef USE_I2C -#ifdef USE_SCD30 - -#define XSNS_42 42 - -#define SCD30_MAX_MISSED_READS 3 -#define SONOFF_SCD30_STATE_NO_ERROR 0 -#define SONOFF_SCD30_STATE_ERROR_DATA_CRC 1 -#define SONOFF_SCD30_STATE_ERROR_READ_MEAS 2 -#define SONOFF_SCD30_STATE_ERROR_SOFT_RESET 3 -#define SONOFF_SCD30_STATE_ERROR_I2C_RESET 4 -#define SONOFF_SCD30_STATE_ERROR_UNKNOWN 5 - -#include "Arduino.h" -#include - -#define D_CMND_SCD30 "SCD30" - -const char S_JSON_SCD30_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d}"; -const char S_JSON_SCD30_COMMAND_NFW_VALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d.%d}"; -const char S_JSON_SCD30_COMMAND[] PROGMEM = "{\"" D_CMND_SCD30 "%s\"}"; -const char kSCD30_Commands[] PROGMEM = "Alt|Auto|Cal|FW|Int|Pres|TOff"; - - - - - -enum SCD30_Commands { - CMND_SCD30_ALTITUDE, - CMND_SCD30_AUTOMODE, - CMND_SCD30_CALIBRATE, - CMND_SCD30_FW, - CMND_SCD30_INTERVAL, - CMND_SCD30_PRESSURE, - CMND_SCD30_TEMPOFFSET -}; - - - -FrogmoreScd30 scd30; - -bool scd30Found = false; -bool scd30IsDataValid = false; -int scd30ErrorState = SONOFF_SCD30_STATE_NO_ERROR; -uint16_t scd30Interval_sec; -int scd30Loop_count = 0; -int scd30DataNotAvailable_count = 0; -int scd30GoodMeas_count = 0; -int scd30Reset_count = 0; -int scd30CrcError_count = 0; -int scd30Co2Zero_count = 0; -int i2cReset_count = 0; -uint16_t scd30_CO2 = 0; -uint16_t scd30_CO2EAvg = 0; -float scd30_Humid = 0.0; -float scd30_Temp = 0.0; - -bool Scd30Init() -{ - int error; - bool i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); - if (i2c_flg) - { - uint8_t major = 0; - uint8_t minor = 0; - uint16_t interval_sec; - scd30.begin(); - error = scd30.getFirmwareVersion(&major, &minor); - if (error) - { -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: did not find an SCD30: 0x%lX", error); - AddLog(LOG_LEVEL_DEBUG); -#endif - return false; - } - else - { -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: found an SCD30: FW v%d.%d", major, minor); - AddLog(LOG_LEVEL_INFO); -#endif - } - - error = scd30.getMeasurementInterval(&scd30Interval_sec); - if (error) - { -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: error getMeasurementInterval: 0x%lX", error); - AddLog(LOG_LEVEL_ERROR); -#endif - return false; - } - - error = scd30.beginMeasuring(); - if (error) - { -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "Error: Scd30BeginMeasuring: 0x%lX", error); - AddLog(LOG_LEVEL_ERROR); -#endif - return false; - } - - return true; - } -} - - -int Scd30Update() -{ - int error = 0; - int16_t delta = 0; - scd30Loop_count++; - - if (!scd30Found) - { - scd30Found = Scd30Init(); -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "Scd30Update: found: %d ", scd30Found); - AddLog(LOG_LEVEL_INFO); -#endif - if (!scd30Found) - { -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "Scd30Update: found: %d ", scd30Found); - AddLog(LOG_LEVEL_INFO); -#endif - return (ERROR_SCD30_NOT_FOUND_ERROR); - } - } - else - { - if (scd30Loop_count > (scd30Interval_sec - 1)) - { - switch (scd30ErrorState) - { - case SONOFF_SCD30_STATE_NO_ERROR: - { - error = scd30.readMeasurement(&scd30_CO2, &scd30_CO2EAvg, &scd30_Temp, &scd30_Humid); - switch (error) - { - case ERROR_SCD30_NO_ERROR: - scd30Loop_count = 0; - scd30IsDataValid = true; - scd30GoodMeas_count++; - break; - - case ERROR_SCD30_NO_DATA: - scd30DataNotAvailable_count++; - break; - - case ERROR_SCD30_CRC_ERROR: - scd30ErrorState = SONOFF_SCD30_STATE_ERROR_DATA_CRC; - scd30CrcError_count++; -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: CRC error, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld", scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog(LOG_LEVEL_ERROR); -#endif - break; - - case ERROR_SCD30_CO2_ZERO: - scd30Co2Zero_count++; -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: CO2 zero, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld", scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog(LOG_LEVEL_ERROR); -#endif - break; - - default: - { - scd30ErrorState = SONOFF_SCD30_STATE_ERROR_READ_MEAS; -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld", error, scd30Loop_count); - AddLog(LOG_LEVEL_ERROR); -#endif - return (error); - } - break; - } - } - break; - - case SONOFF_SCD30_STATE_ERROR_DATA_CRC: - { - -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld", scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog(LOG_LEVEL_ERROR); - snprintf_P(log_data, sizeof(log_data), "SCD30: got CRC error, try again, counter: %ld", scd30Loop_count); - AddLog(LOG_LEVEL_ERROR); -#endif - scd30ErrorState = ERROR_SCD30_NO_ERROR; - } - break; - - case SONOFF_SCD30_STATE_ERROR_READ_MEAS: - { - -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld", scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog(LOG_LEVEL_ERROR); - snprintf_P(log_data, sizeof(log_data), "SCD30: not answering, sending soft reset, counter: %ld", scd30Loop_count); - AddLog(LOG_LEVEL_ERROR); -#endif - scd30Reset_count++; - error = scd30.softReset(); - if (error) - { -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: resetting got error: 0x%lX", error); - AddLog(LOG_LEVEL_ERROR); -#endif - error >>= 8; - if (error == 4) - { - scd30ErrorState = SONOFF_SCD30_STATE_ERROR_SOFT_RESET; - } - else - { - scd30ErrorState = SONOFF_SCD30_STATE_ERROR_UNKNOWN; - } - } - else - { - scd30ErrorState = ERROR_SCD30_NO_ERROR; - } - } - break; - - case SONOFF_SCD30_STATE_ERROR_SOFT_RESET: - { - -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld", scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog(LOG_LEVEL_ERROR); - snprintf_P(log_data, sizeof(log_data), "SCD30: clearing i2c bus"); - AddLog(LOG_LEVEL_ERROR); -#endif - i2cReset_count++; - error = scd30.clearI2CBus(); - if (error) - { - scd30ErrorState = SONOFF_SCD30_STATE_ERROR_I2C_RESET; -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: error clearing i2c bus: 0x%lX", error); - AddLog(LOG_LEVEL_ERROR); -#endif - } - else - { - scd30ErrorState = ERROR_SCD30_NO_ERROR; - } - } - break; - - default: - { - -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: unknown error state: 0x%lX", scd30ErrorState); - AddLog(LOG_LEVEL_ERROR); -#endif - scd30ErrorState = SONOFF_SCD30_STATE_ERROR_SOFT_RESET; - } - } - - if (scd30Loop_count > (SCD30_MAX_MISSED_READS * scd30Interval_sec)) - { - scd30IsDataValid = false; - } - } - } - return (ERROR_SCD30_NO_ERROR); -} - - -int Scd30GetCommand(int command_code, uint16_t *pvalue) -{ - switch (command_code) - { - case CMND_SCD30_ALTITUDE: - return scd30.getAltitudeCompensation(pvalue); - break; - - case CMND_SCD30_AUTOMODE: - return scd30.getCalibrationType(pvalue); - break; - - case CMND_SCD30_CALIBRATE: - return scd30.getForcedRecalibrationFactor(pvalue); - break; - - case CMND_SCD30_INTERVAL: - return scd30.getMeasurementInterval(pvalue); - break; - - case CMND_SCD30_PRESSURE: - return scd30.getAmbientPressure(pvalue); - break; - - case CMND_SCD30_TEMPOFFSET: - return scd30.getTemperatureOffset(pvalue); - break; - - default: - - break; - } -} - -int Scd30SetCommand(int command_code, uint16_t value) -{ - switch (command_code) - { - case CMND_SCD30_ALTITUDE: - return scd30.setAltitudeCompensation(value); - break; - - case CMND_SCD30_AUTOMODE: - return scd30.setCalibrationType(value); - break; - - case CMND_SCD30_CALIBRATE: - return scd30.setForcedRecalibrationFactor(value); - break; - - case CMND_SCD30_INTERVAL: - { - int error = scd30.setMeasurementInterval(value); - if (!error) - { - scd30Interval_sec = value; - } - - return error; - } - break; - - case CMND_SCD30_PRESSURE: - return scd30.setAmbientPressure(value); - break; - - case CMND_SCD30_TEMPOFFSET: - return scd30.setTemperatureOffset(value); - break; - - default: - - break; - } -} - - - - -bool Scd30CommandSensor() -{ - char command[CMDSZ]; - bool serviced = true; - uint8_t prefix_len = strlen(D_CMND_SCD30); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_SCD30), prefix_len)) { - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + prefix_len, kSCD30_Commands); - - switch (command_code) { - case CMND_SCD30_ALTITUDE: - case CMND_SCD30_AUTOMODE: - case CMND_SCD30_CALIBRATE: - case CMND_SCD30_INTERVAL: - case CMND_SCD30_PRESSURE: - case CMND_SCD30_TEMPOFFSET: - { - uint16_t value = 0; - if (XdrvMailbox.data_len > 0) - { - value = XdrvMailbox.payload; - Scd30SetCommand(command_code, value); - } - else - { - Scd30GetCommand(command_code, &value); - } - - Response_P(S_JSON_SCD30_COMMAND_NVALUE, command, value); - } - break; - - case CMND_SCD30_FW: - { - uint8_t major = 0; - uint8_t minor = 0; - int error; - error = scd30.getFirmwareVersion(&major, &minor); - if (error) - { -#ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: error getting FW version: 0x%lX", error); - AddLog(LOG_LEVEL_ERROR); -#endif - serviced = false; - } - else - { - Response_P(S_JSON_SCD30_COMMAND_NFW_VALUE, command, major, minor); - } - } - break; - - default: - - serviced = false; - break; - } - } - return serviced; -} - -void Scd30Show(bool json) -{ - char humidity[10]; - char temperature[10]; - - if (scd30Found && scd30IsDataValid) - { - dtostrfd(ConvertHumidity(scd30_Humid), Settings.flag2.humidity_resolution, humidity); - dtostrfd(ConvertTemp(scd30_Temp), Settings.flag2.temperature_resolution, temperature); - if (json) { - - ResponseAppend_P(PSTR(",\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), - scd30_CO2, scd30_CO2EAvg, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) - { - DomoticzSensor(DZ_AIRQUALITY, scd30_CO2); - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2EAVG, "SCD30", scd30_CO2EAvg); - WSContentSend_PD(HTTP_SNS_CO2, "SCD30", scd30_CO2); - WSContentSend_PD(HTTP_SNS_TEMP, "SCD30", temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, "SCD30", humidity); -#endif - } - } -} - - - - - -bool Xsns42(byte function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_EVERY_SECOND: - Scd30Update(); - break; - case FUNC_COMMAND: - result = Scd30CommandSensor(); - break; - case FUNC_JSON_APPEND: - Scd30Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Scd30Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_43_hre.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_43_hre.ino" -#ifdef USE_HRE -# 49 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_43_hre.ino" -#define XSNS_43 43 - -enum hre_states { - hre_idle, - hre_sync, - hre_syncing, - hre_read, - hre_reading, - hre_sleep, - hre_sleeping -}; - -hre_states hre_state = hre_idle; - -float hre_usage = 0; -float hre_rate = 0; -uint32_t hre_usage_time = 0; - -int hre_read_errors = 0; -bool hre_good = false; - - - -int hreReadBit() -{ - digitalWrite(pin[GPIO_HRE_CLOCK], HIGH); - delay(1); - int bit = digitalRead(pin[GPIO_HRE_DATA]); - digitalWrite(pin[GPIO_HRE_CLOCK], LOW); - delay(1); - return bit; -} - - - -char hreReadChar(int &parity_errors) -{ - - hreReadBit(); - - unsigned ch=0; - int sum=0; - for (uint32_t i=0; i<7; i++) - { - int b = hreReadBit(); - ch |= b << i; - sum += b; - } - - - if ( (sum & 0x1) != hreReadBit()) - parity_errors++; - - - hreReadBit(); - - return ch; -} - -void hreInit(void) -{ - hre_read_errors = 0; - hre_good = false; - - pinMode(pin[GPIO_HRE_CLOCK], OUTPUT); - pinMode(pin[GPIO_HRE_DATA], INPUT); - - - - digitalWrite(pin[GPIO_HRE_CLOCK], LOW); - - hre_state = hre_sync; -} - - -void hreEvery50ms(void) -{ - static int sync_counter = 0; - static int sync_run = 0; - - static uint32_t curr_start = 0; - static int read_counter = 0; - static int parity_errors = 0; - static char buff[46]; - - static char ch; - static size_t i; - - switch (hre_state) - { - case hre_sync: - if (uptime < 10) - break; - sync_run = 0; - sync_counter = 0; - hre_state = hre_syncing; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_syncing")); - break; - - case hre_syncing: - - - for (uint32_t i=0; i<20; i++) - { - if (hreReadBit()) - sync_run++; - else - sync_run = 0; - if (sync_run == 62) - { - hre_state = hre_read; - break; - } - sync_counter++; - } - - if (sync_counter > 1000) - { - hre_state = hre_sleep; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE D_ERROR)); - } - break; - - - case hre_read: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "sync_run:%d, sync_counter:%d"), sync_run, sync_counter); - read_counter = 0; - parity_errors = 0; - curr_start = uptime; - memset(buff, 0, sizeof(buff)); - hre_state = hre_reading; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_reading")); - - - - - - case hre_reading: - - buff[read_counter++] = hreReadChar(parity_errors); - buff[read_counter++] = hreReadChar(parity_errors); - - if (read_counter == 46) - { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "pe:%d, re:%d, buff:%s"), - parity_errors, hre_read_errors, buff); - if (parity_errors == 0) - { - float curr_usage; - curr_usage = 0.01 * atol(buff+24); - if (hre_usage_time) - { - double dt = 1.666e-2 * (curr_start - hre_usage_time); - hre_rate = (curr_usage - hre_usage)/dt; - } - hre_usage = curr_usage; - hre_usage_time = curr_start; - hre_good = true; - - hre_state = hre_sleep; - } - else - { - hre_read_errors++; - hre_state = hre_sleep; - } - } - break; - - case hre_sleep: - hre_usage_time = curr_start; - hre_state = hre_sleeping; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_sleeping")); - - case hre_sleeping: - - - if (uptime - hre_usage_time >= 27) - hre_state = hre_sync; - } -} - -void hreShow(boolean json) -{ - if (!hre_good) - return; - - const char *id = "HRE"; - - char usage[16]; - char rate[16]; - dtostrfd(hre_usage, 2, usage); - dtostrfd(hre_rate, 3, rate); - - if (json) - { - ResponseAppend_P(JSON_SNS_GNGPM, id, usage, rate); -#ifdef USE_WEBSERVER - } - else - { - WSContentSend_PD(HTTP_SNS_GALLONS, id, usage); - WSContentSend_PD(HTTP_SNS_GPM, id, rate); -#endif - } -} - - - - - -bool Xsns43(byte function) -{ - - if (pin[GPIO_HRE_CLOCK] >= 99 || pin[GPIO_HRE_DATA] >= 99) - return false; - - switch (function) - { - case FUNC_INIT: - hreInit(); - break; - case FUNC_EVERY_50_MSECOND: - hreEvery50ms(); - break; - case FUNC_EVERY_SECOND: - break; - case FUNC_JSON_APPEND: - hreShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - hreShow(0); - break; -#endif - } - return false; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_44_sps30.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_44_sps30.ino" -#ifdef USE_I2C -#ifdef USE_SPS30 - -#define XSNS_44 44 - -#define SPS30_ADDR 0x69 - -#include -#include - -uint8_t sps30_ready = 0; -uint8_t sps30_running; - -struct SPS30 { - float PM1_0; - float PM2_5; - float PM4_0; - float PM10; - float NCPM0_5; - float NCPM1_0; - float NCPM2_5; - float NCPM4_0; - float NCPM10; - float TYPSIZ; -} sps30_result; - -#define SPS_CMD_START_MEASUREMENT 0x0010 -#define SPS_CMD_START_MEASUREMENT_ARG 0x0300 -#define SPS_CMD_STOP_MEASUREMENT 0x0104 -#define SPS_CMD_READ_MEASUREMENT 0x0300 -#define SPS_CMD_GET_DATA_READY 0x0202 -#define SPS_CMD_AUTOCLEAN_INTERVAL 0x8004 -#define SPS_CMD_CLEAN 0x5607 -#define SPS_CMD_GET_ACODE 0xd025 -#define SPS_CMD_GET_SERIAL 0xd033 -#define SPS_CMD_RESET 0xd304 -#define SPS_WRITE_DELAY_US 20000 -#define SPS_MAX_SERIAL_LEN 32 - -uint8_t sps30_calc_CRC(uint8_t *data) { - uint8_t crc = 0xFF; - for (uint32_t i = 0; i < 2; i++) { - crc ^= data[i]; - for (uint32_t bit = 8; bit > 0; --bit) { - if(crc & 0x80) { - crc = (crc << 1) ^ 0x31u; - } else { - crc = (crc << 1); - } - } - } - return crc; -} - -void CmdClean(void); - -unsigned char twi_readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop); - -void sps30_get_data(uint16_t cmd, uint8_t *data, uint8_t dlen) { -unsigned char cmdb[2]; -uint8_t tmp[3]; -uint8_t index=0; -memset(data,0,dlen); -uint8_t twi_buff[64]; - - Wire.beginTransmission(SPS30_ADDR); - cmdb[0]=cmd>>8; - cmdb[1]=cmd; - Wire.write(cmdb,2); - Wire.endTransmission(); - - - dlen/=2; - dlen*=3; - - twi_readFrom(SPS30_ADDR,twi_buff,dlen,1); - - uint8_t bind=0; - while (bind>8; - cmdb[1]=cmd; - - if (cmd==SPS_CMD_START_MEASUREMENT) { - cmdb[2]=SPS_CMD_START_MEASUREMENT_ARG>>8; - cmdb[3]=SPS_CMD_START_MEASUREMENT_ARG&0xff; - cmdb[4]=sps30_calc_CRC(&cmdb[2]); - Wire.write(cmdb,5); - } else { - Wire.write(cmdb,2); - } - Wire.endTransmission(); -} - -void SPS30_Detect() { - - if (!I2cDevice(SPS30_ADDR)) { - return; - } - uint8_t dcode[32]; - sps30_get_data(SPS_CMD_GET_SERIAL,dcode,sizeof(dcode)); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("sps30 found with serial: %s"),dcode); - sps30_cmd(SPS_CMD_START_MEASUREMENT); - sps30_running = 1; - sps30_ready = 1; -} - -#define D_UNIT_PM "ug/m3" -#define D_UNIT_NCPM "#/m3" - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SPS30_a[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_PM "{e}"; -const char HTTP_SNS_SPS30_b[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_NCPM "{e}"; -const char HTTP_SNS_SPS30_c[] PROGMEM ="{s}SPS30 " "TYPSIZ" "{m}%s " "um" "{e}"; -#endif - -#define PMDP 2 - -#define SPS30_HOURS Settings.sps30_inuse_hours - - - -void SPS30_Every_Second() { - - if (!sps30_ready) return; - if (!sps30_running) return; - - - if (uptime%10==0) { - uint8_t vars[sizeof(float)*10]; - sps30_get_data(SPS_CMD_READ_MEASUREMENT,vars,sizeof(vars)); - float *fp=&sps30_result.PM1_0; - - typedef union { - uint8_t array[4]; - float value; - } ByteToFloat; - - ByteToFloat conv; - - for (uint32_t count=0; count<10; count++) { - for (uint32_t i = 0; i < 4; i++){ - conv.array[3-i] = vars[count*sizeof(float)+i]; - } - *fp++=conv.value; - } - } - - if (uptime%3600==0 && uptime>60) { - - - SPS30_HOURS++; - if (SPS30_HOURS>(7*24)) { - CmdClean(); - SPS30_HOURS=0; - } - } - -} - -void SPS30_Show(bool json) { - char str[64]; - if (!sps30_ready) { - return; - } - - if (!sps30_running) { - return; - } - - if (json) { - dtostrfd(sps30_result.PM1_0,PMDP,str); - ResponseAppend_P(PSTR(",\"SPS30\":{\"" "PM1_0" "\":%s"), str); - dtostrfd(sps30_result.PM2_5,PMDP,str); - ResponseAppend_P(PSTR(",\"" "PM2_5" "\":%s"), str); - dtostrfd(sps30_result.PM4_0,PMDP,str); - ResponseAppend_P(PSTR(",\"" "PM4_0" "\":%s"), str); - dtostrfd(sps30_result.PM10,PMDP,str); - ResponseAppend_P(PSTR(",\"" "PM10" "\":%s"), str); - dtostrfd(sps30_result.NCPM0_5,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM0_5" "\":%s"), str); - dtostrfd(sps30_result.NCPM1_0,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM1_0" "\":%s"), str); - dtostrfd(sps30_result.NCPM2_5,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM2_5" "\":%s"), str); - dtostrfd(sps30_result.NCPM4_0,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM4_0" "\":%s"), str); - dtostrfd(sps30_result.NCPM10,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM10" "\":%s"), str); - dtostrfd(sps30_result.TYPSIZ,PMDP,str); - ResponseAppend_P(PSTR(",\"" "TYPSIZ" "\":%s}"), str); - -#ifdef USE_WEBSERVER - } else { - dtostrfd(sps30_result.PM1_0,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 1.0",str); - dtostrfd(sps30_result.PM2_5,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 2.5",str); - dtostrfd(sps30_result.PM4_0,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 4.0",str); - dtostrfd(sps30_result.PM10,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 10",str); - dtostrfd(sps30_result.NCPM0_5,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 0.5",str); - dtostrfd(sps30_result.NCPM1_0,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 1.0",str); - dtostrfd(sps30_result.NCPM2_5,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 2.5",str); - dtostrfd(sps30_result.NCPM4_0,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 4.0",str); - dtostrfd(sps30_result.NCPM10,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 10",str); - dtostrfd(sps30_result.TYPSIZ,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_c,str); -#endif - } - -} - -void CmdClean(void) { - sps30_cmd(SPS_CMD_CLEAN); - ResponseTime_P(PSTR(",\"SPS30\":{\"CFAN\":\"true\"}}")); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -} - -bool SPS30_cmd(void) { - bool serviced = true; - if (XdrvMailbox.data_len > 0) { - char *cp=XdrvMailbox.data; - if (*cp=='c') { - - CmdClean(); - } else if (*cp=='0' || *cp=='1') { - sps30_running=*cp&1; - sps30_cmd(sps30_running?SPS_CMD_START_MEASUREMENT:SPS_CMD_STOP_MEASUREMENT); - } else { - serviced=false; - } - } - Response_P(PSTR("{\"SPS30\":\"%s\"}"), sps30_running?"running":"stopped"); - - return serviced; -} - - - - - - -bool Xsns44(byte function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - SPS30_Detect(); - break; - case FUNC_EVERY_SECOND: - SPS30_Every_Second(); - break; - case FUNC_JSON_APPEND: - SPS30_Show(1); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_44 == XdrvMailbox.index) { - result = SPS30_cmd(); - } - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SPS30_Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_45_vl53l0x.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_45_vl53l0x.ino" -#ifdef USE_I2C -#ifdef USE_VL53L0X - -#include -#include "VL53L0X.h" -VL53L0X sensor; - -uint8_t vl53l0x_ready = 0; -uint16_t vl53l0x_distance; -uint16_t Vl53l0_buffer[5]; -uint8_t Vl53l0_index; - - - - -void Vl53l0Detect() -{ - - if (!I2cDevice(0x29)) { - return; - } - - if (vl53l0x_ready) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("VL53L1X is ready")); - return; - } - - if (sensor.init()==true) { - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "VL53L0X", sensor.getAddress()); - AddLog(LOG_LEVEL_DEBUG); - } else { - return; - } - - sensor.setTimeout(500); - - - - - - sensor.startContinuous(); - vl53l0x_ready = 1; - - Vl53l0_index=0; - -} - -#define D_UNIT_MILLIMETER "mm" - -#ifdef USE_WEBSERVER -const char HTTP_SNS_VL53L0X[] PROGMEM = - "{s}VL53L0X " D_DISTANCE "{m}%d" D_UNIT_MILLIMETER "{e}"; -#endif - -#define USE_VL_MEDIAN - -void Vl53l0Every_250MSecond() { - uint16_t tbuff[5],tmp; - uint8_t flag; - - if (!vl53l0x_ready) return; - - - uint16_t dist = sensor.readRangeContinuousMillimeters(); - if (dist==0 || dist>2000) { - dist=9999; - } - -#ifdef USE_VL_MEDIAN - - Vl53l0_buffer[Vl53l0_index]=dist; - Vl53l0_index++; - if (Vl53l0_index>=5) Vl53l0_index=0; - - - memmove(tbuff,Vl53l0_buffer,sizeof(tbuff)); - for (byte ocnt=0; ocnt<5; ocnt++) { - flag=0; - for (byte count=0; count<4; count++) { - if (tbuff[count]>tbuff[count+1]) { - tmp=tbuff[count]; - tbuff[count]=tbuff[count+1]; - tbuff[count+1]=tmp; - flag=1; - } - } - if (!flag) break; - } - vl53l0x_distance=tbuff[2]; -#else - vl53l0x_distance=dist; -#endif -} - -void Vl53l0Show(boolean json) -{ - if (!vl53l0x_ready) { - return; - } - - if (json) { - ResponseAppend_P(PSTR(",\"VL53L0X\":{\"" D_JSON_DISTANCE "\":%d}"), vl53l0x_distance); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_VL53L0X, vl53l0x_distance); -#endif - } - -} - - - - - -#define XSNS_45 45 - -bool Xsns45(byte function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - Vl53l0Detect(); - break; - case FUNC_EVERY_250_MSECOND: - Vl53l0Every_250MSecond(); - break; - case FUNC_JSON_APPEND: - Vl53l0Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Vl53l0Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_46_MLX90614.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_46_MLX90614.ino" -#ifdef USE_I2C -#ifdef USE_MLX90614 - -#define XSNS_46 46 - -#define I2_ADR_IRT 0x5a - -uint8_t mlx_ready; -float obj_temp; -float amb_temp; - -void MLX90614_Init() { - - if (!I2cDevice(I2_ADR_IRT)) { - return; - } - - mlx_ready=1; - - - - -} - -#define MLX90614_RAWIR1 0x04 -#define MLX90614_RAWIR2 0x05 -#define MLX90614_TA 0x06 -#define MLX90614_TOBJ1 0x07 -#define MLX90614_TOBJ2 0x08 - - - - -uint16_t read_irtmp(uint8_t flag) { - uint8_t hig,low; - uint16_t val; - - Wire.beginTransmission(I2_ADR_IRT); - if (!flag) Wire.write(MLX90614_TA); - else Wire.write(MLX90614_TOBJ1); - Wire.endTransmission(false); - - Wire.requestFrom(I2_ADR_IRT, (uint8_t)3); - low=Wire.read(); - hig=Wire.read(); - Wire.read(); - - val=((uint16_t)hig<<8)|low; - return val; -} - -void MLX90614_Every_Second(void) { - - if (!mlx_ready) return; - uint16_t uval=read_irtmp(1); - if (uval&0x8000) { - obj_temp=-999; - } else { - obj_temp=((float)uval*0.02)-273.15; - } - uval=read_irtmp(0); - if (uval&0x8000) { - amb_temp=-999; - } else { - amb_temp=((float)uval*0.02)-273.15; - } -} - -#ifdef USE_WEBSERVER - const char HTTP_IRTMP[] PROGMEM = - "{s}MXL90614 " "OBJ-" D_TEMPERATURE "{m}%s C" "{e}" - "{s}MXL90614 " "AMB-" D_TEMPERATURE "{m}%s C" "{e}"; - -void MLX90614_Show(uint8_t json) { - - if (!mlx_ready) return; - - char obj_tstr[16]; - dtostrfd(obj_temp, Settings.flag2.temperature_resolution, obj_tstr); - char amb_tstr[16]; - dtostrfd(amb_temp, Settings.flag2.temperature_resolution, amb_tstr); - - if (json) { - ResponseAppend_P(PSTR(",\"MLX90614\":{\"OBJTMP\":%s,\"AMBTMP\":%s}"), obj_tstr,amb_tstr); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_IRTMP,obj_tstr,amb_tstr); -#endif - } - -} -#endif - - - - - -bool Xsns46(byte function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - MLX90614_Init(); - break; - case FUNC_EVERY_SECOND: - MLX90614_Every_Second(); - break; - case FUNC_JSON_APPEND: - MLX90614_Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MLX90614_Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_47_max31865.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_47_max31865.ino" -#ifdef USE_MAX31865 - -#ifndef USE_SPI -#error "MAX31865 requires USE_SPI enabled" -#endif - -#include "Adafruit_MAX31865.h" - -#define XSNS_47 47 - -#if MAX31865_PTD_WIRES == 4 - #define PTD_WIRES MAX31865_4WIRE -#elif MAX31865_PTD_WIRES == 3 - #define PTD_WIRES MAX31865_3WIRE -#else - #define PTD_WIRES MAX31865_2WIRE -#endif - -int8_t init_status = 0; - -Adafruit_MAX31865 max31865; - -struct MAX31865_Result_Struct { - uint8_t ErrorCode; - uint16_t Rtd; - float PtdResistance; - float PtdTemp; -} MAX31865_Result; - -void MAX31865_Init(void){ - if(init_status) - return; - - max31865.setPins( - pin[GPIO_SSPI_CS], - pin[GPIO_SSPI_MOSI], - pin[GPIO_SSPI_MISO], - pin[GPIO_SSPI_SCLK] - ); - - if(max31865.begin(PTD_WIRES)) - init_status = 1; - else - init_status = -1; -} - - - - - -void MAX31865_GetResult(void){ - uint16_t rtd; - - rtd = max31865.readRTD(); - MAX31865_Result.Rtd = rtd; - MAX31865_Result.PtdResistance = max31865.rtd_to_resistance(rtd, MAX31865_REF_RES); - MAX31865_Result.PtdTemp = max31865.rtd_to_temperature(rtd, MAX31865_PTD_RES, MAX31865_REF_RES) + MAX31865_PTD_BIAS; -} - -void MAX31865_Show(bool Json){ - char temperature[33]; - char resistance[33]; - - dtostrfd(MAX31865_Result.PtdResistance, Settings.flag2.temperature_resolution, resistance); - dtostrfd(MAX31865_Result.PtdTemp, Settings.flag2.temperature_resolution, temperature); - - if(Json){ - ResponseAppend_P(PSTR(",\"MAX31865\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RESISTANCE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ - temperature, resistance, MAX31865_Result.ErrorCode); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, MAX31865_Result.PtdTemp); - } -#endif - } else { -#ifdef USE_WEBSERVER - WSContentSend_PD(HTTP_SNS_TEMP, "MAX31865", temperature, TempUnit()); -#endif - } -} - - - - - -bool Xsns47(uint8_t function) -{ - bool result = false; - if((pin[GPIO_SSPI_MISO] < 99) && (pin[GPIO_SSPI_MOSI] < 99) && - (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_CS] < 99)) { - - switch (function) { - case FUNC_INIT: - MAX31865_Init(); - break; - - case FUNC_EVERY_SECOND: - MAX31865_GetResult(); - break; - - case FUNC_JSON_APPEND: - MAX31865_Show(true); - break; - -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MAX31865_Show(false); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_48_chirp.ino" -# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_48_chirp.ino" -#ifdef USE_I2C -#ifdef USE_CHIRP - - - - - - - -#define XSNS_48 48 -#define CHIRP_MAX_SENSOR_COUNT 3 - -#define CHIRP_ADDR_STANDARD 0x20 - - - - - -#define D_CMND_CHIRP "CHIRP" - -const char S_JSON_CHIRP_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_CHIRP "%s\":%d}"; -const char S_JSON_CHIRP_COMMAND[] PROGMEM = "{\"" D_CMND_CHIRP "%s\"}"; -const char kCHIRP_Commands[] PROGMEM = "Select|Set|Scan|Reset|Sleep|Wake"; - -const char kChirpTypes[] PROGMEM = "CHIRP"; - - - - - -enum CHIRP_Commands { - CMND_CHIRP_SELECT, - CMND_CHIRP_SET, - CMND_CHIRP_SCAN, - CMND_CHIRP_RESET, - CMND_CHIRP_SLEEP, - CMND_CHIRP_WAKE }; - - - - - - -#define CHIRP_GET_CAPACITANCE 0x00 -#define CHIRP_SET_ADDRESS 0x01 -#define CHIRP_GET_ADDRESS 0x02 -#define CHIRP_MEASURE_LIGHT 0x03 -#define CHIRP_GET_LIGHT 0x04 -#define CHIRP_GET_TEMPERATURE 0x05 -#define CHIRP_RESET 0x06 -#define CHIRP_GET_VERSION 0x07 -#define CHIRP_SLEEP 0x08 -#define CHIRP_GET_BUSY 0x09 - - - - - -bool I2cWriteReg(uint8_t addr, uint8_t reg) -{ - return I2cWrite(addr, reg, 0, 0); -} - - - - - -uint8_t chirp_current = 0; -uint8_t chirp_found_sensors = 0; - -char chirp_name[7]; -uint8_t chirp_next_job = 0; -uint32_t chirp_timeout_count = 0; - -#pragma pack(1) -struct ChirpSensor_t{ - uint16_t moisture = 0; - uint16_t light = 0; - int16_t temperature= 0; - uint8_t version = 0; - uint8_t address:7; - uint8_t explicitSleep:1; -}; -#pragma pack() - -ChirpSensor_t chirp_sensor[CHIRP_MAX_SENSOR_COUNT]; - - - -void ChirpReset(uint8_t addr) { - I2cWriteReg(addr, CHIRP_RESET); -} - - - -void ChirpResetAll(void) { - for (uint32_t i = 0; i < chirp_found_sensors; i++) { - if (chirp_sensor[i].version) { - ChirpReset(chirp_sensor[i].address); - } - } -} - - -void ChirpClockSet() { - Wire.setClockStretchLimit(4000); - Wire.setClock(50000); -} - - - -void ChirpSleep(uint8_t addr) { - I2cWriteReg(addr, CHIRP_SLEEP); -} -# 168 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_48_chirp.ino" -void ChirpSelect(uint8_t sensor) { - if(sensor < chirp_found_sensors) { - chirp_current = sensor; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: Sensor %u now active."), chirp_current); - } - if (sensor == 255) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: Sensor %u active at address 0x%x."), chirp_current, chirp_sensor[chirp_current].address); - } -} - - - -bool ChirpMeasureLight(void) { - for (uint32_t i = 0; i < chirp_found_sensors; i++) { - if (chirp_sensor[i].version && !chirp_sensor[i].explicitSleep) { - uint8_t lightReady = I2cRead8(chirp_sensor[i].address, CHIRP_GET_BUSY); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: busy status for light for sensor %u"), lightReady); - if (lightReady == 1) { - return false; - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: init measure light for sensor %u"), i); - I2cWriteReg(chirp_sensor[i].address, CHIRP_MEASURE_LIGHT); - } - } - return true; -} - - - -void ChirpReadCapTemp() { - for (uint32_t i = 0; i < chirp_found_sensors; i++) { - if (chirp_sensor[i].version && !chirp_sensor[i].explicitSleep) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: now really read CapTemp for sensor at address 0x%x"), chirp_sensor[i].address); - chirp_sensor[i].moisture = I2cRead16(chirp_sensor[i].address, CHIRP_GET_CAPACITANCE); - chirp_sensor[i].temperature = I2cRead16(chirp_sensor[i].address, CHIRP_GET_TEMPERATURE); - } - } -} - - - -bool ChirpReadLight() { - bool success = false; - for (uint32_t i = 0; i < chirp_found_sensors; i++) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: will read light for sensor %u"), i); - if (chirp_sensor[i].version) { - if (I2cValidRead16(&chirp_sensor[i].light, chirp_sensor[i].address, CHIRP_GET_LIGHT)){ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: light read success")); - success = true; - } - if(!chirp_sensor[i].explicitSleep){ success = true;} - } - } - return success; -} - - - -uint8_t ChirpReadVersion(uint8_t addr) { - return (I2cRead8(addr, CHIRP_GET_VERSION)); -} - - - -bool ChirpSet(uint8_t addr) { - if(addr < 128){ - if (I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr)){ - I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: Wrote adress %u "), addr); - ChirpReset(chirp_sensor[chirp_current].address); - chirp_sensor[chirp_current].address = addr; - return true; - } - } - return false; -} - - - -bool ChirpScan() { - ChirpClockSet(); - chirp_found_sensors = 0; - for (uint8_t address = 1; address <= 127; address++) { - chirp_sensor[chirp_found_sensors].version = 0; - chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); - delay(2); - chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); - if(chirp_sensor[chirp_found_sensors].version > 0) { - AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "CHIRP:", address); - if(chirp_found_sensors 0) { - return; - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: scan will start ...")); - if (ChirpScan()) { - uint8_t chirp_model = 0; - GetTextIndexed(chirp_name, sizeof(chirp_name), chirp_model, kChirpTypes); - } -} - - - - -void ChirpEverySecond(void) -{ - - if(chirp_timeout_count == 0) { - switch(chirp_next_job) { - case 0: - AddLog_P2(LOG_LEVEL_DEBUG,PSTR( "CHIRP: reset all")); - ChirpResetAll(); - chirp_timeout_count = 1; - chirp_next_job++; - break; - case 1: - - - chirp_next_job++; - break; - case 2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: call CapTemp twice")); - ChirpReadCapTemp(); - ChirpReadCapTemp(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: call measure light")); - ChirpMeasureLight(); - chirp_timeout_count = 2; - chirp_next_job++; - break; - case 3: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: call read light")); - if (ChirpReadLight()){ - - - chirp_next_job++; - } - break; - case 4: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: paused, waiting for TELE")); - break; - case 5: - if (Settings.tele_period > 9){ - chirp_timeout_count = Settings.tele_period - 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CHIRP: timeout: %u, tele: %u"), chirp_timeout_count, Settings.tele_period); - } - chirp_next_job = 1; - break; - } - } - else { - chirp_timeout_count--; - } -} - - - - -#define D_JSON_MOISTURE "Moisture" - -#ifdef USE_WEBSERVER - - - const char HTTP_SNS_MOISTURE[] PROGMEM = "{s} " D_JSON_MOISTURE ": {m}%s %{e}"; - const char HTTP_SNS_CHIRPVER[] PROGMEM = "{s} CHIRP-sensor %u at address: {m}0x%x{e}" - "{s} FW-version: {m}%s {e}"; ; - const char HTTP_SNS_CHIRPSLEEP[] PROGMEM = "{s} {m} is sleeping ...{e}"; -#endif - - - - -void ChirpShow(bool json) -{ - for (uint32_t i = 0; i < chirp_found_sensors; i++) { - if (chirp_sensor[i].version) { - - char str_moisture[33]; - dtostrfd(chirp_sensor[i].moisture, 0, str_moisture); - char str_temperature[33]; - double t_temperature = ((double) chirp_sensor[i].temperature )/10.0; - dtostrfd(t_temperature, Settings.flag2.temperature_resolution, str_temperature); - char str_light[33]; - dtostrfd(chirp_sensor[i].light, 0, str_light); - char str_version[33]; - dtostrfd(chirp_sensor[i].version, 0, str_version); - if (json) { - if(!chirp_sensor[i].explicitSleep){ - ResponseAppend_P(PSTR(",\"%s%u\":{\"" D_JSON_MOISTURE "\":%s,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":\"%s}"), - chirp_name, i, str_moisture, str_temperature, str_light);} - else { - ResponseAppend_P(PSTR(",\"%s%u\":{\"sleeping\"}"), - chirp_name, i); - } - #ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(str_temperature, str_moisture); - DomoticzSensor(DZ_ILLUMINANCE,chirp_sensor[i].light); - } - #endif - #ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CHIRPVER, i, chirp_sensor[i].address, str_version); - if (chirp_sensor[i].explicitSleep){ - WSContentSend_PD(HTTP_SNS_CHIRPSLEEP); - } - else { - WSContentSend_PD(HTTP_SNS_MOISTURE, str_moisture); - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, " ", chirp_sensor[i].light); - WSContentSend_PD(HTTP_SNS_TEMP, " ",str_temperature, TempUnit()); - } - - #endif - } - } - } -} - - - - - -bool ChirpCmd(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t disp_len = strlen(D_CMND_CHIRP); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_CHIRP), disp_len)) { - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kCHIRP_Commands); - - switch (command_code) { - case CMND_CHIRP_SELECT: - case CMND_CHIRP_SET: - if (XdrvMailbox.data_len > 0) { - if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(XdrvMailbox.payload); } - if (command_code == CMND_CHIRP_SET) { ChirpSet((uint8_t)XdrvMailbox.payload); } - Response_P(S_JSON_CHIRP_COMMAND_NVALUE, command, XdrvMailbox.payload); - } - else { - if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(255); } - Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); - } - break; - case CMND_CHIRP_SCAN: - case CMND_CHIRP_SLEEP: - case CMND_CHIRP_WAKE: - case CMND_CHIRP_RESET: - if (command_code == CMND_CHIRP_SCAN) { chirp_next_job = 0; - ChirpDetect(); } - if (command_code == CMND_CHIRP_SLEEP) { chirp_sensor[chirp_current].explicitSleep = true; - ChirpSleep(chirp_sensor[chirp_current].address); } - if (command_code == CMND_CHIRP_WAKE) { chirp_sensor[chirp_current].explicitSleep = false; - ChirpReadVersion(chirp_sensor[chirp_current].address); } - if (command_code == CMND_CHIRP_RESET) { ChirpReset(chirp_sensor[chirp_current].address); } - Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); - break; - default: - - serviced = false; - break; - } - } - return serviced; -} - - - - - -bool Xsns48(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - ChirpDetect(); - break; - case FUNC_EVERY_SECOND: - if(chirp_found_sensors > 0){ - ChirpEverySecond(); - } - break; - case FUNC_COMMAND: - result = ChirpCmd(); - break; - case FUNC_JSON_APPEND: - ChirpShow(1); - chirp_next_job = 5; - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - ChirpShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_49_solaxX1.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_49_solaxX1.ino" -#ifdef USE_SOLAX_X1 - - - - -#define XSNS_49 49 - -#ifndef SOLAXX1_SPEED -#define SOLAXX1_SPEED 9600 -#endif - -#define INVERTER_ADDRESS 0x0A - -#define D_SOLAX_X1 "SolaxX1" - -#include - -enum solaxX1_Error -{ - solaxX1_ERR_NO_ERROR, - solaxX1_ERR_CRC_ERROR -}; - -union { - uint32_t ErrMessage; - struct { - - uint8_t TzProtectFault:1; - uint8_t MainsLostFault:1; - uint8_t GridVoltFault:1; - uint8_t GridFreqFault:1; - uint8_t PLLLostFault:1; - uint8_t BusVoltFault:1; - uint8_t ErrBit06:1; - uint8_t OciFault:1; - - uint8_t Dci_OCP_Fault:1; - uint8_t ResidualCurrentFault:1; - uint8_t PvVoltFault:1; - uint8_t Ac10Mins_Voltage_Fault:1; - uint8_t IsolationFault:1; - uint8_t TemperatureOverFault:1; - uint8_t FanFault:1; - uint8_t ErrBit15:1; - - uint8_t SpiCommsFault:1; - uint8_t SciCommsFault:1; - uint8_t ErrBit18:1; - uint8_t InputConfigFault:1; - uint8_t EepromFault:1; - uint8_t RelayFault:1; - uint8_t SampleConsistenceFault:1; - uint8_t ResidualCurrent_DeviceFault:1; - - uint8_t ErrBit24:1; - uint8_t ErrBit25:1; - uint8_t ErrBit26:1; - uint8_t ErrBit27:1; - uint8_t ErrBit28:1; - uint8_t DCI_DeviceFault:1; - uint8_t OtherDeviceFault:1; - uint8_t ErrBit31:1; - }; -} ErrCode; - -const char kSolaxMode[] PROGMEM = D_WAITING "|" D_CHECKING "|" D_WORKING "|" D_FAILURE; - -const char kSolaxError[] PROGMEM = - D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|" - D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8; - - - -TasmotaSerial *solaxX1Serial; - -uint8_t solaxX1_Init = 1; - -uint8_t solaxX1_status = 0; -uint32_t solaxX1_errorCode = 0; - -float solaxX1_temperature = 0; -float solaxX1_energy_today = 0; -float solaxX1_dc1_voltage = 0; -float solaxX1_dc2_voltage = 0; -float solaxX1_dc1_current = 0; -float solaxX1_dc2_current = 0; -float solaxX1_ac_current = 0; -float solaxX1_ac_voltage = 0; -float solaxX1_frequency = 0; -float solaxX1_power = 0; -float solaxX1_energy_total = 0; -float solaxX1_runtime_total = 0; - -float solaxX1_dc1_power = 0; -float solaxX1_dc2_power = 0; - -bool queryOffline = false; -bool queryOfflineSend = false; -bool hasAddress = true; -bool inverterAddressSend = false; -bool inverterSnReceived = false; - -uint8_t header[2] = {0xAA, 0x55}; -uint8_t source[2] = {0x00, 0x00}; -uint8_t destination[2] = {0x00, 0x00}; -uint8_t controlCode[1] = {0x00}; -uint8_t functionCode[1] = {0x00}; -uint8_t dataLength[1] = {0x00}; -uint8_t data[16] = {0}; - -uint8_t message[30]; - - - -bool solaxX1_RS485ReceiveReady(void) -{ - return (solaxX1Serial->available() > 1); -} - -void solaxX1_RS485Send(uint8_t *msg, uint16_t msgLen) -{ - - uint16_t crc = solaxX1_calculateCRC(msg, msgLen - 1); - - while (solaxX1Serial->available() > 0) - { - solaxX1Serial->read(); - } - - solaxX1Serial->flush(); - solaxX1Serial->write(msg, msgLen); - solaxX1Serial->write(highByte(crc)); - solaxX1Serial->write(lowByte(crc)); -} - -uint8_t solaxX1_RS485Receive(uint8_t *value) -{ - uint8_t len = 0; - - while (solaxX1Serial->available() > 0) - { - value[len++] = (uint8_t)solaxX1Serial->read(); - } - - uint16_t crc = solaxX1_calculateCRC(value, len - 3); - - if (value[len - 1] == lowByte(crc) && value[len - 2] == highByte(crc)) - { - return solaxX1_ERR_NO_ERROR; - } - else - { - return solaxX1_ERR_CRC_ERROR; - } -} - -uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) -{ - uint8_t i; - uint16_t wChkSum; - wChkSum = 0; - - for (i = 0; i <= bLen; i++) - { - wChkSum = wChkSum + bExternTxPackage[i]; - } - return wChkSum; -} - -void solaxX1_setMessage(uint8_t *message) -{ - memcpy(message, header, 2); - memcpy(message + 2, source, 2); - memcpy(message + 4, destination, 2); - memcpy(message + 6, controlCode, 1); - memcpy(message + 7, functionCode, 1); - memcpy(message + 8, dataLength, 1); - memcpy(message + 9, data, sizeof(data)); -} - -void solaxX1_SendInverterAddress() -{ - source[0] = 0x00; - destination[0] = 0x00; - destination[1] = 0x00; - controlCode[0] = 0x10; - functionCode[0] = 0x01; - dataLength[0] = 0x0F; - - - data[14] = INVERTER_ADDRESS; - - solaxX1_setMessage(message); - solaxX1_RS485Send(message, 24); -} - -void solaxX1_QueryLiveData() -{ - source[0] = 0x01; - destination[0] = 0x00; - destination[1] = INVERTER_ADDRESS; - controlCode[0] = 0x11; - functionCode[0] = 0x02; - dataLength[0] = 0x00; - - solaxX1_setMessage(message); - solaxX1_RS485Send(message, 9); -} - -uint8_t solaxX1_ParseErrorCode(uint32_t code){ - ErrCode.ErrMessage = code; - - if (code == 0) return 0; - if (ErrCode.MainsLostFault) return 1; - if (ErrCode.GridVoltFault) return 2; - if (ErrCode.GridFreqFault) return 3; - if (ErrCode.PvVoltFault) return 4; - if (ErrCode.IsolationFault) return 5; - if (ErrCode.TemperatureOverFault) return 6; - if (ErrCode.FanFault) return 7; - if (ErrCode.OtherDeviceFault) return 8; -} - - - -uint8_t solaxX1_send_retry = 0; -uint8_t solaxX1_nodata_count = 0; - -void solaxX1_Update(void) -{ - uint8_t value[61] = {0}; - - bool data_ready = solaxX1_RS485ReceiveReady(); - - DEBUG_SENSOR_LOG(PSTR("SX1: queryOffline: %d , queryOfflineSend: %d, hasAddress: %d, inverterAddressSend: %d, solaxX1_send_retry: %d"), - queryOffline, queryOfflineSend, hasAddress, inverterAddressSend, solaxX1_send_retry); - - if (!hasAddress && (data_ready || solaxX1_send_retry == 0)) - { - - if (data_ready) - { - - if (inverterAddressSend) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Address confirmation response CRC error")); - } - else - { - if (value[6] == 0x10 && value[7] == 0x81 && value[9] == 0x06) - { - inverterAddressSend = false; - queryOfflineSend = false; - hasAddress = true; - } - } - } - - - if (queryOfflineSend) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline response CRC error")); - } - else - { - - if (value[6] == 0x10 && value[7] == 0x80 && inverterSnReceived == false) - { - for (uint8_t i = 9; i <= 22; i++) - { - data[i - 9] = value[i]; - } - inverterSnReceived = true; - } - - solaxX1_SendInverterAddress(); - - inverterAddressSend = true; - queryOfflineSend = false; - queryOffline = false; - } - } - } - - - if (queryOffline) - { - - source[0] = 0x01; - destination[1] = 0x00; - controlCode[0] = 0x10; - functionCode[0] = 0x00; - dataLength[0] = 0x00; - - solaxX1_setMessage(message); - solaxX1_RS485Send(message, 9); - - queryOfflineSend = true; - queryOffline = false; - } - - if (solaxX1_send_retry == 0) - { - - if (inverterAddressSend) - { - solaxX1_SendInverterAddress(); - } - if (queryOfflineSend) - { - queryOffline = true; - queryOfflineSend = false; - } - solaxX1_send_retry = 2; - } - - } - - if (hasAddress && (data_ready || solaxX1_send_retry == 0)) - { - - if (data_ready) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error")); - } - else - { - - - solaxX1_nodata_count = 0; - solaxX1_send_retry = 2; - uint32_t temporal = 0; - - temporal = (value[9] << 8) | value[10]; - solaxX1_temperature = temporal; - - temporal = (value[11] << 8) | value[12]; - solaxX1_energy_today = temporal * 0.1f; - - temporal = (value[13] << 8) | value[14]; - solaxX1_dc1_voltage = temporal * 0.1f; - - temporal = (value[15] << 8) | value[16]; - solaxX1_dc2_voltage = temporal * 0.1f; - - temporal = (value[17] << 8) | value[18]; - solaxX1_dc1_current = temporal * 0.1f; - - temporal = (value[19] << 8) | value[20]; - solaxX1_dc2_current = temporal * 0.1f; - - temporal = (value[21] << 8) | value[22]; - solaxX1_ac_current = temporal * 0.1f; - - temporal = (value[23] << 8) | value[24]; - solaxX1_ac_voltage = temporal * 0.1f; - - temporal = (value[25] << 8) | value[26]; - solaxX1_frequency = temporal * 0.01f; - - temporal = (value[27] << 8) | value[28]; - solaxX1_power = temporal; - - - - - temporal = (value[31] << 8) | (value[32] << 8) | (value[33] << 8) | value[34]; - solaxX1_energy_total = temporal * 0.1f; - - temporal = (value[35] << 8) | (value[36] << 8) | (value[37] << 8) | value[38]; - solaxX1_runtime_total = temporal; - - temporal = (value[39] << 8) | value[40]; - solaxX1_status = (uint8_t)temporal; -# 412 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_49_solaxX1.ino" - temporal = (value[58] << 8) | (value[57] << 8) | (value[56] << 8) | value[55]; - solaxX1_errorCode = (uint32_t)temporal; - - solaxX1_dc1_power = solaxX1_dc1_voltage * solaxX1_dc1_current; - solaxX1_dc2_power = solaxX1_dc2_voltage * solaxX1_dc2_current; - - solaxX1_QueryLiveData(); - } - } - - if (solaxX1_send_retry == 0) - { - solaxX1_send_retry = 2; - solaxX1_QueryLiveData(); - } - } - else - { - - if (solaxX1_nodata_count <= 10) - { - solaxX1_nodata_count++; - } - else if (solaxX1_nodata_count != 255) - { - - solaxX1_nodata_count = 255; - queryOffline = true; - queryOfflineSend = false; - hasAddress = false; - inverterAddressSend = false; - inverterSnReceived = false; - - solaxX1_temperature = solaxX1_dc1_voltage = solaxX1_dc2_voltage = solaxX1_dc1_current = solaxX1_dc2_current = solaxX1_ac_current = 0; - solaxX1_ac_voltage = solaxX1_frequency = solaxX1_power = solaxX1_dc1_power = solaxX1_dc2_power = solaxX1_status = 0; - - - } - } - - if (!data_ready) - solaxX1_send_retry--; -} - -void solaxX1Init(void) -{ - AddLog_P(LOG_LEVEL_DEBUG, PSTR("Solax X1 Inverter Init")); - DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX]); - solaxX1_Init = 0; - if ((pin[GPIO_SOLAXX1_RX] < 99) && (pin[GPIO_SOLAXX1_TX] < 99)) - { - solaxX1Serial = new TasmotaSerial(pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX], 1); - if (solaxX1Serial->begin(SOLAXX1_SPEED)) - { - if (solaxX1Serial->hardwareSerial()) - { - ClaimSerial(); - } - solaxX1_Init = 1; - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_solaxX1_DATA1[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}" - "{s}" D_SOLAX_X1 " " D_INVERTER_POWER "{m}%s " D_UNIT_WATT "{e}" - "{s}" D_SOLAX_X1 " " D_SOLAR_POWER "{m}%s " D_UNIT_WATT "{e}" - "{s}" D_SOLAX_X1 " " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_SOLAX_X1 " " D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_POWER "{m}%s " D_UNIT_WATT "{e}"; -#ifdef SOLAXX1_PV2 -const char HTTP_SNS_solaxX1_DATA2[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_PV2_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_PV2_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}"; -#endif -const char HTTP_SNS_solaxX1_DATA3[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%s " D_UNIT_HOUR "{e}" - "{s}" D_SOLAX_X1 " " D_STATUS "{m}%s" - "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s"; -#endif - -void solaxX1Show(bool json) -{ - char voltage[33]; - dtostrfd(solaxX1_ac_voltage, Settings.flag2.voltage_resolution, voltage); - char current[33]; - dtostrfd(solaxX1_ac_current, Settings.flag2.current_resolution, current); - char inverter_power[33]; - dtostrfd(solaxX1_power, Settings.flag2.wattage_resolution, inverter_power); - char solar_power[33]; - dtostrfd(solaxX1_dc1_power + solaxX1_dc2_power, Settings.flag2.wattage_resolution, solar_power); - char frequency[33]; - dtostrfd(solaxX1_frequency, Settings.flag2.frequency_resolution, frequency); - char energy_total[33]; - dtostrfd(solaxX1_energy_total, Settings.flag2.energy_resolution, energy_total); - char energy_today[33]; - dtostrfd(solaxX1_energy_today, Settings.flag2.energy_resolution, energy_today); - char pv1_voltage[33]; - dtostrfd(solaxX1_dc1_voltage, Settings.flag2.voltage_resolution, pv1_voltage); - char pv1_current[33]; - dtostrfd(solaxX1_dc1_current, Settings.flag2.current_resolution, pv1_current); - char pv1_power[33]; - dtostrfd(solaxX1_dc1_power, Settings.flag2.wattage_resolution, pv1_power); -#ifdef SOLAXX1_PV2 - char pv2_voltage[33]; - dtostrfd(solaxX1_dc2_voltage, Settings.flag2.voltage_resolution, pv2_voltage); - char pv2_current[33]; - dtostrfd(solaxX1_dc2_current, Settings.flag2.current_resolution, pv2_current); - char pv2_power[33]; - dtostrfd(solaxX1_dc2_power, Settings.flag2.wattage_resolution, pv2_power); -#endif - char temperature[33]; - dtostrfd(solaxX1_temperature, Settings.flag2.temperature_resolution, temperature); - char runtime[33]; - dtostrfd(solaxX1_runtime_total, 0, runtime); - char status[33]; - GetTextIndexed(status, sizeof(status), solaxX1_status, kSolaxMode); - - if (json) - { - ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" - D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_TOTAL "\":%s,\"" D_JSON_TODAY "\":%s,\"" - D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"), - voltage, current, inverter_power, - solar_power, frequency, energy_total, energy_today, - pv1_voltage, pv1_current, pv1_power); -#ifdef SOLAXX1_PV2 - ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), - pv2_voltage, pv2_current, pv2_power); -#endif - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d}"), - temperature, runtime, status, solaxX1_errorCode); - - -#ifdef USE_DOMOTICZ - if (0 == tele_period) - { - char energy_total_chr[33]; - dtostrfd(solaxX1_energy_total * 1000, 1, energy_total_chr); - - DomoticzSensor(DZ_VOLTAGE, voltage); - DomoticzSensor(DZ_CURRENT, current); - - if (solaxX1_temperature > 0) DomoticzSensor(DZ_TEMP, temperature); - if (solaxX1_energy_total > 0) DomoticzSensorPowerEnergy((int)solaxX1_power, energy_total_chr); - } -#endif -#ifdef USE_WEBSERVER - } - else - { - WSContentSend_PD(HTTP_SNS_solaxX1_DATA1, voltage, current, frequency, inverter_power, solar_power, energy_total, energy_today, pv1_voltage, pv1_current, pv1_power); -#ifdef SOLAXX1_PV2 - WSContentSend_PD(HTTP_SNS_solaxX1_DATA2, pv2_voltage, pv2_current, pv2_power); -#endif - WSContentSend_PD(HTTP_SNS_TEMP, D_SOLAX_X1, temperature, TempUnit()); - char errorCodeString[33]; - WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, runtime, status, - GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1_errorCode), kSolaxError)); -#endif - } -} - - - - - -bool Xsns49(uint8_t function) -{ - bool result = false; - - if (solaxX1_Init) - { - switch (function) - { - case FUNC_INIT: - solaxX1Init(); - break; - case FUNC_EVERY_SECOND: - solaxX1_Update(); - break; - case FUNC_JSON_APPEND: - solaxX1Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - solaxX1Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_50_paj7620.ino" -# 31 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_50_paj7620.ino" -#ifdef USE_I2C -#ifdef USE_PAJ7620 - - - - - - - -#define XSNS_50 50 - -#define PAJ7620_ADDR 0x73 - -#define PAJ7620_BANK_SEL 0xEF - - - -#define PAJ7620_GET_GESTURE 0x43 -#define PAJ7620_PROXIMITY_AVG_Y 0x6c - -#define PAJ7620_OBJECT_CENTER_X 0xad -#define PAJ7620_OBJECT_CENTER_Y 0xaf - -#define PAJ7620_DOWN 1 -#define PAJ7620_UP 2 -#define PAJ7620_RIGHT 4 -#define PAJ7620_LEFT 8 -#define PAJ7620_NEAR 16 -#define PAJ7620_FAR 32 -#define PAJ7620_CW 64 -#define PAJ7620_CCW 128 - - - - -const uint8_t PAJ7620initRegisterArray[][2] PROGMEM = { - {0xEF,0x00}, - {0x32,0x29}, {0x33,0x01}, {0x34,0x00}, {0x35,0x01}, {0x36,0x00}, {0x37,0x07}, {0x38,0x17}, {0x39,0x06}, - {0x3A,0x12}, {0x3F,0x00}, {0x40,0x02}, {0x41,0xFF}, {0x42,0x01}, {0x46,0x2D}, {0x47,0x0F}, {0x48,0x3C}, - {0x49,0x00}, {0x4A,0x1E}, {0x4B,0x00}, {0x4C,0x20}, {0x4D,0x00}, {0x4E,0x1A}, {0x4F,0x14}, {0x50,0x00}, - {0x51,0x10}, {0x52,0x00}, {0x5C,0x02}, {0x5D,0x00}, {0x5E,0x10}, {0x5F,0x3F}, {0x60,0x27}, {0x61,0x28}, - {0x62,0x00}, {0x63,0x03}, {0x64,0xF7}, {0x65,0x03}, {0x66,0xD9}, {0x67,0x03}, {0x68,0x01}, {0x69,0xC8}, - {0x6A,0x40}, {0x6D,0x04}, {0x6E,0x00}, {0x6F,0x00}, {0x70,0x80}, {0x71,0x00}, {0x72,0x00}, {0x73,0x00}, - {0x74,0xF0}, {0x75,0x00}, {0x80,0x42}, {0x81,0x44}, {0x82,0x04}, {0x83,0x20}, {0x84,0x20}, {0x85,0x00}, - {0x86,0x10}, {0x87,0x00}, {0x88,0x05}, {0x89,0x18}, {0x8A,0x10}, {0x8B,0x01}, {0x8C,0x37}, {0x8D,0x00}, - {0x8E,0xF0}, {0x8F,0x81}, {0x90,0x06}, {0x91,0x06}, {0x92,0x1E}, {0x93,0x0D}, {0x94,0x0A}, {0x95,0x0A}, - {0x96,0x0C}, {0x97,0x05}, {0x98,0x0A}, {0x99,0x41}, {0x9A,0x14}, {0x9B,0x0A}, {0x9C,0x3F}, {0x9D,0x33}, - {0x9E,0xAE}, {0x9F,0xF9}, {0xA0,0x48}, {0xA1,0x13}, {0xA2,0x10}, {0xA3,0x08}, {0xA4,0x30}, {0xA5,0x19}, - {0xA6,0x10}, {0xA7,0x08}, {0xA8,0x24}, {0xA9,0x04}, {0xAA,0x1E}, {0xAB,0x1E}, {0xCC,0x19}, {0xCD,0x0B}, - {0xCE,0x13}, {0xCF,0x64}, {0xD0,0x21}, {0xD1,0x0F}, {0xD2,0x88}, {0xE0,0x01}, {0xE1,0x04}, {0xE2,0x41}, - {0xE3,0xD6}, {0xE4,0x00}, {0xE5,0x0C}, {0xE6,0x0A}, {0xE7,0x00}, {0xE8,0x00}, {0xE9,0x00}, {0xEE,0x07}, - {0xEF,0x01}, - {0x00,0x1E}, {0x01,0x1E}, {0x02,0x0F}, {0x03,0x10}, {0x04,0x02}, {0x05,0x00}, {0x06,0xB0}, {0x07,0x04}, - {0x08,0x0D}, {0x09,0x0E}, {0x0A,0x9C}, {0x0B,0x04}, {0x0C,0x05}, {0x0D,0x0F}, {0x0E,0x02}, {0x0F,0x12}, - {0x10,0x02}, {0x11,0x02}, {0x12,0x00}, {0x13,0x01}, {0x14,0x05}, {0x15,0x07}, {0x16,0x05}, {0x17,0x07}, - {0x18,0x01}, {0x19,0x04}, {0x1A,0x05}, {0x1B,0x0C}, {0x1C,0x2A}, {0x1D,0x01}, {0x1E,0x00}, {0x21,0x00}, - {0x22,0x00}, {0x23,0x00}, {0x25,0x01}, {0x26,0x00}, {0x27,0x39}, {0x28,0x7F}, {0x29,0x08}, {0x30,0x03}, - {0x31,0x00}, {0x32,0x1A}, {0x33,0x1A}, {0x34,0x07}, {0x35,0x07}, {0x36,0x01}, {0x37,0xFF}, {0x38,0x36}, - {0x39,0x07}, {0x3A,0x00}, {0x3E,0xFF}, {0x3F,0x00}, {0x40,0x77}, {0x41,0x40}, {0x42,0x00}, {0x43,0x30}, - {0x44,0xA0}, {0x45,0x5C}, {0x46,0x00}, {0x47,0x00}, {0x48,0x58}, {0x4A,0x1E}, {0x4B,0x1E}, {0x4C,0x00}, - {0x4D,0x00}, {0x4E,0xA0}, {0x4F,0x80}, {0x50,0x00}, {0x51,0x00}, {0x52,0x00}, {0x53,0x00}, {0x54,0x00}, - {0x57,0x80}, {0x59,0x10}, {0x5A,0x08}, {0x5B,0x94}, {0x5C,0xE8}, {0x5D,0x08}, {0x5E,0x3D}, {0x5F,0x99}, - {0x60,0x45}, {0x61,0x40}, {0x63,0x2D}, {0x64,0x02}, {0x65,0x96}, {0x66,0x00}, {0x67,0x97}, {0x68,0x01}, - {0x69,0xCD}, {0x6A,0x01}, {0x6B,0xB0}, {0x6C,0x04}, {0x6D,0x2C}, {0x6E,0x01}, {0x6F,0x32}, {0x71,0x00}, - {0x72,0x01}, {0x73,0x35}, {0x74,0x00}, {0x75,0x33}, {0x76,0x31}, {0x77,0x01}, {0x7C,0x84}, {0x7D,0x03}, - {0x7E,0x01}, - {0xEF,0x00} -}; - - - - - -#define D_CMND_PAJ7620 "PAJ7620" - -const char S_JSON_PAJ7620_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_PAJ7620 "%s\":%d}"; - -const char kPAJ7620Types[] PROGMEM = "PAJ7620"; - -const uint8_t PAJ7620_PIN[]= {1,2,3,4}; - - - - - - -void PAJ7620SelectBank(uint8_t bank) -{ - switch(bank){ - case 0: - I2cWrite(PAJ7620_ADDR, PAJ7620_BANK_SEL, 0, 1); - break; - case 1: - I2cWrite(PAJ7620_ADDR, PAJ7620_BANK_SEL, 1, 1); - break; - default: - break; - } -} - - - -void PAJ7620TriggerTele(){ - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -#ifdef USE_RULES - RulesTeleperiod(); -#endif - } -} - - - - - -char PAJ7620_name[9]; - -uint32_t PAJ7620_timeout_counter = 10; -uint32_t PAJ7620_next_job = 0; -uint32_t PAJ7620_mode = 1; - -struct { - uint8_t current; - uint8_t last; - uint8_t same; - uint8_t unfinished; -} PAJ7620_gesture; - -bool PAJ7620_finished_gesture = false; -char PAJ7620_currentGestureName[6]; - -struct{ - uint8_t x; - uint8_t y; - uint8_t last_x; - uint8_t last_y; - uint8_t proximity; - uint8_t last_proximity; - uint8_t corner; - struct { - uint8_t step:3; - uint8_t countdown:3; - uint8_t valid:1; - } PIN; -} PAJ7620_state; - - - - -void PAJ7620DecodeGesture(void) -{ - switch (PAJ7620_gesture.current) { - case PAJ7620_DOWN: - DEBUG_SENSOR_LOG(PSTR("DOWN")); - snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("Down")); - if(PAJ7620_gesture.unfinished){ - PAJ7620_finished_gesture = true; - break; - } - PAJ7620_gesture.unfinished = PAJ7620_gesture.current; - PAJ7620_timeout_counter = 5; - break; - case PAJ7620_UP: - DEBUG_SENSOR_LOG(PSTR("UP")); - snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("Up")); - if(PAJ7620_gesture.unfinished){ - PAJ7620_finished_gesture = true; - break; - } - PAJ7620_gesture.unfinished = PAJ7620_gesture.current; - PAJ7620_timeout_counter = 5; - break; - case PAJ7620_RIGHT: - DEBUG_SENSOR_LOG(PSTR("RIGHT")); - snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("Right")); - if(PAJ7620_gesture.unfinished){ - PAJ7620_finished_gesture = true; - break; - } - PAJ7620_gesture.unfinished = PAJ7620_gesture.current; - PAJ7620_timeout_counter = 5; - break; - case PAJ7620_LEFT: - DEBUG_SENSOR_LOG(PSTR("LEFT")); - snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("Left")); - if(PAJ7620_gesture.unfinished){ - PAJ7620_finished_gesture = true; - break; - } - PAJ7620_gesture.unfinished = PAJ7620_gesture.current; - PAJ7620_timeout_counter = 5; - break; - case PAJ7620_NEAR: - DEBUG_SENSOR_LOG(PSTR("NEAR")); - snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("Near")); - PAJ7620_finished_gesture = true; - PAJ7620_timeout_counter = 25; - break; - case PAJ7620_FAR: - DEBUG_SENSOR_LOG(PSTR("FAR")); - snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("Far")); - PAJ7620_finished_gesture = true; - PAJ7620_timeout_counter = 25; - break; - case PAJ7620_CW: - DEBUG_SENSOR_LOG(PSTR("ClockWise")); - snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("CW")); - PAJ7620_finished_gesture = true; - break; - case PAJ7620_CCW: - DEBUG_SENSOR_LOG(PSTR("CounterClockWise")); - snprintf_P(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), PSTR("CCW")); - PAJ7620_finished_gesture = true; - break; - default: - if(PAJ7620_gesture.unfinished){ - PAJ7620_finished_gesture = true; - break; - } - break; - } -if(PAJ7620_finished_gesture){ - if (PAJ7620_gesture.unfinished){ - if(PAJ7620_gesture.current!=PAJ7620_NEAR && PAJ7620_gesture.current!=PAJ7620_FAR){ - PAJ7620_gesture.current = PAJ7620_gesture.unfinished; - } - } - if (PAJ7620_gesture.current == PAJ7620_gesture.last){ - PAJ7620_gesture.same++; - } - else{ - PAJ7620_gesture.same = 1; - } - PAJ7620_gesture.last = PAJ7620_gesture.current; - PAJ7620_finished_gesture = false; - PAJ7620_gesture.unfinished = 0; - PAJ7620_timeout_counter += 3; - PAJ7620TriggerTele(); - } -} - - -void PAJ7620ReadGesture(void){ - switch(PAJ7620_mode){ - case 1: - PAJ7620_gesture.current = I2cRead8(PAJ7620_ADDR,PAJ7620_GET_GESTURE); - if(PAJ7620_gesture.current > 0 || PAJ7620_gesture.unfinished){ - DEBUG_SENSOR_LOG(PSTR("PAJ7620: gesture: %u"),PAJ7620_gesture.current ); - PAJ7620DecodeGesture(); - } - - break; - case 2: - PAJ7620_state.proximity = I2cRead8(PAJ7620_ADDR, PAJ7620_PROXIMITY_AVG_Y); - if((PAJ7620_state.proximity>0)||(PAJ7620_state.last_proximity>0)) - { - if(PAJ7620_state.proximity!=PAJ7620_state.last_proximity){ - PAJ7620_state.last_proximity = PAJ7620_state.proximity; - DEBUG_SENSOR_LOG(PSTR("PAJ7620: Proximity: %u"),PAJ7620_state.proximity ); - PAJ7620TriggerTele(); - } - } - break; - case 3: case 4: case 5: - PAJ7620_state.x = I2cRead8(PAJ7620_ADDR, PAJ7620_OBJECT_CENTER_X); - PAJ7620_state.y = I2cRead8(PAJ7620_ADDR, PAJ7620_OBJECT_CENTER_Y); - if(PAJ7620_state.y>0 && PAJ7620_state.x>0){ - if(PAJ7620_state.y!=PAJ7620_state.last_y || PAJ7620_state.x!=PAJ7620_state.last_x){ - PAJ7620_state.last_y = PAJ7620_state.y; - PAJ7620_state.last_x = PAJ7620_state.x; - DEBUG_SENSOR_LOG(PSTR("PAJ7620: x: %u y: %u"), PAJ7620_state.x, PAJ7620_state.y); - - PAJ7620_state.corner = 0; - - - - switch(PAJ7620_state.y){ - case 0: case 1: case 2: case 3: case 4: case 5: - PAJ7620_state.corner = 3; - break; - case 9: case 10: case 11: case 12: case 13: case 14: - PAJ7620_state.corner = 1; - break; - default: - break; - } - if(PAJ7620_state.corner!=0){ - switch(PAJ7620_state.x){ - case 0: case 1: case 2: case 3: case 4: case 5: - break; - case 9: case 10: case 11: case 12: case 13: case 14: - PAJ7620_state.corner++; - break; - default: - PAJ7620_state.corner = 0; - break; - } - } - DEBUG_SENSOR_LOG(PSTR("PAJ7620: corner: %u"), PAJ7620_state.corner); - - if(PAJ7620_state.PIN.countdown == 0){ - PAJ7620_state.PIN.step=0; - PAJ7620_state.PIN.valid=0; - } - if(!PAJ7620_state.PIN.step){ - if(PAJ7620_state.corner == PAJ7620_PIN[PAJ7620_state.PIN.step]){ - PAJ7620_state.PIN.step=1; - PAJ7620_state.PIN.countdown=7; - } - } - else{ - if(PAJ7620_state.corner == PAJ7620_PIN[PAJ7620_state.PIN.step]){ - PAJ7620_state.PIN.step+=1; - PAJ7620_state.PIN.countdown=7; - } - else{ - PAJ7620_state.PIN.countdown-=1; - } - } - if(PAJ7620_state.PIN.step == 4){ - PAJ7620_state.PIN.valid = 1; - DEBUG_SENSOR_LOG(PSTR("PAJ7620: PIN valid!!")); - PAJ7620_state.PIN.countdown = 0; - } - PAJ7620TriggerTele(); - } - } - break; - default: - break; - } -} - - - -void PAJ7620Detect(void) -{ - DEBUG_SENSOR_LOG(PSTR("PAJ7620: scan will start ...")); - PAJ7620SelectBank(0); - PAJ7620SelectBank(0); - uint16_t PAJ7620_id = I2cRead16LE(PAJ7620_ADDR,0); - uint8_t PAJ7620_ver = I2cRead8(PAJ7620_ADDR,2); - if (PAJ7620_id == 0x7620) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAJ7620: sensor found with ID: 0x%x and VER: %u"), PAJ7620_id, PAJ7620_ver); - uint8_t PAJ7620_model = 0; - GetTextIndexed(PAJ7620_name, sizeof(PAJ7620_name), PAJ7620_model, kPAJ7620Types); - PAJ7620_next_job = 1; - } - else { - DEBUG_SENSOR_LOG(PSTR("PAJ7620: sensor not found, false ID 0x%x"), PAJ7620_id); - PAJ7620_next_job = 255; - } -} - - -void PAJ7620Init(void) -{ - DEBUG_SENSOR_LOG(PSTR("PAJ7620: init sensor start %u"),millis()); - union{ - uint32_t raw; - uint8_t reg_val[4]; - } buf; - for(uint32_t i = 0; i < (sizeof(PAJ7620initRegisterArray)/2); i+=2) - { - buf.raw = pgm_read_dword(PAJ7620initRegisterArray+i); - DEBUG_SENSOR_LOG("%x %x %x %x",buf.reg_val[0],buf.reg_val[1],buf.reg_val[2],buf.reg_val[3]); - I2cWrite(PAJ7620_ADDR, buf.reg_val[0], buf.reg_val[1], 1); - I2cWrite(PAJ7620_ADDR, buf.reg_val[2], buf.reg_val[3], 1); - } - DEBUG_SENSOR_LOG(PSTR("PAJ7620: init sensor done %u"),millis()); - PAJ7620_next_job = 2; -} - - - -void PAJ7620SelectMode(uint16_t mode){ - DEBUG_SENSOR_LOG(PSTR("PAJ7620: set mode to %u"),mode); - switch(mode){ - case 0: - PAJ7620_mode = 0; - break; - case 1: - PAJ7620_mode = 1; - break; - case 2: - PAJ7620_mode = 2; - break; - case 3: - PAJ7620_mode = 3; - break; - case 4: - PAJ7620_mode = 4; - break; - case 5: - PAJ7620_mode = 5; - break; - default: - break; - } -} - - -void PAJ7620Loop(void) -{ - if(PAJ7620_timeout_counter == 0){ - switch(PAJ7620_next_job){ - case 0: - PAJ7620Detect(); - break; - case 1: - PAJ7620Init(); - break; - case 2: - if(PAJ7620_mode != 0){ - PAJ7620ReadGesture(); - } - break; - default: - break; - } - } - else { - PAJ7620_timeout_counter--; - } -} - - - - -#define D_JSON_PAJ7620 "PAJ7620" - -#ifdef USE_WEBSERVER - - - const char HTTP_SNS_PAJ7620[] PROGMEM = "{s} " D_JSON_PAJ7620 ": {m}%s {e}"; - const char HTTP_SNS_PAJ7620VER[] PROGMEM = "{s} PAJ7620 at address: {m}0x73{e}" - "{s} version: {m}1 {e}"; - -#endif - - - - -void PAJ7620Show(bool json) -{ - if (json) { - if((PAJ7620_currentGestureName[0] != '\0' )){ - ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), PAJ7620_name, PAJ7620_currentGestureName, PAJ7620_gesture.same); - PAJ7620_currentGestureName[0] = '\0'; - return; - } - switch(PAJ7620_mode){ - case 2: - if(PAJ7620_mode>1){ - ResponseAppend_P(PSTR(",\"%s\":{\"Proximity\":%u}"), PAJ7620_name, PAJ7620_state.proximity); - } - break; - case 3: - if(PAJ7620_mode>1 && PAJ7620_state.corner>0){ - ResponseAppend_P(PSTR(",\"%s\":{\"Corner\":%u}"), PAJ7620_name, PAJ7620_state.corner); - } - break; - case 4: - if(PAJ7620_mode>1 && PAJ7620_state.PIN.valid){ - ResponseAppend_P(PSTR(",\"%s\":{\"PIN\":%u}"), PAJ7620_name, 1); - PAJ7620_state.PIN.valid = 0; - } - break; - case 5: - if(PAJ7620_mode>1){ - ResponseAppend_P(PSTR(",\"%s\":{\"x\":%u,\"y\":%u}"), PAJ7620_name, PAJ7620_state.x, PAJ7620_state.y); - } - break; - default: - break; - } - #ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_PAJ7620VER); - #endif - } -} - - - - - -bool PAJ7620Cmd(void) { - bool serviced = true; - if (XdrvMailbox.data_len > 0) { - DEBUG_SENSOR_LOG(PSTR("PAJ7620: got argument for mode")); - PAJ7620SelectMode(XdrvMailbox.payload); - Response_P(S_JSON_PAJ7620_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); - } - else { - DEBUG_SENSOR_LOG(PSTR("PAJ7620: show mode")); - Response_P(S_JSON_PAJ7620_COMMAND_NVALUE, XdrvMailbox.command, PAJ7620_mode); - } - return serviced; -} - - - - - -bool Xsns50(uint8_t function) -{ - bool result = false; - - if (i2c_flg) { - switch (function) { - case FUNC_INIT: - DEBUG_SENSOR_LOG(PSTR("PAJ7620: 1 second until init")); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_50 == XdrvMailbox.index){ - result = PAJ7620Cmd(); - } - break; - case FUNC_EVERY_100_MSECOND: - if(PAJ7620_next_job <255) { - PAJ7620Loop(); - } - break; - case FUNC_JSON_APPEND: - PAJ7620Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - PAJ7620Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_51_rdm6300.ino" -# 21 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_51_rdm6300.ino" -#ifdef USE_RDM6300 - -#define XSNS_51 51 - -#define RDM6300_BAUDRATE 9600 - -#include - -#define RDM_TIMEOUT 100 -char rdm_uid_str[10]; - - -#define RDM6300_BLOCK 2*10 - -uint8_t rdm_blcnt; -TasmotaSerial *RDM6300_Serial = nullptr; - -void RDM6300_Init() { - if (pin[GPIO_RDM6300_RX] < 99) { - RDM6300_Serial = new TasmotaSerial(pin[GPIO_RDM6300_RX],-1,1); - if (RDM6300_Serial->begin(RDM6300_BAUDRATE)) { - if (RDM6300_Serial->hardwareSerial()) { - ClaimSerial(); - } - } - } - rdm_blcnt=0; -} - - -void RDM6300_ScanForTag() { - char rdm_buffer[14]; - uint8_t rdm_index; - uint8_t rdm_array[6]; - - if (!RDM6300_Serial) return; - - if (rdm_blcnt>0) { - rdm_blcnt--; - while (RDM6300_Serial->available()) RDM6300_Serial->read(); - return; - } - - if (RDM6300_Serial->available()) { - - char c=RDM6300_Serial->read(); - if (c!=2) return; - - - rdm_index=0; - uint32_t cmillis=millis(); - while (1) { - if (RDM6300_Serial->available()) { - char c=RDM6300_Serial->read(); - if (c==3) { - - break; - } - rdm_buffer[rdm_index++]=c; - if (rdm_index>13) { - - return; - } - } - if ((millis()-cmillis)>RDM_TIMEOUT) { - - return; - } - } - - - rdm_blcnt=RDM6300_BLOCK; - - - rm6300_hstring_to_array(rdm_array,sizeof(rdm_array),rdm_buffer); - uint8_t accu=0; - for (uint8_t count=0;count<5;count++) { - accu^=rdm_array[count]; - } - if (accu!=rdm_array[5]) { - - return; - } - - - memcpy(rdm_uid_str,&rdm_buffer[2],8); - rdm_uid_str[9]=0; - - ResponseTime_P(PSTR(",\"RDM6300\":{\"UID\":\"%s\"}}"), rdm_uid_str); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - - - - - - } - - -} - -uint8_t rm6300_hexnibble(char chr) { - uint8_t rVal = 0; - if (isdigit(chr)) { - rVal = chr - '0'; - } else { - if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; - if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; - } - return rVal; -} - - -void rm6300_hstring_to_array(uint8_t array[], uint8_t len, char buffer[]) -{ - char *cp=buffer; - for (uint8_t i = 0; i < len; i++) { - uint8_t val = rm6300_hexnibble(*cp++) << 4; - array[i]= val | rm6300_hexnibble(*cp++); - } -} - -#ifdef USE_WEBSERVER -const char HTTP_RDM6300[] PROGMEM = - "{s}RDM6300 " "UID" "{m}%s" "{e}"; - -void RDM6300_Show(void) { - if (!RDM6300_Serial) return; - if (!rdm_uid_str[0]) strcpy(rdm_uid_str,"????"); - WSContentSend_PD(HTTP_RDM6300,rdm_uid_str); -} -#endif - - - - - -bool Xsns51(byte function) -{ - bool result = false; - - switch (function) { - case FUNC_INIT: - RDM6300_Init(); - break; - case FUNC_EVERY_100_MSECOND: - RDM6300_ScanForTag(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - RDM6300_Show(); - break; -#endif - } - return result; -} - -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_52_ibeacon.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_52_ibeacon.ino" -#ifdef USE_IBEACON - - - -#define XSNS_52 52 - -#include - -#define HM17_BAUDRATE 9600 - - - - -#define IB_TIMEOUT_INTERVAL 30 - -#define IB_UPDATE_TIME_INTERVAL 10 - -TasmotaSerial *IBEACON_Serial = nullptr; - - -uint8_t hm17_found,hm17_cmd,hm17_flag; - -#ifdef IBEACON_DEBUG -uint8_t hm17_debug=0; -#endif - - - -#define HM17_BSIZ 128 -char hm17_sbuffer[HM17_BSIZ]; -uint8_t hm17_sindex,hm17_result,hm17_scanning,hm17_connecting; -uint32_t hm17_lastms; -char ib_mac[14]; - - -#if 1 -uint8_t ib_upd_interval,ib_tout_interval; -#define IB_UPDATE_TIME ib_upd_interval -#define IB_TIMEOUT_TIME ib_tout_interval -#else -#undef IB_UPDATE_TIME -#undef IB_TIMEOUT_TIME -#define IB_UPDATE_TIME Settings.ib_upd_interval -#define IB_TIMEOUT_TIME Settings.ib_tout_interval -#endif - -enum {HM17_TEST,HM17_ROLE,HM17_IMME,HM17_DISI,HM17_IBEA,HM17_SCAN,HM17_DISC,HM17_RESET,HM17_RENEW,HM17_CON}; -#define HM17_SUCESS 99 - -struct IBEACON { - char FACID[8]; - char UID[32]; - char MAJOR[4]; - char MINOR[4]; - char PWR[2]; - char MAC[12]; - char RSSI[4]; -}; - -#define MAX_IBEACONS 16 - -struct IBEACON_UID { - char MAC[12]; - char RSSI[4]; - uint8_t FLAGS; - uint8_t TIME; -} ibeacons[MAX_IBEACONS]; - - -void IBEACON_Init() { - - hm17_found=0; - - - if ((pin[GPIO_IBEACON_RX] < 99) && (pin[GPIO_IBEACON_TX] < 99)) { - IBEACON_Serial = new TasmotaSerial(pin[GPIO_IBEACON_RX], pin[GPIO_IBEACON_TX],1); - if (IBEACON_Serial->begin(HM17_BAUDRATE)) { - if (IBEACON_Serial->hardwareSerial()) { - ClaimSerial(); - } - hm17_sendcmd(HM17_TEST); - hm17_lastms=millis(); - - IB_UPDATE_TIME=IB_UPDATE_TIME_INTERVAL; - IB_TIMEOUT_TIME=IB_TIMEOUT_INTERVAL; - } - } -} - -void hm17_every_second(void) { - if (!IBEACON_Serial) return; - - if (hm17_found) { - if (IB_UPDATE_TIME && (uptime%IB_UPDATE_TIME==0)) { - if (hm17_cmd!=99) { - if (hm17_flag&2) { - ib_sendbeep(); - } else { - if (!hm17_connecting) { - hm17_sendcmd(HM17_DISI); - } - } - } - } - for (uint32_t cnt=0;cntIB_TIMEOUT_TIME) { - ibeacons[cnt].FLAGS=0; - ibeacon_mqtt(ibeacons[cnt].MAC,"0000"); - } - } - } - } else { - if (uptime%20==0) { - hm17_sendcmd(HM17_TEST); - } - } -} - -void hm17_sbclr(void) { - memset(hm17_sbuffer,0,HM17_BSIZ); - hm17_sindex=0; - IBEACON_Serial->flush(); -} - -void hm17_sendcmd(uint8_t cmd) { - hm17_sbclr(); - hm17_cmd=cmd; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("hm17cmd %d"),cmd); -#endif - switch (cmd) { - case HM17_TEST: - IBEACON_Serial->write("AT"); - break; - case HM17_ROLE: - IBEACON_Serial->write("AT+ROLE1"); - break; - case HM17_IMME: - IBEACON_Serial->write("AT+IMME1"); - break; - case HM17_DISI: - IBEACON_Serial->write("AT+DISI?"); - hm17_scanning=1; - break; - case HM17_IBEA: - IBEACON_Serial->write("AT+IBEA1"); - break; - case HM17_RESET: - IBEACON_Serial->write("AT+RESET"); - break; - case HM17_RENEW: - IBEACON_Serial->write("AT+RENEW"); - break; - case HM17_SCAN: - IBEACON_Serial->write("AT+SCAN5"); - break; - case HM17_DISC: - IBEACON_Serial->write("AT+DISC?"); - hm17_scanning=1; - break; - case HM17_CON: - IBEACON_Serial->write((const uint8_t*)"AT+CON",6); - IBEACON_Serial->write((const uint8_t*)ib_mac,12); - hm17_connecting=1; - break; - } -} - -uint32_t ibeacon_add(struct IBEACON *ib) { - - if (!strncmp(ib->MAC,"FFFF",4) || strncmp(ib->FACID,"00000000",8)) { - for (uint32_t cnt=0;cntMAC,12)) { - - memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); - ibeacons[cnt].TIME=0; - return 1; - } - } - } - for (uint32_t cnt=0;cntMAC,12); - memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); - ibeacons[cnt].FLAGS=1; - ibeacons[cnt].TIME=0; - return 1; - } - } - } - return 0; -} - -void hm17_decode(void) { - struct IBEACON ib; - switch (hm17_cmd) { - case HM17_TEST: - if (!strncmp(hm17_sbuffer,"OK",2)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("AT OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - hm17_found=1; - } - break; - case HM17_ROLE: - if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("ROLE OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_IMME: - if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("IMME OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_IBEA: - if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("IBEA OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_SCAN: - if (!strncmp(hm17_sbuffer,"OK+Set:5",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("SCAN OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_RESET: - if (!strncmp(hm17_sbuffer,"OK+RESET",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("RESET OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_RENEW: - if (!strncmp(hm17_sbuffer,"OK+RENEW",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("RENEW OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_CON: - if (!strncmp(hm17_sbuffer,"OK+CONNA",8)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNA OK")); -#endif - hm17_connecting=2; - break; - } - if (!strncmp(hm17_sbuffer,"OK+CONNE",8)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNE ERROR")); -#endif - break; - } - if (!strncmp(hm17_sbuffer,"OK+CONNF",8)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNF ERROR")); -#endif - break; - } - if (hm17_connecting==2 && !strncmp(hm17_sbuffer,"OK+CONN",7)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONN OK")); -#endif - hm17_connecting=3; - hm17_sendcmd(HM17_TEST); - hm17_connecting=0; - break; - } - break; - - case HM17_DISI: - case HM17_DISC: - if (!strncmp(hm17_sbuffer,"OK+DISCS",8)) { - hm17_sbclr(); - hm17_result=1; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISCS OK")); -#endif - break; - } - if (!strncmp(hm17_sbuffer,"OK+DISCE",8)) { - hm17_sbclr(); - hm17_result=HM17_SUCESS; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISCE OK")); -#endif - hm17_scanning=0; - break; - } - if (!strncmp(hm17_sbuffer,"OK+NAME:",8)) { - if (hm17_sbuffer[hm17_sindex-1]=='\n') { - hm17_result=HM17_SUCESS; -#ifdef IBEACON_DEBUG - if (hm17_debug) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("NAME OK")); - AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); - } -#endif - hm17_sbclr(); - } - break; - } - if (!strncmp(hm17_sbuffer,"OK+DIS0:",8)) { - if (hm17_sindex==20) { - hm17_result=HM17_SUCESS; -#ifdef IBEACON_DEBUG - if (hm17_debug) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("DIS0 OK")); - AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); - } -#endif - hm17_sbclr(); - } - break; - } - if (!strncmp(hm17_sbuffer,"OK+DISC:",8)) { - if (hm17_cmd==HM17_DISI) { - if (hm17_sindex==78) { -#ifdef IBEACON_DEBUG - if (hm17_debug) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("DISC: OK")); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); - } -#endif - memcpy(ib.FACID,&hm17_sbuffer[8],8); - memcpy(ib.UID,&hm17_sbuffer[8+8+1],32); - memcpy(ib.MAJOR,&hm17_sbuffer[8+8+1+32+1],4); - memcpy(ib.MINOR,&hm17_sbuffer[8+8+1+32+1+4],4); - memcpy(ib.PWR,&hm17_sbuffer[8+8+1+32+1+4+4],2); - memcpy(ib.MAC,&hm17_sbuffer[8+8+1+32+1+4+4+2+1],12); - memcpy(ib.RSSI,&hm17_sbuffer[8+8+1+32+1+4+4+2+1+12+1],4); - - if (ibeacon_add(&ib)) { - ibeacon_mqtt(ib.MAC,ib.RSSI); - } - hm17_sbclr(); - hm17_result=1; - } - } else { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); -#endif - } - break; - } - } -} - -void IBEACON_loop() { - - if (!IBEACON_Serial) return; - -uint32_t difftime=millis()-hm17_lastms; - - while (IBEACON_Serial->available()) { - hm17_lastms=millis(); - - if (hm17_sindexread(); - hm17_sindex++; - hm17_decode(); - } else { - hm17_sindex=0; - break; - } - } - - if (hm17_cmd==99) { - if (hm17_sindex>=HM17_BSIZ-2 || (hm17_sindex && (difftime>100))) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),hm17_sbuffer); - hm17_sbclr(); - } - } - -} - -#ifdef USE_WEBSERVER -const char HTTP_IBEACON[] PROGMEM = - "{s}IBEACON-UID : %s" " - RSSI : %s" "{m}{e}"; - -void IBEACON_Show(void) { -char mac[14]; -char rssi[6]; - - for (uint32_t cnt=0;cnt 0) { - char *cp=XdrvMailbox.data; - if (*cp>='0' && *cp<='8') { - hm17_sendcmd(*cp&7); - Response_P(S_JSON_IBEACON, XSNS_52,"hm17cmd",*cp&7); - } else if (*cp=='s') { - cp++; - len--; - while (*cp==' ') { - len--; - cp++; - } - IBEACON_Serial->write((uint8_t*)cp,len); - hm17_cmd=99; - Response_P(S_JSON_IBEACON1, XSNS_52,"hm17cmd",cp); - } else if (*cp=='u') { - cp++; - if (*cp) IB_UPDATE_TIME=atoi(cp); - Response_P(S_JSON_IBEACON, XSNS_52,"uintv",IB_UPDATE_TIME); - } else if (*cp=='t') { - cp++; - if (*cp) IB_TIMEOUT_TIME=atoi(cp); - Response_P(S_JSON_IBEACON, XSNS_52,"lintv",IB_TIMEOUT_TIME); - } else if (*cp=='c') { - for (uint32_t cnt=0;cnt - - -#define SPECIAL_SS - - - - - -#if DMY_LANGUAGE==de-DE - -#define D_TPWRIN "Verbrauch" -#define D_TPWROUT "Einspeisung" -#define D_TPWRCURR "Aktueller Verbrauch" -#define D_TPWRCURR1 "Verbrauch P1" -#define D_TPWRCURR2 "Verbrauch P2" -#define D_TPWRCURR3 "Verbrauch P3" -#define D_Strom_L1 "Strom L1" -#define D_Strom_L2 "Strom L2" -#define D_Strom_L3 "Strom L3" -#define D_Spannung_L1 "Spannung L1" -#define D_Spannung_L2 "Spannung L2" -#define D_Spannung_L3 "Spannung L3" -#define D_METERNR "Zähler Nr" -#define D_METERSID "Service ID" -#define D_GasIN "Zählerstand" -#define D_H2oIN "Zählerstand" -#define D_StL1L2L3 "Ströme L1+L2+L3" -#define D_SpL1L2L3 "Spannung L1+L2+L3/3" - -#else - -#undef D_TPWRIN -#undef D_TPWROUT -#undef D_TPWRCURR -#undef D_TPWRCURR1 -#undef D_TPWRCURR2 -#undef D_TPWRCURR3 -#undef D_Strom_L1 -#undef D_Strom_L2 -#undef D_Strom_L3 -#undef D_Spannung_L1 -#undef D_Spannung_L2 -#undef D_Spannung_L3 -#undef D_METERNR -#undef D_METERSID -#undef D_GasIN -#undef D_H2oIN -#undef D_StL1L2L3 -#undef D_SpL1L2L3 - -#define D_TPWRIN "Total-In" -#define D_TPWROUT "Total-Out" -#define D_TPWRCURR "Current-In/Out" -#define D_TPWRCURR1 "Current-In p1" -#define D_TPWRCURR2 "Current-In p2" -#define D_TPWRCURR3 "Current-In p3" -#define D_Strom_L1 "Current L1" -#define D_Strom_L2 "Current L2" -#define D_Strom_L3 "Current L3" -#define D_Spannung_L1 "Voltage L1" -#define D_Spannung_L2 "Voltage L2" -#define D_Spannung_L3 "Voltage L3" -#define D_METERNR "Meter_number" -#define D_METERSID "Service ID" -#define D_GasIN "Counter" -#define D_H2oIN "Counter" -#define D_StL1L2L3 "Current L1+L2+L3" -#define D_SpL1L2L3 "Voltage L1+L2+L3/3" - -#endif - - - -#define DJ_TPWRIN "Total_in" -#define DJ_TPWROUT "Total_out" -#define DJ_TPWRCURR "Power_curr" -#define DJ_TPWRCURR1 "Power_p1" -#define DJ_TPWRCURR2 "Power_p2" -#define DJ_TPWRCURR3 "Power_p3" -#define DJ_CURR1 "Curr_p1" -#define DJ_CURR2 "Curr_p2" -#define DJ_CURR3 "Curr_p3" -#define DJ_VOLT1 "Volt_p1" -#define DJ_VOLT2 "Volt_p2" -#define DJ_VOLT3 "Volt_p3" -#define DJ_METERNR "Meter_number" -#define DJ_METERSID "Meter_id" -#define DJ_CSUM "Curr_summ" -#define DJ_VAVG "Volt_avg" -#define DJ_COUNTER "Count" - -struct METER_DESC { - uint8_t srcpin; - uint8_t type; - uint16_t flag; - int32_t params; - char prefix[8]; - int8_t trxpin; - uint8_t tsecs; - char *txmem; - uint8_t index; - uint8_t max_index; -}; - - - - - - -#define EHZ161_0 1 -#define EHZ161_1 2 -#define EHZ363 3 -#define EHZH 4 -#define EDL300 5 -#define Q3B 6 -#define COMBO3 7 -#define COMBO2 8 -#define COMBO3a 9 -#define Q3B_V1 10 -#define EHZ363_2 11 -#define COMBO3b 12 -#define WGS_COMBO 13 -#define EBZD_G 14 - - -#define METER EHZ161_1 - - -#if METER==EHZ161_0 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; -const uint8_t meter[]= -"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,1-0:21.7.0*255(@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",0|" -"1,1-0:41.7.0*255(@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",0|" -"1,1-0:61.7.0*255(@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",0|" -"1,=m 3+4+5 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; - -#endif - - - -#if METER==EHZ161_1 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; -const uint8_t meter[]= -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; -#endif - - - -#if METER==EHZ363 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" - -"1,77070100000009ff@#," D_METERNR ",," DJ_METERNR ",0"; -#endif - - - -#if METER==EHZH -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - - -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,770701000f0700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; -#endif - - - -#if METER==EDL300 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - - -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020801ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,770701000f0700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; -#endif - -#if METER==EBZD_G -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"strom",-1,1,0}}; -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,77070100010801ff@1000," D_TPWRCURR1 ",KWh," DJ_TPWRCURR1 ",4|" - -"1,77070100010802ff@1000," D_TPWRCURR2 ",KWh," DJ_TPWRCURR2 ",4|" - -"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" - -"1,77070100600100ff@#," D_METERNR ",," DJ_METERNR ",0"; -#endif - - - - -#if METER==Q3B -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020801ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,77070100010700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; -#endif - -#if METER==COMBO3 - -#undef METERS_USED -#define METERS_USED 3 - -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, - [1]={14,'s',0,SML_BAUDRATE,"SML",-1,1,0}, - [2]={4,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; - - -const uint8_t meter[]= -"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,1-0:21.7.0*255(@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",0|" -"1,1-0:41.7.0*255(@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",0|" -"1,1-0:61.7.0*255(@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",0|" -"1,=m 3+4+5 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" -"2,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"2,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"2,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"3,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"3,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"3,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"3,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; - -#endif - -#if METER==COMBO2 - -#undef METERS_USED -#define METERS_USED 2 - -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, - [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; - - -const uint8_t meter[]= -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" - -"2,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"2,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"2,=d 6 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"2,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; - -#endif - -#if METER==COMBO3a -#undef METERS_USED -#define METERS_USED 3 - -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, - [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}, - [2]={1,'o',0,SML_BAUDRATE,"OBIS3",-1,1,0}}; - - -const uint8_t meter[]= -"1,=h --- Zähler Nr 1 ---|" -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" -"2,=h --- Zähler Nr 2 ---|" -"2,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"2,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"2,=d 6 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"2,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" -"3,=h --- Zähler Nr 3 ---|" -"3,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"3,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"3,=d 10 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"3,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; - -#endif - - - -#if METER==Q3B_V1 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ -[0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; -const uint8_t meter[]= -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,=d 1 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; -#endif - - - -#if METER==EHZ363_2 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ -[0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,77070100010801ff@1000," D_TPWRCURR1 ",KWh," DJ_TPWRCURR1 ",4|" - -"1,77070100010802ff@1000," D_TPWRCURR2 ",KWh," DJ_TPWRCURR2 ",4|" - -"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" - -"1,77070100000009ff@#," D_METERNR ",," DJ_METERNR ",0"; -#endif - - -#if METER==COMBO3b -#undef METERS_USED -#define METERS_USED 3 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, - [1]={14,'c',0,50,"Gas"}, - [2]={1,'c',0,10,"Wasser"}}; - - -const uint8_t meter[]= -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" - - -"2,1-0:1.8.0*255(@100," D_GasIN ",cbm," DJ_COUNTER ",2|" - -"3,1-0:1.8.0*255(@100," D_H2oIN ",cbm," DJ_COUNTER ",2"; -#endif - - -#if METER==WGS_COMBO -#undef METERS_USED -#define METERS_USED 3 - -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={1,'c',0,10,"H20",-1,1,0}, - [1]={4,'c',0,50,"GAS",-1,1,0}, - [2]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - -const uint8_t meter[]= - - -"1,1-0:1.8.0*255(@10000," D_H2oIN ",cbm," DJ_COUNTER ",4|" - - -"2,=h==================|" -"2,1-0:1.8.0*255(@100," D_GasIN ",cbm," DJ_COUNTER ",3|" - -"3,=h==================|" - -"3,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",3|" -"3,=h==================|" - -"3,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",2|" -"3,=h -------------------------------|" -"3,=m 10+11+12 @100," D_StL1L2L3 ",A," DJ_CSUM ",2|" - -"3,=m 13+14+15/#3 @100," D_SpL1L2L3 ",V," DJ_VAVG ",2|" -"3,=h==================|" - -"3,77070100240700ff@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",2|" - -"3,77070100380700ff@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",2|" - -"3,770701004c0700ff@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",2|" -"3,=h -------------------------------|" - -"3,770701001f0700ff@100," D_Strom_L1 ",A," DJ_CURR1 ",2|" - -"3,77070100330700ff@100," D_Strom_L2 ",A," DJ_CURR2 ",2|" - -"3,77070100470700ff@100," D_Strom_L3 ",A," DJ_CURR3 ",2|" -"3,=h -------------------------------|" - -"3,77070100200700ff@100," D_Spannung_L1 ",V," DJ_VOLT1 ",2|" - -"3,77070100340700ff@100," D_Spannung_L2 ",V," DJ_VOLT2 ",2|" - -"3,77070100480700ff@100," D_Spannung_L3 ",V," DJ_VOLT3 ",2|" -"3,=h==================|" - -"3,77070100000009ff@#," D_METERSID ",," DJ_METERSID ",0|" -"3,=h--------------------------------"; -#endif -# 499 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_53_sml.ino" -#define USE_SML_MEDIAN_FILTER - - -#define MAX_VARS 20 - -#define MAX_METERS 5 -double meter_vars[MAX_VARS]; - -#define MAX_DVARS MAX_METERS*2 -double dvalues[MAX_DVARS]; -uint32_t dtimes[MAX_DVARS]; -uint8_t meters_used; - -struct METER_DESC const *meter_desc_p; -const uint8_t *meter_p; -uint8_t meter_spos[MAX_METERS]; - - -TasmotaSerial *meter_ss[MAX_METERS]; - - -#define SML_BSIZ 48 -uint8_t smltbuf[MAX_METERS][SML_BSIZ]; - - -#define METER_ID_SIZE 24 -char meter_id[MAX_METERS][METER_ID_SIZE]; - -#define EBUS_SYNC 0xaa -#define EBUS_ESC 0xa9 - -uint8_t sml_send_blocks; -uint8_t sml_100ms_cnt; -uint8_t sml_desc_cnt; - -#ifdef USE_SML_MEDIAN_FILTER - -#define MEDIAN_SIZE 5 -struct SML_MEDIAN_FILTER { -double buffer[MEDIAN_SIZE]; -int8_t index; -} sml_mf[MAX_VARS]; - - -double sml_median_array(double *array,uint8_t len) { - uint8_t ind[len]; - uint8_t mind=0,index=0,flg; - double min=FLT_MAX; - - for (uint8_t hcnt=0; hcntbuffer[mf->index]=in; - mf->index++; - if (mf->index>=MEDIAN_SIZE) mf->index=0; - - return sml_median_array(mf->buffer,MEDIAN_SIZE); -# 597 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_53_sml.ino" -} -#endif - -#ifdef ANALOG_OPTO_SENSOR - -uint8_t ads1115_up; - - -#define SAMPLE_BIT (0x8000) - -#define ADS1115_COMP_QUEUE_SHIFT 0 -#define ADS1115_COMP_LATCH_SHIFT 2 -#define ADS1115_COMP_POLARITY_SHIFT 3 -#define ADS1115_COMP_MODE_SHIFT 4 -#define ADS1115_DATA_RATE_SHIFT 5 -#define ADS1115_MODE_SHIFT 8 -#define ADS1115_PGA_SHIFT 9 -#define ADS1115_MUX_SHIFT 12 - -enum ads1115_comp_queue { - ADS1115_COMP_QUEUE_AFTER_ONE = 0, - ADS1115_COMP_QUEUE_AFTER_TWO = 0x1 << ADS1115_COMP_QUEUE_SHIFT, - ADS1115_COMP_QUEUE_AFTER_FOUR = 0x2 << ADS1115_COMP_QUEUE_SHIFT, - ADS1115_COMP_QUEUE_DISABLE = 0x3 << ADS1115_COMP_QUEUE_SHIFT, - ADS1115_COMP_QUEUE_MASK = 0x3 << ADS1115_COMP_QUEUE_SHIFT, -}; - -enum ads1115_comp_latch { - ADS1115_COMP_LATCH_NO = 0, - ADS1115_COMP_LATCH_YES = 1 << ADS1115_COMP_LATCH_SHIFT, - ADS1115_COMP_LATCH_MASK = 1 << ADS1115_COMP_LATCH_SHIFT, -}; - -enum ads1115_comp_polarity { - ADS1115_COMP_POLARITY_ACTIVE_LOW = 0, - ADS1115_COMP_POLARITY_ACTIVE_HIGH = 1 << ADS1115_COMP_POLARITY_SHIFT, - ADS1115_COMP_POLARITY_MASK = 1 << ADS1115_COMP_POLARITY_SHIFT, -}; - -enum ads1115_comp_mode { - ADS1115_COMP_MODE_WINDOW = 0, - ADS1115_COMP_MODE_HYSTERESIS = 1 << ADS1115_COMP_MODE_SHIFT, - ADS1115_COMP_MODE_MASK = 1 << ADS1115_COMP_MODE_SHIFT, -}; - -enum ads1115_data_rate { - ADS1115_DATA_RATE_8_SPS = 0, - ADS1115_DATA_RATE_16_SPS = 0x1 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_32_SPS = 0x2 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_64_SPS = 0x3 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_128_SPS = 0x4 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_250_SPS = 0x5 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_475_SPS = 0x6 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_860_SPS = 0x7 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_MASK = 0x7 << ADS1115_DATA_RATE_SHIFT, -}; - -enum ads1115_mode { - ADS1115_MODE_CONTINUOUS = 0, - ADS1115_MODE_SINGLE_SHOT = 1 << ADS1115_MODE_SHIFT, - ADS1115_MODE_MASK = 1 << ADS1115_MODE_SHIFT, -}; - -enum ads1115_pga { - ADS1115_PGA_TWO_THIRDS = 0, - ADS1115_PGA_ONE = 0x1 << ADS1115_PGA_SHIFT, - ADS1115_PGA_TWO = 0x2 << ADS1115_PGA_SHIFT, - ADS1115_PGA_FOUR = 0x3 << ADS1115_PGA_SHIFT, - ADS1115_PGA_EIGHT = 0x4 << ADS1115_PGA_SHIFT, - ADS1115_PGA_SIXTEEN = 0x5 << ADS1115_PGA_SHIFT, - ADS1115_PGA_MASK = 0x7 << ADS1115_PGA_SHIFT, -}; - - -enum ads1115_mux { - ADS1115_MUX_DIFF_AIN0_AIN1 = 0, - ADS1115_MUX_DIFF_AIN0_AIN3 = 0x1 << ADS1115_MUX_SHIFT, - ADS1115_MUX_DIFF_AIN1_AIN3 = 0x2 << ADS1115_MUX_SHIFT, - ADS1115_MUX_DIFF_AIN2_AIN3 = 0x3 << ADS1115_MUX_SHIFT, - ADS1115_MUX_GND_AIN0 = 0x4 << ADS1115_MUX_SHIFT, - ADS1115_MUX_GND_AIN1 = 0x5 << ADS1115_MUX_SHIFT, - ADS1115_MUX_GND_AIN2 = 0x6 << ADS1115_MUX_SHIFT, - ADS1115_MUX_GND_AIN3 = 0x7 << ADS1115_MUX_SHIFT, - ADS1115_MUX_MASK = 0x7 << ADS1115_MUX_SHIFT, -}; - -class ADS1115 { -public: - ADS1115(uint8_t address = 0x48); - - void begin(); - uint8_t trigger_sample(); - uint8_t reset(); - bool is_sample_in_progress(); - int16_t read_sample(); - float sample_to_float(int16_t val); - float read_sample_float(); - - void set_comp_queue(enum ads1115_comp_queue val) { set_config(val, ADS1115_COMP_QUEUE_MASK); } - void set_comp_latching(enum ads1115_comp_latch val) { set_config(val, ADS1115_COMP_LATCH_MASK); } - void set_comp_polarity(enum ads1115_comp_polarity val) { set_config(val, ADS1115_COMP_POLARITY_MASK); } - void set_comp_mode(enum ads1115_comp_mode val) { set_config(val, ADS1115_COMP_MODE_MASK); } - void set_data_rate(enum ads1115_data_rate val) { set_config(val, ADS1115_DATA_RATE_MASK); } - void set_mode(enum ads1115_mode val) { set_config(val, ADS1115_MODE_MASK); } - void set_pga(enum ads1115_pga val) { set_config(val, ADS1115_PGA_MASK); m_voltage_range = val >> ADS1115_PGA_SHIFT; } - void set_mux(enum ads1115_mux val) { set_config(val, ADS1115_MUX_MASK); } - -private: - void set_config(uint16_t val, uint16_t mask) { - m_config = (m_config & ~mask) | val; - } - - uint8_t write_register(uint8_t reg, uint16_t val); - uint16_t read_register(uint8_t reg); - - uint8_t m_address; - uint16_t m_config; - int m_voltage_range; -}; - - -enum ads1115_register { - ADS1115_REGISTER_CONVERSION = 0, - ADS1115_REGISTER_CONFIG = 1, - ADS1115_REGISTER_LOW_THRESH = 2, - ADS1115_REGISTER_HIGH_THRESH = 3, -}; - -#define FACTOR 32768.0 -static float ranges[] = { 6.144 / FACTOR, 4.096 / FACTOR, 2.048 / FACTOR, 1.024 / FACTOR, 0.512 / FACTOR, 0.256 / FACTOR}; - -ADS1115::ADS1115(uint8_t address) -{ - m_address = address; - m_config = ADS1115_COMP_QUEUE_AFTER_ONE | - ADS1115_COMP_LATCH_NO | - ADS1115_COMP_POLARITY_ACTIVE_LOW | - ADS1115_COMP_MODE_WINDOW | - ADS1115_DATA_RATE_128_SPS | - ADS1115_MODE_SINGLE_SHOT | - ADS1115_MUX_GND_AIN0; - set_pga(ADS1115_PGA_ONE); -} - -uint8_t ADS1115::write_register(uint8_t reg, uint16_t val) -{ - Wire.beginTransmission(m_address); - Wire.write(reg); - Wire.write(val>>8); - Wire.write(val & 0xFF); - return Wire.endTransmission(); -} - -uint16_t ADS1115::read_register(uint8_t reg) -{ - Wire.beginTransmission(m_address); - Wire.write(reg); - Wire.endTransmission(); - - uint8_t result = Wire.requestFrom((int)m_address, 2, 1); - if (result != 2) { - return 0; - } - - uint16_t val; - - val = Wire.read() << 8; - val |= Wire.read(); - return val; -} - -void ADS1115::begin() -{ - Wire.begin(); -} - -uint8_t ADS1115::trigger_sample() -{ - return write_register(ADS1115_REGISTER_CONFIG, m_config | SAMPLE_BIT); -} - -uint8_t ADS1115::reset() -{ - Wire.beginTransmission(0); - Wire.write(0x6); - return Wire.endTransmission(); -} - -bool ADS1115::is_sample_in_progress() -{ - uint16_t val = read_register(ADS1115_REGISTER_CONFIG); - return (val & SAMPLE_BIT) == 0; -} - -int16_t ADS1115::read_sample() -{ - return read_register(ADS1115_REGISTER_CONVERSION); -} - -float ADS1115::sample_to_float(int16_t val) -{ - return val * ranges[m_voltage_range]; -} - -float ADS1115::read_sample_float() -{ - return sample_to_float(read_sample()); -} - -ADS1115 adc; - -void ADS1115_init(void) { - - ads1115_up=0; - if (!i2c_flg) return; - - adc.begin(); - adc.set_data_rate(ADS1115_DATA_RATE_128_SPS); - adc.set_mode(ADS1115_MODE_CONTINUOUS); - adc.set_mux(ADS1115_MUX_DIFF_AIN0_AIN3); - adc.set_pga(ADS1115_PGA_TWO); - - int16_t val = adc.read_sample(); - ads1115_up=1; -} - -#endif - -char sml_start; -uint8_t dump2log=0; - -#define SML_SAVAILABLE Serial_available() -#define SML_SREAD Serial_read() -#define SML_SPEAK Serial_peek() - -bool Serial_available() { - uint8_t num=dump2log&7; - if (num<1 || num>meters_used) num=1; - return meter_ss[num-1]->available(); -} - -uint8_t Serial_read() { - uint8_t num=dump2log&7; - if (num<1 || num>meters_used) num=1; - return meter_ss[num-1]->read(); -} - -uint8_t Serial_peek() { - uint8_t num=dump2log&7; - if (num<1 || num>meters_used) num=1; - return meter_ss[num-1]->peek(); -} - -void Dump2log(void) { - -int16_t index=0,hcnt=0; -uint32_t d_lastms; -uint8_t dchars[16]; - - if (!SML_SAVAILABLE) return; - - if (dump2log&8) { - - while (SML_SAVAILABLE) { - log_data[index]=':'; - index++; - log_data[index]=' '; - index++; - d_lastms=millis(); - while ((millis()-d_lastms)<40) { - if (SML_SAVAILABLE) { - uint8_t c=SML_SREAD; - sprintf(&log_data[index],"%02x ",c); - dchars[hcnt]=c; - index+=3; - hcnt++; - if (hcnt>15) { - - log_data[index]='='; - index++; - log_data[index]='>'; - index++; - log_data[index]=' '; - index++; - for (uint8_t ccnt=0; ccnt<16; ccnt++) { - if (isprint(dchars[ccnt])) { - log_data[index]=dchars[ccnt]; - } else { - log_data[index]=' '; - } - index++; - } - break; - } - } - } - if (index>0) { - log_data[index]=0; - AddLog(LOG_LEVEL_INFO); - index=0; - hcnt=0; - } - } - } else { - - index=0; - log_data[index]=':'; - index++; - log_data[index]=' '; - index++; - d_lastms=millis(); - while ((millis()-d_lastms)<40) { - if (SML_SAVAILABLE) { - if (meter_desc_p[(dump2log&7)-1].type=='o') { - - char c=SML_SREAD&0x7f; - if (c=='\n' || c=='\r') break; - log_data[index]=c; - index++; - } else { - unsigned char c; - if (meter_desc_p[(dump2log&7)-1].type=='e') { - - c=SML_SREAD; - sprintf(&log_data[index],"%02x ",c); - index+=3; - if (c==EBUS_SYNC) break; - } else { - - if (sml_start==0x77) { - sml_start=0; - } else { - c=SML_SPEAK; - if (c==0x77) { - sml_start=c; - break; - } - } - c=SML_SREAD; - sprintf(&log_data[index],"%02x ",c); - index+=3; - } - } - } - } - if (index>0) { - log_data[index]=0; - AddLog(LOG_LEVEL_INFO); - } - } - - -} - - -uint8_t *skip_sml(uint8_t *cp,int16_t *res) { - uint8_t len,len1,type; - len=*cp&0xf; - type=*cp&0x70; - if (type==0x70) { - - - cp++; - while (len--) { - len1=*cp&0x0f; - cp+=len1; - } - *res=0; - } else { - - *res=(signed char)*(cp+1); - cp+=len; - } - return cp; -} - - - -double sml_getvalue(unsigned char *cp,uint8_t index) { -uint8_t len,unit,type; -int16_t scaler,result; -int64_t value; -double dval; - - - - cp=skip_sml(cp,&result); - - cp=skip_sml(cp,&result); - - cp=skip_sml(cp,&result); - - cp=skip_sml(cp,&result); - scaler=result; - - type=*cp&0x70; - len=*cp&0x0f; - cp++; - if (type==0x50 || type==0x60) { - - uint64_t uvalue=0; - uint8_t nlen=len; - while (--nlen) { - uvalue<<=8; - uvalue|=*cp++; - } - if (type==0x50) { - - switch (len-1) { - case 1: - - value=(signed char)uvalue; - break; - case 2: - -#ifdef DWS74_BUG - if (scaler==-2) { - value=(uint32_t)uvalue; - } else { - value=(int16_t)uvalue; - } -#else - value=(int16_t)uvalue; -#endif - break; - case 3: - case 4: - - value=(int32_t)uvalue; - break; - case 5: - case 6: - case 7: - case 8: - - value=(int64_t)uvalue; - break; - } - } else { - - value=uvalue; - } - - } else { - if (!(type&0xf0)) { - - - - if (len==9) { - - cp++; - uint32_t s1,s2; - s1=*cp<<16|*(cp+1)<<8|*(cp+2); - cp+=4; - s2=*cp<<16|*(cp+1)<<8|*(cp+2); - sprintf(&meter_id[index][0],"%u-%u",s1,s2); - } else { - - char *str=&meter_id[index][0]; - for (type=0; type= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; - } - return rVal; -} - -uint8_t sb_counter; - - -double CharToDouble(const char *str) -{ - - char strbuf[24]; - - strlcpy(strbuf, str, sizeof(strbuf)); - char *pt = strbuf; - while ((*pt != '\0') && isblank(*pt)) { pt++; } - - signed char sign = 1; - if (*pt == '-') { sign = -1; } - if (*pt == '-' || *pt=='+') { pt++; } - - double left = 0; - if (*pt != '.') { - left = atoi(pt); - while (isdigit(*pt)) { pt++; } - } - - double right = 0; - if (*pt == '.') { - pt++; - right = atoi(pt); - while (isdigit(*pt)) { - pt++; - right /= 10.0; - } - } - - double result = left + right; - if (sign < 0) { - return -result; - } - return result; -} - - - -void ebus_esc(uint8_t *ebus_buffer, unsigned char len) { - short count,count1; - for (count=0; countavailable()) { - meter_ss[meters]->read(); - } -} - - -void sml_shift_in(uint32_t meters,uint32_t shard) { - uint32_t count; - if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='p') { - - for (count=0; countread(); - - if (meter_desc_p[meters].type=='o') { - smltbuf[meters][SML_BSIZ-1]=iob&0x7f; - } else if (meter_desc_p[meters].type=='s') { - smltbuf[meters][SML_BSIZ-1]=iob; - } else if (meter_desc_p[meters].type=='r') { - smltbuf[meters][SML_BSIZ-1]=iob; - } else if (meter_desc_p[meters].type=='m') { - smltbuf[meters][meter_spos[meters]] = iob; - meter_spos[meters]++; - if (meter_spos[meters]>=9) { - SML_Decode(meters); - sml_empty_receiver(meters); - meter_spos[meters]=0; - } - } else if (meter_desc_p[meters].type=='p') { - smltbuf[meters][meter_spos[meters]] = iob; - meter_spos[meters]++; - if (meter_spos[meters]>=7) { - SML_Decode(meters); - sml_empty_receiver(meters); - meter_spos[meters]=0; - } - } else { - if (iob==EBUS_SYNC) { - - - if (meter_spos[meters]>4+5) { - - uint8_t tlen=smltbuf[meters][4]+5; - - if (smltbuf[meters][tlen]=ebus_CalculateCRC(smltbuf[meters],tlen)) { - ebus_esc(smltbuf[meters],tlen); - SML_Decode(meters); - } else { - - - } - } - meter_spos[meters]=0; - return; - } - smltbuf[meters][meter_spos[meters]] = iob; - meter_spos[meters]++; - if (meter_spos[meters]>=SML_BSIZ) { - meter_spos[meters]=0; - } - } - sb_counter++; - if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='p') SML_Decode(meters); -} - - - -void SML_Poll(void) { -uint32_t meters; - - for (meters=0; metersavailable()) { - sml_shift_in(meters,0); - } - } - } -} - - -void SML_Decode(uint8_t index) { - const char *mp=(const char*)meter_p; - int8_t mindex; - uint8_t *cp; - uint8_t dindex=0,vindex=0; - delay(0); - while (mp != NULL) { - - - - mindex=((*mp)&7)-1; - - if (mindex<0 || mindex>=meters_used) mindex=0; - mp+=2; - if (*mp=='=' && *(mp+1)=='h') { - mp = strchr(mp, '|'); - if (mp) mp++; - continue; - } - - if (index!=mindex) goto nextsect; - - - cp=&smltbuf[mindex][0]; - - - if (*mp=='=') { - - mp++; - - if (*mp=='m' && !sb_counter) { - - - mp++; - while (*mp==' ') mp++; - - double dvar; - uint8_t opr; - uint32_t ind; - ind=atoi(mp); - while (*mp>='0' && *mp<='9') mp++; - if (ind<1 || ind>MAX_VARS) ind=1; - dvar=meter_vars[ind-1]; - for (uint8_t p=0;p<5;p++) { - if (*mp=='@') { - - meter_vars[vindex]=dvar; - mp++; - SML_Immediate_MQTT((const char*)mp,vindex,mindex); - break; - } - opr=*mp; - mp++; - uint8_t iflg=0; - if (*mp=='#') { - iflg=1; - mp++; - } - ind=atoi(mp); - while (*mp>='0' && *mp<='9') mp++; - if (ind<1 || ind>MAX_VARS) ind=1; - switch (opr) { - case '+': - if (iflg) dvar+=ind; - else dvar+=meter_vars[ind-1]; - break; - case '-': - if (iflg) dvar-=ind; - else dvar-=meter_vars[ind-1]; - break; - case '*': - if (iflg) dvar*=ind; - else dvar*=meter_vars[ind-1]; - break; - case '/': - if (iflg) dvar/=ind; - else dvar/=meter_vars[ind-1]; - break; - } - while (*mp==' ') mp++; - if (*mp=='@') { - - meter_vars[vindex]=dvar; - mp++; - SML_Immediate_MQTT((const char*)mp,vindex,mindex); - break; - } - } - } else if (*mp=='d') { - - if (dindex='0' && *mp<='9') mp++; - if (ind<1 || ind>MAX_VARS) ind=1; - uint32_t delay=atoi(mp)*1000; - uint32_t dtime=millis()-dtimes[dindex]; - if (dtime>delay) { - - dtimes[dindex]=millis(); - double vdiff = meter_vars[ind-1]-dvalues[dindex]; - dvalues[dindex]=meter_vars[ind-1]; - meter_vars[vindex]=(double)360000.0*vdiff/((double)dtime/10000.0); - - mp=strchr(mp,'@'); - if (mp) { - mp++; - SML_Immediate_MQTT((const char*)mp,vindex,mindex); - } - } - dindex++; - } - } else if (*mp=='h') { - - mp = strchr(mp, '|'); - if (mp) mp++; - continue; - } - } else { - - uint8_t found=1; - uint32_t ebus_dval=99; - float mbus_dval=99; - while (*mp!='@') { - if (meter_desc_p[mindex].type=='o' || meter_desc_p[mindex].type=='c') { - if (*mp++!=*cp++) { - found=0; - } - } else { - if (meter_desc_p[mindex].type=='s') { - - uint8_t val = hexnibble(*mp++) << 4; - val |= hexnibble(*mp++); - if (val!=*cp++) { - found=0; - } - } else { - - - if (*mp=='x' && *(mp+1)=='x') { - - mp+=2; - cp++; - } else if (!strncmp(mp,"uuuuuuuu",8)) { - uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); - ebus_dval=val; - mbus_dval=val; - mp+=8; - cp+=4; - } - else if (*mp=='u' && *(mp+1)=='u' && *(mp+2)=='u' && *(mp+3)=='u'){ - uint16_t val = cp[0]|(cp[1]<<8); - mbus_dval=val; - ebus_dval=val; - mp+=4; - cp+=2; - } else if (*mp=='u' && *(mp+1)=='u') { - uint8_t val = *cp++; - ebus_dval=val; - mp+=2; - } - else if (*mp=='s' && *(mp+1)=='s' && *(mp+2)=='s' && *(mp+3)=='s') { - int16_t val = *cp|(*(cp+1)<<8); - ebus_dval=val; - mp+=4; - cp+=2; - } - else if (*mp=='s' && *(mp+1)=='s') { - int8_t val = *cp++; - ebus_dval=val; - mp+=2; - } - else if (!strncmp(mp,"ffffffff",8)) { - uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); - float *fp=(float*)&val; - ebus_dval=*fp; - mbus_dval=*fp; - mp+=8; - cp+=4; - } - else if (!strncmp(mp,"FFffFFff",8)) { - - uint32_t val= (cp[1]<<0)|(cp[0]<<8)|(cp[3]<<16)|(cp[2]<<24); - float *fp=(float*)&val; - ebus_dval=*fp; - mbus_dval=*fp; - mp+=8; - cp+=4; - } - else if (!strncmp(mp,"eeeeee",6)) { - uint32_t val=(cp[0]<<16)|(cp[1]<<8)|(cp[2]<<0); - mbus_dval=val; - mp+=6; - cp+=3; - } - else if (!strncmp(mp,"vvvvvv",6)) { - mbus_dval=(float)((cp[0]<<8)|(cp[1])) + ((float)cp[2]/10.0); - mp+=6; - cp+=3; - } - else if (!strncmp(mp,"cccccc",6)) { - mbus_dval=(float)((cp[0]<<8)|(cp[1])) + ((float)cp[2]/100.0); - mp+=6; - cp+=3; - } - else if (!strncmp(mp,"pppp",4)) { - mbus_dval=(float)((cp[0]<<8)|cp[1]); - mp+=4; - cp+=2; - } - else { - uint8_t val = hexnibble(*mp++) << 4; - val |= hexnibble(*mp++); - if (val!=*cp++) { - found=0; - } - } - } - } - } - if (found) { - - mp++; - if (*mp=='#') { - - mp++; - if (meter_desc_p[mindex].type=='o') { - for (uint8_t p=0;p>=shift; - ebus_dval&=1; - mp+=2; - } - if (*mp=='i') { - - mp++; - uint8_t mb_index=strtol((char*)mp,(char**)&mp,10); - if (mb_index!=meter_desc_p[mindex].index) { - goto nextsect; - } - uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],7); - if (lowByte(crc)!=smltbuf[mindex][7]) goto nextsect; - if (highByte(crc)!=smltbuf[mindex][8]) goto nextsect; - dval=mbus_dval; - - mp++; - } else { - if (meter_desc_p[mindex].type=='p') { - uint8_t crc = SML_PzemCrc(&smltbuf[mindex][0],6); - if (crc!=smltbuf[mindex][6]) goto nextsect; - dval=mbus_dval; - } else { - dval=ebus_dval; - } - } - - } -#ifdef USE_SML_MEDIAN_FILTER - if (meter_desc_p[mindex].flag&16) { - meter_vars[vindex]=sml_median(&sml_mf[vindex],dval); - } else { - meter_vars[vindex]=dval; - } -#else - meter_vars[vindex]=dval; -#endif - - - double fac=CharToDouble((char*)mp); - meter_vars[vindex]/=fac; - SML_Immediate_MQTT((const char*)mp,vindex,mindex); - } - } - } -nextsect: - - if (vindex=meters_used) lastmind=0; - while (mp != NULL) { - - mindex=((*mp)&7)-1; - if (mindex<0 || mindex>=meters_used) mindex=0; - mp+=2; - if (*mp=='=' && *(mp+1)=='h') { - mp+=2; - - if (json) { - mp = strchr(mp, '|'); - if (mp) mp++; - continue; - } - - uint8_t i; - for (i=0;isml_counters[index].sml_debounce) { - RtcSettings.pulse_counter[index]++; - InjektCounterValue(sml_counters[index].sml_cnt_old_state,RtcSettings.pulse_counter[index]); - } -} - -void SML_CounterUpd1(void) { - SML_CounterUpd(0); -} - -void SML_CounterUpd2(void) { - SML_CounterUpd(1); -} - -void SML_CounterUpd3(void) { - SML_CounterUpd(2); -} - -void SML_CounterUpd4(void) { - SML_CounterUpd(3); -} - -#ifdef USE_SCRIPT -struct METER_DESC script_meter_desc[MAX_METERS]; -uint8_t *script_meter; -#endif - -#define METER_DEF_SIZE 2000 - -bool Gpio_used(uint8_t gpiopin) { - for (uint16_t i=0;iM",-2,0); - if (meter_script==99) { - - if (script_meter) free(script_meter); - script_meter=0; - uint8_t *tp=0; - uint16_t index=0; - uint8_t section=0; - uint8_t srcpin=0; - char *lp=glob_script_mem.scriptptr; - sml_send_blocks=0; - while (lp) { - if (!section) { - if (*lp=='>' && *(lp+1)=='M') { - lp+=2; - meters_used=strtol(lp,0,10); - section=1; - uint32_t mlen=0; - for (uint32_t cnt=0;cnt') { - if (*(tp-1)=='|') *(tp-1)=0; - break; - } - if (*lp=='+') { - - - lp++; - index=*lp&7; - lp+=2; - if (index<1 || index>meters_used) goto next_line; - index--; - srcpin=strtol(lp,&lp,10); - if (Gpio_used(srcpin)) { - AddLog_P(LOG_LEVEL_INFO, PSTR("gpio rx double define!")); -dddef_exit: - if (script_meter) free(script_meter); - script_meter=0; - meters_used=METERS_USED; - goto init10; - } - script_meter_desc[index].srcpin=srcpin; - if (*lp!=',') goto next_line; - lp++; - script_meter_desc[index].type=*lp; - lp+=2; - script_meter_desc[index].flag=strtol(lp,&lp,10); - if (*lp!=',') goto next_line; - lp++; - script_meter_desc[index].params=strtol(lp,&lp,10); - if (*lp!=',') goto next_line; - lp++; - script_meter_desc[index].prefix[7]=0; - for (uint32_t cnt=0; cnt<8; cnt++) { - if (*lp==SCRIPT_EOL || *lp==',') { - script_meter_desc[index].prefix[cnt]=0; - break; - } - script_meter_desc[index].prefix[cnt]=*lp++; - } - if (*lp==',') { - lp++; - script_meter_desc[index].trxpin=strtol(lp,&lp,10); - if (Gpio_used(script_meter_desc[index].trxpin)) { - AddLog_P(LOG_LEVEL_INFO, PSTR("gpio tx double define!")); - goto dddef_exit; - } - if (*lp!=',') goto next_line; - lp++; - script_meter_desc[index].tsecs=strtol(lp,&lp,10); - if (*lp==',') { - lp++; - char txbuff[256]; - uint32_t txlen=0,tx_entries=1; - for (uint32_t cnt=0; cntmeters_used) goto next_line; - while (1) { - if (*lp==SCRIPT_EOL) { - if (*(tp-1)!='|') *tp++='|'; - goto next_line; - } - *tp++=*lp++; - index++; - if (index>=METER_DEF_SIZE) break; - } - } - - } - -next_line: - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } - *tp=0; - meter_desc_p=script_meter_desc; - meter_p=script_meter; - } -#endif - -init10: - typedef void (*function)(); - function counter_callbacks[] = {SML_CounterUpd1,SML_CounterUpd2,SML_CounterUpd3,SML_CounterUpd4}; - uint8_t cindex=0; - - for (byte i = 0; i < MAX_COUNTERS; i++) { - RtcSettings.pulse_counter[i]=Settings.pulse_counter[i]; - sml_counters[i].sml_cnt_last_ts=millis(); - } - for (uint8_t meters=0; metersbegin(meter_desc_p[meters].params)) { - meter_ss[meters]->flush(); - } - if (meter_ss[meters]->hardwareSerial()) { ClaimSerial(); } - - } - } - -} - - -void SetDBGLed(uint8_t srcpin, uint8_t ledpin) { - pinMode(ledpin, OUTPUT); - if (digitalRead(srcpin)) { - digitalWrite(ledpin,LOW); - } else { - digitalWrite(ledpin,HIGH); - } -} - - -void SML_Counter_Poll(void) { -uint16_t meters,cindex=0; -uint32_t ctime=millis(); - - for (meters=0; meters0) { - if (ctime-sml_counters[cindex].sml_cnt_last_ts>meter_desc_p[meters].params) { - sml_counters[cindex].sml_cnt_last_ts=ctime; - - if (meter_desc_p[meters].flag&2) { - -#ifdef ANALOG_OPTO_SENSOR - if (ads1115_up) { - int16_t val = adc.read_sample(); - if (val>sml_counters[cindex].ana_max) sml_counters[cindex].ana_max=val; - if (val10) { - sml_counters[cindex].sml_cnt_last_ts=ctime; -#ifdef DEBUG_CNT_LED1 - if (cindex==0) SetDBGLed(meter_desc_p[meters].srcpin,DEBUG_CNT_LED1); -#endif -#ifdef DEBUG_CNT_LED2 - if (cindex==1) SetDBGLed(meter_desc_p[meters].srcpin,DEBUG_CNT_LED2); -#endif - } - } - cindex++; - } - } -} - -#ifdef USE_SCRIPT -char *SML_Get_Sequence(char *cp,uint32_t index) { - if (!index) return cp; - uint32_t cindex=0; - while (cp) { - cp=strchr(cp,','); - if (cp) { - cp++; - cindex++; - if (cindex==index) { - return cp; - } - } - } -} - -void SML_Check_Send(void) { - sml_100ms_cnt++; - char *cp; - for (uint32_t cnt=sml_desc_cnt; cnt=0 && script_meter_desc[cnt].txmem) { - if ((sml_100ms_cnt%script_meter_desc[cnt].tsecs)==0) { - if (script_meter_desc[cnt].max_index>1) { - script_meter_desc[cnt].index++; - if (script_meter_desc[cnt].index>=script_meter_desc[cnt].max_index) { - script_meter_desc[cnt].index=0; - sml_desc_cnt++; - } - cp=SML_Get_Sequence(script_meter_desc[cnt].txmem,script_meter_desc[cnt].index); - - } else { - cp=script_meter_desc[cnt].txmem; - - sml_desc_cnt++; - } - - SML_Send_Seq(cnt,cp); - if (sml_desc_cnt>=meters_used) { - sml_desc_cnt=0; - } - break; - } - } else { - sml_desc_cnt++; - } - - if (sml_desc_cnt>=meters_used) { - sml_desc_cnt=0; - } - } -} - -uint8_t sml_hexnibble(char chr) { - uint8_t rVal = 0; - if (isdigit(chr)) { - rVal = chr - '0'; - } else { - if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; - if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; - } - return rVal; -} - - -void SML_Send_Seq(uint32_t meter,char *seq) { - uint8_t sbuff[32]; - uint8_t *ucp=sbuff,slen=0; - char *cp=seq; - while (*cp) { - if (!*cp || !*(cp+1)) break; - if (*cp==',') break; - uint8_t iob=(sml_hexnibble(*cp) << 4) | sml_hexnibble(*(cp+1)); - cp+=2; - *ucp++=iob; - slen++; - if (slen>=sizeof(sbuff)) break; - } - if (script_meter_desc[meter].type=='m') { - *ucp++=0; - *ucp++=2; - - uint16_t crc = MBUS_calculateCRC(sbuff,6); - *ucp++=lowByte(crc); - *ucp++=highByte(crc); - slen+=4; - } - if (script_meter_desc[meter].type=='p') { - *ucp++=0xc0; - *ucp++=0xa8; - *ucp++=1; - *ucp++=1; - *ucp++=0; - *ucp++=SML_PzemCrc(sbuff,6); - slen+=6; - } - meter_ss[meter]->write(sbuff,slen); -} -#endif - -uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num) { - uint16_t crc, flag; - crc = 0xFFFF; - for (uint32_t i = 0; i < num; i++) { - crc ^= frame[i]; - for (uint32_t j = 8; j; j--) { - if ((crc & 0x0001) != 0) { - crc >>= 1; - crc ^= 0xA001; - } else { - crc >>= 1; - } - } - } - return crc; -} - -uint8_t SML_PzemCrc(uint8_t *data, uint8_t len) { - uint16_t crc = 0; - for (uint32_t i = 0; i < len; i++) crc += *data++; - return (uint8_t)(crc & 0xFF); -} -# 2277 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_53_sml.ino" -bool XSNS_53_cmd(void) { - bool serviced = true; - if (XdrvMailbox.data_len > 0) { - char *cp=XdrvMailbox.data; - if (*cp=='d') { - - cp++; - dump2log=atoi(cp); - ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"dump: %d\"}}"),dump2log); - } else if (*cp=='c') { - - cp++; - uint8_t index=*cp&7; - if (index<1 || index>MAX_COUNTERS) index=1; - cp++; - while (*cp==' ') cp++; - if (isdigit(*cp)) { - uint32_t cval=atoi(cp); - while (isdigit(*cp)) cp++; - RtcSettings.pulse_counter[index-1]=cval; - uint8_t cindex=0; - for (uint8_t meters=0; metersaddress, INA226_REG_CALIBRATION, si->calibrationValue); - -} - - - - - - -bool Ina226TestPresence(uint8_t device) -{ - - - - uint16_t config = I2cRead16( slaveInfo[device].address, INA226_REG_CONFIG ); - - - if (config != slaveInfo[device].config) - return false; - - return true; - -} - - - - - - -void Ina226Init() -{ - - - uint32_t i; - - slavesFound = 0; - - Ina226SlaveInfo_t *p = slaveInfo; - - - - AddLog_P2( LOG_LEVEL_NONE, "Size of Settings: %d bytes", sizeof(Settings)); - - if (!i2c_flg) - AddLog_P2(LOG_LEVEL_DEBUG, "INA226: Initialization failed: No I2C support"); - - - - - for (i = 0; i < 4; i++){ - *p = {0}; - } - - - - - - for (i = 0; (i < INA226_MAX_ADDRESSES); i++){ - uint8_t addr = pgm_read_byte(probeAddresses + i); - - - - - if (!Settings.ina226_i_fs[i]) - continue; - - - - - - - if (!I2cWrite16( addr, INA226_REG_CONFIG, INA226_CONFIG_RESET)){ - - AddLog_P2( LOG_LEVEL_DEBUG, "No INA226 at address: %02X", addr); - continue; - } - - - - uint16_t config = I2cRead16( addr, INA226_REG_CONFIG ); - - - if (INA226_RES_CONFIG != config) - continue; - - - config = INA226_DEF_CONFIG; - - - if (!I2cWrite16( addr, INA226_REG_CONFIG, config)) - continue; - - - - p = &slaveInfo[i]; - - p->address = addr; - - p->config = config; - - - p->i_lsb = (((float) Settings.ina226_i_fs[i])/10.0f)/32768.0f; - - - - uint32_t r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[i]); - - - - p->calibrationValue = ((uint16_t) (0.00512/(p->i_lsb * r_shunt_uohms/1000000.0f))); - - p->present = true; - - - Ina226SetCalibration(i); - - - slavesFound++; - - } -} - - - - - -float Ina226ReadBus_v(uint8_t device) -{ - uint8_t addr = slaveInfo[device].address; - int16_t reg_bus_v = I2cReadS16( addr, INA226_REG_BUSVOLTAGE); - - float result = ((float) reg_bus_v) * 0.00125f; - - return result; - -} - - - - - -float Ina226ReadShunt_i(uint8_t device) -{ - uint8_t addr = slaveInfo[device].address; - int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_CURRENT); - - float result = ((float) reg_shunt_i) * slaveInfo[device].i_lsb; - - return result; -} - - - - - -float Ina226ReadPower_w(uint8_t device) -{ - uint8_t addr = slaveInfo[device].address; - int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_POWER); - - float result = ((float) reg_shunt_i) * (slaveInfo[device].i_lsb * 25.0); - - return result; -} - - - - - - -void Ina226Read(uint8_t device) -{ - - voltages[device] = Ina226ReadBus_v(device); - currents[device] = Ina226ReadShunt_i(device); - powers[device] = Ina226ReadPower_w(device); - - - - -} - - - - - -void Ina226EverySecond() -{ - - for (uint8_t device = 0; device < INA226_MAX_ADDRESSES; device++){ - - if (slavesFound && slaveInfo[device].present && Ina226TestPresence(device)){ - Ina226Read(device); - } - else { - powers[device] = currents[device] = voltages[device] = 0.0f; - - - - - - - slaveInfo[device].present = false; - } - } -} - - - - - -bool Ina226CommandSensor() -{ - bool serviced = true; - bool show_config = false; - char param_str[64]; - char *cp, *params[4]; - uint8_t i, param_count, device, p1 = XdrvMailbox.payload; - uint32_t r_shunt_uohms; - uint16_t compact_r_shunt_uohms; - - - - - - if (XdrvMailbox.data_len > 62){ - return false; - } - - strncpy(param_str, XdrvMailbox.data, XdrvMailbox.data_len + 1); - param_str[XdrvMailbox.data_len] = 0; - - - for (cp = param_str, i = 0, param_count = 0; *cp && (i < XdrvMailbox.data_len + 1) && (param_count <= 3); i++) - if (param_str[i] == ' ' || param_str[i] == ',' || param_str[i] == 0){ - param_str[i] = 0; - params[param_count] = cp; - - param_count++; - cp = param_str + i + 1; - } - - - if (p1 < 10 || p1 >= 50){ - - switch (p1){ - case 1: - Ina226Init(); - Response_P(PSTR("{\"Sensor54-Command-Result\":{\"SlavesFound\":%d}}"),slavesFound); - break; - - case 2: - restart_flag = 2; - Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Restart_flag\":%d}}"),restart_flag); - break; - - default: - serviced = false; - } - } - else if (p1 < 50){ - - device = (p1 / 10) - 1; - switch (p1 % 10){ - case 0: - show_config = true; - break; - - case 1: - r_shunt_uohms = (uint32_t) ((CharToFloat(params[1])) * 1000000.0f); - - - - if (r_shunt_uohms > 32767){ - uint32_t r_shunt_mohms = r_shunt_uohms/1000UL; - Settings.ina226_r_shunt[device] = (uint16_t) (r_shunt_mohms | 0x8000); - } - else - Settings.ina226_r_shunt[device] = (uint16_t) r_shunt_uohms; - - - show_config = true; - break; - - case 2: - Settings.ina226_i_fs[device] = (uint16_t) ((CharToFloat(params[1])) * 10.0f); - - show_config = true; - break; - - - default: - serviced = false; - break; - } - } - else - serviced = false; - - if (show_config) { - char shunt_r_str[16]; - char fs_i_str[16]; - - - r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[device]); - dtostrfd(((float)r_shunt_uohms)/1000000.0f, 6, shunt_r_str); - - dtostrfd(((float)Settings.ina226_i_fs[device])/10.0f, 1, fs_i_str); - - Response_P(PSTR("{\"Sensor54-device-settings-%d\":{\"SHUNT_R\":%s,\"FS_I\":%s}}"), - device + 1, shunt_r_str, fs_i_str); - } - - return serviced; -} - - - - - -#ifdef USE_WEBSERVER -const char HTTP_SNS_INA226_DATA[] PROGMEM = - "{s}%s " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}%s " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}%s " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; -#endif - -void Ina226Show(bool json) -{ - int i, num_found; - for (num_found = 0, i = 0; i < INA226_MAX_ADDRESSES; i++) { - - if (!slaveInfo[i].present) - continue; - - num_found++; - - char voltage[16]; - dtostrfd(voltages[i], Settings.flag2.voltage_resolution, voltage); - char current[16]; - dtostrfd(currents[i], Settings.flag2.current_resolution, current); - char power[16]; - dtostrfd(powers[i], Settings.flag2.wattage_resolution, power); - char name[16]; - snprintf_P(name, sizeof(name), PSTR("INA226%c%d"),IndexSeparator(), i + 1); - - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%02x,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), - name, i, voltage, current, power); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_VOLTAGE, voltage); - DomoticzSensor(DZ_CURRENT, current); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_INA226_DATA, name, voltage, name, current, name, power); -#endif - } - - } - -} -# 532 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_54_ina226.ino" -bool Xsns54(byte callback_id) { - - - bool result = false; - - - if(i2c_flg) { - - - switch (callback_id) { - case FUNC_EVERY_SECOND: - Ina226EverySecond(); - break; - case FUNC_INIT: - Ina226Init(); - break; - case FUNC_JSON_APPEND: - Ina226Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ina226Show(0); - break; -#endif - case FUNC_COMMAND_SENSOR: - if (XSNS_54 == XdrvMailbox.index) { - result = Ina226CommandSensor(); - } - break; - } - } - - return result; -} - -#endif -#endif -# 1 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_interface.ino" -# 20 "/Users/gerhardmutz1/Desktop/Smart-Home/Tasmota/Development/Sonoff-Tasmota/sonoff/xsns_interface.ino" -#ifdef XFUNC_PTR_IN_ROM -bool (* const xsns_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xsns_func_ptr[])(uint8_t) = { -#endif - -#ifdef XSNS_01 - &Xsns01, -#endif - -#ifdef XSNS_02 - &Xsns02, -#endif - -#ifdef XSNS_03 - &Xsns03, -#endif - -#ifdef XSNS_04 - &Xsns04, -#endif - -#ifdef XSNS_05 - &Xsns05, -#endif - -#ifdef XSNS_06 - &Xsns06, -#endif - -#ifdef XSNS_07 - &Xsns07, -#endif - -#ifdef XSNS_08 - &Xsns08, -#endif - -#ifdef XSNS_09 - &Xsns09, -#endif - -#ifdef XSNS_10 - &Xsns10, -#endif - -#ifdef XSNS_11 - &Xsns11, -#endif - -#ifdef XSNS_12 - &Xsns12, -#endif - -#ifdef XSNS_13 - &Xsns13, -#endif - -#ifdef XSNS_14 - &Xsns14, -#endif - -#ifdef XSNS_15 - &Xsns15, -#endif - -#ifdef XSNS_16 - &Xsns16, -#endif - -#ifdef XSNS_17 - &Xsns17, -#endif - -#ifdef XSNS_18 - &Xsns18, -#endif - -#ifdef XSNS_19 - &Xsns19, -#endif - -#ifdef XSNS_20 - &Xsns20, -#endif - -#ifdef XSNS_21 - &Xsns21, -#endif - -#ifdef XSNS_22 - &Xsns22, -#endif - -#ifdef XSNS_23 - &Xsns23, -#endif - -#ifdef XSNS_24 - &Xsns24, -#endif - -#ifdef XSNS_25 - &Xsns25, -#endif - -#ifdef XSNS_26 - &Xsns26, -#endif - -#ifdef XSNS_27 - &Xsns27, -#endif - -#ifdef XSNS_28 - &Xsns28, -#endif - -#ifdef XSNS_29 - &Xsns29, -#endif - -#ifdef XSNS_30 - &Xsns30, -#endif - -#ifdef XSNS_31 - &Xsns31, -#endif - -#ifdef XSNS_32 - &Xsns32, -#endif - -#ifdef XSNS_33 - &Xsns33, -#endif - -#ifdef XSNS_34 - &Xsns34, -#endif - -#ifdef XSNS_35 - &Xsns35, -#endif - -#ifdef XSNS_36 - &Xsns36, -#endif - -#ifdef XSNS_37 - &Xsns37, -#endif - -#ifdef XSNS_38 - &Xsns38, -#endif - -#ifdef XSNS_39 - &Xsns39, -#endif - -#ifdef XSNS_40 - &Xsns40, -#endif - -#ifdef XSNS_41 - &Xsns41, -#endif - -#ifdef XSNS_42 - &Xsns42, -#endif - -#ifdef XSNS_43 - &Xsns43, -#endif - -#ifdef XSNS_44 - &Xsns44, -#endif - -#ifdef XSNS_45 - &Xsns45, -#endif - -#ifdef XSNS_46 - &Xsns46, -#endif - -#ifdef XSNS_47 - &Xsns47, -#endif - -#ifdef XSNS_48 - &Xsns48, -#endif - -#ifdef XSNS_49 - &Xsns49, -#endif - -#ifdef XSNS_50 - &Xsns50, -#endif - -#ifdef XSNS_51 - &Xsns51, -#endif - -#ifdef XSNS_52 - &Xsns52, -#endif - -#ifdef XSNS_53 - &Xsns53, -#endif - -#ifdef XSNS_54 - &Xsns54, -#endif - -#ifdef XSNS_55 - &Xsns55, -#endif - -#ifdef XSNS_56 - &Xsns56, -#endif - -#ifdef XSNS_57 - &Xsns57, -#endif - -#ifdef XSNS_58 - &Xsns58, -#endif - -#ifdef XSNS_59 - &Xsns59, -#endif - -#ifdef XSNS_60 - &Xsns60, -#endif - -#ifdef XSNS_61 - &Xsns61, -#endif - -#ifdef XSNS_62 - &Xsns62, -#endif - -#ifdef XSNS_63 - &Xsns63, -#endif - -#ifdef XSNS_64 - &Xsns64, -#endif - -#ifdef XSNS_65 - &Xsns65, -#endif - -#ifdef XSNS_66 - &Xsns66, -#endif - -#ifdef XSNS_67 - &Xsns67, -#endif - -#ifdef XSNS_68 - &Xsns68, -#endif - -#ifdef XSNS_69 - &Xsns69, -#endif - -#ifdef XSNS_70 - &Xsns70, -#endif - -#ifdef XSNS_71 - &Xsns71, -#endif - -#ifdef XSNS_72 - &Xsns72, -#endif - -#ifdef XSNS_73 - &Xsns73, -#endif - -#ifdef XSNS_74 - &Xsns74, -#endif - -#ifdef XSNS_75 - &Xsns75, -#endif - -#ifdef XSNS_76 - &Xsns76, -#endif - -#ifdef XSNS_77 - &Xsns77, -#endif - -#ifdef XSNS_78 - &Xsns78, -#endif - -#ifdef XSNS_79 - &Xsns79, -#endif - -#ifdef XSNS_80 - &Xsns80, -#endif - -#ifdef XSNS_81 - &Xsns81, -#endif - -#ifdef XSNS_82 - &Xsns82, -#endif - -#ifdef XSNS_83 - &Xsns83, -#endif - -#ifdef XSNS_84 - &Xsns84, -#endif - -#ifdef XSNS_85 - &Xsns85, -#endif - -#ifdef XSNS_86 - &Xsns86, -#endif - -#ifdef XSNS_87 - &Xsns87, -#endif - -#ifdef XSNS_88 - &Xsns88, -#endif - -#ifdef XSNS_89 - &Xsns89, -#endif - -#ifdef XSNS_90 - &Xsns90, -#endif - -#ifdef XSNS_91 - &Xsns91, -#endif - -#ifdef XSNS_92 - &Xsns92, -#endif - -#ifdef XSNS_93 - &Xsns93, -#endif - -#ifdef XSNS_94 - &Xsns94, -#endif - -#ifdef XSNS_95 - &Xsns95, -#endif - -#ifdef XSNS_96 - &Xsns96, -#endif - -#ifdef XSNS_97 - &Xsns97, -#endif - -#ifdef XSNS_98 - &Xsns98, -#endif - -#ifdef XSNS_99 - &Xsns99 -#endif -}; - -const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); - - - - - -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kXsnsList[] PROGMEM = { -#else -const uint8_t kXsnsList[] = { -#endif - -#ifdef XSNS_01 - XSNS_01, -#endif - -#ifdef XSNS_02 - XSNS_02, -#endif - -#ifdef XSNS_03 - XSNS_03, -#endif - -#ifdef XSNS_04 - XSNS_04, -#endif - -#ifdef XSNS_05 - XSNS_05, -#endif - -#ifdef XSNS_06 - XSNS_06, -#endif - -#ifdef XSNS_07 - XSNS_07, -#endif - -#ifdef XSNS_08 - XSNS_08, -#endif - -#ifdef XSNS_09 - XSNS_09, -#endif - -#ifdef XSNS_10 - XSNS_10, -#endif - -#ifdef XSNS_11 - XSNS_11, -#endif - -#ifdef XSNS_12 - XSNS_12, -#endif - -#ifdef XSNS_13 - XSNS_13, -#endif - -#ifdef XSNS_14 - XSNS_14, -#endif - -#ifdef XSNS_15 - XSNS_15, -#endif - -#ifdef XSNS_16 - XSNS_16, -#endif - -#ifdef XSNS_17 - XSNS_17, -#endif - -#ifdef XSNS_18 - XSNS_18, -#endif - -#ifdef XSNS_19 - XSNS_19, -#endif - -#ifdef XSNS_20 - XSNS_20, -#endif - -#ifdef XSNS_21 - XSNS_21, -#endif - -#ifdef XSNS_22 - XSNS_22, -#endif - -#ifdef XSNS_23 - XSNS_23, -#endif - -#ifdef XSNS_24 - XSNS_24, -#endif - -#ifdef XSNS_25 - XSNS_25, -#endif - -#ifdef XSNS_26 - XSNS_26, -#endif - -#ifdef XSNS_27 - XSNS_27, -#endif - -#ifdef XSNS_28 - XSNS_28, -#endif - -#ifdef XSNS_29 - XSNS_29, -#endif - -#ifdef XSNS_30 - XSNS_30, -#endif - -#ifdef XSNS_31 - XSNS_31, -#endif - -#ifdef XSNS_32 - XSNS_32, -#endif - -#ifdef XSNS_33 - XSNS_33, -#endif - -#ifdef XSNS_34 - XSNS_34, -#endif - -#ifdef XSNS_35 - XSNS_35, -#endif - -#ifdef XSNS_36 - XSNS_36, -#endif - -#ifdef XSNS_37 - XSNS_37, -#endif - -#ifdef XSNS_38 - XSNS_38, -#endif - -#ifdef XSNS_39 - XSNS_39, -#endif - -#ifdef XSNS_40 - XSNS_40, -#endif - -#ifdef XSNS_41 - XSNS_41, -#endif - -#ifdef XSNS_42 - XSNS_42, -#endif - -#ifdef XSNS_43 - XSNS_43, -#endif - -#ifdef XSNS_44 - XSNS_44, -#endif - -#ifdef XSNS_45 - XSNS_45, -#endif - -#ifdef XSNS_46 - XSNS_46, -#endif - -#ifdef XSNS_47 - XSNS_47, -#endif - -#ifdef XSNS_48 - XSNS_48, -#endif - -#ifdef XSNS_49 - XSNS_49, -#endif - -#ifdef XSNS_50 - XSNS_50, -#endif - -#ifdef XSNS_51 - XSNS_51, -#endif - -#ifdef XSNS_52 - XSNS_52, -#endif - -#ifdef XSNS_53 - XSNS_53, -#endif - -#ifdef XSNS_54 - XSNS_54, -#endif - -#ifdef XSNS_55 - XSNS_55, -#endif - -#ifdef XSNS_56 - XSNS_56, -#endif - -#ifdef XSNS_57 - XSNS_57, -#endif - -#ifdef XSNS_58 - XSNS_58, -#endif - -#ifdef XSNS_59 - XSNS_59, -#endif - -#ifdef XSNS_60 - XSNS_60, -#endif - -#ifdef XSNS_61 - XSNS_61, -#endif - -#ifdef XSNS_62 - XSNS_62, -#endif - -#ifdef XSNS_63 - XSNS_63, -#endif - -#ifdef XSNS_64 - XSNS_64, -#endif - -#ifdef XSNS_65 - XSNS_65, -#endif - -#ifdef XSNS_66 - XSNS_66, -#endif - -#ifdef XSNS_67 - XSNS_67, -#endif - -#ifdef XSNS_68 - XSNS_68, -#endif - -#ifdef XSNS_69 - XSNS_69, -#endif - -#ifdef XSNS_70 - XSNS_70, -#endif - -#ifdef XSNS_71 - XSNS_71, -#endif - -#ifdef XSNS_72 - XSNS_72, -#endif - -#ifdef XSNS_73 - XSNS_73, -#endif - -#ifdef XSNS_74 - XSNS_74, -#endif - -#ifdef XSNS_75 - XSNS_75, -#endif - -#ifdef XSNS_76 - XSNS_76, -#endif - -#ifdef XSNS_77 - XSNS_77, -#endif - -#ifdef XSNS_78 - XSNS_78, -#endif - -#ifdef XSNS_79 - XSNS_79, -#endif - -#ifdef XSNS_80 - XSNS_80, -#endif - -#ifdef XSNS_81 - XSNS_81, -#endif - -#ifdef XSNS_82 - XSNS_82, -#endif - -#ifdef XSNS_83 - XSNS_83, -#endif - -#ifdef XSNS_84 - XSNS_84, -#endif - -#ifdef XSNS_85 - XSNS_85, -#endif - -#ifdef XSNS_86 - XSNS_86, -#endif - -#ifdef XSNS_87 - XSNS_87, -#endif - -#ifdef XSNS_88 - XSNS_88, -#endif - -#ifdef XSNS_89 - XSNS_89, -#endif - -#ifdef XSNS_90 - XSNS_90, -#endif - -#ifdef XSNS_91 - XSNS_91, -#endif - -#ifdef XSNS_92 - XSNS_92, -#endif - -#ifdef XSNS_93 - XSNS_93, -#endif - -#ifdef XSNS_94 - XSNS_94, -#endif - -#ifdef XSNS_95 - XSNS_95, -#endif - -#ifdef XSNS_96 - XSNS_96, -#endif - -#ifdef XSNS_97 - XSNS_97, -#endif - -#ifdef XSNS_98 - XSNS_98, -#endif - -#ifdef XSNS_99 - XSNS_99 -#endif -}; - - - -bool XsnsEnabled(uint32_t sns_index) -{ - if (sns_index < sizeof(kXsnsList)) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t index = pgm_read_byte(kXsnsList + sns_index); -#else - uint32_t index = kXsnsList[sns_index]; -#endif - return bitRead(Settings.sensors[index / 32], index % 32); - } - return true; -} - -void XsnsSensorState(void) -{ - ResponseAppend_P(PSTR("\"")); - for (uint32_t i = 0; i < sizeof(kXsnsList); i++) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t sensorid = pgm_read_byte(kXsnsList + i); -#else - uint32_t sensorid = kXsnsList[i]; -#endif - bool disabled = false; - if (sensorid < MAX_XSNS_DRIVERS) { - disabled = !bitRead(Settings.sensors[sensorid / 32], sensorid % 32); - } - ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (disabled) ? "!" : "", sensorid); - } - ResponseAppend_P(PSTR("\"")); -} - - - - - -bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index) -{ - xsns_index++; - if (xsns_index == xsns_present) { xsns_index = 0; } - -#ifndef USE_DEBUG_DRIVER - if (FUNC_WEB_SENSOR == Function) { -#endif - uint32_t max_disabled = xsns_present; - while (!XsnsEnabled(xsns_index) && max_disabled--) { - xsns_index++; - if (xsns_index == xsns_present) { xsns_index = 0; } - } -#ifndef USE_DEBUG_DRIVER - } -#endif - - return xsns_func_ptr[xsns_index](Function); -} - -bool XsnsCall(uint8_t Function) -{ - bool result = false; - -#ifdef PROFILE_XSNS_EVERY_SECOND - uint32_t profile_start_millis = millis(); -#endif - - for (uint32_t x = 0; x < xsns_present; x++) { -#ifdef USE_DEBUG_DRIVER - if (XsnsEnabled(x)) { -#endif - - if ((FUNC_WEB_SENSOR == Function) && !XsnsEnabled(x)) { continue; } - -#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND - uint32_t profile_start_millis = millis(); -#endif - result = xsns_func_ptr[x](Function); - -#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND - uint32_t profile_millis = millis() - profile_start_millis; - if (profile_millis) { - if (FUNC_EVERY_SECOND == Function) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), uptime, Function, x, profile_millis); - } - } -#endif - - if (result && ((FUNC_COMMAND == Function) || - (FUNC_PIN_STATE == Function) || - (FUNC_COMMAND_SENSOR == Function) - )) { - break; - } -#ifdef USE_DEBUG_DRIVER - } -#endif - } - -#ifdef PROFILE_XSNS_EVERY_SECOND - uint32_t profile_millis = millis() - profile_start_millis; - if (profile_millis) { - if (FUNC_EVERY_SECOND == Function) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d took %u mS"), uptime, Function, profile_millis); - } - } -#endif - - return result; -} \ No newline at end of file From 56c3de022ba9598dfbbdcad2e0bec2072a4f3a5b Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 24 Sep 2019 08:32:55 +0200 Subject: [PATCH 1981/2222] Update xdrv_01_webserver.ino --- sonoff/xdrv_01_webserver.ino | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 2ae92dd50..e65e9f53b 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -91,6 +91,8 @@ const char HTTP_SCRIPT_COUNTER[] PROGMEM = "}" "wl(u);"; + +#ifdef USE_SCRIPT_WEB_DISPLAY const char HTTP_SCRIPT_ROOT[] PROGMEM = "var rfsh=1;" "function la(p){" @@ -113,7 +115,6 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "lt=setTimeout(la,%d);" // Settings.web_refresh "}" "}" -#ifdef USE_SCRIPT_WEB_DISPLAY "function seva(par,ivar){" "la('&sv='+ivar+'_'+par);" "}" @@ -131,7 +132,27 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "rfsh=0;" "}" "}" -#endif +#else // USE_SCRIPT_WEB_DISPLAY +const char HTTP_SCRIPT_ROOT[] PROGMEM = + "function la(p){" + "var a='';" + "if(la.arguments.length==1){" + "a=p;" + "clearTimeout(lt);" + "}" + "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1) + "x=new XMLHttpRequest();" + "x.onreadystatechange=function(){" + "if(x.readyState==4&&x.status==200){" + "var s=x.responseText.replace(/{t}/g,\"\").replace(/{s}/g,\"\").replace(/{c}/g,\"%%'>
hasArg("m") + "x.send();" + "lt=setTimeout(la,%d);" // Settings.web_refresh + "}" +#endif // USE_SCRIPT_WEB_DISPLAY #ifdef USE_JAVASCRIPT_ES6 From 31a269a82fc77402f7c810819521497fff6b0027 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 24 Sep 2019 08:43:13 +0200 Subject: [PATCH 1982/2222] Update xdrv_01_webserver.ino --- sonoff/xdrv_01_webserver.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index e65e9f53b..c85c6a252 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -92,8 +92,8 @@ const char HTTP_SCRIPT_COUNTER[] PROGMEM = "wl(u);"; -#ifdef USE_SCRIPT_WEB_DISPLAY const char HTTP_SCRIPT_ROOT[] PROGMEM = +#ifdef USE_SCRIPT_WEB_DISPLAY "var rfsh=1;" "function la(p){" "var a='';" @@ -133,7 +133,6 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "}" "}" #else // USE_SCRIPT_WEB_DISPLAY -const char HTTP_SCRIPT_ROOT[] PROGMEM = "function la(p){" "var a='';" "if(la.arguments.length==1){" From 854b60ac7aa02e0d5cc5fee4fca71fe65cb21320 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 24 Sep 2019 08:51:09 +0200 Subject: [PATCH 1983/2222] Update support_command.ino --- sonoff/support_command.ino | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index fff2831cb..809b3e154 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -185,6 +185,16 @@ void CommandHandler(char* topic, uint8_t* data, uint32_t data_len) XdrvMailbox.topic = type; XdrvMailbox.data = dataBuf; +#ifdef USE_SCRIPT_SUB_COMMAND + // allow overwrite tasmota cmds + if (!XdrvCall(FUNC_COMMAND)) { + if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { + if (!XsnsCall(FUNC_COMMAND)) { + type = nullptr; // Unknown command + } + } + } +#else if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { if (!XdrvCall(FUNC_COMMAND)) { if (!XsnsCall(FUNC_COMMAND)) { @@ -192,6 +202,8 @@ void CommandHandler(char* topic, uint8_t* data, uint32_t data_len) } } } +#endif + } if (type == nullptr) { From c369289cb58c0a260d1d2cd3e759b4e2e14a048b Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 24 Sep 2019 15:30:26 +0200 Subject: [PATCH 1984/2222] Update xdrv_10_scripter.ino --- sonoff/xdrv_10_scripter.ino | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index 5c7b7b6ae..40fa40391 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -42,8 +42,9 @@ keywords if then else endif, or, and are better readable for beginners (others m #define SCRIPT_DEBUG 0 #define MAXVARS 50 -#define MAXNVARS 45 #define MAXSVARS 5 +#define MAXNVARS MAXVARS-MAXSVARS + #define MAXFILT 5 #define SCRIPT_SVARSIZE 20 #define SCRIPT_MAXSSIZE 48 @@ -465,6 +466,10 @@ char *script; } namep++; index++; + if (index>255) { + free(glob_script_mem.script_mem); + return -5; + } } // copy string variables From 6ad2d3b86fb9c8b3ba2fd515ab1fa85096b9fdf3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 25 Sep 2019 14:17:20 +0200 Subject: [PATCH 1985/2222] Bump version 6.6.0.14 Bump version 6.6.0.14 --- sonoff/_changelog.ino | 2 ++ sonoff/sonoff_version.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 36ff5c65c..f7a8ca31a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,6 @@ /*********************************************************************************************\ + * 6.6.0.14 20190925 + * * 6.6.0.13 20190922 * Add command EnergyReset4 x,x to initialize total usage for two tarrifs * Add command EnergyReset5 x,x to initialize total export (or production) for two tarrifs diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 6015685ae..02af08bab 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x0606000D; +const uint32_t VERSION = 0x0606000E; #endif // _SONOFF_VERSION_H_ From 5bd19d54db2d7bd964ba00bbbae9d950d94fe925 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 25 Sep 2019 14:24:49 +0200 Subject: [PATCH 1986/2222] Change command Tariffx to allow time entries like 23 (hours), 1320 (minutes) or 23:00 Change command Tariffx to allow time entries like 23 (hours), 1320 (minutes) or 23:00. NOTE: As this is development branch previous tariffs are lost! (#6488) --- sonoff/_changelog.ino | 1 + sonoff/settings.h | 3 +- sonoff/sonoff.h | 2 +- sonoff/support_rtc.ino | 9 +++++- sonoff/xdrv_03_energy.ino | 59 +++++++++++++++++++++++++-------------- 5 files changed, 50 insertions(+), 24 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index f7a8ca31a..6fd2e5f0a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /*********************************************************************************************\ * 6.6.0.14 20190925 + * Change command Tariffx to allow time entries like 23 (hours), 1320 (minutes) or 23:00. NOTE: As this is development branch previous tariffs are lost! (#6488) * * 6.6.0.13 20190922 * Add command EnergyReset4 x,x to initialize total usage for two tarrifs diff --git a/sonoff/settings.h b/sonoff/settings.h index 46fc8b555..ac2079412 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -373,8 +373,9 @@ struct SYSCFG { TuyaFnidDpidMap tuya_fnid_map[MAX_TUYA_FUNCTIONS]; // E00 32 bytes uint16_t ina226_r_shunt[4]; // E20 uint16_t ina226_i_fs[4]; // E28 + uint16_t tariff[4][2]; // E30 - uint8_t free_e30[456]; // E30 + uint8_t free_e40[440]; // E40 uint32_t cfg_timestamp; // FF8 uint32_t cfg_crc32; // FFC diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 7269ac5fa..ec317d7f5 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -252,7 +252,7 @@ enum SettingsParamIndex { P_HOLD_TIME, P_MAX_POWER_RETRY, P_ex_TUYA_DIMMER_ID, P P_ex_ENERGY_TARIFF1, P_ex_ENERGY_TARIFF2, // SetOption47 .. SetOption48 P_MAX_PARAM8 }; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 -enum SettingsRegister8 { R8_ENERGY_TARIFF1_ST, R8_ENERGY_TARIFF2_ST, R8_ENERGY_TARIFF1_DS, R8_ENERGY_TARIFF2_DS, +enum SettingsRegister8 { R8_SPARE00, R8_SPARE01, R8_SPARE02, R8_SPARE03, R8_SPARE04, R8_SPARE05, R8_SPARE06, R8_SPARE07, R8_SPARE08, R8_SPARE09, R8_SPARE10, R8_SPARE11, R8_SPARE12, R8_SPARE13, R8_SPARE14, R8_SPARE15, diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index 961869687..b799003c4 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -120,10 +120,17 @@ String GetBuildDateAndTime(void) return String(bdt); // 2017-03-07T11:08:02 } +String GetMinuteTime(uint32_t minutes) +{ + char tm[6]; + snprintf_P(tm, sizeof(tm), PSTR("%02d:%02d"), minutes / 60, minutes % 60); + + return String(tm); // 03:45 +} + String GetTimeZone(void) { char tz[7]; - snprintf_P(tz, sizeof(tz), PSTR("%+03d:%02d"), Rtc.time_timezone / 60, abs(Rtc.time_timezone % 60)); return String(tz); // -03:45 diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 4e4931b33..55bf1a15f 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -129,18 +129,18 @@ Ticker ticker_energy; bool EnergyTariff1Active() // Off-Peak hours { - uint8_t tariff1 = Settings.register8[R8_ENERGY_TARIFF1_ST]; - uint8_t tariff2 = Settings.register8[R8_ENERGY_TARIFF2_ST]; - if (IsDst() && (Settings.register8[R8_ENERGY_TARIFF1_DS] != Settings.register8[R8_ENERGY_TARIFF2_DS])) { - tariff1 = Settings.register8[R8_ENERGY_TARIFF1_DS]; - tariff2 = Settings.register8[R8_ENERGY_TARIFF2_DS]; + uint8_t dst = 0; + if (IsDst() && (Settings.tariff[0][1] != Settings.tariff[1][1])) { + dst = 1; } - if (tariff1 != tariff2) { - return ((RtcTime.hour < tariff2) || // Tarrif1 = Off-Peak - (RtcTime.hour >= tariff1) || + if (Settings.tariff[0][dst] != Settings.tariff[1][dst]) { + uint32_t minutes = MinutesPastMidnight(); + return ((minutes < Settings.tariff[1][dst]) || // Tarrif1 = Off-Peak + (minutes >= Settings.tariff[0][dst]) || (Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) || (RtcTime.day_of_week == 7))) ); + } else { return false; } @@ -583,30 +583,46 @@ void CmndEnergyReset(void) void CmndTariff(void) { - // Tariff1 22,23 - Tariff1 start hour for Standard Time and Daylight Savings Time - // Tariff2 6,7 - Tariff2 start hour for Standard Time and Daylight Savings Time + // Tariff1 22:00,23:00 - Tariff1 start hour for Standard Time and Daylight Savings Time + // Tariff2 6:00,7:00 - Tariff2 start hour for Standard Time and Daylight Savings Time + // Tariffx 1320, 1380 = minutes and also 22:00, 23:00 + // Tariffx 22, 23 = hours and also 22:00, 23:00 // Tariff9 0/1 if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); + uint32_t tariff = XdrvMailbox.index -1; uint32_t time_type = 0; - while ((str != nullptr) && (time_type <= 2)) { - uint8_t value = strtol(str, nullptr, 10); - if ((value >= 0) && (value < 24)) { - Settings.register8[R8_ENERGY_TARIFF1_ST + (XdrvMailbox.index -1) + time_type] = value; + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); // 23:15, 22:30 + while ((str != nullptr) && (time_type < 2)) { + char *q; + uint32_t value = strtol(str, &q, 10); // 23 or 22 + Settings.tariff[tariff][time_type] = value; + if (value < 24) { // Below 24 is hours + Settings.tariff[tariff][time_type] *= 60; // Multiply hours by 60 minutes + char *minute = strtok_r(nullptr, ":", &q); + if (minute) { + value = strtol(minute, nullptr, 10); // 15 or 30 + if (value > 59) { + value = 59; + } + Settings.tariff[tariff][time_type] += value; + } + } + if (Settings.tariff[tariff][time_type] > 1439) { + Settings.tariff[tariff][time_type] = 1439; // Max is 23:59 } str = strtok_r(nullptr, ", ", &p); - time_type += 2; + time_type++; } } else if (XdrvMailbox.index == 9) { Settings.flag3.energy_weekend = XdrvMailbox.payload & 1; } - Response_P(PSTR("{\"%s\":{\"Off-Peak\":[%d,%d],\"Standard\":[%d,%d],\"Weekend\":\"%s\"}}"), + Response_P(PSTR("{\"%s\":{\"Off-Peak\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Standard\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Weekend\":\"%s\"}}"), XdrvMailbox.command, - Settings.register8[R8_ENERGY_TARIFF1_ST], Settings.register8[R8_ENERGY_TARIFF1_DS], - Settings.register8[R8_ENERGY_TARIFF2_ST], Settings.register8[R8_ENERGY_TARIFF2_DS], + GetMinuteTime(Settings.tariff[0][0]).c_str(),GetMinuteTime(Settings.tariff[0][1]).c_str(), + GetMinuteTime(Settings.tariff[1][0]).c_str(),GetMinuteTime(Settings.tariff[1][1]).c_str(), GetStateText(Settings.flag3.energy_weekend)); } @@ -954,7 +970,8 @@ void EnergyShow(bool json) char export_active_chr[3][FLOATSZ]; dtostrfd(Energy.export_active, Settings.flag2.energy_resolution, export_active_chr[0]); uint8_t energy_total_fields = 1; - if (Settings.register8[R8_ENERGY_TARIFF1_ST] != Settings.register8[R8_ENERGY_TARIFF2_ST]) { + + if (Settings.tariff[0][0] != Settings.tariff[1][0]) { dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[1]); // Tariff1 dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[2]); // Tariff2 dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[1]); // Tariff1 From 3eb219ccaaf2fa986a0a969de61d4f310cd07b1a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 25 Sep 2019 14:35:37 +0200 Subject: [PATCH 1987/2222] Remove support for define USE_DS18x20_LEGACY Remove support for define USE_DS18x20_LEGACY and legacy DS18x20 driver (#6486) --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 3 +-- sonoff/sonoff_post.h | 5 +---- sonoff/sonoff_template.h | 2 +- sonoff/support_features.ino | 2 +- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 6fd2e5f0a..fa2183986 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /*********************************************************************************************\ * 6.6.0.14 20190925 * Change command Tariffx to allow time entries like 23 (hours), 1320 (minutes) or 23:00. NOTE: As this is development branch previous tariffs are lost! (#6488) + * Remove support for define USE_DS18x20_LEGACY and legacy DS18x20 driver (#6486) * * 6.6.0.13 20190922 * Add command EnergyReset4 x,x to initialize total usage for two tarrifs diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 12bbb60ce..c9e9521a1 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -321,8 +321,7 @@ //#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices // -- One wire sensors ---------------------------- - // WARNING: Select none for default one DS18B20 sensor or enable one of the following two options for multiple sensors -//#define USE_DS18x20_LEGACY // Optional for more than one DS18x20 sensors with dynamic scan using library OneWire (+1k5 code) + // WARNING: Select none for default one DS18B20 sensor or enable the following option for multiple sensors #define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) // #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors // #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistors for single DS18B20 diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 9d9bbb014..3a792f569 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -98,7 +98,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_COUNTER // Enable counters #undef USE_ADC_VCC // Add Analog input on selected devices #define USE_DS18x20 // For more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) -//#define USE_DS18x20_LEGACY // For more than one DS18x20 sensors with dynamic scan using library OneWire (+1k5 code) #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) #define USE_SHT // Add I2C emulating code for SHT1X sensor (+1k4 code) @@ -415,7 +414,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c * Mandatory define for DS18x20 if changed by above image selections \*********************************************************************************************/ -#if defined(USE_DS18x20) || defined(USE_DS18x20_LEGACY) +#if defined(USE_DS18x20) #else #define USE_DS18B20 // Default DS18B20 sensor needs no external library #endif @@ -461,7 +460,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_COUNTER // Disable counters #undef USE_DS18x20 // Disable DS18x20 sensor -#undef USE_DS18x20_LEGACY // Disable DS18x20 sensor #undef USE_DS18B20 // Disable internal DS18B20 sensor #undef USE_I2C // Disable all I2C sensors and devices #undef USE_SPI // Disable all SPI devices @@ -546,7 +544,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_COUNTER // Disable counters #undef USE_DS18x20 // Disable DS18x20 sensor -#undef USE_DS18x20_LEGACY // Disable DS18x20 sensor #undef USE_DS18B20 // Disable internal DS18B20 sensor #undef USE_I2C // Disable all I2C sensors and devices #undef USE_SPI // Disable all SPI devices diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 0ab4d0752..e0f3c6e06 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -531,7 +531,7 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_DHT22, // DHT21, DHT22, AM2301, AM2302, AM2321 GPIO_SI7021, // iTead SI7021 #endif -#if defined(USE_DS18B20) || defined(USE_DS18x20) || defined(USE_DS18x20_LEGACY) +#if defined(USE_DS18B20) || defined(USE_DS18x20) GPIO_DSB, // Single wire DS18B20 or DS18S20 #endif diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 35d900041..9b5e05747 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -243,7 +243,7 @@ void GetFeatures(void) feature_sns1 |= 0x00000010; // xsns_05_ds18b20.ino #endif #ifdef USE_DS18x20_LEGACY - feature_sns1 |= 0x00000020; // xsns_05_ds18x20_legacy.ino + feature_sns1 |= 0x00000020; // xsns_05_ds18x20_legacy.ino - no more supported since 6.6.0.14 #endif #ifdef USE_DS18x20 feature_sns1 |= 0x00000040; // xsns_05_ds18x20.ino From f03ec437feaa754df86c9fafb6ac24b648654c05 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 25 Sep 2019 15:07:23 +0200 Subject: [PATCH 1988/2222] Delete xsns_05_ds18x20_legacy.ino --- sonoff/xsns_05_ds18x20_legacy.ino | 245 ------------------------------ 1 file changed, 245 deletions(-) delete mode 100644 sonoff/xsns_05_ds18x20_legacy.ino diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino deleted file mode 100644 index 6fe0d764c..000000000 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ /dev/null @@ -1,245 +0,0 @@ -/* - xsns_05_ds18x20_legacy.ino - DS18x20 temperature sensor support for Sonoff-Tasmota - - Copyright (C) 2019 Heiko Krupp 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 - 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_DS18x20_LEGACY -/*********************************************************************************************\ - * DS18B20 - Temperature -\*********************************************************************************************/ - -#define XSNS_05 5 - -#define DS18S20_CHIPID 0x10 -#define DS18B20_CHIPID 0x28 -#define MAX31850_CHIPID 0x3B - -#define W1_SKIP_ROM 0xCC -#define W1_CONVERT_TEMP 0x44 -#define W1_READ_SCRATCHPAD 0xBE - -#define DS18X20_MAX_SENSORS 8 - -#include - -OneWire *ds = nullptr; - -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 Ds18x20Init(void) -{ - ds = new OneWire(pin[GPIO_DSB]); -} - -void Ds18x20Search(void) -{ - uint8_t num_sensors=0; - uint8_t sensor = 0; - - ds->reset_search(); - for (num_sensors = 0; num_sensors < DS18X20_MAX_SENSORS; 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_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 (uint32_t i = 0; i < num_sensors; i++) { - ds18x20_index[i] = i; - } - for (uint32_t i = 0; i < num_sensors; i++) { - for (uint32_t 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_sensors = num_sensors; -} - -uint8_t Ds18x20Sensors(void) -{ - return ds18x20_sensors; -} - -String Ds18x20Addresses(uint8_t sensor) -{ - char address[20]; - - for (uint32_t i = 0; i < 8; i++) { - sprintf(address+2*i, "%02X", ds18x20_address[ds18x20_index[sensor]][i]); - } - return String(address); -} - -void Ds18x20Convert(void) -{ - ds->reset(); - ds->write(W1_SKIP_ROM); // Address all Sensors on Bus - ds->write(W1_CONVERT_TEMP); // start conversion, no parasite power on at the end -// delay(750); // 750ms should be enough for 12bit conv -} - -bool Ds18x20Read(uint8_t sensor, float &t) -{ - uint8_t data[12]; - int8_t sign = 1; - uint16_t temp12 = 0; - int16_t temp14 = 0; - float temp9 = 0.0; - uint8_t present = 0; - - t = NAN; - - ds->reset(); - ds->select(ds18x20_address[ds18x20_index[sensor]]); - ds->write(W1_READ_SCRATCHPAD); // Read Scratchpad - - for (uint32_t i = 0; i < 9; i++) { - data[i] = ds->read(); - } - if (OneWire::crc8(data, 8) == data[8]) { - switch(ds18x20_address[ds18x20_index[sensor]][0]) { - case DS18S20_CHIPID: - if (data[1] > 0x80) { - data[0] = (~data[0]) +1; - sign = -1; // App-Note fix possible sign error - } - temp9 = (float)(data[0] >> 1) * sign; - t = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); - break; - case DS18B20_CHIPID: - temp12 = (data[1] << 8) + data[0]; - if (temp12 > 2047) { - temp12 = (~temp12) +1; - sign = -1; - } - t = ConvertTemp(sign * temp12 * 0.0625); // Divide by 16 - break; - case MAX31850_CHIPID: - temp14 = (data[1] << 8) + (data[0] & 0xFC); - t = ConvertTemp(temp14 * 0.0625); // Divide by 16 - break; - } - } - return (!isnan(t)); -} - -/********************************************************************************************/ - -void Ds18x20Type(uint8_t sensor) -{ - strcpy_P(ds18x20_types, PSTR("DS18x20")); - switch(ds18x20_address[ds18x20_index[sensor]][0]) { - case DS18S20_CHIPID: - strcpy_P(ds18x20_types, PSTR("DS18S20")); - break; - case DS18B20_CHIPID: - strcpy_P(ds18x20_types, PSTR("DS18B20")); - break; - case MAX31850_CHIPID: - strcpy_P(ds18x20_types, PSTR("MAX31850")); - break; - } -} - -void Ds18x20Show(bool json) -{ - char stemp[10]; - float t; - - uint8_t dsxflg = 0; - for (uint32_t i = 0; i < Ds18x20Sensors(); i++) { - if (Ds18x20Read(i, t)) { // Check if read failed - Ds18x20Type(i); - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - - if (json) { - if (!dsxflg) { - ResponseAppend_P(PSTR(",\"DS18x20\":{")); - stemp[0] = '\0'; - } - dsxflg++; - ResponseAppend_P(PSTR("%s\"DS%d\":{\"" D_JSON_TYPE "\":\"%s\",\"" D_JSON_ADDRESS "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), - stemp, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), temperature); - strlcpy(stemp, ",", sizeof(stemp)); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (1 == dsxflg)) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif // USE_DOMOTICZ -#ifdef USE_KNX - if ((0 == tele_period) && (1 == dsxflg)) { - KnxSensor(KNX_TEMPERATURE, t); - } -#endif // USE_KNX -#ifdef USE_WEBSERVER - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("%s%c%d"), ds18x20_types, IndexSeparator(), i +1); - WSContentSend_PD(HTTP_SNS_TEMP, stemp, temperature, TempUnit()); -#endif // USE_WEBSERVER - } - } - } - if (json) { - if (dsxflg) { - ResponseJsonEnd(); - } - } - Ds18x20Search(); // Check for changes in sensors number - Ds18x20Convert(); // Start Conversion, takes up to one second -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xsns05(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_DSB] < 99) { - switch (function) { - case FUNC_INIT: - Ds18x20Init(); - break; - case FUNC_PREP_BEFORE_TELEPERIOD: - Ds18x20Search(); // Check for changes in sensors number - Ds18x20Convert(); // Start Conversion, takes up to one second - break; - case FUNC_JSON_APPEND: - Ds18x20Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ds18x20Show(0); - break; -#endif // USE_WEBSERVER - } - } - return result; -} - -#endif // USE_DS18x20_LEGACY From 2d1bc97843c71e654a0cceb047ea437d65835592 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 25 Sep 2019 15:44:41 +0200 Subject: [PATCH 1989/2222] Update RELEASENOTES.md --- RELEASENOTES.md | 183 ++++++++++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 83 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1209b76bf..d7084c559 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,4 +1,4 @@ -Logo +Logo # RELEASE NOTES @@ -10,8 +10,13 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade 3. Migrate to **Sonoff-Tasmota 5.14** 4. Migrate to **Sonoff-Tasmota 6.x** -## Core version 2.3.0 vs 2.4.2 -This release is based on ESP8266/Arduino library core 2.3.0 (again) as some people encountered wifi related issues on core 2.4.2. For others core 2.4.2 is working just fine. Both version are available from http://thehackbox.org/tasmota/release/ +## Support of TLS +TLS support for core 2.3.0 is removed. + +TLS is supported on core 2.4.2 and up. To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. See full documentation on https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT + +## Core version 2.3.0 vs 2.4.2 vs 2.5.2 +This release is based on ESP8266/Arduino library core 2.3.0 as some people encountered wifi related issues on core 2.4.2 and 2.5.2. For others core 2.4.2 or 2.5.2 is working just fine. All version are available from http://thehackbox.org/tasmota/release/ ## Change in default initial configuration tool Firmware binary **sonoff-classic.bin** supports **WifiManager, Wps and SmartConfig** for initial configuration. The default tool is **Wps**. @@ -92,6 +97,7 @@ Module | Description 67 SP10 | Tuya SP10 Wifi Smart Switch with Energy Monitoring 68 WAGA CHCZ02MB | WAGA life CHCZ02MB Wifi Smart Switch with Energy Monitoring 69 SYF05 | Sunyesmart SYF05 RGBWW Wifi Led Bulb +70 Sonoff L1 | Sonoff L1 light strip ## Provided Binary Downloads The following binary downloads have been compiled with ESP8266/Arduino library core version **2.3.0**. @@ -107,6 +113,8 @@ The following binary downloads have been compiled with ESP8266/Arduino library c Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/release/020402/ +Core version **2.5.2** binaries can be found at http://thehackbox.org/tasmota/release/020502/ + ## Available Features and Sensors | Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks @@ -118,9 +126,12 @@ Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/re | USE_DOMOTICZ | - | - | x | x | x | x | - | | USE_HOME_ASSISTANT | - | - | - | x | x | x | - | | USE_MQTT_TLS | - | - | - | - | - | - | - | +| USE_MQTT_TLS_CA_CERT | - | - | - | - | - | - | - | +| USE_MQTT_AWS_IOT | - | - | - | - | - | - | - | | USE_KNX | - | - | - | - | x | - | - | | USE_WEBSERVER | x | x | x | x | x | x | x | WifiManager -| USE_EMULATION | - | x | x | x | - | x | - | +| USE_EMULATION_HUE | - | x | x | x | - | x | - | +| USE_EMULATION_WEMO | - | x | x | x | - | x | - | | USE_DISCOVERY | - | - | x | x | x | x | x | | WEBSERVER_ADVERTISE | - | - | x | x | x | x | x | | MQTT_HOST_DISCOVERY | - | - | x | x | x | x | x | @@ -128,12 +139,15 @@ Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/re | USE_TIMERS_WEB | - | x | - | x | x | x | x | | USE_SUNRISE | - | x | - | x | x | x | x | | USE_RULES | - | x | - | x | x | x | x | +| USE_SCRIPT | - | - | - | - | - | - | - | | USE_EXPRESSION | - | - | - | - | - | - | - | | | | | | | | | | -| USE_ADC_VCC | x | x | x | x | x | - | x | +| USE_ADC_VCC | x | x | x | - | - | - | - | +| USE_COUNTER | - | - | - | x | x | x | x | | USE_DS18B20 | - | - | - | - | - | - | - | Single sensor | USE_DS18x20 | - | - | x | x | x | x | x | Multiple sensors | USE_DS18x20_LEGACY | - | - | - | - | - | - | - | Multiple sensors +| USE_DHT | - | - | x | x | x | x | x | | | | | | | | | | | Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks | USE_I2C | - | - | - | x | x | x | x | @@ -162,6 +176,10 @@ Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/re | USE_MGC3130 | - | - | - | - | - | - | - | | USE_MAX44009 | - | - | - | - | - | - | - | | USE_SCD30 | - | - | - | - | - | x | - | +| USE_SPS30 | - | - | - | - | - | - | - | +| USE_ADE7953 | - | - | - | x | x | x | x | +| USE_VL53L0X | - | - | - | - | - | - | - | +| USE_MLX90614 | - | - | - | - | - | - | - | | | | | | | | | | | Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks | USE_SPI | - | - | - | - | - | - | x | @@ -206,81 +224,80 @@ Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/re | USE_DISPLAY_EPAPER_29 | - | - | - | - | - | - | x | Disabled for core 2.3.0 ## Changelog -Version 6.5.0 20190319 - * Remove commands SetOption14 and SetOption63 as it has been superseded by command Interlock - * Remove command SetOption35 0-255 for mDNS start-up delay (#4793) - * Remove support for MQTT_LIBRARY_TYPE, MQTT_ARDUINOMQTT and MQTT_TASMOTAMQTT (#5474) - * Change webserver content handling from single String to small Chunks increasing RAM - * Change code use of boolean to bool and byte to uint8_t - * Change code uint8_t flags to bool flags - * Change sonoff_template.h layout regarding optional module flags like ADC0 - * Change sonoff_template.h module lay-out by removing non-configurable GPIOs - * Change button driver making it modular - * Change switch driver making it modular and introduce input filter (#4665, #4724) - * Change switch input detection by optimizing switch debounce (#4724) - * Change web authentication (#4865) - * Change image name BE_MINIMAL to FIRMWARE_MINIMAL and USE_xyz to FIRMWARE_xyz (#5106) - * Change GUI weblog from XML to plain text solving possible empty screens (#5154) - * Fix most compiler warnings - * Fix Display exception 28 when JSON value is NULL received - * Fix epaper driver (#4785) - * Fix HAss Sensor Discovery Software Watchdog restart (#4831, #4988) - * Fix allowable MAX_RULE_VARS to 16 (#4933) - * Fix mDNS addService (#4938, #4951) - * Fix HAss discovery of MHZ19(B) sensors (#4992) - * Fix some exceptions and watchdogs due to lack of stack space (#5215) - * Fix GUI wifi password acception starting with asteriks (*) (#5231, #5242) - * Fix command WebSend intermittent results (#5273, #5304) - * Fix additional characters in fallbacktopic, hostname and mqttclient on core 2.5.0 (#5359, #5417) - * Fix Energy TotalStartTime when commands EnergyReset0 and/or EnergyReset3 used (#5373) - * Fix DS18S20 temperature calculation (#5375) - * Fix float calculations in range from 0 to -1 (#5386) - * Fix exception on GUI Configure Logging and Configure Other (#5424) - * Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors - * Add command SerialDelimiter 128 to filter reception of only characters between ASCII 32 and 127 (#5131) - * Add command SSerialSend5 \ to SerialBridge - * Add command Interlock 0 / 1 / 1,2 3,4 .. to control interlock ON/OFF and add up to 8 relays in 1 to 4 interlock groups (#4910, #5014) - * Add command Template 255 to copy module configuration over to current active template and store as user template named Merged (#5371) - * Add command WifiConfig 7 to allow reset of device in AP mode without admin password (#5297) - * Add command SetOption36 to control boot loop default restoration (#4645, #5063) - * Add command SetOption37 for RGBCW color mapping (#5326) - * Add command SetOption55 0/1 and define MDNS_ENABLE to disable/enable mDNS (#4793, #4923) - * Add command SetOption62 0/1 to disable retain on Button or Switch hold messages (#5299) - * Add support for Smanergy KA10 Smart Wall Socket with Energy monitoring - * Add support for commands in sensor drivers - * Add support for MAX31855 K-Type thermocouple sensor using softSPI (#4764) - * Add support for Near Field Communication (NFC) controller PN532 using Serial (#4791, #5162) - * Add support for OBI Power Socket 2 (#4829) - * Add support for YTF IR Bridge (#4855) - * Add support for Mi LED Desk Lamp with rotary switch (#4887) - * Add support for Digoo DG-SP202 Smart Socket with Energy monitoring (#4891) - * Add support for MAX44009 Ambient Light sensor (#4907) - * Add support for inverted buttons and inverted buttons without pullup (#4914) - * Add support for Luminea ZX2820 Smart Socket with Energy monitoring (#4921) - * Add support for multiple ADS1115 I2C devices (#5083) - * Add support for online template change using command Template or GUI Configure Other (#5177) - * Add support for Korean language translations (#5344) - * Add support for sensor SCD30 (#5434) - * Add parameter CFG_HOLDER to status 1 message (#5206) - * Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name - * Add Resolution property to Status 3 report providing previous SetOption second value property - * Add property MqttCount to status 6 message representing number of Mqtt re-connections - * Add property LinkCount to state and status 11 message representing number of Wifi Link re-connections - * Add property Downtime to state and status 11 message representing the duration of wifi connection loss - * Add variable %timestamp% to rules (#4749) - * Add rule support for "==", "!=" ">=" and "<=" (#5122) - * Add rule expression enabled by define USE_EXPRESSION in my_user_config.h (#5210) - * Add Power status functionality to LED2 when configured leaving LED1 for Link status indication - * Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring as used in Sonoff Pow and many Tuya based devices - * Add user configuration of MCP39F501 Energy Monitoring as used in Shelly2 - * Add online template configuration using both commands and Configure Template menu option in GUI - * Add (S)SerialSend3 escape sequence \x to allow hexadecimal byte value (#3560, #4947) - * Add define DS18B20_INTERNAL_PULLUP to select internal input pullup when only one DS18B20 sensor is connected eliminating external resistor (#4738) - * Add button control when no relay configured (#4682) - * Add startup delay of 4 seconds to button control (#4829) - * Add core version conditional compile options to provided PWM files (#4917) - * Add resiliency to saved Settings (#5065) - * Add MHZ19 Temperature as Domoticz Temperature selection (#5128) - * Add HAss status sensor (#5139) - * Add status message to former declined group commands (#5145) - * Add 0x to IRRemote (SetOption29) and RCSwitch (SetOption28) received hexadecimal data (#5431) +Version 6.6.0 20190707 + * Remove support of TLS on core 2.3.0 and extent support on core 2.4.2 and up + * Remove MQTT uptime message every hour + * Refactor some defines to const + * Refactor webserver HTML input, button, textarea, and select name based on id + * Refactor webserver sensor data collection + * Refactor TLS based on BearSSL, warning breaking change for fingerprints validation + * Refactor management of lights, using classes and integers instead of floats + * Refactor UDP initial message handling from string to char using static memory and add debug info (#5505) + * Refactor ``IRsend`` and receive for 64-bit support (#5523) + * Refactor MQTT which might solve issue (#5755) + * Refactor ``IRSend`` by using heap when more than 199 values need to be send. May need increase of define MQTT_MAX_PACKET_SIZE too (#5950) + * Refactor double to float in rules, and replaced trigonometric functions from stdlib with smaller versions (#6005) + * Change pubsubclient MQTT_KEEPALIVE from 10 to 30 seconds for AWS IoT support + * Change gamma correction as default behavior, ie "Ledtable 1" + * Change PWM resolution from 8 to 10 bits for low brightness lights + * Change ``IRSend`` Panasonic protocol to 64-bit (#5523) + * Change ADC0 to enabled by default in my_user_config.h (#5671) + * Change define USE_EMULATION by USE_EMULATION_HUE and USE_EMULATION_WEMO (#5826) + * Change default ``PowerDelta`` from 80% to 0% on new installations (#5858, #5028, #4813, #4130, #4145, #3795, #3778, #3660, #3648) + * Fix display Bug in KNX webmenu for Physical Address + * Fix the Unescape() function and the ``SendSerial3`` behaviour + * Fix webserver multiple Javascript window.onload functionality + * Fix TasmotaSerial at 9600 bps solving DFPlayer comms (#5528) + * Fix Configure Timer Web GUI (#5568) + * Fix Shelly 2.5 I2C address priority issue when VEML6070 code is present by disabling VEML6070 for Shelly 2.5 (#5592) + * Fix use of ``SerialDelimiter`` value 128 (#5634) + * Fix Sonoff Pow R2 / S31 invalid energy increments (#5789) + * Fix core 2.5.x ISR not in IRAM exception (#5837) + * Fix Philips Hue emulation Alexa issue by using part of MAC address for LightId (#5849) + * Fix missing white channel for WS2812 (#5869) + * Fix PZem startup issue (#5875) + * Fix exception 9 when syslog is enabled and NTP is just synced (#5917) + * Fix Toggle functionality to button double press when one button and two devices are detected (#5935) + * Fix command ``Channel`` for dual dimmers (#5940) + * Fix not restoring white value on power off/power on (#5993) + * Add command ``AdcParam`` to control ADC0 Temperature and Light formula parameters + * Add command ``LedMask`` to assign which relay has access to power LED (#5602, #5612) + * Add extended LED power control using command ``LedPowerX`` where X is 1 to 4. Enabled when "LedLink(i)" is configured too (#5709) + * Add command ``Sensor20 1..255`` to change Nova Fitness SDS01 working period in minutes (#5452) + * Add command ``SetOption38 6..255`` to set IRReceive protocol detection sensitivity mimizing UNKNOWN protocols (#5853) + * Add command ``SetOption39 1..255`` to control CSE7766 (Pow R2) or HLW8032 (Blitzwolf SHP5) handling of power loads below 6W. Default setting is 128 (#5756) + * Add command ``SetOption40 0..250`` to disable button functionality if activated for over 0.1 second. Needs SetOption1 1 and SetOption13 0 (#5449) + * Add command ``SetOption63 0/1`` to disable relay state feedback scan at restart (#5594, #5663) + * Add command ``SetOption64 0/1`` to switch between "-" or "_" as sensor index separator impacting DS18X20, DHT, BMP and SHT3X sensor names (#5689) + * Add command ``SetOption65 0/1`` and more Tuya Serial based device support (#5815) + * Add command ``WebColor`` to change GUI colors on the fly + * Add support for AWS IoT with TLS 1.2 on core 2.4.2 and up. Full doc here: https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT + * Add support for Badger HR-E Water Meter (#5539) + * Add support for Shelly 2.5 Energy and overtemp Monitoring (#5592) + * Add support for color and colortone for Philips Hue emulation via Alexa (#5600 #4809) + * Add support for Scripts as replacement for Rules. Default disabled but can be enabled in my_user_config.h (#5689) + * Add support for up to four LEDs related to four power outputs. Enabled when "LedLink(i)" is configured too (#5709) + * Add support for Shelly 1PM Template ``{"NAME":"Shelly 1PM","GPIO":[56,0,0,0,82,134,0,0,0,0,0,21,0],"FLAG":2,"BASE":18}`` (#5716) + * Add support for SPS30 Particle sensor thanks to Gerhard Mutz (#5830) + * Add support for VL53L0x time of flight sensor. Might interfere with TSL2561 using same I2C address (#5845) + * Add support for Sonoff L1 thanks to reef-actor (#6002) + * Add rule Http#Initialized + * Add rule System#Save executed just before a planned restart + * Add rule support for single JSON value pair like {"SSerialReceived":"on"} by expanding it to {"SSerialReceived":{"Data":"on"}} allowing for trigger SSerialReceived#Data=on (#5638) + * Add define USE_COUNTER to my_user_config.h to save space in sonoff-basic.bin and sonoff-minimal.bin + * Add define USE_DHT to my_user_config.h to save space in sonoff-basic.bin + * Add defines USE_EMULATION_WEMO and USE_EMULATION_HUE to my_user_config.h to control emulation features at compile time (#5826) + * Add Toggle functionality to button double press when more devices are detected + * Add device OverTemp (>73 Celsius) detection to Energy Monitoring devices with temperature sensor powering off all outputs + * Add Tuya Dimmer 10 second heartbeat serial packet required by some Tuya dimmer secondary MCUs + * Add all temperature, humidity and pressure for global access + * Add validation check when loading settings from flash + * Add HX711 weight restore after controlled restart or after power restore just before executing command Sensor34 7 (#5367, #5786) + * Add GUI hexadecimal color options in my_user_config.h (#5586) + * Add alternative ``IRSend`` command syntax ``IRSend raw,,
,
,,,,`` (#5610) + * Add user configurable ADC0 to Module and Template configuration compatible with current FLAG options (#5671) + * Add AriLux RF control GPIO option "ALux IrSel" (159) replacing "Led4i" (59) for full LED control (#5709) + * Add LED GPIO option "LedLink" (157) and "LedLinki" (158) to select dedicated link status LED (#5709) + * Add all 5 PWM channels individually adressable with LEDs. (#5741) + * Add reset of Energy values when connection to sensor is lost for over 4 seconds (#5874, #5881) + * Add checkbox to GUI password field enabling visibility during password entry only (#5934) \ No newline at end of file From fa826d33d9cf81a4914bda18eab17c8bba8d9ae6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 25 Sep 2019 16:28:54 +0200 Subject: [PATCH 1990/2222] Refactor ds18x20.ino --- sonoff/my_user_config.h | 5 ++--- sonoff/xsns_05_ds18x20.ino | 14 +++++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index c9e9521a1..338ce5d17 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -321,10 +321,9 @@ //#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices // -- One wire sensors ---------------------------- - // WARNING: Select none for default one DS18B20 sensor or enable the following option for multiple sensors #define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) -// #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors -// #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistors for single DS18B20 +// #define W1_PARASITE_POWER // Optimize for parasite powered sensors +// #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistor // -- I2C sensors --------------------------------- #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index ca3d667da..ccbb5df5e 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -74,7 +74,11 @@ uint8_t OneWireReset(void) uint8_t retries = 125; //noInterrupts(); +#ifdef DS18B20_INTERNAL_PULLUP + pinMode(ds18x20_pin, INPUT_PULLUP); +#else pinMode(ds18x20_pin, INPUT); +#endif do { if (--retries == 0) { return 0; @@ -84,7 +88,11 @@ uint8_t OneWireReset(void) pinMode(ds18x20_pin, OUTPUT); digitalWrite(ds18x20_pin, LOW); delayMicroseconds(480); +#ifdef DS18B20_INTERNAL_PULLUP + pinMode(ds18x20_pin, INPUT_PULLUP); +#else pinMode(ds18x20_pin, INPUT); +#endif delayMicroseconds(70); uint8_t r = !digitalRead(ds18x20_pin); //interrupts(); @@ -113,7 +121,11 @@ uint8_t OneWireReadBit(void) pinMode(ds18x20_pin, OUTPUT); digitalWrite(ds18x20_pin, LOW); delayMicroseconds(3); +#ifdef DS18B20_INTERNAL_PULLUP + pinMode(ds18x20_pin, INPUT_PULLUP); +#else pinMode(ds18x20_pin, INPUT); +#endif delayMicroseconds(10); uint8_t r = digitalRead(ds18x20_pin); //interrupts(); @@ -432,7 +444,7 @@ void Ds18x20Show(bool json) if (json) { if (1 == ds18x20_sensors) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, temperature); + ResponseAppend_P(JSON_SNS_TEMP, ds18x20_types, temperature); } else { char address[17]; for (uint32_t j = 0; j < 6; j++) { From 902dc6b69c016d99a7bc530b4b59410ddaf3758e Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 25 Sep 2019 17:56:03 +0200 Subject: [PATCH 1991/2222] Fix rounding issue when reading Channel value --- sonoff/xdrv_04_light.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 1e30152f2..c41f1ae0e 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -2281,7 +2281,7 @@ void CmndChannel(void) light_controller.changeChannels(Light.current_color); coldim = true; } - ResponseCmndIdxNumber(Light.current_color[XdrvMailbox.index -1] * 100 / 255); + ResponseCmndIdxNumber(changeUIntScale(Light.current_color[XdrvMailbox.index -1],0,255,0,100)); if (coldim) { LightPreparePower(); } From 9c885079f087bf3555e4d46bb9b015e533960582 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 25 Sep 2019 18:14:58 +0200 Subject: [PATCH 1992/2222] Allow Hue emulation friendly names to go beyond 13 --- sonoff/xdrv_20_hue.ino | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sonoff/xdrv_20_hue.ino b/sonoff/xdrv_20_hue.ino index 7d7146272..2b40b2eea 100644 --- a/sonoff/xdrv_20_hue.ino +++ b/sonoff/xdrv_20_hue.ino @@ -364,12 +364,15 @@ void HueLightStatus2(uint8_t device, String *response) char fname[33]; strcpy(fname, Settings.friendlyname[MAX_FRIENDLYNAMES-1]); uint32_t fname_len = strlen(fname); - if (fname_len >= 33-3) { - fname[33-3] = 0x00; - fname_len = 33-3; - } + if (fname_len > 30) { fname_len = 30; } fname[fname_len++] = '-'; - fname[fname_len++] = '0' + device - MAX_FRIENDLYNAMES; + if (device - MAX_FRIENDLYNAMES < 10) { + fname[fname_len++] = '0' + device - MAX_FRIENDLYNAMES; + } else { + fname[fname_len++] = 'A' + device - MAX_FRIENDLYNAMES - 10; + } + fname[fname_len] = 0x00; + response->replace("{j1", fname); } response->replace("{j2", GetHueDeviceId(device)); From febb93788cf5766e927c931710c6bc8dc21ae3d2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 26 Sep 2019 12:30:21 +0200 Subject: [PATCH 1993/2222] Experimental support for SM2135 Experimental support for SM2135 (#6495) --- sonoff/xdrv_26_sm2135.ino | 104 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 sonoff/xdrv_26_sm2135.ino diff --git a/sonoff/xdrv_26_sm2135.ino b/sonoff/xdrv_26_sm2135.ino new file mode 100644 index 000000000..0590cda1c --- /dev/null +++ b/sonoff/xdrv_26_sm2135.ino @@ -0,0 +1,104 @@ +/* + xdrv_26_sm2135.ino - sm2135 I2C five channel led support for Sonoff-Tasmota + + Copyright (C) 2019 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_LIGHT +#ifdef USE_SM2135 +/*********************************************************************************************\ + * SM2135 I2C RGBCW Led bulbs like Action LSC SmartLed +\*********************************************************************************************/ + +#define XDRV_26 26 + +#define SM2135_ADDR 0x40 // 0x40 .. 0x46 +#define SM2135_CURRENT 0x24 // Defaults: 20mA for RGB, 30mA for CW +#define SM2135_RGB 0x00 +#define SM2135_CW 0x80 + +struct SM2135 { + bool found = true; +} Sm2135; + +bool Sm2135SetChannels(void) +{ + char *buffer = XdrvMailbox.data; + + // EXPERIMENTAL: Figure out if selecting RGB or CW blanks the opposite + + if (('\0' == buffer[3]) && ('\0' == buffer[4])) { + Wire.beginTransmission(SM2135_ADDR); + Wire.write(SM2135_CURRENT); // Set current + Wire.write(SM2135_RGB); // Select RGB - Shutdown CW? + Wire.write(buffer[0]); // Red + Wire.write(buffer[1]); // Green + Wire.write(buffer[2]); // Blue + Wire.endTransmission(); + } else { + Wire.beginTransmission(SM2135_ADDR); + Wire.write(SM2135_CURRENT); // Set current + Wire.write(SM2135_CW); // Select CW - Shutdown RGB? + Wire.endTransmission(); + + Wire.beginTransmission(SM2135_ADDR +5); + Wire.write(buffer[4]); // Cold + Wire.write(buffer[3]); // Warm + Wire.endTransmission(); + } + + return true; +} + +bool Sm2135ModuleSelected(void) +{ + if (I2cDevice(SM2135_ADDR)) { + + // Make sure it is the SM2135 chip as it's address is also used by HTU21, INA219, INA226 + // EXPERIMENTAL: Need further testing + + light_type = LT_RGBWC; + + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "SM2135", SM2135_ADDR); + } else { + Sm2135.found = false; + } + return Sm2135.found; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv26(uint8_t function) +{ + bool result = false; + + if (i2c_flg && Sm2135.found) { + switch (function) { + case FUNC_SET_CHANNELS: + result = Sm2135SetChannels(); + break; + case FUNC_MODULE_INIT: + result = Sm2135ModuleSelected(); + break; + } + } + return result; +} + +#endif // USE_SM2135 +#endif // USE_LIGHT From 81b081f62010d3c4d666eeb244913557bc956829 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 26 Sep 2019 16:06:05 +0200 Subject: [PATCH 1994/2222] Add max current checks to SM2135 Add max current checks to SM2135 (#6495) --- sonoff/xdrv_26_sm2135.ino | 44 ++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/sonoff/xdrv_26_sm2135.ino b/sonoff/xdrv_26_sm2135.ino index 0590cda1c..9b4c8de8d 100644 --- a/sonoff/xdrv_26_sm2135.ino +++ b/sonoff/xdrv_26_sm2135.ino @@ -26,7 +26,10 @@ #define XDRV_26 26 #define SM2135_ADDR 0x40 // 0x40 .. 0x46 -#define SM2135_CURRENT 0x24 // Defaults: 20mA for RGB, 30mA for CW + +//#define SM2135_CURRENT 0x24 // Defaults: 20mA for RGB, 30mA for CW +#define SM2135_CURRENT 0x16 // Defaults: 15mA for RGB, 40mA for CW + #define SM2135_RGB 0x00 #define SM2135_CW 0x80 @@ -38,26 +41,39 @@ bool Sm2135SetChannels(void) { char *buffer = XdrvMailbox.data; - // EXPERIMENTAL: Figure out if selecting RGB or CW blanks the opposite +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SM1: R %d G %d B %d, C %d W %d"), buffer[0], buffer[1], buffer[2], buffer[3], buffer[4]); - if (('\0' == buffer[3]) && ('\0' == buffer[4])) { + if (('\0' == buffer[0]) && ('\0' == buffer[1]) && ('\0' == buffer[2])) { + // No color so must be Cold/Warm + if ((buffer[3] + buffer[4]) >= (1 * 256)) { + // Scale down to 255 total to fix max power usage of 9W (=40mA) + // Currently not needed with setting 2 x 40mA/2 = 40mA = 9W = 255 (handled by lights.ino) + + buffer[3] <<= 1; // Divide by 2 + buffer[4] <<= 1; // Divide by 2 + } Wire.beginTransmission(SM2135_ADDR); - Wire.write(SM2135_CURRENT); // Set current + Wire.write(SM2135_CURRENT); // Set current to 40mA + Wire.write(SM2135_CW); // Select CW - Shutdown RGB? + Wire.endTransmission(); + delay(1); + Wire.beginTransmission(SM2135_ADDR +5); + Wire.write(buffer[3]); // Cold + Wire.write(buffer[4]); // Warm + Wire.endTransmission(); + } else { + // Color + if ((buffer[0] + buffer[1] + buffer[2]) >= (3 * 256)) { + // Scale down to 765 total to fix max power usage of 9W + // Currently not needed with setting 3 x 15mA = 45mA = 11W = 765 + } + Wire.beginTransmission(SM2135_ADDR); + Wire.write(SM2135_CURRENT); // Set current to 15mA Wire.write(SM2135_RGB); // Select RGB - Shutdown CW? Wire.write(buffer[0]); // Red Wire.write(buffer[1]); // Green Wire.write(buffer[2]); // Blue Wire.endTransmission(); - } else { - Wire.beginTransmission(SM2135_ADDR); - Wire.write(SM2135_CURRENT); // Set current - Wire.write(SM2135_CW); // Select CW - Shutdown RGB? - Wire.endTransmission(); - - Wire.beginTransmission(SM2135_ADDR +5); - Wire.write(buffer[4]); // Cold - Wire.write(buffer[3]); // Warm - Wire.endTransmission(); } return true; From 82b72253320551ebfe2b85c8161730eef01de8bd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 26 Sep 2019 16:16:38 +0200 Subject: [PATCH 1995/2222] Fix divide Fix divide --- sonoff/xdrv_26_sm2135.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_26_sm2135.ino b/sonoff/xdrv_26_sm2135.ino index 9b4c8de8d..509b268dc 100644 --- a/sonoff/xdrv_26_sm2135.ino +++ b/sonoff/xdrv_26_sm2135.ino @@ -28,7 +28,7 @@ #define SM2135_ADDR 0x40 // 0x40 .. 0x46 //#define SM2135_CURRENT 0x24 // Defaults: 20mA for RGB, 30mA for CW -#define SM2135_CURRENT 0x16 // Defaults: 15mA for RGB, 40mA for CW +#define SM2135_CURRENT 0x16 // 3 x 15mA for RGB, 2 x 40mA/2 for CW #define SM2135_RGB 0x00 #define SM2135_CW 0x80 @@ -49,8 +49,8 @@ bool Sm2135SetChannels(void) // Scale down to 255 total to fix max power usage of 9W (=40mA) // Currently not needed with setting 2 x 40mA/2 = 40mA = 9W = 255 (handled by lights.ino) - buffer[3] <<= 1; // Divide by 2 - buffer[4] <<= 1; // Divide by 2 + buffer[3] >>= 1; // Divide by 2 + buffer[4] >>= 1; // Divide by 2 } Wire.beginTransmission(SM2135_ADDR); Wire.write(SM2135_CURRENT); // Set current to 40mA From b7aa3cd88466260dce97050187925cb66cdedf5f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 27 Sep 2019 18:13:00 +0200 Subject: [PATCH 1996/2222] Add initial support for MQTT logging Add initial support for MQTT logging using command MqttLog (#6498) --- sonoff/_changelog.ino | 1 + sonoff/i18n.h | 1 + sonoff/settings.h | 3 ++- sonoff/sonoff.h | 2 +- sonoff/support.ino | 1 + sonoff/xdrv_02_mqtt.ino | 41 +++++++++++++++++++++++++++++++++++++++-- 6 files changed, 45 insertions(+), 4 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index fa2183986..e6fb28658 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * 6.6.0.14 20190925 * Change command Tariffx to allow time entries like 23 (hours), 1320 (minutes) or 23:00. NOTE: As this is development branch previous tariffs are lost! (#6488) * Remove support for define USE_DS18x20_LEGACY and legacy DS18x20 driver (#6486) + * Add initial support for MQTT logging using command MqttLog (#6498) * * 6.6.0.13 20190922 * Add command EnergyReset4 x,x to initialize total usage for two tarrifs diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 023a528e8..46bc52ea0 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -291,6 +291,7 @@ #define D_JSON_BASE "BASE" // Commands xdrv_01_mqtt.ino +#define D_CMND_MQTTLOG "MqttLog" #define D_CMND_MQTTHOST "MqttHost" #define D_CMND_MQTTPORT "MqttPort" #define D_CMND_MQTTRETRY "MqttRetry" diff --git a/sonoff/settings.h b/sonoff/settings.h index ac2079412..a4470799a 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -227,7 +227,8 @@ struct SYSCFG { uint8_t weblog_level; // 1AC uint8_t mqtt_fingerprint[2][20]; // 1AD uint8_t adc_param_type; // 1D5 - uint8_t register8[18]; // 1D6 - 18 x 8-bit registers indexed by enum SettingsRegister8 + uint8_t register8[17]; // 1D6 - 17 x 8-bit registers indexed by enum SettingsRegister8 + uint8_t mqttlog_level; // 1E7 uint8_t sps30_inuse_hours; // 1E8 char mqtt_host[33]; // 1E9 - Keep together with below as being copied as one chunck with reset 6 uint16_t mqtt_port; // 20A - Keep together diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index ec317d7f5..1b29754a5 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -256,7 +256,7 @@ enum SettingsRegister8 { R8_SPARE00, R8_SPARE01, R8_SPARE02, R8_SPARE03, R8_SPARE04, R8_SPARE05, R8_SPARE06, R8_SPARE07, R8_SPARE08, R8_SPARE09, R8_SPARE10, R8_SPARE11, R8_SPARE12, R8_SPARE13, R8_SPARE14, R8_SPARE15, - R8_SPARE16, R8_SPARE17 }; // Max size is 18 (Settings.register8[]) + R8_SPARE16 }; // Max size is 17 (Settings.register8[]) enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_P1_SMART_METER, DZ_MAX_SENSORS}; diff --git a/sonoff/support.ino b/sonoff/support.ino index 6fd41b8f0..10bbd2194 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1571,6 +1571,7 @@ void AddLog(uint32_t loglevel) if (!web_log_index) web_log_index++; // Index 0 is not allowed as it is the end of char string } #endif // USE_WEBSERVER + if (!global_state.mqtt_down && (loglevel <= Settings.mqttlog_level)) { MqttPublishLogging(mxtime); } if (!global_state.wifi_down && (loglevel <= syslog_level)) { Syslog(); } } diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 052c881a9..d1bf375a6 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -39,7 +39,7 @@ const char kMqttCommands[] PROGMEM = "|" // No prefix D_CMND_TLSKEY "|" #endif D_CMND_MQTTHOST "|" D_CMND_MQTTPORT "|" D_CMND_MQTTRETRY "|" D_CMND_STATETEXT "|" D_CMND_MQTTCLIENT "|" - D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|" + D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|" D_CMND_MQTTLOG "|" D_CMND_BUTTONTOPIC "|" D_CMND_SWITCHTOPIC "|" D_CMND_BUTTONRETAIN "|" D_CMND_SWITCHRETAIN "|" D_CMND_POWERRETAIN "|" D_CMND_SENSORRETAIN ; void (* const MqttCommand[])(void) PROGMEM = { @@ -53,7 +53,7 @@ void (* const MqttCommand[])(void) PROGMEM = { &CmndTlsKey, #endif &CmndMqttHost, &CmndMqttPort, &CmndMqttRetry, &CmndStateText, &CmndMqttClient, - &CmndFullTopic, &CmndPrefix, &CmndGroupTopic, &CmndTopic, &CmndPublish, + &CmndFullTopic, &CmndPrefix, &CmndGroupTopic, &CmndTopic, &CmndPublish, &CmndMqttlog, &CmndButtonTopic, &CmndSwitchTopic, &CmndButtonRetain, &CmndSwitchRetain, &CmndPowerRetain, &CmndSensorRetain }; struct MQTT { @@ -305,6 +305,35 @@ void MqttUnsubscribe(const char *topic) MqttUnsubscribeLib(topic); } +void MqttPublishLogging(const char *mxtime) +{ + if (Settings.flag.mqtt_enabled) { + if (MqttIsConnected()) { + + char saved_mqtt_data[MESSZ]; + memcpy(saved_mqtt_data, mqtt_data, sizeof(saved_mqtt_data)); +// ResponseTime_P(PSTR(",\"Log\":{\"%s\"}}"), log_data); // Will fail as some messages contain JSON + Response_P(PSTR("%s%s"), mxtime, log_data); // No JSON and ugly!! + + char romram[33]; + char stopic[TOPSZ]; + snprintf_P(romram, sizeof(romram), PSTR("LOGGING")); + GetTopic_P(stopic, STAT, mqtt_topic, romram); + + char *me; + if (!strcmp(Settings.mqtt_prefix[0], Settings.mqtt_prefix[1])) { + me = strstr(stopic, Settings.mqtt_prefix[0]); + if (me == stopic) { + mqtt_cmnd_publish += 3; + } + } + MqttPublishLib(stopic, false); + + memcpy(mqtt_data, saved_mqtt_data, sizeof(saved_mqtt_data)); + } + } +} + void MqttPublishDirect(const char* topic, bool retained) { char sretained[CMDSZ]; @@ -724,6 +753,14 @@ void CmndMqttPassword(void) } #endif // USE_MQTT_AWS_IOT +void CmndMqttlog(void) +{ + if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { + Settings.mqttlog_level = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.mqttlog_level); +} + void CmndMqttHost(void) { #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) From 834e9c7b21898848ee92fd4142cf91d64538700d Mon Sep 17 00:00:00 2001 From: Laurent <44267323+laurentdong@users.noreply.github.com> Date: Fri, 27 Sep 2019 21:52:33 -0400 Subject: [PATCH 1997/2222] Expression evaluation got exception Should use pgm_read_byte to access PROGMEM data --- sonoff/xdrv_10_rules.ino | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 10f733f56..f82a2026b 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -97,7 +97,7 @@ const char kCompareOperators[] PROGMEM = "=\0>\0<\0|\0==!=>=<="; #ifdef USE_EXPRESSION #include // Import LinkedList library - const char kExpressionOperators[] PROGMEM = "+-*/%^"; + const char kExpressionOperators[] PROGMEM = "+-*/%^\0"; #define EXPRESSION_OPERATOR_ADD 0 #define EXPRESSION_OPERATOR_SUBTRACT 1 #define EXPRESSION_OPERATOR_MULTIPLY 2 @@ -1062,10 +1062,16 @@ bool findNextOperator(char * &pointer, int8_t &op) pointer++; continue; } - if (char *pch = strchr(kExpressionOperators, *pointer)) { //If it is an operator - op = (int8_t)(pch - kExpressionOperators); - pointer++; - bSucceed = true; + op = EXPRESSION_OPERATOR_ADD; + const char *pch = kExpressionOperators; + char ch; + while ((ch = pgm_read_byte(pch++)) != '\0') { + if (ch == *pointer) { + bSucceed = true; + pointer++; + break; + } + op++; } break; } @@ -1173,7 +1179,7 @@ float evaluateExpression(const char * expression, unsigned int len) for (int32_t priority = MAX_EXPRESSION_OPERATOR_PRIORITY; priority>0; priority--) { int index = 0; while (index < operators.size()) { - if (priority == kExpressionOperatorsPriorities[(operators.get(index))]) { //need to calculate the operator first + if (priority == pgm_read_byte(kExpressionOperatorsPriorities + operators.get(index))) { //need to calculate the operator first //get current object value and remove the next object with current operator va = calculateTwoValues(object_values.get(index), object_values.remove(index + 1), operators.remove(index)); //Replace the current value with the result From dbd234ef815ff813b0172d8aa0040b974ef57aea Mon Sep 17 00:00:00 2001 From: Laurent <44267323+laurentdong@users.noreply.github.com> Date: Fri, 27 Sep 2019 21:58:32 -0400 Subject: [PATCH 1998/2222] Accept negative number Expression should support negative number --- sonoff/xdrv_10_rules.ino | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 10f733f56..c23b13279 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -919,6 +919,10 @@ bool findNextNumber(char * &pNumber, float &value) { bool bSucceed = false; String sNumber = ""; + if (*pNumber == '-') { + sNumber = "-"; + pNumber++; + } while (*pNumber) { if (isdigit(*pNumber) || (*pNumber == '.')) { sNumber += *pNumber; @@ -996,7 +1000,7 @@ bool findNextVariableValue(char * &pVarname, float &value) /* * Find next object in expression and evaluate it * An object could be: - * - A float number start with a digit, like 0.787 + * - A float number start with a digit or minus, like 0.787, -3 * - A variable name, like VAR1, MEM3 * - An expression enclosed with a pair of round brackets, (.....) * Input: @@ -1018,7 +1022,7 @@ bool findNextObjectValue(char * &pointer, float &value) pointer++; continue; } - if (isdigit(*pointer)) { //This object is a number + if (isdigit(*pointer) || (*pointer) == '-') { //This object is a number bSucceed = findNextNumber(pointer, value); break; } else if (isalpha(*pointer)) { //Should be a variable like VAR12, MEM1 From 9327329b0f9374aa8a2a7a51c549d9aa6780c8da Mon Sep 17 00:00:00 2001 From: Laurent <44267323+laurentdong@users.noreply.github.com> Date: Fri, 27 Sep 2019 22:15:42 -0400 Subject: [PATCH 1999/2222] Missed one character previous of closure bracket For example: Var1 = (1+2) will be treat as: Var1 = 1+ --- sonoff/xdrv_10_rules.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 10f733f56..444904ca0 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -1027,7 +1027,7 @@ bool findNextObjectValue(char * &pointer, float &value) } else if (*pointer == '(') { //It is a sub expression bracketed with () char * closureBracket = findClosureBracket(pointer); //Get the position of closure bracket ")" if (closureBracket != nullptr) { - value = evaluateExpression(pointer+1, closureBracket - pointer - 2); + value = evaluateExpression(pointer+1, closureBracket - pointer - 1); pointer = closureBracket + 1; bSucceed = true; } @@ -1323,7 +1323,7 @@ bool findNextLogicObjectValue(char * &pointer, bool &value) } else if (*pointer == '(') { //It is a sub expression bracketed with () char * closureBracket = findClosureBracket(pointer); //Get the position of closure bracket ")" if (closureBracket != nullptr) { - value = evaluateLogicalExpression(pointer+1, closureBracket - pointer - 2); + value = evaluateLogicalExpression(pointer+1, closureBracket - pointer - 1); pointer = closureBracket + 1; bSucceed = true; } From 702df2b29f8fe8c563997af3df0209226da3def4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 29 Sep 2019 11:52:22 +0200 Subject: [PATCH 2000/2222] Prep for I2C Active control Prep for I2C Active control --- sonoff/support.ino | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 10bbd2194..3baa88f2d 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1264,6 +1264,7 @@ void SetNextTimeInterval(unsigned long& timer, const unsigned long step) #ifdef USE_I2C const uint8_t I2C_RETRY_COUNTER = 3; +uint32_t i2c_active[4] = { 0 }; uint32_t i2c_buffer = 0; bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size) @@ -1457,12 +1458,35 @@ void I2cScan(char *devs, unsigned int devs_len) } } +void I2cSetActive(uint32_t addr, uint32_t count = 1) +{ + addr &= 0x7F; + count &= 0x7F; + while (count-- && (addr < 128)) { + i2c_active[addr / 32] |= (1 << (addr % 32)); + addr++; + } +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("I2C: Active %08X,%08X,%08X,%08X"), i2c_active[0], i2c_active[1], i2c_active[2], i2c_active[3]); +} + +bool I2cActive(uint32_t addr) +{ + addr &= 0x7F; + if (i2c_active[addr / 32] & (1 << (addr % 32))) { + return true; + } + return false; +} + bool I2cDevice(uint8_t addr) { + if (I2cActive(addr)) { + return false; // If already active report as not present; + } for (uint8_t address = 1; address <= 127; address++) { Wire.beginTransmission(address); if (!Wire.endTransmission() && (address == addr)) { - return true; + return true; // Report as present; } } return false; From ea726710183a99101ff3e0f9af594bfbd18f7095 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 29 Sep 2019 12:18:09 +0200 Subject: [PATCH 2001/2222] Fix Energy Off-Peak detection calculation Fix Energy Off-Peak detection calculation (#6500) --- sonoff/xdrv_03_energy.ino | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 55bf1a15f..cd5cc0f45 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -134,13 +134,18 @@ bool EnergyTariff1Active() // Off-Peak hours dst = 1; } if (Settings.tariff[0][dst] != Settings.tariff[1][dst]) { + if (Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) || + (RtcTime.day_of_week == 7))) { + return true; + } uint32_t minutes = MinutesPastMidnight(); - return ((minutes < Settings.tariff[1][dst]) || // Tarrif1 = Off-Peak - (minutes >= Settings.tariff[0][dst]) || - (Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) || - (RtcTime.day_of_week == 7))) - ); - + if (Settings.tariff[0][dst] > Settings.tariff[1][dst]) { + // {"Tariff":{"Off-Peak":{"STD":"22:00","DST":"23:00"},"Standard":{"STD":"06:00","DST":"07:00"},"Weekend":"OFF"}} + return ((minutes >= Settings.tariff[0][dst]) || (minutes < Settings.tariff[1][dst])); + } else { + // {"Tariff":{"Off-Peak":{"STD":"00:29","DST":"01:29"},"Standard":{"STD":"07:29","DST":"08:29"},"Weekend":"OFF"}} + return ((minutes >= Settings.tariff[0][dst]) && (minutes < Settings.tariff[1][dst])); + } } else { return false; } From 4c21e465128444c8e81e608801020692cde82458 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 29 Sep 2019 12:37:33 +0200 Subject: [PATCH 2002/2222] Fix compilation error Fix compilation error (#6509) --- sonoff/support.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 3baa88f2d..0a8b6c42c 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -125,7 +125,7 @@ size_t strcspn(const char *str1, const char *str2) } // https://clc-wiki.net/wiki/C_standard_library:string.h:strpbrk -// Locate the first occurrence in the string pointed to by s1 of any character from the string pointed to by s2 +// Locate the first occurrence in the string pointed to by s1 of any character from the string pointed to by s2 char* strpbrk(const char *s1, const char *s2) { while(*s1) { From ab70dd2755c75a8ed64151898fccd8a70d248ac3 Mon Sep 17 00:00:00 2001 From: Staars Date: Sun, 29 Sep 2019 13:27:50 +0200 Subject: [PATCH 2003/2222] various fixes for the Chirp-sensor --- sonoff/xsns_48_chirp.ino | 48 ++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/sonoff/xsns_48_chirp.ino b/sonoff/xsns_48_chirp.ino index 283128b29..872478b8d 100644 --- a/sonoff/xsns_48_chirp.ino +++ b/sonoff/xsns_48_chirp.ino @@ -21,9 +21,10 @@ -------------------------------------------------------------------------------------------- 1.0.0.1 20190917 changed - rework of the inner loop to enable delays in the middle of I2C-reads + changed - double send address change only for fw>0x25 changed - use DEBUG_SENSOR_LOG, change ILLUMINANCE to DARKNESS - changed - do not publish missing temperature reads - added - now really support the (slower) CHIRP-Sensor + changed - do not publish missing temperature reads, show fw-version as hex + added - now really support the (slower) CHIRP!-Sensor --- 1.0.0.0 20190608 started - further development by Christian Baars - https://github.com/Staars/Sonoff-Tasmota forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota @@ -36,7 +37,8 @@ #ifdef USE_CHIRP /*********************************************************************************************\ - * CHIRP - Soil moisture sensor + * CHIRP - Chirp!-sensor and I2C-soil-moisture-sensor + * !! The I2C-soil-moisture-sensor is the preferred one !! * * I2C Address: 0x20 - standard address, is changeable \*********************************************************************************************/ @@ -82,7 +84,7 @@ enum CHIRP_Commands { // commands useable in con #define CHIRP_GET_LIGHT 0x04 // 16 bit, read, -> higher value means darker environment, noisy data, not calibrated #define CHIRP_GET_TEMPERATURE 0x05 // 16 bit, read #define CHIRP_RESET 0x06 // no value, write -#define CHIRP_GET_VERSION 0x07 // 8 bit, read, -> 22 means 2.2 +#define CHIRP_GET_VERSION 0x07 // 8 bit, read, -> 0x22 means 2.2 #define CHIRP_SLEEP 0x08 // no value, write #define CHIRP_GET_BUSY 0x09 // 8 bit, read, -> 1 = busy, 0 = otherwise @@ -187,24 +189,35 @@ void ChirpSelect(uint8_t sensor) { } } -/********************************************************************************************/ +/******************************************************************************************************************/ uint8_t ChirpReadVersion(uint8_t addr) { - return (I2cRead8(addr, CHIRP_GET_VERSION)); + return (I2cRead8(addr, CHIRP_GET_VERSION)); // the Chirp!-sensor does not provide fw-version and we will get 255 } -/********************************************************************************************/ +/******************************************************************************************************************/ bool ChirpSet(uint8_t addr) { if(addr < 128){ if (I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr)){ - I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr); // two calls are needed for sensor firmware version 2.6 + if(chirp_sensor[chirp_current].version>0x25 && chirp_sensor[chirp_current].version != 255){ + delay(5); + I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr); + // two calls are needed for sensor firmware version 2.6, but maybe dangerous before + } DEBUG_SENSOR_LOG(PSTR("CHIRP: Wrote adress %u "), addr); ChirpReset(chirp_sensor[chirp_current].address); chirp_sensor[chirp_current].address = addr; + chirp_timeout_count = 10; + chirp_next_job = 0; + if(chirp_sensor[chirp_current].version == 255){ // this should be Chirp! and it seems to need a power cycle (or RESET to GND) + AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: wrote new address %u, please power off device"), addr); + chirp_sensor[chirp_current].version == 0; // make it "invisible" + } return true; } } + AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: address %u incorrect and not used"), addr); return false; } @@ -222,11 +235,12 @@ bool ChirpScan() { AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "CHIRP:", address); if(chirp_found_sensors 16){ chirp_timeout_count = (Settings.tele_period - 17) * 10; // sync it with the TELEPERIOD, we need about up to 17 seconds to measure - DEBUG_SENSOR_LOG(PSTR("CHIRP: timeout: %u, tele: %u"), chirp_timeout_count, Settings.tele_period); + DEBUG_SENSOR_LOG(PSTR("CHIRP: timeout 1/10 sec: %u, tele: %u"), chirp_timeout_count, Settings.tele_period); } else{ AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: TELEPERIOD must be > 16 seconds !")); + // we could overwrite it to i.e. 20 seconds here } chirp_next_job = 1; // back to step 1 break; @@ -408,10 +423,15 @@ void ChirpShow(bool json) char str_temperature[33]; double t_temperature = ((double) chirp_sensor[i].temperature )/10.0; dtostrfd(t_temperature, Settings.flag2.temperature_resolution, str_temperature); - char str_light[33]; + char str_light[33]; dtostrfd(chirp_sensor[i].light, 0, str_light); - char str_version[33]; - dtostrfd(chirp_sensor[i].version, 0, str_version); + char str_version[7]; + if(chirp_sensor[i].version == 255){ + strncpy_P(str_version, PSTR("Chirp!"), sizeof(str_version)); + } + else{ + sprintf(str_version, "%x", chirp_sensor[i].version); + } if (json) { if(!chirp_sensor[i].explicitSleep) { ResponseAppend_P(PSTR(",\"%s%u\":{\"" D_JSON_MOISTURE "\":%s"),chirp_name, i, str_moisture); @@ -426,7 +446,7 @@ void ChirpShow(bool json) #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzTempHumSensor(str_temperature, str_moisture); - DomoticzSensor(DZ_ILLUMINANCE,chirp_sensor[i].light); + DomoticzSensor(DZ_ILLUMINANCE,chirp_sensor[i].light); // this is not LUX!! } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER From d86cd349050d60506f45c63c711635d3a149a317 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 29 Sep 2019 15:38:26 +0200 Subject: [PATCH 2004/2222] Add Zigbee more support - collect endpoints and clusters, added ZigbeeDump command --- sonoff/_changelog.ino | 1 + sonoff/i18n.h | 1 + sonoff/xdrv_23_zigbee_4_converters.ino | 537 +++++++++------ sonoff/xdrv_23_zigbee_6_devices.ino | 169 +++++ sonoff/xdrv_23_zigbee_7_statemachine.ino | 650 ++++++++++++++++++ sonoff/xdrv_23_zigbee_8_parsers.ino | 372 +++++++++++ sonoff/xdrv_23_zigbee_9_impl.ino | 814 +---------------------- 7 files changed, 1539 insertions(+), 1005 deletions(-) create mode 100644 sonoff/xdrv_23_zigbee_6_devices.ino create mode 100644 sonoff/xdrv_23_zigbee_7_statemachine.ino create mode 100644 sonoff/xdrv_23_zigbee_8_parsers.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e6fb28658..2da2d46ff 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Change command Tariffx to allow time entries like 23 (hours), 1320 (minutes) or 23:00. NOTE: As this is development branch previous tariffs are lost! (#6488) * Remove support for define USE_DS18x20_LEGACY and legacy DS18x20 driver (#6486) * Add initial support for MQTT logging using command MqttLog (#6498) + * Add Zigbee more support - collect endpoints and clusters, added ZigbeeDump command * * 6.6.0.13 20190922 * Add command EnergyReset4 x,x to initialize total usage for two tarrifs diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 46bc52ea0..5dae197a6 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -456,6 +456,7 @@ // Commands xdrv_23_zigbee.ino #define D_CMND_ZIGBEE_PERMITJOIN "ZigbeePermitJoin" +#define D_CMND_ZIGBEE_DUMP "ZigbeeDump" #define D_CMND_ZIGBEEZNPSEND "ZigbeeZNPSend" #define D_JSON_ZIGBEE_STATUS "ZigbeeStatus" #define D_JSON_ZIGBEEZNPRECEIVED "ZigbeeZNPReceived" diff --git a/sonoff/xdrv_23_zigbee_4_converters.ino b/sonoff/xdrv_23_zigbee_4_converters.ino index 2271c4371..09b2872b9 100644 --- a/sonoff/xdrv_23_zigbee_4_converters.ino +++ b/sonoff/xdrv_23_zigbee_4_converters.ino @@ -133,6 +133,16 @@ private: SBuffer _payload; }; +char Hex36Char(uint8_t value) { + // convert an integer from 0 to 46, to a single digit 0-9A-Z + if (value < 10) { + return '0' + value; + } else if (value < 46) { + return 'A' + value - 10; + } else { + return '?'; // out of range + } +} // Zigbee ZCL converters @@ -374,17 +384,17 @@ uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer void ZCLFrame::parseRawAttributes(JsonObject& json, uint8_t offset) { uint32_t i = offset; uint32_t len = _payload.len(); - uint32_t attrid = _cluster_id << 16; // set high 16 bits with cluster id - while (len + offset - i >= 3) { - attrid = (attrid & 0xFFFF0000) | _payload.get16(i); // get lower 16 bits + while (len - i >= 3) { + uint16_t attrid = _payload.get16(i); i += 2; - char shortaddr[12]; - snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%08X"), attrid); + char shortaddr[16]; + snprintf_P(shortaddr, sizeof(shortaddr), PSTR("%c_%04X_%04X"), + Hex36Char(_cmd_id), _cluster_id, attrid); // exception for Xiaomi lumi.weather - specific field to be treated as octet and not char - if (0x0000FF01 == attrid) { + if ((0x0000 == _cluster_id) && (0xFF01 == attrid)) { if (0x42 == _payload.get8(i)) { _payload.set8(i, 0x41); // change type from 0x42 to 0x41 } @@ -394,14 +404,13 @@ void ZCLFrame::parseRawAttributes(JsonObject& json, uint8_t offset) { } // Parse non-normalized attributes -// The key is 24 bits, high 16 bits is cluserid, low 8 bits is command id +// The key is "s_" followed by 16 bits clusterId, "_" followed by 8 bits command id void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { uint32_t i = offset; uint32_t len = _payload.len(); - uint32_t attrid = _cluster_id << 8 | _cmd_id; char attrid_str[12]; - snprintf_P(attrid_str, sizeof(attrid_str), PSTR("0x%06X"), attrid); // 24 bits + snprintf_P(attrid_str, sizeof(attrid_str), PSTR("s_%04X_%02X"), _cluster_id, _cmd_id); char hex_char[_payload.len()*2+2]; ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); @@ -409,211 +418,333 @@ void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { json[attrid_str] = hex_char; } -#define ZCL_MODELID "0x00000005" // Cluster 0x0000, attribute 0x05 -#define ZCL_TEMPERATURE "0x04020000" // Cluster 0x0402, attribute 0x00 -#define ZCL_PRESSURE "0x04030000" // Cluster 0x0403, attribute 0x00 -#define ZCL_PRESSURE_SCALED "0x04030010" // Cluster 0x0403, attribute 0x10 -#define ZCL_PRESSURE_SCALE "0x04030014" // Cluster 0x0403, attribute 0x14 -#define ZCL_HUMIDITY "0x04050000" // Cluster 0x0403, attribute 0x00 -#define ZCL_LUMI_WEATHER "0x0000FF01" // Cluster 0x0000, attribute 0xFF01 - proprietary +// return value: +// 0 = keep initial value +// 1 = remove initial value +typedef int32_t (*Z_AttrConverter)(JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param); +typedef struct Z_AttributeConverter { + const char * filter; + const char * name; + Z_AttrConverter func; + void * param; +} Z_AttributeConverter; -#define ZCL_OO_OFF "0x000600" // Cluster 0x0006, cmd 0x00 - On/Off - Off -#define ZCL_OO_ON "0x000601" // Cluster 0x0006, cmd 0x01 - On/Off - On -#define ZCL_COLORTEMP_MOVE "0x03000A" // Cluster 0x0300, cmd 0x0A, Move to Color Temp -#define ZCL_LC_MOVE "0x000800" // Cluster 0x0008, cmd 0x00, Level Control Move to Level -#define ZCL_LC_MOVE_1 "0x000801" // Cluster 0x0008, cmd 0x01, Level Control Move -#define ZCL_LC_STEP "0x000802" // Cluster 0x0008, cmd 0x02, Level Control Step -#define ZCL_LC_STOP "0x000803" // Cluster 0x0008, cmd 0x03, Level Control Stop -#define ZCL_LC_MOVE_WOO "0x000804" // Cluster 0x0008, cmd 0x04, Level Control Move to Level, with On/Off -#define ZCL_LC_MOVE_1_WOO "0x000805" // Cluster 0x0008, cmd 0x05, Level Control Move, with On/Off -#define ZCL_LC_STEP_WOO "0x000806" // Cluster 0x0008, cmd 0x05, Level Control Step, with On/Off -#define ZCL_LC_STOP_WOO "0x000807" // Cluster 0x0008, cmd 0x07, Level Control Stop +const float Z_100 PROGMEM = 100.0f; +const float Z_10 PROGMEM = 10.0f; -void ZCLFrame::postProcessAttributes(JsonObject& json) { - const __FlashStringHelper *key; +// list of post-processing directives +const Z_AttributeConverter Z_PostProcess[] = { + { "A_0000_0005", D_JSON_MODEL D_JSON_ID, &Z_Copy, nullptr }, // ModelID - // ModelID ZCL 3.2 - key = F(ZCL_MODELID); - if (json.containsKey(key)) { - json[F(D_JSON_MODEL D_JSON_ID)] = json[key]; - json.remove(key); - } + { "A_0400_0000", D_JSON_ILLUMINANCE, &Z_Copy, nullptr }, // Illuminance (in Lux) + { "A_0400_0004", "LightSensorType", &Z_Copy, nullptr }, // LightSensorType + { "A_0400_????", nullptr, &Z_Remove, nullptr }, // Remove all other values - // Temperature ZCL 4.4 - key = F(ZCL_TEMPERATURE); - if (json.containsKey(key)) { - // parse temperature - int32_t temperature = json[key]; - json.remove(key); - json[F(D_JSON_TEMPERATURE)] = temperature / 100.0f; - } + { "A_0401_0000", "LevelStatus", &Z_Copy, nullptr }, // Illuminance (in Lux) + { "A_0401_0001", "LightSensorType", &Z_Copy, nullptr }, // LightSensorType + { "A_0401_????", nullptr, &Z_Remove, nullptr }, // Remove all other values - // Pressure ZCL 4.5 - key = F(ZCL_PRESSURE); - if (json.containsKey(key)) { - json[F(D_JSON_PRESSURE)] = json[key]; - json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); // hPa - json.remove(key); - } - json.remove(F(ZCL_PRESSURE_SCALE)); - json.remove(F(ZCL_PRESSURE_SCALED)); + { "A_0402_0000", D_JSON_TEMPERATURE, &Z_ConvFloatDivider, (void*) &Z_100 }, // Temperature + { "A_0402_????", nullptr, &Z_Remove, nullptr }, // Remove all other values - // Humidity ZCL 4.7 - key = F(ZCL_HUMIDITY); - if (json.containsKey(key)) { - // parse temperature - uint32_t humidity = json[key]; - json.remove(key); - json[F(D_JSON_HUMIDITY)] = humidity / 100.0f; - } + { "A_0403_0000", D_JSON_PRESSURE_UNIT, &Z_Const_Keep, (void*) D_UNIT_PRESSURE}, // Pressure Unit + { "A_0403_0000", D_JSON_PRESSURE, &Z_Copy, nullptr }, // Pressure + { "A_0403_????", nullptr, &Z_Remove, nullptr }, // Remove all other Pressure values - // Osram Mini Switch - key = F(ZCL_OO_OFF); - if (json.containsKey(key)) { - json.remove(key); - json[F(D_CMND_POWER)] = F("Off"); - } - key = F(ZCL_OO_ON); - if (json.containsKey(key)) { - json.remove(key); - json[F(D_CMND_POWER)] = F("On"); - } - key = F(ZCL_COLORTEMP_MOVE); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint16_t color_temp = buf2.get16(0); - uint16_t transition_time = buf2.get16(2); - json.remove(key); - json[F("ColorTemp")] = color_temp; - json[F("TransitionTime")] = transition_time / 10.0f; - } - key = F(ZCL_LC_MOVE_WOO); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint8_t level = buf2.get8(0); - uint16_t transition_time = buf2.get16(1); - json.remove(key); - json[F("Dimmer")] = changeUIntScale(level, 0, 255, 0, 100); // change to percentage - json[F("TransitionTime")] = transition_time / 10.0f; - if (0 == level) { - json[F(D_CMND_POWER)] = F("Off"); - } else { - json[F(D_CMND_POWER)] = F("On"); - } - } - key = F(ZCL_LC_MOVE); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint8_t level = buf2.get8(0); - uint16_t transition_time = buf2.get16(1); - json.remove(key); - json[F("Dimmer")] = changeUIntScale(level, 0, 255, 0, 100); // change to percentage - json[F("TransitionTime")] = transition_time / 10.0f; - } - key = F(ZCL_LC_MOVE_1); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint8_t move_mode = buf2.get8(0); - uint8_t move_rate = buf2.get8(1); - json.remove(key); - json[F("Move")] = move_mode ? F("Down") : F("Up"); - json[F("Rate")] = move_rate; - } - key = F(ZCL_LC_MOVE_1_WOO); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint8_t move_mode = buf2.get8(0); - uint8_t move_rate = buf2.get8(1); - json.remove(key); - json[F("Move")] = move_mode ? F("Down") : F("Up"); - json[F("Rate")] = move_rate; - if (0 == move_mode) { - json[F(D_CMND_POWER)] = F("On"); - } - } - key = F(ZCL_LC_STEP); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint8_t step_mode = buf2.get8(0); - uint8_t step_size = buf2.get8(1); - uint16_t transition_time = buf2.get16(2); - json.remove(key); - json[F("Step")] = step_mode ? F("Down") : F("Up"); - json[F("StepSize")] = step_size; - json[F("TransitionTime")] = transition_time / 10.0f; - } - key = F(ZCL_LC_STEP_WOO); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint8_t step_mode = buf2.get8(0); - uint8_t step_size = buf2.get8(1); - uint16_t transition_time = buf2.get16(2); - json.remove(key); - json[F("Step")] = step_mode ? F("Down") : F("Up"); - json[F("StepSize")] = step_size; - json[F("TransitionTime")] = transition_time / 10.0f; - if (0 == step_mode) { - json[F(D_CMND_POWER)] = F("On"); - } - } - key = F(ZCL_LC_STOP); - if (json.containsKey(key)) { - json.remove(key); - json[F("Stop")] = 1; - } - key = F(ZCL_LC_STOP_WOO); - if (json.containsKey(key)) { - json.remove(key); - json[F("Stop")] = 1; - } + { "A_0404_0000", D_JSON_FLOWRATE, &Z_ConvFloatDivider, (void*) &Z_10 }, // Flow (in m3/h) + { "A_0404_????", nullptr, &Z_Remove, nullptr }, // Remove all other values - // Lumi.weather proprietary field - key = F(ZCL_LUMI_WEATHER); - if (json.containsKey(key)) { - String hex = json[key]; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - DynamicJsonBuffer jsonBuffer; - JsonObject& json_lumi = jsonBuffer.createObject(); - uint32_t i = 0; - uint32_t len = buf2.len(); - char shortaddr[8]; + { "A_0405_0000", D_JSON_HUMIDITY, &Z_ConvFloatDivider, (void*) &Z_100 }, // Humidity + { "A_0405_????", nullptr, &Z_Remove, nullptr }, // Remove all other values - while (len - i >= 2) { - uint8_t attrid = buf2.get8(i++); + { "A_0406_0000", "Occupancy", &Z_Copy, nullptr }, // Occupancy (map8) + { "A_0406_0001", "OccupancySensorType", &Z_Copy, nullptr }, // OccupancySensorType + { "A_0406_????", nullptr, &Z_Remove, nullptr }, // Remove all other values - snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%02X"), attrid); - - i += parseSingleAttribute(json_lumi, shortaddr, buf2, i, len); - } - // parse output - if (json_lumi.containsKey("0x64")) { // Temperature - int32_t temperature = json_lumi["0x64"]; - json[F(D_JSON_TEMPERATURE)] = temperature / 100.0f; - } - if (json_lumi.containsKey("0x65")) { // Humidity - uint32_t humidity = json_lumi["0x65"]; - json[F(D_JSON_HUMIDITY)] = humidity / 100.0f; - } - if (json_lumi.containsKey("0x66")) { // Pressure - int32_t pressure = json_lumi["0x66"]; - json[F(D_JSON_PRESSURE)] = pressure / 100.0f; - json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); // hPa - } - if (json_lumi.containsKey("0x01")) { // Battery Voltage - uint32_t voltage = json_lumi["0x01"]; - json[F(D_JSON_VOLTAGE)] = voltage / 1000.0f; - json[F("Battery")] = toPercentageCR2032(voltage); - } - json.remove(key); - } + // Cmd 0x0A - Cluster 0x0000, attribute 0xFF01 - proprietary + { "A_0000_FF01", nullptr, &Z_AqaraSensor, nullptr }, // Occupancy (map8) + // // 0x0b04 Electrical Measurement + // { "A_0B04_0100", "DCVoltage", &Z_Copy, nullptr }, // Occupancy (map8) + // { "A_0B04_0001", "OccupancySensorType", &Z_Copy, nullptr }, // OccupancySensorType + // { "A_0B04_????", "", &Z_Remove, nullptr }, // Remove all other values +}; +// ====================================================================== +// Remove attribute +int32_t Z_Remove(JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param) { + return 1; // remove original key } +// Copy value as-is +int32_t Z_Copy(JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param) { + json[new_name] = value; + return 1; // remove original key +} + +// Copy value as-is +int32_t Z_Const_Keep(JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param) { + json[new_name] = (char*)param; + return 0; // keep original key +} + +// Convert int to float with divider +int32_t Z_ConvFloatDivider(JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param) { + float f_value = value; + float *divider = (float*) param; + json[new_name] = f_value / *divider; + return 1; // remove original key +} + +int32_t Z_AqaraSensor(JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param) { + String hex = value; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + uint32_t i = 0; + uint32_t len = buf2.len(); + char shortaddr[8]; + char tmp[] = "tmp"; // for obscure reasons, it must be converted from const char* to char*, otherwise ArduinoJson gets confused + + JsonVariant sub_value; + + while (len - i >= 2) { + uint8_t attrid = buf2.get8(i++); + + i += parseSingleAttribute(json, tmp, buf2, i, len); + float val = json[tmp]; + json.remove(tmp); + if (0x64 == attrid) { + json[F(D_JSON_TEMPERATURE)] = val / 100.0f; + } else if (0x65 == attrid) { + json[F(D_JSON_HUMIDITY)] = val / 100.0f; + } else if (0x66 == attrid) { + json[F(D_JSON_PRESSURE)] = val / 100.0f; + json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); // hPa + } else if (0x01 == attrid) { + json[F(D_JSON_VOLTAGE)] = val / 1000.0f; + json[F("Battery")] = toPercentageCR2032(val); + } + } + return 1; // remove original key +} +// ====================================================================== + +#define ZCL_MODELID "A_0000_0005" // Cmd 0x0A - Cluster 0x0000, attribute 0x05 +#define ZCL_TEMPERATURE "A_0402_0000" // Cmd 0x0A - Cluster 0x0402, attribute 0x00 +#define ZCL_PRESSURE "A_0403_0000" // Cmd 0x0A - Cluster 0x0403, attribute 0x00 +#define ZCL_PRESSURE_SCALED "A_0403_0010" // Cmd 0x0A - Cluster 0x0403, attribute 0x10 +#define ZCL_PRESSURE_SCALE "A_0403_0014" // Cmd 0x0A - Cluster 0x0403, attribute 0x14 +#define ZCL_HUMIDITY "A_0405_0000" // Cmd 0x0A - Cluster 0x0403, attribute 0x00 +#define ZCL_LUMI_WEATHER "A_0000_FF01" // Cmd 0x0A - Cluster 0x0000, attribute 0xFF01 - proprietary + +// Cluster Specific commands +#define ZCL_OO_OFF "s_0006_00" // Cluster 0x0006, cmd 0x00 - On/Off - Off +#define ZCL_OO_ON "s_0006_01" // Cluster 0x0006, cmd 0x01 - On/Off - On +#define ZCL_COLORTEMP_MOVE "s_0300_0A" // Cluster 0x0300, cmd 0x0A, Move to Color Temp +#define ZCL_LC_MOVE "s_0008_00" // Cluster 0x0008, cmd 0x00, Level Control Move to Level +#define ZCL_LC_MOVE_1 "s_0008_01" // Cluster 0x0008, cmd 0x01, Level Control Move +#define ZCL_LC_STEP "s_0008_02" // Cluster 0x0008, cmd 0x02, Level Control Step +#define ZCL_LC_STOP "s_0008_03" // Cluster 0x0008, cmd 0x03, Level Control Stop +#define ZCL_LC_MOVE_WOO "s_0008_04" // Cluster 0x0008, cmd 0x04, Level Control Move to Level, with On/Off +#define ZCL_LC_MOVE_1_WOO "s_0008_05" // Cluster 0x0008, cmd 0x05, Level Control Move, with On/Off +#define ZCL_LC_STEP_WOO "s_0008_06" // Cluster 0x0008, cmd 0x05, Level Control Step, with On/Off +#define ZCL_LC_STOP_WOO "s_0008_07" // Cluster 0x0008, cmd 0x07, Level Control Stop + +// inspired from https://github.com/torvalds/linux/blob/master/lib/glob.c +bool mini_glob_match(char const *pat, char const *str) { + for (;;) { + unsigned char c = *str++; + unsigned char d = *pat++; + + switch (d) { + case '?': /* Wildcard: anything but nul */ + if (c == '\0') + return false; + break; + case '\\': + d = *pat++; + /*FALLTHROUGH*/ + default: /* Literal character */ + if (c == d) { + if (d == '\0') + return true; + break; + } + return false; /* No point continuing */ + } + } +} + +void ZCLFrame::postProcessAttributes(JsonObject& json) { + // iterate on json elements + for (auto kv : json) { + String key = kv.key; + JsonVariant& value = kv.value; + + // Iterate on filter + for (uint32_t i = 0; i < sizeof(Z_PostProcess) / sizeof(Z_PostProcess[0]); i++) { + const Z_AttributeConverter *converter = &Z_PostProcess[i]; + + if (mini_glob_match(converter->filter, key.c_str())) { + int32_t drop = (*converter->func)(json, key.c_str(), value, converter->name, converter->param); + if (drop) { + json.remove(key); + } + + } + } + } +} + +//void ZCLFrame::postProcessAttributes2(JsonObject& json) { +// void postProcessAttributes2(JsonObject& json) { +// const __FlashStringHelper *key; +// +// // Osram Mini Switch +// key = F(ZCL_OO_OFF); +// if (json.containsKey(key)) { +// json.remove(key); +// json[F(D_CMND_POWER)] = F("Off"); +// } +// key = F(ZCL_OO_ON); +// if (json.containsKey(key)) { +// json.remove(key); +// json[F(D_CMND_POWER)] = F("On"); +// } +// key = F(ZCL_COLORTEMP_MOVE); +// if (json.containsKey(key)) { +// String hex = json[key]; +// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); +// uint16_t color_temp = buf2.get16(0); +// uint16_t transition_time = buf2.get16(2); +// json.remove(key); +// json[F("ColorTemp")] = color_temp; +// json[F("TransitionTime")] = transition_time / 10.0f; +// } +// key = F(ZCL_LC_MOVE_WOO); +// if (json.containsKey(key)) { +// String hex = json[key]; +// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); +// uint8_t level = buf2.get8(0); +// uint16_t transition_time = buf2.get16(1); +// json.remove(key); +// json[F("Dimmer")] = changeUIntScale(level, 0, 255, 0, 100); // change to percentage +// json[F("TransitionTime")] = transition_time / 10.0f; +// if (0 == level) { +// json[F(D_CMND_POWER)] = F("Off"); +// } else { +// json[F(D_CMND_POWER)] = F("On"); +// } +// } +// key = F(ZCL_LC_MOVE); +// if (json.containsKey(key)) { +// String hex = json[key]; +// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); +// uint8_t level = buf2.get8(0); +// uint16_t transition_time = buf2.get16(1); +// json.remove(key); +// json[F("Dimmer")] = changeUIntScale(level, 0, 255, 0, 100); // change to percentage +// json[F("TransitionTime")] = transition_time / 10.0f; +// } +// key = F(ZCL_LC_MOVE_1); +// if (json.containsKey(key)) { +// String hex = json[key]; +// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); +// uint8_t move_mode = buf2.get8(0); +// uint8_t move_rate = buf2.get8(1); +// json.remove(key); +// json[F("Move")] = move_mode ? F("Down") : F("Up"); +// json[F("Rate")] = move_rate; +// } +// key = F(ZCL_LC_MOVE_1_WOO); +// if (json.containsKey(key)) { +// String hex = json[key]; +// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); +// uint8_t move_mode = buf2.get8(0); +// uint8_t move_rate = buf2.get8(1); +// json.remove(key); +// json[F("Move")] = move_mode ? F("Down") : F("Up"); +// json[F("Rate")] = move_rate; +// if (0 == move_mode) { +// json[F(D_CMND_POWER)] = F("On"); +// } +// } +// key = F(ZCL_LC_STEP); +// if (json.containsKey(key)) { +// String hex = json[key]; +// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); +// uint8_t step_mode = buf2.get8(0); +// uint8_t step_size = buf2.get8(1); +// uint16_t transition_time = buf2.get16(2); +// json.remove(key); +// json[F("Step")] = step_mode ? F("Down") : F("Up"); +// json[F("StepSize")] = step_size; +// json[F("TransitionTime")] = transition_time / 10.0f; +// } +// key = F(ZCL_LC_STEP_WOO); +// if (json.containsKey(key)) { +// String hex = json[key]; +// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); +// uint8_t step_mode = buf2.get8(0); +// uint8_t step_size = buf2.get8(1); +// uint16_t transition_time = buf2.get16(2); +// json.remove(key); +// json[F("Step")] = step_mode ? F("Down") : F("Up"); +// json[F("StepSize")] = step_size; +// json[F("TransitionTime")] = transition_time / 10.0f; +// if (0 == step_mode) { +// json[F(D_CMND_POWER)] = F("On"); +// } +// } +// key = F(ZCL_LC_STOP); +// if (json.containsKey(key)) { +// json.remove(key); +// json[F("Stop")] = 1; +// } +// key = F(ZCL_LC_STOP_WOO); +// if (json.containsKey(key)) { +// json.remove(key); +// json[F("Stop")] = 1; +// } +// +// // Lumi.weather proprietary field +// key = F(ZCL_LUMI_WEATHER); +// if (json.containsKey(key)) { +// String hex = json[key]; +// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); +// DynamicJsonBuffer jsonBuffer; +// JsonObject& json_lumi = jsonBuffer.createObject(); +// uint32_t i = 0; +// uint32_t len = buf2.len(); +// char shortaddr[8]; +// +// while (len - i >= 2) { +// uint8_t attrid = buf2.get8(i++); +// +// snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%02X"), attrid); +// +// //json[shortaddr] = parseSingleAttribute(json_lumi, buf2, i, len, nullptr, 0); +// } +// // parse output +// if (json_lumi.containsKey("0x64")) { // Temperature +// int32_t temperature = json_lumi["0x64"]; +// json[F(D_JSON_TEMPERATURE)] = temperature / 100.0f; +// } +// if (json_lumi.containsKey("0x65")) { // Humidity +// uint32_t humidity = json_lumi["0x65"]; +// json[F(D_JSON_HUMIDITY)] = humidity / 100.0f; +// } +// if (json_lumi.containsKey("0x66")) { // Pressure +// int32_t pressure = json_lumi["0x66"]; +// json[F(D_JSON_PRESSURE)] = pressure / 100.0f; +// json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); // hPa +// } +// if (json_lumi.containsKey("0x01")) { // Battery Voltage +// uint32_t voltage = json_lumi["0x01"]; +// json[F(D_JSON_VOLTAGE)] = voltage / 1000.0f; +// json[F("Battery")] = toPercentageCR2032(voltage); +// } +// json.remove(key); +// } +// +// } + #endif // USE_ZIGBEE diff --git a/sonoff/xdrv_23_zigbee_6_devices.ino b/sonoff/xdrv_23_zigbee_6_devices.ino new file mode 100644 index 000000000..128f11857 --- /dev/null +++ b/sonoff/xdrv_23_zigbee_6_devices.ino @@ -0,0 +1,169 @@ +/* + xdrv_23_zigbee.ino - zigbee support for Sonoff-Tasmota + + Copyright (C) 2019 Theo Arends and Stephan Hadinger + + 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_ZIGBEE + +#include +#include + +typedef struct Z_Device { + uint16_t shortaddr; + uint64_t longaddr; // 0x00 means unspecified + std::vector endpoints; + std::vector clusters_in; // encoded as high 16 bits is endpoint, low 16 bits is cluster number + std::vector clusters_out; // encoded as high 16 bits is endpoint, low 16 bits is cluster number +} Z_Device; + +std::map zigbee_devices = {}; + + +template < typename T> +bool findInVector(const std::vector & vecOfElements, const T & element) { + // Find given element in vector + auto it = std::find(vecOfElements.begin(), vecOfElements.end(), element); + + if (it != vecOfElements.end()) { + return true; + } else { + return false; + } +} + +// insert an entry when it is known it is missing +void Z_InsertShortAddrEntry(uint16_t shortaddr, uint64_t longaddr) { + Z_Device device = { shortaddr, longaddr, + std::vector(), + std::vector(), + std::vector() }; + zigbee_devices[shortaddr] = device; +} + +void Z_AddDeviceLongAddr(uint16_t shortaddr, uint64_t longaddr) { + // is the short address already recorded? + if (0 == zigbee_devices.count(shortaddr)) { + // No, add an entry + Z_InsertShortAddrEntry(shortaddr, longaddr); + } else { + // Yes, update the longaddr if necessary + Z_Device &device = zigbee_devices[shortaddr]; + uint64_t prev_longaddr = device.longaddr; + if (prev_longaddr != longaddr) { + // new device, i.e. collision + device.longaddr = longaddr; + device.endpoints.clear(); + device.clusters_in.clear(); + device.clusters_out.clear(); + } + } +} + +void Z_AddDeviceEndpoint(uint16_t shortaddr, uint8_t endpoint) { + if (0 == zigbee_devices.count(shortaddr)) { + // No entry + Z_InsertShortAddrEntry(shortaddr, 0); + } + Z_Device &device = zigbee_devices[shortaddr]; + if (!findInVector(device.endpoints, endpoint)) { + device.endpoints.push_back(endpoint); + } +} + +void Z_AddDeviceCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out) { + if (0 == zigbee_devices.count(shortaddr)) { + // No entry + Z_InsertShortAddrEntry(shortaddr, 0); + } + Z_Device &device = zigbee_devices[shortaddr]; + if (!findInVector(device.endpoints, endpoint)) { + device.endpoints.push_back(endpoint); + } + uint32_t ep_cluster = (endpoint << 16) | cluster; + if (!out) { + if (!findInVector(device.clusters_in, ep_cluster)) { + device.clusters_in.push_back(ep_cluster); + } + } else { // out + if (!findInVector(device.clusters_out, ep_cluster)) { + device.clusters_out.push_back(ep_cluster); + } + } +} + +String Z_DumpDevices(void) { + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + JsonObject& devices = json.createNestedObject(F("ZigbeeDevices")); + + for (std::map::iterator it = zigbee_devices.begin(); it != zigbee_devices.end(); ++it) { + uint16_t shortaddr = it->first; + Z_Device& device = it->second; + char hex[20]; + + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); + JsonObject& dev = devices.createNestedObject(hex); + dev[F("ShortAddr")] = hex; + + Uint64toHex(device.longaddr, hex, 64); + dev[F("IEEEAddr")] = hex; + + JsonArray& dev_endpoints = dev.createNestedArray(F("Endpoints")); + for (std::vector::iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) { + uint8_t endpoint = *ite; + + snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); + dev_endpoints.add(hex); + } + + JsonObject& dev_clusters_in = dev.createNestedObject(F("Clusters_in")); + for (std::vector::iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) { + uint16_t cluster = *itc & 0xFFFF; + uint8_t endpoint = (*itc >> 16) & 0xFF; + + snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); + if (!dev_clusters_in.containsKey(hex)) { + dev_clusters_in.createNestedArray(hex); + } + JsonArray &cluster_arr = dev_clusters_in[hex]; + + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster); + cluster_arr.add(hex); + } + + JsonObject& dev_clusters_out = dev.createNestedObject(F("Clusters_out")); + for (std::vector::iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) { + uint16_t cluster = *itc & 0xFFFF; + uint8_t endpoint = (*itc >> 16) & 0xFF; + + snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); + if (!dev_clusters_out.containsKey(hex)) { + dev_clusters_out.createNestedArray(hex); + } + JsonArray &cluster_arr = dev_clusters_out[hex]; + + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster); + cluster_arr.add(hex); + } + } + String payload = ""; + payload.reserve(200); + json.printTo(payload); + return payload; +} + +#endif // USE_ZIGBEE diff --git a/sonoff/xdrv_23_zigbee_7_statemachine.ino b/sonoff/xdrv_23_zigbee_7_statemachine.ino new file mode 100644 index 000000000..6d271f0a9 --- /dev/null +++ b/sonoff/xdrv_23_zigbee_7_statemachine.ino @@ -0,0 +1,650 @@ +/* + xdrv_23_zigbee.ino - zigbee support for Sonoff-Tasmota + + Copyright (C) 2019 Theo Arends and Stephan Hadinger + + 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_ZIGBEE + +// Status code used for ZigbeeStatus MQTT message +// Ex: {"ZigbeeStatus":{"Status": 3,"Message":"Configured, starting coordinator"}} +const uint8_t ZIGBEE_STATUS_OK = 0; // Zigbee started and working +const uint8_t ZIGBEE_STATUS_BOOT = 1; // CC2530 booting +const uint8_t ZIGBEE_STATUS_RESET_CONF = 2; // Resetting CC2530 configuration +const uint8_t ZIGBEE_STATUS_STARTING = 3; // Starting CC2530 as coordinator +const uint8_t ZIGBEE_STATUS_PERMITJOIN_CLOSE = 20; // Disable PermitJoin +const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_60 = 21; // Enable PermitJoin for 60 seconds +const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_XX = 22; // Enable PermitJoin until next boot +const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; // Device announces its address +const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; // Node descriptor +const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; // Endpoints descriptor +const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; // Simple Descriptor (clusters) +const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; // Status: CC2530 ZNP Version +const uint8_t ZIGBEE_STATUS_CC_INFO = 51; // Status: CC2530 Device Configuration +const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version +const uint8_t ZIGBEE_STATUS_ABORT = 99; // Fatal error, Zigbee not working + +typedef int32_t (*ZB_Func)(uint8_t value); +typedef int32_t (*ZB_RecvMsgFunc)(int32_t res, class SBuffer &buf); + +typedef union Zigbee_Instruction { + struct { + uint8_t i; // instruction + uint8_t d8; // 8 bits data + uint16_t d16; // 16 bits data + } i; + const void *p; // pointer + // const void *m; // for type checking only, message + // const ZB_Func f; + // const ZB_RecvMsgFunc fr; +} Zigbee_Instruction; +// +// Zigbee_Instruction z1 = { .i = {1,2,3}}; +// Zigbee_Instruction z3 = { .p = nullptr }; + +typedef struct Zigbee_Instruction_Type { + uint8_t instr; + uint8_t data; +} Zigbee_Instruction_Type; + +enum Zigbee_StateMachine_Instruction_Set { + // 2 bytes instructions + ZGB_INSTR_4_BYTES = 0, + ZGB_INSTR_NOOP = 0, // do nothing + ZGB_INSTR_LABEL, // define a label + ZGB_INSTR_GOTO, // goto label + ZGB_INSTR_ON_ERROR_GOTO, // goto label if error + ZGB_INSTR_ON_TIMEOUT_GOTO, // goto label if timeout + ZGB_INSTR_WAIT, // wait for x ms (in chunks of 100ms) + ZGB_INSTR_WAIT_FOREVER, // wait forever but state machine still active + ZGB_INSTR_STOP, // stop state machine with optional error code + + // 6 bytes instructions + ZGB_INSTR_8_BYTES = 0x80, + ZGB_INSTR_CALL = 0x80, // call a function + ZGB_INSTR_LOG, // log a message, if more detailed logging required, call a function + ZGB_INSTR_MQTT_STATUS, // send MQTT status string with code + ZGB_INSTR_SEND, // send a ZNP message + ZGB_INSTR_WAIT_UNTIL, // wait until the specified message is received, ignore all others + ZGB_INSTR_WAIT_RECV, // wait for a message according to the filter + ZGB_ON_RECV_UNEXPECTED, // function to handle unexpected messages, or nullptr + + // 10 bytes instructions + ZGB_INSTR_12_BYTES = 0xF0, + ZGB_INSTR_WAIT_RECV_CALL, // wait for a filtered message and call function upon receive +}; + +#define ZI_NOOP() { .i = { ZGB_INSTR_NOOP, 0x00, 0x0000} }, +#define ZI_LABEL(x) { .i = { ZGB_INSTR_LABEL, (x), 0x0000} }, +#define ZI_GOTO(x) { .i = { ZGB_INSTR_GOTO, (x), 0x0000} }, +#define ZI_ON_ERROR_GOTO(x) { .i = { ZGB_INSTR_ON_ERROR_GOTO, (x), 0x0000} }, +#define ZI_ON_TIMEOUT_GOTO(x) { .i = { ZGB_INSTR_ON_TIMEOUT_GOTO, (x), 0x0000} }, +#define ZI_WAIT(x) { .i = { ZGB_INSTR_WAIT, 0x00, (x)} }, +#define ZI_WAIT_FOREVER() { .i = { ZGB_INSTR_WAIT_FOREVER, 0x00, 0x0000} }, +#define ZI_STOP(x) { .i = { ZGB_INSTR_STOP, (x), 0x0000} }, + +#define ZI_CALL(f, x) { .i = { ZGB_INSTR_CALL, (x), 0x0000} }, { .p = (const void*)(f) }, +#define ZI_LOG(x, m) { .i = { ZGB_INSTR_LOG, (x), 0x0000 } }, { .p = ((const void*)(m)) }, +#define ZI_MQTT_STATUS(x, m) { .i = { ZGB_INSTR_MQTT_STATUS, (x), 0x0000 } }, { .p = ((const void*)(m)) }, +#define ZI_ON_RECV_UNEXPECTED(f) { .i = { ZGB_ON_RECV_UNEXPECTED, 0x00, 0x0000} }, { .p = (const void*)(f) }, +#define ZI_SEND(m) { .i = { ZGB_INSTR_SEND, sizeof(m), 0x0000} }, { .p = (const void*)(m) }, +#define ZI_WAIT_RECV(x, m) { .i = { ZGB_INSTR_WAIT_RECV, sizeof(m), (x)} }, { .p = (const void*)(m) }, +#define ZI_WAIT_UNTIL(x, m) { .i = { ZGB_INSTR_WAIT_UNTIL, sizeof(m), (x)} }, { .p = (const void*)(m) }, +#define ZI_WAIT_RECV_FUNC(x, m, f) { .i = { ZGB_INSTR_WAIT_RECV_CALL, sizeof(m), (x)} }, { .p = (const void*)(m) }, { .p = (const void*)(f) }, + +// Labels used in the State Machine -- internal only +const uint8_t ZIGBEE_LABEL_START = 10; // Start ZNP +const uint8_t ZIGBEE_LABEL_READY = 20; // goto label 20 for main loop +const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; // main loop +const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_CLOSE = 30; // disable permit join +const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60 = 31; // enable permit join for 60 seconds +const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX = 32; // enable permit join for 60 seconds +// errors +const uint8_t ZIGBEE_LABEL_ABORT = 99; // goto label 99 in case of fatal error +const uint8_t ZIGBEE_LABEL_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version + +struct ZigbeeStatus { + bool active = true; // is Zigbee active for this device, i.e. GPIOs configured + bool state_machine = false; // the state machine is running + bool state_waiting = false; // the state machine is waiting for external event or timeout + bool state_no_timeout = false; // the current wait loop does not generate a timeout but only continues running + bool ready = false; // cc2530 initialization is complet, ready to operate + uint8_t on_error_goto = ZIGBEE_LABEL_ABORT; // on error goto label, 99 default to abort + uint8_t on_timeout_goto = ZIGBEE_LABEL_ABORT; // on timeout goto label, 99 default to abort + int16_t pc = 0; // program counter, -1 means abort + uint32_t next_timeout = 0; // millis for the next timeout + + uint8_t *recv_filter = nullptr; // receive filter message + bool recv_until = false; // ignore all messages until the received frame fully matches + size_t recv_filter_len = 0; + ZB_RecvMsgFunc recv_func = nullptr; // function to call when message is expected + ZB_RecvMsgFunc recv_unexpected = nullptr; // function called when unexpected message is received + + bool init_phase = true; // initialization phase, before accepting zigbee traffic +}; +struct ZigbeeStatus zigbee; + +SBuffer *zigbee_buffer = nullptr; + +/*********************************************************************************************\ + * State Machine +\*********************************************************************************************/ + +#define Z_B0(a) (uint8_t)( ((a) ) & 0xFF ) +#define Z_B1(a) (uint8_t)( ((a) >> 8) & 0xFF ) +#define Z_B2(a) (uint8_t)( ((a) >> 16) & 0xFF ) +#define Z_B3(a) (uint8_t)( ((a) >> 24) & 0xFF ) +#define Z_B4(a) (uint8_t)( ((a) >> 32) & 0xFF ) +#define Z_B5(a) (uint8_t)( ((a) >> 40) & 0xFF ) +#define Z_B6(a) (uint8_t)( ((a) >> 48) & 0xFF ) +#define Z_B7(a) (uint8_t)( ((a) >> 56) & 0xFF ) +// Macro to define message to send and receive +#define ZBM(n, x...) const uint8_t n[] PROGMEM = { x }; + +#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL)) + +// ZBS_* Zigbee Send +// ZBR_* Zigbee Recv +ZBM(ZBS_RESET, Z_AREQ | Z_SYS, SYS_RESET, 0x00 ) // 410001 SYS_RESET_REQ Hardware reset +ZBM(ZBR_RESET, Z_AREQ | Z_SYS, SYS_RESET_IND ) // 4180 SYS_RESET_REQ Hardware reset response + +ZBM(ZBS_VERSION, Z_SREQ | Z_SYS, SYS_VERSION ) // 2102 Z_SYS:version +ZBM(ZBR_VERSION, Z_SRSP | Z_SYS, SYS_VERSION ) // 6102 Z_SYS:version + +// Check if ZNP_HAS_CONFIGURED is set +ZBM(ZBS_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, 0x00 /* offset */ ) // 2108000F00 - 6108000155 +ZBM(ZBR_ZNPHC, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_Success, 0x01 /* len */, 0x55) // 6108000155 +// If not set, the response is 61-08-02-00 = Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_InvalidParameter, 0x00 /* len */ + +ZBM(ZBS_PAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PANID ) // 260483 +ZBM(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PANID, 0x02 /* len */, + Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) // 6604008302xxxx + +ZBM(ZBS_EXTPAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_EXTENDED_PAN_ID ) // 26042D +ZBM(ZBR_EXTPAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_EXTENDED_PAN_ID, + 0x08 /* len */, + Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), + Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID), + ) // 6604002D08xxxxxxxxxxxxxxxx + +ZBM(ZBS_CHANN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_CHANLIST ) // 260484 +ZBM(ZBR_CHANN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_CHANLIST, + 0x04 /* len */, + Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), + ) // 6604008404xxxxxxxx + +ZBM(ZBS_PFGK, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEY ) // 260462 +ZBM(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEY, + 0x10 /* len */, + Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), + Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), + Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), + Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), + /*0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0D*/ ) // 660400621001030507090B0D0F00020406080A0C0D + +ZBM(ZBS_PFGKEN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEYS_ENABLE ) // 260463 +ZBM(ZBR_PFGKEN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEYS_ENABLE, + 0x01 /* len */, 0x00 ) // 660400630100 + +// commands to "format" the device +// Write configuration - write success +ZBM(ZBR_W_OK, Z_SRSP | Z_SAPI, SAPI_WRITE_CONFIGURATION, Z_Success ) // 660500 - Write Configuration +ZBM(ZBR_WNV_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_WRITE, Z_Success ) // 610900 - NV Write + +// Factory reset +ZBM(ZBS_FACTRES, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 /* len */, 0x02 ) // 2605030102 +// Write PAN ID +ZBM(ZBS_W_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 /* len */, Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) // 26058302xxxx +// Write EXT PAN ID +ZBM(ZBS_W_EXTPAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_EXTENDED_PAN_ID, 0x08 /* len */, + Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), + Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID) + ) // 26052D086263151D004B1200 +// Write Channel ID +ZBM(ZBS_W_CHANN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_CHANLIST, 0x04 /* len */, + Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), + /*0x00, 0x08, 0x00, 0x00*/ ) // 26058404xxxxxxxx +// Write Logical Type = 00 = coordinator +ZBM(ZBS_W_LOGTYP, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 /* len */, 0x00 ) // 2605870100 +// Write precfgkey +ZBM(ZBS_W_PFGK, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEY, + 0x10 /* len */, + Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), + Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), + Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), + Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), + /*0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0D*/ ) // 2605621001030507090B0D0F00020406080A0C0D +// Write precfgkey enable +ZBM(ZBS_W_PFGKEN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEYS_ENABLE, 0x01 /* len */, 0x00 ) // 2605630100 +// Write Security Mode +ZBM(ZBS_WNV_SECMODE, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(CONF_TCLK_TABLE_START), Z_B1(CONF_TCLK_TABLE_START), + 0x00 /* offset */, 0x20 /* len */, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x5a, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6c, + 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) // 2109010100200FFFFFFFFFFFFFFFF5A6967426565416C6C69616E636530390000000000000000 +// Write Z_ZDO Direct CB +ZBM(ZBS_W_ZDODCB, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_ZDO_DIRECT_CB, 0x01 /* len */, 0x01 ) // 26058F0101 +// NV Init ZNP Has Configured +ZBM(ZBS_WNV_INITZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_ITEM_INIT, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, + 0x01, 0x00 /* InitLen 16 bits */, 0x01 /* len */, 0x00 ) // 2107000F01000100 - 610709 +// Init succeeded +//ZBM(ZBR_WNV_INIT_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_ITEM_INIT, Z_Created ) // 610709 - NV Write +ZBM(ZBR_WNV_INIT_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_ITEM_INIT ) // 6107xx, Success if 610700 or 610709 - NV Write + +// Write ZNP Has Configured +ZBM(ZBS_WNV_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(ZNP_HAS_CONFIGURED), Z_B1(ZNP_HAS_CONFIGURED), + 0x00 /* offset */, 0x01 /* len */, 0x55 ) // 2109000F000155 - 610900 +// Z_ZDO:startupFromApp +ZBM(ZBS_STARTUPFROMAPP, Z_SREQ | Z_ZDO, ZDO_STARTUP_FROM_APP, 100, 0 /* delay */) // 25406400 +ZBM(ZBR_STARTUPFROMAPP, Z_SRSP | Z_ZDO, ZDO_STARTUP_FROM_APP ) // 6540 + 01 for new network, 00 for exisitng network, 02 for error +ZBM(AREQ_STARTUPFROMAPP, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ZB_COORD ) // 45C009 + 08 = starting, 09 = started +// GetDeviceInfo +ZBM(ZBS_GETDEVICEINFO, Z_SREQ | Z_UTIL, Z_UTIL_GET_DEVICE_INFO ) // 2700 +ZBM(ZBR_GETDEVICEINFO, Z_SRSP | Z_UTIL, Z_UTIL_GET_DEVICE_INFO, Z_Success ) // Ex= 6700.00.6263151D004B1200.0000.07.09.00 + // IEEE Adr (8 bytes) = 6263151D004B1200 + // Short Addr (2 bytes) = 0000 + // Device Type (1 byte) = 07 (coord?) + // Device State (1 byte) = 09 (coordinator started) + // NumAssocDevices (1 byte) = 00 + +// Read Pan ID +//ZBM(ZBS_READ_NV_PANID, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, PANID & 0xFF, PANID >> 8, 0x00 /* offset */ ) // 2108830000 + +// Z_ZDO:nodeDescReq +ZBM(ZBS_ZDO_NODEDESCREQ, Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, 0x00, 0x00 /* dst addr */, 0x00, 0x00 /* NWKAddrOfInterest */) // 250200000000 +ZBM(ZBR_ZDO_NODEDESCREQ, Z_SRSP | Z_ZDO, ZDO_NODE_DESC_REQ, Z_Success ) // 650200 +// Async resp ex: 4582.0000.00.0000.00.40.8F.0000.50.A000.0100.A000.00 +ZBM(AREQ_ZDO_NODEDESCRSP, Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP) // 4582 +// SrcAddr (2 bytes) 0000 +// Status (1 byte) 00 Success +// NwkAddr (2 bytes) 0000 +// LogicalType (1 byte) - 00 Coordinator +// APSFlags (1 byte) - 40 0=APSFlags 4=NodeFreqBands +// MACCapabilityFlags (1 byte) - 8F ALL +// ManufacturerCode (2 bytes) - 0000 +// MaxBufferSize (1 byte) - 50 NPDU +// MaxTransferSize (2 bytes) - A000 = 160 +// ServerMask (2 bytes) - 0100 - Primary Trust Center +// MaxOutTransferSize (2 bytes) - A000 = 160 +// DescriptorCapabilities (1 byte) - 00 +ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4584 +ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) // 4585 + +// Z_ZDO:activeEpReq +ZBM(ZBS_ZDO_ACTIVEEPREQ, Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, 0x00, 0x00, 0x00, 0x00) // 250500000000 +ZBM(ZBR_ZDO_ACTIVEEPREQ, Z_SRSP | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_Success) // 65050000 +ZBM(ZBR_ZDO_ACTIVEEPRSP_NONE, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 /* srcAddr */, Z_Success, + 0x00, 0x00 /* nwkaddr */, 0x00 /* activeepcount */) // 45050000 - no Ep running +ZBM(ZBR_ZDO_ACTIVEEPRSP_OK, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 /* srcAddr */, Z_Success, + 0x00, 0x00 /* nwkaddr */, 0x02 /* activeepcount */, 0x0B, 0x01 /* the actual endpoints */) // 25050000 - no Ep running + +// Z_AF:register profile:104, ep:01 +ZBM(ZBS_AF_REGISTER01, Z_SREQ | Z_AF, AF_REGISTER, 0x01 /* endpoint */, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), // 24000401050000000000 + 0x05, 0x00 /* AppDeviceId */, 0x00 /* AppDevVer */, 0x00 /* LatencyReq */, + 0x00 /* AppNumInClusters */, 0x00 /* AppNumInClusters */) +ZBM(ZBR_AF_REGISTER, Z_SRSP | Z_AF, AF_REGISTER, Z_Success) // 640000 +ZBM(ZBS_AF_REGISTER0B, Z_SREQ | Z_AF, AF_REGISTER, 0x0B /* endpoint */, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), // 2400040B050000000000 + 0x05, 0x00 /* AppDeviceId */, 0x00 /* AppDevVer */, 0x00 /* LatencyReq */, + 0x00 /* AppNumInClusters */, 0x00 /* AppNumInClusters */) +// Z_ZDO:mgmtPermitJoinReq +ZBM(ZBS_PERMITJOINREQ_CLOSE, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x02 /* AddrMode */, // 25360200000000 + 0x00, 0x00 /* DstAddr */, 0x00 /* Duration */, 0x00 /* TCSignificance */) +ZBM(ZBS_PERMITJOINREQ_OPEN_60, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F /* AddrMode */, // 25360FFFFC3C00 + 0xFC, 0xFF /* DstAddr */, 60 /* Duration */, 0x00 /* TCSignificance */) +ZBM(ZBS_PERMITJOINREQ_OPEN_XX, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F /* AddrMode */, // 25360FFFFCFF00 + 0xFC, 0xFF /* DstAddr */, 0xFF /* Duration */, 0x00 /* TCSignificance */) +ZBM(ZBR_PERMITJOINREQ, Z_SRSP | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, Z_Success) // 653600 +ZBM(ZBR_PERMITJOIN_AREQ_CLOSE, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0x00 /* Duration */) // 45CB00 +ZBM(ZBR_PERMITJOIN_AREQ_OPEN_60, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 60 /* Duration */) // 45CB3C +ZBM(ZBR_PERMITJOIN_AREQ_OPEN_FF, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0xFF /* Duration */) // 45CBFF +ZBM(ZBR_PERMITJOIN_AREQ_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND ) // 45CB +ZBM(ZBR_PERMITJOIN_AREQ_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_RSP, 0x00, 0x00 /* srcAddr*/, Z_Success ) // 45B6000000 + +// Filters for ZCL frames +ZBM(ZBR_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) // 4481 +ZBM(ZBR_END_DEVICE_ANNCE_IND, Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND) // 45C1 + +static const Zigbee_Instruction zb_prog[] PROGMEM = { + ZI_LABEL(0) + ZI_NOOP() + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) + ZI_ON_RECV_UNEXPECTED(&Z_Recv_Default) + ZI_WAIT(15000) // wait for 15 seconds for Tasmota to stabilize + ZI_ON_ERROR_GOTO(50) + + ZI_MQTT_STATUS(ZIGBEE_STATUS_BOOT, "Booting") + //ZI_LOG(LOG_LEVEL_INFO, "ZIG: rebooting device") + ZI_SEND(ZBS_RESET) // reboot cc2530 just in case we rebooted ESP8266 but not cc2530 + ZI_WAIT_RECV(5000, ZBR_RESET) // timeout 5s + ZI_WAIT(100) + ZI_LOG(LOG_LEVEL_INFO, "ZIG: checking device configuration") + ZI_SEND(ZBS_ZNPHC) // check value of ZNP Has Configured + ZI_WAIT_RECV(2000, ZBR_ZNPHC) + ZI_WAIT(100) + ZI_SEND(ZBS_VERSION) // check ZNP software version + ZI_WAIT_RECV_FUNC(2000, ZBR_VERSION, &Z_ReceiveCheckVersion) // Check version + ZI_SEND(ZBS_PAN) // check PAN ID + ZI_WAIT_RECV(1000, ZBR_PAN) + ZI_SEND(ZBS_EXTPAN) // check EXT PAN ID + ZI_WAIT_RECV(1000, ZBR_EXTPAN) + ZI_SEND(ZBS_CHANN) // check CHANNEL + ZI_WAIT_RECV(1000, ZBR_CHANN) + ZI_SEND(ZBS_PFGK) // check PFGK + ZI_WAIT_RECV(1000, ZBR_PFGK) + ZI_SEND(ZBS_PFGKEN) // check PFGKEN + ZI_WAIT_RECV(1000, ZBR_PFGKEN) + //ZI_LOG(LOG_LEVEL_INFO, "ZIG: zigbee configuration ok") + // all is good, we can start + + ZI_LABEL(ZIGBEE_LABEL_START) // START ZNP App + ZI_MQTT_STATUS(ZIGBEE_STATUS_STARTING, "Configured, starting coordinator") + //ZI_CALL(&Z_State_Ready, 1) // Now accept incoming messages + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + // Z_ZDO:startupFromApp + //ZI_LOG(LOG_LEVEL_INFO, "ZIG: starting zigbee coordinator") +ZI_SEND(ZBS_STARTUPFROMAPP) // start coordinator + ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) // wait for sync ack of command + ZI_WAIT_UNTIL(5000, AREQ_STARTUPFROMAPP) // wait for async message that coordinator started + ZI_SEND(ZBS_GETDEVICEINFO) // GetDeviceInfo + ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &Z_ReceiveDeviceInfo) + //ZI_WAIT_RECV(2000, ZBR_GETDEVICEINFO) // TODO memorize info + ZI_SEND(ZBS_ZDO_NODEDESCREQ) // Z_ZDO:nodeDescReq + ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ) + ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCRSP) + ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) // Z_ZDO:activeEpReq + ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) + ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_NONE) + ZI_SEND(ZBS_AF_REGISTER01) // Z_AF register for endpoint 01, profile 0x0104 Home Automation + ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) + ZI_SEND(ZBS_AF_REGISTER0B) // Z_AF register for endpoint 0B, profile 0x0104 Home Automation + ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) + // Z_ZDO:nodeDescReq ?? Is is useful to redo it? TODO + // redo Z_ZDO:activeEpReq to check that Ep are available + ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) // Z_ZDO:activeEpReq + ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) + ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_OK) + ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) // Closing the Permit Join + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) // not sure it's useful + //ZI_WAIT_UNTIL(500, ZBR_PERMITJOIN_AREQ_CLOSE) + //ZI_SEND(ZBS_PERMITJOINREQ_OPEN_XX) // Opening Permit Join, normally through command + //ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + //ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) // not sure it's useful + //ZI_WAIT_UNTIL(500, ZBR_PERMITJOIN_AREQ_OPEN_FF) + + ZI_LABEL(ZIGBEE_LABEL_READY) + ZI_MQTT_STATUS(ZIGBEE_STATUS_OK, "Started") + ZI_LOG(LOG_LEVEL_INFO, "ZIG: zigbee device ready, listening...") + ZI_CALL(&Z_State_Ready, 1) // Now accept incoming messages + ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) + ZI_WAIT_FOREVER() + ZI_GOTO(ZIGBEE_LABEL_READY) + + ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE) + //ZI_MQTT_STATUS(ZIGBEE_STATUS_PERMITJOIN_CLOSE, "Disable Pairing mode") + ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) // Closing the Permit Join + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + //ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) // not sure it's useful + //ZI_WAIT_UNTIL(500, ZBR_PERMITJOIN_AREQ_CLOSE) + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60) + //ZI_MQTT_STATUS(ZIGBEE_STATUS_PERMITJOIN_OPEN_60, "Enable Pairing mode for 60 seconds") + ZI_SEND(ZBS_PERMITJOINREQ_OPEN_60) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + //ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) // not sure it's useful + //ZI_WAIT_UNTIL(500, ZBR_PERMITJOIN_AREQ_OPEN_60) + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX) + //ZI_MQTT_STATUS(ZIGBEE_STATUS_PERMITJOIN_OPEN_XX, "Enable Pairing mode until next boot") + ZI_SEND(ZBS_PERMITJOINREQ_OPEN_XX) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + //ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) // not sure it's useful + //ZI_WAIT_UNTIL(500, ZBR_PERMITJOIN_AREQ_OPEN_FF) + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + ZI_LABEL(50) // reformat device + ZI_MQTT_STATUS(ZIGBEE_STATUS_RESET_CONF, "Reseting configuration") + //ZI_LOG(LOG_LEVEL_INFO, "ZIG: zigbee bad configuration of device, doing a factory reset") + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + ZI_SEND(ZBS_FACTRES) // factory reset + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_RESET) // reset device + ZI_WAIT_RECV(5000, ZBR_RESET) + ZI_SEND(ZBS_W_PAN) // write PAN ID + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_EXTPAN) // write EXT PAN ID + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_CHANN) // write CHANNEL + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_LOGTYP) // write Logical Type = coordinator + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_PFGK) // write PRECFGKEY + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_PFGKEN) // write PRECFGKEY Enable + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_WNV_SECMODE) // write Security Mode + ZI_WAIT_RECV(1000, ZBR_WNV_OK) + ZI_SEND(ZBS_W_ZDODCB) // write Z_ZDO Direct CB + ZI_WAIT_RECV(1000, ZBR_W_OK) + // Now mark the device as ready, writing 0x55 in memory slot 0x0F00 + ZI_SEND(ZBS_WNV_INITZNPHC) // Init NV ZNP Has Configured + ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &Z_CheckNVWrite) + ZI_SEND(ZBS_WNV_ZNPHC) // Write NV ZNP Has Configured + ZI_WAIT_RECV(1000, ZBR_WNV_OK) + + //ZI_LOG(LOG_LEVEL_INFO, "ZIG: zigbee device reconfigured") + ZI_GOTO(ZIGBEE_LABEL_START) + + ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION) + ZI_MQTT_STATUS(ZIGBEE_STATUS_UNSUPPORTED_VERSION, "Only ZNP 1.2 is currently supported") + ZI_GOTO(ZIGBEE_LABEL_ABORT) + + ZI_LABEL(ZIGBEE_LABEL_ABORT) // Label 99: abort + ZI_MQTT_STATUS(ZIGBEE_STATUS_ABORT, "Abort") + ZI_LOG(LOG_LEVEL_ERROR, "ZIG: Abort") + ZI_STOP(ZIGBEE_LABEL_ABORT) +}; + +uint8_t ZigbeeGetInstructionSize(uint8_t instr) { // in Zigbee_Instruction lines (words) + if (instr >= ZGB_INSTR_12_BYTES) { + return 3; + } else if (instr >= ZGB_INSTR_8_BYTES) { + return 2; + } else { + return 1; + } +} + +void ZigbeeGotoLabel(uint8_t label) { + // look for the label scanning entire code + uint16_t goto_pc = 0xFFFF; // 0xFFFF means not found + uint8_t cur_instr = 0; + uint8_t cur_d8 = 0; + uint8_t cur_instr_len = 1; // size of current instruction in words + + for (uint32_t i = 0; i < sizeof(zb_prog)/sizeof(zb_prog[0]); i += cur_instr_len) { + const Zigbee_Instruction *cur_instr_line = &zb_prog[i]; + cur_instr = pgm_read_byte(&cur_instr_line->i.i); + cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZGB GOTO: pc %d instr %d"), i, cur_instr); + + if (ZGB_INSTR_LABEL == cur_instr) { + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: found label %d at pc %d"), cur_d8, i); + if (label == cur_d8) { + // label found, goto to this pc + zigbee.pc = i; + zigbee.state_machine = true; + zigbee.state_waiting = false; + return; + } + } + // get instruction length + cur_instr_len = ZigbeeGetInstructionSize(cur_instr); + } + + // no label found, abort + AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Goto label not found, label=%d pc=%d"), label, zigbee.pc); + if (ZIGBEE_LABEL_ABORT != label) { + // if not already looking for ZIGBEE_LABEL_ABORT, goto ZIGBEE_LABEL_ABORT + ZigbeeGotoLabel(ZIGBEE_LABEL_ABORT); + } else { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Label Abort (%d) not present, aborting Zigbee"), ZIGBEE_LABEL_ABORT); + zigbee.state_machine = false; + zigbee.active = false; + } +} + +void ZigbeeStateMachine_Run(void) { + uint8_t cur_instr = 0; + uint8_t cur_d8 = 0; + uint16_t cur_d16 = 0; + const void* cur_ptr1 = nullptr; + const void* cur_ptr2 = nullptr; + uint32_t now = millis(); + + if (zigbee.state_waiting) { // state machine is waiting for external event or timeout + // checking if timeout expired + if ((zigbee.next_timeout) && (now > zigbee.next_timeout)) { // if next_timeout == 0 then wait forever + //AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: timeout occured pc=%d"), zigbee.pc); + if (!zigbee.state_no_timeout) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: timeout, goto label %d"), zigbee.on_timeout_goto); + ZigbeeGotoLabel(zigbee.on_timeout_goto); + } else { + zigbee.state_waiting = false; // simply stop waiting + } + } + } + + while ((zigbee.state_machine) && (!zigbee.state_waiting)) { + // reinit receive filters and functions (they only work for a single instruction) + zigbee.recv_filter = nullptr; + zigbee.recv_func = nullptr; + zigbee.recv_until = false; + zigbee.state_no_timeout = false; // reset the no_timeout for next instruction + + if (zigbee.pc > (sizeof(zb_prog)/sizeof(zb_prog[0]))) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Invalid pc: %d, aborting"), zigbee.pc); + zigbee.pc = -1; + } + if (zigbee.pc < 0) { + zigbee.state_machine = false; + return; + } + + // load current instruction details + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: Executing instruction pc=%d"), zigbee.pc); + const Zigbee_Instruction *cur_instr_line = &zb_prog[zigbee.pc]; + cur_instr = pgm_read_byte(&cur_instr_line->i.i); + cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); + cur_d16 = pgm_read_word(&cur_instr_line->i.d16); + if (cur_instr >= ZGB_INSTR_8_BYTES) { + cur_instr_line++; + cur_ptr1 = cur_instr_line->p; + } + if (cur_instr >= ZGB_INSTR_12_BYTES) { + cur_instr_line++; + cur_ptr2 = cur_instr_line->p; + } + + zigbee.pc += ZigbeeGetInstructionSize(cur_instr); // move pc to next instruction, before any goto + + switch (cur_instr) { + case ZGB_INSTR_NOOP: + case ZGB_INSTR_LABEL: // do nothing + break; + case ZGB_INSTR_GOTO: + ZigbeeGotoLabel(cur_d8); + break; + case ZGB_INSTR_ON_ERROR_GOTO: + zigbee.on_error_goto = cur_d8; + break; + case ZGB_INSTR_ON_TIMEOUT_GOTO: + zigbee.on_timeout_goto = cur_d8; + break; + case ZGB_INSTR_WAIT: + zigbee.next_timeout = now + cur_d16; + zigbee.state_waiting = true; + zigbee.state_no_timeout = true; // do not generate a timeout error when waiting is done + break; + case ZGB_INSTR_WAIT_FOREVER: + zigbee.next_timeout = 0; + zigbee.state_waiting = true; + //zigbee.state_no_timeout = true; // do not generate a timeout error when waiting is done + break; + case ZGB_INSTR_STOP: + zigbee.state_machine = false; + if (cur_d8) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Stopping (%d)"), cur_d8); + } + break; + case ZGB_INSTR_CALL: + if (cur_ptr1) { + uint32_t res; + res = (*((ZB_Func)cur_ptr1))(cur_d8); + if (res > 0) { + ZigbeeGotoLabel(res); + continue; // avoid incrementing PC after goto + } else if (res == 0) { + // do nothing + } else if (res == -1) { + // do nothing + } else { + ZigbeeGotoLabel(zigbee.on_error_goto); + continue; + } + } + break; + case ZGB_INSTR_LOG: + AddLog_P(cur_d8, (char*) cur_ptr1); + break; + case ZGB_INSTR_MQTT_STATUS: + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{\"Status\":%d,\"Message\":\"%s\"}}"), + cur_d8, (char*) cur_ptr1); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); + XdrvRulesProcess(); + break; + case ZGB_INSTR_SEND: + ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 /* len */); + break; + case ZGB_INSTR_WAIT_UNTIL: + zigbee.recv_until = true; // and reuse ZGB_INSTR_WAIT_RECV + case ZGB_INSTR_WAIT_RECV: + zigbee.recv_filter = (uint8_t *) cur_ptr1; + zigbee.recv_filter_len = cur_d8; // len + zigbee.next_timeout = now + cur_d16; + zigbee.state_waiting = true; + break; + case ZGB_ON_RECV_UNEXPECTED: + zigbee.recv_unexpected = (ZB_RecvMsgFunc) cur_ptr1; + break; + case ZGB_INSTR_WAIT_RECV_CALL: + zigbee.recv_filter = (uint8_t *) cur_ptr1; + zigbee.recv_filter_len = cur_d8; // len + zigbee.recv_func = (ZB_RecvMsgFunc) cur_ptr2; + zigbee.next_timeout = now + cur_d16; + zigbee.state_waiting = true; + break; + } + } +} + +#endif // USE_ZIGBEE diff --git a/sonoff/xdrv_23_zigbee_8_parsers.ino b/sonoff/xdrv_23_zigbee_8_parsers.ino new file mode 100644 index 000000000..2a304f8f1 --- /dev/null +++ b/sonoff/xdrv_23_zigbee_8_parsers.ino @@ -0,0 +1,372 @@ +/* + xdrv_23_zigbee.ino - zigbee support for Sonoff-Tasmota + + Copyright (C) 2019 Theo Arends and Stephan Hadinger + + 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_ZIGBEE + +int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) { + // Ex= 6700.00.6263151D004B1200.0000.07.09.02.83869991 + // IEEE Adr (8 bytes) = 0x00124B001D156362 + // Short Addr (2 bytes) = 0x0000 + // Device Type (1 byte) = 0x07 (coord?) + // Device State (1 byte) = 0x09 (coordinator started) + // NumAssocDevices (1 byte) = 0x02 + // List of devices: 0x8683, 0x9199 + Z_IEEEAddress long_adr = buf.get64(3); + Z_ShortAddress short_adr = buf.get16(11); + uint8_t device_type = buf.get8(13); + uint8_t device_state = buf.get8(14); + uint8_t device_associated = buf.get8(15); + + char hex[20]; + Uint64toHex(long_adr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + ",\"DeviceType\":%d,\"DeviceState\":%d" + ",\"NumAssocDevices\":%d"), + ZIGBEE_STATUS_CC_INFO, hex, short_adr, device_type, device_state, + device_associated); + + if (device_associated > 0) { + uint idx = 16; + ResponseAppend_P(PSTR(",\"AssocDevicesList\":[")); + for (uint32_t i = 0; i < device_associated; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(idx)); + idx += 2; + } + ResponseAppend_P(PSTR("]")); + } + + ResponseJsonEnd(); // append '}' + ResponseJsonEnd(); // append '}' + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); + XdrvRulesProcess(); + + return res; +} + +int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf) { + // Check the status after NV Init "ZNP Has Configured" + // Good response should be 610700 or 610709 (Success or Created) + // We only filter the response on 6107 and check the code in this function + uint8_t status = buf.get8(2); + if ((0x00 == status) || (0x09 == status)) { + return 0; // Ok, continue + } else { + return -2; // Error + } +} + +int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { + // check that the version is supported + // typical version for ZNP 1.2 + // 61020200-02.06.03.D9143401.0200000000 + // TranportRev = 02 + // Product = 00 + // MajorRel = 2 + // MinorRel = 6 + // MaintRel = 3 + // Revision = 20190425 d (0x013414D9) + uint8_t major_rel = buf.get8(4); + uint8_t minor_rel = buf.get8(5); + uint8_t maint_rel = buf.get8(6); + uint32_t revision = buf.get32(7); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" + "\"Status\":%d,\"MajorRel\":%d,\"MinorRel\":%d" + ",\"MaintRel\":%d,\"Revision\":%d}}"), + ZIGBEE_STATUS_CC_VERSION, major_rel, minor_rel, + maint_rel, revision); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); + XdrvRulesProcess(); + + if ((0x02 == major_rel) && (0x06 == minor_rel)) { + return 0; // version 2.6.x is ok + } else { + return ZIGBEE_LABEL_UNSUPPORTED_VERSION; // abort + } +} + +bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match) { + if ( (pgm_read_byte(&match[0]) == buf.get8(0)) && + (pgm_read_byte(&match[1]) == buf.get8(1)) ) { + return true; + } else { + return false; + } +} + +int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) { + // we received a PermitJoin status change + uint8_t duration = buf.get8(2); + uint8_t status_code; + const char* message; + + if (0xFF == duration) { + status_code = ZIGBEE_STATUS_PERMITJOIN_OPEN_XX; + message = PSTR("Enable Pairing mode until next boot"); + } else if (duration > 0) { + status_code = ZIGBEE_STATUS_PERMITJOIN_OPEN_60; + message = PSTR("Enable Pairing mode for %d seconds"); + } else { + status_code = ZIGBEE_STATUS_PERMITJOIN_CLOSE; + message = PSTR("Disable Pairing mode"); + } + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" + "\"Status\":%d,\"Message\":\""), + status_code); + ResponseAppend_P(message, duration); + ResponseAppend_P(PSTR("\"}}")); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); + XdrvRulesProcess(); + return -1; +} + +// Send ACTIVE_EP_REQ to collect active endpoints for this address +void Z_SendActiveEpReq(uint16_t shortaddr) { + uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, + Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; + + uint8_t NodeDescReq[] = { Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, + Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; + + ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq)); + //ZigbeeZNPSend(NodeDescReq, sizeof(NodeDescReq)); Not sure this is useful +} + +// Send ZDO_SIMPLE_DESC_REQ to get full list of supported Clusters for a specific endpoint +void Z_SendSimpleDescReq(uint16_t shortaddr, uint8_t endpoint) { + uint8_t SimpleDescReq[] = { Z_SREQ | Z_ZDO, ZDO_SIMPLE_DESC_REQ, // 2504 + Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr), + endpoint }; + + ZigbeeZNPSend(SimpleDescReq, sizeof(SimpleDescReq)); +} + +const char* Z_DeviceType[] = { "Coordinator", "Router", "End Device", "Unknown" }; +int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) { + // Received ZDO_NODE_DESC_RSP + Z_ShortAddress srcAddr = buf.get16(2); + uint8_t status = buf.get8(4); + Z_ShortAddress nwkAddr = buf.get16(5); + uint8_t logicalType = buf.get8(7); + uint8_t apsFlags = buf.get8(8); + uint8_t MACCapabilityFlags = buf.get8(9); + uint16_t manufacturerCapabilities = buf.get16(10); + uint8_t maxBufferSize = buf.get8(12); + uint16_t maxInTransferSize = buf.get16(13); + uint16_t serverMask = buf.get16(15); + uint16_t maxOutTransferSize = buf.get16(17); + uint8_t descriptorCapabilities = buf.get8(19); + + if (0 == status) { + uint8_t deviceType = logicalType & 0x7; // 0=coordinator, 1=router, 2=end device + if (deviceType > 3) { deviceType = 3; } + bool complexDescriptorAvailable = (logicalType & 0x08) ? 1 : 0; + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" + "\"Status\":%d,\"NodeType\":\"%s\",\"ComplexDesc\":%s}}"), + ZIGBEE_STATUS_NODE_DESC, Z_DeviceType[deviceType], + complexDescriptorAvailable ? "true" : "false" + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLRECEIVED)); + XdrvRulesProcess(); + } + + return -1; +} + +int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { + // Received ZDO_ACTIVE_EP_RSP + Z_ShortAddress srcAddr = buf.get16(2); + uint8_t status = buf.get8(4); + Z_ShortAddress nwkAddr = buf.get16(5); + uint8_t activeEpCount = buf.get8(7); + uint8_t* activeEpList = (uint8_t*) buf.charptr(8); + + + for (uint32_t i = 0; i < activeEpCount; i++) { + Z_AddDeviceEndpoint(nwkAddr, activeEpList[i]); + } + + for (uint32_t i = 0; i < activeEpCount; i++) { + Z_SendSimpleDescReq(nwkAddr, activeEpList[i]); + } + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" + "\"Status\":%d,\"ActiveEndpoints\":["), + ZIGBEE_STATUS_ACTIVE_EP); + for (uint32_t i = 0; i < activeEpCount; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%02X\""), activeEpList[i]); + } + ResponseAppend_P(PSTR("]}}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLRECEIVED)); + XdrvRulesProcess(); + return -1; +} + + +int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf) { + // Received ZDO_SIMPLE_DESC_RSP + Z_ShortAddress srcAddr = buf.get16(2); + uint8_t status = buf.get8(4); + Z_ShortAddress nwkAddr = buf.get16(5); + uint8_t lenDescriptor = buf.get8(7); + uint8_t endpoint = buf.get8(8); + uint16_t profileId = buf.get16(9); // The profile Id for this endpoint. + uint16_t deviceId = buf.get16(11); // The Device Description Id for this endpoint. + uint8_t deviceVersion = buf.get8(13); // 0 – Version 1.00 + uint8_t numInCluster = buf.get8(14); + uint8_t numOutCluster = buf.get8(15 + numInCluster*2); + + if (0 == status) { + for (uint32_t i = 0; i < numInCluster; i++) { + Z_AddDeviceCluster(nwkAddr, endpoint, buf.get16(15 + i*2), false); + } + for (uint32_t i = 0; i < numOutCluster; i++) { + Z_AddDeviceCluster(nwkAddr, endpoint, buf.get16(16 + numInCluster*2 + i*2), true); + } + // String dump = Z_DumpDevices(); + // Serial.printf(">>> Devices dump = %s\n", dump.c_str()); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" + "\"Status\":%d,\"Endpoint\":\"0x%02X\"" + ",\"ProfileId\":\"0x%04X\",\"DeviceId\":\"0x%04X\",\"DeviceVerion\":%d" + "\"InClusters\":["), + ZIGBEE_STATUS_SIMPLE_DESC, endpoint, + profileId, deviceId, deviceVersion); + for (uint32_t i = 0; i < numInCluster; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(15 + i*2)); + } + ResponseAppend_P(PSTR("],\"OutClusters\":[")); + for (uint32_t i = 0; i < numOutCluster; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(16 + numInCluster*2 + i*2)); + } + ResponseAppend_P(PSTR("]}}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLRECEIVED)); + XdrvRulesProcess(); + } + return -1; +} + +int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { + Z_ShortAddress srcAddr = buf.get16(2); + Z_ShortAddress nwkAddr = buf.get16(4); + Z_IEEEAddress ieeeAddr = buf.get64(6); + uint8_t capabilities = buf.get8(14); + + Z_AddDeviceLongAddr(nwkAddr, ieeeAddr); +// String dump = Z_DumpDevices(); +// Serial.printf(">>> Devices dump = %s\n", dump.c_str()); + + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + ",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"), + ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr, + (capabilities & 0x04) ? "true" : "false", + (capabilities & 0x08) ? "true" : "false", + (capabilities & 0x40) ? "true" : "false" + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLRECEIVED)); + XdrvRulesProcess(); + Z_SendActiveEpReq(nwkAddr); + return -1; +} + +int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { + uint16_t groupid = buf.get16(2); + uint16_t clusterid = buf.get16(4); + Z_ShortAddress srcaddr = buf.get16(6); + uint8_t srcendpoint = buf.get8(8); + uint8_t dstendpoint = buf.get8(9); + uint8_t wasbroadcast = buf.get8(10); + uint8_t linkquality = buf.get8(11); + uint8_t securityuse = buf.get8(12); + uint32_t timestamp = buf.get32(13); + uint8_t seqnumber = buf.get8(17); + + ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid); + + zcl_received.publishMQTTReceived(groupid, clusterid, srcaddr, + srcendpoint, dstendpoint, wasbroadcast, + linkquality, securityuse, seqnumber, + timestamp); + + char shortaddr[8]; + snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); + + DynamicJsonBuffer jsonBuffer; + JsonObject& json_root = jsonBuffer.createObject(); + JsonObject& json = json_root.createNestedObject(shortaddr); + if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { + zcl_received.parseRawAttributes(json); + } else if (zcl_received.isClusterSpecificCommand()) { + zcl_received.parseClusterSpecificCommand(json); + } + zcl_received.postProcessAttributes(json); + + String msg(""); + msg.reserve(100); + json_root.printTo(msg); + + Response_P(PSTR("%s"), msg.c_str()); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLRECEIVED)); + XdrvRulesProcess(); + return -1; +} + +int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { + // Default message handler for new messages + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: Z_Recv_Default")); + if (zigbee.init_phase) { + // if still during initialization phase, ignore any unexpected message + return -1; // ignore message + } else { + if (Z_ReceiveMatchPrefix(buf, ZBR_AF_INCOMING_MESSAGE)) { + return Z_ReceiveAfIncomingMessage(res, buf); + } else if (Z_ReceiveMatchPrefix(buf, ZBR_END_DEVICE_ANNCE_IND)) { + return Z_ReceiveEndDeviceAnnonce(res, buf); + } else if (Z_ReceiveMatchPrefix(buf, ZBR_PERMITJOIN_AREQ_OPEN_XX)) { + return Z_ReceivePermitJoinStatus(res, buf); + } else if (Z_ReceiveMatchPrefix(buf, AREQ_ZDO_NODEDESCRSP)) { + return Z_ReceiveNodeDesc(res, buf); + } else if (Z_ReceiveMatchPrefix(buf, AREQ_ZDO_ACTIVEEPRSP)) { + return Z_ReceiveActiveEp(res, buf); + } else if (Z_ReceiveMatchPrefix(buf, AREQ_ZDO_SIMPLEDESCRSP)) { + return Z_ReceiveSimpleDesc(res, buf); + } + return -1; + } +} + +int32_t Z_State_Ready(uint8_t value) { + zigbee.init_phase = false; // initialization phase complete + return 0; // continue +} + +#endif // USE_ZIGBEE diff --git a/sonoff/xdrv_23_zigbee_9_impl.ino b/sonoff/xdrv_23_zigbee_9_impl.ino index 14251e04a..d570573c2 100644 --- a/sonoff/xdrv_23_zigbee_9_impl.ino +++ b/sonoff/xdrv_23_zigbee_9_impl.ino @@ -24,21 +24,6 @@ const uint32_t ZIGBEE_BUFFER_SIZE = 256; // Max ZNP frame is SOF+LEN+CMD1+CMD2+250+FCS = 255 const uint8_t ZIGBEE_SOF = 0xFE; -// Status code used for ZigbeeStatus MQTT message -// Ex: {"ZigbeeStatus":{"Status": 3,"Message":"Configured, starting coordinator"}} -const uint8_t ZIGBEE_STATUS_OK = 0; // Zigbee started and working -const uint8_t ZIGBEE_STATUS_BOOT = 1; // CC2530 booting -const uint8_t ZIGBEE_STATUS_RESET_CONF = 2; // Resetting CC2530 configuration -const uint8_t ZIGBEE_STATUS_STARTING = 3; // Starting CC2530 as coordinator -const uint8_t ZIGBEE_STATUS_PERMITJOIN_CLOSE = 20; // Disable PermitJoin -const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_60 = 21; // Enable PermitJoin for 60 seconds -const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_XX = 22; // Enable PermitJoin until next boot -const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; // Device announces its address -const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; // Status: CC2530 ZNP Version -const uint8_t ZIGBEE_STATUS_CC_INFO = 51; // Status: CC2530 Device Configuration -const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version -const uint8_t ZIGBEE_STATUS_ABORT = 99; // Fatal error, Zigbee not working - //#define Z_USE_SOFTWARE_SERIAL #ifdef Z_USE_SOFTWARE_SERIAL @@ -50,793 +35,11 @@ TasmotaSerial *ZigbeeSerial = nullptr; #endif -const char kZigbeeCommands[] PROGMEM = "|" D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN; +const char kZigbeeCommands[] PROGMEM = "|" D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN + "|" D_CMND_ZIGBEE_DUMP; -void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZigbeeZNPSend, &CmndZigbeePermitJoin }; - -typedef int32_t (*ZB_Func)(uint8_t value); -typedef int32_t (*ZB_RecvMsgFunc)(int32_t res, class SBuffer &buf); - -typedef union Zigbee_Instruction { - struct { - uint8_t i; // instruction - uint8_t d8; // 8 bits data - uint16_t d16; // 16 bits data - } i; - const void *p; // pointer - // const void *m; // for type checking only, message - // const ZB_Func f; - // const ZB_RecvMsgFunc fr; -} Zigbee_Instruction; -// -// Zigbee_Instruction z1 = { .i = {1,2,3}}; -// Zigbee_Instruction z3 = { .p = nullptr }; - -typedef struct Zigbee_Instruction_Type { - uint8_t instr; - uint8_t data; -} Zigbee_Instruction_Type; - -enum Zigbee_StateMachine_Instruction_Set { - // 2 bytes instructions - ZGB_INSTR_4_BYTES = 0, - ZGB_INSTR_NOOP = 0, // do nothing - ZGB_INSTR_LABEL, // define a label - ZGB_INSTR_GOTO, // goto label - ZGB_INSTR_ON_ERROR_GOTO, // goto label if error - ZGB_INSTR_ON_TIMEOUT_GOTO, // goto label if timeout - ZGB_INSTR_WAIT, // wait for x ms (in chunks of 100ms) - ZGB_INSTR_WAIT_FOREVER, // wait forever but state machine still active - ZGB_INSTR_STOP, // stop state machine with optional error code - - // 6 bytes instructions - ZGB_INSTR_8_BYTES = 0x80, - ZGB_INSTR_CALL = 0x80, // call a function - ZGB_INSTR_LOG, // log a message, if more detailed logging required, call a function - ZGB_INSTR_MQTT_STATUS, // send MQTT status string with code - ZGB_INSTR_SEND, // send a ZNP message - ZGB_INSTR_WAIT_UNTIL, // wait until the specified message is received, ignore all others - ZGB_INSTR_WAIT_RECV, // wait for a message according to the filter - ZGB_ON_RECV_UNEXPECTED, // function to handle unexpected messages, or nullptr - - // 10 bytes instructions - ZGB_INSTR_12_BYTES = 0xF0, - ZGB_INSTR_WAIT_RECV_CALL, // wait for a filtered message and call function upon receive -}; - -#define ZI_NOOP() { .i = { ZGB_INSTR_NOOP, 0x00, 0x0000} }, -#define ZI_LABEL(x) { .i = { ZGB_INSTR_LABEL, (x), 0x0000} }, -#define ZI_GOTO(x) { .i = { ZGB_INSTR_GOTO, (x), 0x0000} }, -#define ZI_ON_ERROR_GOTO(x) { .i = { ZGB_INSTR_ON_ERROR_GOTO, (x), 0x0000} }, -#define ZI_ON_TIMEOUT_GOTO(x) { .i = { ZGB_INSTR_ON_TIMEOUT_GOTO, (x), 0x0000} }, -#define ZI_WAIT(x) { .i = { ZGB_INSTR_WAIT, 0x00, (x)} }, -#define ZI_WAIT_FOREVER() { .i = { ZGB_INSTR_WAIT_FOREVER, 0x00, 0x0000} }, -#define ZI_STOP(x) { .i = { ZGB_INSTR_STOP, (x), 0x0000} }, - -#define ZI_CALL(f, x) { .i = { ZGB_INSTR_CALL, (x), 0x0000} }, { .p = (const void*)(f) }, -#define ZI_LOG(x, m) { .i = { ZGB_INSTR_LOG, (x), 0x0000 } }, { .p = ((const void*)(m)) }, -#define ZI_MQTT_STATUS(x, m) { .i = { ZGB_INSTR_MQTT_STATUS, (x), 0x0000 } }, { .p = ((const void*)(m)) }, -#define ZI_ON_RECV_UNEXPECTED(f) { .i = { ZGB_ON_RECV_UNEXPECTED, 0x00, 0x0000} }, { .p = (const void*)(f) }, -#define ZI_SEND(m) { .i = { ZGB_INSTR_SEND, sizeof(m), 0x0000} }, { .p = (const void*)(m) }, -#define ZI_WAIT_RECV(x, m) { .i = { ZGB_INSTR_WAIT_RECV, sizeof(m), (x)} }, { .p = (const void*)(m) }, -#define ZI_WAIT_UNTIL(x, m) { .i = { ZGB_INSTR_WAIT_UNTIL, sizeof(m), (x)} }, { .p = (const void*)(m) }, -#define ZI_WAIT_RECV_FUNC(x, m, f) { .i = { ZGB_INSTR_WAIT_RECV_CALL, sizeof(m), (x)} }, { .p = (const void*)(m) }, { .p = (const void*)(f) }, - -// Labels used in the State Machine -- internal only -const uint8_t ZIGBEE_LABEL_START = 10; // Start ZNP -const uint8_t ZIGBEE_LABEL_READY = 20; // goto label 20 for main loop -const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; // main loop -const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_CLOSE = 30; // disable permit join -const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60 = 31; // enable permit join for 60 seconds -const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX = 32; // enable permit join for 60 seconds -// errors -const uint8_t ZIGBEE_LABEL_ABORT = 99; // goto label 99 in case of fatal error -const uint8_t ZIGBEE_LABEL_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version - -struct ZigbeeStatus { - bool active = true; // is Zigbee active for this device, i.e. GPIOs configured - bool state_machine = false; // the state machine is running - bool state_waiting = false; // the state machine is waiting for external event or timeout - bool state_no_timeout = false; // the current wait loop does not generate a timeout but only continues running - bool ready = false; // cc2530 initialization is complet, ready to operate - uint8_t on_error_goto = ZIGBEE_LABEL_ABORT; // on error goto label, 99 default to abort - uint8_t on_timeout_goto = ZIGBEE_LABEL_ABORT; // on timeout goto label, 99 default to abort - int16_t pc = 0; // program counter, -1 means abort - uint32_t next_timeout = 0; // millis for the next timeout - - uint8_t *recv_filter = nullptr; // receive filter message - bool recv_until = false; // ignore all messages until the received frame fully matches - size_t recv_filter_len = 0; - ZB_RecvMsgFunc recv_func = nullptr; // function to call when message is expected - ZB_RecvMsgFunc recv_unexpected = nullptr; // function called when unexpected message is received - - bool init_phase = true; // initialization phase, before accepting zigbee traffic -}; -struct ZigbeeStatus zigbee; - -SBuffer *zigbee_buffer = nullptr; - -/*********************************************************************************************\ - * State Machine -\*********************************************************************************************/ - -#define Z_B0(a) (uint8_t)( ((a) ) & 0xFF ) -#define Z_B1(a) (uint8_t)( ((a) >> 8) & 0xFF ) -#define Z_B2(a) (uint8_t)( ((a) >> 16) & 0xFF ) -#define Z_B3(a) (uint8_t)( ((a) >> 24) & 0xFF ) -#define Z_B4(a) (uint8_t)( ((a) >> 32) & 0xFF ) -#define Z_B5(a) (uint8_t)( ((a) >> 40) & 0xFF ) -#define Z_B6(a) (uint8_t)( ((a) >> 48) & 0xFF ) -#define Z_B7(a) (uint8_t)( ((a) >> 56) & 0xFF ) -// Macro to define message to send and receive -#define ZBM(n, x...) const uint8_t n[] PROGMEM = { x }; - -#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL)) - -// ZBS_* Zigbee Send -// ZBR_* Zigbee Recv -ZBM(ZBS_RESET, Z_AREQ | Z_SYS, SYS_RESET, 0x00 ) // 410001 SYS_RESET_REQ Hardware reset -ZBM(ZBR_RESET, Z_AREQ | Z_SYS, SYS_RESET_IND ) // 4180 SYS_RESET_REQ Hardware reset response - -ZBM(ZBS_VERSION, Z_SREQ | Z_SYS, SYS_VERSION ) // 2102 Z_SYS:version -ZBM(ZBR_VERSION, Z_SRSP | Z_SYS, SYS_VERSION ) // 6102 Z_SYS:version - -// Check if ZNP_HAS_CONFIGURED is set -ZBM(ZBS_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, 0x00 /* offset */ ) // 2108000F00 - 6108000155 -ZBM(ZBR_ZNPHC, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_Success, 0x01 /* len */, 0x55) // 6108000155 -// If not set, the response is 61-08-02-00 = Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_InvalidParameter, 0x00 /* len */ - -ZBM(ZBS_PAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PANID ) // 260483 -ZBM(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PANID, 0x02 /* len */, - Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) // 6604008302xxxx - -ZBM(ZBS_EXTPAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_EXTENDED_PAN_ID ) // 26042D -ZBM(ZBR_EXTPAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_EXTENDED_PAN_ID, - 0x08 /* len */, - Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), - Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID), - ) // 6604002D08xxxxxxxxxxxxxxxx - -ZBM(ZBS_CHANN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_CHANLIST ) // 260484 -ZBM(ZBR_CHANN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_CHANLIST, - 0x04 /* len */, - Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), - ) // 6604008404xxxxxxxx - -ZBM(ZBS_PFGK, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEY ) // 260462 -ZBM(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEY, - 0x10 /* len */, - Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), - Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), - Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), - Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), - /*0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, - 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0D*/ ) // 660400621001030507090B0D0F00020406080A0C0D - -ZBM(ZBS_PFGKEN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEYS_ENABLE ) // 260463 -ZBM(ZBR_PFGKEN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEYS_ENABLE, - 0x01 /* len */, 0x00 ) // 660400630100 - -// commands to "format" the device -// Write configuration - write success -ZBM(ZBR_W_OK, Z_SRSP | Z_SAPI, SAPI_WRITE_CONFIGURATION, Z_Success ) // 660500 - Write Configuration -ZBM(ZBR_WNV_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_WRITE, Z_Success ) // 610900 - NV Write - -// Factory reset -ZBM(ZBS_FACTRES, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 /* len */, 0x02 ) // 2605030102 -// Write PAN ID -ZBM(ZBS_W_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 /* len */, Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) // 26058302xxxx -// Write EXT PAN ID -ZBM(ZBS_W_EXTPAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_EXTENDED_PAN_ID, 0x08 /* len */, - Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), - Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID) - ) // 26052D086263151D004B1200 -// Write Channel ID -ZBM(ZBS_W_CHANN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_CHANLIST, 0x04 /* len */, - Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), - /*0x00, 0x08, 0x00, 0x00*/ ) // 26058404xxxxxxxx -// Write Logical Type = 00 = coordinator -ZBM(ZBS_W_LOGTYP, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 /* len */, 0x00 ) // 2605870100 -// Write precfgkey -ZBM(ZBS_W_PFGK, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEY, - 0x10 /* len */, - Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), - Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), - Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), - Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), - /*0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, - 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0D*/ ) // 2605621001030507090B0D0F00020406080A0C0D -// Write precfgkey enable -ZBM(ZBS_W_PFGKEN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEYS_ENABLE, 0x01 /* len */, 0x00 ) // 2605630100 -// Write Security Mode -ZBM(ZBS_WNV_SECMODE, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(CONF_TCLK_TABLE_START), Z_B1(CONF_TCLK_TABLE_START), - 0x00 /* offset */, 0x20 /* len */, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x5a, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6c, - 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) // 2109010100200FFFFFFFFFFFFFFFF5A6967426565416C6C69616E636530390000000000000000 -// Write Z_ZDO Direct CB -ZBM(ZBS_W_ZDODCB, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_ZDO_DIRECT_CB, 0x01 /* len */, 0x01 ) // 26058F0101 -// NV Init ZNP Has Configured -ZBM(ZBS_WNV_INITZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_ITEM_INIT, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, - 0x01, 0x00 /* InitLen 16 bits */, 0x01 /* len */, 0x00 ) // 2107000F01000100 - 610709 -// Init succeeded -//ZBM(ZBR_WNV_INIT_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_ITEM_INIT, Z_Created ) // 610709 - NV Write -ZBM(ZBR_WNV_INIT_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_ITEM_INIT ) // 6107xx, Success if 610700 or 610709 - NV Write - -// Write ZNP Has Configured -ZBM(ZBS_WNV_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(ZNP_HAS_CONFIGURED), Z_B1(ZNP_HAS_CONFIGURED), - 0x00 /* offset */, 0x01 /* len */, 0x55 ) // 2109000F000155 - 610900 -// Z_ZDO:startupFromApp -ZBM(ZBS_STARTUPFROMAPP, Z_SREQ | Z_ZDO, ZDO_STARTUP_FROM_APP, 100, 0 /* delay */) // 25406400 -ZBM(ZBR_STARTUPFROMAPP, Z_SRSP | Z_ZDO, ZDO_STARTUP_FROM_APP ) // 6540 + 01 for new network, 00 for exisitng network, 02 for error -ZBM(AREQ_STARTUPFROMAPP, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ZB_COORD ) // 45C009 + 08 = starting, 09 = started -// GetDeviceInfo -ZBM(ZBS_GETDEVICEINFO, Z_SREQ | Z_UTIL, Z_UTIL_GET_DEVICE_INFO ) // 2700 -ZBM(ZBR_GETDEVICEINFO, Z_SRSP | Z_UTIL, Z_UTIL_GET_DEVICE_INFO, Z_Success ) // Ex= 6700.00.6263151D004B1200.0000.07.09.00 - // IEEE Adr (8 bytes) = 6263151D004B1200 - // Short Addr (2 bytes) = 0000 - // Device Type (1 byte) = 07 (coord?) - // Device State (1 byte) = 09 (coordinator started) - // NumAssocDevices (1 byte) = 00 - -// Read Pan ID -//ZBM(ZBS_READ_NV_PANID, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, PANID & 0xFF, PANID >> 8, 0x00 /* offset */ ) // 2108830000 - -// Z_ZDO:nodeDescReq -ZBM(ZBS_ZDO_NODEDESCREQ, Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, 0x00, 0x00 /* dst addr */, 0x00, 0x00 /* NWKAddrOfInterest */) // 250200000000 -ZBM(ZBR_ZDO_NODEDESCREQ, Z_SRSP | Z_ZDO, ZDO_NODE_DESC_REQ, Z_Success ) // 650200 -// Async resp ex: 4582.0000.00.0000.00.40.8F.0000.50.A000.0100.A000.00 -ZBM(AREQ_ZDO_NODEDESCREQ, Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP) // 4582 -// SrcAddr (2 bytes) 0000 -// Status (1 byte) 00 Success -// NwkAddr (2 bytes) 0000 -// LogicalType (1 byte) - 00 Coordinator -// APSFlags (1 byte) - 40 0=APSFlags 4=NodeFreqBands -// MACCapabilityFlags (1 byte) - 8F ALL -// ManufacturerCode (2 bytes) - 0000 -// MaxBufferSize (1 byte) - 50 NPDU -// MaxTransferSize (2 bytes) - A000 = 160 -// ServerMask (2 bytes) - 0100 - Primary Trust Center -// MaxOutTransferSize (2 bytes) - A000 = 160 -// DescriptorCapabilities (1 byte) - 00 - -// Z_ZDO:activeEpReq -ZBM(ZBS_ZDO_ACTIVEEPREQ, Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, 0x00, 0x00, 0x00, 0x00) // 250500000000 -ZBM(ZBR_ZDO_ACTIVEEPREQ, Z_SRSP | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_Success) // 65050000 -ZBM(ZBR_ZDO_ACTIVEEPRSP_NONE, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 /* srcAddr */, Z_Success, - 0x00, 0x00 /* nwkaddr */, 0x00 /* activeepcount */) // 45050000 - no Ep running -ZBM(ZBR_ZDO_ACTIVEEPRSP_OK, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 /* srcAddr */, Z_Success, - 0x00, 0x00 /* nwkaddr */, 0x02 /* activeepcount */, 0x0B, 0x01 /* the actual endpoints */) // 25050000 - no Ep running - -// Z_AF:register profile:104, ep:01 -ZBM(ZBS_AF_REGISTER01, Z_SREQ | Z_AF, AF_REGISTER, 0x01 /* endpoint */, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), // 24000401050000000000 - 0x05, 0x00 /* AppDeviceId */, 0x00 /* AppDevVer */, 0x00 /* LatencyReq */, - 0x00 /* AppNumInClusters */, 0x00 /* AppNumInClusters */) -ZBM(ZBR_AF_REGISTER, Z_SRSP | Z_AF, AF_REGISTER, Z_Success) // 640000 -ZBM(ZBS_AF_REGISTER0B, Z_SREQ | Z_AF, AF_REGISTER, 0x0B /* endpoint */, Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), // 2400040B050000000000 - 0x05, 0x00 /* AppDeviceId */, 0x00 /* AppDevVer */, 0x00 /* LatencyReq */, - 0x00 /* AppNumInClusters */, 0x00 /* AppNumInClusters */) -// Z_ZDO:mgmtPermitJoinReq -ZBM(ZBS_PERMITJOINREQ_CLOSE, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x02 /* AddrMode */, // 25360200000000 - 0x00, 0x00 /* DstAddr */, 0x00 /* Duration */, 0x00 /* TCSignificance */) -ZBM(ZBS_PERMITJOINREQ_OPEN_60, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F /* AddrMode */, // 25360FFFFC3C00 - 0xFC, 0xFF /* DstAddr */, 60 /* Duration */, 0x00 /* TCSignificance */) -ZBM(ZBS_PERMITJOINREQ_OPEN_XX, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F /* AddrMode */, // 25360FFFFCFF00 - 0xFC, 0xFF /* DstAddr */, 0xFF /* Duration */, 0x00 /* TCSignificance */) -ZBM(ZBR_PERMITJOINREQ, Z_SRSP | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, Z_Success) // 653600 -ZBM(ZBR_PERMITJOIN_AREQ_CLOSE, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0x00 /* Duration */) // 45CB00 -ZBM(ZBR_PERMITJOIN_AREQ_OPEN_60, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 60 /* Duration */) // 45CB3C -ZBM(ZBR_PERMITJOIN_AREQ_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0xFF /* Duration */) // 45CBFF -ZBM(ZBR_PERMITJOIN_AREQ_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_RSP, 0x00, 0x00 /* srcAddr*/, Z_Success ) // 45B6000000 - -// Filters for ZCL frames -ZBM(ZBR_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) // 4481 -ZBM(ZBR_END_DEVICE_ANNCE_IND, Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND) // 45C1 - -static const Zigbee_Instruction zb_prog[] PROGMEM = { - ZI_LABEL(0) - ZI_NOOP() - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) - ZI_ON_RECV_UNEXPECTED(&Z_Recv_Default) - ZI_WAIT(15000) // wait for 15 seconds for Tasmota to stabilize - ZI_ON_ERROR_GOTO(50) - - ZI_MQTT_STATUS(ZIGBEE_STATUS_BOOT, "Booting") - //ZI_LOG(LOG_LEVEL_INFO, "ZIG: rebooting device") - ZI_SEND(ZBS_RESET) // reboot cc2530 just in case we rebooted ESP8266 but not cc2530 - ZI_WAIT_RECV(5000, ZBR_RESET) // timeout 5s - ZI_LOG(LOG_LEVEL_INFO, "ZIG: checking device configuration") - ZI_SEND(ZBS_ZNPHC) // check value of ZNP Has Configured - ZI_WAIT_RECV(2000, ZBR_ZNPHC) - ZI_SEND(ZBS_VERSION) // check ZNP software version - ZI_WAIT_RECV_FUNC(2000, ZBR_VERSION, &Z_ReceiveCheckVersion) // Check version - ZI_SEND(ZBS_PAN) // check PAN ID - ZI_WAIT_RECV(1000, ZBR_PAN) - ZI_SEND(ZBS_EXTPAN) // check EXT PAN ID - ZI_WAIT_RECV(1000, ZBR_EXTPAN) - ZI_SEND(ZBS_CHANN) // check CHANNEL - ZI_WAIT_RECV(1000, ZBR_CHANN) - ZI_SEND(ZBS_PFGK) // check PFGK - ZI_WAIT_RECV(1000, ZBR_PFGK) - ZI_SEND(ZBS_PFGKEN) // check PFGKEN - ZI_WAIT_RECV(1000, ZBR_PFGKEN) - //ZI_LOG(LOG_LEVEL_INFO, "ZIG: zigbee configuration ok") - // all is good, we can start - - ZI_LABEL(ZIGBEE_LABEL_START) // START ZNP App - ZI_MQTT_STATUS(ZIGBEE_STATUS_STARTING, "Configured, starting coordinator") - //ZI_CALL(&Z_State_Ready, 1) // Now accept incoming messages - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - // Z_ZDO:startupFromApp - //ZI_LOG(LOG_LEVEL_INFO, "ZIG: starting zigbee coordinator") -ZI_SEND(ZBS_STARTUPFROMAPP) // start coordinator - ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) // wait for sync ack of command - ZI_WAIT_UNTIL(5000, AREQ_STARTUPFROMAPP) // wait for async message that coordinator started - ZI_SEND(ZBS_GETDEVICEINFO) // GetDeviceInfo - ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &Z_ReceiveDeviceInfo) - //ZI_WAIT_RECV(2000, ZBR_GETDEVICEINFO) // TODO memorize info - ZI_SEND(ZBS_ZDO_NODEDESCREQ) // Z_ZDO:nodeDescReq - ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ) - ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCREQ) - ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) // Z_ZDO:activeEpReq - ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) - ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_NONE) - ZI_SEND(ZBS_AF_REGISTER01) // Z_AF register for endpoint 01, profile 0x0104 Home Automation - ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) - ZI_SEND(ZBS_AF_REGISTER0B) // Z_AF register for endpoint 0B, profile 0x0104 Home Automation - ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) - // Z_ZDO:nodeDescReq ?? Is is useful to redo it? TODO - // redo Z_ZDO:activeEpReq to check that Ep are available - ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) // Z_ZDO:activeEpReq - ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) - ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_OK) - ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) // Closing the Permit Join - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) // not sure it's useful - //ZI_WAIT_UNTIL(500, ZBR_PERMITJOIN_AREQ_CLOSE) - //ZI_SEND(ZBS_PERMITJOINREQ_OPEN_XX) // Opening Permit Join, normally through command - //ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - //ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) // not sure it's useful - //ZI_WAIT_UNTIL(500, ZBR_PERMITJOIN_AREQ_OPEN_XX) - - ZI_LABEL(ZIGBEE_LABEL_READY) - ZI_MQTT_STATUS(ZIGBEE_STATUS_OK, "Started") - ZI_LOG(LOG_LEVEL_INFO, "ZIG: zigbee device ready, listening...") - ZI_CALL(&Z_State_Ready, 1) // Now accept incoming messages - ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) - ZI_WAIT_FOREVER() - ZI_GOTO(ZIGBEE_LABEL_READY) - - ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE) - ZI_MQTT_STATUS(ZIGBEE_STATUS_PERMITJOIN_CLOSE, "Disable Pairing mode") - ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) // Closing the Permit Join - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - //ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) // not sure it's useful - //ZI_WAIT_UNTIL(500, ZBR_PERMITJOIN_AREQ_CLOSE) - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60) - ZI_MQTT_STATUS(ZIGBEE_STATUS_PERMITJOIN_OPEN_60, "Enable Pairing mode for 60 seconds") - ZI_SEND(ZBS_PERMITJOINREQ_OPEN_60) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - //ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) // not sure it's useful - //ZI_WAIT_UNTIL(500, ZBR_PERMITJOIN_AREQ_OPEN_60) - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX) - ZI_MQTT_STATUS(ZIGBEE_STATUS_PERMITJOIN_OPEN_XX, "Enable Pairing mode until next boot") - ZI_SEND(ZBS_PERMITJOINREQ_OPEN_XX) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - //ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) // not sure it's useful - //ZI_WAIT_UNTIL(500, ZBR_PERMITJOIN_AREQ_OPEN_XX) - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - ZI_LABEL(50) // reformat device - ZI_MQTT_STATUS(ZIGBEE_STATUS_RESET_CONF, "Reseting configuration") - //ZI_LOG(LOG_LEVEL_INFO, "ZIG: zigbee bad configuration of device, doing a factory reset") - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - ZI_SEND(ZBS_FACTRES) // factory reset - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_RESET) // reset device - ZI_WAIT_RECV(5000, ZBR_RESET) - ZI_SEND(ZBS_W_PAN) // write PAN ID - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_EXTPAN) // write EXT PAN ID - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_CHANN) // write CHANNEL - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_LOGTYP) // write Logical Type = coordinator - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_PFGK) // write PRECFGKEY - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_PFGKEN) // write PRECFGKEY Enable - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_WNV_SECMODE) // write Security Mode - ZI_WAIT_RECV(1000, ZBR_WNV_OK) - ZI_SEND(ZBS_W_ZDODCB) // write Z_ZDO Direct CB - ZI_WAIT_RECV(1000, ZBR_W_OK) - // Now mark the device as ready, writing 0x55 in memory slot 0x0F00 - ZI_SEND(ZBS_WNV_INITZNPHC) // Init NV ZNP Has Configured - ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &Z_CheckNVWrite) - ZI_SEND(ZBS_WNV_ZNPHC) // Write NV ZNP Has Configured - ZI_WAIT_RECV(1000, ZBR_WNV_OK) - - //ZI_LOG(LOG_LEVEL_INFO, "ZIG: zigbee device reconfigured") - ZI_GOTO(ZIGBEE_LABEL_START) - - ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION) - ZI_MQTT_STATUS(ZIGBEE_STATUS_UNSUPPORTED_VERSION, "Only ZNP 1.2 is currently supported") - ZI_GOTO(ZIGBEE_LABEL_ABORT) - - ZI_LABEL(ZIGBEE_LABEL_ABORT) // Label 99: abort - ZI_MQTT_STATUS(ZIGBEE_STATUS_ABORT, "Abort") - ZI_LOG(LOG_LEVEL_ERROR, "ZIG: Abort") - ZI_STOP(ZIGBEE_LABEL_ABORT) -}; - -int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) { - // Ex= 6700.00.6263151D004B1200.0000.07.09.02.83869991 - // IEEE Adr (8 bytes) = 0x00124B001D156362 - // Short Addr (2 bytes) = 0x0000 - // Device Type (1 byte) = 0x07 (coord?) - // Device State (1 byte) = 0x09 (coordinator started) - // NumAssocDevices (1 byte) = 0x02 - // List of devices: 0x8683, 0x9199 - Z_IEEEAddress long_adr = buf.get64(3); - Z_ShortAddress short_adr = buf.get16(11); - uint8_t device_type = buf.get8(13); - uint8_t device_state = buf.get8(14); - uint8_t device_associated = buf.get8(15); - - char hex[20]; - Uint64toHex(long_adr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - ",\"DeviceType\":%d,\"DeviceState\":%d" - ",\"NumAssocDevices\":%d"), - ZIGBEE_STATUS_CC_INFO, hex, short_adr, device_type, device_state, - device_associated); - - if (device_associated > 0) { - uint idx = 16; - ResponseAppend_P(PSTR(",\"AssocDevicesList\":[")); - for (uint32_t i = 0; i < device_associated; i++) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(idx)); - idx += 2; - } - ResponseAppend_P(PSTR("]")); - } - - ResponseJsonEnd(); // append '}' - ResponseJsonEnd(); // append '}' - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); - XdrvRulesProcess(); - - return res; -} - -int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf) { - // Check the status after NV Init "ZNP Has Configured" - // Good response should be 610700 or 610709 (Success or Created) - // We only filter the response on 6107 and check the code in this function - uint8_t status = buf.get8(2); - if ((0x00 == status) || (0x09 == status)) { - return 0; // Ok, continue - } else { - return -2; // Error - } -} - -int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { - // check that the version is supported - // typical version for ZNP 1.2 - // 61020200-02.06.03.D9143401.0200000000 - // TranportRev = 02 - // Product = 00 - // MajorRel = 2 - // MinorRel = 6 - // MaintRel = 3 - // Revision = 20190425 d (0x013414D9) - uint8_t major_rel = buf.get8(4); - uint8_t minor_rel = buf.get8(5); - uint8_t maint_rel = buf.get8(6); - uint32_t revision = buf.get32(7); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" - "\"Status\":%d,\"MajorRel\":%d,\"MinorRel\":%d" - ",\"MaintRel\":%d,\"Revision\":%d}}"), - ZIGBEE_STATUS_CC_VERSION, major_rel, minor_rel, - maint_rel, revision); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); - XdrvRulesProcess(); - - if ((0x02 == major_rel) && (0x06 == minor_rel)) { - return 0; // version 2.6.x is ok - } else { - return ZIGBEE_LABEL_UNSUPPORTED_VERSION; // abort - } -} - -bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match) { - if ( (pgm_read_byte(&match[0]) == buf.get8(0)) && - (pgm_read_byte(&match[1]) == buf.get8(1)) ) { - return true; - } else { - return false; - } -} - -int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { - Z_ShortAddress srcAddr = buf.get16(2); - Z_ShortAddress nwkAddr = buf.get16(4); - Z_IEEEAddress ieeeAddr = buf.get64(6); - uint8_t capabilities = buf.get8(14); - - char hex[20]; - Uint64toHex(ieeeAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - ",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"), - ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr, - (capabilities & 0x04) ? "true" : "false", - (capabilities & 0x08) ? "true" : "false", - (capabilities & 0x40) ? "true" : "false" - ); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLRECEIVED)); - XdrvRulesProcess(); - return -1; -} - -int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { - uint16_t groupid = buf.get16(2); - uint16_t clusterid = buf.get16(4); - Z_ShortAddress srcaddr = buf.get16(6); - uint8_t srcendpoint = buf.get8(8); - uint8_t dstendpoint = buf.get8(9); - uint8_t wasbroadcast = buf.get8(10); - uint8_t linkquality = buf.get8(11); - uint8_t securityuse = buf.get8(12); - uint32_t timestamp = buf.get32(13); - uint8_t seqnumber = buf.get8(17); - - ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid); - - zcl_received.publishMQTTReceived(groupid, clusterid, srcaddr, - srcendpoint, dstendpoint, wasbroadcast, - linkquality, securityuse, seqnumber, - timestamp); - - char shortaddr[8]; - snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); - - DynamicJsonBuffer jsonBuffer; - JsonObject& json_root = jsonBuffer.createObject(); - JsonObject& json = json_root.createNestedObject(shortaddr); - if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { - zcl_received.parseRawAttributes(json); - } else if (zcl_received.isClusterSpecificCommand()) { - zcl_received.parseClusterSpecificCommand(json); - } - zcl_received.postProcessAttributes(json); - - String msg(""); - msg.reserve(100); - json_root.printTo(msg); - - Response_P(PSTR("%s"), msg.c_str()); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLRECEIVED)); - XdrvRulesProcess(); - return -1; -} - -int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { - // Default message handler for new messages - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: Z_Recv_Default")); - if (zigbee.init_phase) { - // if still during initialization phase, ignore any unexpected message - return -1; // ignore message - } else { - if (Z_ReceiveMatchPrefix(buf, ZBR_AF_INCOMING_MESSAGE)) { - return Z_ReceiveAfIncomingMessage(res, buf); - } else if (Z_ReceiveMatchPrefix(buf, ZBR_END_DEVICE_ANNCE_IND)) { - return Z_ReceiveEndDeviceAnnonce(res, buf); - } - return -1; - } -} - -int32_t Z_State_Ready(uint8_t value) { - zigbee.init_phase = false; // initialization phase complete - return 0; // continue -} - -uint8_t ZigbeeGetInstructionSize(uint8_t instr) { // in Zigbee_Instruction lines (words) - if (instr >= ZGB_INSTR_12_BYTES) { - return 3; - } else if (instr >= ZGB_INSTR_8_BYTES) { - return 2; - } else { - return 1; - } -} - -void ZigbeeGotoLabel(uint8_t label) { - // look for the label scanning entire code - uint16_t goto_pc = 0xFFFF; // 0xFFFF means not found - uint8_t cur_instr = 0; - uint8_t cur_d8 = 0; - uint8_t cur_instr_len = 1; // size of current instruction in words - - for (uint32_t i = 0; i < sizeof(zb_prog)/sizeof(zb_prog[0]); i += cur_instr_len) { - const Zigbee_Instruction *cur_instr_line = &zb_prog[i]; - cur_instr = pgm_read_byte(&cur_instr_line->i.i); - cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); - //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZGB GOTO: pc %d instr %d"), i, cur_instr); - - if (ZGB_INSTR_LABEL == cur_instr) { - //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: found label %d at pc %d"), cur_d8, i); - if (label == cur_d8) { - // label found, goto to this pc - zigbee.pc = i; - zigbee.state_machine = true; - zigbee.state_waiting = false; - return; - } - } - // get instruction length - cur_instr_len = ZigbeeGetInstructionSize(cur_instr); - } - - // no label found, abort - AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Goto label not found, label=%d pc=%d"), label, zigbee.pc); - if (ZIGBEE_LABEL_ABORT != label) { - // if not already looking for ZIGBEE_LABEL_ABORT, goto ZIGBEE_LABEL_ABORT - ZigbeeGotoLabel(ZIGBEE_LABEL_ABORT); - } else { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Label Abort (%d) not present, aborting Zigbee"), ZIGBEE_LABEL_ABORT); - zigbee.state_machine = false; - zigbee.active = false; - } -} - -void ZigbeeStateMachine_Run(void) { - uint8_t cur_instr = 0; - uint8_t cur_d8 = 0; - uint16_t cur_d16 = 0; - const void* cur_ptr1 = nullptr; - const void* cur_ptr2 = nullptr; - uint32_t now = millis(); - - if (zigbee.state_waiting) { // state machine is waiting for external event or timeout - // checking if timeout expired - if ((zigbee.next_timeout) && (now > zigbee.next_timeout)) { // if next_timeout == 0 then wait forever - //AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: timeout occured pc=%d"), zigbee.pc); - if (!zigbee.state_no_timeout) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZIG: timeout, goto label %d"), zigbee.on_timeout_goto); - ZigbeeGotoLabel(zigbee.on_timeout_goto); - } else { - zigbee.state_waiting = false; // simply stop waiting - } - } - } - - while ((zigbee.state_machine) && (!zigbee.state_waiting)) { - // reinit receive filters and functions (they only work for a single instruction) - zigbee.recv_filter = nullptr; - zigbee.recv_func = nullptr; - zigbee.recv_until = false; - zigbee.state_no_timeout = false; // reset the no_timeout for next instruction - - if (zigbee.pc > (sizeof(zb_prog)/sizeof(zb_prog[0]))) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Invalid pc: %d, aborting"), zigbee.pc); - zigbee.pc = -1; - } - if (zigbee.pc < 0) { - zigbee.state_machine = false; - return; - } - - // load current instruction details - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: Executing instruction pc=%d"), zigbee.pc); - const Zigbee_Instruction *cur_instr_line = &zb_prog[zigbee.pc]; - cur_instr = pgm_read_byte(&cur_instr_line->i.i); - cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); - cur_d16 = pgm_read_word(&cur_instr_line->i.d16); - if (cur_instr >= ZGB_INSTR_8_BYTES) { - cur_instr_line++; - cur_ptr1 = cur_instr_line->p; - } - if (cur_instr >= ZGB_INSTR_12_BYTES) { - cur_instr_line++; - cur_ptr2 = cur_instr_line->p; - } - - zigbee.pc += ZigbeeGetInstructionSize(cur_instr); // move pc to next instruction, before any goto - - switch (cur_instr) { - case ZGB_INSTR_NOOP: - case ZGB_INSTR_LABEL: // do nothing - break; - case ZGB_INSTR_GOTO: - ZigbeeGotoLabel(cur_d8); - break; - case ZGB_INSTR_ON_ERROR_GOTO: - zigbee.on_error_goto = cur_d8; - break; - case ZGB_INSTR_ON_TIMEOUT_GOTO: - zigbee.on_timeout_goto = cur_d8; - break; - case ZGB_INSTR_WAIT: - zigbee.next_timeout = now + cur_d16; - zigbee.state_waiting = true; - zigbee.state_no_timeout = true; // do not generate a timeout error when waiting is done - break; - case ZGB_INSTR_WAIT_FOREVER: - zigbee.next_timeout = 0; - zigbee.state_waiting = true; - //zigbee.state_no_timeout = true; // do not generate a timeout error when waiting is done - break; - case ZGB_INSTR_STOP: - zigbee.state_machine = false; - if (cur_d8) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("ZIG: Stopping (%d)"), cur_d8); - } - break; - case ZGB_INSTR_CALL: - if (cur_ptr1) { - uint32_t res; - res = (*((ZB_Func)cur_ptr1))(cur_d8); - if (res > 0) { - ZigbeeGotoLabel(res); - continue; // avoid incrementing PC after goto - } else if (res == 0) { - // do nothing - } else if (res == -1) { - // do nothing - } else { - ZigbeeGotoLabel(zigbee.on_error_goto); - continue; - } - } - break; - case ZGB_INSTR_LOG: - AddLog_P(cur_d8, (char*) cur_ptr1); - break; - case ZGB_INSTR_MQTT_STATUS: - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATUS "\":{\"Status\":%d,\"Message\":\"%s\"}}"), - cur_d8, (char*) cur_ptr1); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATUS)); - XdrvRulesProcess(); - break; - case ZGB_INSTR_SEND: - ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 /* len */); - break; - case ZGB_INSTR_WAIT_UNTIL: - zigbee.recv_until = true; // and reuse ZGB_INSTR_WAIT_RECV - case ZGB_INSTR_WAIT_RECV: - zigbee.recv_filter = (uint8_t *) cur_ptr1; - zigbee.recv_filter_len = cur_d8; // len - zigbee.next_timeout = now + cur_d16; - zigbee.state_waiting = true; - break; - case ZGB_ON_RECV_UNEXPECTED: - zigbee.recv_unexpected = (ZB_RecvMsgFunc) cur_ptr1; - break; - case ZGB_INSTR_WAIT_RECV_CALL: - zigbee.recv_filter = (uint8_t *) cur_ptr1; - zigbee.recv_filter_len = cur_d8; // len - zigbee.recv_func = (ZB_RecvMsgFunc) cur_ptr2; - zigbee.next_timeout = now + cur_d16; - zigbee.state_waiting = true; - break; - } - } -} +void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZigbeeZNPSend, &CmndZigbeePermitJoin, + &CmndZigbeeDump }; int32_t ZigbeeProcessInput(class SBuffer &buf) { if (!zigbee.state_machine) { return -1; } // if state machine is stopped, send 'ignore' message @@ -1031,6 +234,13 @@ void ZigbeeInit(void) * Commands \*********************************************************************************************/ +void CmndZigbeeDump(void) { + if (ZigbeeSerial) { + String dump = Z_DumpDevices(); + Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, dump.c_str()); + } +} + void CmndZigbeeZNPSend(void) { if (ZigbeeSerial && (XdrvMailbox.data_len > 0)) { @@ -1086,7 +296,7 @@ void ZigbeeZNPSend(const uint8_t *msg, size_t len) { XdrvRulesProcess(); } - +// Allow or Deny pairing of new Zigbee devices void CmndZigbeePermitJoin(void) { uint32_t payload = XdrvMailbox.payload; From 9ce32790db4d75e5f8d6997b4d5b3f613c541af1 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 29 Sep 2019 16:06:18 +0200 Subject: [PATCH 2005/2222] Fix 6508 --- sonoff/xdrv_05_irremote_full.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sonoff/xdrv_05_irremote_full.ino b/sonoff/xdrv_05_irremote_full.ino index 6c2fe9452..2bfa7a6c4 100644 --- a/sonoff/xdrv_05_irremote_full.ino +++ b/sonoff/xdrv_05_irremote_full.ino @@ -169,15 +169,15 @@ String sendIRJsonState(const struct decode_results &results) { char hvalue[64]; if (UNKNOWN != results.decode_type) { Uint64toHex(results.value, hvalue, results.bits); // Get 64bit value as hex 0x00123456 - json += "\""; + json += "\"0x"; json += hvalue; - json += "\",\"" D_JSON_IR_DATALSB "\":\""; + json += "\",\"" D_JSON_IR_DATALSB "\":\"0x"; Uint64toHex(reverseBitsInBytes64(results.value), hvalue, results.bits); // Get 64bit value as hex 0x00123456, LSB json += hvalue; json += "\""; } else { // UNKNOWN Uint64toHex(results.value, hvalue, 32); // Unknown is always 32 bits - json += "\""; + json += "\"0x"; json += hvalue; json += "\""; } @@ -210,7 +210,7 @@ void IrReceiveCheck(void) // if ((now - ir_lasttime > IR_TIME_AVOID_DUPLICATE) && (UNKNOWN != results.decode_type) && (results.bits > 0)) { if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { ir_lasttime = now; - ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str()); + Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str()); if (Settings.flag3.receive_raw) { ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); @@ -438,7 +438,7 @@ uint32_t IrRemoteCmndIrSendJson(void) char dvalue[32]; char hvalue[32]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol %d, bits %d, data %s (%s), repeat %d"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol %d, bits %d, data 0x%s (%s), repeat %d"), protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat); irsend_active = true; // deactivate receive From e40475b5631c66e0b84d78526d0ec4abbb8424b6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 29 Sep 2019 18:00:01 +0200 Subject: [PATCH 2006/2222] Add initial support for shutters Add initial support for shutters by Stefan Bode (#288) --- sonoff/_changelog.ino | 1 + sonoff/language/bg-BG.h | 5 + sonoff/language/cs-CZ.h | 5 + sonoff/language/de-DE.h | 5 + sonoff/language/el-GR.h | 5 + sonoff/language/en-GB.h | 5 + sonoff/language/es-ES.h | 5 + sonoff/language/fr-FR.h | 5 + sonoff/language/he-HE.h | 5 + sonoff/language/hu-HU.h | 5 + sonoff/language/it-IT.h | 5 + sonoff/language/ko-KO.h | 5 + sonoff/language/nl-NL.h | 5 + sonoff/language/pl-PL.h | 5 + sonoff/language/pt-BR.h | 5 + sonoff/language/pt-PT.h | 5 + sonoff/language/ru-RU.h | 5 + sonoff/language/sk-SK.h | 5 + sonoff/language/sv-SE.h | 5 + sonoff/language/tr-TR.h | 5 + sonoff/language/uk-UK.h | 5 + sonoff/language/zh-CN.h | 5 + sonoff/language/zh-TW.h | 5 + sonoff/my_user_config.h | 1 + sonoff/settings.h | 23 +- sonoff/sonoff.h | 13 +- sonoff/sonoff.ino | 3 + sonoff/xdrv_01_webserver.ino | 53 +++- sonoff/xdrv_07_domoticz.ino | 11 +- sonoff/xdrv_10_rules.ino | 10 +- sonoff/xdrv_10_scripter.ino | 13 + sonoff/xdrv_20_hue.ino | 49 ++- sonoff/xdrv_27_shutter.ino | 588 +++++++++++++++++++++++++++++++++++ 33 files changed, 844 insertions(+), 31 deletions(-) create mode 100644 sonoff/xdrv_27_shutter.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 2da2d46ff..5b26d35d3 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,6 +4,7 @@ * Remove support for define USE_DS18x20_LEGACY and legacy DS18x20 driver (#6486) * Add initial support for MQTT logging using command MqttLog (#6498) * Add Zigbee more support - collect endpoints and clusters, added ZigbeeDump command + * Add initial support for shutters by Stefan Bode (#288) * * 6.6.0.13 20190922 * Add command EnergyReset4 x,x to initialize total usage for two tarrifs diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 69e35925d..1cc34be2c 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Използвана енергия вчера" #define D_ENERGY_TOTAL "Използвана енергия общо" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Датчикът DS18x20 е зает" #define D_SENSOR_CRC_ERROR "Датчик DS18x20 - грешка CRC" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 3cc0d3197..c8a5713c8 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Spotřeba Včera" #define D_ENERGY_TOTAL "Celková spotřeba" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor DS18x20 obsazen" #define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index a516eeb42..295402d6b 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Energie gestern" #define D_ENERGY_TOTAL "Energie insgesamt" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor beschäftigt" #define D_SENSOR_CRC_ERROR "Sensor CRC-Fehler" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 100791bb1..222c06ef6 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Ενέργεια χθες" #define D_ENERGY_TOTAL "Ενέργεια συνολικά" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Ο αισθητήρας είναι απασχολημένος" #define D_SENSOR_CRC_ERROR "Σφάλμα CRC αισθητήρα" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 3e415c6e2..546d99af1 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Energy Yesterday" #define D_ENERGY_TOTAL "Energy Total" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor busy" #define D_SENSOR_CRC_ERROR "Sensor CRC error" diff --git a/sonoff/language/es-ES.h b/sonoff/language/es-ES.h index bbd1d776a..b62e54661 100644 --- a/sonoff/language/es-ES.h +++ b/sonoff/language/es-ES.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Energía Ayer" #define D_ENERGY_TOTAL "Energía Total" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor ocupado" #define D_SENSOR_CRC_ERROR "Error CRC del Sensor" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index d08f654ff..6091da84f 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Énergie hier" #define D_ENERGY_TOTAL "Énergie totale" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Capteur occupé" #define D_SENSOR_CRC_ERROR "Erreur CRC capteur" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index e2a54fe57..ee16e5073 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "צריכה בעבר" #define D_ENERGY_TOTAL "צריכה כללית" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "שרת עסוק" #define D_SENSOR_CRC_ERROR "בחיישן CRC שגיאת" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 564d385c1..90a52b03a 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Tegnapi energia" #define D_ENERGY_TOTAL "Összes energia" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Szenzor foglalt" #define D_SENSOR_CRC_ERROR "Szenzor CRC hiba" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index cfb564eca..2a990dc8e 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Energia Ieri" #define D_ENERGY_TOTAL "Energia Totale" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensore occupato" #define D_SENSOR_CRC_ERROR "Sensore errore CRC" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index d713fa79d..7ffc5271d 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "어제 전력 사용량" #define D_ENERGY_TOTAL "총 전력 사용량" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "센서가 사용 중" #define D_SENSOR_CRC_ERROR "센서 CRC 에러" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 03f77b4eb..822bf1542 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Verbruik gisteren" #define D_ENERGY_TOTAL "Verbruik totaal" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor bezet" #define D_SENSOR_CRC_ERROR "Sensor CRC fout" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 6b4d35678..8729be3c7 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Energia Wczoraj" #define D_ENERGY_TOTAL "Energia suma" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Czujnik DS18x20 zajęty" #define D_SENSOR_CRC_ERROR "Czujnik DS18x20 błąd CRC" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 388db5620..f1ec6326f 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Consumo energético de ontem" #define D_ENERGY_TOTAL "Consumo total de energia" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor ocupado" #define D_SENSOR_CRC_ERROR "Erro sensor CRC" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 44e5b3469..0fac99308 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Consumo energético de ontem" #define D_ENERGY_TOTAL "Consumo total de energial" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor ocupado" #define D_SENSOR_CRC_ERROR "Erro Sensor CRC" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 614fea8fe..2b0b68cb7 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Энергия Вчера" #define D_ENERGY_TOTAL "Энергия Всего" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Датчик DS18x20 занят" #define D_SENSOR_CRC_ERROR "Датчик DS18x20 - ошибка CRC" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 18e3fcb41..84385ee28 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Spotreba včera" #define D_ENERGY_TOTAL "Celková spotreba" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor DS18x20 obsadený" #define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 477e17e67..d55b6ddbc 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Energi igår" #define D_ENERGY_TOTAL "Energi totalt" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor upptagen" #define D_SENSOR_CRC_ERROR "Sensor CRC-fel" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 6826c9e92..f31efe078 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Energy Yesterday" #define D_ENERGY_TOTAL "Energy Total" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensör başgül" #define D_SENSOR_CRC_ERROR "Sensor CRC hatası" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index eb9db9913..dd21904d8 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "Енергія Вчора" #define D_ENERGY_TOTAL "Енергія Всього" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Датчик DS18x20 зайнятий" #define D_SENSOR_CRC_ERROR "Датчик DS18x20 - помилка CRC" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 0f16bf057..0d776f40c 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "昨日用电量" #define D_ENERGY_TOTAL "总用电量" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "传感器正忙" #define D_SENSOR_CRC_ERROR "传感器 CRC 校验错误" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 8d65c1c67..38d0b26be 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -442,6 +442,11 @@ #define D_ENERGY_YESTERDAY "昨日用電量" #define D_ENERGY_TOTAL "總用電量" +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "傳感器正忙" #define D_SENSOR_CRC_ERROR "傳感器 CRC 校驗錯誤" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 338ce5d17..a2a2eda67 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -313,6 +313,7 @@ #define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) //#define ROTARY_V1 // Add support for MI Desk Lamp +//#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+6k code) // -- Counter input ------------------------------- #define USE_COUNTER // Enable inputs as counter (+0k8 code) diff --git a/sonoff/settings.h b/sonoff/settings.h index a4470799a..c11926855 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -93,7 +93,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t spare27 : 1; uint32_t spare28 : 1; uint32_t spare29 : 1; - uint32_t spare30 : 1; + uint32_t shutter_mode : 1; // bit 30 (v6.6.0.15) - SetOption80 - Enable shutter support uint32_t spare31 : 1; }; } SysBitfield3; @@ -227,7 +227,8 @@ struct SYSCFG { uint8_t weblog_level; // 1AC uint8_t mqtt_fingerprint[2][20]; // 1AD uint8_t adc_param_type; // 1D5 - uint8_t register8[17]; // 1D6 - 17 x 8-bit registers indexed by enum SettingsRegister8 + uint8_t register8[16]; // 1D6 - 16 x 8-bit registers indexed by enum SettingsRegister8 + uint8_t shutter_accuracy; // 1E6 uint8_t mqttlog_level; // 1E7 uint8_t sps30_inuse_hours; // 1E8 char mqtt_host[33]; // 1E9 - Keep together with below as being copied as one chunck with reset 6 @@ -376,7 +377,15 @@ struct SYSCFG { uint16_t ina226_i_fs[4]; // E28 uint16_t tariff[4][2]; // E30 - uint8_t free_e40[440]; // E40 + uint16_t shutter_opentime[MAX_SHUTTERS]; // E40 + uint16_t shutter_closetime[MAX_SHUTTERS]; // E48 + int16_t shuttercoeff[5][MAX_SHUTTERS]; // E50 + uint8_t shutter_invert[MAX_SHUTTERS]; // E78 + uint8_t shutter_set50percent[MAX_SHUTTERS]; // E7C + uint8_t shutter_position[MAX_SHUTTERS]; // E80 + uint8_t shutter_startrelay[MAX_SHUTTERS]; // E84 + + uint8_t free_e88[368]; // E88 uint32_t cfg_timestamp; // FF8 uint32_t cfg_crc32; // FFC @@ -427,7 +436,11 @@ struct XDRVMAILBOX { char *command; } XdrvMailbox; +#ifdef USE_SHUTTER +const uint8_t MAX_RULES_FLAG = 10; // Number of bits used in RulesBitfield (tricky I know...) +#else const uint8_t MAX_RULES_FLAG = 8; // Number of bits used in RulesBitfield (tricky I know...) +#endif // USE_SHUTTER typedef union { // Restricted by MISRA-C Rule 18.4 but so useful... uint16_t data; // Allow bit manipulation struct { @@ -439,8 +452,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint16_t wifi_connected : 1; uint16_t wifi_disconnected : 1; uint16_t http_init : 1; - uint16_t spare08 : 1; - uint16_t spare09 : 1; + uint16_t shutter_moved : 1; + uint16_t shutter_moving : 1; uint16_t spare10 : 1; uint16_t spare11 : 1; uint16_t spare12 : 1; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 1b29754a5..5ee19873c 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -67,6 +67,7 @@ const uint8_t MAX_XNRG_DRIVERS = 32; // Max number of allowed energy driv const uint8_t MAX_XDSP_DRIVERS = 32; // Max number of allowed display drivers const uint8_t MAX_XDRV_DRIVERS = 96; // Max number of allowed driver drivers const uint8_t MAX_XSNS_DRIVERS = 96; // Max number of allowed sensor drivers +const uint8_t MAX_SHUTTERS = 4; // Max number of shutters const uint8_t MAX_RULE_MEMS = 5; // Max number of saved vars const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 512 characters const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules @@ -255,10 +256,10 @@ enum SettingsParamIndex { P_HOLD_TIME, P_MAX_POWER_RETRY, P_ex_TUYA_DIMMER_ID, P enum SettingsRegister8 { R8_SPARE00, R8_SPARE01, R8_SPARE02, R8_SPARE03, R8_SPARE04, R8_SPARE05, R8_SPARE06, R8_SPARE07, R8_SPARE08, R8_SPARE09, R8_SPARE10, R8_SPARE11, - R8_SPARE12, R8_SPARE13, R8_SPARE14, R8_SPARE15, - R8_SPARE16 }; // Max size is 17 (Settings.register8[]) + R8_SPARE12, R8_SPARE13, R8_SPARE14, R8_SPARE15 }; // Max size is 16 (Settings.register8[]) -enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_P1_SMART_METER, DZ_MAX_SENSORS}; +enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, + DZ_AIRQUALITY, DZ_P1_SMART_METER, DZ_SHUTTER, DZ_MAX_SENSORS}; enum Ws2812ClockIndex { WS_SECOND, WS_MINUTE, WS_HOUR, WS_MARKER }; enum Ws2812Color { WS_RED, WS_GREEN, WS_BLUE }; @@ -282,8 +283,10 @@ enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FU enum AddressConfigSteps { ADDR_IDLE, ADDR_RECEIVE, ADDR_SEND }; enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER, - SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_MAX }; -const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|Timer|Rule|MaxPower|MaxEnergy|Overtemp|Light|Knx|Display|Wemo|Hue|Retry|Remote"; + SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER, + SRC_MAX }; +const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|" + "Timer|Rule|MaxPower|MaxEnergy|Overtemp|Light|Knx|Display|Wemo|Hue|Retry|Remote|Shutter"; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ff771c95e..d0a786e0c 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -96,6 +96,7 @@ power_t blink_mask = 0; // Blink relay active mask power_t blink_powersave; // Blink start power save state power_t latching_power = 0; // Power state at latching start power_t rel_inverted = 0; // Relay inverted flag (1 = (0 = On, 1 = Off)) +power_t shutter_mask = 0; // Bit Array to mark all relays that belong to at least one shutter int baudrate = APP_BAUDRATE; // Serial interface baud rate int serial_in_byte_counter = 0; // Index in receive buffer int ota_state_flag = 0; // OTA state flag @@ -138,6 +139,8 @@ uint8_t seriallog_level; // Current copy of Settings.seriallo uint8_t syslog_level; // Current copy of Settings.syslog_level uint8_t my_module_type; // Current copy of Settings.module or user template type uint8_t my_adc0; // Active copy of Module ADC0 +uint8_t last_source = 0; +uint8_t shutters_present = 0; // Number of actual define shutters //uint8_t mdns_delayed_start = 0; // mDNS delayed start bool serial_local = false; // Handle serial locally; bool fallback_topic_flag = false; // Use Topic or FallbackTopic diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index c85c6a252..c4239e90f 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -132,7 +132,7 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "rfsh=0;" "}" "}" -#else // USE_SCRIPT_WEB_DISPLAY +#else // USE_SCRIPT_WEB_DISPLAY "function la(p){" "var a='';" "if(la.arguments.length==1){" @@ -151,8 +151,7 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "x.send();" "lt=setTimeout(la,%d);" // Settings.web_refresh "}" -#endif // USE_SCRIPT_WEB_DISPLAY - +#endif // USE_SCRIPT_WEB_DISPLAY #ifdef USE_JAVASCRIPT_ES6 "lb=p=>la('&d='+p);" // Dark - Bright &d related to lb(value) and WebGetArg("d", tmp, sizeof(tmp)); @@ -164,7 +163,29 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "function lc(p){" "la('&t='+p);" // &t related to WebGetArg("t", tmp, sizeof(tmp)); "}" -#endif +#endif // USE_JAVASCRIPT_ES6 + +#ifdef USE_SHUTTER +#ifdef USE_JAVASCRIPT_ES6 + "ld1=p=>la('&u1='+p);" + "ld2=p=>la('&u2='+p);" + "ld3=p=>la('&u3='+p);" + "ld4=p=>la('&u4='+p);" +#else + "function ld1(p){" + "la('&u1='+p);" + "}" + "function ld2(p){" + "la('&u2='+p);" + "}" + "function ld3(p){" + "la('&u3='+p);" + "}" + "function ld4(p){" + "la('&u4='+p);" + "}" +#endif // USE_JAVASCRIPT_ES6 +#endif // USE_SHUTTER "wl(la);"; @@ -380,6 +401,11 @@ const char HTTP_MSG_SLIDER1[] PROGMEM = const char HTTP_MSG_SLIDER2[] PROGMEM = "
" D_DARKLIGHT "" D_BRIGHTLIGHT "
" "
"; +#ifdef USE_SHUTTER +const char HTTP_MSG_SLIDER3[] PROGMEM = + "
" D_CLOSE "" D_OPEN "
" + "
"; +#endif // USE_SHUTTER const char HTTP_MSG_RSTRT[] PROGMEM = "
" D_DEVICE_WILL_RESTART "

"; @@ -554,6 +580,7 @@ void ShowWebSource(uint32_t source) void ExecuteWebCommand(char* svalue, uint32_t source) { ShowWebSource(source); + last_source = source; ExecuteCommand(svalue, SRC_IGNORE); } @@ -992,6 +1019,13 @@ void HandleRoot(void) WSContentSend_P(HTTP_MSG_SLIDER2, Settings.light_dimmer); } #endif +#ifdef USE_SHUTTER + if (Settings.flag3.shutter_mode) { + for (uint32_t i = 0; i < shutters_present; i++) { + WSContentSend_P(HTTP_MSG_SLIDER3, Settings.shutter_position[i], i+1); + } + } +#endif // USE_SHUTTER WSContentSend_P(HTTP_TABLE100); WSContentSend_P(PSTR("
")); #ifdef USE_SONOFF_IFAN @@ -1092,6 +1126,17 @@ bool HandleRootStatusRefresh(void) snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } +#ifdef USE_SHUTTER + char webindex[5]; // WebGetArg name + for (uint32_t j = 1; j < 5; j++) { + snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j); + WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), j, tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + } +#endif // USE_SHUTTER WebGetArg("k", tmp, sizeof(tmp)); // 1 - 16 Pre defined RF keys if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), tmp); diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index a65c82851..44959045b 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -42,7 +42,7 @@ const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\" 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 "|" D_DOMOTICZ_AIRQUALITY "|" D_DOMOTICZ_P1_SMART_METER ; + D_DOMOTICZ_COUNT "|" D_DOMOTICZ_VOLTAGE "|" D_DOMOTICZ_CURRENT "|" D_DOMOTICZ_AIRQUALITY "|" D_DOMOTICZ_P1_SMART_METER "|" D_DOMOTICZ_SHUTTER ; char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; char domoticz_out_topic[] = DOMOTICZ_OUT_TOPIC; @@ -347,8 +347,15 @@ void DomoticzSensor(uint8_t idx, char *data) Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), Settings.domoticz_sensor_idx[idx], data, DomoticzBatteryQuality(), DomoticzRssiQuality()); } else { + uint8_t nvalue = 0; +#ifdef USE_SHUTTER + if (DZ_SHUTTER == idx) { + uint8_t position = atoi(data); + nvalue = position < 2 ? 0 : (position == 100 ? 1 : 2); + } +#endif // USE_SHUTTER Response_P(DOMOTICZ_MESSAGE, - Settings.domoticz_sensor_idx[idx], 0, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); + Settings.domoticz_sensor_idx[idx], nvalue, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); } MqttPublish(domoticz_in_topic); memcpy(mqtt_data, dmess, sizeof(dmess)); diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 74424386b..b26e5402d 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -605,6 +605,10 @@ void RulesEvery50ms(void) case 5: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Connected\":1}}"), sizeof(json_event)); break; case 6: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Disconnected\":1}}"), sizeof(json_event)); break; case 7: strncpy_P(json_event, PSTR("{\"HTTP\":{\"Initialized\":1}}"), sizeof(json_event)); break; +#ifdef USE_SHUTTER + case 8: strncpy_P(json_event, PSTR("{\"SHUTTER\":{\"Moved\":1}}"), sizeof(json_event)); break; + case 9: strncpy_P(json_event, PSTR("{\"SHUTTER\":{\"Moving\":1}}"), sizeof(json_event)); break; +#endif // USE_SHUTTER } if (json_event[0]) { RulesProcessEvent(json_event); @@ -1881,9 +1885,6 @@ bool Xdrv10(uint8_t function) bool result = false; switch (function) { - case FUNC_PRE_INIT: - RulesInit(); - break; case FUNC_EVERY_50_MSECOND: RulesEvery50ms(); break; @@ -1910,6 +1911,9 @@ bool Xdrv10(uint8_t function) result = RulesMqttData(); break; #endif // SUPPORT_MQTT_EVENT + case FUNC_PRE_INIT: + RulesInit(); + break; } return result; } diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index 40fa40391..b1e91e64a 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -1514,6 +1514,19 @@ chknext: len+=1; goto exit; } +#ifdef USE_SHUTTER + if (!strncmp(vname,"sht[",4)) { + GetNumericResult(vname+4,OPER_EQU,&fvar,0); + uint8_t index=fvar; + if (index<=shutters_present) { + fvar=Settings.shutter_position[index-1]; + } else { + fvar=-1; + } + len+=1; + goto exit; + } +#endif if (!strncmp(vname,"pc[",3)) { GetNumericResult(vname+3,OPER_EQU,&fvar,0); uint8_t index=fvar; diff --git a/sonoff/xdrv_20_hue.ino b/sonoff/xdrv_20_hue.ino index 2b40b2eea..0299aba14 100644 --- a/sonoff/xdrv_20_hue.ino +++ b/sonoff/xdrv_20_hue.ino @@ -276,6 +276,12 @@ void HueLightStatus1(uint8_t device, String *response) if (bri > 254) bri = 254; // Philips Hue bri is between 1 and 254 if (bri < 1) bri = 1; +#ifdef USE_SHUTTER + if (ShutterState(device)) { + bri = (float)(Settings.shutter_invert[device-1] ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100; + } +#endif + if (light_type) { light_state.getHSB(&hue, &sat, nullptr); @@ -519,19 +525,32 @@ void HueLights(String *path) response.replace("{id", String(EncodeLightId(device))); response.replace("{cm", "on"); - on = hue_json["on"]; - switch(on) - { - case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); - response.replace("{re", "false"); - break; - case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); - response.replace("{re", "true"); - break; - default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); - break; +#ifdef USE_SHUTTER + if (ShutterState(device)) { + if (!change) { + on = hue_json["on"]; + bri = on ? 1.0f : 0.0f; // when bri is not part of this request then calculate it + change = true; + } + response.replace("{re", on ? "true" : "false"); + } else { +#endif + on = hue_json["on"]; + switch(on) + { + case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); + response.replace("{re", "false"); + break; + case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); + response.replace("{re", "true"); + break; + default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); + break; + } + resp = true; +#ifdef USE_SHUTTER } - resp = true; +#endif // USE_SHUTTER } if (light_type && (local_light_subtype >= LST_SINGLE)) { @@ -637,6 +656,12 @@ void HueLights(String *path) resp = true; } if (change) { +#ifdef USE_SHUTTER + if (ShutterState(device)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_invert[device-1]); + SetShutterPosition(device, bri * 100.0f ); + } else +#endif if (light_type && (local_light_subtype > LST_NONE)) { // not relay if (!Settings.flag3.pwm_multi_channels) { if (g_gotct) { diff --git a/sonoff/xdrv_27_shutter.ino b/sonoff/xdrv_27_shutter.ino new file mode 100644 index 000000000..c6ebf8485 --- /dev/null +++ b/sonoff/xdrv_27_shutter.ino @@ -0,0 +1,588 @@ +/* + xdrv_27_shutter.ino - Shutter/Blind support for Sonoff-Tasmota + + Copyright (C) 2019 Stefan Bode + + 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_SHUTTER // +3.8k code +/*********************************************************************************************\ + * Energy +\*********************************************************************************************/ + +#define XDRV_27 27 + +#define D_PRFX_SHUTTER "Shutter" +#define D_CMND_SHUTTER_OPEN "Open" +#define D_CMND_SHUTTER_CLOSE "Close" +#define D_CMND_SHUTTER_STOP "Stop" +#define D_CMND_SHUTTER_POSITION "Position" +#define D_CMND_SHUTTER_OPENTIME "OpenDuration" +#define D_CMND_SHUTTER_CLOSETIME "CloseDuration" +#define D_CMND_SHUTTER_RELAY "Relay" +#define D_CMND_SHUTTER_SETHALFWAY "SetHalfway" +#define D_CMND_SHUTTER_SETCLOSE "SetClose" +#define D_CMND_SHUTTER_INVERT "Invert" +#define D_CMND_SHUTTER_CLIBRATION "Calibration" + +#define D_SHUTTER "SHUTTER" + +enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE }; + +const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" + D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" + D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|" + D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION; + +void (* const ShutterCommand[])(void) PROGMEM = { + &CmndShutterOpen, &CmndShutterClose, &CmndShutterStop, &CmndShutterPosition, + &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, + &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration }; + +const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_SHUTTER "%d\":{\"position\":%d,\"direction\":%d}"; + +Ticker TickerShutter; + +const uint16_t MOTOR_STOP_TIME=500; // in mS + +uint16_t Shutter_Open_Time[MAX_SHUTTERS] ; // duration to open the shutter +uint16_t Shutter_Close_Time[MAX_SHUTTERS]; // duration to close the shutter +int32_t Shutter_Open_Max[MAX_SHUTTERS]; // max value on maximum open calculated +int32_t Shutter_Target_Position[MAX_SHUTTERS] ; // position to go to +int32_t Shutter_Start_Position[MAX_SHUTTERS] ; +uint16_t Shutter_Close_Velocity[MAX_SHUTTERS]; // in relation to open velocity. higher value = faster +uint16_t Shutter_Operations[MAX_SHUTTERS]; +int8_t Shutter_Direction[MAX_SHUTTERS]; // 1 == UP , 0 == stop; -1 == down +int32_t Shutter_Real_Position[MAX_SHUTTERS]; // value between 0 and Shutter_Open_Max +//power_t shutter_mask = 0; // bit mask with 11 at the position of relays that belong to at least ONE shutter +power_t old_power = power; // preserve old bitmask for power to extract the relay that changes. +power_t SwitchedRelay = 0; // bitmatrix that contain the relays that was lastly changed. +uint32_t shutter_time[MAX_SHUTTERS] ; +uint8_t shutterMode = 0; // operation mode definition. see enum type above OFF_OPEN-OFF_CLOSE, OFF_ON-OPEN_CLOSE, PULSE_OPEN-PULSE_CLOSE + +void Rtc_ms50_Second() +{ + for (byte i=0;i < MAX_SHUTTERS; i++) { + shutter_time[i]++; + } +} + +int32_t percent_to_realposition(uint8_t percent,uint8_t index) +{ + if (Settings.shutter_set50percent[index] != 50) { + return percent <= 5 ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; + } else { + return percent <= 5 ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; + } +} + +uint8_t realposition_to_percent(int32_t realpos, uint8_t index) +{ + if (Settings.shutter_set50percent[index] != 50) { + return Settings.shuttercoeff[2][index] * 5 > realpos ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index]; + } else { + return Settings.shuttercoeff[2][index] * 5 > realpos ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index]; + } +} + +void ShutterInit() +{ + shutters_present = 0; + shutter_mask = 0; + //Initialize to get relay that changed + old_power = power; + char shutter_open_chr[10]; + char shutter_close_chr[10]; + bool relay_in_interlock = false; + + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Accuracy digits: %d"), Settings.shutter_accuracy); + + for (byte i=0;i < MAX_SHUTTERS; i++) { + // upgrade to 0.1sec calculation base. + if ( Settings.shutter_accuracy == 0) { + Settings.shutter_closetime[i] = Settings.shutter_closetime[i] * 10; + Settings.shutter_opentime[i] = Settings.shutter_opentime[i] * 10; + } + // set startrelay to 1 on first init, but only to shutter 1. 90% usecase + Settings.shutter_startrelay[i] = (Settings.shutter_startrelay[i] == 0 && i == 0? 1 : Settings.shutter_startrelay[i]); + if (Settings.shutter_startrelay[i] && Settings.shutter_startrelay[i] <9) { + shutters_present++; + + // Determine shutter types + shutter_mask |= 3 << (Settings.shutter_startrelay[i] -1) ; + + for (uint8_t i = 0; i < MAX_INTERLOCKS * Settings.flag.interlock; i++) { + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Interlock state i=%d %d, flag %d, , shuttermask %d, maskedIL %d"),i, Settings.interlock[i], Settings.flag.interlock,shutter_mask, Settings.interlock[i]&shutter_mask); + if (Settings.interlock[i] && Settings.interlock[i] & shutter_mask) { + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Relay in Interlock group")); + relay_in_interlock = true; + } + } + if ( relay_in_interlock) { + if (Settings.pulse_timer[i] > 0) { + shutterMode = SHT_PULSE_OPEN__PULSE_CLOSE; + } else { + shutterMode = SHT_OFF_OPEN__OFF_CLOSE; + } + } else { + shutterMode = SHT_OFF_ON__OPEN_CLOSE; + } + + TickerShutter.attach_ms(50, Rtc_ms50_Second ); + // default the 50 percent should not have any impact without changing it. set to 60 + Settings.shutter_set50percent[i] = (Settings.shutter_set50percent[i] == 0 ? 50 : Settings.shutter_set50percent[i]); + // use 10 sec. as default to allow everybody to play without deep initialize + Shutter_Open_Time[i] = Settings.shutter_opentime[i] > 0 ? Settings.shutter_opentime[i] : 100; + Shutter_Close_Time[i] = Settings.shutter_closetime[i] > 0 ? Settings.shutter_closetime[i] : 100; + + // Update Calculation 20 because time interval is 0.05 sec + Shutter_Open_Max[i] = 200 * Shutter_Open_Time[i]; + Shutter_Close_Velocity[i] = Shutter_Open_Max[i] / Shutter_Close_Time[i] / 2 ; + + // calculate a ramp slope at the first 5 percent to compensate that shutters move with down part later than the upper part + Settings.shuttercoeff[1][i] = Shutter_Open_Max[i] * (100 - Settings.shutter_set50percent[i] ) / 5000; + Settings.shuttercoeff[0][i] = Shutter_Open_Max[i] - (Settings.shuttercoeff[1][i] * 100); + Settings.shuttercoeff[2][i] = (Settings.shuttercoeff[0][i] + 5 * Settings.shuttercoeff[1][i]) / 5; + shutter_mask |= 3 << (Settings.shutter_startrelay[i] -1) ; + + Shutter_Real_Position[i] = percent_to_realposition(Settings.shutter_position[i], i); + //Shutter_Real_Position[i] = Settings.shutter_position[i] <= 5 ? Settings.shuttercoeff[2][i] * Settings.shutter_position[i] : Settings.shuttercoeff[1][i] * Settings.shutter_position[i] + Settings.shuttercoeff[0,i]; + Shutter_Start_Position[i] = Shutter_Real_Position[i]; + dtostrfd((double)Shutter_Open_Time[i] / 10 , 1, shutter_open_chr); + dtostrfd((double)Shutter_Close_Time[i] / 10, 1, shutter_close_chr); + + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoedffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d"), i, Settings.shutter_startrelay[i],Shutter_Real_Position[i],Settings.shutter_position[i], Shutter_Close_Velocity[i] , Shutter_Open_Max[i], shutter_open_chr, shutter_close_chr,Settings.shuttercoeff[0][i],Settings.shuttercoeff[1][i],Settings.shuttercoeff[2][i],Settings.shuttercoeff[3][i],Settings.shuttercoeff[4][i],shutter_mask,Settings.shutter_invert[i],shutterMode ); + } else { + // terminate loop at first INVALID shutter. + break; + } + Settings.shutter_accuracy = 1; + } +} + +void Schutter_Update_Position() +{ + char scommand[CMDSZ]; + char stopic[TOPSZ]; + + for (byte i=0; i < shutters_present; i++) { + if (Shutter_Direction[i] != 0) { + //char stemp1[20]; + Shutter_Real_Position[i] = Shutter_Start_Position[i] + ( shutter_time[i] * (Shutter_Direction[i] > 0 ? 100 : -Shutter_Close_Velocity[i])); + // avoid real position leaving the boundaries. + Shutter_Real_Position[i] = Shutter_Real_Position[i] < 0 ? 0 : (Shutter_Real_Position[i] > Shutter_Open_Max[i] ? Shutter_Open_Max[i] : Shutter_Real_Position[i]) ; + + // Add additional runtime, if shutter did not reach the endstop for some time. + if (Shutter_Target_Position[i] == Shutter_Real_Position[i] && Shutter_Target_Position[i] == 0) { + // for every operation add 5x50ms = 250ms to stop position + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Adding additional runtime")); + Shutter_Real_Position[i] += 500 * Shutter_Operations[i] ; + Shutter_Operations[i] = 0; + } + if (Shutter_Real_Position[i] * Shutter_Direction[i] >= Shutter_Target_Position[i] * Shutter_Direction[i] ) { + // calculate relay number responsible for current movement. + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Condition detected: real: %d, Target: %d, direction: %d"),Shutter_Real_Position[i], Shutter_Target_Position[i],Shutter_Direction[i]); + uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter_Direction[i] == 1 ? 0 : 1) ; + char stemp2[10]; + + Settings.shutter_position[i] = realposition_to_percent(Shutter_Real_Position[i], i); + //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter_Real_Position[i] ? (Shutter_Real_Position[i] * 10 / Settings.shuttercoeff[2][i] + 4)/10 : ((Shutter_Real_Position[i]-Settings.shuttercoeff[0,i]) *10 / Settings.shuttercoeff[1][i] +4) / 10; + + if (0 < Settings.shutter_position[i] && Settings.shutter_position[i] < 100) { + Shutter_Operations[i]++; + } else { + Shutter_Operations[i] = 0; + } + + dtostrfd((double)shutter_time[i] / 20, 1, stemp2); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos. %d, Stoppos: %ld, relay: %d, direction %d, pulsetimer: %d, rtcshutter: %s [s], operationtime %d"), i, Shutter_Real_Position[i], Settings.shutter_position[i], cur_relay -1, Shutter_Direction[i], Settings.pulse_timer[cur_relay -1], stemp2, Shutter_Operations[i]); + Shutter_Start_Position[i] = Shutter_Real_Position[i]; + + // sending MQTT result to broker + snprintf_P(scommand, sizeof(scommand),PSTR("%s%d"), D_SHUTTER, i+1); + GetTopic_P(stopic, STAT, mqtt_topic, scommand); + Response_P("%d", Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); + MqttPublish(stopic, Settings.flag.mqtt_power_retain); + + switch (shutterMode) { + case SHT_PULSE_OPEN__PULSE_CLOSE: + // we have a momentary switch here. Needs additional pulse on same relay after the end + if (SRC_PULSETIMER == last_source || SRC_SHUTTER == last_source || SRC_WEBGUI == last_source) { + ExecuteCommandPower(cur_relay, 1, SRC_SHUTTER); + } else { + last_source = SRC_SHUTTER; + } + break; + case SHT_OFF_ON__OPEN_CLOSE: + // This is a failsafe configuration. Relay1 ON/OFF Relay2 -1/1 direction + if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { + ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); + } + break; + case SHT_OFF_OPEN__OFF_CLOSE: + // avoid switching OFF a relay already OFF + if ((1 << (cur_relay-1)) & power) { + // Relay is on and need to be switched off. + ExecuteCommandPower(cur_relay, 0, SRC_SHUTTER); + } + break; + } + Shutter_Direction[i] = 0; + byte position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; + Response_P(PSTR("{")); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, 0 /*Shutter_Direction[i]*/); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + XdrvRulesProcess(); + } + } + } + +} + +bool ShutterState(uint8_t device) +{ + device--; + device &= 3; + return (Settings.flag3.shutter_mode && (shutter_mask & (1 << (Settings.shutter_startrelay[device]-1))) ); +} + +void Shutter_StartInit (uint8_t index, uint8_t direction, int32_t target_pos) +{ + Shutter_Direction[index] = direction; + Shutter_Target_Position[index] = target_pos; + Shutter_Start_Position[index] = Shutter_Real_Position[index]; + shutter_time[index] = 0; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter_Start_Position[index], Shutter_Target_Position[index], Shutter_Direction[index]); +} + +void DelayForMotorStop() +{ + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop %d"), MOTOR_STOP_TIME); + delay(MOTOR_STOP_TIME); +} + +void Schutter_Report_Position() +{ + uint16_t shutter_moving = 0; + for (byte i=0; i < shutters_present; i++) { + if (Shutter_Direction[i] != 0) { + char stemp1[20]; + char stemp2[10]; + dtostrfd((double)shutter_time[i] / 20, 1, stemp2); + shutter_moving = 1; + //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter_Real_Position[i] ? Shutter_Real_Position[i] / Settings.shuttercoeff[2][i] : (Shutter_Real_Position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d, Target %d, source: %s, start-pos: %d %%, direction: %d, rtcshutter: %s [s]"), i,Shutter_Real_Position[i], Shutter_Target_Position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), Settings.shutter_position[i], Shutter_Direction[i], stemp2 ); + } + } + if (rules_flag.shutter_moving > shutter_moving) { + rules_flag.shutter_moved = 1; + } else { + rules_flag.shutter_moved = 0; + } + rules_flag.shutter_moving = shutter_moving; + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); +} + +void Shutter_Relay_changed() +{ + + // SwitchedRelay = binary relay that was recently changed and cause an Action + // powerstate_local = binary powermatrix and relays from shutter: 0..3 + // relays_changed = bool if one of the relays that belong to the shutter changed not by shutter or pulsetimer + char stemp1[10]; + + + for (byte i=0; i < shutters_present; i++) { + power_t powerstate_local = (power >> (Settings.shutter_startrelay[i] -1)) & 3; + //uint8 manual_relays_changed = ((SwitchedRelay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_IGNORE != last_source && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; + uint8 manual_relays_changed = ((SwitchedRelay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; + if (manual_relays_changed) { + if (shutterMode == SHT_OFF_ON__OPEN_CLOSE) { + switch (powerstate_local) { + case 1: + DelayForMotorStop(); + Shutter_StartInit(i, 1, Shutter_Open_Max[i]); + break; + case 3: + DelayForMotorStop(); + Shutter_StartInit(i, -1, 0); + break; + default: + Shutter_Direction[i] = 0; + Shutter_Target_Position[i] = Shutter_Real_Position[i]; + } + } else { + if (Shutter_Direction[i] != 0 && (!powerstate_local || (powerstate_local && shutterMode == SHT_PULSE_OPEN__PULSE_CLOSE))) { + Shutter_Target_Position[i] = Shutter_Real_Position[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, switchedRelay %d, manual change %d"), i, Shutter_Target_Position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,SwitchedRelay,manual_relays_changed); + } else { + last_source = SRC_SHUTTER; // avoid switch off in the next loop + if (powerstate_local == 2) { // testing on CLOSE relay, if ON + // close with relay two + DelayForMotorStop(); + Shutter_StartInit(i, -1, 0); + } else { + // opens with relay one + DelayForMotorStop(); + Shutter_StartInit(i, 1, Shutter_Open_Max[i]); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i, Shutter_Target_Position[i], powerstate_local); + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////////// +// Shutter specific functions +// TODO: move to shutter driver and make them accessible in a generic way + +// device: 1.. +// position: 0-100 +void SetShutterPosition(uint8_t device, uint8_t position) +{ + char svalue[32]; // Command and number parameter + snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION "%d %d"), device, position); + ExecuteCommand(svalue, SRC_IGNORE); +} + +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + +void CmndShutterOpen(void) +{ + XdrvMailbox.payload = 100; + last_source = SRC_WEBGUI; + CmndShutterPosition(); +} + +void CmndShutterClose(void) +{ + XdrvMailbox.payload = 0; + last_source = SRC_WEBGUI; + CmndShutterPosition(); +} + +void CmndShutterStop(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + uint32_t index = XdrvMailbox.index -1; + if (Shutter_Direction[index] != 0) { + + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving shutter %d: direction:%d"), XdrvMailbox.index, Shutter_Direction[index]); + + int32_t temp_realpos = Shutter_Start_Position[index] + ( (shutter_time[index]+10) * (Shutter_Direction[index] > 0 ? 100 : -Shutter_Close_Velocity[index])); + XdrvMailbox.payload = realposition_to_percent(temp_realpos, index); + //XdrvMailbox.payload = Settings.shuttercoeff[2][index] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][index] : (temp_realpos-Settings.shuttercoeff[0,index]) / Settings.shuttercoeff[1][index]; + last_source = SRC_WEBGUI; + CmndShutterPosition(); + } else { + ResponseCmndDone(); + } + } +} + +void CmndShutterPosition(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + uint32_t index = XdrvMailbox.index -1; + //limit the payload + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Position in: payload %d, index %d, source %d"), XdrvMailbox.payload , XdrvMailbox.index, last_source ); + + int8_t target_pos_percent = XdrvMailbox.payload < 0 ? 0 : (XdrvMailbox.payload > 100 ? 100 : XdrvMailbox.payload); + // webgui still send also on inverted shutter the native position. + target_pos_percent = Settings.shutter_invert[index] && SRC_WEBGUI != last_source ? 100 - target_pos_percent : target_pos_percent; + if (target_pos_percent != -99) { + //target_pos_percent = Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent; + Shutter_Target_Position[index] = percent_to_realposition(target_pos_percent, index); + //Shutter_Target_Position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, realpos %d, target %d, payload %d"), last_source, Shutter_Real_Position[index] ,Shutter_Target_Position[index],target_pos_percent); + } + if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter_Target_Position[index] - Shutter_Real_Position[index] ) / Shutter_Close_Velocity[index] > 2) { + int8_t new_shutterdirection = Shutter_Real_Position[index] < Shutter_Target_Position[index] ? 1 : -1; + if (Shutter_Direction[index] == -new_shutterdirection ) { + // direction need to be changed. on momentary switches first stop the Shutter + if (shutterMode == SHT_PULSE_OPEN__PULSE_CLOSE) { + // code for momentary shutters only small switch on to stop Shutter + ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); + delay(100); + } else { + ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 1 : 0), 0, SRC_SHUTTER); + DelayForMotorStop(); + } + } + if (Shutter_Direction[index] != new_shutterdirection ) { + Shutter_StartInit(index, new_shutterdirection, Shutter_Target_Position[index]); + Shutter_Operations[index]++; + if (shutterMode == SHT_OFF_ON__OPEN_CLOSE) { + ExecuteCommandPower(Settings.shutter_startrelay[index] , 0, SRC_SHUTTER); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload); + DelayForMotorStop(); + // Code for shutters with circuit safe configuration, switch the direction Relay + ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); + // power on + ExecuteCommandPower(Settings.shutter_startrelay[index] , 1, SRC_SHUTTER); + } else { + // now start the motor for the right direction, work for momentary and normal shutters. + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter in direction %d"), Shutter_Direction[index]); + ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay6 5s, xdrv %d"), XdrvMailbox.payload); + } + SwitchedRelay = 0; + } + } else { + target_pos_percent = realposition_to_percent(Shutter_Real_Position[index], index); + } + ResponseCmndIdxNumber(Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent); + } +} + +void CmndShutterOpenTime(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + Settings.shutter_opentime[XdrvMailbox.index-1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); + ShutterInit(); + } + char time_chr[10]; + dtostrfd((float)(Settings.shutter_opentime[XdrvMailbox.index-1]) / 10, 1, time_chr); + ResponseCmndIdxChar(time_chr); + } +} + +void CmndShutterCloseTime(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + Settings.shutter_closetime[XdrvMailbox.index-1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); + ShutterInit(); + } + char time_chr[10]; + dtostrfd((float)(Settings.shutter_closetime[XdrvMailbox.index-1]) / 10, 1, time_chr); + ResponseCmndIdxChar(time_chr); + } +} + +void CmndShutterRelay(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64)) { + Settings.shutter_startrelay[XdrvMailbox.index-1] = XdrvMailbox.payload; + if (XdrvMailbox.payload > 0) { + shutter_mask |= 3 << (XdrvMailbox.payload - 1); + } else { + shutter_mask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index-1] - 1); + } + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Relay %d is %d"), XdrvMailbox.index, XdrvMailbox.payload); + Settings.shutter_startrelay[XdrvMailbox.index-1] = XdrvMailbox.payload; + ShutterInit(); + // if payload is 0 to disable the relay there must be a reboot. Otherwhise does not work + } + ResponseCmndIdxNumber(Settings.shutter_startrelay[XdrvMailbox.index -1]); + } +} + +void CmndShutterSetHalfway(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + Settings.shutter_set50percent[XdrvMailbox.index-1] = Settings.shutter_invert[XdrvMailbox.index-1] ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; + ShutterInit(); + ResponseCmndIdxNumber(XdrvMailbox.payload); // ???? + } else { + ResponseCmndIdxNumber(Settings.shutter_set50percent[XdrvMailbox.index-1]); + } + } +} + +void CmndShutterSetClose(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + Shutter_Real_Position[XdrvMailbox.index-1] = 0; + Shutter_StartInit(XdrvMailbox.index-1, 0, 0); + Settings.shutter_position[XdrvMailbox.index-1] = 0; + ResponseCmndChar(D_CONFIGURATION_RESET); + } +} + +void CmndShutterInvert(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.shutter_invert[XdrvMailbox.index-1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.shutter_invert[XdrvMailbox.index-1]); + } +} + +void CmndShutterCalibration(void) // ???? +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { + if (XdrvMailbox.data_len > 0) { + ResponseCmndIdxChar(XdrvMailbox.data); + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv27(uint8_t function) +{ + bool result = false; + + if (Settings.flag3.shutter_mode) { + switch (function) { + case FUNC_PRE_INIT: + ShutterInit(); + break; + case FUNC_EVERY_50_MSECOND: + Schutter_Update_Position(); + break; + case FUNC_EVERY_SECOND: + Schutter_Report_Position(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kShutterCommands, ShutterCommand); + break; + case FUNC_JSON_APPEND: + for (uint32_t i = 0; i < shutters_present; i++) { + uint8_t position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; + ResponseAppend_P(","); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter_Direction[i]); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzSensor(DZ_SHUTTER, position); + } +#endif // USE_DOMOTICZ + } + break; + case FUNC_SET_POWER: + char stemp1[10]; + // extract the number of the relay that was switched and save for later in Update Position. + SwitchedRelay = power ^ old_power; + old_power = power; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), SwitchedRelay,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource)); + Shutter_Relay_changed(); + break; + } + } + return result; +} + +#endif //USE_SHUTTER From e90f67bbbbd497d5685887904b0c1641daf1ec5d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 29 Sep 2019 18:11:36 +0200 Subject: [PATCH 2007/2222] Add driver JSON if available Add driver JSON if available --- sonoff/sonoff.ino | 3 --- sonoff/xdrv_27_shutter.ino | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index d0a786e0c..1e4cee99c 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -748,10 +748,7 @@ bool MqttShowSensor(void) } } XsnsCall(FUNC_JSON_APPEND); - -#ifdef USE_SCRIPT_JSON_EXPORT XdrvCall(FUNC_JSON_APPEND); -#endif bool json_data_available = (strlen(mqtt_data) - json_data_start); if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE)) != nullptr) { diff --git a/sonoff/xdrv_27_shutter.ino b/sonoff/xdrv_27_shutter.ino index c6ebf8485..2c9bf170d 100644 --- a/sonoff/xdrv_27_shutter.ino +++ b/sonoff/xdrv_27_shutter.ino @@ -51,7 +51,7 @@ void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration }; -const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_SHUTTER "%d\":{\"position\":%d,\"direction\":%d}"; +const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d}"; Ticker TickerShutter; @@ -211,7 +211,7 @@ void Schutter_Update_Position() Shutter_Start_Position[i] = Shutter_Real_Position[i]; // sending MQTT result to broker - snprintf_P(scommand, sizeof(scommand),PSTR("%s%d"), D_SHUTTER, i+1); + snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); GetTopic_P(stopic, STAT, mqtt_topic, scommand); Response_P("%d", Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); MqttPublish(stopic, Settings.flag.mqtt_power_retain); From 6da17ccb6b47ce5c888195120d827ebe1d241405 Mon Sep 17 00:00:00 2001 From: Staars Date: Sun, 29 Sep 2019 18:35:02 +0200 Subject: [PATCH 2008/2222] last fixes for the Chirp-sensor --- sonoff/xsns_48_chirp.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_48_chirp.ino b/sonoff/xsns_48_chirp.ino index 872478b8d..b0246566f 100644 --- a/sonoff/xsns_48_chirp.ino +++ b/sonoff/xsns_48_chirp.ino @@ -426,7 +426,7 @@ void ChirpShow(bool json) char str_light[33]; dtostrfd(chirp_sensor[i].light, 0, str_light); char str_version[7]; - if(chirp_sensor[i].version == 255){ + if(chirp_sensor[i].version == 0xff){ strncpy_P(str_version, PSTR("Chirp!"), sizeof(str_version)); } else{ From e6824ff903ec47865d024793796e5a6f54925f69 Mon Sep 17 00:00:00 2001 From: Staars Date: Sun, 29 Sep 2019 18:38:14 +0200 Subject: [PATCH 2009/2222] remove #define USE_CHIRP --- sonoff/xsns_48_chirp.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/sonoff/xsns_48_chirp.ino b/sonoff/xsns_48_chirp.ino index b0246566f..c2bf08f1d 100644 --- a/sonoff/xsns_48_chirp.ino +++ b/sonoff/xsns_48_chirp.ino @@ -32,7 +32,6 @@ */ -#define USE_CHIRP #ifdef USE_I2C #ifdef USE_CHIRP From 6eb3c746896a1d3a02830f2aa45f3f7058fb22e7 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Mon, 30 Sep 2019 10:25:02 +0200 Subject: [PATCH 2010/2222] scripter update --- sonoff/support_command.ino | 10 +- sonoff/xdrv_10_scripter.ino | 395 +++++++++++++++++++++++++++++++++--- sonoff/xdrv_20_hue.ino | 71 ++++--- 3 files changed, 407 insertions(+), 69 deletions(-) diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 809b3e154..0e2f6d4e6 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -187,14 +187,16 @@ void CommandHandler(char* topic, uint8_t* data, uint32_t data_len) #ifdef USE_SCRIPT_SUB_COMMAND // allow overwrite tasmota cmds - if (!XdrvCall(FUNC_COMMAND)) { + if (!Script_SubCmd()) { if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { - if (!XsnsCall(FUNC_COMMAND)) { + if (!XdrvCall(FUNC_COMMAND)) { + if (!XsnsCall(FUNC_COMMAND)) { type = nullptr; // Unknown command + } } } } -#else +#else //USE_SCRIPT_SUB_COMMAND if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { if (!XdrvCall(FUNC_COMMAND)) { if (!XsnsCall(FUNC_COMMAND)) { @@ -202,7 +204,7 @@ void CommandHandler(char* topic, uint8_t* data, uint32_t data_len) } } } -#endif +#endif //USE_SCRIPT_SUB_COMMAND } diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index b1e91e64a..0d3307490 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -41,8 +41,13 @@ keywords if then else endif, or, and are better readable for beginners (others m #define SCRIPT_DEBUG 0 + +#ifndef MAXVARS #define MAXVARS 50 +#endif +#ifndef MAXSVARS #define MAXSVARS 5 +#endif #define MAXNVARS MAXVARS-MAXSVARS #define MAXFILT 5 @@ -62,7 +67,9 @@ enum {SCRIPT_LOGLEVEL=1,SCRIPT_TELEPERIOD}; #ifdef USE_SCRIPT_FATFS #include #include +#ifndef FAT_SCRIPT_SIZE #define FAT_SCRIPT_SIZE 4096 +#endif #define FAT_SCRIPT_NAME "script.txt" #if USE_LONG_FILE_NAMES==1 #warning ("FATFS long filenames not supported"); @@ -215,7 +222,11 @@ void RulesTeleperiod(void) { #include #define EEPROM_ADDRESS 0x50 // strange bug, crashes with powers of 2 ??? 4096 crashes +#ifndef EEP_SCRIPT_SIZE #define EEP_SCRIPT_SIZE 4095 +#endif + + static Eeprom24C128_256 eeprom(EEPROM_ADDRESS); // eeprom.writeBytes(address, length, buffer); #define EEP_WRITE(A,B,C) eeprom.writeBytes(A,B,(uint8_t*)C); @@ -471,6 +482,8 @@ char *script; return -5; } } + // variables usage info + AddLog_P2(LOG_LEVEL_INFO, PSTR("Script: nv=%d, tv=%d, vns=%d, ram=%d"), nvars, svars, index, glob_script_mem.script_mem_size); // copy string variables char *cp1=glob_script_mem.glob_snp; @@ -1514,19 +1527,6 @@ chknext: len+=1; goto exit; } -#ifdef USE_SHUTTER - if (!strncmp(vname,"sht[",4)) { - GetNumericResult(vname+4,OPER_EQU,&fvar,0); - uint8_t index=fvar; - if (index<=shutters_present) { - fvar=Settings.shutter_position[index-1]; - } else { - fvar=-1; - } - len+=1; - goto exit; - } -#endif if (!strncmp(vname,"pc[",3)) { GetNumericResult(vname+3,OPER_EQU,&fvar,0); uint8_t index=fvar; @@ -3352,10 +3352,353 @@ void ScriptSaveSettings(void) { #endif +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) + +/* +"state": { +"temperature": 2674, +"lastupdated": "2017-08-04T12:13:04" +}, +"config": { +"on": true, +"battery": 100, +"reachable": true, +"alert": "none", +"ledindication": false, +"usertest": false, +"pending": [] +}, +"name": "Hue temperature sensor 1", +"type": "ZLLTemperature", +"modelid": "SML001", +"manufacturername": "Philips", +"swversion": "6.1.0.18912", +"uniqueid": "xxx" +} +*/ + +#define HUE_DEV_MVNUM 5 +#define HUE_DEV_NSIZE 16 +struct HUE_SCRIPT { + char name[HUE_DEV_NSIZE]; + uint8_t type; + uint8_t index[HUE_DEV_MVNUM]; + uint8_t vindex[HUE_DEV_MVNUM]; +} hue_script[32]; + + +const char SCRIPT_HUE_LIGHTS_STATUS_JSON1[] PROGMEM = + "{\"state\":" + "{\"on\":{state}," + "{light_status}" + "\"alert\":\"none\"," + "\"effect\":\"none\"," + "\"reachable\":true}" + ",\"type\":\"{type}\"," + "\"name\":\"{j1\"," + "\"modelid\":\"LCT007\"," + "\"uniqueid\":\"{j2\"," + "\"swversion\":\"5.50.1.19085\"}"; + + +void Script_HueStatus(String *response, uint16_t hue_devs) { + *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON1); + uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; + response->replace("{state}", (pwr ? "true" : "false")); + String light_status = ""; + if (hue_script[hue_devs].index[1]>0) { + // bri + light_status += "\"bri\":"; + uint32_t bri=glob_script_mem.fvars[hue_script[hue_devs].index[1]-1]; + if (bri > 254) bri = 254; + if (bri < 1) bri = 1; + light_status += String(bri); + light_status += ","; + } + if (hue_script[hue_devs].index[2]>0) { + // hue + uint32_t hue=glob_script_mem.fvars[hue_script[hue_devs].index[2]-1]; + //hue = changeUIntScale(hue, 0, 359, 0, 65535); + light_status += "\"hue\":"; + light_status += String(hue); + light_status += ","; + } + if (hue_script[hue_devs].index[3]>0) { + // sat + uint32_t sat=glob_script_mem.fvars[hue_script[hue_devs].index[3]-1] ; + if (sat > 254) sat = 254; + if (sat < 1) sat = 1; + light_status += "\"sat\":"; + light_status += String(sat); + light_status += ","; + } + if (hue_script[hue_devs].index[4]>0) { + // ct + uint32_t ct=glob_script_mem.fvars[hue_script[hue_devs].index[4]-1]; + light_status += "\"ct\":"; + light_status += String(ct); + light_status += ","; + } + + response->replace("{light_status}", light_status); + response->replace("{j1",hue_script[hue_devs].name); + response->replace("{j2", GetHueDeviceId(hue_devs<<8)); + + if (hue_script[hue_devs].type=='E') { + response->replace("{type}","Extended color light"); + } else { + response->replace("{type}","color light"); + } + + +} + +void Script_Check_Hue(String *response) { + if (!bitRead(Settings.rule_enabled, 0)) return; + + uint8_t hue_script_found=Run_Scripter(">H",-2,0); + if (hue_script_found!=99) return; + + char line[128]; + char tmp[128]; + uint8_t hue_devs=0; + uint8_t vindex=0; + char *cp; + char *lp=glob_script_mem.section_ptr+2; + while (lp) { + SCRIPT_SKIP_SPACES + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + // check this line + memcpy(line,lp,sizeof(line)); + line[sizeof(line)-1]=0; + cp=line; + for (uint32_t i=0; i>>>"); + toLog(response->c_str()); + toLog(response->c_str()+LOGSZ); +#endif +} + +const char sHUE_LIGHT_RESPONSE_JSON[] PROGMEM = + "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; +const char sHUE_ERROR_JSON[] PROGMEM = + "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; + + +// get alexa arguments +void Script_Handle_Hue(String *path) { + String response; + int code = 200; + uint16_t tmp = 0; + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = 254; + uint16_t ct = 0; + bool resp = false; + + uint8_t device = DecodeLightId(atoi(path->c_str())); + uint8_t index = device-devices_present-1; + + if (WebServer->args()) { + response = "["; + + StaticJsonBuffer<400> jsonBuffer; + JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); + if (hue_json.containsKey("on")) { + + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "on"); + + bool on = hue_json["on"]; + switch(on) + { + case false : glob_script_mem.fvars[hue_script[index].index[0]-1]=0; + response.replace("{re", "false"); + break; + case true : glob_script_mem.fvars[hue_script[index].index[0]-1]=1; + response.replace("{re", "true"); + break; + } + glob_script_mem.type[hue_script[index].vindex[0]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("bri")) { // Brightness is a scale from 1 (the minimum the light is capable of) to 254 (the maximum). Note: a brightness of 1 is not off. + tmp = hue_json["bri"]; + bri=tmp; + if (254 <= bri) { bri = 255; } + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "bri"); + response.replace("{re", String(tmp)); + glob_script_mem.fvars[hue_script[index].index[1]-1]=bri; + glob_script_mem.type[hue_script[index].vindex[1]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("hue")) { // The hue value is a wrapping value between 0 and 65535. Both 0 and 65535 are red, 25500 is green and 46920 is blue. + tmp = hue_json["hue"]; + //hue = changeUIntScale(tmp, 0, 65535, 0, 359); + //tmp = changeUIntScale(hue, 0, 359, 0, 65535); + hue=tmp; + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "hue"); + response.replace("{re", String(tmp)); + glob_script_mem.fvars[hue_script[index].index[2]-1]=hue; + glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("sat")) { // Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white). + tmp = hue_json["sat"]; + sat=tmp; + if (254 <= sat) { sat = 255; } + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "sat"); + response.replace("{re", String(tmp)); + glob_script_mem.fvars[hue_script[index].index[3]-1]=sat; + glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm) + ct = hue_json["ct"]; + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "ct"); + response.replace("{re", String(ct)); + glob_script_mem.fvars[hue_script[index].index[4]-1]=ct; + glob_script_mem.type[hue_script[index].vindex[4]].bits.changed=1; + resp = true; + } + response += "]"; + + } else { + response = FPSTR(sHUE_ERROR_JSON); + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); + WSSend(code, CT_JSON, response); + if (resp) { + Run_Scripter(">E",2,0); + } +} +#endif // hue interface + + #ifdef USE_SCRIPT_SUB_COMMAND bool Script_SubCmd(void) { if (!bitRead(Settings.rule_enabled, 0)) return false; + if (tasm_cmd_activ) return false; + + char command[CMDSZ]; + strlcpy(command,XdrvMailbox.topic,CMDSZ); + uint32_t pl=XdrvMailbox.payload; + char pld[64]; + strlcpy(pld,XdrvMailbox.data,sizeof(pld)); + char cmdbuff[128]; char *cp=cmdbuff; *cp++='#'; @@ -3377,7 +3720,14 @@ bool Script_SubCmd(void) { uint32_t res=Run_Scripter(cmdbuff,tlen+1,0); //AddLog_P2(LOG_LEVEL_INFO,">>%d",res); if (res) return false; - else return true; + else { + if (pl>=0) { + Response_P(S_JSON_COMMAND_NVALUE, command, pl); + } else { + Response_P(S_JSON_COMMAND_SVALUE, command, pld); + } + } + return true; } #endif @@ -3400,22 +3750,10 @@ bool ScriptCommand(void) { bool serviced = true; uint8_t index = XdrvMailbox.index; + if (tasm_cmd_activ) return false; + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kScriptCommands); if (-1 == command_code) { -#ifdef USE_SCRIPT_SUB_COMMAND - strlcpy(command,XdrvMailbox.topic,CMDSZ); - uint32_t pl=XdrvMailbox.payload; - char pld[64]; - strlcpy(pld,XdrvMailbox.data,sizeof(pld)); - if (Script_SubCmd()) { - if (pl>=0) { - Response_P(S_JSON_COMMAND_NVALUE, command, pl); - } else { - Response_P(S_JSON_COMMAND_SVALUE, command, pld); - } - return serviced; - } -#endif serviced = false; // Unknown command } else if ((CMND_SCRIPT == command_code) && (index > 0)) { @@ -4085,6 +4423,7 @@ bool Xdrv10(uint8_t function) if (bitRead(Settings.rule_enabled, 0)) { Run_Scripter(">B",2,0); fast_script=Run_Scripter(">F",-2,0); + Script_Check_Hue(0); } break; case FUNC_EVERY_100_MSECOND: diff --git a/sonoff/xdrv_20_hue.ino b/sonoff/xdrv_20_hue.ino index 0299aba14..49eaf2dc8 100644 --- a/sonoff/xdrv_20_hue.ino +++ b/sonoff/xdrv_20_hue.ino @@ -276,12 +276,6 @@ void HueLightStatus1(uint8_t device, String *response) if (bri > 254) bri = 254; // Philips Hue bri is between 1 and 254 if (bri < 1) bri = 1; -#ifdef USE_SHUTTER - if (ShutterState(device)) { - bri = (float)(Settings.shutter_invert[device-1] ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100; - } -#endif - if (light_type) { light_state.getHSB(&hue, &sat, nullptr); @@ -458,6 +452,7 @@ void HueGlobalConfig(String *path) response += ",\""; } } + response += F("},\"groups\":{},\"schedules\":{},\"config\":"); HueConfigResponse(&response); response += "}"; @@ -503,12 +498,23 @@ void HueLights(String *path) response += ",\""; } } +#ifdef USE_SCRIPT + Script_Check_Hue(&response); +#endif response += "}"; + } else if (path->endsWith("/state")) { // Got ID/state path->remove(0,8); // Remove /lights/ path->remove(path->indexOf("/state")); // Remove /state device = DecodeLightId(atoi(path->c_str())); + +#ifdef USE_SCRIPT + if (device>devices_present) { + return Script_Handle_Hue(path); + } +#endif + if ((device < 1) || (device > maxhue)) { device = 1; } @@ -525,32 +531,19 @@ void HueLights(String *path) response.replace("{id", String(EncodeLightId(device))); response.replace("{cm", "on"); -#ifdef USE_SHUTTER - if (ShutterState(device)) { - if (!change) { - on = hue_json["on"]; - bri = on ? 1.0f : 0.0f; // when bri is not part of this request then calculate it - change = true; - } - response.replace("{re", on ? "true" : "false"); - } else { -#endif - on = hue_json["on"]; - switch(on) - { - case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); - response.replace("{re", "false"); - break; - case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); - response.replace("{re", "true"); - break; - default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); - break; - } - resp = true; -#ifdef USE_SHUTTER + on = hue_json["on"]; + switch(on) + { + case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); + response.replace("{re", "false"); + break; + case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); + response.replace("{re", "true"); + break; + default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); + break; } -#endif // USE_SHUTTER + resp = true; } if (light_type && (local_light_subtype >= LST_SINGLE)) { @@ -656,12 +649,6 @@ void HueLights(String *path) resp = true; } if (change) { -#ifdef USE_SHUTTER - if (ShutterState(device)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_invert[device-1]); - SetShutterPosition(device, bri * 100.0f ); - } else -#endif if (light_type && (local_light_subtype > LST_NONE)) { // not relay if (!Settings.flag3.pwm_multi_channels) { if (g_gotct) { @@ -695,17 +682,27 @@ void HueLights(String *path) AddLog_P2(LOG_LEVEL_DEBUG_MORE, "/lights path=%s", path->c_str()); path->remove(0,8); // Remove /lights/ device = DecodeLightId(atoi(path->c_str())); + +#ifdef USE_SCRIPT + if (device>devices_present) { + Script_HueStatus(&response,device-devices_present-1); + goto exit; + } +#endif + if ((device < 1) || (device > maxhue)) { device = 1; } response += F("{\"state\":"); HueLightStatus1(device, &response); HueLightStatus2(device, &response); + } else { response = "{}"; code = 406; } + exit: AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); WSSend(code, CT_JSON, response); } From 768c264d04d5ee2e863746297485e3ef57f40b14 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Mon, 30 Sep 2019 10:31:13 +0200 Subject: [PATCH 2011/2222] Update xdrv_20_hue.ino --- sonoff/xdrv_20_hue.ino | 54 +++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/sonoff/xdrv_20_hue.ino b/sonoff/xdrv_20_hue.ino index 49eaf2dc8..a37caa559 100644 --- a/sonoff/xdrv_20_hue.ino +++ b/sonoff/xdrv_20_hue.ino @@ -276,6 +276,12 @@ void HueLightStatus1(uint8_t device, String *response) if (bri > 254) bri = 254; // Philips Hue bri is between 1 and 254 if (bri < 1) bri = 1; +#ifdef USE_SHUTTER + if (ShutterState(device)) { + bri = (float)(Settings.shutter_invert[device-1] ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100; + } +#endif + if (light_type) { light_state.getHSB(&hue, &sat, nullptr); @@ -452,7 +458,6 @@ void HueGlobalConfig(String *path) response += ",\""; } } - response += F("},\"groups\":{},\"schedules\":{},\"config\":"); HueConfigResponse(&response); response += "}"; @@ -502,7 +507,6 @@ void HueLights(String *path) Script_Check_Hue(&response); #endif response += "}"; - } else if (path->endsWith("/state")) { // Got ID/state path->remove(0,8); // Remove /lights/ @@ -531,19 +535,32 @@ void HueLights(String *path) response.replace("{id", String(EncodeLightId(device))); response.replace("{cm", "on"); - on = hue_json["on"]; - switch(on) - { - case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); - response.replace("{re", "false"); - break; - case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); - response.replace("{re", "true"); - break; - default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); - break; +#ifdef USE_SHUTTER + if (ShutterState(device)) { + if (!change) { + on = hue_json["on"]; + bri = on ? 1.0f : 0.0f; // when bri is not part of this request then calculate it + change = true; + } + response.replace("{re", on ? "true" : "false"); + } else { +#endif + on = hue_json["on"]; + switch(on) + { + case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); + response.replace("{re", "false"); + break; + case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); + response.replace("{re", "true"); + break; + default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); + break; + } + resp = true; +#ifdef USE_SHUTTER } - resp = true; +#endif // USE_SHUTTER } if (light_type && (local_light_subtype >= LST_SINGLE)) { @@ -649,6 +666,12 @@ void HueLights(String *path) resp = true; } if (change) { +#ifdef USE_SHUTTER + if (ShutterState(device)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_invert[device-1]); + SetShutterPosition(device, bri * 100.0f ); + } else +#endif if (light_type && (local_light_subtype > LST_NONE)) { // not relay if (!Settings.flag3.pwm_multi_channels) { if (g_gotct) { @@ -687,7 +710,7 @@ void HueLights(String *path) if (device>devices_present) { Script_HueStatus(&response,device-devices_present-1); goto exit; - } +} #endif if ((device < 1) || (device > maxhue)) { @@ -696,7 +719,6 @@ void HueLights(String *path) response += F("{\"state\":"); HueLightStatus1(device, &response); HueLightStatus2(device, &response); - } else { response = "{}"; From 8f2ba87ceda6f54970ad4d4478973597dffa24cf Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Mon, 30 Sep 2019 10:41:04 +0200 Subject: [PATCH 2012/2222] Update xdrv_10_scripter.ino --- sonoff/xdrv_10_scripter.ino | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index 0d3307490..ce0430f8f 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -1646,6 +1646,20 @@ chknext: goto exit; } #endif + +#ifdef USE_SHUTTER + if (!strncmp(vname,"sht[",4)) { + GetNumericResult(vname+4,OPER_EQU,&fvar,0); + uint8_t index=fvar; + if (index<=shutters_present) { + fvar=Settings.shutter_position[index-1]; + } else { + fvar=-1; + } + len+=1; + goto exit; + } +#endif break; case 't': if (!strncmp(vname,"time",4)) { From 62cda21cecce85165ac1c668832b9c6f4801247e Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Mon, 30 Sep 2019 10:53:16 +0200 Subject: [PATCH 2013/2222] sml fix obis dump mode --- sonoff/xsns_53_sml.ino | 73 +++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/sonoff/xsns_53_sml.ino b/sonoff/xsns_53_sml.ino index 77c88bd36..4b74e7d73 100644 --- a/sonoff/xsns_53_sml.ino +++ b/sonoff/xsns_53_sml.ino @@ -847,13 +847,15 @@ uint8_t Serial_peek() { return meter_ss[num-1]->peek(); } +uint8_t sml_logindex; + void Dump2log(void) { int16_t index=0,hcnt=0; uint32_t d_lastms; uint8_t dchars[16]; - if (!SML_SAVAILABLE) return; + //if (!SML_SAVAILABLE) return; if (dump2log&8) { // combo mode @@ -898,7 +900,25 @@ uint8_t dchars[16]; } } } else { - //while (SML_SAVAILABLE) { + if (meter_desc_p[(dump2log&7)-1].type=='o') { + // obis + while (SML_SAVAILABLE) { + char c=SML_SREAD&0x7f; + if (c=='\n' || c=='\r') { + log_data[sml_logindex]=0; + AddLog(LOG_LEVEL_INFO); + sml_logindex=2; + log_data[0]=':'; + log_data[1]=' '; + break; + } + log_data[sml_logindex]=c; + if (sml_logindex0) { + if (index>2) { log_data[index]=0; AddLog(LOG_LEVEL_INFO); } } - //} - + } } // skip sml entries @@ -1750,6 +1761,7 @@ void SML_Show(boolean json) { } +/* #ifdef USE_DOMOTICZ if (json && !tele_period) { char str[16]; @@ -1761,6 +1773,7 @@ void SML_Show(boolean json) { DomoticzSensor(DZ_CURRENT, str); // Current } #endif // USE_DOMOTICZ +*/ } struct SML_COUNTER { From 7689534cf514e4b554e661eea06696ba036b26b9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 30 Sep 2019 11:21:43 +0200 Subject: [PATCH 2014/2222] Refactor shutter support Refactor shutter support (#6516) --- sonoff/sonoff.ino | 3 +- sonoff/xdrv_20_hue.ino | 2 +- sonoff/xdrv_27_shutter.ino | 286 +++++++++++++++++++------------------ 3 files changed, 148 insertions(+), 143 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 1e4cee99c..07862a9a5 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -96,7 +96,6 @@ power_t blink_mask = 0; // Blink relay active mask power_t blink_powersave; // Blink start power save state power_t latching_power = 0; // Power state at latching start power_t rel_inverted = 0; // Relay inverted flag (1 = (0 = On, 1 = Off)) -power_t shutter_mask = 0; // Bit Array to mark all relays that belong to at least one shutter int baudrate = APP_BAUDRATE; // Serial interface baud rate int serial_in_byte_counter = 0; // Index in receive buffer int ota_state_flag = 0; // OTA state flag @@ -139,7 +138,7 @@ uint8_t seriallog_level; // Current copy of Settings.seriallo uint8_t syslog_level; // Current copy of Settings.syslog_level uint8_t my_module_type; // Current copy of Settings.module or user template type uint8_t my_adc0; // Active copy of Module ADC0 -uint8_t last_source = 0; +uint8_t last_source = 0; // Last command source uint8_t shutters_present = 0; // Number of actual define shutters //uint8_t mdns_delayed_start = 0; // mDNS delayed start bool serial_local = false; // Handle serial locally; diff --git a/sonoff/xdrv_20_hue.ino b/sonoff/xdrv_20_hue.ino index a37caa559..d39da9a4c 100644 --- a/sonoff/xdrv_20_hue.ino +++ b/sonoff/xdrv_20_hue.ino @@ -669,7 +669,7 @@ void HueLights(String *path) #ifdef USE_SHUTTER if (ShutterState(device)) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_invert[device-1]); - SetShutterPosition(device, bri * 100.0f ); + ShutterSetPosition(device, bri * 100.0f ); } else #endif if (light_type && (local_light_subtype > LST_NONE)) { // not relay diff --git a/sonoff/xdrv_27_shutter.ino b/sonoff/xdrv_27_shutter.ino index 2c9bf170d..009912a4c 100644 --- a/sonoff/xdrv_27_shutter.ino +++ b/sonoff/xdrv_27_shutter.ino @@ -17,9 +17,9 @@ along with this program. If not, see . */ -#ifdef USE_SHUTTER // +3.8k code +#ifdef USE_SHUTTER /*********************************************************************************************\ - * Energy + * Shutter or Blind support using two consecutive relays \*********************************************************************************************/ #define XDRV_27 27 @@ -39,6 +39,8 @@ #define D_SHUTTER "SHUTTER" +const uint16_t MOTOR_STOP_TIME = 500; // in mS + enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE }; const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" @@ -51,35 +53,37 @@ void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration }; -const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d}"; +const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"direction\":%d}"; + +#include Ticker TickerShutter; -const uint16_t MOTOR_STOP_TIME=500; // in mS +struct SHUTTER { + power_t mask = 0; // bit mask with 11 at the position of relays that belong to at least ONE shutter + power_t old_power = 0; // preserve old bitmask for power to extract the relay that changes. + power_t switched_relay = 0; // bitmatrix that contain the relays that was lastly changed. + uint32_t time[MAX_SHUTTERS]; + int32_t open_max[MAX_SHUTTERS]; // max value on maximum open calculated + int32_t target_position[MAX_SHUTTERS]; // position to go to + int32_t start_position[MAX_SHUTTERS]; + int32_t real_position[MAX_SHUTTERS]; // value between 0 and Shutter.open_max + uint16_t open_time[MAX_SHUTTERS]; // duration to open the shutter + uint16_t close_time[MAX_SHUTTERS]; // duration to close the shutter + uint16_t close_velocity[MAX_SHUTTERS]; // in relation to open velocity. higher value = faster + uint16_t operations[MAX_SHUTTERS]; + int8_t direction[MAX_SHUTTERS]; // 1 == UP , 0 == stop; -1 == down + uint8_t mode = 0; // operation mode definition. see enum type above SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE +} Shutter; -uint16_t Shutter_Open_Time[MAX_SHUTTERS] ; // duration to open the shutter -uint16_t Shutter_Close_Time[MAX_SHUTTERS]; // duration to close the shutter -int32_t Shutter_Open_Max[MAX_SHUTTERS]; // max value on maximum open calculated -int32_t Shutter_Target_Position[MAX_SHUTTERS] ; // position to go to -int32_t Shutter_Start_Position[MAX_SHUTTERS] ; -uint16_t Shutter_Close_Velocity[MAX_SHUTTERS]; // in relation to open velocity. higher value = faster -uint16_t Shutter_Operations[MAX_SHUTTERS]; -int8_t Shutter_Direction[MAX_SHUTTERS]; // 1 == UP , 0 == stop; -1 == down -int32_t Shutter_Real_Position[MAX_SHUTTERS]; // value between 0 and Shutter_Open_Max -//power_t shutter_mask = 0; // bit mask with 11 at the position of relays that belong to at least ONE shutter -power_t old_power = power; // preserve old bitmask for power to extract the relay that changes. -power_t SwitchedRelay = 0; // bitmatrix that contain the relays that was lastly changed. -uint32_t shutter_time[MAX_SHUTTERS] ; -uint8_t shutterMode = 0; // operation mode definition. see enum type above OFF_OPEN-OFF_CLOSE, OFF_ON-OPEN_CLOSE, PULSE_OPEN-PULSE_CLOSE - -void Rtc_ms50_Second() +void ShutterRtc50mS(void) { - for (byte i=0;i < MAX_SHUTTERS; i++) { - shutter_time[i]++; + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + Shutter.time[i]++; } } -int32_t percent_to_realposition(uint8_t percent,uint8_t index) +int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t index) { if (Settings.shutter_set50percent[index] != 50) { return percent <= 5 ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; @@ -88,7 +92,7 @@ int32_t percent_to_realposition(uint8_t percent,uint8_t index) } } -uint8_t realposition_to_percent(int32_t realpos, uint8_t index) +uint8_t ShutterRealToPercentlPosition(int32_t realpos, uint8_t index) { if (Settings.shutter_set50percent[index] != 50) { return Settings.shuttercoeff[2][index] * 5 > realpos ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index]; @@ -97,19 +101,19 @@ uint8_t realposition_to_percent(int32_t realpos, uint8_t index) } } -void ShutterInit() +void ShutterInit(void) { shutters_present = 0; - shutter_mask = 0; + Shutter.mask = 0; //Initialize to get relay that changed - old_power = power; + Shutter.old_power = power; char shutter_open_chr[10]; char shutter_close_chr[10]; bool relay_in_interlock = false; AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Accuracy digits: %d"), Settings.shutter_accuracy); - for (byte i=0;i < MAX_SHUTTERS; i++) { + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { // upgrade to 0.1sec calculation base. if ( Settings.shutter_accuracy == 0) { Settings.shutter_closetime[i] = Settings.shutter_closetime[i] * 10; @@ -121,49 +125,53 @@ void ShutterInit() shutters_present++; // Determine shutter types - shutter_mask |= 3 << (Settings.shutter_startrelay[i] -1) ; + Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1) ; - for (uint8_t i = 0; i < MAX_INTERLOCKS * Settings.flag.interlock; i++) { - //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Interlock state i=%d %d, flag %d, , shuttermask %d, maskedIL %d"),i, Settings.interlock[i], Settings.flag.interlock,shutter_mask, Settings.interlock[i]&shutter_mask); - if (Settings.interlock[i] && Settings.interlock[i] & shutter_mask) { + for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings.flag.interlock; j++) { + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Interlock state i=%d %d, flag %d, , shuttermask %d, maskedIL %d"),i, Settings.interlock[i], Settings.flag.interlock,Shutter.mask, Settings.interlock[i]&Shutter.mask); + if (Settings.interlock[j] && Settings.interlock[j] & Shutter.mask) { //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Relay in Interlock group")); relay_in_interlock = true; } } - if ( relay_in_interlock) { + if (relay_in_interlock) { if (Settings.pulse_timer[i] > 0) { - shutterMode = SHT_PULSE_OPEN__PULSE_CLOSE; + Shutter.mode = SHT_PULSE_OPEN__PULSE_CLOSE; } else { - shutterMode = SHT_OFF_OPEN__OFF_CLOSE; + Shutter.mode = SHT_OFF_OPEN__OFF_CLOSE; } } else { - shutterMode = SHT_OFF_ON__OPEN_CLOSE; + Shutter.mode = SHT_OFF_ON__OPEN_CLOSE; } - TickerShutter.attach_ms(50, Rtc_ms50_Second ); + TickerShutter.attach_ms(50, ShutterRtc50mS ); // default the 50 percent should not have any impact without changing it. set to 60 Settings.shutter_set50percent[i] = (Settings.shutter_set50percent[i] == 0 ? 50 : Settings.shutter_set50percent[i]); // use 10 sec. as default to allow everybody to play without deep initialize - Shutter_Open_Time[i] = Settings.shutter_opentime[i] > 0 ? Settings.shutter_opentime[i] : 100; - Shutter_Close_Time[i] = Settings.shutter_closetime[i] > 0 ? Settings.shutter_closetime[i] : 100; + Shutter.open_time[i] = Settings.shutter_opentime[i] > 0 ? Settings.shutter_opentime[i] : 100; + Shutter.close_time[i] = Settings.shutter_closetime[i] > 0 ? Settings.shutter_closetime[i] : 100; // Update Calculation 20 because time interval is 0.05 sec - Shutter_Open_Max[i] = 200 * Shutter_Open_Time[i]; - Shutter_Close_Velocity[i] = Shutter_Open_Max[i] / Shutter_Close_Time[i] / 2 ; + Shutter.open_max[i] = 200 * Shutter.open_time[i]; + Shutter.close_velocity[i] = Shutter.open_max[i] / Shutter.close_time[i] / 2 ; // calculate a ramp slope at the first 5 percent to compensate that shutters move with down part later than the upper part - Settings.shuttercoeff[1][i] = Shutter_Open_Max[i] * (100 - Settings.shutter_set50percent[i] ) / 5000; - Settings.shuttercoeff[0][i] = Shutter_Open_Max[i] - (Settings.shuttercoeff[1][i] * 100); + Settings.shuttercoeff[1][i] = Shutter.open_max[i] * (100 - Settings.shutter_set50percent[i] ) / 5000; + Settings.shuttercoeff[0][i] = Shutter.open_max[i] - (Settings.shuttercoeff[1][i] * 100); Settings.shuttercoeff[2][i] = (Settings.shuttercoeff[0][i] + 5 * Settings.shuttercoeff[1][i]) / 5; - shutter_mask |= 3 << (Settings.shutter_startrelay[i] -1) ; + Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1) ; - Shutter_Real_Position[i] = percent_to_realposition(Settings.shutter_position[i], i); - //Shutter_Real_Position[i] = Settings.shutter_position[i] <= 5 ? Settings.shuttercoeff[2][i] * Settings.shutter_position[i] : Settings.shuttercoeff[1][i] * Settings.shutter_position[i] + Settings.shuttercoeff[0,i]; - Shutter_Start_Position[i] = Shutter_Real_Position[i]; - dtostrfd((double)Shutter_Open_Time[i] / 10 , 1, shutter_open_chr); - dtostrfd((double)Shutter_Close_Time[i] / 10, 1, shutter_close_chr); + Shutter.real_position[i] = ShutterPercentToRealPosition(Settings.shutter_position[i], i); + //Shutter.real_position[i] = Settings.shutter_position[i] <= 5 ? Settings.shuttercoeff[2][i] * Settings.shutter_position[i] : Settings.shuttercoeff[1][i] * Settings.shutter_position[i] + Settings.shuttercoeff[0,i]; + Shutter.start_position[i] = Shutter.real_position[i]; + dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr); + dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr); + + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoedffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d"), + i, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr, + Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], + Shutter.mask, Settings.shutter_invert[i], Shutter.mode); - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoedffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d"), i, Settings.shutter_startrelay[i],Shutter_Real_Position[i],Settings.shutter_position[i], Shutter_Close_Velocity[i] , Shutter_Open_Max[i], shutter_open_chr, shutter_close_chr,Settings.shuttercoeff[0][i],Settings.shuttercoeff[1][i],Settings.shuttercoeff[2][i],Settings.shuttercoeff[3][i],Settings.shuttercoeff[4][i],shutter_mask,Settings.shutter_invert[i],shutterMode ); } else { // terminate loop at first INVALID shutter. break; @@ -172,43 +180,43 @@ void ShutterInit() } } -void Schutter_Update_Position() +void ShutterUpdatePosition(void) { char scommand[CMDSZ]; char stopic[TOPSZ]; - for (byte i=0; i < shutters_present; i++) { - if (Shutter_Direction[i] != 0) { + for (uint32_t i = 0; i < shutters_present; i++) { + if (Shutter.direction[i] != 0) { //char stemp1[20]; - Shutter_Real_Position[i] = Shutter_Start_Position[i] + ( shutter_time[i] * (Shutter_Direction[i] > 0 ? 100 : -Shutter_Close_Velocity[i])); + Shutter.real_position[i] = Shutter.start_position[i] + ( Shutter.time[i] * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); // avoid real position leaving the boundaries. - Shutter_Real_Position[i] = Shutter_Real_Position[i] < 0 ? 0 : (Shutter_Real_Position[i] > Shutter_Open_Max[i] ? Shutter_Open_Max[i] : Shutter_Real_Position[i]) ; + Shutter.real_position[i] = Shutter.real_position[i] < 0 ? 0 : (Shutter.real_position[i] > Shutter.open_max[i] ? Shutter.open_max[i] : Shutter.real_position[i]) ; // Add additional runtime, if shutter did not reach the endstop for some time. - if (Shutter_Target_Position[i] == Shutter_Real_Position[i] && Shutter_Target_Position[i] == 0) { + if (Shutter.target_position[i] == Shutter.real_position[i] && Shutter.target_position[i] == 0) { // for every operation add 5x50ms = 250ms to stop position //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Adding additional runtime")); - Shutter_Real_Position[i] += 500 * Shutter_Operations[i] ; - Shutter_Operations[i] = 0; + Shutter.real_position[i] += 500 * Shutter.operations[i] ; + Shutter.operations[i] = 0; } - if (Shutter_Real_Position[i] * Shutter_Direction[i] >= Shutter_Target_Position[i] * Shutter_Direction[i] ) { + if (Shutter.real_position[i] * Shutter.direction[i] >= Shutter.target_position[i] * Shutter.direction[i] ) { // calculate relay number responsible for current movement. - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Condition detected: real: %d, Target: %d, direction: %d"),Shutter_Real_Position[i], Shutter_Target_Position[i],Shutter_Direction[i]); - uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter_Direction[i] == 1 ? 0 : 1) ; + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Condition detected: real: %d, Target: %d, direction: %d"),Shutter.real_position[i], Shutter.target_position[i],Shutter.direction[i]); + uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter.direction[i] == 1 ? 0 : 1) ; char stemp2[10]; - Settings.shutter_position[i] = realposition_to_percent(Shutter_Real_Position[i], i); - //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter_Real_Position[i] ? (Shutter_Real_Position[i] * 10 / Settings.shuttercoeff[2][i] + 4)/10 : ((Shutter_Real_Position[i]-Settings.shuttercoeff[0,i]) *10 / Settings.shuttercoeff[1][i] +4) / 10; + Settings.shutter_position[i] = ShutterRealToPercentlPosition(Shutter.real_position[i], i); + //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? (Shutter.real_position[i] * 10 / Settings.shuttercoeff[2][i] + 4)/10 : ((Shutter.real_position[i]-Settings.shuttercoeff[0,i]) *10 / Settings.shuttercoeff[1][i] +4) / 10; if (0 < Settings.shutter_position[i] && Settings.shutter_position[i] < 100) { - Shutter_Operations[i]++; + Shutter.operations[i]++; } else { - Shutter_Operations[i] = 0; + Shutter.operations[i] = 0; } - dtostrfd((double)shutter_time[i] / 20, 1, stemp2); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos. %d, Stoppos: %ld, relay: %d, direction %d, pulsetimer: %d, rtcshutter: %s [s], operationtime %d"), i, Shutter_Real_Position[i], Settings.shutter_position[i], cur_relay -1, Shutter_Direction[i], Settings.pulse_timer[cur_relay -1], stemp2, Shutter_Operations[i]); - Shutter_Start_Position[i] = Shutter_Real_Position[i]; + dtostrfd((float)Shutter.time[i] / 20, 1, stemp2); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos. %d, Stoppos: %ld, relay: %d, direction %d, pulsetimer: %d, rtcshutter: %s [s], operationtime %d"), i, Shutter.real_position[i], Settings.shutter_position[i], cur_relay -1, Shutter.direction[i], Settings.pulse_timer[cur_relay -1], stemp2, Shutter.operations[i]); + Shutter.start_position[i] = Shutter.real_position[i]; // sending MQTT result to broker snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); @@ -216,7 +224,7 @@ void Schutter_Update_Position() Response_P("%d", Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); MqttPublish(stopic, Settings.flag.mqtt_power_retain); - switch (shutterMode) { + switch (Shutter.mode) { case SHT_PULSE_OPEN__PULSE_CLOSE: // we have a momentary switch here. Needs additional pulse on same relay after the end if (SRC_PULSETIMER == last_source || SRC_SHUTTER == last_source || SRC_WEBGUI == last_source) { @@ -239,52 +247,51 @@ void Schutter_Update_Position() } break; } - Shutter_Direction[i] = 0; - byte position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; + Shutter.direction[i] = 0; + uint8_t position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; Response_P(PSTR("{")); - ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, 0 /*Shutter_Direction[i]*/); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, 0 /*Shutter.direction[i]*/); ResponseJsonEnd(); MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); XdrvRulesProcess(); } } } - } bool ShutterState(uint8_t device) { device--; device &= 3; - return (Settings.flag3.shutter_mode && (shutter_mask & (1 << (Settings.shutter_startrelay[device]-1))) ); + return (Settings.flag3.shutter_mode && (Shutter.mask & (1 << (Settings.shutter_startrelay[device]-1))) ); } -void Shutter_StartInit (uint8_t index, uint8_t direction, int32_t target_pos) +void ShutterStartInit(uint8_t index, uint8_t direction, int32_t target_pos) { - Shutter_Direction[index] = direction; - Shutter_Target_Position[index] = target_pos; - Shutter_Start_Position[index] = Shutter_Real_Position[index]; - shutter_time[index] = 0; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter_Start_Position[index], Shutter_Target_Position[index], Shutter_Direction[index]); + Shutter.direction[index] = direction; + Shutter.target_position[index] = target_pos; + Shutter.start_position[index] = Shutter.real_position[index]; + Shutter.time[index] = 0; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter.start_position[index], Shutter.target_position[index], Shutter.direction[index]); } -void DelayForMotorStop() +void ShutterDelayForMotorStop(void) { AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop %d"), MOTOR_STOP_TIME); delay(MOTOR_STOP_TIME); } -void Schutter_Report_Position() +void ShutterReportPosition(void) { uint16_t shutter_moving = 0; - for (byte i=0; i < shutters_present; i++) { - if (Shutter_Direction[i] != 0) { + for (uint32_t i = 0; i < shutters_present; i++) { + if (Shutter.direction[i] != 0) { char stemp1[20]; char stemp2[10]; - dtostrfd((double)shutter_time[i] / 20, 1, stemp2); + dtostrfd((float)Shutter.time[i] / 20, 1, stemp2); shutter_moving = 1; - //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter_Real_Position[i] ? Shutter_Real_Position[i] / Settings.shuttercoeff[2][i] : (Shutter_Real_Position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d, Target %d, source: %s, start-pos: %d %%, direction: %d, rtcshutter: %s [s]"), i,Shutter_Real_Position[i], Shutter_Target_Position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), Settings.shutter_position[i], Shutter_Direction[i], stemp2 ); + //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? Shutter.real_position[i] / Settings.shuttercoeff[2][i] : (Shutter.real_position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d, Target %d, source: %s, start-pos: %d %%, direction: %d, rtcshutter: %s [s]"), i,Shutter.real_position[i], Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), Settings.shutter_position[i], Shutter.direction[i], stemp2 ); } } if (rules_flag.shutter_moving > shutter_moving) { @@ -296,51 +303,50 @@ void Schutter_Report_Position() //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); } -void Shutter_Relay_changed() +void ShutterRelayChanged(void) { - // SwitchedRelay = binary relay that was recently changed and cause an Action + // Shutter.switched_relay = binary relay that was recently changed and cause an Action // powerstate_local = binary powermatrix and relays from shutter: 0..3 // relays_changed = bool if one of the relays that belong to the shutter changed not by shutter or pulsetimer char stemp1[10]; - - for (byte i=0; i < shutters_present; i++) { + for (uint32_t i = 0; i < shutters_present; i++) { power_t powerstate_local = (power >> (Settings.shutter_startrelay[i] -1)) & 3; - //uint8 manual_relays_changed = ((SwitchedRelay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_IGNORE != last_source && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; - uint8 manual_relays_changed = ((SwitchedRelay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; + //uint8 manual_relays_changed = ((Shutter.switched_relay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_IGNORE != last_source && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; + uint8 manual_relays_changed = ((Shutter.switched_relay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; if (manual_relays_changed) { - if (shutterMode == SHT_OFF_ON__OPEN_CLOSE) { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { switch (powerstate_local) { case 1: - DelayForMotorStop(); - Shutter_StartInit(i, 1, Shutter_Open_Max[i]); + ShutterDelayForMotorStop(); + ShutterStartInit(i, 1, Shutter.open_max[i]); break; case 3: - DelayForMotorStop(); - Shutter_StartInit(i, -1, 0); + ShutterDelayForMotorStop(); + ShutterStartInit(i, -1, 0); break; default: - Shutter_Direction[i] = 0; - Shutter_Target_Position[i] = Shutter_Real_Position[i]; + Shutter.direction[i] = 0; + Shutter.target_position[i] = Shutter.real_position[i]; } } else { - if (Shutter_Direction[i] != 0 && (!powerstate_local || (powerstate_local && shutterMode == SHT_PULSE_OPEN__PULSE_CLOSE))) { - Shutter_Target_Position[i] = Shutter_Real_Position[i]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, switchedRelay %d, manual change %d"), i, Shutter_Target_Position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,SwitchedRelay,manual_relays_changed); + if (Shutter.direction[i] != 0 && (!powerstate_local || (powerstate_local && Shutter.mode == SHT_PULSE_OPEN__PULSE_CLOSE))) { + Shutter.target_position[i] = Shutter.real_position[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i, Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed); } else { last_source = SRC_SHUTTER; // avoid switch off in the next loop if (powerstate_local == 2) { // testing on CLOSE relay, if ON // close with relay two - DelayForMotorStop(); - Shutter_StartInit(i, -1, 0); + ShutterDelayForMotorStop(); + ShutterStartInit(i, -1, 0); } else { // opens with relay one - DelayForMotorStop(); - Shutter_StartInit(i, 1, Shutter_Open_Max[i]); + ShutterDelayForMotorStop(); + ShutterStartInit(i, 1, Shutter.open_max[i]); } } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i, Shutter_Target_Position[i], powerstate_local); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i, Shutter.target_position[i], powerstate_local); } } } @@ -352,7 +358,7 @@ void Shutter_Relay_changed() // device: 1.. // position: 0-100 -void SetShutterPosition(uint8_t device, uint8_t position) +void ShutterSetPosition(uint8_t device, uint8_t position) { char svalue[32]; // Command and number parameter snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION "%d %d"), device, position); @@ -381,12 +387,12 @@ void CmndShutterStop(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { uint32_t index = XdrvMailbox.index -1; - if (Shutter_Direction[index] != 0) { + if (Shutter.direction[index] != 0) { - //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving shutter %d: direction:%d"), XdrvMailbox.index, Shutter_Direction[index]); + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving shutter %d: direction: %d"), XdrvMailbox.index, Shutter.direction[index]); - int32_t temp_realpos = Shutter_Start_Position[index] + ( (shutter_time[index]+10) * (Shutter_Direction[index] > 0 ? 100 : -Shutter_Close_Velocity[index])); - XdrvMailbox.payload = realposition_to_percent(temp_realpos, index); + int32_t temp_realpos = Shutter.start_position[index] + ( (Shutter.time[index]+10) * (Shutter.direction[index] > 0 ? 100 : -Shutter.close_velocity[index])); + XdrvMailbox.payload = ShutterRealToPercentlPosition(temp_realpos, index); //XdrvMailbox.payload = Settings.shuttercoeff[2][index] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][index] : (temp_realpos-Settings.shuttercoeff[0,index]) / Settings.shuttercoeff[1][index]; last_source = SRC_WEBGUI; CmndShutterPosition(); @@ -408,44 +414,44 @@ void CmndShutterPosition(void) target_pos_percent = Settings.shutter_invert[index] && SRC_WEBGUI != last_source ? 100 - target_pos_percent : target_pos_percent; if (target_pos_percent != -99) { //target_pos_percent = Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent; - Shutter_Target_Position[index] = percent_to_realposition(target_pos_percent, index); - //Shutter_Target_Position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, realpos %d, target %d, payload %d"), last_source, Shutter_Real_Position[index] ,Shutter_Target_Position[index],target_pos_percent); + Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); + //Shutter.target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, realpos %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); } - if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter_Target_Position[index] - Shutter_Real_Position[index] ) / Shutter_Close_Velocity[index] > 2) { - int8_t new_shutterdirection = Shutter_Real_Position[index] < Shutter_Target_Position[index] ? 1 : -1; - if (Shutter_Direction[index] == -new_shutterdirection ) { + if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter.target_position[index] - Shutter.real_position[index] ) / Shutter.close_velocity[index] > 2) { + int8_t new_shutterdirection = Shutter.real_position[index] < Shutter.target_position[index] ? 1 : -1; + if (Shutter.direction[index] == -new_shutterdirection ) { // direction need to be changed. on momentary switches first stop the Shutter - if (shutterMode == SHT_PULSE_OPEN__PULSE_CLOSE) { + if (Shutter.mode == SHT_PULSE_OPEN__PULSE_CLOSE) { // code for momentary shutters only small switch on to stop Shutter ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); delay(100); } else { ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 1 : 0), 0, SRC_SHUTTER); - DelayForMotorStop(); + ShutterDelayForMotorStop(); } } - if (Shutter_Direction[index] != new_shutterdirection ) { - Shutter_StartInit(index, new_shutterdirection, Shutter_Target_Position[index]); - Shutter_Operations[index]++; - if (shutterMode == SHT_OFF_ON__OPEN_CLOSE) { + if (Shutter.direction[index] != new_shutterdirection ) { + ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); + Shutter.operations[index]++; + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { ExecuteCommandPower(Settings.shutter_startrelay[index] , 0, SRC_SHUTTER); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload); - DelayForMotorStop(); + ShutterDelayForMotorStop(); // Code for shutters with circuit safe configuration, switch the direction Relay ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); // power on ExecuteCommandPower(Settings.shutter_startrelay[index] , 1, SRC_SHUTTER); } else { // now start the motor for the right direction, work for momentary and normal shutters. - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter in direction %d"), Shutter_Direction[index]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter in direction %d"), Shutter.direction[index]); ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay6 5s, xdrv %d"), XdrvMailbox.payload); } - SwitchedRelay = 0; + Shutter.switched_relay = 0; } } else { - target_pos_percent = realposition_to_percent(Shutter_Real_Position[index], index); + target_pos_percent = ShutterRealToPercentlPosition(Shutter.real_position[index], index); } ResponseCmndIdxNumber(Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent); } @@ -483,9 +489,9 @@ void CmndShutterRelay(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64)) { Settings.shutter_startrelay[XdrvMailbox.index-1] = XdrvMailbox.payload; if (XdrvMailbox.payload > 0) { - shutter_mask |= 3 << (XdrvMailbox.payload - 1); + Shutter.mask |= 3 << (XdrvMailbox.payload - 1); } else { - shutter_mask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index-1] - 1); + Shutter.mask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index-1] - 1); } AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Relay %d is %d"), XdrvMailbox.index, XdrvMailbox.payload); Settings.shutter_startrelay[XdrvMailbox.index-1] = XdrvMailbox.payload; @@ -512,8 +518,8 @@ void CmndShutterSetHalfway(void) void CmndShutterSetClose(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - Shutter_Real_Position[XdrvMailbox.index-1] = 0; - Shutter_StartInit(XdrvMailbox.index-1, 0, 0); + Shutter.real_position[XdrvMailbox.index-1] = 0; + ShutterStartInit(XdrvMailbox.index-1, 0, 0); Settings.shutter_position[XdrvMailbox.index-1] = 0; ResponseCmndChar(D_CONFIGURATION_RESET); } @@ -552,10 +558,10 @@ bool Xdrv27(uint8_t function) ShutterInit(); break; case FUNC_EVERY_50_MSECOND: - Schutter_Update_Position(); + ShutterUpdatePosition(); break; case FUNC_EVERY_SECOND: - Schutter_Report_Position(); + ShutterReportPosition(); break; case FUNC_COMMAND: result = DecodeCommand(kShutterCommands, ShutterCommand); @@ -564,7 +570,7 @@ bool Xdrv27(uint8_t function) for (uint32_t i = 0; i < shutters_present; i++) { uint8_t position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; ResponseAppend_P(","); - ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter_Direction[i]); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i]); #ifdef USE_DOMOTICZ if ((0 == tele_period) && (0 == i)) { DomoticzSensor(DZ_SHUTTER, position); @@ -575,10 +581,10 @@ bool Xdrv27(uint8_t function) case FUNC_SET_POWER: char stemp1[10]; // extract the number of the relay that was switched and save for later in Update Position. - SwitchedRelay = power ^ old_power; - old_power = power; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), SwitchedRelay,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource)); - Shutter_Relay_changed(); + Shutter.switched_relay = power ^ Shutter.old_power; + Shutter.old_power = power; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), Shutter.switched_relay,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource)); + ShutterRelayChanged(); break; } } From 9cc4bc67bad5807fe1f6091a37b7faa2c9e8d9d1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 30 Sep 2019 11:34:33 +0200 Subject: [PATCH 2015/2222] Refactor shutter code Refactor shutter code --- sonoff/xdrv_27_shutter.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sonoff/xdrv_27_shutter.ino b/sonoff/xdrv_27_shutter.ino index 009912a4c..e7eaa4250 100644 --- a/sonoff/xdrv_27_shutter.ino +++ b/sonoff/xdrv_27_shutter.ino @@ -92,7 +92,7 @@ int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t index) } } -uint8_t ShutterRealToPercentlPosition(int32_t realpos, uint8_t index) +uint8_t ShutterRealToPercentPosition(int32_t realpos, uint8_t index) { if (Settings.shutter_set50percent[index] != 50) { return Settings.shuttercoeff[2][index] * 5 > realpos ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index]; @@ -205,7 +205,7 @@ void ShutterUpdatePosition(void) uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter.direction[i] == 1 ? 0 : 1) ; char stemp2[10]; - Settings.shutter_position[i] = ShutterRealToPercentlPosition(Shutter.real_position[i], i); + Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? (Shutter.real_position[i] * 10 / Settings.shuttercoeff[2][i] + 4)/10 : ((Shutter.real_position[i]-Settings.shuttercoeff[0,i]) *10 / Settings.shuttercoeff[1][i] +4) / 10; if (0 < Settings.shutter_position[i] && Settings.shutter_position[i] < 100) { @@ -392,7 +392,7 @@ void CmndShutterStop(void) //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving shutter %d: direction: %d"), XdrvMailbox.index, Shutter.direction[index]); int32_t temp_realpos = Shutter.start_position[index] + ( (Shutter.time[index]+10) * (Shutter.direction[index] > 0 ? 100 : -Shutter.close_velocity[index])); - XdrvMailbox.payload = ShutterRealToPercentlPosition(temp_realpos, index); + XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, index); //XdrvMailbox.payload = Settings.shuttercoeff[2][index] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][index] : (temp_realpos-Settings.shuttercoeff[0,index]) / Settings.shuttercoeff[1][index]; last_source = SRC_WEBGUI; CmndShutterPosition(); @@ -451,7 +451,7 @@ void CmndShutterPosition(void) Shutter.switched_relay = 0; } } else { - target_pos_percent = ShutterRealToPercentlPosition(Shutter.real_position[index], index); + target_pos_percent = ShutterRealToPercentPosition(Shutter.real_position[index], index); } ResponseCmndIdxNumber(Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent); } From bed26fd121bb2daef3816faf5395f49a04a7a98c Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Mon, 30 Sep 2019 17:19:15 +0200 Subject: [PATCH 2016/2222] MCP230xx - Add 1 and 0 as option for ON and OFF MCP230xx - Add 1 and 0 as option for ON and OFF --- sonoff/xsns_29_mcp230xx.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index caefb67e8..9eb98b95a 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -628,11 +628,11 @@ bool MCP230xx_Command(void) { #ifdef USE_MCP230xx_OUTPUT if (Settings.mcp230xx_config[pin].pinmode >= 5) { uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "ON")) { + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "ON")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "1"))) { MCP230xx_SetOutPin(pin,abs(pincmd-1)); return serviced; } - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "OFF")) { + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "OFF")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0"))) { MCP230xx_SetOutPin(pin,pincmd); return serviced; } From b38a8bd8eb8ac1f5457764a656bbc0533457fcf9 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Mon, 30 Sep 2019 17:26:07 +0200 Subject: [PATCH 2017/2222] MCP230xx - Add sensor29 pin,1 and sensor29 pin,0 MCP230xx - Add sensor29 pin,1 and sensor29 pin,0 as an alternative to sensor29 pin,ON and sensor29 pin,OFF respectively. --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 5b26d35d3..8429ce360 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -5,6 +5,7 @@ * Add initial support for MQTT logging using command MqttLog (#6498) * Add Zigbee more support - collect endpoints and clusters, added ZigbeeDump command * Add initial support for shutters by Stefan Bode (#288) + * Add use case for sensor29 pin,1 and sensor29 pin,0 to substitute ON and OFF respectively with MCP230xx driver * * 6.6.0.13 20190922 * Add command EnergyReset4 x,x to initialize total usage for two tarrifs From d7d03167693df3dbd227a2e74bb11d9c3ca1386f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 30 Sep 2019 19:27:54 +0200 Subject: [PATCH 2018/2222] Fix open/close to limits Fix open/close to limits (#6516) --- sonoff/sonoff.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 07862a9a5..8f0627b1b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -315,6 +315,7 @@ void SetLatchingRelay(power_t lpower, uint32_t state) void SetDevicePower(power_t rpower, uint32_t source) { ShowSource(source); + last_source = source; if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { // All on and stay on power = (1 << devices_present) -1; From dea255db26d03e7b43dec6e9e35c0f746c1736fc Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Mon, 30 Sep 2019 21:31:23 +0200 Subject: [PATCH 2019/2222] MCP230xx: Prevent inadvertent pinmode change We've added support for sensor29 pin,0/1 for OFF/ON but the current code would allow the pinmode to be changed without specifying a default state e.g. sensor29 pin,3 would cause the pinmode to be changed to input even if it was previously configured for output (pinmode 5/6) This change prevents these instances by enforcing the configuration rules as outlined in the wiki e.g. sensor29 pin,pinmode,pullup/default state (if used for output) --- sonoff/xsns_29_mcp230xx.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 9eb98b95a..855de1349 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -655,9 +655,9 @@ bool MCP230xx_Command(void) { intmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); } #ifdef USE_MCP230xx_OUTPUT - if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 7) && (pullup < 2)) { + if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 7) && (pullup < 2) && (paramcount > 2)) { #else // not use OUTPUT - if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 5) && (pullup < 2)) { + if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 5) && (pullup < 2) && (paramcount > 2)) { #endif // USE_MCP230xx_OUTPUT Settings.mcp230xx_config[pin].pinmode=pinmode; Settings.mcp230xx_config[pin].pullup=pullup; From 9884cfaf161cd098596dadedb2d8cb881468b4ea Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Tue, 1 Oct 2019 08:49:40 +0200 Subject: [PATCH 2020/2222] MCP230xx Add sensor29 pin,2 for toggle --- sonoff/xsns_29_mcp230xx.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 855de1349..0e9cc1039 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -636,7 +636,7 @@ bool MCP230xx_Command(void) { MCP230xx_SetOutPin(pin,pincmd); return serviced; } - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "T")) { + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "T")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "2"))) { MCP230xx_SetOutPin(pin,2); return serviced; } From 26fc172df4af8dc6e5dca2336f3077a739da6039 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Tue, 1 Oct 2019 08:54:44 +0200 Subject: [PATCH 2021/2222] Update _changelog.ino --- sonoff/_changelog.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 8429ce360..3f88ba690 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -5,7 +5,7 @@ * Add initial support for MQTT logging using command MqttLog (#6498) * Add Zigbee more support - collect endpoints and clusters, added ZigbeeDump command * Add initial support for shutters by Stefan Bode (#288) - * Add use case for sensor29 pin,1 and sensor29 pin,0 to substitute ON and OFF respectively with MCP230xx driver + * Add command to MCP230xx: sensor29 pin,0/1/2 for OFF/ON/TOGGLE * * 6.6.0.13 20190922 * Add command EnergyReset4 x,x to initialize total usage for two tarrifs From f847763ad17fa4779956bc2be6e263207bdbf734 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 1 Oct 2019 10:49:42 +0200 Subject: [PATCH 2022/2222] Update xdrv_01_webserver.ino --- sonoff/xdrv_01_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index c4239e90f..9f8ec9eed 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1128,7 +1128,7 @@ bool HandleRootStatusRefresh(void) } #ifdef USE_SHUTTER char webindex[5]; // WebGetArg name - for (uint32_t j = 1; j < 5; j++) { + for (uint32_t j = 1; j <= shutters_present; j++) { snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j); WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent if (strlen(tmp)) { From 92c2196e7304ad76f82d9897507adcb3f897be09 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 1 Oct 2019 16:21:39 +0200 Subject: [PATCH 2023/2222] Fix possible I2C init errors Fix possible I2C init errors --- sonoff/support.ino | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 0a8b6c42c..8dbbc3316 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1460,8 +1460,8 @@ void I2cScan(char *devs, unsigned int devs_len) void I2cSetActive(uint32_t addr, uint32_t count = 1) { - addr &= 0x7F; - count &= 0x7F; + addr &= 0x7F; // Max I2C address is 127 + count &= 0x7F; // Max 4 x 32 bits available while (count-- && (addr < 128)) { i2c_active[addr / 32] |= (1 << (addr % 32)); addr++; @@ -1471,7 +1471,7 @@ void I2cSetActive(uint32_t addr, uint32_t count = 1) bool I2cActive(uint32_t addr) { - addr &= 0x7F; + addr &= 0x7F; // Max I2C address is 127 if (i2c_active[addr / 32] & (1 << (addr % 32))) { return true; } @@ -1480,16 +1480,12 @@ bool I2cActive(uint32_t addr) bool I2cDevice(uint8_t addr) { + addr &= 0x7F; // Max I2C address is 127 if (I2cActive(addr)) { return false; // If already active report as not present; } - for (uint8_t address = 1; address <= 127; address++) { - Wire.beginTransmission(address); - if (!Wire.endTransmission() && (address == addr)) { - return true; // Report as present; - } - } - return false; + Wire.beginTransmission(addr); + return (0 == Wire.endTransmission()); } #endif // USE_I2C From aa5b5e891e6be031f231079bf927ccc8759b6e7b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 1 Oct 2019 16:33:39 +0200 Subject: [PATCH 2024/2222] Add initial support for PCF8574 I2C I/O Expander Add initial support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode --- sonoff/_changelog.ino | 1 + sonoff/settings.h | 8 +- sonoff/sonoff.h | 1 + sonoff/xdrv_27_shutter.ino | 8 +- sonoff/xdrv_28_pcf8574.ino | 248 +++++++++++++++++++++++++++++++++++++ 5 files changed, 258 insertions(+), 8 deletions(-) create mode 100644 sonoff/xdrv_28_pcf8574.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 3f88ba690..7739e9a0b 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -6,6 +6,7 @@ * Add Zigbee more support - collect endpoints and clusters, added ZigbeeDump command * Add initial support for shutters by Stefan Bode (#288) * Add command to MCP230xx: sensor29 pin,0/1/2 for OFF/ON/TOGGLE + * Add initial support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode * * 6.6.0.13 20190922 * Add command EnergyReset4 x,x to initialize total usage for two tarrifs diff --git a/sonoff/settings.h b/sonoff/settings.h index c11926855..4f808586d 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -93,8 +93,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t spare27 : 1; uint32_t spare28 : 1; uint32_t spare29 : 1; - uint32_t shutter_mode : 1; // bit 30 (v6.6.0.15) - SetOption80 - Enable shutter support - uint32_t spare31 : 1; + uint32_t shutter_mode : 1; // bit 30 (v6.6.0.14) - SetOption80 - Enable shutter support + uint32_t pcf8574_ports_inverted : 1; // bit 31 (v6.6.0.14) - SetOption81 - Invert all ports on PCF8574 devices }; } SysBitfield3; @@ -376,7 +376,6 @@ struct SYSCFG { uint16_t ina226_r_shunt[4]; // E20 uint16_t ina226_i_fs[4]; // E28 uint16_t tariff[4][2]; // E30 - uint16_t shutter_opentime[MAX_SHUTTERS]; // E40 uint16_t shutter_closetime[MAX_SHUTTERS]; // E48 int16_t shuttercoeff[5][MAX_SHUTTERS]; // E50 @@ -384,8 +383,9 @@ struct SYSCFG { uint8_t shutter_set50percent[MAX_SHUTTERS]; // E7C uint8_t shutter_position[MAX_SHUTTERS]; // E80 uint8_t shutter_startrelay[MAX_SHUTTERS]; // E84 + uint8_t pcf8574_config[MAX_PCF8574]; // E88 - uint8_t free_e88[368]; // E88 + uint8_t free_e90[360]; // E90 uint32_t cfg_timestamp; // FF8 uint32_t cfg_crc32; // FFC diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 5ee19873c..46c0868e2 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -68,6 +68,7 @@ const uint8_t MAX_XDSP_DRIVERS = 32; // Max number of allowed display dri const uint8_t MAX_XDRV_DRIVERS = 96; // Max number of allowed driver drivers const uint8_t MAX_XSNS_DRIVERS = 96; // Max number of allowed sensor drivers const uint8_t MAX_SHUTTERS = 4; // Max number of shutters +const uint8_t MAX_PCF8574 = 8; // Max number of PCF8574 devices const uint8_t MAX_RULE_MEMS = 5; // Max number of saved vars const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 512 characters const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules diff --git a/sonoff/xdrv_27_shutter.ino b/sonoff/xdrv_27_shutter.ino index e7eaa4250..989a522bd 100644 --- a/sonoff/xdrv_27_shutter.ino +++ b/sonoff/xdrv_27_shutter.ino @@ -107,8 +107,6 @@ void ShutterInit(void) Shutter.mask = 0; //Initialize to get relay that changed Shutter.old_power = power; - char shutter_open_chr[10]; - char shutter_close_chr[10]; bool relay_in_interlock = false; AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Accuracy digits: %d"), Settings.shutter_accuracy); @@ -164,9 +162,11 @@ void ShutterInit(void) Shutter.real_position[i] = ShutterPercentToRealPosition(Settings.shutter_position[i], i); //Shutter.real_position[i] = Settings.shutter_position[i] <= 5 ? Settings.shuttercoeff[2][i] * Settings.shutter_position[i] : Settings.shuttercoeff[1][i] * Settings.shutter_position[i] + Settings.shuttercoeff[0,i]; Shutter.start_position[i] = Shutter.real_position[i]; - dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr); - dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr); + char shutter_open_chr[10]; + dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr); + char shutter_close_chr[10]; + dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr); AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoedffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d"), i, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr, Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], diff --git a/sonoff/xdrv_28_pcf8574.ino b/sonoff/xdrv_28_pcf8574.ino new file mode 100644 index 000000000..6b651a296 --- /dev/null +++ b/sonoff/xdrv_28_pcf8574.ino @@ -0,0 +1,248 @@ +/* + xdrv_28_pcf8574.ino - PCF8574 I2C support for Sonoff-Tasmota + + Copyright (C) 2019 Stefan Bode + + 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_PCF8574 +/*********************************************************************************************\ + * PCF8574 - I2C IO Expander + * + * I2C Address: PCF8574 = 0x20 .. 0x27, PCF8574A = 0x38 .. 0x3F +\*********************************************************************************************/ + +#define XDRV_28 28 + +#define PCF8574_ADDR1 0x20 // PCF8574 +#define PCF8574_ADDR2 0x38 // PCF8574A + +struct PCF8574 { + int error; + uint8_t pin[64]; + uint8_t address[MAX_PCF8574]; + uint8_t pin_mask[MAX_PCF8574] = { 0 }; + uint8_t max_connected_ports = 0; // Max numbers of devices comming from PCF8574 modules + uint8_t max_devices = 0; // Max numbers of PCF8574 modules + char stype[8]; + bool type = true; +} Pcf8574; + +void Pcf8574SwitchRelay(void) +{ + for (uint32_t i = 0; i < devices_present; i++) { + uint8_t relay_state = bitRead(XdrvMailbox.index, i); + + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: Pcf8574.max_devices %d requested pin %d"), Pcf8574.max_devices,Pcf8574.pin[i]); + + if (Pcf8574.max_devices > 0 && Pcf8574.pin[i] < 99) { + uint8_t board = Pcf8574.pin[i]>>3; + uint8_t oldpinmask = Pcf8574.pin_mask[board]; + uint8_t _val = bitRead(rel_inverted, i) ? !relay_state : relay_state; + + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: Pcf8574SwitchRelay %d on pin %d"), i,state); + + if (_val) { + Pcf8574.pin_mask[board] |= _val << (Pcf8574.pin[i]&0x7); + } else { + Pcf8574.pin_mask[board] &= ~(1 << (Pcf8574.pin[i]&0x7)); + } + if (oldpinmask != Pcf8574.pin_mask[board]) { + Wire.beginTransmission(Pcf8574.address[board]); + Wire.write(Pcf8574.pin_mask[board]); + Pcf8574.error = Wire.endTransmission(); + } + //pcf8574.write(Pcf8574.pin[i]&0x7, rel_inverted[i] ? !state : state); + } + } +} + +void Pcf8574Init() +{ + Pcf8574.type = false; + + uint8_t pcf8574_address = PCF8574_ADDR1; + for (uint32_t i = 0; i < MAX_PCF8574; i++) { + + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: Probing addr: 0x%x for PCF8574"), pcf8574_address); + + if (I2cDevice(pcf8574_address)) { + I2cSetActive(pcf8574_address); + Pcf8574.type = true; + + Pcf8574.address[Pcf8574.max_devices] = pcf8574_address; + Pcf8574.max_devices++; + + strcpy(Pcf8574.stype, "PCF8574"); + if (pcf8574_address >= PCF8574_ADDR2) { + strcpy(Pcf8574.stype, "PCF8574A"); + } + AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, Pcf8574.stype, pcf8574_address); + } + pcf8574_address++; + if ((PCF8574_ADDR1 + 8) == pcf8574_address) { + pcf8574_address = PCF8574_ADDR2; + } + } + if (Pcf8574.max_devices) { + for (uint32_t i = 0; i < sizeof(Pcf8574.pin); i++) { + Pcf8574.pin[i] = 99; + } + devices_present = devices_present - Pcf8574.max_connected_ports; // reset no of devices to avoid duplicate ports on duplicate init. + Pcf8574.max_connected_ports = 0; // reset no of devices to avoid duplicate ports on duplicate init. + for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { // suport up to 8 boards PCF8574 + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: Device %d config 0x%02x"), idx +1, Settings.pcf8574_config[idx]); + + for (uint32_t i = 0; i < 8; i++) { + uint8_t _result = Settings.pcf8574_config[idx] >> i &1; + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: I2C shift i %d: %d. Powerstate: %d, devices_present: %d"), i,_result, Settings.power>>i&1, devices_present); + if (_result > 0) { + Pcf8574.pin[devices_present] = i + 8 * idx; + bitWrite(rel_inverted, devices_present, Settings.flag3.pcf8574_ports_inverted); + devices_present++; + Pcf8574.max_connected_ports++; + } + } + } + AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Total devices %d, PCF8574 output ports %d"), devices_present, Pcf8574.max_connected_ports); + } +} + +/*********************************************************************************************\ + * Presentation +\*********************************************************************************************/ + +#ifdef USE_WEBSERVER + +#define WEB_HANDLE_PCF8574 "pcf" + +const char HTTP_BTN_MENU_PCF8574[] PROGMEM = + "

"; + +const char HTTP_FORM_I2C_PCF8574_1[] PROGMEM = + "
 " D_PCF8574_PARAMETERS " " + "
" + "

" D_INVERT_PORTS "


"; + +const char HTTP_FORM_I2C_PCF8574_2[] PROGMEM = + "
"; + +void HandlePcf8574(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_PCF8574)); + + if (WebServer->hasArg("save")) { + Pcf8574SaveSettings(); + WebRestart(1); + return; + } + + WSContentStart_P(D_CONFIGURE_PCF8574); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_I2C_PCF8574_1, (Settings.flag3.pcf8574_ports_inverted) ? " checked" : ""); + WSContentSend_P(HTTP_TABLE100); + for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { + for (uint32_t idx2 = 0; idx2 < 8; idx2++) { // 8 ports on PCF8574 + uint8_t helper = 1 << idx2; + WSContentSend_P(HTTP_FORM_I2C_PCF8574_2, + idx +1, idx2, + idx2 + 8*idx, + idx2 + 8*idx, + ((helper & Settings.pcf8574_config[idx]) >> idx2 == 0) ? " selected " : " ", + ((helper & Settings.pcf8574_config[idx]) >> idx2 == 1) ? " selected " : " " + ); + } + } + WSContentSend_P(PSTR("
\").replace(/{m}/g,\"\").replace(/{e}/g,\"
" D_DEVICE " %d " D_PORT " %d
")); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void Pcf8574SaveSettings() +{ + char stemp[7]; + char tmp[100]; + + //AddLog_P(LOG_LEVEL_DEBUG, PSTR("PCF: Start working on Save arguements: inverted:%d")), WebServer->hasArg("b1"); + + Settings.flag3.pcf8574_ports_inverted = WebServer->hasArg("b1"); + for (byte idx = 0; idx < Pcf8574.max_devices; idx++) { + byte count=0; + byte n = Settings.pcf8574_config[idx]; + while(n!=0) { + n = n&(n-1); + count++; + } + if (count <= devices_present) { + devices_present = devices_present - count; + } + for (byte i = 0; i < 8; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("i2cs%d"), i+8*idx); + WebGetArg(stemp, tmp, sizeof(tmp)); + byte _value = (!strlen(tmp)) ? 0 : atoi(tmp); + if (_value) { + Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] | 1 << i; + devices_present++; + Pcf8574.max_connected_ports++; + } else { + Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] & ~(1 << i ); + } + } + //Settings.pcf8574_config[0] = (!strlen(webServer->arg("i2cs0").c_str())) ? 0 : atoi(webServer->arg("i2cs0").c_str()); + //AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: I2C Board: %d, Config: %2x")), idx, Settings.pcf8574_config[idx]; + + } +} +#endif // USE_WEBSERVER + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv28(uint8_t function) +{ + bool result = false; + + if (i2c_flg && Pcf8574.type) { + switch (function) { + case FUNC_SET_POWER: + Pcf8574SwitchRelay(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_PCF8574); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_PCF8574, HandlePcf8574); + break; +#endif // USE_WEBSERVER + case FUNC_PRE_INIT: + Pcf8574Init(); + break; + } + } + return result; +} + +#endif // USE_PCF8574 +#endif // USE_I2C From be4867e7f6d51e866cc9771e8191821f4c0a1634 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 1 Oct 2019 16:45:53 +0200 Subject: [PATCH 2025/2222] Fix compilation error Fix compilation error --- sonoff/language/bg-BG.h | 8 ++++++++ sonoff/language/cs-CZ.h | 8 ++++++++ sonoff/language/de-DE.h | 8 ++++++++ sonoff/language/el-GR.h | 8 ++++++++ sonoff/language/en-GB.h | 8 ++++++++ sonoff/language/es-ES.h | 8 ++++++++ sonoff/language/fr-FR.h | 8 ++++++++ sonoff/language/he-HE.h | 8 ++++++++ sonoff/language/hu-HU.h | 8 ++++++++ sonoff/language/it-IT.h | 8 ++++++++ sonoff/language/ko-KO.h | 8 ++++++++ sonoff/language/nl-NL.h | 8 ++++++++ sonoff/language/pl-PL.h | 8 ++++++++ sonoff/language/pt-BR.h | 8 ++++++++ sonoff/language/pt-PT.h | 8 ++++++++ sonoff/language/ru-RU.h | 8 ++++++++ sonoff/language/sk-SK.h | 8 ++++++++ sonoff/language/sv-SE.h | 8 ++++++++ sonoff/language/tr-TR.h | 8 ++++++++ sonoff/language/uk-UK.h | 8 ++++++++ sonoff/language/zh-CN.h | 8 ++++++++ sonoff/language/zh-TW.h | 8 ++++++++ sonoff/my_user_config.h | 1 + sonoff/support_features.ino | 13 +++++++++---- tools/decode-status.py | 8 +++++--- 25 files changed, 191 insertions(+), 7 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 1cc34be2c..b7080f2ca 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Датчикът DS18x20 е зает" #define D_SENSOR_CRC_ERROR "Датчик DS18x20 - грешка CRC" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index c8a5713c8..d413910b3 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor DS18x20 obsazen" #define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 295402d6b..f53267421 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor beschäftigt" #define D_SENSOR_CRC_ERROR "Sensor CRC-Fehler" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 222c06ef6..3b6f5edcc 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Ο αισθητήρας είναι απασχολημένος" #define D_SENSOR_CRC_ERROR "Σφάλμα CRC αισθητήρα" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 546d99af1..af4ba7b64 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor busy" #define D_SENSOR_CRC_ERROR "Sensor CRC error" diff --git a/sonoff/language/es-ES.h b/sonoff/language/es-ES.h index b62e54661..94e2a092c 100644 --- a/sonoff/language/es-ES.h +++ b/sonoff/language/es-ES.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor ocupado" #define D_SENSOR_CRC_ERROR "Error CRC del Sensor" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 6091da84f..3216932ee 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Capteur occupé" #define D_SENSOR_CRC_ERROR "Erreur CRC capteur" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index ee16e5073..5fdcc93e3 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "שרת עסוק" #define D_SENSOR_CRC_ERROR "בחיישן CRC שגיאת" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 90a52b03a..0bcb1da05 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Szenzor foglalt" #define D_SENSOR_CRC_ERROR "Szenzor CRC hiba" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 2a990dc8e..f1183d090 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensore occupato" #define D_SENSOR_CRC_ERROR "Sensore errore CRC" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index 7ffc5271d..5b99924bb 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "센서가 사용 중" #define D_SENSOR_CRC_ERROR "센서 CRC 에러" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 822bf1542..b8b0c1e88 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor bezet" #define D_SENSOR_CRC_ERROR "Sensor CRC fout" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 8729be3c7..d3a7712b9 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Czujnik DS18x20 zajęty" #define D_SENSOR_CRC_ERROR "Czujnik DS18x20 błąd CRC" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index f1ec6326f..209738d81 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor ocupado" #define D_SENSOR_CRC_ERROR "Erro sensor CRC" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 0fac99308..f9debe83b 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor ocupado" #define D_SENSOR_CRC_ERROR "Erro Sensor CRC" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 2b0b68cb7..7306b1820 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Датчик DS18x20 занят" #define D_SENSOR_CRC_ERROR "Датчик DS18x20 - ошибка CRC" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 84385ee28..d462ecfac 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor DS18x20 obsadený" #define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index d55b6ddbc..a903db1f9 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor upptagen" #define D_SENSOR_CRC_ERROR "Sensor CRC-fel" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index f31efe078..7e23b9d4d 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensör başgül" #define D_SENSOR_CRC_ERROR "Sensor CRC hatası" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index dd21904d8..dd694ff85 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Датчик DS18x20 зайнятий" #define D_SENSOR_CRC_ERROR "Датчик DS18x20 - помилка CRC" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 0d776f40c..8b1464b33 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "传感器正忙" #define D_SENSOR_CRC_ERROR "传感器 CRC 校验错误" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 38d0b26be..8fa61ed9e 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -447,6 +447,14 @@ #define D_CLOSE "Close" #define D_DOMOTICZ_SHUTTER "Shutter" +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "傳感器正忙" #define D_SENSOR_CRC_ERROR "傳感器 CRC 校驗錯誤" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index a2a2eda67..cd82cea53 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -372,6 +372,7 @@ // #define USE_MLX90614 // Enable MLX90614 ir temp sensor (I2C address 0x5a) (+0.6k code) // #define USE_CHIRP // Enable CHIRP soil moisture sensor (variable I2C address, default 0x20) // #define USE_PAJ7620 // Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code) +// #define USE_PCF8574 // Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x27 and 0x38 - 0x3F) (+1k9 code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 9b5e05747..999850db3 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -450,10 +450,15 @@ void GetFeatures(void) #ifdef USE_DDS2382 feature5 |= 0x00000040; // Xnrg_09_dds2382.ino #endif -// feature5 |= 0x00000080; - -// feature5 |= 0x00000100; -// feature5 |= 0x00000200; +#ifdef USE_SM2135 + feature5 |= 0x00000080; // Xdrv_026_sm2135.ino +#endif +#ifdef USE_SHUTTER + feature5 |= 0x00000100; // Xdrv_027_shutter.ino +#endif +#ifdef USE_PCF8574 + feature5 |= 0x00000200; // Xdrv_028_pcf8574.ino +#endif // feature5 |= 0x00000400; // feature5 |= 0x00000800; diff --git a/tools/decode-status.py b/tools/decode-status.py index f1c3bacf2..8682373ec 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -126,7 +126,9 @@ a_setoption = [[ "Enable Weekend Energy Tariff", "","","", "","","","", - "","","","" + "","", + "Enable shutter support", + "Invert PCF8574 ports" ]] a_features = [[ @@ -167,8 +169,8 @@ a_features = [[ "USE_MAX31865","USE_CHIRP","USE_SOLAX_X1","USE_PAJ7620" ],[ "USE_BUZZER","USE_RDM6300","USE_IBEACON","USE_SML_M", - "USE_INA226","USE_A4988_Stepper","USE_DDS2382","", - "","","","", + "USE_INA226","USE_A4988_Stepper","USE_DDS2382","USE_SM2135", + "USE_SHUTTER","USE_PCF8574","","", "","","","", "","","","", "","","","", From ea7718c81028003e4e232836a458e451da9bfced Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 1 Oct 2019 17:19:37 +0200 Subject: [PATCH 2026/2222] Fix ShutterClose Index display Fix ShutterClose Index display (#6535) --- sonoff/xdrv_27_shutter.ino | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/sonoff/xdrv_27_shutter.ino b/sonoff/xdrv_27_shutter.ino index 989a522bd..d02057bcd 100644 --- a/sonoff/xdrv_27_shutter.ino +++ b/sonoff/xdrv_27_shutter.ino @@ -441,7 +441,7 @@ void CmndShutterPosition(void) // Code for shutters with circuit safe configuration, switch the direction Relay ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); // power on - ExecuteCommandPower(Settings.shutter_startrelay[index] , 1, SRC_SHUTTER); + ExecuteCommandPower(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); } else { // now start the motor for the right direction, work for momentary and normal shutters. AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter in direction %d"), Shutter.direction[index]); @@ -453,7 +453,8 @@ void CmndShutterPosition(void) } else { target_pos_percent = ShutterRealToPercentPosition(Shutter.real_position[index], index); } - ResponseCmndIdxNumber(Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent); + XdrvMailbox.index = index +1; + ResponseCmndIdxNumber(Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent); } } @@ -461,11 +462,11 @@ void CmndShutterOpenTime(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { if (XdrvMailbox.data_len > 0) { - Settings.shutter_opentime[XdrvMailbox.index-1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); + Settings.shutter_opentime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); ShutterInit(); } char time_chr[10]; - dtostrfd((float)(Settings.shutter_opentime[XdrvMailbox.index-1]) / 10, 1, time_chr); + dtostrfd((float)(Settings.shutter_opentime[XdrvMailbox.index -1]) / 10, 1, time_chr); ResponseCmndIdxChar(time_chr); } } @@ -474,11 +475,11 @@ void CmndShutterCloseTime(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { if (XdrvMailbox.data_len > 0) { - Settings.shutter_closetime[XdrvMailbox.index-1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); + Settings.shutter_closetime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); ShutterInit(); } char time_chr[10]; - dtostrfd((float)(Settings.shutter_closetime[XdrvMailbox.index-1]) / 10, 1, time_chr); + dtostrfd((float)(Settings.shutter_closetime[XdrvMailbox.index -1]) / 10, 1, time_chr); ResponseCmndIdxChar(time_chr); } } @@ -487,14 +488,14 @@ void CmndShutterRelay(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64)) { - Settings.shutter_startrelay[XdrvMailbox.index-1] = XdrvMailbox.payload; + Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; if (XdrvMailbox.payload > 0) { Shutter.mask |= 3 << (XdrvMailbox.payload - 1); } else { - Shutter.mask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index-1] - 1); + Shutter.mask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index -1] - 1); } AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Relay %d is %d"), XdrvMailbox.index, XdrvMailbox.payload); - Settings.shutter_startrelay[XdrvMailbox.index-1] = XdrvMailbox.payload; + Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; ShutterInit(); // if payload is 0 to disable the relay there must be a reboot. Otherwhise does not work } @@ -506,11 +507,11 @@ void CmndShutterSetHalfway(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Settings.shutter_set50percent[XdrvMailbox.index-1] = Settings.shutter_invert[XdrvMailbox.index-1] ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; + Settings.shutter_set50percent[XdrvMailbox.index -1] = Settings.shutter_invert[XdrvMailbox.index -1] ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; ShutterInit(); ResponseCmndIdxNumber(XdrvMailbox.payload); // ???? } else { - ResponseCmndIdxNumber(Settings.shutter_set50percent[XdrvMailbox.index-1]); + ResponseCmndIdxNumber(Settings.shutter_set50percent[XdrvMailbox.index -1]); } } } @@ -518,9 +519,9 @@ void CmndShutterSetHalfway(void) void CmndShutterSetClose(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - Shutter.real_position[XdrvMailbox.index-1] = 0; - ShutterStartInit(XdrvMailbox.index-1, 0, 0); - Settings.shutter_position[XdrvMailbox.index-1] = 0; + Shutter.real_position[XdrvMailbox.index -1] = 0; + ShutterStartInit(XdrvMailbox.index -1, 0, 0); + Settings.shutter_position[XdrvMailbox.index -1] = 0; ResponseCmndChar(D_CONFIGURATION_RESET); } } @@ -529,9 +530,9 @@ void CmndShutterInvert(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.shutter_invert[XdrvMailbox.index-1] = XdrvMailbox.payload; + Settings.shutter_invert[XdrvMailbox.index -1] = XdrvMailbox.payload; } - ResponseCmndIdxNumber(Settings.shutter_invert[XdrvMailbox.index-1]); + ResponseCmndIdxNumber(Settings.shutter_invert[XdrvMailbox.index -1]); } } From d9aeb95503246a9dd5f927642a21c95ff0def13c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 1 Oct 2019 17:20:43 +0200 Subject: [PATCH 2027/2222] Update xdrv_27_shutter.ino --- sonoff/xdrv_27_shutter.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_27_shutter.ino b/sonoff/xdrv_27_shutter.ino index d02057bcd..3a5aacd22 100644 --- a/sonoff/xdrv_27_shutter.ino +++ b/sonoff/xdrv_27_shutter.ino @@ -435,7 +435,7 @@ void CmndShutterPosition(void) ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); Shutter.operations[index]++; if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { - ExecuteCommandPower(Settings.shutter_startrelay[index] , 0, SRC_SHUTTER); + ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload); ShutterDelayForMotorStop(); // Code for shutters with circuit safe configuration, switch the direction Relay @@ -453,7 +453,7 @@ void CmndShutterPosition(void) } else { target_pos_percent = ShutterRealToPercentPosition(Shutter.real_position[index], index); } - XdrvMailbox.index = index +1; + XdrvMailbox.index = index +1; // Fix random index for ShutterClose ResponseCmndIdxNumber(Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent); } } From c7308e2dfff0bdbbbd36869d59968038cf3970f6 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 1 Oct 2019 17:05:58 -0300 Subject: [PATCH 2028/2222] Updated Spanish Translation --- sonoff/language/es-ES.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sonoff/language/es-ES.h b/sonoff/language/es-ES.h index 94e2a092c..239542068 100644 --- a/sonoff/language/es-ES.h +++ b/sonoff/language/es-ES.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.6.0.4 + * Updated until v6.6.0.14 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -443,17 +443,17 @@ #define D_ENERGY_TOTAL "Energía Total" // xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" +#define D_OPEN "Abrir" +#define D_CLOSE "Cerrar" +#define D_DOMOTICZ_SHUTTER "Cortina" // xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" +#define D_CONFIGURE_PCF8574 "Configurar PCF8574" +#define D_PCF8574_PARAMETERS "Parámetros de PCF8574" +#define D_INVERT_PORTS "Invertir Puertos" +#define D_DEVICE "Dispositivo" +#define D_DEVICE_INPUT "Entrada" +#define D_DEVICE_OUTPUT "Salida" // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor ocupado" From 838e571d10d1b258d54bf80d29ec2419204c79fd Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Tue, 1 Oct 2019 22:58:08 +0200 Subject: [PATCH 2029/2222] Fix TasmotaSerial: move serial send to IRAM for high speed baud rates --- .../README.md | 0 .../examples/swsertest/swsertest.ino | 0 .../keywords.txt | 0 .../library.json | 2 +- .../library.properties | 2 +- .../src/TasmotaSerial.cpp | 62 ++++++++++++++----- .../src/TasmotaSerial.h | 2 + sonoff/_changelog.ino | 1 + 8 files changed, 50 insertions(+), 19 deletions(-) rename lib/{TasmotaSerial-2.4.0 => TasmotaSerial-2.4.1}/README.md (100%) rename lib/{TasmotaSerial-2.4.0 => TasmotaSerial-2.4.1}/examples/swsertest/swsertest.ino (100%) rename lib/{TasmotaSerial-2.4.0 => TasmotaSerial-2.4.1}/keywords.txt (100%) rename lib/{TasmotaSerial-2.4.0 => TasmotaSerial-2.4.1}/library.json (94%) rename lib/{TasmotaSerial-2.4.0 => TasmotaSerial-2.4.1}/library.properties (94%) rename lib/{TasmotaSerial-2.4.0 => TasmotaSerial-2.4.1}/src/TasmotaSerial.cpp (88%) rename lib/{TasmotaSerial-2.4.0 => TasmotaSerial-2.4.1}/src/TasmotaSerial.h (97%) diff --git a/lib/TasmotaSerial-2.4.0/README.md b/lib/TasmotaSerial-2.4.1/README.md similarity index 100% rename from lib/TasmotaSerial-2.4.0/README.md rename to lib/TasmotaSerial-2.4.1/README.md diff --git a/lib/TasmotaSerial-2.4.0/examples/swsertest/swsertest.ino b/lib/TasmotaSerial-2.4.1/examples/swsertest/swsertest.ino similarity index 100% rename from lib/TasmotaSerial-2.4.0/examples/swsertest/swsertest.ino rename to lib/TasmotaSerial-2.4.1/examples/swsertest/swsertest.ino diff --git a/lib/TasmotaSerial-2.4.0/keywords.txt b/lib/TasmotaSerial-2.4.1/keywords.txt similarity index 100% rename from lib/TasmotaSerial-2.4.0/keywords.txt rename to lib/TasmotaSerial-2.4.1/keywords.txt diff --git a/lib/TasmotaSerial-2.4.0/library.json b/lib/TasmotaSerial-2.4.1/library.json similarity index 94% rename from lib/TasmotaSerial-2.4.0/library.json rename to lib/TasmotaSerial-2.4.1/library.json index cdce0deba..554d9ea9e 100644 --- a/lib/TasmotaSerial-2.4.0/library.json +++ b/lib/TasmotaSerial-2.4.1/library.json @@ -1,6 +1,6 @@ { "name": "TasmotaSerial", - "version": "2.4.0", + "version": "2.4.1", "keywords": [ "serial", "io", "TasmotaSerial" ], diff --git a/lib/TasmotaSerial-2.4.0/library.properties b/lib/TasmotaSerial-2.4.1/library.properties similarity index 94% rename from lib/TasmotaSerial-2.4.0/library.properties rename to lib/TasmotaSerial-2.4.1/library.properties index f1486dfab..b326d7404 100644 --- a/lib/TasmotaSerial-2.4.0/library.properties +++ b/lib/TasmotaSerial-2.4.1/library.properties @@ -1,5 +1,5 @@ name=TasmotaSerial -version=2.4.0 +version=2.4.1 author=Theo Arends maintainer=Theo Arends sentence=Implementation of software serial with hardware serial fallback for ESP8266. diff --git a/lib/TasmotaSerial-2.4.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp similarity index 88% rename from lib/TasmotaSerial-2.4.0/src/TasmotaSerial.cpp rename to lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp index 5ffcaf390..0a1386375 100644 --- a/lib/TasmotaSerial-2.4.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp @@ -213,6 +213,7 @@ int TasmotaSerial::available() #ifdef TM_SERIAL_USE_IRAM #define TM_SERIAL_WAIT_SND { while (ESP.getCycleCount() < (wait + start)) if (!m_high_speed) optimistic_yield(1); wait += m_bit_time; } // Watchdog timeouts +#define TM_SERIAL_WAIT_SND_FAST { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; } #define TM_SERIAL_WAIT_RCV { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; } #define TM_SERIAL_WAIT_RCV_LOOP { while (ESP.getCycleCount() < (wait + start)); } #else @@ -221,31 +222,58 @@ int TasmotaSerial::available() #define TM_SERIAL_WAIT_RCV_LOOP { while (ESP.getCycleCount() < (wait + start)); } #endif +#ifdef TM_SERIAL_USE_IRAM +void ICACHE_RAM_ATTR TasmotaSerial::_fast_write(uint8_t b) { +#else +void TasmotaSerial::_fast_write(uint8_t b) { +#endif + uint32_t wait = m_bit_time; + uint32_t start = ESP.getCycleCount(); + // Start bit; + digitalWrite(m_tx_pin, LOW); + TM_SERIAL_WAIT_SND_FAST; + for (uint32_t i = 0; i < 8; i++) { + digitalWrite(m_tx_pin, (b & 1) ? HIGH : LOW); + TM_SERIAL_WAIT_SND_FAST; + b >>= 1; + } + // Stop bit(s) + digitalWrite(m_tx_pin, HIGH); + for (uint32_t i = 0; i < m_stop_bits; i++) { + TM_SERIAL_WAIT_SND_FAST; + } +} + size_t TasmotaSerial::write(uint8_t b) { if (m_hardserial) { return Serial.write(b); } else { if (-1 == m_tx_pin) return 0; - if (m_high_speed) cli(); // Disable interrupts in order to get a clean transmit - uint32_t wait = m_bit_time; - //digitalWrite(m_tx_pin, HIGH); // already in HIGH mode - uint32_t start = ESP.getCycleCount(); - // Start bit; - digitalWrite(m_tx_pin, LOW); - TM_SERIAL_WAIT_SND; - for (uint32_t i = 0; i < 8; i++) { - digitalWrite(m_tx_pin, (b & 1) ? HIGH : LOW); - TM_SERIAL_WAIT_SND; - b >>= 1; - } - // Stop bit(s) - digitalWrite(m_tx_pin, HIGH); - // re-enable interrupts during stop bits, it's not an issue if they are longer than expected - if (m_high_speed) sei(); - for (uint32_t i = 0; i < m_stop_bits; i++) { + if (m_high_speed) { + cli(); // Disable interrupts in order to get a clean transmit + _fast_write(b); + sei(); + } else { + uint32_t wait = m_bit_time; + //digitalWrite(m_tx_pin, HIGH); // already in HIGH mode + uint32_t start = ESP.getCycleCount(); + // Start bit; + digitalWrite(m_tx_pin, LOW); TM_SERIAL_WAIT_SND; + for (uint32_t i = 0; i < 8; i++) { + digitalWrite(m_tx_pin, (b & 1) ? HIGH : LOW); + TM_SERIAL_WAIT_SND; + b >>= 1; + } + // Stop bit(s) + digitalWrite(m_tx_pin, HIGH); + // re-enable interrupts during stop bits, it's not an issue if they are longer than expected + for (uint32_t i = 0; i < m_stop_bits; i++) { + TM_SERIAL_WAIT_SND; + } } + return 1; } } diff --git a/lib/TasmotaSerial-2.4.0/src/TasmotaSerial.h b/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.h similarity index 97% rename from lib/TasmotaSerial-2.4.0/src/TasmotaSerial.h rename to lib/TasmotaSerial-2.4.1/src/TasmotaSerial.h index 41f3cd0d7..81545f522 100644 --- a/lib/TasmotaSerial-2.4.0/src/TasmotaSerial.h +++ b/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.h @@ -81,6 +81,8 @@ class TasmotaSerial : public Stream { bool m_high_speed = false; bool m_very_high_speed = false; // above 100000 bauds uint8_t *m_buffer; + + void _fast_write(uint8_t b); // IRAM minimized version }; #endif // TasmotaSerial_h diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 7739e9a0b..be07e8788 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -7,6 +7,7 @@ * Add initial support for shutters by Stefan Bode (#288) * Add command to MCP230xx: sensor29 pin,0/1/2 for OFF/ON/TOGGLE * Add initial support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode + * Fix TasmotaSerial: move serial send to IRAM for high speed baud rates * * 6.6.0.13 20190922 * Add command EnergyReset4 x,x to initialize total usage for two tarrifs From 6379677218078e123bf549324ef69ddecbb84c6f Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Wed, 2 Oct 2019 10:39:14 +0200 Subject: [PATCH 2030/2222] Shutter and PC8574 --- sonoff/language/de-DE.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index f53267421..71c4a1de1 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.6.0.4 + * Updated until v6.6.0.14 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -443,17 +443,17 @@ #define D_ENERGY_TOTAL "Energie insgesamt" // xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" +#define D_OPEN "Öffnen" +#define D_CLOSE "Schliessen" +#define D_DOMOTICZ_SHUTTER "Rollo" // xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" +#define D_CONFIGURE_PCF8574 "Konfiguriere PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 Parameter" +#define D_INVERT_PORTS "Invertiere Ports" +#define D_DEVICE "Gerät" +#define D_DEVICE_INPUT "Eingang" +#define D_DEVICE_OUTPUT "Ausgang" // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensor beschäftigt" From 37fc7d22592058b5793de83fa7e096306b4de735 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 2 Oct 2019 11:24:51 +0200 Subject: [PATCH 2031/2222] Add command SetOption71 for DDS238-2 Add command SetOption71 0/1 to switch between different Modbus Active Energy registers on DDS238-2 energy meters (#6531) --- sonoff/_changelog.ino | 1 + sonoff/settings.h | 2 +- sonoff/xnrg_09_dds2382.ino | 15 ++++++++++----- tools/decode-status.py | 3 ++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 7739e9a0b..9139cb622 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -7,6 +7,7 @@ * Add initial support for shutters by Stefan Bode (#288) * Add command to MCP230xx: sensor29 pin,0/1/2 for OFF/ON/TOGGLE * Add initial support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode + * Add command SetOption71 0/1 to switch between different Modbus Active Energy registers on DDS238-2 energy meters (#6531) * * 6.6.0.13 20190922 * Add command EnergyReset4 x,x to initialize total usage for two tarrifs diff --git a/sonoff/settings.h b/sonoff/settings.h index 4f808586d..c2be9d6e3 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -84,7 +84,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t pwm_multi_channels : 1; // bit 18 (v6.6.0.3) - SetOption68 - Enable multi-channels PWM instead of Color PWM uint32_t tuya_dimmer_min_limit : 1; // bit 19 (v6.6.0.5) - SetOption69 - Limits Tuya dimmers to minimum of 10% (25) when enabled. uint32_t energy_weekend : 1; // bit 20 (v6.6.0.8) - CMND_TARIFF - uint32_t spare21 : 1; + uint32_t dds2382_model : 1; // bit 21 (v6.6.0.14) - SetOption71 - Select different Modbus registers for Active Energy (#6531) uint32_t spare22 : 1; uint32_t spare23 : 1; uint32_t spare24 : 1; diff --git a/sonoff/xnrg_09_dds2382.ino b/sonoff/xnrg_09_dds2382.ino index b36a12d8f..590a60186 100644 --- a/sonoff/xnrg_09_dds2382.ino +++ b/sonoff/xnrg_09_dds2382.ino @@ -54,8 +54,10 @@ void Dds2382EverySecond(void) } else { Energy.data_valid[0] = 0; - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 - // SA FC BC EnergyTotal ExportActiv ImportActiv Volta Curre APowe RPowe PFact Frequ Crc-- + // 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 = ModBus register + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 = Buffer index + // SA FC BC EnergyTotal ExportActiv ImportActiv Volta Curre APowe RPowe PFact Frequ Crc-- = DDS238-2 ZN/S version 1 (#6384) + // SA FC BC EnergyTotal ExportActiv ImportActiv Volta Curre APowe RPowe PFact Frequ Crc-- = DDS238-2 ZN/S version 2 (#6531) Energy.voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0; Energy.current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0; @@ -63,9 +65,12 @@ void Dds2382EverySecond(void) Energy.reactive_power[0] = (float)((buffer[33] << 8) + buffer[34]); Energy.power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0; // 1.00 Energy.frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0; // 50.0 Hz - Energy.export_active = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[13] << 8) + buffer[14]) / 100.0; // 429496729.0 W -// float energy_total = (float)((buffer[3] << 24) + (buffer[4] << 16) + (buffer[5] << 8) + buffer[6]) / 100.0; // 429496729.0 W - float import_active = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[17] << 8) + buffer[18]) / 100.0; // 429496729.0 W + uint8_t offset = 11; + if (Settings.flag3.dds2382_model) { + offset = 19; + } + Energy.export_active = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; // 429496729.0 W + float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; // 429496729.0 W EnergyUpdateTotal(import_active, false); // 484.708 kWh } diff --git a/tools/decode-status.py b/tools/decode-status.py index 8682373ec..a08689306 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -124,7 +124,8 @@ a_setoption = [[ "Enable multi-channels PWM instead of Color PWM", "Limits Tuya MCU dimmers to minimum of 10% (25) when enabled", "Enable Weekend Energy Tariff", - "","","", + "Select different Modbus registers for Active Energy", + "","", "","","","", "","", "Enable shutter support", From f946ebaf7b558f996a1adb0db003afc0fa6817b3 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Wed, 2 Oct 2019 11:11:50 +0100 Subject: [PATCH 2032/2222] Dimmer: Change SetOption43 (Dimmer Max) generic instead of Tuya only --- sonoff/settings.ino | 10 +++++----- sonoff/sonoff.h | 2 +- sonoff/support_command.ino | 2 +- sonoff/xdrv_16_tuyamcu.ino | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 289c8392b..f16273f7c 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -125,8 +125,8 @@ #ifndef ENERGY_OVERTEMP #define ENERGY_OVERTEMP 90 // Overtemp in Celsius #endif -#ifndef TUYA_DIMMER_MAX -#define TUYA_DIMMER_MAX 100 +#ifndef DEFAULT_DIMMER_MAX +#define DEFAULT_DIMMER_MAX 100 #endif enum WebColors { @@ -774,7 +774,7 @@ void SettingsDefaultSet2(void) // Settings.light_rotation = 0; SettingsDefaultSet_5_8_1(); // Clock color - Settings.param[P_TUYA_DIMMER_MAX] = TUYA_DIMMER_MAX; + Settings.param[P_DIMMER_MAX] = DEFAULT_DIMMER_MAX; // Display SettingsDefaultSet_5_10_1(); // Display settings @@ -1084,9 +1084,9 @@ void SettingsDelta(void) if (Settings.version < 0x06060008) { // Move current tuya dimmer range to the new param. if (Settings.flag3.tuya_dimmer_range_255) { - Settings.param[P_TUYA_DIMMER_MAX] = 100; + Settings.param[P_DIMMER_MAX] = 100; } else { - Settings.param[P_TUYA_DIMMER_MAX] = 255; + Settings.param[P_DIMMER_MAX] = 255; } } if (Settings.version < 0x06060009) { diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 46c0868e2..c1c19f3fe 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -249,7 +249,7 @@ enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; enum SettingsParamIndex { P_HOLD_TIME, P_MAX_POWER_RETRY, P_ex_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_IR_UNKNOW_THRESHOLD, // SetOption32 .. SetOption38 P_CSE7766_INVALID_POWER, P_HOLD_IGNORE, P_ex_TUYA_RELAYS, P_OVER_TEMP, // SetOption39 .. SetOption42 - P_TUYA_DIMMER_MAX, + P_DIMMER_MAX, P_ex_TUYA_VOLTAGE_ID, P_ex_TUYA_CURRENT_ID, P_ex_TUYA_POWER_ID, // SetOption43 .. SetOption46 P_ex_ENERGY_TARIFF1, P_ex_ENERGY_TARIFF2, // SetOption47 .. SetOption48 P_MAX_PARAM8 }; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 0e2f6d4e6..9e2fd5fcb 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -687,7 +687,7 @@ void CmndSetoption(void) break; #endif #ifdef USE_TUYA_MCU - case P_TUYA_DIMMER_MAX: + case P_DIMMER_MAX: restart_flag = 2; // Need a restart to update GUI break; #endif diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index d849d4712..db190f58f 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -297,14 +297,14 @@ void LightSerialDuty(uint8_t duty) if (Settings.flag3.tuya_dimmer_min_limit) { // Enable dimming limit SetOption69: Enabled by default if (duty < 25) { duty = 25; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself } - duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]); + duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_DIMMER_MAX]); if (Tuya.new_dim != duty) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); TuyaSendValue(dpid, duty); } } else if (dpid > 0) { Tuya.ignore_dim = false; // reset flag - duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]); + duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_DIMMER_MAX]); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); // due to 0 or already set } else { AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); // @@ -375,7 +375,7 @@ void TuyaPacketProcess(void) bool tuya_energy_enabled = (XNRG_16 == energy_flg); if (fnId == TUYA_MCU_FUNC_DIMMER) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]); - Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_TUYA_DIMMER_MAX], 0, 100); + Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_DIMMER_MAX], 0, 100); if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { Tuya.ignore_dim = true; From 39b201898d7bfc2a4838b04899db19594f573db7 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Wed, 2 Oct 2019 11:12:51 +0100 Subject: [PATCH 2033/2222] PS_16_DZ: Implement SetOption43 (Dimmer Max) for PS_16_DZ dimmers. Fixes #6544 --- sonoff/xdrv_19_ps16dz_dimmer.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index b0dc80190..0c637a2ae 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -83,6 +83,7 @@ void PS16DZSerialSendUpdateCommand(void) uint8_t light_state_dimmer = light_state.getDimmer(); // Dimming acts odd below 10% - this mirrors the threshold set on the faceplate itself light_state_dimmer = (light_state_dimmer < 10) ? 10 : light_state_dimmer; + light_state_dimmer = (light_state_dimmer > Settings.param[P_DIMMER_MAX]) ? Settings.param[P_DIMMER_MAX] : light_state_dimmer; snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer); From bac30bbe1bdbaada05fa963c71897e09b1402390 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 2 Oct 2019 12:51:37 +0200 Subject: [PATCH 2034/2222] Try to catch domoticz test Try to catch domoticz test (#6529) --- sonoff/xdrv_02_mqtt.ino | 6 +- sonoff/xdrv_07_domoticz.ino | 170 ++++++++++++++++++------------------ sonoff/xdrv_10_rules.ino | 2 +- sonoff/xdrv_interface.ino | 10 --- 4 files changed, 92 insertions(+), 96 deletions(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index d1bf375a6..81fd45b6f 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -279,7 +279,11 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) // if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) { Serial.println(dataBuf); } // MQTT pre-processing - if (XdrvMqttData(topic, strlen(topic), (char*)data, data_len)) { return; } + XdrvMailbox.index = strlen(topic); + XdrvMailbox.data_len = data_len; + XdrvMailbox.topic = topic; + XdrvMailbox.data = (char*)data; + if (XdrvCall(FUNC_MQTT_DATA)) { return; } ShowSource(SRC_MQTT); diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 44959045b..0bdc22b83 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -199,102 +199,104 @@ void DomoticzMqttSubscribe(void) bool DomoticzMqttData(void) { - char stemp1[10]; - unsigned long idx = 0; - int16_t nvalue = -1; - bool found = false; - domoticz_update_flag = true; - if (!strncmp(XdrvMailbox.topic, domoticz_out_topic, strlen(domoticz_out_topic))) { - if (XdrvMailbox.data_len < 20) { - return true; // No valid data - } - StaticJsonBuffer<400> jsonBuf; - JsonObject& domoticz = jsonBuf.parseObject(XdrvMailbox.data); - if (!domoticz.success()) { - return true; // To much or invalid data - } + + if (strncasecmp(XdrvMailbox.topic, domoticz_out_topic, strlen(domoticz_out_topic)) != 0) { + return false; // Process unchanged data + } + + // topic is domoticz/out so try to analyse + if (XdrvMailbox.data_len < 20) { + return true; // No valid data + } + StaticJsonBuffer<400> jsonBuf; + JsonObject& domoticz = jsonBuf.parseObject(XdrvMailbox.data); + if (!domoticz.success()) { + return true; // To much or invalid data + } // if (strcmp_P(domoticz["dtype"],PSTR("Light/Switch"))) { // return true; // } - idx = domoticz["idx"]; - if (domoticz.containsKey("nvalue")) { - nvalue = domoticz["nvalue"]; - } + uint32_t idx = domoticz["idx"]; + int16_t nvalue = -1; + if (domoticz.containsKey("nvalue")) { + nvalue = domoticz["nvalue"]; + } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); - if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) { - uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; - for (uint32_t i = 0; i < maxdev; i++) { - if (idx == Settings.domoticz_relay_idx[i]) { - bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); + bool found = false; + if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) { + uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; + for (uint32_t i = 0; i < maxdev; i++) { + if (idx == Settings.domoticz_relay_idx[i]) { + bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; + char stemp1[10]; + snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); #ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (1 == i)) { // Idx 2 is fanspeed - uint8_t svalue = 0; - if (domoticz.containsKey("svalue1")) { - svalue = domoticz["svalue1"]; - } else { - return true; // Invalid data - } - svalue = (nvalue == 2) ? svalue / 10 : 0; - if (GetFanspeed() == svalue) { - return true; // Stop loop as already set - } - if (TimePassedSince(domoticz_fan_debounce) < 1000) { - return true; // Stop loop if device in limbo - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue); - found = true; - } else + if (IsModuleIfan() && (1 == i)) { // Idx 2 is fanspeed + uint8_t svalue = 0; + if (domoticz.containsKey("svalue1")) { + svalue = domoticz["svalue1"]; + } else { + return true; // Invalid data + } + svalue = (nvalue == 2) ? svalue / 10 : 0; + if (GetFanspeed() == svalue) { + return true; // Stop loop as already set + } + if (TimePassedSince(domoticz_fan_debounce) < 1000) { + return true; // Stop loop if device in limbo + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue); + found = true; + } else #endif // USE_SONOFF_IFAN - if (iscolordimmer && 10 == nvalue) { // Color_SetColor - JsonObject& color = domoticz["Color"]; - uint16_t level = nvalue = domoticz["svalue1"]; - uint16_t r = color["r"]; r = r * level / 100; - uint16_t g = color["g"]; g = g * level / 100; - uint16_t b = color["b"]; b = b * level / 100; - uint16_t cw = color["cw"]; cw = cw * level / 100; - uint16_t ww = color["ww"]; ww = ww * level / 100; - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww); - found = true; - } - else if ((!iscolordimmer && 2 == nvalue) || // gswitch_sSetLevel - (iscolordimmer && 15 == nvalue)) { // Color_SetBrightnessLevel - if (domoticz.containsKey("svalue1")) { - nvalue = domoticz["svalue1"]; - } else { - return true; // Invalid data - } - if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) { - return true; // State already set - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); - found = true; - } - else if (1 == nvalue || 0 == nvalue) { - if (((power >> i) &1) == (power_t)nvalue) { - return true; // Stop loop - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : ""); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); - found = true; - } - break; + if (iscolordimmer && 10 == nvalue) { // Color_SetColor + JsonObject& color = domoticz["Color"]; + uint16_t level = nvalue = domoticz["svalue1"]; + uint16_t r = color["r"]; r = r * level / 100; + uint16_t g = color["g"]; g = g * level / 100; + uint16_t b = color["b"]; b = b * level / 100; + uint16_t cw = color["cw"]; cw = cw * level / 100; + uint16_t ww = color["ww"]; ww = ww * level / 100; + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww); + found = true; } + else if ((!iscolordimmer && 2 == nvalue) || // gswitch_sSetLevel + (iscolordimmer && 15 == nvalue)) { // Color_SetBrightnessLevel + if (domoticz.containsKey("svalue1")) { + nvalue = domoticz["svalue1"]; + } else { + return true; // Invalid data + } + if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) { + return true; // State already set + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); + found = true; + } + else if (1 == nvalue || 0 == nvalue) { + if (((power >> i) &1) == (power_t)nvalue) { + return true; // Stop loop + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : ""); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); + found = true; + } + break; } } - if (!found) { return true; } // No command received - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data); - - domoticz_update_flag = false; } - return false; // Process unchanged or new data + if (!found) { return true; } // No command received + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data); + + domoticz_update_flag = false; + return false; // Process new data } /*********************************************************************************************/ diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index b26e5402d..04a6d3413 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -698,10 +698,10 @@ void RulesTeleperiod(void) */ bool RulesMqttData(void) { - bool serviced = false; if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) { return false; } + bool serviced = false; String sTopic = XdrvMailbox.topic; String sData = XdrvMailbox.data; //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: MQTT Topic %s, Event %s"), XdrvMailbox.topic, XdrvMailbox.data); diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index be9936c4d..ead58e613 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -847,16 +847,6 @@ void XsnsDriverState(void) /*********************************************************************************************/ -bool XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t sdataBuf) -{ - XdrvMailbox.index = stopicBuf; - XdrvMailbox.data_len = sdataBuf; - XdrvMailbox.topic = topicBuf; - XdrvMailbox.data = dataBuf; - - return XdrvCall(FUNC_MQTT_DATA); -} - bool XdrvRulesProcess(void) { return XdrvCallDriver(10, FUNC_RULES_PROCESS); From da2b2efae03cfd8504a70cd6aa76ada1ca8b5c0c Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 2 Oct 2019 13:38:05 +0200 Subject: [PATCH 2035/2222] update scripter hue without devices --- sonoff/support_udp.ino | 4 + sonoff/xdrv_10_scripter.ino | 185 ++++++++++++++++++++++++++++-------- sonoff/xdrv_20_hue.ino | 12 ++- 3 files changed, 159 insertions(+), 42 deletions(-) diff --git a/sonoff/support_udp.ino b/sonoff/support_udp.ino index 550e97b97..a33ca6973 100644 --- a/sonoff/support_udp.ino +++ b/sonoff/support_udp.ino @@ -85,7 +85,11 @@ void PollUdp(void) // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); // Simple Service Discovery Protocol (SSDP) +#ifdef USE_SCRIPT_HUE + if (!udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { +#else if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { +#endif udp_response_mutex = true; udp_remote_ip = PortUdp.remoteIP(); diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index ce0430f8f..4c12c6253 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -3366,30 +3366,8 @@ void ScriptSaveSettings(void) { #endif -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) +#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) -/* -"state": { -"temperature": 2674, -"lastupdated": "2017-08-04T12:13:04" -}, -"config": { -"on": true, -"battery": 100, -"reachable": true, -"alert": "none", -"ledindication": false, -"usertest": false, -"pending": [] -}, -"name": "Hue temperature sensor 1", -"type": "ZLLTemperature", -"modelid": "SML001", -"manufacturername": "Philips", -"swversion": "6.1.0.18912", -"uniqueid": "xxx" -} -*/ #define HUE_DEV_MVNUM 5 #define HUE_DEV_NSIZE 16 @@ -3414,8 +3392,76 @@ const char SCRIPT_HUE_LIGHTS_STATUS_JSON1[] PROGMEM = "\"uniqueid\":\"{j2\"," "\"swversion\":\"5.50.1.19085\"}"; +/* +const char SCRIPT_HUE_LIGHTS_STATUS_JSON2[] PROGMEM = + "{\"state\":" + "{\"temperature\": 2674," + "\"lastupdated\": \"2019-08-04T12:13:04\"}," + "\"config\": {" + "\"on\": true," + "\"battery\": 100," + "\"reachable\": true," + "\"alert\": \"none\"," + "\"ledindication\": false," + "\"usertest\": false," + "\"pending\": []" + "}," + "\"name\": \"{j1\"," + "\"type\": \"ZLLTemperature\"," + "\"modelid\": \"SML001\"," + "\"manufacturername\": \"Philips\"," + "\"swversion\": \"6.1.0.18912\"," + "\"uniqueid\": \"{j2\"}"; +*/ + + +const char SCRIPT_HUE_LIGHTS_STATUS_JSON2[] PROGMEM = +"{\"state\":{" +"\"presence\":{state}," +"\"lastupdated\":\"2017-10-01T12:37:30\"" +"}," +"\"swupdate\":{" +"\"state\":\"noupdates\"," +"\"lastinstall\": null" +"}," +"\"config\":{" +"\"on\":true," +"\"battery\":100," +"\"reachable\":true," +"\"alert\":\"none\"," +"\"ledindication\":false," +"\"usertest\":false," +"\"sensitivity\":2," +"\"sensitivitymax\":2," +"\"pending\":[]" +"}," +"\"name\":\"{j1\"," +"\"type\":\"ZLLPresence\"," +"\"modelid\":\"SML001\"," +"\"manufacturername\":\"Philips\"," +"\"swversion\":\"6.1.0.18912\"," +"\"uniqueid\":\"{j2\"" +"}"; + +/* + temperature ZLLTemperature + lightlevel ZLLLightLevel + presence ZLLPresence + */ + + void Script_HueStatus(String *response, uint16_t hue_devs) { + + if (hue_script[hue_devs].type=='P') { + *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON2); + response->replace("{j1",hue_script[hue_devs].name); + response->replace("{j2", GetHueDeviceId(hue_devs)); + uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; + response->replace("{state}", (pwr ? "true" : "false")); + return; + } + *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON1); uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; response->replace("{state}", (pwr ? "true" : "false")); @@ -3454,16 +3500,44 @@ void Script_HueStatus(String *response, uint16_t hue_devs) { light_status += ","; } - response->replace("{light_status}", light_status); - response->replace("{j1",hue_script[hue_devs].name); - response->replace("{j2", GetHueDeviceId(hue_devs<<8)); - - if (hue_script[hue_devs].type=='E') { - response->replace("{type}","Extended color light"); - } else { - response->replace("{type}","color light"); + float temp; + switch (hue_script[hue_devs].type) { + case 'E': + response->replace("{type}","Extended color light"); + break; + case 'S': + response->replace("{type}","color light"); + break; + case 'T': + response->replace("{type}","ZLLTemperature"); + temp=glob_script_mem.fvars[hue_script[hue_devs].index[2]-1]; + light_status += "\"temperature\":"; + light_status += String(temp*100); + light_status += ","; + break; + case 'L': + response->replace("{type}","ZLLLightLevel"); + temp=glob_script_mem.fvars[hue_script[hue_devs].index[2]-1]; + light_status += "\"lightlevel\":"; + light_status += String(temp); + light_status += ","; + break; + case 'P': + response->replace("{type}","ZLLPresence"); + temp=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; + light_status += "\"presence\":"; + if (temp==0)light_status += "false"; + else light_status += "true"; + light_status += ","; + break; + default: + response->replace("{type}","color light"); + break; } + response->replace("{light_status}", light_status); + response->replace("{j1",hue_script[hue_devs].name); + response->replace("{j2", GetHueDeviceId(hue_devs)); } @@ -3570,7 +3644,13 @@ void Script_Check_Hue(String *response) { } // append response if (response) { - *response+=",\""+String(EncodeLightId(hue_devs+devices_present+1))+"\":"; + if (devices_present) { + *response+=",\""; + } + else { + if (hue_devs>0) *response+=",\""; + } + *response+=String(EncodeLightId(hue_devs+devices_present+1))+"\":"; Script_HueStatus(response,hue_devs); } @@ -3584,16 +3664,22 @@ void Script_Check_Hue(String *response) { lp++; } } -#if 0 - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Hue: %d"), hue_devs); - toLog(">>>>"); - toLog(response->c_str()); - toLog(response->c_str()+LOGSZ); +#if 1 + if (response) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Hue: %d"), hue_devs); + toLog(">>>>"); + toLog(response->c_str()); + toLog(response->c_str()+LOGSZ); + } #endif } const char sHUE_LIGHT_RESPONSE_JSON[] PROGMEM = "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; + +const char sHUE_SENSOR_RESPONSE_JSON[] PROGMEM = + "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; + const char sHUE_ERROR_JSON[] PROGMEM = "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; @@ -3649,6 +3735,27 @@ void Script_Handle_Hue(String *path) { glob_script_mem.type[hue_script[index].vindex[1]].bits.changed=1; resp = true; } + if (hue_json.containsKey("xy")) { // Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white). + float x, y; + x = hue_json["xy"][0]; + y = hue_json["xy"][1]; + const String &x_str = hue_json["xy"][0]; + const String &y_str = hue_json["xy"][1]; + uint8_t rr,gg,bb; + LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); + LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "xy"); + response.replace("{re", "[" + x_str + "," + y_str + "]"); + glob_script_mem.fvars[hue_script[index].index[2]-1]=hue; + glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1; + glob_script_mem.fvars[hue_script[index].index[3]-1]=sat; + glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("hue")) { // The hue value is a wrapping value between 0 and 65535. Both 0 and 65535 are red, 25500 is green and 46920 is blue. tmp = hue_json["hue"]; //hue = changeUIntScale(tmp, 0, 65535, 0, 359); @@ -4067,7 +4174,7 @@ const char SCRIPT_MSG_BUTTONa_TBL[] PROGMEM = ""; const char SCRIPT_MSG_BUTTONb[] PROGMEM = - "<\img>"; + ""; const char SCRIPT_MSG_BUT_START[] PROGMEM = "
"; @@ -4437,7 +4544,9 @@ bool Xdrv10(uint8_t function) if (bitRead(Settings.rule_enabled, 0)) { Run_Scripter(">B",2,0); fast_script=Run_Scripter(">F",-2,0); +#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) Script_Check_Hue(0); +#endif } break; case FUNC_EVERY_100_MSECOND: diff --git a/sonoff/xdrv_20_hue.ino b/sonoff/xdrv_20_hue.ino index d39da9a4c..cd41a30ef 100644 --- a/sonoff/xdrv_20_hue.ino +++ b/sonoff/xdrv_20_hue.ino @@ -36,7 +36,7 @@ const char HUE_RESPONSE[] PROGMEM = "CACHE-CONTROL: max-age=100\r\n" "EXT:\r\n" "LOCATION: http://%s:80/description.xml\r\n" - "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.17.0\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.24.0\r\n" // was 1.17 "hue-bridgeid: %s\r\n"; const char HUE_ST1[] PROGMEM = "ST: upnp:rootdevice\r\n" @@ -503,7 +503,7 @@ void HueLights(String *path) response += ",\""; } } -#ifdef USE_SCRIPT +#ifdef USE_SCRIPT_HUE Script_Check_Hue(&response); #endif response += "}"; @@ -513,7 +513,7 @@ void HueLights(String *path) path->remove(path->indexOf("/state")); // Remove /state device = DecodeLightId(atoi(path->c_str())); -#ifdef USE_SCRIPT +#ifdef USE_SCRIPT_HUE if (device>devices_present) { return Script_Handle_Hue(path); } @@ -706,7 +706,7 @@ void HueLights(String *path) path->remove(0,8); // Remove /lights/ device = DecodeLightId(atoi(path->c_str())); -#ifdef USE_SCRIPT +#ifdef USE_SCRIPT_HUE if (device>devices_present) { Script_HueStatus(&response,device-devices_present-1); goto exit; @@ -799,7 +799,11 @@ bool Xdrv20(uint8_t function) { bool result = false; +#ifdef USE_SCRIPT_HUE + if ((EMUL_HUE == Settings.flag2.emulation)) { +#else if (devices_present && (EMUL_HUE == Settings.flag2.emulation)) { +#endif switch (function) { case FUNC_WEB_ADD_HANDLER: WebServer->on("/description.xml", HandleUpnpSetupHue); From 8c34b9edbd9efc3405c1c29324e347f6accd8de1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 2 Oct 2019 16:45:53 +0200 Subject: [PATCH 2036/2222] Change command handling * Change command SetOption43 to make it more general. Now supports PS_16_DZ driver too (#6547) * Change command handling by moving buffers up in chain solving MQTTlog support (#6524) * Change detection of non-MQTT commands by allowing non-space characters as delimiter (#6540) --- sonoff/_changelog.ino | 3 ++ sonoff/support_command.ino | 73 ++++++++++++++++++++------------------ sonoff/xdrv_02_mqtt.ino | 17 +++++---- 3 files changed, 53 insertions(+), 40 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 9139cb622..8345f9e52 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -8,6 +8,9 @@ * Add command to MCP230xx: sensor29 pin,0/1/2 for OFF/ON/TOGGLE * Add initial support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode * Add command SetOption71 0/1 to switch between different Modbus Active Energy registers on DDS238-2 energy meters (#6531) + * Change command SetOption43 to make it more general. Now supports PS_16_DZ driver too (#6547) + * Change command handling by moving buffers up in chain solving MQTTlog support (#6524) + * Change detection of non-MQTT commands by allowing non-space characters as delimiter (#6540) * * 6.6.0.13 20190922 * Add command EnergyReset4 x,x to initialize total usage for two tarrifs diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 9e2fd5fcb..182796519 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -81,55 +81,61 @@ void ResponseCmndIdxChar(const char* value) /********************************************************************************************/ -void ExecuteCommand(char *cmnd, uint32_t source) +void ExecuteCommand(const char *cmnd, uint32_t source) { - char *start; - char *token; - + // cmnd: "status 0" = stopic "status" and svalue " 0" + // cmnd: "var1 =1" = stopic "var1" and svalue " =1" + // cmnd: "var1=1" = stopic "var1" and svalue "=1" #ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("ExecuteCommand")); #endif ShowSource(source); - token = strtok(cmnd, " "); - if (token != nullptr) { - start = strrchr(token, '/'); // Skip possible cmnd/sonoff/ preamble - if (start) { token = start +1; } + const char *pos = cmnd; + while (*pos && isspace(*pos)) { + pos++; // Skip all spaces } - uint32_t size = (token != nullptr) ? strlen(token) : 0; - char stopic[size +2]; // / + \0 - snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == nullptr) ? "" : token); - token = strtok(nullptr, ""); - size = (token != nullptr) ? strlen(token) : 0; - char svalue[size +1]; - strlcpy(svalue, (token == nullptr) ? "" : token, sizeof(svalue)); // Fixed 5.8.0b - CommandHandler(stopic, (uint8_t*)svalue, strlen(svalue)); + const char *start = pos; + // Get a command. Commands can only use letters, digits and underscores + while (*pos && (isalpha(*pos) || isdigit(*pos) || '_' == *pos || '/' == *pos)) { + if ('/' == *pos) { // Skip possible cmnd/sonoff/ preamble + start = pos + 1; + } + pos++; + } + if ('\0' == *start || pos <= start) { + return; // Did not find any command to execute + } + + uint32_t size = pos - start; + char stopic[size + 2]; // with leader '/' and end '\0' + stopic[0] = '/'; + memcpy(stopic+1, start, size); + stopic[size+1] = '\0'; + + char svalue[strlen(pos) +1]; // pos point to the start of parameters + strlcpy(svalue, pos, sizeof(svalue)); + CommandHandler(stopic, svalue, strlen(svalue)); } /********************************************************************************************/ -// topic: /power1 data: toggle = Console command -// topic: cmnd/sonoff/power1 data: toggle = Mqtt command using topic -// topic: cmnd/sonoffs/power1 data: toggle = Mqtt command using a group topic -// topic: cmnd/DVES_83BB10_fb/power1 data: toggle = Mqtt command using fallback topic +// topicBuf: /power1 dataBuf: toggle = Console command +// topicBuf: cmnd/sonoff/power1 dataBuf: toggle = Mqtt command using topic +// topicBuf: cmnd/sonoffs/power1 dataBuf: toggle = Mqtt command using a group topic +// topicBuf: cmnd/DVES_83BB10_fb/power1 dataBuf: toggle = Mqtt command using fallback topic -void CommandHandler(char* topic, uint8_t* data, uint32_t data_len) +void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) { #ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("CommandHandler")); #endif - char topicBuf[TOPSZ]; - strlcpy(topicBuf, topic, sizeof(topicBuf)); - - uint32_t i = 0; - for (i = 0; i < data_len; i++) { - if (!isspace(data[i])) { break; } // Skip leading spaces in data + while (*dataBuf && isspace(*dataBuf)) { + dataBuf++; // Skip leading spaces in data + data_len--; } - data_len -= i; - char dataBuf[data_len+1]; - memcpy(dataBuf, data +i, sizeof(dataBuf)); bool grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != nullptr); @@ -137,8 +143,9 @@ void CommandHandler(char* topic, uint8_t* data, uint32_t data_len) GetFallbackTopic_P(stemp1, CMND, ""); // Full Fallback topic = cmnd/DVES_xxxxxxxx_fb/ fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); - char *type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type) + char *type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type) + uint32_t i = 0; uint32_t index = 1; bool user_index = false; if (type != nullptr) { @@ -156,7 +163,7 @@ void CommandHandler(char* topic, uint8_t* data, uint32_t data_len) type[i] = '\0'; } - DEBUG_CORE_LOG(PSTR("CMD: " D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " \"%s\", " D_DATA " \"%s\""), grpflg, index, type, dataBuf); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CMD: " D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " \"%s\", " D_DATA " \"%s\""), grpflg, index, type, dataBuf); if (type != nullptr) { Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); @@ -686,11 +693,9 @@ void CmndSetoption(void) IrReceiveUpdateThreshold(); break; #endif -#ifdef USE_TUYA_MCU case P_DIMMER_MAX: restart_flag = 2; // Need a restart to update GUI break; -#endif } } } diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 81fd45b6f..edc844448 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -251,7 +251,7 @@ bool MqttPublishLib(const char* topic, bool retained) return result; } -void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) +void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len) { #ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("MqttDataHandler")); @@ -262,8 +262,8 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) // Do not execute multiple times if Prefix1 equals Prefix2 if (!strcmp(Settings.mqtt_prefix[0], Settings.mqtt_prefix[1])) { - char *str = strstr(topic, Settings.mqtt_prefix[0]); - if ((str == topic) && mqtt_cmnd_publish) { + char *str = strstr(mqtt_topic, Settings.mqtt_prefix[0]); + if ((str == mqtt_topic) && mqtt_cmnd_publish) { if (mqtt_cmnd_publish > 3) { mqtt_cmnd_publish -= 3; } else { @@ -273,10 +273,15 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } } - data[data_len] = 0; + // Save MQTT data ASAP as it's data is discarded by PubSubClient with next publish as used in MQTTlog + char topic[TOPSZ]; + strlcpy(topic, mqtt_topic, sizeof(topic)); + mqtt_data[data_len] = 0; + char data[data_len +1]; + memcpy(data, mqtt_data, sizeof(data)); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_RECEIVED_TOPIC " %s, " D_DATA_SIZE " %d, " D_DATA " %s"), topic, data_len, data); -// if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) { Serial.println(dataBuf); } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_RECEIVED_TOPIC " \"%s\", " D_DATA_SIZE " %d, " D_DATA " \"%s\""), topic, data_len, data); +// if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) { Serial.println(data); } // MQTT pre-processing XdrvMailbox.index = strlen(topic); From 3e7e882ee5a9ad774daae77b18e54d2f59898a5d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 2 Oct 2019 17:20:03 +0200 Subject: [PATCH 2037/2222] Update TasmotaSerial.cpp --- lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp b/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp index 0a1386375..ebce5a496 100644 --- a/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp @@ -218,6 +218,7 @@ int TasmotaSerial::available() #define TM_SERIAL_WAIT_RCV_LOOP { while (ESP.getCycleCount() < (wait + start)); } #else #define TM_SERIAL_WAIT_SND { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; } +#define TM_SERIAL_WAIT_SND_FAST { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; } #define TM_SERIAL_WAIT_RCV { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; } #define TM_SERIAL_WAIT_RCV_LOOP { while (ESP.getCycleCount() < (wait + start)); } #endif From bc55237154061d22677a01e8ef66235780579ae1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 2 Oct 2019 17:39:27 +0200 Subject: [PATCH 2038/2222] Fix domoticz core 2.3.0 compilation error Fix domoticz core 2.3.0 compilation error --- sonoff/_changelog.ino | 4 ++-- sonoff/xdrv_07_domoticz.ino | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 98b13e80e..ac8e7a1b0 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -8,8 +8,8 @@ * Add command to MCP230xx: sensor29 pin,0/1/2 for OFF/ON/TOGGLE * Add initial support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode * Add command SetOption71 0/1 to switch between different Modbus Active Energy registers on DDS238-2 energy meters (#6531) - * Change command SetOption43 to make it more general. Now supports PS_16_DZ driver too (#6547) - * Change command handling by moving buffers up in chain solving MQTTlog support (#6524) + * Change command SetOption43 to make it more general. Now supports PS_16_DZ driver too (#6544) + * Change command handling by moving buffers up in chain solving MQTTlog support (#6529) * Change detection of non-MQTT commands by allowing non-space characters as delimiter (#6540) * Fix TasmotaSerial: move serial send to IRAM for high speed baud rates * diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 0bdc22b83..e4f1b5ca1 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -45,7 +45,6 @@ const char kDomoticzSensors[] PROGMEM = D_DOMOTICZ_COUNT "|" D_DOMOTICZ_VOLTAGE "|" D_DOMOTICZ_CURRENT "|" D_DOMOTICZ_AIRQUALITY "|" D_DOMOTICZ_P1_SMART_METER "|" D_DOMOTICZ_SHUTTER ; char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; -char domoticz_out_topic[] = DOMOTICZ_OUT_TOPIC; int domoticz_update_timer = 0; uint32_t domoticz_fan_debounce = 0; // iFan02 state debounce timer @@ -166,7 +165,7 @@ void DomoticzMqttSubscribe(void) } if (domoticz_subscribe) { char stopic[TOPSZ]; - snprintf_P(stopic, sizeof(stopic), PSTR("%s/#"), domoticz_out_topic); // domoticz topic + snprintf_P(stopic, sizeof(stopic), PSTR(DOMOTICZ_OUT_TOPIC "/#")); // domoticz topic MqttSubscribe(stopic); } } @@ -201,7 +200,7 @@ bool DomoticzMqttData(void) { domoticz_update_flag = true; - if (strncasecmp(XdrvMailbox.topic, domoticz_out_topic, strlen(domoticz_out_topic)) != 0) { + if (strncasecmp_P(XdrvMailbox.topic, PSTR(DOMOTICZ_OUT_TOPIC), strlen(DOMOTICZ_OUT_TOPIC)) != 0) { return false; // Process unchanged data } From 4eef80e4d9689f2a37b068df559af4c7df707a4a Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Wed, 2 Oct 2019 13:16:14 -0300 Subject: [PATCH 2039/2222] Update xdrv_12_home_assistant.ino --- sonoff/xdrv_12_home_assistant.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 538c25e06..3d887bde1 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -347,7 +347,7 @@ void HAssAnnounceSwitches(void) // Send info about buttons char *tmp = Settings.switch_topic; Format(sw_topic, tmp, sizeof(sw_topic)); - if ((strlen(sw_topic) != 0) && strcmp(sw_topic, "0")) { + if (strlen(sw_topic) != 0) { for (uint32_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) { uint8_t switch_present = 0; uint8_t toggle = 1; @@ -376,7 +376,7 @@ void HAssAnnounceButtons(void) // Send info about buttons char *tmp = Settings.button_topic; Format(key_topic, tmp, sizeof(key_topic)); - if ((strlen(key_topic) != 0) && strcmp(key_topic, "0")) { + if (strlen(key_topic) != 0) { for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { uint8_t button_present = 0; uint8_t toggle = 1; From 11d4cd9058770e0edd8ac01711881ae08b64b58e Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Wed, 2 Oct 2019 16:58:52 -0300 Subject: [PATCH 2040/2222] Update my_user_config.h --- sonoff/my_user_config.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index cd82cea53..2310df0d2 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -66,8 +66,9 @@ #define STA_PASS1 "" // [Password1] Wifi password #define STA_SSID2 "" // [Ssid2] Optional alternate AP Wifi SSID #define STA_PASS2 "" // [Password2] Optional alternate AP Wifi password -#define WIFI_CONFIG_TOOL WIFI_RETRY // [WifiConfig] Default tool if wifi fails to connect - // (WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL) +#define WIFI_CONFIG_TOOL WIFI_RETRY // [WifiConfig] Default tool if wifi fails to connect (default option: 4 - WIFI_RETRY) + // (WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, WIFI_MANAGER_RESET_ONLY) + // The configuration can be changed after first setup using WifiConfig 0, 1, 2, 3, 4, 5, 6 and 7. #define WIFI_CONFIG_NO_SSID WIFI_WPSCONFIG // Default tool if wifi fails to connect and no SSID is configured // (WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_SERIAL) // *** NOTE: When WPS is disabled by USE_WPS below, WIFI_WPSCONFIG will execute WIFI_MANAGER *** From 913a80924293ffe7a0f49378bd0f1e95ce3707e4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 3 Oct 2019 09:58:23 +0200 Subject: [PATCH 2041/2222] Bump version 6.6.0.15 Bump version 6.6.0.15 --- sonoff/_changelog.ino | 2 ++ sonoff/sonoff_version.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index ac8e7a1b0..13a994061 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,6 @@ /*********************************************************************************************\ + * 6.6.0.15 20191003 + * * 6.6.0.14 20190925 * Change command Tariffx to allow time entries like 23 (hours), 1320 (minutes) or 23:00. NOTE: As this is development branch previous tariffs are lost! (#6488) * Remove support for define USE_DS18x20_LEGACY and legacy DS18x20 driver (#6486) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 02af08bab..51d92d944 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x0606000E; +const uint32_t VERSION = 0x0606000F; #endif // _SONOFF_VERSION_H_ From cbb3f9e0af6e163cebf18a29c4d011281743db23 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 3 Oct 2019 10:02:57 +0200 Subject: [PATCH 2042/2222] Change command PulseTime JSON message Change command PulseTime JSON message format and allow display of all pulsetimer information (#6519) --- sonoff/_changelog.ino | 1 + sonoff/i18n.h | 3 ++- sonoff/support_command.ino | 20 ++++++++++++++++---- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 13a994061..e9cdf437d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /*********************************************************************************************\ * 6.6.0.15 20191003 + * Change command PulseTime JSON message format and allow display of all pulsetimer information (#6519) * * 6.6.0.14 20190925 * Change command Tariffx to allow time entries like 23 (hours), 1320 (minutes) or 23:00. NOTE: As this is development branch previous tariffs are lost! (#6488) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 5dae197a6..089140dd9 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -118,6 +118,7 @@ #define D_JSON_PROGRAMFLASHSIZE "ProgramFlashSize" #define D_JSON_PROGRAMSIZE "ProgramSize" #define D_JSON_REFERENCETEMPERATURE "ReferenceTemperature" +#define D_JSON_REMAINING "Remaining" #define D_JSON_RESET "Reset" #define D_JSON_RESISTANCE "Resistance" #define D_JSON_RESOLUTION "Resolution" @@ -132,6 +133,7 @@ #define D_JSON_SDKVERSION "SDK" #define D_JSON_SELECTED "selected" #define D_JSON_SERIALRECEIVED "SerialReceived" +#define D_JSON_SET "Set" #define D_JSON_SSID "SSId" #define D_JSON_STARTDST "StartDST" // Start Daylight Savings Time #define D_JSON_STARTED "Started" @@ -557,7 +559,6 @@ const char S_JSON_COMMAND_INDEX_LVALUE[] PROGMEM = "{\"%s%d\":%lu}"; const char S_JSON_COMMAND_INDEX_SVALUE[] PROGMEM = "{\"%s%d\":\"%s\"}"; const char S_JSON_COMMAND_INDEX_ASTERISK[] PROGMEM = "{\"%s%d\":\"" D_ASTERISK_PWD "\"}"; const char S_JSON_COMMAND_INDEX_SVALUE_SVALUE[] PROGMEM = "{\"%s%d\":\"%s%s\"}"; -const char S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE[] PROGMEM = "{\"%s%d\":{\"%d\":{\"" D_JSON_ACTIVE "\":\"%d\"}}}"; const char S_JSON_SENSOR_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":%d}"; const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":\"%s\"}"; diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 182796519..4683c7c85 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -565,11 +565,23 @@ void CmndPowerOnState(void) void CmndPulsetime(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PULSETIMERS)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { - Settings.pulse_timer[XdrvMailbox.index -1] = XdrvMailbox.payload; // 0 - 65535 - SetPulseTimer(XdrvMailbox.index -1, XdrvMailbox.payload); + uint32_t items = 1; + if (!XdrvMailbox.usridx) { + items = MAX_PULSETIMERS; + } else { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { + Settings.pulse_timer[XdrvMailbox.index -1] = XdrvMailbox.payload; // 0 - 65535 + SetPulseTimer(XdrvMailbox.index -1, XdrvMailbox.payload); + } } - Response_P(S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, XdrvMailbox.index, Settings.pulse_timer[XdrvMailbox.index -1], GetPulseTimer(XdrvMailbox.index -1)); + mqtt_data[0] = '\0'; + for (uint32_t i = 0; i < items; i++) { + ResponseAppend_P(PSTR("%c\"%s%d\":{\"" D_JSON_SET "\":%d,\"" D_JSON_REMAINING "\":%d}"), + (i) ? ',' : '{', + XdrvMailbox.command, (1 == items) ? XdrvMailbox.index : i +1, + Settings.pulse_timer[XdrvMailbox.index -1], GetPulseTimer(XdrvMailbox.index -1)); + } + ResponseJsonEnd(); } } From 9e711095490eb70f07ad0623195710f88e71eee4 Mon Sep 17 00:00:00 2001 From: pablozg Date: Thu, 3 Oct 2019 10:06:51 +0200 Subject: [PATCH 2043/2222] add support to chint ddsu666 --- sonoff/language/bg-BG.h | 2 + sonoff/language/cs-CZ.h | 2 + sonoff/language/de-DE.h | 2 + sonoff/language/el-GR.h | 2 + sonoff/language/en-GB.h | 2 + sonoff/language/es-ES.h | 2 + sonoff/language/fr-FR.h | 2 + sonoff/language/he-HE.h | 2 + sonoff/language/hu-HU.h | 2 + sonoff/language/it-IT.h | 2 + sonoff/language/ko-KO.h | 2 + sonoff/language/nl-NL.h | 2 + sonoff/language/pl-PL.h | 2 + sonoff/language/pt-BR.h | 2 + sonoff/language/pt-PT.h | 2 + sonoff/language/ru-RU.h | 2 + sonoff/language/sk-SK.h | 2 + sonoff/language/sv-SE.h | 2 + sonoff/language/tr-TR.h | 2 + sonoff/language/uk-UK.h | 2 + sonoff/language/zh-CN.h | 2 + sonoff/language/zh-TW.h | 2 + sonoff/my_user_config.h | 2 + sonoff/sonoff_post.h | 6 ++ sonoff/sonoff_template.h | 7 ++ sonoff/support_features.ino | 4 +- sonoff/xnrg_11_ddsu666.ino | 175 ++++++++++++++++++++++++++++++++++++ tools/decode-status.py | 2 +- 28 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 sonoff/xnrg_11_ddsu666.ino diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index b7080f2ca..43792cdb3 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index d413910b3..1067a6f02 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 71c4a1de1..fe6067153 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 3b6f5edcc..3c43b65c6 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index af4ba7b64..27ef1e342 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-ES.h b/sonoff/language/es-ES.h index 239542068..252f72ce3 100644 --- a/sonoff/language/es-ES.h +++ b/sonoff/language/es-ES.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 3216932ee..1c8eb4eec 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 5fdcc93e3..b551de296 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 0bcb1da05..81f1d080a 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index f1183d090..1c6390cc2 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index 5b99924bb..0f628e04e 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index b8b0c1e88..d79a419b2 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index d3a7712b9..8e374437f 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 209738d81..831d79d03 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index f9debe83b..970fb2b8a 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 7306b1820..474d7f254 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index d462ecfac..092661890 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index a903db1f9..16d5110be 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 7e23b9d4d..e17623637 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index dd694ff85..92b3711fd 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 8b1464b33..872c13563 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 8fa61ed9e..4d26109fa 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -617,6 +617,8 @@ #define D_SENSOR_A4988_MS3 "A4988 MS3" #define D_SENSOR_DDS2382_TX "DDS238-2 Tx" #define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 2310df0d2..e13a666e5 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -447,6 +447,8 @@ //#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+4k1 code) #define SOLAXX1_SPEED 9600 // Solax X1 Modbus RS485 serial speed (default: 9600 baud) #define SOLAXX1_PV2 // Solax X1 using second PV +//#define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) + #define DDSU666_SPEED 9600 // Chint DDSU666 Modbus RS485 serial speed (default: 9600 baud) // -- Low level interface devices ----------------- #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor (1k6 code) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 3a792f569..eceb972a0 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -165,6 +165,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_SDM120_2 // Add support for Eastron SDM120-Modbus energy monitor (+1k1 code) #define USE_SDM630_2 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) #define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) +#define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI @@ -251,6 +252,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) +#undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI @@ -305,6 +307,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) + #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) #undef USE_DOMOTICZ // Disable Domoticz #undef USE_HOME_ASSISTANT // Disable Home Assistant @@ -388,6 +391,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) +#undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) //#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI @@ -484,6 +488,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) +#undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI @@ -568,6 +573,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) +#undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index e0f3c6e06..6781e607f 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -202,6 +202,8 @@ enum UserSelectablePins { GPIO_A4988_MS3, // A4988 microstep pin3 GPIO_DDS2382_TX, // DDS2382 Serial interface GPIO_DDS2382_RX, // DDS2382 Serial interface + GPIO_DDSU666_TX, // DDSU666 Serial interface + GPIO_DDSU666_RX, // DDSU666 Serial interface GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -277,6 +279,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_IBEACON_TX "|" D_SENSOR_IBEACON_RX "|" D_SENSOR_A4988_DIR "|" D_SENSOR_A4988_STP "|" D_SENSOR_A4988_ENA "|" D_SENSOR_A4988_MS1 "|" D_SENSOR_A4988_MS2 "|" D_SENSOR_A4988_MS3 "|" D_SENSOR_DDS2382_TX "|" D_SENSOR_DDS2382_RX "|" + D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|" ; // User selectable ADC0 functionality @@ -645,6 +648,10 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_SOLAXX1_TX, // Solax Inverter tx pin GPIO_SOLAXX1_RX, // Solax Inverter rx pin #endif +#ifdef USE_DDSU666 + GPIO_DDSU666_TX, // DDSU666 Serial interface + GPIO_DDSU666_RX, // DDSU666 Serial interface +#endif // USE_DDSU666 #ifdef USE_SERIAL_BRIDGE GPIO_SBR_TX, // Serial Bridge Serial interface diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 999850db3..30403e6c3 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -459,7 +459,9 @@ void GetFeatures(void) #ifdef USE_PCF8574 feature5 |= 0x00000200; // Xdrv_028_pcf8574.ino #endif -// feature5 |= 0x00000400; +#ifdef USE_DDSU666 + feature5 |= 0x00000400; // Xnrg_11_ddsu666.ino +#endif // feature5 |= 0x00000800; // feature5 |= 0x00001000; diff --git a/sonoff/xnrg_11_ddsu666.ino b/sonoff/xnrg_11_ddsu666.ino new file mode 100644 index 000000000..2f6dfbf36 --- /dev/null +++ b/sonoff/xnrg_11_ddsu666.ino @@ -0,0 +1,175 @@ +/* + xnrg_11_ddsu666.ino - Chint DDSU666-Modbus energy meter support for Sonoff-Tasmota + + Copyright (C) 2019 Pablo Zerón 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 + 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_ENERGY_SENSOR +#ifdef USE_DDSU666 +/*********************************************************************************************\ + * Chint DDSU666 Modbus energy meter +\*********************************************************************************************/ + +#define XNRG_11 11 + +// can be user defined in my_user_config.h +#ifndef DDSU666_SPEED + #define DDSU666_SPEED 9600 // default DDSU66 Modbus address +#endif +// can be user defined in my_user_config.h +#ifndef DDSU666_ADDR + #define DDSU666_ADDR 1 // default DDSU66 Modbus address +#endif + +#include +TasmotaModbus *Ddsu666Modbus; + +const uint16_t Ddsu666_start_addresses[] { + 0x2000, // DDSU666_VOLTAGE [V] + 0x2002, // DDSU666_CURRENT [A] + 0x2004, // DDSU666_POWER [KW] + 0x2006, // DDSU666_REACTIVE_POWER [KVAR] + 0x200A, // DDSU666_POWER_FACTOR + 0x200E, // DDSU666_FREQUENCY [Hz] + 0X4000, // DDSU666_IMPORT_ACTIVE [kWh] + 0X400A, // DDSU666_EXPORT_ACTIVE [kWh] +}; + +struct DDSU666 { + float import_active = NAN; + uint8_t read_state = 0; + uint8_t send_retry = 0; +} Ddsu666; + +/*********************************************************************************************/ + +void DDSU666Every250ms(void) +{ + bool data_ready = Ddsu666Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; // At least 5 + (2 * 2) = 9 + + uint32_t error = Ddsu666Modbus->ReceiveBuffer(buffer, 2); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Ddsu666Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: Ddsu666 error %d"), error); + } else { + Energy.data_valid[0] = 0; + + // 0 1 2 3 4 5 6 7 8 + // SA FC BC Fh Fl Sh Sl Cl Ch + // 01 04 04 43 66 33 34 1B 38 = 230.2 Volt + float value; + ((uint8_t*)&value)[3] = buffer[3]; // Get float values + ((uint8_t*)&value)[2] = buffer[4]; + ((uint8_t*)&value)[1] = buffer[5]; + ((uint8_t*)&value)[0] = buffer[6]; + + switch(Ddsu666.read_state) { + case 0: + Energy.voltage[0] = value; // 230.2 V + break; + + case 1: + Energy.current[0] = value; // 1.260 A + break; + + case 2: + Energy.active_power[0] = value * 1000; // -196.3 W + break; + + case 3: + Energy.reactive_power[0] = value * 1000; // 92.2 + break; + + case 4: + Energy.power_factor[0] = value; // 0.91 + break; + + case 5: + Energy.frequency[0] = value; // 50.0 Hz + break; + + case 6: + Ddsu666.import_active = value; // 478.492 kWh + break; + + case 7: + Energy.export_active = value; // 6.216 kWh + break; + } + + Ddsu666.read_state++; + + if (Ddsu666.read_state == 8) { + Ddsu666.read_state = 0; + EnergyUpdateTotal(Ddsu666.import_active, true); // 484.708 kWh + } + } + } // end data ready + + if (0 == Ddsu666.send_retry || data_ready) { + Ddsu666.send_retry = 5; + Ddsu666Modbus->Send(DDSU666_ADDR, 0x04, Ddsu666_start_addresses[Ddsu666.read_state], 2); + } else { + Ddsu666.send_retry--; + } +} + +void Ddsu666SnsInit(void) +{ + Ddsu666Modbus = new TasmotaModbus(pin[GPIO_DDSU666_RX], pin[GPIO_DDSU666_TX]); + uint8_t result = Ddsu666Modbus->Begin(DDSU666_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void Ddsu666DrvInit(void) +{ + if ((pin[GPIO_DDSU666_RX] < 99) && (pin[GPIO_DDSU666_TX] < 99)) { + energy_flg = XNRG_11; + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xnrg11(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { DDSU666Every250ms(); } + break; + case FUNC_INIT: + Ddsu666SnsInit(); + break; + case FUNC_PRE_INIT: + Ddsu666DrvInit(); + break; + } + return result; +} + +#endif // USE_DDSU666 +#endif // USE_ENERGY_SENSOR diff --git a/tools/decode-status.py b/tools/decode-status.py index a08689306..3d35f1147 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -171,7 +171,7 @@ a_features = [[ ],[ "USE_BUZZER","USE_RDM6300","USE_IBEACON","USE_SML_M", "USE_INA226","USE_A4988_Stepper","USE_DDS2382","USE_SM2135", - "USE_SHUTTER","USE_PCF8574","","", + "USE_SHUTTER","USE_PCF8574","USE_DDSU666","", "","","","", "","","","", "","","","", From aebe37c8909d90f4d1372dbc8c6f5ee2bd8dadd0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 3 Oct 2019 13:11:43 +0200 Subject: [PATCH 2044/2222] Fix PulseTime command responses Fix PulseTime command responses --- sonoff/support_command.ino | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 4683c7c85..d940985f9 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -566,7 +566,7 @@ void CmndPulsetime(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PULSETIMERS)) { uint32_t items = 1; - if (!XdrvMailbox.usridx) { + if (!XdrvMailbox.usridx && !XdrvMailbox.data_len) { items = MAX_PULSETIMERS; } else { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { @@ -576,10 +576,11 @@ void CmndPulsetime(void) } mqtt_data[0] = '\0'; for (uint32_t i = 0; i < items; i++) { + uint32_t index = (1 == items) ? XdrvMailbox.index : i +1; ResponseAppend_P(PSTR("%c\"%s%d\":{\"" D_JSON_SET "\":%d,\"" D_JSON_REMAINING "\":%d}"), (i) ? ',' : '{', - XdrvMailbox.command, (1 == items) ? XdrvMailbox.index : i +1, - Settings.pulse_timer[XdrvMailbox.index -1], GetPulseTimer(XdrvMailbox.index -1)); + XdrvMailbox.command, index, + Settings.pulse_timer[index -1], GetPulseTimer(index -1)); } ResponseJsonEnd(); } From 0580ceb0b6f94f7e97540f6c7fd79905aa35581a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 3 Oct 2019 14:18:04 +0200 Subject: [PATCH 2045/2222] Add support for Chint DDSU666 Modbus energy meter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for Chint DDSU666 Modbus energy meter by Pablo Zerón --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e9cdf437d..badd8306c 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /*********************************************************************************************\ * 6.6.0.15 20191003 * Change command PulseTime JSON message format and allow display of all pulsetimer information (#6519) + * Add support for Chint DDSU666 Modbus energy meter by Pablo Zerón * * 6.6.0.14 20190925 * Change command Tariffx to allow time entries like 23 (hours), 1320 (minutes) or 23:00. NOTE: As this is development branch previous tariffs are lost! (#6488) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index e13a666e5..95def6f00 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -438,6 +438,8 @@ #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) //#define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #define DDS2382_SPEED 9600 // Hiking DDS2382 Modbus RS485 serial speed (default: 9600 baud) +//#define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) + #define DDSU666_SPEED 9600 // Chint DDSU666 Modbus RS485 serial speed (default: 9600 baud) //#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+2k4 code) // #define SDM120_SPEED 2400 // SDM120-Modbus RS485 serial speed (default: 2400 baud) @@ -447,8 +449,6 @@ //#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+4k1 code) #define SOLAXX1_SPEED 9600 // Solax X1 Modbus RS485 serial speed (default: 9600 baud) #define SOLAXX1_PV2 // Solax X1 using second PV -//#define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) - #define DDSU666_SPEED 9600 // Chint DDSU666 Modbus RS485 serial speed (default: 9600 baud) // -- Low level interface devices ----------------- #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor (1k6 code) From a0c7db7f7c7c2744a6fa993684a2ab5999951e88 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 3 Oct 2019 14:27:01 +0200 Subject: [PATCH 2046/2222] Add Mqtt log level text Add Mqtt log level text --- sonoff/language/bg-BG.h | 1 + sonoff/language/cs-CZ.h | 1 + sonoff/language/de-DE.h | 1 + sonoff/language/el-GR.h | 1 + sonoff/language/en-GB.h | 1 + sonoff/language/es-ES.h | 1 + sonoff/language/fr-FR.h | 1 + sonoff/language/he-HE.h | 1 + sonoff/language/hu-HU.h | 1 + sonoff/language/it-IT.h | 1 + sonoff/language/ko-KO.h | 1 + sonoff/language/nl-NL.h | 1 + sonoff/language/pl-PL.h | 1 + sonoff/language/pt-BR.h | 1 + sonoff/language/pt-PT.h | 1 + sonoff/language/ru-RU.h | 1 + sonoff/language/sk-SK.h | 1 + sonoff/language/sv-SE.h | 1 + sonoff/language/tr-TR.h | 1 + sonoff/language/uk-UK.h | 1 + sonoff/language/zh-CN.h | 1 + sonoff/language/zh-TW.h | 1 + 22 files changed, 22 insertions(+) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 43792cdb3..83323eb7d 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Параметри на лога" #define D_SERIAL_LOG_LEVEL "Степен на серийния лог" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Степен на уеб лога" #define D_SYS_LOG_LEVEL "Степен на системния лог" #define D_MORE_DEBUG "Още дебъгване" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 1067a6f02..fac229e77 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Volba logování" #define D_SERIAL_LOG_LEVEL "Seriová úroveň logu" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Webová úroveň logu" #define D_SYS_LOG_LEVEL "Systemová úroveň logu" #define D_MORE_DEBUG "Více debug informací" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index fe6067153..60d4243d5 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Logging-Einstellungen" #define D_SERIAL_LOG_LEVEL "Seriell-Log Level" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Web-Log Level" #define D_SYS_LOG_LEVEL "Sys-Log Level" #define D_MORE_DEBUG "More debug" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 3c43b65c6..27fbaff3f 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Παράμετροι καταγραφής" #define D_SERIAL_LOG_LEVEL "Επίπεδο Σειριακής" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Επίπεδο Web" #define D_SYS_LOG_LEVEL "Επίπεδο Syslog" #define D_MORE_DEBUG "More debug" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 27ef1e342..b09cd462f 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Logging parameters" #define D_SERIAL_LOG_LEVEL "Serial log level" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Web log level" #define D_SYS_LOG_LEVEL "Syslog level" #define D_MORE_DEBUG "More debug" diff --git a/sonoff/language/es-ES.h b/sonoff/language/es-ES.h index 252f72ce3..987951e02 100644 --- a/sonoff/language/es-ES.h +++ b/sonoff/language/es-ES.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Parámetros Logging" #define D_SERIAL_LOG_LEVEL "Nivel de log Serial" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Nivel de log Web" #define D_SYS_LOG_LEVEL "Nivel de Syslog" #define D_MORE_DEBUG "Más Debug" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 1c8eb4eec..838e50616 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Paramètres du journal" #define D_SERIAL_LOG_LEVEL "Niveau de journalisation série" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Niveau de journalisation web" #define D_SYS_LOG_LEVEL "Niveau SysLog" #define D_MORE_DEBUG "Plus de debug" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index b551de296..226141459 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "פרמטרי לוגים" #define D_SERIAL_LOG_LEVEL "רמת לוג עבור סריאל" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "רמת לוג עבור אתר" #define D_SYS_LOG_LEVEL "Syslog רמת לוג עבור שרת" #define D_MORE_DEBUG "מיפוי נוסף" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 81f1d080a..425dc27f1 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Naplózási paraméterek" #define D_SERIAL_LOG_LEVEL "Soros naplózási szint" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Web naplózási szint" #define D_SYS_LOG_LEVEL "Syslog szint" #define D_MORE_DEBUG "Részletes hibakeresés" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 1c6390cc2..a29916940 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Parametri Logging" #define D_SERIAL_LOG_LEVEL "Livello di log Seriale" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "livello di log Web" #define D_SYS_LOG_LEVEL "livello di log Sys" #define D_MORE_DEBUG "Debug aggiuntivo" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index 0f628e04e..065b4d8e0 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "로그 상세" #define D_SERIAL_LOG_LEVEL "시리얼 로그 레벨" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Web 로그 레벨" #define D_SYS_LOG_LEVEL "Syslog 로그 레벨" #define D_MORE_DEBUG "More debug" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index d79a419b2..c568395cf 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Logging parameters" #define D_SERIAL_LOG_LEVEL "Serieel log niveau" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Web log niveau" #define D_SYS_LOG_LEVEL "Syslog niveau" #define D_MORE_DEBUG "Meer debug" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 8e374437f..c8366f1b9 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Opcje dziennika" #define D_SERIAL_LOG_LEVEL "Serial poziom dziennika" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Web poziom dziennika" #define D_SYS_LOG_LEVEL "System poziom dziennika" #define D_MORE_DEBUG "Więcej informacji debug" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 831d79d03..f05d2fffe 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Parâmetros Logging" #define D_SERIAL_LOG_LEVEL "Nível de registro serial" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Nível de registro WEB" #define D_SYS_LOG_LEVEL "Nível de registro Syslog" #define D_MORE_DEBUG "Depurar mais" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 970fb2b8a..92b43739e 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Parametros Logging" #define D_SERIAL_LOG_LEVEL "Nível de registro serial" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Nível de registro WEB" #define D_SYS_LOG_LEVEL "Nível de registro Syslog" #define D_MORE_DEBUG "Depurar mais" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 474d7f254..73b4604aa 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Параметры Logging" #define D_SERIAL_LOG_LEVEL "Serial лог уровень" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Web лог уровень" #define D_SYS_LOG_LEVEL "System лог уровень" #define D_MORE_DEBUG "Дополнительная информация для отладки" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 092661890..e0b055fcc 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Voľba logovania" #define D_SERIAL_LOG_LEVEL "Sériová úroveň logu" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Webová úroveň logu" #define D_SYS_LOG_LEVEL "Systemová úroveň logu" #define D_MORE_DEBUG "Viac debug informácí" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 16d5110be..a3f326fc7 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Loggningsparametrar" #define D_SERIAL_LOG_LEVEL "Seriell loggnivå" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Webb loggnivå" #define D_SYS_LOG_LEVEL "Syslog-nivå" #define D_MORE_DEBUG "Mer debugging" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index e17623637..7c22cedbe 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Loglama parametreleri" #define D_SERIAL_LOG_LEVEL "Serial log seviyesi" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Web log seviyesi" #define D_SYS_LOG_LEVEL "Syslog seviyesi" #define D_MORE_DEBUG "Hata ayıklama devamı" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 92b3711fd..a586a5114 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "Параметри журналу" #define D_SERIAL_LOG_LEVEL "Serial рівень" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Web рівень" #define D_SYS_LOG_LEVEL "System рівень" #define D_MORE_DEBUG "Додаткова інформація для налагодження" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 872c13563..30a733b1d 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "日志设置" #define D_SERIAL_LOG_LEVEL "串口日志级别" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Web 日志级别" #define D_SYS_LOG_LEVEL "Syslog 日志级别" #define D_MORE_DEBUG "全部调试" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 4d26109fa..bfac974f5 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -284,6 +284,7 @@ #define D_LOGGING_PARAMETERS "日志設置" #define D_SERIAL_LOG_LEVEL "串口日志級別" +#define D_MQTT_LOG_LEVEL "Mqtt log level" #define D_WEB_LOG_LEVEL "Web 日志級別" #define D_SYS_LOG_LEVEL "Syslog 日志級別" #define D_MORE_DEBUG "全部調試" From fef7faa5beeda6ecf2b8ce5642e24209230657b0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 3 Oct 2019 14:45:24 +0200 Subject: [PATCH 2047/2222] Add MQTTLog option to GUI Add MQTTLog option to GUI --- sonoff/xdrv_01_webserver.ino | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 9f8ec9eed..aeb9fcbcf 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -527,7 +527,7 @@ const char kButtonConfirm[] PROGMEM = D_CONFIRM_RESTART "|" D_CONFIRM_RESET_CONF enum CTypes { CT_HTML, CT_PLAIN, CT_XML, CT_JSON, CT_STREAM }; const char kContentTypes[] PROGMEM = "text/html|text/plain|text/xml|application/json|application/octet-stream"; -const char kLoggingOptions[] PROGMEM = D_SERIAL_LOG_LEVEL "|" D_WEB_LOG_LEVEL "|" D_SYS_LOG_LEVEL; +const char kLoggingOptions[] PROGMEM = D_SERIAL_LOG_LEVEL "|" D_WEB_LOG_LEVEL "|" D_MQTT_LOG_LEVEL "|" D_SYS_LOG_LEVEL; const char kLoggingLevels[] PROGMEM = D_NONE "|" D_ERROR "|" D_INFO "|" D_DEBUG "|" D_MORE_DEBUG; const char kEmulationOptions[] PROGMEM = D_NONE "|" D_BELKIN_WEMO "|" D_HUE_BRIDGE; @@ -1618,9 +1618,10 @@ void HandleLoggingConfiguration(void) WSContentSend_P(HTTP_FORM_LOG1); char stemp1[45]; char stemp2[32]; - uint8_t dlevel[3] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE }; - for (uint32_t idx = 0; idx < 3; idx++) { - uint32_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:Settings.syslog_level; + uint8_t dlevel[4] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE, LOG_LEVEL_NONE }; + for (uint32_t idx = 0; idx < 4; idx++) { + if ((2==idx) && !Settings.flag.mqtt_enabled) { continue; } + uint32_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:(2==idx)?Settings.mqttlog_level:Settings.syslog_level; WSContentSend_P(PSTR("

%s (%s)

"; + "
%s%s
" + "
"; const char HTTP_MSG_SLIDER2[] PROGMEM = - "
" D_DARKLIGHT "" D_BRIGHTLIGHT "
" - "
"; -#ifdef USE_SHUTTER -const char HTTP_MSG_SLIDER3[] PROGMEM = - "
" D_CLOSE "" D_OPEN "
" - "
"; -#endif // USE_SHUTTER + "
%s%s
" + "
"; const char HTTP_MSG_RSTRT[] PROGMEM = "
" D_DEVICE_WILL_RESTART "

"; @@ -1012,16 +985,31 @@ void HandleRoot(void) if (devices_present) { #ifdef USE_LIGHT if (light_type) { - if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { - WSContentSend_P(HTTP_MSG_SLIDER1, LightGetColorTemp()); - } - WSContentSend_P(HTTP_MSG_SLIDER2, Settings.light_dimmer); + if (!Settings.flag3.pwm_multi_channels) { + if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { + // Cold - Warm &t related to lb("t", value) and WebGetArg("t", tmp, sizeof(tmp)); + WSContentSend_P(HTTP_MSG_SLIDER1, F(D_COLDLIGHT), F(D_WARMLIGHT), + 153, 500, LightGetColorTemp(), 't'); + } + // Dark - Bright &d related to lb("d", value) and WebGetArg("d", tmp, sizeof(tmp)); + WSContentSend_P(HTTP_MSG_SLIDER1, F(D_DARKLIGHT), F(D_BRIGHTLIGHT), + 1, 100, Settings.light_dimmer, 'd'); + } else { // Settings.flag3.pwm_multi_channels + uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + for (uint32_t i = 0; i < pwm_channels; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("c%d"), i); + WSContentSend_P(HTTP_MSG_SLIDER2, stemp, FPSTR("100%"), + 1, 100, + changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), 'd', i+1); + } + } // Settings.flag3.pwm_multi_channels } #endif #ifdef USE_SHUTTER if (Settings.flag3.shutter_mode) { for (uint32_t i = 0; i < shutters_present; i++) { - WSContentSend_P(HTTP_MSG_SLIDER3, Settings.shutter_position[i], i+1); + WSContentSend_P(HTTP_MSG_SLIDER2, F(D_CLOSE), F(D_OPEN), + 0, 100, Settings.shutter_position[i], 'u', i+1); } } #endif // USE_SHUTTER @@ -1097,6 +1085,7 @@ bool HandleRootStatusRefresh(void) char tmp[8]; // WebGetArg numbers only char svalue[32]; // Command and number parameter + char webindex[5]; // WebGetArg name WebGetArg("o", tmp, sizeof(tmp)); // 1 - 16 Device number for button Toggle or Fanspeed if (strlen(tmp)) { @@ -1122,13 +1111,21 @@ bool HandleRootStatusRefresh(void) snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } + uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + for (uint32_t j = 1; j <= pwm_channels; j++) { + snprintf_P(webindex, sizeof(webindex), PSTR("d%d"), j); + WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_CHANNEL "%d %s"), j, tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + } WebGetArg("t", tmp, sizeof(tmp)); // 153 - 500 Color temperature if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } #ifdef USE_SHUTTER - char webindex[5]; // WebGetArg name for (uint32_t j = 1; j <= shutters_present; j++) { snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j); WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent From e2a73f48ffe97920c254f2424b3e109342fcf546 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 15 Oct 2019 17:37:02 +0200 Subject: [PATCH 2129/2222] Tabs to spaces --- sonoff/xdrv_01_webserver.ino | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 936b46c28..009f0fa39 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -986,30 +986,30 @@ void HandleRoot(void) #ifdef USE_LIGHT if (light_type) { if (!Settings.flag3.pwm_multi_channels) { - if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { - // Cold - Warm &t related to lb("t", value) and WebGetArg("t", tmp, sizeof(tmp)); - WSContentSend_P(HTTP_MSG_SLIDER1, F(D_COLDLIGHT), F(D_WARMLIGHT), - 153, 500, LightGetColorTemp(), 't'); - } - // Dark - Bright &d related to lb("d", value) and WebGetArg("d", tmp, sizeof(tmp)); - WSContentSend_P(HTTP_MSG_SLIDER1, F(D_DARKLIGHT), F(D_BRIGHTLIGHT), - 1, 100, Settings.light_dimmer, 'd'); + if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { + // Cold - Warm &t related to lb("t", value) and WebGetArg("t", tmp, sizeof(tmp)); + WSContentSend_P(HTTP_MSG_SLIDER1, F(D_COLDLIGHT), F(D_WARMLIGHT), + 153, 500, LightGetColorTemp(), 't'); + } + // Dark - Bright &d related to lb("d", value) and WebGetArg("d", tmp, sizeof(tmp)); + WSContentSend_P(HTTP_MSG_SLIDER1, F(D_DARKLIGHT), F(D_BRIGHTLIGHT), + 1, 100, Settings.light_dimmer, 'd'); } else { // Settings.flag3.pwm_multi_channels - uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); - for (uint32_t i = 0; i < pwm_channels; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("c%d"), i); - WSContentSend_P(HTTP_MSG_SLIDER2, stemp, FPSTR("100%"), - 1, 100, - changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), 'd', i+1); - } - } // Settings.flag3.pwm_multi_channels + uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + for (uint32_t i = 0; i < pwm_channels; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("c%d"), i); + WSContentSend_P(HTTP_MSG_SLIDER2, stemp, FPSTR("100%"), + 1, 100, + changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), 'd', i+1); + } + } // Settings.flag3.pwm_multi_channels } #endif #ifdef USE_SHUTTER if (Settings.flag3.shutter_mode) { for (uint32_t i = 0; i < shutters_present; i++) { - WSContentSend_P(HTTP_MSG_SLIDER2, F(D_CLOSE), F(D_OPEN), - 0, 100, Settings.shutter_position[i], 'u', i+1); + WSContentSend_P(HTTP_MSG_SLIDER2, F(D_CLOSE), F(D_OPEN), + 0, 100, Settings.shutter_position[i], 'u', i+1); } } #endif // USE_SHUTTER From 1be3a43f6e0a0d89dc051c62a87fb22b07a7bd74 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Tue, 15 Oct 2019 19:49:33 +0200 Subject: [PATCH 2130/2222] Fix line used for tagging during custom builds I'm starting to use lines with `--` in them to identify different portions of the my_user_config.h to determine which directives are mandatory to make a build possible and those that may be commented out without impacting on a compile. This is useful for automation of custom builds wherein the my_user_config.h file is loaded, edited according to requirements, and rewritten by means of a program or script. I'm guessing this particular line is an exception by mistake so this PR just brings this particular line in check with the others that look the same or follow the same convention of `-- FUNCTIONAL DESCRIPTION ---------------` --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 5cb920bee..62d166afc 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -440,7 +440,7 @@ //#define USE_RDM6300 // Add support for RDM6300 125kHz RFID Reader (+0k8) //#define USE_IBEACON // Add support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) -// Power monitoring sensors ----------------------- +// -- Power monitoring sensors -------------------- #define USE_ENERGY_MARGIN_DETECTION // Add support for Energy Margin detection (+1k6 code) #define USE_ENERGY_POWER_LIMIT // Add additional support for Energy Power Limit detection (+1k2 code) #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) From 96b7ed8880f727fa886d9171ac0268c453e080dc Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Tue, 15 Oct 2019 20:00:57 +0200 Subject: [PATCH 2131/2222] Update my_user_config.h --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 62d166afc..9630da2f6 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -524,7 +524,7 @@ #define USE_ZIGBEE_PRECFGKEY_H 0x0D0C0A0806040200L // note: changing requires to re-pair all devices #define USE_ZIGBEE_PERMIT_JOIN false // don't allow joining by default -// ------------------------------------------------ +// -- Other sensors/drivers ----------------------- #define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) From 33d5304e5480f8061c64aa29833520e152adf11c Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Tue, 15 Oct 2019 20:03:13 +0200 Subject: [PATCH 2132/2222] Update my_user_config.h --- sonoff/my_user_config.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 9630da2f6..0c45cdde4 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -543,6 +543,8 @@ //#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) //#define USE_A4988_Stepper // Add support for A4988 stepper-motor-driver-circuit (+10k5 code) +// -- End of general directives ------------------- + /*********************************************************************************************\ * Debug features \*********************************************************************************************/ From 5903a2b9c552cf075c7d81b21ef9df2f848620a3 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 15 Oct 2019 20:07:12 +0200 Subject: [PATCH 2133/2222] scripter button events, remove comments on paste --- sonoff/xdrv_10_scripter.ino | 173 ++++++++++++++++++++++++++++++++++-- 1 file changed, 164 insertions(+), 9 deletions(-) diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index a43975abb..ef4175566 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -177,6 +177,10 @@ uint8_t fast_script=0; uint32_t script_lastmillis; +#ifdef USE_BUTTON_EVENT +int8_t script_button[MAX_KEYS]; +#endif + char *GetNumericResult(char *lp,uint8_t lastop,float *fp,JsonObject *jo); char *GetStringResult(char *lp,uint8_t lastop,char *cp,JsonObject *jo); char *ForceStringVar(char *lp,char *dstr); @@ -1062,6 +1066,17 @@ chknext: } goto exit; } +#ifdef USE_BUTTON_EVENT + if (!strncmp(vname,"bt[",3)) { + // tasmota button state + GetNumericResult(vname+3,OPER_EQU,&fvar,0); + uint32_t index=fvar; + if (index<1 || index>MAX_KEYS) index=1; + fvar=script_button[index-1]; + len++; + goto exit; + } +#endif break; case 'c': if (!strncmp(vname,"chg[",4)) { @@ -2122,7 +2137,20 @@ void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) { } } } else { - dstbuf[count]=*cp; + if (*cp=='\\') { + cp++; + if (*cp=='n') { + dstbuf[count]='\n'; + } else if (*cp=='r') { + dstbuf[count]='\r'; + } else if (*cp=='\\') { + dstbuf[count]='\\'; + } else { + dstbuf[count]=*cp; + } + } else { + dstbuf[count]=*cp; + } if (*cp==0) { break; } @@ -2970,22 +2998,80 @@ const char HTTP_FORM_SCRIPT1[] PROGMEM = "script enable
" "
" ""; const char HTTP_SCRIPT_FORM_END[] PROGMEM = @@ -3291,7 +3377,15 @@ void HandleScriptConfiguration(void) { WSContentStart_P(S_CONFIGURE_SCRIPT); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_SCRIPT); + + +#ifdef xSCRIPT_STRIP_COMMENTS + uint16_t ssize=glob_script_mem.script_size; + if (bitRead(Settings.rule_enabled, 1)) ssize*=2; + WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",ssize); +#else WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",glob_script_mem.script_size); +#endif // script is to larg for WSContentSend_P if (glob_script_mem.script_ram[0]) { @@ -3329,6 +3423,38 @@ void ScriptSaveSettings(void) { str.replace("\r\n","\n"); str.replace("\r","\n"); +#ifdef xSCRIPT_STRIP_COMMENTS + if (bitRead(Settings.rule_enabled, 1)) { + char *sp=(char*)str.c_str(); + char *sp1=sp; + char *dp=sp; + uint8_t flg=0; + while (*sp) { + while (*sp==' ') sp++; + sp1=sp; + sp=strchr(sp,'\n'); + if (!sp) { + flg=1; + } else { + *sp=0; + } + if (*sp1!=';') { + uint8_t slen=strlen(sp1); + if (slen) { + strcpy(dp,sp1); + dp+=slen; + *dp++='\n'; + } + } + if (flg) { + *dp=0; + break; + } + sp++; + } + } +#endif + strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size); #ifdef USE_24C256 @@ -3923,11 +4049,20 @@ bool ScriptCommand(void) { } else if ((CMND_SCRIPT == command_code) && (index > 0)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 2)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { switch (XdrvMailbox.payload) { case 0: // Off case 1: // On - bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload); + bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload); + break; +#ifdef xSCRIPT_STRIP_COMMENTS + case 2: + bitWrite(Settings.rule_enabled, 1,0); + break; + case 3: + bitWrite(Settings.rule_enabled, 1,1); + break; +#endif } } else { if ('>' == XdrvMailbox.data[0]) { @@ -4519,6 +4654,12 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_pram=(uint8_t*)Settings.mems[0]; glob_script_mem.script_pram_size=MAX_RULE_MEMS*10; +#ifdef USE_BUTTON_EVENT + for (uint32_t cnt=0;cntb",2,0); + } + } + break; +#endif } return result; } + + #endif // Do not USE_RULES #endif // USE_SCRIPT From d9407e3374a885918597970b8f7d7fd3af7afa1f Mon Sep 17 00:00:00 2001 From: Michael Ingraham <34340210+meingraham@users.noreply.github.com> Date: Tue, 15 Oct 2019 14:24:06 -0400 Subject: [PATCH 2134/2222] Uppercase USE_A4988_STEPPER --- sonoff/xdrv_25_A4988_Stepper.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_25_A4988_Stepper.ino b/sonoff/xdrv_25_A4988_Stepper.ino index f80cc1a81..99bcde51b 100644 --- a/sonoff/xdrv_25_A4988_Stepper.ino +++ b/sonoff/xdrv_25_A4988_Stepper.ino @@ -18,7 +18,7 @@ along with this program. If not, see . */ -#ifdef USE_A4988_Stepper +#ifdef USE_A4988_STEPPER #include #define XDRV_25 25 From 7e33dfb18b82903b653032e1e009687131f6d304 Mon Sep 17 00:00:00 2001 From: Michael Ingraham <34340210+meingraham@users.noreply.github.com> Date: Tue, 15 Oct 2019 14:28:09 -0400 Subject: [PATCH 2135/2222] Uppercase USE_A4988_STEPPER --- sonoff/sonoff_post.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index c25b961c3..aea346dba 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -268,7 +268,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) -#undef USE_A4988_Stepper // Disable support for A4988_Stepper +#undef USE_A4988_STEPPER // Disable support for A4988_Stepper #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_CLASSIC From f458e3ac36c6cf5f7765021e0d3f7b44db2ffcc1 Mon Sep 17 00:00:00 2001 From: Michael Ingraham <34340210+meingraham@users.noreply.github.com> Date: Tue, 15 Oct 2019 14:30:04 -0400 Subject: [PATCH 2136/2222] Uppercase USE_A4988_STEPPER --- sonoff/support_features.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 0589433f7..07a70ab17 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -444,7 +444,7 @@ void GetFeatures(void) #ifdef USE_INA226 feature5 |= 0x00000010; // xsns_54_ina226.ino #endif -#ifdef USE_A4988_Stepper +#ifdef USE_A4988_STEPPER feature5 |= 0x00000020; // xdrv_25_A4988.ino #endif #ifdef USE_DDS2382 From 08ccf63a37bf2788f7f0917d6984587d0b638c04 Mon Sep 17 00:00:00 2001 From: Michael Ingraham <34340210+meingraham@users.noreply.github.com> Date: Tue, 15 Oct 2019 14:31:10 -0400 Subject: [PATCH 2137/2222] Uppercase USE_A4988_STEPPER --- tools/decode-status.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/decode-status.py b/tools/decode-status.py index 92437b864..39e2b96e3 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -170,7 +170,7 @@ a_features = [[ "USE_MAX31865","USE_CHIRP","USE_SOLAX_X1","USE_PAJ7620" ],[ "USE_BUZZER","USE_RDM6300","USE_IBEACON","USE_SML_M", - "USE_INA226","USE_A4988_Stepper","USE_DDS2382","USE_SM2135", + "USE_INA226","USE_A4988_STEPPER","USE_DDS2382","USE_SM2135", "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", "USE_SONOFF_SC","USE_SONOFF_RF","","", "","","","", From 67e96e761d9ccb5afaf0f18fe7110fbcf78d7cb0 Mon Sep 17 00:00:00 2001 From: Michael Ingraham <34340210+meingraham@users.noreply.github.com> Date: Tue, 15 Oct 2019 14:32:00 -0400 Subject: [PATCH 2138/2222] Uppercase USE_A4988_STEPPER --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 5cb920bee..ccd93af71 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -541,7 +541,7 @@ // #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver (+1k7 code) //#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) -//#define USE_A4988_Stepper // Add support for A4988 stepper-motor-driver-circuit (+10k5 code) +//#define USE_A4988_STEPPER // Add support for A4988 stepper-motor-driver-circuit (+10k5 code) /*********************************************************************************************\ * Debug features From 0b3e41d2765ccde6405f3171f42afe4dfe04151a Mon Sep 17 00:00:00 2001 From: Michael Ingraham <34340210+meingraham@users.noreply.github.com> Date: Tue, 15 Oct 2019 14:33:37 -0400 Subject: [PATCH 2139/2222] Uppercase USE_A4988_STEPPER --- sonoff/i18n.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index cee36cd89..96f4db54e 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -473,7 +473,7 @@ #define D_CMND_ZIGBEE_PROBE "ZigbeeProbe" // Commands xdrv_25_A4988_Stepper.ino - #ifdef USE_A4988_Stepper + #ifdef USE_A4988_STEPPER #define D_CMND_MOTOR "MOTOR" #define D_JSON_MOTOR_MOVE "doMove" #define D_JSON_MOTOR_ROTATE "doRotate" From a5683156ce1b0678e31b8be1a0e768d2596c78eb Mon Sep 17 00:00:00 2001 From: Michael Ingraham <34340210+meingraham@users.noreply.github.com> Date: Tue, 15 Oct 2019 14:34:35 -0400 Subject: [PATCH 2140/2222] Uppercase USE_A4988_STEPPER --- sonoff/sonoff_template.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 3061ae366..0af77e6b3 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -731,7 +731,7 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_HRE_CLOCK, GPIO_HRE_DATA, #endif -#ifdef USE_A4988_Stepper +#ifdef USE_A4988_STEPPER GPIO_A4988_DIR, // A4988 direction pin GPIO_A4988_STP, // A4988 step pin // folowing are not mandatory From 4840861ced8b4bbe6af38d83755004dd8ca28e7a Mon Sep 17 00:00:00 2001 From: andrethomas2 <43345003+andrethomas2@users.noreply.github.com> Date: Tue, 15 Oct 2019 20:49:02 +0200 Subject: [PATCH 2141/2222] Include mention of DRV8825 --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index ccd93af71..49fd91dc7 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -541,7 +541,7 @@ // #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver (+1k7 code) //#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) -//#define USE_A4988_STEPPER // Add support for A4988 stepper-motor-driver-circuit (+10k5 code) +//#define USE_A4988_STEPPER // Add support for A4988/DRV8825 stepper-motor-driver-circuit (+10k5 code) /*********************************************************************************************\ * Debug features From f6ed6edd75abb9689352dccb7399a05c2e862863 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 16 Oct 2019 05:33:22 +0200 Subject: [PATCH 2142/2222] scripter better button event --- sonoff/xdrv_10_scripter.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index ef4175566..ee78cc740 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -1073,6 +1073,7 @@ chknext: uint32_t index=fvar; if (index<1 || index>MAX_KEYS) index=1; fvar=script_button[index-1]; + script_button[index-1]|=0x80; len++; goto exit; } @@ -4794,7 +4795,7 @@ bool Xdrv10(uint8_t function) #ifdef USE_BUTTON_EVENT case FUNC_BUTTON_PRESSED: if (bitRead(Settings.rule_enabled, 0)) { - if (script_button[XdrvMailbox.index]!=XdrvMailbox.payload) { + if ((script_button[XdrvMailbox.index]&1)!=(XdrvMailbox.payload&1)) { script_button[XdrvMailbox.index]=XdrvMailbox.payload; Run_Scripter(">b",2,0); } From ee8bb3452bf0476ea7838c86cdc077aa603cc849 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 16 Oct 2019 11:09:48 +0200 Subject: [PATCH 2143/2222] (Try to) fix EnergyReset (Try to) fix EnergyReset (#6561) --- sonoff/xdrv_03_energy.ino | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index af51682a5..fbc7881b3 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -204,7 +204,7 @@ void EnergyUpdateTotal(float value, bool kwh) Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: Energy Total updated with hardware value")); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: Energy Total updated with hardware value")); } EnergyUpdateToday(); } @@ -499,6 +499,7 @@ void CmndEnergyReset(void) Energy.kWhtoday_offset = lnum *100; Energy.kWhtoday = 0; Energy.kWhtoday_delta = 0; + Energy.start_energy = 0; Energy.period = Energy.kWhtoday_offset; Settings.energy_kWhtoday = Energy.kWhtoday_offset; RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset; @@ -515,15 +516,14 @@ void CmndEnergyReset(void) // Reset Energy Total RtcSettings.energy_kWhtotal = lnum *100; Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; +// Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 1000); break; } } } - - if ((XdrvMailbox.index > 3) && (XdrvMailbox.index <= 5)) { + else if ((XdrvMailbox.index > 3) && (XdrvMailbox.index <= 5)) { char *p; char *str = strtok_r(XdrvMailbox.data, ", ", &p); int32_t position = -1; @@ -559,13 +559,12 @@ void CmndEnergyReset(void) } Settings.energy_usage.return1_kWhtotal = RtcSettings.energy_usage.return1_kWhtotal; Settings.energy_usage.return2_kWhtotal = RtcSettings.energy_usage.return2_kWhtotal; - - - break; } } + Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; + char energy_total_chr[FLOATSZ]; dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr); char energy_daily_chr[FLOATSZ]; From fb428a9c7dfdf087ad2d116c8800d6cc3e03e57d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 16 Oct 2019 11:51:38 +0200 Subject: [PATCH 2144/2222] Remove default DS18B20 driver Remove default DS18B20 driver and only support define DS18x20 (#6647) --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 2 +- sonoff/sonoff_post.h | 18 +-- sonoff/sonoff_template.h | 6 +- sonoff/support_features.ino | 4 +- sonoff/xsns_05_ds18b20.ino | 253 ------------------------------------ 6 files changed, 12 insertions(+), 272 deletions(-) delete mode 100644 sonoff/xsns_05_ds18b20.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 882d09787..83caab8c4 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -9,6 +9,7 @@ * Add rule support after every command execution like Fanspeed#Data=2 (#6636) * Fix handling of ligth channels when pwm_multichannel (Option68) is enabled * Add WebUI for multiple, independent PWM channels + * Remove default DS18B20 driver and only support define DS18x20 (#6647) * * 6.6.0.17 20191009 * Add command SetOption34 0..255 to set backlog delay. Default value is 200 (mSeconds) (#6562) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index a046d92f5..99cd318ba 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -338,7 +338,7 @@ //#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices // -- One wire sensors ---------------------------- -#define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) +#define USE_DS18x20 // Add support for DS18x20 sensors with id sort, single scan and read retry (+2k6 code) // #define W1_PARASITE_POWER // Optimize for parasite powered sensors // #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistor diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index aea346dba..43ee45ea4 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -97,7 +97,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_COUNTER // Enable counters #undef USE_ADC_VCC // Add Analog input on selected devices -#define USE_DS18x20 // For more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) +#define USE_DS18x20 // Add support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) #define USE_SHT // Add I2C emulating code for SHT1X sensor (+1k4 code) @@ -364,7 +364,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_TUYA_MCU // Disable support for Tuya Serial MCU #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) -#undef USE_DS18x20 // Disable Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) +#undef USE_DS18x20 // Disable support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) #undef USE_I2C // Disable all I2C sensors #undef USE_SPI // Disable all SPI devices @@ -414,15 +414,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif // FIRMWARE_IR -/*********************************************************************************************\ - * Mandatory define for DS18x20 if changed by above image selections -\*********************************************************************************************/ - -#if defined(USE_DS18x20) -#else -#define USE_DS18B20 // Default DS18B20 sensor needs no external library -#endif - /*********************************************************************************************\ * [sonoff-basic.bin] * Provide an image without sensors @@ -464,7 +455,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_COUNTER // Disable counters #undef USE_DS18x20 // Disable DS18x20 sensor -#undef USE_DS18B20 // Disable internal DS18B20 sensor #undef USE_I2C // Disable all I2C sensors and devices #undef USE_SPI // Disable all SPI devices #undef USE_DISPLAY // Disable Display support @@ -549,7 +539,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_COUNTER // Disable counters #undef USE_DS18x20 // Disable DS18x20 sensor -#undef USE_DS18B20 // Disable internal DS18B20 sensor #undef USE_I2C // Disable all I2C sensors and devices #undef USE_SPI // Disable all SPI devices #undef USE_DISPLAY // Disable Display support @@ -637,9 +626,8 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif #ifndef MESSZ -//#define MESSZ 405 // Max number of characters in JSON message string (6 x DS18x20 sensors) //#define MESSZ 893 // Max number of characters in JSON message string (Hass discovery and nice MQTT_MAX_PACKET_SIZE = 1000) -#define MESSZ (MQTT_MAX_PACKET_SIZE -TOPSZ -7) // Max number of characters in JSON message string (6 x DS18x20 sensors) +#define MESSZ (MQTT_MAX_PACKET_SIZE -TOPSZ -7) // Max number of characters in JSON message string #endif //#include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 0af77e6b3..76f5cb8d4 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -543,7 +543,7 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_DHT22, // DHT21, DHT22, AM2301, AM2302, AM2321 GPIO_SI7021, // iTead SI7021 #endif -#if defined(USE_DS18B20) || defined(USE_DS18x20) +#ifdef USE_DS18x20 GPIO_DSB, // Single wire DS18B20 or DS18S20 #endif @@ -1363,7 +1363,11 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { // http://www.wykop.pl/ramka/3325399/diy-supla-do-puszki-instalacyjnej-podtynkowej-supla-org/ 0, // GPIO00 Flash jumper GPIO_USER, // GPIO01 Serial RXD and Optional sensor +#ifdef USE_DS18x20 GPIO_DSB, // GPIO02 DS18B20 sensor +#else + GPIO_USER, // GPIO02 Optional sensor +#endif GPIO_USER, // GPIO03 Serial TXD and Optional sensor GPIO_KEY1, // GPIO04 Button 1 GPIO_REL1, // GPIO05 Relay 1 (0 = Off, 1 = On) diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 07a70ab17..cf0740e72 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -240,10 +240,10 @@ void GetFeatures(void) feature_sns1 |= 0x00000008; // xnrg_03_pzem004t.ino #endif #ifdef USE_DS18B20 - feature_sns1 |= 0x00000010; // xsns_05_ds18b20.ino + feature_sns1 |= 0x00000010; // xsns_05_ds18b20.ino - no more support since 6.6.0.18 #endif #ifdef USE_DS18x20_LEGACY - feature_sns1 |= 0x00000020; // xsns_05_ds18x20_legacy.ino - no more supported since 6.6.0.14 + feature_sns1 |= 0x00000020; // xsns_05_ds18x20_legacy.ino - no more support since 6.6.0.14 #endif #ifdef USE_DS18x20 feature_sns1 |= 0x00000040; // xsns_05_ds18x20.ino diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino deleted file mode 100644 index a0a05a44a..000000000 --- a/sonoff/xsns_05_ds18b20.ino +++ /dev/null @@ -1,253 +0,0 @@ -/* - xsns_05_ds18b20.ino - DS18B20 temperature sensor support for Sonoff-Tasmota - - Copyright (C) 2019 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_DS18B20 -/*********************************************************************************************\ - * DS18B20 - Temperature - Single sensor -\*********************************************************************************************/ - -#define XSNS_05 5 - -#define W1_SKIP_ROM 0xCC -#define W1_CONVERT_TEMP 0x44 -#define W1_READ_SCRATCHPAD 0xBE - -float ds18b20_temperature = 0; -uint8_t ds18b20_valid = 0; -uint8_t ds18x20_pin = 0; -char ds18b20_types[] = "DS18B20"; - -/*********************************************************************************************\ - * Embedded stripped and tuned OneWire library -\*********************************************************************************************/ - -uint8_t OneWireReset(void) -{ - uint8_t retries = 125; - - //noInterrupts(); -#ifdef DS18B20_INTERNAL_PULLUP - pinMode(ds18x20_pin, INPUT_PULLUP); -#else - pinMode(ds18x20_pin, INPUT); -#endif - do { - if (--retries == 0) { - return 0; - } - delayMicroseconds(2); - } while (!digitalRead(ds18x20_pin)); - pinMode(ds18x20_pin, OUTPUT); - digitalWrite(ds18x20_pin, LOW); - delayMicroseconds(480); -#ifdef DS18B20_INTERNAL_PULLUP - pinMode(ds18x20_pin, INPUT_PULLUP); -#else - pinMode(ds18x20_pin, INPUT); -#endif - delayMicroseconds(70); - uint8_t r = !digitalRead(ds18x20_pin); - //interrupts(); - delayMicroseconds(410); - return r; -} - -void OneWireWriteBit(uint8_t v) -{ - static const uint8_t delay_low[2] = { 65, 10 }; - static const uint8_t delay_high[2] = { 5, 55 }; - - v &= 1; - //noInterrupts(); - digitalWrite(ds18x20_pin, LOW); - pinMode(ds18x20_pin, OUTPUT); - delayMicroseconds(delay_low[v]); - digitalWrite(ds18x20_pin, HIGH); - //interrupts(); - delayMicroseconds(delay_high[v]); -} - -uint8_t OneWireReadBit(void) -{ - //noInterrupts(); - pinMode(ds18x20_pin, OUTPUT); - digitalWrite(ds18x20_pin, LOW); - delayMicroseconds(3); -#ifdef DS18B20_INTERNAL_PULLUP - pinMode(ds18x20_pin, INPUT_PULLUP); -#else - pinMode(ds18x20_pin, INPUT); -#endif - delayMicroseconds(10); - uint8_t r = digitalRead(ds18x20_pin); - //interrupts(); - delayMicroseconds(53); - return r; -} - -void OneWireWrite(uint8_t v) -{ - for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { - OneWireWriteBit((bit_mask & v) ? 1 : 0); - } -} - -uint8_t OneWireRead(void) -{ - uint8_t r = 0; - - for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { - if (OneWireReadBit()) { - r |= bit_mask; - } - } - return r; -} - -bool OneWireCrc8(uint8_t *addr) -{ - uint8_t crc = 0; - uint8_t len = 8; - - while (len--) { - uint8_t inbyte = *addr++; // from 0 to 7 - for (uint32_t i = 8; i; i--) { - uint8_t mix = (crc ^ inbyte) & 0x01; - crc >>= 1; - if (mix) { - crc ^= 0x8C; - } - inbyte >>= 1; - } - } - return (crc == *addr); // addr 8 -} - -/********************************************************************************************/ - -void Ds18b20Convert(void) -{ - OneWireReset(); - OneWireWrite(W1_SKIP_ROM); // Address all Sensors on Bus - OneWireWrite(W1_CONVERT_TEMP); // start conversion, no parasite power on at the end -// delay(750); // 750ms should be enough for 12bit conv -} - -bool Ds18b20Read(void) -{ - uint8_t data[9]; - int8_t sign = 1; - - if (ds18b20_valid) { ds18b20_valid--; } -/* - if (!OneWireReadBit()) { // Check end of measurement - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_BUSY)); - return; - } -*/ - for (uint32_t retry = 0; retry < 3; retry++) { - OneWireReset(); - OneWireWrite(W1_SKIP_ROM); - OneWireWrite(W1_READ_SCRATCHPAD); - for (uint32_t i = 0; i < 9; i++) { - data[i] = OneWireRead(); - } - if (OneWireCrc8(data)) { - uint16_t temp12 = (data[1] << 8) + data[0]; - if (temp12 > 2047) { - temp12 = (~temp12) +1; - sign = -1; - } - ds18b20_temperature = ConvertTemp(sign * temp12 * 0.0625); - ds18b20_valid = SENSOR_MAX_MISS; - return true; - } - } - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); - return false; -} - -/********************************************************************************************/ - -void Ds18b20EverySecond(void) -{ - ds18x20_pin = pin[GPIO_DSB]; - if (uptime &1) { - // 2mS - Ds18b20Convert(); // Start conversion, takes up to one second - } else { - // 12mS - if (!Ds18b20Read()) { // Read temperature - AddLogMissed(ds18b20_types, ds18b20_valid); - } - } -} - -void Ds18b20Show(bool json) -{ - if (ds18b20_valid) { // Check for valid temperature - char temperature[33]; - dtostrfd(ds18b20_temperature, Settings.flag2.temperature_resolution, temperature); - if(json) { - ResponseAppend_P(JSON_SNS_TEMP, ds18b20_types, temperature); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif // USE_DOMOTICZ -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, ds18b20_temperature); - } -#endif // USE_KNX -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, ds18b20_types, temperature, TempUnit()); -#endif // USE_WEBSERVER - } - } -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xsns05(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_DSB] < 99) { - switch (function) { - case FUNC_EVERY_SECOND: - Ds18b20EverySecond(); - break; - case FUNC_JSON_APPEND: - Ds18b20Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ds18b20Show(0); - break; -#endif // USE_WEBSERVER - } - } - return result; -} - -#endif // USE_DS18B20 From 81d3a09aeeb4de87cbc2c9f3b67ab061e74bca1d Mon Sep 17 00:00:00 2001 From: Vasco Baptista Date: Wed, 16 Oct 2019 12:10:48 +0200 Subject: [PATCH 2145/2222] Added support for PMS3003 Added support to PMS3003 to the already existing PMS5003-7003 driver. Support is changed from PMS5003-7003 to PMS3003 by enabling the PMS_MODEL_PMS3003 define. --- sonoff/my_user_config.h | 1 + sonoff/sonoff_post.h | 1 + sonoff/xsns_18_pms5003.ino | 72 ++++++++++++++++++++++++++++++++++---- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index a046d92f5..fcd2cccba 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -427,6 +427,7 @@ #define CO2_LOW 800 // Below this CO2 value show green light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) + //#define PMS_MODEL_PMS3003 // Enable support of PMS3003 instead of PMS5003/PMS7003 (needs the USE_PMS5003 above) #define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) #define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index aea346dba..5d69e7a23 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -147,6 +147,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #endif #define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) + //#define PMS_MODEL_PMS3003 // Enable support of PMS3003 instead of PMS5003/PMS7003 (needs the USE_PMS5003 above) #define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) //#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) diff --git a/sonoff/xsns_18_pms5003.ino b/sonoff/xsns_18_pms5003.ino index ee14f9348..78c6ab05a 100644 --- a/sonoff/xsns_18_pms5003.ino +++ b/sonoff/xsns_18_pms5003.ino @@ -1,5 +1,5 @@ /* - xsns_18_pms5003.ino - PMS5003-7003 particle concentration sensor support for Sonoff-Tasmota + xsns_18_pms5003.ino - PMS3003, PMS5003, PMS7003 particle concentration sensor support for Sonoff-Tasmota Copyright (C) 2019 Theo Arends @@ -19,10 +19,13 @@ #ifdef USE_PMS5003 /*********************************************************************************************\ - * PlanTower PMS5003 and PMS7003 particle concentration sensor - * For background information see http://aqicn.org/sensor/pms5003-7003/ + * PlanTower PMS3003, PMS5003, PMS7003 particle concentration sensor + * For background information see http://aqicn.org/sensor/pms5003-7003/ or + * http://aqicn.org/sensor/pms3003/ * * Hardware Serial will be selected if GPIO3 = [PMS5003] + * You can either support PMS3003 or PMS5003-7003 at one time. To enable the PMS3003 support + * you must enable the define PMS_MODEL_PMS3003 on your configuration file. \*********************************************************************************************/ #define XSNS_18 18 @@ -34,12 +37,16 @@ TasmotaSerial *PmsSerial; uint8_t pms_type = 1; uint8_t pms_valid = 0; -struct pms5003data { +struct pmsX003data { uint16_t framelen; uint16_t pm10_standard, pm25_standard, pm100_standard; uint16_t pm10_env, pm25_env, pm100_env; +#ifdef PMS_MODEL_PMS3003 + uint16_t reserved1, reserved2, reserved3; +#else uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um; uint16_t unused; +#endif // PMS_MODEL_PMS3003 uint16_t checksum; } pms_data; @@ -53,33 +60,63 @@ bool PmsReadData(void) while ((PmsSerial->peek() != 0x42) && PmsSerial->available()) { PmsSerial->read(); } +#ifdef PMS_MODEL_PMS3003 + if (PmsSerial->available() < 22) { +#else if (PmsSerial->available() < 32) { +#endif // PMS_MODEL_PMS3003 return false; } +#ifdef PMS_MODEL_PMS3003 + uint8_t buffer[22]; + PmsSerial->readBytes(buffer, 22); +#else uint8_t buffer[32]; - uint16_t sum = 0; PmsSerial->readBytes(buffer, 32); +#endif // PMS_MODEL_PMS3003 + uint16_t sum = 0; PmsSerial->flush(); // Make room for another burst +#ifdef PMS_MODEL_PMS3003 + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 22); +#else AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 32); +#endif // PMS_MODEL_PMS3003 // get checksum ready +#ifdef PMS_MODEL_PMS3003 + for (uint32_t i = 0; i < 20; i++) { +#else for (uint32_t i = 0; i < 30; i++) { +#endif // PMS_MODEL_PMS3003 sum += buffer[i]; } // The data comes in endian'd, this solves it so it works on all platforms +#ifdef PMS_MODEL_PMS3003 + uint16_t buffer_u16[10]; + for (uint32_t i = 0; i < 10; i++) { +#else uint16_t buffer_u16[15]; for (uint32_t i = 0; i < 15; i++) { +#endif // PMS_MODEL_PMS3003 buffer_u16[i] = buffer[2 + i*2 + 1]; buffer_u16[i] += (buffer[2 + i*2] << 8); } +#ifdef PMS_MODEL_PMS3003 + if (sum != buffer_u16[9]) { +#else if (sum != buffer_u16[14]) { +#endif // PMS_MODEL_PMS3003 AddLog_P(LOG_LEVEL_DEBUG, PSTR("PMS: " D_CHECKSUM_FAILURE)); return false; } +#ifdef PMS_MODEL_PMS3003 + memcpy((void *)&pms_data, (void *)buffer_u16, 20); +#else memcpy((void *)&pms_data, (void *)buffer_u16, 30); +#endif // PMS_MODEL_PMS3003 pms_valid = 10; return true; @@ -113,6 +150,15 @@ void PmsInit(void) } #ifdef USE_WEBSERVER +#ifdef PMS_MODEL_PMS3003 +const char HTTP_PMS3003_SNS[] PROGMEM = +// "{s}PMS3003 " D_STANDARD_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" +// "{s}PMS3003 " D_STANDARD_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" +// "{s}PMS3003 " D_STANDARD_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; +#else const char HTTP_PMS5003_SNS[] PROGMEM = // "{s}PMS5003 " D_STANDARD_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" // "{s}PMS5003 " D_STANDARD_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" @@ -126,16 +172,23 @@ const char HTTP_PMS5003_SNS[] PROGMEM = "{s}PMS5003 " D_PARTICALS_BEYOND " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" "{s}PMS5003 " D_PARTICALS_BEYOND " 5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" "{s}PMS5003 " D_PARTICALS_BEYOND " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"; // {s} = , {m} = , {e} = +#endif // PMS_MODEL_PMS3003 #endif // USE_WEBSERVER void PmsShow(bool json) { if (pms_valid) { if (json) { +#ifdef PMS_MODEL_PMS3003 + ResponseAppend_P(PSTR(",\"PMS3003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d}"), + pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env); +#else ResponseAppend_P(PSTR(",\"PMS5003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d,\"PB0.3\":%d,\"PB0.5\":%d,\"PB1\":%d,\"PB2.5\":%d,\"PB5\":%d,\"PB10\":%d}"), pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); +#endif // PMS_MODEL_PMS3003 #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_COUNT, pms_data.pm10_env); // PM1 @@ -145,10 +198,17 @@ void PmsShow(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - WSContentSend_PD(HTTP_PMS5003_SNS, + +#ifdef PMS_MODEL_PMS3003 + WSContentSend_PD(HTTP_PMS3003_SNS, +// pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env); +#else + WSContentSend_PD(HTTP_PMS5003_SNS, // pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); +#endif // PMS_MODEL_PMS3003 #endif // USE_WEBSERVER } } From 14be94ae1e6fc2a704aba1c1d98458d56f1f8207 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Tue, 15 Oct 2019 13:32:57 +0100 Subject: [PATCH 2146/2222] Travis: Upgrade cached Platformio and platforms to latest --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 09cfd0123..491f37bd6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ python: sudo: false install: - pip install -U platformio + - platformio upgrade + - platformio update cache: directories: From bbab803985c433020fb48839aef7e1bfaef86d7f Mon Sep 17 00:00:00 2001 From: Vasco Baptista Date: Wed, 16 Oct 2019 12:38:56 +0200 Subject: [PATCH 2147/2222] Added PMS3003 support Added PMS3003 support on documentation (forgot on the first commit) --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 83caab8c4..7c3307cdb 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -10,6 +10,7 @@ * Fix handling of ligth channels when pwm_multichannel (Option68) is enabled * Add WebUI for multiple, independent PWM channels * Remove default DS18B20 driver and only support define DS18x20 (#6647) + * Add support for PMS3003 dust particle sensor * * 6.6.0.17 20191009 * Add command SetOption34 0..255 to set backlog delay. Default value is 200 (mSeconds) (#6562) From a4452b9ffbeb0d9c4455c6830d71fc726d2d4ae9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 16 Oct 2019 14:04:01 +0200 Subject: [PATCH 2148/2222] Fix possible KNX compilation error --- sonoff/xdrv_11_knx.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 94b320c86..6fa6231c0 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -492,7 +492,9 @@ void KNX_INIT(void) if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } +#ifdef USE_DS18x20 if (GetUsedInModule(GPIO_DSB, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } +#endif if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } From f6de8bc5a08add4cffffa15094d2ca1d2a32cdc1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 16 Oct 2019 14:33:25 +0200 Subject: [PATCH 2149/2222] Tune default defines Tune default defines (#6662) --- sonoff/sonoff_post.h | 72 ++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index e6ef18998..6ac4a6ac1 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -222,15 +222,21 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_RULES // Disable support for rules // -- Optional modules ------------------------- -//#ifndef USE_SONOFF_IFAN -#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) -//#endif +#undef ROTARY_V1 // Disable support for MI Desk Lamp +#define USE_SONOFF_RF // Add support for Sonoff Rf Bridge (+3k2 code) + #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#define USE_SONOFF_SC // Add support for Sonoff Sc (+1k1 code) #undef USE_TUYA_MCU // Disable support for Tuya Serial MCU #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) -#undef ROTARY_V1 // Disable support for MI Desk Lamp +#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) +#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) +#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller +#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) +#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) #undef USE_COUNTER // Disable counters +#define USE_DS18x20 // Add support for DS18x20 sensors with id sort, single scan and read retry (+2k6 code) #undef USE_I2C // Disable all I2C sensors #undef USE_SPI // Disable all SPI devices #undef USE_MHZ19 // Disable support for MH-Z19 CO2 sensor @@ -259,11 +265,9 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI #undef USE_IR_REMOTE // Disable IR remote commands using library IRremoteESP8266 and ArduinoJson #undef USE_IR_RECEIVE // Disable support for IR receiver -#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell -#undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) @@ -300,6 +304,19 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef CODE_IMAGE #define CODE_IMAGE 6 +#undef ROTARY_V1 // Disable support for MI Desk Lamp +#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) + #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) +//#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU +#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) +#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) +#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) +#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) +#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller +#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) +#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) + #undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) #undef USE_PZEM004T // Disable PZEM004T energy sensor #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor @@ -331,8 +348,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c // #define USE_DISPLAY_RA8876 // [DisplayModel 10] #endif -#undef USE_ARILUX_RF // Remove support for Arilux RF remote controller (-0k8 code, 252 iram (non 2.3.0)) -#undef USE_RF_FLASH // Remove support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (-3k code) #endif // FIRMWARE_DISPLAYS /*********************************************************************************************\ @@ -359,12 +374,19 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c //#undef USE_RULES // Disable support for rules #undef USE_DISCOVERY // Disable mDNS for the following services (+8k code or +23.5k code with core 2_5_x, +0.3k mem) -// -- Optional modules ------------------------- -#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) -#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) +#undef ROTARY_V1 // Disable support for MI Desk Lamp +#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) + #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) #undef USE_TUYA_MCU // Disable support for Tuya Serial MCU #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) +#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) +#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) +#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller +#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) +#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) + #undef USE_DS18x20 // Disable support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) #undef USE_I2C // Disable all I2C sensors @@ -448,11 +470,18 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c //#undef USE_RULES // Disable support for rules // -- Optional modules ------------------------- -#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) -//#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU +#undef ROTARY_V1 // Disable support for MI Desk Lamp +#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) + #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) +//#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) -#undef ROTARY_V1 // Disable support for MI Desk Lamp +#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) +#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) +#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller +#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) +#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) #undef USE_COUNTER // Disable counters #undef USE_DS18x20 // Disable DS18x20 sensor @@ -485,11 +514,9 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI #undef USE_IR_REMOTE // Disable IR driver #undef USE_WS2812 // Disable WS2812 Led string -#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell -#undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) @@ -532,11 +559,18 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_LIGHT // Disable support for lights // -- Optional modules ------------------------- -#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) +#undef ROTARY_V1 // Disable support for MI Desk Lamp +#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) + #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) #undef USE_TUYA_MCU // Disable support for Tuya Serial MCU #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) -#undef ROTARY_V1 // Disable support for MI Desk Lamp +#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) +#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) +#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller +#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) +#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) #undef USE_COUNTER // Disable counters #undef USE_DS18x20 // Disable DS18x20 sensor @@ -569,11 +603,9 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI #undef USE_IR_REMOTE // Disable IR driver #undef USE_WS2812 // Disable WS2812 Led string -#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell -#undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) From a3c0451e414c2bfd99e726210b0cf3ce164c145d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 16 Oct 2019 15:15:10 +0200 Subject: [PATCH 2150/2222] Remove support for core 2.5.2 Remove support for core 2.5.2 (#6664) --- platformio.ini | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/platformio.ini b/platformio.ini index 5b651c4f5..b8ad836e6 100755 --- a/platformio.ini +++ b/platformio.ini @@ -69,32 +69,6 @@ build_flags = ${esp82xx_defaults.build_flags} -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -DVTABLES_IN_FLASH -[core_2_5_2] -; *** Esp8266 core for Arduino version 2.5.2 -platform = espressif8266@~2.2.2 -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld -; Code optimization see https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473 - -O2 - -DBEARSSL_SSL_BASIC -; nonos-sdk 22x - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x -; nonos-sdk-pre-v3 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH - -DVTABLES_IN_FLASH - -fno-exceptions - -lstdc++ - [core_pre] ; *** Arduino Esp8266 core pre 2.6.x for Tasmota (mqtt reconnects fixed) platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota @@ -215,8 +189,6 @@ build_flags = ${esp82xx_defaults.build_flags} ;build_flags = ${core_2_3_0.build_flags} ;platform = ${core_2_4_2.platform} ;build_flags = ${core_2_4_2.build_flags} -;platform = ${core_2_5_2.platform} -;build_flags = ${core_2_5_2.build_flags} platform = ${core_pre.platform} build_flags = ${core_pre.build_flags} ;platform = ${core_pre_ipv6.platform} From 782563b3ae1301b91759bcdc8f7cfcea221f3be0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 16 Oct 2019 19:00:20 +0200 Subject: [PATCH 2151/2222] Add reset after four Quick Power Cycles Add reset after four Quick Power Cycles (#6639) --- sonoff/settings.ino | 35 +++++++++++++++++++++++++++++++++++ sonoff/sonoff.ino | 8 +++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 7109f20b1..4cb4e5b0d 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -360,6 +360,36 @@ void SettingsSaveAll(void) SettingsSave(0); } +/*********************************************************************************************\ + * Quick power cycle monitoring +\*********************************************************************************************/ + +void UpdateQuickPowerCycle(bool update) +{ + uint32_t pc_register; + uint32_t pc_location = SETTINGS_LOCATION - CFG_ROTATES; + + ESP.flashRead(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); + if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AB0)) { + uint32_t counter = ((pc_register & 0xF) << 1) & 0xF; + if (0 == counter) { // 4 power cycles in a row + SettingsErase(2); // Quickly reset all settings including QuickPowerCycle flag + EspRestart(); // And restart + } else { + pc_register = 0xFFA55AB0 | counter; + ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter); // Won't show as too early in power on sequence + } + } + else if (pc_register != 0xFFA55ABF) { + pc_register = 0xFFA55ABF; + // Assume flash is default all ones and setting a bit to zero does not need an erase + ESP.flashEraseSector(pc_location); + ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Reset")); // Won't show as too early in power on sequence + } +} + /*********************************************************************************************\ * Config Save - Save parameters to Flash ONLY if any parameter has changed \*********************************************************************************************/ @@ -486,6 +516,7 @@ void SettingsErase(uint8_t type) /* 0 = Erase from program end until end of physical flash 1 = Erase SDK parameter area at end of linker memory model (0x0FDxxx - 0x0FFFFF) solving possible wifi errors + 2 = Erase Tasmota settings */ #ifndef FIRMWARE_MINIMAL @@ -497,6 +528,10 @@ void SettingsErase(uint8_t type) _sectorStart = SETTINGS_LOCATION +2; // SDK parameter area above EEPROM area (0x0FDxxx - 0x0FFFFF) _sectorEnd = SETTINGS_LOCATION +5; } + else if (2 == type) { + _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; // Tasmota parameter area (0x0F4xxx - 0x0FBFFF) + _sectorEnd = SETTINGS_LOCATION +1; + } bool _serialoutput = (LOG_LEVEL_DEBUG_MORE <= seriallog_level); diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index f3bd8bed0..22fb2daf7 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -781,6 +781,7 @@ void PerformEverySecond(void) if (BOOT_LOOP_TIME == uptime) { RtcReboot.fast_reboot_count = 0; RtcRebootSave(); + UpdateQuickPowerCycle(false); Settings.bootcount++; // Moved to here to stop flash writes during start-up AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); @@ -1471,7 +1472,10 @@ void setup(void) global_state.data = 3; // Init global state (wifi_down, mqtt_down) to solve possible network issues RtcRebootLoad(); - if (!RtcRebootValid()) { RtcReboot.fast_reboot_count = 0; } + if (!RtcRebootValid()) { + RtcReboot.fast_reboot_count = 0; + UpdateQuickPowerCycle(true); // As RTC is invalid it must be a power cycle + } RtcReboot.fast_reboot_count++; RtcRebootSave(); @@ -1545,6 +1549,8 @@ void setup(void) } } +// UpdateQuickPowerCycle(true); // Test location + Format(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); Format(mqtt_topic, Settings.mqtt_topic, sizeof(mqtt_topic)); if (strstr(Settings.hostname, "%") != nullptr) { From 99901986a094617e0f2ddb0768f4b9432aad8f73 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Wed, 16 Oct 2019 18:38:41 -0300 Subject: [PATCH 2152/2222] Update PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index fb31333b5..53b64f906 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,6 +6,6 @@ - [ ] The pull request is done against the latest dev branch - [ ] Only relevant files were touched - [ ] Only one feature/fix was added per PR. - - [ ] The code change is tested and works on core 2.3.0, 2.4.2, 2.5.2, and pre-2.6 + - [ ] The code change is tested and works on core pre-2.6 - [ ] The code change pass travis tests. **Your PR cannot be merged unless tests pass** - [ ] I accept the [CLA](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla). From 60ffc96f151beda6416977f9122c38cbd9b68171 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 17 Oct 2019 10:30:43 +0200 Subject: [PATCH 2153/2222] Change PowerCycleTime form 10 to 8 seconds --- sonoff/sonoff.h | 1 + sonoff/sonoff.ino | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index c8c5a290d..c5e801564 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -110,6 +110,7 @@ const uint8_t MAX_POWER_RETRY = 5; // Retry count allowing agreed power const uint8_t STATES = 20; // Number of states per second using 50 mSec interval const uint8_t IMMINENT_RESET_FACTOR = 10; // Factor to extent button hold time for imminent Reset to default 40 seconds using KEY_HOLD_TIME of 40 const uint32_t BOOT_LOOP_TIME = 10; // Number of seconds to stop detecting boot loops +const uint32_t POWER_CYCLE_TIME = 8; // Number of seconds to reset power cycle boot loops const uint16_t SYSLOG_TIMER = 600; // Seconds to restore syslog_level const uint16_t SERIALLOG_TIMER = 600; // Seconds to disable SerialLog const uint8_t OTA_ATTEMPTS = 5; // Number of times to try fetching the new firmware diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 22fb2daf7..3e198737a 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -778,10 +778,13 @@ void PerformEverySecond(void) ntp_synced_message = false; } + if (POWER_CYCLE_TIME == uptime) { + UpdateQuickPowerCycle(false); + } + if (BOOT_LOOP_TIME == uptime) { RtcReboot.fast_reboot_count = 0; RtcRebootSave(); - UpdateQuickPowerCycle(false); Settings.bootcount++; // Moved to here to stop flash writes during start-up AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); From c10c057c9b726963029a5fff5a9679d2039a512c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 17 Oct 2019 10:45:51 +0200 Subject: [PATCH 2154/2222] Add max colors for color drivers --- sonoff/xdrv_04_light.ino | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 603e95f30..c4a4a2504 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -1679,15 +1679,19 @@ void LightAnimate(void) } } + // Some devices need scaled RGB like Sonoff L1 + uint8_t scale_col[3]; + uint32_t max = (cur_col[0] > cur_col[1] && cur_col[0] > cur_col[2]) ? cur_col[0] : (cur_col[1] > cur_col[2]) ? cur_col[1] : cur_col[2]; // 0..255 + for (uint32_t i = 0; i < 3; i++) { + scale_col[i] = (0 == max) ? 255 : (255 > max) ? changeUIntScale(cur_col[i], 0, max, 0, 255) : cur_col[i]; + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: R%d(%d) G%d(%d) B%d(%d), C%d W%d, D%d"), + cur_col[0], scale_col[0], cur_col[1], scale_col[1], cur_col[2], scale_col[2], cur_col[3], cur_col[4], light_state.getDimmer()); + char *tmp_data = XdrvMailbox.data; - uint16_t tmp_data_len = XdrvMailbox.data_len; - + char *tmp_topic = XdrvMailbox.topic; XdrvMailbox.data = (char*)cur_col; - XdrvMailbox.data_len = sizeof(cur_col); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "R%d G%d B%d, C%d W%d"), - cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); - + XdrvMailbox.topic = (char*)scale_col; if (XlgtCall(FUNC_SET_CHANNELS)) { // Serviced } @@ -1695,7 +1699,7 @@ void LightAnimate(void) // Serviced } XdrvMailbox.data = tmp_data; - XdrvMailbox.data_len = tmp_data_len; + XdrvMailbox.topic = tmp_topic; } } } From 948ef16f91b63f951377cd896773b9d701fa7743 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Thu, 17 Oct 2019 11:12:42 +0200 Subject: [PATCH 2155/2222] Add warnings to old cores --- platformio.ini | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index b8ad836e6..b081f3990 100755 --- a/platformio.ini +++ b/platformio.ini @@ -51,12 +51,14 @@ build_flags = -D NDEBUG [core_2_3_0] ; *** Esp8266 core for Arduino version 2.3.0 +; *** W A R N I N G ! *** old outdated Arduino Esp8266 core with many security issues! NOT recommended to use. NO SUPPORT! platform = espressif8266@1.5.0 build_flags = ${esp82xx_defaults.build_flags} -Wl,-Tesp8266.flash.1m0.ld [core_2_4_2] ; *** Esp8266 core for Arduino version 2.4.2 +; *** W A R N I N G ! *** old outdated Arduino Esp8266 core with security issues. NOT recommended to use. NO SUPPORT! platform = espressif8266@1.8.0 build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m0.ld @@ -70,7 +72,7 @@ build_flags = ${esp82xx_defaults.build_flags} -DVTABLES_IN_FLASH [core_pre] -; *** Arduino Esp8266 core pre 2.6.x for Tasmota (mqtt reconnects fixed) +; *** Arduino Esp8266 core pre 2.6.x for Tasmota (recommended version, no known issues) platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota build_flags = ${esp82xx_defaults.build_flags} -Wl,-Tesp8266.flash.1m.ld @@ -107,7 +109,7 @@ build_flags = ${esp82xx_defaults.build_flags} ; -lstdc++-exc [core_pre_ipv6] -; *** Arduino Esp8266 core pre 2.6.x for Tasmota (mqtt reconnects fixed) +; *** Arduino Esp8266 core pre 2.6.x IPv6 for Tasmota (use ONLY if you need IPv6, experimental!) platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota build_flags = ${esp82xx_defaults.build_flags} -Wl,-Tesp8266.flash.1m.ld From cd10e84ecf12c706508046a90fefa186285056d7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 17 Oct 2019 12:20:26 +0200 Subject: [PATCH 2156/2222] Change Sonoff L1 support --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 3 +- sonoff/sonoff_post.h | 7 +- sonoff/sonoff_template.h | 2 +- sonoff/support_features.ino | 4 +- sonoff/xdrv_19_ps16dz_dimmer.ino | 200 ++++++++---------------- sonoff/xlgt_05_sonoff_l1.ino | 258 +++++++++++++++++++++++++++++++ tools/decode-status.py | 4 +- 8 files changed, 334 insertions(+), 145 deletions(-) create mode 100644 sonoff/xlgt_05_sonoff_l1.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 7c3307cdb..ba41d1f6d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -11,6 +11,7 @@ * Add WebUI for multiple, independent PWM channels * Remove default DS18B20 driver and only support define DS18x20 (#6647) * Add support for PMS3003 dust particle sensor + * Change Sonoff L1 support by adding define USE_SONOFF_L1 * * 6.6.0.17 20191009 * Add command SetOption34 0..255 to set backlog delay. Default value is 200 (mSeconds) (#6562) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index dd03de4b6..0e25ea3ed 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -315,7 +315,7 @@ #define USE_TUYA_MCU // Add support for Tuya Serial MCU #define TUYA_DIMMER_ID 0 // Default dimmer Id #define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) -#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) +#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer (+2k code) #define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) #define USE_BUZZER // Add support for a buzzer (+0k6 code) #define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) @@ -330,6 +330,7 @@ #define USE_MY92X1 // Add support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas #define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) #define USE_SM2135 // Add support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) +#define USE_SONOFF_L1 // Add support for Sonoff L1 led control // -- Counter input ------------------------------- #define USE_COUNTER // Enable inputs as counter (+0k8 code) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 6ac4a6ac1..b9aaf1fb3 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -86,6 +86,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_DISCOVERY // Disable mDNS (+8k code or +23.5k code with core 2_5_x, +0.3k mem) // -- Optional modules ------------------------- +//#define ROTARY_V1 // Add support for MI Desk Lamp #define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) #define USE_TUYA_MCU // Add support for Tuya Serial MCU #ifndef TUYA_DIMMER_ID @@ -93,7 +94,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif //#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) -//#define ROTARY_V1 // Add support for MI Desk Lamp #define USE_COUNTER // Enable counters #undef USE_ADC_VCC // Add Analog input on selected devices @@ -150,8 +150,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c //#define PMS_MODEL_PMS3003 // Enable support of PMS3003 instead of PMS5003/PMS7003 (needs the USE_PMS5003 above) #define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) -//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) -//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) #define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger @@ -167,6 +165,8 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_SDM630_2 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) #define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) +//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) +//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI @@ -419,7 +419,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c //#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI #undef USE_WS2812 // Disable WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // -#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 76f5cb8d4..c5a8a4652 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -763,7 +763,7 @@ const uint8_t kModuleNiceList[] PROGMEM = { SONOFF_T13, SONOFF_LED, // Sonoff Light Devices SONOFF_BN, -#ifdef USE_PS_16_DZ +#ifdef USE_SONOFF_L1 SONOFF_L1, #endif SONOFF_B1, // Sonoff Light Bulbs diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index cf0740e72..9ba69feee 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -471,7 +471,9 @@ void GetFeatures(void) #ifdef USE_SONOFF_RF feature5 |= 0x00002000; // xdrv_06_snfbridge.ino #endif -// feature5 |= 0x00004000; +#ifdef USE_SONOFF_L1 + feature5 |= 0x00004000; +#endif // feature5 |= 0x00008000; // feature5 |= 0x00010000; diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 67771aa48..c9fdff640 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -1,5 +1,5 @@ /* - xdrv_19_ps16dz.dimmer.ino - PS_16_DZ dimmer and Sonoff L1 support for Sonoff-Tasmota + xdrv_19_ps16dz.dimmer.ino - PS_16_DZ dimmer support for Sonoff-Tasmota Copyright (C) 2019 Joel Stein and Theo Arends @@ -20,64 +20,46 @@ #ifdef USE_LIGHT #ifdef USE_PS_16_DZ /*********************************************************************************************\ - * PS 16 DZ Serial Dimmer and Sonoff L1 + * PS 16 DZ Serial Dimmer \*********************************************************************************************/ #define XDRV_19 19 -#define PS16DZ_BUFFER_SIZE 140 - -#define PS16DZ_SONOFF_L1_MODE_COLORFUL 1 // Colorful (static color) -#define PS16DZ_SONOFF_L1_MODE_COLORFUL_GRADIENT 2 // Colorful Gradient -#define PS16DZ_SONOFF_L1_MODE_COLORFUL_BREATH 3 // Colorful Breath -#define PS16DZ_SONOFF_L1_MODE_DIY_GRADIENT 4 // DIY Gradient (fade in and out) [Speed 1- 100, color] -#define PS16DZ_SONOFF_L1_MODE_DIY_PULSE 5 // DIY Pulse (faster fade in and out) [Speed 1- 100, color] -#define PS16DZ_SONOFF_L1_MODE_DIY_BREATH 6 // DIY Breath (toggle on/off) [Speed 1- 100, color] -#define PS16DZ_SONOFF_L1_MODE_DIY_STROBE 7 // DIY Strobe (faster toggle on/off) [Speed 1- 100, color] -#define PS16DZ_SONOFF_L1_MODE_RGB_GRADIENT 8 // RGB Gradient -#define PS16DZ_SONOFF_L1_MODE_RGB_PULSE 9 // RGB Pulse -#define PS16DZ_SONOFF_L1_MODE_RGB_BREATH 10 // RGB Breath -#define PS16DZ_SONOFF_L1_MODE_RGB_STROBE 11 // RGB strobe -#define PS16DZ_SONOFF_L1_MODE_SYNC_TO_MUSIC 12 // Sync to music [Speed 1- 100, sensitivity 1 - 10] +#define PS16DZ_BUFFER_SIZE 80 #include TasmotaSerial *PS16DZSerial = nullptr; struct PS16DZ { - char *tx_buffer = nullptr; // Serial transmit buffer char *rx_buffer = nullptr; // Serial receive buffer int byte_counter = 0; - uint8_t color[3]; // Most recent serial sent/received values uint8_t dimmer = 0; - bool supports_color = false; - bool switch_state = false; } Ps16dz; /*********************************************************************************************\ * Internal Functions \*********************************************************************************************/ -void PS16DZSerialSendTxBuffer(void) +void PS16DZSerialSend(const char *tx_buffer) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Send %s"), Ps16dz.tx_buffer); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Send %s"), tx_buffer); - PS16DZSerial->print(Ps16dz.tx_buffer); + PS16DZSerial->print(tx_buffer); PS16DZSerial->write(0x1B); PS16DZSerial->flush(); } -void PS16DZSerialSendOkCommand(void) +void PS16DZSerialSendOk(void) { - snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("AT+SEND=ok")); - PS16DZSerialSendTxBuffer(); + char tx_buffer[16]; + snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+SEND=ok")); + PS16DZSerialSend(tx_buffer); } // Send a serial update command to the LED controller // For dimmer types: // AT+UPDATE="sequence":"1554682835320","switch":"on","bright":100 -// For color types: -// AT+UPDATE="sequence":"1554682835320","switch":"on","bright":100,"mode":1,"colorR":255,"colorG":46,"colorB":101,"light_types":1 void PS16DZSerialSendUpdateCommand(void) { uint8_t light_state_dimmer = light_state.getDimmer(); @@ -85,74 +67,17 @@ void PS16DZSerialSendUpdateCommand(void) light_state_dimmer = (light_state_dimmer < Settings.dimmer_hw_min) ? Settings.dimmer_hw_min : light_state_dimmer; light_state_dimmer = (light_state_dimmer > Settings.dimmer_hw_max) ? Settings.dimmer_hw_max : light_state_dimmer; - snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), + char tx_buffer[80]; + snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer); - if (Ps16dz.supports_color) { - uint8_t light_state_rgb[3]; - light_state.getRGB(&light_state_rgb[0], &light_state_rgb[1], &light_state_rgb[2]); - - snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("%s,\"mode\":%d,\"colorR\":%d,\"colorG\":%d,\"colorB\":%d,\"light_types\":1"), - Ps16dz.tx_buffer, PS16DZ_SONOFF_L1_MODE_COLORFUL, light_state_rgb[0], light_state_rgb[1], light_state_rgb[2]); - } - PS16DZSerialSendTxBuffer(); + PS16DZSerialSend(tx_buffer); } /*********************************************************************************************\ * API Functions \*********************************************************************************************/ -bool PS16DZSerialSendUpdateCommandIfRequired(void) -{ - if (!PS16DZSerial) { return true; } - - bool is_switch_change = (XdrvMailbox.payload != SRC_SWITCH); - bool is_brightness_change = (light_state.getDimmer() != Ps16dz.dimmer); - - uint8_t light_state_rgb[3]; - light_state.getRGB(&light_state_rgb[0], &light_state_rgb[1], &light_state_rgb[2]); - bool is_color_change = (Ps16dz.supports_color && (memcmp(light_state_rgb, Ps16dz.color, 3) != 0)); - - if (is_switch_change || is_brightness_change || is_color_change) { - PS16DZSerialSendUpdateCommand(); - } - - return true; -} - -bool PS16DZModuleSelected(void) -{ - switch (my_module_type) - { - case PS_16_DZ: - devices_present++; - light_type = LT_SERIAL1; - break; - case SONOFF_L1: - devices_present++; - light_type = LT_PWM3; - break; - } - - return true; -} - -void PS16DZInit(void) -{ - Ps16dz.supports_color = (light_state.getColorMode() == LCM_RGB); - - Ps16dz.tx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); - if (Ps16dz.tx_buffer != nullptr) { - Ps16dz.rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); - if (Ps16dz.rx_buffer != nullptr) { - PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); - if (PS16DZSerial->begin(19200)) { - if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } - } - } - } -} - void PS16DZSerialInput(void) { char scmnd[20]; @@ -171,18 +96,18 @@ void PS16DZSerialInput(void) Ps16dz.rx_buffer[Ps16dz.byte_counter++] = 0x00; // AT+RESULT="sequence":"1554682835320" - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Received %s"), Ps16dz.rx_buffer); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Rcvd %s"), Ps16dz.rx_buffer); - if (!strncmp(Ps16dz.rx_buffer+3, "UPDATE", 6)) { - // AT+UPDATE="switch":"on","light_type":1,"colorR":255,"colorG":255,"colorB":255,"bright":100,"mode":19,"speed":100,"sensitive":100 + if (!strncmp(Ps16dz.rx_buffer+3, "RESULT", 6)) { + + } + else if (!strncmp(Ps16dz.rx_buffer+3, "UPDATE", 6)) { + // AT+UPDATE="switch":"on","bright":100 char *end_str; char *string = Ps16dz.rx_buffer+10; char *token = strtok_r(string, ",", &end_str); - bool color_updated[3] = { false, false, false }; - memcpy(Ps16dz.color, Settings.light_color, 3); bool is_switch_change = false; - bool is_color_change = false; bool is_brightness_change = false; while (token != nullptr) { @@ -191,43 +116,13 @@ void PS16DZSerialInput(void) char* token3 = strtok_r(nullptr, ":", &end_token); if (!strncmp(token2, "\"switch\"", 8)) { - Ps16dz.switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; + bool switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Switch %d"), Ps16dz.switch_state); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Switch %d"), switch_state); - is_switch_change = (Ps16dz.switch_state != power); + is_switch_change = (switch_state != power); if (is_switch_change) { - ExecuteCommandPower(1, Ps16dz.switch_state, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction - } - } - else if (!strncmp(token2, "\"color", 6)) { - - char color_channel_name = token2[6]; - int color_index; - switch(color_channel_name) - { - case 'R': color_index = 0; - break; - case 'G': color_index = 1; - break; - case 'B': color_index = 2; - break; - } - int color_value = atoi(token3); - Ps16dz.color[color_index] = color_value; - color_updated[color_index] = true; - - bool all_color_channels_updated = color_updated[0] && color_updated[1] && color_updated[2]; - if (all_color_channels_updated) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Color R:%d, G:%d, B:%d"), Ps16dz.color[0], Ps16dz.color[1], Ps16dz.color[2]); - - is_color_change = (memcmp(Ps16dz.color, Settings.light_color, 3) != 0); - } - - if (power && is_color_change) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_COLOR "2 %02x%02x%02x"), Ps16dz.color[0], Ps16dz.color[1], Ps16dz.color[2]); - ExecuteCommand(scmnd, SRC_SWITCH); + ExecuteCommandPower(1, switch_state, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction } } else if (!strncmp(token2, "\"bright\"", 8)) { @@ -249,11 +144,11 @@ void PS16DZSerialInput(void) token = strtok_r(nullptr, ",", &end_str); } - if (!is_color_change && !is_brightness_change) { + if (!is_brightness_change) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Update")); - PS16DZSerialSendOkCommand(); + PS16DZSerialSendOk(); } } else if (!strncmp(Ps16dz.rx_buffer+3, "SETTING", 7)) { @@ -274,6 +169,39 @@ void PS16DZSerialInput(void) } } +bool PS16DZSerialSendUpdateCommandIfRequired(void) +{ + if (!PS16DZSerial) { return true; } + + bool is_switch_change = (XdrvMailbox.payload != SRC_SWITCH); + bool is_brightness_change = (light_state.getDimmer() != Ps16dz.dimmer); + + if (is_switch_change || is_brightness_change) { + PS16DZSerialSendUpdateCommand(); + } + + return true; +} + +void PS16DZInit(void) +{ + Ps16dz.rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); + if (Ps16dz.rx_buffer != nullptr) { + PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (PS16DZSerial->begin(19200)) { + if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } + } + } +} + +bool PS16DZModuleSelected(void) +{ + devices_present++; + light_type = LT_SERIAL1; + + return true; +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -282,20 +210,20 @@ bool Xdrv19(uint8_t function) { bool result = false; - if ((PS_16_DZ == my_module_type) || (SONOFF_L1 == my_module_type)) { + if (PS_16_DZ == my_module_type) { switch (function) { case FUNC_LOOP: if (PS16DZSerial) { PS16DZSerialInput(); } break; - case FUNC_MODULE_INIT: - result = PS16DZModuleSelected(); + case FUNC_SET_DEVICE_POWER: + case FUNC_SET_CHANNELS: + result = PS16DZSerialSendUpdateCommandIfRequired(); break; case FUNC_INIT: PS16DZInit(); break; - case FUNC_SET_DEVICE_POWER: - case FUNC_SET_CHANNELS: - result = PS16DZSerialSendUpdateCommandIfRequired(); + case FUNC_MODULE_INIT: + result = PS16DZModuleSelected(); break; } } diff --git a/sonoff/xlgt_05_sonoff_l1.ino b/sonoff/xlgt_05_sonoff_l1.ino new file mode 100644 index 000000000..b0661a594 --- /dev/null +++ b/sonoff/xlgt_05_sonoff_l1.ino @@ -0,0 +1,258 @@ +/* + xlgt_05_sonoff_l1.ino - Sonoff L1 led support for Sonoff-Tasmota + + Copyright (C) 2019 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_LIGHT +#ifdef USE_SONOFF_L1 +/*********************************************************************************************\ + * Sonoff L1 +\*********************************************************************************************/ + +#define XLGT_05 5 + +#define SONOFF_L1_BUFFER_SIZE 140 + +#define SONOFF_L1_MODE_COLORFUL 1 // [Color key] Colorful (static color) +#define SONOFF_L1_MODE_COLORFUL_GRADIENT 2 // [SMOOTH] Colorful Gradient +#define SONOFF_L1_MODE_COLORFUL_BREATH 3 // [FADE] Colorful Breath +#define SONOFF_L1_MODE_DIY_GRADIENT 4 // DIY Gradient (fade in and out) [Speed 1- 100, color] +#define SONOFF_L1_MODE_DIY_PULSE 5 // DIY Pulse (faster fade in and out) [Speed 1- 100, color] +#define SONOFF_L1_MODE_DIY_BREATH 6 // DIY Breath (toggle on/off) [Speed 1- 100, color] +#define SONOFF_L1_MODE_DIY_STROBE 7 // DIY Strobe (faster toggle on/off) [Speed 1- 100, color] +#define SONOFF_L1_MODE_RGB_GRADIENT 8 // RGB Gradient +#define SONOFF_L1_MODE_RGB_PULSE 9 // [STROBE] RGB Pulse +#define SONOFF_L1_MODE_RGB_BREATH 10 // RGB Breath +#define SONOFF_L1_MODE_RGB_STROBE 11 // [FLASH] RGB strobe +#define SONOFF_L1_MODE_SYNC_TO_MUSIC 12 // Sync to music [Speed 1- 100, sensitivity 1 - 10] + +struct SNFL1 { + uint32_t unlock = 0; + bool receive_ready = true; +} Snfl1; + +/********************************************************************************************/ + +void SnfL1Send(const char *buffer) +{ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Send %s"), buffer); + + Serial.print(buffer); + Serial.write(0x1B); + Serial.flush(); +} + +void SnfL1SerialSendOk(void) +{ + char buffer[16]; + snprintf_P(buffer, sizeof(buffer), PSTR("AT+SEND=ok")); + + SnfL1Send(buffer); +} + +bool SnfL1SerialInput(void) +{ + if (serial_in_byte != 0x1B) { + if (serial_in_byte_counter >= 140) { + serial_in_byte_counter = 0; + } + if (serial_in_byte_counter || (!serial_in_byte_counter && ('A' == serial_in_byte))) { // A from AT + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + } + } else { + serial_in_buffer[serial_in_byte_counter++] = 0x00; + + // AT+RESULT="sequence":"1554682835320" + // AT+UPDATE="sequence":"34906","switch":"on","light_type":1,"colorR":0,"colorG":16,"colorB":0,"bright":6,"mode":1 + // AT+UPDATE="switch":"on","light_type":1,"colorR":255,"colorG":0,"colorB":0,"bright":6,"mode":1,"speed":100,"sensitive":10 + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd %s"), serial_in_buffer); + + if (!strncmp(serial_in_buffer +3, "RESULT", 6)) { + Snfl1.receive_ready = true; + } + else if (!strncmp(serial_in_buffer +3, "UPDATE", 6)) { + char cmnd_dimmer[20]; + char cmnd_color[20]; + char *end_str; + char *string = serial_in_buffer +10; + char *token = strtok_r(string, ",", &end_str); + + bool color_updated[3] = { false, false, false }; + uint8_t current_color[3]; + memcpy(current_color, Settings.light_color, 3); + + bool switch_state = false; + bool is_power_change = false; + bool is_color_change = false; + bool is_brightness_change = false; + + while (token != nullptr) { + char* end_token; + char* token2 = strtok_r(token, ":", &end_token); + char* token3 = strtok_r(nullptr, ":", &end_token); + + if (!strncmp(token2, "\"sequence\"", 10)) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd sequence %s"), token3); + + token = nullptr; + } + + else if (!strncmp(token2, "\"switch\"", 8)) { + switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd switch %d (%d)"), switch_state, Light.power); + + is_power_change = (switch_state != Light.power); + } + + else if (!strncmp(token2, "\"color", 6)) { + char color_channel_name = token2[6]; + int color_index; + switch(color_channel_name) + { + case 'R': color_index = 0; + break; + case 'G': color_index = 1; + break; + case 'B': color_index = 2; + break; + } + int color_value = atoi(token3); + current_color[color_index] = color_value; + color_updated[color_index] = true; + + bool all_color_channels_updated = color_updated[0] && color_updated[1] && color_updated[2]; + if (all_color_channels_updated) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd color R%d G%d B%d (R%d G%d B%d)"), + current_color[0], current_color[1], current_color[2], + Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); + + is_color_change = (Light.power && (memcmp(current_color, Settings.light_color, 3) != 0)); + } + snprintf_P(cmnd_color, sizeof(cmnd_color), PSTR(D_CMND_COLOR "2 %02x%02x%02x"), current_color[0], current_color[1], current_color[2]); + } + + else if (!strncmp(token2, "\"bright\"", 8)) { + uint8_t dimmer = atoi(token3); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd dimmer %d (%d)"), dimmer, Settings.light_dimmer); + + is_brightness_change = (Light.power && (dimmer > 0) && (dimmer != Settings.light_dimmer)); + snprintf_P(cmnd_dimmer, sizeof(cmnd_dimmer), PSTR(D_CMND_DIMMER " %d"), dimmer); + } + + token = strtok_r(nullptr, ",", &end_str); + } + + if (is_power_change) { + if (Settings.light_scheme > 0) { + if (!switch_state) { // If power off RC button pressed stop schemes + char cmnd_scheme[20]; + snprintf_P(cmnd_scheme, sizeof(cmnd_scheme), PSTR(D_CMND_SCHEME " 0")); + ExecuteCommand(cmnd_scheme, SRC_SWITCH); + } + } else { + ExecuteCommandPower(1, switch_state, SRC_SWITCH); + } + } + else if (is_brightness_change) { + ExecuteCommand(cmnd_dimmer, SRC_SWITCH); + } + else if (Light.power && is_color_change) { + if (0 == Settings.light_scheme) { // Fix spurious color receptions when scheme > 0 + if (Settings.light_fade) { // Disable fade as RC button colors overrule and are immediate supressing ghost colors + char cmnd_fade[20]; + snprintf_P(cmnd_fade, sizeof(cmnd_fade), PSTR(D_CMND_FADE " 0")); + ExecuteCommand(cmnd_fade, SRC_SWITCH); + } + ExecuteCommand(cmnd_color, SRC_SWITCH); + } + } + } + + SnfL1SerialSendOk(); + + return true; + } + serial_in_byte = 0; + return false; +} + +/********************************************************************************************/ + +bool SnfL1SetChannels(void) +{ + if (Snfl1.receive_ready || TimeReached(Snfl1.unlock)) { + + uint8_t *scale_col = (uint8_t*)XdrvMailbox.topic; + + char buffer[140]; + snprintf_P(buffer, sizeof(buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"light_type\":1,\"colorR\":%d,\"colorG\":%d,\"colorB\":%d,\"bright\":%d,\"mode\":%d"), + LocalTime(), millis()%1000, + Light.power ? "on" : "off", + scale_col[0], scale_col[1], scale_col[2], + light_state.getDimmer(), + SONOFF_L1_MODE_COLORFUL); + + SnfL1Send(buffer); + + Snfl1.unlock = millis() + 500; // Allow time for the RC + Snfl1.receive_ready = false; + } + return true; +} + +void SnfL1ModuleSelected(void) +{ + if (SONOFF_L1 == my_module_type) { + if ((pin[GPIO_RXD] < 99) && (pin[GPIO_TXD] < 99)) { + Settings.flag.mqtt_serial = 0; + baudrate = 19200; + + light_type = LT_RGB; + light_flg = XLGT_05; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Sonoff L1 Found")); + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xlgt05(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SERIAL: + result = SnfL1SerialInput(); + break; + case FUNC_SET_CHANNELS: + result = SnfL1SetChannels(); + break; + case FUNC_MODULE_INIT: + SnfL1ModuleSelected(); + break; + } + return result; +} + +#endif // USE_SONOFF_L1 +#endif // USE_LIGHT \ No newline at end of file diff --git a/tools/decode-status.py b/tools/decode-status.py index 39e2b96e3..1cb86a0b9 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -170,9 +170,9 @@ a_features = [[ "USE_MAX31865","USE_CHIRP","USE_SOLAX_X1","USE_PAJ7620" ],[ "USE_BUZZER","USE_RDM6300","USE_IBEACON","USE_SML_M", - "USE_INA226","USE_A4988_STEPPER","USE_DDS2382","USE_SM2135", + "USE_INA226","USE_A4988_Stepper","USE_DDS2382","USE_SM2135", "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", - "USE_SONOFF_SC","USE_SONOFF_RF","","", + "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","", "","","","", "","","","", "","","","", From 1f268bbf39edfc65135767ba6c4256f88b5b5cba Mon Sep 17 00:00:00 2001 From: Bastian Urschel Date: Thu, 17 Oct 2019 13:10:43 +0200 Subject: [PATCH 2157/2222] Changed the type for getting sensor values to polling. Before we used the "working period" method (the sensor starts/stops periodically on it's own and reports the data if Tasmota asks for values). Because of that I've detected a drift after some time which means that you don't get current values if "tele_period" is reached. Another point was that the "working period" method only allows a frequency above 1 minute. The new code starts the sensor directly (with commands sleep and work) if we reached a time we set in define "STARTING_OFFSET". 5 seconds before tele_period, we are doing 4 measurements, calculate the average and current values are present if tele_period is reached. The new method allows us also to get a polling frequency below 1 minute (usable for early fire detection). For precise measurements values of STARTING_OFFSET above 30 seconds are recommended. If using STARTING_OFFSET of 30 seconds and tele_period of 30 seconds the sensor now runs permanent. Fixed also wrong values at defines NOVA_SDS_SLEEP and NOVA_SDS_WORK. --- sonoff/my_user_config.h | 4 +-- sonoff/xsns_20_novasds.ino | 69 +++++++++++++++++++++++++------------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 0e25ea3ed..d205335d5 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -429,8 +429,8 @@ #define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) //#define PMS_MODEL_PMS3003 // Enable support of PMS3003 instead of PMS5003/PMS7003 (needs the USE_PMS5003 above) -#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) - #define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes +#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+1k5 code) + #define STARTING_OFFSET 30 // Turn on NovaSDS XX-seconds before tele_period is reached #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) //#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index ec6369a28..a434e56a3 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -31,14 +31,11 @@ #include -#ifndef WORKING_PERIOD -#define WORKING_PERIOD 5 // NodaSDS sleep working period in minutes +#ifndef STARTING_OFFSET +#define STARTING_OFFSET 30 // Turn on NovaSDS XX-seconds before tele_period is reached #endif -#ifndef NOVA_SDS_REINIT_CHECK -#define NOVA_SDS_REINIT_CHECK 80 // NodaSDS reinitalized check in seconds -#endif -#ifndef NOVA_SDS_QUERY_INTERVAL -#define NOVA_SDS_QUERY_INTERVAL 3 // NodaSDS query interval in seconds +#if STARTING_OFFSET < 10 +#error "Please set STARTING_OFFSET >= 10" #endif #ifndef NOVA_SDS_RECDATA_TIMEOUT #define NOVA_SDS_RECDATA_TIMEOUT 150 // NodaSDS query data timeout in ms @@ -51,11 +48,14 @@ TasmotaSerial *NovaSdsSerial; uint8_t novasds_type = 1; uint8_t novasds_valid = 0; +uint8_t cont_mode = 1; struct sds011data { uint16_t pm100; uint16_t pm25; } novasds_data; +uint16_t pm100_sum; +uint16_t pm25_sum; // NovaSDS commands #define NOVA_SDS_REPORTING_MODE 2 // Cmnd "data reporting mode" @@ -68,8 +68,8 @@ struct sds011data { #define NOVA_SDS_SET_MODE 1 // Subcmnd "set mode" #define NOVA_SDS_REPORT_ACTIVE 0 // Subcmnd "report active mode" - Sensor received query data command to report a measurement data #define NOVA_SDS_REPORT_QUERY 1 // Subcmnd "report query mode" - Sensor automatically reports a measurement data in a work period - #define NOVA_SDS_WORK 0 // Subcmnd "work mode" - #define NOVA_SDS_SLEEP 1 // Subcmnd "sleep mode" + #define NOVA_SDS_SLEEP 0 // Subcmnd "sleep mode" + #define NOVA_SDS_WORK 1 // Subcmnd "work mode" bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer) @@ -124,10 +124,10 @@ bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensor void NovaSdsSetWorkPeriod(void) { - // set sensor working period - NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, Settings.novasds_period, NOVA_SDS_DEVICE_ID, nullptr); - // set sensor report only on query - NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); + // set sensor working period to default + NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, 0, NOVA_SDS_DEVICE_ID, nullptr); + // set sensor report on query + NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); } bool NovaSdsReadData(void) @@ -146,19 +146,40 @@ bool NovaSdsReadData(void) void NovaSdsSecond(void) // Every second { - if (0 == (uptime % NOVA_SDS_REINIT_CHECK)) { - if (!novasds_valid) { - NovaSdsSetWorkPeriod(); - } - } else if (0 == (uptime % NOVA_SDS_QUERY_INTERVAL)) { - if (NovaSdsReadData()) { - novasds_valid = 10; - } else { - if (novasds_valid) { - novasds_valid--; - } + if (!novasds_valid) + { //communication problem, reinit + NovaSdsSetWorkPeriod(); + novasds_valid=1; + } + if((Settings.tele_period - STARTING_OFFSET <= 0)) + { + if(!cont_mode) + { //switched to continuous mode + cont_mode = 1; + NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); } } + else + cont_mode = 0; + + if(tele_period == Settings.tele_period - STARTING_OFFSET && !cont_mode) + { //lets start fan and laser + NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); + } + if(tele_period >= Settings.tele_period-5 && tele_period <= Settings.tele_period-2) + { //we are doing 4 measurements here + if(!(NovaSdsReadData())) novasds_valid=0; + pm100_sum += novasds_data.pm100; + pm25_sum += novasds_data.pm25; + } + if(tele_period == Settings.tele_period-1) + { //calculate the average of 4 measuremens + novasds_data.pm100 = pm100_sum >> 2; + novasds_data.pm25 = pm25_sum >> 2; + if(!cont_mode) + NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_SLEEP, NOVA_SDS_DEVICE_ID, nullptr); //stop fan and laser + pm100_sum = pm25_sum = 0; + } } /*********************************************************************************************\ From a62432f6ebb8167344a0ff9c07d8f818fbb40085 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 17 Oct 2019 15:28:46 +0200 Subject: [PATCH 2158/2222] Fix USE_A4988_STEPPER compilation --- sonoff/sonoff_post.h | 6 +++--- sonoff/xdrv_25_A4988_Stepper.ino | 11 ++++++++--- tools/decode-status.py | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index b9aaf1fb3..bb7505293 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -428,7 +428,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) -#undef USE_A4988_Stepper // Disable support for A4988_Stepper +#undef USE_A4988_STEPPER // Disable support for A4988_Stepper #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code @@ -521,7 +521,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) -#undef USE_A4988_Stepper // Disable support for A4988_Stepper +#undef USE_A4988_STEPPER // Disable support for A4988_Stepper #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_BASIC @@ -610,7 +610,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) -#undef USE_A4988_Stepper // Disable support for A4988_Stepper +#undef USE_A4988_STEPPER // Disable support for A4988_Stepper #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_MINIMAL diff --git a/sonoff/xdrv_25_A4988_Stepper.ino b/sonoff/xdrv_25_A4988_Stepper.ino index 99bcde51b..f863b9768 100644 --- a/sonoff/xdrv_25_A4988_Stepper.ino +++ b/sonoff/xdrv_25_A4988_Stepper.ino @@ -19,9 +19,14 @@ */ #ifdef USE_A4988_STEPPER -#include +/*********************************************************************************************\ + * A4988 Stepper motor driver circuit +\*********************************************************************************************/ + #define XDRV_25 25 +#include + short A4988_dir_pin = pin[GPIO_MAX]; short A4988_stp_pin = pin[GPIO_MAX]; short A4988_ms1_pin = pin[GPIO_MAX]; @@ -60,7 +65,7 @@ void A4988Init(void) const char kA4988Commands[] PROGMEM = "Motor|" // prefix "Move|Rotate|Turn|MIS|SPR|RPM"; -void (* const A4988Command[])(void) PROGMEM = { +void (* const A4988Command[])(void) PROGMEM = { &CmndDoMove,&CmndDoRotate,&CmndDoTurn,&CmndSetMIS,&CmndSetSPR,&CmndSetRPM}; void CmndDoMove(void) { @@ -130,4 +135,4 @@ bool Xdrv25(uint8_t function) return result; } -#endif +#endif // USE_A4988_STEPPER diff --git a/tools/decode-status.py b/tools/decode-status.py index 1cb86a0b9..1abbc7b32 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -170,7 +170,7 @@ a_features = [[ "USE_MAX31865","USE_CHIRP","USE_SOLAX_X1","USE_PAJ7620" ],[ "USE_BUZZER","USE_RDM6300","USE_IBEACON","USE_SML_M", - "USE_INA226","USE_A4988_Stepper","USE_DDS2382","USE_SM2135", + "USE_INA226","USE_A4988_STEPPER","USE_DDS2382","USE_SM2135", "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","", "","","","", From d3dc82170e359bd53af97d5fca7fdceee13d8b34 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 17 Oct 2019 16:51:20 +0200 Subject: [PATCH 2159/2222] Prep for release --- sonoff/sonoff_post.h | 930 +++++++++++++++++++++++-------------------- 1 file changed, 504 insertions(+), 426 deletions(-) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index bb7505293..d83bb624d 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -49,7 +49,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c \*********************************************************************************************/ #ifndef ENERGY_OVERTEMP -#define ENERGY_OVERTEMP 90 // Overtemp in Celsius +#define ENERGY_OVERTEMP 90 // Overtemp in Celsius #endif #ifdef USE_EMULATION_HUE @@ -60,9 +60,9 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif #ifdef USE_MQTT_TLS - const uint16_t WEB_LOG_SIZE = 2000; // Max number of characters in weblog + const uint16_t WEB_LOG_SIZE = 2000; // Max number of characters in weblog #else - const uint16_t WEB_LOG_SIZE = 4000; // Max number of characters in weblog + const uint16_t WEB_LOG_SIZE = 4000; // Max number of characters in weblog #endif #if defined(USE_MQTT_TLS) && defined(ARDUINO_ESP8266_RELEASE_2_3_0) @@ -70,7 +70,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif #ifndef MODULE -#define MODULE SONOFF_BASIC // [Module] Select default model +#define MODULE SONOFF_BASIC // [Module] Select default model #endif /*********************************************************************************************\ @@ -83,115 +83,137 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef CODE_IMAGE #define CODE_IMAGE 3 -#undef USE_DISCOVERY // Disable mDNS (+8k code or +23.5k code with core 2_5_x, +0.3k mem) +#undef USE_DISCOVERY // Disable mDNS (+8k code or +23.5k code with core 2_5_x, +0.3k mem) -// -- Optional modules ------------------------- -//#define ROTARY_V1 // Add support for MI Desk Lamp -#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) -#define USE_TUYA_MCU // Add support for Tuya Serial MCU +// -- Optional modules ---------------------------- +//#define ROTARY_V1 // Add support for MI Desk Lamp +#define USE_SONOFF_RF // Add support for Sonoff Rf Bridge (+3k2 code) + #define USE_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (+2k7 code) +#define USE_SONOFF_SC // Add support for Sonoff Sc (+1k1 code) +#define USE_TUYA_MCU // Add support for Tuya Serial MCU #ifndef TUYA_DIMMER_ID - #define TUYA_DIMMER_ID 0 // Default dimmer Id + #define TUYA_DIMMER_ID 0 // Default dimmer Id #endif -//#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) -#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) +//#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) +#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer (+2k code) +#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) +#define USE_BUZZER // Add support for a buzzer (+0k6 code) +#define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) +//#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+6k code) +//#define USE_DEEPSLEEP // Add support for deepsleep (+1k code) -#define USE_COUNTER // Enable counters -#undef USE_ADC_VCC // Add Analog input on selected devices -#define USE_DS18x20 // Add support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) +// -- Optional light modules ---------------------- +#define USE_LIGHT // Add Dimmer/Light support +#define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // +// #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial RXD) (+1k mem). When USE_WS2812_DMA is enabled expect Exceptions on Pow +#ifndef USE_WS2812_HARDWARE + #define USE_WS2812_HARDWARE NEO_HW_WS2812 // Hardware type (NEO_HW_WS2812, NEO_HW_WS2812X, NEO_HW_WS2813, NEO_HW_SK6812, NEO_HW_LC8812, NEO_HW_APA106) +#endif +#ifndef USE_WS2812_CTYPE + #define USE_WS2812_CTYPE NEO_GRB // Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW) +#endif +#define USE_MY92X1 // Add support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas +#define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) +#define USE_SM2135 // Add support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) +#define USE_SONOFF_L1 // Add support for Sonoff L1 led control -#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) -#define USE_SHT // Add I2C emulating code for SHT1X sensor (+1k4 code) -#define USE_HTU // Add I2C code for HTU21/SI7013/SI7020/SI7021 sensor (+1k5 code) -#define USE_BMP // Add I2C code for BMP085/BMP180/BMP280/BME280 sensor (+4k code) - #define USE_BME680 // Add additional support for BME680 sensor using Bosch BME680 library (+4k code) -#define USE_BH1750 // Add I2C code for BH1750 sensor (+0k5 code) -#define USE_VEML6070 // Add I2C code for VEML6070 sensor (+0k5 code) -#define USE_ADS1115 // Add I2C code for ADS1115 16 bit A/D converter based on Adafruit ADS1x15 library (no library needed) (+0k7 code) -//#define USE_ADS1115_I2CDEV // Add I2C code for ADS1115 16 bit A/D converter using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code) -#define USE_INA219 // Add I2C code for INA219 Low voltage and current sensor (+1k code) -//#define USE_INA226 // Enable INA226 (I2C address 0x40, 0x41 0x44 or 0x45) Low voltage and current sensor (+2k3 code) -#define USE_SHT3X // Add I2C code for SHT3x sensor (+0k6 code) -#define USE_TSL2561 // Add I2C code for TSL2561 sensor using library Adafruit TSL2561 Arduino (+1k2 code) -#define USE_MGS // Add I2C code for Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code) -#define USE_SGP30 // Add I2C code for SGP30 sensor (+1k1 code) -//#define USE_SI1145 // Add I2C code for SI1145/46/47 sensor (+1k code) -#define USE_LM75AD // Add I2C code for LM75AD sensor (+0k5 code) -//#define USE_APDS9960 // Add I2C code for APDS9960 Proximity Sensor. Disables SHT and VEML6070 (+4k7 code) -//#define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) -// #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) -// #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+1k5 code) -// #define USE_MCP230xx_DISPLAYOUTPUT // Enable MCP23008/MCP23017 to display state of OUTPUT pins on Web UI (+0k2 code) -//#define USE_PCA9685 // Enable PCA9685 I2C HW PWM Driver - Must define I2C Address in #define USE_PCA9685_ADDR below - range 0x40 - 0x47 (+1k4 code) -// #define USE_PCA9685_ADDR 0x40 // Enable PCA9685 I2C Address to use (Must be within range 0x40 through 0x47 - set according to your wired setup) -// #define USE_PCA9685_FREQ 50 // Define default PWM frequency in Hz to be used (must be within 24 to 1526) - If other value is used, it will rever to 50Hz -//#define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code) -//#define USE_CCS811 // Add I2C code for CCS811 sensor (+2k2 code) -//#define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) -//#define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) -//#define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) -//#define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code) -#define USE_SCD30 // Enable Sensiron SCd30 CO2 sensor (I2C address 0x61) (+3k3 code) -//#define USE_SPS30 // Enable Sensiron SPS30 particle sensor (I2C address 0x69) (+1.7 code) -#define USE_ADE7953 // Enable ADE7953 Energy monitor as used on Shelly 2.5 (I2C address 0x38) (+1k5) -//#define USE_VL53L0X // Enable VL53L0x time of flight sensor (I2C address 0x29) (+4k code) -//#define USE_MLX90614 // Enable MLX90614 ir temp sensor (I2C address 0x5a) (+0.6k code) -//#define USE_CHIRP // Enable CHIRP soil moisture sensor (variable I2C address, default 0x20) -//#define USE_PAJ7620 // Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code) +#define USE_COUNTER // Enable counters +#undef USE_ADC_VCC // Add Analog input on selected devices +#define USE_DS18x20 // Add support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) -#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) -#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) +#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) +#define USE_SHT // Add I2C emulating code for SHT1X sensor (+1k4 code) +#define USE_HTU // Add I2C code for HTU21/SI7013/SI7020/SI7021 sensor (+1k5 code) +#define USE_BMP // Add I2C code for BMP085/BMP180/BMP280/BME280 sensor (+4k code) + #define USE_BME680 // Add additional support for BME680 sensor using Bosch BME680 library (+4k code) +#define USE_BH1750 // Add I2C code for BH1750 sensor (+0k5 code) +#define USE_VEML6070 // Add I2C code for VEML6070 sensor (+0k5 code) +#define USE_ADS1115 // Add I2C code for ADS1115 16 bit A/D converter based on Adafruit ADS1x15 library (no library needed) (+0k7 code) +//#define USE_ADS1115_I2CDEV // Add I2C code for ADS1115 16 bit A/D converter using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code) +#define USE_INA219 // Add I2C code for INA219 Low voltage and current sensor (+1k code) +//#define USE_INA226 // Enable INA226 (I2C address 0x40, 0x41 0x44 or 0x45) Low voltage and current sensor (+2k3 code) +#define USE_SHT3X // Add I2C code for SHT3x sensor (+0k6 code) +#define USE_TSL2561 // Add I2C code for TSL2561 sensor using library Adafruit TSL2561 Arduino (+1k2 code) +#define USE_MGS // Add I2C code for Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code) +#define USE_SGP30 // Add I2C code for SGP30 sensor (+1k1 code) +//#define USE_SI1145 // Add I2C code for SI1145/46/47 sensor (+1k code) +#define USE_LM75AD // Add I2C code for LM75AD sensor (+0k5 code) +//#define USE_APDS9960 // Add I2C code for APDS9960 Proximity Sensor. Disables SHT and VEML6070 (+4k7 code) +//#define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) +// #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) +// #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+1k5 code) +// #define USE_MCP230xx_DISPLAYOUTPUT // Enable MCP23008/MCP23017 to display state of OUTPUT pins on Web UI (+0k2 code) +//#define USE_PCA9685 // Enable PCA9685 I2C HW PWM Driver - Must define I2C Address in #define USE_PCA9685_ADDR below - range 0x40 - 0x47 (+1k4 code) +// #define USE_PCA9685_ADDR 0x40 // Enable PCA9685 I2C Address to use (Must be within range 0x40 through 0x47 - set according to your wired setup) +// #define USE_PCA9685_FREQ 50 // Define default PWM frequency in Hz to be used (must be within 24 to 1526) - If other value is used, it will rever to 50Hz +//#define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code) +//#define USE_CCS811 // Add I2C code for CCS811 sensor (+2k2 code) +//#define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) +//#define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) +//#define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) +//#define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code) +#define USE_SCD30 // Enable Sensiron SCd30 CO2 sensor (I2C address 0x61) (+3k3 code) +//#define USE_SPS30 // Enable Sensiron SPS30 particle sensor (I2C address 0x69) (+1.7 code) +#define USE_ADE7953 // Enable ADE7953 Energy monitor as used on Shelly 2.5 (I2C address 0x38) (+1k5) +//#define USE_VL53L0X // Enable VL53L0x time of flight sensor (I2C address 0x29) (+4k code) +//#define USE_MLX90614 // Enable MLX90614 ir temp sensor (I2C address 0x5a) (+0.6k code) +//#define USE_CHIRP // Enable CHIRP soil moisture sensor (variable I2C address, default 0x20) +//#define USE_PAJ7620 // Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code) +//#define USE_PCF8574 // Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x27 and 0x38 - 0x3F) (+1k9 code) + +#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) +#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) #ifndef CO2_LOW - #define CO2_LOW 800 // Below this CO2 value show green light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) + #define CO2_LOW 800 // Below this CO2 value show green light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #endif #ifndef CO2_HIGH - #define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) + #define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #endif -#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) +#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) //#define PMS_MODEL_PMS3003 // Enable support of PMS3003 instead of PMS5003/PMS7003 (needs the USE_PMS5003 above) -#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) -#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) -#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop - #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) -//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger -#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) -#define USE_RDM6300 // Add support for RDM6300 125kHz RFID Reader (+0k8) -#define USE_IBEACON // Add support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) +#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) +#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) +#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop + #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) +//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger +#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) +#define USE_RDM6300 // Add support for RDM6300 125kHz RFID Reader (+0k8) +#define USE_IBEACON // Add support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) -#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) -#define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) -#define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) -#define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) -#define USE_SDM120_2 // Add support for Eastron SDM120-Modbus energy monitor (+1k1 code) -#define USE_SDM630_2 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) -#define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) -#define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) -//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) -//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) +#define USE_ENERGY_SENSOR // Add energy sensors (-14k code) +#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) +#define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) +#define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) +#define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) +#define USE_SDM120_2 // Add support for Eastron SDM120-Modbus energy monitor (+1k1 code) +#define USE_SDM630_2 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) +#define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) +#define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) +//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) +//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) +//#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+4k1 code) -#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor -#define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI -#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) - #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) - #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) -#define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // -#ifndef USE_WS2812_CTYPE - #define USE_WS2812_CTYPE NEO_GRB // WS2812 Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW) -#endif -// #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial RXD) (+1k mem). When USE_WS2812_DMA is enabled expect Exceptions on Pow -#define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) -#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) -#define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code) -#define USE_HX711 // Add support for HX711 load cell (+1k5 code) -//#define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) -#define USE_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (+3k code) -//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code) -#define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram) -#define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) -// #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) - #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code) -#define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) -#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) -//#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+4k1 code) +#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor +#define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI +#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) + #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) + #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) + +//#define USE_ZIGBEE // Enable serial communication with Zigbee CC2530 flashed with ZNP + +#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) +#define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code) +#define USE_HX711 // Add support for HX711 load cell (+1k5 code) +//#define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) +//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code) +#define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram) +#define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +// #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) + #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code) +#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) +//#define USE_A4988_STEPPER // Add support for A4988/DRV8825 stepper-motor-driver-circuit (+10k5 code) +#undef DEBUG_THEO // Disable debug code +#undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_SENSORS /*********************************************************************************************\ @@ -204,78 +226,95 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef CODE_IMAGE #define CODE_IMAGE 2 -#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices +#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices #ifndef USE_WPS -#define USE_WPS // Add support for WPS as initial wifi configuration tool (+33k code, 1k mem (5k mem with core v2.4.2+)) +#define USE_WPS // Add support for WPS as initial wifi configuration tool (+33k code, 1k mem (5k mem with core v2.4.2+)) #endif #ifndef USE_SMARTCONFIG -#define USE_SMARTCONFIG // Add support for Wifi SmartConfig as initial wifi configuration tool (+23k code, +0.6k mem) +#define USE_SMARTCONFIG // Add support for Wifi SmartConfig as initial wifi configuration tool (+23k code, +0.6k mem) #endif -#undef USE_ARDUINO_OTA // Disable support for Arduino OTA -//#undef USE_DOMOTICZ // Disable Domoticz -#undef USE_HOME_ASSISTANT // Disable Home Assistant -#undef USE_KNX // Disable KNX IP Protocol Support -#undef USE_CUSTOM // Disable Custom features -#undef USE_TIMERS // Disable support for up to 16 timers -#undef USE_TIMERS_WEB // Disable support for timer webpage -#undef USE_SUNRISE // Disable support for Sunrise and sunset tools -#undef USE_RULES // Disable support for rules +#undef USE_ARDUINO_OTA // Disable support for Arduino OTA +//#undef USE_DOMOTICZ // Disable Domoticz +#undef USE_HOME_ASSISTANT // Disable Home Assistant +#undef USE_KNX // Disable KNX IP Protocol Support +#undef USE_CUSTOM // Disable Custom features +#undef USE_TIMERS // Disable support for up to 16 timers +#undef USE_TIMERS_WEB // Disable support for timer webpage +#undef USE_SUNRISE // Disable support for Sunrise and sunset tools +#undef USE_RULES // Disable support for rules +#undef USE_SCRIPT // Disable support for script (+17k code) -// -- Optional modules ------------------------- -#undef ROTARY_V1 // Disable support for MI Desk Lamp -#define USE_SONOFF_RF // Add support for Sonoff Rf Bridge (+3k2 code) - #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB -#define USE_SONOFF_SC // Add support for Sonoff Sc (+1k1 code) -#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU -#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) -#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) -#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) -#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) -#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller -#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) -#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) +// -- Optional modules ---------------------------- +#undef ROTARY_V1 // Disable support for MI Desk Lamp +#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) + #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) +#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU +#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) +#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) +#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) +#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) +#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller +#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) +#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) -#undef USE_COUNTER // Disable counters -#define USE_DS18x20 // Add support for DS18x20 sensors with id sort, single scan and read retry (+2k6 code) -#undef USE_I2C // Disable all I2C sensors -#undef USE_SPI // Disable all SPI devices -#undef USE_MHZ19 // Disable support for MH-Z19 CO2 sensor -#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor -#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor -#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor -#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge -#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop -#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger -#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) -#undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8) -#undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) +// -- Optional light modules ---------------------- +//#undef USE_LIGHT // Disable Dimmer/Light support +#define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // +// #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_HARDWARE NEO_HW_WS2812 // Hardware type (NEO_HW_WS2812, NEO_HW_WS2812X, NEO_HW_WS2813, NEO_HW_SK6812, NEO_HW_LC8812, NEO_HW_APA106) + #define USE_WS2812_CTYPE NEO_GRB // Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW) +#undef USE_MY92X1 // Disable support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas +#undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) +#undef USE_SM2135 // Disable support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) +#undef USE_SONOFF_L1 // Disable support for Sonoff L1 led control -#undef USE_PZEM004T // Disable PZEM004T energy sensor -#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor -#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor -#undef USE_MCP39F501 // Disable support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) -#undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) -#undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) -#undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) +#undef USE_COUNTER // Disable counters +#define USE_DS18x20 // Add support for DS18x20 sensors with id sort, single scan and read retry (+2k6 code) +#undef USE_I2C // Disable all I2C sensors +#undef USE_SPI // Disable all SPI devices -#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor -#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI -#undef USE_IR_REMOTE // Disable IR remote commands using library IRremoteESP8266 and ArduinoJson -#undef USE_IR_RECEIVE // Disable support for IR receiver -#undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices -#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 -#undef USE_HX711 // Disable support for HX711 load cell -#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer -#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch -#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) -#undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) -#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) -#undef USE_A4988_STEPPER // Disable support for A4988_Stepper -#undef DEBUG_THEO // Disable debug code -#undef USE_DEBUG_DRIVER // Disable debug code +#undef USE_MHZ19 // Disable support for MH-Z19 CO2 sensor +#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor +#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor +#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor +#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge +#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop +#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger +#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) +#undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8) +#undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) + +//#undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) +#undef USE_PZEM004T // Disable PZEM004T energy sensor +#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor +#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor +#undef USE_MCP39F501 // Disable support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) +#undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) +#undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) +#undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) +#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter +#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+4k1 code) + +#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor +#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI +#undef USE_IR_REMOTE // Disable IR remote commands using library IRremoteESP8266 and ArduinoJson +#undef USE_IR_RECEIVE // Disable support for IR receiver + +#undef USE_ZIGBEE // Disable serial communication with Zigbee CC2530 flashed with ZNP + +#undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices +#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 +#undef USE_HX711 // Disable support for HX711 load cell +#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer +#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch +#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) +#undef USE_A4988_STEPPER // Disable support for A4988_Stepper +#undef DEBUG_THEO // Disable debug code +#undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_CLASSIC /*********************************************************************************************\ @@ -289,9 +328,13 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define CODE_IMAGE 4 #ifndef USE_KNX -#define USE_KNX // Enable KNX IP Protocol Support (+23k code, +3k3 mem) +#define USE_KNX // Enable KNX IP Protocol Support (+23k code, +3k3 mem) #endif -#undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) +#undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) +#undef USE_EMULATION_HUE // Disable Hue Bridge emulation for Alexa (+14k code, +2k mem common) +#undef USE_EMULATION_WEMO // Disable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) +#undef DEBUG_THEO // Disable debug code +#undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_KNX_NO_EMULATION /*********************************************************************************************\ @@ -304,50 +347,59 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef CODE_IMAGE #define CODE_IMAGE 6 -#undef ROTARY_V1 // Disable support for MI Desk Lamp -#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) - #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB -#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) -//#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU -#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) -#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) -#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) -#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) -#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller -#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) -#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) +#undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) +#undef USE_EMULATION_HUE // Disable Hue Bridge emulation for Alexa (+14k code, +2k mem common) +#undef USE_EMULATION_WEMO // Disable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) +#undef USE_DOMOTICZ // Disable Domoticz +#undef USE_HOME_ASSISTANT // Disable Home Assistant -#undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) - #undef USE_PZEM004T // Disable PZEM004T energy sensor - #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor - #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor - #undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 - #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter - #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) - #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) - #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) -#undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) -#undef USE_DOMOTICZ // Disable Domoticz -#undef USE_HOME_ASSISTANT // Disable Home Assistant +// -- Optional modules ---------------------------- +#undef ROTARY_V1 // Disable support for MI Desk Lamp +#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) + #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) +//#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU +#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) +#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) +#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) +#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) +#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller +#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) +#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) -#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) - #define USE_DISPLAY // Add I2C Display Support (+2k code) - #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 - #define USE_DISPLAY_LCD // [DisplayModel 1] Enable Lcd display (I2C addresses 0x27 and 0x3F) (+6k code) - #define USE_DISPLAY_SSD1306 // [DisplayModel 2] Enable SSD1306 Oled 128x64 display (I2C addresses 0x3C and 0x3D) (+16k code) - #define USE_DISPLAY_MATRIX // [DisplayModel 3] Enable 8x8 Matrix display (I2C adresseses see below) (+11k code) - #define USE_DISPLAY_SH1106 // [DisplayModel 7] Enable SH1106 Oled 128x64 display (I2C addresses 0x3C and 0x3D) +#undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) + #undef USE_PZEM004T // Disable PZEM004T energy sensor + #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor + #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor + #undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 + #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter + #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) + #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) + #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) +#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter +#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+4k1 code) -#define USE_SPI // Hardware SPI using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK) in addition to two user selectable GPIOs(CS and DC) - #define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display (+19k code) -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // There is not enough spare RAM with core 2.3.0 to support the following - #define USE_DISPLAY_EPAPER_29 // [DisplayModel 5] Enable e-paper 2.9 inch display (+19k code) - #define USE_DISPLAY_EPAPER_42 // [DisplayModel 6] Enable e-paper 4.2 inch display -// #define USE_DISPLAY_ILI9488 // [DisplayModel 8] -// #define USE_DISPLAY_SSD1351 // [DisplayModel 9] -// #define USE_DISPLAY_RA8876 // [DisplayModel 10] +#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) + #define USE_DISPLAY // Add I2C Display Support (+2k code) + #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 + #define USE_DISPLAY_LCD // [DisplayModel 1] Enable Lcd display (I2C addresses 0x27 and 0x3F) (+6k code) + #define USE_DISPLAY_SSD1306 // [DisplayModel 2] Enable SSD1306 Oled 128x64 display (I2C addresses 0x3C and 0x3D) (+16k code) + #define USE_DISPLAY_MATRIX // [DisplayModel 3] Enable 8x8 Matrix display (I2C adresseses see below) (+11k code) + #define USE_DISPLAY_SH1106 // [DisplayModel 7] Enable SH1106 Oled 128x64 display (I2C addresses 0x3C and 0x3D) + +#define USE_SPI // Hardware SPI using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK) in addition to two user selectable GPIOs(CS and DC) + #define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display (+19k code) +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // There is not enough spare RAM with core 2.3.0 to support the following + #define USE_DISPLAY_EPAPER_29 // [DisplayModel 5] Enable e-paper 2.9 inch display (+19k code) + #define USE_DISPLAY_EPAPER_42 // [DisplayModel 6] Enable e-paper 4.2 inch display +// #define USE_DISPLAY_ILI9488 // [DisplayModel 8] +// #define USE_DISPLAY_SSD1351 // [DisplayModel 9] +// #define USE_DISPLAY_RA8876 // [DisplayModel 10] #endif +#undef DEBUG_THEO // Disable debug code +#undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_DISPLAYS /*********************************************************************************************\ @@ -360,80 +412,83 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef CODE_IMAGE #define CODE_IMAGE 7 -#undef USE_EMULATION_HUE // disable Hue emulation - only for lights and relays -#undef USE_EMULATION_WEMO // disable Wemo emulation - only for relays #undef USE_EMULATION +#undef USE_EMULATION_HUE // Disable Hue emulation - only for lights and relays +#undef USE_EMULATION_WEMO // Disable Wemo emulation - only for relays -//#undef USE_DOMOTICZ // Disable Domoticz -//#undef USE_HOME_ASSISTANT // Disable Home Assistant -//#undef USE_KNX // Disable KNX IP Protocol Support -//#undef USE_CUSTOM // Disable Custom features -//#undef USE_TIMERS // Disable support for up to 16 timers -//#undef USE_TIMERS_WEB // Disable support for timer webpage -//#undef USE_SUNRISE // Disable support for Sunrise and sunset tools -//#undef USE_RULES // Disable support for rules -#undef USE_DISCOVERY // Disable mDNS for the following services (+8k code or +23.5k code with core 2_5_x, +0.3k mem) +//#undef USE_DOMOTICZ // Disable Domoticz +//#undef USE_HOME_ASSISTANT // Disable Home Assistant +//#undef USE_KNX // Disable KNX IP Protocol Support +//#undef USE_CUSTOM // Disable Custom features +//#undef USE_TIMERS // Disable support for up to 16 timers +//#undef USE_TIMERS_WEB // Disable support for timer webpage +//#undef USE_SUNRISE // Disable support for Sunrise and sunset tools +//#undef USE_RULES // Disable support for rules +#undef USE_DISCOVERY // Disable mDNS for the following services (+8k code or +23.5k code with core 2_5_x, +0.3k mem) -#undef ROTARY_V1 // Disable support for MI Desk Lamp -#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) - #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB -#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) -#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU -#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) -#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) -#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) -#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) -#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller -#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) -#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) +// -- Optional modules ---------------------------- +#undef ROTARY_V1 // Disable support for MI Desk Lamp +#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) + #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) +#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU +#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) +#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) +#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) +#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) +#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller +#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) +#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) -#undef USE_DS18x20 // Disable support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) +// -- Optional light modules ---------------------- +//#undef USE_LIGHT // Also disable all Dimmer/Light support +#undef USE_WS2812 // Disable WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // +#undef USE_MY92X1 // Disable support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas +#undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) +#undef USE_SM2135 // Disable support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) +#undef USE_SONOFF_L1 // Disable support for Sonoff L1 led control -#undef USE_I2C // Disable all I2C sensors -#undef USE_SPI // Disable all SPI devices +#undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) + #undef USE_PZEM004T // Disable PZEM004T energy sensor + #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor + #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor + #undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 + #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter + #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) + #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) + #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) +#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter +#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+4k1 code) -#undef USE_MHZ19 // Disable support for MH-Z19 CO2 sensor -#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor -#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor -#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor -#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge -#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop -#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger -#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) -#undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8) -#undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) +#undef USE_DS18x20 // Disable support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) -#undef USE_ENERGY_SENSOR // Disable Use energy sensors (+14k code) -#undef USE_ENERGY_MARGIN_DETECTION // Disable support for Energy Margin detection (+1k6 code) -#undef USE_PZEM004T // Disable PZEM004T energy sensor -#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor -#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor -#undef USE_MCP39F501 // Disable support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) -#undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) -#undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) -#undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) +#undef USE_I2C // Disable all I2C sensors +#undef USE_SPI // Disable all SPI devices -//#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor -#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI -#undef USE_WS2812 // Disable WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // -#undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices -#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 -#undef USE_HX711 // Disable support for HX711 load cell -#undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB -#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer -#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch -#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) -#undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) -#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) -#undef USE_A4988_STEPPER // Disable support for A4988_Stepper -#undef DEBUG_THEO // Disable debug code -#undef USE_DEBUG_DRIVER // Disable debug code - -//#undef USE_LIGHT // Also disable all Dimmer/Light support +#undef USE_MHZ19 // Disable support for MH-Z19 CO2 sensor +#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor +#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor +#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor +#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge +#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop +#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger +#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) +#undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8) +#undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) +//#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor +#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI +#undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices +#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 +#undef USE_HX711 // Disable support for HX711 load cell +#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer +#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch +#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) +#undef USE_A4988_STEPPER // Disable support for A4988_Stepper +#undef DEBUG_THEO // Disable debug code +#undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_IR /*********************************************************************************************\ @@ -447,83 +502,96 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define CODE_IMAGE 5 #undef APP_SLEEP -#define APP_SLEEP 1 // Default to sleep = 1 for FIRMWARE_BASIC +#define APP_SLEEP 1 // Default to sleep = 1 for FIRMWARE_BASIC -#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices -//#undef USE_ENERGY_SENSOR // Disable energy sensors -#undef USE_ARDUINO_OTA // Disable support for Arduino OTA -#undef USE_WPS // Disable support for WPS as initial wifi configuration tool -#undef USE_SMARTCONFIG // Disable support for Wifi SmartConfig as initial wifi configuration tool -#undef USE_DOMOTICZ // Disable Domoticz -#undef USE_HOME_ASSISTANT // Disable Home Assistant -#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set -#undef USE_KNX // Disable KNX IP Protocol Support -//#undef USE_WEBSERVER // Disable Webserver -#undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code) -//#undef USE_EMULATION // Disable Wemo or Hue emulation -#undef USE_CUSTOM // Disable Custom features -#undef USE_DISCOVERY // Disable Discovery services for both MQTT and web server -//#undef USE_TIMERS // Disable support for up to 16 timers -//#undef USE_TIMERS_WEB // Disable support for timer webpage -//#undef USE_SUNRISE // Disable support for Sunrise and sunset tools -//#undef USE_RULES // Disable support for rules +#undef USE_WPS // Disable support for WPS as initial wifi configuration tool +#undef USE_SMARTCONFIG // Disable support for Wifi SmartConfig as initial wifi configuration tool +#undef USE_ARDUINO_OTA // Disable support for Arduino OTA +#undef USE_DOMOTICZ // Disable Domoticz +#undef USE_HOME_ASSISTANT // Disable Home Assistant +#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set +#undef USE_KNX // Disable KNX IP Protocol Support +//#undef USE_WEBSERVER // Disable Webserver +#undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code) +//#undef USE_EMULATION // Disable Wemo or Hue emulation +//#undef USE_EMULATION_HUE // Disable Hue Bridge emulation for Alexa (+14k code, +2k mem common) +//#undef USE_EMULATION_WEMO // Disable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) +#undef USE_CUSTOM // Disable Custom features +#undef USE_DISCOVERY // Disable Discovery services for both MQTT and web server +//#undef USE_TIMERS // Disable support for up to 16 timers +//#undef USE_TIMERS_WEB // Disable support for timer webpage +//#undef USE_SUNRISE // Disable support for Sunrise and sunset tools +//#undef USE_RULES // Disable support for rules +#undef USE_SCRIPT // Add support for script (+17k code) // -- Optional modules ------------------------- -#undef ROTARY_V1 // Disable support for MI Desk Lamp -#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) - #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB -#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) -//#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU -#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) -#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) -#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) -#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) -#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller -#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) -#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) +#undef ROTARY_V1 // Disable support for MI Desk Lamp +#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) + #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) +//#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU +#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) +#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) +#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) +#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) +#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller +#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) +#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) -#undef USE_COUNTER // Disable counters -#undef USE_DS18x20 // Disable DS18x20 sensor -#undef USE_I2C // Disable all I2C sensors and devices -#undef USE_SPI // Disable all SPI devices -#undef USE_DISPLAY // Disable Display support -#undef USE_MHZ19 // Disable support for MH-Z19 CO2 sensor -#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor -#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor -#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor -#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge -#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop -#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger -#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) -#undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8) -#undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) +// -- Optional light modules ---------------------- +//#undef USE_LIGHT // Also disable all Dimmer/Light support +#undef USE_WS2812 // Disable WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // +#undef USE_MY92X1 // Disable support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas +#undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) +#undef USE_SM2135 // Disable support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) +#undef USE_SONOFF_L1 // Disable support for Sonoff L1 led control -#undef USE_PZEM004T // Disable PZEM004T energy sensor -#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor -#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor -//#undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 -#undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) -#undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) -#undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) +#undef USE_COUNTER // Disable counters +#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices +#undef USE_DS18x20 // Disable DS18x20 sensor +#undef USE_I2C // Disable all I2C sensors and devices +#undef USE_SPI // Disable all SPI devices +#undef USE_DISPLAY // Disable Display support +#undef USE_MHZ19 // Disable support for MH-Z19 CO2 sensor +#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor +#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor +#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor +#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge +#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop +#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger +#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) +#undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8) +#undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) -#undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor -#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI -#undef USE_IR_REMOTE // Disable IR driver -#undef USE_WS2812 // Disable WS2812 Led string -#undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices -#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 -#undef USE_HX711 // Disable support for HX711 load cell -#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer -#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch -#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) -#undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) -#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) -#undef USE_A4988_STEPPER // Disable support for A4988_Stepper -#undef DEBUG_THEO // Disable debug code -#undef USE_DEBUG_DRIVER // Disable debug code +//#undef USE_ENERGY_SENSOR // Disable energy sensors +#undef USE_PZEM004T // Disable PZEM004T energy sensor +#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor +#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor +//#undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 +#undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) +#undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) +#undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) +#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter +#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+4k1 code) + +#undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor +#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI +#undef USE_IR_REMOTE // Disable IR driver + +#undef USE_ZIGBEE // Disable serial communication with Zigbee CC2530 flashed with ZNP + +#undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices +#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 +#undef USE_HX711 // Disable support for HX711 load cell +#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer +#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch +#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) +#undef USE_A4988_STEPPER // Disable support for A4988_Stepper +#undef DEBUG_THEO // Disable debug code +#undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_BASIC /*********************************************************************************************\ @@ -536,99 +604,109 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef CODE_IMAGE #define CODE_IMAGE 1 -#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices -#undef USE_ENERGY_SENSOR // Disable energy sensors -#undef USE_ARDUINO_OTA // Disable support for Arduino OTA -#undef USE_WPS // Disable support for WPS as initial wifi configuration tool -#undef USE_SMARTCONFIG // Disable support for Wifi SmartConfig as initial wifi configuration tool -#undef USE_DOMOTICZ // Disable Domoticz -#undef USE_HOME_ASSISTANT // Disable Home Assistant -#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set -#undef USE_KNX // Disable KNX IP Protocol Support -//#undef USE_WEBSERVER // Disable Webserver -#undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code) -#undef USE_EMULATION // Disable Wemo or Hue emulation -#undef USE_CUSTOM // Disable Custom features -#undef USE_DISCOVERY // Disable Discovery services for both MQTT and web server -#undef USE_TIMERS // Disable support for up to 16 timers -#undef USE_TIMERS_WEB // Disable support for timer webpage -#undef USE_SUNRISE // Disable support for Sunrise and sunset tools -#undef USE_RULES // Disable support for rules -#undef USE_SCRIPT // Disable support for script -#undef USE_LIGHT // Disable support for lights +#undef USE_WPS // Disable support for WPS as initial wifi configuration tool +#undef USE_SMARTCONFIG // Disable support for Wifi SmartConfig as initial wifi configuration tool +#undef USE_ARDUINO_OTA // Disable support for Arduino OTA +#undef USE_DOMOTICZ // Disable Domoticz +#undef USE_HOME_ASSISTANT // Disable Home Assistant +#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set +#undef USE_KNX // Disable KNX IP Protocol Support +//#undef USE_WEBSERVER // Disable Webserver +#undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code) +#undef USE_EMULATION // Disable Wemo or Hue emulation +#undef USE_EMULATION_HUE // Disable Hue Bridge emulation for Alexa (+14k code, +2k mem common) +#undef USE_EMULATION_WEMO // Disable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) +#undef USE_CUSTOM // Disable Custom features +#undef USE_DISCOVERY // Disable Discovery services for both MQTT and web server +#undef USE_TIMERS // Disable support for up to 16 timers +#undef USE_TIMERS_WEB // Disable support for timer webpage +#undef USE_SUNRISE // Disable support for Sunrise and sunset tools +#undef USE_RULES // Disable support for rules +#undef USE_SCRIPT // Disable support for script -// -- Optional modules ------------------------- -#undef ROTARY_V1 // Disable support for MI Desk Lamp -#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) - #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB -#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) -#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU -#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) -#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) -#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) -#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) -#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller -#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) -#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) +// -- Optional modules ---------------------------- +#undef ROTARY_V1 // Disable support for MI Desk Lamp +#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) + #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) +#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU +#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) +#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) +#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) +#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) +#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller +#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) +#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) -#undef USE_COUNTER // Disable counters -#undef USE_DS18x20 // Disable DS18x20 sensor -#undef USE_I2C // Disable all I2C sensors and devices -#undef USE_SPI // Disable all SPI devices -#undef USE_DISPLAY // Disable Display support -#undef USE_MHZ19 // Disable support for MH-Z19 CO2 sensor -#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor -#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor -#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor -#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge -#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop -#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger -#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) -#undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8) -#undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) +// -- Optional light modules ---------------------- +#undef USE_LIGHT // Disable support for lights +#undef USE_WS2812 // Disable WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // +#undef USE_MY92X1 // Disable support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas +#undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) +#undef USE_SM2135 // Disable support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) +#undef USE_SONOFF_L1 // Disable support for Sonoff L1 led control -#undef USE_PZEM004T // Disable PZEM004T energy sensor -#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor -#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor -#undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 -#undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) -#undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) -#undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) +#undef USE_COUNTER // Disable counters +#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices +#undef USE_DS18x20 // Disable DS18x20 sensor -#undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor -#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI -#undef USE_IR_REMOTE // Disable IR driver -#undef USE_WS2812 // Disable WS2812 Led string -#undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices -#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 -#undef USE_HX711 // Disable support for HX711 load cell -#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer -#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch -#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) -#undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) -#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) -#undef USE_A4988_STEPPER // Disable support for A4988_Stepper -#undef DEBUG_THEO // Disable debug code -#undef USE_DEBUG_DRIVER // Disable debug code +#undef USE_I2C // Disable all I2C sensors and devices +#undef USE_SPI // Disable all SPI devices +#undef USE_DISPLAY // Disable Display support + +#undef USE_MHZ19 // Disable support for MH-Z19 CO2 sensor +#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor +#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor +#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor +#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge +#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop +#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger +#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) +#undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8) +#undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) + +#undef USE_ENERGY_SENSOR // Disable energy sensors +#undef USE_PZEM004T // Disable PZEM004T energy sensor +#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor +#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor +#undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 +#undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) +#undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) +#undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) +#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter +#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+4k1 code) + +#undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor +#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI +#undef USE_IR_REMOTE // Disable IR driver +#undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices +#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 +#undef USE_HX711 // Disable support for HX711 load cell +#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer +#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch +#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) +#undef USE_A4988_STEPPER // Disable support for A4988_Stepper +#undef DEBUG_THEO // Disable debug code +#undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_MINIMAL /*********************************************************************************************\ * Mandatory defines satisfying possible disabled defines \*********************************************************************************************/ -#ifndef USE_WPS // See https://github.com/esp8266/Arduino/pull/4889 -#undef NO_EXTRA_4K_HEAP // Allocate 4k heap for WPS in ESP8166/Arduino core v2.4.2 (was always allocated in previous versions) +#ifndef USE_WPS // See https://github.com/esp8266/Arduino/pull/4889 +#undef NO_EXTRA_4K_HEAP // Allocate 4k heap for WPS in ESP8166/Arduino core v2.4.2 (was always allocated in previous versions) #endif #ifndef USE_SONOFF_RF -#undef USE_RF_FLASH // Disable RF firmware flash when SOnoff Rf is disabled +#undef USE_RF_FLASH // Disable RF firmware flash when SOnoff Rf is disabled #endif #ifndef SWITCH_MODE -#define SWITCH_MODE TOGGLE // TOGGLE, FOLLOW or FOLLOW_INV (the wall switch state) +#define SWITCH_MODE TOGGLE // TOGGLE, FOLLOW or FOLLOW_INV (the wall switch state) #endif #ifndef MQTT_FINGERPRINT1 @@ -641,33 +719,33 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif #ifndef WS2812_LEDS -#define WS2812_LEDS 30 // [Pixels] Number of LEDs +#define WS2812_LEDS 30 // [Pixels] Number of LEDs #endif #ifndef MQTT_MAX_PACKET_SIZE -#define MQTT_MAX_PACKET_SIZE 1000 // Bytes +#define MQTT_MAX_PACKET_SIZE 1000 // Bytes #endif #ifndef MQTT_KEEPALIVE -#define MQTT_KEEPALIVE 30 // Seconds +#define MQTT_KEEPALIVE 30 // Seconds #endif #ifndef MQTT_TIMEOUT -#define MQTT_TIMEOUT 10000 // milli seconds +#define MQTT_TIMEOUT 10000 // milli seconds #endif #ifndef MQTT_CLEAN_SESSION -#define MQTT_CLEAN_SESSION 1 // 0 = No clean session, 1 = Clean session (default) +#define MQTT_CLEAN_SESSION 1 // 0 = No clean session, 1 = Clean session (default) #endif #ifndef MESSZ -//#define MESSZ 893 // Max number of characters in JSON message string (Hass discovery and nice MQTT_MAX_PACKET_SIZE = 1000) +//#define MESSZ 893 // Max number of characters in JSON message string (Hass discovery and nice MQTT_MAX_PACKET_SIZE = 1000) #define MESSZ (MQTT_MAX_PACKET_SIZE -TOPSZ -7) // Max number of characters in JSON message string #endif -//#include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) +//#include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) #ifndef ARDUINO_ESP8266_RELEASE #define ARDUINO_ESP8266_RELEASE "STAGE" #endif -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 // Disable not supported features in core 2.3.0 +#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 // Disable not supported features in core 2.3.0 #undef USE_MQTT_TLS_CA_CERT #endif From 9be8c20668473160ec8038b6a011bf6a7861a26e Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Thu, 17 Oct 2019 11:57:54 -0300 Subject: [PATCH 2160/2222] Update xdrv_12_home_assistant.ino --- sonoff/xdrv_12_home_assistant.ino | 36 ++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 326cced2f..d5a52a491 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -131,8 +131,7 @@ const char HASS_DISCOVER_SENSOR_ILLUMINANCE[] PROGMEM = "\"dev_cla\":\"illuminance\""; // illuminance const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = - ",\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass - "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} + ",\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = ",\"json_attributes_topic\":\"%s\"," @@ -405,28 +404,41 @@ void HAssAnnounceButtons(void) } } -void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) +void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) { char stopic[TOPSZ]; char stemp1[TOPSZ]; char stemp2[TOPSZ]; char unique_id[30]; + bool is_sensor = true; // Announce sensor, special handling of temperature and humidity sensors mqtt_data[0] = '\0'; // Clear retained message // Clear or Set topic snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP.getChipId(), sensorname, subsensortype); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); - + if (!strncmp_P(sensorname, "MPR121", 6)) { // Add more exceptions here. Perhaps MCP230XX? + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); + is_sensor = false; + } else { + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); + } if (Settings.flag.hass_discovery) { char name[33+42]; // friendlyname(33) + " " + sensorname(20?) + " " + sensortype(20?) char prefix[TOPSZ]; char *state_topic = stemp1; char *availability_topic = stemp2; + // sensor or binary_sensor? // + if (!is_sensor) { + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); + GetTopic_P(state_topic, STAT, mqtt_topic, PSTR(D_RSLT_RESULT)); + } else { + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); + GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); + } + snprintf_P(name, sizeof(name), PSTR("%s %s %s"), Settings.friendlyname[0], sensorname, subsensortype); - GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); FindPrefix(state_topic, availability_topic, prefix); Shorten(&state_topic, prefix); @@ -436,9 +448,6 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); if (!strcmp_P(subsensortype, PSTR(D_JSON_TEMPERATURE))) { - if (!strncmp_P(sensorname, "DS18B20-", 8)){ - TryResponseAppend_P(HASS_DISCOVER_DS18X20_MULTI, state_topic, sensorname); // Add 'Id' as additional information - } TryResponseAppend_P(HASS_DISCOVER_SENSOR_TEMP, TempUnit(), sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { TryResponseAppend_P(HASS_DISCOVER_SENSOR_HUM, sensorname); @@ -457,7 +466,10 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) } else if (!strcmp_P(subsensortype, PSTR(D_JSON_ILLUMINANCE))){ TryResponseAppend_P(HASS_DISCOVER_SENSOR_ILLUMINANCE, sensorname, subsensortype); } else { - TryResponseAppend_P(HASS_DISCOVER_SENSOR_ANY, sensorname, subsensortype); + if (is_sensor){ + TryResponseAppend_P(PSTR(",\"unit_of_meas\":\" \"")); // " " As unit of measurement to get a value graph (not available for binary sensors) + } + TryResponseAppend_P(HASS_DISCOVER_SENSOR_ANY, sensorname, subsensortype); } TryResponseAppend_P(PSTR("}")); } @@ -489,14 +501,14 @@ void HAssAnnounceSensors(void) StaticJsonBuffer<500> jsonBuffer; JsonObject& root = jsonBuffer.parseObject(sensordata); if (!root.success()) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: failed to parse '%s'"), sensordata); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: jsonBuffer failed to parse '%s'"), sensordata); continue; } for (auto sensor : root) { const char* sensorname = sensor.key; JsonObject& sensors = sensor.value.as(); if (!sensors.success()) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: failed to parse '%s'"), sensordata); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: JsonObject failed to parse '%s'"), sensordata); continue; } for (auto subsensor : sensors) { From 29bff1a3f6dc47c30c9319a09a7ff16e4798e58e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 17 Oct 2019 18:09:23 +0200 Subject: [PATCH 2161/2222] Prep for release --- RELEASENOTES.md | 90 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 31 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index d7084c559..12c8c8321 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -10,13 +10,11 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade 3. Migrate to **Sonoff-Tasmota 5.14** 4. Migrate to **Sonoff-Tasmota 6.x** +## Change of supported Core versions +This release will be supported from ESP8266/Arduino library Core version **pre-2.6.0** due to reported security and stability issues on previous Core version. Although it might still compile on previous Core versions all support will be removed starting from the next Release. + ## Support of TLS -TLS support for core 2.3.0 is removed. - -TLS is supported on core 2.4.2 and up. To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. See full documentation on https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT - -## Core version 2.3.0 vs 2.4.2 vs 2.5.2 -This release is based on ESP8266/Arduino library core 2.3.0 as some people encountered wifi related issues on core 2.4.2 and 2.5.2. For others core 2.4.2 or 2.5.2 is working just fine. All version are available from http://thehackbox.org/tasmota/release/ +To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. See full documentation on https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT ## Change in default initial configuration tool Firmware binary **sonoff-classic.bin** supports **WifiManager, Wps and SmartConfig** for initial configuration. The default tool is **Wps**. @@ -98,9 +96,10 @@ Module | Description 68 WAGA CHCZ02MB | WAGA life CHCZ02MB Wifi Smart Switch with Energy Monitoring 69 SYF05 | Sunyesmart SYF05 RGBWW Wifi Led Bulb 70 Sonoff L1 | Sonoff L1 light strip +71 Sonoff iFan03 | Sonoff iFan03 Wifi Smart Ceiling Fan with Light ## Provided Binary Downloads -The following binary downloads have been compiled with ESP8266/Arduino library core version **2.3.0**. +The following binary downloads have been compiled with ESP8266/Arduino library core version **pre-2.6.0**. - **sonoff.bin** = The Sonoff version without Wps and SmartConfig configuration but adds more sensors. **RECOMMENDED RELEASE BINARY** - **sonoff-basic.bin** = The Basic version without Wps and SmartConfig configuration and most sensors. @@ -111,10 +110,6 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - **sonoff-display.bin** = The Display version without Wps and SmartConfig configuration and Energy Monitoring but adds display support. - **sonoff-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**. -Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/release/020402/ - -Core version **2.5.2** binaries can be found at http://thehackbox.org/tasmota/release/020502/ - ## Available Features and Sensors | Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks @@ -142,12 +137,47 @@ Core version **2.5.2** binaries can be found at http://thehackbox.org/tasmota/re | USE_SCRIPT | - | - | - | - | - | - | - | | USE_EXPRESSION | - | - | - | - | - | - | - | | | | | | | | | | +| ROTARY_V1 | - | - | - | - | - | - | - | +| USE_SONOFF_RF | - | - | - | x | x | x | - | +| USE_RF_FLASH | - | - | - | x | x | x | - | +| USE_SONOFF_SC | - | - | - | x | - | x | - | +| USE_TUYA_MCU | - | x | - | x | x | x | x | +| USE_ARMTRONIX_DIMMERS | - | - | - | x | x | - | - | +| USE_PS_16_DZ | - | - | - | x | x | x | - | +| USE_SONOFF_IFAN | - | - | - | x | x | x | - | +| USE_BUZZER | - | - | - | x | x | x | - | +| USE_ARILUX_RF | - | - | - | x | x | x | - | +| USE_SHUTTER | - | - | - | - | - | - | - | +| USE_DEEPSLEEP | - | - | - | - | - | - | - | +| | | | | | | | | +| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks +| USE_LIGHT | - | x | x | x | x | x | x | +| USE_WS2812 | - | - | x | x | x | x | x | +| USE_WS2812_DMA | - | - | - | - | - | - | - | +| USE_MY92X1 | - | - | - | x | x | x | x | +| USE_SM16716 | - | - | - | x | x | x | x | +| USE_SM2135 | - | - | - | x | x | x | x | +| USE_SONOFF_L1 | - | - | - | x | x | x | x | +| | | | | | | | | +| USE_ENERGY_SENSOR | - | x | x | x | x | x | - | +| USE_PZEM004T | - | - | - | x | x | x | - | +| USE_PZEM_AC | - | - | - | x | x | x | - | +| USE_PZEM_DC | - | - | - | x | x | x | - | +| USE_MCP39F501 | - | x | - | x | x | x | - | +| USE_SDM120_2 | - | - | - | - | - | x | - | +| USE_SDM630_2 | - | - | - | - | - | x | - | +| USE_DDS2382 | - | - | - | - | - | x | - | +| USE_DDSU666 | - | - | - | - | - | x | - | +| USE_SDM120 | - | - | - | - | - | - | - | +| USE_SDM630 | - | - | - | - | - | - | - | +| USE_SOLAX_X1 | - | - | - | - | - | - | - | +| | | | | | | | | | USE_ADC_VCC | x | x | x | - | - | - | - | | USE_COUNTER | - | - | - | x | x | x | x | -| USE_DS18B20 | - | - | - | - | - | - | - | Single sensor -| USE_DS18x20 | - | - | x | x | x | x | x | Multiple sensors -| USE_DS18x20_LEGACY | - | - | - | - | - | - | - | Multiple sensors +| USE_DS18x20 | - | - | x | x | x | x | x | | USE_DHT | - | - | x | x | x | x | x | +| USE_MAX31855 | - | - | - | - | - | x | - | +| USE_MAX31865 | - | - | - | - | - | - | - | | | | | | | | | | | Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks | USE_I2C | - | - | - | x | x | x | x | @@ -160,6 +190,7 @@ Core version **2.5.2** binaries can be found at http://thehackbox.org/tasmota/re | USE_ADS1115 | - | - | - | - | - | x | - | | USE_ADS1115_I2CDEV | - | - | - | - | - | - | - | | USE_INA219 | - | - | - | - | - | x | - | +| USE_INA226 | - | - | - | - | - | - | - | | USE_SHT3X | - | - | - | x | x | x | x | | USE_TSL2561 | - | - | - | - | - | x | - | | USE_MGS | - | - | - | - | - | x | - | @@ -180,6 +211,9 @@ Core version **2.5.2** binaries can be found at http://thehackbox.org/tasmota/re | USE_ADE7953 | - | - | - | x | x | x | x | | USE_VL53L0X | - | - | - | - | - | - | - | | USE_MLX90614 | - | - | - | - | - | - | - | +| USE_CHIRP | - | - | - | - | - | - | - | +| USE_PAJ7620 | - | - | - | - | - | - | - | +| USE_PCF8574 | - | - | - | - | - | - | - | | | | | | | | | | | Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks | USE_SPI | - | - | - | - | - | - | x | @@ -187,41 +221,35 @@ Core version **2.5.2** binaries can be found at http://thehackbox.org/tasmota/re | USE_SENSEAIR | - | - | - | x | x | x | x | | USE_PMS5003 | - | - | - | x | x | x | x | | USE_NOVA_SDS | - | - | - | x | x | x | x | -| USE_ENERGY_SENSOR | - | x | x | x | x | x | - | -| USE_PZEM004T | - | - | - | x | x | x | - | -| USE_PZEM_AC | - | - | - | x | x | x | - | -| USE_PZEM_DC | - | - | - | x | x | x | - | -| USE_MCP39F501 | - | x | - | x | x | x | - | | USE_SERIAL_BRIDGE | - | - | - | x | x | x | x | -| USE_SDM120 | - | - | - | - | - | x | - | -| USE_SDM630 | - | - | - | - | - | x | - | | USE_MP3_PLAYER | - | - | - | - | - | x | - | -| USE_TUYA_DIMMER | - | x | - | x | x | x | x | -| USE_ARMTRONIX_DIMMERS | - | x | - | x | x | x | x | -| USE_PS_16_DZ | - | x | - | x | x | x | x | | USE_AZ7798 | - | - | - | - | - | - | - | | USE_PN532_HSU | - | - | - | - | - | x | - | +| USE_ZIGBEE | - | - | - | - | - | - | - | +| | | | | | | | | | USE_IR_REMOTE | - | - | - | x | x | x | x | | USE_IR_HVAC | - | - | - | - | - | x | - | | USE_IR_RECEIVE | - | - | - | x | x | x | x | -| USE_WS2812 | - | - | x | x | x | x | x | -| USE_WS2812_DMA | - | - | - | - | - | - | - | -| USE_ARILUX_RF | - | - | - | x | x | x | - | +| | | | | | | | | | USE_SR04 | - | - | - | x | x | x | x | | USE_TM1638 | - | - | - | - | - | x | - | | USE_HX711 | - | - | - | x | x | x | x | -| USE_RF_FLASH | - | - | - | x | x | x | - | -| USE_TX20_WIND_SENSOR | - | - | - | x | x | x | x | -| USE_RC_SWITCH | - | - | - | x | x | x | x | +| USE_TX20_WIND_SENSOR | - | - | - | - | - | x | - | +| USE_RC_SWITCH | - | - | - | - | - | x | - | | USE_RF_SENSOR | - | - | - | - | - | x | - | AlectoV2 only -| USE_SM16716 | - | x | x | x | x | x | x | | USE_HRE | - | - | - | - | - | x | - | +| USE_A4988_STEPPER | - | - | - | - | - | - | - | +| | | | | | | | | | USE_DISPLAY | - | - | - | - | - | - | x | | USE_DISPLAY_LCD | - | - | - | - | - | - | x | | USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x | | USE_DISPLAY_MATRIX | - | - | - | - | - | - | x | | USE_DISPLAY_ILI9341 | - | - | - | - | - | - | x | | USE_DISPLAY_EPAPER_29 | - | - | - | - | - | - | x | Disabled for core 2.3.0 +| USE_DISPLAY_EPAPER_42 | - | - | - | - | - | - | - | +| USE_DISPLAY_ILI9488 | - | - | - | - | - | - | - | +| USE_DISPLAY_SSD1351 | - | - | - | - | - | - | - | +| USE_DISPLAY_RA8876 | - | - | - | - | - | - | - | ## Changelog Version 6.6.0 20190707 From 926869e8491ac57d1dacff6b7cf96556ecb4b455 Mon Sep 17 00:00:00 2001 From: pablozg Date: Thu, 17 Oct 2019 18:22:11 +0200 Subject: [PATCH 2162/2222] Solax X1: Code refactor and optimitation, add as energy driver to get today/yesterday totals and P1 smart meter function --- sonoff/my_user_config.h | 5 +- sonoff/sonoff_post.h | 16 +- sonoff/sonoff_template.h | 14 +- sonoff/xnrg_12_solaxX1.ino | 530 +++++++++++++++++++++++++++++++++++++ sonoff/xsns_49_solaxX1.ino | 391 ++++++++++++--------------- 5 files changed, 727 insertions(+), 229 deletions(-) create mode 100644 sonoff/xnrg_12_solaxX1.ino diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index d205335d5..9a9d70402 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -457,13 +457,16 @@ #define DDS2382_SPEED 9600 // Hiking DDS2382 Modbus RS485 serial speed (default: 9600 baud) //#define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) #define DDSU666_SPEED 9600 // Chint DDSU666 Modbus RS485 serial speed (default: 9600 baud) +//#define USE_SOLAX_X1_NRG // Add support for Solax X1 series Modbus log info (+3k1 code) + #define SOLAXX1_SPEED 9600 // Solax X1 Modbus RS485 serial speed (default: 9600 baud) + #define SOLAXX1_PV2 // Solax X1 using second PV //#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+2k4 code) // #define SDM120_SPEED 2400 // SDM120-Modbus RS485 serial speed (default: 2400 baud) #define USE_SDM220 // Add extra parameters for SDM220 (+0k1 code) //#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) // #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) -//#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+4k1 code) +//#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+3k6 code) #define SOLAXX1_SPEED 9600 // Solax X1 Modbus RS485 serial speed (default: 9600 baud) #define SOLAXX1_PV2 // Solax X1 using second PV diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index d83bb624d..15052711e 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -189,9 +189,10 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_SDM630_2 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) #define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) +//#define USE_SOLAX_X1_NRG // Add support for Solax X1 series Modbus log info (+3k1 code) //#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) //#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) -//#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+4k1 code) +//#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+3k6 code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI @@ -294,9 +295,10 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) +#undef USE_SOLAX_X1_NRG // Disable support for Solax X1 series Modbus log info (+3k1 code) #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+4k1 code) +#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k6 code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI @@ -376,9 +378,10 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) + #undef USE_SOLAX_X1_NRG // Disable support for Solax X1 series Modbus log info (+3k1 code) #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+4k1 code) +#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k6 code) #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) #define USE_DISPLAY // Add I2C Display Support (+2k code) @@ -457,9 +460,10 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) + #undef USE_SOLAX_X1_NRG // Disable support for Solax X1 series Modbus log info (+3k1 code) #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+4k1 code) +#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k6 code) #undef USE_DS18x20 // Disable support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) @@ -572,6 +576,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) +#undef USE_SOLAX_X1_NRG // Disable support for Solax X1 series Modbus log info (+3k1 code) #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+4k1 code) @@ -674,9 +679,10 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) +#undef USE_SOLAX_X1_NRG // Disable support for Solax X1 series Modbus log info (+3k1 code) #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+4k1 code) +#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k6 code) #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index c5a8a4652..81c5f7657 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -646,6 +646,14 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_DDS2382_TX, // DDS2382 Serial interface GPIO_DDS2382_RX, // DDS2382 Serial interface #endif +#ifdef USE_DDSU666 + GPIO_DDSU666_TX, // DDSU666 Serial interface + GPIO_DDSU666_RX, // DDSU666 Serial interface +#endif // USE_DDSU666 +#ifdef USE_SOLAX_X1_NRG + GPIO_SOLAXX1_TX, // Solax Inverter tx pin + GPIO_SOLAXX1_RX, // Solax Inverter rx pin +#endif // USE_SOLAX_X1_NRG #endif // USE_ENERGY_SENSOR #ifndef USE_SDM120_2 #ifdef USE_SDM120 @@ -659,14 +667,12 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_SDM630_RX, // SDM630 Serial interface #endif #endif // USE_SDM630_2 +#ifndef USE_SOLAX_X1_NRG #ifdef USE_SOLAX_X1 GPIO_SOLAXX1_TX, // Solax Inverter tx pin GPIO_SOLAXX1_RX, // Solax Inverter rx pin #endif -#ifdef USE_DDSU666 - GPIO_DDSU666_TX, // DDSU666 Serial interface - GPIO_DDSU666_RX, // DDSU666 Serial interface -#endif // USE_DDSU666 +#endif // USE_SOLAX_X1_NRG #ifdef USE_SERIAL_BRIDGE GPIO_SBR_TX, // Serial Bridge Serial interface diff --git a/sonoff/xnrg_12_solaxX1.ino b/sonoff/xnrg_12_solaxX1.ino new file mode 100644 index 000000000..0bd67ec4d --- /dev/null +++ b/sonoff/xnrg_12_solaxX1.ino @@ -0,0 +1,530 @@ +/* + xnrg_12_solaxX1.ino - Solax X1 inverter RS485 support for Sonoff-Tasmota + + Copyright (C) 2019 Pablo Zerón + + 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_ENERGY_SENSOR +#ifdef USE_SOLAX_X1_NRG +/*********************************************************************************************\ + * Solax X1 Inverter +\*********************************************************************************************/ + +#define XNRG_12 12 + +#ifndef SOLAXX1_SPEED +#define SOLAXX1_SPEED 9600 // default solax rs485 speed +#endif + +#define INVERTER_ADDRESS 0x0A + +#define D_SOLAX_X1 "SolaxX1" + +#include + +enum solaxX1_Error +{ + solaxX1_ERR_NO_ERROR, + solaxX1_ERR_CRC_ERROR +}; + +union { + uint32_t ErrMessage; + struct { + //BYTE0 + uint8_t TzProtectFault:1;//0 + uint8_t MainsLostFault:1;//1 + uint8_t GridVoltFault:1;//2 + uint8_t GridFreqFault:1;//3 + uint8_t PLLLostFault:1;//4 + uint8_t BusVoltFault:1;//5 + uint8_t ErrBit06:1;//6 + uint8_t OciFault:1;//7 + //BYTE1 + uint8_t Dci_OCP_Fault:1;//8 + uint8_t ResidualCurrentFault:1;//9 + uint8_t PvVoltFault:1;//10 + uint8_t Ac10Mins_Voltage_Fault:1;//11 + uint8_t IsolationFault:1;//12 + uint8_t TemperatureOverFault:1;//13 + uint8_t FanFault:1;//14 + uint8_t ErrBit15:1;//15 + //BYTE2 + uint8_t SpiCommsFault:1;//16 + uint8_t SciCommsFault:1;//17 + uint8_t ErrBit18:1;//18 + uint8_t InputConfigFault:1;//19 + uint8_t EepromFault:1;//20 + uint8_t RelayFault:1;//21 + uint8_t SampleConsistenceFault:1;//22 + uint8_t ResidualCurrent_DeviceFault:1;//23 + //BYTE3 + uint8_t ErrBit24:1;//24 + uint8_t ErrBit25:1;//25 + uint8_t ErrBit26:1;//26 + uint8_t ErrBit27:1;//27 + uint8_t ErrBit28:1;//28 + uint8_t DCI_DeviceFault:1;//29 + uint8_t OtherDeviceFault:1;//30 + uint8_t ErrBit31:1;//31 + }; +} ErrCode; + +const char kSolaxMode[] PROGMEM = D_WAITING "|" D_CHECKING "|" D_WORKING "|" D_FAILURE; + +const char kSolaxError[] PROGMEM = + D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|" + D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8; + +/*********************************************************************************************/ + +TasmotaSerial *solaxX1Serial; + +uint8_t solaxX1_Init = 1; + +struct SOLAXX1 { + float temperature = 0; + float energy_today = 0; + float dc1_voltage = 0; + float dc2_voltage = 0; + float dc1_current = 0; + float dc2_current = 0; + float energy_total = 0; + float runtime_total = 0; + float dc1_power = 0; + float dc2_power = 0; + + uint8_t status = 0; + uint32_t errorCode = 0; +} solaxX1; + +union { + uint8_t status; + struct { + uint8_t freeBit7:1; // Bit7 + uint8_t freeBit6:1; // Bit6 + uint8_t freeBit5:1; // Bit5 + uint8_t queryOffline:1; // Bit4 + uint8_t queryOfflineSend:1; // Bit3 + uint8_t hasAddress:1; // Bit2 + uint8_t inverterAddressSend:1; // Bit1 + uint8_t inverterSnReceived:1; // Bit0 + }; +} protocolStatus; + +uint8_t header[2] = {0xAA, 0x55}; +uint8_t source[2] = {0x00, 0x00}; +uint8_t destination[2] = {0x00, 0x00}; +uint8_t controlCode[1] = {0x00}; +uint8_t functionCode[1] = {0x00}; +uint8_t dataLength[1] = {0x00}; +uint8_t data[16] = {0}; + +uint8_t message[30]; + +/*********************************************************************************************/ + +bool solaxX1_RS485ReceiveReady(void) +{ + return (solaxX1Serial->available() > 1); +} + +void solaxX1_RS485Send(uint16_t msgLen) +{ + memcpy(message, header, 2); + memcpy(message + 2, source, 2); + memcpy(message + 4, destination, 2); + memcpy(message + 6, controlCode, 1); + memcpy(message + 7, functionCode, 1); + memcpy(message + 8, dataLength, 1); + memcpy(message + 9, data, sizeof(data)); + uint16_t crc = solaxX1_calculateCRC(message, msgLen); // calculate out crc bytes + + while (solaxX1Serial->available() > 0) + { // read serial if any old data is available + solaxX1Serial->read(); + } + + solaxX1Serial->flush(); + solaxX1Serial->write(message, msgLen); + solaxX1Serial->write(highByte(crc)); + solaxX1Serial->write(lowByte(crc)); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, message, msgLen); +} + +uint8_t solaxX1_RS485Receive(uint8_t *value) +{ + uint8_t len = 0; + + while (solaxX1Serial->available() > 0) + { + value[len++] = (uint8_t)solaxX1Serial->read(); + } + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, value, len); + + uint16_t crc = solaxX1_calculateCRC(value, len - 2); // calculate out crc bytes + + if (value[len - 1] == lowByte(crc) && value[len - 2] == highByte(crc)) + { // check calc crc with received crc + return solaxX1_ERR_NO_ERROR; + } + else + { + return solaxX1_ERR_CRC_ERROR; + } +} + +uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) +{ + uint8_t i; + uint16_t wChkSum; + wChkSum = 0; + + for (i = 0; i < bLen; i++) + { + wChkSum = wChkSum + bExternTxPackage[i]; + } + return wChkSum; +} + +void solaxX1_SendInverterAddress() +{ + source[0] = 0x00; + destination[0] = 0x00; + destination[1] = 0x00; + controlCode[0] = 0x10; + functionCode[0] = 0x01; + dataLength[0] = 0x0F; + data[14] = INVERTER_ADDRESS; // Inverter Address, It must be unique in case of more inverters in the same rs485 net. + solaxX1_RS485Send(24); +} + +void solaxX1_QueryLiveData() +{ + source[0] = 0x01; + destination[0] = 0x00; + destination[1] = INVERTER_ADDRESS; + controlCode[0] = 0x11; + functionCode[0] = 0x02; + dataLength[0] = 0x00; + solaxX1_RS485Send(9); +} + +uint8_t solaxX1_ParseErrorCode(uint32_t code){ + ErrCode.ErrMessage = code; + + if (code == 0) return 0; + if (ErrCode.MainsLostFault) return 1; + if (ErrCode.GridVoltFault) return 2; + if (ErrCode.GridFreqFault) return 3; + if (ErrCode.PvVoltFault) return 4; + if (ErrCode.IsolationFault) return 5; + if (ErrCode.TemperatureOverFault) return 6; + if (ErrCode.FanFault) return 7; + if (ErrCode.OtherDeviceFault) return 8; +} + +/*********************************************************************************************/ + +uint8_t solaxX1_send_retry = 0; +uint8_t solaxX1_nodata_count = 0; + +void solaxX1250MSecond(void) // Every Second +{ + uint8_t value[61] = {0}; + bool data_ready = solaxX1_RS485ReceiveReady(); + + if (protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) + { + if (data_ready) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error")); + } + else + { + solaxX1_nodata_count = 0; + solaxX1_send_retry = 12; + Energy.data_valid[0] = 0; + + solaxX1.temperature = (float)((value[9] << 8) | value[10]); // Temperature + solaxX1.energy_today = (float)((value[11] << 8) | value[12]) * 0.1f; // Energy Today + solaxX1.dc1_voltage = (float)((value[13] << 8) | value[14]) * 0.1f; // PV1 Voltage + solaxX1.dc2_voltage = (float)((value[15] << 8) | value[16]) * 0.1f; // PV2 Voltage + solaxX1.dc1_current = (float)((value[17] << 8) | value[18]) * 0.1f; // PV1 Current + solaxX1.dc2_current = (float)((value[19] << 8) | value[20]) * 0.1f; // PV2 Current + Energy.current[0] = (float)((value[21] << 8) | value[22]) * 0.1f; // AC Current + Energy.voltage[0] = (float)((value[23] << 8) | value[24]) * 0.1f; // AC Voltage + Energy.frequency[0] = (float)((value[25] << 8) | value[26]) * 0.01f; // AC Frequency + Energy.active_power[0] = (float)((value[27] << 8) | value[28]); // AC Power + //temporal = (float)((value[29] << 8) | value[30]) * 0.1f; // Not Used + solaxX1.energy_total = (float)((value[31] << 8) | (value[32] << 8) | (value[33] << 8) | value[34]) * 0.1f; // Energy Total + solaxX1.runtime_total = (float)((value[35] << 8) | (value[36] << 8) | (value[37] << 8) | value[38]); // Work Time Total + solaxX1.status = (uint8_t)((value[39] << 8) | value[40]); // Work mode + //temporal = (float)((value[41] << 8) | value[42]); // Grid voltage fault value 0.1V + //temporal = (float)((value[43] << 8) | value[44]); // Gird frequency fault value 0.01Hz + //temporal = (float)((value[45] << 8) | value[46]); // Dc injection fault value 1mA + //temporal = (float)((value[47] << 8) | value[48]); // Temperature fault value + //temporal = (float)((value[49] << 8) | value[50]); // Pv1 voltage fault value 0.1V + //temporal = (float)((value[51] << 8) | value[52]); // Pv2 voltage fault value 0.1V + //temporal = (float)((value[53] << 8) | value[54]); // GFC fault value + solaxX1.errorCode = (uint32_t)((value[58] << 8) | (value[57] << 8) | (value[56] << 8) | value[55]); // Error Code + + solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current; + solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current; + + solaxX1_QueryLiveData(); + EnergyUpdateTotal(solaxX1.energy_total, true); // 484.708 kWh + } + } // End data Ready + + if (0 == solaxX1_send_retry && 255 != solaxX1_nodata_count) { + solaxX1_send_retry = 12; + solaxX1_QueryLiveData(); + } + + // While the inverter has not stable ambient light, will send an address adquired but go offline again, + // so no data will be received when the query is send, then we start the countdown to set the inverter as offline again. + if (255 == solaxX1_nodata_count) { + solaxX1_nodata_count = 0; + solaxX1_send_retry = 12; + } + } // end hasAddress && (data_ready || solaxX1_send_retry == 0) + else + { + if ((solaxX1_nodata_count % 4) == 0) { DEBUG_SENSOR_LOG(PSTR("SX1: No Data count: %d"), solaxX1_nodata_count); } + if (solaxX1_nodata_count < 10 * 4) // max. seconds without data + { + solaxX1_nodata_count++; + } + else if (255 != solaxX1_nodata_count) + { + // no data from RS485, reset values to 0 and set inverter as offline + solaxX1_nodata_count = 255; + solaxX1_send_retry = 12; + protocolStatus.status = 0b00001000; // queryOffline + Energy.data_valid[0] = ENERGY_WATCHDOG; + + solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.dc1_power = 0; + solaxX1.dc2_power = solaxX1.status = Energy.current[0] = Energy.voltage[0] = Energy.frequency[0] = Energy.active_power[0] = 0; + //solaxX1.energy_today = solaxX1.energy_total = solaxX1.runtime_total = 0; + } + } + + if (!protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) + { + if (data_ready) + { + // check address confirmation from inverter + if (protocolStatus.inverterAddressSend) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Address confirmation response CRC error")); + } + else + { + if (value[6] == 0x10 && value[7] == 0x81 && value[9] == 0x06) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Set hasAddress")); + protocolStatus.status = 0b00100000; // hasAddress + } + } + } + + // Check inverter serial number and send the set address request + if (protocolStatus.queryOfflineSend) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline response CRC error")); + } + else + { + // Serial number from query response + if (value[6] == 0x10 && value[7] == 0x80 && protocolStatus.inverterSnReceived == false) + { + for (uint8_t i = 9; i <= 22; i++) + { + data[i - 9] = value[i]; + } + solaxX1_SendInverterAddress(); + protocolStatus.status = 0b1100000; // inverterSnReceived and inverterAddressSend + DEBUG_SENSOR_LOG(PSTR("SX1: Set inverterSnReceived and inverterAddressSend")); + } + } + } + } // End data ready + + if (solaxX1_send_retry == 0) + { + if (protocolStatus.queryOfflineSend) + { + protocolStatus.status = 0b00001000; // queryOffline + DEBUG_SENSOR_LOG(PSTR("SX1: Set Query Offline")); + } + solaxX1_send_retry = 12; + } + + // request to the inverter the serial number if offline + if (protocolStatus.queryOffline) + { + // We sent the message to query inverters in offline status + source[0] = 0x01; + destination[1] = 0x00; + controlCode[0] = 0x10; + functionCode[0] = 0x00; + dataLength[0] = 0x00; + solaxX1_RS485Send(9); + protocolStatus.status = 0b00010000; // queryOfflineSend + DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline Send")); + } + } // end !hasAddress && (data_ready || solaxX1_send_retry == 0) + + if (!data_ready) + solaxX1_send_retry--; +} + +void solaxX1SnsInit(void) +{ + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SX1: Solax X1 Inverter Init")); + DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX]); + protocolStatus.status = 0b00100000; // hasAddress + + solaxX1Serial = new TasmotaSerial(pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX], 1); + if (solaxX1Serial->begin(SOLAXX1_SPEED)) + { + if (solaxX1Serial->hardwareSerial()) { ClaimSerial(); } + }else { + energy_flg = ENERGY_NONE; + } +} + +void solaxX1DrvInit(void) +{ + if ((pin[GPIO_SOLAXX1_RX] < 99) && (pin[GPIO_SOLAXX1_TX] < 99)) { + energy_flg = XNRG_12; + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_solaxX1_DATA1[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_SOLAR_POWER "{m}%s " D_UNIT_WATT "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_POWER "{m}%s " D_UNIT_WATT "{e}"; +#ifdef SOLAXX1_PV2 +const char HTTP_SNS_solaxX1_DATA2[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_PV2_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}" D_SOLAX_X1 " " D_PV2_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}"; +#endif +const char HTTP_SNS_solaxX1_DATA3[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%s " D_UNIT_HOUR "{e}" + "{s}" D_SOLAX_X1 " " D_STATUS "{m}%s" + "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s"; +#endif // USE_WEBSERVER + +void solaxX1Show(bool json) +{ + char solar_power[33]; + dtostrfd(solaxX1.dc1_power + solaxX1.dc2_power, Settings.flag2.wattage_resolution, solar_power); + char pv1_voltage[33]; + dtostrfd(solaxX1.dc1_voltage, Settings.flag2.voltage_resolution, pv1_voltage); + char pv1_current[33]; + dtostrfd(solaxX1.dc1_current, Settings.flag2.current_resolution, pv1_current); + char pv1_power[33]; + dtostrfd(solaxX1.dc1_power, Settings.flag2.wattage_resolution, pv1_power); +#ifdef SOLAXX1_PV2 + char pv2_voltage[33]; + dtostrfd(solaxX1.dc2_voltage, Settings.flag2.voltage_resolution, pv2_voltage); + char pv2_current[33]; + dtostrfd(solaxX1.dc2_current, Settings.flag2.current_resolution, pv2_current); + char pv2_power[33]; + dtostrfd(solaxX1.dc2_power, Settings.flag2.wattage_resolution, pv2_power); +#endif + char temperature[33]; + dtostrfd(solaxX1.temperature, Settings.flag2.temperature_resolution, temperature); + char runtime[33]; + dtostrfd(solaxX1.runtime_total, 0, runtime); + char status[33]; + GetTextIndexed(status, sizeof(status), solaxX1.status, kSolaxMode); + + if (json) + { + ResponseAppend_P(PSTR(",\"" D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"), + solar_power, pv1_voltage, pv1_current, pv1_power); +#ifdef SOLAXX1_PV2 + ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), + pv2_voltage, pv2_current, pv2_power); +#endif + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"), + temperature, runtime, status, solaxX1.errorCode); + +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_SNS_solaxX1_DATA1, solar_power, pv1_voltage, pv1_current, pv1_power); +#ifdef SOLAXX1_PV2 + WSContentSend_PD(HTTP_SNS_solaxX1_DATA2, pv2_voltage, pv2_current, pv2_power); +#endif + WSContentSend_PD(HTTP_SNS_TEMP, D_SOLAX_X1, temperature, TempUnit()); + char errorCodeString[33]; + WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, runtime, status, + GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError)); +#endif // USE_WEBSERVER + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xnrg12(uint8_t function) +{ + bool result = false; + + switch (function) + { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { solaxX1250MSecond(); } + break; + case FUNC_INIT: + solaxX1SnsInit(); + break; + case FUNC_PRE_INIT: + solaxX1DrvInit(); + break; + case FUNC_JSON_APPEND: + solaxX1Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + solaxX1Show(0); + break; +#endif // USE_WEBSERVER + } + return result; +} + +#endif // USE_SOLAX_X1_NRG +#endif // USE_ENERGY_SENSOR \ No newline at end of file diff --git a/sonoff/xsns_49_solaxX1.ino b/sonoff/xsns_49_solaxX1.ino index 72583484f..059017e49 100644 --- a/sonoff/xsns_49_solaxX1.ino +++ b/sonoff/xsns_49_solaxX1.ino @@ -94,30 +94,39 @@ TasmotaSerial *solaxX1Serial; uint8_t solaxX1_Init = 1; -uint8_t solaxX1_status = 0; -uint32_t solaxX1_errorCode = 0; +struct SOLAXX1 { + float temperature = 0; + float energy_today = 0; + float dc1_voltage = 0; + float dc2_voltage = 0; + float dc1_current = 0; + float dc2_current = 0; + float ac_current = 0; + float ac_voltage = 0; + float frequency = 0; + float power = 0; + float energy_total = 0; + float runtime_total = 0; + float dc1_power = 0; + float dc2_power = 0; -float solaxX1_temperature = 0; -float solaxX1_energy_today = 0; -float solaxX1_dc1_voltage = 0; -float solaxX1_dc2_voltage = 0; -float solaxX1_dc1_current = 0; -float solaxX1_dc2_current = 0; -float solaxX1_ac_current = 0; -float solaxX1_ac_voltage = 0; -float solaxX1_frequency = 0; -float solaxX1_power = 0; -float solaxX1_energy_total = 0; -float solaxX1_runtime_total = 0; + uint8_t status = 0; + uint32_t errorCode = 0; +} solaxX1; -float solaxX1_dc1_power = 0; -float solaxX1_dc2_power = 0; - -bool queryOffline = false; -bool queryOfflineSend = false; -bool hasAddress = true; -bool inverterAddressSend = false; -bool inverterSnReceived = false; +union { + uint8_t status; + struct { + uint8_t freeBit7:1; // Bit7 + uint8_t freeBit6:1; // Bit6 + uint8_t freeBit5:1; // Bit5 + uint8_t queryOffline:1; // Bit4 + uint8_t queryOfflineSend:1; // Bit3 + uint8_t hasAddress:1; // Bit2 + uint8_t inverterAddressSend:1; // Bit1 + uint8_t inverterSnReceived:1; // Bit0 + }; +} protocolStatus; uint8_t header[2] = {0xAA, 0x55}; uint8_t source[2] = {0x00, 0x00}; @@ -136,10 +145,16 @@ bool solaxX1_RS485ReceiveReady(void) return (solaxX1Serial->available() > 1); } -void solaxX1_RS485Send(uint8_t *msg, uint16_t msgLen) +void solaxX1_RS485Send(uint16_t msgLen) { - - uint16_t crc = solaxX1_calculateCRC(msg, msgLen - 1); // calculate out crc bytes + memcpy(message, header, 2); + memcpy(message + 2, source, 2); + memcpy(message + 4, destination, 2); + memcpy(message + 6, controlCode, 1); + memcpy(message + 7, functionCode, 1); + memcpy(message + 8, dataLength, 1); + memcpy(message + 9, data, sizeof(data)); + uint16_t crc = solaxX1_calculateCRC(message, msgLen); // calculate out crc bytes while (solaxX1Serial->available() > 0) { // read serial if any old data is available @@ -147,9 +162,10 @@ void solaxX1_RS485Send(uint8_t *msg, uint16_t msgLen) } solaxX1Serial->flush(); - solaxX1Serial->write(msg, msgLen); + solaxX1Serial->write(message, msgLen); solaxX1Serial->write(highByte(crc)); solaxX1Serial->write(lowByte(crc)); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, message, msgLen); } uint8_t solaxX1_RS485Receive(uint8_t *value) @@ -161,7 +177,8 @@ uint8_t solaxX1_RS485Receive(uint8_t *value) value[len++] = (uint8_t)solaxX1Serial->read(); } - uint16_t crc = solaxX1_calculateCRC(value, len - 3); // calculate out crc bytes + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, value, len); + uint16_t crc = solaxX1_calculateCRC(value, len - 2); // calculate out crc bytes if (value[len - 1] == lowByte(crc) && value[len - 2] == highByte(crc)) { // check calc crc with received crc @@ -179,24 +196,13 @@ uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) uint16_t wChkSum; wChkSum = 0; - for (i = 0; i <= bLen; i++) + for (i = 0; i < bLen; i++) { wChkSum = wChkSum + bExternTxPackage[i]; } return wChkSum; } -void solaxX1_setMessage(uint8_t *message) -{ - memcpy(message, header, 2); - memcpy(message + 2, source, 2); - memcpy(message + 4, destination, 2); - memcpy(message + 6, controlCode, 1); - memcpy(message + 7, functionCode, 1); - memcpy(message + 8, dataLength, 1); - memcpy(message + 9, data, sizeof(data)); -} - void solaxX1_SendInverterAddress() { source[0] = 0x00; @@ -205,12 +211,8 @@ void solaxX1_SendInverterAddress() controlCode[0] = 0x10; functionCode[0] = 0x01; dataLength[0] = 0x0F; - - // Inverter Address, It must be unique in case of more inverters in the same rs485 net. - data[14] = INVERTER_ADDRESS; - - solaxX1_setMessage(message); - solaxX1_RS485Send(message, 24); + data[14] = INVERTER_ADDRESS; // Inverter Address, It must be unique in case of more inverters in the same rs485 net. + solaxX1_RS485Send(24); } void solaxX1_QueryLiveData() @@ -221,9 +223,7 @@ void solaxX1_QueryLiveData() controlCode[0] = 0x11; functionCode[0] = 0x02; dataLength[0] = 0x00; - - solaxX1_setMessage(message); - solaxX1_RS485Send(message, 9); + solaxX1_RS485Send(9); } uint8_t solaxX1_ParseErrorCode(uint32_t code){ @@ -245,22 +245,95 @@ uint8_t solaxX1_ParseErrorCode(uint32_t code){ uint8_t solaxX1_send_retry = 0; uint8_t solaxX1_nodata_count = 0; -void solaxX1_Update(void) // Every Second +void solaxX1EverySecond(void) // Every Second { uint8_t value[61] = {0}; - bool data_ready = solaxX1_RS485ReceiveReady(); - DEBUG_SENSOR_LOG(PSTR("SX1: queryOffline: %d , queryOfflineSend: %d, hasAddress: %d, inverterAddressSend: %d, solaxX1_send_retry: %d"), - queryOffline, queryOfflineSend, hasAddress, inverterAddressSend, solaxX1_send_retry); + if (protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) + { + if (data_ready) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error")); + } + else + { + solaxX1_nodata_count = 0; + solaxX1_send_retry = 3; - if (!hasAddress && (data_ready || solaxX1_send_retry == 0)) + solaxX1.temperature = (float)((value[9] << 8) | value[10]); // Temperature + solaxX1.energy_today = (float)((value[11] << 8) | value[12]) * 0.1f; // Energy Today + solaxX1.dc1_voltage = (float)((value[13] << 8) | value[14]) * 0.1f; // PV1 Voltage + solaxX1.dc2_voltage = (float)((value[15] << 8) | value[16]) * 0.1f; // PV2 Voltage + solaxX1.dc1_current = (float)((value[17] << 8) | value[18]) * 0.1f; // PV1 Current + solaxX1.dc2_current = (float)((value[19] << 8) | value[20]) * 0.1f; // PV2 Current + solaxX1.ac_current = (float)((value[21] << 8) | value[22]) * 0.1f; // AC Current + solaxX1.ac_voltage = (float)((value[23] << 8) | value[24]) * 0.1f; // AC Voltage + solaxX1.frequency = (float)((value[25] << 8) | value[26]) * 0.01f; // AC Frequency + solaxX1.power = (float)((value[27] << 8) | value[28]); // AC Power + //temporal = (float)((value[29] << 8) | value[30]) * 0.1f; // Not Used + solaxX1.energy_total = (float)((value[31] << 8) | (value[32] << 8) | (value[33] << 8) | value[34]) * 0.1f; // Energy Total + solaxX1.runtime_total = (float)((value[35] << 8) | (value[36] << 8) | (value[37] << 8) | value[38]); // Work Time Total + solaxX1.status = (uint8_t)((value[39] << 8) | value[40]); // Work mode + //temporal = (float)((value[41] << 8) | value[42]); // Grid voltage fault value 0.1V + //temporal = (float)((value[43] << 8) | value[44]); // Gird frequency fault value 0.01Hz + //temporal = (float)((value[45] << 8) | value[46]); // Dc injection fault value 1mA + //temporal = (float)((value[47] << 8) | value[48]); // Temperature fault value + //temporal = (float)((value[49] << 8) | value[50]); // Pv1 voltage fault value 0.1V + //temporal = (float)((value[51] << 8) | value[52]); // Pv2 voltage fault value 0.1V + //temporal = (float)((value[53] << 8) | value[54]); // GFC fault value + solaxX1.errorCode = (uint32_t)((value[58] << 8) | (value[57] << 8) | (value[56] << 8) | value[55]); // Error Code + + solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current; + solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current; + + solaxX1_QueryLiveData(); + } + } // End data Ready + + if (0 == solaxX1_send_retry && 255 != solaxX1_nodata_count) { + solaxX1_send_retry = 3; + solaxX1_QueryLiveData(); + } + + // While the inverter has not stable ambient light, will send an address adquired but go offline again, + // so no data will be received when the query is send, then we start the countdown to set the inverter as offline again. + if (255 == solaxX1_nodata_count) { + solaxX1_nodata_count = 0; + solaxX1_send_retry = 3; + } + } // end hasAddress && (data_ready || solaxX1_send_retry == 0) + else { + DEBUG_SENSOR_LOG(PSTR("SX1: No Data count: %d"), solaxX1_nodata_count); + + if (solaxX1_nodata_count < 10) // max. seconds without data + { + solaxX1_nodata_count++; + } + else if (255 != solaxX1_nodata_count) + { + // no data from RS485, reset values to 0 and set inverter as offline + solaxX1_nodata_count = 255; + solaxX1_send_retry = 3; + protocolStatus.status = 0b00001000; // queryOffline + + solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.ac_current = 0; + solaxX1.ac_voltage = solaxX1.frequency = solaxX1.power = solaxX1.dc1_power = solaxX1.dc2_power = solaxX1.status = 0; + //solaxX1.energy_today = solaxX1.energy_total = solaxX1.runtime_total = 0; + } + } + + if (!protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) + { if (data_ready) { // check address confirmation from inverter - if (inverterAddressSend) + if (protocolStatus.inverterAddressSend) { uint8_t error = solaxX1_RS485Receive(value); if (error) @@ -271,15 +344,14 @@ void solaxX1_Update(void) // Every Second { if (value[6] == 0x10 && value[7] == 0x81 && value[9] == 0x06) { - inverterAddressSend = false; - queryOfflineSend = false; - hasAddress = true; + DEBUG_SENSOR_LOG(PSTR("SX1: Set hasAddress")); + protocolStatus.status = 0b00100000; // hasAddress } } } // Check inverter serial number and send the set address request - if (queryOfflineSend) + if (protocolStatus.queryOfflineSend) { uint8_t error = solaxX1_RS485Receive(value); if (error) @@ -289,26 +361,32 @@ void solaxX1_Update(void) // Every Second else { // Serial number from query response - if (value[6] == 0x10 && value[7] == 0x80 && inverterSnReceived == false) + if (value[6] == 0x10 && value[7] == 0x80 && protocolStatus.inverterSnReceived == false) { for (uint8_t i = 9; i <= 22; i++) { data[i - 9] = value[i]; } - inverterSnReceived = true; + solaxX1_SendInverterAddress(); + protocolStatus.status = 0b1100000; // inverterSnReceived and inverterAddressSend + DEBUG_SENSOR_LOG(PSTR("SX1: Set inverterSnReceived and inverterAddressSend")); } - - solaxX1_SendInverterAddress(); - - inverterAddressSend = true; - queryOfflineSend = false; - queryOffline = false; } } + } // End data ready + + if (solaxX1_send_retry == 0) + { + if (protocolStatus.queryOfflineSend) + { + protocolStatus.status = 0b00001000; // queryOffline + DEBUG_SENSOR_LOG(PSTR("SX1: Set Query Offline")); + } + solaxX1_send_retry = 3; } // request to the inverter the serial number if offline - if (queryOffline) + if (protocolStatus.queryOffline) { // We sent the message to query inverters in offline status source[0] = 0x01; @@ -316,139 +394,12 @@ void solaxX1_Update(void) // Every Second controlCode[0] = 0x10; functionCode[0] = 0x00; dataLength[0] = 0x00; - - solaxX1_setMessage(message); - solaxX1_RS485Send(message, 9); - - queryOfflineSend = true; - queryOffline = false; + solaxX1_RS485Send(9); + protocolStatus.status = 0b00010000; // queryOfflineSend + DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline Send")); } - - if (solaxX1_send_retry == 0) - { - - if (inverterAddressSend) - { - solaxX1_SendInverterAddress(); - } - if (queryOfflineSend) - { - queryOffline = true; - queryOfflineSend = false; - } - solaxX1_send_retry = 2; - } - } // end !hasAddress && (data_ready || solaxX1_send_retry == 0) - if (hasAddress && (data_ready || solaxX1_send_retry == 0)) - { - - if (data_ready) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error")); - } - else - { -// AddLogBuffer(LOG_LEVEL_DEBUG, value, sizeof(value)); - - solaxX1_nodata_count = 0; - solaxX1_send_retry = 2; - uint32_t temporal = 0; - - temporal = (value[9] << 8) | value[10]; // Temperature - solaxX1_temperature = temporal; - - temporal = (value[11] << 8) | value[12]; // Energy Today - solaxX1_energy_today = temporal * 0.1f; - - temporal = (value[13] << 8) | value[14]; // PV1 Voltage - solaxX1_dc1_voltage = temporal * 0.1f; - - temporal = (value[15] << 8) | value[16]; // PV2 Voltage - solaxX1_dc2_voltage = temporal * 0.1f; - - temporal = (value[17] << 8) | value[18]; // PV1 Current - solaxX1_dc1_current = temporal * 0.1f; - - temporal = (value[19] << 8) | value[20]; // PV2 Current - solaxX1_dc2_current = temporal * 0.1f; - - temporal = (value[21] << 8) | value[22]; // AC Current - solaxX1_ac_current = temporal * 0.1f; - - temporal = (value[23] << 8) | value[24]; // AC Voltage - solaxX1_ac_voltage = temporal * 0.1f; - - temporal = (value[25] << 8) | value[26]; // AC Frequency - solaxX1_frequency = temporal * 0.01f; - - temporal = (value[27] << 8) | value[28]; // AC Power - solaxX1_power = temporal; - - //temporal = (value[29] << 8) | value[30]; // Not Used - //solaxX1_notused = temporal * 0.1f; - - temporal = (value[31] << 8) | (value[32] << 8) | (value[33] << 8) | value[34]; // Energy Total - solaxX1_energy_total = temporal * 0.1f; - - temporal = (value[35] << 8) | (value[36] << 8) | (value[37] << 8) | value[38]; // Work Time Total - solaxX1_runtime_total = temporal; - - temporal = (value[39] << 8) | value[40]; // Work mode - solaxX1_status = (uint8_t)temporal; - - //temporal = (value[41] << 8) | value[42]; // Grid voltage fault value 0.1V - //temporal = (value[43] << 8) | value[44]; // Gird frequency fault value 0.01Hz - //temporal = (value[45] << 8) | value[46]; // Dc injection fault value 1mA - //temporal = (value[47] << 8) | value[48]; // Temperature fault value - //temporal = (value[49] << 8) | value[50]; // Pv1 voltage fault value 0.1V - //temporal = (value[51] << 8) | value[52]; // Pv2 voltage fault value 0.1V - //temporal = (value[53] << 8) | value[54]; // GFC fault value - - temporal = (value[58] << 8) | (value[57] << 8) | (value[56] << 8) | value[55]; // Error Code - solaxX1_errorCode = (uint32_t)temporal; - - solaxX1_dc1_power = solaxX1_dc1_voltage * solaxX1_dc1_current; - solaxX1_dc2_power = solaxX1_dc2_voltage * solaxX1_dc2_current; - - solaxX1_QueryLiveData(); - } // end else no error - } - - if (solaxX1_send_retry == 0) - { - solaxX1_send_retry = 2; - solaxX1_QueryLiveData(); - } - } - else - { // end hasAddress && (data_ready || solaxX1_send_retry == 0) - - if (solaxX1_nodata_count <= 10) // max. 10 sec without data - { - solaxX1_nodata_count++; - } - else if (solaxX1_nodata_count != 255) - { - // no data from RS485, reset values to 0 - solaxX1_nodata_count = 255; - queryOffline = true; - queryOfflineSend = false; - hasAddress = false; - inverterAddressSend = false; - inverterSnReceived = false; - - solaxX1_temperature = solaxX1_dc1_voltage = solaxX1_dc2_voltage = solaxX1_dc1_current = solaxX1_dc2_current = solaxX1_ac_current = 0; - solaxX1_ac_voltage = solaxX1_frequency = solaxX1_power = solaxX1_dc1_power = solaxX1_dc2_power = solaxX1_status = 0; - - //solaxX1_energy_today = solaxX1_energy_total = solaxX1_runtime_total = 0; - } - } - if (!data_ready) solaxX1_send_retry--; } @@ -458,6 +409,8 @@ void solaxX1Init(void) AddLog_P(LOG_LEVEL_DEBUG, PSTR("Solax X1 Inverter Init")); DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX]); solaxX1_Init = 0; + protocolStatus.status = 0b00100000; // hasAddress + if ((pin[GPIO_SOLAXX1_RX] < 99) && (pin[GPIO_SOLAXX1_TX] < 99)) { solaxX1Serial = new TasmotaSerial(pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX], 1); @@ -499,39 +452,39 @@ const char HTTP_SNS_solaxX1_DATA3[] PROGMEM = void solaxX1Show(bool json) { char voltage[33]; - dtostrfd(solaxX1_ac_voltage, Settings.flag2.voltage_resolution, voltage); + dtostrfd(solaxX1.ac_voltage, Settings.flag2.voltage_resolution, voltage); char current[33]; - dtostrfd(solaxX1_ac_current, Settings.flag2.current_resolution, current); + dtostrfd(solaxX1.ac_current, Settings.flag2.current_resolution, current); char inverter_power[33]; - dtostrfd(solaxX1_power, Settings.flag2.wattage_resolution, inverter_power); + dtostrfd(solaxX1.power, Settings.flag2.wattage_resolution, inverter_power); char solar_power[33]; - dtostrfd(solaxX1_dc1_power + solaxX1_dc2_power, Settings.flag2.wattage_resolution, solar_power); + dtostrfd(solaxX1.dc1_power + solaxX1.dc2_power, Settings.flag2.wattage_resolution, solar_power); char frequency[33]; - dtostrfd(solaxX1_frequency, Settings.flag2.frequency_resolution, frequency); + dtostrfd(solaxX1.frequency, Settings.flag2.frequency_resolution, frequency); char energy_total[33]; - dtostrfd(solaxX1_energy_total, Settings.flag2.energy_resolution, energy_total); + dtostrfd(solaxX1.energy_total, Settings.flag2.energy_resolution, energy_total); char energy_today[33]; - dtostrfd(solaxX1_energy_today, Settings.flag2.energy_resolution, energy_today); + dtostrfd(solaxX1.energy_today, Settings.flag2.energy_resolution, energy_today); char pv1_voltage[33]; - dtostrfd(solaxX1_dc1_voltage, Settings.flag2.voltage_resolution, pv1_voltage); + dtostrfd(solaxX1.dc1_voltage, Settings.flag2.voltage_resolution, pv1_voltage); char pv1_current[33]; - dtostrfd(solaxX1_dc1_current, Settings.flag2.current_resolution, pv1_current); + dtostrfd(solaxX1.dc1_current, Settings.flag2.current_resolution, pv1_current); char pv1_power[33]; - dtostrfd(solaxX1_dc1_power, Settings.flag2.wattage_resolution, pv1_power); + dtostrfd(solaxX1.dc1_power, Settings.flag2.wattage_resolution, pv1_power); #ifdef SOLAXX1_PV2 char pv2_voltage[33]; - dtostrfd(solaxX1_dc2_voltage, Settings.flag2.voltage_resolution, pv2_voltage); + dtostrfd(solaxX1.dc2_voltage, Settings.flag2.voltage_resolution, pv2_voltage); char pv2_current[33]; - dtostrfd(solaxX1_dc2_current, Settings.flag2.current_resolution, pv2_current); + dtostrfd(solaxX1.dc2_current, Settings.flag2.current_resolution, pv2_current); char pv2_power[33]; - dtostrfd(solaxX1_dc2_power, Settings.flag2.wattage_resolution, pv2_power); + dtostrfd(solaxX1.dc2_power, Settings.flag2.wattage_resolution, pv2_power); #endif char temperature[33]; - dtostrfd(solaxX1_temperature, Settings.flag2.temperature_resolution, temperature); + dtostrfd(solaxX1.temperature, Settings.flag2.temperature_resolution, temperature); char runtime[33]; - dtostrfd(solaxX1_runtime_total, 0, runtime); + dtostrfd(solaxX1.runtime_total, 0, runtime); char status[33]; - GetTextIndexed(status, sizeof(status), solaxX1_status, kSolaxMode); + GetTextIndexed(status, sizeof(status), solaxX1.status, kSolaxMode); if (json) { @@ -546,20 +499,20 @@ void solaxX1Show(bool json) pv2_voltage, pv2_current, pv2_power); #endif ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d}"), - temperature, runtime, status, solaxX1_errorCode); + temperature, runtime, status, solaxX1.errorCode); #ifdef USE_DOMOTICZ if (0 == tele_period) { char energy_total_chr[33]; - dtostrfd(solaxX1_energy_total * 1000, 1, energy_total_chr); + dtostrfd(solaxX1.energy_total * 1000, 1, energy_total_chr); DomoticzSensor(DZ_VOLTAGE, voltage); DomoticzSensor(DZ_CURRENT, current); // Only do the updates if the values are greater than 0, to avoid wrong data representation in domoticz - if (solaxX1_temperature > 0) DomoticzSensor(DZ_TEMP, temperature); - if (solaxX1_energy_total > 0) DomoticzSensorPowerEnergy((int)solaxX1_power, energy_total_chr); + if (solaxX1.temperature > 0) DomoticzSensor(DZ_TEMP, temperature); + if (solaxX1.energy_total > 0) DomoticzSensorPowerEnergy((int)solaxX1.power, energy_total_chr); } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER @@ -573,7 +526,7 @@ void solaxX1Show(bool json) WSContentSend_PD(HTTP_SNS_TEMP, D_SOLAX_X1, temperature, TempUnit()); char errorCodeString[33]; WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, runtime, status, - GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1_errorCode), kSolaxError)); + GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError)); #endif // USE_WEBSERVER } } @@ -594,7 +547,7 @@ bool Xsns49(uint8_t function) solaxX1Init(); break; case FUNC_EVERY_SECOND: - solaxX1_Update(); + if (uptime > 4) { solaxX1EverySecond(); } break; case FUNC_JSON_APPEND: solaxX1Show(1); From d7279fa2aa0b0f853d3b983d30f7e6ec15369c06 Mon Sep 17 00:00:00 2001 From: pablozg Date: Thu, 17 Oct 2019 19:30:55 +0200 Subject: [PATCH 2163/2222] Solax X1: Delete all references to old driver --- sonoff/my_user_config.h | 5 +- sonoff/sonoff_post.h | 18 +- sonoff/sonoff_template.h | 10 +- sonoff/xnrg_12_solaxX1.ino | 2 +- sonoff/xsns_49_solaxX1.ino | 565 ------------------------------------- 5 files changed, 10 insertions(+), 590 deletions(-) delete mode 100644 sonoff/xsns_49_solaxX1.ino diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 9a9d70402..6df2203bc 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -457,7 +457,7 @@ #define DDS2382_SPEED 9600 // Hiking DDS2382 Modbus RS485 serial speed (default: 9600 baud) //#define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) #define DDSU666_SPEED 9600 // Chint DDSU666 Modbus RS485 serial speed (default: 9600 baud) -//#define USE_SOLAX_X1_NRG // Add support for Solax X1 series Modbus log info (+3k1 code) +//#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+3k1 code) #define SOLAXX1_SPEED 9600 // Solax X1 Modbus RS485 serial speed (default: 9600 baud) #define SOLAXX1_PV2 // Solax X1 using second PV @@ -466,9 +466,6 @@ #define USE_SDM220 // Add extra parameters for SDM220 (+0k1 code) //#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) // #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) -//#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+3k6 code) - #define SOLAXX1_SPEED 9600 // Solax X1 Modbus RS485 serial speed (default: 9600 baud) - #define SOLAXX1_PV2 // Solax X1 using second PV // -- Low level interface devices ----------------- #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor (1k6 code) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 15052711e..7e9df3143 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -189,10 +189,9 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_SDM630_2 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) #define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) -//#define USE_SOLAX_X1_NRG // Add support for Solax X1 series Modbus log info (+3k1 code) +//#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+3k1 code) //#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) //#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) -//#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+3k6 code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI @@ -295,10 +294,9 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) -#undef USE_SOLAX_X1_NRG // Disable support for Solax X1 series Modbus log info (+3k1 code) +#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k6 code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI @@ -378,10 +376,9 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) - #undef USE_SOLAX_X1_NRG // Disable support for Solax X1 series Modbus log info (+3k1 code) + #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k6 code) #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) #define USE_DISPLAY // Add I2C Display Support (+2k code) @@ -460,10 +457,9 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) - #undef USE_SOLAX_X1_NRG // Disable support for Solax X1 series Modbus log info (+3k1 code) + #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k6 code) #undef USE_DS18x20 // Disable support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) @@ -576,10 +572,9 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) -#undef USE_SOLAX_X1_NRG // Disable support for Solax X1 series Modbus log info (+3k1 code) +#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+4k1 code) #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI @@ -679,10 +674,9 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) -#undef USE_SOLAX_X1_NRG // Disable support for Solax X1 series Modbus log info (+3k1 code) +#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter -#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k6 code) #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 81c5f7657..925b053ee 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -650,10 +650,10 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_DDSU666_TX, // DDSU666 Serial interface GPIO_DDSU666_RX, // DDSU666 Serial interface #endif // USE_DDSU666 -#ifdef USE_SOLAX_X1_NRG +#ifdef USE_SOLAX_X1 GPIO_SOLAXX1_TX, // Solax Inverter tx pin GPIO_SOLAXX1_RX, // Solax Inverter rx pin -#endif // USE_SOLAX_X1_NRG +#endif // USE_SOLAX_X1 #endif // USE_ENERGY_SENSOR #ifndef USE_SDM120_2 #ifdef USE_SDM120 @@ -667,12 +667,6 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_SDM630_RX, // SDM630 Serial interface #endif #endif // USE_SDM630_2 -#ifndef USE_SOLAX_X1_NRG -#ifdef USE_SOLAX_X1 - GPIO_SOLAXX1_TX, // Solax Inverter tx pin - GPIO_SOLAXX1_RX, // Solax Inverter rx pin -#endif -#endif // USE_SOLAX_X1_NRG #ifdef USE_SERIAL_BRIDGE GPIO_SBR_TX, // Serial Bridge Serial interface diff --git a/sonoff/xnrg_12_solaxX1.ino b/sonoff/xnrg_12_solaxX1.ino index 0bd67ec4d..a505d1a93 100644 --- a/sonoff/xnrg_12_solaxX1.ino +++ b/sonoff/xnrg_12_solaxX1.ino @@ -18,7 +18,7 @@ */ #ifdef USE_ENERGY_SENSOR -#ifdef USE_SOLAX_X1_NRG +#ifdef USE_SOLAX_X1 /*********************************************************************************************\ * Solax X1 Inverter \*********************************************************************************************/ diff --git a/sonoff/xsns_49_solaxX1.ino b/sonoff/xsns_49_solaxX1.ino deleted file mode 100644 index 059017e49..000000000 --- a/sonoff/xsns_49_solaxX1.ino +++ /dev/null @@ -1,565 +0,0 @@ -/* - xsns_48_solaxX1.ino - Solax X1 inverter RS485 support for Sonoff-Tasmota - - Copyright (C) 2019 Pablo Zerón - - 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_SOLAX_X1 -/*********************************************************************************************\ - * Solax X1 Inverter -\*********************************************************************************************/ - -#define XSNS_49 49 - -#ifndef SOLAXX1_SPEED -#define SOLAXX1_SPEED 9600 // default solax rs485 speed -#endif - -#define INVERTER_ADDRESS 0x0A - -#define D_SOLAX_X1 "SolaxX1" - -#include - -enum solaxX1_Error -{ - solaxX1_ERR_NO_ERROR, - solaxX1_ERR_CRC_ERROR -}; - -union { - uint32_t ErrMessage; - struct { - //BYTE0 - uint8_t TzProtectFault:1;//0 - uint8_t MainsLostFault:1;//1 - uint8_t GridVoltFault:1;//2 - uint8_t GridFreqFault:1;//3 - uint8_t PLLLostFault:1;//4 - uint8_t BusVoltFault:1;//5 - uint8_t ErrBit06:1;//6 - uint8_t OciFault:1;//7 - //BYTE1 - uint8_t Dci_OCP_Fault:1;//8 - uint8_t ResidualCurrentFault:1;//9 - uint8_t PvVoltFault:1;//10 - uint8_t Ac10Mins_Voltage_Fault:1;//11 - uint8_t IsolationFault:1;//12 - uint8_t TemperatureOverFault:1;//13 - uint8_t FanFault:1;//14 - uint8_t ErrBit15:1;//15 - //BYTE2 - uint8_t SpiCommsFault:1;//16 - uint8_t SciCommsFault:1;//17 - uint8_t ErrBit18:1;//18 - uint8_t InputConfigFault:1;//19 - uint8_t EepromFault:1;//20 - uint8_t RelayFault:1;//21 - uint8_t SampleConsistenceFault:1;//22 - uint8_t ResidualCurrent_DeviceFault:1;//23 - //BYTE3 - uint8_t ErrBit24:1;//24 - uint8_t ErrBit25:1;//25 - uint8_t ErrBit26:1;//26 - uint8_t ErrBit27:1;//27 - uint8_t ErrBit28:1;//28 - uint8_t DCI_DeviceFault:1;//29 - uint8_t OtherDeviceFault:1;//30 - uint8_t ErrBit31:1;//31 - }; -} ErrCode; - -const char kSolaxMode[] PROGMEM = D_WAITING "|" D_CHECKING "|" D_WORKING "|" D_FAILURE; - -const char kSolaxError[] PROGMEM = - D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|" - D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8; - -/*********************************************************************************************/ - -TasmotaSerial *solaxX1Serial; - -uint8_t solaxX1_Init = 1; - -struct SOLAXX1 { - float temperature = 0; - float energy_today = 0; - float dc1_voltage = 0; - float dc2_voltage = 0; - float dc1_current = 0; - float dc2_current = 0; - float ac_current = 0; - float ac_voltage = 0; - float frequency = 0; - float power = 0; - float energy_total = 0; - float runtime_total = 0; - float dc1_power = 0; - float dc2_power = 0; - - uint8_t status = 0; - uint32_t errorCode = 0; -} solaxX1; - -union { - uint8_t status; - struct { - uint8_t freeBit7:1; // Bit7 - uint8_t freeBit6:1; // Bit6 - uint8_t freeBit5:1; // Bit5 - uint8_t queryOffline:1; // Bit4 - uint8_t queryOfflineSend:1; // Bit3 - uint8_t hasAddress:1; // Bit2 - uint8_t inverterAddressSend:1; // Bit1 - uint8_t inverterSnReceived:1; // Bit0 - }; -} protocolStatus; - -uint8_t header[2] = {0xAA, 0x55}; -uint8_t source[2] = {0x00, 0x00}; -uint8_t destination[2] = {0x00, 0x00}; -uint8_t controlCode[1] = {0x00}; -uint8_t functionCode[1] = {0x00}; -uint8_t dataLength[1] = {0x00}; -uint8_t data[16] = {0}; - -uint8_t message[30]; - -/*********************************************************************************************/ - -bool solaxX1_RS485ReceiveReady(void) -{ - return (solaxX1Serial->available() > 1); -} - -void solaxX1_RS485Send(uint16_t msgLen) -{ - memcpy(message, header, 2); - memcpy(message + 2, source, 2); - memcpy(message + 4, destination, 2); - memcpy(message + 6, controlCode, 1); - memcpy(message + 7, functionCode, 1); - memcpy(message + 8, dataLength, 1); - memcpy(message + 9, data, sizeof(data)); - uint16_t crc = solaxX1_calculateCRC(message, msgLen); // calculate out crc bytes - - while (solaxX1Serial->available() > 0) - { // read serial if any old data is available - solaxX1Serial->read(); - } - - solaxX1Serial->flush(); - solaxX1Serial->write(message, msgLen); - solaxX1Serial->write(highByte(crc)); - solaxX1Serial->write(lowByte(crc)); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, message, msgLen); -} - -uint8_t solaxX1_RS485Receive(uint8_t *value) -{ - uint8_t len = 0; - - while (solaxX1Serial->available() > 0) - { - value[len++] = (uint8_t)solaxX1Serial->read(); - } - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, value, len); - uint16_t crc = solaxX1_calculateCRC(value, len - 2); // calculate out crc bytes - - if (value[len - 1] == lowByte(crc) && value[len - 2] == highByte(crc)) - { // check calc crc with received crc - return solaxX1_ERR_NO_ERROR; - } - else - { - return solaxX1_ERR_CRC_ERROR; - } -} - -uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) -{ - uint8_t i; - uint16_t wChkSum; - wChkSum = 0; - - for (i = 0; i < bLen; i++) - { - wChkSum = wChkSum + bExternTxPackage[i]; - } - return wChkSum; -} - -void solaxX1_SendInverterAddress() -{ - source[0] = 0x00; - destination[0] = 0x00; - destination[1] = 0x00; - controlCode[0] = 0x10; - functionCode[0] = 0x01; - dataLength[0] = 0x0F; - data[14] = INVERTER_ADDRESS; // Inverter Address, It must be unique in case of more inverters in the same rs485 net. - solaxX1_RS485Send(24); -} - -void solaxX1_QueryLiveData() -{ - source[0] = 0x01; - destination[0] = 0x00; - destination[1] = INVERTER_ADDRESS; - controlCode[0] = 0x11; - functionCode[0] = 0x02; - dataLength[0] = 0x00; - solaxX1_RS485Send(9); -} - -uint8_t solaxX1_ParseErrorCode(uint32_t code){ - ErrCode.ErrMessage = code; - - if (code == 0) return 0; - if (ErrCode.MainsLostFault) return 1; - if (ErrCode.GridVoltFault) return 2; - if (ErrCode.GridFreqFault) return 3; - if (ErrCode.PvVoltFault) return 4; - if (ErrCode.IsolationFault) return 5; - if (ErrCode.TemperatureOverFault) return 6; - if (ErrCode.FanFault) return 7; - if (ErrCode.OtherDeviceFault) return 8; -} - -/*********************************************************************************************/ - -uint8_t solaxX1_send_retry = 0; -uint8_t solaxX1_nodata_count = 0; - -void solaxX1EverySecond(void) // Every Second -{ - uint8_t value[61] = {0}; - bool data_ready = solaxX1_RS485ReceiveReady(); - - if (protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) - { - if (data_ready) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error")); - } - else - { - solaxX1_nodata_count = 0; - solaxX1_send_retry = 3; - - solaxX1.temperature = (float)((value[9] << 8) | value[10]); // Temperature - solaxX1.energy_today = (float)((value[11] << 8) | value[12]) * 0.1f; // Energy Today - solaxX1.dc1_voltage = (float)((value[13] << 8) | value[14]) * 0.1f; // PV1 Voltage - solaxX1.dc2_voltage = (float)((value[15] << 8) | value[16]) * 0.1f; // PV2 Voltage - solaxX1.dc1_current = (float)((value[17] << 8) | value[18]) * 0.1f; // PV1 Current - solaxX1.dc2_current = (float)((value[19] << 8) | value[20]) * 0.1f; // PV2 Current - solaxX1.ac_current = (float)((value[21] << 8) | value[22]) * 0.1f; // AC Current - solaxX1.ac_voltage = (float)((value[23] << 8) | value[24]) * 0.1f; // AC Voltage - solaxX1.frequency = (float)((value[25] << 8) | value[26]) * 0.01f; // AC Frequency - solaxX1.power = (float)((value[27] << 8) | value[28]); // AC Power - //temporal = (float)((value[29] << 8) | value[30]) * 0.1f; // Not Used - solaxX1.energy_total = (float)((value[31] << 8) | (value[32] << 8) | (value[33] << 8) | value[34]) * 0.1f; // Energy Total - solaxX1.runtime_total = (float)((value[35] << 8) | (value[36] << 8) | (value[37] << 8) | value[38]); // Work Time Total - solaxX1.status = (uint8_t)((value[39] << 8) | value[40]); // Work mode - //temporal = (float)((value[41] << 8) | value[42]); // Grid voltage fault value 0.1V - //temporal = (float)((value[43] << 8) | value[44]); // Gird frequency fault value 0.01Hz - //temporal = (float)((value[45] << 8) | value[46]); // Dc injection fault value 1mA - //temporal = (float)((value[47] << 8) | value[48]); // Temperature fault value - //temporal = (float)((value[49] << 8) | value[50]); // Pv1 voltage fault value 0.1V - //temporal = (float)((value[51] << 8) | value[52]); // Pv2 voltage fault value 0.1V - //temporal = (float)((value[53] << 8) | value[54]); // GFC fault value - solaxX1.errorCode = (uint32_t)((value[58] << 8) | (value[57] << 8) | (value[56] << 8) | value[55]); // Error Code - - solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current; - solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current; - - solaxX1_QueryLiveData(); - } - } // End data Ready - - if (0 == solaxX1_send_retry && 255 != solaxX1_nodata_count) { - solaxX1_send_retry = 3; - solaxX1_QueryLiveData(); - } - - // While the inverter has not stable ambient light, will send an address adquired but go offline again, - // so no data will be received when the query is send, then we start the countdown to set the inverter as offline again. - if (255 == solaxX1_nodata_count) { - solaxX1_nodata_count = 0; - solaxX1_send_retry = 3; - } - } // end hasAddress && (data_ready || solaxX1_send_retry == 0) - else - { - - DEBUG_SENSOR_LOG(PSTR("SX1: No Data count: %d"), solaxX1_nodata_count); - - if (solaxX1_nodata_count < 10) // max. seconds without data - { - solaxX1_nodata_count++; - } - else if (255 != solaxX1_nodata_count) - { - // no data from RS485, reset values to 0 and set inverter as offline - solaxX1_nodata_count = 255; - solaxX1_send_retry = 3; - protocolStatus.status = 0b00001000; // queryOffline - - solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.ac_current = 0; - solaxX1.ac_voltage = solaxX1.frequency = solaxX1.power = solaxX1.dc1_power = solaxX1.dc2_power = solaxX1.status = 0; - //solaxX1.energy_today = solaxX1.energy_total = solaxX1.runtime_total = 0; - } - } - - if (!protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) - { - if (data_ready) - { - // check address confirmation from inverter - if (protocolStatus.inverterAddressSend) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Address confirmation response CRC error")); - } - else - { - if (value[6] == 0x10 && value[7] == 0x81 && value[9] == 0x06) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Set hasAddress")); - protocolStatus.status = 0b00100000; // hasAddress - } - } - } - - // Check inverter serial number and send the set address request - if (protocolStatus.queryOfflineSend) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline response CRC error")); - } - else - { - // Serial number from query response - if (value[6] == 0x10 && value[7] == 0x80 && protocolStatus.inverterSnReceived == false) - { - for (uint8_t i = 9; i <= 22; i++) - { - data[i - 9] = value[i]; - } - solaxX1_SendInverterAddress(); - protocolStatus.status = 0b1100000; // inverterSnReceived and inverterAddressSend - DEBUG_SENSOR_LOG(PSTR("SX1: Set inverterSnReceived and inverterAddressSend")); - } - } - } - } // End data ready - - if (solaxX1_send_retry == 0) - { - if (protocolStatus.queryOfflineSend) - { - protocolStatus.status = 0b00001000; // queryOffline - DEBUG_SENSOR_LOG(PSTR("SX1: Set Query Offline")); - } - solaxX1_send_retry = 3; - } - - // request to the inverter the serial number if offline - if (protocolStatus.queryOffline) - { - // We sent the message to query inverters in offline status - source[0] = 0x01; - destination[1] = 0x00; - controlCode[0] = 0x10; - functionCode[0] = 0x00; - dataLength[0] = 0x00; - solaxX1_RS485Send(9); - protocolStatus.status = 0b00010000; // queryOfflineSend - DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline Send")); - } - } // end !hasAddress && (data_ready || solaxX1_send_retry == 0) - - if (!data_ready) - solaxX1_send_retry--; -} - -void solaxX1Init(void) -{ - AddLog_P(LOG_LEVEL_DEBUG, PSTR("Solax X1 Inverter Init")); - DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX]); - solaxX1_Init = 0; - protocolStatus.status = 0b00100000; // hasAddress - - if ((pin[GPIO_SOLAXX1_RX] < 99) && (pin[GPIO_SOLAXX1_TX] < 99)) - { - solaxX1Serial = new TasmotaSerial(pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX], 1); - if (solaxX1Serial->begin(SOLAXX1_SPEED)) - { - if (solaxX1Serial->hardwareSerial()) - { - ClaimSerial(); - } - solaxX1_Init = 1; - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_solaxX1_DATA1[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}" - "{s}" D_SOLAX_X1 " " D_INVERTER_POWER "{m}%s " D_UNIT_WATT "{e}" - "{s}" D_SOLAX_X1 " " D_SOLAR_POWER "{m}%s " D_UNIT_WATT "{e}" - "{s}" D_SOLAX_X1 " " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_SOLAX_X1 " " D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_POWER "{m}%s " D_UNIT_WATT "{e}"; -#ifdef SOLAXX1_PV2 -const char HTTP_SNS_solaxX1_DATA2[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_PV2_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_PV2_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}"; -#endif -const char HTTP_SNS_solaxX1_DATA3[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%s " D_UNIT_HOUR "{e}" - "{s}" D_SOLAX_X1 " " D_STATUS "{m}%s" - "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s"; -#endif // USE_WEBSERVER - -void solaxX1Show(bool json) -{ - char voltage[33]; - dtostrfd(solaxX1.ac_voltage, Settings.flag2.voltage_resolution, voltage); - char current[33]; - dtostrfd(solaxX1.ac_current, Settings.flag2.current_resolution, current); - char inverter_power[33]; - dtostrfd(solaxX1.power, Settings.flag2.wattage_resolution, inverter_power); - char solar_power[33]; - dtostrfd(solaxX1.dc1_power + solaxX1.dc2_power, Settings.flag2.wattage_resolution, solar_power); - char frequency[33]; - dtostrfd(solaxX1.frequency, Settings.flag2.frequency_resolution, frequency); - char energy_total[33]; - dtostrfd(solaxX1.energy_total, Settings.flag2.energy_resolution, energy_total); - char energy_today[33]; - dtostrfd(solaxX1.energy_today, Settings.flag2.energy_resolution, energy_today); - char pv1_voltage[33]; - dtostrfd(solaxX1.dc1_voltage, Settings.flag2.voltage_resolution, pv1_voltage); - char pv1_current[33]; - dtostrfd(solaxX1.dc1_current, Settings.flag2.current_resolution, pv1_current); - char pv1_power[33]; - dtostrfd(solaxX1.dc1_power, Settings.flag2.wattage_resolution, pv1_power); -#ifdef SOLAXX1_PV2 - char pv2_voltage[33]; - dtostrfd(solaxX1.dc2_voltage, Settings.flag2.voltage_resolution, pv2_voltage); - char pv2_current[33]; - dtostrfd(solaxX1.dc2_current, Settings.flag2.current_resolution, pv2_current); - char pv2_power[33]; - dtostrfd(solaxX1.dc2_power, Settings.flag2.wattage_resolution, pv2_power); -#endif - char temperature[33]; - dtostrfd(solaxX1.temperature, Settings.flag2.temperature_resolution, temperature); - char runtime[33]; - dtostrfd(solaxX1.runtime_total, 0, runtime); - char status[33]; - GetTextIndexed(status, sizeof(status), solaxX1.status, kSolaxMode); - - if (json) - { - ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" - D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_TOTAL "\":%s,\"" D_JSON_TODAY "\":%s,\"" - D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"), - voltage, current, inverter_power, - solar_power, frequency, energy_total, energy_today, - pv1_voltage, pv1_current, pv1_power); -#ifdef SOLAXX1_PV2 - ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), - pv2_voltage, pv2_current, pv2_power); -#endif - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d}"), - temperature, runtime, status, solaxX1.errorCode); - - -#ifdef USE_DOMOTICZ - if (0 == tele_period) - { - char energy_total_chr[33]; - dtostrfd(solaxX1.energy_total * 1000, 1, energy_total_chr); - - DomoticzSensor(DZ_VOLTAGE, voltage); - DomoticzSensor(DZ_CURRENT, current); - // Only do the updates if the values are greater than 0, to avoid wrong data representation in domoticz - if (solaxX1.temperature > 0) DomoticzSensor(DZ_TEMP, temperature); - if (solaxX1.energy_total > 0) DomoticzSensorPowerEnergy((int)solaxX1.power, energy_total_chr); - } -#endif // USE_DOMOTICZ -#ifdef USE_WEBSERVER - } - else - { - WSContentSend_PD(HTTP_SNS_solaxX1_DATA1, voltage, current, frequency, inverter_power, solar_power, energy_total, energy_today, pv1_voltage, pv1_current, pv1_power); -#ifdef SOLAXX1_PV2 - WSContentSend_PD(HTTP_SNS_solaxX1_DATA2, pv2_voltage, pv2_current, pv2_power); -#endif - WSContentSend_PD(HTTP_SNS_TEMP, D_SOLAX_X1, temperature, TempUnit()); - char errorCodeString[33]; - WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, runtime, status, - GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError)); -#endif // USE_WEBSERVER - } -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xsns49(uint8_t function) -{ - bool result = false; - - if (solaxX1_Init) - { - switch (function) - { - case FUNC_INIT: - solaxX1Init(); - break; - case FUNC_EVERY_SECOND: - if (uptime > 4) { solaxX1EverySecond(); } - break; - case FUNC_JSON_APPEND: - solaxX1Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - solaxX1Show(0); - break; -#endif // USE_WEBSERVER - } - } - return result; -} - -#endif // USE_SOLAX_X1 \ No newline at end of file From 41cc74ea7b19931053480e9ab7c21ba525db6ac7 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Fri, 18 Oct 2019 09:31:59 +0200 Subject: [PATCH 2164/2222] Update xdrv_29_deepsleep.ino Added RESULT message before deepsleep to send via MQTT next Wakeup time in Local Time and UTC: 09:30:12 MQT: stat/sonoff/RESULT = {"Deepsleep":{"Time":"2019-10-18T09:35:00","Epoch":1571384100}} --- sonoff/xdrv_29_deepsleep.ino | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/sonoff/xdrv_29_deepsleep.ino b/sonoff/xdrv_29_deepsleep.ino index d48ffb31a..13706798b 100644 --- a/sonoff/xdrv_29_deepsleep.ino +++ b/sonoff/xdrv_29_deepsleep.ino @@ -66,9 +66,6 @@ void CheckForDeepsleep(void) // new function AFTER_TELEPERIOD can take some time therefore <2 if ((Settings.deepsleep > 10) && (Settings.deepsleep < 4294967295) && !disable_deepsleep_switch && (tele_period < 2) && prep_called) { SettingsSaveAll(); - Response_P(S_OFFLINE); - MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic - yield(); // deepsleep_slip is ideally 10.000 == 100% // typically the device has up to 4% slip. Anything else is a wrong setting in the deepsleep_slip // therefore all values >110% or <90% will be resetted to 100% to avoid crazy sleep times. @@ -102,16 +99,17 @@ void CheckForDeepsleep(void) // ensure nextwakeup is at least in the future RtcSettings.nextwakeup += (((UtcTime() + MIN_DEEPSLEEP_TIME - RtcSettings.nextwakeup) / Settings.deepsleep) + 1) * Settings.deepsleep; } - Response_P(PSTR("%d"), RtcSettings.nextwakeup); - MqttPublishPrefixTopic_P(TELE, PSTR(D_DOMOTICZ_UPDATE_TIMER), false); // Offline or remove previous retained topic - yield(); - MqttDisconnect(); String dt = GetDT(RtcSettings.nextwakeup + LocalTime() - UtcTime()); // 2017-03-07T11:08:02 // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("DSL: Next wakeup %s"), (char*)dt.c_str()); //limit sleeptime to MAX_DEEPSLEEP_CYCLE //uint32_t sleeptime = MAX_DEEPSLEEP_CYCLE < (RtcSettings.nextwakeup - UtcTime()) ? (uint32_t)MAX_DEEPSLEEP_CYCLE : RtcSettings.nextwakeup - UtcTime(); uint32_t sleeptime = tmin((uint32_t)MAX_DEEPSLEEP_CYCLE , RtcSettings.nextwakeup - UtcTime()); - + Response_P(PSTR("{\"" D_PRFX_DEEPSLEEP "\":{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%d}}"), (char*)dt.c_str(), RtcSettings.nextwakeup); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_STATUS "1"), false); + Response_P(S_OFFLINE); + MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic + yield(); + MqttDisconnect(); RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - UtcTime(); // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("DSL: Sleeptime %d sec, deepsleep_slip %ld"), sleeptime, RtcSettings.deepsleep_slip); RtcSettingsSave(); @@ -157,4 +155,4 @@ bool Xdrv29(uint8_t function) return result; } -#endif //USE_DEEPSLEEP \ No newline at end of file +#endif //USE_DEEPSLEEP From 3dfc954eb58db79d3b0fe3d289e1d8b28b864390 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 18 Oct 2019 10:03:06 +0200 Subject: [PATCH 2165/2222] Only Core pre 2.6.x for dev on thehackbox --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2f302d827..73cc67f32 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ See [sonoff/_changelog.ino](https://github.com/arendst/Sonoff-Tasmota/blob/devel Unless your Tasmota based device exhibits a problem or you need to make use of a feature that is not available in the Tasmota version currently installed on your device, leave your device alone - it works so don't make unnecessary changes! If the release version (i.e., the master branch) exhibits problems for your device and configuration, you should upgrade to the latest development version instead to see if your problem is resolved. -The Tasmota development codebase is checked every 1-2 hours for changes. If new commits have been merged and they compile successfuly, new binary files for every variant and Core will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA too). The last compiled commit number is also posted on the same page along with the current build status (if a firmware rebuild is in progress). It is important to note that these binaries are based on the current development codebase. These commits are tested as much as is possible and are typically quite stable. However, it is infeasible to test on the hundreds of different types of devices with the specific configurations that are permitted. +The Tasmota development codebase is checked every 1-2 hours for changes. If new commits have been merged and they compile successfuly, new binary files for every variant will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA too). The last compiled commit number is also posted on the same page along with the current build status (if a firmware rebuild is in progress). It is important to note that these binaries are based on the current development codebase. These commits are tested as much as is possible and are typically quite stable. However, it is infeasible to test on the hundreds of different types of devices with the specific configurations that are permitted. Note that there is a chance, as with any upgrade, that the device may not function as expected. You must always account for the possibility that you may need to flash the device via the serial programming interface if the OTA fails. Even with the master release, you should always attempt to test the device or a similar prototype before upgrading a device which is in production or is hard to reach. And, as always, make a backup of the device configuration before beginning any firmware update. From 672ea3d7e9f755d9d54150f6cd7c4dd2727cf26f Mon Sep 17 00:00:00 2001 From: Bastian Urschel Date: Fri, 18 Oct 2019 10:32:48 +0200 Subject: [PATCH 2166/2222] Fixes the funcionality of command "Sensor20" which was missing after merge #6673. With command "Sensor20" you can now set the starting offset at runtime. The polling interval still depends on the tele_period. --- sonoff/settings.h | 2 +- sonoff/settings.ino | 4 ++-- sonoff/xsns_20_novasds.ino | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 81fcfaac8..0edf3c73b 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -348,7 +348,7 @@ struct SYSCFG { uint8_t rgbwwTable[5]; // 71A uint8_t user_template_base; // 71F mytmplt user_template; // 720 29 bytes - uint8_t novasds_period; // 73D + uint8_t novasds_startingoffset; // 73D uint8_t web_color[18][3]; // 73E uint16_t display_width; // 774 uint16_t display_height; // 776 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 4cb4e5b0d..8cd67a610 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -849,7 +849,7 @@ void SettingsDefaultSet2(void) Settings.rgbwwTable[j] = 255; } - Settings.novasds_period = WORKING_PERIOD; + Settings.novasds_startingoffset = STARTING_OFFSET; SettingsDefaultWebColor(); @@ -1102,7 +1102,7 @@ void SettingsDelta(void) Settings.param[P_RGB_REMAP] = RGB_REMAP_RGBW; } if (Settings.version < 0x06050003) { - Settings.novasds_period = WORKING_PERIOD; + Settings.novasds_startingoffset = STARTING_OFFSET; } if (Settings.version < 0x06050006) { SettingsDefaultWebColor(); diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index a434e56a3..8e6dbd88d 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -151,7 +151,7 @@ void NovaSdsSecond(void) // Every second NovaSdsSetWorkPeriod(); novasds_valid=1; } - if((Settings.tele_period - STARTING_OFFSET <= 0)) + if((Settings.tele_period - Settings.novasds_startingoffset <= 0)) { if(!cont_mode) { //switched to continuous mode @@ -162,7 +162,7 @@ void NovaSdsSecond(void) // Every second else cont_mode = 0; - if(tele_period == Settings.tele_period - STARTING_OFFSET && !cont_mode) + if(tele_period == Settings.tele_period - Settings.novasds_startingoffset && !cont_mode) { //lets start fan and laser NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); } @@ -191,10 +191,10 @@ void NovaSdsSecond(void) // Every second bool NovaSdsCommandSensor(void) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 256)) { - Settings.novasds_period = XdrvMailbox.payload; - NovaSdsSetWorkPeriod(); + if( XdrvMailbox.payload < 10 ) Settings.novasds_startingoffset = 10; + else Settings.novasds_startingoffset = XdrvMailbox.payload; } - Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_20, Settings.novasds_period); + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_20, Settings.novasds_startingoffset); return true; } From a42515160f47cf04cdc329cad8703f7856d42b8f Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Fri, 18 Oct 2019 10:57:06 +0200 Subject: [PATCH 2167/2222] preserve some stack size on FUNC_EVERY_SECOND --- sonoff/sonoff.ino | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 3e198737a..b3f7ce0e3 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -838,8 +838,8 @@ void PerformEverySecond(void) } } - XdrvCall(FUNC_EVERY_SECOND); - XsnsCall(FUNC_EVERY_SECOND); + //XdrvCall(FUNC_EVERY_SECOND); + //XsnsCall(FUNC_EVERY_SECOND); } /*********************************************************************************************\ @@ -1682,6 +1682,10 @@ void loop(void) Every250mSeconds(); XdrvCall(FUNC_EVERY_250_MSECOND); XsnsCall(FUNC_EVERY_250_MSECOND); + if (!state_250mS) { + XdrvCall(FUNC_EVERY_SECOND); + XsnsCall(FUNC_EVERY_SECOND); + } } if (!serial_local) { SerialInput(); } From d989abfb45f8c80e08043fca67fc0fe44d8907d3 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Fri, 18 Oct 2019 11:33:52 +0200 Subject: [PATCH 2168/2222] refactor sendmail --- sonoff/WiFiClientSecureLightBearSSL.h | 2 +- sonoff/sendemail.h | 2 +- sonoff/sendemail.ino | 345 +++++++++++++++----------- sonoff/xdrv_01_webserver.ino | 146 ----------- 4 files changed, 207 insertions(+), 288 deletions(-) diff --git a/sonoff/WiFiClientSecureLightBearSSL.h b/sonoff/WiFiClientSecureLightBearSSL.h index 653c75502..5dd0df35e 100644 --- a/sonoff/WiFiClientSecureLightBearSSL.h +++ b/sonoff/WiFiClientSecureLightBearSSL.h @@ -24,7 +24,7 @@ #ifndef wificlientlightbearssl_h #define wificlientlightbearssl_h -#ifdef USE_MQTT_TLS +#if defined(USE_MQTT_TLS) || defined (USE_SENDMAIL) #include #include "WiFiClient.h" #include diff --git a/sonoff/sendemail.h b/sonoff/sendemail.h index 4b911c266..2422ad91f 100755 --- a/sonoff/sendemail.h +++ b/sonoff/sendemail.h @@ -31,7 +31,7 @@ class SendEmail int base64_encode(char *output, const char *input, int inputLen); public: SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used); - bool send(const String& from, const String& to, const String& subject, const String& msg); + bool send(const String& from, const String& to, const String& subject, const char *msg); ~SendEmail() {client->stop(); delete client;} }; diff --git a/sonoff/sendemail.ino b/sonoff/sendemail.ino index 3d4f59159..4a54c85e0 100755 --- a/sonoff/sendemail.ino +++ b/sonoff/sendemail.ino @@ -5,17 +5,183 @@ // enable serial debugging //#define DEBUG_EMAIL_PORT Serial +//SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const bool ssl); +//SendEmail::send(const String& from, const String& to, const String& subject, const String& msg) +// sendmail [server:port:user:passwd:from:to:subject] data +// sendmail [*:*:*:*:*:to:subject] data uses defines from user_config +// sendmail currently only works with core 2.4.2 +//HW Watchdog 8.44 sec. +//SW Watchdog 3.2 sec. + +#define SEND_MAIL_MINRAM 12*1024 + +uint16_t SendMail(char *buffer) { + uint16_t count; + char *params,*oparams; + char *mserv; + uint16_t port; + char *user; + char *pstr; + char *passwd; + char *from; + char *to; + char *subject; + char *cmd; + char secure=0,auth=0; + uint16_t status=1; + SendEmail *mail=0; + uint16_t blen; + char *endcmd; + + //DebugFreeMem(); + +// return if not enough memory + uint16_t mem=ESP.getFreeHeap(); + if (memsend(from,to,subject,cmd); + delete mail; + if (result==true) status=0; + } + +exit: + if (oparams) free(oparams); + return status; +} + + + + SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) : host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new BearSSL::WiFiClientSecure_light(1024,1024)) { } - - -String SendEmail::readClient() -{ +String SendEmail::readClient() { + delay(0); String r = client->readStringUntil('\n'); + r.trim(); while (client->available()) { delay(0); @@ -26,12 +192,15 @@ String SendEmail::readClient() //void SetSerialBaudrate(int baudrate); -bool SendEmail::send(const String& from, const String& to, const String& subject, const String& msg) +bool SendEmail::send(const String& from, const String& to, const String& subject, const char *msg) { - if (!host.length()) - { - return false; +bool status=false; +String buffer; + + if (!host.length()) { + return status; } + client->setTimeout(timeout); // smtp connect #ifdef DEBUG_EMAIL_PORT @@ -42,39 +211,22 @@ bool SendEmail::send(const String& from, const String& to, const String& subject DEBUG_EMAIL_PORT.println(port); #endif -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) -#else - //client->setInsecure(); - /* - bool mfln = client->probeMaxFragmentLength(host.c_str(), port, 512); -#ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.printf("MFLN supported: %s\n", mfln ? "yes" : "no"); -#endif - if (mfln) { - client->setBufferSizes(512, 512); - }*/ -#endif - - - if (!client->connect(host.c_str(), port)) - { + if (!client->connect(host.c_str(), port)) { #ifdef DEBUG_EMAIL_PORT DEBUG_EMAIL_PORT.println("Connection failed: "); //DEBUG_EMAIL_PORT.println (client->getLastSSLError()); #endif - return false; + goto exit; } - String buffer = readClient(); + buffer = readClient(); #ifdef DEBUG_EMAIL_PORT DEBUG_EMAIL_PORT.println(buffer); #endif - if (!buffer.startsWith(F("220"))) - { - return false; + if (!buffer.startsWith(F("220"))) { + goto exit; } - buffer = F("EHLO "); buffer += client->localIP().toString(); @@ -86,58 +238,14 @@ bool SendEmail::send(const String& from, const String& to, const String& subject #ifdef DEBUG_EMAIL_PORT DEBUG_EMAIL_PORT.println(buffer); #endif - if (!buffer.startsWith(F("250"))) - { - return false; + if (!buffer.startsWith(F("250"))) { + goto exit; } - if (user.length()>0 && passwd.length()>0 ) - { + if (user.length()>0 && passwd.length()>0 ) { //buffer = F("STARTTLS"); //client->println(buffer); -if (auth_used==1) { - // plain -#ifdef USE_PLAIN - buffer = F("AUTH PLAIN"); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); -#endif - if (!buffer.startsWith(F("334"))) - { - return false; - } - - char plainAuth[100]; - memset(plainAuth,sizeof(plainAuth),0); - plainAuth[0] = '\0'; - strcpy(&plainAuth[1], user.c_str()); - strcpy(&plainAuth[2+user.length()],passwd.c_str()); - const char* pA = (const char*)&plainAuth; - char buf[100]; - base64_encode(buf, pA, user.length()+passwd.length()+2); - client->println(buf); - -#ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buf); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); -#endif - if (!buffer.startsWith(F("235"))) - { - return false; - } -#endif - -} else { - buffer = F("AUTH LOGIN"); client->println(buffer); #ifdef DEBUG_EMAIL_PORT @@ -149,7 +257,7 @@ if (auth_used==1) { #endif if (!buffer.startsWith(F("334"))) { - return false; + goto exit; } base64 b; //buffer = user; @@ -165,9 +273,8 @@ if (auth_used==1) { #ifdef DEBUG_EMAIL_PORT DEBUG_EMAIL_PORT.println(buffer); #endif - if (!buffer.startsWith(F("334"))) - { - return false; + if (!buffer.startsWith(F("334"))) { + goto exit; } //buffer = this->passwd; //buffer = b.encode(buffer); @@ -181,12 +288,9 @@ if (auth_used==1) { #ifdef DEBUG_EMAIL_PORT DEBUG_EMAIL_PORT.println(buffer); #endif - if (!buffer.startsWith(F("235"))) - { - return false; + if (!buffer.startsWith(F("235"))) { + goto exit; } -} - } // smtp send mail @@ -200,9 +304,8 @@ if (auth_used==1) { #ifdef DEBUG_EMAIL_PORT DEBUG_EMAIL_PORT.println(buffer); #endif - if (!buffer.startsWith(F("250"))) - { - return false; + if (!buffer.startsWith(F("250"))) { + goto exit; } buffer = F("RCPT TO:"); buffer += to; @@ -214,12 +317,10 @@ if (auth_used==1) { #ifdef DEBUG_EMAIL_PORT DEBUG_EMAIL_PORT.println(buffer); #endif - if (!buffer.startsWith(F("250"))) - { - return false; + if (!buffer.startsWith(F("250"))) { + goto exit; } - buffer = F("DATA"); client->println(buffer); #ifdef DEBUG_EMAIL_PORT @@ -229,9 +330,8 @@ if (auth_used==1) { #ifdef DEBUG_EMAIL_PORT DEBUG_EMAIL_PORT.println(buffer); #endif - if (!buffer.startsWith(F("354"))) - { - return false; + if (!buffer.startsWith(F("354"))) { + goto exit; } buffer = F("From: "); buffer += from; @@ -252,59 +352,24 @@ if (auth_used==1) { #ifdef DEBUG_EMAIL_PORT DEBUG_EMAIL_PORT.println(buffer); #endif - buffer = msg; - client->println(buffer); + + client->println(msg); client->println('.'); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + DEBUG_EMAIL_PORT.println(msg); #endif + buffer = F("QUIT"); client->println(buffer); #ifdef DEBUG_EMAIL_PORT DEBUG_EMAIL_PORT.println(buffer); #endif - return true; + + status=true; +exit: + + return status; } -#ifdef USE_PLAIN -void SendEmail::a3_to_a4(unsigned char * a4, unsigned char * a3) { - a4[0] = (a3[0] & 0xfc) >> 2; - a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4); - a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6); - a4[3] = (a3[2] & 0x3f); -} - -int SendEmail::base64_encode(char *output, const char *input, int inputLen) { - const char* _b64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - int i = 0, j = 0; - int encLen = 0; - unsigned char a3[3]; - unsigned char a4[4]; - while(inputLen--) { - a3[i++] = *(input++); - if(i == 3) { - a3_to_a4(a4, a3); - for(i = 0; i < 4; i++) { - output[encLen++] = _b64_alphabet[a4[i]]; - } - i = 0; - } - } - if(i) { - for(j = i; j < 3; j++) { - a3[j] = '\0'; - } - a3_to_a4(a4, a3); - for(j = 0; j < i + 1; j++) { - output[encLen++] = _b64_alphabet[a4[j]]; - } - while((i++ < 3)) { - output[encLen++] = '='; - } - } - output[encLen] = '\0'; - return encLen; -} -#endif #endif // USE_SENDMAIL diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 009f0fa39..04af1906f 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2450,152 +2450,6 @@ String UrlEncode(const String& text) return encoded; } -#ifdef USE_SENDMAIL - -#include "sendemail.h" - -//SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const bool ssl); -//SendEmail::send(const String& from, const String& to, const String& subject, const String& msg) -// sendmail [server:port:user:passwd:from:to:subject] data -// sendmail [*:*:*:*:*:to:subject] data uses defines from user_config -// sendmail currently only works with core 2.4.2 - - -#define SEND_MAIL_MINRAM 12*1024 - -uint16_t SendMail(char *buffer) { - uint16_t count; - char *params,*oparams; - char *mserv; - uint16_t port; - char *user; - char *pstr; - char *passwd; - char *from; - char *to; - char *subject; - char *cmd; - char secure=0,auth=0; - uint16_t status=1; - SendEmail *mail=0; - - //DebugFreeMem(); - -// return if not enough memory - uint16_t mem=ESP.getFreeHeap(); - if (mem AUTH LOGIN 1 => PLAIN LOGIN - // 2 seconds timeout - #define MAIL_TIMEOUT 2000 - mail = new SendEmail(mserv, port,user,passwd, MAIL_TIMEOUT, auth); - -#ifdef EMAIL_FROM - if (*from=='*') { - from=(char*)EMAIL_FROM; - } -#endif - -exit: - if (mail) { - bool result=mail->send(from,to,subject,cmd); - delete mail; - if (result==true) status=0; - } - - - if (oparams) free(oparams); - return status; -} - -#endif - int WebSend(char *buffer) { // [sonoff] POWER1 ON --> Sends http://sonoff/cm?cmnd=POWER1 ON From 531c38b231f3ffcea2a5fd150538649dd8968bc8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 12:03:01 +0200 Subject: [PATCH 2169/2222] Minor refactor --- sonoff/xnrg_12_solaxX1.ino | 54 ++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/sonoff/xnrg_12_solaxX1.ino b/sonoff/xnrg_12_solaxX1.ino index a505d1a93..2c6c34a9e 100644 --- a/sonoff/xnrg_12_solaxX1.ino +++ b/sonoff/xnrg_12_solaxX1.ino @@ -291,23 +291,23 @@ void solaxX1250MSecond(void) // Every Second solaxX1_QueryLiveData(); EnergyUpdateTotal(solaxX1.energy_total, true); // 484.708 kWh - } + } } // End data Ready if (0 == solaxX1_send_retry && 255 != solaxX1_nodata_count) { solaxX1_send_retry = 12; solaxX1_QueryLiveData(); } - + // While the inverter has not stable ambient light, will send an address adquired but go offline again, // so no data will be received when the query is send, then we start the countdown to set the inverter as offline again. if (255 == solaxX1_nodata_count) { solaxX1_nodata_count = 0; - solaxX1_send_retry = 12; + solaxX1_send_retry = 12; } } // end hasAddress && (data_ready || solaxX1_send_retry == 0) else - { + { if ((solaxX1_nodata_count % 4) == 0) { DEBUG_SENSOR_LOG(PSTR("SX1: No Data count: %d"), solaxX1_nodata_count); } if (solaxX1_nodata_count < 10 * 4) // max. seconds without data { @@ -317,7 +317,7 @@ void solaxX1250MSecond(void) // Every Second { // no data from RS485, reset values to 0 and set inverter as offline solaxX1_nodata_count = 255; - solaxX1_send_retry = 12; + solaxX1_send_retry = 12; protocolStatus.status = 0b00001000; // queryOffline Energy.data_valid[0] = ENERGY_WATCHDOG; @@ -326,7 +326,7 @@ void solaxX1250MSecond(void) // Every Second //solaxX1.energy_today = solaxX1.energy_total = solaxX1.runtime_total = 0; } } - + if (!protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) { if (data_ready) @@ -408,12 +408,11 @@ void solaxX1SnsInit(void) AddLog_P(LOG_LEVEL_DEBUG, PSTR("SX1: Solax X1 Inverter Init")); DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX]); protocolStatus.status = 0b00100000; // hasAddress - + solaxX1Serial = new TasmotaSerial(pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX], 1); - if (solaxX1Serial->begin(SOLAXX1_SPEED)) - { + if (solaxX1Serial->begin(SOLAXX1_SPEED)) { if (solaxX1Serial->hardwareSerial()) { ClaimSerial(); } - }else { + } else { energy_flg = ENERGY_NONE; } } @@ -503,26 +502,25 @@ bool Xnrg12(uint8_t function) { bool result = false; - switch (function) - { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { solaxX1250MSecond(); } - break; - case FUNC_INIT: - solaxX1SnsInit(); - break; - case FUNC_PRE_INIT: - solaxX1DrvInit(); - break; - case FUNC_JSON_APPEND: - solaxX1Show(1); - break; + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { solaxX1250MSecond(); } + break; + case FUNC_JSON_APPEND: + solaxX1Show(1); + break; #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - solaxX1Show(0); - break; + case FUNC_WEB_SENSOR: + solaxX1Show(0); + break; #endif // USE_WEBSERVER - } + case FUNC_INIT: + solaxX1SnsInit(); + break; + case FUNC_PRE_INIT: + solaxX1DrvInit(); + break; + } return result; } From d724d15bfa348c88160ebe4bb23c92bdf5e876d7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 12:12:31 +0200 Subject: [PATCH 2170/2222] Bump version to 6.6.0.19 --- sonoff/sonoff_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 3f9afcc0e..828c71aa6 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06060012; +const uint32_t VERSION = 0x06060013; #endif // _SONOFF_VERSION_H_ From 9a03d831a66e62968cdbcb942812f5852da8483c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 12:28:29 +0200 Subject: [PATCH 2171/2222] Remove old SDM120 and SDM630 drivers * Replace obsolete xsns_23_sdm120 with xnrg_08_sdm120 and consolidate define USE_SDM120 * Replace obsolete xsns_25_sdm630 with xnrg_10_sdm630 and consolidate define USE_SDM630 * Replace obsolete xsns_49_solaxX1 with xnrg_12_solaxX1 (#6677) --- sonoff/_changelog.ino | 5 +++++ sonoff/my_user_config.h | 10 ++------- sonoff/sonoff_post.h | 41 +++++++++++++++---------------------- sonoff/sonoff_template.h | 16 ++------------- sonoff/support_features.ino | 6 +++--- sonoff/xnrg_08_sdm120.ino | 4 ++-- sonoff/xnrg_10_sdm630.ino | 4 ++-- 7 files changed, 33 insertions(+), 53 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index ba41d1f6d..2600039cf 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,9 @@ /*********************************************************************************************\ + * 6.6.0.19 20191018 + * Replace obsolete xsns_23_sdm120 with xnrg_08_sdm120 and consolidate define USE_SDM120 + * Replace obsolete xsns_25_sdm630 with xnrg_10_sdm630 and consolidate define USE_SDM630 + * Replace obsolete xsns_49_solaxX1 with xnrg_12_solaxX1 (#6677) + * * 6.6.0.18 20191010 * Add command DimmerRange in Light module to support 2 byte dimming ranges from Tuya * Add Zigbee additional commands and sending messages to control devices (#6095) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 6df2203bc..ad25e3b3a 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -449,9 +449,9 @@ #define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) #define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) #define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) -//#define USE_SDM120_2 // Add support for Eastron SDM120-Modbus energy monitor (+1k1 code) +//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy monitor (+1k1 code) #define SDM120_SPEED 2400 // SDM120-Modbus RS485 serial speed (default: 2400 baud) -//#define USE_SDM630_2 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) +//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) //#define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #define DDS2382_SPEED 9600 // Hiking DDS2382 Modbus RS485 serial speed (default: 9600 baud) @@ -461,12 +461,6 @@ #define SOLAXX1_SPEED 9600 // Solax X1 Modbus RS485 serial speed (default: 9600 baud) #define SOLAXX1_PV2 // Solax X1 using second PV -//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+2k4 code) -// #define SDM120_SPEED 2400 // SDM120-Modbus RS485 serial speed (default: 2400 baud) - #define USE_SDM220 // Add extra parameters for SDM220 (+0k1 code) -//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) -// #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) - // -- Low level interface devices ----------------- #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor (1k6 code) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 7e9df3143..1446d8946 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -185,16 +185,15 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) #define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) #define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) -#define USE_SDM120_2 // Add support for Eastron SDM120-Modbus energy monitor (+1k1 code) -#define USE_SDM630_2 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) +#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy monitor (+1k1 code) +#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) #define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) //#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+3k1 code) -//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) -//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI +//#define USE_MAX31865 // Add support for MAX31865 RTD sensors using softSPI #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) @@ -290,16 +289,15 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor #undef USE_MCP39F501 // Disable support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) -#undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) +#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) -#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI +#undef USE_MAX31865 // Disable support for MAX31865 RTD sensors using softSPI #undef USE_IR_REMOTE // Disable IR remote commands using library IRremoteESP8266 and ArduinoJson #undef USE_IR_RECEIVE // Disable support for IR receiver @@ -372,13 +370,11 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor #undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 - #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter - #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) + #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter + #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) -#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) #define USE_DISPLAY // Add I2C Display Support (+2k code) @@ -453,13 +449,11 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor #undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 - #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter - #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) + #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter + #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) -#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter #undef USE_DS18x20 // Disable support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) @@ -479,6 +473,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c //#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI +#undef USE_MAX31865 // Disable support for MAX31865 RTD sensors using softSPI #undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell @@ -568,16 +563,15 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor //#undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 -#undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) +#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) -#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI +#undef USE_MAX31865 // Disable support for MAX31865 RTD sensors using softSPI #undef USE_IR_REMOTE // Disable IR driver #undef USE_ZIGBEE // Disable serial communication with Zigbee CC2530 flashed with ZNP @@ -670,16 +664,15 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor #undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 -#undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) +#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) #undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) -#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI +#undef USE_MAX31865 // Disable support for MAX31865 RTD sensors using softSPI #undef USE_IR_REMOTE // Disable IR driver #undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 925b053ee..2a3ddcaca 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -634,11 +634,11 @@ const uint8_t kGpioNiceList[] PROGMEM = { #ifdef USE_PZEM_DC GPIO_PZEM017_RX, // PZEM-003,017 Serial Modbus interface #endif -#ifdef USE_SDM120_2 +#ifdef USE_SDM120 GPIO_SDM120_TX, // SDM120 Serial interface GPIO_SDM120_RX, // SDM120 Serial interface #endif -#ifdef USE_SDM630_2 +#ifdef USE_SDM630 GPIO_SDM630_TX, // SDM630 Serial interface GPIO_SDM630_RX, // SDM630 Serial interface #endif @@ -655,18 +655,6 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_SOLAXX1_RX, // Solax Inverter rx pin #endif // USE_SOLAX_X1 #endif // USE_ENERGY_SENSOR -#ifndef USE_SDM120_2 -#ifdef USE_SDM120 - GPIO_SDM120_TX, // SDM120 Serial interface - GPIO_SDM120_RX, // SDM120 Serial interface -#endif -#endif // USE_SDM120_2 -#ifndef USE_SDM630_2 -#ifdef USE_SDM630 - GPIO_SDM630_TX, // SDM630 Serial interface - GPIO_SDM630_RX, // SDM630 Serial interface -#endif -#endif // USE_SDM630_2 #ifdef USE_SERIAL_BRIDGE GPIO_SBR_TX, // Serial Bridge Serial interface diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 9ba69feee..6ee9afe21 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -306,13 +306,13 @@ void GetFeatures(void) feature_sns1 |= 0x02000000; // xsns_22_sr04.ino #endif #ifdef USE_SDM120 - feature_sns1 |= 0x04000000; // xsns_23_sdm120.ino + feature_sns1 |= 0x04000000; // xnrg_08_sdm120.ino #endif #ifdef USE_SI1145 feature_sns1 |= 0x08000000; // xsns_24_si1145.ino #endif #ifdef USE_SDM630 - feature_sns1 |= 0x10000000; // xsns_25_sdm630.ino + feature_sns1 |= 0x10000000; // xnrg_10_sdm630.ino #endif #ifdef USE_LM75AD feature_sns1 |= 0x20000000; // xsns_26_lm75ad.ino @@ -419,7 +419,7 @@ void GetFeatures(void) feature_sns2 |= 0x20000000; // xsns_48_chirp.ino #endif #ifdef USE_SOLAX_X1 - feature_sns2 |= 0x40000000; // xsns_49_solaxX1.ino + feature_sns2 |= 0x40000000; // xnrg_12_solaxX1.ino #endif #ifdef USE_PAJ7620 feature_sns2 |= 0x80000000; // xsns_50_paj7620.ino diff --git a/sonoff/xnrg_08_sdm120.ino b/sonoff/xnrg_08_sdm120.ino index 8b771ba80..c60dd16a7 100644 --- a/sonoff/xnrg_08_sdm120.ino +++ b/sonoff/xnrg_08_sdm120.ino @@ -18,7 +18,7 @@ */ #ifdef USE_ENERGY_SENSOR -#ifdef USE_SDM120_2 +#ifdef USE_SDM120 /*********************************************************************************************\ * Eastron SDM120 or SDM220 Modbus energy meter * @@ -265,5 +265,5 @@ bool Xnrg08(uint8_t function) return result; } -#endif // USE_SDM120_2 +#endif // USE_SDM120 #endif // USE_ENERGY_SENSOR diff --git a/sonoff/xnrg_10_sdm630.ino b/sonoff/xnrg_10_sdm630.ino index 4c048b062..8bf1827f8 100644 --- a/sonoff/xnrg_10_sdm630.ino +++ b/sonoff/xnrg_10_sdm630.ino @@ -18,7 +18,7 @@ */ #ifdef USE_ENERGY_SENSOR -#ifdef USE_SDM630_2 +#ifdef USE_SDM630 /*********************************************************************************************\ * Eastron SDM630-Modbus energy meter * @@ -213,5 +213,5 @@ bool Xnrg10(uint8_t function) return result; } -#endif // USE_SDM630_2 +#endif // USE_SDM630 #endif // USE_ENERGY_SENSOR From 5ab85a9825960942f0a43ea99148f6052fab8ee2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 12:28:59 +0200 Subject: [PATCH 2172/2222] Update RELEASENOTES.md --- RELEASENOTES.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 12c8c8321..ef0af1ff9 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -164,12 +164,10 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_PZEM_AC | - | - | - | x | x | x | - | | USE_PZEM_DC | - | - | - | x | x | x | - | | USE_MCP39F501 | - | x | - | x | x | x | - | -| USE_SDM120_2 | - | - | - | - | - | x | - | -| USE_SDM630_2 | - | - | - | - | - | x | - | +| USE_SDM120 | - | - | - | - | - | x | - | +| USE_SDM630 | - | - | - | - | - | x | - | | USE_DDS2382 | - | - | - | - | - | x | - | | USE_DDSU666 | - | - | - | - | - | x | - | -| USE_SDM120 | - | - | - | - | - | - | - | -| USE_SDM630 | - | - | - | - | - | - | - | | USE_SOLAX_X1 | - | - | - | - | - | - | - | | | | | | | | | | | USE_ADC_VCC | x | x | x | - | - | - | - | From b361d0cc46f3c598d2d82cce7616e7963d7f8188 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 12:31:56 +0200 Subject: [PATCH 2173/2222] Remove obsolete SDM120 and SDM630 drivers --- sonoff/xsns_23_sdm120.ino | 397 -------------------------------------- sonoff/xsns_25_sdm630.ino | 362 ---------------------------------- 2 files changed, 759 deletions(-) delete mode 100644 sonoff/xsns_23_sdm120.ino delete mode 100644 sonoff/xsns_25_sdm630.ino diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino deleted file mode 100644 index b363ce16f..000000000 --- a/sonoff/xsns_23_sdm120.ino +++ /dev/null @@ -1,397 +0,0 @@ -/* - xsns_23_sdm120.ino - Eastron SDM120-Modbus energy meter support for Sonoff-Tasmota - - Copyright (C) 2019 Gennaro Tortone - - 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_SDM120 - -/*********************************************************************************************\ - * Eastron SDM120-Modbus energy meter - * - * Based on: https://github.com/reaper7/SDM_Energy_Meter -\*********************************************************************************************/ - -#define XSNS_23 23 - -// can be user defined in my_user_config.h -#ifndef SDM120_SPEED - #define SDM120_SPEED 2400 // default SDM120 Modbus address -#endif -// can be user defined in my_user_config.h -#ifndef SDM120_ADDR - #define SDM120_ADDR 1 // default SDM120 Modbus address -#endif - - -#include - -enum SDM120_Error {SDM120_ERR_NO_ERROR=0, SDM120_ERR_CRC_ERROR, SDM120_ERR_WRONG_BYTES, SDM120_ERR_NOT_ENOUGHT_BYTES}; - -TasmotaSerial *SDM120Serial; - -uint8_t sdm120_type = 1; -//uint8_t sdm120_state = 0; - -float sdm120_voltage = 0; -float sdm120_current = 0; -float sdm120_active_power = 0; -float sdm120_apparent_power = 0; -float sdm120_reactive_power = 0; -float sdm120_power_factor = 0; -float sdm120_frequency = 0; -float sdm120_energy_total = 0; -float sdm120_phase_angle = 0; -float sdm120_import_active = 0; -float sdm120_export_active = 0; -float sdm120_import_reactive = 0; -float sdm120_export_reactive = 0; -float sdm120_total_reactive = 0; - -bool SDM120_ModbusReceiveReady(void) -{ - return (SDM120Serial->available() > 1); -} - -void SDM120_ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count) -{ - uint8_t frame[8]; - - frame[0] = SDM120_ADDR; - frame[1] = function_code; - frame[2] = (uint8_t)(start_address >> 8); - frame[3] = (uint8_t)(start_address); - frame[4] = (uint8_t)(register_count >> 8); - frame[5] = (uint8_t)(register_count); - - uint16_t crc = SDM120_calculateCRC(frame, 6); // calculate out crc only from first 6 bytes - frame[6] = lowByte(crc); - frame[7] = highByte(crc); - - while (SDM120Serial->available() > 0) { // read serial if any old data is available - SDM120Serial->read(); - } - - SDM120Serial->flush(); - SDM120Serial->write(frame, sizeof(frame)); -} - -uint8_t SDM120_ModbusReceive(float *value) -{ - uint8_t buffer[9]; - - *value = NAN; - uint8_t len = 0; - while (SDM120Serial->available() > 0) { - buffer[len++] = (uint8_t)SDM120Serial->read(); - } - - if (len < 9) { - return SDM120_ERR_NOT_ENOUGHT_BYTES; - } - - if (9 == len) { - if (0x01 == buffer[0] && 0x04 == buffer[1] && 4 == buffer[2]) { // check node number, op code and reply bytes count - if((SDM120_calculateCRC(buffer, 7)) == ((buffer[8] << 8) | buffer[7])) { //calculate crc from first 7 bytes and compare with received crc (bytes 7 & 8) - - ((uint8_t*)value)[3] = buffer[3]; - ((uint8_t*)value)[2] = buffer[4]; - ((uint8_t*)value)[1] = buffer[5]; - ((uint8_t*)value)[0] = buffer[6]; - - } else { - return SDM120_ERR_CRC_ERROR; - } - - } else { - return SDM120_ERR_WRONG_BYTES; - } - } - - return SDM120_ERR_NO_ERROR; -} - -uint16_t SDM120_calculateCRC(uint8_t *frame, uint8_t num) -{ - uint16_t crc, flag; - crc = 0xFFFF; - for (uint32_t i = 0; i < num; i++) { - crc ^= frame[i]; - for (uint32_t j = 8; j; j--) { - if ((crc & 0x0001) != 0) { // If the LSB is set - crc >>= 1; // Shift right and XOR 0xA001 - crc ^= 0xA001; - } else { // Else LSB is not set - crc >>= 1; // Just shift right - } - } - } - return crc; -} - -/*********************************************************************************************/ - -const uint16_t sdm120_start_addresses[] { - 0x0000, // SDM120C_VOLTAGE [V] - 0x0006, // SDM120C_CURRENT [A] - 0x000C, // SDM120C_POWER [W] - 0x0012, // SDM120C_APPARENT_POWER [VA] - 0x0018, // SDM120C_REACTIVE_POWER [VAR] - 0x001E, // SDM120C_POWER_FACTOR - 0x0046, // SDM120C_FREQUENCY [Hz] -#ifdef USE_SDM220 - 0x0156, // SDM120C_TOTAL_ACTIVE_ENERGY [Wh] - 0X0024, // SDM220_PHASE_ANGLE [Degre] - 0X0048, // SDM220_IMPORT_ACTIVE [kWh] - 0X004A, // SDM220_EXPORT_ACTIVE [kWh] - 0X004C, // SDM220_IMPORT_REACTIVE [kVArh] - 0X004E, // SDM220_EXPORT_REACTIVE [kVArh] - 0X0158 // SDM220 TOTAL_REACTIVE [kVArh] -#else // USE_SDM220 - 0x0156 // SDM120C_TOTAL_ACTIVE_ENERGY [Wh] -#endif // USE_SDM220 -}; - -uint8_t sdm120_read_state = 0; -uint8_t sdm120_send_retry = 0; -uint8_t sdm120_nodata_count = 0; - -void SDM120250ms(void) // Every 250 mSec -{ -// sdm120_state++; -// if (6 == sdm120_state) { // Every 300 mSec -// sdm120_state = 0; - - float value = 0; - bool data_ready = SDM120_ModbusReceiveReady(); - - if (data_ready) { - sdm120_nodata_count = 0; - uint8_t error = SDM120_ModbusReceive(&value); - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM120 response error %d"), error); - } else { - switch(sdm120_read_state) { - case 0: - sdm120_voltage = value; - break; - - case 1: - sdm120_current = value; - break; - - case 2: - sdm120_active_power = value; - break; - - case 3: - sdm120_apparent_power = value; - break; - - case 4: - sdm120_reactive_power = value; - break; - - case 5: - sdm120_power_factor = value; - break; - - case 6: - sdm120_frequency = value; - break; - - case 7: - sdm120_energy_total = value; - break; -#ifdef USE_SDM220 - case 8: - sdm120_phase_angle = value; - break; - - case 9: - sdm120_import_active = value; - break; - - case 10: - sdm120_export_active = value; - break; - - case 11: - sdm120_import_reactive = value; - break; - - case 12: - sdm120_export_reactive = value; - break; - - case 13: - sdm120_total_reactive = value; - break; -#endif // USE_SDM220 - } // end switch - - sdm120_read_state++; - - if (sizeof(sdm120_start_addresses)/2 == sdm120_read_state) { - sdm120_read_state = 0; - } - } - } // end data ready - else { - if (sdm120_nodata_count <= (1000/250) * 4) { // max. 4 sec without data - sdm120_nodata_count++; - } else if (sdm120_nodata_count != 255) { - // no data from modbus, reset values to 0 - sdm120_nodata_count = 255; - sdm120_voltage = sdm120_current = sdm120_active_power = sdm120_apparent_power = sdm120_reactive_power = sdm120_power_factor = sdm120_frequency = sdm120_energy_total = 0; -#ifdef USE_SDM220 - sdm120_phase_angle = sdm120_import_active = sdm120_export_active = sdm120_import_reactive = sdm120_export_reactive = sdm120_total_reactive = 0; -#endif - } - } - - if (0 == sdm120_send_retry || data_ready) { - sdm120_send_retry = 5; - SDM120_ModbusSend(0x04, sdm120_start_addresses[sdm120_read_state], 2); - } else { - sdm120_send_retry--; - } -// } // end 300 ms -} - -void SDM120Init(void) -{ - sdm120_type = 0; - if ((pin[GPIO_SDM120_RX] < 99) && (pin[GPIO_SDM120_TX] < 99)) { - SDM120Serial = new TasmotaSerial(pin[GPIO_SDM120_RX], pin[GPIO_SDM120_TX], 1); - if (SDM120Serial->begin(SDM120_SPEED)) { - if (SDM120Serial->hardwareSerial()) { ClaimSerial(); } - sdm120_type = 1; - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SDM120_DATA[] PROGMEM = - "{s}SDM120 " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}SDM120 " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}SDM120 " D_POWERUSAGE_ACTIVE "{m}%s " D_UNIT_WATT "{e}" - "{s}SDM120 " D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" - "{s}SDM120 " D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" - "{s}SDM120 " D_POWER_FACTOR "{m}%s{e}" - "{s}SDM120 " D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}" - "{s}SDM120 " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}" -#ifdef USE_SDM220 - "{s}SDM120 " D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}" - "{s}SDM120 " D_IMPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}SDM120 " D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}SDM120 " D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - "{s}SDM120 " D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - "{s}SDM120 " D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" -#endif // USE_SDM220 - ; -#endif // USE_WEBSERVER - -void SDM120Show(bool json) -{ - char voltage[33]; - dtostrfd(sdm120_voltage, Settings.flag2.voltage_resolution, voltage); - char current[33]; - dtostrfd(sdm120_current, Settings.flag2.current_resolution, current); - char active_power[33]; - dtostrfd(sdm120_active_power, Settings.flag2.wattage_resolution, active_power); - char apparent_power[33]; - dtostrfd(sdm120_apparent_power, Settings.flag2.wattage_resolution, apparent_power); - char reactive_power[33]; - dtostrfd(sdm120_reactive_power, Settings.flag2.wattage_resolution, reactive_power); - char power_factor[33]; - dtostrfd(sdm120_power_factor, 2, power_factor); - char frequency[33]; - dtostrfd(sdm120_frequency, Settings.flag2.frequency_resolution, frequency); - char energy_total[33]; - dtostrfd(sdm120_energy_total, Settings.flag2.energy_resolution, energy_total); -#ifdef USE_SDM220 - char phase_angle[33]; - dtostrfd(sdm120_phase_angle, 2, phase_angle); - char import_active[33]; - dtostrfd(sdm120_import_active, Settings.flag2.wattage_resolution, import_active); - char export_active[33]; - dtostrfd(sdm120_export_active, Settings.flag2.wattage_resolution, export_active); - char import_reactive[33]; - dtostrfd(sdm120_import_reactive,Settings.flag2.wattage_resolution, import_reactive); - char export_reactive[33]; - dtostrfd(sdm120_export_reactive,Settings.flag2.wattage_resolution, export_reactive); - char total_reactive[33]; - dtostrfd(sdm120_total_reactive, Settings.flag2.wattage_resolution, total_reactive); -#endif // USE_SDM220 - if (json) { -#ifdef USE_SDM220 - ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s,\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_EXPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s}"), - energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current, phase_angle, import_active, export_active, import_reactive, export_reactive, total_reactive); -#else - ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), - energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current); -#endif // USE_SDM220 -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - char energy_total_chr[33]; - dtostrfd(sdm120_energy_total * 1000, 1, energy_total_chr); - DomoticzSensor(DZ_VOLTAGE, voltage); - DomoticzSensor(DZ_CURRENT, current); - DomoticzSensorPowerEnergy((int)sdm120_active_power, energy_total_chr); - } -#endif // USE_DOMOTICZ -#ifdef USE_WEBSERVER - } else { -#ifdef USE_SDM220 - WSContentSend_PD(HTTP_SNS_SDM120_DATA, voltage, current, active_power, apparent_power, reactive_power, power_factor, frequency, energy_total, phase_angle,import_active,export_active,import_reactive,export_reactive,total_reactive); -#else - WSContentSend_PD(HTTP_SNS_SDM120_DATA, voltage, current, active_power, apparent_power, reactive_power, power_factor, frequency, energy_total); -#endif // USE_SDM220 -#endif // USE_WEBSERVER - } -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xsns23(uint8_t function) -{ - bool result = false; - - if (sdm120_type) { - switch (function) { - case FUNC_INIT: - SDM120Init(); - break; - case FUNC_EVERY_250_MSECOND: - SDM120250ms(); - break; - case FUNC_JSON_APPEND: - SDM120Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SDM120Show(0); - break; -#endif // USE_WEBSERVER - } - } - return result; -} - -#endif // USE_SDM120 diff --git a/sonoff/xsns_25_sdm630.ino b/sonoff/xsns_25_sdm630.ino deleted file mode 100644 index 93580b96b..000000000 --- a/sonoff/xsns_25_sdm630.ino +++ /dev/null @@ -1,362 +0,0 @@ -/* - xsns_25_sdm630.ino - Eastron SDM630-Modbus energy meter support for Sonoff-Tasmota - - Copyright (C) 2019 Gennaro Tortone - - 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_SDM630 - -/*********************************************************************************************\ - * Eastron SDM630-Modbus energy meter - * - * Based on: https://github.com/reaper7/SDM_Energy_Meter -\*********************************************************************************************/ - -#define XSNS_25 25 - -#include - -TasmotaSerial *SDM630Serial; - -uint8_t sdm630_type = 1; -//uint8_t sdm630_state = 0; - -float sdm630_voltage[] = {0,0,0}; -float sdm630_current[] = {0,0,0}; -float sdm630_active_power[] = {0,0,0}; -float sdm630_reactive_power[] = {0,0,0}; -float sdm630_power_factor[] = {0,0,0}; -float sdm630_energy_total = 0; - -bool SDM630_ModbusReceiveReady(void) -{ - return (SDM630Serial->available() > 1); -} - -void SDM630_ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count) -{ - uint8_t frame[8]; - - frame[0] = 0x01; // default SDM630 Modbus address - frame[1] = function_code; - frame[2] = (uint8_t)(start_address >> 8); - frame[3] = (uint8_t)(start_address); - frame[4] = (uint8_t)(register_count >> 8); - frame[5] = (uint8_t)(register_count); - - uint16_t crc = SDM630_calculateCRC(frame, 6); // calculate out crc only from first 6 bytes - frame[6] = lowByte(crc); - frame[7] = highByte(crc); - - while (SDM630Serial->available() > 0) { // read serial if any old data is available - SDM630Serial->read(); - } - - SDM630Serial->flush(); - SDM630Serial->write(frame, sizeof(frame)); -} - -uint8_t SDM630_ModbusReceive(float *value) -{ - uint8_t buffer[9]; - - *value = NAN; - uint8_t len = 0; - while (SDM630Serial->available() > 0) { - buffer[len++] = (uint8_t)SDM630Serial->read(); - } - - if (len < 9) - return 3; // SDM_ERR_NOT_ENOUGHT_BYTES - - if (len == 9) { - - if (buffer[0] == 0x01 && buffer[1] == 0x04 && buffer[2] == 4) { // check node number, op code and reply bytes count - - if((SDM630_calculateCRC(buffer, 7)) == ((buffer[8] << 8) | buffer[7])) { //calculate crc from first 7 bytes and compare with received crc (bytes 7 & 8) - - ((uint8_t*)value)[3] = buffer[3]; - ((uint8_t*)value)[2] = buffer[4]; - ((uint8_t*)value)[1] = buffer[5]; - ((uint8_t*)value)[0] = buffer[6]; - - } else return 1; // SDM_ERR_CRC_ERROR - - } else return 2; // SDM_ERR_WRONG_BYTES - } - - return 0; // SDM_ERR_NO_ERROR -} - -uint16_t SDM630_calculateCRC(uint8_t *frame, uint8_t num) -{ - uint16_t crc, flag; - crc = 0xFFFF; - for (uint32_t i = 0; i < num; i++) { - crc ^= frame[i]; - for (uint32_t j = 8; j; j--) { - if ((crc & 0x0001) != 0) { // If the LSB is set - crc >>= 1; // Shift right and XOR 0xA001 - crc ^= 0xA001; - } else { // Else LSB is not set - crc >>= 1; // Just shift right - } - } - } - return crc; -} - -/*********************************************************************************************/ - -const uint16_t sdm630_start_addresses[] { - 0x0000, // L1 - SDM630_VOLTAGE [V] - 0x0002, // L2 - SDM630_VOLTAGE [V] - 0x0004, // L3 - SDM630_VOLTAGE [V] - 0x0006, // L1 - SDM630_CURRENT [A] - 0x0008, // L2 - SDM630_CURRENT [A] - 0x000A, // L3 - SDM630_CURRENT [A] - 0x000C, // L1 - SDM630_POWER [W] - 0x000E, // L2 - SDM630_POWER [W] - 0x0010, // L3 - SDM630_POWER [W] - 0x0018, // L1 - SDM630_REACTIVE_POWER [VAR] - 0x001A, // L2 - SDM630_REACTIVE_POWER [VAR] - 0x001C, // L3 - SDM630_REACTIVE_POWER [VAR] - 0x001E, // L1 - SDM630_POWER_FACTOR - 0x0020, // L2 - SDM630_POWER_FACTOR - 0x0022, // L3 - SDM630_POWER_FACTOR - 0x0156 // Total - SDM630_TOTAL_ACTIVE_ENERGY [Wh] -}; - -uint8_t sdm630_read_state = 0; -uint8_t sdm630_send_retry = 0; - -void SDM630250ms(void) // Every 250 mSec -{ -// sdm630_state++; -// if (6 == sdm630_state) { // Every 300 mSec -// sdm630_state = 0; - - float value = 0; - bool data_ready = SDM630_ModbusReceiveReady(); - - if (data_ready) { - uint8_t error = SDM630_ModbusReceive(&value); - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM630 response error %d"), error); - } else { - switch(sdm630_read_state) { - case 0: - sdm630_voltage[0] = value; - break; - - case 1: - sdm630_voltage[1] = value; - break; - - case 2: - sdm630_voltage[2] = value; - break; - - case 3: - sdm630_current[0] = value; - break; - - case 4: - sdm630_current[1] = value; - break; - - case 5: - sdm630_current[2] = value; - break; - - case 6: - sdm630_active_power[0] = value; - break; - - case 7: - sdm630_active_power[1] = value; - break; - - case 8: - sdm630_active_power[2] = value; - break; - - case 9: - sdm630_reactive_power[0] = value; - break; - - case 10: - sdm630_reactive_power[1] = value; - break; - - case 11: - sdm630_reactive_power[2] = value; - break; - - case 12: - sdm630_power_factor[0] = value; - break; - - case 13: - sdm630_power_factor[1] = value; - break; - - case 14: - sdm630_power_factor[2] = value; - break; - - case 15: - sdm630_energy_total = value; - break; - } // end switch - - sdm630_read_state++; - - if (sizeof(sdm630_start_addresses)/2 == sdm630_read_state) { - sdm630_read_state = 0; - } - } - } // end data ready - - if (0 == sdm630_send_retry || data_ready) { - sdm630_send_retry = 5; - SDM630_ModbusSend(0x04, sdm630_start_addresses[sdm630_read_state], 2); - } else { - sdm630_send_retry--; - } -// } // end 300 ms -} - -void SDM630Init(void) -{ - sdm630_type = 0; - if ((pin[GPIO_SDM630_RX] < 99) && (pin[GPIO_SDM630_TX] < 99)) { - SDM630Serial = new TasmotaSerial(pin[GPIO_SDM630_RX], pin[GPIO_SDM630_TX], 1); -#ifdef SDM630_SPEED - if (SDM630Serial->begin(SDM630_SPEED)) { -#else - if (SDM630Serial->begin(2400)) { -#endif - if (SDM630Serial->hardwareSerial()) { ClaimSerial(); } - sdm630_type = 1; - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SDM630_DATA[] PROGMEM = - "{s}SDM630 " D_VOLTAGE "{m}%s/%s/%s " D_UNIT_VOLT "{e}" - "{s}SDM630 " D_CURRENT "{m}%s/%s/%s " D_UNIT_AMPERE "{e}" - "{s}SDM630 " D_POWERUSAGE_ACTIVE "{m}%s/%s/%s " D_UNIT_WATT "{e}" - "{s}SDM630 " D_POWERUSAGE_REACTIVE "{m}%s/%s/%s " D_UNIT_VAR "{e}" - "{s}SDM630 " D_POWER_FACTOR "{m}%s/%s/%s{e}" - "{s}SDM630 " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; -#endif // USE_WEBSERVER - -void SDM630Show(bool json) -{ - char voltage_l1[33]; - dtostrfd(sdm630_voltage[0], Settings.flag2.voltage_resolution, voltage_l1); - char voltage_l2[33]; - dtostrfd(sdm630_voltage[1], Settings.flag2.voltage_resolution, voltage_l2); - char voltage_l3[33]; - dtostrfd(sdm630_voltage[2], Settings.flag2.voltage_resolution, voltage_l3); - char current_l1[33]; - dtostrfd(sdm630_current[0], Settings.flag2.current_resolution, current_l1); - char current_l2[33]; - dtostrfd(sdm630_current[1], Settings.flag2.current_resolution, current_l2); - char current_l3[33]; - dtostrfd(sdm630_current[2], Settings.flag2.current_resolution, current_l3); - char active_power_l1[33]; - dtostrfd(sdm630_active_power[0], Settings.flag2.wattage_resolution, active_power_l1); - char active_power_l2[33]; - dtostrfd(sdm630_active_power[1], Settings.flag2.wattage_resolution, active_power_l2); - char active_power_l3[33]; - dtostrfd(sdm630_active_power[2], Settings.flag2.wattage_resolution, active_power_l3); - char reactive_power_l1[33]; - dtostrfd(sdm630_reactive_power[0], Settings.flag2.wattage_resolution, reactive_power_l1); - char reactive_power_l2[33]; - dtostrfd(sdm630_reactive_power[1], Settings.flag2.wattage_resolution, reactive_power_l2); - char reactive_power_l3[33]; - dtostrfd(sdm630_reactive_power[2], Settings.flag2.wattage_resolution, reactive_power_l3); - char power_factor_l1[33]; - dtostrfd(sdm630_power_factor[0], 2, power_factor_l1); - char power_factor_l2[33]; - dtostrfd(sdm630_power_factor[1], 2, power_factor_l2); - char power_factor_l3[33]; - dtostrfd(sdm630_power_factor[2], 2, power_factor_l3); - char energy_total[33]; - dtostrfd(sdm630_energy_total, Settings.flag2.energy_resolution, energy_total); - - if (json) { - ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" - D_JSON_ACTIVE_POWERUSAGE "\":[%s,%s,%s],\"" D_JSON_REACTIVE_POWERUSAGE "\":[%s,%s,%s],\"" - D_JSON_POWERFACTOR "\":[%s,%s,%s],\"" D_JSON_VOLTAGE "\":[%s,%s,%s],\"" D_JSON_CURRENT "\":[%s,%s,%s]}"), - energy_total, active_power_l1, active_power_l2, active_power_l3, - reactive_power_l1, reactive_power_l2, reactive_power_l3, - power_factor_l1, power_factor_l2, power_factor_l3, - voltage_l1, voltage_l2, voltage_l3, - current_l1, current_l2, current_l3); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - char energy_total_chr[33]; - dtostrfd(sdm630_energy_total * 1000, 1, energy_total_chr); - DomoticzSensor(DZ_VOLTAGE, voltage_l1); - DomoticzSensor(DZ_CURRENT, current_l1); - DomoticzSensorPowerEnergy((int)sdm630_active_power[0], energy_total_chr); - } -#endif // USE_DOMOTICZ -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_SDM630_DATA, - voltage_l1, voltage_l2, voltage_l3, current_l1, current_l2, current_l3, - active_power_l1, active_power_l2, active_power_l3, - reactive_power_l1, reactive_power_l2, reactive_power_l3, - power_factor_l1, power_factor_l2, power_factor_l3, energy_total); -#endif // USE_WEBSERVER - } -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xsns25(uint8_t function) -{ - bool result = false; - - if (sdm630_type) { - switch (function) { - case FUNC_INIT: - SDM630Init(); - break; - case FUNC_EVERY_250_MSECOND: - SDM630250ms(); - break; - case FUNC_JSON_APPEND: - SDM630Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SDM630Show(0); - break; -#endif // USE_WEBSERVER - } - } - return result; -} - -#endif From 71a9fbcf6595841853c1405b643f2772ab3fcf8f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 12:47:22 +0200 Subject: [PATCH 2174/2222] Refactor FUNC_EVERY_SECOND --- sonoff/sonoff.ino | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index b3f7ce0e3..1c6d95b4b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -837,9 +837,6 @@ void PerformEverySecond(void) XdrvCall(FUNC_AFTER_TELEPERIOD); } } - - //XdrvCall(FUNC_EVERY_SECOND); - //XsnsCall(FUNC_EVERY_SECOND); } /*********************************************************************************************\ @@ -937,8 +934,6 @@ void Every250mSeconds(void) switch (state_250mS) { case 0: // Every x.0 second - PerformEverySecond(); - if (ota_state_flag && BACKLOG_EMPTY) { ota_state_flag--; if (2 == ota_state_flag) { @@ -1682,10 +1677,12 @@ void loop(void) Every250mSeconds(); XdrvCall(FUNC_EVERY_250_MSECOND); XsnsCall(FUNC_EVERY_250_MSECOND); - if (!state_250mS) { - XdrvCall(FUNC_EVERY_SECOND); - XsnsCall(FUNC_EVERY_SECOND); - } + } + if (TimeReached(state_second)) { + SetNextTimeInterval(state_second, 1000); + PerformEverySecond(); + XdrvCall(FUNC_EVERY_SECOND); + XsnsCall(FUNC_EVERY_SECOND); } if (!serial_local) { SerialInput(); } From 3bb58b3ea019e4561cdfa3f312a47410e08f607b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 12:53:35 +0200 Subject: [PATCH 2175/2222] Disable some logging --- sonoff/xdrv_19_ps16dz_dimmer.ino | 12 ++++++------ sonoff/xlgt_05_sonoff_l1.ino | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index c9fdff640..80c32ba47 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -43,7 +43,7 @@ struct PS16DZ { void PS16DZSerialSend(const char *tx_buffer) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Send %s"), tx_buffer); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Send %s"), tx_buffer); PS16DZSerial->print(tx_buffer); PS16DZSerial->write(0x1B); @@ -96,7 +96,7 @@ void PS16DZSerialInput(void) Ps16dz.rx_buffer[Ps16dz.byte_counter++] = 0x00; // AT+RESULT="sequence":"1554682835320" - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Rcvd %s"), Ps16dz.rx_buffer); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Rcvd %s"), Ps16dz.rx_buffer); if (!strncmp(Ps16dz.rx_buffer+3, "RESULT", 6)) { @@ -118,7 +118,7 @@ void PS16DZSerialInput(void) if (!strncmp(token2, "\"switch\"", 8)) { bool switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Switch %d"), switch_state); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Switch %d"), switch_state); is_switch_change = (switch_state != power); if (is_switch_change) { @@ -128,7 +128,7 @@ void PS16DZSerialInput(void) else if (!strncmp(token2, "\"bright\"", 8)) { Ps16dz.dimmer = atoi(token3); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Brightness %d"), Ps16dz.dimmer); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Brightness %d"), Ps16dz.dimmer); is_brightness_change = Ps16dz.dimmer != Settings.light_dimmer; if (power && (Ps16dz.dimmer > 0) && is_brightness_change) { @@ -138,7 +138,7 @@ void PS16DZSerialInput(void) } else if (!strncmp(token2, "\"sequence\"", 10)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Sequence %s"), token3); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Sequence %s"), token3); } token = strtok_r(nullptr, ",", &end_str); @@ -146,7 +146,7 @@ void PS16DZSerialInput(void) if (!is_brightness_change) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Update")); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Update")); PS16DZSerialSendOk(); } diff --git a/sonoff/xlgt_05_sonoff_l1.ino b/sonoff/xlgt_05_sonoff_l1.ino index b0661a594..f9f49aaa5 100644 --- a/sonoff/xlgt_05_sonoff_l1.ino +++ b/sonoff/xlgt_05_sonoff_l1.ino @@ -49,7 +49,7 @@ struct SNFL1 { void SnfL1Send(const char *buffer) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Send %s"), buffer); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Send %s"), buffer); Serial.print(buffer); Serial.write(0x1B); @@ -79,7 +79,7 @@ bool SnfL1SerialInput(void) // AT+RESULT="sequence":"1554682835320" // AT+UPDATE="sequence":"34906","switch":"on","light_type":1,"colorR":0,"colorG":16,"colorB":0,"bright":6,"mode":1 // AT+UPDATE="switch":"on","light_type":1,"colorR":255,"colorG":0,"colorB":0,"bright":6,"mode":1,"speed":100,"sensitive":10 - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd %s"), serial_in_buffer); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd %s"), serial_in_buffer); if (!strncmp(serial_in_buffer +3, "RESULT", 6)) { Snfl1.receive_ready = true; @@ -107,7 +107,7 @@ bool SnfL1SerialInput(void) if (!strncmp(token2, "\"sequence\"", 10)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd sequence %s"), token3); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd sequence %s"), token3); token = nullptr; } @@ -115,7 +115,7 @@ bool SnfL1SerialInput(void) else if (!strncmp(token2, "\"switch\"", 8)) { switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd switch %d (%d)"), switch_state, Light.power); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd switch %d (%d)"), switch_state, Light.power); is_power_change = (switch_state != Light.power); } @@ -139,9 +139,9 @@ bool SnfL1SerialInput(void) bool all_color_channels_updated = color_updated[0] && color_updated[1] && color_updated[2]; if (all_color_channels_updated) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd color R%d G%d B%d (R%d G%d B%d)"), - current_color[0], current_color[1], current_color[2], - Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd color R%d G%d B%d (R%d G%d B%d)"), +// current_color[0], current_color[1], current_color[2], +// Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); is_color_change = (Light.power && (memcmp(current_color, Settings.light_color, 3) != 0)); } @@ -151,7 +151,7 @@ bool SnfL1SerialInput(void) else if (!strncmp(token2, "\"bright\"", 8)) { uint8_t dimmer = atoi(token3); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd dimmer %d (%d)"), dimmer, Settings.light_dimmer); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd dimmer %d (%d)"), dimmer, Settings.light_dimmer); is_brightness_change = (Light.power && (dimmer > 0) && (dimmer != Settings.light_dimmer)); snprintf_P(cmnd_dimmer, sizeof(cmnd_dimmer), PSTR(D_CMND_DIMMER " %d"), dimmer); From 84fe7b8e763561e93025bf4e004ef7495c20b0e3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 15:18:39 +0200 Subject: [PATCH 2176/2222] Bump version to 6.6.0.20 Add command SetOption65 0/1 to disable (1) fast power cycle detection fixing unwanted brownout trigger --- sonoff/_changelog.ino | 5 ++++- sonoff/settings.h | 2 +- sonoff/settings.ino | 24 ++++++++++++++++++++---- sonoff/sonoff.ino | 4 +--- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_04_light.ino | 4 ++-- tools/decode-status.py | 8 ++++---- 7 files changed, 33 insertions(+), 16 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 2600039cf..64525de6d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ /*********************************************************************************************\ + * 6.6.0.20 20191018 + * Add command SetOption65 0/1 to disable (1) fast power cycle detection fixing unwanted brownout trigger + * * 6.6.0.19 20191018 * Replace obsolete xsns_23_sdm120 with xnrg_08_sdm120 and consolidate define USE_SDM120 * Replace obsolete xsns_25_sdm630 with xnrg_10_sdm630 and consolidate define USE_SDM630 @@ -78,7 +81,7 @@ * Add support for Hiking DDS238-2 Modbus energy meter by Matteo Campanella (#6384) * * 6.6.0.10 20190905 - * Redesign Tuya support by Shantur Rathore (#6353) + * Redesign Tuya support by Shantur Rathore removing commands SetOption34, 41, 44, 45, 46 and 65 (#6353) * Add command Reset 99 to reset bootcount to zero (#684, #6351) * Change command Time 1/2/3 to select JSON time format ISO, ISO + Epoch or Epoch for legacy reason * diff --git a/sonoff/settings.h b/sonoff/settings.h index 0edf3c73b..0709395f1 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -78,7 +78,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t no_hold_retain : 1; // bit 12 (v6.4.1.19) - SetOption62 - Don't use retain flag on HOLD messages uint32_t no_power_feedback : 1; // bit 13 (v6.5.0.9) - SetOption63 - Don't scan relay power state at restart uint32_t use_underscore : 1; // bit 14 (v6.5.0.12) - SetOption64 - Enable "_" instead of "-" as sensor index separator - uint32_t ex_tuya_disable_dimmer : 1; // bit 15 (v6.5.0.15) - SetOption65 - (Enable or Disable Tuya Serial Dimmer control) - free since 6.6.0.10 + uint32_t fast_power_cycle_disable : 1; // bit 15 (v6.6.0.20) - SetOption65 - Disable fast power cycle detection for device reset uint32_t ex_tuya_dimmer_range_255 : 1; // bit 16 (v6.6.0.1) - SetOption66 - Enable or Disable Dimmer range 255 slider control uint32_t buzzer_enable : 1; // bit 17 (v6.6.0.1) - SetOption67 - Enable buzzer when available uint32_t pwm_multi_channels : 1; // bit 18 (v6.6.0.3) - SetOption68 - Enable multi-channels PWM instead of Color PWM diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 8cd67a610..ae0f0577f 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -366,6 +366,8 @@ void SettingsSaveAll(void) void UpdateQuickPowerCycle(bool update) { + if (Settings.flag3.fast_power_cycle_disable) { return; } + uint32_t pc_register; uint32_t pc_location = SETTINGS_LOCATION - CFG_ROTATES; @@ -378,7 +380,7 @@ void UpdateQuickPowerCycle(bool update) } else { pc_register = 0xFFA55AB0 | counter; ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter); // Won't show as too early in power on sequence + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter); } } else if (pc_register != 0xFFA55ABF) { @@ -386,7 +388,7 @@ void UpdateQuickPowerCycle(bool update) // Assume flash is default all ones and setting a bit to zero does not need an erase ESP.flashEraseSector(pc_location); ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Reset")); // Won't show as too early in power on sequence + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Reset")); } } @@ -1137,11 +1139,11 @@ void SettingsDelta(void) if (Settings.version < 0x0606000A) { uint8_t tuyaindex = 0; - if (Settings.param[P_BACKLOG_DELAY] > 0) { // ex SetOption34 + if (Settings.param[P_BACKLOG_DELAY] > 0) { // ex SetOption34 Settings.tuya_fnid_map[tuyaindex].fnid = 21; // TUYA_MCU_FUNC_DIMMER - Move Tuya Dimmer Id to Map Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_BACKLOG_DELAY]; tuyaindex++; - } else if (Settings.flag3.ex_tuya_disable_dimmer == 1) { // ex SetOption65 + } else if (Settings.flag3.fast_power_cycle_disable == 1) { // ex SetOption65 Settings.tuya_fnid_map[tuyaindex].fnid = 11; // TUYA_MCU_FUNC_REL1 - Create FnID for Switches Settings.tuya_fnid_map[tuyaindex].dpid = 1; tuyaindex++; @@ -1195,6 +1197,20 @@ void SettingsDelta(void) Settings.dimmer_hw_max = Settings.param[P_ex_DIMMER_MAX]; } } + if (Settings.version < 0x06060014) { + // Clear unused parameters for future use + Settings.flag3.ex_tuya_dimmer_range_255 = 0; + Settings.flag3.ex_tuya_dimmer_min_limit = 0; + Settings.param[P_ex_TUYA_RELAYS] = 0; + Settings.param[P_ex_DIMMER_MAX] = 0; + Settings.param[P_ex_TUYA_VOLTAGE_ID] = 0; + Settings.param[P_ex_TUYA_CURRENT_ID] = 0; + Settings.param[P_ex_TUYA_POWER_ID] = 0; + Settings.ex_baudrate = 0; + Settings.ex_sbaudrate = 0; + + Settings.flag3.fast_power_cycle_disable = 0; + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 1c6d95b4b..0fbc690cc 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1472,7 +1472,6 @@ void setup(void) RtcRebootLoad(); if (!RtcRebootValid()) { RtcReboot.fast_reboot_count = 0; - UpdateQuickPowerCycle(true); // As RTC is invalid it must be a power cycle } RtcReboot.fast_reboot_count++; RtcRebootSave(); @@ -1497,6 +1496,7 @@ void setup(void) GetFeatures(); if (1 == RtcReboot.fast_reboot_count) { // Allow setting override only when all is well + UpdateQuickPowerCycle(true); XdrvCall(FUNC_SETTINGS_OVERRIDE); } @@ -1547,8 +1547,6 @@ void setup(void) } } -// UpdateQuickPowerCycle(true); // Test location - Format(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); Format(mqtt_topic, Settings.mqtt_topic, sizeof(mqtt_topic)); if (strstr(Settings.hostname, "%") != nullptr) { diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 828c71aa6..062d4dedf 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06060013; +const uint32_t VERSION = 0x06060014; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index c4a4a2504..558b843da 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -1685,8 +1685,8 @@ void LightAnimate(void) for (uint32_t i = 0; i < 3; i++) { scale_col[i] = (0 == max) ? 255 : (255 > max) ? changeUIntScale(cur_col[i], 0, max, 0, 255) : cur_col[i]; } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: R%d(%d) G%d(%d) B%d(%d), C%d W%d, D%d"), - cur_col[0], scale_col[0], cur_col[1], scale_col[1], cur_col[2], scale_col[2], cur_col[3], cur_col[4], light_state.getDimmer()); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: R%d(%d) G%d(%d) B%d(%d), C%d W%d, D%d"), +// cur_col[0], scale_col[0], cur_col[1], scale_col[1], cur_col[2], scale_col[2], cur_col[3], cur_col[4], light_state.getDimmer()); char *tmp_data = XdrvMailbox.data; char *tmp_topic = XdrvMailbox.topic; diff --git a/tools/decode-status.py b/tools/decode-status.py index 1abbc7b32..ce20da571 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -95,7 +95,7 @@ a_setoption = [[ "Ignore hold time (s)", "(not used) Number of Tuya MCU relays", "Over temperature threshold (celsius)", - "Tuya MCU max dimmer value", + "(not used) Tuya MCU max dimmer value", "(not used) Tuya MCU voltage Id", "(not used) Tuya MCU current Id", "(not used) Tuya MCU power Id", @@ -118,11 +118,11 @@ a_setoption = [[ "Do not use retain flag on HOLD messages", "Do not scan relay power state at restart", "Use _ instead of - as sensor index separator", - "(not used) Disable Dimmer slider control", - "Disable Dimmer range 255 slider control", + "Disable fast power cycle detection for device reset", + "(not used) Disable Dimmer range 255 slider control", "Enable buzzer when available", "Enable multi-channels PWM instead of Color PWM", - "Limits Tuya MCU dimmers to minimum of 10% (25) when enabled", + "(not used) Limits Tuya MCU dimmers to minimum of 10% (25) when enabled", "Enable Weekend Energy Tariff", "Select different Modbus registers for Active Energy", "","", From 63320f76f8509216fbbc768d44fc15c0c81860c7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 15:33:58 +0200 Subject: [PATCH 2177/2222] Prep for PowerDelta change --- sonoff/settings.h | 5 +++-- sonoff/settings.ino | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 0709395f1..027b073df 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -259,7 +259,7 @@ struct SYSCFG { int16_t toffset[2]; // 30E uint8_t display_font; // 312 char state_text[4][11]; // 313 - uint8_t energy_power_delta; // 33F + uint8_t ex_energy_power_delta; // 33F uint16_t domoticz_update_timer; // 340 uint16_t pwm_range; // 342 unsigned long domoticz_relay_idx[MAX_DOMOTICZ_IDX]; // 344 @@ -387,8 +387,9 @@ struct SYSCFG { uint16_t dimmer_hw_min; // E90 uint16_t dimmer_hw_max; // E92 uint32_t deepsleep; // E94 + uint16_t energy_power_delta; // E98 - uint8_t free_e98[352]; // E98 + uint8_t free_e9a[350]; // E9A uint32_t cfg_timestamp; // FF8 uint32_t cfg_crc32; // FFC diff --git a/sonoff/settings.ino b/sonoff/settings.ino index ae0f0577f..aa8646142 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -1210,6 +1210,8 @@ void SettingsDelta(void) Settings.ex_sbaudrate = 0; Settings.flag3.fast_power_cycle_disable = 0; + Settings.energy_power_delta = Settings.ex_energy_power_delta; + Settings.ex_energy_power_delta = 0; } Settings.version = VERSION; From 9f55ab6a2a21e572a5f0d11a6bad409aaf276005 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 16:53:30 +0200 Subject: [PATCH 2178/2222] Add absolute PowerDelta Add absolute PowerDelta using command PowerDelta 101..32000 where 101 = 101-100 = 1W, 202 = 202-100 = 102W (#5901) --- sonoff/_changelog.ino | 1 + sonoff/settings.h | 2 +- sonoff/xdrv_03_energy.ino | 44 +++++++++++++++++++-------------------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 64525de6d..ede627571 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /*********************************************************************************************\ * 6.6.0.20 20191018 * Add command SetOption65 0/1 to disable (1) fast power cycle detection fixing unwanted brownout trigger + * Add absolute PowerDelta using command PowerDelta 101..32000 where 101 = 101-100 = 1W, 202 = 202-100 = 102W (#5901) * * 6.6.0.19 20191018 * Replace obsolete xsns_23_sdm120 with xnrg_08_sdm120 and consolidate define USE_SDM120 diff --git a/sonoff/settings.h b/sonoff/settings.h index 027b073df..b31e0416d 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -259,7 +259,7 @@ struct SYSCFG { int16_t toffset[2]; // 30E uint8_t display_font; // 312 char state_text[4][11]; // 313 - uint8_t ex_energy_power_delta; // 33F + uint8_t ex_energy_power_delta; // 33F - Free since 6.6.0.20 uint16_t domoticz_update_timer; // 340 uint16_t pwm_range; // 342 unsigned long domoticz_relay_idx[MAX_DOMOTICZ_IDX]; // 344 diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index fbc7881b3..7df40b976 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -104,9 +104,9 @@ struct ENERGY { bool power_on = true; #ifdef USE_ENERGY_MARGIN_DETECTION - float power_history[3] = { 0 }; + uint16_t power_history[3] = { 0 }; uint8_t power_steady_counter = 8; // Allow for power on stabilization - uint8_t power_delta = 0; + bool power_delta = false; bool min_power_flag = false; bool max_power_flag = false; bool min_voltage_flag = false; @@ -279,41 +279,39 @@ bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool & void EnergyMarginCheck(void) { - uint16_t energy_daily_u = 0; - uint16_t energy_power_u = 0; - uint16_t energy_voltage_u = 0; - uint16_t energy_current_u = 0; - bool flag; - bool jsonflg; - if (Energy.power_steady_counter) { Energy.power_steady_counter--; return; } + uint16_t energy_power_u = (uint16_t)(Energy.active_power[0]); + if (Settings.energy_power_delta) { - float delta = abs(Energy.power_history[0] - Energy.active_power[0]); - // Any delta compared to minimal delta - float min_power = (Energy.power_history[0] > Energy.active_power[0]) ? Energy.active_power[0] : Energy.power_history[0]; - if (((delta / min_power) * 100) > Settings.energy_power_delta) { - Energy.power_delta = 1; + uint16_t delta = abs(Energy.power_history[0] - energy_power_u); + uint16_t min_power = (Energy.power_history[0] > energy_power_u) ? energy_power_u : Energy.power_history[0]; + + DEBUG_DRIVER_LOG(PSTR("NRG: Delta %d, Power %d"), delta, min_power); + + if ( ((Settings.energy_power_delta < 101) && (((delta * 100) / min_power) > Settings.energy_power_delta)) || // 1..100 = Percentage + ((Settings.energy_power_delta > 100) && (delta > (Settings.energy_power_delta -100))) ) { // 101..32000 = Absolute + Energy.power_delta = true; Energy.power_history[1] = Energy.active_power[0]; // We only want one report so reset history Energy.power_history[2] = Energy.active_power[0]; } } Energy.power_history[0] = Energy.power_history[1]; // Shift in history every second allowing power changes to settle for up to three seconds Energy.power_history[1] = Energy.power_history[2]; - Energy.power_history[2] = Energy.active_power[0]; + Energy.power_history[2] = energy_power_u; if (Energy.power_on && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) { - energy_power_u = (uint16_t)(Energy.active_power[0]); - energy_voltage_u = (uint16_t)(Energy.voltage[0]); - energy_current_u = (uint16_t)(Energy.current[0] * 1000); + uint16_t energy_voltage_u = (uint16_t)(Energy.voltage[0]); + uint16_t energy_current_u = (uint16_t)(Energy.current[0] * 1000); DEBUG_DRIVER_LOG(PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); Response_P(PSTR("{")); - jsonflg = false; + bool flag; + bool jsonflg = false; if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, Energy.min_power_flag)) { ResponseAppend_P(PSTR("%s\"" D_CMND_POWERLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; @@ -392,7 +390,7 @@ void EnergyMarginCheck(void) // Max Energy if (Settings.energy_max_energy) { - energy_daily_u = (uint16_t)(Energy.daily * 1000); + uint16_t energy_daily_u = (uint16_t)(Energy.daily * 1000); if (!Energy.max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) { Energy.max_energy_state = 1; ResponseTime_P(PSTR(",\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); @@ -424,7 +422,7 @@ void EnergyMqttShow(void) tele_period = tele_period_save; ResponseJsonEnd(); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - Energy.power_delta = 0; + Energy.power_delta = false; } #endif // USE_ENERGY_MARGIN_DETECTION @@ -708,10 +706,10 @@ void CmndModuleAddress(void) #ifdef USE_ENERGY_MARGIN_DETECTION void CmndPowerDelta(void) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 101)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32000)) { Settings.energy_power_delta = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_power_delta, UNIT_PERCENTAGE); + EnergyCommandResponse(Settings.energy_power_delta, (Settings.energy_power_delta < 101) ? UNIT_PERCENTAGE : UNIT_WATT); } void CmndPowerLow(void) From 4e45e660f23fafe52679cb3964e91b48d6c4d372 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 17:29:19 +0200 Subject: [PATCH 2179/2222] Add support for EX-Store WiFi Dimmer V4 Add support for EX-Store WiFi Dimmer V4 (#5856) --- sonoff/_changelog.ino | 1 + sonoff/language/bg-BG.h | 1 + sonoff/language/cs-CZ.h | 1 + sonoff/language/de-DE.h | 1 + sonoff/language/el-GR.h | 1 + sonoff/language/en-GB.h | 1 + sonoff/language/es-ES.h | 1 + sonoff/language/fr-FR.h | 1 + sonoff/language/he-HE.h | 1 + sonoff/language/hu-HU.h | 1 + sonoff/language/it-IT.h | 1 + sonoff/language/ko-KO.h | 1 + sonoff/language/nl-NL.h | 1 + sonoff/language/pl-PL.h | 1 + sonoff/language/pt-BR.h | 1 + sonoff/language/pt-PT.h | 1 + sonoff/language/ru-RU.h | 1 + sonoff/language/sk-SK.h | 1 + sonoff/language/sv-SE.h | 1 + sonoff/language/tr-TR.h | 1 + sonoff/language/uk-UK.h | 1 + sonoff/language/zh-CN.h | 1 + sonoff/language/zh-TW.h | 1 + sonoff/my_user_config.h | 2 + sonoff/sonoff_post.h | 6 + sonoff/sonoff_template.h | 31 +- sonoff/support_features.ino | 6 +- sonoff/xdrv_30_exs_dimmer.ino | 624 ++++++++++++++++++++++++++++++++++ tools/decode-status.py | 2 +- 29 files changed, 690 insertions(+), 4 deletions(-) create mode 100644 sonoff/xdrv_30_exs_dimmer.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index ede627571..b2badf70f 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * 6.6.0.20 20191018 * Add command SetOption65 0/1 to disable (1) fast power cycle detection fixing unwanted brownout trigger * Add absolute PowerDelta using command PowerDelta 101..32000 where 101 = 101-100 = 1W, 202 = 202-100 = 102W (#5901) + * Add support for EX-Store WiFi Dimmer V4 (#5856) * * 6.6.0.19 20191018 * Replace obsolete xsns_23_sdm120 with xnrg_08_sdm120 and consolidate define USE_SDM120 diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 29e932cfc..a24e95d70 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 948853f3d..31b23dac9 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 2627e3986..849d356af 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 7dc1bdad1..325558b83 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 1ce9f12b9..5cee90b5c 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-ES.h b/sonoff/language/es-ES.h index f9ce932a3..f5f31ffc6 100644 --- a/sonoff/language/es-ES.h +++ b/sonoff/language/es-ES.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index a0cee0290..b52156447 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index c609b5ac6..52c9d8cf9 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index b014b531a..635756447 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 46ab48e52..7a35a4dfc 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index 6da901543..6ae84f9a7 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 728b5249e..fd94dbe09 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index a1610bef0..b871a18ea 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 737e785a4..b4048fe8c 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index f6f106bce..80ac976b7 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index c03ae5feb..543d8a4f1 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 6ca306f54..207764960 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index f03aa1539..79cf9dedc 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 39881132e..f28f951d9 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 02ac21a24..0ea4127c7 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 264964b2e..22ac1f9cf 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 3c3afd739..437656457 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -626,6 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_MCU_RESET "EXS Reset" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index ad25e3b3a..33a3f9208 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -321,6 +321,8 @@ #define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) //#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+6k code) //#define USE_DEEPSLEEP // Add support for deepsleep (+1k code) +//#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) +// #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 1446d8946..8e0e95cf4 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -101,6 +101,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) //#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+6k code) //#define USE_DEEPSLEEP // Add support for deepsleep (+1k code) +//#define USE_EXS_DIMMER // Add support for EX-Store WiFi Dimmer // -- Optional light modules ---------------------- #define USE_LIGHT // Add Dimmer/Light support @@ -256,6 +257,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) #undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) +#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer // -- Optional light modules ---------------------- //#undef USE_LIGHT // Disable Dimmer/Light support @@ -364,6 +366,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) #undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) +#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer #undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) #undef USE_PZEM004T // Disable PZEM004T energy sensor @@ -435,6 +438,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) #undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) +#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer // -- Optional light modules ---------------------- //#undef USE_LIGHT // Also disable all Dimmer/Light support @@ -532,6 +536,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) #undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) +#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer // -- Optional light modules ---------------------- //#undef USE_LIGHT // Also disable all Dimmer/Light support @@ -631,6 +636,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) #undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) +#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer // -- Optional light modules ---------------------- #undef USE_LIGHT // Disable support for lights diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 2a3ddcaca..c6ed63361 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -207,6 +207,7 @@ enum UserSelectablePins { GPIO_SM2135_CLK, // SM2135 Clk GPIO_SM2135_DAT, // SM2135 Dat GPIO_DEEPSLEEP, // Kill switch for deepsleep + GPIO_EXS_MCU_RESET, // EXS MCU Reset GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -284,7 +285,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_DDS2382_TX "|" D_SENSOR_DDS2382_RX "|" D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|" D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|" - D_SENSOR_DEEPSLEEP "|" + D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_MCU_RESET "|" ; const char kSensorNamesFixed[] PROGMEM = @@ -392,6 +393,7 @@ enum SupportedModules { SYF05, SONOFF_L1, SONOFF_IFAN03, + EXS_DIMMER, MAXMODULE}; #define USER_MODULE 255 @@ -573,6 +575,9 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_TUYA_TX, // Tuya Serial interface GPIO_TUYA_RX, // Tuya Serial interface #endif +#ifdef USE_EXS_DIMMER + GPIO_EXS_MCU_RESET, // EXS MCU Reset +#endif #endif // USE_LIGHT #if defined(USE_IR_REMOTE) || defined(USE_IR_REMOTE_FULL) @@ -803,6 +808,9 @@ const uint8_t kModuleNiceList[] PROGMEM = { #endif #ifdef USE_PS_16_DZ PS_16_DZ, +#endif +#ifdef USE_EXS_DIMMER + EXS_DIMMER, #endif H801, // Light Devices MAGICHOME, @@ -2122,6 +2130,27 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL2, // GPIO14 WIFI_O1 Relay 2 (0 = Off, 1 = On) controlling the fan GPIO_REL4, // GPIO15 WIFI_O3 Relay 4 (0 = Off, 1 = On) controlling the fan 0, 0 + }, + { "EXS Dimmer", // EXS_DIMMER - EX-Stroe WiFi Dimmer v4, two channel (ESP8266 w/ separate MCU dimmer) + // https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A + // https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A-ESP8266-V12-Stift-und-Buchsenleisten + 0, + GPIO_TXD, // GPIO01 MCU serial control + 0, + GPIO_RXD, // GPIO03 MCU serial control + GPIO_USER, // GPIO04 + GPIO_USER, // GPIO05 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 + GPIO_EXS_MCU_RESET, // GPIO13 EXS MCU Reset + GPIO_USER, // GPIO14 + 0, // GPIO15 + 0, 0 } }; diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 6ee9afe21..a159377d8 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -472,9 +472,11 @@ void GetFeatures(void) feature5 |= 0x00002000; // xdrv_06_snfbridge.ino #endif #ifdef USE_SONOFF_L1 - feature5 |= 0x00004000; + feature5 |= 0x00004000; // xlgt_05_sonoff_l1.ino +#endif +#ifdef USE_EXS_DIMMER + feature5 |= 0x00008000; // xdrv_30_exs_dimmer.ino #endif -// feature5 |= 0x00008000; // feature5 |= 0x00010000; // feature5 |= 0x00020000; diff --git a/sonoff/xdrv_30_exs_dimmer.ino b/sonoff/xdrv_30_exs_dimmer.ino new file mode 100644 index 000000000..63b489b56 --- /dev/null +++ b/sonoff/xdrv_30_exs_dimmer.ino @@ -0,0 +1,624 @@ +/* + xdrv_30_exs_dimmer.ino - ex-store dimmer support for Sonoff-Tasmota + + Copyright (C) 2019 Andreas Schultz + + 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_LIGHT +#ifdef USE_EXS_DIMMER +/*********************************************************************************************\ + * EX-Store WiFi Dimmer V4 + * https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A + * https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A-ESP8266-V12-Stift-und-Buchsenleisten +\*********************************************************************************************/ +//#define EXS_DEBUG + +#define XDRV_30 30 + +#define EXS_GATE_1_ON 0x20 +#define EXS_GATE_1_OFF 0x21 +#define EXS_DIMM_1_ON 0x22 +#define EXS_DIMM_1_OFF 0x23 +#define EXS_DIMM_1_TBL 0x24 +#define EXS_DIMM_1_VAL 0x25 +#define EXS_GATE_2_ON 0x30 +#define EXS_GATE_2_OFF 0x31 +#define EXS_DIMM_2_ON 0x32 +#define EXS_DIMM_2_OFF 0x33 +#define EXS_DIMM_2_TBL 0x34 +#define EXS_DIMM_2_VAL 0x35 +#define EXS_GATES_ON 0x40 +#define EXS_GATES_OFF 0x41 +#define EXS_DIMMS_ON 0x50 +#define EXS_DIMMS_OFF 0x51 +#define EXS_CH_LOCK 0x60 +#define EXS_GET_VALUES 0xFA +#define EXS_WRITE_EE 0xFC +#define EXS_READ_EE 0xFD +#define EXS_GET_VERSION 0xFE +#define EXS_RESET 0xFF + +#define EXS_BUFFER_SIZE 256 +#define EXS_ACK_TIMEOUT 200 // 200 ms ACK timeout + +#include + +TasmotaSerial *ExsSerial = nullptr; + +typedef struct +{ + uint8_t on = 0; + uint8_t bright_tbl = 0; + uint8_t dimm = 0; + uint8_t impuls_start = 0; + uint32_t impuls_len = 0; +} CHANNEL; + +typedef struct +{ + uint8_t version_major = 0; + uint8_t version_minor = 0; + CHANNEL channel[2]; + uint8_t gate_lock = 0; +} DIMMER; + +struct EXS +{ + uint8_t *buffer = nullptr; // Serial receive buffer + int byte_counter = 0; // Index in serial receive buffer + int cmd_status = 0; + uint8_t power = 0; + uint8_t dimm[2] = {0, 0}; + DIMMER dimmer; +} Exs; + +/* + * Internal Functions + */ + +uint8_t crc8(const uint8_t *p, uint8_t len) +{ + const uint8_t table[] = { + 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, + 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D}; + + const uint8_t table_rev[] = { + 0x00, 0x70, 0xE0, 0x90, 0xC1, 0xB1, 0x21, 0x51, + 0x83, 0xF3, 0x63, 0x13, 0x42, 0x32, 0xA2, 0xD2}; + + uint8_t offset; + uint8_t temp, crc8_temp; + uint8_t crc8 = 0; + + for (int i = 0; i < len; i++) + { + temp = *(p + i); + offset = temp ^ crc8; + offset >>= 4; + crc8_temp = crc8 & 0x0f; + crc8 = crc8_temp ^ table_rev[offset]; + offset = crc8 ^ temp; + offset &= 0x0f; + crc8_temp = crc8 & 0xf0; + crc8 = crc8_temp ^ table[offset]; + } + return crc8 ^ 0x55; +} + +void ExsSerialSend(const uint8_t data[] = nullptr, uint16_t len = 0) +{ + int retries = 3; + char rc; + +#ifdef EXS_DEBUG + snprintf_P(log_data, sizeof(log_data), PSTR("EXS: Tx Packet: \"")); + for (uint32_t i = 0; i < len; i++) + { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, data[i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + + while (retries) + { + retries--; + + ExsSerial->write(data, len); + ExsSerial->flush(); + + // wait for any response + uint32_t snd_time = millis(); + while ((TimePassedSince(snd_time) < EXS_ACK_TIMEOUT) && + (!ExsSerial->available())) + ; + + if (!ExsSerial->available()) + { + // timeout +#ifdef EXS_DEBUG + AddLog_P(LOG_LEVEL_DEBUG, PSTR("ESX: serial send timeout")); +#endif + continue; + } + + rc = ExsSerial->read(); + if (rc == 0xFF) + break; + } +} + +void ExsSendCmd(uint8_t cmd, uint8_t value) +{ + uint8_t buffer[8]; + uint16_t len; + + buffer[0] = 0x7b; + buffer[3] = cmd; + + switch (cmd) + { + case EXS_GATE_1_ON: + case EXS_GATE_1_OFF: + case EXS_DIMM_1_ON: + case EXS_DIMM_1_OFF: + case EXS_GATE_2_ON: + case EXS_GATE_2_OFF: + case EXS_DIMM_2_ON: + case EXS_DIMM_2_OFF: + case EXS_GATES_ON: + case EXS_GATES_OFF: + case EXS_DIMMS_ON: + case EXS_DIMMS_OFF: + case EXS_GET_VALUES: + case EXS_GET_VERSION: + case EXS_RESET: + buffer[2] = 1; + len = 4; + break; + + case EXS_CH_LOCK: + case EXS_DIMM_1_TBL: + case EXS_DIMM_1_VAL: + case EXS_DIMM_2_TBL: + case EXS_DIMM_2_VAL: + buffer[2] = 2; + buffer[4] = value; + len = 5; + break; + } + buffer[1] = crc8(&buffer[3], buffer[2]); + + ExsSerialSend(buffer, len); +} + +uint8_t ExsSetPower(uint8_t device, uint8_t power) +{ + Exs.dimmer.channel[device].dimm = power; + ExsSendCmd(EXS_DIMM_1_ON + 0x10 * device + power ^ 1, 0); +} + +uint8_t ExsSetBri(uint8_t device, uint8_t bri) +{ + Exs.dimmer.channel[device].bright_tbl = bri; + ExsSendCmd(EXS_DIMM_1_TBL + 0x10 * device, bri); +} + +uint8_t ExsSyncState(uint8_t device) +{ +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Channel %d Power Want %d, Is %d"), + device, bitRead(Exs.power, device), Exs.dimmer.channel[device].dimm); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Set Channel %d Brightness Want %d, Is %d"), + device, Exs.dimm[device], Exs.dimmer.channel[device].bright_tbl); +#endif + + if (bitRead(Exs.power, device) && + Exs.dimm[device] != Exs.dimmer.channel[device].bright_tbl) { + ExsSetBri(device, Exs.dimm[device]); + } + + if (!Exs.dimm[device]) { + Exs.dimmer.channel[device].dimm = 0; + } else if (Exs.dimmer.channel[device].dimm != bitRead(Exs.power, device)) { + ExsSetPower(device, bitRead(Exs.power, device)); + } +} + +bool ExsSyncState() +{ +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Serial %p, Cmd %d"), ExsSerial, Exs.cmd_status); +#endif + + if (!ExsSerial || Exs.cmd_status != 0) + return false; + + ExsSyncState(0); + ExsSyncState(1); +} + +static inline void ExsSetChannelV10(uint8_t channel, const uint8_t *buffer) +{ + Exs.dimmer.channel[channel].on = buffer[0]; + Exs.dimmer.channel[channel].dimm = buffer[1]; + Exs.dimmer.channel[channel].bright_tbl = 0; +} + +static inline void ExsSetChannel(uint8_t channel, const uint8_t *buffer) +{ + Exs.dimmer.channel[channel].on = buffer[0]; + Exs.dimmer.channel[channel].dimm = buffer[1]; + Exs.dimmer.channel[channel].bright_tbl = buffer[2]; +} + +void ExsDebugState() +{ +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: MCU v%d.%d, c0: On:%d,Dim:%d,Tbl:%d(%d%%), c1: On:%d,Dim:%d,Tbl:%d(%d%%), ChLock: %d"), + Exs.dimmer.version_major, Exs.dimmer.version_minor, + Exs.dimmer.channel[0].on, Exs.dimmer.channel[0].dimm, + Exs.dimmer.channel[0].bright_tbl, + changeUIntScale(Exs.dimmer.channel[0].bright_tbl, 0, 255, 0, 100), + Exs.dimmer.channel[1].on, Exs.dimmer.channel[1].dimm, + Exs.dimmer.channel[1].bright_tbl, + changeUIntScale(Exs.dimmer.channel[1].bright_tbl, 0, 255, 0, 100), + Exs.dimmer.gate_lock); +#endif +} + +void ExsPacketProcess(void) +{ + uint8_t len = Exs.buffer[1]; + uint8_t cmd = Exs.buffer[2]; + + switch (cmd) + { + case EXS_GET_VALUES: + if (len > 9) + { + Exs.dimmer.version_major = Exs.buffer[3]; + Exs.dimmer.version_minor = Exs.buffer[4]; + ExsSetChannel(0, &Exs.buffer[5]); + ExsSetChannel(1, &Exs.buffer[8]); + Exs.dimmer.gate_lock = Exs.buffer[11]; + } + else + { + Exs.dimmer.version_major = 1; + Exs.dimmer.version_minor = 0; + ExsSetChannel(0, &Exs.buffer[3]); + ExsSetChannel(1, &Exs.buffer[5]); + Exs.dimmer.gate_lock = Exs.buffer[8]; + } + + ExsDebugState(); + ExsSyncState(); + ExsDebugState(); + break; + default: + break; + } +} + +/* + * API Functions + */ +bool ExsModuleSelected(void) +{ + Settings.light_correction = 0; + Settings.flag.mqtt_serial = 0; + Settings.flag3.pwm_multi_channels = 1; + SetSeriallog(LOG_LEVEL_NONE); + + devices_present = +2; + light_type = LT_SERIAL2; + return true; +} + +bool ExsSetChannels(void) +{ +#ifdef EXS_DEBUG + snprintf_P(log_data, sizeof(log_data), PSTR("EXS: SetChannels: \"")); + for (int i = 0; i < XdrvMailbox.data_len; i++) + { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, ((uint8_t *)XdrvMailbox.data)[i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + + Exs.dimm[0] = ((uint8_t *)XdrvMailbox.data)[0]; + Exs.dimm[1] = ((uint8_t *)XdrvMailbox.data)[1]; + return ExsSyncState(); +} + +bool ExsSetPower(void) +{ + AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Set Power, Device %d, Power 0x%02x"), + active_device, XdrvMailbox.index); + + Exs.power = XdrvMailbox.index; + return ExsSyncState(); +} + +void EsxMcuStart(void) +{ + int retries = 3; + +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Request MCU configuration, PIN %d to Low"), pin[GPIO_EXS_MCU_RESET]); +#endif + + pinMode(pin[GPIO_EXS_MCU_RESET], OUTPUT); + digitalWrite(pin[GPIO_EXS_MCU_RESET], LOW); + + delay(1); // wait 1ms fot the MCU to come online + + while (ExsSerial->available()) + { + // clear in the receive buffer + ExsSerial->read(); + } +} + +void ExsInit(void) +{ +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Starting Tx %d Rx %d"), pin[GPIO_TXD], pin[GPIO_RXD]); +#endif + + Exs.buffer = (uint8_t *)malloc(EXS_BUFFER_SIZE); + if (Exs.buffer != nullptr) + { + ExsSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (ExsSerial->begin(9600)) + { + if (ExsSerial->hardwareSerial()) + { + ClaimSerial(); + } + ExsSerial->flush(); + EsxMcuStart(); + ExsSendCmd(EXS_CH_LOCK, 0); + ExsSendCmd(EXS_GET_VALUES, 0); + } + } +} + +void ExsSerialInput(void) +{ + while (ExsSerial->available()) + { + yield(); + uint8_t serial_in_byte = ExsSerial->read(); + + AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Serial In Byte 0x%02x"), serial_in_byte); + + if (Exs.cmd_status == 0 && + serial_in_byte == 0x7B) + { + Exs.cmd_status = 1; + Exs.byte_counter = 0; + } + else if (Exs.byte_counter >= EXS_BUFFER_SIZE) + { + Exs.cmd_status = 0; + } + else if (Exs.cmd_status == 1) + { + Exs.buffer[Exs.byte_counter++] = serial_in_byte; + + if (Exs.byte_counter > 2 && Exs.byte_counter == Exs.buffer[1] + 2) + { + uint8_t crc = crc8(&Exs.buffer[2], Exs.buffer[1]); + + // all read + Exs.cmd_status = 0; + +#ifdef EXS_DEBUG + snprintf_P(log_data, sizeof(log_data), PSTR("EXS: RX Packet: \"")); + for (uint32_t i = 0; i < Exs.byte_counter; i++) + { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, Exs.buffer[i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s\", CRC: 0x%02x"), log_data, crc); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + + if (Exs.buffer[0] == crc) + { + ExsSerial->write(0xFF); //send ACK + ExsPacketProcess(); + } + else + { + ExsSerial->write(0x00); //send NO-ACK + } + + } + } + } +} + +/* + * Commands + */ + +#ifdef EXS_MCU_CMNDS + +#define D_PRFX_EXS "Exs" +#define D_CMND_EXS_GATE "Gate" +#define D_CMND_EXS_DIMM "Dimm" +#define D_CMND_EXS_DIMM_TBL "DimmTbl" +#define D_CMND_EXS_DIMM_VAL "DimmVal" +#define D_CMND_EXS_GATES "Gates" +#define D_CMND_EXS_DIMMS "Dimms" +#define D_CMND_EXS_CH_LOCK "ChLock" +#define D_CMND_EXS_STATE "State" + +const char kExsCommands[] PROGMEM = D_PRFX_EXS "|" + D_CMND_EXS_GATE "|" + D_CMND_EXS_DIMM "|" D_CMND_EXS_DIMM_TBL "|" D_CMND_EXS_DIMM_VAL "|" + D_CMND_EXS_GATES "|" D_CMND_EXS_DIMMS "|" D_CMND_EXS_CH_LOCK "|" + D_CMND_EXS_STATE; + +void (* const ExsCommand[])(void) PROGMEM = + { &CmndExsGate, + &CmndExsDimm, &CmndExsDimmTbl, &CmndExsDimmVal, + &CmndExsGates, &CmndExsDimms, &CmndExsChLock, + &CmndExsState }; + +void CmndExsGate(void) +{ + if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && + (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1)) { + ExsSendCmd(EXS_GATE_1_ON + 0x10 * (XdrvMailbox.index - 1) + + XdrvMailbox.payload ^ 1, 0); + } + CmndExsState(); +} + +void CmndExsDimm(void) +{ + if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && + (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1)) { + ExsSendCmd(EXS_DIMM_1_ON + 0x10 * (XdrvMailbox.index - 1) + + XdrvMailbox.payload ^ 1, 0); + } + CmndExsState(); +} + +void CmndExsDimmTbl(void) +{ + if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && + (XdrvMailbox.payload > 0 || XdrvMailbox.payload <= 255)) { + ExsSendCmd(EXS_DIMM_1_TBL + 0x10 * (XdrvMailbox.index - 1), + XdrvMailbox.payload); + } + CmndExsState(); +} + +void CmndExsDimmVal(void) +{ + if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && + (XdrvMailbox.payload > 0 || XdrvMailbox.payload <= 255)) { + ExsSendCmd(EXS_DIMM_1_VAL + 0x10 * (XdrvMailbox.index - 1), + XdrvMailbox.payload); + } + CmndExsState(); +} + +void CmndExsGates(void) +{ + if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { + ExsSendCmd(EXS_GATES_ON + XdrvMailbox.payload ^ 1, 0); + } + CmndExsState(); +} + +void CmndExsDimms(void) +{ + if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { + ExsSendCmd(EXS_DIMMS_ON + XdrvMailbox.payload ^ 1, 0); + } + CmndExsState(); +} + +void CmndExsChLock(void) +{ + if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { + ExsSendCmd(EXS_CH_LOCK, XdrvMailbox.payload); + } + CmndExsState(); +} + +void CmndExsState(void) +{ + ExsSendCmd(EXS_GET_VALUES, 0); + + // wait for data + uint32_t snd_time = millis(); + while ((TimePassedSince(snd_time) < EXS_ACK_TIMEOUT) && + (!ExsSerial->available())) + ; + ExsSerialInput(); + + Response_P(PSTR("{\"" D_CMND_EXS_STATE "\":{")); + ResponseAppend_P(PSTR("\"McuVersion\":\"%d.%d\"," + "\"Channels\":["), + Exs.dimmer.version_major, Exs.dimmer.version_minor); + + for (uint32_t i = 0; i < 2; i++) { + if (i != 0) { + ResponseAppend_P(PSTR(",")); + } + ResponseAppend_P(PSTR("{\"On\":\"%d\"," + "\"BrightProz\":\"%d\"," + "\"BrightTab\":\"%d\"," + "\"Dimm\":\"%d\"}"), + Exs.dimmer.channel[i].on, + changeUIntScale(Exs.dimmer.channel[i].bright_tbl, 0, 255, 0, 100), + Exs.dimmer.channel[i].bright_tbl, + Exs.dimmer.channel[i].dimm); + } + ResponseAppend_P(PSTR("],")); + ResponseAppend_P(PSTR("\"GateLock\":\"%d\""), Exs.dimmer.gate_lock); + ResponseJsonEndEnd(); +} + +#endif + +/* + * Interface + */ + +bool Xdrv30(uint8_t function) +{ + bool result = false; + + if (EXS_DIMMER == my_module_type) + { + switch (function) + { + case FUNC_LOOP: + if (ExsSerial) + ExsSerialInput(); + break; + case FUNC_MODULE_INIT: + result = ExsModuleSelected(); + break; + case FUNC_INIT: + ExsInit(); + break; + case FUNC_SET_DEVICE_POWER: + result = ExsSetPower(); + break; + case FUNC_SET_CHANNELS: + result = ExsSetChannels(); + break; +#ifdef EXS_MCU_CMNDS + case FUNC_COMMAND: + result = DecodeCommand(kExsCommands, ExsCommand); + break; +#endif + } + } + return result; +} + +#endif // USE_EXS_DIMMER +#endif // USE_LIGHT \ No newline at end of file diff --git a/tools/decode-status.py b/tools/decode-status.py index ce20da571..7b8bce742 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -172,7 +172,7 @@ a_features = [[ "USE_BUZZER","USE_RDM6300","USE_IBEACON","USE_SML_M", "USE_INA226","USE_A4988_STEPPER","USE_DDS2382","USE_SM2135", "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", - "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","", + "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","USE_EXS_DIMMER", "","","","", "","","","", "","","","", From c2ecd487b0ef09706baa00c64ae5d94a75b8828c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 17:35:56 +0200 Subject: [PATCH 2180/2222] Oops --- RELEASENOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ef0af1ff9..d8dcaec76 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -149,6 +149,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_ARILUX_RF | - | - | - | x | x | x | - | | USE_SHUTTER | - | - | - | - | - | - | - | | USE_DEEPSLEEP | - | - | - | - | - | - | - | +| USE_EXS_DIMMER | - | - | - | - | - | - | - | | | | | | | | | | | Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks | USE_LIGHT | - | x | x | x | x | x | x | From d62d33bc4d051624f7113adf6cc8da35ec6cfb37 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 18 Oct 2019 18:06:17 +0200 Subject: [PATCH 2181/2222] Fix display hPa and mmHg Fix display hPa and mmHg (#2642) --- sonoff/xdrv_13_display.ino | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 3a144b6c9..9aa17139f 100755 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -111,6 +111,7 @@ uint8_t dsp_on; char **disp_log_buffer; char **disp_screen_buffer; char disp_temp[2]; // C or F +char disp_pres[5]; // hPa or mmHg uint8_t disp_log_buffer_cols = 0; uint8_t disp_log_buffer_idx = 0; @@ -995,6 +996,7 @@ void DisplayLogBufferInit(void) disp_refresh = Settings.display_refresh; snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit()); + snprintf_P(disp_pres, sizeof(disp_pres), PressureUnit().c_str()); DisplayReAllocLogBuffer(); @@ -1079,7 +1081,7 @@ void DisplayJsonValue(const char* topic, const char* device, const char* mkey, c snprintf_P(svalue, sizeof(svalue), PSTR("%s%%"), value); } else if ((quantity_code >= JSON_PRESSURE) && (quantity_code <= JSON_PRESSUREATSEALEVEL)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PRESSURE), value); + snprintf_P(svalue, sizeof(svalue), PSTR("%s%s"), value, disp_pres); } else if (JSON_ILLUMINANCE == quantity_code) { snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_LUX), value); @@ -1130,7 +1132,6 @@ void DisplayAnalyzeJson(char *topic, char *json) // tele/wemos5/SENSOR {"Time":"2017-09-20T11:53:53","SHT1X":{"Temperature":20.1,"Humidity":58.9},"HTU21":{"Temperature":20.7,"Humidity":58.5},"BMP280":{"Temperature":21.6,"Pressure":1020.3},"TempUnit":"C"} // tele/th1/SENSOR {"Time":"2017-09-20T11:54:48","DS18B20":{"Temperature":49.7},"TempUnit":"C"} - const char *tempunit; // char jsonStr[MESSZ]; // strlcpy(jsonStr, json, sizeof(jsonStr)); // Save original before destruction by JsonObject @@ -1140,10 +1141,14 @@ void DisplayAnalyzeJson(char *topic, char *json) JsonObject &root = jsonBuf.parseObject(jsonStr); if (root.success()) { - tempunit = root[D_JSON_TEMPERATURE_UNIT]; - if (tempunit) { - snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%s"), tempunit); -// AddLog_P2(LOG_LEVEL_DEBUG, disp_temp); + const char *unit; + unit = root[D_JSON_TEMPERATURE_UNIT]; + if (unit) { + snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%s"), unit); // C or F + } + unit = root[D_JSON_PRESSURE_UNIT]; + if (unit) { + snprintf_P(disp_pres, sizeof(disp_pres), PSTR("%s"), unit); // hPa or mmHg } for (JsonObject::iterator it = root.begin(); it != root.end(); ++it) { From 13b016191956fcf70733b26c9bc72f7a9110de26 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sat, 19 Oct 2019 12:46:00 +0200 Subject: [PATCH 2182/2222] fix ssd1306 rotate --- .../Adafruit_SSD1306.cpp | 16 ++++++++++++++++ .../Adafruit_SSD1306.h | 1 + 2 files changed, 17 insertions(+) diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp index b2f27c20f..9015c6e83 100644 --- a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp +++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp @@ -584,6 +584,22 @@ boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset, } +void Adafruit_SSD1306::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) { +// ignore update mode + //if (p==DISPLAY_INIT_MODE) { + setRotation(rot); + invertDisplay(false); + setTextWrap(false); // Allow text to run off edges + cp437(true); + setTextFont(font); + setTextSize(size); + setTextColor(WHITE,BLACK); + setCursor(0,0); + fillScreen(BLACK); + Updateframe(); + //} +} + #if 0 // DRAWING FUNCTIONS ------------------------------------------------------- diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h index 5df0ceba8..5be544199 100644 --- a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h +++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.h @@ -141,6 +141,7 @@ public: void invertDisplay(boolean i); void dim(boolean dim); void DisplayOnff(int8_t on); + void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font); #if 0 void clearDisplay(void); From 3cfbb83477590c37c46f3045998f427095cff459 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 19 Oct 2019 12:46:31 +0200 Subject: [PATCH 2183/2222] Fix display rotation Fix display rotation (#6687) --- sonoff/xdrv_13_display.ino | 4 +++- sonoff/xdsp_02_ssd1306.ino | 2 +- sonoff/xdsp_07_sh1106.ino | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 9aa17139f..6ace31eb2 100755 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -127,7 +127,9 @@ bool disp_subscribed = false; void DisplayInit(uint8_t mode) { if (renderer) { - renderer->DisplayInit(mode,Settings.display_size,Settings.display_rotate,Settings.display_font); + renderer->DisplayInit(mode, Settings.display_size, Settings.display_rotate, Settings.display_font); + // Add below line as the parameters above do nothing + renderer->setRotation(Settings.display_rotate); } else { dsp_init = mode; diff --git a/sonoff/xdsp_02_ssd1306.ino b/sonoff/xdsp_02_ssd1306.ino index 078ef1f09..221bf9e3f 100755 --- a/sonoff/xdsp_02_ssd1306.ino +++ b/sonoff/xdsp_02_ssd1306.ino @@ -84,7 +84,7 @@ void SSD1306InitDriver() oled1306->begin(SSD1306_SWITCHCAPVCC, Settings.display_address[0], 0); renderer = oled1306; renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font); - + renderer->setRotation(Settings.display_rotate); renderer->setTextColor(1,0); #ifdef SHOW_SPLASH diff --git a/sonoff/xdsp_07_sh1106.ino b/sonoff/xdsp_07_sh1106.ino index 6c535b02a..e8fc24107 100644 --- a/sonoff/xdsp_07_sh1106.ino +++ b/sonoff/xdsp_07_sh1106.ino @@ -79,6 +79,7 @@ void SH1106InitDriver() renderer=oled1106; renderer->Begin(SH1106_SWITCHCAPVCC, Settings.display_address[0],0); renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + renderer->setRotation(Settings.display_rotate); renderer->setTextColor(1,0); #ifdef SHOW_SPLASH From 9bec8dedb9d14b6dd266aadff28bf8529a4d7ffc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 19 Oct 2019 14:02:31 +0200 Subject: [PATCH 2184/2222] Revert previous commit --- sonoff/xdrv_13_display.ino | 2 -- sonoff/xdsp_02_ssd1306.ino | 1 - sonoff/xdsp_07_sh1106.ino | 1 - 3 files changed, 4 deletions(-) diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 6ace31eb2..0317c4e03 100755 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -128,8 +128,6 @@ void DisplayInit(uint8_t mode) { if (renderer) { renderer->DisplayInit(mode, Settings.display_size, Settings.display_rotate, Settings.display_font); - // Add below line as the parameters above do nothing - renderer->setRotation(Settings.display_rotate); } else { dsp_init = mode; diff --git a/sonoff/xdsp_02_ssd1306.ino b/sonoff/xdsp_02_ssd1306.ino index 221bf9e3f..04251b595 100755 --- a/sonoff/xdsp_02_ssd1306.ino +++ b/sonoff/xdsp_02_ssd1306.ino @@ -84,7 +84,6 @@ void SSD1306InitDriver() oled1306->begin(SSD1306_SWITCHCAPVCC, Settings.display_address[0], 0); renderer = oled1306; renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font); - renderer->setRotation(Settings.display_rotate); renderer->setTextColor(1,0); #ifdef SHOW_SPLASH diff --git a/sonoff/xdsp_07_sh1106.ino b/sonoff/xdsp_07_sh1106.ino index e8fc24107..6c535b02a 100644 --- a/sonoff/xdsp_07_sh1106.ino +++ b/sonoff/xdsp_07_sh1106.ino @@ -79,7 +79,6 @@ void SH1106InitDriver() renderer=oled1106; renderer->Begin(SH1106_SWITCHCAPVCC, Settings.display_address[0],0); renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - renderer->setRotation(Settings.display_rotate); renderer->setTextColor(1,0); #ifdef SHOW_SPLASH From 6bcfcf1e67f2f7261aa871e43fcda489456f59e3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 19 Oct 2019 14:55:12 +0200 Subject: [PATCH 2185/2222] Update RELEASENOTES.md --- RELEASENOTES.md | 302 +++++++++++++++++++++++++----------------------- 1 file changed, 155 insertions(+), 147 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index d8dcaec76..6a4c3429e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -10,16 +10,18 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade 3. Migrate to **Sonoff-Tasmota 5.14** 4. Migrate to **Sonoff-Tasmota 6.x** -## Change of supported Core versions -This release will be supported from ESP8266/Arduino library Core version **pre-2.6.0** due to reported security and stability issues on previous Core version. Although it might still compile on previous Core versions all support will be removed starting from the next Release. +## Supported Core versions +This release will be supported from ESP8266/Arduino library Core version **pre-2.6.0** due to reported security and stability issues on previous Core version. + +Although it might still compile on previous Core versions all support will be removed starting in the next Release. ## Support of TLS To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. See full documentation on https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT ## Change in default initial configuration tool -Firmware binary **sonoff-classic.bin** supports **WifiManager, Wps and SmartConfig** for initial configuration. The default tool is **Wps**. +Firmware binary **sonoff-classic.bin** supports **WifiManager, Wps and SmartConfig** for initial configuration. The default tool is **Wps**. To save code space all other binaries support **WifiManager only**. -To save memory space all other binaries support **WifiManager only**. +The next release will remove support for **WPS** and **SmartConfig** ## Supported Modules The following hardware modules are supported. @@ -97,158 +99,164 @@ Module | Description 69 SYF05 | Sunyesmart SYF05 RGBWW Wifi Led Bulb 70 Sonoff L1 | Sonoff L1 light strip 71 Sonoff iFan03 | Sonoff iFan03 Wifi Smart Ceiling Fan with Light +72 EXS Dimmer | EXS Wifi Dimmer v4 ## Provided Binary Downloads The following binary downloads have been compiled with ESP8266/Arduino library core version **pre-2.6.0**. -- **sonoff.bin** = The Sonoff version without Wps and SmartConfig configuration but adds more sensors. **RECOMMENDED RELEASE BINARY** -- **sonoff-basic.bin** = The Basic version without Wps and SmartConfig configuration and most sensors. +- **sonoff.bin** = The Sonoff version adds more sensors. **RECOMMENDED RELEASE BINARY** +- **sonoff-basic.bin** = The Basic version without most sensors. - **sonoff-classic.bin** = The Classic version allows initial installation using either WifiManager, Wps or SmartConfig. -- **sonoff-BG.bin** to **sonoff-TW.bin** = The Sonoff version without Wps and SmartConfig configuration in different languages. -- **sonoff-knx.bin** = The Knx version without Wps and SmartConfig configuration and some other features but adds KNX support. -- **sonoff-sensors.bin** = The Sensors version without Wps and SmartConfig configuration but adds even more useful sensors. -- **sonoff-display.bin** = The Display version without Wps and SmartConfig configuration and Energy Monitoring but adds display support. +- **sonoff-BG.bin** to **sonoff-TW.bin** = The Sonoff version in different languages. +- **sonoff-knx.bin** = The Knx version without some features but adds KNX support. +- **sonoff-sensors.bin** = The Sensors version adds even more useful sensors. +- **sonoff-ir** = The InfraRed Receiver and transmitter version allowing all available protocols provided by library IRremoteESP8266 but without most other features. +- **sonoff-display.bin** = The Display version without Energy Monitoring but adds display support. - **sonoff-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**. ## Available Features and Sensors -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks -|-----------------------|---------|-------|---------|--------|------|---------|---------|-------- -| MY_LANGUAGE en-GB | x | x | x | x | x | x | x | -| USE_WPS | - | - | x | - | - | - | - | WPS -| USE_SMARTCONFIG | - | - | x | - | - | - | - | SmartConfig -| USE_ARDUINO_OTA | - | - | - | - | - | - | - | -| USE_DOMOTICZ | - | - | x | x | x | x | - | -| USE_HOME_ASSISTANT | - | - | - | x | x | x | - | -| USE_MQTT_TLS | - | - | - | - | - | - | - | -| USE_MQTT_TLS_CA_CERT | - | - | - | - | - | - | - | -| USE_MQTT_AWS_IOT | - | - | - | - | - | - | - | -| USE_KNX | - | - | - | - | x | - | - | -| USE_WEBSERVER | x | x | x | x | x | x | x | WifiManager -| USE_EMULATION_HUE | - | x | x | x | - | x | - | -| USE_EMULATION_WEMO | - | x | x | x | - | x | - | -| USE_DISCOVERY | - | - | x | x | x | x | x | -| WEBSERVER_ADVERTISE | - | - | x | x | x | x | x | -| MQTT_HOST_DISCOVERY | - | - | x | x | x | x | x | -| USE_TIMERS | - | x | - | x | x | x | x | -| USE_TIMERS_WEB | - | x | - | x | x | x | x | -| USE_SUNRISE | - | x | - | x | x | x | x | -| USE_RULES | - | x | - | x | x | x | x | -| USE_SCRIPT | - | - | - | - | - | - | - | -| USE_EXPRESSION | - | - | - | - | - | - | - | -| | | | | | | | | -| ROTARY_V1 | - | - | - | - | - | - | - | -| USE_SONOFF_RF | - | - | - | x | x | x | - | -| USE_RF_FLASH | - | - | - | x | x | x | - | -| USE_SONOFF_SC | - | - | - | x | - | x | - | -| USE_TUYA_MCU | - | x | - | x | x | x | x | -| USE_ARMTRONIX_DIMMERS | - | - | - | x | x | - | - | -| USE_PS_16_DZ | - | - | - | x | x | x | - | -| USE_SONOFF_IFAN | - | - | - | x | x | x | - | -| USE_BUZZER | - | - | - | x | x | x | - | -| USE_ARILUX_RF | - | - | - | x | x | x | - | -| USE_SHUTTER | - | - | - | - | - | - | - | -| USE_DEEPSLEEP | - | - | - | - | - | - | - | -| USE_EXS_DIMMER | - | - | - | - | - | - | - | -| | | | | | | | | -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks -| USE_LIGHT | - | x | x | x | x | x | x | -| USE_WS2812 | - | - | x | x | x | x | x | -| USE_WS2812_DMA | - | - | - | - | - | - | - | -| USE_MY92X1 | - | - | - | x | x | x | x | -| USE_SM16716 | - | - | - | x | x | x | x | -| USE_SM2135 | - | - | - | x | x | x | x | -| USE_SONOFF_L1 | - | - | - | x | x | x | x | -| | | | | | | | | -| USE_ENERGY_SENSOR | - | x | x | x | x | x | - | -| USE_PZEM004T | - | - | - | x | x | x | - | -| USE_PZEM_AC | - | - | - | x | x | x | - | -| USE_PZEM_DC | - | - | - | x | x | x | - | -| USE_MCP39F501 | - | x | - | x | x | x | - | -| USE_SDM120 | - | - | - | - | - | x | - | -| USE_SDM630 | - | - | - | - | - | x | - | -| USE_DDS2382 | - | - | - | - | - | x | - | -| USE_DDSU666 | - | - | - | - | - | x | - | -| USE_SOLAX_X1 | - | - | - | - | - | - | - | -| | | | | | | | | -| USE_ADC_VCC | x | x | x | - | - | - | - | -| USE_COUNTER | - | - | - | x | x | x | x | -| USE_DS18x20 | - | - | x | x | x | x | x | -| USE_DHT | - | - | x | x | x | x | x | -| USE_MAX31855 | - | - | - | - | - | x | - | -| USE_MAX31865 | - | - | - | - | - | - | - | -| | | | | | | | | -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks -| USE_I2C | - | - | - | x | x | x | x | -| USE_SHT | - | - | - | x | x | x | x | -| USE_HTU | - | - | - | x | x | x | x | -| USE_BMP | - | - | - | x | x | x | x | -| USE_BME680 | - | - | - | - | - | x | - | -| USE_BH1750 | - | - | - | x | x | x | x | -| USE_VEML6070 | - | - | - | - | - | x | - | -| USE_ADS1115 | - | - | - | - | - | x | - | -| USE_ADS1115_I2CDEV | - | - | - | - | - | - | - | -| USE_INA219 | - | - | - | - | - | x | - | -| USE_INA226 | - | - | - | - | - | - | - | -| USE_SHT3X | - | - | - | x | x | x | x | -| USE_TSL2561 | - | - | - | - | - | x | - | -| USE_MGS | - | - | - | - | - | x | - | -| USE_SGP30 | - | - | - | x | x | x | x | -| USE_SI1145 | - | - | - | - | - | - | - | -| USE_LM75AD | - | - | - | x | x | x | x | -| USE_APDS9960 | - | - | - | - | - | - | - | -| USE_MCP230xx | - | - | - | - | - | - | - | -| USE_PCA9685 | - | - | - | - | - | - | - | -| USE_MPR121 | - | - | - | - | - | - | - | -| USE_CCS811 | - | - | - | - | - | - | - | -| USE_MPU6050 | - | - | - | - | - | - | - | -| USE_DS3231 | - | - | - | - | - | - | - | -| USE_MGC3130 | - | - | - | - | - | - | - | -| USE_MAX44009 | - | - | - | - | - | - | - | -| USE_SCD30 | - | - | - | - | - | x | - | -| USE_SPS30 | - | - | - | - | - | - | - | -| USE_ADE7953 | - | - | - | x | x | x | x | -| USE_VL53L0X | - | - | - | - | - | - | - | -| USE_MLX90614 | - | - | - | - | - | - | - | -| USE_CHIRP | - | - | - | - | - | - | - | -| USE_PAJ7620 | - | - | - | - | - | - | - | -| USE_PCF8574 | - | - | - | - | - | - | - | -| | | | | | | | | -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks -| USE_SPI | - | - | - | - | - | - | x | -| USE_MHZ19 | - | - | - | x | x | x | x | -| USE_SENSEAIR | - | - | - | x | x | x | x | -| USE_PMS5003 | - | - | - | x | x | x | x | -| USE_NOVA_SDS | - | - | - | x | x | x | x | -| USE_SERIAL_BRIDGE | - | - | - | x | x | x | x | -| USE_MP3_PLAYER | - | - | - | - | - | x | - | -| USE_AZ7798 | - | - | - | - | - | - | - | -| USE_PN532_HSU | - | - | - | - | - | x | - | -| USE_ZIGBEE | - | - | - | - | - | - | - | -| | | | | | | | | -| USE_IR_REMOTE | - | - | - | x | x | x | x | -| USE_IR_HVAC | - | - | - | - | - | x | - | -| USE_IR_RECEIVE | - | - | - | x | x | x | x | -| | | | | | | | | -| USE_SR04 | - | - | - | x | x | x | x | -| USE_TM1638 | - | - | - | - | - | x | - | -| USE_HX711 | - | - | - | x | x | x | x | -| USE_TX20_WIND_SENSOR | - | - | - | - | - | x | - | -| USE_RC_SWITCH | - | - | - | - | - | x | - | -| USE_RF_SENSOR | - | - | - | - | - | x | - | AlectoV2 only -| USE_HRE | - | - | - | - | - | x | - | -| USE_A4988_STEPPER | - | - | - | - | - | - | - | -| | | | | | | | | -| USE_DISPLAY | - | - | - | - | - | - | x | -| USE_DISPLAY_LCD | - | - | - | - | - | - | x | -| USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x | -| USE_DISPLAY_MATRIX | - | - | - | - | - | - | x | -| USE_DISPLAY_ILI9341 | - | - | - | - | - | - | x | -| USE_DISPLAY_EPAPER_29 | - | - | - | - | - | - | x | Disabled for core 2.3.0 -| USE_DISPLAY_EPAPER_42 | - | - | - | - | - | - | - | -| USE_DISPLAY_ILI9488 | - | - | - | - | - | - | - | -| USE_DISPLAY_SSD1351 | - | - | - | - | - | - | - | -| USE_DISPLAY_RA8876 | - | - | - | - | - | - | - | +| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | ir | display | Remarks +|-----------------------|---------|-------|---------|--------|-----|---------|----|---------|-------- +| MY_LANGUAGE en-GB | x | x | x | x | x | x | x | x | +| USE_WPS | - | - | x | - | - | - | - | - | WPS +| USE_SMARTCONFIG | - | - | x | - | - | - | - | - | SmartConfig +| USE_ARDUINO_OTA | - | - | - | - | - | - | - | - | +| USE_DOMOTICZ | - | - | x | x | x | x | x | - | +| USE_HOME_ASSISTANT | - | - | - | x | x | x | x | - | +| USE_MQTT_TLS | - | - | - | - | - | - | - | - | +| USE_MQTT_TLS_CA_CERT | - | - | - | - | - | - | - | - | +| USE_MQTT_AWS_IOT | - | - | - | - | - | - | - | - | +| USE_KNX | - | - | - | - | x | - | - | - | +| USE_WEBSERVER | x | x | x | x | x | x | x | x | WifiManager +| USE_JAVASCRIPT_ES6 | - | - | - | - | - | - | - | - | +| USE_WEBSEND_RESPONSE | - | - | - | - | - | - | - | - | +| USE_EMULATION_HUE | - | x | x | x | - | x | - | - | +| USE_EMULATION_WEMO | - | x | x | x | - | x | - | - | +| USE_DISCOVERY | - | - | x | x | x | - | - | x | +| WEBSERVER_ADVERTISE | - | - | x | x | x | - | - | x | +| MQTT_HOST_DISCOVERY | - | - | x | x | x | - | - | x | +| USE_TIMERS | - | x | - | x | x | x | x | x | +| USE_TIMERS_WEB | - | x | - | x | x | x | x | x | +| USE_SUNRISE | - | x | - | x | x | x | x | x | +| USE_RULES | - | x | - | x | x | x | x | x | +| USE_SCRIPT | - | - | - | - | - | - | - | - | +| USE_EXPRESSION | - | - | - | - | - | - | - | - | +| SUPPORT_IF_STATEMENT | - | - | - | - | - | - | - | - | +| | | | | | | | | | +| ROTARY_V1 | - | - | - | - | - | - | - | - | +| USE_SONOFF_RF | - | - | - | x | x | x | - | - | +| USE_RF_FLASH | - | - | - | x | x | x | - | - | +| USE_SONOFF_SC | - | - | - | x | - | x | - | - | +| USE_TUYA_MCU | - | x | - | x | x | x | - | x | +| USE_ARMTRONIX_DIMMERS | - | - | - | x | x | - | - | - | +| USE_PS_16_DZ | - | - | - | x | x | x | - | - | +| USE_SONOFF_IFAN | - | - | - | x | x | x | - | - | +| USE_BUZZER | - | - | - | x | x | x | - | - | +| USE_ARILUX_RF | - | - | - | x | x | x | - | - | +| USE_SHUTTER | - | - | - | - | - | - | - | - | +| USE_DEEPSLEEP | - | - | - | - | - | - | - | - | +| USE_EXS_DIMMER | - | - | - | - | - | - | - | - | +| | | | | | | | | | +| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | ir | display | Remarks +| USE_LIGHT | - | x | x | x | x | x | x | x | +| USE_WS2812 | - | - | x | x | x | x | - | x | +| USE_WS2812_DMA | - | - | - | - | - | - | - | - | +| USE_MY92X1 | - | - | - | x | x | x | - | x | +| USE_SM16716 | - | - | - | x | x | x | - | x | +| USE_SM2135 | - | - | - | x | x | x | - | x | +| USE_SONOFF_L1 | - | - | - | x | x | x | - | x | +| | | | | | | | | | +| USE_ENERGY_SENSOR | - | x | x | x | x | x | - | - | +| USE_PZEM004T | - | - | - | x | x | x | - | - | +| USE_PZEM_AC | - | - | - | x | x | x | - | - | +| USE_PZEM_DC | - | - | - | x | x | x | - | - | +| USE_MCP39F501 | - | x | - | x | x | x | - | - | +| USE_SDM120 | - | - | - | - | - | x | - | - | +| USE_SDM630 | - | - | - | - | - | x | - | - | +| USE_DDS2382 | - | - | - | - | - | x | - | - | +| USE_DDSU666 | - | - | - | - | - | x | - | - | +| USE_SOLAX_X1 | - | - | - | - | - | - | - | - | +| | | | | | | | | | +| USE_ADC_VCC | x | x | x | - | - | - | - | - | +| USE_COUNTER | - | - | - | x | x | x | x | x | +| USE_DS18x20 | - | - | x | x | x | x | - | x | +| USE_DHT | - | - | x | x | x | x | x | x | +| USE_MAX31855 | - | - | - | - | - | x | - | - | +| USE_MAX31865 | - | - | - | - | - | - | - | - | +| | | | | | | | | | +| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | ir | display | Remarks +| USE_I2C | - | - | - | x | x | x | - | x | +| USE_SHT | - | - | - | x | x | x | - | x | +| USE_HTU | - | - | - | x | x | x | - | x | +| USE_BMP | - | - | - | x | x | x | - | x | +| USE_BME680 | - | - | - | - | - | x | - | - | +| USE_BH1750 | - | - | - | x | x | x | - | x | +| USE_VEML6070 | - | - | - | - | - | x | - | - | +| USE_ADS1115 | - | - | - | - | - | x | - | - | +| USE_ADS1115_I2CDEV | - | - | - | - | - | - | - | - | +| USE_INA219 | - | - | - | - | - | x | - | - | +| USE_INA226 | - | - | - | - | - | - | - | - | +| USE_SHT3X | - | - | - | x | x | x | - | x | +| USE_TSL2561 | - | - | - | - | - | x | - | - | +| USE_MGS | - | - | - | - | - | x | - | - | +| USE_SGP30 | - | - | - | x | x | x | - | x | +| USE_SI1145 | - | - | - | - | - | - | - | - | +| USE_LM75AD | - | - | - | x | x | x | - | x | +| USE_APDS9960 | - | - | - | - | - | - | - | - | +| USE_MCP230xx | - | - | - | - | - | - | - | - | +| USE_PCA9685 | - | - | - | - | - | - | - | - | +| USE_MPR121 | - | - | - | - | - | - | - | - | +| USE_CCS811 | - | - | - | - | - | - | - | - | +| USE_MPU6050 | - | - | - | - | - | - | - | - | +| USE_DS3231 | - | - | - | - | - | - | - | - | +| USE_MGC3130 | - | - | - | - | - | - | - | - | +| USE_MAX44009 | - | - | - | - | - | - | - | - | +| USE_SCD30 | - | - | - | - | - | x | - | - | +| USE_SPS30 | - | - | - | - | - | - | - | - | +| USE_ADE7953 | - | - | - | x | x | x | - | x | +| USE_VL53L0X | - | - | - | - | - | - | - | - | +| USE_MLX90614 | - | - | - | - | - | - | - | - | +| USE_CHIRP | - | - | - | - | - | - | - | - | +| USE_PAJ7620 | - | - | - | - | - | - | - | - | +| USE_PCF8574 | - | - | - | - | - | - | - | - | +| | | | | | | | | | +| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | ir | display | Remarks +| USE_SPI | - | - | - | - | - | - | - | x | +| USE_MHZ19 | - | - | - | x | x | x | - | x | +| USE_SENSEAIR | - | - | - | x | x | x | - | x | +| USE_PMS5003 | - | - | - | x | x | x | - | x | +| USE_NOVA_SDS | - | - | - | x | x | x | - | x | +| USE_SERIAL_BRIDGE | - | - | - | x | x | x | - | x | +| USE_MP3_PLAYER | - | - | - | - | - | x | - | - | +| USE_AZ7798 | - | - | - | - | - | - | - | - | +| USE_PN532_HSU | - | - | - | - | - | x | - | - | +| USE_ZIGBEE | - | - | - | - | - | - | - | - | Experimental +| | | | | | | | | | +| USE_IR_REMOTE | - | - | - | x | x | x | x | x | +| USE_IR_HVAC | - | - | - | - | - | x | x | - | +| USE_IR_RECEIVE | - | - | - | x | x | x | x | x | +| | | | | | | | | | +| USE_SR04 | - | - | - | x | x | x | - | x | +| USE_TM1638 | - | - | - | - | - | x | - | - | +| USE_HX711 | - | - | - | x | x | x | - | x | +| USE_TX20_WIND_SENSOR | - | - | - | - | - | x | - | - | +| USE_RC_SWITCH | - | - | - | - | - | x | - | - | +| USE_RF_SENSOR | - | - | - | - | - | x | - | - | AlectoV2 only +| USE_HRE | - | - | - | - | - | x | - | - | +| USE_A4988_STEPPER | - | - | - | - | - | - | - | - | +| | | | | | | | | | +| USE_DISPLAY | - | - | - | - | - | - | - | x | +| USE_DISPLAY_LCD | - | - | - | - | - | - | - | x | +| USE_DISPLAY_SSD1306 | - | - | - | - | - | - | - | x | +| USE_DISPLAY_MATRIX | - | - | - | - | - | - | - | x | +| USE_DISPLAY_SH1106 | - | - | - | - | - | - | - | x | +| USE_DISPLAY_ILI9341 | - | - | - | - | - | - | - | x | +| USE_DISPLAY_EPAPER_29 | - | - | - | - | - | - | - | x | Disabled for core 2.3.0 +| USE_DISPLAY_EPAPER_42 | - | - | - | - | - | - | - | x | Disabled for core 2.3.0 +| USE_DISPLAY_ILI9488 | - | - | - | - | - | - | - | - | +| USE_DISPLAY_SSD1351 | - | - | - | - | - | - | - | - | +| USE_DISPLAY_RA8876 | - | - | - | - | - | - | - | - | ## Changelog Version 6.6.0 20190707 From 18d84c0e60041ca771294d8581be704e69ce0dc4 Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Sat, 19 Oct 2019 22:45:53 +0200 Subject: [PATCH 2186/2222] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 73cc67f32..59cce39ab 100644 --- a/README.md +++ b/README.md @@ -25,11 +25,11 @@ In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/r See [sonoff/_changelog.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_changelog.ino) for detailed change information. -Unless your Tasmota based device exhibits a problem or you need to make use of a feature that is not available in the Tasmota version currently installed on your device, leave your device alone - it works so don't make unnecessary changes! If the release version (i.e., the master branch) exhibits problems for your device and configuration, you should upgrade to the latest development version instead to see if your problem is resolved. +Unless your Tasmota powered device exhibits a problem or you need to make use of a feature that is not available in the Tasmota version currently installed on your device, leave your device alone - it works so don't make unnecessary changes! If the release version (i.e., the master branch) exhibits unexpected behaviour for your device and configuration, you should upgrade to the latest development version instead to see if your problem is resolved as some bugs in previous releases or development builds may already have been resolved. -The Tasmota development codebase is checked every 1-2 hours for changes. If new commits have been merged and they compile successfuly, new binary files for every variant will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA too). The last compiled commit number is also posted on the same page along with the current build status (if a firmware rebuild is in progress). It is important to note that these binaries are based on the current development codebase. These commits are tested as much as is possible and are typically quite stable. However, it is infeasible to test on the hundreds of different types of devices with the specific configurations that are permitted. +The Tasmota development codebase is checked every 1-2 hours for changes. If new commits have been merged and they compile successfuly, new binary files for every variant (excluding non-English languages) will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA updates too). The last compiled commit number is also indicated on the same page. It is important to note that these binaries are based on the current development codebase. These commits are tested as much as is possible and are typically quite stable. However, it is infeasible to test on the hundreds of different types of devices with all the available configuration options permitted. -Note that there is a chance, as with any upgrade, that the device may not function as expected. You must always account for the possibility that you may need to flash the device via the serial programming interface if the OTA fails. Even with the master release, you should always attempt to test the device or a similar prototype before upgrading a device which is in production or is hard to reach. And, as always, make a backup of the device configuration before beginning any firmware update. +Note that there is a chance, as with any upgrade, that the device may not function as expected. You must always account for the possibility that you may need to flash the device via the serial programming interface if the OTA upgrade fails. Even with the master release, you should always attempt to test the device or a similar prototype before upgrading a device which is in production or is hard to reach. And, as always, make a backup of the device configuration before beginning any firmware update. ## Disclaimer :warning: **DANGER OF ELECTROCUTION** :warning: From d2ff52215c558f7310470d4a010a1353840f4e8d Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sun, 20 Oct 2019 08:23:27 +0200 Subject: [PATCH 2187/2222] sml counter debounce on both edges --- sonoff/xsns_53_sml.ino | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/sonoff/xsns_53_sml.ino b/sonoff/xsns_53_sml.ino index 4b74e7d73..158296e14 100644 --- a/sonoff/xsns_53_sml.ino +++ b/sonoff/xsns_53_sml.ino @@ -539,6 +539,9 @@ double buffer[MEDIAN_SIZE]; int8_t index; } sml_mf[MAX_VARS]; +#ifndef FLT_MAX +#define FLT_MAX 99999999 +#endif double sml_median_array(double *array,uint8_t len) { uint8_t ind[len]; @@ -1802,11 +1805,19 @@ void SML_CounterUpd4(void) ICACHE_RAM_ATTR; #endif // ARDUINO_ESP8266_RELEASE_2_3_0 void SML_CounterUpd(uint8_t index) { - uint32_t ltime=millis()-sml_counters[index].sml_counter_ltime; - sml_counters[index].sml_counter_ltime=millis(); - if (ltime>sml_counters[index].sml_debounce) { - RtcSettings.pulse_counter[index]++; - InjektCounterValue(sml_counters[index].sml_cnt_old_state,RtcSettings.pulse_counter[index]); + + uint8_t level=digitalRead(meter_desc_p[sml_counters[index].sml_cnt_old_state].srcpin); + if (!level) { + // falling edge + uint32_t ltime=millis()-sml_counters[index].sml_counter_ltime; + sml_counters[index].sml_counter_ltime=millis(); + if (ltime>sml_counters[index].sml_debounce) { + RtcSettings.pulse_counter[index]++; + InjektCounterValue(sml_counters[index].sml_cnt_old_state,RtcSettings.pulse_counter[index]); + } + } else { + // rising edge + sml_counters[index].sml_counter_ltime=millis(); } } @@ -2040,7 +2051,7 @@ init10: // check for irq mode if (meter_desc_p[meters].params<=0) { // init irq mode - attachInterrupt(meter_desc_p[meters].srcpin, counter_callbacks[cindex], FALLING); + attachInterrupt(meter_desc_p[meters].srcpin, counter_callbacks[cindex], CHANGE); sml_counters[cindex].sml_cnt_old_state=meters; sml_counters[cindex].sml_debounce=-meter_desc_p[meters].params; } @@ -2232,6 +2243,11 @@ void SML_Send_Seq(uint32_t meter,char *seq) { *ucp++=highByte(crc); slen+=4; } + if (script_meter_desc[meter].type=='o') { + for (uint32_t cnt=0;cntmeters_used) index=1; + if (index>0 && meter_desc_p[(index&7)-1].type=='c') { + index=0; + } + dump2log=index; ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"dump: %d\"}}"),dump2log); } else if (*cp=='c') { // set ounter From 0e1e1a15a17968e3dfde9cc5fdbc5c671bfe0f18 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sun, 20 Oct 2019 11:21:25 +0200 Subject: [PATCH 2188/2222] scripter sendmail update --- sonoff/sendemail.ino | 146 +++++++++++++++++------------------- sonoff/xdrv_10_scripter.ino | 58 +++++++++++++- 2 files changed, 124 insertions(+), 80 deletions(-) diff --git a/sonoff/sendemail.ino b/sonoff/sendemail.ino index 4a54c85e0..dbc13cf41 100755 --- a/sonoff/sendemail.ino +++ b/sonoff/sendemail.ino @@ -3,37 +3,48 @@ #include "sendemail.h" // enable serial debugging -//#define DEBUG_EMAIL_PORT Serial +//#define DEBUG_EMAIL_PORT -//SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const bool ssl); -//SendEmail::send(const String& from, const String& to, const String& subject, const String& msg) -// sendmail [server:port:user:passwd:from:to:subject] data -// sendmail [*:*:*:*:*:to:subject] data uses defines from user_config -// sendmail currently only works with core 2.4.2 +// sendmail works only with server port 465 SSL and doesnt support STARTTLS (not supported in Arduino) +// only a couple of mailservers support this (e.g. gmail,gmx,yahoo,freenetmail) +// sendmail [server:port:user:passwd:from:to:subject] body +// sendmail [*:*:*:*:*:to:subject] data uses defines from user_config_overwrite +// #define EMAIL_USER "user" +// #define EMAIL_PASSWORD "passwd" +// #define EMAIL_FROM "" +// #define EMAIL_SERVER "smtp.gmail.com" +// #define EMAIL_PORT 465 +// if email body consist of a single * and scripter is present +// and a section >m is found, the lines in this section (until #) are sent +// as email body + +// sendmail works with pre2.6 using Light BearSSL //HW Watchdog 8.44 sec. //SW Watchdog 3.2 sec. +#ifndef SEND_MAIL_MINRAM #define SEND_MAIL_MINRAM 12*1024 +#endif + +#define xPSTR(a) a uint16_t SendMail(char *buffer) { - uint16_t count; char *params,*oparams; - char *mserv; + const char *mserv; uint16_t port; - char *user; - char *pstr; - char *passwd; - char *from; - char *to; - char *subject; - char *cmd; - char secure=0,auth=0; + const char *user; + const char *pstr; + const char *passwd; + const char *from; + const char *to; + const char *subject; + const char *cmd; + char auth=0; uint16_t status=1; SendEmail *mail=0; uint16_t blen; char *endcmd; - //DebugFreeMem(); // return if not enough memory uint16_t mem=ESP.getFreeHeap(); @@ -65,9 +76,7 @@ uint16_t SendMail(char *buffer) { cmd=endcmd+1; #ifdef DEBUG_EMAIL_PORT - SetSerialBaudrate(115200); - DEBUG_EMAIL_PORT.print("mailsize: "); - DEBUG_EMAIL_PORT.println(blen); + AddLog_P2(LOG_LEVEL_INFO, PSTR("mailsize: %d"),blen); #endif mserv=strtok(params,":"); @@ -119,43 +128,39 @@ uint16_t SendMail(char *buffer) { #ifdef EMAIL_USER if (*user=='*') { - user=(char*)EMAIL_USER; + user=xPSTR(EMAIL_USER); } #endif #ifdef EMAIL_PASSWORD if (*passwd=='*') { - passwd=(char*)EMAIL_PASSWORD; + passwd=xPSTR(EMAIL_PASSWORD); } #endif #ifdef EMAIL_SERVER if (*mserv=='*') { - mserv=(char*)EMAIL_SERVER; + mserv=xPSTR(EMAIL_SERVER); } #endif //USE_SENDMAIL #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(mserv); - DEBUG_EMAIL_PORT.println(port); - DEBUG_EMAIL_PORT.println(user); - DEBUG_EMAIL_PORT.println(passwd); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s - %d - %s - %s"),mserv,port,user,passwd); #endif // 2 seconds timeout +#ifndef MAIL_TIMEOUT #define MAIL_TIMEOUT 500 +#endif mail = new SendEmail(mserv,port,user,passwd, MAIL_TIMEOUT, auth); #ifdef EMAIL_FROM if (*from=='*') { - from=(char*)EMAIL_FROM; + from=xPSTR(EMAIL_FROM); } #endif #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(from); - DEBUG_EMAIL_PORT.println(to); - DEBUG_EMAIL_PORT.println(subject); - DEBUG_EMAIL_PORT.println(cmd); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s - %s - %s - %s"),from,to,subject,cmd); #endif if (mail) { @@ -169,13 +174,11 @@ exit: return status; } - +void script_send_email_body(BearSSL::WiFiClientSecure_light *client); SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) : - host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new BearSSL::WiFiClientSecure_light(1024,1024)) -{ - + host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new BearSSL::WiFiClientSecure_light(1024,1024)) { } String SendEmail::readClient() { @@ -190,10 +193,7 @@ String SendEmail::readClient() { return r; } -//void SetSerialBaudrate(int baudrate); - -bool SendEmail::send(const String& from, const String& to, const String& subject, const char *msg) -{ +bool SendEmail::send(const String& from, const String& to, const String& subject, const char *msg) { bool status=false; String buffer; @@ -204,24 +204,19 @@ String buffer; client->setTimeout(timeout); // smtp connect #ifdef DEBUG_EMAIL_PORT - SetSerialBaudrate(115200); - DEBUG_EMAIL_PORT.print("Connecting: "); - DEBUG_EMAIL_PORT.print(host); - DEBUG_EMAIL_PORT.print(":"); - DEBUG_EMAIL_PORT.println(port); + AddLog_P2(LOG_LEVEL_INFO, PSTR("Connecting: %s on port %d"),host.c_str(),port); #endif if (!client->connect(host.c_str(), port)) { #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println("Connection failed: "); - //DEBUG_EMAIL_PORT.println (client->getLastSSLError()); + AddLog_P(LOG_LEVEL_INFO, PSTR("Connection failed")); #endif goto exit; } buffer = readClient(); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("220"))) { goto exit; @@ -232,61 +227,52 @@ String buffer; client->println(buffer); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("250"))) { goto exit; } if (user.length()>0 && passwd.length()>0 ) { - //buffer = F("STARTTLS"); - //client->println(buffer); - buffer = F("AUTH LOGIN"); client->println(buffer); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("334"))) { goto exit; } base64 b; - //buffer = user; - //buffer = b.encode(buffer); buffer = b.encode(user); client->println(buffer); #ifdef DEBUG_EMAIL_PORT - //DEBUG_EMAIL_PORT.println(user); - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("334"))) { goto exit; } - //buffer = this->passwd; - //buffer = b.encode(buffer); buffer = b.encode(passwd); client->println(buffer); #ifdef DEBUG_EMAIL_PORT - //DEBUG_EMAIL_PORT.println(passwd); - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("235"))) { goto exit; @@ -298,11 +284,11 @@ String buffer; buffer += from; client->println(buffer); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("250"))) { goto exit; @@ -311,11 +297,11 @@ String buffer; buffer += to; client->println(buffer); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("250"))) { goto exit; @@ -324,11 +310,11 @@ String buffer; buffer = F("DATA"); client->println(buffer); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = readClient(); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif if (!buffer.startsWith(F("354"))) { goto exit; @@ -337,32 +323,40 @@ String buffer; buffer += from; client->println(buffer); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = F("To: "); buffer += to; client->println(buffer); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = F("Subject: "); buffer += subject; buffer += F("\r\n"); client->println(buffer); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif +#ifdef USE_SCRIPT + if (*msg=='*' && *(msg+1)==0) { + script_send_email_body(client); + } else { + client->println(msg); + } +#else client->println(msg); +#endif client->println('.'); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(msg); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif buffer = F("QUIT"); client->println(buffer); #ifdef DEBUG_EMAIL_PORT - DEBUG_EMAIL_PORT.println(buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); #endif status=true; diff --git a/sonoff/xdrv_10_scripter.ino b/sonoff/xdrv_10_scripter.ino index ee78cc740..3e1487b64 100644 --- a/sonoff/xdrv_10_scripter.ino +++ b/sonoff/xdrv_10_scripter.ino @@ -2100,6 +2100,7 @@ void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) { cp=srcbuf; struct T_INDEX ind; char string[SCRIPT_MAXSSIZE]; + dstsize-=2; for (count=0;countm",-2,0); + if (msect==99) { + char line[128]; + char tmp[128]; + char *lp=glob_script_mem.section_ptr+2; + while (lp) { + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + // send this line to smtp + memcpy(line,lp,sizeof(line)); + line[sizeof(line)-1]=0; + char *cp=line; + for (uint32_t i=0; iprintln(tmp); + } + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } + } else { + client->println("*"); + } +} +#endif + #ifdef USE_SCRIPT_JSON_EXPORT void ScriptJsonAppend(void) { uint8_t web_script=Run_Scripter(">J",-2,0); From 60ea83f41ca1de81b6ce934202dbcf5d1dedc3cf Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sun, 20 Oct 2019 11:34:29 +0200 Subject: [PATCH 2189/2222] sendmail timeout 2000 --- sonoff/sendemail.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sendemail.ino b/sonoff/sendemail.ino index dbc13cf41..70571b5d2 100755 --- a/sonoff/sendemail.ino +++ b/sonoff/sendemail.ino @@ -149,7 +149,7 @@ uint16_t SendMail(char *buffer) { // 2 seconds timeout #ifndef MAIL_TIMEOUT - #define MAIL_TIMEOUT 500 + #define MAIL_TIMEOUT 2000 #endif mail = new SendEmail(mserv,port,user,passwd, MAIL_TIMEOUT, auth); From 73c2fd3cb4a546605ea2fa3edf8c37ebc341d26d Mon Sep 17 00:00:00 2001 From: Andre Thomas Date: Sun, 20 Oct 2019 11:48:09 +0200 Subject: [PATCH 2190/2222] Update TasmotaSerial.cpp --- lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp b/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp index ebce5a496..45a1d47af 100644 --- a/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp @@ -158,7 +158,7 @@ bool TasmotaSerial::begin(long speed, int stop_bits) { m_bit_time = ESP.getCpuFreqMHz() * 1000000 / speed; m_bit_start_time = m_bit_time + m_bit_time/3 - (ESP.getCpuFreqMHz() > 120 ? 700 : 500); // pre-compute first wait m_high_speed = (speed >= 9600); - m_very_high_speed = (speed >= 100000); + m_very_high_speed = (speed >= 50000); } return m_valid; } From 393ccd779932777e194f7af5e4dbb18b984f82de Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 20 Oct 2019 11:57:38 +0200 Subject: [PATCH 2191/2222] Change EXS Dimmer driver Change EXS Dimmer driver by Gerry Lenz (#6658) --- sonoff/language/bg-BG.h | 2 +- sonoff/language/cs-CZ.h | 2 +- sonoff/language/de-DE.h | 2 +- sonoff/language/el-GR.h | 2 +- sonoff/language/en-GB.h | 2 +- sonoff/language/es-ES.h | 2 +- sonoff/language/fr-FR.h | 2 +- sonoff/language/he-HE.h | 2 +- sonoff/language/hu-HU.h | 2 +- sonoff/language/it-IT.h | 2 +- sonoff/language/ko-KO.h | 2 +- sonoff/language/nl-NL.h | 2 +- sonoff/language/pl-PL.h | 2 +- sonoff/language/pt-BR.h | 2 +- sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 2 +- sonoff/language/sk-SK.h | 2 +- sonoff/language/sv-SE.h | 2 +- sonoff/language/tr-TR.h | 2 +- sonoff/language/uk-UK.h | 2 +- sonoff/language/zh-CN.h | 2 +- sonoff/language/zh-TW.h | 2 +- sonoff/sonoff_template.h | 12 ++-- sonoff/xdrv_30_exs_dimmer.ino | 109 +++++++++++++++++++--------------- 24 files changed, 89 insertions(+), 76 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index a24e95d70..47cc10d88 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 31b23dac9..f21911772 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 849d356af..93a44c9de 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 325558b83..00d690e80 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 5cee90b5c..2402e8c01 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-ES.h b/sonoff/language/es-ES.h index f5f31ffc6..43c9b2fa9 100644 --- a/sonoff/language/es-ES.h +++ b/sonoff/language/es-ES.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index b52156447..a33c48639 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 52c9d8cf9..d31069675 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 635756447..a5094fe44 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 7a35a4dfc..6ac9a14d6 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index 6ae84f9a7..ac1ae34ce 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index fd94dbe09..5d0a6aacd 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index b871a18ea..a167cfa7d 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index b4048fe8c..ae2349b8e 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 80ac976b7..fd769a2e4 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 543d8a4f1..3f61e323b 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 207764960..573975948 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 79cf9dedc..190e9b956 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index f28f951d9..9189de9ee 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 0ea4127c7..f09e80497 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 22ac1f9cf..fdc8e1277 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 437656457..85f68b991 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -626,7 +626,7 @@ #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_MCU_RESET "EXS Reset" +#define D_SENSOR_EXS_ENABLE "EXS Enable" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index c6ed63361..c6ed5b3e2 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -207,7 +207,7 @@ enum UserSelectablePins { GPIO_SM2135_CLK, // SM2135 Clk GPIO_SM2135_DAT, // SM2135 Dat GPIO_DEEPSLEEP, // Kill switch for deepsleep - GPIO_EXS_MCU_RESET, // EXS MCU Reset + GPIO_EXS_ENABLE, // EXS MCU Enable GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -285,7 +285,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_DDS2382_TX "|" D_SENSOR_DDS2382_RX "|" D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|" D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|" - D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_MCU_RESET "|" + D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|" ; const char kSensorNamesFixed[] PROGMEM = @@ -576,7 +576,7 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_TUYA_RX, // Tuya Serial interface #endif #ifdef USE_EXS_DIMMER - GPIO_EXS_MCU_RESET, // EXS MCU Reset + GPIO_EXS_ENABLE, // EXS MCU Enable #endif #endif // USE_LIGHT @@ -2131,12 +2131,12 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL4, // GPIO15 WIFI_O3 Relay 4 (0 = Off, 1 = On) controlling the fan 0, 0 }, - { "EXS Dimmer", // EXS_DIMMER - EX-Stroe WiFi Dimmer v4, two channel (ESP8266 w/ separate MCU dimmer) + { "EXS Dimmer", // EXS_DIMMER - EX-Store WiFi Dimmer v4, two channel (ESP8266 w/ separate MCU dimmer) // https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A // https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A-ESP8266-V12-Stift-und-Buchsenleisten 0, GPIO_TXD, // GPIO01 MCU serial control - 0, + GPIO_LEDLNK, // GPIO02 LED Link GPIO_RXD, // GPIO03 MCU serial control GPIO_USER, // GPIO04 GPIO_USER, // GPIO05 @@ -2147,7 +2147,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) // GPIO11 (SD_CMD Flash) GPIO_USER, // GPIO12 - GPIO_EXS_MCU_RESET, // GPIO13 EXS MCU Reset + GPIO_EXS_ENABLE, // GPIO13 EXS MCU Enable GPIO_USER, // GPIO14 0, // GPIO15 0, 0 diff --git a/sonoff/xdrv_30_exs_dimmer.ino b/sonoff/xdrv_30_exs_dimmer.ino index 63b489b56..a476db95c 100644 --- a/sonoff/xdrv_30_exs_dimmer.ino +++ b/sonoff/xdrv_30_exs_dimmer.ino @@ -251,20 +251,6 @@ bool ExsSyncState() ExsSyncState(1); } -static inline void ExsSetChannelV10(uint8_t channel, const uint8_t *buffer) -{ - Exs.dimmer.channel[channel].on = buffer[0]; - Exs.dimmer.channel[channel].dimm = buffer[1]; - Exs.dimmer.channel[channel].bright_tbl = 0; -} - -static inline void ExsSetChannel(uint8_t channel, const uint8_t *buffer) -{ - Exs.dimmer.channel[channel].on = buffer[0]; - Exs.dimmer.channel[channel].dimm = buffer[1]; - Exs.dimmer.channel[channel].bright_tbl = buffer[2]; -} - void ExsDebugState() { #ifdef EXS_DEBUG @@ -288,21 +274,71 @@ void ExsPacketProcess(void) switch (cmd) { case EXS_GET_VALUES: + /* + format firmware 2.1 + 0. byte = startMarker + 1. byte = 0. crc of bytes 2(CMD) - 11(GATE_LOCK) + 2. byte = 1. len_Of_Payload + 3. byte = 2. CMD + 4. byte = 3. MAJOR + 5. byte = 4. MINOR + 6. byte = 5. GATE1_ON + 7. byte = 6. GATE1_DIMM + 8. byte = 7. GATE1.BRIGHT + 9. byte = 8. GATE2_ON + 10. byte = 9. GATE2_DIMM + 11. byte = 10. GATE2.BRIGHT + 12. byte = 11. GATE_LOCK + 13. byte = '\0' + */ if (len > 9) { Exs.dimmer.version_major = Exs.buffer[3]; Exs.dimmer.version_minor = Exs.buffer[4]; - ExsSetChannel(0, &Exs.buffer[5]); - ExsSetChannel(1, &Exs.buffer[8]); + + //Exs.dimmer.channel[0].on = Exs.buffer[5]; + Exs.dimmer.channel[0].on = Exs.buffer[6]; + Exs.dimmer.channel[0].dimm = Exs.buffer[6]; + Exs.dimmer.channel[0].bright_tbl = Exs.buffer[7]; + + //Exs.dimmer.channel[1].on = Exs.buffer[8]; + Exs.dimmer.channel[1].on = Exs.buffer[9]; + Exs.dimmer.channel[1].dimm = Exs.buffer[9]; + Exs.dimmer.channel[1].bright_tbl = Exs.buffer[10]; + Exs.dimmer.gate_lock = Exs.buffer[11]; } else + /* + format firmware 1.0 + 0. byte = startMarker + 1. byte = 0. crc of bytes 2(CMD) - 9(GATE_LOCK) + 2. byte = 1. len_Of_Payload + 3. byte = 2. CMD + 4. byte = 3. GATE1_ON + 5. byte = 4. GATE1_DIMM + 6. byte = 5. GATE1.BRIGHT + 7. byte = 6. GATE2_ON + 8. byte = 7. GATE2_DIMM + 9. byte = 8. GATE2.BRIGHT + 10. byte = 9. GATE_LOCK + 11. byte = '\0' + */ { Exs.dimmer.version_major = 1; Exs.dimmer.version_minor = 0; - ExsSetChannel(0, &Exs.buffer[3]); - ExsSetChannel(1, &Exs.buffer[5]); - Exs.dimmer.gate_lock = Exs.buffer[8]; + + //Exs.dimmer.channel[0].on = Exs.buffer[3] - 48; + Exs.dimmer.channel[0].on = Exs.buffer[4] - 48; + Exs.dimmer.channel[0].dimm = Exs.buffer[4] - 48; + Exs.dimmer.channel[0].bright_tbl = Exs.buffer[5] - 48; + + //Exs.dimmer.channel[1].on = Exs.buffer[6] - 48; + Exs.dimmer.channel[1].on = Exs.buffer[7] - 48; + Exs.dimmer.channel[1].dimm = Exs.buffer[7] - 48; + Exs.dimmer.channel[1].bright_tbl = Exs.buffer[8] - 48; + + Exs.dimmer.gate_lock = Exs.buffer[9] - 48; } ExsDebugState(); @@ -313,7 +349,6 @@ void ExsPacketProcess(void) break; } } - /* * API Functions */ @@ -360,11 +395,11 @@ void EsxMcuStart(void) int retries = 3; #ifdef EXS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Request MCU configuration, PIN %d to Low"), pin[GPIO_EXS_MCU_RESET]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Request MCU configuration, PIN %d to Low"), pin[GPIO_EXS_ENABLE]); #endif - pinMode(pin[GPIO_EXS_MCU_RESET], OUTPUT); - digitalWrite(pin[GPIO_EXS_MCU_RESET], LOW); + pinMode(pin[GPIO_EXS_ENABLE], OUTPUT); + digitalWrite(pin[GPIO_EXS_ENABLE], LOW); delay(1); // wait 1ms fot the MCU to come online @@ -461,37 +496,23 @@ void ExsSerialInput(void) #ifdef EXS_MCU_CMNDS #define D_PRFX_EXS "Exs" -#define D_CMND_EXS_GATE "Gate" #define D_CMND_EXS_DIMM "Dimm" #define D_CMND_EXS_DIMM_TBL "DimmTbl" #define D_CMND_EXS_DIMM_VAL "DimmVal" -#define D_CMND_EXS_GATES "Gates" #define D_CMND_EXS_DIMMS "Dimms" #define D_CMND_EXS_CH_LOCK "ChLock" #define D_CMND_EXS_STATE "State" const char kExsCommands[] PROGMEM = D_PRFX_EXS "|" - D_CMND_EXS_GATE "|" D_CMND_EXS_DIMM "|" D_CMND_EXS_DIMM_TBL "|" D_CMND_EXS_DIMM_VAL "|" - D_CMND_EXS_GATES "|" D_CMND_EXS_DIMMS "|" D_CMND_EXS_CH_LOCK "|" + D_CMND_EXS_DIMMS "|" D_CMND_EXS_CH_LOCK "|" D_CMND_EXS_STATE; void (* const ExsCommand[])(void) PROGMEM = - { &CmndExsGate, - &CmndExsDimm, &CmndExsDimmTbl, &CmndExsDimmVal, - &CmndExsGates, &CmndExsDimms, &CmndExsChLock, + { &CmndExsDimm, &CmndExsDimmTbl, &CmndExsDimmVal, + &CmndExsDimms, &CmndExsChLock, &CmndExsState }; -void CmndExsGate(void) -{ - if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && - (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1)) { - ExsSendCmd(EXS_GATE_1_ON + 0x10 * (XdrvMailbox.index - 1) + - XdrvMailbox.payload ^ 1, 0); - } - CmndExsState(); -} - void CmndExsDimm(void) { if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && @@ -522,14 +543,6 @@ void CmndExsDimmVal(void) CmndExsState(); } -void CmndExsGates(void) -{ - if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { - ExsSendCmd(EXS_GATES_ON + XdrvMailbox.payload ^ 1, 0); - } - CmndExsState(); -} - void CmndExsDimms(void) { if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { From ad73a51023ef472643538dcc3940995cedb81d5f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 20 Oct 2019 13:27:48 +0200 Subject: [PATCH 2192/2222] (Try to) fix EnergyReset (again) (Try to) fix EnergyReset (again) (#6561) --- sonoff/xnrg_03_pzem004t.ino | 6 +++++- sonoff/xnrg_05_pzem_ac.ino | 10 ++++++++-- sonoff/xnrg_06_pzem_dc.ino | 9 +++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index d41910f93..39b690bce 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -58,6 +58,7 @@ TasmotaSerial *PzemSerial = nullptr; struct PZEM { float energy = 0; + float last_energy = 0; uint8_t send_retry = 0; uint8_t read_state = 0; // Set address uint8_t phase = 0; @@ -190,7 +191,10 @@ void PzemEvery250ms(void) case 4: // Total energy as 99999Wh Pzem.energy += value; if (Pzem.phase == Energy.phase_count -1) { - EnergyUpdateTotal(Pzem.energy, false); + if (Pzem.energy > Pzem.last_energy) { // Handle missed phase + EnergyUpdateTotal(Pzem.energy, false); + Pzem.last_energy = Pzem.energy; + } Pzem.energy = 0; } break; diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index 4209b32af..af36d7466 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -38,6 +38,7 @@ TasmotaModbus *PzemAcModbus; struct PZEMAC { float energy = 0; + float last_energy = 0; uint8_t send_retry = 0; uint8_t phase = 0; uint8_t address = 0; @@ -65,7 +66,8 @@ void PzemAcEverySecond(void) Energy.data_valid[PzemAc.phase] = 0; if (10 == registers) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + // 0 1 2 3 4 5 6 7 8 9 = ModBus register + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 = Buffer index // 01 04 14 08 D1 00 6C 00 00 00 F4 00 00 00 26 00 00 01 F4 00 64 00 00 51 34 // Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc-- Energy.voltage[PzemAc.phase] = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V @@ -76,9 +78,13 @@ void PzemAcEverySecond(void) PzemAc.energy += (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh if (PzemAc.phase == Energy.phase_count -1) { - EnergyUpdateTotal(PzemAc.energy, false); + if (PzemAc.energy > PzemAc.last_energy) { // Handle missed phase + EnergyUpdateTotal(PzemAc.energy, false); + PzemAc.last_energy = PzemAc.energy; + } PzemAc.energy = 0; } + } } } diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index d7d4f2818..5aaf3f29e 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -38,6 +38,7 @@ TasmotaModbus *PzemDcModbus; struct PZEMDC { float energy = 0; + float last_energy = 0; uint8_t send_retry = 0; uint8_t channel = 0; uint8_t address = 0; @@ -65,7 +66,8 @@ void PzemDcEverySecond(void) Energy.data_valid[PzemDc.channel] = 0; if (8 == registers) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + // 0 1 2 3 4 5 6 7 = ModBus register + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 = Buffer index // 01 04 10 05 40 00 0A 00 0D 00 00 00 02 00 00 00 00 00 00 D6 29 // Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc-- Energy.voltage[PzemDc.channel] = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V @@ -74,7 +76,10 @@ void PzemDcEverySecond(void) PzemDc.energy += (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh if (PzemDc.channel == Energy.phase_count -1) { - EnergyUpdateTotal(PzemDc.energy, false); + if (PzemDc.energy > PzemDc.last_energy) { // Handle missed channel + EnergyUpdateTotal(PzemDc.energy, false); + PzemDc.last_energy = PzemDc.energy; + } PzemDc.energy = 0; } } From 37c2239d619bec47e4cc2cdaab3749a63a2b7a8a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 20 Oct 2019 15:48:14 +0200 Subject: [PATCH 2193/2222] (Try to) fix EnergyReset (again) (Try to) fix EnergyReset (again) (#6561) --- sonoff/xnrg_03_pzem004t.ino | 8 ++++++-- sonoff/xnrg_05_pzem_ac.ino | 9 ++++++--- sonoff/xnrg_06_pzem_dc.ino | 9 ++++++--- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index 39b690bce..1a541b8f8 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -30,6 +30,8 @@ #define XNRG_03 3 +const uint32_t PZEM_STABILIZE = 30; // Number of seconds to stabilize configuration + #include TasmotaSerial *PzemSerial = nullptr; @@ -192,7 +194,9 @@ void PzemEvery250ms(void) Pzem.energy += value; if (Pzem.phase == Energy.phase_count -1) { if (Pzem.energy > Pzem.last_energy) { // Handle missed phase - EnergyUpdateTotal(Pzem.energy, false); + if (uptime > PZEM_STABILIZE) { + EnergyUpdateTotal(Pzem.energy, false); + } Pzem.last_energy = Pzem.energy; } Pzem.energy = 0; @@ -228,7 +232,7 @@ void PzemEvery250ms(void) } else { Pzem.send_retry--; - if ((Energy.phase_count > 1) && (0 == Pzem.send_retry) && (uptime < 30)) { + if ((Energy.phase_count > 1) && (0 == Pzem.send_retry) && (uptime < PZEM_STABILIZE)) { Energy.phase_count--; // Decrement phases if no response after retry within 30 seconds after restart } } diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index af36d7466..b438138bd 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -31,7 +31,8 @@ #define XNRG_05 5 -#define PZEM_AC_DEVICE_ADDRESS 0x01 // PZEM default address +const uint8_t PZEM_AC_DEVICE_ADDRESS = 0x01; // PZEM default address +const uint32_t PZEM_AC_STABILIZE = 30; // Number of seconds to stabilize configuration #include TasmotaModbus *PzemAcModbus; @@ -79,7 +80,9 @@ void PzemAcEverySecond(void) PzemAc.energy += (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh if (PzemAc.phase == Energy.phase_count -1) { if (PzemAc.energy > PzemAc.last_energy) { // Handle missed phase - EnergyUpdateTotal(PzemAc.energy, false); + if (uptime > PZEM_AC_STABILIZE) { + EnergyUpdateTotal(PzemAc.energy, false); + } PzemAc.last_energy = PzemAc.energy; } PzemAc.energy = 0; @@ -105,7 +108,7 @@ void PzemAcEverySecond(void) } else { PzemAc.send_retry--; - if ((Energy.phase_count > 1) && (0 == PzemAc.send_retry) && (uptime < 30)) { + if ((Energy.phase_count > 1) && (0 == PzemAc.send_retry) && (uptime < PZEM_AC_STABILIZE)) { Energy.phase_count--; // Decrement phases if no response after retry within 30 seconds after restart } } diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index 5aaf3f29e..29687967a 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -31,7 +31,8 @@ #define XNRG_06 6 -#define PZEM_DC_DEVICE_ADDRESS 0x01 // PZEM default address +const uint8_t PZEM_DC_DEVICE_ADDRESS = 0x01; // PZEM default address +const uint32_t PZEM_DC_STABILIZE = 30; // Number of seconds to stabilize configuration #include TasmotaModbus *PzemDcModbus; @@ -77,7 +78,9 @@ void PzemDcEverySecond(void) PzemDc.energy += (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh if (PzemDc.channel == Energy.phase_count -1) { if (PzemDc.energy > PzemDc.last_energy) { // Handle missed channel - EnergyUpdateTotal(PzemDc.energy, false); + if (uptime > PZEM_DC_STABILIZE) { + EnergyUpdateTotal(PzemDc.energy, false); + } PzemDc.last_energy = PzemDc.energy; } PzemDc.energy = 0; @@ -102,7 +105,7 @@ void PzemDcEverySecond(void) } else { PzemDc.send_retry--; - if ((Energy.phase_count > 1) && (0 == PzemDc.send_retry) && (uptime < 30)) { + if ((Energy.phase_count > 1) && (0 == PzemDc.send_retry) && (uptime < PZEM_DC_STABILIZE)) { Energy.phase_count--; // Decrement channels if no response after retry within 30 seconds after restart } } From 833845e602064f805c2cea34f087f84f9006b7da Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 20 Oct 2019 16:43:50 +0200 Subject: [PATCH 2194/2222] Add ZigbeeRead command and many improvements (#6095) --- sonoff/_changelog.ino | 1 + sonoff/i18n.h | 5 + sonoff/xdrv_23_zigbee_3_devices.ino | 4 +- sonoff/xdrv_23_zigbee_5_converters.ino | 431 +++++++++++++++++------ sonoff/xdrv_23_zigbee_6_commands.ino | 92 +++++ sonoff/xdrv_23_zigbee_7_statemachine.ino | 2 +- sonoff/xdrv_23_zigbee_8_parsers.ino | 10 +- sonoff/xdrv_23_zigbee_9_impl.ino | 68 +++- 8 files changed, 486 insertions(+), 127 deletions(-) create mode 100644 sonoff/xdrv_23_zigbee_6_commands.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index b2badf70f..479f295aa 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -3,6 +3,7 @@ * Add command SetOption65 0/1 to disable (1) fast power cycle detection fixing unwanted brownout trigger * Add absolute PowerDelta using command PowerDelta 101..32000 where 101 = 101-100 = 1W, 202 = 202-100 = 102W (#5901) * Add support for EX-Store WiFi Dimmer V4 (#5856) + * Add ZigbeeRead command and many improvements (#6095) * * 6.6.0.19 20191018 * Replace obsolete xsns_23_sdm120 with xnrg_08_sdm120 and consolidate define USE_SDM120 diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 96f4db54e..e97cd1fee 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -468,9 +468,14 @@ #define D_JSON_ZIGBEEZNPSENT "ZigbeeZNPSent" #define D_JSON_ZIGBEEZCL_RECEIVED "ZigbeeZCLReceived" #define D_JSON_ZIGBEEZCL_RAW_RECEIVED "ZigbeeZCLRawReceived" + #define D_JSON_ZIGBEE_DEVICE "Device" + #define D_JSON_ZIGBEE_NAME "Name" #define D_CMND_ZIGBEE_ZCL_SEND "ZigbeeZCLSend" #define D_JSON_ZIGBEE_ZCL_SENT "ZigbeeZCLSent" #define D_CMND_ZIGBEE_PROBE "ZigbeeProbe" +#define D_CMND_ZIGBEE_RECEIVED "ZigbeeReceived" + #define D_CMND_ZIGBEE_LINKQUALITY "LinkQuality" +#define D_CMND_ZIGBEE_READ "ZigbeeRead" // Commands xdrv_25_A4988_Stepper.ino #ifdef USE_A4988_STEPPER diff --git a/sonoff/xdrv_23_zigbee_3_devices.ino b/sonoff/xdrv_23_zigbee_3_devices.ino index 3b0989027..3596ef78e 100644 --- a/sonoff/xdrv_23_zigbee_3_devices.ino +++ b/sonoff/xdrv_23_zigbee_3_devices.ino @@ -363,10 +363,10 @@ String Z_Devices::dump(uint8_t dump_mode) const { JsonObject& dev = devices.createNestedObject(); snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); - dev[F("ShortAddr")] = hex; + dev[F(D_JSON_ZIGBEE_DEVICE)] = hex; if (device.friendlyName.length() > 0) { - dev[F("FriendlyName")] = device.friendlyName; + dev[F(D_JSON_ZIGBEE_NAME)] = device.friendlyName; } if (1 == dump_mode) { diff --git a/sonoff/xdrv_23_zigbee_5_converters.ino b/sonoff/xdrv_23_zigbee_5_converters.ino index 8aa11ad01..804aa3d4f 100644 --- a/sonoff/xdrv_23_zigbee_5_converters.ino +++ b/sonoff/xdrv_23_zigbee_5_converters.ino @@ -59,7 +59,7 @@ public: Response_P(PSTR("{\"" D_JSON_ZIGBEEZCL_RECEIVED "\":{" "\"groupid\":%d," "\"clusterid\":%d," "\"srcaddr\":\"0x%04X\"," "\"srcendpoint\":%d," "\"dstendpoint\":%d," "\"wasbroadcast\":%d," - "\"linkquality\":%d," "\"securityuse\":%d," "\"seqnumber\":%d," + "\"" D_CMND_ZIGBEE_LINKQUALITY "\":%d," "\"securityuse\":%d," "\"seqnumber\":%d," "\"timestamp\":%d," "\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," "\"cmdid\":\"0x%02X\",\"payload\":\"%s\""), @@ -390,8 +390,8 @@ void ZCLFrame::parseRawAttributes(JsonObject& json, uint8_t offset) { i += 2; char key[16]; - snprintf_P(key, sizeof(key), PSTR("%04X_%02X_%04X"), - _cluster_id, _cmd_id, attrid); + snprintf_P(key, sizeof(key), PSTR("%04X/%04X"), + _cluster_id, attrid); // exception for Xiaomi lumi.weather - specific field to be treated as octet and not char if ((0x0000 == _cluster_id) && (0xFF01 == attrid)) { @@ -415,8 +415,8 @@ void ZCLFrame::parseReadAttributes(JsonObject& json, uint8_t offset) { if (0 == status) { char key[16]; - snprintf_P(key, sizeof(key), PSTR("%04X_%02X_%04X"), - _cluster_id, _cmd_id, attrid); + snprintf_P(key, sizeof(key), PSTR("%04X/%04X"), + _cluster_id, attrid); i += parseSingleAttribute(json, key, _payload, i, len); } @@ -442,106 +442,327 @@ void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { // return value: // 0 = keep initial value // 1 = remove initial value -typedef int32_t (*Z_AttrConverter)(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param); +typedef int32_t (*Z_AttrConverter)(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper* new_name); typedef struct Z_AttributeConverter { - const char * filter; + uint16_t cluster; + uint16_t attribute; const char * name; Z_AttrConverter func; - void * param; } Z_AttributeConverter; -const float Z_100 PROGMEM = 100.0f; -const float Z_10 PROGMEM = 10.0f; - // list of post-processing directives -const Z_AttributeConverter Z_PostProcess[] = { - { "0000_0?_0004", nullptr, &Z_ManufKeep, nullptr }, // record Manufacturer - { "0000_0?_0005", nullptr, &Z_ModelKeep, nullptr }, // record Model +const Z_AttributeConverter Z_PostProcess[] PROGMEM = { + // { 0x0000, 0x0004, "Manufacturer", &Z_ManufKeep }, // record Manufacturer + // { 0x0000, 0x0005, D_JSON_MODEL D_JSON_ID, &Z_ModelKeep }, // record Model + // { 0x0405, 0x0000, D_JSON_HUMIDITY, &Z_FloatDiv100 }, // Humidity - { "0000_0?_0000", "ZCLVersion", &Z_Copy, nullptr }, - { "0000_0?_0001", "AppVersion", &Z_Copy, nullptr }, - { "0000_0?_0002", "StackVersion", &Z_Copy, nullptr }, - { "0000_0?_0003", "HWVersion", &Z_Copy, nullptr }, - { "0000_0?_0004", "Manufacturer", &Z_Copy, nullptr }, - { "0000_0?_0005", D_JSON_MODEL D_JSON_ID, &Z_Copy, nullptr }, - { "0000_0?_0006", "DateCode", &Z_Copy, nullptr }, - { "0000_0?_0007", "PowerSource", &Z_Copy, nullptr }, - { "0000_0?_4000", "SWBuildID", &Z_Copy, nullptr }, - { "0000_0?_????", nullptr, &Z_Remove, nullptr }, // Remove all other values + { 0x0000, 0x0000, "ZCLVersion", &Z_Copy }, + { 0x0000, 0x0001, "AppVersion", &Z_Copy }, + { 0x0000, 0x0002, "StackVersion", &Z_Copy }, + { 0x0000, 0x0003, "HWVersion", &Z_Copy }, + { 0x0000, 0x0004, "Manufacturer", &Z_ManufKeep }, // record Manufacturer + { 0x0000, 0x0005, D_JSON_MODEL D_JSON_ID, &Z_ModelKeep }, // record Model + { 0x0000, 0x0006, "DateCode", &Z_Copy }, + { 0x0000, 0x0007, "PowerSource", &Z_Copy }, + { 0x0000, 0x4000, "SWBuildID", &Z_Copy }, + { 0x0000, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values - { "0400_0A_0000", D_JSON_ILLUMINANCE, &Z_Copy, nullptr }, // Illuminance (in Lux) - { "0400_0A_0004", "LightSensorType", &Z_Copy, nullptr }, // LightSensorType - { "0400_0A_????", nullptr, &Z_Remove, nullptr }, // Remove all other values + // Color Control cluster + { 0x0003, 0x0000, "CurrentHue", &Z_Copy }, + { 0x0003, 0x0001, "CurrentSaturation", &Z_Copy }, + { 0x0003, 0x0002, "RemainingTime", &Z_Copy }, + { 0x0003, 0x0003, "CurrentX", &Z_Copy }, + { 0x0003, 0x0004, "CurrentY", &Z_Copy }, + { 0x0003, 0x0005, "DriftCompensation", &Z_Copy }, + { 0x0003, 0x0006, "CompensationText", &Z_Copy }, + { 0x0003, 0x0007, "ColorTemperatureMireds",&Z_Copy }, + { 0x0003, 0x0008, "ColorMode", &Z_Copy }, + { 0x0003, 0x0010, "NumberOfPrimaries", &Z_Copy }, + { 0x0003, 0x0011, "Primary1X", &Z_Copy }, + { 0x0003, 0x0012, "Primary1Y", &Z_Copy }, + { 0x0003, 0x0013, "Primary1Intensity", &Z_Copy }, + { 0x0003, 0x0015, "Primary2X", &Z_Copy }, + { 0x0003, 0x0016, "Primary2Y", &Z_Copy }, + { 0x0003, 0x0017, "Primary2Intensity", &Z_Copy }, + { 0x0003, 0x0019, "Primary3X", &Z_Copy }, + { 0x0003, 0x001A, "Primary3Y", &Z_Copy }, + { 0x0003, 0x001B, "Primary3Intensity", &Z_Copy }, + { 0x0003, 0x0030, "WhitePointX", &Z_Copy }, + { 0x0003, 0x0031, "WhitePointY", &Z_Copy }, + { 0x0003, 0x0032, "ColorPointRX", &Z_Copy }, + { 0x0003, 0x0033, "ColorPointRY", &Z_Copy }, + { 0x0003, 0x0034, "ColorPointRIntensity", &Z_Copy }, + { 0x0003, 0x0036, "ColorPointGX", &Z_Copy }, + { 0x0003, 0x0037, "ColorPointGY", &Z_Copy }, + { 0x0003, 0x0038, "ColorPointGIntensity", &Z_Copy }, + { 0x0003, 0x003A, "ColorPointBX", &Z_Copy }, + { 0x0003, 0x003B, "ColorPointBY", &Z_Copy }, + { 0x0003, 0x003C, "ColorPointBIntensity", &Z_Copy }, - { "0401_0A_0000", "LevelStatus", &Z_Copy, nullptr }, // Illuminance (in Lux) - { "0401_0A_0001", "LightSensorType", &Z_Copy, nullptr }, // LightSensorType - { "0401_0A_????", nullptr, &Z_Remove, nullptr }, // Remove all other values + // On/off cluster + { 0x0006, 0x0000, "Power", &Z_Copy }, + // On/Off Switch Configuration cluster + { 0x0007, 0x0000, "SwitchType", &Z_Copy }, + // Level Control cluster + { 0x0008, 0x0000, "CurrentLevel", &Z_Copy }, + { 0x0008, 0x0001, "RemainingTime", &Z_Copy }, + { 0x0008, 0x0010, "OnOffTransitionTime", &Z_Copy }, + { 0x0008, 0x0011, "OnLevel", &Z_Copy }, + { 0x0008, 0x0012, "OnTransitionTime", &Z_Copy }, + { 0x0008, 0x0013, "OffTransitionTime", &Z_Copy }, + { 0x0008, 0x0014, "DefaultMoveRate", &Z_Copy }, + // Alarms cluster + { 0x0009, 0x0000, "AlarmCount", &Z_Copy }, + // Time cluster + { 0x000A, 0x0000, "Time", &Z_Copy }, + { 0x000A, 0x0001, "TimeStatus", &Z_Copy }, + { 0x000A, 0x0002, "TimeZone", &Z_Copy }, + { 0x000A, 0x0003, "DstStart", &Z_Copy }, + { 0x000A, 0x0004, "DstStart", &Z_Copy }, + { 0x000A, 0x0005, "DstShift", &Z_Copy }, + { 0x000A, 0x0006, "StandardTime", &Z_Copy }, + { 0x000A, 0x0007, "LocalTime", &Z_Copy }, + { 0x000A, 0x0008, "LastSetTime", &Z_Copy }, + { 0x000A, 0x0009, "ValidUntilTime", &Z_Copy }, + // RSSI Location cluster + { 0x000B, 0x0000, "LocationType", &Z_Copy }, + { 0x000B, 0x0000, "LocationMethod", &Z_Copy }, + { 0x000B, 0x0000, "LocationAge", &Z_Copy }, + { 0x000B, 0x0000, "QualityMeasure", &Z_Copy }, + { 0x000B, 0x0000, "NumberOfDevices", &Z_Copy }, + // Analog Input cluster + { 0x000C, 0x0004, "ActiveText", &Z_Copy }, + { 0x000C, 0x001C, "Description", &Z_Copy }, + { 0x000C, 0x002E, "InactiveText", &Z_Copy }, + { 0x000C, 0x0041, "MaxPresentValue", &Z_Copy }, + { 0x000C, 0x0045, "MinPresentValue", &Z_Copy }, + { 0x000C, 0x0051, "OutOfService", &Z_Copy }, + { 0x000C, 0x0055, "PresentValue", &Z_Copy }, + { 0x000C, 0x0057, "PriorityArray", &Z_Copy }, + { 0x000C, 0x0067, "Reliability", &Z_Copy }, + { 0x000C, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x000C, 0x006A, "Resolution", &Z_Copy }, + { 0x000C, 0x006F, "StatusFlags", &Z_Copy }, + { 0x000C, 0x0075, "EngineeringUnits", &Z_Copy }, + { 0x000C, 0x0100, "ApplicationType", &Z_Copy }, + // Binary Output cluster + { 0x0010, 0x0004, "ActiveText", &Z_Copy }, + { 0x0010, 0x001C, "Description", &Z_Copy }, + { 0x0010, 0x002E, "InactiveText", &Z_Copy }, + { 0x0010, 0x0042, "MinimumOffTime", &Z_Copy }, + { 0x0010, 0x0043, "MinimumOnTime", &Z_Copy }, + { 0x0010, 0x0051, "OutOfService", &Z_Copy }, + { 0x0010, 0x0054, "Polarity", &Z_Copy }, + { 0x0010, 0x0055, "PresentValue", &Z_Copy }, + { 0x0010, 0x0057, "PriorityArray", &Z_Copy }, + { 0x0010, 0x0067, "Reliability", &Z_Copy }, + { 0x0010, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x0010, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0010, 0x0100, "ApplicationType", &Z_Copy }, + // Binary Value cluster + { 0x0011, 0x0004, "ActiveText", &Z_Copy }, + { 0x0011, 0x001C, "Description", &Z_Copy }, + { 0x0011, 0x002E, "InactiveText", &Z_Copy }, + { 0x0011, 0x0042, "MinimumOffTime", &Z_Copy }, + { 0x0011, 0x0043, "MinimumOnTime", &Z_Copy }, + { 0x0011, 0x0051, "OutOfService", &Z_Copy }, + { 0x0011, 0x0055, "PresentValue", &Z_Copy }, + { 0x0011, 0x0057, "PriorityArray", &Z_Copy }, + { 0x0011, 0x0067, "Reliability", &Z_Copy }, + { 0x0011, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x0011, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0011, 0x0100, "ApplicationType", &Z_Copy }, + // Multistate Input cluster + { 0x0012, 0x000E, "StateText", &Z_Copy }, + { 0x0012, 0x001C, "Description", &Z_Copy }, + { 0x0012, 0x004A, "NumberOfStates", &Z_Copy }, + { 0x0012, 0x0051, "OutOfService", &Z_Copy }, + { 0x0012, 0x0055, "PresentValue", &Z_Copy }, + { 0x0012, 0x0067, "Reliability", &Z_Copy }, + { 0x0012, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0012, 0x0100, "ApplicationType", &Z_Copy }, + // Multistate output + { 0x0013, 0x000E, "StateText", &Z_Copy }, + { 0x0013, 0x001C, "Description", &Z_Copy }, + { 0x0013, 0x004A, "NumberOfStates", &Z_Copy }, + { 0x0013, 0x0051, "OutOfService", &Z_Copy }, + { 0x0013, 0x0055, "PresentValue", &Z_Copy }, + { 0x0013, 0x0057, "PriorityArray", &Z_Copy }, + { 0x0013, 0x0067, "Reliability", &Z_Copy }, + { 0x0013, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x0013, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0013, 0x0100, "ApplicationType", &Z_Copy }, + // Multistate Value cluster + { 0x0014, 0x000E, "StateText", &Z_Copy }, + { 0x0014, 0x001C, "Description", &Z_Copy }, + { 0x0014, 0x004A, "NumberOfStates", &Z_Copy }, + { 0x0014, 0x0051, "OutOfService", &Z_Copy }, + { 0x0014, 0x0055, "PresentValue", &Z_Copy }, + { 0x0014, 0x0067, "Reliability", &Z_Copy }, + { 0x0014, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x0014, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0014, 0x0100, "ApplicationType", &Z_Copy }, + // Diagnostics cluster + { 0x0B05, 0x0000, "NumberOfResets", &Z_Copy }, + { 0x0B05, 0x0001, "PersistentMemoryWrites",&Z_Copy }, + { 0x0B05, 0x011C, "LastMessageLQI", &Z_Copy }, + { 0x0B05, 0x011D, "LastMessageRSSI", &Z_Copy }, + // Poll Control cluster + { 0x0020, 0x0000, "CheckinInterval", &Z_Copy }, + { 0x0020, 0x0001, "LongPollInterval", &Z_Copy }, + { 0x0020, 0x0002, "ShortPollInterval", &Z_Copy }, + { 0x0020, 0x0003, "FastPollTimeout", &Z_Copy }, + { 0x0020, 0x0004, "CheckinIntervalMin", &Z_Copy }, + { 0x0020, 0x0005, "LongPollIntervalMin", &Z_Copy }, + { 0x0020, 0x0006, "FastPollTimeoutMax", &Z_Copy }, + // Shade Configuration cluster + { 0x0100, 0x0000, "PhysicalClosedLimit", &Z_Copy }, + { 0x0100, 0x0001, "MotorStepSize", &Z_Copy }, + { 0x0100, 0x0002, "Status", &Z_Copy }, + { 0x0100, 0x0010, "ClosedLimit", &Z_Copy }, + { 0x0100, 0x0011, "Mode", &Z_Copy }, + // Door Lock cluster + { 0x0101, 0x0000, "LockState", &Z_Copy }, + { 0x0101, 0x0001, "LockType", &Z_Copy }, + { 0x0101, 0x0002, "ActuatorEnabled", &Z_Copy }, + { 0x0101, 0x0003, "DoorState", &Z_Copy }, + { 0x0101, 0x0004, "DoorOpenEvents", &Z_Copy }, + { 0x0101, 0x0005, "DoorClosedEvents", &Z_Copy }, + { 0x0101, 0x0006, "OpenPeriod", &Z_Copy }, + // Window Covering cluster + { 0x0102, 0x0000, "WindowCoveringType", &Z_Copy }, + { 0x0102, 0x0001, "PhysicalClosedLimitLift",&Z_Copy }, + { 0x0102, 0x0002, "PhysicalClosedLimitTilt",&Z_Copy }, + { 0x0102, 0x0003, "CurrentPositionLift", &Z_Copy }, + { 0x0102, 0x0004, "CurrentPositionTilt", &Z_Copy }, + { 0x0102, 0x0005, "NumberofActuationsLift",&Z_Copy }, + { 0x0102, 0x0006, "NumberofActuationsTilt",&Z_Copy }, + { 0x0102, 0x0007, "ConfigStatus", &Z_Copy }, + { 0x0102, 0x0008, "CurrentPositionLiftPercentage",&Z_Copy }, + { 0x0102, 0x0009, "CurrentPositionTiltPercentage",&Z_Copy }, + { 0x0102, 0x0010, "InstalledOpenLimitLift",&Z_Copy }, + { 0x0102, 0x0011, "InstalledClosedLimitLift",&Z_Copy }, + { 0x0102, 0x0012, "InstalledOpenLimitTilt", &Z_Copy }, + { 0x0102, 0x0013, "InstalledClosedLimitTilt", &Z_Copy }, + { 0x0102, 0x0014, "VelocityLift",&Z_Copy }, + { 0x0102, 0x0015, "AccelerationTimeLift",&Z_Copy }, + { 0x0102, 0x0016, "DecelerationTimeLift", &Z_Copy }, + { 0x0102, 0x0017, "Mode",&Z_Copy }, + { 0x0102, 0x0018, "IntermediateSetpointsLift",&Z_Copy }, + { 0x0102, 0x0019, "IntermediateSetpointsTilt",&Z_Copy }, - { "0402_0A_0000", D_JSON_TEMPERATURE, &Z_ConvFloatDivider, (void*) &Z_100 }, // Temperature - { "0402_0A_????", nullptr, &Z_Remove, nullptr }, // Remove all other values + // Power Profile cluster + { 0x001A, 0x0000, "TotalProfileNum", &Z_Copy }, + { 0x001A, 0x0001, "MultipleScheduling", &Z_Copy }, + { 0x001A, 0x0002, "EnergyFormatting", &Z_Copy }, + { 0x001A, 0x0003, "EnergyRemote", &Z_Copy }, + { 0x001A, 0x0004, "ScheduleMode", &Z_Copy }, + // Meter Identification cluster + { 0x0B01, 0x0000, "CompanyName", &Z_Copy }, + { 0x0B01, 0x0001, "MeterTypeID", &Z_Copy }, + { 0x0B01, 0x0004, "DataQualityID", &Z_Copy }, + { 0x0B01, 0x0005, "CustomerName", &Z_Copy }, + { 0x0B01, 0x0006, "Model", &Z_Copy }, + { 0x0B01, 0x0007, "PartNumber", &Z_Copy }, + { 0x0B01, 0x000A, "SoftwareRevision", &Z_Copy }, + { 0x0B01, 0x000C, "POD", &Z_Copy }, + { 0x0B01, 0x000D, "AvailablePower", &Z_Copy }, + { 0x0B01, 0x000E, "PowerThreshold", &Z_Copy }, - { "0403_0A_0000", D_JSON_PRESSURE_UNIT, &Z_Const_Keep, (void*) D_UNIT_PRESSURE}, // Pressure Unit - { "0403_0A_0000", D_JSON_PRESSURE, &Z_Copy, nullptr }, // Pressure - { "0403_0A_????", nullptr, &Z_Remove, nullptr }, // Remove all other Pressure values + { 0x0400, 0x0000, D_JSON_ILLUMINANCE, &Z_Copy }, // Illuminance (in Lux) + { 0x0400, 0x0001, "MinMeasuredValue", &Z_Copy }, // + { 0x0400, 0x0002, "MaxMeasuredValue", &Z_Copy }, // + { 0x0400, 0x0003, "Tolerance", &Z_Copy }, // + { 0x0400, 0x0004, "LightSensorType", &Z_Copy }, // + { 0x0400, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values - { "0404_0A_0000", D_JSON_FLOWRATE, &Z_ConvFloatDivider, (void*) &Z_10 }, // Flow (in m3/h) - { "0404_0A_????", nullptr, &Z_Remove, nullptr }, // Remove all other values + { 0x0401, 0x0000, "LevelStatus", &Z_Copy }, // Illuminance (in Lux) + { 0x0401, 0x0001, "LightSensorType", &Z_Copy }, // LightSensorType + { 0x0401, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values - { "0405_0A_0000", D_JSON_HUMIDITY, &Z_ConvFloatDivider, (void*) &Z_100 }, // Humidity - { "0405_0A_????", nullptr, &Z_Remove, nullptr }, // Remove all other values + { 0x0402, 0x0000, D_JSON_TEMPERATURE, &Z_FloatDiv100 }, // Temperature + { 0x0402, 0x0001, "MinMeasuredValue", &Z_FloatDiv100 }, // + { 0x0402, 0x0002, "MaxMeasuredValue", &Z_FloatDiv100 }, // + { 0x0402, 0x0003, "Tolerance", &Z_FloatDiv100 }, // + { 0x0402, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values - { "0406_0A_0000", "Occupancy", &Z_Copy, nullptr }, // Occupancy (map8) - { "0406_0A_0001", "OccupancySensorType", &Z_Copy, nullptr }, // OccupancySensorType - { "0406_0A_????", nullptr, &Z_Remove, nullptr }, // Remove all other values + { 0x0403, 0x0000, D_JSON_PRESSURE_UNIT, &Z_AddPressureUnit }, // Pressure Unit + { 0x0403, 0x0000, D_JSON_PRESSURE, &Z_Copy }, // Pressure + { 0x0403, 0x0001, "MinMeasuredValue", &Z_Copy }, // + { 0x0403, 0x0002, "MaxMeasuredValue", &Z_Copy }, // + { 0x0403, 0x0003, "Tolerance", &Z_Copy }, // + { 0x0403, 0x0010, "ScaledValue", &Z_Copy }, // + { 0x0403, 0x0011, "MinScaledValue", &Z_Copy }, // + { 0x0403, 0x0012, "MaxScaledValue", &Z_Copy }, // + { 0x0403, 0x0013, "ScaledTolerance", &Z_Copy }, // + { 0x0403, 0x0014, "Scale", &Z_Copy }, // + { 0x0403, 0xFFFF, nullptr, &Z_Remove }, // Remove all other Pressure values + + { 0x0404, 0x0000, D_JSON_FLOWRATE, &Z_FloatDiv10 }, // Flow (in m3/h) + { 0x0404, 0x0001, "MinMeasuredValue", &Z_Copy }, // + { 0x0404, 0x0002, "MaxMeasuredValue", &Z_Copy }, // + { 0x0404, 0x0003, "Tolerance", &Z_Copy }, // + { 0x0404, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values + + { 0x0405, 0x0000, D_JSON_HUMIDITY, &Z_FloatDiv100 }, // Humidity + { 0x0405, 0x0001, "MinMeasuredValue", &Z_Copy }, // + { 0x0405, 0x0002, "MaxMeasuredValue", &Z_Copy }, // + { 0x0405, 0x0003, "Tolerance", &Z_Copy }, // + { 0x0405, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values + + { 0x0406, 0x0000, "Occupancy", &Z_Copy }, // Occupancy (map8) + { 0x0406, 0x0001, "OccupancySensorType", &Z_Copy }, // OccupancySensorType + { 0x0406, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Cmd 0x0A - Cluster 0x0000, attribute 0xFF01 - proprietary - { "0000_0A_FF01", nullptr, &Z_AqaraSensor, nullptr }, // Occupancy (map8) - // // 0x0b04 Electrical Measurement - // { "0B04_0100", "DCVoltage", &Z_Copy, nullptr }, // - // { "0B04_0001", "OccupancySensorType", &Z_Copy, nullptr }, // - // { "0B04_????", "", &Z_Remove, nullptr }, // -}; + { 0x0000, 0xFF01, nullptr, &Z_AqaraSensor }, // Occupancy (map8) +}; // ====================================================================== // Record Manuf -int32_t Z_ManufKeep(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param) { +int32_t Z_ManufKeep(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { + json[new_name] = value; zigbee_devices.setManufId(shortaddr, value.as()); - return 0; // keep original key + return 1; } // -int32_t Z_ModelKeep(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param) { +int32_t Z_ModelKeep(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { + json[new_name] = value; zigbee_devices.setModelId(shortaddr, value.as()); - return 0; // keep original key + return 1; } // ====================================================================== // Remove attribute -int32_t Z_Remove(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param) { +int32_t Z_Remove(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { return 1; // remove original key } // Copy value as-is -int32_t Z_Copy(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param) { +int32_t Z_Copy(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { json[new_name] = value; return 1; // remove original key } -// Copy value as-is -int32_t Z_Const_Keep(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param) { - json[new_name] = (char*)param; +// Add pressure unit +int32_t Z_AddPressureUnit(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { + json[new_name] = F(D_UNIT_PRESSURE); return 0; // keep original key } -// Convert int to float with divider -int32_t Z_ConvFloatDivider(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param) { - float f_value = value; - float *divider = (float*) param; - json[new_name] = f_value / *divider; +// Convert int to float and divide by 100 +int32_t Z_FloatDiv100(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { + json[new_name] = ((float)value) / 100.0f; + return 1; // remove original key +} +// Convert int to float and divide by 10 +int32_t Z_FloatDiv10(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { + json[new_name] = ((float)value) / 10.0f; return 1; // remove original key } -int32_t Z_AqaraSensor(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param) { +int32_t Z_AqaraSensor(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { String hex = value; SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); uint32_t i = 0; @@ -572,69 +793,49 @@ int32_t Z_AqaraSensor(uint16_t shortaddr, JsonObject& json, const char *name, Js } // ====================================================================== -// #define ZCL_MODELID "A_0000_0005" // Cmd 0x0A - Cluster 0x0000, attribute 0x05 -// #define ZCL_TEMPERATURE "A_0402_0000" // Cmd 0x0A - Cluster 0x0402, attribute 0x00 -// #define ZCL_PRESSURE "A_0403_0000" // Cmd 0x0A - Cluster 0x0403, attribute 0x00 -// #define ZCL_PRESSURE_SCALED "A_0403_0010" // Cmd 0x0A - Cluster 0x0403, attribute 0x10 -// #define ZCL_PRESSURE_SCALE "A_0403_0014" // Cmd 0x0A - Cluster 0x0403, attribute 0x14 -// #define ZCL_HUMIDITY "A_0405_0000" // Cmd 0x0A - Cluster 0x0403, attribute 0x00 -// #define ZCL_LUMI_WEATHER "A_0000_FF01" // Cmd 0x0A - Cluster 0x0000, attribute 0xFF01 - proprietary - // Cluster Specific commands -#define ZCL_OO_OFF "s_0006_00" // Cluster 0x0006, cmd 0x00 - On/Off - Off -#define ZCL_OO_ON "s_0006_01" // Cluster 0x0006, cmd 0x01 - On/Off - On -#define ZCL_COLORTEMP_MOVE "s_0300_0A" // Cluster 0x0300, cmd 0x0A, Move to Color Temp -#define ZCL_LC_MOVE "s_0008_00" // Cluster 0x0008, cmd 0x00, Level Control Move to Level -#define ZCL_LC_MOVE_1 "s_0008_01" // Cluster 0x0008, cmd 0x01, Level Control Move -#define ZCL_LC_STEP "s_0008_02" // Cluster 0x0008, cmd 0x02, Level Control Step -#define ZCL_LC_STOP "s_0008_03" // Cluster 0x0008, cmd 0x03, Level Control Stop -#define ZCL_LC_MOVE_WOO "s_0008_04" // Cluster 0x0008, cmd 0x04, Level Control Move to Level, with On/Off -#define ZCL_LC_MOVE_1_WOO "s_0008_05" // Cluster 0x0008, cmd 0x05, Level Control Move, with On/Off -#define ZCL_LC_STEP_WOO "s_0008_06" // Cluster 0x0008, cmd 0x05, Level Control Step, with On/Off -#define ZCL_LC_STOP_WOO "s_0008_07" // Cluster 0x0008, cmd 0x07, Level Control Stop +// #define ZCL_OO_OFF "s_0006_00" // Cluster 0x0006, cmd 0x00 - On/Off - Off +// #define ZCL_OO_ON "s_0006_01" // Cluster 0x0006, cmd 0x01 - On/Off - On +// #define ZCL_COLORTEMP_MOVE "s_0300_0A" // Cluster 0x0300, cmd 0x0A, Move to Color Temp +// #define ZCL_LC_MOVE "s_0008_00" // Cluster 0x0008, cmd 0x00, Level Control Move to Level +// #define ZCL_LC_MOVE_1 "s_0008_01" // Cluster 0x0008, cmd 0x01, Level Control Move +// #define ZCL_LC_STEP "s_0008_02" // Cluster 0x0008, cmd 0x02, Level Control Step +// #define ZCL_LC_STOP "s_0008_03" // Cluster 0x0008, cmd 0x03, Level Control Stop +// #define ZCL_LC_MOVE_WOO "s_0008_04" // Cluster 0x0008, cmd 0x04, Level Control Move to Level, with On/Off +// #define ZCL_LC_MOVE_1_WOO "s_0008_05" // Cluster 0x0008, cmd 0x05, Level Control Move, with On/Off +// #define ZCL_LC_STEP_WOO "s_0008_06" // Cluster 0x0008, cmd 0x05, Level Control Step, with On/Off +// #define ZCL_LC_STOP_WOO "s_0008_07" // Cluster 0x0008, cmd 0x07, Level Control Stop -// inspired from https://github.com/torvalds/linux/blob/master/lib/glob.c -bool mini_glob_match(char const *pat, char const *str) { - for (;;) { - unsigned char c = *str++; - unsigned char d = *pat++; - - switch (d) { - case '?': /* Wildcard: anything but nul */ - if (c == '\0') - return false; - break; - case '\\': - d = *pat++; - /*FALLTHROUGH*/ - default: /* Literal character */ - if (c == d) { - if (d == '\0') - return true; - break; - } - return false; /* No point continuing */ - } - } -} void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { // iterate on json elements for (auto kv : json) { - String key = kv.key; + String key_string = kv.key; + const char * key = key_string.c_str(); JsonVariant& value = kv.value; + // Check that format looks like "CCCC/AAAA" + char * delimiter = strchr(key, '/'); + if (delimiter) { + uint16_t cluster = strtoul(key, &delimiter, 16); + uint16_t attribute = strtoul(delimiter+1, nullptr, 16); - // Iterate on filter - for (uint32_t i = 0; i < sizeof(Z_PostProcess) / sizeof(Z_PostProcess[0]); i++) { - const Z_AttributeConverter *converter = &Z_PostProcess[i]; + // Iterate on filter + for (uint32_t i = 0; i < sizeof(Z_PostProcess) / sizeof(Z_PostProcess[0]); i++) { + const Z_AttributeConverter *converter = &Z_PostProcess[i]; + uint16_t conv_cluster = pgm_read_word(&converter->cluster); + uint16_t conv_attribute = pgm_read_word(&converter->attribute); + + if ((conv_cluster == cluster) && + ((conv_attribute == attribute) || (conv_attribute == 0xFFFF)) ) { + int32_t drop = (*converter->func)(shortaddr, json, key, value, (const __FlashStringHelper*) converter->name); + if (drop) { + json.remove(key); + } - if (mini_glob_match(converter->filter, key.c_str())) { - int32_t drop = (*converter->func)(shortaddr, json, key.c_str(), value, converter->name, converter->param); - if (drop) { - json.remove(key); } - } + } else { + AddLog_P2(LOG_LEVEL_INFO, PSTR("postProcessAttributes: wrong format for attribute : %s"), key); } } } diff --git a/sonoff/xdrv_23_zigbee_6_commands.ino b/sonoff/xdrv_23_zigbee_6_commands.ino new file mode 100644 index 000000000..017d2cd98 --- /dev/null +++ b/sonoff/xdrv_23_zigbee_6_commands.ino @@ -0,0 +1,92 @@ +/* + xdrv_23_zigbee_converters.ino - zigbee support for Sonoff-Tasmota + + Copyright (C) 2019 Theo Arends and Stephan Hadinger + + 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_ZIGBEE + +//typedef int32_t (*Z_AttrConverter)(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param); +typedef struct Z_CommandConverter { + const char * tasmota_cmd; + const char * zcl_cmd; +} Z_CommandConverter; + +// list of post-processing directives +const Z_CommandConverter Z_Commands[] = { + { "Power", "0006!xx" }, // 0=Off, 1=On, 2=Toggle + { "Dimmer", "0008!04/xx0A00" }, // Move to Level with On/Off, xx=0..254 (255 is invalid) + { "Dimmer+", "0008!06/001902" }, // Step up by 10%, 0.2 secs + { "Dimmer-", "0008!06/011902" }, // Step down by 10%, 0.2 secs + { "Hue", "0300!00/xx000A00" }, // Move to Hue, shortest time, 1s + { "Sat", "0300!03/xx0A00" }, // Move to Sat + { "HueSat", "0300!06/xxyy0A00" }, // Hue, Sat + { "Color", "0300!07/xxxxyyyy0A00" }, // x, y (uint16) + { "CT", "0300!0A/xxxx0A00" }, // Color Temperature Mireds (uint16) + { "ShutterOpen", "0102!00"}, + { "ShutterClose", "0102!01"}, + { "ShutterStop", "0102!02"}, + { "ShutterLift", "0102!05xx"}, // Lift percentage, 0%=open, 100%=closed + { "ShutterTilt", "0102!08xx"}, // Tilt percentage +}; + +inline bool isXYZ(char c) { + return (c >= 'x') && (c <= 'z'); +} + +// take the lower 4 bits and turn it to an hex char +inline char hexDigit(uint32_t h) { + uint32_t nybble = h & 0x0F; + return (nybble > 9) ? 'A' - 10 + nybble : '0' + nybble; +} + +// replace all xx/yy/zz substrings with unsigned ints, and the corresponding len (8, 16 or 32 bits) +// zcl_cmd can be in PROGMEM +String SendZCLCommand_P(const char *zcl_cmd_P, uint32_t x, uint32_t y, uint32_t z) { + size_t len = strlen_P(zcl_cmd_P); + char zcl_cmd[len+1]; + strcpy_P(zcl_cmd, zcl_cmd_P); // copy into RAM + + char *p = zcl_cmd; + while (*p) { + if (isXYZ(*p) && (*p == *(p+1))) { // if char is [x-z] and followed by same char + uint8_t val; + switch (*p) { + case 'x': + val = x & 0xFF; + x = x >> 8; + break; + case 'y': + val = y & 0xFF; + y = y >> 8; + break; + case 'z': + val = z & 0xFF; + z = z >> 8; + break; + } + *p = hexDigit(val >> 4); + *(p+1) = hexDigit(val); + p++; + } + p++; + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SendZCLCommand_P: zcl_cmd = %s"), zcl_cmd); + + return String(zcl_cmd); +} + +#endif // USE_ZIGBEE diff --git a/sonoff/xdrv_23_zigbee_7_statemachine.ino b/sonoff/xdrv_23_zigbee_7_statemachine.ino index 7bd3a4129..844086bce 100644 --- a/sonoff/xdrv_23_zigbee_7_statemachine.ino +++ b/sonoff/xdrv_23_zigbee_7_statemachine.ino @@ -319,7 +319,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = { ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) ZI_ON_RECV_UNEXPECTED(&Z_Recv_Default) - ZI_WAIT(10000) // wait for 10 seconds for Tasmota to stabilize + ZI_WAIT(10500) // wait for 10 seconds for Tasmota to stabilize ZI_ON_ERROR_GOTO(50) //ZI_MQTT_STATUS(ZIGBEE_STATUS_BOOT, "Booting") diff --git a/sonoff/xdrv_23_zigbee_8_parsers.ino b/sonoff/xdrv_23_zigbee_8_parsers.ino index 4050e45ae..495ce61ab 100644 --- a/sonoff/xdrv_23_zigbee_8_parsers.ino +++ b/sonoff/xdrv_23_zigbee_8_parsers.ino @@ -274,7 +274,7 @@ void Z_SendAFInfoRequest(uint16_t shortaddr, uint8_t endpoint, uint16_t clusteri buf.add8(3 + 2*sizeof(uint16_t)); // Len = 0x07 buf.add8(0x00); // Frame Control Field - buf.add8(transacid); // Transaction Sequance Number + buf.add8(transacid); // Transaction Sequence Number buf.add8(ZCL_READ_ATTRIBUTES); // 00 Command buf.add16(0x0004); // 0400 ManufacturerName buf.add16(0x0005); // 0500 ModelIdentifier @@ -385,7 +385,9 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { DynamicJsonBuffer jsonBuffer; JsonObject& json_root = jsonBuffer.createObject(); - JsonObject& json = json_root.createNestedObject(shortaddr); + JsonObject& json = json_root.createNestedObject(F(D_CMND_ZIGBEE_RECEIVED)); + json[F(D_JSON_ZIGBEE_DEVICE)] = shortaddr; + // TODO add name field if it is known if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { zcl_received.parseRawAttributes(json); } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES_RESPONSE == zcl_received.getCmdId())) { @@ -399,11 +401,13 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeZCLRawReceived: %s"), msg.c_str()); zcl_received.postProcessAttributes(srcaddr, json); + // Add linkquality + json[F("_" D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; // prefix with underscore for metadata msg = ""; json_root.printTo(msg); Response_P(PSTR("%s"), msg.c_str()); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); XdrvRulesProcess(); return -1; } diff --git a/sonoff/xdrv_23_zigbee_9_impl.ino b/sonoff/xdrv_23_zigbee_9_impl.ino index 32d1e8885..07fec54f4 100644 --- a/sonoff/xdrv_23_zigbee_9_impl.ino +++ b/sonoff/xdrv_23_zigbee_9_impl.ino @@ -38,11 +38,11 @@ TasmotaSerial *ZigbeeSerial = nullptr; const char kZigbeeCommands[] PROGMEM = "|" D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_ZCL_SEND - "|" D_CMND_ZIGBEE_PROBE; + "|" D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ; void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZigbeeZNPSend, &CmndZigbeePermitJoin, &CmndZigbeeStatus, &CmndZigbeeReset, &CmndZigbeeZCLSend, - &CmndZigbeeProbe }; + &CmndZigbeeProbe, &CmndZigbeeRead }; int32_t ZigbeeProcessInput(class SBuffer &buf) { if (!zigbee.state_machine) { return -1; } // if state machine is stopped, send 'ignore' message @@ -338,7 +338,7 @@ void ZigbeeZNPSend(const uint8_t *msg, size_t len) { #endif } -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, uint8_t transacId = 1) { +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp = true, uint8_t transacId = 1) { SBuffer buf(25+len); buf.add8(Z_SREQ | Z_AF); // 24 buf.add8(AF_DATA_REQUEST); // 01 @@ -351,10 +351,12 @@ void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8 buf.add8(0x1E); // 1E radius buf.add8(3 + len); - buf.add8(0x10 | (clusterSpecific ? 0x01 : 0x00)); // Frame Control Field + buf.add8((disableDefResp ? 0x10 : 0x00) | (clusterSpecific ? 0x01 : 0x00)); // Frame Control Field buf.add8(transacId); // Transaction Sequance Number buf.add8(cmdId); - buf.addBuffer(msg, len); // add the payload + if (len > 0) { + buf.addBuffer(msg, len); // add the payload + } ZigbeeZNPSend(buf.getBuffer(), buf.len()); } @@ -385,7 +387,7 @@ uint32_t parseHex(const char **data, size_t max_len = 8) { void CmndZigbeeZCLSend(void) { char parm_uc[12]; // used to convert JSON keys to uppercase - // ZigbeeZCLSend { "dst":"0x1234", "cluster":"0x0300", "endpoint":"0x01", "cmd":10, "data":"AABBCC" } + // ZigbeeZCLSend { "dst":"0x1234", "endpoint":"0x01", "cmd":"AABBCC" } char dataBufUc[XdrvMailbox.data_len]; UpperCase(dataBufUc, XdrvMailbox.data); RemoveSpace(dataBufUc); @@ -472,6 +474,60 @@ void CmndZigbeeProbe(void) { ResponseCmndDone(); } +// Send an attribute read command to a device, specifying cluster and list of attributes +void CmndZigbeeRead(void) { + char parm_uc[12]; // used to convert JSON keys to uppercase + // ZigbeeRead {"Device":"0xF289","Cluster":0,"Endpoint":3,"Attr":5} + // ZigbeeRead {"Device":"0xF289","Cluster":"0x0000","Endpoint":"0x0003","Attr":"0x0005"} + // ZigbeeRead {"Device":"0xF289","Cluster":0,"Endpoint":3,"Attr":[5,6,7,4]} + char dataBufUc[XdrvMailbox.data_len]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } + + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(dataBufUc); + if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } + + // params + uint16_t dstAddr = 0x0000; // default to local address + uint16_t cluster = 0x0000; // default to general clsuter + uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint + size_t attrs_len = 0; + uint8_t* attrs = nullptr; // empty string is valid + + dstAddr = strToUInt(json[UpperCase_P(parm_uc, PSTR("device"))]); + endpoint = strToUInt(json[UpperCase_P(parm_uc, PSTR("endpoint"))]); + cluster = strToUInt(json[UpperCase_P(parm_uc, PSTR("cluster"))]); + UpperCase_P(parm_uc, PSTR("Attr")); + if (json.containsKey(parm_uc)) { + const JsonVariant& attr_data = json[parm_uc]; + if (attr_data.is()) { + JsonArray& attr_arr = attr_data; + attrs_len = attr_arr.size() * 2; + attrs = new uint8_t[attrs_len]; + + uint32_t i = 0; + for (auto value : attr_arr) { + uint16_t val = strToUInt(value); + attrs[i++] = val & 0xFF; + attrs[i++] = val >> 8; + } + + } else { + attrs_len = 2; + attrs = new uint8_t[attrs_len]; + uint16_t val = strToUInt(attr_data); + attrs[0] = val & 0xFF; // little endian + attrs[1] = val >> 8; + } + } + + ZigbeeZCLSend(dstAddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false /* we do want a response */); + + if (attrs) { delete[] attrs; } +} + // Allow or Deny pairing of new Zigbee devices void CmndZigbeePermitJoin(void) { From 8d857ef8e215a5849247f8a3a4326f4107a431dc Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 20 Oct 2019 17:28:34 +0200 Subject: [PATCH 2195/2222] Fix remove useless log --- sonoff/xdrv_23_zigbee_5_converters.ino | 2 -- 1 file changed, 2 deletions(-) diff --git a/sonoff/xdrv_23_zigbee_5_converters.ino b/sonoff/xdrv_23_zigbee_5_converters.ino index 804aa3d4f..76df95aeb 100644 --- a/sonoff/xdrv_23_zigbee_5_converters.ino +++ b/sonoff/xdrv_23_zigbee_5_converters.ino @@ -834,8 +834,6 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { } } - } else { - AddLog_P2(LOG_LEVEL_INFO, PSTR("postProcessAttributes: wrong format for attribute : %s"), key); } } } From 8976021389cd58a2d4ea39790a1a3eea433a4f3d Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 20 Oct 2019 20:08:46 +0200 Subject: [PATCH 2196/2222] Add ArduinoHexParse library for specific page size --- lib/ArduinoHexParse/README.md | 3 + lib/ArduinoHexParse/keywords.txt | 25 ++++ lib/ArduinoHexParse/library.json | 12 ++ lib/ArduinoHexParse/library.properties | 9 ++ lib/ArduinoHexParse/src/ArduinoHexParse.cpp | 134 ++++++++++++++++++++ lib/ArduinoHexParse/src/ArduinoHexParse.h | 47 +++++++ 6 files changed, 230 insertions(+) create mode 100644 lib/ArduinoHexParse/README.md create mode 100644 lib/ArduinoHexParse/keywords.txt create mode 100644 lib/ArduinoHexParse/library.json create mode 100644 lib/ArduinoHexParse/library.properties create mode 100644 lib/ArduinoHexParse/src/ArduinoHexParse.cpp create mode 100644 lib/ArduinoHexParse/src/ArduinoHexParse.h diff --git a/lib/ArduinoHexParse/README.md b/lib/ArduinoHexParse/README.md new file mode 100644 index 000000000..c5c6a6751 --- /dev/null +++ b/lib/ArduinoHexParse/README.md @@ -0,0 +1,3 @@ +# ArduinoHexParse + +Parse hex files created by Arduino for Uno/Mini/Nano diff --git a/lib/ArduinoHexParse/keywords.txt b/lib/ArduinoHexParse/keywords.txt new file mode 100644 index 000000000..c60688578 --- /dev/null +++ b/lib/ArduinoHexParse/keywords.txt @@ -0,0 +1,25 @@ +####################################### +# Syntax Coloring Map for ArduinoHexParse +# (esp8266) +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +ArduinoHexParse KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +ArduinoHexParse KEYWORD2 +ParseLine KEYWORD2 +GetFlashPage KEYWORD2 +GetLoadAddress KEYWORD2 +IsFlashPageReady KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/lib/ArduinoHexParse/library.json b/lib/ArduinoHexParse/library.json new file mode 100644 index 000000000..896b53f6d --- /dev/null +++ b/lib/ArduinoHexParse/library.json @@ -0,0 +1,12 @@ +{ + "name": "ArduinoHexParse", + "version": "0.0.1", + "description": "Parse hex files created by Arduino for Uno/Mini/Nano", + "repository": + { + "type": "git", + "url": "https://github.com/arendst/Sonoff-Tasmota/lib/ArduinoHexParse" + }, + "frameworks": "arduino", + "platforms": "espressif8266" +} diff --git a/lib/ArduinoHexParse/library.properties b/lib/ArduinoHexParse/library.properties new file mode 100644 index 000000000..034c22e64 --- /dev/null +++ b/lib/ArduinoHexParse/library.properties @@ -0,0 +1,9 @@ +name=ArduinoHexParse +version=0.0.1 +author=Andre Thomas +maintainer=Andre Thomas +sentence=Parse hex files created by Arduino for Uno/Mini/Nano +paragraph= +category=Signal Input/Output +url= +architectures=esp8266 diff --git a/lib/ArduinoHexParse/src/ArduinoHexParse.cpp b/lib/ArduinoHexParse/src/ArduinoHexParse.cpp new file mode 100644 index 000000000..d4125f2f5 --- /dev/null +++ b/lib/ArduinoHexParse/src/ArduinoHexParse.cpp @@ -0,0 +1,134 @@ +/* + Copyright (C) 2019 Andre Thomas 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 + 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 . +*/ + +#include +#include "ArduinoHexParse.h" + +ArduinoHexParse::ArduinoHexParse(void) +{ + loadAddress[0] = 0; + loadAddress[1] = 0; +} + +void ArduinoHexParse::ParseLine(byte* hexline) +{ + recordType = GetRecordType(hexline); + if (0 == recordType) { + address = GetAddress(hexline); + len = GetLength(hexline); + GetData(hexline, len); + if (128 == PageMemIdx) { + if (!firstRun) { + loadAddress[1] += 0x40; + if (0 == loadAddress[1]) { + loadAddress[0] += 1; + } + } + firstRun = false; + FlashPageReady = true; + PageMemIdx = 0; + } + nextAddress = address + len; + } + if (1 == recordType) { + EndOfFile(); + FlashPageReady = true; + } +} + +bool ArduinoHexParse::IsFlashPageReady(void) +{ + return FlashPageReady; +} + +byte* ArduinoHexParse::GetFlashPage(void) +{ + FlashPageReady = false; + return FlashPage; +} + +byte* ArduinoHexParse::GetLoadAddress(void) +{ + return loadAddress; +} + +void ArduinoHexParse::GetLoadAddress(byte* hexline) +{ + char buff[3]; + buff[2] = '\0'; + buff[0] = hexline[3]; + buff[1] = hexline[4]; + loadAddress[0] = strtol(buff, 0, 16); + buff[0] = hexline[5]; + buff[1] = hexline[6]; + loadAddress[1] = strtol(buff, 0, 16); +} + +byte* ArduinoHexParse::GetData(byte* hexline, uint32_t len) +{ + uint32_t start = 9; + uint32_t end = (len * 2) + start; + char buff[3]; + buff[2] = '\0'; + for (uint32_t x = start; x < end; x = x+2) { + buff[0] = hexline[x]; + buff[1] = hexline[x+1]; + FlashPage[PageMemIdx] = strtol(buff, 0, 16); + PageMemIdx++; + } +} + +void ArduinoHexParse::EndOfFile(void) +{ + loadAddress[1] += 0x40; + if (0 == loadAddress[1]) { + loadAddress[0] += 1; + } + while (128 > PageMemIdx) { // Fill the remaing space in the memory page with 0xFF + FlashPage[PageMemIdx] = 0xFF; + PageMemIdx++; + } +} + +uint32_t ArduinoHexParse::GetAddress(byte* hexline) +{ + char buff[5]; + buff[0] = hexline[3]; + buff[1] = hexline[4]; + buff[2] = hexline[5]; + buff[3] = hexline[6]; + buff[4] = '\0'; + return strtol(buff, 0, 16); +} + +uint16_t ArduinoHexParse::GetLength(byte* hexline) +{ + char buff[3]; + buff[0] = hexline[1]; + buff[1] = hexline[2]; + buff[2] = '\0'; + return strtol(buff, 0, 16); +} + +uint16_t ArduinoHexParse::GetRecordType(byte* hexline) +{ + char buff[3]; + buff[0] = hexline[7]; + buff[1] = hexline[8]; + buff[2] = '\0'; + return strtol(buff, 0, 16); +} diff --git a/lib/ArduinoHexParse/src/ArduinoHexParse.h b/lib/ArduinoHexParse/src/ArduinoHexParse.h new file mode 100644 index 000000000..7b941eea1 --- /dev/null +++ b/lib/ArduinoHexParse/src/ArduinoHexParse.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2019 Andre Thomas 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 + 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 __ARDUINOHEXPARSE_H__ + +#include + +class ArduinoHexParse { + public: + ArduinoHexParse(void); + void ParseLine(byte* data); + byte* GetFlashPage(void); + byte* GetLoadAddress(void); + bool IsFlashPageReady(void); + private: + uint32_t address = 0; + uint32_t len = 0; + uint32_t nextAddress = 0; + uint32_t PageMemIdx = 0; + uint32_t recordType = 0; + byte FlashPage[128]; + byte loadAddress[2]; + bool FlashPageReady = false; + bool firstRun = true; + uint32_t GetAddress(byte* hexline); + uint16_t GetLength(byte* hexline); + uint16_t GetRecordType(byte* hexline); + byte* GetData(byte* hexline, uint32_t len); + void GetLoadAddress(byte* hexline); + void EndOfFile(void); +}; + +#endif // __ARDUINOHEXPARSE_H__ \ No newline at end of file From d84288b46e190b2e9f5c9798281ebb45d8b36c2f Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 20 Oct 2019 20:09:32 +0200 Subject: [PATCH 2197/2222] Update language files --- sonoff/language/bg-BG.h | 3 +++ sonoff/language/cs-CZ.h | 3 +++ sonoff/language/de-DE.h | 3 +++ sonoff/language/el-GR.h | 3 +++ sonoff/language/en-GB.h | 3 +++ sonoff/language/es-ES.h | 3 +++ sonoff/language/fr-FR.h | 3 +++ sonoff/language/he-HE.h | 3 +++ sonoff/language/hu-HU.h | 3 +++ sonoff/language/it-IT.h | 3 +++ sonoff/language/ko-KO.h | 3 +++ sonoff/language/nl-NL.h | 3 +++ sonoff/language/pl-PL.h | 3 +++ sonoff/language/pt-BR.h | 3 +++ sonoff/language/pt-PT.h | 3 +++ sonoff/language/ru-RU.h | 3 +++ sonoff/language/sk-SK.h | 3 +++ sonoff/language/sv-SE.h | 3 +++ sonoff/language/tr-TR.h | 3 +++ sonoff/language/uk-UK.h | 3 +++ sonoff/language/zh-CN.h | 3 +++ sonoff/language/zh-TW.h | 3 +++ 22 files changed, 66 insertions(+) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 47cc10d88..d765614f6 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index f21911772..fd654c148 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 93a44c9de..92e456f96 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 00d690e80..680633d6a 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 2402e8c01..74a2fdca0 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-ES.h b/sonoff/language/es-ES.h index 43c9b2fa9..2530fd6e4 100644 --- a/sonoff/language/es-ES.h +++ b/sonoff/language/es-ES.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index a33c48639..1522ec15f 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index d31069675..3e5fe4031 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index a5094fe44..f55f8ed38 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 6ac9a14d6..912e95ec1 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index ac1ae34ce..35ae260b6 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 5d0a6aacd..4091f9928 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index a167cfa7d..bd03d60e3 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index ae2349b8e..5d7b02613 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index fd769a2e4..bfa234599 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 3f61e323b..13b721092 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 573975948..d35fff407 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 190e9b956..701ed43ac 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 9189de9ee..295664ae0 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index f09e80497..8030b1f2a 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index fdc8e1277..36f71ea4c 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 85f68b991..53bd3e1a7 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -627,6 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_ARDUINO_TX "Arduino TX" +#define D_SENSOR_ARDUINO_RX "Arduino RX" +#define D_SENSOR_ARDUINO_RESET "Arduino RST" // Units #define D_UNIT_AMPERE "安" From f97d1a56ed97798cb7bf2a67103a67148c761c17 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 20 Oct 2019 20:10:14 +0200 Subject: [PATCH 2198/2222] Update my_user_config.h --- sonoff/my_user_config.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 33a3f9208..cbd0958f5 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -541,6 +541,11 @@ //#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) //#define USE_A4988_STEPPER // Add support for A4988/DRV8825 stepper-motor-driver-circuit (+10k5 code) +//#define USE_ARDUINO_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) +// #define USE_ARDUINO_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants +// #define USE_ARDUINO_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini +// #define USE_ARDUINO_INVERT_RESET + // -- End of general directives ------------------- /*********************************************************************************************\ From 3411ad655dcde62b23997caf270d7405c811369a Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 20 Oct 2019 20:11:07 +0200 Subject: [PATCH 2199/2222] Add ArduinoSlave --- sonoff/xdrv_01_webserver.ino | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 04af1906f..b1037bdfd 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -44,7 +44,7 @@ const uint16_t HTTP_REFRESH_TIME = 2345; // milliseconds uint8_t *efm8bb1_update = nullptr; #endif // USE_RF_FLASH -enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1 }; +enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_ARDUINOSLAVE }; static const char * HEADER_KEYS[] = { "User-Agent", }; @@ -2037,12 +2037,25 @@ void HandleUploadDone(void) WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "
"), WebColor(COL_TEXT_SUCCESS)); WSContentSend_P(HTTP_MSG_RSTRT); ShowWebSource(SRC_WEBGUI); +#ifdef USE_ARDUINO_SLAVE + if (ArduinoSlave_GetFlagFlashing()) { + restart_flag = 0; + } else { // It was a normal firmware file, or we are ready to restart device + restart_flag = 2; + } +#else restart_flag = 2; // Always restart to re-enable disabled features during update +#endif } SettingsBufferFree(); WSContentSend_P(PSTR("

")); WSContentSpaceButton(BUTTON_MAIN); WSContentStop(); +#ifdef USE_ARDUINO_SLAVE + if (ArduinoSlave_GetFlagFlashing()) { + ArduinoSlave_Flash(); + } +#endif } void HandleUploadLoop(void) @@ -2108,6 +2121,14 @@ void HandleUploadLoop(void) if (Web.upload_error != 0) { return; } } else #endif // USE_RF_FLASH +#ifdef USE_ARDUINO_SLAVE + if ((WEMOS == my_module_type) && (upload.buf[0] == ':')) { // Check if this is a ARDUINO SLAVE hex file + Update.end(); // End esp8266 update session + Web.upload_file_type = UPL_ARDUINOSLAVE; + Web.upload_error = ArduinoSlave_UpdateInit(); + if (Web.upload_error != 0) { return; } + } else +#endif { if (upload.buf[0] != 0xE9) { Web.upload_error = 3; // Magic byte is not 0xE9 @@ -2166,6 +2187,11 @@ void HandleUploadLoop(void) } } #endif // USE_RF_FLASH +#ifdef USE_ARDUINO_SLAVE + else if (UPL_ARDUINOSLAVE == Web.upload_file_type) { + ArduinoSlave_WriteBuffer(upload.buf, upload.currentSize); + } +#endif else { // firmware if (!Web.upload_error && (Update.write(upload.buf, upload.currentSize) != upload.currentSize)) { Web.upload_error = 5; // Upload buffer miscompare @@ -2217,6 +2243,13 @@ void HandleUploadLoop(void) Web.upload_file_type = UPL_TASMOTA; } #endif // USE_RF_FLASH +#ifdef USE_ARDUINO_SLAVE + else if (UPL_ARDUINOSLAVE == Web.upload_file_type) { + // Done writing the hex to SPI flash + ArduinoSlave_SetFlagFlashing(true); // So we know on upload success page if it needs to flash hex or do a normal restart + Web.upload_file_type = UPL_TASMOTA; + } +#endif else { if (!Update.end(true)) { // true to set the size to the current progress if (_serialoutput) { Update.printError(Serial); } From 711210c053aa01bae1e76581422de2ccf67bdde5 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 20 Oct 2019 20:12:05 +0200 Subject: [PATCH 2200/2222] Add ArduinoSlave as xdrv_31 --- sonoff/xdrv_31_arduino_slave.ino | 277 +++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 sonoff/xdrv_31_arduino_slave.ino diff --git a/sonoff/xdrv_31_arduino_slave.ino b/sonoff/xdrv_31_arduino_slave.ino new file mode 100644 index 000000000..09e434126 --- /dev/null +++ b/sonoff/xdrv_31_arduino_slave.ino @@ -0,0 +1,277 @@ +/* + xdrv_31_arduino_slave.ino - Support for Arduino Slave on Serial + + Copyright (C) 2019 Andre Thomas 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 + 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_ARDUINO_SLAVE + +#include +#include + +#define CONST_STK_CRC_EOP 0x20 + +#define CMND_STK_GET_SYNC 0x30 +#define CMND_STK_SET_DEVICE 0x42 +#define CMND_STK_SET_DEVICE_EXT 0x45 +#define CMND_STK_ENTER_PROGMODE 0x50 +#define CMND_STK_LEAVE_PROGMODE 0x51 +#define CMND_STK_LOAD_ADDRESS 0x55 +#define CMND_STK_PROG_PAGE 0x64 + +uint32_t as_spi_hex_size = 0; +uint8_t as_spi_sector_start = 0x96; +uint8_t as_spi_sector_counter = 0x96; +uint8_t as_spi_sector_cursor = 0; +bool as_flashing = false; + +uint8_t as_type = 0; + +TasmotaSerial *ArduinoSlave_Serial; + +#define XDRV_31 31 + +uint8_t ArduinoSlave_UpdateInit(void) +{ + as_spi_hex_size = 0; + as_spi_sector_counter = as_spi_sector_start; // Reset the pre-defined write address where firmware will temporarily be stored + as_spi_sector_cursor = 0; + return 0; +} + +void ArduinoSlave_Reset(void) +{ + if (as_type) { +#ifdef USE_ARDUINO_INVERT_RESET + digitalWrite(pin[GPIO_ARDUINO_RESET], LOW); + delay(1); + digitalWrite(pin[GPIO_ARDUINO_RESET], HIGH); + delay(1); + digitalWrite(pin[GPIO_ARDUINO_RESET], LOW); + delay(5); +#else + digitalWrite(pin[GPIO_ARDUINO_RESET], HIGH); + delay(1); + digitalWrite(pin[GPIO_ARDUINO_RESET], LOW); + delay(1); + digitalWrite(pin[GPIO_ARDUINO_RESET], HIGH); + delay(5); +#endif + } +} + +uint8_t ArduinoSlave_waitForSerialData(int dataCount, int timeout) { + int timer = 0; + while (timer < timeout) { + if (ArduinoSlave_Serial->available() >= dataCount) { + return 1; + } + delay(1); + timer++; + } + return 0; +} + +byte ArduinoSlave_sendBytes(byte* bytes, int count) { + ArduinoSlave_Serial->write(bytes, count); + ArduinoSlave_waitForSerialData(2, 1000); + byte sync = ArduinoSlave_Serial->read(); + byte ok = ArduinoSlave_Serial->read(); + if (sync == 0x14 && ok == 0x10) { + return 1; + } + return 0; +} + +byte ArduinoSlave_execCmd(byte cmd) { + byte bytes[] = { cmd, CONST_STK_CRC_EOP }; + return ArduinoSlave_sendBytes(bytes, 2); +} + +byte ArduinoSlave_execParam(byte cmd, byte* params, int count) { + byte bytes[32]; + bytes[0] = cmd; + int i = 0; + while (i < count) { + bytes[i + 1] = params[i]; + i++; + } + bytes[i + 1] = CONST_STK_CRC_EOP; + return ArduinoSlave_sendBytes(bytes, i + 2); +} + +uint8_t ArduinoSlave_exitProgMode(void) +{ + return ArduinoSlave_execCmd(CMND_STK_LEAVE_PROGMODE); // Exit programming mode +} + +void ArduinoSlave_SetupFlash(void) +{ + byte ProgParams[] = {0x86,0x00,0x00,0x01,0x01,0x01,0x01,0x03,0xff,0xff,0xff,0xff,0x00,0x80,0x04,0x00,0x00,0x00,0x80,0x00}; + byte ExtProgParams[] = {0x05,0x04,0xd7,0xc2,0x00}; + ArduinoSlave_Serial->begin(USE_ARDUINO_FLASH_SPEED); + if (ArduinoSlave_Serial->hardwareSerial()) { + ClaimSerial(); + } + ArduinoSlave_Reset(); + ArduinoSlave_execCmd(CMND_STK_GET_SYNC); + ArduinoSlave_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams)); // Set programming parameters + ArduinoSlave_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams)); // Set extended programming parameters + ArduinoSlave_execCmd(CMND_STK_ENTER_PROGMODE); // Enter programming mode +} + +uint8_t ArduinoSlave_loadAddress(byte adrHi, byte adrLo) { + byte params[] = { adrHi, adrLo }; + return ArduinoSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params)); +} + +void ArduinoSlave_FlashPage(byte* address, byte* data) +{ + byte Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46}; + ArduinoSlave_loadAddress(address[1], address[0]); + ArduinoSlave_Serial->write(Header, 4); + for (int i = 0; i < 128; i++) { + ArduinoSlave_Serial->write(data[i]); + } + ArduinoSlave_Serial->write(CONST_STK_CRC_EOP); + ArduinoSlave_waitForSerialData(2, 1000); + ArduinoSlave_Serial->read(); + ArduinoSlave_Serial->read(); +} + +void ArduinoSlave_Flash(void) +{ + bool reading = true; + uint32_t read = 0; + uint32_t processed = 0; + char thishexline[50]; + uint8_t position = 0; + char* flash_buffer; + ArduinoHexParse hexParse = ArduinoHexParse(); + + ArduinoSlave_SetupFlash(); + + flash_buffer = new char[SPI_FLASH_SEC_SIZE]; + while (reading) { + ESP.flashRead(0x96000 + read, (uint32_t*)flash_buffer, FLASH_SECTOR_SIZE); + read = read + FLASH_SECTOR_SIZE; + if (read >= as_spi_hex_size) { + reading = false; + } + for (uint16_t ca=0; cabegin(USE_ARDUINO_SERIAL_SPEED)) { + if (ArduinoSlave_Serial->hardwareSerial()) { + ClaimSerial(); + } + pinMode(pin[GPIO_ARDUINO_RESET], OUTPUT); + as_type = 1; + ArduinoSlave_Reset(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("Arduino Slave Enabled")); + } + } +} + +void ArduinoSlave_Show(bool json) +{ + if (as_type) { + char buffer[100]; + ArduinoSlave_Serial->flush(); + ArduinoSlave_Serial->print("JSON"); + ArduinoSlave_Serial->find(char(0xFE)); + uint16_t haveread = ArduinoSlave_Serial->readBytesUntil(char(0xFF), buffer, sizeof(buffer)-1); + buffer[haveread] = '\0'; + if (json) { + ResponseAppend_P(PSTR(",\"ArduinoSlave\":%s"), buffer); + } + } +} + +bool Xdrv31(uint8_t function) +{ + bool result = false; + switch (function) { + case FUNC_EVERY_SECOND: + ArduinoSlave_Init(); + break; + case FUNC_JSON_APPEND: + ArduinoSlave_Show(1); + break; + case FUNC_COMMAND_DRIVER: + break; + default: + break; + } +} + +#endif // USE_ARDUINO_SLAVE \ No newline at end of file From 9ba9a25dc6a8554051283eef72f81699126803a1 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 20 Oct 2019 20:12:55 +0200 Subject: [PATCH 2201/2222] Add ArduinoSlave to sonoff_template.h --- sonoff/sonoff_template.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index c6ed5b3e2..01fc75129 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -208,6 +208,9 @@ enum UserSelectablePins { GPIO_SM2135_DAT, // SM2135 Dat GPIO_DEEPSLEEP, // Kill switch for deepsleep GPIO_EXS_ENABLE, // EXS MCU Enable + GPIO_ARDUINO_TXD, // Arduino Slave TX + GPIO_ARDUINO_RXD, // Arduino Slave RX + GPIO_ARDUINO_RESET, // Arduino Reset Pin GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -286,6 +289,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|" D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|" D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|" + D_SENSOR_ARDUINO_TX "|" D_SENSOR_ARDUINO_RX "|" D_SENSOR_ARDUINO_RESET "|" ; const char kSensorNamesFixed[] PROGMEM = @@ -698,6 +702,11 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_PN532_TXD, // PN532 HSU Tx GPIO_PN532_RXD, // PN532 HSU Rx #endif +#ifdef USE_ARDUINO_SLAVE + GPIO_ARDUINO_TXD, // Arduino Slave TX + GPIO_ARDUINO_RXD, // Arduino Slave RX + GPIO_ARDUINO_RESET, // Arduino Reset Pin +#endif #ifdef USE_RDM6300 GPIO_RDM6300_RX, #endif From 1d5920d1c8e719d034fc235f616ab51a26062046 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Sun, 20 Oct 2019 20:14:17 +0200 Subject: [PATCH 2202/2222] Add ArduinoSlave Driver --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 479f295aa..65820ecdf 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -4,6 +4,7 @@ * Add absolute PowerDelta using command PowerDelta 101..32000 where 101 = 101-100 = 1W, 202 = 202-100 = 102W (#5901) * Add support for EX-Store WiFi Dimmer V4 (#5856) * Add ZigbeeRead command and many improvements (#6095) + * Add ArduinoSlave driver (EXPERIMENTAL) * * 6.6.0.19 20191018 * Replace obsolete xsns_23_sdm120 with xnrg_08_sdm120 and consolidate define USE_SDM120 From 4c973772630bfa999799f595dc157caf0b7ad790 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 20 Oct 2019 20:52:44 +0200 Subject: [PATCH 2203/2222] Fix Revert key as shortaddr for ZigbeeReveived --- sonoff/xdrv_23_zigbee_8_parsers.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_23_zigbee_8_parsers.ino b/sonoff/xdrv_23_zigbee_8_parsers.ino index 495ce61ab..286596e33 100644 --- a/sonoff/xdrv_23_zigbee_8_parsers.ino +++ b/sonoff/xdrv_23_zigbee_8_parsers.ino @@ -385,8 +385,9 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { DynamicJsonBuffer jsonBuffer; JsonObject& json_root = jsonBuffer.createObject(); - JsonObject& json = json_root.createNestedObject(F(D_CMND_ZIGBEE_RECEIVED)); - json[F(D_JSON_ZIGBEE_DEVICE)] = shortaddr; + JsonObject& json1 = json_root.createNestedObject(F(D_CMND_ZIGBEE_RECEIVED)); + JsonObject& json = json1.createNestedObject(shortaddr); + // TODO add name field if it is known if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { zcl_received.parseRawAttributes(json); From 4861e53330a01c7fedbd3dfe9ee33a75b844e7c4 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sun, 20 Oct 2019 23:02:51 -0300 Subject: [PATCH 2204/2222] Fix issue if STARTING_OFFSET is undefined If STARTING_OFFSET is undefined in my_user_config.h file, the compilation fails due to this parameter is used in the defaults of settings.ino --- sonoff/sonoff_post.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 8e0e95cf4..7cb08a27a 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -708,6 +708,10 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define SWITCH_MODE TOGGLE // TOGGLE, FOLLOW or FOLLOW_INV (the wall switch state) #endif +#ifndef STARTING_OFFSET // NOVA SDS parameter used in settings +#define STARTING_OFFSET 30 +#endif + #ifndef MQTT_FINGERPRINT1 // Set an all-zeros default fingerprint to activate auto-learning on first connection (AWS IoT) #define MQTT_FINGERPRINT1 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" From 4d21a47edbd5b7d1ea20437d60a1df01b7e4642a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 21 Oct 2019 10:27:36 +0200 Subject: [PATCH 2205/2222] Update PZEM comments Update PZEM comments --- sonoff/xnrg_03_pzem004t.ino | 4 ++-- sonoff/xnrg_05_pzem_ac.ino | 7 ++++--- sonoff/xnrg_06_pzem_dc.ino | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index 1a541b8f8..93657ae01 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -20,12 +20,12 @@ #ifdef USE_ENERGY_SENSOR #ifdef USE_PZEM004T /*********************************************************************************************\ - * PZEM004T - Energy + * PZEM-004T V1 and V2 - Energy * * Source: Victor Ferrer https://github.com/vicfergar/Sonoff-MQTT-OTA-Arduino * Based on: PZEM004T library https://github.com/olehs/PZEM004T * - * Hardware Serial will be selected if GPIO1 = [63 PZEM004 Rx] and GPIO3 = [62 PZEM0XX Tx] + * Hardware Serial will be selected if GPIO1 = [62 PZEM0XX Tx] and GPIO3 = [63 PZEM004 Rx] \*********************************************************************************************/ #define XNRG_03 3 diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index b438138bd..3758e68a3 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -20,13 +20,14 @@ #ifdef USE_ENERGY_SENSOR #ifdef USE_PZEM_AC /*********************************************************************************************\ - * PZEM-014 - AC 220V 10A Energy - * PZEM-016 - AC 220V 100A Energy + * PZEM-004T V3 - AC 220V 10/100A Energy + * PZEM-014 - AC 220V 10A Energy + * PZEM-016 - AC 220V 100A Energy * * Based on: * PZEM-014,016 docs https://pan.baidu.com/s/1B0MdMgURyjtO1oQa2lavKw password ytkv * - * Hardware Serial will be selected if GPIO1 = [98 PZEM016 Rx] and GPIO3 = [62 PZEM0XX Tx] + * Hardware Serial will be selected if GPIO1 = [62 PZEM0XX Tx] and GPIO3 = [98 PZEM016 Rx] \*********************************************************************************************/ #define XNRG_05 5 diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index 29687967a..2e85ac945 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -26,7 +26,7 @@ * Based on: * PZEM-003,017 docs Https://pan.baidu.com/s/1V9bDWj3RK2u6_fbBJ3GtqQ password rq37 * - * Hardware Serial will be selected if GPIO1 = [99 PZEM017 Rx] and GPIO3 = [62 PZEM0XX Tx] + * Hardware Serial will be selected if GPIO1 = [62 PZEM0XX Tx] and GPIO3 = [99 PZEM017 Rx] \*********************************************************************************************/ #define XNRG_06 6 From aaf6f90507994fc38b0e70a655daf017706f498a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 21 Oct 2019 12:25:22 +0200 Subject: [PATCH 2206/2222] Refactor Arduino Slave --- sonoff/my_user_config.h | 5 +- sonoff/sonoff_template.h | 8 +- sonoff/xdrv_31_arduino_slave.ino | 156 +++++++++++++++++-------------- 3 files changed, 92 insertions(+), 77 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index cbd0958f5..4c41c48d8 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -542,9 +542,8 @@ //#define USE_A4988_STEPPER // Add support for A4988/DRV8825 stepper-motor-driver-circuit (+10k5 code) //#define USE_ARDUINO_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) -// #define USE_ARDUINO_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants -// #define USE_ARDUINO_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini -// #define USE_ARDUINO_INVERT_RESET + #define USE_ARDUINO_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants + #define USE_ARDUINO_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini // -- End of general directives ------------------- diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 01fc75129..f85543cd0 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -210,7 +210,8 @@ enum UserSelectablePins { GPIO_EXS_ENABLE, // EXS MCU Enable GPIO_ARDUINO_TXD, // Arduino Slave TX GPIO_ARDUINO_RXD, // Arduino Slave RX - GPIO_ARDUINO_RESET, // Arduino Reset Pin + GPIO_ARDUINO_RST, // Arduino Reset Pin + GPIO_ARDUINO_RST_INV, // Arduino Reset Pin inverted GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -289,7 +290,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|" D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|" D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|" - D_SENSOR_ARDUINO_TX "|" D_SENSOR_ARDUINO_RX "|" D_SENSOR_ARDUINO_RESET "|" + D_SENSOR_ARDUINO_TX "|" D_SENSOR_ARDUINO_RX "|" D_SENSOR_ARDUINO_RESET "|" D_SENSOR_ARDUINO_RESET "i|" ; const char kSensorNamesFixed[] PROGMEM = @@ -705,7 +706,8 @@ const uint8_t kGpioNiceList[] PROGMEM = { #ifdef USE_ARDUINO_SLAVE GPIO_ARDUINO_TXD, // Arduino Slave TX GPIO_ARDUINO_RXD, // Arduino Slave RX - GPIO_ARDUINO_RESET, // Arduino Reset Pin + GPIO_ARDUINO_RST, // Arduino Reset Pin + GPIO_ARDUINO_RST_INV, // Arduino Reset Pin inverted #endif #ifdef USE_RDM6300 GPIO_RDM6300_RX, diff --git a/sonoff/xdrv_31_arduino_slave.ino b/sonoff/xdrv_31_arduino_slave.ino index 09e434126..497ab28dd 100644 --- a/sonoff/xdrv_31_arduino_slave.ino +++ b/sonoff/xdrv_31_arduino_slave.ino @@ -18,9 +18,11 @@ */ #ifdef USE_ARDUINO_SLAVE +/*********************************************************************************************\ + * Arduino slave +\*********************************************************************************************/ -#include -#include +#define XDRV_31 31 #define CONST_STK_CRC_EOP 0x20 @@ -32,48 +34,47 @@ #define CMND_STK_LOAD_ADDRESS 0x55 #define CMND_STK_PROG_PAGE 0x64 -uint32_t as_spi_hex_size = 0; -uint8_t as_spi_sector_start = 0x96; -uint8_t as_spi_sector_counter = 0x96; -uint8_t as_spi_sector_cursor = 0; -bool as_flashing = false; +#include +#include -uint8_t as_type = 0; +struct ASLAVE { + uint32_t spi_hex_size = 0; + uint32_t spi_sector_counter = 0; + uint8_t spi_sector_cursor = 0; + uint8_t inverted = LOW; + bool type = false; + bool flashing = false; +} ASlave; TasmotaSerial *ArduinoSlave_Serial; -#define XDRV_31 31 +uint32_t ArduinoSlaveFlashStart(void) +{ + return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side +} uint8_t ArduinoSlave_UpdateInit(void) { - as_spi_hex_size = 0; - as_spi_sector_counter = as_spi_sector_start; // Reset the pre-defined write address where firmware will temporarily be stored - as_spi_sector_cursor = 0; + ASlave.spi_hex_size = 0; + ASlave.spi_sector_counter = ArduinoSlaveFlashStart(); // Reset the pre-defined write address where firmware will temporarily be stored + ASlave.spi_sector_cursor = 0; return 0; } void ArduinoSlave_Reset(void) { - if (as_type) { -#ifdef USE_ARDUINO_INVERT_RESET - digitalWrite(pin[GPIO_ARDUINO_RESET], LOW); + if (ASlave.type) { + digitalWrite(pin[GPIO_ARDUINO_RST], !ASlave.inverted); delay(1); - digitalWrite(pin[GPIO_ARDUINO_RESET], HIGH); + digitalWrite(pin[GPIO_ARDUINO_RST], ASlave.inverted); delay(1); - digitalWrite(pin[GPIO_ARDUINO_RESET], LOW); + digitalWrite(pin[GPIO_ARDUINO_RST], !ASlave.inverted); delay(5); -#else - digitalWrite(pin[GPIO_ARDUINO_RESET], HIGH); - delay(1); - digitalWrite(pin[GPIO_ARDUINO_RESET], LOW); - delay(1); - digitalWrite(pin[GPIO_ARDUINO_RESET], HIGH); - delay(5); -#endif } } -uint8_t ArduinoSlave_waitForSerialData(int dataCount, int timeout) { +uint8_t ArduinoSlave_waitForSerialData(int dataCount, int timeout) +{ int timer = 0; while (timer < timeout) { if (ArduinoSlave_Serial->available() >= dataCount) { @@ -85,24 +86,27 @@ uint8_t ArduinoSlave_waitForSerialData(int dataCount, int timeout) { return 0; } -byte ArduinoSlave_sendBytes(byte* bytes, int count) { +uint8_t ArduinoSlave_sendBytes(uint8_t* bytes, int count) +{ ArduinoSlave_Serial->write(bytes, count); ArduinoSlave_waitForSerialData(2, 1000); - byte sync = ArduinoSlave_Serial->read(); - byte ok = ArduinoSlave_Serial->read(); + uint8_t sync = ArduinoSlave_Serial->read(); + uint8_t ok = ArduinoSlave_Serial->read(); if (sync == 0x14 && ok == 0x10) { return 1; } return 0; } -byte ArduinoSlave_execCmd(byte cmd) { - byte bytes[] = { cmd, CONST_STK_CRC_EOP }; +uint8_t ArduinoSlave_execCmd(uint8_t cmd) +{ + uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP }; return ArduinoSlave_sendBytes(bytes, 2); } -byte ArduinoSlave_execParam(byte cmd, byte* params, int count) { - byte bytes[32]; +uint8_t ArduinoSlave_execParam(uint8_t cmd, uint8_t* params, int count) +{ + uint8_t bytes[32]; bytes[0] = cmd; int i = 0; while (i < count) { @@ -120,10 +124,10 @@ uint8_t ArduinoSlave_exitProgMode(void) void ArduinoSlave_SetupFlash(void) { - byte ProgParams[] = {0x86,0x00,0x00,0x01,0x01,0x01,0x01,0x03,0xff,0xff,0xff,0xff,0x00,0x80,0x04,0x00,0x00,0x00,0x80,0x00}; - byte ExtProgParams[] = {0x05,0x04,0xd7,0xc2,0x00}; + uint8_t ProgParams[] = {0x86,0x00,0x00,0x01,0x01,0x01,0x01,0x03,0xff,0xff,0xff,0xff,0x00,0x80,0x04,0x00,0x00,0x00,0x80,0x00}; + uint8_t ExtProgParams[] = {0x05,0x04,0xd7,0xc2,0x00}; ArduinoSlave_Serial->begin(USE_ARDUINO_FLASH_SPEED); - if (ArduinoSlave_Serial->hardwareSerial()) { + if (ArduinoSlave_Serial->hardwareSerial()) { ClaimSerial(); } ArduinoSlave_Reset(); @@ -133,14 +137,15 @@ void ArduinoSlave_SetupFlash(void) ArduinoSlave_execCmd(CMND_STK_ENTER_PROGMODE); // Enter programming mode } -uint8_t ArduinoSlave_loadAddress(byte adrHi, byte adrLo) { - byte params[] = { adrHi, adrLo }; +uint8_t ArduinoSlave_loadAddress(uint8_t adrHi, uint8_t adrLo) +{ + uint8_t params[] = { adrHi, adrLo }; return ArduinoSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params)); } -void ArduinoSlave_FlashPage(byte* address, byte* data) +void ArduinoSlave_FlashPage(uint8_t* address, uint8_t* data) { - byte Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46}; + uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46}; ArduinoSlave_loadAddress(address[1], address[0]); ArduinoSlave_Serial->write(Header, 4); for (int i = 0; i < 128; i++) { @@ -165,24 +170,25 @@ void ArduinoSlave_Flash(void) ArduinoSlave_SetupFlash(); flash_buffer = new char[SPI_FLASH_SEC_SIZE]; + uint32_t flash_start = ArduinoSlaveFlashStart() * SPI_FLASH_SEC_SIZE; while (reading) { - ESP.flashRead(0x96000 + read, (uint32_t*)flash_buffer, FLASH_SECTOR_SIZE); - read = read + FLASH_SECTOR_SIZE; - if (read >= as_spi_hex_size) { + ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE); + read = read + SPI_FLASH_SEC_SIZE; + if (read >= ASlave.spi_hex_size) { reading = false; } - for (uint16_t ca=0; cabegin(USE_ARDUINO_SERIAL_SPEED)) { - if (ArduinoSlave_Serial->hardwareSerial()) { + if (ArduinoSlave_Serial->hardwareSerial()) { ClaimSerial(); } - pinMode(pin[GPIO_ARDUINO_RESET], OUTPUT); - as_type = 1; + if (pin[GPIO_ARDUINO_RST_INV] < 99) { + pin[GPIO_ARDUINO_RST] = pin[GPIO_ARDUINO_RST_INV]; + pin[GPIO_ARDUINO_RST_INV] = 99; + ASlave.inverted = HIGH; + } + pinMode(pin[GPIO_ARDUINO_RST], OUTPUT); + ASlave.type = true; ArduinoSlave_Reset(); AddLog_P2(LOG_LEVEL_INFO, PSTR("Arduino Slave Enabled")); } @@ -244,11 +256,11 @@ void ArduinoSlave_Init(void) void ArduinoSlave_Show(bool json) { - if (as_type) { - char buffer[100]; + if (ASlave.type) { ArduinoSlave_Serial->flush(); ArduinoSlave_Serial->print("JSON"); ArduinoSlave_Serial->find(char(0xFE)); + char buffer[100]; uint16_t haveread = ArduinoSlave_Serial->readBytesUntil(char(0xFF), buffer, sizeof(buffer)-1); buffer[haveread] = '\0'; if (json) { @@ -257,9 +269,14 @@ void ArduinoSlave_Show(bool json) } } +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + bool Xdrv31(uint8_t function) { bool result = false; + switch (function) { case FUNC_EVERY_SECOND: ArduinoSlave_Init(); @@ -267,11 +284,8 @@ bool Xdrv31(uint8_t function) case FUNC_JSON_APPEND: ArduinoSlave_Show(1); break; - case FUNC_COMMAND_DRIVER: - break; - default: - break; } + return result; } -#endif // USE_ARDUINO_SLAVE \ No newline at end of file +#endif // USE_ARDUINO_SLAVE \ No newline at end of file From 1110bac41008ba9723e99e233496165b7205d8e8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 21 Oct 2019 12:36:08 +0200 Subject: [PATCH 2207/2222] Houskeeping Arduino Slave --- sonoff/support_features.ino | 5 +++-- tools/decode-status.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index a159377d8..5aa59f592 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -477,8 +477,9 @@ void GetFeatures(void) #ifdef USE_EXS_DIMMER feature5 |= 0x00008000; // xdrv_30_exs_dimmer.ino #endif - -// feature5 |= 0x00010000; +#ifdef USE_ARDUINO_SLAVE + feature5 |= 0x00010000; // xdrv_31_arduino_slave.ino +#endif // feature5 |= 0x00020000; // feature5 |= 0x00040000; // feature5 |= 0x00080000; diff --git a/tools/decode-status.py b/tools/decode-status.py index 7b8bce742..1497f35e2 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -173,7 +173,7 @@ a_features = [[ "USE_INA226","USE_A4988_STEPPER","USE_DDS2382","USE_SM2135", "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","USE_EXS_DIMMER", - "","","","", + "USE_ARDUINO_SLAVE","","","", "","","","", "","","","", "","","","" From f017c7b6c53d32b8aa858c07d2e0fdf312fc9f90 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 21 Oct 2019 14:02:17 +0200 Subject: [PATCH 2208/2222] Add Arduino Slave --- RELEASENOTES.md | 3 +++ sonoff/sonoff_post.h | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6a4c3429e..3f99c2e7b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -144,6 +144,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_EXPRESSION | - | - | - | - | - | - | - | - | | SUPPORT_IF_STATEMENT | - | - | - | - | - | - | - | - | | | | | | | | | | | +| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | ir | display | Remarks | ROTARY_V1 | - | - | - | - | - | - | - | - | | USE_SONOFF_RF | - | - | - | x | x | x | - | - | | USE_RF_FLASH | - | - | - | x | x | x | - | - | @@ -245,7 +246,9 @@ The following binary downloads have been compiled with ESP8266/Arduino library c | USE_RF_SENSOR | - | - | - | - | - | x | - | - | AlectoV2 only | USE_HRE | - | - | - | - | - | x | - | - | | USE_A4988_STEPPER | - | - | - | - | - | - | - | - | +| USE_ARDUINO_SLAVE | - | - | - | - | - | - | - | - | | | | | | | | | | | +| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | ir | display | Remarks | USE_DISPLAY | - | - | - | - | - | - | - | x | | USE_DISPLAY_LCD | - | - | - | - | - | - | - | x | | USE_DISPLAY_SSD1306 | - | - | - | - | - | - | - | x | diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 7cb08a27a..6e2bd7390 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -212,6 +212,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code) #define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) //#define USE_A4988_STEPPER // Add support for A4988/DRV8825 stepper-motor-driver-circuit (+10k5 code) +//#define USE_ARDUINO_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_SENSORS @@ -313,6 +314,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) #undef USE_A4988_STEPPER // Disable support for A4988_Stepper +#undef USE_ARDUINO_SLAVE // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_CLASSIC @@ -486,6 +488,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) #undef USE_A4988_STEPPER // Disable support for A4988_Stepper +#undef USE_ARDUINO_SLAVE // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_IR @@ -589,6 +592,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) #undef USE_A4988_STEPPER // Disable support for A4988_Stepper +#undef USE_ARDUINO_SLAVE // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_BASIC @@ -688,6 +692,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) #undef USE_A4988_STEPPER // Disable support for A4988_Stepper +#undef USE_ARDUINO_SLAVE // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_MINIMAL From 9238d4237d7ecc5d3444a07d1ac4c5bc3295daaf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 21 Oct 2019 18:21:35 +0200 Subject: [PATCH 2209/2222] Add templates cheat sheet Add templates cheat sheet --- TEMPLATE.md | 89 --------------- TEMPLATES.md | 301 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 301 insertions(+), 89 deletions(-) delete mode 100644 TEMPLATE.md create mode 100644 TEMPLATES.md diff --git a/TEMPLATE.md b/TEMPLATE.md deleted file mode 100644 index 33465a0e9..000000000 --- a/TEMPLATE.md +++ /dev/null @@ -1,89 +0,0 @@ -Logo - -# Template information - -Sonoff-Tasmota uses Device or Module information to control peripherals connected to GPIOs. This information is stored in the ``sonoff_template.h`` file as a device specific template. The template contains information about what GPIO should be connected to what peripheral and what GPIO may be configured online using the ``GPIO`` command or GUI Configure Module menu. In addition a device may need specific coding to process the data from these peripherals. The module number as provided by the ``Modules`` command is used to select this coding. - -Starting with version 6.4.1.16 Sonoff-Tasmota Modules can be extended by users online using a template. To provide easy processing by Sonoff-Tasmota a user template is written as JSON text and could look like this: - -{"NAME":"UserModule1","GPIO":[17,148,29,149,7,255,255,255,138,255,139,255,255],"FLAG":0,"BASE":18} - -The four properties with UPPERCASE property names have the following functionality: - -Property name | Property value description ---------------|------------------------------------------------------------------------------------------------------------------- -NAME | Up to 14 characters for the Module name -GPIO | Up to 13 decimal numbers from 0 to 255 representing GPIO0 to GPIO5, GPIO09, GPIO10 and GPIO12 to GPIO16 -FLAG | 8 bit mask flag register -BASE | Module number of a hard-coded device to be used when device specific functionality is needed - -The above example, based on the Generic Module does not allow ADC0 input. - -## GPIO functionality -The GPIO functionality numbers are the same is shown by command ``GPIOs``. In addition code 255 is added to select a GPIO as user configurable via the GUI Configure Module menu. - -## FLAG functionality -The FLAG value is an 8-bit mask where each bit controls a features. Add FLAG values to set multiple bits. - -FLAG | Mask | Feature description ------|----------|------------------------------ - 1 | xxxxxxx1 | Allowing to use Analog0 (ADC0) as input if define USE_ADC_VCC in ``my_user_config.h`` is disabled - 2 | xxxxxx1x | Enable GUI pull-up control message - 4 | xxxxx1xx | Not used - 8 | xxxx1xxx | Not used - 16 | xxx1xxxx | Not used - 32 | xx1xxxxx | Not used - 64 | x1xxxxxx | Not used - 128 | 1xxxxxxx | Not used - -## BASE functionality -The following table lists hard-coded device specific functionality. Notice that not all device modules need special handling. - -BASE | Module | Description ------|----------------|---------------------------------------------- - 4 | Sonoff Dual | Process relay and button via hardware serial interface using GPIO01 and GPIO03. Change baudrate to 19200 bps. Process buttons as single press only - 9 | Sonoff Touch | Invert ledstate 1 functionality - 10 | Sonoff LED | Set light type to 2 PWM channels disregarding SetOption15. Fix device specific LED instabilities by disabling GPIO04, GPIO5 and GPIO14 - 12 | 4 Channel | See 4 - 13 | Motor C/AC | Force all relays ON at Power On and disable command ``PowerOnState`` - 15 | EXS Relay(s) | Enable pulse latching using even/odd numbered relay pairs - 18 | Generic | Show Wemos specific pin information in GUI - 19 | H801 | Change hardware UART Tx from GPIO01 to GPIO02 - 20 | Sonoff SC | Enable and Process data via hardware serial interface using GPIO01 and GPIO03. Change baudrate to 19200 bps - 21 | Sonoff BN-SZ | Set light type to 1 PWM channel disregarding SetOption15 - 22 | Sonoff 4CH Pro | Button handling disregarding SetOption13 only allowing single press to enable RF learning while holding the button - 24 | Sonoff Bridge | Enable and Process data via hardware serial interface using GPIO01 and GPIO03. Change baudrate to 19200 bps. Process 16 buttons in web GUI. Enable EFM8BB1 firmware upload - 25 | Sonoff B1 | Set light type to RGBWC using MY92x1 - 26 | AiLight | Set light type to RGBW using MY92x1 - 27 | Sonoff T1 1CH | See 9 - 28 | Sonoff T1 2CH | See 9 - 29 | Sonoff T1 3CH | See 9 - 38 | Sonoff Dual R2 | Process buttons as single press only - 43 | Sonoff iFan02 | Enable command ``Fanspeed``. Disable Interlock and PulseTime. Tune status information, MQTT data and GUI. Sync with microcontroller. Process Domoticz Fan state - 47 | Xiaomi Philips | Process Color Temperature using PWM2 and Intensity using PWM1 - 53 | Tuya Dimmer | Enable and Process data via software or hardware serial interface using GPIO 148 and 149 or forced GPIO01 and GPIO03. Change baudrate to 9600 bps. Process all Buttons - 55 | ARMTR Dimmer | Enable and Process data via software or hardware serial interface using GPIO 148 and 149. Change baudrate to 115200 bps. - 57 | PS-16-DZ | Enable and Process data via software or hardware serial interface using GPIO 148 and 149. Change baudrate to 19200 bps. - 61 | YTF IR Bridge | Disable serial interface to stop loopback - 65 | Mi Desk Lamp | Process rotary and Button1 data specific to this device - -## Usage -A user provided template can be stored in Sonoff-Tasmota using the ``Template`` command. It has the following options. - -Command | Payload | Description ----------|----------|--------------------------------------- -Template | | Show current user template -Template | 0 | Copy active module template to user template -Template | 1 .. 69 | Copy hard-coded module template to user template - -The following command will store a complete template based on the Generic module -``Template {"NAME":"UserModule1","GPIO":[17,148,29,149,7,255,255,255,138,255,139,255,255],"FLAG":0,"BASE":18}`` - -The following command will update the name of a stored template -``Template {"NAME":"UserModule2"}`` - -The following command will update the flag of a stored template -``Template {"FLAG":1}`` - -The following command will update the base of a stored template to Generic -``Template {"BASE":0}`` diff --git a/TEMPLATES.md b/TEMPLATES.md new file mode 100644 index 000000000..bc8eb9f65 --- /dev/null +++ b/TEMPLATES.md @@ -0,0 +1,301 @@ +Logo + +# Templates + +Find below a selection of available templates as of October, 21 2019. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) + +Note that currently only devices A to L have been documented. Work in Progress. + +## Bulb +``` +A19 RGBW 8W E26 {"NAME":"OOOLED 60W RGB","GPIO":[0,0,0,0,39,40,0,0,37,0,38,0,0],"FLAG":1,"BASE":18} +Aisirer 9W A19 E26 {"NAME":"AISIRER E26","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":15,"BASE":18} +Anoopsyche CW/WW 60W {"NAME":"Anoop-CW-WW","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} +Aoycocr A19 {"NAME":"AoycocrA19","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":15,"BASE":18} +Arlec GLD112HA {"NAME":"Arlec CCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} +Ausein E14 7W White {"NAME":"Tuya RGBW","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Avatar 5W E14 {"NAME":"AVATAR","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +BNeta A60 E27 {"NAME":"OM60/RGBW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +BNeta GU10 RGB {"NAME":"BNeta","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Bomcosy 7W E27 RGB CW {"NAME":"Generic","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":1,"BASE":18} +Brilliant 20741 {"NAME":"Brilliant RGB+","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Brilliant HK17653S72 {"NAME":"Brilliant E14 ","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":15,"BASE":18} +DGM L-WT9W1 {"NAME":"DGM L-WT9W1","GPIO":[0,0,0,0,140,142,0,0,38,37,141,0,0],"FLAG":0,"BASE":18} +electriQ RGBW B22 {"NAME":"ElectricQ B22","GPIO":[0,0,0,0,37,41,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} +EleLight 7W A19 E27 RGBW {"NAME":"EleLight 7wA19","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":0,"BASE":18} +Esicoo 9W E26 {"NAME":"Esicoo Bulb","GPIO":[0,0,0,0,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} +Fcmila 7W RGBW E27 {"NAME":"FCMILA 7W","GPIO":[0,0,0,0,39,40,0,0,37,0,38,0,0],"FLAG":0,"BASE":18} +Fcmila EQ723 {"NAME":"FCMILA LED E27","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Fcmila FC-12W {"NAME":"SYF05","GPIO":[255,0,255,0,140,37,0,0,255,255,141,0,255],"FLAG":1,"BASE":69} +Feit Electric BPA800/RGBW/AG/2 {"NAME":"BPA800/RGBW","GPIO":[0,0,0,0,37,38,0,0,141,142,140,0,0],"FLAG":0,"BASE":48} +Feit Electric BR30/927CA/AG {"NAME":"Feit BR30 WW","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Feit Electric BR30/950CA/AG {"NAME":"Feit BR30 CW","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Feit Electric OM60/RGBW/CA/AG {"NAME":"OM60/RGBW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Feit Electric OM60/927CA/AG {"NAME":"Feit P_A800_2","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Geeni Lux A21 White {"NAME":"Geeni-1050-WW","GPIO":[0,0,0,0,37,37,0,0,38,0,0,0,0],"FLAG":1,"BASE":18} +Generic 10W E26/E27 RGBW {"NAME":"10W E27 RGBW","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} +Globe RGBW {"NAME":"GlobeRGBWW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Globe CW/WW {"NAME":"Globe CW/WW","GPIO":[0,0,0,0,38,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Gosund E27 8W RGBW {"NAME":"Gosund RGB+W","GPIO":[0,0,0,0,40,0,0,0,37,38,39,0,0],"FLAG":0,"BASE":18} +Jomarto 9W B22 {"NAME":"Jomarto Wifi S","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":1,"BASE":18} +Kainsy 7W E27 RGBW {"NAME":"KAINSY","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} +Kogan SmarterHome White 10W B22 {"NAME":"Kogan White/Wa","GPIO":[0,0,0,0,37,40,0,0,41,38,39,0,0],"FLAG":0,"BASE":18} +Kohree A19 7W {"NAME":"Kohree VHP560","GPIO":[0,0,0,0,37,41,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} +LE A19 RGBCT 9W E26 {"NAME":"LE RGBWW 60W","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":1,"BASE":18} +Legelite E26 {"NAME":"Legelite E26","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Linganzh LWE3 6W RGBW {"NAME":"Linganzh LWE3 ","GPIO":[0,0,0,0,0,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} +Lohas 5W E12 {"NAME":"LH-5W-ZN01204","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Lohas 9W E26 RGBW {"NAME":"Lohas RGBW","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":18} +Lohas E14 R50 {"NAME":"Lohas E14 R50","GPIO":[17,255,255,255,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Lohas ZN031 {"NAME":"Lohas ZN031","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Lohas A19 RGBW E12 {"NAME":"Lohas","GPIO":[17,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":1,"BASE":26} +LSC Filament CW {"NAME":"LSC Filament","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +LSC RGBCW E14 {"NAME":"LSC RGBCW E14","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} +``` + +## Bulb socket +``` +Elegant Choice E27/E26 {"NAME":"Sm Lghtg Base","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +``` + +## Dimmer +``` +Armtronix AC Dimmer One {"NAME":"ARMTR Dimmer","GPIO":[255,148,255,149,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":56} +Armtronix AC Dimmer Two {"NAME":"ARMTR Dimmer","GPIO":[255,148,255,149,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":56} +CE Smart Home WF500D {"NAME":"CE-WF500D","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} +EVA LOGIK WF31 {"NAME":"WF31 Dimmer","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} +EX-Store 2 Kanal RS232 V4 {"NAME":"EXS Dimmer","GPIO":[0,148,0,149,255,255,0,0,255,183,255,0,0],"FLAG":0,"BASE":72} +Kingart Touch {"NAME":"PS-16-DZ","GPIO":[255,148,255,149,255,255,0,0,255,52,255,255,255],"FLAG":0,"BASE":58} +``` + +## Infra Red blaster +``` +Alfawise KS1 {"NAME":"KS1","GPIO":[255,71,17,72,17,51,0,0,56,0,8,0,0],"FLAG":1,"BASE":62} +auvisio S06 {"NAME":"NX-4519-675","GPIO":[0,0,0,0,52,51,0,0,0,0,8,0,0],"FLAG":1,"BASE":18} +Eachen SANT-IR 01 {"NAME":"Eachen IR","GPIO":[0,0,0,0,56,51,255,255,255,17,8,0,0],"FLAG":0,"BASE":18}' +Geeklink {"NAME":"GL IR Blaster","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +Genio Mirabella HKWL-IR02W {"NAME":"Genio IR TxRx","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +``` + +## Light +``` +Brilliant 20702/06 Garden {"NAME":"Brilliant Gard","GPIO":[0,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Brilliant Smart WiFi Downlight CCT {"NAME":"SmartCCTDwnLgt","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} +Fcmila XDD-48W {"NAME":"XDD-48W","GPIO":[0,0,0,0,37,40,0,0,38,25,39,0,0],"FLAG":0,"BASE":18} +``` + +## Light strip +``` +Arilux AL-LC01 {"NAME":"Arilux LC01","GPIO":[17,255,59,255,147,37,0,0,38,39,255,0,0],"FLAG":0,"BASE":37} +Arilux AL-LC06 {"NAME":"Arilux LC06","GPIO":[17,255,255,255,255,255,255,255,38,39,37,41,40],"FLAG":0,"BASE":18} +Arilux AL-LC11 {"NAME":"Arilux LC11","GPIO":[17,255,59,255,38,37,0,0,41,40,39,147,0],"FLAG":0,"BASE":38} +BlitzWolf BW-LT11 {"NAME":"BW-LT11 Strip","GPIO":[17,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":0,"BASE":18} +Electrodragon Mosfet Drive {"NAME":"LEDBoard RGBW","GPIO":[255,0,0,0,255,255,0,0,39,38,40,37,52],"FLAG":0,"BASE":18} +H801 {"NAME":"H801","GPIO":[255,52,255,255,41,57,0,0,39,38,40,37,0],"FLAG":0,"BASE":20} +LEDEnet {"NAME":"LEDEnet","GPIO":[0,255,56,255,147,0,0,0,38,39,37,40,0],"FLAG":0,"BASE":34} +LSC RGBW {"NAME":"LSC RGBW Strip","GPIO":[51,0,0,0,37,0,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} +``` + +## Power plug +``` +3Stone Mini {"NAME":"3Stone Smart P","GPIO":[0,17,0,0,0,0,0,0,0,57,21,0,0],"FLAG":0,"BASE":18} +Acashna HS108 {"NAME":"HS108","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} +Acenx SOP04-US Dual {"NAME":"SOP04-US Dual","GPIO":[0,0,0,0,56,57,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +Aisirer UK1 {"NAME":"AISIRER","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +Albohes PS-1602 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39} +Albohes PC-1606 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39} +Alexfirst TV-ASP801EU {"NAME":"Alexfirst","GPIO":[17,0,0,0,54,56,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} +Alfawise PE1004T {"NAME":"PE1004T","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Amysen YX-WS01 {"NAME":"Amyse YX WS01","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} +ANBES ABS-CZ004 {"NAME":"ANBES ABS-CZ00","GPIO":[0,0,0,0,21,133,0,0,131,17,132,22,18],"FLAG":0,"BASE":18} +Anoopsyche AWP07L {"NAME":"Anoopsyche AWP","GPIO":[0,0,0,0,56,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +Anoopsyche JH-G01B1 {"NAME":"JH-G01B1","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":41} +Anoopsyche UK1D {"NAME":"UK1D","GPIO":[0,17,0,0,133,132,0,0,130,52,21,0,0],"FLAG":0,"BASE":6} +Aoycocr Smart Plug {"NAME":"Aoycocr Smart ","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} +Aoycocr EU5-16A {"NAME":"Aoycocr","GPIO":[255,0,56,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17} +Arlec Grid Connect PC189HA {"NAME":"Arlec","GPIO":[0,0,0,0,123,0,0,0,21,56,17,0,0],"FLAG":0,"BASE":18} +Arlec Twin PC288HA {"NAME":"Arlec Twin","GPIO":[0,17,0,22,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Aukey SH-PA1 {"NAME":"AUKEY SH-PA1","GPIO":[0,0,255,0,0,0,0,0,0,17,0,21,0],"FLAG":15,"BASE":18} +Avatar 10A {"NAME":"AWP07L","GPIO":[56,0,0,0,0,134,0,0,130,17,132,21,0],"FLAG":1,"BASE":18} +Avatar AWP07L 10A {"NAME":"Avatar AWP07L","GPIO":[56,0,0,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Avatto JH-G01E {"NAME":"AVATTO JH-G01E","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":41} +AWP04L {"NAME":"AWP04L","GPIO":[57,0,0,131,0,134,0,0,21,17,132,56,0],"FLAG":0,"BASE":18} +AWP07L {"NAME":"AISIRER AWP07L","GPIO":[0,0,0,0,56,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +AWP08L {"NAME":"AWP08L","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} +AzpenHome Smart {"NAME":"Socket2Me","GPIO":[52,0,0,0,22,0,0,0,21,0,17,0,0],"FLAG":15,"BASE":18} +Bestek MRJ1011 {"NAME":"BestekMRJ1011","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} +Bilikay SP10 {"NAME":"Bilikay SP10","GPIO":[0,37,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Blitzwolf BW-SHP2 {"NAME":"BlitzWolf SHP","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Blitzwolf BW-SHP3 {"NAME":"Blitzwolf SHP3","GPIO":[56,0,57,0,22,134,0,0,131,18,132,21,17],"FLAG":0,"BASE":45} +Blitzwolf BW-SHP3 alt {"NAME":"Blitzwolf SHP3","GPIO":[18,56,0,131,134,132,0,0,17,0,22,21,0],"FLAG":0,"BASE":18} +Blitzwolf BW-SHP4 {"NAME":"BlitzWolf SHP","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Blitzwolf BW-SHP5 {"NAME":"SHP5","GPIO":[57,145,56,146,0,22,0,0,0,0,21,0,17],"FLAG":0,"BASE":18} +Blitzwolf BW-SHP6 {"NAME":"BlitzWolf SHP","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Blitzwolf BW-SHP8 {"NAME":"SHP8","GPIO":[0,56,0,17,134,132,0,0,131,53,21,0,0],"FLAG":0,"BASE":64} +BN-LINK BNC-60/U133TJ-2P {"NAME":"BNC-60/U133TJ","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":18} +BSD15 {"NAME":"TuyaPlugBSD15","GPIO":[0,0,0,0,0,0,0,0,21,17,56,0,0],"FLAG":1,"BASE":18} +BSD25 {"NAME":"Tuya Wifi Plug","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +BSD29 {"NAME":"BSD29","GPIO":[0,0,0,131,134,132,0,0,21,17,56,0,0],"FLAG":0,"BASE":52} +BSD33 {"NAME":"Generic","GPIO":[0,0,0,131,134,132,0,0,21,17,56,0,0],"FLAG":15,"BASE":18} +BSD34 {"NAME":"BSD34 Plug","GPIO":[0,0,0,0,0,0,0,0,21,17,56,0,0],"FLAG":0,"BASE":18} +CE Smart Home LA-WF3 {"NAME":"CE LA-WF3","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Conico SM-PW70 {"NAME":"Conico SM-PW70","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +Coosa {"NAME":"COOSA","GPIO":[0,0,0,0,57,52,0,0,21,17,255,0,0],"FLAG":0,"BASE":1} +Coosa SP1 {"NAME":"COOSA SP1","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +CrazyLynX WiFi {"NAME":"CrazyLynX","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +CYYLTF BIFANS J23 {"NAME":"CYYLTD BIFANS J23","GPIO":[56,0,0,0,0,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +Delock 11826 {"NAME":"Delock 11826","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +Digoo NX-SP202 {"NAME":"Generic_SP202","GPIO":[52,0,0,131,91,134,0,0,22,17,132,21,0],"FLAG":0,"BASE":63} +Digoo DG-SP01 {"NAME":"DG-SP01","GPIO":[0,17,0,21,56,37,0,0,38,39,40,0,0],"FLAG":0,"BASE":18} +DILISENS SP201 {"NAME":"Dilisens SP201","GPIO":[0,0,131,0,133,132,52,21,18,22,17,0,0],"FLAG":0,"BASE":18} +DWFeng AWP02L-N {"NAME":"AWP02L-N","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +ECF-SOP03 {"NAME":"Outdoor3Outlet","GPIO":[0,0,0,23,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +ECO Plugs CT-065W {"NAME":"ECO/CT-065W","GPIO":[0,0,0,0,0,0,0,0,0,17,0,21,0],"FLAG":15,"BASE":18} +EFUN SH331W {"NAME":"Efun-Plug","GPIO":[56,0,158,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} +EletecPro 2 {"NAME":"EletecPro-2","GPIO":[0,0,0,0,17,0,0,0,53,52,21,0,0],"FLAG":1,"BASE":18} +ENJOWI SP111-EU-W {"NAME":"Enjowi SP111-E","GPIO":[17,56,0,0,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} +Epicka {"NAME":"Epicka","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +Esicoo YX-WS01 {"NAME":"Esicoo Plug","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Estink C178 {"NAME":"Estink C178","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +ESW01-US {"NAME":"ESW01-US","GPIO":[0,0,0,0,21,56,0,0,0,0,9,0,0],"FLAG":1,"BASE":18} +EVA LOGIK NWF001 {"NAME":"EVA LOGIK Plug","GPIO":[0,17,0,0,0,0,0,0,0,52,21,0,0],"FLAG":0,"BASE":18} +EVO-Smart JH-G01U {"NAME":"EVO JH-G01U","GPIO":[0,0,0,0,21,17,0,0,56,0,0,0,0],"FLAG":0,"BASE":18} +Feit Electric Dual {"NAME":"Prime Smart ou","GPIO":[0,0,0,0,157,56,0,0,21,17,0,0,0],"FLAG":15,"BASE":18} +FK-PW901U {"NAME":"FK-PW901U","GPIO":[56,0,0,0,0,23,0,0,21,17,24,22,0],"FLAG":15,"BASE":18} +FLHS-ZN04 {"NAME":"FLHS-ZN04","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Fontastic SH01 {"NAME":"Fontastic","GPIO":[255,0,255,0,56,0,255,255,21,17,0,0,0],"FLAG":1,"BASE":18} +FrankEver FLHS-ZN04 {"NAME":"Israel plug","GPIO":[57,0,56,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":45} +GDTech W-US001 {"NAME":"GDTech W-US001","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} +GDTech W-US003 {"NAME":"W-US003","GPIO":[0,17,255,255,255,0,0,0,0,56,21,0,0],"FLAG":15,"BASE":18} +Geeni Charge {"NAME":"Geeni Charge","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Geeni Glo {"NAME":"Geeni Glo","GPIO":[0,0,0,0,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +Geeni GN-OW101-101 {"NAME":"Geeni Outdoor","GPIO":[17,0,0,0,0,57,0,0,0,52,21,0,0],"FLAG":0,"BASE":18} +Geeni Spot {"NAME":"Geeni Spot","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Geeni Switch Duo {"NAME":"Geeni Duo","GPIO":[0,0,0,0,18,22,0,0,17,52,21,0,53],"FLAG":0,"BASE":18} +Globe Smart {"NAME":"GlobeSmartPlug","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} +Gosund SP1 {"NAME":"Gosund SP1 v23","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} +Gosund SP111 {"NAME":"Gosund SP111","GPIO":[56,0,57,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} +Gosund SP112 {"NAME":"SHP5","GPIO":[56,145,57,146,255,22,0,0,255,255,21,255,17],"FLAG":0,"BASE":18} +Gosund WP1-1 {"NAME":"Gosund WP1-1","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Gosund WP2 {"NAME":"Gosund_WP212","GPIO":[17,0,0,0,18,0,0,0,21,0,22,0,0],"FLAG":0,"BASE":18} +Gosund WP3 {"NAME":"Gosund WP3","GPIO":[0,0,0,0,17,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} +Gosund WP5 {"NAME":"Gosund-WP5","GPIO":[0,0,0,0,17,0,0,0,53,52,21,0,0],"FLAG":1,"BASE":18} +Gosund WP6 {"NAME":"Gosund WP6","GPIO":[0,0,0,17,0,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} +Gosund WP211 {"NAME":"Gosund wp211","GPIO":[0,0,0,0,21,0,0,0,0,17,0,22,18],"FLAG":0,"BASE":18} +Gosund WP212 {"NAME":"Gosund_WP212","GPIO":[17,0,0,0,18,0,0,0,21,0,22,0,0],"FLAG":0,"BASE":18} +Grefic TE101 {"NAME":"Grefic TE101","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} +Gyman SM-PW701U {"NAME":"Gyman","GPIO":[0,0,157,0,56,0,0,0,21,17,0,0,0],"FLAG":15,"BASE":18} +Hauppauge SL-1642 {"NAME":"SL-1642","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +HiHome WPP-16T {"NAME":"HiHome WPP-16T","GPIO":[17,56,0,0,134,132,0,0,18,0,22,130,21],"FLAG":1,"BASE":18} +hiwild W-US002 {"NAME":"W-US002","GPIO":[0,17,0,0,0,0,0,0,0,52,21,0,158],"FLAG":0,"BASE":18} +Houzetek AWP07L {"NAME":"AWP07L","GPIO":[56,0,0,130,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":18} +HuaFan QinLu {"NAME":"Huafan SS","GPIO":[56,0,0,57,17,29,0,0,132,130,133,0,0],"FLAG":0,"BASE":24} +AWP02L-N {"NAME":"AWP02L-N","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} +Hyleton 313 {"NAME":"Hyleton 313","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Hyleton 317 {"NAME":"hyleton-317","GPIO":[56,0,57,0,58,0,0,0,0,90,0,21,0],"FLAG":0,"BASE":18} +Innens BSD29 {"NAME":"BSD29","GPIO":[0,0,56,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":52} +iSwitch {"NAME":"Smart Plug XSA","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Jeeo TF-SH330 {"NAME":"Jeeo TF-SH330","GPIO":[56,0,0,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} +Jinvoo SM-PW701U {"NAME":"SM-PW702","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Jinvoo SM-PW762U {"NAME":"SM-PW762U","GPIO":[0,0,0,0,158,56,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +Jules V (Upgrade Version) {"NAME":"Jules-V_UV","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18} +Jules.V NX-SM300 {"NAME":"NX-SM300","GPIO":[52,0,0,0,0,130,0,0,21,132,133,52,0],"FLAG":0,"BASE":6} +Kimire S12 {"NAME":"Kimire S12","GPIO":[0,0,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +King-Link C128 {"NAME":"King-Link C128","GPIO":[0,0,55,0,22,53,0,0,23,52,17,21,54],"FLAG":0,"BASE":18} +KMC 70011 {"NAME":"KMC 70011","GPIO":[17,0,0,0,133,132,0,0,130,56,21,0,0],"FLAG":0,"BASE":36} +KMC 4 30608 {"NAME":"KMC 4 Outlet","GPIO":[0,56,0,0,133,132,0,0,130,22,23,21,17],"FLAG":0,"BASE":36} +Kogan SmarterHome Energy Meter {"NAME":"Kogan Smart Sw","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} +Koogeek KLUP1 {"NAME":"Koogeek-KLUP1","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} +Koogeek KLUP1 {"NAME":"Koogeek-KLUP1","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":1} +Koogeek KLSP1 {"NAME":"Koogeek-KLSP1","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} +Laduo YX-DE01 {"NAME":"YX-DE01","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +LA-WF3 {"NAME":"CE Smart Plug","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +LEPOWER {"NAME":"LEPOWER Outdoo","GPIO":[0,0,0,0,56,57,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +LESHP KS-501 {"NAME":"LESHP KS-501","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +LINGANZH 16A {"NAME":"Linganzh Smart","GPIO":[56,0,0,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Lonsonho 10A Type E {"NAME":"Lonsonho10ALed","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Lonsonho RGB {"NAME":"RGB Smart Plug","GPIO":[37,0,38,0,0,39,0,0,0,17,0,21,0],"FLAG":0,"BASE":45} +LSC Smart Connect {"NAME":"LSC Smart Plug","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} +``` + +## Power socket +``` +Bestten LO-2-W2 {"NAME":"BESTTEN LO-2-W","GPIO":[17,0,0,0,57,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +Charging Essentials WiFi Smart {"NAME":"CESmart-Wall","GPIO":[0,0,0,0,0,17,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} +Kesen KS-604 {"NAME":"KS-604","GPIO":[0,0,52,0,0,18,0,0,22,21,0,0,17],"FLAG":0,"BASE":18} +Kesen KS-604S {"NAME":"KS-604S","GPIO":[0,0,31,0,0,18,0,0,22,21,0,0,17],"FLAG":1,"BASE":18} +``` + +## Power strip +``` +3Stone (2019 Model) {"NAME":"3Stone-2019","GPIO":[0,0,56,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} +ACENX 3AC+3USB {"NAME":"ACENX 3-Outlet","GPIO":[56,55,54,53,0,21,0,0,23,24,22,0,17],"FLAG":0,"BASE":18} +Annhome 3AC + 2USB {"NAME":"1200W WiFi SPS","GPIO":[32,0,0,0,57,52,0,0,21,17,22,23,33],"FLAG":0,"BASE":18} +AOFO 3AC+4USB {"NAME":"AOFO","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18} +AOFO 4AC+4USB {"NAME":"AOFO4AC4USB","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} +CE Garden Power Stake {"NAME":"CE Power Stake","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +CE Smart Home LTS-6A-W5 {"NAME":"CE Power Strip","GPIO":[52,0,0,0,22,21,0,0,24,23,25,26,17],"FLAG":0,"BASE":18} +CRST LTS-4G-W {"NAME":"CRST LTS-4G-W","GPIO":[0,0,0,0,24,0,255,255,22,23,21,0,0],"FLAG":0,"BASE":18} +Digoo DG-PS01 {"NAME":"Digoo DG-PS01","GPIO":[0,56,0,17,23,22,0,0,0,24,21,0,0],"FLAG":1,"BASE":18} +Geekbes 4AC+4USB {"NAME":"Geekbes 4xStri","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} +Geeni GN-SW003 {"NAME":"Geeni GNCSW003","GPIO":[52,0,0,0,22,21,0,0,24,25,23,26,17],"FLAG":0,"BASE":18} +Hyleton 330 {"NAME":"Hyleton-330","GPIO":[57,0,0,56,29,17,0,0,31,30,32,0,25],"FLAG":0,"BASE":18} +Hyleton 331 {"NAME":"HLT-331","GPIO":[52,0,0,57,29,17,0,0,31,30,32,0,58],"FLAG":0,"BASE":18} +Hyleton 336 {"NAME":"HLT-336","GPIO":[52,0,0,57,29,17,0,0,31,30,0,0,32],"FLAG":0,"BASE":18} +KMC 5 {"NAME":"KMC 5-Outlet","GPIO":[56,0,0,0,25,9,0,0,22,21,23,0,24],"FLAG":0,"BASE":18} +Koogeek KLOE4 {"NAME":"Koogeek KLOE4","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} +LeFun SK2 {"NAME":"LeFun SK2","GPIO":[0,0,0,17,22,21,0,0,23,24,25,0,0],"FLAG":0,"BASE":18} +``` + +## Relay module +``` +Blitzwolf BW-SS1 {"NAME":"BW-SS1","GPIO":[255,255,255,255,157,21,0,0,255,17,255,255,0],"FLAG":15,"BASE":18} +Canwing CW-001 {"NAME":"Canwing CW-001","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +EACHEN ST-DC2 {"NAME":"Garage Control","GPIO":[11,0,0,0,23,22,18,0,21,52,12,24,0],"FLAG":1,"BASE":18} +Electrodragon Board SPDT {"NAME":"ED Relay Board","GPIO":[255,255,255,255,255,255,255,255,21,22,255,255,52],"FLAG":1,"BASE":18} +Electrodragon ESP8266 {"NAME":"ElectroDragon","GPIO":[18,255,17,255,255,255,0,0,22,21,255,255,52],"FLAG":1,"BASE":15} +eMylo SS-8839-03 {"NAME":"eMylo","GPIO":[0,0,0,0,52,0,0,0,21,0,17,0,0],"FLAG":1,"BASE":18} +eMylo XL9251WI {"NAME":"XL9251WI","GPIO":[255,255,255,255,56,255,255,255,21,255,17,255,255],"FLAG":0,"BASE":18} +eMylo YSA111A1N-FBA {"NAME":"Emylo","GPIO":[255,255,255,255,52,255,255,255,21,255,17,255,255],"FLAG":0,"BASE":18} +Zemismart ERC309 Kinetic {"NAME":"Kinetic Switch","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} +ESP-01 Relay V4.0 {"NAME":"ESP01v4","GPIO":[29,52,0,255,255,255,255,255,255,255,255,255,255],"FLAG":0,"BASE":18} +EX Store 2 Kanal V5 {"NAME":"EXS Relay V5","GPIO":[255,255,255,255,255,255,0,0,21,22,31,52,32],"FLAG":0,"BASE":16} +Geekcreit 2 Channel {"NAME":"Geekcreit 2ch","GPIO":[17,0,0,0,0,22,18,0,21,52,0,0,0],"FLAG":1,"BASE":18} +Gocomma Wi-Fi Smart Switch {"NAME":"GoCommaSmartSw","GPIO":[17,255,255,255,21,255,255,255,255,56,255,255,255],"FLAG":0,"BASE":18} +LC Technology 4CH {"NAME":"LC-Tech_4CH ","GPIO":[52,255,17,255,255,255,255,255,21,22,23,24,255],"FLAG":0,"BASE":18} +LC-Tech 1Ch and PZEM-004T {"NAME":"HW-655 PZEM","GPIO":[0,63,0,62,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +LinkNode R4 {"NAME":"LinkNode R4","GPIO":[0,0,0,0,0,0,0,0,21,22,23,0,24],"FLAG":0,"BASE":18} +LinkNode R8 {"NAME":"LinkNode R8","GPIO":[0,0,0,0,25,26,0,28,23,24,22,27,21],"FLAG":0,"BASE":18} +``` + +## Switch +``` +3A Smart Home HGZB-043 {"NAME":"3A Smart Home","GPIO":[52,0,55,18,22,19,0,0,17,21,54,23,53],"FLAG":0,"BASE":18} +Deta 6912HA {"NAME":"DETA 2G Switch","GPIO":[0,0,0,0,157,0,0,0,91,21,22,0,90],"FLAG":0,"BASE":18} +DS-102 1 Gang {"NAME":"DS-102 1 Gang","GPIO":[57,0,0,17,0,0,0,0,0,21,56,0,0],"FLAG":1,"BASE":18} +DS-102 2 Gang {"NAME":"DS-102 2 Gang","GPIO":[56,58,0,17,22,18,0,0,0,21,57,0,0],"FLAG":0,"BASE":18} +DS-102 3 Gang {"NAME":"DS-102 3 Gang","GPIO":[158,58,0,18,22,19,0,0,17,21,57,23,56],"FLAG":0,"BASE":18} +Enjowi WF-SK301 {"NAME":"Tuya 3 Channel","GPIO":[0,0,0,0,23,18,0,0,17,21,19,22,157],"FLAG":0,"BASE":18} +Etekcity 3-way {"NAME":"Etekcity 3Way","GPIO":[255,255,0,255,23,29,0,0,82,22,10,0,0],"FLAG":0,"BASE":18} +EtekCity ESWL01 {"NAME":"EtekCityESWL01","GPIO":[0,0,0,0,52,53,0,0,0,21,122,0,0],"FLAG":1,"BASE":18} +Gosund KS-602S {"NAME":"Gosund KS-602S","GPIO":[17,56,0,0,0,0,0,0,0,0,21,0,158],"FLAG":0,"BASE":18} +Jinvoo SM-SW101-1 {"NAME":"SM-SW101-1","GPIO":[52,0,0,18,0,0,0,0,17,21,0,0,0],"FLAG":1,"BASE":18} +Jinvoo SM-SW101-2 {"NAME":"SM-SW101-2","GPIO":[52,0,0,18,22,0,0,0,17,21,0,0,0],"FLAG":1,"BASE":18} +Jinvoo SM-SW101-3 {"NAME":"Jinvoo Wall Sw","GPIO":[52,0,0,18,22,19,0,0,17,21,0,23,0],"FLAG":1,"BASE":18} +Jinvoo SM-SW101-C Curtain {"NAME":"Jinvoo Curtain","GPIO":[52,0,0,18,22,19,0,0,17,21,0,23,0],"FLAG":1,"BASE":18} +KMC 70008 {"NAME":"KMC 70008","GPIO":[17,0,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +KOAANW DS302 {"NAME":"DS302","GPIO":[0,0,0,19,23,18,0,0,17,21,0,22,52],"FLAG":1,"BASE":18} +Kuled K36 {"NAME":"KULED-B","GPIO":[9,0,0,0,0,0,21,52,29,56,0,0,0],"FLAG":0,"BASE":18} +Kuled KS602S {"NAME":"KULED","GPIO":[9,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":18} +KYGNE CD-301 {"NAME":"KYGNE Touch","GPIO":[0,0,0,0,52,53,0,0,21,17,0,0,0],"FLAG":0,"BASE":10} +Lonsonho SK3-01 {"NAME":"Tuya 1 Channel","GPIO":[0,0,0,0,0,17,0,0,0,0,0,21,52],"FLAG":0,"BASE":18} +Lonsonho SK3-02 {"NAME":"Tuya 2 Channel","GPIO":[0,0,0,0,22,0,0,0,17,21,18,0,52],"FLAG":0,"BASE":18} +``` + +## Miscellaneous +``` +Asakuki 500ml {"NAME":"Oil Diffuser","GPIO":[255,255,255,255,255,255,255,255,255,255,255,21,22],"FLAG":0,"BASE":18} +Hoenyzy DN20 3/4 {"NAME":"DN20 WIFI Valve","GPIO":[0,0,0,0,0,0,0,0,17,21,0,0,0],"FLAG":0,"BASE":18} +Jinvoo SM-AW713 {"NAME":"Jinvoo Valve","GPIO":[0,0,0,0,0,52,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Jinvoo SM-PW713 {"NAME":"Jinvoo Valve","GPIO":[0,0,0,0,21,52,0,0,17,53,0,0,0],"FLAG":1,"BASE":18} +``` \ No newline at end of file From a567226415ad76dbbc96d29b643b5f2d656f9250 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Mon, 21 Oct 2019 17:24:03 +0100 Subject: [PATCH 2210/2222] Rules: Add TuyaMcuReceived#Data= rule and fix SerialReceived and SSerialRecieved rules --- sonoff/i18n.h | 1 + sonoff/sonoff.ino | 2 +- sonoff/xdrv_08_serial_bridge.ino | 2 +- sonoff/xdrv_16_tuyamcu.ino | 10 ++++------ 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index e97cd1fee..76e00d35e 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -456,6 +456,7 @@ // Commands xdrv_16_tuyadimmer.ino #define D_CMND_TUYA_MCU "TuyaMCU" +#define D_JSON_TUYA_MCU_RECEIVED "TuyaMcuReceived" // Commands xdrv_23_zigbee.ino #define D_CMND_ZIGBEE_PERMITJOIN "ZigbeePermitJoin" diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 0fbc690cc..d6fc706f7 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1241,7 +1241,7 @@ void SerialInput(void) if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed char hex_char[(serial_in_byte_counter * 2) + 2]; - ResponseTime_P(PSTR(",\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), + Response_P(PSTR(",\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), (Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); XdrvRulesProcess(); diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 2604bfebf..117671d94 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -71,7 +71,7 @@ void SerialBridgeInput(void) if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) { serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // Serial data completed char hex_char[(serial_bridge_in_byte_counter * 2) + 2]; - ResponseTime_P(PSTR(",\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), + Response_P(PSTR(",\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), (serial_bridge_raw) ? ToHex_P((unsigned char*)serial_bridge_buffer, serial_bridge_in_byte_counter, hex_char, sizeof(hex_char)) : serial_bridge_buffer); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); XdrvRulesProcess(); diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index fa9b7a22c..764be681a 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -538,12 +538,10 @@ void TuyaSerialInput(void) else if ((Tuya.cmd_status == 3) && (Tuya.byte_counter == (6 + Tuya.data_len)) && (Tuya.cmd_checksum == serial_in_byte)) { // Compare checksum and process packet Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: RX Packet: \"")); - for (uint32_t i = 0; i < Tuya.byte_counter; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, Tuya.buffer[i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); - AddLog(LOG_LEVEL_DEBUG); + char hex_char[(Tuya.byte_counter * 2) + 2]; + Response_P(PSTR("{\"" D_JSON_TUYA_MCU_RECEIVED "\":\"%s\"}"), ToHex_P((unsigned char*)Tuya.buffer, Tuya.byte_counter, hex_char, sizeof(hex_char))); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); + XdrvRulesProcess(); TuyaPacketProcess(); Tuya.byte_counter = 0; From c798e9bd8c898f0f908adf3deaaa8e4f7b13f8ea Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Tue, 22 Oct 2019 09:29:16 +0200 Subject: [PATCH 2211/2222] No issue support for Tuya Converted devices --- .github/ISSUE_TEMPLATE/Bug_report.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 1e29983f7..0d3d5f7f5 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -8,7 +8,8 @@ about: Create a report to help us improve > This BUG issue template is meant to REPORT Tasmota software BUGS ONLY> > > Please DO NOT OPEN AN ISSUE: -> - If your Tasmota version is not the latest from the development branch, please update your device before submitting your issue. Your problem might already be solved. The latest precompiled binaries of Tasmota can be downloaded from http://thehackbox.org/tasmota/ +> - If your Tasmota version is not the latest from the development branch, please update your device before submitting your issue. Your problem might already be solved. The latest precompiled binaries of Tasmota can be downloaded from http://thehackbox.org/tasmota/ +> - If you have a issue when flashing was done via Tuya Convert > - If your issue is a flashing issue, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) > - If your issue is compilation problem, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) > - If your issue has been addressed before (i.e., duplicated issue), please ask in the original issue From b2d1e385c0b3f33daf50de4f91e4a0f6dea77d01 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 22 Oct 2019 14:56:06 +0200 Subject: [PATCH 2212/2222] Change timer reset to 70 minutes Change timer reset to 70 minutes (#6349) --- sonoff/xsns_01_counter.ino | 102 ++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 40 deletions(-) diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index a6bc80acb..e3b6a171a 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -34,10 +34,13 @@ const char kCounterCommands[] PROGMEM = D_PRFX_COUNTER "|" // Prefix void (* const CounterCommand[])(void) PROGMEM = { &CmndCounter, &CmndCounterType, &CmndCounterDebounce }; -unsigned long last_counter_timer[MAX_COUNTERS]; // Last counter time in micro seconds -uint8_t counter_no_pullup = 0; // Counter input pullup flag (1 = No pullup) +struct COUNTER { + uint32_t timer[MAX_COUNTERS]; // Last counter time in micro seconds + uint8_t no_pullup = 0; // Counter input pullup flag (1 = No pullup) + bool any_counter = false; +} Counter; -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception void CounterUpdate(uint8_t index) ICACHE_RAM_ATTR; void CounterUpdate1(void) ICACHE_RAM_ATTR; void CounterUpdate2(void) ICACHE_RAM_ATTR; @@ -47,37 +50,36 @@ void CounterUpdate4(void) ICACHE_RAM_ATTR; void CounterUpdate(uint8_t index) { - unsigned long counter_debounce_time = micros() - last_counter_timer[index -1]; - if (counter_debounce_time > Settings.pulse_counter_debounce * 1000) { - last_counter_timer[index -1] = micros(); - if (bitRead(Settings.pulse_counter_type, index -1)) { - RtcSettings.pulse_counter[index -1] = counter_debounce_time; + uint32_t time = micros(); + uint32_t debounce_time = time - Counter.timer[index]; + if (debounce_time > Settings.pulse_counter_debounce * 1000) { + Counter.timer[index] = time; + if (bitRead(Settings.pulse_counter_type, index)) { + RtcSettings.pulse_counter[index] = debounce_time; } else { - RtcSettings.pulse_counter[index -1]++; + RtcSettings.pulse_counter[index]++; } - -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CNTR: Interrupt %d"), index); } } void CounterUpdate1(void) { - CounterUpdate(1); + CounterUpdate(0); } void CounterUpdate2(void) { - CounterUpdate(2); + CounterUpdate(1); } void CounterUpdate3(void) { - CounterUpdate(3); + CounterUpdate(2); } void CounterUpdate4(void) { - CounterUpdate(4); + CounterUpdate(3); } /********************************************************************************************/ @@ -85,7 +87,7 @@ void CounterUpdate4(void) bool CounterPinState(void) { if ((XdrvMailbox.index >= GPIO_CNTR1_NP) && (XdrvMailbox.index < (GPIO_CNTR1_NP + MAX_COUNTERS))) { - bitSet(counter_no_pullup, XdrvMailbox.index - GPIO_CNTR1_NP); + bitSet(Counter.no_pullup, XdrvMailbox.index - GPIO_CNTR1_NP); XdrvMailbox.index -= (GPIO_CNTR1_NP - GPIO_CNTR1); return true; } @@ -99,12 +101,27 @@ void CounterInit(void) for (uint32_t i = 0; i < MAX_COUNTERS; i++) { if (pin[GPIO_CNTR1 +i] < 99) { - pinMode(pin[GPIO_CNTR1 +i], bitRead(counter_no_pullup, i) ? INPUT : INPUT_PULLUP); + Counter.any_counter = true; + pinMode(pin[GPIO_CNTR1 +i], bitRead(Counter.no_pullup, i) ? INPUT : INPUT_PULLUP); attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); } } } +void CounterEverySecond(void) +{ + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + if (bitRead(Settings.pulse_counter_type, i)) { + uint32_t time = micros() - Counter.timer[i]; + if (time > 4200000000) { // 70 minutes + RtcSettings.pulse_counter[i] = 4200000000; // Set Timer to max in case of no more interrupts due to stall of measured device + } + } + } + } +} + void CounterSaveState(void) { for (uint32_t i = 0; i < MAX_COUNTERS; i++) { @@ -147,9 +164,6 @@ void CounterShow(bool json) #endif // USE_WEBSERVER } } - if (bitRead(Settings.pulse_counter_type, i)) { - RtcSettings.pulse_counter[i] = 0xFFFFFFFF; // Set Timer to max in case of no more interrupts due to stall of measured device - } } if (header) { ResponseJsonEnd(); @@ -204,28 +218,36 @@ bool Xsns01(uint8_t function) { bool result = false; - switch (function) { - case FUNC_JSON_APPEND: - CounterShow(1); - break; + if (Counter.any_counter) { + switch (function) { + case FUNC_EVERY_SECOND: + CounterEverySecond(); + break; + case FUNC_JSON_APPEND: + CounterShow(1); + break; #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - CounterShow(0); - break; + case FUNC_WEB_SENSOR: + CounterShow(0); + break; #endif // USE_WEBSERVER - case FUNC_SAVE_BEFORE_RESTART: - case FUNC_SAVE_AT_MIDNIGHT: - CounterSaveState(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kCounterCommands, CounterCommand); - break; - case FUNC_INIT: - CounterInit(); - break; - case FUNC_PIN_STATE: - result = CounterPinState(); - break; + case FUNC_SAVE_BEFORE_RESTART: + case FUNC_SAVE_AT_MIDNIGHT: + CounterSaveState(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kCounterCommands, CounterCommand); + break; + } + } else { + switch (function) { + case FUNC_INIT: + CounterInit(); + break; + case FUNC_PIN_STATE: + result = CounterPinState(); + break; + } } return result; } From b072791426747a4cd4b41568c61ded7229708dbc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 22 Oct 2019 16:34:25 +0200 Subject: [PATCH 2213/2222] Bump version 6.6.0.21 * Remove support for WPS and SmartConfig in favour of Web server (!) based WifiManager (#6680) * Remove binary sonoff-classic (#6680) --- .travis.yml | 1 - RELEASENOTES.md | 378 +++++++++++---------------- platformio.ini | 16 -- sonoff/_changelog.ino | 4 + sonoff/i18n.h | 12 +- sonoff/my_user_config.h | 12 +- sonoff/settings.ino | 5 + sonoff/sonoff.h | 4 +- sonoff/sonoff_post.h | 126 +-------- sonoff/sonoff_version.h | 2 +- sonoff/support_button.ino | 6 +- sonoff/support_features.ino | 4 +- sonoff/support_wifi.ino | 90 +------ sonoff/xdrv_01_webserver.ino | 8 +- sonoff/xdrv_16_tuyamcu.ino | 4 - sonoff/xdrv_18_armtronix_dimmers.ino | 4 - 16 files changed, 193 insertions(+), 483 deletions(-) diff --git a/.travis.yml b/.travis.yml index 491f37bd6..3f4121386 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,6 @@ env: - ENV=sonoff - ENV=sonoff-minimal - ENV=sonoff-basic - - ENV=sonoff-classic - ENV=sonoff-knx - ENV=sonoff-sensors - ENV=sonoff-display diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 3f99c2e7b..89efea9d5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -18,10 +18,8 @@ Although it might still compile on previous Core versions all support will be re ## Support of TLS To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. See full documentation on https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT -## Change in default initial configuration tool -Firmware binary **sonoff-classic.bin** supports **WifiManager, Wps and SmartConfig** for initial configuration. The default tool is **Wps**. To save code space all other binaries support **WifiManager only**. - -The next release will remove support for **WPS** and **SmartConfig** +## Initial configuration tools +For initial configuration this release supports Webserver based **WifiManager** or **Serial** based command interface only. Support for **WPS** and **SmartConfig** has been removed. ## Supported Modules The following hardware modules are supported. @@ -104,238 +102,160 @@ Module | Description ## Provided Binary Downloads The following binary downloads have been compiled with ESP8266/Arduino library core version **pre-2.6.0**. -- **sonoff.bin** = The Sonoff version adds more sensors. **RECOMMENDED RELEASE BINARY** -- **sonoff-basic.bin** = The Basic version without most sensors. -- **sonoff-classic.bin** = The Classic version allows initial installation using either WifiManager, Wps or SmartConfig. +- **sonoff.bin** = The Sonoff version with sensors. **RECOMMENDED RELEASE BINARY** - **sonoff-BG.bin** to **sonoff-TW.bin** = The Sonoff version in different languages. +- **sonoff-basic.bin** = The Basic version without most sensors. - **sonoff-knx.bin** = The Knx version without some features but adds KNX support. -- **sonoff-sensors.bin** = The Sensors version adds even more useful sensors. +- **sonoff-sensors.bin** = The Sensors version adds more useful sensors. - **sonoff-ir** = The InfraRed Receiver and transmitter version allowing all available protocols provided by library IRremoteESP8266 but without most other features. - **sonoff-display.bin** = The Display version without Energy Monitoring but adds display support. - **sonoff-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**. ## Available Features and Sensors -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | ir | display | Remarks -|-----------------------|---------|-------|---------|--------|-----|---------|----|---------|-------- -| MY_LANGUAGE en-GB | x | x | x | x | x | x | x | x | -| USE_WPS | - | - | x | - | - | - | - | - | WPS -| USE_SMARTCONFIG | - | - | x | - | - | - | - | - | SmartConfig -| USE_ARDUINO_OTA | - | - | - | - | - | - | - | - | -| USE_DOMOTICZ | - | - | x | x | x | x | x | - | -| USE_HOME_ASSISTANT | - | - | - | x | x | x | x | - | -| USE_MQTT_TLS | - | - | - | - | - | - | - | - | -| USE_MQTT_TLS_CA_CERT | - | - | - | - | - | - | - | - | -| USE_MQTT_AWS_IOT | - | - | - | - | - | - | - | - | -| USE_KNX | - | - | - | - | x | - | - | - | -| USE_WEBSERVER | x | x | x | x | x | x | x | x | WifiManager -| USE_JAVASCRIPT_ES6 | - | - | - | - | - | - | - | - | -| USE_WEBSEND_RESPONSE | - | - | - | - | - | - | - | - | -| USE_EMULATION_HUE | - | x | x | x | - | x | - | - | -| USE_EMULATION_WEMO | - | x | x | x | - | x | - | - | -| USE_DISCOVERY | - | - | x | x | x | - | - | x | -| WEBSERVER_ADVERTISE | - | - | x | x | x | - | - | x | -| MQTT_HOST_DISCOVERY | - | - | x | x | x | - | - | x | -| USE_TIMERS | - | x | - | x | x | x | x | x | -| USE_TIMERS_WEB | - | x | - | x | x | x | x | x | -| USE_SUNRISE | - | x | - | x | x | x | x | x | -| USE_RULES | - | x | - | x | x | x | x | x | -| USE_SCRIPT | - | - | - | - | - | - | - | - | -| USE_EXPRESSION | - | - | - | - | - | - | - | - | -| SUPPORT_IF_STATEMENT | - | - | - | - | - | - | - | - | -| | | | | | | | | | -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | ir | display | Remarks -| ROTARY_V1 | - | - | - | - | - | - | - | - | -| USE_SONOFF_RF | - | - | - | x | x | x | - | - | -| USE_RF_FLASH | - | - | - | x | x | x | - | - | -| USE_SONOFF_SC | - | - | - | x | - | x | - | - | -| USE_TUYA_MCU | - | x | - | x | x | x | - | x | -| USE_ARMTRONIX_DIMMERS | - | - | - | x | x | - | - | - | -| USE_PS_16_DZ | - | - | - | x | x | x | - | - | -| USE_SONOFF_IFAN | - | - | - | x | x | x | - | - | -| USE_BUZZER | - | - | - | x | x | x | - | - | -| USE_ARILUX_RF | - | - | - | x | x | x | - | - | -| USE_SHUTTER | - | - | - | - | - | - | - | - | -| USE_DEEPSLEEP | - | - | - | - | - | - | - | - | -| USE_EXS_DIMMER | - | - | - | - | - | - | - | - | -| | | | | | | | | | -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | ir | display | Remarks -| USE_LIGHT | - | x | x | x | x | x | x | x | -| USE_WS2812 | - | - | x | x | x | x | - | x | -| USE_WS2812_DMA | - | - | - | - | - | - | - | - | -| USE_MY92X1 | - | - | - | x | x | x | - | x | -| USE_SM16716 | - | - | - | x | x | x | - | x | -| USE_SM2135 | - | - | - | x | x | x | - | x | -| USE_SONOFF_L1 | - | - | - | x | x | x | - | x | -| | | | | | | | | | -| USE_ENERGY_SENSOR | - | x | x | x | x | x | - | - | -| USE_PZEM004T | - | - | - | x | x | x | - | - | -| USE_PZEM_AC | - | - | - | x | x | x | - | - | -| USE_PZEM_DC | - | - | - | x | x | x | - | - | -| USE_MCP39F501 | - | x | - | x | x | x | - | - | -| USE_SDM120 | - | - | - | - | - | x | - | - | -| USE_SDM630 | - | - | - | - | - | x | - | - | -| USE_DDS2382 | - | - | - | - | - | x | - | - | -| USE_DDSU666 | - | - | - | - | - | x | - | - | -| USE_SOLAX_X1 | - | - | - | - | - | - | - | - | -| | | | | | | | | | -| USE_ADC_VCC | x | x | x | - | - | - | - | - | -| USE_COUNTER | - | - | - | x | x | x | x | x | -| USE_DS18x20 | - | - | x | x | x | x | - | x | -| USE_DHT | - | - | x | x | x | x | x | x | -| USE_MAX31855 | - | - | - | - | - | x | - | - | -| USE_MAX31865 | - | - | - | - | - | - | - | - | -| | | | | | | | | | -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | ir | display | Remarks -| USE_I2C | - | - | - | x | x | x | - | x | -| USE_SHT | - | - | - | x | x | x | - | x | -| USE_HTU | - | - | - | x | x | x | - | x | -| USE_BMP | - | - | - | x | x | x | - | x | -| USE_BME680 | - | - | - | - | - | x | - | - | -| USE_BH1750 | - | - | - | x | x | x | - | x | -| USE_VEML6070 | - | - | - | - | - | x | - | - | -| USE_ADS1115 | - | - | - | - | - | x | - | - | -| USE_ADS1115_I2CDEV | - | - | - | - | - | - | - | - | -| USE_INA219 | - | - | - | - | - | x | - | - | -| USE_INA226 | - | - | - | - | - | - | - | - | -| USE_SHT3X | - | - | - | x | x | x | - | x | -| USE_TSL2561 | - | - | - | - | - | x | - | - | -| USE_MGS | - | - | - | - | - | x | - | - | -| USE_SGP30 | - | - | - | x | x | x | - | x | -| USE_SI1145 | - | - | - | - | - | - | - | - | -| USE_LM75AD | - | - | - | x | x | x | - | x | -| USE_APDS9960 | - | - | - | - | - | - | - | - | -| USE_MCP230xx | - | - | - | - | - | - | - | - | -| USE_PCA9685 | - | - | - | - | - | - | - | - | -| USE_MPR121 | - | - | - | - | - | - | - | - | -| USE_CCS811 | - | - | - | - | - | - | - | - | -| USE_MPU6050 | - | - | - | - | - | - | - | - | -| USE_DS3231 | - | - | - | - | - | - | - | - | -| USE_MGC3130 | - | - | - | - | - | - | - | - | -| USE_MAX44009 | - | - | - | - | - | - | - | - | -| USE_SCD30 | - | - | - | - | - | x | - | - | -| USE_SPS30 | - | - | - | - | - | - | - | - | -| USE_ADE7953 | - | - | - | x | x | x | - | x | -| USE_VL53L0X | - | - | - | - | - | - | - | - | -| USE_MLX90614 | - | - | - | - | - | - | - | - | -| USE_CHIRP | - | - | - | - | - | - | - | - | -| USE_PAJ7620 | - | - | - | - | - | - | - | - | -| USE_PCF8574 | - | - | - | - | - | - | - | - | -| | | | | | | | | | -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | ir | display | Remarks -| USE_SPI | - | - | - | - | - | - | - | x | -| USE_MHZ19 | - | - | - | x | x | x | - | x | -| USE_SENSEAIR | - | - | - | x | x | x | - | x | -| USE_PMS5003 | - | - | - | x | x | x | - | x | -| USE_NOVA_SDS | - | - | - | x | x | x | - | x | -| USE_SERIAL_BRIDGE | - | - | - | x | x | x | - | x | -| USE_MP3_PLAYER | - | - | - | - | - | x | - | - | -| USE_AZ7798 | - | - | - | - | - | - | - | - | -| USE_PN532_HSU | - | - | - | - | - | x | - | - | -| USE_ZIGBEE | - | - | - | - | - | - | - | - | Experimental -| | | | | | | | | | -| USE_IR_REMOTE | - | - | - | x | x | x | x | x | -| USE_IR_HVAC | - | - | - | - | - | x | x | - | -| USE_IR_RECEIVE | - | - | - | x | x | x | x | x | -| | | | | | | | | | -| USE_SR04 | - | - | - | x | x | x | - | x | -| USE_TM1638 | - | - | - | - | - | x | - | - | -| USE_HX711 | - | - | - | x | x | x | - | x | -| USE_TX20_WIND_SENSOR | - | - | - | - | - | x | - | - | -| USE_RC_SWITCH | - | - | - | - | - | x | - | - | -| USE_RF_SENSOR | - | - | - | - | - | x | - | - | AlectoV2 only -| USE_HRE | - | - | - | - | - | x | - | - | -| USE_A4988_STEPPER | - | - | - | - | - | - | - | - | -| USE_ARDUINO_SLAVE | - | - | - | - | - | - | - | - | -| | | | | | | | | | -| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | ir | display | Remarks -| USE_DISPLAY | - | - | - | - | - | - | - | x | -| USE_DISPLAY_LCD | - | - | - | - | - | - | - | x | -| USE_DISPLAY_SSD1306 | - | - | - | - | - | - | - | x | -| USE_DISPLAY_MATRIX | - | - | - | - | - | - | - | x | -| USE_DISPLAY_SH1106 | - | - | - | - | - | - | - | x | -| USE_DISPLAY_ILI9341 | - | - | - | - | - | - | - | x | -| USE_DISPLAY_EPAPER_29 | - | - | - | - | - | - | - | x | Disabled for core 2.3.0 -| USE_DISPLAY_EPAPER_42 | - | - | - | - | - | - | - | x | Disabled for core 2.3.0 -| USE_DISPLAY_ILI9488 | - | - | - | - | - | - | - | - | -| USE_DISPLAY_SSD1351 | - | - | - | - | - | - | - | - | -| USE_DISPLAY_RA8876 | - | - | - | - | - | - | - | - | +| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks +|-----------------------|---------|-------|--------|-----|---------|----|---------|-------- +| MY_LANGUAGE en-GB | x | x | x | x | x | x | x | +| USE_ARDUINO_OTA | - | - | - | - | - | - | - | +| USE_DOMOTICZ | - | - | x | x | x | x | - | +| USE_HOME_ASSISTANT | - | - | x | x | x | x | - | +| USE_MQTT_TLS | - | - | - | - | - | - | - | +| USE_MQTT_TLS_CA_CERT | - | - | - | - | - | - | - | +| USE_MQTT_AWS_IOT | - | - | - | - | - | - | - | +| USE_KNX | - | - | - | x | - | - | - | +| USE_WEBSERVER | x | x | x | x | x | x | x | +| USE_JAVASCRIPT_ES6 | - | - | - | - | - | - | - | +| USE_WEBSEND_RESPONSE | - | - | - | - | - | - | - | +| USE_EMULATION_HUE | - | x | x | - | x | - | - | +| USE_EMULATION_WEMO | - | x | x | - | x | - | - | +| USE_DISCOVERY | - | - | x | x | - | - | x | +| WEBSERVER_ADVERTISE | - | - | x | x | - | - | x | +| MQTT_HOST_DISCOVERY | - | - | x | x | - | - | x | +| USE_TIMERS | - | x | x | x | x | x | x | +| USE_TIMERS_WEB | - | x | x | x | x | x | x | +| USE_SUNRISE | - | x | x | x | x | x | x | +| USE_RULES | - | x | x | x | x | x | x | +| USE_SCRIPT | - | - | - | - | - | - | - | +| USE_EXPRESSION | - | - | - | - | - | - | - | +| SUPPORT_IF_STATEMENT | - | - | - | - | - | - | - | +| | | | | | | | | +| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks +| ROTARY_V1 | - | - | - | - | - | - | - | +| USE_SONOFF_RF | - | - | x | x | x | - | - | +| USE_RF_FLASH | - | - | x | x | x | - | - | +| USE_SONOFF_SC | - | - | x | - | x | - | - | +| USE_TUYA_MCU | - | x | x | x | x | - | x | +| USE_ARMTRONIX_DIMMERS | - | - | x | x | - | - | - | +| USE_PS_16_DZ | - | - | x | x | x | - | - | +| USE_SONOFF_IFAN | - | - | x | x | x | - | - | +| USE_BUZZER | - | - | x | x | x | - | - | +| USE_ARILUX_RF | - | - | x | x | x | - | - | +| USE_SHUTTER | - | - | - | - | - | - | - | +| USE_DEEPSLEEP | - | - | - | - | - | - | - | +| USE_EXS_DIMMER | - | - | - | - | - | - | - | +| | | | | | | | | +| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks +| USE_LIGHT | - | x | x | x | x | x | x | +| USE_WS2812 | - | - | x | x | x | - | x | +| USE_WS2812_DMA | - | - | - | - | - | - | - | +| USE_MY92X1 | - | - | x | x | x | - | x | +| USE_SM16716 | - | - | x | x | x | - | x | +| USE_SM2135 | - | - | x | x | x | - | x | +| USE_SONOFF_L1 | - | - | x | x | x | - | x | +| | | | | | | | | +| USE_ENERGY_SENSOR | - | x | x | x | x | - | - | +| USE_PZEM004T | - | - | x | x | x | - | - | +| USE_PZEM_AC | - | - | x | x | x | - | - | +| USE_PZEM_DC | - | - | x | x | x | - | - | +| USE_MCP39F501 | - | x | x | x | x | - | - | +| USE_SDM120 | - | - | - | - | x | - | - | +| USE_SDM630 | - | - | - | - | x | - | - | +| USE_DDS2382 | - | - | - | - | x | - | - | +| USE_DDSU666 | - | - | - | - | x | - | - | +| USE_SOLAX_X1 | - | - | - | - | - | - | - | +| | | | | | | | | +| USE_ADC_VCC | x | x | - | - | - | - | - | +| USE_COUNTER | - | - | x | x | x | x | x | +| USE_DS18x20 | - | - | x | x | x | - | x | +| USE_DHT | - | - | x | x | x | x | x | +| USE_MAX31855 | - | - | - | - | x | - | - | +| USE_MAX31865 | - | - | - | - | - | - | - | +| | | | | | | | | +| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks +| USE_I2C | - | - | x | x | x | - | x | +| USE_SHT | - | - | x | x | x | - | x | +| USE_HTU | - | - | x | x | x | - | x | +| USE_BMP | - | - | x | x | x | - | x | +| USE_BME680 | - | - | - | - | x | - | - | +| USE_BH1750 | - | - | x | x | x | - | x | +| USE_VEML6070 | - | - | - | - | x | - | - | +| USE_ADS1115 | - | - | - | - | x | - | - | +| USE_ADS1115_I2CDEV | - | - | - | - | - | - | - | +| USE_INA219 | - | - | - | - | x | - | - | +| USE_INA226 | - | - | - | - | - | - | - | +| USE_SHT3X | - | - | x | x | x | - | x | +| USE_TSL2561 | - | - | - | - | x | - | - | +| USE_MGS | - | - | - | - | x | - | - | +| USE_SGP30 | - | - | x | x | x | - | x | +| USE_SI1145 | - | - | - | - | - | - | - | +| USE_LM75AD | - | - | x | x | x | - | x | +| USE_APDS9960 | - | - | - | - | - | - | - | +| USE_MCP230xx | - | - | - | - | - | - | - | +| USE_PCA9685 | - | - | - | - | - | - | - | +| USE_MPR121 | - | - | - | - | - | - | - | +| USE_CCS811 | - | - | - | - | - | - | - | +| USE_MPU6050 | - | - | - | - | - | - | - | +| USE_DS3231 | - | - | - | - | - | - | - | +| USE_MGC3130 | - | - | - | - | - | - | - | +| USE_MAX44009 | - | - | - | - | - | - | - | +| USE_SCD30 | - | - | - | - | x | - | - | +| USE_SPS30 | - | - | - | - | - | - | - | +| USE_ADE7953 | - | - | x | x | x | - | x | +| USE_VL53L0X | - | - | - | - | - | - | - | +| USE_MLX90614 | - | - | - | - | - | - | - | +| USE_CHIRP | - | - | - | - | - | - | - | +| USE_PAJ7620 | - | - | - | - | - | - | - | +| USE_PCF8574 | - | - | - | - | - | - | - | +| | | | | | | | | +| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks +| USE_SPI | - | - | - | - | - | - | x | +| USE_MHZ19 | - | - | x | x | x | - | x | +| USE_SENSEAIR | - | - | x | x | x | - | x | +| USE_PMS5003 | - | - | x | x | x | - | x | +| USE_NOVA_SDS | - | - | x | x | x | - | x | +| USE_SERIAL_BRIDGE | - | - | x | x | x | - | x | +| USE_MP3_PLAYER | - | - | - | - | x | - | - | +| USE_AZ7798 | - | - | - | - | - | - | - | +| USE_PN532_HSU | - | - | - | - | x | - | - | +| USE_ZIGBEE | - | - | - | - | - | - | - | Experimental +| | | | | | | | | +| USE_IR_REMOTE | - | - | x | x | x | x | x | +| USE_IR_HVAC | - | - | - | - | x | x | - | +| USE_IR_RECEIVE | - | - | x | x | x | x | x | +| | | | | | | | | +| USE_SR04 | - | - | x | x | x | - | x | +| USE_TM1638 | - | - | - | - | x | - | - | +| USE_HX711 | - | - | x | x | x | - | x | +| USE_TX20_WIND_SENSOR | - | - | - | - | x | - | - | +| USE_RC_SWITCH | - | - | - | - | x | - | - | +| USE_RF_SENSOR | - | - | - | - | x | - | - | AlectoV2 only +| USE_HRE | - | - | - | - | x | - | - | +| USE_A4988_STEPPER | - | - | - | - | - | - | - | +| USE_ARDUINO_SLAVE | - | - | - | - | - | - | - | Experimental +| | | | | | | | | +| Feature or Sensor | minimal | basic | sonoff | knx | sensors | ir | display | Remarks +| USE_DISPLAY | - | - | - | - | - | - | x | +| USE_DISPLAY_LCD | - | - | - | - | - | - | x | +| USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x | +| USE_DISPLAY_MATRIX | - | - | - | - | - | - | x | +| USE_DISPLAY_SH1106 | - | - | - | - | - | - | x | +| USE_DISPLAY_ILI9341 | - | - | - | - | - | - | x | +| USE_DISPLAY_EPAPER_29 | - | - | - | - | - | - | x | Disabled for core 2.3.0 +| USE_DISPLAY_EPAPER_42 | - | - | - | - | - | - | x | Disabled for core 2.3.0 +| USE_DISPLAY_ILI9488 | - | - | - | - | - | - | - | +| USE_DISPLAY_SSD1351 | - | - | - | - | - | - | - | +| USE_DISPLAY_RA8876 | - | - | - | - | - | - | - | ## Changelog -Version 6.6.0 20190707 - * Remove support of TLS on core 2.3.0 and extent support on core 2.4.2 and up - * Remove MQTT uptime message every hour - * Refactor some defines to const - * Refactor webserver HTML input, button, textarea, and select name based on id - * Refactor webserver sensor data collection - * Refactor TLS based on BearSSL, warning breaking change for fingerprints validation - * Refactor management of lights, using classes and integers instead of floats - * Refactor UDP initial message handling from string to char using static memory and add debug info (#5505) - * Refactor ``IRsend`` and receive for 64-bit support (#5523) - * Refactor MQTT which might solve issue (#5755) - * Refactor ``IRSend`` by using heap when more than 199 values need to be send. May need increase of define MQTT_MAX_PACKET_SIZE too (#5950) - * Refactor double to float in rules, and replaced trigonometric functions from stdlib with smaller versions (#6005) - * Change pubsubclient MQTT_KEEPALIVE from 10 to 30 seconds for AWS IoT support - * Change gamma correction as default behavior, ie "Ledtable 1" - * Change PWM resolution from 8 to 10 bits for low brightness lights - * Change ``IRSend`` Panasonic protocol to 64-bit (#5523) - * Change ADC0 to enabled by default in my_user_config.h (#5671) - * Change define USE_EMULATION by USE_EMULATION_HUE and USE_EMULATION_WEMO (#5826) - * Change default ``PowerDelta`` from 80% to 0% on new installations (#5858, #5028, #4813, #4130, #4145, #3795, #3778, #3660, #3648) - * Fix display Bug in KNX webmenu for Physical Address - * Fix the Unescape() function and the ``SendSerial3`` behaviour - * Fix webserver multiple Javascript window.onload functionality - * Fix TasmotaSerial at 9600 bps solving DFPlayer comms (#5528) - * Fix Configure Timer Web GUI (#5568) - * Fix Shelly 2.5 I2C address priority issue when VEML6070 code is present by disabling VEML6070 for Shelly 2.5 (#5592) - * Fix use of ``SerialDelimiter`` value 128 (#5634) - * Fix Sonoff Pow R2 / S31 invalid energy increments (#5789) - * Fix core 2.5.x ISR not in IRAM exception (#5837) - * Fix Philips Hue emulation Alexa issue by using part of MAC address for LightId (#5849) - * Fix missing white channel for WS2812 (#5869) - * Fix PZem startup issue (#5875) - * Fix exception 9 when syslog is enabled and NTP is just synced (#5917) - * Fix Toggle functionality to button double press when one button and two devices are detected (#5935) - * Fix command ``Channel`` for dual dimmers (#5940) - * Fix not restoring white value on power off/power on (#5993) - * Add command ``AdcParam`` to control ADC0 Temperature and Light formula parameters - * Add command ``LedMask`` to assign which relay has access to power LED (#5602, #5612) - * Add extended LED power control using command ``LedPowerX`` where X is 1 to 4. Enabled when "LedLink(i)" is configured too (#5709) - * Add command ``Sensor20 1..255`` to change Nova Fitness SDS01 working period in minutes (#5452) - * Add command ``SetOption38 6..255`` to set IRReceive protocol detection sensitivity mimizing UNKNOWN protocols (#5853) - * Add command ``SetOption39 1..255`` to control CSE7766 (Pow R2) or HLW8032 (Blitzwolf SHP5) handling of power loads below 6W. Default setting is 128 (#5756) - * Add command ``SetOption40 0..250`` to disable button functionality if activated for over 0.1 second. Needs SetOption1 1 and SetOption13 0 (#5449) - * Add command ``SetOption63 0/1`` to disable relay state feedback scan at restart (#5594, #5663) - * Add command ``SetOption64 0/1`` to switch between "-" or "_" as sensor index separator impacting DS18X20, DHT, BMP and SHT3X sensor names (#5689) - * Add command ``SetOption65 0/1`` and more Tuya Serial based device support (#5815) - * Add command ``WebColor`` to change GUI colors on the fly - * Add support for AWS IoT with TLS 1.2 on core 2.4.2 and up. Full doc here: https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT - * Add support for Badger HR-E Water Meter (#5539) - * Add support for Shelly 2.5 Energy and overtemp Monitoring (#5592) - * Add support for color and colortone for Philips Hue emulation via Alexa (#5600 #4809) - * Add support for Scripts as replacement for Rules. Default disabled but can be enabled in my_user_config.h (#5689) - * Add support for up to four LEDs related to four power outputs. Enabled when "LedLink(i)" is configured too (#5709) - * Add support for Shelly 1PM Template ``{"NAME":"Shelly 1PM","GPIO":[56,0,0,0,82,134,0,0,0,0,0,21,0],"FLAG":2,"BASE":18}`` (#5716) - * Add support for SPS30 Particle sensor thanks to Gerhard Mutz (#5830) - * Add support for VL53L0x time of flight sensor. Might interfere with TSL2561 using same I2C address (#5845) - * Add support for Sonoff L1 thanks to reef-actor (#6002) - * Add rule Http#Initialized - * Add rule System#Save executed just before a planned restart - * Add rule support for single JSON value pair like {"SSerialReceived":"on"} by expanding it to {"SSerialReceived":{"Data":"on"}} allowing for trigger SSerialReceived#Data=on (#5638) - * Add define USE_COUNTER to my_user_config.h to save space in sonoff-basic.bin and sonoff-minimal.bin - * Add define USE_DHT to my_user_config.h to save space in sonoff-basic.bin - * Add defines USE_EMULATION_WEMO and USE_EMULATION_HUE to my_user_config.h to control emulation features at compile time (#5826) - * Add Toggle functionality to button double press when more devices are detected - * Add device OverTemp (>73 Celsius) detection to Energy Monitoring devices with temperature sensor powering off all outputs - * Add Tuya Dimmer 10 second heartbeat serial packet required by some Tuya dimmer secondary MCUs - * Add all temperature, humidity and pressure for global access - * Add validation check when loading settings from flash - * Add HX711 weight restore after controlled restart or after power restore just before executing command Sensor34 7 (#5367, #5786) - * Add GUI hexadecimal color options in my_user_config.h (#5586) - * Add alternative ``IRSend`` command syntax ``IRSend raw,,
,
,,,,`` (#5610) - * Add user configurable ADC0 to Module and Template configuration compatible with current FLAG options (#5671) - * Add AriLux RF control GPIO option "ALux IrSel" (159) replacing "Led4i" (59) for full LED control (#5709) - * Add LED GPIO option "LedLink" (157) and "LedLinki" (158) to select dedicated link status LED (#5709) - * Add all 5 PWM channels individually adressable with LEDs. (#5741) - * Add reset of Energy values when connection to sensor is lost for over 4 seconds (#5874, #5881) - * Add checkbox to GUI password field enabling visibility during password entry only (#5934) \ No newline at end of file +Version 6.7.0 20191101 + * TBS diff --git a/platformio.ini b/platformio.ini index b081f3990..65f11515d 100755 --- a/platformio.ini +++ b/platformio.ini @@ -17,7 +17,6 @@ build_cache_dir = .cache ;default_envs = sonoff-ircustom ; alternative to 'sonoff' with full IR protocols activated, you will need to disable some features to keep code not too big ;default_envs = sonoff-minimal ;default_envs = sonoff-basic -;default_envs = sonoff-classic ;default_envs = sonoff-knx ;default_envs = sonoff-sensors ;default_envs = sonoff-display @@ -212,7 +211,6 @@ build_flags = ${core_active.build_flags} ; -DDEBUG_TASMOTA_SENSOR ; *** Optional Firmware configurations -; -DFIRMWARE_CLASSIC ; -DFIRMWARE_MINIMAL ; -DFIRMWARE_SENSORS ; -DFIRMWARE_BASIC @@ -290,20 +288,6 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -[env:sonoff-classic] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DFIRMWARE_CLASSIC -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - [env:sonoff-knx] platform = ${common.platform} framework = ${common.framework} diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 65820ecdf..554cd44b5 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ /*********************************************************************************************\ + * 6.6.0.21 20191022 + * Remove support for WPS and SmartConfig in favour of Web server (!) based WifiManager (#6680) + * Remove binary sonoff-classic (#6680) + * * 6.6.0.20 20191018 * Add command SetOption65 0/1 to disable (1) fast power cycle detection fixing unwanted brownout trigger * Add absolute PowerDelta using command PowerDelta 101..32000 where 101 = 101-100 = 1W, 202 = 202-100 = 102W (#5901) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 76e00d35e..41b42983a 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -258,9 +258,7 @@ #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_WCFG_6_SERIAL "Serial" @@ -599,16 +597,16 @@ const char S_OFFLINE[] PROGMEM = D_OFFLINE; // sonoff.ino #define MAX_BUTTON_COMMANDS 5 // Max number of button commands supported const char kCommands[MAX_BUTTON_COMMANDS][14] PROGMEM = { - D_CMND_WIFICONFIG " 1", // Press button three times + D_CMND_WIFICONFIG " 2", // Press button three times D_CMND_WIFICONFIG " 2", // Press button four times - D_CMND_WIFICONFIG " 3", // Press button five times + D_CMND_WIFICONFIG " 2", // Press button five times D_CMND_RESTART " 1", // Press button six times D_CMND_UPGRADE " 1" }; // Press button seven times 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_2_WIFIMANAGER, + D_WCFG_2_WIFIMANAGER, D_WCFG_4_RETRY, D_WCFG_5_WAIT, D_WCFG_6_SERIAL, @@ -618,7 +616,7 @@ const char kPrefixes[3][PRFX_MAX_STRING_LENGTH] PROGMEM = { D_STAT, D_TELE }; -const char kCodeImage[] PROGMEM = "sonoff|minimal|classic|sensors|knx|basic|display|ir"; +const char kCodeImage[] PROGMEM = "sonoff|minimal|sensors|knx|basic|display|ir"; // support.ino static const char kMonthNames[] = D_MONTH3LIST; diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 4c41c48d8..cb067fbf7 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -67,13 +67,8 @@ #define STA_SSID2 "" // [Ssid2] Optional alternate AP Wifi SSID #define STA_PASS2 "" // [Password2] Optional alternate AP Wifi password #define WIFI_CONFIG_TOOL WIFI_RETRY // [WifiConfig] Default tool if wifi fails to connect (default option: 4 - WIFI_RETRY) - // (WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, WIFI_MANAGER_RESET_ONLY) - // The configuration can be changed after first setup using WifiConfig 0, 1, 2, 3, 4, 5, 6 and 7. -#define WIFI_CONFIG_NO_SSID WIFI_WPSCONFIG // Default tool if wifi fails to connect and no SSID is configured - // (WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_SERIAL) - // *** NOTE: When WPS is disabled by USE_WPS below, WIFI_WPSCONFIG will execute WIFI_MANAGER *** - // *** NOTE: When WIFI_MANAGER is disabled by USE_WEBSERVER below, WIFI_MANAGER will execute WIFI_SMARTCONFIG *** - // *** NOTE: When WIFI_SMARTCONFIG is disabled by USE_SMARTCONFIG below, WIFI_SMARTCONFIG will execute WIFI_SERIAL *** + // (WIFI_RESTART, WIFI_MANAGER, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, WIFI_MANAGER_RESET_ONLY) + // The configuration can be changed after first setup using WifiConfig 0, 2, 4, 5, 6 and 7. // -- Syslog -------------------------------------- #define SYS_LOG_HOST "" // [LogHost] (Linux) syslog host @@ -246,8 +241,6 @@ // -- Wifi Config tools --------------------------- #define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI -//#define USE_WPS // Add support for WPS as initial wifi configuration tool (+33k code, 1k mem (5k mem with core v2.4.2+)) -//#define USE_SMARTCONFIG // Add support for Wifi SmartConfig as initial wifi configuration tool (+23k code, +0.6k mem) // -- OTA ----------------------------------------- //#define USE_ARDUINO_OTA // Add optional support for Arduino OTA (+13k code) @@ -562,7 +555,6 @@ * See RELEASENOTES.md for selected features \*********************************************************************************************/ -//#define FIRMWARE_CLASSIC // Create sonoff-classic with initial configuration tools WPS, SmartConfig and WifiManager //#define FIRMWARE_BASIC // Create sonoff-basic with no sensors //#define FIRMWARE_SENSORS // Create sonoff-sensors with useful sensors enabled //#define FIRMWARE_KNX_NO_EMULATION // Create sonoff-knx with KNX but without Emulation diff --git a/sonoff/settings.ino b/sonoff/settings.ino index aa8646142..0a34123df 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -1213,6 +1213,11 @@ void SettingsDelta(void) Settings.energy_power_delta = Settings.ex_energy_power_delta; Settings.ex_energy_power_delta = 0; } + if (Settings.version < 0x06060015) { + if ((EX_WIFI_SMARTCONFIG == Settings.sta_config) || (EX_WIFI_WPSCONFIG == Settings.sta_config)) { + Settings.sta_config = WIFI_MANAGER; + } + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index c5e801564..40b3dcb98 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -145,8 +145,6 @@ const uint32_t LOOP_SLEEP_DELAY = 50; // Lowest number of milliseconds to #define MAX_RULE_TIMERS 8 // Max number of rule timers (4 bytes / timer) #define MAX_RULE_VARS 5 // Max number of rule variables (10 bytes / variable) -#define NO_EXTRA_4K_HEAP // Allocate 4k heap for WPS in ESP8166/Arduino core v2.4.2 (was always allocated in previous versions) - /* // Removed from esp8266 core since 20171105 #define min(a,b) ((a)<(b)?(a):(b)) @@ -224,7 +222,7 @@ enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_RESTART, DT_ENERGY }; enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; -enum WifiConfigOptions {WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, WIFI_MANAGER_RESET_ONLY, MAX_WIFI_OPTION}; +enum WifiConfigOptions {WIFI_RESTART, EX_WIFI_SMARTCONFIG, WIFI_MANAGER, EX_WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, WIFI_MANAGER_RESET_ONLY, MAX_WIFI_OPTION}; enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION}; diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 6e2bd7390..74be27fdb 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -24,18 +24,17 @@ * Function declarations \*********************************************************************************************/ +/* #ifdef __cplusplus extern "C" { #endif #include "user_interface.h" -// Function prototypes -void WifiWpsStatusCallback(wps_cb_status status); - #ifdef __cplusplus } #endif +*/ //#ifdef USE_KNX // Enabling this will fail compilation. It has no impact if not used. (20180417) #include @@ -81,7 +80,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #ifdef FIRMWARE_SENSORS #undef CODE_IMAGE -#define CODE_IMAGE 3 +#define CODE_IMAGE 2 #undef USE_DISCOVERY // Disable mDNS (+8k code or +23.5k code with core 2_5_x, +0.3k mem) @@ -217,108 +216,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_SENSORS -/*********************************************************************************************\ - * [sonoff-classic.bin] - * Provide an image close to version 5.12.0 but still within 499k program space to allow one time OTA -\*********************************************************************************************/ - -#ifdef FIRMWARE_CLASSIC - -#undef CODE_IMAGE -#define CODE_IMAGE 2 - -#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices -#ifndef USE_WPS -#define USE_WPS // Add support for WPS as initial wifi configuration tool (+33k code, 1k mem (5k mem with core v2.4.2+)) -#endif -#ifndef USE_SMARTCONFIG -#define USE_SMARTCONFIG // Add support for Wifi SmartConfig as initial wifi configuration tool (+23k code, +0.6k mem) -#endif -#undef USE_ARDUINO_OTA // Disable support for Arduino OTA -//#undef USE_DOMOTICZ // Disable Domoticz -#undef USE_HOME_ASSISTANT // Disable Home Assistant -#undef USE_KNX // Disable KNX IP Protocol Support -#undef USE_CUSTOM // Disable Custom features -#undef USE_TIMERS // Disable support for up to 16 timers -#undef USE_TIMERS_WEB // Disable support for timer webpage -#undef USE_SUNRISE // Disable support for Sunrise and sunset tools -#undef USE_RULES // Disable support for rules -#undef USE_SCRIPT // Disable support for script (+17k code) - -// -- Optional modules ---------------------------- -#undef ROTARY_V1 // Disable support for MI Desk Lamp -#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code) - #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB -#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code) -#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU -#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) -#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) -#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) -#undef USE_BUZZER // Disable support for a buzzer (+0k6 code) -#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller -#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) -#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) -#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer - -// -- Optional light modules ---------------------- -//#undef USE_LIGHT // Disable Dimmer/Light support -#define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // -// #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_HARDWARE NEO_HW_WS2812 // Hardware type (NEO_HW_WS2812, NEO_HW_WS2812X, NEO_HW_WS2813, NEO_HW_SK6812, NEO_HW_LC8812, NEO_HW_APA106) - #define USE_WS2812_CTYPE NEO_GRB // Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW) -#undef USE_MY92X1 // Disable support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas -#undef USE_SM16716 // Disable support for SM16716 RGB LED controller (+0k7 code) -#undef USE_SM2135 // Disable support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) -#undef USE_SONOFF_L1 // Disable support for Sonoff L1 led control - -#undef USE_COUNTER // Disable counters -#define USE_DS18x20 // Add support for DS18x20 sensors with id sort, single scan and read retry (+2k6 code) -#undef USE_I2C // Disable all I2C sensors -#undef USE_SPI // Disable all SPI devices - -#undef USE_MHZ19 // Disable support for MH-Z19 CO2 sensor -#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor -#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor -#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor -#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge -#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop -#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger -#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) -#undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8) -#undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) - -//#undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) -#undef USE_PZEM004T // Disable PZEM004T energy sensor -#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor -#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor -#undef USE_MCP39F501 // Disable support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) -#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter -#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) -#undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) -#undef USE_DDSU666 // Disable support for Chint DDSU666 Modbus energy monitor (+0k6 code) -#undef USE_SOLAX_X1 // Disable support for Solax X1 series Modbus log info (+3k1 code) - -#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor -#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI -#undef USE_MAX31865 // Disable support for MAX31865 RTD sensors using softSPI -#undef USE_IR_REMOTE // Disable IR remote commands using library IRremoteESP8266 and ArduinoJson -#undef USE_IR_RECEIVE // Disable support for IR receiver - -#undef USE_ZIGBEE // Disable serial communication with Zigbee CC2530 flashed with ZNP - -#undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices -#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 -#undef USE_HX711 // Disable support for HX711 load cell -#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer -#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch -#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) -#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) -#undef USE_A4988_STEPPER // Disable support for A4988_Stepper -#undef USE_ARDUINO_SLAVE // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) -#undef DEBUG_THEO // Disable debug code -#undef USE_DEBUG_DRIVER // Disable debug code -#endif // FIRMWARE_CLASSIC - /*********************************************************************************************\ * [sonoff-knx.bin] * Provide a dedicated KNX image allowing enough code and memory space @@ -327,7 +224,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #ifdef FIRMWARE_KNX_NO_EMULATION #undef CODE_IMAGE -#define CODE_IMAGE 4 +#define CODE_IMAGE 3 #ifndef USE_KNX #define USE_KNX // Enable KNX IP Protocol Support (+23k code, +3k3 mem) @@ -347,7 +244,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #ifdef FIRMWARE_DISPLAYS #undef CODE_IMAGE -#define CODE_IMAGE 6 +#define CODE_IMAGE 5 #undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) #undef USE_EMULATION_HUE // Disable Hue Bridge emulation for Alexa (+14k code, +2k mem common) @@ -411,7 +308,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #ifdef FIRMWARE_IR #undef CODE_IMAGE -#define CODE_IMAGE 7 +#define CODE_IMAGE 6 #undef USE_EMULATION #undef USE_EMULATION_HUE // Disable Hue emulation - only for lights and relays @@ -501,13 +398,11 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #ifdef FIRMWARE_BASIC #undef CODE_IMAGE -#define CODE_IMAGE 5 +#define CODE_IMAGE 4 #undef APP_SLEEP #define APP_SLEEP 1 // Default to sleep = 1 for FIRMWARE_BASIC -#undef USE_WPS // Disable support for WPS as initial wifi configuration tool -#undef USE_SMARTCONFIG // Disable support for Wifi SmartConfig as initial wifi configuration tool #undef USE_ARDUINO_OTA // Disable support for Arduino OTA #undef USE_DOMOTICZ // Disable Domoticz #undef USE_HOME_ASSISTANT // Disable Home Assistant @@ -607,8 +502,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef CODE_IMAGE #define CODE_IMAGE 1 -#undef USE_WPS // Disable support for WPS as initial wifi configuration tool -#undef USE_SMARTCONFIG // Disable support for Wifi SmartConfig as initial wifi configuration tool #undef USE_ARDUINO_OTA // Disable support for Arduino OTA #undef USE_DOMOTICZ // Disable Domoticz #undef USE_HOME_ASSISTANT // Disable Home Assistant @@ -701,9 +594,8 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c * Mandatory defines satisfying possible disabled defines \*********************************************************************************************/ -#ifndef USE_WPS // See https://github.com/esp8266/Arduino/pull/4889 + // See https://github.com/esp8266/Arduino/pull/4889 #undef NO_EXTRA_4K_HEAP // Allocate 4k heap for WPS in ESP8166/Arduino core v2.4.2 (was always allocated in previous versions) -#endif #ifndef USE_SONOFF_RF #undef USE_RF_FLASH // Disable RF firmware flash when SOnoff Rf is disabled @@ -714,7 +606,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif #ifndef STARTING_OFFSET // NOVA SDS parameter used in settings -#define STARTING_OFFSET 30 +#define STARTING_OFFSET 30 #endif #ifndef MQTT_FINGERPRINT1 diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 062d4dedf..22e12ed7b 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06060014; +const uint32_t VERSION = 0x06060015; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index 5c8db5d09..255422082 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -224,7 +224,7 @@ void ButtonHandler(void) } else { if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS +3)) { bool single_press = false; - if (Button.press_counter[button_index] < 3) { // Single or Double press + if (Button.press_counter[button_index] < 3) { // Single or Double press if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { single_press = true; } else { @@ -244,8 +244,8 @@ void ButtonHandler(void) if (single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set // Success } else { - if (Button.press_counter[button_index] < 3) { // Single or Double press - if (WifiState() > WIFI_RESTART) { // WPSconfig, Smartconfig or Wifimanager active + if (Button.press_counter[button_index] < 3) { // Single or Double press + if (WifiState() > WIFI_RESTART) { // Wifimanager active restart_flag = 1; } else { ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 5aa59f592..638930d21 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -113,10 +113,10 @@ void GetFeatures(void) feature_drv1 |= 0x10000000; // xdrv_11_knx.ino #endif #ifdef USE_WPS - feature_drv1 |= 0x20000000; // support.ino + feature_drv1 |= 0x20000000; // support.ino - removed with version 6.6.0.21 #endif #ifdef USE_SMARTCONFIG - feature_drv1 |= 0x40000000; // support.ino + feature_drv1 |= 0x40000000; // support.ino - removed with version 6.6.0.21 #endif #ifdef USE_ENERGY_POWER_LIMIT feature_drv1 |= 0x80000000; // xdrv_03_energy.ino diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 5e526198d..23727fcbe 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -45,7 +45,6 @@ struct WIFI { uint8_t retry_init; uint8_t retry; uint8_t status; - uint8_t wps_result; uint8_t config_type = 0; uint8_t config_counter = 0; uint8_t mdns_begun = 0; // mDNS active @@ -75,46 +74,9 @@ bool WifiConfigCounter(void) return (Wifi.config_counter); } -extern "C" { -#include "user_interface.h" -} - -void WifiWpsStatusCallback(wps_cb_status status); - -void WifiWpsStatusCallback(wps_cb_status status) -{ -/* from user_interface.h: - enum wps_cb_status { - WPS_CB_ST_SUCCESS = 0, - WPS_CB_ST_FAILED, - WPS_CB_ST_TIMEOUT, - WPS_CB_ST_WEP, // WPS failed because that WEP is not supported - WPS_CB_ST_SCAN_ERR, // can not find the target WPS AP - }; -*/ - Wifi.wps_result = status; - if (WPS_CB_ST_SUCCESS == Wifi.wps_result) { - wifi_wps_disable(); - } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_WPS_FAILED_WITH_STATUS " %d"), Wifi.wps_result); - Wifi.config_counter = 2; - } -} - -bool WifiWpsConfigDone(void) -{ - return (!Wifi.wps_result); -} - -bool WifiWpsConfigBegin(void) -{ - Wifi.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) &WifiWpsStatusCallback)) { return false; } - if (!wifi_wps_start()) { return false; } - return true; -} +//extern "C" { +//#include "user_interface.h" +//} void WifiConfig(uint8_t type) { @@ -126,15 +88,11 @@ void WifiConfig(uint8_t type) WiFi.disconnect(); // Solve possible Wifi hangs Wifi.config_type = type; -#ifndef USE_WPS - if (WIFI_WPSCONFIG == Wifi.config_type) { Wifi.config_type = WIFI_MANAGER; } -#endif // USE_WPS #ifndef USE_WEBSERVER - if (WIFI_MANAGER == Wifi.config_type) { Wifi.config_type = WIFI_SMARTCONFIG; } + if (WIFI_MANAGER == Wifi.config_type) { + Wifi.config_type = WIFI_SERIAL; + } #endif // USE_WEBSERVER -#ifndef USE_SMARTCONFIG - if (WIFI_SMARTCONFIG == Wifi.config_type) { Wifi.config_type = WIFI_SERIAL; } -#endif // USE_SMARTCONFIG 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; @@ -145,23 +103,6 @@ void WifiConfig(uint8_t type) else if (WIFI_SERIAL == Wifi.config_type) { AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_6_SERIAL " " D_ACTIVE_FOR_3_MINUTES)); } -#ifdef USE_SMARTCONFIG - else if (WIFI_SMARTCONFIG == Wifi.config_type) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_1_SMARTCONFIG " " D_ACTIVE_FOR_3_MINUTES)); - WiFi.mode(WIFI_STA); // Disable AP mode - WiFi.beginSmartConfig(); - } -#endif // USE_SMARTCONFIG -#ifdef USE_WPS - 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_3_MINUTES)); - } else { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_3_WPSCONFIG " " D_FAILED_TO_START)); - Wifi.config_counter = 3; - } - } -#endif // USE_WPS #ifdef USE_WEBSERVER else if (WIFI_MANAGER == Wifi.config_type || WIFI_MANAGER_RESET_ONLY == Wifi.config_type) { AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_2_WIFIMANAGER " " D_ACTIVE_FOR_3_MINUTES)); @@ -452,7 +393,7 @@ void WifiCheckIp(void) AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); } else { if (('\0' == Settings.sta_ssid[0][0]) && ('\0' == Settings.sta_ssid[1][0])) { - wifi_config_tool = WIFI_CONFIG_NO_SSID; // Skip empty SSIDs and start Wifi config tool + wifi_config_tool = WIFI_MANAGER; // Skip empty SSIDs and start Wifi config tool Wifi.retry = 0; } else { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_ATTEMPTING_CONNECTION)); @@ -487,9 +428,7 @@ void WifiCheck(uint8_t param) Wifi.counter--; switch (param) { case WIFI_SERIAL: - case WIFI_SMARTCONFIG: case WIFI_MANAGER: - case WIFI_WPSCONFIG: WifiConfig(param); break; default: @@ -497,16 +436,6 @@ void WifiCheck(uint8_t param) Wifi.config_counter--; Wifi.counter = Wifi.config_counter +5; if (Wifi.config_counter) { -#ifdef USE_SMARTCONFIG - if ((WIFI_SMARTCONFIG == Wifi.config_type) && WiFi.smartConfigDone()) { - Wifi.config_counter = 0; - } -#endif // USE_SMARTCONFIG -#ifdef USE_WPS - if ((WIFI_WPSCONFIG == Wifi.config_type) && WifiWpsConfigDone()) { - Wifi.config_counter = 0; - } -#endif // USE_WPS if (!Wifi.config_counter) { if (strlen(WiFi.SSID().c_str())) { strlcpy(Settings.sta_ssid[0], WiFi.SSID().c_str(), sizeof(Settings.sta_ssid[0])); @@ -515,13 +444,10 @@ void WifiCheck(uint8_t param) strlcpy(Settings.sta_pwd[0], WiFi.psk().c_str(), sizeof(Settings.sta_pwd[0])); } Settings.sta_active = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_1_SMARTCONFIG D_CMND_SSID "1 %s"), Settings.sta_ssid[0]); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_2_WIFIMANAGER D_CMND_SSID "1 %s"), Settings.sta_ssid[0]); } } if (!Wifi.config_counter) { -#ifdef USE_SMARTCONFIG - if (WIFI_SMARTCONFIG == Wifi.config_type) { WiFi.stopSmartConfig(); } -#endif // USE_SMARTCONFIG // SettingsSdkErase(); // Disabled v6.1.0b due to possible bad wifi connects restart_flag = 2; } diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index b1037bdfd..1f3fc3733 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -28,7 +28,7 @@ #define XDRV_01 1 #ifndef WIFI_SOFT_AP_CHANNEL -#define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by SmartConfig web GUI +#define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by WifiManager web GUI #endif const uint16_t CHUNKED_BUFFER_SIZE = 400; // Chunk buffer size (should be smaller than half mqtt_date size) @@ -2043,9 +2043,9 @@ void HandleUploadDone(void) } else { // It was a normal firmware file, or we are ready to restart device restart_flag = 2; } -#else +#else restart_flag = 2; // Always restart to re-enable disabled features during update -#endif +#endif } SettingsBufferFree(); WSContentSend_P(PSTR("

")); @@ -2055,7 +2055,7 @@ void HandleUploadDone(void) if (ArduinoSlave_GetFlagFlashing()) { ArduinoSlave_Flash(); } -#endif +#endif } void HandleUploadLoop(void) diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index 764be681a..797cdba8f 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -575,11 +575,7 @@ void TuyaSetWifiLed(void) { uint8_t wifi_state = 0x02; switch(WifiState()){ - case WIFI_SMARTCONFIG: - wifi_state = 0x00; - break; case WIFI_MANAGER: - case WIFI_WPSCONFIG: wifi_state = 0x01; break; case WIFI_RESTART: diff --git a/sonoff/xdrv_18_armtronix_dimmers.ino b/sonoff/xdrv_18_armtronix_dimmers.ino index 88860c853..abf366c14 100644 --- a/sonoff/xdrv_18_armtronix_dimmers.ino +++ b/sonoff/xdrv_18_armtronix_dimmers.ino @@ -140,11 +140,7 @@ void ArmtronixSetWifiLed(void) uint8_t wifi_state = 0x02; switch (WifiState()) { - case WIFI_SMARTCONFIG: - wifi_state = 0x00; - break; case WIFI_MANAGER: - case WIFI_WPSCONFIG: wifi_state = 0x01; break; case WIFI_RESTART: From bd260a2f40a33b905263f69233bd1875f6de8c9e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 22 Oct 2019 16:46:07 +0200 Subject: [PATCH 2214/2222] Fix command WifiConfig --- sonoff/support_command.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index a3cf45f69..13f132adb 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -1186,6 +1186,9 @@ void CmndWifiConfig(void) { char stemp1[TOPSZ]; if ((XdrvMailbox.payload >= WIFI_RESTART) && (XdrvMailbox.payload < MAX_WIFI_OPTION)) { + if ((EX_WIFI_SMARTCONFIG == XdrvMailbox.payload) || (EX_WIFI_WPSCONFIG == XdrvMailbox.payload)) { + XdrvMailbox.payload = WIFI_MANAGER; + } Settings.sta_config = XdrvMailbox.payload; wifi_state_flag = Settings.sta_config; snprintf_P(stemp1, sizeof(stemp1), kWifiConfig[Settings.sta_config]); From 98680336544e09982b825b202c1bd814fc116ccb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 22 Oct 2019 17:29:21 +0200 Subject: [PATCH 2215/2222] Refactor string code --- sonoff/i18n.h | 74 ++++---------------------------------- sonoff/sonoff.ino | 7 ++-- sonoff/support_button.ino | 6 +++- sonoff/support_command.ino | 12 +++---- 4 files changed, 21 insertions(+), 78 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 41b42983a..3f19f67dd 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -256,7 +256,6 @@ #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_2_WIFIMANAGER "WifiManager" #define D_WCFG_4_RETRY "Retry" @@ -303,7 +302,6 @@ #define D_CMND_TLSKEY "TLSKey" #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" @@ -505,49 +503,13 @@ // Common enum UnitNames { - UNIT_AMPERE, - UNIT_HOUR, - UNIT_KILOOHM, - UNIT_KILOWATTHOUR, - UNIT_LUX, - UNIT_MICROSECOND, - UNIT_MILLIAMPERE, - UNIT_MILLIMETER_MERCURY, - UNIT_MILLISECOND, - UNIT_MINUTE, - UNIT_PPB, - UNIT_PPD, - UNIT_PPM, - UNIT_PERCENTAGE, - UNIT_PRESSURE, - UNIT_SECOND, - UNIT_SECTORS, - UNIT_VOLT, - UNIT_WATT, - UNIT_WATTHOUR, - UNIT_HERTZ }; + UNIT_AMPERE, UNIT_HOUR, UNIT_KILOOHM, UNIT_KILOWATTHOUR, UNIT_LUX, UNIT_MICROSECOND, UNIT_MILLIAMPERE, UNIT_MILLIMETER_MERCURY, + UNIT_MILLISECOND, UNIT_MINUTE, UNIT_PPB, UNIT_PPD, UNIT_PPM, UNIT_PERCENTAGE, UNIT_PRESSURE, UNIT_SECOND, + UNIT_SECTORS, UNIT_VOLT, UNIT_WATT, UNIT_WATTHOUR, UNIT_HERTZ }; const char kUnitNames[] PROGMEM = - D_UNIT_AMPERE "|" - D_UNIT_HOUR "|" - D_UNIT_KILOOHM "|" - D_UNIT_KILOWATTHOUR "|" - D_UNIT_LUX "|" - D_UNIT_MICROSECOND "|" - D_UNIT_MILLIAMPERE "|" - D_UNIT_MILLIMETER_MERCURY "|" - D_UNIT_MILLISECOND "|" - D_UNIT_MINUTE "|" - D_UNIT_PARTS_PER_BILLION "|" - D_UNIT_PARTS_PER_DECILITER "|" - D_UNIT_PARTS_PER_MILLION "|" - "%|" - D_UNIT_PRESSURE "|" - D_UNIT_SECOND "|" - D_UNIT_SECTORS "|" - D_UNIT_VOLT "|" - D_UNIT_WATT "|" - D_UNIT_WATTHOUR "|" - D_UNIT_HERTZ ; + D_UNIT_AMPERE "|" D_UNIT_HOUR "|" D_UNIT_KILOOHM "|" D_UNIT_KILOWATTHOUR "|" D_UNIT_LUX "|" D_UNIT_MICROSECOND "|" D_UNIT_MILLIAMPERE "|" D_UNIT_MILLIMETER_MERCURY "|" + D_UNIT_MILLISECOND "|" D_UNIT_MINUTE "|" D_UNIT_PARTS_PER_BILLION "|" D_UNIT_PARTS_PER_DECILITER "|" D_UNIT_PARTS_PER_MILLION "|%|" D_UNIT_PRESSURE "|" D_UNIT_SECOND "|" + D_UNIT_SECTORS "|" D_UNIT_VOLT "|" D_UNIT_WATT "|" D_UNIT_WATTHOUR "|" D_UNIT_HERTZ ; const char S_JSON_COMMAND_NVALUE_SPACE_UNIT[] PROGMEM = "{\"%s\":\"%d %s\"}"; const char S_JSON_COMMAND_LVALUE_SPACE_UNIT[] PROGMEM = "{\"%s\":\"%lu %s\"}"; @@ -594,30 +556,6 @@ const char S_RSLT_WARNING[] PROGMEM = D_RSLT_WARNING; const char S_LWT[] PROGMEM = D_LWT; const char S_OFFLINE[] PROGMEM = D_OFFLINE; -// sonoff.ino -#define MAX_BUTTON_COMMANDS 5 // Max number of button commands supported -const char kCommands[MAX_BUTTON_COMMANDS][14] PROGMEM = { - D_CMND_WIFICONFIG " 2", // Press button three times - D_CMND_WIFICONFIG " 2", // Press button four times - D_CMND_WIFICONFIG " 2", // Press button five times - D_CMND_RESTART " 1", // Press button six times - D_CMND_UPGRADE " 1" }; // Press button seven times -const char kWifiConfig[MAX_WIFI_OPTION][WCFG_MAX_STRING_LENGTH] PROGMEM = { - D_WCFG_0_RESTART, - D_WCFG_2_WIFIMANAGER, - D_WCFG_2_WIFIMANAGER, - D_WCFG_2_WIFIMANAGER, - D_WCFG_4_RETRY, - D_WCFG_5_WAIT, - D_WCFG_6_SERIAL, - D_WCFG_7_WIFIMANAGER_RESET_ONLY }; -const char kPrefixes[3][PRFX_MAX_STRING_LENGTH] PROGMEM = { - D_CMND, - D_STAT, - D_TELE }; - -const char kCodeImage[] PROGMEM = "sonoff|minimal|sensors|knx|basic|display|ir"; - // support.ino static const char kMonthNames[] = D_MONTH3LIST; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index d6fc706f7..18afb76c7 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -70,6 +70,8 @@ #include "settings.h" const char kSleepMode[] PROGMEM = "Dynamic|Normal"; +const char kPrefixes[] PROGMEM = D_CMND "|" D_STAT "|" D_TELE; +const char kCodeImage[] PROGMEM = "sonoff|minimal|sensors|knx|basic|display|ir"; // Global variables SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit @@ -248,7 +250,8 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi snprintf_P(romram, sizeof(romram), subtopic); if (fallback_topic_flag || (prefix > 3)) { prefix &= 3; - fulltopic = FPSTR(kPrefixes[prefix]); + char stemp[11]; + fulltopic = GetTextIndexed(stemp, sizeof(stemp), prefix, kPrefixes); fulltopic += F("/"); fulltopic += mqtt_client; fulltopic += F("_fb"); // cmnd/_fb @@ -260,7 +263,7 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi } for (uint32_t i = 0; i < 3; i++) { if ('\0' == Settings.mqtt_prefix[i][0]) { - snprintf_P(Settings.mqtt_prefix[i], sizeof(Settings.mqtt_prefix[i]), kPrefixes[i]); + GetTextIndexed(Settings.mqtt_prefix[i], sizeof(Settings.mqtt_prefix[i]), i, kPrefixes); } } fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), Settings.mqtt_prefix[prefix]); diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index 255422082..f449eb180 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -23,6 +23,10 @@ * Button support \*********************************************************************************************/ +#define MAX_BUTTON_COMMANDS 5 // Max number of button commands supported +const char kCommands[] PROGMEM = + D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1"; + struct BUTTON { unsigned long debounce = 0; // Button debounce timer uint16_t hold_timer[MAX_KEYS] = { 0 }; // Timer for button hold @@ -252,7 +256,7 @@ void ButtonHandler(void) } } else { // 3 - 7 press if (!Settings.flag.button_restrict) { // SetOption1 (0) - snprintf_P(scmnd, sizeof(scmnd), kCommands[Button.press_counter[button_index] -3]); + GetTextIndexed(scmnd, sizeof(scmnd), Button.press_counter[button_index] -3, kCommands); ExecuteCommand(scmnd, SRC_BUTTON); } } diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 13f132adb..c6315ff23 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -47,6 +47,9 @@ void (* const TasmotaCommand[])(void) PROGMEM = { #endif &CmndSensor, &CmndDriver }; +const char kWifiConfig[] PROGMEM = + D_WCFG_0_RESTART "||" D_WCFG_2_WIFIMANAGER "||" D_WCFG_4_RETRY "|" D_WCFG_5_WAIT "|" D_WCFG_6_SERIAL "|" D_WCFG_7_WIFIMANAGER_RESET_ONLY; + /********************************************************************************************/ void ResponseCmndNumber(int value) @@ -1184,23 +1187,18 @@ void CmndHostname(void) void CmndWifiConfig(void) { - char stemp1[TOPSZ]; if ((XdrvMailbox.payload >= WIFI_RESTART) && (XdrvMailbox.payload < MAX_WIFI_OPTION)) { if ((EX_WIFI_SMARTCONFIG == XdrvMailbox.payload) || (EX_WIFI_WPSCONFIG == XdrvMailbox.payload)) { XdrvMailbox.payload = WIFI_MANAGER; } Settings.sta_config = XdrvMailbox.payload; wifi_state_flag = Settings.sta_config; - snprintf_P(stemp1, sizeof(stemp1), kWifiConfig[Settings.sta_config]); - Response_P(PSTR("{\"" D_CMND_WIFICONFIG "\":\"%s " D_JSON_SELECTED "\"}"), stemp1); if (WifiState() > WIFI_RESTART) { -// ResponseAppend_P(PSTR(" after restart")); restart_flag = 2; } - } else { - snprintf_P(stemp1, sizeof(stemp1), kWifiConfig[Settings.sta_config]); - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_config, stemp1); } + char stemp1[TOPSZ]; + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_config, GetTextIndexed(stemp1, sizeof(stemp1), Settings.sta_config, kWifiConfig)); } void CmndFriendlyname(void) From b7061a01eaa777384a23f4634805e33a7fd2fb91 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Tue, 22 Oct 2019 17:48:49 +0200 Subject: [PATCH 2216/2222] decode-config.py: adapt settings - add DimmerRange (dimmer_hw_min/dimmer_hw_max) - add DeepSleepTime (deepsleep) - change PowerDelta (energy_power_delta) - rename novasds_period > novasds_startingoffset - fix tuya_disable_dimmer remove - fix json 'header' crc32 --- tools/decode-config.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 36ace62dc..12ce09baa 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.3.0035' +VER = '2.3.0036' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -993,6 +993,7 @@ Setting_6_6_0_9.update ({ }) # ====================================================================== Setting_6_6_0_10 = copy.deepcopy(Setting_6_6_0_9) +Setting_6_6_0_10['flag3'][0].pop('tuya_disable_dimmer',None) Setting_6_6_0_10.update ({ 'cfg_timestamp': (' Date: Tue, 22 Oct 2019 18:34:41 +0200 Subject: [PATCH 2217/2222] Remove command SetOption2 --- sonoff/_changelog.ino | 1 + sonoff/i18n.h | 11 ------- sonoff/settings.h | 2 +- sonoff/support_command.ino | 5 +-- sonoff/xdrv_03_energy.ino | 66 +++++++++++++++++--------------------- tools/decode-status.py | 2 +- 6 files changed, 35 insertions(+), 52 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 554cd44b5..1c37b3664 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * 6.6.0.21 20191022 * Remove support for WPS and SmartConfig in favour of Web server (!) based WifiManager (#6680) * Remove binary sonoff-classic (#6680) + * Remove command SetOption2 * * 6.6.0.20 20191018 * Add command SetOption65 0/1 to disable (1) fast power cycle detection fixing unwanted brownout trigger diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 3f19f67dd..d8d0db151 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -502,20 +502,9 @@ #endif // Common -enum UnitNames { - UNIT_AMPERE, UNIT_HOUR, UNIT_KILOOHM, UNIT_KILOWATTHOUR, UNIT_LUX, UNIT_MICROSECOND, UNIT_MILLIAMPERE, UNIT_MILLIMETER_MERCURY, - UNIT_MILLISECOND, UNIT_MINUTE, UNIT_PPB, UNIT_PPD, UNIT_PPM, UNIT_PERCENTAGE, UNIT_PRESSURE, UNIT_SECOND, - UNIT_SECTORS, UNIT_VOLT, UNIT_WATT, UNIT_WATTHOUR, UNIT_HERTZ }; -const char kUnitNames[] PROGMEM = - D_UNIT_AMPERE "|" D_UNIT_HOUR "|" D_UNIT_KILOOHM "|" D_UNIT_KILOWATTHOUR "|" D_UNIT_LUX "|" D_UNIT_MICROSECOND "|" D_UNIT_MILLIAMPERE "|" D_UNIT_MILLIMETER_MERCURY "|" - D_UNIT_MILLISECOND "|" D_UNIT_MINUTE "|" D_UNIT_PARTS_PER_BILLION "|" D_UNIT_PARTS_PER_DECILITER "|" D_UNIT_PARTS_PER_MILLION "|%|" D_UNIT_PRESSURE "|" D_UNIT_SECOND "|" - D_UNIT_SECTORS "|" D_UNIT_VOLT "|" D_UNIT_WATT "|" D_UNIT_WATTHOUR "|" D_UNIT_HERTZ ; - const char S_JSON_COMMAND_NVALUE_SPACE_UNIT[] PROGMEM = "{\"%s\":\"%d %s\"}"; const char S_JSON_COMMAND_LVALUE_SPACE_UNIT[] PROGMEM = "{\"%s\":\"%lu %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_JSON_ACTIVE "\":\"%d\"}}}"; diff --git a/sonoff/settings.h b/sonoff/settings.h index b31e0416d..80960260a 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -27,7 +27,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu struct { // SetOption0 .. SetOption31 uint32_t save_state : 1; // bit 0 - SetOption0 - Save power state and use after restart uint32_t button_restrict : 1; // bit 1 - SetOption1 - Control button multipress - uint32_t value_units : 1; // bit 2 - SetOption2 - Add units to JSON status messages + uint32_t ex_value_units : 1; // bit 2 - SetOption2 - Add units to JSON status messages - removed 6.6.0.21 uint32_t mqtt_enabled : 1; // bit 3 - SetOption3 - Control MQTT uint32_t mqtt_response : 1; // bit 4 - SetOption4 - Switch between MQTT RESULT or COMMAND uint32_t mqtt_power_retain : 1; // bit 5 - CMND_POWERRETAIN diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index c6315ff23..4704e14e1 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -495,7 +495,8 @@ void CmndSleep(void) sleep = XdrvMailbox.payload; WiFiSetSleepMode(); } - Response_P(S_JSON_COMMAND_NVALUE_UNIT_NVALUE_UNIT, XdrvMailbox.command, sleep, (Settings.flag.value_units) ? " " D_UNIT_MILLISECOND : "", Settings.sleep, (Settings.flag.value_units) ? " " D_UNIT_MILLISECOND : ""); + Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.sleep, sleep); + } void CmndUpgrade(void) @@ -1306,7 +1307,7 @@ void CmndTeleperiod(void) if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) Settings.tele_period = 10; // Do not allow periods < 10 seconds tele_period = Settings.tele_period; } - Response_P(S_JSON_COMMAND_NVALUE_UNIT, XdrvMailbox.command, Settings.tele_period, (Settings.flag.value_units) ? " " D_UNIT_SECOND : ""); + ResponseCmndNumber(Settings.tele_period); } void CmndReset(void) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 7df40b976..30b0237e2 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -352,7 +352,7 @@ void EnergyMarginCheck(void) } else { Energy.mplh_counter--; if (!Energy.mplh_counter) { - ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); + ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHED "\":%d}"), energy_power_u); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); @@ -399,8 +399,9 @@ void EnergyMarginCheck(void) } else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) { Energy.max_energy_state = 2; - dtostrfd(Energy.daily, 3, mqtt_data); - ResponseTime_P(PSTR(",\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); + char stemp[FLOATSZ]; + dtostrfd(Energy.daily, 3, stemp); + ResponseTime_P(PSTR(",\"" D_JSON_MAXENERGYREACHED "\":%s}"), stemp); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY); @@ -470,19 +471,10 @@ void EnergyEverySecond() * Commands \*********************************************************************************************/ -void EnergyCommandResponse(uint32_t nvalue, uint32_t unit) +void EnergyCommandCalResponse(uint32_t nvalue) { - if (UNIT_MILLISECOND == unit) { - snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command); - unit = UNIT_MICROSECOND; - } - - if (Settings.flag.value_units) { - char sunit[CMDSZ]; - Response_P(S_JSON_COMMAND_LVALUE_SPACE_UNIT, XdrvMailbox.command, nvalue, GetTextIndexed(sunit, sizeof(sunit), unit, kUnitNames)); - } else { - Response_P(S_JSON_COMMAND_LVALUE, XdrvMailbox.command, nvalue); - } + snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command); + ResponseCmndNumber(nvalue); } void CmndEnergyReset(void) @@ -635,7 +627,7 @@ void CmndPowerCal(void) if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { Settings.energy_power_calibration = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_power_calibration, UNIT_MICROSECOND); + ResponseCmndNumber(Settings.energy_power_calibration); } } @@ -646,7 +638,7 @@ void CmndVoltageCal(void) if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { Settings.energy_voltage_calibration = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_voltage_calibration, UNIT_MICROSECOND); + ResponseCmndNumber(Settings.energy_voltage_calibration); } } @@ -657,7 +649,7 @@ void CmndCurrentCal(void) if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { Settings.energy_current_calibration = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_current_calibration, UNIT_MICROSECOND); + ResponseCmndNumber(Settings.energy_current_calibration); } } @@ -665,7 +657,7 @@ void CmndPowerSet(void) { Energy.command_code = CMND_POWERSET; if (XnrgCall(FUNC_COMMAND)) { // Watt - EnergyCommandResponse(Settings.energy_power_calibration, UNIT_MILLISECOND); + EnergyCommandCalResponse(Settings.energy_power_calibration); } } @@ -673,7 +665,7 @@ void CmndVoltageSet(void) { Energy.command_code = CMND_VOLTAGESET; if (XnrgCall(FUNC_COMMAND)) { // Volt - EnergyCommandResponse(Settings.energy_voltage_calibration, UNIT_MILLISECOND); + EnergyCommandCalResponse(Settings.energy_voltage_calibration); } } @@ -681,7 +673,7 @@ void CmndCurrentSet(void) { Energy.command_code = CMND_CURRENTSET; if (XnrgCall(FUNC_COMMAND)) { // milliAmpere - EnergyCommandResponse(Settings.energy_current_calibration, UNIT_MILLISECOND); + EnergyCommandCalResponse(Settings.energy_current_calibration); } } @@ -689,7 +681,7 @@ void CmndFrequencySet(void) { Energy.command_code = CMND_FREQUENCYSET; if (XnrgCall(FUNC_COMMAND)) { // Hz - EnergyCommandResponse(Settings.energy_frequency_calibration, UNIT_MILLISECOND); + EnergyCommandCalResponse(Settings.energy_frequency_calibration); } } @@ -709,7 +701,7 @@ void CmndPowerDelta(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32000)) { Settings.energy_power_delta = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_power_delta, (Settings.energy_power_delta < 101) ? UNIT_PERCENTAGE : UNIT_WATT); + ResponseCmndNumber(Settings.energy_power_delta); } void CmndPowerLow(void) @@ -717,7 +709,7 @@ void CmndPowerLow(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { Settings.energy_min_power = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_min_power, UNIT_WATT); + ResponseCmndNumber(Settings.energy_min_power); } void CmndPowerHigh(void) @@ -725,7 +717,7 @@ void CmndPowerHigh(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { Settings.energy_max_power = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_max_power, UNIT_WATT); + ResponseCmndNumber(Settings.energy_max_power); } void CmndVoltageLow(void) @@ -733,7 +725,7 @@ void CmndVoltageLow(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { Settings.energy_min_voltage = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_min_voltage, UNIT_VOLT); + ResponseCmndNumber(Settings.energy_min_voltage); } void CmndVoltageHigh(void) @@ -741,7 +733,7 @@ void CmndVoltageHigh(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { Settings.energy_max_voltage = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_max_voltage, UNIT_VOLT); + ResponseCmndNumber(Settings.energy_max_voltage); } void CmndCurrentLow(void) @@ -749,7 +741,7 @@ void CmndCurrentLow(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { Settings.energy_min_current = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_min_current, UNIT_MILLIAMPERE); + ResponseCmndNumber(Settings.energy_min_current); } void CmndCurrentHigh(void) @@ -757,7 +749,7 @@ void CmndCurrentHigh(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { Settings.energy_max_current = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_max_current, UNIT_MILLIAMPERE); + ResponseCmndNumber(Settings.energy_max_current); } #ifdef USE_ENERGY_POWER_LIMIT @@ -766,7 +758,7 @@ void CmndMaxPower(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { Settings.energy_max_power_limit = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_max_power_limit, UNIT_WATT); + ResponseCmndNumber(Settings.energy_max_power_limit); } void CmndMaxPowerHold(void) @@ -774,7 +766,7 @@ void CmndMaxPowerHold(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_max_power_limit_hold, UNIT_SECOND); + ResponseCmndNumber(Settings.energy_max_power_limit_hold); } void CmndMaxPowerWindow(void) @@ -782,7 +774,7 @@ void CmndMaxPowerWindow(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_max_power_limit_window, UNIT_SECOND); + ResponseCmndNumber(Settings.energy_max_power_limit_window); } void CmndSafePower(void) @@ -790,7 +782,7 @@ void CmndSafePower(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { Settings.energy_max_power_safe_limit = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_max_power_safe_limit, UNIT_WATT); + ResponseCmndNumber(Settings.energy_max_power_safe_limit); } void CmndSafePowerHold(void) @@ -798,7 +790,7 @@ void CmndSafePowerHold(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { Settings.energy_max_power_safe_limit_hold = (1 == XdrvMailbox.payload) ? SAFE_POWER_HOLD : XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_max_power_safe_limit_hold, UNIT_SECOND); + ResponseCmndNumber(Settings.energy_max_power_safe_limit_hold); } void CmndSafePowerWindow(void) @@ -806,7 +798,7 @@ void CmndSafePowerWindow(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 1440)) { Settings.energy_max_power_safe_limit_window = (1 == XdrvMailbox.payload) ? SAFE_POWER_WINDOW : XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_max_power_safe_limit_window, UNIT_MINUTE); + ResponseCmndNumber(Settings.energy_max_power_safe_limit_window); } void CmndMaxEnergy(void) @@ -815,7 +807,7 @@ void CmndMaxEnergy(void) Settings.energy_max_energy = XdrvMailbox.payload; Energy.max_energy_state = 3; } - EnergyCommandResponse(Settings.energy_max_energy, UNIT_WATTHOUR); + ResponseCmndNumber(Settings.energy_max_energy); } void CmndMaxEnergyStart(void) @@ -823,7 +815,7 @@ void CmndMaxEnergyStart(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) { Settings.energy_max_energy_start = XdrvMailbox.payload; } - EnergyCommandResponse(Settings.energy_max_energy_start, UNIT_HOUR); + ResponseCmndNumber(Settings.energy_max_energy_start); } #endif // USE_ENERGY_POWER_LIMIT #endif // USE_ENERGY_MARGIN_DETECTION diff --git a/tools/decode-status.py b/tools/decode-status.py index 1497f35e2..10deefede 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -53,7 +53,7 @@ a_on_off = ["OFF","ON "] a_setoption = [[ "Save power state and use after restart", "Restrict button actions to single, double and hold", - "Show value units in JSON messages", + "(not used) Show value units in JSON messages", "MQTT enabled", "Respond as Command topic instead of RESULT", "MQTT retain on Power", From 11a205065225d101b21cb2308786e3571551b177 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 23 Oct 2019 11:13:15 +0200 Subject: [PATCH 2218/2222] Update TEMPLATES.md --- TEMPLATES.md | 564 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 438 insertions(+), 126 deletions(-) diff --git a/TEMPLATES.md b/TEMPLATES.md index bc8eb9f65..13aa9e085 100644 --- a/TEMPLATES.md +++ b/TEMPLATES.md @@ -2,231 +2,426 @@ # Templates -Find below a selection of available templates as of October, 21 2019. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) - -Note that currently only devices A to L have been documented. Work in Progress. +Find below a the available templates as of October 22nd, 2019. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) ## Bulb ``` -A19 RGBW 8W E26 {"NAME":"OOOLED 60W RGB","GPIO":[0,0,0,0,39,40,0,0,37,0,38,0,0],"FLAG":1,"BASE":18} -Aisirer 9W A19 E26 {"NAME":"AISIRER E26","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":15,"BASE":18} +A19 RGBW 8W E26 {"NAME":"OOOLED 60W RGB","GPIO":[255,255,255,255,39,40,255,255,37,255,38,255,255],"FLAG":1,"BASE":18} +Aisirer 9W A19 E26 {"NAME":"AISIRER E26","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} Anoopsyche CW/WW 60W {"NAME":"Anoop-CW-WW","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} -Aoycocr A19 {"NAME":"AoycocrA19","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":15,"BASE":18} +Aoycocr A19 {"NAME":"AoycocrA19","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} Arlec GLD112HA {"NAME":"Arlec CCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} -Ausein E14 7W White {"NAME":"Tuya RGBW","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Arlec GLD122HA {"NAME":"Arlec RGBWW","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} +Ausein E14 7W White {"NAME":"Tuya RGBW","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":0,"BASE":18} Avatar 5W E14 {"NAME":"AVATAR","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} -BNeta A60 E27 {"NAME":"OM60/RGBW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} -BNeta GU10 RGB {"NAME":"BNeta","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +BNeta A60 E27 {"NAME":"OM60/RGBW","GPIO":[255,255,255,255,140,37,0,0,38,142,141,255,255],"FLAG":0,"BASE":18} +BNeta GU10 RGB {"NAME":"BNeta","GPIO":[255,255,255,255,140,37,0,0,38,142,141,255,255],"FLAG":0,"BASE":18} Bomcosy 7W E27 RGB CW {"NAME":"Generic","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":1,"BASE":18} -Brilliant 20741 {"NAME":"Brilliant RGB+","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} -Brilliant HK17653S72 {"NAME":"Brilliant E14 ","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":15,"BASE":18} +Brilliant 20741 {"NAME":"Brilliant RGB+","GPIO":[255,255,255,255,37,40,255,255,38,0,39,0,0],"FLAG":0,"BASE":18} +Brilliant HK17653S72 {"NAME":"Brilliant E14 ","GPIO":[255,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":0,"BASE":18} +Candle 6W E14/E27 RGBWW {"NAME":"E14_RGBWW_6W","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":20} DGM L-WT9W1 {"NAME":"DGM L-WT9W1","GPIO":[0,0,0,0,140,142,0,0,38,37,141,0,0],"FLAG":0,"BASE":18} -electriQ RGBW B22 {"NAME":"ElectricQ B22","GPIO":[0,0,0,0,37,41,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} -EleLight 7W A19 E27 RGBW {"NAME":"EleLight 7wA19","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":0,"BASE":18} +electriQ RGBW B22 {"NAME":"ElectricQ B22","GPIO":[255,255,255,255,37,41,255,255,38,40,39,255,255],"FLAG":0,"BASE":18} +EleLight 7W A19 E27 RGBW {"NAME":"EleLight 7wA19","GPIO":[255,255,255,255,140,37,255,255,255,142,141,255,255],"FLAG":0,"BASE":18} Esicoo 9W E26 {"NAME":"Esicoo Bulb","GPIO":[0,0,0,0,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} -Fcmila 7W RGBW E27 {"NAME":"FCMILA 7W","GPIO":[0,0,0,0,39,40,0,0,37,0,38,0,0],"FLAG":0,"BASE":18} -Fcmila EQ723 {"NAME":"FCMILA LED E27","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Fcmila 7W RGBW E27 {"NAME":"FCMILA 7W","GPIO":[255,255,255,255,39,40,255,255,37,255,38,255,255],"FLAG":0,"BASE":18} +Fcmila EQ723 {"NAME":"FCMILA LED E27","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":0,"BASE":18} Fcmila FC-12W {"NAME":"SYF05","GPIO":[255,0,255,0,140,37,0,0,255,255,141,0,255],"FLAG":1,"BASE":69} -Feit Electric BPA800/RGBW/AG/2 {"NAME":"BPA800/RGBW","GPIO":[0,0,0,0,37,38,0,0,141,142,140,0,0],"FLAG":0,"BASE":48} +Feit Electric BPA800/RGBW/AG/2 {"NAME":" BPA800/RGBW","GPIO":[255,255,255,255,37,38,255,255,141,142,140,255,255],"FLAG":0,"BASE":48} Feit Electric BR30/927CA/AG {"NAME":"Feit BR30 WW","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} Feit Electric BR30/950CA/AG {"NAME":"Feit BR30 CW","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} -Feit Electric OM60/RGBW/CA/AG {"NAME":"OM60/RGBW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} -Feit Electric OM60/927CA/AG {"NAME":"Feit P_A800_2","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Feit Electric OM60/927CA/AG {"NAME":" Feit P_A800_2","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Feit Electric OM60/RGBW/CA/AG {"NAME":"OM60/RGBW","GPIO":[255,255,255,255,140,37,0,0,38,142,141,255,255],"FLAG":0,"BASE":18} Geeni Lux A21 White {"NAME":"Geeni-1050-WW","GPIO":[0,0,0,0,37,37,0,0,38,0,0,0,0],"FLAG":1,"BASE":18} Generic 10W E26/E27 RGBW {"NAME":"10W E27 RGBW","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} -Globe RGBW {"NAME":"GlobeRGBWW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Globe CW/WW {"NAME":"Globe CW/WW","GPIO":[0,0,0,0,38,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} -Gosund E27 8W RGBW {"NAME":"Gosund RGB+W","GPIO":[0,0,0,0,40,0,0,0,37,38,39,0,0],"FLAG":0,"BASE":18} +Globe RGBW {"NAME":"GlobeRGBWW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Gosund E27 8W RGBW {"NAME":"Gosund RGB+W","GPIO":[255,255,255,255,40,255,255,255,37,38,39,255,255],"FLAG":0,"BASE":18} Jomarto 9W B22 {"NAME":"Jomarto Wifi S","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":1,"BASE":18} Kainsy 7W E27 RGBW {"NAME":"KAINSY","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} -Kogan SmarterHome White 10W B22 {"NAME":"Kogan White/Wa","GPIO":[0,0,0,0,37,40,0,0,41,38,39,0,0],"FLAG":0,"BASE":18} -Kohree A19 7W {"NAME":"Kohree VHP560","GPIO":[0,0,0,0,37,41,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} -LE A19 RGBCT 9W E26 {"NAME":"LE RGBWW 60W","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":1,"BASE":18} -Legelite E26 {"NAME":"Legelite E26","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} -Linganzh LWE3 6W RGBW {"NAME":"Linganzh LWE3 ","GPIO":[0,0,0,0,0,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} +Kogan SmarterHome™ White 10W B22 {"NAME":"Kogan White/Wa","GPIO":[0,0,0,0,37,40,0,0,41,38,39,0,0],"FLAG":0,"BASE":18} +Kohree A19 7W {"NAME":"Kohree VHP560","GPIO":[255,255,255,255,37,41,255,255,38,40,39,255,255],"FLAG":0,"BASE":18} +LE A19 RGBCT 9W E26 {"NAME":"LE RGBWW 60W","GPIO":[255,0,255,0,140,37,0,0,38,142,141,0,255],"FLAG":1,"BASE":18} +Legelite E26 {"NAME":"Legelite E26","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} +Linganzh LWE3 6W RGBW {"NAME":"Linganzh LWE3 ","GPIO":[255,255,255,255,255,38,255,255,39,255,40,37,255],"FLAG":0,"BASE":18} Lohas 5W E12 {"NAME":"LH-5W-ZN01204","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} Lohas 9W E26 RGBW {"NAME":"Lohas RGBW","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":18} +Lohas A19 RGBW E12 {"NAME":"Lohas","GPIO":[17,255,255,255,0,0,0,0,0,143,0,144,0],"FLAG":1,"BASE":26} Lohas E14 R50 {"NAME":"Lohas E14 R50","GPIO":[17,255,255,255,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} -Lohas ZN031 {"NAME":"Lohas ZN031","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} -Lohas A19 RGBW E12 {"NAME":"Lohas","GPIO":[17,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":1,"BASE":26} -LSC Filament CW {"NAME":"LSC Filament","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} -LSC RGBCW E14 {"NAME":"LSC RGBCW E14","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} +Lohas ZN031 {"NAME":"Lohas ZN031","GPIO":[255,255,255,255,38,37,255,255,41,39,40,255,255],"FLAG":0,"BASE":18} +LSC Smart Connect Multicolor Spot GU10 {"NAME":"LSC RGBCW LED","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} +LSC Smart Connect Smart Filament LED {"NAME":"LSC-Filam-Big","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +Lumiman E27 Multicolor {"NAME":"Lumiman RGB","GPIO":[255,255,255,255,37,40,255,255,38,41,39,52,255],"FLAG":1,"BASE":18} +Lumiman LM530 E26 {"NAME":"Lumiman LM530","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":1,"BASE":18} +Lumiman LM650 {"NAME":"Legelite E26","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} +Luminea ZX-2831 E27 CCT {"NAME":"Luminea CCT","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Luminea ZX-2832 E27 RGBW {"NAME":"Luminea RGBW","GPIO":[255,255,255,255,140,37,255,255,38,142,141,255,255],"FLAG":1,"BASE":18} +Lyasi PT-BW09 {"NAME":"Lyasi PT-BW09","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} +Maxcio YX-L01P-E7 {"NAME":"Maxcio YXL01P","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} +Merkury A19 60W {"NAME":"MI-BW902-999W","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Merkury A21 75W {"NAME":"MI-BW904-999W","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":1,"BASE":69} +Merkury BR30 65W {"NAME":"MI-BW905-999W","GPIO":[0,0,0,0,37,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +Mirabella Genio CW {"NAME":"GenioBulbCW","GPIO":[0,0,0,0,38,37,0,0,0,40,39,0,0],"FLAG":0,"BASE":18} +Mirabella Genio Dimmable {"NAME":"GenioBulbCCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} +Mirabella Genio RGBW {"NAME":"GenioBulbRGB","GPIO":[255,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":1,"BASE":18} +Mixigoo 10W E27 RGBW {"NAME":"Mixigoo Bulb","GPIO":[255,255,255,255,41,38,255,255,39,255,37,40,255],"FLAG":0,"BASE":18} +MOKO YX-L01C-E27 {"NAME":"MOKO","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} +Nedis WIFILC10WTE27 {"NAME":"Nedis RGBW","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":1,"BASE":18} +Nedis WIFILW10WTE27 {"NAME":"WIFILW10WTE27","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +NiteBird TT-WB4 {"NAME":"NiteBird TT-WB","GPIO":[255,255,255,255,40,255,255,255,37,38,39,255,255],"FLAG":0,"BASE":18} +Novostella 12W RGBCT E27 {"NAME":"Novostella","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} +Novostella B22 7W {"NAME":"Novostella B22","GPIO":[255,255,255,255,37,41,255,255,38,40,39,255,255],"FLAG":0,"BASE":18} +Oobest RGBW E27 {"NAME":"WifiBulb","GPIO":[0,0,0,0,0,37,0,0,39,40,38,0,0],"FLAG":1,"BASE":18} +Oobest ZN93028 11W E27 RGB {"NAME":"RGB Bulb 11W","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":1,"BASE":18} +Reafoo 9W A26 {"NAME":"ReaFooE26","GPIO":[0,0,0,0,41,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} +RGBW 7W B22 {"NAME":"SM16716","GPIO":[255,255,255,255,140,37,255,255,255,255,141,255,255],"FLAG":0,"BASE":18} +RGBW 7W E14 {"NAME":"7W-E14-RGBW-La","GPIO":[255,255,255,255,38,37,255,255,39,255,40,255,255],"FLAG":0,"BASE":18} +Solimo 12W B22 RGBWW {"NAME":"Solimo RGBWW12","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} +Solimo 9W B22 RGBWW {"NAME":"Solimo RGBWW 9","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} +Sonoff B1 (R2) {"NAME":"Sonoff B1","GPIO":[17,255,255,255,0,0,0,0,143,0,144,0,0],"FLAG":0,"BASE":26} +TCP B22 RGBW {"NAME":"TCP Smart RGBW","GPIO":[255,255,255,255,140,37,0,0,38,142,141,255,255],"FLAG":0,"BASE":18} +Teckin SB50 {"NAME":"Teckin SB50","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":0,"BASE":18} +Teckin SB50 v2 {"NAME":"Teckin SB50","GPIO":[255,255,255,255,37,255,255,255,38,40,39,255,255],"FLAG":0,"BASE":18} +Teckin SB50 V3 {"NAME":"Teckin SB50v3","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} +Teckin SB51 {"NAME":"Teckin SB51","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":0,"BASE":18} +Teckin SB53 {"NAME":"Teckin SB53","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} +TikLOk 7.5W A19 E26 {"NAME":"TikLOk WW-CW-L","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +Wipro Garnet B22 9W {"NAME":"WiproSmartBulb","GPIO":[255,255,255,255,37,41,255,255,38,40,39,255,255],"FLAG":0,"BASE":18} +Woopower RGBW E14 5W {"NAME":"Woopower E14","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Xiaomi Phillips E14 {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,38,0,0,37,0],"FLAG":0,"BASE":48} +Xiaomi Phillips E27 {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,38,0,0,37,0],"FLAG":0,"BASE":48} +XMRJ {"NAME":"XMRJ","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +ZZHXON 6W E14/E27 {"NAME":"E27_RGB_Bulb","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} ``` -## Bulb socket +## Bulb Socket ``` Elegant Choice E27/E26 {"NAME":"Sm Lghtg Base","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Slampher {"NAME":"Slampher","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":9} +SmartBase E0260 {"NAME":"SmartBaseE0260","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +``` + +## Curtain Switch +``` +Teepao {"NAME":"Taopao","GPIO":[255,255,255,18,22,19,255,255,255,21,255,255,17],"FLAG":1,"BASE":18} +WF-CS01 {"NAME":"Tuya Shutter","GPIO":[157,0,54,10,22,19,0,0,17,21,53,23,52],"FLAG":0,"BASE":18} +``` + +## DIY Project +``` +LC-Tech 1Ch and PZEM-004T {"NAME":"HW-655 PZEM","GPIO":[0,63,0,62,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Luani HVIO {"NAME":"Luani HVIO","GPIO":[0,255,255,255,21,22,0,0,9,10,255,52,0],"FLAG":1,"BASE":35} +SUPLA inCan by Espablo {"NAME":"Supla Espablo","GPIO":[0,255,4,255,17,21,0,0,255,22,255,0,52],"FLAG":1,"BASE":31} +``` + +## Development Board +``` +Witty Cloud {"NAME":"Witty Cloud","GPIO":[255,255,56,255,17,255,0,0,38,39,255,37,255],"FLAG":1,"BASE":32} ``` ## Dimmer ``` -Armtronix AC Dimmer One {"NAME":"ARMTR Dimmer","GPIO":[255,148,255,149,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":56} -Armtronix AC Dimmer Two {"NAME":"ARMTR Dimmer","GPIO":[255,148,255,149,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":56} +Armtronix AC Dimmer One Triac Board {"NAME":"ARMTR Dimmer","GPIO":[255,148,255,149,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":56} +Armtronix AC Dimmer Two Triac Board {"NAME":"ARMTR Dimmer","GPIO":[255,148,255,149,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":56} CE Smart Home WF500D {"NAME":"CE-WF500D","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} EVA LOGIK WF31 {"NAME":"WF31 Dimmer","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} EX-Store 2 Kanal RS232 V4 {"NAME":"EXS Dimmer","GPIO":[0,148,0,149,255,255,0,0,255,183,255,0,0],"FLAG":0,"BASE":72} Kingart Touch {"NAME":"PS-16-DZ","GPIO":[255,148,255,149,255,255,0,0,255,52,255,255,255],"FLAG":0,"BASE":58} +Moes DS01 {"NAME":"MOES - DS01","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} +Moes QS-WiFi-D01 Dimmer 150W {"NAME":"WiFi-Dimmer","GPIO":[0,148,0,149,0,0,0,0,0,42,37,0,0],"FLAG":0,"BASE":18} +PS-16-DZ {"NAME":"PS-16-DZ","GPIO":[255,148,255,149,255,255,0,0,255,52,255,255,255],"FLAG":0,"BASE":58} +Zemismart KS-7011 {"NAME":"KS-7011 Dimmer","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} ``` -## Infra Red blaster +## Environment Monitor +``` +Sonoff SC {"NAME":"Sonoff SC","GPIO":[17,148,255,149,0,0,0,0,0,56,0,0,0],"FLAG":0,"BASE":21} +``` + +## Fan Controller +``` +Sonoff iFan02 {"NAME":"Sonoff iFan02","GPIO":[17,255,0,255,23,22,18,19,21,56,20,24,0],"FLAG":0,"BASE":44} +Sonoff iFan03 {"NAME":"SonoffiFan03","GPIO":[17,148,0,149,0,0,29,161,23,56,22,24,0],"FLAG":0,"BASE":71} +``` + +## Humidifier +``` +Asakuki 500ml {"NAME":"Oil Diffuser","GPIO":[255,255,255,255,255,255,255,255,255,255,255,21,22],"FLAG":0,"BASE":18} +Maxcio 400ml {"NAME":"MaxcioDiffuser","GPIO":[255,255,255,255,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} +Oil Diffuser 550ML {"NAME":"Oil Diffuser","GPIO":[255,255,255,255,255,255,255,255,255,255,255,21,22],"FLAG":0,"BASE":18} +``` + +## IR Bridge ``` Alfawise KS1 {"NAME":"KS1","GPIO":[255,71,17,72,17,51,0,0,56,0,8,0,0],"FLAG":1,"BASE":62} -auvisio S06 {"NAME":"NX-4519-675","GPIO":[0,0,0,0,52,51,0,0,0,0,8,0,0],"FLAG":1,"BASE":18} -Eachen SANT-IR 01 {"NAME":"Eachen IR","GPIO":[0,0,0,0,56,51,255,255,255,17,8,0,0],"FLAG":0,"BASE":18}' +auvisio S06 {"NAME":"NX-4519-675","GPIO":[255,255,255,255,52,51,255,255,255,255,8,255,255],"FLAG":1,"BASE":18} +Eachen SANT-IR 01 {"NAME":"Eachen IR","GPIO":[0,0,0,0,56,51,255,255,255,17,8,0,0],"FLAG":0,"BASE":18} Geeklink {"NAME":"GL IR Blaster","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} -Genio Mirabella HKWL-IR02W {"NAME":"Genio IR TxRx","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +Mirabella Genio HKWL-IR02W {"NAME":"Genio IR TxRx","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +STITCH by Monoprice 35753 {"NAME":"Stitch 35753","GPIO":[0,0,0,0,52,51,0,0,0,90,8,0,0],"FLAG":0,"BASE":18} +YTF {"NAME":"YTF IR Bridge","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} ``` -## Light -``` -Brilliant 20702/06 Garden {"NAME":"Brilliant Gard","GPIO":[0,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} -Brilliant Smart WiFi Downlight CCT {"NAME":"SmartCCTDwnLgt","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} -Fcmila XDD-48W {"NAME":"XDD-48W","GPIO":[0,0,0,0,37,40,0,0,38,25,39,0,0],"FLAG":0,"BASE":18} -``` - -## Light strip +## LED Controller ``` Arilux AL-LC01 {"NAME":"Arilux LC01","GPIO":[17,255,59,255,147,37,0,0,38,39,255,0,0],"FLAG":0,"BASE":37} Arilux AL-LC06 {"NAME":"Arilux LC06","GPIO":[17,255,255,255,255,255,255,255,38,39,37,41,40],"FLAG":0,"BASE":18} Arilux AL-LC11 {"NAME":"Arilux LC11","GPIO":[17,255,59,255,38,37,0,0,41,40,39,147,0],"FLAG":0,"BASE":38} -BlitzWolf BW-LT11 {"NAME":"BW-LT11 Strip","GPIO":[17,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":0,"BASE":18} Electrodragon Mosfet Drive {"NAME":"LEDBoard RGBW","GPIO":[255,0,0,0,255,255,0,0,39,38,40,37,52],"FLAG":0,"BASE":18} H801 {"NAME":"H801","GPIO":[255,52,255,255,41,57,0,0,39,38,40,37,0],"FLAG":0,"BASE":20} LEDEnet {"NAME":"LEDEnet","GPIO":[0,255,56,255,147,0,0,0,38,39,37,40,0],"FLAG":0,"BASE":34} -LSC RGBW {"NAME":"LSC RGBW Strip","GPIO":[51,0,0,0,37,0,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} +Luminea ZX-2844 {"NAME":"Luminea ZX-284","GPIO":[40,255,255,255,0,39,255,255,38,17,37,255,255],"FLAG":0,"BASE":18} +MagicHome RGB ZJ-WFMN-A V1.1 {"NAME":"MagicHome RGB","GPIO":[0,0,0,0,0,37,0,0,38,39,0,0,0],"FLAG":0,"BASE":34} +MagicHome RGBW ZJ-WFMN-A V1.1 {"NAME":"MagicHome RGBW","GPIO":[0,0,0,0,51,38,0,0,37,39,0,40,0],"FLAG":0,"BASE":34} +MagicHome ZJ-ESP-IR-F V1 {"NAME":"ZJ-ESP-IR-F V1","GPIO":[255,255,255,255,51,38,255,255,37,39,255,40,255],"FLAG":0,"BASE":18} +Nexlux {"NAME":"MagicHome V1.1","GPIO":[0,0,0,0,51,37,0,0,38,39,0,0,0],"FLAG":0,"BASE":34} +Shelly RGBW2 {"NAME":"RGBW2","GPIO":[255,255,33,255,24,91,255,255,21,17,23,22,255],"FLAG":0,"BASE":18} ``` -## Power plug +## LED Strip +``` +BlitzWolf BW-LT11 {"NAME":"BW-LT11 Strip","GPIO":[17,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":0,"BASE":18} +LSC Smart Connect RGBW {"NAME":"LSC-RGBW-Strip","GPIO":[51,0,0,0,37,0,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} +Merkury Innovations MI-EW003-999W {"NAME":"MI-EW003-999W ","GPIO":[17,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} +Mirabella Genio 3 Metre {"NAME":"MirabellaStrip","GPIO":[17,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":0,"BASE":18} +Monster Smart IlluminEssence {"NAME":"MI-EW003-999W ","GPIO":[17,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} +Sonoff L1 {"NAME":"SonoffL1","GPIO":[0,148,0,149,0,0,0,0,0,56,0,0,0],"FLAG":0,"BASE":70} +Torchstar {"NAME":"Torchstar","GPIO":[255,255,255,255,52,255,255,255,255,255,255,37,53],"FLAG":1,"BASE":18} +``` + +## Light +``` +Brilliant 20702/06 Garden {"NAME":"Brilliant Gard","GPIO":[0,0,0,0,37,0,255,255,38,0,39,0,0],"FLAG":0,"BASE":18} +Brilliant Smart WiFi Downlight CCT {"NAME":"SmartCCTDwnLgt","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} +Fcmila XDD-48W {"NAME":"XDD-48W","GPIO":[0,0,0,0,37,40,0,0,38,25,39,0,0],"FLAG":0,"BASE":18} +Mi LED Desk Lamp MJTD01YL {"NAME":"Mi Desk Lamp","GPIO":[0,0,17,0,37,38,0,0,150,151,0,0,0],"FLAG":0,"BASE":66} +Mirabella Genio Dimmable CCT Downlight {"NAME":"GenioDLightCCT","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":48} +Mirabella Genio Dimmable RGBCCT Downlight {"NAME":"GenioDLightRGB","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Sonoff BN-SZ01 {"NAME":"Sonoff BN-SZ","GPIO":[0,0,0,0,0,0,0,0,37,56,0,0,0],"FLAG":0,"BASE":22} +Spotlight 9cm RGB+W 7W {"NAME":"Spotlight RGBW","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Utorch PZE-911 {"NAME":"Utorch PZE-911","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":1} +Utorch UT40 {"NAME":"Utorch UT40","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":1} +Wipro Next 20W Smart LED Batten {"NAME":"WIPROBatten","GPIO":[255,255,255,255,255,37,255,255,255,47,255,255,255],"FLAG":1,"BASE":18} +Zemismart 14W RGB-CCT {"NAME":"ZemiDownLight6","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Zemismart 4" 10W RGBW {"NAME":"ZemiDownLight","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +``` + +## Outdoor Plug +``` +Acenx SOP04-US Dual {"NAME":"SOP04-US Dual","GPIO":[255,255,255,255,56,57,255,255,21,17,22,255,255],"FLAG":0,"BASE":18} +Albohes PC-1606 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39} +ECF-SOP03 {"NAME":"Outdoor3Outlet","GPIO":[0,0,0,23,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +Feit Electric Dual {"NAME":"Prime Smart ou","GPIO":[255,255,255,255,157,56,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} +Geeni GN-OW101-101 {"NAME":"Geeni Outdoor","GPIO":[17,0,0,0,0,57,0,0,0,52,21,0,0],"FLAG":0,"BASE":18} +LEPOWER {"NAME":"LEPOWER Outdoo","GPIO":[255,255,255,255,56,57,255,255,21,17,22,255,255],"FLAG":0,"BASE":18} +Oittm Outdoor {"NAME":"Oittm Outdoor","GPIO":[17,0,0,0,0,0,0,0,0,0,56,21,255],"FLAG":0,"BASE":18} +SK03 {"NAME":"SK03 Outdoor","GPIO":[17,0,0,0,133,132,0,0,131,57,56,21,0],"FLAG":0,"BASE":57} +Top-Max PS-1602 {"NAME":"PS-1602","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} +``` + +## Plug ``` 3Stone Mini {"NAME":"3Stone Smart P","GPIO":[0,17,0,0,0,0,0,0,0,57,21,0,0],"FLAG":0,"BASE":18} Acashna HS108 {"NAME":"HS108","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} -Acenx SOP04-US Dual {"NAME":"SOP04-US Dual","GPIO":[0,0,0,0,56,57,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} -Aisirer UK1 {"NAME":"AISIRER","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +Aisirer UK1 {"NAME":"AISIRER","GPIO":[255,255,255,255,56,255,255,255,21,17,255,255,255],"FLAG":1,"BASE":18} Albohes PS-1602 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39} -Albohes PC-1606 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39} +Aldi Medion Life+ S85225 {"NAME":"Medion","GPIO":[0,0,0,17,134,132,0,0,131,158,21,0,0],"FLAG":0,"BASE":52} Alexfirst TV-ASP801EU {"NAME":"Alexfirst","GPIO":[17,0,0,0,54,56,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} -Alfawise PE1004T {"NAME":"PE1004T","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -Amysen YX-WS01 {"NAME":"Amyse YX WS01","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} +Alfawise PE1004T {"NAME":"PE1004T","GPIO":[255,255,255,255,56,57,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} +Amysen YX-WS01 {"NAME":"Amyse YX WS01","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":1,"BASE":18} ANBES ABS-CZ004 {"NAME":"ANBES ABS-CZ00","GPIO":[0,0,0,0,21,133,0,0,131,17,132,22,18],"FLAG":0,"BASE":18} Anoopsyche AWP07L {"NAME":"Anoopsyche AWP","GPIO":[0,0,0,0,56,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} Anoopsyche JH-G01B1 {"NAME":"JH-G01B1","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":41} Anoopsyche UK1D {"NAME":"UK1D","GPIO":[0,17,0,0,133,132,0,0,130,52,21,0,0],"FLAG":0,"BASE":6} -Aoycocr Smart Plug {"NAME":"Aoycocr Smart ","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} Aoycocr EU5-16A {"NAME":"Aoycocr","GPIO":[255,0,56,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17} +Aoycocr Smart Plug {"NAME":"Aoycocr Smart ","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} Arlec Grid Connect PC189HA {"NAME":"Arlec","GPIO":[0,0,0,0,123,0,0,0,21,56,17,0,0],"FLAG":0,"BASE":18} Arlec Twin PC288HA {"NAME":"Arlec Twin","GPIO":[0,17,0,22,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} -Aukey SH-PA1 {"NAME":"AUKEY SH-PA1","GPIO":[0,0,255,0,0,0,0,0,0,17,0,21,0],"FLAG":15,"BASE":18} -Avatar 10A {"NAME":"AWP07L","GPIO":[56,0,0,0,0,134,0,0,130,17,132,21,0],"FLAG":1,"BASE":18} -Avatar AWP07L 10A {"NAME":"Avatar AWP07L","GPIO":[56,0,0,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Aukey SH-PA1 {"NAME":"AUKEY SH-PA1","GPIO":[0,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Avatar 10A {"NAME":"AWP07L","GPIO":[56,255,255,255,255,134,255,255,130,17,132,21,255],"FLAG":1,"BASE":18} +Avatar AWP07L 10A {"NAME":"Avatar AWP07L","GPIO":[56,255,255,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} Avatto JH-G01E {"NAME":"AVATTO JH-G01E","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":41} -AWP04L {"NAME":"AWP04L","GPIO":[57,0,0,131,0,134,0,0,21,17,132,56,0],"FLAG":0,"BASE":18} +AWP02L-N {"NAME":"AWP02L-N","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} +AWP04L {"NAME":"AWP04L","GPIO":[57,255,255,131,255,134,0,0,21,17,132,56,255],"FLAG":0,"BASE":18} AWP07L {"NAME":"AISIRER AWP07L","GPIO":[0,0,0,0,56,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} AWP08L {"NAME":"AWP08L","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} -AzpenHome Smart {"NAME":"Socket2Me","GPIO":[52,0,0,0,22,0,0,0,21,0,17,0,0],"FLAG":15,"BASE":18} +AzpenHome Smart {"NAME":"Socket2Me","GPIO":[52,255,255,255,22,255,0,0,21,255,17,255,255],"FLAG":0,"BASE":18} Bestek MRJ1011 {"NAME":"BestekMRJ1011","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} -Bilikay SP10 {"NAME":"Bilikay SP10","GPIO":[0,37,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} -Blitzwolf BW-SHP2 {"NAME":"BlitzWolf SHP","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Bilikay SP10 {"NAME":"Bilikay SP10","GPIO":[255,37,255,17,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18} +Blitzwolf BW-SHP2 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} Blitzwolf BW-SHP3 {"NAME":"Blitzwolf SHP3","GPIO":[56,0,57,0,22,134,0,0,131,18,132,21,17],"FLAG":0,"BASE":45} Blitzwolf BW-SHP3 alt {"NAME":"Blitzwolf SHP3","GPIO":[18,56,0,131,134,132,0,0,17,0,22,21,0],"FLAG":0,"BASE":18} -Blitzwolf BW-SHP4 {"NAME":"BlitzWolf SHP","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Blitzwolf BW-SHP4 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} Blitzwolf BW-SHP5 {"NAME":"SHP5","GPIO":[57,145,56,146,0,22,0,0,0,0,21,0,17],"FLAG":0,"BASE":18} -Blitzwolf BW-SHP6 {"NAME":"BlitzWolf SHP","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Blitzwolf BW-SHP6 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} Blitzwolf BW-SHP8 {"NAME":"SHP8","GPIO":[0,56,0,17,134,132,0,0,131,53,21,0,0],"FLAG":0,"BASE":64} BN-LINK BNC-60/U133TJ-2P {"NAME":"BNC-60/U133TJ","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":18} -BSD15 {"NAME":"TuyaPlugBSD15","GPIO":[0,0,0,0,0,0,0,0,21,17,56,0,0],"FLAG":1,"BASE":18} -BSD25 {"NAME":"Tuya Wifi Plug","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Brilliant USB Charger {"NAME":"Brilliant","GPIO":[0,0,0,0,0,21,0,0,0,52,90,0,0],"FLAG":0,"BASE":18} +BSD15 {"NAME":"TuyaPlugBSD15","GPIO":[255,255,255,255,255,255,255,255,21,17,56,255,255],"FLAG":1,"BASE":18} +BSD25 {"NAME":"Tuya Wifi Plug","GPIO":[255,255,255,255,56,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} BSD29 {"NAME":"BSD29","GPIO":[0,0,0,131,134,132,0,0,21,17,56,0,0],"FLAG":0,"BASE":52} -BSD33 {"NAME":"Generic","GPIO":[0,0,0,131,134,132,0,0,21,17,56,0,0],"FLAG":15,"BASE":18} -BSD34 {"NAME":"BSD34 Plug","GPIO":[0,0,0,0,0,0,0,0,21,17,56,0,0],"FLAG":0,"BASE":18} -CE Smart Home LA-WF3 {"NAME":"CE LA-WF3","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +BSD33 {"NAME":"Generic","GPIO":[255,255,255,131,134,132,255,255,21,17,56,255,255],"FLAG":0,"BASE":18} +BSD34 {"NAME":"BSD34 Plug","GPIO":[255,255,255,255,255,255,255,255,21,17,56,255,255],"FLAG":0,"BASE":18} +CE Smart Home - LA-WF3 {"NAME":"CE LA-WF3","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} Conico SM-PW70 {"NAME":"Conico SM-PW70","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} Coosa {"NAME":"COOSA","GPIO":[0,0,0,0,57,52,0,0,21,17,255,0,0],"FLAG":0,"BASE":1} Coosa SP1 {"NAME":"COOSA SP1","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -CrazyLynX WiFi {"NAME":"CrazyLynX","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +CrazyLynX WiFi {"NAME":"CrazyLynX","GPIO":[255,255,255,255,57,56,255,255,21,17,255,255,255],"FLAG":1,"BASE":18} CYYLTF BIFANS J23 {"NAME":"CYYLTD BIFANS J23","GPIO":[56,0,0,0,0,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} Delock 11826 {"NAME":"Delock 11826","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +Digoo DG-SP01 {"NAME":"DG-SP01","GPIO":[255,17,255,21,56,37,255,255,38,39,40,255,255],"FLAG":0,"BASE":18} Digoo NX-SP202 {"NAME":"Generic_SP202","GPIO":[52,0,0,131,91,134,0,0,22,17,132,21,0],"FLAG":0,"BASE":63} -Digoo DG-SP01 {"NAME":"DG-SP01","GPIO":[0,17,0,21,56,37,0,0,38,39,40,0,0],"FLAG":0,"BASE":18} DILISENS SP201 {"NAME":"Dilisens SP201","GPIO":[0,0,131,0,133,132,52,21,18,22,17,0,0],"FLAG":0,"BASE":18} -DWFeng AWP02L-N {"NAME":"AWP02L-N","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} -ECF-SOP03 {"NAME":"Outdoor3Outlet","GPIO":[0,0,0,23,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} -ECO Plugs CT-065W {"NAME":"ECO/CT-065W","GPIO":[0,0,0,0,0,0,0,0,0,17,0,21,0],"FLAG":15,"BASE":18} +DWFeng AWP02L-N {"NAME":"AWP02L-N","GPIO":[255,255,56,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18} +ECO Plugs CT-065W {"NAME":"ECO/CT-065W","GPIO":[255,255,255,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18} EFUN SH331W {"NAME":"Efun-Plug","GPIO":[56,0,158,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} -EletecPro 2 {"NAME":"EletecPro-2","GPIO":[0,0,0,0,17,0,0,0,53,52,21,0,0],"FLAG":1,"BASE":18} +EletecPro 2 {"NAME":"EletecPro-2","GPIO":[255,255,255,255,17,255,255,255,53,52,21,255,255],"FLAG":1,"BASE":18} ENJOWI SP111-EU-W {"NAME":"Enjowi SP111-E","GPIO":[17,56,0,0,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} -Epicka {"NAME":"Epicka","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} -Esicoo YX-WS01 {"NAME":"Esicoo Plug","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Epicka {"NAME":"Epicka","GPIO":[255,255,255,255,57,56,255,255,21,17,255,255,255],"FLAG":1,"BASE":18} +Esicoo YX-WS01 {"NAME":"Esicoo Plug","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18} Estink C178 {"NAME":"Estink C178","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} ESW01-US {"NAME":"ESW01-US","GPIO":[0,0,0,0,21,56,0,0,0,0,9,0,0],"FLAG":1,"BASE":18} -EVA LOGIK NWF001 {"NAME":"EVA LOGIK Plug","GPIO":[0,17,0,0,0,0,0,0,0,52,21,0,0],"FLAG":0,"BASE":18} +ET RGB {"NAME":"RGB Smart Plug","GPIO":[37,0,39,0,38,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +EVA LOGIK NWF001 {"NAME":"EVA LOGIK Plug","GPIO":[255,17,255,255,255,255,255,255,255,52,21,255,255],"FLAG":0,"BASE":18} EVO-Smart JH-G01U {"NAME":"EVO JH-G01U","GPIO":[0,0,0,0,21,17,0,0,56,0,0,0,0],"FLAG":0,"BASE":18} -Feit Electric Dual {"NAME":"Prime Smart ou","GPIO":[0,0,0,0,157,56,0,0,21,17,0,0,0],"FLAG":15,"BASE":18} -FK-PW901U {"NAME":"FK-PW901U","GPIO":[56,0,0,0,0,23,0,0,21,17,24,22,0],"FLAG":15,"BASE":18} +FK-PW901U {"NAME":"FK-PW901U","GPIO":[56,255,255,255,255,23,255,255,21,17,24,22,255],"FLAG":0,"BASE":18} FLHS-ZN04 {"NAME":"FLHS-ZN04","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} Fontastic SH01 {"NAME":"Fontastic","GPIO":[255,0,255,0,56,0,255,255,21,17,0,0,0],"FLAG":1,"BASE":18} FrankEver FLHS-ZN04 {"NAME":"Israel plug","GPIO":[57,0,56,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":45} -GDTech W-US001 {"NAME":"GDTech W-US001","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} -GDTech W-US003 {"NAME":"W-US003","GPIO":[0,17,255,255,255,0,0,0,0,56,21,0,0],"FLAG":15,"BASE":18} +GDTech W-US001 {"NAME":"GDTech W-US001","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":1,"BASE":18} +GDTech W-US003 {"NAME":"W-US003","GPIO":[0,17,255,255,255,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} Geeni Charge {"NAME":"Geeni Charge","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} Geeni Glo {"NAME":"Geeni Glo","GPIO":[0,0,0,0,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} -Geeni GN-OW101-101 {"NAME":"Geeni Outdoor","GPIO":[17,0,0,0,0,57,0,0,0,52,21,0,0],"FLAG":0,"BASE":18} Geeni Spot {"NAME":"Geeni Spot","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} Geeni Switch Duo {"NAME":"Geeni Duo","GPIO":[0,0,0,0,18,22,0,0,17,52,21,0,53],"FLAG":0,"BASE":18} Globe Smart {"NAME":"GlobeSmartPlug","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} Gosund SP1 {"NAME":"Gosund SP1 v23","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} Gosund SP111 {"NAME":"Gosund SP111","GPIO":[56,0,57,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} -Gosund SP112 {"NAME":"SHP5","GPIO":[56,145,57,146,255,22,0,0,255,255,21,255,17],"FLAG":0,"BASE":18} +Gosund SP112 {"NAME":"SHP5","GPIO":[56,145,57,146,255,22,0,0,255,255,21,255,18],"FLAG":0,"BASE":18} Gosund WP1-1 {"NAME":"Gosund WP1-1","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Gosund WP2 {"NAME":"Gosund_WP212","GPIO":[17,0,0,0,18,0,0,0,21,0,22,0,0],"FLAG":0,"BASE":18} -Gosund WP3 {"NAME":"Gosund WP3","GPIO":[0,0,0,0,17,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} -Gosund WP5 {"NAME":"Gosund-WP5","GPIO":[0,0,0,0,17,0,0,0,53,52,21,0,0],"FLAG":1,"BASE":18} -Gosund WP6 {"NAME":"Gosund WP6","GPIO":[0,0,0,17,0,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} Gosund WP211 {"NAME":"Gosund wp211","GPIO":[0,0,0,0,21,0,0,0,0,17,0,22,18],"FLAG":0,"BASE":18} Gosund WP212 {"NAME":"Gosund_WP212","GPIO":[17,0,0,0,18,0,0,0,21,0,22,0,0],"FLAG":0,"BASE":18} +Gosund WP3 {"NAME":"Gosund WP3","GPIO":[0,0,0,0,17,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} +Gosund WP5 {"NAME":"Gosund-WP5","GPIO":[255,255,255,255,17,255,255,255,53,52,21,255,255],"FLAG":1,"BASE":18} +Gosund WP6 {"NAME":"Gosund WP6","GPIO":[0,0,0,17,0,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} Grefic TE101 {"NAME":"Grefic TE101","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} -Gyman SM-PW701U {"NAME":"Gyman","GPIO":[0,0,157,0,56,0,0,0,21,17,0,0,0],"FLAG":15,"BASE":18} +Gyman SM-PW701U {"NAME":"Gyman","GPIO":[255,255,157,255,56,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} Hauppauge SL-1642 {"NAME":"SL-1642","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -HiHome WPP-16T {"NAME":"HiHome WPP-16T","GPIO":[17,56,0,0,134,132,0,0,18,0,22,130,21],"FLAG":1,"BASE":18} +HiHome WPP-16T {"NAME":"HiHome WPP-16T","GPIO":[17,56,255,255,134,132,255,255,18,255,22,130,21],"FLAG":1,"BASE":18} hiwild W-US002 {"NAME":"W-US002","GPIO":[0,17,0,0,0,0,0,0,0,52,21,0,158],"FLAG":0,"BASE":18} -Houzetek AWP07L {"NAME":"AWP07L","GPIO":[56,0,0,130,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":18} +Houzetek AWP07L {"NAME":"AWP07L","GPIO":[56,255,255,130,255,134,255,255,0,17,132,21,255],"FLAG":0,"BASE":18} HuaFan QinLu {"NAME":"Huafan SS","GPIO":[56,0,0,57,17,29,0,0,132,130,133,0,0],"FLAG":0,"BASE":24} -AWP02L-N {"NAME":"AWP02L-N","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} Hyleton 313 {"NAME":"Hyleton 313","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} Hyleton 317 {"NAME":"hyleton-317","GPIO":[56,0,57,0,58,0,0,0,0,90,0,21,0],"FLAG":0,"BASE":18} Innens BSD29 {"NAME":"BSD29","GPIO":[0,0,56,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":52} -iSwitch {"NAME":"Smart Plug XSA","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} -Jeeo TF-SH330 {"NAME":"Jeeo TF-SH330","GPIO":[56,0,0,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} +iSwitch {"NAME":"Smart Plug XSA","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18} +Jeeo TF-SH330 {"NAME":"Jeeo TF-SH330","GPIO":[56,255,255,255,255,255,255,255,255,17,255,21,255],"FLAG":1,"BASE":18} Jinvoo SM-PW701U {"NAME":"SM-PW702","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} Jinvoo SM-PW762U {"NAME":"SM-PW762U","GPIO":[0,0,0,0,158,56,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} Jules V (Upgrade Version) {"NAME":"Jules-V_UV","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18} Jules.V NX-SM300 {"NAME":"NX-SM300","GPIO":[52,0,0,0,0,130,0,0,21,132,133,52,0],"FLAG":0,"BASE":6} -Kimire S12 {"NAME":"Kimire S12","GPIO":[0,0,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Kimire S12 {"NAME":"Kimire S12","GPIO":[255,255,255,17,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18} King-Link C128 {"NAME":"King-Link C128","GPIO":[0,0,55,0,22,53,0,0,23,52,17,21,54],"FLAG":0,"BASE":18} -KMC 70011 {"NAME":"KMC 70011","GPIO":[17,0,0,0,133,132,0,0,130,56,21,0,0],"FLAG":0,"BASE":36} KMC 4 30608 {"NAME":"KMC 4 Outlet","GPIO":[0,56,0,0,133,132,0,0,130,22,23,21,17],"FLAG":0,"BASE":36} -Kogan SmarterHome Energy Meter {"NAME":"Kogan Smart Sw","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} -Koogeek KLUP1 {"NAME":"Koogeek-KLUP1","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} -Koogeek KLUP1 {"NAME":"Koogeek-KLUP1","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":1} +KMC 70011 {"NAME":"KMC 70011","GPIO":[17,0,0,0,133,132,0,0,130,56,21,0,0],"FLAG":0,"BASE":36} +Kogan SmarterHome™ Energy Meter {"NAME":"Kogan Smart Sw","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} Koogeek KLSP1 {"NAME":"Koogeek-KLSP1","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} -Laduo YX-DE01 {"NAME":"YX-DE01","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} -LA-WF3 {"NAME":"CE Smart Plug","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -LEPOWER {"NAME":"LEPOWER Outdoo","GPIO":[0,0,0,0,56,57,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +Koogeek KLUP1 {"NAME":"Koogeek-KLUP1","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} +LA-WF3 {"NAME":"CE Smart Plug","GPIO":[255,255,255,255,56,57,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} +Laduo YX-DE01 {"NAME":"YX-DE01","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18} LESHP KS-501 {"NAME":"LESHP KS-501","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} LINGANZH 16A {"NAME":"Linganzh Smart","GPIO":[56,0,0,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} Lonsonho 10A Type E {"NAME":"Lonsonho10ALed","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} Lonsonho RGB {"NAME":"RGB Smart Plug","GPIO":[37,0,38,0,0,39,0,0,0,17,0,21,0],"FLAG":0,"BASE":45} -LSC Smart Connect {"NAME":"LSC Smart Plug","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} +LSC Smart Connect {"NAME":"LSC Smart Plug","GPIO":[255,255,255,255,56,255,255,255,21,255,17,255,255],"FLAG":0,"BASE":18} +Luminea ZX-2820-675 {"NAME":"ZX2820-675","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Luminea ZX-2820-919 {"NAME":"Luminea ZX2820","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":65} +Martin Jerry {"NAME":"MJ V01","GPIO":[255,255,255,255,56,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} +Martin Jerry XS-SSA01 {"NAME":"MJ_XS-SSA01","GPIO":[0,0,0,0,0,0,0,0,56,17,0,21,0],"FLAG":0,"BASE":18} +Maxcio W-DE004 {"NAME":"Maxcio W-DE004","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} +Maxcio W-UK007 {"NAME":"Maxcio","GPIO":[0,17,0,0,0,0,255,255,0,56,21,0,0],"FLAG":0,"BASE":18} +Maxcio W-UK007S {"NAME":"Maxcio","GPIO":[56,0,255,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Maxcio W-US002S {"NAME":"W-US002S","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Maxcio W-US003 {"NAME":"W-US003","GPIO":[255,17,255,255,255,255,255,255,255,22,21,255,255],"FLAG":0,"BASE":18} +Maxcio YX-DE02 {"NAME":"Generic","GPIO":[255,17,255,21,56,37,255,255,38,39,40,255,255],"FLAG":1,"BASE":18} +Merisny P2 {"NAME":"Generic","GPIO":[0,0,52,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} +Merkury 70011 MIC-WW102 {"NAME":"MIC-WW102","GPIO":[17,0,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":36} +Merkury Innovations {"NAME":"Merkury Switch","GPIO":[255,255,255,255,53,56,255,255,21,17,255,255,255],"FLAG":1,"BASE":18} +Merkury MI-OW101-101W {"NAME":"Merkury Switch","GPIO":[17,255,255,255,255,56,255,255,255,255,21,255,255],"FLAG":1,"BASE":18} +Mirabella Genio {"NAME":"Genio 1","GPIO":[0,0,56,0,0,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} +Nanxin NX-SM200 16A {"NAME":"NX-SM200","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18} +NEO Coolcam 16A {"NAME":"Neo Coolcam 16","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":49} +Obi Stecker {"NAME":"OBI Socket","GPIO":[255,255,0,255,52,21,0,0,54,255,17,0,255],"FLAG":1,"BASE":51} +Obi Stecker 2 {"NAME":"OBI Socket 2","GPIO":[0,0,0,0,21,17,0,0,56,53,0,0,0],"FLAG":0,"BASE":61} +Obi Stecker IP44 {"NAME":"OBI Socket 2","GPIO":[0,0,0,0,21,17,0,0,56,53,0,0,0],"FLAG":0,"BASE":61} +Oittm Smart {"NAME":"Oittm","GPIO":[0,0,0,0,21,56,0,0,17,0,0,0,0],"FLAG":0,"BASE":1} +Oukitel P1 {"NAME":"Oukitel P1Dual","GPIO":[52,255,255,255,255,255,255,255,22,17,255,21,255],"FLAG":0,"BASE":18} +Oukitel X6P {"NAME":"OUKITEL X6P","GPIO":[255,255,57,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18} +OxaOxe NX-SM200 {"NAME":"NX-SM200","GPIO":[17,0,0,0,133,132,0,0,131,158,21,0,0],"FLAG":0,"BASE":18} +Oxaoxe NX-SM800 {"NAME":"NX-SM800","GPIO":[0,0,0,131,0,134,0,0,21,17,132,0,0],"FLAG":0,"BASE":45} +OxaOxe NX-SP202 {"NAME":"oxaoxe-dual","GPIO":[18,0,0,0,134,132,0,0,131,56,21,22,17],"FLAG":0,"BASE":18} +OxaOxe NX-SP202 v2 {"NAME":"oxaoxe-dold","GPIO":[56,0,0,131,17,134,0,0,21,18,132,22,0],"FLAG":0,"BASE":18} +Panamalar NX-SM200 16A {"NAME":"NX-SM200","GPIO":[0,0,0,0,56,134,0,0,131,17,132,21,0],"FLAG":1,"BASE":18} +Powertech {"NAME":"Jaycar","GPIO":[56,0,0,0,0,0,0,0,0,9,0,21,0],"FLAG":0,"BASE":6} +Powrui AW-08 {"NAME":"POWRUI AW-08","GPIO":[0,0,0,0,9,21,0,0,0,52,57,0,0],"FLAG":1,"BASE":18} +Prime CCRCWFII113PK {"NAME":"Prime","GPIO":[0,0,0,0,57,56,0,0,21,122,0,0,0],"FLAG":0,"BASE":18} +RGB Light {"NAME":"RGB Light","GPIO":[37,0,38,0,0,39,0,0,0,90,0,21,0],"FLAG":0,"BASE":18} +RSH-WS007 {"NAME":"RSH-WS007","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} +Shelly Plug S {"NAME":"Shelly Plug S","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":2,"BASE":45} +Slitinto NX-SM110 {"NAME":"Slitinto SM110","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Slitinto NX-SM112 {"NAME":"NX-SM112","GPIO":[158,0,0,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":45} +Slitinto NX-SP202 {"NAME":"Slitinto SP202","GPIO":[17,0,0,0,134,132,0,0,131,52,22,21,91],"FLAG":0,"BASE":64} +SM-PW702 {"NAME":"SM-PW702","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +SmartDGM PP-W162 {"NAME":"SmartDGM Plug","GPIO":[0,0,0,17,134,132,0,0,131,52,21,0,0],"FLAG":0,"BASE":18} +Sonoff S20 {"NAME":"Sonoff S20","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":8} +Sonoff S22 TH {"NAME":"Sonoff S22","GPIO":[17,255,0,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":4} +Sonoff S26 {"NAME":"Sonoff S26","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":8} +Sonoff S31 {"NAME":"Sonoff S31","GPIO":[17,145,0,146,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":41} +SP201 Dual {"NAME":"SP-201","GPIO":[31,0,0,131,17,134,0,0,21,18,132,22,0],"FLAG":0,"BASE":45} +SS01 {"NAME":"Smart Plug SS0","GPIO":[255,255,255,255,255,255,255,255,21,17,255,255,255],"FLAG":1,"BASE":18} +STITCH by Monoprice 27937 {"NAME":"Stitch 27937","GPIO":[17,0,56,0,133,132,0,0,131,0,21,0,57],"FLAG":0,"BASE":18} +STITCH by Monoprice 35511 {"NAME":"Stitch 35511","GPIO":[56,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} +SuperNight Dual {"NAME":"SuperNight Dua","GPIO":[255,17,255,21,132,133,255,255,22,130,58,255,255],"FLAG":1,"BASE":18} +SWA1 {"NAME":"SWA1","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +SWA1 {"NAME":"SWA1","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +SWA11 {"NAME":"SWA1","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +SWA9 {"NAME":"SWA9","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +TanTan WP3 {"NAME":"TanTan WP3","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Teckin SP10 {"NAME":"Teckin SP10","GPIO":[255,255,56,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18} +Teckin SP20 {"NAME":"TECKIN SP20","GPIO":[56,255,57,255,21,134,0,0,131,17,132,0,0],"FLAG":0,"BASE":45} +Teckin SP21 {"NAME":"Teckin SP21","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":45} +Teckin SP22 {"NAME":"Teckin","GPIO":[0,17,0,57,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":52} +Teckin SP23 {"NAME":"Teckin SP23","GPIO":[56,255,57,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Teckin SP25 {"NAME":"Teckin SP25","GPIO":[56,255,255,255,255,255,255,255,22,17,255,21,255],"FLAG":1,"BASE":18} +Teckin SP27 {"NAME":"Teckin SP27","GPIO":[56,255,255,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18} +Tflag NX-SM100 {"NAME":"NX-SM100","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18} +THRUMM XS-A11 {"NAME":"THRUMM XS-A11 ","GPIO":[255,17,255,255,255,255,255,255,255,56,29,255,255],"FLAG":0,"BASE":18} +Timethinker TK04 {"NAME":"TimethinkerEU","GPIO":[255,255,255,255,17,255,0,0,255,52,21,255,0],"FLAG":0,"BASE":18} +TimeThinker WS2 {"NAME":"TimeThinkerWS2","GPIO":[0,0,0,0,17,0,0,0,0,52,21,0,0],"FLAG":0,"BASE":18} +TomaxUSA HKWL-SO07W {"NAME":"HKWL-SO07W","GPIO":[17,255,255,255,255,255,255,255,255,255,21,255,56],"FLAG":0,"BASE":18} +WAGA life CHCZ02MB {"NAME":"WAGA CHCZ02MB","GPIO":[57,0,0,131,0,134,0,0,21,17,132,56,0],"FLAG":0,"BASE":68} +WAZA 10A {"NAME":"WAZA","GPIO":[0,0,0,0,21,17,0,0,56,0,0,0,0],"FLAG":1,"BASE":18} +WAZA JH-G01B {"NAME":"Teckin SP27","GPIO":[255,255,255,255,53,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} +WAZA JH-G01E {"NAME":"Waza JH-G01E","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +WiOn 50055 {"NAME":"WiOn","GPIO":[255,0,52,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17} +WL-SC01 {"NAME":"WL-SC01","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":1} +Woox R4026 {"NAME":"WOOX R4026","GPIO":[0,0,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +XS-SSA01 {"NAME":"XS-SSA01","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18} +XS-SSA01 Alternate {"NAME":"XS-SSA01","GPIO":[255,17,255,255,255,255,255,255,56,255,255,21,255],"FLAG":0,"BASE":18} +XS-SSA05 {"NAME":"XS-SSA05","GPIO":[30,255,255,131,255,133,255,255,21,17,132,31,255],"FLAG":1,"BASE":18} +XS-SSA06 {"NAME":"RGB Light","GPIO":[37,0,38,0,0,39,0,0,0,90,0,21,0],"FLAG":0,"BASE":18} +Yelomin JH-G01E {"NAME":"Yelomin","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":18} +YERON US101 {"NAME":"YERON_US101","GPIO":[255,255,255,17,133,132,255,255,131,56,21,255,255],"FLAG":0,"BASE":18} +YT-E003 {"NAME":"YT-E003-SP202","GPIO":[17,0,0,0,134,132,0,0,131,52,22,21,91],"FLAG":0,"BASE":64} +YX-WS02 {"NAME":"Amysen YX-WS02","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":1,"BASE":18} +ZBR-001 {"NAME":"ZBR-001","GPIO":[17,255,255,255,133,132,255,255,130,56,21,255,57],"FLAG":1,"BASE":18} +ZooZee {"NAME":"ZooZee","GPIO":[57,255,56,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18} +ZooZee SA102 {"NAME":"ZooZee","GPIO":[57,255,56,255,21,133,255,255,131,17,132,255,255],"FLAG":0,"BASE":18} +ZooZee SE131 {"NAME":"ZooZee SE131","GPIO":[255,0,56,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17} +ZSP-001 {"NAME":"ZSP-001","GPIO":[17,255,255,255,133,132,255,255,130,57,21,255,56],"FLAG":1,"BASE":18} ``` -## Power socket -``` -Bestten LO-2-W2 {"NAME":"BESTTEN LO-2-W","GPIO":[17,0,0,0,57,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} -Charging Essentials WiFi Smart {"NAME":"CESmart-Wall","GPIO":[0,0,0,0,0,17,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} -Kesen KS-604 {"NAME":"KS-604","GPIO":[0,0,52,0,0,18,0,0,22,21,0,0,17],"FLAG":0,"BASE":18} -Kesen KS-604S {"NAME":"KS-604S","GPIO":[0,0,31,0,0,18,0,0,22,21,0,0,17],"FLAG":1,"BASE":18} -``` - -## Power strip +## Power Strip ``` 3Stone (2019 Model) {"NAME":"3Stone-2019","GPIO":[0,0,56,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} ACENX 3AC+3USB {"NAME":"ACENX 3-Outlet","GPIO":[56,55,54,53,0,21,0,0,23,24,22,0,17],"FLAG":0,"BASE":18} @@ -240,62 +435,179 @@ Digoo DG-PS01 {"NAME":"Digoo DG-PS01","GPIO":[0,56,0,17,23,22,0,0,0,24,2 Geekbes 4AC+4USB {"NAME":"Geekbes 4xStri","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} Geeni GN-SW003 {"NAME":"Geeni GNCSW003","GPIO":[52,0,0,0,22,21,0,0,24,25,23,26,17],"FLAG":0,"BASE":18} Hyleton 330 {"NAME":"Hyleton-330","GPIO":[57,0,0,56,29,17,0,0,31,30,32,0,25],"FLAG":0,"BASE":18} -Hyleton 331 {"NAME":"HLT-331","GPIO":[52,0,0,57,29,17,0,0,31,30,32,0,58],"FLAG":0,"BASE":18} +Hyleton 331 {"NAME":"HLT-331","GPIO":[52,255,255,57,29,17,255,255,31,30,32,255,58],"FLAG":0,"BASE":18} Hyleton 336 {"NAME":"HLT-336","GPIO":[52,0,0,57,29,17,0,0,31,30,0,0,32],"FLAG":0,"BASE":18} KMC 5 {"NAME":"KMC 5-Outlet","GPIO":[56,0,0,0,25,9,0,0,22,21,23,0,24],"FLAG":0,"BASE":18} Koogeek KLOE4 {"NAME":"Koogeek KLOE4","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} LeFun SK2 {"NAME":"LeFun SK2","GPIO":[0,0,0,17,22,21,0,0,23,24,25,0,0],"FLAG":0,"BASE":18} +Meross MSS425 {"NAME":"Meross MSS425","GPIO":[33,0,0,0,56,0,0,0,21,17,22,23,32],"FLAG":0,"BASE":18} +Monoprice 34082 {"NAME":"Stitch 34082","GPIO":[255,255,255,255,21,20,255,255,23,22,24,255,255],"FLAG":0,"BASE":18} +Nedis WIFIP310FWT {"NAME":"Nedis WIFIP310","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18} +Powrui AW-39 {"NAME":"Porui AW-39","GPIO":[56,0,0,0,21,255,0,0,23,24,22,0,9],"FLAG":0,"BASE":18} +S2199EU {"NAME":"S2199EU","GPIO":[0,17,0,52,23,25,0,0,21,24,22,0,0],"FLAG":1,"BASE":18} +SM-S0301 {"NAME":"SM-SO301","GPIO":[56,0,0,0,30,17,0,0,32,31,33,0,21],"FLAG":0,"BASE":18} +SM-S0301 {"NAME":"SM-SO301","GPIO":[52,255,255,57,29,17,255,255,31,30,32,255,25],"FLAG":0,"BASE":18} +SWB1 {"NAME":"SWB1","GPIO":[52,0,0,0,0,24,0,0,21,17,22,23,0],"FLAG":0,"BASE":18} +Teckin SS30 {"NAME":"Teckin SS30","GPIO":[52,255,255,57,29,17,255,255,31,30,32,255,58],"FLAG":0,"BASE":18} +Tellur TLL331031 {"NAME":"Tellur","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18} +TESSAN A4L-BK {"NAME":"TESSAN A4L-BK","GPIO":[0,0,0,24,23,0,255,255,21,0,22,0,0],"FLAG":0,"BASE":18} +Viflykoo 3AC+4USB {"NAME":"Viflykoo 3xStr","GPIO":[0,0,53,0,0,23,0,0,21,56,17,24,22],"FLAG":1,"BASE":18} +Woox R4028 {"NAME":"Woox R4028","GPIO":[0,56,0,17,23,22,0,0,0,24,21,0,0],"FLAG":1,"BASE":18} +Xenon SM-S0301 {"NAME":"SM-SO301","GPIO":[52,255,255,57,29,17,255,255,31,30,32,255,25],"FLAG":0,"BASE":18} +XS-A25 {"NAME":"XS-A25","GPIO":[52,0,53,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} +XSA26-EU {"NAME":"XSA26-EU","GPIO":[52,0,53,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} +Yagala {"NAME":"Yagala","GPIO":[0,0,0,17,22,24,0,0,23,25,21,0,0],"FLAG":0,"BASE":18} +Yagala SWB3 {"NAME":"YAGALA SWB3","GPIO":[0,0,53,0,0,23,0,0,21,0,22,24,0],"FLAG":1,"BASE":18} +Yagala SWB3 v2 {"NAME":"YAGALA SWB3","GPIO":[157,0,53,0,0,23,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +Yuanguo 4AC + 2 USB {"NAME":"YUANGUO","GPIO":[0,20,0,24,19,18,0,0,17,22,21,23,0],"FLAG":0,"BASE":1} +Zeoota PS022 {"NAME":"ZEOOTA 3x plus","GPIO":[0,57,0,56,22,21,0,0,17,23,24,0,0],"FLAG":1,"BASE":18} +ZLD-44EU-W {"NAME":"ZLD-44EU-W","GPIO":[17,255,255,255,22,21,18,19,23,24,25,0,0],"FLAG":0,"BASE":23} +ZLD-44USA-W {"NAME":"ZLD-44USA-W","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} +ZLD64-EU-W {"NAME":"ZLD64-EU-W","GPIO":[0,56,0,17,22,21,0,0,0,0,23,0,0],"FLAG":0,"BASE":18} ``` -## Relay module +## RF Bridge ``` -Blitzwolf BW-SS1 {"NAME":"BW-SS1","GPIO":[255,255,255,255,157,21,0,0,255,17,255,255,0],"FLAG":15,"BASE":18} +Sonoff RF Bridge 433 {"NAME":"Sonoff Bridge","GPIO":[17,148,255,149,255,255,0,0,255,56,255,0,0],"FLAG":0,"BASE":25} +``` + +## Relay +``` +1 Channel Inching/Self-Locking {"NAME":"1 Channel","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":12} +Blitzwolf BW-SS1 {"NAME":"BW-SS1","GPIO":[255,255,255,255,157,21,0,0,255,17,255,255,0],"FLAG":0,"BASE":18} Canwing CW-001 {"NAME":"Canwing CW-001","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} EACHEN ST-DC2 {"NAME":"Garage Control","GPIO":[11,0,0,0,23,22,18,0,21,52,12,24,0],"FLAG":1,"BASE":18} Electrodragon Board SPDT {"NAME":"ED Relay Board","GPIO":[255,255,255,255,255,255,255,255,21,22,255,255,52],"FLAG":1,"BASE":18} Electrodragon ESP8266 {"NAME":"ElectroDragon","GPIO":[18,255,17,255,255,255,0,0,22,21,255,255,52],"FLAG":1,"BASE":15} -eMylo SS-8839-03 {"NAME":"eMylo","GPIO":[0,0,0,0,52,0,0,0,21,0,17,0,0],"FLAG":1,"BASE":18} +eMylo SS-8839-03 {"NAME":"eMylo","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":1,"BASE":18} eMylo XL9251WI {"NAME":"XL9251WI","GPIO":[255,255,255,255,56,255,255,255,21,255,17,255,255],"FLAG":0,"BASE":18} eMylo YSA111A1N-FBA {"NAME":"Emylo","GPIO":[255,255,255,255,52,255,255,255,21,255,17,255,255],"FLAG":0,"BASE":18} -Zemismart ERC309 Kinetic {"NAME":"Kinetic Switch","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} ESP-01 Relay V4.0 {"NAME":"ESP01v4","GPIO":[29,52,0,255,255,255,255,255,255,255,255,255,255],"FLAG":0,"BASE":18} EX Store 2 Kanal V5 {"NAME":"EXS Relay V5","GPIO":[255,255,255,255,255,255,0,0,21,22,31,52,32],"FLAG":0,"BASE":16} Geekcreit 2 Channel {"NAME":"Geekcreit 2ch","GPIO":[17,0,0,0,0,22,18,0,21,52,0,0,0],"FLAG":1,"BASE":18} Gocomma Wi-Fi Smart Switch {"NAME":"GoCommaSmartSw","GPIO":[17,255,255,255,21,255,255,255,255,56,255,255,255],"FLAG":0,"BASE":18} LC Technology 4CH {"NAME":"LC-Tech_4CH ","GPIO":[52,255,17,255,255,255,255,255,21,22,23,24,255],"FLAG":0,"BASE":18} -LC-Tech 1Ch and PZEM-004T {"NAME":"HW-655 PZEM","GPIO":[0,63,0,62,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} LinkNode R4 {"NAME":"LinkNode R4","GPIO":[0,0,0,0,0,0,0,0,21,22,23,0,24],"FLAG":0,"BASE":18} LinkNode R8 {"NAME":"LinkNode R8","GPIO":[0,0,0,0,25,26,0,28,23,24,22,27,21],"FLAG":0,"BASE":18} +MHCOZY {"NAME":"Portail","GPIO":[9,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":1,"BASE":18} +Moeshouse 2 way 2 gang MS-104B {"NAME":"moeshouse2gang","GPIO":[0,0,17,0,160,0,0,0,43,42,21,22,0],"FLAG":0,"BASE":18} +Nova Digital Basic 1 MS101 {"NAME":"NovaDigBasic1","GPIO":[255,255,255,255,56,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} +QS-WIFI-S03 {"NAME":"Generic","GPIO":[17,255,255,255,255,0,0,0,82,21,0,0,0],"FLAG":0,"BASE":1} +Shelly 1 {"NAME":"Shelly 1","GPIO":[0,0,0,0,21,82,0,0,0,0,0,0,0],"FLAG":0,"BASE":46} +Shelly 1PM {"NAME":"Shelly 1PM","GPIO":[56,0,0,0,82,134,0,0,0,0,0,21,0],"FLAG":2,"BASE":18} +Shelly 2 {"NAME":"Shelly 2","GPIO":[0,135,0,136,21,22,0,0,9,0,10,137,0],"FLAG":0,"BASE":47} +Shelly 2.5 {"NAME":"Shelly 2.5","GPIO":[56,255,17,255,21,83,0,0,6,82,5,22,156],"FLAG":2,"BASE":18} +SmartHome Smart Breaker {"NAME":"SmartHome Swit","GPIO":[255,255,255,255,21,255,255,255,17,57,255,56,255],"FLAG":0,"BASE":18} +Sonoff 4CH (R2) {"NAME":"Sonoff 4CH","GPIO":[17,255,255,255,23,22,18,19,21,56,20,24,0],"FLAG":0,"BASE":7} +Sonoff 4CH Pro (R2) {"NAME":"Sonoff 4CH Pro","GPIO":[17,255,255,255,23,22,18,19,21,56,20,24,0],"FLAG":0,"BASE":23} +Sonoff 5V Inching/Selflock Module RE5V1C {"NAME":"Sonoff RE5V1C","GPIO":[17,255,255,255,255,255,0,0,21,56,0,0,0],"FLAG":0,"BASE":18} +Sonoff Basic {"NAME":"Sonoff Basic","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":1} +Sonoff Basic R3 {"NAME":"Basic R3","GPIO":[17,255,0,255,255,0,255,255,21,56,255,0,255],"FLAG":0,"BASE":1} +Sonoff Dual {"NAME":"Sonoff Dual","GPIO":[0,148,0,149,255,0,0,0,0,56,255,0,0],"FLAG":0,"BASE":5} +Sonoff Dual R2 {"NAME":"Sonoff Dual R2","GPIO":[255,255,0,255,0,22,255,17,21,56,0,0,0],"FLAG":0,"BASE":39} +Sonoff Mini {"NAME":"Sonoff Mini","GPIO":[17,0,0,0,9,0,0,0,21,56,0,0,255],"FLAG":0,"BASE":1} +Sonoff Pow {"NAME":"Sonoff Pow","GPIO":[17,0,0,0,0,130,0,0,21,132,133,52,0],"FLAG":0,"BASE":6} +Sonoff Pow R2 {"NAME":"Sonoff Pow R2","GPIO":[17,145,0,146,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":43} +Sonoff RF {"NAME":"Sonoff RF","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":2} +Sonoff SV {"NAME":"Sonoff SV","GPIO":[17,255,0,255,255,255,0,0,21,56,255,0,0],"FLAG":1,"BASE":3} +Sonoff TH10/TH16 {"NAME":"Sonoff TH","GPIO":[17,255,0,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":4} +Tuya Kinetic Switch {"NAME":"Kinetic Switch","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Wemos Module 10A {"NAME":"WeMos Relay","GPIO":[17,255,52,255,21,255,255,255,255,255,255,255,255],"FLAG":0,"BASE":18} +WL-SW01_10 {"NAME":"WL-SW01_10","GPIO":[17,149,0,148,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +Yunshan 10A 7-30VDC {"NAME":"Yunshan Relay","GPIO":[0,255,56,255,21,17,0,0,0,0,0,0,0],"FLAG":0,"BASE":33} +Zemismart ERC309 Kinetic {"NAME":"Kinetic Switch","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} ``` ## Switch ``` -3A Smart Home HGZB-043 {"NAME":"3A Smart Home","GPIO":[52,0,55,18,22,19,0,0,17,21,54,23,53],"FLAG":0,"BASE":18} +3A Smart Home HGZB-043 {"NAME":"3A Smart Home ","GPIO":[52,0,55,18,22,19,0,0,17,21,54,23,53],"FLAG":0,"BASE":18} Deta 6912HA {"NAME":"DETA 2G Switch","GPIO":[0,0,0,0,157,0,0,0,91,21,22,0,90],"FLAG":0,"BASE":18} DS-102 1 Gang {"NAME":"DS-102 1 Gang","GPIO":[57,0,0,17,0,0,0,0,0,21,56,0,0],"FLAG":1,"BASE":18} -DS-102 2 Gang {"NAME":"DS-102 2 Gang","GPIO":[56,58,0,17,22,18,0,0,0,21,57,0,0],"FLAG":0,"BASE":18} +DS-102 2 Gang {"NAME":"DS-102 2 Gang","GPIO":[56,58,0,17,22,18,0,0,0,21,57,255,0],"FLAG":0,"BASE":18} DS-102 3 Gang {"NAME":"DS-102 3 Gang","GPIO":[158,58,0,18,22,19,0,0,17,21,57,23,56],"FLAG":0,"BASE":18} Enjowi WF-SK301 {"NAME":"Tuya 3 Channel","GPIO":[0,0,0,0,23,18,0,0,17,21,19,22,157],"FLAG":0,"BASE":18} Etekcity 3-way {"NAME":"Etekcity 3Way","GPIO":[255,255,0,255,23,29,0,0,82,22,10,0,0],"FLAG":0,"BASE":18} -EtekCity ESWL01 {"NAME":"EtekCityESWL01","GPIO":[0,0,0,0,52,53,0,0,0,21,122,0,0],"FLAG":1,"BASE":18} +EtekCity ESWL01 {"NAME":"EtekCityESWL01","GPIO":[255,255,255,255,52,53,255,255,255,21,122,255,255],"FLAG":1,"BASE":18} Gosund KS-602S {"NAME":"Gosund KS-602S","GPIO":[17,56,0,0,0,0,0,0,0,0,21,0,158],"FLAG":0,"BASE":18} Jinvoo SM-SW101-1 {"NAME":"SM-SW101-1","GPIO":[52,0,0,18,0,0,0,0,17,21,0,0,0],"FLAG":1,"BASE":18} Jinvoo SM-SW101-2 {"NAME":"SM-SW101-2","GPIO":[52,0,0,18,22,0,0,0,17,21,0,0,0],"FLAG":1,"BASE":18} Jinvoo SM-SW101-3 {"NAME":"Jinvoo Wall Sw","GPIO":[52,0,0,18,22,19,0,0,17,21,0,23,0],"FLAG":1,"BASE":18} Jinvoo SM-SW101-C Curtain {"NAME":"Jinvoo Curtain","GPIO":[52,0,0,18,22,19,0,0,17,21,0,23,0],"FLAG":1,"BASE":18} -KMC 70008 {"NAME":"KMC 70008","GPIO":[17,0,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +KMC 70008 {"NAME":"KMC 70008","GPIO":[17,255,255,0,0,255,255,255,0,56,21,255,255],"FLAG":0,"BASE":18} KOAANW DS302 {"NAME":"DS302","GPIO":[0,0,0,19,23,18,0,0,17,21,0,22,52],"FLAG":1,"BASE":18} -Kuled K36 {"NAME":"KULED-B","GPIO":[9,0,0,0,0,0,21,52,29,56,0,0,0],"FLAG":0,"BASE":18} -Kuled KS602S {"NAME":"KULED","GPIO":[9,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":18} +KS-601 2-way {"NAME":"2way Switch","GPIO":[255,255,158,255,255,83,255,255,22,21,255,82,255],"FLAG":0,"BASE":18} +Kuled K36 {"NAME":"KULED-B","GPIO":[9,255,255,255,255,255,21,52,29,56,255,255,255],"FLAG":0,"BASE":18} +Kuled KS602S {"NAME":"KULED","GPIO":[9,255,255,255,255,255,255,255,21,56,255,255,255],"FLAG":0,"BASE":18} KYGNE CD-301 {"NAME":"KYGNE Touch","GPIO":[0,0,0,0,52,53,0,0,21,17,0,0,0],"FLAG":0,"BASE":10} Lonsonho SK3-01 {"NAME":"Tuya 1 Channel","GPIO":[0,0,0,0,0,17,0,0,0,0,0,21,52],"FLAG":0,"BASE":18} Lonsonho SK3-02 {"NAME":"Tuya 2 Channel","GPIO":[0,0,0,0,22,0,0,0,17,21,18,0,52],"FLAG":0,"BASE":18} +Luminea LHC-101.on {"NAME":"LHC-101.on","GPIO":[157,0,0,17,21,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":18} +Luminea LHC-102.on {"NAME":"LHC-102.on","GPIO":[157,0,53,0,0,18,0,0,17,21,0,22,52],"FLAG":0,"BASE":18} +LX-WIFI-00M 4 Gang {"NAME":"LX-WIFI-00M","GPIO":[17,25,255,255,23,22,18,19,21,0,20,24,0],"FLAG":0,"BASE":7} +LYASI B07PYMG3WD {"NAME":"LYASI Touch Sw","GPIO":[0,0,0,0,56,52,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Martin Jerry 15A {"NAME":"MJ Switch","GPIO":[255,255,255,255,57,56,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} +Martin Jerry 3 Way {"NAME":"MJ 3Way Switch","GPIO":[255,255,255,255,52,53,0,0,21,9,157,255,0],"FLAG":0,"BASE":18} +Merkury MI-WW107-199W {"NAME":"MI-WW107-199W","GPIO":[52,0,0,0,0,0,0,0,17,21,0,0,0],"FLAG":0,"BASE":18} +Minitiger 1 Gang {"NAME":"minitiger 1 Gang","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} +Minitiger 2 Gang {"NAME":"minitiger 2 Gang","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":28} +Moes 1 Gang Touch {"NAME":"B07C8FJY3G","GPIO":[54,0,0,17,21,0,0,0,0,0,52,0,55],"FLAG":0,"BASE":18} +Moes 2 Gang Touch {"NAME":"B07BLZFQZZ ","GPIO":[52,0,53,0,0,18,0,0,17,21,0,22,54],"FLAG":0,"BASE":18} +Moes 2 Gang Touch {"NAME":"Tuya Moes 2 Ch","GPIO":[25,255,24,0,0,18,0,0,17,21,0,22,23],"FLAG":0,"BASE":18} +Moes 3 Gang Touch {"NAME":"Tuya Moes 3 Ch","GPIO":[27,255,26,18,22,19,0,0,17,21,25,23,24],"FLAG":0,"BASE":18} +Moes 3-Way {"NAME":"Moes 3-Way","GPIO":[255,255,255,255,21,57,0,0,30,10,9,255,255],"FLAG":0,"BASE":18} +Moko {"NAME":"Moko Switch","GPIO":[0,0,0,17,21,134,0,0,0,0,0,0,0],"FLAG":0,"BASE":59} +Nexete DS-123 {"NAME":"DS-123","GPIO":[157,57,255,17,21,18,0,0,255,22,56,255,255],"FLAG":0,"BASE":18} +Sainko 1-Way {"NAME":"SAINKO 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} +SANA {"NAME":"SW02-03","GPIO":[56,255,255,19,23,18,255,255,17,21,255,22,255],"FLAG":0,"BASE":18} +SANA SASW-03 {"NAME":"SANA SASW-03","GPIO":[54,0,0,19,23,18,0,0,17,21,0,22,0],"FLAG":0,"BASE":18} +Sesoo SK3-04 {"NAME":"Tuya 4 Channel","GPIO":[52,255,255,19,23,17,0,0,20,24,22,21,18],"FLAG":0,"BASE":18} +Sesoo WIFI-US-SK3-04 {"NAME":"WIFI-US-SK3-04","GPIO":[255,255,255,19,23,17,0,0,20,24,22,21,18],"FLAG":0,"BASE":18} +SmartPlex 3 Gang {"NAME":"Tuya 3 Channel","GPIO":[255,255,255,255,21,18,0,0,19,23,17,22,255],"FLAG":0,"BASE":18} +Sonoff T1 EU 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} +Sonoff T1 EU 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} +Sonoff T1 UK 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} +Sonoff T1 UK 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} +Sonoff T1 UK 3 Gang {"NAME":"Sonoff T1 3CH","GPIO":[17,255,255,255,23,22,18,19,21,56,0,0,0],"FLAG":0,"BASE":30} +Sonoff T1 US 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} +Sonoff T1 US 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} +Sonoff T1 US 3 Gang {"NAME":"Sonoff T1 3CH","GPIO":[17,255,255,255,23,22,18,19,21,56,0,0,0],"FLAG":0,"BASE":30} +Sonoff Touch EU {"NAME":"Sonoff Touch","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":10} +Sonoff Touch US {"NAME":"Sonoff Touch","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":10} +SS118-01K1 {"NAME":"SS118-01K1","GPIO":[255,255,255,17,21,255,255,255,255,255,56,255,255],"FLAG":0,"BASE":18} +STITCH by Monoprice 35557 {"NAME":"Tuya WF15S ","GPIO":[255,255,0,0,255,255,0,0,255,108,255,107,0],"FLAG":0,"BASE":54} +Teepao Smart-Rollladen-Schalter {"NAME":"Teepao","GPIO":[158,58,23,18,22,19,0,0,56,21,57,0,17],"FLAG":0,"BASE":18} +Tonbux AMZ180648-2 {"NAME":"Tonbux","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":1} +Touch 2 Gang {"NAME":"tuya_2_gang","GPIO":[52,0,0,0,18,0,0,0,17,21,255,22,29],"FLAG":0,"BASE":18} +TreatLife SS01S {"NAME":"TL SS01S Swtch","GPIO":[0,0,0,0,52,158,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +WS-US-03 {"NAME":"WS-US-03","GPIO":[17,255,255,255,23,22,18,19,21,56,0,0,0],"FLAG":0,"BASE":30} +Xenon SM-SW102-2 {"NAME":"SM SW102","GPIO":[255,255,255,18,22,255,255,255,17,21,255,255,255],"FLAG":0,"BASE":18} +Youngzuth SW02 2-way {"NAME":"SW02 2W","GPIO":[52,255,255,9,21,255,255,255,10,22,255,255,255],"FLAG":0,"BASE":18} +Zemismart KS-611 3 Gang {"NAME":"Zemismart 3 Ga","GPIO":[0,0,56,0,19,18,0,0,22,21,23,0,17],"FLAG":0,"BASE":18} +Zemismart KS-811 1 gang {"NAME":"KS-811 Single","GPIO":[17,255,255,255,255,255,255,255,21,56,255,255,255],"FLAG":0,"BASE":18} +Zemismart KS-811 2 Gang {"NAME":"KS-811 Dual","GPIO":[255,255,52,255,255,18,255,255,22,21,255,255,17],"FLAG":0,"BASE":18} +Zemismart KS-811 3 Gang {"NAME":"KS-811 Triple","GPIO":[255,255,56,255,19,18,255,255,22,21,23,255,17],"FLAG":0,"BASE":18} +Zemismart WF-BS01 {"NAME":"WF-BS01","GPIO":[53,0,0,17,21,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":18} +Zemismart ZM-L02E {"NAME":"ZSmart ZM-L02E","GPIO":[255,255,255,255,255,17,255,255,18,21,22,255,255],"FLAG":0,"BASE":18} ``` -## Miscellaneous +## Valve ``` -Asakuki 500ml {"NAME":"Oil Diffuser","GPIO":[255,255,255,255,255,255,255,255,255,255,255,21,22],"FLAG":0,"BASE":18} -Hoenyzy DN20 3/4 {"NAME":"DN20 WIFI Valve","GPIO":[0,0,0,0,0,0,0,0,17,21,0,0,0],"FLAG":0,"BASE":18} -Jinvoo SM-AW713 {"NAME":"Jinvoo Valve","GPIO":[0,0,0,0,0,52,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Hoenyzy DN20 3/4 {"NAME":"Unbranded TYWE3S DN20 WIFI Valve","GPIO":[0,0,0,0,0,0,0,0,17,21,0,0,0],"FLAG":0,"BASE":18} Jinvoo SM-PW713 {"NAME":"Jinvoo Valve","GPIO":[0,0,0,0,21,52,0,0,17,53,0,0,0],"FLAG":1,"BASE":18} +TopKitchen Irrigation Timer {"NAME":"HoseController","GPIO":[255,255,255,255,255,255,255,255,255,255,255,21,22],"FLAG":1,"BASE":18} +``` + +## Wall Outlet +``` +Bestten LO-2-W2 {"NAME":"BESTTEN LO-2-W","GPIO":[17,0,0,0,57,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +Charging Essentials WiFi Smart {"NAME":"CESmart-Wall","GPIO":[255,255,255,255,255,17,255,255,21,255,255,255,255],"FLAG":0,"BASE":18} +Kesen KS-604 {"NAME":"KS-604","GPIO":[255,255,52,255,255,18,255,255,22,21,255,255,17],"FLAG":0,"BASE":18} +Kesen KS-604S {"NAME":"KS-604S","GPIO":[255,255,31,255,255,18,255,255,22,21,255,255,17],"FLAG":1,"BASE":18} +MakeGood MG-AUWF01 {"NAME":"MG-AUWF01","GPIO":[56,10,157,59,134,132,255,255,131,22,57,21,9],"FLAG":0,"BASE":18} +MoesHouse Smart Socket {"NAME":"Smart Socket","GPIO":[255,255,255,255,52,53,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} +Smanergy KA10 {"NAME":"KA10","GPIO":[0,56,0,17,134,132,0,0,131,53,21,0,0],"FLAG":0,"BASE":64} +Sonoff S55 {"NAME":"Sonoff S55","GPIO":[17,255,0,255,255,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +Topgreener TGWF15RM {"NAME":"TGWF15RM","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} +Vigica VGSPK00815 {"NAME":"VIGICA outlet","GPIO":[17,255,255,255,255,22,18,255,21,255,255,255,255],"FLAG":1,"BASE":18} +WWK-UN-W Glass Panel {"NAME":"tuya wall sock","GPIO":[255,255,255,255,52,53,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} ``` \ No newline at end of file From ce4ef9d258e1d91d6baae5e4286004f5d20a47e0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 23 Oct 2019 11:17:41 +0200 Subject: [PATCH 2219/2222] Update TEMPLATES.md --- TEMPLATES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TEMPLATES.md b/TEMPLATES.md index 13aa9e085..2cb5b4773 100644 --- a/TEMPLATES.md +++ b/TEMPLATES.md @@ -2,7 +2,7 @@ # Templates -Find below a the available templates as of October 22nd, 2019. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) +Find below the available templates as of October 22nd, 2019. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) ## Bulb ``` From 9a1474c6b16733b1f7cd3b017bc9a2def38e701f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 23 Oct 2019 11:26:28 +0200 Subject: [PATCH 2220/2222] Fix core 2.3.0 compile error Fix core 2.3.0 compile error (#6721) --- sonoff/sonoff_post.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 74be27fdb..760d64565 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -24,7 +24,6 @@ * Function declarations \*********************************************************************************************/ -/* #ifdef __cplusplus extern "C" { #endif @@ -34,7 +33,6 @@ extern "C" { #ifdef __cplusplus } #endif -*/ //#ifdef USE_KNX // Enabling this will fail compilation. It has no impact if not used. (20180417) #include From 6002407043ee6edcce4441b08532210d142450d8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 23 Oct 2019 11:33:35 +0200 Subject: [PATCH 2221/2222] Refactoring --- sonoff/sonoff_post.h | 3 +-- sonoff/support_wifi.ino | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 760d64565..b8b282fa7 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -24,12 +24,11 @@ * Function declarations \*********************************************************************************************/ +// Needed for core 2.3.0 compilation (#6721) #ifdef __cplusplus extern "C" { #endif - #include "user_interface.h" - #ifdef __cplusplus } #endif diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 23727fcbe..a0f4bd3e5 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -74,10 +74,6 @@ bool WifiConfigCounter(void) return (Wifi.config_counter); } -//extern "C" { -//#include "user_interface.h" -//} - void WifiConfig(uint8_t type) { if (!Wifi.config_type) { From 0ebec1fa2ea233643107800a3c8c3cd1cd267989 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 23 Oct 2019 12:26:01 +0200 Subject: [PATCH 2222/2222] Add support for Arduino IDE OTA upload --- arduino/version pre-2.6.0/boards.txt | 6448 ++++++++++++++++++++++++ arduino/version pre-2.6.0/platform.txt | 166 + 2 files changed, 6614 insertions(+) create mode 100644 arduino/version pre-2.6.0/boards.txt create mode 100644 arduino/version pre-2.6.0/platform.txt diff --git a/arduino/version pre-2.6.0/boards.txt b/arduino/version pre-2.6.0/boards.txt new file mode 100644 index 000000000..401ff23ea --- /dev/null +++ b/arduino/version pre-2.6.0/boards.txt @@ -0,0 +1,6448 @@ +# +# Do not create pull-requests for this file only, CI will not accept them. +# You *must* edit/modify/run boards.txt.py to regenerate boards.txt. +# All modified files after running with option "--allgen" must be included in the pull-request. +# + +menu.BoardModel=Model +menu.baud=Upload Speed + +menu.UploadTool=Upload Using + +menu.xtal=CPU Frequency +menu.CrystalFreq=Crystal Frequency +menu.eesz=Flash Size +menu.FlashMode=Flash Mode +menu.FlashFreq=Flash Frequency +menu.ResetMethod=Reset Method +menu.ESPModule=Module +menu.dbg=Debug port +menu.lvl=Debug Level +menu.ip=lwIP Variant +menu.vt=VTables +menu.exception=Exceptions +menu.led=Builtin Led +menu.wipe=Erase Flash +menu.sdk=Espressif FW +menu.ssl=SSL Support + +############################################################## +generic.name=Generic ESP8266 Module +generic.build.board=ESP8266_GENERIC +generic.upload.tool=esptool +generic.upload.maximum_data_size=81920 +generic.upload.wait_for_upload_port=true +generic.upload.erase_cmd=version +generic.serial.disableDTR=true +generic.serial.disableRTS=true +generic.build.mcu=esp8266 +generic.build.core=esp8266 +generic.build.variant=generic +generic.build.spiffs_pagesize=256 +generic.build.debug_port= +generic.build.debug_level= + +generic.menu.UploadTool.esptool=Serial +generic.menu.UploadTool.esptool.upload.tool=esptool +generic.menu.UploadTool.esptool.upload.verbose=-vv +generic.menu.UploadTool.espupload=OTA_upload +generic.menu.UploadTool.espupload.upload.tool=espupload + +generic.menu.xtal.80=80 MHz +generic.menu.xtal.80.build.f_cpu=80000000L +generic.menu.xtal.160=160 MHz +generic.menu.xtal.160.build.f_cpu=160000000L +generic.menu.vt.flash=Flash +generic.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +generic.menu.vt.heap=Heap +generic.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +generic.menu.vt.iram=IRAM +generic.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +generic.menu.exception.legacy=Legacy (new can return nullptr) +generic.menu.exception.legacy.build.exception_flags=-fno-exceptions +generic.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +generic.menu.exception.disabled=Disabled (new can abort) +generic.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +generic.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +generic.menu.exception.enabled=Enabled +generic.menu.exception.enabled.build.exception_flags=-fexceptions +generic.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +generic.menu.ssl.all=All SSL ciphers (most compatible) +generic.menu.ssl.all.build.sslflags= +generic.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +generic.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +generic.menu.ResetMethod.ck=ck +generic.menu.ResetMethod.ck.upload.resetmethod=ck +generic.menu.ResetMethod.nodemcu=nodemcu +generic.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +generic.menu.ResetMethod.none=none +generic.menu.ResetMethod.none.upload.resetmethod=none +generic.menu.ResetMethod.dtrset=dtrset +generic.menu.ResetMethod.dtrset.upload.resetmethod=dtrset +generic.menu.CrystalFreq.26=26 MHz +generic.menu.CrystalFreq.40=40 MHz +generic.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +generic.menu.FlashFreq.40=40MHz +generic.menu.FlashFreq.40.build.flash_freq=40 +generic.menu.FlashFreq.80=80MHz +generic.menu.FlashFreq.80.build.flash_freq=80 +generic.menu.FlashFreq.20=20MHz +generic.menu.FlashFreq.20.build.flash_freq=20 +generic.menu.FlashFreq.26=26MHz +generic.menu.FlashFreq.26.build.flash_freq=26 +generic.menu.FlashMode.dout=DOUT (compatible) +generic.menu.FlashMode.dout.build.flash_mode=dout +generic.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT +generic.menu.FlashMode.dio=DIO +generic.menu.FlashMode.dio.build.flash_mode=dio +generic.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO +generic.menu.FlashMode.qout=QOUT +generic.menu.FlashMode.qout.build.flash_mode=qout +generic.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT +generic.menu.FlashMode.qio=QIO (fast) +generic.menu.FlashMode.qio.build.flash_mode=qio +generic.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO +generic.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) +generic.menu.eesz.1M64.build.flash_size=1M +generic.menu.eesz.1M64.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +generic.menu.eesz.1M64.build.spiffs_pagesize=256 +generic.menu.eesz.1M64.upload.maximum_size=958448 +generic.menu.eesz.1M64.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M64.build.spiffs_start=0xEB000 +generic.menu.eesz.1M64.build.spiffs_end=0xFB000 +generic.menu.eesz.1M64.build.spiffs_blocksize=4096 +generic.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) +generic.menu.eesz.1M128.build.flash_size=1M +generic.menu.eesz.1M128.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +generic.menu.eesz.1M128.build.spiffs_pagesize=256 +generic.menu.eesz.1M128.upload.maximum_size=892912 +generic.menu.eesz.1M128.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M128.build.spiffs_start=0xDB000 +generic.menu.eesz.1M128.build.spiffs_end=0xFB000 +generic.menu.eesz.1M128.build.spiffs_blocksize=4096 +generic.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) +generic.menu.eesz.1M144.build.flash_size=1M +generic.menu.eesz.1M144.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +generic.menu.eesz.1M144.build.spiffs_pagesize=256 +generic.menu.eesz.1M144.upload.maximum_size=876528 +generic.menu.eesz.1M144.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M144.build.spiffs_start=0xD7000 +generic.menu.eesz.1M144.build.spiffs_end=0xFB000 +generic.menu.eesz.1M144.build.spiffs_blocksize=4096 +generic.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) +generic.menu.eesz.1M160.build.flash_size=1M +generic.menu.eesz.1M160.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +generic.menu.eesz.1M160.build.spiffs_pagesize=256 +generic.menu.eesz.1M160.upload.maximum_size=860144 +generic.menu.eesz.1M160.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M160.build.spiffs_start=0xD3000 +generic.menu.eesz.1M160.build.spiffs_end=0xFB000 +generic.menu.eesz.1M160.build.spiffs_blocksize=4096 +generic.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) +generic.menu.eesz.1M192.build.flash_size=1M +generic.menu.eesz.1M192.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +generic.menu.eesz.1M192.build.spiffs_pagesize=256 +generic.menu.eesz.1M192.upload.maximum_size=827376 +generic.menu.eesz.1M192.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M192.build.spiffs_start=0xCB000 +generic.menu.eesz.1M192.build.spiffs_end=0xFB000 +generic.menu.eesz.1M192.build.spiffs_blocksize=4096 +generic.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) +generic.menu.eesz.1M256.build.flash_size=1M +generic.menu.eesz.1M256.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +generic.menu.eesz.1M256.build.spiffs_pagesize=256 +generic.menu.eesz.1M256.upload.maximum_size=761840 +generic.menu.eesz.1M256.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M256.build.spiffs_start=0xBB000 +generic.menu.eesz.1M256.build.spiffs_end=0xFB000 +generic.menu.eesz.1M256.build.spiffs_blocksize=4096 +generic.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) +generic.menu.eesz.1M512.build.flash_size=1M +generic.menu.eesz.1M512.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +generic.menu.eesz.1M512.build.spiffs_pagesize=256 +generic.menu.eesz.1M512.upload.maximum_size=499696 +generic.menu.eesz.1M512.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M512.build.spiffs_start=0x7B000 +generic.menu.eesz.1M512.build.spiffs_end=0xFB000 +generic.menu.eesz.1M512.build.spiffs_blocksize=8192 +generic.menu.eesz.1M=1MB (FS:none OTA:~502KB) +generic.menu.eesz.1M.build.flash_size=1M +generic.menu.eesz.1M.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +generic.menu.eesz.1M.build.spiffs_pagesize=256 +generic.menu.eesz.1M.upload.maximum_size=1023984 +generic.menu.eesz.1M.build.rfcal_addr=0xFC000 +generic.menu.eesz.2M64=2MB (FS:64KB OTA:~992KB) +generic.menu.eesz.2M64.build.flash_size=2M +generic.menu.eesz.2M64.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M64.build.flash_ld=eagle.flash.2m64.ld +generic.menu.eesz.2M64.build.spiffs_pagesize=256 +generic.menu.eesz.2M64.upload.maximum_size=1044464 +generic.menu.eesz.2M64.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M64.build.spiffs_start=0x1F0000 +generic.menu.eesz.2M64.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M64.build.spiffs_blocksize=4096 +generic.menu.eesz.2M128=2MB (FS:128KB OTA:~960KB) +generic.menu.eesz.2M128.build.flash_size=2M +generic.menu.eesz.2M128.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld +generic.menu.eesz.2M128.build.spiffs_pagesize=256 +generic.menu.eesz.2M128.upload.maximum_size=1044464 +generic.menu.eesz.2M128.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M128.build.spiffs_start=0x1E0000 +generic.menu.eesz.2M128.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M128.build.spiffs_blocksize=4096 +generic.menu.eesz.2M256=2MB (FS:256KB OTA:~896KB) +generic.menu.eesz.2M256.build.flash_size=2M +generic.menu.eesz.2M256.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld +generic.menu.eesz.2M256.build.spiffs_pagesize=256 +generic.menu.eesz.2M256.upload.maximum_size=1044464 +generic.menu.eesz.2M256.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M256.build.spiffs_start=0x1C0000 +generic.menu.eesz.2M256.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M256.build.spiffs_blocksize=4096 +generic.menu.eesz.2M512=2MB (FS:512KB OTA:~768KB) +generic.menu.eesz.2M512.build.flash_size=2M +generic.menu.eesz.2M512.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld +generic.menu.eesz.2M512.build.spiffs_pagesize=256 +generic.menu.eesz.2M512.upload.maximum_size=1044464 +generic.menu.eesz.2M512.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M512.build.spiffs_start=0x180000 +generic.menu.eesz.2M512.build.spiffs_end=0x1FA000 +generic.menu.eesz.2M512.build.spiffs_blocksize=8192 +generic.menu.eesz.2M1M=2MB (FS:1MB OTA:~512KB) +generic.menu.eesz.2M1M.build.flash_size=2M +generic.menu.eesz.2M1M.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld +generic.menu.eesz.2M1M.build.spiffs_pagesize=256 +generic.menu.eesz.2M1M.upload.maximum_size=1044464 +generic.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M1M.build.spiffs_start=0x100000 +generic.menu.eesz.2M1M.build.spiffs_end=0x1FA000 +generic.menu.eesz.2M1M.build.spiffs_blocksize=8192 +generic.menu.eesz.2M=2MB (FS:none OTA:~1019KB) +generic.menu.eesz.2M.build.flash_size=2M +generic.menu.eesz.2M.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld +generic.menu.eesz.2M.build.spiffs_pagesize=256 +generic.menu.eesz.2M.upload.maximum_size=1044464 +generic.menu.eesz.2M.build.rfcal_addr=0x1FC000 +generic.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +generic.menu.eesz.4M2M.build.flash_size=4M +generic.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +generic.menu.eesz.4M2M.build.spiffs_pagesize=256 +generic.menu.eesz.4M2M.upload.maximum_size=1044464 +generic.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M2M.build.spiffs_start=0x200000 +generic.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +generic.menu.eesz.4M2M.build.spiffs_blocksize=8192 +generic.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +generic.menu.eesz.4M3M.build.flash_size=4M +generic.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +generic.menu.eesz.4M3M.build.spiffs_pagesize=256 +generic.menu.eesz.4M3M.upload.maximum_size=1044464 +generic.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M3M.build.spiffs_start=0x100000 +generic.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +generic.menu.eesz.4M3M.build.spiffs_blocksize=8192 +generic.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +generic.menu.eesz.4M1M.build.flash_size=4M +generic.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +generic.menu.eesz.4M1M.build.spiffs_pagesize=256 +generic.menu.eesz.4M1M.upload.maximum_size=1044464 +generic.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M1M.build.spiffs_start=0x300000 +generic.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +generic.menu.eesz.4M1M.build.spiffs_blocksize=8192 +generic.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +generic.menu.eesz.4M.build.flash_size=4M +generic.menu.eesz.4M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +generic.menu.eesz.4M.build.spiffs_pagesize=256 +generic.menu.eesz.4M.upload.maximum_size=1044464 +generic.menu.eesz.4M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.8M6M=8MB (FS:6MB OTA:~1019KB) +generic.menu.eesz.8M6M.build.flash_size=8M +generic.menu.eesz.8M6M.build.flash_size_bytes=0x800000 +generic.menu.eesz.8M6M.build.flash_ld=eagle.flash.8m6m.ld +generic.menu.eesz.8M6M.build.spiffs_pagesize=256 +generic.menu.eesz.8M6M.upload.maximum_size=1044464 +generic.menu.eesz.8M6M.build.rfcal_addr=0x7FC000 +generic.menu.eesz.8M6M.build.spiffs_start=0x200000 +generic.menu.eesz.8M6M.build.spiffs_end=0x7FA000 +generic.menu.eesz.8M6M.build.spiffs_blocksize=8192 +generic.menu.eesz.8M7M=8MB (FS:7MB OTA:~512KB) +generic.menu.eesz.8M7M.build.flash_size=8M +generic.menu.eesz.8M7M.build.flash_size_bytes=0x800000 +generic.menu.eesz.8M7M.build.flash_ld=eagle.flash.8m7m.ld +generic.menu.eesz.8M7M.build.spiffs_pagesize=256 +generic.menu.eesz.8M7M.upload.maximum_size=1044464 +generic.menu.eesz.8M7M.build.rfcal_addr=0x7FC000 +generic.menu.eesz.8M7M.build.spiffs_start=0x100000 +generic.menu.eesz.8M7M.build.spiffs_end=0x7FA000 +generic.menu.eesz.8M7M.build.spiffs_blocksize=8192 +generic.menu.eesz.16M14M=16MB (FS:14MB OTA:~1019KB) +generic.menu.eesz.16M14M.build.flash_size=16M +generic.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 +generic.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld +generic.menu.eesz.16M14M.build.spiffs_pagesize=256 +generic.menu.eesz.16M14M.upload.maximum_size=1044464 +generic.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 +generic.menu.eesz.16M14M.build.spiffs_start=0x200000 +generic.menu.eesz.16M14M.build.spiffs_end=0xFFA000 +generic.menu.eesz.16M14M.build.spiffs_blocksize=8192 +generic.menu.eesz.16M15M=16MB (FS:15MB OTA:~512KB) +generic.menu.eesz.16M15M.build.flash_size=16M +generic.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 +generic.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld +generic.menu.eesz.16M15M.build.spiffs_pagesize=256 +generic.menu.eesz.16M15M.upload.maximum_size=1044464 +generic.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 +generic.menu.eesz.16M15M.build.spiffs_start=0x100000 +generic.menu.eesz.16M15M.build.spiffs_end=0xFFA000 +generic.menu.eesz.16M15M.build.spiffs_blocksize=8192 +generic.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB) +generic.menu.eesz.512K32.build.flash_size=512K +generic.menu.eesz.512K32.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +generic.menu.eesz.512K32.build.spiffs_pagesize=256 +generic.menu.eesz.512K32.upload.maximum_size=466928 +generic.menu.eesz.512K32.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K32.build.spiffs_start=0x73000 +generic.menu.eesz.512K32.build.spiffs_end=0x7B000 +generic.menu.eesz.512K32.build.spiffs_blocksize=4096 +generic.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB) +generic.menu.eesz.512K64.build.flash_size=512K +generic.menu.eesz.512K64.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +generic.menu.eesz.512K64.build.spiffs_pagesize=256 +generic.menu.eesz.512K64.upload.maximum_size=434160 +generic.menu.eesz.512K64.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K64.build.spiffs_start=0x6B000 +generic.menu.eesz.512K64.build.spiffs_end=0x7B000 +generic.menu.eesz.512K64.build.spiffs_blocksize=4096 +generic.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB) +generic.menu.eesz.512K128.build.flash_size=512K +generic.menu.eesz.512K128.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +generic.menu.eesz.512K128.build.spiffs_pagesize=256 +generic.menu.eesz.512K128.upload.maximum_size=368624 +generic.menu.eesz.512K128.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K128.build.spiffs_start=0x5B000 +generic.menu.eesz.512K128.build.spiffs_end=0x7B000 +generic.menu.eesz.512K128.build.spiffs_blocksize=4096 +generic.menu.eesz.512K=512KB (FS:none OTA:~246KB) +generic.menu.eesz.512K.build.flash_size=512K +generic.menu.eesz.512K.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +generic.menu.eesz.512K.build.spiffs_pagesize=256 +generic.menu.eesz.512K.upload.maximum_size=499696 +generic.menu.eesz.512K.build.rfcal_addr=0x7C000 +generic.menu.led.2=2 +generic.menu.led.2.build.led=-DLED_BUILTIN=2 +generic.menu.led.0=0 +generic.menu.led.0.build.led=-DLED_BUILTIN=0 +generic.menu.led.1=1 +generic.menu.led.1.build.led=-DLED_BUILTIN=1 +generic.menu.led.3=3 +generic.menu.led.3.build.led=-DLED_BUILTIN=3 +generic.menu.led.4=4 +generic.menu.led.4.build.led=-DLED_BUILTIN=4 +generic.menu.led.5=5 +generic.menu.led.5.build.led=-DLED_BUILTIN=5 +generic.menu.led.6=6 +generic.menu.led.6.build.led=-DLED_BUILTIN=6 +generic.menu.led.7=7 +generic.menu.led.7.build.led=-DLED_BUILTIN=7 +generic.menu.led.8=8 +generic.menu.led.8.build.led=-DLED_BUILTIN=8 +generic.menu.led.9=9 +generic.menu.led.9.build.led=-DLED_BUILTIN=9 +generic.menu.led.10=10 +generic.menu.led.10.build.led=-DLED_BUILTIN=10 +generic.menu.led.11=11 +generic.menu.led.11.build.led=-DLED_BUILTIN=11 +generic.menu.led.12=12 +generic.menu.led.12.build.led=-DLED_BUILTIN=12 +generic.menu.led.13=13 +generic.menu.led.13.build.led=-DLED_BUILTIN=13 +generic.menu.led.14=14 +generic.menu.led.14.build.led=-DLED_BUILTIN=14 +generic.menu.led.15=15 +generic.menu.led.15.build.led=-DLED_BUILTIN=15 +generic.menu.led.16=16 +generic.menu.led.16.build.led=-DLED_BUILTIN=16 +generic.menu.sdk.nonosdk222_100=nonos-sdk 2.2.1+100 (testing) +generic.menu.sdk.nonosdk222_100.build.sdk=NONOSDK22y +generic.menu.sdk.nonosdk221=nonos-sdk 2.2.1 (legacy) +generic.menu.sdk.nonosdk221.build.sdk=NONOSDK221 +generic.menu.sdk.nonosdk3v0=nonos-sdk pre-3 (known issues) +generic.menu.sdk.nonosdk3v0.build.sdk=NONOSDK3V0 +generic.menu.ip.lm2f=v2 Lower Memory +generic.menu.ip.lm2f.build.lwip_include=lwip2/include +generic.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +generic.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +generic.menu.ip.hb2f=v2 Higher Bandwidth +generic.menu.ip.hb2f.build.lwip_include=lwip2/include +generic.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +generic.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +generic.menu.ip.lm2n=v2 Lower Memory (no features) +generic.menu.ip.lm2n.build.lwip_include=lwip2/include +generic.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +generic.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +generic.menu.ip.hb2n=v2 Higher Bandwidth (no features) +generic.menu.ip.hb2n.build.lwip_include=lwip2/include +generic.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +generic.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +generic.menu.ip.lm6f=v2 IPv6 Lower Memory +generic.menu.ip.lm6f.build.lwip_include=lwip2/include +generic.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +generic.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +generic.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +generic.menu.ip.hb6f.build.lwip_include=lwip2/include +generic.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +generic.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +generic.menu.ip.hb1=v1.4 Higher Bandwidth +generic.menu.ip.hb1.build.lwip_lib=-llwip_gcc +generic.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +generic.menu.ip.src=v1.4 Compile from source +generic.menu.ip.src.build.lwip_lib=-llwip_src +generic.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +generic.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +generic.menu.dbg.Disabled=Disabled +generic.menu.dbg.Disabled.build.debug_port= +generic.menu.dbg.Serial=Serial +generic.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +generic.menu.dbg.Serial1=Serial1 +generic.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +generic.menu.lvl.None____=None +generic.menu.lvl.None____.build.debug_level= +generic.menu.lvl.SSL=SSL +generic.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +generic.menu.lvl.TLS_MEM=TLS_MEM +generic.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +generic.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +generic.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.HTTP_SERVER=HTTP_SERVER +generic.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +generic.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +generic.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +generic.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +generic.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +generic.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.CORE=CORE +generic.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +generic.menu.lvl.WIFI=WIFI +generic.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +generic.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +generic.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +generic.menu.lvl.UPDATER=UPDATER +generic.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +generic.menu.lvl.OTA=OTA +generic.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +generic.menu.lvl.OOM=OOM +generic.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +generic.menu.lvl.MDNS=MDNS +generic.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +generic.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +generic.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +generic.menu.wipe.none=Only Sketch +generic.menu.wipe.none.upload.erase_cmd=version +generic.menu.wipe.sdk=Sketch + WiFi Settings +generic.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +generic.menu.wipe.all=All Flash Contents +generic.menu.wipe.all.upload.erase_cmd=erase_flash +generic.menu.baud.115200=115200 +generic.menu.baud.115200.upload.speed=115200 +generic.menu.baud.57600=57600 +generic.menu.baud.57600.upload.speed=57600 +generic.menu.baud.230400.linux=230400 +generic.menu.baud.230400.macosx=230400 +generic.menu.baud.230400.upload.speed=230400 +generic.menu.baud.256000.windows=256000 +generic.menu.baud.256000.upload.speed=256000 +generic.menu.baud.460800.linux=460800 +generic.menu.baud.460800.macosx=460800 +generic.menu.baud.460800.upload.speed=460800 +generic.menu.baud.512000.windows=512000 +generic.menu.baud.512000.upload.speed=512000 +generic.menu.baud.921600=921600 +generic.menu.baud.921600.upload.speed=921600 +generic.menu.baud.3000000=3000000 +generic.menu.baud.3000000.upload.speed=3000000 + +############################################################## +esp8285.name=Generic ESP8285 Module +esp8285.build.board=ESP8266_ESP01 +esp8285.build.variant=esp8285 +esp8285.upload.tool=esptool +esp8285.upload.maximum_data_size=81920 +esp8285.upload.wait_for_upload_port=true +esp8285.upload.erase_cmd=version +esp8285.serial.disableDTR=true +esp8285.serial.disableRTS=true +esp8285.build.mcu=esp8266 +esp8285.build.core=esp8266 +esp8285.build.spiffs_pagesize=256 +esp8285.build.debug_port= +esp8285.build.debug_level= +esp8285.menu.xtal.80=80 MHz +esp8285.menu.xtal.80.build.f_cpu=80000000L +esp8285.menu.xtal.160=160 MHz +esp8285.menu.xtal.160.build.f_cpu=160000000L +esp8285.menu.vt.flash=Flash +esp8285.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +esp8285.menu.vt.heap=Heap +esp8285.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +esp8285.menu.vt.iram=IRAM +esp8285.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +esp8285.menu.exception.legacy=Legacy (new can return nullptr) +esp8285.menu.exception.legacy.build.exception_flags=-fno-exceptions +esp8285.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +esp8285.menu.exception.disabled=Disabled (new can abort) +esp8285.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +esp8285.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +esp8285.menu.exception.enabled=Enabled +esp8285.menu.exception.enabled.build.exception_flags=-fexceptions +esp8285.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +esp8285.menu.ssl.all=All SSL ciphers (most compatible) +esp8285.menu.ssl.all.build.sslflags= +esp8285.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +esp8285.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +esp8285.menu.ResetMethod.ck=ck +esp8285.menu.ResetMethod.ck.upload.resetmethod=ck +esp8285.menu.ResetMethod.nodemcu=nodemcu +esp8285.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +esp8285.menu.ResetMethod.none=none +esp8285.menu.ResetMethod.none.upload.resetmethod=none +esp8285.menu.ResetMethod.dtrset=dtrset +esp8285.menu.ResetMethod.dtrset.upload.resetmethod=dtrset +esp8285.menu.CrystalFreq.26=26 MHz +esp8285.menu.CrystalFreq.40=40 MHz +esp8285.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +esp8285.build.flash_mode=dout +esp8285.build.flash_flags=-DFLASHMODE_DOUT +esp8285.build.flash_freq=40 +esp8285.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) +esp8285.menu.eesz.1M64.build.flash_size=1M +esp8285.menu.eesz.1M64.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +esp8285.menu.eesz.1M64.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M64.upload.maximum_size=958448 +esp8285.menu.eesz.1M64.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M64.build.spiffs_start=0xEB000 +esp8285.menu.eesz.1M64.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M64.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) +esp8285.menu.eesz.1M128.build.flash_size=1M +esp8285.menu.eesz.1M128.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +esp8285.menu.eesz.1M128.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M128.upload.maximum_size=892912 +esp8285.menu.eesz.1M128.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M128.build.spiffs_start=0xDB000 +esp8285.menu.eesz.1M128.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M128.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) +esp8285.menu.eesz.1M144.build.flash_size=1M +esp8285.menu.eesz.1M144.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +esp8285.menu.eesz.1M144.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M144.upload.maximum_size=876528 +esp8285.menu.eesz.1M144.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M144.build.spiffs_start=0xD7000 +esp8285.menu.eesz.1M144.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M144.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) +esp8285.menu.eesz.1M160.build.flash_size=1M +esp8285.menu.eesz.1M160.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +esp8285.menu.eesz.1M160.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M160.upload.maximum_size=860144 +esp8285.menu.eesz.1M160.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M160.build.spiffs_start=0xD3000 +esp8285.menu.eesz.1M160.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M160.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) +esp8285.menu.eesz.1M192.build.flash_size=1M +esp8285.menu.eesz.1M192.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +esp8285.menu.eesz.1M192.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M192.upload.maximum_size=827376 +esp8285.menu.eesz.1M192.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M192.build.spiffs_start=0xCB000 +esp8285.menu.eesz.1M192.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M192.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) +esp8285.menu.eesz.1M256.build.flash_size=1M +esp8285.menu.eesz.1M256.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +esp8285.menu.eesz.1M256.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M256.upload.maximum_size=761840 +esp8285.menu.eesz.1M256.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M256.build.spiffs_start=0xBB000 +esp8285.menu.eesz.1M256.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M256.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) +esp8285.menu.eesz.1M512.build.flash_size=1M +esp8285.menu.eesz.1M512.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +esp8285.menu.eesz.1M512.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M512.upload.maximum_size=499696 +esp8285.menu.eesz.1M512.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M512.build.spiffs_start=0x7B000 +esp8285.menu.eesz.1M512.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M512.build.spiffs_blocksize=8192 +esp8285.menu.eesz.1M=1MB (FS:none OTA:~502KB) +esp8285.menu.eesz.1M.build.flash_size=1M +esp8285.menu.eesz.1M.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +esp8285.menu.eesz.1M.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M.upload.maximum_size=1023984 +esp8285.menu.eesz.1M.build.rfcal_addr=0xFC000 +esp8285.menu.led.2=2 +esp8285.menu.led.2.build.led=-DLED_BUILTIN=2 +esp8285.menu.led.0=0 +esp8285.menu.led.0.build.led=-DLED_BUILTIN=0 +esp8285.menu.led.1=1 +esp8285.menu.led.1.build.led=-DLED_BUILTIN=1 +esp8285.menu.led.3=3 +esp8285.menu.led.3.build.led=-DLED_BUILTIN=3 +esp8285.menu.led.4=4 +esp8285.menu.led.4.build.led=-DLED_BUILTIN=4 +esp8285.menu.led.5=5 +esp8285.menu.led.5.build.led=-DLED_BUILTIN=5 +esp8285.menu.led.6=6 +esp8285.menu.led.6.build.led=-DLED_BUILTIN=6 +esp8285.menu.led.7=7 +esp8285.menu.led.7.build.led=-DLED_BUILTIN=7 +esp8285.menu.led.8=8 +esp8285.menu.led.8.build.led=-DLED_BUILTIN=8 +esp8285.menu.led.9=9 +esp8285.menu.led.9.build.led=-DLED_BUILTIN=9 +esp8285.menu.led.10=10 +esp8285.menu.led.10.build.led=-DLED_BUILTIN=10 +esp8285.menu.led.11=11 +esp8285.menu.led.11.build.led=-DLED_BUILTIN=11 +esp8285.menu.led.12=12 +esp8285.menu.led.12.build.led=-DLED_BUILTIN=12 +esp8285.menu.led.13=13 +esp8285.menu.led.13.build.led=-DLED_BUILTIN=13 +esp8285.menu.led.14=14 +esp8285.menu.led.14.build.led=-DLED_BUILTIN=14 +esp8285.menu.led.15=15 +esp8285.menu.led.15.build.led=-DLED_BUILTIN=15 +esp8285.menu.led.16=16 +esp8285.menu.led.16.build.led=-DLED_BUILTIN=16 +esp8285.menu.ip.lm2f=v2 Lower Memory +esp8285.menu.ip.lm2f.build.lwip_include=lwip2/include +esp8285.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +esp8285.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp8285.menu.ip.hb2f=v2 Higher Bandwidth +esp8285.menu.ip.hb2f.build.lwip_include=lwip2/include +esp8285.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +esp8285.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp8285.menu.ip.lm2n=v2 Lower Memory (no features) +esp8285.menu.ip.lm2n.build.lwip_include=lwip2/include +esp8285.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +esp8285.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp8285.menu.ip.hb2n=v2 Higher Bandwidth (no features) +esp8285.menu.ip.hb2n.build.lwip_include=lwip2/include +esp8285.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +esp8285.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp8285.menu.ip.lm6f=v2 IPv6 Lower Memory +esp8285.menu.ip.lm6f.build.lwip_include=lwip2/include +esp8285.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +esp8285.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp8285.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +esp8285.menu.ip.hb6f.build.lwip_include=lwip2/include +esp8285.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +esp8285.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp8285.menu.ip.hb1=v1.4 Higher Bandwidth +esp8285.menu.ip.hb1.build.lwip_lib=-llwip_gcc +esp8285.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +esp8285.menu.ip.src=v1.4 Compile from source +esp8285.menu.ip.src.build.lwip_lib=-llwip_src +esp8285.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +esp8285.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +esp8285.menu.dbg.Disabled=Disabled +esp8285.menu.dbg.Disabled.build.debug_port= +esp8285.menu.dbg.Serial=Serial +esp8285.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +esp8285.menu.dbg.Serial1=Serial1 +esp8285.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +esp8285.menu.lvl.None____=None +esp8285.menu.lvl.None____.build.debug_level= +esp8285.menu.lvl.SSL=SSL +esp8285.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +esp8285.menu.lvl.TLS_MEM=TLS_MEM +esp8285.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +esp8285.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +esp8285.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.HTTP_SERVER=HTTP_SERVER +esp8285.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +esp8285.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +esp8285.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +esp8285.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +esp8285.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +esp8285.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.CORE=CORE +esp8285.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +esp8285.menu.lvl.WIFI=WIFI +esp8285.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +esp8285.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +esp8285.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +esp8285.menu.lvl.UPDATER=UPDATER +esp8285.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +esp8285.menu.lvl.OTA=OTA +esp8285.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +esp8285.menu.lvl.OOM=OOM +esp8285.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +esp8285.menu.lvl.MDNS=MDNS +esp8285.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +esp8285.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +esp8285.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +esp8285.menu.wipe.none=Only Sketch +esp8285.menu.wipe.none.upload.erase_cmd=version +esp8285.menu.wipe.sdk=Sketch + WiFi Settings +esp8285.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +esp8285.menu.wipe.all=All Flash Contents +esp8285.menu.wipe.all.upload.erase_cmd=erase_flash +esp8285.menu.baud.115200=115200 +esp8285.menu.baud.115200.upload.speed=115200 +esp8285.menu.baud.57600=57600 +esp8285.menu.baud.57600.upload.speed=57600 +esp8285.menu.baud.230400.linux=230400 +esp8285.menu.baud.230400.macosx=230400 +esp8285.menu.baud.230400.upload.speed=230400 +esp8285.menu.baud.256000.windows=256000 +esp8285.menu.baud.256000.upload.speed=256000 +esp8285.menu.baud.460800.linux=460800 +esp8285.menu.baud.460800.macosx=460800 +esp8285.menu.baud.460800.upload.speed=460800 +esp8285.menu.baud.512000.windows=512000 +esp8285.menu.baud.512000.upload.speed=512000 +esp8285.menu.baud.921600=921600 +esp8285.menu.baud.921600.upload.speed=921600 +esp8285.menu.baud.3000000=3000000 +esp8285.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espduino.name=ESPDuino (ESP-13 Module) +espduino.build.board=ESP8266_ESP13 +espduino.build.variant=ESPDuino +espduino.menu.ResetMethod.v1=ESPduino-V1 +espduino.menu.ResetMethod.v1.upload.resetmethod=ck +espduino.menu.ResetMethod.v2=ESPduino-V2 +espduino.menu.ResetMethod.v2.upload.resetmethod=nodemcu +espduino.menu.UploadTool.espota=OTA +espduino.menu.UploadTool.espota.upload.tool=espota +espduino.menu.UploadTool.esptool=Serial +espduino.menu.UploadTool.esptool.upload.tool=esptool +espduino.menu.UploadTool.esptool.upload.verbose=--trace +espduino.upload.tool=esptool +espduino.upload.maximum_data_size=81920 +espduino.upload.wait_for_upload_port=true +espduino.upload.erase_cmd=version +espduino.serial.disableDTR=true +espduino.serial.disableRTS=true +espduino.build.mcu=esp8266 +espduino.build.core=esp8266 +espduino.build.spiffs_pagesize=256 +espduino.build.debug_port= +espduino.build.debug_level= +espduino.menu.xtal.80=80 MHz +espduino.menu.xtal.80.build.f_cpu=80000000L +espduino.menu.xtal.160=160 MHz +espduino.menu.xtal.160.build.f_cpu=160000000L +espduino.menu.vt.flash=Flash +espduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espduino.menu.vt.heap=Heap +espduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espduino.menu.vt.iram=IRAM +espduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espduino.menu.exception.legacy=Legacy (new can return nullptr) +espduino.menu.exception.legacy.build.exception_flags=-fno-exceptions +espduino.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espduino.menu.exception.disabled=Disabled (new can abort) +espduino.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espduino.menu.exception.enabled=Enabled +espduino.menu.exception.enabled.build.exception_flags=-fexceptions +espduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espduino.menu.ssl.all=All SSL ciphers (most compatible) +espduino.menu.ssl.all.build.sslflags= +espduino.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espduino.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espduino.build.flash_mode=dio +espduino.build.flash_flags=-DFLASHMODE_DIO +espduino.build.flash_freq=40 +espduino.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +espduino.menu.eesz.4M2M.build.flash_size=4M +espduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espduino.menu.eesz.4M2M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M2M.upload.maximum_size=1044464 +espduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M2M.build.spiffs_start=0x200000 +espduino.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +espduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espduino.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +espduino.menu.eesz.4M3M.build.flash_size=4M +espduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espduino.menu.eesz.4M3M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M3M.upload.maximum_size=1044464 +espduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M3M.build.spiffs_start=0x100000 +espduino.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +espduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espduino.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +espduino.menu.eesz.4M1M.build.flash_size=4M +espduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espduino.menu.eesz.4M1M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M1M.upload.maximum_size=1044464 +espduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M1M.build.spiffs_start=0x300000 +espduino.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +espduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espduino.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +espduino.menu.eesz.4M.build.flash_size=4M +espduino.menu.eesz.4M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espduino.menu.eesz.4M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M.upload.maximum_size=1044464 +espduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espduino.menu.ip.lm2f=v2 Lower Memory +espduino.menu.ip.lm2f.build.lwip_include=lwip2/include +espduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espduino.menu.ip.hb2f=v2 Higher Bandwidth +espduino.menu.ip.hb2f.build.lwip_include=lwip2/include +espduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espduino.menu.ip.lm2n=v2 Lower Memory (no features) +espduino.menu.ip.lm2n.build.lwip_include=lwip2/include +espduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espduino.menu.ip.hb2n.build.lwip_include=lwip2/include +espduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espduino.menu.ip.lm6f=v2 IPv6 Lower Memory +espduino.menu.ip.lm6f.build.lwip_include=lwip2/include +espduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espduino.menu.ip.hb6f.build.lwip_include=lwip2/include +espduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espduino.menu.ip.hb1=v1.4 Higher Bandwidth +espduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espduino.menu.ip.src=v1.4 Compile from source +espduino.menu.ip.src.build.lwip_lib=-llwip_src +espduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espduino.menu.dbg.Disabled=Disabled +espduino.menu.dbg.Disabled.build.debug_port= +espduino.menu.dbg.Serial=Serial +espduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espduino.menu.dbg.Serial1=Serial1 +espduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espduino.menu.lvl.None____=None +espduino.menu.lvl.None____.build.debug_level= +espduino.menu.lvl.SSL=SSL +espduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espduino.menu.lvl.TLS_MEM=TLS_MEM +espduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.HTTP_SERVER=HTTP_SERVER +espduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.CORE=CORE +espduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espduino.menu.lvl.WIFI=WIFI +espduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espduino.menu.lvl.UPDATER=UPDATER +espduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espduino.menu.lvl.OTA=OTA +espduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espduino.menu.lvl.OOM=OOM +espduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espduino.menu.lvl.MDNS=MDNS +espduino.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espduino.menu.wipe.none=Only Sketch +espduino.menu.wipe.none.upload.erase_cmd=version +espduino.menu.wipe.sdk=Sketch + WiFi Settings +espduino.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espduino.menu.wipe.all=All Flash Contents +espduino.menu.wipe.all.upload.erase_cmd=erase_flash +espduino.menu.baud.115200=115200 +espduino.menu.baud.115200.upload.speed=115200 +espduino.menu.baud.57600=57600 +espduino.menu.baud.57600.upload.speed=57600 +espduino.menu.baud.230400.linux=230400 +espduino.menu.baud.230400.macosx=230400 +espduino.menu.baud.230400.upload.speed=230400 +espduino.menu.baud.256000.windows=256000 +espduino.menu.baud.256000.upload.speed=256000 +espduino.menu.baud.460800.linux=460800 +espduino.menu.baud.460800.macosx=460800 +espduino.menu.baud.460800.upload.speed=460800 +espduino.menu.baud.512000.windows=512000 +espduino.menu.baud.512000.upload.speed=512000 +espduino.menu.baud.921600=921600 +espduino.menu.baud.921600.upload.speed=921600 +espduino.menu.baud.3000000=3000000 +espduino.menu.baud.3000000.upload.speed=3000000 + +############################################################## +huzzah.name=Adafruit Feather HUZZAH ESP8266 +huzzah.build.board=ESP8266_ESP12 +huzzah.build.variant=adafruit +huzzah.upload.tool=esptool +huzzah.upload.maximum_data_size=81920 +huzzah.upload.wait_for_upload_port=true +huzzah.upload.erase_cmd=version +huzzah.serial.disableDTR=true +huzzah.serial.disableRTS=true +huzzah.build.mcu=esp8266 +huzzah.build.core=esp8266 +huzzah.build.spiffs_pagesize=256 +huzzah.build.debug_port= +huzzah.build.debug_level= +huzzah.menu.xtal.80=80 MHz +huzzah.menu.xtal.80.build.f_cpu=80000000L +huzzah.menu.xtal.160=160 MHz +huzzah.menu.xtal.160.build.f_cpu=160000000L +huzzah.menu.vt.flash=Flash +huzzah.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +huzzah.menu.vt.heap=Heap +huzzah.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +huzzah.menu.vt.iram=IRAM +huzzah.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +huzzah.menu.exception.legacy=Legacy (new can return nullptr) +huzzah.menu.exception.legacy.build.exception_flags=-fno-exceptions +huzzah.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +huzzah.menu.exception.disabled=Disabled (new can abort) +huzzah.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +huzzah.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +huzzah.menu.exception.enabled=Enabled +huzzah.menu.exception.enabled.build.exception_flags=-fexceptions +huzzah.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +huzzah.menu.ssl.all=All SSL ciphers (most compatible) +huzzah.menu.ssl.all.build.sslflags= +huzzah.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +huzzah.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +huzzah.upload.resetmethod=nodemcu +huzzah.build.flash_mode=qio +huzzah.build.flash_flags=-DFLASHMODE_QIO +huzzah.build.flash_freq=40 +huzzah.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +huzzah.menu.eesz.4M2M.build.flash_size=4M +huzzah.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +huzzah.menu.eesz.4M2M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M2M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M2M.build.spiffs_start=0x200000 +huzzah.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +huzzah.menu.eesz.4M2M.build.spiffs_blocksize=8192 +huzzah.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +huzzah.menu.eesz.4M3M.build.flash_size=4M +huzzah.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +huzzah.menu.eesz.4M3M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M3M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M3M.build.spiffs_start=0x100000 +huzzah.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +huzzah.menu.eesz.4M3M.build.spiffs_blocksize=8192 +huzzah.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +huzzah.menu.eesz.4M1M.build.flash_size=4M +huzzah.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +huzzah.menu.eesz.4M1M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M1M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M1M.build.spiffs_start=0x300000 +huzzah.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +huzzah.menu.eesz.4M1M.build.spiffs_blocksize=8192 +huzzah.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +huzzah.menu.eesz.4M.build.flash_size=4M +huzzah.menu.eesz.4M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +huzzah.menu.eesz.4M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M.build.rfcal_addr=0x3FC000 +huzzah.menu.ip.lm2f=v2 Lower Memory +huzzah.menu.ip.lm2f.build.lwip_include=lwip2/include +huzzah.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +huzzah.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +huzzah.menu.ip.hb2f=v2 Higher Bandwidth +huzzah.menu.ip.hb2f.build.lwip_include=lwip2/include +huzzah.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +huzzah.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +huzzah.menu.ip.lm2n=v2 Lower Memory (no features) +huzzah.menu.ip.lm2n.build.lwip_include=lwip2/include +huzzah.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +huzzah.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +huzzah.menu.ip.hb2n=v2 Higher Bandwidth (no features) +huzzah.menu.ip.hb2n.build.lwip_include=lwip2/include +huzzah.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +huzzah.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +huzzah.menu.ip.lm6f=v2 IPv6 Lower Memory +huzzah.menu.ip.lm6f.build.lwip_include=lwip2/include +huzzah.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +huzzah.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +huzzah.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +huzzah.menu.ip.hb6f.build.lwip_include=lwip2/include +huzzah.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +huzzah.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +huzzah.menu.ip.hb1=v1.4 Higher Bandwidth +huzzah.menu.ip.hb1.build.lwip_lib=-llwip_gcc +huzzah.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +huzzah.menu.ip.src=v1.4 Compile from source +huzzah.menu.ip.src.build.lwip_lib=-llwip_src +huzzah.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +huzzah.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +huzzah.menu.dbg.Disabled=Disabled +huzzah.menu.dbg.Disabled.build.debug_port= +huzzah.menu.dbg.Serial=Serial +huzzah.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +huzzah.menu.dbg.Serial1=Serial1 +huzzah.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +huzzah.menu.lvl.None____=None +huzzah.menu.lvl.None____.build.debug_level= +huzzah.menu.lvl.SSL=SSL +huzzah.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +huzzah.menu.lvl.TLS_MEM=TLS_MEM +huzzah.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +huzzah.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +huzzah.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.HTTP_SERVER=HTTP_SERVER +huzzah.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +huzzah.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +huzzah.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +huzzah.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +huzzah.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +huzzah.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.CORE=CORE +huzzah.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +huzzah.menu.lvl.WIFI=WIFI +huzzah.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +huzzah.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +huzzah.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +huzzah.menu.lvl.UPDATER=UPDATER +huzzah.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +huzzah.menu.lvl.OTA=OTA +huzzah.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +huzzah.menu.lvl.OOM=OOM +huzzah.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +huzzah.menu.lvl.MDNS=MDNS +huzzah.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +huzzah.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +huzzah.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +huzzah.menu.wipe.none=Only Sketch +huzzah.menu.wipe.none.upload.erase_cmd=version +huzzah.menu.wipe.sdk=Sketch + WiFi Settings +huzzah.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +huzzah.menu.wipe.all=All Flash Contents +huzzah.menu.wipe.all.upload.erase_cmd=erase_flash +huzzah.menu.baud.115200=115200 +huzzah.menu.baud.115200.upload.speed=115200 +huzzah.menu.baud.57600=57600 +huzzah.menu.baud.57600.upload.speed=57600 +huzzah.menu.baud.230400.linux=230400 +huzzah.menu.baud.230400.macosx=230400 +huzzah.menu.baud.230400.upload.speed=230400 +huzzah.menu.baud.256000.windows=256000 +huzzah.menu.baud.256000.upload.speed=256000 +huzzah.menu.baud.460800.linux=460800 +huzzah.menu.baud.460800.macosx=460800 +huzzah.menu.baud.460800.upload.speed=460800 +huzzah.menu.baud.512000.windows=512000 +huzzah.menu.baud.512000.upload.speed=512000 +huzzah.menu.baud.921600=921600 +huzzah.menu.baud.921600.upload.speed=921600 +huzzah.menu.baud.3000000=3000000 +huzzah.menu.baud.3000000.upload.speed=3000000 + +############################################################## +inventone.name=Invent One +inventone.build.board=ESP8266_GENERIC +inventone.build.variant=inventone +inventone.upload.tool=esptool +inventone.upload.maximum_data_size=81920 +inventone.upload.wait_for_upload_port=true +inventone.upload.erase_cmd=version +inventone.serial.disableDTR=true +inventone.serial.disableRTS=true +inventone.build.mcu=esp8266 +inventone.build.core=esp8266 +inventone.build.spiffs_pagesize=256 +inventone.build.debug_port= +inventone.build.debug_level= +inventone.menu.xtal.80=80 MHz +inventone.menu.xtal.80.build.f_cpu=80000000L +inventone.menu.xtal.160=160 MHz +inventone.menu.xtal.160.build.f_cpu=160000000L +inventone.menu.vt.flash=Flash +inventone.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +inventone.menu.vt.heap=Heap +inventone.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +inventone.menu.vt.iram=IRAM +inventone.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +inventone.menu.exception.legacy=Legacy (new can return nullptr) +inventone.menu.exception.legacy.build.exception_flags=-fno-exceptions +inventone.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +inventone.menu.exception.disabled=Disabled (new can abort) +inventone.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +inventone.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +inventone.menu.exception.enabled=Enabled +inventone.menu.exception.enabled.build.exception_flags=-fexceptions +inventone.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +inventone.menu.ssl.all=All SSL ciphers (most compatible) +inventone.menu.ssl.all.build.sslflags= +inventone.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +inventone.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +inventone.upload.resetmethod=nodemcu +inventone.build.flash_mode=dio +inventone.build.flash_flags=-DFLASHMODE_DIO +inventone.build.flash_freq=40 +inventone.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +inventone.menu.eesz.4M2M.build.flash_size=4M +inventone.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +inventone.menu.eesz.4M2M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M2M.upload.maximum_size=1044464 +inventone.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M2M.build.spiffs_start=0x200000 +inventone.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +inventone.menu.eesz.4M2M.build.spiffs_blocksize=8192 +inventone.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +inventone.menu.eesz.4M3M.build.flash_size=4M +inventone.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +inventone.menu.eesz.4M3M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M3M.upload.maximum_size=1044464 +inventone.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M3M.build.spiffs_start=0x100000 +inventone.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +inventone.menu.eesz.4M3M.build.spiffs_blocksize=8192 +inventone.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +inventone.menu.eesz.4M1M.build.flash_size=4M +inventone.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +inventone.menu.eesz.4M1M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M1M.upload.maximum_size=1044464 +inventone.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M1M.build.spiffs_start=0x300000 +inventone.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +inventone.menu.eesz.4M1M.build.spiffs_blocksize=8192 +inventone.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +inventone.menu.eesz.4M.build.flash_size=4M +inventone.menu.eesz.4M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +inventone.menu.eesz.4M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M.upload.maximum_size=1044464 +inventone.menu.eesz.4M.build.rfcal_addr=0x3FC000 +inventone.menu.ip.lm2f=v2 Lower Memory +inventone.menu.ip.lm2f.build.lwip_include=lwip2/include +inventone.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +inventone.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +inventone.menu.ip.hb2f=v2 Higher Bandwidth +inventone.menu.ip.hb2f.build.lwip_include=lwip2/include +inventone.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +inventone.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +inventone.menu.ip.lm2n=v2 Lower Memory (no features) +inventone.menu.ip.lm2n.build.lwip_include=lwip2/include +inventone.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +inventone.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +inventone.menu.ip.hb2n=v2 Higher Bandwidth (no features) +inventone.menu.ip.hb2n.build.lwip_include=lwip2/include +inventone.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +inventone.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +inventone.menu.ip.lm6f=v2 IPv6 Lower Memory +inventone.menu.ip.lm6f.build.lwip_include=lwip2/include +inventone.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +inventone.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +inventone.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +inventone.menu.ip.hb6f.build.lwip_include=lwip2/include +inventone.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +inventone.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +inventone.menu.ip.hb1=v1.4 Higher Bandwidth +inventone.menu.ip.hb1.build.lwip_lib=-llwip_gcc +inventone.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +inventone.menu.ip.src=v1.4 Compile from source +inventone.menu.ip.src.build.lwip_lib=-llwip_src +inventone.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +inventone.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +inventone.menu.dbg.Disabled=Disabled +inventone.menu.dbg.Disabled.build.debug_port= +inventone.menu.dbg.Serial=Serial +inventone.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +inventone.menu.dbg.Serial1=Serial1 +inventone.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +inventone.menu.lvl.None____=None +inventone.menu.lvl.None____.build.debug_level= +inventone.menu.lvl.SSL=SSL +inventone.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +inventone.menu.lvl.TLS_MEM=TLS_MEM +inventone.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +inventone.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +inventone.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.HTTP_SERVER=HTTP_SERVER +inventone.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +inventone.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +inventone.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +inventone.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +inventone.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +inventone.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.CORE=CORE +inventone.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +inventone.menu.lvl.WIFI=WIFI +inventone.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +inventone.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +inventone.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +inventone.menu.lvl.UPDATER=UPDATER +inventone.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +inventone.menu.lvl.OTA=OTA +inventone.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +inventone.menu.lvl.OOM=OOM +inventone.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +inventone.menu.lvl.MDNS=MDNS +inventone.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +inventone.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +inventone.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +inventone.menu.wipe.none=Only Sketch +inventone.menu.wipe.none.upload.erase_cmd=version +inventone.menu.wipe.sdk=Sketch + WiFi Settings +inventone.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +inventone.menu.wipe.all=All Flash Contents +inventone.menu.wipe.all.upload.erase_cmd=erase_flash +inventone.menu.baud.115200=115200 +inventone.menu.baud.115200.upload.speed=115200 +inventone.menu.baud.57600=57600 +inventone.menu.baud.57600.upload.speed=57600 +inventone.menu.baud.230400.linux=230400 +inventone.menu.baud.230400.macosx=230400 +inventone.menu.baud.230400.upload.speed=230400 +inventone.menu.baud.256000.windows=256000 +inventone.menu.baud.256000.upload.speed=256000 +inventone.menu.baud.460800.linux=460800 +inventone.menu.baud.460800.macosx=460800 +inventone.menu.baud.460800.upload.speed=460800 +inventone.menu.baud.512000.windows=512000 +inventone.menu.baud.512000.upload.speed=512000 +inventone.menu.baud.921600=921600 +inventone.menu.baud.921600.upload.speed=921600 +inventone.menu.baud.3000000=3000000 +inventone.menu.baud.3000000.upload.speed=3000000 + +############################################################## +cw01.name=XinaBox CW01 +cw01.build.board=ESP8266_GENERIC +cw01.build.variant=xinabox +cw01.upload.tool=esptool +cw01.upload.maximum_data_size=81920 +cw01.upload.wait_for_upload_port=true +cw01.upload.erase_cmd=version +cw01.serial.disableDTR=true +cw01.serial.disableRTS=true +cw01.build.mcu=esp8266 +cw01.build.core=esp8266 +cw01.build.spiffs_pagesize=256 +cw01.build.debug_port= +cw01.build.debug_level= +cw01.menu.xtal.80=80 MHz +cw01.menu.xtal.80.build.f_cpu=80000000L +cw01.menu.xtal.160=160 MHz +cw01.menu.xtal.160.build.f_cpu=160000000L +cw01.menu.vt.flash=Flash +cw01.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +cw01.menu.vt.heap=Heap +cw01.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +cw01.menu.vt.iram=IRAM +cw01.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +cw01.menu.exception.legacy=Legacy (new can return nullptr) +cw01.menu.exception.legacy.build.exception_flags=-fno-exceptions +cw01.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +cw01.menu.exception.disabled=Disabled (new can abort) +cw01.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +cw01.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +cw01.menu.exception.enabled=Enabled +cw01.menu.exception.enabled.build.exception_flags=-fexceptions +cw01.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +cw01.menu.ssl.all=All SSL ciphers (most compatible) +cw01.menu.ssl.all.build.sslflags= +cw01.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +cw01.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +cw01.upload.resetmethod=nodemcu +cw01.menu.CrystalFreq.26=26 MHz +cw01.menu.CrystalFreq.40=40 MHz +cw01.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +cw01.build.flash_mode=dio +cw01.build.flash_flags=-DFLASHMODE_DIO +cw01.build.flash_freq=40 +cw01.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +cw01.menu.eesz.4M2M.build.flash_size=4M +cw01.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +cw01.menu.eesz.4M2M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M2M.upload.maximum_size=1044464 +cw01.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M2M.build.spiffs_start=0x200000 +cw01.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +cw01.menu.eesz.4M2M.build.spiffs_blocksize=8192 +cw01.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +cw01.menu.eesz.4M3M.build.flash_size=4M +cw01.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +cw01.menu.eesz.4M3M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M3M.upload.maximum_size=1044464 +cw01.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M3M.build.spiffs_start=0x100000 +cw01.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +cw01.menu.eesz.4M3M.build.spiffs_blocksize=8192 +cw01.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +cw01.menu.eesz.4M1M.build.flash_size=4M +cw01.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +cw01.menu.eesz.4M1M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M1M.upload.maximum_size=1044464 +cw01.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M1M.build.spiffs_start=0x300000 +cw01.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +cw01.menu.eesz.4M1M.build.spiffs_blocksize=8192 +cw01.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +cw01.menu.eesz.4M.build.flash_size=4M +cw01.menu.eesz.4M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +cw01.menu.eesz.4M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M.upload.maximum_size=1044464 +cw01.menu.eesz.4M.build.rfcal_addr=0x3FC000 +cw01.menu.ip.lm2f=v2 Lower Memory +cw01.menu.ip.lm2f.build.lwip_include=lwip2/include +cw01.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +cw01.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +cw01.menu.ip.hb2f=v2 Higher Bandwidth +cw01.menu.ip.hb2f.build.lwip_include=lwip2/include +cw01.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +cw01.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +cw01.menu.ip.lm2n=v2 Lower Memory (no features) +cw01.menu.ip.lm2n.build.lwip_include=lwip2/include +cw01.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +cw01.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +cw01.menu.ip.hb2n=v2 Higher Bandwidth (no features) +cw01.menu.ip.hb2n.build.lwip_include=lwip2/include +cw01.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +cw01.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +cw01.menu.ip.lm6f=v2 IPv6 Lower Memory +cw01.menu.ip.lm6f.build.lwip_include=lwip2/include +cw01.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +cw01.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +cw01.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +cw01.menu.ip.hb6f.build.lwip_include=lwip2/include +cw01.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +cw01.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +cw01.menu.ip.hb1=v1.4 Higher Bandwidth +cw01.menu.ip.hb1.build.lwip_lib=-llwip_gcc +cw01.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +cw01.menu.ip.src=v1.4 Compile from source +cw01.menu.ip.src.build.lwip_lib=-llwip_src +cw01.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +cw01.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +cw01.menu.dbg.Disabled=Disabled +cw01.menu.dbg.Disabled.build.debug_port= +cw01.menu.dbg.Serial=Serial +cw01.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +cw01.menu.dbg.Serial1=Serial1 +cw01.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +cw01.menu.lvl.None____=None +cw01.menu.lvl.None____.build.debug_level= +cw01.menu.lvl.SSL=SSL +cw01.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +cw01.menu.lvl.TLS_MEM=TLS_MEM +cw01.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +cw01.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +cw01.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.HTTP_SERVER=HTTP_SERVER +cw01.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +cw01.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +cw01.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +cw01.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +cw01.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +cw01.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.CORE=CORE +cw01.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +cw01.menu.lvl.WIFI=WIFI +cw01.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +cw01.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +cw01.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +cw01.menu.lvl.UPDATER=UPDATER +cw01.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +cw01.menu.lvl.OTA=OTA +cw01.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +cw01.menu.lvl.OOM=OOM +cw01.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +cw01.menu.lvl.MDNS=MDNS +cw01.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +cw01.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +cw01.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +cw01.menu.wipe.none=Only Sketch +cw01.menu.wipe.none.upload.erase_cmd=version +cw01.menu.wipe.sdk=Sketch + WiFi Settings +cw01.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +cw01.menu.wipe.all=All Flash Contents +cw01.menu.wipe.all.upload.erase_cmd=erase_flash +cw01.menu.baud.115200=115200 +cw01.menu.baud.115200.upload.speed=115200 +cw01.menu.baud.57600=57600 +cw01.menu.baud.57600.upload.speed=57600 +cw01.menu.baud.230400.linux=230400 +cw01.menu.baud.230400.macosx=230400 +cw01.menu.baud.230400.upload.speed=230400 +cw01.menu.baud.256000.windows=256000 +cw01.menu.baud.256000.upload.speed=256000 +cw01.menu.baud.460800.linux=460800 +cw01.menu.baud.460800.macosx=460800 +cw01.menu.baud.460800.upload.speed=460800 +cw01.menu.baud.512000.windows=512000 +cw01.menu.baud.512000.upload.speed=512000 +cw01.menu.baud.921600=921600 +cw01.menu.baud.921600.upload.speed=921600 +cw01.menu.baud.3000000=3000000 +cw01.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espresso_lite_v1.name=ESPresso Lite 1.0 +espresso_lite_v1.build.board=ESP8266_ESPRESSO_LITE_V1 +espresso_lite_v1.build.variant=espresso_lite_v1 +espresso_lite_v1.upload.tool=esptool +espresso_lite_v1.upload.maximum_data_size=81920 +espresso_lite_v1.upload.wait_for_upload_port=true +espresso_lite_v1.upload.erase_cmd=version +espresso_lite_v1.serial.disableDTR=true +espresso_lite_v1.serial.disableRTS=true +espresso_lite_v1.build.mcu=esp8266 +espresso_lite_v1.build.core=esp8266 +espresso_lite_v1.build.spiffs_pagesize=256 +espresso_lite_v1.build.debug_port= +espresso_lite_v1.build.debug_level= +espresso_lite_v1.menu.xtal.80=80 MHz +espresso_lite_v1.menu.xtal.80.build.f_cpu=80000000L +espresso_lite_v1.menu.xtal.160=160 MHz +espresso_lite_v1.menu.xtal.160.build.f_cpu=160000000L +espresso_lite_v1.menu.vt.flash=Flash +espresso_lite_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espresso_lite_v1.menu.vt.heap=Heap +espresso_lite_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espresso_lite_v1.menu.vt.iram=IRAM +espresso_lite_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espresso_lite_v1.menu.exception.legacy=Legacy (new can return nullptr) +espresso_lite_v1.menu.exception.legacy.build.exception_flags=-fno-exceptions +espresso_lite_v1.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espresso_lite_v1.menu.exception.disabled=Disabled (new can abort) +espresso_lite_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espresso_lite_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espresso_lite_v1.menu.exception.enabled=Enabled +espresso_lite_v1.menu.exception.enabled.build.exception_flags=-fexceptions +espresso_lite_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espresso_lite_v1.menu.ssl.all=All SSL ciphers (most compatible) +espresso_lite_v1.menu.ssl.all.build.sslflags= +espresso_lite_v1.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espresso_lite_v1.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espresso_lite_v1.build.flash_mode=dio +espresso_lite_v1.build.flash_flags=-DFLASHMODE_DIO +espresso_lite_v1.build.flash_freq=40 +espresso_lite_v1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +espresso_lite_v1.menu.eesz.4M2M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M2M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espresso_lite_v1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +espresso_lite_v1.menu.eesz.4M3M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M3M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espresso_lite_v1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +espresso_lite_v1.menu.eesz.4M1M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M1M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espresso_lite_v1.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +espresso_lite_v1.menu.eesz.4M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espresso_lite_v1.menu.eesz.4M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.ResetMethod.ck=ck +espresso_lite_v1.menu.ResetMethod.ck.upload.resetmethod=ck +espresso_lite_v1.menu.ResetMethod.nodemcu=nodemcu +espresso_lite_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +espresso_lite_v1.menu.ip.lm2f=v2 Lower Memory +espresso_lite_v1.menu.ip.lm2f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espresso_lite_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.hb2f=v2 Higher Bandwidth +espresso_lite_v1.menu.ip.hb2f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espresso_lite_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.lm2n=v2 Lower Memory (no features) +espresso_lite_v1.menu.ip.lm2n.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espresso_lite_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espresso_lite_v1.menu.ip.hb2n.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espresso_lite_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.lm6f=v2 IPv6 Lower Memory +espresso_lite_v1.menu.ip.lm6f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espresso_lite_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espresso_lite_v1.menu.ip.hb6f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espresso_lite_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v1.menu.ip.hb1=v1.4 Higher Bandwidth +espresso_lite_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espresso_lite_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v1.menu.ip.src=v1.4 Compile from source +espresso_lite_v1.menu.ip.src.build.lwip_lib=-llwip_src +espresso_lite_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espresso_lite_v1.menu.dbg.Disabled=Disabled +espresso_lite_v1.menu.dbg.Disabled.build.debug_port= +espresso_lite_v1.menu.dbg.Serial=Serial +espresso_lite_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espresso_lite_v1.menu.dbg.Serial1=Serial1 +espresso_lite_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espresso_lite_v1.menu.lvl.None____=None +espresso_lite_v1.menu.lvl.None____.build.debug_level= +espresso_lite_v1.menu.lvl.SSL=SSL +espresso_lite_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espresso_lite_v1.menu.lvl.TLS_MEM=TLS_MEM +espresso_lite_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espresso_lite_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espresso_lite_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER +espresso_lite_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espresso_lite_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.CORE=CORE +espresso_lite_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espresso_lite_v1.menu.lvl.WIFI=WIFI +espresso_lite_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espresso_lite_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espresso_lite_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espresso_lite_v1.menu.lvl.UPDATER=UPDATER +espresso_lite_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espresso_lite_v1.menu.lvl.OTA=OTA +espresso_lite_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espresso_lite_v1.menu.lvl.OOM=OOM +espresso_lite_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espresso_lite_v1.menu.lvl.MDNS=MDNS +espresso_lite_v1.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espresso_lite_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espresso_lite_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espresso_lite_v1.menu.wipe.none=Only Sketch +espresso_lite_v1.menu.wipe.none.upload.erase_cmd=version +espresso_lite_v1.menu.wipe.sdk=Sketch + WiFi Settings +espresso_lite_v1.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espresso_lite_v1.menu.wipe.all=All Flash Contents +espresso_lite_v1.menu.wipe.all.upload.erase_cmd=erase_flash +espresso_lite_v1.menu.baud.115200=115200 +espresso_lite_v1.menu.baud.115200.upload.speed=115200 +espresso_lite_v1.menu.baud.57600=57600 +espresso_lite_v1.menu.baud.57600.upload.speed=57600 +espresso_lite_v1.menu.baud.230400.linux=230400 +espresso_lite_v1.menu.baud.230400.macosx=230400 +espresso_lite_v1.menu.baud.230400.upload.speed=230400 +espresso_lite_v1.menu.baud.256000.windows=256000 +espresso_lite_v1.menu.baud.256000.upload.speed=256000 +espresso_lite_v1.menu.baud.460800.linux=460800 +espresso_lite_v1.menu.baud.460800.macosx=460800 +espresso_lite_v1.menu.baud.460800.upload.speed=460800 +espresso_lite_v1.menu.baud.512000.windows=512000 +espresso_lite_v1.menu.baud.512000.upload.speed=512000 +espresso_lite_v1.menu.baud.921600=921600 +espresso_lite_v1.menu.baud.921600.upload.speed=921600 +espresso_lite_v1.menu.baud.3000000=3000000 +espresso_lite_v1.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espresso_lite_v2.name=ESPresso Lite 2.0 +espresso_lite_v2.build.board=ESP8266_ESPRESSO_LITE_V2 +espresso_lite_v2.build.variant=espresso_lite_v2 +espresso_lite_v2.upload.tool=esptool +espresso_lite_v2.upload.maximum_data_size=81920 +espresso_lite_v2.upload.wait_for_upload_port=true +espresso_lite_v2.upload.erase_cmd=version +espresso_lite_v2.serial.disableDTR=true +espresso_lite_v2.serial.disableRTS=true +espresso_lite_v2.build.mcu=esp8266 +espresso_lite_v2.build.core=esp8266 +espresso_lite_v2.build.spiffs_pagesize=256 +espresso_lite_v2.build.debug_port= +espresso_lite_v2.build.debug_level= +espresso_lite_v2.menu.xtal.80=80 MHz +espresso_lite_v2.menu.xtal.80.build.f_cpu=80000000L +espresso_lite_v2.menu.xtal.160=160 MHz +espresso_lite_v2.menu.xtal.160.build.f_cpu=160000000L +espresso_lite_v2.menu.vt.flash=Flash +espresso_lite_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espresso_lite_v2.menu.vt.heap=Heap +espresso_lite_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espresso_lite_v2.menu.vt.iram=IRAM +espresso_lite_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espresso_lite_v2.menu.exception.legacy=Legacy (new can return nullptr) +espresso_lite_v2.menu.exception.legacy.build.exception_flags=-fno-exceptions +espresso_lite_v2.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espresso_lite_v2.menu.exception.disabled=Disabled (new can abort) +espresso_lite_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espresso_lite_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espresso_lite_v2.menu.exception.enabled=Enabled +espresso_lite_v2.menu.exception.enabled.build.exception_flags=-fexceptions +espresso_lite_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espresso_lite_v2.menu.ssl.all=All SSL ciphers (most compatible) +espresso_lite_v2.menu.ssl.all.build.sslflags= +espresso_lite_v2.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espresso_lite_v2.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espresso_lite_v2.build.flash_mode=dio +espresso_lite_v2.build.flash_flags=-DFLASHMODE_DIO +espresso_lite_v2.build.flash_freq=40 +espresso_lite_v2.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +espresso_lite_v2.menu.eesz.4M2M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M2M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espresso_lite_v2.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +espresso_lite_v2.menu.eesz.4M3M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M3M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espresso_lite_v2.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +espresso_lite_v2.menu.eesz.4M1M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M1M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espresso_lite_v2.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +espresso_lite_v2.menu.eesz.4M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espresso_lite_v2.menu.eesz.4M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.ResetMethod.ck=ck +espresso_lite_v2.menu.ResetMethod.ck.upload.resetmethod=ck +espresso_lite_v2.menu.ResetMethod.nodemcu=nodemcu +espresso_lite_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +espresso_lite_v2.menu.ip.lm2f=v2 Lower Memory +espresso_lite_v2.menu.ip.lm2f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espresso_lite_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.hb2f=v2 Higher Bandwidth +espresso_lite_v2.menu.ip.hb2f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espresso_lite_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.lm2n=v2 Lower Memory (no features) +espresso_lite_v2.menu.ip.lm2n.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espresso_lite_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espresso_lite_v2.menu.ip.hb2n.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espresso_lite_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.lm6f=v2 IPv6 Lower Memory +espresso_lite_v2.menu.ip.lm6f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espresso_lite_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espresso_lite_v2.menu.ip.hb6f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espresso_lite_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v2.menu.ip.hb1=v1.4 Higher Bandwidth +espresso_lite_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espresso_lite_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v2.menu.ip.src=v1.4 Compile from source +espresso_lite_v2.menu.ip.src.build.lwip_lib=-llwip_src +espresso_lite_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espresso_lite_v2.menu.dbg.Disabled=Disabled +espresso_lite_v2.menu.dbg.Disabled.build.debug_port= +espresso_lite_v2.menu.dbg.Serial=Serial +espresso_lite_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espresso_lite_v2.menu.dbg.Serial1=Serial1 +espresso_lite_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espresso_lite_v2.menu.lvl.None____=None +espresso_lite_v2.menu.lvl.None____.build.debug_level= +espresso_lite_v2.menu.lvl.SSL=SSL +espresso_lite_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espresso_lite_v2.menu.lvl.TLS_MEM=TLS_MEM +espresso_lite_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espresso_lite_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espresso_lite_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER +espresso_lite_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espresso_lite_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.CORE=CORE +espresso_lite_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espresso_lite_v2.menu.lvl.WIFI=WIFI +espresso_lite_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espresso_lite_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espresso_lite_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espresso_lite_v2.menu.lvl.UPDATER=UPDATER +espresso_lite_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espresso_lite_v2.menu.lvl.OTA=OTA +espresso_lite_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espresso_lite_v2.menu.lvl.OOM=OOM +espresso_lite_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espresso_lite_v2.menu.lvl.MDNS=MDNS +espresso_lite_v2.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espresso_lite_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espresso_lite_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espresso_lite_v2.menu.wipe.none=Only Sketch +espresso_lite_v2.menu.wipe.none.upload.erase_cmd=version +espresso_lite_v2.menu.wipe.sdk=Sketch + WiFi Settings +espresso_lite_v2.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espresso_lite_v2.menu.wipe.all=All Flash Contents +espresso_lite_v2.menu.wipe.all.upload.erase_cmd=erase_flash +espresso_lite_v2.menu.baud.115200=115200 +espresso_lite_v2.menu.baud.115200.upload.speed=115200 +espresso_lite_v2.menu.baud.57600=57600 +espresso_lite_v2.menu.baud.57600.upload.speed=57600 +espresso_lite_v2.menu.baud.230400.linux=230400 +espresso_lite_v2.menu.baud.230400.macosx=230400 +espresso_lite_v2.menu.baud.230400.upload.speed=230400 +espresso_lite_v2.menu.baud.256000.windows=256000 +espresso_lite_v2.menu.baud.256000.upload.speed=256000 +espresso_lite_v2.menu.baud.460800.linux=460800 +espresso_lite_v2.menu.baud.460800.macosx=460800 +espresso_lite_v2.menu.baud.460800.upload.speed=460800 +espresso_lite_v2.menu.baud.512000.windows=512000 +espresso_lite_v2.menu.baud.512000.upload.speed=512000 +espresso_lite_v2.menu.baud.921600=921600 +espresso_lite_v2.menu.baud.921600.upload.speed=921600 +espresso_lite_v2.menu.baud.3000000=3000000 +espresso_lite_v2.menu.baud.3000000.upload.speed=3000000 + +############################################################## +phoenix_v1.name=Phoenix 1.0 +phoenix_v1.build.board=ESP8266_PHOENIX_V1 +phoenix_v1.build.variant=phoenix_v1 +phoenix_v1.upload.tool=esptool +phoenix_v1.upload.maximum_data_size=81920 +phoenix_v1.upload.wait_for_upload_port=true +phoenix_v1.upload.erase_cmd=version +phoenix_v1.serial.disableDTR=true +phoenix_v1.serial.disableRTS=true +phoenix_v1.build.mcu=esp8266 +phoenix_v1.build.core=esp8266 +phoenix_v1.build.spiffs_pagesize=256 +phoenix_v1.build.debug_port= +phoenix_v1.build.debug_level= +phoenix_v1.menu.xtal.80=80 MHz +phoenix_v1.menu.xtal.80.build.f_cpu=80000000L +phoenix_v1.menu.xtal.160=160 MHz +phoenix_v1.menu.xtal.160.build.f_cpu=160000000L +phoenix_v1.menu.vt.flash=Flash +phoenix_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +phoenix_v1.menu.vt.heap=Heap +phoenix_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +phoenix_v1.menu.vt.iram=IRAM +phoenix_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +phoenix_v1.menu.exception.legacy=Legacy (new can return nullptr) +phoenix_v1.menu.exception.legacy.build.exception_flags=-fno-exceptions +phoenix_v1.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +phoenix_v1.menu.exception.disabled=Disabled (new can abort) +phoenix_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +phoenix_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +phoenix_v1.menu.exception.enabled=Enabled +phoenix_v1.menu.exception.enabled.build.exception_flags=-fexceptions +phoenix_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +phoenix_v1.menu.ssl.all=All SSL ciphers (most compatible) +phoenix_v1.menu.ssl.all.build.sslflags= +phoenix_v1.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +phoenix_v1.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +phoenix_v1.build.flash_mode=dio +phoenix_v1.build.flash_flags=-DFLASHMODE_DIO +phoenix_v1.build.flash_freq=40 +phoenix_v1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +phoenix_v1.menu.eesz.4M2M.build.flash_size=4M +phoenix_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +phoenix_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M2M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 +phoenix_v1.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +phoenix_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 +phoenix_v1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +phoenix_v1.menu.eesz.4M3M.build.flash_size=4M +phoenix_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +phoenix_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M3M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 +phoenix_v1.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +phoenix_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 +phoenix_v1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +phoenix_v1.menu.eesz.4M1M.build.flash_size=4M +phoenix_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +phoenix_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M1M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 +phoenix_v1.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +phoenix_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 +phoenix_v1.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +phoenix_v1.menu.eesz.4M.build.flash_size=4M +phoenix_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +phoenix_v1.menu.eesz.4M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.ResetMethod.ck=ck +phoenix_v1.menu.ResetMethod.ck.upload.resetmethod=ck +phoenix_v1.menu.ResetMethod.nodemcu=nodemcu +phoenix_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +phoenix_v1.menu.ip.lm2f=v2 Lower Memory +phoenix_v1.menu.ip.lm2f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +phoenix_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.hb2f=v2 Higher Bandwidth +phoenix_v1.menu.ip.hb2f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +phoenix_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.lm2n=v2 Lower Memory (no features) +phoenix_v1.menu.ip.lm2n.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +phoenix_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) +phoenix_v1.menu.ip.hb2n.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +phoenix_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.lm6f=v2 IPv6 Lower Memory +phoenix_v1.menu.ip.lm6f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +phoenix_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +phoenix_v1.menu.ip.hb6f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +phoenix_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v1.menu.ip.hb1=v1.4 Higher Bandwidth +phoenix_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc +phoenix_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v1.menu.ip.src=v1.4 Compile from source +phoenix_v1.menu.ip.src.build.lwip_lib=-llwip_src +phoenix_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +phoenix_v1.menu.dbg.Disabled=Disabled +phoenix_v1.menu.dbg.Disabled.build.debug_port= +phoenix_v1.menu.dbg.Serial=Serial +phoenix_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +phoenix_v1.menu.dbg.Serial1=Serial1 +phoenix_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +phoenix_v1.menu.lvl.None____=None +phoenix_v1.menu.lvl.None____.build.debug_level= +phoenix_v1.menu.lvl.SSL=SSL +phoenix_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +phoenix_v1.menu.lvl.TLS_MEM=TLS_MEM +phoenix_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +phoenix_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +phoenix_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER +phoenix_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +phoenix_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +phoenix_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +phoenix_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +phoenix_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.CORE=CORE +phoenix_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +phoenix_v1.menu.lvl.WIFI=WIFI +phoenix_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +phoenix_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +phoenix_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +phoenix_v1.menu.lvl.UPDATER=UPDATER +phoenix_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +phoenix_v1.menu.lvl.OTA=OTA +phoenix_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +phoenix_v1.menu.lvl.OOM=OOM +phoenix_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +phoenix_v1.menu.lvl.MDNS=MDNS +phoenix_v1.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +phoenix_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +phoenix_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +phoenix_v1.menu.wipe.none=Only Sketch +phoenix_v1.menu.wipe.none.upload.erase_cmd=version +phoenix_v1.menu.wipe.sdk=Sketch + WiFi Settings +phoenix_v1.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +phoenix_v1.menu.wipe.all=All Flash Contents +phoenix_v1.menu.wipe.all.upload.erase_cmd=erase_flash +phoenix_v1.menu.baud.115200=115200 +phoenix_v1.menu.baud.115200.upload.speed=115200 +phoenix_v1.menu.baud.57600=57600 +phoenix_v1.menu.baud.57600.upload.speed=57600 +phoenix_v1.menu.baud.230400.linux=230400 +phoenix_v1.menu.baud.230400.macosx=230400 +phoenix_v1.menu.baud.230400.upload.speed=230400 +phoenix_v1.menu.baud.256000.windows=256000 +phoenix_v1.menu.baud.256000.upload.speed=256000 +phoenix_v1.menu.baud.460800.linux=460800 +phoenix_v1.menu.baud.460800.macosx=460800 +phoenix_v1.menu.baud.460800.upload.speed=460800 +phoenix_v1.menu.baud.512000.windows=512000 +phoenix_v1.menu.baud.512000.upload.speed=512000 +phoenix_v1.menu.baud.921600=921600 +phoenix_v1.menu.baud.921600.upload.speed=921600 +phoenix_v1.menu.baud.3000000=3000000 +phoenix_v1.menu.baud.3000000.upload.speed=3000000 + +############################################################## +phoenix_v2.name=Phoenix 2.0 +phoenix_v2.build.board=ESP8266_PHOENIX_V2 +phoenix_v2.build.variant=phoenix_v2 +phoenix_v2.upload.tool=esptool +phoenix_v2.upload.maximum_data_size=81920 +phoenix_v2.upload.wait_for_upload_port=true +phoenix_v2.upload.erase_cmd=version +phoenix_v2.serial.disableDTR=true +phoenix_v2.serial.disableRTS=true +phoenix_v2.build.mcu=esp8266 +phoenix_v2.build.core=esp8266 +phoenix_v2.build.spiffs_pagesize=256 +phoenix_v2.build.debug_port= +phoenix_v2.build.debug_level= +phoenix_v2.menu.xtal.80=80 MHz +phoenix_v2.menu.xtal.80.build.f_cpu=80000000L +phoenix_v2.menu.xtal.160=160 MHz +phoenix_v2.menu.xtal.160.build.f_cpu=160000000L +phoenix_v2.menu.vt.flash=Flash +phoenix_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +phoenix_v2.menu.vt.heap=Heap +phoenix_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +phoenix_v2.menu.vt.iram=IRAM +phoenix_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +phoenix_v2.menu.exception.legacy=Legacy (new can return nullptr) +phoenix_v2.menu.exception.legacy.build.exception_flags=-fno-exceptions +phoenix_v2.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +phoenix_v2.menu.exception.disabled=Disabled (new can abort) +phoenix_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +phoenix_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +phoenix_v2.menu.exception.enabled=Enabled +phoenix_v2.menu.exception.enabled.build.exception_flags=-fexceptions +phoenix_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +phoenix_v2.menu.ssl.all=All SSL ciphers (most compatible) +phoenix_v2.menu.ssl.all.build.sslflags= +phoenix_v2.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +phoenix_v2.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +phoenix_v2.build.flash_mode=dio +phoenix_v2.build.flash_flags=-DFLASHMODE_DIO +phoenix_v2.build.flash_freq=40 +phoenix_v2.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +phoenix_v2.menu.eesz.4M2M.build.flash_size=4M +phoenix_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +phoenix_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M2M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 +phoenix_v2.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +phoenix_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 +phoenix_v2.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +phoenix_v2.menu.eesz.4M3M.build.flash_size=4M +phoenix_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +phoenix_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M3M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 +phoenix_v2.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +phoenix_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 +phoenix_v2.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +phoenix_v2.menu.eesz.4M1M.build.flash_size=4M +phoenix_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +phoenix_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M1M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 +phoenix_v2.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +phoenix_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 +phoenix_v2.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +phoenix_v2.menu.eesz.4M.build.flash_size=4M +phoenix_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +phoenix_v2.menu.eesz.4M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.ResetMethod.ck=ck +phoenix_v2.menu.ResetMethod.ck.upload.resetmethod=ck +phoenix_v2.menu.ResetMethod.nodemcu=nodemcu +phoenix_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +phoenix_v2.menu.ip.lm2f=v2 Lower Memory +phoenix_v2.menu.ip.lm2f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +phoenix_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.hb2f=v2 Higher Bandwidth +phoenix_v2.menu.ip.hb2f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +phoenix_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.lm2n=v2 Lower Memory (no features) +phoenix_v2.menu.ip.lm2n.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +phoenix_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) +phoenix_v2.menu.ip.hb2n.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +phoenix_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.lm6f=v2 IPv6 Lower Memory +phoenix_v2.menu.ip.lm6f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +phoenix_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +phoenix_v2.menu.ip.hb6f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +phoenix_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v2.menu.ip.hb1=v1.4 Higher Bandwidth +phoenix_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc +phoenix_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v2.menu.ip.src=v1.4 Compile from source +phoenix_v2.menu.ip.src.build.lwip_lib=-llwip_src +phoenix_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +phoenix_v2.menu.dbg.Disabled=Disabled +phoenix_v2.menu.dbg.Disabled.build.debug_port= +phoenix_v2.menu.dbg.Serial=Serial +phoenix_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +phoenix_v2.menu.dbg.Serial1=Serial1 +phoenix_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +phoenix_v2.menu.lvl.None____=None +phoenix_v2.menu.lvl.None____.build.debug_level= +phoenix_v2.menu.lvl.SSL=SSL +phoenix_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +phoenix_v2.menu.lvl.TLS_MEM=TLS_MEM +phoenix_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +phoenix_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +phoenix_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER +phoenix_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +phoenix_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +phoenix_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +phoenix_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +phoenix_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.CORE=CORE +phoenix_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +phoenix_v2.menu.lvl.WIFI=WIFI +phoenix_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +phoenix_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +phoenix_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +phoenix_v2.menu.lvl.UPDATER=UPDATER +phoenix_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +phoenix_v2.menu.lvl.OTA=OTA +phoenix_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +phoenix_v2.menu.lvl.OOM=OOM +phoenix_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +phoenix_v2.menu.lvl.MDNS=MDNS +phoenix_v2.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +phoenix_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +phoenix_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +phoenix_v2.menu.wipe.none=Only Sketch +phoenix_v2.menu.wipe.none.upload.erase_cmd=version +phoenix_v2.menu.wipe.sdk=Sketch + WiFi Settings +phoenix_v2.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +phoenix_v2.menu.wipe.all=All Flash Contents +phoenix_v2.menu.wipe.all.upload.erase_cmd=erase_flash +phoenix_v2.menu.baud.115200=115200 +phoenix_v2.menu.baud.115200.upload.speed=115200 +phoenix_v2.menu.baud.57600=57600 +phoenix_v2.menu.baud.57600.upload.speed=57600 +phoenix_v2.menu.baud.230400.linux=230400 +phoenix_v2.menu.baud.230400.macosx=230400 +phoenix_v2.menu.baud.230400.upload.speed=230400 +phoenix_v2.menu.baud.256000.windows=256000 +phoenix_v2.menu.baud.256000.upload.speed=256000 +phoenix_v2.menu.baud.460800.linux=460800 +phoenix_v2.menu.baud.460800.macosx=460800 +phoenix_v2.menu.baud.460800.upload.speed=460800 +phoenix_v2.menu.baud.512000.windows=512000 +phoenix_v2.menu.baud.512000.upload.speed=512000 +phoenix_v2.menu.baud.921600=921600 +phoenix_v2.menu.baud.921600.upload.speed=921600 +phoenix_v2.menu.baud.3000000=3000000 +phoenix_v2.menu.baud.3000000.upload.speed=3000000 + +############################################################## +nodemcu.name=NodeMCU 0.9 (ESP-12 Module) +nodemcu.build.board=ESP8266_NODEMCU +nodemcu.build.variant=nodemcu +nodemcu.upload.tool=esptool +nodemcu.upload.maximum_data_size=81920 +nodemcu.upload.wait_for_upload_port=true +nodemcu.upload.erase_cmd=version +nodemcu.serial.disableDTR=true +nodemcu.serial.disableRTS=true +nodemcu.build.mcu=esp8266 +nodemcu.build.core=esp8266 +nodemcu.build.spiffs_pagesize=256 +nodemcu.build.debug_port= +nodemcu.build.debug_level= +nodemcu.menu.xtal.80=80 MHz +nodemcu.menu.xtal.80.build.f_cpu=80000000L +nodemcu.menu.xtal.160=160 MHz +nodemcu.menu.xtal.160.build.f_cpu=160000000L +nodemcu.menu.vt.flash=Flash +nodemcu.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +nodemcu.menu.vt.heap=Heap +nodemcu.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +nodemcu.menu.vt.iram=IRAM +nodemcu.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +nodemcu.menu.exception.legacy=Legacy (new can return nullptr) +nodemcu.menu.exception.legacy.build.exception_flags=-fno-exceptions +nodemcu.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +nodemcu.menu.exception.disabled=Disabled (new can abort) +nodemcu.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +nodemcu.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +nodemcu.menu.exception.enabled=Enabled +nodemcu.menu.exception.enabled.build.exception_flags=-fexceptions +nodemcu.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +nodemcu.menu.ssl.all=All SSL ciphers (most compatible) +nodemcu.menu.ssl.all.build.sslflags= +nodemcu.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +nodemcu.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +nodemcu.upload.resetmethod=nodemcu +nodemcu.build.flash_mode=qio +nodemcu.build.flash_flags=-DFLASHMODE_QIO +nodemcu.build.flash_freq=40 +nodemcu.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +nodemcu.menu.eesz.4M2M.build.flash_size=4M +nodemcu.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +nodemcu.menu.eesz.4M2M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M2M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M2M.build.spiffs_start=0x200000 +nodemcu.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +nodemcu.menu.eesz.4M2M.build.spiffs_blocksize=8192 +nodemcu.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +nodemcu.menu.eesz.4M3M.build.flash_size=4M +nodemcu.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +nodemcu.menu.eesz.4M3M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M3M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M3M.build.spiffs_start=0x100000 +nodemcu.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +nodemcu.menu.eesz.4M3M.build.spiffs_blocksize=8192 +nodemcu.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +nodemcu.menu.eesz.4M1M.build.flash_size=4M +nodemcu.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +nodemcu.menu.eesz.4M1M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M1M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M1M.build.spiffs_start=0x300000 +nodemcu.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +nodemcu.menu.eesz.4M1M.build.spiffs_blocksize=8192 +nodemcu.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +nodemcu.menu.eesz.4M.build.flash_size=4M +nodemcu.menu.eesz.4M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +nodemcu.menu.eesz.4M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M.build.rfcal_addr=0x3FC000 +nodemcu.menu.ip.lm2f=v2 Lower Memory +nodemcu.menu.ip.lm2f.build.lwip_include=lwip2/include +nodemcu.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +nodemcu.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcu.menu.ip.hb2f=v2 Higher Bandwidth +nodemcu.menu.ip.hb2f.build.lwip_include=lwip2/include +nodemcu.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +nodemcu.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcu.menu.ip.lm2n=v2 Lower Memory (no features) +nodemcu.menu.ip.lm2n.build.lwip_include=lwip2/include +nodemcu.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +nodemcu.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcu.menu.ip.hb2n=v2 Higher Bandwidth (no features) +nodemcu.menu.ip.hb2n.build.lwip_include=lwip2/include +nodemcu.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +nodemcu.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcu.menu.ip.lm6f=v2 IPv6 Lower Memory +nodemcu.menu.ip.lm6f.build.lwip_include=lwip2/include +nodemcu.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +nodemcu.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcu.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +nodemcu.menu.ip.hb6f.build.lwip_include=lwip2/include +nodemcu.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +nodemcu.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcu.menu.ip.hb1=v1.4 Higher Bandwidth +nodemcu.menu.ip.hb1.build.lwip_lib=-llwip_gcc +nodemcu.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcu.menu.ip.src=v1.4 Compile from source +nodemcu.menu.ip.src.build.lwip_lib=-llwip_src +nodemcu.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcu.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +nodemcu.menu.dbg.Disabled=Disabled +nodemcu.menu.dbg.Disabled.build.debug_port= +nodemcu.menu.dbg.Serial=Serial +nodemcu.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +nodemcu.menu.dbg.Serial1=Serial1 +nodemcu.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +nodemcu.menu.lvl.None____=None +nodemcu.menu.lvl.None____.build.debug_level= +nodemcu.menu.lvl.SSL=SSL +nodemcu.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +nodemcu.menu.lvl.TLS_MEM=TLS_MEM +nodemcu.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +nodemcu.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +nodemcu.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.HTTP_SERVER=HTTP_SERVER +nodemcu.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +nodemcu.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +nodemcu.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +nodemcu.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +nodemcu.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.CORE=CORE +nodemcu.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +nodemcu.menu.lvl.WIFI=WIFI +nodemcu.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +nodemcu.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +nodemcu.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +nodemcu.menu.lvl.UPDATER=UPDATER +nodemcu.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +nodemcu.menu.lvl.OTA=OTA +nodemcu.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +nodemcu.menu.lvl.OOM=OOM +nodemcu.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +nodemcu.menu.lvl.MDNS=MDNS +nodemcu.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +nodemcu.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +nodemcu.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +nodemcu.menu.wipe.none=Only Sketch +nodemcu.menu.wipe.none.upload.erase_cmd=version +nodemcu.menu.wipe.sdk=Sketch + WiFi Settings +nodemcu.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +nodemcu.menu.wipe.all=All Flash Contents +nodemcu.menu.wipe.all.upload.erase_cmd=erase_flash +nodemcu.menu.baud.115200=115200 +nodemcu.menu.baud.115200.upload.speed=115200 +nodemcu.menu.baud.57600=57600 +nodemcu.menu.baud.57600.upload.speed=57600 +nodemcu.menu.baud.230400.linux=230400 +nodemcu.menu.baud.230400.macosx=230400 +nodemcu.menu.baud.230400.upload.speed=230400 +nodemcu.menu.baud.256000.windows=256000 +nodemcu.menu.baud.256000.upload.speed=256000 +nodemcu.menu.baud.460800.linux=460800 +nodemcu.menu.baud.460800.macosx=460800 +nodemcu.menu.baud.460800.upload.speed=460800 +nodemcu.menu.baud.512000.windows=512000 +nodemcu.menu.baud.512000.upload.speed=512000 +nodemcu.menu.baud.921600=921600 +nodemcu.menu.baud.921600.upload.speed=921600 +nodemcu.menu.baud.3000000=3000000 +nodemcu.menu.baud.3000000.upload.speed=3000000 + +############################################################## +nodemcuv2.name=NodeMCU 1.0 (ESP-12E Module) +nodemcuv2.build.board=ESP8266_NODEMCU +nodemcuv2.build.variant=nodemcu +nodemcuv2.upload.tool=esptool +nodemcuv2.upload.maximum_data_size=81920 +nodemcuv2.upload.wait_for_upload_port=true +nodemcuv2.upload.erase_cmd=version +nodemcuv2.serial.disableDTR=true +nodemcuv2.serial.disableRTS=true +nodemcuv2.build.mcu=esp8266 +nodemcuv2.build.core=esp8266 +nodemcuv2.build.spiffs_pagesize=256 +nodemcuv2.build.debug_port= +nodemcuv2.build.debug_level= +nodemcuv2.menu.xtal.80=80 MHz +nodemcuv2.menu.xtal.80.build.f_cpu=80000000L +nodemcuv2.menu.xtal.160=160 MHz +nodemcuv2.menu.xtal.160.build.f_cpu=160000000L +nodemcuv2.menu.vt.flash=Flash +nodemcuv2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +nodemcuv2.menu.vt.heap=Heap +nodemcuv2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +nodemcuv2.menu.vt.iram=IRAM +nodemcuv2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +nodemcuv2.menu.exception.legacy=Legacy (new can return nullptr) +nodemcuv2.menu.exception.legacy.build.exception_flags=-fno-exceptions +nodemcuv2.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +nodemcuv2.menu.exception.disabled=Disabled (new can abort) +nodemcuv2.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +nodemcuv2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +nodemcuv2.menu.exception.enabled=Enabled +nodemcuv2.menu.exception.enabled.build.exception_flags=-fexceptions +nodemcuv2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +nodemcuv2.menu.ssl.all=All SSL ciphers (most compatible) +nodemcuv2.menu.ssl.all.build.sslflags= +nodemcuv2.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +nodemcuv2.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +nodemcuv2.upload.resetmethod=nodemcu +nodemcuv2.build.flash_mode=dio +nodemcuv2.build.flash_flags=-DFLASHMODE_DIO +nodemcuv2.build.flash_freq=40 +nodemcuv2.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +nodemcuv2.menu.eesz.4M2M.build.flash_size=4M +nodemcuv2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +nodemcuv2.menu.eesz.4M2M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M2M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M2M.build.spiffs_start=0x200000 +nodemcuv2.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +nodemcuv2.menu.eesz.4M2M.build.spiffs_blocksize=8192 +nodemcuv2.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +nodemcuv2.menu.eesz.4M3M.build.flash_size=4M +nodemcuv2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +nodemcuv2.menu.eesz.4M3M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M3M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M3M.build.spiffs_start=0x100000 +nodemcuv2.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +nodemcuv2.menu.eesz.4M3M.build.spiffs_blocksize=8192 +nodemcuv2.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +nodemcuv2.menu.eesz.4M1M.build.flash_size=4M +nodemcuv2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +nodemcuv2.menu.eesz.4M1M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M1M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M1M.build.spiffs_start=0x300000 +nodemcuv2.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +nodemcuv2.menu.eesz.4M1M.build.spiffs_blocksize=8192 +nodemcuv2.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +nodemcuv2.menu.eesz.4M.build.flash_size=4M +nodemcuv2.menu.eesz.4M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +nodemcuv2.menu.eesz.4M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.ip.lm2f=v2 Lower Memory +nodemcuv2.menu.ip.lm2f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +nodemcuv2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.hb2f=v2 Higher Bandwidth +nodemcuv2.menu.ip.hb2f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +nodemcuv2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.lm2n=v2 Lower Memory (no features) +nodemcuv2.menu.ip.lm2n.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +nodemcuv2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.hb2n=v2 Higher Bandwidth (no features) +nodemcuv2.menu.ip.hb2n.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +nodemcuv2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.lm6f=v2 IPv6 Lower Memory +nodemcuv2.menu.ip.lm6f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +nodemcuv2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcuv2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +nodemcuv2.menu.ip.hb6f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +nodemcuv2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcuv2.menu.ip.hb1=v1.4 Higher Bandwidth +nodemcuv2.menu.ip.hb1.build.lwip_lib=-llwip_gcc +nodemcuv2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcuv2.menu.ip.src=v1.4 Compile from source +nodemcuv2.menu.ip.src.build.lwip_lib=-llwip_src +nodemcuv2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcuv2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +nodemcuv2.menu.dbg.Disabled=Disabled +nodemcuv2.menu.dbg.Disabled.build.debug_port= +nodemcuv2.menu.dbg.Serial=Serial +nodemcuv2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +nodemcuv2.menu.dbg.Serial1=Serial1 +nodemcuv2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +nodemcuv2.menu.lvl.None____=None +nodemcuv2.menu.lvl.None____.build.debug_level= +nodemcuv2.menu.lvl.SSL=SSL +nodemcuv2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +nodemcuv2.menu.lvl.TLS_MEM=TLS_MEM +nodemcuv2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +nodemcuv2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +nodemcuv2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.HTTP_SERVER=HTTP_SERVER +nodemcuv2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +nodemcuv2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +nodemcuv2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +nodemcuv2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +nodemcuv2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.CORE=CORE +nodemcuv2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +nodemcuv2.menu.lvl.WIFI=WIFI +nodemcuv2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +nodemcuv2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +nodemcuv2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +nodemcuv2.menu.lvl.UPDATER=UPDATER +nodemcuv2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +nodemcuv2.menu.lvl.OTA=OTA +nodemcuv2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +nodemcuv2.menu.lvl.OOM=OOM +nodemcuv2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +nodemcuv2.menu.lvl.MDNS=MDNS +nodemcuv2.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +nodemcuv2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +nodemcuv2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +nodemcuv2.menu.wipe.none=Only Sketch +nodemcuv2.menu.wipe.none.upload.erase_cmd=version +nodemcuv2.menu.wipe.sdk=Sketch + WiFi Settings +nodemcuv2.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +nodemcuv2.menu.wipe.all=All Flash Contents +nodemcuv2.menu.wipe.all.upload.erase_cmd=erase_flash +nodemcuv2.menu.baud.115200=115200 +nodemcuv2.menu.baud.115200.upload.speed=115200 +nodemcuv2.menu.baud.57600=57600 +nodemcuv2.menu.baud.57600.upload.speed=57600 +nodemcuv2.menu.baud.230400.linux=230400 +nodemcuv2.menu.baud.230400.macosx=230400 +nodemcuv2.menu.baud.230400.upload.speed=230400 +nodemcuv2.menu.baud.256000.windows=256000 +nodemcuv2.menu.baud.256000.upload.speed=256000 +nodemcuv2.menu.baud.460800.linux=460800 +nodemcuv2.menu.baud.460800.macosx=460800 +nodemcuv2.menu.baud.460800.upload.speed=460800 +nodemcuv2.menu.baud.512000.windows=512000 +nodemcuv2.menu.baud.512000.upload.speed=512000 +nodemcuv2.menu.baud.921600=921600 +nodemcuv2.menu.baud.921600.upload.speed=921600 +nodemcuv2.menu.baud.3000000=3000000 +nodemcuv2.menu.baud.3000000.upload.speed=3000000 + +############################################################## +modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV) +modwifi.build.board=MOD_WIFI_ESP8266 +modwifi.build.variant=modwifi +modwifi.upload.tool=esptool +modwifi.upload.maximum_data_size=81920 +modwifi.upload.wait_for_upload_port=true +modwifi.upload.erase_cmd=version +modwifi.serial.disableDTR=true +modwifi.serial.disableRTS=true +modwifi.build.mcu=esp8266 +modwifi.build.core=esp8266 +modwifi.build.spiffs_pagesize=256 +modwifi.build.debug_port= +modwifi.build.debug_level= +modwifi.menu.xtal.80=80 MHz +modwifi.menu.xtal.80.build.f_cpu=80000000L +modwifi.menu.xtal.160=160 MHz +modwifi.menu.xtal.160.build.f_cpu=160000000L +modwifi.menu.vt.flash=Flash +modwifi.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +modwifi.menu.vt.heap=Heap +modwifi.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +modwifi.menu.vt.iram=IRAM +modwifi.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +modwifi.menu.exception.legacy=Legacy (new can return nullptr) +modwifi.menu.exception.legacy.build.exception_flags=-fno-exceptions +modwifi.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +modwifi.menu.exception.disabled=Disabled (new can abort) +modwifi.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +modwifi.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +modwifi.menu.exception.enabled=Enabled +modwifi.menu.exception.enabled.build.exception_flags=-fexceptions +modwifi.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +modwifi.menu.ssl.all=All SSL ciphers (most compatible) +modwifi.menu.ssl.all.build.sslflags= +modwifi.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +modwifi.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +modwifi.upload.resetmethod=ck +modwifi.build.flash_mode=qio +modwifi.build.flash_flags=-DFLASHMODE_QIO +modwifi.build.flash_freq=40 +modwifi.menu.eesz.2M64=2MB (FS:64KB OTA:~992KB) +modwifi.menu.eesz.2M64.build.flash_size=2M +modwifi.menu.eesz.2M64.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M64.build.flash_ld=eagle.flash.2m64.ld +modwifi.menu.eesz.2M64.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M64.upload.maximum_size=1044464 +modwifi.menu.eesz.2M64.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M64.build.spiffs_start=0x1F0000 +modwifi.menu.eesz.2M64.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M64.build.spiffs_blocksize=4096 +modwifi.menu.eesz.2M128=2MB (FS:128KB OTA:~960KB) +modwifi.menu.eesz.2M128.build.flash_size=2M +modwifi.menu.eesz.2M128.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld +modwifi.menu.eesz.2M128.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M128.upload.maximum_size=1044464 +modwifi.menu.eesz.2M128.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M128.build.spiffs_start=0x1E0000 +modwifi.menu.eesz.2M128.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M128.build.spiffs_blocksize=4096 +modwifi.menu.eesz.2M256=2MB (FS:256KB OTA:~896KB) +modwifi.menu.eesz.2M256.build.flash_size=2M +modwifi.menu.eesz.2M256.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld +modwifi.menu.eesz.2M256.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M256.upload.maximum_size=1044464 +modwifi.menu.eesz.2M256.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M256.build.spiffs_start=0x1C0000 +modwifi.menu.eesz.2M256.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M256.build.spiffs_blocksize=4096 +modwifi.menu.eesz.2M512=2MB (FS:512KB OTA:~768KB) +modwifi.menu.eesz.2M512.build.flash_size=2M +modwifi.menu.eesz.2M512.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld +modwifi.menu.eesz.2M512.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M512.upload.maximum_size=1044464 +modwifi.menu.eesz.2M512.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M512.build.spiffs_start=0x180000 +modwifi.menu.eesz.2M512.build.spiffs_end=0x1FA000 +modwifi.menu.eesz.2M512.build.spiffs_blocksize=8192 +modwifi.menu.eesz.2M1M=2MB (FS:1MB OTA:~512KB) +modwifi.menu.eesz.2M1M.build.flash_size=2M +modwifi.menu.eesz.2M1M.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld +modwifi.menu.eesz.2M1M.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M1M.upload.maximum_size=1044464 +modwifi.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M1M.build.spiffs_start=0x100000 +modwifi.menu.eesz.2M1M.build.spiffs_end=0x1FA000 +modwifi.menu.eesz.2M1M.build.spiffs_blocksize=8192 +modwifi.menu.eesz.2M=2MB (FS:none OTA:~1019KB) +modwifi.menu.eesz.2M.build.flash_size=2M +modwifi.menu.eesz.2M.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld +modwifi.menu.eesz.2M.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M.upload.maximum_size=1044464 +modwifi.menu.eesz.2M.build.rfcal_addr=0x1FC000 +modwifi.menu.ip.lm2f=v2 Lower Memory +modwifi.menu.ip.lm2f.build.lwip_include=lwip2/include +modwifi.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +modwifi.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +modwifi.menu.ip.hb2f=v2 Higher Bandwidth +modwifi.menu.ip.hb2f.build.lwip_include=lwip2/include +modwifi.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +modwifi.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +modwifi.menu.ip.lm2n=v2 Lower Memory (no features) +modwifi.menu.ip.lm2n.build.lwip_include=lwip2/include +modwifi.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +modwifi.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +modwifi.menu.ip.hb2n=v2 Higher Bandwidth (no features) +modwifi.menu.ip.hb2n.build.lwip_include=lwip2/include +modwifi.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +modwifi.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +modwifi.menu.ip.lm6f=v2 IPv6 Lower Memory +modwifi.menu.ip.lm6f.build.lwip_include=lwip2/include +modwifi.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +modwifi.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +modwifi.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +modwifi.menu.ip.hb6f.build.lwip_include=lwip2/include +modwifi.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +modwifi.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +modwifi.menu.ip.hb1=v1.4 Higher Bandwidth +modwifi.menu.ip.hb1.build.lwip_lib=-llwip_gcc +modwifi.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +modwifi.menu.ip.src=v1.4 Compile from source +modwifi.menu.ip.src.build.lwip_lib=-llwip_src +modwifi.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +modwifi.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +modwifi.menu.dbg.Disabled=Disabled +modwifi.menu.dbg.Disabled.build.debug_port= +modwifi.menu.dbg.Serial=Serial +modwifi.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +modwifi.menu.dbg.Serial1=Serial1 +modwifi.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +modwifi.menu.lvl.None____=None +modwifi.menu.lvl.None____.build.debug_level= +modwifi.menu.lvl.SSL=SSL +modwifi.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +modwifi.menu.lvl.TLS_MEM=TLS_MEM +modwifi.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +modwifi.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +modwifi.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.HTTP_SERVER=HTTP_SERVER +modwifi.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +modwifi.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +modwifi.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +modwifi.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +modwifi.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +modwifi.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.CORE=CORE +modwifi.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +modwifi.menu.lvl.WIFI=WIFI +modwifi.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +modwifi.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +modwifi.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +modwifi.menu.lvl.UPDATER=UPDATER +modwifi.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +modwifi.menu.lvl.OTA=OTA +modwifi.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +modwifi.menu.lvl.OOM=OOM +modwifi.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +modwifi.menu.lvl.MDNS=MDNS +modwifi.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +modwifi.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +modwifi.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +modwifi.menu.wipe.none=Only Sketch +modwifi.menu.wipe.none.upload.erase_cmd=version +modwifi.menu.wipe.sdk=Sketch + WiFi Settings +modwifi.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +modwifi.menu.wipe.all=All Flash Contents +modwifi.menu.wipe.all.upload.erase_cmd=erase_flash +modwifi.menu.baud.115200=115200 +modwifi.menu.baud.115200.upload.speed=115200 +modwifi.menu.baud.57600=57600 +modwifi.menu.baud.57600.upload.speed=57600 +modwifi.menu.baud.230400.linux=230400 +modwifi.menu.baud.230400.macosx=230400 +modwifi.menu.baud.230400.upload.speed=230400 +modwifi.menu.baud.256000.windows=256000 +modwifi.menu.baud.256000.upload.speed=256000 +modwifi.menu.baud.460800.linux=460800 +modwifi.menu.baud.460800.macosx=460800 +modwifi.menu.baud.460800.upload.speed=460800 +modwifi.menu.baud.512000.windows=512000 +modwifi.menu.baud.512000.upload.speed=512000 +modwifi.menu.baud.921600=921600 +modwifi.menu.baud.921600.upload.speed=921600 +modwifi.menu.baud.3000000=3000000 +modwifi.menu.baud.3000000.upload.speed=3000000 + +############################################################## +thing.name=SparkFun ESP8266 Thing +thing.build.board=ESP8266_THING +thing.build.variant=thing +thing.upload.tool=esptool +thing.upload.maximum_data_size=81920 +thing.upload.wait_for_upload_port=true +thing.upload.erase_cmd=version +thing.serial.disableDTR=true +thing.serial.disableRTS=true +thing.build.mcu=esp8266 +thing.build.core=esp8266 +thing.build.spiffs_pagesize=256 +thing.build.debug_port= +thing.build.debug_level= +thing.menu.xtal.80=80 MHz +thing.menu.xtal.80.build.f_cpu=80000000L +thing.menu.xtal.160=160 MHz +thing.menu.xtal.160.build.f_cpu=160000000L +thing.menu.vt.flash=Flash +thing.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +thing.menu.vt.heap=Heap +thing.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +thing.menu.vt.iram=IRAM +thing.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +thing.menu.exception.legacy=Legacy (new can return nullptr) +thing.menu.exception.legacy.build.exception_flags=-fno-exceptions +thing.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +thing.menu.exception.disabled=Disabled (new can abort) +thing.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +thing.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +thing.menu.exception.enabled=Enabled +thing.menu.exception.enabled.build.exception_flags=-fexceptions +thing.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +thing.menu.ssl.all=All SSL ciphers (most compatible) +thing.menu.ssl.all.build.sslflags= +thing.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +thing.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +thing.upload.resetmethod=ck +thing.build.flash_mode=qio +thing.build.flash_flags=-DFLASHMODE_QIO +thing.build.flash_freq=40 +thing.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB) +thing.menu.eesz.512K32.build.flash_size=512K +thing.menu.eesz.512K32.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +thing.menu.eesz.512K32.build.spiffs_pagesize=256 +thing.menu.eesz.512K32.upload.maximum_size=466928 +thing.menu.eesz.512K32.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K32.build.spiffs_start=0x73000 +thing.menu.eesz.512K32.build.spiffs_end=0x7B000 +thing.menu.eesz.512K32.build.spiffs_blocksize=4096 +thing.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB) +thing.menu.eesz.512K64.build.flash_size=512K +thing.menu.eesz.512K64.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +thing.menu.eesz.512K64.build.spiffs_pagesize=256 +thing.menu.eesz.512K64.upload.maximum_size=434160 +thing.menu.eesz.512K64.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K64.build.spiffs_start=0x6B000 +thing.menu.eesz.512K64.build.spiffs_end=0x7B000 +thing.menu.eesz.512K64.build.spiffs_blocksize=4096 +thing.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB) +thing.menu.eesz.512K128.build.flash_size=512K +thing.menu.eesz.512K128.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +thing.menu.eesz.512K128.build.spiffs_pagesize=256 +thing.menu.eesz.512K128.upload.maximum_size=368624 +thing.menu.eesz.512K128.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K128.build.spiffs_start=0x5B000 +thing.menu.eesz.512K128.build.spiffs_end=0x7B000 +thing.menu.eesz.512K128.build.spiffs_blocksize=4096 +thing.menu.eesz.512K=512KB (FS:none OTA:~246KB) +thing.menu.eesz.512K.build.flash_size=512K +thing.menu.eesz.512K.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +thing.menu.eesz.512K.build.spiffs_pagesize=256 +thing.menu.eesz.512K.upload.maximum_size=499696 +thing.menu.eesz.512K.build.rfcal_addr=0x7C000 +thing.menu.ip.lm2f=v2 Lower Memory +thing.menu.ip.lm2f.build.lwip_include=lwip2/include +thing.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +thing.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thing.menu.ip.hb2f=v2 Higher Bandwidth +thing.menu.ip.hb2f.build.lwip_include=lwip2/include +thing.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +thing.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thing.menu.ip.lm2n=v2 Lower Memory (no features) +thing.menu.ip.lm2n.build.lwip_include=lwip2/include +thing.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +thing.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thing.menu.ip.hb2n=v2 Higher Bandwidth (no features) +thing.menu.ip.hb2n.build.lwip_include=lwip2/include +thing.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +thing.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thing.menu.ip.lm6f=v2 IPv6 Lower Memory +thing.menu.ip.lm6f.build.lwip_include=lwip2/include +thing.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +thing.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thing.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +thing.menu.ip.hb6f.build.lwip_include=lwip2/include +thing.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +thing.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thing.menu.ip.hb1=v1.4 Higher Bandwidth +thing.menu.ip.hb1.build.lwip_lib=-llwip_gcc +thing.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +thing.menu.ip.src=v1.4 Compile from source +thing.menu.ip.src.build.lwip_lib=-llwip_src +thing.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +thing.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +thing.menu.dbg.Disabled=Disabled +thing.menu.dbg.Disabled.build.debug_port= +thing.menu.dbg.Serial=Serial +thing.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +thing.menu.dbg.Serial1=Serial1 +thing.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +thing.menu.lvl.None____=None +thing.menu.lvl.None____.build.debug_level= +thing.menu.lvl.SSL=SSL +thing.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +thing.menu.lvl.TLS_MEM=TLS_MEM +thing.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +thing.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +thing.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.HTTP_SERVER=HTTP_SERVER +thing.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +thing.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +thing.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +thing.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +thing.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +thing.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.CORE=CORE +thing.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +thing.menu.lvl.WIFI=WIFI +thing.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +thing.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +thing.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +thing.menu.lvl.UPDATER=UPDATER +thing.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +thing.menu.lvl.OTA=OTA +thing.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +thing.menu.lvl.OOM=OOM +thing.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +thing.menu.lvl.MDNS=MDNS +thing.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +thing.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +thing.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +thing.menu.wipe.none=Only Sketch +thing.menu.wipe.none.upload.erase_cmd=version +thing.menu.wipe.sdk=Sketch + WiFi Settings +thing.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +thing.menu.wipe.all=All Flash Contents +thing.menu.wipe.all.upload.erase_cmd=erase_flash +thing.menu.baud.115200=115200 +thing.menu.baud.115200.upload.speed=115200 +thing.menu.baud.57600=57600 +thing.menu.baud.57600.upload.speed=57600 +thing.menu.baud.230400.linux=230400 +thing.menu.baud.230400.macosx=230400 +thing.menu.baud.230400.upload.speed=230400 +thing.menu.baud.256000.windows=256000 +thing.menu.baud.256000.upload.speed=256000 +thing.menu.baud.460800.linux=460800 +thing.menu.baud.460800.macosx=460800 +thing.menu.baud.460800.upload.speed=460800 +thing.menu.baud.512000.windows=512000 +thing.menu.baud.512000.upload.speed=512000 +thing.menu.baud.921600=921600 +thing.menu.baud.921600.upload.speed=921600 +thing.menu.baud.3000000=3000000 +thing.menu.baud.3000000.upload.speed=3000000 + +############################################################## +thingdev.name=SparkFun ESP8266 Thing Dev +thingdev.build.board=ESP8266_THING_DEV +thingdev.build.variant=thing +thingdev.upload.tool=esptool +thingdev.upload.maximum_data_size=81920 +thingdev.upload.wait_for_upload_port=true +thingdev.upload.erase_cmd=version +thingdev.serial.disableDTR=true +thingdev.serial.disableRTS=true +thingdev.build.mcu=esp8266 +thingdev.build.core=esp8266 +thingdev.build.spiffs_pagesize=256 +thingdev.build.debug_port= +thingdev.build.debug_level= +thingdev.menu.xtal.80=80 MHz +thingdev.menu.xtal.80.build.f_cpu=80000000L +thingdev.menu.xtal.160=160 MHz +thingdev.menu.xtal.160.build.f_cpu=160000000L +thingdev.menu.vt.flash=Flash +thingdev.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +thingdev.menu.vt.heap=Heap +thingdev.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +thingdev.menu.vt.iram=IRAM +thingdev.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +thingdev.menu.exception.legacy=Legacy (new can return nullptr) +thingdev.menu.exception.legacy.build.exception_flags=-fno-exceptions +thingdev.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +thingdev.menu.exception.disabled=Disabled (new can abort) +thingdev.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +thingdev.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +thingdev.menu.exception.enabled=Enabled +thingdev.menu.exception.enabled.build.exception_flags=-fexceptions +thingdev.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +thingdev.menu.ssl.all=All SSL ciphers (most compatible) +thingdev.menu.ssl.all.build.sslflags= +thingdev.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +thingdev.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +thingdev.upload.resetmethod=nodemcu +thingdev.build.flash_mode=dio +thingdev.build.flash_flags=-DFLASHMODE_DIO +thingdev.build.flash_freq=40 +thingdev.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB) +thingdev.menu.eesz.512K32.build.flash_size=512K +thingdev.menu.eesz.512K32.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +thingdev.menu.eesz.512K32.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K32.upload.maximum_size=466928 +thingdev.menu.eesz.512K32.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K32.build.spiffs_start=0x73000 +thingdev.menu.eesz.512K32.build.spiffs_end=0x7B000 +thingdev.menu.eesz.512K32.build.spiffs_blocksize=4096 +thingdev.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB) +thingdev.menu.eesz.512K64.build.flash_size=512K +thingdev.menu.eesz.512K64.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +thingdev.menu.eesz.512K64.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K64.upload.maximum_size=434160 +thingdev.menu.eesz.512K64.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K64.build.spiffs_start=0x6B000 +thingdev.menu.eesz.512K64.build.spiffs_end=0x7B000 +thingdev.menu.eesz.512K64.build.spiffs_blocksize=4096 +thingdev.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB) +thingdev.menu.eesz.512K128.build.flash_size=512K +thingdev.menu.eesz.512K128.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +thingdev.menu.eesz.512K128.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K128.upload.maximum_size=368624 +thingdev.menu.eesz.512K128.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K128.build.spiffs_start=0x5B000 +thingdev.menu.eesz.512K128.build.spiffs_end=0x7B000 +thingdev.menu.eesz.512K128.build.spiffs_blocksize=4096 +thingdev.menu.eesz.512K=512KB (FS:none OTA:~246KB) +thingdev.menu.eesz.512K.build.flash_size=512K +thingdev.menu.eesz.512K.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +thingdev.menu.eesz.512K.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K.upload.maximum_size=499696 +thingdev.menu.eesz.512K.build.rfcal_addr=0x7C000 +thingdev.menu.ip.lm2f=v2 Lower Memory +thingdev.menu.ip.lm2f.build.lwip_include=lwip2/include +thingdev.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +thingdev.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thingdev.menu.ip.hb2f=v2 Higher Bandwidth +thingdev.menu.ip.hb2f.build.lwip_include=lwip2/include +thingdev.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +thingdev.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thingdev.menu.ip.lm2n=v2 Lower Memory (no features) +thingdev.menu.ip.lm2n.build.lwip_include=lwip2/include +thingdev.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +thingdev.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thingdev.menu.ip.hb2n=v2 Higher Bandwidth (no features) +thingdev.menu.ip.hb2n.build.lwip_include=lwip2/include +thingdev.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +thingdev.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thingdev.menu.ip.lm6f=v2 IPv6 Lower Memory +thingdev.menu.ip.lm6f.build.lwip_include=lwip2/include +thingdev.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +thingdev.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thingdev.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +thingdev.menu.ip.hb6f.build.lwip_include=lwip2/include +thingdev.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +thingdev.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thingdev.menu.ip.hb1=v1.4 Higher Bandwidth +thingdev.menu.ip.hb1.build.lwip_lib=-llwip_gcc +thingdev.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +thingdev.menu.ip.src=v1.4 Compile from source +thingdev.menu.ip.src.build.lwip_lib=-llwip_src +thingdev.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +thingdev.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +thingdev.menu.dbg.Disabled=Disabled +thingdev.menu.dbg.Disabled.build.debug_port= +thingdev.menu.dbg.Serial=Serial +thingdev.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +thingdev.menu.dbg.Serial1=Serial1 +thingdev.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +thingdev.menu.lvl.None____=None +thingdev.menu.lvl.None____.build.debug_level= +thingdev.menu.lvl.SSL=SSL +thingdev.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +thingdev.menu.lvl.TLS_MEM=TLS_MEM +thingdev.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +thingdev.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +thingdev.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.HTTP_SERVER=HTTP_SERVER +thingdev.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +thingdev.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +thingdev.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +thingdev.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +thingdev.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +thingdev.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.CORE=CORE +thingdev.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +thingdev.menu.lvl.WIFI=WIFI +thingdev.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +thingdev.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +thingdev.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +thingdev.menu.lvl.UPDATER=UPDATER +thingdev.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +thingdev.menu.lvl.OTA=OTA +thingdev.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +thingdev.menu.lvl.OOM=OOM +thingdev.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +thingdev.menu.lvl.MDNS=MDNS +thingdev.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +thingdev.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +thingdev.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +thingdev.menu.wipe.none=Only Sketch +thingdev.menu.wipe.none.upload.erase_cmd=version +thingdev.menu.wipe.sdk=Sketch + WiFi Settings +thingdev.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +thingdev.menu.wipe.all=All Flash Contents +thingdev.menu.wipe.all.upload.erase_cmd=erase_flash +thingdev.menu.baud.115200=115200 +thingdev.menu.baud.115200.upload.speed=115200 +thingdev.menu.baud.57600=57600 +thingdev.menu.baud.57600.upload.speed=57600 +thingdev.menu.baud.230400.linux=230400 +thingdev.menu.baud.230400.macosx=230400 +thingdev.menu.baud.230400.upload.speed=230400 +thingdev.menu.baud.256000.windows=256000 +thingdev.menu.baud.256000.upload.speed=256000 +thingdev.menu.baud.460800.linux=460800 +thingdev.menu.baud.460800.macosx=460800 +thingdev.menu.baud.460800.upload.speed=460800 +thingdev.menu.baud.512000.windows=512000 +thingdev.menu.baud.512000.upload.speed=512000 +thingdev.menu.baud.921600=921600 +thingdev.menu.baud.921600.upload.speed=921600 +thingdev.menu.baud.3000000=3000000 +thingdev.menu.baud.3000000.upload.speed=3000000 + +############################################################## +esp210.name=SweetPea ESP-210 +esp210.build.board=ESP8266_ESP210 +esp210.upload.tool=esptool +esp210.upload.maximum_data_size=81920 +esp210.upload.wait_for_upload_port=true +esp210.upload.erase_cmd=version +esp210.serial.disableDTR=true +esp210.serial.disableRTS=true +esp210.build.mcu=esp8266 +esp210.build.core=esp8266 +esp210.build.variant=generic +esp210.build.spiffs_pagesize=256 +esp210.build.debug_port= +esp210.build.debug_level= +esp210.menu.xtal.80=80 MHz +esp210.menu.xtal.80.build.f_cpu=80000000L +esp210.menu.xtal.160=160 MHz +esp210.menu.xtal.160.build.f_cpu=160000000L +esp210.menu.vt.flash=Flash +esp210.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +esp210.menu.vt.heap=Heap +esp210.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +esp210.menu.vt.iram=IRAM +esp210.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +esp210.menu.exception.legacy=Legacy (new can return nullptr) +esp210.menu.exception.legacy.build.exception_flags=-fno-exceptions +esp210.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +esp210.menu.exception.disabled=Disabled (new can abort) +esp210.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +esp210.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +esp210.menu.exception.enabled=Enabled +esp210.menu.exception.enabled.build.exception_flags=-fexceptions +esp210.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +esp210.menu.ssl.all=All SSL ciphers (most compatible) +esp210.menu.ssl.all.build.sslflags= +esp210.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +esp210.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +esp210.upload.resetmethod=ck +esp210.build.flash_mode=qio +esp210.build.flash_flags=-DFLASHMODE_QIO +esp210.build.flash_freq=40 +esp210.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +esp210.menu.eesz.4M2M.build.flash_size=4M +esp210.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +esp210.menu.eesz.4M2M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M2M.upload.maximum_size=1044464 +esp210.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M2M.build.spiffs_start=0x200000 +esp210.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +esp210.menu.eesz.4M2M.build.spiffs_blocksize=8192 +esp210.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +esp210.menu.eesz.4M3M.build.flash_size=4M +esp210.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +esp210.menu.eesz.4M3M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M3M.upload.maximum_size=1044464 +esp210.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M3M.build.spiffs_start=0x100000 +esp210.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +esp210.menu.eesz.4M3M.build.spiffs_blocksize=8192 +esp210.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +esp210.menu.eesz.4M1M.build.flash_size=4M +esp210.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +esp210.menu.eesz.4M1M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M1M.upload.maximum_size=1044464 +esp210.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M1M.build.spiffs_start=0x300000 +esp210.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +esp210.menu.eesz.4M1M.build.spiffs_blocksize=8192 +esp210.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +esp210.menu.eesz.4M.build.flash_size=4M +esp210.menu.eesz.4M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +esp210.menu.eesz.4M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M.upload.maximum_size=1044464 +esp210.menu.eesz.4M.build.rfcal_addr=0x3FC000 +esp210.menu.ip.lm2f=v2 Lower Memory +esp210.menu.ip.lm2f.build.lwip_include=lwip2/include +esp210.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +esp210.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp210.menu.ip.hb2f=v2 Higher Bandwidth +esp210.menu.ip.hb2f.build.lwip_include=lwip2/include +esp210.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +esp210.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp210.menu.ip.lm2n=v2 Lower Memory (no features) +esp210.menu.ip.lm2n.build.lwip_include=lwip2/include +esp210.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +esp210.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp210.menu.ip.hb2n=v2 Higher Bandwidth (no features) +esp210.menu.ip.hb2n.build.lwip_include=lwip2/include +esp210.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +esp210.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp210.menu.ip.lm6f=v2 IPv6 Lower Memory +esp210.menu.ip.lm6f.build.lwip_include=lwip2/include +esp210.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +esp210.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp210.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +esp210.menu.ip.hb6f.build.lwip_include=lwip2/include +esp210.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +esp210.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp210.menu.ip.hb1=v1.4 Higher Bandwidth +esp210.menu.ip.hb1.build.lwip_lib=-llwip_gcc +esp210.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +esp210.menu.ip.src=v1.4 Compile from source +esp210.menu.ip.src.build.lwip_lib=-llwip_src +esp210.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +esp210.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +esp210.menu.dbg.Disabled=Disabled +esp210.menu.dbg.Disabled.build.debug_port= +esp210.menu.dbg.Serial=Serial +esp210.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +esp210.menu.dbg.Serial1=Serial1 +esp210.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +esp210.menu.lvl.None____=None +esp210.menu.lvl.None____.build.debug_level= +esp210.menu.lvl.SSL=SSL +esp210.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +esp210.menu.lvl.TLS_MEM=TLS_MEM +esp210.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +esp210.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +esp210.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.HTTP_SERVER=HTTP_SERVER +esp210.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +esp210.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +esp210.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +esp210.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +esp210.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +esp210.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.CORE=CORE +esp210.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +esp210.menu.lvl.WIFI=WIFI +esp210.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +esp210.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +esp210.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +esp210.menu.lvl.UPDATER=UPDATER +esp210.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +esp210.menu.lvl.OTA=OTA +esp210.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +esp210.menu.lvl.OOM=OOM +esp210.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +esp210.menu.lvl.MDNS=MDNS +esp210.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +esp210.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +esp210.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +esp210.menu.wipe.none=Only Sketch +esp210.menu.wipe.none.upload.erase_cmd=version +esp210.menu.wipe.sdk=Sketch + WiFi Settings +esp210.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +esp210.menu.wipe.all=All Flash Contents +esp210.menu.wipe.all.upload.erase_cmd=erase_flash +esp210.menu.baud.57600=57600 +esp210.menu.baud.57600.upload.speed=57600 +esp210.menu.baud.115200=115200 +esp210.menu.baud.115200.upload.speed=115200 +esp210.menu.baud.230400.linux=230400 +esp210.menu.baud.230400.macosx=230400 +esp210.menu.baud.230400.upload.speed=230400 +esp210.menu.baud.256000.windows=256000 +esp210.menu.baud.256000.upload.speed=256000 +esp210.menu.baud.460800.linux=460800 +esp210.menu.baud.460800.macosx=460800 +esp210.menu.baud.460800.upload.speed=460800 +esp210.menu.baud.512000.windows=512000 +esp210.menu.baud.512000.upload.speed=512000 +esp210.menu.baud.921600=921600 +esp210.menu.baud.921600.upload.speed=921600 +esp210.menu.baud.3000000=3000000 +esp210.menu.baud.3000000.upload.speed=3000000 + +############################################################## +d1_mini.name=LOLIN(WEMOS) D1 R2 & mini +d1_mini.build.board=ESP8266_WEMOS_D1MINI +d1_mini.build.variant=d1_mini +d1_mini.upload.tool=esptool +d1_mini.upload.maximum_data_size=81920 +d1_mini.upload.wait_for_upload_port=true +d1_mini.upload.erase_cmd=version +d1_mini.serial.disableDTR=true +d1_mini.serial.disableRTS=true +d1_mini.build.mcu=esp8266 +d1_mini.build.core=esp8266 +d1_mini.build.spiffs_pagesize=256 +d1_mini.build.debug_port= +d1_mini.build.debug_level= +d1_mini.menu.xtal.80=80 MHz +d1_mini.menu.xtal.80.build.f_cpu=80000000L +d1_mini.menu.xtal.160=160 MHz +d1_mini.menu.xtal.160.build.f_cpu=160000000L +d1_mini.menu.vt.flash=Flash +d1_mini.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1_mini.menu.vt.heap=Heap +d1_mini.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1_mini.menu.vt.iram=IRAM +d1_mini.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1_mini.menu.exception.legacy=Legacy (new can return nullptr) +d1_mini.menu.exception.legacy.build.exception_flags=-fno-exceptions +d1_mini.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +d1_mini.menu.exception.disabled=Disabled (new can abort) +d1_mini.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +d1_mini.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1_mini.menu.exception.enabled=Enabled +d1_mini.menu.exception.enabled.build.exception_flags=-fexceptions +d1_mini.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1_mini.menu.ssl.all=All SSL ciphers (most compatible) +d1_mini.menu.ssl.all.build.sslflags= +d1_mini.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +d1_mini.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +d1_mini.upload.resetmethod=nodemcu +d1_mini.build.flash_mode=dio +d1_mini.build.flash_flags=-DFLASHMODE_DIO +d1_mini.build.flash_freq=40 +d1_mini.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +d1_mini.menu.eesz.4M2M.build.flash_size=4M +d1_mini.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +d1_mini.menu.eesz.4M2M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M2M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M2M.build.spiffs_start=0x200000 +d1_mini.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +d1_mini.menu.eesz.4M2M.build.spiffs_blocksize=8192 +d1_mini.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +d1_mini.menu.eesz.4M3M.build.flash_size=4M +d1_mini.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +d1_mini.menu.eesz.4M3M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M3M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M3M.build.spiffs_start=0x100000 +d1_mini.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +d1_mini.menu.eesz.4M3M.build.spiffs_blocksize=8192 +d1_mini.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +d1_mini.menu.eesz.4M1M.build.flash_size=4M +d1_mini.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +d1_mini.menu.eesz.4M1M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M1M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M1M.build.spiffs_start=0x300000 +d1_mini.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +d1_mini.menu.eesz.4M1M.build.spiffs_blocksize=8192 +d1_mini.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +d1_mini.menu.eesz.4M.build.flash_size=4M +d1_mini.menu.eesz.4M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +d1_mini.menu.eesz.4M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M.build.rfcal_addr=0x3FC000 +d1_mini.menu.ip.lm2f=v2 Lower Memory +d1_mini.menu.ip.lm2f.build.lwip_include=lwip2/include +d1_mini.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1_mini.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini.menu.ip.hb2f=v2 Higher Bandwidth +d1_mini.menu.ip.hb2f.build.lwip_include=lwip2/include +d1_mini.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1_mini.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini.menu.ip.lm2n=v2 Lower Memory (no features) +d1_mini.menu.ip.lm2n.build.lwip_include=lwip2/include +d1_mini.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1_mini.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1_mini.menu.ip.hb2n.build.lwip_include=lwip2/include +d1_mini.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1_mini.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini.menu.ip.lm6f=v2 IPv6 Lower Memory +d1_mini.menu.ip.lm6f.build.lwip_include=lwip2/include +d1_mini.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1_mini.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1_mini.menu.ip.hb6f.build.lwip_include=lwip2/include +d1_mini.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1_mini.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini.menu.ip.hb1=v1.4 Higher Bandwidth +d1_mini.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1_mini.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini.menu.ip.src=v1.4 Compile from source +d1_mini.menu.ip.src.build.lwip_lib=-llwip_src +d1_mini.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1_mini.menu.dbg.Disabled=Disabled +d1_mini.menu.dbg.Disabled.build.debug_port= +d1_mini.menu.dbg.Serial=Serial +d1_mini.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1_mini.menu.dbg.Serial1=Serial1 +d1_mini.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1_mini.menu.lvl.None____=None +d1_mini.menu.lvl.None____.build.debug_level= +d1_mini.menu.lvl.SSL=SSL +d1_mini.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1_mini.menu.lvl.TLS_MEM=TLS_MEM +d1_mini.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1_mini.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1_mini.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1_mini.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1_mini.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1_mini.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1_mini.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1_mini.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.CORE=CORE +d1_mini.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1_mini.menu.lvl.WIFI=WIFI +d1_mini.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1_mini.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1_mini.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1_mini.menu.lvl.UPDATER=UPDATER +d1_mini.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1_mini.menu.lvl.OTA=OTA +d1_mini.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1_mini.menu.lvl.OOM=OOM +d1_mini.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1_mini.menu.lvl.MDNS=MDNS +d1_mini.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1_mini.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1_mini.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1_mini.menu.wipe.none=Only Sketch +d1_mini.menu.wipe.none.upload.erase_cmd=version +d1_mini.menu.wipe.sdk=Sketch + WiFi Settings +d1_mini.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +d1_mini.menu.wipe.all=All Flash Contents +d1_mini.menu.wipe.all.upload.erase_cmd=erase_flash +d1_mini.menu.baud.921600=921600 +d1_mini.menu.baud.921600.upload.speed=921600 +d1_mini.menu.baud.57600=57600 +d1_mini.menu.baud.57600.upload.speed=57600 +d1_mini.menu.baud.115200=115200 +d1_mini.menu.baud.115200.upload.speed=115200 +d1_mini.menu.baud.230400.linux=230400 +d1_mini.menu.baud.230400.macosx=230400 +d1_mini.menu.baud.230400.upload.speed=230400 +d1_mini.menu.baud.256000.windows=256000 +d1_mini.menu.baud.256000.upload.speed=256000 +d1_mini.menu.baud.460800.linux=460800 +d1_mini.menu.baud.460800.macosx=460800 +d1_mini.menu.baud.460800.upload.speed=460800 +d1_mini.menu.baud.512000.windows=512000 +d1_mini.menu.baud.512000.upload.speed=512000 +d1_mini.menu.baud.3000000=3000000 +d1_mini.menu.baud.3000000.upload.speed=3000000 + +############################################################## +d1_mini_pro.name=LOLIN(WEMOS) D1 mini Pro +d1_mini_pro.build.board=ESP8266_WEMOS_D1MINIPRO +d1_mini_pro.build.variant=d1_mini +d1_mini_pro.upload.tool=esptool +d1_mini_pro.upload.maximum_data_size=81920 +d1_mini_pro.upload.wait_for_upload_port=true +d1_mini_pro.upload.erase_cmd=version +d1_mini_pro.serial.disableDTR=true +d1_mini_pro.serial.disableRTS=true +d1_mini_pro.build.mcu=esp8266 +d1_mini_pro.build.core=esp8266 +d1_mini_pro.build.spiffs_pagesize=256 +d1_mini_pro.build.debug_port= +d1_mini_pro.build.debug_level= +d1_mini_pro.menu.xtal.80=80 MHz +d1_mini_pro.menu.xtal.80.build.f_cpu=80000000L +d1_mini_pro.menu.xtal.160=160 MHz +d1_mini_pro.menu.xtal.160.build.f_cpu=160000000L +d1_mini_pro.menu.vt.flash=Flash +d1_mini_pro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1_mini_pro.menu.vt.heap=Heap +d1_mini_pro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1_mini_pro.menu.vt.iram=IRAM +d1_mini_pro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1_mini_pro.menu.exception.legacy=Legacy (new can return nullptr) +d1_mini_pro.menu.exception.legacy.build.exception_flags=-fno-exceptions +d1_mini_pro.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +d1_mini_pro.menu.exception.disabled=Disabled (new can abort) +d1_mini_pro.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +d1_mini_pro.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1_mini_pro.menu.exception.enabled=Enabled +d1_mini_pro.menu.exception.enabled.build.exception_flags=-fexceptions +d1_mini_pro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1_mini_pro.menu.ssl.all=All SSL ciphers (most compatible) +d1_mini_pro.menu.ssl.all.build.sslflags= +d1_mini_pro.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +d1_mini_pro.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +d1_mini_pro.upload.resetmethod=nodemcu +d1_mini_pro.build.flash_mode=dio +d1_mini_pro.build.flash_flags=-DFLASHMODE_DIO +d1_mini_pro.build.flash_freq=40 +d1_mini_pro.menu.eesz.16M14M=16MB (FS:14MB OTA:~1019KB) +d1_mini_pro.menu.eesz.16M14M.build.flash_size=16M +d1_mini_pro.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 +d1_mini_pro.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld +d1_mini_pro.menu.eesz.16M14M.build.spiffs_pagesize=256 +d1_mini_pro.menu.eesz.16M14M.upload.maximum_size=1044464 +d1_mini_pro.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 +d1_mini_pro.menu.eesz.16M14M.build.spiffs_start=0x200000 +d1_mini_pro.menu.eesz.16M14M.build.spiffs_end=0xFFA000 +d1_mini_pro.menu.eesz.16M14M.build.spiffs_blocksize=8192 +d1_mini_pro.menu.eesz.16M15M=16MB (FS:15MB OTA:~512KB) +d1_mini_pro.menu.eesz.16M15M.build.flash_size=16M +d1_mini_pro.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 +d1_mini_pro.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld +d1_mini_pro.menu.eesz.16M15M.build.spiffs_pagesize=256 +d1_mini_pro.menu.eesz.16M15M.upload.maximum_size=1044464 +d1_mini_pro.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 +d1_mini_pro.menu.eesz.16M15M.build.spiffs_start=0x100000 +d1_mini_pro.menu.eesz.16M15M.build.spiffs_end=0xFFA000 +d1_mini_pro.menu.eesz.16M15M.build.spiffs_blocksize=8192 +d1_mini_pro.menu.ip.lm2f=v2 Lower Memory +d1_mini_pro.menu.ip.lm2f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1_mini_pro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.hb2f=v2 Higher Bandwidth +d1_mini_pro.menu.ip.hb2f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1_mini_pro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.lm2n=v2 Lower Memory (no features) +d1_mini_pro.menu.ip.lm2n.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1_mini_pro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1_mini_pro.menu.ip.hb2n.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1_mini_pro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.lm6f=v2 IPv6 Lower Memory +d1_mini_pro.menu.ip.lm6f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1_mini_pro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_pro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1_mini_pro.menu.ip.hb6f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1_mini_pro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_pro.menu.ip.hb1=v1.4 Higher Bandwidth +d1_mini_pro.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1_mini_pro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_pro.menu.ip.src=v1.4 Compile from source +d1_mini_pro.menu.ip.src.build.lwip_lib=-llwip_src +d1_mini_pro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_pro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1_mini_pro.menu.dbg.Disabled=Disabled +d1_mini_pro.menu.dbg.Disabled.build.debug_port= +d1_mini_pro.menu.dbg.Serial=Serial +d1_mini_pro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1_mini_pro.menu.dbg.Serial1=Serial1 +d1_mini_pro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1_mini_pro.menu.lvl.None____=None +d1_mini_pro.menu.lvl.None____.build.debug_level= +d1_mini_pro.menu.lvl.SSL=SSL +d1_mini_pro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1_mini_pro.menu.lvl.TLS_MEM=TLS_MEM +d1_mini_pro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1_mini_pro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1_mini_pro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1_mini_pro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1_mini_pro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1_mini_pro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.CORE=CORE +d1_mini_pro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1_mini_pro.menu.lvl.WIFI=WIFI +d1_mini_pro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1_mini_pro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1_mini_pro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1_mini_pro.menu.lvl.UPDATER=UPDATER +d1_mini_pro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1_mini_pro.menu.lvl.OTA=OTA +d1_mini_pro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1_mini_pro.menu.lvl.OOM=OOM +d1_mini_pro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1_mini_pro.menu.lvl.MDNS=MDNS +d1_mini_pro.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1_mini_pro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1_mini_pro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1_mini_pro.menu.wipe.none=Only Sketch +d1_mini_pro.menu.wipe.none.upload.erase_cmd=version +d1_mini_pro.menu.wipe.sdk=Sketch + WiFi Settings +d1_mini_pro.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +d1_mini_pro.menu.wipe.all=All Flash Contents +d1_mini_pro.menu.wipe.all.upload.erase_cmd=erase_flash +d1_mini_pro.menu.baud.921600=921600 +d1_mini_pro.menu.baud.921600.upload.speed=921600 +d1_mini_pro.menu.baud.57600=57600 +d1_mini_pro.menu.baud.57600.upload.speed=57600 +d1_mini_pro.menu.baud.115200=115200 +d1_mini_pro.menu.baud.115200.upload.speed=115200 +d1_mini_pro.menu.baud.230400.linux=230400 +d1_mini_pro.menu.baud.230400.macosx=230400 +d1_mini_pro.menu.baud.230400.upload.speed=230400 +d1_mini_pro.menu.baud.256000.windows=256000 +d1_mini_pro.menu.baud.256000.upload.speed=256000 +d1_mini_pro.menu.baud.460800.linux=460800 +d1_mini_pro.menu.baud.460800.macosx=460800 +d1_mini_pro.menu.baud.460800.upload.speed=460800 +d1_mini_pro.menu.baud.512000.windows=512000 +d1_mini_pro.menu.baud.512000.upload.speed=512000 +d1_mini_pro.menu.baud.3000000=3000000 +d1_mini_pro.menu.baud.3000000.upload.speed=3000000 + +############################################################## +d1_mini_lite.name=LOLIN(WEMOS) D1 mini Lite +d1_mini_lite.build.board=ESP8266_WEMOS_D1MINILITE +d1_mini_lite.build.variant=d1_mini +d1_mini_lite.upload.tool=esptool +d1_mini_lite.upload.maximum_data_size=81920 +d1_mini_lite.upload.wait_for_upload_port=true +d1_mini_lite.upload.erase_cmd=version +d1_mini_lite.serial.disableDTR=true +d1_mini_lite.serial.disableRTS=true +d1_mini_lite.build.mcu=esp8266 +d1_mini_lite.build.core=esp8266 +d1_mini_lite.build.spiffs_pagesize=256 +d1_mini_lite.build.debug_port= +d1_mini_lite.build.debug_level= +d1_mini_lite.menu.xtal.80=80 MHz +d1_mini_lite.menu.xtal.80.build.f_cpu=80000000L +d1_mini_lite.menu.xtal.160=160 MHz +d1_mini_lite.menu.xtal.160.build.f_cpu=160000000L +d1_mini_lite.menu.vt.flash=Flash +d1_mini_lite.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1_mini_lite.menu.vt.heap=Heap +d1_mini_lite.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1_mini_lite.menu.vt.iram=IRAM +d1_mini_lite.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1_mini_lite.menu.exception.legacy=Legacy (new can return nullptr) +d1_mini_lite.menu.exception.legacy.build.exception_flags=-fno-exceptions +d1_mini_lite.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +d1_mini_lite.menu.exception.disabled=Disabled (new can abort) +d1_mini_lite.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +d1_mini_lite.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1_mini_lite.menu.exception.enabled=Enabled +d1_mini_lite.menu.exception.enabled.build.exception_flags=-fexceptions +d1_mini_lite.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1_mini_lite.menu.ssl.all=All SSL ciphers (most compatible) +d1_mini_lite.menu.ssl.all.build.sslflags= +d1_mini_lite.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +d1_mini_lite.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +d1_mini_lite.upload.resetmethod=nodemcu +d1_mini_lite.build.flash_mode=dout +d1_mini_lite.build.flash_flags=-DFLASHMODE_DOUT +d1_mini_lite.build.flash_freq=40 +d1_mini_lite.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) +d1_mini_lite.menu.eesz.1M64.build.flash_size=1M +d1_mini_lite.menu.eesz.1M64.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +d1_mini_lite.menu.eesz.1M64.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M64.upload.maximum_size=958448 +d1_mini_lite.menu.eesz.1M64.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M64.build.spiffs_start=0xEB000 +d1_mini_lite.menu.eesz.1M64.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M64.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) +d1_mini_lite.menu.eesz.1M128.build.flash_size=1M +d1_mini_lite.menu.eesz.1M128.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +d1_mini_lite.menu.eesz.1M128.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M128.upload.maximum_size=892912 +d1_mini_lite.menu.eesz.1M128.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M128.build.spiffs_start=0xDB000 +d1_mini_lite.menu.eesz.1M128.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M128.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) +d1_mini_lite.menu.eesz.1M144.build.flash_size=1M +d1_mini_lite.menu.eesz.1M144.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +d1_mini_lite.menu.eesz.1M144.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M144.upload.maximum_size=876528 +d1_mini_lite.menu.eesz.1M144.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M144.build.spiffs_start=0xD7000 +d1_mini_lite.menu.eesz.1M144.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M144.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) +d1_mini_lite.menu.eesz.1M160.build.flash_size=1M +d1_mini_lite.menu.eesz.1M160.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +d1_mini_lite.menu.eesz.1M160.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M160.upload.maximum_size=860144 +d1_mini_lite.menu.eesz.1M160.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M160.build.spiffs_start=0xD3000 +d1_mini_lite.menu.eesz.1M160.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M160.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) +d1_mini_lite.menu.eesz.1M192.build.flash_size=1M +d1_mini_lite.menu.eesz.1M192.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +d1_mini_lite.menu.eesz.1M192.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M192.upload.maximum_size=827376 +d1_mini_lite.menu.eesz.1M192.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M192.build.spiffs_start=0xCB000 +d1_mini_lite.menu.eesz.1M192.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M192.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) +d1_mini_lite.menu.eesz.1M256.build.flash_size=1M +d1_mini_lite.menu.eesz.1M256.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +d1_mini_lite.menu.eesz.1M256.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M256.upload.maximum_size=761840 +d1_mini_lite.menu.eesz.1M256.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M256.build.spiffs_start=0xBB000 +d1_mini_lite.menu.eesz.1M256.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M256.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) +d1_mini_lite.menu.eesz.1M512.build.flash_size=1M +d1_mini_lite.menu.eesz.1M512.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +d1_mini_lite.menu.eesz.1M512.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M512.upload.maximum_size=499696 +d1_mini_lite.menu.eesz.1M512.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M512.build.spiffs_start=0x7B000 +d1_mini_lite.menu.eesz.1M512.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M512.build.spiffs_blocksize=8192 +d1_mini_lite.menu.eesz.1M=1MB (FS:none OTA:~502KB) +d1_mini_lite.menu.eesz.1M.build.flash_size=1M +d1_mini_lite.menu.eesz.1M.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +d1_mini_lite.menu.eesz.1M.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M.upload.maximum_size=1023984 +d1_mini_lite.menu.eesz.1M.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.ip.lm2f=v2 Lower Memory +d1_mini_lite.menu.ip.lm2f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1_mini_lite.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.hb2f=v2 Higher Bandwidth +d1_mini_lite.menu.ip.hb2f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1_mini_lite.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.lm2n=v2 Lower Memory (no features) +d1_mini_lite.menu.ip.lm2n.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1_mini_lite.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1_mini_lite.menu.ip.hb2n.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1_mini_lite.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.lm6f=v2 IPv6 Lower Memory +d1_mini_lite.menu.ip.lm6f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1_mini_lite.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_lite.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1_mini_lite.menu.ip.hb6f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1_mini_lite.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_lite.menu.ip.hb1=v1.4 Higher Bandwidth +d1_mini_lite.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1_mini_lite.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_lite.menu.ip.src=v1.4 Compile from source +d1_mini_lite.menu.ip.src.build.lwip_lib=-llwip_src +d1_mini_lite.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_lite.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1_mini_lite.menu.dbg.Disabled=Disabled +d1_mini_lite.menu.dbg.Disabled.build.debug_port= +d1_mini_lite.menu.dbg.Serial=Serial +d1_mini_lite.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1_mini_lite.menu.dbg.Serial1=Serial1 +d1_mini_lite.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1_mini_lite.menu.lvl.None____=None +d1_mini_lite.menu.lvl.None____.build.debug_level= +d1_mini_lite.menu.lvl.SSL=SSL +d1_mini_lite.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1_mini_lite.menu.lvl.TLS_MEM=TLS_MEM +d1_mini_lite.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1_mini_lite.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1_mini_lite.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1_mini_lite.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1_mini_lite.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1_mini_lite.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.CORE=CORE +d1_mini_lite.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1_mini_lite.menu.lvl.WIFI=WIFI +d1_mini_lite.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1_mini_lite.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1_mini_lite.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1_mini_lite.menu.lvl.UPDATER=UPDATER +d1_mini_lite.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1_mini_lite.menu.lvl.OTA=OTA +d1_mini_lite.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1_mini_lite.menu.lvl.OOM=OOM +d1_mini_lite.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1_mini_lite.menu.lvl.MDNS=MDNS +d1_mini_lite.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1_mini_lite.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1_mini_lite.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1_mini_lite.menu.wipe.none=Only Sketch +d1_mini_lite.menu.wipe.none.upload.erase_cmd=version +d1_mini_lite.menu.wipe.sdk=Sketch + WiFi Settings +d1_mini_lite.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +d1_mini_lite.menu.wipe.all=All Flash Contents +d1_mini_lite.menu.wipe.all.upload.erase_cmd=erase_flash +d1_mini_lite.menu.baud.921600=921600 +d1_mini_lite.menu.baud.921600.upload.speed=921600 +d1_mini_lite.menu.baud.57600=57600 +d1_mini_lite.menu.baud.57600.upload.speed=57600 +d1_mini_lite.menu.baud.115200=115200 +d1_mini_lite.menu.baud.115200.upload.speed=115200 +d1_mini_lite.menu.baud.230400.linux=230400 +d1_mini_lite.menu.baud.230400.macosx=230400 +d1_mini_lite.menu.baud.230400.upload.speed=230400 +d1_mini_lite.menu.baud.256000.windows=256000 +d1_mini_lite.menu.baud.256000.upload.speed=256000 +d1_mini_lite.menu.baud.460800.linux=460800 +d1_mini_lite.menu.baud.460800.macosx=460800 +d1_mini_lite.menu.baud.460800.upload.speed=460800 +d1_mini_lite.menu.baud.512000.windows=512000 +d1_mini_lite.menu.baud.512000.upload.speed=512000 +d1_mini_lite.menu.baud.3000000=3000000 +d1_mini_lite.menu.baud.3000000.upload.speed=3000000 + +############################################################## +d1.name=WeMos D1 R1 +d1.build.board=ESP8266_WEMOS_D1R1 +d1.build.variant=d1 +d1.upload.tool=esptool +d1.upload.maximum_data_size=81920 +d1.upload.wait_for_upload_port=true +d1.upload.erase_cmd=version +d1.serial.disableDTR=true +d1.serial.disableRTS=true +d1.build.mcu=esp8266 +d1.build.core=esp8266 +d1.build.spiffs_pagesize=256 +d1.build.debug_port= +d1.build.debug_level= +d1.menu.xtal.80=80 MHz +d1.menu.xtal.80.build.f_cpu=80000000L +d1.menu.xtal.160=160 MHz +d1.menu.xtal.160.build.f_cpu=160000000L +d1.menu.vt.flash=Flash +d1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1.menu.vt.heap=Heap +d1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1.menu.vt.iram=IRAM +d1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1.menu.exception.legacy=Legacy (new can return nullptr) +d1.menu.exception.legacy.build.exception_flags=-fno-exceptions +d1.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +d1.menu.exception.disabled=Disabled (new can abort) +d1.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +d1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1.menu.exception.enabled=Enabled +d1.menu.exception.enabled.build.exception_flags=-fexceptions +d1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1.menu.ssl.all=All SSL ciphers (most compatible) +d1.menu.ssl.all.build.sslflags= +d1.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +d1.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +d1.upload.resetmethod=nodemcu +d1.build.flash_mode=dio +d1.build.flash_flags=-DFLASHMODE_DIO +d1.build.flash_freq=40 +d1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +d1.menu.eesz.4M2M.build.flash_size=4M +d1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +d1.menu.eesz.4M2M.build.spiffs_pagesize=256 +d1.menu.eesz.4M2M.upload.maximum_size=1044464 +d1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M2M.build.spiffs_start=0x200000 +d1.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +d1.menu.eesz.4M2M.build.spiffs_blocksize=8192 +d1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +d1.menu.eesz.4M3M.build.flash_size=4M +d1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +d1.menu.eesz.4M3M.build.spiffs_pagesize=256 +d1.menu.eesz.4M3M.upload.maximum_size=1044464 +d1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M3M.build.spiffs_start=0x100000 +d1.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +d1.menu.eesz.4M3M.build.spiffs_blocksize=8192 +d1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +d1.menu.eesz.4M1M.build.flash_size=4M +d1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +d1.menu.eesz.4M1M.build.spiffs_pagesize=256 +d1.menu.eesz.4M1M.upload.maximum_size=1044464 +d1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M1M.build.spiffs_start=0x300000 +d1.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +d1.menu.eesz.4M1M.build.spiffs_blocksize=8192 +d1.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +d1.menu.eesz.4M.build.flash_size=4M +d1.menu.eesz.4M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +d1.menu.eesz.4M.build.spiffs_pagesize=256 +d1.menu.eesz.4M.upload.maximum_size=1044464 +d1.menu.eesz.4M.build.rfcal_addr=0x3FC000 +d1.menu.ip.lm2f=v2 Lower Memory +d1.menu.ip.lm2f.build.lwip_include=lwip2/include +d1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1.menu.ip.hb2f=v2 Higher Bandwidth +d1.menu.ip.hb2f.build.lwip_include=lwip2/include +d1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1.menu.ip.lm2n=v2 Lower Memory (no features) +d1.menu.ip.lm2n.build.lwip_include=lwip2/include +d1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1.menu.ip.hb2n.build.lwip_include=lwip2/include +d1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1.menu.ip.lm6f=v2 IPv6 Lower Memory +d1.menu.ip.lm6f.build.lwip_include=lwip2/include +d1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1.menu.ip.hb6f.build.lwip_include=lwip2/include +d1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1.menu.ip.hb1=v1.4 Higher Bandwidth +d1.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1.menu.ip.src=v1.4 Compile from source +d1.menu.ip.src.build.lwip_lib=-llwip_src +d1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1.menu.dbg.Disabled=Disabled +d1.menu.dbg.Disabled.build.debug_port= +d1.menu.dbg.Serial=Serial +d1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1.menu.dbg.Serial1=Serial1 +d1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1.menu.lvl.None____=None +d1.menu.lvl.None____.build.debug_level= +d1.menu.lvl.SSL=SSL +d1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1.menu.lvl.TLS_MEM=TLS_MEM +d1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.CORE=CORE +d1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1.menu.lvl.WIFI=WIFI +d1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1.menu.lvl.UPDATER=UPDATER +d1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1.menu.lvl.OTA=OTA +d1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1.menu.lvl.OOM=OOM +d1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1.menu.lvl.MDNS=MDNS +d1.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1.menu.wipe.none=Only Sketch +d1.menu.wipe.none.upload.erase_cmd=version +d1.menu.wipe.sdk=Sketch + WiFi Settings +d1.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +d1.menu.wipe.all=All Flash Contents +d1.menu.wipe.all.upload.erase_cmd=erase_flash +d1.menu.baud.921600=921600 +d1.menu.baud.921600.upload.speed=921600 +d1.menu.baud.57600=57600 +d1.menu.baud.57600.upload.speed=57600 +d1.menu.baud.115200=115200 +d1.menu.baud.115200.upload.speed=115200 +d1.menu.baud.230400.linux=230400 +d1.menu.baud.230400.macosx=230400 +d1.menu.baud.230400.upload.speed=230400 +d1.menu.baud.256000.windows=256000 +d1.menu.baud.256000.upload.speed=256000 +d1.menu.baud.460800.linux=460800 +d1.menu.baud.460800.macosx=460800 +d1.menu.baud.460800.upload.speed=460800 +d1.menu.baud.512000.windows=512000 +d1.menu.baud.512000.upload.speed=512000 +d1.menu.baud.3000000=3000000 +d1.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espino.name=ESPino (ESP-12 Module) +espino.build.board=ESP8266_ESP12 +espino.build.variant=espino +espino.upload.tool=esptool +espino.upload.maximum_data_size=81920 +espino.upload.wait_for_upload_port=true +espino.upload.erase_cmd=version +espino.serial.disableDTR=true +espino.serial.disableRTS=true +espino.build.mcu=esp8266 +espino.build.core=esp8266 +espino.build.spiffs_pagesize=256 +espino.build.debug_port= +espino.build.debug_level= +espino.menu.xtal.80=80 MHz +espino.menu.xtal.80.build.f_cpu=80000000L +espino.menu.xtal.160=160 MHz +espino.menu.xtal.160.build.f_cpu=160000000L +espino.menu.vt.flash=Flash +espino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espino.menu.vt.heap=Heap +espino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espino.menu.vt.iram=IRAM +espino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espino.menu.exception.legacy=Legacy (new can return nullptr) +espino.menu.exception.legacy.build.exception_flags=-fno-exceptions +espino.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espino.menu.exception.disabled=Disabled (new can abort) +espino.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espino.menu.exception.enabled=Enabled +espino.menu.exception.enabled.build.exception_flags=-fexceptions +espino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espino.menu.ssl.all=All SSL ciphers (most compatible) +espino.menu.ssl.all.build.sslflags= +espino.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espino.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espino.menu.ResetMethod.ck=ck +espino.menu.ResetMethod.ck.upload.resetmethod=ck +espino.menu.ResetMethod.nodemcu=nodemcu +espino.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu +espino.build.flash_mode=qio +espino.build.flash_flags=-DFLASHMODE_QIO +espino.build.flash_freq=40 +espino.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +espino.menu.eesz.4M2M.build.flash_size=4M +espino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espino.menu.eesz.4M2M.build.spiffs_pagesize=256 +espino.menu.eesz.4M2M.upload.maximum_size=1044464 +espino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M2M.build.spiffs_start=0x200000 +espino.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +espino.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espino.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +espino.menu.eesz.4M3M.build.flash_size=4M +espino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espino.menu.eesz.4M3M.build.spiffs_pagesize=256 +espino.menu.eesz.4M3M.upload.maximum_size=1044464 +espino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M3M.build.spiffs_start=0x100000 +espino.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +espino.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espino.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +espino.menu.eesz.4M1M.build.flash_size=4M +espino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espino.menu.eesz.4M1M.build.spiffs_pagesize=256 +espino.menu.eesz.4M1M.upload.maximum_size=1044464 +espino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M1M.build.spiffs_start=0x300000 +espino.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +espino.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espino.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +espino.menu.eesz.4M.build.flash_size=4M +espino.menu.eesz.4M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espino.menu.eesz.4M.build.spiffs_pagesize=256 +espino.menu.eesz.4M.upload.maximum_size=1044464 +espino.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espino.menu.ip.lm2f=v2 Lower Memory +espino.menu.ip.lm2f.build.lwip_include=lwip2/include +espino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espino.menu.ip.hb2f=v2 Higher Bandwidth +espino.menu.ip.hb2f.build.lwip_include=lwip2/include +espino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espino.menu.ip.lm2n=v2 Lower Memory (no features) +espino.menu.ip.lm2n.build.lwip_include=lwip2/include +espino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espino.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espino.menu.ip.hb2n.build.lwip_include=lwip2/include +espino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espino.menu.ip.lm6f=v2 IPv6 Lower Memory +espino.menu.ip.lm6f.build.lwip_include=lwip2/include +espino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espino.menu.ip.hb6f.build.lwip_include=lwip2/include +espino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espino.menu.ip.hb1=v1.4 Higher Bandwidth +espino.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espino.menu.ip.src=v1.4 Compile from source +espino.menu.ip.src.build.lwip_lib=-llwip_src +espino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espino.menu.dbg.Disabled=Disabled +espino.menu.dbg.Disabled.build.debug_port= +espino.menu.dbg.Serial=Serial +espino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espino.menu.dbg.Serial1=Serial1 +espino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espino.menu.lvl.None____=None +espino.menu.lvl.None____.build.debug_level= +espino.menu.lvl.SSL=SSL +espino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espino.menu.lvl.TLS_MEM=TLS_MEM +espino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.HTTP_SERVER=HTTP_SERVER +espino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.CORE=CORE +espino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espino.menu.lvl.WIFI=WIFI +espino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espino.menu.lvl.UPDATER=UPDATER +espino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espino.menu.lvl.OTA=OTA +espino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espino.menu.lvl.OOM=OOM +espino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espino.menu.lvl.MDNS=MDNS +espino.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espino.menu.wipe.none=Only Sketch +espino.menu.wipe.none.upload.erase_cmd=version +espino.menu.wipe.sdk=Sketch + WiFi Settings +espino.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espino.menu.wipe.all=All Flash Contents +espino.menu.wipe.all.upload.erase_cmd=erase_flash +espino.menu.baud.115200=115200 +espino.menu.baud.115200.upload.speed=115200 +espino.menu.baud.57600=57600 +espino.menu.baud.57600.upload.speed=57600 +espino.menu.baud.230400.linux=230400 +espino.menu.baud.230400.macosx=230400 +espino.menu.baud.230400.upload.speed=230400 +espino.menu.baud.256000.windows=256000 +espino.menu.baud.256000.upload.speed=256000 +espino.menu.baud.460800.linux=460800 +espino.menu.baud.460800.macosx=460800 +espino.menu.baud.460800.upload.speed=460800 +espino.menu.baud.512000.windows=512000 +espino.menu.baud.512000.upload.speed=512000 +espino.menu.baud.921600=921600 +espino.menu.baud.921600.upload.speed=921600 +espino.menu.baud.3000000=3000000 +espino.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espinotee.name=ThaiEasyElec's ESPino +espinotee.build.board=ESP8266_ESP13 +espinotee.build.variant=espinotee +espinotee.upload.tool=esptool +espinotee.upload.maximum_data_size=81920 +espinotee.upload.wait_for_upload_port=true +espinotee.upload.erase_cmd=version +espinotee.serial.disableDTR=true +espinotee.serial.disableRTS=true +espinotee.build.mcu=esp8266 +espinotee.build.core=esp8266 +espinotee.build.spiffs_pagesize=256 +espinotee.build.debug_port= +espinotee.build.debug_level= +espinotee.menu.xtal.80=80 MHz +espinotee.menu.xtal.80.build.f_cpu=80000000L +espinotee.menu.xtal.160=160 MHz +espinotee.menu.xtal.160.build.f_cpu=160000000L +espinotee.menu.vt.flash=Flash +espinotee.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espinotee.menu.vt.heap=Heap +espinotee.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espinotee.menu.vt.iram=IRAM +espinotee.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espinotee.menu.exception.legacy=Legacy (new can return nullptr) +espinotee.menu.exception.legacy.build.exception_flags=-fno-exceptions +espinotee.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espinotee.menu.exception.disabled=Disabled (new can abort) +espinotee.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espinotee.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espinotee.menu.exception.enabled=Enabled +espinotee.menu.exception.enabled.build.exception_flags=-fexceptions +espinotee.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espinotee.menu.ssl.all=All SSL ciphers (most compatible) +espinotee.menu.ssl.all.build.sslflags= +espinotee.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espinotee.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espinotee.upload.resetmethod=nodemcu +espinotee.build.flash_mode=qio +espinotee.build.flash_flags=-DFLASHMODE_QIO +espinotee.build.flash_freq=40 +espinotee.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +espinotee.menu.eesz.4M2M.build.flash_size=4M +espinotee.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espinotee.menu.eesz.4M2M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M2M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M2M.build.spiffs_start=0x200000 +espinotee.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +espinotee.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espinotee.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +espinotee.menu.eesz.4M3M.build.flash_size=4M +espinotee.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espinotee.menu.eesz.4M3M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M3M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M3M.build.spiffs_start=0x100000 +espinotee.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +espinotee.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espinotee.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +espinotee.menu.eesz.4M1M.build.flash_size=4M +espinotee.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espinotee.menu.eesz.4M1M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M1M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M1M.build.spiffs_start=0x300000 +espinotee.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +espinotee.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espinotee.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +espinotee.menu.eesz.4M.build.flash_size=4M +espinotee.menu.eesz.4M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espinotee.menu.eesz.4M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espinotee.menu.ip.lm2f=v2 Lower Memory +espinotee.menu.ip.lm2f.build.lwip_include=lwip2/include +espinotee.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espinotee.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espinotee.menu.ip.hb2f=v2 Higher Bandwidth +espinotee.menu.ip.hb2f.build.lwip_include=lwip2/include +espinotee.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espinotee.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espinotee.menu.ip.lm2n=v2 Lower Memory (no features) +espinotee.menu.ip.lm2n.build.lwip_include=lwip2/include +espinotee.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espinotee.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espinotee.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espinotee.menu.ip.hb2n.build.lwip_include=lwip2/include +espinotee.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espinotee.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espinotee.menu.ip.lm6f=v2 IPv6 Lower Memory +espinotee.menu.ip.lm6f.build.lwip_include=lwip2/include +espinotee.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espinotee.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espinotee.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espinotee.menu.ip.hb6f.build.lwip_include=lwip2/include +espinotee.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espinotee.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espinotee.menu.ip.hb1=v1.4 Higher Bandwidth +espinotee.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espinotee.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espinotee.menu.ip.src=v1.4 Compile from source +espinotee.menu.ip.src.build.lwip_lib=-llwip_src +espinotee.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espinotee.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espinotee.menu.dbg.Disabled=Disabled +espinotee.menu.dbg.Disabled.build.debug_port= +espinotee.menu.dbg.Serial=Serial +espinotee.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espinotee.menu.dbg.Serial1=Serial1 +espinotee.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espinotee.menu.lvl.None____=None +espinotee.menu.lvl.None____.build.debug_level= +espinotee.menu.lvl.SSL=SSL +espinotee.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espinotee.menu.lvl.TLS_MEM=TLS_MEM +espinotee.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espinotee.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espinotee.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.HTTP_SERVER=HTTP_SERVER +espinotee.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espinotee.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espinotee.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espinotee.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espinotee.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espinotee.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.CORE=CORE +espinotee.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espinotee.menu.lvl.WIFI=WIFI +espinotee.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espinotee.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espinotee.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espinotee.menu.lvl.UPDATER=UPDATER +espinotee.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espinotee.menu.lvl.OTA=OTA +espinotee.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espinotee.menu.lvl.OOM=OOM +espinotee.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espinotee.menu.lvl.MDNS=MDNS +espinotee.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espinotee.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espinotee.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espinotee.menu.wipe.none=Only Sketch +espinotee.menu.wipe.none.upload.erase_cmd=version +espinotee.menu.wipe.sdk=Sketch + WiFi Settings +espinotee.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espinotee.menu.wipe.all=All Flash Contents +espinotee.menu.wipe.all.upload.erase_cmd=erase_flash +espinotee.menu.baud.115200=115200 +espinotee.menu.baud.115200.upload.speed=115200 +espinotee.menu.baud.57600=57600 +espinotee.menu.baud.57600.upload.speed=57600 +espinotee.menu.baud.230400.linux=230400 +espinotee.menu.baud.230400.macosx=230400 +espinotee.menu.baud.230400.upload.speed=230400 +espinotee.menu.baud.256000.windows=256000 +espinotee.menu.baud.256000.upload.speed=256000 +espinotee.menu.baud.460800.linux=460800 +espinotee.menu.baud.460800.macosx=460800 +espinotee.menu.baud.460800.upload.speed=460800 +espinotee.menu.baud.512000.windows=512000 +espinotee.menu.baud.512000.upload.speed=512000 +espinotee.menu.baud.921600=921600 +espinotee.menu.baud.921600.upload.speed=921600 +espinotee.menu.baud.3000000=3000000 +espinotee.menu.baud.3000000.upload.speed=3000000 + +############################################################## +wifinfo.name=WifInfo +wifinfo.build.board=WIFINFO +wifinfo.build.variant=wifinfo +wifinfo.menu.ESPModule.ESP07192=ESP07 (1M/192K SPIFFS) +wifinfo.menu.ESPModule.ESP07192.build.board=ESP8266_ESP07 +wifinfo.menu.ESPModule.ESP07192.build.flash_ld=eagle.flash.1m192.ld +wifinfo.menu.ESPModule.ESP07192.build.flash_size=1M +wifinfo.menu.ESPModule.ESP07192.build.spiffs_blocksize=4096 +wifinfo.menu.ESPModule.ESP07192.build.spiffs_end=0xFB000 +wifinfo.menu.ESPModule.ESP07192.build.spiffs_start=0xCB000 +wifinfo.menu.ESPModule.ESP07192.upload.maximum_size=827376 +wifinfo.menu.ESPModule.ESP12=ESP12 (4M/1M SPIFFS) +wifinfo.menu.ESPModule.ESP12.build.board=ESP8266_ESP12 +wifinfo.menu.ESPModule.ESP12.build.flash_ld=eagle.flash.4m1m.ld +wifinfo.menu.ESPModule.ESP12.build.flash_size=4M +wifinfo.menu.ESPModule.ESP12.build.spiffs_blocksize=8192 +wifinfo.menu.ESPModule.ESP12.build.spiffs_end=0x3FB000 +wifinfo.menu.ESPModule.ESP12.build.spiffs_pagesize=256 +wifinfo.menu.ESPModule.ESP12.build.spiffs_start=0x300000 +wifinfo.menu.ESPModule.ESP12.upload.maximum_size=1044464 +wifinfo.upload.tool=esptool +wifinfo.upload.maximum_data_size=81920 +wifinfo.upload.wait_for_upload_port=true +wifinfo.upload.erase_cmd=version +wifinfo.serial.disableDTR=true +wifinfo.serial.disableRTS=true +wifinfo.build.mcu=esp8266 +wifinfo.build.core=esp8266 +wifinfo.build.spiffs_pagesize=256 +wifinfo.build.debug_port= +wifinfo.build.debug_level= +wifinfo.menu.xtal.80=80 MHz +wifinfo.menu.xtal.80.build.f_cpu=80000000L +wifinfo.menu.xtal.160=160 MHz +wifinfo.menu.xtal.160.build.f_cpu=160000000L +wifinfo.menu.vt.flash=Flash +wifinfo.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wifinfo.menu.vt.heap=Heap +wifinfo.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wifinfo.menu.vt.iram=IRAM +wifinfo.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wifinfo.menu.exception.legacy=Legacy (new can return nullptr) +wifinfo.menu.exception.legacy.build.exception_flags=-fno-exceptions +wifinfo.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +wifinfo.menu.exception.disabled=Disabled (new can abort) +wifinfo.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +wifinfo.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wifinfo.menu.exception.enabled=Enabled +wifinfo.menu.exception.enabled.build.exception_flags=-fexceptions +wifinfo.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wifinfo.menu.ssl.all=All SSL ciphers (most compatible) +wifinfo.menu.ssl.all.build.sslflags= +wifinfo.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +wifinfo.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +wifinfo.upload.resetmethod=nodemcu +wifinfo.build.flash_mode=qio +wifinfo.build.flash_flags=-DFLASHMODE_QIO +wifinfo.menu.FlashFreq.40=40MHz +wifinfo.menu.FlashFreq.40.build.flash_freq=40 +wifinfo.menu.FlashFreq.80=80MHz +wifinfo.menu.FlashFreq.80.build.flash_freq=80 +wifinfo.menu.FlashFreq.20=20MHz +wifinfo.menu.FlashFreq.20.build.flash_freq=20 +wifinfo.menu.FlashFreq.26=26MHz +wifinfo.menu.FlashFreq.26.build.flash_freq=26 +wifinfo.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) +wifinfo.menu.eesz.1M64.build.flash_size=1M +wifinfo.menu.eesz.1M64.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +wifinfo.menu.eesz.1M64.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M64.upload.maximum_size=958448 +wifinfo.menu.eesz.1M64.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M64.build.spiffs_start=0xEB000 +wifinfo.menu.eesz.1M64.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M64.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) +wifinfo.menu.eesz.1M128.build.flash_size=1M +wifinfo.menu.eesz.1M128.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +wifinfo.menu.eesz.1M128.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M128.upload.maximum_size=892912 +wifinfo.menu.eesz.1M128.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M128.build.spiffs_start=0xDB000 +wifinfo.menu.eesz.1M128.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M128.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) +wifinfo.menu.eesz.1M144.build.flash_size=1M +wifinfo.menu.eesz.1M144.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +wifinfo.menu.eesz.1M144.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M144.upload.maximum_size=876528 +wifinfo.menu.eesz.1M144.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M144.build.spiffs_start=0xD7000 +wifinfo.menu.eesz.1M144.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M144.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) +wifinfo.menu.eesz.1M160.build.flash_size=1M +wifinfo.menu.eesz.1M160.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +wifinfo.menu.eesz.1M160.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M160.upload.maximum_size=860144 +wifinfo.menu.eesz.1M160.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M160.build.spiffs_start=0xD3000 +wifinfo.menu.eesz.1M160.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M160.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) +wifinfo.menu.eesz.1M192.build.flash_size=1M +wifinfo.menu.eesz.1M192.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +wifinfo.menu.eesz.1M192.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M192.upload.maximum_size=827376 +wifinfo.menu.eesz.1M192.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M192.build.spiffs_start=0xCB000 +wifinfo.menu.eesz.1M192.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M192.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) +wifinfo.menu.eesz.1M256.build.flash_size=1M +wifinfo.menu.eesz.1M256.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +wifinfo.menu.eesz.1M256.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M256.upload.maximum_size=761840 +wifinfo.menu.eesz.1M256.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M256.build.spiffs_start=0xBB000 +wifinfo.menu.eesz.1M256.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M256.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) +wifinfo.menu.eesz.1M512.build.flash_size=1M +wifinfo.menu.eesz.1M512.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +wifinfo.menu.eesz.1M512.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M512.upload.maximum_size=499696 +wifinfo.menu.eesz.1M512.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M512.build.spiffs_start=0x7B000 +wifinfo.menu.eesz.1M512.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M512.build.spiffs_blocksize=8192 +wifinfo.menu.eesz.1M=1MB (FS:none OTA:~502KB) +wifinfo.menu.eesz.1M.build.flash_size=1M +wifinfo.menu.eesz.1M.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +wifinfo.menu.eesz.1M.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M.upload.maximum_size=1023984 +wifinfo.menu.eesz.1M.build.rfcal_addr=0xFC000 +wifinfo.menu.ip.lm2f=v2 Lower Memory +wifinfo.menu.ip.lm2f.build.lwip_include=lwip2/include +wifinfo.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wifinfo.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifinfo.menu.ip.hb2f=v2 Higher Bandwidth +wifinfo.menu.ip.hb2f.build.lwip_include=lwip2/include +wifinfo.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wifinfo.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifinfo.menu.ip.lm2n=v2 Lower Memory (no features) +wifinfo.menu.ip.lm2n.build.lwip_include=lwip2/include +wifinfo.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wifinfo.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifinfo.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wifinfo.menu.ip.hb2n.build.lwip_include=lwip2/include +wifinfo.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wifinfo.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifinfo.menu.ip.lm6f=v2 IPv6 Lower Memory +wifinfo.menu.ip.lm6f.build.lwip_include=lwip2/include +wifinfo.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wifinfo.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifinfo.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wifinfo.menu.ip.hb6f.build.lwip_include=lwip2/include +wifinfo.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wifinfo.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifinfo.menu.ip.hb1=v1.4 Higher Bandwidth +wifinfo.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wifinfo.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wifinfo.menu.ip.src=v1.4 Compile from source +wifinfo.menu.ip.src.build.lwip_lib=-llwip_src +wifinfo.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wifinfo.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wifinfo.menu.dbg.Disabled=Disabled +wifinfo.menu.dbg.Disabled.build.debug_port= +wifinfo.menu.dbg.Serial=Serial +wifinfo.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wifinfo.menu.dbg.Serial1=Serial1 +wifinfo.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wifinfo.menu.lvl.None____=None +wifinfo.menu.lvl.None____.build.debug_level= +wifinfo.menu.lvl.SSL=SSL +wifinfo.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wifinfo.menu.lvl.TLS_MEM=TLS_MEM +wifinfo.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wifinfo.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wifinfo.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.HTTP_SERVER=HTTP_SERVER +wifinfo.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wifinfo.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wifinfo.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wifinfo.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wifinfo.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.CORE=CORE +wifinfo.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wifinfo.menu.lvl.WIFI=WIFI +wifinfo.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wifinfo.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wifinfo.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wifinfo.menu.lvl.UPDATER=UPDATER +wifinfo.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wifinfo.menu.lvl.OTA=OTA +wifinfo.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wifinfo.menu.lvl.OOM=OOM +wifinfo.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wifinfo.menu.lvl.MDNS=MDNS +wifinfo.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wifinfo.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wifinfo.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wifinfo.menu.wipe.none=Only Sketch +wifinfo.menu.wipe.none.upload.erase_cmd=version +wifinfo.menu.wipe.sdk=Sketch + WiFi Settings +wifinfo.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +wifinfo.menu.wipe.all=All Flash Contents +wifinfo.menu.wipe.all.upload.erase_cmd=erase_flash +wifinfo.menu.baud.115200=115200 +wifinfo.menu.baud.115200.upload.speed=115200 +wifinfo.menu.baud.57600=57600 +wifinfo.menu.baud.57600.upload.speed=57600 +wifinfo.menu.baud.230400.linux=230400 +wifinfo.menu.baud.230400.macosx=230400 +wifinfo.menu.baud.230400.upload.speed=230400 +wifinfo.menu.baud.256000.windows=256000 +wifinfo.menu.baud.256000.upload.speed=256000 +wifinfo.menu.baud.460800.linux=460800 +wifinfo.menu.baud.460800.macosx=460800 +wifinfo.menu.baud.460800.upload.speed=460800 +wifinfo.menu.baud.512000.windows=512000 +wifinfo.menu.baud.512000.upload.speed=512000 +wifinfo.menu.baud.921600=921600 +wifinfo.menu.baud.921600.upload.speed=921600 +wifinfo.menu.baud.3000000=3000000 +wifinfo.menu.baud.3000000.upload.speed=3000000 + +############################################################## +arduino-esp8266.name=Arduino +arduino-esp8266.build.board=ESP8266_ARDUINO +arduino-esp8266.menu.BoardModel.primo=Primo +arduino-esp8266.menu.BoardModel.primo.build.board=ESP8266_ARDUINO_PRIMO +arduino-esp8266.menu.BoardModel.primo.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +arduino-esp8266.menu.BoardModel.primo.build.variant=arduino_spi +arduino-esp8266.menu.BoardModel.starottodeved=Star OTTO +arduino-esp8266.menu.BoardModel.starottodeved.build.board=ESP8266_ARDUINO_STAR_OTTO +arduino-esp8266.menu.BoardModel.starottodeved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +arduino-esp8266.menu.BoardModel.starottodeved.build.variant=arduino_uart +arduino-esp8266.menu.BoardModel.unowifideved=Uno WiFi +arduino-esp8266.menu.BoardModel.unowifideved.build.board=ESP8266_ARDUINO_UNOWIFI +arduino-esp8266.menu.BoardModel.unowifideved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +arduino-esp8266.menu.BoardModel.unowifideved.build.variant=arduino_uart +arduino-esp8266.upload.tool=esptool +arduino-esp8266.upload.maximum_data_size=81920 +arduino-esp8266.upload.wait_for_upload_port=true +arduino-esp8266.upload.erase_cmd=version +arduino-esp8266.serial.disableDTR=true +arduino-esp8266.serial.disableRTS=true +arduino-esp8266.build.mcu=esp8266 +arduino-esp8266.build.core=esp8266 +arduino-esp8266.build.variant=generic +arduino-esp8266.build.spiffs_pagesize=256 +arduino-esp8266.build.debug_port= +arduino-esp8266.build.debug_level= +arduino-esp8266.menu.xtal.80=80 MHz +arduino-esp8266.menu.xtal.80.build.f_cpu=80000000L +arduino-esp8266.menu.xtal.160=160 MHz +arduino-esp8266.menu.xtal.160.build.f_cpu=160000000L +arduino-esp8266.menu.vt.flash=Flash +arduino-esp8266.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +arduino-esp8266.menu.vt.heap=Heap +arduino-esp8266.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +arduino-esp8266.menu.vt.iram=IRAM +arduino-esp8266.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +arduino-esp8266.menu.exception.legacy=Legacy (new can return nullptr) +arduino-esp8266.menu.exception.legacy.build.exception_flags=-fno-exceptions +arduino-esp8266.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +arduino-esp8266.menu.exception.disabled=Disabled (new can abort) +arduino-esp8266.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +arduino-esp8266.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +arduino-esp8266.menu.exception.enabled=Enabled +arduino-esp8266.menu.exception.enabled.build.exception_flags=-fexceptions +arduino-esp8266.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +arduino-esp8266.menu.ssl.all=All SSL ciphers (most compatible) +arduino-esp8266.menu.ssl.all.build.sslflags= +arduino-esp8266.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +arduino-esp8266.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +arduino-esp8266.upload.resetmethod=ck +arduino-esp8266.build.flash_mode=qio +arduino-esp8266.build.flash_flags=-DFLASHMODE_QIO +arduino-esp8266.build.flash_freq=40 +arduino-esp8266.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +arduino-esp8266.menu.eesz.4M2M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +arduino-esp8266.menu.eesz.4M2M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M2M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M2M.build.spiffs_start=0x200000 +arduino-esp8266.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +arduino-esp8266.menu.eesz.4M2M.build.spiffs_blocksize=8192 +arduino-esp8266.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +arduino-esp8266.menu.eesz.4M3M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +arduino-esp8266.menu.eesz.4M3M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M3M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M3M.build.spiffs_start=0x100000 +arduino-esp8266.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +arduino-esp8266.menu.eesz.4M3M.build.spiffs_blocksize=8192 +arduino-esp8266.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +arduino-esp8266.menu.eesz.4M1M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +arduino-esp8266.menu.eesz.4M1M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M1M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M1M.build.spiffs_start=0x300000 +arduino-esp8266.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +arduino-esp8266.menu.eesz.4M1M.build.spiffs_blocksize=8192 +arduino-esp8266.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +arduino-esp8266.menu.eesz.4M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +arduino-esp8266.menu.eesz.4M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.ip.lm2f=v2 Lower Memory +arduino-esp8266.menu.ip.lm2f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +arduino-esp8266.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.hb2f=v2 Higher Bandwidth +arduino-esp8266.menu.ip.hb2f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +arduino-esp8266.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.lm2n=v2 Lower Memory (no features) +arduino-esp8266.menu.ip.lm2n.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +arduino-esp8266.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.hb2n=v2 Higher Bandwidth (no features) +arduino-esp8266.menu.ip.hb2n.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +arduino-esp8266.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.lm6f=v2 IPv6 Lower Memory +arduino-esp8266.menu.ip.lm6f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +arduino-esp8266.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +arduino-esp8266.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +arduino-esp8266.menu.ip.hb6f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +arduino-esp8266.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +arduino-esp8266.menu.ip.hb1=v1.4 Higher Bandwidth +arduino-esp8266.menu.ip.hb1.build.lwip_lib=-llwip_gcc +arduino-esp8266.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +arduino-esp8266.menu.ip.src=v1.4 Compile from source +arduino-esp8266.menu.ip.src.build.lwip_lib=-llwip_src +arduino-esp8266.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +arduino-esp8266.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +arduino-esp8266.menu.dbg.Disabled=Disabled +arduino-esp8266.menu.dbg.Disabled.build.debug_port= +arduino-esp8266.menu.dbg.Serial=Serial +arduino-esp8266.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +arduino-esp8266.menu.dbg.Serial1=Serial1 +arduino-esp8266.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +arduino-esp8266.menu.lvl.None____=None +arduino-esp8266.menu.lvl.None____.build.debug_level= +arduino-esp8266.menu.lvl.SSL=SSL +arduino-esp8266.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +arduino-esp8266.menu.lvl.TLS_MEM=TLS_MEM +arduino-esp8266.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +arduino-esp8266.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +arduino-esp8266.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.HTTP_SERVER=HTTP_SERVER +arduino-esp8266.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +arduino-esp8266.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +arduino-esp8266.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.CORE=CORE +arduino-esp8266.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +arduino-esp8266.menu.lvl.WIFI=WIFI +arduino-esp8266.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +arduino-esp8266.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +arduino-esp8266.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +arduino-esp8266.menu.lvl.UPDATER=UPDATER +arduino-esp8266.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +arduino-esp8266.menu.lvl.OTA=OTA +arduino-esp8266.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +arduino-esp8266.menu.lvl.OOM=OOM +arduino-esp8266.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +arduino-esp8266.menu.lvl.MDNS=MDNS +arduino-esp8266.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +arduino-esp8266.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +arduino-esp8266.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +arduino-esp8266.menu.wipe.none=Only Sketch +arduino-esp8266.menu.wipe.none.upload.erase_cmd=version +arduino-esp8266.menu.wipe.sdk=Sketch + WiFi Settings +arduino-esp8266.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +arduino-esp8266.menu.wipe.all=All Flash Contents +arduino-esp8266.menu.wipe.all.upload.erase_cmd=erase_flash +arduino-esp8266.menu.baud.115200=115200 +arduino-esp8266.menu.baud.115200.upload.speed=115200 +arduino-esp8266.menu.baud.57600=57600 +arduino-esp8266.menu.baud.57600.upload.speed=57600 +arduino-esp8266.menu.baud.230400.linux=230400 +arduino-esp8266.menu.baud.230400.macosx=230400 +arduino-esp8266.menu.baud.230400.upload.speed=230400 +arduino-esp8266.menu.baud.256000.windows=256000 +arduino-esp8266.menu.baud.256000.upload.speed=256000 +arduino-esp8266.menu.baud.460800.linux=460800 +arduino-esp8266.menu.baud.460800.macosx=460800 +arduino-esp8266.menu.baud.460800.upload.speed=460800 +arduino-esp8266.menu.baud.512000.windows=512000 +arduino-esp8266.menu.baud.512000.upload.speed=512000 +arduino-esp8266.menu.baud.921600=921600 +arduino-esp8266.menu.baud.921600.upload.speed=921600 +arduino-esp8266.menu.baud.3000000=3000000 +arduino-esp8266.menu.baud.3000000.upload.speed=3000000 + +############################################################## +gen4iod.name=4D Systems gen4 IoD Range +gen4iod.build.board=GEN4_IOD +gen4iod.build.f_cpu=160000000L +gen4iod.build.variant=generic +gen4iod.upload.tool=esptool +gen4iod.upload.maximum_data_size=81920 +gen4iod.upload.wait_for_upload_port=true +gen4iod.upload.erase_cmd=version +gen4iod.serial.disableDTR=true +gen4iod.serial.disableRTS=true +gen4iod.build.mcu=esp8266 +gen4iod.build.core=esp8266 +gen4iod.build.spiffs_pagesize=256 +gen4iod.build.debug_port= +gen4iod.build.debug_level= +gen4iod.menu.xtal.80=80 MHz +gen4iod.menu.xtal.80.build.f_cpu=80000000L +gen4iod.menu.xtal.160=160 MHz +gen4iod.menu.xtal.160.build.f_cpu=160000000L +gen4iod.menu.vt.flash=Flash +gen4iod.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +gen4iod.menu.vt.heap=Heap +gen4iod.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +gen4iod.menu.vt.iram=IRAM +gen4iod.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +gen4iod.menu.exception.legacy=Legacy (new can return nullptr) +gen4iod.menu.exception.legacy.build.exception_flags=-fno-exceptions +gen4iod.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +gen4iod.menu.exception.disabled=Disabled (new can abort) +gen4iod.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +gen4iod.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +gen4iod.menu.exception.enabled=Enabled +gen4iod.menu.exception.enabled.build.exception_flags=-fexceptions +gen4iod.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +gen4iod.menu.ssl.all=All SSL ciphers (most compatible) +gen4iod.menu.ssl.all.build.sslflags= +gen4iod.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +gen4iod.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +gen4iod.upload.resetmethod=nodemcu +gen4iod.build.flash_mode=dio +gen4iod.build.flash_flags=-DFLASHMODE_DIO +gen4iod.build.flash_freq=80 +gen4iod.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB) +gen4iod.menu.eesz.512K32.build.flash_size=512K +gen4iod.menu.eesz.512K32.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +gen4iod.menu.eesz.512K32.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K32.upload.maximum_size=466928 +gen4iod.menu.eesz.512K32.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K32.build.spiffs_start=0x73000 +gen4iod.menu.eesz.512K32.build.spiffs_end=0x7B000 +gen4iod.menu.eesz.512K32.build.spiffs_blocksize=4096 +gen4iod.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB) +gen4iod.menu.eesz.512K64.build.flash_size=512K +gen4iod.menu.eesz.512K64.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +gen4iod.menu.eesz.512K64.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K64.upload.maximum_size=434160 +gen4iod.menu.eesz.512K64.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K64.build.spiffs_start=0x6B000 +gen4iod.menu.eesz.512K64.build.spiffs_end=0x7B000 +gen4iod.menu.eesz.512K64.build.spiffs_blocksize=4096 +gen4iod.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB) +gen4iod.menu.eesz.512K128.build.flash_size=512K +gen4iod.menu.eesz.512K128.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +gen4iod.menu.eesz.512K128.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K128.upload.maximum_size=368624 +gen4iod.menu.eesz.512K128.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K128.build.spiffs_start=0x5B000 +gen4iod.menu.eesz.512K128.build.spiffs_end=0x7B000 +gen4iod.menu.eesz.512K128.build.spiffs_blocksize=4096 +gen4iod.menu.eesz.512K=512KB (FS:none OTA:~246KB) +gen4iod.menu.eesz.512K.build.flash_size=512K +gen4iod.menu.eesz.512K.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +gen4iod.menu.eesz.512K.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K.upload.maximum_size=499696 +gen4iod.menu.eesz.512K.build.rfcal_addr=0x7C000 +gen4iod.menu.ip.lm2f=v2 Lower Memory +gen4iod.menu.ip.lm2f.build.lwip_include=lwip2/include +gen4iod.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +gen4iod.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +gen4iod.menu.ip.hb2f=v2 Higher Bandwidth +gen4iod.menu.ip.hb2f.build.lwip_include=lwip2/include +gen4iod.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +gen4iod.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +gen4iod.menu.ip.lm2n=v2 Lower Memory (no features) +gen4iod.menu.ip.lm2n.build.lwip_include=lwip2/include +gen4iod.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +gen4iod.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +gen4iod.menu.ip.hb2n=v2 Higher Bandwidth (no features) +gen4iod.menu.ip.hb2n.build.lwip_include=lwip2/include +gen4iod.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +gen4iod.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +gen4iod.menu.ip.lm6f=v2 IPv6 Lower Memory +gen4iod.menu.ip.lm6f.build.lwip_include=lwip2/include +gen4iod.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +gen4iod.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +gen4iod.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +gen4iod.menu.ip.hb6f.build.lwip_include=lwip2/include +gen4iod.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +gen4iod.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +gen4iod.menu.ip.hb1=v1.4 Higher Bandwidth +gen4iod.menu.ip.hb1.build.lwip_lib=-llwip_gcc +gen4iod.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +gen4iod.menu.ip.src=v1.4 Compile from source +gen4iod.menu.ip.src.build.lwip_lib=-llwip_src +gen4iod.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +gen4iod.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +gen4iod.menu.dbg.Disabled=Disabled +gen4iod.menu.dbg.Disabled.build.debug_port= +gen4iod.menu.dbg.Serial=Serial +gen4iod.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +gen4iod.menu.dbg.Serial1=Serial1 +gen4iod.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +gen4iod.menu.lvl.None____=None +gen4iod.menu.lvl.None____.build.debug_level= +gen4iod.menu.lvl.SSL=SSL +gen4iod.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +gen4iod.menu.lvl.TLS_MEM=TLS_MEM +gen4iod.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +gen4iod.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +gen4iod.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.HTTP_SERVER=HTTP_SERVER +gen4iod.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +gen4iod.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +gen4iod.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +gen4iod.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +gen4iod.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.CORE=CORE +gen4iod.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +gen4iod.menu.lvl.WIFI=WIFI +gen4iod.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +gen4iod.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +gen4iod.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +gen4iod.menu.lvl.UPDATER=UPDATER +gen4iod.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +gen4iod.menu.lvl.OTA=OTA +gen4iod.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +gen4iod.menu.lvl.OOM=OOM +gen4iod.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +gen4iod.menu.lvl.MDNS=MDNS +gen4iod.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +gen4iod.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +gen4iod.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +gen4iod.menu.wipe.none=Only Sketch +gen4iod.menu.wipe.none.upload.erase_cmd=version +gen4iod.menu.wipe.sdk=Sketch + WiFi Settings +gen4iod.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +gen4iod.menu.wipe.all=All Flash Contents +gen4iod.menu.wipe.all.upload.erase_cmd=erase_flash +gen4iod.menu.baud.115200=115200 +gen4iod.menu.baud.115200.upload.speed=115200 +gen4iod.menu.baud.57600=57600 +gen4iod.menu.baud.57600.upload.speed=57600 +gen4iod.menu.baud.230400.linux=230400 +gen4iod.menu.baud.230400.macosx=230400 +gen4iod.menu.baud.230400.upload.speed=230400 +gen4iod.menu.baud.256000.windows=256000 +gen4iod.menu.baud.256000.upload.speed=256000 +gen4iod.menu.baud.460800.linux=460800 +gen4iod.menu.baud.460800.macosx=460800 +gen4iod.menu.baud.460800.upload.speed=460800 +gen4iod.menu.baud.512000.windows=512000 +gen4iod.menu.baud.512000.upload.speed=512000 +gen4iod.menu.baud.921600=921600 +gen4iod.menu.baud.921600.upload.speed=921600 +gen4iod.menu.baud.3000000=3000000 +gen4iod.menu.baud.3000000.upload.speed=3000000 + +############################################################## +oak.name=Digistump Oak +oak.build.board=ESP8266_OAK +oak.build.variant=oak +oak.upload.maximum_size=1040368 +oak.upload.tool=esptool +oak.upload.maximum_data_size=81920 +oak.upload.wait_for_upload_port=true +oak.upload.erase_cmd=version +oak.serial.disableDTR=true +oak.serial.disableRTS=true +oak.build.mcu=esp8266 +oak.build.core=esp8266 +oak.build.spiffs_pagesize=256 +oak.build.debug_port= +oak.build.debug_level= +oak.menu.xtal.80=80 MHz +oak.menu.xtal.80.build.f_cpu=80000000L +oak.menu.xtal.160=160 MHz +oak.menu.xtal.160.build.f_cpu=160000000L +oak.menu.vt.flash=Flash +oak.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +oak.menu.vt.heap=Heap +oak.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +oak.menu.vt.iram=IRAM +oak.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +oak.menu.exception.legacy=Legacy (new can return nullptr) +oak.menu.exception.legacy.build.exception_flags=-fno-exceptions +oak.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +oak.menu.exception.disabled=Disabled (new can abort) +oak.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +oak.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +oak.menu.exception.enabled=Enabled +oak.menu.exception.enabled.build.exception_flags=-fexceptions +oak.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +oak.menu.ssl.all=All SSL ciphers (most compatible) +oak.menu.ssl.all.build.sslflags= +oak.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +oak.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +oak.upload.resetmethod=none +oak.build.flash_mode=dio +oak.build.flash_flags=-DFLASHMODE_DIO +oak.build.flash_freq=40 +oak.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +oak.menu.eesz.4M2M.build.flash_size=4M +oak.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +oak.menu.eesz.4M2M.build.spiffs_pagesize=256 +oak.menu.eesz.4M2M.upload.maximum_size=1044464 +oak.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M2M.build.spiffs_start=0x200000 +oak.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +oak.menu.eesz.4M2M.build.spiffs_blocksize=8192 +oak.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +oak.menu.eesz.4M3M.build.flash_size=4M +oak.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +oak.menu.eesz.4M3M.build.spiffs_pagesize=256 +oak.menu.eesz.4M3M.upload.maximum_size=1044464 +oak.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M3M.build.spiffs_start=0x100000 +oak.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +oak.menu.eesz.4M3M.build.spiffs_blocksize=8192 +oak.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +oak.menu.eesz.4M1M.build.flash_size=4M +oak.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +oak.menu.eesz.4M1M.build.spiffs_pagesize=256 +oak.menu.eesz.4M1M.upload.maximum_size=1044464 +oak.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M1M.build.spiffs_start=0x300000 +oak.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +oak.menu.eesz.4M1M.build.spiffs_blocksize=8192 +oak.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +oak.menu.eesz.4M.build.flash_size=4M +oak.menu.eesz.4M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +oak.menu.eesz.4M.build.spiffs_pagesize=256 +oak.menu.eesz.4M.upload.maximum_size=1044464 +oak.menu.eesz.4M.build.rfcal_addr=0x3FC000 +oak.menu.ip.lm2f=v2 Lower Memory +oak.menu.ip.lm2f.build.lwip_include=lwip2/include +oak.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +oak.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +oak.menu.ip.hb2f=v2 Higher Bandwidth +oak.menu.ip.hb2f.build.lwip_include=lwip2/include +oak.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +oak.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +oak.menu.ip.lm2n=v2 Lower Memory (no features) +oak.menu.ip.lm2n.build.lwip_include=lwip2/include +oak.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +oak.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +oak.menu.ip.hb2n=v2 Higher Bandwidth (no features) +oak.menu.ip.hb2n.build.lwip_include=lwip2/include +oak.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +oak.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +oak.menu.ip.lm6f=v2 IPv6 Lower Memory +oak.menu.ip.lm6f.build.lwip_include=lwip2/include +oak.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +oak.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +oak.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +oak.menu.ip.hb6f.build.lwip_include=lwip2/include +oak.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +oak.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +oak.menu.ip.hb1=v1.4 Higher Bandwidth +oak.menu.ip.hb1.build.lwip_lib=-llwip_gcc +oak.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +oak.menu.ip.src=v1.4 Compile from source +oak.menu.ip.src.build.lwip_lib=-llwip_src +oak.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +oak.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +oak.menu.dbg.Disabled=Disabled +oak.menu.dbg.Disabled.build.debug_port= +oak.menu.dbg.Serial=Serial +oak.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +oak.menu.dbg.Serial1=Serial1 +oak.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +oak.menu.lvl.None____=None +oak.menu.lvl.None____.build.debug_level= +oak.menu.lvl.SSL=SSL +oak.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +oak.menu.lvl.TLS_MEM=TLS_MEM +oak.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +oak.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +oak.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.HTTP_SERVER=HTTP_SERVER +oak.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +oak.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +oak.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +oak.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +oak.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +oak.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.CORE=CORE +oak.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +oak.menu.lvl.WIFI=WIFI +oak.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +oak.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +oak.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +oak.menu.lvl.UPDATER=UPDATER +oak.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +oak.menu.lvl.OTA=OTA +oak.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +oak.menu.lvl.OOM=OOM +oak.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +oak.menu.lvl.MDNS=MDNS +oak.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +oak.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +oak.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +oak.menu.wipe.none=Only Sketch +oak.menu.wipe.none.upload.erase_cmd=version +oak.menu.wipe.sdk=Sketch + WiFi Settings +oak.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +oak.menu.wipe.all=All Flash Contents +oak.menu.wipe.all.upload.erase_cmd=erase_flash +oak.menu.baud.921600=921600 +oak.menu.baud.921600.upload.speed=921600 +oak.menu.baud.57600=57600 +oak.menu.baud.57600.upload.speed=57600 +oak.menu.baud.115200=115200 +oak.menu.baud.115200.upload.speed=115200 +oak.menu.baud.230400.linux=230400 +oak.menu.baud.230400.macosx=230400 +oak.menu.baud.230400.upload.speed=230400 +oak.menu.baud.256000.windows=256000 +oak.menu.baud.256000.upload.speed=256000 +oak.menu.baud.460800.linux=460800 +oak.menu.baud.460800.macosx=460800 +oak.menu.baud.460800.upload.speed=460800 +oak.menu.baud.512000.windows=512000 +oak.menu.baud.512000.upload.speed=512000 +oak.menu.baud.3000000=3000000 +oak.menu.baud.3000000.upload.speed=3000000 + +############################################################## +wifiduino.name=WiFiduino +wifiduino.build.board=WIFIDUINO_ESP8266 +wifiduino.build.variant=wifiduino +wifiduino.upload.tool=esptool +wifiduino.upload.maximum_data_size=81920 +wifiduino.upload.wait_for_upload_port=true +wifiduino.upload.erase_cmd=version +wifiduino.serial.disableDTR=true +wifiduino.serial.disableRTS=true +wifiduino.build.mcu=esp8266 +wifiduino.build.core=esp8266 +wifiduino.build.spiffs_pagesize=256 +wifiduino.build.debug_port= +wifiduino.build.debug_level= +wifiduino.menu.xtal.80=80 MHz +wifiduino.menu.xtal.80.build.f_cpu=80000000L +wifiduino.menu.xtal.160=160 MHz +wifiduino.menu.xtal.160.build.f_cpu=160000000L +wifiduino.menu.vt.flash=Flash +wifiduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wifiduino.menu.vt.heap=Heap +wifiduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wifiduino.menu.vt.iram=IRAM +wifiduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wifiduino.menu.exception.legacy=Legacy (new can return nullptr) +wifiduino.menu.exception.legacy.build.exception_flags=-fno-exceptions +wifiduino.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +wifiduino.menu.exception.disabled=Disabled (new can abort) +wifiduino.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +wifiduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wifiduino.menu.exception.enabled=Enabled +wifiduino.menu.exception.enabled.build.exception_flags=-fexceptions +wifiduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wifiduino.menu.ssl.all=All SSL ciphers (most compatible) +wifiduino.menu.ssl.all.build.sslflags= +wifiduino.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +wifiduino.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +wifiduino.upload.resetmethod=nodemcu +wifiduino.build.flash_mode=dio +wifiduino.build.flash_flags=-DFLASHMODE_DIO +wifiduino.build.flash_freq=40 +wifiduino.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +wifiduino.menu.eesz.4M2M.build.flash_size=4M +wifiduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +wifiduino.menu.eesz.4M2M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M2M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M2M.build.spiffs_start=0x200000 +wifiduino.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +wifiduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 +wifiduino.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +wifiduino.menu.eesz.4M3M.build.flash_size=4M +wifiduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +wifiduino.menu.eesz.4M3M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M3M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M3M.build.spiffs_start=0x100000 +wifiduino.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +wifiduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 +wifiduino.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +wifiduino.menu.eesz.4M1M.build.flash_size=4M +wifiduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +wifiduino.menu.eesz.4M1M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M1M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M1M.build.spiffs_start=0x300000 +wifiduino.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +wifiduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 +wifiduino.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +wifiduino.menu.eesz.4M.build.flash_size=4M +wifiduino.menu.eesz.4M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +wifiduino.menu.eesz.4M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 +wifiduino.menu.ip.lm2f=v2 Lower Memory +wifiduino.menu.ip.lm2f.build.lwip_include=lwip2/include +wifiduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wifiduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifiduino.menu.ip.hb2f=v2 Higher Bandwidth +wifiduino.menu.ip.hb2f.build.lwip_include=lwip2/include +wifiduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wifiduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifiduino.menu.ip.lm2n=v2 Lower Memory (no features) +wifiduino.menu.ip.lm2n.build.lwip_include=lwip2/include +wifiduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wifiduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifiduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wifiduino.menu.ip.hb2n.build.lwip_include=lwip2/include +wifiduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wifiduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifiduino.menu.ip.lm6f=v2 IPv6 Lower Memory +wifiduino.menu.ip.lm6f.build.lwip_include=lwip2/include +wifiduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wifiduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifiduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wifiduino.menu.ip.hb6f.build.lwip_include=lwip2/include +wifiduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wifiduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifiduino.menu.ip.hb1=v1.4 Higher Bandwidth +wifiduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wifiduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wifiduino.menu.ip.src=v1.4 Compile from source +wifiduino.menu.ip.src.build.lwip_lib=-llwip_src +wifiduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wifiduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wifiduino.menu.dbg.Disabled=Disabled +wifiduino.menu.dbg.Disabled.build.debug_port= +wifiduino.menu.dbg.Serial=Serial +wifiduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wifiduino.menu.dbg.Serial1=Serial1 +wifiduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wifiduino.menu.lvl.None____=None +wifiduino.menu.lvl.None____.build.debug_level= +wifiduino.menu.lvl.SSL=SSL +wifiduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wifiduino.menu.lvl.TLS_MEM=TLS_MEM +wifiduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wifiduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wifiduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.HTTP_SERVER=HTTP_SERVER +wifiduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wifiduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wifiduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wifiduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wifiduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.CORE=CORE +wifiduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wifiduino.menu.lvl.WIFI=WIFI +wifiduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wifiduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wifiduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wifiduino.menu.lvl.UPDATER=UPDATER +wifiduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wifiduino.menu.lvl.OTA=OTA +wifiduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wifiduino.menu.lvl.OOM=OOM +wifiduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wifiduino.menu.lvl.MDNS=MDNS +wifiduino.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wifiduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wifiduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wifiduino.menu.wipe.none=Only Sketch +wifiduino.menu.wipe.none.upload.erase_cmd=version +wifiduino.menu.wipe.sdk=Sketch + WiFi Settings +wifiduino.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +wifiduino.menu.wipe.all=All Flash Contents +wifiduino.menu.wipe.all.upload.erase_cmd=erase_flash +wifiduino.menu.baud.921600=921600 +wifiduino.menu.baud.921600.upload.speed=921600 +wifiduino.menu.baud.57600=57600 +wifiduino.menu.baud.57600.upload.speed=57600 +wifiduino.menu.baud.115200=115200 +wifiduino.menu.baud.115200.upload.speed=115200 +wifiduino.menu.baud.230400.linux=230400 +wifiduino.menu.baud.230400.macosx=230400 +wifiduino.menu.baud.230400.upload.speed=230400 +wifiduino.menu.baud.256000.windows=256000 +wifiduino.menu.baud.256000.upload.speed=256000 +wifiduino.menu.baud.460800.linux=460800 +wifiduino.menu.baud.460800.macosx=460800 +wifiduino.menu.baud.460800.upload.speed=460800 +wifiduino.menu.baud.512000.windows=512000 +wifiduino.menu.baud.512000.upload.speed=512000 +wifiduino.menu.baud.3000000=3000000 +wifiduino.menu.baud.3000000.upload.speed=3000000 + +############################################################## +wifi_slot.name=Amperka WiFi Slot +wifi_slot.build.board=AMPERKA_WIFI_SLOT +wifi_slot.build.variant=wifi_slot +wifi_slot.upload.tool=esptool +wifi_slot.upload.maximum_data_size=81920 +wifi_slot.upload.wait_for_upload_port=true +wifi_slot.upload.erase_cmd=version +wifi_slot.serial.disableDTR=true +wifi_slot.serial.disableRTS=true +wifi_slot.build.mcu=esp8266 +wifi_slot.build.core=esp8266 +wifi_slot.build.spiffs_pagesize=256 +wifi_slot.build.debug_port= +wifi_slot.build.debug_level= +wifi_slot.menu.xtal.80=80 MHz +wifi_slot.menu.xtal.80.build.f_cpu=80000000L +wifi_slot.menu.xtal.160=160 MHz +wifi_slot.menu.xtal.160.build.f_cpu=160000000L +wifi_slot.menu.vt.flash=Flash +wifi_slot.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wifi_slot.menu.vt.heap=Heap +wifi_slot.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wifi_slot.menu.vt.iram=IRAM +wifi_slot.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wifi_slot.menu.exception.legacy=Legacy (new can return nullptr) +wifi_slot.menu.exception.legacy.build.exception_flags=-fno-exceptions +wifi_slot.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +wifi_slot.menu.exception.disabled=Disabled (new can abort) +wifi_slot.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +wifi_slot.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wifi_slot.menu.exception.enabled=Enabled +wifi_slot.menu.exception.enabled.build.exception_flags=-fexceptions +wifi_slot.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wifi_slot.menu.ssl.all=All SSL ciphers (most compatible) +wifi_slot.menu.ssl.all.build.sslflags= +wifi_slot.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +wifi_slot.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +wifi_slot.upload.resetmethod=nodemcu +wifi_slot.menu.FlashFreq.40=40MHz +wifi_slot.menu.FlashFreq.40.build.flash_freq=40 +wifi_slot.menu.FlashFreq.80=80MHz +wifi_slot.menu.FlashFreq.80.build.flash_freq=80 +wifi_slot.menu.FlashFreq.20=20MHz +wifi_slot.menu.FlashFreq.20.build.flash_freq=20 +wifi_slot.menu.FlashFreq.26=26MHz +wifi_slot.menu.FlashFreq.26.build.flash_freq=26 +wifi_slot.menu.FlashMode.dout=DOUT (compatible) +wifi_slot.menu.FlashMode.dout.build.flash_mode=dout +wifi_slot.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT +wifi_slot.menu.FlashMode.dio=DIO +wifi_slot.menu.FlashMode.dio.build.flash_mode=dio +wifi_slot.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO +wifi_slot.menu.FlashMode.qout=QOUT +wifi_slot.menu.FlashMode.qout.build.flash_mode=qout +wifi_slot.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT +wifi_slot.menu.FlashMode.qio=QIO (fast) +wifi_slot.menu.FlashMode.qio.build.flash_mode=qio +wifi_slot.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO +wifi_slot.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) +wifi_slot.menu.eesz.1M64.build.flash_size=1M +wifi_slot.menu.eesz.1M64.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +wifi_slot.menu.eesz.1M64.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M64.upload.maximum_size=958448 +wifi_slot.menu.eesz.1M64.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M64.build.spiffs_start=0xEB000 +wifi_slot.menu.eesz.1M64.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M64.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) +wifi_slot.menu.eesz.1M128.build.flash_size=1M +wifi_slot.menu.eesz.1M128.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +wifi_slot.menu.eesz.1M128.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M128.upload.maximum_size=892912 +wifi_slot.menu.eesz.1M128.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M128.build.spiffs_start=0xDB000 +wifi_slot.menu.eesz.1M128.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M128.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) +wifi_slot.menu.eesz.1M144.build.flash_size=1M +wifi_slot.menu.eesz.1M144.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +wifi_slot.menu.eesz.1M144.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M144.upload.maximum_size=876528 +wifi_slot.menu.eesz.1M144.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M144.build.spiffs_start=0xD7000 +wifi_slot.menu.eesz.1M144.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M144.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) +wifi_slot.menu.eesz.1M160.build.flash_size=1M +wifi_slot.menu.eesz.1M160.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +wifi_slot.menu.eesz.1M160.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M160.upload.maximum_size=860144 +wifi_slot.menu.eesz.1M160.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M160.build.spiffs_start=0xD3000 +wifi_slot.menu.eesz.1M160.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M160.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) +wifi_slot.menu.eesz.1M192.build.flash_size=1M +wifi_slot.menu.eesz.1M192.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +wifi_slot.menu.eesz.1M192.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M192.upload.maximum_size=827376 +wifi_slot.menu.eesz.1M192.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M192.build.spiffs_start=0xCB000 +wifi_slot.menu.eesz.1M192.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M192.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) +wifi_slot.menu.eesz.1M256.build.flash_size=1M +wifi_slot.menu.eesz.1M256.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +wifi_slot.menu.eesz.1M256.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M256.upload.maximum_size=761840 +wifi_slot.menu.eesz.1M256.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M256.build.spiffs_start=0xBB000 +wifi_slot.menu.eesz.1M256.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M256.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) +wifi_slot.menu.eesz.1M512.build.flash_size=1M +wifi_slot.menu.eesz.1M512.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +wifi_slot.menu.eesz.1M512.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M512.upload.maximum_size=499696 +wifi_slot.menu.eesz.1M512.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M512.build.spiffs_start=0x7B000 +wifi_slot.menu.eesz.1M512.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M512.build.spiffs_blocksize=8192 +wifi_slot.menu.eesz.1M=1MB (FS:none OTA:~502KB) +wifi_slot.menu.eesz.1M.build.flash_size=1M +wifi_slot.menu.eesz.1M.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +wifi_slot.menu.eesz.1M.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M.upload.maximum_size=1023984 +wifi_slot.menu.eesz.1M.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.2M64=2MB (FS:64KB OTA:~992KB) +wifi_slot.menu.eesz.2M64.build.flash_size=2M +wifi_slot.menu.eesz.2M64.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M64.build.flash_ld=eagle.flash.2m64.ld +wifi_slot.menu.eesz.2M64.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M64.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M64.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M64.build.spiffs_start=0x1F0000 +wifi_slot.menu.eesz.2M64.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M64.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.2M128=2MB (FS:128KB OTA:~960KB) +wifi_slot.menu.eesz.2M128.build.flash_size=2M +wifi_slot.menu.eesz.2M128.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld +wifi_slot.menu.eesz.2M128.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M128.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M128.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M128.build.spiffs_start=0x1E0000 +wifi_slot.menu.eesz.2M128.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M128.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.2M256=2MB (FS:256KB OTA:~896KB) +wifi_slot.menu.eesz.2M256.build.flash_size=2M +wifi_slot.menu.eesz.2M256.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld +wifi_slot.menu.eesz.2M256.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M256.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M256.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M256.build.spiffs_start=0x1C0000 +wifi_slot.menu.eesz.2M256.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M256.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.2M512=2MB (FS:512KB OTA:~768KB) +wifi_slot.menu.eesz.2M512.build.flash_size=2M +wifi_slot.menu.eesz.2M512.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld +wifi_slot.menu.eesz.2M512.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M512.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M512.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M512.build.spiffs_start=0x180000 +wifi_slot.menu.eesz.2M512.build.spiffs_end=0x1FA000 +wifi_slot.menu.eesz.2M512.build.spiffs_blocksize=8192 +wifi_slot.menu.eesz.2M1M=2MB (FS:1MB OTA:~512KB) +wifi_slot.menu.eesz.2M1M.build.flash_size=2M +wifi_slot.menu.eesz.2M1M.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld +wifi_slot.menu.eesz.2M1M.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M1M.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M1M.build.spiffs_start=0x100000 +wifi_slot.menu.eesz.2M1M.build.spiffs_end=0x1FA000 +wifi_slot.menu.eesz.2M1M.build.spiffs_blocksize=8192 +wifi_slot.menu.eesz.2M=2MB (FS:none OTA:~1019KB) +wifi_slot.menu.eesz.2M.build.flash_size=2M +wifi_slot.menu.eesz.2M.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld +wifi_slot.menu.eesz.2M.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M.build.rfcal_addr=0x1FC000 +wifi_slot.menu.ip.lm2f=v2 Lower Memory +wifi_slot.menu.ip.lm2f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wifi_slot.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifi_slot.menu.ip.hb2f=v2 Higher Bandwidth +wifi_slot.menu.ip.hb2f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wifi_slot.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifi_slot.menu.ip.lm2n=v2 Lower Memory (no features) +wifi_slot.menu.ip.lm2n.build.lwip_include=lwip2/include +wifi_slot.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wifi_slot.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifi_slot.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wifi_slot.menu.ip.hb2n.build.lwip_include=lwip2/include +wifi_slot.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wifi_slot.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifi_slot.menu.ip.lm6f=v2 IPv6 Lower Memory +wifi_slot.menu.ip.lm6f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wifi_slot.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifi_slot.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wifi_slot.menu.ip.hb6f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wifi_slot.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifi_slot.menu.ip.hb1=v1.4 Higher Bandwidth +wifi_slot.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wifi_slot.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wifi_slot.menu.ip.src=v1.4 Compile from source +wifi_slot.menu.ip.src.build.lwip_lib=-llwip_src +wifi_slot.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wifi_slot.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wifi_slot.menu.dbg.Disabled=Disabled +wifi_slot.menu.dbg.Disabled.build.debug_port= +wifi_slot.menu.dbg.Serial=Serial +wifi_slot.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wifi_slot.menu.dbg.Serial1=Serial1 +wifi_slot.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wifi_slot.menu.lvl.None____=None +wifi_slot.menu.lvl.None____.build.debug_level= +wifi_slot.menu.lvl.SSL=SSL +wifi_slot.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wifi_slot.menu.lvl.TLS_MEM=TLS_MEM +wifi_slot.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wifi_slot.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wifi_slot.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.HTTP_SERVER=HTTP_SERVER +wifi_slot.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wifi_slot.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wifi_slot.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wifi_slot.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wifi_slot.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.CORE=CORE +wifi_slot.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wifi_slot.menu.lvl.WIFI=WIFI +wifi_slot.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wifi_slot.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wifi_slot.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wifi_slot.menu.lvl.UPDATER=UPDATER +wifi_slot.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wifi_slot.menu.lvl.OTA=OTA +wifi_slot.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wifi_slot.menu.lvl.OOM=OOM +wifi_slot.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wifi_slot.menu.lvl.MDNS=MDNS +wifi_slot.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wifi_slot.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wifi_slot.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wifi_slot.menu.wipe.none=Only Sketch +wifi_slot.menu.wipe.none.upload.erase_cmd=version +wifi_slot.menu.wipe.sdk=Sketch + WiFi Settings +wifi_slot.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +wifi_slot.menu.wipe.all=All Flash Contents +wifi_slot.menu.wipe.all.upload.erase_cmd=erase_flash +wifi_slot.menu.baud.115200=115200 +wifi_slot.menu.baud.115200.upload.speed=115200 +wifi_slot.menu.baud.57600=57600 +wifi_slot.menu.baud.57600.upload.speed=57600 +wifi_slot.menu.baud.230400.linux=230400 +wifi_slot.menu.baud.230400.macosx=230400 +wifi_slot.menu.baud.230400.upload.speed=230400 +wifi_slot.menu.baud.256000.windows=256000 +wifi_slot.menu.baud.256000.upload.speed=256000 +wifi_slot.menu.baud.460800.linux=460800 +wifi_slot.menu.baud.460800.macosx=460800 +wifi_slot.menu.baud.460800.upload.speed=460800 +wifi_slot.menu.baud.512000.windows=512000 +wifi_slot.menu.baud.512000.upload.speed=512000 +wifi_slot.menu.baud.921600=921600 +wifi_slot.menu.baud.921600.upload.speed=921600 +wifi_slot.menu.baud.3000000=3000000 +wifi_slot.menu.baud.3000000.upload.speed=3000000 + +############################################################## +wiolink.name=Seeed Wio Link +wiolink.build.board=ESP8266_WIO_LINK +wiolink.build.variant=wiolink +wiolink.upload.tool=esptool +wiolink.upload.maximum_data_size=81920 +wiolink.upload.wait_for_upload_port=true +wiolink.upload.erase_cmd=version +wiolink.serial.disableDTR=true +wiolink.serial.disableRTS=true +wiolink.build.mcu=esp8266 +wiolink.build.core=esp8266 +wiolink.build.spiffs_pagesize=256 +wiolink.build.debug_port= +wiolink.build.debug_level= +wiolink.menu.xtal.80=80 MHz +wiolink.menu.xtal.80.build.f_cpu=80000000L +wiolink.menu.xtal.160=160 MHz +wiolink.menu.xtal.160.build.f_cpu=160000000L +wiolink.menu.vt.flash=Flash +wiolink.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wiolink.menu.vt.heap=Heap +wiolink.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wiolink.menu.vt.iram=IRAM +wiolink.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wiolink.menu.exception.legacy=Legacy (new can return nullptr) +wiolink.menu.exception.legacy.build.exception_flags=-fno-exceptions +wiolink.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +wiolink.menu.exception.disabled=Disabled (new can abort) +wiolink.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +wiolink.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wiolink.menu.exception.enabled=Enabled +wiolink.menu.exception.enabled.build.exception_flags=-fexceptions +wiolink.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wiolink.menu.ssl.all=All SSL ciphers (most compatible) +wiolink.menu.ssl.all.build.sslflags= +wiolink.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +wiolink.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +wiolink.upload.resetmethod=nodemcu +wiolink.build.flash_mode=qio +wiolink.build.flash_flags=-DFLASHMODE_QIO +wiolink.build.flash_freq=40 +wiolink.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +wiolink.menu.eesz.4M2M.build.flash_size=4M +wiolink.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +wiolink.menu.eesz.4M2M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M2M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M2M.build.spiffs_start=0x200000 +wiolink.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +wiolink.menu.eesz.4M2M.build.spiffs_blocksize=8192 +wiolink.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +wiolink.menu.eesz.4M3M.build.flash_size=4M +wiolink.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +wiolink.menu.eesz.4M3M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M3M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M3M.build.spiffs_start=0x100000 +wiolink.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +wiolink.menu.eesz.4M3M.build.spiffs_blocksize=8192 +wiolink.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +wiolink.menu.eesz.4M1M.build.flash_size=4M +wiolink.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +wiolink.menu.eesz.4M1M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M1M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M1M.build.spiffs_start=0x300000 +wiolink.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +wiolink.menu.eesz.4M1M.build.spiffs_blocksize=8192 +wiolink.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +wiolink.menu.eesz.4M.build.flash_size=4M +wiolink.menu.eesz.4M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +wiolink.menu.eesz.4M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M.build.rfcal_addr=0x3FC000 +wiolink.menu.ip.lm2f=v2 Lower Memory +wiolink.menu.ip.lm2f.build.lwip_include=lwip2/include +wiolink.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wiolink.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wiolink.menu.ip.hb2f=v2 Higher Bandwidth +wiolink.menu.ip.hb2f.build.lwip_include=lwip2/include +wiolink.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wiolink.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wiolink.menu.ip.lm2n=v2 Lower Memory (no features) +wiolink.menu.ip.lm2n.build.lwip_include=lwip2/include +wiolink.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wiolink.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wiolink.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wiolink.menu.ip.hb2n.build.lwip_include=lwip2/include +wiolink.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wiolink.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wiolink.menu.ip.lm6f=v2 IPv6 Lower Memory +wiolink.menu.ip.lm6f.build.lwip_include=lwip2/include +wiolink.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wiolink.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wiolink.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wiolink.menu.ip.hb6f.build.lwip_include=lwip2/include +wiolink.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wiolink.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wiolink.menu.ip.hb1=v1.4 Higher Bandwidth +wiolink.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wiolink.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wiolink.menu.ip.src=v1.4 Compile from source +wiolink.menu.ip.src.build.lwip_lib=-llwip_src +wiolink.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wiolink.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wiolink.menu.dbg.Disabled=Disabled +wiolink.menu.dbg.Disabled.build.debug_port= +wiolink.menu.dbg.Serial=Serial +wiolink.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wiolink.menu.dbg.Serial1=Serial1 +wiolink.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wiolink.menu.lvl.None____=None +wiolink.menu.lvl.None____.build.debug_level= +wiolink.menu.lvl.SSL=SSL +wiolink.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wiolink.menu.lvl.TLS_MEM=TLS_MEM +wiolink.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wiolink.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wiolink.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.HTTP_SERVER=HTTP_SERVER +wiolink.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wiolink.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wiolink.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wiolink.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wiolink.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wiolink.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.CORE=CORE +wiolink.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wiolink.menu.lvl.WIFI=WIFI +wiolink.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wiolink.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wiolink.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wiolink.menu.lvl.UPDATER=UPDATER +wiolink.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wiolink.menu.lvl.OTA=OTA +wiolink.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wiolink.menu.lvl.OOM=OOM +wiolink.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wiolink.menu.lvl.MDNS=MDNS +wiolink.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wiolink.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wiolink.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wiolink.menu.wipe.none=Only Sketch +wiolink.menu.wipe.none.upload.erase_cmd=version +wiolink.menu.wipe.sdk=Sketch + WiFi Settings +wiolink.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +wiolink.menu.wipe.all=All Flash Contents +wiolink.menu.wipe.all.upload.erase_cmd=erase_flash +wiolink.menu.baud.115200=115200 +wiolink.menu.baud.115200.upload.speed=115200 +wiolink.menu.baud.57600=57600 +wiolink.menu.baud.57600.upload.speed=57600 +wiolink.menu.baud.230400.linux=230400 +wiolink.menu.baud.230400.macosx=230400 +wiolink.menu.baud.230400.upload.speed=230400 +wiolink.menu.baud.256000.windows=256000 +wiolink.menu.baud.256000.upload.speed=256000 +wiolink.menu.baud.460800.linux=460800 +wiolink.menu.baud.460800.macosx=460800 +wiolink.menu.baud.460800.upload.speed=460800 +wiolink.menu.baud.512000.windows=512000 +wiolink.menu.baud.512000.upload.speed=512000 +wiolink.menu.baud.921600=921600 +wiolink.menu.baud.921600.upload.speed=921600 +wiolink.menu.baud.3000000=3000000 +wiolink.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espectro.name=ESPectro Core +espectro.build.board=ESP8266_ESPECTRO_CORE +espectro.build.variant=espectro +espectro.upload.tool=esptool +espectro.upload.maximum_data_size=81920 +espectro.upload.wait_for_upload_port=true +espectro.upload.erase_cmd=version +espectro.serial.disableDTR=true +espectro.serial.disableRTS=true +espectro.build.mcu=esp8266 +espectro.build.core=esp8266 +espectro.build.spiffs_pagesize=256 +espectro.build.debug_port= +espectro.build.debug_level= +espectro.menu.xtal.80=80 MHz +espectro.menu.xtal.80.build.f_cpu=80000000L +espectro.menu.xtal.160=160 MHz +espectro.menu.xtal.160.build.f_cpu=160000000L +espectro.menu.vt.flash=Flash +espectro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espectro.menu.vt.heap=Heap +espectro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espectro.menu.vt.iram=IRAM +espectro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espectro.menu.exception.legacy=Legacy (new can return nullptr) +espectro.menu.exception.legacy.build.exception_flags=-fno-exceptions +espectro.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espectro.menu.exception.disabled=Disabled (new can abort) +espectro.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espectro.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espectro.menu.exception.enabled=Enabled +espectro.menu.exception.enabled.build.exception_flags=-fexceptions +espectro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espectro.menu.ssl.all=All SSL ciphers (most compatible) +espectro.menu.ssl.all.build.sslflags= +espectro.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espectro.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espectro.upload.resetmethod=nodemcu +espectro.build.flash_mode=dio +espectro.build.flash_flags=-DFLASHMODE_DIO +espectro.build.flash_freq=40 +espectro.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +espectro.menu.eesz.4M2M.build.flash_size=4M +espectro.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espectro.menu.eesz.4M2M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M2M.upload.maximum_size=1044464 +espectro.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M2M.build.spiffs_start=0x200000 +espectro.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +espectro.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espectro.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +espectro.menu.eesz.4M3M.build.flash_size=4M +espectro.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espectro.menu.eesz.4M3M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M3M.upload.maximum_size=1044464 +espectro.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M3M.build.spiffs_start=0x100000 +espectro.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +espectro.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espectro.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +espectro.menu.eesz.4M1M.build.flash_size=4M +espectro.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espectro.menu.eesz.4M1M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M1M.upload.maximum_size=1044464 +espectro.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M1M.build.spiffs_start=0x300000 +espectro.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +espectro.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espectro.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +espectro.menu.eesz.4M.build.flash_size=4M +espectro.menu.eesz.4M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espectro.menu.eesz.4M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M.upload.maximum_size=1044464 +espectro.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espectro.menu.ip.lm2f=v2 Lower Memory +espectro.menu.ip.lm2f.build.lwip_include=lwip2/include +espectro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espectro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espectro.menu.ip.hb2f=v2 Higher Bandwidth +espectro.menu.ip.hb2f.build.lwip_include=lwip2/include +espectro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espectro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espectro.menu.ip.lm2n=v2 Lower Memory (no features) +espectro.menu.ip.lm2n.build.lwip_include=lwip2/include +espectro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espectro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espectro.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espectro.menu.ip.hb2n.build.lwip_include=lwip2/include +espectro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espectro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espectro.menu.ip.lm6f=v2 IPv6 Lower Memory +espectro.menu.ip.lm6f.build.lwip_include=lwip2/include +espectro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espectro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espectro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espectro.menu.ip.hb6f.build.lwip_include=lwip2/include +espectro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espectro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espectro.menu.ip.hb1=v1.4 Higher Bandwidth +espectro.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espectro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espectro.menu.ip.src=v1.4 Compile from source +espectro.menu.ip.src.build.lwip_lib=-llwip_src +espectro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espectro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espectro.menu.dbg.Disabled=Disabled +espectro.menu.dbg.Disabled.build.debug_port= +espectro.menu.dbg.Serial=Serial +espectro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espectro.menu.dbg.Serial1=Serial1 +espectro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espectro.menu.lvl.None____=None +espectro.menu.lvl.None____.build.debug_level= +espectro.menu.lvl.SSL=SSL +espectro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espectro.menu.lvl.TLS_MEM=TLS_MEM +espectro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espectro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espectro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.HTTP_SERVER=HTTP_SERVER +espectro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espectro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espectro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espectro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espectro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espectro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.CORE=CORE +espectro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espectro.menu.lvl.WIFI=WIFI +espectro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espectro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espectro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espectro.menu.lvl.UPDATER=UPDATER +espectro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espectro.menu.lvl.OTA=OTA +espectro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espectro.menu.lvl.OOM=OOM +espectro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espectro.menu.lvl.MDNS=MDNS +espectro.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espectro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espectro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espectro.menu.wipe.none=Only Sketch +espectro.menu.wipe.none.upload.erase_cmd=version +espectro.menu.wipe.sdk=Sketch + WiFi Settings +espectro.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espectro.menu.wipe.all=All Flash Contents +espectro.menu.wipe.all.upload.erase_cmd=erase_flash +espectro.menu.baud.115200=115200 +espectro.menu.baud.115200.upload.speed=115200 +espectro.menu.baud.57600=57600 +espectro.menu.baud.57600.upload.speed=57600 +espectro.menu.baud.230400.linux=230400 +espectro.menu.baud.230400.macosx=230400 +espectro.menu.baud.230400.upload.speed=230400 +espectro.menu.baud.256000.windows=256000 +espectro.menu.baud.256000.upload.speed=256000 +espectro.menu.baud.460800.linux=460800 +espectro.menu.baud.460800.macosx=460800 +espectro.menu.baud.460800.upload.speed=460800 +espectro.menu.baud.512000.windows=512000 +espectro.menu.baud.512000.upload.speed=512000 +espectro.menu.baud.921600=921600 +espectro.menu.baud.921600.upload.speed=921600 +espectro.menu.baud.3000000=3000000 +espectro.menu.baud.3000000.upload.speed=3000000 + diff --git a/arduino/version pre-2.6.0/platform.txt b/arduino/version pre-2.6.0/platform.txt new file mode 100644 index 000000000..aed8672f9 --- /dev/null +++ b/arduino/version pre-2.6.0/platform.txt @@ -0,0 +1,166 @@ + +# ESP8266 platform +# ------------------------------ + +# For more info: +# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification + +name=ESP8266 Boards (2.5.2-196-g45d71ae4) +version=2.5.2-196-g45d71ae4 + +# These will be removed by the packager script when doing a JSON release + + + + +runtime.tools.signing={runtime.platform.path}/tools/signing.py +runtime.tools.elf2bin={runtime.platform.path}/tools/elf2bin.py +runtime.tools.sizes={runtime.platform.path}/tools/sizes.py +runtime.tools.makecorever={runtime.platform.path}/tools/makecorever.py +runtime.tools.eboot={runtime.platform.path}/bootloaders/eboot/eboot.elf + +compiler.warning_flags=-w +compiler.warning_flags.none=-w +compiler.warning_flags.default= +compiler.warning_flags.more=-Wall +compiler.warning_flags.all=-Wall -Wextra + +build.lwip_lib=-llwip_gcc +build.lwip_include=lwip/include +build.lwip_flags=-DLWIP_OPEN_SRC + +build.vtable_flags=-DVTABLES_IN_FLASH + +build.sslflags= + +build.exception_flags=-fno-exceptions +build.stdcpp_lib=-lstdc++ +build.stdcpp_level=-std=gnu++11 + +# build.float=-u _printf_float -u _scanf_float +build.float= +build.led= +build.sdk=NONOSDK22y + +compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/ +compiler.sdk.path={runtime.platform.path}/tools/sdk + +compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf +compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" + +compiler.c.cmd=xtensa-lx106-elf-gcc +compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} + +compiler.S.cmd=xtensa-lx106-elf-gcc +compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls + +compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/lib/{build.sdk}" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read + +compiler.c.elf.cmd=xtensa-lx106-elf-gcc +compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc + +compiler.cpp.cmd=xtensa-lx106-elf-g++ +compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 {build.stdcpp_level} -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} + +compiler.as.cmd=xtensa-lx106-elf-as + +compiler.ar.cmd=xtensa-lx106-elf-ar +compiler.ar.flags=cru + +compiler.elf2hex.cmd=esptool +compiler.elf2hex.flags= + +compiler.size.cmd=xtensa-lx106-elf-size + +# This can be overriden in boards.txt +build.extra_flags=-DESP8266 + +# These can be overridden in platform.local.txt +compiler.c.extra_flags= +compiler.c.elf.extra_flags= +compiler.S.extra_flags= +compiler.cpp.extra_flags= +compiler.ar.extra_flags= +compiler.objcopy.eep.extra_flags= +compiler.elf2hex.extra_flags= + +## generate file with git version number +## needs git +recipe.hooks.sketch.prebuild.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h" +# This is quite a working hack. This form of prebuild hook, while intuitive, is not explicitly documented. +recipe.hooks.prebuild.10.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.makecorever}" --build_path "{build.path}" --platform_path "{runtime.platform.path}" --version "unix-{version}" + +## Build the app.ld linker file +recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld" + +## Compile c files +recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Compile c++ files +recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Compile S files +recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Create archives +recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" + +## Combine gc-sections, archives, and objects +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" + +## Create eeprom +recipe.objcopy.eep.pattern= + +## Create hex +recipe.objcopy.hex.1.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.elf2bin}" --eboot "{runtime.tools.eboot}" --app "{build.path}/{build.project_name}.elf" --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size {build.flash_size} --path "{runtime.tools.xtensa-lx106-elf-gcc.path}/bin" --out "{build.path}/{build.project_name}.bin" +recipe.objcopy.hex.2.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed" --legacy "{build.path}/{build.project_name}.bin.legacy_sig" +recipe.objcopy.hex.3.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.sizes}" --elf "{build.path}/{build.project_name}.elf" --path "{runtime.tools.xtensa-lx106-elf-gcc.path}/bin" + +## Save hex +recipe.output.tmp_file={build.project_name}.bin +recipe.output.save_file={build.project_name}.{build.variant}.bin + +## Compute size +recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" +recipe.size.regex=^(?:\.irom0\.text|\.text|\.text1|\.data|\.rodata|)\s+([0-9]+).* +recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* +#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* + +# ------------------------------ + +tools.esptool.path= +# Because the variable expansion doesn't allow one tool to find another, the following lines +# will point to "{runtime.platform.path}/tools/python3/python3" in GIT and +# "{runtime.tools.python3.path}/python3" for JSON board manager releases. +tools.esptool.cmd={runtime.tools.python3.path}/python3 +tools.esptool.network_cmd={runtime.tools.python3.path}/python3 + + + +tools.esptool.upload.protocol=esp +# esptool.py --trace option is a debug option, not a verbose option +tools.esptool.upload.params.verbose= +tools.esptool.upload.params.quiet= + +# First, potentially perform an erase or nothing +# Next, do the binary upload +# Combined in one rule because Arduino doesn't suport upload.1.pattern/upload.3.pattern +tools.esptool.upload.pattern="{cmd}" "{runtime.platform.path}/tools/upload.py" --chip esp8266 --port "{serial.port}" --baud "{upload.speed}" "{upload.verbose}" {upload.erase_cmd} --end --chip esp8266 --port "{serial.port}" --baud "{upload.speed}" "{upload.verbose}" write_flash 0x0 "{build.path}/{build.project_name}.bin" --end + +tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" + +tools.mkspiffs.cmd=mkspiffs +tools.mkspiffs.cmd.windows=mkspiffs.exe +tools.mkspiffs.path={runtime.tools.mkspiffs.path} + +tools.mklittlefs.cmd=mklittlefs +tools.mklittlefs.cmd.windows=mklittlefs.exe +tools.mklittlefs.path={runtime.platform.path}/tools/mklittlefs + +tools.espupload.cmd=python +tools.espupload.cmd.windows=python.exe +tools.espupload.path={runtime.platform.path}/tools +tools.espupload.upload.protocol=espupload +tools.espupload.upload.params.verbose= +tools.espupload.upload.params.quiet= +tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin"